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;
1085 int bytes_returned, wct;
1089 /* cFYI(1,("write at %lld %d bytes",offset,count));*/
1090 if(tcon->ses == NULL)
1091 return -ECONNABORTED;
1093 if(tcon->ses->capabilities & CAP_LARGE_FILES)
1098 rc = smb_init(SMB_COM_WRITE_ANDX, wct, tcon, (void **) &pSMB,
1102 /* tcon and ses pointer are checked in smb_init */
1103 if (tcon->ses->server == NULL)
1104 return -ECONNABORTED;
1106 pSMB->AndXCommand = 0xFF; /* none */
1108 pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF);
1110 pSMB->OffsetHigh = cpu_to_le32(offset >> 32);
1111 else if((offset >> 32) > 0) /* can not handle this big offset for old */
1114 pSMB->Reserved = 0xFFFFFFFF;
1115 pSMB->WriteMode = 0;
1116 pSMB->Remaining = 0;
1118 /* Can increase buffer size if buffer is big enough in some cases - ie we
1119 can send more if LARGE_WRITE_X capability returned by the server and if
1120 our buffer is big enough or if we convert to iovecs on socket writes
1121 and eliminate the copy to the CIFS buffer */
1122 if(tcon->ses->capabilities & CAP_LARGE_WRITE_X) {
1123 bytes_sent = min_t(const unsigned int, CIFSMaxBufSize, count);
1125 bytes_sent = (tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE)
1129 if (bytes_sent > count)
1132 cpu_to_le16(offsetof(struct smb_com_write_req,Data) - 4);
1134 memcpy(pSMB->Data,buf,bytes_sent);
1136 if(copy_from_user(pSMB->Data,ubuf,bytes_sent)) {
1137 cifs_buf_release(pSMB);
1142 cifs_buf_release(pSMB);
1146 byte_count = bytes_sent + 1 /* pad */ ; /* BB fix this for sends > 64K */
1147 pSMB->DataLengthLow = cpu_to_le16(bytes_sent & 0xFFFF);
1148 pSMB->DataLengthHigh = cpu_to_le16(bytes_sent >> 16);
1149 pSMB->hdr.smb_buf_length += bytes_sent+1;
1152 pSMB->ByteCount = cpu_to_le16(byte_count);
1153 else { /* old style write has byte count 4 bytes earlier */
1154 struct smb_com_writex_req * pSMBW =
1155 (struct smb_com_writex_req *)pSMB;
1156 pSMBW->ByteCount = cpu_to_le16(byte_count);
1159 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1160 (struct smb_hdr *) pSMBr, &bytes_returned, long_op);
1161 cifs_stats_inc(&tcon->num_writes);
1163 cFYI(1, ("Send error in write = %d", rc));
1166 *nbytes = le16_to_cpu(pSMBr->CountHigh);
1167 *nbytes = (*nbytes) << 16;
1168 *nbytes += le16_to_cpu(pSMBr->Count);
1171 cifs_buf_release(pSMB);
1173 /* Note: On -EAGAIN error only caller can retry on handle based calls
1174 since file handle passed in no longer valid */
1179 #ifdef CONFIG_CIFS_EXPERIMENTAL
1181 CIFSSMBWrite2(const int xid, struct cifsTconInfo *tcon,
1182 const int netfid, const unsigned int count,
1183 const __u64 offset, unsigned int *nbytes, const char *buf,
1187 WRITE_REQ *pSMB = NULL;
1193 cFYI(1,("write2 at %lld %d bytes",offset,count)); /* BB removeme BB */
1194 rc = small_smb_init(SMB_COM_WRITE_ANDX, 14, tcon, (void **) &pSMB);
1197 /* tcon and ses pointer are checked in smb_init */
1198 if (tcon->ses->server == NULL)
1199 return -ECONNABORTED;
1201 pSMB->AndXCommand = 0xFF; /* none */
1203 pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF);
1204 pSMB->OffsetHigh = cpu_to_le32(offset >> 32);
1205 pSMB->Reserved = 0xFFFFFFFF;
1206 pSMB->WriteMode = 0;
1207 pSMB->Remaining = 0;
1209 /* Can increase buffer size if buffer is big enough in some cases - ie
1210 can send more if LARGE_WRITE_X capability returned by the server and if
1211 our buffer is big enough or if we convert to iovecs on socket writes
1212 and eliminate the copy to the CIFS buffer */
1213 if(tcon->ses->capabilities & CAP_LARGE_WRITE_X) {
1214 bytes_sent = min_t(const unsigned int, CIFSMaxBufSize, count);
1216 bytes_sent = (tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE)
1220 if (bytes_sent > count)
1223 cpu_to_le16(offsetof(struct smb_com_write_req,Data) - 4);
1225 byte_count = bytes_sent + 1 /* pad */ ; /* BB fix this for sends > 64K */
1226 pSMB->DataLengthLow = cpu_to_le16(bytes_sent & 0xFFFF);
1227 pSMB->DataLengthHigh = cpu_to_le16(bytes_sent >> 16);
1228 smb_hdr_len = pSMB->hdr.smb_buf_length + 1; /* hdr + 1 byte pad */
1229 pSMB->hdr.smb_buf_length += bytes_sent+1;
1230 pSMB->ByteCount = cpu_to_le16(byte_count);
1232 rc = SendReceive2(xid, tcon->ses, (struct smb_hdr *) pSMB, smb_hdr_len,
1233 buf, bytes_sent, &bytes_returned, long_op);
1234 cifs_stats_inc(&tcon->num_writes);
1236 cFYI(1, ("Send error in write = %d", rc));
1239 WRITE_RSP * pSMBr = (WRITE_RSP *)pSMB;
1240 *nbytes = le16_to_cpu(pSMBr->CountHigh);
1241 *nbytes = (*nbytes) << 16;
1242 *nbytes += le16_to_cpu(pSMBr->Count);
1245 cifs_small_buf_release(pSMB);
1247 /* Note: On -EAGAIN error only caller can retry on handle based calls
1248 since file handle passed in no longer valid */
1254 #endif /* CIFS_EXPERIMENTAL */
1257 CIFSSMBLock(const int xid, struct cifsTconInfo *tcon,
1258 const __u16 smb_file_id, const __u64 len,
1259 const __u64 offset, const __u32 numUnlock,
1260 const __u32 numLock, const __u8 lockType, const int waitFlag)
1263 LOCK_REQ *pSMB = NULL;
1264 LOCK_RSP *pSMBr = NULL;
1269 cFYI(1, ("In CIFSSMBLock - timeout %d numLock %d",waitFlag,numLock));
1270 rc = small_smb_init(SMB_COM_LOCKING_ANDX, 8, tcon, (void **) &pSMB);
1275 pSMBr = (LOCK_RSP *)pSMB; /* BB removeme BB */
1277 if(lockType == LOCKING_ANDX_OPLOCK_RELEASE) {
1278 timeout = -1; /* no response expected */
1280 } else if (waitFlag == TRUE) {
1281 timeout = 3; /* blocking operation, no timeout */
1282 pSMB->Timeout = cpu_to_le32(-1);/* blocking - do not time out */
1287 pSMB->NumberOfLocks = cpu_to_le16(numLock);
1288 pSMB->NumberOfUnlocks = cpu_to_le16(numUnlock);
1289 pSMB->LockType = lockType;
1290 pSMB->AndXCommand = 0xFF; /* none */
1291 pSMB->Fid = smb_file_id; /* netfid stays le */
1293 if((numLock != 0) || (numUnlock != 0)) {
1294 pSMB->Locks[0].Pid = cpu_to_le16(current->tgid);
1295 /* BB where to store pid high? */
1296 pSMB->Locks[0].LengthLow = cpu_to_le32((u32)len);
1297 pSMB->Locks[0].LengthHigh = cpu_to_le32((u32)(len>>32));
1298 pSMB->Locks[0].OffsetLow = cpu_to_le32((u32)offset);
1299 pSMB->Locks[0].OffsetHigh = cpu_to_le32((u32)(offset>>32));
1300 count = sizeof(LOCKING_ANDX_RANGE);
1305 pSMB->hdr.smb_buf_length += count;
1306 pSMB->ByteCount = cpu_to_le16(count);
1308 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1309 (struct smb_hdr *) pSMBr, &bytes_returned, timeout);
1310 cifs_stats_inc(&tcon->num_locks);
1312 cFYI(1, ("Send error in Lock = %d", rc));
1314 cifs_small_buf_release(pSMB);
1316 /* Note: On -EAGAIN error only caller can retry on handle based calls
1317 since file handle passed in no longer valid */
1322 CIFSSMBClose(const int xid, struct cifsTconInfo *tcon, int smb_file_id)
1325 CLOSE_REQ *pSMB = NULL;
1326 CLOSE_RSP *pSMBr = NULL;
1328 cFYI(1, ("In CIFSSMBClose"));
1330 /* do not retry on dead session on close */
1331 rc = small_smb_init(SMB_COM_CLOSE, 3, tcon, (void **) &pSMB);
1337 pSMBr = (CLOSE_RSP *)pSMB; /* BB removeme BB */
1339 pSMB->FileID = (__u16) smb_file_id;
1340 pSMB->LastWriteTime = 0;
1341 pSMB->ByteCount = 0;
1342 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1343 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1344 cifs_stats_inc(&tcon->num_closes);
1347 /* EINTR is expected when user ctl-c to kill app */
1348 cERROR(1, ("Send error in Close = %d", rc));
1352 cifs_small_buf_release(pSMB);
1354 /* Since session is dead, file will be closed on server already */
1362 CIFSSMBRename(const int xid, struct cifsTconInfo *tcon,
1363 const char *fromName, const char *toName,
1364 const struct nls_table *nls_codepage, int remap)
1367 RENAME_REQ *pSMB = NULL;
1368 RENAME_RSP *pSMBr = NULL;
1370 int name_len, name_len2;
1373 cFYI(1, ("In CIFSSMBRename"));
1375 rc = smb_init(SMB_COM_RENAME, 1, tcon, (void **) &pSMB,
1380 pSMB->BufferFormat = 0x04;
1381 pSMB->SearchAttributes =
1382 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
1385 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1387 cifsConvertToUCS((__le16 *) pSMB->OldFileName, fromName,
1388 PATH_MAX, nls_codepage, remap);
1389 name_len++; /* trailing null */
1391 pSMB->OldFileName[name_len] = 0x04; /* pad */
1392 /* protocol requires ASCII signature byte on Unicode string */
1393 pSMB->OldFileName[name_len + 1] = 0x00;
1395 cifsConvertToUCS((__le16 *) &pSMB->OldFileName[name_len + 2],
1396 toName, PATH_MAX, nls_codepage, remap);
1397 name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
1398 name_len2 *= 2; /* convert to bytes */
1399 } else { /* BB improve the check for buffer overruns BB */
1400 name_len = strnlen(fromName, PATH_MAX);
1401 name_len++; /* trailing null */
1402 strncpy(pSMB->OldFileName, fromName, name_len);
1403 name_len2 = strnlen(toName, PATH_MAX);
1404 name_len2++; /* trailing null */
1405 pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */
1406 strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2);
1407 name_len2++; /* trailing null */
1408 name_len2++; /* signature byte */
1411 count = 1 /* 1st signature byte */ + name_len + name_len2;
1412 pSMB->hdr.smb_buf_length += count;
1413 pSMB->ByteCount = cpu_to_le16(count);
1415 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1416 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1417 cifs_stats_inc(&tcon->num_renames);
1419 cFYI(1, ("Send error in rename = %d", rc));
1422 cifs_buf_release(pSMB);
1430 int CIFSSMBRenameOpenFile(const int xid,struct cifsTconInfo *pTcon,
1431 int netfid, char * target_name,
1432 const struct nls_table * nls_codepage, int remap)
1434 struct smb_com_transaction2_sfi_req *pSMB = NULL;
1435 struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
1436 struct set_file_rename * rename_info;
1438 char dummy_string[30];
1440 int bytes_returned = 0;
1442 __u16 params, param_offset, offset, count, byte_count;
1444 cFYI(1, ("Rename to File by handle"));
1445 rc = smb_init(SMB_COM_TRANSACTION2, 15, pTcon, (void **) &pSMB,
1451 pSMB->MaxSetupCount = 0;
1455 pSMB->Reserved2 = 0;
1456 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
1457 offset = param_offset + params;
1459 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
1460 rename_info = (struct set_file_rename *) data_offset;
1461 pSMB->MaxParameterCount = cpu_to_le16(2);
1462 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB PDU from sess */
1463 pSMB->SetupCount = 1;
1464 pSMB->Reserved3 = 0;
1465 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
1466 byte_count = 3 /* pad */ + params;
1467 pSMB->ParameterCount = cpu_to_le16(params);
1468 pSMB->TotalParameterCount = pSMB->ParameterCount;
1469 pSMB->ParameterOffset = cpu_to_le16(param_offset);
1470 pSMB->DataOffset = cpu_to_le16(offset);
1471 /* construct random name ".cifs_tmp<inodenum><mid>" */
1472 rename_info->overwrite = cpu_to_le32(1);
1473 rename_info->root_fid = 0;
1474 /* unicode only call */
1475 if(target_name == NULL) {
1476 sprintf(dummy_string,"cifs%x",pSMB->hdr.Mid);
1477 len_of_str = cifsConvertToUCS((__le16 *)rename_info->target_name,
1478 dummy_string, 24, nls_codepage, remap);
1480 len_of_str = cifsConvertToUCS((__le16 *)rename_info->target_name,
1481 target_name, PATH_MAX, nls_codepage, remap);
1483 rename_info->target_name_len = cpu_to_le32(2 * len_of_str);
1484 count = 12 /* sizeof(struct set_file_rename) */ + (2 * len_of_str) + 2;
1485 byte_count += count;
1486 pSMB->DataCount = cpu_to_le16(count);
1487 pSMB->TotalDataCount = pSMB->DataCount;
1489 pSMB->InformationLevel =
1490 cpu_to_le16(SMB_SET_FILE_RENAME_INFORMATION);
1491 pSMB->Reserved4 = 0;
1492 pSMB->hdr.smb_buf_length += byte_count;
1493 pSMB->ByteCount = cpu_to_le16(byte_count);
1494 rc = SendReceive(xid, pTcon->ses, (struct smb_hdr *) pSMB,
1495 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1496 cifs_stats_inc(&pTcon->num_t2renames);
1498 cFYI(1,("Send error in Rename (by file handle) = %d", rc));
1501 cifs_buf_release(pSMB);
1503 /* Note: On -EAGAIN error only caller can retry on handle based calls
1504 since file handle passed in no longer valid */
1510 CIFSSMBCopy(const int xid, struct cifsTconInfo *tcon, const char * fromName,
1511 const __u16 target_tid, const char *toName, const int flags,
1512 const struct nls_table *nls_codepage, int remap)
1515 COPY_REQ *pSMB = NULL;
1516 COPY_RSP *pSMBr = NULL;
1518 int name_len, name_len2;
1521 cFYI(1, ("In CIFSSMBCopy"));
1523 rc = smb_init(SMB_COM_COPY, 1, tcon, (void **) &pSMB,
1528 pSMB->BufferFormat = 0x04;
1529 pSMB->Tid2 = target_tid;
1531 pSMB->Flags = cpu_to_le16(flags & COPY_TREE);
1533 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1534 name_len = cifsConvertToUCS((__le16 *) pSMB->OldFileName,
1535 fromName, PATH_MAX, nls_codepage,
1537 name_len++; /* trailing null */
1539 pSMB->OldFileName[name_len] = 0x04; /* pad */
1540 /* protocol requires ASCII signature byte on Unicode string */
1541 pSMB->OldFileName[name_len + 1] = 0x00;
1542 name_len2 = cifsConvertToUCS((__le16 *)&pSMB->OldFileName[name_len + 2],
1543 toName, PATH_MAX, nls_codepage, remap);
1544 name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
1545 name_len2 *= 2; /* convert to bytes */
1546 } else { /* BB improve the check for buffer overruns BB */
1547 name_len = strnlen(fromName, PATH_MAX);
1548 name_len++; /* trailing null */
1549 strncpy(pSMB->OldFileName, fromName, name_len);
1550 name_len2 = strnlen(toName, PATH_MAX);
1551 name_len2++; /* trailing null */
1552 pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */
1553 strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2);
1554 name_len2++; /* trailing null */
1555 name_len2++; /* signature byte */
1558 count = 1 /* 1st signature byte */ + name_len + name_len2;
1559 pSMB->hdr.smb_buf_length += count;
1560 pSMB->ByteCount = cpu_to_le16(count);
1562 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1563 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1565 cFYI(1, ("Send error in copy = %d with %d files copied",
1566 rc, le16_to_cpu(pSMBr->CopyCount)));
1569 cifs_buf_release(pSMB);
1578 CIFSUnixCreateSymLink(const int xid, struct cifsTconInfo *tcon,
1579 const char *fromName, const char *toName,
1580 const struct nls_table *nls_codepage)
1582 TRANSACTION2_SPI_REQ *pSMB = NULL;
1583 TRANSACTION2_SPI_RSP *pSMBr = NULL;
1586 int name_len_target;
1588 int bytes_returned = 0;
1589 __u16 params, param_offset, offset, byte_count;
1591 cFYI(1, ("In Symlink Unix style"));
1593 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
1598 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1600 cifs_strtoUCS((wchar_t *) pSMB->FileName, fromName, PATH_MAX
1601 /* find define for this maxpathcomponent */
1603 name_len++; /* trailing null */
1606 } else { /* BB improve the check for buffer overruns BB */
1607 name_len = strnlen(fromName, PATH_MAX);
1608 name_len++; /* trailing null */
1609 strncpy(pSMB->FileName, fromName, name_len);
1611 params = 6 + name_len;
1612 pSMB->MaxSetupCount = 0;
1616 pSMB->Reserved2 = 0;
1617 param_offset = offsetof(struct smb_com_transaction2_spi_req,
1618 InformationLevel) - 4;
1619 offset = param_offset + params;
1621 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
1622 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1624 cifs_strtoUCS((wchar_t *) data_offset, toName, PATH_MAX
1625 /* find define for this maxpathcomponent */
1627 name_len_target++; /* trailing null */
1628 name_len_target *= 2;
1629 } else { /* BB improve the check for buffer overruns BB */
1630 name_len_target = strnlen(toName, PATH_MAX);
1631 name_len_target++; /* trailing null */
1632 strncpy(data_offset, toName, name_len_target);
1635 pSMB->MaxParameterCount = cpu_to_le16(2);
1636 /* BB find exact max on data count below from sess */
1637 pSMB->MaxDataCount = cpu_to_le16(1000);
1638 pSMB->SetupCount = 1;
1639 pSMB->Reserved3 = 0;
1640 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
1641 byte_count = 3 /* pad */ + params + name_len_target;
1642 pSMB->DataCount = cpu_to_le16(name_len_target);
1643 pSMB->ParameterCount = cpu_to_le16(params);
1644 pSMB->TotalDataCount = pSMB->DataCount;
1645 pSMB->TotalParameterCount = pSMB->ParameterCount;
1646 pSMB->ParameterOffset = cpu_to_le16(param_offset);
1647 pSMB->DataOffset = cpu_to_le16(offset);
1648 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_LINK);
1649 pSMB->Reserved4 = 0;
1650 pSMB->hdr.smb_buf_length += byte_count;
1651 pSMB->ByteCount = cpu_to_le16(byte_count);
1652 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1653 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1654 cifs_stats_inc(&tcon->num_symlinks);
1657 ("Send error in SetPathInfo (create symlink) = %d",
1662 cifs_buf_release(pSMB);
1665 goto createSymLinkRetry;
1671 CIFSUnixCreateHardLink(const int xid, struct cifsTconInfo *tcon,
1672 const char *fromName, const char *toName,
1673 const struct nls_table *nls_codepage, int remap)
1675 TRANSACTION2_SPI_REQ *pSMB = NULL;
1676 TRANSACTION2_SPI_RSP *pSMBr = NULL;
1679 int name_len_target;
1681 int bytes_returned = 0;
1682 __u16 params, param_offset, offset, byte_count;
1684 cFYI(1, ("In Create Hard link Unix style"));
1685 createHardLinkRetry:
1686 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
1691 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1692 name_len = cifsConvertToUCS((__le16 *) pSMB->FileName, toName,
1693 PATH_MAX, nls_codepage, remap);
1694 name_len++; /* trailing null */
1697 } else { /* BB improve the check for buffer overruns BB */
1698 name_len = strnlen(toName, PATH_MAX);
1699 name_len++; /* trailing null */
1700 strncpy(pSMB->FileName, toName, name_len);
1702 params = 6 + name_len;
1703 pSMB->MaxSetupCount = 0;
1707 pSMB->Reserved2 = 0;
1708 param_offset = offsetof(struct smb_com_transaction2_spi_req,
1709 InformationLevel) - 4;
1710 offset = param_offset + params;
1712 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
1713 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1715 cifsConvertToUCS((__le16 *) data_offset, fromName, PATH_MAX,
1716 nls_codepage, remap);
1717 name_len_target++; /* trailing null */
1718 name_len_target *= 2;
1719 } else { /* BB improve the check for buffer overruns BB */
1720 name_len_target = strnlen(fromName, PATH_MAX);
1721 name_len_target++; /* trailing null */
1722 strncpy(data_offset, fromName, name_len_target);
1725 pSMB->MaxParameterCount = cpu_to_le16(2);
1726 /* BB find exact max on data count below from sess*/
1727 pSMB->MaxDataCount = cpu_to_le16(1000);
1728 pSMB->SetupCount = 1;
1729 pSMB->Reserved3 = 0;
1730 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
1731 byte_count = 3 /* pad */ + params + name_len_target;
1732 pSMB->ParameterCount = cpu_to_le16(params);
1733 pSMB->TotalParameterCount = pSMB->ParameterCount;
1734 pSMB->DataCount = cpu_to_le16(name_len_target);
1735 pSMB->TotalDataCount = pSMB->DataCount;
1736 pSMB->ParameterOffset = cpu_to_le16(param_offset);
1737 pSMB->DataOffset = cpu_to_le16(offset);
1738 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_HLINK);
1739 pSMB->Reserved4 = 0;
1740 pSMB->hdr.smb_buf_length += byte_count;
1741 pSMB->ByteCount = cpu_to_le16(byte_count);
1742 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1743 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1744 cifs_stats_inc(&tcon->num_hardlinks);
1746 cFYI(1, ("Send error in SetPathInfo (hard link) = %d", rc));
1749 cifs_buf_release(pSMB);
1751 goto createHardLinkRetry;
1757 CIFSCreateHardLink(const int xid, struct cifsTconInfo *tcon,
1758 const char *fromName, const char *toName,
1759 const struct nls_table *nls_codepage, int remap)
1762 NT_RENAME_REQ *pSMB = NULL;
1763 RENAME_RSP *pSMBr = NULL;
1765 int name_len, name_len2;
1768 cFYI(1, ("In CIFSCreateHardLink"));
1769 winCreateHardLinkRetry:
1771 rc = smb_init(SMB_COM_NT_RENAME, 4, tcon, (void **) &pSMB,
1776 pSMB->SearchAttributes =
1777 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
1779 pSMB->Flags = cpu_to_le16(CREATE_HARD_LINK);
1780 pSMB->ClusterCount = 0;
1782 pSMB->BufferFormat = 0x04;
1784 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1786 cifsConvertToUCS((__le16 *) pSMB->OldFileName, fromName,
1787 PATH_MAX, nls_codepage, remap);
1788 name_len++; /* trailing null */
1790 pSMB->OldFileName[name_len] = 0; /* pad */
1791 pSMB->OldFileName[name_len + 1] = 0x04;
1793 cifsConvertToUCS((__le16 *)&pSMB->OldFileName[name_len + 2],
1794 toName, PATH_MAX, nls_codepage, remap);
1795 name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
1796 name_len2 *= 2; /* convert to bytes */
1797 } else { /* BB improve the check for buffer overruns BB */
1798 name_len = strnlen(fromName, PATH_MAX);
1799 name_len++; /* trailing null */
1800 strncpy(pSMB->OldFileName, fromName, name_len);
1801 name_len2 = strnlen(toName, PATH_MAX);
1802 name_len2++; /* trailing null */
1803 pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */
1804 strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2);
1805 name_len2++; /* trailing null */
1806 name_len2++; /* signature byte */
1809 count = 1 /* string type byte */ + name_len + name_len2;
1810 pSMB->hdr.smb_buf_length += count;
1811 pSMB->ByteCount = cpu_to_le16(count);
1813 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1814 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1815 cifs_stats_inc(&tcon->num_hardlinks);
1817 cFYI(1, ("Send error in hard link (NT rename) = %d", rc));
1819 cifs_buf_release(pSMB);
1821 goto winCreateHardLinkRetry;
1827 CIFSSMBUnixQuerySymLink(const int xid, struct cifsTconInfo *tcon,
1828 const unsigned char *searchName,
1829 char *symlinkinfo, const int buflen,
1830 const struct nls_table *nls_codepage)
1832 /* SMB_QUERY_FILE_UNIX_LINK */
1833 TRANSACTION2_QPI_REQ *pSMB = NULL;
1834 TRANSACTION2_QPI_RSP *pSMBr = NULL;
1838 __u16 params, byte_count;
1840 cFYI(1, ("In QPathSymLinkInfo (Unix) for path %s", searchName));
1843 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
1848 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1850 cifs_strtoUCS((wchar_t *) pSMB->FileName, searchName, PATH_MAX
1851 /* find define for this maxpathcomponent */
1853 name_len++; /* trailing null */
1855 } else { /* BB improve the check for buffer overruns BB */
1856 name_len = strnlen(searchName, PATH_MAX);
1857 name_len++; /* trailing null */
1858 strncpy(pSMB->FileName, searchName, name_len);
1861 params = 2 /* level */ + 4 /* rsrvd */ + name_len /* incl null */ ;
1862 pSMB->TotalDataCount = 0;
1863 pSMB->MaxParameterCount = cpu_to_le16(2);
1864 /* BB find exact max data count below from sess structure BB */
1865 pSMB->MaxDataCount = cpu_to_le16(4000);
1866 pSMB->MaxSetupCount = 0;
1870 pSMB->Reserved2 = 0;
1871 pSMB->ParameterOffset = cpu_to_le16(offsetof(
1872 struct smb_com_transaction2_qpi_req ,InformationLevel) - 4);
1873 pSMB->DataCount = 0;
1874 pSMB->DataOffset = 0;
1875 pSMB->SetupCount = 1;
1876 pSMB->Reserved3 = 0;
1877 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
1878 byte_count = params + 1 /* pad */ ;
1879 pSMB->TotalParameterCount = cpu_to_le16(params);
1880 pSMB->ParameterCount = pSMB->TotalParameterCount;
1881 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_LINK);
1882 pSMB->Reserved4 = 0;
1883 pSMB->hdr.smb_buf_length += byte_count;
1884 pSMB->ByteCount = cpu_to_le16(byte_count);
1886 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1887 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1889 cFYI(1, ("Send error in QuerySymLinkInfo = %d", rc));
1891 /* decode response */
1893 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
1894 if (rc || (pSMBr->ByteCount < 2))
1895 /* BB also check enough total bytes returned */
1896 rc = -EIO; /* bad smb */
1898 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
1899 __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
1901 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
1902 name_len = UniStrnlen((wchar_t *) ((char *)
1903 &pSMBr->hdr.Protocol +data_offset),
1904 min_t(const int, buflen,count) / 2);
1905 /* BB FIXME investigate remapping reserved chars here */
1906 cifs_strfromUCS_le(symlinkinfo,
1907 (wchar_t *) ((char *)&pSMBr->hdr.Protocol +
1909 name_len, nls_codepage);
1911 strncpy(symlinkinfo,
1912 (char *) &pSMBr->hdr.Protocol +
1914 min_t(const int, buflen, count));
1916 symlinkinfo[buflen] = 0;
1917 /* just in case so calling code does not go off the end of buffer */
1920 cifs_buf_release(pSMB);
1922 goto querySymLinkRetry;
1927 CIFSSMBQueryReparseLinkInfo(const int xid, struct cifsTconInfo *tcon,
1928 const unsigned char *searchName,
1929 char *symlinkinfo, const int buflen,__u16 fid,
1930 const struct nls_table *nls_codepage)
1935 struct smb_com_transaction_ioctl_req * pSMB;
1936 struct smb_com_transaction_ioctl_rsp * pSMBr;
1938 cFYI(1, ("In Windows reparse style QueryLink for path %s", searchName));
1939 rc = smb_init(SMB_COM_NT_TRANSACT, 23, tcon, (void **) &pSMB,
1944 pSMB->TotalParameterCount = 0 ;
1945 pSMB->TotalDataCount = 0;
1946 pSMB->MaxParameterCount = cpu_to_le32(2);
1947 /* BB find exact data count max from sess structure BB */
1948 pSMB->MaxDataCount = cpu_to_le32(4000);
1949 pSMB->MaxSetupCount = 4;
1951 pSMB->ParameterOffset = 0;
1952 pSMB->DataCount = 0;
1953 pSMB->DataOffset = 0;
1954 pSMB->SetupCount = 4;
1955 pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_IOCTL);
1956 pSMB->ParameterCount = pSMB->TotalParameterCount;
1957 pSMB->FunctionCode = cpu_to_le32(FSCTL_GET_REPARSE_POINT);
1958 pSMB->IsFsctl = 1; /* FSCTL */
1959 pSMB->IsRootFlag = 0;
1960 pSMB->Fid = fid; /* file handle always le */
1961 pSMB->ByteCount = 0;
1963 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1964 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1966 cFYI(1, ("Send error in QueryReparseLinkInfo = %d", rc));
1967 } else { /* decode response */
1968 __u32 data_offset = le32_to_cpu(pSMBr->DataOffset);
1969 __u32 data_count = le32_to_cpu(pSMBr->DataCount);
1970 if ((pSMBr->ByteCount < 2) || (data_offset > 512))
1971 /* BB also check enough total bytes returned */
1972 rc = -EIO; /* bad smb */
1974 if(data_count && (data_count < 2048)) {
1975 char * end_of_smb = pSMBr->ByteCount + (char *)&pSMBr->ByteCount;
1977 struct reparse_data * reparse_buf = (struct reparse_data *)
1978 ((char *)&pSMBr->hdr.Protocol + data_offset);
1979 if((char*)reparse_buf >= end_of_smb) {
1983 if((reparse_buf->LinkNamesBuf +
1984 reparse_buf->TargetNameOffset +
1985 reparse_buf->TargetNameLen) >
1987 cFYI(1,("reparse buf extended beyond SMB"));
1992 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
1993 name_len = UniStrnlen((wchar_t *)
1994 (reparse_buf->LinkNamesBuf +
1995 reparse_buf->TargetNameOffset),
1996 min(buflen/2, reparse_buf->TargetNameLen / 2));
1997 cifs_strfromUCS_le(symlinkinfo,
1998 (wchar_t *) (reparse_buf->LinkNamesBuf +
1999 reparse_buf->TargetNameOffset),
2000 name_len, nls_codepage);
2001 } else { /* ASCII names */
2002 strncpy(symlinkinfo,reparse_buf->LinkNamesBuf +
2003 reparse_buf->TargetNameOffset,
2004 min_t(const int, buflen, reparse_buf->TargetNameLen));
2008 cFYI(1,("Invalid return data count on get reparse info ioctl"));
2010 symlinkinfo[buflen] = 0; /* just in case so the caller
2011 does not go off the end of the buffer */
2012 cFYI(1,("readlink result - %s ",symlinkinfo));
2016 cifs_buf_release(pSMB);
2018 /* Note: On -EAGAIN error only caller can retry on handle based calls
2019 since file handle passed in no longer valid */
2024 #ifdef CONFIG_CIFS_POSIX
2026 /*Convert an Access Control Entry from wire format to local POSIX xattr format*/
2027 static void cifs_convert_ace(posix_acl_xattr_entry * ace, struct cifs_posix_ace * cifs_ace)
2029 /* u8 cifs fields do not need le conversion */
2030 ace->e_perm = (__u16)cifs_ace->cifs_e_perm;
2031 ace->e_tag = (__u16)cifs_ace->cifs_e_tag;
2032 ace->e_id = (__u32)le64_to_cpu(cifs_ace->cifs_uid);
2033 /* cFYI(1,("perm %d tag %d id %d",ace->e_perm,ace->e_tag,ace->e_id)); */
2038 /* Convert ACL from CIFS POSIX wire format to local Linux POSIX ACL xattr */
2039 static int cifs_copy_posix_acl(char * trgt,char * src, const int buflen,
2040 const int acl_type,const int size_of_data_area)
2045 struct cifs_posix_ace * pACE;
2046 struct cifs_posix_acl * cifs_acl = (struct cifs_posix_acl *)src;
2047 posix_acl_xattr_header * local_acl = (posix_acl_xattr_header *)trgt;
2049 if (le16_to_cpu(cifs_acl->version) != CIFS_ACL_VERSION)
2052 if(acl_type & ACL_TYPE_ACCESS) {
2053 count = le16_to_cpu(cifs_acl->access_entry_count);
2054 pACE = &cifs_acl->ace_array[0];
2055 size = sizeof(struct cifs_posix_acl);
2056 size += sizeof(struct cifs_posix_ace) * count;
2057 /* check if we would go beyond end of SMB */
2058 if(size_of_data_area < size) {
2059 cFYI(1,("bad CIFS POSIX ACL size %d vs. %d",size_of_data_area,size));
2062 } else if(acl_type & ACL_TYPE_DEFAULT) {
2063 count = le16_to_cpu(cifs_acl->access_entry_count);
2064 size = sizeof(struct cifs_posix_acl);
2065 size += sizeof(struct cifs_posix_ace) * count;
2066 /* skip past access ACEs to get to default ACEs */
2067 pACE = &cifs_acl->ace_array[count];
2068 count = le16_to_cpu(cifs_acl->default_entry_count);
2069 size += sizeof(struct cifs_posix_ace) * count;
2070 /* check if we would go beyond end of SMB */
2071 if(size_of_data_area < size)
2078 size = posix_acl_xattr_size(count);
2079 if((buflen == 0) || (local_acl == NULL)) {
2080 /* used to query ACL EA size */
2081 } else if(size > buflen) {
2083 } else /* buffer big enough */ {
2084 local_acl->a_version = POSIX_ACL_XATTR_VERSION;
2085 for(i = 0;i < count ;i++) {
2086 cifs_convert_ace(&local_acl->a_entries[i],pACE);
2093 static __u16 convert_ace_to_cifs_ace(struct cifs_posix_ace * cifs_ace,
2094 const posix_acl_xattr_entry * local_ace)
2096 __u16 rc = 0; /* 0 = ACL converted ok */
2098 cifs_ace->cifs_e_perm = (__u8)cpu_to_le16(local_ace->e_perm);
2099 cifs_ace->cifs_e_tag = (__u8)cpu_to_le16(local_ace->e_tag);
2100 /* BB is there a better way to handle the large uid? */
2101 if(local_ace->e_id == -1) {
2102 /* Probably no need to le convert -1 on any arch but can not hurt */
2103 cifs_ace->cifs_uid = cpu_to_le64(-1);
2105 cifs_ace->cifs_uid = (__u64)cpu_to_le32(local_ace->e_id);
2106 /*cFYI(1,("perm %d tag %d id %d",ace->e_perm,ace->e_tag,ace->e_id));*/
2110 /* Convert ACL from local Linux POSIX xattr to CIFS POSIX ACL wire format */
2111 static __u16 ACL_to_cifs_posix(char * parm_data,const char * pACL,const int buflen,
2115 struct cifs_posix_acl * cifs_acl = (struct cifs_posix_acl *)parm_data;
2116 posix_acl_xattr_header * local_acl = (posix_acl_xattr_header *)pACL;
2120 if((buflen == 0) || (pACL == NULL) || (cifs_acl == NULL))
2123 count = posix_acl_xattr_count((size_t)buflen);
2124 cFYI(1,("setting acl with %d entries from buf of length %d and version of %d",
2125 count,buflen,local_acl->a_version));
2126 if(local_acl->a_version != 2) {
2127 cFYI(1,("unknown POSIX ACL version %d",local_acl->a_version));
2130 cifs_acl->version = cpu_to_le16(1);
2131 if(acl_type == ACL_TYPE_ACCESS)
2132 cifs_acl->access_entry_count = count;
2133 else if(acl_type == ACL_TYPE_DEFAULT)
2134 cifs_acl->default_entry_count = count;
2136 cFYI(1,("unknown ACL type %d",acl_type));
2139 for(i=0;i<count;i++) {
2140 rc = convert_ace_to_cifs_ace(&cifs_acl->ace_array[i],
2141 &local_acl->a_entries[i]);
2143 /* ACE not converted */
2148 rc = (__u16)(count * sizeof(struct cifs_posix_ace));
2149 rc += sizeof(struct cifs_posix_acl);
2150 /* BB add check to make sure ACL does not overflow SMB */
2156 CIFSSMBGetPosixACL(const int xid, struct cifsTconInfo *tcon,
2157 const unsigned char *searchName,
2158 char *acl_inf, const int buflen, const int acl_type,
2159 const struct nls_table *nls_codepage, int remap)
2161 /* SMB_QUERY_POSIX_ACL */
2162 TRANSACTION2_QPI_REQ *pSMB = NULL;
2163 TRANSACTION2_QPI_RSP *pSMBr = NULL;
2167 __u16 params, byte_count;
2169 cFYI(1, ("In GetPosixACL (Unix) for path %s", searchName));
2172 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2177 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2179 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
2180 PATH_MAX, nls_codepage, remap);
2181 name_len++; /* trailing null */
2183 pSMB->FileName[name_len] = 0;
2184 pSMB->FileName[name_len+1] = 0;
2185 } else { /* BB improve the check for buffer overruns BB */
2186 name_len = strnlen(searchName, PATH_MAX);
2187 name_len++; /* trailing null */
2188 strncpy(pSMB->FileName, searchName, name_len);
2191 params = 2 /* level */ + 4 /* rsrvd */ + name_len /* incl null */ ;
2192 pSMB->TotalDataCount = 0;
2193 pSMB->MaxParameterCount = cpu_to_le16(2);
2194 /* BB find exact max data count below from sess structure BB */
2195 pSMB->MaxDataCount = cpu_to_le16(4000);
2196 pSMB->MaxSetupCount = 0;
2200 pSMB->Reserved2 = 0;
2201 pSMB->ParameterOffset = cpu_to_le16(
2202 offsetof(struct smb_com_transaction2_qpi_req ,InformationLevel) - 4);
2203 pSMB->DataCount = 0;
2204 pSMB->DataOffset = 0;
2205 pSMB->SetupCount = 1;
2206 pSMB->Reserved3 = 0;
2207 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
2208 byte_count = params + 1 /* pad */ ;
2209 pSMB->TotalParameterCount = cpu_to_le16(params);
2210 pSMB->ParameterCount = pSMB->TotalParameterCount;
2211 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_POSIX_ACL);
2212 pSMB->Reserved4 = 0;
2213 pSMB->hdr.smb_buf_length += byte_count;
2214 pSMB->ByteCount = cpu_to_le16(byte_count);
2216 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2217 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2219 cFYI(1, ("Send error in Query POSIX ACL = %d", rc));
2221 /* decode response */
2223 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
2224 if (rc || (pSMBr->ByteCount < 2))
2225 /* BB also check enough total bytes returned */
2226 rc = -EIO; /* bad smb */
2228 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
2229 __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
2230 rc = cifs_copy_posix_acl(acl_inf,
2231 (char *)&pSMBr->hdr.Protocol+data_offset,
2232 buflen,acl_type,count);
2235 cifs_buf_release(pSMB);
2242 CIFSSMBSetPosixACL(const int xid, struct cifsTconInfo *tcon,
2243 const unsigned char *fileName,
2244 const char *local_acl, const int buflen,
2246 const struct nls_table *nls_codepage, int remap)
2248 struct smb_com_transaction2_spi_req *pSMB = NULL;
2249 struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
2253 int bytes_returned = 0;
2254 __u16 params, byte_count, data_count, param_offset, offset;
2256 cFYI(1, ("In SetPosixACL (Unix) for path %s", fileName));
2258 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2262 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2264 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
2265 PATH_MAX, nls_codepage, remap);
2266 name_len++; /* trailing null */
2268 } else { /* BB improve the check for buffer overruns BB */
2269 name_len = strnlen(fileName, PATH_MAX);
2270 name_len++; /* trailing null */
2271 strncpy(pSMB->FileName, fileName, name_len);
2273 params = 6 + name_len;
2274 pSMB->MaxParameterCount = cpu_to_le16(2);
2275 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB size from sess */
2276 pSMB->MaxSetupCount = 0;
2280 pSMB->Reserved2 = 0;
2281 param_offset = offsetof(struct smb_com_transaction2_spi_req,
2282 InformationLevel) - 4;
2283 offset = param_offset + params;
2284 parm_data = ((char *) &pSMB->hdr.Protocol) + offset;
2285 pSMB->ParameterOffset = cpu_to_le16(param_offset);
2287 /* convert to on the wire format for POSIX ACL */
2288 data_count = ACL_to_cifs_posix(parm_data,local_acl,buflen,acl_type);
2290 if(data_count == 0) {
2292 goto setACLerrorExit;
2294 pSMB->DataOffset = cpu_to_le16(offset);
2295 pSMB->SetupCount = 1;
2296 pSMB->Reserved3 = 0;
2297 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
2298 pSMB->InformationLevel = cpu_to_le16(SMB_SET_POSIX_ACL);
2299 byte_count = 3 /* pad */ + params + data_count;
2300 pSMB->DataCount = cpu_to_le16(data_count);
2301 pSMB->TotalDataCount = pSMB->DataCount;
2302 pSMB->ParameterCount = cpu_to_le16(params);
2303 pSMB->TotalParameterCount = pSMB->ParameterCount;
2304 pSMB->Reserved4 = 0;
2305 pSMB->hdr.smb_buf_length += byte_count;
2306 pSMB->ByteCount = cpu_to_le16(byte_count);
2307 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2308 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2310 cFYI(1, ("Set POSIX ACL returned %d", rc));
2314 cifs_buf_release(pSMB);
2320 /* BB fix tabs in this function FIXME BB */
2322 CIFSGetExtAttr(const int xid, struct cifsTconInfo *tcon,
2323 const int netfid, __u64 * pExtAttrBits, __u64 *pMask)
2326 struct smb_t2_qfi_req *pSMB = NULL;
2327 struct smb_t2_qfi_rsp *pSMBr = NULL;
2329 __u16 params, byte_count;
2331 cFYI(1,("In GetExtAttr"));
2336 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2341 params = 2 /* level */ +2 /* fid */;
2342 pSMB->t2.TotalDataCount = 0;
2343 pSMB->t2.MaxParameterCount = cpu_to_le16(4);
2344 /* BB find exact max data count below from sess structure BB */
2345 pSMB->t2.MaxDataCount = cpu_to_le16(4000);
2346 pSMB->t2.MaxSetupCount = 0;
2347 pSMB->t2.Reserved = 0;
2349 pSMB->t2.Timeout = 0;
2350 pSMB->t2.Reserved2 = 0;
2351 pSMB->t2.ParameterOffset = cpu_to_le16(offsetof(struct smb_t2_qfi_req,
2353 pSMB->t2.DataCount = 0;
2354 pSMB->t2.DataOffset = 0;
2355 pSMB->t2.SetupCount = 1;
2356 pSMB->t2.Reserved3 = 0;
2357 pSMB->t2.SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION);
2358 byte_count = params + 1 /* pad */ ;
2359 pSMB->t2.TotalParameterCount = cpu_to_le16(params);
2360 pSMB->t2.ParameterCount = pSMB->t2.TotalParameterCount;
2361 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_ATTR_FLAGS);
2364 pSMB->hdr.smb_buf_length += byte_count;
2365 pSMB->t2.ByteCount = cpu_to_le16(byte_count);
2367 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2368 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2370 cFYI(1, ("error %d in GetExtAttr", rc));
2372 /* decode response */
2373 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
2374 if (rc || (pSMBr->ByteCount < 2))
2375 /* BB also check enough total bytes returned */
2376 /* If rc should we check for EOPNOSUPP and
2377 disable the srvino flag? or in caller? */
2378 rc = -EIO; /* bad smb */
2380 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
2381 __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
2382 struct file_chattr_info * pfinfo;
2383 /* BB Do we need a cast or hash here ? */
2385 cFYI(1, ("Illegal size ret in GetExtAttr"));
2389 pfinfo = (struct file_chattr_info *)
2390 (data_offset + (char *) &pSMBr->hdr.Protocol);
2391 *pExtAttrBits = le64_to_cpu(pfinfo->mode);
2392 *pMask = le64_to_cpu(pfinfo->mask);
2396 cifs_buf_release(pSMB);
2398 goto GetExtAttrRetry;
2403 #endif /* CONFIG_POSIX */
2405 /* Legacy Query Path Information call for lookup to old servers such
2407 int SMBQueryInformation(const int xid, struct cifsTconInfo *tcon,
2408 const unsigned char *searchName,
2409 FILE_ALL_INFO * pFinfo,
2410 const struct nls_table *nls_codepage, int remap)
2412 QUERY_INFORMATION_REQ * pSMB;
2413 QUERY_INFORMATION_RSP * pSMBr;
2418 cFYI(1, ("In SMBQPath path %s", searchName));
2420 rc = smb_init(SMB_COM_QUERY_INFORMATION, 0, tcon, (void **) &pSMB,
2425 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2427 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
2428 PATH_MAX, nls_codepage, remap);
2429 name_len++; /* trailing null */
2432 name_len = strnlen(searchName, PATH_MAX);
2433 name_len++; /* trailing null */
2434 strncpy(pSMB->FileName, searchName, name_len);
2436 pSMB->BufferFormat = 0x04;
2437 name_len++; /* account for buffer type byte */
2438 pSMB->hdr.smb_buf_length += (__u16) name_len;
2439 pSMB->ByteCount = cpu_to_le16(name_len);
2441 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2442 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2444 cFYI(1, ("Send error in QueryInfo = %d", rc));
2445 } else if (pFinfo) { /* decode response */
2446 memset(pFinfo, 0, sizeof(FILE_ALL_INFO));
2447 pFinfo->AllocationSize = (__le64) pSMBr->size;
2448 pFinfo->EndOfFile = (__le64) pSMBr->size;
2449 pFinfo->Attributes = (__le32) pSMBr->attr;
2451 rc = -EIO; /* bad buffer passed in */
2453 cifs_buf_release(pSMB);
2465 CIFSSMBQPathInfo(const int xid, struct cifsTconInfo *tcon,
2466 const unsigned char *searchName,
2467 FILE_ALL_INFO * pFindData,
2468 const struct nls_table *nls_codepage, int remap)
2470 /* level 263 SMB_QUERY_FILE_ALL_INFO */
2471 TRANSACTION2_QPI_REQ *pSMB = NULL;
2472 TRANSACTION2_QPI_RSP *pSMBr = NULL;
2476 __u16 params, byte_count;
2478 /* cFYI(1, ("In QPathInfo path %s", searchName)); */
2480 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2485 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2487 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
2488 PATH_MAX, nls_codepage, remap);
2489 name_len++; /* trailing null */
2491 } else { /* BB improve the check for buffer overruns BB */
2492 name_len = strnlen(searchName, PATH_MAX);
2493 name_len++; /* trailing null */
2494 strncpy(pSMB->FileName, searchName, name_len);
2497 params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */ ;
2498 pSMB->TotalDataCount = 0;
2499 pSMB->MaxParameterCount = cpu_to_le16(2);
2500 pSMB->MaxDataCount = cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
2501 pSMB->MaxSetupCount = 0;
2505 pSMB->Reserved2 = 0;
2506 pSMB->ParameterOffset = cpu_to_le16(offsetof(
2507 struct smb_com_transaction2_qpi_req ,InformationLevel) - 4);
2508 pSMB->DataCount = 0;
2509 pSMB->DataOffset = 0;
2510 pSMB->SetupCount = 1;
2511 pSMB->Reserved3 = 0;
2512 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
2513 byte_count = params + 1 /* pad */ ;
2514 pSMB->TotalParameterCount = cpu_to_le16(params);
2515 pSMB->ParameterCount = pSMB->TotalParameterCount;
2516 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_ALL_INFO);
2517 pSMB->Reserved4 = 0;
2518 pSMB->hdr.smb_buf_length += byte_count;
2519 pSMB->ByteCount = cpu_to_le16(byte_count);
2521 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2522 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2524 cFYI(1, ("Send error in QPathInfo = %d", rc));
2525 } else { /* decode response */
2526 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
2528 if (rc || (pSMBr->ByteCount < 40))
2529 rc = -EIO; /* bad smb */
2530 else if (pFindData){
2531 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
2532 memcpy((char *) pFindData,
2533 (char *) &pSMBr->hdr.Protocol +
2534 data_offset, sizeof (FILE_ALL_INFO));
2538 cifs_buf_release(pSMB);
2540 goto QPathInfoRetry;
2546 CIFSSMBUnixQPathInfo(const int xid, struct cifsTconInfo *tcon,
2547 const unsigned char *searchName,
2548 FILE_UNIX_BASIC_INFO * pFindData,
2549 const struct nls_table *nls_codepage, int remap)
2551 /* SMB_QUERY_FILE_UNIX_BASIC */
2552 TRANSACTION2_QPI_REQ *pSMB = NULL;
2553 TRANSACTION2_QPI_RSP *pSMBr = NULL;
2555 int bytes_returned = 0;
2557 __u16 params, byte_count;
2559 cFYI(1, ("In QPathInfo (Unix) the path %s", searchName));
2561 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2566 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2568 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
2569 PATH_MAX, nls_codepage, remap);
2570 name_len++; /* trailing null */
2572 } else { /* BB improve the check for buffer overruns BB */
2573 name_len = strnlen(searchName, PATH_MAX);
2574 name_len++; /* trailing null */
2575 strncpy(pSMB->FileName, searchName, name_len);
2578 params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */ ;
2579 pSMB->TotalDataCount = 0;
2580 pSMB->MaxParameterCount = cpu_to_le16(2);
2581 /* BB find exact max SMB PDU from sess structure BB */
2582 pSMB->MaxDataCount = cpu_to_le16(4000);
2583 pSMB->MaxSetupCount = 0;
2587 pSMB->Reserved2 = 0;
2588 pSMB->ParameterOffset = cpu_to_le16(offsetof(
2589 struct smb_com_transaction2_qpi_req ,InformationLevel) - 4);
2590 pSMB->DataCount = 0;
2591 pSMB->DataOffset = 0;
2592 pSMB->SetupCount = 1;
2593 pSMB->Reserved3 = 0;
2594 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
2595 byte_count = params + 1 /* pad */ ;
2596 pSMB->TotalParameterCount = cpu_to_le16(params);
2597 pSMB->ParameterCount = pSMB->TotalParameterCount;
2598 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC);
2599 pSMB->Reserved4 = 0;
2600 pSMB->hdr.smb_buf_length += byte_count;
2601 pSMB->ByteCount = cpu_to_le16(byte_count);
2603 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2604 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2606 cFYI(1, ("Send error in QPathInfo = %d", rc));
2607 } else { /* decode response */
2608 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
2610 if (rc || (pSMBr->ByteCount < sizeof(FILE_UNIX_BASIC_INFO))) {
2611 rc = -EIO; /* bad smb */
2613 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
2614 memcpy((char *) pFindData,
2615 (char *) &pSMBr->hdr.Protocol +
2617 sizeof (FILE_UNIX_BASIC_INFO));
2620 cifs_buf_release(pSMB);
2622 goto UnixQPathInfoRetry;
2627 #if 0 /* function unused at present */
2628 int CIFSFindSingle(const int xid, struct cifsTconInfo *tcon,
2629 const char *searchName, FILE_ALL_INFO * findData,
2630 const struct nls_table *nls_codepage)
2632 /* level 257 SMB_ */
2633 TRANSACTION2_FFIRST_REQ *pSMB = NULL;
2634 TRANSACTION2_FFIRST_RSP *pSMBr = NULL;
2638 __u16 params, byte_count;
2640 cFYI(1, ("In FindUnique"));
2642 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2647 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2649 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName, PATH_MAX
2650 /* find define for this maxpathcomponent */
2652 name_len++; /* trailing null */
2654 } else { /* BB improve the check for buffer overruns BB */
2655 name_len = strnlen(searchName, PATH_MAX);
2656 name_len++; /* trailing null */
2657 strncpy(pSMB->FileName, searchName, name_len);
2660 params = 12 + name_len /* includes null */ ;
2661 pSMB->TotalDataCount = 0; /* no EAs */
2662 pSMB->MaxParameterCount = cpu_to_le16(2);
2663 pSMB->MaxDataCount = cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
2664 pSMB->MaxSetupCount = 0;
2668 pSMB->Reserved2 = 0;
2669 pSMB->ParameterOffset = cpu_to_le16(
2670 offsetof(struct smb_com_transaction2_ffirst_req,InformationLevel) - 4);
2671 pSMB->DataCount = 0;
2672 pSMB->DataOffset = 0;
2673 pSMB->SetupCount = 1; /* one byte, no need to le convert */
2674 pSMB->Reserved3 = 0;
2675 pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_FIRST);
2676 byte_count = params + 1 /* pad */ ;
2677 pSMB->TotalParameterCount = cpu_to_le16(params);
2678 pSMB->ParameterCount = pSMB->TotalParameterCount;
2679 pSMB->SearchAttributes =
2680 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
2682 pSMB->SearchCount = cpu_to_le16(16); /* BB increase */
2683 pSMB->SearchFlags = cpu_to_le16(1);
2684 pSMB->InformationLevel = cpu_to_le16(SMB_FIND_FILE_DIRECTORY_INFO);
2685 pSMB->SearchStorageType = 0; /* BB what should we set this to? BB */
2686 pSMB->hdr.smb_buf_length += byte_count;
2687 pSMB->ByteCount = cpu_to_le16(byte_count);
2689 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2690 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2693 cFYI(1, ("Send error in FindFileDirInfo = %d", rc));
2694 } else { /* decode response */
2695 cifs_stats_inc(&tcon->num_ffirst);
2699 cifs_buf_release(pSMB);
2701 goto findUniqueRetry;
2705 #endif /* end unused (temporarily) function */
2707 /* xid, tcon, searchName and codepage are input parms, rest are returned */
2709 CIFSFindFirst(const int xid, struct cifsTconInfo *tcon,
2710 const char *searchName,
2711 const struct nls_table *nls_codepage,
2713 struct cifs_search_info * psrch_inf, int remap, const char dirsep)
2715 /* level 257 SMB_ */
2716 TRANSACTION2_FFIRST_REQ *pSMB = NULL;
2717 TRANSACTION2_FFIRST_RSP *pSMBr = NULL;
2718 T2_FFIRST_RSP_PARMS * parms;
2720 int bytes_returned = 0;
2722 __u16 params, byte_count;
2724 cFYI(1, ("In FindFirst for %s",searchName));
2727 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2732 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2734 cifsConvertToUCS((__le16 *) pSMB->FileName,searchName,
2735 PATH_MAX, nls_codepage, remap);
2736 /* We can not add the asterik earlier in case
2737 it got remapped to 0xF03A as if it were part of the
2738 directory name instead of a wildcard */
2740 pSMB->FileName[name_len] = dirsep;
2741 pSMB->FileName[name_len+1] = 0;
2742 pSMB->FileName[name_len+2] = '*';
2743 pSMB->FileName[name_len+3] = 0;
2744 name_len += 4; /* now the trailing null */
2745 pSMB->FileName[name_len] = 0; /* null terminate just in case */
2746 pSMB->FileName[name_len+1] = 0;
2748 } else { /* BB add check for overrun of SMB buf BB */
2749 name_len = strnlen(searchName, PATH_MAX);
2750 /* BB fix here and in unicode clause above ie
2751 if(name_len > buffersize-header)
2752 free buffer exit; BB */
2753 strncpy(pSMB->FileName, searchName, name_len);
2754 pSMB->FileName[name_len] = dirsep;
2755 pSMB->FileName[name_len+1] = '*';
2756 pSMB->FileName[name_len+2] = 0;
2760 params = 12 + name_len /* includes null */ ;
2761 pSMB->TotalDataCount = 0; /* no EAs */
2762 pSMB->MaxParameterCount = cpu_to_le16(10);
2763 pSMB->MaxDataCount = cpu_to_le16((tcon->ses->server->maxBuf -
2764 MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
2765 pSMB->MaxSetupCount = 0;
2769 pSMB->Reserved2 = 0;
2770 byte_count = params + 1 /* pad */ ;
2771 pSMB->TotalParameterCount = cpu_to_le16(params);
2772 pSMB->ParameterCount = pSMB->TotalParameterCount;
2773 pSMB->ParameterOffset = cpu_to_le16(
2774 offsetof(struct smb_com_transaction2_ffirst_req, SearchAttributes) - 4);
2775 pSMB->DataCount = 0;
2776 pSMB->DataOffset = 0;
2777 pSMB->SetupCount = 1; /* one byte, no need to make endian neutral */
2778 pSMB->Reserved3 = 0;
2779 pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_FIRST);
2780 pSMB->SearchAttributes =
2781 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
2783 pSMB->SearchCount= cpu_to_le16(CIFSMaxBufSize/sizeof(FILE_UNIX_INFO));
2784 pSMB->SearchFlags = cpu_to_le16(CIFS_SEARCH_CLOSE_AT_END |
2785 CIFS_SEARCH_RETURN_RESUME);
2786 pSMB->InformationLevel = cpu_to_le16(psrch_inf->info_level);
2788 /* BB what should we set StorageType to? Does it matter? BB */
2789 pSMB->SearchStorageType = 0;
2790 pSMB->hdr.smb_buf_length += byte_count;
2791 pSMB->ByteCount = cpu_to_le16(byte_count);
2793 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2794 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2795 cifs_stats_inc(&tcon->num_ffirst);
2797 if (rc) {/* BB add logic to retry regular search if Unix search rejected unexpectedly by server */
2798 /* BB Add code to handle unsupported level rc */
2799 cFYI(1, ("Error in FindFirst = %d", rc));
2802 cifs_buf_release(pSMB);
2804 /* BB eventually could optimize out free and realloc of buf */
2807 goto findFirstRetry;
2808 } else { /* decode response */
2809 /* BB remember to free buffer if error BB */
2810 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
2812 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
2813 psrch_inf->unicode = TRUE;
2815 psrch_inf->unicode = FALSE;
2817 psrch_inf->ntwrk_buf_start = (char *)pSMBr;
2818 psrch_inf->srch_entries_start =
2819 (char *) &pSMBr->hdr.Protocol +
2820 le16_to_cpu(pSMBr->t2.DataOffset);
2821 parms = (T2_FFIRST_RSP_PARMS *)((char *) &pSMBr->hdr.Protocol +
2822 le16_to_cpu(pSMBr->t2.ParameterOffset));
2824 if(parms->EndofSearch)
2825 psrch_inf->endOfSearch = TRUE;
2827 psrch_inf->endOfSearch = FALSE;
2829 psrch_inf->entries_in_buffer = le16_to_cpu(parms->SearchCount);
2830 psrch_inf->index_of_last_entry =
2831 psrch_inf->entries_in_buffer;
2832 *pnetfid = parms->SearchHandle;
2834 cifs_buf_release(pSMB);
2841 int CIFSFindNext(const int xid, struct cifsTconInfo *tcon,
2842 __u16 searchHandle, struct cifs_search_info * psrch_inf)
2844 TRANSACTION2_FNEXT_REQ *pSMB = NULL;
2845 TRANSACTION2_FNEXT_RSP *pSMBr = NULL;
2846 T2_FNEXT_RSP_PARMS * parms;
2847 char *response_data;
2849 int bytes_returned, name_len;
2850 __u16 params, byte_count;
2852 cFYI(1, ("In FindNext"));
2854 if(psrch_inf->endOfSearch == TRUE)
2857 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2862 params = 14; /* includes 2 bytes of null string, converted to LE below */
2864 pSMB->TotalDataCount = 0; /* no EAs */
2865 pSMB->MaxParameterCount = cpu_to_le16(8);
2866 pSMB->MaxDataCount =
2867 cpu_to_le16((tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
2868 pSMB->MaxSetupCount = 0;
2872 pSMB->Reserved2 = 0;
2873 pSMB->ParameterOffset = cpu_to_le16(
2874 offsetof(struct smb_com_transaction2_fnext_req,SearchHandle) - 4);
2875 pSMB->DataCount = 0;
2876 pSMB->DataOffset = 0;
2877 pSMB->SetupCount = 1;
2878 pSMB->Reserved3 = 0;
2879 pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_NEXT);
2880 pSMB->SearchHandle = searchHandle; /* always kept as le */
2882 cpu_to_le16(CIFSMaxBufSize / sizeof (FILE_UNIX_INFO));
2883 /* test for Unix extensions */
2884 /* if (tcon->ses->capabilities & CAP_UNIX) {
2885 pSMB->InformationLevel = cpu_to_le16(SMB_FIND_FILE_UNIX);
2886 psrch_inf->info_level = SMB_FIND_FILE_UNIX;
2888 pSMB->InformationLevel =
2889 cpu_to_le16(SMB_FIND_FILE_DIRECTORY_INFO);
2890 psrch_inf->info_level = SMB_FIND_FILE_DIRECTORY_INFO;
2892 pSMB->InformationLevel = cpu_to_le16(psrch_inf->info_level);
2893 pSMB->ResumeKey = psrch_inf->resume_key;
2895 cpu_to_le16(CIFS_SEARCH_CLOSE_AT_END | CIFS_SEARCH_RETURN_RESUME);
2897 name_len = psrch_inf->resume_name_len;
2899 if(name_len < PATH_MAX) {
2900 memcpy(pSMB->ResumeFileName, psrch_inf->presume_name, name_len);
2901 byte_count += name_len;
2902 /* 14 byte parm len above enough for 2 byte null terminator */
2903 pSMB->ResumeFileName[name_len] = 0;
2904 pSMB->ResumeFileName[name_len+1] = 0;
2907 goto FNext2_err_exit;
2909 byte_count = params + 1 /* pad */ ;
2910 pSMB->TotalParameterCount = cpu_to_le16(params);
2911 pSMB->ParameterCount = pSMB->TotalParameterCount;
2912 pSMB->hdr.smb_buf_length += byte_count;
2913 pSMB->ByteCount = cpu_to_le16(byte_count);
2915 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2916 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2917 cifs_stats_inc(&tcon->num_fnext);
2920 psrch_inf->endOfSearch = TRUE;
2921 rc = 0; /* search probably was closed at end of search above */
2923 cFYI(1, ("FindNext returned = %d", rc));
2924 } else { /* decode response */
2925 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
2928 /* BB fixme add lock for file (srch_info) struct here */
2929 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
2930 psrch_inf->unicode = TRUE;
2932 psrch_inf->unicode = FALSE;
2933 response_data = (char *) &pSMBr->hdr.Protocol +
2934 le16_to_cpu(pSMBr->t2.ParameterOffset);
2935 parms = (T2_FNEXT_RSP_PARMS *)response_data;
2936 response_data = (char *)&pSMBr->hdr.Protocol +
2937 le16_to_cpu(pSMBr->t2.DataOffset);
2938 cifs_buf_release(psrch_inf->ntwrk_buf_start);
2939 psrch_inf->srch_entries_start = response_data;
2940 psrch_inf->ntwrk_buf_start = (char *)pSMB;
2941 if(parms->EndofSearch)
2942 psrch_inf->endOfSearch = TRUE;
2944 psrch_inf->endOfSearch = FALSE;
2946 psrch_inf->entries_in_buffer = le16_to_cpu(parms->SearchCount);
2947 psrch_inf->index_of_last_entry +=
2948 psrch_inf->entries_in_buffer;
2949 /* cFYI(1,("fnxt2 entries in buf %d index_of_last %d",psrch_inf->entries_in_buffer,psrch_inf->index_of_last_entry)); */
2951 /* BB fixme add unlock here */
2956 /* BB On error, should we leave previous search buf (and count and
2957 last entry fields) intact or free the previous one? */
2959 /* Note: On -EAGAIN error only caller can retry on handle based calls
2960 since file handle passed in no longer valid */
2963 cifs_buf_release(pSMB);
2969 CIFSFindClose(const int xid, struct cifsTconInfo *tcon, const __u16 searchHandle)
2972 FINDCLOSE_REQ *pSMB = NULL;
2973 CLOSE_RSP *pSMBr = NULL; /* BB removeme BB */
2976 cFYI(1, ("In CIFSSMBFindClose"));
2977 rc = small_smb_init(SMB_COM_FIND_CLOSE2, 1, tcon, (void **)&pSMB);
2979 /* no sense returning error if session restarted
2980 as file handle has been closed */
2986 pSMBr = (CLOSE_RSP *)pSMB; /* BB removeme BB */
2987 pSMB->FileID = searchHandle;
2988 pSMB->ByteCount = 0;
2989 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2990 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2992 cERROR(1, ("Send error in FindClose = %d", rc));
2994 cifs_stats_inc(&tcon->num_fclose);
2995 cifs_small_buf_release(pSMB);
2997 /* Since session is dead, search handle closed on server already */
3004 #ifdef CONFIG_CIFS_EXPERIMENTAL
3006 CIFSGetSrvInodeNumber(const int xid, struct cifsTconInfo *tcon,
3007 const unsigned char *searchName,
3008 __u64 * inode_number,
3009 const struct nls_table *nls_codepage, int remap)
3012 TRANSACTION2_QPI_REQ *pSMB = NULL;
3013 TRANSACTION2_QPI_RSP *pSMBr = NULL;
3014 int name_len, bytes_returned;
3015 __u16 params, byte_count;
3017 cFYI(1,("In GetSrvInodeNum for %s",searchName));
3021 GetInodeNumberRetry:
3022 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3028 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3030 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
3031 PATH_MAX,nls_codepage, remap);
3032 name_len++; /* trailing null */
3034 } else { /* BB improve the check for buffer overruns BB */
3035 name_len = strnlen(searchName, PATH_MAX);
3036 name_len++; /* trailing null */
3037 strncpy(pSMB->FileName, searchName, name_len);
3040 params = 2 /* level */ + 4 /* rsrvd */ + name_len /* incl null */ ;
3041 pSMB->TotalDataCount = 0;
3042 pSMB->MaxParameterCount = cpu_to_le16(2);
3043 /* BB find exact max data count below from sess structure BB */
3044 pSMB->MaxDataCount = cpu_to_le16(4000);
3045 pSMB->MaxSetupCount = 0;
3049 pSMB->Reserved2 = 0;
3050 pSMB->ParameterOffset = cpu_to_le16(offsetof(
3051 struct smb_com_transaction2_qpi_req ,InformationLevel) - 4);
3052 pSMB->DataCount = 0;
3053 pSMB->DataOffset = 0;
3054 pSMB->SetupCount = 1;
3055 pSMB->Reserved3 = 0;
3056 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
3057 byte_count = params + 1 /* pad */ ;
3058 pSMB->TotalParameterCount = cpu_to_le16(params);
3059 pSMB->ParameterCount = pSMB->TotalParameterCount;
3060 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_INTERNAL_INFO);
3061 pSMB->Reserved4 = 0;
3062 pSMB->hdr.smb_buf_length += byte_count;
3063 pSMB->ByteCount = cpu_to_le16(byte_count);
3065 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3066 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3068 cFYI(1, ("error %d in QueryInternalInfo", rc));
3070 /* decode response */
3071 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3072 if (rc || (pSMBr->ByteCount < 2))
3073 /* BB also check enough total bytes returned */
3074 /* If rc should we check for EOPNOSUPP and
3075 disable the srvino flag? or in caller? */
3076 rc = -EIO; /* bad smb */
3078 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3079 __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
3080 struct file_internal_info * pfinfo;
3081 /* BB Do we need a cast or hash here ? */
3083 cFYI(1, ("Illegal size ret in QryIntrnlInf"));
3085 goto GetInodeNumOut;
3087 pfinfo = (struct file_internal_info *)
3088 (data_offset + (char *) &pSMBr->hdr.Protocol);
3089 *inode_number = pfinfo->UniqueId;
3093 cifs_buf_release(pSMB);
3095 goto GetInodeNumberRetry;
3098 #endif /* CIFS_EXPERIMENTAL */
3101 CIFSGetDFSRefer(const int xid, struct cifsSesInfo *ses,
3102 const unsigned char *searchName,
3103 unsigned char **targetUNCs,
3104 unsigned int *number_of_UNC_in_array,
3105 const struct nls_table *nls_codepage, int remap)
3107 /* TRANS2_GET_DFS_REFERRAL */
3108 TRANSACTION2_GET_DFS_REFER_REQ *pSMB = NULL;
3109 TRANSACTION2_GET_DFS_REFER_RSP *pSMBr = NULL;
3110 struct dfs_referral_level_3 * referrals = NULL;
3116 __u16 params, byte_count;
3117 *number_of_UNC_in_array = 0;
3120 cFYI(1, ("In GetDFSRefer the path %s", searchName));
3124 rc = smb_init(SMB_COM_TRANSACTION2, 15, NULL, (void **) &pSMB,
3129 /* server pointer checked in called function,
3130 but should never be null here anyway */
3131 pSMB->hdr.Mid = GetNextMid(ses->server);
3132 pSMB->hdr.Tid = ses->ipc_tid;
3133 pSMB->hdr.Uid = ses->Suid;
3134 if (ses->capabilities & CAP_STATUS32) {
3135 pSMB->hdr.Flags2 |= SMBFLG2_ERR_STATUS;
3137 if (ses->capabilities & CAP_DFS) {
3138 pSMB->hdr.Flags2 |= SMBFLG2_DFS;
3141 if (ses->capabilities & CAP_UNICODE) {
3142 pSMB->hdr.Flags2 |= SMBFLG2_UNICODE;
3144 cifsConvertToUCS((__le16 *) pSMB->RequestFileName,
3145 searchName, PATH_MAX, nls_codepage, remap);
3146 name_len++; /* trailing null */
3148 } else { /* BB improve the check for buffer overruns BB */
3149 name_len = strnlen(searchName, PATH_MAX);
3150 name_len++; /* trailing null */
3151 strncpy(pSMB->RequestFileName, searchName, name_len);
3154 params = 2 /* level */ + name_len /*includes null */ ;
3155 pSMB->TotalDataCount = 0;
3156 pSMB->DataCount = 0;
3157 pSMB->DataOffset = 0;
3158 pSMB->MaxParameterCount = 0;
3159 pSMB->MaxDataCount = cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
3160 pSMB->MaxSetupCount = 0;
3164 pSMB->Reserved2 = 0;
3165 pSMB->ParameterOffset = cpu_to_le16(offsetof(
3166 struct smb_com_transaction2_get_dfs_refer_req, MaxReferralLevel) - 4);
3167 pSMB->SetupCount = 1;
3168 pSMB->Reserved3 = 0;
3169 pSMB->SubCommand = cpu_to_le16(TRANS2_GET_DFS_REFERRAL);
3170 byte_count = params + 3 /* pad */ ;
3171 pSMB->ParameterCount = cpu_to_le16(params);
3172 pSMB->TotalParameterCount = pSMB->ParameterCount;
3173 pSMB->MaxReferralLevel = cpu_to_le16(3);
3174 pSMB->hdr.smb_buf_length += byte_count;
3175 pSMB->ByteCount = cpu_to_le16(byte_count);
3177 rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB,
3178 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3180 cFYI(1, ("Send error in GetDFSRefer = %d", rc));
3181 } else { /* decode response */
3182 /* BB Add logic to parse referrals here */
3183 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3185 if (rc || (pSMBr->ByteCount < 17)) /* BB also check enough total bytes returned */
3186 rc = -EIO; /* bad smb */
3188 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3189 __u16 data_count = le16_to_cpu(pSMBr->t2.DataCount);
3192 ("Decoding GetDFSRefer response. BCC: %d Offset %d",
3193 pSMBr->ByteCount, data_offset));
3195 (struct dfs_referral_level_3 *)
3196 (8 /* sizeof start of data block */ +
3198 (char *) &pSMBr->hdr.Protocol);
3199 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",
3200 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)));
3201 /* BB This field is actually two bytes in from start of
3202 data block so we could do safety check that DataBlock
3203 begins at address of pSMBr->NumberOfReferrals */
3204 *number_of_UNC_in_array = le16_to_cpu(pSMBr->NumberOfReferrals);
3206 /* BB Fix below so can return more than one referral */
3207 if(*number_of_UNC_in_array > 1)
3208 *number_of_UNC_in_array = 1;
3210 /* get the length of the strings describing refs */
3212 for(i=0;i<*number_of_UNC_in_array;i++) {
3213 /* make sure that DfsPathOffset not past end */
3214 __u16 offset = le16_to_cpu(referrals->DfsPathOffset);
3215 if (offset > data_count) {
3216 /* if invalid referral, stop here and do
3217 not try to copy any more */
3218 *number_of_UNC_in_array = i;
3221 temp = ((char *)referrals) + offset;
3223 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
3224 name_len += UniStrnlen((wchar_t *)temp,data_count);
3226 name_len += strnlen(temp,data_count);
3229 /* BB add check that referral pointer does not fall off end PDU */
3232 /* BB add check for name_len bigger than bcc */
3234 kmalloc(name_len+1+ (*number_of_UNC_in_array),GFP_KERNEL);
3235 if(*targetUNCs == NULL) {
3239 /* copy the ref strings */
3241 (struct dfs_referral_level_3 *)
3242 (8 /* sizeof data hdr */ +
3244 (char *) &pSMBr->hdr.Protocol);
3246 for(i=0;i<*number_of_UNC_in_array;i++) {
3247 temp = ((char *)referrals) + le16_to_cpu(referrals->DfsPathOffset);
3248 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
3249 cifs_strfromUCS_le(*targetUNCs,
3250 (wchar_t *) temp, name_len, nls_codepage);
3252 strncpy(*targetUNCs,temp,name_len);
3254 /* BB update target_uncs pointers */
3264 cifs_buf_release(pSMB);
3273 CIFSSMBQFSInfo(const int xid, struct cifsTconInfo *tcon, struct kstatfs *FSData)
3275 /* level 0x103 SMB_QUERY_FILE_SYSTEM_INFO */
3276 TRANSACTION2_QFSI_REQ *pSMB = NULL;
3277 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
3278 FILE_SYSTEM_INFO *response_data;
3280 int bytes_returned = 0;
3281 __u16 params, byte_count;
3283 cFYI(1, ("In QFSInfo"));
3285 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3290 params = 2; /* level */
3291 pSMB->TotalDataCount = 0;
3292 pSMB->MaxParameterCount = cpu_to_le16(2);
3293 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
3294 pSMB->MaxSetupCount = 0;
3298 pSMB->Reserved2 = 0;
3299 byte_count = params + 1 /* pad */ ;
3300 pSMB->TotalParameterCount = cpu_to_le16(params);
3301 pSMB->ParameterCount = pSMB->TotalParameterCount;
3302 pSMB->ParameterOffset = cpu_to_le16(offsetof(
3303 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
3304 pSMB->DataCount = 0;
3305 pSMB->DataOffset = 0;
3306 pSMB->SetupCount = 1;
3307 pSMB->Reserved3 = 0;
3308 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
3309 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_SIZE_INFO);
3310 pSMB->hdr.smb_buf_length += byte_count;
3311 pSMB->ByteCount = cpu_to_le16(byte_count);
3313 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3314 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3316 cERROR(1, ("Send error in QFSInfo = %d", rc));
3317 } else { /* decode response */
3318 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3320 if (rc || (pSMBr->ByteCount < 24)) /* BB alsO CHEck enough total bytes returned */
3321 rc = -EIO; /* bad smb */
3323 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3325 ("Decoding qfsinfo response. BCC: %d Offset %d",
3326 pSMBr->ByteCount, data_offset));
3330 *) (((char *) &pSMBr->hdr.Protocol) +
3333 le32_to_cpu(response_data->BytesPerSector) *
3334 le32_to_cpu(response_data->
3335 SectorsPerAllocationUnit);
3337 le64_to_cpu(response_data->TotalAllocationUnits);
3338 FSData->f_bfree = FSData->f_bavail =
3339 le64_to_cpu(response_data->FreeAllocationUnits);
3341 ("Blocks: %lld Free: %lld Block size %ld",
3342 (unsigned long long)FSData->f_blocks,
3343 (unsigned long long)FSData->f_bfree,
3347 cifs_buf_release(pSMB);
3356 CIFSSMBQFSAttributeInfo(const int xid, struct cifsTconInfo *tcon)
3358 /* level 0x105 SMB_QUERY_FILE_SYSTEM_INFO */
3359 TRANSACTION2_QFSI_REQ *pSMB = NULL;
3360 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
3361 FILE_SYSTEM_ATTRIBUTE_INFO *response_data;
3363 int bytes_returned = 0;
3364 __u16 params, byte_count;
3366 cFYI(1, ("In QFSAttributeInfo"));
3368 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3373 params = 2; /* level */
3374 pSMB->TotalDataCount = 0;
3375 pSMB->MaxParameterCount = cpu_to_le16(2);
3376 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
3377 pSMB->MaxSetupCount = 0;
3381 pSMB->Reserved2 = 0;
3382 byte_count = params + 1 /* pad */ ;
3383 pSMB->TotalParameterCount = cpu_to_le16(params);
3384 pSMB->ParameterCount = pSMB->TotalParameterCount;
3385 pSMB->ParameterOffset = cpu_to_le16(offsetof(
3386 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
3387 pSMB->DataCount = 0;
3388 pSMB->DataOffset = 0;
3389 pSMB->SetupCount = 1;
3390 pSMB->Reserved3 = 0;
3391 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
3392 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_ATTRIBUTE_INFO);
3393 pSMB->hdr.smb_buf_length += byte_count;
3394 pSMB->ByteCount = cpu_to_le16(byte_count);
3396 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3397 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3399 cERROR(1, ("Send error in QFSAttributeInfo = %d", rc));
3400 } else { /* decode response */
3401 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3403 if (rc || (pSMBr->ByteCount < 13)) { /* BB also check enough bytes returned */
3404 rc = -EIO; /* bad smb */
3406 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3408 (FILE_SYSTEM_ATTRIBUTE_INFO
3409 *) (((char *) &pSMBr->hdr.Protocol) +
3411 memcpy(&tcon->fsAttrInfo, response_data,
3412 sizeof (FILE_SYSTEM_ATTRIBUTE_INFO));
3415 cifs_buf_release(pSMB);
3418 goto QFSAttributeRetry;
3424 CIFSSMBQFSDeviceInfo(const int xid, struct cifsTconInfo *tcon)
3426 /* level 0x104 SMB_QUERY_FILE_SYSTEM_INFO */
3427 TRANSACTION2_QFSI_REQ *pSMB = NULL;
3428 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
3429 FILE_SYSTEM_DEVICE_INFO *response_data;
3431 int bytes_returned = 0;
3432 __u16 params, byte_count;
3434 cFYI(1, ("In QFSDeviceInfo"));
3436 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3441 params = 2; /* level */
3442 pSMB->TotalDataCount = 0;
3443 pSMB->MaxParameterCount = cpu_to_le16(2);
3444 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
3445 pSMB->MaxSetupCount = 0;
3449 pSMB->Reserved2 = 0;
3450 byte_count = params + 1 /* pad */ ;
3451 pSMB->TotalParameterCount = cpu_to_le16(params);
3452 pSMB->ParameterCount = pSMB->TotalParameterCount;
3453 pSMB->ParameterOffset = cpu_to_le16(offsetof(
3454 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
3456 pSMB->DataCount = 0;
3457 pSMB->DataOffset = 0;
3458 pSMB->SetupCount = 1;
3459 pSMB->Reserved3 = 0;
3460 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
3461 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_DEVICE_INFO);
3462 pSMB->hdr.smb_buf_length += byte_count;
3463 pSMB->ByteCount = cpu_to_le16(byte_count);
3465 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3466 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3468 cFYI(1, ("Send error in QFSDeviceInfo = %d", rc));
3469 } else { /* decode response */
3470 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3472 if (rc || (pSMBr->ByteCount < sizeof (FILE_SYSTEM_DEVICE_INFO)))
3473 rc = -EIO; /* bad smb */
3475 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3477 (FILE_SYSTEM_DEVICE_INFO *)
3478 (((char *) &pSMBr->hdr.Protocol) +
3480 memcpy(&tcon->fsDevInfo, response_data,
3481 sizeof (FILE_SYSTEM_DEVICE_INFO));
3484 cifs_buf_release(pSMB);
3487 goto QFSDeviceRetry;
3493 CIFSSMBQFSUnixInfo(const int xid, struct cifsTconInfo *tcon)
3495 /* level 0x200 SMB_QUERY_CIFS_UNIX_INFO */
3496 TRANSACTION2_QFSI_REQ *pSMB = NULL;
3497 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
3498 FILE_SYSTEM_UNIX_INFO *response_data;
3500 int bytes_returned = 0;
3501 __u16 params, byte_count;
3503 cFYI(1, ("In QFSUnixInfo"));
3505 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3510 params = 2; /* level */
3511 pSMB->TotalDataCount = 0;
3512 pSMB->DataCount = 0;
3513 pSMB->DataOffset = 0;
3514 pSMB->MaxParameterCount = cpu_to_le16(2);
3515 pSMB->MaxDataCount = cpu_to_le16(100); /* BB find exact max SMB PDU from sess structure BB */
3516 pSMB->MaxSetupCount = 0;
3520 pSMB->Reserved2 = 0;
3521 byte_count = params + 1 /* pad */ ;
3522 pSMB->ParameterCount = cpu_to_le16(params);
3523 pSMB->TotalParameterCount = pSMB->ParameterCount;
3524 pSMB->ParameterOffset = cpu_to_le16(offsetof(struct
3525 smb_com_transaction2_qfsi_req, InformationLevel) - 4);
3526 pSMB->SetupCount = 1;
3527 pSMB->Reserved3 = 0;
3528 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
3529 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_CIFS_UNIX_INFO);
3530 pSMB->hdr.smb_buf_length += byte_count;
3531 pSMB->ByteCount = cpu_to_le16(byte_count);
3533 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3534 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3536 cERROR(1, ("Send error in QFSUnixInfo = %d", rc));
3537 } else { /* decode response */
3538 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3540 if (rc || (pSMBr->ByteCount < 13)) {
3541 rc = -EIO; /* bad smb */
3543 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3545 (FILE_SYSTEM_UNIX_INFO
3546 *) (((char *) &pSMBr->hdr.Protocol) +
3548 memcpy(&tcon->fsUnixInfo, response_data,
3549 sizeof (FILE_SYSTEM_UNIX_INFO));
3552 cifs_buf_release(pSMB);
3562 CIFSSMBSetFSUnixInfo(const int xid, struct cifsTconInfo *tcon, __u64 cap)
3564 /* level 0x200 SMB_SET_CIFS_UNIX_INFO */
3565 TRANSACTION2_SETFSI_REQ *pSMB = NULL;
3566 TRANSACTION2_SETFSI_RSP *pSMBr = NULL;
3568 int bytes_returned = 0;
3569 __u16 params, param_offset, offset, byte_count;
3571 cFYI(1, ("In SETFSUnixInfo"));
3573 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3578 params = 4; /* 2 bytes zero followed by info level. */
3579 pSMB->MaxSetupCount = 0;
3583 pSMB->Reserved2 = 0;
3584 param_offset = offsetof(struct smb_com_transaction2_setfsi_req, FileNum) - 4;
3585 offset = param_offset + params;
3587 pSMB->MaxParameterCount = cpu_to_le16(4);
3588 pSMB->MaxDataCount = cpu_to_le16(100); /* BB find exact max SMB PDU from sess structure BB */
3589 pSMB->SetupCount = 1;
3590 pSMB->Reserved3 = 0;
3591 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FS_INFORMATION);
3592 byte_count = 1 /* pad */ + params + 12;
3594 pSMB->DataCount = cpu_to_le16(12);
3595 pSMB->ParameterCount = cpu_to_le16(params);
3596 pSMB->TotalDataCount = pSMB->DataCount;
3597 pSMB->TotalParameterCount = pSMB->ParameterCount;
3598 pSMB->ParameterOffset = cpu_to_le16(param_offset);
3599 pSMB->DataOffset = cpu_to_le16(offset);
3603 pSMB->InformationLevel = cpu_to_le16(SMB_SET_CIFS_UNIX_INFO);
3606 pSMB->ClientUnixMajor = cpu_to_le16(CIFS_UNIX_MAJOR_VERSION);
3607 pSMB->ClientUnixMinor = cpu_to_le16(CIFS_UNIX_MINOR_VERSION);
3608 pSMB->ClientUnixCap = cpu_to_le64(cap);
3610 pSMB->hdr.smb_buf_length += byte_count;
3611 pSMB->ByteCount = cpu_to_le16(byte_count);
3613 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3614 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3616 cERROR(1, ("Send error in SETFSUnixInfo = %d", rc));
3617 } else { /* decode response */
3618 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3620 rc = -EIO; /* bad smb */
3623 cifs_buf_release(pSMB);
3626 goto SETFSUnixRetry;
3634 CIFSSMBQFSPosixInfo(const int xid, struct cifsTconInfo *tcon,
3635 struct kstatfs *FSData)
3637 /* level 0x201 SMB_QUERY_CIFS_POSIX_INFO */
3638 TRANSACTION2_QFSI_REQ *pSMB = NULL;
3639 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
3640 FILE_SYSTEM_POSIX_INFO *response_data;
3642 int bytes_returned = 0;
3643 __u16 params, byte_count;
3645 cFYI(1, ("In QFSPosixInfo"));
3647 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3652 params = 2; /* level */
3653 pSMB->TotalDataCount = 0;
3654 pSMB->DataCount = 0;
3655 pSMB->DataOffset = 0;
3656 pSMB->MaxParameterCount = cpu_to_le16(2);
3657 pSMB->MaxDataCount = cpu_to_le16(100); /* BB find exact max SMB PDU from sess structure BB */
3658 pSMB->MaxSetupCount = 0;
3662 pSMB->Reserved2 = 0;
3663 byte_count = params + 1 /* pad */ ;
3664 pSMB->ParameterCount = cpu_to_le16(params);
3665 pSMB->TotalParameterCount = pSMB->ParameterCount;
3666 pSMB->ParameterOffset = cpu_to_le16(offsetof(struct
3667 smb_com_transaction2_qfsi_req, InformationLevel) - 4);
3668 pSMB->SetupCount = 1;
3669 pSMB->Reserved3 = 0;
3670 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
3671 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_POSIX_FS_INFO);
3672 pSMB->hdr.smb_buf_length += byte_count;
3673 pSMB->ByteCount = cpu_to_le16(byte_count);
3675 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3676 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3678 cFYI(1, ("Send error in QFSUnixInfo = %d", rc));
3679 } else { /* decode response */
3680 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3682 if (rc || (pSMBr->ByteCount < 13)) {
3683 rc = -EIO; /* bad smb */
3685 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3687 (FILE_SYSTEM_POSIX_INFO
3688 *) (((char *) &pSMBr->hdr.Protocol) +
3691 le32_to_cpu(response_data->BlockSize);
3693 le64_to_cpu(response_data->TotalBlocks);
3695 le64_to_cpu(response_data->BlocksAvail);
3696 if(response_data->UserBlocksAvail == -1) {
3697 FSData->f_bavail = FSData->f_bfree;
3700 le64_to_cpu(response_data->UserBlocksAvail);
3702 if(response_data->TotalFileNodes != -1)
3704 le64_to_cpu(response_data->TotalFileNodes);
3705 if(response_data->FreeFileNodes != -1)
3707 le64_to_cpu(response_data->FreeFileNodes);
3710 cifs_buf_release(pSMB);
3719 /* We can not use write of zero bytes trick to
3720 set file size due to need for large file support. Also note that
3721 this SetPathInfo is preferred to SetFileInfo based method in next
3722 routine which is only needed to work around a sharing violation bug
3723 in Samba which this routine can run into */
3726 CIFSSMBSetEOF(const int xid, struct cifsTconInfo *tcon, const char *fileName,
3727 __u64 size, int SetAllocation,
3728 const struct nls_table *nls_codepage, int remap)
3730 struct smb_com_transaction2_spi_req *pSMB = NULL;
3731 struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
3732 struct file_end_of_file_info *parm_data;
3735 int bytes_returned = 0;
3736 __u16 params, byte_count, data_count, param_offset, offset;
3738 cFYI(1, ("In SetEOF"));
3740 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3745 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3747 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
3748 PATH_MAX, nls_codepage, remap);
3749 name_len++; /* trailing null */
3751 } else { /* BB improve the check for buffer overruns BB */
3752 name_len = strnlen(fileName, PATH_MAX);
3753 name_len++; /* trailing null */
3754 strncpy(pSMB->FileName, fileName, name_len);
3756 params = 6 + name_len;
3757 data_count = sizeof (struct file_end_of_file_info);
3758 pSMB->MaxParameterCount = cpu_to_le16(2);
3759 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB size from sess */
3760 pSMB->MaxSetupCount = 0;
3764 pSMB->Reserved2 = 0;
3765 param_offset = offsetof(struct smb_com_transaction2_spi_req,
3766 InformationLevel) - 4;
3767 offset = param_offset + params;
3769 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
3770 pSMB->InformationLevel =
3771 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2);
3773 pSMB->InformationLevel =
3774 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO);
3775 } else /* Set File Size */ {
3776 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
3777 pSMB->InformationLevel =
3778 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO2);
3780 pSMB->InformationLevel =
3781 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO);
3785 (struct file_end_of_file_info *) (((char *) &pSMB->hdr.Protocol) +
3787 pSMB->ParameterOffset = cpu_to_le16(param_offset);
3788 pSMB->DataOffset = cpu_to_le16(offset);
3789 pSMB->SetupCount = 1;
3790 pSMB->Reserved3 = 0;
3791 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
3792 byte_count = 3 /* pad */ + params + data_count;
3793 pSMB->DataCount = cpu_to_le16(data_count);
3794 pSMB->TotalDataCount = pSMB->DataCount;
3795 pSMB->ParameterCount = cpu_to_le16(params);
3796 pSMB->TotalParameterCount = pSMB->ParameterCount;
3797 pSMB->Reserved4 = 0;
3798 pSMB->hdr.smb_buf_length += byte_count;
3799 parm_data->FileSize = cpu_to_le64(size);
3800 pSMB->ByteCount = cpu_to_le16(byte_count);
3801 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3802 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3804 cFYI(1, ("SetPathInfo (file size) returned %d", rc));
3807 cifs_buf_release(pSMB);
3816 CIFSSMBSetFileSize(const int xid, struct cifsTconInfo *tcon, __u64 size,
3817 __u16 fid, __u32 pid_of_opener, int SetAllocation)
3819 struct smb_com_transaction2_sfi_req *pSMB = NULL;
3820 struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
3822 struct file_end_of_file_info *parm_data;
3824 int bytes_returned = 0;
3825 __u16 params, param_offset, offset, byte_count, count;
3827 cFYI(1, ("SetFileSize (via SetFileInfo) %lld",
3829 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
3834 pSMBr = (struct smb_com_transaction2_sfi_rsp *)pSMB;
3836 pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
3837 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));
3840 pSMB->MaxSetupCount = 0;
3844 pSMB->Reserved2 = 0;
3845 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
3846 offset = param_offset + params;
3848 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
3850 count = sizeof(struct file_end_of_file_info);
3851 pSMB->MaxParameterCount = cpu_to_le16(2);
3852 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB PDU from sess */
3853 pSMB->SetupCount = 1;
3854 pSMB->Reserved3 = 0;
3855 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
3856 byte_count = 3 /* pad */ + params + count;
3857 pSMB->DataCount = cpu_to_le16(count);
3858 pSMB->ParameterCount = cpu_to_le16(params);
3859 pSMB->TotalDataCount = pSMB->DataCount;
3860 pSMB->TotalParameterCount = pSMB->ParameterCount;
3861 pSMB->ParameterOffset = cpu_to_le16(param_offset);
3863 (struct file_end_of_file_info *) (((char *) &pSMB->hdr.Protocol) +
3865 pSMB->DataOffset = cpu_to_le16(offset);
3866 parm_data->FileSize = cpu_to_le64(size);
3869 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
3870 pSMB->InformationLevel =
3871 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2);
3873 pSMB->InformationLevel =
3874 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO);
3875 } else /* Set File Size */ {
3876 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
3877 pSMB->InformationLevel =
3878 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO2);
3880 pSMB->InformationLevel =
3881 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO);
3883 pSMB->Reserved4 = 0;
3884 pSMB->hdr.smb_buf_length += byte_count;
3885 pSMB->ByteCount = cpu_to_le16(byte_count);
3886 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3887 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3890 ("Send error in SetFileInfo (SetFileSize) = %d",
3895 cifs_small_buf_release(pSMB);
3897 /* Note: On -EAGAIN error only caller can retry on handle based calls
3898 since file handle passed in no longer valid */
3903 /* Some legacy servers such as NT4 require that the file times be set on
3904 an open handle, rather than by pathname - this is awkward due to
3905 potential access conflicts on the open, but it is unavoidable for these
3906 old servers since the only other choice is to go from 100 nanosecond DCE
3907 time and resort to the original setpathinfo level which takes the ancient
3908 DOS time format with 2 second granularity */
3910 CIFSSMBSetFileTimes(const int xid, struct cifsTconInfo *tcon, const FILE_BASIC_INFO * data,
3913 struct smb_com_transaction2_sfi_req *pSMB = NULL;
3914 struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
3917 int bytes_returned = 0;
3918 __u16 params, param_offset, offset, byte_count, count;
3920 cFYI(1, ("Set Times (via SetFileInfo)"));
3921 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
3926 pSMBr = (struct smb_com_transaction2_sfi_rsp *)pSMB;
3928 /* At this point there is no need to override the current pid
3929 with the pid of the opener, but that could change if we someday
3930 use an existing handle (rather than opening one on the fly) */
3931 /* pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
3932 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));*/
3935 pSMB->MaxSetupCount = 0;
3939 pSMB->Reserved2 = 0;
3940 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
3941 offset = param_offset + params;
3943 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
3945 count = sizeof (FILE_BASIC_INFO);
3946 pSMB->MaxParameterCount = cpu_to_le16(2);
3947 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB PDU from sess */
3948 pSMB->SetupCount = 1;
3949 pSMB->Reserved3 = 0;
3950 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
3951 byte_count = 3 /* pad */ + params + count;
3952 pSMB->DataCount = cpu_to_le16(count);
3953 pSMB->ParameterCount = cpu_to_le16(params);
3954 pSMB->TotalDataCount = pSMB->DataCount;
3955 pSMB->TotalParameterCount = pSMB->ParameterCount;
3956 pSMB->ParameterOffset = cpu_to_le16(param_offset);
3957 pSMB->DataOffset = cpu_to_le16(offset);
3959 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
3960 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO2);
3962 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO);
3963 pSMB->Reserved4 = 0;
3964 pSMB->hdr.smb_buf_length += byte_count;
3965 pSMB->ByteCount = cpu_to_le16(byte_count);
3966 memcpy(data_offset,data,sizeof(FILE_BASIC_INFO));
3967 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3968 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3970 cFYI(1,("Send error in Set Time (SetFileInfo) = %d",rc));
3973 cifs_small_buf_release(pSMB);
3975 /* Note: On -EAGAIN error only caller can retry on handle based calls
3976 since file handle passed in no longer valid */
3983 CIFSSMBSetTimes(const int xid, struct cifsTconInfo *tcon, const char *fileName,
3984 const FILE_BASIC_INFO * data,
3985 const struct nls_table *nls_codepage, int remap)
3987 TRANSACTION2_SPI_REQ *pSMB = NULL;
3988 TRANSACTION2_SPI_RSP *pSMBr = NULL;
3991 int bytes_returned = 0;
3993 __u16 params, param_offset, offset, byte_count, count;
3995 cFYI(1, ("In SetTimes"));
3998 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4003 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4005 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
4006 PATH_MAX, nls_codepage, remap);
4007 name_len++; /* trailing null */
4009 } else { /* BB improve the check for buffer overruns BB */
4010 name_len = strnlen(fileName, PATH_MAX);
4011 name_len++; /* trailing null */
4012 strncpy(pSMB->FileName, fileName, name_len);
4015 params = 6 + name_len;
4016 count = sizeof (FILE_BASIC_INFO);
4017 pSMB->MaxParameterCount = cpu_to_le16(2);
4018 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
4019 pSMB->MaxSetupCount = 0;
4023 pSMB->Reserved2 = 0;
4024 param_offset = offsetof(struct smb_com_transaction2_spi_req,
4025 InformationLevel) - 4;
4026 offset = param_offset + params;
4027 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
4028 pSMB->ParameterOffset = cpu_to_le16(param_offset);
4029 pSMB->DataOffset = cpu_to_le16(offset);
4030 pSMB->SetupCount = 1;
4031 pSMB->Reserved3 = 0;
4032 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
4033 byte_count = 3 /* pad */ + params + count;
4035 pSMB->DataCount = cpu_to_le16(count);
4036 pSMB->ParameterCount = cpu_to_le16(params);
4037 pSMB->TotalDataCount = pSMB->DataCount;
4038 pSMB->TotalParameterCount = pSMB->ParameterCount;
4039 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
4040 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO2);
4042 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO);
4043 pSMB->Reserved4 = 0;
4044 pSMB->hdr.smb_buf_length += byte_count;
4045 memcpy(data_offset, data, sizeof (FILE_BASIC_INFO));
4046 pSMB->ByteCount = cpu_to_le16(byte_count);
4047 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4048 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4050 cFYI(1, ("SetPathInfo (times) returned %d", rc));
4053 cifs_buf_release(pSMB);
4061 /* Can not be used to set time stamps yet (due to old DOS time format) */
4062 /* Can be used to set attributes */
4063 #if 0 /* Possibly not needed - since it turns out that strangely NT4 has a bug
4064 handling it anyway and NT4 was what we thought it would be needed for
4065 Do not delete it until we prove whether needed for Win9x though */
4067 CIFSSMBSetAttrLegacy(int xid, struct cifsTconInfo *tcon, char *fileName,
4068 __u16 dos_attrs, const struct nls_table *nls_codepage)
4070 SETATTR_REQ *pSMB = NULL;
4071 SETATTR_RSP *pSMBr = NULL;
4076 cFYI(1, ("In SetAttrLegacy"));
4079 rc = smb_init(SMB_COM_SETATTR, 8, tcon, (void **) &pSMB,
4084 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4086 ConvertToUCS((__le16 *) pSMB->fileName, fileName,
4087 PATH_MAX, nls_codepage);
4088 name_len++; /* trailing null */
4090 } else { /* BB improve the check for buffer overruns BB */
4091 name_len = strnlen(fileName, PATH_MAX);
4092 name_len++; /* trailing null */
4093 strncpy(pSMB->fileName, fileName, name_len);
4095 pSMB->attr = cpu_to_le16(dos_attrs);
4096 pSMB->BufferFormat = 0x04;
4097 pSMB->hdr.smb_buf_length += name_len + 1;
4098 pSMB->ByteCount = cpu_to_le16(name_len + 1);
4099 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4100 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4102 cFYI(1, ("Error in LegacySetAttr = %d", rc));
4105 cifs_buf_release(pSMB);
4108 goto SetAttrLgcyRetry;
4112 #endif /* temporarily unneeded SetAttr legacy function */
4115 CIFSSMBUnixSetPerms(const int xid, struct cifsTconInfo *tcon,
4116 char *fileName, __u64 mode, __u64 uid, __u64 gid,
4117 dev_t device, const struct nls_table *nls_codepage,
4120 TRANSACTION2_SPI_REQ *pSMB = NULL;
4121 TRANSACTION2_SPI_RSP *pSMBr = NULL;
4124 int bytes_returned = 0;
4125 FILE_UNIX_BASIC_INFO *data_offset;
4126 __u16 params, param_offset, offset, count, byte_count;
4128 cFYI(1, ("In SetUID/GID/Mode"));
4130 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4135 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4137 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
4138 PATH_MAX, nls_codepage, remap);
4139 name_len++; /* trailing null */
4141 } else { /* BB improve the check for buffer overruns BB */
4142 name_len = strnlen(fileName, PATH_MAX);
4143 name_len++; /* trailing null */
4144 strncpy(pSMB->FileName, fileName, name_len);
4147 params = 6 + name_len;
4148 count = sizeof (FILE_UNIX_BASIC_INFO);
4149 pSMB->MaxParameterCount = cpu_to_le16(2);
4150 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
4151 pSMB->MaxSetupCount = 0;
4155 pSMB->Reserved2 = 0;
4156 param_offset = offsetof(struct smb_com_transaction2_spi_req,
4157 InformationLevel) - 4;
4158 offset = param_offset + params;
4160 (FILE_UNIX_BASIC_INFO *) ((char *) &pSMB->hdr.Protocol +
4162 memset(data_offset, 0, count);
4163 pSMB->DataOffset = cpu_to_le16(offset);
4164 pSMB->ParameterOffset = cpu_to_le16(param_offset);
4165 pSMB->SetupCount = 1;
4166 pSMB->Reserved3 = 0;
4167 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
4168 byte_count = 3 /* pad */ + params + count;
4169 pSMB->ParameterCount = cpu_to_le16(params);
4170 pSMB->DataCount = cpu_to_le16(count);
4171 pSMB->TotalParameterCount = pSMB->ParameterCount;
4172 pSMB->TotalDataCount = pSMB->DataCount;
4173 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_BASIC);
4174 pSMB->Reserved4 = 0;
4175 pSMB->hdr.smb_buf_length += byte_count;
4176 data_offset->Uid = cpu_to_le64(uid);
4177 data_offset->Gid = cpu_to_le64(gid);
4178 /* better to leave device as zero when it is */
4179 data_offset->DevMajor = cpu_to_le64(MAJOR(device));
4180 data_offset->DevMinor = cpu_to_le64(MINOR(device));
4181 data_offset->Permissions = cpu_to_le64(mode);
4184 data_offset->Type = cpu_to_le32(UNIX_FILE);
4185 else if(S_ISDIR(mode))
4186 data_offset->Type = cpu_to_le32(UNIX_DIR);
4187 else if(S_ISLNK(mode))
4188 data_offset->Type = cpu_to_le32(UNIX_SYMLINK);
4189 else if(S_ISCHR(mode))
4190 data_offset->Type = cpu_to_le32(UNIX_CHARDEV);
4191 else if(S_ISBLK(mode))
4192 data_offset->Type = cpu_to_le32(UNIX_BLOCKDEV);
4193 else if(S_ISFIFO(mode))
4194 data_offset->Type = cpu_to_le32(UNIX_FIFO);
4195 else if(S_ISSOCK(mode))
4196 data_offset->Type = cpu_to_le32(UNIX_SOCKET);
4199 pSMB->ByteCount = cpu_to_le16(byte_count);
4200 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4201 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4203 cFYI(1, ("SetPathInfo (perms) returned %d", rc));
4207 cifs_buf_release(pSMB);
4213 int CIFSSMBNotify(const int xid, struct cifsTconInfo *tcon,
4214 const int notify_subdirs, const __u16 netfid,
4215 __u32 filter, struct file * pfile, int multishot,
4216 const struct nls_table *nls_codepage)
4219 struct smb_com_transaction_change_notify_req * pSMB = NULL;
4220 struct smb_com_transaction_change_notify_rsp * pSMBr = NULL;
4221 struct dir_notify_req *dnotify_req;
4224 cFYI(1, ("In CIFSSMBNotify for file handle %d",(int)netfid));
4225 rc = smb_init(SMB_COM_NT_TRANSACT, 23, tcon, (void **) &pSMB,
4230 pSMB->TotalParameterCount = 0 ;
4231 pSMB->TotalDataCount = 0;
4232 pSMB->MaxParameterCount = cpu_to_le32(2);
4233 /* BB find exact data count max from sess structure BB */
4234 pSMB->MaxDataCount = 0; /* same in little endian or be */
4235 pSMB->MaxSetupCount = 4;
4237 pSMB->ParameterOffset = 0;
4238 pSMB->DataCount = 0;
4239 pSMB->DataOffset = 0;
4240 pSMB->SetupCount = 4; /* single byte does not need le conversion */
4241 pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_NOTIFY_CHANGE);
4242 pSMB->ParameterCount = pSMB->TotalParameterCount;
4244 pSMB->WatchTree = 1; /* one byte - no le conversion needed */
4245 pSMB->Reserved2 = 0;
4246 pSMB->CompletionFilter = cpu_to_le32(filter);
4247 pSMB->Fid = netfid; /* file handle always le */
4248 pSMB->ByteCount = 0;
4250 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4251 (struct smb_hdr *) pSMBr, &bytes_returned, -1);
4253 cFYI(1, ("Error in Notify = %d", rc));
4255 /* Add file to outstanding requests */
4256 dnotify_req = (struct dir_notify_req *) kmalloc(
4257 sizeof(struct dir_notify_req), GFP_KERNEL);
4258 dnotify_req->Pid = pSMB->hdr.Pid;
4259 dnotify_req->PidHigh = pSMB->hdr.PidHigh;
4260 dnotify_req->Mid = pSMB->hdr.Mid;
4261 dnotify_req->Tid = pSMB->hdr.Tid;
4262 dnotify_req->Uid = pSMB->hdr.Uid;
4263 dnotify_req->netfid = netfid;
4264 dnotify_req->pfile = pfile;
4265 dnotify_req->filter = filter;
4266 dnotify_req->multishot = multishot;
4267 spin_lock(&GlobalMid_Lock);
4268 list_add_tail(&dnotify_req->lhead, &GlobalDnotifyReqList);
4269 spin_unlock(&GlobalMid_Lock);
4271 cifs_buf_release(pSMB);
4274 #ifdef CONFIG_CIFS_XATTR
4276 CIFSSMBQAllEAs(const int xid, struct cifsTconInfo *tcon,
4277 const unsigned char *searchName,
4278 char * EAData, size_t buf_size,
4279 const struct nls_table *nls_codepage, int remap)
4281 /* BB assumes one setup word */
4282 TRANSACTION2_QPI_REQ *pSMB = NULL;
4283 TRANSACTION2_QPI_RSP *pSMBr = NULL;
4287 struct fea * temp_fea;
4289 __u16 params, byte_count;
4291 cFYI(1, ("In Query All EAs path %s", searchName));
4293 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4298 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4300 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
4301 PATH_MAX, nls_codepage, remap);
4302 name_len++; /* trailing null */
4304 } else { /* BB improve the check for buffer overruns BB */
4305 name_len = strnlen(searchName, PATH_MAX);
4306 name_len++; /* trailing null */
4307 strncpy(pSMB->FileName, searchName, name_len);
4310 params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */ ;
4311 pSMB->TotalDataCount = 0;
4312 pSMB->MaxParameterCount = cpu_to_le16(2);
4313 pSMB->MaxDataCount = cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
4314 pSMB->MaxSetupCount = 0;
4318 pSMB->Reserved2 = 0;
4319 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4320 struct smb_com_transaction2_qpi_req ,InformationLevel) - 4);
4321 pSMB->DataCount = 0;
4322 pSMB->DataOffset = 0;
4323 pSMB->SetupCount = 1;
4324 pSMB->Reserved3 = 0;
4325 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
4326 byte_count = params + 1 /* pad */ ;
4327 pSMB->TotalParameterCount = cpu_to_le16(params);
4328 pSMB->ParameterCount = pSMB->TotalParameterCount;
4329 pSMB->InformationLevel = cpu_to_le16(SMB_INFO_QUERY_ALL_EAS);
4330 pSMB->Reserved4 = 0;
4331 pSMB->hdr.smb_buf_length += byte_count;
4332 pSMB->ByteCount = cpu_to_le16(byte_count);
4334 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4335 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4337 cFYI(1, ("Send error in QueryAllEAs = %d", rc));
4338 } else { /* decode response */
4339 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4341 /* BB also check enough total bytes returned */
4342 /* BB we need to improve the validity checking
4343 of these trans2 responses */
4344 if (rc || (pSMBr->ByteCount < 4))
4345 rc = -EIO; /* bad smb */
4346 /* else if (pFindData){
4347 memcpy((char *) pFindData,
4348 (char *) &pSMBr->hdr.Protocol +
4351 /* check that length of list is not more than bcc */
4352 /* check that each entry does not go beyond length
4354 /* check that each element of each entry does not
4355 go beyond end of list */
4356 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4357 struct fealist * ea_response_data;
4359 /* validate_trans2_offsets() */
4360 /* BB to check if(start of smb + data_offset > &bcc+ bcc)*/
4361 ea_response_data = (struct fealist *)
4362 (((char *) &pSMBr->hdr.Protocol) +
4364 name_len = le32_to_cpu(ea_response_data->list_len);
4365 cFYI(1,("ea length %d", name_len));
4367 /* returned EA size zeroed at top of function */
4368 cFYI(1,("empty EA list returned from server"));
4370 /* account for ea list len */
4372 temp_fea = ea_response_data->list;
4373 temp_ptr = (char *)temp_fea;
4374 while(name_len > 0) {
4378 rc += temp_fea->name_len;
4379 /* account for prefix user. and trailing null */
4381 if(rc<(int)buf_size) {
4382 memcpy(EAData,"user.",5);
4384 memcpy(EAData,temp_ptr,temp_fea->name_len);
4385 EAData+=temp_fea->name_len;
4386 /* null terminate name */
4388 EAData = EAData + 1;
4389 } else if(buf_size == 0) {
4390 /* skip copy - calc size only */
4392 /* stop before overrun buffer */
4396 name_len -= temp_fea->name_len;
4397 temp_ptr += temp_fea->name_len;
4398 /* account for trailing null */
4401 value_len = le16_to_cpu(temp_fea->value_len);
4402 name_len -= value_len;
4403 temp_ptr += value_len;
4404 /* BB check that temp_ptr is still within smb BB*/
4405 /* no trailing null to account for in value len */
4406 /* go on to next EA */
4407 temp_fea = (struct fea *)temp_ptr;
4413 cifs_buf_release(pSMB);
4420 ssize_t CIFSSMBQueryEA(const int xid,struct cifsTconInfo * tcon,
4421 const unsigned char * searchName,const unsigned char * ea_name,
4422 unsigned char * ea_value, size_t buf_size,
4423 const struct nls_table *nls_codepage, int remap)
4425 TRANSACTION2_QPI_REQ *pSMB = NULL;
4426 TRANSACTION2_QPI_RSP *pSMBr = NULL;
4430 struct fea * temp_fea;
4432 __u16 params, byte_count;
4434 cFYI(1, ("In Query EA path %s", searchName));
4436 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4441 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4443 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
4444 PATH_MAX, nls_codepage, remap);
4445 name_len++; /* trailing null */
4447 } else { /* BB improve the check for buffer overruns BB */
4448 name_len = strnlen(searchName, PATH_MAX);
4449 name_len++; /* trailing null */
4450 strncpy(pSMB->FileName, searchName, name_len);
4453 params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */ ;
4454 pSMB->TotalDataCount = 0;
4455 pSMB->MaxParameterCount = cpu_to_le16(2);
4456 pSMB->MaxDataCount = cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
4457 pSMB->MaxSetupCount = 0;
4461 pSMB->Reserved2 = 0;
4462 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4463 struct smb_com_transaction2_qpi_req ,InformationLevel) - 4);
4464 pSMB->DataCount = 0;
4465 pSMB->DataOffset = 0;
4466 pSMB->SetupCount = 1;
4467 pSMB->Reserved3 = 0;
4468 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
4469 byte_count = params + 1 /* pad */ ;
4470 pSMB->TotalParameterCount = cpu_to_le16(params);
4471 pSMB->ParameterCount = pSMB->TotalParameterCount;
4472 pSMB->InformationLevel = cpu_to_le16(SMB_INFO_QUERY_ALL_EAS);
4473 pSMB->Reserved4 = 0;
4474 pSMB->hdr.smb_buf_length += byte_count;
4475 pSMB->ByteCount = cpu_to_le16(byte_count);
4477 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4478 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4480 cFYI(1, ("Send error in Query EA = %d", rc));
4481 } else { /* decode response */
4482 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4484 /* BB also check enough total bytes returned */
4485 /* BB we need to improve the validity checking
4486 of these trans2 responses */
4487 if (rc || (pSMBr->ByteCount < 4))
4488 rc = -EIO; /* bad smb */
4489 /* else if (pFindData){
4490 memcpy((char *) pFindData,
4491 (char *) &pSMBr->hdr.Protocol +
4494 /* check that length of list is not more than bcc */
4495 /* check that each entry does not go beyond length
4497 /* check that each element of each entry does not
4498 go beyond end of list */
4499 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4500 struct fealist * ea_response_data;
4502 /* validate_trans2_offsets() */
4503 /* BB to check if(start of smb + data_offset > &bcc+ bcc)*/
4504 ea_response_data = (struct fealist *)
4505 (((char *) &pSMBr->hdr.Protocol) +
4507 name_len = le32_to_cpu(ea_response_data->list_len);
4508 cFYI(1,("ea length %d", name_len));
4510 /* returned EA size zeroed at top of function */
4511 cFYI(1,("empty EA list returned from server"));
4513 /* account for ea list len */
4515 temp_fea = ea_response_data->list;
4516 temp_ptr = (char *)temp_fea;
4517 /* loop through checking if we have a matching
4518 name and then return the associated value */
4519 while(name_len > 0) {
4523 value_len = le16_to_cpu(temp_fea->value_len);
4524 /* BB validate that value_len falls within SMB,
4525 even though maximum for name_len is 255 */
4526 if(memcmp(temp_fea->name,ea_name,
4527 temp_fea->name_len) == 0) {
4530 /* account for prefix user. and trailing null */
4531 if(rc<=(int)buf_size) {
4533 temp_fea->name+temp_fea->name_len+1,
4535 /* ea values, unlike ea names,
4536 are not null terminated */
4537 } else if(buf_size == 0) {
4538 /* skip copy - calc size only */
4540 /* stop before overrun buffer */
4545 name_len -= temp_fea->name_len;
4546 temp_ptr += temp_fea->name_len;
4547 /* account for trailing null */
4550 name_len -= value_len;
4551 temp_ptr += value_len;
4552 /* no trailing null to account for in value len */
4553 /* go on to next EA */
4554 temp_fea = (struct fea *)temp_ptr;
4560 cifs_buf_release(pSMB);
4568 CIFSSMBSetEA(const int xid, struct cifsTconInfo *tcon, const char *fileName,
4569 const char * ea_name, const void * ea_value,
4570 const __u16 ea_value_len, const struct nls_table *nls_codepage,
4573 struct smb_com_transaction2_spi_req *pSMB = NULL;
4574 struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
4575 struct fealist *parm_data;
4578 int bytes_returned = 0;
4579 __u16 params, param_offset, byte_count, offset, count;
4581 cFYI(1, ("In SetEA"));
4583 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4588 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4590 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
4591 PATH_MAX, nls_codepage, remap);
4592 name_len++; /* trailing null */
4594 } else { /* BB improve the check for buffer overruns BB */
4595 name_len = strnlen(fileName, PATH_MAX);
4596 name_len++; /* trailing null */
4597 strncpy(pSMB->FileName, fileName, name_len);
4600 params = 6 + name_len;
4602 /* done calculating parms using name_len of file name,
4603 now use name_len to calculate length of ea name
4604 we are going to create in the inode xattrs */
4608 name_len = strnlen(ea_name,255);
4610 count = sizeof(*parm_data) + ea_value_len + name_len + 1;
4611 pSMB->MaxParameterCount = cpu_to_le16(2);
4612 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB size from sess */
4613 pSMB->MaxSetupCount = 0;
4617 pSMB->Reserved2 = 0;
4618 param_offset = offsetof(struct smb_com_transaction2_spi_req,
4619 InformationLevel) - 4;
4620 offset = param_offset + params;
4621 pSMB->InformationLevel =
4622 cpu_to_le16(SMB_SET_FILE_EA);
4625 (struct fealist *) (((char *) &pSMB->hdr.Protocol) +
4627 pSMB->ParameterOffset = cpu_to_le16(param_offset);
4628 pSMB->DataOffset = cpu_to_le16(offset);
4629 pSMB->SetupCount = 1;
4630 pSMB->Reserved3 = 0;
4631 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
4632 byte_count = 3 /* pad */ + params + count;
4633 pSMB->DataCount = cpu_to_le16(count);
4634 parm_data->list_len = cpu_to_le32(count);
4635 parm_data->list[0].EA_flags = 0;
4636 /* we checked above that name len is less than 255 */
4637 parm_data->list[0].name_len = (__u8)name_len;;
4638 /* EA names are always ASCII */
4640 strncpy(parm_data->list[0].name,ea_name,name_len);
4641 parm_data->list[0].name[name_len] = 0;
4642 parm_data->list[0].value_len = cpu_to_le16(ea_value_len);
4643 /* caller ensures that ea_value_len is less than 64K but
4644 we need to ensure that it fits within the smb */
4646 /*BB add length check that it would fit in negotiated SMB buffer size BB */
4647 /* if(ea_value_len > buffer_size - 512 (enough for header)) */
4649 memcpy(parm_data->list[0].name+name_len+1,ea_value,ea_value_len);
4651 pSMB->TotalDataCount = pSMB->DataCount;
4652 pSMB->ParameterCount = cpu_to_le16(params);
4653 pSMB->TotalParameterCount = pSMB->ParameterCount;
4654 pSMB->Reserved4 = 0;
4655 pSMB->hdr.smb_buf_length += byte_count;
4656 pSMB->ByteCount = cpu_to_le16(byte_count);
4657 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4658 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4660 cFYI(1, ("SetPathInfo (EA) returned %d", rc));
4663 cifs_buf_release(pSMB);