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);
128 /* BB FIXME add code to check if wsize needs
129 update due to negotiated smb buffer size
132 atomic_inc(&tconInfoReconnectCount);
134 cFYI(1, ("reconnect tcon rc = %d", rc));
135 /* Removed call to reopen open files here -
136 it is safer (and faster) to reopen files
137 one at a time as needed in read and write */
139 /* Check if handle based operation so we
140 know whether we can continue or not without
141 returning to caller to reset file handle */
142 switch(smb_command) {
143 case SMB_COM_READ_ANDX:
144 case SMB_COM_WRITE_ANDX:
146 case SMB_COM_FIND_CLOSE2:
147 case SMB_COM_LOCKING_ANDX: {
148 unload_nls(nls_codepage);
153 up(&tcon->ses->sesSem);
155 unload_nls(nls_codepage);
164 *request_buf = cifs_small_buf_get();
165 if (*request_buf == NULL) {
166 /* BB should we add a retry in here if not a writepage? */
170 header_assemble((struct smb_hdr *) *request_buf, smb_command, tcon,wct);
173 cifs_stats_inc(&tcon->num_smbs_sent);
178 /* If the return code is zero, this function must fill in request_buf pointer */
180 smb_init(int smb_command, int wct, struct cifsTconInfo *tcon,
181 void **request_buf /* returned */ ,
182 void **response_buf /* returned */ )
186 /* SMBs NegProt, SessSetup, uLogoff do not have tcon yet so
187 check for tcp and smb session status done differently
188 for those three - in the calling routine */
190 if((tcon->ses) && (tcon->ses->status != CifsExiting) &&
191 (tcon->ses->server)){
192 struct nls_table *nls_codepage;
193 /* Give Demultiplex thread up to 10 seconds to
194 reconnect, should be greater than cifs socket
195 timeout which is 7 seconds */
196 while(tcon->ses->server->tcpStatus == CifsNeedReconnect) {
197 wait_event_interruptible_timeout(tcon->ses->server->response_q,
198 (tcon->ses->server->tcpStatus == CifsGood), 10 * HZ);
199 if(tcon->ses->server->tcpStatus ==
201 /* on "soft" mounts we wait once */
202 if((tcon->retry == FALSE) ||
203 (tcon->ses->status == CifsExiting)) {
204 cFYI(1,("gave up waiting on reconnect in smb_init"));
206 } /* else "hard" mount - keep retrying
207 until process is killed or server
209 } else /* TCP session is reestablished now */
214 nls_codepage = load_nls_default();
215 /* need to prevent multiple threads trying to
216 simultaneously reconnect the same SMB session */
217 down(&tcon->ses->sesSem);
218 if(tcon->ses->status == CifsNeedReconnect)
219 rc = cifs_setup_session(0, tcon->ses,
221 if(!rc && (tcon->tidStatus == CifsNeedReconnect)) {
222 mark_open_files_invalid(tcon);
223 rc = CIFSTCon(0, tcon->ses, tcon->treeName,
225 up(&tcon->ses->sesSem);
226 /* BB FIXME add code to check if wsize needs
227 update due to negotiated smb buffer size
230 atomic_inc(&tconInfoReconnectCount);
232 cFYI(1, ("reconnect tcon rc = %d", rc));
233 /* Removed call to reopen open files here -
234 it is safer (and faster) to reopen files
235 one at a time as needed in read and write */
237 /* Check if handle based operation so we
238 know whether we can continue or not without
239 returning to caller to reset file handle */
240 switch(smb_command) {
241 case SMB_COM_READ_ANDX:
242 case SMB_COM_WRITE_ANDX:
244 case SMB_COM_FIND_CLOSE2:
245 case SMB_COM_LOCKING_ANDX: {
246 unload_nls(nls_codepage);
251 up(&tcon->ses->sesSem);
253 unload_nls(nls_codepage);
262 *request_buf = cifs_buf_get();
263 if (*request_buf == NULL) {
264 /* BB should we add a retry in here if not a writepage? */
267 /* Although the original thought was we needed the response buf for */
268 /* potential retries of smb operations it turns out we can determine */
269 /* from the mid flags when the request buffer can be resent without */
270 /* having to use a second distinct buffer for the response */
271 *response_buf = *request_buf;
273 header_assemble((struct smb_hdr *) *request_buf, smb_command, tcon,
277 cifs_stats_inc(&tcon->num_smbs_sent);
282 static int validate_t2(struct smb_t2_rsp * pSMB)
288 /* check for plausible wct, bcc and t2 data and parm sizes */
289 /* check for parm and data offset going beyond end of smb */
290 if(pSMB->hdr.WordCount >= 10) {
291 if((le16_to_cpu(pSMB->t2_rsp.ParameterOffset) <= 1024) &&
292 (le16_to_cpu(pSMB->t2_rsp.DataOffset) <= 1024)) {
293 /* check that bcc is at least as big as parms + data */
294 /* check that bcc is less than negotiated smb buffer */
295 total_size = le16_to_cpu(pSMB->t2_rsp.ParameterCount);
296 if(total_size < 512) {
297 total_size+=le16_to_cpu(pSMB->t2_rsp.DataCount);
298 /* BCC le converted in SendReceive */
299 pBCC = (pSMB->hdr.WordCount * 2) +
300 sizeof(struct smb_hdr) +
302 if((total_size <= (*(u16 *)pBCC)) &&
304 CIFSMaxBufSize+MAX_CIFS_HDR_SIZE)) {
311 cifs_dump_mem("Invalid transact2 SMB: ",(char *)pSMB,
312 sizeof(struct smb_t2_rsp) + 16);
316 CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses)
319 NEGOTIATE_RSP *pSMBr;
322 struct TCP_Server_Info * server;
326 server = ses->server;
331 rc = smb_init(SMB_COM_NEGOTIATE, 0, NULL /* no tcon yet */ ,
332 (void **) &pSMB, (void **) &pSMBr);
335 pSMB->hdr.Mid = GetNextMid(server);
336 pSMB->hdr.Flags2 |= SMBFLG2_UNICODE;
337 if (extended_security)
338 pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC;
340 count = strlen(protocols[0].name) + 1;
341 strncpy(pSMB->DialectsArray, protocols[0].name, 30);
342 /* null guaranteed to be at end of source and target buffers anyway */
344 pSMB->hdr.smb_buf_length += count;
345 pSMB->ByteCount = cpu_to_le16(count);
347 rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB,
348 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
350 server->secMode = pSMBr->SecurityMode;
351 server->secType = NTLM; /* BB override default for
352 NTLMv2 or kerberos v5 */
353 /* one byte - no need to convert this or EncryptionKeyLen
354 from little endian */
355 server->maxReq = le16_to_cpu(pSMBr->MaxMpxCount);
356 /* probably no need to store and check maxvcs */
358 min(le32_to_cpu(pSMBr->MaxBufferSize),
359 (__u32) CIFSMaxBufSize + MAX_CIFS_HDR_SIZE);
360 server->maxRw = le32_to_cpu(pSMBr->MaxRawSize);
361 cFYI(0, ("Max buf = %d ", ses->server->maxBuf));
362 GETU32(ses->server->sessid) = le32_to_cpu(pSMBr->SessionKey);
363 server->capabilities = le32_to_cpu(pSMBr->Capabilities);
364 server->timeZone = le16_to_cpu(pSMBr->ServerTimeZone);
365 /* BB with UTC do we ever need to be using srvr timezone? */
366 if (pSMBr->EncryptionKeyLength == CIFS_CRYPTO_KEY_SIZE) {
367 memcpy(server->cryptKey, pSMBr->u.EncryptionKey,
368 CIFS_CRYPTO_KEY_SIZE);
369 } else if ((pSMBr->hdr.Flags2 & SMBFLG2_EXT_SEC)
370 && (pSMBr->EncryptionKeyLength == 0)) {
371 /* decode security blob */
375 /* BB might be helpful to save off the domain of server here */
377 if ((pSMBr->hdr.Flags2 & SMBFLG2_EXT_SEC) &&
378 (server->capabilities & CAP_EXTENDED_SECURITY)) {
379 count = pSMBr->ByteCount;
382 else if (count == 16) {
383 server->secType = RawNTLMSSP;
384 if (server->socketUseCount.counter > 1) {
386 (server->server_GUID,
387 pSMBr->u.extended_response.
390 ("UID of server does not match previous connection to same ip address"));
398 memcpy(server->server_GUID,
399 pSMBr->u.extended_response.
402 rc = decode_negTokenInit(pSMBr->u.
408 /* BB Need to fill struct for sessetup here */
415 server->capabilities &= ~CAP_EXTENDED_SECURITY;
416 if(sign_CIFS_PDUs == FALSE) {
417 if(server->secMode & SECMODE_SIGN_REQUIRED)
419 ("Server requires /proc/fs/cifs/PacketSigningEnabled"));
420 server->secMode &= ~(SECMODE_SIGN_ENABLED | SECMODE_SIGN_REQUIRED);
421 } else if(sign_CIFS_PDUs == 1) {
422 if((server->secMode & SECMODE_SIGN_REQUIRED) == 0)
423 server->secMode &= ~(SECMODE_SIGN_ENABLED | SECMODE_SIGN_REQUIRED);
428 cifs_buf_release(pSMB);
433 CIFSSMBTDis(const int xid, struct cifsTconInfo *tcon)
435 struct smb_hdr *smb_buffer;
436 struct smb_hdr *smb_buffer_response; /* BB removeme BB */
440 cFYI(1, ("In tree disconnect"));
442 * If last user of the connection and
443 * connection alive - disconnect it
444 * If this is the last connection on the server session disconnect it
445 * (and inside session disconnect we should check if tcp socket needs
446 * to be freed and kernel thread woken up).
449 down(&tcon->tconSem);
453 atomic_dec(&tcon->useCount);
454 if (atomic_read(&tcon->useCount) > 0) {
459 /* No need to return error on this operation if tid invalidated and
460 closed on server already e.g. due to tcp session crashing */
461 if(tcon->tidStatus == CifsNeedReconnect) {
466 if((tcon->ses == NULL) || (tcon->ses->server == NULL)) {
470 rc = small_smb_init(SMB_COM_TREE_DISCONNECT, 0, tcon,
471 (void **)&smb_buffer);
476 smb_buffer_response = smb_buffer; /* BB removeme BB */
478 rc = SendReceive(xid, tcon->ses, smb_buffer, smb_buffer_response,
481 cFYI(1, ("Tree disconnect failed %d", rc));
484 cifs_small_buf_release(smb_buffer);
487 /* No need to return error on this operation if tid invalidated and
488 closed on server already e.g. due to tcp session crashing */
496 CIFSSMBLogoff(const int xid, struct cifsSesInfo *ses)
498 struct smb_hdr *smb_buffer_response;
499 LOGOFF_ANDX_REQ *pSMB;
503 cFYI(1, ("In SMBLogoff for session disconnect"));
509 atomic_dec(&ses->inUse);
510 if (atomic_read(&ses->inUse) > 0) {
514 rc = small_smb_init(SMB_COM_LOGOFF_ANDX, 2, NULL, (void **)&pSMB);
520 smb_buffer_response = (struct smb_hdr *)pSMB; /* BB removeme BB */
523 pSMB->hdr.Mid = GetNextMid(ses->server);
525 if(ses->server->secMode &
526 (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
527 pSMB->hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
530 pSMB->hdr.Uid = ses->Suid;
532 pSMB->AndXCommand = 0xFF;
533 rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB,
534 smb_buffer_response, &length, 0);
536 atomic_dec(&ses->server->socketUseCount);
537 if (atomic_read(&ses->server->socketUseCount) == 0) {
538 spin_lock(&GlobalMid_Lock);
539 ses->server->tcpStatus = CifsExiting;
540 spin_unlock(&GlobalMid_Lock);
545 cifs_small_buf_release(pSMB);
547 /* if session dead then we do not need to do ulogoff,
548 since server closed smb session, no sense reporting
556 CIFSSMBDelFile(const int xid, struct cifsTconInfo *tcon, const char *fileName,
557 const struct nls_table *nls_codepage, int remap)
559 DELETE_FILE_REQ *pSMB = NULL;
560 DELETE_FILE_RSP *pSMBr = NULL;
566 rc = smb_init(SMB_COM_DELETE, 1, tcon, (void **) &pSMB,
571 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
573 cifsConvertToUCS((__le16 *) pSMB->fileName, fileName,
574 PATH_MAX, nls_codepage, remap);
575 name_len++; /* trailing null */
577 } else { /* BB improve check for buffer overruns BB */
578 name_len = strnlen(fileName, PATH_MAX);
579 name_len++; /* trailing null */
580 strncpy(pSMB->fileName, fileName, name_len);
582 pSMB->SearchAttributes =
583 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM);
584 pSMB->BufferFormat = 0x04;
585 pSMB->hdr.smb_buf_length += name_len + 1;
586 pSMB->ByteCount = cpu_to_le16(name_len + 1);
587 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
588 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
589 cifs_stats_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 cifs_stats_inc(&tcon->num_rmdirs);
636 cFYI(1, ("Error in RMDir = %d", rc));
639 cifs_buf_release(pSMB);
646 CIFSSMBMkDir(const int xid, struct cifsTconInfo *tcon,
647 const char *name, const struct nls_table *nls_codepage, int remap)
650 CREATE_DIRECTORY_REQ *pSMB = NULL;
651 CREATE_DIRECTORY_RSP *pSMBr = NULL;
655 cFYI(1, ("In CIFSSMBMkDir"));
657 rc = smb_init(SMB_COM_CREATE_DIRECTORY, 0, tcon, (void **) &pSMB,
662 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
663 name_len = cifsConvertToUCS((__le16 *) pSMB->DirName, name,
664 PATH_MAX, nls_codepage, remap);
665 name_len++; /* trailing null */
667 } else { /* BB improve check for buffer overruns BB */
668 name_len = strnlen(name, PATH_MAX);
669 name_len++; /* trailing null */
670 strncpy(pSMB->DirName, name, name_len);
673 pSMB->BufferFormat = 0x04;
674 pSMB->hdr.smb_buf_length += name_len + 1;
675 pSMB->ByteCount = cpu_to_le16(name_len + 1);
676 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
677 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
678 cifs_stats_inc(&tcon->num_mkdirs);
680 cFYI(1, ("Error in Mkdir = %d", rc));
683 cifs_buf_release(pSMB);
689 static __u16 convert_disposition(int disposition)
693 switch (disposition) {
695 ofun = SMBOPEN_OCREATE | SMBOPEN_OTRUNC;
698 ofun = SMBOPEN_OAPPEND;
701 ofun = SMBOPEN_OCREATE;
704 ofun = SMBOPEN_OCREATE | SMBOPEN_OAPPEND;
707 ofun = SMBOPEN_OTRUNC;
709 case FILE_OVERWRITE_IF:
710 ofun = SMBOPEN_OCREATE | SMBOPEN_OTRUNC;
713 cFYI(1,("unknown disposition %d",disposition));
714 ofun = SMBOPEN_OAPPEND; /* regular open */
720 SMBLegacyOpen(const int xid, struct cifsTconInfo *tcon,
721 const char *fileName, const int openDisposition,
722 const int access_flags, const int create_options, __u16 * netfid,
723 int *pOplock, FILE_ALL_INFO * pfile_info,
724 const struct nls_table *nls_codepage, int remap)
727 OPENX_REQ *pSMB = NULL;
728 OPENX_RSP *pSMBr = NULL;
734 rc = smb_init(SMB_COM_OPEN_ANDX, 15, tcon, (void **) &pSMB,
739 pSMB->AndXCommand = 0xFF; /* none */
741 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
742 count = 1; /* account for one byte pad to word boundary */
744 cifsConvertToUCS((__le16 *) (pSMB->fileName + 1),
745 fileName, PATH_MAX, nls_codepage, remap);
746 name_len++; /* trailing null */
748 } else { /* BB improve check for buffer overruns BB */
749 count = 0; /* no pad */
750 name_len = strnlen(fileName, PATH_MAX);
751 name_len++; /* trailing null */
752 strncpy(pSMB->fileName, fileName, name_len);
754 if (*pOplock & REQ_OPLOCK)
755 pSMB->OpenFlags = cpu_to_le16(REQ_OPLOCK);
756 else if (*pOplock & REQ_BATCHOPLOCK) {
757 pSMB->OpenFlags = cpu_to_le16(REQ_BATCHOPLOCK);
759 pSMB->OpenFlags |= cpu_to_le16(REQ_MORE_INFO);
760 /* BB fixme add conversion for access_flags to bits 0 - 2 of mode */
766 pSMB->Mode = cpu_to_le16(2);
767 pSMB->Mode |= cpu_to_le16(0x40); /* deny none */
768 /* set file as system file if special file such
769 as fifo and server expecting SFU style and
770 no Unix extensions */
772 if(create_options & CREATE_OPTION_SPECIAL)
773 pSMB->FileAttributes = cpu_to_le16(ATTR_SYSTEM);
775 pSMB->FileAttributes = cpu_to_le16(0/*ATTR_NORMAL*/); /* BB FIXME */
777 /* if ((omode & S_IWUGO) == 0)
778 pSMB->FileAttributes |= cpu_to_le32(ATTR_READONLY);*/
779 /* Above line causes problems due to vfs splitting create into two
780 pieces - need to set mode after file created not while it is
784 /* pSMB->CreateOptions = cpu_to_le32(create_options & CREATE_OPTIONS_MASK); */
785 /* BB FIXME END BB */
787 pSMB->Sattr = cpu_to_le16(ATTR_HIDDEN | ATTR_SYSTEM | ATTR_DIRECTORY);
788 pSMB->OpenFunction = cpu_to_le16(convert_disposition(openDisposition));
790 pSMB->hdr.smb_buf_length += count;
792 pSMB->ByteCount = cpu_to_le16(count);
793 /* long_op set to 1 to allow for oplock break timeouts */
794 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
795 (struct smb_hdr *) pSMBr, &bytes_returned, 1);
796 cifs_stats_inc(&tcon->num_opens);
798 cFYI(1, ("Error in Open = %d", rc));
800 /* BB verify if wct == 15 */
802 /* *pOplock = pSMBr->OplockLevel; */ /* BB take from action field BB */
804 *netfid = pSMBr->Fid; /* cifs fid stays in le */
805 /* Let caller know file was created so we can set the mode. */
806 /* Do we care about the CreateAction in any other cases? */
808 /* if(cpu_to_le32(FILE_CREATE) == pSMBr->CreateAction)
809 *pOplock |= CIFS_CREATE_ACTION; */
813 pfile_info->CreationTime = 0; /* BB convert CreateTime*/
814 pfile_info->LastAccessTime = 0; /* BB fixme */
815 pfile_info->LastWriteTime = 0; /* BB fixme */
816 pfile_info->ChangeTime = 0; /* BB fixme */
817 pfile_info->Attributes =
818 cpu_to_le32(le16_to_cpu(pSMBr->FileAttributes));
819 /* the file_info buf is endian converted by caller */
820 pfile_info->AllocationSize =
821 cpu_to_le64(le32_to_cpu(pSMBr->EndOfFile));
822 pfile_info->EndOfFile = pfile_info->AllocationSize;
823 pfile_info->NumberOfLinks = cpu_to_le32(1);
827 cifs_buf_release(pSMB);
834 CIFSSMBOpen(const int xid, struct cifsTconInfo *tcon,
835 const char *fileName, const int openDisposition,
836 const int access_flags, const int create_options, __u16 * netfid,
837 int *pOplock, FILE_ALL_INFO * pfile_info,
838 const struct nls_table *nls_codepage, int remap)
841 OPEN_REQ *pSMB = NULL;
842 OPEN_RSP *pSMBr = NULL;
848 rc = smb_init(SMB_COM_NT_CREATE_ANDX, 24, tcon, (void **) &pSMB,
853 pSMB->AndXCommand = 0xFF; /* none */
855 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
856 count = 1; /* account for one byte pad to word boundary */
858 cifsConvertToUCS((__le16 *) (pSMB->fileName + 1),
859 fileName, PATH_MAX, nls_codepage, remap);
860 name_len++; /* trailing null */
862 pSMB->NameLength = cpu_to_le16(name_len);
863 } else { /* BB improve check for buffer overruns BB */
864 count = 0; /* no pad */
865 name_len = strnlen(fileName, PATH_MAX);
866 name_len++; /* trailing null */
867 pSMB->NameLength = cpu_to_le16(name_len);
868 strncpy(pSMB->fileName, fileName, name_len);
870 if (*pOplock & REQ_OPLOCK)
871 pSMB->OpenFlags = cpu_to_le32(REQ_OPLOCK);
872 else if (*pOplock & REQ_BATCHOPLOCK) {
873 pSMB->OpenFlags = cpu_to_le32(REQ_BATCHOPLOCK);
875 pSMB->DesiredAccess = cpu_to_le32(access_flags);
876 pSMB->AllocationSize = 0;
877 /* set file as system file if special file such
878 as fifo and server expecting SFU style and
879 no Unix extensions */
880 if(create_options & CREATE_OPTION_SPECIAL)
881 pSMB->FileAttributes = cpu_to_le32(ATTR_SYSTEM);
883 pSMB->FileAttributes = cpu_to_le32(ATTR_NORMAL);
884 /* XP does not handle ATTR_POSIX_SEMANTICS */
885 /* but it helps speed up case sensitive checks for other
886 servers such as Samba */
887 if (tcon->ses->capabilities & CAP_UNIX)
888 pSMB->FileAttributes |= cpu_to_le32(ATTR_POSIX_SEMANTICS);
890 /* if ((omode & S_IWUGO) == 0)
891 pSMB->FileAttributes |= cpu_to_le32(ATTR_READONLY);*/
892 /* Above line causes problems due to vfs splitting create into two
893 pieces - need to set mode after file created not while it is
895 pSMB->ShareAccess = cpu_to_le32(FILE_SHARE_ALL);
896 pSMB->CreateDisposition = cpu_to_le32(openDisposition);
897 pSMB->CreateOptions = cpu_to_le32(create_options & CREATE_OPTIONS_MASK);
898 /* BB Expirement with various impersonation levels and verify */
899 pSMB->ImpersonationLevel = cpu_to_le32(SECURITY_IMPERSONATION);
900 pSMB->SecurityFlags =
901 SECURITY_CONTEXT_TRACKING | SECURITY_EFFECTIVE_ONLY;
904 pSMB->hdr.smb_buf_length += count;
906 pSMB->ByteCount = cpu_to_le16(count);
907 /* long_op set to 1 to allow for oplock break timeouts */
908 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
909 (struct smb_hdr *) pSMBr, &bytes_returned, 1);
910 cifs_stats_inc(&tcon->num_opens);
912 cFYI(1, ("Error in Open = %d", rc));
914 *pOplock = pSMBr->OplockLevel; /* 1 byte no need to le_to_cpu */
915 *netfid = pSMBr->Fid; /* cifs fid stays in le */
916 /* Let caller know file was created so we can set the mode. */
917 /* Do we care about the CreateAction in any other cases? */
918 if(cpu_to_le32(FILE_CREATE) == pSMBr->CreateAction)
919 *pOplock |= CIFS_CREATE_ACTION;
921 memcpy((char *)pfile_info,(char *)&pSMBr->CreationTime,
922 36 /* CreationTime to Attributes */);
923 /* the file_info buf is endian converted by caller */
924 pfile_info->AllocationSize = pSMBr->AllocationSize;
925 pfile_info->EndOfFile = pSMBr->EndOfFile;
926 pfile_info->NumberOfLinks = cpu_to_le32(1);
930 cifs_buf_release(pSMB);
936 /* If no buffer passed in, then caller wants to do the copy
937 as in the case of readpages so the SMB buffer must be
938 freed by the caller */
941 CIFSSMBRead(const int xid, struct cifsTconInfo *tcon,
942 const int netfid, const unsigned int count,
943 const __u64 lseek, unsigned int *nbytes, char **buf)
946 READ_REQ *pSMB = NULL;
947 READ_RSP *pSMBr = NULL;
948 char *pReadData = NULL;
952 cFYI(1,("Reading %d bytes on fid %d",count,netfid));
953 if(tcon->ses->capabilities & CAP_LARGE_FILES)
956 wct = 10; /* old style read */
959 rc = smb_init(SMB_COM_READ_ANDX, wct, tcon, (void **) &pSMB,
964 /* tcon and ses pointer are checked in smb_init */
965 if (tcon->ses->server == NULL)
966 return -ECONNABORTED;
968 pSMB->AndXCommand = 0xFF; /* none */
970 pSMB->OffsetLow = cpu_to_le32(lseek & 0xFFFFFFFF);
972 pSMB->OffsetHigh = cpu_to_le32(lseek >> 32);
973 else if((lseek >> 32) > 0) /* can not handle this big offset for old */
977 pSMB->MaxCount = cpu_to_le16(count & 0xFFFF);
978 pSMB->MaxCountHigh = cpu_to_le32(count >> 16);
980 pSMB->ByteCount = 0; /* no need to do le conversion since 0 */
983 struct smb_com_readx_req * pSMBW =
984 (struct smb_com_readx_req *)pSMB;
985 pSMBW->ByteCount = 0;
988 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
989 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
990 cifs_stats_inc(&tcon->num_reads);
992 cERROR(1, ("Send error in read = %d", rc));
994 int data_length = le16_to_cpu(pSMBr->DataLengthHigh);
995 data_length = data_length << 16;
996 data_length += le16_to_cpu(pSMBr->DataLength);
997 *nbytes = data_length;
999 /*check that DataLength would not go beyond end of SMB */
1000 if ((data_length > CIFSMaxBufSize)
1001 || (data_length > count)) {
1002 cFYI(1,("bad length %d for count %d",data_length,count));
1007 (char *) (&pSMBr->hdr.Protocol) +
1008 le16_to_cpu(pSMBr->DataOffset);
1009 /* if(rc = copy_to_user(buf, pReadData, data_length)) {
1010 cERROR(1,("Faulting on read rc = %d",rc));
1012 }*/ /* can not use copy_to_user when using page cache*/
1014 memcpy(*buf,pReadData,data_length);
1018 cifs_buf_release(pSMB);
1020 *buf = (char *)pSMB;
1022 /* Note: On -EAGAIN error only caller can retry on handle based calls
1023 since file handle passed in no longer valid */
1028 CIFSSMBWrite(const int xid, struct cifsTconInfo *tcon,
1029 const int netfid, const unsigned int count,
1030 const __u64 offset, unsigned int *nbytes, const char *buf,
1031 const char __user * ubuf, const int long_op)
1034 WRITE_REQ *pSMB = NULL;
1035 WRITE_RSP *pSMBr = NULL;
1036 int bytes_returned, wct;
1040 /* cFYI(1,("write at %lld %d bytes",offset,count));*/
1041 if(tcon->ses == NULL)
1042 return -ECONNABORTED;
1044 if(tcon->ses->capabilities & CAP_LARGE_FILES)
1049 rc = smb_init(SMB_COM_WRITE_ANDX, wct, tcon, (void **) &pSMB,
1053 /* tcon and ses pointer are checked in smb_init */
1054 if (tcon->ses->server == NULL)
1055 return -ECONNABORTED;
1057 pSMB->AndXCommand = 0xFF; /* none */
1059 pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF);
1061 pSMB->OffsetHigh = cpu_to_le32(offset >> 32);
1062 else if((offset >> 32) > 0) /* can not handle this big offset for old */
1065 pSMB->Reserved = 0xFFFFFFFF;
1066 pSMB->WriteMode = 0;
1067 pSMB->Remaining = 0;
1069 /* Can increase buffer size if buffer is big enough in some cases - ie we
1070 can send more if LARGE_WRITE_X capability returned by the server and if
1071 our buffer is big enough or if we convert to iovecs on socket writes
1072 and eliminate the copy to the CIFS buffer */
1073 if(tcon->ses->capabilities & CAP_LARGE_WRITE_X) {
1074 bytes_sent = min_t(const unsigned int, CIFSMaxBufSize, count);
1076 bytes_sent = (tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE)
1080 if (bytes_sent > count)
1083 cpu_to_le16(offsetof(struct smb_com_write_req,Data) - 4);
1085 memcpy(pSMB->Data,buf,bytes_sent);
1087 if(copy_from_user(pSMB->Data,ubuf,bytes_sent)) {
1088 cifs_buf_release(pSMB);
1091 } else if (count != 0) {
1093 cifs_buf_release(pSMB);
1095 } /* else setting file size with write of zero bytes */
1097 byte_count = bytes_sent + 1; /* pad */
1098 else /* wct == 12 */ {
1099 byte_count = bytes_sent + 5; /* bigger pad, smaller smb hdr */
1101 pSMB->DataLengthLow = cpu_to_le16(bytes_sent & 0xFFFF);
1102 pSMB->DataLengthHigh = cpu_to_le16(bytes_sent >> 16);
1103 pSMB->hdr.smb_buf_length += byte_count;
1106 pSMB->ByteCount = cpu_to_le16(byte_count);
1107 else { /* old style write has byte count 4 bytes earlier so 4 bytes pad */
1108 struct smb_com_writex_req * pSMBW =
1109 (struct smb_com_writex_req *)pSMB;
1110 pSMBW->ByteCount = cpu_to_le16(byte_count);
1113 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1114 (struct smb_hdr *) pSMBr, &bytes_returned, long_op);
1115 cifs_stats_inc(&tcon->num_writes);
1117 cFYI(1, ("Send error in write = %d", rc));
1120 *nbytes = le16_to_cpu(pSMBr->CountHigh);
1121 *nbytes = (*nbytes) << 16;
1122 *nbytes += le16_to_cpu(pSMBr->Count);
1125 cifs_buf_release(pSMB);
1127 /* Note: On -EAGAIN error only caller can retry on handle based calls
1128 since file handle passed in no longer valid */
1133 #ifdef CONFIG_CIFS_EXPERIMENTAL
1135 CIFSSMBWrite2(const int xid, struct cifsTconInfo *tcon,
1136 const int netfid, const unsigned int count,
1137 const __u64 offset, unsigned int *nbytes, struct kvec *iov,
1138 int n_vec, const int long_op)
1141 WRITE_REQ *pSMB = NULL;
1142 int bytes_returned, wct;
1145 cFYI(1,("write2 at %lld %d bytes",offset,count)); /* BB removeme BB */
1146 if(tcon->ses->capabilities & CAP_LARGE_FILES)
1150 rc = small_smb_init(SMB_COM_WRITE_ANDX, wct, tcon, (void **) &pSMB);
1153 /* tcon and ses pointer are checked in smb_init */
1154 if (tcon->ses->server == NULL)
1155 return -ECONNABORTED;
1157 pSMB->AndXCommand = 0xFF; /* none */
1159 pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF);
1161 pSMB->OffsetHigh = cpu_to_le32(offset >> 32);
1162 else if((offset >> 32) > 0) /* can not handle this big offset for old */
1164 pSMB->Reserved = 0xFFFFFFFF;
1165 pSMB->WriteMode = 0;
1166 pSMB->Remaining = 0;
1169 cpu_to_le16(offsetof(struct smb_com_write_req,Data) - 4);
1171 pSMB->DataLengthLow = cpu_to_le16(count & 0xFFFF);
1172 pSMB->DataLengthHigh = cpu_to_le16(count >> 16);
1173 smb_hdr_len = pSMB->hdr.smb_buf_length + 1; /* hdr + 1 byte pad */
1175 pSMB->hdr.smb_buf_length += count+1;
1176 else /* wct == 12 */
1177 pSMB->hdr.smb_buf_length += count+5; /* smb data starts later */
1179 pSMB->ByteCount = cpu_to_le16(count + 1);
1180 else /* wct == 12 */ /* bigger pad, smaller smb hdr, keep offset ok */ {
1181 struct smb_com_writex_req * pSMBW =
1182 (struct smb_com_writex_req *)pSMB;
1183 pSMBW->ByteCount = cpu_to_le16(count + 5);
1185 iov[0].iov_base = pSMB;
1186 iov[0].iov_len = smb_hdr_len + 4;
1188 rc = SendReceive2(xid, tcon->ses, iov, n_vec + 1, &bytes_returned,
1190 cifs_stats_inc(&tcon->num_writes);
1192 cFYI(1, ("Send error Write2 = %d", rc));
1195 WRITE_RSP * pSMBr = (WRITE_RSP *)pSMB;
1196 *nbytes = le16_to_cpu(pSMBr->CountHigh);
1197 *nbytes = (*nbytes) << 16;
1198 *nbytes += le16_to_cpu(pSMBr->Count);
1201 cifs_small_buf_release(pSMB);
1203 /* Note: On -EAGAIN error only caller can retry on handle based calls
1204 since file handle passed in no longer valid */
1210 #endif /* CIFS_EXPERIMENTAL */
1213 CIFSSMBLock(const int xid, struct cifsTconInfo *tcon,
1214 const __u16 smb_file_id, const __u64 len,
1215 const __u64 offset, const __u32 numUnlock,
1216 const __u32 numLock, const __u8 lockType, const int waitFlag)
1219 LOCK_REQ *pSMB = NULL;
1220 LOCK_RSP *pSMBr = NULL;
1225 cFYI(1, ("In CIFSSMBLock - timeout %d numLock %d",waitFlag,numLock));
1226 rc = small_smb_init(SMB_COM_LOCKING_ANDX, 8, tcon, (void **) &pSMB);
1231 pSMBr = (LOCK_RSP *)pSMB; /* BB removeme BB */
1233 if(lockType == LOCKING_ANDX_OPLOCK_RELEASE) {
1234 timeout = -1; /* no response expected */
1236 } else if (waitFlag == TRUE) {
1237 timeout = 3; /* blocking operation, no timeout */
1238 pSMB->Timeout = cpu_to_le32(-1);/* blocking - do not time out */
1243 pSMB->NumberOfLocks = cpu_to_le16(numLock);
1244 pSMB->NumberOfUnlocks = cpu_to_le16(numUnlock);
1245 pSMB->LockType = lockType;
1246 pSMB->AndXCommand = 0xFF; /* none */
1247 pSMB->Fid = smb_file_id; /* netfid stays le */
1249 if((numLock != 0) || (numUnlock != 0)) {
1250 pSMB->Locks[0].Pid = cpu_to_le16(current->tgid);
1251 /* BB where to store pid high? */
1252 pSMB->Locks[0].LengthLow = cpu_to_le32((u32)len);
1253 pSMB->Locks[0].LengthHigh = cpu_to_le32((u32)(len>>32));
1254 pSMB->Locks[0].OffsetLow = cpu_to_le32((u32)offset);
1255 pSMB->Locks[0].OffsetHigh = cpu_to_le32((u32)(offset>>32));
1256 count = sizeof(LOCKING_ANDX_RANGE);
1261 pSMB->hdr.smb_buf_length += count;
1262 pSMB->ByteCount = cpu_to_le16(count);
1264 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1265 (struct smb_hdr *) pSMBr, &bytes_returned, timeout);
1266 cifs_stats_inc(&tcon->num_locks);
1268 cFYI(1, ("Send error in Lock = %d", rc));
1270 cifs_small_buf_release(pSMB);
1272 /* Note: On -EAGAIN error only caller can retry on handle based calls
1273 since file handle passed in no longer valid */
1278 CIFSSMBClose(const int xid, struct cifsTconInfo *tcon, int smb_file_id)
1281 CLOSE_REQ *pSMB = NULL;
1282 CLOSE_RSP *pSMBr = NULL;
1284 cFYI(1, ("In CIFSSMBClose"));
1286 /* do not retry on dead session on close */
1287 rc = small_smb_init(SMB_COM_CLOSE, 3, tcon, (void **) &pSMB);
1293 pSMBr = (CLOSE_RSP *)pSMB; /* BB removeme BB */
1295 pSMB->FileID = (__u16) smb_file_id;
1296 pSMB->LastWriteTime = 0;
1297 pSMB->ByteCount = 0;
1298 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1299 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1300 cifs_stats_inc(&tcon->num_closes);
1303 /* EINTR is expected when user ctl-c to kill app */
1304 cERROR(1, ("Send error in Close = %d", rc));
1308 cifs_small_buf_release(pSMB);
1310 /* Since session is dead, file will be closed on server already */
1318 CIFSSMBRename(const int xid, struct cifsTconInfo *tcon,
1319 const char *fromName, const char *toName,
1320 const struct nls_table *nls_codepage, int remap)
1323 RENAME_REQ *pSMB = NULL;
1324 RENAME_RSP *pSMBr = NULL;
1326 int name_len, name_len2;
1329 cFYI(1, ("In CIFSSMBRename"));
1331 rc = smb_init(SMB_COM_RENAME, 1, tcon, (void **) &pSMB,
1336 pSMB->BufferFormat = 0x04;
1337 pSMB->SearchAttributes =
1338 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
1341 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1343 cifsConvertToUCS((__le16 *) pSMB->OldFileName, fromName,
1344 PATH_MAX, nls_codepage, remap);
1345 name_len++; /* trailing null */
1347 pSMB->OldFileName[name_len] = 0x04; /* pad */
1348 /* protocol requires ASCII signature byte on Unicode string */
1349 pSMB->OldFileName[name_len + 1] = 0x00;
1351 cifsConvertToUCS((__le16 *) &pSMB->OldFileName[name_len + 2],
1352 toName, PATH_MAX, nls_codepage, remap);
1353 name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
1354 name_len2 *= 2; /* convert to bytes */
1355 } else { /* BB improve the check for buffer overruns BB */
1356 name_len = strnlen(fromName, PATH_MAX);
1357 name_len++; /* trailing null */
1358 strncpy(pSMB->OldFileName, fromName, name_len);
1359 name_len2 = strnlen(toName, PATH_MAX);
1360 name_len2++; /* trailing null */
1361 pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */
1362 strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2);
1363 name_len2++; /* trailing null */
1364 name_len2++; /* signature byte */
1367 count = 1 /* 1st signature byte */ + name_len + name_len2;
1368 pSMB->hdr.smb_buf_length += count;
1369 pSMB->ByteCount = cpu_to_le16(count);
1371 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1372 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1373 cifs_stats_inc(&tcon->num_renames);
1375 cFYI(1, ("Send error in rename = %d", rc));
1378 cifs_buf_release(pSMB);
1386 int CIFSSMBRenameOpenFile(const int xid,struct cifsTconInfo *pTcon,
1387 int netfid, char * target_name,
1388 const struct nls_table * nls_codepage, int remap)
1390 struct smb_com_transaction2_sfi_req *pSMB = NULL;
1391 struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
1392 struct set_file_rename * rename_info;
1394 char dummy_string[30];
1396 int bytes_returned = 0;
1398 __u16 params, param_offset, offset, count, byte_count;
1400 cFYI(1, ("Rename to File by handle"));
1401 rc = smb_init(SMB_COM_TRANSACTION2, 15, pTcon, (void **) &pSMB,
1407 pSMB->MaxSetupCount = 0;
1411 pSMB->Reserved2 = 0;
1412 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
1413 offset = param_offset + params;
1415 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
1416 rename_info = (struct set_file_rename *) data_offset;
1417 pSMB->MaxParameterCount = cpu_to_le16(2);
1418 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB PDU from sess */
1419 pSMB->SetupCount = 1;
1420 pSMB->Reserved3 = 0;
1421 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
1422 byte_count = 3 /* pad */ + params;
1423 pSMB->ParameterCount = cpu_to_le16(params);
1424 pSMB->TotalParameterCount = pSMB->ParameterCount;
1425 pSMB->ParameterOffset = cpu_to_le16(param_offset);
1426 pSMB->DataOffset = cpu_to_le16(offset);
1427 /* construct random name ".cifs_tmp<inodenum><mid>" */
1428 rename_info->overwrite = cpu_to_le32(1);
1429 rename_info->root_fid = 0;
1430 /* unicode only call */
1431 if(target_name == NULL) {
1432 sprintf(dummy_string,"cifs%x",pSMB->hdr.Mid);
1433 len_of_str = cifsConvertToUCS((__le16 *)rename_info->target_name,
1434 dummy_string, 24, nls_codepage, remap);
1436 len_of_str = cifsConvertToUCS((__le16 *)rename_info->target_name,
1437 target_name, PATH_MAX, nls_codepage, remap);
1439 rename_info->target_name_len = cpu_to_le32(2 * len_of_str);
1440 count = 12 /* sizeof(struct set_file_rename) */ + (2 * len_of_str) + 2;
1441 byte_count += count;
1442 pSMB->DataCount = cpu_to_le16(count);
1443 pSMB->TotalDataCount = pSMB->DataCount;
1445 pSMB->InformationLevel =
1446 cpu_to_le16(SMB_SET_FILE_RENAME_INFORMATION);
1447 pSMB->Reserved4 = 0;
1448 pSMB->hdr.smb_buf_length += byte_count;
1449 pSMB->ByteCount = cpu_to_le16(byte_count);
1450 rc = SendReceive(xid, pTcon->ses, (struct smb_hdr *) pSMB,
1451 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1452 cifs_stats_inc(&pTcon->num_t2renames);
1454 cFYI(1,("Send error in Rename (by file handle) = %d", rc));
1457 cifs_buf_release(pSMB);
1459 /* Note: On -EAGAIN error only caller can retry on handle based calls
1460 since file handle passed in no longer valid */
1466 CIFSSMBCopy(const int xid, struct cifsTconInfo *tcon, const char * fromName,
1467 const __u16 target_tid, const char *toName, const int flags,
1468 const struct nls_table *nls_codepage, int remap)
1471 COPY_REQ *pSMB = NULL;
1472 COPY_RSP *pSMBr = NULL;
1474 int name_len, name_len2;
1477 cFYI(1, ("In CIFSSMBCopy"));
1479 rc = smb_init(SMB_COM_COPY, 1, tcon, (void **) &pSMB,
1484 pSMB->BufferFormat = 0x04;
1485 pSMB->Tid2 = target_tid;
1487 pSMB->Flags = cpu_to_le16(flags & COPY_TREE);
1489 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1490 name_len = cifsConvertToUCS((__le16 *) pSMB->OldFileName,
1491 fromName, PATH_MAX, nls_codepage,
1493 name_len++; /* trailing null */
1495 pSMB->OldFileName[name_len] = 0x04; /* pad */
1496 /* protocol requires ASCII signature byte on Unicode string */
1497 pSMB->OldFileName[name_len + 1] = 0x00;
1498 name_len2 = cifsConvertToUCS((__le16 *)&pSMB->OldFileName[name_len + 2],
1499 toName, PATH_MAX, nls_codepage, remap);
1500 name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
1501 name_len2 *= 2; /* convert to bytes */
1502 } else { /* BB improve the check for buffer overruns BB */
1503 name_len = strnlen(fromName, PATH_MAX);
1504 name_len++; /* trailing null */
1505 strncpy(pSMB->OldFileName, fromName, name_len);
1506 name_len2 = strnlen(toName, PATH_MAX);
1507 name_len2++; /* trailing null */
1508 pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */
1509 strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2);
1510 name_len2++; /* trailing null */
1511 name_len2++; /* signature byte */
1514 count = 1 /* 1st signature byte */ + name_len + name_len2;
1515 pSMB->hdr.smb_buf_length += count;
1516 pSMB->ByteCount = cpu_to_le16(count);
1518 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1519 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1521 cFYI(1, ("Send error in copy = %d with %d files copied",
1522 rc, le16_to_cpu(pSMBr->CopyCount)));
1525 cifs_buf_release(pSMB);
1534 CIFSUnixCreateSymLink(const int xid, struct cifsTconInfo *tcon,
1535 const char *fromName, const char *toName,
1536 const struct nls_table *nls_codepage)
1538 TRANSACTION2_SPI_REQ *pSMB = NULL;
1539 TRANSACTION2_SPI_RSP *pSMBr = NULL;
1542 int name_len_target;
1544 int bytes_returned = 0;
1545 __u16 params, param_offset, offset, byte_count;
1547 cFYI(1, ("In Symlink Unix style"));
1549 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
1554 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1556 cifs_strtoUCS((wchar_t *) pSMB->FileName, fromName, PATH_MAX
1557 /* find define for this maxpathcomponent */
1559 name_len++; /* trailing null */
1562 } else { /* BB improve the check for buffer overruns BB */
1563 name_len = strnlen(fromName, PATH_MAX);
1564 name_len++; /* trailing null */
1565 strncpy(pSMB->FileName, fromName, name_len);
1567 params = 6 + name_len;
1568 pSMB->MaxSetupCount = 0;
1572 pSMB->Reserved2 = 0;
1573 param_offset = offsetof(struct smb_com_transaction2_spi_req,
1574 InformationLevel) - 4;
1575 offset = param_offset + params;
1577 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
1578 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1580 cifs_strtoUCS((wchar_t *) data_offset, toName, PATH_MAX
1581 /* find define for this maxpathcomponent */
1583 name_len_target++; /* trailing null */
1584 name_len_target *= 2;
1585 } else { /* BB improve the check for buffer overruns BB */
1586 name_len_target = strnlen(toName, PATH_MAX);
1587 name_len_target++; /* trailing null */
1588 strncpy(data_offset, toName, name_len_target);
1591 pSMB->MaxParameterCount = cpu_to_le16(2);
1592 /* BB find exact max on data count below from sess */
1593 pSMB->MaxDataCount = cpu_to_le16(1000);
1594 pSMB->SetupCount = 1;
1595 pSMB->Reserved3 = 0;
1596 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
1597 byte_count = 3 /* pad */ + params + name_len_target;
1598 pSMB->DataCount = cpu_to_le16(name_len_target);
1599 pSMB->ParameterCount = cpu_to_le16(params);
1600 pSMB->TotalDataCount = pSMB->DataCount;
1601 pSMB->TotalParameterCount = pSMB->ParameterCount;
1602 pSMB->ParameterOffset = cpu_to_le16(param_offset);
1603 pSMB->DataOffset = cpu_to_le16(offset);
1604 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_LINK);
1605 pSMB->Reserved4 = 0;
1606 pSMB->hdr.smb_buf_length += byte_count;
1607 pSMB->ByteCount = cpu_to_le16(byte_count);
1608 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1609 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1610 cifs_stats_inc(&tcon->num_symlinks);
1613 ("Send error in SetPathInfo (create symlink) = %d",
1618 cifs_buf_release(pSMB);
1621 goto createSymLinkRetry;
1627 CIFSUnixCreateHardLink(const int xid, struct cifsTconInfo *tcon,
1628 const char *fromName, const char *toName,
1629 const struct nls_table *nls_codepage, int remap)
1631 TRANSACTION2_SPI_REQ *pSMB = NULL;
1632 TRANSACTION2_SPI_RSP *pSMBr = NULL;
1635 int name_len_target;
1637 int bytes_returned = 0;
1638 __u16 params, param_offset, offset, byte_count;
1640 cFYI(1, ("In Create Hard link Unix style"));
1641 createHardLinkRetry:
1642 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
1647 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1648 name_len = cifsConvertToUCS((__le16 *) pSMB->FileName, toName,
1649 PATH_MAX, nls_codepage, remap);
1650 name_len++; /* trailing null */
1653 } else { /* BB improve the check for buffer overruns BB */
1654 name_len = strnlen(toName, PATH_MAX);
1655 name_len++; /* trailing null */
1656 strncpy(pSMB->FileName, toName, name_len);
1658 params = 6 + name_len;
1659 pSMB->MaxSetupCount = 0;
1663 pSMB->Reserved2 = 0;
1664 param_offset = offsetof(struct smb_com_transaction2_spi_req,
1665 InformationLevel) - 4;
1666 offset = param_offset + params;
1668 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
1669 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1671 cifsConvertToUCS((__le16 *) data_offset, fromName, PATH_MAX,
1672 nls_codepage, remap);
1673 name_len_target++; /* trailing null */
1674 name_len_target *= 2;
1675 } else { /* BB improve the check for buffer overruns BB */
1676 name_len_target = strnlen(fromName, PATH_MAX);
1677 name_len_target++; /* trailing null */
1678 strncpy(data_offset, fromName, name_len_target);
1681 pSMB->MaxParameterCount = cpu_to_le16(2);
1682 /* BB find exact max on data count below from sess*/
1683 pSMB->MaxDataCount = cpu_to_le16(1000);
1684 pSMB->SetupCount = 1;
1685 pSMB->Reserved3 = 0;
1686 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
1687 byte_count = 3 /* pad */ + params + name_len_target;
1688 pSMB->ParameterCount = cpu_to_le16(params);
1689 pSMB->TotalParameterCount = pSMB->ParameterCount;
1690 pSMB->DataCount = cpu_to_le16(name_len_target);
1691 pSMB->TotalDataCount = pSMB->DataCount;
1692 pSMB->ParameterOffset = cpu_to_le16(param_offset);
1693 pSMB->DataOffset = cpu_to_le16(offset);
1694 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_HLINK);
1695 pSMB->Reserved4 = 0;
1696 pSMB->hdr.smb_buf_length += byte_count;
1697 pSMB->ByteCount = cpu_to_le16(byte_count);
1698 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1699 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1700 cifs_stats_inc(&tcon->num_hardlinks);
1702 cFYI(1, ("Send error in SetPathInfo (hard link) = %d", rc));
1705 cifs_buf_release(pSMB);
1707 goto createHardLinkRetry;
1713 CIFSCreateHardLink(const int xid, struct cifsTconInfo *tcon,
1714 const char *fromName, const char *toName,
1715 const struct nls_table *nls_codepage, int remap)
1718 NT_RENAME_REQ *pSMB = NULL;
1719 RENAME_RSP *pSMBr = NULL;
1721 int name_len, name_len2;
1724 cFYI(1, ("In CIFSCreateHardLink"));
1725 winCreateHardLinkRetry:
1727 rc = smb_init(SMB_COM_NT_RENAME, 4, tcon, (void **) &pSMB,
1732 pSMB->SearchAttributes =
1733 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
1735 pSMB->Flags = cpu_to_le16(CREATE_HARD_LINK);
1736 pSMB->ClusterCount = 0;
1738 pSMB->BufferFormat = 0x04;
1740 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1742 cifsConvertToUCS((__le16 *) pSMB->OldFileName, fromName,
1743 PATH_MAX, nls_codepage, remap);
1744 name_len++; /* trailing null */
1746 pSMB->OldFileName[name_len] = 0; /* pad */
1747 pSMB->OldFileName[name_len + 1] = 0x04;
1749 cifsConvertToUCS((__le16 *)&pSMB->OldFileName[name_len + 2],
1750 toName, PATH_MAX, nls_codepage, remap);
1751 name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
1752 name_len2 *= 2; /* convert to bytes */
1753 } else { /* BB improve the check for buffer overruns BB */
1754 name_len = strnlen(fromName, PATH_MAX);
1755 name_len++; /* trailing null */
1756 strncpy(pSMB->OldFileName, fromName, name_len);
1757 name_len2 = strnlen(toName, PATH_MAX);
1758 name_len2++; /* trailing null */
1759 pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */
1760 strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2);
1761 name_len2++; /* trailing null */
1762 name_len2++; /* signature byte */
1765 count = 1 /* string type byte */ + name_len + name_len2;
1766 pSMB->hdr.smb_buf_length += count;
1767 pSMB->ByteCount = cpu_to_le16(count);
1769 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1770 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1771 cifs_stats_inc(&tcon->num_hardlinks);
1773 cFYI(1, ("Send error in hard link (NT rename) = %d", rc));
1775 cifs_buf_release(pSMB);
1777 goto winCreateHardLinkRetry;
1783 CIFSSMBUnixQuerySymLink(const int xid, struct cifsTconInfo *tcon,
1784 const unsigned char *searchName,
1785 char *symlinkinfo, const int buflen,
1786 const struct nls_table *nls_codepage)
1788 /* SMB_QUERY_FILE_UNIX_LINK */
1789 TRANSACTION2_QPI_REQ *pSMB = NULL;
1790 TRANSACTION2_QPI_RSP *pSMBr = NULL;
1794 __u16 params, byte_count;
1796 cFYI(1, ("In QPathSymLinkInfo (Unix) for path %s", searchName));
1799 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
1804 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1806 cifs_strtoUCS((wchar_t *) pSMB->FileName, searchName, PATH_MAX
1807 /* find define for this maxpathcomponent */
1809 name_len++; /* trailing null */
1811 } else { /* BB improve the check for buffer overruns BB */
1812 name_len = strnlen(searchName, PATH_MAX);
1813 name_len++; /* trailing null */
1814 strncpy(pSMB->FileName, searchName, name_len);
1817 params = 2 /* level */ + 4 /* rsrvd */ + name_len /* incl null */ ;
1818 pSMB->TotalDataCount = 0;
1819 pSMB->MaxParameterCount = cpu_to_le16(2);
1820 /* BB find exact max data count below from sess structure BB */
1821 pSMB->MaxDataCount = cpu_to_le16(4000);
1822 pSMB->MaxSetupCount = 0;
1826 pSMB->Reserved2 = 0;
1827 pSMB->ParameterOffset = cpu_to_le16(offsetof(
1828 struct smb_com_transaction2_qpi_req ,InformationLevel) - 4);
1829 pSMB->DataCount = 0;
1830 pSMB->DataOffset = 0;
1831 pSMB->SetupCount = 1;
1832 pSMB->Reserved3 = 0;
1833 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
1834 byte_count = params + 1 /* pad */ ;
1835 pSMB->TotalParameterCount = cpu_to_le16(params);
1836 pSMB->ParameterCount = pSMB->TotalParameterCount;
1837 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_LINK);
1838 pSMB->Reserved4 = 0;
1839 pSMB->hdr.smb_buf_length += byte_count;
1840 pSMB->ByteCount = cpu_to_le16(byte_count);
1842 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1843 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1845 cFYI(1, ("Send error in QuerySymLinkInfo = %d", rc));
1847 /* decode response */
1849 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
1850 if (rc || (pSMBr->ByteCount < 2))
1851 /* BB also check enough total bytes returned */
1852 rc = -EIO; /* bad smb */
1854 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
1855 __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
1857 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
1858 name_len = UniStrnlen((wchar_t *) ((char *)
1859 &pSMBr->hdr.Protocol +data_offset),
1860 min_t(const int, buflen,count) / 2);
1861 /* BB FIXME investigate remapping reserved chars here */
1862 cifs_strfromUCS_le(symlinkinfo,
1863 (wchar_t *) ((char *)&pSMBr->hdr.Protocol +
1865 name_len, nls_codepage);
1867 strncpy(symlinkinfo,
1868 (char *) &pSMBr->hdr.Protocol +
1870 min_t(const int, buflen, count));
1872 symlinkinfo[buflen] = 0;
1873 /* just in case so calling code does not go off the end of buffer */
1876 cifs_buf_release(pSMB);
1878 goto querySymLinkRetry;
1883 CIFSSMBQueryReparseLinkInfo(const int xid, struct cifsTconInfo *tcon,
1884 const unsigned char *searchName,
1885 char *symlinkinfo, const int buflen,__u16 fid,
1886 const struct nls_table *nls_codepage)
1891 struct smb_com_transaction_ioctl_req * pSMB;
1892 struct smb_com_transaction_ioctl_rsp * pSMBr;
1894 cFYI(1, ("In Windows reparse style QueryLink for path %s", searchName));
1895 rc = smb_init(SMB_COM_NT_TRANSACT, 23, tcon, (void **) &pSMB,
1900 pSMB->TotalParameterCount = 0 ;
1901 pSMB->TotalDataCount = 0;
1902 pSMB->MaxParameterCount = cpu_to_le32(2);
1903 /* BB find exact data count max from sess structure BB */
1904 pSMB->MaxDataCount = cpu_to_le32(4000);
1905 pSMB->MaxSetupCount = 4;
1907 pSMB->ParameterOffset = 0;
1908 pSMB->DataCount = 0;
1909 pSMB->DataOffset = 0;
1910 pSMB->SetupCount = 4;
1911 pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_IOCTL);
1912 pSMB->ParameterCount = pSMB->TotalParameterCount;
1913 pSMB->FunctionCode = cpu_to_le32(FSCTL_GET_REPARSE_POINT);
1914 pSMB->IsFsctl = 1; /* FSCTL */
1915 pSMB->IsRootFlag = 0;
1916 pSMB->Fid = fid; /* file handle always le */
1917 pSMB->ByteCount = 0;
1919 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1920 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1922 cFYI(1, ("Send error in QueryReparseLinkInfo = %d", rc));
1923 } else { /* decode response */
1924 __u32 data_offset = le32_to_cpu(pSMBr->DataOffset);
1925 __u32 data_count = le32_to_cpu(pSMBr->DataCount);
1926 if ((pSMBr->ByteCount < 2) || (data_offset > 512))
1927 /* BB also check enough total bytes returned */
1928 rc = -EIO; /* bad smb */
1930 if(data_count && (data_count < 2048)) {
1931 char * end_of_smb = pSMBr->ByteCount + (char *)&pSMBr->ByteCount;
1933 struct reparse_data * reparse_buf = (struct reparse_data *)
1934 ((char *)&pSMBr->hdr.Protocol + data_offset);
1935 if((char*)reparse_buf >= end_of_smb) {
1939 if((reparse_buf->LinkNamesBuf +
1940 reparse_buf->TargetNameOffset +
1941 reparse_buf->TargetNameLen) >
1943 cFYI(1,("reparse buf extended beyond SMB"));
1948 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
1949 name_len = UniStrnlen((wchar_t *)
1950 (reparse_buf->LinkNamesBuf +
1951 reparse_buf->TargetNameOffset),
1952 min(buflen/2, reparse_buf->TargetNameLen / 2));
1953 cifs_strfromUCS_le(symlinkinfo,
1954 (wchar_t *) (reparse_buf->LinkNamesBuf +
1955 reparse_buf->TargetNameOffset),
1956 name_len, nls_codepage);
1957 } else { /* ASCII names */
1958 strncpy(symlinkinfo,reparse_buf->LinkNamesBuf +
1959 reparse_buf->TargetNameOffset,
1960 min_t(const int, buflen, reparse_buf->TargetNameLen));
1964 cFYI(1,("Invalid return data count on get reparse info ioctl"));
1966 symlinkinfo[buflen] = 0; /* just in case so the caller
1967 does not go off the end of the buffer */
1968 cFYI(1,("readlink result - %s ",symlinkinfo));
1972 cifs_buf_release(pSMB);
1974 /* Note: On -EAGAIN error only caller can retry on handle based calls
1975 since file handle passed in no longer valid */
1980 #ifdef CONFIG_CIFS_POSIX
1982 /*Convert an Access Control Entry from wire format to local POSIX xattr format*/
1983 static void cifs_convert_ace(posix_acl_xattr_entry * ace, struct cifs_posix_ace * cifs_ace)
1985 /* u8 cifs fields do not need le conversion */
1986 ace->e_perm = (__u16)cifs_ace->cifs_e_perm;
1987 ace->e_tag = (__u16)cifs_ace->cifs_e_tag;
1988 ace->e_id = (__u32)le64_to_cpu(cifs_ace->cifs_uid);
1989 /* cFYI(1,("perm %d tag %d id %d",ace->e_perm,ace->e_tag,ace->e_id)); */
1994 /* Convert ACL from CIFS POSIX wire format to local Linux POSIX ACL xattr */
1995 static int cifs_copy_posix_acl(char * trgt,char * src, const int buflen,
1996 const int acl_type,const int size_of_data_area)
2001 struct cifs_posix_ace * pACE;
2002 struct cifs_posix_acl * cifs_acl = (struct cifs_posix_acl *)src;
2003 posix_acl_xattr_header * local_acl = (posix_acl_xattr_header *)trgt;
2005 if (le16_to_cpu(cifs_acl->version) != CIFS_ACL_VERSION)
2008 if(acl_type & ACL_TYPE_ACCESS) {
2009 count = le16_to_cpu(cifs_acl->access_entry_count);
2010 pACE = &cifs_acl->ace_array[0];
2011 size = sizeof(struct cifs_posix_acl);
2012 size += sizeof(struct cifs_posix_ace) * count;
2013 /* check if we would go beyond end of SMB */
2014 if(size_of_data_area < size) {
2015 cFYI(1,("bad CIFS POSIX ACL size %d vs. %d",size_of_data_area,size));
2018 } else if(acl_type & ACL_TYPE_DEFAULT) {
2019 count = le16_to_cpu(cifs_acl->access_entry_count);
2020 size = sizeof(struct cifs_posix_acl);
2021 size += sizeof(struct cifs_posix_ace) * count;
2022 /* skip past access ACEs to get to default ACEs */
2023 pACE = &cifs_acl->ace_array[count];
2024 count = le16_to_cpu(cifs_acl->default_entry_count);
2025 size += sizeof(struct cifs_posix_ace) * count;
2026 /* check if we would go beyond end of SMB */
2027 if(size_of_data_area < size)
2034 size = posix_acl_xattr_size(count);
2035 if((buflen == 0) || (local_acl == NULL)) {
2036 /* used to query ACL EA size */
2037 } else if(size > buflen) {
2039 } else /* buffer big enough */ {
2040 local_acl->a_version = POSIX_ACL_XATTR_VERSION;
2041 for(i = 0;i < count ;i++) {
2042 cifs_convert_ace(&local_acl->a_entries[i],pACE);
2049 static __u16 convert_ace_to_cifs_ace(struct cifs_posix_ace * cifs_ace,
2050 const posix_acl_xattr_entry * local_ace)
2052 __u16 rc = 0; /* 0 = ACL converted ok */
2054 cifs_ace->cifs_e_perm = (__u8)cpu_to_le16(local_ace->e_perm);
2055 cifs_ace->cifs_e_tag = (__u8)cpu_to_le16(local_ace->e_tag);
2056 /* BB is there a better way to handle the large uid? */
2057 if(local_ace->e_id == -1) {
2058 /* Probably no need to le convert -1 on any arch but can not hurt */
2059 cifs_ace->cifs_uid = cpu_to_le64(-1);
2061 cifs_ace->cifs_uid = (__u64)cpu_to_le32(local_ace->e_id);
2062 /*cFYI(1,("perm %d tag %d id %d",ace->e_perm,ace->e_tag,ace->e_id));*/
2066 /* Convert ACL from local Linux POSIX xattr to CIFS POSIX ACL wire format */
2067 static __u16 ACL_to_cifs_posix(char * parm_data,const char * pACL,const int buflen,
2071 struct cifs_posix_acl * cifs_acl = (struct cifs_posix_acl *)parm_data;
2072 posix_acl_xattr_header * local_acl = (posix_acl_xattr_header *)pACL;
2076 if((buflen == 0) || (pACL == NULL) || (cifs_acl == NULL))
2079 count = posix_acl_xattr_count((size_t)buflen);
2080 cFYI(1,("setting acl with %d entries from buf of length %d and version of %d",
2081 count,buflen,local_acl->a_version));
2082 if(local_acl->a_version != 2) {
2083 cFYI(1,("unknown POSIX ACL version %d",local_acl->a_version));
2086 cifs_acl->version = cpu_to_le16(1);
2087 if(acl_type == ACL_TYPE_ACCESS)
2088 cifs_acl->access_entry_count = count;
2089 else if(acl_type == ACL_TYPE_DEFAULT)
2090 cifs_acl->default_entry_count = count;
2092 cFYI(1,("unknown ACL type %d",acl_type));
2095 for(i=0;i<count;i++) {
2096 rc = convert_ace_to_cifs_ace(&cifs_acl->ace_array[i],
2097 &local_acl->a_entries[i]);
2099 /* ACE not converted */
2104 rc = (__u16)(count * sizeof(struct cifs_posix_ace));
2105 rc += sizeof(struct cifs_posix_acl);
2106 /* BB add check to make sure ACL does not overflow SMB */
2112 CIFSSMBGetPosixACL(const int xid, struct cifsTconInfo *tcon,
2113 const unsigned char *searchName,
2114 char *acl_inf, const int buflen, const int acl_type,
2115 const struct nls_table *nls_codepage, int remap)
2117 /* SMB_QUERY_POSIX_ACL */
2118 TRANSACTION2_QPI_REQ *pSMB = NULL;
2119 TRANSACTION2_QPI_RSP *pSMBr = NULL;
2123 __u16 params, byte_count;
2125 cFYI(1, ("In GetPosixACL (Unix) for path %s", searchName));
2128 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2133 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2135 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
2136 PATH_MAX, nls_codepage, remap);
2137 name_len++; /* trailing null */
2139 pSMB->FileName[name_len] = 0;
2140 pSMB->FileName[name_len+1] = 0;
2141 } else { /* BB improve the check for buffer overruns BB */
2142 name_len = strnlen(searchName, PATH_MAX);
2143 name_len++; /* trailing null */
2144 strncpy(pSMB->FileName, searchName, name_len);
2147 params = 2 /* level */ + 4 /* rsrvd */ + name_len /* incl null */ ;
2148 pSMB->TotalDataCount = 0;
2149 pSMB->MaxParameterCount = cpu_to_le16(2);
2150 /* BB find exact max data count below from sess structure BB */
2151 pSMB->MaxDataCount = cpu_to_le16(4000);
2152 pSMB->MaxSetupCount = 0;
2156 pSMB->Reserved2 = 0;
2157 pSMB->ParameterOffset = cpu_to_le16(
2158 offsetof(struct smb_com_transaction2_qpi_req ,InformationLevel) - 4);
2159 pSMB->DataCount = 0;
2160 pSMB->DataOffset = 0;
2161 pSMB->SetupCount = 1;
2162 pSMB->Reserved3 = 0;
2163 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
2164 byte_count = params + 1 /* pad */ ;
2165 pSMB->TotalParameterCount = cpu_to_le16(params);
2166 pSMB->ParameterCount = pSMB->TotalParameterCount;
2167 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_POSIX_ACL);
2168 pSMB->Reserved4 = 0;
2169 pSMB->hdr.smb_buf_length += byte_count;
2170 pSMB->ByteCount = cpu_to_le16(byte_count);
2172 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2173 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2175 cFYI(1, ("Send error in Query POSIX ACL = %d", rc));
2177 /* decode response */
2179 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
2180 if (rc || (pSMBr->ByteCount < 2))
2181 /* BB also check enough total bytes returned */
2182 rc = -EIO; /* bad smb */
2184 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
2185 __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
2186 rc = cifs_copy_posix_acl(acl_inf,
2187 (char *)&pSMBr->hdr.Protocol+data_offset,
2188 buflen,acl_type,count);
2191 cifs_buf_release(pSMB);
2198 CIFSSMBSetPosixACL(const int xid, struct cifsTconInfo *tcon,
2199 const unsigned char *fileName,
2200 const char *local_acl, const int buflen,
2202 const struct nls_table *nls_codepage, int remap)
2204 struct smb_com_transaction2_spi_req *pSMB = NULL;
2205 struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
2209 int bytes_returned = 0;
2210 __u16 params, byte_count, data_count, param_offset, offset;
2212 cFYI(1, ("In SetPosixACL (Unix) for path %s", fileName));
2214 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2218 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2220 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
2221 PATH_MAX, nls_codepage, remap);
2222 name_len++; /* trailing null */
2224 } else { /* BB improve the check for buffer overruns BB */
2225 name_len = strnlen(fileName, PATH_MAX);
2226 name_len++; /* trailing null */
2227 strncpy(pSMB->FileName, fileName, name_len);
2229 params = 6 + name_len;
2230 pSMB->MaxParameterCount = cpu_to_le16(2);
2231 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB size from sess */
2232 pSMB->MaxSetupCount = 0;
2236 pSMB->Reserved2 = 0;
2237 param_offset = offsetof(struct smb_com_transaction2_spi_req,
2238 InformationLevel) - 4;
2239 offset = param_offset + params;
2240 parm_data = ((char *) &pSMB->hdr.Protocol) + offset;
2241 pSMB->ParameterOffset = cpu_to_le16(param_offset);
2243 /* convert to on the wire format for POSIX ACL */
2244 data_count = ACL_to_cifs_posix(parm_data,local_acl,buflen,acl_type);
2246 if(data_count == 0) {
2248 goto setACLerrorExit;
2250 pSMB->DataOffset = cpu_to_le16(offset);
2251 pSMB->SetupCount = 1;
2252 pSMB->Reserved3 = 0;
2253 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
2254 pSMB->InformationLevel = cpu_to_le16(SMB_SET_POSIX_ACL);
2255 byte_count = 3 /* pad */ + params + data_count;
2256 pSMB->DataCount = cpu_to_le16(data_count);
2257 pSMB->TotalDataCount = pSMB->DataCount;
2258 pSMB->ParameterCount = cpu_to_le16(params);
2259 pSMB->TotalParameterCount = pSMB->ParameterCount;
2260 pSMB->Reserved4 = 0;
2261 pSMB->hdr.smb_buf_length += byte_count;
2262 pSMB->ByteCount = cpu_to_le16(byte_count);
2263 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2264 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2266 cFYI(1, ("Set POSIX ACL returned %d", rc));
2270 cifs_buf_release(pSMB);
2276 /* BB fix tabs in this function FIXME BB */
2278 CIFSGetExtAttr(const int xid, struct cifsTconInfo *tcon,
2279 const int netfid, __u64 * pExtAttrBits, __u64 *pMask)
2282 struct smb_t2_qfi_req *pSMB = NULL;
2283 struct smb_t2_qfi_rsp *pSMBr = NULL;
2285 __u16 params, byte_count;
2287 cFYI(1,("In GetExtAttr"));
2292 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2297 params = 2 /* level */ +2 /* fid */;
2298 pSMB->t2.TotalDataCount = 0;
2299 pSMB->t2.MaxParameterCount = cpu_to_le16(4);
2300 /* BB find exact max data count below from sess structure BB */
2301 pSMB->t2.MaxDataCount = cpu_to_le16(4000);
2302 pSMB->t2.MaxSetupCount = 0;
2303 pSMB->t2.Reserved = 0;
2305 pSMB->t2.Timeout = 0;
2306 pSMB->t2.Reserved2 = 0;
2307 pSMB->t2.ParameterOffset = cpu_to_le16(offsetof(struct smb_t2_qfi_req,
2309 pSMB->t2.DataCount = 0;
2310 pSMB->t2.DataOffset = 0;
2311 pSMB->t2.SetupCount = 1;
2312 pSMB->t2.Reserved3 = 0;
2313 pSMB->t2.SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION);
2314 byte_count = params + 1 /* pad */ ;
2315 pSMB->t2.TotalParameterCount = cpu_to_le16(params);
2316 pSMB->t2.ParameterCount = pSMB->t2.TotalParameterCount;
2317 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_ATTR_FLAGS);
2320 pSMB->hdr.smb_buf_length += byte_count;
2321 pSMB->t2.ByteCount = cpu_to_le16(byte_count);
2323 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2324 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2326 cFYI(1, ("error %d in GetExtAttr", rc));
2328 /* decode response */
2329 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
2330 if (rc || (pSMBr->ByteCount < 2))
2331 /* BB also check enough total bytes returned */
2332 /* If rc should we check for EOPNOSUPP and
2333 disable the srvino flag? or in caller? */
2334 rc = -EIO; /* bad smb */
2336 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
2337 __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
2338 struct file_chattr_info * pfinfo;
2339 /* BB Do we need a cast or hash here ? */
2341 cFYI(1, ("Illegal size ret in GetExtAttr"));
2345 pfinfo = (struct file_chattr_info *)
2346 (data_offset + (char *) &pSMBr->hdr.Protocol);
2347 *pExtAttrBits = le64_to_cpu(pfinfo->mode);
2348 *pMask = le64_to_cpu(pfinfo->mask);
2352 cifs_buf_release(pSMB);
2354 goto GetExtAttrRetry;
2359 #endif /* CONFIG_POSIX */
2361 /* Legacy Query Path Information call for lookup to old servers such
2363 int SMBQueryInformation(const int xid, struct cifsTconInfo *tcon,
2364 const unsigned char *searchName,
2365 FILE_ALL_INFO * pFinfo,
2366 const struct nls_table *nls_codepage, int remap)
2368 QUERY_INFORMATION_REQ * pSMB;
2369 QUERY_INFORMATION_RSP * pSMBr;
2374 cFYI(1, ("In SMBQPath path %s", searchName));
2376 rc = smb_init(SMB_COM_QUERY_INFORMATION, 0, tcon, (void **) &pSMB,
2381 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2383 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
2384 PATH_MAX, nls_codepage, remap);
2385 name_len++; /* trailing null */
2388 name_len = strnlen(searchName, PATH_MAX);
2389 name_len++; /* trailing null */
2390 strncpy(pSMB->FileName, searchName, name_len);
2392 pSMB->BufferFormat = 0x04;
2393 name_len++; /* account for buffer type byte */
2394 pSMB->hdr.smb_buf_length += (__u16) name_len;
2395 pSMB->ByteCount = cpu_to_le16(name_len);
2397 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2398 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2400 cFYI(1, ("Send error in QueryInfo = %d", rc));
2401 } else if (pFinfo) { /* decode response */
2402 memset(pFinfo, 0, sizeof(FILE_ALL_INFO));
2403 pFinfo->AllocationSize =
2404 cpu_to_le64(le32_to_cpu(pSMBr->size));
2405 pFinfo->EndOfFile = pFinfo->AllocationSize;
2406 pFinfo->Attributes =
2407 cpu_to_le32(le16_to_cpu(pSMBr->attr));
2409 rc = -EIO; /* bad buffer passed in */
2411 cifs_buf_release(pSMB);
2423 CIFSSMBQPathInfo(const int xid, struct cifsTconInfo *tcon,
2424 const unsigned char *searchName,
2425 FILE_ALL_INFO * pFindData,
2426 const struct nls_table *nls_codepage, int remap)
2428 /* level 263 SMB_QUERY_FILE_ALL_INFO */
2429 TRANSACTION2_QPI_REQ *pSMB = NULL;
2430 TRANSACTION2_QPI_RSP *pSMBr = NULL;
2434 __u16 params, byte_count;
2436 /* cFYI(1, ("In QPathInfo path %s", searchName)); */
2438 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2443 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2445 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
2446 PATH_MAX, nls_codepage, remap);
2447 name_len++; /* trailing null */
2449 } else { /* BB improve the check for buffer overruns BB */
2450 name_len = strnlen(searchName, PATH_MAX);
2451 name_len++; /* trailing null */
2452 strncpy(pSMB->FileName, searchName, name_len);
2455 params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */ ;
2456 pSMB->TotalDataCount = 0;
2457 pSMB->MaxParameterCount = cpu_to_le16(2);
2458 pSMB->MaxDataCount = cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
2459 pSMB->MaxSetupCount = 0;
2463 pSMB->Reserved2 = 0;
2464 pSMB->ParameterOffset = cpu_to_le16(offsetof(
2465 struct smb_com_transaction2_qpi_req ,InformationLevel) - 4);
2466 pSMB->DataCount = 0;
2467 pSMB->DataOffset = 0;
2468 pSMB->SetupCount = 1;
2469 pSMB->Reserved3 = 0;
2470 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
2471 byte_count = params + 1 /* pad */ ;
2472 pSMB->TotalParameterCount = cpu_to_le16(params);
2473 pSMB->ParameterCount = pSMB->TotalParameterCount;
2474 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_ALL_INFO);
2475 pSMB->Reserved4 = 0;
2476 pSMB->hdr.smb_buf_length += byte_count;
2477 pSMB->ByteCount = cpu_to_le16(byte_count);
2479 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2480 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2482 cFYI(1, ("Send error in QPathInfo = %d", rc));
2483 } else { /* decode response */
2484 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
2486 if (rc || (pSMBr->ByteCount < 40))
2487 rc = -EIO; /* bad smb */
2488 else if (pFindData){
2489 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
2490 memcpy((char *) pFindData,
2491 (char *) &pSMBr->hdr.Protocol +
2492 data_offset, sizeof (FILE_ALL_INFO));
2496 cifs_buf_release(pSMB);
2498 goto QPathInfoRetry;
2504 CIFSSMBUnixQPathInfo(const int xid, struct cifsTconInfo *tcon,
2505 const unsigned char *searchName,
2506 FILE_UNIX_BASIC_INFO * pFindData,
2507 const struct nls_table *nls_codepage, int remap)
2509 /* SMB_QUERY_FILE_UNIX_BASIC */
2510 TRANSACTION2_QPI_REQ *pSMB = NULL;
2511 TRANSACTION2_QPI_RSP *pSMBr = NULL;
2513 int bytes_returned = 0;
2515 __u16 params, byte_count;
2517 cFYI(1, ("In QPathInfo (Unix) the path %s", searchName));
2519 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2524 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2526 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
2527 PATH_MAX, nls_codepage, remap);
2528 name_len++; /* trailing null */
2530 } else { /* BB improve the check for buffer overruns BB */
2531 name_len = strnlen(searchName, PATH_MAX);
2532 name_len++; /* trailing null */
2533 strncpy(pSMB->FileName, searchName, name_len);
2536 params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */ ;
2537 pSMB->TotalDataCount = 0;
2538 pSMB->MaxParameterCount = cpu_to_le16(2);
2539 /* BB find exact max SMB PDU from sess structure BB */
2540 pSMB->MaxDataCount = cpu_to_le16(4000);
2541 pSMB->MaxSetupCount = 0;
2545 pSMB->Reserved2 = 0;
2546 pSMB->ParameterOffset = cpu_to_le16(offsetof(
2547 struct smb_com_transaction2_qpi_req ,InformationLevel) - 4);
2548 pSMB->DataCount = 0;
2549 pSMB->DataOffset = 0;
2550 pSMB->SetupCount = 1;
2551 pSMB->Reserved3 = 0;
2552 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
2553 byte_count = params + 1 /* pad */ ;
2554 pSMB->TotalParameterCount = cpu_to_le16(params);
2555 pSMB->ParameterCount = pSMB->TotalParameterCount;
2556 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC);
2557 pSMB->Reserved4 = 0;
2558 pSMB->hdr.smb_buf_length += byte_count;
2559 pSMB->ByteCount = cpu_to_le16(byte_count);
2561 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2562 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2564 cFYI(1, ("Send error in QPathInfo = %d", rc));
2565 } else { /* decode response */
2566 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
2568 if (rc || (pSMBr->ByteCount < sizeof(FILE_UNIX_BASIC_INFO))) {
2569 rc = -EIO; /* bad smb */
2571 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
2572 memcpy((char *) pFindData,
2573 (char *) &pSMBr->hdr.Protocol +
2575 sizeof (FILE_UNIX_BASIC_INFO));
2578 cifs_buf_release(pSMB);
2580 goto UnixQPathInfoRetry;
2585 #if 0 /* function unused at present */
2586 int CIFSFindSingle(const int xid, struct cifsTconInfo *tcon,
2587 const char *searchName, FILE_ALL_INFO * findData,
2588 const struct nls_table *nls_codepage)
2590 /* level 257 SMB_ */
2591 TRANSACTION2_FFIRST_REQ *pSMB = NULL;
2592 TRANSACTION2_FFIRST_RSP *pSMBr = NULL;
2596 __u16 params, byte_count;
2598 cFYI(1, ("In FindUnique"));
2600 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2605 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2607 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName, PATH_MAX
2608 /* find define for this maxpathcomponent */
2610 name_len++; /* trailing null */
2612 } else { /* BB improve the check for buffer overruns BB */
2613 name_len = strnlen(searchName, PATH_MAX);
2614 name_len++; /* trailing null */
2615 strncpy(pSMB->FileName, searchName, name_len);
2618 params = 12 + name_len /* includes null */ ;
2619 pSMB->TotalDataCount = 0; /* no EAs */
2620 pSMB->MaxParameterCount = cpu_to_le16(2);
2621 pSMB->MaxDataCount = cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
2622 pSMB->MaxSetupCount = 0;
2626 pSMB->Reserved2 = 0;
2627 pSMB->ParameterOffset = cpu_to_le16(
2628 offsetof(struct smb_com_transaction2_ffirst_req,InformationLevel) - 4);
2629 pSMB->DataCount = 0;
2630 pSMB->DataOffset = 0;
2631 pSMB->SetupCount = 1; /* one byte, no need to le convert */
2632 pSMB->Reserved3 = 0;
2633 pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_FIRST);
2634 byte_count = params + 1 /* pad */ ;
2635 pSMB->TotalParameterCount = cpu_to_le16(params);
2636 pSMB->ParameterCount = pSMB->TotalParameterCount;
2637 pSMB->SearchAttributes =
2638 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
2640 pSMB->SearchCount = cpu_to_le16(16); /* BB increase */
2641 pSMB->SearchFlags = cpu_to_le16(1);
2642 pSMB->InformationLevel = cpu_to_le16(SMB_FIND_FILE_DIRECTORY_INFO);
2643 pSMB->SearchStorageType = 0; /* BB what should we set this to? BB */
2644 pSMB->hdr.smb_buf_length += byte_count;
2645 pSMB->ByteCount = cpu_to_le16(byte_count);
2647 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2648 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2651 cFYI(1, ("Send error in FindFileDirInfo = %d", rc));
2652 } else { /* decode response */
2653 cifs_stats_inc(&tcon->num_ffirst);
2657 cifs_buf_release(pSMB);
2659 goto findUniqueRetry;
2663 #endif /* end unused (temporarily) function */
2665 /* xid, tcon, searchName and codepage are input parms, rest are returned */
2667 CIFSFindFirst(const int xid, struct cifsTconInfo *tcon,
2668 const char *searchName,
2669 const struct nls_table *nls_codepage,
2671 struct cifs_search_info * psrch_inf, int remap, const char dirsep)
2673 /* level 257 SMB_ */
2674 TRANSACTION2_FFIRST_REQ *pSMB = NULL;
2675 TRANSACTION2_FFIRST_RSP *pSMBr = NULL;
2676 T2_FFIRST_RSP_PARMS * parms;
2678 int bytes_returned = 0;
2680 __u16 params, byte_count;
2682 cFYI(1, ("In FindFirst for %s",searchName));
2685 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2690 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2692 cifsConvertToUCS((__le16 *) pSMB->FileName,searchName,
2693 PATH_MAX, nls_codepage, remap);
2694 /* We can not add the asterik earlier in case
2695 it got remapped to 0xF03A as if it were part of the
2696 directory name instead of a wildcard */
2698 pSMB->FileName[name_len] = dirsep;
2699 pSMB->FileName[name_len+1] = 0;
2700 pSMB->FileName[name_len+2] = '*';
2701 pSMB->FileName[name_len+3] = 0;
2702 name_len += 4; /* now the trailing null */
2703 pSMB->FileName[name_len] = 0; /* null terminate just in case */
2704 pSMB->FileName[name_len+1] = 0;
2706 } else { /* BB add check for overrun of SMB buf BB */
2707 name_len = strnlen(searchName, PATH_MAX);
2708 /* BB fix here and in unicode clause above ie
2709 if(name_len > buffersize-header)
2710 free buffer exit; BB */
2711 strncpy(pSMB->FileName, searchName, name_len);
2712 pSMB->FileName[name_len] = dirsep;
2713 pSMB->FileName[name_len+1] = '*';
2714 pSMB->FileName[name_len+2] = 0;
2718 params = 12 + name_len /* includes null */ ;
2719 pSMB->TotalDataCount = 0; /* no EAs */
2720 pSMB->MaxParameterCount = cpu_to_le16(10);
2721 pSMB->MaxDataCount = cpu_to_le16((tcon->ses->server->maxBuf -
2722 MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
2723 pSMB->MaxSetupCount = 0;
2727 pSMB->Reserved2 = 0;
2728 byte_count = params + 1 /* pad */ ;
2729 pSMB->TotalParameterCount = cpu_to_le16(params);
2730 pSMB->ParameterCount = pSMB->TotalParameterCount;
2731 pSMB->ParameterOffset = cpu_to_le16(
2732 offsetof(struct smb_com_transaction2_ffirst_req, SearchAttributes) - 4);
2733 pSMB->DataCount = 0;
2734 pSMB->DataOffset = 0;
2735 pSMB->SetupCount = 1; /* one byte, no need to make endian neutral */
2736 pSMB->Reserved3 = 0;
2737 pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_FIRST);
2738 pSMB->SearchAttributes =
2739 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
2741 pSMB->SearchCount= cpu_to_le16(CIFSMaxBufSize/sizeof(FILE_UNIX_INFO));
2742 pSMB->SearchFlags = cpu_to_le16(CIFS_SEARCH_CLOSE_AT_END |
2743 CIFS_SEARCH_RETURN_RESUME);
2744 pSMB->InformationLevel = cpu_to_le16(psrch_inf->info_level);
2746 /* BB what should we set StorageType to? Does it matter? BB */
2747 pSMB->SearchStorageType = 0;
2748 pSMB->hdr.smb_buf_length += byte_count;
2749 pSMB->ByteCount = cpu_to_le16(byte_count);
2751 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2752 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2753 cifs_stats_inc(&tcon->num_ffirst);
2755 if (rc) {/* BB add logic to retry regular search if Unix search rejected unexpectedly by server */
2756 /* BB Add code to handle unsupported level rc */
2757 cFYI(1, ("Error in FindFirst = %d", rc));
2760 cifs_buf_release(pSMB);
2762 /* BB eventually could optimize out free and realloc of buf */
2765 goto findFirstRetry;
2766 } else { /* decode response */
2767 /* BB remember to free buffer if error BB */
2768 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
2770 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
2771 psrch_inf->unicode = TRUE;
2773 psrch_inf->unicode = FALSE;
2775 psrch_inf->ntwrk_buf_start = (char *)pSMBr;
2776 psrch_inf->srch_entries_start =
2777 (char *) &pSMBr->hdr.Protocol +
2778 le16_to_cpu(pSMBr->t2.DataOffset);
2779 parms = (T2_FFIRST_RSP_PARMS *)((char *) &pSMBr->hdr.Protocol +
2780 le16_to_cpu(pSMBr->t2.ParameterOffset));
2782 if(parms->EndofSearch)
2783 psrch_inf->endOfSearch = TRUE;
2785 psrch_inf->endOfSearch = FALSE;
2787 psrch_inf->entries_in_buffer = le16_to_cpu(parms->SearchCount);
2788 psrch_inf->index_of_last_entry =
2789 psrch_inf->entries_in_buffer;
2790 *pnetfid = parms->SearchHandle;
2792 cifs_buf_release(pSMB);
2799 int CIFSFindNext(const int xid, struct cifsTconInfo *tcon,
2800 __u16 searchHandle, struct cifs_search_info * psrch_inf)
2802 TRANSACTION2_FNEXT_REQ *pSMB = NULL;
2803 TRANSACTION2_FNEXT_RSP *pSMBr = NULL;
2804 T2_FNEXT_RSP_PARMS * parms;
2805 char *response_data;
2807 int bytes_returned, name_len;
2808 __u16 params, byte_count;
2810 cFYI(1, ("In FindNext"));
2812 if(psrch_inf->endOfSearch == TRUE)
2815 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2820 params = 14; /* includes 2 bytes of null string, converted to LE below */
2822 pSMB->TotalDataCount = 0; /* no EAs */
2823 pSMB->MaxParameterCount = cpu_to_le16(8);
2824 pSMB->MaxDataCount =
2825 cpu_to_le16((tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
2826 pSMB->MaxSetupCount = 0;
2830 pSMB->Reserved2 = 0;
2831 pSMB->ParameterOffset = cpu_to_le16(
2832 offsetof(struct smb_com_transaction2_fnext_req,SearchHandle) - 4);
2833 pSMB->DataCount = 0;
2834 pSMB->DataOffset = 0;
2835 pSMB->SetupCount = 1;
2836 pSMB->Reserved3 = 0;
2837 pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_NEXT);
2838 pSMB->SearchHandle = searchHandle; /* always kept as le */
2840 cpu_to_le16(CIFSMaxBufSize / sizeof (FILE_UNIX_INFO));
2841 /* test for Unix extensions */
2842 /* if (tcon->ses->capabilities & CAP_UNIX) {
2843 pSMB->InformationLevel = cpu_to_le16(SMB_FIND_FILE_UNIX);
2844 psrch_inf->info_level = SMB_FIND_FILE_UNIX;
2846 pSMB->InformationLevel =
2847 cpu_to_le16(SMB_FIND_FILE_DIRECTORY_INFO);
2848 psrch_inf->info_level = SMB_FIND_FILE_DIRECTORY_INFO;
2850 pSMB->InformationLevel = cpu_to_le16(psrch_inf->info_level);
2851 pSMB->ResumeKey = psrch_inf->resume_key;
2853 cpu_to_le16(CIFS_SEARCH_CLOSE_AT_END | CIFS_SEARCH_RETURN_RESUME);
2855 name_len = psrch_inf->resume_name_len;
2857 if(name_len < PATH_MAX) {
2858 memcpy(pSMB->ResumeFileName, psrch_inf->presume_name, name_len);
2859 byte_count += name_len;
2860 /* 14 byte parm len above enough for 2 byte null terminator */
2861 pSMB->ResumeFileName[name_len] = 0;
2862 pSMB->ResumeFileName[name_len+1] = 0;
2865 goto FNext2_err_exit;
2867 byte_count = params + 1 /* pad */ ;
2868 pSMB->TotalParameterCount = cpu_to_le16(params);
2869 pSMB->ParameterCount = pSMB->TotalParameterCount;
2870 pSMB->hdr.smb_buf_length += byte_count;
2871 pSMB->ByteCount = cpu_to_le16(byte_count);
2873 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2874 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2875 cifs_stats_inc(&tcon->num_fnext);
2878 psrch_inf->endOfSearch = TRUE;
2879 rc = 0; /* search probably was closed at end of search above */
2881 cFYI(1, ("FindNext returned = %d", rc));
2882 } else { /* decode response */
2883 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
2886 /* BB fixme add lock for file (srch_info) struct here */
2887 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
2888 psrch_inf->unicode = TRUE;
2890 psrch_inf->unicode = FALSE;
2891 response_data = (char *) &pSMBr->hdr.Protocol +
2892 le16_to_cpu(pSMBr->t2.ParameterOffset);
2893 parms = (T2_FNEXT_RSP_PARMS *)response_data;
2894 response_data = (char *)&pSMBr->hdr.Protocol +
2895 le16_to_cpu(pSMBr->t2.DataOffset);
2896 cifs_buf_release(psrch_inf->ntwrk_buf_start);
2897 psrch_inf->srch_entries_start = response_data;
2898 psrch_inf->ntwrk_buf_start = (char *)pSMB;
2899 if(parms->EndofSearch)
2900 psrch_inf->endOfSearch = TRUE;
2902 psrch_inf->endOfSearch = FALSE;
2904 psrch_inf->entries_in_buffer = le16_to_cpu(parms->SearchCount);
2905 psrch_inf->index_of_last_entry +=
2906 psrch_inf->entries_in_buffer;
2907 /* cFYI(1,("fnxt2 entries in buf %d index_of_last %d",psrch_inf->entries_in_buffer,psrch_inf->index_of_last_entry)); */
2909 /* BB fixme add unlock here */
2914 /* BB On error, should we leave previous search buf (and count and
2915 last entry fields) intact or free the previous one? */
2917 /* Note: On -EAGAIN error only caller can retry on handle based calls
2918 since file handle passed in no longer valid */
2921 cifs_buf_release(pSMB);
2927 CIFSFindClose(const int xid, struct cifsTconInfo *tcon, const __u16 searchHandle)
2930 FINDCLOSE_REQ *pSMB = NULL;
2931 CLOSE_RSP *pSMBr = NULL; /* BB removeme BB */
2934 cFYI(1, ("In CIFSSMBFindClose"));
2935 rc = small_smb_init(SMB_COM_FIND_CLOSE2, 1, tcon, (void **)&pSMB);
2937 /* no sense returning error if session restarted
2938 as file handle has been closed */
2944 pSMBr = (CLOSE_RSP *)pSMB; /* BB removeme BB */
2945 pSMB->FileID = searchHandle;
2946 pSMB->ByteCount = 0;
2947 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2948 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2950 cERROR(1, ("Send error in FindClose = %d", rc));
2952 cifs_stats_inc(&tcon->num_fclose);
2953 cifs_small_buf_release(pSMB);
2955 /* Since session is dead, search handle closed on server already */
2963 CIFSGetSrvInodeNumber(const int xid, struct cifsTconInfo *tcon,
2964 const unsigned char *searchName,
2965 __u64 * inode_number,
2966 const struct nls_table *nls_codepage, int remap)
2969 TRANSACTION2_QPI_REQ *pSMB = NULL;
2970 TRANSACTION2_QPI_RSP *pSMBr = NULL;
2971 int name_len, bytes_returned;
2972 __u16 params, byte_count;
2974 cFYI(1,("In GetSrvInodeNum for %s",searchName));
2978 GetInodeNumberRetry:
2979 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2985 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2987 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
2988 PATH_MAX,nls_codepage, remap);
2989 name_len++; /* trailing null */
2991 } else { /* BB improve the check for buffer overruns BB */
2992 name_len = strnlen(searchName, PATH_MAX);
2993 name_len++; /* trailing null */
2994 strncpy(pSMB->FileName, searchName, name_len);
2997 params = 2 /* level */ + 4 /* rsrvd */ + name_len /* incl null */ ;
2998 pSMB->TotalDataCount = 0;
2999 pSMB->MaxParameterCount = cpu_to_le16(2);
3000 /* BB find exact max data count below from sess structure BB */
3001 pSMB->MaxDataCount = cpu_to_le16(4000);
3002 pSMB->MaxSetupCount = 0;
3006 pSMB->Reserved2 = 0;
3007 pSMB->ParameterOffset = cpu_to_le16(offsetof(
3008 struct smb_com_transaction2_qpi_req ,InformationLevel) - 4);
3009 pSMB->DataCount = 0;
3010 pSMB->DataOffset = 0;
3011 pSMB->SetupCount = 1;
3012 pSMB->Reserved3 = 0;
3013 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
3014 byte_count = params + 1 /* pad */ ;
3015 pSMB->TotalParameterCount = cpu_to_le16(params);
3016 pSMB->ParameterCount = pSMB->TotalParameterCount;
3017 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_INTERNAL_INFO);
3018 pSMB->Reserved4 = 0;
3019 pSMB->hdr.smb_buf_length += byte_count;
3020 pSMB->ByteCount = cpu_to_le16(byte_count);
3022 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3023 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3025 cFYI(1, ("error %d in QueryInternalInfo", rc));
3027 /* decode response */
3028 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3029 if (rc || (pSMBr->ByteCount < 2))
3030 /* BB also check enough total bytes returned */
3031 /* If rc should we check for EOPNOSUPP and
3032 disable the srvino flag? or in caller? */
3033 rc = -EIO; /* bad smb */
3035 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3036 __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
3037 struct file_internal_info * pfinfo;
3038 /* BB Do we need a cast or hash here ? */
3040 cFYI(1, ("Illegal size ret in QryIntrnlInf"));
3042 goto GetInodeNumOut;
3044 pfinfo = (struct file_internal_info *)
3045 (data_offset + (char *) &pSMBr->hdr.Protocol);
3046 *inode_number = pfinfo->UniqueId;
3050 cifs_buf_release(pSMB);
3052 goto GetInodeNumberRetry;
3057 CIFSGetDFSRefer(const int xid, struct cifsSesInfo *ses,
3058 const unsigned char *searchName,
3059 unsigned char **targetUNCs,
3060 unsigned int *number_of_UNC_in_array,
3061 const struct nls_table *nls_codepage, int remap)
3063 /* TRANS2_GET_DFS_REFERRAL */
3064 TRANSACTION2_GET_DFS_REFER_REQ *pSMB = NULL;
3065 TRANSACTION2_GET_DFS_REFER_RSP *pSMBr = NULL;
3066 struct dfs_referral_level_3 * referrals = NULL;
3072 __u16 params, byte_count;
3073 *number_of_UNC_in_array = 0;
3076 cFYI(1, ("In GetDFSRefer the path %s", searchName));
3080 rc = smb_init(SMB_COM_TRANSACTION2, 15, NULL, (void **) &pSMB,
3085 /* server pointer checked in called function,
3086 but should never be null here anyway */
3087 pSMB->hdr.Mid = GetNextMid(ses->server);
3088 pSMB->hdr.Tid = ses->ipc_tid;
3089 pSMB->hdr.Uid = ses->Suid;
3090 if (ses->capabilities & CAP_STATUS32) {
3091 pSMB->hdr.Flags2 |= SMBFLG2_ERR_STATUS;
3093 if (ses->capabilities & CAP_DFS) {
3094 pSMB->hdr.Flags2 |= SMBFLG2_DFS;
3097 if (ses->capabilities & CAP_UNICODE) {
3098 pSMB->hdr.Flags2 |= SMBFLG2_UNICODE;
3100 cifsConvertToUCS((__le16 *) pSMB->RequestFileName,
3101 searchName, PATH_MAX, nls_codepage, remap);
3102 name_len++; /* trailing null */
3104 } else { /* BB improve the check for buffer overruns BB */
3105 name_len = strnlen(searchName, PATH_MAX);
3106 name_len++; /* trailing null */
3107 strncpy(pSMB->RequestFileName, searchName, name_len);
3110 params = 2 /* level */ + name_len /*includes null */ ;
3111 pSMB->TotalDataCount = 0;
3112 pSMB->DataCount = 0;
3113 pSMB->DataOffset = 0;
3114 pSMB->MaxParameterCount = 0;
3115 pSMB->MaxDataCount = cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
3116 pSMB->MaxSetupCount = 0;
3120 pSMB->Reserved2 = 0;
3121 pSMB->ParameterOffset = cpu_to_le16(offsetof(
3122 struct smb_com_transaction2_get_dfs_refer_req, MaxReferralLevel) - 4);
3123 pSMB->SetupCount = 1;
3124 pSMB->Reserved3 = 0;
3125 pSMB->SubCommand = cpu_to_le16(TRANS2_GET_DFS_REFERRAL);
3126 byte_count = params + 3 /* pad */ ;
3127 pSMB->ParameterCount = cpu_to_le16(params);
3128 pSMB->TotalParameterCount = pSMB->ParameterCount;
3129 pSMB->MaxReferralLevel = cpu_to_le16(3);
3130 pSMB->hdr.smb_buf_length += byte_count;
3131 pSMB->ByteCount = cpu_to_le16(byte_count);
3133 rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB,
3134 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3136 cFYI(1, ("Send error in GetDFSRefer = %d", rc));
3137 } else { /* decode response */
3138 /* BB Add logic to parse referrals here */
3139 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3141 if (rc || (pSMBr->ByteCount < 17)) /* BB also check enough total bytes returned */
3142 rc = -EIO; /* bad smb */
3144 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3145 __u16 data_count = le16_to_cpu(pSMBr->t2.DataCount);
3148 ("Decoding GetDFSRefer response. BCC: %d Offset %d",
3149 pSMBr->ByteCount, data_offset));
3151 (struct dfs_referral_level_3 *)
3152 (8 /* sizeof start of data block */ +
3154 (char *) &pSMBr->hdr.Protocol);
3155 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",
3156 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)));
3157 /* BB This field is actually two bytes in from start of
3158 data block so we could do safety check that DataBlock
3159 begins at address of pSMBr->NumberOfReferrals */
3160 *number_of_UNC_in_array = le16_to_cpu(pSMBr->NumberOfReferrals);
3162 /* BB Fix below so can return more than one referral */
3163 if(*number_of_UNC_in_array > 1)
3164 *number_of_UNC_in_array = 1;
3166 /* get the length of the strings describing refs */
3168 for(i=0;i<*number_of_UNC_in_array;i++) {
3169 /* make sure that DfsPathOffset not past end */
3170 __u16 offset = le16_to_cpu(referrals->DfsPathOffset);
3171 if (offset > data_count) {
3172 /* if invalid referral, stop here and do
3173 not try to copy any more */
3174 *number_of_UNC_in_array = i;
3177 temp = ((char *)referrals) + offset;
3179 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
3180 name_len += UniStrnlen((wchar_t *)temp,data_count);
3182 name_len += strnlen(temp,data_count);
3185 /* BB add check that referral pointer does not fall off end PDU */
3188 /* BB add check for name_len bigger than bcc */
3190 kmalloc(name_len+1+ (*number_of_UNC_in_array),GFP_KERNEL);
3191 if(*targetUNCs == NULL) {
3195 /* copy the ref strings */
3197 (struct dfs_referral_level_3 *)
3198 (8 /* sizeof data hdr */ +
3200 (char *) &pSMBr->hdr.Protocol);
3202 for(i=0;i<*number_of_UNC_in_array;i++) {
3203 temp = ((char *)referrals) + le16_to_cpu(referrals->DfsPathOffset);
3204 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
3205 cifs_strfromUCS_le(*targetUNCs,
3206 (wchar_t *) temp, name_len, nls_codepage);
3208 strncpy(*targetUNCs,temp,name_len);
3210 /* BB update target_uncs pointers */
3220 cifs_buf_release(pSMB);
3228 /* Query File System Info such as free space to old servers such as Win 9x */
3230 SMBOldQFSInfo(const int xid, struct cifsTconInfo *tcon, struct kstatfs *FSData)
3232 /* level 0x01 SMB_QUERY_FILE_SYSTEM_INFO */
3233 TRANSACTION2_QFSI_REQ *pSMB = NULL;
3234 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
3235 FILE_SYSTEM_ALLOC_INFO *response_data;
3237 int bytes_returned = 0;
3238 __u16 params, byte_count;
3240 cFYI(1, ("OldQFSInfo"));
3242 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3246 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3251 params = 2; /* level */
3252 pSMB->TotalDataCount = 0;
3253 pSMB->MaxParameterCount = cpu_to_le16(2);
3254 pSMB->MaxDataCount = cpu_to_le16(1000);
3255 pSMB->MaxSetupCount = 0;
3259 pSMB->Reserved2 = 0;
3260 byte_count = params + 1 /* pad */ ;
3261 pSMB->TotalParameterCount = cpu_to_le16(params);
3262 pSMB->ParameterCount = pSMB->TotalParameterCount;
3263 pSMB->ParameterOffset = cpu_to_le16(offsetof(
3264 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
3265 pSMB->DataCount = 0;
3266 pSMB->DataOffset = 0;
3267 pSMB->SetupCount = 1;
3268 pSMB->Reserved3 = 0;
3269 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
3270 pSMB->InformationLevel = cpu_to_le16(SMB_INFO_ALLOCATION);
3271 pSMB->hdr.smb_buf_length += byte_count;
3272 pSMB->ByteCount = cpu_to_le16(byte_count);
3274 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3275 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3277 cFYI(1, ("Send error in QFSInfo = %d", rc));
3278 } else { /* decode response */
3279 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3281 if (rc || (pSMBr->ByteCount < 18))
3282 rc = -EIO; /* bad smb */
3284 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3285 cFYI(1,("qfsinf resp BCC: %d Offset %d",
3286 pSMBr->ByteCount, data_offset));
3289 (FILE_SYSTEM_ALLOC_INFO *)
3290 (((char *) &pSMBr->hdr.Protocol) + data_offset);
3292 le16_to_cpu(response_data->BytesPerSector) *
3293 le32_to_cpu(response_data->
3294 SectorsPerAllocationUnit);
3296 le32_to_cpu(response_data->TotalAllocationUnits);
3297 FSData->f_bfree = FSData->f_bavail =
3298 le32_to_cpu(response_data->FreeAllocationUnits);
3300 ("Blocks: %lld Free: %lld Block size %ld",
3301 (unsigned long long)FSData->f_blocks,
3302 (unsigned long long)FSData->f_bfree,
3306 cifs_buf_release(pSMB);
3309 goto oldQFSInfoRetry;
3315 CIFSSMBQFSInfo(const int xid, struct cifsTconInfo *tcon, struct kstatfs *FSData)
3317 /* level 0x103 SMB_QUERY_FILE_SYSTEM_INFO */
3318 TRANSACTION2_QFSI_REQ *pSMB = NULL;
3319 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
3320 FILE_SYSTEM_INFO *response_data;
3322 int bytes_returned = 0;
3323 __u16 params, byte_count;
3325 cFYI(1, ("In QFSInfo"));
3327 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3332 params = 2; /* level */
3333 pSMB->TotalDataCount = 0;
3334 pSMB->MaxParameterCount = cpu_to_le16(2);
3335 pSMB->MaxDataCount = cpu_to_le16(1000);
3336 pSMB->MaxSetupCount = 0;
3340 pSMB->Reserved2 = 0;
3341 byte_count = params + 1 /* pad */ ;
3342 pSMB->TotalParameterCount = cpu_to_le16(params);
3343 pSMB->ParameterCount = pSMB->TotalParameterCount;
3344 pSMB->ParameterOffset = cpu_to_le16(offsetof(
3345 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
3346 pSMB->DataCount = 0;
3347 pSMB->DataOffset = 0;
3348 pSMB->SetupCount = 1;
3349 pSMB->Reserved3 = 0;
3350 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
3351 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_SIZE_INFO);
3352 pSMB->hdr.smb_buf_length += byte_count;
3353 pSMB->ByteCount = cpu_to_le16(byte_count);
3355 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3356 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3358 cFYI(1, ("Send error in QFSInfo = %d", rc));
3359 } else { /* decode response */
3360 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3362 if (rc || (pSMBr->ByteCount < 24))
3363 rc = -EIO; /* bad smb */
3365 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3369 *) (((char *) &pSMBr->hdr.Protocol) +
3372 le32_to_cpu(response_data->BytesPerSector) *
3373 le32_to_cpu(response_data->
3374 SectorsPerAllocationUnit);
3376 le64_to_cpu(response_data->TotalAllocationUnits);
3377 FSData->f_bfree = FSData->f_bavail =
3378 le64_to_cpu(response_data->FreeAllocationUnits);
3380 ("Blocks: %lld Free: %lld Block size %ld",
3381 (unsigned long long)FSData->f_blocks,
3382 (unsigned long long)FSData->f_bfree,
3386 cifs_buf_release(pSMB);
3395 CIFSSMBQFSAttributeInfo(const int xid, struct cifsTconInfo *tcon)
3397 /* level 0x105 SMB_QUERY_FILE_SYSTEM_INFO */
3398 TRANSACTION2_QFSI_REQ *pSMB = NULL;
3399 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
3400 FILE_SYSTEM_ATTRIBUTE_INFO *response_data;
3402 int bytes_returned = 0;
3403 __u16 params, byte_count;
3405 cFYI(1, ("In QFSAttributeInfo"));
3407 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3412 params = 2; /* level */
3413 pSMB->TotalDataCount = 0;
3414 pSMB->MaxParameterCount = cpu_to_le16(2);
3415 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
3416 pSMB->MaxSetupCount = 0;
3420 pSMB->Reserved2 = 0;
3421 byte_count = params + 1 /* pad */ ;
3422 pSMB->TotalParameterCount = cpu_to_le16(params);
3423 pSMB->ParameterCount = pSMB->TotalParameterCount;
3424 pSMB->ParameterOffset = cpu_to_le16(offsetof(
3425 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
3426 pSMB->DataCount = 0;
3427 pSMB->DataOffset = 0;
3428 pSMB->SetupCount = 1;
3429 pSMB->Reserved3 = 0;
3430 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
3431 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_ATTRIBUTE_INFO);
3432 pSMB->hdr.smb_buf_length += byte_count;
3433 pSMB->ByteCount = cpu_to_le16(byte_count);
3435 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3436 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3438 cERROR(1, ("Send error in QFSAttributeInfo = %d", rc));
3439 } else { /* decode response */
3440 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3442 if (rc || (pSMBr->ByteCount < 13)) { /* BB also check enough bytes returned */
3443 rc = -EIO; /* bad smb */
3445 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3447 (FILE_SYSTEM_ATTRIBUTE_INFO
3448 *) (((char *) &pSMBr->hdr.Protocol) +
3450 memcpy(&tcon->fsAttrInfo, response_data,
3451 sizeof (FILE_SYSTEM_ATTRIBUTE_INFO));
3454 cifs_buf_release(pSMB);
3457 goto QFSAttributeRetry;
3463 CIFSSMBQFSDeviceInfo(const int xid, struct cifsTconInfo *tcon)
3465 /* level 0x104 SMB_QUERY_FILE_SYSTEM_INFO */
3466 TRANSACTION2_QFSI_REQ *pSMB = NULL;
3467 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
3468 FILE_SYSTEM_DEVICE_INFO *response_data;
3470 int bytes_returned = 0;
3471 __u16 params, byte_count;
3473 cFYI(1, ("In QFSDeviceInfo"));
3475 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3480 params = 2; /* level */
3481 pSMB->TotalDataCount = 0;
3482 pSMB->MaxParameterCount = cpu_to_le16(2);
3483 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
3484 pSMB->MaxSetupCount = 0;
3488 pSMB->Reserved2 = 0;
3489 byte_count = params + 1 /* pad */ ;
3490 pSMB->TotalParameterCount = cpu_to_le16(params);
3491 pSMB->ParameterCount = pSMB->TotalParameterCount;
3492 pSMB->ParameterOffset = cpu_to_le16(offsetof(
3493 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
3495 pSMB->DataCount = 0;
3496 pSMB->DataOffset = 0;
3497 pSMB->SetupCount = 1;
3498 pSMB->Reserved3 = 0;
3499 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
3500 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_DEVICE_INFO);
3501 pSMB->hdr.smb_buf_length += byte_count;
3502 pSMB->ByteCount = cpu_to_le16(byte_count);
3504 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3505 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3507 cFYI(1, ("Send error in QFSDeviceInfo = %d", rc));
3508 } else { /* decode response */
3509 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3511 if (rc || (pSMBr->ByteCount < sizeof (FILE_SYSTEM_DEVICE_INFO)))
3512 rc = -EIO; /* bad smb */
3514 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3516 (FILE_SYSTEM_DEVICE_INFO *)
3517 (((char *) &pSMBr->hdr.Protocol) +
3519 memcpy(&tcon->fsDevInfo, response_data,
3520 sizeof (FILE_SYSTEM_DEVICE_INFO));
3523 cifs_buf_release(pSMB);
3526 goto QFSDeviceRetry;
3532 CIFSSMBQFSUnixInfo(const int xid, struct cifsTconInfo *tcon)
3534 /* level 0x200 SMB_QUERY_CIFS_UNIX_INFO */
3535 TRANSACTION2_QFSI_REQ *pSMB = NULL;
3536 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
3537 FILE_SYSTEM_UNIX_INFO *response_data;
3539 int bytes_returned = 0;
3540 __u16 params, byte_count;
3542 cFYI(1, ("In QFSUnixInfo"));
3544 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3549 params = 2; /* level */
3550 pSMB->TotalDataCount = 0;
3551 pSMB->DataCount = 0;
3552 pSMB->DataOffset = 0;
3553 pSMB->MaxParameterCount = cpu_to_le16(2);
3554 pSMB->MaxDataCount = cpu_to_le16(100); /* BB find exact max SMB PDU from sess structure BB */
3555 pSMB->MaxSetupCount = 0;
3559 pSMB->Reserved2 = 0;
3560 byte_count = params + 1 /* pad */ ;
3561 pSMB->ParameterCount = cpu_to_le16(params);
3562 pSMB->TotalParameterCount = pSMB->ParameterCount;
3563 pSMB->ParameterOffset = cpu_to_le16(offsetof(struct
3564 smb_com_transaction2_qfsi_req, InformationLevel) - 4);
3565 pSMB->SetupCount = 1;
3566 pSMB->Reserved3 = 0;
3567 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
3568 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_CIFS_UNIX_INFO);
3569 pSMB->hdr.smb_buf_length += byte_count;
3570 pSMB->ByteCount = cpu_to_le16(byte_count);
3572 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3573 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3575 cERROR(1, ("Send error in QFSUnixInfo = %d", rc));
3576 } else { /* decode response */
3577 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3579 if (rc || (pSMBr->ByteCount < 13)) {
3580 rc = -EIO; /* bad smb */
3582 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3584 (FILE_SYSTEM_UNIX_INFO
3585 *) (((char *) &pSMBr->hdr.Protocol) +
3587 memcpy(&tcon->fsUnixInfo, response_data,
3588 sizeof (FILE_SYSTEM_UNIX_INFO));
3591 cifs_buf_release(pSMB);
3601 CIFSSMBSetFSUnixInfo(const int xid, struct cifsTconInfo *tcon, __u64 cap)
3603 /* level 0x200 SMB_SET_CIFS_UNIX_INFO */
3604 TRANSACTION2_SETFSI_REQ *pSMB = NULL;
3605 TRANSACTION2_SETFSI_RSP *pSMBr = NULL;
3607 int bytes_returned = 0;
3608 __u16 params, param_offset, offset, byte_count;
3610 cFYI(1, ("In SETFSUnixInfo"));
3612 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3617 params = 4; /* 2 bytes zero followed by info level. */
3618 pSMB->MaxSetupCount = 0;
3622 pSMB->Reserved2 = 0;
3623 param_offset = offsetof(struct smb_com_transaction2_setfsi_req, FileNum) - 4;
3624 offset = param_offset + params;
3626 pSMB->MaxParameterCount = cpu_to_le16(4);
3627 pSMB->MaxDataCount = cpu_to_le16(100); /* BB find exact max SMB PDU from sess structure BB */
3628 pSMB->SetupCount = 1;
3629 pSMB->Reserved3 = 0;
3630 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FS_INFORMATION);
3631 byte_count = 1 /* pad */ + params + 12;
3633 pSMB->DataCount = cpu_to_le16(12);
3634 pSMB->ParameterCount = cpu_to_le16(params);
3635 pSMB->TotalDataCount = pSMB->DataCount;
3636 pSMB->TotalParameterCount = pSMB->ParameterCount;
3637 pSMB->ParameterOffset = cpu_to_le16(param_offset);
3638 pSMB->DataOffset = cpu_to_le16(offset);
3642 pSMB->InformationLevel = cpu_to_le16(SMB_SET_CIFS_UNIX_INFO);
3645 pSMB->ClientUnixMajor = cpu_to_le16(CIFS_UNIX_MAJOR_VERSION);
3646 pSMB->ClientUnixMinor = cpu_to_le16(CIFS_UNIX_MINOR_VERSION);
3647 pSMB->ClientUnixCap = cpu_to_le64(cap);
3649 pSMB->hdr.smb_buf_length += byte_count;
3650 pSMB->ByteCount = cpu_to_le16(byte_count);
3652 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3653 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3655 cERROR(1, ("Send error in SETFSUnixInfo = %d", rc));
3656 } else { /* decode response */
3657 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3659 rc = -EIO; /* bad smb */
3662 cifs_buf_release(pSMB);
3665 goto SETFSUnixRetry;
3673 CIFSSMBQFSPosixInfo(const int xid, struct cifsTconInfo *tcon,
3674 struct kstatfs *FSData)
3676 /* level 0x201 SMB_QUERY_CIFS_POSIX_INFO */
3677 TRANSACTION2_QFSI_REQ *pSMB = NULL;
3678 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
3679 FILE_SYSTEM_POSIX_INFO *response_data;
3681 int bytes_returned = 0;
3682 __u16 params, byte_count;
3684 cFYI(1, ("In QFSPosixInfo"));
3686 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3691 params = 2; /* level */
3692 pSMB->TotalDataCount = 0;
3693 pSMB->DataCount = 0;
3694 pSMB->DataOffset = 0;
3695 pSMB->MaxParameterCount = cpu_to_le16(2);
3696 pSMB->MaxDataCount = cpu_to_le16(100); /* BB find exact max SMB PDU from sess structure BB */
3697 pSMB->MaxSetupCount = 0;
3701 pSMB->Reserved2 = 0;
3702 byte_count = params + 1 /* pad */ ;
3703 pSMB->ParameterCount = cpu_to_le16(params);
3704 pSMB->TotalParameterCount = pSMB->ParameterCount;
3705 pSMB->ParameterOffset = cpu_to_le16(offsetof(struct
3706 smb_com_transaction2_qfsi_req, InformationLevel) - 4);
3707 pSMB->SetupCount = 1;
3708 pSMB->Reserved3 = 0;
3709 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
3710 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_POSIX_FS_INFO);
3711 pSMB->hdr.smb_buf_length += byte_count;
3712 pSMB->ByteCount = cpu_to_le16(byte_count);
3714 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3715 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3717 cFYI(1, ("Send error in QFSUnixInfo = %d", rc));
3718 } else { /* decode response */
3719 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3721 if (rc || (pSMBr->ByteCount < 13)) {
3722 rc = -EIO; /* bad smb */
3724 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3726 (FILE_SYSTEM_POSIX_INFO
3727 *) (((char *) &pSMBr->hdr.Protocol) +
3730 le32_to_cpu(response_data->BlockSize);
3732 le64_to_cpu(response_data->TotalBlocks);
3734 le64_to_cpu(response_data->BlocksAvail);
3735 if(response_data->UserBlocksAvail == cpu_to_le64(-1)) {
3736 FSData->f_bavail = FSData->f_bfree;
3739 le64_to_cpu(response_data->UserBlocksAvail);
3741 if(response_data->TotalFileNodes != cpu_to_le64(-1))
3743 le64_to_cpu(response_data->TotalFileNodes);
3744 if(response_data->FreeFileNodes != cpu_to_le64(-1))
3746 le64_to_cpu(response_data->FreeFileNodes);
3749 cifs_buf_release(pSMB);
3758 /* We can not use write of zero bytes trick to
3759 set file size due to need for large file support. Also note that
3760 this SetPathInfo is preferred to SetFileInfo based method in next
3761 routine which is only needed to work around a sharing violation bug
3762 in Samba which this routine can run into */
3765 CIFSSMBSetEOF(const int xid, struct cifsTconInfo *tcon, const char *fileName,
3766 __u64 size, int SetAllocation,
3767 const struct nls_table *nls_codepage, int remap)
3769 struct smb_com_transaction2_spi_req *pSMB = NULL;
3770 struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
3771 struct file_end_of_file_info *parm_data;
3774 int bytes_returned = 0;
3775 __u16 params, byte_count, data_count, param_offset, offset;
3777 cFYI(1, ("In SetEOF"));
3779 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3784 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3786 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
3787 PATH_MAX, nls_codepage, remap);
3788 name_len++; /* trailing null */
3790 } else { /* BB improve the check for buffer overruns BB */
3791 name_len = strnlen(fileName, PATH_MAX);
3792 name_len++; /* trailing null */
3793 strncpy(pSMB->FileName, fileName, name_len);
3795 params = 6 + name_len;
3796 data_count = sizeof (struct file_end_of_file_info);
3797 pSMB->MaxParameterCount = cpu_to_le16(2);
3798 pSMB->MaxDataCount = cpu_to_le16(4100);
3799 pSMB->MaxSetupCount = 0;
3803 pSMB->Reserved2 = 0;
3804 param_offset = offsetof(struct smb_com_transaction2_spi_req,
3805 InformationLevel) - 4;
3806 offset = param_offset + params;
3808 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
3809 pSMB->InformationLevel =
3810 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2);
3812 pSMB->InformationLevel =
3813 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO);
3814 } else /* Set File Size */ {
3815 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
3816 pSMB->InformationLevel =
3817 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO2);
3819 pSMB->InformationLevel =
3820 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO);
3824 (struct file_end_of_file_info *) (((char *) &pSMB->hdr.Protocol) +
3826 pSMB->ParameterOffset = cpu_to_le16(param_offset);
3827 pSMB->DataOffset = cpu_to_le16(offset);
3828 pSMB->SetupCount = 1;
3829 pSMB->Reserved3 = 0;
3830 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
3831 byte_count = 3 /* pad */ + params + data_count;
3832 pSMB->DataCount = cpu_to_le16(data_count);
3833 pSMB->TotalDataCount = pSMB->DataCount;
3834 pSMB->ParameterCount = cpu_to_le16(params);
3835 pSMB->TotalParameterCount = pSMB->ParameterCount;
3836 pSMB->Reserved4 = 0;
3837 pSMB->hdr.smb_buf_length += byte_count;
3838 parm_data->FileSize = cpu_to_le64(size);
3839 pSMB->ByteCount = cpu_to_le16(byte_count);
3840 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3841 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3843 cFYI(1, ("SetPathInfo (file size) returned %d", rc));
3846 cifs_buf_release(pSMB);
3855 CIFSSMBSetFileSize(const int xid, struct cifsTconInfo *tcon, __u64 size,
3856 __u16 fid, __u32 pid_of_opener, int SetAllocation)
3858 struct smb_com_transaction2_sfi_req *pSMB = NULL;
3859 struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
3861 struct file_end_of_file_info *parm_data;
3863 int bytes_returned = 0;
3864 __u16 params, param_offset, offset, byte_count, count;
3866 cFYI(1, ("SetFileSize (via SetFileInfo) %lld",
3868 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
3873 pSMBr = (struct smb_com_transaction2_sfi_rsp *)pSMB;
3875 pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
3876 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));
3879 pSMB->MaxSetupCount = 0;
3883 pSMB->Reserved2 = 0;
3884 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
3885 offset = param_offset + params;
3887 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
3889 count = sizeof(struct file_end_of_file_info);
3890 pSMB->MaxParameterCount = cpu_to_le16(2);
3891 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB PDU from sess */
3892 pSMB->SetupCount = 1;
3893 pSMB->Reserved3 = 0;
3894 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
3895 byte_count = 3 /* pad */ + params + count;
3896 pSMB->DataCount = cpu_to_le16(count);
3897 pSMB->ParameterCount = cpu_to_le16(params);
3898 pSMB->TotalDataCount = pSMB->DataCount;
3899 pSMB->TotalParameterCount = pSMB->ParameterCount;
3900 pSMB->ParameterOffset = cpu_to_le16(param_offset);
3902 (struct file_end_of_file_info *) (((char *) &pSMB->hdr.Protocol) +
3904 pSMB->DataOffset = cpu_to_le16(offset);
3905 parm_data->FileSize = cpu_to_le64(size);
3908 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
3909 pSMB->InformationLevel =
3910 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2);
3912 pSMB->InformationLevel =
3913 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO);
3914 } else /* Set File Size */ {
3915 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
3916 pSMB->InformationLevel =
3917 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO2);
3919 pSMB->InformationLevel =
3920 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO);
3922 pSMB->Reserved4 = 0;
3923 pSMB->hdr.smb_buf_length += byte_count;
3924 pSMB->ByteCount = cpu_to_le16(byte_count);
3925 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3926 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3929 ("Send error in SetFileInfo (SetFileSize) = %d",
3934 cifs_small_buf_release(pSMB);
3936 /* Note: On -EAGAIN error only caller can retry on handle based calls
3937 since file handle passed in no longer valid */
3942 /* Some legacy servers such as NT4 require that the file times be set on
3943 an open handle, rather than by pathname - this is awkward due to
3944 potential access conflicts on the open, but it is unavoidable for these
3945 old servers since the only other choice is to go from 100 nanosecond DCE
3946 time and resort to the original setpathinfo level which takes the ancient
3947 DOS time format with 2 second granularity */
3949 CIFSSMBSetFileTimes(const int xid, struct cifsTconInfo *tcon, const FILE_BASIC_INFO * data,
3952 struct smb_com_transaction2_sfi_req *pSMB = NULL;
3953 struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
3956 int bytes_returned = 0;
3957 __u16 params, param_offset, offset, byte_count, count;
3959 cFYI(1, ("Set Times (via SetFileInfo)"));
3960 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
3965 pSMBr = (struct smb_com_transaction2_sfi_rsp *)pSMB;
3967 /* At this point there is no need to override the current pid
3968 with the pid of the opener, but that could change if we someday
3969 use an existing handle (rather than opening one on the fly) */
3970 /* pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
3971 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));*/
3974 pSMB->MaxSetupCount = 0;
3978 pSMB->Reserved2 = 0;
3979 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
3980 offset = param_offset + params;
3982 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
3984 count = sizeof (FILE_BASIC_INFO);
3985 pSMB->MaxParameterCount = cpu_to_le16(2);
3986 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB PDU from sess */
3987 pSMB->SetupCount = 1;
3988 pSMB->Reserved3 = 0;
3989 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
3990 byte_count = 3 /* pad */ + params + count;
3991 pSMB->DataCount = cpu_to_le16(count);
3992 pSMB->ParameterCount = cpu_to_le16(params);
3993 pSMB->TotalDataCount = pSMB->DataCount;
3994 pSMB->TotalParameterCount = pSMB->ParameterCount;
3995 pSMB->ParameterOffset = cpu_to_le16(param_offset);
3996 pSMB->DataOffset = cpu_to_le16(offset);
3998 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
3999 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO2);
4001 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO);
4002 pSMB->Reserved4 = 0;
4003 pSMB->hdr.smb_buf_length += byte_count;
4004 pSMB->ByteCount = cpu_to_le16(byte_count);
4005 memcpy(data_offset,data,sizeof(FILE_BASIC_INFO));
4006 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4007 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4009 cFYI(1,("Send error in Set Time (SetFileInfo) = %d",rc));
4012 cifs_small_buf_release(pSMB);
4014 /* Note: On -EAGAIN error only caller can retry on handle based calls
4015 since file handle passed in no longer valid */
4022 CIFSSMBSetTimes(const int xid, struct cifsTconInfo *tcon, const char *fileName,
4023 const FILE_BASIC_INFO * data,
4024 const struct nls_table *nls_codepage, int remap)
4026 TRANSACTION2_SPI_REQ *pSMB = NULL;
4027 TRANSACTION2_SPI_RSP *pSMBr = NULL;
4030 int bytes_returned = 0;
4032 __u16 params, param_offset, offset, byte_count, count;
4034 cFYI(1, ("In SetTimes"));
4037 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4042 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4044 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
4045 PATH_MAX, nls_codepage, remap);
4046 name_len++; /* trailing null */
4048 } else { /* BB improve the check for buffer overruns BB */
4049 name_len = strnlen(fileName, PATH_MAX);
4050 name_len++; /* trailing null */
4051 strncpy(pSMB->FileName, fileName, name_len);
4054 params = 6 + name_len;
4055 count = sizeof (FILE_BASIC_INFO);
4056 pSMB->MaxParameterCount = cpu_to_le16(2);
4057 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
4058 pSMB->MaxSetupCount = 0;
4062 pSMB->Reserved2 = 0;
4063 param_offset = offsetof(struct smb_com_transaction2_spi_req,
4064 InformationLevel) - 4;
4065 offset = param_offset + params;
4066 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
4067 pSMB->ParameterOffset = cpu_to_le16(param_offset);
4068 pSMB->DataOffset = cpu_to_le16(offset);
4069 pSMB->SetupCount = 1;
4070 pSMB->Reserved3 = 0;
4071 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
4072 byte_count = 3 /* pad */ + params + count;
4074 pSMB->DataCount = cpu_to_le16(count);
4075 pSMB->ParameterCount = cpu_to_le16(params);
4076 pSMB->TotalDataCount = pSMB->DataCount;
4077 pSMB->TotalParameterCount = pSMB->ParameterCount;
4078 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
4079 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO2);
4081 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO);
4082 pSMB->Reserved4 = 0;
4083 pSMB->hdr.smb_buf_length += byte_count;
4084 memcpy(data_offset, data, sizeof (FILE_BASIC_INFO));
4085 pSMB->ByteCount = cpu_to_le16(byte_count);
4086 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4087 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4089 cFYI(1, ("SetPathInfo (times) returned %d", rc));
4092 cifs_buf_release(pSMB);
4100 /* Can not be used to set time stamps yet (due to old DOS time format) */
4101 /* Can be used to set attributes */
4102 #if 0 /* Possibly not needed - since it turns out that strangely NT4 has a bug
4103 handling it anyway and NT4 was what we thought it would be needed for
4104 Do not delete it until we prove whether needed for Win9x though */
4106 CIFSSMBSetAttrLegacy(int xid, struct cifsTconInfo *tcon, char *fileName,
4107 __u16 dos_attrs, const struct nls_table *nls_codepage)
4109 SETATTR_REQ *pSMB = NULL;
4110 SETATTR_RSP *pSMBr = NULL;
4115 cFYI(1, ("In SetAttrLegacy"));
4118 rc = smb_init(SMB_COM_SETATTR, 8, tcon, (void **) &pSMB,
4123 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4125 ConvertToUCS((__le16 *) pSMB->fileName, fileName,
4126 PATH_MAX, nls_codepage);
4127 name_len++; /* trailing null */
4129 } else { /* BB improve the check for buffer overruns BB */
4130 name_len = strnlen(fileName, PATH_MAX);
4131 name_len++; /* trailing null */
4132 strncpy(pSMB->fileName, fileName, name_len);
4134 pSMB->attr = cpu_to_le16(dos_attrs);
4135 pSMB->BufferFormat = 0x04;
4136 pSMB->hdr.smb_buf_length += name_len + 1;
4137 pSMB->ByteCount = cpu_to_le16(name_len + 1);
4138 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4139 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4141 cFYI(1, ("Error in LegacySetAttr = %d", rc));
4144 cifs_buf_release(pSMB);
4147 goto SetAttrLgcyRetry;
4151 #endif /* temporarily unneeded SetAttr legacy function */
4154 CIFSSMBUnixSetPerms(const int xid, struct cifsTconInfo *tcon,
4155 char *fileName, __u64 mode, __u64 uid, __u64 gid,
4156 dev_t device, const struct nls_table *nls_codepage,
4159 TRANSACTION2_SPI_REQ *pSMB = NULL;
4160 TRANSACTION2_SPI_RSP *pSMBr = NULL;
4163 int bytes_returned = 0;
4164 FILE_UNIX_BASIC_INFO *data_offset;
4165 __u16 params, param_offset, offset, count, byte_count;
4167 cFYI(1, ("In SetUID/GID/Mode"));
4169 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4174 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4176 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
4177 PATH_MAX, nls_codepage, remap);
4178 name_len++; /* trailing null */
4180 } else { /* BB improve the check for buffer overruns BB */
4181 name_len = strnlen(fileName, PATH_MAX);
4182 name_len++; /* trailing null */
4183 strncpy(pSMB->FileName, fileName, name_len);
4186 params = 6 + name_len;
4187 count = sizeof (FILE_UNIX_BASIC_INFO);
4188 pSMB->MaxParameterCount = cpu_to_le16(2);
4189 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
4190 pSMB->MaxSetupCount = 0;
4194 pSMB->Reserved2 = 0;
4195 param_offset = offsetof(struct smb_com_transaction2_spi_req,
4196 InformationLevel) - 4;
4197 offset = param_offset + params;
4199 (FILE_UNIX_BASIC_INFO *) ((char *) &pSMB->hdr.Protocol +
4201 memset(data_offset, 0, count);
4202 pSMB->DataOffset = cpu_to_le16(offset);
4203 pSMB->ParameterOffset = cpu_to_le16(param_offset);
4204 pSMB->SetupCount = 1;
4205 pSMB->Reserved3 = 0;
4206 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
4207 byte_count = 3 /* pad */ + params + count;
4208 pSMB->ParameterCount = cpu_to_le16(params);
4209 pSMB->DataCount = cpu_to_le16(count);
4210 pSMB->TotalParameterCount = pSMB->ParameterCount;
4211 pSMB->TotalDataCount = pSMB->DataCount;
4212 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_BASIC);
4213 pSMB->Reserved4 = 0;
4214 pSMB->hdr.smb_buf_length += byte_count;
4215 data_offset->Uid = cpu_to_le64(uid);
4216 data_offset->Gid = cpu_to_le64(gid);
4217 /* better to leave device as zero when it is */
4218 data_offset->DevMajor = cpu_to_le64(MAJOR(device));
4219 data_offset->DevMinor = cpu_to_le64(MINOR(device));
4220 data_offset->Permissions = cpu_to_le64(mode);
4223 data_offset->Type = cpu_to_le32(UNIX_FILE);
4224 else if(S_ISDIR(mode))
4225 data_offset->Type = cpu_to_le32(UNIX_DIR);
4226 else if(S_ISLNK(mode))
4227 data_offset->Type = cpu_to_le32(UNIX_SYMLINK);
4228 else if(S_ISCHR(mode))
4229 data_offset->Type = cpu_to_le32(UNIX_CHARDEV);
4230 else if(S_ISBLK(mode))
4231 data_offset->Type = cpu_to_le32(UNIX_BLOCKDEV);
4232 else if(S_ISFIFO(mode))
4233 data_offset->Type = cpu_to_le32(UNIX_FIFO);
4234 else if(S_ISSOCK(mode))
4235 data_offset->Type = cpu_to_le32(UNIX_SOCKET);
4238 pSMB->ByteCount = cpu_to_le16(byte_count);
4239 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4240 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4242 cFYI(1, ("SetPathInfo (perms) returned %d", rc));
4246 cifs_buf_release(pSMB);
4252 int CIFSSMBNotify(const int xid, struct cifsTconInfo *tcon,
4253 const int notify_subdirs, const __u16 netfid,
4254 __u32 filter, struct file * pfile, int multishot,
4255 const struct nls_table *nls_codepage)
4258 struct smb_com_transaction_change_notify_req * pSMB = NULL;
4259 struct smb_com_transaction_change_notify_rsp * pSMBr = NULL;
4260 struct dir_notify_req *dnotify_req;
4263 cFYI(1, ("In CIFSSMBNotify for file handle %d",(int)netfid));
4264 rc = smb_init(SMB_COM_NT_TRANSACT, 23, tcon, (void **) &pSMB,
4269 pSMB->TotalParameterCount = 0 ;
4270 pSMB->TotalDataCount = 0;
4271 pSMB->MaxParameterCount = cpu_to_le32(2);
4272 /* BB find exact data count max from sess structure BB */
4273 pSMB->MaxDataCount = 0; /* same in little endian or be */
4274 pSMB->MaxSetupCount = 4;
4276 pSMB->ParameterOffset = 0;
4277 pSMB->DataCount = 0;
4278 pSMB->DataOffset = 0;
4279 pSMB->SetupCount = 4; /* single byte does not need le conversion */
4280 pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_NOTIFY_CHANGE);
4281 pSMB->ParameterCount = pSMB->TotalParameterCount;
4283 pSMB->WatchTree = 1; /* one byte - no le conversion needed */
4284 pSMB->Reserved2 = 0;
4285 pSMB->CompletionFilter = cpu_to_le32(filter);
4286 pSMB->Fid = netfid; /* file handle always le */
4287 pSMB->ByteCount = 0;
4289 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4290 (struct smb_hdr *) pSMBr, &bytes_returned, -1);
4292 cFYI(1, ("Error in Notify = %d", rc));
4294 /* Add file to outstanding requests */
4295 /* BB change to kmem cache alloc */
4296 dnotify_req = (struct dir_notify_req *) kmalloc(
4297 sizeof(struct dir_notify_req),
4300 dnotify_req->Pid = pSMB->hdr.Pid;
4301 dnotify_req->PidHigh = pSMB->hdr.PidHigh;
4302 dnotify_req->Mid = pSMB->hdr.Mid;
4303 dnotify_req->Tid = pSMB->hdr.Tid;
4304 dnotify_req->Uid = pSMB->hdr.Uid;
4305 dnotify_req->netfid = netfid;
4306 dnotify_req->pfile = pfile;
4307 dnotify_req->filter = filter;
4308 dnotify_req->multishot = multishot;
4309 spin_lock(&GlobalMid_Lock);
4310 list_add_tail(&dnotify_req->lhead,
4311 &GlobalDnotifyReqList);
4312 spin_unlock(&GlobalMid_Lock);
4316 cifs_buf_release(pSMB);
4319 #ifdef CONFIG_CIFS_XATTR
4321 CIFSSMBQAllEAs(const int xid, struct cifsTconInfo *tcon,
4322 const unsigned char *searchName,
4323 char * EAData, size_t buf_size,
4324 const struct nls_table *nls_codepage, int remap)
4326 /* BB assumes one setup word */
4327 TRANSACTION2_QPI_REQ *pSMB = NULL;
4328 TRANSACTION2_QPI_RSP *pSMBr = NULL;
4332 struct fea * temp_fea;
4334 __u16 params, byte_count;
4336 cFYI(1, ("In Query All EAs path %s", searchName));
4338 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4343 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4345 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
4346 PATH_MAX, nls_codepage, remap);
4347 name_len++; /* trailing null */
4349 } else { /* BB improve the check for buffer overruns BB */
4350 name_len = strnlen(searchName, PATH_MAX);
4351 name_len++; /* trailing null */
4352 strncpy(pSMB->FileName, searchName, name_len);
4355 params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */ ;
4356 pSMB->TotalDataCount = 0;
4357 pSMB->MaxParameterCount = cpu_to_le16(2);
4358 pSMB->MaxDataCount = cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
4359 pSMB->MaxSetupCount = 0;
4363 pSMB->Reserved2 = 0;
4364 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4365 struct smb_com_transaction2_qpi_req ,InformationLevel) - 4);
4366 pSMB->DataCount = 0;
4367 pSMB->DataOffset = 0;
4368 pSMB->SetupCount = 1;
4369 pSMB->Reserved3 = 0;
4370 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
4371 byte_count = params + 1 /* pad */ ;
4372 pSMB->TotalParameterCount = cpu_to_le16(params);
4373 pSMB->ParameterCount = pSMB->TotalParameterCount;
4374 pSMB->InformationLevel = cpu_to_le16(SMB_INFO_QUERY_ALL_EAS);
4375 pSMB->Reserved4 = 0;
4376 pSMB->hdr.smb_buf_length += byte_count;
4377 pSMB->ByteCount = cpu_to_le16(byte_count);
4379 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4380 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4382 cFYI(1, ("Send error in QueryAllEAs = %d", rc));
4383 } else { /* decode response */
4384 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4386 /* BB also check enough total bytes returned */
4387 /* BB we need to improve the validity checking
4388 of these trans2 responses */
4389 if (rc || (pSMBr->ByteCount < 4))
4390 rc = -EIO; /* bad smb */
4391 /* else if (pFindData){
4392 memcpy((char *) pFindData,
4393 (char *) &pSMBr->hdr.Protocol +
4396 /* check that length of list is not more than bcc */
4397 /* check that each entry does not go beyond length
4399 /* check that each element of each entry does not
4400 go beyond end of list */
4401 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4402 struct fealist * ea_response_data;
4404 /* validate_trans2_offsets() */
4405 /* BB to check if(start of smb + data_offset > &bcc+ bcc)*/
4406 ea_response_data = (struct fealist *)
4407 (((char *) &pSMBr->hdr.Protocol) +
4409 name_len = le32_to_cpu(ea_response_data->list_len);
4410 cFYI(1,("ea length %d", name_len));
4412 /* returned EA size zeroed at top of function */
4413 cFYI(1,("empty EA list returned from server"));
4415 /* account for ea list len */
4417 temp_fea = ea_response_data->list;
4418 temp_ptr = (char *)temp_fea;
4419 while(name_len > 0) {
4423 rc += temp_fea->name_len;
4424 /* account for prefix user. and trailing null */
4426 if(rc<(int)buf_size) {
4427 memcpy(EAData,"user.",5);
4429 memcpy(EAData,temp_ptr,temp_fea->name_len);
4430 EAData+=temp_fea->name_len;
4431 /* null terminate name */
4433 EAData = EAData + 1;
4434 } else if(buf_size == 0) {
4435 /* skip copy - calc size only */
4437 /* stop before overrun buffer */
4441 name_len -= temp_fea->name_len;
4442 temp_ptr += temp_fea->name_len;
4443 /* account for trailing null */
4446 value_len = le16_to_cpu(temp_fea->value_len);
4447 name_len -= value_len;
4448 temp_ptr += value_len;
4449 /* BB check that temp_ptr is still within smb BB*/
4450 /* no trailing null to account for in value len */
4451 /* go on to next EA */
4452 temp_fea = (struct fea *)temp_ptr;
4458 cifs_buf_release(pSMB);
4465 ssize_t CIFSSMBQueryEA(const int xid,struct cifsTconInfo * tcon,
4466 const unsigned char * searchName,const unsigned char * ea_name,
4467 unsigned char * ea_value, size_t buf_size,
4468 const struct nls_table *nls_codepage, int remap)
4470 TRANSACTION2_QPI_REQ *pSMB = NULL;
4471 TRANSACTION2_QPI_RSP *pSMBr = NULL;
4475 struct fea * temp_fea;
4477 __u16 params, byte_count;
4479 cFYI(1, ("In Query EA path %s", searchName));
4481 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4486 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4488 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
4489 PATH_MAX, nls_codepage, remap);
4490 name_len++; /* trailing null */
4492 } else { /* BB improve the check for buffer overruns BB */
4493 name_len = strnlen(searchName, PATH_MAX);
4494 name_len++; /* trailing null */
4495 strncpy(pSMB->FileName, searchName, name_len);
4498 params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */ ;
4499 pSMB->TotalDataCount = 0;
4500 pSMB->MaxParameterCount = cpu_to_le16(2);
4501 pSMB->MaxDataCount = cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
4502 pSMB->MaxSetupCount = 0;
4506 pSMB->Reserved2 = 0;
4507 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4508 struct smb_com_transaction2_qpi_req ,InformationLevel) - 4);
4509 pSMB->DataCount = 0;
4510 pSMB->DataOffset = 0;
4511 pSMB->SetupCount = 1;
4512 pSMB->Reserved3 = 0;
4513 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
4514 byte_count = params + 1 /* pad */ ;
4515 pSMB->TotalParameterCount = cpu_to_le16(params);
4516 pSMB->ParameterCount = pSMB->TotalParameterCount;
4517 pSMB->InformationLevel = cpu_to_le16(SMB_INFO_QUERY_ALL_EAS);
4518 pSMB->Reserved4 = 0;
4519 pSMB->hdr.smb_buf_length += byte_count;
4520 pSMB->ByteCount = cpu_to_le16(byte_count);
4522 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4523 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4525 cFYI(1, ("Send error in Query EA = %d", rc));
4526 } else { /* decode response */
4527 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4529 /* BB also check enough total bytes returned */
4530 /* BB we need to improve the validity checking
4531 of these trans2 responses */
4532 if (rc || (pSMBr->ByteCount < 4))
4533 rc = -EIO; /* bad smb */
4534 /* else if (pFindData){
4535 memcpy((char *) pFindData,
4536 (char *) &pSMBr->hdr.Protocol +
4539 /* check that length of list is not more than bcc */
4540 /* check that each entry does not go beyond length
4542 /* check that each element of each entry does not
4543 go beyond end of list */
4544 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4545 struct fealist * ea_response_data;
4547 /* validate_trans2_offsets() */
4548 /* BB to check if(start of smb + data_offset > &bcc+ bcc)*/
4549 ea_response_data = (struct fealist *)
4550 (((char *) &pSMBr->hdr.Protocol) +
4552 name_len = le32_to_cpu(ea_response_data->list_len);
4553 cFYI(1,("ea length %d", name_len));
4555 /* returned EA size zeroed at top of function */
4556 cFYI(1,("empty EA list returned from server"));
4558 /* account for ea list len */
4560 temp_fea = ea_response_data->list;
4561 temp_ptr = (char *)temp_fea;
4562 /* loop through checking if we have a matching
4563 name and then return the associated value */
4564 while(name_len > 0) {
4568 value_len = le16_to_cpu(temp_fea->value_len);
4569 /* BB validate that value_len falls within SMB,
4570 even though maximum for name_len is 255 */
4571 if(memcmp(temp_fea->name,ea_name,
4572 temp_fea->name_len) == 0) {
4575 /* account for prefix user. and trailing null */
4576 if(rc<=(int)buf_size) {
4578 temp_fea->name+temp_fea->name_len+1,
4580 /* ea values, unlike ea names,
4581 are not null terminated */
4582 } else if(buf_size == 0) {
4583 /* skip copy - calc size only */
4585 /* stop before overrun buffer */
4590 name_len -= temp_fea->name_len;
4591 temp_ptr += temp_fea->name_len;
4592 /* account for trailing null */
4595 name_len -= value_len;
4596 temp_ptr += value_len;
4597 /* no trailing null to account for in value len */
4598 /* go on to next EA */
4599 temp_fea = (struct fea *)temp_ptr;
4605 cifs_buf_release(pSMB);
4613 CIFSSMBSetEA(const int xid, struct cifsTconInfo *tcon, const char *fileName,
4614 const char * ea_name, const void * ea_value,
4615 const __u16 ea_value_len, const struct nls_table *nls_codepage,
4618 struct smb_com_transaction2_spi_req *pSMB = NULL;
4619 struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
4620 struct fealist *parm_data;
4623 int bytes_returned = 0;
4624 __u16 params, param_offset, byte_count, offset, count;
4626 cFYI(1, ("In SetEA"));
4628 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4633 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4635 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
4636 PATH_MAX, nls_codepage, remap);
4637 name_len++; /* trailing null */
4639 } else { /* BB improve the check for buffer overruns BB */
4640 name_len = strnlen(fileName, PATH_MAX);
4641 name_len++; /* trailing null */
4642 strncpy(pSMB->FileName, fileName, name_len);
4645 params = 6 + name_len;
4647 /* done calculating parms using name_len of file name,
4648 now use name_len to calculate length of ea name
4649 we are going to create in the inode xattrs */
4653 name_len = strnlen(ea_name,255);
4655 count = sizeof(*parm_data) + ea_value_len + name_len + 1;
4656 pSMB->MaxParameterCount = cpu_to_le16(2);
4657 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB size from sess */
4658 pSMB->MaxSetupCount = 0;
4662 pSMB->Reserved2 = 0;
4663 param_offset = offsetof(struct smb_com_transaction2_spi_req,
4664 InformationLevel) - 4;
4665 offset = param_offset + params;
4666 pSMB->InformationLevel =
4667 cpu_to_le16(SMB_SET_FILE_EA);
4670 (struct fealist *) (((char *) &pSMB->hdr.Protocol) +
4672 pSMB->ParameterOffset = cpu_to_le16(param_offset);
4673 pSMB->DataOffset = cpu_to_le16(offset);
4674 pSMB->SetupCount = 1;
4675 pSMB->Reserved3 = 0;
4676 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
4677 byte_count = 3 /* pad */ + params + count;
4678 pSMB->DataCount = cpu_to_le16(count);
4679 parm_data->list_len = cpu_to_le32(count);
4680 parm_data->list[0].EA_flags = 0;
4681 /* we checked above that name len is less than 255 */
4682 parm_data->list[0].name_len = (__u8)name_len;;
4683 /* EA names are always ASCII */
4685 strncpy(parm_data->list[0].name,ea_name,name_len);
4686 parm_data->list[0].name[name_len] = 0;
4687 parm_data->list[0].value_len = cpu_to_le16(ea_value_len);
4688 /* caller ensures that ea_value_len is less than 64K but
4689 we need to ensure that it fits within the smb */
4691 /*BB add length check that it would fit in negotiated SMB buffer size BB */
4692 /* if(ea_value_len > buffer_size - 512 (enough for header)) */
4694 memcpy(parm_data->list[0].name+name_len+1,ea_value,ea_value_len);
4696 pSMB->TotalDataCount = pSMB->DataCount;
4697 pSMB->ParameterCount = cpu_to_le16(params);
4698 pSMB->TotalParameterCount = pSMB->ParameterCount;
4699 pSMB->Reserved4 = 0;
4700 pSMB->hdr.smb_buf_length += byte_count;
4701 pSMB->ByteCount = cpu_to_le16(byte_count);
4702 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4703 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4705 cFYI(1, ("SetPathInfo (EA) returned %d", rc));
4708 cifs_buf_release(pSMB);