4 * Copyright (C) International Business Machines Corp., 2002,2005
5 * Author(s): Steve French (sfrench@us.ibm.com)
7 * Contains the routines for constructing the SMB PDUs themselves
9 * This library is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU Lesser General Public License as published
11 * by the Free Software Foundation; either version 2.1 of the License, or
12 * (at your option) any later version.
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
17 * the GNU Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public License
20 * along with this library; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 /* SMB/CIFS PDU handling routines here - except for leftovers in connect.c */
25 /* These are mostly routines that operate on a pathname, or on a tree id */
26 /* (mounted volume), but there are eight handle based routines which must be */
27 /* treated slightly different for reconnection purposes since we never want */
28 /* to reuse a stale file handle and the caller knows the file handle */
31 #include <linux/kernel.h>
32 #include <linux/vfs.h>
33 #include <linux/posix_acl_xattr.h>
34 #include <asm/uaccess.h>
37 #include "cifsproto.h"
38 #include "cifs_unicode.h"
39 #include "cifs_debug.h"
41 #ifdef CONFIG_CIFS_POSIX
46 {CIFS_PROT, "\2NT LM 0.12"},
47 {CIFS_PROT, "\2POSIX 2"},
55 {CIFS_PROT, "\2NT LM 0.12"},
61 /* Mark as invalid, all open files on tree connections since they
62 were closed when session to server was lost */
63 static void mark_open_files_invalid(struct cifsTconInfo * pTcon)
65 struct cifsFileInfo *open_file = NULL;
66 struct list_head * tmp;
67 struct list_head * tmp1;
69 /* list all files open on tree connection and mark them invalid */
70 write_lock(&GlobalSMBSeslock);
71 list_for_each_safe(tmp, tmp1, &pTcon->openFileList) {
72 open_file = list_entry(tmp,struct cifsFileInfo, tlist);
74 open_file->invalidHandle = TRUE;
77 write_unlock(&GlobalSMBSeslock);
78 /* BB Add call to invalidate_inodes(sb) for all superblocks mounted
82 /* If the return code is zero, this function must fill in request_buf pointer */
84 small_smb_init(int smb_command, int wct, struct cifsTconInfo *tcon,
85 void **request_buf /* returned */)
89 /* SMBs NegProt, SessSetup, uLogoff do not have tcon yet so
90 check for tcp and smb session status done differently
91 for those three - in the calling routine */
93 if((tcon->ses) && (tcon->ses->status != CifsExiting) &&
95 struct nls_table *nls_codepage;
96 /* Give Demultiplex thread up to 10 seconds to
97 reconnect, should be greater than cifs socket
98 timeout which is 7 seconds */
99 while(tcon->ses->server->tcpStatus == CifsNeedReconnect) {
100 wait_event_interruptible_timeout(tcon->ses->server->response_q,
101 (tcon->ses->server->tcpStatus == CifsGood), 10 * HZ);
102 if(tcon->ses->server->tcpStatus == CifsNeedReconnect) {
103 /* on "soft" mounts we wait once */
104 if((tcon->retry == FALSE) ||
105 (tcon->ses->status == CifsExiting)) {
106 cFYI(1,("gave up waiting on reconnect in smb_init"));
108 } /* else "hard" mount - keep retrying
109 until process is killed or server
110 comes back on-line */
111 } else /* TCP session is reestablished now */
116 nls_codepage = load_nls_default();
117 /* need to prevent multiple threads trying to
118 simultaneously reconnect the same SMB session */
119 down(&tcon->ses->sesSem);
120 if(tcon->ses->status == CifsNeedReconnect)
121 rc = cifs_setup_session(0, tcon->ses,
123 if(!rc && (tcon->tidStatus == CifsNeedReconnect)) {
124 mark_open_files_invalid(tcon);
125 rc = CIFSTCon(0, tcon->ses, tcon->treeName, tcon
127 up(&tcon->ses->sesSem);
129 atomic_inc(&tconInfoReconnectCount);
131 cFYI(1, ("reconnect tcon rc = %d", rc));
132 /* Removed call to reopen open files here -
133 it is safer (and faster) to reopen files
134 one at a time as needed in read and write */
136 /* Check if handle based operation so we
137 know whether we can continue or not without
138 returning to caller to reset file handle */
139 switch(smb_command) {
140 case SMB_COM_READ_ANDX:
141 case SMB_COM_WRITE_ANDX:
143 case SMB_COM_FIND_CLOSE2:
144 case SMB_COM_LOCKING_ANDX: {
145 unload_nls(nls_codepage);
150 up(&tcon->ses->sesSem);
152 unload_nls(nls_codepage);
161 *request_buf = cifs_small_buf_get();
162 if (*request_buf == NULL) {
163 /* BB should we add a retry in here if not a writepage? */
167 header_assemble((struct smb_hdr *) *request_buf, smb_command, tcon,wct);
170 cifs_stats_inc(&tcon->num_smbs_sent);
175 /* If the return code is zero, this function must fill in request_buf pointer */
177 smb_init(int smb_command, int wct, struct cifsTconInfo *tcon,
178 void **request_buf /* returned */ ,
179 void **response_buf /* returned */ )
183 /* SMBs NegProt, SessSetup, uLogoff do not have tcon yet so
184 check for tcp and smb session status done differently
185 for those three - in the calling routine */
187 if((tcon->ses) && (tcon->ses->status != CifsExiting) &&
188 (tcon->ses->server)){
189 struct nls_table *nls_codepage;
190 /* Give Demultiplex thread up to 10 seconds to
191 reconnect, should be greater than cifs socket
192 timeout which is 7 seconds */
193 while(tcon->ses->server->tcpStatus == CifsNeedReconnect) {
194 wait_event_interruptible_timeout(tcon->ses->server->response_q,
195 (tcon->ses->server->tcpStatus == CifsGood), 10 * HZ);
196 if(tcon->ses->server->tcpStatus ==
198 /* on "soft" mounts we wait once */
199 if((tcon->retry == FALSE) ||
200 (tcon->ses->status == CifsExiting)) {
201 cFYI(1,("gave up waiting on reconnect in smb_init"));
203 } /* else "hard" mount - keep retrying
204 until process is killed or server
206 } else /* TCP session is reestablished now */
211 nls_codepage = load_nls_default();
212 /* need to prevent multiple threads trying to
213 simultaneously reconnect the same SMB session */
214 down(&tcon->ses->sesSem);
215 if(tcon->ses->status == CifsNeedReconnect)
216 rc = cifs_setup_session(0, tcon->ses,
218 if(!rc && (tcon->tidStatus == CifsNeedReconnect)) {
219 mark_open_files_invalid(tcon);
220 rc = CIFSTCon(0, tcon->ses, tcon->treeName,
222 up(&tcon->ses->sesSem);
224 atomic_inc(&tconInfoReconnectCount);
226 cFYI(1, ("reconnect tcon rc = %d", rc));
227 /* Removed call to reopen open files here -
228 it is safer (and faster) to reopen files
229 one at a time as needed in read and write */
231 /* Check if handle based operation so we
232 know whether we can continue or not without
233 returning to caller to reset file handle */
234 switch(smb_command) {
235 case SMB_COM_READ_ANDX:
236 case SMB_COM_WRITE_ANDX:
238 case SMB_COM_FIND_CLOSE2:
239 case SMB_COM_LOCKING_ANDX: {
240 unload_nls(nls_codepage);
245 up(&tcon->ses->sesSem);
247 unload_nls(nls_codepage);
256 *request_buf = cifs_buf_get();
257 if (*request_buf == NULL) {
258 /* BB should we add a retry in here if not a writepage? */
261 /* Although the original thought was we needed the response buf for */
262 /* potential retries of smb operations it turns out we can determine */
263 /* from the mid flags when the request buffer can be resent without */
264 /* having to use a second distinct buffer for the response */
265 *response_buf = *request_buf;
267 header_assemble((struct smb_hdr *) *request_buf, smb_command, tcon,
271 cifs_stats_inc(&tcon->num_smbs_sent);
276 static int validate_t2(struct smb_t2_rsp * pSMB)
282 /* check for plausible wct, bcc and t2 data and parm sizes */
283 /* check for parm and data offset going beyond end of smb */
284 if(pSMB->hdr.WordCount >= 10) {
285 if((le16_to_cpu(pSMB->t2_rsp.ParameterOffset) <= 1024) &&
286 (le16_to_cpu(pSMB->t2_rsp.DataOffset) <= 1024)) {
287 /* check that bcc is at least as big as parms + data */
288 /* check that bcc is less than negotiated smb buffer */
289 total_size = le16_to_cpu(pSMB->t2_rsp.ParameterCount);
290 if(total_size < 512) {
291 total_size+=le16_to_cpu(pSMB->t2_rsp.DataCount);
292 /* BCC le converted in SendReceive */
293 pBCC = (pSMB->hdr.WordCount * 2) +
294 sizeof(struct smb_hdr) +
296 if((total_size <= (*(u16 *)pBCC)) &&
298 CIFSMaxBufSize+MAX_CIFS_HDR_SIZE)) {
305 cifs_dump_mem("Invalid transact2 SMB: ",(char *)pSMB,
306 sizeof(struct smb_t2_rsp) + 16);
310 CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses)
313 NEGOTIATE_RSP *pSMBr;
316 struct TCP_Server_Info * server;
320 server = ses->server;
325 rc = smb_init(SMB_COM_NEGOTIATE, 0, NULL /* no tcon yet */ ,
326 (void **) &pSMB, (void **) &pSMBr);
329 pSMB->hdr.Mid = GetNextMid(server);
330 pSMB->hdr.Flags2 |= SMBFLG2_UNICODE;
331 if (extended_security)
332 pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC;
334 count = strlen(protocols[0].name) + 1;
335 strncpy(pSMB->DialectsArray, protocols[0].name, 30);
336 /* null guaranteed to be at end of source and target buffers anyway */
338 pSMB->hdr.smb_buf_length += count;
339 pSMB->ByteCount = cpu_to_le16(count);
341 rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB,
342 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
344 server->secMode = pSMBr->SecurityMode;
345 server->secType = NTLM; /* BB override default for
346 NTLMv2 or kerberos v5 */
347 /* one byte - no need to convert this or EncryptionKeyLen
348 from little endian */
349 server->maxReq = le16_to_cpu(pSMBr->MaxMpxCount);
350 /* probably no need to store and check maxvcs */
352 min(le32_to_cpu(pSMBr->MaxBufferSize),
353 (__u32) CIFSMaxBufSize + MAX_CIFS_HDR_SIZE);
354 server->maxRw = le32_to_cpu(pSMBr->MaxRawSize);
355 cFYI(0, ("Max buf = %d ", ses->server->maxBuf));
356 GETU32(ses->server->sessid) = le32_to_cpu(pSMBr->SessionKey);
357 server->capabilities = le32_to_cpu(pSMBr->Capabilities);
358 server->timeZone = le16_to_cpu(pSMBr->ServerTimeZone);
359 /* BB with UTC do we ever need to be using srvr timezone? */
360 if (pSMBr->EncryptionKeyLength == CIFS_CRYPTO_KEY_SIZE) {
361 memcpy(server->cryptKey, pSMBr->u.EncryptionKey,
362 CIFS_CRYPTO_KEY_SIZE);
363 } else if ((pSMBr->hdr.Flags2 & SMBFLG2_EXT_SEC)
364 && (pSMBr->EncryptionKeyLength == 0)) {
365 /* decode security blob */
369 /* BB might be helpful to save off the domain of server here */
371 if ((pSMBr->hdr.Flags2 & SMBFLG2_EXT_SEC) &&
372 (server->capabilities & CAP_EXTENDED_SECURITY)) {
373 count = pSMBr->ByteCount;
376 else if (count == 16) {
377 server->secType = RawNTLMSSP;
378 if (server->socketUseCount.counter > 1) {
380 (server->server_GUID,
381 pSMBr->u.extended_response.
384 ("UID of server does not match previous connection to same ip address"));
392 memcpy(server->server_GUID,
393 pSMBr->u.extended_response.
396 rc = decode_negTokenInit(pSMBr->u.
402 /* BB Need to fill struct for sessetup here */
409 server->capabilities &= ~CAP_EXTENDED_SECURITY;
410 if(sign_CIFS_PDUs == FALSE) {
411 if(server->secMode & SECMODE_SIGN_REQUIRED)
413 ("Server requires /proc/fs/cifs/PacketSigningEnabled"));
414 server->secMode &= ~(SECMODE_SIGN_ENABLED | SECMODE_SIGN_REQUIRED);
415 } else if(sign_CIFS_PDUs == 1) {
416 if((server->secMode & SECMODE_SIGN_REQUIRED) == 0)
417 server->secMode &= ~(SECMODE_SIGN_ENABLED | SECMODE_SIGN_REQUIRED);
422 cifs_buf_release(pSMB);
427 CIFSSMBTDis(const int xid, struct cifsTconInfo *tcon)
429 struct smb_hdr *smb_buffer;
430 struct smb_hdr *smb_buffer_response; /* BB removeme BB */
434 cFYI(1, ("In tree disconnect"));
436 * If last user of the connection and
437 * connection alive - disconnect it
438 * If this is the last connection on the server session disconnect it
439 * (and inside session disconnect we should check if tcp socket needs
440 * to be freed and kernel thread woken up).
443 down(&tcon->tconSem);
447 atomic_dec(&tcon->useCount);
448 if (atomic_read(&tcon->useCount) > 0) {
453 /* No need to return error on this operation if tid invalidated and
454 closed on server already e.g. due to tcp session crashing */
455 if(tcon->tidStatus == CifsNeedReconnect) {
460 if((tcon->ses == NULL) || (tcon->ses->server == NULL)) {
464 rc = small_smb_init(SMB_COM_TREE_DISCONNECT, 0, tcon,
465 (void **)&smb_buffer);
470 smb_buffer_response = smb_buffer; /* BB removeme BB */
472 rc = SendReceive(xid, tcon->ses, smb_buffer, smb_buffer_response,
475 cFYI(1, ("Tree disconnect failed %d", rc));
478 cifs_small_buf_release(smb_buffer);
481 /* No need to return error on this operation if tid invalidated and
482 closed on server already e.g. due to tcp session crashing */
490 CIFSSMBLogoff(const int xid, struct cifsSesInfo *ses)
492 struct smb_hdr *smb_buffer_response;
493 LOGOFF_ANDX_REQ *pSMB;
497 cFYI(1, ("In SMBLogoff for session disconnect"));
503 atomic_dec(&ses->inUse);
504 if (atomic_read(&ses->inUse) > 0) {
508 rc = small_smb_init(SMB_COM_LOGOFF_ANDX, 2, NULL, (void **)&pSMB);
514 smb_buffer_response = (struct smb_hdr *)pSMB; /* BB removeme BB */
517 pSMB->hdr.Mid = GetNextMid(ses->server);
519 if(ses->server->secMode &
520 (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
521 pSMB->hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
524 pSMB->hdr.Uid = ses->Suid;
526 pSMB->AndXCommand = 0xFF;
527 rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB,
528 smb_buffer_response, &length, 0);
530 atomic_dec(&ses->server->socketUseCount);
531 if (atomic_read(&ses->server->socketUseCount) == 0) {
532 spin_lock(&GlobalMid_Lock);
533 ses->server->tcpStatus = CifsExiting;
534 spin_unlock(&GlobalMid_Lock);
539 cifs_small_buf_release(pSMB);
541 /* if session dead then we do not need to do ulogoff,
542 since server closed smb session, no sense reporting
550 CIFSSMBDelFile(const int xid, struct cifsTconInfo *tcon, const char *fileName,
551 const struct nls_table *nls_codepage, int remap)
553 DELETE_FILE_REQ *pSMB = NULL;
554 DELETE_FILE_RSP *pSMBr = NULL;
560 rc = smb_init(SMB_COM_DELETE, 1, tcon, (void **) &pSMB,
565 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
567 cifsConvertToUCS((__le16 *) pSMB->fileName, fileName,
568 PATH_MAX, nls_codepage, remap);
569 name_len++; /* trailing null */
571 } else { /* BB improve check for buffer overruns BB */
572 name_len = strnlen(fileName, PATH_MAX);
573 name_len++; /* trailing null */
574 strncpy(pSMB->fileName, fileName, name_len);
576 pSMB->SearchAttributes =
577 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM);
578 pSMB->BufferFormat = 0x04;
579 pSMB->hdr.smb_buf_length += name_len + 1;
580 pSMB->ByteCount = cpu_to_le16(name_len + 1);
581 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
582 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
583 cifs_stats_inc(&tcon->num_deletes);
585 cFYI(1, ("Error in RMFile = %d", rc));
588 cifs_buf_release(pSMB);
596 CIFSSMBRmDir(const int xid, struct cifsTconInfo *tcon, const char *dirName,
597 const struct nls_table *nls_codepage, int remap)
599 DELETE_DIRECTORY_REQ *pSMB = NULL;
600 DELETE_DIRECTORY_RSP *pSMBr = NULL;
605 cFYI(1, ("In CIFSSMBRmDir"));
607 rc = smb_init(SMB_COM_DELETE_DIRECTORY, 0, tcon, (void **) &pSMB,
612 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
613 name_len = cifsConvertToUCS((__le16 *) pSMB->DirName, dirName,
614 PATH_MAX, nls_codepage, remap);
615 name_len++; /* trailing null */
617 } else { /* BB improve check for buffer overruns BB */
618 name_len = strnlen(dirName, PATH_MAX);
619 name_len++; /* trailing null */
620 strncpy(pSMB->DirName, dirName, name_len);
623 pSMB->BufferFormat = 0x04;
624 pSMB->hdr.smb_buf_length += name_len + 1;
625 pSMB->ByteCount = cpu_to_le16(name_len + 1);
626 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
627 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
628 cifs_stats_inc(&tcon->num_rmdirs);
630 cFYI(1, ("Error in RMDir = %d", rc));
633 cifs_buf_release(pSMB);
640 CIFSSMBMkDir(const int xid, struct cifsTconInfo *tcon,
641 const char *name, const struct nls_table *nls_codepage, int remap)
644 CREATE_DIRECTORY_REQ *pSMB = NULL;
645 CREATE_DIRECTORY_RSP *pSMBr = NULL;
649 cFYI(1, ("In CIFSSMBMkDir"));
651 rc = smb_init(SMB_COM_CREATE_DIRECTORY, 0, tcon, (void **) &pSMB,
656 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
657 name_len = cifsConvertToUCS((__le16 *) pSMB->DirName, name,
658 PATH_MAX, nls_codepage, remap);
659 name_len++; /* trailing null */
661 } else { /* BB improve check for buffer overruns BB */
662 name_len = strnlen(name, PATH_MAX);
663 name_len++; /* trailing null */
664 strncpy(pSMB->DirName, name, name_len);
667 pSMB->BufferFormat = 0x04;
668 pSMB->hdr.smb_buf_length += name_len + 1;
669 pSMB->ByteCount = cpu_to_le16(name_len + 1);
670 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
671 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
672 cifs_stats_inc(&tcon->num_mkdirs);
674 cFYI(1, ("Error in Mkdir = %d", rc));
677 cifs_buf_release(pSMB);
683 static __u16 convert_disposition(int disposition)
687 switch (disposition) {
689 ofun = SMBOPEN_OCREATE | SMBOPEN_OTRUNC;
692 ofun = SMBOPEN_OAPPEND;
695 ofun = SMBOPEN_OCREATE;
698 ofun = SMBOPEN_OCREATE | SMBOPEN_OAPPEND;
701 ofun = SMBOPEN_OTRUNC;
703 case FILE_OVERWRITE_IF:
704 ofun = SMBOPEN_OCREATE | SMBOPEN_OTRUNC;
707 cFYI(1,("unknown disposition %d",disposition));
708 ofun = SMBOPEN_OAPPEND; /* regular open */
714 SMBLegacyOpen(const int xid, struct cifsTconInfo *tcon,
715 const char *fileName, const int openDisposition,
716 const int access_flags, const int create_options, __u16 * netfid,
717 int *pOplock, FILE_ALL_INFO * pfile_info,
718 const struct nls_table *nls_codepage, int remap)
721 OPENX_REQ *pSMB = NULL;
722 OPENX_RSP *pSMBr = NULL;
728 rc = smb_init(SMB_COM_OPEN_ANDX, 15, tcon, (void **) &pSMB,
733 pSMB->AndXCommand = 0xFF; /* none */
735 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
736 count = 1; /* account for one byte pad to word boundary */
738 cifsConvertToUCS((__le16 *) (pSMB->fileName + 1),
739 fileName, PATH_MAX, nls_codepage, remap);
740 name_len++; /* trailing null */
742 } else { /* BB improve check for buffer overruns BB */
743 count = 0; /* no pad */
744 name_len = strnlen(fileName, PATH_MAX);
745 name_len++; /* trailing null */
746 strncpy(pSMB->fileName, fileName, name_len);
748 if (*pOplock & REQ_OPLOCK)
749 pSMB->OpenFlags = cpu_to_le16(REQ_OPLOCK);
750 else if (*pOplock & REQ_BATCHOPLOCK) {
751 pSMB->OpenFlags = cpu_to_le16(REQ_BATCHOPLOCK);
753 pSMB->OpenFlags |= cpu_to_le16(REQ_MORE_INFO);
754 /* BB fixme add conversion for access_flags to bits 0 - 2 of mode */
760 pSMB->Mode = cpu_to_le16(2);
761 pSMB->Mode |= cpu_to_le16(0x40); /* deny none */
762 /* set file as system file if special file such
763 as fifo and server expecting SFU style and
764 no Unix extensions */
766 if(create_options & CREATE_OPTION_SPECIAL)
767 pSMB->FileAttributes = cpu_to_le16(ATTR_SYSTEM);
769 pSMB->FileAttributes = cpu_to_le16(ATTR_NORMAL);
771 /* if ((omode & S_IWUGO) == 0)
772 pSMB->FileAttributes |= cpu_to_le32(ATTR_READONLY);*/
773 /* Above line causes problems due to vfs splitting create into two
774 pieces - need to set mode after file created not while it is
778 /* pSMB->CreateOptions = cpu_to_le32(create_options & CREATE_OPTIONS_MASK); */
779 /* BB FIXME END BB */
780 pSMB->OpenFunction = convert_disposition(openDisposition);
782 pSMB->hdr.smb_buf_length += count;
784 pSMB->ByteCount = cpu_to_le16(count);
785 /* long_op set to 1 to allow for oplock break timeouts */
786 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
787 (struct smb_hdr *) pSMBr, &bytes_returned, 1);
788 cifs_stats_inc(&tcon->num_opens);
790 cFYI(1, ("Error in Open = %d", rc));
792 /* BB verify if wct == 15 */
794 /* *pOplock = pSMBr->OplockLevel; */ /* BB take from action field BB */
796 *netfid = pSMBr->Fid; /* cifs fid stays in le */
797 /* Let caller know file was created so we can set the mode. */
798 /* Do we care about the CreateAction in any other cases? */
800 /* if(cpu_to_le32(FILE_CREATE) == pSMBr->CreateAction)
801 *pOplock |= CIFS_CREATE_ACTION; */
805 pfile_info->CreationTime = 0; /* BB convert CreateTime*/
806 pfile_info->LastAccessTime = 0; /* BB fixme */
807 pfile_info->LastWriteTime = 0; /* BB fixme */
808 pfile_info->ChangeTime = 0; /* BB fixme */
809 pfile_info->Attributes = pSMBr->FileAttributes;
810 /* the file_info buf is endian converted by caller */
811 pfile_info->AllocationSize = pSMBr->EndOfFile;
812 pfile_info->EndOfFile = pSMBr->EndOfFile;
813 pfile_info->NumberOfLinks = cpu_to_le32(1);
817 cifs_buf_release(pSMB);
824 CIFSSMBOpen(const int xid, struct cifsTconInfo *tcon,
825 const char *fileName, const int openDisposition,
826 const int access_flags, const int create_options, __u16 * netfid,
827 int *pOplock, FILE_ALL_INFO * pfile_info,
828 const struct nls_table *nls_codepage, int remap)
831 OPEN_REQ *pSMB = NULL;
832 OPEN_RSP *pSMBr = NULL;
838 rc = smb_init(SMB_COM_NT_CREATE_ANDX, 24, tcon, (void **) &pSMB,
843 pSMB->AndXCommand = 0xFF; /* none */
845 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
846 count = 1; /* account for one byte pad to word boundary */
848 cifsConvertToUCS((__le16 *) (pSMB->fileName + 1),
849 fileName, PATH_MAX, nls_codepage, remap);
850 name_len++; /* trailing null */
852 pSMB->NameLength = cpu_to_le16(name_len);
853 } else { /* BB improve check for buffer overruns BB */
854 count = 0; /* no pad */
855 name_len = strnlen(fileName, PATH_MAX);
856 name_len++; /* trailing null */
857 pSMB->NameLength = cpu_to_le16(name_len);
858 strncpy(pSMB->fileName, fileName, name_len);
860 if (*pOplock & REQ_OPLOCK)
861 pSMB->OpenFlags = cpu_to_le32(REQ_OPLOCK);
862 else if (*pOplock & REQ_BATCHOPLOCK) {
863 pSMB->OpenFlags = cpu_to_le32(REQ_BATCHOPLOCK);
865 pSMB->DesiredAccess = cpu_to_le32(access_flags);
866 pSMB->AllocationSize = 0;
867 /* set file as system file if special file such
868 as fifo and server expecting SFU style and
869 no Unix extensions */
870 if(create_options & CREATE_OPTION_SPECIAL)
871 pSMB->FileAttributes = cpu_to_le32(ATTR_SYSTEM);
873 pSMB->FileAttributes = cpu_to_le32(ATTR_NORMAL);
874 /* XP does not handle ATTR_POSIX_SEMANTICS */
875 /* but it helps speed up case sensitive checks for other
876 servers such as Samba */
877 if (tcon->ses->capabilities & CAP_UNIX)
878 pSMB->FileAttributes |= cpu_to_le32(ATTR_POSIX_SEMANTICS);
880 /* if ((omode & S_IWUGO) == 0)
881 pSMB->FileAttributes |= cpu_to_le32(ATTR_READONLY);*/
882 /* Above line causes problems due to vfs splitting create into two
883 pieces - need to set mode after file created not while it is
885 pSMB->ShareAccess = cpu_to_le32(FILE_SHARE_ALL);
886 pSMB->CreateDisposition = cpu_to_le32(openDisposition);
887 pSMB->CreateOptions = cpu_to_le32(create_options & CREATE_OPTIONS_MASK);
888 /* BB Expirement with various impersonation levels and verify */
889 pSMB->ImpersonationLevel = cpu_to_le32(SECURITY_IMPERSONATION);
890 pSMB->SecurityFlags =
891 SECURITY_CONTEXT_TRACKING | SECURITY_EFFECTIVE_ONLY;
894 pSMB->hdr.smb_buf_length += count;
896 pSMB->ByteCount = cpu_to_le16(count);
897 /* long_op set to 1 to allow for oplock break timeouts */
898 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
899 (struct smb_hdr *) pSMBr, &bytes_returned, 1);
900 cifs_stats_inc(&tcon->num_opens);
902 cFYI(1, ("Error in Open = %d", rc));
904 *pOplock = pSMBr->OplockLevel; /* 1 byte no need to le_to_cpu */
905 *netfid = pSMBr->Fid; /* cifs fid stays in le */
906 /* Let caller know file was created so we can set the mode. */
907 /* Do we care about the CreateAction in any other cases? */
908 if(cpu_to_le32(FILE_CREATE) == pSMBr->CreateAction)
909 *pOplock |= CIFS_CREATE_ACTION;
911 memcpy((char *)pfile_info,(char *)&pSMBr->CreationTime,
912 36 /* CreationTime to Attributes */);
913 /* the file_info buf is endian converted by caller */
914 pfile_info->AllocationSize = pSMBr->AllocationSize;
915 pfile_info->EndOfFile = pSMBr->EndOfFile;
916 pfile_info->NumberOfLinks = cpu_to_le32(1);
920 cifs_buf_release(pSMB);
926 /* If no buffer passed in, then caller wants to do the copy
927 as in the case of readpages so the SMB buffer must be
928 freed by the caller */
931 CIFSSMBRead(const int xid, struct cifsTconInfo *tcon,
932 const int netfid, const unsigned int count,
933 const __u64 lseek, unsigned int *nbytes, char **buf)
936 READ_REQ *pSMB = NULL;
937 READ_RSP *pSMBr = NULL;
938 char *pReadData = NULL;
942 cFYI(1,("Reading %d bytes on fid %d",count,netfid));
943 if(tcon->ses->capabilities & CAP_LARGE_FILES)
946 wct = 10; /* old style read */
949 rc = smb_init(SMB_COM_READ_ANDX, wct, tcon, (void **) &pSMB,
954 /* tcon and ses pointer are checked in smb_init */
955 if (tcon->ses->server == NULL)
956 return -ECONNABORTED;
958 pSMB->AndXCommand = 0xFF; /* none */
960 pSMB->OffsetLow = cpu_to_le32(lseek & 0xFFFFFFFF);
962 pSMB->OffsetHigh = cpu_to_le32(lseek >> 32);
963 else if((lseek >> 32) > 0) /* can not handle this big offset for old */
967 pSMB->MaxCount = cpu_to_le16(count & 0xFFFF);
968 pSMB->MaxCountHigh = cpu_to_le32(count >> 16);
970 pSMB->ByteCount = 0; /* no need to do le conversion since 0 */
973 struct smb_com_readx_req * pSMBW =
974 (struct smb_com_readx_req *)pSMB;
975 pSMBW->ByteCount = 0;
978 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
979 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
980 cifs_stats_inc(&tcon->num_reads);
982 cERROR(1, ("Send error in read = %d", rc));
984 int data_length = le16_to_cpu(pSMBr->DataLengthHigh);
985 data_length = data_length << 16;
986 data_length += le16_to_cpu(pSMBr->DataLength);
987 *nbytes = data_length;
989 /*check that DataLength would not go beyond end of SMB */
990 if ((data_length > CIFSMaxBufSize)
991 || (data_length > count)) {
992 cFYI(1,("bad length %d for count %d",data_length,count));
997 (char *) (&pSMBr->hdr.Protocol) +
998 le16_to_cpu(pSMBr->DataOffset);
999 /* if(rc = copy_to_user(buf, pReadData, data_length)) {
1000 cERROR(1,("Faulting on read rc = %d",rc));
1002 }*/ /* can not use copy_to_user when using page cache*/
1004 memcpy(*buf,pReadData,data_length);
1008 cifs_buf_release(pSMB);
1010 *buf = (char *)pSMB;
1012 /* Note: On -EAGAIN error only caller can retry on handle based calls
1013 since file handle passed in no longer valid */
1018 CIFSSMBWrite(const int xid, struct cifsTconInfo *tcon,
1019 const int netfid, const unsigned int count,
1020 const __u64 offset, unsigned int *nbytes, const char *buf,
1021 const char __user * ubuf, const int long_op)
1024 WRITE_REQ *pSMB = NULL;
1025 WRITE_RSP *pSMBr = NULL;
1026 int bytes_returned, wct;
1030 /* cFYI(1,("write at %lld %d bytes",offset,count));*/
1031 if(tcon->ses == NULL)
1032 return -ECONNABORTED;
1034 if(tcon->ses->capabilities & CAP_LARGE_FILES)
1039 rc = smb_init(SMB_COM_WRITE_ANDX, wct, tcon, (void **) &pSMB,
1043 /* tcon and ses pointer are checked in smb_init */
1044 if (tcon->ses->server == NULL)
1045 return -ECONNABORTED;
1047 pSMB->AndXCommand = 0xFF; /* none */
1049 pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF);
1051 pSMB->OffsetHigh = cpu_to_le32(offset >> 32);
1052 else if((offset >> 32) > 0) /* can not handle this big offset for old */
1055 pSMB->Reserved = 0xFFFFFFFF;
1056 pSMB->WriteMode = 0;
1057 pSMB->Remaining = 0;
1059 /* Can increase buffer size if buffer is big enough in some cases - ie we
1060 can send more if LARGE_WRITE_X capability returned by the server and if
1061 our buffer is big enough or if we convert to iovecs on socket writes
1062 and eliminate the copy to the CIFS buffer */
1063 if(tcon->ses->capabilities & CAP_LARGE_WRITE_X) {
1064 bytes_sent = min_t(const unsigned int, CIFSMaxBufSize, count);
1066 bytes_sent = (tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE)
1070 if (bytes_sent > count)
1073 cpu_to_le16(offsetof(struct smb_com_write_req,Data) - 4);
1075 memcpy(pSMB->Data,buf,bytes_sent);
1077 if(copy_from_user(pSMB->Data,ubuf,bytes_sent)) {
1078 cifs_buf_release(pSMB);
1083 cifs_buf_release(pSMB);
1087 byte_count = bytes_sent + 1 /* pad */ ; /* BB fix this for sends > 64K */
1088 pSMB->DataLengthLow = cpu_to_le16(bytes_sent & 0xFFFF);
1089 pSMB->DataLengthHigh = cpu_to_le16(bytes_sent >> 16);
1090 pSMB->hdr.smb_buf_length += bytes_sent+1;
1093 pSMB->ByteCount = cpu_to_le16(byte_count);
1094 else { /* old style write has byte count 4 bytes earlier */
1095 struct smb_com_writex_req * pSMBW =
1096 (struct smb_com_writex_req *)pSMB;
1097 pSMBW->ByteCount = cpu_to_le16(byte_count);
1100 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1101 (struct smb_hdr *) pSMBr, &bytes_returned, long_op);
1102 cifs_stats_inc(&tcon->num_writes);
1104 cFYI(1, ("Send error in write = %d", rc));
1107 *nbytes = le16_to_cpu(pSMBr->CountHigh);
1108 *nbytes = (*nbytes) << 16;
1109 *nbytes += le16_to_cpu(pSMBr->Count);
1112 cifs_buf_release(pSMB);
1114 /* Note: On -EAGAIN error only caller can retry on handle based calls
1115 since file handle passed in no longer valid */
1120 #ifdef CONFIG_CIFS_EXPERIMENTAL
1122 CIFSSMBWrite2(const int xid, struct cifsTconInfo *tcon,
1123 const int netfid, const unsigned int count,
1124 const __u64 offset, unsigned int *nbytes, const char *buf,
1128 WRITE_REQ *pSMB = NULL;
1134 cFYI(1,("write2 at %lld %d bytes",offset,count)); /* BB removeme BB */
1135 rc = small_smb_init(SMB_COM_WRITE_ANDX, 14, tcon, (void **) &pSMB);
1138 /* tcon and ses pointer are checked in smb_init */
1139 if (tcon->ses->server == NULL)
1140 return -ECONNABORTED;
1142 pSMB->AndXCommand = 0xFF; /* none */
1144 pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF);
1145 pSMB->OffsetHigh = cpu_to_le32(offset >> 32);
1146 pSMB->Reserved = 0xFFFFFFFF;
1147 pSMB->WriteMode = 0;
1148 pSMB->Remaining = 0;
1150 /* Can increase buffer size if buffer is big enough in some cases - ie
1151 can send more if LARGE_WRITE_X capability returned by the server and if
1152 our buffer is big enough or if we convert to iovecs on socket writes
1153 and eliminate the copy to the CIFS buffer */
1154 if(tcon->ses->capabilities & CAP_LARGE_WRITE_X) {
1155 bytes_sent = min_t(const unsigned int, CIFSMaxBufSize, count);
1157 bytes_sent = (tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE)
1161 if (bytes_sent > count)
1164 cpu_to_le16(offsetof(struct smb_com_write_req,Data) - 4);
1166 byte_count = bytes_sent + 1 /* pad */ ; /* BB fix this for sends > 64K */
1167 pSMB->DataLengthLow = cpu_to_le16(bytes_sent & 0xFFFF);
1168 pSMB->DataLengthHigh = cpu_to_le16(bytes_sent >> 16);
1169 smb_hdr_len = pSMB->hdr.smb_buf_length + 1; /* hdr + 1 byte pad */
1170 pSMB->hdr.smb_buf_length += bytes_sent+1;
1171 pSMB->ByteCount = cpu_to_le16(byte_count);
1173 rc = SendReceive2(xid, tcon->ses, (struct smb_hdr *) pSMB, smb_hdr_len,
1174 buf, bytes_sent, &bytes_returned, long_op);
1175 cifs_stats_inc(&tcon->num_writes);
1177 cFYI(1, ("Send error in write = %d", rc));
1180 WRITE_RSP * pSMBr = (WRITE_RSP *)pSMB;
1181 *nbytes = le16_to_cpu(pSMBr->CountHigh);
1182 *nbytes = (*nbytes) << 16;
1183 *nbytes += le16_to_cpu(pSMBr->Count);
1186 cifs_small_buf_release(pSMB);
1188 /* Note: On -EAGAIN error only caller can retry on handle based calls
1189 since file handle passed in no longer valid */
1195 #endif /* CIFS_EXPERIMENTAL */
1198 CIFSSMBLock(const int xid, struct cifsTconInfo *tcon,
1199 const __u16 smb_file_id, const __u64 len,
1200 const __u64 offset, const __u32 numUnlock,
1201 const __u32 numLock, const __u8 lockType, const int waitFlag)
1204 LOCK_REQ *pSMB = NULL;
1205 LOCK_RSP *pSMBr = NULL;
1210 cFYI(1, ("In CIFSSMBLock - timeout %d numLock %d",waitFlag,numLock));
1211 rc = small_smb_init(SMB_COM_LOCKING_ANDX, 8, tcon, (void **) &pSMB);
1216 pSMBr = (LOCK_RSP *)pSMB; /* BB removeme BB */
1218 if(lockType == LOCKING_ANDX_OPLOCK_RELEASE) {
1219 timeout = -1; /* no response expected */
1221 } else if (waitFlag == TRUE) {
1222 timeout = 3; /* blocking operation, no timeout */
1223 pSMB->Timeout = cpu_to_le32(-1);/* blocking - do not time out */
1228 pSMB->NumberOfLocks = cpu_to_le16(numLock);
1229 pSMB->NumberOfUnlocks = cpu_to_le16(numUnlock);
1230 pSMB->LockType = lockType;
1231 pSMB->AndXCommand = 0xFF; /* none */
1232 pSMB->Fid = smb_file_id; /* netfid stays le */
1234 if((numLock != 0) || (numUnlock != 0)) {
1235 pSMB->Locks[0].Pid = cpu_to_le16(current->tgid);
1236 /* BB where to store pid high? */
1237 pSMB->Locks[0].LengthLow = cpu_to_le32((u32)len);
1238 pSMB->Locks[0].LengthHigh = cpu_to_le32((u32)(len>>32));
1239 pSMB->Locks[0].OffsetLow = cpu_to_le32((u32)offset);
1240 pSMB->Locks[0].OffsetHigh = cpu_to_le32((u32)(offset>>32));
1241 count = sizeof(LOCKING_ANDX_RANGE);
1246 pSMB->hdr.smb_buf_length += count;
1247 pSMB->ByteCount = cpu_to_le16(count);
1249 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1250 (struct smb_hdr *) pSMBr, &bytes_returned, timeout);
1251 cifs_stats_inc(&tcon->num_locks);
1253 cFYI(1, ("Send error in Lock = %d", rc));
1255 cifs_small_buf_release(pSMB);
1257 /* Note: On -EAGAIN error only caller can retry on handle based calls
1258 since file handle passed in no longer valid */
1263 CIFSSMBClose(const int xid, struct cifsTconInfo *tcon, int smb_file_id)
1266 CLOSE_REQ *pSMB = NULL;
1267 CLOSE_RSP *pSMBr = NULL;
1269 cFYI(1, ("In CIFSSMBClose"));
1271 /* do not retry on dead session on close */
1272 rc = small_smb_init(SMB_COM_CLOSE, 3, tcon, (void **) &pSMB);
1278 pSMBr = (CLOSE_RSP *)pSMB; /* BB removeme BB */
1280 pSMB->FileID = (__u16) smb_file_id;
1281 pSMB->LastWriteTime = 0;
1282 pSMB->ByteCount = 0;
1283 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1284 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1285 cifs_stats_inc(&tcon->num_closes);
1288 /* EINTR is expected when user ctl-c to kill app */
1289 cERROR(1, ("Send error in Close = %d", rc));
1293 cifs_small_buf_release(pSMB);
1295 /* Since session is dead, file will be closed on server already */
1303 CIFSSMBRename(const int xid, struct cifsTconInfo *tcon,
1304 const char *fromName, const char *toName,
1305 const struct nls_table *nls_codepage, int remap)
1308 RENAME_REQ *pSMB = NULL;
1309 RENAME_RSP *pSMBr = NULL;
1311 int name_len, name_len2;
1314 cFYI(1, ("In CIFSSMBRename"));
1316 rc = smb_init(SMB_COM_RENAME, 1, tcon, (void **) &pSMB,
1321 pSMB->BufferFormat = 0x04;
1322 pSMB->SearchAttributes =
1323 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
1326 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1328 cifsConvertToUCS((__le16 *) pSMB->OldFileName, fromName,
1329 PATH_MAX, nls_codepage, remap);
1330 name_len++; /* trailing null */
1332 pSMB->OldFileName[name_len] = 0x04; /* pad */
1333 /* protocol requires ASCII signature byte on Unicode string */
1334 pSMB->OldFileName[name_len + 1] = 0x00;
1336 cifsConvertToUCS((__le16 *) &pSMB->OldFileName[name_len + 2],
1337 toName, PATH_MAX, nls_codepage, remap);
1338 name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
1339 name_len2 *= 2; /* convert to bytes */
1340 } else { /* BB improve the check for buffer overruns BB */
1341 name_len = strnlen(fromName, PATH_MAX);
1342 name_len++; /* trailing null */
1343 strncpy(pSMB->OldFileName, fromName, name_len);
1344 name_len2 = strnlen(toName, PATH_MAX);
1345 name_len2++; /* trailing null */
1346 pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */
1347 strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2);
1348 name_len2++; /* trailing null */
1349 name_len2++; /* signature byte */
1352 count = 1 /* 1st signature byte */ + name_len + name_len2;
1353 pSMB->hdr.smb_buf_length += count;
1354 pSMB->ByteCount = cpu_to_le16(count);
1356 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1357 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1358 cifs_stats_inc(&tcon->num_renames);
1360 cFYI(1, ("Send error in rename = %d", rc));
1363 cifs_buf_release(pSMB);
1371 int CIFSSMBRenameOpenFile(const int xid,struct cifsTconInfo *pTcon,
1372 int netfid, char * target_name,
1373 const struct nls_table * nls_codepage, int remap)
1375 struct smb_com_transaction2_sfi_req *pSMB = NULL;
1376 struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
1377 struct set_file_rename * rename_info;
1379 char dummy_string[30];
1381 int bytes_returned = 0;
1383 __u16 params, param_offset, offset, count, byte_count;
1385 cFYI(1, ("Rename to File by handle"));
1386 rc = smb_init(SMB_COM_TRANSACTION2, 15, pTcon, (void **) &pSMB,
1392 pSMB->MaxSetupCount = 0;
1396 pSMB->Reserved2 = 0;
1397 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
1398 offset = param_offset + params;
1400 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
1401 rename_info = (struct set_file_rename *) data_offset;
1402 pSMB->MaxParameterCount = cpu_to_le16(2);
1403 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB PDU from sess */
1404 pSMB->SetupCount = 1;
1405 pSMB->Reserved3 = 0;
1406 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
1407 byte_count = 3 /* pad */ + params;
1408 pSMB->ParameterCount = cpu_to_le16(params);
1409 pSMB->TotalParameterCount = pSMB->ParameterCount;
1410 pSMB->ParameterOffset = cpu_to_le16(param_offset);
1411 pSMB->DataOffset = cpu_to_le16(offset);
1412 /* construct random name ".cifs_tmp<inodenum><mid>" */
1413 rename_info->overwrite = cpu_to_le32(1);
1414 rename_info->root_fid = 0;
1415 /* unicode only call */
1416 if(target_name == NULL) {
1417 sprintf(dummy_string,"cifs%x",pSMB->hdr.Mid);
1418 len_of_str = cifsConvertToUCS((__le16 *)rename_info->target_name,
1419 dummy_string, 24, nls_codepage, remap);
1421 len_of_str = cifsConvertToUCS((__le16 *)rename_info->target_name,
1422 target_name, PATH_MAX, nls_codepage, remap);
1424 rename_info->target_name_len = cpu_to_le32(2 * len_of_str);
1425 count = 12 /* sizeof(struct set_file_rename) */ + (2 * len_of_str) + 2;
1426 byte_count += count;
1427 pSMB->DataCount = cpu_to_le16(count);
1428 pSMB->TotalDataCount = pSMB->DataCount;
1430 pSMB->InformationLevel =
1431 cpu_to_le16(SMB_SET_FILE_RENAME_INFORMATION);
1432 pSMB->Reserved4 = 0;
1433 pSMB->hdr.smb_buf_length += byte_count;
1434 pSMB->ByteCount = cpu_to_le16(byte_count);
1435 rc = SendReceive(xid, pTcon->ses, (struct smb_hdr *) pSMB,
1436 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1437 cifs_stats_inc(&pTcon->num_t2renames);
1439 cFYI(1,("Send error in Rename (by file handle) = %d", rc));
1442 cifs_buf_release(pSMB);
1444 /* Note: On -EAGAIN error only caller can retry on handle based calls
1445 since file handle passed in no longer valid */
1451 CIFSSMBCopy(const int xid, struct cifsTconInfo *tcon, const char * fromName,
1452 const __u16 target_tid, const char *toName, const int flags,
1453 const struct nls_table *nls_codepage, int remap)
1456 COPY_REQ *pSMB = NULL;
1457 COPY_RSP *pSMBr = NULL;
1459 int name_len, name_len2;
1462 cFYI(1, ("In CIFSSMBCopy"));
1464 rc = smb_init(SMB_COM_COPY, 1, tcon, (void **) &pSMB,
1469 pSMB->BufferFormat = 0x04;
1470 pSMB->Tid2 = target_tid;
1472 pSMB->Flags = cpu_to_le16(flags & COPY_TREE);
1474 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1475 name_len = cifsConvertToUCS((__le16 *) pSMB->OldFileName,
1476 fromName, PATH_MAX, nls_codepage,
1478 name_len++; /* trailing null */
1480 pSMB->OldFileName[name_len] = 0x04; /* pad */
1481 /* protocol requires ASCII signature byte on Unicode string */
1482 pSMB->OldFileName[name_len + 1] = 0x00;
1483 name_len2 = cifsConvertToUCS((__le16 *)&pSMB->OldFileName[name_len + 2],
1484 toName, PATH_MAX, nls_codepage, remap);
1485 name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
1486 name_len2 *= 2; /* convert to bytes */
1487 } else { /* BB improve the check for buffer overruns BB */
1488 name_len = strnlen(fromName, PATH_MAX);
1489 name_len++; /* trailing null */
1490 strncpy(pSMB->OldFileName, fromName, name_len);
1491 name_len2 = strnlen(toName, PATH_MAX);
1492 name_len2++; /* trailing null */
1493 pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */
1494 strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2);
1495 name_len2++; /* trailing null */
1496 name_len2++; /* signature byte */
1499 count = 1 /* 1st signature byte */ + name_len + name_len2;
1500 pSMB->hdr.smb_buf_length += count;
1501 pSMB->ByteCount = cpu_to_le16(count);
1503 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1504 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1506 cFYI(1, ("Send error in copy = %d with %d files copied",
1507 rc, le16_to_cpu(pSMBr->CopyCount)));
1510 cifs_buf_release(pSMB);
1519 CIFSUnixCreateSymLink(const int xid, struct cifsTconInfo *tcon,
1520 const char *fromName, const char *toName,
1521 const struct nls_table *nls_codepage)
1523 TRANSACTION2_SPI_REQ *pSMB = NULL;
1524 TRANSACTION2_SPI_RSP *pSMBr = NULL;
1527 int name_len_target;
1529 int bytes_returned = 0;
1530 __u16 params, param_offset, offset, byte_count;
1532 cFYI(1, ("In Symlink Unix style"));
1534 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
1539 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1541 cifs_strtoUCS((wchar_t *) pSMB->FileName, fromName, PATH_MAX
1542 /* find define for this maxpathcomponent */
1544 name_len++; /* trailing null */
1547 } else { /* BB improve the check for buffer overruns BB */
1548 name_len = strnlen(fromName, PATH_MAX);
1549 name_len++; /* trailing null */
1550 strncpy(pSMB->FileName, fromName, name_len);
1552 params = 6 + name_len;
1553 pSMB->MaxSetupCount = 0;
1557 pSMB->Reserved2 = 0;
1558 param_offset = offsetof(struct smb_com_transaction2_spi_req,
1559 InformationLevel) - 4;
1560 offset = param_offset + params;
1562 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
1563 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1565 cifs_strtoUCS((wchar_t *) data_offset, toName, PATH_MAX
1566 /* find define for this maxpathcomponent */
1568 name_len_target++; /* trailing null */
1569 name_len_target *= 2;
1570 } else { /* BB improve the check for buffer overruns BB */
1571 name_len_target = strnlen(toName, PATH_MAX);
1572 name_len_target++; /* trailing null */
1573 strncpy(data_offset, toName, name_len_target);
1576 pSMB->MaxParameterCount = cpu_to_le16(2);
1577 /* BB find exact max on data count below from sess */
1578 pSMB->MaxDataCount = cpu_to_le16(1000);
1579 pSMB->SetupCount = 1;
1580 pSMB->Reserved3 = 0;
1581 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
1582 byte_count = 3 /* pad */ + params + name_len_target;
1583 pSMB->DataCount = cpu_to_le16(name_len_target);
1584 pSMB->ParameterCount = cpu_to_le16(params);
1585 pSMB->TotalDataCount = pSMB->DataCount;
1586 pSMB->TotalParameterCount = pSMB->ParameterCount;
1587 pSMB->ParameterOffset = cpu_to_le16(param_offset);
1588 pSMB->DataOffset = cpu_to_le16(offset);
1589 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_LINK);
1590 pSMB->Reserved4 = 0;
1591 pSMB->hdr.smb_buf_length += byte_count;
1592 pSMB->ByteCount = cpu_to_le16(byte_count);
1593 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1594 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1595 cifs_stats_inc(&tcon->num_symlinks);
1598 ("Send error in SetPathInfo (create symlink) = %d",
1603 cifs_buf_release(pSMB);
1606 goto createSymLinkRetry;
1612 CIFSUnixCreateHardLink(const int xid, struct cifsTconInfo *tcon,
1613 const char *fromName, const char *toName,
1614 const struct nls_table *nls_codepage, int remap)
1616 TRANSACTION2_SPI_REQ *pSMB = NULL;
1617 TRANSACTION2_SPI_RSP *pSMBr = NULL;
1620 int name_len_target;
1622 int bytes_returned = 0;
1623 __u16 params, param_offset, offset, byte_count;
1625 cFYI(1, ("In Create Hard link Unix style"));
1626 createHardLinkRetry:
1627 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
1632 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1633 name_len = cifsConvertToUCS((__le16 *) pSMB->FileName, toName,
1634 PATH_MAX, nls_codepage, remap);
1635 name_len++; /* trailing null */
1638 } else { /* BB improve the check for buffer overruns BB */
1639 name_len = strnlen(toName, PATH_MAX);
1640 name_len++; /* trailing null */
1641 strncpy(pSMB->FileName, toName, name_len);
1643 params = 6 + name_len;
1644 pSMB->MaxSetupCount = 0;
1648 pSMB->Reserved2 = 0;
1649 param_offset = offsetof(struct smb_com_transaction2_spi_req,
1650 InformationLevel) - 4;
1651 offset = param_offset + params;
1653 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
1654 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1656 cifsConvertToUCS((__le16 *) data_offset, fromName, PATH_MAX,
1657 nls_codepage, remap);
1658 name_len_target++; /* trailing null */
1659 name_len_target *= 2;
1660 } else { /* BB improve the check for buffer overruns BB */
1661 name_len_target = strnlen(fromName, PATH_MAX);
1662 name_len_target++; /* trailing null */
1663 strncpy(data_offset, fromName, name_len_target);
1666 pSMB->MaxParameterCount = cpu_to_le16(2);
1667 /* BB find exact max on data count below from sess*/
1668 pSMB->MaxDataCount = cpu_to_le16(1000);
1669 pSMB->SetupCount = 1;
1670 pSMB->Reserved3 = 0;
1671 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
1672 byte_count = 3 /* pad */ + params + name_len_target;
1673 pSMB->ParameterCount = cpu_to_le16(params);
1674 pSMB->TotalParameterCount = pSMB->ParameterCount;
1675 pSMB->DataCount = cpu_to_le16(name_len_target);
1676 pSMB->TotalDataCount = pSMB->DataCount;
1677 pSMB->ParameterOffset = cpu_to_le16(param_offset);
1678 pSMB->DataOffset = cpu_to_le16(offset);
1679 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_HLINK);
1680 pSMB->Reserved4 = 0;
1681 pSMB->hdr.smb_buf_length += byte_count;
1682 pSMB->ByteCount = cpu_to_le16(byte_count);
1683 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1684 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1685 cifs_stats_inc(&tcon->num_hardlinks);
1687 cFYI(1, ("Send error in SetPathInfo (hard link) = %d", rc));
1690 cifs_buf_release(pSMB);
1692 goto createHardLinkRetry;
1698 CIFSCreateHardLink(const int xid, struct cifsTconInfo *tcon,
1699 const char *fromName, const char *toName,
1700 const struct nls_table *nls_codepage, int remap)
1703 NT_RENAME_REQ *pSMB = NULL;
1704 RENAME_RSP *pSMBr = NULL;
1706 int name_len, name_len2;
1709 cFYI(1, ("In CIFSCreateHardLink"));
1710 winCreateHardLinkRetry:
1712 rc = smb_init(SMB_COM_NT_RENAME, 4, tcon, (void **) &pSMB,
1717 pSMB->SearchAttributes =
1718 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
1720 pSMB->Flags = cpu_to_le16(CREATE_HARD_LINK);
1721 pSMB->ClusterCount = 0;
1723 pSMB->BufferFormat = 0x04;
1725 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1727 cifsConvertToUCS((__le16 *) pSMB->OldFileName, fromName,
1728 PATH_MAX, nls_codepage, remap);
1729 name_len++; /* trailing null */
1731 pSMB->OldFileName[name_len] = 0; /* pad */
1732 pSMB->OldFileName[name_len + 1] = 0x04;
1734 cifsConvertToUCS((__le16 *)&pSMB->OldFileName[name_len + 2],
1735 toName, PATH_MAX, nls_codepage, remap);
1736 name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
1737 name_len2 *= 2; /* convert to bytes */
1738 } else { /* BB improve the check for buffer overruns BB */
1739 name_len = strnlen(fromName, PATH_MAX);
1740 name_len++; /* trailing null */
1741 strncpy(pSMB->OldFileName, fromName, name_len);
1742 name_len2 = strnlen(toName, PATH_MAX);
1743 name_len2++; /* trailing null */
1744 pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */
1745 strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2);
1746 name_len2++; /* trailing null */
1747 name_len2++; /* signature byte */
1750 count = 1 /* string type byte */ + name_len + name_len2;
1751 pSMB->hdr.smb_buf_length += count;
1752 pSMB->ByteCount = cpu_to_le16(count);
1754 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1755 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1756 cifs_stats_inc(&tcon->num_hardlinks);
1758 cFYI(1, ("Send error in hard link (NT rename) = %d", rc));
1760 cifs_buf_release(pSMB);
1762 goto winCreateHardLinkRetry;
1768 CIFSSMBUnixQuerySymLink(const int xid, struct cifsTconInfo *tcon,
1769 const unsigned char *searchName,
1770 char *symlinkinfo, const int buflen,
1771 const struct nls_table *nls_codepage)
1773 /* SMB_QUERY_FILE_UNIX_LINK */
1774 TRANSACTION2_QPI_REQ *pSMB = NULL;
1775 TRANSACTION2_QPI_RSP *pSMBr = NULL;
1779 __u16 params, byte_count;
1781 cFYI(1, ("In QPathSymLinkInfo (Unix) for path %s", searchName));
1784 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
1789 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1791 cifs_strtoUCS((wchar_t *) pSMB->FileName, searchName, PATH_MAX
1792 /* find define for this maxpathcomponent */
1794 name_len++; /* trailing null */
1796 } else { /* BB improve the check for buffer overruns BB */
1797 name_len = strnlen(searchName, PATH_MAX);
1798 name_len++; /* trailing null */
1799 strncpy(pSMB->FileName, searchName, name_len);
1802 params = 2 /* level */ + 4 /* rsrvd */ + name_len /* incl null */ ;
1803 pSMB->TotalDataCount = 0;
1804 pSMB->MaxParameterCount = cpu_to_le16(2);
1805 /* BB find exact max data count below from sess structure BB */
1806 pSMB->MaxDataCount = cpu_to_le16(4000);
1807 pSMB->MaxSetupCount = 0;
1811 pSMB->Reserved2 = 0;
1812 pSMB->ParameterOffset = cpu_to_le16(offsetof(
1813 struct smb_com_transaction2_qpi_req ,InformationLevel) - 4);
1814 pSMB->DataCount = 0;
1815 pSMB->DataOffset = 0;
1816 pSMB->SetupCount = 1;
1817 pSMB->Reserved3 = 0;
1818 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
1819 byte_count = params + 1 /* pad */ ;
1820 pSMB->TotalParameterCount = cpu_to_le16(params);
1821 pSMB->ParameterCount = pSMB->TotalParameterCount;
1822 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_LINK);
1823 pSMB->Reserved4 = 0;
1824 pSMB->hdr.smb_buf_length += byte_count;
1825 pSMB->ByteCount = cpu_to_le16(byte_count);
1827 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1828 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1830 cFYI(1, ("Send error in QuerySymLinkInfo = %d", rc));
1832 /* decode response */
1834 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
1835 if (rc || (pSMBr->ByteCount < 2))
1836 /* BB also check enough total bytes returned */
1837 rc = -EIO; /* bad smb */
1839 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
1840 __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
1842 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
1843 name_len = UniStrnlen((wchar_t *) ((char *)
1844 &pSMBr->hdr.Protocol +data_offset),
1845 min_t(const int, buflen,count) / 2);
1846 /* BB FIXME investigate remapping reserved chars here */
1847 cifs_strfromUCS_le(symlinkinfo,
1848 (wchar_t *) ((char *)&pSMBr->hdr.Protocol +
1850 name_len, nls_codepage);
1852 strncpy(symlinkinfo,
1853 (char *) &pSMBr->hdr.Protocol +
1855 min_t(const int, buflen, count));
1857 symlinkinfo[buflen] = 0;
1858 /* just in case so calling code does not go off the end of buffer */
1861 cifs_buf_release(pSMB);
1863 goto querySymLinkRetry;
1868 CIFSSMBQueryReparseLinkInfo(const int xid, struct cifsTconInfo *tcon,
1869 const unsigned char *searchName,
1870 char *symlinkinfo, const int buflen,__u16 fid,
1871 const struct nls_table *nls_codepage)
1876 struct smb_com_transaction_ioctl_req * pSMB;
1877 struct smb_com_transaction_ioctl_rsp * pSMBr;
1879 cFYI(1, ("In Windows reparse style QueryLink for path %s", searchName));
1880 rc = smb_init(SMB_COM_NT_TRANSACT, 23, tcon, (void **) &pSMB,
1885 pSMB->TotalParameterCount = 0 ;
1886 pSMB->TotalDataCount = 0;
1887 pSMB->MaxParameterCount = cpu_to_le32(2);
1888 /* BB find exact data count max from sess structure BB */
1889 pSMB->MaxDataCount = cpu_to_le32(4000);
1890 pSMB->MaxSetupCount = 4;
1892 pSMB->ParameterOffset = 0;
1893 pSMB->DataCount = 0;
1894 pSMB->DataOffset = 0;
1895 pSMB->SetupCount = 4;
1896 pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_IOCTL);
1897 pSMB->ParameterCount = pSMB->TotalParameterCount;
1898 pSMB->FunctionCode = cpu_to_le32(FSCTL_GET_REPARSE_POINT);
1899 pSMB->IsFsctl = 1; /* FSCTL */
1900 pSMB->IsRootFlag = 0;
1901 pSMB->Fid = fid; /* file handle always le */
1902 pSMB->ByteCount = 0;
1904 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1905 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1907 cFYI(1, ("Send error in QueryReparseLinkInfo = %d", rc));
1908 } else { /* decode response */
1909 __u32 data_offset = le32_to_cpu(pSMBr->DataOffset);
1910 __u32 data_count = le32_to_cpu(pSMBr->DataCount);
1911 if ((pSMBr->ByteCount < 2) || (data_offset > 512))
1912 /* BB also check enough total bytes returned */
1913 rc = -EIO; /* bad smb */
1915 if(data_count && (data_count < 2048)) {
1916 char * end_of_smb = pSMBr->ByteCount + (char *)&pSMBr->ByteCount;
1918 struct reparse_data * reparse_buf = (struct reparse_data *)
1919 ((char *)&pSMBr->hdr.Protocol + data_offset);
1920 if((char*)reparse_buf >= end_of_smb) {
1924 if((reparse_buf->LinkNamesBuf +
1925 reparse_buf->TargetNameOffset +
1926 reparse_buf->TargetNameLen) >
1928 cFYI(1,("reparse buf extended beyond SMB"));
1933 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
1934 name_len = UniStrnlen((wchar_t *)
1935 (reparse_buf->LinkNamesBuf +
1936 reparse_buf->TargetNameOffset),
1937 min(buflen/2, reparse_buf->TargetNameLen / 2));
1938 cifs_strfromUCS_le(symlinkinfo,
1939 (wchar_t *) (reparse_buf->LinkNamesBuf +
1940 reparse_buf->TargetNameOffset),
1941 name_len, nls_codepage);
1942 } else { /* ASCII names */
1943 strncpy(symlinkinfo,reparse_buf->LinkNamesBuf +
1944 reparse_buf->TargetNameOffset,
1945 min_t(const int, buflen, reparse_buf->TargetNameLen));
1949 cFYI(1,("Invalid return data count on get reparse info ioctl"));
1951 symlinkinfo[buflen] = 0; /* just in case so the caller
1952 does not go off the end of the buffer */
1953 cFYI(1,("readlink result - %s ",symlinkinfo));
1957 cifs_buf_release(pSMB);
1959 /* Note: On -EAGAIN error only caller can retry on handle based calls
1960 since file handle passed in no longer valid */
1965 #ifdef CONFIG_CIFS_POSIX
1967 /*Convert an Access Control Entry from wire format to local POSIX xattr format*/
1968 static void cifs_convert_ace(posix_acl_xattr_entry * ace, struct cifs_posix_ace * cifs_ace)
1970 /* u8 cifs fields do not need le conversion */
1971 ace->e_perm = (__u16)cifs_ace->cifs_e_perm;
1972 ace->e_tag = (__u16)cifs_ace->cifs_e_tag;
1973 ace->e_id = (__u32)le64_to_cpu(cifs_ace->cifs_uid);
1974 /* cFYI(1,("perm %d tag %d id %d",ace->e_perm,ace->e_tag,ace->e_id)); */
1979 /* Convert ACL from CIFS POSIX wire format to local Linux POSIX ACL xattr */
1980 static int cifs_copy_posix_acl(char * trgt,char * src, const int buflen,
1981 const int acl_type,const int size_of_data_area)
1986 struct cifs_posix_ace * pACE;
1987 struct cifs_posix_acl * cifs_acl = (struct cifs_posix_acl *)src;
1988 posix_acl_xattr_header * local_acl = (posix_acl_xattr_header *)trgt;
1990 if (le16_to_cpu(cifs_acl->version) != CIFS_ACL_VERSION)
1993 if(acl_type & ACL_TYPE_ACCESS) {
1994 count = le16_to_cpu(cifs_acl->access_entry_count);
1995 pACE = &cifs_acl->ace_array[0];
1996 size = sizeof(struct cifs_posix_acl);
1997 size += sizeof(struct cifs_posix_ace) * count;
1998 /* check if we would go beyond end of SMB */
1999 if(size_of_data_area < size) {
2000 cFYI(1,("bad CIFS POSIX ACL size %d vs. %d",size_of_data_area,size));
2003 } else if(acl_type & ACL_TYPE_DEFAULT) {
2004 count = le16_to_cpu(cifs_acl->access_entry_count);
2005 size = sizeof(struct cifs_posix_acl);
2006 size += sizeof(struct cifs_posix_ace) * count;
2007 /* skip past access ACEs to get to default ACEs */
2008 pACE = &cifs_acl->ace_array[count];
2009 count = le16_to_cpu(cifs_acl->default_entry_count);
2010 size += sizeof(struct cifs_posix_ace) * count;
2011 /* check if we would go beyond end of SMB */
2012 if(size_of_data_area < size)
2019 size = posix_acl_xattr_size(count);
2020 if((buflen == 0) || (local_acl == NULL)) {
2021 /* used to query ACL EA size */
2022 } else if(size > buflen) {
2024 } else /* buffer big enough */ {
2025 local_acl->a_version = POSIX_ACL_XATTR_VERSION;
2026 for(i = 0;i < count ;i++) {
2027 cifs_convert_ace(&local_acl->a_entries[i],pACE);
2034 static __u16 convert_ace_to_cifs_ace(struct cifs_posix_ace * cifs_ace,
2035 const posix_acl_xattr_entry * local_ace)
2037 __u16 rc = 0; /* 0 = ACL converted ok */
2039 cifs_ace->cifs_e_perm = (__u8)cpu_to_le16(local_ace->e_perm);
2040 cifs_ace->cifs_e_tag = (__u8)cpu_to_le16(local_ace->e_tag);
2041 /* BB is there a better way to handle the large uid? */
2042 if(local_ace->e_id == -1) {
2043 /* Probably no need to le convert -1 on any arch but can not hurt */
2044 cifs_ace->cifs_uid = cpu_to_le64(-1);
2046 cifs_ace->cifs_uid = (__u64)cpu_to_le32(local_ace->e_id);
2047 /*cFYI(1,("perm %d tag %d id %d",ace->e_perm,ace->e_tag,ace->e_id));*/
2051 /* Convert ACL from local Linux POSIX xattr to CIFS POSIX ACL wire format */
2052 static __u16 ACL_to_cifs_posix(char * parm_data,const char * pACL,const int buflen,
2056 struct cifs_posix_acl * cifs_acl = (struct cifs_posix_acl *)parm_data;
2057 posix_acl_xattr_header * local_acl = (posix_acl_xattr_header *)pACL;
2061 if((buflen == 0) || (pACL == NULL) || (cifs_acl == NULL))
2064 count = posix_acl_xattr_count((size_t)buflen);
2065 cFYI(1,("setting acl with %d entries from buf of length %d and version of %d",
2066 count,buflen,local_acl->a_version));
2067 if(local_acl->a_version != 2) {
2068 cFYI(1,("unknown POSIX ACL version %d",local_acl->a_version));
2071 cifs_acl->version = cpu_to_le16(1);
2072 if(acl_type == ACL_TYPE_ACCESS)
2073 cifs_acl->access_entry_count = count;
2074 else if(acl_type == ACL_TYPE_DEFAULT)
2075 cifs_acl->default_entry_count = count;
2077 cFYI(1,("unknown ACL type %d",acl_type));
2080 for(i=0;i<count;i++) {
2081 rc = convert_ace_to_cifs_ace(&cifs_acl->ace_array[i],
2082 &local_acl->a_entries[i]);
2084 /* ACE not converted */
2089 rc = (__u16)(count * sizeof(struct cifs_posix_ace));
2090 rc += sizeof(struct cifs_posix_acl);
2091 /* BB add check to make sure ACL does not overflow SMB */
2097 CIFSSMBGetPosixACL(const int xid, struct cifsTconInfo *tcon,
2098 const unsigned char *searchName,
2099 char *acl_inf, const int buflen, const int acl_type,
2100 const struct nls_table *nls_codepage, int remap)
2102 /* SMB_QUERY_POSIX_ACL */
2103 TRANSACTION2_QPI_REQ *pSMB = NULL;
2104 TRANSACTION2_QPI_RSP *pSMBr = NULL;
2108 __u16 params, byte_count;
2110 cFYI(1, ("In GetPosixACL (Unix) for path %s", searchName));
2113 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2118 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2120 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
2121 PATH_MAX, nls_codepage, remap);
2122 name_len++; /* trailing null */
2124 pSMB->FileName[name_len] = 0;
2125 pSMB->FileName[name_len+1] = 0;
2126 } else { /* BB improve the check for buffer overruns BB */
2127 name_len = strnlen(searchName, PATH_MAX);
2128 name_len++; /* trailing null */
2129 strncpy(pSMB->FileName, searchName, name_len);
2132 params = 2 /* level */ + 4 /* rsrvd */ + name_len /* incl null */ ;
2133 pSMB->TotalDataCount = 0;
2134 pSMB->MaxParameterCount = cpu_to_le16(2);
2135 /* BB find exact max data count below from sess structure BB */
2136 pSMB->MaxDataCount = cpu_to_le16(4000);
2137 pSMB->MaxSetupCount = 0;
2141 pSMB->Reserved2 = 0;
2142 pSMB->ParameterOffset = cpu_to_le16(
2143 offsetof(struct smb_com_transaction2_qpi_req ,InformationLevel) - 4);
2144 pSMB->DataCount = 0;
2145 pSMB->DataOffset = 0;
2146 pSMB->SetupCount = 1;
2147 pSMB->Reserved3 = 0;
2148 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
2149 byte_count = params + 1 /* pad */ ;
2150 pSMB->TotalParameterCount = cpu_to_le16(params);
2151 pSMB->ParameterCount = pSMB->TotalParameterCount;
2152 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_POSIX_ACL);
2153 pSMB->Reserved4 = 0;
2154 pSMB->hdr.smb_buf_length += byte_count;
2155 pSMB->ByteCount = cpu_to_le16(byte_count);
2157 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2158 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2160 cFYI(1, ("Send error in Query POSIX ACL = %d", rc));
2162 /* decode response */
2164 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
2165 if (rc || (pSMBr->ByteCount < 2))
2166 /* BB also check enough total bytes returned */
2167 rc = -EIO; /* bad smb */
2169 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
2170 __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
2171 rc = cifs_copy_posix_acl(acl_inf,
2172 (char *)&pSMBr->hdr.Protocol+data_offset,
2173 buflen,acl_type,count);
2176 cifs_buf_release(pSMB);
2183 CIFSSMBSetPosixACL(const int xid, struct cifsTconInfo *tcon,
2184 const unsigned char *fileName,
2185 const char *local_acl, const int buflen,
2187 const struct nls_table *nls_codepage, int remap)
2189 struct smb_com_transaction2_spi_req *pSMB = NULL;
2190 struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
2194 int bytes_returned = 0;
2195 __u16 params, byte_count, data_count, param_offset, offset;
2197 cFYI(1, ("In SetPosixACL (Unix) for path %s", fileName));
2199 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2203 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2205 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
2206 PATH_MAX, nls_codepage, remap);
2207 name_len++; /* trailing null */
2209 } else { /* BB improve the check for buffer overruns BB */
2210 name_len = strnlen(fileName, PATH_MAX);
2211 name_len++; /* trailing null */
2212 strncpy(pSMB->FileName, fileName, name_len);
2214 params = 6 + name_len;
2215 pSMB->MaxParameterCount = cpu_to_le16(2);
2216 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB size from sess */
2217 pSMB->MaxSetupCount = 0;
2221 pSMB->Reserved2 = 0;
2222 param_offset = offsetof(struct smb_com_transaction2_spi_req,
2223 InformationLevel) - 4;
2224 offset = param_offset + params;
2225 parm_data = ((char *) &pSMB->hdr.Protocol) + offset;
2226 pSMB->ParameterOffset = cpu_to_le16(param_offset);
2228 /* convert to on the wire format for POSIX ACL */
2229 data_count = ACL_to_cifs_posix(parm_data,local_acl,buflen,acl_type);
2231 if(data_count == 0) {
2233 goto setACLerrorExit;
2235 pSMB->DataOffset = cpu_to_le16(offset);
2236 pSMB->SetupCount = 1;
2237 pSMB->Reserved3 = 0;
2238 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
2239 pSMB->InformationLevel = cpu_to_le16(SMB_SET_POSIX_ACL);
2240 byte_count = 3 /* pad */ + params + data_count;
2241 pSMB->DataCount = cpu_to_le16(data_count);
2242 pSMB->TotalDataCount = pSMB->DataCount;
2243 pSMB->ParameterCount = cpu_to_le16(params);
2244 pSMB->TotalParameterCount = pSMB->ParameterCount;
2245 pSMB->Reserved4 = 0;
2246 pSMB->hdr.smb_buf_length += byte_count;
2247 pSMB->ByteCount = cpu_to_le16(byte_count);
2248 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2249 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2251 cFYI(1, ("Set POSIX ACL returned %d", rc));
2255 cifs_buf_release(pSMB);
2261 /* BB fix tabs in this function FIXME BB */
2263 CIFSGetExtAttr(const int xid, struct cifsTconInfo *tcon,
2264 const int netfid, __u64 * pExtAttrBits, __u64 *pMask)
2267 struct smb_t2_qfi_req *pSMB = NULL;
2268 struct smb_t2_qfi_rsp *pSMBr = NULL;
2270 __u16 params, byte_count;
2272 cFYI(1,("In GetExtAttr"));
2277 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2282 params = 2 /* level */ +2 /* fid */;
2283 pSMB->t2.TotalDataCount = 0;
2284 pSMB->t2.MaxParameterCount = cpu_to_le16(4);
2285 /* BB find exact max data count below from sess structure BB */
2286 pSMB->t2.MaxDataCount = cpu_to_le16(4000);
2287 pSMB->t2.MaxSetupCount = 0;
2288 pSMB->t2.Reserved = 0;
2290 pSMB->t2.Timeout = 0;
2291 pSMB->t2.Reserved2 = 0;
2292 pSMB->t2.ParameterOffset = cpu_to_le16(offsetof(struct smb_t2_qfi_req,
2294 pSMB->t2.DataCount = 0;
2295 pSMB->t2.DataOffset = 0;
2296 pSMB->t2.SetupCount = 1;
2297 pSMB->t2.Reserved3 = 0;
2298 pSMB->t2.SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION);
2299 byte_count = params + 1 /* pad */ ;
2300 pSMB->t2.TotalParameterCount = cpu_to_le16(params);
2301 pSMB->t2.ParameterCount = pSMB->t2.TotalParameterCount;
2302 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_ATTR_FLAGS);
2305 pSMB->hdr.smb_buf_length += byte_count;
2306 pSMB->t2.ByteCount = cpu_to_le16(byte_count);
2308 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2309 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2311 cFYI(1, ("error %d in GetExtAttr", rc));
2313 /* decode response */
2314 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
2315 if (rc || (pSMBr->ByteCount < 2))
2316 /* BB also check enough total bytes returned */
2317 /* If rc should we check for EOPNOSUPP and
2318 disable the srvino flag? or in caller? */
2319 rc = -EIO; /* bad smb */
2321 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
2322 __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
2323 struct file_chattr_info * pfinfo;
2324 /* BB Do we need a cast or hash here ? */
2326 cFYI(1, ("Illegal size ret in GetExtAttr"));
2330 pfinfo = (struct file_chattr_info *)
2331 (data_offset + (char *) &pSMBr->hdr.Protocol);
2332 *pExtAttrBits = le64_to_cpu(pfinfo->mode);
2333 *pMask = le64_to_cpu(pfinfo->mask);
2337 cifs_buf_release(pSMB);
2339 goto GetExtAttrRetry;
2344 #endif /* CONFIG_POSIX */
2346 /* Legacy Query Path Information call for lookup to old servers such
2348 int SMBQueryInformation(const int xid, struct cifsTconInfo *tcon,
2349 const unsigned char *searchName,
2350 FILE_ALL_INFO * pFinfo,
2351 const struct nls_table *nls_codepage, int remap)
2353 QUERY_INFORMATION_REQ * pSMB;
2354 QUERY_INFORMATION_RSP * pSMBr;
2359 cFYI(1, ("In SMBQPath path %s", searchName));
2361 rc = smb_init(SMB_COM_QUERY_INFORMATION, 0, tcon, (void **) &pSMB,
2366 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2368 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
2369 PATH_MAX, nls_codepage, remap);
2370 name_len++; /* trailing null */
2373 name_len = strnlen(searchName, PATH_MAX);
2374 name_len++; /* trailing null */
2375 strncpy(pSMB->FileName, searchName, name_len);
2377 pSMB->BufferFormat = 0x04;
2378 name_len++; /* account for buffer type byte */
2379 pSMB->hdr.smb_buf_length += (__u16) name_len;
2380 pSMB->ByteCount = cpu_to_le16(name_len);
2382 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2383 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2385 cFYI(1, ("Send error in QueryInfo = %d", rc));
2386 } else if (pFinfo) { /* decode response */
2387 memset(pFinfo, 0, sizeof(FILE_ALL_INFO));
2388 pFinfo->AllocationSize = (__le64) pSMBr->size;
2389 pFinfo->EndOfFile = (__le64) pSMBr->size;
2390 pFinfo->Attributes = (__le32) pSMBr->attr;
2392 rc = -EIO; /* bad buffer passed in */
2394 cifs_buf_release(pSMB);
2406 CIFSSMBQPathInfo(const int xid, struct cifsTconInfo *tcon,
2407 const unsigned char *searchName,
2408 FILE_ALL_INFO * pFindData,
2409 const struct nls_table *nls_codepage, int remap)
2411 /* level 263 SMB_QUERY_FILE_ALL_INFO */
2412 TRANSACTION2_QPI_REQ *pSMB = NULL;
2413 TRANSACTION2_QPI_RSP *pSMBr = NULL;
2417 __u16 params, byte_count;
2419 /* cFYI(1, ("In QPathInfo path %s", searchName)); */
2421 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2426 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2428 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
2429 PATH_MAX, nls_codepage, remap);
2430 name_len++; /* trailing null */
2432 } else { /* BB improve the check for buffer overruns BB */
2433 name_len = strnlen(searchName, PATH_MAX);
2434 name_len++; /* trailing null */
2435 strncpy(pSMB->FileName, searchName, name_len);
2438 params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */ ;
2439 pSMB->TotalDataCount = 0;
2440 pSMB->MaxParameterCount = cpu_to_le16(2);
2441 pSMB->MaxDataCount = cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
2442 pSMB->MaxSetupCount = 0;
2446 pSMB->Reserved2 = 0;
2447 pSMB->ParameterOffset = cpu_to_le16(offsetof(
2448 struct smb_com_transaction2_qpi_req ,InformationLevel) - 4);
2449 pSMB->DataCount = 0;
2450 pSMB->DataOffset = 0;
2451 pSMB->SetupCount = 1;
2452 pSMB->Reserved3 = 0;
2453 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
2454 byte_count = params + 1 /* pad */ ;
2455 pSMB->TotalParameterCount = cpu_to_le16(params);
2456 pSMB->ParameterCount = pSMB->TotalParameterCount;
2457 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_ALL_INFO);
2458 pSMB->Reserved4 = 0;
2459 pSMB->hdr.smb_buf_length += byte_count;
2460 pSMB->ByteCount = cpu_to_le16(byte_count);
2462 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2463 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2465 cFYI(1, ("Send error in QPathInfo = %d", rc));
2466 } else { /* decode response */
2467 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
2469 if (rc || (pSMBr->ByteCount < 40))
2470 rc = -EIO; /* bad smb */
2471 else if (pFindData){
2472 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
2473 memcpy((char *) pFindData,
2474 (char *) &pSMBr->hdr.Protocol +
2475 data_offset, sizeof (FILE_ALL_INFO));
2479 cifs_buf_release(pSMB);
2481 goto QPathInfoRetry;
2487 CIFSSMBUnixQPathInfo(const int xid, struct cifsTconInfo *tcon,
2488 const unsigned char *searchName,
2489 FILE_UNIX_BASIC_INFO * pFindData,
2490 const struct nls_table *nls_codepage, int remap)
2492 /* SMB_QUERY_FILE_UNIX_BASIC */
2493 TRANSACTION2_QPI_REQ *pSMB = NULL;
2494 TRANSACTION2_QPI_RSP *pSMBr = NULL;
2496 int bytes_returned = 0;
2498 __u16 params, byte_count;
2500 cFYI(1, ("In QPathInfo (Unix) the path %s", searchName));
2502 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2507 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2509 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
2510 PATH_MAX, nls_codepage, remap);
2511 name_len++; /* trailing null */
2513 } else { /* BB improve the check for buffer overruns BB */
2514 name_len = strnlen(searchName, PATH_MAX);
2515 name_len++; /* trailing null */
2516 strncpy(pSMB->FileName, searchName, name_len);
2519 params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */ ;
2520 pSMB->TotalDataCount = 0;
2521 pSMB->MaxParameterCount = cpu_to_le16(2);
2522 /* BB find exact max SMB PDU from sess structure BB */
2523 pSMB->MaxDataCount = cpu_to_le16(4000);
2524 pSMB->MaxSetupCount = 0;
2528 pSMB->Reserved2 = 0;
2529 pSMB->ParameterOffset = cpu_to_le16(offsetof(
2530 struct smb_com_transaction2_qpi_req ,InformationLevel) - 4);
2531 pSMB->DataCount = 0;
2532 pSMB->DataOffset = 0;
2533 pSMB->SetupCount = 1;
2534 pSMB->Reserved3 = 0;
2535 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
2536 byte_count = params + 1 /* pad */ ;
2537 pSMB->TotalParameterCount = cpu_to_le16(params);
2538 pSMB->ParameterCount = pSMB->TotalParameterCount;
2539 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC);
2540 pSMB->Reserved4 = 0;
2541 pSMB->hdr.smb_buf_length += byte_count;
2542 pSMB->ByteCount = cpu_to_le16(byte_count);
2544 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2545 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2547 cFYI(1, ("Send error in QPathInfo = %d", rc));
2548 } else { /* decode response */
2549 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
2551 if (rc || (pSMBr->ByteCount < sizeof(FILE_UNIX_BASIC_INFO))) {
2552 rc = -EIO; /* bad smb */
2554 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
2555 memcpy((char *) pFindData,
2556 (char *) &pSMBr->hdr.Protocol +
2558 sizeof (FILE_UNIX_BASIC_INFO));
2561 cifs_buf_release(pSMB);
2563 goto UnixQPathInfoRetry;
2568 #if 0 /* function unused at present */
2569 int CIFSFindSingle(const int xid, struct cifsTconInfo *tcon,
2570 const char *searchName, FILE_ALL_INFO * findData,
2571 const struct nls_table *nls_codepage)
2573 /* level 257 SMB_ */
2574 TRANSACTION2_FFIRST_REQ *pSMB = NULL;
2575 TRANSACTION2_FFIRST_RSP *pSMBr = NULL;
2579 __u16 params, byte_count;
2581 cFYI(1, ("In FindUnique"));
2583 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2588 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2590 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName, PATH_MAX
2591 /* find define for this maxpathcomponent */
2593 name_len++; /* trailing null */
2595 } else { /* BB improve the check for buffer overruns BB */
2596 name_len = strnlen(searchName, PATH_MAX);
2597 name_len++; /* trailing null */
2598 strncpy(pSMB->FileName, searchName, name_len);
2601 params = 12 + name_len /* includes null */ ;
2602 pSMB->TotalDataCount = 0; /* no EAs */
2603 pSMB->MaxParameterCount = cpu_to_le16(2);
2604 pSMB->MaxDataCount = cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
2605 pSMB->MaxSetupCount = 0;
2609 pSMB->Reserved2 = 0;
2610 pSMB->ParameterOffset = cpu_to_le16(
2611 offsetof(struct smb_com_transaction2_ffirst_req,InformationLevel) - 4);
2612 pSMB->DataCount = 0;
2613 pSMB->DataOffset = 0;
2614 pSMB->SetupCount = 1; /* one byte, no need to le convert */
2615 pSMB->Reserved3 = 0;
2616 pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_FIRST);
2617 byte_count = params + 1 /* pad */ ;
2618 pSMB->TotalParameterCount = cpu_to_le16(params);
2619 pSMB->ParameterCount = pSMB->TotalParameterCount;
2620 pSMB->SearchAttributes =
2621 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
2623 pSMB->SearchCount = cpu_to_le16(16); /* BB increase */
2624 pSMB->SearchFlags = cpu_to_le16(1);
2625 pSMB->InformationLevel = cpu_to_le16(SMB_FIND_FILE_DIRECTORY_INFO);
2626 pSMB->SearchStorageType = 0; /* BB what should we set this to? BB */
2627 pSMB->hdr.smb_buf_length += byte_count;
2628 pSMB->ByteCount = cpu_to_le16(byte_count);
2630 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2631 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2634 cFYI(1, ("Send error in FindFileDirInfo = %d", rc));
2635 } else { /* decode response */
2636 cifs_stats_inc(&tcon->num_ffirst);
2640 cifs_buf_release(pSMB);
2642 goto findUniqueRetry;
2646 #endif /* end unused (temporarily) function */
2648 /* xid, tcon, searchName and codepage are input parms, rest are returned */
2650 CIFSFindFirst(const int xid, struct cifsTconInfo *tcon,
2651 const char *searchName,
2652 const struct nls_table *nls_codepage,
2654 struct cifs_search_info * psrch_inf, int remap, const char dirsep)
2656 /* level 257 SMB_ */
2657 TRANSACTION2_FFIRST_REQ *pSMB = NULL;
2658 TRANSACTION2_FFIRST_RSP *pSMBr = NULL;
2659 T2_FFIRST_RSP_PARMS * parms;
2661 int bytes_returned = 0;
2663 __u16 params, byte_count;
2665 cFYI(1, ("In FindFirst for %s",searchName));
2668 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2673 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2675 cifsConvertToUCS((__le16 *) pSMB->FileName,searchName,
2676 PATH_MAX, nls_codepage, remap);
2677 /* We can not add the asterik earlier in case
2678 it got remapped to 0xF03A as if it were part of the
2679 directory name instead of a wildcard */
2681 pSMB->FileName[name_len] = dirsep;
2682 pSMB->FileName[name_len+1] = 0;
2683 pSMB->FileName[name_len+2] = '*';
2684 pSMB->FileName[name_len+3] = 0;
2685 name_len += 4; /* now the trailing null */
2686 pSMB->FileName[name_len] = 0; /* null terminate just in case */
2687 pSMB->FileName[name_len+1] = 0;
2689 } else { /* BB add check for overrun of SMB buf BB */
2690 name_len = strnlen(searchName, PATH_MAX);
2691 /* BB fix here and in unicode clause above ie
2692 if(name_len > buffersize-header)
2693 free buffer exit; BB */
2694 strncpy(pSMB->FileName, searchName, name_len);
2695 pSMB->FileName[name_len] = dirsep;
2696 pSMB->FileName[name_len+1] = '*';
2697 pSMB->FileName[name_len+2] = 0;
2701 params = 12 + name_len /* includes null */ ;
2702 pSMB->TotalDataCount = 0; /* no EAs */
2703 pSMB->MaxParameterCount = cpu_to_le16(10);
2704 pSMB->MaxDataCount = cpu_to_le16((tcon->ses->server->maxBuf -
2705 MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
2706 pSMB->MaxSetupCount = 0;
2710 pSMB->Reserved2 = 0;
2711 byte_count = params + 1 /* pad */ ;
2712 pSMB->TotalParameterCount = cpu_to_le16(params);
2713 pSMB->ParameterCount = pSMB->TotalParameterCount;
2714 pSMB->ParameterOffset = cpu_to_le16(
2715 offsetof(struct smb_com_transaction2_ffirst_req, SearchAttributes) - 4);
2716 pSMB->DataCount = 0;
2717 pSMB->DataOffset = 0;
2718 pSMB->SetupCount = 1; /* one byte, no need to make endian neutral */
2719 pSMB->Reserved3 = 0;
2720 pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_FIRST);
2721 pSMB->SearchAttributes =
2722 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
2724 pSMB->SearchCount= cpu_to_le16(CIFSMaxBufSize/sizeof(FILE_UNIX_INFO));
2725 pSMB->SearchFlags = cpu_to_le16(CIFS_SEARCH_CLOSE_AT_END |
2726 CIFS_SEARCH_RETURN_RESUME);
2727 pSMB->InformationLevel = cpu_to_le16(psrch_inf->info_level);
2729 /* BB what should we set StorageType to? Does it matter? BB */
2730 pSMB->SearchStorageType = 0;
2731 pSMB->hdr.smb_buf_length += byte_count;
2732 pSMB->ByteCount = cpu_to_le16(byte_count);
2734 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2735 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2736 cifs_stats_inc(&tcon->num_ffirst);
2738 if (rc) {/* BB add logic to retry regular search if Unix search rejected unexpectedly by server */
2739 /* BB Add code to handle unsupported level rc */
2740 cFYI(1, ("Error in FindFirst = %d", rc));
2743 cifs_buf_release(pSMB);
2745 /* BB eventually could optimize out free and realloc of buf */
2748 goto findFirstRetry;
2749 } else { /* decode response */
2750 /* BB remember to free buffer if error BB */
2751 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
2753 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
2754 psrch_inf->unicode = TRUE;
2756 psrch_inf->unicode = FALSE;
2758 psrch_inf->ntwrk_buf_start = (char *)pSMBr;
2759 psrch_inf->srch_entries_start =
2760 (char *) &pSMBr->hdr.Protocol +
2761 le16_to_cpu(pSMBr->t2.DataOffset);
2762 parms = (T2_FFIRST_RSP_PARMS *)((char *) &pSMBr->hdr.Protocol +
2763 le16_to_cpu(pSMBr->t2.ParameterOffset));
2765 if(parms->EndofSearch)
2766 psrch_inf->endOfSearch = TRUE;
2768 psrch_inf->endOfSearch = FALSE;
2770 psrch_inf->entries_in_buffer = le16_to_cpu(parms->SearchCount);
2771 psrch_inf->index_of_last_entry =
2772 psrch_inf->entries_in_buffer;
2773 *pnetfid = parms->SearchHandle;
2775 cifs_buf_release(pSMB);
2782 int CIFSFindNext(const int xid, struct cifsTconInfo *tcon,
2783 __u16 searchHandle, struct cifs_search_info * psrch_inf)
2785 TRANSACTION2_FNEXT_REQ *pSMB = NULL;
2786 TRANSACTION2_FNEXT_RSP *pSMBr = NULL;
2787 T2_FNEXT_RSP_PARMS * parms;
2788 char *response_data;
2790 int bytes_returned, name_len;
2791 __u16 params, byte_count;
2793 cFYI(1, ("In FindNext"));
2795 if(psrch_inf->endOfSearch == TRUE)
2798 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2803 params = 14; /* includes 2 bytes of null string, converted to LE below */
2805 pSMB->TotalDataCount = 0; /* no EAs */
2806 pSMB->MaxParameterCount = cpu_to_le16(8);
2807 pSMB->MaxDataCount =
2808 cpu_to_le16((tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
2809 pSMB->MaxSetupCount = 0;
2813 pSMB->Reserved2 = 0;
2814 pSMB->ParameterOffset = cpu_to_le16(
2815 offsetof(struct smb_com_transaction2_fnext_req,SearchHandle) - 4);
2816 pSMB->DataCount = 0;
2817 pSMB->DataOffset = 0;
2818 pSMB->SetupCount = 1;
2819 pSMB->Reserved3 = 0;
2820 pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_NEXT);
2821 pSMB->SearchHandle = searchHandle; /* always kept as le */
2823 cpu_to_le16(CIFSMaxBufSize / sizeof (FILE_UNIX_INFO));
2824 /* test for Unix extensions */
2825 /* if (tcon->ses->capabilities & CAP_UNIX) {
2826 pSMB->InformationLevel = cpu_to_le16(SMB_FIND_FILE_UNIX);
2827 psrch_inf->info_level = SMB_FIND_FILE_UNIX;
2829 pSMB->InformationLevel =
2830 cpu_to_le16(SMB_FIND_FILE_DIRECTORY_INFO);
2831 psrch_inf->info_level = SMB_FIND_FILE_DIRECTORY_INFO;
2833 pSMB->InformationLevel = cpu_to_le16(psrch_inf->info_level);
2834 pSMB->ResumeKey = psrch_inf->resume_key;
2836 cpu_to_le16(CIFS_SEARCH_CLOSE_AT_END | CIFS_SEARCH_RETURN_RESUME);
2838 name_len = psrch_inf->resume_name_len;
2840 if(name_len < PATH_MAX) {
2841 memcpy(pSMB->ResumeFileName, psrch_inf->presume_name, name_len);
2842 byte_count += name_len;
2843 /* 14 byte parm len above enough for 2 byte null terminator */
2844 pSMB->ResumeFileName[name_len] = 0;
2845 pSMB->ResumeFileName[name_len+1] = 0;
2848 goto FNext2_err_exit;
2850 byte_count = params + 1 /* pad */ ;
2851 pSMB->TotalParameterCount = cpu_to_le16(params);
2852 pSMB->ParameterCount = pSMB->TotalParameterCount;
2853 pSMB->hdr.smb_buf_length += byte_count;
2854 pSMB->ByteCount = cpu_to_le16(byte_count);
2856 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2857 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2858 cifs_stats_inc(&tcon->num_fnext);
2861 psrch_inf->endOfSearch = TRUE;
2862 rc = 0; /* search probably was closed at end of search above */
2864 cFYI(1, ("FindNext returned = %d", rc));
2865 } else { /* decode response */
2866 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
2869 /* BB fixme add lock for file (srch_info) struct here */
2870 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
2871 psrch_inf->unicode = TRUE;
2873 psrch_inf->unicode = FALSE;
2874 response_data = (char *) &pSMBr->hdr.Protocol +
2875 le16_to_cpu(pSMBr->t2.ParameterOffset);
2876 parms = (T2_FNEXT_RSP_PARMS *)response_data;
2877 response_data = (char *)&pSMBr->hdr.Protocol +
2878 le16_to_cpu(pSMBr->t2.DataOffset);
2879 cifs_buf_release(psrch_inf->ntwrk_buf_start);
2880 psrch_inf->srch_entries_start = response_data;
2881 psrch_inf->ntwrk_buf_start = (char *)pSMB;
2882 if(parms->EndofSearch)
2883 psrch_inf->endOfSearch = TRUE;
2885 psrch_inf->endOfSearch = FALSE;
2887 psrch_inf->entries_in_buffer = le16_to_cpu(parms->SearchCount);
2888 psrch_inf->index_of_last_entry +=
2889 psrch_inf->entries_in_buffer;
2890 /* cFYI(1,("fnxt2 entries in buf %d index_of_last %d",psrch_inf->entries_in_buffer,psrch_inf->index_of_last_entry)); */
2892 /* BB fixme add unlock here */
2897 /* BB On error, should we leave previous search buf (and count and
2898 last entry fields) intact or free the previous one? */
2900 /* Note: On -EAGAIN error only caller can retry on handle based calls
2901 since file handle passed in no longer valid */
2904 cifs_buf_release(pSMB);
2910 CIFSFindClose(const int xid, struct cifsTconInfo *tcon, const __u16 searchHandle)
2913 FINDCLOSE_REQ *pSMB = NULL;
2914 CLOSE_RSP *pSMBr = NULL; /* BB removeme BB */
2917 cFYI(1, ("In CIFSSMBFindClose"));
2918 rc = small_smb_init(SMB_COM_FIND_CLOSE2, 1, tcon, (void **)&pSMB);
2920 /* no sense returning error if session restarted
2921 as file handle has been closed */
2927 pSMBr = (CLOSE_RSP *)pSMB; /* BB removeme BB */
2928 pSMB->FileID = searchHandle;
2929 pSMB->ByteCount = 0;
2930 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2931 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2933 cERROR(1, ("Send error in FindClose = %d", rc));
2935 cifs_stats_inc(&tcon->num_fclose);
2936 cifs_small_buf_release(pSMB);
2938 /* Since session is dead, search handle closed on server already */
2945 #ifdef CONFIG_CIFS_EXPERIMENTAL
2947 CIFSGetSrvInodeNumber(const int xid, struct cifsTconInfo *tcon,
2948 const unsigned char *searchName,
2949 __u64 * inode_number,
2950 const struct nls_table *nls_codepage, int remap)
2953 TRANSACTION2_QPI_REQ *pSMB = NULL;
2954 TRANSACTION2_QPI_RSP *pSMBr = NULL;
2955 int name_len, bytes_returned;
2956 __u16 params, byte_count;
2958 cFYI(1,("In GetSrvInodeNum for %s",searchName));
2962 GetInodeNumberRetry:
2963 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2969 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2971 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
2972 PATH_MAX,nls_codepage, remap);
2973 name_len++; /* trailing null */
2975 } else { /* BB improve the check for buffer overruns BB */
2976 name_len = strnlen(searchName, PATH_MAX);
2977 name_len++; /* trailing null */
2978 strncpy(pSMB->FileName, searchName, name_len);
2981 params = 2 /* level */ + 4 /* rsrvd */ + name_len /* incl null */ ;
2982 pSMB->TotalDataCount = 0;
2983 pSMB->MaxParameterCount = cpu_to_le16(2);
2984 /* BB find exact max data count below from sess structure BB */
2985 pSMB->MaxDataCount = cpu_to_le16(4000);
2986 pSMB->MaxSetupCount = 0;
2990 pSMB->Reserved2 = 0;
2991 pSMB->ParameterOffset = cpu_to_le16(offsetof(
2992 struct smb_com_transaction2_qpi_req ,InformationLevel) - 4);
2993 pSMB->DataCount = 0;
2994 pSMB->DataOffset = 0;
2995 pSMB->SetupCount = 1;
2996 pSMB->Reserved3 = 0;
2997 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
2998 byte_count = params + 1 /* pad */ ;
2999 pSMB->TotalParameterCount = cpu_to_le16(params);
3000 pSMB->ParameterCount = pSMB->TotalParameterCount;
3001 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_INTERNAL_INFO);
3002 pSMB->Reserved4 = 0;
3003 pSMB->hdr.smb_buf_length += byte_count;
3004 pSMB->ByteCount = cpu_to_le16(byte_count);
3006 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3007 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3009 cFYI(1, ("error %d in QueryInternalInfo", rc));
3011 /* decode response */
3012 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3013 if (rc || (pSMBr->ByteCount < 2))
3014 /* BB also check enough total bytes returned */
3015 /* If rc should we check for EOPNOSUPP and
3016 disable the srvino flag? or in caller? */
3017 rc = -EIO; /* bad smb */
3019 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3020 __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
3021 struct file_internal_info * pfinfo;
3022 /* BB Do we need a cast or hash here ? */
3024 cFYI(1, ("Illegal size ret in QryIntrnlInf"));
3026 goto GetInodeNumOut;
3028 pfinfo = (struct file_internal_info *)
3029 (data_offset + (char *) &pSMBr->hdr.Protocol);
3030 *inode_number = pfinfo->UniqueId;
3034 cifs_buf_release(pSMB);
3036 goto GetInodeNumberRetry;
3039 #endif /* CIFS_EXPERIMENTAL */
3042 CIFSGetDFSRefer(const int xid, struct cifsSesInfo *ses,
3043 const unsigned char *searchName,
3044 unsigned char **targetUNCs,
3045 unsigned int *number_of_UNC_in_array,
3046 const struct nls_table *nls_codepage, int remap)
3048 /* TRANS2_GET_DFS_REFERRAL */
3049 TRANSACTION2_GET_DFS_REFER_REQ *pSMB = NULL;
3050 TRANSACTION2_GET_DFS_REFER_RSP *pSMBr = NULL;
3051 struct dfs_referral_level_3 * referrals = NULL;
3057 __u16 params, byte_count;
3058 *number_of_UNC_in_array = 0;
3061 cFYI(1, ("In GetDFSRefer the path %s", searchName));
3065 rc = smb_init(SMB_COM_TRANSACTION2, 15, NULL, (void **) &pSMB,
3070 /* server pointer checked in called function,
3071 but should never be null here anyway */
3072 pSMB->hdr.Mid = GetNextMid(ses->server);
3073 pSMB->hdr.Tid = ses->ipc_tid;
3074 pSMB->hdr.Uid = ses->Suid;
3075 if (ses->capabilities & CAP_STATUS32) {
3076 pSMB->hdr.Flags2 |= SMBFLG2_ERR_STATUS;
3078 if (ses->capabilities & CAP_DFS) {
3079 pSMB->hdr.Flags2 |= SMBFLG2_DFS;
3082 if (ses->capabilities & CAP_UNICODE) {
3083 pSMB->hdr.Flags2 |= SMBFLG2_UNICODE;
3085 cifsConvertToUCS((__le16 *) pSMB->RequestFileName,
3086 searchName, PATH_MAX, nls_codepage, remap);
3087 name_len++; /* trailing null */
3089 } else { /* BB improve the check for buffer overruns BB */
3090 name_len = strnlen(searchName, PATH_MAX);
3091 name_len++; /* trailing null */
3092 strncpy(pSMB->RequestFileName, searchName, name_len);
3095 params = 2 /* level */ + name_len /*includes null */ ;
3096 pSMB->TotalDataCount = 0;
3097 pSMB->DataCount = 0;
3098 pSMB->DataOffset = 0;
3099 pSMB->MaxParameterCount = 0;
3100 pSMB->MaxDataCount = cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
3101 pSMB->MaxSetupCount = 0;
3105 pSMB->Reserved2 = 0;
3106 pSMB->ParameterOffset = cpu_to_le16(offsetof(
3107 struct smb_com_transaction2_get_dfs_refer_req, MaxReferralLevel) - 4);
3108 pSMB->SetupCount = 1;
3109 pSMB->Reserved3 = 0;
3110 pSMB->SubCommand = cpu_to_le16(TRANS2_GET_DFS_REFERRAL);
3111 byte_count = params + 3 /* pad */ ;
3112 pSMB->ParameterCount = cpu_to_le16(params);
3113 pSMB->TotalParameterCount = pSMB->ParameterCount;
3114 pSMB->MaxReferralLevel = cpu_to_le16(3);
3115 pSMB->hdr.smb_buf_length += byte_count;
3116 pSMB->ByteCount = cpu_to_le16(byte_count);
3118 rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB,
3119 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3121 cFYI(1, ("Send error in GetDFSRefer = %d", rc));
3122 } else { /* decode response */
3123 /* BB Add logic to parse referrals here */
3124 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3126 if (rc || (pSMBr->ByteCount < 17)) /* BB also check enough total bytes returned */
3127 rc = -EIO; /* bad smb */
3129 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3130 __u16 data_count = le16_to_cpu(pSMBr->t2.DataCount);
3133 ("Decoding GetDFSRefer response. BCC: %d Offset %d",
3134 pSMBr->ByteCount, data_offset));
3136 (struct dfs_referral_level_3 *)
3137 (8 /* sizeof start of data block */ +
3139 (char *) &pSMBr->hdr.Protocol);
3140 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",
3141 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)));
3142 /* BB This field is actually two bytes in from start of
3143 data block so we could do safety check that DataBlock
3144 begins at address of pSMBr->NumberOfReferrals */
3145 *number_of_UNC_in_array = le16_to_cpu(pSMBr->NumberOfReferrals);
3147 /* BB Fix below so can return more than one referral */
3148 if(*number_of_UNC_in_array > 1)
3149 *number_of_UNC_in_array = 1;
3151 /* get the length of the strings describing refs */
3153 for(i=0;i<*number_of_UNC_in_array;i++) {
3154 /* make sure that DfsPathOffset not past end */
3155 __u16 offset = le16_to_cpu(referrals->DfsPathOffset);
3156 if (offset > data_count) {
3157 /* if invalid referral, stop here and do
3158 not try to copy any more */
3159 *number_of_UNC_in_array = i;
3162 temp = ((char *)referrals) + offset;
3164 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
3165 name_len += UniStrnlen((wchar_t *)temp,data_count);
3167 name_len += strnlen(temp,data_count);
3170 /* BB add check that referral pointer does not fall off end PDU */
3173 /* BB add check for name_len bigger than bcc */
3175 kmalloc(name_len+1+ (*number_of_UNC_in_array),GFP_KERNEL);
3176 if(*targetUNCs == NULL) {
3180 /* copy the ref strings */
3182 (struct dfs_referral_level_3 *)
3183 (8 /* sizeof data hdr */ +
3185 (char *) &pSMBr->hdr.Protocol);
3187 for(i=0;i<*number_of_UNC_in_array;i++) {
3188 temp = ((char *)referrals) + le16_to_cpu(referrals->DfsPathOffset);
3189 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
3190 cifs_strfromUCS_le(*targetUNCs,
3191 (wchar_t *) temp, name_len, nls_codepage);
3193 strncpy(*targetUNCs,temp,name_len);
3195 /* BB update target_uncs pointers */
3205 cifs_buf_release(pSMB);
3214 CIFSSMBQFSInfo(const int xid, struct cifsTconInfo *tcon, struct kstatfs *FSData)
3216 /* level 0x103 SMB_QUERY_FILE_SYSTEM_INFO */
3217 TRANSACTION2_QFSI_REQ *pSMB = NULL;
3218 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
3219 FILE_SYSTEM_INFO *response_data;
3221 int bytes_returned = 0;
3222 __u16 params, byte_count;
3224 cFYI(1, ("In QFSInfo"));
3226 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3231 params = 2; /* level */
3232 pSMB->TotalDataCount = 0;
3233 pSMB->MaxParameterCount = cpu_to_le16(2);
3234 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
3235 pSMB->MaxSetupCount = 0;
3239 pSMB->Reserved2 = 0;
3240 byte_count = params + 1 /* pad */ ;
3241 pSMB->TotalParameterCount = cpu_to_le16(params);
3242 pSMB->ParameterCount = pSMB->TotalParameterCount;
3243 pSMB->ParameterOffset = cpu_to_le16(offsetof(
3244 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
3245 pSMB->DataCount = 0;
3246 pSMB->DataOffset = 0;
3247 pSMB->SetupCount = 1;
3248 pSMB->Reserved3 = 0;
3249 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
3250 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_SIZE_INFO);
3251 pSMB->hdr.smb_buf_length += byte_count;
3252 pSMB->ByteCount = cpu_to_le16(byte_count);
3254 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3255 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3257 cERROR(1, ("Send error in QFSInfo = %d", rc));
3258 } else { /* decode response */
3259 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3261 if (rc || (pSMBr->ByteCount < 24)) /* BB alsO CHEck enough total bytes returned */
3262 rc = -EIO; /* bad smb */
3264 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3266 ("Decoding qfsinfo response. BCC: %d Offset %d",
3267 pSMBr->ByteCount, data_offset));
3271 *) (((char *) &pSMBr->hdr.Protocol) +
3274 le32_to_cpu(response_data->BytesPerSector) *
3275 le32_to_cpu(response_data->
3276 SectorsPerAllocationUnit);
3278 le64_to_cpu(response_data->TotalAllocationUnits);
3279 FSData->f_bfree = FSData->f_bavail =
3280 le64_to_cpu(response_data->FreeAllocationUnits);
3282 ("Blocks: %lld Free: %lld Block size %ld",
3283 (unsigned long long)FSData->f_blocks,
3284 (unsigned long long)FSData->f_bfree,
3288 cifs_buf_release(pSMB);
3297 CIFSSMBQFSAttributeInfo(const int xid, struct cifsTconInfo *tcon)
3299 /* level 0x105 SMB_QUERY_FILE_SYSTEM_INFO */
3300 TRANSACTION2_QFSI_REQ *pSMB = NULL;
3301 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
3302 FILE_SYSTEM_ATTRIBUTE_INFO *response_data;
3304 int bytes_returned = 0;
3305 __u16 params, byte_count;
3307 cFYI(1, ("In QFSAttributeInfo"));
3309 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3314 params = 2; /* level */
3315 pSMB->TotalDataCount = 0;
3316 pSMB->MaxParameterCount = cpu_to_le16(2);
3317 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
3318 pSMB->MaxSetupCount = 0;
3322 pSMB->Reserved2 = 0;
3323 byte_count = params + 1 /* pad */ ;
3324 pSMB->TotalParameterCount = cpu_to_le16(params);
3325 pSMB->ParameterCount = pSMB->TotalParameterCount;
3326 pSMB->ParameterOffset = cpu_to_le16(offsetof(
3327 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
3328 pSMB->DataCount = 0;
3329 pSMB->DataOffset = 0;
3330 pSMB->SetupCount = 1;
3331 pSMB->Reserved3 = 0;
3332 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
3333 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_ATTRIBUTE_INFO);
3334 pSMB->hdr.smb_buf_length += byte_count;
3335 pSMB->ByteCount = cpu_to_le16(byte_count);
3337 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3338 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3340 cERROR(1, ("Send error in QFSAttributeInfo = %d", rc));
3341 } else { /* decode response */
3342 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3344 if (rc || (pSMBr->ByteCount < 13)) { /* BB also check enough bytes returned */
3345 rc = -EIO; /* bad smb */
3347 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3349 (FILE_SYSTEM_ATTRIBUTE_INFO
3350 *) (((char *) &pSMBr->hdr.Protocol) +
3352 memcpy(&tcon->fsAttrInfo, response_data,
3353 sizeof (FILE_SYSTEM_ATTRIBUTE_INFO));
3356 cifs_buf_release(pSMB);
3359 goto QFSAttributeRetry;
3365 CIFSSMBQFSDeviceInfo(const int xid, struct cifsTconInfo *tcon)
3367 /* level 0x104 SMB_QUERY_FILE_SYSTEM_INFO */
3368 TRANSACTION2_QFSI_REQ *pSMB = NULL;
3369 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
3370 FILE_SYSTEM_DEVICE_INFO *response_data;
3372 int bytes_returned = 0;
3373 __u16 params, byte_count;
3375 cFYI(1, ("In QFSDeviceInfo"));
3377 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3382 params = 2; /* level */
3383 pSMB->TotalDataCount = 0;
3384 pSMB->MaxParameterCount = cpu_to_le16(2);
3385 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
3386 pSMB->MaxSetupCount = 0;
3390 pSMB->Reserved2 = 0;
3391 byte_count = params + 1 /* pad */ ;
3392 pSMB->TotalParameterCount = cpu_to_le16(params);
3393 pSMB->ParameterCount = pSMB->TotalParameterCount;
3394 pSMB->ParameterOffset = cpu_to_le16(offsetof(
3395 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
3397 pSMB->DataCount = 0;
3398 pSMB->DataOffset = 0;
3399 pSMB->SetupCount = 1;
3400 pSMB->Reserved3 = 0;
3401 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
3402 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_DEVICE_INFO);
3403 pSMB->hdr.smb_buf_length += byte_count;
3404 pSMB->ByteCount = cpu_to_le16(byte_count);
3406 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3407 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3409 cFYI(1, ("Send error in QFSDeviceInfo = %d", rc));
3410 } else { /* decode response */
3411 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3413 if (rc || (pSMBr->ByteCount < sizeof (FILE_SYSTEM_DEVICE_INFO)))
3414 rc = -EIO; /* bad smb */
3416 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3418 (FILE_SYSTEM_DEVICE_INFO *)
3419 (((char *) &pSMBr->hdr.Protocol) +
3421 memcpy(&tcon->fsDevInfo, response_data,
3422 sizeof (FILE_SYSTEM_DEVICE_INFO));
3425 cifs_buf_release(pSMB);
3428 goto QFSDeviceRetry;
3434 CIFSSMBQFSUnixInfo(const int xid, struct cifsTconInfo *tcon)
3436 /* level 0x200 SMB_QUERY_CIFS_UNIX_INFO */
3437 TRANSACTION2_QFSI_REQ *pSMB = NULL;
3438 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
3439 FILE_SYSTEM_UNIX_INFO *response_data;
3441 int bytes_returned = 0;
3442 __u16 params, byte_count;
3444 cFYI(1, ("In QFSUnixInfo"));
3446 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3451 params = 2; /* level */
3452 pSMB->TotalDataCount = 0;
3453 pSMB->DataCount = 0;
3454 pSMB->DataOffset = 0;
3455 pSMB->MaxParameterCount = cpu_to_le16(2);
3456 pSMB->MaxDataCount = cpu_to_le16(100); /* BB find exact max SMB PDU from sess structure BB */
3457 pSMB->MaxSetupCount = 0;
3461 pSMB->Reserved2 = 0;
3462 byte_count = params + 1 /* pad */ ;
3463 pSMB->ParameterCount = cpu_to_le16(params);
3464 pSMB->TotalParameterCount = pSMB->ParameterCount;
3465 pSMB->ParameterOffset = cpu_to_le16(offsetof(struct
3466 smb_com_transaction2_qfsi_req, InformationLevel) - 4);
3467 pSMB->SetupCount = 1;
3468 pSMB->Reserved3 = 0;
3469 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
3470 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_CIFS_UNIX_INFO);
3471 pSMB->hdr.smb_buf_length += byte_count;
3472 pSMB->ByteCount = cpu_to_le16(byte_count);
3474 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3475 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3477 cERROR(1, ("Send error in QFSUnixInfo = %d", rc));
3478 } else { /* decode response */
3479 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3481 if (rc || (pSMBr->ByteCount < 13)) {
3482 rc = -EIO; /* bad smb */
3484 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3486 (FILE_SYSTEM_UNIX_INFO
3487 *) (((char *) &pSMBr->hdr.Protocol) +
3489 memcpy(&tcon->fsUnixInfo, response_data,
3490 sizeof (FILE_SYSTEM_UNIX_INFO));
3493 cifs_buf_release(pSMB);
3503 CIFSSMBSetFSUnixInfo(const int xid, struct cifsTconInfo *tcon, __u64 cap)
3505 /* level 0x200 SMB_SET_CIFS_UNIX_INFO */
3506 TRANSACTION2_SETFSI_REQ *pSMB = NULL;
3507 TRANSACTION2_SETFSI_RSP *pSMBr = NULL;
3509 int bytes_returned = 0;
3510 __u16 params, param_offset, offset, byte_count;
3512 cFYI(1, ("In SETFSUnixInfo"));
3514 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3519 params = 4; /* 2 bytes zero followed by info level. */
3520 pSMB->MaxSetupCount = 0;
3524 pSMB->Reserved2 = 0;
3525 param_offset = offsetof(struct smb_com_transaction2_setfsi_req, FileNum) - 4;
3526 offset = param_offset + params;
3528 pSMB->MaxParameterCount = cpu_to_le16(4);
3529 pSMB->MaxDataCount = cpu_to_le16(100); /* BB find exact max SMB PDU from sess structure BB */
3530 pSMB->SetupCount = 1;
3531 pSMB->Reserved3 = 0;
3532 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FS_INFORMATION);
3533 byte_count = 1 /* pad */ + params + 12;
3535 pSMB->DataCount = cpu_to_le16(12);
3536 pSMB->ParameterCount = cpu_to_le16(params);
3537 pSMB->TotalDataCount = pSMB->DataCount;
3538 pSMB->TotalParameterCount = pSMB->ParameterCount;
3539 pSMB->ParameterOffset = cpu_to_le16(param_offset);
3540 pSMB->DataOffset = cpu_to_le16(offset);
3544 pSMB->InformationLevel = cpu_to_le16(SMB_SET_CIFS_UNIX_INFO);
3547 pSMB->ClientUnixMajor = cpu_to_le16(CIFS_UNIX_MAJOR_VERSION);
3548 pSMB->ClientUnixMinor = cpu_to_le16(CIFS_UNIX_MINOR_VERSION);
3549 pSMB->ClientUnixCap = cpu_to_le64(cap);
3551 pSMB->hdr.smb_buf_length += byte_count;
3552 pSMB->ByteCount = cpu_to_le16(byte_count);
3554 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3555 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3557 cERROR(1, ("Send error in SETFSUnixInfo = %d", rc));
3558 } else { /* decode response */
3559 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3561 rc = -EIO; /* bad smb */
3564 cifs_buf_release(pSMB);
3567 goto SETFSUnixRetry;
3575 CIFSSMBQFSPosixInfo(const int xid, struct cifsTconInfo *tcon,
3576 struct kstatfs *FSData)
3578 /* level 0x201 SMB_QUERY_CIFS_POSIX_INFO */
3579 TRANSACTION2_QFSI_REQ *pSMB = NULL;
3580 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
3581 FILE_SYSTEM_POSIX_INFO *response_data;
3583 int bytes_returned = 0;
3584 __u16 params, byte_count;
3586 cFYI(1, ("In QFSPosixInfo"));
3588 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3593 params = 2; /* level */
3594 pSMB->TotalDataCount = 0;
3595 pSMB->DataCount = 0;
3596 pSMB->DataOffset = 0;
3597 pSMB->MaxParameterCount = cpu_to_le16(2);
3598 pSMB->MaxDataCount = cpu_to_le16(100); /* BB find exact max SMB PDU from sess structure BB */
3599 pSMB->MaxSetupCount = 0;
3603 pSMB->Reserved2 = 0;
3604 byte_count = params + 1 /* pad */ ;
3605 pSMB->ParameterCount = cpu_to_le16(params);
3606 pSMB->TotalParameterCount = pSMB->ParameterCount;
3607 pSMB->ParameterOffset = cpu_to_le16(offsetof(struct
3608 smb_com_transaction2_qfsi_req, InformationLevel) - 4);
3609 pSMB->SetupCount = 1;
3610 pSMB->Reserved3 = 0;
3611 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
3612 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_POSIX_FS_INFO);
3613 pSMB->hdr.smb_buf_length += byte_count;
3614 pSMB->ByteCount = cpu_to_le16(byte_count);
3616 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3617 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3619 cFYI(1, ("Send error in QFSUnixInfo = %d", rc));
3620 } else { /* decode response */
3621 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3623 if (rc || (pSMBr->ByteCount < 13)) {
3624 rc = -EIO; /* bad smb */
3626 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3628 (FILE_SYSTEM_POSIX_INFO
3629 *) (((char *) &pSMBr->hdr.Protocol) +
3632 le32_to_cpu(response_data->BlockSize);
3634 le64_to_cpu(response_data->TotalBlocks);
3636 le64_to_cpu(response_data->BlocksAvail);
3637 if(response_data->UserBlocksAvail == -1) {
3638 FSData->f_bavail = FSData->f_bfree;
3641 le64_to_cpu(response_data->UserBlocksAvail);
3643 if(response_data->TotalFileNodes != -1)
3645 le64_to_cpu(response_data->TotalFileNodes);
3646 if(response_data->FreeFileNodes != -1)
3648 le64_to_cpu(response_data->FreeFileNodes);
3651 cifs_buf_release(pSMB);
3660 /* We can not use write of zero bytes trick to
3661 set file size due to need for large file support. Also note that
3662 this SetPathInfo is preferred to SetFileInfo based method in next
3663 routine which is only needed to work around a sharing violation bug
3664 in Samba which this routine can run into */
3667 CIFSSMBSetEOF(const int xid, struct cifsTconInfo *tcon, const char *fileName,
3668 __u64 size, int SetAllocation,
3669 const struct nls_table *nls_codepage, int remap)
3671 struct smb_com_transaction2_spi_req *pSMB = NULL;
3672 struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
3673 struct file_end_of_file_info *parm_data;
3676 int bytes_returned = 0;
3677 __u16 params, byte_count, data_count, param_offset, offset;
3679 cFYI(1, ("In SetEOF"));
3681 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3686 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3688 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
3689 PATH_MAX, nls_codepage, remap);
3690 name_len++; /* trailing null */
3692 } else { /* BB improve the check for buffer overruns BB */
3693 name_len = strnlen(fileName, PATH_MAX);
3694 name_len++; /* trailing null */
3695 strncpy(pSMB->FileName, fileName, name_len);
3697 params = 6 + name_len;
3698 data_count = sizeof (struct file_end_of_file_info);
3699 pSMB->MaxParameterCount = cpu_to_le16(2);
3700 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB size from sess */
3701 pSMB->MaxSetupCount = 0;
3705 pSMB->Reserved2 = 0;
3706 param_offset = offsetof(struct smb_com_transaction2_spi_req,
3707 InformationLevel) - 4;
3708 offset = param_offset + params;
3710 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
3711 pSMB->InformationLevel =
3712 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2);
3714 pSMB->InformationLevel =
3715 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO);
3716 } else /* Set File Size */ {
3717 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
3718 pSMB->InformationLevel =
3719 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO2);
3721 pSMB->InformationLevel =
3722 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO);
3726 (struct file_end_of_file_info *) (((char *) &pSMB->hdr.Protocol) +
3728 pSMB->ParameterOffset = cpu_to_le16(param_offset);
3729 pSMB->DataOffset = cpu_to_le16(offset);
3730 pSMB->SetupCount = 1;
3731 pSMB->Reserved3 = 0;
3732 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
3733 byte_count = 3 /* pad */ + params + data_count;
3734 pSMB->DataCount = cpu_to_le16(data_count);
3735 pSMB->TotalDataCount = pSMB->DataCount;
3736 pSMB->ParameterCount = cpu_to_le16(params);
3737 pSMB->TotalParameterCount = pSMB->ParameterCount;
3738 pSMB->Reserved4 = 0;
3739 pSMB->hdr.smb_buf_length += byte_count;
3740 parm_data->FileSize = cpu_to_le64(size);
3741 pSMB->ByteCount = cpu_to_le16(byte_count);
3742 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3743 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3745 cFYI(1, ("SetPathInfo (file size) returned %d", rc));
3748 cifs_buf_release(pSMB);
3757 CIFSSMBSetFileSize(const int xid, struct cifsTconInfo *tcon, __u64 size,
3758 __u16 fid, __u32 pid_of_opener, int SetAllocation)
3760 struct smb_com_transaction2_sfi_req *pSMB = NULL;
3761 struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
3763 struct file_end_of_file_info *parm_data;
3765 int bytes_returned = 0;
3766 __u16 params, param_offset, offset, byte_count, count;
3768 cFYI(1, ("SetFileSize (via SetFileInfo) %lld",
3770 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
3775 pSMBr = (struct smb_com_transaction2_sfi_rsp *)pSMB;
3777 pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
3778 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));
3781 pSMB->MaxSetupCount = 0;
3785 pSMB->Reserved2 = 0;
3786 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
3787 offset = param_offset + params;
3789 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
3791 count = sizeof(struct file_end_of_file_info);
3792 pSMB->MaxParameterCount = cpu_to_le16(2);
3793 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB PDU from sess */
3794 pSMB->SetupCount = 1;
3795 pSMB->Reserved3 = 0;
3796 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
3797 byte_count = 3 /* pad */ + params + count;
3798 pSMB->DataCount = cpu_to_le16(count);
3799 pSMB->ParameterCount = cpu_to_le16(params);
3800 pSMB->TotalDataCount = pSMB->DataCount;
3801 pSMB->TotalParameterCount = pSMB->ParameterCount;
3802 pSMB->ParameterOffset = cpu_to_le16(param_offset);
3804 (struct file_end_of_file_info *) (((char *) &pSMB->hdr.Protocol) +
3806 pSMB->DataOffset = cpu_to_le16(offset);
3807 parm_data->FileSize = cpu_to_le64(size);
3810 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
3811 pSMB->InformationLevel =
3812 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2);
3814 pSMB->InformationLevel =
3815 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO);
3816 } else /* Set File Size */ {
3817 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
3818 pSMB->InformationLevel =
3819 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO2);
3821 pSMB->InformationLevel =
3822 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO);
3824 pSMB->Reserved4 = 0;
3825 pSMB->hdr.smb_buf_length += byte_count;
3826 pSMB->ByteCount = cpu_to_le16(byte_count);
3827 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3828 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3831 ("Send error in SetFileInfo (SetFileSize) = %d",
3836 cifs_small_buf_release(pSMB);
3838 /* Note: On -EAGAIN error only caller can retry on handle based calls
3839 since file handle passed in no longer valid */
3844 /* Some legacy servers such as NT4 require that the file times be set on
3845 an open handle, rather than by pathname - this is awkward due to
3846 potential access conflicts on the open, but it is unavoidable for these
3847 old servers since the only other choice is to go from 100 nanosecond DCE
3848 time and resort to the original setpathinfo level which takes the ancient
3849 DOS time format with 2 second granularity */
3851 CIFSSMBSetFileTimes(const int xid, struct cifsTconInfo *tcon, const FILE_BASIC_INFO * data,
3854 struct smb_com_transaction2_sfi_req *pSMB = NULL;
3855 struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
3858 int bytes_returned = 0;
3859 __u16 params, param_offset, offset, byte_count, count;
3861 cFYI(1, ("Set Times (via SetFileInfo)"));
3862 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
3867 pSMBr = (struct smb_com_transaction2_sfi_rsp *)pSMB;
3869 /* At this point there is no need to override the current pid
3870 with the pid of the opener, but that could change if we someday
3871 use an existing handle (rather than opening one on the fly) */
3872 /* pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
3873 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));*/
3876 pSMB->MaxSetupCount = 0;
3880 pSMB->Reserved2 = 0;
3881 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
3882 offset = param_offset + params;
3884 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
3886 count = sizeof (FILE_BASIC_INFO);
3887 pSMB->MaxParameterCount = cpu_to_le16(2);
3888 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB PDU from sess */
3889 pSMB->SetupCount = 1;
3890 pSMB->Reserved3 = 0;
3891 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
3892 byte_count = 3 /* pad */ + params + count;
3893 pSMB->DataCount = cpu_to_le16(count);
3894 pSMB->ParameterCount = cpu_to_le16(params);
3895 pSMB->TotalDataCount = pSMB->DataCount;
3896 pSMB->TotalParameterCount = pSMB->ParameterCount;
3897 pSMB->ParameterOffset = cpu_to_le16(param_offset);
3898 pSMB->DataOffset = cpu_to_le16(offset);
3900 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
3901 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO2);
3903 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO);
3904 pSMB->Reserved4 = 0;
3905 pSMB->hdr.smb_buf_length += byte_count;
3906 pSMB->ByteCount = cpu_to_le16(byte_count);
3907 memcpy(data_offset,data,sizeof(FILE_BASIC_INFO));
3908 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3909 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3911 cFYI(1,("Send error in Set Time (SetFileInfo) = %d",rc));
3914 cifs_small_buf_release(pSMB);
3916 /* Note: On -EAGAIN error only caller can retry on handle based calls
3917 since file handle passed in no longer valid */
3924 CIFSSMBSetTimes(const int xid, struct cifsTconInfo *tcon, const char *fileName,
3925 const FILE_BASIC_INFO * data,
3926 const struct nls_table *nls_codepage, int remap)
3928 TRANSACTION2_SPI_REQ *pSMB = NULL;
3929 TRANSACTION2_SPI_RSP *pSMBr = NULL;
3932 int bytes_returned = 0;
3934 __u16 params, param_offset, offset, byte_count, count;
3936 cFYI(1, ("In SetTimes"));
3939 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3944 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3946 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
3947 PATH_MAX, nls_codepage, remap);
3948 name_len++; /* trailing null */
3950 } else { /* BB improve the check for buffer overruns BB */
3951 name_len = strnlen(fileName, PATH_MAX);
3952 name_len++; /* trailing null */
3953 strncpy(pSMB->FileName, fileName, name_len);
3956 params = 6 + name_len;
3957 count = sizeof (FILE_BASIC_INFO);
3958 pSMB->MaxParameterCount = cpu_to_le16(2);
3959 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
3960 pSMB->MaxSetupCount = 0;
3964 pSMB->Reserved2 = 0;
3965 param_offset = offsetof(struct smb_com_transaction2_spi_req,
3966 InformationLevel) - 4;
3967 offset = param_offset + params;
3968 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
3969 pSMB->ParameterOffset = cpu_to_le16(param_offset);
3970 pSMB->DataOffset = cpu_to_le16(offset);
3971 pSMB->SetupCount = 1;
3972 pSMB->Reserved3 = 0;
3973 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
3974 byte_count = 3 /* pad */ + params + count;
3976 pSMB->DataCount = cpu_to_le16(count);
3977 pSMB->ParameterCount = cpu_to_le16(params);
3978 pSMB->TotalDataCount = pSMB->DataCount;
3979 pSMB->TotalParameterCount = pSMB->ParameterCount;
3980 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
3981 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO2);
3983 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO);
3984 pSMB->Reserved4 = 0;
3985 pSMB->hdr.smb_buf_length += byte_count;
3986 memcpy(data_offset, data, sizeof (FILE_BASIC_INFO));
3987 pSMB->ByteCount = cpu_to_le16(byte_count);
3988 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3989 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3991 cFYI(1, ("SetPathInfo (times) returned %d", rc));
3994 cifs_buf_release(pSMB);
4002 /* Can not be used to set time stamps yet (due to old DOS time format) */
4003 /* Can be used to set attributes */
4004 #if 0 /* Possibly not needed - since it turns out that strangely NT4 has a bug
4005 handling it anyway and NT4 was what we thought it would be needed for
4006 Do not delete it until we prove whether needed for Win9x though */
4008 CIFSSMBSetAttrLegacy(int xid, struct cifsTconInfo *tcon, char *fileName,
4009 __u16 dos_attrs, const struct nls_table *nls_codepage)
4011 SETATTR_REQ *pSMB = NULL;
4012 SETATTR_RSP *pSMBr = NULL;
4017 cFYI(1, ("In SetAttrLegacy"));
4020 rc = smb_init(SMB_COM_SETATTR, 8, tcon, (void **) &pSMB,
4025 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4027 ConvertToUCS((__le16 *) pSMB->fileName, fileName,
4028 PATH_MAX, nls_codepage);
4029 name_len++; /* trailing null */
4031 } else { /* BB improve the check for buffer overruns BB */
4032 name_len = strnlen(fileName, PATH_MAX);
4033 name_len++; /* trailing null */
4034 strncpy(pSMB->fileName, fileName, name_len);
4036 pSMB->attr = cpu_to_le16(dos_attrs);
4037 pSMB->BufferFormat = 0x04;
4038 pSMB->hdr.smb_buf_length += name_len + 1;
4039 pSMB->ByteCount = cpu_to_le16(name_len + 1);
4040 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4041 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4043 cFYI(1, ("Error in LegacySetAttr = %d", rc));
4046 cifs_buf_release(pSMB);
4049 goto SetAttrLgcyRetry;
4053 #endif /* temporarily unneeded SetAttr legacy function */
4056 CIFSSMBUnixSetPerms(const int xid, struct cifsTconInfo *tcon,
4057 char *fileName, __u64 mode, __u64 uid, __u64 gid,
4058 dev_t device, const struct nls_table *nls_codepage,
4061 TRANSACTION2_SPI_REQ *pSMB = NULL;
4062 TRANSACTION2_SPI_RSP *pSMBr = NULL;
4065 int bytes_returned = 0;
4066 FILE_UNIX_BASIC_INFO *data_offset;
4067 __u16 params, param_offset, offset, count, byte_count;
4069 cFYI(1, ("In SetUID/GID/Mode"));
4071 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4076 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4078 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
4079 PATH_MAX, nls_codepage, remap);
4080 name_len++; /* trailing null */
4082 } else { /* BB improve the check for buffer overruns BB */
4083 name_len = strnlen(fileName, PATH_MAX);
4084 name_len++; /* trailing null */
4085 strncpy(pSMB->FileName, fileName, name_len);
4088 params = 6 + name_len;
4089 count = sizeof (FILE_UNIX_BASIC_INFO);
4090 pSMB->MaxParameterCount = cpu_to_le16(2);
4091 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
4092 pSMB->MaxSetupCount = 0;
4096 pSMB->Reserved2 = 0;
4097 param_offset = offsetof(struct smb_com_transaction2_spi_req,
4098 InformationLevel) - 4;
4099 offset = param_offset + params;
4101 (FILE_UNIX_BASIC_INFO *) ((char *) &pSMB->hdr.Protocol +
4103 memset(data_offset, 0, count);
4104 pSMB->DataOffset = cpu_to_le16(offset);
4105 pSMB->ParameterOffset = cpu_to_le16(param_offset);
4106 pSMB->SetupCount = 1;
4107 pSMB->Reserved3 = 0;
4108 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
4109 byte_count = 3 /* pad */ + params + count;
4110 pSMB->ParameterCount = cpu_to_le16(params);
4111 pSMB->DataCount = cpu_to_le16(count);
4112 pSMB->TotalParameterCount = pSMB->ParameterCount;
4113 pSMB->TotalDataCount = pSMB->DataCount;
4114 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_BASIC);
4115 pSMB->Reserved4 = 0;
4116 pSMB->hdr.smb_buf_length += byte_count;
4117 data_offset->Uid = cpu_to_le64(uid);
4118 data_offset->Gid = cpu_to_le64(gid);
4119 /* better to leave device as zero when it is */
4120 data_offset->DevMajor = cpu_to_le64(MAJOR(device));
4121 data_offset->DevMinor = cpu_to_le64(MINOR(device));
4122 data_offset->Permissions = cpu_to_le64(mode);
4125 data_offset->Type = cpu_to_le32(UNIX_FILE);
4126 else if(S_ISDIR(mode))
4127 data_offset->Type = cpu_to_le32(UNIX_DIR);
4128 else if(S_ISLNK(mode))
4129 data_offset->Type = cpu_to_le32(UNIX_SYMLINK);
4130 else if(S_ISCHR(mode))
4131 data_offset->Type = cpu_to_le32(UNIX_CHARDEV);
4132 else if(S_ISBLK(mode))
4133 data_offset->Type = cpu_to_le32(UNIX_BLOCKDEV);
4134 else if(S_ISFIFO(mode))
4135 data_offset->Type = cpu_to_le32(UNIX_FIFO);
4136 else if(S_ISSOCK(mode))
4137 data_offset->Type = cpu_to_le32(UNIX_SOCKET);
4140 pSMB->ByteCount = cpu_to_le16(byte_count);
4141 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4142 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4144 cFYI(1, ("SetPathInfo (perms) returned %d", rc));
4148 cifs_buf_release(pSMB);
4154 int CIFSSMBNotify(const int xid, struct cifsTconInfo *tcon,
4155 const int notify_subdirs, const __u16 netfid,
4156 __u32 filter, struct file * pfile, int multishot,
4157 const struct nls_table *nls_codepage)
4160 struct smb_com_transaction_change_notify_req * pSMB = NULL;
4161 struct smb_com_transaction_change_notify_rsp * pSMBr = NULL;
4162 struct dir_notify_req *dnotify_req;
4165 cFYI(1, ("In CIFSSMBNotify for file handle %d",(int)netfid));
4166 rc = smb_init(SMB_COM_NT_TRANSACT, 23, tcon, (void **) &pSMB,
4171 pSMB->TotalParameterCount = 0 ;
4172 pSMB->TotalDataCount = 0;
4173 pSMB->MaxParameterCount = cpu_to_le32(2);
4174 /* BB find exact data count max from sess structure BB */
4175 pSMB->MaxDataCount = 0; /* same in little endian or be */
4176 pSMB->MaxSetupCount = 4;
4178 pSMB->ParameterOffset = 0;
4179 pSMB->DataCount = 0;
4180 pSMB->DataOffset = 0;
4181 pSMB->SetupCount = 4; /* single byte does not need le conversion */
4182 pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_NOTIFY_CHANGE);
4183 pSMB->ParameterCount = pSMB->TotalParameterCount;
4185 pSMB->WatchTree = 1; /* one byte - no le conversion needed */
4186 pSMB->Reserved2 = 0;
4187 pSMB->CompletionFilter = cpu_to_le32(filter);
4188 pSMB->Fid = netfid; /* file handle always le */
4189 pSMB->ByteCount = 0;
4191 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4192 (struct smb_hdr *) pSMBr, &bytes_returned, -1);
4194 cFYI(1, ("Error in Notify = %d", rc));
4196 /* Add file to outstanding requests */
4197 dnotify_req = (struct dir_notify_req *) kmalloc(
4198 sizeof(struct dir_notify_req), GFP_KERNEL);
4199 dnotify_req->Pid = pSMB->hdr.Pid;
4200 dnotify_req->PidHigh = pSMB->hdr.PidHigh;
4201 dnotify_req->Mid = pSMB->hdr.Mid;
4202 dnotify_req->Tid = pSMB->hdr.Tid;
4203 dnotify_req->Uid = pSMB->hdr.Uid;
4204 dnotify_req->netfid = netfid;
4205 dnotify_req->pfile = pfile;
4206 dnotify_req->filter = filter;
4207 dnotify_req->multishot = multishot;
4208 spin_lock(&GlobalMid_Lock);
4209 list_add_tail(&dnotify_req->lhead, &GlobalDnotifyReqList);
4210 spin_unlock(&GlobalMid_Lock);
4212 cifs_buf_release(pSMB);
4215 #ifdef CONFIG_CIFS_XATTR
4217 CIFSSMBQAllEAs(const int xid, struct cifsTconInfo *tcon,
4218 const unsigned char *searchName,
4219 char * EAData, size_t buf_size,
4220 const struct nls_table *nls_codepage, int remap)
4222 /* BB assumes one setup word */
4223 TRANSACTION2_QPI_REQ *pSMB = NULL;
4224 TRANSACTION2_QPI_RSP *pSMBr = NULL;
4228 struct fea * temp_fea;
4230 __u16 params, byte_count;
4232 cFYI(1, ("In Query All EAs path %s", searchName));
4234 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4239 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4241 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
4242 PATH_MAX, nls_codepage, remap);
4243 name_len++; /* trailing null */
4245 } else { /* BB improve the check for buffer overruns BB */
4246 name_len = strnlen(searchName, PATH_MAX);
4247 name_len++; /* trailing null */
4248 strncpy(pSMB->FileName, searchName, name_len);
4251 params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */ ;
4252 pSMB->TotalDataCount = 0;
4253 pSMB->MaxParameterCount = cpu_to_le16(2);
4254 pSMB->MaxDataCount = cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
4255 pSMB->MaxSetupCount = 0;
4259 pSMB->Reserved2 = 0;
4260 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4261 struct smb_com_transaction2_qpi_req ,InformationLevel) - 4);
4262 pSMB->DataCount = 0;
4263 pSMB->DataOffset = 0;
4264 pSMB->SetupCount = 1;
4265 pSMB->Reserved3 = 0;
4266 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
4267 byte_count = params + 1 /* pad */ ;
4268 pSMB->TotalParameterCount = cpu_to_le16(params);
4269 pSMB->ParameterCount = pSMB->TotalParameterCount;
4270 pSMB->InformationLevel = cpu_to_le16(SMB_INFO_QUERY_ALL_EAS);
4271 pSMB->Reserved4 = 0;
4272 pSMB->hdr.smb_buf_length += byte_count;
4273 pSMB->ByteCount = cpu_to_le16(byte_count);
4275 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4276 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4278 cFYI(1, ("Send error in QueryAllEAs = %d", rc));
4279 } else { /* decode response */
4280 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4282 /* BB also check enough total bytes returned */
4283 /* BB we need to improve the validity checking
4284 of these trans2 responses */
4285 if (rc || (pSMBr->ByteCount < 4))
4286 rc = -EIO; /* bad smb */
4287 /* else if (pFindData){
4288 memcpy((char *) pFindData,
4289 (char *) &pSMBr->hdr.Protocol +
4292 /* check that length of list is not more than bcc */
4293 /* check that each entry does not go beyond length
4295 /* check that each element of each entry does not
4296 go beyond end of list */
4297 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4298 struct fealist * ea_response_data;
4300 /* validate_trans2_offsets() */
4301 /* BB to check if(start of smb + data_offset > &bcc+ bcc)*/
4302 ea_response_data = (struct fealist *)
4303 (((char *) &pSMBr->hdr.Protocol) +
4305 name_len = le32_to_cpu(ea_response_data->list_len);
4306 cFYI(1,("ea length %d", name_len));
4308 /* returned EA size zeroed at top of function */
4309 cFYI(1,("empty EA list returned from server"));
4311 /* account for ea list len */
4313 temp_fea = ea_response_data->list;
4314 temp_ptr = (char *)temp_fea;
4315 while(name_len > 0) {
4319 rc += temp_fea->name_len;
4320 /* account for prefix user. and trailing null */
4322 if(rc<(int)buf_size) {
4323 memcpy(EAData,"user.",5);
4325 memcpy(EAData,temp_ptr,temp_fea->name_len);
4326 EAData+=temp_fea->name_len;
4327 /* null terminate name */
4329 EAData = EAData + 1;
4330 } else if(buf_size == 0) {
4331 /* skip copy - calc size only */
4333 /* stop before overrun buffer */
4337 name_len -= temp_fea->name_len;
4338 temp_ptr += temp_fea->name_len;
4339 /* account for trailing null */
4342 value_len = le16_to_cpu(temp_fea->value_len);
4343 name_len -= value_len;
4344 temp_ptr += value_len;
4345 /* BB check that temp_ptr is still within smb BB*/
4346 /* no trailing null to account for in value len */
4347 /* go on to next EA */
4348 temp_fea = (struct fea *)temp_ptr;
4354 cifs_buf_release(pSMB);
4361 ssize_t CIFSSMBQueryEA(const int xid,struct cifsTconInfo * tcon,
4362 const unsigned char * searchName,const unsigned char * ea_name,
4363 unsigned char * ea_value, size_t buf_size,
4364 const struct nls_table *nls_codepage, int remap)
4366 TRANSACTION2_QPI_REQ *pSMB = NULL;
4367 TRANSACTION2_QPI_RSP *pSMBr = NULL;
4371 struct fea * temp_fea;
4373 __u16 params, byte_count;
4375 cFYI(1, ("In Query EA path %s", searchName));
4377 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4382 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4384 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
4385 PATH_MAX, nls_codepage, remap);
4386 name_len++; /* trailing null */
4388 } else { /* BB improve the check for buffer overruns BB */
4389 name_len = strnlen(searchName, PATH_MAX);
4390 name_len++; /* trailing null */
4391 strncpy(pSMB->FileName, searchName, name_len);
4394 params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */ ;
4395 pSMB->TotalDataCount = 0;
4396 pSMB->MaxParameterCount = cpu_to_le16(2);
4397 pSMB->MaxDataCount = cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
4398 pSMB->MaxSetupCount = 0;
4402 pSMB->Reserved2 = 0;
4403 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4404 struct smb_com_transaction2_qpi_req ,InformationLevel) - 4);
4405 pSMB->DataCount = 0;
4406 pSMB->DataOffset = 0;
4407 pSMB->SetupCount = 1;
4408 pSMB->Reserved3 = 0;
4409 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
4410 byte_count = params + 1 /* pad */ ;
4411 pSMB->TotalParameterCount = cpu_to_le16(params);
4412 pSMB->ParameterCount = pSMB->TotalParameterCount;
4413 pSMB->InformationLevel = cpu_to_le16(SMB_INFO_QUERY_ALL_EAS);
4414 pSMB->Reserved4 = 0;
4415 pSMB->hdr.smb_buf_length += byte_count;
4416 pSMB->ByteCount = cpu_to_le16(byte_count);
4418 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4419 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4421 cFYI(1, ("Send error in Query EA = %d", rc));
4422 } else { /* decode response */
4423 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4425 /* BB also check enough total bytes returned */
4426 /* BB we need to improve the validity checking
4427 of these trans2 responses */
4428 if (rc || (pSMBr->ByteCount < 4))
4429 rc = -EIO; /* bad smb */
4430 /* else if (pFindData){
4431 memcpy((char *) pFindData,
4432 (char *) &pSMBr->hdr.Protocol +
4435 /* check that length of list is not more than bcc */
4436 /* check that each entry does not go beyond length
4438 /* check that each element of each entry does not
4439 go beyond end of list */
4440 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4441 struct fealist * ea_response_data;
4443 /* validate_trans2_offsets() */
4444 /* BB to check if(start of smb + data_offset > &bcc+ bcc)*/
4445 ea_response_data = (struct fealist *)
4446 (((char *) &pSMBr->hdr.Protocol) +
4448 name_len = le32_to_cpu(ea_response_data->list_len);
4449 cFYI(1,("ea length %d", name_len));
4451 /* returned EA size zeroed at top of function */
4452 cFYI(1,("empty EA list returned from server"));
4454 /* account for ea list len */
4456 temp_fea = ea_response_data->list;
4457 temp_ptr = (char *)temp_fea;
4458 /* loop through checking if we have a matching
4459 name and then return the associated value */
4460 while(name_len > 0) {
4464 value_len = le16_to_cpu(temp_fea->value_len);
4465 /* BB validate that value_len falls within SMB,
4466 even though maximum for name_len is 255 */
4467 if(memcmp(temp_fea->name,ea_name,
4468 temp_fea->name_len) == 0) {
4471 /* account for prefix user. and trailing null */
4472 if(rc<=(int)buf_size) {
4474 temp_fea->name+temp_fea->name_len+1,
4476 /* ea values, unlike ea names,
4477 are not null terminated */
4478 } else if(buf_size == 0) {
4479 /* skip copy - calc size only */
4481 /* stop before overrun buffer */
4486 name_len -= temp_fea->name_len;
4487 temp_ptr += temp_fea->name_len;
4488 /* account for trailing null */
4491 name_len -= value_len;
4492 temp_ptr += value_len;
4493 /* no trailing null to account for in value len */
4494 /* go on to next EA */
4495 temp_fea = (struct fea *)temp_ptr;
4501 cifs_buf_release(pSMB);
4509 CIFSSMBSetEA(const int xid, struct cifsTconInfo *tcon, const char *fileName,
4510 const char * ea_name, const void * ea_value,
4511 const __u16 ea_value_len, const struct nls_table *nls_codepage,
4514 struct smb_com_transaction2_spi_req *pSMB = NULL;
4515 struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
4516 struct fealist *parm_data;
4519 int bytes_returned = 0;
4520 __u16 params, param_offset, byte_count, offset, count;
4522 cFYI(1, ("In SetEA"));
4524 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4529 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4531 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
4532 PATH_MAX, nls_codepage, remap);
4533 name_len++; /* trailing null */
4535 } else { /* BB improve the check for buffer overruns BB */
4536 name_len = strnlen(fileName, PATH_MAX);
4537 name_len++; /* trailing null */
4538 strncpy(pSMB->FileName, fileName, name_len);
4541 params = 6 + name_len;
4543 /* done calculating parms using name_len of file name,
4544 now use name_len to calculate length of ea name
4545 we are going to create in the inode xattrs */
4549 name_len = strnlen(ea_name,255);
4551 count = sizeof(*parm_data) + ea_value_len + name_len + 1;
4552 pSMB->MaxParameterCount = cpu_to_le16(2);
4553 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB size from sess */
4554 pSMB->MaxSetupCount = 0;
4558 pSMB->Reserved2 = 0;
4559 param_offset = offsetof(struct smb_com_transaction2_spi_req,
4560 InformationLevel) - 4;
4561 offset = param_offset + params;
4562 pSMB->InformationLevel =
4563 cpu_to_le16(SMB_SET_FILE_EA);
4566 (struct fealist *) (((char *) &pSMB->hdr.Protocol) +
4568 pSMB->ParameterOffset = cpu_to_le16(param_offset);
4569 pSMB->DataOffset = cpu_to_le16(offset);
4570 pSMB->SetupCount = 1;
4571 pSMB->Reserved3 = 0;
4572 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
4573 byte_count = 3 /* pad */ + params + count;
4574 pSMB->DataCount = cpu_to_le16(count);
4575 parm_data->list_len = cpu_to_le32(count);
4576 parm_data->list[0].EA_flags = 0;
4577 /* we checked above that name len is less than 255 */
4578 parm_data->list[0].name_len = (__u8)name_len;;
4579 /* EA names are always ASCII */
4581 strncpy(parm_data->list[0].name,ea_name,name_len);
4582 parm_data->list[0].name[name_len] = 0;
4583 parm_data->list[0].value_len = cpu_to_le16(ea_value_len);
4584 /* caller ensures that ea_value_len is less than 64K but
4585 we need to ensure that it fits within the smb */
4587 /*BB add length check that it would fit in negotiated SMB buffer size BB */
4588 /* if(ea_value_len > buffer_size - 512 (enough for header)) */
4590 memcpy(parm_data->list[0].name+name_len+1,ea_value,ea_value_len);
4592 pSMB->TotalDataCount = pSMB->DataCount;
4593 pSMB->ParameterCount = cpu_to_le16(params);
4594 pSMB->TotalParameterCount = pSMB->ParameterCount;
4595 pSMB->Reserved4 = 0;
4596 pSMB->hdr.smb_buf_length += byte_count;
4597 pSMB->ByteCount = cpu_to_le16(byte_count);
4598 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4599 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4601 cFYI(1, ("SetPathInfo (EA) returned %d", rc));
4604 cifs_buf_release(pSMB);