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->tidStatus == CifsExiting) {
94 /* only tree disconnect, open, and write,
95 (and ulogoff which does not have tcon)
96 are allowed as we start force umount */
97 if((smb_command != SMB_COM_WRITE_ANDX) &&
98 (smb_command != SMB_COM_OPEN_ANDX) &&
99 (smb_command != SMB_COM_TREE_DISCONNECT)) {
100 cFYI(1,("can not send cmd %d while umounting",
105 if((tcon->ses) && (tcon->ses->status != CifsExiting) &&
106 (tcon->ses->server)){
107 struct nls_table *nls_codepage;
108 /* Give Demultiplex thread up to 10 seconds to
109 reconnect, should be greater than cifs socket
110 timeout which is 7 seconds */
111 while(tcon->ses->server->tcpStatus == CifsNeedReconnect) {
112 wait_event_interruptible_timeout(tcon->ses->server->response_q,
113 (tcon->ses->server->tcpStatus == CifsGood), 10 * HZ);
114 if(tcon->ses->server->tcpStatus == CifsNeedReconnect) {
115 /* on "soft" mounts we wait once */
116 if((tcon->retry == FALSE) ||
117 (tcon->ses->status == CifsExiting)) {
118 cFYI(1,("gave up waiting on reconnect in smb_init"));
120 } /* else "hard" mount - keep retrying
121 until process is killed or server
122 comes back on-line */
123 } else /* TCP session is reestablished now */
128 nls_codepage = load_nls_default();
129 /* need to prevent multiple threads trying to
130 simultaneously reconnect the same SMB session */
131 down(&tcon->ses->sesSem);
132 if(tcon->ses->status == CifsNeedReconnect)
133 rc = cifs_setup_session(0, tcon->ses,
135 if(!rc && (tcon->tidStatus == CifsNeedReconnect)) {
136 mark_open_files_invalid(tcon);
137 rc = CIFSTCon(0, tcon->ses, tcon->treeName, tcon
139 up(&tcon->ses->sesSem);
140 /* BB FIXME add code to check if wsize needs
141 update due to negotiated smb buffer size
144 atomic_inc(&tconInfoReconnectCount);
146 cFYI(1, ("reconnect tcon rc = %d", rc));
147 /* Removed call to reopen open files here -
148 it is safer (and faster) to reopen files
149 one at a time as needed in read and write */
151 /* Check if handle based operation so we
152 know whether we can continue or not without
153 returning to caller to reset file handle */
154 switch(smb_command) {
155 case SMB_COM_READ_ANDX:
156 case SMB_COM_WRITE_ANDX:
158 case SMB_COM_FIND_CLOSE2:
159 case SMB_COM_LOCKING_ANDX: {
160 unload_nls(nls_codepage);
165 up(&tcon->ses->sesSem);
167 unload_nls(nls_codepage);
176 *request_buf = cifs_small_buf_get();
177 if (*request_buf == NULL) {
178 /* BB should we add a retry in here if not a writepage? */
182 header_assemble((struct smb_hdr *) *request_buf, smb_command, tcon,wct);
185 cifs_stats_inc(&tcon->num_smbs_sent);
190 /* If the return code is zero, this function must fill in request_buf pointer */
192 smb_init(int smb_command, int wct, struct cifsTconInfo *tcon,
193 void **request_buf /* returned */ ,
194 void **response_buf /* returned */ )
198 /* SMBs NegProt, SessSetup, uLogoff do not have tcon yet so
199 check for tcp and smb session status done differently
200 for those three - in the calling routine */
202 if(tcon->tidStatus == CifsExiting) {
203 /* only tree disconnect, open, and write,
204 (and ulogoff which does not have tcon)
205 are allowed as we start force umount */
206 if((smb_command != SMB_COM_WRITE_ANDX) &&
207 (smb_command != SMB_COM_OPEN_ANDX) &&
208 (smb_command != SMB_COM_TREE_DISCONNECT)) {
209 cFYI(1,("can not send cmd %d while umounting",
215 if((tcon->ses) && (tcon->ses->status != CifsExiting) &&
216 (tcon->ses->server)){
217 struct nls_table *nls_codepage;
218 /* Give Demultiplex thread up to 10 seconds to
219 reconnect, should be greater than cifs socket
220 timeout which is 7 seconds */
221 while(tcon->ses->server->tcpStatus == CifsNeedReconnect) {
222 wait_event_interruptible_timeout(tcon->ses->server->response_q,
223 (tcon->ses->server->tcpStatus == CifsGood), 10 * HZ);
224 if(tcon->ses->server->tcpStatus ==
226 /* on "soft" mounts we wait once */
227 if((tcon->retry == FALSE) ||
228 (tcon->ses->status == CifsExiting)) {
229 cFYI(1,("gave up waiting on reconnect in smb_init"));
231 } /* else "hard" mount - keep retrying
232 until process is killed or server
234 } else /* TCP session is reestablished now */
239 nls_codepage = load_nls_default();
240 /* need to prevent multiple threads trying to
241 simultaneously reconnect the same SMB session */
242 down(&tcon->ses->sesSem);
243 if(tcon->ses->status == CifsNeedReconnect)
244 rc = cifs_setup_session(0, tcon->ses,
246 if(!rc && (tcon->tidStatus == CifsNeedReconnect)) {
247 mark_open_files_invalid(tcon);
248 rc = CIFSTCon(0, tcon->ses, tcon->treeName,
250 up(&tcon->ses->sesSem);
251 /* BB FIXME add code to check if wsize needs
252 update due to negotiated smb buffer size
255 atomic_inc(&tconInfoReconnectCount);
257 cFYI(1, ("reconnect tcon rc = %d", rc));
258 /* Removed call to reopen open files here -
259 it is safer (and faster) to reopen files
260 one at a time as needed in read and write */
262 /* Check if handle based operation so we
263 know whether we can continue or not without
264 returning to caller to reset file handle */
265 switch(smb_command) {
266 case SMB_COM_READ_ANDX:
267 case SMB_COM_WRITE_ANDX:
269 case SMB_COM_FIND_CLOSE2:
270 case SMB_COM_LOCKING_ANDX: {
271 unload_nls(nls_codepage);
276 up(&tcon->ses->sesSem);
278 unload_nls(nls_codepage);
287 *request_buf = cifs_buf_get();
288 if (*request_buf == NULL) {
289 /* BB should we add a retry in here if not a writepage? */
292 /* Although the original thought was we needed the response buf for */
293 /* potential retries of smb operations it turns out we can determine */
294 /* from the mid flags when the request buffer can be resent without */
295 /* having to use a second distinct buffer for the response */
296 *response_buf = *request_buf;
298 header_assemble((struct smb_hdr *) *request_buf, smb_command, tcon,
302 cifs_stats_inc(&tcon->num_smbs_sent);
307 static int validate_t2(struct smb_t2_rsp * pSMB)
313 /* check for plausible wct, bcc and t2 data and parm sizes */
314 /* check for parm and data offset going beyond end of smb */
315 if(pSMB->hdr.WordCount >= 10) {
316 if((le16_to_cpu(pSMB->t2_rsp.ParameterOffset) <= 1024) &&
317 (le16_to_cpu(pSMB->t2_rsp.DataOffset) <= 1024)) {
318 /* check that bcc is at least as big as parms + data */
319 /* check that bcc is less than negotiated smb buffer */
320 total_size = le16_to_cpu(pSMB->t2_rsp.ParameterCount);
321 if(total_size < 512) {
322 total_size+=le16_to_cpu(pSMB->t2_rsp.DataCount);
323 /* BCC le converted in SendReceive */
324 pBCC = (pSMB->hdr.WordCount * 2) +
325 sizeof(struct smb_hdr) +
327 if((total_size <= (*(u16 *)pBCC)) &&
329 CIFSMaxBufSize+MAX_CIFS_HDR_SIZE)) {
336 cifs_dump_mem("Invalid transact2 SMB: ",(char *)pSMB,
337 sizeof(struct smb_t2_rsp) + 16);
341 CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses)
344 NEGOTIATE_RSP *pSMBr;
347 struct TCP_Server_Info * server;
351 server = ses->server;
356 rc = smb_init(SMB_COM_NEGOTIATE, 0, NULL /* no tcon yet */ ,
357 (void **) &pSMB, (void **) &pSMBr);
360 pSMB->hdr.Mid = GetNextMid(server);
361 pSMB->hdr.Flags2 |= SMBFLG2_UNICODE;
362 if (extended_security)
363 pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC;
365 count = strlen(protocols[0].name) + 1;
366 strncpy(pSMB->DialectsArray, protocols[0].name, 30);
367 /* null guaranteed to be at end of source and target buffers anyway */
369 pSMB->hdr.smb_buf_length += count;
370 pSMB->ByteCount = cpu_to_le16(count);
372 rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB,
373 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
375 server->secMode = pSMBr->SecurityMode;
376 server->secType = NTLM; /* BB override default for
377 NTLMv2 or kerberos v5 */
378 /* one byte - no need to convert this or EncryptionKeyLen
379 from little endian */
380 server->maxReq = le16_to_cpu(pSMBr->MaxMpxCount);
381 /* probably no need to store and check maxvcs */
383 min(le32_to_cpu(pSMBr->MaxBufferSize),
384 (__u32) CIFSMaxBufSize + MAX_CIFS_HDR_SIZE);
385 server->maxRw = le32_to_cpu(pSMBr->MaxRawSize);
386 cFYI(0, ("Max buf = %d ", ses->server->maxBuf));
387 GETU32(ses->server->sessid) = le32_to_cpu(pSMBr->SessionKey);
388 server->capabilities = le32_to_cpu(pSMBr->Capabilities);
389 server->timeZone = le16_to_cpu(pSMBr->ServerTimeZone);
390 /* BB with UTC do we ever need to be using srvr timezone? */
391 if (pSMBr->EncryptionKeyLength == CIFS_CRYPTO_KEY_SIZE) {
392 memcpy(server->cryptKey, pSMBr->u.EncryptionKey,
393 CIFS_CRYPTO_KEY_SIZE);
394 } else if ((pSMBr->hdr.Flags2 & SMBFLG2_EXT_SEC)
395 && (pSMBr->EncryptionKeyLength == 0)) {
396 /* decode security blob */
400 /* BB might be helpful to save off the domain of server here */
402 if ((pSMBr->hdr.Flags2 & SMBFLG2_EXT_SEC) &&
403 (server->capabilities & CAP_EXTENDED_SECURITY)) {
404 count = pSMBr->ByteCount;
407 else if (count == 16) {
408 server->secType = RawNTLMSSP;
409 if (server->socketUseCount.counter > 1) {
411 (server->server_GUID,
412 pSMBr->u.extended_response.
415 ("UID of server does not match previous connection to same ip address"));
423 memcpy(server->server_GUID,
424 pSMBr->u.extended_response.
427 rc = decode_negTokenInit(pSMBr->u.
433 /* BB Need to fill struct for sessetup here */
440 server->capabilities &= ~CAP_EXTENDED_SECURITY;
441 if(sign_CIFS_PDUs == FALSE) {
442 if(server->secMode & SECMODE_SIGN_REQUIRED)
444 ("Server requires /proc/fs/cifs/PacketSigningEnabled"));
445 server->secMode &= ~(SECMODE_SIGN_ENABLED | SECMODE_SIGN_REQUIRED);
446 } else if(sign_CIFS_PDUs == 1) {
447 if((server->secMode & SECMODE_SIGN_REQUIRED) == 0)
448 server->secMode &= ~(SECMODE_SIGN_ENABLED | SECMODE_SIGN_REQUIRED);
453 cifs_buf_release(pSMB);
458 CIFSSMBTDis(const int xid, struct cifsTconInfo *tcon)
460 struct smb_hdr *smb_buffer;
461 struct smb_hdr *smb_buffer_response; /* BB removeme BB */
465 cFYI(1, ("In tree disconnect"));
467 * If last user of the connection and
468 * connection alive - disconnect it
469 * If this is the last connection on the server session disconnect it
470 * (and inside session disconnect we should check if tcp socket needs
471 * to be freed and kernel thread woken up).
474 down(&tcon->tconSem);
478 atomic_dec(&tcon->useCount);
479 if (atomic_read(&tcon->useCount) > 0) {
484 /* No need to return error on this operation if tid invalidated and
485 closed on server already e.g. due to tcp session crashing */
486 if(tcon->tidStatus == CifsNeedReconnect) {
491 if((tcon->ses == NULL) || (tcon->ses->server == NULL)) {
495 rc = small_smb_init(SMB_COM_TREE_DISCONNECT, 0, tcon,
496 (void **)&smb_buffer);
501 smb_buffer_response = smb_buffer; /* BB removeme BB */
503 rc = SendReceive(xid, tcon->ses, smb_buffer, smb_buffer_response,
506 cFYI(1, ("Tree disconnect failed %d", rc));
509 cifs_small_buf_release(smb_buffer);
512 /* No need to return error on this operation if tid invalidated and
513 closed on server already e.g. due to tcp session crashing */
521 CIFSSMBLogoff(const int xid, struct cifsSesInfo *ses)
523 struct smb_hdr *smb_buffer_response;
524 LOGOFF_ANDX_REQ *pSMB;
528 cFYI(1, ("In SMBLogoff for session disconnect"));
534 atomic_dec(&ses->inUse);
535 if (atomic_read(&ses->inUse) > 0) {
539 rc = small_smb_init(SMB_COM_LOGOFF_ANDX, 2, NULL, (void **)&pSMB);
545 smb_buffer_response = (struct smb_hdr *)pSMB; /* BB removeme BB */
548 pSMB->hdr.Mid = GetNextMid(ses->server);
550 if(ses->server->secMode &
551 (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
552 pSMB->hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
555 pSMB->hdr.Uid = ses->Suid;
557 pSMB->AndXCommand = 0xFF;
558 rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB,
559 smb_buffer_response, &length, 0);
561 atomic_dec(&ses->server->socketUseCount);
562 if (atomic_read(&ses->server->socketUseCount) == 0) {
563 spin_lock(&GlobalMid_Lock);
564 ses->server->tcpStatus = CifsExiting;
565 spin_unlock(&GlobalMid_Lock);
570 cifs_small_buf_release(pSMB);
572 /* if session dead then we do not need to do ulogoff,
573 since server closed smb session, no sense reporting
581 CIFSSMBDelFile(const int xid, struct cifsTconInfo *tcon, const char *fileName,
582 const struct nls_table *nls_codepage, int remap)
584 DELETE_FILE_REQ *pSMB = NULL;
585 DELETE_FILE_RSP *pSMBr = NULL;
591 rc = smb_init(SMB_COM_DELETE, 1, tcon, (void **) &pSMB,
596 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
598 cifsConvertToUCS((__le16 *) pSMB->fileName, fileName,
599 PATH_MAX, nls_codepage, remap);
600 name_len++; /* trailing null */
602 } else { /* BB improve check for buffer overruns BB */
603 name_len = strnlen(fileName, PATH_MAX);
604 name_len++; /* trailing null */
605 strncpy(pSMB->fileName, fileName, name_len);
607 pSMB->SearchAttributes =
608 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM);
609 pSMB->BufferFormat = 0x04;
610 pSMB->hdr.smb_buf_length += name_len + 1;
611 pSMB->ByteCount = cpu_to_le16(name_len + 1);
612 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
613 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
614 cifs_stats_inc(&tcon->num_deletes);
616 cFYI(1, ("Error in RMFile = %d", rc));
619 cifs_buf_release(pSMB);
627 CIFSSMBRmDir(const int xid, struct cifsTconInfo *tcon, const char *dirName,
628 const struct nls_table *nls_codepage, int remap)
630 DELETE_DIRECTORY_REQ *pSMB = NULL;
631 DELETE_DIRECTORY_RSP *pSMBr = NULL;
636 cFYI(1, ("In CIFSSMBRmDir"));
638 rc = smb_init(SMB_COM_DELETE_DIRECTORY, 0, tcon, (void **) &pSMB,
643 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
644 name_len = cifsConvertToUCS((__le16 *) pSMB->DirName, dirName,
645 PATH_MAX, nls_codepage, remap);
646 name_len++; /* trailing null */
648 } else { /* BB improve check for buffer overruns BB */
649 name_len = strnlen(dirName, PATH_MAX);
650 name_len++; /* trailing null */
651 strncpy(pSMB->DirName, dirName, name_len);
654 pSMB->BufferFormat = 0x04;
655 pSMB->hdr.smb_buf_length += name_len + 1;
656 pSMB->ByteCount = cpu_to_le16(name_len + 1);
657 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
658 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
659 cifs_stats_inc(&tcon->num_rmdirs);
661 cFYI(1, ("Error in RMDir = %d", rc));
664 cifs_buf_release(pSMB);
671 CIFSSMBMkDir(const int xid, struct cifsTconInfo *tcon,
672 const char *name, const struct nls_table *nls_codepage, int remap)
675 CREATE_DIRECTORY_REQ *pSMB = NULL;
676 CREATE_DIRECTORY_RSP *pSMBr = NULL;
680 cFYI(1, ("In CIFSSMBMkDir"));
682 rc = smb_init(SMB_COM_CREATE_DIRECTORY, 0, tcon, (void **) &pSMB,
687 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
688 name_len = cifsConvertToUCS((__le16 *) pSMB->DirName, name,
689 PATH_MAX, nls_codepage, remap);
690 name_len++; /* trailing null */
692 } else { /* BB improve check for buffer overruns BB */
693 name_len = strnlen(name, PATH_MAX);
694 name_len++; /* trailing null */
695 strncpy(pSMB->DirName, name, name_len);
698 pSMB->BufferFormat = 0x04;
699 pSMB->hdr.smb_buf_length += name_len + 1;
700 pSMB->ByteCount = cpu_to_le16(name_len + 1);
701 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
702 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
703 cifs_stats_inc(&tcon->num_mkdirs);
705 cFYI(1, ("Error in Mkdir = %d", rc));
708 cifs_buf_release(pSMB);
714 static __u16 convert_disposition(int disposition)
718 switch (disposition) {
720 ofun = SMBOPEN_OCREATE | SMBOPEN_OTRUNC;
723 ofun = SMBOPEN_OAPPEND;
726 ofun = SMBOPEN_OCREATE;
729 ofun = SMBOPEN_OCREATE | SMBOPEN_OAPPEND;
732 ofun = SMBOPEN_OTRUNC;
734 case FILE_OVERWRITE_IF:
735 ofun = SMBOPEN_OCREATE | SMBOPEN_OTRUNC;
738 cFYI(1,("unknown disposition %d",disposition));
739 ofun = SMBOPEN_OAPPEND; /* regular open */
745 SMBLegacyOpen(const int xid, struct cifsTconInfo *tcon,
746 const char *fileName, const int openDisposition,
747 const int access_flags, const int create_options, __u16 * netfid,
748 int *pOplock, FILE_ALL_INFO * pfile_info,
749 const struct nls_table *nls_codepage, int remap)
752 OPENX_REQ *pSMB = NULL;
753 OPENX_RSP *pSMBr = NULL;
759 rc = smb_init(SMB_COM_OPEN_ANDX, 15, tcon, (void **) &pSMB,
764 pSMB->AndXCommand = 0xFF; /* none */
766 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
767 count = 1; /* account for one byte pad to word boundary */
769 cifsConvertToUCS((__le16 *) (pSMB->fileName + 1),
770 fileName, PATH_MAX, nls_codepage, remap);
771 name_len++; /* trailing null */
773 } else { /* BB improve check for buffer overruns BB */
774 count = 0; /* no pad */
775 name_len = strnlen(fileName, PATH_MAX);
776 name_len++; /* trailing null */
777 strncpy(pSMB->fileName, fileName, name_len);
779 if (*pOplock & REQ_OPLOCK)
780 pSMB->OpenFlags = cpu_to_le16(REQ_OPLOCK);
781 else if (*pOplock & REQ_BATCHOPLOCK) {
782 pSMB->OpenFlags = cpu_to_le16(REQ_BATCHOPLOCK);
784 pSMB->OpenFlags |= cpu_to_le16(REQ_MORE_INFO);
785 /* BB fixme add conversion for access_flags to bits 0 - 2 of mode */
791 pSMB->Mode = cpu_to_le16(2);
792 pSMB->Mode |= cpu_to_le16(0x40); /* deny none */
793 /* set file as system file if special file such
794 as fifo and server expecting SFU style and
795 no Unix extensions */
797 if(create_options & CREATE_OPTION_SPECIAL)
798 pSMB->FileAttributes = cpu_to_le16(ATTR_SYSTEM);
800 pSMB->FileAttributes = cpu_to_le16(0/*ATTR_NORMAL*/); /* BB FIXME */
802 /* if ((omode & S_IWUGO) == 0)
803 pSMB->FileAttributes |= cpu_to_le32(ATTR_READONLY);*/
804 /* Above line causes problems due to vfs splitting create into two
805 pieces - need to set mode after file created not while it is
809 /* pSMB->CreateOptions = cpu_to_le32(create_options & CREATE_OPTIONS_MASK); */
810 /* BB FIXME END BB */
812 pSMB->Sattr = cpu_to_le16(ATTR_HIDDEN | ATTR_SYSTEM | ATTR_DIRECTORY);
813 pSMB->OpenFunction = cpu_to_le16(convert_disposition(openDisposition));
815 pSMB->hdr.smb_buf_length += count;
817 pSMB->ByteCount = cpu_to_le16(count);
818 /* long_op set to 1 to allow for oplock break timeouts */
819 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
820 (struct smb_hdr *) pSMBr, &bytes_returned, 1);
821 cifs_stats_inc(&tcon->num_opens);
823 cFYI(1, ("Error in Open = %d", rc));
825 /* BB verify if wct == 15 */
827 /* *pOplock = pSMBr->OplockLevel; */ /* BB take from action field BB */
829 *netfid = pSMBr->Fid; /* cifs fid stays in le */
830 /* Let caller know file was created so we can set the mode. */
831 /* Do we care about the CreateAction in any other cases? */
833 /* if(cpu_to_le32(FILE_CREATE) == pSMBr->CreateAction)
834 *pOplock |= CIFS_CREATE_ACTION; */
838 pfile_info->CreationTime = 0; /* BB convert CreateTime*/
839 pfile_info->LastAccessTime = 0; /* BB fixme */
840 pfile_info->LastWriteTime = 0; /* BB fixme */
841 pfile_info->ChangeTime = 0; /* BB fixme */
842 pfile_info->Attributes =
843 cpu_to_le32(le16_to_cpu(pSMBr->FileAttributes));
844 /* the file_info buf is endian converted by caller */
845 pfile_info->AllocationSize =
846 cpu_to_le64(le32_to_cpu(pSMBr->EndOfFile));
847 pfile_info->EndOfFile = pfile_info->AllocationSize;
848 pfile_info->NumberOfLinks = cpu_to_le32(1);
852 cifs_buf_release(pSMB);
859 CIFSSMBOpen(const int xid, struct cifsTconInfo *tcon,
860 const char *fileName, const int openDisposition,
861 const int access_flags, const int create_options, __u16 * netfid,
862 int *pOplock, FILE_ALL_INFO * pfile_info,
863 const struct nls_table *nls_codepage, int remap)
866 OPEN_REQ *pSMB = NULL;
867 OPEN_RSP *pSMBr = NULL;
873 rc = smb_init(SMB_COM_NT_CREATE_ANDX, 24, tcon, (void **) &pSMB,
878 pSMB->AndXCommand = 0xFF; /* none */
880 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
881 count = 1; /* account for one byte pad to word boundary */
883 cifsConvertToUCS((__le16 *) (pSMB->fileName + 1),
884 fileName, PATH_MAX, nls_codepage, remap);
885 name_len++; /* trailing null */
887 pSMB->NameLength = cpu_to_le16(name_len);
888 } else { /* BB improve check for buffer overruns BB */
889 count = 0; /* no pad */
890 name_len = strnlen(fileName, PATH_MAX);
891 name_len++; /* trailing null */
892 pSMB->NameLength = cpu_to_le16(name_len);
893 strncpy(pSMB->fileName, fileName, name_len);
895 if (*pOplock & REQ_OPLOCK)
896 pSMB->OpenFlags = cpu_to_le32(REQ_OPLOCK);
897 else if (*pOplock & REQ_BATCHOPLOCK) {
898 pSMB->OpenFlags = cpu_to_le32(REQ_BATCHOPLOCK);
900 pSMB->DesiredAccess = cpu_to_le32(access_flags);
901 pSMB->AllocationSize = 0;
902 /* set file as system file if special file such
903 as fifo and server expecting SFU style and
904 no Unix extensions */
905 if(create_options & CREATE_OPTION_SPECIAL)
906 pSMB->FileAttributes = cpu_to_le32(ATTR_SYSTEM);
908 pSMB->FileAttributes = cpu_to_le32(ATTR_NORMAL);
909 /* XP does not handle ATTR_POSIX_SEMANTICS */
910 /* but it helps speed up case sensitive checks for other
911 servers such as Samba */
912 if (tcon->ses->capabilities & CAP_UNIX)
913 pSMB->FileAttributes |= cpu_to_le32(ATTR_POSIX_SEMANTICS);
915 /* if ((omode & S_IWUGO) == 0)
916 pSMB->FileAttributes |= cpu_to_le32(ATTR_READONLY);*/
917 /* Above line causes problems due to vfs splitting create into two
918 pieces - need to set mode after file created not while it is
920 pSMB->ShareAccess = cpu_to_le32(FILE_SHARE_ALL);
921 pSMB->CreateDisposition = cpu_to_le32(openDisposition);
922 pSMB->CreateOptions = cpu_to_le32(create_options & CREATE_OPTIONS_MASK);
923 /* BB Expirement with various impersonation levels and verify */
924 pSMB->ImpersonationLevel = cpu_to_le32(SECURITY_IMPERSONATION);
925 pSMB->SecurityFlags =
926 SECURITY_CONTEXT_TRACKING | SECURITY_EFFECTIVE_ONLY;
929 pSMB->hdr.smb_buf_length += count;
931 pSMB->ByteCount = cpu_to_le16(count);
932 /* long_op set to 1 to allow for oplock break timeouts */
933 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
934 (struct smb_hdr *) pSMBr, &bytes_returned, 1);
935 cifs_stats_inc(&tcon->num_opens);
937 cFYI(1, ("Error in Open = %d", rc));
939 *pOplock = pSMBr->OplockLevel; /* 1 byte no need to le_to_cpu */
940 *netfid = pSMBr->Fid; /* cifs fid stays in le */
941 /* Let caller know file was created so we can set the mode. */
942 /* Do we care about the CreateAction in any other cases? */
943 if(cpu_to_le32(FILE_CREATE) == pSMBr->CreateAction)
944 *pOplock |= CIFS_CREATE_ACTION;
946 memcpy((char *)pfile_info,(char *)&pSMBr->CreationTime,
947 36 /* CreationTime to Attributes */);
948 /* the file_info buf is endian converted by caller */
949 pfile_info->AllocationSize = pSMBr->AllocationSize;
950 pfile_info->EndOfFile = pSMBr->EndOfFile;
951 pfile_info->NumberOfLinks = cpu_to_le32(1);
955 cifs_buf_release(pSMB);
962 CIFSSMBRead(const int xid, struct cifsTconInfo *tcon,
963 const int netfid, const unsigned int count,
964 const __u64 lseek, unsigned int *nbytes, char **buf,
968 READ_REQ *pSMB = NULL;
969 READ_RSP *pSMBr = NULL;
970 char *pReadData = NULL;
972 int resp_buf_type = 0;
975 cFYI(1,("Reading %d bytes on fid %d",count,netfid));
976 if(tcon->ses->capabilities & CAP_LARGE_FILES)
979 wct = 10; /* old style read */
982 rc = small_smb_init(SMB_COM_READ_ANDX, wct, tcon, (void **) &pSMB);
986 /* tcon and ses pointer are checked in smb_init */
987 if (tcon->ses->server == NULL)
988 return -ECONNABORTED;
990 pSMB->AndXCommand = 0xFF; /* none */
992 pSMB->OffsetLow = cpu_to_le32(lseek & 0xFFFFFFFF);
994 pSMB->OffsetHigh = cpu_to_le32(lseek >> 32);
995 else if((lseek >> 32) > 0) /* can not handle this big offset for old */
999 pSMB->MaxCount = cpu_to_le16(count & 0xFFFF);
1000 pSMB->MaxCountHigh = cpu_to_le32(count >> 16);
1002 pSMB->ByteCount = 0; /* no need to do le conversion since 0 */
1004 /* old style read */
1005 struct smb_com_readx_req * pSMBW =
1006 (struct smb_com_readx_req *)pSMB;
1007 pSMBW->ByteCount = 0;
1010 iov[0].iov_base = (char *)pSMB;
1011 iov[0].iov_len = pSMB->hdr.smb_buf_length + 4;
1012 rc = SendReceive2(xid, tcon->ses, iov,
1015 cifs_stats_inc(&tcon->num_reads);
1016 pSMBr = (READ_RSP *)iov[0].iov_base;
1018 cERROR(1, ("Send error in read = %d", rc));
1020 int data_length = le16_to_cpu(pSMBr->DataLengthHigh);
1021 data_length = data_length << 16;
1022 data_length += le16_to_cpu(pSMBr->DataLength);
1023 *nbytes = data_length;
1025 /*check that DataLength would not go beyond end of SMB */
1026 if ((data_length > CIFSMaxBufSize)
1027 || (data_length > count)) {
1028 cFYI(1,("bad length %d for count %d",data_length,count));
1032 pReadData = (char *) (&pSMBr->hdr.Protocol) +
1033 le16_to_cpu(pSMBr->DataOffset);
1034 /* if(rc = copy_to_user(buf, pReadData, data_length)) {
1035 cERROR(1,("Faulting on read rc = %d",rc));
1037 }*/ /* can not use copy_to_user when using page cache*/
1039 memcpy(*buf,pReadData,data_length);
1043 cifs_small_buf_release(pSMB);
1045 if(resp_buf_type == CIFS_SMALL_BUFFER)
1046 cifs_small_buf_release(iov[0].iov_base);
1047 else if(resp_buf_type == CIFS_LARGE_BUFFER)
1048 cifs_buf_release(iov[0].iov_base);
1049 } else /* return buffer to caller to free */ /* BB FIXME how do we tell caller if it is not a large buffer */ {
1050 *buf = iov[0].iov_base;
1051 if(resp_buf_type == CIFS_SMALL_BUFFER)
1052 *pbuf_type = CIFS_SMALL_BUFFER;
1053 else if(resp_buf_type == CIFS_LARGE_BUFFER)
1054 *pbuf_type = CIFS_LARGE_BUFFER;
1057 /* Note: On -EAGAIN error only caller can retry on handle based calls
1058 since file handle passed in no longer valid */
1064 CIFSSMBWrite(const int xid, struct cifsTconInfo *tcon,
1065 const int netfid, const unsigned int count,
1066 const __u64 offset, unsigned int *nbytes, const char *buf,
1067 const char __user * ubuf, const int long_op)
1070 WRITE_REQ *pSMB = NULL;
1071 WRITE_RSP *pSMBr = NULL;
1072 int bytes_returned, wct;
1076 /* cFYI(1,("write at %lld %d bytes",offset,count));*/
1077 if(tcon->ses == NULL)
1078 return -ECONNABORTED;
1080 if(tcon->ses->capabilities & CAP_LARGE_FILES)
1085 rc = smb_init(SMB_COM_WRITE_ANDX, wct, tcon, (void **) &pSMB,
1089 /* tcon and ses pointer are checked in smb_init */
1090 if (tcon->ses->server == NULL)
1091 return -ECONNABORTED;
1093 pSMB->AndXCommand = 0xFF; /* none */
1095 pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF);
1097 pSMB->OffsetHigh = cpu_to_le32(offset >> 32);
1098 else if((offset >> 32) > 0) /* can not handle this big offset for old */
1101 pSMB->Reserved = 0xFFFFFFFF;
1102 pSMB->WriteMode = 0;
1103 pSMB->Remaining = 0;
1105 /* Can increase buffer size if buffer is big enough in some cases - ie we
1106 can send more if LARGE_WRITE_X capability returned by the server and if
1107 our buffer is big enough or if we convert to iovecs on socket writes
1108 and eliminate the copy to the CIFS buffer */
1109 if(tcon->ses->capabilities & CAP_LARGE_WRITE_X) {
1110 bytes_sent = min_t(const unsigned int, CIFSMaxBufSize, count);
1112 bytes_sent = (tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE)
1116 if (bytes_sent > count)
1119 cpu_to_le16(offsetof(struct smb_com_write_req,Data) - 4);
1121 memcpy(pSMB->Data,buf,bytes_sent);
1123 if(copy_from_user(pSMB->Data,ubuf,bytes_sent)) {
1124 cifs_buf_release(pSMB);
1127 } else if (count != 0) {
1129 cifs_buf_release(pSMB);
1131 } /* else setting file size with write of zero bytes */
1133 byte_count = bytes_sent + 1; /* pad */
1134 else /* wct == 12 */ {
1135 byte_count = bytes_sent + 5; /* bigger pad, smaller smb hdr */
1137 pSMB->DataLengthLow = cpu_to_le16(bytes_sent & 0xFFFF);
1138 pSMB->DataLengthHigh = cpu_to_le16(bytes_sent >> 16);
1139 pSMB->hdr.smb_buf_length += byte_count;
1142 pSMB->ByteCount = cpu_to_le16(byte_count);
1143 else { /* old style write has byte count 4 bytes earlier so 4 bytes pad */
1144 struct smb_com_writex_req * pSMBW =
1145 (struct smb_com_writex_req *)pSMB;
1146 pSMBW->ByteCount = cpu_to_le16(byte_count);
1149 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1150 (struct smb_hdr *) pSMBr, &bytes_returned, long_op);
1151 cifs_stats_inc(&tcon->num_writes);
1153 cFYI(1, ("Send error in write = %d", rc));
1156 *nbytes = le16_to_cpu(pSMBr->CountHigh);
1157 *nbytes = (*nbytes) << 16;
1158 *nbytes += le16_to_cpu(pSMBr->Count);
1161 cifs_buf_release(pSMB);
1163 /* Note: On -EAGAIN error only caller can retry on handle based calls
1164 since file handle passed in no longer valid */
1170 CIFSSMBWrite2(const int xid, struct cifsTconInfo *tcon,
1171 const int netfid, const unsigned int count,
1172 const __u64 offset, unsigned int *nbytes, struct kvec *iov,
1173 int n_vec, const int long_op)
1176 WRITE_REQ *pSMB = NULL;
1179 int resp_buf_type = 0;
1181 cFYI(1,("write2 at %lld %d bytes", (long long)offset, count));
1183 if(tcon->ses->capabilities & CAP_LARGE_FILES)
1187 rc = small_smb_init(SMB_COM_WRITE_ANDX, wct, tcon, (void **) &pSMB);
1190 /* tcon and ses pointer are checked in smb_init */
1191 if (tcon->ses->server == NULL)
1192 return -ECONNABORTED;
1194 pSMB->AndXCommand = 0xFF; /* none */
1196 pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF);
1198 pSMB->OffsetHigh = cpu_to_le32(offset >> 32);
1199 else if((offset >> 32) > 0) /* can not handle this big offset for old */
1201 pSMB->Reserved = 0xFFFFFFFF;
1202 pSMB->WriteMode = 0;
1203 pSMB->Remaining = 0;
1206 cpu_to_le16(offsetof(struct smb_com_write_req,Data) - 4);
1208 pSMB->DataLengthLow = cpu_to_le16(count & 0xFFFF);
1209 pSMB->DataLengthHigh = cpu_to_le16(count >> 16);
1210 smb_hdr_len = pSMB->hdr.smb_buf_length + 1; /* hdr + 1 byte pad */
1212 pSMB->hdr.smb_buf_length += count+1;
1213 else /* wct == 12 */
1214 pSMB->hdr.smb_buf_length += count+5; /* smb data starts later */
1216 pSMB->ByteCount = cpu_to_le16(count + 1);
1217 else /* wct == 12 */ /* bigger pad, smaller smb hdr, keep offset ok */ {
1218 struct smb_com_writex_req * pSMBW =
1219 (struct smb_com_writex_req *)pSMB;
1220 pSMBW->ByteCount = cpu_to_le16(count + 5);
1222 iov[0].iov_base = pSMB;
1224 iov[0].iov_len = smb_hdr_len + 4;
1225 else /* wct == 12 pad bigger by four bytes */
1226 iov[0].iov_len = smb_hdr_len + 8;
1229 rc = SendReceive2(xid, tcon->ses, iov, n_vec + 1, &resp_buf_type,
1231 cifs_stats_inc(&tcon->num_writes);
1233 cFYI(1, ("Send error Write2 = %d", rc));
1235 } else if(resp_buf_type == 0) {
1236 /* presumably this can not happen, but best to be safe */
1240 WRITE_RSP * pSMBr = (WRITE_RSP *)iov[0].iov_base;
1241 *nbytes = le16_to_cpu(pSMBr->CountHigh);
1242 *nbytes = (*nbytes) << 16;
1243 *nbytes += le16_to_cpu(pSMBr->Count);
1246 cifs_small_buf_release(pSMB);
1247 if(resp_buf_type == CIFS_SMALL_BUFFER)
1248 cifs_small_buf_release(iov[0].iov_base);
1249 else if(resp_buf_type == CIFS_LARGE_BUFFER)
1250 cifs_buf_release(iov[0].iov_base);
1252 /* Note: On -EAGAIN error only caller can retry on handle based calls
1253 since file handle passed in no longer valid */
1260 CIFSSMBLock(const int xid, struct cifsTconInfo *tcon,
1261 const __u16 smb_file_id, const __u64 len,
1262 const __u64 offset, const __u32 numUnlock,
1263 const __u32 numLock, const __u8 lockType, const int waitFlag)
1266 LOCK_REQ *pSMB = NULL;
1267 LOCK_RSP *pSMBr = NULL;
1272 cFYI(1, ("In CIFSSMBLock - timeout %d numLock %d",waitFlag,numLock));
1273 rc = small_smb_init(SMB_COM_LOCKING_ANDX, 8, tcon, (void **) &pSMB);
1278 pSMBr = (LOCK_RSP *)pSMB; /* BB removeme BB */
1280 if(lockType == LOCKING_ANDX_OPLOCK_RELEASE) {
1281 timeout = -1; /* no response expected */
1283 } else if (waitFlag == TRUE) {
1284 timeout = 3; /* blocking operation, no timeout */
1285 pSMB->Timeout = cpu_to_le32(-1);/* blocking - do not time out */
1290 pSMB->NumberOfLocks = cpu_to_le16(numLock);
1291 pSMB->NumberOfUnlocks = cpu_to_le16(numUnlock);
1292 pSMB->LockType = lockType;
1293 pSMB->AndXCommand = 0xFF; /* none */
1294 pSMB->Fid = smb_file_id; /* netfid stays le */
1296 if((numLock != 0) || (numUnlock != 0)) {
1297 pSMB->Locks[0].Pid = cpu_to_le16(current->tgid);
1298 /* BB where to store pid high? */
1299 pSMB->Locks[0].LengthLow = cpu_to_le32((u32)len);
1300 pSMB->Locks[0].LengthHigh = cpu_to_le32((u32)(len>>32));
1301 pSMB->Locks[0].OffsetLow = cpu_to_le32((u32)offset);
1302 pSMB->Locks[0].OffsetHigh = cpu_to_le32((u32)(offset>>32));
1303 count = sizeof(LOCKING_ANDX_RANGE);
1308 pSMB->hdr.smb_buf_length += count;
1309 pSMB->ByteCount = cpu_to_le16(count);
1311 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1312 (struct smb_hdr *) pSMBr, &bytes_returned, timeout);
1313 cifs_stats_inc(&tcon->num_locks);
1315 cFYI(1, ("Send error in Lock = %d", rc));
1317 cifs_small_buf_release(pSMB);
1319 /* Note: On -EAGAIN error only caller can retry on handle based calls
1320 since file handle passed in no longer valid */
1325 CIFSSMBClose(const int xid, struct cifsTconInfo *tcon, int smb_file_id)
1328 CLOSE_REQ *pSMB = NULL;
1329 CLOSE_RSP *pSMBr = NULL;
1331 cFYI(1, ("In CIFSSMBClose"));
1333 /* do not retry on dead session on close */
1334 rc = small_smb_init(SMB_COM_CLOSE, 3, tcon, (void **) &pSMB);
1340 pSMBr = (CLOSE_RSP *)pSMB; /* BB removeme BB */
1342 pSMB->FileID = (__u16) smb_file_id;
1343 pSMB->LastWriteTime = 0;
1344 pSMB->ByteCount = 0;
1345 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1346 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1347 cifs_stats_inc(&tcon->num_closes);
1350 /* EINTR is expected when user ctl-c to kill app */
1351 cERROR(1, ("Send error in Close = %d", rc));
1355 cifs_small_buf_release(pSMB);
1357 /* Since session is dead, file will be closed on server already */
1365 CIFSSMBRename(const int xid, struct cifsTconInfo *tcon,
1366 const char *fromName, const char *toName,
1367 const struct nls_table *nls_codepage, int remap)
1370 RENAME_REQ *pSMB = NULL;
1371 RENAME_RSP *pSMBr = NULL;
1373 int name_len, name_len2;
1376 cFYI(1, ("In CIFSSMBRename"));
1378 rc = smb_init(SMB_COM_RENAME, 1, tcon, (void **) &pSMB,
1383 pSMB->BufferFormat = 0x04;
1384 pSMB->SearchAttributes =
1385 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
1388 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1390 cifsConvertToUCS((__le16 *) pSMB->OldFileName, fromName,
1391 PATH_MAX, nls_codepage, remap);
1392 name_len++; /* trailing null */
1394 pSMB->OldFileName[name_len] = 0x04; /* pad */
1395 /* protocol requires ASCII signature byte on Unicode string */
1396 pSMB->OldFileName[name_len + 1] = 0x00;
1398 cifsConvertToUCS((__le16 *) &pSMB->OldFileName[name_len + 2],
1399 toName, PATH_MAX, nls_codepage, remap);
1400 name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
1401 name_len2 *= 2; /* convert to bytes */
1402 } else { /* BB improve the check for buffer overruns BB */
1403 name_len = strnlen(fromName, PATH_MAX);
1404 name_len++; /* trailing null */
1405 strncpy(pSMB->OldFileName, fromName, name_len);
1406 name_len2 = strnlen(toName, PATH_MAX);
1407 name_len2++; /* trailing null */
1408 pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */
1409 strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2);
1410 name_len2++; /* trailing null */
1411 name_len2++; /* signature byte */
1414 count = 1 /* 1st signature byte */ + name_len + name_len2;
1415 pSMB->hdr.smb_buf_length += count;
1416 pSMB->ByteCount = cpu_to_le16(count);
1418 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1419 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1420 cifs_stats_inc(&tcon->num_renames);
1422 cFYI(1, ("Send error in rename = %d", rc));
1425 cifs_buf_release(pSMB);
1433 int CIFSSMBRenameOpenFile(const int xid,struct cifsTconInfo *pTcon,
1434 int netfid, char * target_name,
1435 const struct nls_table * nls_codepage, int remap)
1437 struct smb_com_transaction2_sfi_req *pSMB = NULL;
1438 struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
1439 struct set_file_rename * rename_info;
1441 char dummy_string[30];
1443 int bytes_returned = 0;
1445 __u16 params, param_offset, offset, count, byte_count;
1447 cFYI(1, ("Rename to File by handle"));
1448 rc = smb_init(SMB_COM_TRANSACTION2, 15, pTcon, (void **) &pSMB,
1454 pSMB->MaxSetupCount = 0;
1458 pSMB->Reserved2 = 0;
1459 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
1460 offset = param_offset + params;
1462 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
1463 rename_info = (struct set_file_rename *) data_offset;
1464 pSMB->MaxParameterCount = cpu_to_le16(2);
1465 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB PDU from sess */
1466 pSMB->SetupCount = 1;
1467 pSMB->Reserved3 = 0;
1468 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
1469 byte_count = 3 /* pad */ + params;
1470 pSMB->ParameterCount = cpu_to_le16(params);
1471 pSMB->TotalParameterCount = pSMB->ParameterCount;
1472 pSMB->ParameterOffset = cpu_to_le16(param_offset);
1473 pSMB->DataOffset = cpu_to_le16(offset);
1474 /* construct random name ".cifs_tmp<inodenum><mid>" */
1475 rename_info->overwrite = cpu_to_le32(1);
1476 rename_info->root_fid = 0;
1477 /* unicode only call */
1478 if(target_name == NULL) {
1479 sprintf(dummy_string,"cifs%x",pSMB->hdr.Mid);
1480 len_of_str = cifsConvertToUCS((__le16 *)rename_info->target_name,
1481 dummy_string, 24, nls_codepage, remap);
1483 len_of_str = cifsConvertToUCS((__le16 *)rename_info->target_name,
1484 target_name, PATH_MAX, nls_codepage, remap);
1486 rename_info->target_name_len = cpu_to_le32(2 * len_of_str);
1487 count = 12 /* sizeof(struct set_file_rename) */ + (2 * len_of_str) + 2;
1488 byte_count += count;
1489 pSMB->DataCount = cpu_to_le16(count);
1490 pSMB->TotalDataCount = pSMB->DataCount;
1492 pSMB->InformationLevel =
1493 cpu_to_le16(SMB_SET_FILE_RENAME_INFORMATION);
1494 pSMB->Reserved4 = 0;
1495 pSMB->hdr.smb_buf_length += byte_count;
1496 pSMB->ByteCount = cpu_to_le16(byte_count);
1497 rc = SendReceive(xid, pTcon->ses, (struct smb_hdr *) pSMB,
1498 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1499 cifs_stats_inc(&pTcon->num_t2renames);
1501 cFYI(1,("Send error in Rename (by file handle) = %d", rc));
1504 cifs_buf_release(pSMB);
1506 /* Note: On -EAGAIN error only caller can retry on handle based calls
1507 since file handle passed in no longer valid */
1513 CIFSSMBCopy(const int xid, struct cifsTconInfo *tcon, const char * fromName,
1514 const __u16 target_tid, const char *toName, const int flags,
1515 const struct nls_table *nls_codepage, int remap)
1518 COPY_REQ *pSMB = NULL;
1519 COPY_RSP *pSMBr = NULL;
1521 int name_len, name_len2;
1524 cFYI(1, ("In CIFSSMBCopy"));
1526 rc = smb_init(SMB_COM_COPY, 1, tcon, (void **) &pSMB,
1531 pSMB->BufferFormat = 0x04;
1532 pSMB->Tid2 = target_tid;
1534 pSMB->Flags = cpu_to_le16(flags & COPY_TREE);
1536 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1537 name_len = cifsConvertToUCS((__le16 *) pSMB->OldFileName,
1538 fromName, PATH_MAX, nls_codepage,
1540 name_len++; /* trailing null */
1542 pSMB->OldFileName[name_len] = 0x04; /* pad */
1543 /* protocol requires ASCII signature byte on Unicode string */
1544 pSMB->OldFileName[name_len + 1] = 0x00;
1545 name_len2 = cifsConvertToUCS((__le16 *)&pSMB->OldFileName[name_len + 2],
1546 toName, PATH_MAX, nls_codepage, remap);
1547 name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
1548 name_len2 *= 2; /* convert to bytes */
1549 } else { /* BB improve the check for buffer overruns BB */
1550 name_len = strnlen(fromName, PATH_MAX);
1551 name_len++; /* trailing null */
1552 strncpy(pSMB->OldFileName, fromName, name_len);
1553 name_len2 = strnlen(toName, PATH_MAX);
1554 name_len2++; /* trailing null */
1555 pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */
1556 strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2);
1557 name_len2++; /* trailing null */
1558 name_len2++; /* signature byte */
1561 count = 1 /* 1st signature byte */ + name_len + name_len2;
1562 pSMB->hdr.smb_buf_length += count;
1563 pSMB->ByteCount = cpu_to_le16(count);
1565 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1566 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1568 cFYI(1, ("Send error in copy = %d with %d files copied",
1569 rc, le16_to_cpu(pSMBr->CopyCount)));
1572 cifs_buf_release(pSMB);
1581 CIFSUnixCreateSymLink(const int xid, struct cifsTconInfo *tcon,
1582 const char *fromName, const char *toName,
1583 const struct nls_table *nls_codepage)
1585 TRANSACTION2_SPI_REQ *pSMB = NULL;
1586 TRANSACTION2_SPI_RSP *pSMBr = NULL;
1589 int name_len_target;
1591 int bytes_returned = 0;
1592 __u16 params, param_offset, offset, byte_count;
1594 cFYI(1, ("In Symlink Unix style"));
1596 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
1601 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1603 cifs_strtoUCS((__le16 *) pSMB->FileName, fromName, PATH_MAX
1604 /* find define for this maxpathcomponent */
1606 name_len++; /* trailing null */
1609 } else { /* BB improve the check for buffer overruns BB */
1610 name_len = strnlen(fromName, PATH_MAX);
1611 name_len++; /* trailing null */
1612 strncpy(pSMB->FileName, fromName, name_len);
1614 params = 6 + name_len;
1615 pSMB->MaxSetupCount = 0;
1619 pSMB->Reserved2 = 0;
1620 param_offset = offsetof(struct smb_com_transaction2_spi_req,
1621 InformationLevel) - 4;
1622 offset = param_offset + params;
1624 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
1625 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1627 cifs_strtoUCS((__le16 *) data_offset, toName, PATH_MAX
1628 /* find define for this maxpathcomponent */
1630 name_len_target++; /* trailing null */
1631 name_len_target *= 2;
1632 } else { /* BB improve the check for buffer overruns BB */
1633 name_len_target = strnlen(toName, PATH_MAX);
1634 name_len_target++; /* trailing null */
1635 strncpy(data_offset, toName, name_len_target);
1638 pSMB->MaxParameterCount = cpu_to_le16(2);
1639 /* BB find exact max on data count below from sess */
1640 pSMB->MaxDataCount = cpu_to_le16(1000);
1641 pSMB->SetupCount = 1;
1642 pSMB->Reserved3 = 0;
1643 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
1644 byte_count = 3 /* pad */ + params + name_len_target;
1645 pSMB->DataCount = cpu_to_le16(name_len_target);
1646 pSMB->ParameterCount = cpu_to_le16(params);
1647 pSMB->TotalDataCount = pSMB->DataCount;
1648 pSMB->TotalParameterCount = pSMB->ParameterCount;
1649 pSMB->ParameterOffset = cpu_to_le16(param_offset);
1650 pSMB->DataOffset = cpu_to_le16(offset);
1651 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_LINK);
1652 pSMB->Reserved4 = 0;
1653 pSMB->hdr.smb_buf_length += byte_count;
1654 pSMB->ByteCount = cpu_to_le16(byte_count);
1655 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1656 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1657 cifs_stats_inc(&tcon->num_symlinks);
1660 ("Send error in SetPathInfo (create symlink) = %d",
1665 cifs_buf_release(pSMB);
1668 goto createSymLinkRetry;
1674 CIFSUnixCreateHardLink(const int xid, struct cifsTconInfo *tcon,
1675 const char *fromName, const char *toName,
1676 const struct nls_table *nls_codepage, int remap)
1678 TRANSACTION2_SPI_REQ *pSMB = NULL;
1679 TRANSACTION2_SPI_RSP *pSMBr = NULL;
1682 int name_len_target;
1684 int bytes_returned = 0;
1685 __u16 params, param_offset, offset, byte_count;
1687 cFYI(1, ("In Create Hard link Unix style"));
1688 createHardLinkRetry:
1689 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
1694 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1695 name_len = cifsConvertToUCS((__le16 *) pSMB->FileName, toName,
1696 PATH_MAX, nls_codepage, remap);
1697 name_len++; /* trailing null */
1700 } else { /* BB improve the check for buffer overruns BB */
1701 name_len = strnlen(toName, PATH_MAX);
1702 name_len++; /* trailing null */
1703 strncpy(pSMB->FileName, toName, name_len);
1705 params = 6 + name_len;
1706 pSMB->MaxSetupCount = 0;
1710 pSMB->Reserved2 = 0;
1711 param_offset = offsetof(struct smb_com_transaction2_spi_req,
1712 InformationLevel) - 4;
1713 offset = param_offset + params;
1715 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
1716 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1718 cifsConvertToUCS((__le16 *) data_offset, fromName, PATH_MAX,
1719 nls_codepage, remap);
1720 name_len_target++; /* trailing null */
1721 name_len_target *= 2;
1722 } else { /* BB improve the check for buffer overruns BB */
1723 name_len_target = strnlen(fromName, PATH_MAX);
1724 name_len_target++; /* trailing null */
1725 strncpy(data_offset, fromName, name_len_target);
1728 pSMB->MaxParameterCount = cpu_to_le16(2);
1729 /* BB find exact max on data count below from sess*/
1730 pSMB->MaxDataCount = cpu_to_le16(1000);
1731 pSMB->SetupCount = 1;
1732 pSMB->Reserved3 = 0;
1733 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
1734 byte_count = 3 /* pad */ + params + name_len_target;
1735 pSMB->ParameterCount = cpu_to_le16(params);
1736 pSMB->TotalParameterCount = pSMB->ParameterCount;
1737 pSMB->DataCount = cpu_to_le16(name_len_target);
1738 pSMB->TotalDataCount = pSMB->DataCount;
1739 pSMB->ParameterOffset = cpu_to_le16(param_offset);
1740 pSMB->DataOffset = cpu_to_le16(offset);
1741 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_HLINK);
1742 pSMB->Reserved4 = 0;
1743 pSMB->hdr.smb_buf_length += byte_count;
1744 pSMB->ByteCount = cpu_to_le16(byte_count);
1745 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1746 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1747 cifs_stats_inc(&tcon->num_hardlinks);
1749 cFYI(1, ("Send error in SetPathInfo (hard link) = %d", rc));
1752 cifs_buf_release(pSMB);
1754 goto createHardLinkRetry;
1760 CIFSCreateHardLink(const int xid, struct cifsTconInfo *tcon,
1761 const char *fromName, const char *toName,
1762 const struct nls_table *nls_codepage, int remap)
1765 NT_RENAME_REQ *pSMB = NULL;
1766 RENAME_RSP *pSMBr = NULL;
1768 int name_len, name_len2;
1771 cFYI(1, ("In CIFSCreateHardLink"));
1772 winCreateHardLinkRetry:
1774 rc = smb_init(SMB_COM_NT_RENAME, 4, tcon, (void **) &pSMB,
1779 pSMB->SearchAttributes =
1780 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
1782 pSMB->Flags = cpu_to_le16(CREATE_HARD_LINK);
1783 pSMB->ClusterCount = 0;
1785 pSMB->BufferFormat = 0x04;
1787 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1789 cifsConvertToUCS((__le16 *) pSMB->OldFileName, fromName,
1790 PATH_MAX, nls_codepage, remap);
1791 name_len++; /* trailing null */
1793 pSMB->OldFileName[name_len] = 0; /* pad */
1794 pSMB->OldFileName[name_len + 1] = 0x04;
1796 cifsConvertToUCS((__le16 *)&pSMB->OldFileName[name_len + 2],
1797 toName, PATH_MAX, nls_codepage, remap);
1798 name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
1799 name_len2 *= 2; /* convert to bytes */
1800 } else { /* BB improve the check for buffer overruns BB */
1801 name_len = strnlen(fromName, PATH_MAX);
1802 name_len++; /* trailing null */
1803 strncpy(pSMB->OldFileName, fromName, name_len);
1804 name_len2 = strnlen(toName, PATH_MAX);
1805 name_len2++; /* trailing null */
1806 pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */
1807 strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2);
1808 name_len2++; /* trailing null */
1809 name_len2++; /* signature byte */
1812 count = 1 /* string type byte */ + name_len + name_len2;
1813 pSMB->hdr.smb_buf_length += count;
1814 pSMB->ByteCount = cpu_to_le16(count);
1816 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1817 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1818 cifs_stats_inc(&tcon->num_hardlinks);
1820 cFYI(1, ("Send error in hard link (NT rename) = %d", rc));
1822 cifs_buf_release(pSMB);
1824 goto winCreateHardLinkRetry;
1830 CIFSSMBUnixQuerySymLink(const int xid, struct cifsTconInfo *tcon,
1831 const unsigned char *searchName,
1832 char *symlinkinfo, const int buflen,
1833 const struct nls_table *nls_codepage)
1835 /* SMB_QUERY_FILE_UNIX_LINK */
1836 TRANSACTION2_QPI_REQ *pSMB = NULL;
1837 TRANSACTION2_QPI_RSP *pSMBr = NULL;
1841 __u16 params, byte_count;
1843 cFYI(1, ("In QPathSymLinkInfo (Unix) for path %s", searchName));
1846 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
1851 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1853 cifs_strtoUCS((__le16 *) pSMB->FileName, searchName, PATH_MAX
1854 /* find define for this maxpathcomponent */
1856 name_len++; /* trailing null */
1858 } else { /* BB improve the check for buffer overruns BB */
1859 name_len = strnlen(searchName, PATH_MAX);
1860 name_len++; /* trailing null */
1861 strncpy(pSMB->FileName, searchName, name_len);
1864 params = 2 /* level */ + 4 /* rsrvd */ + name_len /* incl null */ ;
1865 pSMB->TotalDataCount = 0;
1866 pSMB->MaxParameterCount = cpu_to_le16(2);
1867 /* BB find exact max data count below from sess structure BB */
1868 pSMB->MaxDataCount = cpu_to_le16(4000);
1869 pSMB->MaxSetupCount = 0;
1873 pSMB->Reserved2 = 0;
1874 pSMB->ParameterOffset = cpu_to_le16(offsetof(
1875 struct smb_com_transaction2_qpi_req ,InformationLevel) - 4);
1876 pSMB->DataCount = 0;
1877 pSMB->DataOffset = 0;
1878 pSMB->SetupCount = 1;
1879 pSMB->Reserved3 = 0;
1880 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
1881 byte_count = params + 1 /* pad */ ;
1882 pSMB->TotalParameterCount = cpu_to_le16(params);
1883 pSMB->ParameterCount = pSMB->TotalParameterCount;
1884 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_LINK);
1885 pSMB->Reserved4 = 0;
1886 pSMB->hdr.smb_buf_length += byte_count;
1887 pSMB->ByteCount = cpu_to_le16(byte_count);
1889 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1890 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1892 cFYI(1, ("Send error in QuerySymLinkInfo = %d", rc));
1894 /* decode response */
1896 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
1897 if (rc || (pSMBr->ByteCount < 2))
1898 /* BB also check enough total bytes returned */
1899 rc = -EIO; /* bad smb */
1901 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
1902 __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
1904 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
1905 name_len = UniStrnlen((wchar_t *) ((char *)
1906 &pSMBr->hdr.Protocol +data_offset),
1907 min_t(const int, buflen,count) / 2);
1908 /* BB FIXME investigate remapping reserved chars here */
1909 cifs_strfromUCS_le(symlinkinfo,
1910 (__le16 *) ((char *)&pSMBr->hdr.Protocol +
1912 name_len, nls_codepage);
1914 strncpy(symlinkinfo,
1915 (char *) &pSMBr->hdr.Protocol +
1917 min_t(const int, buflen, count));
1919 symlinkinfo[buflen] = 0;
1920 /* just in case so calling code does not go off the end of buffer */
1923 cifs_buf_release(pSMB);
1925 goto querySymLinkRetry;
1930 CIFSSMBQueryReparseLinkInfo(const int xid, struct cifsTconInfo *tcon,
1931 const unsigned char *searchName,
1932 char *symlinkinfo, const int buflen,__u16 fid,
1933 const struct nls_table *nls_codepage)
1938 struct smb_com_transaction_ioctl_req * pSMB;
1939 struct smb_com_transaction_ioctl_rsp * pSMBr;
1941 cFYI(1, ("In Windows reparse style QueryLink for path %s", searchName));
1942 rc = smb_init(SMB_COM_NT_TRANSACT, 23, tcon, (void **) &pSMB,
1947 pSMB->TotalParameterCount = 0 ;
1948 pSMB->TotalDataCount = 0;
1949 pSMB->MaxParameterCount = cpu_to_le32(2);
1950 /* BB find exact data count max from sess structure BB */
1951 pSMB->MaxDataCount = cpu_to_le32(4000);
1952 pSMB->MaxSetupCount = 4;
1954 pSMB->ParameterOffset = 0;
1955 pSMB->DataCount = 0;
1956 pSMB->DataOffset = 0;
1957 pSMB->SetupCount = 4;
1958 pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_IOCTL);
1959 pSMB->ParameterCount = pSMB->TotalParameterCount;
1960 pSMB->FunctionCode = cpu_to_le32(FSCTL_GET_REPARSE_POINT);
1961 pSMB->IsFsctl = 1; /* FSCTL */
1962 pSMB->IsRootFlag = 0;
1963 pSMB->Fid = fid; /* file handle always le */
1964 pSMB->ByteCount = 0;
1966 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1967 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1969 cFYI(1, ("Send error in QueryReparseLinkInfo = %d", rc));
1970 } else { /* decode response */
1971 __u32 data_offset = le32_to_cpu(pSMBr->DataOffset);
1972 __u32 data_count = le32_to_cpu(pSMBr->DataCount);
1973 if ((pSMBr->ByteCount < 2) || (data_offset > 512))
1974 /* BB also check enough total bytes returned */
1975 rc = -EIO; /* bad smb */
1977 if(data_count && (data_count < 2048)) {
1978 char * end_of_smb = pSMBr->ByteCount + (char *)&pSMBr->ByteCount;
1980 struct reparse_data * reparse_buf = (struct reparse_data *)
1981 ((char *)&pSMBr->hdr.Protocol + data_offset);
1982 if((char*)reparse_buf >= end_of_smb) {
1986 if((reparse_buf->LinkNamesBuf +
1987 reparse_buf->TargetNameOffset +
1988 reparse_buf->TargetNameLen) >
1990 cFYI(1,("reparse buf extended beyond SMB"));
1995 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
1996 name_len = UniStrnlen((wchar_t *)
1997 (reparse_buf->LinkNamesBuf +
1998 reparse_buf->TargetNameOffset),
1999 min(buflen/2, reparse_buf->TargetNameLen / 2));
2000 cifs_strfromUCS_le(symlinkinfo,
2001 (__le16 *) (reparse_buf->LinkNamesBuf +
2002 reparse_buf->TargetNameOffset),
2003 name_len, nls_codepage);
2004 } else { /* ASCII names */
2005 strncpy(symlinkinfo,reparse_buf->LinkNamesBuf +
2006 reparse_buf->TargetNameOffset,
2007 min_t(const int, buflen, reparse_buf->TargetNameLen));
2011 cFYI(1,("Invalid return data count on get reparse info ioctl"));
2013 symlinkinfo[buflen] = 0; /* just in case so the caller
2014 does not go off the end of the buffer */
2015 cFYI(1,("readlink result - %s ",symlinkinfo));
2019 cifs_buf_release(pSMB);
2021 /* Note: On -EAGAIN error only caller can retry on handle based calls
2022 since file handle passed in no longer valid */
2027 #ifdef CONFIG_CIFS_POSIX
2029 /*Convert an Access Control Entry from wire format to local POSIX xattr format*/
2030 static void cifs_convert_ace(posix_acl_xattr_entry * ace, struct cifs_posix_ace * cifs_ace)
2032 /* u8 cifs fields do not need le conversion */
2033 ace->e_perm = cpu_to_le16(cifs_ace->cifs_e_perm);
2034 ace->e_tag = cpu_to_le16(cifs_ace->cifs_e_tag);
2035 ace->e_id = cpu_to_le32(le64_to_cpu(cifs_ace->cifs_uid));
2036 /* cFYI(1,("perm %d tag %d id %d",ace->e_perm,ace->e_tag,ace->e_id)); */
2041 /* Convert ACL from CIFS POSIX wire format to local Linux POSIX ACL xattr */
2042 static int cifs_copy_posix_acl(char * trgt,char * src, const int buflen,
2043 const int acl_type,const int size_of_data_area)
2048 struct cifs_posix_ace * pACE;
2049 struct cifs_posix_acl * cifs_acl = (struct cifs_posix_acl *)src;
2050 posix_acl_xattr_header * local_acl = (posix_acl_xattr_header *)trgt;
2052 if (le16_to_cpu(cifs_acl->version) != CIFS_ACL_VERSION)
2055 if(acl_type & ACL_TYPE_ACCESS) {
2056 count = le16_to_cpu(cifs_acl->access_entry_count);
2057 pACE = &cifs_acl->ace_array[0];
2058 size = sizeof(struct cifs_posix_acl);
2059 size += sizeof(struct cifs_posix_ace) * count;
2060 /* check if we would go beyond end of SMB */
2061 if(size_of_data_area < size) {
2062 cFYI(1,("bad CIFS POSIX ACL size %d vs. %d",size_of_data_area,size));
2065 } else if(acl_type & ACL_TYPE_DEFAULT) {
2066 count = le16_to_cpu(cifs_acl->access_entry_count);
2067 size = sizeof(struct cifs_posix_acl);
2068 size += sizeof(struct cifs_posix_ace) * count;
2069 /* skip past access ACEs to get to default ACEs */
2070 pACE = &cifs_acl->ace_array[count];
2071 count = le16_to_cpu(cifs_acl->default_entry_count);
2072 size += sizeof(struct cifs_posix_ace) * count;
2073 /* check if we would go beyond end of SMB */
2074 if(size_of_data_area < size)
2081 size = posix_acl_xattr_size(count);
2082 if((buflen == 0) || (local_acl == NULL)) {
2083 /* used to query ACL EA size */
2084 } else if(size > buflen) {
2086 } else /* buffer big enough */ {
2087 local_acl->a_version = cpu_to_le32(POSIX_ACL_XATTR_VERSION);
2088 for(i = 0;i < count ;i++) {
2089 cifs_convert_ace(&local_acl->a_entries[i],pACE);
2096 static __u16 convert_ace_to_cifs_ace(struct cifs_posix_ace * cifs_ace,
2097 const posix_acl_xattr_entry * local_ace)
2099 __u16 rc = 0; /* 0 = ACL converted ok */
2101 cifs_ace->cifs_e_perm = le16_to_cpu(local_ace->e_perm);
2102 cifs_ace->cifs_e_tag = le16_to_cpu(local_ace->e_tag);
2103 /* BB is there a better way to handle the large uid? */
2104 if(local_ace->e_id == cpu_to_le32(-1)) {
2105 /* Probably no need to le convert -1 on any arch but can not hurt */
2106 cifs_ace->cifs_uid = cpu_to_le64(-1);
2108 cifs_ace->cifs_uid = cpu_to_le64(le32_to_cpu(local_ace->e_id));
2109 /*cFYI(1,("perm %d tag %d id %d",ace->e_perm,ace->e_tag,ace->e_id));*/
2113 /* Convert ACL from local Linux POSIX xattr to CIFS POSIX ACL wire format */
2114 static __u16 ACL_to_cifs_posix(char * parm_data,const char * pACL,const int buflen,
2118 struct cifs_posix_acl * cifs_acl = (struct cifs_posix_acl *)parm_data;
2119 posix_acl_xattr_header * local_acl = (posix_acl_xattr_header *)pACL;
2123 if((buflen == 0) || (pACL == NULL) || (cifs_acl == NULL))
2126 count = posix_acl_xattr_count((size_t)buflen);
2127 cFYI(1,("setting acl with %d entries from buf of length %d and version of %d",
2128 count, buflen, le32_to_cpu(local_acl->a_version)));
2129 if(le32_to_cpu(local_acl->a_version) != 2) {
2130 cFYI(1,("unknown POSIX ACL version %d",
2131 le32_to_cpu(local_acl->a_version)));
2134 cifs_acl->version = cpu_to_le16(1);
2135 if(acl_type == ACL_TYPE_ACCESS)
2136 cifs_acl->access_entry_count = cpu_to_le16(count);
2137 else if(acl_type == ACL_TYPE_DEFAULT)
2138 cifs_acl->default_entry_count = cpu_to_le16(count);
2140 cFYI(1,("unknown ACL type %d",acl_type));
2143 for(i=0;i<count;i++) {
2144 rc = convert_ace_to_cifs_ace(&cifs_acl->ace_array[i],
2145 &local_acl->a_entries[i]);
2147 /* ACE not converted */
2152 rc = (__u16)(count * sizeof(struct cifs_posix_ace));
2153 rc += sizeof(struct cifs_posix_acl);
2154 /* BB add check to make sure ACL does not overflow SMB */
2160 CIFSSMBGetPosixACL(const int xid, struct cifsTconInfo *tcon,
2161 const unsigned char *searchName,
2162 char *acl_inf, const int buflen, const int acl_type,
2163 const struct nls_table *nls_codepage, int remap)
2165 /* SMB_QUERY_POSIX_ACL */
2166 TRANSACTION2_QPI_REQ *pSMB = NULL;
2167 TRANSACTION2_QPI_RSP *pSMBr = NULL;
2171 __u16 params, byte_count;
2173 cFYI(1, ("In GetPosixACL (Unix) for path %s", searchName));
2176 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2181 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2183 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
2184 PATH_MAX, nls_codepage, remap);
2185 name_len++; /* trailing null */
2187 pSMB->FileName[name_len] = 0;
2188 pSMB->FileName[name_len+1] = 0;
2189 } else { /* BB improve the check for buffer overruns BB */
2190 name_len = strnlen(searchName, PATH_MAX);
2191 name_len++; /* trailing null */
2192 strncpy(pSMB->FileName, searchName, name_len);
2195 params = 2 /* level */ + 4 /* rsrvd */ + name_len /* incl null */ ;
2196 pSMB->TotalDataCount = 0;
2197 pSMB->MaxParameterCount = cpu_to_le16(2);
2198 /* BB find exact max data count below from sess structure BB */
2199 pSMB->MaxDataCount = cpu_to_le16(4000);
2200 pSMB->MaxSetupCount = 0;
2204 pSMB->Reserved2 = 0;
2205 pSMB->ParameterOffset = cpu_to_le16(
2206 offsetof(struct smb_com_transaction2_qpi_req ,InformationLevel) - 4);
2207 pSMB->DataCount = 0;
2208 pSMB->DataOffset = 0;
2209 pSMB->SetupCount = 1;
2210 pSMB->Reserved3 = 0;
2211 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
2212 byte_count = params + 1 /* pad */ ;
2213 pSMB->TotalParameterCount = cpu_to_le16(params);
2214 pSMB->ParameterCount = pSMB->TotalParameterCount;
2215 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_POSIX_ACL);
2216 pSMB->Reserved4 = 0;
2217 pSMB->hdr.smb_buf_length += byte_count;
2218 pSMB->ByteCount = cpu_to_le16(byte_count);
2220 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2221 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2223 cFYI(1, ("Send error in Query POSIX ACL = %d", rc));
2225 /* decode response */
2227 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
2228 if (rc || (pSMBr->ByteCount < 2))
2229 /* BB also check enough total bytes returned */
2230 rc = -EIO; /* bad smb */
2232 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
2233 __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
2234 rc = cifs_copy_posix_acl(acl_inf,
2235 (char *)&pSMBr->hdr.Protocol+data_offset,
2236 buflen,acl_type,count);
2239 cifs_buf_release(pSMB);
2246 CIFSSMBSetPosixACL(const int xid, struct cifsTconInfo *tcon,
2247 const unsigned char *fileName,
2248 const char *local_acl, const int buflen,
2250 const struct nls_table *nls_codepage, int remap)
2252 struct smb_com_transaction2_spi_req *pSMB = NULL;
2253 struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
2257 int bytes_returned = 0;
2258 __u16 params, byte_count, data_count, param_offset, offset;
2260 cFYI(1, ("In SetPosixACL (Unix) for path %s", fileName));
2262 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2266 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2268 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
2269 PATH_MAX, nls_codepage, remap);
2270 name_len++; /* trailing null */
2272 } else { /* BB improve the check for buffer overruns BB */
2273 name_len = strnlen(fileName, PATH_MAX);
2274 name_len++; /* trailing null */
2275 strncpy(pSMB->FileName, fileName, name_len);
2277 params = 6 + name_len;
2278 pSMB->MaxParameterCount = cpu_to_le16(2);
2279 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB size from sess */
2280 pSMB->MaxSetupCount = 0;
2284 pSMB->Reserved2 = 0;
2285 param_offset = offsetof(struct smb_com_transaction2_spi_req,
2286 InformationLevel) - 4;
2287 offset = param_offset + params;
2288 parm_data = ((char *) &pSMB->hdr.Protocol) + offset;
2289 pSMB->ParameterOffset = cpu_to_le16(param_offset);
2291 /* convert to on the wire format for POSIX ACL */
2292 data_count = ACL_to_cifs_posix(parm_data,local_acl,buflen,acl_type);
2294 if(data_count == 0) {
2296 goto setACLerrorExit;
2298 pSMB->DataOffset = cpu_to_le16(offset);
2299 pSMB->SetupCount = 1;
2300 pSMB->Reserved3 = 0;
2301 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
2302 pSMB->InformationLevel = cpu_to_le16(SMB_SET_POSIX_ACL);
2303 byte_count = 3 /* pad */ + params + data_count;
2304 pSMB->DataCount = cpu_to_le16(data_count);
2305 pSMB->TotalDataCount = pSMB->DataCount;
2306 pSMB->ParameterCount = cpu_to_le16(params);
2307 pSMB->TotalParameterCount = pSMB->ParameterCount;
2308 pSMB->Reserved4 = 0;
2309 pSMB->hdr.smb_buf_length += byte_count;
2310 pSMB->ByteCount = cpu_to_le16(byte_count);
2311 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2312 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2314 cFYI(1, ("Set POSIX ACL returned %d", rc));
2318 cifs_buf_release(pSMB);
2324 /* BB fix tabs in this function FIXME BB */
2326 CIFSGetExtAttr(const int xid, struct cifsTconInfo *tcon,
2327 const int netfid, __u64 * pExtAttrBits, __u64 *pMask)
2330 struct smb_t2_qfi_req *pSMB = NULL;
2331 struct smb_t2_qfi_rsp *pSMBr = NULL;
2333 __u16 params, byte_count;
2335 cFYI(1,("In GetExtAttr"));
2340 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2345 params = 2 /* level */ +2 /* fid */;
2346 pSMB->t2.TotalDataCount = 0;
2347 pSMB->t2.MaxParameterCount = cpu_to_le16(4);
2348 /* BB find exact max data count below from sess structure BB */
2349 pSMB->t2.MaxDataCount = cpu_to_le16(4000);
2350 pSMB->t2.MaxSetupCount = 0;
2351 pSMB->t2.Reserved = 0;
2353 pSMB->t2.Timeout = 0;
2354 pSMB->t2.Reserved2 = 0;
2355 pSMB->t2.ParameterOffset = cpu_to_le16(offsetof(struct smb_t2_qfi_req,
2357 pSMB->t2.DataCount = 0;
2358 pSMB->t2.DataOffset = 0;
2359 pSMB->t2.SetupCount = 1;
2360 pSMB->t2.Reserved3 = 0;
2361 pSMB->t2.SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION);
2362 byte_count = params + 1 /* pad */ ;
2363 pSMB->t2.TotalParameterCount = cpu_to_le16(params);
2364 pSMB->t2.ParameterCount = pSMB->t2.TotalParameterCount;
2365 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_ATTR_FLAGS);
2368 pSMB->hdr.smb_buf_length += byte_count;
2369 pSMB->t2.ByteCount = cpu_to_le16(byte_count);
2371 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2372 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2374 cFYI(1, ("error %d in GetExtAttr", rc));
2376 /* decode response */
2377 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
2378 if (rc || (pSMBr->ByteCount < 2))
2379 /* BB also check enough total bytes returned */
2380 /* If rc should we check for EOPNOSUPP and
2381 disable the srvino flag? or in caller? */
2382 rc = -EIO; /* bad smb */
2384 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
2385 __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
2386 struct file_chattr_info * pfinfo;
2387 /* BB Do we need a cast or hash here ? */
2389 cFYI(1, ("Illegal size ret in GetExtAttr"));
2393 pfinfo = (struct file_chattr_info *)
2394 (data_offset + (char *) &pSMBr->hdr.Protocol);
2395 *pExtAttrBits = le64_to_cpu(pfinfo->mode);
2396 *pMask = le64_to_cpu(pfinfo->mask);
2400 cifs_buf_release(pSMB);
2402 goto GetExtAttrRetry;
2407 #endif /* CONFIG_POSIX */
2409 /* Legacy Query Path Information call for lookup to old servers such
2411 int SMBQueryInformation(const int xid, struct cifsTconInfo *tcon,
2412 const unsigned char *searchName,
2413 FILE_ALL_INFO * pFinfo,
2414 const struct nls_table *nls_codepage, int remap)
2416 QUERY_INFORMATION_REQ * pSMB;
2417 QUERY_INFORMATION_RSP * pSMBr;
2422 cFYI(1, ("In SMBQPath path %s", searchName));
2424 rc = smb_init(SMB_COM_QUERY_INFORMATION, 0, tcon, (void **) &pSMB,
2429 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2431 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
2432 PATH_MAX, nls_codepage, remap);
2433 name_len++; /* trailing null */
2436 name_len = strnlen(searchName, PATH_MAX);
2437 name_len++; /* trailing null */
2438 strncpy(pSMB->FileName, searchName, name_len);
2440 pSMB->BufferFormat = 0x04;
2441 name_len++; /* account for buffer type byte */
2442 pSMB->hdr.smb_buf_length += (__u16) name_len;
2443 pSMB->ByteCount = cpu_to_le16(name_len);
2445 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2446 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2448 cFYI(1, ("Send error in QueryInfo = %d", rc));
2449 } else if (pFinfo) { /* decode response */
2450 memset(pFinfo, 0, sizeof(FILE_ALL_INFO));
2451 pFinfo->AllocationSize =
2452 cpu_to_le64(le32_to_cpu(pSMBr->size));
2453 pFinfo->EndOfFile = pFinfo->AllocationSize;
2454 pFinfo->Attributes =
2455 cpu_to_le32(le16_to_cpu(pSMBr->attr));
2457 rc = -EIO; /* bad buffer passed in */
2459 cifs_buf_release(pSMB);
2471 CIFSSMBQPathInfo(const int xid, struct cifsTconInfo *tcon,
2472 const unsigned char *searchName,
2473 FILE_ALL_INFO * pFindData,
2474 const struct nls_table *nls_codepage, int remap)
2476 /* level 263 SMB_QUERY_FILE_ALL_INFO */
2477 TRANSACTION2_QPI_REQ *pSMB = NULL;
2478 TRANSACTION2_QPI_RSP *pSMBr = NULL;
2482 __u16 params, byte_count;
2484 /* cFYI(1, ("In QPathInfo path %s", searchName)); */
2486 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2491 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2493 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
2494 PATH_MAX, nls_codepage, remap);
2495 name_len++; /* trailing null */
2497 } else { /* BB improve the check for buffer overruns BB */
2498 name_len = strnlen(searchName, PATH_MAX);
2499 name_len++; /* trailing null */
2500 strncpy(pSMB->FileName, searchName, name_len);
2503 params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */ ;
2504 pSMB->TotalDataCount = 0;
2505 pSMB->MaxParameterCount = cpu_to_le16(2);
2506 pSMB->MaxDataCount = cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
2507 pSMB->MaxSetupCount = 0;
2511 pSMB->Reserved2 = 0;
2512 pSMB->ParameterOffset = cpu_to_le16(offsetof(
2513 struct smb_com_transaction2_qpi_req ,InformationLevel) - 4);
2514 pSMB->DataCount = 0;
2515 pSMB->DataOffset = 0;
2516 pSMB->SetupCount = 1;
2517 pSMB->Reserved3 = 0;
2518 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
2519 byte_count = params + 1 /* pad */ ;
2520 pSMB->TotalParameterCount = cpu_to_le16(params);
2521 pSMB->ParameterCount = pSMB->TotalParameterCount;
2522 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_ALL_INFO);
2523 pSMB->Reserved4 = 0;
2524 pSMB->hdr.smb_buf_length += byte_count;
2525 pSMB->ByteCount = cpu_to_le16(byte_count);
2527 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2528 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2530 cFYI(1, ("Send error in QPathInfo = %d", rc));
2531 } else { /* decode response */
2532 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
2534 if (rc || (pSMBr->ByteCount < 40))
2535 rc = -EIO; /* bad smb */
2536 else if (pFindData){
2537 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
2538 memcpy((char *) pFindData,
2539 (char *) &pSMBr->hdr.Protocol +
2540 data_offset, sizeof (FILE_ALL_INFO));
2544 cifs_buf_release(pSMB);
2546 goto QPathInfoRetry;
2552 CIFSSMBUnixQPathInfo(const int xid, struct cifsTconInfo *tcon,
2553 const unsigned char *searchName,
2554 FILE_UNIX_BASIC_INFO * pFindData,
2555 const struct nls_table *nls_codepage, int remap)
2557 /* SMB_QUERY_FILE_UNIX_BASIC */
2558 TRANSACTION2_QPI_REQ *pSMB = NULL;
2559 TRANSACTION2_QPI_RSP *pSMBr = NULL;
2561 int bytes_returned = 0;
2563 __u16 params, byte_count;
2565 cFYI(1, ("In QPathInfo (Unix) the path %s", searchName));
2567 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2572 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2574 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
2575 PATH_MAX, nls_codepage, remap);
2576 name_len++; /* trailing null */
2578 } else { /* BB improve the check for buffer overruns BB */
2579 name_len = strnlen(searchName, PATH_MAX);
2580 name_len++; /* trailing null */
2581 strncpy(pSMB->FileName, searchName, name_len);
2584 params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */ ;
2585 pSMB->TotalDataCount = 0;
2586 pSMB->MaxParameterCount = cpu_to_le16(2);
2587 /* BB find exact max SMB PDU from sess structure BB */
2588 pSMB->MaxDataCount = cpu_to_le16(4000);
2589 pSMB->MaxSetupCount = 0;
2593 pSMB->Reserved2 = 0;
2594 pSMB->ParameterOffset = cpu_to_le16(offsetof(
2595 struct smb_com_transaction2_qpi_req ,InformationLevel) - 4);
2596 pSMB->DataCount = 0;
2597 pSMB->DataOffset = 0;
2598 pSMB->SetupCount = 1;
2599 pSMB->Reserved3 = 0;
2600 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
2601 byte_count = params + 1 /* pad */ ;
2602 pSMB->TotalParameterCount = cpu_to_le16(params);
2603 pSMB->ParameterCount = pSMB->TotalParameterCount;
2604 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC);
2605 pSMB->Reserved4 = 0;
2606 pSMB->hdr.smb_buf_length += byte_count;
2607 pSMB->ByteCount = cpu_to_le16(byte_count);
2609 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2610 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2612 cFYI(1, ("Send error in QPathInfo = %d", rc));
2613 } else { /* decode response */
2614 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
2616 if (rc || (pSMBr->ByteCount < sizeof(FILE_UNIX_BASIC_INFO))) {
2617 rc = -EIO; /* bad smb */
2619 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
2620 memcpy((char *) pFindData,
2621 (char *) &pSMBr->hdr.Protocol +
2623 sizeof (FILE_UNIX_BASIC_INFO));
2626 cifs_buf_release(pSMB);
2628 goto UnixQPathInfoRetry;
2633 #if 0 /* function unused at present */
2634 int CIFSFindSingle(const int xid, struct cifsTconInfo *tcon,
2635 const char *searchName, FILE_ALL_INFO * findData,
2636 const struct nls_table *nls_codepage)
2638 /* level 257 SMB_ */
2639 TRANSACTION2_FFIRST_REQ *pSMB = NULL;
2640 TRANSACTION2_FFIRST_RSP *pSMBr = NULL;
2644 __u16 params, byte_count;
2646 cFYI(1, ("In FindUnique"));
2648 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2653 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2655 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName, PATH_MAX
2656 /* find define for this maxpathcomponent */
2658 name_len++; /* trailing null */
2660 } else { /* BB improve the check for buffer overruns BB */
2661 name_len = strnlen(searchName, PATH_MAX);
2662 name_len++; /* trailing null */
2663 strncpy(pSMB->FileName, searchName, name_len);
2666 params = 12 + name_len /* includes null */ ;
2667 pSMB->TotalDataCount = 0; /* no EAs */
2668 pSMB->MaxParameterCount = cpu_to_le16(2);
2669 pSMB->MaxDataCount = cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
2670 pSMB->MaxSetupCount = 0;
2674 pSMB->Reserved2 = 0;
2675 pSMB->ParameterOffset = cpu_to_le16(
2676 offsetof(struct smb_com_transaction2_ffirst_req,InformationLevel) - 4);
2677 pSMB->DataCount = 0;
2678 pSMB->DataOffset = 0;
2679 pSMB->SetupCount = 1; /* one byte, no need to le convert */
2680 pSMB->Reserved3 = 0;
2681 pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_FIRST);
2682 byte_count = params + 1 /* pad */ ;
2683 pSMB->TotalParameterCount = cpu_to_le16(params);
2684 pSMB->ParameterCount = pSMB->TotalParameterCount;
2685 pSMB->SearchAttributes =
2686 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
2688 pSMB->SearchCount = cpu_to_le16(16); /* BB increase */
2689 pSMB->SearchFlags = cpu_to_le16(1);
2690 pSMB->InformationLevel = cpu_to_le16(SMB_FIND_FILE_DIRECTORY_INFO);
2691 pSMB->SearchStorageType = 0; /* BB what should we set this to? BB */
2692 pSMB->hdr.smb_buf_length += byte_count;
2693 pSMB->ByteCount = cpu_to_le16(byte_count);
2695 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2696 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2699 cFYI(1, ("Send error in FindFileDirInfo = %d", rc));
2700 } else { /* decode response */
2701 cifs_stats_inc(&tcon->num_ffirst);
2705 cifs_buf_release(pSMB);
2707 goto findUniqueRetry;
2711 #endif /* end unused (temporarily) function */
2713 /* xid, tcon, searchName and codepage are input parms, rest are returned */
2715 CIFSFindFirst(const int xid, struct cifsTconInfo *tcon,
2716 const char *searchName,
2717 const struct nls_table *nls_codepage,
2719 struct cifs_search_info * psrch_inf, int remap, const char dirsep)
2721 /* level 257 SMB_ */
2722 TRANSACTION2_FFIRST_REQ *pSMB = NULL;
2723 TRANSACTION2_FFIRST_RSP *pSMBr = NULL;
2724 T2_FFIRST_RSP_PARMS * parms;
2726 int bytes_returned = 0;
2728 __u16 params, byte_count;
2730 cFYI(1, ("In FindFirst for %s",searchName));
2733 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2738 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2740 cifsConvertToUCS((__le16 *) pSMB->FileName,searchName,
2741 PATH_MAX, nls_codepage, remap);
2742 /* We can not add the asterik earlier in case
2743 it got remapped to 0xF03A as if it were part of the
2744 directory name instead of a wildcard */
2746 pSMB->FileName[name_len] = dirsep;
2747 pSMB->FileName[name_len+1] = 0;
2748 pSMB->FileName[name_len+2] = '*';
2749 pSMB->FileName[name_len+3] = 0;
2750 name_len += 4; /* now the trailing null */
2751 pSMB->FileName[name_len] = 0; /* null terminate just in case */
2752 pSMB->FileName[name_len+1] = 0;
2754 } else { /* BB add check for overrun of SMB buf BB */
2755 name_len = strnlen(searchName, PATH_MAX);
2756 /* BB fix here and in unicode clause above ie
2757 if(name_len > buffersize-header)
2758 free buffer exit; BB */
2759 strncpy(pSMB->FileName, searchName, name_len);
2760 pSMB->FileName[name_len] = dirsep;
2761 pSMB->FileName[name_len+1] = '*';
2762 pSMB->FileName[name_len+2] = 0;
2766 params = 12 + name_len /* includes null */ ;
2767 pSMB->TotalDataCount = 0; /* no EAs */
2768 pSMB->MaxParameterCount = cpu_to_le16(10);
2769 pSMB->MaxDataCount = cpu_to_le16((tcon->ses->server->maxBuf -
2770 MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
2771 pSMB->MaxSetupCount = 0;
2775 pSMB->Reserved2 = 0;
2776 byte_count = params + 1 /* pad */ ;
2777 pSMB->TotalParameterCount = cpu_to_le16(params);
2778 pSMB->ParameterCount = pSMB->TotalParameterCount;
2779 pSMB->ParameterOffset = cpu_to_le16(
2780 offsetof(struct smb_com_transaction2_ffirst_req, SearchAttributes) - 4);
2781 pSMB->DataCount = 0;
2782 pSMB->DataOffset = 0;
2783 pSMB->SetupCount = 1; /* one byte, no need to make endian neutral */
2784 pSMB->Reserved3 = 0;
2785 pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_FIRST);
2786 pSMB->SearchAttributes =
2787 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
2789 pSMB->SearchCount= cpu_to_le16(CIFSMaxBufSize/sizeof(FILE_UNIX_INFO));
2790 pSMB->SearchFlags = cpu_to_le16(CIFS_SEARCH_CLOSE_AT_END |
2791 CIFS_SEARCH_RETURN_RESUME);
2792 pSMB->InformationLevel = cpu_to_le16(psrch_inf->info_level);
2794 /* BB what should we set StorageType to? Does it matter? BB */
2795 pSMB->SearchStorageType = 0;
2796 pSMB->hdr.smb_buf_length += byte_count;
2797 pSMB->ByteCount = cpu_to_le16(byte_count);
2799 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2800 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2801 cifs_stats_inc(&tcon->num_ffirst);
2803 if (rc) {/* BB add logic to retry regular search if Unix search rejected unexpectedly by server */
2804 /* BB Add code to handle unsupported level rc */
2805 cFYI(1, ("Error in FindFirst = %d", rc));
2808 cifs_buf_release(pSMB);
2810 /* BB eventually could optimize out free and realloc of buf */
2813 goto findFirstRetry;
2814 } else { /* decode response */
2815 /* BB remember to free buffer if error BB */
2816 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
2818 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
2819 psrch_inf->unicode = TRUE;
2821 psrch_inf->unicode = FALSE;
2823 psrch_inf->ntwrk_buf_start = (char *)pSMBr;
2824 psrch_inf->srch_entries_start =
2825 (char *) &pSMBr->hdr.Protocol +
2826 le16_to_cpu(pSMBr->t2.DataOffset);
2827 parms = (T2_FFIRST_RSP_PARMS *)((char *) &pSMBr->hdr.Protocol +
2828 le16_to_cpu(pSMBr->t2.ParameterOffset));
2830 if(parms->EndofSearch)
2831 psrch_inf->endOfSearch = TRUE;
2833 psrch_inf->endOfSearch = FALSE;
2835 psrch_inf->entries_in_buffer = le16_to_cpu(parms->SearchCount);
2836 psrch_inf->index_of_last_entry =
2837 psrch_inf->entries_in_buffer;
2838 *pnetfid = parms->SearchHandle;
2840 cifs_buf_release(pSMB);
2847 int CIFSFindNext(const int xid, struct cifsTconInfo *tcon,
2848 __u16 searchHandle, struct cifs_search_info * psrch_inf)
2850 TRANSACTION2_FNEXT_REQ *pSMB = NULL;
2851 TRANSACTION2_FNEXT_RSP *pSMBr = NULL;
2852 T2_FNEXT_RSP_PARMS * parms;
2853 char *response_data;
2855 int bytes_returned, name_len;
2856 __u16 params, byte_count;
2858 cFYI(1, ("In FindNext"));
2860 if(psrch_inf->endOfSearch == TRUE)
2863 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2868 params = 14; /* includes 2 bytes of null string, converted to LE below */
2870 pSMB->TotalDataCount = 0; /* no EAs */
2871 pSMB->MaxParameterCount = cpu_to_le16(8);
2872 pSMB->MaxDataCount =
2873 cpu_to_le16((tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
2874 pSMB->MaxSetupCount = 0;
2878 pSMB->Reserved2 = 0;
2879 pSMB->ParameterOffset = cpu_to_le16(
2880 offsetof(struct smb_com_transaction2_fnext_req,SearchHandle) - 4);
2881 pSMB->DataCount = 0;
2882 pSMB->DataOffset = 0;
2883 pSMB->SetupCount = 1;
2884 pSMB->Reserved3 = 0;
2885 pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_NEXT);
2886 pSMB->SearchHandle = searchHandle; /* always kept as le */
2888 cpu_to_le16(CIFSMaxBufSize / sizeof (FILE_UNIX_INFO));
2889 /* test for Unix extensions */
2890 /* if (tcon->ses->capabilities & CAP_UNIX) {
2891 pSMB->InformationLevel = cpu_to_le16(SMB_FIND_FILE_UNIX);
2892 psrch_inf->info_level = SMB_FIND_FILE_UNIX;
2894 pSMB->InformationLevel =
2895 cpu_to_le16(SMB_FIND_FILE_DIRECTORY_INFO);
2896 psrch_inf->info_level = SMB_FIND_FILE_DIRECTORY_INFO;
2898 pSMB->InformationLevel = cpu_to_le16(psrch_inf->info_level);
2899 pSMB->ResumeKey = psrch_inf->resume_key;
2901 cpu_to_le16(CIFS_SEARCH_CLOSE_AT_END | CIFS_SEARCH_RETURN_RESUME);
2903 name_len = psrch_inf->resume_name_len;
2905 if(name_len < PATH_MAX) {
2906 memcpy(pSMB->ResumeFileName, psrch_inf->presume_name, name_len);
2907 byte_count += name_len;
2908 /* 14 byte parm len above enough for 2 byte null terminator */
2909 pSMB->ResumeFileName[name_len] = 0;
2910 pSMB->ResumeFileName[name_len+1] = 0;
2913 goto FNext2_err_exit;
2915 byte_count = params + 1 /* pad */ ;
2916 pSMB->TotalParameterCount = cpu_to_le16(params);
2917 pSMB->ParameterCount = pSMB->TotalParameterCount;
2918 pSMB->hdr.smb_buf_length += byte_count;
2919 pSMB->ByteCount = cpu_to_le16(byte_count);
2921 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2922 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2923 cifs_stats_inc(&tcon->num_fnext);
2926 psrch_inf->endOfSearch = TRUE;
2927 rc = 0; /* search probably was closed at end of search above */
2929 cFYI(1, ("FindNext returned = %d", rc));
2930 } else { /* decode response */
2931 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
2934 /* BB fixme add lock for file (srch_info) struct here */
2935 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
2936 psrch_inf->unicode = TRUE;
2938 psrch_inf->unicode = FALSE;
2939 response_data = (char *) &pSMBr->hdr.Protocol +
2940 le16_to_cpu(pSMBr->t2.ParameterOffset);
2941 parms = (T2_FNEXT_RSP_PARMS *)response_data;
2942 response_data = (char *)&pSMBr->hdr.Protocol +
2943 le16_to_cpu(pSMBr->t2.DataOffset);
2944 cifs_buf_release(psrch_inf->ntwrk_buf_start);
2945 psrch_inf->srch_entries_start = response_data;
2946 psrch_inf->ntwrk_buf_start = (char *)pSMB;
2947 if(parms->EndofSearch)
2948 psrch_inf->endOfSearch = TRUE;
2950 psrch_inf->endOfSearch = FALSE;
2952 psrch_inf->entries_in_buffer = le16_to_cpu(parms->SearchCount);
2953 psrch_inf->index_of_last_entry +=
2954 psrch_inf->entries_in_buffer;
2955 /* cFYI(1,("fnxt2 entries in buf %d index_of_last %d",psrch_inf->entries_in_buffer,psrch_inf->index_of_last_entry)); */
2957 /* BB fixme add unlock here */
2962 /* BB On error, should we leave previous search buf (and count and
2963 last entry fields) intact or free the previous one? */
2965 /* Note: On -EAGAIN error only caller can retry on handle based calls
2966 since file handle passed in no longer valid */
2969 cifs_buf_release(pSMB);
2975 CIFSFindClose(const int xid, struct cifsTconInfo *tcon, const __u16 searchHandle)
2978 FINDCLOSE_REQ *pSMB = NULL;
2979 CLOSE_RSP *pSMBr = NULL; /* BB removeme BB */
2982 cFYI(1, ("In CIFSSMBFindClose"));
2983 rc = small_smb_init(SMB_COM_FIND_CLOSE2, 1, tcon, (void **)&pSMB);
2985 /* no sense returning error if session restarted
2986 as file handle has been closed */
2992 pSMBr = (CLOSE_RSP *)pSMB; /* BB removeme BB */
2993 pSMB->FileID = searchHandle;
2994 pSMB->ByteCount = 0;
2995 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2996 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2998 cERROR(1, ("Send error in FindClose = %d", rc));
3000 cifs_stats_inc(&tcon->num_fclose);
3001 cifs_small_buf_release(pSMB);
3003 /* Since session is dead, search handle closed on server already */
3011 CIFSGetSrvInodeNumber(const int xid, struct cifsTconInfo *tcon,
3012 const unsigned char *searchName,
3013 __u64 * inode_number,
3014 const struct nls_table *nls_codepage, int remap)
3017 TRANSACTION2_QPI_REQ *pSMB = NULL;
3018 TRANSACTION2_QPI_RSP *pSMBr = NULL;
3019 int name_len, bytes_returned;
3020 __u16 params, byte_count;
3022 cFYI(1,("In GetSrvInodeNum for %s",searchName));
3026 GetInodeNumberRetry:
3027 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3033 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3035 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
3036 PATH_MAX,nls_codepage, remap);
3037 name_len++; /* trailing null */
3039 } else { /* BB improve the check for buffer overruns BB */
3040 name_len = strnlen(searchName, PATH_MAX);
3041 name_len++; /* trailing null */
3042 strncpy(pSMB->FileName, searchName, name_len);
3045 params = 2 /* level */ + 4 /* rsrvd */ + name_len /* incl null */ ;
3046 pSMB->TotalDataCount = 0;
3047 pSMB->MaxParameterCount = cpu_to_le16(2);
3048 /* BB find exact max data count below from sess structure BB */
3049 pSMB->MaxDataCount = cpu_to_le16(4000);
3050 pSMB->MaxSetupCount = 0;
3054 pSMB->Reserved2 = 0;
3055 pSMB->ParameterOffset = cpu_to_le16(offsetof(
3056 struct smb_com_transaction2_qpi_req ,InformationLevel) - 4);
3057 pSMB->DataCount = 0;
3058 pSMB->DataOffset = 0;
3059 pSMB->SetupCount = 1;
3060 pSMB->Reserved3 = 0;
3061 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
3062 byte_count = params + 1 /* pad */ ;
3063 pSMB->TotalParameterCount = cpu_to_le16(params);
3064 pSMB->ParameterCount = pSMB->TotalParameterCount;
3065 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_INTERNAL_INFO);
3066 pSMB->Reserved4 = 0;
3067 pSMB->hdr.smb_buf_length += byte_count;
3068 pSMB->ByteCount = cpu_to_le16(byte_count);
3070 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3071 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3073 cFYI(1, ("error %d in QueryInternalInfo", rc));
3075 /* decode response */
3076 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3077 if (rc || (pSMBr->ByteCount < 2))
3078 /* BB also check enough total bytes returned */
3079 /* If rc should we check for EOPNOSUPP and
3080 disable the srvino flag? or in caller? */
3081 rc = -EIO; /* bad smb */
3083 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3084 __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
3085 struct file_internal_info * pfinfo;
3086 /* BB Do we need a cast or hash here ? */
3088 cFYI(1, ("Illegal size ret in QryIntrnlInf"));
3090 goto GetInodeNumOut;
3092 pfinfo = (struct file_internal_info *)
3093 (data_offset + (char *) &pSMBr->hdr.Protocol);
3094 *inode_number = pfinfo->UniqueId;
3098 cifs_buf_release(pSMB);
3100 goto GetInodeNumberRetry;
3105 CIFSGetDFSRefer(const int xid, struct cifsSesInfo *ses,
3106 const unsigned char *searchName,
3107 unsigned char **targetUNCs,
3108 unsigned int *number_of_UNC_in_array,
3109 const struct nls_table *nls_codepage, int remap)
3111 /* TRANS2_GET_DFS_REFERRAL */
3112 TRANSACTION2_GET_DFS_REFER_REQ *pSMB = NULL;
3113 TRANSACTION2_GET_DFS_REFER_RSP *pSMBr = NULL;
3114 struct dfs_referral_level_3 * referrals = NULL;
3120 __u16 params, byte_count;
3121 *number_of_UNC_in_array = 0;
3124 cFYI(1, ("In GetDFSRefer the path %s", searchName));
3128 rc = smb_init(SMB_COM_TRANSACTION2, 15, NULL, (void **) &pSMB,
3133 /* server pointer checked in called function,
3134 but should never be null here anyway */
3135 pSMB->hdr.Mid = GetNextMid(ses->server);
3136 pSMB->hdr.Tid = ses->ipc_tid;
3137 pSMB->hdr.Uid = ses->Suid;
3138 if (ses->capabilities & CAP_STATUS32) {
3139 pSMB->hdr.Flags2 |= SMBFLG2_ERR_STATUS;
3141 if (ses->capabilities & CAP_DFS) {
3142 pSMB->hdr.Flags2 |= SMBFLG2_DFS;
3145 if (ses->capabilities & CAP_UNICODE) {
3146 pSMB->hdr.Flags2 |= SMBFLG2_UNICODE;
3148 cifsConvertToUCS((__le16 *) pSMB->RequestFileName,
3149 searchName, PATH_MAX, nls_codepage, remap);
3150 name_len++; /* trailing null */
3152 } else { /* BB improve the check for buffer overruns BB */
3153 name_len = strnlen(searchName, PATH_MAX);
3154 name_len++; /* trailing null */
3155 strncpy(pSMB->RequestFileName, searchName, name_len);
3158 params = 2 /* level */ + name_len /*includes null */ ;
3159 pSMB->TotalDataCount = 0;
3160 pSMB->DataCount = 0;
3161 pSMB->DataOffset = 0;
3162 pSMB->MaxParameterCount = 0;
3163 pSMB->MaxDataCount = cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
3164 pSMB->MaxSetupCount = 0;
3168 pSMB->Reserved2 = 0;
3169 pSMB->ParameterOffset = cpu_to_le16(offsetof(
3170 struct smb_com_transaction2_get_dfs_refer_req, MaxReferralLevel) - 4);
3171 pSMB->SetupCount = 1;
3172 pSMB->Reserved3 = 0;
3173 pSMB->SubCommand = cpu_to_le16(TRANS2_GET_DFS_REFERRAL);
3174 byte_count = params + 3 /* pad */ ;
3175 pSMB->ParameterCount = cpu_to_le16(params);
3176 pSMB->TotalParameterCount = pSMB->ParameterCount;
3177 pSMB->MaxReferralLevel = cpu_to_le16(3);
3178 pSMB->hdr.smb_buf_length += byte_count;
3179 pSMB->ByteCount = cpu_to_le16(byte_count);
3181 rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB,
3182 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3184 cFYI(1, ("Send error in GetDFSRefer = %d", rc));
3185 } else { /* decode response */
3186 /* BB Add logic to parse referrals here */
3187 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3189 if (rc || (pSMBr->ByteCount < 17)) /* BB also check enough total bytes returned */
3190 rc = -EIO; /* bad smb */
3192 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3193 __u16 data_count = le16_to_cpu(pSMBr->t2.DataCount);
3196 ("Decoding GetDFSRefer response. BCC: %d Offset %d",
3197 pSMBr->ByteCount, data_offset));
3199 (struct dfs_referral_level_3 *)
3200 (8 /* sizeof start of data block */ +
3202 (char *) &pSMBr->hdr.Protocol);
3203 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",
3204 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)));
3205 /* BB This field is actually two bytes in from start of
3206 data block so we could do safety check that DataBlock
3207 begins at address of pSMBr->NumberOfReferrals */
3208 *number_of_UNC_in_array = le16_to_cpu(pSMBr->NumberOfReferrals);
3210 /* BB Fix below so can return more than one referral */
3211 if(*number_of_UNC_in_array > 1)
3212 *number_of_UNC_in_array = 1;
3214 /* get the length of the strings describing refs */
3216 for(i=0;i<*number_of_UNC_in_array;i++) {
3217 /* make sure that DfsPathOffset not past end */
3218 __u16 offset = le16_to_cpu(referrals->DfsPathOffset);
3219 if (offset > data_count) {
3220 /* if invalid referral, stop here and do
3221 not try to copy any more */
3222 *number_of_UNC_in_array = i;
3225 temp = ((char *)referrals) + offset;
3227 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
3228 name_len += UniStrnlen((wchar_t *)temp,data_count);
3230 name_len += strnlen(temp,data_count);
3233 /* BB add check that referral pointer does not fall off end PDU */
3236 /* BB add check for name_len bigger than bcc */
3238 kmalloc(name_len+1+ (*number_of_UNC_in_array),GFP_KERNEL);
3239 if(*targetUNCs == NULL) {
3243 /* copy the ref strings */
3245 (struct dfs_referral_level_3 *)
3246 (8 /* sizeof data hdr */ +
3248 (char *) &pSMBr->hdr.Protocol);
3250 for(i=0;i<*number_of_UNC_in_array;i++) {
3251 temp = ((char *)referrals) + le16_to_cpu(referrals->DfsPathOffset);
3252 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
3253 cifs_strfromUCS_le(*targetUNCs,
3254 (__le16 *) temp, name_len, nls_codepage);
3256 strncpy(*targetUNCs,temp,name_len);
3258 /* BB update target_uncs pointers */
3268 cifs_buf_release(pSMB);
3276 /* Query File System Info such as free space to old servers such as Win 9x */
3278 SMBOldQFSInfo(const int xid, struct cifsTconInfo *tcon, struct kstatfs *FSData)
3280 /* level 0x01 SMB_QUERY_FILE_SYSTEM_INFO */
3281 TRANSACTION2_QFSI_REQ *pSMB = NULL;
3282 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
3283 FILE_SYSTEM_ALLOC_INFO *response_data;
3285 int bytes_returned = 0;
3286 __u16 params, byte_count;
3288 cFYI(1, ("OldQFSInfo"));
3290 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3294 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3299 params = 2; /* level */
3300 pSMB->TotalDataCount = 0;
3301 pSMB->MaxParameterCount = cpu_to_le16(2);
3302 pSMB->MaxDataCount = cpu_to_le16(1000);
3303 pSMB->MaxSetupCount = 0;
3307 pSMB->Reserved2 = 0;
3308 byte_count = params + 1 /* pad */ ;
3309 pSMB->TotalParameterCount = cpu_to_le16(params);
3310 pSMB->ParameterCount = pSMB->TotalParameterCount;
3311 pSMB->ParameterOffset = cpu_to_le16(offsetof(
3312 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
3313 pSMB->DataCount = 0;
3314 pSMB->DataOffset = 0;
3315 pSMB->SetupCount = 1;
3316 pSMB->Reserved3 = 0;
3317 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
3318 pSMB->InformationLevel = cpu_to_le16(SMB_INFO_ALLOCATION);
3319 pSMB->hdr.smb_buf_length += byte_count;
3320 pSMB->ByteCount = cpu_to_le16(byte_count);
3322 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3323 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3325 cFYI(1, ("Send error in QFSInfo = %d", rc));
3326 } else { /* decode response */
3327 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3329 if (rc || (pSMBr->ByteCount < 18))
3330 rc = -EIO; /* bad smb */
3332 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3333 cFYI(1,("qfsinf resp BCC: %d Offset %d",
3334 pSMBr->ByteCount, data_offset));
3337 (FILE_SYSTEM_ALLOC_INFO *)
3338 (((char *) &pSMBr->hdr.Protocol) + data_offset);
3340 le16_to_cpu(response_data->BytesPerSector) *
3341 le32_to_cpu(response_data->
3342 SectorsPerAllocationUnit);
3344 le32_to_cpu(response_data->TotalAllocationUnits);
3345 FSData->f_bfree = FSData->f_bavail =
3346 le32_to_cpu(response_data->FreeAllocationUnits);
3348 ("Blocks: %lld Free: %lld Block size %ld",
3349 (unsigned long long)FSData->f_blocks,
3350 (unsigned long long)FSData->f_bfree,
3354 cifs_buf_release(pSMB);
3357 goto oldQFSInfoRetry;
3363 CIFSSMBQFSInfo(const int xid, struct cifsTconInfo *tcon, struct kstatfs *FSData)
3365 /* level 0x103 SMB_QUERY_FILE_SYSTEM_INFO */
3366 TRANSACTION2_QFSI_REQ *pSMB = NULL;
3367 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
3368 FILE_SYSTEM_INFO *response_data;
3370 int bytes_returned = 0;
3371 __u16 params, byte_count;
3373 cFYI(1, ("In QFSInfo"));
3375 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3380 params = 2; /* level */
3381 pSMB->TotalDataCount = 0;
3382 pSMB->MaxParameterCount = cpu_to_le16(2);
3383 pSMB->MaxDataCount = cpu_to_le16(1000);
3384 pSMB->MaxSetupCount = 0;
3388 pSMB->Reserved2 = 0;
3389 byte_count = params + 1 /* pad */ ;
3390 pSMB->TotalParameterCount = cpu_to_le16(params);
3391 pSMB->ParameterCount = pSMB->TotalParameterCount;
3392 pSMB->ParameterOffset = cpu_to_le16(offsetof(
3393 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
3394 pSMB->DataCount = 0;
3395 pSMB->DataOffset = 0;
3396 pSMB->SetupCount = 1;
3397 pSMB->Reserved3 = 0;
3398 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
3399 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_SIZE_INFO);
3400 pSMB->hdr.smb_buf_length += byte_count;
3401 pSMB->ByteCount = cpu_to_le16(byte_count);
3403 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3404 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3406 cFYI(1, ("Send error in QFSInfo = %d", rc));
3407 } else { /* decode response */
3408 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3410 if (rc || (pSMBr->ByteCount < 24))
3411 rc = -EIO; /* bad smb */
3413 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3417 *) (((char *) &pSMBr->hdr.Protocol) +
3420 le32_to_cpu(response_data->BytesPerSector) *
3421 le32_to_cpu(response_data->
3422 SectorsPerAllocationUnit);
3424 le64_to_cpu(response_data->TotalAllocationUnits);
3425 FSData->f_bfree = FSData->f_bavail =
3426 le64_to_cpu(response_data->FreeAllocationUnits);
3428 ("Blocks: %lld Free: %lld Block size %ld",
3429 (unsigned long long)FSData->f_blocks,
3430 (unsigned long long)FSData->f_bfree,
3434 cifs_buf_release(pSMB);
3443 CIFSSMBQFSAttributeInfo(const int xid, struct cifsTconInfo *tcon)
3445 /* level 0x105 SMB_QUERY_FILE_SYSTEM_INFO */
3446 TRANSACTION2_QFSI_REQ *pSMB = NULL;
3447 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
3448 FILE_SYSTEM_ATTRIBUTE_INFO *response_data;
3450 int bytes_returned = 0;
3451 __u16 params, byte_count;
3453 cFYI(1, ("In QFSAttributeInfo"));
3455 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3460 params = 2; /* level */
3461 pSMB->TotalDataCount = 0;
3462 pSMB->MaxParameterCount = cpu_to_le16(2);
3463 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
3464 pSMB->MaxSetupCount = 0;
3468 pSMB->Reserved2 = 0;
3469 byte_count = params + 1 /* pad */ ;
3470 pSMB->TotalParameterCount = cpu_to_le16(params);
3471 pSMB->ParameterCount = pSMB->TotalParameterCount;
3472 pSMB->ParameterOffset = cpu_to_le16(offsetof(
3473 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
3474 pSMB->DataCount = 0;
3475 pSMB->DataOffset = 0;
3476 pSMB->SetupCount = 1;
3477 pSMB->Reserved3 = 0;
3478 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
3479 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_ATTRIBUTE_INFO);
3480 pSMB->hdr.smb_buf_length += byte_count;
3481 pSMB->ByteCount = cpu_to_le16(byte_count);
3483 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3484 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3486 cERROR(1, ("Send error in QFSAttributeInfo = %d", rc));
3487 } else { /* decode response */
3488 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3490 if (rc || (pSMBr->ByteCount < 13)) { /* BB also check enough bytes returned */
3491 rc = -EIO; /* bad smb */
3493 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3495 (FILE_SYSTEM_ATTRIBUTE_INFO
3496 *) (((char *) &pSMBr->hdr.Protocol) +
3498 memcpy(&tcon->fsAttrInfo, response_data,
3499 sizeof (FILE_SYSTEM_ATTRIBUTE_INFO));
3502 cifs_buf_release(pSMB);
3505 goto QFSAttributeRetry;
3511 CIFSSMBQFSDeviceInfo(const int xid, struct cifsTconInfo *tcon)
3513 /* level 0x104 SMB_QUERY_FILE_SYSTEM_INFO */
3514 TRANSACTION2_QFSI_REQ *pSMB = NULL;
3515 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
3516 FILE_SYSTEM_DEVICE_INFO *response_data;
3518 int bytes_returned = 0;
3519 __u16 params, byte_count;
3521 cFYI(1, ("In QFSDeviceInfo"));
3523 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3528 params = 2; /* level */
3529 pSMB->TotalDataCount = 0;
3530 pSMB->MaxParameterCount = cpu_to_le16(2);
3531 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
3532 pSMB->MaxSetupCount = 0;
3536 pSMB->Reserved2 = 0;
3537 byte_count = params + 1 /* pad */ ;
3538 pSMB->TotalParameterCount = cpu_to_le16(params);
3539 pSMB->ParameterCount = pSMB->TotalParameterCount;
3540 pSMB->ParameterOffset = cpu_to_le16(offsetof(
3541 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
3543 pSMB->DataCount = 0;
3544 pSMB->DataOffset = 0;
3545 pSMB->SetupCount = 1;
3546 pSMB->Reserved3 = 0;
3547 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
3548 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_DEVICE_INFO);
3549 pSMB->hdr.smb_buf_length += byte_count;
3550 pSMB->ByteCount = cpu_to_le16(byte_count);
3552 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3553 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3555 cFYI(1, ("Send error in QFSDeviceInfo = %d", rc));
3556 } else { /* decode response */
3557 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3559 if (rc || (pSMBr->ByteCount < sizeof (FILE_SYSTEM_DEVICE_INFO)))
3560 rc = -EIO; /* bad smb */
3562 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3564 (FILE_SYSTEM_DEVICE_INFO *)
3565 (((char *) &pSMBr->hdr.Protocol) +
3567 memcpy(&tcon->fsDevInfo, response_data,
3568 sizeof (FILE_SYSTEM_DEVICE_INFO));
3571 cifs_buf_release(pSMB);
3574 goto QFSDeviceRetry;
3580 CIFSSMBQFSUnixInfo(const int xid, struct cifsTconInfo *tcon)
3582 /* level 0x200 SMB_QUERY_CIFS_UNIX_INFO */
3583 TRANSACTION2_QFSI_REQ *pSMB = NULL;
3584 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
3585 FILE_SYSTEM_UNIX_INFO *response_data;
3587 int bytes_returned = 0;
3588 __u16 params, byte_count;
3590 cFYI(1, ("In QFSUnixInfo"));
3592 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3597 params = 2; /* level */
3598 pSMB->TotalDataCount = 0;
3599 pSMB->DataCount = 0;
3600 pSMB->DataOffset = 0;
3601 pSMB->MaxParameterCount = cpu_to_le16(2);
3602 pSMB->MaxDataCount = cpu_to_le16(100); /* BB find exact max SMB PDU from sess structure BB */
3603 pSMB->MaxSetupCount = 0;
3607 pSMB->Reserved2 = 0;
3608 byte_count = params + 1 /* pad */ ;
3609 pSMB->ParameterCount = cpu_to_le16(params);
3610 pSMB->TotalParameterCount = pSMB->ParameterCount;
3611 pSMB->ParameterOffset = cpu_to_le16(offsetof(struct
3612 smb_com_transaction2_qfsi_req, InformationLevel) - 4);
3613 pSMB->SetupCount = 1;
3614 pSMB->Reserved3 = 0;
3615 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
3616 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_CIFS_UNIX_INFO);
3617 pSMB->hdr.smb_buf_length += byte_count;
3618 pSMB->ByteCount = cpu_to_le16(byte_count);
3620 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3621 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3623 cERROR(1, ("Send error in QFSUnixInfo = %d", rc));
3624 } else { /* decode response */
3625 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3627 if (rc || (pSMBr->ByteCount < 13)) {
3628 rc = -EIO; /* bad smb */
3630 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3632 (FILE_SYSTEM_UNIX_INFO
3633 *) (((char *) &pSMBr->hdr.Protocol) +
3635 memcpy(&tcon->fsUnixInfo, response_data,
3636 sizeof (FILE_SYSTEM_UNIX_INFO));
3639 cifs_buf_release(pSMB);
3649 CIFSSMBSetFSUnixInfo(const int xid, struct cifsTconInfo *tcon, __u64 cap)
3651 /* level 0x200 SMB_SET_CIFS_UNIX_INFO */
3652 TRANSACTION2_SETFSI_REQ *pSMB = NULL;
3653 TRANSACTION2_SETFSI_RSP *pSMBr = NULL;
3655 int bytes_returned = 0;
3656 __u16 params, param_offset, offset, byte_count;
3658 cFYI(1, ("In SETFSUnixInfo"));
3660 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3665 params = 4; /* 2 bytes zero followed by info level. */
3666 pSMB->MaxSetupCount = 0;
3670 pSMB->Reserved2 = 0;
3671 param_offset = offsetof(struct smb_com_transaction2_setfsi_req, FileNum) - 4;
3672 offset = param_offset + params;
3674 pSMB->MaxParameterCount = cpu_to_le16(4);
3675 pSMB->MaxDataCount = cpu_to_le16(100); /* BB find exact max SMB PDU from sess structure BB */
3676 pSMB->SetupCount = 1;
3677 pSMB->Reserved3 = 0;
3678 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FS_INFORMATION);
3679 byte_count = 1 /* pad */ + params + 12;
3681 pSMB->DataCount = cpu_to_le16(12);
3682 pSMB->ParameterCount = cpu_to_le16(params);
3683 pSMB->TotalDataCount = pSMB->DataCount;
3684 pSMB->TotalParameterCount = pSMB->ParameterCount;
3685 pSMB->ParameterOffset = cpu_to_le16(param_offset);
3686 pSMB->DataOffset = cpu_to_le16(offset);
3690 pSMB->InformationLevel = cpu_to_le16(SMB_SET_CIFS_UNIX_INFO);
3693 pSMB->ClientUnixMajor = cpu_to_le16(CIFS_UNIX_MAJOR_VERSION);
3694 pSMB->ClientUnixMinor = cpu_to_le16(CIFS_UNIX_MINOR_VERSION);
3695 pSMB->ClientUnixCap = cpu_to_le64(cap);
3697 pSMB->hdr.smb_buf_length += byte_count;
3698 pSMB->ByteCount = cpu_to_le16(byte_count);
3700 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3701 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3703 cERROR(1, ("Send error in SETFSUnixInfo = %d", rc));
3704 } else { /* decode response */
3705 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3707 rc = -EIO; /* bad smb */
3710 cifs_buf_release(pSMB);
3713 goto SETFSUnixRetry;
3721 CIFSSMBQFSPosixInfo(const int xid, struct cifsTconInfo *tcon,
3722 struct kstatfs *FSData)
3724 /* level 0x201 SMB_QUERY_CIFS_POSIX_INFO */
3725 TRANSACTION2_QFSI_REQ *pSMB = NULL;
3726 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
3727 FILE_SYSTEM_POSIX_INFO *response_data;
3729 int bytes_returned = 0;
3730 __u16 params, byte_count;
3732 cFYI(1, ("In QFSPosixInfo"));
3734 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3739 params = 2; /* level */
3740 pSMB->TotalDataCount = 0;
3741 pSMB->DataCount = 0;
3742 pSMB->DataOffset = 0;
3743 pSMB->MaxParameterCount = cpu_to_le16(2);
3744 pSMB->MaxDataCount = cpu_to_le16(100); /* BB find exact max SMB PDU from sess structure BB */
3745 pSMB->MaxSetupCount = 0;
3749 pSMB->Reserved2 = 0;
3750 byte_count = params + 1 /* pad */ ;
3751 pSMB->ParameterCount = cpu_to_le16(params);
3752 pSMB->TotalParameterCount = pSMB->ParameterCount;
3753 pSMB->ParameterOffset = cpu_to_le16(offsetof(struct
3754 smb_com_transaction2_qfsi_req, InformationLevel) - 4);
3755 pSMB->SetupCount = 1;
3756 pSMB->Reserved3 = 0;
3757 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
3758 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_POSIX_FS_INFO);
3759 pSMB->hdr.smb_buf_length += byte_count;
3760 pSMB->ByteCount = cpu_to_le16(byte_count);
3762 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3763 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3765 cFYI(1, ("Send error in QFSUnixInfo = %d", rc));
3766 } else { /* decode response */
3767 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3769 if (rc || (pSMBr->ByteCount < 13)) {
3770 rc = -EIO; /* bad smb */
3772 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3774 (FILE_SYSTEM_POSIX_INFO
3775 *) (((char *) &pSMBr->hdr.Protocol) +
3778 le32_to_cpu(response_data->BlockSize);
3780 le64_to_cpu(response_data->TotalBlocks);
3782 le64_to_cpu(response_data->BlocksAvail);
3783 if(response_data->UserBlocksAvail == cpu_to_le64(-1)) {
3784 FSData->f_bavail = FSData->f_bfree;
3787 le64_to_cpu(response_data->UserBlocksAvail);
3789 if(response_data->TotalFileNodes != cpu_to_le64(-1))
3791 le64_to_cpu(response_data->TotalFileNodes);
3792 if(response_data->FreeFileNodes != cpu_to_le64(-1))
3794 le64_to_cpu(response_data->FreeFileNodes);
3797 cifs_buf_release(pSMB);
3806 /* We can not use write of zero bytes trick to
3807 set file size due to need for large file support. Also note that
3808 this SetPathInfo is preferred to SetFileInfo based method in next
3809 routine which is only needed to work around a sharing violation bug
3810 in Samba which this routine can run into */
3813 CIFSSMBSetEOF(const int xid, struct cifsTconInfo *tcon, const char *fileName,
3814 __u64 size, int SetAllocation,
3815 const struct nls_table *nls_codepage, int remap)
3817 struct smb_com_transaction2_spi_req *pSMB = NULL;
3818 struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
3819 struct file_end_of_file_info *parm_data;
3822 int bytes_returned = 0;
3823 __u16 params, byte_count, data_count, param_offset, offset;
3825 cFYI(1, ("In SetEOF"));
3827 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3832 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3834 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
3835 PATH_MAX, nls_codepage, remap);
3836 name_len++; /* trailing null */
3838 } else { /* BB improve the check for buffer overruns BB */
3839 name_len = strnlen(fileName, PATH_MAX);
3840 name_len++; /* trailing null */
3841 strncpy(pSMB->FileName, fileName, name_len);
3843 params = 6 + name_len;
3844 data_count = sizeof (struct file_end_of_file_info);
3845 pSMB->MaxParameterCount = cpu_to_le16(2);
3846 pSMB->MaxDataCount = cpu_to_le16(4100);
3847 pSMB->MaxSetupCount = 0;
3851 pSMB->Reserved2 = 0;
3852 param_offset = offsetof(struct smb_com_transaction2_spi_req,
3853 InformationLevel) - 4;
3854 offset = param_offset + params;
3856 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
3857 pSMB->InformationLevel =
3858 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2);
3860 pSMB->InformationLevel =
3861 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO);
3862 } else /* Set File Size */ {
3863 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
3864 pSMB->InformationLevel =
3865 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO2);
3867 pSMB->InformationLevel =
3868 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO);
3872 (struct file_end_of_file_info *) (((char *) &pSMB->hdr.Protocol) +
3874 pSMB->ParameterOffset = cpu_to_le16(param_offset);
3875 pSMB->DataOffset = cpu_to_le16(offset);
3876 pSMB->SetupCount = 1;
3877 pSMB->Reserved3 = 0;
3878 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
3879 byte_count = 3 /* pad */ + params + data_count;
3880 pSMB->DataCount = cpu_to_le16(data_count);
3881 pSMB->TotalDataCount = pSMB->DataCount;
3882 pSMB->ParameterCount = cpu_to_le16(params);
3883 pSMB->TotalParameterCount = pSMB->ParameterCount;
3884 pSMB->Reserved4 = 0;
3885 pSMB->hdr.smb_buf_length += byte_count;
3886 parm_data->FileSize = cpu_to_le64(size);
3887 pSMB->ByteCount = cpu_to_le16(byte_count);
3888 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3889 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3891 cFYI(1, ("SetPathInfo (file size) returned %d", rc));
3894 cifs_buf_release(pSMB);
3903 CIFSSMBSetFileSize(const int xid, struct cifsTconInfo *tcon, __u64 size,
3904 __u16 fid, __u32 pid_of_opener, int SetAllocation)
3906 struct smb_com_transaction2_sfi_req *pSMB = NULL;
3907 struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
3909 struct file_end_of_file_info *parm_data;
3911 int bytes_returned = 0;
3912 __u16 params, param_offset, offset, byte_count, count;
3914 cFYI(1, ("SetFileSize (via SetFileInfo) %lld",
3916 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
3921 pSMBr = (struct smb_com_transaction2_sfi_rsp *)pSMB;
3923 pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
3924 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));
3927 pSMB->MaxSetupCount = 0;
3931 pSMB->Reserved2 = 0;
3932 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
3933 offset = param_offset + params;
3935 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
3937 count = sizeof(struct file_end_of_file_info);
3938 pSMB->MaxParameterCount = cpu_to_le16(2);
3939 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB PDU from sess */
3940 pSMB->SetupCount = 1;
3941 pSMB->Reserved3 = 0;
3942 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
3943 byte_count = 3 /* pad */ + params + count;
3944 pSMB->DataCount = cpu_to_le16(count);
3945 pSMB->ParameterCount = cpu_to_le16(params);
3946 pSMB->TotalDataCount = pSMB->DataCount;
3947 pSMB->TotalParameterCount = pSMB->ParameterCount;
3948 pSMB->ParameterOffset = cpu_to_le16(param_offset);
3950 (struct file_end_of_file_info *) (((char *) &pSMB->hdr.Protocol) +
3952 pSMB->DataOffset = cpu_to_le16(offset);
3953 parm_data->FileSize = cpu_to_le64(size);
3956 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
3957 pSMB->InformationLevel =
3958 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2);
3960 pSMB->InformationLevel =
3961 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO);
3962 } else /* Set File Size */ {
3963 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
3964 pSMB->InformationLevel =
3965 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO2);
3967 pSMB->InformationLevel =
3968 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO);
3970 pSMB->Reserved4 = 0;
3971 pSMB->hdr.smb_buf_length += byte_count;
3972 pSMB->ByteCount = cpu_to_le16(byte_count);
3973 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3974 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3977 ("Send error in SetFileInfo (SetFileSize) = %d",
3982 cifs_small_buf_release(pSMB);
3984 /* Note: On -EAGAIN error only caller can retry on handle based calls
3985 since file handle passed in no longer valid */
3990 /* Some legacy servers such as NT4 require that the file times be set on
3991 an open handle, rather than by pathname - this is awkward due to
3992 potential access conflicts on the open, but it is unavoidable for these
3993 old servers since the only other choice is to go from 100 nanosecond DCE
3994 time and resort to the original setpathinfo level which takes the ancient
3995 DOS time format with 2 second granularity */
3997 CIFSSMBSetFileTimes(const int xid, struct cifsTconInfo *tcon, const FILE_BASIC_INFO * data,
4000 struct smb_com_transaction2_sfi_req *pSMB = NULL;
4001 struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
4004 int bytes_returned = 0;
4005 __u16 params, param_offset, offset, byte_count, count;
4007 cFYI(1, ("Set Times (via SetFileInfo)"));
4008 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
4013 pSMBr = (struct smb_com_transaction2_sfi_rsp *)pSMB;
4015 /* At this point there is no need to override the current pid
4016 with the pid of the opener, but that could change if we someday
4017 use an existing handle (rather than opening one on the fly) */
4018 /* pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
4019 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));*/
4022 pSMB->MaxSetupCount = 0;
4026 pSMB->Reserved2 = 0;
4027 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
4028 offset = param_offset + params;
4030 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
4032 count = sizeof (FILE_BASIC_INFO);
4033 pSMB->MaxParameterCount = cpu_to_le16(2);
4034 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB PDU from sess */
4035 pSMB->SetupCount = 1;
4036 pSMB->Reserved3 = 0;
4037 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
4038 byte_count = 3 /* pad */ + params + count;
4039 pSMB->DataCount = cpu_to_le16(count);
4040 pSMB->ParameterCount = cpu_to_le16(params);
4041 pSMB->TotalDataCount = pSMB->DataCount;
4042 pSMB->TotalParameterCount = pSMB->ParameterCount;
4043 pSMB->ParameterOffset = cpu_to_le16(param_offset);
4044 pSMB->DataOffset = cpu_to_le16(offset);
4046 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
4047 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO2);
4049 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO);
4050 pSMB->Reserved4 = 0;
4051 pSMB->hdr.smb_buf_length += byte_count;
4052 pSMB->ByteCount = cpu_to_le16(byte_count);
4053 memcpy(data_offset,data,sizeof(FILE_BASIC_INFO));
4054 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4055 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4057 cFYI(1,("Send error in Set Time (SetFileInfo) = %d",rc));
4060 cifs_small_buf_release(pSMB);
4062 /* Note: On -EAGAIN error only caller can retry on handle based calls
4063 since file handle passed in no longer valid */
4070 CIFSSMBSetTimes(const int xid, struct cifsTconInfo *tcon, const char *fileName,
4071 const FILE_BASIC_INFO * data,
4072 const struct nls_table *nls_codepage, int remap)
4074 TRANSACTION2_SPI_REQ *pSMB = NULL;
4075 TRANSACTION2_SPI_RSP *pSMBr = NULL;
4078 int bytes_returned = 0;
4080 __u16 params, param_offset, offset, byte_count, count;
4082 cFYI(1, ("In SetTimes"));
4085 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4090 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4092 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
4093 PATH_MAX, nls_codepage, remap);
4094 name_len++; /* trailing null */
4096 } else { /* BB improve the check for buffer overruns BB */
4097 name_len = strnlen(fileName, PATH_MAX);
4098 name_len++; /* trailing null */
4099 strncpy(pSMB->FileName, fileName, name_len);
4102 params = 6 + name_len;
4103 count = sizeof (FILE_BASIC_INFO);
4104 pSMB->MaxParameterCount = cpu_to_le16(2);
4105 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
4106 pSMB->MaxSetupCount = 0;
4110 pSMB->Reserved2 = 0;
4111 param_offset = offsetof(struct smb_com_transaction2_spi_req,
4112 InformationLevel) - 4;
4113 offset = param_offset + params;
4114 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
4115 pSMB->ParameterOffset = cpu_to_le16(param_offset);
4116 pSMB->DataOffset = cpu_to_le16(offset);
4117 pSMB->SetupCount = 1;
4118 pSMB->Reserved3 = 0;
4119 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
4120 byte_count = 3 /* pad */ + params + count;
4122 pSMB->DataCount = cpu_to_le16(count);
4123 pSMB->ParameterCount = cpu_to_le16(params);
4124 pSMB->TotalDataCount = pSMB->DataCount;
4125 pSMB->TotalParameterCount = pSMB->ParameterCount;
4126 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
4127 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO2);
4129 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO);
4130 pSMB->Reserved4 = 0;
4131 pSMB->hdr.smb_buf_length += byte_count;
4132 memcpy(data_offset, data, sizeof (FILE_BASIC_INFO));
4133 pSMB->ByteCount = cpu_to_le16(byte_count);
4134 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4135 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4137 cFYI(1, ("SetPathInfo (times) returned %d", rc));
4140 cifs_buf_release(pSMB);
4148 /* Can not be used to set time stamps yet (due to old DOS time format) */
4149 /* Can be used to set attributes */
4150 #if 0 /* Possibly not needed - since it turns out that strangely NT4 has a bug
4151 handling it anyway and NT4 was what we thought it would be needed for
4152 Do not delete it until we prove whether needed for Win9x though */
4154 CIFSSMBSetAttrLegacy(int xid, struct cifsTconInfo *tcon, char *fileName,
4155 __u16 dos_attrs, const struct nls_table *nls_codepage)
4157 SETATTR_REQ *pSMB = NULL;
4158 SETATTR_RSP *pSMBr = NULL;
4163 cFYI(1, ("In SetAttrLegacy"));
4166 rc = smb_init(SMB_COM_SETATTR, 8, tcon, (void **) &pSMB,
4171 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4173 ConvertToUCS((__le16 *) pSMB->fileName, fileName,
4174 PATH_MAX, nls_codepage);
4175 name_len++; /* trailing null */
4177 } else { /* BB improve the check for buffer overruns BB */
4178 name_len = strnlen(fileName, PATH_MAX);
4179 name_len++; /* trailing null */
4180 strncpy(pSMB->fileName, fileName, name_len);
4182 pSMB->attr = cpu_to_le16(dos_attrs);
4183 pSMB->BufferFormat = 0x04;
4184 pSMB->hdr.smb_buf_length += name_len + 1;
4185 pSMB->ByteCount = cpu_to_le16(name_len + 1);
4186 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4187 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4189 cFYI(1, ("Error in LegacySetAttr = %d", rc));
4192 cifs_buf_release(pSMB);
4195 goto SetAttrLgcyRetry;
4199 #endif /* temporarily unneeded SetAttr legacy function */
4202 CIFSSMBUnixSetPerms(const int xid, struct cifsTconInfo *tcon,
4203 char *fileName, __u64 mode, __u64 uid, __u64 gid,
4204 dev_t device, const struct nls_table *nls_codepage,
4207 TRANSACTION2_SPI_REQ *pSMB = NULL;
4208 TRANSACTION2_SPI_RSP *pSMBr = NULL;
4211 int bytes_returned = 0;
4212 FILE_UNIX_BASIC_INFO *data_offset;
4213 __u16 params, param_offset, offset, count, byte_count;
4215 cFYI(1, ("In SetUID/GID/Mode"));
4217 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4222 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4224 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
4225 PATH_MAX, nls_codepage, remap);
4226 name_len++; /* trailing null */
4228 } else { /* BB improve the check for buffer overruns BB */
4229 name_len = strnlen(fileName, PATH_MAX);
4230 name_len++; /* trailing null */
4231 strncpy(pSMB->FileName, fileName, name_len);
4234 params = 6 + name_len;
4235 count = sizeof (FILE_UNIX_BASIC_INFO);
4236 pSMB->MaxParameterCount = cpu_to_le16(2);
4237 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
4238 pSMB->MaxSetupCount = 0;
4242 pSMB->Reserved2 = 0;
4243 param_offset = offsetof(struct smb_com_transaction2_spi_req,
4244 InformationLevel) - 4;
4245 offset = param_offset + params;
4247 (FILE_UNIX_BASIC_INFO *) ((char *) &pSMB->hdr.Protocol +
4249 memset(data_offset, 0, count);
4250 pSMB->DataOffset = cpu_to_le16(offset);
4251 pSMB->ParameterOffset = cpu_to_le16(param_offset);
4252 pSMB->SetupCount = 1;
4253 pSMB->Reserved3 = 0;
4254 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
4255 byte_count = 3 /* pad */ + params + count;
4256 pSMB->ParameterCount = cpu_to_le16(params);
4257 pSMB->DataCount = cpu_to_le16(count);
4258 pSMB->TotalParameterCount = pSMB->ParameterCount;
4259 pSMB->TotalDataCount = pSMB->DataCount;
4260 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_BASIC);
4261 pSMB->Reserved4 = 0;
4262 pSMB->hdr.smb_buf_length += byte_count;
4263 data_offset->Uid = cpu_to_le64(uid);
4264 data_offset->Gid = cpu_to_le64(gid);
4265 /* better to leave device as zero when it is */
4266 data_offset->DevMajor = cpu_to_le64(MAJOR(device));
4267 data_offset->DevMinor = cpu_to_le64(MINOR(device));
4268 data_offset->Permissions = cpu_to_le64(mode);
4271 data_offset->Type = cpu_to_le32(UNIX_FILE);
4272 else if(S_ISDIR(mode))
4273 data_offset->Type = cpu_to_le32(UNIX_DIR);
4274 else if(S_ISLNK(mode))
4275 data_offset->Type = cpu_to_le32(UNIX_SYMLINK);
4276 else if(S_ISCHR(mode))
4277 data_offset->Type = cpu_to_le32(UNIX_CHARDEV);
4278 else if(S_ISBLK(mode))
4279 data_offset->Type = cpu_to_le32(UNIX_BLOCKDEV);
4280 else if(S_ISFIFO(mode))
4281 data_offset->Type = cpu_to_le32(UNIX_FIFO);
4282 else if(S_ISSOCK(mode))
4283 data_offset->Type = cpu_to_le32(UNIX_SOCKET);
4286 pSMB->ByteCount = cpu_to_le16(byte_count);
4287 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4288 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4290 cFYI(1, ("SetPathInfo (perms) returned %d", rc));
4294 cifs_buf_release(pSMB);
4300 int CIFSSMBNotify(const int xid, struct cifsTconInfo *tcon,
4301 const int notify_subdirs, const __u16 netfid,
4302 __u32 filter, struct file * pfile, int multishot,
4303 const struct nls_table *nls_codepage)
4306 struct smb_com_transaction_change_notify_req * pSMB = NULL;
4307 struct smb_com_transaction_change_notify_rsp * pSMBr = NULL;
4308 struct dir_notify_req *dnotify_req;
4311 cFYI(1, ("In CIFSSMBNotify for file handle %d",(int)netfid));
4312 rc = smb_init(SMB_COM_NT_TRANSACT, 23, tcon, (void **) &pSMB,
4317 pSMB->TotalParameterCount = 0 ;
4318 pSMB->TotalDataCount = 0;
4319 pSMB->MaxParameterCount = cpu_to_le32(2);
4320 /* BB find exact data count max from sess structure BB */
4321 pSMB->MaxDataCount = 0; /* same in little endian or be */
4322 pSMB->MaxSetupCount = 4;
4324 pSMB->ParameterOffset = 0;
4325 pSMB->DataCount = 0;
4326 pSMB->DataOffset = 0;
4327 pSMB->SetupCount = 4; /* single byte does not need le conversion */
4328 pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_NOTIFY_CHANGE);
4329 pSMB->ParameterCount = pSMB->TotalParameterCount;
4331 pSMB->WatchTree = 1; /* one byte - no le conversion needed */
4332 pSMB->Reserved2 = 0;
4333 pSMB->CompletionFilter = cpu_to_le32(filter);
4334 pSMB->Fid = netfid; /* file handle always le */
4335 pSMB->ByteCount = 0;
4337 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4338 (struct smb_hdr *) pSMBr, &bytes_returned, -1);
4340 cFYI(1, ("Error in Notify = %d", rc));
4342 /* Add file to outstanding requests */
4343 /* BB change to kmem cache alloc */
4344 dnotify_req = (struct dir_notify_req *) kmalloc(
4345 sizeof(struct dir_notify_req),
4348 dnotify_req->Pid = pSMB->hdr.Pid;
4349 dnotify_req->PidHigh = pSMB->hdr.PidHigh;
4350 dnotify_req->Mid = pSMB->hdr.Mid;
4351 dnotify_req->Tid = pSMB->hdr.Tid;
4352 dnotify_req->Uid = pSMB->hdr.Uid;
4353 dnotify_req->netfid = netfid;
4354 dnotify_req->pfile = pfile;
4355 dnotify_req->filter = filter;
4356 dnotify_req->multishot = multishot;
4357 spin_lock(&GlobalMid_Lock);
4358 list_add_tail(&dnotify_req->lhead,
4359 &GlobalDnotifyReqList);
4360 spin_unlock(&GlobalMid_Lock);
4364 cifs_buf_release(pSMB);
4367 #ifdef CONFIG_CIFS_XATTR
4369 CIFSSMBQAllEAs(const int xid, struct cifsTconInfo *tcon,
4370 const unsigned char *searchName,
4371 char * EAData, size_t buf_size,
4372 const struct nls_table *nls_codepage, int remap)
4374 /* BB assumes one setup word */
4375 TRANSACTION2_QPI_REQ *pSMB = NULL;
4376 TRANSACTION2_QPI_RSP *pSMBr = NULL;
4380 struct fea * temp_fea;
4382 __u16 params, byte_count;
4384 cFYI(1, ("In Query All EAs path %s", searchName));
4386 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4391 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4393 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
4394 PATH_MAX, nls_codepage, remap);
4395 name_len++; /* trailing null */
4397 } else { /* BB improve the check for buffer overruns BB */
4398 name_len = strnlen(searchName, PATH_MAX);
4399 name_len++; /* trailing null */
4400 strncpy(pSMB->FileName, searchName, name_len);
4403 params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */ ;
4404 pSMB->TotalDataCount = 0;
4405 pSMB->MaxParameterCount = cpu_to_le16(2);
4406 pSMB->MaxDataCount = cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
4407 pSMB->MaxSetupCount = 0;
4411 pSMB->Reserved2 = 0;
4412 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4413 struct smb_com_transaction2_qpi_req ,InformationLevel) - 4);
4414 pSMB->DataCount = 0;
4415 pSMB->DataOffset = 0;
4416 pSMB->SetupCount = 1;
4417 pSMB->Reserved3 = 0;
4418 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
4419 byte_count = params + 1 /* pad */ ;
4420 pSMB->TotalParameterCount = cpu_to_le16(params);
4421 pSMB->ParameterCount = pSMB->TotalParameterCount;
4422 pSMB->InformationLevel = cpu_to_le16(SMB_INFO_QUERY_ALL_EAS);
4423 pSMB->Reserved4 = 0;
4424 pSMB->hdr.smb_buf_length += byte_count;
4425 pSMB->ByteCount = cpu_to_le16(byte_count);
4427 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4428 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4430 cFYI(1, ("Send error in QueryAllEAs = %d", rc));
4431 } else { /* decode response */
4432 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4434 /* BB also check enough total bytes returned */
4435 /* BB we need to improve the validity checking
4436 of these trans2 responses */
4437 if (rc || (pSMBr->ByteCount < 4))
4438 rc = -EIO; /* bad smb */
4439 /* else if (pFindData){
4440 memcpy((char *) pFindData,
4441 (char *) &pSMBr->hdr.Protocol +
4444 /* check that length of list is not more than bcc */
4445 /* check that each entry does not go beyond length
4447 /* check that each element of each entry does not
4448 go beyond end of list */
4449 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4450 struct fealist * ea_response_data;
4452 /* validate_trans2_offsets() */
4453 /* BB to check if(start of smb + data_offset > &bcc+ bcc)*/
4454 ea_response_data = (struct fealist *)
4455 (((char *) &pSMBr->hdr.Protocol) +
4457 name_len = le32_to_cpu(ea_response_data->list_len);
4458 cFYI(1,("ea length %d", name_len));
4460 /* returned EA size zeroed at top of function */
4461 cFYI(1,("empty EA list returned from server"));
4463 /* account for ea list len */
4465 temp_fea = ea_response_data->list;
4466 temp_ptr = (char *)temp_fea;
4467 while(name_len > 0) {
4471 rc += temp_fea->name_len;
4472 /* account for prefix user. and trailing null */
4474 if(rc<(int)buf_size) {
4475 memcpy(EAData,"user.",5);
4477 memcpy(EAData,temp_ptr,temp_fea->name_len);
4478 EAData+=temp_fea->name_len;
4479 /* null terminate name */
4481 EAData = EAData + 1;
4482 } else if(buf_size == 0) {
4483 /* skip copy - calc size only */
4485 /* stop before overrun buffer */
4489 name_len -= temp_fea->name_len;
4490 temp_ptr += temp_fea->name_len;
4491 /* account for trailing null */
4494 value_len = le16_to_cpu(temp_fea->value_len);
4495 name_len -= value_len;
4496 temp_ptr += value_len;
4497 /* BB check that temp_ptr is still within smb BB*/
4498 /* no trailing null to account for in value len */
4499 /* go on to next EA */
4500 temp_fea = (struct fea *)temp_ptr;
4506 cifs_buf_release(pSMB);
4513 ssize_t CIFSSMBQueryEA(const int xid,struct cifsTconInfo * tcon,
4514 const unsigned char * searchName,const unsigned char * ea_name,
4515 unsigned char * ea_value, size_t buf_size,
4516 const struct nls_table *nls_codepage, int remap)
4518 TRANSACTION2_QPI_REQ *pSMB = NULL;
4519 TRANSACTION2_QPI_RSP *pSMBr = NULL;
4523 struct fea * temp_fea;
4525 __u16 params, byte_count;
4527 cFYI(1, ("In Query EA path %s", searchName));
4529 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4534 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4536 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
4537 PATH_MAX, nls_codepage, remap);
4538 name_len++; /* trailing null */
4540 } else { /* BB improve the check for buffer overruns BB */
4541 name_len = strnlen(searchName, PATH_MAX);
4542 name_len++; /* trailing null */
4543 strncpy(pSMB->FileName, searchName, name_len);
4546 params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */ ;
4547 pSMB->TotalDataCount = 0;
4548 pSMB->MaxParameterCount = cpu_to_le16(2);
4549 pSMB->MaxDataCount = cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
4550 pSMB->MaxSetupCount = 0;
4554 pSMB->Reserved2 = 0;
4555 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4556 struct smb_com_transaction2_qpi_req ,InformationLevel) - 4);
4557 pSMB->DataCount = 0;
4558 pSMB->DataOffset = 0;
4559 pSMB->SetupCount = 1;
4560 pSMB->Reserved3 = 0;
4561 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
4562 byte_count = params + 1 /* pad */ ;
4563 pSMB->TotalParameterCount = cpu_to_le16(params);
4564 pSMB->ParameterCount = pSMB->TotalParameterCount;
4565 pSMB->InformationLevel = cpu_to_le16(SMB_INFO_QUERY_ALL_EAS);
4566 pSMB->Reserved4 = 0;
4567 pSMB->hdr.smb_buf_length += byte_count;
4568 pSMB->ByteCount = cpu_to_le16(byte_count);
4570 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4571 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4573 cFYI(1, ("Send error in Query EA = %d", rc));
4574 } else { /* decode response */
4575 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4577 /* BB also check enough total bytes returned */
4578 /* BB we need to improve the validity checking
4579 of these trans2 responses */
4580 if (rc || (pSMBr->ByteCount < 4))
4581 rc = -EIO; /* bad smb */
4582 /* else if (pFindData){
4583 memcpy((char *) pFindData,
4584 (char *) &pSMBr->hdr.Protocol +
4587 /* check that length of list is not more than bcc */
4588 /* check that each entry does not go beyond length
4590 /* check that each element of each entry does not
4591 go beyond end of list */
4592 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4593 struct fealist * ea_response_data;
4595 /* validate_trans2_offsets() */
4596 /* BB to check if(start of smb + data_offset > &bcc+ bcc)*/
4597 ea_response_data = (struct fealist *)
4598 (((char *) &pSMBr->hdr.Protocol) +
4600 name_len = le32_to_cpu(ea_response_data->list_len);
4601 cFYI(1,("ea length %d", name_len));
4603 /* returned EA size zeroed at top of function */
4604 cFYI(1,("empty EA list returned from server"));
4606 /* account for ea list len */
4608 temp_fea = ea_response_data->list;
4609 temp_ptr = (char *)temp_fea;
4610 /* loop through checking if we have a matching
4611 name and then return the associated value */
4612 while(name_len > 0) {
4616 value_len = le16_to_cpu(temp_fea->value_len);
4617 /* BB validate that value_len falls within SMB,
4618 even though maximum for name_len is 255 */
4619 if(memcmp(temp_fea->name,ea_name,
4620 temp_fea->name_len) == 0) {
4623 /* account for prefix user. and trailing null */
4624 if(rc<=(int)buf_size) {
4626 temp_fea->name+temp_fea->name_len+1,
4628 /* ea values, unlike ea names,
4629 are not null terminated */
4630 } else if(buf_size == 0) {
4631 /* skip copy - calc size only */
4633 /* stop before overrun buffer */
4638 name_len -= temp_fea->name_len;
4639 temp_ptr += temp_fea->name_len;
4640 /* account for trailing null */
4643 name_len -= value_len;
4644 temp_ptr += value_len;
4645 /* no trailing null to account for in value len */
4646 /* go on to next EA */
4647 temp_fea = (struct fea *)temp_ptr;
4653 cifs_buf_release(pSMB);
4661 CIFSSMBSetEA(const int xid, struct cifsTconInfo *tcon, const char *fileName,
4662 const char * ea_name, const void * ea_value,
4663 const __u16 ea_value_len, const struct nls_table *nls_codepage,
4666 struct smb_com_transaction2_spi_req *pSMB = NULL;
4667 struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
4668 struct fealist *parm_data;
4671 int bytes_returned = 0;
4672 __u16 params, param_offset, byte_count, offset, count;
4674 cFYI(1, ("In SetEA"));
4676 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4681 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4683 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
4684 PATH_MAX, nls_codepage, remap);
4685 name_len++; /* trailing null */
4687 } else { /* BB improve the check for buffer overruns BB */
4688 name_len = strnlen(fileName, PATH_MAX);
4689 name_len++; /* trailing null */
4690 strncpy(pSMB->FileName, fileName, name_len);
4693 params = 6 + name_len;
4695 /* done calculating parms using name_len of file name,
4696 now use name_len to calculate length of ea name
4697 we are going to create in the inode xattrs */
4701 name_len = strnlen(ea_name,255);
4703 count = sizeof(*parm_data) + ea_value_len + name_len + 1;
4704 pSMB->MaxParameterCount = cpu_to_le16(2);
4705 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB size from sess */
4706 pSMB->MaxSetupCount = 0;
4710 pSMB->Reserved2 = 0;
4711 param_offset = offsetof(struct smb_com_transaction2_spi_req,
4712 InformationLevel) - 4;
4713 offset = param_offset + params;
4714 pSMB->InformationLevel =
4715 cpu_to_le16(SMB_SET_FILE_EA);
4718 (struct fealist *) (((char *) &pSMB->hdr.Protocol) +
4720 pSMB->ParameterOffset = cpu_to_le16(param_offset);
4721 pSMB->DataOffset = cpu_to_le16(offset);
4722 pSMB->SetupCount = 1;
4723 pSMB->Reserved3 = 0;
4724 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
4725 byte_count = 3 /* pad */ + params + count;
4726 pSMB->DataCount = cpu_to_le16(count);
4727 parm_data->list_len = cpu_to_le32(count);
4728 parm_data->list[0].EA_flags = 0;
4729 /* we checked above that name len is less than 255 */
4730 parm_data->list[0].name_len = (__u8)name_len;;
4731 /* EA names are always ASCII */
4733 strncpy(parm_data->list[0].name,ea_name,name_len);
4734 parm_data->list[0].name[name_len] = 0;
4735 parm_data->list[0].value_len = cpu_to_le16(ea_value_len);
4736 /* caller ensures that ea_value_len is less than 64K but
4737 we need to ensure that it fits within the smb */
4739 /*BB add length check that it would fit in negotiated SMB buffer size BB */
4740 /* if(ea_value_len > buffer_size - 512 (enough for header)) */
4742 memcpy(parm_data->list[0].name+name_len+1,ea_value,ea_value_len);
4744 pSMB->TotalDataCount = pSMB->DataCount;
4745 pSMB->ParameterCount = cpu_to_le16(params);
4746 pSMB->TotalParameterCount = pSMB->ParameterCount;
4747 pSMB->Reserved4 = 0;
4748 pSMB->hdr.smb_buf_length += byte_count;
4749 pSMB->ByteCount = cpu_to_le16(byte_count);
4750 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4751 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4753 cFYI(1, ("SetPathInfo (EA) returned %d", rc));
4756 cifs_buf_release(pSMB);