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 = cpu_to_le16(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 =
812 cpu_to_le32(le16_to_cpu(pSMBr->FileAttributes));
813 /* the file_info buf is endian converted by caller */
814 pfile_info->AllocationSize =
815 cpu_to_le64(le32_to_cpu(pSMBr->EndOfFile));
816 pfile_info->EndOfFile = pfile_info->AllocationSize;
817 pfile_info->NumberOfLinks = cpu_to_le32(1);
821 cifs_buf_release(pSMB);
828 CIFSSMBOpen(const int xid, struct cifsTconInfo *tcon,
829 const char *fileName, const int openDisposition,
830 const int access_flags, const int create_options, __u16 * netfid,
831 int *pOplock, FILE_ALL_INFO * pfile_info,
832 const struct nls_table *nls_codepage, int remap)
835 OPEN_REQ *pSMB = NULL;
836 OPEN_RSP *pSMBr = NULL;
842 rc = smb_init(SMB_COM_NT_CREATE_ANDX, 24, tcon, (void **) &pSMB,
847 pSMB->AndXCommand = 0xFF; /* none */
849 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
850 count = 1; /* account for one byte pad to word boundary */
852 cifsConvertToUCS((__le16 *) (pSMB->fileName + 1),
853 fileName, PATH_MAX, nls_codepage, remap);
854 name_len++; /* trailing null */
856 pSMB->NameLength = cpu_to_le16(name_len);
857 } else { /* BB improve check for buffer overruns BB */
858 count = 0; /* no pad */
859 name_len = strnlen(fileName, PATH_MAX);
860 name_len++; /* trailing null */
861 pSMB->NameLength = cpu_to_le16(name_len);
862 strncpy(pSMB->fileName, fileName, name_len);
864 if (*pOplock & REQ_OPLOCK)
865 pSMB->OpenFlags = cpu_to_le32(REQ_OPLOCK);
866 else if (*pOplock & REQ_BATCHOPLOCK) {
867 pSMB->OpenFlags = cpu_to_le32(REQ_BATCHOPLOCK);
869 pSMB->DesiredAccess = cpu_to_le32(access_flags);
870 pSMB->AllocationSize = 0;
871 /* set file as system file if special file such
872 as fifo and server expecting SFU style and
873 no Unix extensions */
874 if(create_options & CREATE_OPTION_SPECIAL)
875 pSMB->FileAttributes = cpu_to_le32(ATTR_SYSTEM);
877 pSMB->FileAttributes = cpu_to_le32(ATTR_NORMAL);
878 /* XP does not handle ATTR_POSIX_SEMANTICS */
879 /* but it helps speed up case sensitive checks for other
880 servers such as Samba */
881 if (tcon->ses->capabilities & CAP_UNIX)
882 pSMB->FileAttributes |= cpu_to_le32(ATTR_POSIX_SEMANTICS);
884 /* if ((omode & S_IWUGO) == 0)
885 pSMB->FileAttributes |= cpu_to_le32(ATTR_READONLY);*/
886 /* Above line causes problems due to vfs splitting create into two
887 pieces - need to set mode after file created not while it is
889 pSMB->ShareAccess = cpu_to_le32(FILE_SHARE_ALL);
890 pSMB->CreateDisposition = cpu_to_le32(openDisposition);
891 pSMB->CreateOptions = cpu_to_le32(create_options & CREATE_OPTIONS_MASK);
892 /* BB Expirement with various impersonation levels and verify */
893 pSMB->ImpersonationLevel = cpu_to_le32(SECURITY_IMPERSONATION);
894 pSMB->SecurityFlags =
895 SECURITY_CONTEXT_TRACKING | SECURITY_EFFECTIVE_ONLY;
898 pSMB->hdr.smb_buf_length += count;
900 pSMB->ByteCount = cpu_to_le16(count);
901 /* long_op set to 1 to allow for oplock break timeouts */
902 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
903 (struct smb_hdr *) pSMBr, &bytes_returned, 1);
904 cifs_stats_inc(&tcon->num_opens);
906 cFYI(1, ("Error in Open = %d", rc));
908 *pOplock = pSMBr->OplockLevel; /* 1 byte no need to le_to_cpu */
909 *netfid = pSMBr->Fid; /* cifs fid stays in le */
910 /* Let caller know file was created so we can set the mode. */
911 /* Do we care about the CreateAction in any other cases? */
912 if(cpu_to_le32(FILE_CREATE) == pSMBr->CreateAction)
913 *pOplock |= CIFS_CREATE_ACTION;
915 memcpy((char *)pfile_info,(char *)&pSMBr->CreationTime,
916 36 /* CreationTime to Attributes */);
917 /* the file_info buf is endian converted by caller */
918 pfile_info->AllocationSize = pSMBr->AllocationSize;
919 pfile_info->EndOfFile = pSMBr->EndOfFile;
920 pfile_info->NumberOfLinks = cpu_to_le32(1);
924 cifs_buf_release(pSMB);
930 /* If no buffer passed in, then caller wants to do the copy
931 as in the case of readpages so the SMB buffer must be
932 freed by the caller */
935 CIFSSMBRead(const int xid, struct cifsTconInfo *tcon,
936 const int netfid, const unsigned int count,
937 const __u64 lseek, unsigned int *nbytes, char **buf)
940 READ_REQ *pSMB = NULL;
941 READ_RSP *pSMBr = NULL;
942 char *pReadData = NULL;
946 cFYI(1,("Reading %d bytes on fid %d",count,netfid));
947 if(tcon->ses->capabilities & CAP_LARGE_FILES)
950 wct = 10; /* old style read */
953 rc = smb_init(SMB_COM_READ_ANDX, wct, tcon, (void **) &pSMB,
958 /* tcon and ses pointer are checked in smb_init */
959 if (tcon->ses->server == NULL)
960 return -ECONNABORTED;
962 pSMB->AndXCommand = 0xFF; /* none */
964 pSMB->OffsetLow = cpu_to_le32(lseek & 0xFFFFFFFF);
966 pSMB->OffsetHigh = cpu_to_le32(lseek >> 32);
967 else if((lseek >> 32) > 0) /* can not handle this big offset for old */
971 pSMB->MaxCount = cpu_to_le16(count & 0xFFFF);
972 pSMB->MaxCountHigh = cpu_to_le32(count >> 16);
974 pSMB->ByteCount = 0; /* no need to do le conversion since 0 */
977 struct smb_com_readx_req * pSMBW =
978 (struct smb_com_readx_req *)pSMB;
979 pSMBW->ByteCount = 0;
982 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
983 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
984 cifs_stats_inc(&tcon->num_reads);
986 cERROR(1, ("Send error in read = %d", rc));
988 int data_length = le16_to_cpu(pSMBr->DataLengthHigh);
989 data_length = data_length << 16;
990 data_length += le16_to_cpu(pSMBr->DataLength);
991 *nbytes = data_length;
993 /*check that DataLength would not go beyond end of SMB */
994 if ((data_length > CIFSMaxBufSize)
995 || (data_length > count)) {
996 cFYI(1,("bad length %d for count %d",data_length,count));
1001 (char *) (&pSMBr->hdr.Protocol) +
1002 le16_to_cpu(pSMBr->DataOffset);
1003 /* if(rc = copy_to_user(buf, pReadData, data_length)) {
1004 cERROR(1,("Faulting on read rc = %d",rc));
1006 }*/ /* can not use copy_to_user when using page cache*/
1008 memcpy(*buf,pReadData,data_length);
1012 cifs_buf_release(pSMB);
1014 *buf = (char *)pSMB;
1016 /* Note: On -EAGAIN error only caller can retry on handle based calls
1017 since file handle passed in no longer valid */
1022 CIFSSMBWrite(const int xid, struct cifsTconInfo *tcon,
1023 const int netfid, const unsigned int count,
1024 const __u64 offset, unsigned int *nbytes, const char *buf,
1025 const char __user * ubuf, const int long_op)
1028 WRITE_REQ *pSMB = NULL;
1029 WRITE_RSP *pSMBr = NULL;
1030 int bytes_returned, wct;
1034 /* cFYI(1,("write at %lld %d bytes",offset,count));*/
1035 if(tcon->ses == NULL)
1036 return -ECONNABORTED;
1038 if(tcon->ses->capabilities & CAP_LARGE_FILES)
1043 rc = smb_init(SMB_COM_WRITE_ANDX, wct, tcon, (void **) &pSMB,
1047 /* tcon and ses pointer are checked in smb_init */
1048 if (tcon->ses->server == NULL)
1049 return -ECONNABORTED;
1051 pSMB->AndXCommand = 0xFF; /* none */
1053 pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF);
1055 pSMB->OffsetHigh = cpu_to_le32(offset >> 32);
1056 else if((offset >> 32) > 0) /* can not handle this big offset for old */
1059 pSMB->Reserved = 0xFFFFFFFF;
1060 pSMB->WriteMode = 0;
1061 pSMB->Remaining = 0;
1063 /* Can increase buffer size if buffer is big enough in some cases - ie we
1064 can send more if LARGE_WRITE_X capability returned by the server and if
1065 our buffer is big enough or if we convert to iovecs on socket writes
1066 and eliminate the copy to the CIFS buffer */
1067 if(tcon->ses->capabilities & CAP_LARGE_WRITE_X) {
1068 bytes_sent = min_t(const unsigned int, CIFSMaxBufSize, count);
1070 bytes_sent = (tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE)
1074 if (bytes_sent > count)
1077 cpu_to_le16(offsetof(struct smb_com_write_req,Data) - 4);
1079 memcpy(pSMB->Data,buf,bytes_sent);
1081 if(copy_from_user(pSMB->Data,ubuf,bytes_sent)) {
1082 cifs_buf_release(pSMB);
1085 } else if (count != 0) {
1087 cifs_buf_release(pSMB);
1089 } /* else setting file size with write of zero bytes */
1091 byte_count = bytes_sent + 1; /* pad */
1092 else /* wct == 12 */ {
1093 byte_count = bytes_sent + 5; /* bigger pad, smaller smb hdr */
1095 pSMB->DataLengthLow = cpu_to_le16(bytes_sent & 0xFFFF);
1096 pSMB->DataLengthHigh = cpu_to_le16(bytes_sent >> 16);
1097 pSMB->hdr.smb_buf_length += byte_count;
1100 pSMB->ByteCount = cpu_to_le16(byte_count);
1101 else { /* old style write has byte count 4 bytes earlier so 4 bytes pad */
1102 struct smb_com_writex_req * pSMBW =
1103 (struct smb_com_writex_req *)pSMB;
1104 pSMBW->ByteCount = cpu_to_le16(byte_count);
1107 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1108 (struct smb_hdr *) pSMBr, &bytes_returned, long_op);
1109 cifs_stats_inc(&tcon->num_writes);
1111 cFYI(1, ("Send error in write = %d", rc));
1114 *nbytes = le16_to_cpu(pSMBr->CountHigh);
1115 *nbytes = (*nbytes) << 16;
1116 *nbytes += le16_to_cpu(pSMBr->Count);
1119 cifs_buf_release(pSMB);
1121 /* Note: On -EAGAIN error only caller can retry on handle based calls
1122 since file handle passed in no longer valid */
1127 #ifdef CONFIG_CIFS_EXPERIMENTAL
1129 CIFSSMBWrite2(const int xid, struct cifsTconInfo *tcon,
1130 const int netfid, const unsigned int count,
1131 const __u64 offset, unsigned int *nbytes, const char *buf,
1135 WRITE_REQ *pSMB = NULL;
1141 cFYI(1,("write2 at %lld %d bytes",offset,count)); /* BB removeme BB */
1142 rc = small_smb_init(SMB_COM_WRITE_ANDX, 14, tcon, (void **) &pSMB);
1145 /* tcon and ses pointer are checked in smb_init */
1146 if (tcon->ses->server == NULL)
1147 return -ECONNABORTED;
1149 pSMB->AndXCommand = 0xFF; /* none */
1151 pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF);
1152 pSMB->OffsetHigh = cpu_to_le32(offset >> 32);
1153 pSMB->Reserved = 0xFFFFFFFF;
1154 pSMB->WriteMode = 0;
1155 pSMB->Remaining = 0;
1157 /* Can increase buffer size if buffer is big enough in some cases - ie
1158 can send more if LARGE_WRITE_X capability returned by the server and if
1159 our buffer is big enough or if we convert to iovecs on socket writes
1160 and eliminate the copy to the CIFS buffer */
1161 if(tcon->ses->capabilities & CAP_LARGE_WRITE_X) {
1162 bytes_sent = min_t(const unsigned int, CIFSMaxBufSize, count);
1164 bytes_sent = (tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE)
1168 if (bytes_sent > count)
1171 cpu_to_le16(offsetof(struct smb_com_write_req,Data) - 4);
1173 byte_count = bytes_sent + 1 /* pad */ ; /* BB fix this for sends > 64K */
1174 pSMB->DataLengthLow = cpu_to_le16(bytes_sent & 0xFFFF);
1175 pSMB->DataLengthHigh = cpu_to_le16(bytes_sent >> 16);
1176 smb_hdr_len = pSMB->hdr.smb_buf_length + 1; /* hdr + 1 byte pad */
1177 pSMB->hdr.smb_buf_length += bytes_sent+1;
1178 pSMB->ByteCount = cpu_to_le16(byte_count);
1180 rc = SendReceive2(xid, tcon->ses, (struct smb_hdr *) pSMB, smb_hdr_len,
1181 buf, bytes_sent, &bytes_returned, long_op);
1182 cifs_stats_inc(&tcon->num_writes);
1184 cFYI(1, ("Send error in write = %d", rc));
1187 WRITE_RSP * pSMBr = (WRITE_RSP *)pSMB;
1188 *nbytes = le16_to_cpu(pSMBr->CountHigh);
1189 *nbytes = (*nbytes) << 16;
1190 *nbytes += le16_to_cpu(pSMBr->Count);
1193 cifs_small_buf_release(pSMB);
1195 /* Note: On -EAGAIN error only caller can retry on handle based calls
1196 since file handle passed in no longer valid */
1202 #endif /* CIFS_EXPERIMENTAL */
1205 CIFSSMBLock(const int xid, struct cifsTconInfo *tcon,
1206 const __u16 smb_file_id, const __u64 len,
1207 const __u64 offset, const __u32 numUnlock,
1208 const __u32 numLock, const __u8 lockType, const int waitFlag)
1211 LOCK_REQ *pSMB = NULL;
1212 LOCK_RSP *pSMBr = NULL;
1217 cFYI(1, ("In CIFSSMBLock - timeout %d numLock %d",waitFlag,numLock));
1218 rc = small_smb_init(SMB_COM_LOCKING_ANDX, 8, tcon, (void **) &pSMB);
1223 pSMBr = (LOCK_RSP *)pSMB; /* BB removeme BB */
1225 if(lockType == LOCKING_ANDX_OPLOCK_RELEASE) {
1226 timeout = -1; /* no response expected */
1228 } else if (waitFlag == TRUE) {
1229 timeout = 3; /* blocking operation, no timeout */
1230 pSMB->Timeout = cpu_to_le32(-1);/* blocking - do not time out */
1235 pSMB->NumberOfLocks = cpu_to_le16(numLock);
1236 pSMB->NumberOfUnlocks = cpu_to_le16(numUnlock);
1237 pSMB->LockType = lockType;
1238 pSMB->AndXCommand = 0xFF; /* none */
1239 pSMB->Fid = smb_file_id; /* netfid stays le */
1241 if((numLock != 0) || (numUnlock != 0)) {
1242 pSMB->Locks[0].Pid = cpu_to_le16(current->tgid);
1243 /* BB where to store pid high? */
1244 pSMB->Locks[0].LengthLow = cpu_to_le32((u32)len);
1245 pSMB->Locks[0].LengthHigh = cpu_to_le32((u32)(len>>32));
1246 pSMB->Locks[0].OffsetLow = cpu_to_le32((u32)offset);
1247 pSMB->Locks[0].OffsetHigh = cpu_to_le32((u32)(offset>>32));
1248 count = sizeof(LOCKING_ANDX_RANGE);
1253 pSMB->hdr.smb_buf_length += count;
1254 pSMB->ByteCount = cpu_to_le16(count);
1256 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1257 (struct smb_hdr *) pSMBr, &bytes_returned, timeout);
1258 cifs_stats_inc(&tcon->num_locks);
1260 cFYI(1, ("Send error in Lock = %d", rc));
1262 cifs_small_buf_release(pSMB);
1264 /* Note: On -EAGAIN error only caller can retry on handle based calls
1265 since file handle passed in no longer valid */
1270 CIFSSMBClose(const int xid, struct cifsTconInfo *tcon, int smb_file_id)
1273 CLOSE_REQ *pSMB = NULL;
1274 CLOSE_RSP *pSMBr = NULL;
1276 cFYI(1, ("In CIFSSMBClose"));
1278 /* do not retry on dead session on close */
1279 rc = small_smb_init(SMB_COM_CLOSE, 3, tcon, (void **) &pSMB);
1285 pSMBr = (CLOSE_RSP *)pSMB; /* BB removeme BB */
1287 pSMB->FileID = (__u16) smb_file_id;
1288 pSMB->LastWriteTime = 0;
1289 pSMB->ByteCount = 0;
1290 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1291 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1292 cifs_stats_inc(&tcon->num_closes);
1295 /* EINTR is expected when user ctl-c to kill app */
1296 cERROR(1, ("Send error in Close = %d", rc));
1300 cifs_small_buf_release(pSMB);
1302 /* Since session is dead, file will be closed on server already */
1310 CIFSSMBRename(const int xid, struct cifsTconInfo *tcon,
1311 const char *fromName, const char *toName,
1312 const struct nls_table *nls_codepage, int remap)
1315 RENAME_REQ *pSMB = NULL;
1316 RENAME_RSP *pSMBr = NULL;
1318 int name_len, name_len2;
1321 cFYI(1, ("In CIFSSMBRename"));
1323 rc = smb_init(SMB_COM_RENAME, 1, tcon, (void **) &pSMB,
1328 pSMB->BufferFormat = 0x04;
1329 pSMB->SearchAttributes =
1330 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
1333 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1335 cifsConvertToUCS((__le16 *) pSMB->OldFileName, fromName,
1336 PATH_MAX, nls_codepage, remap);
1337 name_len++; /* trailing null */
1339 pSMB->OldFileName[name_len] = 0x04; /* pad */
1340 /* protocol requires ASCII signature byte on Unicode string */
1341 pSMB->OldFileName[name_len + 1] = 0x00;
1343 cifsConvertToUCS((__le16 *) &pSMB->OldFileName[name_len + 2],
1344 toName, PATH_MAX, nls_codepage, remap);
1345 name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
1346 name_len2 *= 2; /* convert to bytes */
1347 } else { /* BB improve the check for buffer overruns BB */
1348 name_len = strnlen(fromName, PATH_MAX);
1349 name_len++; /* trailing null */
1350 strncpy(pSMB->OldFileName, fromName, name_len);
1351 name_len2 = strnlen(toName, PATH_MAX);
1352 name_len2++; /* trailing null */
1353 pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */
1354 strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2);
1355 name_len2++; /* trailing null */
1356 name_len2++; /* signature byte */
1359 count = 1 /* 1st signature byte */ + name_len + name_len2;
1360 pSMB->hdr.smb_buf_length += count;
1361 pSMB->ByteCount = cpu_to_le16(count);
1363 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1364 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1365 cifs_stats_inc(&tcon->num_renames);
1367 cFYI(1, ("Send error in rename = %d", rc));
1370 cifs_buf_release(pSMB);
1378 int CIFSSMBRenameOpenFile(const int xid,struct cifsTconInfo *pTcon,
1379 int netfid, char * target_name,
1380 const struct nls_table * nls_codepage, int remap)
1382 struct smb_com_transaction2_sfi_req *pSMB = NULL;
1383 struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
1384 struct set_file_rename * rename_info;
1386 char dummy_string[30];
1388 int bytes_returned = 0;
1390 __u16 params, param_offset, offset, count, byte_count;
1392 cFYI(1, ("Rename to File by handle"));
1393 rc = smb_init(SMB_COM_TRANSACTION2, 15, pTcon, (void **) &pSMB,
1399 pSMB->MaxSetupCount = 0;
1403 pSMB->Reserved2 = 0;
1404 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
1405 offset = param_offset + params;
1407 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
1408 rename_info = (struct set_file_rename *) data_offset;
1409 pSMB->MaxParameterCount = cpu_to_le16(2);
1410 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB PDU from sess */
1411 pSMB->SetupCount = 1;
1412 pSMB->Reserved3 = 0;
1413 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
1414 byte_count = 3 /* pad */ + params;
1415 pSMB->ParameterCount = cpu_to_le16(params);
1416 pSMB->TotalParameterCount = pSMB->ParameterCount;
1417 pSMB->ParameterOffset = cpu_to_le16(param_offset);
1418 pSMB->DataOffset = cpu_to_le16(offset);
1419 /* construct random name ".cifs_tmp<inodenum><mid>" */
1420 rename_info->overwrite = cpu_to_le32(1);
1421 rename_info->root_fid = 0;
1422 /* unicode only call */
1423 if(target_name == NULL) {
1424 sprintf(dummy_string,"cifs%x",pSMB->hdr.Mid);
1425 len_of_str = cifsConvertToUCS((__le16 *)rename_info->target_name,
1426 dummy_string, 24, nls_codepage, remap);
1428 len_of_str = cifsConvertToUCS((__le16 *)rename_info->target_name,
1429 target_name, PATH_MAX, nls_codepage, remap);
1431 rename_info->target_name_len = cpu_to_le32(2 * len_of_str);
1432 count = 12 /* sizeof(struct set_file_rename) */ + (2 * len_of_str) + 2;
1433 byte_count += count;
1434 pSMB->DataCount = cpu_to_le16(count);
1435 pSMB->TotalDataCount = pSMB->DataCount;
1437 pSMB->InformationLevel =
1438 cpu_to_le16(SMB_SET_FILE_RENAME_INFORMATION);
1439 pSMB->Reserved4 = 0;
1440 pSMB->hdr.smb_buf_length += byte_count;
1441 pSMB->ByteCount = cpu_to_le16(byte_count);
1442 rc = SendReceive(xid, pTcon->ses, (struct smb_hdr *) pSMB,
1443 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1444 cifs_stats_inc(&pTcon->num_t2renames);
1446 cFYI(1,("Send error in Rename (by file handle) = %d", rc));
1449 cifs_buf_release(pSMB);
1451 /* Note: On -EAGAIN error only caller can retry on handle based calls
1452 since file handle passed in no longer valid */
1458 CIFSSMBCopy(const int xid, struct cifsTconInfo *tcon, const char * fromName,
1459 const __u16 target_tid, const char *toName, const int flags,
1460 const struct nls_table *nls_codepage, int remap)
1463 COPY_REQ *pSMB = NULL;
1464 COPY_RSP *pSMBr = NULL;
1466 int name_len, name_len2;
1469 cFYI(1, ("In CIFSSMBCopy"));
1471 rc = smb_init(SMB_COM_COPY, 1, tcon, (void **) &pSMB,
1476 pSMB->BufferFormat = 0x04;
1477 pSMB->Tid2 = target_tid;
1479 pSMB->Flags = cpu_to_le16(flags & COPY_TREE);
1481 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1482 name_len = cifsConvertToUCS((__le16 *) pSMB->OldFileName,
1483 fromName, PATH_MAX, nls_codepage,
1485 name_len++; /* trailing null */
1487 pSMB->OldFileName[name_len] = 0x04; /* pad */
1488 /* protocol requires ASCII signature byte on Unicode string */
1489 pSMB->OldFileName[name_len + 1] = 0x00;
1490 name_len2 = cifsConvertToUCS((__le16 *)&pSMB->OldFileName[name_len + 2],
1491 toName, PATH_MAX, nls_codepage, remap);
1492 name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
1493 name_len2 *= 2; /* convert to bytes */
1494 } else { /* BB improve the check for buffer overruns BB */
1495 name_len = strnlen(fromName, PATH_MAX);
1496 name_len++; /* trailing null */
1497 strncpy(pSMB->OldFileName, fromName, name_len);
1498 name_len2 = strnlen(toName, PATH_MAX);
1499 name_len2++; /* trailing null */
1500 pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */
1501 strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2);
1502 name_len2++; /* trailing null */
1503 name_len2++; /* signature byte */
1506 count = 1 /* 1st signature byte */ + name_len + name_len2;
1507 pSMB->hdr.smb_buf_length += count;
1508 pSMB->ByteCount = cpu_to_le16(count);
1510 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1511 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1513 cFYI(1, ("Send error in copy = %d with %d files copied",
1514 rc, le16_to_cpu(pSMBr->CopyCount)));
1517 cifs_buf_release(pSMB);
1526 CIFSUnixCreateSymLink(const int xid, struct cifsTconInfo *tcon,
1527 const char *fromName, const char *toName,
1528 const struct nls_table *nls_codepage)
1530 TRANSACTION2_SPI_REQ *pSMB = NULL;
1531 TRANSACTION2_SPI_RSP *pSMBr = NULL;
1534 int name_len_target;
1536 int bytes_returned = 0;
1537 __u16 params, param_offset, offset, byte_count;
1539 cFYI(1, ("In Symlink Unix style"));
1541 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
1546 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1548 cifs_strtoUCS((wchar_t *) pSMB->FileName, fromName, PATH_MAX
1549 /* find define for this maxpathcomponent */
1551 name_len++; /* trailing null */
1554 } else { /* BB improve the check for buffer overruns BB */
1555 name_len = strnlen(fromName, PATH_MAX);
1556 name_len++; /* trailing null */
1557 strncpy(pSMB->FileName, fromName, name_len);
1559 params = 6 + name_len;
1560 pSMB->MaxSetupCount = 0;
1564 pSMB->Reserved2 = 0;
1565 param_offset = offsetof(struct smb_com_transaction2_spi_req,
1566 InformationLevel) - 4;
1567 offset = param_offset + params;
1569 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
1570 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1572 cifs_strtoUCS((wchar_t *) data_offset, toName, PATH_MAX
1573 /* find define for this maxpathcomponent */
1575 name_len_target++; /* trailing null */
1576 name_len_target *= 2;
1577 } else { /* BB improve the check for buffer overruns BB */
1578 name_len_target = strnlen(toName, PATH_MAX);
1579 name_len_target++; /* trailing null */
1580 strncpy(data_offset, toName, name_len_target);
1583 pSMB->MaxParameterCount = cpu_to_le16(2);
1584 /* BB find exact max on data count below from sess */
1585 pSMB->MaxDataCount = cpu_to_le16(1000);
1586 pSMB->SetupCount = 1;
1587 pSMB->Reserved3 = 0;
1588 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
1589 byte_count = 3 /* pad */ + params + name_len_target;
1590 pSMB->DataCount = cpu_to_le16(name_len_target);
1591 pSMB->ParameterCount = cpu_to_le16(params);
1592 pSMB->TotalDataCount = pSMB->DataCount;
1593 pSMB->TotalParameterCount = pSMB->ParameterCount;
1594 pSMB->ParameterOffset = cpu_to_le16(param_offset);
1595 pSMB->DataOffset = cpu_to_le16(offset);
1596 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_LINK);
1597 pSMB->Reserved4 = 0;
1598 pSMB->hdr.smb_buf_length += byte_count;
1599 pSMB->ByteCount = cpu_to_le16(byte_count);
1600 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1601 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1602 cifs_stats_inc(&tcon->num_symlinks);
1605 ("Send error in SetPathInfo (create symlink) = %d",
1610 cifs_buf_release(pSMB);
1613 goto createSymLinkRetry;
1619 CIFSUnixCreateHardLink(const int xid, struct cifsTconInfo *tcon,
1620 const char *fromName, const char *toName,
1621 const struct nls_table *nls_codepage, int remap)
1623 TRANSACTION2_SPI_REQ *pSMB = NULL;
1624 TRANSACTION2_SPI_RSP *pSMBr = NULL;
1627 int name_len_target;
1629 int bytes_returned = 0;
1630 __u16 params, param_offset, offset, byte_count;
1632 cFYI(1, ("In Create Hard link Unix style"));
1633 createHardLinkRetry:
1634 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
1639 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1640 name_len = cifsConvertToUCS((__le16 *) pSMB->FileName, toName,
1641 PATH_MAX, nls_codepage, remap);
1642 name_len++; /* trailing null */
1645 } else { /* BB improve the check for buffer overruns BB */
1646 name_len = strnlen(toName, PATH_MAX);
1647 name_len++; /* trailing null */
1648 strncpy(pSMB->FileName, toName, name_len);
1650 params = 6 + name_len;
1651 pSMB->MaxSetupCount = 0;
1655 pSMB->Reserved2 = 0;
1656 param_offset = offsetof(struct smb_com_transaction2_spi_req,
1657 InformationLevel) - 4;
1658 offset = param_offset + params;
1660 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
1661 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1663 cifsConvertToUCS((__le16 *) data_offset, fromName, PATH_MAX,
1664 nls_codepage, remap);
1665 name_len_target++; /* trailing null */
1666 name_len_target *= 2;
1667 } else { /* BB improve the check for buffer overruns BB */
1668 name_len_target = strnlen(fromName, PATH_MAX);
1669 name_len_target++; /* trailing null */
1670 strncpy(data_offset, fromName, name_len_target);
1673 pSMB->MaxParameterCount = cpu_to_le16(2);
1674 /* BB find exact max on data count below from sess*/
1675 pSMB->MaxDataCount = cpu_to_le16(1000);
1676 pSMB->SetupCount = 1;
1677 pSMB->Reserved3 = 0;
1678 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
1679 byte_count = 3 /* pad */ + params + name_len_target;
1680 pSMB->ParameterCount = cpu_to_le16(params);
1681 pSMB->TotalParameterCount = pSMB->ParameterCount;
1682 pSMB->DataCount = cpu_to_le16(name_len_target);
1683 pSMB->TotalDataCount = pSMB->DataCount;
1684 pSMB->ParameterOffset = cpu_to_le16(param_offset);
1685 pSMB->DataOffset = cpu_to_le16(offset);
1686 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_HLINK);
1687 pSMB->Reserved4 = 0;
1688 pSMB->hdr.smb_buf_length += byte_count;
1689 pSMB->ByteCount = cpu_to_le16(byte_count);
1690 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1691 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1692 cifs_stats_inc(&tcon->num_hardlinks);
1694 cFYI(1, ("Send error in SetPathInfo (hard link) = %d", rc));
1697 cifs_buf_release(pSMB);
1699 goto createHardLinkRetry;
1705 CIFSCreateHardLink(const int xid, struct cifsTconInfo *tcon,
1706 const char *fromName, const char *toName,
1707 const struct nls_table *nls_codepage, int remap)
1710 NT_RENAME_REQ *pSMB = NULL;
1711 RENAME_RSP *pSMBr = NULL;
1713 int name_len, name_len2;
1716 cFYI(1, ("In CIFSCreateHardLink"));
1717 winCreateHardLinkRetry:
1719 rc = smb_init(SMB_COM_NT_RENAME, 4, tcon, (void **) &pSMB,
1724 pSMB->SearchAttributes =
1725 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
1727 pSMB->Flags = cpu_to_le16(CREATE_HARD_LINK);
1728 pSMB->ClusterCount = 0;
1730 pSMB->BufferFormat = 0x04;
1732 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1734 cifsConvertToUCS((__le16 *) pSMB->OldFileName, fromName,
1735 PATH_MAX, nls_codepage, remap);
1736 name_len++; /* trailing null */
1738 pSMB->OldFileName[name_len] = 0; /* pad */
1739 pSMB->OldFileName[name_len + 1] = 0x04;
1741 cifsConvertToUCS((__le16 *)&pSMB->OldFileName[name_len + 2],
1742 toName, PATH_MAX, nls_codepage, remap);
1743 name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
1744 name_len2 *= 2; /* convert to bytes */
1745 } else { /* BB improve the check for buffer overruns BB */
1746 name_len = strnlen(fromName, PATH_MAX);
1747 name_len++; /* trailing null */
1748 strncpy(pSMB->OldFileName, fromName, name_len);
1749 name_len2 = strnlen(toName, PATH_MAX);
1750 name_len2++; /* trailing null */
1751 pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */
1752 strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2);
1753 name_len2++; /* trailing null */
1754 name_len2++; /* signature byte */
1757 count = 1 /* string type byte */ + name_len + name_len2;
1758 pSMB->hdr.smb_buf_length += count;
1759 pSMB->ByteCount = cpu_to_le16(count);
1761 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1762 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1763 cifs_stats_inc(&tcon->num_hardlinks);
1765 cFYI(1, ("Send error in hard link (NT rename) = %d", rc));
1767 cifs_buf_release(pSMB);
1769 goto winCreateHardLinkRetry;
1775 CIFSSMBUnixQuerySymLink(const int xid, struct cifsTconInfo *tcon,
1776 const unsigned char *searchName,
1777 char *symlinkinfo, const int buflen,
1778 const struct nls_table *nls_codepage)
1780 /* SMB_QUERY_FILE_UNIX_LINK */
1781 TRANSACTION2_QPI_REQ *pSMB = NULL;
1782 TRANSACTION2_QPI_RSP *pSMBr = NULL;
1786 __u16 params, byte_count;
1788 cFYI(1, ("In QPathSymLinkInfo (Unix) for path %s", searchName));
1791 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
1796 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1798 cifs_strtoUCS((wchar_t *) pSMB->FileName, searchName, PATH_MAX
1799 /* find define for this maxpathcomponent */
1801 name_len++; /* trailing null */
1803 } else { /* BB improve the check for buffer overruns BB */
1804 name_len = strnlen(searchName, PATH_MAX);
1805 name_len++; /* trailing null */
1806 strncpy(pSMB->FileName, searchName, name_len);
1809 params = 2 /* level */ + 4 /* rsrvd */ + name_len /* incl null */ ;
1810 pSMB->TotalDataCount = 0;
1811 pSMB->MaxParameterCount = cpu_to_le16(2);
1812 /* BB find exact max data count below from sess structure BB */
1813 pSMB->MaxDataCount = cpu_to_le16(4000);
1814 pSMB->MaxSetupCount = 0;
1818 pSMB->Reserved2 = 0;
1819 pSMB->ParameterOffset = cpu_to_le16(offsetof(
1820 struct smb_com_transaction2_qpi_req ,InformationLevel) - 4);
1821 pSMB->DataCount = 0;
1822 pSMB->DataOffset = 0;
1823 pSMB->SetupCount = 1;
1824 pSMB->Reserved3 = 0;
1825 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
1826 byte_count = params + 1 /* pad */ ;
1827 pSMB->TotalParameterCount = cpu_to_le16(params);
1828 pSMB->ParameterCount = pSMB->TotalParameterCount;
1829 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_LINK);
1830 pSMB->Reserved4 = 0;
1831 pSMB->hdr.smb_buf_length += byte_count;
1832 pSMB->ByteCount = cpu_to_le16(byte_count);
1834 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1835 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1837 cFYI(1, ("Send error in QuerySymLinkInfo = %d", rc));
1839 /* decode response */
1841 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
1842 if (rc || (pSMBr->ByteCount < 2))
1843 /* BB also check enough total bytes returned */
1844 rc = -EIO; /* bad smb */
1846 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
1847 __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
1849 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
1850 name_len = UniStrnlen((wchar_t *) ((char *)
1851 &pSMBr->hdr.Protocol +data_offset),
1852 min_t(const int, buflen,count) / 2);
1853 /* BB FIXME investigate remapping reserved chars here */
1854 cifs_strfromUCS_le(symlinkinfo,
1855 (wchar_t *) ((char *)&pSMBr->hdr.Protocol +
1857 name_len, nls_codepage);
1859 strncpy(symlinkinfo,
1860 (char *) &pSMBr->hdr.Protocol +
1862 min_t(const int, buflen, count));
1864 symlinkinfo[buflen] = 0;
1865 /* just in case so calling code does not go off the end of buffer */
1868 cifs_buf_release(pSMB);
1870 goto querySymLinkRetry;
1875 CIFSSMBQueryReparseLinkInfo(const int xid, struct cifsTconInfo *tcon,
1876 const unsigned char *searchName,
1877 char *symlinkinfo, const int buflen,__u16 fid,
1878 const struct nls_table *nls_codepage)
1883 struct smb_com_transaction_ioctl_req * pSMB;
1884 struct smb_com_transaction_ioctl_rsp * pSMBr;
1886 cFYI(1, ("In Windows reparse style QueryLink for path %s", searchName));
1887 rc = smb_init(SMB_COM_NT_TRANSACT, 23, tcon, (void **) &pSMB,
1892 pSMB->TotalParameterCount = 0 ;
1893 pSMB->TotalDataCount = 0;
1894 pSMB->MaxParameterCount = cpu_to_le32(2);
1895 /* BB find exact data count max from sess structure BB */
1896 pSMB->MaxDataCount = cpu_to_le32(4000);
1897 pSMB->MaxSetupCount = 4;
1899 pSMB->ParameterOffset = 0;
1900 pSMB->DataCount = 0;
1901 pSMB->DataOffset = 0;
1902 pSMB->SetupCount = 4;
1903 pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_IOCTL);
1904 pSMB->ParameterCount = pSMB->TotalParameterCount;
1905 pSMB->FunctionCode = cpu_to_le32(FSCTL_GET_REPARSE_POINT);
1906 pSMB->IsFsctl = 1; /* FSCTL */
1907 pSMB->IsRootFlag = 0;
1908 pSMB->Fid = fid; /* file handle always le */
1909 pSMB->ByteCount = 0;
1911 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1912 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1914 cFYI(1, ("Send error in QueryReparseLinkInfo = %d", rc));
1915 } else { /* decode response */
1916 __u32 data_offset = le32_to_cpu(pSMBr->DataOffset);
1917 __u32 data_count = le32_to_cpu(pSMBr->DataCount);
1918 if ((pSMBr->ByteCount < 2) || (data_offset > 512))
1919 /* BB also check enough total bytes returned */
1920 rc = -EIO; /* bad smb */
1922 if(data_count && (data_count < 2048)) {
1923 char * end_of_smb = pSMBr->ByteCount + (char *)&pSMBr->ByteCount;
1925 struct reparse_data * reparse_buf = (struct reparse_data *)
1926 ((char *)&pSMBr->hdr.Protocol + data_offset);
1927 if((char*)reparse_buf >= end_of_smb) {
1931 if((reparse_buf->LinkNamesBuf +
1932 reparse_buf->TargetNameOffset +
1933 reparse_buf->TargetNameLen) >
1935 cFYI(1,("reparse buf extended beyond SMB"));
1940 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
1941 name_len = UniStrnlen((wchar_t *)
1942 (reparse_buf->LinkNamesBuf +
1943 reparse_buf->TargetNameOffset),
1944 min(buflen/2, reparse_buf->TargetNameLen / 2));
1945 cifs_strfromUCS_le(symlinkinfo,
1946 (wchar_t *) (reparse_buf->LinkNamesBuf +
1947 reparse_buf->TargetNameOffset),
1948 name_len, nls_codepage);
1949 } else { /* ASCII names */
1950 strncpy(symlinkinfo,reparse_buf->LinkNamesBuf +
1951 reparse_buf->TargetNameOffset,
1952 min_t(const int, buflen, reparse_buf->TargetNameLen));
1956 cFYI(1,("Invalid return data count on get reparse info ioctl"));
1958 symlinkinfo[buflen] = 0; /* just in case so the caller
1959 does not go off the end of the buffer */
1960 cFYI(1,("readlink result - %s ",symlinkinfo));
1964 cifs_buf_release(pSMB);
1966 /* Note: On -EAGAIN error only caller can retry on handle based calls
1967 since file handle passed in no longer valid */
1972 #ifdef CONFIG_CIFS_POSIX
1974 /*Convert an Access Control Entry from wire format to local POSIX xattr format*/
1975 static void cifs_convert_ace(posix_acl_xattr_entry * ace, struct cifs_posix_ace * cifs_ace)
1977 /* u8 cifs fields do not need le conversion */
1978 ace->e_perm = (__u16)cifs_ace->cifs_e_perm;
1979 ace->e_tag = (__u16)cifs_ace->cifs_e_tag;
1980 ace->e_id = (__u32)le64_to_cpu(cifs_ace->cifs_uid);
1981 /* cFYI(1,("perm %d tag %d id %d",ace->e_perm,ace->e_tag,ace->e_id)); */
1986 /* Convert ACL from CIFS POSIX wire format to local Linux POSIX ACL xattr */
1987 static int cifs_copy_posix_acl(char * trgt,char * src, const int buflen,
1988 const int acl_type,const int size_of_data_area)
1993 struct cifs_posix_ace * pACE;
1994 struct cifs_posix_acl * cifs_acl = (struct cifs_posix_acl *)src;
1995 posix_acl_xattr_header * local_acl = (posix_acl_xattr_header *)trgt;
1997 if (le16_to_cpu(cifs_acl->version) != CIFS_ACL_VERSION)
2000 if(acl_type & ACL_TYPE_ACCESS) {
2001 count = le16_to_cpu(cifs_acl->access_entry_count);
2002 pACE = &cifs_acl->ace_array[0];
2003 size = sizeof(struct cifs_posix_acl);
2004 size += sizeof(struct cifs_posix_ace) * count;
2005 /* check if we would go beyond end of SMB */
2006 if(size_of_data_area < size) {
2007 cFYI(1,("bad CIFS POSIX ACL size %d vs. %d",size_of_data_area,size));
2010 } else if(acl_type & ACL_TYPE_DEFAULT) {
2011 count = le16_to_cpu(cifs_acl->access_entry_count);
2012 size = sizeof(struct cifs_posix_acl);
2013 size += sizeof(struct cifs_posix_ace) * count;
2014 /* skip past access ACEs to get to default ACEs */
2015 pACE = &cifs_acl->ace_array[count];
2016 count = le16_to_cpu(cifs_acl->default_entry_count);
2017 size += sizeof(struct cifs_posix_ace) * count;
2018 /* check if we would go beyond end of SMB */
2019 if(size_of_data_area < size)
2026 size = posix_acl_xattr_size(count);
2027 if((buflen == 0) || (local_acl == NULL)) {
2028 /* used to query ACL EA size */
2029 } else if(size > buflen) {
2031 } else /* buffer big enough */ {
2032 local_acl->a_version = POSIX_ACL_XATTR_VERSION;
2033 for(i = 0;i < count ;i++) {
2034 cifs_convert_ace(&local_acl->a_entries[i],pACE);
2041 static __u16 convert_ace_to_cifs_ace(struct cifs_posix_ace * cifs_ace,
2042 const posix_acl_xattr_entry * local_ace)
2044 __u16 rc = 0; /* 0 = ACL converted ok */
2046 cifs_ace->cifs_e_perm = (__u8)cpu_to_le16(local_ace->e_perm);
2047 cifs_ace->cifs_e_tag = (__u8)cpu_to_le16(local_ace->e_tag);
2048 /* BB is there a better way to handle the large uid? */
2049 if(local_ace->e_id == -1) {
2050 /* Probably no need to le convert -1 on any arch but can not hurt */
2051 cifs_ace->cifs_uid = cpu_to_le64(-1);
2053 cifs_ace->cifs_uid = (__u64)cpu_to_le32(local_ace->e_id);
2054 /*cFYI(1,("perm %d tag %d id %d",ace->e_perm,ace->e_tag,ace->e_id));*/
2058 /* Convert ACL from local Linux POSIX xattr to CIFS POSIX ACL wire format */
2059 static __u16 ACL_to_cifs_posix(char * parm_data,const char * pACL,const int buflen,
2063 struct cifs_posix_acl * cifs_acl = (struct cifs_posix_acl *)parm_data;
2064 posix_acl_xattr_header * local_acl = (posix_acl_xattr_header *)pACL;
2068 if((buflen == 0) || (pACL == NULL) || (cifs_acl == NULL))
2071 count = posix_acl_xattr_count((size_t)buflen);
2072 cFYI(1,("setting acl with %d entries from buf of length %d and version of %d",
2073 count,buflen,local_acl->a_version));
2074 if(local_acl->a_version != 2) {
2075 cFYI(1,("unknown POSIX ACL version %d",local_acl->a_version));
2078 cifs_acl->version = cpu_to_le16(1);
2079 if(acl_type == ACL_TYPE_ACCESS)
2080 cifs_acl->access_entry_count = count;
2081 else if(acl_type == ACL_TYPE_DEFAULT)
2082 cifs_acl->default_entry_count = count;
2084 cFYI(1,("unknown ACL type %d",acl_type));
2087 for(i=0;i<count;i++) {
2088 rc = convert_ace_to_cifs_ace(&cifs_acl->ace_array[i],
2089 &local_acl->a_entries[i]);
2091 /* ACE not converted */
2096 rc = (__u16)(count * sizeof(struct cifs_posix_ace));
2097 rc += sizeof(struct cifs_posix_acl);
2098 /* BB add check to make sure ACL does not overflow SMB */
2104 CIFSSMBGetPosixACL(const int xid, struct cifsTconInfo *tcon,
2105 const unsigned char *searchName,
2106 char *acl_inf, const int buflen, const int acl_type,
2107 const struct nls_table *nls_codepage, int remap)
2109 /* SMB_QUERY_POSIX_ACL */
2110 TRANSACTION2_QPI_REQ *pSMB = NULL;
2111 TRANSACTION2_QPI_RSP *pSMBr = NULL;
2115 __u16 params, byte_count;
2117 cFYI(1, ("In GetPosixACL (Unix) for path %s", searchName));
2120 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2125 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2127 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
2128 PATH_MAX, nls_codepage, remap);
2129 name_len++; /* trailing null */
2131 pSMB->FileName[name_len] = 0;
2132 pSMB->FileName[name_len+1] = 0;
2133 } else { /* BB improve the check for buffer overruns BB */
2134 name_len = strnlen(searchName, PATH_MAX);
2135 name_len++; /* trailing null */
2136 strncpy(pSMB->FileName, searchName, name_len);
2139 params = 2 /* level */ + 4 /* rsrvd */ + name_len /* incl null */ ;
2140 pSMB->TotalDataCount = 0;
2141 pSMB->MaxParameterCount = cpu_to_le16(2);
2142 /* BB find exact max data count below from sess structure BB */
2143 pSMB->MaxDataCount = cpu_to_le16(4000);
2144 pSMB->MaxSetupCount = 0;
2148 pSMB->Reserved2 = 0;
2149 pSMB->ParameterOffset = cpu_to_le16(
2150 offsetof(struct smb_com_transaction2_qpi_req ,InformationLevel) - 4);
2151 pSMB->DataCount = 0;
2152 pSMB->DataOffset = 0;
2153 pSMB->SetupCount = 1;
2154 pSMB->Reserved3 = 0;
2155 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
2156 byte_count = params + 1 /* pad */ ;
2157 pSMB->TotalParameterCount = cpu_to_le16(params);
2158 pSMB->ParameterCount = pSMB->TotalParameterCount;
2159 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_POSIX_ACL);
2160 pSMB->Reserved4 = 0;
2161 pSMB->hdr.smb_buf_length += byte_count;
2162 pSMB->ByteCount = cpu_to_le16(byte_count);
2164 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2165 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2167 cFYI(1, ("Send error in Query POSIX ACL = %d", rc));
2169 /* decode response */
2171 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
2172 if (rc || (pSMBr->ByteCount < 2))
2173 /* BB also check enough total bytes returned */
2174 rc = -EIO; /* bad smb */
2176 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
2177 __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
2178 rc = cifs_copy_posix_acl(acl_inf,
2179 (char *)&pSMBr->hdr.Protocol+data_offset,
2180 buflen,acl_type,count);
2183 cifs_buf_release(pSMB);
2190 CIFSSMBSetPosixACL(const int xid, struct cifsTconInfo *tcon,
2191 const unsigned char *fileName,
2192 const char *local_acl, const int buflen,
2194 const struct nls_table *nls_codepage, int remap)
2196 struct smb_com_transaction2_spi_req *pSMB = NULL;
2197 struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
2201 int bytes_returned = 0;
2202 __u16 params, byte_count, data_count, param_offset, offset;
2204 cFYI(1, ("In SetPosixACL (Unix) for path %s", fileName));
2206 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2210 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2212 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
2213 PATH_MAX, nls_codepage, remap);
2214 name_len++; /* trailing null */
2216 } else { /* BB improve the check for buffer overruns BB */
2217 name_len = strnlen(fileName, PATH_MAX);
2218 name_len++; /* trailing null */
2219 strncpy(pSMB->FileName, fileName, name_len);
2221 params = 6 + name_len;
2222 pSMB->MaxParameterCount = cpu_to_le16(2);
2223 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB size from sess */
2224 pSMB->MaxSetupCount = 0;
2228 pSMB->Reserved2 = 0;
2229 param_offset = offsetof(struct smb_com_transaction2_spi_req,
2230 InformationLevel) - 4;
2231 offset = param_offset + params;
2232 parm_data = ((char *) &pSMB->hdr.Protocol) + offset;
2233 pSMB->ParameterOffset = cpu_to_le16(param_offset);
2235 /* convert to on the wire format for POSIX ACL */
2236 data_count = ACL_to_cifs_posix(parm_data,local_acl,buflen,acl_type);
2238 if(data_count == 0) {
2240 goto setACLerrorExit;
2242 pSMB->DataOffset = cpu_to_le16(offset);
2243 pSMB->SetupCount = 1;
2244 pSMB->Reserved3 = 0;
2245 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
2246 pSMB->InformationLevel = cpu_to_le16(SMB_SET_POSIX_ACL);
2247 byte_count = 3 /* pad */ + params + data_count;
2248 pSMB->DataCount = cpu_to_le16(data_count);
2249 pSMB->TotalDataCount = pSMB->DataCount;
2250 pSMB->ParameterCount = cpu_to_le16(params);
2251 pSMB->TotalParameterCount = pSMB->ParameterCount;
2252 pSMB->Reserved4 = 0;
2253 pSMB->hdr.smb_buf_length += byte_count;
2254 pSMB->ByteCount = cpu_to_le16(byte_count);
2255 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2256 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2258 cFYI(1, ("Set POSIX ACL returned %d", rc));
2262 cifs_buf_release(pSMB);
2268 /* BB fix tabs in this function FIXME BB */
2270 CIFSGetExtAttr(const int xid, struct cifsTconInfo *tcon,
2271 const int netfid, __u64 * pExtAttrBits, __u64 *pMask)
2274 struct smb_t2_qfi_req *pSMB = NULL;
2275 struct smb_t2_qfi_rsp *pSMBr = NULL;
2277 __u16 params, byte_count;
2279 cFYI(1,("In GetExtAttr"));
2284 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2289 params = 2 /* level */ +2 /* fid */;
2290 pSMB->t2.TotalDataCount = 0;
2291 pSMB->t2.MaxParameterCount = cpu_to_le16(4);
2292 /* BB find exact max data count below from sess structure BB */
2293 pSMB->t2.MaxDataCount = cpu_to_le16(4000);
2294 pSMB->t2.MaxSetupCount = 0;
2295 pSMB->t2.Reserved = 0;
2297 pSMB->t2.Timeout = 0;
2298 pSMB->t2.Reserved2 = 0;
2299 pSMB->t2.ParameterOffset = cpu_to_le16(offsetof(struct smb_t2_qfi_req,
2301 pSMB->t2.DataCount = 0;
2302 pSMB->t2.DataOffset = 0;
2303 pSMB->t2.SetupCount = 1;
2304 pSMB->t2.Reserved3 = 0;
2305 pSMB->t2.SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION);
2306 byte_count = params + 1 /* pad */ ;
2307 pSMB->t2.TotalParameterCount = cpu_to_le16(params);
2308 pSMB->t2.ParameterCount = pSMB->t2.TotalParameterCount;
2309 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_ATTR_FLAGS);
2312 pSMB->hdr.smb_buf_length += byte_count;
2313 pSMB->t2.ByteCount = cpu_to_le16(byte_count);
2315 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2316 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2318 cFYI(1, ("error %d in GetExtAttr", rc));
2320 /* decode response */
2321 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
2322 if (rc || (pSMBr->ByteCount < 2))
2323 /* BB also check enough total bytes returned */
2324 /* If rc should we check for EOPNOSUPP and
2325 disable the srvino flag? or in caller? */
2326 rc = -EIO; /* bad smb */
2328 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
2329 __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
2330 struct file_chattr_info * pfinfo;
2331 /* BB Do we need a cast or hash here ? */
2333 cFYI(1, ("Illegal size ret in GetExtAttr"));
2337 pfinfo = (struct file_chattr_info *)
2338 (data_offset + (char *) &pSMBr->hdr.Protocol);
2339 *pExtAttrBits = le64_to_cpu(pfinfo->mode);
2340 *pMask = le64_to_cpu(pfinfo->mask);
2344 cifs_buf_release(pSMB);
2346 goto GetExtAttrRetry;
2351 #endif /* CONFIG_POSIX */
2353 /* Legacy Query Path Information call for lookup to old servers such
2355 int SMBQueryInformation(const int xid, struct cifsTconInfo *tcon,
2356 const unsigned char *searchName,
2357 FILE_ALL_INFO * pFinfo,
2358 const struct nls_table *nls_codepage, int remap)
2360 QUERY_INFORMATION_REQ * pSMB;
2361 QUERY_INFORMATION_RSP * pSMBr;
2366 cFYI(1, ("In SMBQPath path %s", searchName));
2368 rc = smb_init(SMB_COM_QUERY_INFORMATION, 0, tcon, (void **) &pSMB,
2373 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2375 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
2376 PATH_MAX, nls_codepage, remap);
2377 name_len++; /* trailing null */
2380 name_len = strnlen(searchName, PATH_MAX);
2381 name_len++; /* trailing null */
2382 strncpy(pSMB->FileName, searchName, name_len);
2384 pSMB->BufferFormat = 0x04;
2385 name_len++; /* account for buffer type byte */
2386 pSMB->hdr.smb_buf_length += (__u16) name_len;
2387 pSMB->ByteCount = cpu_to_le16(name_len);
2389 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2390 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2392 cFYI(1, ("Send error in QueryInfo = %d", rc));
2393 } else if (pFinfo) { /* decode response */
2394 memset(pFinfo, 0, sizeof(FILE_ALL_INFO));
2395 pFinfo->AllocationSize =
2396 cpu_to_le64(le32_to_cpu(pSMBr->size));
2397 pFinfo->EndOfFile = pFinfo->AllocationSize;
2398 pFinfo->Attributes =
2399 cpu_to_le32(le16_to_cpu(pSMBr->attr));
2401 rc = -EIO; /* bad buffer passed in */
2403 cifs_buf_release(pSMB);
2415 CIFSSMBQPathInfo(const int xid, struct cifsTconInfo *tcon,
2416 const unsigned char *searchName,
2417 FILE_ALL_INFO * pFindData,
2418 const struct nls_table *nls_codepage, int remap)
2420 /* level 263 SMB_QUERY_FILE_ALL_INFO */
2421 TRANSACTION2_QPI_REQ *pSMB = NULL;
2422 TRANSACTION2_QPI_RSP *pSMBr = NULL;
2426 __u16 params, byte_count;
2428 /* cFYI(1, ("In QPathInfo path %s", searchName)); */
2430 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2435 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2437 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
2438 PATH_MAX, nls_codepage, remap);
2439 name_len++; /* trailing null */
2441 } else { /* BB improve the check for buffer overruns BB */
2442 name_len = strnlen(searchName, PATH_MAX);
2443 name_len++; /* trailing null */
2444 strncpy(pSMB->FileName, searchName, name_len);
2447 params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */ ;
2448 pSMB->TotalDataCount = 0;
2449 pSMB->MaxParameterCount = cpu_to_le16(2);
2450 pSMB->MaxDataCount = cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
2451 pSMB->MaxSetupCount = 0;
2455 pSMB->Reserved2 = 0;
2456 pSMB->ParameterOffset = cpu_to_le16(offsetof(
2457 struct smb_com_transaction2_qpi_req ,InformationLevel) - 4);
2458 pSMB->DataCount = 0;
2459 pSMB->DataOffset = 0;
2460 pSMB->SetupCount = 1;
2461 pSMB->Reserved3 = 0;
2462 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
2463 byte_count = params + 1 /* pad */ ;
2464 pSMB->TotalParameterCount = cpu_to_le16(params);
2465 pSMB->ParameterCount = pSMB->TotalParameterCount;
2466 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_ALL_INFO);
2467 pSMB->Reserved4 = 0;
2468 pSMB->hdr.smb_buf_length += byte_count;
2469 pSMB->ByteCount = cpu_to_le16(byte_count);
2471 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2472 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2474 cFYI(1, ("Send error in QPathInfo = %d", rc));
2475 } else { /* decode response */
2476 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
2478 if (rc || (pSMBr->ByteCount < 40))
2479 rc = -EIO; /* bad smb */
2480 else if (pFindData){
2481 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
2482 memcpy((char *) pFindData,
2483 (char *) &pSMBr->hdr.Protocol +
2484 data_offset, sizeof (FILE_ALL_INFO));
2488 cifs_buf_release(pSMB);
2490 goto QPathInfoRetry;
2496 CIFSSMBUnixQPathInfo(const int xid, struct cifsTconInfo *tcon,
2497 const unsigned char *searchName,
2498 FILE_UNIX_BASIC_INFO * pFindData,
2499 const struct nls_table *nls_codepage, int remap)
2501 /* SMB_QUERY_FILE_UNIX_BASIC */
2502 TRANSACTION2_QPI_REQ *pSMB = NULL;
2503 TRANSACTION2_QPI_RSP *pSMBr = NULL;
2505 int bytes_returned = 0;
2507 __u16 params, byte_count;
2509 cFYI(1, ("In QPathInfo (Unix) the path %s", searchName));
2511 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2516 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2518 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
2519 PATH_MAX, nls_codepage, remap);
2520 name_len++; /* trailing null */
2522 } else { /* BB improve the check for buffer overruns BB */
2523 name_len = strnlen(searchName, PATH_MAX);
2524 name_len++; /* trailing null */
2525 strncpy(pSMB->FileName, searchName, name_len);
2528 params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */ ;
2529 pSMB->TotalDataCount = 0;
2530 pSMB->MaxParameterCount = cpu_to_le16(2);
2531 /* BB find exact max SMB PDU from sess structure BB */
2532 pSMB->MaxDataCount = cpu_to_le16(4000);
2533 pSMB->MaxSetupCount = 0;
2537 pSMB->Reserved2 = 0;
2538 pSMB->ParameterOffset = cpu_to_le16(offsetof(
2539 struct smb_com_transaction2_qpi_req ,InformationLevel) - 4);
2540 pSMB->DataCount = 0;
2541 pSMB->DataOffset = 0;
2542 pSMB->SetupCount = 1;
2543 pSMB->Reserved3 = 0;
2544 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
2545 byte_count = params + 1 /* pad */ ;
2546 pSMB->TotalParameterCount = cpu_to_le16(params);
2547 pSMB->ParameterCount = pSMB->TotalParameterCount;
2548 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC);
2549 pSMB->Reserved4 = 0;
2550 pSMB->hdr.smb_buf_length += byte_count;
2551 pSMB->ByteCount = cpu_to_le16(byte_count);
2553 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2554 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2556 cFYI(1, ("Send error in QPathInfo = %d", rc));
2557 } else { /* decode response */
2558 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
2560 if (rc || (pSMBr->ByteCount < sizeof(FILE_UNIX_BASIC_INFO))) {
2561 rc = -EIO; /* bad smb */
2563 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
2564 memcpy((char *) pFindData,
2565 (char *) &pSMBr->hdr.Protocol +
2567 sizeof (FILE_UNIX_BASIC_INFO));
2570 cifs_buf_release(pSMB);
2572 goto UnixQPathInfoRetry;
2577 #if 0 /* function unused at present */
2578 int CIFSFindSingle(const int xid, struct cifsTconInfo *tcon,
2579 const char *searchName, FILE_ALL_INFO * findData,
2580 const struct nls_table *nls_codepage)
2582 /* level 257 SMB_ */
2583 TRANSACTION2_FFIRST_REQ *pSMB = NULL;
2584 TRANSACTION2_FFIRST_RSP *pSMBr = NULL;
2588 __u16 params, byte_count;
2590 cFYI(1, ("In FindUnique"));
2592 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2597 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2599 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName, PATH_MAX
2600 /* find define for this maxpathcomponent */
2602 name_len++; /* trailing null */
2604 } else { /* BB improve the check for buffer overruns BB */
2605 name_len = strnlen(searchName, PATH_MAX);
2606 name_len++; /* trailing null */
2607 strncpy(pSMB->FileName, searchName, name_len);
2610 params = 12 + name_len /* includes null */ ;
2611 pSMB->TotalDataCount = 0; /* no EAs */
2612 pSMB->MaxParameterCount = cpu_to_le16(2);
2613 pSMB->MaxDataCount = cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
2614 pSMB->MaxSetupCount = 0;
2618 pSMB->Reserved2 = 0;
2619 pSMB->ParameterOffset = cpu_to_le16(
2620 offsetof(struct smb_com_transaction2_ffirst_req,InformationLevel) - 4);
2621 pSMB->DataCount = 0;
2622 pSMB->DataOffset = 0;
2623 pSMB->SetupCount = 1; /* one byte, no need to le convert */
2624 pSMB->Reserved3 = 0;
2625 pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_FIRST);
2626 byte_count = params + 1 /* pad */ ;
2627 pSMB->TotalParameterCount = cpu_to_le16(params);
2628 pSMB->ParameterCount = pSMB->TotalParameterCount;
2629 pSMB->SearchAttributes =
2630 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
2632 pSMB->SearchCount = cpu_to_le16(16); /* BB increase */
2633 pSMB->SearchFlags = cpu_to_le16(1);
2634 pSMB->InformationLevel = cpu_to_le16(SMB_FIND_FILE_DIRECTORY_INFO);
2635 pSMB->SearchStorageType = 0; /* BB what should we set this to? BB */
2636 pSMB->hdr.smb_buf_length += byte_count;
2637 pSMB->ByteCount = cpu_to_le16(byte_count);
2639 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2640 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2643 cFYI(1, ("Send error in FindFileDirInfo = %d", rc));
2644 } else { /* decode response */
2645 cifs_stats_inc(&tcon->num_ffirst);
2649 cifs_buf_release(pSMB);
2651 goto findUniqueRetry;
2655 #endif /* end unused (temporarily) function */
2657 /* xid, tcon, searchName and codepage are input parms, rest are returned */
2659 CIFSFindFirst(const int xid, struct cifsTconInfo *tcon,
2660 const char *searchName,
2661 const struct nls_table *nls_codepage,
2663 struct cifs_search_info * psrch_inf, int remap, const char dirsep)
2665 /* level 257 SMB_ */
2666 TRANSACTION2_FFIRST_REQ *pSMB = NULL;
2667 TRANSACTION2_FFIRST_RSP *pSMBr = NULL;
2668 T2_FFIRST_RSP_PARMS * parms;
2670 int bytes_returned = 0;
2672 __u16 params, byte_count;
2674 cFYI(1, ("In FindFirst for %s",searchName));
2677 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2682 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2684 cifsConvertToUCS((__le16 *) pSMB->FileName,searchName,
2685 PATH_MAX, nls_codepage, remap);
2686 /* We can not add the asterik earlier in case
2687 it got remapped to 0xF03A as if it were part of the
2688 directory name instead of a wildcard */
2690 pSMB->FileName[name_len] = dirsep;
2691 pSMB->FileName[name_len+1] = 0;
2692 pSMB->FileName[name_len+2] = '*';
2693 pSMB->FileName[name_len+3] = 0;
2694 name_len += 4; /* now the trailing null */
2695 pSMB->FileName[name_len] = 0; /* null terminate just in case */
2696 pSMB->FileName[name_len+1] = 0;
2698 } else { /* BB add check for overrun of SMB buf BB */
2699 name_len = strnlen(searchName, PATH_MAX);
2700 /* BB fix here and in unicode clause above ie
2701 if(name_len > buffersize-header)
2702 free buffer exit; BB */
2703 strncpy(pSMB->FileName, searchName, name_len);
2704 pSMB->FileName[name_len] = dirsep;
2705 pSMB->FileName[name_len+1] = '*';
2706 pSMB->FileName[name_len+2] = 0;
2710 params = 12 + name_len /* includes null */ ;
2711 pSMB->TotalDataCount = 0; /* no EAs */
2712 pSMB->MaxParameterCount = cpu_to_le16(10);
2713 pSMB->MaxDataCount = cpu_to_le16((tcon->ses->server->maxBuf -
2714 MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
2715 pSMB->MaxSetupCount = 0;
2719 pSMB->Reserved2 = 0;
2720 byte_count = params + 1 /* pad */ ;
2721 pSMB->TotalParameterCount = cpu_to_le16(params);
2722 pSMB->ParameterCount = pSMB->TotalParameterCount;
2723 pSMB->ParameterOffset = cpu_to_le16(
2724 offsetof(struct smb_com_transaction2_ffirst_req, SearchAttributes) - 4);
2725 pSMB->DataCount = 0;
2726 pSMB->DataOffset = 0;
2727 pSMB->SetupCount = 1; /* one byte, no need to make endian neutral */
2728 pSMB->Reserved3 = 0;
2729 pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_FIRST);
2730 pSMB->SearchAttributes =
2731 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
2733 pSMB->SearchCount= cpu_to_le16(CIFSMaxBufSize/sizeof(FILE_UNIX_INFO));
2734 pSMB->SearchFlags = cpu_to_le16(CIFS_SEARCH_CLOSE_AT_END |
2735 CIFS_SEARCH_RETURN_RESUME);
2736 pSMB->InformationLevel = cpu_to_le16(psrch_inf->info_level);
2738 /* BB what should we set StorageType to? Does it matter? BB */
2739 pSMB->SearchStorageType = 0;
2740 pSMB->hdr.smb_buf_length += byte_count;
2741 pSMB->ByteCount = cpu_to_le16(byte_count);
2743 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2744 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2745 cifs_stats_inc(&tcon->num_ffirst);
2747 if (rc) {/* BB add logic to retry regular search if Unix search rejected unexpectedly by server */
2748 /* BB Add code to handle unsupported level rc */
2749 cFYI(1, ("Error in FindFirst = %d", rc));
2752 cifs_buf_release(pSMB);
2754 /* BB eventually could optimize out free and realloc of buf */
2757 goto findFirstRetry;
2758 } else { /* decode response */
2759 /* BB remember to free buffer if error BB */
2760 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
2762 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
2763 psrch_inf->unicode = TRUE;
2765 psrch_inf->unicode = FALSE;
2767 psrch_inf->ntwrk_buf_start = (char *)pSMBr;
2768 psrch_inf->srch_entries_start =
2769 (char *) &pSMBr->hdr.Protocol +
2770 le16_to_cpu(pSMBr->t2.DataOffset);
2771 parms = (T2_FFIRST_RSP_PARMS *)((char *) &pSMBr->hdr.Protocol +
2772 le16_to_cpu(pSMBr->t2.ParameterOffset));
2774 if(parms->EndofSearch)
2775 psrch_inf->endOfSearch = TRUE;
2777 psrch_inf->endOfSearch = FALSE;
2779 psrch_inf->entries_in_buffer = le16_to_cpu(parms->SearchCount);
2780 psrch_inf->index_of_last_entry =
2781 psrch_inf->entries_in_buffer;
2782 *pnetfid = parms->SearchHandle;
2784 cifs_buf_release(pSMB);
2791 int CIFSFindNext(const int xid, struct cifsTconInfo *tcon,
2792 __u16 searchHandle, struct cifs_search_info * psrch_inf)
2794 TRANSACTION2_FNEXT_REQ *pSMB = NULL;
2795 TRANSACTION2_FNEXT_RSP *pSMBr = NULL;
2796 T2_FNEXT_RSP_PARMS * parms;
2797 char *response_data;
2799 int bytes_returned, name_len;
2800 __u16 params, byte_count;
2802 cFYI(1, ("In FindNext"));
2804 if(psrch_inf->endOfSearch == TRUE)
2807 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2812 params = 14; /* includes 2 bytes of null string, converted to LE below */
2814 pSMB->TotalDataCount = 0; /* no EAs */
2815 pSMB->MaxParameterCount = cpu_to_le16(8);
2816 pSMB->MaxDataCount =
2817 cpu_to_le16((tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
2818 pSMB->MaxSetupCount = 0;
2822 pSMB->Reserved2 = 0;
2823 pSMB->ParameterOffset = cpu_to_le16(
2824 offsetof(struct smb_com_transaction2_fnext_req,SearchHandle) - 4);
2825 pSMB->DataCount = 0;
2826 pSMB->DataOffset = 0;
2827 pSMB->SetupCount = 1;
2828 pSMB->Reserved3 = 0;
2829 pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_NEXT);
2830 pSMB->SearchHandle = searchHandle; /* always kept as le */
2832 cpu_to_le16(CIFSMaxBufSize / sizeof (FILE_UNIX_INFO));
2833 /* test for Unix extensions */
2834 /* if (tcon->ses->capabilities & CAP_UNIX) {
2835 pSMB->InformationLevel = cpu_to_le16(SMB_FIND_FILE_UNIX);
2836 psrch_inf->info_level = SMB_FIND_FILE_UNIX;
2838 pSMB->InformationLevel =
2839 cpu_to_le16(SMB_FIND_FILE_DIRECTORY_INFO);
2840 psrch_inf->info_level = SMB_FIND_FILE_DIRECTORY_INFO;
2842 pSMB->InformationLevel = cpu_to_le16(psrch_inf->info_level);
2843 pSMB->ResumeKey = psrch_inf->resume_key;
2845 cpu_to_le16(CIFS_SEARCH_CLOSE_AT_END | CIFS_SEARCH_RETURN_RESUME);
2847 name_len = psrch_inf->resume_name_len;
2849 if(name_len < PATH_MAX) {
2850 memcpy(pSMB->ResumeFileName, psrch_inf->presume_name, name_len);
2851 byte_count += name_len;
2852 /* 14 byte parm len above enough for 2 byte null terminator */
2853 pSMB->ResumeFileName[name_len] = 0;
2854 pSMB->ResumeFileName[name_len+1] = 0;
2857 goto FNext2_err_exit;
2859 byte_count = params + 1 /* pad */ ;
2860 pSMB->TotalParameterCount = cpu_to_le16(params);
2861 pSMB->ParameterCount = pSMB->TotalParameterCount;
2862 pSMB->hdr.smb_buf_length += byte_count;
2863 pSMB->ByteCount = cpu_to_le16(byte_count);
2865 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2866 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2867 cifs_stats_inc(&tcon->num_fnext);
2870 psrch_inf->endOfSearch = TRUE;
2871 rc = 0; /* search probably was closed at end of search above */
2873 cFYI(1, ("FindNext returned = %d", rc));
2874 } else { /* decode response */
2875 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
2878 /* BB fixme add lock for file (srch_info) struct here */
2879 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
2880 psrch_inf->unicode = TRUE;
2882 psrch_inf->unicode = FALSE;
2883 response_data = (char *) &pSMBr->hdr.Protocol +
2884 le16_to_cpu(pSMBr->t2.ParameterOffset);
2885 parms = (T2_FNEXT_RSP_PARMS *)response_data;
2886 response_data = (char *)&pSMBr->hdr.Protocol +
2887 le16_to_cpu(pSMBr->t2.DataOffset);
2888 cifs_buf_release(psrch_inf->ntwrk_buf_start);
2889 psrch_inf->srch_entries_start = response_data;
2890 psrch_inf->ntwrk_buf_start = (char *)pSMB;
2891 if(parms->EndofSearch)
2892 psrch_inf->endOfSearch = TRUE;
2894 psrch_inf->endOfSearch = FALSE;
2896 psrch_inf->entries_in_buffer = le16_to_cpu(parms->SearchCount);
2897 psrch_inf->index_of_last_entry +=
2898 psrch_inf->entries_in_buffer;
2899 /* cFYI(1,("fnxt2 entries in buf %d index_of_last %d",psrch_inf->entries_in_buffer,psrch_inf->index_of_last_entry)); */
2901 /* BB fixme add unlock here */
2906 /* BB On error, should we leave previous search buf (and count and
2907 last entry fields) intact or free the previous one? */
2909 /* Note: On -EAGAIN error only caller can retry on handle based calls
2910 since file handle passed in no longer valid */
2913 cifs_buf_release(pSMB);
2919 CIFSFindClose(const int xid, struct cifsTconInfo *tcon, const __u16 searchHandle)
2922 FINDCLOSE_REQ *pSMB = NULL;
2923 CLOSE_RSP *pSMBr = NULL; /* BB removeme BB */
2926 cFYI(1, ("In CIFSSMBFindClose"));
2927 rc = small_smb_init(SMB_COM_FIND_CLOSE2, 1, tcon, (void **)&pSMB);
2929 /* no sense returning error if session restarted
2930 as file handle has been closed */
2936 pSMBr = (CLOSE_RSP *)pSMB; /* BB removeme BB */
2937 pSMB->FileID = searchHandle;
2938 pSMB->ByteCount = 0;
2939 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2940 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2942 cERROR(1, ("Send error in FindClose = %d", rc));
2944 cifs_stats_inc(&tcon->num_fclose);
2945 cifs_small_buf_release(pSMB);
2947 /* Since session is dead, search handle closed on server already */
2954 #ifdef CONFIG_CIFS_EXPERIMENTAL
2956 CIFSGetSrvInodeNumber(const int xid, struct cifsTconInfo *tcon,
2957 const unsigned char *searchName,
2958 __u64 * inode_number,
2959 const struct nls_table *nls_codepage, int remap)
2962 TRANSACTION2_QPI_REQ *pSMB = NULL;
2963 TRANSACTION2_QPI_RSP *pSMBr = NULL;
2964 int name_len, bytes_returned;
2965 __u16 params, byte_count;
2967 cFYI(1,("In GetSrvInodeNum for %s",searchName));
2971 GetInodeNumberRetry:
2972 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2978 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2980 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
2981 PATH_MAX,nls_codepage, remap);
2982 name_len++; /* trailing null */
2984 } else { /* BB improve the check for buffer overruns BB */
2985 name_len = strnlen(searchName, PATH_MAX);
2986 name_len++; /* trailing null */
2987 strncpy(pSMB->FileName, searchName, name_len);
2990 params = 2 /* level */ + 4 /* rsrvd */ + name_len /* incl null */ ;
2991 pSMB->TotalDataCount = 0;
2992 pSMB->MaxParameterCount = cpu_to_le16(2);
2993 /* BB find exact max data count below from sess structure BB */
2994 pSMB->MaxDataCount = cpu_to_le16(4000);
2995 pSMB->MaxSetupCount = 0;
2999 pSMB->Reserved2 = 0;
3000 pSMB->ParameterOffset = cpu_to_le16(offsetof(
3001 struct smb_com_transaction2_qpi_req ,InformationLevel) - 4);
3002 pSMB->DataCount = 0;
3003 pSMB->DataOffset = 0;
3004 pSMB->SetupCount = 1;
3005 pSMB->Reserved3 = 0;
3006 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
3007 byte_count = params + 1 /* pad */ ;
3008 pSMB->TotalParameterCount = cpu_to_le16(params);
3009 pSMB->ParameterCount = pSMB->TotalParameterCount;
3010 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_INTERNAL_INFO);
3011 pSMB->Reserved4 = 0;
3012 pSMB->hdr.smb_buf_length += byte_count;
3013 pSMB->ByteCount = cpu_to_le16(byte_count);
3015 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3016 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3018 cFYI(1, ("error %d in QueryInternalInfo", rc));
3020 /* decode response */
3021 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3022 if (rc || (pSMBr->ByteCount < 2))
3023 /* BB also check enough total bytes returned */
3024 /* If rc should we check for EOPNOSUPP and
3025 disable the srvino flag? or in caller? */
3026 rc = -EIO; /* bad smb */
3028 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3029 __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
3030 struct file_internal_info * pfinfo;
3031 /* BB Do we need a cast or hash here ? */
3033 cFYI(1, ("Illegal size ret in QryIntrnlInf"));
3035 goto GetInodeNumOut;
3037 pfinfo = (struct file_internal_info *)
3038 (data_offset + (char *) &pSMBr->hdr.Protocol);
3039 *inode_number = pfinfo->UniqueId;
3043 cifs_buf_release(pSMB);
3045 goto GetInodeNumberRetry;
3048 #endif /* CIFS_EXPERIMENTAL */
3051 CIFSGetDFSRefer(const int xid, struct cifsSesInfo *ses,
3052 const unsigned char *searchName,
3053 unsigned char **targetUNCs,
3054 unsigned int *number_of_UNC_in_array,
3055 const struct nls_table *nls_codepage, int remap)
3057 /* TRANS2_GET_DFS_REFERRAL */
3058 TRANSACTION2_GET_DFS_REFER_REQ *pSMB = NULL;
3059 TRANSACTION2_GET_DFS_REFER_RSP *pSMBr = NULL;
3060 struct dfs_referral_level_3 * referrals = NULL;
3066 __u16 params, byte_count;
3067 *number_of_UNC_in_array = 0;
3070 cFYI(1, ("In GetDFSRefer the path %s", searchName));
3074 rc = smb_init(SMB_COM_TRANSACTION2, 15, NULL, (void **) &pSMB,
3079 /* server pointer checked in called function,
3080 but should never be null here anyway */
3081 pSMB->hdr.Mid = GetNextMid(ses->server);
3082 pSMB->hdr.Tid = ses->ipc_tid;
3083 pSMB->hdr.Uid = ses->Suid;
3084 if (ses->capabilities & CAP_STATUS32) {
3085 pSMB->hdr.Flags2 |= SMBFLG2_ERR_STATUS;
3087 if (ses->capabilities & CAP_DFS) {
3088 pSMB->hdr.Flags2 |= SMBFLG2_DFS;
3091 if (ses->capabilities & CAP_UNICODE) {
3092 pSMB->hdr.Flags2 |= SMBFLG2_UNICODE;
3094 cifsConvertToUCS((__le16 *) pSMB->RequestFileName,
3095 searchName, PATH_MAX, nls_codepage, remap);
3096 name_len++; /* trailing null */
3098 } else { /* BB improve the check for buffer overruns BB */
3099 name_len = strnlen(searchName, PATH_MAX);
3100 name_len++; /* trailing null */
3101 strncpy(pSMB->RequestFileName, searchName, name_len);
3104 params = 2 /* level */ + name_len /*includes null */ ;
3105 pSMB->TotalDataCount = 0;
3106 pSMB->DataCount = 0;
3107 pSMB->DataOffset = 0;
3108 pSMB->MaxParameterCount = 0;
3109 pSMB->MaxDataCount = cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
3110 pSMB->MaxSetupCount = 0;
3114 pSMB->Reserved2 = 0;
3115 pSMB->ParameterOffset = cpu_to_le16(offsetof(
3116 struct smb_com_transaction2_get_dfs_refer_req, MaxReferralLevel) - 4);
3117 pSMB->SetupCount = 1;
3118 pSMB->Reserved3 = 0;
3119 pSMB->SubCommand = cpu_to_le16(TRANS2_GET_DFS_REFERRAL);
3120 byte_count = params + 3 /* pad */ ;
3121 pSMB->ParameterCount = cpu_to_le16(params);
3122 pSMB->TotalParameterCount = pSMB->ParameterCount;
3123 pSMB->MaxReferralLevel = cpu_to_le16(3);
3124 pSMB->hdr.smb_buf_length += byte_count;
3125 pSMB->ByteCount = cpu_to_le16(byte_count);
3127 rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB,
3128 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3130 cFYI(1, ("Send error in GetDFSRefer = %d", rc));
3131 } else { /* decode response */
3132 /* BB Add logic to parse referrals here */
3133 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3135 if (rc || (pSMBr->ByteCount < 17)) /* BB also check enough total bytes returned */
3136 rc = -EIO; /* bad smb */
3138 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3139 __u16 data_count = le16_to_cpu(pSMBr->t2.DataCount);
3142 ("Decoding GetDFSRefer response. BCC: %d Offset %d",
3143 pSMBr->ByteCount, data_offset));
3145 (struct dfs_referral_level_3 *)
3146 (8 /* sizeof start of data block */ +
3148 (char *) &pSMBr->hdr.Protocol);
3149 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",
3150 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)));
3151 /* BB This field is actually two bytes in from start of
3152 data block so we could do safety check that DataBlock
3153 begins at address of pSMBr->NumberOfReferrals */
3154 *number_of_UNC_in_array = le16_to_cpu(pSMBr->NumberOfReferrals);
3156 /* BB Fix below so can return more than one referral */
3157 if(*number_of_UNC_in_array > 1)
3158 *number_of_UNC_in_array = 1;
3160 /* get the length of the strings describing refs */
3162 for(i=0;i<*number_of_UNC_in_array;i++) {
3163 /* make sure that DfsPathOffset not past end */
3164 __u16 offset = le16_to_cpu(referrals->DfsPathOffset);
3165 if (offset > data_count) {
3166 /* if invalid referral, stop here and do
3167 not try to copy any more */
3168 *number_of_UNC_in_array = i;
3171 temp = ((char *)referrals) + offset;
3173 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
3174 name_len += UniStrnlen((wchar_t *)temp,data_count);
3176 name_len += strnlen(temp,data_count);
3179 /* BB add check that referral pointer does not fall off end PDU */
3182 /* BB add check for name_len bigger than bcc */
3184 kmalloc(name_len+1+ (*number_of_UNC_in_array),GFP_KERNEL);
3185 if(*targetUNCs == NULL) {
3189 /* copy the ref strings */
3191 (struct dfs_referral_level_3 *)
3192 (8 /* sizeof data hdr */ +
3194 (char *) &pSMBr->hdr.Protocol);
3196 for(i=0;i<*number_of_UNC_in_array;i++) {
3197 temp = ((char *)referrals) + le16_to_cpu(referrals->DfsPathOffset);
3198 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
3199 cifs_strfromUCS_le(*targetUNCs,
3200 (wchar_t *) temp, name_len, nls_codepage);
3202 strncpy(*targetUNCs,temp,name_len);
3204 /* BB update target_uncs pointers */
3214 cifs_buf_release(pSMB);
3222 /* Query File System Info such as free space to old servers such as Win 9x */
3224 SMBOldQFSInfo(const int xid, struct cifsTconInfo *tcon, struct kstatfs *FSData)
3226 /* level 0x01 SMB_QUERY_FILE_SYSTEM_INFO */
3227 TRANSACTION2_QFSI_REQ *pSMB = NULL;
3228 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
3229 FILE_SYSTEM_ALLOC_INFO *response_data;
3231 int bytes_returned = 0;
3232 __u16 params, byte_count;
3234 cFYI(1, ("OldQFSInfo"));
3236 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3240 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3245 params = 2; /* level */
3246 pSMB->TotalDataCount = 0;
3247 pSMB->MaxParameterCount = cpu_to_le16(2);
3248 pSMB->MaxDataCount = cpu_to_le16(1000);
3249 pSMB->MaxSetupCount = 0;
3253 pSMB->Reserved2 = 0;
3254 byte_count = params + 1 /* pad */ ;
3255 pSMB->TotalParameterCount = cpu_to_le16(params);
3256 pSMB->ParameterCount = pSMB->TotalParameterCount;
3257 pSMB->ParameterOffset = cpu_to_le16(offsetof(
3258 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
3259 pSMB->DataCount = 0;
3260 pSMB->DataOffset = 0;
3261 pSMB->SetupCount = 1;
3262 pSMB->Reserved3 = 0;
3263 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
3264 pSMB->InformationLevel = cpu_to_le16(SMB_INFO_ALLOCATION);
3265 pSMB->hdr.smb_buf_length += byte_count;
3266 pSMB->ByteCount = cpu_to_le16(byte_count);
3268 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3269 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3271 cFYI(1, ("Send error in QFSInfo = %d", rc));
3272 } else { /* decode response */
3273 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3275 if (rc || (pSMBr->ByteCount < 18))
3276 rc = -EIO; /* bad smb */
3278 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3279 cFYI(1,("qfsinf resp BCC: %d Offset %d",
3280 pSMBr->ByteCount, data_offset));
3283 (FILE_SYSTEM_ALLOC_INFO *)
3284 (((char *) &pSMBr->hdr.Protocol) + data_offset);
3286 le16_to_cpu(response_data->BytesPerSector) *
3287 le32_to_cpu(response_data->
3288 SectorsPerAllocationUnit);
3290 le32_to_cpu(response_data->TotalAllocationUnits);
3291 FSData->f_bfree = FSData->f_bavail =
3292 le32_to_cpu(response_data->FreeAllocationUnits);
3294 ("Blocks: %lld Free: %lld Block size %ld",
3295 (unsigned long long)FSData->f_blocks,
3296 (unsigned long long)FSData->f_bfree,
3300 cifs_buf_release(pSMB);
3303 goto oldQFSInfoRetry;
3309 CIFSSMBQFSInfo(const int xid, struct cifsTconInfo *tcon, struct kstatfs *FSData)
3311 /* level 0x103 SMB_QUERY_FILE_SYSTEM_INFO */
3312 TRANSACTION2_QFSI_REQ *pSMB = NULL;
3313 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
3314 FILE_SYSTEM_INFO *response_data;
3316 int bytes_returned = 0;
3317 __u16 params, byte_count;
3319 cFYI(1, ("In QFSInfo"));
3321 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3326 params = 2; /* level */
3327 pSMB->TotalDataCount = 0;
3328 pSMB->MaxParameterCount = cpu_to_le16(2);
3329 pSMB->MaxDataCount = cpu_to_le16(1000);
3330 pSMB->MaxSetupCount = 0;
3334 pSMB->Reserved2 = 0;
3335 byte_count = params + 1 /* pad */ ;
3336 pSMB->TotalParameterCount = cpu_to_le16(params);
3337 pSMB->ParameterCount = pSMB->TotalParameterCount;
3338 pSMB->ParameterOffset = cpu_to_le16(offsetof(
3339 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
3340 pSMB->DataCount = 0;
3341 pSMB->DataOffset = 0;
3342 pSMB->SetupCount = 1;
3343 pSMB->Reserved3 = 0;
3344 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
3345 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_SIZE_INFO);
3346 pSMB->hdr.smb_buf_length += byte_count;
3347 pSMB->ByteCount = cpu_to_le16(byte_count);
3349 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3350 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3352 cFYI(1, ("Send error in QFSInfo = %d", rc));
3353 } else { /* decode response */
3354 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3356 if (rc || (pSMBr->ByteCount < 24))
3357 rc = -EIO; /* bad smb */
3359 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3363 *) (((char *) &pSMBr->hdr.Protocol) +
3366 le32_to_cpu(response_data->BytesPerSector) *
3367 le32_to_cpu(response_data->
3368 SectorsPerAllocationUnit);
3370 le64_to_cpu(response_data->TotalAllocationUnits);
3371 FSData->f_bfree = FSData->f_bavail =
3372 le64_to_cpu(response_data->FreeAllocationUnits);
3374 ("Blocks: %lld Free: %lld Block size %ld",
3375 (unsigned long long)FSData->f_blocks,
3376 (unsigned long long)FSData->f_bfree,
3380 cifs_buf_release(pSMB);
3389 CIFSSMBQFSAttributeInfo(const int xid, struct cifsTconInfo *tcon)
3391 /* level 0x105 SMB_QUERY_FILE_SYSTEM_INFO */
3392 TRANSACTION2_QFSI_REQ *pSMB = NULL;
3393 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
3394 FILE_SYSTEM_ATTRIBUTE_INFO *response_data;
3396 int bytes_returned = 0;
3397 __u16 params, byte_count;
3399 cFYI(1, ("In QFSAttributeInfo"));
3401 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3406 params = 2; /* level */
3407 pSMB->TotalDataCount = 0;
3408 pSMB->MaxParameterCount = cpu_to_le16(2);
3409 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
3410 pSMB->MaxSetupCount = 0;
3414 pSMB->Reserved2 = 0;
3415 byte_count = params + 1 /* pad */ ;
3416 pSMB->TotalParameterCount = cpu_to_le16(params);
3417 pSMB->ParameterCount = pSMB->TotalParameterCount;
3418 pSMB->ParameterOffset = cpu_to_le16(offsetof(
3419 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
3420 pSMB->DataCount = 0;
3421 pSMB->DataOffset = 0;
3422 pSMB->SetupCount = 1;
3423 pSMB->Reserved3 = 0;
3424 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
3425 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_ATTRIBUTE_INFO);
3426 pSMB->hdr.smb_buf_length += byte_count;
3427 pSMB->ByteCount = cpu_to_le16(byte_count);
3429 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3430 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3432 cERROR(1, ("Send error in QFSAttributeInfo = %d", rc));
3433 } else { /* decode response */
3434 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3436 if (rc || (pSMBr->ByteCount < 13)) { /* BB also check enough bytes returned */
3437 rc = -EIO; /* bad smb */
3439 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3441 (FILE_SYSTEM_ATTRIBUTE_INFO
3442 *) (((char *) &pSMBr->hdr.Protocol) +
3444 memcpy(&tcon->fsAttrInfo, response_data,
3445 sizeof (FILE_SYSTEM_ATTRIBUTE_INFO));
3448 cifs_buf_release(pSMB);
3451 goto QFSAttributeRetry;
3457 CIFSSMBQFSDeviceInfo(const int xid, struct cifsTconInfo *tcon)
3459 /* level 0x104 SMB_QUERY_FILE_SYSTEM_INFO */
3460 TRANSACTION2_QFSI_REQ *pSMB = NULL;
3461 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
3462 FILE_SYSTEM_DEVICE_INFO *response_data;
3464 int bytes_returned = 0;
3465 __u16 params, byte_count;
3467 cFYI(1, ("In QFSDeviceInfo"));
3469 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3474 params = 2; /* level */
3475 pSMB->TotalDataCount = 0;
3476 pSMB->MaxParameterCount = cpu_to_le16(2);
3477 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
3478 pSMB->MaxSetupCount = 0;
3482 pSMB->Reserved2 = 0;
3483 byte_count = params + 1 /* pad */ ;
3484 pSMB->TotalParameterCount = cpu_to_le16(params);
3485 pSMB->ParameterCount = pSMB->TotalParameterCount;
3486 pSMB->ParameterOffset = cpu_to_le16(offsetof(
3487 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
3489 pSMB->DataCount = 0;
3490 pSMB->DataOffset = 0;
3491 pSMB->SetupCount = 1;
3492 pSMB->Reserved3 = 0;
3493 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
3494 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_DEVICE_INFO);
3495 pSMB->hdr.smb_buf_length += byte_count;
3496 pSMB->ByteCount = cpu_to_le16(byte_count);
3498 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3499 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3501 cFYI(1, ("Send error in QFSDeviceInfo = %d", rc));
3502 } else { /* decode response */
3503 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3505 if (rc || (pSMBr->ByteCount < sizeof (FILE_SYSTEM_DEVICE_INFO)))
3506 rc = -EIO; /* bad smb */
3508 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3510 (FILE_SYSTEM_DEVICE_INFO *)
3511 (((char *) &pSMBr->hdr.Protocol) +
3513 memcpy(&tcon->fsDevInfo, response_data,
3514 sizeof (FILE_SYSTEM_DEVICE_INFO));
3517 cifs_buf_release(pSMB);
3520 goto QFSDeviceRetry;
3526 CIFSSMBQFSUnixInfo(const int xid, struct cifsTconInfo *tcon)
3528 /* level 0x200 SMB_QUERY_CIFS_UNIX_INFO */
3529 TRANSACTION2_QFSI_REQ *pSMB = NULL;
3530 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
3531 FILE_SYSTEM_UNIX_INFO *response_data;
3533 int bytes_returned = 0;
3534 __u16 params, byte_count;
3536 cFYI(1, ("In QFSUnixInfo"));
3538 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3543 params = 2; /* level */
3544 pSMB->TotalDataCount = 0;
3545 pSMB->DataCount = 0;
3546 pSMB->DataOffset = 0;
3547 pSMB->MaxParameterCount = cpu_to_le16(2);
3548 pSMB->MaxDataCount = cpu_to_le16(100); /* BB find exact max SMB PDU from sess structure BB */
3549 pSMB->MaxSetupCount = 0;
3553 pSMB->Reserved2 = 0;
3554 byte_count = params + 1 /* pad */ ;
3555 pSMB->ParameterCount = cpu_to_le16(params);
3556 pSMB->TotalParameterCount = pSMB->ParameterCount;
3557 pSMB->ParameterOffset = cpu_to_le16(offsetof(struct
3558 smb_com_transaction2_qfsi_req, InformationLevel) - 4);
3559 pSMB->SetupCount = 1;
3560 pSMB->Reserved3 = 0;
3561 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
3562 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_CIFS_UNIX_INFO);
3563 pSMB->hdr.smb_buf_length += byte_count;
3564 pSMB->ByteCount = cpu_to_le16(byte_count);
3566 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3567 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3569 cERROR(1, ("Send error in QFSUnixInfo = %d", rc));
3570 } else { /* decode response */
3571 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3573 if (rc || (pSMBr->ByteCount < 13)) {
3574 rc = -EIO; /* bad smb */
3576 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3578 (FILE_SYSTEM_UNIX_INFO
3579 *) (((char *) &pSMBr->hdr.Protocol) +
3581 memcpy(&tcon->fsUnixInfo, response_data,
3582 sizeof (FILE_SYSTEM_UNIX_INFO));
3585 cifs_buf_release(pSMB);
3595 CIFSSMBSetFSUnixInfo(const int xid, struct cifsTconInfo *tcon, __u64 cap)
3597 /* level 0x200 SMB_SET_CIFS_UNIX_INFO */
3598 TRANSACTION2_SETFSI_REQ *pSMB = NULL;
3599 TRANSACTION2_SETFSI_RSP *pSMBr = NULL;
3601 int bytes_returned = 0;
3602 __u16 params, param_offset, offset, byte_count;
3604 cFYI(1, ("In SETFSUnixInfo"));
3606 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3611 params = 4; /* 2 bytes zero followed by info level. */
3612 pSMB->MaxSetupCount = 0;
3616 pSMB->Reserved2 = 0;
3617 param_offset = offsetof(struct smb_com_transaction2_setfsi_req, FileNum) - 4;
3618 offset = param_offset + params;
3620 pSMB->MaxParameterCount = cpu_to_le16(4);
3621 pSMB->MaxDataCount = cpu_to_le16(100); /* BB find exact max SMB PDU from sess structure BB */
3622 pSMB->SetupCount = 1;
3623 pSMB->Reserved3 = 0;
3624 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FS_INFORMATION);
3625 byte_count = 1 /* pad */ + params + 12;
3627 pSMB->DataCount = cpu_to_le16(12);
3628 pSMB->ParameterCount = cpu_to_le16(params);
3629 pSMB->TotalDataCount = pSMB->DataCount;
3630 pSMB->TotalParameterCount = pSMB->ParameterCount;
3631 pSMB->ParameterOffset = cpu_to_le16(param_offset);
3632 pSMB->DataOffset = cpu_to_le16(offset);
3636 pSMB->InformationLevel = cpu_to_le16(SMB_SET_CIFS_UNIX_INFO);
3639 pSMB->ClientUnixMajor = cpu_to_le16(CIFS_UNIX_MAJOR_VERSION);
3640 pSMB->ClientUnixMinor = cpu_to_le16(CIFS_UNIX_MINOR_VERSION);
3641 pSMB->ClientUnixCap = cpu_to_le64(cap);
3643 pSMB->hdr.smb_buf_length += byte_count;
3644 pSMB->ByteCount = cpu_to_le16(byte_count);
3646 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3647 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3649 cERROR(1, ("Send error in SETFSUnixInfo = %d", rc));
3650 } else { /* decode response */
3651 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3653 rc = -EIO; /* bad smb */
3656 cifs_buf_release(pSMB);
3659 goto SETFSUnixRetry;
3667 CIFSSMBQFSPosixInfo(const int xid, struct cifsTconInfo *tcon,
3668 struct kstatfs *FSData)
3670 /* level 0x201 SMB_QUERY_CIFS_POSIX_INFO */
3671 TRANSACTION2_QFSI_REQ *pSMB = NULL;
3672 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
3673 FILE_SYSTEM_POSIX_INFO *response_data;
3675 int bytes_returned = 0;
3676 __u16 params, byte_count;
3678 cFYI(1, ("In QFSPosixInfo"));
3680 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3685 params = 2; /* level */
3686 pSMB->TotalDataCount = 0;
3687 pSMB->DataCount = 0;
3688 pSMB->DataOffset = 0;
3689 pSMB->MaxParameterCount = cpu_to_le16(2);
3690 pSMB->MaxDataCount = cpu_to_le16(100); /* BB find exact max SMB PDU from sess structure BB */
3691 pSMB->MaxSetupCount = 0;
3695 pSMB->Reserved2 = 0;
3696 byte_count = params + 1 /* pad */ ;
3697 pSMB->ParameterCount = cpu_to_le16(params);
3698 pSMB->TotalParameterCount = pSMB->ParameterCount;
3699 pSMB->ParameterOffset = cpu_to_le16(offsetof(struct
3700 smb_com_transaction2_qfsi_req, InformationLevel) - 4);
3701 pSMB->SetupCount = 1;
3702 pSMB->Reserved3 = 0;
3703 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
3704 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_POSIX_FS_INFO);
3705 pSMB->hdr.smb_buf_length += byte_count;
3706 pSMB->ByteCount = cpu_to_le16(byte_count);
3708 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3709 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3711 cFYI(1, ("Send error in QFSUnixInfo = %d", rc));
3712 } else { /* decode response */
3713 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3715 if (rc || (pSMBr->ByteCount < 13)) {
3716 rc = -EIO; /* bad smb */
3718 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3720 (FILE_SYSTEM_POSIX_INFO
3721 *) (((char *) &pSMBr->hdr.Protocol) +
3724 le32_to_cpu(response_data->BlockSize);
3726 le64_to_cpu(response_data->TotalBlocks);
3728 le64_to_cpu(response_data->BlocksAvail);
3729 if(response_data->UserBlocksAvail == cpu_to_le64(-1)) {
3730 FSData->f_bavail = FSData->f_bfree;
3733 le64_to_cpu(response_data->UserBlocksAvail);
3735 if(response_data->TotalFileNodes != cpu_to_le64(-1))
3737 le64_to_cpu(response_data->TotalFileNodes);
3738 if(response_data->FreeFileNodes != cpu_to_le64(-1))
3740 le64_to_cpu(response_data->FreeFileNodes);
3743 cifs_buf_release(pSMB);
3752 /* We can not use write of zero bytes trick to
3753 set file size due to need for large file support. Also note that
3754 this SetPathInfo is preferred to SetFileInfo based method in next
3755 routine which is only needed to work around a sharing violation bug
3756 in Samba which this routine can run into */
3759 CIFSSMBSetEOF(const int xid, struct cifsTconInfo *tcon, const char *fileName,
3760 __u64 size, int SetAllocation,
3761 const struct nls_table *nls_codepage, int remap)
3763 struct smb_com_transaction2_spi_req *pSMB = NULL;
3764 struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
3765 struct file_end_of_file_info *parm_data;
3768 int bytes_returned = 0;
3769 __u16 params, byte_count, data_count, param_offset, offset;
3771 cFYI(1, ("In SetEOF"));
3773 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3778 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3780 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
3781 PATH_MAX, nls_codepage, remap);
3782 name_len++; /* trailing null */
3784 } else { /* BB improve the check for buffer overruns BB */
3785 name_len = strnlen(fileName, PATH_MAX);
3786 name_len++; /* trailing null */
3787 strncpy(pSMB->FileName, fileName, name_len);
3789 params = 6 + name_len;
3790 data_count = sizeof (struct file_end_of_file_info);
3791 pSMB->MaxParameterCount = cpu_to_le16(2);
3792 pSMB->MaxDataCount = cpu_to_le16(4100);
3793 pSMB->MaxSetupCount = 0;
3797 pSMB->Reserved2 = 0;
3798 param_offset = offsetof(struct smb_com_transaction2_spi_req,
3799 InformationLevel) - 4;
3800 offset = param_offset + params;
3802 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
3803 pSMB->InformationLevel =
3804 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2);
3806 pSMB->InformationLevel =
3807 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO);
3808 } else /* Set File Size */ {
3809 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
3810 pSMB->InformationLevel =
3811 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO2);
3813 pSMB->InformationLevel =
3814 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO);
3818 (struct file_end_of_file_info *) (((char *) &pSMB->hdr.Protocol) +
3820 pSMB->ParameterOffset = cpu_to_le16(param_offset);
3821 pSMB->DataOffset = cpu_to_le16(offset);
3822 pSMB->SetupCount = 1;
3823 pSMB->Reserved3 = 0;
3824 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
3825 byte_count = 3 /* pad */ + params + data_count;
3826 pSMB->DataCount = cpu_to_le16(data_count);
3827 pSMB->TotalDataCount = pSMB->DataCount;
3828 pSMB->ParameterCount = cpu_to_le16(params);
3829 pSMB->TotalParameterCount = pSMB->ParameterCount;
3830 pSMB->Reserved4 = 0;
3831 pSMB->hdr.smb_buf_length += byte_count;
3832 parm_data->FileSize = cpu_to_le64(size);
3833 pSMB->ByteCount = cpu_to_le16(byte_count);
3834 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3835 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3837 cFYI(1, ("SetPathInfo (file size) returned %d", rc));
3840 cifs_buf_release(pSMB);
3849 CIFSSMBSetFileSize(const int xid, struct cifsTconInfo *tcon, __u64 size,
3850 __u16 fid, __u32 pid_of_opener, int SetAllocation)
3852 struct smb_com_transaction2_sfi_req *pSMB = NULL;
3853 struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
3855 struct file_end_of_file_info *parm_data;
3857 int bytes_returned = 0;
3858 __u16 params, param_offset, offset, byte_count, count;
3860 cFYI(1, ("SetFileSize (via SetFileInfo) %lld",
3862 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
3867 pSMBr = (struct smb_com_transaction2_sfi_rsp *)pSMB;
3869 pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
3870 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));
3873 pSMB->MaxSetupCount = 0;
3877 pSMB->Reserved2 = 0;
3878 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
3879 offset = param_offset + params;
3881 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
3883 count = sizeof(struct file_end_of_file_info);
3884 pSMB->MaxParameterCount = cpu_to_le16(2);
3885 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB PDU from sess */
3886 pSMB->SetupCount = 1;
3887 pSMB->Reserved3 = 0;
3888 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
3889 byte_count = 3 /* pad */ + params + count;
3890 pSMB->DataCount = cpu_to_le16(count);
3891 pSMB->ParameterCount = cpu_to_le16(params);
3892 pSMB->TotalDataCount = pSMB->DataCount;
3893 pSMB->TotalParameterCount = pSMB->ParameterCount;
3894 pSMB->ParameterOffset = cpu_to_le16(param_offset);
3896 (struct file_end_of_file_info *) (((char *) &pSMB->hdr.Protocol) +
3898 pSMB->DataOffset = cpu_to_le16(offset);
3899 parm_data->FileSize = cpu_to_le64(size);
3902 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
3903 pSMB->InformationLevel =
3904 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2);
3906 pSMB->InformationLevel =
3907 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO);
3908 } else /* Set File Size */ {
3909 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
3910 pSMB->InformationLevel =
3911 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO2);
3913 pSMB->InformationLevel =
3914 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO);
3916 pSMB->Reserved4 = 0;
3917 pSMB->hdr.smb_buf_length += byte_count;
3918 pSMB->ByteCount = cpu_to_le16(byte_count);
3919 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3920 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3923 ("Send error in SetFileInfo (SetFileSize) = %d",
3928 cifs_small_buf_release(pSMB);
3930 /* Note: On -EAGAIN error only caller can retry on handle based calls
3931 since file handle passed in no longer valid */
3936 /* Some legacy servers such as NT4 require that the file times be set on
3937 an open handle, rather than by pathname - this is awkward due to
3938 potential access conflicts on the open, but it is unavoidable for these
3939 old servers since the only other choice is to go from 100 nanosecond DCE
3940 time and resort to the original setpathinfo level which takes the ancient
3941 DOS time format with 2 second granularity */
3943 CIFSSMBSetFileTimes(const int xid, struct cifsTconInfo *tcon, const FILE_BASIC_INFO * data,
3946 struct smb_com_transaction2_sfi_req *pSMB = NULL;
3947 struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
3950 int bytes_returned = 0;
3951 __u16 params, param_offset, offset, byte_count, count;
3953 cFYI(1, ("Set Times (via SetFileInfo)"));
3954 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
3959 pSMBr = (struct smb_com_transaction2_sfi_rsp *)pSMB;
3961 /* At this point there is no need to override the current pid
3962 with the pid of the opener, but that could change if we someday
3963 use an existing handle (rather than opening one on the fly) */
3964 /* pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
3965 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));*/
3968 pSMB->MaxSetupCount = 0;
3972 pSMB->Reserved2 = 0;
3973 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
3974 offset = param_offset + params;
3976 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
3978 count = sizeof (FILE_BASIC_INFO);
3979 pSMB->MaxParameterCount = cpu_to_le16(2);
3980 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB PDU from sess */
3981 pSMB->SetupCount = 1;
3982 pSMB->Reserved3 = 0;
3983 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
3984 byte_count = 3 /* pad */ + params + count;
3985 pSMB->DataCount = cpu_to_le16(count);
3986 pSMB->ParameterCount = cpu_to_le16(params);
3987 pSMB->TotalDataCount = pSMB->DataCount;
3988 pSMB->TotalParameterCount = pSMB->ParameterCount;
3989 pSMB->ParameterOffset = cpu_to_le16(param_offset);
3990 pSMB->DataOffset = cpu_to_le16(offset);
3992 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
3993 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO2);
3995 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO);
3996 pSMB->Reserved4 = 0;
3997 pSMB->hdr.smb_buf_length += byte_count;
3998 pSMB->ByteCount = cpu_to_le16(byte_count);
3999 memcpy(data_offset,data,sizeof(FILE_BASIC_INFO));
4000 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4001 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4003 cFYI(1,("Send error in Set Time (SetFileInfo) = %d",rc));
4006 cifs_small_buf_release(pSMB);
4008 /* Note: On -EAGAIN error only caller can retry on handle based calls
4009 since file handle passed in no longer valid */
4016 CIFSSMBSetTimes(const int xid, struct cifsTconInfo *tcon, const char *fileName,
4017 const FILE_BASIC_INFO * data,
4018 const struct nls_table *nls_codepage, int remap)
4020 TRANSACTION2_SPI_REQ *pSMB = NULL;
4021 TRANSACTION2_SPI_RSP *pSMBr = NULL;
4024 int bytes_returned = 0;
4026 __u16 params, param_offset, offset, byte_count, count;
4028 cFYI(1, ("In SetTimes"));
4031 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4036 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4038 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
4039 PATH_MAX, nls_codepage, remap);
4040 name_len++; /* trailing null */
4042 } else { /* BB improve the check for buffer overruns BB */
4043 name_len = strnlen(fileName, PATH_MAX);
4044 name_len++; /* trailing null */
4045 strncpy(pSMB->FileName, fileName, name_len);
4048 params = 6 + name_len;
4049 count = sizeof (FILE_BASIC_INFO);
4050 pSMB->MaxParameterCount = cpu_to_le16(2);
4051 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
4052 pSMB->MaxSetupCount = 0;
4056 pSMB->Reserved2 = 0;
4057 param_offset = offsetof(struct smb_com_transaction2_spi_req,
4058 InformationLevel) - 4;
4059 offset = param_offset + params;
4060 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
4061 pSMB->ParameterOffset = cpu_to_le16(param_offset);
4062 pSMB->DataOffset = cpu_to_le16(offset);
4063 pSMB->SetupCount = 1;
4064 pSMB->Reserved3 = 0;
4065 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
4066 byte_count = 3 /* pad */ + params + count;
4068 pSMB->DataCount = cpu_to_le16(count);
4069 pSMB->ParameterCount = cpu_to_le16(params);
4070 pSMB->TotalDataCount = pSMB->DataCount;
4071 pSMB->TotalParameterCount = pSMB->ParameterCount;
4072 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
4073 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO2);
4075 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO);
4076 pSMB->Reserved4 = 0;
4077 pSMB->hdr.smb_buf_length += byte_count;
4078 memcpy(data_offset, data, sizeof (FILE_BASIC_INFO));
4079 pSMB->ByteCount = cpu_to_le16(byte_count);
4080 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4081 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4083 cFYI(1, ("SetPathInfo (times) returned %d", rc));
4086 cifs_buf_release(pSMB);
4094 /* Can not be used to set time stamps yet (due to old DOS time format) */
4095 /* Can be used to set attributes */
4096 #if 0 /* Possibly not needed - since it turns out that strangely NT4 has a bug
4097 handling it anyway and NT4 was what we thought it would be needed for
4098 Do not delete it until we prove whether needed for Win9x though */
4100 CIFSSMBSetAttrLegacy(int xid, struct cifsTconInfo *tcon, char *fileName,
4101 __u16 dos_attrs, const struct nls_table *nls_codepage)
4103 SETATTR_REQ *pSMB = NULL;
4104 SETATTR_RSP *pSMBr = NULL;
4109 cFYI(1, ("In SetAttrLegacy"));
4112 rc = smb_init(SMB_COM_SETATTR, 8, tcon, (void **) &pSMB,
4117 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4119 ConvertToUCS((__le16 *) pSMB->fileName, fileName,
4120 PATH_MAX, nls_codepage);
4121 name_len++; /* trailing null */
4123 } else { /* BB improve the check for buffer overruns BB */
4124 name_len = strnlen(fileName, PATH_MAX);
4125 name_len++; /* trailing null */
4126 strncpy(pSMB->fileName, fileName, name_len);
4128 pSMB->attr = cpu_to_le16(dos_attrs);
4129 pSMB->BufferFormat = 0x04;
4130 pSMB->hdr.smb_buf_length += name_len + 1;
4131 pSMB->ByteCount = cpu_to_le16(name_len + 1);
4132 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4133 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4135 cFYI(1, ("Error in LegacySetAttr = %d", rc));
4138 cifs_buf_release(pSMB);
4141 goto SetAttrLgcyRetry;
4145 #endif /* temporarily unneeded SetAttr legacy function */
4148 CIFSSMBUnixSetPerms(const int xid, struct cifsTconInfo *tcon,
4149 char *fileName, __u64 mode, __u64 uid, __u64 gid,
4150 dev_t device, const struct nls_table *nls_codepage,
4153 TRANSACTION2_SPI_REQ *pSMB = NULL;
4154 TRANSACTION2_SPI_RSP *pSMBr = NULL;
4157 int bytes_returned = 0;
4158 FILE_UNIX_BASIC_INFO *data_offset;
4159 __u16 params, param_offset, offset, count, byte_count;
4161 cFYI(1, ("In SetUID/GID/Mode"));
4163 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4168 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4170 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
4171 PATH_MAX, nls_codepage, remap);
4172 name_len++; /* trailing null */
4174 } else { /* BB improve the check for buffer overruns BB */
4175 name_len = strnlen(fileName, PATH_MAX);
4176 name_len++; /* trailing null */
4177 strncpy(pSMB->FileName, fileName, name_len);
4180 params = 6 + name_len;
4181 count = sizeof (FILE_UNIX_BASIC_INFO);
4182 pSMB->MaxParameterCount = cpu_to_le16(2);
4183 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
4184 pSMB->MaxSetupCount = 0;
4188 pSMB->Reserved2 = 0;
4189 param_offset = offsetof(struct smb_com_transaction2_spi_req,
4190 InformationLevel) - 4;
4191 offset = param_offset + params;
4193 (FILE_UNIX_BASIC_INFO *) ((char *) &pSMB->hdr.Protocol +
4195 memset(data_offset, 0, count);
4196 pSMB->DataOffset = cpu_to_le16(offset);
4197 pSMB->ParameterOffset = cpu_to_le16(param_offset);
4198 pSMB->SetupCount = 1;
4199 pSMB->Reserved3 = 0;
4200 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
4201 byte_count = 3 /* pad */ + params + count;
4202 pSMB->ParameterCount = cpu_to_le16(params);
4203 pSMB->DataCount = cpu_to_le16(count);
4204 pSMB->TotalParameterCount = pSMB->ParameterCount;
4205 pSMB->TotalDataCount = pSMB->DataCount;
4206 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_BASIC);
4207 pSMB->Reserved4 = 0;
4208 pSMB->hdr.smb_buf_length += byte_count;
4209 data_offset->Uid = cpu_to_le64(uid);
4210 data_offset->Gid = cpu_to_le64(gid);
4211 /* better to leave device as zero when it is */
4212 data_offset->DevMajor = cpu_to_le64(MAJOR(device));
4213 data_offset->DevMinor = cpu_to_le64(MINOR(device));
4214 data_offset->Permissions = cpu_to_le64(mode);
4217 data_offset->Type = cpu_to_le32(UNIX_FILE);
4218 else if(S_ISDIR(mode))
4219 data_offset->Type = cpu_to_le32(UNIX_DIR);
4220 else if(S_ISLNK(mode))
4221 data_offset->Type = cpu_to_le32(UNIX_SYMLINK);
4222 else if(S_ISCHR(mode))
4223 data_offset->Type = cpu_to_le32(UNIX_CHARDEV);
4224 else if(S_ISBLK(mode))
4225 data_offset->Type = cpu_to_le32(UNIX_BLOCKDEV);
4226 else if(S_ISFIFO(mode))
4227 data_offset->Type = cpu_to_le32(UNIX_FIFO);
4228 else if(S_ISSOCK(mode))
4229 data_offset->Type = cpu_to_le32(UNIX_SOCKET);
4232 pSMB->ByteCount = cpu_to_le16(byte_count);
4233 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4234 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4236 cFYI(1, ("SetPathInfo (perms) returned %d", rc));
4240 cifs_buf_release(pSMB);
4246 int CIFSSMBNotify(const int xid, struct cifsTconInfo *tcon,
4247 const int notify_subdirs, const __u16 netfid,
4248 __u32 filter, struct file * pfile, int multishot,
4249 const struct nls_table *nls_codepage)
4252 struct smb_com_transaction_change_notify_req * pSMB = NULL;
4253 struct smb_com_transaction_change_notify_rsp * pSMBr = NULL;
4254 struct dir_notify_req *dnotify_req;
4257 cFYI(1, ("In CIFSSMBNotify for file handle %d",(int)netfid));
4258 rc = smb_init(SMB_COM_NT_TRANSACT, 23, tcon, (void **) &pSMB,
4263 pSMB->TotalParameterCount = 0 ;
4264 pSMB->TotalDataCount = 0;
4265 pSMB->MaxParameterCount = cpu_to_le32(2);
4266 /* BB find exact data count max from sess structure BB */
4267 pSMB->MaxDataCount = 0; /* same in little endian or be */
4268 pSMB->MaxSetupCount = 4;
4270 pSMB->ParameterOffset = 0;
4271 pSMB->DataCount = 0;
4272 pSMB->DataOffset = 0;
4273 pSMB->SetupCount = 4; /* single byte does not need le conversion */
4274 pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_NOTIFY_CHANGE);
4275 pSMB->ParameterCount = pSMB->TotalParameterCount;
4277 pSMB->WatchTree = 1; /* one byte - no le conversion needed */
4278 pSMB->Reserved2 = 0;
4279 pSMB->CompletionFilter = cpu_to_le32(filter);
4280 pSMB->Fid = netfid; /* file handle always le */
4281 pSMB->ByteCount = 0;
4283 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4284 (struct smb_hdr *) pSMBr, &bytes_returned, -1);
4286 cFYI(1, ("Error in Notify = %d", rc));
4288 /* Add file to outstanding requests */
4289 dnotify_req = (struct dir_notify_req *) kmalloc(
4290 sizeof(struct dir_notify_req), GFP_KERNEL);
4291 dnotify_req->Pid = pSMB->hdr.Pid;
4292 dnotify_req->PidHigh = pSMB->hdr.PidHigh;
4293 dnotify_req->Mid = pSMB->hdr.Mid;
4294 dnotify_req->Tid = pSMB->hdr.Tid;
4295 dnotify_req->Uid = pSMB->hdr.Uid;
4296 dnotify_req->netfid = netfid;
4297 dnotify_req->pfile = pfile;
4298 dnotify_req->filter = filter;
4299 dnotify_req->multishot = multishot;
4300 spin_lock(&GlobalMid_Lock);
4301 list_add_tail(&dnotify_req->lhead, &GlobalDnotifyReqList);
4302 spin_unlock(&GlobalMid_Lock);
4304 cifs_buf_release(pSMB);
4307 #ifdef CONFIG_CIFS_XATTR
4309 CIFSSMBQAllEAs(const int xid, struct cifsTconInfo *tcon,
4310 const unsigned char *searchName,
4311 char * EAData, size_t buf_size,
4312 const struct nls_table *nls_codepage, int remap)
4314 /* BB assumes one setup word */
4315 TRANSACTION2_QPI_REQ *pSMB = NULL;
4316 TRANSACTION2_QPI_RSP *pSMBr = NULL;
4320 struct fea * temp_fea;
4322 __u16 params, byte_count;
4324 cFYI(1, ("In Query All EAs path %s", searchName));
4326 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4331 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4333 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
4334 PATH_MAX, nls_codepage, remap);
4335 name_len++; /* trailing null */
4337 } else { /* BB improve the check for buffer overruns BB */
4338 name_len = strnlen(searchName, PATH_MAX);
4339 name_len++; /* trailing null */
4340 strncpy(pSMB->FileName, searchName, name_len);
4343 params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */ ;
4344 pSMB->TotalDataCount = 0;
4345 pSMB->MaxParameterCount = cpu_to_le16(2);
4346 pSMB->MaxDataCount = cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
4347 pSMB->MaxSetupCount = 0;
4351 pSMB->Reserved2 = 0;
4352 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4353 struct smb_com_transaction2_qpi_req ,InformationLevel) - 4);
4354 pSMB->DataCount = 0;
4355 pSMB->DataOffset = 0;
4356 pSMB->SetupCount = 1;
4357 pSMB->Reserved3 = 0;
4358 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
4359 byte_count = params + 1 /* pad */ ;
4360 pSMB->TotalParameterCount = cpu_to_le16(params);
4361 pSMB->ParameterCount = pSMB->TotalParameterCount;
4362 pSMB->InformationLevel = cpu_to_le16(SMB_INFO_QUERY_ALL_EAS);
4363 pSMB->Reserved4 = 0;
4364 pSMB->hdr.smb_buf_length += byte_count;
4365 pSMB->ByteCount = cpu_to_le16(byte_count);
4367 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4368 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4370 cFYI(1, ("Send error in QueryAllEAs = %d", rc));
4371 } else { /* decode response */
4372 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4374 /* BB also check enough total bytes returned */
4375 /* BB we need to improve the validity checking
4376 of these trans2 responses */
4377 if (rc || (pSMBr->ByteCount < 4))
4378 rc = -EIO; /* bad smb */
4379 /* else if (pFindData){
4380 memcpy((char *) pFindData,
4381 (char *) &pSMBr->hdr.Protocol +
4384 /* check that length of list is not more than bcc */
4385 /* check that each entry does not go beyond length
4387 /* check that each element of each entry does not
4388 go beyond end of list */
4389 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4390 struct fealist * ea_response_data;
4392 /* validate_trans2_offsets() */
4393 /* BB to check if(start of smb + data_offset > &bcc+ bcc)*/
4394 ea_response_data = (struct fealist *)
4395 (((char *) &pSMBr->hdr.Protocol) +
4397 name_len = le32_to_cpu(ea_response_data->list_len);
4398 cFYI(1,("ea length %d", name_len));
4400 /* returned EA size zeroed at top of function */
4401 cFYI(1,("empty EA list returned from server"));
4403 /* account for ea list len */
4405 temp_fea = ea_response_data->list;
4406 temp_ptr = (char *)temp_fea;
4407 while(name_len > 0) {
4411 rc += temp_fea->name_len;
4412 /* account for prefix user. and trailing null */
4414 if(rc<(int)buf_size) {
4415 memcpy(EAData,"user.",5);
4417 memcpy(EAData,temp_ptr,temp_fea->name_len);
4418 EAData+=temp_fea->name_len;
4419 /* null terminate name */
4421 EAData = EAData + 1;
4422 } else if(buf_size == 0) {
4423 /* skip copy - calc size only */
4425 /* stop before overrun buffer */
4429 name_len -= temp_fea->name_len;
4430 temp_ptr += temp_fea->name_len;
4431 /* account for trailing null */
4434 value_len = le16_to_cpu(temp_fea->value_len);
4435 name_len -= value_len;
4436 temp_ptr += value_len;
4437 /* BB check that temp_ptr is still within smb BB*/
4438 /* no trailing null to account for in value len */
4439 /* go on to next EA */
4440 temp_fea = (struct fea *)temp_ptr;
4446 cifs_buf_release(pSMB);
4453 ssize_t CIFSSMBQueryEA(const int xid,struct cifsTconInfo * tcon,
4454 const unsigned char * searchName,const unsigned char * ea_name,
4455 unsigned char * ea_value, size_t buf_size,
4456 const struct nls_table *nls_codepage, int remap)
4458 TRANSACTION2_QPI_REQ *pSMB = NULL;
4459 TRANSACTION2_QPI_RSP *pSMBr = NULL;
4463 struct fea * temp_fea;
4465 __u16 params, byte_count;
4467 cFYI(1, ("In Query EA path %s", searchName));
4469 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4474 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4476 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
4477 PATH_MAX, nls_codepage, remap);
4478 name_len++; /* trailing null */
4480 } else { /* BB improve the check for buffer overruns BB */
4481 name_len = strnlen(searchName, PATH_MAX);
4482 name_len++; /* trailing null */
4483 strncpy(pSMB->FileName, searchName, name_len);
4486 params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */ ;
4487 pSMB->TotalDataCount = 0;
4488 pSMB->MaxParameterCount = cpu_to_le16(2);
4489 pSMB->MaxDataCount = cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
4490 pSMB->MaxSetupCount = 0;
4494 pSMB->Reserved2 = 0;
4495 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4496 struct smb_com_transaction2_qpi_req ,InformationLevel) - 4);
4497 pSMB->DataCount = 0;
4498 pSMB->DataOffset = 0;
4499 pSMB->SetupCount = 1;
4500 pSMB->Reserved3 = 0;
4501 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
4502 byte_count = params + 1 /* pad */ ;
4503 pSMB->TotalParameterCount = cpu_to_le16(params);
4504 pSMB->ParameterCount = pSMB->TotalParameterCount;
4505 pSMB->InformationLevel = cpu_to_le16(SMB_INFO_QUERY_ALL_EAS);
4506 pSMB->Reserved4 = 0;
4507 pSMB->hdr.smb_buf_length += byte_count;
4508 pSMB->ByteCount = cpu_to_le16(byte_count);
4510 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4511 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4513 cFYI(1, ("Send error in Query EA = %d", rc));
4514 } else { /* decode response */
4515 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4517 /* BB also check enough total bytes returned */
4518 /* BB we need to improve the validity checking
4519 of these trans2 responses */
4520 if (rc || (pSMBr->ByteCount < 4))
4521 rc = -EIO; /* bad smb */
4522 /* else if (pFindData){
4523 memcpy((char *) pFindData,
4524 (char *) &pSMBr->hdr.Protocol +
4527 /* check that length of list is not more than bcc */
4528 /* check that each entry does not go beyond length
4530 /* check that each element of each entry does not
4531 go beyond end of list */
4532 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4533 struct fealist * ea_response_data;
4535 /* validate_trans2_offsets() */
4536 /* BB to check if(start of smb + data_offset > &bcc+ bcc)*/
4537 ea_response_data = (struct fealist *)
4538 (((char *) &pSMBr->hdr.Protocol) +
4540 name_len = le32_to_cpu(ea_response_data->list_len);
4541 cFYI(1,("ea length %d", name_len));
4543 /* returned EA size zeroed at top of function */
4544 cFYI(1,("empty EA list returned from server"));
4546 /* account for ea list len */
4548 temp_fea = ea_response_data->list;
4549 temp_ptr = (char *)temp_fea;
4550 /* loop through checking if we have a matching
4551 name and then return the associated value */
4552 while(name_len > 0) {
4556 value_len = le16_to_cpu(temp_fea->value_len);
4557 /* BB validate that value_len falls within SMB,
4558 even though maximum for name_len is 255 */
4559 if(memcmp(temp_fea->name,ea_name,
4560 temp_fea->name_len) == 0) {
4563 /* account for prefix user. and trailing null */
4564 if(rc<=(int)buf_size) {
4566 temp_fea->name+temp_fea->name_len+1,
4568 /* ea values, unlike ea names,
4569 are not null terminated */
4570 } else if(buf_size == 0) {
4571 /* skip copy - calc size only */
4573 /* stop before overrun buffer */
4578 name_len -= temp_fea->name_len;
4579 temp_ptr += temp_fea->name_len;
4580 /* account for trailing null */
4583 name_len -= value_len;
4584 temp_ptr += value_len;
4585 /* no trailing null to account for in value len */
4586 /* go on to next EA */
4587 temp_fea = (struct fea *)temp_ptr;
4593 cifs_buf_release(pSMB);
4601 CIFSSMBSetEA(const int xid, struct cifsTconInfo *tcon, const char *fileName,
4602 const char * ea_name, const void * ea_value,
4603 const __u16 ea_value_len, const struct nls_table *nls_codepage,
4606 struct smb_com_transaction2_spi_req *pSMB = NULL;
4607 struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
4608 struct fealist *parm_data;
4611 int bytes_returned = 0;
4612 __u16 params, param_offset, byte_count, offset, count;
4614 cFYI(1, ("In SetEA"));
4616 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4621 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4623 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
4624 PATH_MAX, nls_codepage, remap);
4625 name_len++; /* trailing null */
4627 } else { /* BB improve the check for buffer overruns BB */
4628 name_len = strnlen(fileName, PATH_MAX);
4629 name_len++; /* trailing null */
4630 strncpy(pSMB->FileName, fileName, name_len);
4633 params = 6 + name_len;
4635 /* done calculating parms using name_len of file name,
4636 now use name_len to calculate length of ea name
4637 we are going to create in the inode xattrs */
4641 name_len = strnlen(ea_name,255);
4643 count = sizeof(*parm_data) + ea_value_len + name_len + 1;
4644 pSMB->MaxParameterCount = cpu_to_le16(2);
4645 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB size from sess */
4646 pSMB->MaxSetupCount = 0;
4650 pSMB->Reserved2 = 0;
4651 param_offset = offsetof(struct smb_com_transaction2_spi_req,
4652 InformationLevel) - 4;
4653 offset = param_offset + params;
4654 pSMB->InformationLevel =
4655 cpu_to_le16(SMB_SET_FILE_EA);
4658 (struct fealist *) (((char *) &pSMB->hdr.Protocol) +
4660 pSMB->ParameterOffset = cpu_to_le16(param_offset);
4661 pSMB->DataOffset = cpu_to_le16(offset);
4662 pSMB->SetupCount = 1;
4663 pSMB->Reserved3 = 0;
4664 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
4665 byte_count = 3 /* pad */ + params + count;
4666 pSMB->DataCount = cpu_to_le16(count);
4667 parm_data->list_len = cpu_to_le32(count);
4668 parm_data->list[0].EA_flags = 0;
4669 /* we checked above that name len is less than 255 */
4670 parm_data->list[0].name_len = (__u8)name_len;;
4671 /* EA names are always ASCII */
4673 strncpy(parm_data->list[0].name,ea_name,name_len);
4674 parm_data->list[0].name[name_len] = 0;
4675 parm_data->list[0].value_len = cpu_to_le16(ea_value_len);
4676 /* caller ensures that ea_value_len is less than 64K but
4677 we need to ensure that it fits within the smb */
4679 /*BB add length check that it would fit in negotiated SMB buffer size BB */
4680 /* if(ea_value_len > buffer_size - 512 (enough for header)) */
4682 memcpy(parm_data->list[0].name+name_len+1,ea_value,ea_value_len);
4684 pSMB->TotalDataCount = pSMB->DataCount;
4685 pSMB->ParameterCount = cpu_to_le16(params);
4686 pSMB->TotalParameterCount = pSMB->ParameterCount;
4687 pSMB->Reserved4 = 0;
4688 pSMB->hdr.smb_buf_length += byte_count;
4689 pSMB->ByteCount = cpu_to_le16(byte_count);
4690 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4691 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4693 cFYI(1, ("SetPathInfo (EA) returned %d", rc));
4696 cifs_buf_release(pSMB);