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;
1929 /* Initialize NT TRANSACT SMB into small smb request buffer.
1930 This assumes that all NT TRANSACTS that we init here have
1931 total parm and data under about 400 bytes (to fit in small cifs
1932 buffer size), which is the case so far, it easily fits. NB:
1933 Setup words themselves and ByteCount
1934 MaxSetupCount (size of returned setup area) and
1935 MaxParameterCount (returned parms size) must be set by caller */
1937 smb_init_ntransact(const __u16 sub_command, const int setup_count,
1938 const int parm_len, struct cifsTconInfo *tcon,
1943 struct smb_com_ntransact_req * pSMB;
1945 rc = small_smb_init(SMB_COM_NT_TRANSACT, 19 + setup_count, tcon,
1949 *ret_buf = (void *)pSMB;
1951 pSMB->TotalParameterCount = cpu_to_le32(parm_len);
1952 pSMB->TotalDataCount = 0;
1953 pSMB->MaxDataCount = cpu_to_le32((tcon->ses->server->maxBuf -
1954 MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
1955 pSMB->ParameterCount = pSMB->TotalParameterCount;
1956 pSMB->DataCount = pSMB->TotalDataCount;
1957 temp_offset = offsetof(struct smb_com_ntransact_req, Parms) +
1958 (setup_count * 2) - 4 /* for rfc1001 length itself */;
1959 pSMB->ParameterOffset = cpu_to_le32(temp_offset);
1960 pSMB->DataOffset = cpu_to_le32(temp_offset + parm_len);
1961 pSMB->SetupCount = setup_count; /* no need to le convert byte fields */
1962 pSMB->SubCommand = cpu_to_le16(sub_command);
1967 validate_ntransact(char * buf, char ** ppparm, char ** ppdata,
1968 int * pdatalen, int * pparmlen)
1971 __u32 data_count, data_offset, parm_count, parm_offset;
1972 struct smb_com_ntransact_rsp * pSMBr;
1977 pSMBr = (struct smb_com_ntransact_rsp *)buf;
1979 /* ByteCount was converted from little endian in SendReceive */
1980 end_of_smb = 2 /* sizeof byte count */ + pSMBr->ByteCount +
1981 (char *)&pSMBr->ByteCount;
1984 data_offset = le32_to_cpu(pSMBr->DataOffset);
1985 data_count = le32_to_cpu(pSMBr->DataCount);
1986 parm_offset = le32_to_cpu(pSMBr->ParameterOffset);
1987 parm_count = le32_to_cpu(pSMBr->ParameterCount);
1989 *ppparm = (char *)&pSMBr->hdr.Protocol + parm_offset;
1990 *ppdata = (char *)&pSMBr->hdr.Protocol + data_offset;
1992 /* should we also check that parm and data areas do not overlap? */
1993 if(*ppparm > end_of_smb) {
1994 cFYI(1,("parms start after end of smb"));
1996 } else if(parm_count + *ppparm > end_of_smb) {
1997 cFYI(1,("parm end after end of smb"));
1999 } else if(*ppdata > end_of_smb) {
2000 cFYI(1,("data starts after end of smb"));
2002 } else if(data_count + *ppdata > end_of_smb) {
2003 cFYI(1,("data %p + count %d (%p) ends after end of smb %p start %p",
2004 *ppdata, data_count, (data_count + *ppdata), end_of_smb, pSMBr)); /* BB FIXME */
2006 } else if(parm_count + data_count > pSMBr->ByteCount) {
2007 cFYI(1,("parm count and data count larger than SMB"));
2014 CIFSSMBQueryReparseLinkInfo(const int xid, struct cifsTconInfo *tcon,
2015 const unsigned char *searchName,
2016 char *symlinkinfo, const int buflen,__u16 fid,
2017 const struct nls_table *nls_codepage)
2022 struct smb_com_transaction_ioctl_req * pSMB;
2023 struct smb_com_transaction_ioctl_rsp * pSMBr;
2025 cFYI(1, ("In Windows reparse style QueryLink for path %s", searchName));
2026 rc = smb_init(SMB_COM_NT_TRANSACT, 23, tcon, (void **) &pSMB,
2031 pSMB->TotalParameterCount = 0 ;
2032 pSMB->TotalDataCount = 0;
2033 pSMB->MaxParameterCount = cpu_to_le32(2);
2034 /* BB find exact data count max from sess structure BB */
2035 pSMB->MaxDataCount = cpu_to_le32((tcon->ses->server->maxBuf -
2036 MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
2037 pSMB->MaxSetupCount = 4;
2039 pSMB->ParameterOffset = 0;
2040 pSMB->DataCount = 0;
2041 pSMB->DataOffset = 0;
2042 pSMB->SetupCount = 4;
2043 pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_IOCTL);
2044 pSMB->ParameterCount = pSMB->TotalParameterCount;
2045 pSMB->FunctionCode = cpu_to_le32(FSCTL_GET_REPARSE_POINT);
2046 pSMB->IsFsctl = 1; /* FSCTL */
2047 pSMB->IsRootFlag = 0;
2048 pSMB->Fid = fid; /* file handle always le */
2049 pSMB->ByteCount = 0;
2051 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2052 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2054 cFYI(1, ("Send error in QueryReparseLinkInfo = %d", rc));
2055 } else { /* decode response */
2056 __u32 data_offset = le32_to_cpu(pSMBr->DataOffset);
2057 __u32 data_count = le32_to_cpu(pSMBr->DataCount);
2058 if ((pSMBr->ByteCount < 2) || (data_offset > 512))
2059 /* BB also check enough total bytes returned */
2060 rc = -EIO; /* bad smb */
2062 if(data_count && (data_count < 2048)) {
2063 char * end_of_smb = 2 /* sizeof byte count */ +
2065 (char *)&pSMBr->ByteCount;
2067 struct reparse_data * reparse_buf = (struct reparse_data *)
2068 ((char *)&pSMBr->hdr.Protocol + data_offset);
2069 if((char*)reparse_buf >= end_of_smb) {
2073 if((reparse_buf->LinkNamesBuf +
2074 reparse_buf->TargetNameOffset +
2075 reparse_buf->TargetNameLen) >
2077 cFYI(1,("reparse buf extended beyond SMB"));
2082 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
2083 name_len = UniStrnlen((wchar_t *)
2084 (reparse_buf->LinkNamesBuf +
2085 reparse_buf->TargetNameOffset),
2086 min(buflen/2, reparse_buf->TargetNameLen / 2));
2087 cifs_strfromUCS_le(symlinkinfo,
2088 (__le16 *) (reparse_buf->LinkNamesBuf +
2089 reparse_buf->TargetNameOffset),
2090 name_len, nls_codepage);
2091 } else { /* ASCII names */
2092 strncpy(symlinkinfo,reparse_buf->LinkNamesBuf +
2093 reparse_buf->TargetNameOffset,
2094 min_t(const int, buflen, reparse_buf->TargetNameLen));
2098 cFYI(1,("Invalid return data count on get reparse info ioctl"));
2100 symlinkinfo[buflen] = 0; /* just in case so the caller
2101 does not go off the end of the buffer */
2102 cFYI(1,("readlink result - %s ",symlinkinfo));
2106 cifs_buf_release(pSMB);
2108 /* Note: On -EAGAIN error only caller can retry on handle based calls
2109 since file handle passed in no longer valid */
2114 #ifdef CONFIG_CIFS_POSIX
2116 /*Convert an Access Control Entry from wire format to local POSIX xattr format*/
2117 static void cifs_convert_ace(posix_acl_xattr_entry * ace, struct cifs_posix_ace * cifs_ace)
2119 /* u8 cifs fields do not need le conversion */
2120 ace->e_perm = cpu_to_le16(cifs_ace->cifs_e_perm);
2121 ace->e_tag = cpu_to_le16(cifs_ace->cifs_e_tag);
2122 ace->e_id = cpu_to_le32(le64_to_cpu(cifs_ace->cifs_uid));
2123 /* cFYI(1,("perm %d tag %d id %d",ace->e_perm,ace->e_tag,ace->e_id)); */
2128 /* Convert ACL from CIFS POSIX wire format to local Linux POSIX ACL xattr */
2129 static int cifs_copy_posix_acl(char * trgt,char * src, const int buflen,
2130 const int acl_type,const int size_of_data_area)
2135 struct cifs_posix_ace * pACE;
2136 struct cifs_posix_acl * cifs_acl = (struct cifs_posix_acl *)src;
2137 posix_acl_xattr_header * local_acl = (posix_acl_xattr_header *)trgt;
2139 if (le16_to_cpu(cifs_acl->version) != CIFS_ACL_VERSION)
2142 if(acl_type & ACL_TYPE_ACCESS) {
2143 count = le16_to_cpu(cifs_acl->access_entry_count);
2144 pACE = &cifs_acl->ace_array[0];
2145 size = sizeof(struct cifs_posix_acl);
2146 size += sizeof(struct cifs_posix_ace) * count;
2147 /* check if we would go beyond end of SMB */
2148 if(size_of_data_area < size) {
2149 cFYI(1,("bad CIFS POSIX ACL size %d vs. %d",size_of_data_area,size));
2152 } else if(acl_type & ACL_TYPE_DEFAULT) {
2153 count = le16_to_cpu(cifs_acl->access_entry_count);
2154 size = sizeof(struct cifs_posix_acl);
2155 size += sizeof(struct cifs_posix_ace) * count;
2156 /* skip past access ACEs to get to default ACEs */
2157 pACE = &cifs_acl->ace_array[count];
2158 count = le16_to_cpu(cifs_acl->default_entry_count);
2159 size += sizeof(struct cifs_posix_ace) * count;
2160 /* check if we would go beyond end of SMB */
2161 if(size_of_data_area < size)
2168 size = posix_acl_xattr_size(count);
2169 if((buflen == 0) || (local_acl == NULL)) {
2170 /* used to query ACL EA size */
2171 } else if(size > buflen) {
2173 } else /* buffer big enough */ {
2174 local_acl->a_version = cpu_to_le32(POSIX_ACL_XATTR_VERSION);
2175 for(i = 0;i < count ;i++) {
2176 cifs_convert_ace(&local_acl->a_entries[i],pACE);
2183 static __u16 convert_ace_to_cifs_ace(struct cifs_posix_ace * cifs_ace,
2184 const posix_acl_xattr_entry * local_ace)
2186 __u16 rc = 0; /* 0 = ACL converted ok */
2188 cifs_ace->cifs_e_perm = le16_to_cpu(local_ace->e_perm);
2189 cifs_ace->cifs_e_tag = le16_to_cpu(local_ace->e_tag);
2190 /* BB is there a better way to handle the large uid? */
2191 if(local_ace->e_id == cpu_to_le32(-1)) {
2192 /* Probably no need to le convert -1 on any arch but can not hurt */
2193 cifs_ace->cifs_uid = cpu_to_le64(-1);
2195 cifs_ace->cifs_uid = cpu_to_le64(le32_to_cpu(local_ace->e_id));
2196 /*cFYI(1,("perm %d tag %d id %d",ace->e_perm,ace->e_tag,ace->e_id));*/
2200 /* Convert ACL from local Linux POSIX xattr to CIFS POSIX ACL wire format */
2201 static __u16 ACL_to_cifs_posix(char * parm_data,const char * pACL,const int buflen,
2205 struct cifs_posix_acl * cifs_acl = (struct cifs_posix_acl *)parm_data;
2206 posix_acl_xattr_header * local_acl = (posix_acl_xattr_header *)pACL;
2210 if((buflen == 0) || (pACL == NULL) || (cifs_acl == NULL))
2213 count = posix_acl_xattr_count((size_t)buflen);
2214 cFYI(1,("setting acl with %d entries from buf of length %d and version of %d",
2215 count, buflen, le32_to_cpu(local_acl->a_version)));
2216 if(le32_to_cpu(local_acl->a_version) != 2) {
2217 cFYI(1,("unknown POSIX ACL version %d",
2218 le32_to_cpu(local_acl->a_version)));
2221 cifs_acl->version = cpu_to_le16(1);
2222 if(acl_type == ACL_TYPE_ACCESS)
2223 cifs_acl->access_entry_count = cpu_to_le16(count);
2224 else if(acl_type == ACL_TYPE_DEFAULT)
2225 cifs_acl->default_entry_count = cpu_to_le16(count);
2227 cFYI(1,("unknown ACL type %d",acl_type));
2230 for(i=0;i<count;i++) {
2231 rc = convert_ace_to_cifs_ace(&cifs_acl->ace_array[i],
2232 &local_acl->a_entries[i]);
2234 /* ACE not converted */
2239 rc = (__u16)(count * sizeof(struct cifs_posix_ace));
2240 rc += sizeof(struct cifs_posix_acl);
2241 /* BB add check to make sure ACL does not overflow SMB */
2247 CIFSSMBGetPosixACL(const int xid, struct cifsTconInfo *tcon,
2248 const unsigned char *searchName,
2249 char *acl_inf, const int buflen, const int acl_type,
2250 const struct nls_table *nls_codepage, int remap)
2252 /* SMB_QUERY_POSIX_ACL */
2253 TRANSACTION2_QPI_REQ *pSMB = NULL;
2254 TRANSACTION2_QPI_RSP *pSMBr = NULL;
2258 __u16 params, byte_count;
2260 cFYI(1, ("In GetPosixACL (Unix) for path %s", searchName));
2263 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2268 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2270 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
2271 PATH_MAX, nls_codepage, remap);
2272 name_len++; /* trailing null */
2274 pSMB->FileName[name_len] = 0;
2275 pSMB->FileName[name_len+1] = 0;
2276 } else { /* BB improve the check for buffer overruns BB */
2277 name_len = strnlen(searchName, PATH_MAX);
2278 name_len++; /* trailing null */
2279 strncpy(pSMB->FileName, searchName, name_len);
2282 params = 2 /* level */ + 4 /* rsrvd */ + name_len /* incl null */ ;
2283 pSMB->TotalDataCount = 0;
2284 pSMB->MaxParameterCount = cpu_to_le16(2);
2285 /* BB find exact max data count below from sess structure BB */
2286 pSMB->MaxDataCount = cpu_to_le16(4000);
2287 pSMB->MaxSetupCount = 0;
2291 pSMB->Reserved2 = 0;
2292 pSMB->ParameterOffset = cpu_to_le16(
2293 offsetof(struct smb_com_transaction2_qpi_req ,InformationLevel) - 4);
2294 pSMB->DataCount = 0;
2295 pSMB->DataOffset = 0;
2296 pSMB->SetupCount = 1;
2297 pSMB->Reserved3 = 0;
2298 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
2299 byte_count = params + 1 /* pad */ ;
2300 pSMB->TotalParameterCount = cpu_to_le16(params);
2301 pSMB->ParameterCount = pSMB->TotalParameterCount;
2302 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_POSIX_ACL);
2303 pSMB->Reserved4 = 0;
2304 pSMB->hdr.smb_buf_length += byte_count;
2305 pSMB->ByteCount = cpu_to_le16(byte_count);
2307 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2308 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2309 cifs_stats_inc(&tcon->num_acl_get);
2311 cFYI(1, ("Send error in Query POSIX ACL = %d", rc));
2313 /* decode response */
2315 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
2316 if (rc || (pSMBr->ByteCount < 2))
2317 /* BB also check enough total bytes returned */
2318 rc = -EIO; /* bad smb */
2320 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
2321 __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
2322 rc = cifs_copy_posix_acl(acl_inf,
2323 (char *)&pSMBr->hdr.Protocol+data_offset,
2324 buflen,acl_type,count);
2327 cifs_buf_release(pSMB);
2334 CIFSSMBSetPosixACL(const int xid, struct cifsTconInfo *tcon,
2335 const unsigned char *fileName,
2336 const char *local_acl, const int buflen,
2338 const struct nls_table *nls_codepage, int remap)
2340 struct smb_com_transaction2_spi_req *pSMB = NULL;
2341 struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
2345 int bytes_returned = 0;
2346 __u16 params, byte_count, data_count, param_offset, offset;
2348 cFYI(1, ("In SetPosixACL (Unix) for path %s", fileName));
2350 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2354 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2356 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
2357 PATH_MAX, nls_codepage, remap);
2358 name_len++; /* trailing null */
2360 } else { /* BB improve the check for buffer overruns BB */
2361 name_len = strnlen(fileName, PATH_MAX);
2362 name_len++; /* trailing null */
2363 strncpy(pSMB->FileName, fileName, name_len);
2365 params = 6 + name_len;
2366 pSMB->MaxParameterCount = cpu_to_le16(2);
2367 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB size from sess */
2368 pSMB->MaxSetupCount = 0;
2372 pSMB->Reserved2 = 0;
2373 param_offset = offsetof(struct smb_com_transaction2_spi_req,
2374 InformationLevel) - 4;
2375 offset = param_offset + params;
2376 parm_data = ((char *) &pSMB->hdr.Protocol) + offset;
2377 pSMB->ParameterOffset = cpu_to_le16(param_offset);
2379 /* convert to on the wire format for POSIX ACL */
2380 data_count = ACL_to_cifs_posix(parm_data,local_acl,buflen,acl_type);
2382 if(data_count == 0) {
2384 goto setACLerrorExit;
2386 pSMB->DataOffset = cpu_to_le16(offset);
2387 pSMB->SetupCount = 1;
2388 pSMB->Reserved3 = 0;
2389 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
2390 pSMB->InformationLevel = cpu_to_le16(SMB_SET_POSIX_ACL);
2391 byte_count = 3 /* pad */ + params + data_count;
2392 pSMB->DataCount = cpu_to_le16(data_count);
2393 pSMB->TotalDataCount = pSMB->DataCount;
2394 pSMB->ParameterCount = cpu_to_le16(params);
2395 pSMB->TotalParameterCount = pSMB->ParameterCount;
2396 pSMB->Reserved4 = 0;
2397 pSMB->hdr.smb_buf_length += byte_count;
2398 pSMB->ByteCount = cpu_to_le16(byte_count);
2399 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2400 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2402 cFYI(1, ("Set POSIX ACL returned %d", rc));
2406 cifs_buf_release(pSMB);
2412 /* BB fix tabs in this function FIXME BB */
2414 CIFSGetExtAttr(const int xid, struct cifsTconInfo *tcon,
2415 const int netfid, __u64 * pExtAttrBits, __u64 *pMask)
2418 struct smb_t2_qfi_req *pSMB = NULL;
2419 struct smb_t2_qfi_rsp *pSMBr = NULL;
2421 __u16 params, byte_count;
2423 cFYI(1,("In GetExtAttr"));
2428 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2433 params = 2 /* level */ +2 /* fid */;
2434 pSMB->t2.TotalDataCount = 0;
2435 pSMB->t2.MaxParameterCount = cpu_to_le16(4);
2436 /* BB find exact max data count below from sess structure BB */
2437 pSMB->t2.MaxDataCount = cpu_to_le16(4000);
2438 pSMB->t2.MaxSetupCount = 0;
2439 pSMB->t2.Reserved = 0;
2441 pSMB->t2.Timeout = 0;
2442 pSMB->t2.Reserved2 = 0;
2443 pSMB->t2.ParameterOffset = cpu_to_le16(offsetof(struct smb_t2_qfi_req,
2445 pSMB->t2.DataCount = 0;
2446 pSMB->t2.DataOffset = 0;
2447 pSMB->t2.SetupCount = 1;
2448 pSMB->t2.Reserved3 = 0;
2449 pSMB->t2.SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION);
2450 byte_count = params + 1 /* pad */ ;
2451 pSMB->t2.TotalParameterCount = cpu_to_le16(params);
2452 pSMB->t2.ParameterCount = pSMB->t2.TotalParameterCount;
2453 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_ATTR_FLAGS);
2456 pSMB->hdr.smb_buf_length += byte_count;
2457 pSMB->t2.ByteCount = cpu_to_le16(byte_count);
2459 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2460 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2462 cFYI(1, ("error %d in GetExtAttr", rc));
2464 /* decode response */
2465 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
2466 if (rc || (pSMBr->ByteCount < 2))
2467 /* BB also check enough total bytes returned */
2468 /* If rc should we check for EOPNOSUPP and
2469 disable the srvino flag? or in caller? */
2470 rc = -EIO; /* bad smb */
2472 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
2473 __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
2474 struct file_chattr_info * pfinfo;
2475 /* BB Do we need a cast or hash here ? */
2477 cFYI(1, ("Illegal size ret in GetExtAttr"));
2481 pfinfo = (struct file_chattr_info *)
2482 (data_offset + (char *) &pSMBr->hdr.Protocol);
2483 *pExtAttrBits = le64_to_cpu(pfinfo->mode);
2484 *pMask = le64_to_cpu(pfinfo->mask);
2488 cifs_buf_release(pSMB);
2490 goto GetExtAttrRetry;
2495 #endif /* CONFIG_POSIX */
2497 /* Convert CIFS ACL to POSIX form */
2498 static int parse_sec_desc(struct sec_desc * psec_desc, int acl_len)
2503 /* Get Security Descriptor (by handle) from remote server for a file or dir */
2505 CIFSSMBGetCIFSACL(const int xid, struct cifsTconInfo *tcon, __u16 fid,
2506 /* BB fix up return info */ char *acl_inf, const int buflen,
2507 const int acl_type /* ACCESS/DEFAULT not sure implication */)
2511 QUERY_SEC_DESC_REQ * pSMB;
2514 cFYI(1, ("GetCifsACL"));
2516 rc = smb_init_ntransact(NT_TRANSACT_QUERY_SECURITY_DESC, 0,
2517 8 /* parm len */, tcon, (void **) &pSMB);
2521 pSMB->MaxParameterCount = cpu_to_le32(4);
2522 /* BB TEST with big acls that might need to be e.g. larger than 16K */
2523 pSMB->MaxSetupCount = 0;
2524 pSMB->Fid = fid; /* file handle always le */
2525 pSMB->AclFlags = cpu_to_le32(CIFS_ACL_OWNER | CIFS_ACL_GROUP |
2527 pSMB->ByteCount = cpu_to_le16(11); /* 3 bytes pad + 8 bytes parm */
2528 pSMB->hdr.smb_buf_length += 11;
2529 iov[0].iov_base = (char *)pSMB;
2530 iov[0].iov_len = pSMB->hdr.smb_buf_length + 4;
2532 rc = SendReceive2(xid, tcon->ses, iov, 1 /* num iovec */, &buf_type, 0);
2533 cifs_stats_inc(&tcon->num_acl_get);
2535 cFYI(1, ("Send error in QuerySecDesc = %d", rc));
2536 } else { /* decode response */
2537 struct sec_desc * psec_desc;
2542 struct smb_com_ntransact_rsp * pSMBr;
2544 /* validate_nttransact */
2545 rc = validate_ntransact(iov[0].iov_base, (char **)&parm,
2546 (char **)&psec_desc,
2547 &parm_len, &data_len);
2551 pSMBr = (struct smb_com_ntransact_rsp *)iov[0].iov_base;
2553 cERROR(1,("smb %p parm %p data %p",pSMBr,parm,psec_desc)); /* BB removeme BB */
2555 if (le32_to_cpu(pSMBr->ParameterCount) != 4) {
2556 rc = -EIO; /* bad smb */
2560 /* BB check that data area is minimum length and as big as acl_len */
2562 acl_len = le32_to_cpu(*(__le32 *)parm);
2563 /* BB check if(acl_len > bufsize) */
2565 parse_sec_desc(psec_desc, acl_len);
2568 if(buf_type == CIFS_SMALL_BUFFER)
2569 cifs_small_buf_release(iov[0].iov_base);
2570 else if(buf_type == CIFS_LARGE_BUFFER)
2571 cifs_buf_release(iov[0].iov_base);
2572 cifs_small_buf_release(pSMB);
2577 /* Legacy Query Path Information call for lookup to old servers such
2579 int SMBQueryInformation(const int xid, struct cifsTconInfo *tcon,
2580 const unsigned char *searchName,
2581 FILE_ALL_INFO * pFinfo,
2582 const struct nls_table *nls_codepage, int remap)
2584 QUERY_INFORMATION_REQ * pSMB;
2585 QUERY_INFORMATION_RSP * pSMBr;
2590 cFYI(1, ("In SMBQPath path %s", searchName));
2592 rc = smb_init(SMB_COM_QUERY_INFORMATION, 0, tcon, (void **) &pSMB,
2597 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2599 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
2600 PATH_MAX, nls_codepage, remap);
2601 name_len++; /* trailing null */
2604 name_len = strnlen(searchName, PATH_MAX);
2605 name_len++; /* trailing null */
2606 strncpy(pSMB->FileName, searchName, name_len);
2608 pSMB->BufferFormat = 0x04;
2609 name_len++; /* account for buffer type byte */
2610 pSMB->hdr.smb_buf_length += (__u16) name_len;
2611 pSMB->ByteCount = cpu_to_le16(name_len);
2613 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2614 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2616 cFYI(1, ("Send error in QueryInfo = %d", rc));
2617 } else if (pFinfo) { /* decode response */
2618 memset(pFinfo, 0, sizeof(FILE_ALL_INFO));
2619 pFinfo->AllocationSize =
2620 cpu_to_le64(le32_to_cpu(pSMBr->size));
2621 pFinfo->EndOfFile = pFinfo->AllocationSize;
2622 pFinfo->Attributes =
2623 cpu_to_le32(le16_to_cpu(pSMBr->attr));
2625 rc = -EIO; /* bad buffer passed in */
2627 cifs_buf_release(pSMB);
2639 CIFSSMBQPathInfo(const int xid, struct cifsTconInfo *tcon,
2640 const unsigned char *searchName,
2641 FILE_ALL_INFO * pFindData,
2642 const struct nls_table *nls_codepage, int remap)
2644 /* level 263 SMB_QUERY_FILE_ALL_INFO */
2645 TRANSACTION2_QPI_REQ *pSMB = NULL;
2646 TRANSACTION2_QPI_RSP *pSMBr = NULL;
2650 __u16 params, byte_count;
2652 /* cFYI(1, ("In QPathInfo path %s", searchName)); */
2654 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2659 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2661 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
2662 PATH_MAX, nls_codepage, remap);
2663 name_len++; /* trailing null */
2665 } else { /* BB improve the check for buffer overruns BB */
2666 name_len = strnlen(searchName, PATH_MAX);
2667 name_len++; /* trailing null */
2668 strncpy(pSMB->FileName, searchName, name_len);
2671 params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */ ;
2672 pSMB->TotalDataCount = 0;
2673 pSMB->MaxParameterCount = cpu_to_le16(2);
2674 pSMB->MaxDataCount = cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
2675 pSMB->MaxSetupCount = 0;
2679 pSMB->Reserved2 = 0;
2680 pSMB->ParameterOffset = cpu_to_le16(offsetof(
2681 struct smb_com_transaction2_qpi_req ,InformationLevel) - 4);
2682 pSMB->DataCount = 0;
2683 pSMB->DataOffset = 0;
2684 pSMB->SetupCount = 1;
2685 pSMB->Reserved3 = 0;
2686 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
2687 byte_count = params + 1 /* pad */ ;
2688 pSMB->TotalParameterCount = cpu_to_le16(params);
2689 pSMB->ParameterCount = pSMB->TotalParameterCount;
2690 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_ALL_INFO);
2691 pSMB->Reserved4 = 0;
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);
2698 cFYI(1, ("Send error in QPathInfo = %d", rc));
2699 } else { /* decode response */
2700 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
2702 if (rc || (pSMBr->ByteCount < 40))
2703 rc = -EIO; /* bad smb */
2704 else if (pFindData){
2705 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
2706 memcpy((char *) pFindData,
2707 (char *) &pSMBr->hdr.Protocol +
2708 data_offset, sizeof (FILE_ALL_INFO));
2712 cifs_buf_release(pSMB);
2714 goto QPathInfoRetry;
2720 CIFSSMBUnixQPathInfo(const int xid, struct cifsTconInfo *tcon,
2721 const unsigned char *searchName,
2722 FILE_UNIX_BASIC_INFO * pFindData,
2723 const struct nls_table *nls_codepage, int remap)
2725 /* SMB_QUERY_FILE_UNIX_BASIC */
2726 TRANSACTION2_QPI_REQ *pSMB = NULL;
2727 TRANSACTION2_QPI_RSP *pSMBr = NULL;
2729 int bytes_returned = 0;
2731 __u16 params, byte_count;
2733 cFYI(1, ("In QPathInfo (Unix) the path %s", searchName));
2735 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2740 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2742 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
2743 PATH_MAX, nls_codepage, remap);
2744 name_len++; /* trailing null */
2746 } else { /* BB improve the check for buffer overruns BB */
2747 name_len = strnlen(searchName, PATH_MAX);
2748 name_len++; /* trailing null */
2749 strncpy(pSMB->FileName, searchName, name_len);
2752 params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */ ;
2753 pSMB->TotalDataCount = 0;
2754 pSMB->MaxParameterCount = cpu_to_le16(2);
2755 /* BB find exact max SMB PDU from sess structure BB */
2756 pSMB->MaxDataCount = cpu_to_le16(4000);
2757 pSMB->MaxSetupCount = 0;
2761 pSMB->Reserved2 = 0;
2762 pSMB->ParameterOffset = cpu_to_le16(offsetof(
2763 struct smb_com_transaction2_qpi_req ,InformationLevel) - 4);
2764 pSMB->DataCount = 0;
2765 pSMB->DataOffset = 0;
2766 pSMB->SetupCount = 1;
2767 pSMB->Reserved3 = 0;
2768 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
2769 byte_count = params + 1 /* pad */ ;
2770 pSMB->TotalParameterCount = cpu_to_le16(params);
2771 pSMB->ParameterCount = pSMB->TotalParameterCount;
2772 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC);
2773 pSMB->Reserved4 = 0;
2774 pSMB->hdr.smb_buf_length += byte_count;
2775 pSMB->ByteCount = cpu_to_le16(byte_count);
2777 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2778 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2780 cFYI(1, ("Send error in QPathInfo = %d", rc));
2781 } else { /* decode response */
2782 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
2784 if (rc || (pSMBr->ByteCount < sizeof(FILE_UNIX_BASIC_INFO))) {
2785 rc = -EIO; /* bad smb */
2787 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
2788 memcpy((char *) pFindData,
2789 (char *) &pSMBr->hdr.Protocol +
2791 sizeof (FILE_UNIX_BASIC_INFO));
2794 cifs_buf_release(pSMB);
2796 goto UnixQPathInfoRetry;
2801 #if 0 /* function unused at present */
2802 int CIFSFindSingle(const int xid, struct cifsTconInfo *tcon,
2803 const char *searchName, FILE_ALL_INFO * findData,
2804 const struct nls_table *nls_codepage)
2806 /* level 257 SMB_ */
2807 TRANSACTION2_FFIRST_REQ *pSMB = NULL;
2808 TRANSACTION2_FFIRST_RSP *pSMBr = NULL;
2812 __u16 params, byte_count;
2814 cFYI(1, ("In FindUnique"));
2816 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2821 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2823 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName, PATH_MAX
2824 /* find define for this maxpathcomponent */
2826 name_len++; /* trailing null */
2828 } else { /* BB improve the check for buffer overruns BB */
2829 name_len = strnlen(searchName, PATH_MAX);
2830 name_len++; /* trailing null */
2831 strncpy(pSMB->FileName, searchName, name_len);
2834 params = 12 + name_len /* includes null */ ;
2835 pSMB->TotalDataCount = 0; /* no EAs */
2836 pSMB->MaxParameterCount = cpu_to_le16(2);
2837 pSMB->MaxDataCount = cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
2838 pSMB->MaxSetupCount = 0;
2842 pSMB->Reserved2 = 0;
2843 pSMB->ParameterOffset = cpu_to_le16(
2844 offsetof(struct smb_com_transaction2_ffirst_req,InformationLevel) - 4);
2845 pSMB->DataCount = 0;
2846 pSMB->DataOffset = 0;
2847 pSMB->SetupCount = 1; /* one byte, no need to le convert */
2848 pSMB->Reserved3 = 0;
2849 pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_FIRST);
2850 byte_count = params + 1 /* pad */ ;
2851 pSMB->TotalParameterCount = cpu_to_le16(params);
2852 pSMB->ParameterCount = pSMB->TotalParameterCount;
2853 pSMB->SearchAttributes =
2854 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
2856 pSMB->SearchCount = cpu_to_le16(16); /* BB increase */
2857 pSMB->SearchFlags = cpu_to_le16(1);
2858 pSMB->InformationLevel = cpu_to_le16(SMB_FIND_FILE_DIRECTORY_INFO);
2859 pSMB->SearchStorageType = 0; /* BB what should we set this to? BB */
2860 pSMB->hdr.smb_buf_length += byte_count;
2861 pSMB->ByteCount = cpu_to_le16(byte_count);
2863 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2864 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2867 cFYI(1, ("Send error in FindFileDirInfo = %d", rc));
2868 } else { /* decode response */
2869 cifs_stats_inc(&tcon->num_ffirst);
2873 cifs_buf_release(pSMB);
2875 goto findUniqueRetry;
2879 #endif /* end unused (temporarily) function */
2881 /* xid, tcon, searchName and codepage are input parms, rest are returned */
2883 CIFSFindFirst(const int xid, struct cifsTconInfo *tcon,
2884 const char *searchName,
2885 const struct nls_table *nls_codepage,
2887 struct cifs_search_info * psrch_inf, int remap, const char dirsep)
2889 /* level 257 SMB_ */
2890 TRANSACTION2_FFIRST_REQ *pSMB = NULL;
2891 TRANSACTION2_FFIRST_RSP *pSMBr = NULL;
2892 T2_FFIRST_RSP_PARMS * parms;
2894 int bytes_returned = 0;
2896 __u16 params, byte_count;
2898 cFYI(1, ("In FindFirst for %s",searchName));
2901 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2906 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2908 cifsConvertToUCS((__le16 *) pSMB->FileName,searchName,
2909 PATH_MAX, nls_codepage, remap);
2910 /* We can not add the asterik earlier in case
2911 it got remapped to 0xF03A as if it were part of the
2912 directory name instead of a wildcard */
2914 pSMB->FileName[name_len] = dirsep;
2915 pSMB->FileName[name_len+1] = 0;
2916 pSMB->FileName[name_len+2] = '*';
2917 pSMB->FileName[name_len+3] = 0;
2918 name_len += 4; /* now the trailing null */
2919 pSMB->FileName[name_len] = 0; /* null terminate just in case */
2920 pSMB->FileName[name_len+1] = 0;
2922 } else { /* BB add check for overrun of SMB buf BB */
2923 name_len = strnlen(searchName, PATH_MAX);
2924 /* BB fix here and in unicode clause above ie
2925 if(name_len > buffersize-header)
2926 free buffer exit; BB */
2927 strncpy(pSMB->FileName, searchName, name_len);
2928 pSMB->FileName[name_len] = dirsep;
2929 pSMB->FileName[name_len+1] = '*';
2930 pSMB->FileName[name_len+2] = 0;
2934 params = 12 + name_len /* includes null */ ;
2935 pSMB->TotalDataCount = 0; /* no EAs */
2936 pSMB->MaxParameterCount = cpu_to_le16(10);
2937 pSMB->MaxDataCount = cpu_to_le16((tcon->ses->server->maxBuf -
2938 MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
2939 pSMB->MaxSetupCount = 0;
2943 pSMB->Reserved2 = 0;
2944 byte_count = params + 1 /* pad */ ;
2945 pSMB->TotalParameterCount = cpu_to_le16(params);
2946 pSMB->ParameterCount = pSMB->TotalParameterCount;
2947 pSMB->ParameterOffset = cpu_to_le16(
2948 offsetof(struct smb_com_transaction2_ffirst_req, SearchAttributes) - 4);
2949 pSMB->DataCount = 0;
2950 pSMB->DataOffset = 0;
2951 pSMB->SetupCount = 1; /* one byte, no need to make endian neutral */
2952 pSMB->Reserved3 = 0;
2953 pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_FIRST);
2954 pSMB->SearchAttributes =
2955 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
2957 pSMB->SearchCount= cpu_to_le16(CIFSMaxBufSize/sizeof(FILE_UNIX_INFO));
2958 pSMB->SearchFlags = cpu_to_le16(CIFS_SEARCH_CLOSE_AT_END |
2959 CIFS_SEARCH_RETURN_RESUME);
2960 pSMB->InformationLevel = cpu_to_le16(psrch_inf->info_level);
2962 /* BB what should we set StorageType to? Does it matter? BB */
2963 pSMB->SearchStorageType = 0;
2964 pSMB->hdr.smb_buf_length += byte_count;
2965 pSMB->ByteCount = cpu_to_le16(byte_count);
2967 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2968 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2969 cifs_stats_inc(&tcon->num_ffirst);
2971 if (rc) {/* BB add logic to retry regular search if Unix search rejected unexpectedly by server */
2972 /* BB Add code to handle unsupported level rc */
2973 cFYI(1, ("Error in FindFirst = %d", rc));
2976 cifs_buf_release(pSMB);
2978 /* BB eventually could optimize out free and realloc of buf */
2981 goto findFirstRetry;
2982 } else { /* decode response */
2983 /* BB remember to free buffer if error BB */
2984 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
2986 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
2987 psrch_inf->unicode = TRUE;
2989 psrch_inf->unicode = FALSE;
2991 psrch_inf->ntwrk_buf_start = (char *)pSMBr;
2992 psrch_inf->srch_entries_start =
2993 (char *) &pSMBr->hdr.Protocol +
2994 le16_to_cpu(pSMBr->t2.DataOffset);
2995 parms = (T2_FFIRST_RSP_PARMS *)((char *) &pSMBr->hdr.Protocol +
2996 le16_to_cpu(pSMBr->t2.ParameterOffset));
2998 if(parms->EndofSearch)
2999 psrch_inf->endOfSearch = TRUE;
3001 psrch_inf->endOfSearch = FALSE;
3003 psrch_inf->entries_in_buffer = le16_to_cpu(parms->SearchCount);
3004 psrch_inf->index_of_last_entry =
3005 psrch_inf->entries_in_buffer;
3006 *pnetfid = parms->SearchHandle;
3008 cifs_buf_release(pSMB);
3015 int CIFSFindNext(const int xid, struct cifsTconInfo *tcon,
3016 __u16 searchHandle, struct cifs_search_info * psrch_inf)
3018 TRANSACTION2_FNEXT_REQ *pSMB = NULL;
3019 TRANSACTION2_FNEXT_RSP *pSMBr = NULL;
3020 T2_FNEXT_RSP_PARMS * parms;
3021 char *response_data;
3023 int bytes_returned, name_len;
3024 __u16 params, byte_count;
3026 cFYI(1, ("In FindNext"));
3028 if(psrch_inf->endOfSearch == TRUE)
3031 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3036 params = 14; /* includes 2 bytes of null string, converted to LE below */
3038 pSMB->TotalDataCount = 0; /* no EAs */
3039 pSMB->MaxParameterCount = cpu_to_le16(8);
3040 pSMB->MaxDataCount =
3041 cpu_to_le16((tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
3042 pSMB->MaxSetupCount = 0;
3046 pSMB->Reserved2 = 0;
3047 pSMB->ParameterOffset = cpu_to_le16(
3048 offsetof(struct smb_com_transaction2_fnext_req,SearchHandle) - 4);
3049 pSMB->DataCount = 0;
3050 pSMB->DataOffset = 0;
3051 pSMB->SetupCount = 1;
3052 pSMB->Reserved3 = 0;
3053 pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_NEXT);
3054 pSMB->SearchHandle = searchHandle; /* always kept as le */
3056 cpu_to_le16(CIFSMaxBufSize / sizeof (FILE_UNIX_INFO));
3057 /* test for Unix extensions */
3058 /* if (tcon->ses->capabilities & CAP_UNIX) {
3059 pSMB->InformationLevel = cpu_to_le16(SMB_FIND_FILE_UNIX);
3060 psrch_inf->info_level = SMB_FIND_FILE_UNIX;
3062 pSMB->InformationLevel =
3063 cpu_to_le16(SMB_FIND_FILE_DIRECTORY_INFO);
3064 psrch_inf->info_level = SMB_FIND_FILE_DIRECTORY_INFO;
3066 pSMB->InformationLevel = cpu_to_le16(psrch_inf->info_level);
3067 pSMB->ResumeKey = psrch_inf->resume_key;
3069 cpu_to_le16(CIFS_SEARCH_CLOSE_AT_END | CIFS_SEARCH_RETURN_RESUME);
3071 name_len = psrch_inf->resume_name_len;
3073 if(name_len < PATH_MAX) {
3074 memcpy(pSMB->ResumeFileName, psrch_inf->presume_name, name_len);
3075 byte_count += name_len;
3076 /* 14 byte parm len above enough for 2 byte null terminator */
3077 pSMB->ResumeFileName[name_len] = 0;
3078 pSMB->ResumeFileName[name_len+1] = 0;
3081 goto FNext2_err_exit;
3083 byte_count = params + 1 /* pad */ ;
3084 pSMB->TotalParameterCount = cpu_to_le16(params);
3085 pSMB->ParameterCount = pSMB->TotalParameterCount;
3086 pSMB->hdr.smb_buf_length += byte_count;
3087 pSMB->ByteCount = cpu_to_le16(byte_count);
3089 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3090 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3091 cifs_stats_inc(&tcon->num_fnext);
3094 psrch_inf->endOfSearch = TRUE;
3095 rc = 0; /* search probably was closed at end of search above */
3097 cFYI(1, ("FindNext returned = %d", rc));
3098 } else { /* decode response */
3099 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3102 /* BB fixme add lock for file (srch_info) struct here */
3103 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
3104 psrch_inf->unicode = TRUE;
3106 psrch_inf->unicode = FALSE;
3107 response_data = (char *) &pSMBr->hdr.Protocol +
3108 le16_to_cpu(pSMBr->t2.ParameterOffset);
3109 parms = (T2_FNEXT_RSP_PARMS *)response_data;
3110 response_data = (char *)&pSMBr->hdr.Protocol +
3111 le16_to_cpu(pSMBr->t2.DataOffset);
3112 cifs_buf_release(psrch_inf->ntwrk_buf_start);
3113 psrch_inf->srch_entries_start = response_data;
3114 psrch_inf->ntwrk_buf_start = (char *)pSMB;
3115 if(parms->EndofSearch)
3116 psrch_inf->endOfSearch = TRUE;
3118 psrch_inf->endOfSearch = FALSE;
3120 psrch_inf->entries_in_buffer = le16_to_cpu(parms->SearchCount);
3121 psrch_inf->index_of_last_entry +=
3122 psrch_inf->entries_in_buffer;
3123 /* cFYI(1,("fnxt2 entries in buf %d index_of_last %d",psrch_inf->entries_in_buffer,psrch_inf->index_of_last_entry)); */
3125 /* BB fixme add unlock here */
3130 /* BB On error, should we leave previous search buf (and count and
3131 last entry fields) intact or free the previous one? */
3133 /* Note: On -EAGAIN error only caller can retry on handle based calls
3134 since file handle passed in no longer valid */
3137 cifs_buf_release(pSMB);
3143 CIFSFindClose(const int xid, struct cifsTconInfo *tcon, const __u16 searchHandle)
3146 FINDCLOSE_REQ *pSMB = NULL;
3147 CLOSE_RSP *pSMBr = NULL; /* BB removeme BB */
3150 cFYI(1, ("In CIFSSMBFindClose"));
3151 rc = small_smb_init(SMB_COM_FIND_CLOSE2, 1, tcon, (void **)&pSMB);
3153 /* no sense returning error if session restarted
3154 as file handle has been closed */
3160 pSMBr = (CLOSE_RSP *)pSMB; /* BB removeme BB */
3161 pSMB->FileID = searchHandle;
3162 pSMB->ByteCount = 0;
3163 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3164 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3166 cERROR(1, ("Send error in FindClose = %d", rc));
3168 cifs_stats_inc(&tcon->num_fclose);
3169 cifs_small_buf_release(pSMB);
3171 /* Since session is dead, search handle closed on server already */
3179 CIFSGetSrvInodeNumber(const int xid, struct cifsTconInfo *tcon,
3180 const unsigned char *searchName,
3181 __u64 * inode_number,
3182 const struct nls_table *nls_codepage, int remap)
3185 TRANSACTION2_QPI_REQ *pSMB = NULL;
3186 TRANSACTION2_QPI_RSP *pSMBr = NULL;
3187 int name_len, bytes_returned;
3188 __u16 params, byte_count;
3190 cFYI(1,("In GetSrvInodeNum for %s",searchName));
3194 GetInodeNumberRetry:
3195 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3201 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3203 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
3204 PATH_MAX,nls_codepage, remap);
3205 name_len++; /* trailing null */
3207 } else { /* BB improve the check for buffer overruns BB */
3208 name_len = strnlen(searchName, PATH_MAX);
3209 name_len++; /* trailing null */
3210 strncpy(pSMB->FileName, searchName, name_len);
3213 params = 2 /* level */ + 4 /* rsrvd */ + name_len /* incl null */ ;
3214 pSMB->TotalDataCount = 0;
3215 pSMB->MaxParameterCount = cpu_to_le16(2);
3216 /* BB find exact max data count below from sess structure BB */
3217 pSMB->MaxDataCount = cpu_to_le16(4000);
3218 pSMB->MaxSetupCount = 0;
3222 pSMB->Reserved2 = 0;
3223 pSMB->ParameterOffset = cpu_to_le16(offsetof(
3224 struct smb_com_transaction2_qpi_req ,InformationLevel) - 4);
3225 pSMB->DataCount = 0;
3226 pSMB->DataOffset = 0;
3227 pSMB->SetupCount = 1;
3228 pSMB->Reserved3 = 0;
3229 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
3230 byte_count = params + 1 /* pad */ ;
3231 pSMB->TotalParameterCount = cpu_to_le16(params);
3232 pSMB->ParameterCount = pSMB->TotalParameterCount;
3233 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_INTERNAL_INFO);
3234 pSMB->Reserved4 = 0;
3235 pSMB->hdr.smb_buf_length += byte_count;
3236 pSMB->ByteCount = cpu_to_le16(byte_count);
3238 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3239 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3241 cFYI(1, ("error %d in QueryInternalInfo", rc));
3243 /* decode response */
3244 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3245 if (rc || (pSMBr->ByteCount < 2))
3246 /* BB also check enough total bytes returned */
3247 /* If rc should we check for EOPNOSUPP and
3248 disable the srvino flag? or in caller? */
3249 rc = -EIO; /* bad smb */
3251 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3252 __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
3253 struct file_internal_info * pfinfo;
3254 /* BB Do we need a cast or hash here ? */
3256 cFYI(1, ("Illegal size ret in QryIntrnlInf"));
3258 goto GetInodeNumOut;
3260 pfinfo = (struct file_internal_info *)
3261 (data_offset + (char *) &pSMBr->hdr.Protocol);
3262 *inode_number = pfinfo->UniqueId;
3266 cifs_buf_release(pSMB);
3268 goto GetInodeNumberRetry;
3273 CIFSGetDFSRefer(const int xid, struct cifsSesInfo *ses,
3274 const unsigned char *searchName,
3275 unsigned char **targetUNCs,
3276 unsigned int *number_of_UNC_in_array,
3277 const struct nls_table *nls_codepage, int remap)
3279 /* TRANS2_GET_DFS_REFERRAL */
3280 TRANSACTION2_GET_DFS_REFER_REQ *pSMB = NULL;
3281 TRANSACTION2_GET_DFS_REFER_RSP *pSMBr = NULL;
3282 struct dfs_referral_level_3 * referrals = NULL;
3288 __u16 params, byte_count;
3289 *number_of_UNC_in_array = 0;
3292 cFYI(1, ("In GetDFSRefer the path %s", searchName));
3296 rc = smb_init(SMB_COM_TRANSACTION2, 15, NULL, (void **) &pSMB,
3301 /* server pointer checked in called function,
3302 but should never be null here anyway */
3303 pSMB->hdr.Mid = GetNextMid(ses->server);
3304 pSMB->hdr.Tid = ses->ipc_tid;
3305 pSMB->hdr.Uid = ses->Suid;
3306 if (ses->capabilities & CAP_STATUS32) {
3307 pSMB->hdr.Flags2 |= SMBFLG2_ERR_STATUS;
3309 if (ses->capabilities & CAP_DFS) {
3310 pSMB->hdr.Flags2 |= SMBFLG2_DFS;
3313 if (ses->capabilities & CAP_UNICODE) {
3314 pSMB->hdr.Flags2 |= SMBFLG2_UNICODE;
3316 cifsConvertToUCS((__le16 *) pSMB->RequestFileName,
3317 searchName, PATH_MAX, nls_codepage, remap);
3318 name_len++; /* trailing null */
3320 } else { /* BB improve the check for buffer overruns BB */
3321 name_len = strnlen(searchName, PATH_MAX);
3322 name_len++; /* trailing null */
3323 strncpy(pSMB->RequestFileName, searchName, name_len);
3326 params = 2 /* level */ + name_len /*includes null */ ;
3327 pSMB->TotalDataCount = 0;
3328 pSMB->DataCount = 0;
3329 pSMB->DataOffset = 0;
3330 pSMB->MaxParameterCount = 0;
3331 pSMB->MaxDataCount = cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
3332 pSMB->MaxSetupCount = 0;
3336 pSMB->Reserved2 = 0;
3337 pSMB->ParameterOffset = cpu_to_le16(offsetof(
3338 struct smb_com_transaction2_get_dfs_refer_req, MaxReferralLevel) - 4);
3339 pSMB->SetupCount = 1;
3340 pSMB->Reserved3 = 0;
3341 pSMB->SubCommand = cpu_to_le16(TRANS2_GET_DFS_REFERRAL);
3342 byte_count = params + 3 /* pad */ ;
3343 pSMB->ParameterCount = cpu_to_le16(params);
3344 pSMB->TotalParameterCount = pSMB->ParameterCount;
3345 pSMB->MaxReferralLevel = cpu_to_le16(3);
3346 pSMB->hdr.smb_buf_length += byte_count;
3347 pSMB->ByteCount = cpu_to_le16(byte_count);
3349 rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB,
3350 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3352 cFYI(1, ("Send error in GetDFSRefer = %d", rc));
3353 } else { /* decode response */
3354 /* BB Add logic to parse referrals here */
3355 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3357 if (rc || (pSMBr->ByteCount < 17)) /* BB also check enough total bytes returned */
3358 rc = -EIO; /* bad smb */
3360 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3361 __u16 data_count = le16_to_cpu(pSMBr->t2.DataCount);
3364 ("Decoding GetDFSRefer response. BCC: %d Offset %d",
3365 pSMBr->ByteCount, data_offset));
3367 (struct dfs_referral_level_3 *)
3368 (8 /* sizeof start of data block */ +
3370 (char *) &pSMBr->hdr.Protocol);
3371 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",
3372 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)));
3373 /* BB This field is actually two bytes in from start of
3374 data block so we could do safety check that DataBlock
3375 begins at address of pSMBr->NumberOfReferrals */
3376 *number_of_UNC_in_array = le16_to_cpu(pSMBr->NumberOfReferrals);
3378 /* BB Fix below so can return more than one referral */
3379 if(*number_of_UNC_in_array > 1)
3380 *number_of_UNC_in_array = 1;
3382 /* get the length of the strings describing refs */
3384 for(i=0;i<*number_of_UNC_in_array;i++) {
3385 /* make sure that DfsPathOffset not past end */
3386 __u16 offset = le16_to_cpu(referrals->DfsPathOffset);
3387 if (offset > data_count) {
3388 /* if invalid referral, stop here and do
3389 not try to copy any more */
3390 *number_of_UNC_in_array = i;
3393 temp = ((char *)referrals) + offset;
3395 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
3396 name_len += UniStrnlen((wchar_t *)temp,data_count);
3398 name_len += strnlen(temp,data_count);
3401 /* BB add check that referral pointer does not fall off end PDU */
3404 /* BB add check for name_len bigger than bcc */
3406 kmalloc(name_len+1+ (*number_of_UNC_in_array),GFP_KERNEL);
3407 if(*targetUNCs == NULL) {
3411 /* copy the ref strings */
3413 (struct dfs_referral_level_3 *)
3414 (8 /* sizeof data hdr */ +
3416 (char *) &pSMBr->hdr.Protocol);
3418 for(i=0;i<*number_of_UNC_in_array;i++) {
3419 temp = ((char *)referrals) + le16_to_cpu(referrals->DfsPathOffset);
3420 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
3421 cifs_strfromUCS_le(*targetUNCs,
3422 (__le16 *) temp, name_len, nls_codepage);
3424 strncpy(*targetUNCs,temp,name_len);
3426 /* BB update target_uncs pointers */
3436 cifs_buf_release(pSMB);
3444 /* Query File System Info such as free space to old servers such as Win 9x */
3446 SMBOldQFSInfo(const int xid, struct cifsTconInfo *tcon, struct kstatfs *FSData)
3448 /* level 0x01 SMB_QUERY_FILE_SYSTEM_INFO */
3449 TRANSACTION2_QFSI_REQ *pSMB = NULL;
3450 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
3451 FILE_SYSTEM_ALLOC_INFO *response_data;
3453 int bytes_returned = 0;
3454 __u16 params, byte_count;
3456 cFYI(1, ("OldQFSInfo"));
3458 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3462 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3467 params = 2; /* level */
3468 pSMB->TotalDataCount = 0;
3469 pSMB->MaxParameterCount = cpu_to_le16(2);
3470 pSMB->MaxDataCount = cpu_to_le16(1000);
3471 pSMB->MaxSetupCount = 0;
3475 pSMB->Reserved2 = 0;
3476 byte_count = params + 1 /* pad */ ;
3477 pSMB->TotalParameterCount = cpu_to_le16(params);
3478 pSMB->ParameterCount = pSMB->TotalParameterCount;
3479 pSMB->ParameterOffset = cpu_to_le16(offsetof(
3480 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
3481 pSMB->DataCount = 0;
3482 pSMB->DataOffset = 0;
3483 pSMB->SetupCount = 1;
3484 pSMB->Reserved3 = 0;
3485 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
3486 pSMB->InformationLevel = cpu_to_le16(SMB_INFO_ALLOCATION);
3487 pSMB->hdr.smb_buf_length += byte_count;
3488 pSMB->ByteCount = cpu_to_le16(byte_count);
3490 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3491 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3493 cFYI(1, ("Send error in QFSInfo = %d", rc));
3494 } else { /* decode response */
3495 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3497 if (rc || (pSMBr->ByteCount < 18))
3498 rc = -EIO; /* bad smb */
3500 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3501 cFYI(1,("qfsinf resp BCC: %d Offset %d",
3502 pSMBr->ByteCount, data_offset));
3505 (FILE_SYSTEM_ALLOC_INFO *)
3506 (((char *) &pSMBr->hdr.Protocol) + data_offset);
3508 le16_to_cpu(response_data->BytesPerSector) *
3509 le32_to_cpu(response_data->
3510 SectorsPerAllocationUnit);
3512 le32_to_cpu(response_data->TotalAllocationUnits);
3513 FSData->f_bfree = FSData->f_bavail =
3514 le32_to_cpu(response_data->FreeAllocationUnits);
3516 ("Blocks: %lld Free: %lld Block size %ld",
3517 (unsigned long long)FSData->f_blocks,
3518 (unsigned long long)FSData->f_bfree,
3522 cifs_buf_release(pSMB);
3525 goto oldQFSInfoRetry;
3531 CIFSSMBQFSInfo(const int xid, struct cifsTconInfo *tcon, struct kstatfs *FSData)
3533 /* level 0x103 SMB_QUERY_FILE_SYSTEM_INFO */
3534 TRANSACTION2_QFSI_REQ *pSMB = NULL;
3535 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
3536 FILE_SYSTEM_INFO *response_data;
3538 int bytes_returned = 0;
3539 __u16 params, byte_count;
3541 cFYI(1, ("In QFSInfo"));
3543 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3548 params = 2; /* level */
3549 pSMB->TotalDataCount = 0;
3550 pSMB->MaxParameterCount = cpu_to_le16(2);
3551 pSMB->MaxDataCount = cpu_to_le16(1000);
3552 pSMB->MaxSetupCount = 0;
3556 pSMB->Reserved2 = 0;
3557 byte_count = params + 1 /* pad */ ;
3558 pSMB->TotalParameterCount = cpu_to_le16(params);
3559 pSMB->ParameterCount = pSMB->TotalParameterCount;
3560 pSMB->ParameterOffset = cpu_to_le16(offsetof(
3561 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
3562 pSMB->DataCount = 0;
3563 pSMB->DataOffset = 0;
3564 pSMB->SetupCount = 1;
3565 pSMB->Reserved3 = 0;
3566 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
3567 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_SIZE_INFO);
3568 pSMB->hdr.smb_buf_length += byte_count;
3569 pSMB->ByteCount = cpu_to_le16(byte_count);
3571 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3572 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3574 cFYI(1, ("Send error in QFSInfo = %d", rc));
3575 } else { /* decode response */
3576 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3578 if (rc || (pSMBr->ByteCount < 24))
3579 rc = -EIO; /* bad smb */
3581 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3585 *) (((char *) &pSMBr->hdr.Protocol) +
3588 le32_to_cpu(response_data->BytesPerSector) *
3589 le32_to_cpu(response_data->
3590 SectorsPerAllocationUnit);
3592 le64_to_cpu(response_data->TotalAllocationUnits);
3593 FSData->f_bfree = FSData->f_bavail =
3594 le64_to_cpu(response_data->FreeAllocationUnits);
3596 ("Blocks: %lld Free: %lld Block size %ld",
3597 (unsigned long long)FSData->f_blocks,
3598 (unsigned long long)FSData->f_bfree,
3602 cifs_buf_release(pSMB);
3611 CIFSSMBQFSAttributeInfo(const int xid, struct cifsTconInfo *tcon)
3613 /* level 0x105 SMB_QUERY_FILE_SYSTEM_INFO */
3614 TRANSACTION2_QFSI_REQ *pSMB = NULL;
3615 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
3616 FILE_SYSTEM_ATTRIBUTE_INFO *response_data;
3618 int bytes_returned = 0;
3619 __u16 params, byte_count;
3621 cFYI(1, ("In QFSAttributeInfo"));
3623 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3628 params = 2; /* level */
3629 pSMB->TotalDataCount = 0;
3630 pSMB->MaxParameterCount = cpu_to_le16(2);
3631 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
3632 pSMB->MaxSetupCount = 0;
3636 pSMB->Reserved2 = 0;
3637 byte_count = params + 1 /* pad */ ;
3638 pSMB->TotalParameterCount = cpu_to_le16(params);
3639 pSMB->ParameterCount = pSMB->TotalParameterCount;
3640 pSMB->ParameterOffset = cpu_to_le16(offsetof(
3641 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
3642 pSMB->DataCount = 0;
3643 pSMB->DataOffset = 0;
3644 pSMB->SetupCount = 1;
3645 pSMB->Reserved3 = 0;
3646 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
3647 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_ATTRIBUTE_INFO);
3648 pSMB->hdr.smb_buf_length += byte_count;
3649 pSMB->ByteCount = cpu_to_le16(byte_count);
3651 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3652 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3654 cERROR(1, ("Send error in QFSAttributeInfo = %d", rc));
3655 } else { /* decode response */
3656 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3658 if (rc || (pSMBr->ByteCount < 13)) { /* BB also check enough bytes returned */
3659 rc = -EIO; /* bad smb */
3661 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3663 (FILE_SYSTEM_ATTRIBUTE_INFO
3664 *) (((char *) &pSMBr->hdr.Protocol) +
3666 memcpy(&tcon->fsAttrInfo, response_data,
3667 sizeof (FILE_SYSTEM_ATTRIBUTE_INFO));
3670 cifs_buf_release(pSMB);
3673 goto QFSAttributeRetry;
3679 CIFSSMBQFSDeviceInfo(const int xid, struct cifsTconInfo *tcon)
3681 /* level 0x104 SMB_QUERY_FILE_SYSTEM_INFO */
3682 TRANSACTION2_QFSI_REQ *pSMB = NULL;
3683 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
3684 FILE_SYSTEM_DEVICE_INFO *response_data;
3686 int bytes_returned = 0;
3687 __u16 params, byte_count;
3689 cFYI(1, ("In QFSDeviceInfo"));
3691 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3696 params = 2; /* level */
3697 pSMB->TotalDataCount = 0;
3698 pSMB->MaxParameterCount = cpu_to_le16(2);
3699 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
3700 pSMB->MaxSetupCount = 0;
3704 pSMB->Reserved2 = 0;
3705 byte_count = params + 1 /* pad */ ;
3706 pSMB->TotalParameterCount = cpu_to_le16(params);
3707 pSMB->ParameterCount = pSMB->TotalParameterCount;
3708 pSMB->ParameterOffset = cpu_to_le16(offsetof(
3709 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
3711 pSMB->DataCount = 0;
3712 pSMB->DataOffset = 0;
3713 pSMB->SetupCount = 1;
3714 pSMB->Reserved3 = 0;
3715 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
3716 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_DEVICE_INFO);
3717 pSMB->hdr.smb_buf_length += byte_count;
3718 pSMB->ByteCount = cpu_to_le16(byte_count);
3720 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3721 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3723 cFYI(1, ("Send error in QFSDeviceInfo = %d", rc));
3724 } else { /* decode response */
3725 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3727 if (rc || (pSMBr->ByteCount < sizeof (FILE_SYSTEM_DEVICE_INFO)))
3728 rc = -EIO; /* bad smb */
3730 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3732 (FILE_SYSTEM_DEVICE_INFO *)
3733 (((char *) &pSMBr->hdr.Protocol) +
3735 memcpy(&tcon->fsDevInfo, response_data,
3736 sizeof (FILE_SYSTEM_DEVICE_INFO));
3739 cifs_buf_release(pSMB);
3742 goto QFSDeviceRetry;
3748 CIFSSMBQFSUnixInfo(const int xid, struct cifsTconInfo *tcon)
3750 /* level 0x200 SMB_QUERY_CIFS_UNIX_INFO */
3751 TRANSACTION2_QFSI_REQ *pSMB = NULL;
3752 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
3753 FILE_SYSTEM_UNIX_INFO *response_data;
3755 int bytes_returned = 0;
3756 __u16 params, byte_count;
3758 cFYI(1, ("In QFSUnixInfo"));
3760 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3765 params = 2; /* level */
3766 pSMB->TotalDataCount = 0;
3767 pSMB->DataCount = 0;
3768 pSMB->DataOffset = 0;
3769 pSMB->MaxParameterCount = cpu_to_le16(2);
3770 pSMB->MaxDataCount = cpu_to_le16(100); /* BB find exact max SMB PDU from sess structure BB */
3771 pSMB->MaxSetupCount = 0;
3775 pSMB->Reserved2 = 0;
3776 byte_count = params + 1 /* pad */ ;
3777 pSMB->ParameterCount = cpu_to_le16(params);
3778 pSMB->TotalParameterCount = pSMB->ParameterCount;
3779 pSMB->ParameterOffset = cpu_to_le16(offsetof(struct
3780 smb_com_transaction2_qfsi_req, InformationLevel) - 4);
3781 pSMB->SetupCount = 1;
3782 pSMB->Reserved3 = 0;
3783 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
3784 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_CIFS_UNIX_INFO);
3785 pSMB->hdr.smb_buf_length += byte_count;
3786 pSMB->ByteCount = cpu_to_le16(byte_count);
3788 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3789 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3791 cERROR(1, ("Send error in QFSUnixInfo = %d", rc));
3792 } else { /* decode response */
3793 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3795 if (rc || (pSMBr->ByteCount < 13)) {
3796 rc = -EIO; /* bad smb */
3798 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3800 (FILE_SYSTEM_UNIX_INFO
3801 *) (((char *) &pSMBr->hdr.Protocol) +
3803 memcpy(&tcon->fsUnixInfo, response_data,
3804 sizeof (FILE_SYSTEM_UNIX_INFO));
3807 cifs_buf_release(pSMB);
3817 CIFSSMBSetFSUnixInfo(const int xid, struct cifsTconInfo *tcon, __u64 cap)
3819 /* level 0x200 SMB_SET_CIFS_UNIX_INFO */
3820 TRANSACTION2_SETFSI_REQ *pSMB = NULL;
3821 TRANSACTION2_SETFSI_RSP *pSMBr = NULL;
3823 int bytes_returned = 0;
3824 __u16 params, param_offset, offset, byte_count;
3826 cFYI(1, ("In SETFSUnixInfo"));
3828 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3833 params = 4; /* 2 bytes zero followed by info level. */
3834 pSMB->MaxSetupCount = 0;
3838 pSMB->Reserved2 = 0;
3839 param_offset = offsetof(struct smb_com_transaction2_setfsi_req, FileNum) - 4;
3840 offset = param_offset + params;
3842 pSMB->MaxParameterCount = cpu_to_le16(4);
3843 pSMB->MaxDataCount = cpu_to_le16(100); /* BB find exact max SMB PDU from sess structure BB */
3844 pSMB->SetupCount = 1;
3845 pSMB->Reserved3 = 0;
3846 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FS_INFORMATION);
3847 byte_count = 1 /* pad */ + params + 12;
3849 pSMB->DataCount = cpu_to_le16(12);
3850 pSMB->ParameterCount = cpu_to_le16(params);
3851 pSMB->TotalDataCount = pSMB->DataCount;
3852 pSMB->TotalParameterCount = pSMB->ParameterCount;
3853 pSMB->ParameterOffset = cpu_to_le16(param_offset);
3854 pSMB->DataOffset = cpu_to_le16(offset);
3858 pSMB->InformationLevel = cpu_to_le16(SMB_SET_CIFS_UNIX_INFO);
3861 pSMB->ClientUnixMajor = cpu_to_le16(CIFS_UNIX_MAJOR_VERSION);
3862 pSMB->ClientUnixMinor = cpu_to_le16(CIFS_UNIX_MINOR_VERSION);
3863 pSMB->ClientUnixCap = cpu_to_le64(cap);
3865 pSMB->hdr.smb_buf_length += byte_count;
3866 pSMB->ByteCount = cpu_to_le16(byte_count);
3868 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3869 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3871 cERROR(1, ("Send error in SETFSUnixInfo = %d", rc));
3872 } else { /* decode response */
3873 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3875 rc = -EIO; /* bad smb */
3878 cifs_buf_release(pSMB);
3881 goto SETFSUnixRetry;
3889 CIFSSMBQFSPosixInfo(const int xid, struct cifsTconInfo *tcon,
3890 struct kstatfs *FSData)
3892 /* level 0x201 SMB_QUERY_CIFS_POSIX_INFO */
3893 TRANSACTION2_QFSI_REQ *pSMB = NULL;
3894 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
3895 FILE_SYSTEM_POSIX_INFO *response_data;
3897 int bytes_returned = 0;
3898 __u16 params, byte_count;
3900 cFYI(1, ("In QFSPosixInfo"));
3902 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3907 params = 2; /* level */
3908 pSMB->TotalDataCount = 0;
3909 pSMB->DataCount = 0;
3910 pSMB->DataOffset = 0;
3911 pSMB->MaxParameterCount = cpu_to_le16(2);
3912 pSMB->MaxDataCount = cpu_to_le16(100); /* BB find exact max SMB PDU from sess structure BB */
3913 pSMB->MaxSetupCount = 0;
3917 pSMB->Reserved2 = 0;
3918 byte_count = params + 1 /* pad */ ;
3919 pSMB->ParameterCount = cpu_to_le16(params);
3920 pSMB->TotalParameterCount = pSMB->ParameterCount;
3921 pSMB->ParameterOffset = cpu_to_le16(offsetof(struct
3922 smb_com_transaction2_qfsi_req, InformationLevel) - 4);
3923 pSMB->SetupCount = 1;
3924 pSMB->Reserved3 = 0;
3925 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
3926 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_POSIX_FS_INFO);
3927 pSMB->hdr.smb_buf_length += byte_count;
3928 pSMB->ByteCount = cpu_to_le16(byte_count);
3930 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3931 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3933 cFYI(1, ("Send error in QFSUnixInfo = %d", rc));
3934 } else { /* decode response */
3935 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3937 if (rc || (pSMBr->ByteCount < 13)) {
3938 rc = -EIO; /* bad smb */
3940 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3942 (FILE_SYSTEM_POSIX_INFO
3943 *) (((char *) &pSMBr->hdr.Protocol) +
3946 le32_to_cpu(response_data->BlockSize);
3948 le64_to_cpu(response_data->TotalBlocks);
3950 le64_to_cpu(response_data->BlocksAvail);
3951 if(response_data->UserBlocksAvail == cpu_to_le64(-1)) {
3952 FSData->f_bavail = FSData->f_bfree;
3955 le64_to_cpu(response_data->UserBlocksAvail);
3957 if(response_data->TotalFileNodes != cpu_to_le64(-1))
3959 le64_to_cpu(response_data->TotalFileNodes);
3960 if(response_data->FreeFileNodes != cpu_to_le64(-1))
3962 le64_to_cpu(response_data->FreeFileNodes);
3965 cifs_buf_release(pSMB);
3974 /* We can not use write of zero bytes trick to
3975 set file size due to need for large file support. Also note that
3976 this SetPathInfo is preferred to SetFileInfo based method in next
3977 routine which is only needed to work around a sharing violation bug
3978 in Samba which this routine can run into */
3981 CIFSSMBSetEOF(const int xid, struct cifsTconInfo *tcon, const char *fileName,
3982 __u64 size, int SetAllocation,
3983 const struct nls_table *nls_codepage, int remap)
3985 struct smb_com_transaction2_spi_req *pSMB = NULL;
3986 struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
3987 struct file_end_of_file_info *parm_data;
3990 int bytes_returned = 0;
3991 __u16 params, byte_count, data_count, param_offset, offset;
3993 cFYI(1, ("In SetEOF"));
3995 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4000 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4002 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
4003 PATH_MAX, nls_codepage, remap);
4004 name_len++; /* trailing null */
4006 } else { /* BB improve the check for buffer overruns BB */
4007 name_len = strnlen(fileName, PATH_MAX);
4008 name_len++; /* trailing null */
4009 strncpy(pSMB->FileName, fileName, name_len);
4011 params = 6 + name_len;
4012 data_count = sizeof (struct file_end_of_file_info);
4013 pSMB->MaxParameterCount = cpu_to_le16(2);
4014 pSMB->MaxDataCount = cpu_to_le16(4100);
4015 pSMB->MaxSetupCount = 0;
4019 pSMB->Reserved2 = 0;
4020 param_offset = offsetof(struct smb_com_transaction2_spi_req,
4021 InformationLevel) - 4;
4022 offset = param_offset + params;
4024 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
4025 pSMB->InformationLevel =
4026 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2);
4028 pSMB->InformationLevel =
4029 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO);
4030 } else /* Set File Size */ {
4031 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
4032 pSMB->InformationLevel =
4033 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO2);
4035 pSMB->InformationLevel =
4036 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO);
4040 (struct file_end_of_file_info *) (((char *) &pSMB->hdr.Protocol) +
4042 pSMB->ParameterOffset = cpu_to_le16(param_offset);
4043 pSMB->DataOffset = cpu_to_le16(offset);
4044 pSMB->SetupCount = 1;
4045 pSMB->Reserved3 = 0;
4046 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
4047 byte_count = 3 /* pad */ + params + data_count;
4048 pSMB->DataCount = cpu_to_le16(data_count);
4049 pSMB->TotalDataCount = pSMB->DataCount;
4050 pSMB->ParameterCount = cpu_to_le16(params);
4051 pSMB->TotalParameterCount = pSMB->ParameterCount;
4052 pSMB->Reserved4 = 0;
4053 pSMB->hdr.smb_buf_length += byte_count;
4054 parm_data->FileSize = cpu_to_le64(size);
4055 pSMB->ByteCount = cpu_to_le16(byte_count);
4056 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4057 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4059 cFYI(1, ("SetPathInfo (file size) returned %d", rc));
4062 cifs_buf_release(pSMB);
4071 CIFSSMBSetFileSize(const int xid, struct cifsTconInfo *tcon, __u64 size,
4072 __u16 fid, __u32 pid_of_opener, int SetAllocation)
4074 struct smb_com_transaction2_sfi_req *pSMB = NULL;
4075 struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
4077 struct file_end_of_file_info *parm_data;
4079 int bytes_returned = 0;
4080 __u16 params, param_offset, offset, byte_count, count;
4082 cFYI(1, ("SetFileSize (via SetFileInfo) %lld",
4084 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
4089 pSMBr = (struct smb_com_transaction2_sfi_rsp *)pSMB;
4091 pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
4092 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));
4095 pSMB->MaxSetupCount = 0;
4099 pSMB->Reserved2 = 0;
4100 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
4101 offset = param_offset + params;
4103 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
4105 count = sizeof(struct file_end_of_file_info);
4106 pSMB->MaxParameterCount = cpu_to_le16(2);
4107 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB PDU from sess */
4108 pSMB->SetupCount = 1;
4109 pSMB->Reserved3 = 0;
4110 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
4111 byte_count = 3 /* pad */ + params + count;
4112 pSMB->DataCount = cpu_to_le16(count);
4113 pSMB->ParameterCount = cpu_to_le16(params);
4114 pSMB->TotalDataCount = pSMB->DataCount;
4115 pSMB->TotalParameterCount = pSMB->ParameterCount;
4116 pSMB->ParameterOffset = cpu_to_le16(param_offset);
4118 (struct file_end_of_file_info *) (((char *) &pSMB->hdr.Protocol) +
4120 pSMB->DataOffset = cpu_to_le16(offset);
4121 parm_data->FileSize = cpu_to_le64(size);
4124 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
4125 pSMB->InformationLevel =
4126 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2);
4128 pSMB->InformationLevel =
4129 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO);
4130 } else /* Set File Size */ {
4131 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
4132 pSMB->InformationLevel =
4133 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO2);
4135 pSMB->InformationLevel =
4136 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO);
4138 pSMB->Reserved4 = 0;
4139 pSMB->hdr.smb_buf_length += byte_count;
4140 pSMB->ByteCount = cpu_to_le16(byte_count);
4141 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4142 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4145 ("Send error in SetFileInfo (SetFileSize) = %d",
4150 cifs_small_buf_release(pSMB);
4152 /* Note: On -EAGAIN error only caller can retry on handle based calls
4153 since file handle passed in no longer valid */
4158 /* Some legacy servers such as NT4 require that the file times be set on
4159 an open handle, rather than by pathname - this is awkward due to
4160 potential access conflicts on the open, but it is unavoidable for these
4161 old servers since the only other choice is to go from 100 nanosecond DCE
4162 time and resort to the original setpathinfo level which takes the ancient
4163 DOS time format with 2 second granularity */
4165 CIFSSMBSetFileTimes(const int xid, struct cifsTconInfo *tcon, const FILE_BASIC_INFO * data,
4168 struct smb_com_transaction2_sfi_req *pSMB = NULL;
4169 struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
4172 int bytes_returned = 0;
4173 __u16 params, param_offset, offset, byte_count, count;
4175 cFYI(1, ("Set Times (via SetFileInfo)"));
4176 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
4181 pSMBr = (struct smb_com_transaction2_sfi_rsp *)pSMB;
4183 /* At this point there is no need to override the current pid
4184 with the pid of the opener, but that could change if we someday
4185 use an existing handle (rather than opening one on the fly) */
4186 /* pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
4187 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));*/
4190 pSMB->MaxSetupCount = 0;
4194 pSMB->Reserved2 = 0;
4195 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
4196 offset = param_offset + params;
4198 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
4200 count = sizeof (FILE_BASIC_INFO);
4201 pSMB->MaxParameterCount = cpu_to_le16(2);
4202 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB PDU from sess */
4203 pSMB->SetupCount = 1;
4204 pSMB->Reserved3 = 0;
4205 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
4206 byte_count = 3 /* pad */ + params + count;
4207 pSMB->DataCount = cpu_to_le16(count);
4208 pSMB->ParameterCount = cpu_to_le16(params);
4209 pSMB->TotalDataCount = pSMB->DataCount;
4210 pSMB->TotalParameterCount = pSMB->ParameterCount;
4211 pSMB->ParameterOffset = cpu_to_le16(param_offset);
4212 pSMB->DataOffset = cpu_to_le16(offset);
4214 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
4215 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO2);
4217 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO);
4218 pSMB->Reserved4 = 0;
4219 pSMB->hdr.smb_buf_length += byte_count;
4220 pSMB->ByteCount = cpu_to_le16(byte_count);
4221 memcpy(data_offset,data,sizeof(FILE_BASIC_INFO));
4222 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4223 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4225 cFYI(1,("Send error in Set Time (SetFileInfo) = %d",rc));
4228 cifs_small_buf_release(pSMB);
4230 /* Note: On -EAGAIN error only caller can retry on handle based calls
4231 since file handle passed in no longer valid */
4238 CIFSSMBSetTimes(const int xid, struct cifsTconInfo *tcon, const char *fileName,
4239 const FILE_BASIC_INFO * data,
4240 const struct nls_table *nls_codepage, int remap)
4242 TRANSACTION2_SPI_REQ *pSMB = NULL;
4243 TRANSACTION2_SPI_RSP *pSMBr = NULL;
4246 int bytes_returned = 0;
4248 __u16 params, param_offset, offset, byte_count, count;
4250 cFYI(1, ("In SetTimes"));
4253 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4258 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4260 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
4261 PATH_MAX, nls_codepage, remap);
4262 name_len++; /* trailing null */
4264 } else { /* BB improve the check for buffer overruns BB */
4265 name_len = strnlen(fileName, PATH_MAX);
4266 name_len++; /* trailing null */
4267 strncpy(pSMB->FileName, fileName, name_len);
4270 params = 6 + name_len;
4271 count = sizeof (FILE_BASIC_INFO);
4272 pSMB->MaxParameterCount = cpu_to_le16(2);
4273 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
4274 pSMB->MaxSetupCount = 0;
4278 pSMB->Reserved2 = 0;
4279 param_offset = offsetof(struct smb_com_transaction2_spi_req,
4280 InformationLevel) - 4;
4281 offset = param_offset + params;
4282 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
4283 pSMB->ParameterOffset = cpu_to_le16(param_offset);
4284 pSMB->DataOffset = cpu_to_le16(offset);
4285 pSMB->SetupCount = 1;
4286 pSMB->Reserved3 = 0;
4287 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
4288 byte_count = 3 /* pad */ + params + count;
4290 pSMB->DataCount = cpu_to_le16(count);
4291 pSMB->ParameterCount = cpu_to_le16(params);
4292 pSMB->TotalDataCount = pSMB->DataCount;
4293 pSMB->TotalParameterCount = pSMB->ParameterCount;
4294 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
4295 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO2);
4297 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO);
4298 pSMB->Reserved4 = 0;
4299 pSMB->hdr.smb_buf_length += byte_count;
4300 memcpy(data_offset, data, sizeof (FILE_BASIC_INFO));
4301 pSMB->ByteCount = cpu_to_le16(byte_count);
4302 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4303 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4305 cFYI(1, ("SetPathInfo (times) returned %d", rc));
4308 cifs_buf_release(pSMB);
4316 /* Can not be used to set time stamps yet (due to old DOS time format) */
4317 /* Can be used to set attributes */
4318 #if 0 /* Possibly not needed - since it turns out that strangely NT4 has a bug
4319 handling it anyway and NT4 was what we thought it would be needed for
4320 Do not delete it until we prove whether needed for Win9x though */
4322 CIFSSMBSetAttrLegacy(int xid, struct cifsTconInfo *tcon, char *fileName,
4323 __u16 dos_attrs, const struct nls_table *nls_codepage)
4325 SETATTR_REQ *pSMB = NULL;
4326 SETATTR_RSP *pSMBr = NULL;
4331 cFYI(1, ("In SetAttrLegacy"));
4334 rc = smb_init(SMB_COM_SETATTR, 8, tcon, (void **) &pSMB,
4339 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4341 ConvertToUCS((__le16 *) pSMB->fileName, fileName,
4342 PATH_MAX, nls_codepage);
4343 name_len++; /* trailing null */
4345 } else { /* BB improve the check for buffer overruns BB */
4346 name_len = strnlen(fileName, PATH_MAX);
4347 name_len++; /* trailing null */
4348 strncpy(pSMB->fileName, fileName, name_len);
4350 pSMB->attr = cpu_to_le16(dos_attrs);
4351 pSMB->BufferFormat = 0x04;
4352 pSMB->hdr.smb_buf_length += name_len + 1;
4353 pSMB->ByteCount = cpu_to_le16(name_len + 1);
4354 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4355 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4357 cFYI(1, ("Error in LegacySetAttr = %d", rc));
4360 cifs_buf_release(pSMB);
4363 goto SetAttrLgcyRetry;
4367 #endif /* temporarily unneeded SetAttr legacy function */
4370 CIFSSMBUnixSetPerms(const int xid, struct cifsTconInfo *tcon,
4371 char *fileName, __u64 mode, __u64 uid, __u64 gid,
4372 dev_t device, const struct nls_table *nls_codepage,
4375 TRANSACTION2_SPI_REQ *pSMB = NULL;
4376 TRANSACTION2_SPI_RSP *pSMBr = NULL;
4379 int bytes_returned = 0;
4380 FILE_UNIX_BASIC_INFO *data_offset;
4381 __u16 params, param_offset, offset, count, byte_count;
4383 cFYI(1, ("In SetUID/GID/Mode"));
4385 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4390 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4392 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
4393 PATH_MAX, nls_codepage, remap);
4394 name_len++; /* trailing null */
4396 } else { /* BB improve the check for buffer overruns BB */
4397 name_len = strnlen(fileName, PATH_MAX);
4398 name_len++; /* trailing null */
4399 strncpy(pSMB->FileName, fileName, name_len);
4402 params = 6 + name_len;
4403 count = sizeof (FILE_UNIX_BASIC_INFO);
4404 pSMB->MaxParameterCount = cpu_to_le16(2);
4405 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
4406 pSMB->MaxSetupCount = 0;
4410 pSMB->Reserved2 = 0;
4411 param_offset = offsetof(struct smb_com_transaction2_spi_req,
4412 InformationLevel) - 4;
4413 offset = param_offset + params;
4415 (FILE_UNIX_BASIC_INFO *) ((char *) &pSMB->hdr.Protocol +
4417 memset(data_offset, 0, count);
4418 pSMB->DataOffset = cpu_to_le16(offset);
4419 pSMB->ParameterOffset = cpu_to_le16(param_offset);
4420 pSMB->SetupCount = 1;
4421 pSMB->Reserved3 = 0;
4422 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
4423 byte_count = 3 /* pad */ + params + count;
4424 pSMB->ParameterCount = cpu_to_le16(params);
4425 pSMB->DataCount = cpu_to_le16(count);
4426 pSMB->TotalParameterCount = pSMB->ParameterCount;
4427 pSMB->TotalDataCount = pSMB->DataCount;
4428 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_BASIC);
4429 pSMB->Reserved4 = 0;
4430 pSMB->hdr.smb_buf_length += byte_count;
4431 data_offset->Uid = cpu_to_le64(uid);
4432 data_offset->Gid = cpu_to_le64(gid);
4433 /* better to leave device as zero when it is */
4434 data_offset->DevMajor = cpu_to_le64(MAJOR(device));
4435 data_offset->DevMinor = cpu_to_le64(MINOR(device));
4436 data_offset->Permissions = cpu_to_le64(mode);
4439 data_offset->Type = cpu_to_le32(UNIX_FILE);
4440 else if(S_ISDIR(mode))
4441 data_offset->Type = cpu_to_le32(UNIX_DIR);
4442 else if(S_ISLNK(mode))
4443 data_offset->Type = cpu_to_le32(UNIX_SYMLINK);
4444 else if(S_ISCHR(mode))
4445 data_offset->Type = cpu_to_le32(UNIX_CHARDEV);
4446 else if(S_ISBLK(mode))
4447 data_offset->Type = cpu_to_le32(UNIX_BLOCKDEV);
4448 else if(S_ISFIFO(mode))
4449 data_offset->Type = cpu_to_le32(UNIX_FIFO);
4450 else if(S_ISSOCK(mode))
4451 data_offset->Type = cpu_to_le32(UNIX_SOCKET);
4454 pSMB->ByteCount = cpu_to_le16(byte_count);
4455 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4456 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4458 cFYI(1, ("SetPathInfo (perms) returned %d", rc));
4462 cifs_buf_release(pSMB);
4468 int CIFSSMBNotify(const int xid, struct cifsTconInfo *tcon,
4469 const int notify_subdirs, const __u16 netfid,
4470 __u32 filter, struct file * pfile, int multishot,
4471 const struct nls_table *nls_codepage)
4474 struct smb_com_transaction_change_notify_req * pSMB = NULL;
4475 struct smb_com_ntransaction_change_notify_rsp * pSMBr = NULL;
4476 struct dir_notify_req *dnotify_req;
4479 cFYI(1, ("In CIFSSMBNotify for file handle %d",(int)netfid));
4480 rc = smb_init(SMB_COM_NT_TRANSACT, 23, tcon, (void **) &pSMB,
4485 pSMB->TotalParameterCount = 0 ;
4486 pSMB->TotalDataCount = 0;
4487 pSMB->MaxParameterCount = cpu_to_le32(2);
4488 /* BB find exact data count max from sess structure BB */
4489 pSMB->MaxDataCount = 0; /* same in little endian or be */
4490 /* BB VERIFY verify which is correct for above BB */
4491 pSMB->MaxDataCount = cpu_to_le32((tcon->ses->server->maxBuf -
4492 MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
4494 pSMB->MaxSetupCount = 4;
4496 pSMB->ParameterOffset = 0;
4497 pSMB->DataCount = 0;
4498 pSMB->DataOffset = 0;
4499 pSMB->SetupCount = 4; /* single byte does not need le conversion */
4500 pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_NOTIFY_CHANGE);
4501 pSMB->ParameterCount = pSMB->TotalParameterCount;
4503 pSMB->WatchTree = 1; /* one byte - no le conversion needed */
4504 pSMB->Reserved2 = 0;
4505 pSMB->CompletionFilter = cpu_to_le32(filter);
4506 pSMB->Fid = netfid; /* file handle always le */
4507 pSMB->ByteCount = 0;
4509 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4510 (struct smb_hdr *) pSMBr, &bytes_returned, -1);
4512 cFYI(1, ("Error in Notify = %d", rc));
4514 /* Add file to outstanding requests */
4515 /* BB change to kmem cache alloc */
4516 dnotify_req = (struct dir_notify_req *) kmalloc(
4517 sizeof(struct dir_notify_req),
4520 dnotify_req->Pid = pSMB->hdr.Pid;
4521 dnotify_req->PidHigh = pSMB->hdr.PidHigh;
4522 dnotify_req->Mid = pSMB->hdr.Mid;
4523 dnotify_req->Tid = pSMB->hdr.Tid;
4524 dnotify_req->Uid = pSMB->hdr.Uid;
4525 dnotify_req->netfid = netfid;
4526 dnotify_req->pfile = pfile;
4527 dnotify_req->filter = filter;
4528 dnotify_req->multishot = multishot;
4529 spin_lock(&GlobalMid_Lock);
4530 list_add_tail(&dnotify_req->lhead,
4531 &GlobalDnotifyReqList);
4532 spin_unlock(&GlobalMid_Lock);
4536 cifs_buf_release(pSMB);
4539 #ifdef CONFIG_CIFS_XATTR
4541 CIFSSMBQAllEAs(const int xid, struct cifsTconInfo *tcon,
4542 const unsigned char *searchName,
4543 char * EAData, size_t buf_size,
4544 const struct nls_table *nls_codepage, int remap)
4546 /* BB assumes one setup word */
4547 TRANSACTION2_QPI_REQ *pSMB = NULL;
4548 TRANSACTION2_QPI_RSP *pSMBr = NULL;
4552 struct fea * temp_fea;
4554 __u16 params, byte_count;
4556 cFYI(1, ("In Query All EAs path %s", searchName));
4558 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4563 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4565 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
4566 PATH_MAX, nls_codepage, remap);
4567 name_len++; /* trailing null */
4569 } else { /* BB improve the check for buffer overruns BB */
4570 name_len = strnlen(searchName, PATH_MAX);
4571 name_len++; /* trailing null */
4572 strncpy(pSMB->FileName, searchName, name_len);
4575 params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */ ;
4576 pSMB->TotalDataCount = 0;
4577 pSMB->MaxParameterCount = cpu_to_le16(2);
4578 pSMB->MaxDataCount = cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
4579 pSMB->MaxSetupCount = 0;
4583 pSMB->Reserved2 = 0;
4584 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4585 struct smb_com_transaction2_qpi_req ,InformationLevel) - 4);
4586 pSMB->DataCount = 0;
4587 pSMB->DataOffset = 0;
4588 pSMB->SetupCount = 1;
4589 pSMB->Reserved3 = 0;
4590 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
4591 byte_count = params + 1 /* pad */ ;
4592 pSMB->TotalParameterCount = cpu_to_le16(params);
4593 pSMB->ParameterCount = pSMB->TotalParameterCount;
4594 pSMB->InformationLevel = cpu_to_le16(SMB_INFO_QUERY_ALL_EAS);
4595 pSMB->Reserved4 = 0;
4596 pSMB->hdr.smb_buf_length += byte_count;
4597 pSMB->ByteCount = cpu_to_le16(byte_count);
4599 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4600 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4602 cFYI(1, ("Send error in QueryAllEAs = %d", rc));
4603 } else { /* decode response */
4604 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4606 /* BB also check enough total bytes returned */
4607 /* BB we need to improve the validity checking
4608 of these trans2 responses */
4609 if (rc || (pSMBr->ByteCount < 4))
4610 rc = -EIO; /* bad smb */
4611 /* else if (pFindData){
4612 memcpy((char *) pFindData,
4613 (char *) &pSMBr->hdr.Protocol +
4616 /* check that length of list is not more than bcc */
4617 /* check that each entry does not go beyond length
4619 /* check that each element of each entry does not
4620 go beyond end of list */
4621 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4622 struct fealist * ea_response_data;
4624 /* validate_trans2_offsets() */
4625 /* BB to check if(start of smb + data_offset > &bcc+ bcc)*/
4626 ea_response_data = (struct fealist *)
4627 (((char *) &pSMBr->hdr.Protocol) +
4629 name_len = le32_to_cpu(ea_response_data->list_len);
4630 cFYI(1,("ea length %d", name_len));
4632 /* returned EA size zeroed at top of function */
4633 cFYI(1,("empty EA list returned from server"));
4635 /* account for ea list len */
4637 temp_fea = ea_response_data->list;
4638 temp_ptr = (char *)temp_fea;
4639 while(name_len > 0) {
4643 rc += temp_fea->name_len;
4644 /* account for prefix user. and trailing null */
4646 if(rc<(int)buf_size) {
4647 memcpy(EAData,"user.",5);
4649 memcpy(EAData,temp_ptr,temp_fea->name_len);
4650 EAData+=temp_fea->name_len;
4651 /* null terminate name */
4653 EAData = EAData + 1;
4654 } else if(buf_size == 0) {
4655 /* skip copy - calc size only */
4657 /* stop before overrun buffer */
4661 name_len -= temp_fea->name_len;
4662 temp_ptr += temp_fea->name_len;
4663 /* account for trailing null */
4666 value_len = le16_to_cpu(temp_fea->value_len);
4667 name_len -= value_len;
4668 temp_ptr += value_len;
4669 /* BB check that temp_ptr is still within smb BB*/
4670 /* no trailing null to account for in value len */
4671 /* go on to next EA */
4672 temp_fea = (struct fea *)temp_ptr;
4678 cifs_buf_release(pSMB);
4685 ssize_t CIFSSMBQueryEA(const int xid,struct cifsTconInfo * tcon,
4686 const unsigned char * searchName,const unsigned char * ea_name,
4687 unsigned char * ea_value, size_t buf_size,
4688 const struct nls_table *nls_codepage, int remap)
4690 TRANSACTION2_QPI_REQ *pSMB = NULL;
4691 TRANSACTION2_QPI_RSP *pSMBr = NULL;
4695 struct fea * temp_fea;
4697 __u16 params, byte_count;
4699 cFYI(1, ("In Query EA path %s", searchName));
4701 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4706 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4708 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
4709 PATH_MAX, nls_codepage, remap);
4710 name_len++; /* trailing null */
4712 } else { /* BB improve the check for buffer overruns BB */
4713 name_len = strnlen(searchName, PATH_MAX);
4714 name_len++; /* trailing null */
4715 strncpy(pSMB->FileName, searchName, name_len);
4718 params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */ ;
4719 pSMB->TotalDataCount = 0;
4720 pSMB->MaxParameterCount = cpu_to_le16(2);
4721 pSMB->MaxDataCount = cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
4722 pSMB->MaxSetupCount = 0;
4726 pSMB->Reserved2 = 0;
4727 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4728 struct smb_com_transaction2_qpi_req ,InformationLevel) - 4);
4729 pSMB->DataCount = 0;
4730 pSMB->DataOffset = 0;
4731 pSMB->SetupCount = 1;
4732 pSMB->Reserved3 = 0;
4733 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
4734 byte_count = params + 1 /* pad */ ;
4735 pSMB->TotalParameterCount = cpu_to_le16(params);
4736 pSMB->ParameterCount = pSMB->TotalParameterCount;
4737 pSMB->InformationLevel = cpu_to_le16(SMB_INFO_QUERY_ALL_EAS);
4738 pSMB->Reserved4 = 0;
4739 pSMB->hdr.smb_buf_length += byte_count;
4740 pSMB->ByteCount = cpu_to_le16(byte_count);
4742 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4743 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4745 cFYI(1, ("Send error in Query EA = %d", rc));
4746 } else { /* decode response */
4747 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4749 /* BB also check enough total bytes returned */
4750 /* BB we need to improve the validity checking
4751 of these trans2 responses */
4752 if (rc || (pSMBr->ByteCount < 4))
4753 rc = -EIO; /* bad smb */
4754 /* else if (pFindData){
4755 memcpy((char *) pFindData,
4756 (char *) &pSMBr->hdr.Protocol +
4759 /* check that length of list is not more than bcc */
4760 /* check that each entry does not go beyond length
4762 /* check that each element of each entry does not
4763 go beyond end of list */
4764 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4765 struct fealist * ea_response_data;
4767 /* validate_trans2_offsets() */
4768 /* BB to check if(start of smb + data_offset > &bcc+ bcc)*/
4769 ea_response_data = (struct fealist *)
4770 (((char *) &pSMBr->hdr.Protocol) +
4772 name_len = le32_to_cpu(ea_response_data->list_len);
4773 cFYI(1,("ea length %d", name_len));
4775 /* returned EA size zeroed at top of function */
4776 cFYI(1,("empty EA list returned from server"));
4778 /* account for ea list len */
4780 temp_fea = ea_response_data->list;
4781 temp_ptr = (char *)temp_fea;
4782 /* loop through checking if we have a matching
4783 name and then return the associated value */
4784 while(name_len > 0) {
4788 value_len = le16_to_cpu(temp_fea->value_len);
4789 /* BB validate that value_len falls within SMB,
4790 even though maximum for name_len is 255 */
4791 if(memcmp(temp_fea->name,ea_name,
4792 temp_fea->name_len) == 0) {
4795 /* account for prefix user. and trailing null */
4796 if(rc<=(int)buf_size) {
4798 temp_fea->name+temp_fea->name_len+1,
4800 /* ea values, unlike ea names,
4801 are not null terminated */
4802 } else if(buf_size == 0) {
4803 /* skip copy - calc size only */
4805 /* stop before overrun buffer */
4810 name_len -= temp_fea->name_len;
4811 temp_ptr += temp_fea->name_len;
4812 /* account for trailing null */
4815 name_len -= value_len;
4816 temp_ptr += value_len;
4817 /* no trailing null to account for in value len */
4818 /* go on to next EA */
4819 temp_fea = (struct fea *)temp_ptr;
4825 cifs_buf_release(pSMB);
4833 CIFSSMBSetEA(const int xid, struct cifsTconInfo *tcon, const char *fileName,
4834 const char * ea_name, const void * ea_value,
4835 const __u16 ea_value_len, const struct nls_table *nls_codepage,
4838 struct smb_com_transaction2_spi_req *pSMB = NULL;
4839 struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
4840 struct fealist *parm_data;
4843 int bytes_returned = 0;
4844 __u16 params, param_offset, byte_count, offset, count;
4846 cFYI(1, ("In SetEA"));
4848 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4853 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4855 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
4856 PATH_MAX, nls_codepage, remap);
4857 name_len++; /* trailing null */
4859 } else { /* BB improve the check for buffer overruns BB */
4860 name_len = strnlen(fileName, PATH_MAX);
4861 name_len++; /* trailing null */
4862 strncpy(pSMB->FileName, fileName, name_len);
4865 params = 6 + name_len;
4867 /* done calculating parms using name_len of file name,
4868 now use name_len to calculate length of ea name
4869 we are going to create in the inode xattrs */
4873 name_len = strnlen(ea_name,255);
4875 count = sizeof(*parm_data) + ea_value_len + name_len + 1;
4876 pSMB->MaxParameterCount = cpu_to_le16(2);
4877 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB size from sess */
4878 pSMB->MaxSetupCount = 0;
4882 pSMB->Reserved2 = 0;
4883 param_offset = offsetof(struct smb_com_transaction2_spi_req,
4884 InformationLevel) - 4;
4885 offset = param_offset + params;
4886 pSMB->InformationLevel =
4887 cpu_to_le16(SMB_SET_FILE_EA);
4890 (struct fealist *) (((char *) &pSMB->hdr.Protocol) +
4892 pSMB->ParameterOffset = cpu_to_le16(param_offset);
4893 pSMB->DataOffset = cpu_to_le16(offset);
4894 pSMB->SetupCount = 1;
4895 pSMB->Reserved3 = 0;
4896 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
4897 byte_count = 3 /* pad */ + params + count;
4898 pSMB->DataCount = cpu_to_le16(count);
4899 parm_data->list_len = cpu_to_le32(count);
4900 parm_data->list[0].EA_flags = 0;
4901 /* we checked above that name len is less than 255 */
4902 parm_data->list[0].name_len = (__u8)name_len;;
4903 /* EA names are always ASCII */
4905 strncpy(parm_data->list[0].name,ea_name,name_len);
4906 parm_data->list[0].name[name_len] = 0;
4907 parm_data->list[0].value_len = cpu_to_le16(ea_value_len);
4908 /* caller ensures that ea_value_len is less than 64K but
4909 we need to ensure that it fits within the smb */
4911 /*BB add length check that it would fit in negotiated SMB buffer size BB */
4912 /* if(ea_value_len > buffer_size - 512 (enough for header)) */
4914 memcpy(parm_data->list[0].name+name_len+1,ea_value,ea_value_len);
4916 pSMB->TotalDataCount = pSMB->DataCount;
4917 pSMB->ParameterCount = cpu_to_le16(params);
4918 pSMB->TotalParameterCount = pSMB->ParameterCount;
4919 pSMB->Reserved4 = 0;
4920 pSMB->hdr.smb_buf_length += byte_count;
4921 pSMB->ByteCount = cpu_to_le16(byte_count);
4922 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4923 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4925 cFYI(1, ("SetPathInfo (EA) returned %d", rc));
4928 cifs_buf_release(pSMB);