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(0/*ATTR_NORMAL*/); /* BB FIXME */
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 */
781 pSMB->Sattr = cpu_to_le16(ATTR_HIDDEN | ATTR_SYSTEM | ATTR_DIRECTORY);
782 pSMB->OpenFunction = convert_disposition(openDisposition);
784 pSMB->hdr.smb_buf_length += count;
786 pSMB->ByteCount = cpu_to_le16(count);
787 /* long_op set to 1 to allow for oplock break timeouts */
788 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
789 (struct smb_hdr *) pSMBr, &bytes_returned, 1);
790 cifs_stats_inc(&tcon->num_opens);
792 cFYI(1, ("Error in Open = %d", rc));
794 /* BB verify if wct == 15 */
796 /* *pOplock = pSMBr->OplockLevel; */ /* BB take from action field BB */
798 *netfid = pSMBr->Fid; /* cifs fid stays in le */
799 /* Let caller know file was created so we can set the mode. */
800 /* Do we care about the CreateAction in any other cases? */
802 /* if(cpu_to_le32(FILE_CREATE) == pSMBr->CreateAction)
803 *pOplock |= CIFS_CREATE_ACTION; */
807 pfile_info->CreationTime = 0; /* BB convert CreateTime*/
808 pfile_info->LastAccessTime = 0; /* BB fixme */
809 pfile_info->LastWriteTime = 0; /* BB fixme */
810 pfile_info->ChangeTime = 0; /* BB fixme */
811 pfile_info->Attributes = pSMBr->FileAttributes;
812 /* the file_info buf is endian converted by caller */
813 pfile_info->AllocationSize = pSMBr->EndOfFile;
814 pfile_info->EndOfFile = pSMBr->EndOfFile;
815 pfile_info->NumberOfLinks = cpu_to_le32(1);
819 cifs_buf_release(pSMB);
826 CIFSSMBOpen(const int xid, struct cifsTconInfo *tcon,
827 const char *fileName, const int openDisposition,
828 const int access_flags, const int create_options, __u16 * netfid,
829 int *pOplock, FILE_ALL_INFO * pfile_info,
830 const struct nls_table *nls_codepage, int remap)
833 OPEN_REQ *pSMB = NULL;
834 OPEN_RSP *pSMBr = NULL;
840 rc = smb_init(SMB_COM_NT_CREATE_ANDX, 24, tcon, (void **) &pSMB,
845 pSMB->AndXCommand = 0xFF; /* none */
847 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
848 count = 1; /* account for one byte pad to word boundary */
850 cifsConvertToUCS((__le16 *) (pSMB->fileName + 1),
851 fileName, PATH_MAX, nls_codepage, remap);
852 name_len++; /* trailing null */
854 pSMB->NameLength = cpu_to_le16(name_len);
855 } else { /* BB improve check for buffer overruns BB */
856 count = 0; /* no pad */
857 name_len = strnlen(fileName, PATH_MAX);
858 name_len++; /* trailing null */
859 pSMB->NameLength = cpu_to_le16(name_len);
860 strncpy(pSMB->fileName, fileName, name_len);
862 if (*pOplock & REQ_OPLOCK)
863 pSMB->OpenFlags = cpu_to_le32(REQ_OPLOCK);
864 else if (*pOplock & REQ_BATCHOPLOCK) {
865 pSMB->OpenFlags = cpu_to_le32(REQ_BATCHOPLOCK);
867 pSMB->DesiredAccess = cpu_to_le32(access_flags);
868 pSMB->AllocationSize = 0;
869 /* set file as system file if special file such
870 as fifo and server expecting SFU style and
871 no Unix extensions */
872 if(create_options & CREATE_OPTION_SPECIAL)
873 pSMB->FileAttributes = cpu_to_le32(ATTR_SYSTEM);
875 pSMB->FileAttributes = cpu_to_le32(ATTR_NORMAL);
876 /* XP does not handle ATTR_POSIX_SEMANTICS */
877 /* but it helps speed up case sensitive checks for other
878 servers such as Samba */
879 if (tcon->ses->capabilities & CAP_UNIX)
880 pSMB->FileAttributes |= cpu_to_le32(ATTR_POSIX_SEMANTICS);
882 /* if ((omode & S_IWUGO) == 0)
883 pSMB->FileAttributes |= cpu_to_le32(ATTR_READONLY);*/
884 /* Above line causes problems due to vfs splitting create into two
885 pieces - need to set mode after file created not while it is
887 pSMB->ShareAccess = cpu_to_le32(FILE_SHARE_ALL);
888 pSMB->CreateDisposition = cpu_to_le32(openDisposition);
889 pSMB->CreateOptions = cpu_to_le32(create_options & CREATE_OPTIONS_MASK);
890 /* BB Expirement with various impersonation levels and verify */
891 pSMB->ImpersonationLevel = cpu_to_le32(SECURITY_IMPERSONATION);
892 pSMB->SecurityFlags =
893 SECURITY_CONTEXT_TRACKING | SECURITY_EFFECTIVE_ONLY;
896 pSMB->hdr.smb_buf_length += count;
898 pSMB->ByteCount = cpu_to_le16(count);
899 /* long_op set to 1 to allow for oplock break timeouts */
900 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
901 (struct smb_hdr *) pSMBr, &bytes_returned, 1);
902 cifs_stats_inc(&tcon->num_opens);
904 cFYI(1, ("Error in Open = %d", rc));
906 *pOplock = pSMBr->OplockLevel; /* 1 byte no need to le_to_cpu */
907 *netfid = pSMBr->Fid; /* cifs fid stays in le */
908 /* Let caller know file was created so we can set the mode. */
909 /* Do we care about the CreateAction in any other cases? */
910 if(cpu_to_le32(FILE_CREATE) == pSMBr->CreateAction)
911 *pOplock |= CIFS_CREATE_ACTION;
913 memcpy((char *)pfile_info,(char *)&pSMBr->CreationTime,
914 36 /* CreationTime to Attributes */);
915 /* the file_info buf is endian converted by caller */
916 pfile_info->AllocationSize = pSMBr->AllocationSize;
917 pfile_info->EndOfFile = pSMBr->EndOfFile;
918 pfile_info->NumberOfLinks = cpu_to_le32(1);
922 cifs_buf_release(pSMB);
928 /* If no buffer passed in, then caller wants to do the copy
929 as in the case of readpages so the SMB buffer must be
930 freed by the caller */
933 CIFSSMBRead(const int xid, struct cifsTconInfo *tcon,
934 const int netfid, const unsigned int count,
935 const __u64 lseek, unsigned int *nbytes, char **buf)
938 READ_REQ *pSMB = NULL;
939 READ_RSP *pSMBr = NULL;
940 char *pReadData = NULL;
944 cFYI(1,("Reading %d bytes on fid %d",count,netfid));
945 if(tcon->ses->capabilities & CAP_LARGE_FILES)
948 wct = 10; /* old style read */
951 rc = smb_init(SMB_COM_READ_ANDX, wct, tcon, (void **) &pSMB,
956 /* tcon and ses pointer are checked in smb_init */
957 if (tcon->ses->server == NULL)
958 return -ECONNABORTED;
960 pSMB->AndXCommand = 0xFF; /* none */
962 pSMB->OffsetLow = cpu_to_le32(lseek & 0xFFFFFFFF);
964 pSMB->OffsetHigh = cpu_to_le32(lseek >> 32);
965 else if((lseek >> 32) > 0) /* can not handle this big offset for old */
969 pSMB->MaxCount = cpu_to_le16(count & 0xFFFF);
970 pSMB->MaxCountHigh = cpu_to_le32(count >> 16);
972 pSMB->ByteCount = 0; /* no need to do le conversion since 0 */
975 struct smb_com_readx_req * pSMBW =
976 (struct smb_com_readx_req *)pSMB;
977 pSMBW->ByteCount = 0;
980 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
981 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
982 cifs_stats_inc(&tcon->num_reads);
984 cERROR(1, ("Send error in read = %d", rc));
986 int data_length = le16_to_cpu(pSMBr->DataLengthHigh);
987 data_length = data_length << 16;
988 data_length += le16_to_cpu(pSMBr->DataLength);
989 *nbytes = data_length;
991 /*check that DataLength would not go beyond end of SMB */
992 if ((data_length > CIFSMaxBufSize)
993 || (data_length > count)) {
994 cFYI(1,("bad length %d for count %d",data_length,count));
999 (char *) (&pSMBr->hdr.Protocol) +
1000 le16_to_cpu(pSMBr->DataOffset);
1001 /* if(rc = copy_to_user(buf, pReadData, data_length)) {
1002 cERROR(1,("Faulting on read rc = %d",rc));
1004 }*/ /* can not use copy_to_user when using page cache*/
1006 memcpy(*buf,pReadData,data_length);
1010 cifs_buf_release(pSMB);
1012 *buf = (char *)pSMB;
1014 /* Note: On -EAGAIN error only caller can retry on handle based calls
1015 since file handle passed in no longer valid */
1020 CIFSSMBWrite(const int xid, struct cifsTconInfo *tcon,
1021 const int netfid, const unsigned int count,
1022 const __u64 offset, unsigned int *nbytes, const char *buf,
1023 const char __user * ubuf, const int long_op)
1026 WRITE_REQ *pSMB = NULL;
1027 WRITE_RSP *pSMBr = NULL;
1028 int bytes_returned, wct;
1032 /* cFYI(1,("write at %lld %d bytes",offset,count));*/
1033 if(tcon->ses == NULL)
1034 return -ECONNABORTED;
1036 if(tcon->ses->capabilities & CAP_LARGE_FILES)
1041 rc = smb_init(SMB_COM_WRITE_ANDX, wct, tcon, (void **) &pSMB,
1045 /* tcon and ses pointer are checked in smb_init */
1046 if (tcon->ses->server == NULL)
1047 return -ECONNABORTED;
1049 pSMB->AndXCommand = 0xFF; /* none */
1051 pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF);
1053 pSMB->OffsetHigh = cpu_to_le32(offset >> 32);
1054 else if((offset >> 32) > 0) /* can not handle this big offset for old */
1057 pSMB->Reserved = 0xFFFFFFFF;
1058 pSMB->WriteMode = 0;
1059 pSMB->Remaining = 0;
1061 /* Can increase buffer size if buffer is big enough in some cases - ie we
1062 can send more if LARGE_WRITE_X capability returned by the server and if
1063 our buffer is big enough or if we convert to iovecs on socket writes
1064 and eliminate the copy to the CIFS buffer */
1065 if(tcon->ses->capabilities & CAP_LARGE_WRITE_X) {
1066 bytes_sent = min_t(const unsigned int, CIFSMaxBufSize, count);
1068 bytes_sent = (tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE)
1072 if (bytes_sent > count)
1075 cpu_to_le16(offsetof(struct smb_com_write_req,Data) - 4);
1077 memcpy(pSMB->Data,buf,bytes_sent);
1079 if(copy_from_user(pSMB->Data,ubuf,bytes_sent)) {
1080 cifs_buf_release(pSMB);
1083 } else if (count != 0) {
1085 cifs_buf_release(pSMB);
1087 } /* else setting file size with write of zero bytes */
1089 byte_count = bytes_sent + 1; /* pad */
1090 else /* wct == 12 */ {
1091 byte_count = bytes_sent + 5; /* bigger pad, smaller smb hdr */
1093 pSMB->DataLengthLow = cpu_to_le16(bytes_sent & 0xFFFF);
1094 pSMB->DataLengthHigh = cpu_to_le16(bytes_sent >> 16);
1095 pSMB->hdr.smb_buf_length += byte_count;
1098 pSMB->ByteCount = cpu_to_le16(byte_count);
1099 else { /* old style write has byte count 4 bytes earlier so 4 bytes pad */
1100 struct smb_com_writex_req * pSMBW =
1101 (struct smb_com_writex_req *)pSMB;
1102 pSMBW->ByteCount = cpu_to_le16(byte_count);
1105 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1106 (struct smb_hdr *) pSMBr, &bytes_returned, long_op);
1107 cifs_stats_inc(&tcon->num_writes);
1109 cFYI(1, ("Send error in write = %d", rc));
1112 *nbytes = le16_to_cpu(pSMBr->CountHigh);
1113 *nbytes = (*nbytes) << 16;
1114 *nbytes += le16_to_cpu(pSMBr->Count);
1117 cifs_buf_release(pSMB);
1119 /* Note: On -EAGAIN error only caller can retry on handle based calls
1120 since file handle passed in no longer valid */
1125 #ifdef CONFIG_CIFS_EXPERIMENTAL
1127 CIFSSMBWrite2(const int xid, struct cifsTconInfo *tcon,
1128 const int netfid, const unsigned int count,
1129 const __u64 offset, unsigned int *nbytes, const char *buf,
1133 WRITE_REQ *pSMB = NULL;
1139 cFYI(1,("write2 at %lld %d bytes",offset,count)); /* BB removeme BB */
1140 rc = small_smb_init(SMB_COM_WRITE_ANDX, 14, tcon, (void **) &pSMB);
1143 /* tcon and ses pointer are checked in smb_init */
1144 if (tcon->ses->server == NULL)
1145 return -ECONNABORTED;
1147 pSMB->AndXCommand = 0xFF; /* none */
1149 pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF);
1150 pSMB->OffsetHigh = cpu_to_le32(offset >> 32);
1151 pSMB->Reserved = 0xFFFFFFFF;
1152 pSMB->WriteMode = 0;
1153 pSMB->Remaining = 0;
1155 /* Can increase buffer size if buffer is big enough in some cases - ie
1156 can send more if LARGE_WRITE_X capability returned by the server and if
1157 our buffer is big enough or if we convert to iovecs on socket writes
1158 and eliminate the copy to the CIFS buffer */
1159 if(tcon->ses->capabilities & CAP_LARGE_WRITE_X) {
1160 bytes_sent = min_t(const unsigned int, CIFSMaxBufSize, count);
1162 bytes_sent = (tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE)
1166 if (bytes_sent > count)
1169 cpu_to_le16(offsetof(struct smb_com_write_req,Data) - 4);
1171 byte_count = bytes_sent + 1 /* pad */ ; /* BB fix this for sends > 64K */
1172 pSMB->DataLengthLow = cpu_to_le16(bytes_sent & 0xFFFF);
1173 pSMB->DataLengthHigh = cpu_to_le16(bytes_sent >> 16);
1174 smb_hdr_len = pSMB->hdr.smb_buf_length + 1; /* hdr + 1 byte pad */
1175 pSMB->hdr.smb_buf_length += bytes_sent+1;
1176 pSMB->ByteCount = cpu_to_le16(byte_count);
1178 rc = SendReceive2(xid, tcon->ses, (struct smb_hdr *) pSMB, smb_hdr_len,
1179 buf, bytes_sent, &bytes_returned, long_op);
1180 cifs_stats_inc(&tcon->num_writes);
1182 cFYI(1, ("Send error in write = %d", rc));
1185 WRITE_RSP * pSMBr = (WRITE_RSP *)pSMB;
1186 *nbytes = le16_to_cpu(pSMBr->CountHigh);
1187 *nbytes = (*nbytes) << 16;
1188 *nbytes += le16_to_cpu(pSMBr->Count);
1191 cifs_small_buf_release(pSMB);
1193 /* Note: On -EAGAIN error only caller can retry on handle based calls
1194 since file handle passed in no longer valid */
1200 #endif /* CIFS_EXPERIMENTAL */
1203 CIFSSMBLock(const int xid, struct cifsTconInfo *tcon,
1204 const __u16 smb_file_id, const __u64 len,
1205 const __u64 offset, const __u32 numUnlock,
1206 const __u32 numLock, const __u8 lockType, const int waitFlag)
1209 LOCK_REQ *pSMB = NULL;
1210 LOCK_RSP *pSMBr = NULL;
1215 cFYI(1, ("In CIFSSMBLock - timeout %d numLock %d",waitFlag,numLock));
1216 rc = small_smb_init(SMB_COM_LOCKING_ANDX, 8, tcon, (void **) &pSMB);
1221 pSMBr = (LOCK_RSP *)pSMB; /* BB removeme BB */
1223 if(lockType == LOCKING_ANDX_OPLOCK_RELEASE) {
1224 timeout = -1; /* no response expected */
1226 } else if (waitFlag == TRUE) {
1227 timeout = 3; /* blocking operation, no timeout */
1228 pSMB->Timeout = cpu_to_le32(-1);/* blocking - do not time out */
1233 pSMB->NumberOfLocks = cpu_to_le16(numLock);
1234 pSMB->NumberOfUnlocks = cpu_to_le16(numUnlock);
1235 pSMB->LockType = lockType;
1236 pSMB->AndXCommand = 0xFF; /* none */
1237 pSMB->Fid = smb_file_id; /* netfid stays le */
1239 if((numLock != 0) || (numUnlock != 0)) {
1240 pSMB->Locks[0].Pid = cpu_to_le16(current->tgid);
1241 /* BB where to store pid high? */
1242 pSMB->Locks[0].LengthLow = cpu_to_le32((u32)len);
1243 pSMB->Locks[0].LengthHigh = cpu_to_le32((u32)(len>>32));
1244 pSMB->Locks[0].OffsetLow = cpu_to_le32((u32)offset);
1245 pSMB->Locks[0].OffsetHigh = cpu_to_le32((u32)(offset>>32));
1246 count = sizeof(LOCKING_ANDX_RANGE);
1251 pSMB->hdr.smb_buf_length += count;
1252 pSMB->ByteCount = cpu_to_le16(count);
1254 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1255 (struct smb_hdr *) pSMBr, &bytes_returned, timeout);
1256 cifs_stats_inc(&tcon->num_locks);
1258 cFYI(1, ("Send error in Lock = %d", rc));
1260 cifs_small_buf_release(pSMB);
1262 /* Note: On -EAGAIN error only caller can retry on handle based calls
1263 since file handle passed in no longer valid */
1268 CIFSSMBClose(const int xid, struct cifsTconInfo *tcon, int smb_file_id)
1271 CLOSE_REQ *pSMB = NULL;
1272 CLOSE_RSP *pSMBr = NULL;
1274 cFYI(1, ("In CIFSSMBClose"));
1276 /* do not retry on dead session on close */
1277 rc = small_smb_init(SMB_COM_CLOSE, 3, tcon, (void **) &pSMB);
1283 pSMBr = (CLOSE_RSP *)pSMB; /* BB removeme BB */
1285 pSMB->FileID = (__u16) smb_file_id;
1286 pSMB->LastWriteTime = 0;
1287 pSMB->ByteCount = 0;
1288 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1289 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1290 cifs_stats_inc(&tcon->num_closes);
1293 /* EINTR is expected when user ctl-c to kill app */
1294 cERROR(1, ("Send error in Close = %d", rc));
1298 cifs_small_buf_release(pSMB);
1300 /* Since session is dead, file will be closed on server already */
1308 CIFSSMBRename(const int xid, struct cifsTconInfo *tcon,
1309 const char *fromName, const char *toName,
1310 const struct nls_table *nls_codepage, int remap)
1313 RENAME_REQ *pSMB = NULL;
1314 RENAME_RSP *pSMBr = NULL;
1316 int name_len, name_len2;
1319 cFYI(1, ("In CIFSSMBRename"));
1321 rc = smb_init(SMB_COM_RENAME, 1, tcon, (void **) &pSMB,
1326 pSMB->BufferFormat = 0x04;
1327 pSMB->SearchAttributes =
1328 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
1331 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1333 cifsConvertToUCS((__le16 *) pSMB->OldFileName, fromName,
1334 PATH_MAX, nls_codepage, remap);
1335 name_len++; /* trailing null */
1337 pSMB->OldFileName[name_len] = 0x04; /* pad */
1338 /* protocol requires ASCII signature byte on Unicode string */
1339 pSMB->OldFileName[name_len + 1] = 0x00;
1341 cifsConvertToUCS((__le16 *) &pSMB->OldFileName[name_len + 2],
1342 toName, PATH_MAX, nls_codepage, remap);
1343 name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
1344 name_len2 *= 2; /* convert to bytes */
1345 } else { /* BB improve the check for buffer overruns BB */
1346 name_len = strnlen(fromName, PATH_MAX);
1347 name_len++; /* trailing null */
1348 strncpy(pSMB->OldFileName, fromName, name_len);
1349 name_len2 = strnlen(toName, PATH_MAX);
1350 name_len2++; /* trailing null */
1351 pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */
1352 strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2);
1353 name_len2++; /* trailing null */
1354 name_len2++; /* signature byte */
1357 count = 1 /* 1st signature byte */ + name_len + name_len2;
1358 pSMB->hdr.smb_buf_length += count;
1359 pSMB->ByteCount = cpu_to_le16(count);
1361 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1362 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1363 cifs_stats_inc(&tcon->num_renames);
1365 cFYI(1, ("Send error in rename = %d", rc));
1368 cifs_buf_release(pSMB);
1376 int CIFSSMBRenameOpenFile(const int xid,struct cifsTconInfo *pTcon,
1377 int netfid, char * target_name,
1378 const struct nls_table * nls_codepage, int remap)
1380 struct smb_com_transaction2_sfi_req *pSMB = NULL;
1381 struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
1382 struct set_file_rename * rename_info;
1384 char dummy_string[30];
1386 int bytes_returned = 0;
1388 __u16 params, param_offset, offset, count, byte_count;
1390 cFYI(1, ("Rename to File by handle"));
1391 rc = smb_init(SMB_COM_TRANSACTION2, 15, pTcon, (void **) &pSMB,
1397 pSMB->MaxSetupCount = 0;
1401 pSMB->Reserved2 = 0;
1402 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
1403 offset = param_offset + params;
1405 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
1406 rename_info = (struct set_file_rename *) data_offset;
1407 pSMB->MaxParameterCount = cpu_to_le16(2);
1408 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB PDU from sess */
1409 pSMB->SetupCount = 1;
1410 pSMB->Reserved3 = 0;
1411 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
1412 byte_count = 3 /* pad */ + params;
1413 pSMB->ParameterCount = cpu_to_le16(params);
1414 pSMB->TotalParameterCount = pSMB->ParameterCount;
1415 pSMB->ParameterOffset = cpu_to_le16(param_offset);
1416 pSMB->DataOffset = cpu_to_le16(offset);
1417 /* construct random name ".cifs_tmp<inodenum><mid>" */
1418 rename_info->overwrite = cpu_to_le32(1);
1419 rename_info->root_fid = 0;
1420 /* unicode only call */
1421 if(target_name == NULL) {
1422 sprintf(dummy_string,"cifs%x",pSMB->hdr.Mid);
1423 len_of_str = cifsConvertToUCS((__le16 *)rename_info->target_name,
1424 dummy_string, 24, nls_codepage, remap);
1426 len_of_str = cifsConvertToUCS((__le16 *)rename_info->target_name,
1427 target_name, PATH_MAX, nls_codepage, remap);
1429 rename_info->target_name_len = cpu_to_le32(2 * len_of_str);
1430 count = 12 /* sizeof(struct set_file_rename) */ + (2 * len_of_str) + 2;
1431 byte_count += count;
1432 pSMB->DataCount = cpu_to_le16(count);
1433 pSMB->TotalDataCount = pSMB->DataCount;
1435 pSMB->InformationLevel =
1436 cpu_to_le16(SMB_SET_FILE_RENAME_INFORMATION);
1437 pSMB->Reserved4 = 0;
1438 pSMB->hdr.smb_buf_length += byte_count;
1439 pSMB->ByteCount = cpu_to_le16(byte_count);
1440 rc = SendReceive(xid, pTcon->ses, (struct smb_hdr *) pSMB,
1441 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1442 cifs_stats_inc(&pTcon->num_t2renames);
1444 cFYI(1,("Send error in Rename (by file handle) = %d", rc));
1447 cifs_buf_release(pSMB);
1449 /* Note: On -EAGAIN error only caller can retry on handle based calls
1450 since file handle passed in no longer valid */
1456 CIFSSMBCopy(const int xid, struct cifsTconInfo *tcon, const char * fromName,
1457 const __u16 target_tid, const char *toName, const int flags,
1458 const struct nls_table *nls_codepage, int remap)
1461 COPY_REQ *pSMB = NULL;
1462 COPY_RSP *pSMBr = NULL;
1464 int name_len, name_len2;
1467 cFYI(1, ("In CIFSSMBCopy"));
1469 rc = smb_init(SMB_COM_COPY, 1, tcon, (void **) &pSMB,
1474 pSMB->BufferFormat = 0x04;
1475 pSMB->Tid2 = target_tid;
1477 pSMB->Flags = cpu_to_le16(flags & COPY_TREE);
1479 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1480 name_len = cifsConvertToUCS((__le16 *) pSMB->OldFileName,
1481 fromName, PATH_MAX, nls_codepage,
1483 name_len++; /* trailing null */
1485 pSMB->OldFileName[name_len] = 0x04; /* pad */
1486 /* protocol requires ASCII signature byte on Unicode string */
1487 pSMB->OldFileName[name_len + 1] = 0x00;
1488 name_len2 = cifsConvertToUCS((__le16 *)&pSMB->OldFileName[name_len + 2],
1489 toName, PATH_MAX, nls_codepage, remap);
1490 name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
1491 name_len2 *= 2; /* convert to bytes */
1492 } else { /* BB improve the check for buffer overruns BB */
1493 name_len = strnlen(fromName, PATH_MAX);
1494 name_len++; /* trailing null */
1495 strncpy(pSMB->OldFileName, fromName, name_len);
1496 name_len2 = strnlen(toName, PATH_MAX);
1497 name_len2++; /* trailing null */
1498 pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */
1499 strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2);
1500 name_len2++; /* trailing null */
1501 name_len2++; /* signature byte */
1504 count = 1 /* 1st signature byte */ + name_len + name_len2;
1505 pSMB->hdr.smb_buf_length += count;
1506 pSMB->ByteCount = cpu_to_le16(count);
1508 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1509 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1511 cFYI(1, ("Send error in copy = %d with %d files copied",
1512 rc, le16_to_cpu(pSMBr->CopyCount)));
1515 cifs_buf_release(pSMB);
1524 CIFSUnixCreateSymLink(const int xid, struct cifsTconInfo *tcon,
1525 const char *fromName, const char *toName,
1526 const struct nls_table *nls_codepage)
1528 TRANSACTION2_SPI_REQ *pSMB = NULL;
1529 TRANSACTION2_SPI_RSP *pSMBr = NULL;
1532 int name_len_target;
1534 int bytes_returned = 0;
1535 __u16 params, param_offset, offset, byte_count;
1537 cFYI(1, ("In Symlink Unix style"));
1539 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
1544 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1546 cifs_strtoUCS((wchar_t *) pSMB->FileName, fromName, PATH_MAX
1547 /* find define for this maxpathcomponent */
1549 name_len++; /* trailing null */
1552 } else { /* BB improve the check for buffer overruns BB */
1553 name_len = strnlen(fromName, PATH_MAX);
1554 name_len++; /* trailing null */
1555 strncpy(pSMB->FileName, fromName, name_len);
1557 params = 6 + name_len;
1558 pSMB->MaxSetupCount = 0;
1562 pSMB->Reserved2 = 0;
1563 param_offset = offsetof(struct smb_com_transaction2_spi_req,
1564 InformationLevel) - 4;
1565 offset = param_offset + params;
1567 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
1568 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1570 cifs_strtoUCS((wchar_t *) data_offset, toName, PATH_MAX
1571 /* find define for this maxpathcomponent */
1573 name_len_target++; /* trailing null */
1574 name_len_target *= 2;
1575 } else { /* BB improve the check for buffer overruns BB */
1576 name_len_target = strnlen(toName, PATH_MAX);
1577 name_len_target++; /* trailing null */
1578 strncpy(data_offset, toName, name_len_target);
1581 pSMB->MaxParameterCount = cpu_to_le16(2);
1582 /* BB find exact max on data count below from sess */
1583 pSMB->MaxDataCount = cpu_to_le16(1000);
1584 pSMB->SetupCount = 1;
1585 pSMB->Reserved3 = 0;
1586 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
1587 byte_count = 3 /* pad */ + params + name_len_target;
1588 pSMB->DataCount = cpu_to_le16(name_len_target);
1589 pSMB->ParameterCount = cpu_to_le16(params);
1590 pSMB->TotalDataCount = pSMB->DataCount;
1591 pSMB->TotalParameterCount = pSMB->ParameterCount;
1592 pSMB->ParameterOffset = cpu_to_le16(param_offset);
1593 pSMB->DataOffset = cpu_to_le16(offset);
1594 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_LINK);
1595 pSMB->Reserved4 = 0;
1596 pSMB->hdr.smb_buf_length += byte_count;
1597 pSMB->ByteCount = cpu_to_le16(byte_count);
1598 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1599 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1600 cifs_stats_inc(&tcon->num_symlinks);
1603 ("Send error in SetPathInfo (create symlink) = %d",
1608 cifs_buf_release(pSMB);
1611 goto createSymLinkRetry;
1617 CIFSUnixCreateHardLink(const int xid, struct cifsTconInfo *tcon,
1618 const char *fromName, const char *toName,
1619 const struct nls_table *nls_codepage, int remap)
1621 TRANSACTION2_SPI_REQ *pSMB = NULL;
1622 TRANSACTION2_SPI_RSP *pSMBr = NULL;
1625 int name_len_target;
1627 int bytes_returned = 0;
1628 __u16 params, param_offset, offset, byte_count;
1630 cFYI(1, ("In Create Hard link Unix style"));
1631 createHardLinkRetry:
1632 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
1637 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1638 name_len = cifsConvertToUCS((__le16 *) pSMB->FileName, toName,
1639 PATH_MAX, nls_codepage, remap);
1640 name_len++; /* trailing null */
1643 } else { /* BB improve the check for buffer overruns BB */
1644 name_len = strnlen(toName, PATH_MAX);
1645 name_len++; /* trailing null */
1646 strncpy(pSMB->FileName, toName, name_len);
1648 params = 6 + name_len;
1649 pSMB->MaxSetupCount = 0;
1653 pSMB->Reserved2 = 0;
1654 param_offset = offsetof(struct smb_com_transaction2_spi_req,
1655 InformationLevel) - 4;
1656 offset = param_offset + params;
1658 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
1659 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1661 cifsConvertToUCS((__le16 *) data_offset, fromName, PATH_MAX,
1662 nls_codepage, remap);
1663 name_len_target++; /* trailing null */
1664 name_len_target *= 2;
1665 } else { /* BB improve the check for buffer overruns BB */
1666 name_len_target = strnlen(fromName, PATH_MAX);
1667 name_len_target++; /* trailing null */
1668 strncpy(data_offset, fromName, name_len_target);
1671 pSMB->MaxParameterCount = cpu_to_le16(2);
1672 /* BB find exact max on data count below from sess*/
1673 pSMB->MaxDataCount = cpu_to_le16(1000);
1674 pSMB->SetupCount = 1;
1675 pSMB->Reserved3 = 0;
1676 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
1677 byte_count = 3 /* pad */ + params + name_len_target;
1678 pSMB->ParameterCount = cpu_to_le16(params);
1679 pSMB->TotalParameterCount = pSMB->ParameterCount;
1680 pSMB->DataCount = cpu_to_le16(name_len_target);
1681 pSMB->TotalDataCount = pSMB->DataCount;
1682 pSMB->ParameterOffset = cpu_to_le16(param_offset);
1683 pSMB->DataOffset = cpu_to_le16(offset);
1684 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_HLINK);
1685 pSMB->Reserved4 = 0;
1686 pSMB->hdr.smb_buf_length += byte_count;
1687 pSMB->ByteCount = cpu_to_le16(byte_count);
1688 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1689 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1690 cifs_stats_inc(&tcon->num_hardlinks);
1692 cFYI(1, ("Send error in SetPathInfo (hard link) = %d", rc));
1695 cifs_buf_release(pSMB);
1697 goto createHardLinkRetry;
1703 CIFSCreateHardLink(const int xid, struct cifsTconInfo *tcon,
1704 const char *fromName, const char *toName,
1705 const struct nls_table *nls_codepage, int remap)
1708 NT_RENAME_REQ *pSMB = NULL;
1709 RENAME_RSP *pSMBr = NULL;
1711 int name_len, name_len2;
1714 cFYI(1, ("In CIFSCreateHardLink"));
1715 winCreateHardLinkRetry:
1717 rc = smb_init(SMB_COM_NT_RENAME, 4, tcon, (void **) &pSMB,
1722 pSMB->SearchAttributes =
1723 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
1725 pSMB->Flags = cpu_to_le16(CREATE_HARD_LINK);
1726 pSMB->ClusterCount = 0;
1728 pSMB->BufferFormat = 0x04;
1730 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1732 cifsConvertToUCS((__le16 *) pSMB->OldFileName, fromName,
1733 PATH_MAX, nls_codepage, remap);
1734 name_len++; /* trailing null */
1736 pSMB->OldFileName[name_len] = 0; /* pad */
1737 pSMB->OldFileName[name_len + 1] = 0x04;
1739 cifsConvertToUCS((__le16 *)&pSMB->OldFileName[name_len + 2],
1740 toName, PATH_MAX, nls_codepage, remap);
1741 name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
1742 name_len2 *= 2; /* convert to bytes */
1743 } else { /* BB improve the check for buffer overruns BB */
1744 name_len = strnlen(fromName, PATH_MAX);
1745 name_len++; /* trailing null */
1746 strncpy(pSMB->OldFileName, fromName, name_len);
1747 name_len2 = strnlen(toName, PATH_MAX);
1748 name_len2++; /* trailing null */
1749 pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */
1750 strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2);
1751 name_len2++; /* trailing null */
1752 name_len2++; /* signature byte */
1755 count = 1 /* string type byte */ + name_len + name_len2;
1756 pSMB->hdr.smb_buf_length += count;
1757 pSMB->ByteCount = cpu_to_le16(count);
1759 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1760 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1761 cifs_stats_inc(&tcon->num_hardlinks);
1763 cFYI(1, ("Send error in hard link (NT rename) = %d", rc));
1765 cifs_buf_release(pSMB);
1767 goto winCreateHardLinkRetry;
1773 CIFSSMBUnixQuerySymLink(const int xid, struct cifsTconInfo *tcon,
1774 const unsigned char *searchName,
1775 char *symlinkinfo, const int buflen,
1776 const struct nls_table *nls_codepage)
1778 /* SMB_QUERY_FILE_UNIX_LINK */
1779 TRANSACTION2_QPI_REQ *pSMB = NULL;
1780 TRANSACTION2_QPI_RSP *pSMBr = NULL;
1784 __u16 params, byte_count;
1786 cFYI(1, ("In QPathSymLinkInfo (Unix) for path %s", searchName));
1789 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
1794 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1796 cifs_strtoUCS((wchar_t *) pSMB->FileName, searchName, PATH_MAX
1797 /* find define for this maxpathcomponent */
1799 name_len++; /* trailing null */
1801 } else { /* BB improve the check for buffer overruns BB */
1802 name_len = strnlen(searchName, PATH_MAX);
1803 name_len++; /* trailing null */
1804 strncpy(pSMB->FileName, searchName, name_len);
1807 params = 2 /* level */ + 4 /* rsrvd */ + name_len /* incl null */ ;
1808 pSMB->TotalDataCount = 0;
1809 pSMB->MaxParameterCount = cpu_to_le16(2);
1810 /* BB find exact max data count below from sess structure BB */
1811 pSMB->MaxDataCount = cpu_to_le16(4000);
1812 pSMB->MaxSetupCount = 0;
1816 pSMB->Reserved2 = 0;
1817 pSMB->ParameterOffset = cpu_to_le16(offsetof(
1818 struct smb_com_transaction2_qpi_req ,InformationLevel) - 4);
1819 pSMB->DataCount = 0;
1820 pSMB->DataOffset = 0;
1821 pSMB->SetupCount = 1;
1822 pSMB->Reserved3 = 0;
1823 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
1824 byte_count = params + 1 /* pad */ ;
1825 pSMB->TotalParameterCount = cpu_to_le16(params);
1826 pSMB->ParameterCount = pSMB->TotalParameterCount;
1827 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_LINK);
1828 pSMB->Reserved4 = 0;
1829 pSMB->hdr.smb_buf_length += byte_count;
1830 pSMB->ByteCount = cpu_to_le16(byte_count);
1832 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1833 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1835 cFYI(1, ("Send error in QuerySymLinkInfo = %d", rc));
1837 /* decode response */
1839 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
1840 if (rc || (pSMBr->ByteCount < 2))
1841 /* BB also check enough total bytes returned */
1842 rc = -EIO; /* bad smb */
1844 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
1845 __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
1847 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
1848 name_len = UniStrnlen((wchar_t *) ((char *)
1849 &pSMBr->hdr.Protocol +data_offset),
1850 min_t(const int, buflen,count) / 2);
1851 /* BB FIXME investigate remapping reserved chars here */
1852 cifs_strfromUCS_le(symlinkinfo,
1853 (wchar_t *) ((char *)&pSMBr->hdr.Protocol +
1855 name_len, nls_codepage);
1857 strncpy(symlinkinfo,
1858 (char *) &pSMBr->hdr.Protocol +
1860 min_t(const int, buflen, count));
1862 symlinkinfo[buflen] = 0;
1863 /* just in case so calling code does not go off the end of buffer */
1866 cifs_buf_release(pSMB);
1868 goto querySymLinkRetry;
1873 CIFSSMBQueryReparseLinkInfo(const int xid, struct cifsTconInfo *tcon,
1874 const unsigned char *searchName,
1875 char *symlinkinfo, const int buflen,__u16 fid,
1876 const struct nls_table *nls_codepage)
1881 struct smb_com_transaction_ioctl_req * pSMB;
1882 struct smb_com_transaction_ioctl_rsp * pSMBr;
1884 cFYI(1, ("In Windows reparse style QueryLink for path %s", searchName));
1885 rc = smb_init(SMB_COM_NT_TRANSACT, 23, tcon, (void **) &pSMB,
1890 pSMB->TotalParameterCount = 0 ;
1891 pSMB->TotalDataCount = 0;
1892 pSMB->MaxParameterCount = cpu_to_le32(2);
1893 /* BB find exact data count max from sess structure BB */
1894 pSMB->MaxDataCount = cpu_to_le32(4000);
1895 pSMB->MaxSetupCount = 4;
1897 pSMB->ParameterOffset = 0;
1898 pSMB->DataCount = 0;
1899 pSMB->DataOffset = 0;
1900 pSMB->SetupCount = 4;
1901 pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_IOCTL);
1902 pSMB->ParameterCount = pSMB->TotalParameterCount;
1903 pSMB->FunctionCode = cpu_to_le32(FSCTL_GET_REPARSE_POINT);
1904 pSMB->IsFsctl = 1; /* FSCTL */
1905 pSMB->IsRootFlag = 0;
1906 pSMB->Fid = fid; /* file handle always le */
1907 pSMB->ByteCount = 0;
1909 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1910 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1912 cFYI(1, ("Send error in QueryReparseLinkInfo = %d", rc));
1913 } else { /* decode response */
1914 __u32 data_offset = le32_to_cpu(pSMBr->DataOffset);
1915 __u32 data_count = le32_to_cpu(pSMBr->DataCount);
1916 if ((pSMBr->ByteCount < 2) || (data_offset > 512))
1917 /* BB also check enough total bytes returned */
1918 rc = -EIO; /* bad smb */
1920 if(data_count && (data_count < 2048)) {
1921 char * end_of_smb = pSMBr->ByteCount + (char *)&pSMBr->ByteCount;
1923 struct reparse_data * reparse_buf = (struct reparse_data *)
1924 ((char *)&pSMBr->hdr.Protocol + data_offset);
1925 if((char*)reparse_buf >= end_of_smb) {
1929 if((reparse_buf->LinkNamesBuf +
1930 reparse_buf->TargetNameOffset +
1931 reparse_buf->TargetNameLen) >
1933 cFYI(1,("reparse buf extended beyond SMB"));
1938 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
1939 name_len = UniStrnlen((wchar_t *)
1940 (reparse_buf->LinkNamesBuf +
1941 reparse_buf->TargetNameOffset),
1942 min(buflen/2, reparse_buf->TargetNameLen / 2));
1943 cifs_strfromUCS_le(symlinkinfo,
1944 (wchar_t *) (reparse_buf->LinkNamesBuf +
1945 reparse_buf->TargetNameOffset),
1946 name_len, nls_codepage);
1947 } else { /* ASCII names */
1948 strncpy(symlinkinfo,reparse_buf->LinkNamesBuf +
1949 reparse_buf->TargetNameOffset,
1950 min_t(const int, buflen, reparse_buf->TargetNameLen));
1954 cFYI(1,("Invalid return data count on get reparse info ioctl"));
1956 symlinkinfo[buflen] = 0; /* just in case so the caller
1957 does not go off the end of the buffer */
1958 cFYI(1,("readlink result - %s ",symlinkinfo));
1962 cifs_buf_release(pSMB);
1964 /* Note: On -EAGAIN error only caller can retry on handle based calls
1965 since file handle passed in no longer valid */
1970 #ifdef CONFIG_CIFS_POSIX
1972 /*Convert an Access Control Entry from wire format to local POSIX xattr format*/
1973 static void cifs_convert_ace(posix_acl_xattr_entry * ace, struct cifs_posix_ace * cifs_ace)
1975 /* u8 cifs fields do not need le conversion */
1976 ace->e_perm = (__u16)cifs_ace->cifs_e_perm;
1977 ace->e_tag = (__u16)cifs_ace->cifs_e_tag;
1978 ace->e_id = (__u32)le64_to_cpu(cifs_ace->cifs_uid);
1979 /* cFYI(1,("perm %d tag %d id %d",ace->e_perm,ace->e_tag,ace->e_id)); */
1984 /* Convert ACL from CIFS POSIX wire format to local Linux POSIX ACL xattr */
1985 static int cifs_copy_posix_acl(char * trgt,char * src, const int buflen,
1986 const int acl_type,const int size_of_data_area)
1991 struct cifs_posix_ace * pACE;
1992 struct cifs_posix_acl * cifs_acl = (struct cifs_posix_acl *)src;
1993 posix_acl_xattr_header * local_acl = (posix_acl_xattr_header *)trgt;
1995 if (le16_to_cpu(cifs_acl->version) != CIFS_ACL_VERSION)
1998 if(acl_type & ACL_TYPE_ACCESS) {
1999 count = le16_to_cpu(cifs_acl->access_entry_count);
2000 pACE = &cifs_acl->ace_array[0];
2001 size = sizeof(struct cifs_posix_acl);
2002 size += sizeof(struct cifs_posix_ace) * count;
2003 /* check if we would go beyond end of SMB */
2004 if(size_of_data_area < size) {
2005 cFYI(1,("bad CIFS POSIX ACL size %d vs. %d",size_of_data_area,size));
2008 } else if(acl_type & ACL_TYPE_DEFAULT) {
2009 count = le16_to_cpu(cifs_acl->access_entry_count);
2010 size = sizeof(struct cifs_posix_acl);
2011 size += sizeof(struct cifs_posix_ace) * count;
2012 /* skip past access ACEs to get to default ACEs */
2013 pACE = &cifs_acl->ace_array[count];
2014 count = le16_to_cpu(cifs_acl->default_entry_count);
2015 size += sizeof(struct cifs_posix_ace) * count;
2016 /* check if we would go beyond end of SMB */
2017 if(size_of_data_area < size)
2024 size = posix_acl_xattr_size(count);
2025 if((buflen == 0) || (local_acl == NULL)) {
2026 /* used to query ACL EA size */
2027 } else if(size > buflen) {
2029 } else /* buffer big enough */ {
2030 local_acl->a_version = POSIX_ACL_XATTR_VERSION;
2031 for(i = 0;i < count ;i++) {
2032 cifs_convert_ace(&local_acl->a_entries[i],pACE);
2039 static __u16 convert_ace_to_cifs_ace(struct cifs_posix_ace * cifs_ace,
2040 const posix_acl_xattr_entry * local_ace)
2042 __u16 rc = 0; /* 0 = ACL converted ok */
2044 cifs_ace->cifs_e_perm = (__u8)cpu_to_le16(local_ace->e_perm);
2045 cifs_ace->cifs_e_tag = (__u8)cpu_to_le16(local_ace->e_tag);
2046 /* BB is there a better way to handle the large uid? */
2047 if(local_ace->e_id == -1) {
2048 /* Probably no need to le convert -1 on any arch but can not hurt */
2049 cifs_ace->cifs_uid = cpu_to_le64(-1);
2051 cifs_ace->cifs_uid = (__u64)cpu_to_le32(local_ace->e_id);
2052 /*cFYI(1,("perm %d tag %d id %d",ace->e_perm,ace->e_tag,ace->e_id));*/
2056 /* Convert ACL from local Linux POSIX xattr to CIFS POSIX ACL wire format */
2057 static __u16 ACL_to_cifs_posix(char * parm_data,const char * pACL,const int buflen,
2061 struct cifs_posix_acl * cifs_acl = (struct cifs_posix_acl *)parm_data;
2062 posix_acl_xattr_header * local_acl = (posix_acl_xattr_header *)pACL;
2066 if((buflen == 0) || (pACL == NULL) || (cifs_acl == NULL))
2069 count = posix_acl_xattr_count((size_t)buflen);
2070 cFYI(1,("setting acl with %d entries from buf of length %d and version of %d",
2071 count,buflen,local_acl->a_version));
2072 if(local_acl->a_version != 2) {
2073 cFYI(1,("unknown POSIX ACL version %d",local_acl->a_version));
2076 cifs_acl->version = cpu_to_le16(1);
2077 if(acl_type == ACL_TYPE_ACCESS)
2078 cifs_acl->access_entry_count = count;
2079 else if(acl_type == ACL_TYPE_DEFAULT)
2080 cifs_acl->default_entry_count = count;
2082 cFYI(1,("unknown ACL type %d",acl_type));
2085 for(i=0;i<count;i++) {
2086 rc = convert_ace_to_cifs_ace(&cifs_acl->ace_array[i],
2087 &local_acl->a_entries[i]);
2089 /* ACE not converted */
2094 rc = (__u16)(count * sizeof(struct cifs_posix_ace));
2095 rc += sizeof(struct cifs_posix_acl);
2096 /* BB add check to make sure ACL does not overflow SMB */
2102 CIFSSMBGetPosixACL(const int xid, struct cifsTconInfo *tcon,
2103 const unsigned char *searchName,
2104 char *acl_inf, const int buflen, const int acl_type,
2105 const struct nls_table *nls_codepage, int remap)
2107 /* SMB_QUERY_POSIX_ACL */
2108 TRANSACTION2_QPI_REQ *pSMB = NULL;
2109 TRANSACTION2_QPI_RSP *pSMBr = NULL;
2113 __u16 params, byte_count;
2115 cFYI(1, ("In GetPosixACL (Unix) for path %s", searchName));
2118 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2123 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2125 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
2126 PATH_MAX, nls_codepage, remap);
2127 name_len++; /* trailing null */
2129 pSMB->FileName[name_len] = 0;
2130 pSMB->FileName[name_len+1] = 0;
2131 } else { /* BB improve the check for buffer overruns BB */
2132 name_len = strnlen(searchName, PATH_MAX);
2133 name_len++; /* trailing null */
2134 strncpy(pSMB->FileName, searchName, name_len);
2137 params = 2 /* level */ + 4 /* rsrvd */ + name_len /* incl null */ ;
2138 pSMB->TotalDataCount = 0;
2139 pSMB->MaxParameterCount = cpu_to_le16(2);
2140 /* BB find exact max data count below from sess structure BB */
2141 pSMB->MaxDataCount = cpu_to_le16(4000);
2142 pSMB->MaxSetupCount = 0;
2146 pSMB->Reserved2 = 0;
2147 pSMB->ParameterOffset = cpu_to_le16(
2148 offsetof(struct smb_com_transaction2_qpi_req ,InformationLevel) - 4);
2149 pSMB->DataCount = 0;
2150 pSMB->DataOffset = 0;
2151 pSMB->SetupCount = 1;
2152 pSMB->Reserved3 = 0;
2153 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
2154 byte_count = params + 1 /* pad */ ;
2155 pSMB->TotalParameterCount = cpu_to_le16(params);
2156 pSMB->ParameterCount = pSMB->TotalParameterCount;
2157 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_POSIX_ACL);
2158 pSMB->Reserved4 = 0;
2159 pSMB->hdr.smb_buf_length += byte_count;
2160 pSMB->ByteCount = cpu_to_le16(byte_count);
2162 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2163 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2165 cFYI(1, ("Send error in Query POSIX ACL = %d", rc));
2167 /* decode response */
2169 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
2170 if (rc || (pSMBr->ByteCount < 2))
2171 /* BB also check enough total bytes returned */
2172 rc = -EIO; /* bad smb */
2174 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
2175 __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
2176 rc = cifs_copy_posix_acl(acl_inf,
2177 (char *)&pSMBr->hdr.Protocol+data_offset,
2178 buflen,acl_type,count);
2181 cifs_buf_release(pSMB);
2188 CIFSSMBSetPosixACL(const int xid, struct cifsTconInfo *tcon,
2189 const unsigned char *fileName,
2190 const char *local_acl, const int buflen,
2192 const struct nls_table *nls_codepage, int remap)
2194 struct smb_com_transaction2_spi_req *pSMB = NULL;
2195 struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
2199 int bytes_returned = 0;
2200 __u16 params, byte_count, data_count, param_offset, offset;
2202 cFYI(1, ("In SetPosixACL (Unix) for path %s", fileName));
2204 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2208 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2210 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
2211 PATH_MAX, nls_codepage, remap);
2212 name_len++; /* trailing null */
2214 } else { /* BB improve the check for buffer overruns BB */
2215 name_len = strnlen(fileName, PATH_MAX);
2216 name_len++; /* trailing null */
2217 strncpy(pSMB->FileName, fileName, name_len);
2219 params = 6 + name_len;
2220 pSMB->MaxParameterCount = cpu_to_le16(2);
2221 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB size from sess */
2222 pSMB->MaxSetupCount = 0;
2226 pSMB->Reserved2 = 0;
2227 param_offset = offsetof(struct smb_com_transaction2_spi_req,
2228 InformationLevel) - 4;
2229 offset = param_offset + params;
2230 parm_data = ((char *) &pSMB->hdr.Protocol) + offset;
2231 pSMB->ParameterOffset = cpu_to_le16(param_offset);
2233 /* convert to on the wire format for POSIX ACL */
2234 data_count = ACL_to_cifs_posix(parm_data,local_acl,buflen,acl_type);
2236 if(data_count == 0) {
2238 goto setACLerrorExit;
2240 pSMB->DataOffset = cpu_to_le16(offset);
2241 pSMB->SetupCount = 1;
2242 pSMB->Reserved3 = 0;
2243 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
2244 pSMB->InformationLevel = cpu_to_le16(SMB_SET_POSIX_ACL);
2245 byte_count = 3 /* pad */ + params + data_count;
2246 pSMB->DataCount = cpu_to_le16(data_count);
2247 pSMB->TotalDataCount = pSMB->DataCount;
2248 pSMB->ParameterCount = cpu_to_le16(params);
2249 pSMB->TotalParameterCount = pSMB->ParameterCount;
2250 pSMB->Reserved4 = 0;
2251 pSMB->hdr.smb_buf_length += byte_count;
2252 pSMB->ByteCount = cpu_to_le16(byte_count);
2253 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2254 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2256 cFYI(1, ("Set POSIX ACL returned %d", rc));
2260 cifs_buf_release(pSMB);
2266 /* BB fix tabs in this function FIXME BB */
2268 CIFSGetExtAttr(const int xid, struct cifsTconInfo *tcon,
2269 const int netfid, __u64 * pExtAttrBits, __u64 *pMask)
2272 struct smb_t2_qfi_req *pSMB = NULL;
2273 struct smb_t2_qfi_rsp *pSMBr = NULL;
2275 __u16 params, byte_count;
2277 cFYI(1,("In GetExtAttr"));
2282 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2287 params = 2 /* level */ +2 /* fid */;
2288 pSMB->t2.TotalDataCount = 0;
2289 pSMB->t2.MaxParameterCount = cpu_to_le16(4);
2290 /* BB find exact max data count below from sess structure BB */
2291 pSMB->t2.MaxDataCount = cpu_to_le16(4000);
2292 pSMB->t2.MaxSetupCount = 0;
2293 pSMB->t2.Reserved = 0;
2295 pSMB->t2.Timeout = 0;
2296 pSMB->t2.Reserved2 = 0;
2297 pSMB->t2.ParameterOffset = cpu_to_le16(offsetof(struct smb_t2_qfi_req,
2299 pSMB->t2.DataCount = 0;
2300 pSMB->t2.DataOffset = 0;
2301 pSMB->t2.SetupCount = 1;
2302 pSMB->t2.Reserved3 = 0;
2303 pSMB->t2.SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION);
2304 byte_count = params + 1 /* pad */ ;
2305 pSMB->t2.TotalParameterCount = cpu_to_le16(params);
2306 pSMB->t2.ParameterCount = pSMB->t2.TotalParameterCount;
2307 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_ATTR_FLAGS);
2310 pSMB->hdr.smb_buf_length += byte_count;
2311 pSMB->t2.ByteCount = cpu_to_le16(byte_count);
2313 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2314 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2316 cFYI(1, ("error %d in GetExtAttr", rc));
2318 /* decode response */
2319 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
2320 if (rc || (pSMBr->ByteCount < 2))
2321 /* BB also check enough total bytes returned */
2322 /* If rc should we check for EOPNOSUPP and
2323 disable the srvino flag? or in caller? */
2324 rc = -EIO; /* bad smb */
2326 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
2327 __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
2328 struct file_chattr_info * pfinfo;
2329 /* BB Do we need a cast or hash here ? */
2331 cFYI(1, ("Illegal size ret in GetExtAttr"));
2335 pfinfo = (struct file_chattr_info *)
2336 (data_offset + (char *) &pSMBr->hdr.Protocol);
2337 *pExtAttrBits = le64_to_cpu(pfinfo->mode);
2338 *pMask = le64_to_cpu(pfinfo->mask);
2342 cifs_buf_release(pSMB);
2344 goto GetExtAttrRetry;
2349 #endif /* CONFIG_POSIX */
2351 /* Legacy Query Path Information call for lookup to old servers such
2353 int SMBQueryInformation(const int xid, struct cifsTconInfo *tcon,
2354 const unsigned char *searchName,
2355 FILE_ALL_INFO * pFinfo,
2356 const struct nls_table *nls_codepage, int remap)
2358 QUERY_INFORMATION_REQ * pSMB;
2359 QUERY_INFORMATION_RSP * pSMBr;
2364 cFYI(1, ("In SMBQPath path %s", searchName));
2366 rc = smb_init(SMB_COM_QUERY_INFORMATION, 0, tcon, (void **) &pSMB,
2371 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2373 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
2374 PATH_MAX, nls_codepage, remap);
2375 name_len++; /* trailing null */
2378 name_len = strnlen(searchName, PATH_MAX);
2379 name_len++; /* trailing null */
2380 strncpy(pSMB->FileName, searchName, name_len);
2382 pSMB->BufferFormat = 0x04;
2383 name_len++; /* account for buffer type byte */
2384 pSMB->hdr.smb_buf_length += (__u16) name_len;
2385 pSMB->ByteCount = cpu_to_le16(name_len);
2387 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2388 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2390 cFYI(1, ("Send error in QueryInfo = %d", rc));
2391 } else if (pFinfo) { /* decode response */
2392 memset(pFinfo, 0, sizeof(FILE_ALL_INFO));
2393 pFinfo->AllocationSize = (__le64) pSMBr->size;
2394 pFinfo->EndOfFile = (__le64) pSMBr->size;
2395 pFinfo->Attributes = (__le32) pSMBr->attr;
2397 rc = -EIO; /* bad buffer passed in */
2399 cifs_buf_release(pSMB);
2411 CIFSSMBQPathInfo(const int xid, struct cifsTconInfo *tcon,
2412 const unsigned char *searchName,
2413 FILE_ALL_INFO * pFindData,
2414 const struct nls_table *nls_codepage, int remap)
2416 /* level 263 SMB_QUERY_FILE_ALL_INFO */
2417 TRANSACTION2_QPI_REQ *pSMB = NULL;
2418 TRANSACTION2_QPI_RSP *pSMBr = NULL;
2422 __u16 params, byte_count;
2424 /* cFYI(1, ("In QPathInfo path %s", searchName)); */
2426 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2431 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2433 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
2434 PATH_MAX, nls_codepage, remap);
2435 name_len++; /* trailing null */
2437 } else { /* BB improve the check for buffer overruns BB */
2438 name_len = strnlen(searchName, PATH_MAX);
2439 name_len++; /* trailing null */
2440 strncpy(pSMB->FileName, searchName, name_len);
2443 params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */ ;
2444 pSMB->TotalDataCount = 0;
2445 pSMB->MaxParameterCount = cpu_to_le16(2);
2446 pSMB->MaxDataCount = cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
2447 pSMB->MaxSetupCount = 0;
2451 pSMB->Reserved2 = 0;
2452 pSMB->ParameterOffset = cpu_to_le16(offsetof(
2453 struct smb_com_transaction2_qpi_req ,InformationLevel) - 4);
2454 pSMB->DataCount = 0;
2455 pSMB->DataOffset = 0;
2456 pSMB->SetupCount = 1;
2457 pSMB->Reserved3 = 0;
2458 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
2459 byte_count = params + 1 /* pad */ ;
2460 pSMB->TotalParameterCount = cpu_to_le16(params);
2461 pSMB->ParameterCount = pSMB->TotalParameterCount;
2462 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_ALL_INFO);
2463 pSMB->Reserved4 = 0;
2464 pSMB->hdr.smb_buf_length += byte_count;
2465 pSMB->ByteCount = cpu_to_le16(byte_count);
2467 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2468 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2470 cFYI(1, ("Send error in QPathInfo = %d", rc));
2471 } else { /* decode response */
2472 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
2474 if (rc || (pSMBr->ByteCount < 40))
2475 rc = -EIO; /* bad smb */
2476 else if (pFindData){
2477 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
2478 memcpy((char *) pFindData,
2479 (char *) &pSMBr->hdr.Protocol +
2480 data_offset, sizeof (FILE_ALL_INFO));
2484 cifs_buf_release(pSMB);
2486 goto QPathInfoRetry;
2492 CIFSSMBUnixQPathInfo(const int xid, struct cifsTconInfo *tcon,
2493 const unsigned char *searchName,
2494 FILE_UNIX_BASIC_INFO * pFindData,
2495 const struct nls_table *nls_codepage, int remap)
2497 /* SMB_QUERY_FILE_UNIX_BASIC */
2498 TRANSACTION2_QPI_REQ *pSMB = NULL;
2499 TRANSACTION2_QPI_RSP *pSMBr = NULL;
2501 int bytes_returned = 0;
2503 __u16 params, byte_count;
2505 cFYI(1, ("In QPathInfo (Unix) the path %s", searchName));
2507 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2512 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2514 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
2515 PATH_MAX, nls_codepage, remap);
2516 name_len++; /* trailing null */
2518 } else { /* BB improve the check for buffer overruns BB */
2519 name_len = strnlen(searchName, PATH_MAX);
2520 name_len++; /* trailing null */
2521 strncpy(pSMB->FileName, searchName, name_len);
2524 params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */ ;
2525 pSMB->TotalDataCount = 0;
2526 pSMB->MaxParameterCount = cpu_to_le16(2);
2527 /* BB find exact max SMB PDU from sess structure BB */
2528 pSMB->MaxDataCount = cpu_to_le16(4000);
2529 pSMB->MaxSetupCount = 0;
2533 pSMB->Reserved2 = 0;
2534 pSMB->ParameterOffset = cpu_to_le16(offsetof(
2535 struct smb_com_transaction2_qpi_req ,InformationLevel) - 4);
2536 pSMB->DataCount = 0;
2537 pSMB->DataOffset = 0;
2538 pSMB->SetupCount = 1;
2539 pSMB->Reserved3 = 0;
2540 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
2541 byte_count = params + 1 /* pad */ ;
2542 pSMB->TotalParameterCount = cpu_to_le16(params);
2543 pSMB->ParameterCount = pSMB->TotalParameterCount;
2544 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC);
2545 pSMB->Reserved4 = 0;
2546 pSMB->hdr.smb_buf_length += byte_count;
2547 pSMB->ByteCount = cpu_to_le16(byte_count);
2549 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2550 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2552 cFYI(1, ("Send error in QPathInfo = %d", rc));
2553 } else { /* decode response */
2554 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
2556 if (rc || (pSMBr->ByteCount < sizeof(FILE_UNIX_BASIC_INFO))) {
2557 rc = -EIO; /* bad smb */
2559 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
2560 memcpy((char *) pFindData,
2561 (char *) &pSMBr->hdr.Protocol +
2563 sizeof (FILE_UNIX_BASIC_INFO));
2566 cifs_buf_release(pSMB);
2568 goto UnixQPathInfoRetry;
2573 #if 0 /* function unused at present */
2574 int CIFSFindSingle(const int xid, struct cifsTconInfo *tcon,
2575 const char *searchName, FILE_ALL_INFO * findData,
2576 const struct nls_table *nls_codepage)
2578 /* level 257 SMB_ */
2579 TRANSACTION2_FFIRST_REQ *pSMB = NULL;
2580 TRANSACTION2_FFIRST_RSP *pSMBr = NULL;
2584 __u16 params, byte_count;
2586 cFYI(1, ("In FindUnique"));
2588 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2593 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2595 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName, PATH_MAX
2596 /* find define for this maxpathcomponent */
2598 name_len++; /* trailing null */
2600 } else { /* BB improve the check for buffer overruns BB */
2601 name_len = strnlen(searchName, PATH_MAX);
2602 name_len++; /* trailing null */
2603 strncpy(pSMB->FileName, searchName, name_len);
2606 params = 12 + name_len /* includes null */ ;
2607 pSMB->TotalDataCount = 0; /* no EAs */
2608 pSMB->MaxParameterCount = cpu_to_le16(2);
2609 pSMB->MaxDataCount = cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
2610 pSMB->MaxSetupCount = 0;
2614 pSMB->Reserved2 = 0;
2615 pSMB->ParameterOffset = cpu_to_le16(
2616 offsetof(struct smb_com_transaction2_ffirst_req,InformationLevel) - 4);
2617 pSMB->DataCount = 0;
2618 pSMB->DataOffset = 0;
2619 pSMB->SetupCount = 1; /* one byte, no need to le convert */
2620 pSMB->Reserved3 = 0;
2621 pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_FIRST);
2622 byte_count = params + 1 /* pad */ ;
2623 pSMB->TotalParameterCount = cpu_to_le16(params);
2624 pSMB->ParameterCount = pSMB->TotalParameterCount;
2625 pSMB->SearchAttributes =
2626 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
2628 pSMB->SearchCount = cpu_to_le16(16); /* BB increase */
2629 pSMB->SearchFlags = cpu_to_le16(1);
2630 pSMB->InformationLevel = cpu_to_le16(SMB_FIND_FILE_DIRECTORY_INFO);
2631 pSMB->SearchStorageType = 0; /* BB what should we set this to? BB */
2632 pSMB->hdr.smb_buf_length += byte_count;
2633 pSMB->ByteCount = cpu_to_le16(byte_count);
2635 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2636 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2639 cFYI(1, ("Send error in FindFileDirInfo = %d", rc));
2640 } else { /* decode response */
2641 cifs_stats_inc(&tcon->num_ffirst);
2645 cifs_buf_release(pSMB);
2647 goto findUniqueRetry;
2651 #endif /* end unused (temporarily) function */
2653 /* xid, tcon, searchName and codepage are input parms, rest are returned */
2655 CIFSFindFirst(const int xid, struct cifsTconInfo *tcon,
2656 const char *searchName,
2657 const struct nls_table *nls_codepage,
2659 struct cifs_search_info * psrch_inf, int remap, const char dirsep)
2661 /* level 257 SMB_ */
2662 TRANSACTION2_FFIRST_REQ *pSMB = NULL;
2663 TRANSACTION2_FFIRST_RSP *pSMBr = NULL;
2664 T2_FFIRST_RSP_PARMS * parms;
2666 int bytes_returned = 0;
2668 __u16 params, byte_count;
2670 cFYI(1, ("In FindFirst for %s",searchName));
2673 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2678 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2680 cifsConvertToUCS((__le16 *) pSMB->FileName,searchName,
2681 PATH_MAX, nls_codepage, remap);
2682 /* We can not add the asterik earlier in case
2683 it got remapped to 0xF03A as if it were part of the
2684 directory name instead of a wildcard */
2686 pSMB->FileName[name_len] = dirsep;
2687 pSMB->FileName[name_len+1] = 0;
2688 pSMB->FileName[name_len+2] = '*';
2689 pSMB->FileName[name_len+3] = 0;
2690 name_len += 4; /* now the trailing null */
2691 pSMB->FileName[name_len] = 0; /* null terminate just in case */
2692 pSMB->FileName[name_len+1] = 0;
2694 } else { /* BB add check for overrun of SMB buf BB */
2695 name_len = strnlen(searchName, PATH_MAX);
2696 /* BB fix here and in unicode clause above ie
2697 if(name_len > buffersize-header)
2698 free buffer exit; BB */
2699 strncpy(pSMB->FileName, searchName, name_len);
2700 pSMB->FileName[name_len] = dirsep;
2701 pSMB->FileName[name_len+1] = '*';
2702 pSMB->FileName[name_len+2] = 0;
2706 params = 12 + name_len /* includes null */ ;
2707 pSMB->TotalDataCount = 0; /* no EAs */
2708 pSMB->MaxParameterCount = cpu_to_le16(10);
2709 pSMB->MaxDataCount = cpu_to_le16((tcon->ses->server->maxBuf -
2710 MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
2711 pSMB->MaxSetupCount = 0;
2715 pSMB->Reserved2 = 0;
2716 byte_count = params + 1 /* pad */ ;
2717 pSMB->TotalParameterCount = cpu_to_le16(params);
2718 pSMB->ParameterCount = pSMB->TotalParameterCount;
2719 pSMB->ParameterOffset = cpu_to_le16(
2720 offsetof(struct smb_com_transaction2_ffirst_req, SearchAttributes) - 4);
2721 pSMB->DataCount = 0;
2722 pSMB->DataOffset = 0;
2723 pSMB->SetupCount = 1; /* one byte, no need to make endian neutral */
2724 pSMB->Reserved3 = 0;
2725 pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_FIRST);
2726 pSMB->SearchAttributes =
2727 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
2729 pSMB->SearchCount= cpu_to_le16(CIFSMaxBufSize/sizeof(FILE_UNIX_INFO));
2730 pSMB->SearchFlags = cpu_to_le16(CIFS_SEARCH_CLOSE_AT_END |
2731 CIFS_SEARCH_RETURN_RESUME);
2732 pSMB->InformationLevel = cpu_to_le16(psrch_inf->info_level);
2734 /* BB what should we set StorageType to? Does it matter? BB */
2735 pSMB->SearchStorageType = 0;
2736 pSMB->hdr.smb_buf_length += byte_count;
2737 pSMB->ByteCount = cpu_to_le16(byte_count);
2739 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2740 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2741 cifs_stats_inc(&tcon->num_ffirst);
2743 if (rc) {/* BB add logic to retry regular search if Unix search rejected unexpectedly by server */
2744 /* BB Add code to handle unsupported level rc */
2745 cFYI(1, ("Error in FindFirst = %d", rc));
2748 cifs_buf_release(pSMB);
2750 /* BB eventually could optimize out free and realloc of buf */
2753 goto findFirstRetry;
2754 } else { /* decode response */
2755 /* BB remember to free buffer if error BB */
2756 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
2758 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
2759 psrch_inf->unicode = TRUE;
2761 psrch_inf->unicode = FALSE;
2763 psrch_inf->ntwrk_buf_start = (char *)pSMBr;
2764 psrch_inf->srch_entries_start =
2765 (char *) &pSMBr->hdr.Protocol +
2766 le16_to_cpu(pSMBr->t2.DataOffset);
2767 parms = (T2_FFIRST_RSP_PARMS *)((char *) &pSMBr->hdr.Protocol +
2768 le16_to_cpu(pSMBr->t2.ParameterOffset));
2770 if(parms->EndofSearch)
2771 psrch_inf->endOfSearch = TRUE;
2773 psrch_inf->endOfSearch = FALSE;
2775 psrch_inf->entries_in_buffer = le16_to_cpu(parms->SearchCount);
2776 psrch_inf->index_of_last_entry =
2777 psrch_inf->entries_in_buffer;
2778 *pnetfid = parms->SearchHandle;
2780 cifs_buf_release(pSMB);
2787 int CIFSFindNext(const int xid, struct cifsTconInfo *tcon,
2788 __u16 searchHandle, struct cifs_search_info * psrch_inf)
2790 TRANSACTION2_FNEXT_REQ *pSMB = NULL;
2791 TRANSACTION2_FNEXT_RSP *pSMBr = NULL;
2792 T2_FNEXT_RSP_PARMS * parms;
2793 char *response_data;
2795 int bytes_returned, name_len;
2796 __u16 params, byte_count;
2798 cFYI(1, ("In FindNext"));
2800 if(psrch_inf->endOfSearch == TRUE)
2803 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2808 params = 14; /* includes 2 bytes of null string, converted to LE below */
2810 pSMB->TotalDataCount = 0; /* no EAs */
2811 pSMB->MaxParameterCount = cpu_to_le16(8);
2812 pSMB->MaxDataCount =
2813 cpu_to_le16((tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
2814 pSMB->MaxSetupCount = 0;
2818 pSMB->Reserved2 = 0;
2819 pSMB->ParameterOffset = cpu_to_le16(
2820 offsetof(struct smb_com_transaction2_fnext_req,SearchHandle) - 4);
2821 pSMB->DataCount = 0;
2822 pSMB->DataOffset = 0;
2823 pSMB->SetupCount = 1;
2824 pSMB->Reserved3 = 0;
2825 pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_NEXT);
2826 pSMB->SearchHandle = searchHandle; /* always kept as le */
2828 cpu_to_le16(CIFSMaxBufSize / sizeof (FILE_UNIX_INFO));
2829 /* test for Unix extensions */
2830 /* if (tcon->ses->capabilities & CAP_UNIX) {
2831 pSMB->InformationLevel = cpu_to_le16(SMB_FIND_FILE_UNIX);
2832 psrch_inf->info_level = SMB_FIND_FILE_UNIX;
2834 pSMB->InformationLevel =
2835 cpu_to_le16(SMB_FIND_FILE_DIRECTORY_INFO);
2836 psrch_inf->info_level = SMB_FIND_FILE_DIRECTORY_INFO;
2838 pSMB->InformationLevel = cpu_to_le16(psrch_inf->info_level);
2839 pSMB->ResumeKey = psrch_inf->resume_key;
2841 cpu_to_le16(CIFS_SEARCH_CLOSE_AT_END | CIFS_SEARCH_RETURN_RESUME);
2843 name_len = psrch_inf->resume_name_len;
2845 if(name_len < PATH_MAX) {
2846 memcpy(pSMB->ResumeFileName, psrch_inf->presume_name, name_len);
2847 byte_count += name_len;
2848 /* 14 byte parm len above enough for 2 byte null terminator */
2849 pSMB->ResumeFileName[name_len] = 0;
2850 pSMB->ResumeFileName[name_len+1] = 0;
2853 goto FNext2_err_exit;
2855 byte_count = params + 1 /* pad */ ;
2856 pSMB->TotalParameterCount = cpu_to_le16(params);
2857 pSMB->ParameterCount = pSMB->TotalParameterCount;
2858 pSMB->hdr.smb_buf_length += byte_count;
2859 pSMB->ByteCount = cpu_to_le16(byte_count);
2861 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2862 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2863 cifs_stats_inc(&tcon->num_fnext);
2866 psrch_inf->endOfSearch = TRUE;
2867 rc = 0; /* search probably was closed at end of search above */
2869 cFYI(1, ("FindNext returned = %d", rc));
2870 } else { /* decode response */
2871 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
2874 /* BB fixme add lock for file (srch_info) struct here */
2875 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
2876 psrch_inf->unicode = TRUE;
2878 psrch_inf->unicode = FALSE;
2879 response_data = (char *) &pSMBr->hdr.Protocol +
2880 le16_to_cpu(pSMBr->t2.ParameterOffset);
2881 parms = (T2_FNEXT_RSP_PARMS *)response_data;
2882 response_data = (char *)&pSMBr->hdr.Protocol +
2883 le16_to_cpu(pSMBr->t2.DataOffset);
2884 cifs_buf_release(psrch_inf->ntwrk_buf_start);
2885 psrch_inf->srch_entries_start = response_data;
2886 psrch_inf->ntwrk_buf_start = (char *)pSMB;
2887 if(parms->EndofSearch)
2888 psrch_inf->endOfSearch = TRUE;
2890 psrch_inf->endOfSearch = FALSE;
2892 psrch_inf->entries_in_buffer = le16_to_cpu(parms->SearchCount);
2893 psrch_inf->index_of_last_entry +=
2894 psrch_inf->entries_in_buffer;
2895 /* cFYI(1,("fnxt2 entries in buf %d index_of_last %d",psrch_inf->entries_in_buffer,psrch_inf->index_of_last_entry)); */
2897 /* BB fixme add unlock here */
2902 /* BB On error, should we leave previous search buf (and count and
2903 last entry fields) intact or free the previous one? */
2905 /* Note: On -EAGAIN error only caller can retry on handle based calls
2906 since file handle passed in no longer valid */
2909 cifs_buf_release(pSMB);
2915 CIFSFindClose(const int xid, struct cifsTconInfo *tcon, const __u16 searchHandle)
2918 FINDCLOSE_REQ *pSMB = NULL;
2919 CLOSE_RSP *pSMBr = NULL; /* BB removeme BB */
2922 cFYI(1, ("In CIFSSMBFindClose"));
2923 rc = small_smb_init(SMB_COM_FIND_CLOSE2, 1, tcon, (void **)&pSMB);
2925 /* no sense returning error if session restarted
2926 as file handle has been closed */
2932 pSMBr = (CLOSE_RSP *)pSMB; /* BB removeme BB */
2933 pSMB->FileID = searchHandle;
2934 pSMB->ByteCount = 0;
2935 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2936 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2938 cERROR(1, ("Send error in FindClose = %d", rc));
2940 cifs_stats_inc(&tcon->num_fclose);
2941 cifs_small_buf_release(pSMB);
2943 /* Since session is dead, search handle closed on server already */
2950 #ifdef CONFIG_CIFS_EXPERIMENTAL
2952 CIFSGetSrvInodeNumber(const int xid, struct cifsTconInfo *tcon,
2953 const unsigned char *searchName,
2954 __u64 * inode_number,
2955 const struct nls_table *nls_codepage, int remap)
2958 TRANSACTION2_QPI_REQ *pSMB = NULL;
2959 TRANSACTION2_QPI_RSP *pSMBr = NULL;
2960 int name_len, bytes_returned;
2961 __u16 params, byte_count;
2963 cFYI(1,("In GetSrvInodeNum for %s",searchName));
2967 GetInodeNumberRetry:
2968 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2974 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2976 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
2977 PATH_MAX,nls_codepage, remap);
2978 name_len++; /* trailing null */
2980 } else { /* BB improve the check for buffer overruns BB */
2981 name_len = strnlen(searchName, PATH_MAX);
2982 name_len++; /* trailing null */
2983 strncpy(pSMB->FileName, searchName, name_len);
2986 params = 2 /* level */ + 4 /* rsrvd */ + name_len /* incl null */ ;
2987 pSMB->TotalDataCount = 0;
2988 pSMB->MaxParameterCount = cpu_to_le16(2);
2989 /* BB find exact max data count below from sess structure BB */
2990 pSMB->MaxDataCount = cpu_to_le16(4000);
2991 pSMB->MaxSetupCount = 0;
2995 pSMB->Reserved2 = 0;
2996 pSMB->ParameterOffset = cpu_to_le16(offsetof(
2997 struct smb_com_transaction2_qpi_req ,InformationLevel) - 4);
2998 pSMB->DataCount = 0;
2999 pSMB->DataOffset = 0;
3000 pSMB->SetupCount = 1;
3001 pSMB->Reserved3 = 0;
3002 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
3003 byte_count = params + 1 /* pad */ ;
3004 pSMB->TotalParameterCount = cpu_to_le16(params);
3005 pSMB->ParameterCount = pSMB->TotalParameterCount;
3006 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_INTERNAL_INFO);
3007 pSMB->Reserved4 = 0;
3008 pSMB->hdr.smb_buf_length += byte_count;
3009 pSMB->ByteCount = cpu_to_le16(byte_count);
3011 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3012 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3014 cFYI(1, ("error %d in QueryInternalInfo", rc));
3016 /* decode response */
3017 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3018 if (rc || (pSMBr->ByteCount < 2))
3019 /* BB also check enough total bytes returned */
3020 /* If rc should we check for EOPNOSUPP and
3021 disable the srvino flag? or in caller? */
3022 rc = -EIO; /* bad smb */
3024 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3025 __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
3026 struct file_internal_info * pfinfo;
3027 /* BB Do we need a cast or hash here ? */
3029 cFYI(1, ("Illegal size ret in QryIntrnlInf"));
3031 goto GetInodeNumOut;
3033 pfinfo = (struct file_internal_info *)
3034 (data_offset + (char *) &pSMBr->hdr.Protocol);
3035 *inode_number = pfinfo->UniqueId;
3039 cifs_buf_release(pSMB);
3041 goto GetInodeNumberRetry;
3044 #endif /* CIFS_EXPERIMENTAL */
3047 CIFSGetDFSRefer(const int xid, struct cifsSesInfo *ses,
3048 const unsigned char *searchName,
3049 unsigned char **targetUNCs,
3050 unsigned int *number_of_UNC_in_array,
3051 const struct nls_table *nls_codepage, int remap)
3053 /* TRANS2_GET_DFS_REFERRAL */
3054 TRANSACTION2_GET_DFS_REFER_REQ *pSMB = NULL;
3055 TRANSACTION2_GET_DFS_REFER_RSP *pSMBr = NULL;
3056 struct dfs_referral_level_3 * referrals = NULL;
3062 __u16 params, byte_count;
3063 *number_of_UNC_in_array = 0;
3066 cFYI(1, ("In GetDFSRefer the path %s", searchName));
3070 rc = smb_init(SMB_COM_TRANSACTION2, 15, NULL, (void **) &pSMB,
3075 /* server pointer checked in called function,
3076 but should never be null here anyway */
3077 pSMB->hdr.Mid = GetNextMid(ses->server);
3078 pSMB->hdr.Tid = ses->ipc_tid;
3079 pSMB->hdr.Uid = ses->Suid;
3080 if (ses->capabilities & CAP_STATUS32) {
3081 pSMB->hdr.Flags2 |= SMBFLG2_ERR_STATUS;
3083 if (ses->capabilities & CAP_DFS) {
3084 pSMB->hdr.Flags2 |= SMBFLG2_DFS;
3087 if (ses->capabilities & CAP_UNICODE) {
3088 pSMB->hdr.Flags2 |= SMBFLG2_UNICODE;
3090 cifsConvertToUCS((__le16 *) pSMB->RequestFileName,
3091 searchName, PATH_MAX, nls_codepage, remap);
3092 name_len++; /* trailing null */
3094 } else { /* BB improve the check for buffer overruns BB */
3095 name_len = strnlen(searchName, PATH_MAX);
3096 name_len++; /* trailing null */
3097 strncpy(pSMB->RequestFileName, searchName, name_len);
3100 params = 2 /* level */ + name_len /*includes null */ ;
3101 pSMB->TotalDataCount = 0;
3102 pSMB->DataCount = 0;
3103 pSMB->DataOffset = 0;
3104 pSMB->MaxParameterCount = 0;
3105 pSMB->MaxDataCount = cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
3106 pSMB->MaxSetupCount = 0;
3110 pSMB->Reserved2 = 0;
3111 pSMB->ParameterOffset = cpu_to_le16(offsetof(
3112 struct smb_com_transaction2_get_dfs_refer_req, MaxReferralLevel) - 4);
3113 pSMB->SetupCount = 1;
3114 pSMB->Reserved3 = 0;
3115 pSMB->SubCommand = cpu_to_le16(TRANS2_GET_DFS_REFERRAL);
3116 byte_count = params + 3 /* pad */ ;
3117 pSMB->ParameterCount = cpu_to_le16(params);
3118 pSMB->TotalParameterCount = pSMB->ParameterCount;
3119 pSMB->MaxReferralLevel = cpu_to_le16(3);
3120 pSMB->hdr.smb_buf_length += byte_count;
3121 pSMB->ByteCount = cpu_to_le16(byte_count);
3123 rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB,
3124 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3126 cFYI(1, ("Send error in GetDFSRefer = %d", rc));
3127 } else { /* decode response */
3128 /* BB Add logic to parse referrals here */
3129 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3131 if (rc || (pSMBr->ByteCount < 17)) /* BB also check enough total bytes returned */
3132 rc = -EIO; /* bad smb */
3134 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3135 __u16 data_count = le16_to_cpu(pSMBr->t2.DataCount);
3138 ("Decoding GetDFSRefer response. BCC: %d Offset %d",
3139 pSMBr->ByteCount, data_offset));
3141 (struct dfs_referral_level_3 *)
3142 (8 /* sizeof start of data block */ +
3144 (char *) &pSMBr->hdr.Protocol);
3145 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",
3146 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)));
3147 /* BB This field is actually two bytes in from start of
3148 data block so we could do safety check that DataBlock
3149 begins at address of pSMBr->NumberOfReferrals */
3150 *number_of_UNC_in_array = le16_to_cpu(pSMBr->NumberOfReferrals);
3152 /* BB Fix below so can return more than one referral */
3153 if(*number_of_UNC_in_array > 1)
3154 *number_of_UNC_in_array = 1;
3156 /* get the length of the strings describing refs */
3158 for(i=0;i<*number_of_UNC_in_array;i++) {
3159 /* make sure that DfsPathOffset not past end */
3160 __u16 offset = le16_to_cpu(referrals->DfsPathOffset);
3161 if (offset > data_count) {
3162 /* if invalid referral, stop here and do
3163 not try to copy any more */
3164 *number_of_UNC_in_array = i;
3167 temp = ((char *)referrals) + offset;
3169 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
3170 name_len += UniStrnlen((wchar_t *)temp,data_count);
3172 name_len += strnlen(temp,data_count);
3175 /* BB add check that referral pointer does not fall off end PDU */
3178 /* BB add check for name_len bigger than bcc */
3180 kmalloc(name_len+1+ (*number_of_UNC_in_array),GFP_KERNEL);
3181 if(*targetUNCs == NULL) {
3185 /* copy the ref strings */
3187 (struct dfs_referral_level_3 *)
3188 (8 /* sizeof data hdr */ +
3190 (char *) &pSMBr->hdr.Protocol);
3192 for(i=0;i<*number_of_UNC_in_array;i++) {
3193 temp = ((char *)referrals) + le16_to_cpu(referrals->DfsPathOffset);
3194 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
3195 cifs_strfromUCS_le(*targetUNCs,
3196 (wchar_t *) temp, name_len, nls_codepage);
3198 strncpy(*targetUNCs,temp,name_len);
3200 /* BB update target_uncs pointers */
3210 cifs_buf_release(pSMB);
3218 /* Query File System Info such as free space to old servers such as Win 9x */
3220 SMBOldQFSInfo(const int xid, struct cifsTconInfo *tcon, struct kstatfs *FSData)
3222 /* level 0x01 SMB_QUERY_FILE_SYSTEM_INFO */
3223 TRANSACTION2_QFSI_REQ *pSMB = NULL;
3224 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
3225 FILE_SYSTEM_ALLOC_INFO *response_data;
3227 int bytes_returned = 0;
3228 __u16 params, byte_count;
3230 cFYI(1, ("OldQFSInfo"));
3232 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3236 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3241 params = 2; /* level */
3242 pSMB->TotalDataCount = 0;
3243 pSMB->MaxParameterCount = cpu_to_le16(2);
3244 pSMB->MaxDataCount = cpu_to_le16(1000);
3245 pSMB->MaxSetupCount = 0;
3249 pSMB->Reserved2 = 0;
3250 byte_count = params + 1 /* pad */ ;
3251 pSMB->TotalParameterCount = cpu_to_le16(params);
3252 pSMB->ParameterCount = pSMB->TotalParameterCount;
3253 pSMB->ParameterOffset = cpu_to_le16(offsetof(
3254 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
3255 pSMB->DataCount = 0;
3256 pSMB->DataOffset = 0;
3257 pSMB->SetupCount = 1;
3258 pSMB->Reserved3 = 0;
3259 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
3260 pSMB->InformationLevel = cpu_to_le16(SMB_INFO_ALLOCATION);
3261 pSMB->hdr.smb_buf_length += byte_count;
3262 pSMB->ByteCount = cpu_to_le16(byte_count);
3264 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3265 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3267 cFYI(1, ("Send error in QFSInfo = %d", rc));
3268 } else { /* decode response */
3269 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3271 if (rc || (pSMBr->ByteCount < 18))
3272 rc = -EIO; /* bad smb */
3274 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3275 cFYI(1,("qfsinf resp BCC: %d Offset %d",
3276 pSMBr->ByteCount, data_offset));
3279 (FILE_SYSTEM_ALLOC_INFO *)
3280 (((char *) &pSMBr->hdr.Protocol) + data_offset);
3282 le16_to_cpu(response_data->BytesPerSector) *
3283 le32_to_cpu(response_data->
3284 SectorsPerAllocationUnit);
3286 le32_to_cpu(response_data->TotalAllocationUnits);
3287 FSData->f_bfree = FSData->f_bavail =
3288 le32_to_cpu(response_data->FreeAllocationUnits);
3290 ("Blocks: %lld Free: %lld Block size %ld",
3291 (unsigned long long)FSData->f_blocks,
3292 (unsigned long long)FSData->f_bfree,
3296 cifs_buf_release(pSMB);
3299 goto oldQFSInfoRetry;
3305 CIFSSMBQFSInfo(const int xid, struct cifsTconInfo *tcon, struct kstatfs *FSData)
3307 /* level 0x103 SMB_QUERY_FILE_SYSTEM_INFO */
3308 TRANSACTION2_QFSI_REQ *pSMB = NULL;
3309 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
3310 FILE_SYSTEM_INFO *response_data;
3312 int bytes_returned = 0;
3313 __u16 params, byte_count;
3315 cFYI(1, ("In QFSInfo"));
3317 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3322 params = 2; /* level */
3323 pSMB->TotalDataCount = 0;
3324 pSMB->MaxParameterCount = cpu_to_le16(2);
3325 pSMB->MaxDataCount = cpu_to_le16(1000);
3326 pSMB->MaxSetupCount = 0;
3330 pSMB->Reserved2 = 0;
3331 byte_count = params + 1 /* pad */ ;
3332 pSMB->TotalParameterCount = cpu_to_le16(params);
3333 pSMB->ParameterCount = pSMB->TotalParameterCount;
3334 pSMB->ParameterOffset = cpu_to_le16(offsetof(
3335 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
3336 pSMB->DataCount = 0;
3337 pSMB->DataOffset = 0;
3338 pSMB->SetupCount = 1;
3339 pSMB->Reserved3 = 0;
3340 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
3341 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_SIZE_INFO);
3342 pSMB->hdr.smb_buf_length += byte_count;
3343 pSMB->ByteCount = cpu_to_le16(byte_count);
3345 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3346 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3348 cFYI(1, ("Send error in QFSInfo = %d", rc));
3349 } else { /* decode response */
3350 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3352 if (rc || (pSMBr->ByteCount < 24))
3353 rc = -EIO; /* bad smb */
3355 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3359 *) (((char *) &pSMBr->hdr.Protocol) +
3362 le32_to_cpu(response_data->BytesPerSector) *
3363 le32_to_cpu(response_data->
3364 SectorsPerAllocationUnit);
3366 le64_to_cpu(response_data->TotalAllocationUnits);
3367 FSData->f_bfree = FSData->f_bavail =
3368 le64_to_cpu(response_data->FreeAllocationUnits);
3370 ("Blocks: %lld Free: %lld Block size %ld",
3371 (unsigned long long)FSData->f_blocks,
3372 (unsigned long long)FSData->f_bfree,
3376 cifs_buf_release(pSMB);
3385 CIFSSMBQFSAttributeInfo(const int xid, struct cifsTconInfo *tcon)
3387 /* level 0x105 SMB_QUERY_FILE_SYSTEM_INFO */
3388 TRANSACTION2_QFSI_REQ *pSMB = NULL;
3389 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
3390 FILE_SYSTEM_ATTRIBUTE_INFO *response_data;
3392 int bytes_returned = 0;
3393 __u16 params, byte_count;
3395 cFYI(1, ("In QFSAttributeInfo"));
3397 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3402 params = 2; /* level */
3403 pSMB->TotalDataCount = 0;
3404 pSMB->MaxParameterCount = cpu_to_le16(2);
3405 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
3406 pSMB->MaxSetupCount = 0;
3410 pSMB->Reserved2 = 0;
3411 byte_count = params + 1 /* pad */ ;
3412 pSMB->TotalParameterCount = cpu_to_le16(params);
3413 pSMB->ParameterCount = pSMB->TotalParameterCount;
3414 pSMB->ParameterOffset = cpu_to_le16(offsetof(
3415 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
3416 pSMB->DataCount = 0;
3417 pSMB->DataOffset = 0;
3418 pSMB->SetupCount = 1;
3419 pSMB->Reserved3 = 0;
3420 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
3421 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_ATTRIBUTE_INFO);
3422 pSMB->hdr.smb_buf_length += byte_count;
3423 pSMB->ByteCount = cpu_to_le16(byte_count);
3425 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3426 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3428 cERROR(1, ("Send error in QFSAttributeInfo = %d", rc));
3429 } else { /* decode response */
3430 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3432 if (rc || (pSMBr->ByteCount < 13)) { /* BB also check enough bytes returned */
3433 rc = -EIO; /* bad smb */
3435 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3437 (FILE_SYSTEM_ATTRIBUTE_INFO
3438 *) (((char *) &pSMBr->hdr.Protocol) +
3440 memcpy(&tcon->fsAttrInfo, response_data,
3441 sizeof (FILE_SYSTEM_ATTRIBUTE_INFO));
3444 cifs_buf_release(pSMB);
3447 goto QFSAttributeRetry;
3453 CIFSSMBQFSDeviceInfo(const int xid, struct cifsTconInfo *tcon)
3455 /* level 0x104 SMB_QUERY_FILE_SYSTEM_INFO */
3456 TRANSACTION2_QFSI_REQ *pSMB = NULL;
3457 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
3458 FILE_SYSTEM_DEVICE_INFO *response_data;
3460 int bytes_returned = 0;
3461 __u16 params, byte_count;
3463 cFYI(1, ("In QFSDeviceInfo"));
3465 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3470 params = 2; /* level */
3471 pSMB->TotalDataCount = 0;
3472 pSMB->MaxParameterCount = cpu_to_le16(2);
3473 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
3474 pSMB->MaxSetupCount = 0;
3478 pSMB->Reserved2 = 0;
3479 byte_count = params + 1 /* pad */ ;
3480 pSMB->TotalParameterCount = cpu_to_le16(params);
3481 pSMB->ParameterCount = pSMB->TotalParameterCount;
3482 pSMB->ParameterOffset = cpu_to_le16(offsetof(
3483 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
3485 pSMB->DataCount = 0;
3486 pSMB->DataOffset = 0;
3487 pSMB->SetupCount = 1;
3488 pSMB->Reserved3 = 0;
3489 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
3490 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_DEVICE_INFO);
3491 pSMB->hdr.smb_buf_length += byte_count;
3492 pSMB->ByteCount = cpu_to_le16(byte_count);
3494 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3495 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3497 cFYI(1, ("Send error in QFSDeviceInfo = %d", rc));
3498 } else { /* decode response */
3499 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3501 if (rc || (pSMBr->ByteCount < sizeof (FILE_SYSTEM_DEVICE_INFO)))
3502 rc = -EIO; /* bad smb */
3504 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3506 (FILE_SYSTEM_DEVICE_INFO *)
3507 (((char *) &pSMBr->hdr.Protocol) +
3509 memcpy(&tcon->fsDevInfo, response_data,
3510 sizeof (FILE_SYSTEM_DEVICE_INFO));
3513 cifs_buf_release(pSMB);
3516 goto QFSDeviceRetry;
3522 CIFSSMBQFSUnixInfo(const int xid, struct cifsTconInfo *tcon)
3524 /* level 0x200 SMB_QUERY_CIFS_UNIX_INFO */
3525 TRANSACTION2_QFSI_REQ *pSMB = NULL;
3526 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
3527 FILE_SYSTEM_UNIX_INFO *response_data;
3529 int bytes_returned = 0;
3530 __u16 params, byte_count;
3532 cFYI(1, ("In QFSUnixInfo"));
3534 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3539 params = 2; /* level */
3540 pSMB->TotalDataCount = 0;
3541 pSMB->DataCount = 0;
3542 pSMB->DataOffset = 0;
3543 pSMB->MaxParameterCount = cpu_to_le16(2);
3544 pSMB->MaxDataCount = cpu_to_le16(100); /* BB find exact max SMB PDU from sess structure BB */
3545 pSMB->MaxSetupCount = 0;
3549 pSMB->Reserved2 = 0;
3550 byte_count = params + 1 /* pad */ ;
3551 pSMB->ParameterCount = cpu_to_le16(params);
3552 pSMB->TotalParameterCount = pSMB->ParameterCount;
3553 pSMB->ParameterOffset = cpu_to_le16(offsetof(struct
3554 smb_com_transaction2_qfsi_req, InformationLevel) - 4);
3555 pSMB->SetupCount = 1;
3556 pSMB->Reserved3 = 0;
3557 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
3558 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_CIFS_UNIX_INFO);
3559 pSMB->hdr.smb_buf_length += byte_count;
3560 pSMB->ByteCount = cpu_to_le16(byte_count);
3562 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3563 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3565 cERROR(1, ("Send error in QFSUnixInfo = %d", rc));
3566 } else { /* decode response */
3567 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3569 if (rc || (pSMBr->ByteCount < 13)) {
3570 rc = -EIO; /* bad smb */
3572 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3574 (FILE_SYSTEM_UNIX_INFO
3575 *) (((char *) &pSMBr->hdr.Protocol) +
3577 memcpy(&tcon->fsUnixInfo, response_data,
3578 sizeof (FILE_SYSTEM_UNIX_INFO));
3581 cifs_buf_release(pSMB);
3591 CIFSSMBSetFSUnixInfo(const int xid, struct cifsTconInfo *tcon, __u64 cap)
3593 /* level 0x200 SMB_SET_CIFS_UNIX_INFO */
3594 TRANSACTION2_SETFSI_REQ *pSMB = NULL;
3595 TRANSACTION2_SETFSI_RSP *pSMBr = NULL;
3597 int bytes_returned = 0;
3598 __u16 params, param_offset, offset, byte_count;
3600 cFYI(1, ("In SETFSUnixInfo"));
3602 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3607 params = 4; /* 2 bytes zero followed by info level. */
3608 pSMB->MaxSetupCount = 0;
3612 pSMB->Reserved2 = 0;
3613 param_offset = offsetof(struct smb_com_transaction2_setfsi_req, FileNum) - 4;
3614 offset = param_offset + params;
3616 pSMB->MaxParameterCount = cpu_to_le16(4);
3617 pSMB->MaxDataCount = cpu_to_le16(100); /* BB find exact max SMB PDU from sess structure BB */
3618 pSMB->SetupCount = 1;
3619 pSMB->Reserved3 = 0;
3620 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FS_INFORMATION);
3621 byte_count = 1 /* pad */ + params + 12;
3623 pSMB->DataCount = cpu_to_le16(12);
3624 pSMB->ParameterCount = cpu_to_le16(params);
3625 pSMB->TotalDataCount = pSMB->DataCount;
3626 pSMB->TotalParameterCount = pSMB->ParameterCount;
3627 pSMB->ParameterOffset = cpu_to_le16(param_offset);
3628 pSMB->DataOffset = cpu_to_le16(offset);
3632 pSMB->InformationLevel = cpu_to_le16(SMB_SET_CIFS_UNIX_INFO);
3635 pSMB->ClientUnixMajor = cpu_to_le16(CIFS_UNIX_MAJOR_VERSION);
3636 pSMB->ClientUnixMinor = cpu_to_le16(CIFS_UNIX_MINOR_VERSION);
3637 pSMB->ClientUnixCap = cpu_to_le64(cap);
3639 pSMB->hdr.smb_buf_length += byte_count;
3640 pSMB->ByteCount = cpu_to_le16(byte_count);
3642 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3643 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3645 cERROR(1, ("Send error in SETFSUnixInfo = %d", rc));
3646 } else { /* decode response */
3647 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3649 rc = -EIO; /* bad smb */
3652 cifs_buf_release(pSMB);
3655 goto SETFSUnixRetry;
3663 CIFSSMBQFSPosixInfo(const int xid, struct cifsTconInfo *tcon,
3664 struct kstatfs *FSData)
3666 /* level 0x201 SMB_QUERY_CIFS_POSIX_INFO */
3667 TRANSACTION2_QFSI_REQ *pSMB = NULL;
3668 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
3669 FILE_SYSTEM_POSIX_INFO *response_data;
3671 int bytes_returned = 0;
3672 __u16 params, byte_count;
3674 cFYI(1, ("In QFSPosixInfo"));
3676 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3681 params = 2; /* level */
3682 pSMB->TotalDataCount = 0;
3683 pSMB->DataCount = 0;
3684 pSMB->DataOffset = 0;
3685 pSMB->MaxParameterCount = cpu_to_le16(2);
3686 pSMB->MaxDataCount = cpu_to_le16(100); /* BB find exact max SMB PDU from sess structure BB */
3687 pSMB->MaxSetupCount = 0;
3691 pSMB->Reserved2 = 0;
3692 byte_count = params + 1 /* pad */ ;
3693 pSMB->ParameterCount = cpu_to_le16(params);
3694 pSMB->TotalParameterCount = pSMB->ParameterCount;
3695 pSMB->ParameterOffset = cpu_to_le16(offsetof(struct
3696 smb_com_transaction2_qfsi_req, InformationLevel) - 4);
3697 pSMB->SetupCount = 1;
3698 pSMB->Reserved3 = 0;
3699 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
3700 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_POSIX_FS_INFO);
3701 pSMB->hdr.smb_buf_length += byte_count;
3702 pSMB->ByteCount = cpu_to_le16(byte_count);
3704 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3705 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3707 cFYI(1, ("Send error in QFSUnixInfo = %d", rc));
3708 } else { /* decode response */
3709 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3711 if (rc || (pSMBr->ByteCount < 13)) {
3712 rc = -EIO; /* bad smb */
3714 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3716 (FILE_SYSTEM_POSIX_INFO
3717 *) (((char *) &pSMBr->hdr.Protocol) +
3720 le32_to_cpu(response_data->BlockSize);
3722 le64_to_cpu(response_data->TotalBlocks);
3724 le64_to_cpu(response_data->BlocksAvail);
3725 if(response_data->UserBlocksAvail == -1) {
3726 FSData->f_bavail = FSData->f_bfree;
3729 le64_to_cpu(response_data->UserBlocksAvail);
3731 if(response_data->TotalFileNodes != -1)
3733 le64_to_cpu(response_data->TotalFileNodes);
3734 if(response_data->FreeFileNodes != -1)
3736 le64_to_cpu(response_data->FreeFileNodes);
3739 cifs_buf_release(pSMB);
3748 /* We can not use write of zero bytes trick to
3749 set file size due to need for large file support. Also note that
3750 this SetPathInfo is preferred to SetFileInfo based method in next
3751 routine which is only needed to work around a sharing violation bug
3752 in Samba which this routine can run into */
3755 CIFSSMBSetEOF(const int xid, struct cifsTconInfo *tcon, const char *fileName,
3756 __u64 size, int SetAllocation,
3757 const struct nls_table *nls_codepage, int remap)
3759 struct smb_com_transaction2_spi_req *pSMB = NULL;
3760 struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
3761 struct file_end_of_file_info *parm_data;
3764 int bytes_returned = 0;
3765 __u16 params, byte_count, data_count, param_offset, offset;
3767 cFYI(1, ("In SetEOF"));
3769 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3774 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3776 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
3777 PATH_MAX, nls_codepage, remap);
3778 name_len++; /* trailing null */
3780 } else { /* BB improve the check for buffer overruns BB */
3781 name_len = strnlen(fileName, PATH_MAX);
3782 name_len++; /* trailing null */
3783 strncpy(pSMB->FileName, fileName, name_len);
3785 params = 6 + name_len;
3786 data_count = sizeof (struct file_end_of_file_info);
3787 pSMB->MaxParameterCount = cpu_to_le16(2);
3788 pSMB->MaxDataCount = cpu_to_le16(4100);
3789 pSMB->MaxSetupCount = 0;
3793 pSMB->Reserved2 = 0;
3794 param_offset = offsetof(struct smb_com_transaction2_spi_req,
3795 InformationLevel) - 4;
3796 offset = param_offset + params;
3798 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
3799 pSMB->InformationLevel =
3800 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2);
3802 pSMB->InformationLevel =
3803 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO);
3804 } else /* Set File Size */ {
3805 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
3806 pSMB->InformationLevel =
3807 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO2);
3809 pSMB->InformationLevel =
3810 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO);
3814 (struct file_end_of_file_info *) (((char *) &pSMB->hdr.Protocol) +
3816 pSMB->ParameterOffset = cpu_to_le16(param_offset);
3817 pSMB->DataOffset = cpu_to_le16(offset);
3818 pSMB->SetupCount = 1;
3819 pSMB->Reserved3 = 0;
3820 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
3821 byte_count = 3 /* pad */ + params + data_count;
3822 pSMB->DataCount = cpu_to_le16(data_count);
3823 pSMB->TotalDataCount = pSMB->DataCount;
3824 pSMB->ParameterCount = cpu_to_le16(params);
3825 pSMB->TotalParameterCount = pSMB->ParameterCount;
3826 pSMB->Reserved4 = 0;
3827 pSMB->hdr.smb_buf_length += byte_count;
3828 parm_data->FileSize = cpu_to_le64(size);
3829 pSMB->ByteCount = cpu_to_le16(byte_count);
3830 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3831 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3833 cFYI(1, ("SetPathInfo (file size) returned %d", rc));
3836 cifs_buf_release(pSMB);
3845 CIFSSMBSetFileSize(const int xid, struct cifsTconInfo *tcon, __u64 size,
3846 __u16 fid, __u32 pid_of_opener, int SetAllocation)
3848 struct smb_com_transaction2_sfi_req *pSMB = NULL;
3849 struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
3851 struct file_end_of_file_info *parm_data;
3853 int bytes_returned = 0;
3854 __u16 params, param_offset, offset, byte_count, count;
3856 cFYI(1, ("SetFileSize (via SetFileInfo) %lld",
3858 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
3863 pSMBr = (struct smb_com_transaction2_sfi_rsp *)pSMB;
3865 pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
3866 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));
3869 pSMB->MaxSetupCount = 0;
3873 pSMB->Reserved2 = 0;
3874 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
3875 offset = param_offset + params;
3877 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
3879 count = sizeof(struct file_end_of_file_info);
3880 pSMB->MaxParameterCount = cpu_to_le16(2);
3881 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB PDU from sess */
3882 pSMB->SetupCount = 1;
3883 pSMB->Reserved3 = 0;
3884 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
3885 byte_count = 3 /* pad */ + params + count;
3886 pSMB->DataCount = cpu_to_le16(count);
3887 pSMB->ParameterCount = cpu_to_le16(params);
3888 pSMB->TotalDataCount = pSMB->DataCount;
3889 pSMB->TotalParameterCount = pSMB->ParameterCount;
3890 pSMB->ParameterOffset = cpu_to_le16(param_offset);
3892 (struct file_end_of_file_info *) (((char *) &pSMB->hdr.Protocol) +
3894 pSMB->DataOffset = cpu_to_le16(offset);
3895 parm_data->FileSize = cpu_to_le64(size);
3898 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
3899 pSMB->InformationLevel =
3900 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2);
3902 pSMB->InformationLevel =
3903 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO);
3904 } else /* Set File Size */ {
3905 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
3906 pSMB->InformationLevel =
3907 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO2);
3909 pSMB->InformationLevel =
3910 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO);
3912 pSMB->Reserved4 = 0;
3913 pSMB->hdr.smb_buf_length += byte_count;
3914 pSMB->ByteCount = cpu_to_le16(byte_count);
3915 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3916 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3919 ("Send error in SetFileInfo (SetFileSize) = %d",
3924 cifs_small_buf_release(pSMB);
3926 /* Note: On -EAGAIN error only caller can retry on handle based calls
3927 since file handle passed in no longer valid */
3932 /* Some legacy servers such as NT4 require that the file times be set on
3933 an open handle, rather than by pathname - this is awkward due to
3934 potential access conflicts on the open, but it is unavoidable for these
3935 old servers since the only other choice is to go from 100 nanosecond DCE
3936 time and resort to the original setpathinfo level which takes the ancient
3937 DOS time format with 2 second granularity */
3939 CIFSSMBSetFileTimes(const int xid, struct cifsTconInfo *tcon, const FILE_BASIC_INFO * data,
3942 struct smb_com_transaction2_sfi_req *pSMB = NULL;
3943 struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
3946 int bytes_returned = 0;
3947 __u16 params, param_offset, offset, byte_count, count;
3949 cFYI(1, ("Set Times (via SetFileInfo)"));
3950 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
3955 pSMBr = (struct smb_com_transaction2_sfi_rsp *)pSMB;
3957 /* At this point there is no need to override the current pid
3958 with the pid of the opener, but that could change if we someday
3959 use an existing handle (rather than opening one on the fly) */
3960 /* pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
3961 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));*/
3964 pSMB->MaxSetupCount = 0;
3968 pSMB->Reserved2 = 0;
3969 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
3970 offset = param_offset + params;
3972 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
3974 count = sizeof (FILE_BASIC_INFO);
3975 pSMB->MaxParameterCount = cpu_to_le16(2);
3976 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB PDU from sess */
3977 pSMB->SetupCount = 1;
3978 pSMB->Reserved3 = 0;
3979 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
3980 byte_count = 3 /* pad */ + params + count;
3981 pSMB->DataCount = cpu_to_le16(count);
3982 pSMB->ParameterCount = cpu_to_le16(params);
3983 pSMB->TotalDataCount = pSMB->DataCount;
3984 pSMB->TotalParameterCount = pSMB->ParameterCount;
3985 pSMB->ParameterOffset = cpu_to_le16(param_offset);
3986 pSMB->DataOffset = cpu_to_le16(offset);
3988 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
3989 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO2);
3991 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO);
3992 pSMB->Reserved4 = 0;
3993 pSMB->hdr.smb_buf_length += byte_count;
3994 pSMB->ByteCount = cpu_to_le16(byte_count);
3995 memcpy(data_offset,data,sizeof(FILE_BASIC_INFO));
3996 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3997 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3999 cFYI(1,("Send error in Set Time (SetFileInfo) = %d",rc));
4002 cifs_small_buf_release(pSMB);
4004 /* Note: On -EAGAIN error only caller can retry on handle based calls
4005 since file handle passed in no longer valid */
4012 CIFSSMBSetTimes(const int xid, struct cifsTconInfo *tcon, const char *fileName,
4013 const FILE_BASIC_INFO * data,
4014 const struct nls_table *nls_codepage, int remap)
4016 TRANSACTION2_SPI_REQ *pSMB = NULL;
4017 TRANSACTION2_SPI_RSP *pSMBr = NULL;
4020 int bytes_returned = 0;
4022 __u16 params, param_offset, offset, byte_count, count;
4024 cFYI(1, ("In SetTimes"));
4027 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4032 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4034 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
4035 PATH_MAX, nls_codepage, remap);
4036 name_len++; /* trailing null */
4038 } else { /* BB improve the check for buffer overruns BB */
4039 name_len = strnlen(fileName, PATH_MAX);
4040 name_len++; /* trailing null */
4041 strncpy(pSMB->FileName, fileName, name_len);
4044 params = 6 + name_len;
4045 count = sizeof (FILE_BASIC_INFO);
4046 pSMB->MaxParameterCount = cpu_to_le16(2);
4047 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
4048 pSMB->MaxSetupCount = 0;
4052 pSMB->Reserved2 = 0;
4053 param_offset = offsetof(struct smb_com_transaction2_spi_req,
4054 InformationLevel) - 4;
4055 offset = param_offset + params;
4056 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
4057 pSMB->ParameterOffset = cpu_to_le16(param_offset);
4058 pSMB->DataOffset = cpu_to_le16(offset);
4059 pSMB->SetupCount = 1;
4060 pSMB->Reserved3 = 0;
4061 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
4062 byte_count = 3 /* pad */ + params + count;
4064 pSMB->DataCount = cpu_to_le16(count);
4065 pSMB->ParameterCount = cpu_to_le16(params);
4066 pSMB->TotalDataCount = pSMB->DataCount;
4067 pSMB->TotalParameterCount = pSMB->ParameterCount;
4068 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
4069 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO2);
4071 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO);
4072 pSMB->Reserved4 = 0;
4073 pSMB->hdr.smb_buf_length += byte_count;
4074 memcpy(data_offset, data, sizeof (FILE_BASIC_INFO));
4075 pSMB->ByteCount = cpu_to_le16(byte_count);
4076 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4077 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4079 cFYI(1, ("SetPathInfo (times) returned %d", rc));
4082 cifs_buf_release(pSMB);
4090 /* Can not be used to set time stamps yet (due to old DOS time format) */
4091 /* Can be used to set attributes */
4092 #if 0 /* Possibly not needed - since it turns out that strangely NT4 has a bug
4093 handling it anyway and NT4 was what we thought it would be needed for
4094 Do not delete it until we prove whether needed for Win9x though */
4096 CIFSSMBSetAttrLegacy(int xid, struct cifsTconInfo *tcon, char *fileName,
4097 __u16 dos_attrs, const struct nls_table *nls_codepage)
4099 SETATTR_REQ *pSMB = NULL;
4100 SETATTR_RSP *pSMBr = NULL;
4105 cFYI(1, ("In SetAttrLegacy"));
4108 rc = smb_init(SMB_COM_SETATTR, 8, tcon, (void **) &pSMB,
4113 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4115 ConvertToUCS((__le16 *) pSMB->fileName, fileName,
4116 PATH_MAX, nls_codepage);
4117 name_len++; /* trailing null */
4119 } else { /* BB improve the check for buffer overruns BB */
4120 name_len = strnlen(fileName, PATH_MAX);
4121 name_len++; /* trailing null */
4122 strncpy(pSMB->fileName, fileName, name_len);
4124 pSMB->attr = cpu_to_le16(dos_attrs);
4125 pSMB->BufferFormat = 0x04;
4126 pSMB->hdr.smb_buf_length += name_len + 1;
4127 pSMB->ByteCount = cpu_to_le16(name_len + 1);
4128 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4129 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4131 cFYI(1, ("Error in LegacySetAttr = %d", rc));
4134 cifs_buf_release(pSMB);
4137 goto SetAttrLgcyRetry;
4141 #endif /* temporarily unneeded SetAttr legacy function */
4144 CIFSSMBUnixSetPerms(const int xid, struct cifsTconInfo *tcon,
4145 char *fileName, __u64 mode, __u64 uid, __u64 gid,
4146 dev_t device, const struct nls_table *nls_codepage,
4149 TRANSACTION2_SPI_REQ *pSMB = NULL;
4150 TRANSACTION2_SPI_RSP *pSMBr = NULL;
4153 int bytes_returned = 0;
4154 FILE_UNIX_BASIC_INFO *data_offset;
4155 __u16 params, param_offset, offset, count, byte_count;
4157 cFYI(1, ("In SetUID/GID/Mode"));
4159 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4164 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4166 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
4167 PATH_MAX, nls_codepage, remap);
4168 name_len++; /* trailing null */
4170 } else { /* BB improve the check for buffer overruns BB */
4171 name_len = strnlen(fileName, PATH_MAX);
4172 name_len++; /* trailing null */
4173 strncpy(pSMB->FileName, fileName, name_len);
4176 params = 6 + name_len;
4177 count = sizeof (FILE_UNIX_BASIC_INFO);
4178 pSMB->MaxParameterCount = cpu_to_le16(2);
4179 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
4180 pSMB->MaxSetupCount = 0;
4184 pSMB->Reserved2 = 0;
4185 param_offset = offsetof(struct smb_com_transaction2_spi_req,
4186 InformationLevel) - 4;
4187 offset = param_offset + params;
4189 (FILE_UNIX_BASIC_INFO *) ((char *) &pSMB->hdr.Protocol +
4191 memset(data_offset, 0, count);
4192 pSMB->DataOffset = cpu_to_le16(offset);
4193 pSMB->ParameterOffset = cpu_to_le16(param_offset);
4194 pSMB->SetupCount = 1;
4195 pSMB->Reserved3 = 0;
4196 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
4197 byte_count = 3 /* pad */ + params + count;
4198 pSMB->ParameterCount = cpu_to_le16(params);
4199 pSMB->DataCount = cpu_to_le16(count);
4200 pSMB->TotalParameterCount = pSMB->ParameterCount;
4201 pSMB->TotalDataCount = pSMB->DataCount;
4202 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_BASIC);
4203 pSMB->Reserved4 = 0;
4204 pSMB->hdr.smb_buf_length += byte_count;
4205 data_offset->Uid = cpu_to_le64(uid);
4206 data_offset->Gid = cpu_to_le64(gid);
4207 /* better to leave device as zero when it is */
4208 data_offset->DevMajor = cpu_to_le64(MAJOR(device));
4209 data_offset->DevMinor = cpu_to_le64(MINOR(device));
4210 data_offset->Permissions = cpu_to_le64(mode);
4213 data_offset->Type = cpu_to_le32(UNIX_FILE);
4214 else if(S_ISDIR(mode))
4215 data_offset->Type = cpu_to_le32(UNIX_DIR);
4216 else if(S_ISLNK(mode))
4217 data_offset->Type = cpu_to_le32(UNIX_SYMLINK);
4218 else if(S_ISCHR(mode))
4219 data_offset->Type = cpu_to_le32(UNIX_CHARDEV);
4220 else if(S_ISBLK(mode))
4221 data_offset->Type = cpu_to_le32(UNIX_BLOCKDEV);
4222 else if(S_ISFIFO(mode))
4223 data_offset->Type = cpu_to_le32(UNIX_FIFO);
4224 else if(S_ISSOCK(mode))
4225 data_offset->Type = cpu_to_le32(UNIX_SOCKET);
4228 pSMB->ByteCount = cpu_to_le16(byte_count);
4229 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4230 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4232 cFYI(1, ("SetPathInfo (perms) returned %d", rc));
4236 cifs_buf_release(pSMB);
4242 int CIFSSMBNotify(const int xid, struct cifsTconInfo *tcon,
4243 const int notify_subdirs, const __u16 netfid,
4244 __u32 filter, struct file * pfile, int multishot,
4245 const struct nls_table *nls_codepage)
4248 struct smb_com_transaction_change_notify_req * pSMB = NULL;
4249 struct smb_com_transaction_change_notify_rsp * pSMBr = NULL;
4250 struct dir_notify_req *dnotify_req;
4253 cFYI(1, ("In CIFSSMBNotify for file handle %d",(int)netfid));
4254 rc = smb_init(SMB_COM_NT_TRANSACT, 23, tcon, (void **) &pSMB,
4259 pSMB->TotalParameterCount = 0 ;
4260 pSMB->TotalDataCount = 0;
4261 pSMB->MaxParameterCount = cpu_to_le32(2);
4262 /* BB find exact data count max from sess structure BB */
4263 pSMB->MaxDataCount = 0; /* same in little endian or be */
4264 pSMB->MaxSetupCount = 4;
4266 pSMB->ParameterOffset = 0;
4267 pSMB->DataCount = 0;
4268 pSMB->DataOffset = 0;
4269 pSMB->SetupCount = 4; /* single byte does not need le conversion */
4270 pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_NOTIFY_CHANGE);
4271 pSMB->ParameterCount = pSMB->TotalParameterCount;
4273 pSMB->WatchTree = 1; /* one byte - no le conversion needed */
4274 pSMB->Reserved2 = 0;
4275 pSMB->CompletionFilter = cpu_to_le32(filter);
4276 pSMB->Fid = netfid; /* file handle always le */
4277 pSMB->ByteCount = 0;
4279 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4280 (struct smb_hdr *) pSMBr, &bytes_returned, -1);
4282 cFYI(1, ("Error in Notify = %d", rc));
4284 /* Add file to outstanding requests */
4285 dnotify_req = (struct dir_notify_req *) kmalloc(
4286 sizeof(struct dir_notify_req), GFP_KERNEL);
4287 dnotify_req->Pid = pSMB->hdr.Pid;
4288 dnotify_req->PidHigh = pSMB->hdr.PidHigh;
4289 dnotify_req->Mid = pSMB->hdr.Mid;
4290 dnotify_req->Tid = pSMB->hdr.Tid;
4291 dnotify_req->Uid = pSMB->hdr.Uid;
4292 dnotify_req->netfid = netfid;
4293 dnotify_req->pfile = pfile;
4294 dnotify_req->filter = filter;
4295 dnotify_req->multishot = multishot;
4296 spin_lock(&GlobalMid_Lock);
4297 list_add_tail(&dnotify_req->lhead, &GlobalDnotifyReqList);
4298 spin_unlock(&GlobalMid_Lock);
4300 cifs_buf_release(pSMB);
4303 #ifdef CONFIG_CIFS_XATTR
4305 CIFSSMBQAllEAs(const int xid, struct cifsTconInfo *tcon,
4306 const unsigned char *searchName,
4307 char * EAData, size_t buf_size,
4308 const struct nls_table *nls_codepage, int remap)
4310 /* BB assumes one setup word */
4311 TRANSACTION2_QPI_REQ *pSMB = NULL;
4312 TRANSACTION2_QPI_RSP *pSMBr = NULL;
4316 struct fea * temp_fea;
4318 __u16 params, byte_count;
4320 cFYI(1, ("In Query All EAs path %s", searchName));
4322 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4327 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4329 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
4330 PATH_MAX, nls_codepage, remap);
4331 name_len++; /* trailing null */
4333 } else { /* BB improve the check for buffer overruns BB */
4334 name_len = strnlen(searchName, PATH_MAX);
4335 name_len++; /* trailing null */
4336 strncpy(pSMB->FileName, searchName, name_len);
4339 params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */ ;
4340 pSMB->TotalDataCount = 0;
4341 pSMB->MaxParameterCount = cpu_to_le16(2);
4342 pSMB->MaxDataCount = cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
4343 pSMB->MaxSetupCount = 0;
4347 pSMB->Reserved2 = 0;
4348 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4349 struct smb_com_transaction2_qpi_req ,InformationLevel) - 4);
4350 pSMB->DataCount = 0;
4351 pSMB->DataOffset = 0;
4352 pSMB->SetupCount = 1;
4353 pSMB->Reserved3 = 0;
4354 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
4355 byte_count = params + 1 /* pad */ ;
4356 pSMB->TotalParameterCount = cpu_to_le16(params);
4357 pSMB->ParameterCount = pSMB->TotalParameterCount;
4358 pSMB->InformationLevel = cpu_to_le16(SMB_INFO_QUERY_ALL_EAS);
4359 pSMB->Reserved4 = 0;
4360 pSMB->hdr.smb_buf_length += byte_count;
4361 pSMB->ByteCount = cpu_to_le16(byte_count);
4363 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4364 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4366 cFYI(1, ("Send error in QueryAllEAs = %d", rc));
4367 } else { /* decode response */
4368 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4370 /* BB also check enough total bytes returned */
4371 /* BB we need to improve the validity checking
4372 of these trans2 responses */
4373 if (rc || (pSMBr->ByteCount < 4))
4374 rc = -EIO; /* bad smb */
4375 /* else if (pFindData){
4376 memcpy((char *) pFindData,
4377 (char *) &pSMBr->hdr.Protocol +
4380 /* check that length of list is not more than bcc */
4381 /* check that each entry does not go beyond length
4383 /* check that each element of each entry does not
4384 go beyond end of list */
4385 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4386 struct fealist * ea_response_data;
4388 /* validate_trans2_offsets() */
4389 /* BB to check if(start of smb + data_offset > &bcc+ bcc)*/
4390 ea_response_data = (struct fealist *)
4391 (((char *) &pSMBr->hdr.Protocol) +
4393 name_len = le32_to_cpu(ea_response_data->list_len);
4394 cFYI(1,("ea length %d", name_len));
4396 /* returned EA size zeroed at top of function */
4397 cFYI(1,("empty EA list returned from server"));
4399 /* account for ea list len */
4401 temp_fea = ea_response_data->list;
4402 temp_ptr = (char *)temp_fea;
4403 while(name_len > 0) {
4407 rc += temp_fea->name_len;
4408 /* account for prefix user. and trailing null */
4410 if(rc<(int)buf_size) {
4411 memcpy(EAData,"user.",5);
4413 memcpy(EAData,temp_ptr,temp_fea->name_len);
4414 EAData+=temp_fea->name_len;
4415 /* null terminate name */
4417 EAData = EAData + 1;
4418 } else if(buf_size == 0) {
4419 /* skip copy - calc size only */
4421 /* stop before overrun buffer */
4425 name_len -= temp_fea->name_len;
4426 temp_ptr += temp_fea->name_len;
4427 /* account for trailing null */
4430 value_len = le16_to_cpu(temp_fea->value_len);
4431 name_len -= value_len;
4432 temp_ptr += value_len;
4433 /* BB check that temp_ptr is still within smb BB*/
4434 /* no trailing null to account for in value len */
4435 /* go on to next EA */
4436 temp_fea = (struct fea *)temp_ptr;
4442 cifs_buf_release(pSMB);
4449 ssize_t CIFSSMBQueryEA(const int xid,struct cifsTconInfo * tcon,
4450 const unsigned char * searchName,const unsigned char * ea_name,
4451 unsigned char * ea_value, size_t buf_size,
4452 const struct nls_table *nls_codepage, int remap)
4454 TRANSACTION2_QPI_REQ *pSMB = NULL;
4455 TRANSACTION2_QPI_RSP *pSMBr = NULL;
4459 struct fea * temp_fea;
4461 __u16 params, byte_count;
4463 cFYI(1, ("In Query EA path %s", searchName));
4465 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4470 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4472 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
4473 PATH_MAX, nls_codepage, remap);
4474 name_len++; /* trailing null */
4476 } else { /* BB improve the check for buffer overruns BB */
4477 name_len = strnlen(searchName, PATH_MAX);
4478 name_len++; /* trailing null */
4479 strncpy(pSMB->FileName, searchName, name_len);
4482 params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */ ;
4483 pSMB->TotalDataCount = 0;
4484 pSMB->MaxParameterCount = cpu_to_le16(2);
4485 pSMB->MaxDataCount = cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
4486 pSMB->MaxSetupCount = 0;
4490 pSMB->Reserved2 = 0;
4491 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4492 struct smb_com_transaction2_qpi_req ,InformationLevel) - 4);
4493 pSMB->DataCount = 0;
4494 pSMB->DataOffset = 0;
4495 pSMB->SetupCount = 1;
4496 pSMB->Reserved3 = 0;
4497 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
4498 byte_count = params + 1 /* pad */ ;
4499 pSMB->TotalParameterCount = cpu_to_le16(params);
4500 pSMB->ParameterCount = pSMB->TotalParameterCount;
4501 pSMB->InformationLevel = cpu_to_le16(SMB_INFO_QUERY_ALL_EAS);
4502 pSMB->Reserved4 = 0;
4503 pSMB->hdr.smb_buf_length += byte_count;
4504 pSMB->ByteCount = cpu_to_le16(byte_count);
4506 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4507 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4509 cFYI(1, ("Send error in Query EA = %d", rc));
4510 } else { /* decode response */
4511 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4513 /* BB also check enough total bytes returned */
4514 /* BB we need to improve the validity checking
4515 of these trans2 responses */
4516 if (rc || (pSMBr->ByteCount < 4))
4517 rc = -EIO; /* bad smb */
4518 /* else if (pFindData){
4519 memcpy((char *) pFindData,
4520 (char *) &pSMBr->hdr.Protocol +
4523 /* check that length of list is not more than bcc */
4524 /* check that each entry does not go beyond length
4526 /* check that each element of each entry does not
4527 go beyond end of list */
4528 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4529 struct fealist * ea_response_data;
4531 /* validate_trans2_offsets() */
4532 /* BB to check if(start of smb + data_offset > &bcc+ bcc)*/
4533 ea_response_data = (struct fealist *)
4534 (((char *) &pSMBr->hdr.Protocol) +
4536 name_len = le32_to_cpu(ea_response_data->list_len);
4537 cFYI(1,("ea length %d", name_len));
4539 /* returned EA size zeroed at top of function */
4540 cFYI(1,("empty EA list returned from server"));
4542 /* account for ea list len */
4544 temp_fea = ea_response_data->list;
4545 temp_ptr = (char *)temp_fea;
4546 /* loop through checking if we have a matching
4547 name and then return the associated value */
4548 while(name_len > 0) {
4552 value_len = le16_to_cpu(temp_fea->value_len);
4553 /* BB validate that value_len falls within SMB,
4554 even though maximum for name_len is 255 */
4555 if(memcmp(temp_fea->name,ea_name,
4556 temp_fea->name_len) == 0) {
4559 /* account for prefix user. and trailing null */
4560 if(rc<=(int)buf_size) {
4562 temp_fea->name+temp_fea->name_len+1,
4564 /* ea values, unlike ea names,
4565 are not null terminated */
4566 } else if(buf_size == 0) {
4567 /* skip copy - calc size only */
4569 /* stop before overrun buffer */
4574 name_len -= temp_fea->name_len;
4575 temp_ptr += temp_fea->name_len;
4576 /* account for trailing null */
4579 name_len -= value_len;
4580 temp_ptr += value_len;
4581 /* no trailing null to account for in value len */
4582 /* go on to next EA */
4583 temp_fea = (struct fea *)temp_ptr;
4589 cifs_buf_release(pSMB);
4597 CIFSSMBSetEA(const int xid, struct cifsTconInfo *tcon, const char *fileName,
4598 const char * ea_name, const void * ea_value,
4599 const __u16 ea_value_len, const struct nls_table *nls_codepage,
4602 struct smb_com_transaction2_spi_req *pSMB = NULL;
4603 struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
4604 struct fealist *parm_data;
4607 int bytes_returned = 0;
4608 __u16 params, param_offset, byte_count, offset, count;
4610 cFYI(1, ("In SetEA"));
4612 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4617 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4619 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
4620 PATH_MAX, nls_codepage, remap);
4621 name_len++; /* trailing null */
4623 } else { /* BB improve the check for buffer overruns BB */
4624 name_len = strnlen(fileName, PATH_MAX);
4625 name_len++; /* trailing null */
4626 strncpy(pSMB->FileName, fileName, name_len);
4629 params = 6 + name_len;
4631 /* done calculating parms using name_len of file name,
4632 now use name_len to calculate length of ea name
4633 we are going to create in the inode xattrs */
4637 name_len = strnlen(ea_name,255);
4639 count = sizeof(*parm_data) + ea_value_len + name_len + 1;
4640 pSMB->MaxParameterCount = cpu_to_le16(2);
4641 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB size from sess */
4642 pSMB->MaxSetupCount = 0;
4646 pSMB->Reserved2 = 0;
4647 param_offset = offsetof(struct smb_com_transaction2_spi_req,
4648 InformationLevel) - 4;
4649 offset = param_offset + params;
4650 pSMB->InformationLevel =
4651 cpu_to_le16(SMB_SET_FILE_EA);
4654 (struct fealist *) (((char *) &pSMB->hdr.Protocol) +
4656 pSMB->ParameterOffset = cpu_to_le16(param_offset);
4657 pSMB->DataOffset = cpu_to_le16(offset);
4658 pSMB->SetupCount = 1;
4659 pSMB->Reserved3 = 0;
4660 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
4661 byte_count = 3 /* pad */ + params + count;
4662 pSMB->DataCount = cpu_to_le16(count);
4663 parm_data->list_len = cpu_to_le32(count);
4664 parm_data->list[0].EA_flags = 0;
4665 /* we checked above that name len is less than 255 */
4666 parm_data->list[0].name_len = (__u8)name_len;;
4667 /* EA names are always ASCII */
4669 strncpy(parm_data->list[0].name,ea_name,name_len);
4670 parm_data->list[0].name[name_len] = 0;
4671 parm_data->list[0].value_len = cpu_to_le16(ea_value_len);
4672 /* caller ensures that ea_value_len is less than 64K but
4673 we need to ensure that it fits within the smb */
4675 /*BB add length check that it would fit in negotiated SMB buffer size BB */
4676 /* if(ea_value_len > buffer_size - 512 (enough for header)) */
4678 memcpy(parm_data->list[0].name+name_len+1,ea_value,ea_value_len);
4680 pSMB->TotalDataCount = pSMB->DataCount;
4681 pSMB->ParameterCount = cpu_to_le16(params);
4682 pSMB->TotalParameterCount = pSMB->ParameterCount;
4683 pSMB->Reserved4 = 0;
4684 pSMB->hdr.smb_buf_length += byte_count;
4685 pSMB->ByteCount = cpu_to_le16(byte_count);
4686 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4687 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4689 cFYI(1, ("SetPathInfo (EA) returned %d", rc));
4692 cifs_buf_release(pSMB);