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 /* BB removeme BB */
1146 cFYI(1,("write2 at %lld %d bytes", (long long)offset, count));
1148 if(tcon->ses->capabilities & CAP_LARGE_FILES)
1152 rc = small_smb_init(SMB_COM_WRITE_ANDX, wct, tcon, (void **) &pSMB);
1155 /* tcon and ses pointer are checked in smb_init */
1156 if (tcon->ses->server == NULL)
1157 return -ECONNABORTED;
1159 pSMB->AndXCommand = 0xFF; /* none */
1161 pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF);
1163 pSMB->OffsetHigh = cpu_to_le32(offset >> 32);
1164 else if((offset >> 32) > 0) /* can not handle this big offset for old */
1166 pSMB->Reserved = 0xFFFFFFFF;
1167 pSMB->WriteMode = 0;
1168 pSMB->Remaining = 0;
1171 cpu_to_le16(offsetof(struct smb_com_write_req,Data) - 4);
1173 pSMB->DataLengthLow = cpu_to_le16(count & 0xFFFF);
1174 pSMB->DataLengthHigh = cpu_to_le16(count >> 16);
1175 smb_hdr_len = pSMB->hdr.smb_buf_length + 1; /* hdr + 1 byte pad */
1177 pSMB->hdr.smb_buf_length += count+1;
1178 else /* wct == 12 */
1179 pSMB->hdr.smb_buf_length += count+5; /* smb data starts later */
1181 pSMB->ByteCount = cpu_to_le16(count + 1);
1182 else /* wct == 12 */ /* bigger pad, smaller smb hdr, keep offset ok */ {
1183 struct smb_com_writex_req * pSMBW =
1184 (struct smb_com_writex_req *)pSMB;
1185 pSMBW->ByteCount = cpu_to_le16(count + 5);
1187 iov[0].iov_base = pSMB;
1188 iov[0].iov_len = smb_hdr_len + 4;
1190 rc = SendReceive2(xid, tcon->ses, iov, n_vec + 1, &bytes_returned,
1192 cifs_stats_inc(&tcon->num_writes);
1194 cFYI(1, ("Send error Write2 = %d", rc));
1197 WRITE_RSP * pSMBr = (WRITE_RSP *)pSMB;
1198 *nbytes = le16_to_cpu(pSMBr->CountHigh);
1199 *nbytes = (*nbytes) << 16;
1200 *nbytes += le16_to_cpu(pSMBr->Count);
1203 cifs_small_buf_release(pSMB);
1205 /* Note: On -EAGAIN error only caller can retry on handle based calls
1206 since file handle passed in no longer valid */
1212 #endif /* CIFS_EXPERIMENTAL */
1215 CIFSSMBLock(const int xid, struct cifsTconInfo *tcon,
1216 const __u16 smb_file_id, const __u64 len,
1217 const __u64 offset, const __u32 numUnlock,
1218 const __u32 numLock, const __u8 lockType, const int waitFlag)
1221 LOCK_REQ *pSMB = NULL;
1222 LOCK_RSP *pSMBr = NULL;
1227 cFYI(1, ("In CIFSSMBLock - timeout %d numLock %d",waitFlag,numLock));
1228 rc = small_smb_init(SMB_COM_LOCKING_ANDX, 8, tcon, (void **) &pSMB);
1233 pSMBr = (LOCK_RSP *)pSMB; /* BB removeme BB */
1235 if(lockType == LOCKING_ANDX_OPLOCK_RELEASE) {
1236 timeout = -1; /* no response expected */
1238 } else if (waitFlag == TRUE) {
1239 timeout = 3; /* blocking operation, no timeout */
1240 pSMB->Timeout = cpu_to_le32(-1);/* blocking - do not time out */
1245 pSMB->NumberOfLocks = cpu_to_le16(numLock);
1246 pSMB->NumberOfUnlocks = cpu_to_le16(numUnlock);
1247 pSMB->LockType = lockType;
1248 pSMB->AndXCommand = 0xFF; /* none */
1249 pSMB->Fid = smb_file_id; /* netfid stays le */
1251 if((numLock != 0) || (numUnlock != 0)) {
1252 pSMB->Locks[0].Pid = cpu_to_le16(current->tgid);
1253 /* BB where to store pid high? */
1254 pSMB->Locks[0].LengthLow = cpu_to_le32((u32)len);
1255 pSMB->Locks[0].LengthHigh = cpu_to_le32((u32)(len>>32));
1256 pSMB->Locks[0].OffsetLow = cpu_to_le32((u32)offset);
1257 pSMB->Locks[0].OffsetHigh = cpu_to_le32((u32)(offset>>32));
1258 count = sizeof(LOCKING_ANDX_RANGE);
1263 pSMB->hdr.smb_buf_length += count;
1264 pSMB->ByteCount = cpu_to_le16(count);
1266 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1267 (struct smb_hdr *) pSMBr, &bytes_returned, timeout);
1268 cifs_stats_inc(&tcon->num_locks);
1270 cFYI(1, ("Send error in Lock = %d", rc));
1272 cifs_small_buf_release(pSMB);
1274 /* Note: On -EAGAIN error only caller can retry on handle based calls
1275 since file handle passed in no longer valid */
1280 CIFSSMBClose(const int xid, struct cifsTconInfo *tcon, int smb_file_id)
1283 CLOSE_REQ *pSMB = NULL;
1284 CLOSE_RSP *pSMBr = NULL;
1286 cFYI(1, ("In CIFSSMBClose"));
1288 /* do not retry on dead session on close */
1289 rc = small_smb_init(SMB_COM_CLOSE, 3, tcon, (void **) &pSMB);
1295 pSMBr = (CLOSE_RSP *)pSMB; /* BB removeme BB */
1297 pSMB->FileID = (__u16) smb_file_id;
1298 pSMB->LastWriteTime = 0;
1299 pSMB->ByteCount = 0;
1300 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1301 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1302 cifs_stats_inc(&tcon->num_closes);
1305 /* EINTR is expected when user ctl-c to kill app */
1306 cERROR(1, ("Send error in Close = %d", rc));
1310 cifs_small_buf_release(pSMB);
1312 /* Since session is dead, file will be closed on server already */
1320 CIFSSMBRename(const int xid, struct cifsTconInfo *tcon,
1321 const char *fromName, const char *toName,
1322 const struct nls_table *nls_codepage, int remap)
1325 RENAME_REQ *pSMB = NULL;
1326 RENAME_RSP *pSMBr = NULL;
1328 int name_len, name_len2;
1331 cFYI(1, ("In CIFSSMBRename"));
1333 rc = smb_init(SMB_COM_RENAME, 1, tcon, (void **) &pSMB,
1338 pSMB->BufferFormat = 0x04;
1339 pSMB->SearchAttributes =
1340 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
1343 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1345 cifsConvertToUCS((__le16 *) pSMB->OldFileName, fromName,
1346 PATH_MAX, nls_codepage, remap);
1347 name_len++; /* trailing null */
1349 pSMB->OldFileName[name_len] = 0x04; /* pad */
1350 /* protocol requires ASCII signature byte on Unicode string */
1351 pSMB->OldFileName[name_len + 1] = 0x00;
1353 cifsConvertToUCS((__le16 *) &pSMB->OldFileName[name_len + 2],
1354 toName, PATH_MAX, nls_codepage, remap);
1355 name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
1356 name_len2 *= 2; /* convert to bytes */
1357 } else { /* BB improve the check for buffer overruns BB */
1358 name_len = strnlen(fromName, PATH_MAX);
1359 name_len++; /* trailing null */
1360 strncpy(pSMB->OldFileName, fromName, name_len);
1361 name_len2 = strnlen(toName, PATH_MAX);
1362 name_len2++; /* trailing null */
1363 pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */
1364 strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2);
1365 name_len2++; /* trailing null */
1366 name_len2++; /* signature byte */
1369 count = 1 /* 1st signature byte */ + name_len + name_len2;
1370 pSMB->hdr.smb_buf_length += count;
1371 pSMB->ByteCount = cpu_to_le16(count);
1373 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1374 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1375 cifs_stats_inc(&tcon->num_renames);
1377 cFYI(1, ("Send error in rename = %d", rc));
1380 cifs_buf_release(pSMB);
1388 int CIFSSMBRenameOpenFile(const int xid,struct cifsTconInfo *pTcon,
1389 int netfid, char * target_name,
1390 const struct nls_table * nls_codepage, int remap)
1392 struct smb_com_transaction2_sfi_req *pSMB = NULL;
1393 struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
1394 struct set_file_rename * rename_info;
1396 char dummy_string[30];
1398 int bytes_returned = 0;
1400 __u16 params, param_offset, offset, count, byte_count;
1402 cFYI(1, ("Rename to File by handle"));
1403 rc = smb_init(SMB_COM_TRANSACTION2, 15, pTcon, (void **) &pSMB,
1409 pSMB->MaxSetupCount = 0;
1413 pSMB->Reserved2 = 0;
1414 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
1415 offset = param_offset + params;
1417 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
1418 rename_info = (struct set_file_rename *) data_offset;
1419 pSMB->MaxParameterCount = cpu_to_le16(2);
1420 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB PDU from sess */
1421 pSMB->SetupCount = 1;
1422 pSMB->Reserved3 = 0;
1423 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
1424 byte_count = 3 /* pad */ + params;
1425 pSMB->ParameterCount = cpu_to_le16(params);
1426 pSMB->TotalParameterCount = pSMB->ParameterCount;
1427 pSMB->ParameterOffset = cpu_to_le16(param_offset);
1428 pSMB->DataOffset = cpu_to_le16(offset);
1429 /* construct random name ".cifs_tmp<inodenum><mid>" */
1430 rename_info->overwrite = cpu_to_le32(1);
1431 rename_info->root_fid = 0;
1432 /* unicode only call */
1433 if(target_name == NULL) {
1434 sprintf(dummy_string,"cifs%x",pSMB->hdr.Mid);
1435 len_of_str = cifsConvertToUCS((__le16 *)rename_info->target_name,
1436 dummy_string, 24, nls_codepage, remap);
1438 len_of_str = cifsConvertToUCS((__le16 *)rename_info->target_name,
1439 target_name, PATH_MAX, nls_codepage, remap);
1441 rename_info->target_name_len = cpu_to_le32(2 * len_of_str);
1442 count = 12 /* sizeof(struct set_file_rename) */ + (2 * len_of_str) + 2;
1443 byte_count += count;
1444 pSMB->DataCount = cpu_to_le16(count);
1445 pSMB->TotalDataCount = pSMB->DataCount;
1447 pSMB->InformationLevel =
1448 cpu_to_le16(SMB_SET_FILE_RENAME_INFORMATION);
1449 pSMB->Reserved4 = 0;
1450 pSMB->hdr.smb_buf_length += byte_count;
1451 pSMB->ByteCount = cpu_to_le16(byte_count);
1452 rc = SendReceive(xid, pTcon->ses, (struct smb_hdr *) pSMB,
1453 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1454 cifs_stats_inc(&pTcon->num_t2renames);
1456 cFYI(1,("Send error in Rename (by file handle) = %d", rc));
1459 cifs_buf_release(pSMB);
1461 /* Note: On -EAGAIN error only caller can retry on handle based calls
1462 since file handle passed in no longer valid */
1468 CIFSSMBCopy(const int xid, struct cifsTconInfo *tcon, const char * fromName,
1469 const __u16 target_tid, const char *toName, const int flags,
1470 const struct nls_table *nls_codepage, int remap)
1473 COPY_REQ *pSMB = NULL;
1474 COPY_RSP *pSMBr = NULL;
1476 int name_len, name_len2;
1479 cFYI(1, ("In CIFSSMBCopy"));
1481 rc = smb_init(SMB_COM_COPY, 1, tcon, (void **) &pSMB,
1486 pSMB->BufferFormat = 0x04;
1487 pSMB->Tid2 = target_tid;
1489 pSMB->Flags = cpu_to_le16(flags & COPY_TREE);
1491 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1492 name_len = cifsConvertToUCS((__le16 *) pSMB->OldFileName,
1493 fromName, PATH_MAX, nls_codepage,
1495 name_len++; /* trailing null */
1497 pSMB->OldFileName[name_len] = 0x04; /* pad */
1498 /* protocol requires ASCII signature byte on Unicode string */
1499 pSMB->OldFileName[name_len + 1] = 0x00;
1500 name_len2 = cifsConvertToUCS((__le16 *)&pSMB->OldFileName[name_len + 2],
1501 toName, PATH_MAX, nls_codepage, remap);
1502 name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
1503 name_len2 *= 2; /* convert to bytes */
1504 } else { /* BB improve the check for buffer overruns BB */
1505 name_len = strnlen(fromName, PATH_MAX);
1506 name_len++; /* trailing null */
1507 strncpy(pSMB->OldFileName, fromName, name_len);
1508 name_len2 = strnlen(toName, PATH_MAX);
1509 name_len2++; /* trailing null */
1510 pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */
1511 strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2);
1512 name_len2++; /* trailing null */
1513 name_len2++; /* signature byte */
1516 count = 1 /* 1st signature byte */ + name_len + name_len2;
1517 pSMB->hdr.smb_buf_length += count;
1518 pSMB->ByteCount = cpu_to_le16(count);
1520 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1521 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1523 cFYI(1, ("Send error in copy = %d with %d files copied",
1524 rc, le16_to_cpu(pSMBr->CopyCount)));
1527 cifs_buf_release(pSMB);
1536 CIFSUnixCreateSymLink(const int xid, struct cifsTconInfo *tcon,
1537 const char *fromName, const char *toName,
1538 const struct nls_table *nls_codepage)
1540 TRANSACTION2_SPI_REQ *pSMB = NULL;
1541 TRANSACTION2_SPI_RSP *pSMBr = NULL;
1544 int name_len_target;
1546 int bytes_returned = 0;
1547 __u16 params, param_offset, offset, byte_count;
1549 cFYI(1, ("In Symlink Unix style"));
1551 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
1556 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1558 cifs_strtoUCS((__le16 *) pSMB->FileName, fromName, PATH_MAX
1559 /* find define for this maxpathcomponent */
1561 name_len++; /* trailing null */
1564 } else { /* BB improve the check for buffer overruns BB */
1565 name_len = strnlen(fromName, PATH_MAX);
1566 name_len++; /* trailing null */
1567 strncpy(pSMB->FileName, fromName, name_len);
1569 params = 6 + name_len;
1570 pSMB->MaxSetupCount = 0;
1574 pSMB->Reserved2 = 0;
1575 param_offset = offsetof(struct smb_com_transaction2_spi_req,
1576 InformationLevel) - 4;
1577 offset = param_offset + params;
1579 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
1580 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1582 cifs_strtoUCS((__le16 *) data_offset, toName, PATH_MAX
1583 /* find define for this maxpathcomponent */
1585 name_len_target++; /* trailing null */
1586 name_len_target *= 2;
1587 } else { /* BB improve the check for buffer overruns BB */
1588 name_len_target = strnlen(toName, PATH_MAX);
1589 name_len_target++; /* trailing null */
1590 strncpy(data_offset, toName, name_len_target);
1593 pSMB->MaxParameterCount = cpu_to_le16(2);
1594 /* BB find exact max on data count below from sess */
1595 pSMB->MaxDataCount = cpu_to_le16(1000);
1596 pSMB->SetupCount = 1;
1597 pSMB->Reserved3 = 0;
1598 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
1599 byte_count = 3 /* pad */ + params + name_len_target;
1600 pSMB->DataCount = cpu_to_le16(name_len_target);
1601 pSMB->ParameterCount = cpu_to_le16(params);
1602 pSMB->TotalDataCount = pSMB->DataCount;
1603 pSMB->TotalParameterCount = pSMB->ParameterCount;
1604 pSMB->ParameterOffset = cpu_to_le16(param_offset);
1605 pSMB->DataOffset = cpu_to_le16(offset);
1606 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_LINK);
1607 pSMB->Reserved4 = 0;
1608 pSMB->hdr.smb_buf_length += byte_count;
1609 pSMB->ByteCount = cpu_to_le16(byte_count);
1610 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1611 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1612 cifs_stats_inc(&tcon->num_symlinks);
1615 ("Send error in SetPathInfo (create symlink) = %d",
1620 cifs_buf_release(pSMB);
1623 goto createSymLinkRetry;
1629 CIFSUnixCreateHardLink(const int xid, struct cifsTconInfo *tcon,
1630 const char *fromName, const char *toName,
1631 const struct nls_table *nls_codepage, int remap)
1633 TRANSACTION2_SPI_REQ *pSMB = NULL;
1634 TRANSACTION2_SPI_RSP *pSMBr = NULL;
1637 int name_len_target;
1639 int bytes_returned = 0;
1640 __u16 params, param_offset, offset, byte_count;
1642 cFYI(1, ("In Create Hard link Unix style"));
1643 createHardLinkRetry:
1644 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
1649 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1650 name_len = cifsConvertToUCS((__le16 *) pSMB->FileName, toName,
1651 PATH_MAX, nls_codepage, remap);
1652 name_len++; /* trailing null */
1655 } else { /* BB improve the check for buffer overruns BB */
1656 name_len = strnlen(toName, PATH_MAX);
1657 name_len++; /* trailing null */
1658 strncpy(pSMB->FileName, toName, name_len);
1660 params = 6 + name_len;
1661 pSMB->MaxSetupCount = 0;
1665 pSMB->Reserved2 = 0;
1666 param_offset = offsetof(struct smb_com_transaction2_spi_req,
1667 InformationLevel) - 4;
1668 offset = param_offset + params;
1670 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
1671 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1673 cifsConvertToUCS((__le16 *) data_offset, fromName, PATH_MAX,
1674 nls_codepage, remap);
1675 name_len_target++; /* trailing null */
1676 name_len_target *= 2;
1677 } else { /* BB improve the check for buffer overruns BB */
1678 name_len_target = strnlen(fromName, PATH_MAX);
1679 name_len_target++; /* trailing null */
1680 strncpy(data_offset, fromName, name_len_target);
1683 pSMB->MaxParameterCount = cpu_to_le16(2);
1684 /* BB find exact max on data count below from sess*/
1685 pSMB->MaxDataCount = cpu_to_le16(1000);
1686 pSMB->SetupCount = 1;
1687 pSMB->Reserved3 = 0;
1688 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
1689 byte_count = 3 /* pad */ + params + name_len_target;
1690 pSMB->ParameterCount = cpu_to_le16(params);
1691 pSMB->TotalParameterCount = pSMB->ParameterCount;
1692 pSMB->DataCount = cpu_to_le16(name_len_target);
1693 pSMB->TotalDataCount = pSMB->DataCount;
1694 pSMB->ParameterOffset = cpu_to_le16(param_offset);
1695 pSMB->DataOffset = cpu_to_le16(offset);
1696 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_HLINK);
1697 pSMB->Reserved4 = 0;
1698 pSMB->hdr.smb_buf_length += byte_count;
1699 pSMB->ByteCount = cpu_to_le16(byte_count);
1700 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1701 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1702 cifs_stats_inc(&tcon->num_hardlinks);
1704 cFYI(1, ("Send error in SetPathInfo (hard link) = %d", rc));
1707 cifs_buf_release(pSMB);
1709 goto createHardLinkRetry;
1715 CIFSCreateHardLink(const int xid, struct cifsTconInfo *tcon,
1716 const char *fromName, const char *toName,
1717 const struct nls_table *nls_codepage, int remap)
1720 NT_RENAME_REQ *pSMB = NULL;
1721 RENAME_RSP *pSMBr = NULL;
1723 int name_len, name_len2;
1726 cFYI(1, ("In CIFSCreateHardLink"));
1727 winCreateHardLinkRetry:
1729 rc = smb_init(SMB_COM_NT_RENAME, 4, tcon, (void **) &pSMB,
1734 pSMB->SearchAttributes =
1735 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
1737 pSMB->Flags = cpu_to_le16(CREATE_HARD_LINK);
1738 pSMB->ClusterCount = 0;
1740 pSMB->BufferFormat = 0x04;
1742 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1744 cifsConvertToUCS((__le16 *) pSMB->OldFileName, fromName,
1745 PATH_MAX, nls_codepage, remap);
1746 name_len++; /* trailing null */
1748 pSMB->OldFileName[name_len] = 0; /* pad */
1749 pSMB->OldFileName[name_len + 1] = 0x04;
1751 cifsConvertToUCS((__le16 *)&pSMB->OldFileName[name_len + 2],
1752 toName, PATH_MAX, nls_codepage, remap);
1753 name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
1754 name_len2 *= 2; /* convert to bytes */
1755 } else { /* BB improve the check for buffer overruns BB */
1756 name_len = strnlen(fromName, PATH_MAX);
1757 name_len++; /* trailing null */
1758 strncpy(pSMB->OldFileName, fromName, name_len);
1759 name_len2 = strnlen(toName, PATH_MAX);
1760 name_len2++; /* trailing null */
1761 pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */
1762 strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2);
1763 name_len2++; /* trailing null */
1764 name_len2++; /* signature byte */
1767 count = 1 /* string type byte */ + name_len + name_len2;
1768 pSMB->hdr.smb_buf_length += count;
1769 pSMB->ByteCount = cpu_to_le16(count);
1771 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1772 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1773 cifs_stats_inc(&tcon->num_hardlinks);
1775 cFYI(1, ("Send error in hard link (NT rename) = %d", rc));
1777 cifs_buf_release(pSMB);
1779 goto winCreateHardLinkRetry;
1785 CIFSSMBUnixQuerySymLink(const int xid, struct cifsTconInfo *tcon,
1786 const unsigned char *searchName,
1787 char *symlinkinfo, const int buflen,
1788 const struct nls_table *nls_codepage)
1790 /* SMB_QUERY_FILE_UNIX_LINK */
1791 TRANSACTION2_QPI_REQ *pSMB = NULL;
1792 TRANSACTION2_QPI_RSP *pSMBr = NULL;
1796 __u16 params, byte_count;
1798 cFYI(1, ("In QPathSymLinkInfo (Unix) for path %s", searchName));
1801 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
1806 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1808 cifs_strtoUCS((__le16 *) pSMB->FileName, searchName, PATH_MAX
1809 /* find define for this maxpathcomponent */
1811 name_len++; /* trailing null */
1813 } else { /* BB improve the check for buffer overruns BB */
1814 name_len = strnlen(searchName, PATH_MAX);
1815 name_len++; /* trailing null */
1816 strncpy(pSMB->FileName, searchName, name_len);
1819 params = 2 /* level */ + 4 /* rsrvd */ + name_len /* incl null */ ;
1820 pSMB->TotalDataCount = 0;
1821 pSMB->MaxParameterCount = cpu_to_le16(2);
1822 /* BB find exact max data count below from sess structure BB */
1823 pSMB->MaxDataCount = cpu_to_le16(4000);
1824 pSMB->MaxSetupCount = 0;
1828 pSMB->Reserved2 = 0;
1829 pSMB->ParameterOffset = cpu_to_le16(offsetof(
1830 struct smb_com_transaction2_qpi_req ,InformationLevel) - 4);
1831 pSMB->DataCount = 0;
1832 pSMB->DataOffset = 0;
1833 pSMB->SetupCount = 1;
1834 pSMB->Reserved3 = 0;
1835 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
1836 byte_count = params + 1 /* pad */ ;
1837 pSMB->TotalParameterCount = cpu_to_le16(params);
1838 pSMB->ParameterCount = pSMB->TotalParameterCount;
1839 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_LINK);
1840 pSMB->Reserved4 = 0;
1841 pSMB->hdr.smb_buf_length += byte_count;
1842 pSMB->ByteCount = cpu_to_le16(byte_count);
1844 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1845 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1847 cFYI(1, ("Send error in QuerySymLinkInfo = %d", rc));
1849 /* decode response */
1851 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
1852 if (rc || (pSMBr->ByteCount < 2))
1853 /* BB also check enough total bytes returned */
1854 rc = -EIO; /* bad smb */
1856 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
1857 __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
1859 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
1860 name_len = UniStrnlen((wchar_t *) ((char *)
1861 &pSMBr->hdr.Protocol +data_offset),
1862 min_t(const int, buflen,count) / 2);
1863 /* BB FIXME investigate remapping reserved chars here */
1864 cifs_strfromUCS_le(symlinkinfo,
1865 (__le16 *) ((char *)&pSMBr->hdr.Protocol +
1867 name_len, nls_codepage);
1869 strncpy(symlinkinfo,
1870 (char *) &pSMBr->hdr.Protocol +
1872 min_t(const int, buflen, count));
1874 symlinkinfo[buflen] = 0;
1875 /* just in case so calling code does not go off the end of buffer */
1878 cifs_buf_release(pSMB);
1880 goto querySymLinkRetry;
1885 CIFSSMBQueryReparseLinkInfo(const int xid, struct cifsTconInfo *tcon,
1886 const unsigned char *searchName,
1887 char *symlinkinfo, const int buflen,__u16 fid,
1888 const struct nls_table *nls_codepage)
1893 struct smb_com_transaction_ioctl_req * pSMB;
1894 struct smb_com_transaction_ioctl_rsp * pSMBr;
1896 cFYI(1, ("In Windows reparse style QueryLink for path %s", searchName));
1897 rc = smb_init(SMB_COM_NT_TRANSACT, 23, tcon, (void **) &pSMB,
1902 pSMB->TotalParameterCount = 0 ;
1903 pSMB->TotalDataCount = 0;
1904 pSMB->MaxParameterCount = cpu_to_le32(2);
1905 /* BB find exact data count max from sess structure BB */
1906 pSMB->MaxDataCount = cpu_to_le32(4000);
1907 pSMB->MaxSetupCount = 4;
1909 pSMB->ParameterOffset = 0;
1910 pSMB->DataCount = 0;
1911 pSMB->DataOffset = 0;
1912 pSMB->SetupCount = 4;
1913 pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_IOCTL);
1914 pSMB->ParameterCount = pSMB->TotalParameterCount;
1915 pSMB->FunctionCode = cpu_to_le32(FSCTL_GET_REPARSE_POINT);
1916 pSMB->IsFsctl = 1; /* FSCTL */
1917 pSMB->IsRootFlag = 0;
1918 pSMB->Fid = fid; /* file handle always le */
1919 pSMB->ByteCount = 0;
1921 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1922 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1924 cFYI(1, ("Send error in QueryReparseLinkInfo = %d", rc));
1925 } else { /* decode response */
1926 __u32 data_offset = le32_to_cpu(pSMBr->DataOffset);
1927 __u32 data_count = le32_to_cpu(pSMBr->DataCount);
1928 if ((pSMBr->ByteCount < 2) || (data_offset > 512))
1929 /* BB also check enough total bytes returned */
1930 rc = -EIO; /* bad smb */
1932 if(data_count && (data_count < 2048)) {
1933 char * end_of_smb = pSMBr->ByteCount + (char *)&pSMBr->ByteCount;
1935 struct reparse_data * reparse_buf = (struct reparse_data *)
1936 ((char *)&pSMBr->hdr.Protocol + data_offset);
1937 if((char*)reparse_buf >= end_of_smb) {
1941 if((reparse_buf->LinkNamesBuf +
1942 reparse_buf->TargetNameOffset +
1943 reparse_buf->TargetNameLen) >
1945 cFYI(1,("reparse buf extended beyond SMB"));
1950 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
1951 name_len = UniStrnlen((wchar_t *)
1952 (reparse_buf->LinkNamesBuf +
1953 reparse_buf->TargetNameOffset),
1954 min(buflen/2, reparse_buf->TargetNameLen / 2));
1955 cifs_strfromUCS_le(symlinkinfo,
1956 (__le16 *) (reparse_buf->LinkNamesBuf +
1957 reparse_buf->TargetNameOffset),
1958 name_len, nls_codepage);
1959 } else { /* ASCII names */
1960 strncpy(symlinkinfo,reparse_buf->LinkNamesBuf +
1961 reparse_buf->TargetNameOffset,
1962 min_t(const int, buflen, reparse_buf->TargetNameLen));
1966 cFYI(1,("Invalid return data count on get reparse info ioctl"));
1968 symlinkinfo[buflen] = 0; /* just in case so the caller
1969 does not go off the end of the buffer */
1970 cFYI(1,("readlink result - %s ",symlinkinfo));
1974 cifs_buf_release(pSMB);
1976 /* Note: On -EAGAIN error only caller can retry on handle based calls
1977 since file handle passed in no longer valid */
1982 #ifdef CONFIG_CIFS_POSIX
1984 /*Convert an Access Control Entry from wire format to local POSIX xattr format*/
1985 static void cifs_convert_ace(posix_acl_xattr_entry * ace, struct cifs_posix_ace * cifs_ace)
1987 /* u8 cifs fields do not need le conversion */
1988 ace->e_perm = cpu_to_le16(cifs_ace->cifs_e_perm);
1989 ace->e_tag = cpu_to_le16(cifs_ace->cifs_e_tag);
1990 ace->e_id = cpu_to_le32(le64_to_cpu(cifs_ace->cifs_uid));
1991 /* cFYI(1,("perm %d tag %d id %d",ace->e_perm,ace->e_tag,ace->e_id)); */
1996 /* Convert ACL from CIFS POSIX wire format to local Linux POSIX ACL xattr */
1997 static int cifs_copy_posix_acl(char * trgt,char * src, const int buflen,
1998 const int acl_type,const int size_of_data_area)
2003 struct cifs_posix_ace * pACE;
2004 struct cifs_posix_acl * cifs_acl = (struct cifs_posix_acl *)src;
2005 posix_acl_xattr_header * local_acl = (posix_acl_xattr_header *)trgt;
2007 if (le16_to_cpu(cifs_acl->version) != CIFS_ACL_VERSION)
2010 if(acl_type & ACL_TYPE_ACCESS) {
2011 count = le16_to_cpu(cifs_acl->access_entry_count);
2012 pACE = &cifs_acl->ace_array[0];
2013 size = sizeof(struct cifs_posix_acl);
2014 size += sizeof(struct cifs_posix_ace) * count;
2015 /* check if we would go beyond end of SMB */
2016 if(size_of_data_area < size) {
2017 cFYI(1,("bad CIFS POSIX ACL size %d vs. %d",size_of_data_area,size));
2020 } else if(acl_type & ACL_TYPE_DEFAULT) {
2021 count = le16_to_cpu(cifs_acl->access_entry_count);
2022 size = sizeof(struct cifs_posix_acl);
2023 size += sizeof(struct cifs_posix_ace) * count;
2024 /* skip past access ACEs to get to default ACEs */
2025 pACE = &cifs_acl->ace_array[count];
2026 count = le16_to_cpu(cifs_acl->default_entry_count);
2027 size += sizeof(struct cifs_posix_ace) * count;
2028 /* check if we would go beyond end of SMB */
2029 if(size_of_data_area < size)
2036 size = posix_acl_xattr_size(count);
2037 if((buflen == 0) || (local_acl == NULL)) {
2038 /* used to query ACL EA size */
2039 } else if(size > buflen) {
2041 } else /* buffer big enough */ {
2042 local_acl->a_version = cpu_to_le32(POSIX_ACL_XATTR_VERSION);
2043 for(i = 0;i < count ;i++) {
2044 cifs_convert_ace(&local_acl->a_entries[i],pACE);
2051 static __u16 convert_ace_to_cifs_ace(struct cifs_posix_ace * cifs_ace,
2052 const posix_acl_xattr_entry * local_ace)
2054 __u16 rc = 0; /* 0 = ACL converted ok */
2056 cifs_ace->cifs_e_perm = le16_to_cpu(local_ace->e_perm);
2057 cifs_ace->cifs_e_tag = le16_to_cpu(local_ace->e_tag);
2058 /* BB is there a better way to handle the large uid? */
2059 if(local_ace->e_id == cpu_to_le32(-1)) {
2060 /* Probably no need to le convert -1 on any arch but can not hurt */
2061 cifs_ace->cifs_uid = cpu_to_le64(-1);
2063 cifs_ace->cifs_uid = cpu_to_le64(le32_to_cpu(local_ace->e_id));
2064 /*cFYI(1,("perm %d tag %d id %d",ace->e_perm,ace->e_tag,ace->e_id));*/
2068 /* Convert ACL from local Linux POSIX xattr to CIFS POSIX ACL wire format */
2069 static __u16 ACL_to_cifs_posix(char * parm_data,const char * pACL,const int buflen,
2073 struct cifs_posix_acl * cifs_acl = (struct cifs_posix_acl *)parm_data;
2074 posix_acl_xattr_header * local_acl = (posix_acl_xattr_header *)pACL;
2078 if((buflen == 0) || (pACL == NULL) || (cifs_acl == NULL))
2081 count = posix_acl_xattr_count((size_t)buflen);
2082 cFYI(1,("setting acl with %d entries from buf of length %d and version of %d",
2083 count, buflen, le32_to_cpu(local_acl->a_version)));
2084 if(le32_to_cpu(local_acl->a_version) != 2) {
2085 cFYI(1,("unknown POSIX ACL version %d",
2086 le32_to_cpu(local_acl->a_version)));
2089 cifs_acl->version = cpu_to_le16(1);
2090 if(acl_type == ACL_TYPE_ACCESS)
2091 cifs_acl->access_entry_count = cpu_to_le16(count);
2092 else if(acl_type == ACL_TYPE_DEFAULT)
2093 cifs_acl->default_entry_count = cpu_to_le16(count);
2095 cFYI(1,("unknown ACL type %d",acl_type));
2098 for(i=0;i<count;i++) {
2099 rc = convert_ace_to_cifs_ace(&cifs_acl->ace_array[i],
2100 &local_acl->a_entries[i]);
2102 /* ACE not converted */
2107 rc = (__u16)(count * sizeof(struct cifs_posix_ace));
2108 rc += sizeof(struct cifs_posix_acl);
2109 /* BB add check to make sure ACL does not overflow SMB */
2115 CIFSSMBGetPosixACL(const int xid, struct cifsTconInfo *tcon,
2116 const unsigned char *searchName,
2117 char *acl_inf, const int buflen, const int acl_type,
2118 const struct nls_table *nls_codepage, int remap)
2120 /* SMB_QUERY_POSIX_ACL */
2121 TRANSACTION2_QPI_REQ *pSMB = NULL;
2122 TRANSACTION2_QPI_RSP *pSMBr = NULL;
2126 __u16 params, byte_count;
2128 cFYI(1, ("In GetPosixACL (Unix) for path %s", searchName));
2131 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2136 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2138 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
2139 PATH_MAX, nls_codepage, remap);
2140 name_len++; /* trailing null */
2142 pSMB->FileName[name_len] = 0;
2143 pSMB->FileName[name_len+1] = 0;
2144 } else { /* BB improve the check for buffer overruns BB */
2145 name_len = strnlen(searchName, PATH_MAX);
2146 name_len++; /* trailing null */
2147 strncpy(pSMB->FileName, searchName, name_len);
2150 params = 2 /* level */ + 4 /* rsrvd */ + name_len /* incl null */ ;
2151 pSMB->TotalDataCount = 0;
2152 pSMB->MaxParameterCount = cpu_to_le16(2);
2153 /* BB find exact max data count below from sess structure BB */
2154 pSMB->MaxDataCount = cpu_to_le16(4000);
2155 pSMB->MaxSetupCount = 0;
2159 pSMB->Reserved2 = 0;
2160 pSMB->ParameterOffset = cpu_to_le16(
2161 offsetof(struct smb_com_transaction2_qpi_req ,InformationLevel) - 4);
2162 pSMB->DataCount = 0;
2163 pSMB->DataOffset = 0;
2164 pSMB->SetupCount = 1;
2165 pSMB->Reserved3 = 0;
2166 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
2167 byte_count = params + 1 /* pad */ ;
2168 pSMB->TotalParameterCount = cpu_to_le16(params);
2169 pSMB->ParameterCount = pSMB->TotalParameterCount;
2170 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_POSIX_ACL);
2171 pSMB->Reserved4 = 0;
2172 pSMB->hdr.smb_buf_length += byte_count;
2173 pSMB->ByteCount = cpu_to_le16(byte_count);
2175 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2176 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2178 cFYI(1, ("Send error in Query POSIX ACL = %d", rc));
2180 /* decode response */
2182 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
2183 if (rc || (pSMBr->ByteCount < 2))
2184 /* BB also check enough total bytes returned */
2185 rc = -EIO; /* bad smb */
2187 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
2188 __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
2189 rc = cifs_copy_posix_acl(acl_inf,
2190 (char *)&pSMBr->hdr.Protocol+data_offset,
2191 buflen,acl_type,count);
2194 cifs_buf_release(pSMB);
2201 CIFSSMBSetPosixACL(const int xid, struct cifsTconInfo *tcon,
2202 const unsigned char *fileName,
2203 const char *local_acl, const int buflen,
2205 const struct nls_table *nls_codepage, int remap)
2207 struct smb_com_transaction2_spi_req *pSMB = NULL;
2208 struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
2212 int bytes_returned = 0;
2213 __u16 params, byte_count, data_count, param_offset, offset;
2215 cFYI(1, ("In SetPosixACL (Unix) for path %s", fileName));
2217 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2221 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2223 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
2224 PATH_MAX, nls_codepage, remap);
2225 name_len++; /* trailing null */
2227 } else { /* BB improve the check for buffer overruns BB */
2228 name_len = strnlen(fileName, PATH_MAX);
2229 name_len++; /* trailing null */
2230 strncpy(pSMB->FileName, fileName, name_len);
2232 params = 6 + name_len;
2233 pSMB->MaxParameterCount = cpu_to_le16(2);
2234 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB size from sess */
2235 pSMB->MaxSetupCount = 0;
2239 pSMB->Reserved2 = 0;
2240 param_offset = offsetof(struct smb_com_transaction2_spi_req,
2241 InformationLevel) - 4;
2242 offset = param_offset + params;
2243 parm_data = ((char *) &pSMB->hdr.Protocol) + offset;
2244 pSMB->ParameterOffset = cpu_to_le16(param_offset);
2246 /* convert to on the wire format for POSIX ACL */
2247 data_count = ACL_to_cifs_posix(parm_data,local_acl,buflen,acl_type);
2249 if(data_count == 0) {
2251 goto setACLerrorExit;
2253 pSMB->DataOffset = cpu_to_le16(offset);
2254 pSMB->SetupCount = 1;
2255 pSMB->Reserved3 = 0;
2256 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
2257 pSMB->InformationLevel = cpu_to_le16(SMB_SET_POSIX_ACL);
2258 byte_count = 3 /* pad */ + params + data_count;
2259 pSMB->DataCount = cpu_to_le16(data_count);
2260 pSMB->TotalDataCount = pSMB->DataCount;
2261 pSMB->ParameterCount = cpu_to_le16(params);
2262 pSMB->TotalParameterCount = pSMB->ParameterCount;
2263 pSMB->Reserved4 = 0;
2264 pSMB->hdr.smb_buf_length += byte_count;
2265 pSMB->ByteCount = cpu_to_le16(byte_count);
2266 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2267 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2269 cFYI(1, ("Set POSIX ACL returned %d", rc));
2273 cifs_buf_release(pSMB);
2279 /* BB fix tabs in this function FIXME BB */
2281 CIFSGetExtAttr(const int xid, struct cifsTconInfo *tcon,
2282 const int netfid, __u64 * pExtAttrBits, __u64 *pMask)
2285 struct smb_t2_qfi_req *pSMB = NULL;
2286 struct smb_t2_qfi_rsp *pSMBr = NULL;
2288 __u16 params, byte_count;
2290 cFYI(1,("In GetExtAttr"));
2295 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2300 params = 2 /* level */ +2 /* fid */;
2301 pSMB->t2.TotalDataCount = 0;
2302 pSMB->t2.MaxParameterCount = cpu_to_le16(4);
2303 /* BB find exact max data count below from sess structure BB */
2304 pSMB->t2.MaxDataCount = cpu_to_le16(4000);
2305 pSMB->t2.MaxSetupCount = 0;
2306 pSMB->t2.Reserved = 0;
2308 pSMB->t2.Timeout = 0;
2309 pSMB->t2.Reserved2 = 0;
2310 pSMB->t2.ParameterOffset = cpu_to_le16(offsetof(struct smb_t2_qfi_req,
2312 pSMB->t2.DataCount = 0;
2313 pSMB->t2.DataOffset = 0;
2314 pSMB->t2.SetupCount = 1;
2315 pSMB->t2.Reserved3 = 0;
2316 pSMB->t2.SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION);
2317 byte_count = params + 1 /* pad */ ;
2318 pSMB->t2.TotalParameterCount = cpu_to_le16(params);
2319 pSMB->t2.ParameterCount = pSMB->t2.TotalParameterCount;
2320 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_ATTR_FLAGS);
2323 pSMB->hdr.smb_buf_length += byte_count;
2324 pSMB->t2.ByteCount = cpu_to_le16(byte_count);
2326 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2327 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2329 cFYI(1, ("error %d in GetExtAttr", rc));
2331 /* decode response */
2332 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
2333 if (rc || (pSMBr->ByteCount < 2))
2334 /* BB also check enough total bytes returned */
2335 /* If rc should we check for EOPNOSUPP and
2336 disable the srvino flag? or in caller? */
2337 rc = -EIO; /* bad smb */
2339 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
2340 __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
2341 struct file_chattr_info * pfinfo;
2342 /* BB Do we need a cast or hash here ? */
2344 cFYI(1, ("Illegal size ret in GetExtAttr"));
2348 pfinfo = (struct file_chattr_info *)
2349 (data_offset + (char *) &pSMBr->hdr.Protocol);
2350 *pExtAttrBits = le64_to_cpu(pfinfo->mode);
2351 *pMask = le64_to_cpu(pfinfo->mask);
2355 cifs_buf_release(pSMB);
2357 goto GetExtAttrRetry;
2362 #endif /* CONFIG_POSIX */
2364 /* Legacy Query Path Information call for lookup to old servers such
2366 int SMBQueryInformation(const int xid, struct cifsTconInfo *tcon,
2367 const unsigned char *searchName,
2368 FILE_ALL_INFO * pFinfo,
2369 const struct nls_table *nls_codepage, int remap)
2371 QUERY_INFORMATION_REQ * pSMB;
2372 QUERY_INFORMATION_RSP * pSMBr;
2377 cFYI(1, ("In SMBQPath path %s", searchName));
2379 rc = smb_init(SMB_COM_QUERY_INFORMATION, 0, tcon, (void **) &pSMB,
2384 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2386 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
2387 PATH_MAX, nls_codepage, remap);
2388 name_len++; /* trailing null */
2391 name_len = strnlen(searchName, PATH_MAX);
2392 name_len++; /* trailing null */
2393 strncpy(pSMB->FileName, searchName, name_len);
2395 pSMB->BufferFormat = 0x04;
2396 name_len++; /* account for buffer type byte */
2397 pSMB->hdr.smb_buf_length += (__u16) name_len;
2398 pSMB->ByteCount = cpu_to_le16(name_len);
2400 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2401 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2403 cFYI(1, ("Send error in QueryInfo = %d", rc));
2404 } else if (pFinfo) { /* decode response */
2405 memset(pFinfo, 0, sizeof(FILE_ALL_INFO));
2406 pFinfo->AllocationSize =
2407 cpu_to_le64(le32_to_cpu(pSMBr->size));
2408 pFinfo->EndOfFile = pFinfo->AllocationSize;
2409 pFinfo->Attributes =
2410 cpu_to_le32(le16_to_cpu(pSMBr->attr));
2412 rc = -EIO; /* bad buffer passed in */
2414 cifs_buf_release(pSMB);
2426 CIFSSMBQPathInfo(const int xid, struct cifsTconInfo *tcon,
2427 const unsigned char *searchName,
2428 FILE_ALL_INFO * pFindData,
2429 const struct nls_table *nls_codepage, int remap)
2431 /* level 263 SMB_QUERY_FILE_ALL_INFO */
2432 TRANSACTION2_QPI_REQ *pSMB = NULL;
2433 TRANSACTION2_QPI_RSP *pSMBr = NULL;
2437 __u16 params, byte_count;
2439 /* cFYI(1, ("In QPathInfo path %s", searchName)); */
2441 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2446 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2448 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
2449 PATH_MAX, nls_codepage, remap);
2450 name_len++; /* trailing null */
2452 } else { /* BB improve the check for buffer overruns BB */
2453 name_len = strnlen(searchName, PATH_MAX);
2454 name_len++; /* trailing null */
2455 strncpy(pSMB->FileName, searchName, name_len);
2458 params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */ ;
2459 pSMB->TotalDataCount = 0;
2460 pSMB->MaxParameterCount = cpu_to_le16(2);
2461 pSMB->MaxDataCount = cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
2462 pSMB->MaxSetupCount = 0;
2466 pSMB->Reserved2 = 0;
2467 pSMB->ParameterOffset = cpu_to_le16(offsetof(
2468 struct smb_com_transaction2_qpi_req ,InformationLevel) - 4);
2469 pSMB->DataCount = 0;
2470 pSMB->DataOffset = 0;
2471 pSMB->SetupCount = 1;
2472 pSMB->Reserved3 = 0;
2473 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
2474 byte_count = params + 1 /* pad */ ;
2475 pSMB->TotalParameterCount = cpu_to_le16(params);
2476 pSMB->ParameterCount = pSMB->TotalParameterCount;
2477 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_ALL_INFO);
2478 pSMB->Reserved4 = 0;
2479 pSMB->hdr.smb_buf_length += byte_count;
2480 pSMB->ByteCount = cpu_to_le16(byte_count);
2482 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2483 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2485 cFYI(1, ("Send error in QPathInfo = %d", rc));
2486 } else { /* decode response */
2487 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
2489 if (rc || (pSMBr->ByteCount < 40))
2490 rc = -EIO; /* bad smb */
2491 else if (pFindData){
2492 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
2493 memcpy((char *) pFindData,
2494 (char *) &pSMBr->hdr.Protocol +
2495 data_offset, sizeof (FILE_ALL_INFO));
2499 cifs_buf_release(pSMB);
2501 goto QPathInfoRetry;
2507 CIFSSMBUnixQPathInfo(const int xid, struct cifsTconInfo *tcon,
2508 const unsigned char *searchName,
2509 FILE_UNIX_BASIC_INFO * pFindData,
2510 const struct nls_table *nls_codepage, int remap)
2512 /* SMB_QUERY_FILE_UNIX_BASIC */
2513 TRANSACTION2_QPI_REQ *pSMB = NULL;
2514 TRANSACTION2_QPI_RSP *pSMBr = NULL;
2516 int bytes_returned = 0;
2518 __u16 params, byte_count;
2520 cFYI(1, ("In QPathInfo (Unix) the path %s", searchName));
2522 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2527 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2529 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
2530 PATH_MAX, nls_codepage, remap);
2531 name_len++; /* trailing null */
2533 } else { /* BB improve the check for buffer overruns BB */
2534 name_len = strnlen(searchName, PATH_MAX);
2535 name_len++; /* trailing null */
2536 strncpy(pSMB->FileName, searchName, name_len);
2539 params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */ ;
2540 pSMB->TotalDataCount = 0;
2541 pSMB->MaxParameterCount = cpu_to_le16(2);
2542 /* BB find exact max SMB PDU from sess structure BB */
2543 pSMB->MaxDataCount = cpu_to_le16(4000);
2544 pSMB->MaxSetupCount = 0;
2548 pSMB->Reserved2 = 0;
2549 pSMB->ParameterOffset = cpu_to_le16(offsetof(
2550 struct smb_com_transaction2_qpi_req ,InformationLevel) - 4);
2551 pSMB->DataCount = 0;
2552 pSMB->DataOffset = 0;
2553 pSMB->SetupCount = 1;
2554 pSMB->Reserved3 = 0;
2555 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
2556 byte_count = params + 1 /* pad */ ;
2557 pSMB->TotalParameterCount = cpu_to_le16(params);
2558 pSMB->ParameterCount = pSMB->TotalParameterCount;
2559 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC);
2560 pSMB->Reserved4 = 0;
2561 pSMB->hdr.smb_buf_length += byte_count;
2562 pSMB->ByteCount = cpu_to_le16(byte_count);
2564 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2565 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2567 cFYI(1, ("Send error in QPathInfo = %d", rc));
2568 } else { /* decode response */
2569 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
2571 if (rc || (pSMBr->ByteCount < sizeof(FILE_UNIX_BASIC_INFO))) {
2572 rc = -EIO; /* bad smb */
2574 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
2575 memcpy((char *) pFindData,
2576 (char *) &pSMBr->hdr.Protocol +
2578 sizeof (FILE_UNIX_BASIC_INFO));
2581 cifs_buf_release(pSMB);
2583 goto UnixQPathInfoRetry;
2588 #if 0 /* function unused at present */
2589 int CIFSFindSingle(const int xid, struct cifsTconInfo *tcon,
2590 const char *searchName, FILE_ALL_INFO * findData,
2591 const struct nls_table *nls_codepage)
2593 /* level 257 SMB_ */
2594 TRANSACTION2_FFIRST_REQ *pSMB = NULL;
2595 TRANSACTION2_FFIRST_RSP *pSMBr = NULL;
2599 __u16 params, byte_count;
2601 cFYI(1, ("In FindUnique"));
2603 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2608 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2610 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName, PATH_MAX
2611 /* find define for this maxpathcomponent */
2613 name_len++; /* trailing null */
2615 } else { /* BB improve the check for buffer overruns BB */
2616 name_len = strnlen(searchName, PATH_MAX);
2617 name_len++; /* trailing null */
2618 strncpy(pSMB->FileName, searchName, name_len);
2621 params = 12 + name_len /* includes null */ ;
2622 pSMB->TotalDataCount = 0; /* no EAs */
2623 pSMB->MaxParameterCount = cpu_to_le16(2);
2624 pSMB->MaxDataCount = cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
2625 pSMB->MaxSetupCount = 0;
2629 pSMB->Reserved2 = 0;
2630 pSMB->ParameterOffset = cpu_to_le16(
2631 offsetof(struct smb_com_transaction2_ffirst_req,InformationLevel) - 4);
2632 pSMB->DataCount = 0;
2633 pSMB->DataOffset = 0;
2634 pSMB->SetupCount = 1; /* one byte, no need to le convert */
2635 pSMB->Reserved3 = 0;
2636 pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_FIRST);
2637 byte_count = params + 1 /* pad */ ;
2638 pSMB->TotalParameterCount = cpu_to_le16(params);
2639 pSMB->ParameterCount = pSMB->TotalParameterCount;
2640 pSMB->SearchAttributes =
2641 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
2643 pSMB->SearchCount = cpu_to_le16(16); /* BB increase */
2644 pSMB->SearchFlags = cpu_to_le16(1);
2645 pSMB->InformationLevel = cpu_to_le16(SMB_FIND_FILE_DIRECTORY_INFO);
2646 pSMB->SearchStorageType = 0; /* BB what should we set this to? BB */
2647 pSMB->hdr.smb_buf_length += byte_count;
2648 pSMB->ByteCount = cpu_to_le16(byte_count);
2650 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2651 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2654 cFYI(1, ("Send error in FindFileDirInfo = %d", rc));
2655 } else { /* decode response */
2656 cifs_stats_inc(&tcon->num_ffirst);
2660 cifs_buf_release(pSMB);
2662 goto findUniqueRetry;
2666 #endif /* end unused (temporarily) function */
2668 /* xid, tcon, searchName and codepage are input parms, rest are returned */
2670 CIFSFindFirst(const int xid, struct cifsTconInfo *tcon,
2671 const char *searchName,
2672 const struct nls_table *nls_codepage,
2674 struct cifs_search_info * psrch_inf, int remap, const char dirsep)
2676 /* level 257 SMB_ */
2677 TRANSACTION2_FFIRST_REQ *pSMB = NULL;
2678 TRANSACTION2_FFIRST_RSP *pSMBr = NULL;
2679 T2_FFIRST_RSP_PARMS * parms;
2681 int bytes_returned = 0;
2683 __u16 params, byte_count;
2685 cFYI(1, ("In FindFirst for %s",searchName));
2688 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2693 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2695 cifsConvertToUCS((__le16 *) pSMB->FileName,searchName,
2696 PATH_MAX, nls_codepage, remap);
2697 /* We can not add the asterik earlier in case
2698 it got remapped to 0xF03A as if it were part of the
2699 directory name instead of a wildcard */
2701 pSMB->FileName[name_len] = dirsep;
2702 pSMB->FileName[name_len+1] = 0;
2703 pSMB->FileName[name_len+2] = '*';
2704 pSMB->FileName[name_len+3] = 0;
2705 name_len += 4; /* now the trailing null */
2706 pSMB->FileName[name_len] = 0; /* null terminate just in case */
2707 pSMB->FileName[name_len+1] = 0;
2709 } else { /* BB add check for overrun of SMB buf BB */
2710 name_len = strnlen(searchName, PATH_MAX);
2711 /* BB fix here and in unicode clause above ie
2712 if(name_len > buffersize-header)
2713 free buffer exit; BB */
2714 strncpy(pSMB->FileName, searchName, name_len);
2715 pSMB->FileName[name_len] = dirsep;
2716 pSMB->FileName[name_len+1] = '*';
2717 pSMB->FileName[name_len+2] = 0;
2721 params = 12 + name_len /* includes null */ ;
2722 pSMB->TotalDataCount = 0; /* no EAs */
2723 pSMB->MaxParameterCount = cpu_to_le16(10);
2724 pSMB->MaxDataCount = cpu_to_le16((tcon->ses->server->maxBuf -
2725 MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
2726 pSMB->MaxSetupCount = 0;
2730 pSMB->Reserved2 = 0;
2731 byte_count = params + 1 /* pad */ ;
2732 pSMB->TotalParameterCount = cpu_to_le16(params);
2733 pSMB->ParameterCount = pSMB->TotalParameterCount;
2734 pSMB->ParameterOffset = cpu_to_le16(
2735 offsetof(struct smb_com_transaction2_ffirst_req, SearchAttributes) - 4);
2736 pSMB->DataCount = 0;
2737 pSMB->DataOffset = 0;
2738 pSMB->SetupCount = 1; /* one byte, no need to make endian neutral */
2739 pSMB->Reserved3 = 0;
2740 pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_FIRST);
2741 pSMB->SearchAttributes =
2742 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
2744 pSMB->SearchCount= cpu_to_le16(CIFSMaxBufSize/sizeof(FILE_UNIX_INFO));
2745 pSMB->SearchFlags = cpu_to_le16(CIFS_SEARCH_CLOSE_AT_END |
2746 CIFS_SEARCH_RETURN_RESUME);
2747 pSMB->InformationLevel = cpu_to_le16(psrch_inf->info_level);
2749 /* BB what should we set StorageType to? Does it matter? BB */
2750 pSMB->SearchStorageType = 0;
2751 pSMB->hdr.smb_buf_length += byte_count;
2752 pSMB->ByteCount = cpu_to_le16(byte_count);
2754 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2755 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2756 cifs_stats_inc(&tcon->num_ffirst);
2758 if (rc) {/* BB add logic to retry regular search if Unix search rejected unexpectedly by server */
2759 /* BB Add code to handle unsupported level rc */
2760 cFYI(1, ("Error in FindFirst = %d", rc));
2763 cifs_buf_release(pSMB);
2765 /* BB eventually could optimize out free and realloc of buf */
2768 goto findFirstRetry;
2769 } else { /* decode response */
2770 /* BB remember to free buffer if error BB */
2771 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
2773 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
2774 psrch_inf->unicode = TRUE;
2776 psrch_inf->unicode = FALSE;
2778 psrch_inf->ntwrk_buf_start = (char *)pSMBr;
2779 psrch_inf->srch_entries_start =
2780 (char *) &pSMBr->hdr.Protocol +
2781 le16_to_cpu(pSMBr->t2.DataOffset);
2782 parms = (T2_FFIRST_RSP_PARMS *)((char *) &pSMBr->hdr.Protocol +
2783 le16_to_cpu(pSMBr->t2.ParameterOffset));
2785 if(parms->EndofSearch)
2786 psrch_inf->endOfSearch = TRUE;
2788 psrch_inf->endOfSearch = FALSE;
2790 psrch_inf->entries_in_buffer = le16_to_cpu(parms->SearchCount);
2791 psrch_inf->index_of_last_entry =
2792 psrch_inf->entries_in_buffer;
2793 *pnetfid = parms->SearchHandle;
2795 cifs_buf_release(pSMB);
2802 int CIFSFindNext(const int xid, struct cifsTconInfo *tcon,
2803 __u16 searchHandle, struct cifs_search_info * psrch_inf)
2805 TRANSACTION2_FNEXT_REQ *pSMB = NULL;
2806 TRANSACTION2_FNEXT_RSP *pSMBr = NULL;
2807 T2_FNEXT_RSP_PARMS * parms;
2808 char *response_data;
2810 int bytes_returned, name_len;
2811 __u16 params, byte_count;
2813 cFYI(1, ("In FindNext"));
2815 if(psrch_inf->endOfSearch == TRUE)
2818 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2823 params = 14; /* includes 2 bytes of null string, converted to LE below */
2825 pSMB->TotalDataCount = 0; /* no EAs */
2826 pSMB->MaxParameterCount = cpu_to_le16(8);
2827 pSMB->MaxDataCount =
2828 cpu_to_le16((tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
2829 pSMB->MaxSetupCount = 0;
2833 pSMB->Reserved2 = 0;
2834 pSMB->ParameterOffset = cpu_to_le16(
2835 offsetof(struct smb_com_transaction2_fnext_req,SearchHandle) - 4);
2836 pSMB->DataCount = 0;
2837 pSMB->DataOffset = 0;
2838 pSMB->SetupCount = 1;
2839 pSMB->Reserved3 = 0;
2840 pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_NEXT);
2841 pSMB->SearchHandle = searchHandle; /* always kept as le */
2843 cpu_to_le16(CIFSMaxBufSize / sizeof (FILE_UNIX_INFO));
2844 /* test for Unix extensions */
2845 /* if (tcon->ses->capabilities & CAP_UNIX) {
2846 pSMB->InformationLevel = cpu_to_le16(SMB_FIND_FILE_UNIX);
2847 psrch_inf->info_level = SMB_FIND_FILE_UNIX;
2849 pSMB->InformationLevel =
2850 cpu_to_le16(SMB_FIND_FILE_DIRECTORY_INFO);
2851 psrch_inf->info_level = SMB_FIND_FILE_DIRECTORY_INFO;
2853 pSMB->InformationLevel = cpu_to_le16(psrch_inf->info_level);
2854 pSMB->ResumeKey = psrch_inf->resume_key;
2856 cpu_to_le16(CIFS_SEARCH_CLOSE_AT_END | CIFS_SEARCH_RETURN_RESUME);
2858 name_len = psrch_inf->resume_name_len;
2860 if(name_len < PATH_MAX) {
2861 memcpy(pSMB->ResumeFileName, psrch_inf->presume_name, name_len);
2862 byte_count += name_len;
2863 /* 14 byte parm len above enough for 2 byte null terminator */
2864 pSMB->ResumeFileName[name_len] = 0;
2865 pSMB->ResumeFileName[name_len+1] = 0;
2868 goto FNext2_err_exit;
2870 byte_count = params + 1 /* pad */ ;
2871 pSMB->TotalParameterCount = cpu_to_le16(params);
2872 pSMB->ParameterCount = pSMB->TotalParameterCount;
2873 pSMB->hdr.smb_buf_length += byte_count;
2874 pSMB->ByteCount = cpu_to_le16(byte_count);
2876 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2877 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2878 cifs_stats_inc(&tcon->num_fnext);
2881 psrch_inf->endOfSearch = TRUE;
2882 rc = 0; /* search probably was closed at end of search above */
2884 cFYI(1, ("FindNext returned = %d", rc));
2885 } else { /* decode response */
2886 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
2889 /* BB fixme add lock for file (srch_info) struct here */
2890 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
2891 psrch_inf->unicode = TRUE;
2893 psrch_inf->unicode = FALSE;
2894 response_data = (char *) &pSMBr->hdr.Protocol +
2895 le16_to_cpu(pSMBr->t2.ParameterOffset);
2896 parms = (T2_FNEXT_RSP_PARMS *)response_data;
2897 response_data = (char *)&pSMBr->hdr.Protocol +
2898 le16_to_cpu(pSMBr->t2.DataOffset);
2899 cifs_buf_release(psrch_inf->ntwrk_buf_start);
2900 psrch_inf->srch_entries_start = response_data;
2901 psrch_inf->ntwrk_buf_start = (char *)pSMB;
2902 if(parms->EndofSearch)
2903 psrch_inf->endOfSearch = TRUE;
2905 psrch_inf->endOfSearch = FALSE;
2907 psrch_inf->entries_in_buffer = le16_to_cpu(parms->SearchCount);
2908 psrch_inf->index_of_last_entry +=
2909 psrch_inf->entries_in_buffer;
2910 /* cFYI(1,("fnxt2 entries in buf %d index_of_last %d",psrch_inf->entries_in_buffer,psrch_inf->index_of_last_entry)); */
2912 /* BB fixme add unlock here */
2917 /* BB On error, should we leave previous search buf (and count and
2918 last entry fields) intact or free the previous one? */
2920 /* Note: On -EAGAIN error only caller can retry on handle based calls
2921 since file handle passed in no longer valid */
2924 cifs_buf_release(pSMB);
2930 CIFSFindClose(const int xid, struct cifsTconInfo *tcon, const __u16 searchHandle)
2933 FINDCLOSE_REQ *pSMB = NULL;
2934 CLOSE_RSP *pSMBr = NULL; /* BB removeme BB */
2937 cFYI(1, ("In CIFSSMBFindClose"));
2938 rc = small_smb_init(SMB_COM_FIND_CLOSE2, 1, tcon, (void **)&pSMB);
2940 /* no sense returning error if session restarted
2941 as file handle has been closed */
2947 pSMBr = (CLOSE_RSP *)pSMB; /* BB removeme BB */
2948 pSMB->FileID = searchHandle;
2949 pSMB->ByteCount = 0;
2950 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2951 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2953 cERROR(1, ("Send error in FindClose = %d", rc));
2955 cifs_stats_inc(&tcon->num_fclose);
2956 cifs_small_buf_release(pSMB);
2958 /* Since session is dead, search handle closed on server already */
2966 CIFSGetSrvInodeNumber(const int xid, struct cifsTconInfo *tcon,
2967 const unsigned char *searchName,
2968 __u64 * inode_number,
2969 const struct nls_table *nls_codepage, int remap)
2972 TRANSACTION2_QPI_REQ *pSMB = NULL;
2973 TRANSACTION2_QPI_RSP *pSMBr = NULL;
2974 int name_len, bytes_returned;
2975 __u16 params, byte_count;
2977 cFYI(1,("In GetSrvInodeNum for %s",searchName));
2981 GetInodeNumberRetry:
2982 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2988 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2990 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
2991 PATH_MAX,nls_codepage, remap);
2992 name_len++; /* trailing null */
2994 } else { /* BB improve the check for buffer overruns BB */
2995 name_len = strnlen(searchName, PATH_MAX);
2996 name_len++; /* trailing null */
2997 strncpy(pSMB->FileName, searchName, name_len);
3000 params = 2 /* level */ + 4 /* rsrvd */ + name_len /* incl null */ ;
3001 pSMB->TotalDataCount = 0;
3002 pSMB->MaxParameterCount = cpu_to_le16(2);
3003 /* BB find exact max data count below from sess structure BB */
3004 pSMB->MaxDataCount = cpu_to_le16(4000);
3005 pSMB->MaxSetupCount = 0;
3009 pSMB->Reserved2 = 0;
3010 pSMB->ParameterOffset = cpu_to_le16(offsetof(
3011 struct smb_com_transaction2_qpi_req ,InformationLevel) - 4);
3012 pSMB->DataCount = 0;
3013 pSMB->DataOffset = 0;
3014 pSMB->SetupCount = 1;
3015 pSMB->Reserved3 = 0;
3016 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
3017 byte_count = params + 1 /* pad */ ;
3018 pSMB->TotalParameterCount = cpu_to_le16(params);
3019 pSMB->ParameterCount = pSMB->TotalParameterCount;
3020 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_INTERNAL_INFO);
3021 pSMB->Reserved4 = 0;
3022 pSMB->hdr.smb_buf_length += byte_count;
3023 pSMB->ByteCount = cpu_to_le16(byte_count);
3025 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3026 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3028 cFYI(1, ("error %d in QueryInternalInfo", rc));
3030 /* decode response */
3031 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3032 if (rc || (pSMBr->ByteCount < 2))
3033 /* BB also check enough total bytes returned */
3034 /* If rc should we check for EOPNOSUPP and
3035 disable the srvino flag? or in caller? */
3036 rc = -EIO; /* bad smb */
3038 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3039 __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
3040 struct file_internal_info * pfinfo;
3041 /* BB Do we need a cast or hash here ? */
3043 cFYI(1, ("Illegal size ret in QryIntrnlInf"));
3045 goto GetInodeNumOut;
3047 pfinfo = (struct file_internal_info *)
3048 (data_offset + (char *) &pSMBr->hdr.Protocol);
3049 *inode_number = pfinfo->UniqueId;
3053 cifs_buf_release(pSMB);
3055 goto GetInodeNumberRetry;
3060 CIFSGetDFSRefer(const int xid, struct cifsSesInfo *ses,
3061 const unsigned char *searchName,
3062 unsigned char **targetUNCs,
3063 unsigned int *number_of_UNC_in_array,
3064 const struct nls_table *nls_codepage, int remap)
3066 /* TRANS2_GET_DFS_REFERRAL */
3067 TRANSACTION2_GET_DFS_REFER_REQ *pSMB = NULL;
3068 TRANSACTION2_GET_DFS_REFER_RSP *pSMBr = NULL;
3069 struct dfs_referral_level_3 * referrals = NULL;
3075 __u16 params, byte_count;
3076 *number_of_UNC_in_array = 0;
3079 cFYI(1, ("In GetDFSRefer the path %s", searchName));
3083 rc = smb_init(SMB_COM_TRANSACTION2, 15, NULL, (void **) &pSMB,
3088 /* server pointer checked in called function,
3089 but should never be null here anyway */
3090 pSMB->hdr.Mid = GetNextMid(ses->server);
3091 pSMB->hdr.Tid = ses->ipc_tid;
3092 pSMB->hdr.Uid = ses->Suid;
3093 if (ses->capabilities & CAP_STATUS32) {
3094 pSMB->hdr.Flags2 |= SMBFLG2_ERR_STATUS;
3096 if (ses->capabilities & CAP_DFS) {
3097 pSMB->hdr.Flags2 |= SMBFLG2_DFS;
3100 if (ses->capabilities & CAP_UNICODE) {
3101 pSMB->hdr.Flags2 |= SMBFLG2_UNICODE;
3103 cifsConvertToUCS((__le16 *) pSMB->RequestFileName,
3104 searchName, PATH_MAX, nls_codepage, remap);
3105 name_len++; /* trailing null */
3107 } else { /* BB improve the check for buffer overruns BB */
3108 name_len = strnlen(searchName, PATH_MAX);
3109 name_len++; /* trailing null */
3110 strncpy(pSMB->RequestFileName, searchName, name_len);
3113 params = 2 /* level */ + name_len /*includes null */ ;
3114 pSMB->TotalDataCount = 0;
3115 pSMB->DataCount = 0;
3116 pSMB->DataOffset = 0;
3117 pSMB->MaxParameterCount = 0;
3118 pSMB->MaxDataCount = cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
3119 pSMB->MaxSetupCount = 0;
3123 pSMB->Reserved2 = 0;
3124 pSMB->ParameterOffset = cpu_to_le16(offsetof(
3125 struct smb_com_transaction2_get_dfs_refer_req, MaxReferralLevel) - 4);
3126 pSMB->SetupCount = 1;
3127 pSMB->Reserved3 = 0;
3128 pSMB->SubCommand = cpu_to_le16(TRANS2_GET_DFS_REFERRAL);
3129 byte_count = params + 3 /* pad */ ;
3130 pSMB->ParameterCount = cpu_to_le16(params);
3131 pSMB->TotalParameterCount = pSMB->ParameterCount;
3132 pSMB->MaxReferralLevel = cpu_to_le16(3);
3133 pSMB->hdr.smb_buf_length += byte_count;
3134 pSMB->ByteCount = cpu_to_le16(byte_count);
3136 rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB,
3137 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3139 cFYI(1, ("Send error in GetDFSRefer = %d", rc));
3140 } else { /* decode response */
3141 /* BB Add logic to parse referrals here */
3142 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3144 if (rc || (pSMBr->ByteCount < 17)) /* BB also check enough total bytes returned */
3145 rc = -EIO; /* bad smb */
3147 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3148 __u16 data_count = le16_to_cpu(pSMBr->t2.DataCount);
3151 ("Decoding GetDFSRefer response. BCC: %d Offset %d",
3152 pSMBr->ByteCount, data_offset));
3154 (struct dfs_referral_level_3 *)
3155 (8 /* sizeof start of data block */ +
3157 (char *) &pSMBr->hdr.Protocol);
3158 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",
3159 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)));
3160 /* BB This field is actually two bytes in from start of
3161 data block so we could do safety check that DataBlock
3162 begins at address of pSMBr->NumberOfReferrals */
3163 *number_of_UNC_in_array = le16_to_cpu(pSMBr->NumberOfReferrals);
3165 /* BB Fix below so can return more than one referral */
3166 if(*number_of_UNC_in_array > 1)
3167 *number_of_UNC_in_array = 1;
3169 /* get the length of the strings describing refs */
3171 for(i=0;i<*number_of_UNC_in_array;i++) {
3172 /* make sure that DfsPathOffset not past end */
3173 __u16 offset = le16_to_cpu(referrals->DfsPathOffset);
3174 if (offset > data_count) {
3175 /* if invalid referral, stop here and do
3176 not try to copy any more */
3177 *number_of_UNC_in_array = i;
3180 temp = ((char *)referrals) + offset;
3182 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
3183 name_len += UniStrnlen((wchar_t *)temp,data_count);
3185 name_len += strnlen(temp,data_count);
3188 /* BB add check that referral pointer does not fall off end PDU */
3191 /* BB add check for name_len bigger than bcc */
3193 kmalloc(name_len+1+ (*number_of_UNC_in_array),GFP_KERNEL);
3194 if(*targetUNCs == NULL) {
3198 /* copy the ref strings */
3200 (struct dfs_referral_level_3 *)
3201 (8 /* sizeof data hdr */ +
3203 (char *) &pSMBr->hdr.Protocol);
3205 for(i=0;i<*number_of_UNC_in_array;i++) {
3206 temp = ((char *)referrals) + le16_to_cpu(referrals->DfsPathOffset);
3207 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
3208 cifs_strfromUCS_le(*targetUNCs,
3209 (__le16 *) temp, name_len, nls_codepage);
3211 strncpy(*targetUNCs,temp,name_len);
3213 /* BB update target_uncs pointers */
3223 cifs_buf_release(pSMB);
3231 /* Query File System Info such as free space to old servers such as Win 9x */
3233 SMBOldQFSInfo(const int xid, struct cifsTconInfo *tcon, struct kstatfs *FSData)
3235 /* level 0x01 SMB_QUERY_FILE_SYSTEM_INFO */
3236 TRANSACTION2_QFSI_REQ *pSMB = NULL;
3237 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
3238 FILE_SYSTEM_ALLOC_INFO *response_data;
3240 int bytes_returned = 0;
3241 __u16 params, byte_count;
3243 cFYI(1, ("OldQFSInfo"));
3245 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3249 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3254 params = 2; /* level */
3255 pSMB->TotalDataCount = 0;
3256 pSMB->MaxParameterCount = cpu_to_le16(2);
3257 pSMB->MaxDataCount = cpu_to_le16(1000);
3258 pSMB->MaxSetupCount = 0;
3262 pSMB->Reserved2 = 0;
3263 byte_count = params + 1 /* pad */ ;
3264 pSMB->TotalParameterCount = cpu_to_le16(params);
3265 pSMB->ParameterCount = pSMB->TotalParameterCount;
3266 pSMB->ParameterOffset = cpu_to_le16(offsetof(
3267 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
3268 pSMB->DataCount = 0;
3269 pSMB->DataOffset = 0;
3270 pSMB->SetupCount = 1;
3271 pSMB->Reserved3 = 0;
3272 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
3273 pSMB->InformationLevel = cpu_to_le16(SMB_INFO_ALLOCATION);
3274 pSMB->hdr.smb_buf_length += byte_count;
3275 pSMB->ByteCount = cpu_to_le16(byte_count);
3277 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3278 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3280 cFYI(1, ("Send error in QFSInfo = %d", rc));
3281 } else { /* decode response */
3282 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3284 if (rc || (pSMBr->ByteCount < 18))
3285 rc = -EIO; /* bad smb */
3287 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3288 cFYI(1,("qfsinf resp BCC: %d Offset %d",
3289 pSMBr->ByteCount, data_offset));
3292 (FILE_SYSTEM_ALLOC_INFO *)
3293 (((char *) &pSMBr->hdr.Protocol) + data_offset);
3295 le16_to_cpu(response_data->BytesPerSector) *
3296 le32_to_cpu(response_data->
3297 SectorsPerAllocationUnit);
3299 le32_to_cpu(response_data->TotalAllocationUnits);
3300 FSData->f_bfree = FSData->f_bavail =
3301 le32_to_cpu(response_data->FreeAllocationUnits);
3303 ("Blocks: %lld Free: %lld Block size %ld",
3304 (unsigned long long)FSData->f_blocks,
3305 (unsigned long long)FSData->f_bfree,
3309 cifs_buf_release(pSMB);
3312 goto oldQFSInfoRetry;
3318 CIFSSMBQFSInfo(const int xid, struct cifsTconInfo *tcon, struct kstatfs *FSData)
3320 /* level 0x103 SMB_QUERY_FILE_SYSTEM_INFO */
3321 TRANSACTION2_QFSI_REQ *pSMB = NULL;
3322 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
3323 FILE_SYSTEM_INFO *response_data;
3325 int bytes_returned = 0;
3326 __u16 params, byte_count;
3328 cFYI(1, ("In QFSInfo"));
3330 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3335 params = 2; /* level */
3336 pSMB->TotalDataCount = 0;
3337 pSMB->MaxParameterCount = cpu_to_le16(2);
3338 pSMB->MaxDataCount = cpu_to_le16(1000);
3339 pSMB->MaxSetupCount = 0;
3343 pSMB->Reserved2 = 0;
3344 byte_count = params + 1 /* pad */ ;
3345 pSMB->TotalParameterCount = cpu_to_le16(params);
3346 pSMB->ParameterCount = pSMB->TotalParameterCount;
3347 pSMB->ParameterOffset = cpu_to_le16(offsetof(
3348 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
3349 pSMB->DataCount = 0;
3350 pSMB->DataOffset = 0;
3351 pSMB->SetupCount = 1;
3352 pSMB->Reserved3 = 0;
3353 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
3354 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_SIZE_INFO);
3355 pSMB->hdr.smb_buf_length += byte_count;
3356 pSMB->ByteCount = cpu_to_le16(byte_count);
3358 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3359 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3361 cFYI(1, ("Send error in QFSInfo = %d", rc));
3362 } else { /* decode response */
3363 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3365 if (rc || (pSMBr->ByteCount < 24))
3366 rc = -EIO; /* bad smb */
3368 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3372 *) (((char *) &pSMBr->hdr.Protocol) +
3375 le32_to_cpu(response_data->BytesPerSector) *
3376 le32_to_cpu(response_data->
3377 SectorsPerAllocationUnit);
3379 le64_to_cpu(response_data->TotalAllocationUnits);
3380 FSData->f_bfree = FSData->f_bavail =
3381 le64_to_cpu(response_data->FreeAllocationUnits);
3383 ("Blocks: %lld Free: %lld Block size %ld",
3384 (unsigned long long)FSData->f_blocks,
3385 (unsigned long long)FSData->f_bfree,
3389 cifs_buf_release(pSMB);
3398 CIFSSMBQFSAttributeInfo(const int xid, struct cifsTconInfo *tcon)
3400 /* level 0x105 SMB_QUERY_FILE_SYSTEM_INFO */
3401 TRANSACTION2_QFSI_REQ *pSMB = NULL;
3402 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
3403 FILE_SYSTEM_ATTRIBUTE_INFO *response_data;
3405 int bytes_returned = 0;
3406 __u16 params, byte_count;
3408 cFYI(1, ("In QFSAttributeInfo"));
3410 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3415 params = 2; /* level */
3416 pSMB->TotalDataCount = 0;
3417 pSMB->MaxParameterCount = cpu_to_le16(2);
3418 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
3419 pSMB->MaxSetupCount = 0;
3423 pSMB->Reserved2 = 0;
3424 byte_count = params + 1 /* pad */ ;
3425 pSMB->TotalParameterCount = cpu_to_le16(params);
3426 pSMB->ParameterCount = pSMB->TotalParameterCount;
3427 pSMB->ParameterOffset = cpu_to_le16(offsetof(
3428 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
3429 pSMB->DataCount = 0;
3430 pSMB->DataOffset = 0;
3431 pSMB->SetupCount = 1;
3432 pSMB->Reserved3 = 0;
3433 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
3434 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_ATTRIBUTE_INFO);
3435 pSMB->hdr.smb_buf_length += byte_count;
3436 pSMB->ByteCount = cpu_to_le16(byte_count);
3438 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3439 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3441 cERROR(1, ("Send error in QFSAttributeInfo = %d", rc));
3442 } else { /* decode response */
3443 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3445 if (rc || (pSMBr->ByteCount < 13)) { /* BB also check enough bytes returned */
3446 rc = -EIO; /* bad smb */
3448 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3450 (FILE_SYSTEM_ATTRIBUTE_INFO
3451 *) (((char *) &pSMBr->hdr.Protocol) +
3453 memcpy(&tcon->fsAttrInfo, response_data,
3454 sizeof (FILE_SYSTEM_ATTRIBUTE_INFO));
3457 cifs_buf_release(pSMB);
3460 goto QFSAttributeRetry;
3466 CIFSSMBQFSDeviceInfo(const int xid, struct cifsTconInfo *tcon)
3468 /* level 0x104 SMB_QUERY_FILE_SYSTEM_INFO */
3469 TRANSACTION2_QFSI_REQ *pSMB = NULL;
3470 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
3471 FILE_SYSTEM_DEVICE_INFO *response_data;
3473 int bytes_returned = 0;
3474 __u16 params, byte_count;
3476 cFYI(1, ("In QFSDeviceInfo"));
3478 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3483 params = 2; /* level */
3484 pSMB->TotalDataCount = 0;
3485 pSMB->MaxParameterCount = cpu_to_le16(2);
3486 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
3487 pSMB->MaxSetupCount = 0;
3491 pSMB->Reserved2 = 0;
3492 byte_count = params + 1 /* pad */ ;
3493 pSMB->TotalParameterCount = cpu_to_le16(params);
3494 pSMB->ParameterCount = pSMB->TotalParameterCount;
3495 pSMB->ParameterOffset = cpu_to_le16(offsetof(
3496 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
3498 pSMB->DataCount = 0;
3499 pSMB->DataOffset = 0;
3500 pSMB->SetupCount = 1;
3501 pSMB->Reserved3 = 0;
3502 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
3503 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_DEVICE_INFO);
3504 pSMB->hdr.smb_buf_length += byte_count;
3505 pSMB->ByteCount = cpu_to_le16(byte_count);
3507 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3508 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3510 cFYI(1, ("Send error in QFSDeviceInfo = %d", rc));
3511 } else { /* decode response */
3512 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3514 if (rc || (pSMBr->ByteCount < sizeof (FILE_SYSTEM_DEVICE_INFO)))
3515 rc = -EIO; /* bad smb */
3517 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3519 (FILE_SYSTEM_DEVICE_INFO *)
3520 (((char *) &pSMBr->hdr.Protocol) +
3522 memcpy(&tcon->fsDevInfo, response_data,
3523 sizeof (FILE_SYSTEM_DEVICE_INFO));
3526 cifs_buf_release(pSMB);
3529 goto QFSDeviceRetry;
3535 CIFSSMBQFSUnixInfo(const int xid, struct cifsTconInfo *tcon)
3537 /* level 0x200 SMB_QUERY_CIFS_UNIX_INFO */
3538 TRANSACTION2_QFSI_REQ *pSMB = NULL;
3539 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
3540 FILE_SYSTEM_UNIX_INFO *response_data;
3542 int bytes_returned = 0;
3543 __u16 params, byte_count;
3545 cFYI(1, ("In QFSUnixInfo"));
3547 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3552 params = 2; /* level */
3553 pSMB->TotalDataCount = 0;
3554 pSMB->DataCount = 0;
3555 pSMB->DataOffset = 0;
3556 pSMB->MaxParameterCount = cpu_to_le16(2);
3557 pSMB->MaxDataCount = cpu_to_le16(100); /* BB find exact max SMB PDU from sess structure BB */
3558 pSMB->MaxSetupCount = 0;
3562 pSMB->Reserved2 = 0;
3563 byte_count = params + 1 /* pad */ ;
3564 pSMB->ParameterCount = cpu_to_le16(params);
3565 pSMB->TotalParameterCount = pSMB->ParameterCount;
3566 pSMB->ParameterOffset = cpu_to_le16(offsetof(struct
3567 smb_com_transaction2_qfsi_req, InformationLevel) - 4);
3568 pSMB->SetupCount = 1;
3569 pSMB->Reserved3 = 0;
3570 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
3571 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_CIFS_UNIX_INFO);
3572 pSMB->hdr.smb_buf_length += byte_count;
3573 pSMB->ByteCount = cpu_to_le16(byte_count);
3575 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3576 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3578 cERROR(1, ("Send error in QFSUnixInfo = %d", rc));
3579 } else { /* decode response */
3580 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3582 if (rc || (pSMBr->ByteCount < 13)) {
3583 rc = -EIO; /* bad smb */
3585 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3587 (FILE_SYSTEM_UNIX_INFO
3588 *) (((char *) &pSMBr->hdr.Protocol) +
3590 memcpy(&tcon->fsUnixInfo, response_data,
3591 sizeof (FILE_SYSTEM_UNIX_INFO));
3594 cifs_buf_release(pSMB);
3604 CIFSSMBSetFSUnixInfo(const int xid, struct cifsTconInfo *tcon, __u64 cap)
3606 /* level 0x200 SMB_SET_CIFS_UNIX_INFO */
3607 TRANSACTION2_SETFSI_REQ *pSMB = NULL;
3608 TRANSACTION2_SETFSI_RSP *pSMBr = NULL;
3610 int bytes_returned = 0;
3611 __u16 params, param_offset, offset, byte_count;
3613 cFYI(1, ("In SETFSUnixInfo"));
3615 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3620 params = 4; /* 2 bytes zero followed by info level. */
3621 pSMB->MaxSetupCount = 0;
3625 pSMB->Reserved2 = 0;
3626 param_offset = offsetof(struct smb_com_transaction2_setfsi_req, FileNum) - 4;
3627 offset = param_offset + params;
3629 pSMB->MaxParameterCount = cpu_to_le16(4);
3630 pSMB->MaxDataCount = cpu_to_le16(100); /* BB find exact max SMB PDU from sess structure BB */
3631 pSMB->SetupCount = 1;
3632 pSMB->Reserved3 = 0;
3633 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FS_INFORMATION);
3634 byte_count = 1 /* pad */ + params + 12;
3636 pSMB->DataCount = cpu_to_le16(12);
3637 pSMB->ParameterCount = cpu_to_le16(params);
3638 pSMB->TotalDataCount = pSMB->DataCount;
3639 pSMB->TotalParameterCount = pSMB->ParameterCount;
3640 pSMB->ParameterOffset = cpu_to_le16(param_offset);
3641 pSMB->DataOffset = cpu_to_le16(offset);
3645 pSMB->InformationLevel = cpu_to_le16(SMB_SET_CIFS_UNIX_INFO);
3648 pSMB->ClientUnixMajor = cpu_to_le16(CIFS_UNIX_MAJOR_VERSION);
3649 pSMB->ClientUnixMinor = cpu_to_le16(CIFS_UNIX_MINOR_VERSION);
3650 pSMB->ClientUnixCap = cpu_to_le64(cap);
3652 pSMB->hdr.smb_buf_length += byte_count;
3653 pSMB->ByteCount = cpu_to_le16(byte_count);
3655 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3656 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3658 cERROR(1, ("Send error in SETFSUnixInfo = %d", rc));
3659 } else { /* decode response */
3660 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3662 rc = -EIO; /* bad smb */
3665 cifs_buf_release(pSMB);
3668 goto SETFSUnixRetry;
3676 CIFSSMBQFSPosixInfo(const int xid, struct cifsTconInfo *tcon,
3677 struct kstatfs *FSData)
3679 /* level 0x201 SMB_QUERY_CIFS_POSIX_INFO */
3680 TRANSACTION2_QFSI_REQ *pSMB = NULL;
3681 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
3682 FILE_SYSTEM_POSIX_INFO *response_data;
3684 int bytes_returned = 0;
3685 __u16 params, byte_count;
3687 cFYI(1, ("In QFSPosixInfo"));
3689 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3694 params = 2; /* level */
3695 pSMB->TotalDataCount = 0;
3696 pSMB->DataCount = 0;
3697 pSMB->DataOffset = 0;
3698 pSMB->MaxParameterCount = cpu_to_le16(2);
3699 pSMB->MaxDataCount = cpu_to_le16(100); /* BB find exact max SMB PDU from sess structure BB */
3700 pSMB->MaxSetupCount = 0;
3704 pSMB->Reserved2 = 0;
3705 byte_count = params + 1 /* pad */ ;
3706 pSMB->ParameterCount = cpu_to_le16(params);
3707 pSMB->TotalParameterCount = pSMB->ParameterCount;
3708 pSMB->ParameterOffset = cpu_to_le16(offsetof(struct
3709 smb_com_transaction2_qfsi_req, InformationLevel) - 4);
3710 pSMB->SetupCount = 1;
3711 pSMB->Reserved3 = 0;
3712 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
3713 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_POSIX_FS_INFO);
3714 pSMB->hdr.smb_buf_length += byte_count;
3715 pSMB->ByteCount = cpu_to_le16(byte_count);
3717 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3718 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3720 cFYI(1, ("Send error in QFSUnixInfo = %d", rc));
3721 } else { /* decode response */
3722 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3724 if (rc || (pSMBr->ByteCount < 13)) {
3725 rc = -EIO; /* bad smb */
3727 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3729 (FILE_SYSTEM_POSIX_INFO
3730 *) (((char *) &pSMBr->hdr.Protocol) +
3733 le32_to_cpu(response_data->BlockSize);
3735 le64_to_cpu(response_data->TotalBlocks);
3737 le64_to_cpu(response_data->BlocksAvail);
3738 if(response_data->UserBlocksAvail == cpu_to_le64(-1)) {
3739 FSData->f_bavail = FSData->f_bfree;
3742 le64_to_cpu(response_data->UserBlocksAvail);
3744 if(response_data->TotalFileNodes != cpu_to_le64(-1))
3746 le64_to_cpu(response_data->TotalFileNodes);
3747 if(response_data->FreeFileNodes != cpu_to_le64(-1))
3749 le64_to_cpu(response_data->FreeFileNodes);
3752 cifs_buf_release(pSMB);
3761 /* We can not use write of zero bytes trick to
3762 set file size due to need for large file support. Also note that
3763 this SetPathInfo is preferred to SetFileInfo based method in next
3764 routine which is only needed to work around a sharing violation bug
3765 in Samba which this routine can run into */
3768 CIFSSMBSetEOF(const int xid, struct cifsTconInfo *tcon, const char *fileName,
3769 __u64 size, int SetAllocation,
3770 const struct nls_table *nls_codepage, int remap)
3772 struct smb_com_transaction2_spi_req *pSMB = NULL;
3773 struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
3774 struct file_end_of_file_info *parm_data;
3777 int bytes_returned = 0;
3778 __u16 params, byte_count, data_count, param_offset, offset;
3780 cFYI(1, ("In SetEOF"));
3782 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3787 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3789 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
3790 PATH_MAX, nls_codepage, remap);
3791 name_len++; /* trailing null */
3793 } else { /* BB improve the check for buffer overruns BB */
3794 name_len = strnlen(fileName, PATH_MAX);
3795 name_len++; /* trailing null */
3796 strncpy(pSMB->FileName, fileName, name_len);
3798 params = 6 + name_len;
3799 data_count = sizeof (struct file_end_of_file_info);
3800 pSMB->MaxParameterCount = cpu_to_le16(2);
3801 pSMB->MaxDataCount = cpu_to_le16(4100);
3802 pSMB->MaxSetupCount = 0;
3806 pSMB->Reserved2 = 0;
3807 param_offset = offsetof(struct smb_com_transaction2_spi_req,
3808 InformationLevel) - 4;
3809 offset = param_offset + params;
3811 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
3812 pSMB->InformationLevel =
3813 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2);
3815 pSMB->InformationLevel =
3816 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO);
3817 } else /* Set File Size */ {
3818 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
3819 pSMB->InformationLevel =
3820 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO2);
3822 pSMB->InformationLevel =
3823 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO);
3827 (struct file_end_of_file_info *) (((char *) &pSMB->hdr.Protocol) +
3829 pSMB->ParameterOffset = cpu_to_le16(param_offset);
3830 pSMB->DataOffset = cpu_to_le16(offset);
3831 pSMB->SetupCount = 1;
3832 pSMB->Reserved3 = 0;
3833 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
3834 byte_count = 3 /* pad */ + params + data_count;
3835 pSMB->DataCount = cpu_to_le16(data_count);
3836 pSMB->TotalDataCount = pSMB->DataCount;
3837 pSMB->ParameterCount = cpu_to_le16(params);
3838 pSMB->TotalParameterCount = pSMB->ParameterCount;
3839 pSMB->Reserved4 = 0;
3840 pSMB->hdr.smb_buf_length += byte_count;
3841 parm_data->FileSize = cpu_to_le64(size);
3842 pSMB->ByteCount = cpu_to_le16(byte_count);
3843 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3844 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3846 cFYI(1, ("SetPathInfo (file size) returned %d", rc));
3849 cifs_buf_release(pSMB);
3858 CIFSSMBSetFileSize(const int xid, struct cifsTconInfo *tcon, __u64 size,
3859 __u16 fid, __u32 pid_of_opener, int SetAllocation)
3861 struct smb_com_transaction2_sfi_req *pSMB = NULL;
3862 struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
3864 struct file_end_of_file_info *parm_data;
3866 int bytes_returned = 0;
3867 __u16 params, param_offset, offset, byte_count, count;
3869 cFYI(1, ("SetFileSize (via SetFileInfo) %lld",
3871 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
3876 pSMBr = (struct smb_com_transaction2_sfi_rsp *)pSMB;
3878 pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
3879 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));
3882 pSMB->MaxSetupCount = 0;
3886 pSMB->Reserved2 = 0;
3887 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
3888 offset = param_offset + params;
3890 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
3892 count = sizeof(struct file_end_of_file_info);
3893 pSMB->MaxParameterCount = cpu_to_le16(2);
3894 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB PDU from sess */
3895 pSMB->SetupCount = 1;
3896 pSMB->Reserved3 = 0;
3897 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
3898 byte_count = 3 /* pad */ + params + count;
3899 pSMB->DataCount = cpu_to_le16(count);
3900 pSMB->ParameterCount = cpu_to_le16(params);
3901 pSMB->TotalDataCount = pSMB->DataCount;
3902 pSMB->TotalParameterCount = pSMB->ParameterCount;
3903 pSMB->ParameterOffset = cpu_to_le16(param_offset);
3905 (struct file_end_of_file_info *) (((char *) &pSMB->hdr.Protocol) +
3907 pSMB->DataOffset = cpu_to_le16(offset);
3908 parm_data->FileSize = cpu_to_le64(size);
3911 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
3912 pSMB->InformationLevel =
3913 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2);
3915 pSMB->InformationLevel =
3916 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO);
3917 } else /* Set File Size */ {
3918 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
3919 pSMB->InformationLevel =
3920 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO2);
3922 pSMB->InformationLevel =
3923 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO);
3925 pSMB->Reserved4 = 0;
3926 pSMB->hdr.smb_buf_length += byte_count;
3927 pSMB->ByteCount = cpu_to_le16(byte_count);
3928 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3929 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3932 ("Send error in SetFileInfo (SetFileSize) = %d",
3937 cifs_small_buf_release(pSMB);
3939 /* Note: On -EAGAIN error only caller can retry on handle based calls
3940 since file handle passed in no longer valid */
3945 /* Some legacy servers such as NT4 require that the file times be set on
3946 an open handle, rather than by pathname - this is awkward due to
3947 potential access conflicts on the open, but it is unavoidable for these
3948 old servers since the only other choice is to go from 100 nanosecond DCE
3949 time and resort to the original setpathinfo level which takes the ancient
3950 DOS time format with 2 second granularity */
3952 CIFSSMBSetFileTimes(const int xid, struct cifsTconInfo *tcon, const FILE_BASIC_INFO * data,
3955 struct smb_com_transaction2_sfi_req *pSMB = NULL;
3956 struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
3959 int bytes_returned = 0;
3960 __u16 params, param_offset, offset, byte_count, count;
3962 cFYI(1, ("Set Times (via SetFileInfo)"));
3963 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
3968 pSMBr = (struct smb_com_transaction2_sfi_rsp *)pSMB;
3970 /* At this point there is no need to override the current pid
3971 with the pid of the opener, but that could change if we someday
3972 use an existing handle (rather than opening one on the fly) */
3973 /* pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
3974 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));*/
3977 pSMB->MaxSetupCount = 0;
3981 pSMB->Reserved2 = 0;
3982 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
3983 offset = param_offset + params;
3985 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
3987 count = sizeof (FILE_BASIC_INFO);
3988 pSMB->MaxParameterCount = cpu_to_le16(2);
3989 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB PDU from sess */
3990 pSMB->SetupCount = 1;
3991 pSMB->Reserved3 = 0;
3992 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
3993 byte_count = 3 /* pad */ + params + count;
3994 pSMB->DataCount = cpu_to_le16(count);
3995 pSMB->ParameterCount = cpu_to_le16(params);
3996 pSMB->TotalDataCount = pSMB->DataCount;
3997 pSMB->TotalParameterCount = pSMB->ParameterCount;
3998 pSMB->ParameterOffset = cpu_to_le16(param_offset);
3999 pSMB->DataOffset = cpu_to_le16(offset);
4001 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
4002 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO2);
4004 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO);
4005 pSMB->Reserved4 = 0;
4006 pSMB->hdr.smb_buf_length += byte_count;
4007 pSMB->ByteCount = cpu_to_le16(byte_count);
4008 memcpy(data_offset,data,sizeof(FILE_BASIC_INFO));
4009 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4010 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4012 cFYI(1,("Send error in Set Time (SetFileInfo) = %d",rc));
4015 cifs_small_buf_release(pSMB);
4017 /* Note: On -EAGAIN error only caller can retry on handle based calls
4018 since file handle passed in no longer valid */
4025 CIFSSMBSetTimes(const int xid, struct cifsTconInfo *tcon, const char *fileName,
4026 const FILE_BASIC_INFO * data,
4027 const struct nls_table *nls_codepage, int remap)
4029 TRANSACTION2_SPI_REQ *pSMB = NULL;
4030 TRANSACTION2_SPI_RSP *pSMBr = NULL;
4033 int bytes_returned = 0;
4035 __u16 params, param_offset, offset, byte_count, count;
4037 cFYI(1, ("In SetTimes"));
4040 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4045 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4047 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
4048 PATH_MAX, nls_codepage, remap);
4049 name_len++; /* trailing null */
4051 } else { /* BB improve the check for buffer overruns BB */
4052 name_len = strnlen(fileName, PATH_MAX);
4053 name_len++; /* trailing null */
4054 strncpy(pSMB->FileName, fileName, name_len);
4057 params = 6 + name_len;
4058 count = sizeof (FILE_BASIC_INFO);
4059 pSMB->MaxParameterCount = cpu_to_le16(2);
4060 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
4061 pSMB->MaxSetupCount = 0;
4065 pSMB->Reserved2 = 0;
4066 param_offset = offsetof(struct smb_com_transaction2_spi_req,
4067 InformationLevel) - 4;
4068 offset = param_offset + params;
4069 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
4070 pSMB->ParameterOffset = cpu_to_le16(param_offset);
4071 pSMB->DataOffset = cpu_to_le16(offset);
4072 pSMB->SetupCount = 1;
4073 pSMB->Reserved3 = 0;
4074 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
4075 byte_count = 3 /* pad */ + params + count;
4077 pSMB->DataCount = cpu_to_le16(count);
4078 pSMB->ParameterCount = cpu_to_le16(params);
4079 pSMB->TotalDataCount = pSMB->DataCount;
4080 pSMB->TotalParameterCount = pSMB->ParameterCount;
4081 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
4082 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO2);
4084 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO);
4085 pSMB->Reserved4 = 0;
4086 pSMB->hdr.smb_buf_length += byte_count;
4087 memcpy(data_offset, data, sizeof (FILE_BASIC_INFO));
4088 pSMB->ByteCount = cpu_to_le16(byte_count);
4089 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4090 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4092 cFYI(1, ("SetPathInfo (times) returned %d", rc));
4095 cifs_buf_release(pSMB);
4103 /* Can not be used to set time stamps yet (due to old DOS time format) */
4104 /* Can be used to set attributes */
4105 #if 0 /* Possibly not needed - since it turns out that strangely NT4 has a bug
4106 handling it anyway and NT4 was what we thought it would be needed for
4107 Do not delete it until we prove whether needed for Win9x though */
4109 CIFSSMBSetAttrLegacy(int xid, struct cifsTconInfo *tcon, char *fileName,
4110 __u16 dos_attrs, const struct nls_table *nls_codepage)
4112 SETATTR_REQ *pSMB = NULL;
4113 SETATTR_RSP *pSMBr = NULL;
4118 cFYI(1, ("In SetAttrLegacy"));
4121 rc = smb_init(SMB_COM_SETATTR, 8, tcon, (void **) &pSMB,
4126 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4128 ConvertToUCS((__le16 *) pSMB->fileName, fileName,
4129 PATH_MAX, nls_codepage);
4130 name_len++; /* trailing null */
4132 } else { /* BB improve the check for buffer overruns BB */
4133 name_len = strnlen(fileName, PATH_MAX);
4134 name_len++; /* trailing null */
4135 strncpy(pSMB->fileName, fileName, name_len);
4137 pSMB->attr = cpu_to_le16(dos_attrs);
4138 pSMB->BufferFormat = 0x04;
4139 pSMB->hdr.smb_buf_length += name_len + 1;
4140 pSMB->ByteCount = cpu_to_le16(name_len + 1);
4141 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4142 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4144 cFYI(1, ("Error in LegacySetAttr = %d", rc));
4147 cifs_buf_release(pSMB);
4150 goto SetAttrLgcyRetry;
4154 #endif /* temporarily unneeded SetAttr legacy function */
4157 CIFSSMBUnixSetPerms(const int xid, struct cifsTconInfo *tcon,
4158 char *fileName, __u64 mode, __u64 uid, __u64 gid,
4159 dev_t device, const struct nls_table *nls_codepage,
4162 TRANSACTION2_SPI_REQ *pSMB = NULL;
4163 TRANSACTION2_SPI_RSP *pSMBr = NULL;
4166 int bytes_returned = 0;
4167 FILE_UNIX_BASIC_INFO *data_offset;
4168 __u16 params, param_offset, offset, count, byte_count;
4170 cFYI(1, ("In SetUID/GID/Mode"));
4172 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4177 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4179 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
4180 PATH_MAX, nls_codepage, remap);
4181 name_len++; /* trailing null */
4183 } else { /* BB improve the check for buffer overruns BB */
4184 name_len = strnlen(fileName, PATH_MAX);
4185 name_len++; /* trailing null */
4186 strncpy(pSMB->FileName, fileName, name_len);
4189 params = 6 + name_len;
4190 count = sizeof (FILE_UNIX_BASIC_INFO);
4191 pSMB->MaxParameterCount = cpu_to_le16(2);
4192 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
4193 pSMB->MaxSetupCount = 0;
4197 pSMB->Reserved2 = 0;
4198 param_offset = offsetof(struct smb_com_transaction2_spi_req,
4199 InformationLevel) - 4;
4200 offset = param_offset + params;
4202 (FILE_UNIX_BASIC_INFO *) ((char *) &pSMB->hdr.Protocol +
4204 memset(data_offset, 0, count);
4205 pSMB->DataOffset = cpu_to_le16(offset);
4206 pSMB->ParameterOffset = cpu_to_le16(param_offset);
4207 pSMB->SetupCount = 1;
4208 pSMB->Reserved3 = 0;
4209 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
4210 byte_count = 3 /* pad */ + params + count;
4211 pSMB->ParameterCount = cpu_to_le16(params);
4212 pSMB->DataCount = cpu_to_le16(count);
4213 pSMB->TotalParameterCount = pSMB->ParameterCount;
4214 pSMB->TotalDataCount = pSMB->DataCount;
4215 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_BASIC);
4216 pSMB->Reserved4 = 0;
4217 pSMB->hdr.smb_buf_length += byte_count;
4218 data_offset->Uid = cpu_to_le64(uid);
4219 data_offset->Gid = cpu_to_le64(gid);
4220 /* better to leave device as zero when it is */
4221 data_offset->DevMajor = cpu_to_le64(MAJOR(device));
4222 data_offset->DevMinor = cpu_to_le64(MINOR(device));
4223 data_offset->Permissions = cpu_to_le64(mode);
4226 data_offset->Type = cpu_to_le32(UNIX_FILE);
4227 else if(S_ISDIR(mode))
4228 data_offset->Type = cpu_to_le32(UNIX_DIR);
4229 else if(S_ISLNK(mode))
4230 data_offset->Type = cpu_to_le32(UNIX_SYMLINK);
4231 else if(S_ISCHR(mode))
4232 data_offset->Type = cpu_to_le32(UNIX_CHARDEV);
4233 else if(S_ISBLK(mode))
4234 data_offset->Type = cpu_to_le32(UNIX_BLOCKDEV);
4235 else if(S_ISFIFO(mode))
4236 data_offset->Type = cpu_to_le32(UNIX_FIFO);
4237 else if(S_ISSOCK(mode))
4238 data_offset->Type = cpu_to_le32(UNIX_SOCKET);
4241 pSMB->ByteCount = cpu_to_le16(byte_count);
4242 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4243 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4245 cFYI(1, ("SetPathInfo (perms) returned %d", rc));
4249 cifs_buf_release(pSMB);
4255 int CIFSSMBNotify(const int xid, struct cifsTconInfo *tcon,
4256 const int notify_subdirs, const __u16 netfid,
4257 __u32 filter, struct file * pfile, int multishot,
4258 const struct nls_table *nls_codepage)
4261 struct smb_com_transaction_change_notify_req * pSMB = NULL;
4262 struct smb_com_transaction_change_notify_rsp * pSMBr = NULL;
4263 struct dir_notify_req *dnotify_req;
4266 cFYI(1, ("In CIFSSMBNotify for file handle %d",(int)netfid));
4267 rc = smb_init(SMB_COM_NT_TRANSACT, 23, tcon, (void **) &pSMB,
4272 pSMB->TotalParameterCount = 0 ;
4273 pSMB->TotalDataCount = 0;
4274 pSMB->MaxParameterCount = cpu_to_le32(2);
4275 /* BB find exact data count max from sess structure BB */
4276 pSMB->MaxDataCount = 0; /* same in little endian or be */
4277 pSMB->MaxSetupCount = 4;
4279 pSMB->ParameterOffset = 0;
4280 pSMB->DataCount = 0;
4281 pSMB->DataOffset = 0;
4282 pSMB->SetupCount = 4; /* single byte does not need le conversion */
4283 pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_NOTIFY_CHANGE);
4284 pSMB->ParameterCount = pSMB->TotalParameterCount;
4286 pSMB->WatchTree = 1; /* one byte - no le conversion needed */
4287 pSMB->Reserved2 = 0;
4288 pSMB->CompletionFilter = cpu_to_le32(filter);
4289 pSMB->Fid = netfid; /* file handle always le */
4290 pSMB->ByteCount = 0;
4292 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4293 (struct smb_hdr *) pSMBr, &bytes_returned, -1);
4295 cFYI(1, ("Error in Notify = %d", rc));
4297 /* Add file to outstanding requests */
4298 /* BB change to kmem cache alloc */
4299 dnotify_req = (struct dir_notify_req *) kmalloc(
4300 sizeof(struct dir_notify_req),
4303 dnotify_req->Pid = pSMB->hdr.Pid;
4304 dnotify_req->PidHigh = pSMB->hdr.PidHigh;
4305 dnotify_req->Mid = pSMB->hdr.Mid;
4306 dnotify_req->Tid = pSMB->hdr.Tid;
4307 dnotify_req->Uid = pSMB->hdr.Uid;
4308 dnotify_req->netfid = netfid;
4309 dnotify_req->pfile = pfile;
4310 dnotify_req->filter = filter;
4311 dnotify_req->multishot = multishot;
4312 spin_lock(&GlobalMid_Lock);
4313 list_add_tail(&dnotify_req->lhead,
4314 &GlobalDnotifyReqList);
4315 spin_unlock(&GlobalMid_Lock);
4319 cifs_buf_release(pSMB);
4322 #ifdef CONFIG_CIFS_XATTR
4324 CIFSSMBQAllEAs(const int xid, struct cifsTconInfo *tcon,
4325 const unsigned char *searchName,
4326 char * EAData, size_t buf_size,
4327 const struct nls_table *nls_codepage, int remap)
4329 /* BB assumes one setup word */
4330 TRANSACTION2_QPI_REQ *pSMB = NULL;
4331 TRANSACTION2_QPI_RSP *pSMBr = NULL;
4335 struct fea * temp_fea;
4337 __u16 params, byte_count;
4339 cFYI(1, ("In Query All EAs path %s", searchName));
4341 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4346 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4348 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
4349 PATH_MAX, nls_codepage, remap);
4350 name_len++; /* trailing null */
4352 } else { /* BB improve the check for buffer overruns BB */
4353 name_len = strnlen(searchName, PATH_MAX);
4354 name_len++; /* trailing null */
4355 strncpy(pSMB->FileName, searchName, name_len);
4358 params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */ ;
4359 pSMB->TotalDataCount = 0;
4360 pSMB->MaxParameterCount = cpu_to_le16(2);
4361 pSMB->MaxDataCount = cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
4362 pSMB->MaxSetupCount = 0;
4366 pSMB->Reserved2 = 0;
4367 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4368 struct smb_com_transaction2_qpi_req ,InformationLevel) - 4);
4369 pSMB->DataCount = 0;
4370 pSMB->DataOffset = 0;
4371 pSMB->SetupCount = 1;
4372 pSMB->Reserved3 = 0;
4373 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
4374 byte_count = params + 1 /* pad */ ;
4375 pSMB->TotalParameterCount = cpu_to_le16(params);
4376 pSMB->ParameterCount = pSMB->TotalParameterCount;
4377 pSMB->InformationLevel = cpu_to_le16(SMB_INFO_QUERY_ALL_EAS);
4378 pSMB->Reserved4 = 0;
4379 pSMB->hdr.smb_buf_length += byte_count;
4380 pSMB->ByteCount = cpu_to_le16(byte_count);
4382 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4383 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4385 cFYI(1, ("Send error in QueryAllEAs = %d", rc));
4386 } else { /* decode response */
4387 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4389 /* BB also check enough total bytes returned */
4390 /* BB we need to improve the validity checking
4391 of these trans2 responses */
4392 if (rc || (pSMBr->ByteCount < 4))
4393 rc = -EIO; /* bad smb */
4394 /* else if (pFindData){
4395 memcpy((char *) pFindData,
4396 (char *) &pSMBr->hdr.Protocol +
4399 /* check that length of list is not more than bcc */
4400 /* check that each entry does not go beyond length
4402 /* check that each element of each entry does not
4403 go beyond end of list */
4404 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4405 struct fealist * ea_response_data;
4407 /* validate_trans2_offsets() */
4408 /* BB to check if(start of smb + data_offset > &bcc+ bcc)*/
4409 ea_response_data = (struct fealist *)
4410 (((char *) &pSMBr->hdr.Protocol) +
4412 name_len = le32_to_cpu(ea_response_data->list_len);
4413 cFYI(1,("ea length %d", name_len));
4415 /* returned EA size zeroed at top of function */
4416 cFYI(1,("empty EA list returned from server"));
4418 /* account for ea list len */
4420 temp_fea = ea_response_data->list;
4421 temp_ptr = (char *)temp_fea;
4422 while(name_len > 0) {
4426 rc += temp_fea->name_len;
4427 /* account for prefix user. and trailing null */
4429 if(rc<(int)buf_size) {
4430 memcpy(EAData,"user.",5);
4432 memcpy(EAData,temp_ptr,temp_fea->name_len);
4433 EAData+=temp_fea->name_len;
4434 /* null terminate name */
4436 EAData = EAData + 1;
4437 } else if(buf_size == 0) {
4438 /* skip copy - calc size only */
4440 /* stop before overrun buffer */
4444 name_len -= temp_fea->name_len;
4445 temp_ptr += temp_fea->name_len;
4446 /* account for trailing null */
4449 value_len = le16_to_cpu(temp_fea->value_len);
4450 name_len -= value_len;
4451 temp_ptr += value_len;
4452 /* BB check that temp_ptr is still within smb BB*/
4453 /* no trailing null to account for in value len */
4454 /* go on to next EA */
4455 temp_fea = (struct fea *)temp_ptr;
4461 cifs_buf_release(pSMB);
4468 ssize_t CIFSSMBQueryEA(const int xid,struct cifsTconInfo * tcon,
4469 const unsigned char * searchName,const unsigned char * ea_name,
4470 unsigned char * ea_value, size_t buf_size,
4471 const struct nls_table *nls_codepage, int remap)
4473 TRANSACTION2_QPI_REQ *pSMB = NULL;
4474 TRANSACTION2_QPI_RSP *pSMBr = NULL;
4478 struct fea * temp_fea;
4480 __u16 params, byte_count;
4482 cFYI(1, ("In Query EA path %s", searchName));
4484 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4489 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4491 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
4492 PATH_MAX, nls_codepage, remap);
4493 name_len++; /* trailing null */
4495 } else { /* BB improve the check for buffer overruns BB */
4496 name_len = strnlen(searchName, PATH_MAX);
4497 name_len++; /* trailing null */
4498 strncpy(pSMB->FileName, searchName, name_len);
4501 params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */ ;
4502 pSMB->TotalDataCount = 0;
4503 pSMB->MaxParameterCount = cpu_to_le16(2);
4504 pSMB->MaxDataCount = cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
4505 pSMB->MaxSetupCount = 0;
4509 pSMB->Reserved2 = 0;
4510 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4511 struct smb_com_transaction2_qpi_req ,InformationLevel) - 4);
4512 pSMB->DataCount = 0;
4513 pSMB->DataOffset = 0;
4514 pSMB->SetupCount = 1;
4515 pSMB->Reserved3 = 0;
4516 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
4517 byte_count = params + 1 /* pad */ ;
4518 pSMB->TotalParameterCount = cpu_to_le16(params);
4519 pSMB->ParameterCount = pSMB->TotalParameterCount;
4520 pSMB->InformationLevel = cpu_to_le16(SMB_INFO_QUERY_ALL_EAS);
4521 pSMB->Reserved4 = 0;
4522 pSMB->hdr.smb_buf_length += byte_count;
4523 pSMB->ByteCount = cpu_to_le16(byte_count);
4525 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4526 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4528 cFYI(1, ("Send error in Query EA = %d", rc));
4529 } else { /* decode response */
4530 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4532 /* BB also check enough total bytes returned */
4533 /* BB we need to improve the validity checking
4534 of these trans2 responses */
4535 if (rc || (pSMBr->ByteCount < 4))
4536 rc = -EIO; /* bad smb */
4537 /* else if (pFindData){
4538 memcpy((char *) pFindData,
4539 (char *) &pSMBr->hdr.Protocol +
4542 /* check that length of list is not more than bcc */
4543 /* check that each entry does not go beyond length
4545 /* check that each element of each entry does not
4546 go beyond end of list */
4547 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4548 struct fealist * ea_response_data;
4550 /* validate_trans2_offsets() */
4551 /* BB to check if(start of smb + data_offset > &bcc+ bcc)*/
4552 ea_response_data = (struct fealist *)
4553 (((char *) &pSMBr->hdr.Protocol) +
4555 name_len = le32_to_cpu(ea_response_data->list_len);
4556 cFYI(1,("ea length %d", name_len));
4558 /* returned EA size zeroed at top of function */
4559 cFYI(1,("empty EA list returned from server"));
4561 /* account for ea list len */
4563 temp_fea = ea_response_data->list;
4564 temp_ptr = (char *)temp_fea;
4565 /* loop through checking if we have a matching
4566 name and then return the associated value */
4567 while(name_len > 0) {
4571 value_len = le16_to_cpu(temp_fea->value_len);
4572 /* BB validate that value_len falls within SMB,
4573 even though maximum for name_len is 255 */
4574 if(memcmp(temp_fea->name,ea_name,
4575 temp_fea->name_len) == 0) {
4578 /* account for prefix user. and trailing null */
4579 if(rc<=(int)buf_size) {
4581 temp_fea->name+temp_fea->name_len+1,
4583 /* ea values, unlike ea names,
4584 are not null terminated */
4585 } else if(buf_size == 0) {
4586 /* skip copy - calc size only */
4588 /* stop before overrun buffer */
4593 name_len -= temp_fea->name_len;
4594 temp_ptr += temp_fea->name_len;
4595 /* account for trailing null */
4598 name_len -= value_len;
4599 temp_ptr += value_len;
4600 /* no trailing null to account for in value len */
4601 /* go on to next EA */
4602 temp_fea = (struct fea *)temp_ptr;
4608 cifs_buf_release(pSMB);
4616 CIFSSMBSetEA(const int xid, struct cifsTconInfo *tcon, const char *fileName,
4617 const char * ea_name, const void * ea_value,
4618 const __u16 ea_value_len, const struct nls_table *nls_codepage,
4621 struct smb_com_transaction2_spi_req *pSMB = NULL;
4622 struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
4623 struct fealist *parm_data;
4626 int bytes_returned = 0;
4627 __u16 params, param_offset, byte_count, offset, count;
4629 cFYI(1, ("In SetEA"));
4631 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4636 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4638 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
4639 PATH_MAX, nls_codepage, remap);
4640 name_len++; /* trailing null */
4642 } else { /* BB improve the check for buffer overruns BB */
4643 name_len = strnlen(fileName, PATH_MAX);
4644 name_len++; /* trailing null */
4645 strncpy(pSMB->FileName, fileName, name_len);
4648 params = 6 + name_len;
4650 /* done calculating parms using name_len of file name,
4651 now use name_len to calculate length of ea name
4652 we are going to create in the inode xattrs */
4656 name_len = strnlen(ea_name,255);
4658 count = sizeof(*parm_data) + ea_value_len + name_len + 1;
4659 pSMB->MaxParameterCount = cpu_to_le16(2);
4660 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB size from sess */
4661 pSMB->MaxSetupCount = 0;
4665 pSMB->Reserved2 = 0;
4666 param_offset = offsetof(struct smb_com_transaction2_spi_req,
4667 InformationLevel) - 4;
4668 offset = param_offset + params;
4669 pSMB->InformationLevel =
4670 cpu_to_le16(SMB_SET_FILE_EA);
4673 (struct fealist *) (((char *) &pSMB->hdr.Protocol) +
4675 pSMB->ParameterOffset = cpu_to_le16(param_offset);
4676 pSMB->DataOffset = cpu_to_le16(offset);
4677 pSMB->SetupCount = 1;
4678 pSMB->Reserved3 = 0;
4679 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
4680 byte_count = 3 /* pad */ + params + count;
4681 pSMB->DataCount = cpu_to_le16(count);
4682 parm_data->list_len = cpu_to_le32(count);
4683 parm_data->list[0].EA_flags = 0;
4684 /* we checked above that name len is less than 255 */
4685 parm_data->list[0].name_len = (__u8)name_len;;
4686 /* EA names are always ASCII */
4688 strncpy(parm_data->list[0].name,ea_name,name_len);
4689 parm_data->list[0].name[name_len] = 0;
4690 parm_data->list[0].value_len = cpu_to_le16(ea_value_len);
4691 /* caller ensures that ea_value_len is less than 64K but
4692 we need to ensure that it fits within the smb */
4694 /*BB add length check that it would fit in negotiated SMB buffer size BB */
4695 /* if(ea_value_len > buffer_size - 512 (enough for header)) */
4697 memcpy(parm_data->list[0].name+name_len+1,ea_value,ea_value_len);
4699 pSMB->TotalDataCount = pSMB->DataCount;
4700 pSMB->ParameterCount = cpu_to_le16(params);
4701 pSMB->TotalParameterCount = pSMB->ParameterCount;
4702 pSMB->Reserved4 = 0;
4703 pSMB->hdr.smb_buf_length += byte_count;
4704 pSMB->ByteCount = cpu_to_le16(byte_count);
4705 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4706 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4708 cFYI(1, ("SetPathInfo (EA) returned %d", rc));
4711 cifs_buf_release(pSMB);