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);
927 SMBLegacyRead(const int xid, struct cifsTconInfo *tcon,
928 const int netfid, unsigned int count,
929 const __u64 lseek, unsigned int *nbytes, char **buf)
932 READX_REQ *pSMB = NULL;
933 READ_RSP *pSMBr = NULL;
934 char *pReadData = NULL;
937 cFYI(1,("Legacy read %d bytes fid %d",count,netfid));
939 /* field is shorter in legacy read, only 16 bits */
941 count = 2048; /* BB FIXME make this configurable */
943 if(lseek > 0xFFFFFFFF)
944 return -EIO; /* can not read that far into file on old server */
947 rc = smb_init(SMB_COM_READ_ANDX, 10, tcon, (void **) &pSMB,
952 /* tcon and ses pointer are checked in smb_init */
953 if (tcon->ses->server == NULL)
954 return -ECONNABORTED;
956 pSMB->AndXCommand = 0xFF; /* none */
958 pSMB->OffsetLow = cpu_to_le32(lseek & 0xFFFFFFFF);
960 pSMB->MaxCount = cpu_to_le16(count);
961 pSMB->Reserved = 0; /* Must Be Zero */
962 pSMB->ByteCount = 0; /* no need to do le conversion since it is 0 */
964 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
965 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
966 cifs_stats_inc(&tcon->num_reads);
968 cERROR(1, ("Send error in legacy read = %d", rc));
970 int data_length = le16_to_cpu(pSMBr->DataLengthHigh);
971 data_length = data_length << 16;
972 data_length += le16_to_cpu(pSMBr->DataLength);
973 *nbytes = data_length;
975 /*check that DataLength would not go beyond end of SMB */
976 if ((data_length > CIFSMaxBufSize) || (data_length > count)) {
977 cFYI(1,("bad length %d for count %d",data_length,count));
981 pReadData = (char *) (&pSMBr->hdr.Protocol) +
982 le16_to_cpu(pSMBr->DataOffset);
983 /* if(rc = copy_to_user(buf, pReadData, data_length)) {
984 cERROR(1,("Faulting on read rc = %d",rc));
986 }*/ /* can not use copy_to_user when using page cache*/
988 memcpy(*buf,pReadData,data_length);
992 cifs_buf_release(pSMB);
996 /* Note: On -EAGAIN error only caller can retry on handle based calls
997 since file handle passed in no longer valid */
1001 /* If no buffer passed in, then caller wants to do the copy
1002 as in the case of readpages so the SMB buffer must be
1003 freed by the caller */
1006 CIFSSMBRead(const int xid, struct cifsTconInfo *tcon,
1007 const int netfid, const unsigned int count,
1008 const __u64 lseek, unsigned int *nbytes, char **buf)
1011 READ_REQ *pSMB = NULL;
1012 READ_RSP *pSMBr = NULL;
1013 char *pReadData = NULL;
1016 cFYI(1,("Reading %d bytes on fid %d",count,netfid));
1019 rc = smb_init(SMB_COM_READ_ANDX, 12, tcon, (void **) &pSMB,
1024 /* tcon and ses pointer are checked in smb_init */
1025 if (tcon->ses->server == NULL)
1026 return -ECONNABORTED;
1028 pSMB->AndXCommand = 0xFF; /* none */
1030 pSMB->OffsetLow = cpu_to_le32(lseek & 0xFFFFFFFF);
1031 pSMB->OffsetHigh = cpu_to_le32(lseek >> 32);
1032 pSMB->Remaining = 0;
1033 pSMB->MaxCount = cpu_to_le16(count & 0xFFFF);
1034 pSMB->MaxCountHigh = cpu_to_le32(count >> 16);
1035 pSMB->ByteCount = 0; /* no need to do le conversion since it is 0 */
1037 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1038 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1039 cifs_stats_inc(&tcon->num_reads);
1041 cERROR(1, ("Send error in read = %d", rc));
1043 int data_length = le16_to_cpu(pSMBr->DataLengthHigh);
1044 data_length = data_length << 16;
1045 data_length += le16_to_cpu(pSMBr->DataLength);
1046 *nbytes = data_length;
1048 /*check that DataLength would not go beyond end of SMB */
1049 if ((data_length > CIFSMaxBufSize)
1050 || (data_length > count)) {
1051 cFYI(1,("bad length %d for count %d",data_length,count));
1056 (char *) (&pSMBr->hdr.Protocol) +
1057 le16_to_cpu(pSMBr->DataOffset);
1058 /* if(rc = copy_to_user(buf, pReadData, data_length)) {
1059 cERROR(1,("Faulting on read rc = %d",rc));
1061 }*/ /* can not use copy_to_user when using page cache*/
1063 memcpy(*buf,pReadData,data_length);
1067 cifs_buf_release(pSMB);
1069 *buf = (char *)pSMB;
1071 /* Note: On -EAGAIN error only caller can retry on handle based calls
1072 since file handle passed in no longer valid */
1077 CIFSSMBWrite(const int xid, struct cifsTconInfo *tcon,
1078 const int netfid, const unsigned int count,
1079 const __u64 offset, unsigned int *nbytes, const char *buf,
1080 const char __user * ubuf, const int long_op)
1083 WRITE_REQ *pSMB = NULL;
1084 WRITE_RSP *pSMBr = NULL;
1089 /* cFYI(1,("write at %lld %d bytes",offset,count));*/
1090 rc = smb_init(SMB_COM_WRITE_ANDX, 14, tcon, (void **) &pSMB,
1094 /* tcon and ses pointer are checked in smb_init */
1095 if (tcon->ses->server == NULL)
1096 return -ECONNABORTED;
1098 pSMB->AndXCommand = 0xFF; /* none */
1100 pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF);
1101 pSMB->OffsetHigh = cpu_to_le32(offset >> 32);
1102 pSMB->Reserved = 0xFFFFFFFF;
1103 pSMB->WriteMode = 0;
1104 pSMB->Remaining = 0;
1106 /* Can increase buffer size if buffer is big enough in some cases - ie we
1107 can send more if LARGE_WRITE_X capability returned by the server and if
1108 our buffer is big enough or if we convert to iovecs on socket writes
1109 and eliminate the copy to the CIFS buffer */
1110 if(tcon->ses->capabilities & CAP_LARGE_WRITE_X) {
1111 bytes_sent = min_t(const unsigned int, CIFSMaxBufSize, count);
1113 bytes_sent = (tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE)
1117 if (bytes_sent > count)
1120 cpu_to_le16(offsetof(struct smb_com_write_req,Data) - 4);
1122 memcpy(pSMB->Data,buf,bytes_sent);
1124 if(copy_from_user(pSMB->Data,ubuf,bytes_sent)) {
1125 cifs_buf_release(pSMB);
1130 cifs_buf_release(pSMB);
1134 byte_count = bytes_sent + 1 /* pad */ ; /* BB fix this for sends > 64K */
1135 pSMB->DataLengthLow = cpu_to_le16(bytes_sent & 0xFFFF);
1136 pSMB->DataLengthHigh = cpu_to_le16(bytes_sent >> 16);
1137 pSMB->hdr.smb_buf_length += bytes_sent+1;
1138 pSMB->ByteCount = cpu_to_le16(byte_count);
1140 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1141 (struct smb_hdr *) pSMBr, &bytes_returned, long_op);
1142 cifs_stats_inc(&tcon->num_writes);
1144 cFYI(1, ("Send error in write = %d", rc));
1147 *nbytes = le16_to_cpu(pSMBr->CountHigh);
1148 *nbytes = (*nbytes) << 16;
1149 *nbytes += le16_to_cpu(pSMBr->Count);
1152 cifs_buf_release(pSMB);
1154 /* Note: On -EAGAIN error only caller can retry on handle based calls
1155 since file handle passed in no longer valid */
1160 #ifdef CONFIG_CIFS_EXPERIMENTAL
1162 CIFSSMBWrite2(const int xid, struct cifsTconInfo *tcon,
1163 const int netfid, const unsigned int count,
1164 const __u64 offset, unsigned int *nbytes, const char *buf,
1168 WRITE_REQ *pSMB = NULL;
1174 cFYI(1,("write2 at %lld %d bytes",offset,count)); /* BB removeme BB */
1175 rc = small_smb_init(SMB_COM_WRITE_ANDX, 14, tcon, (void **) &pSMB);
1178 /* tcon and ses pointer are checked in smb_init */
1179 if (tcon->ses->server == NULL)
1180 return -ECONNABORTED;
1182 pSMB->AndXCommand = 0xFF; /* none */
1184 pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF);
1185 pSMB->OffsetHigh = cpu_to_le32(offset >> 32);
1186 pSMB->Reserved = 0xFFFFFFFF;
1187 pSMB->WriteMode = 0;
1188 pSMB->Remaining = 0;
1190 /* Can increase buffer size if buffer is big enough in some cases - ie
1191 can send more if LARGE_WRITE_X capability returned by the server and if
1192 our buffer is big enough or if we convert to iovecs on socket writes
1193 and eliminate the copy to the CIFS buffer */
1194 if(tcon->ses->capabilities & CAP_LARGE_WRITE_X) {
1195 bytes_sent = min_t(const unsigned int, CIFSMaxBufSize, count);
1197 bytes_sent = (tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE)
1201 if (bytes_sent > count)
1204 cpu_to_le16(offsetof(struct smb_com_write_req,Data) - 4);
1206 byte_count = bytes_sent + 1 /* pad */ ; /* BB fix this for sends > 64K */
1207 pSMB->DataLengthLow = cpu_to_le16(bytes_sent & 0xFFFF);
1208 pSMB->DataLengthHigh = cpu_to_le16(bytes_sent >> 16);
1209 smb_hdr_len = pSMB->hdr.smb_buf_length + 1; /* hdr + 1 byte pad */
1210 pSMB->hdr.smb_buf_length += bytes_sent+1;
1211 pSMB->ByteCount = cpu_to_le16(byte_count);
1213 rc = SendReceive2(xid, tcon->ses, (struct smb_hdr *) pSMB, smb_hdr_len,
1214 buf, bytes_sent, &bytes_returned, long_op);
1215 cifs_stats_inc(&tcon->num_writes);
1217 cFYI(1, ("Send error in write = %d", rc));
1220 WRITE_RSP * pSMBr = (WRITE_RSP *)pSMB;
1221 *nbytes = le16_to_cpu(pSMBr->CountHigh);
1222 *nbytes = (*nbytes) << 16;
1223 *nbytes += le16_to_cpu(pSMBr->Count);
1226 cifs_small_buf_release(pSMB);
1228 /* Note: On -EAGAIN error only caller can retry on handle based calls
1229 since file handle passed in no longer valid */
1235 #endif /* CIFS_EXPERIMENTAL */
1238 CIFSSMBLock(const int xid, struct cifsTconInfo *tcon,
1239 const __u16 smb_file_id, const __u64 len,
1240 const __u64 offset, const __u32 numUnlock,
1241 const __u32 numLock, const __u8 lockType, const int waitFlag)
1244 LOCK_REQ *pSMB = NULL;
1245 LOCK_RSP *pSMBr = NULL;
1250 cFYI(1, ("In CIFSSMBLock - timeout %d numLock %d",waitFlag,numLock));
1251 rc = small_smb_init(SMB_COM_LOCKING_ANDX, 8, tcon, (void **) &pSMB);
1256 pSMBr = (LOCK_RSP *)pSMB; /* BB removeme BB */
1258 if(lockType == LOCKING_ANDX_OPLOCK_RELEASE) {
1259 timeout = -1; /* no response expected */
1261 } else if (waitFlag == TRUE) {
1262 timeout = 3; /* blocking operation, no timeout */
1263 pSMB->Timeout = cpu_to_le32(-1);/* blocking - do not time out */
1268 pSMB->NumberOfLocks = cpu_to_le16(numLock);
1269 pSMB->NumberOfUnlocks = cpu_to_le16(numUnlock);
1270 pSMB->LockType = lockType;
1271 pSMB->AndXCommand = 0xFF; /* none */
1272 pSMB->Fid = smb_file_id; /* netfid stays le */
1274 if((numLock != 0) || (numUnlock != 0)) {
1275 pSMB->Locks[0].Pid = cpu_to_le16(current->tgid);
1276 /* BB where to store pid high? */
1277 pSMB->Locks[0].LengthLow = cpu_to_le32((u32)len);
1278 pSMB->Locks[0].LengthHigh = cpu_to_le32((u32)(len>>32));
1279 pSMB->Locks[0].OffsetLow = cpu_to_le32((u32)offset);
1280 pSMB->Locks[0].OffsetHigh = cpu_to_le32((u32)(offset>>32));
1281 count = sizeof(LOCKING_ANDX_RANGE);
1286 pSMB->hdr.smb_buf_length += count;
1287 pSMB->ByteCount = cpu_to_le16(count);
1289 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1290 (struct smb_hdr *) pSMBr, &bytes_returned, timeout);
1291 cifs_stats_inc(&tcon->num_locks);
1293 cFYI(1, ("Send error in Lock = %d", rc));
1295 cifs_small_buf_release(pSMB);
1297 /* Note: On -EAGAIN error only caller can retry on handle based calls
1298 since file handle passed in no longer valid */
1303 CIFSSMBClose(const int xid, struct cifsTconInfo *tcon, int smb_file_id)
1306 CLOSE_REQ *pSMB = NULL;
1307 CLOSE_RSP *pSMBr = NULL;
1309 cFYI(1, ("In CIFSSMBClose"));
1311 /* do not retry on dead session on close */
1312 rc = small_smb_init(SMB_COM_CLOSE, 3, tcon, (void **) &pSMB);
1318 pSMBr = (CLOSE_RSP *)pSMB; /* BB removeme BB */
1320 pSMB->FileID = (__u16) smb_file_id;
1321 pSMB->LastWriteTime = 0;
1322 pSMB->ByteCount = 0;
1323 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1324 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1325 cifs_stats_inc(&tcon->num_closes);
1328 /* EINTR is expected when user ctl-c to kill app */
1329 cERROR(1, ("Send error in Close = %d", rc));
1333 cifs_small_buf_release(pSMB);
1335 /* Since session is dead, file will be closed on server already */
1343 CIFSSMBRename(const int xid, struct cifsTconInfo *tcon,
1344 const char *fromName, const char *toName,
1345 const struct nls_table *nls_codepage, int remap)
1348 RENAME_REQ *pSMB = NULL;
1349 RENAME_RSP *pSMBr = NULL;
1351 int name_len, name_len2;
1354 cFYI(1, ("In CIFSSMBRename"));
1356 rc = smb_init(SMB_COM_RENAME, 1, tcon, (void **) &pSMB,
1361 pSMB->BufferFormat = 0x04;
1362 pSMB->SearchAttributes =
1363 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
1366 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1368 cifsConvertToUCS((__le16 *) pSMB->OldFileName, fromName,
1369 PATH_MAX, nls_codepage, remap);
1370 name_len++; /* trailing null */
1372 pSMB->OldFileName[name_len] = 0x04; /* pad */
1373 /* protocol requires ASCII signature byte on Unicode string */
1374 pSMB->OldFileName[name_len + 1] = 0x00;
1376 cifsConvertToUCS((__le16 *) &pSMB->OldFileName[name_len + 2],
1377 toName, PATH_MAX, nls_codepage, remap);
1378 name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
1379 name_len2 *= 2; /* convert to bytes */
1380 } else { /* BB improve the check for buffer overruns BB */
1381 name_len = strnlen(fromName, PATH_MAX);
1382 name_len++; /* trailing null */
1383 strncpy(pSMB->OldFileName, fromName, name_len);
1384 name_len2 = strnlen(toName, PATH_MAX);
1385 name_len2++; /* trailing null */
1386 pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */
1387 strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2);
1388 name_len2++; /* trailing null */
1389 name_len2++; /* signature byte */
1392 count = 1 /* 1st signature byte */ + name_len + name_len2;
1393 pSMB->hdr.smb_buf_length += count;
1394 pSMB->ByteCount = cpu_to_le16(count);
1396 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1397 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1398 cifs_stats_inc(&tcon->num_renames);
1400 cFYI(1, ("Send error in rename = %d", rc));
1403 cifs_buf_release(pSMB);
1411 int CIFSSMBRenameOpenFile(const int xid,struct cifsTconInfo *pTcon,
1412 int netfid, char * target_name,
1413 const struct nls_table * nls_codepage, int remap)
1415 struct smb_com_transaction2_sfi_req *pSMB = NULL;
1416 struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
1417 struct set_file_rename * rename_info;
1419 char dummy_string[30];
1421 int bytes_returned = 0;
1423 __u16 params, param_offset, offset, count, byte_count;
1425 cFYI(1, ("Rename to File by handle"));
1426 rc = smb_init(SMB_COM_TRANSACTION2, 15, pTcon, (void **) &pSMB,
1432 pSMB->MaxSetupCount = 0;
1436 pSMB->Reserved2 = 0;
1437 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
1438 offset = param_offset + params;
1440 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
1441 rename_info = (struct set_file_rename *) data_offset;
1442 pSMB->MaxParameterCount = cpu_to_le16(2);
1443 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB PDU from sess */
1444 pSMB->SetupCount = 1;
1445 pSMB->Reserved3 = 0;
1446 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
1447 byte_count = 3 /* pad */ + params;
1448 pSMB->ParameterCount = cpu_to_le16(params);
1449 pSMB->TotalParameterCount = pSMB->ParameterCount;
1450 pSMB->ParameterOffset = cpu_to_le16(param_offset);
1451 pSMB->DataOffset = cpu_to_le16(offset);
1452 /* construct random name ".cifs_tmp<inodenum><mid>" */
1453 rename_info->overwrite = cpu_to_le32(1);
1454 rename_info->root_fid = 0;
1455 /* unicode only call */
1456 if(target_name == NULL) {
1457 sprintf(dummy_string,"cifs%x",pSMB->hdr.Mid);
1458 len_of_str = cifsConvertToUCS((__le16 *)rename_info->target_name,
1459 dummy_string, 24, nls_codepage, remap);
1461 len_of_str = cifsConvertToUCS((__le16 *)rename_info->target_name,
1462 target_name, PATH_MAX, nls_codepage, remap);
1464 rename_info->target_name_len = cpu_to_le32(2 * len_of_str);
1465 count = 12 /* sizeof(struct set_file_rename) */ + (2 * len_of_str) + 2;
1466 byte_count += count;
1467 pSMB->DataCount = cpu_to_le16(count);
1468 pSMB->TotalDataCount = pSMB->DataCount;
1470 pSMB->InformationLevel =
1471 cpu_to_le16(SMB_SET_FILE_RENAME_INFORMATION);
1472 pSMB->Reserved4 = 0;
1473 pSMB->hdr.smb_buf_length += byte_count;
1474 pSMB->ByteCount = cpu_to_le16(byte_count);
1475 rc = SendReceive(xid, pTcon->ses, (struct smb_hdr *) pSMB,
1476 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1477 cifs_stats_inc(&pTcon->num_t2renames);
1479 cFYI(1,("Send error in Rename (by file handle) = %d", rc));
1482 cifs_buf_release(pSMB);
1484 /* Note: On -EAGAIN error only caller can retry on handle based calls
1485 since file handle passed in no longer valid */
1491 CIFSSMBCopy(const int xid, struct cifsTconInfo *tcon, const char * fromName,
1492 const __u16 target_tid, const char *toName, const int flags,
1493 const struct nls_table *nls_codepage, int remap)
1496 COPY_REQ *pSMB = NULL;
1497 COPY_RSP *pSMBr = NULL;
1499 int name_len, name_len2;
1502 cFYI(1, ("In CIFSSMBCopy"));
1504 rc = smb_init(SMB_COM_COPY, 1, tcon, (void **) &pSMB,
1509 pSMB->BufferFormat = 0x04;
1510 pSMB->Tid2 = target_tid;
1512 pSMB->Flags = cpu_to_le16(flags & COPY_TREE);
1514 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1515 name_len = cifsConvertToUCS((__le16 *) pSMB->OldFileName,
1516 fromName, PATH_MAX, nls_codepage,
1518 name_len++; /* trailing null */
1520 pSMB->OldFileName[name_len] = 0x04; /* pad */
1521 /* protocol requires ASCII signature byte on Unicode string */
1522 pSMB->OldFileName[name_len + 1] = 0x00;
1523 name_len2 = cifsConvertToUCS((__le16 *)&pSMB->OldFileName[name_len + 2],
1524 toName, PATH_MAX, nls_codepage, remap);
1525 name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
1526 name_len2 *= 2; /* convert to bytes */
1527 } else { /* BB improve the check for buffer overruns BB */
1528 name_len = strnlen(fromName, PATH_MAX);
1529 name_len++; /* trailing null */
1530 strncpy(pSMB->OldFileName, fromName, name_len);
1531 name_len2 = strnlen(toName, PATH_MAX);
1532 name_len2++; /* trailing null */
1533 pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */
1534 strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2);
1535 name_len2++; /* trailing null */
1536 name_len2++; /* signature byte */
1539 count = 1 /* 1st signature byte */ + name_len + name_len2;
1540 pSMB->hdr.smb_buf_length += count;
1541 pSMB->ByteCount = cpu_to_le16(count);
1543 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1544 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1546 cFYI(1, ("Send error in copy = %d with %d files copied",
1547 rc, le16_to_cpu(pSMBr->CopyCount)));
1550 cifs_buf_release(pSMB);
1559 CIFSUnixCreateSymLink(const int xid, struct cifsTconInfo *tcon,
1560 const char *fromName, const char *toName,
1561 const struct nls_table *nls_codepage)
1563 TRANSACTION2_SPI_REQ *pSMB = NULL;
1564 TRANSACTION2_SPI_RSP *pSMBr = NULL;
1567 int name_len_target;
1569 int bytes_returned = 0;
1570 __u16 params, param_offset, offset, byte_count;
1572 cFYI(1, ("In Symlink Unix style"));
1574 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
1579 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1581 cifs_strtoUCS((wchar_t *) pSMB->FileName, fromName, PATH_MAX
1582 /* find define for this maxpathcomponent */
1584 name_len++; /* trailing null */
1587 } else { /* BB improve the check for buffer overruns BB */
1588 name_len = strnlen(fromName, PATH_MAX);
1589 name_len++; /* trailing null */
1590 strncpy(pSMB->FileName, fromName, name_len);
1592 params = 6 + name_len;
1593 pSMB->MaxSetupCount = 0;
1597 pSMB->Reserved2 = 0;
1598 param_offset = offsetof(struct smb_com_transaction2_spi_req,
1599 InformationLevel) - 4;
1600 offset = param_offset + params;
1602 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
1603 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1605 cifs_strtoUCS((wchar_t *) data_offset, toName, PATH_MAX
1606 /* find define for this maxpathcomponent */
1608 name_len_target++; /* trailing null */
1609 name_len_target *= 2;
1610 } else { /* BB improve the check for buffer overruns BB */
1611 name_len_target = strnlen(toName, PATH_MAX);
1612 name_len_target++; /* trailing null */
1613 strncpy(data_offset, toName, name_len_target);
1616 pSMB->MaxParameterCount = cpu_to_le16(2);
1617 /* BB find exact max on data count below from sess */
1618 pSMB->MaxDataCount = cpu_to_le16(1000);
1619 pSMB->SetupCount = 1;
1620 pSMB->Reserved3 = 0;
1621 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
1622 byte_count = 3 /* pad */ + params + name_len_target;
1623 pSMB->DataCount = cpu_to_le16(name_len_target);
1624 pSMB->ParameterCount = cpu_to_le16(params);
1625 pSMB->TotalDataCount = pSMB->DataCount;
1626 pSMB->TotalParameterCount = pSMB->ParameterCount;
1627 pSMB->ParameterOffset = cpu_to_le16(param_offset);
1628 pSMB->DataOffset = cpu_to_le16(offset);
1629 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_LINK);
1630 pSMB->Reserved4 = 0;
1631 pSMB->hdr.smb_buf_length += byte_count;
1632 pSMB->ByteCount = cpu_to_le16(byte_count);
1633 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1634 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1635 cifs_stats_inc(&tcon->num_symlinks);
1638 ("Send error in SetPathInfo (create symlink) = %d",
1643 cifs_buf_release(pSMB);
1646 goto createSymLinkRetry;
1652 CIFSUnixCreateHardLink(const int xid, struct cifsTconInfo *tcon,
1653 const char *fromName, const char *toName,
1654 const struct nls_table *nls_codepage, int remap)
1656 TRANSACTION2_SPI_REQ *pSMB = NULL;
1657 TRANSACTION2_SPI_RSP *pSMBr = NULL;
1660 int name_len_target;
1662 int bytes_returned = 0;
1663 __u16 params, param_offset, offset, byte_count;
1665 cFYI(1, ("In Create Hard link Unix style"));
1666 createHardLinkRetry:
1667 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
1672 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1673 name_len = cifsConvertToUCS((__le16 *) pSMB->FileName, toName,
1674 PATH_MAX, nls_codepage, remap);
1675 name_len++; /* trailing null */
1678 } else { /* BB improve the check for buffer overruns BB */
1679 name_len = strnlen(toName, PATH_MAX);
1680 name_len++; /* trailing null */
1681 strncpy(pSMB->FileName, toName, name_len);
1683 params = 6 + name_len;
1684 pSMB->MaxSetupCount = 0;
1688 pSMB->Reserved2 = 0;
1689 param_offset = offsetof(struct smb_com_transaction2_spi_req,
1690 InformationLevel) - 4;
1691 offset = param_offset + params;
1693 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
1694 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1696 cifsConvertToUCS((__le16 *) data_offset, fromName, PATH_MAX,
1697 nls_codepage, remap);
1698 name_len_target++; /* trailing null */
1699 name_len_target *= 2;
1700 } else { /* BB improve the check for buffer overruns BB */
1701 name_len_target = strnlen(fromName, PATH_MAX);
1702 name_len_target++; /* trailing null */
1703 strncpy(data_offset, fromName, name_len_target);
1706 pSMB->MaxParameterCount = cpu_to_le16(2);
1707 /* BB find exact max on data count below from sess*/
1708 pSMB->MaxDataCount = cpu_to_le16(1000);
1709 pSMB->SetupCount = 1;
1710 pSMB->Reserved3 = 0;
1711 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
1712 byte_count = 3 /* pad */ + params + name_len_target;
1713 pSMB->ParameterCount = cpu_to_le16(params);
1714 pSMB->TotalParameterCount = pSMB->ParameterCount;
1715 pSMB->DataCount = cpu_to_le16(name_len_target);
1716 pSMB->TotalDataCount = pSMB->DataCount;
1717 pSMB->ParameterOffset = cpu_to_le16(param_offset);
1718 pSMB->DataOffset = cpu_to_le16(offset);
1719 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_HLINK);
1720 pSMB->Reserved4 = 0;
1721 pSMB->hdr.smb_buf_length += byte_count;
1722 pSMB->ByteCount = cpu_to_le16(byte_count);
1723 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1724 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1725 cifs_stats_inc(&tcon->num_hardlinks);
1727 cFYI(1, ("Send error in SetPathInfo (hard link) = %d", rc));
1730 cifs_buf_release(pSMB);
1732 goto createHardLinkRetry;
1738 CIFSCreateHardLink(const int xid, struct cifsTconInfo *tcon,
1739 const char *fromName, const char *toName,
1740 const struct nls_table *nls_codepage, int remap)
1743 NT_RENAME_REQ *pSMB = NULL;
1744 RENAME_RSP *pSMBr = NULL;
1746 int name_len, name_len2;
1749 cFYI(1, ("In CIFSCreateHardLink"));
1750 winCreateHardLinkRetry:
1752 rc = smb_init(SMB_COM_NT_RENAME, 4, tcon, (void **) &pSMB,
1757 pSMB->SearchAttributes =
1758 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
1760 pSMB->Flags = cpu_to_le16(CREATE_HARD_LINK);
1761 pSMB->ClusterCount = 0;
1763 pSMB->BufferFormat = 0x04;
1765 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1767 cifsConvertToUCS((__le16 *) pSMB->OldFileName, fromName,
1768 PATH_MAX, nls_codepage, remap);
1769 name_len++; /* trailing null */
1771 pSMB->OldFileName[name_len] = 0; /* pad */
1772 pSMB->OldFileName[name_len + 1] = 0x04;
1774 cifsConvertToUCS((__le16 *)&pSMB->OldFileName[name_len + 2],
1775 toName, PATH_MAX, nls_codepage, remap);
1776 name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
1777 name_len2 *= 2; /* convert to bytes */
1778 } else { /* BB improve the check for buffer overruns BB */
1779 name_len = strnlen(fromName, PATH_MAX);
1780 name_len++; /* trailing null */
1781 strncpy(pSMB->OldFileName, fromName, name_len);
1782 name_len2 = strnlen(toName, PATH_MAX);
1783 name_len2++; /* trailing null */
1784 pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */
1785 strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2);
1786 name_len2++; /* trailing null */
1787 name_len2++; /* signature byte */
1790 count = 1 /* string type byte */ + name_len + name_len2;
1791 pSMB->hdr.smb_buf_length += count;
1792 pSMB->ByteCount = cpu_to_le16(count);
1794 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1795 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1796 cifs_stats_inc(&tcon->num_hardlinks);
1798 cFYI(1, ("Send error in hard link (NT rename) = %d", rc));
1800 cifs_buf_release(pSMB);
1802 goto winCreateHardLinkRetry;
1808 CIFSSMBUnixQuerySymLink(const int xid, struct cifsTconInfo *tcon,
1809 const unsigned char *searchName,
1810 char *symlinkinfo, const int buflen,
1811 const struct nls_table *nls_codepage)
1813 /* SMB_QUERY_FILE_UNIX_LINK */
1814 TRANSACTION2_QPI_REQ *pSMB = NULL;
1815 TRANSACTION2_QPI_RSP *pSMBr = NULL;
1819 __u16 params, byte_count;
1821 cFYI(1, ("In QPathSymLinkInfo (Unix) for path %s", searchName));
1824 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
1829 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1831 cifs_strtoUCS((wchar_t *) pSMB->FileName, searchName, PATH_MAX
1832 /* find define for this maxpathcomponent */
1834 name_len++; /* trailing null */
1836 } else { /* BB improve the check for buffer overruns BB */
1837 name_len = strnlen(searchName, PATH_MAX);
1838 name_len++; /* trailing null */
1839 strncpy(pSMB->FileName, searchName, name_len);
1842 params = 2 /* level */ + 4 /* rsrvd */ + name_len /* incl null */ ;
1843 pSMB->TotalDataCount = 0;
1844 pSMB->MaxParameterCount = cpu_to_le16(2);
1845 /* BB find exact max data count below from sess structure BB */
1846 pSMB->MaxDataCount = cpu_to_le16(4000);
1847 pSMB->MaxSetupCount = 0;
1851 pSMB->Reserved2 = 0;
1852 pSMB->ParameterOffset = cpu_to_le16(offsetof(
1853 struct smb_com_transaction2_qpi_req ,InformationLevel) - 4);
1854 pSMB->DataCount = 0;
1855 pSMB->DataOffset = 0;
1856 pSMB->SetupCount = 1;
1857 pSMB->Reserved3 = 0;
1858 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
1859 byte_count = params + 1 /* pad */ ;
1860 pSMB->TotalParameterCount = cpu_to_le16(params);
1861 pSMB->ParameterCount = pSMB->TotalParameterCount;
1862 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_LINK);
1863 pSMB->Reserved4 = 0;
1864 pSMB->hdr.smb_buf_length += byte_count;
1865 pSMB->ByteCount = cpu_to_le16(byte_count);
1867 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1868 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1870 cFYI(1, ("Send error in QuerySymLinkInfo = %d", rc));
1872 /* decode response */
1874 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
1875 if (rc || (pSMBr->ByteCount < 2))
1876 /* BB also check enough total bytes returned */
1877 rc = -EIO; /* bad smb */
1879 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
1880 __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
1882 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
1883 name_len = UniStrnlen((wchar_t *) ((char *)
1884 &pSMBr->hdr.Protocol +data_offset),
1885 min_t(const int, buflen,count) / 2);
1886 /* BB FIXME investigate remapping reserved chars here */
1887 cifs_strfromUCS_le(symlinkinfo,
1888 (wchar_t *) ((char *)&pSMBr->hdr.Protocol +
1890 name_len, nls_codepage);
1892 strncpy(symlinkinfo,
1893 (char *) &pSMBr->hdr.Protocol +
1895 min_t(const int, buflen, count));
1897 symlinkinfo[buflen] = 0;
1898 /* just in case so calling code does not go off the end of buffer */
1901 cifs_buf_release(pSMB);
1903 goto querySymLinkRetry;
1908 CIFSSMBQueryReparseLinkInfo(const int xid, struct cifsTconInfo *tcon,
1909 const unsigned char *searchName,
1910 char *symlinkinfo, const int buflen,__u16 fid,
1911 const struct nls_table *nls_codepage)
1916 struct smb_com_transaction_ioctl_req * pSMB;
1917 struct smb_com_transaction_ioctl_rsp * pSMBr;
1919 cFYI(1, ("In Windows reparse style QueryLink for path %s", searchName));
1920 rc = smb_init(SMB_COM_NT_TRANSACT, 23, tcon, (void **) &pSMB,
1925 pSMB->TotalParameterCount = 0 ;
1926 pSMB->TotalDataCount = 0;
1927 pSMB->MaxParameterCount = cpu_to_le32(2);
1928 /* BB find exact data count max from sess structure BB */
1929 pSMB->MaxDataCount = cpu_to_le32(4000);
1930 pSMB->MaxSetupCount = 4;
1932 pSMB->ParameterOffset = 0;
1933 pSMB->DataCount = 0;
1934 pSMB->DataOffset = 0;
1935 pSMB->SetupCount = 4;
1936 pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_IOCTL);
1937 pSMB->ParameterCount = pSMB->TotalParameterCount;
1938 pSMB->FunctionCode = cpu_to_le32(FSCTL_GET_REPARSE_POINT);
1939 pSMB->IsFsctl = 1; /* FSCTL */
1940 pSMB->IsRootFlag = 0;
1941 pSMB->Fid = fid; /* file handle always le */
1942 pSMB->ByteCount = 0;
1944 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1945 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1947 cFYI(1, ("Send error in QueryReparseLinkInfo = %d", rc));
1948 } else { /* decode response */
1949 __u32 data_offset = le32_to_cpu(pSMBr->DataOffset);
1950 __u32 data_count = le32_to_cpu(pSMBr->DataCount);
1951 if ((pSMBr->ByteCount < 2) || (data_offset > 512))
1952 /* BB also check enough total bytes returned */
1953 rc = -EIO; /* bad smb */
1955 if(data_count && (data_count < 2048)) {
1956 char * end_of_smb = pSMBr->ByteCount + (char *)&pSMBr->ByteCount;
1958 struct reparse_data * reparse_buf = (struct reparse_data *)
1959 ((char *)&pSMBr->hdr.Protocol + data_offset);
1960 if((char*)reparse_buf >= end_of_smb) {
1964 if((reparse_buf->LinkNamesBuf +
1965 reparse_buf->TargetNameOffset +
1966 reparse_buf->TargetNameLen) >
1968 cFYI(1,("reparse buf extended beyond SMB"));
1973 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
1974 name_len = UniStrnlen((wchar_t *)
1975 (reparse_buf->LinkNamesBuf +
1976 reparse_buf->TargetNameOffset),
1977 min(buflen/2, reparse_buf->TargetNameLen / 2));
1978 cifs_strfromUCS_le(symlinkinfo,
1979 (wchar_t *) (reparse_buf->LinkNamesBuf +
1980 reparse_buf->TargetNameOffset),
1981 name_len, nls_codepage);
1982 } else { /* ASCII names */
1983 strncpy(symlinkinfo,reparse_buf->LinkNamesBuf +
1984 reparse_buf->TargetNameOffset,
1985 min_t(const int, buflen, reparse_buf->TargetNameLen));
1989 cFYI(1,("Invalid return data count on get reparse info ioctl"));
1991 symlinkinfo[buflen] = 0; /* just in case so the caller
1992 does not go off the end of the buffer */
1993 cFYI(1,("readlink result - %s ",symlinkinfo));
1997 cifs_buf_release(pSMB);
1999 /* Note: On -EAGAIN error only caller can retry on handle based calls
2000 since file handle passed in no longer valid */
2005 #ifdef CONFIG_CIFS_POSIX
2007 /*Convert an Access Control Entry from wire format to local POSIX xattr format*/
2008 static void cifs_convert_ace(posix_acl_xattr_entry * ace, struct cifs_posix_ace * cifs_ace)
2010 /* u8 cifs fields do not need le conversion */
2011 ace->e_perm = (__u16)cifs_ace->cifs_e_perm;
2012 ace->e_tag = (__u16)cifs_ace->cifs_e_tag;
2013 ace->e_id = (__u32)le64_to_cpu(cifs_ace->cifs_uid);
2014 /* cFYI(1,("perm %d tag %d id %d",ace->e_perm,ace->e_tag,ace->e_id)); */
2019 /* Convert ACL from CIFS POSIX wire format to local Linux POSIX ACL xattr */
2020 static int cifs_copy_posix_acl(char * trgt,char * src, const int buflen,
2021 const int acl_type,const int size_of_data_area)
2026 struct cifs_posix_ace * pACE;
2027 struct cifs_posix_acl * cifs_acl = (struct cifs_posix_acl *)src;
2028 posix_acl_xattr_header * local_acl = (posix_acl_xattr_header *)trgt;
2030 if (le16_to_cpu(cifs_acl->version) != CIFS_ACL_VERSION)
2033 if(acl_type & ACL_TYPE_ACCESS) {
2034 count = le16_to_cpu(cifs_acl->access_entry_count);
2035 pACE = &cifs_acl->ace_array[0];
2036 size = sizeof(struct cifs_posix_acl);
2037 size += sizeof(struct cifs_posix_ace) * count;
2038 /* check if we would go beyond end of SMB */
2039 if(size_of_data_area < size) {
2040 cFYI(1,("bad CIFS POSIX ACL size %d vs. %d",size_of_data_area,size));
2043 } else if(acl_type & ACL_TYPE_DEFAULT) {
2044 count = le16_to_cpu(cifs_acl->access_entry_count);
2045 size = sizeof(struct cifs_posix_acl);
2046 size += sizeof(struct cifs_posix_ace) * count;
2047 /* skip past access ACEs to get to default ACEs */
2048 pACE = &cifs_acl->ace_array[count];
2049 count = le16_to_cpu(cifs_acl->default_entry_count);
2050 size += sizeof(struct cifs_posix_ace) * count;
2051 /* check if we would go beyond end of SMB */
2052 if(size_of_data_area < size)
2059 size = posix_acl_xattr_size(count);
2060 if((buflen == 0) || (local_acl == NULL)) {
2061 /* used to query ACL EA size */
2062 } else if(size > buflen) {
2064 } else /* buffer big enough */ {
2065 local_acl->a_version = POSIX_ACL_XATTR_VERSION;
2066 for(i = 0;i < count ;i++) {
2067 cifs_convert_ace(&local_acl->a_entries[i],pACE);
2074 static __u16 convert_ace_to_cifs_ace(struct cifs_posix_ace * cifs_ace,
2075 const posix_acl_xattr_entry * local_ace)
2077 __u16 rc = 0; /* 0 = ACL converted ok */
2079 cifs_ace->cifs_e_perm = (__u8)cpu_to_le16(local_ace->e_perm);
2080 cifs_ace->cifs_e_tag = (__u8)cpu_to_le16(local_ace->e_tag);
2081 /* BB is there a better way to handle the large uid? */
2082 if(local_ace->e_id == -1) {
2083 /* Probably no need to le convert -1 on any arch but can not hurt */
2084 cifs_ace->cifs_uid = cpu_to_le64(-1);
2086 cifs_ace->cifs_uid = (__u64)cpu_to_le32(local_ace->e_id);
2087 /*cFYI(1,("perm %d tag %d id %d",ace->e_perm,ace->e_tag,ace->e_id));*/
2091 /* Convert ACL from local Linux POSIX xattr to CIFS POSIX ACL wire format */
2092 static __u16 ACL_to_cifs_posix(char * parm_data,const char * pACL,const int buflen,
2096 struct cifs_posix_acl * cifs_acl = (struct cifs_posix_acl *)parm_data;
2097 posix_acl_xattr_header * local_acl = (posix_acl_xattr_header *)pACL;
2101 if((buflen == 0) || (pACL == NULL) || (cifs_acl == NULL))
2104 count = posix_acl_xattr_count((size_t)buflen);
2105 cFYI(1,("setting acl with %d entries from buf of length %d and version of %d",
2106 count,buflen,local_acl->a_version));
2107 if(local_acl->a_version != 2) {
2108 cFYI(1,("unknown POSIX ACL version %d",local_acl->a_version));
2111 cifs_acl->version = cpu_to_le16(1);
2112 if(acl_type == ACL_TYPE_ACCESS)
2113 cifs_acl->access_entry_count = count;
2114 else if(acl_type == ACL_TYPE_DEFAULT)
2115 cifs_acl->default_entry_count = count;
2117 cFYI(1,("unknown ACL type %d",acl_type));
2120 for(i=0;i<count;i++) {
2121 rc = convert_ace_to_cifs_ace(&cifs_acl->ace_array[i],
2122 &local_acl->a_entries[i]);
2124 /* ACE not converted */
2129 rc = (__u16)(count * sizeof(struct cifs_posix_ace));
2130 rc += sizeof(struct cifs_posix_acl);
2131 /* BB add check to make sure ACL does not overflow SMB */
2137 CIFSSMBGetPosixACL(const int xid, struct cifsTconInfo *tcon,
2138 const unsigned char *searchName,
2139 char *acl_inf, const int buflen, const int acl_type,
2140 const struct nls_table *nls_codepage, int remap)
2142 /* SMB_QUERY_POSIX_ACL */
2143 TRANSACTION2_QPI_REQ *pSMB = NULL;
2144 TRANSACTION2_QPI_RSP *pSMBr = NULL;
2148 __u16 params, byte_count;
2150 cFYI(1, ("In GetPosixACL (Unix) for path %s", searchName));
2153 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2158 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2160 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
2161 PATH_MAX, nls_codepage, remap);
2162 name_len++; /* trailing null */
2164 pSMB->FileName[name_len] = 0;
2165 pSMB->FileName[name_len+1] = 0;
2166 } else { /* BB improve the check for buffer overruns BB */
2167 name_len = strnlen(searchName, PATH_MAX);
2168 name_len++; /* trailing null */
2169 strncpy(pSMB->FileName, searchName, name_len);
2172 params = 2 /* level */ + 4 /* rsrvd */ + name_len /* incl null */ ;
2173 pSMB->TotalDataCount = 0;
2174 pSMB->MaxParameterCount = cpu_to_le16(2);
2175 /* BB find exact max data count below from sess structure BB */
2176 pSMB->MaxDataCount = cpu_to_le16(4000);
2177 pSMB->MaxSetupCount = 0;
2181 pSMB->Reserved2 = 0;
2182 pSMB->ParameterOffset = cpu_to_le16(
2183 offsetof(struct smb_com_transaction2_qpi_req ,InformationLevel) - 4);
2184 pSMB->DataCount = 0;
2185 pSMB->DataOffset = 0;
2186 pSMB->SetupCount = 1;
2187 pSMB->Reserved3 = 0;
2188 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
2189 byte_count = params + 1 /* pad */ ;
2190 pSMB->TotalParameterCount = cpu_to_le16(params);
2191 pSMB->ParameterCount = pSMB->TotalParameterCount;
2192 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_POSIX_ACL);
2193 pSMB->Reserved4 = 0;
2194 pSMB->hdr.smb_buf_length += byte_count;
2195 pSMB->ByteCount = cpu_to_le16(byte_count);
2197 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2198 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2200 cFYI(1, ("Send error in Query POSIX ACL = %d", rc));
2202 /* decode response */
2204 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
2205 if (rc || (pSMBr->ByteCount < 2))
2206 /* BB also check enough total bytes returned */
2207 rc = -EIO; /* bad smb */
2209 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
2210 __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
2211 rc = cifs_copy_posix_acl(acl_inf,
2212 (char *)&pSMBr->hdr.Protocol+data_offset,
2213 buflen,acl_type,count);
2216 cifs_buf_release(pSMB);
2223 CIFSSMBSetPosixACL(const int xid, struct cifsTconInfo *tcon,
2224 const unsigned char *fileName,
2225 const char *local_acl, const int buflen,
2227 const struct nls_table *nls_codepage, int remap)
2229 struct smb_com_transaction2_spi_req *pSMB = NULL;
2230 struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
2234 int bytes_returned = 0;
2235 __u16 params, byte_count, data_count, param_offset, offset;
2237 cFYI(1, ("In SetPosixACL (Unix) for path %s", fileName));
2239 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2243 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2245 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
2246 PATH_MAX, nls_codepage, remap);
2247 name_len++; /* trailing null */
2249 } else { /* BB improve the check for buffer overruns BB */
2250 name_len = strnlen(fileName, PATH_MAX);
2251 name_len++; /* trailing null */
2252 strncpy(pSMB->FileName, fileName, name_len);
2254 params = 6 + name_len;
2255 pSMB->MaxParameterCount = cpu_to_le16(2);
2256 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB size from sess */
2257 pSMB->MaxSetupCount = 0;
2261 pSMB->Reserved2 = 0;
2262 param_offset = offsetof(struct smb_com_transaction2_spi_req,
2263 InformationLevel) - 4;
2264 offset = param_offset + params;
2265 parm_data = ((char *) &pSMB->hdr.Protocol) + offset;
2266 pSMB->ParameterOffset = cpu_to_le16(param_offset);
2268 /* convert to on the wire format for POSIX ACL */
2269 data_count = ACL_to_cifs_posix(parm_data,local_acl,buflen,acl_type);
2271 if(data_count == 0) {
2273 goto setACLerrorExit;
2275 pSMB->DataOffset = cpu_to_le16(offset);
2276 pSMB->SetupCount = 1;
2277 pSMB->Reserved3 = 0;
2278 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
2279 pSMB->InformationLevel = cpu_to_le16(SMB_SET_POSIX_ACL);
2280 byte_count = 3 /* pad */ + params + data_count;
2281 pSMB->DataCount = cpu_to_le16(data_count);
2282 pSMB->TotalDataCount = pSMB->DataCount;
2283 pSMB->ParameterCount = cpu_to_le16(params);
2284 pSMB->TotalParameterCount = pSMB->ParameterCount;
2285 pSMB->Reserved4 = 0;
2286 pSMB->hdr.smb_buf_length += byte_count;
2287 pSMB->ByteCount = cpu_to_le16(byte_count);
2288 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2289 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2291 cFYI(1, ("Set POSIX ACL returned %d", rc));
2295 cifs_buf_release(pSMB);
2301 /* BB fix tabs in this function FIXME BB */
2303 CIFSGetExtAttr(const int xid, struct cifsTconInfo *tcon,
2304 const int netfid, __u64 * pExtAttrBits, __u64 *pMask)
2307 struct smb_t2_qfi_req *pSMB = NULL;
2308 struct smb_t2_qfi_rsp *pSMBr = NULL;
2310 __u16 params, byte_count;
2312 cFYI(1,("In GetExtAttr"));
2317 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2322 params = 2 /* level */ +2 /* fid */;
2323 pSMB->t2.TotalDataCount = 0;
2324 pSMB->t2.MaxParameterCount = cpu_to_le16(4);
2325 /* BB find exact max data count below from sess structure BB */
2326 pSMB->t2.MaxDataCount = cpu_to_le16(4000);
2327 pSMB->t2.MaxSetupCount = 0;
2328 pSMB->t2.Reserved = 0;
2330 pSMB->t2.Timeout = 0;
2331 pSMB->t2.Reserved2 = 0;
2332 pSMB->t2.ParameterOffset = cpu_to_le16(offsetof(struct smb_t2_qfi_req,
2334 pSMB->t2.DataCount = 0;
2335 pSMB->t2.DataOffset = 0;
2336 pSMB->t2.SetupCount = 1;
2337 pSMB->t2.Reserved3 = 0;
2338 pSMB->t2.SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION);
2339 byte_count = params + 1 /* pad */ ;
2340 pSMB->t2.TotalParameterCount = cpu_to_le16(params);
2341 pSMB->t2.ParameterCount = pSMB->t2.TotalParameterCount;
2342 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_ATTR_FLAGS);
2345 pSMB->hdr.smb_buf_length += byte_count;
2346 pSMB->t2.ByteCount = cpu_to_le16(byte_count);
2348 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2349 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2351 cFYI(1, ("error %d in GetExtAttr", rc));
2353 /* decode response */
2354 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
2355 if (rc || (pSMBr->ByteCount < 2))
2356 /* BB also check enough total bytes returned */
2357 /* If rc should we check for EOPNOSUPP and
2358 disable the srvino flag? or in caller? */
2359 rc = -EIO; /* bad smb */
2361 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
2362 __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
2363 struct file_chattr_info * pfinfo;
2364 /* BB Do we need a cast or hash here ? */
2366 cFYI(1, ("Illegal size ret in GetExtAttr"));
2370 pfinfo = (struct file_chattr_info *)
2371 (data_offset + (char *) &pSMBr->hdr.Protocol);
2372 *pExtAttrBits = le64_to_cpu(pfinfo->mode);
2373 *pMask = le64_to_cpu(pfinfo->mask);
2377 cifs_buf_release(pSMB);
2379 goto GetExtAttrRetry;
2384 #endif /* CONFIG_POSIX */
2386 /* Legacy Query Path Information call for lookup to old servers such
2388 int SMBQueryInformation(const int xid, struct cifsTconInfo *tcon,
2389 const unsigned char *searchName,
2390 FILE_ALL_INFO * pFinfo,
2391 const struct nls_table *nls_codepage, int remap)
2393 QUERY_INFORMATION_REQ * pSMB;
2394 QUERY_INFORMATION_RSP * pSMBr;
2399 cFYI(1, ("In SMBQPath path %s", searchName));
2401 rc = smb_init(SMB_COM_QUERY_INFORMATION, 0, tcon, (void **) &pSMB,
2406 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2408 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
2409 PATH_MAX, nls_codepage, remap);
2410 name_len++; /* trailing null */
2413 name_len = strnlen(searchName, PATH_MAX);
2414 name_len++; /* trailing null */
2415 strncpy(pSMB->FileName, searchName, name_len);
2417 pSMB->BufferFormat = 0x04;
2418 name_len++; /* account for buffer type byte */
2419 pSMB->hdr.smb_buf_length += (__u16) name_len;
2420 pSMB->ByteCount = cpu_to_le16(name_len);
2422 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2423 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2425 cFYI(1, ("Send error in QueryInfo = %d", rc));
2426 } else if (pFinfo) { /* decode response */
2427 memset(pFinfo, 0, sizeof(FILE_ALL_INFO));
2428 pFinfo->AllocationSize = (__le64) pSMBr->size;
2429 pFinfo->EndOfFile = (__le64) pSMBr->size;
2430 pFinfo->Attributes = (__le32) pSMBr->attr;
2432 rc = -EIO; /* bad buffer passed in */
2434 cifs_buf_release(pSMB);
2446 CIFSSMBQPathInfo(const int xid, struct cifsTconInfo *tcon,
2447 const unsigned char *searchName,
2448 FILE_ALL_INFO * pFindData,
2449 const struct nls_table *nls_codepage, int remap)
2451 /* level 263 SMB_QUERY_FILE_ALL_INFO */
2452 TRANSACTION2_QPI_REQ *pSMB = NULL;
2453 TRANSACTION2_QPI_RSP *pSMBr = NULL;
2457 __u16 params, byte_count;
2459 /* cFYI(1, ("In QPathInfo path %s", searchName)); */
2461 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2466 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2468 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
2469 PATH_MAX, nls_codepage, remap);
2470 name_len++; /* trailing null */
2472 } else { /* BB improve the check for buffer overruns BB */
2473 name_len = strnlen(searchName, PATH_MAX);
2474 name_len++; /* trailing null */
2475 strncpy(pSMB->FileName, searchName, name_len);
2478 params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */ ;
2479 pSMB->TotalDataCount = 0;
2480 pSMB->MaxParameterCount = cpu_to_le16(2);
2481 pSMB->MaxDataCount = cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
2482 pSMB->MaxSetupCount = 0;
2486 pSMB->Reserved2 = 0;
2487 pSMB->ParameterOffset = cpu_to_le16(offsetof(
2488 struct smb_com_transaction2_qpi_req ,InformationLevel) - 4);
2489 pSMB->DataCount = 0;
2490 pSMB->DataOffset = 0;
2491 pSMB->SetupCount = 1;
2492 pSMB->Reserved3 = 0;
2493 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
2494 byte_count = params + 1 /* pad */ ;
2495 pSMB->TotalParameterCount = cpu_to_le16(params);
2496 pSMB->ParameterCount = pSMB->TotalParameterCount;
2497 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_ALL_INFO);
2498 pSMB->Reserved4 = 0;
2499 pSMB->hdr.smb_buf_length += byte_count;
2500 pSMB->ByteCount = cpu_to_le16(byte_count);
2502 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2503 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2505 cFYI(1, ("Send error in QPathInfo = %d", rc));
2506 } else { /* decode response */
2507 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
2509 if (rc || (pSMBr->ByteCount < 40))
2510 rc = -EIO; /* bad smb */
2511 else if (pFindData){
2512 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
2513 memcpy((char *) pFindData,
2514 (char *) &pSMBr->hdr.Protocol +
2515 data_offset, sizeof (FILE_ALL_INFO));
2519 cifs_buf_release(pSMB);
2521 goto QPathInfoRetry;
2527 CIFSSMBUnixQPathInfo(const int xid, struct cifsTconInfo *tcon,
2528 const unsigned char *searchName,
2529 FILE_UNIX_BASIC_INFO * pFindData,
2530 const struct nls_table *nls_codepage, int remap)
2532 /* SMB_QUERY_FILE_UNIX_BASIC */
2533 TRANSACTION2_QPI_REQ *pSMB = NULL;
2534 TRANSACTION2_QPI_RSP *pSMBr = NULL;
2536 int bytes_returned = 0;
2538 __u16 params, byte_count;
2540 cFYI(1, ("In QPathInfo (Unix) the path %s", searchName));
2542 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2547 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2549 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
2550 PATH_MAX, nls_codepage, remap);
2551 name_len++; /* trailing null */
2553 } else { /* BB improve the check for buffer overruns BB */
2554 name_len = strnlen(searchName, PATH_MAX);
2555 name_len++; /* trailing null */
2556 strncpy(pSMB->FileName, searchName, name_len);
2559 params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */ ;
2560 pSMB->TotalDataCount = 0;
2561 pSMB->MaxParameterCount = cpu_to_le16(2);
2562 /* BB find exact max SMB PDU from sess structure BB */
2563 pSMB->MaxDataCount = cpu_to_le16(4000);
2564 pSMB->MaxSetupCount = 0;
2568 pSMB->Reserved2 = 0;
2569 pSMB->ParameterOffset = cpu_to_le16(offsetof(
2570 struct smb_com_transaction2_qpi_req ,InformationLevel) - 4);
2571 pSMB->DataCount = 0;
2572 pSMB->DataOffset = 0;
2573 pSMB->SetupCount = 1;
2574 pSMB->Reserved3 = 0;
2575 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
2576 byte_count = params + 1 /* pad */ ;
2577 pSMB->TotalParameterCount = cpu_to_le16(params);
2578 pSMB->ParameterCount = pSMB->TotalParameterCount;
2579 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC);
2580 pSMB->Reserved4 = 0;
2581 pSMB->hdr.smb_buf_length += byte_count;
2582 pSMB->ByteCount = cpu_to_le16(byte_count);
2584 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2585 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2587 cFYI(1, ("Send error in QPathInfo = %d", rc));
2588 } else { /* decode response */
2589 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
2591 if (rc || (pSMBr->ByteCount < sizeof(FILE_UNIX_BASIC_INFO))) {
2592 rc = -EIO; /* bad smb */
2594 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
2595 memcpy((char *) pFindData,
2596 (char *) &pSMBr->hdr.Protocol +
2598 sizeof (FILE_UNIX_BASIC_INFO));
2601 cifs_buf_release(pSMB);
2603 goto UnixQPathInfoRetry;
2608 #if 0 /* function unused at present */
2609 int CIFSFindSingle(const int xid, struct cifsTconInfo *tcon,
2610 const char *searchName, FILE_ALL_INFO * findData,
2611 const struct nls_table *nls_codepage)
2613 /* level 257 SMB_ */
2614 TRANSACTION2_FFIRST_REQ *pSMB = NULL;
2615 TRANSACTION2_FFIRST_RSP *pSMBr = NULL;
2619 __u16 params, byte_count;
2621 cFYI(1, ("In FindUnique"));
2623 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2628 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2630 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName, PATH_MAX
2631 /* find define for this maxpathcomponent */
2633 name_len++; /* trailing null */
2635 } else { /* BB improve the check for buffer overruns BB */
2636 name_len = strnlen(searchName, PATH_MAX);
2637 name_len++; /* trailing null */
2638 strncpy(pSMB->FileName, searchName, name_len);
2641 params = 12 + name_len /* includes null */ ;
2642 pSMB->TotalDataCount = 0; /* no EAs */
2643 pSMB->MaxParameterCount = cpu_to_le16(2);
2644 pSMB->MaxDataCount = cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
2645 pSMB->MaxSetupCount = 0;
2649 pSMB->Reserved2 = 0;
2650 pSMB->ParameterOffset = cpu_to_le16(
2651 offsetof(struct smb_com_transaction2_ffirst_req,InformationLevel) - 4);
2652 pSMB->DataCount = 0;
2653 pSMB->DataOffset = 0;
2654 pSMB->SetupCount = 1; /* one byte, no need to le convert */
2655 pSMB->Reserved3 = 0;
2656 pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_FIRST);
2657 byte_count = params + 1 /* pad */ ;
2658 pSMB->TotalParameterCount = cpu_to_le16(params);
2659 pSMB->ParameterCount = pSMB->TotalParameterCount;
2660 pSMB->SearchAttributes =
2661 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
2663 pSMB->SearchCount = cpu_to_le16(16); /* BB increase */
2664 pSMB->SearchFlags = cpu_to_le16(1);
2665 pSMB->InformationLevel = cpu_to_le16(SMB_FIND_FILE_DIRECTORY_INFO);
2666 pSMB->SearchStorageType = 0; /* BB what should we set this to? BB */
2667 pSMB->hdr.smb_buf_length += byte_count;
2668 pSMB->ByteCount = cpu_to_le16(byte_count);
2670 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2671 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2674 cFYI(1, ("Send error in FindFileDirInfo = %d", rc));
2675 } else { /* decode response */
2676 cifs_stats_inc(&tcon->num_ffirst);
2680 cifs_buf_release(pSMB);
2682 goto findUniqueRetry;
2686 #endif /* end unused (temporarily) function */
2688 /* xid, tcon, searchName and codepage are input parms, rest are returned */
2690 CIFSFindFirst(const int xid, struct cifsTconInfo *tcon,
2691 const char *searchName,
2692 const struct nls_table *nls_codepage,
2694 struct cifs_search_info * psrch_inf, int remap, const char dirsep)
2696 /* level 257 SMB_ */
2697 TRANSACTION2_FFIRST_REQ *pSMB = NULL;
2698 TRANSACTION2_FFIRST_RSP *pSMBr = NULL;
2699 T2_FFIRST_RSP_PARMS * parms;
2701 int bytes_returned = 0;
2703 __u16 params, byte_count;
2705 cFYI(1, ("In FindFirst for %s",searchName));
2708 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2713 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2715 cifsConvertToUCS((__le16 *) pSMB->FileName,searchName,
2716 PATH_MAX, nls_codepage, remap);
2717 /* We can not add the asterik earlier in case
2718 it got remapped to 0xF03A as if it were part of the
2719 directory name instead of a wildcard */
2721 pSMB->FileName[name_len] = dirsep;
2722 pSMB->FileName[name_len+1] = 0;
2723 pSMB->FileName[name_len+2] = '*';
2724 pSMB->FileName[name_len+3] = 0;
2725 name_len += 4; /* now the trailing null */
2726 pSMB->FileName[name_len] = 0; /* null terminate just in case */
2727 pSMB->FileName[name_len+1] = 0;
2729 } else { /* BB add check for overrun of SMB buf BB */
2730 name_len = strnlen(searchName, PATH_MAX);
2731 /* BB fix here and in unicode clause above ie
2732 if(name_len > buffersize-header)
2733 free buffer exit; BB */
2734 strncpy(pSMB->FileName, searchName, name_len);
2735 pSMB->FileName[name_len] = dirsep;
2736 pSMB->FileName[name_len+1] = '*';
2737 pSMB->FileName[name_len+2] = 0;
2741 params = 12 + name_len /* includes null */ ;
2742 pSMB->TotalDataCount = 0; /* no EAs */
2743 pSMB->MaxParameterCount = cpu_to_le16(10);
2744 pSMB->MaxDataCount = cpu_to_le16((tcon->ses->server->maxBuf -
2745 MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
2746 pSMB->MaxSetupCount = 0;
2750 pSMB->Reserved2 = 0;
2751 byte_count = params + 1 /* pad */ ;
2752 pSMB->TotalParameterCount = cpu_to_le16(params);
2753 pSMB->ParameterCount = pSMB->TotalParameterCount;
2754 pSMB->ParameterOffset = cpu_to_le16(
2755 offsetof(struct smb_com_transaction2_ffirst_req, SearchAttributes) - 4);
2756 pSMB->DataCount = 0;
2757 pSMB->DataOffset = 0;
2758 pSMB->SetupCount = 1; /* one byte, no need to make endian neutral */
2759 pSMB->Reserved3 = 0;
2760 pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_FIRST);
2761 pSMB->SearchAttributes =
2762 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
2764 pSMB->SearchCount= cpu_to_le16(CIFSMaxBufSize/sizeof(FILE_UNIX_INFO));
2765 pSMB->SearchFlags = cpu_to_le16(CIFS_SEARCH_CLOSE_AT_END |
2766 CIFS_SEARCH_RETURN_RESUME);
2767 pSMB->InformationLevel = cpu_to_le16(psrch_inf->info_level);
2769 /* BB what should we set StorageType to? Does it matter? BB */
2770 pSMB->SearchStorageType = 0;
2771 pSMB->hdr.smb_buf_length += byte_count;
2772 pSMB->ByteCount = cpu_to_le16(byte_count);
2774 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2775 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2776 cifs_stats_inc(&tcon->num_ffirst);
2778 if (rc) {/* BB add logic to retry regular search if Unix search rejected unexpectedly by server */
2779 /* BB Add code to handle unsupported level rc */
2780 cFYI(1, ("Error in FindFirst = %d", rc));
2783 cifs_buf_release(pSMB);
2785 /* BB eventually could optimize out free and realloc of buf */
2788 goto findFirstRetry;
2789 } else { /* decode response */
2790 /* BB remember to free buffer if error BB */
2791 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
2793 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
2794 psrch_inf->unicode = TRUE;
2796 psrch_inf->unicode = FALSE;
2798 psrch_inf->ntwrk_buf_start = (char *)pSMBr;
2799 psrch_inf->srch_entries_start =
2800 (char *) &pSMBr->hdr.Protocol +
2801 le16_to_cpu(pSMBr->t2.DataOffset);
2802 parms = (T2_FFIRST_RSP_PARMS *)((char *) &pSMBr->hdr.Protocol +
2803 le16_to_cpu(pSMBr->t2.ParameterOffset));
2805 if(parms->EndofSearch)
2806 psrch_inf->endOfSearch = TRUE;
2808 psrch_inf->endOfSearch = FALSE;
2810 psrch_inf->entries_in_buffer = le16_to_cpu(parms->SearchCount);
2811 psrch_inf->index_of_last_entry =
2812 psrch_inf->entries_in_buffer;
2813 *pnetfid = parms->SearchHandle;
2815 cifs_buf_release(pSMB);
2822 int CIFSFindNext(const int xid, struct cifsTconInfo *tcon,
2823 __u16 searchHandle, struct cifs_search_info * psrch_inf)
2825 TRANSACTION2_FNEXT_REQ *pSMB = NULL;
2826 TRANSACTION2_FNEXT_RSP *pSMBr = NULL;
2827 T2_FNEXT_RSP_PARMS * parms;
2828 char *response_data;
2830 int bytes_returned, name_len;
2831 __u16 params, byte_count;
2833 cFYI(1, ("In FindNext"));
2835 if(psrch_inf->endOfSearch == TRUE)
2838 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2843 params = 14; /* includes 2 bytes of null string, converted to LE below */
2845 pSMB->TotalDataCount = 0; /* no EAs */
2846 pSMB->MaxParameterCount = cpu_to_le16(8);
2847 pSMB->MaxDataCount =
2848 cpu_to_le16((tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
2849 pSMB->MaxSetupCount = 0;
2853 pSMB->Reserved2 = 0;
2854 pSMB->ParameterOffset = cpu_to_le16(
2855 offsetof(struct smb_com_transaction2_fnext_req,SearchHandle) - 4);
2856 pSMB->DataCount = 0;
2857 pSMB->DataOffset = 0;
2858 pSMB->SetupCount = 1;
2859 pSMB->Reserved3 = 0;
2860 pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_NEXT);
2861 pSMB->SearchHandle = searchHandle; /* always kept as le */
2863 cpu_to_le16(CIFSMaxBufSize / sizeof (FILE_UNIX_INFO));
2864 /* test for Unix extensions */
2865 /* if (tcon->ses->capabilities & CAP_UNIX) {
2866 pSMB->InformationLevel = cpu_to_le16(SMB_FIND_FILE_UNIX);
2867 psrch_inf->info_level = SMB_FIND_FILE_UNIX;
2869 pSMB->InformationLevel =
2870 cpu_to_le16(SMB_FIND_FILE_DIRECTORY_INFO);
2871 psrch_inf->info_level = SMB_FIND_FILE_DIRECTORY_INFO;
2873 pSMB->InformationLevel = cpu_to_le16(psrch_inf->info_level);
2874 pSMB->ResumeKey = psrch_inf->resume_key;
2876 cpu_to_le16(CIFS_SEARCH_CLOSE_AT_END | CIFS_SEARCH_RETURN_RESUME);
2878 name_len = psrch_inf->resume_name_len;
2880 if(name_len < PATH_MAX) {
2881 memcpy(pSMB->ResumeFileName, psrch_inf->presume_name, name_len);
2882 byte_count += name_len;
2883 /* 14 byte parm len above enough for 2 byte null terminator */
2884 pSMB->ResumeFileName[name_len] = 0;
2885 pSMB->ResumeFileName[name_len+1] = 0;
2888 goto FNext2_err_exit;
2890 byte_count = params + 1 /* pad */ ;
2891 pSMB->TotalParameterCount = cpu_to_le16(params);
2892 pSMB->ParameterCount = pSMB->TotalParameterCount;
2893 pSMB->hdr.smb_buf_length += byte_count;
2894 pSMB->ByteCount = cpu_to_le16(byte_count);
2896 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2897 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2898 cifs_stats_inc(&tcon->num_fnext);
2901 psrch_inf->endOfSearch = TRUE;
2902 rc = 0; /* search probably was closed at end of search above */
2904 cFYI(1, ("FindNext returned = %d", rc));
2905 } else { /* decode response */
2906 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
2909 /* BB fixme add lock for file (srch_info) struct here */
2910 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
2911 psrch_inf->unicode = TRUE;
2913 psrch_inf->unicode = FALSE;
2914 response_data = (char *) &pSMBr->hdr.Protocol +
2915 le16_to_cpu(pSMBr->t2.ParameterOffset);
2916 parms = (T2_FNEXT_RSP_PARMS *)response_data;
2917 response_data = (char *)&pSMBr->hdr.Protocol +
2918 le16_to_cpu(pSMBr->t2.DataOffset);
2919 cifs_buf_release(psrch_inf->ntwrk_buf_start);
2920 psrch_inf->srch_entries_start = response_data;
2921 psrch_inf->ntwrk_buf_start = (char *)pSMB;
2922 if(parms->EndofSearch)
2923 psrch_inf->endOfSearch = TRUE;
2925 psrch_inf->endOfSearch = FALSE;
2927 psrch_inf->entries_in_buffer = le16_to_cpu(parms->SearchCount);
2928 psrch_inf->index_of_last_entry +=
2929 psrch_inf->entries_in_buffer;
2930 /* cFYI(1,("fnxt2 entries in buf %d index_of_last %d",psrch_inf->entries_in_buffer,psrch_inf->index_of_last_entry)); */
2932 /* BB fixme add unlock here */
2937 /* BB On error, should we leave previous search buf (and count and
2938 last entry fields) intact or free the previous one? */
2940 /* Note: On -EAGAIN error only caller can retry on handle based calls
2941 since file handle passed in no longer valid */
2944 cifs_buf_release(pSMB);
2950 CIFSFindClose(const int xid, struct cifsTconInfo *tcon, const __u16 searchHandle)
2953 FINDCLOSE_REQ *pSMB = NULL;
2954 CLOSE_RSP *pSMBr = NULL; /* BB removeme BB */
2957 cFYI(1, ("In CIFSSMBFindClose"));
2958 rc = small_smb_init(SMB_COM_FIND_CLOSE2, 1, tcon, (void **)&pSMB);
2960 /* no sense returning error if session restarted
2961 as file handle has been closed */
2967 pSMBr = (CLOSE_RSP *)pSMB; /* BB removeme BB */
2968 pSMB->FileID = searchHandle;
2969 pSMB->ByteCount = 0;
2970 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2971 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2973 cERROR(1, ("Send error in FindClose = %d", rc));
2975 cifs_stats_inc(&tcon->num_fclose);
2976 cifs_small_buf_release(pSMB);
2978 /* Since session is dead, search handle closed on server already */
2985 #ifdef CONFIG_CIFS_EXPERIMENTAL
2987 CIFSGetSrvInodeNumber(const int xid, struct cifsTconInfo *tcon,
2988 const unsigned char *searchName,
2989 __u64 * inode_number,
2990 const struct nls_table *nls_codepage, int remap)
2993 TRANSACTION2_QPI_REQ *pSMB = NULL;
2994 TRANSACTION2_QPI_RSP *pSMBr = NULL;
2995 int name_len, bytes_returned;
2996 __u16 params, byte_count;
2998 cFYI(1,("In GetSrvInodeNum for %s",searchName));
3002 GetInodeNumberRetry:
3003 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3009 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3011 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
3012 PATH_MAX,nls_codepage, remap);
3013 name_len++; /* trailing null */
3015 } else { /* BB improve the check for buffer overruns BB */
3016 name_len = strnlen(searchName, PATH_MAX);
3017 name_len++; /* trailing null */
3018 strncpy(pSMB->FileName, searchName, name_len);
3021 params = 2 /* level */ + 4 /* rsrvd */ + name_len /* incl null */ ;
3022 pSMB->TotalDataCount = 0;
3023 pSMB->MaxParameterCount = cpu_to_le16(2);
3024 /* BB find exact max data count below from sess structure BB */
3025 pSMB->MaxDataCount = cpu_to_le16(4000);
3026 pSMB->MaxSetupCount = 0;
3030 pSMB->Reserved2 = 0;
3031 pSMB->ParameterOffset = cpu_to_le16(offsetof(
3032 struct smb_com_transaction2_qpi_req ,InformationLevel) - 4);
3033 pSMB->DataCount = 0;
3034 pSMB->DataOffset = 0;
3035 pSMB->SetupCount = 1;
3036 pSMB->Reserved3 = 0;
3037 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
3038 byte_count = params + 1 /* pad */ ;
3039 pSMB->TotalParameterCount = cpu_to_le16(params);
3040 pSMB->ParameterCount = pSMB->TotalParameterCount;
3041 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_INTERNAL_INFO);
3042 pSMB->Reserved4 = 0;
3043 pSMB->hdr.smb_buf_length += byte_count;
3044 pSMB->ByteCount = cpu_to_le16(byte_count);
3046 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3047 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3049 cFYI(1, ("error %d in QueryInternalInfo", rc));
3051 /* decode response */
3052 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3053 if (rc || (pSMBr->ByteCount < 2))
3054 /* BB also check enough total bytes returned */
3055 /* If rc should we check for EOPNOSUPP and
3056 disable the srvino flag? or in caller? */
3057 rc = -EIO; /* bad smb */
3059 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3060 __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
3061 struct file_internal_info * pfinfo;
3062 /* BB Do we need a cast or hash here ? */
3064 cFYI(1, ("Illegal size ret in QryIntrnlInf"));
3066 goto GetInodeNumOut;
3068 pfinfo = (struct file_internal_info *)
3069 (data_offset + (char *) &pSMBr->hdr.Protocol);
3070 *inode_number = pfinfo->UniqueId;
3074 cifs_buf_release(pSMB);
3076 goto GetInodeNumberRetry;
3079 #endif /* CIFS_EXPERIMENTAL */
3082 CIFSGetDFSRefer(const int xid, struct cifsSesInfo *ses,
3083 const unsigned char *searchName,
3084 unsigned char **targetUNCs,
3085 unsigned int *number_of_UNC_in_array,
3086 const struct nls_table *nls_codepage, int remap)
3088 /* TRANS2_GET_DFS_REFERRAL */
3089 TRANSACTION2_GET_DFS_REFER_REQ *pSMB = NULL;
3090 TRANSACTION2_GET_DFS_REFER_RSP *pSMBr = NULL;
3091 struct dfs_referral_level_3 * referrals = NULL;
3097 __u16 params, byte_count;
3098 *number_of_UNC_in_array = 0;
3101 cFYI(1, ("In GetDFSRefer the path %s", searchName));
3105 rc = smb_init(SMB_COM_TRANSACTION2, 15, NULL, (void **) &pSMB,
3110 /* server pointer checked in called function,
3111 but should never be null here anyway */
3112 pSMB->hdr.Mid = GetNextMid(ses->server);
3113 pSMB->hdr.Tid = ses->ipc_tid;
3114 pSMB->hdr.Uid = ses->Suid;
3115 if (ses->capabilities & CAP_STATUS32) {
3116 pSMB->hdr.Flags2 |= SMBFLG2_ERR_STATUS;
3118 if (ses->capabilities & CAP_DFS) {
3119 pSMB->hdr.Flags2 |= SMBFLG2_DFS;
3122 if (ses->capabilities & CAP_UNICODE) {
3123 pSMB->hdr.Flags2 |= SMBFLG2_UNICODE;
3125 cifsConvertToUCS((__le16 *) pSMB->RequestFileName,
3126 searchName, PATH_MAX, nls_codepage, remap);
3127 name_len++; /* trailing null */
3129 } else { /* BB improve the check for buffer overruns BB */
3130 name_len = strnlen(searchName, PATH_MAX);
3131 name_len++; /* trailing null */
3132 strncpy(pSMB->RequestFileName, searchName, name_len);
3135 params = 2 /* level */ + name_len /*includes null */ ;
3136 pSMB->TotalDataCount = 0;
3137 pSMB->DataCount = 0;
3138 pSMB->DataOffset = 0;
3139 pSMB->MaxParameterCount = 0;
3140 pSMB->MaxDataCount = cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
3141 pSMB->MaxSetupCount = 0;
3145 pSMB->Reserved2 = 0;
3146 pSMB->ParameterOffset = cpu_to_le16(offsetof(
3147 struct smb_com_transaction2_get_dfs_refer_req, MaxReferralLevel) - 4);
3148 pSMB->SetupCount = 1;
3149 pSMB->Reserved3 = 0;
3150 pSMB->SubCommand = cpu_to_le16(TRANS2_GET_DFS_REFERRAL);
3151 byte_count = params + 3 /* pad */ ;
3152 pSMB->ParameterCount = cpu_to_le16(params);
3153 pSMB->TotalParameterCount = pSMB->ParameterCount;
3154 pSMB->MaxReferralLevel = cpu_to_le16(3);
3155 pSMB->hdr.smb_buf_length += byte_count;
3156 pSMB->ByteCount = cpu_to_le16(byte_count);
3158 rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB,
3159 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3161 cFYI(1, ("Send error in GetDFSRefer = %d", rc));
3162 } else { /* decode response */
3163 /* BB Add logic to parse referrals here */
3164 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3166 if (rc || (pSMBr->ByteCount < 17)) /* BB also check enough total bytes returned */
3167 rc = -EIO; /* bad smb */
3169 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3170 __u16 data_count = le16_to_cpu(pSMBr->t2.DataCount);
3173 ("Decoding GetDFSRefer response. BCC: %d Offset %d",
3174 pSMBr->ByteCount, data_offset));
3176 (struct dfs_referral_level_3 *)
3177 (8 /* sizeof start of data block */ +
3179 (char *) &pSMBr->hdr.Protocol);
3180 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",
3181 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)));
3182 /* BB This field is actually two bytes in from start of
3183 data block so we could do safety check that DataBlock
3184 begins at address of pSMBr->NumberOfReferrals */
3185 *number_of_UNC_in_array = le16_to_cpu(pSMBr->NumberOfReferrals);
3187 /* BB Fix below so can return more than one referral */
3188 if(*number_of_UNC_in_array > 1)
3189 *number_of_UNC_in_array = 1;
3191 /* get the length of the strings describing refs */
3193 for(i=0;i<*number_of_UNC_in_array;i++) {
3194 /* make sure that DfsPathOffset not past end */
3195 __u16 offset = le16_to_cpu(referrals->DfsPathOffset);
3196 if (offset > data_count) {
3197 /* if invalid referral, stop here and do
3198 not try to copy any more */
3199 *number_of_UNC_in_array = i;
3202 temp = ((char *)referrals) + offset;
3204 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
3205 name_len += UniStrnlen((wchar_t *)temp,data_count);
3207 name_len += strnlen(temp,data_count);
3210 /* BB add check that referral pointer does not fall off end PDU */
3213 /* BB add check for name_len bigger than bcc */
3215 kmalloc(name_len+1+ (*number_of_UNC_in_array),GFP_KERNEL);
3216 if(*targetUNCs == NULL) {
3220 /* copy the ref strings */
3222 (struct dfs_referral_level_3 *)
3223 (8 /* sizeof data hdr */ +
3225 (char *) &pSMBr->hdr.Protocol);
3227 for(i=0;i<*number_of_UNC_in_array;i++) {
3228 temp = ((char *)referrals) + le16_to_cpu(referrals->DfsPathOffset);
3229 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
3230 cifs_strfromUCS_le(*targetUNCs,
3231 (wchar_t *) temp, name_len, nls_codepage);
3233 strncpy(*targetUNCs,temp,name_len);
3235 /* BB update target_uncs pointers */
3245 cifs_buf_release(pSMB);
3254 CIFSSMBQFSInfo(const int xid, struct cifsTconInfo *tcon, struct kstatfs *FSData)
3256 /* level 0x103 SMB_QUERY_FILE_SYSTEM_INFO */
3257 TRANSACTION2_QFSI_REQ *pSMB = NULL;
3258 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
3259 FILE_SYSTEM_INFO *response_data;
3261 int bytes_returned = 0;
3262 __u16 params, byte_count;
3264 cFYI(1, ("In QFSInfo"));
3266 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3271 params = 2; /* level */
3272 pSMB->TotalDataCount = 0;
3273 pSMB->MaxParameterCount = cpu_to_le16(2);
3274 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
3275 pSMB->MaxSetupCount = 0;
3279 pSMB->Reserved2 = 0;
3280 byte_count = params + 1 /* pad */ ;
3281 pSMB->TotalParameterCount = cpu_to_le16(params);
3282 pSMB->ParameterCount = pSMB->TotalParameterCount;
3283 pSMB->ParameterOffset = cpu_to_le16(offsetof(
3284 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
3285 pSMB->DataCount = 0;
3286 pSMB->DataOffset = 0;
3287 pSMB->SetupCount = 1;
3288 pSMB->Reserved3 = 0;
3289 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
3290 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_SIZE_INFO);
3291 pSMB->hdr.smb_buf_length += byte_count;
3292 pSMB->ByteCount = cpu_to_le16(byte_count);
3294 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3295 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3297 cERROR(1, ("Send error in QFSInfo = %d", rc));
3298 } else { /* decode response */
3299 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3301 if (rc || (pSMBr->ByteCount < 24)) /* BB alsO CHEck enough total bytes returned */
3302 rc = -EIO; /* bad smb */
3304 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3306 ("Decoding qfsinfo response. BCC: %d Offset %d",
3307 pSMBr->ByteCount, data_offset));
3311 *) (((char *) &pSMBr->hdr.Protocol) +
3314 le32_to_cpu(response_data->BytesPerSector) *
3315 le32_to_cpu(response_data->
3316 SectorsPerAllocationUnit);
3318 le64_to_cpu(response_data->TotalAllocationUnits);
3319 FSData->f_bfree = FSData->f_bavail =
3320 le64_to_cpu(response_data->FreeAllocationUnits);
3322 ("Blocks: %lld Free: %lld Block size %ld",
3323 (unsigned long long)FSData->f_blocks,
3324 (unsigned long long)FSData->f_bfree,
3328 cifs_buf_release(pSMB);
3337 CIFSSMBQFSAttributeInfo(const int xid, struct cifsTconInfo *tcon)
3339 /* level 0x105 SMB_QUERY_FILE_SYSTEM_INFO */
3340 TRANSACTION2_QFSI_REQ *pSMB = NULL;
3341 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
3342 FILE_SYSTEM_ATTRIBUTE_INFO *response_data;
3344 int bytes_returned = 0;
3345 __u16 params, byte_count;
3347 cFYI(1, ("In QFSAttributeInfo"));
3349 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3354 params = 2; /* level */
3355 pSMB->TotalDataCount = 0;
3356 pSMB->MaxParameterCount = cpu_to_le16(2);
3357 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
3358 pSMB->MaxSetupCount = 0;
3362 pSMB->Reserved2 = 0;
3363 byte_count = params + 1 /* pad */ ;
3364 pSMB->TotalParameterCount = cpu_to_le16(params);
3365 pSMB->ParameterCount = pSMB->TotalParameterCount;
3366 pSMB->ParameterOffset = cpu_to_le16(offsetof(
3367 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
3368 pSMB->DataCount = 0;
3369 pSMB->DataOffset = 0;
3370 pSMB->SetupCount = 1;
3371 pSMB->Reserved3 = 0;
3372 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
3373 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_ATTRIBUTE_INFO);
3374 pSMB->hdr.smb_buf_length += byte_count;
3375 pSMB->ByteCount = cpu_to_le16(byte_count);
3377 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3378 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3380 cERROR(1, ("Send error in QFSAttributeInfo = %d", rc));
3381 } else { /* decode response */
3382 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3384 if (rc || (pSMBr->ByteCount < 13)) { /* BB also check enough bytes returned */
3385 rc = -EIO; /* bad smb */
3387 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3389 (FILE_SYSTEM_ATTRIBUTE_INFO
3390 *) (((char *) &pSMBr->hdr.Protocol) +
3392 memcpy(&tcon->fsAttrInfo, response_data,
3393 sizeof (FILE_SYSTEM_ATTRIBUTE_INFO));
3396 cifs_buf_release(pSMB);
3399 goto QFSAttributeRetry;
3405 CIFSSMBQFSDeviceInfo(const int xid, struct cifsTconInfo *tcon)
3407 /* level 0x104 SMB_QUERY_FILE_SYSTEM_INFO */
3408 TRANSACTION2_QFSI_REQ *pSMB = NULL;
3409 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
3410 FILE_SYSTEM_DEVICE_INFO *response_data;
3412 int bytes_returned = 0;
3413 __u16 params, byte_count;
3415 cFYI(1, ("In QFSDeviceInfo"));
3417 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3422 params = 2; /* level */
3423 pSMB->TotalDataCount = 0;
3424 pSMB->MaxParameterCount = cpu_to_le16(2);
3425 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
3426 pSMB->MaxSetupCount = 0;
3430 pSMB->Reserved2 = 0;
3431 byte_count = params + 1 /* pad */ ;
3432 pSMB->TotalParameterCount = cpu_to_le16(params);
3433 pSMB->ParameterCount = pSMB->TotalParameterCount;
3434 pSMB->ParameterOffset = cpu_to_le16(offsetof(
3435 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
3437 pSMB->DataCount = 0;
3438 pSMB->DataOffset = 0;
3439 pSMB->SetupCount = 1;
3440 pSMB->Reserved3 = 0;
3441 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
3442 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_DEVICE_INFO);
3443 pSMB->hdr.smb_buf_length += byte_count;
3444 pSMB->ByteCount = cpu_to_le16(byte_count);
3446 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3447 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3449 cFYI(1, ("Send error in QFSDeviceInfo = %d", rc));
3450 } else { /* decode response */
3451 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3453 if (rc || (pSMBr->ByteCount < sizeof (FILE_SYSTEM_DEVICE_INFO)))
3454 rc = -EIO; /* bad smb */
3456 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3458 (FILE_SYSTEM_DEVICE_INFO *)
3459 (((char *) &pSMBr->hdr.Protocol) +
3461 memcpy(&tcon->fsDevInfo, response_data,
3462 sizeof (FILE_SYSTEM_DEVICE_INFO));
3465 cifs_buf_release(pSMB);
3468 goto QFSDeviceRetry;
3474 CIFSSMBQFSUnixInfo(const int xid, struct cifsTconInfo *tcon)
3476 /* level 0x200 SMB_QUERY_CIFS_UNIX_INFO */
3477 TRANSACTION2_QFSI_REQ *pSMB = NULL;
3478 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
3479 FILE_SYSTEM_UNIX_INFO *response_data;
3481 int bytes_returned = 0;
3482 __u16 params, byte_count;
3484 cFYI(1, ("In QFSUnixInfo"));
3486 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3491 params = 2; /* level */
3492 pSMB->TotalDataCount = 0;
3493 pSMB->DataCount = 0;
3494 pSMB->DataOffset = 0;
3495 pSMB->MaxParameterCount = cpu_to_le16(2);
3496 pSMB->MaxDataCount = cpu_to_le16(100); /* BB find exact max SMB PDU from sess structure BB */
3497 pSMB->MaxSetupCount = 0;
3501 pSMB->Reserved2 = 0;
3502 byte_count = params + 1 /* pad */ ;
3503 pSMB->ParameterCount = cpu_to_le16(params);
3504 pSMB->TotalParameterCount = pSMB->ParameterCount;
3505 pSMB->ParameterOffset = cpu_to_le16(offsetof(struct
3506 smb_com_transaction2_qfsi_req, InformationLevel) - 4);
3507 pSMB->SetupCount = 1;
3508 pSMB->Reserved3 = 0;
3509 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
3510 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_CIFS_UNIX_INFO);
3511 pSMB->hdr.smb_buf_length += byte_count;
3512 pSMB->ByteCount = cpu_to_le16(byte_count);
3514 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3515 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3517 cERROR(1, ("Send error in QFSUnixInfo = %d", rc));
3518 } else { /* decode response */
3519 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3521 if (rc || (pSMBr->ByteCount < 13)) {
3522 rc = -EIO; /* bad smb */
3524 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3526 (FILE_SYSTEM_UNIX_INFO
3527 *) (((char *) &pSMBr->hdr.Protocol) +
3529 memcpy(&tcon->fsUnixInfo, response_data,
3530 sizeof (FILE_SYSTEM_UNIX_INFO));
3533 cifs_buf_release(pSMB);
3543 CIFSSMBSetFSUnixInfo(const int xid, struct cifsTconInfo *tcon, __u64 cap)
3545 /* level 0x200 SMB_SET_CIFS_UNIX_INFO */
3546 TRANSACTION2_SETFSI_REQ *pSMB = NULL;
3547 TRANSACTION2_SETFSI_RSP *pSMBr = NULL;
3549 int bytes_returned = 0;
3550 __u16 params, param_offset, offset, byte_count;
3552 cFYI(1, ("In SETFSUnixInfo"));
3554 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3559 params = 4; /* 2 bytes zero followed by info level. */
3560 pSMB->MaxSetupCount = 0;
3564 pSMB->Reserved2 = 0;
3565 param_offset = offsetof(struct smb_com_transaction2_setfsi_req, FileNum) - 4;
3566 offset = param_offset + params;
3568 pSMB->MaxParameterCount = cpu_to_le16(4);
3569 pSMB->MaxDataCount = cpu_to_le16(100); /* BB find exact max SMB PDU from sess structure BB */
3570 pSMB->SetupCount = 1;
3571 pSMB->Reserved3 = 0;
3572 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FS_INFORMATION);
3573 byte_count = 1 /* pad */ + params + 12;
3575 pSMB->DataCount = cpu_to_le16(12);
3576 pSMB->ParameterCount = cpu_to_le16(params);
3577 pSMB->TotalDataCount = pSMB->DataCount;
3578 pSMB->TotalParameterCount = pSMB->ParameterCount;
3579 pSMB->ParameterOffset = cpu_to_le16(param_offset);
3580 pSMB->DataOffset = cpu_to_le16(offset);
3584 pSMB->InformationLevel = cpu_to_le16(SMB_SET_CIFS_UNIX_INFO);
3587 pSMB->ClientUnixMajor = cpu_to_le16(CIFS_UNIX_MAJOR_VERSION);
3588 pSMB->ClientUnixMinor = cpu_to_le16(CIFS_UNIX_MINOR_VERSION);
3589 pSMB->ClientUnixCap = cpu_to_le64(cap);
3591 pSMB->hdr.smb_buf_length += byte_count;
3592 pSMB->ByteCount = cpu_to_le16(byte_count);
3594 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3595 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3597 cERROR(1, ("Send error in SETFSUnixInfo = %d", rc));
3598 } else { /* decode response */
3599 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3601 rc = -EIO; /* bad smb */
3604 cifs_buf_release(pSMB);
3607 goto SETFSUnixRetry;
3615 CIFSSMBQFSPosixInfo(const int xid, struct cifsTconInfo *tcon,
3616 struct kstatfs *FSData)
3618 /* level 0x201 SMB_QUERY_CIFS_POSIX_INFO */
3619 TRANSACTION2_QFSI_REQ *pSMB = NULL;
3620 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
3621 FILE_SYSTEM_POSIX_INFO *response_data;
3623 int bytes_returned = 0;
3624 __u16 params, byte_count;
3626 cFYI(1, ("In QFSPosixInfo"));
3628 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3633 params = 2; /* level */
3634 pSMB->TotalDataCount = 0;
3635 pSMB->DataCount = 0;
3636 pSMB->DataOffset = 0;
3637 pSMB->MaxParameterCount = cpu_to_le16(2);
3638 pSMB->MaxDataCount = cpu_to_le16(100); /* BB find exact max SMB PDU from sess structure BB */
3639 pSMB->MaxSetupCount = 0;
3643 pSMB->Reserved2 = 0;
3644 byte_count = params + 1 /* pad */ ;
3645 pSMB->ParameterCount = cpu_to_le16(params);
3646 pSMB->TotalParameterCount = pSMB->ParameterCount;
3647 pSMB->ParameterOffset = cpu_to_le16(offsetof(struct
3648 smb_com_transaction2_qfsi_req, InformationLevel) - 4);
3649 pSMB->SetupCount = 1;
3650 pSMB->Reserved3 = 0;
3651 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
3652 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_POSIX_FS_INFO);
3653 pSMB->hdr.smb_buf_length += byte_count;
3654 pSMB->ByteCount = cpu_to_le16(byte_count);
3656 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3657 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3659 cFYI(1, ("Send error in QFSUnixInfo = %d", rc));
3660 } else { /* decode response */
3661 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3663 if (rc || (pSMBr->ByteCount < 13)) {
3664 rc = -EIO; /* bad smb */
3666 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3668 (FILE_SYSTEM_POSIX_INFO
3669 *) (((char *) &pSMBr->hdr.Protocol) +
3672 le32_to_cpu(response_data->BlockSize);
3674 le64_to_cpu(response_data->TotalBlocks);
3676 le64_to_cpu(response_data->BlocksAvail);
3677 if(response_data->UserBlocksAvail == -1) {
3678 FSData->f_bavail = FSData->f_bfree;
3681 le64_to_cpu(response_data->UserBlocksAvail);
3683 if(response_data->TotalFileNodes != -1)
3685 le64_to_cpu(response_data->TotalFileNodes);
3686 if(response_data->FreeFileNodes != -1)
3688 le64_to_cpu(response_data->FreeFileNodes);
3691 cifs_buf_release(pSMB);
3700 /* We can not use write of zero bytes trick to
3701 set file size due to need for large file support. Also note that
3702 this SetPathInfo is preferred to SetFileInfo based method in next
3703 routine which is only needed to work around a sharing violation bug
3704 in Samba which this routine can run into */
3707 CIFSSMBSetEOF(const int xid, struct cifsTconInfo *tcon, const char *fileName,
3708 __u64 size, int SetAllocation,
3709 const struct nls_table *nls_codepage, int remap)
3711 struct smb_com_transaction2_spi_req *pSMB = NULL;
3712 struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
3713 struct file_end_of_file_info *parm_data;
3716 int bytes_returned = 0;
3717 __u16 params, byte_count, data_count, param_offset, offset;
3719 cFYI(1, ("In SetEOF"));
3721 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3726 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3728 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
3729 PATH_MAX, nls_codepage, remap);
3730 name_len++; /* trailing null */
3732 } else { /* BB improve the check for buffer overruns BB */
3733 name_len = strnlen(fileName, PATH_MAX);
3734 name_len++; /* trailing null */
3735 strncpy(pSMB->FileName, fileName, name_len);
3737 params = 6 + name_len;
3738 data_count = sizeof (struct file_end_of_file_info);
3739 pSMB->MaxParameterCount = cpu_to_le16(2);
3740 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB size from sess */
3741 pSMB->MaxSetupCount = 0;
3745 pSMB->Reserved2 = 0;
3746 param_offset = offsetof(struct smb_com_transaction2_spi_req,
3747 InformationLevel) - 4;
3748 offset = param_offset + params;
3750 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
3751 pSMB->InformationLevel =
3752 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2);
3754 pSMB->InformationLevel =
3755 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO);
3756 } else /* Set File Size */ {
3757 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
3758 pSMB->InformationLevel =
3759 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO2);
3761 pSMB->InformationLevel =
3762 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO);
3766 (struct file_end_of_file_info *) (((char *) &pSMB->hdr.Protocol) +
3768 pSMB->ParameterOffset = cpu_to_le16(param_offset);
3769 pSMB->DataOffset = cpu_to_le16(offset);
3770 pSMB->SetupCount = 1;
3771 pSMB->Reserved3 = 0;
3772 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
3773 byte_count = 3 /* pad */ + params + data_count;
3774 pSMB->DataCount = cpu_to_le16(data_count);
3775 pSMB->TotalDataCount = pSMB->DataCount;
3776 pSMB->ParameterCount = cpu_to_le16(params);
3777 pSMB->TotalParameterCount = pSMB->ParameterCount;
3778 pSMB->Reserved4 = 0;
3779 pSMB->hdr.smb_buf_length += byte_count;
3780 parm_data->FileSize = cpu_to_le64(size);
3781 pSMB->ByteCount = cpu_to_le16(byte_count);
3782 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3783 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3785 cFYI(1, ("SetPathInfo (file size) returned %d", rc));
3788 cifs_buf_release(pSMB);
3797 CIFSSMBSetFileSize(const int xid, struct cifsTconInfo *tcon, __u64 size,
3798 __u16 fid, __u32 pid_of_opener, int SetAllocation)
3800 struct smb_com_transaction2_sfi_req *pSMB = NULL;
3801 struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
3803 struct file_end_of_file_info *parm_data;
3805 int bytes_returned = 0;
3806 __u16 params, param_offset, offset, byte_count, count;
3808 cFYI(1, ("SetFileSize (via SetFileInfo) %lld",
3810 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
3815 pSMBr = (struct smb_com_transaction2_sfi_rsp *)pSMB;
3817 pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
3818 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));
3821 pSMB->MaxSetupCount = 0;
3825 pSMB->Reserved2 = 0;
3826 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
3827 offset = param_offset + params;
3829 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
3831 count = sizeof(struct file_end_of_file_info);
3832 pSMB->MaxParameterCount = cpu_to_le16(2);
3833 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB PDU from sess */
3834 pSMB->SetupCount = 1;
3835 pSMB->Reserved3 = 0;
3836 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
3837 byte_count = 3 /* pad */ + params + count;
3838 pSMB->DataCount = cpu_to_le16(count);
3839 pSMB->ParameterCount = cpu_to_le16(params);
3840 pSMB->TotalDataCount = pSMB->DataCount;
3841 pSMB->TotalParameterCount = pSMB->ParameterCount;
3842 pSMB->ParameterOffset = cpu_to_le16(param_offset);
3844 (struct file_end_of_file_info *) (((char *) &pSMB->hdr.Protocol) +
3846 pSMB->DataOffset = cpu_to_le16(offset);
3847 parm_data->FileSize = cpu_to_le64(size);
3850 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
3851 pSMB->InformationLevel =
3852 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2);
3854 pSMB->InformationLevel =
3855 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO);
3856 } else /* Set File Size */ {
3857 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
3858 pSMB->InformationLevel =
3859 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO2);
3861 pSMB->InformationLevel =
3862 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO);
3864 pSMB->Reserved4 = 0;
3865 pSMB->hdr.smb_buf_length += byte_count;
3866 pSMB->ByteCount = cpu_to_le16(byte_count);
3867 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3868 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3871 ("Send error in SetFileInfo (SetFileSize) = %d",
3876 cifs_small_buf_release(pSMB);
3878 /* Note: On -EAGAIN error only caller can retry on handle based calls
3879 since file handle passed in no longer valid */
3884 /* Some legacy servers such as NT4 require that the file times be set on
3885 an open handle, rather than by pathname - this is awkward due to
3886 potential access conflicts on the open, but it is unavoidable for these
3887 old servers since the only other choice is to go from 100 nanosecond DCE
3888 time and resort to the original setpathinfo level which takes the ancient
3889 DOS time format with 2 second granularity */
3891 CIFSSMBSetFileTimes(const int xid, struct cifsTconInfo *tcon, const FILE_BASIC_INFO * data,
3894 struct smb_com_transaction2_sfi_req *pSMB = NULL;
3895 struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
3898 int bytes_returned = 0;
3899 __u16 params, param_offset, offset, byte_count, count;
3901 cFYI(1, ("Set Times (via SetFileInfo)"));
3902 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
3907 pSMBr = (struct smb_com_transaction2_sfi_rsp *)pSMB;
3909 /* At this point there is no need to override the current pid
3910 with the pid of the opener, but that could change if we someday
3911 use an existing handle (rather than opening one on the fly) */
3912 /* pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
3913 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));*/
3916 pSMB->MaxSetupCount = 0;
3920 pSMB->Reserved2 = 0;
3921 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
3922 offset = param_offset + params;
3924 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
3926 count = sizeof (FILE_BASIC_INFO);
3927 pSMB->MaxParameterCount = cpu_to_le16(2);
3928 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB PDU from sess */
3929 pSMB->SetupCount = 1;
3930 pSMB->Reserved3 = 0;
3931 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
3932 byte_count = 3 /* pad */ + params + count;
3933 pSMB->DataCount = cpu_to_le16(count);
3934 pSMB->ParameterCount = cpu_to_le16(params);
3935 pSMB->TotalDataCount = pSMB->DataCount;
3936 pSMB->TotalParameterCount = pSMB->ParameterCount;
3937 pSMB->ParameterOffset = cpu_to_le16(param_offset);
3938 pSMB->DataOffset = cpu_to_le16(offset);
3940 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
3941 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO2);
3943 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO);
3944 pSMB->Reserved4 = 0;
3945 pSMB->hdr.smb_buf_length += byte_count;
3946 pSMB->ByteCount = cpu_to_le16(byte_count);
3947 memcpy(data_offset,data,sizeof(FILE_BASIC_INFO));
3948 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3949 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3951 cFYI(1,("Send error in Set Time (SetFileInfo) = %d",rc));
3954 cifs_small_buf_release(pSMB);
3956 /* Note: On -EAGAIN error only caller can retry on handle based calls
3957 since file handle passed in no longer valid */
3964 CIFSSMBSetTimes(const int xid, struct cifsTconInfo *tcon, const char *fileName,
3965 const FILE_BASIC_INFO * data,
3966 const struct nls_table *nls_codepage, int remap)
3968 TRANSACTION2_SPI_REQ *pSMB = NULL;
3969 TRANSACTION2_SPI_RSP *pSMBr = NULL;
3972 int bytes_returned = 0;
3974 __u16 params, param_offset, offset, byte_count, count;
3976 cFYI(1, ("In SetTimes"));
3979 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3984 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3986 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
3987 PATH_MAX, nls_codepage, remap);
3988 name_len++; /* trailing null */
3990 } else { /* BB improve the check for buffer overruns BB */
3991 name_len = strnlen(fileName, PATH_MAX);
3992 name_len++; /* trailing null */
3993 strncpy(pSMB->FileName, fileName, name_len);
3996 params = 6 + name_len;
3997 count = sizeof (FILE_BASIC_INFO);
3998 pSMB->MaxParameterCount = cpu_to_le16(2);
3999 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
4000 pSMB->MaxSetupCount = 0;
4004 pSMB->Reserved2 = 0;
4005 param_offset = offsetof(struct smb_com_transaction2_spi_req,
4006 InformationLevel) - 4;
4007 offset = param_offset + params;
4008 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
4009 pSMB->ParameterOffset = cpu_to_le16(param_offset);
4010 pSMB->DataOffset = cpu_to_le16(offset);
4011 pSMB->SetupCount = 1;
4012 pSMB->Reserved3 = 0;
4013 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
4014 byte_count = 3 /* pad */ + params + count;
4016 pSMB->DataCount = cpu_to_le16(count);
4017 pSMB->ParameterCount = cpu_to_le16(params);
4018 pSMB->TotalDataCount = pSMB->DataCount;
4019 pSMB->TotalParameterCount = pSMB->ParameterCount;
4020 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
4021 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO2);
4023 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO);
4024 pSMB->Reserved4 = 0;
4025 pSMB->hdr.smb_buf_length += byte_count;
4026 memcpy(data_offset, data, sizeof (FILE_BASIC_INFO));
4027 pSMB->ByteCount = cpu_to_le16(byte_count);
4028 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4029 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4031 cFYI(1, ("SetPathInfo (times) returned %d", rc));
4034 cifs_buf_release(pSMB);
4042 /* Can not be used to set time stamps yet (due to old DOS time format) */
4043 /* Can be used to set attributes */
4044 #if 0 /* Possibly not needed - since it turns out that strangely NT4 has a bug
4045 handling it anyway and NT4 was what we thought it would be needed for
4046 Do not delete it until we prove whether needed for Win9x though */
4048 CIFSSMBSetAttrLegacy(int xid, struct cifsTconInfo *tcon, char *fileName,
4049 __u16 dos_attrs, const struct nls_table *nls_codepage)
4051 SETATTR_REQ *pSMB = NULL;
4052 SETATTR_RSP *pSMBr = NULL;
4057 cFYI(1, ("In SetAttrLegacy"));
4060 rc = smb_init(SMB_COM_SETATTR, 8, tcon, (void **) &pSMB,
4065 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4067 ConvertToUCS((__le16 *) pSMB->fileName, fileName,
4068 PATH_MAX, nls_codepage);
4069 name_len++; /* trailing null */
4071 } else { /* BB improve the check for buffer overruns BB */
4072 name_len = strnlen(fileName, PATH_MAX);
4073 name_len++; /* trailing null */
4074 strncpy(pSMB->fileName, fileName, name_len);
4076 pSMB->attr = cpu_to_le16(dos_attrs);
4077 pSMB->BufferFormat = 0x04;
4078 pSMB->hdr.smb_buf_length += name_len + 1;
4079 pSMB->ByteCount = cpu_to_le16(name_len + 1);
4080 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4081 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4083 cFYI(1, ("Error in LegacySetAttr = %d", rc));
4086 cifs_buf_release(pSMB);
4089 goto SetAttrLgcyRetry;
4093 #endif /* temporarily unneeded SetAttr legacy function */
4096 CIFSSMBUnixSetPerms(const int xid, struct cifsTconInfo *tcon,
4097 char *fileName, __u64 mode, __u64 uid, __u64 gid,
4098 dev_t device, const struct nls_table *nls_codepage,
4101 TRANSACTION2_SPI_REQ *pSMB = NULL;
4102 TRANSACTION2_SPI_RSP *pSMBr = NULL;
4105 int bytes_returned = 0;
4106 FILE_UNIX_BASIC_INFO *data_offset;
4107 __u16 params, param_offset, offset, count, byte_count;
4109 cFYI(1, ("In SetUID/GID/Mode"));
4111 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4116 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4118 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
4119 PATH_MAX, nls_codepage, remap);
4120 name_len++; /* trailing null */
4122 } else { /* BB improve the check for buffer overruns BB */
4123 name_len = strnlen(fileName, PATH_MAX);
4124 name_len++; /* trailing null */
4125 strncpy(pSMB->FileName, fileName, name_len);
4128 params = 6 + name_len;
4129 count = sizeof (FILE_UNIX_BASIC_INFO);
4130 pSMB->MaxParameterCount = cpu_to_le16(2);
4131 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
4132 pSMB->MaxSetupCount = 0;
4136 pSMB->Reserved2 = 0;
4137 param_offset = offsetof(struct smb_com_transaction2_spi_req,
4138 InformationLevel) - 4;
4139 offset = param_offset + params;
4141 (FILE_UNIX_BASIC_INFO *) ((char *) &pSMB->hdr.Protocol +
4143 memset(data_offset, 0, count);
4144 pSMB->DataOffset = cpu_to_le16(offset);
4145 pSMB->ParameterOffset = cpu_to_le16(param_offset);
4146 pSMB->SetupCount = 1;
4147 pSMB->Reserved3 = 0;
4148 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
4149 byte_count = 3 /* pad */ + params + count;
4150 pSMB->ParameterCount = cpu_to_le16(params);
4151 pSMB->DataCount = cpu_to_le16(count);
4152 pSMB->TotalParameterCount = pSMB->ParameterCount;
4153 pSMB->TotalDataCount = pSMB->DataCount;
4154 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_BASIC);
4155 pSMB->Reserved4 = 0;
4156 pSMB->hdr.smb_buf_length += byte_count;
4157 data_offset->Uid = cpu_to_le64(uid);
4158 data_offset->Gid = cpu_to_le64(gid);
4159 /* better to leave device as zero when it is */
4160 data_offset->DevMajor = cpu_to_le64(MAJOR(device));
4161 data_offset->DevMinor = cpu_to_le64(MINOR(device));
4162 data_offset->Permissions = cpu_to_le64(mode);
4165 data_offset->Type = cpu_to_le32(UNIX_FILE);
4166 else if(S_ISDIR(mode))
4167 data_offset->Type = cpu_to_le32(UNIX_DIR);
4168 else if(S_ISLNK(mode))
4169 data_offset->Type = cpu_to_le32(UNIX_SYMLINK);
4170 else if(S_ISCHR(mode))
4171 data_offset->Type = cpu_to_le32(UNIX_CHARDEV);
4172 else if(S_ISBLK(mode))
4173 data_offset->Type = cpu_to_le32(UNIX_BLOCKDEV);
4174 else if(S_ISFIFO(mode))
4175 data_offset->Type = cpu_to_le32(UNIX_FIFO);
4176 else if(S_ISSOCK(mode))
4177 data_offset->Type = cpu_to_le32(UNIX_SOCKET);
4180 pSMB->ByteCount = cpu_to_le16(byte_count);
4181 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4182 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4184 cFYI(1, ("SetPathInfo (perms) returned %d", rc));
4188 cifs_buf_release(pSMB);
4194 int CIFSSMBNotify(const int xid, struct cifsTconInfo *tcon,
4195 const int notify_subdirs, const __u16 netfid,
4196 __u32 filter, struct file * pfile, int multishot,
4197 const struct nls_table *nls_codepage)
4200 struct smb_com_transaction_change_notify_req * pSMB = NULL;
4201 struct smb_com_transaction_change_notify_rsp * pSMBr = NULL;
4202 struct dir_notify_req *dnotify_req;
4205 cFYI(1, ("In CIFSSMBNotify for file handle %d",(int)netfid));
4206 rc = smb_init(SMB_COM_NT_TRANSACT, 23, tcon, (void **) &pSMB,
4211 pSMB->TotalParameterCount = 0 ;
4212 pSMB->TotalDataCount = 0;
4213 pSMB->MaxParameterCount = cpu_to_le32(2);
4214 /* BB find exact data count max from sess structure BB */
4215 pSMB->MaxDataCount = 0; /* same in little endian or be */
4216 pSMB->MaxSetupCount = 4;
4218 pSMB->ParameterOffset = 0;
4219 pSMB->DataCount = 0;
4220 pSMB->DataOffset = 0;
4221 pSMB->SetupCount = 4; /* single byte does not need le conversion */
4222 pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_NOTIFY_CHANGE);
4223 pSMB->ParameterCount = pSMB->TotalParameterCount;
4225 pSMB->WatchTree = 1; /* one byte - no le conversion needed */
4226 pSMB->Reserved2 = 0;
4227 pSMB->CompletionFilter = cpu_to_le32(filter);
4228 pSMB->Fid = netfid; /* file handle always le */
4229 pSMB->ByteCount = 0;
4231 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4232 (struct smb_hdr *) pSMBr, &bytes_returned, -1);
4234 cFYI(1, ("Error in Notify = %d", rc));
4236 /* Add file to outstanding requests */
4237 dnotify_req = (struct dir_notify_req *) kmalloc(
4238 sizeof(struct dir_notify_req), GFP_KERNEL);
4239 dnotify_req->Pid = pSMB->hdr.Pid;
4240 dnotify_req->PidHigh = pSMB->hdr.PidHigh;
4241 dnotify_req->Mid = pSMB->hdr.Mid;
4242 dnotify_req->Tid = pSMB->hdr.Tid;
4243 dnotify_req->Uid = pSMB->hdr.Uid;
4244 dnotify_req->netfid = netfid;
4245 dnotify_req->pfile = pfile;
4246 dnotify_req->filter = filter;
4247 dnotify_req->multishot = multishot;
4248 spin_lock(&GlobalMid_Lock);
4249 list_add_tail(&dnotify_req->lhead, &GlobalDnotifyReqList);
4250 spin_unlock(&GlobalMid_Lock);
4252 cifs_buf_release(pSMB);
4255 #ifdef CONFIG_CIFS_XATTR
4257 CIFSSMBQAllEAs(const int xid, struct cifsTconInfo *tcon,
4258 const unsigned char *searchName,
4259 char * EAData, size_t buf_size,
4260 const struct nls_table *nls_codepage, int remap)
4262 /* BB assumes one setup word */
4263 TRANSACTION2_QPI_REQ *pSMB = NULL;
4264 TRANSACTION2_QPI_RSP *pSMBr = NULL;
4268 struct fea * temp_fea;
4270 __u16 params, byte_count;
4272 cFYI(1, ("In Query All EAs path %s", searchName));
4274 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4279 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4281 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
4282 PATH_MAX, nls_codepage, remap);
4283 name_len++; /* trailing null */
4285 } else { /* BB improve the check for buffer overruns BB */
4286 name_len = strnlen(searchName, PATH_MAX);
4287 name_len++; /* trailing null */
4288 strncpy(pSMB->FileName, searchName, name_len);
4291 params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */ ;
4292 pSMB->TotalDataCount = 0;
4293 pSMB->MaxParameterCount = cpu_to_le16(2);
4294 pSMB->MaxDataCount = cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
4295 pSMB->MaxSetupCount = 0;
4299 pSMB->Reserved2 = 0;
4300 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4301 struct smb_com_transaction2_qpi_req ,InformationLevel) - 4);
4302 pSMB->DataCount = 0;
4303 pSMB->DataOffset = 0;
4304 pSMB->SetupCount = 1;
4305 pSMB->Reserved3 = 0;
4306 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
4307 byte_count = params + 1 /* pad */ ;
4308 pSMB->TotalParameterCount = cpu_to_le16(params);
4309 pSMB->ParameterCount = pSMB->TotalParameterCount;
4310 pSMB->InformationLevel = cpu_to_le16(SMB_INFO_QUERY_ALL_EAS);
4311 pSMB->Reserved4 = 0;
4312 pSMB->hdr.smb_buf_length += byte_count;
4313 pSMB->ByteCount = cpu_to_le16(byte_count);
4315 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4316 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4318 cFYI(1, ("Send error in QueryAllEAs = %d", rc));
4319 } else { /* decode response */
4320 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4322 /* BB also check enough total bytes returned */
4323 /* BB we need to improve the validity checking
4324 of these trans2 responses */
4325 if (rc || (pSMBr->ByteCount < 4))
4326 rc = -EIO; /* bad smb */
4327 /* else if (pFindData){
4328 memcpy((char *) pFindData,
4329 (char *) &pSMBr->hdr.Protocol +
4332 /* check that length of list is not more than bcc */
4333 /* check that each entry does not go beyond length
4335 /* check that each element of each entry does not
4336 go beyond end of list */
4337 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4338 struct fealist * ea_response_data;
4340 /* validate_trans2_offsets() */
4341 /* BB to check if(start of smb + data_offset > &bcc+ bcc)*/
4342 ea_response_data = (struct fealist *)
4343 (((char *) &pSMBr->hdr.Protocol) +
4345 name_len = le32_to_cpu(ea_response_data->list_len);
4346 cFYI(1,("ea length %d", name_len));
4348 /* returned EA size zeroed at top of function */
4349 cFYI(1,("empty EA list returned from server"));
4351 /* account for ea list len */
4353 temp_fea = ea_response_data->list;
4354 temp_ptr = (char *)temp_fea;
4355 while(name_len > 0) {
4359 rc += temp_fea->name_len;
4360 /* account for prefix user. and trailing null */
4362 if(rc<(int)buf_size) {
4363 memcpy(EAData,"user.",5);
4365 memcpy(EAData,temp_ptr,temp_fea->name_len);
4366 EAData+=temp_fea->name_len;
4367 /* null terminate name */
4369 EAData = EAData + 1;
4370 } else if(buf_size == 0) {
4371 /* skip copy - calc size only */
4373 /* stop before overrun buffer */
4377 name_len -= temp_fea->name_len;
4378 temp_ptr += temp_fea->name_len;
4379 /* account for trailing null */
4382 value_len = le16_to_cpu(temp_fea->value_len);
4383 name_len -= value_len;
4384 temp_ptr += value_len;
4385 /* BB check that temp_ptr is still within smb BB*/
4386 /* no trailing null to account for in value len */
4387 /* go on to next EA */
4388 temp_fea = (struct fea *)temp_ptr;
4394 cifs_buf_release(pSMB);
4401 ssize_t CIFSSMBQueryEA(const int xid,struct cifsTconInfo * tcon,
4402 const unsigned char * searchName,const unsigned char * ea_name,
4403 unsigned char * ea_value, size_t buf_size,
4404 const struct nls_table *nls_codepage, int remap)
4406 TRANSACTION2_QPI_REQ *pSMB = NULL;
4407 TRANSACTION2_QPI_RSP *pSMBr = NULL;
4411 struct fea * temp_fea;
4413 __u16 params, byte_count;
4415 cFYI(1, ("In Query EA path %s", searchName));
4417 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4422 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4424 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
4425 PATH_MAX, nls_codepage, remap);
4426 name_len++; /* trailing null */
4428 } else { /* BB improve the check for buffer overruns BB */
4429 name_len = strnlen(searchName, PATH_MAX);
4430 name_len++; /* trailing null */
4431 strncpy(pSMB->FileName, searchName, name_len);
4434 params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */ ;
4435 pSMB->TotalDataCount = 0;
4436 pSMB->MaxParameterCount = cpu_to_le16(2);
4437 pSMB->MaxDataCount = cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
4438 pSMB->MaxSetupCount = 0;
4442 pSMB->Reserved2 = 0;
4443 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4444 struct smb_com_transaction2_qpi_req ,InformationLevel) - 4);
4445 pSMB->DataCount = 0;
4446 pSMB->DataOffset = 0;
4447 pSMB->SetupCount = 1;
4448 pSMB->Reserved3 = 0;
4449 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
4450 byte_count = params + 1 /* pad */ ;
4451 pSMB->TotalParameterCount = cpu_to_le16(params);
4452 pSMB->ParameterCount = pSMB->TotalParameterCount;
4453 pSMB->InformationLevel = cpu_to_le16(SMB_INFO_QUERY_ALL_EAS);
4454 pSMB->Reserved4 = 0;
4455 pSMB->hdr.smb_buf_length += byte_count;
4456 pSMB->ByteCount = cpu_to_le16(byte_count);
4458 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4459 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4461 cFYI(1, ("Send error in Query EA = %d", rc));
4462 } else { /* decode response */
4463 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4465 /* BB also check enough total bytes returned */
4466 /* BB we need to improve the validity checking
4467 of these trans2 responses */
4468 if (rc || (pSMBr->ByteCount < 4))
4469 rc = -EIO; /* bad smb */
4470 /* else if (pFindData){
4471 memcpy((char *) pFindData,
4472 (char *) &pSMBr->hdr.Protocol +
4475 /* check that length of list is not more than bcc */
4476 /* check that each entry does not go beyond length
4478 /* check that each element of each entry does not
4479 go beyond end of list */
4480 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4481 struct fealist * ea_response_data;
4483 /* validate_trans2_offsets() */
4484 /* BB to check if(start of smb + data_offset > &bcc+ bcc)*/
4485 ea_response_data = (struct fealist *)
4486 (((char *) &pSMBr->hdr.Protocol) +
4488 name_len = le32_to_cpu(ea_response_data->list_len);
4489 cFYI(1,("ea length %d", name_len));
4491 /* returned EA size zeroed at top of function */
4492 cFYI(1,("empty EA list returned from server"));
4494 /* account for ea list len */
4496 temp_fea = ea_response_data->list;
4497 temp_ptr = (char *)temp_fea;
4498 /* loop through checking if we have a matching
4499 name and then return the associated value */
4500 while(name_len > 0) {
4504 value_len = le16_to_cpu(temp_fea->value_len);
4505 /* BB validate that value_len falls within SMB,
4506 even though maximum for name_len is 255 */
4507 if(memcmp(temp_fea->name,ea_name,
4508 temp_fea->name_len) == 0) {
4511 /* account for prefix user. and trailing null */
4512 if(rc<=(int)buf_size) {
4514 temp_fea->name+temp_fea->name_len+1,
4516 /* ea values, unlike ea names,
4517 are not null terminated */
4518 } else if(buf_size == 0) {
4519 /* skip copy - calc size only */
4521 /* stop before overrun buffer */
4526 name_len -= temp_fea->name_len;
4527 temp_ptr += temp_fea->name_len;
4528 /* account for trailing null */
4531 name_len -= value_len;
4532 temp_ptr += value_len;
4533 /* no trailing null to account for in value len */
4534 /* go on to next EA */
4535 temp_fea = (struct fea *)temp_ptr;
4541 cifs_buf_release(pSMB);
4549 CIFSSMBSetEA(const int xid, struct cifsTconInfo *tcon, const char *fileName,
4550 const char * ea_name, const void * ea_value,
4551 const __u16 ea_value_len, const struct nls_table *nls_codepage,
4554 struct smb_com_transaction2_spi_req *pSMB = NULL;
4555 struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
4556 struct fealist *parm_data;
4559 int bytes_returned = 0;
4560 __u16 params, param_offset, byte_count, offset, count;
4562 cFYI(1, ("In SetEA"));
4564 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4569 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4571 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
4572 PATH_MAX, nls_codepage, remap);
4573 name_len++; /* trailing null */
4575 } else { /* BB improve the check for buffer overruns BB */
4576 name_len = strnlen(fileName, PATH_MAX);
4577 name_len++; /* trailing null */
4578 strncpy(pSMB->FileName, fileName, name_len);
4581 params = 6 + name_len;
4583 /* done calculating parms using name_len of file name,
4584 now use name_len to calculate length of ea name
4585 we are going to create in the inode xattrs */
4589 name_len = strnlen(ea_name,255);
4591 count = sizeof(*parm_data) + ea_value_len + name_len + 1;
4592 pSMB->MaxParameterCount = cpu_to_le16(2);
4593 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB size from sess */
4594 pSMB->MaxSetupCount = 0;
4598 pSMB->Reserved2 = 0;
4599 param_offset = offsetof(struct smb_com_transaction2_spi_req,
4600 InformationLevel) - 4;
4601 offset = param_offset + params;
4602 pSMB->InformationLevel =
4603 cpu_to_le16(SMB_SET_FILE_EA);
4606 (struct fealist *) (((char *) &pSMB->hdr.Protocol) +
4608 pSMB->ParameterOffset = cpu_to_le16(param_offset);
4609 pSMB->DataOffset = cpu_to_le16(offset);
4610 pSMB->SetupCount = 1;
4611 pSMB->Reserved3 = 0;
4612 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
4613 byte_count = 3 /* pad */ + params + count;
4614 pSMB->DataCount = cpu_to_le16(count);
4615 parm_data->list_len = cpu_to_le32(count);
4616 parm_data->list[0].EA_flags = 0;
4617 /* we checked above that name len is less than 255 */
4618 parm_data->list[0].name_len = (__u8)name_len;;
4619 /* EA names are always ASCII */
4621 strncpy(parm_data->list[0].name,ea_name,name_len);
4622 parm_data->list[0].name[name_len] = 0;
4623 parm_data->list[0].value_len = cpu_to_le16(ea_value_len);
4624 /* caller ensures that ea_value_len is less than 64K but
4625 we need to ensure that it fits within the smb */
4627 /*BB add length check that it would fit in negotiated SMB buffer size BB */
4628 /* if(ea_value_len > buffer_size - 512 (enough for header)) */
4630 memcpy(parm_data->list[0].name+name_len+1,ea_value,ea_value_len);
4632 pSMB->TotalDataCount = pSMB->DataCount;
4633 pSMB->ParameterCount = cpu_to_le16(params);
4634 pSMB->TotalParameterCount = pSMB->ParameterCount;
4635 pSMB->Reserved4 = 0;
4636 pSMB->hdr.smb_buf_length += byte_count;
4637 pSMB->ByteCount = cpu_to_le16(byte_count);
4638 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4639 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4641 cFYI(1, ("SetPathInfo (EA) returned %d", rc));
4644 cifs_buf_release(pSMB);