4 * Copyright (C) International Business Machines Corp., 2002,2006
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"
42 #ifdef CONFIG_CIFS_POSIX
47 {CIFS_PROT, "\2NT LM 0.12"},
48 {CIFS_PROT, "\2POSIX 2"},
56 {CIFS_PROT, "\2NT LM 0.12"},
62 /* Mark as invalid, all open files on tree connections since they
63 were closed when session to server was lost */
64 static void mark_open_files_invalid(struct cifsTconInfo * pTcon)
66 struct cifsFileInfo *open_file = NULL;
67 struct list_head * tmp;
68 struct list_head * tmp1;
70 /* list all files open on tree connection and mark them invalid */
71 write_lock(&GlobalSMBSeslock);
72 list_for_each_safe(tmp, tmp1, &pTcon->openFileList) {
73 open_file = list_entry(tmp,struct cifsFileInfo, tlist);
75 open_file->invalidHandle = TRUE;
78 write_unlock(&GlobalSMBSeslock);
79 /* BB Add call to invalidate_inodes(sb) for all superblocks mounted
83 /* If the return code is zero, this function must fill in request_buf pointer */
85 small_smb_init(int smb_command, int wct, struct cifsTconInfo *tcon,
86 void **request_buf /* returned */)
90 /* SMBs NegProt, SessSetup, uLogoff do not have tcon yet so
91 check for tcp and smb session status done differently
92 for those three - in the calling routine */
94 if(tcon->tidStatus == CifsExiting) {
95 /* only tree disconnect, open, and write,
96 (and ulogoff which does not have tcon)
97 are allowed as we start force umount */
98 if((smb_command != SMB_COM_WRITE_ANDX) &&
99 (smb_command != SMB_COM_OPEN_ANDX) &&
100 (smb_command != SMB_COM_TREE_DISCONNECT)) {
101 cFYI(1,("can not send cmd %d while umounting",
106 if((tcon->ses) && (tcon->ses->status != CifsExiting) &&
107 (tcon->ses->server)){
108 struct nls_table *nls_codepage;
109 /* Give Demultiplex thread up to 10 seconds to
110 reconnect, should be greater than cifs socket
111 timeout which is 7 seconds */
112 while(tcon->ses->server->tcpStatus == CifsNeedReconnect) {
113 wait_event_interruptible_timeout(tcon->ses->server->response_q,
114 (tcon->ses->server->tcpStatus == CifsGood), 10 * HZ);
115 if(tcon->ses->server->tcpStatus == CifsNeedReconnect) {
116 /* on "soft" mounts we wait once */
117 if((tcon->retry == FALSE) ||
118 (tcon->ses->status == CifsExiting)) {
119 cFYI(1,("gave up waiting on reconnect in smb_init"));
121 } /* else "hard" mount - keep retrying
122 until process is killed or server
123 comes back on-line */
124 } else /* TCP session is reestablished now */
129 nls_codepage = load_nls_default();
130 /* need to prevent multiple threads trying to
131 simultaneously reconnect the same SMB session */
132 down(&tcon->ses->sesSem);
133 if(tcon->ses->status == CifsNeedReconnect)
134 rc = cifs_setup_session(0, tcon->ses,
136 if(!rc && (tcon->tidStatus == CifsNeedReconnect)) {
137 mark_open_files_invalid(tcon);
138 rc = CIFSTCon(0, tcon->ses, tcon->treeName, tcon
140 up(&tcon->ses->sesSem);
141 /* BB FIXME add code to check if wsize needs
142 update due to negotiated smb buffer size
145 atomic_inc(&tconInfoReconnectCount);
147 cFYI(1, ("reconnect tcon rc = %d", rc));
148 /* Removed call to reopen open files here -
149 it is safer (and faster) to reopen files
150 one at a time as needed in read and write */
152 /* Check if handle based operation so we
153 know whether we can continue or not without
154 returning to caller to reset file handle */
155 switch(smb_command) {
156 case SMB_COM_READ_ANDX:
157 case SMB_COM_WRITE_ANDX:
159 case SMB_COM_FIND_CLOSE2:
160 case SMB_COM_LOCKING_ANDX: {
161 unload_nls(nls_codepage);
166 up(&tcon->ses->sesSem);
168 unload_nls(nls_codepage);
177 *request_buf = cifs_small_buf_get();
178 if (*request_buf == NULL) {
179 /* BB should we add a retry in here if not a writepage? */
183 header_assemble((struct smb_hdr *) *request_buf, smb_command, tcon,wct);
186 cifs_stats_inc(&tcon->num_smbs_sent);
191 #ifdef CONFIG_CIFS_EXPERIMENTAL
193 small_smb_init_no_tc(const int smb_command, const int wct,
194 struct cifsSesInfo *ses, void **request_buf)
197 struct smb_hdr * buffer;
199 rc = small_smb_init(smb_command, wct, NULL, request_buf);
203 buffer = (struct smb_hdr *)*request_buf;
204 buffer->Mid = GetNextMid(ses->server);
205 if (ses->capabilities & CAP_UNICODE)
206 buffer->Flags2 |= SMBFLG2_UNICODE;
207 if (ses->capabilities & CAP_STATUS32)
208 buffer->Flags2 |= SMBFLG2_ERR_STATUS;
210 /* uid, tid can stay at zero as set in header assemble */
212 /* BB add support for turning on the signing when
213 this function is used after 1st of session setup requests */
217 #endif /* CONFIG_CIFS_EXPERIMENTAL */
219 /* If the return code is zero, this function must fill in request_buf pointer */
221 smb_init(int smb_command, int wct, struct cifsTconInfo *tcon,
222 void **request_buf /* returned */ ,
223 void **response_buf /* returned */ )
227 /* SMBs NegProt, SessSetup, uLogoff do not have tcon yet so
228 check for tcp and smb session status done differently
229 for those three - in the calling routine */
231 if(tcon->tidStatus == CifsExiting) {
232 /* only tree disconnect, open, and write,
233 (and ulogoff which does not have tcon)
234 are allowed as we start force umount */
235 if((smb_command != SMB_COM_WRITE_ANDX) &&
236 (smb_command != SMB_COM_OPEN_ANDX) &&
237 (smb_command != SMB_COM_TREE_DISCONNECT)) {
238 cFYI(1,("can not send cmd %d while umounting",
244 if((tcon->ses) && (tcon->ses->status != CifsExiting) &&
245 (tcon->ses->server)){
246 struct nls_table *nls_codepage;
247 /* Give Demultiplex thread up to 10 seconds to
248 reconnect, should be greater than cifs socket
249 timeout which is 7 seconds */
250 while(tcon->ses->server->tcpStatus == CifsNeedReconnect) {
251 wait_event_interruptible_timeout(tcon->ses->server->response_q,
252 (tcon->ses->server->tcpStatus == CifsGood), 10 * HZ);
253 if(tcon->ses->server->tcpStatus ==
255 /* on "soft" mounts we wait once */
256 if((tcon->retry == FALSE) ||
257 (tcon->ses->status == CifsExiting)) {
258 cFYI(1,("gave up waiting on reconnect in smb_init"));
260 } /* else "hard" mount - keep retrying
261 until process is killed or server
263 } else /* TCP session is reestablished now */
268 nls_codepage = load_nls_default();
269 /* need to prevent multiple threads trying to
270 simultaneously reconnect the same SMB session */
271 down(&tcon->ses->sesSem);
272 if(tcon->ses->status == CifsNeedReconnect)
273 rc = cifs_setup_session(0, tcon->ses,
275 if(!rc && (tcon->tidStatus == CifsNeedReconnect)) {
276 mark_open_files_invalid(tcon);
277 rc = CIFSTCon(0, tcon->ses, tcon->treeName,
279 up(&tcon->ses->sesSem);
280 /* BB FIXME add code to check if wsize needs
281 update due to negotiated smb buffer size
284 atomic_inc(&tconInfoReconnectCount);
286 cFYI(1, ("reconnect tcon rc = %d", rc));
287 /* Removed call to reopen open files here -
288 it is safer (and faster) to reopen files
289 one at a time as needed in read and write */
291 /* Check if handle based operation so we
292 know whether we can continue or not without
293 returning to caller to reset file handle */
294 switch(smb_command) {
295 case SMB_COM_READ_ANDX:
296 case SMB_COM_WRITE_ANDX:
298 case SMB_COM_FIND_CLOSE2:
299 case SMB_COM_LOCKING_ANDX: {
300 unload_nls(nls_codepage);
305 up(&tcon->ses->sesSem);
307 unload_nls(nls_codepage);
316 *request_buf = cifs_buf_get();
317 if (*request_buf == NULL) {
318 /* BB should we add a retry in here if not a writepage? */
321 /* Although the original thought was we needed the response buf for */
322 /* potential retries of smb operations it turns out we can determine */
323 /* from the mid flags when the request buffer can be resent without */
324 /* having to use a second distinct buffer for the response */
325 *response_buf = *request_buf;
327 header_assemble((struct smb_hdr *) *request_buf, smb_command, tcon,
331 cifs_stats_inc(&tcon->num_smbs_sent);
336 static int validate_t2(struct smb_t2_rsp * pSMB)
342 /* check for plausible wct, bcc and t2 data and parm sizes */
343 /* check for parm and data offset going beyond end of smb */
344 if(pSMB->hdr.WordCount >= 10) {
345 if((le16_to_cpu(pSMB->t2_rsp.ParameterOffset) <= 1024) &&
346 (le16_to_cpu(pSMB->t2_rsp.DataOffset) <= 1024)) {
347 /* check that bcc is at least as big as parms + data */
348 /* check that bcc is less than negotiated smb buffer */
349 total_size = le16_to_cpu(pSMB->t2_rsp.ParameterCount);
350 if(total_size < 512) {
351 total_size+=le16_to_cpu(pSMB->t2_rsp.DataCount);
352 /* BCC le converted in SendReceive */
353 pBCC = (pSMB->hdr.WordCount * 2) +
354 sizeof(struct smb_hdr) +
356 if((total_size <= (*(u16 *)pBCC)) &&
358 CIFSMaxBufSize+MAX_CIFS_HDR_SIZE)) {
365 cifs_dump_mem("Invalid transact2 SMB: ",(char *)pSMB,
366 sizeof(struct smb_t2_rsp) + 16);
370 CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses)
373 NEGOTIATE_RSP *pSMBr;
376 struct TCP_Server_Info * server;
380 server = ses->server;
385 rc = smb_init(SMB_COM_NEGOTIATE, 0, NULL /* no tcon yet */ ,
386 (void **) &pSMB, (void **) &pSMBr);
389 pSMB->hdr.Mid = GetNextMid(server);
390 pSMB->hdr.Flags2 |= SMBFLG2_UNICODE;
391 if (extended_security)
392 pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC;
394 count = strlen(protocols[0].name) + 1;
395 strncpy(pSMB->DialectsArray, protocols[0].name, 30);
396 /* null guaranteed to be at end of source and target buffers anyway */
398 pSMB->hdr.smb_buf_length += count;
399 pSMB->ByteCount = cpu_to_le16(count);
401 rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB,
402 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
404 server->secMode = pSMBr->SecurityMode;
405 if((server->secMode & SECMODE_USER) == 0)
406 cFYI(1,("share mode security"));
407 server->secType = NTLM; /* BB override default for
408 NTLMv2 or kerberos v5 */
409 /* one byte - no need to convert this or EncryptionKeyLen
410 from little endian */
411 server->maxReq = le16_to_cpu(pSMBr->MaxMpxCount);
412 /* probably no need to store and check maxvcs */
414 min(le32_to_cpu(pSMBr->MaxBufferSize),
415 (__u32) CIFSMaxBufSize + MAX_CIFS_HDR_SIZE);
416 server->maxRw = le32_to_cpu(pSMBr->MaxRawSize);
417 cFYI(0, ("Max buf = %d", ses->server->maxBuf));
418 GETU32(ses->server->sessid) = le32_to_cpu(pSMBr->SessionKey);
419 server->capabilities = le32_to_cpu(pSMBr->Capabilities);
420 server->timeZone = le16_to_cpu(pSMBr->ServerTimeZone);
421 /* BB with UTC do we ever need to be using srvr timezone? */
422 if (pSMBr->EncryptionKeyLength == CIFS_CRYPTO_KEY_SIZE) {
423 memcpy(server->cryptKey, pSMBr->u.EncryptionKey,
424 CIFS_CRYPTO_KEY_SIZE);
425 } else if ((pSMBr->hdr.Flags2 & SMBFLG2_EXT_SEC)
426 && (pSMBr->EncryptionKeyLength == 0)) {
427 /* decode security blob */
431 /* BB might be helpful to save off the domain of server here */
433 if ((pSMBr->hdr.Flags2 & SMBFLG2_EXT_SEC) &&
434 (server->capabilities & CAP_EXTENDED_SECURITY)) {
435 count = pSMBr->ByteCount;
438 else if (count == 16) {
439 server->secType = RawNTLMSSP;
440 if (server->socketUseCount.counter > 1) {
442 (server->server_GUID,
443 pSMBr->u.extended_response.
445 cFYI(1, ("server UID changed"));
453 memcpy(server->server_GUID,
454 pSMBr->u.extended_response.
457 rc = decode_negTokenInit(pSMBr->u.
463 /* BB Need to fill struct for sessetup here */
470 server->capabilities &= ~CAP_EXTENDED_SECURITY;
471 if(sign_CIFS_PDUs == FALSE) {
472 if(server->secMode & SECMODE_SIGN_REQUIRED)
474 ("Server requires /proc/fs/cifs/PacketSigningEnabled"));
475 server->secMode &= ~(SECMODE_SIGN_ENABLED | SECMODE_SIGN_REQUIRED);
476 } else if(sign_CIFS_PDUs == 1) {
477 if((server->secMode & SECMODE_SIGN_REQUIRED) == 0)
478 server->secMode &= ~(SECMODE_SIGN_ENABLED | SECMODE_SIGN_REQUIRED);
483 cifs_buf_release(pSMB);
488 CIFSSMBTDis(const int xid, struct cifsTconInfo *tcon)
490 struct smb_hdr *smb_buffer;
491 struct smb_hdr *smb_buffer_response; /* BB removeme BB */
495 cFYI(1, ("In tree disconnect"));
497 * If last user of the connection and
498 * connection alive - disconnect it
499 * If this is the last connection on the server session disconnect it
500 * (and inside session disconnect we should check if tcp socket needs
501 * to be freed and kernel thread woken up).
504 down(&tcon->tconSem);
508 atomic_dec(&tcon->useCount);
509 if (atomic_read(&tcon->useCount) > 0) {
514 /* No need to return error on this operation if tid invalidated and
515 closed on server already e.g. due to tcp session crashing */
516 if(tcon->tidStatus == CifsNeedReconnect) {
521 if((tcon->ses == NULL) || (tcon->ses->server == NULL)) {
525 rc = small_smb_init(SMB_COM_TREE_DISCONNECT, 0, tcon,
526 (void **)&smb_buffer);
531 smb_buffer_response = smb_buffer; /* BB removeme BB */
533 rc = SendReceive(xid, tcon->ses, smb_buffer, smb_buffer_response,
536 cFYI(1, ("Tree disconnect failed %d", rc));
539 cifs_small_buf_release(smb_buffer);
542 /* No need to return error on this operation if tid invalidated and
543 closed on server already e.g. due to tcp session crashing */
551 CIFSSMBLogoff(const int xid, struct cifsSesInfo *ses)
553 struct smb_hdr *smb_buffer_response;
554 LOGOFF_ANDX_REQ *pSMB;
558 cFYI(1, ("In SMBLogoff for session disconnect"));
564 atomic_dec(&ses->inUse);
565 if (atomic_read(&ses->inUse) > 0) {
569 rc = small_smb_init(SMB_COM_LOGOFF_ANDX, 2, NULL, (void **)&pSMB);
575 smb_buffer_response = (struct smb_hdr *)pSMB; /* BB removeme BB */
578 pSMB->hdr.Mid = GetNextMid(ses->server);
580 if(ses->server->secMode &
581 (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
582 pSMB->hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
585 pSMB->hdr.Uid = ses->Suid;
587 pSMB->AndXCommand = 0xFF;
588 rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB,
589 smb_buffer_response, &length, 0);
591 atomic_dec(&ses->server->socketUseCount);
592 if (atomic_read(&ses->server->socketUseCount) == 0) {
593 spin_lock(&GlobalMid_Lock);
594 ses->server->tcpStatus = CifsExiting;
595 spin_unlock(&GlobalMid_Lock);
600 cifs_small_buf_release(pSMB);
602 /* if session dead then we do not need to do ulogoff,
603 since server closed smb session, no sense reporting
611 CIFSSMBDelFile(const int xid, struct cifsTconInfo *tcon, const char *fileName,
612 const struct nls_table *nls_codepage, int remap)
614 DELETE_FILE_REQ *pSMB = NULL;
615 DELETE_FILE_RSP *pSMBr = NULL;
621 rc = smb_init(SMB_COM_DELETE, 1, tcon, (void **) &pSMB,
626 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
628 cifsConvertToUCS((__le16 *) pSMB->fileName, fileName,
629 PATH_MAX, nls_codepage, remap);
630 name_len++; /* trailing null */
632 } else { /* BB improve check for buffer overruns BB */
633 name_len = strnlen(fileName, PATH_MAX);
634 name_len++; /* trailing null */
635 strncpy(pSMB->fileName, fileName, name_len);
637 pSMB->SearchAttributes =
638 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM);
639 pSMB->BufferFormat = 0x04;
640 pSMB->hdr.smb_buf_length += name_len + 1;
641 pSMB->ByteCount = cpu_to_le16(name_len + 1);
642 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
643 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
644 cifs_stats_inc(&tcon->num_deletes);
646 cFYI(1, ("Error in RMFile = %d", rc));
649 cifs_buf_release(pSMB);
657 CIFSSMBRmDir(const int xid, struct cifsTconInfo *tcon, const char *dirName,
658 const struct nls_table *nls_codepage, int remap)
660 DELETE_DIRECTORY_REQ *pSMB = NULL;
661 DELETE_DIRECTORY_RSP *pSMBr = NULL;
666 cFYI(1, ("In CIFSSMBRmDir"));
668 rc = smb_init(SMB_COM_DELETE_DIRECTORY, 0, tcon, (void **) &pSMB,
673 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
674 name_len = cifsConvertToUCS((__le16 *) pSMB->DirName, dirName,
675 PATH_MAX, nls_codepage, remap);
676 name_len++; /* trailing null */
678 } else { /* BB improve check for buffer overruns BB */
679 name_len = strnlen(dirName, PATH_MAX);
680 name_len++; /* trailing null */
681 strncpy(pSMB->DirName, dirName, name_len);
684 pSMB->BufferFormat = 0x04;
685 pSMB->hdr.smb_buf_length += name_len + 1;
686 pSMB->ByteCount = cpu_to_le16(name_len + 1);
687 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
688 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
689 cifs_stats_inc(&tcon->num_rmdirs);
691 cFYI(1, ("Error in RMDir = %d", rc));
694 cifs_buf_release(pSMB);
701 CIFSSMBMkDir(const int xid, struct cifsTconInfo *tcon,
702 const char *name, const struct nls_table *nls_codepage, int remap)
705 CREATE_DIRECTORY_REQ *pSMB = NULL;
706 CREATE_DIRECTORY_RSP *pSMBr = NULL;
710 cFYI(1, ("In CIFSSMBMkDir"));
712 rc = smb_init(SMB_COM_CREATE_DIRECTORY, 0, tcon, (void **) &pSMB,
717 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
718 name_len = cifsConvertToUCS((__le16 *) pSMB->DirName, name,
719 PATH_MAX, nls_codepage, remap);
720 name_len++; /* trailing null */
722 } else { /* BB improve check for buffer overruns BB */
723 name_len = strnlen(name, PATH_MAX);
724 name_len++; /* trailing null */
725 strncpy(pSMB->DirName, name, name_len);
728 pSMB->BufferFormat = 0x04;
729 pSMB->hdr.smb_buf_length += name_len + 1;
730 pSMB->ByteCount = cpu_to_le16(name_len + 1);
731 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
732 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
733 cifs_stats_inc(&tcon->num_mkdirs);
735 cFYI(1, ("Error in Mkdir = %d", rc));
738 cifs_buf_release(pSMB);
744 static __u16 convert_disposition(int disposition)
748 switch (disposition) {
750 ofun = SMBOPEN_OCREATE | SMBOPEN_OTRUNC;
753 ofun = SMBOPEN_OAPPEND;
756 ofun = SMBOPEN_OCREATE;
759 ofun = SMBOPEN_OCREATE | SMBOPEN_OAPPEND;
762 ofun = SMBOPEN_OTRUNC;
764 case FILE_OVERWRITE_IF:
765 ofun = SMBOPEN_OCREATE | SMBOPEN_OTRUNC;
768 cFYI(1,("unknown disposition %d",disposition));
769 ofun = SMBOPEN_OAPPEND; /* regular open */
775 SMBLegacyOpen(const int xid, struct cifsTconInfo *tcon,
776 const char *fileName, const int openDisposition,
777 const int access_flags, const int create_options, __u16 * netfid,
778 int *pOplock, FILE_ALL_INFO * pfile_info,
779 const struct nls_table *nls_codepage, int remap)
782 OPENX_REQ *pSMB = NULL;
783 OPENX_RSP *pSMBr = NULL;
789 rc = smb_init(SMB_COM_OPEN_ANDX, 15, tcon, (void **) &pSMB,
794 pSMB->AndXCommand = 0xFF; /* none */
796 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
797 count = 1; /* account for one byte pad to word boundary */
799 cifsConvertToUCS((__le16 *) (pSMB->fileName + 1),
800 fileName, PATH_MAX, nls_codepage, remap);
801 name_len++; /* trailing null */
803 } else { /* BB improve check for buffer overruns BB */
804 count = 0; /* no pad */
805 name_len = strnlen(fileName, PATH_MAX);
806 name_len++; /* trailing null */
807 strncpy(pSMB->fileName, fileName, name_len);
809 if (*pOplock & REQ_OPLOCK)
810 pSMB->OpenFlags = cpu_to_le16(REQ_OPLOCK);
811 else if (*pOplock & REQ_BATCHOPLOCK) {
812 pSMB->OpenFlags = cpu_to_le16(REQ_BATCHOPLOCK);
814 pSMB->OpenFlags |= cpu_to_le16(REQ_MORE_INFO);
815 /* BB fixme add conversion for access_flags to bits 0 - 2 of mode */
821 pSMB->Mode = cpu_to_le16(2);
822 pSMB->Mode |= cpu_to_le16(0x40); /* deny none */
823 /* set file as system file if special file such
824 as fifo and server expecting SFU style and
825 no Unix extensions */
827 if(create_options & CREATE_OPTION_SPECIAL)
828 pSMB->FileAttributes = cpu_to_le16(ATTR_SYSTEM);
830 pSMB->FileAttributes = cpu_to_le16(0/*ATTR_NORMAL*/); /* BB FIXME */
832 /* if ((omode & S_IWUGO) == 0)
833 pSMB->FileAttributes |= cpu_to_le32(ATTR_READONLY);*/
834 /* Above line causes problems due to vfs splitting create into two
835 pieces - need to set mode after file created not while it is
839 /* pSMB->CreateOptions = cpu_to_le32(create_options & CREATE_OPTIONS_MASK); */
840 /* BB FIXME END BB */
842 pSMB->Sattr = cpu_to_le16(ATTR_HIDDEN | ATTR_SYSTEM | ATTR_DIRECTORY);
843 pSMB->OpenFunction = cpu_to_le16(convert_disposition(openDisposition));
845 pSMB->hdr.smb_buf_length += count;
847 pSMB->ByteCount = cpu_to_le16(count);
848 /* long_op set to 1 to allow for oplock break timeouts */
849 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
850 (struct smb_hdr *) pSMBr, &bytes_returned, 1);
851 cifs_stats_inc(&tcon->num_opens);
853 cFYI(1, ("Error in Open = %d", rc));
855 /* BB verify if wct == 15 */
857 /* *pOplock = pSMBr->OplockLevel; */ /* BB take from action field BB */
859 *netfid = pSMBr->Fid; /* cifs fid stays in le */
860 /* Let caller know file was created so we can set the mode. */
861 /* Do we care about the CreateAction in any other cases? */
863 /* if(cpu_to_le32(FILE_CREATE) == pSMBr->CreateAction)
864 *pOplock |= CIFS_CREATE_ACTION; */
868 pfile_info->CreationTime = 0; /* BB convert CreateTime*/
869 pfile_info->LastAccessTime = 0; /* BB fixme */
870 pfile_info->LastWriteTime = 0; /* BB fixme */
871 pfile_info->ChangeTime = 0; /* BB fixme */
872 pfile_info->Attributes =
873 cpu_to_le32(le16_to_cpu(pSMBr->FileAttributes));
874 /* the file_info buf is endian converted by caller */
875 pfile_info->AllocationSize =
876 cpu_to_le64(le32_to_cpu(pSMBr->EndOfFile));
877 pfile_info->EndOfFile = pfile_info->AllocationSize;
878 pfile_info->NumberOfLinks = cpu_to_le32(1);
882 cifs_buf_release(pSMB);
889 CIFSSMBOpen(const int xid, struct cifsTconInfo *tcon,
890 const char *fileName, const int openDisposition,
891 const int access_flags, const int create_options, __u16 * netfid,
892 int *pOplock, FILE_ALL_INFO * pfile_info,
893 const struct nls_table *nls_codepage, int remap)
896 OPEN_REQ *pSMB = NULL;
897 OPEN_RSP *pSMBr = NULL;
903 rc = smb_init(SMB_COM_NT_CREATE_ANDX, 24, tcon, (void **) &pSMB,
908 pSMB->AndXCommand = 0xFF; /* none */
910 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
911 count = 1; /* account for one byte pad to word boundary */
913 cifsConvertToUCS((__le16 *) (pSMB->fileName + 1),
914 fileName, PATH_MAX, nls_codepage, remap);
915 name_len++; /* trailing null */
917 pSMB->NameLength = cpu_to_le16(name_len);
918 } else { /* BB improve check for buffer overruns BB */
919 count = 0; /* no pad */
920 name_len = strnlen(fileName, PATH_MAX);
921 name_len++; /* trailing null */
922 pSMB->NameLength = cpu_to_le16(name_len);
923 strncpy(pSMB->fileName, fileName, name_len);
925 if (*pOplock & REQ_OPLOCK)
926 pSMB->OpenFlags = cpu_to_le32(REQ_OPLOCK);
927 else if (*pOplock & REQ_BATCHOPLOCK) {
928 pSMB->OpenFlags = cpu_to_le32(REQ_BATCHOPLOCK);
930 pSMB->DesiredAccess = cpu_to_le32(access_flags);
931 pSMB->AllocationSize = 0;
932 /* set file as system file if special file such
933 as fifo and server expecting SFU style and
934 no Unix extensions */
935 if(create_options & CREATE_OPTION_SPECIAL)
936 pSMB->FileAttributes = cpu_to_le32(ATTR_SYSTEM);
938 pSMB->FileAttributes = cpu_to_le32(ATTR_NORMAL);
939 /* XP does not handle ATTR_POSIX_SEMANTICS */
940 /* but it helps speed up case sensitive checks for other
941 servers such as Samba */
942 if (tcon->ses->capabilities & CAP_UNIX)
943 pSMB->FileAttributes |= cpu_to_le32(ATTR_POSIX_SEMANTICS);
945 /* if ((omode & S_IWUGO) == 0)
946 pSMB->FileAttributes |= cpu_to_le32(ATTR_READONLY);*/
947 /* Above line causes problems due to vfs splitting create into two
948 pieces - need to set mode after file created not while it is
950 pSMB->ShareAccess = cpu_to_le32(FILE_SHARE_ALL);
951 pSMB->CreateDisposition = cpu_to_le32(openDisposition);
952 pSMB->CreateOptions = cpu_to_le32(create_options & CREATE_OPTIONS_MASK);
953 /* BB Expirement with various impersonation levels and verify */
954 pSMB->ImpersonationLevel = cpu_to_le32(SECURITY_IMPERSONATION);
955 pSMB->SecurityFlags =
956 SECURITY_CONTEXT_TRACKING | SECURITY_EFFECTIVE_ONLY;
959 pSMB->hdr.smb_buf_length += count;
961 pSMB->ByteCount = cpu_to_le16(count);
962 /* long_op set to 1 to allow for oplock break timeouts */
963 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
964 (struct smb_hdr *) pSMBr, &bytes_returned, 1);
965 cifs_stats_inc(&tcon->num_opens);
967 cFYI(1, ("Error in Open = %d", rc));
969 *pOplock = pSMBr->OplockLevel; /* 1 byte no need to le_to_cpu */
970 *netfid = pSMBr->Fid; /* cifs fid stays in le */
971 /* Let caller know file was created so we can set the mode. */
972 /* Do we care about the CreateAction in any other cases? */
973 if(cpu_to_le32(FILE_CREATE) == pSMBr->CreateAction)
974 *pOplock |= CIFS_CREATE_ACTION;
976 memcpy((char *)pfile_info,(char *)&pSMBr->CreationTime,
977 36 /* CreationTime to Attributes */);
978 /* the file_info buf is endian converted by caller */
979 pfile_info->AllocationSize = pSMBr->AllocationSize;
980 pfile_info->EndOfFile = pSMBr->EndOfFile;
981 pfile_info->NumberOfLinks = cpu_to_le32(1);
985 cifs_buf_release(pSMB);
992 CIFSSMBRead(const int xid, struct cifsTconInfo *tcon,
993 const int netfid, const unsigned int count,
994 const __u64 lseek, unsigned int *nbytes, char **buf,
998 READ_REQ *pSMB = NULL;
999 READ_RSP *pSMBr = NULL;
1000 char *pReadData = NULL;
1002 int resp_buf_type = 0;
1005 cFYI(1,("Reading %d bytes on fid %d",count,netfid));
1006 if(tcon->ses->capabilities & CAP_LARGE_FILES)
1009 wct = 10; /* old style read */
1012 rc = small_smb_init(SMB_COM_READ_ANDX, wct, tcon, (void **) &pSMB);
1016 /* tcon and ses pointer are checked in smb_init */
1017 if (tcon->ses->server == NULL)
1018 return -ECONNABORTED;
1020 pSMB->AndXCommand = 0xFF; /* none */
1022 pSMB->OffsetLow = cpu_to_le32(lseek & 0xFFFFFFFF);
1024 pSMB->OffsetHigh = cpu_to_le32(lseek >> 32);
1025 else if((lseek >> 32) > 0) /* can not handle this big offset for old */
1028 pSMB->Remaining = 0;
1029 pSMB->MaxCount = cpu_to_le16(count & 0xFFFF);
1030 pSMB->MaxCountHigh = cpu_to_le32(count >> 16);
1032 pSMB->ByteCount = 0; /* no need to do le conversion since 0 */
1034 /* old style read */
1035 struct smb_com_readx_req * pSMBW =
1036 (struct smb_com_readx_req *)pSMB;
1037 pSMBW->ByteCount = 0;
1040 iov[0].iov_base = (char *)pSMB;
1041 iov[0].iov_len = pSMB->hdr.smb_buf_length + 4;
1042 rc = SendReceive2(xid, tcon->ses, iov,
1045 cifs_stats_inc(&tcon->num_reads);
1046 pSMBr = (READ_RSP *)iov[0].iov_base;
1048 cERROR(1, ("Send error in read = %d", rc));
1050 int data_length = le16_to_cpu(pSMBr->DataLengthHigh);
1051 data_length = data_length << 16;
1052 data_length += le16_to_cpu(pSMBr->DataLength);
1053 *nbytes = data_length;
1055 /*check that DataLength would not go beyond end of SMB */
1056 if ((data_length > CIFSMaxBufSize)
1057 || (data_length > count)) {
1058 cFYI(1,("bad length %d for count %d",data_length,count));
1062 pReadData = (char *) (&pSMBr->hdr.Protocol) +
1063 le16_to_cpu(pSMBr->DataOffset);
1064 /* if(rc = copy_to_user(buf, pReadData, data_length)) {
1065 cERROR(1,("Faulting on read rc = %d",rc));
1067 }*/ /* can not use copy_to_user when using page cache*/
1069 memcpy(*buf,pReadData,data_length);
1073 /* cifs_small_buf_release(pSMB); */ /* Freed earlier now in SendReceive2 */
1075 if(resp_buf_type == CIFS_SMALL_BUFFER)
1076 cifs_small_buf_release(iov[0].iov_base);
1077 else if(resp_buf_type == CIFS_LARGE_BUFFER)
1078 cifs_buf_release(iov[0].iov_base);
1079 } else if(resp_buf_type != CIFS_NO_BUFFER) {
1080 /* return buffer to caller to free */
1081 *buf = iov[0].iov_base;
1082 if(resp_buf_type == CIFS_SMALL_BUFFER)
1083 *pbuf_type = CIFS_SMALL_BUFFER;
1084 else if(resp_buf_type == CIFS_LARGE_BUFFER)
1085 *pbuf_type = CIFS_LARGE_BUFFER;
1086 } /* else no valid buffer on return - leave as null */
1088 /* Note: On -EAGAIN error only caller can retry on handle based calls
1089 since file handle passed in no longer valid */
1095 CIFSSMBWrite(const int xid, struct cifsTconInfo *tcon,
1096 const int netfid, const unsigned int count,
1097 const __u64 offset, unsigned int *nbytes, const char *buf,
1098 const char __user * ubuf, const int long_op)
1101 WRITE_REQ *pSMB = NULL;
1102 WRITE_RSP *pSMBr = NULL;
1103 int bytes_returned, wct;
1107 /* cFYI(1,("write at %lld %d bytes",offset,count));*/
1108 if(tcon->ses == NULL)
1109 return -ECONNABORTED;
1111 if(tcon->ses->capabilities & CAP_LARGE_FILES)
1116 rc = smb_init(SMB_COM_WRITE_ANDX, wct, tcon, (void **) &pSMB,
1120 /* tcon and ses pointer are checked in smb_init */
1121 if (tcon->ses->server == NULL)
1122 return -ECONNABORTED;
1124 pSMB->AndXCommand = 0xFF; /* none */
1126 pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF);
1128 pSMB->OffsetHigh = cpu_to_le32(offset >> 32);
1129 else if((offset >> 32) > 0) /* can not handle this big offset for old */
1132 pSMB->Reserved = 0xFFFFFFFF;
1133 pSMB->WriteMode = 0;
1134 pSMB->Remaining = 0;
1136 /* Can increase buffer size if buffer is big enough in some cases - ie we
1137 can send more if LARGE_WRITE_X capability returned by the server and if
1138 our buffer is big enough or if we convert to iovecs on socket writes
1139 and eliminate the copy to the CIFS buffer */
1140 if(tcon->ses->capabilities & CAP_LARGE_WRITE_X) {
1141 bytes_sent = min_t(const unsigned int, CIFSMaxBufSize, count);
1143 bytes_sent = (tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE)
1147 if (bytes_sent > count)
1150 cpu_to_le16(offsetof(struct smb_com_write_req,Data) - 4);
1152 memcpy(pSMB->Data,buf,bytes_sent);
1154 if(copy_from_user(pSMB->Data,ubuf,bytes_sent)) {
1155 cifs_buf_release(pSMB);
1158 } else if (count != 0) {
1160 cifs_buf_release(pSMB);
1162 } /* else setting file size with write of zero bytes */
1164 byte_count = bytes_sent + 1; /* pad */
1165 else /* wct == 12 */ {
1166 byte_count = bytes_sent + 5; /* bigger pad, smaller smb hdr */
1168 pSMB->DataLengthLow = cpu_to_le16(bytes_sent & 0xFFFF);
1169 pSMB->DataLengthHigh = cpu_to_le16(bytes_sent >> 16);
1170 pSMB->hdr.smb_buf_length += byte_count;
1173 pSMB->ByteCount = cpu_to_le16(byte_count);
1174 else { /* old style write has byte count 4 bytes earlier so 4 bytes pad */
1175 struct smb_com_writex_req * pSMBW =
1176 (struct smb_com_writex_req *)pSMB;
1177 pSMBW->ByteCount = cpu_to_le16(byte_count);
1180 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1181 (struct smb_hdr *) pSMBr, &bytes_returned, long_op);
1182 cifs_stats_inc(&tcon->num_writes);
1184 cFYI(1, ("Send error in write = %d", rc));
1187 *nbytes = le16_to_cpu(pSMBr->CountHigh);
1188 *nbytes = (*nbytes) << 16;
1189 *nbytes += le16_to_cpu(pSMBr->Count);
1192 cifs_buf_release(pSMB);
1194 /* Note: On -EAGAIN error only caller can retry on handle based calls
1195 since file handle passed in no longer valid */
1201 CIFSSMBWrite2(const int xid, struct cifsTconInfo *tcon,
1202 const int netfid, const unsigned int count,
1203 const __u64 offset, unsigned int *nbytes, struct kvec *iov,
1204 int n_vec, const int long_op)
1207 WRITE_REQ *pSMB = NULL;
1210 int resp_buf_type = 0;
1212 cFYI(1,("write2 at %lld %d bytes", (long long)offset, count));
1214 if(tcon->ses->capabilities & CAP_LARGE_FILES)
1218 rc = small_smb_init(SMB_COM_WRITE_ANDX, wct, tcon, (void **) &pSMB);
1221 /* tcon and ses pointer are checked in smb_init */
1222 if (tcon->ses->server == NULL)
1223 return -ECONNABORTED;
1225 pSMB->AndXCommand = 0xFF; /* none */
1227 pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF);
1229 pSMB->OffsetHigh = cpu_to_le32(offset >> 32);
1230 else if((offset >> 32) > 0) /* can not handle this big offset for old */
1232 pSMB->Reserved = 0xFFFFFFFF;
1233 pSMB->WriteMode = 0;
1234 pSMB->Remaining = 0;
1237 cpu_to_le16(offsetof(struct smb_com_write_req,Data) - 4);
1239 pSMB->DataLengthLow = cpu_to_le16(count & 0xFFFF);
1240 pSMB->DataLengthHigh = cpu_to_le16(count >> 16);
1241 smb_hdr_len = pSMB->hdr.smb_buf_length + 1; /* hdr + 1 byte pad */
1243 pSMB->hdr.smb_buf_length += count+1;
1244 else /* wct == 12 */
1245 pSMB->hdr.smb_buf_length += count+5; /* smb data starts later */
1247 pSMB->ByteCount = cpu_to_le16(count + 1);
1248 else /* wct == 12 */ /* bigger pad, smaller smb hdr, keep offset ok */ {
1249 struct smb_com_writex_req * pSMBW =
1250 (struct smb_com_writex_req *)pSMB;
1251 pSMBW->ByteCount = cpu_to_le16(count + 5);
1253 iov[0].iov_base = pSMB;
1255 iov[0].iov_len = smb_hdr_len + 4;
1256 else /* wct == 12 pad bigger by four bytes */
1257 iov[0].iov_len = smb_hdr_len + 8;
1260 rc = SendReceive2(xid, tcon->ses, iov, n_vec + 1, &resp_buf_type,
1262 cifs_stats_inc(&tcon->num_writes);
1264 cFYI(1, ("Send error Write2 = %d", rc));
1266 } else if(resp_buf_type == 0) {
1267 /* presumably this can not happen, but best to be safe */
1271 WRITE_RSP * pSMBr = (WRITE_RSP *)iov[0].iov_base;
1272 *nbytes = le16_to_cpu(pSMBr->CountHigh);
1273 *nbytes = (*nbytes) << 16;
1274 *nbytes += le16_to_cpu(pSMBr->Count);
1277 /* cifs_small_buf_release(pSMB); */ /* Freed earlier now in SendReceive2 */
1278 if(resp_buf_type == CIFS_SMALL_BUFFER)
1279 cifs_small_buf_release(iov[0].iov_base);
1280 else if(resp_buf_type == CIFS_LARGE_BUFFER)
1281 cifs_buf_release(iov[0].iov_base);
1283 /* Note: On -EAGAIN error only caller can retry on handle based calls
1284 since file handle passed in no longer valid */
1291 CIFSSMBLock(const int xid, struct cifsTconInfo *tcon,
1292 const __u16 smb_file_id, const __u64 len,
1293 const __u64 offset, const __u32 numUnlock,
1294 const __u32 numLock, const __u8 lockType, const int waitFlag)
1297 LOCK_REQ *pSMB = NULL;
1298 LOCK_RSP *pSMBr = NULL;
1303 cFYI(1, ("In CIFSSMBLock - timeout %d numLock %d",waitFlag,numLock));
1304 rc = small_smb_init(SMB_COM_LOCKING_ANDX, 8, tcon, (void **) &pSMB);
1309 pSMBr = (LOCK_RSP *)pSMB; /* BB removeme BB */
1311 if(lockType == LOCKING_ANDX_OPLOCK_RELEASE) {
1312 timeout = -1; /* no response expected */
1314 } else if (waitFlag == TRUE) {
1315 timeout = 3; /* blocking operation, no timeout */
1316 pSMB->Timeout = cpu_to_le32(-1);/* blocking - do not time out */
1321 pSMB->NumberOfLocks = cpu_to_le16(numLock);
1322 pSMB->NumberOfUnlocks = cpu_to_le16(numUnlock);
1323 pSMB->LockType = lockType;
1324 pSMB->AndXCommand = 0xFF; /* none */
1325 pSMB->Fid = smb_file_id; /* netfid stays le */
1327 if((numLock != 0) || (numUnlock != 0)) {
1328 pSMB->Locks[0].Pid = cpu_to_le16(current->tgid);
1329 /* BB where to store pid high? */
1330 pSMB->Locks[0].LengthLow = cpu_to_le32((u32)len);
1331 pSMB->Locks[0].LengthHigh = cpu_to_le32((u32)(len>>32));
1332 pSMB->Locks[0].OffsetLow = cpu_to_le32((u32)offset);
1333 pSMB->Locks[0].OffsetHigh = cpu_to_le32((u32)(offset>>32));
1334 count = sizeof(LOCKING_ANDX_RANGE);
1339 pSMB->hdr.smb_buf_length += count;
1340 pSMB->ByteCount = cpu_to_le16(count);
1342 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1343 (struct smb_hdr *) pSMBr, &bytes_returned, timeout);
1344 cifs_stats_inc(&tcon->num_locks);
1346 cFYI(1, ("Send error in Lock = %d", rc));
1348 cifs_small_buf_release(pSMB);
1350 /* Note: On -EAGAIN error only caller can retry on handle based calls
1351 since file handle passed in no longer valid */
1356 CIFSSMBPosixLock(const int xid, struct cifsTconInfo *tcon,
1357 const __u16 smb_file_id, const int get_flag, const __u64 len,
1358 struct file_lock *pLockData, const __u16 lock_type,
1361 struct smb_com_transaction2_sfi_req *pSMB = NULL;
1362 struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
1364 struct cifs_posix_lock *parm_data;
1366 int bytes_returned = 0;
1367 __u16 params, param_offset, offset, byte_count, count;
1369 cFYI(1, ("Posix Lock"));
1371 if(pLockData == NULL)
1374 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
1379 pSMBr = (struct smb_com_transaction2_sfi_rsp *)pSMB;
1382 pSMB->MaxSetupCount = 0;
1386 pSMB->Reserved2 = 0;
1387 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
1388 offset = param_offset + params;
1390 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
1392 count = sizeof(struct cifs_posix_lock);
1393 pSMB->MaxParameterCount = cpu_to_le16(2);
1394 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB PDU from sess */
1395 pSMB->SetupCount = 1;
1396 pSMB->Reserved3 = 0;
1398 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION);
1400 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
1401 byte_count = 3 /* pad */ + params + count;
1402 pSMB->DataCount = cpu_to_le16(count);
1403 pSMB->ParameterCount = cpu_to_le16(params);
1404 pSMB->TotalDataCount = pSMB->DataCount;
1405 pSMB->TotalParameterCount = pSMB->ParameterCount;
1406 pSMB->ParameterOffset = cpu_to_le16(param_offset);
1407 parm_data = (struct cifs_posix_lock *)
1408 (((char *) &pSMB->hdr.Protocol) + offset);
1410 parm_data->lock_type = cpu_to_le16(lock_type);
1412 parm_data->lock_flags = cpu_to_le16(1);
1413 parm_data->pid = cpu_to_le32(current->tgid);
1414 parm_data->start = cpu_to_le64(pLockData->fl_start);
1415 parm_data->length = cpu_to_le64(len); /* normalize negative numbers */
1417 pSMB->DataOffset = cpu_to_le16(offset);
1418 pSMB->Fid = smb_file_id;
1419 pSMB->InformationLevel = cpu_to_le16(SMB_SET_POSIX_LOCK);
1420 pSMB->Reserved4 = 0;
1421 pSMB->hdr.smb_buf_length += byte_count;
1422 pSMB->ByteCount = cpu_to_le16(byte_count);
1423 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1424 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1426 cFYI(1, ("Send error in Posix Lock = %d", rc));
1427 } else if (get_flag) {
1428 /* lock structure can be returned on get */
1431 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
1433 if (rc || (pSMBr->ByteCount < sizeof(struct cifs_posix_lock))) {
1434 rc = -EIO; /* bad smb */
1437 if(pLockData == NULL) {
1441 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
1442 data_count = le16_to_cpu(pSMBr->t2.DataCount);
1443 if(data_count < sizeof(struct cifs_posix_lock)) {
1447 parm_data = (struct cifs_posix_lock *)
1448 ((char *)&pSMBr->hdr.Protocol + data_offset);
1449 if(parm_data->lock_type == cpu_to_le16(CIFS_UNLCK))
1450 pLockData->fl_type = F_UNLCK;
1455 cifs_small_buf_release(pSMB);
1457 /* Note: On -EAGAIN error only caller can retry on handle based calls
1458 since file handle passed in no longer valid */
1465 CIFSSMBClose(const int xid, struct cifsTconInfo *tcon, int smb_file_id)
1468 CLOSE_REQ *pSMB = NULL;
1469 CLOSE_RSP *pSMBr = NULL;
1471 cFYI(1, ("In CIFSSMBClose"));
1473 /* do not retry on dead session on close */
1474 rc = small_smb_init(SMB_COM_CLOSE, 3, tcon, (void **) &pSMB);
1480 pSMBr = (CLOSE_RSP *)pSMB; /* BB removeme BB */
1482 pSMB->FileID = (__u16) smb_file_id;
1483 pSMB->LastWriteTime = 0;
1484 pSMB->ByteCount = 0;
1485 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1486 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1487 cifs_stats_inc(&tcon->num_closes);
1490 /* EINTR is expected when user ctl-c to kill app */
1491 cERROR(1, ("Send error in Close = %d", rc));
1495 cifs_small_buf_release(pSMB);
1497 /* Since session is dead, file will be closed on server already */
1505 CIFSSMBRename(const int xid, struct cifsTconInfo *tcon,
1506 const char *fromName, const char *toName,
1507 const struct nls_table *nls_codepage, int remap)
1510 RENAME_REQ *pSMB = NULL;
1511 RENAME_RSP *pSMBr = NULL;
1513 int name_len, name_len2;
1516 cFYI(1, ("In CIFSSMBRename"));
1518 rc = smb_init(SMB_COM_RENAME, 1, tcon, (void **) &pSMB,
1523 pSMB->BufferFormat = 0x04;
1524 pSMB->SearchAttributes =
1525 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
1528 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1530 cifsConvertToUCS((__le16 *) pSMB->OldFileName, fromName,
1531 PATH_MAX, nls_codepage, remap);
1532 name_len++; /* trailing null */
1534 pSMB->OldFileName[name_len] = 0x04; /* pad */
1535 /* protocol requires ASCII signature byte on Unicode string */
1536 pSMB->OldFileName[name_len + 1] = 0x00;
1538 cifsConvertToUCS((__le16 *) &pSMB->OldFileName[name_len + 2],
1539 toName, PATH_MAX, nls_codepage, remap);
1540 name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
1541 name_len2 *= 2; /* convert to bytes */
1542 } else { /* BB improve the check for buffer overruns BB */
1543 name_len = strnlen(fromName, PATH_MAX);
1544 name_len++; /* trailing null */
1545 strncpy(pSMB->OldFileName, fromName, name_len);
1546 name_len2 = strnlen(toName, PATH_MAX);
1547 name_len2++; /* trailing null */
1548 pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */
1549 strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2);
1550 name_len2++; /* trailing null */
1551 name_len2++; /* signature byte */
1554 count = 1 /* 1st signature byte */ + name_len + name_len2;
1555 pSMB->hdr.smb_buf_length += count;
1556 pSMB->ByteCount = cpu_to_le16(count);
1558 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1559 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1560 cifs_stats_inc(&tcon->num_renames);
1562 cFYI(1, ("Send error in rename = %d", rc));
1565 cifs_buf_release(pSMB);
1573 int CIFSSMBRenameOpenFile(const int xid,struct cifsTconInfo *pTcon,
1574 int netfid, char * target_name,
1575 const struct nls_table * nls_codepage, int remap)
1577 struct smb_com_transaction2_sfi_req *pSMB = NULL;
1578 struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
1579 struct set_file_rename * rename_info;
1581 char dummy_string[30];
1583 int bytes_returned = 0;
1585 __u16 params, param_offset, offset, count, byte_count;
1587 cFYI(1, ("Rename to File by handle"));
1588 rc = smb_init(SMB_COM_TRANSACTION2, 15, pTcon, (void **) &pSMB,
1594 pSMB->MaxSetupCount = 0;
1598 pSMB->Reserved2 = 0;
1599 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
1600 offset = param_offset + params;
1602 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
1603 rename_info = (struct set_file_rename *) data_offset;
1604 pSMB->MaxParameterCount = cpu_to_le16(2);
1605 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB PDU from sess */
1606 pSMB->SetupCount = 1;
1607 pSMB->Reserved3 = 0;
1608 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
1609 byte_count = 3 /* pad */ + params;
1610 pSMB->ParameterCount = cpu_to_le16(params);
1611 pSMB->TotalParameterCount = pSMB->ParameterCount;
1612 pSMB->ParameterOffset = cpu_to_le16(param_offset);
1613 pSMB->DataOffset = cpu_to_le16(offset);
1614 /* construct random name ".cifs_tmp<inodenum><mid>" */
1615 rename_info->overwrite = cpu_to_le32(1);
1616 rename_info->root_fid = 0;
1617 /* unicode only call */
1618 if(target_name == NULL) {
1619 sprintf(dummy_string,"cifs%x",pSMB->hdr.Mid);
1620 len_of_str = cifsConvertToUCS((__le16 *)rename_info->target_name,
1621 dummy_string, 24, nls_codepage, remap);
1623 len_of_str = cifsConvertToUCS((__le16 *)rename_info->target_name,
1624 target_name, PATH_MAX, nls_codepage, remap);
1626 rename_info->target_name_len = cpu_to_le32(2 * len_of_str);
1627 count = 12 /* sizeof(struct set_file_rename) */ + (2 * len_of_str) + 2;
1628 byte_count += count;
1629 pSMB->DataCount = cpu_to_le16(count);
1630 pSMB->TotalDataCount = pSMB->DataCount;
1632 pSMB->InformationLevel =
1633 cpu_to_le16(SMB_SET_FILE_RENAME_INFORMATION);
1634 pSMB->Reserved4 = 0;
1635 pSMB->hdr.smb_buf_length += byte_count;
1636 pSMB->ByteCount = cpu_to_le16(byte_count);
1637 rc = SendReceive(xid, pTcon->ses, (struct smb_hdr *) pSMB,
1638 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1639 cifs_stats_inc(&pTcon->num_t2renames);
1641 cFYI(1,("Send error in Rename (by file handle) = %d", rc));
1644 cifs_buf_release(pSMB);
1646 /* Note: On -EAGAIN error only caller can retry on handle based calls
1647 since file handle passed in no longer valid */
1653 CIFSSMBCopy(const int xid, struct cifsTconInfo *tcon, const char * fromName,
1654 const __u16 target_tid, const char *toName, const int flags,
1655 const struct nls_table *nls_codepage, int remap)
1658 COPY_REQ *pSMB = NULL;
1659 COPY_RSP *pSMBr = NULL;
1661 int name_len, name_len2;
1664 cFYI(1, ("In CIFSSMBCopy"));
1666 rc = smb_init(SMB_COM_COPY, 1, tcon, (void **) &pSMB,
1671 pSMB->BufferFormat = 0x04;
1672 pSMB->Tid2 = target_tid;
1674 pSMB->Flags = cpu_to_le16(flags & COPY_TREE);
1676 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1677 name_len = cifsConvertToUCS((__le16 *) pSMB->OldFileName,
1678 fromName, PATH_MAX, nls_codepage,
1680 name_len++; /* trailing null */
1682 pSMB->OldFileName[name_len] = 0x04; /* pad */
1683 /* protocol requires ASCII signature byte on Unicode string */
1684 pSMB->OldFileName[name_len + 1] = 0x00;
1685 name_len2 = cifsConvertToUCS((__le16 *)&pSMB->OldFileName[name_len + 2],
1686 toName, PATH_MAX, nls_codepage, remap);
1687 name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
1688 name_len2 *= 2; /* convert to bytes */
1689 } else { /* BB improve the check for buffer overruns BB */
1690 name_len = strnlen(fromName, PATH_MAX);
1691 name_len++; /* trailing null */
1692 strncpy(pSMB->OldFileName, fromName, name_len);
1693 name_len2 = strnlen(toName, PATH_MAX);
1694 name_len2++; /* trailing null */
1695 pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */
1696 strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2);
1697 name_len2++; /* trailing null */
1698 name_len2++; /* signature byte */
1701 count = 1 /* 1st signature byte */ + name_len + name_len2;
1702 pSMB->hdr.smb_buf_length += count;
1703 pSMB->ByteCount = cpu_to_le16(count);
1705 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1706 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1708 cFYI(1, ("Send error in copy = %d with %d files copied",
1709 rc, le16_to_cpu(pSMBr->CopyCount)));
1712 cifs_buf_release(pSMB);
1721 CIFSUnixCreateSymLink(const int xid, struct cifsTconInfo *tcon,
1722 const char *fromName, const char *toName,
1723 const struct nls_table *nls_codepage)
1725 TRANSACTION2_SPI_REQ *pSMB = NULL;
1726 TRANSACTION2_SPI_RSP *pSMBr = NULL;
1729 int name_len_target;
1731 int bytes_returned = 0;
1732 __u16 params, param_offset, offset, byte_count;
1734 cFYI(1, ("In Symlink Unix style"));
1736 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
1741 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1743 cifs_strtoUCS((__le16 *) pSMB->FileName, fromName, PATH_MAX
1744 /* find define for this maxpathcomponent */
1746 name_len++; /* trailing null */
1749 } else { /* BB improve the check for buffer overruns BB */
1750 name_len = strnlen(fromName, PATH_MAX);
1751 name_len++; /* trailing null */
1752 strncpy(pSMB->FileName, fromName, name_len);
1754 params = 6 + name_len;
1755 pSMB->MaxSetupCount = 0;
1759 pSMB->Reserved2 = 0;
1760 param_offset = offsetof(struct smb_com_transaction2_spi_req,
1761 InformationLevel) - 4;
1762 offset = param_offset + params;
1764 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
1765 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1767 cifs_strtoUCS((__le16 *) data_offset, toName, PATH_MAX
1768 /* find define for this maxpathcomponent */
1770 name_len_target++; /* trailing null */
1771 name_len_target *= 2;
1772 } else { /* BB improve the check for buffer overruns BB */
1773 name_len_target = strnlen(toName, PATH_MAX);
1774 name_len_target++; /* trailing null */
1775 strncpy(data_offset, toName, name_len_target);
1778 pSMB->MaxParameterCount = cpu_to_le16(2);
1779 /* BB find exact max on data count below from sess */
1780 pSMB->MaxDataCount = cpu_to_le16(1000);
1781 pSMB->SetupCount = 1;
1782 pSMB->Reserved3 = 0;
1783 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
1784 byte_count = 3 /* pad */ + params + name_len_target;
1785 pSMB->DataCount = cpu_to_le16(name_len_target);
1786 pSMB->ParameterCount = cpu_to_le16(params);
1787 pSMB->TotalDataCount = pSMB->DataCount;
1788 pSMB->TotalParameterCount = pSMB->ParameterCount;
1789 pSMB->ParameterOffset = cpu_to_le16(param_offset);
1790 pSMB->DataOffset = cpu_to_le16(offset);
1791 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_LINK);
1792 pSMB->Reserved4 = 0;
1793 pSMB->hdr.smb_buf_length += byte_count;
1794 pSMB->ByteCount = cpu_to_le16(byte_count);
1795 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1796 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1797 cifs_stats_inc(&tcon->num_symlinks);
1800 ("Send error in SetPathInfo (create symlink) = %d",
1805 cifs_buf_release(pSMB);
1808 goto createSymLinkRetry;
1814 CIFSUnixCreateHardLink(const int xid, struct cifsTconInfo *tcon,
1815 const char *fromName, const char *toName,
1816 const struct nls_table *nls_codepage, int remap)
1818 TRANSACTION2_SPI_REQ *pSMB = NULL;
1819 TRANSACTION2_SPI_RSP *pSMBr = NULL;
1822 int name_len_target;
1824 int bytes_returned = 0;
1825 __u16 params, param_offset, offset, byte_count;
1827 cFYI(1, ("In Create Hard link Unix style"));
1828 createHardLinkRetry:
1829 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
1834 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1835 name_len = cifsConvertToUCS((__le16 *) pSMB->FileName, toName,
1836 PATH_MAX, nls_codepage, remap);
1837 name_len++; /* trailing null */
1840 } else { /* BB improve the check for buffer overruns BB */
1841 name_len = strnlen(toName, PATH_MAX);
1842 name_len++; /* trailing null */
1843 strncpy(pSMB->FileName, toName, name_len);
1845 params = 6 + name_len;
1846 pSMB->MaxSetupCount = 0;
1850 pSMB->Reserved2 = 0;
1851 param_offset = offsetof(struct smb_com_transaction2_spi_req,
1852 InformationLevel) - 4;
1853 offset = param_offset + params;
1855 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
1856 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1858 cifsConvertToUCS((__le16 *) data_offset, fromName, PATH_MAX,
1859 nls_codepage, remap);
1860 name_len_target++; /* trailing null */
1861 name_len_target *= 2;
1862 } else { /* BB improve the check for buffer overruns BB */
1863 name_len_target = strnlen(fromName, PATH_MAX);
1864 name_len_target++; /* trailing null */
1865 strncpy(data_offset, fromName, name_len_target);
1868 pSMB->MaxParameterCount = cpu_to_le16(2);
1869 /* BB find exact max on data count below from sess*/
1870 pSMB->MaxDataCount = cpu_to_le16(1000);
1871 pSMB->SetupCount = 1;
1872 pSMB->Reserved3 = 0;
1873 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
1874 byte_count = 3 /* pad */ + params + name_len_target;
1875 pSMB->ParameterCount = cpu_to_le16(params);
1876 pSMB->TotalParameterCount = pSMB->ParameterCount;
1877 pSMB->DataCount = cpu_to_le16(name_len_target);
1878 pSMB->TotalDataCount = pSMB->DataCount;
1879 pSMB->ParameterOffset = cpu_to_le16(param_offset);
1880 pSMB->DataOffset = cpu_to_le16(offset);
1881 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_HLINK);
1882 pSMB->Reserved4 = 0;
1883 pSMB->hdr.smb_buf_length += byte_count;
1884 pSMB->ByteCount = cpu_to_le16(byte_count);
1885 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1886 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1887 cifs_stats_inc(&tcon->num_hardlinks);
1889 cFYI(1, ("Send error in SetPathInfo (hard link) = %d", rc));
1892 cifs_buf_release(pSMB);
1894 goto createHardLinkRetry;
1900 CIFSCreateHardLink(const int xid, struct cifsTconInfo *tcon,
1901 const char *fromName, const char *toName,
1902 const struct nls_table *nls_codepage, int remap)
1905 NT_RENAME_REQ *pSMB = NULL;
1906 RENAME_RSP *pSMBr = NULL;
1908 int name_len, name_len2;
1911 cFYI(1, ("In CIFSCreateHardLink"));
1912 winCreateHardLinkRetry:
1914 rc = smb_init(SMB_COM_NT_RENAME, 4, tcon, (void **) &pSMB,
1919 pSMB->SearchAttributes =
1920 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
1922 pSMB->Flags = cpu_to_le16(CREATE_HARD_LINK);
1923 pSMB->ClusterCount = 0;
1925 pSMB->BufferFormat = 0x04;
1927 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1929 cifsConvertToUCS((__le16 *) pSMB->OldFileName, fromName,
1930 PATH_MAX, nls_codepage, remap);
1931 name_len++; /* trailing null */
1933 pSMB->OldFileName[name_len] = 0; /* pad */
1934 pSMB->OldFileName[name_len + 1] = 0x04;
1936 cifsConvertToUCS((__le16 *)&pSMB->OldFileName[name_len + 2],
1937 toName, PATH_MAX, nls_codepage, remap);
1938 name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
1939 name_len2 *= 2; /* convert to bytes */
1940 } else { /* BB improve the check for buffer overruns BB */
1941 name_len = strnlen(fromName, PATH_MAX);
1942 name_len++; /* trailing null */
1943 strncpy(pSMB->OldFileName, fromName, name_len);
1944 name_len2 = strnlen(toName, PATH_MAX);
1945 name_len2++; /* trailing null */
1946 pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */
1947 strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2);
1948 name_len2++; /* trailing null */
1949 name_len2++; /* signature byte */
1952 count = 1 /* string type byte */ + name_len + name_len2;
1953 pSMB->hdr.smb_buf_length += count;
1954 pSMB->ByteCount = cpu_to_le16(count);
1956 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1957 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1958 cifs_stats_inc(&tcon->num_hardlinks);
1960 cFYI(1, ("Send error in hard link (NT rename) = %d", rc));
1962 cifs_buf_release(pSMB);
1964 goto winCreateHardLinkRetry;
1970 CIFSSMBUnixQuerySymLink(const int xid, struct cifsTconInfo *tcon,
1971 const unsigned char *searchName,
1972 char *symlinkinfo, const int buflen,
1973 const struct nls_table *nls_codepage)
1975 /* SMB_QUERY_FILE_UNIX_LINK */
1976 TRANSACTION2_QPI_REQ *pSMB = NULL;
1977 TRANSACTION2_QPI_RSP *pSMBr = NULL;
1981 __u16 params, byte_count;
1983 cFYI(1, ("In QPathSymLinkInfo (Unix) for path %s", searchName));
1986 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
1991 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1993 cifs_strtoUCS((__le16 *) pSMB->FileName, searchName, PATH_MAX
1994 /* find define for this maxpathcomponent */
1996 name_len++; /* trailing null */
1998 } else { /* BB improve the check for buffer overruns BB */
1999 name_len = strnlen(searchName, PATH_MAX);
2000 name_len++; /* trailing null */
2001 strncpy(pSMB->FileName, searchName, name_len);
2004 params = 2 /* level */ + 4 /* rsrvd */ + name_len /* incl null */ ;
2005 pSMB->TotalDataCount = 0;
2006 pSMB->MaxParameterCount = cpu_to_le16(2);
2007 /* BB find exact max data count below from sess structure BB */
2008 pSMB->MaxDataCount = cpu_to_le16(4000);
2009 pSMB->MaxSetupCount = 0;
2013 pSMB->Reserved2 = 0;
2014 pSMB->ParameterOffset = cpu_to_le16(offsetof(
2015 struct smb_com_transaction2_qpi_req ,InformationLevel) - 4);
2016 pSMB->DataCount = 0;
2017 pSMB->DataOffset = 0;
2018 pSMB->SetupCount = 1;
2019 pSMB->Reserved3 = 0;
2020 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
2021 byte_count = params + 1 /* pad */ ;
2022 pSMB->TotalParameterCount = cpu_to_le16(params);
2023 pSMB->ParameterCount = pSMB->TotalParameterCount;
2024 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_LINK);
2025 pSMB->Reserved4 = 0;
2026 pSMB->hdr.smb_buf_length += byte_count;
2027 pSMB->ByteCount = cpu_to_le16(byte_count);
2029 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2030 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2032 cFYI(1, ("Send error in QuerySymLinkInfo = %d", rc));
2034 /* decode response */
2036 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
2037 if (rc || (pSMBr->ByteCount < 2))
2038 /* BB also check enough total bytes returned */
2039 rc = -EIO; /* bad smb */
2041 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
2042 __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
2044 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
2045 name_len = UniStrnlen((wchar_t *) ((char *)
2046 &pSMBr->hdr.Protocol +data_offset),
2047 min_t(const int, buflen,count) / 2);
2048 /* BB FIXME investigate remapping reserved chars here */
2049 cifs_strfromUCS_le(symlinkinfo,
2050 (__le16 *) ((char *)&pSMBr->hdr.Protocol +
2052 name_len, nls_codepage);
2054 strncpy(symlinkinfo,
2055 (char *) &pSMBr->hdr.Protocol +
2057 min_t(const int, buflen, count));
2059 symlinkinfo[buflen] = 0;
2060 /* just in case so calling code does not go off the end of buffer */
2063 cifs_buf_release(pSMB);
2065 goto querySymLinkRetry;
2069 /* Initialize NT TRANSACT SMB into small smb request buffer.
2070 This assumes that all NT TRANSACTS that we init here have
2071 total parm and data under about 400 bytes (to fit in small cifs
2072 buffer size), which is the case so far, it easily fits. NB:
2073 Setup words themselves and ByteCount
2074 MaxSetupCount (size of returned setup area) and
2075 MaxParameterCount (returned parms size) must be set by caller */
2077 smb_init_ntransact(const __u16 sub_command, const int setup_count,
2078 const int parm_len, struct cifsTconInfo *tcon,
2083 struct smb_com_ntransact_req * pSMB;
2085 rc = small_smb_init(SMB_COM_NT_TRANSACT, 19 + setup_count, tcon,
2089 *ret_buf = (void *)pSMB;
2091 pSMB->TotalParameterCount = cpu_to_le32(parm_len);
2092 pSMB->TotalDataCount = 0;
2093 pSMB->MaxDataCount = cpu_to_le32((tcon->ses->server->maxBuf -
2094 MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
2095 pSMB->ParameterCount = pSMB->TotalParameterCount;
2096 pSMB->DataCount = pSMB->TotalDataCount;
2097 temp_offset = offsetof(struct smb_com_ntransact_req, Parms) +
2098 (setup_count * 2) - 4 /* for rfc1001 length itself */;
2099 pSMB->ParameterOffset = cpu_to_le32(temp_offset);
2100 pSMB->DataOffset = cpu_to_le32(temp_offset + parm_len);
2101 pSMB->SetupCount = setup_count; /* no need to le convert byte fields */
2102 pSMB->SubCommand = cpu_to_le16(sub_command);
2107 validate_ntransact(char * buf, char ** ppparm, char ** ppdata,
2108 int * pdatalen, int * pparmlen)
2111 __u32 data_count, data_offset, parm_count, parm_offset;
2112 struct smb_com_ntransact_rsp * pSMBr;
2117 pSMBr = (struct smb_com_ntransact_rsp *)buf;
2119 /* ByteCount was converted from little endian in SendReceive */
2120 end_of_smb = 2 /* sizeof byte count */ + pSMBr->ByteCount +
2121 (char *)&pSMBr->ByteCount;
2124 data_offset = le32_to_cpu(pSMBr->DataOffset);
2125 data_count = le32_to_cpu(pSMBr->DataCount);
2126 parm_offset = le32_to_cpu(pSMBr->ParameterOffset);
2127 parm_count = le32_to_cpu(pSMBr->ParameterCount);
2129 *ppparm = (char *)&pSMBr->hdr.Protocol + parm_offset;
2130 *ppdata = (char *)&pSMBr->hdr.Protocol + data_offset;
2132 /* should we also check that parm and data areas do not overlap? */
2133 if(*ppparm > end_of_smb) {
2134 cFYI(1,("parms start after end of smb"));
2136 } else if(parm_count + *ppparm > end_of_smb) {
2137 cFYI(1,("parm end after end of smb"));
2139 } else if(*ppdata > end_of_smb) {
2140 cFYI(1,("data starts after end of smb"));
2142 } else if(data_count + *ppdata > end_of_smb) {
2143 cFYI(1,("data %p + count %d (%p) ends after end of smb %p start %p",
2144 *ppdata, data_count, (data_count + *ppdata), end_of_smb, pSMBr)); /* BB FIXME */
2146 } else if(parm_count + data_count > pSMBr->ByteCount) {
2147 cFYI(1,("parm count and data count larger than SMB"));
2154 CIFSSMBQueryReparseLinkInfo(const int xid, struct cifsTconInfo *tcon,
2155 const unsigned char *searchName,
2156 char *symlinkinfo, const int buflen,__u16 fid,
2157 const struct nls_table *nls_codepage)
2162 struct smb_com_transaction_ioctl_req * pSMB;
2163 struct smb_com_transaction_ioctl_rsp * pSMBr;
2165 cFYI(1, ("In Windows reparse style QueryLink for path %s", searchName));
2166 rc = smb_init(SMB_COM_NT_TRANSACT, 23, tcon, (void **) &pSMB,
2171 pSMB->TotalParameterCount = 0 ;
2172 pSMB->TotalDataCount = 0;
2173 pSMB->MaxParameterCount = cpu_to_le32(2);
2174 /* BB find exact data count max from sess structure BB */
2175 pSMB->MaxDataCount = cpu_to_le32((tcon->ses->server->maxBuf -
2176 MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
2177 pSMB->MaxSetupCount = 4;
2179 pSMB->ParameterOffset = 0;
2180 pSMB->DataCount = 0;
2181 pSMB->DataOffset = 0;
2182 pSMB->SetupCount = 4;
2183 pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_IOCTL);
2184 pSMB->ParameterCount = pSMB->TotalParameterCount;
2185 pSMB->FunctionCode = cpu_to_le32(FSCTL_GET_REPARSE_POINT);
2186 pSMB->IsFsctl = 1; /* FSCTL */
2187 pSMB->IsRootFlag = 0;
2188 pSMB->Fid = fid; /* file handle always le */
2189 pSMB->ByteCount = 0;
2191 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2192 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2194 cFYI(1, ("Send error in QueryReparseLinkInfo = %d", rc));
2195 } else { /* decode response */
2196 __u32 data_offset = le32_to_cpu(pSMBr->DataOffset);
2197 __u32 data_count = le32_to_cpu(pSMBr->DataCount);
2198 if ((pSMBr->ByteCount < 2) || (data_offset > 512))
2199 /* BB also check enough total bytes returned */
2200 rc = -EIO; /* bad smb */
2202 if(data_count && (data_count < 2048)) {
2203 char * end_of_smb = 2 /* sizeof byte count */ +
2205 (char *)&pSMBr->ByteCount;
2207 struct reparse_data * reparse_buf = (struct reparse_data *)
2208 ((char *)&pSMBr->hdr.Protocol + data_offset);
2209 if((char*)reparse_buf >= end_of_smb) {
2213 if((reparse_buf->LinkNamesBuf +
2214 reparse_buf->TargetNameOffset +
2215 reparse_buf->TargetNameLen) >
2217 cFYI(1,("reparse buf extended beyond SMB"));
2222 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
2223 name_len = UniStrnlen((wchar_t *)
2224 (reparse_buf->LinkNamesBuf +
2225 reparse_buf->TargetNameOffset),
2226 min(buflen/2, reparse_buf->TargetNameLen / 2));
2227 cifs_strfromUCS_le(symlinkinfo,
2228 (__le16 *) (reparse_buf->LinkNamesBuf +
2229 reparse_buf->TargetNameOffset),
2230 name_len, nls_codepage);
2231 } else { /* ASCII names */
2232 strncpy(symlinkinfo,reparse_buf->LinkNamesBuf +
2233 reparse_buf->TargetNameOffset,
2234 min_t(const int, buflen, reparse_buf->TargetNameLen));
2238 cFYI(1,("Invalid return data count on get reparse info ioctl"));
2240 symlinkinfo[buflen] = 0; /* just in case so the caller
2241 does not go off the end of the buffer */
2242 cFYI(1,("readlink result - %s ",symlinkinfo));
2246 cifs_buf_release(pSMB);
2248 /* Note: On -EAGAIN error only caller can retry on handle based calls
2249 since file handle passed in no longer valid */
2254 #ifdef CONFIG_CIFS_POSIX
2256 /*Convert an Access Control Entry from wire format to local POSIX xattr format*/
2257 static void cifs_convert_ace(posix_acl_xattr_entry * ace, struct cifs_posix_ace * cifs_ace)
2259 /* u8 cifs fields do not need le conversion */
2260 ace->e_perm = cpu_to_le16(cifs_ace->cifs_e_perm);
2261 ace->e_tag = cpu_to_le16(cifs_ace->cifs_e_tag);
2262 ace->e_id = cpu_to_le32(le64_to_cpu(cifs_ace->cifs_uid));
2263 /* cFYI(1,("perm %d tag %d id %d",ace->e_perm,ace->e_tag,ace->e_id)); */
2268 /* Convert ACL from CIFS POSIX wire format to local Linux POSIX ACL xattr */
2269 static int cifs_copy_posix_acl(char * trgt,char * src, const int buflen,
2270 const int acl_type,const int size_of_data_area)
2275 struct cifs_posix_ace * pACE;
2276 struct cifs_posix_acl * cifs_acl = (struct cifs_posix_acl *)src;
2277 posix_acl_xattr_header * local_acl = (posix_acl_xattr_header *)trgt;
2279 if (le16_to_cpu(cifs_acl->version) != CIFS_ACL_VERSION)
2282 if(acl_type & ACL_TYPE_ACCESS) {
2283 count = le16_to_cpu(cifs_acl->access_entry_count);
2284 pACE = &cifs_acl->ace_array[0];
2285 size = sizeof(struct cifs_posix_acl);
2286 size += sizeof(struct cifs_posix_ace) * count;
2287 /* check if we would go beyond end of SMB */
2288 if(size_of_data_area < size) {
2289 cFYI(1,("bad CIFS POSIX ACL size %d vs. %d",size_of_data_area,size));
2292 } else if(acl_type & ACL_TYPE_DEFAULT) {
2293 count = le16_to_cpu(cifs_acl->access_entry_count);
2294 size = sizeof(struct cifs_posix_acl);
2295 size += sizeof(struct cifs_posix_ace) * count;
2296 /* skip past access ACEs to get to default ACEs */
2297 pACE = &cifs_acl->ace_array[count];
2298 count = le16_to_cpu(cifs_acl->default_entry_count);
2299 size += sizeof(struct cifs_posix_ace) * count;
2300 /* check if we would go beyond end of SMB */
2301 if(size_of_data_area < size)
2308 size = posix_acl_xattr_size(count);
2309 if((buflen == 0) || (local_acl == NULL)) {
2310 /* used to query ACL EA size */
2311 } else if(size > buflen) {
2313 } else /* buffer big enough */ {
2314 local_acl->a_version = cpu_to_le32(POSIX_ACL_XATTR_VERSION);
2315 for(i = 0;i < count ;i++) {
2316 cifs_convert_ace(&local_acl->a_entries[i],pACE);
2323 static __u16 convert_ace_to_cifs_ace(struct cifs_posix_ace * cifs_ace,
2324 const posix_acl_xattr_entry * local_ace)
2326 __u16 rc = 0; /* 0 = ACL converted ok */
2328 cifs_ace->cifs_e_perm = le16_to_cpu(local_ace->e_perm);
2329 cifs_ace->cifs_e_tag = le16_to_cpu(local_ace->e_tag);
2330 /* BB is there a better way to handle the large uid? */
2331 if(local_ace->e_id == cpu_to_le32(-1)) {
2332 /* Probably no need to le convert -1 on any arch but can not hurt */
2333 cifs_ace->cifs_uid = cpu_to_le64(-1);
2335 cifs_ace->cifs_uid = cpu_to_le64(le32_to_cpu(local_ace->e_id));
2336 /*cFYI(1,("perm %d tag %d id %d",ace->e_perm,ace->e_tag,ace->e_id));*/
2340 /* Convert ACL from local Linux POSIX xattr to CIFS POSIX ACL wire format */
2341 static __u16 ACL_to_cifs_posix(char * parm_data,const char * pACL,const int buflen,
2345 struct cifs_posix_acl * cifs_acl = (struct cifs_posix_acl *)parm_data;
2346 posix_acl_xattr_header * local_acl = (posix_acl_xattr_header *)pACL;
2350 if((buflen == 0) || (pACL == NULL) || (cifs_acl == NULL))
2353 count = posix_acl_xattr_count((size_t)buflen);
2354 cFYI(1,("setting acl with %d entries from buf of length %d and version of %d",
2355 count, buflen, le32_to_cpu(local_acl->a_version)));
2356 if(le32_to_cpu(local_acl->a_version) != 2) {
2357 cFYI(1,("unknown POSIX ACL version %d",
2358 le32_to_cpu(local_acl->a_version)));
2361 cifs_acl->version = cpu_to_le16(1);
2362 if(acl_type == ACL_TYPE_ACCESS)
2363 cifs_acl->access_entry_count = cpu_to_le16(count);
2364 else if(acl_type == ACL_TYPE_DEFAULT)
2365 cifs_acl->default_entry_count = cpu_to_le16(count);
2367 cFYI(1,("unknown ACL type %d",acl_type));
2370 for(i=0;i<count;i++) {
2371 rc = convert_ace_to_cifs_ace(&cifs_acl->ace_array[i],
2372 &local_acl->a_entries[i]);
2374 /* ACE not converted */
2379 rc = (__u16)(count * sizeof(struct cifs_posix_ace));
2380 rc += sizeof(struct cifs_posix_acl);
2381 /* BB add check to make sure ACL does not overflow SMB */
2387 CIFSSMBGetPosixACL(const int xid, struct cifsTconInfo *tcon,
2388 const unsigned char *searchName,
2389 char *acl_inf, const int buflen, const int acl_type,
2390 const struct nls_table *nls_codepage, int remap)
2392 /* SMB_QUERY_POSIX_ACL */
2393 TRANSACTION2_QPI_REQ *pSMB = NULL;
2394 TRANSACTION2_QPI_RSP *pSMBr = NULL;
2398 __u16 params, byte_count;
2400 cFYI(1, ("In GetPosixACL (Unix) for path %s", searchName));
2403 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2408 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2410 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
2411 PATH_MAX, nls_codepage, remap);
2412 name_len++; /* trailing null */
2414 pSMB->FileName[name_len] = 0;
2415 pSMB->FileName[name_len+1] = 0;
2416 } else { /* BB improve the check for buffer overruns BB */
2417 name_len = strnlen(searchName, PATH_MAX);
2418 name_len++; /* trailing null */
2419 strncpy(pSMB->FileName, searchName, name_len);
2422 params = 2 /* level */ + 4 /* rsrvd */ + name_len /* incl null */ ;
2423 pSMB->TotalDataCount = 0;
2424 pSMB->MaxParameterCount = cpu_to_le16(2);
2425 /* BB find exact max data count below from sess structure BB */
2426 pSMB->MaxDataCount = cpu_to_le16(4000);
2427 pSMB->MaxSetupCount = 0;
2431 pSMB->Reserved2 = 0;
2432 pSMB->ParameterOffset = cpu_to_le16(
2433 offsetof(struct smb_com_transaction2_qpi_req ,InformationLevel) - 4);
2434 pSMB->DataCount = 0;
2435 pSMB->DataOffset = 0;
2436 pSMB->SetupCount = 1;
2437 pSMB->Reserved3 = 0;
2438 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
2439 byte_count = params + 1 /* pad */ ;
2440 pSMB->TotalParameterCount = cpu_to_le16(params);
2441 pSMB->ParameterCount = pSMB->TotalParameterCount;
2442 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_POSIX_ACL);
2443 pSMB->Reserved4 = 0;
2444 pSMB->hdr.smb_buf_length += byte_count;
2445 pSMB->ByteCount = cpu_to_le16(byte_count);
2447 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2448 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2449 cifs_stats_inc(&tcon->num_acl_get);
2451 cFYI(1, ("Send error in Query POSIX ACL = %d", rc));
2453 /* decode response */
2455 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
2456 if (rc || (pSMBr->ByteCount < 2))
2457 /* BB also check enough total bytes returned */
2458 rc = -EIO; /* bad smb */
2460 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
2461 __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
2462 rc = cifs_copy_posix_acl(acl_inf,
2463 (char *)&pSMBr->hdr.Protocol+data_offset,
2464 buflen,acl_type,count);
2467 cifs_buf_release(pSMB);
2474 CIFSSMBSetPosixACL(const int xid, struct cifsTconInfo *tcon,
2475 const unsigned char *fileName,
2476 const char *local_acl, const int buflen,
2478 const struct nls_table *nls_codepage, int remap)
2480 struct smb_com_transaction2_spi_req *pSMB = NULL;
2481 struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
2485 int bytes_returned = 0;
2486 __u16 params, byte_count, data_count, param_offset, offset;
2488 cFYI(1, ("In SetPosixACL (Unix) for path %s", fileName));
2490 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2494 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2496 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
2497 PATH_MAX, nls_codepage, remap);
2498 name_len++; /* trailing null */
2500 } else { /* BB improve the check for buffer overruns BB */
2501 name_len = strnlen(fileName, PATH_MAX);
2502 name_len++; /* trailing null */
2503 strncpy(pSMB->FileName, fileName, name_len);
2505 params = 6 + name_len;
2506 pSMB->MaxParameterCount = cpu_to_le16(2);
2507 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB size from sess */
2508 pSMB->MaxSetupCount = 0;
2512 pSMB->Reserved2 = 0;
2513 param_offset = offsetof(struct smb_com_transaction2_spi_req,
2514 InformationLevel) - 4;
2515 offset = param_offset + params;
2516 parm_data = ((char *) &pSMB->hdr.Protocol) + offset;
2517 pSMB->ParameterOffset = cpu_to_le16(param_offset);
2519 /* convert to on the wire format for POSIX ACL */
2520 data_count = ACL_to_cifs_posix(parm_data,local_acl,buflen,acl_type);
2522 if(data_count == 0) {
2524 goto setACLerrorExit;
2526 pSMB->DataOffset = cpu_to_le16(offset);
2527 pSMB->SetupCount = 1;
2528 pSMB->Reserved3 = 0;
2529 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
2530 pSMB->InformationLevel = cpu_to_le16(SMB_SET_POSIX_ACL);
2531 byte_count = 3 /* pad */ + params + data_count;
2532 pSMB->DataCount = cpu_to_le16(data_count);
2533 pSMB->TotalDataCount = pSMB->DataCount;
2534 pSMB->ParameterCount = cpu_to_le16(params);
2535 pSMB->TotalParameterCount = pSMB->ParameterCount;
2536 pSMB->Reserved4 = 0;
2537 pSMB->hdr.smb_buf_length += byte_count;
2538 pSMB->ByteCount = cpu_to_le16(byte_count);
2539 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2540 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2542 cFYI(1, ("Set POSIX ACL returned %d", rc));
2546 cifs_buf_release(pSMB);
2552 /* BB fix tabs in this function FIXME BB */
2554 CIFSGetExtAttr(const int xid, struct cifsTconInfo *tcon,
2555 const int netfid, __u64 * pExtAttrBits, __u64 *pMask)
2558 struct smb_t2_qfi_req *pSMB = NULL;
2559 struct smb_t2_qfi_rsp *pSMBr = NULL;
2561 __u16 params, byte_count;
2563 cFYI(1,("In GetExtAttr"));
2568 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2573 params = 2 /* level */ +2 /* fid */;
2574 pSMB->t2.TotalDataCount = 0;
2575 pSMB->t2.MaxParameterCount = cpu_to_le16(4);
2576 /* BB find exact max data count below from sess structure BB */
2577 pSMB->t2.MaxDataCount = cpu_to_le16(4000);
2578 pSMB->t2.MaxSetupCount = 0;
2579 pSMB->t2.Reserved = 0;
2581 pSMB->t2.Timeout = 0;
2582 pSMB->t2.Reserved2 = 0;
2583 pSMB->t2.ParameterOffset = cpu_to_le16(offsetof(struct smb_t2_qfi_req,
2585 pSMB->t2.DataCount = 0;
2586 pSMB->t2.DataOffset = 0;
2587 pSMB->t2.SetupCount = 1;
2588 pSMB->t2.Reserved3 = 0;
2589 pSMB->t2.SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION);
2590 byte_count = params + 1 /* pad */ ;
2591 pSMB->t2.TotalParameterCount = cpu_to_le16(params);
2592 pSMB->t2.ParameterCount = pSMB->t2.TotalParameterCount;
2593 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_ATTR_FLAGS);
2596 pSMB->hdr.smb_buf_length += byte_count;
2597 pSMB->t2.ByteCount = cpu_to_le16(byte_count);
2599 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2600 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2602 cFYI(1, ("error %d in GetExtAttr", rc));
2604 /* decode response */
2605 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
2606 if (rc || (pSMBr->ByteCount < 2))
2607 /* BB also check enough total bytes returned */
2608 /* If rc should we check for EOPNOSUPP and
2609 disable the srvino flag? or in caller? */
2610 rc = -EIO; /* bad smb */
2612 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
2613 __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
2614 struct file_chattr_info * pfinfo;
2615 /* BB Do we need a cast or hash here ? */
2617 cFYI(1, ("Illegal size ret in GetExtAttr"));
2621 pfinfo = (struct file_chattr_info *)
2622 (data_offset + (char *) &pSMBr->hdr.Protocol);
2623 *pExtAttrBits = le64_to_cpu(pfinfo->mode);
2624 *pMask = le64_to_cpu(pfinfo->mask);
2628 cifs_buf_release(pSMB);
2630 goto GetExtAttrRetry;
2635 #endif /* CONFIG_POSIX */
2638 /* security id for everyone */
2639 const struct cifs_sid sid_everyone = {1, 1, {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0}};
2641 const struct cifs_sid sid_user = {1, 2 , {0, 0, 0, 0, 0, 5}, {32, 545, 0, 0}};
2643 /* Convert CIFS ACL to POSIX form */
2644 static int parse_sec_desc(struct cifs_sid * psec_desc, int acl_len)
2649 /* Get Security Descriptor (by handle) from remote server for a file or dir */
2651 CIFSSMBGetCIFSACL(const int xid, struct cifsTconInfo *tcon, __u16 fid,
2652 /* BB fix up return info */ char *acl_inf, const int buflen,
2653 const int acl_type /* ACCESS/DEFAULT not sure implication */)
2657 QUERY_SEC_DESC_REQ * pSMB;
2660 cFYI(1, ("GetCifsACL"));
2662 rc = smb_init_ntransact(NT_TRANSACT_QUERY_SECURITY_DESC, 0,
2663 8 /* parm len */, tcon, (void **) &pSMB);
2667 pSMB->MaxParameterCount = cpu_to_le32(4);
2668 /* BB TEST with big acls that might need to be e.g. larger than 16K */
2669 pSMB->MaxSetupCount = 0;
2670 pSMB->Fid = fid; /* file handle always le */
2671 pSMB->AclFlags = cpu_to_le32(CIFS_ACL_OWNER | CIFS_ACL_GROUP |
2673 pSMB->ByteCount = cpu_to_le16(11); /* 3 bytes pad + 8 bytes parm */
2674 pSMB->hdr.smb_buf_length += 11;
2675 iov[0].iov_base = (char *)pSMB;
2676 iov[0].iov_len = pSMB->hdr.smb_buf_length + 4;
2678 rc = SendReceive2(xid, tcon->ses, iov, 1 /* num iovec */, &buf_type, 0);
2679 cifs_stats_inc(&tcon->num_acl_get);
2681 cFYI(1, ("Send error in QuerySecDesc = %d", rc));
2682 } else { /* decode response */
2683 struct cifs_sid * psec_desc;
2688 struct smb_com_ntransact_rsp * pSMBr;
2690 /* validate_nttransact */
2691 rc = validate_ntransact(iov[0].iov_base, (char **)&parm,
2692 (char **)&psec_desc,
2693 &parm_len, &data_len);
2697 pSMBr = (struct smb_com_ntransact_rsp *)iov[0].iov_base;
2699 cERROR(1,("smb %p parm %p data %p",pSMBr,parm,psec_desc)); /* BB removeme BB */
2701 if (le32_to_cpu(pSMBr->ParameterCount) != 4) {
2702 rc = -EIO; /* bad smb */
2706 /* BB check that data area is minimum length and as big as acl_len */
2708 acl_len = le32_to_cpu(*(__le32 *)parm);
2709 /* BB check if(acl_len > bufsize) */
2711 parse_sec_desc(psec_desc, acl_len);
2714 if(buf_type == CIFS_SMALL_BUFFER)
2715 cifs_small_buf_release(iov[0].iov_base);
2716 else if(buf_type == CIFS_LARGE_BUFFER)
2717 cifs_buf_release(iov[0].iov_base);
2718 /* cifs_small_buf_release(pSMB); */ /* Freed earlier now in SendReceive2 */
2723 /* Legacy Query Path Information call for lookup to old servers such
2725 int SMBQueryInformation(const int xid, struct cifsTconInfo *tcon,
2726 const unsigned char *searchName,
2727 FILE_ALL_INFO * pFinfo,
2728 const struct nls_table *nls_codepage, int remap)
2730 QUERY_INFORMATION_REQ * pSMB;
2731 QUERY_INFORMATION_RSP * pSMBr;
2736 cFYI(1, ("In SMBQPath path %s", searchName));
2738 rc = smb_init(SMB_COM_QUERY_INFORMATION, 0, tcon, (void **) &pSMB,
2743 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2745 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
2746 PATH_MAX, nls_codepage, remap);
2747 name_len++; /* trailing null */
2750 name_len = strnlen(searchName, PATH_MAX);
2751 name_len++; /* trailing null */
2752 strncpy(pSMB->FileName, searchName, name_len);
2754 pSMB->BufferFormat = 0x04;
2755 name_len++; /* account for buffer type byte */
2756 pSMB->hdr.smb_buf_length += (__u16) name_len;
2757 pSMB->ByteCount = cpu_to_le16(name_len);
2759 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2760 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2762 cFYI(1, ("Send error in QueryInfo = %d", rc));
2763 } else if (pFinfo) { /* decode response */
2764 memset(pFinfo, 0, sizeof(FILE_ALL_INFO));
2765 pFinfo->AllocationSize =
2766 cpu_to_le64(le32_to_cpu(pSMBr->size));
2767 pFinfo->EndOfFile = pFinfo->AllocationSize;
2768 pFinfo->Attributes =
2769 cpu_to_le32(le16_to_cpu(pSMBr->attr));
2771 rc = -EIO; /* bad buffer passed in */
2773 cifs_buf_release(pSMB);
2785 CIFSSMBQPathInfo(const int xid, struct cifsTconInfo *tcon,
2786 const unsigned char *searchName,
2787 FILE_ALL_INFO * pFindData,
2788 const struct nls_table *nls_codepage, int remap)
2790 /* level 263 SMB_QUERY_FILE_ALL_INFO */
2791 TRANSACTION2_QPI_REQ *pSMB = NULL;
2792 TRANSACTION2_QPI_RSP *pSMBr = NULL;
2796 __u16 params, byte_count;
2798 /* cFYI(1, ("In QPathInfo path %s", searchName)); */
2800 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2805 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2807 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
2808 PATH_MAX, nls_codepage, remap);
2809 name_len++; /* trailing null */
2811 } else { /* BB improve the check for buffer overruns BB */
2812 name_len = strnlen(searchName, PATH_MAX);
2813 name_len++; /* trailing null */
2814 strncpy(pSMB->FileName, searchName, name_len);
2817 params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */ ;
2818 pSMB->TotalDataCount = 0;
2819 pSMB->MaxParameterCount = cpu_to_le16(2);
2820 pSMB->MaxDataCount = cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
2821 pSMB->MaxSetupCount = 0;
2825 pSMB->Reserved2 = 0;
2826 pSMB->ParameterOffset = cpu_to_le16(offsetof(
2827 struct smb_com_transaction2_qpi_req ,InformationLevel) - 4);
2828 pSMB->DataCount = 0;
2829 pSMB->DataOffset = 0;
2830 pSMB->SetupCount = 1;
2831 pSMB->Reserved3 = 0;
2832 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
2833 byte_count = params + 1 /* pad */ ;
2834 pSMB->TotalParameterCount = cpu_to_le16(params);
2835 pSMB->ParameterCount = pSMB->TotalParameterCount;
2836 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_ALL_INFO);
2837 pSMB->Reserved4 = 0;
2838 pSMB->hdr.smb_buf_length += byte_count;
2839 pSMB->ByteCount = cpu_to_le16(byte_count);
2841 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2842 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2844 cFYI(1, ("Send error in QPathInfo = %d", rc));
2845 } else { /* decode response */
2846 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
2848 if (rc || (pSMBr->ByteCount < 40))
2849 rc = -EIO; /* bad smb */
2850 else if (pFindData){
2851 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
2852 memcpy((char *) pFindData,
2853 (char *) &pSMBr->hdr.Protocol +
2854 data_offset, sizeof (FILE_ALL_INFO));
2858 cifs_buf_release(pSMB);
2860 goto QPathInfoRetry;
2866 CIFSSMBUnixQPathInfo(const int xid, struct cifsTconInfo *tcon,
2867 const unsigned char *searchName,
2868 FILE_UNIX_BASIC_INFO * pFindData,
2869 const struct nls_table *nls_codepage, int remap)
2871 /* SMB_QUERY_FILE_UNIX_BASIC */
2872 TRANSACTION2_QPI_REQ *pSMB = NULL;
2873 TRANSACTION2_QPI_RSP *pSMBr = NULL;
2875 int bytes_returned = 0;
2877 __u16 params, byte_count;
2879 cFYI(1, ("In QPathInfo (Unix) the path %s", searchName));
2881 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2886 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2888 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
2889 PATH_MAX, nls_codepage, remap);
2890 name_len++; /* trailing null */
2892 } else { /* BB improve the check for buffer overruns BB */
2893 name_len = strnlen(searchName, PATH_MAX);
2894 name_len++; /* trailing null */
2895 strncpy(pSMB->FileName, searchName, name_len);
2898 params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */ ;
2899 pSMB->TotalDataCount = 0;
2900 pSMB->MaxParameterCount = cpu_to_le16(2);
2901 /* BB find exact max SMB PDU from sess structure BB */
2902 pSMB->MaxDataCount = cpu_to_le16(4000);
2903 pSMB->MaxSetupCount = 0;
2907 pSMB->Reserved2 = 0;
2908 pSMB->ParameterOffset = cpu_to_le16(offsetof(
2909 struct smb_com_transaction2_qpi_req ,InformationLevel) - 4);
2910 pSMB->DataCount = 0;
2911 pSMB->DataOffset = 0;
2912 pSMB->SetupCount = 1;
2913 pSMB->Reserved3 = 0;
2914 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
2915 byte_count = params + 1 /* pad */ ;
2916 pSMB->TotalParameterCount = cpu_to_le16(params);
2917 pSMB->ParameterCount = pSMB->TotalParameterCount;
2918 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC);
2919 pSMB->Reserved4 = 0;
2920 pSMB->hdr.smb_buf_length += byte_count;
2921 pSMB->ByteCount = cpu_to_le16(byte_count);
2923 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2924 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2926 cFYI(1, ("Send error in QPathInfo = %d", rc));
2927 } else { /* decode response */
2928 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
2930 if (rc || (pSMBr->ByteCount < sizeof(FILE_UNIX_BASIC_INFO))) {
2931 rc = -EIO; /* bad smb */
2933 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
2934 memcpy((char *) pFindData,
2935 (char *) &pSMBr->hdr.Protocol +
2937 sizeof (FILE_UNIX_BASIC_INFO));
2940 cifs_buf_release(pSMB);
2942 goto UnixQPathInfoRetry;
2947 #if 0 /* function unused at present */
2948 int CIFSFindSingle(const int xid, struct cifsTconInfo *tcon,
2949 const char *searchName, FILE_ALL_INFO * findData,
2950 const struct nls_table *nls_codepage)
2952 /* level 257 SMB_ */
2953 TRANSACTION2_FFIRST_REQ *pSMB = NULL;
2954 TRANSACTION2_FFIRST_RSP *pSMBr = NULL;
2958 __u16 params, byte_count;
2960 cFYI(1, ("In FindUnique"));
2962 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2967 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2969 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName, PATH_MAX
2970 /* find define for this maxpathcomponent */
2972 name_len++; /* trailing null */
2974 } else { /* BB improve the check for buffer overruns BB */
2975 name_len = strnlen(searchName, PATH_MAX);
2976 name_len++; /* trailing null */
2977 strncpy(pSMB->FileName, searchName, name_len);
2980 params = 12 + name_len /* includes null */ ;
2981 pSMB->TotalDataCount = 0; /* no EAs */
2982 pSMB->MaxParameterCount = cpu_to_le16(2);
2983 pSMB->MaxDataCount = cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
2984 pSMB->MaxSetupCount = 0;
2988 pSMB->Reserved2 = 0;
2989 pSMB->ParameterOffset = cpu_to_le16(
2990 offsetof(struct smb_com_transaction2_ffirst_req,InformationLevel) - 4);
2991 pSMB->DataCount = 0;
2992 pSMB->DataOffset = 0;
2993 pSMB->SetupCount = 1; /* one byte, no need to le convert */
2994 pSMB->Reserved3 = 0;
2995 pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_FIRST);
2996 byte_count = params + 1 /* pad */ ;
2997 pSMB->TotalParameterCount = cpu_to_le16(params);
2998 pSMB->ParameterCount = pSMB->TotalParameterCount;
2999 pSMB->SearchAttributes =
3000 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
3002 pSMB->SearchCount = cpu_to_le16(16); /* BB increase */
3003 pSMB->SearchFlags = cpu_to_le16(1);
3004 pSMB->InformationLevel = cpu_to_le16(SMB_FIND_FILE_DIRECTORY_INFO);
3005 pSMB->SearchStorageType = 0; /* BB what should we set this to? BB */
3006 pSMB->hdr.smb_buf_length += byte_count;
3007 pSMB->ByteCount = cpu_to_le16(byte_count);
3009 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3010 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3013 cFYI(1, ("Send error in FindFileDirInfo = %d", rc));
3014 } else { /* decode response */
3015 cifs_stats_inc(&tcon->num_ffirst);
3019 cifs_buf_release(pSMB);
3021 goto findUniqueRetry;
3025 #endif /* end unused (temporarily) function */
3027 /* xid, tcon, searchName and codepage are input parms, rest are returned */
3029 CIFSFindFirst(const int xid, struct cifsTconInfo *tcon,
3030 const char *searchName,
3031 const struct nls_table *nls_codepage,
3033 struct cifs_search_info * psrch_inf, int remap, const char dirsep)
3035 /* level 257 SMB_ */
3036 TRANSACTION2_FFIRST_REQ *pSMB = NULL;
3037 TRANSACTION2_FFIRST_RSP *pSMBr = NULL;
3038 T2_FFIRST_RSP_PARMS * parms;
3040 int bytes_returned = 0;
3042 __u16 params, byte_count;
3044 cFYI(1, ("In FindFirst for %s",searchName));
3047 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3052 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3054 cifsConvertToUCS((__le16 *) pSMB->FileName,searchName,
3055 PATH_MAX, nls_codepage, remap);
3056 /* We can not add the asterik earlier in case
3057 it got remapped to 0xF03A as if it were part of the
3058 directory name instead of a wildcard */
3060 pSMB->FileName[name_len] = dirsep;
3061 pSMB->FileName[name_len+1] = 0;
3062 pSMB->FileName[name_len+2] = '*';
3063 pSMB->FileName[name_len+3] = 0;
3064 name_len += 4; /* now the trailing null */
3065 pSMB->FileName[name_len] = 0; /* null terminate just in case */
3066 pSMB->FileName[name_len+1] = 0;
3068 } else { /* BB add check for overrun of SMB buf BB */
3069 name_len = strnlen(searchName, PATH_MAX);
3070 /* BB fix here and in unicode clause above ie
3071 if(name_len > buffersize-header)
3072 free buffer exit; BB */
3073 strncpy(pSMB->FileName, searchName, name_len);
3074 pSMB->FileName[name_len] = dirsep;
3075 pSMB->FileName[name_len+1] = '*';
3076 pSMB->FileName[name_len+2] = 0;
3080 params = 12 + name_len /* includes null */ ;
3081 pSMB->TotalDataCount = 0; /* no EAs */
3082 pSMB->MaxParameterCount = cpu_to_le16(10);
3083 pSMB->MaxDataCount = cpu_to_le16((tcon->ses->server->maxBuf -
3084 MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
3085 pSMB->MaxSetupCount = 0;
3089 pSMB->Reserved2 = 0;
3090 byte_count = params + 1 /* pad */ ;
3091 pSMB->TotalParameterCount = cpu_to_le16(params);
3092 pSMB->ParameterCount = pSMB->TotalParameterCount;
3093 pSMB->ParameterOffset = cpu_to_le16(
3094 offsetof(struct smb_com_transaction2_ffirst_req, SearchAttributes)
3096 pSMB->DataCount = 0;
3097 pSMB->DataOffset = 0;
3098 pSMB->SetupCount = 1; /* one byte, no need to make endian neutral */
3099 pSMB->Reserved3 = 0;
3100 pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_FIRST);
3101 pSMB->SearchAttributes =
3102 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
3104 pSMB->SearchCount= cpu_to_le16(CIFSMaxBufSize/sizeof(FILE_UNIX_INFO));
3105 pSMB->SearchFlags = cpu_to_le16(CIFS_SEARCH_CLOSE_AT_END |
3106 CIFS_SEARCH_RETURN_RESUME);
3107 pSMB->InformationLevel = cpu_to_le16(psrch_inf->info_level);
3109 /* BB what should we set StorageType to? Does it matter? BB */
3110 pSMB->SearchStorageType = 0;
3111 pSMB->hdr.smb_buf_length += byte_count;
3112 pSMB->ByteCount = cpu_to_le16(byte_count);
3114 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3115 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3116 cifs_stats_inc(&tcon->num_ffirst);
3118 if (rc) {/* BB add logic to retry regular search if Unix search
3119 rejected unexpectedly by server */
3120 /* BB Add code to handle unsupported level rc */
3121 cFYI(1, ("Error in FindFirst = %d", rc));
3123 cifs_buf_release(pSMB);
3125 /* BB eventually could optimize out free and realloc of buf */
3128 goto findFirstRetry;
3129 } else { /* decode response */
3130 /* BB remember to free buffer if error BB */
3131 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3133 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
3134 psrch_inf->unicode = TRUE;
3136 psrch_inf->unicode = FALSE;
3138 psrch_inf->ntwrk_buf_start = (char *)pSMBr;
3139 psrch_inf->smallBuf = 0;
3140 psrch_inf->srch_entries_start =
3141 (char *) &pSMBr->hdr.Protocol +
3142 le16_to_cpu(pSMBr->t2.DataOffset);
3143 parms = (T2_FFIRST_RSP_PARMS *)((char *) &pSMBr->hdr.Protocol +
3144 le16_to_cpu(pSMBr->t2.ParameterOffset));
3146 if(parms->EndofSearch)
3147 psrch_inf->endOfSearch = TRUE;
3149 psrch_inf->endOfSearch = FALSE;
3151 psrch_inf->entries_in_buffer = le16_to_cpu(parms->SearchCount);
3152 psrch_inf->index_of_last_entry = 2 /* skip . and .. */ +
3153 psrch_inf->entries_in_buffer;
3154 *pnetfid = parms->SearchHandle;
3156 cifs_buf_release(pSMB);
3163 int CIFSFindNext(const int xid, struct cifsTconInfo *tcon,
3164 __u16 searchHandle, struct cifs_search_info * psrch_inf)
3166 TRANSACTION2_FNEXT_REQ *pSMB = NULL;
3167 TRANSACTION2_FNEXT_RSP *pSMBr = NULL;
3168 T2_FNEXT_RSP_PARMS * parms;
3169 char *response_data;
3171 int bytes_returned, name_len;
3172 __u16 params, byte_count;
3174 cFYI(1, ("In FindNext"));
3176 if(psrch_inf->endOfSearch == TRUE)
3179 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3184 params = 14; /* includes 2 bytes of null string, converted to LE below */
3186 pSMB->TotalDataCount = 0; /* no EAs */
3187 pSMB->MaxParameterCount = cpu_to_le16(8);
3188 pSMB->MaxDataCount =
3189 cpu_to_le16((tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
3190 pSMB->MaxSetupCount = 0;
3194 pSMB->Reserved2 = 0;
3195 pSMB->ParameterOffset = cpu_to_le16(
3196 offsetof(struct smb_com_transaction2_fnext_req,SearchHandle) - 4);
3197 pSMB->DataCount = 0;
3198 pSMB->DataOffset = 0;
3199 pSMB->SetupCount = 1;
3200 pSMB->Reserved3 = 0;
3201 pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_NEXT);
3202 pSMB->SearchHandle = searchHandle; /* always kept as le */
3204 cpu_to_le16(CIFSMaxBufSize / sizeof (FILE_UNIX_INFO));
3205 /* test for Unix extensions */
3206 /* if (tcon->ses->capabilities & CAP_UNIX) {
3207 pSMB->InformationLevel = cpu_to_le16(SMB_FIND_FILE_UNIX);
3208 psrch_inf->info_level = SMB_FIND_FILE_UNIX;
3210 pSMB->InformationLevel =
3211 cpu_to_le16(SMB_FIND_FILE_DIRECTORY_INFO);
3212 psrch_inf->info_level = SMB_FIND_FILE_DIRECTORY_INFO;
3214 pSMB->InformationLevel = cpu_to_le16(psrch_inf->info_level);
3215 pSMB->ResumeKey = psrch_inf->resume_key;
3217 cpu_to_le16(CIFS_SEARCH_CLOSE_AT_END | CIFS_SEARCH_RETURN_RESUME);
3219 name_len = psrch_inf->resume_name_len;
3221 if(name_len < PATH_MAX) {
3222 memcpy(pSMB->ResumeFileName, psrch_inf->presume_name, name_len);
3223 byte_count += name_len;
3224 /* 14 byte parm len above enough for 2 byte null terminator */
3225 pSMB->ResumeFileName[name_len] = 0;
3226 pSMB->ResumeFileName[name_len+1] = 0;
3229 goto FNext2_err_exit;
3231 byte_count = params + 1 /* pad */ ;
3232 pSMB->TotalParameterCount = cpu_to_le16(params);
3233 pSMB->ParameterCount = pSMB->TotalParameterCount;
3234 pSMB->hdr.smb_buf_length += byte_count;
3235 pSMB->ByteCount = cpu_to_le16(byte_count);
3237 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3238 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3239 cifs_stats_inc(&tcon->num_fnext);
3242 psrch_inf->endOfSearch = TRUE;
3243 rc = 0; /* search probably was closed at end of search above */
3245 cFYI(1, ("FindNext returned = %d", rc));
3246 } else { /* decode response */
3247 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3250 /* BB fixme add lock for file (srch_info) struct here */
3251 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
3252 psrch_inf->unicode = TRUE;
3254 psrch_inf->unicode = FALSE;
3255 response_data = (char *) &pSMBr->hdr.Protocol +
3256 le16_to_cpu(pSMBr->t2.ParameterOffset);
3257 parms = (T2_FNEXT_RSP_PARMS *)response_data;
3258 response_data = (char *)&pSMBr->hdr.Protocol +
3259 le16_to_cpu(pSMBr->t2.DataOffset);
3260 if(psrch_inf->smallBuf)
3261 cifs_small_buf_release(
3262 psrch_inf->ntwrk_buf_start);
3264 cifs_buf_release(psrch_inf->ntwrk_buf_start);
3265 psrch_inf->srch_entries_start = response_data;
3266 psrch_inf->ntwrk_buf_start = (char *)pSMB;
3267 psrch_inf->smallBuf = 0;
3268 if(parms->EndofSearch)
3269 psrch_inf->endOfSearch = TRUE;
3271 psrch_inf->endOfSearch = FALSE;
3273 psrch_inf->entries_in_buffer = le16_to_cpu(parms->SearchCount);
3274 psrch_inf->index_of_last_entry +=
3275 psrch_inf->entries_in_buffer;
3276 /* cFYI(1,("fnxt2 entries in buf %d index_of_last %d",psrch_inf->entries_in_buffer,psrch_inf->index_of_last_entry)); */
3278 /* BB fixme add unlock here */
3283 /* BB On error, should we leave previous search buf (and count and
3284 last entry fields) intact or free the previous one? */
3286 /* Note: On -EAGAIN error only caller can retry on handle based calls
3287 since file handle passed in no longer valid */
3290 cifs_buf_release(pSMB);
3296 CIFSFindClose(const int xid, struct cifsTconInfo *tcon, const __u16 searchHandle)
3299 FINDCLOSE_REQ *pSMB = NULL;
3300 CLOSE_RSP *pSMBr = NULL; /* BB removeme BB */
3303 cFYI(1, ("In CIFSSMBFindClose"));
3304 rc = small_smb_init(SMB_COM_FIND_CLOSE2, 1, tcon, (void **)&pSMB);
3306 /* no sense returning error if session restarted
3307 as file handle has been closed */
3313 pSMBr = (CLOSE_RSP *)pSMB; /* BB removeme BB */
3314 pSMB->FileID = searchHandle;
3315 pSMB->ByteCount = 0;
3316 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3317 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3319 cERROR(1, ("Send error in FindClose = %d", rc));
3321 cifs_stats_inc(&tcon->num_fclose);
3322 cifs_small_buf_release(pSMB);
3324 /* Since session is dead, search handle closed on server already */
3332 CIFSGetSrvInodeNumber(const int xid, struct cifsTconInfo *tcon,
3333 const unsigned char *searchName,
3334 __u64 * inode_number,
3335 const struct nls_table *nls_codepage, int remap)
3338 TRANSACTION2_QPI_REQ *pSMB = NULL;
3339 TRANSACTION2_QPI_RSP *pSMBr = NULL;
3340 int name_len, bytes_returned;
3341 __u16 params, byte_count;
3343 cFYI(1,("In GetSrvInodeNum for %s",searchName));
3347 GetInodeNumberRetry:
3348 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3354 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3356 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
3357 PATH_MAX,nls_codepage, remap);
3358 name_len++; /* trailing null */
3360 } else { /* BB improve the check for buffer overruns BB */
3361 name_len = strnlen(searchName, PATH_MAX);
3362 name_len++; /* trailing null */
3363 strncpy(pSMB->FileName, searchName, name_len);
3366 params = 2 /* level */ + 4 /* rsrvd */ + name_len /* incl null */ ;
3367 pSMB->TotalDataCount = 0;
3368 pSMB->MaxParameterCount = cpu_to_le16(2);
3369 /* BB find exact max data count below from sess structure BB */
3370 pSMB->MaxDataCount = cpu_to_le16(4000);
3371 pSMB->MaxSetupCount = 0;
3375 pSMB->Reserved2 = 0;
3376 pSMB->ParameterOffset = cpu_to_le16(offsetof(
3377 struct smb_com_transaction2_qpi_req ,InformationLevel) - 4);
3378 pSMB->DataCount = 0;
3379 pSMB->DataOffset = 0;
3380 pSMB->SetupCount = 1;
3381 pSMB->Reserved3 = 0;
3382 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
3383 byte_count = params + 1 /* pad */ ;
3384 pSMB->TotalParameterCount = cpu_to_le16(params);
3385 pSMB->ParameterCount = pSMB->TotalParameterCount;
3386 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_INTERNAL_INFO);
3387 pSMB->Reserved4 = 0;
3388 pSMB->hdr.smb_buf_length += byte_count;
3389 pSMB->ByteCount = cpu_to_le16(byte_count);
3391 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3392 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3394 cFYI(1, ("error %d in QueryInternalInfo", rc));
3396 /* decode response */
3397 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3398 if (rc || (pSMBr->ByteCount < 2))
3399 /* BB also check enough total bytes returned */
3400 /* If rc should we check for EOPNOSUPP and
3401 disable the srvino flag? or in caller? */
3402 rc = -EIO; /* bad smb */
3404 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3405 __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
3406 struct file_internal_info * pfinfo;
3407 /* BB Do we need a cast or hash here ? */
3409 cFYI(1, ("Illegal size ret in QryIntrnlInf"));
3411 goto GetInodeNumOut;
3413 pfinfo = (struct file_internal_info *)
3414 (data_offset + (char *) &pSMBr->hdr.Protocol);
3415 *inode_number = pfinfo->UniqueId;
3419 cifs_buf_release(pSMB);
3421 goto GetInodeNumberRetry;
3426 CIFSGetDFSRefer(const int xid, struct cifsSesInfo *ses,
3427 const unsigned char *searchName,
3428 unsigned char **targetUNCs,
3429 unsigned int *number_of_UNC_in_array,
3430 const struct nls_table *nls_codepage, int remap)
3432 /* TRANS2_GET_DFS_REFERRAL */
3433 TRANSACTION2_GET_DFS_REFER_REQ *pSMB = NULL;
3434 TRANSACTION2_GET_DFS_REFER_RSP *pSMBr = NULL;
3435 struct dfs_referral_level_3 * referrals = NULL;
3441 __u16 params, byte_count;
3442 *number_of_UNC_in_array = 0;
3445 cFYI(1, ("In GetDFSRefer the path %s", searchName));
3449 rc = smb_init(SMB_COM_TRANSACTION2, 15, NULL, (void **) &pSMB,
3454 /* server pointer checked in called function,
3455 but should never be null here anyway */
3456 pSMB->hdr.Mid = GetNextMid(ses->server);
3457 pSMB->hdr.Tid = ses->ipc_tid;
3458 pSMB->hdr.Uid = ses->Suid;
3459 if (ses->capabilities & CAP_STATUS32) {
3460 pSMB->hdr.Flags2 |= SMBFLG2_ERR_STATUS;
3462 if (ses->capabilities & CAP_DFS) {
3463 pSMB->hdr.Flags2 |= SMBFLG2_DFS;
3466 if (ses->capabilities & CAP_UNICODE) {
3467 pSMB->hdr.Flags2 |= SMBFLG2_UNICODE;
3469 cifsConvertToUCS((__le16 *) pSMB->RequestFileName,
3470 searchName, PATH_MAX, nls_codepage, remap);
3471 name_len++; /* trailing null */
3473 } else { /* BB improve the check for buffer overruns BB */
3474 name_len = strnlen(searchName, PATH_MAX);
3475 name_len++; /* trailing null */
3476 strncpy(pSMB->RequestFileName, searchName, name_len);
3479 params = 2 /* level */ + name_len /*includes null */ ;
3480 pSMB->TotalDataCount = 0;
3481 pSMB->DataCount = 0;
3482 pSMB->DataOffset = 0;
3483 pSMB->MaxParameterCount = 0;
3484 pSMB->MaxDataCount = cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
3485 pSMB->MaxSetupCount = 0;
3489 pSMB->Reserved2 = 0;
3490 pSMB->ParameterOffset = cpu_to_le16(offsetof(
3491 struct smb_com_transaction2_get_dfs_refer_req, MaxReferralLevel) - 4);
3492 pSMB->SetupCount = 1;
3493 pSMB->Reserved3 = 0;
3494 pSMB->SubCommand = cpu_to_le16(TRANS2_GET_DFS_REFERRAL);
3495 byte_count = params + 3 /* pad */ ;
3496 pSMB->ParameterCount = cpu_to_le16(params);
3497 pSMB->TotalParameterCount = pSMB->ParameterCount;
3498 pSMB->MaxReferralLevel = cpu_to_le16(3);
3499 pSMB->hdr.smb_buf_length += byte_count;
3500 pSMB->ByteCount = cpu_to_le16(byte_count);
3502 rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB,
3503 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3505 cFYI(1, ("Send error in GetDFSRefer = %d", rc));
3506 } else { /* decode response */
3507 /* BB Add logic to parse referrals here */
3508 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3510 if (rc || (pSMBr->ByteCount < 17)) /* BB also check enough total bytes returned */
3511 rc = -EIO; /* bad smb */
3513 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3514 __u16 data_count = le16_to_cpu(pSMBr->t2.DataCount);
3517 ("Decoding GetDFSRefer response. BCC: %d Offset %d",
3518 pSMBr->ByteCount, data_offset));
3520 (struct dfs_referral_level_3 *)
3521 (8 /* sizeof start of data block */ +
3523 (char *) &pSMBr->hdr.Protocol);
3524 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",
3525 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)));
3526 /* BB This field is actually two bytes in from start of
3527 data block so we could do safety check that DataBlock
3528 begins at address of pSMBr->NumberOfReferrals */
3529 *number_of_UNC_in_array = le16_to_cpu(pSMBr->NumberOfReferrals);
3531 /* BB Fix below so can return more than one referral */
3532 if(*number_of_UNC_in_array > 1)
3533 *number_of_UNC_in_array = 1;
3535 /* get the length of the strings describing refs */
3537 for(i=0;i<*number_of_UNC_in_array;i++) {
3538 /* make sure that DfsPathOffset not past end */
3539 __u16 offset = le16_to_cpu(referrals->DfsPathOffset);
3540 if (offset > data_count) {
3541 /* if invalid referral, stop here and do
3542 not try to copy any more */
3543 *number_of_UNC_in_array = i;
3546 temp = ((char *)referrals) + offset;
3548 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
3549 name_len += UniStrnlen((wchar_t *)temp,data_count);
3551 name_len += strnlen(temp,data_count);
3554 /* BB add check that referral pointer does not fall off end PDU */
3557 /* BB add check for name_len bigger than bcc */
3559 kmalloc(name_len+1+ (*number_of_UNC_in_array),GFP_KERNEL);
3560 if(*targetUNCs == NULL) {
3564 /* copy the ref strings */
3566 (struct dfs_referral_level_3 *)
3567 (8 /* sizeof data hdr */ +
3569 (char *) &pSMBr->hdr.Protocol);
3571 for(i=0;i<*number_of_UNC_in_array;i++) {
3572 temp = ((char *)referrals) + le16_to_cpu(referrals->DfsPathOffset);
3573 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
3574 cifs_strfromUCS_le(*targetUNCs,
3575 (__le16 *) temp, name_len, nls_codepage);
3577 strncpy(*targetUNCs,temp,name_len);
3579 /* BB update target_uncs pointers */
3589 cifs_buf_release(pSMB);
3597 /* Query File System Info such as free space to old servers such as Win 9x */
3599 SMBOldQFSInfo(const int xid, struct cifsTconInfo *tcon, struct kstatfs *FSData)
3601 /* level 0x01 SMB_QUERY_FILE_SYSTEM_INFO */
3602 TRANSACTION2_QFSI_REQ *pSMB = NULL;
3603 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
3604 FILE_SYSTEM_ALLOC_INFO *response_data;
3606 int bytes_returned = 0;
3607 __u16 params, byte_count;
3609 cFYI(1, ("OldQFSInfo"));
3611 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3615 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3620 params = 2; /* level */
3621 pSMB->TotalDataCount = 0;
3622 pSMB->MaxParameterCount = cpu_to_le16(2);
3623 pSMB->MaxDataCount = cpu_to_le16(1000);
3624 pSMB->MaxSetupCount = 0;
3628 pSMB->Reserved2 = 0;
3629 byte_count = params + 1 /* pad */ ;
3630 pSMB->TotalParameterCount = cpu_to_le16(params);
3631 pSMB->ParameterCount = pSMB->TotalParameterCount;
3632 pSMB->ParameterOffset = cpu_to_le16(offsetof(
3633 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
3634 pSMB->DataCount = 0;
3635 pSMB->DataOffset = 0;
3636 pSMB->SetupCount = 1;
3637 pSMB->Reserved3 = 0;
3638 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
3639 pSMB->InformationLevel = cpu_to_le16(SMB_INFO_ALLOCATION);
3640 pSMB->hdr.smb_buf_length += byte_count;
3641 pSMB->ByteCount = cpu_to_le16(byte_count);
3643 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3644 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3646 cFYI(1, ("Send error in QFSInfo = %d", rc));
3647 } else { /* decode response */
3648 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3650 if (rc || (pSMBr->ByteCount < 18))
3651 rc = -EIO; /* bad smb */
3653 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3654 cFYI(1,("qfsinf resp BCC: %d Offset %d",
3655 pSMBr->ByteCount, data_offset));
3658 (FILE_SYSTEM_ALLOC_INFO *)
3659 (((char *) &pSMBr->hdr.Protocol) + data_offset);
3661 le16_to_cpu(response_data->BytesPerSector) *
3662 le32_to_cpu(response_data->
3663 SectorsPerAllocationUnit);
3665 le32_to_cpu(response_data->TotalAllocationUnits);
3666 FSData->f_bfree = FSData->f_bavail =
3667 le32_to_cpu(response_data->FreeAllocationUnits);
3669 ("Blocks: %lld Free: %lld Block size %ld",
3670 (unsigned long long)FSData->f_blocks,
3671 (unsigned long long)FSData->f_bfree,
3675 cifs_buf_release(pSMB);
3678 goto oldQFSInfoRetry;
3684 CIFSSMBQFSInfo(const int xid, struct cifsTconInfo *tcon, struct kstatfs *FSData)
3686 /* level 0x103 SMB_QUERY_FILE_SYSTEM_INFO */
3687 TRANSACTION2_QFSI_REQ *pSMB = NULL;
3688 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
3689 FILE_SYSTEM_INFO *response_data;
3691 int bytes_returned = 0;
3692 __u16 params, byte_count;
3694 cFYI(1, ("In QFSInfo"));
3696 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3701 params = 2; /* level */
3702 pSMB->TotalDataCount = 0;
3703 pSMB->MaxParameterCount = cpu_to_le16(2);
3704 pSMB->MaxDataCount = cpu_to_le16(1000);
3705 pSMB->MaxSetupCount = 0;
3709 pSMB->Reserved2 = 0;
3710 byte_count = params + 1 /* pad */ ;
3711 pSMB->TotalParameterCount = cpu_to_le16(params);
3712 pSMB->ParameterCount = pSMB->TotalParameterCount;
3713 pSMB->ParameterOffset = cpu_to_le16(offsetof(
3714 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
3715 pSMB->DataCount = 0;
3716 pSMB->DataOffset = 0;
3717 pSMB->SetupCount = 1;
3718 pSMB->Reserved3 = 0;
3719 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
3720 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_SIZE_INFO);
3721 pSMB->hdr.smb_buf_length += byte_count;
3722 pSMB->ByteCount = cpu_to_le16(byte_count);
3724 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3725 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3727 cFYI(1, ("Send error in QFSInfo = %d", rc));
3728 } else { /* decode response */
3729 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3731 if (rc || (pSMBr->ByteCount < 24))
3732 rc = -EIO; /* bad smb */
3734 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3738 *) (((char *) &pSMBr->hdr.Protocol) +
3741 le32_to_cpu(response_data->BytesPerSector) *
3742 le32_to_cpu(response_data->
3743 SectorsPerAllocationUnit);
3745 le64_to_cpu(response_data->TotalAllocationUnits);
3746 FSData->f_bfree = FSData->f_bavail =
3747 le64_to_cpu(response_data->FreeAllocationUnits);
3749 ("Blocks: %lld Free: %lld Block size %ld",
3750 (unsigned long long)FSData->f_blocks,
3751 (unsigned long long)FSData->f_bfree,
3755 cifs_buf_release(pSMB);
3764 CIFSSMBQFSAttributeInfo(const int xid, struct cifsTconInfo *tcon)
3766 /* level 0x105 SMB_QUERY_FILE_SYSTEM_INFO */
3767 TRANSACTION2_QFSI_REQ *pSMB = NULL;
3768 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
3769 FILE_SYSTEM_ATTRIBUTE_INFO *response_data;
3771 int bytes_returned = 0;
3772 __u16 params, byte_count;
3774 cFYI(1, ("In QFSAttributeInfo"));
3776 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3781 params = 2; /* level */
3782 pSMB->TotalDataCount = 0;
3783 pSMB->MaxParameterCount = cpu_to_le16(2);
3784 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
3785 pSMB->MaxSetupCount = 0;
3789 pSMB->Reserved2 = 0;
3790 byte_count = params + 1 /* pad */ ;
3791 pSMB->TotalParameterCount = cpu_to_le16(params);
3792 pSMB->ParameterCount = pSMB->TotalParameterCount;
3793 pSMB->ParameterOffset = cpu_to_le16(offsetof(
3794 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
3795 pSMB->DataCount = 0;
3796 pSMB->DataOffset = 0;
3797 pSMB->SetupCount = 1;
3798 pSMB->Reserved3 = 0;
3799 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
3800 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_ATTRIBUTE_INFO);
3801 pSMB->hdr.smb_buf_length += byte_count;
3802 pSMB->ByteCount = cpu_to_le16(byte_count);
3804 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3805 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3807 cERROR(1, ("Send error in QFSAttributeInfo = %d", rc));
3808 } else { /* decode response */
3809 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3811 if (rc || (pSMBr->ByteCount < 13)) { /* BB also check enough bytes returned */
3812 rc = -EIO; /* bad smb */
3814 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3816 (FILE_SYSTEM_ATTRIBUTE_INFO
3817 *) (((char *) &pSMBr->hdr.Protocol) +
3819 memcpy(&tcon->fsAttrInfo, response_data,
3820 sizeof (FILE_SYSTEM_ATTRIBUTE_INFO));
3823 cifs_buf_release(pSMB);
3826 goto QFSAttributeRetry;
3832 CIFSSMBQFSDeviceInfo(const int xid, struct cifsTconInfo *tcon)
3834 /* level 0x104 SMB_QUERY_FILE_SYSTEM_INFO */
3835 TRANSACTION2_QFSI_REQ *pSMB = NULL;
3836 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
3837 FILE_SYSTEM_DEVICE_INFO *response_data;
3839 int bytes_returned = 0;
3840 __u16 params, byte_count;
3842 cFYI(1, ("In QFSDeviceInfo"));
3844 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3849 params = 2; /* level */
3850 pSMB->TotalDataCount = 0;
3851 pSMB->MaxParameterCount = cpu_to_le16(2);
3852 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
3853 pSMB->MaxSetupCount = 0;
3857 pSMB->Reserved2 = 0;
3858 byte_count = params + 1 /* pad */ ;
3859 pSMB->TotalParameterCount = cpu_to_le16(params);
3860 pSMB->ParameterCount = pSMB->TotalParameterCount;
3861 pSMB->ParameterOffset = cpu_to_le16(offsetof(
3862 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
3864 pSMB->DataCount = 0;
3865 pSMB->DataOffset = 0;
3866 pSMB->SetupCount = 1;
3867 pSMB->Reserved3 = 0;
3868 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
3869 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_DEVICE_INFO);
3870 pSMB->hdr.smb_buf_length += byte_count;
3871 pSMB->ByteCount = cpu_to_le16(byte_count);
3873 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3874 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3876 cFYI(1, ("Send error in QFSDeviceInfo = %d", rc));
3877 } else { /* decode response */
3878 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3880 if (rc || (pSMBr->ByteCount < sizeof (FILE_SYSTEM_DEVICE_INFO)))
3881 rc = -EIO; /* bad smb */
3883 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3885 (FILE_SYSTEM_DEVICE_INFO *)
3886 (((char *) &pSMBr->hdr.Protocol) +
3888 memcpy(&tcon->fsDevInfo, response_data,
3889 sizeof (FILE_SYSTEM_DEVICE_INFO));
3892 cifs_buf_release(pSMB);
3895 goto QFSDeviceRetry;
3901 CIFSSMBQFSUnixInfo(const int xid, struct cifsTconInfo *tcon)
3903 /* level 0x200 SMB_QUERY_CIFS_UNIX_INFO */
3904 TRANSACTION2_QFSI_REQ *pSMB = NULL;
3905 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
3906 FILE_SYSTEM_UNIX_INFO *response_data;
3908 int bytes_returned = 0;
3909 __u16 params, byte_count;
3911 cFYI(1, ("In QFSUnixInfo"));
3913 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3918 params = 2; /* level */
3919 pSMB->TotalDataCount = 0;
3920 pSMB->DataCount = 0;
3921 pSMB->DataOffset = 0;
3922 pSMB->MaxParameterCount = cpu_to_le16(2);
3923 pSMB->MaxDataCount = cpu_to_le16(100); /* BB find exact max SMB PDU from sess structure BB */
3924 pSMB->MaxSetupCount = 0;
3928 pSMB->Reserved2 = 0;
3929 byte_count = params + 1 /* pad */ ;
3930 pSMB->ParameterCount = cpu_to_le16(params);
3931 pSMB->TotalParameterCount = pSMB->ParameterCount;
3932 pSMB->ParameterOffset = cpu_to_le16(offsetof(struct
3933 smb_com_transaction2_qfsi_req, InformationLevel) - 4);
3934 pSMB->SetupCount = 1;
3935 pSMB->Reserved3 = 0;
3936 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
3937 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_CIFS_UNIX_INFO);
3938 pSMB->hdr.smb_buf_length += byte_count;
3939 pSMB->ByteCount = cpu_to_le16(byte_count);
3941 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3942 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3944 cERROR(1, ("Send error in QFSUnixInfo = %d", rc));
3945 } else { /* decode response */
3946 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3948 if (rc || (pSMBr->ByteCount < 13)) {
3949 rc = -EIO; /* bad smb */
3951 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3953 (FILE_SYSTEM_UNIX_INFO
3954 *) (((char *) &pSMBr->hdr.Protocol) +
3956 memcpy(&tcon->fsUnixInfo, response_data,
3957 sizeof (FILE_SYSTEM_UNIX_INFO));
3960 cifs_buf_release(pSMB);
3970 CIFSSMBSetFSUnixInfo(const int xid, struct cifsTconInfo *tcon, __u64 cap)
3972 /* level 0x200 SMB_SET_CIFS_UNIX_INFO */
3973 TRANSACTION2_SETFSI_REQ *pSMB = NULL;
3974 TRANSACTION2_SETFSI_RSP *pSMBr = NULL;
3976 int bytes_returned = 0;
3977 __u16 params, param_offset, offset, byte_count;
3979 cFYI(1, ("In SETFSUnixInfo"));
3981 /* BB switch to small buf init to save memory */
3982 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3987 params = 4; /* 2 bytes zero followed by info level. */
3988 pSMB->MaxSetupCount = 0;
3992 pSMB->Reserved2 = 0;
3993 param_offset = offsetof(struct smb_com_transaction2_setfsi_req, FileNum) - 4;
3994 offset = param_offset + params;
3996 pSMB->MaxParameterCount = cpu_to_le16(4);
3997 pSMB->MaxDataCount = cpu_to_le16(100); /* BB find exact max SMB PDU from sess structure BB */
3998 pSMB->SetupCount = 1;
3999 pSMB->Reserved3 = 0;
4000 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FS_INFORMATION);
4001 byte_count = 1 /* pad */ + params + 12;
4003 pSMB->DataCount = cpu_to_le16(12);
4004 pSMB->ParameterCount = cpu_to_le16(params);
4005 pSMB->TotalDataCount = pSMB->DataCount;
4006 pSMB->TotalParameterCount = pSMB->ParameterCount;
4007 pSMB->ParameterOffset = cpu_to_le16(param_offset);
4008 pSMB->DataOffset = cpu_to_le16(offset);
4012 pSMB->InformationLevel = cpu_to_le16(SMB_SET_CIFS_UNIX_INFO);
4015 pSMB->ClientUnixMajor = cpu_to_le16(CIFS_UNIX_MAJOR_VERSION);
4016 pSMB->ClientUnixMinor = cpu_to_le16(CIFS_UNIX_MINOR_VERSION);
4017 pSMB->ClientUnixCap = cpu_to_le64(cap);
4019 pSMB->hdr.smb_buf_length += byte_count;
4020 pSMB->ByteCount = cpu_to_le16(byte_count);
4022 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4023 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4025 cERROR(1, ("Send error in SETFSUnixInfo = %d", rc));
4026 } else { /* decode response */
4027 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4029 rc = -EIO; /* bad smb */
4032 cifs_buf_release(pSMB);
4035 goto SETFSUnixRetry;
4043 CIFSSMBQFSPosixInfo(const int xid, struct cifsTconInfo *tcon,
4044 struct kstatfs *FSData)
4046 /* level 0x201 SMB_QUERY_CIFS_POSIX_INFO */
4047 TRANSACTION2_QFSI_REQ *pSMB = NULL;
4048 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4049 FILE_SYSTEM_POSIX_INFO *response_data;
4051 int bytes_returned = 0;
4052 __u16 params, byte_count;
4054 cFYI(1, ("In QFSPosixInfo"));
4056 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4061 params = 2; /* level */
4062 pSMB->TotalDataCount = 0;
4063 pSMB->DataCount = 0;
4064 pSMB->DataOffset = 0;
4065 pSMB->MaxParameterCount = cpu_to_le16(2);
4066 pSMB->MaxDataCount = cpu_to_le16(100); /* BB find exact max SMB PDU from sess structure BB */
4067 pSMB->MaxSetupCount = 0;
4071 pSMB->Reserved2 = 0;
4072 byte_count = params + 1 /* pad */ ;
4073 pSMB->ParameterCount = cpu_to_le16(params);
4074 pSMB->TotalParameterCount = pSMB->ParameterCount;
4075 pSMB->ParameterOffset = cpu_to_le16(offsetof(struct
4076 smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4077 pSMB->SetupCount = 1;
4078 pSMB->Reserved3 = 0;
4079 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4080 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_POSIX_FS_INFO);
4081 pSMB->hdr.smb_buf_length += byte_count;
4082 pSMB->ByteCount = cpu_to_le16(byte_count);
4084 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4085 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4087 cFYI(1, ("Send error in QFSUnixInfo = %d", rc));
4088 } else { /* decode response */
4089 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4091 if (rc || (pSMBr->ByteCount < 13)) {
4092 rc = -EIO; /* bad smb */
4094 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4096 (FILE_SYSTEM_POSIX_INFO
4097 *) (((char *) &pSMBr->hdr.Protocol) +
4100 le32_to_cpu(response_data->BlockSize);
4102 le64_to_cpu(response_data->TotalBlocks);
4104 le64_to_cpu(response_data->BlocksAvail);
4105 if(response_data->UserBlocksAvail == cpu_to_le64(-1)) {
4106 FSData->f_bavail = FSData->f_bfree;
4109 le64_to_cpu(response_data->UserBlocksAvail);
4111 if(response_data->TotalFileNodes != cpu_to_le64(-1))
4113 le64_to_cpu(response_data->TotalFileNodes);
4114 if(response_data->FreeFileNodes != cpu_to_le64(-1))
4116 le64_to_cpu(response_data->FreeFileNodes);
4119 cifs_buf_release(pSMB);
4128 /* We can not use write of zero bytes trick to
4129 set file size due to need for large file support. Also note that
4130 this SetPathInfo is preferred to SetFileInfo based method in next
4131 routine which is only needed to work around a sharing violation bug
4132 in Samba which this routine can run into */
4135 CIFSSMBSetEOF(const int xid, struct cifsTconInfo *tcon, const char *fileName,
4136 __u64 size, int SetAllocation,
4137 const struct nls_table *nls_codepage, int remap)
4139 struct smb_com_transaction2_spi_req *pSMB = NULL;
4140 struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
4141 struct file_end_of_file_info *parm_data;
4144 int bytes_returned = 0;
4145 __u16 params, byte_count, data_count, param_offset, offset;
4147 cFYI(1, ("In SetEOF"));
4149 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4154 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4156 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
4157 PATH_MAX, nls_codepage, remap);
4158 name_len++; /* trailing null */
4160 } else { /* BB improve the check for buffer overruns BB */
4161 name_len = strnlen(fileName, PATH_MAX);
4162 name_len++; /* trailing null */
4163 strncpy(pSMB->FileName, fileName, name_len);
4165 params = 6 + name_len;
4166 data_count = sizeof (struct file_end_of_file_info);
4167 pSMB->MaxParameterCount = cpu_to_le16(2);
4168 pSMB->MaxDataCount = cpu_to_le16(4100);
4169 pSMB->MaxSetupCount = 0;
4173 pSMB->Reserved2 = 0;
4174 param_offset = offsetof(struct smb_com_transaction2_spi_req,
4175 InformationLevel) - 4;
4176 offset = param_offset + params;
4178 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
4179 pSMB->InformationLevel =
4180 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2);
4182 pSMB->InformationLevel =
4183 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO);
4184 } else /* Set File Size */ {
4185 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
4186 pSMB->InformationLevel =
4187 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO2);
4189 pSMB->InformationLevel =
4190 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO);
4194 (struct file_end_of_file_info *) (((char *) &pSMB->hdr.Protocol) +
4196 pSMB->ParameterOffset = cpu_to_le16(param_offset);
4197 pSMB->DataOffset = cpu_to_le16(offset);
4198 pSMB->SetupCount = 1;
4199 pSMB->Reserved3 = 0;
4200 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
4201 byte_count = 3 /* pad */ + params + data_count;
4202 pSMB->DataCount = cpu_to_le16(data_count);
4203 pSMB->TotalDataCount = pSMB->DataCount;
4204 pSMB->ParameterCount = cpu_to_le16(params);
4205 pSMB->TotalParameterCount = pSMB->ParameterCount;
4206 pSMB->Reserved4 = 0;
4207 pSMB->hdr.smb_buf_length += byte_count;
4208 parm_data->FileSize = cpu_to_le64(size);
4209 pSMB->ByteCount = cpu_to_le16(byte_count);
4210 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4211 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4213 cFYI(1, ("SetPathInfo (file size) returned %d", rc));
4216 cifs_buf_release(pSMB);
4225 CIFSSMBSetFileSize(const int xid, struct cifsTconInfo *tcon, __u64 size,
4226 __u16 fid, __u32 pid_of_opener, int SetAllocation)
4228 struct smb_com_transaction2_sfi_req *pSMB = NULL;
4229 struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
4231 struct file_end_of_file_info *parm_data;
4233 int bytes_returned = 0;
4234 __u16 params, param_offset, offset, byte_count, count;
4236 cFYI(1, ("SetFileSize (via SetFileInfo) %lld",
4238 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
4243 pSMBr = (struct smb_com_transaction2_sfi_rsp *)pSMB;
4245 pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
4246 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));
4249 pSMB->MaxSetupCount = 0;
4253 pSMB->Reserved2 = 0;
4254 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
4255 offset = param_offset + params;
4257 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
4259 count = sizeof(struct file_end_of_file_info);
4260 pSMB->MaxParameterCount = cpu_to_le16(2);
4261 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB PDU from sess */
4262 pSMB->SetupCount = 1;
4263 pSMB->Reserved3 = 0;
4264 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
4265 byte_count = 3 /* pad */ + params + count;
4266 pSMB->DataCount = cpu_to_le16(count);
4267 pSMB->ParameterCount = cpu_to_le16(params);
4268 pSMB->TotalDataCount = pSMB->DataCount;
4269 pSMB->TotalParameterCount = pSMB->ParameterCount;
4270 pSMB->ParameterOffset = cpu_to_le16(param_offset);
4272 (struct file_end_of_file_info *) (((char *) &pSMB->hdr.Protocol) +
4274 pSMB->DataOffset = cpu_to_le16(offset);
4275 parm_data->FileSize = cpu_to_le64(size);
4278 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
4279 pSMB->InformationLevel =
4280 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2);
4282 pSMB->InformationLevel =
4283 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO);
4284 } else /* Set File Size */ {
4285 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
4286 pSMB->InformationLevel =
4287 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO2);
4289 pSMB->InformationLevel =
4290 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO);
4292 pSMB->Reserved4 = 0;
4293 pSMB->hdr.smb_buf_length += byte_count;
4294 pSMB->ByteCount = cpu_to_le16(byte_count);
4295 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4296 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4299 ("Send error in SetFileInfo (SetFileSize) = %d",
4304 cifs_small_buf_release(pSMB);
4306 /* Note: On -EAGAIN error only caller can retry on handle based calls
4307 since file handle passed in no longer valid */
4312 /* Some legacy servers such as NT4 require that the file times be set on
4313 an open handle, rather than by pathname - this is awkward due to
4314 potential access conflicts on the open, but it is unavoidable for these
4315 old servers since the only other choice is to go from 100 nanosecond DCE
4316 time and resort to the original setpathinfo level which takes the ancient
4317 DOS time format with 2 second granularity */
4319 CIFSSMBSetFileTimes(const int xid, struct cifsTconInfo *tcon, const FILE_BASIC_INFO * data,
4322 struct smb_com_transaction2_sfi_req *pSMB = NULL;
4323 struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
4326 int bytes_returned = 0;
4327 __u16 params, param_offset, offset, byte_count, count;
4329 cFYI(1, ("Set Times (via SetFileInfo)"));
4330 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
4335 pSMBr = (struct smb_com_transaction2_sfi_rsp *)pSMB;
4337 /* At this point there is no need to override the current pid
4338 with the pid of the opener, but that could change if we someday
4339 use an existing handle (rather than opening one on the fly) */
4340 /* pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
4341 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));*/
4344 pSMB->MaxSetupCount = 0;
4348 pSMB->Reserved2 = 0;
4349 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
4350 offset = param_offset + params;
4352 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
4354 count = sizeof (FILE_BASIC_INFO);
4355 pSMB->MaxParameterCount = cpu_to_le16(2);
4356 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB PDU from sess */
4357 pSMB->SetupCount = 1;
4358 pSMB->Reserved3 = 0;
4359 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
4360 byte_count = 3 /* pad */ + params + count;
4361 pSMB->DataCount = cpu_to_le16(count);
4362 pSMB->ParameterCount = cpu_to_le16(params);
4363 pSMB->TotalDataCount = pSMB->DataCount;
4364 pSMB->TotalParameterCount = pSMB->ParameterCount;
4365 pSMB->ParameterOffset = cpu_to_le16(param_offset);
4366 pSMB->DataOffset = cpu_to_le16(offset);
4368 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
4369 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO2);
4371 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO);
4372 pSMB->Reserved4 = 0;
4373 pSMB->hdr.smb_buf_length += byte_count;
4374 pSMB->ByteCount = cpu_to_le16(byte_count);
4375 memcpy(data_offset,data,sizeof(FILE_BASIC_INFO));
4376 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4377 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4379 cFYI(1,("Send error in Set Time (SetFileInfo) = %d",rc));
4382 cifs_small_buf_release(pSMB);
4384 /* Note: On -EAGAIN error only caller can retry on handle based calls
4385 since file handle passed in no longer valid */
4392 CIFSSMBSetTimes(const int xid, struct cifsTconInfo *tcon, const char *fileName,
4393 const FILE_BASIC_INFO * data,
4394 const struct nls_table *nls_codepage, int remap)
4396 TRANSACTION2_SPI_REQ *pSMB = NULL;
4397 TRANSACTION2_SPI_RSP *pSMBr = NULL;
4400 int bytes_returned = 0;
4402 __u16 params, param_offset, offset, byte_count, count;
4404 cFYI(1, ("In SetTimes"));
4407 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4412 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4414 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
4415 PATH_MAX, nls_codepage, remap);
4416 name_len++; /* trailing null */
4418 } else { /* BB improve the check for buffer overruns BB */
4419 name_len = strnlen(fileName, PATH_MAX);
4420 name_len++; /* trailing null */
4421 strncpy(pSMB->FileName, fileName, name_len);
4424 params = 6 + name_len;
4425 count = sizeof (FILE_BASIC_INFO);
4426 pSMB->MaxParameterCount = cpu_to_le16(2);
4427 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
4428 pSMB->MaxSetupCount = 0;
4432 pSMB->Reserved2 = 0;
4433 param_offset = offsetof(struct smb_com_transaction2_spi_req,
4434 InformationLevel) - 4;
4435 offset = param_offset + params;
4436 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
4437 pSMB->ParameterOffset = cpu_to_le16(param_offset);
4438 pSMB->DataOffset = cpu_to_le16(offset);
4439 pSMB->SetupCount = 1;
4440 pSMB->Reserved3 = 0;
4441 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
4442 byte_count = 3 /* pad */ + params + count;
4444 pSMB->DataCount = cpu_to_le16(count);
4445 pSMB->ParameterCount = cpu_to_le16(params);
4446 pSMB->TotalDataCount = pSMB->DataCount;
4447 pSMB->TotalParameterCount = pSMB->ParameterCount;
4448 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
4449 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO2);
4451 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO);
4452 pSMB->Reserved4 = 0;
4453 pSMB->hdr.smb_buf_length += byte_count;
4454 memcpy(data_offset, data, sizeof (FILE_BASIC_INFO));
4455 pSMB->ByteCount = cpu_to_le16(byte_count);
4456 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4457 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4459 cFYI(1, ("SetPathInfo (times) returned %d", rc));
4462 cifs_buf_release(pSMB);
4470 /* Can not be used to set time stamps yet (due to old DOS time format) */
4471 /* Can be used to set attributes */
4472 #if 0 /* Possibly not needed - since it turns out that strangely NT4 has a bug
4473 handling it anyway and NT4 was what we thought it would be needed for
4474 Do not delete it until we prove whether needed for Win9x though */
4476 CIFSSMBSetAttrLegacy(int xid, struct cifsTconInfo *tcon, char *fileName,
4477 __u16 dos_attrs, const struct nls_table *nls_codepage)
4479 SETATTR_REQ *pSMB = NULL;
4480 SETATTR_RSP *pSMBr = NULL;
4485 cFYI(1, ("In SetAttrLegacy"));
4488 rc = smb_init(SMB_COM_SETATTR, 8, tcon, (void **) &pSMB,
4493 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4495 ConvertToUCS((__le16 *) pSMB->fileName, fileName,
4496 PATH_MAX, nls_codepage);
4497 name_len++; /* trailing null */
4499 } else { /* BB improve the check for buffer overruns BB */
4500 name_len = strnlen(fileName, PATH_MAX);
4501 name_len++; /* trailing null */
4502 strncpy(pSMB->fileName, fileName, name_len);
4504 pSMB->attr = cpu_to_le16(dos_attrs);
4505 pSMB->BufferFormat = 0x04;
4506 pSMB->hdr.smb_buf_length += name_len + 1;
4507 pSMB->ByteCount = cpu_to_le16(name_len + 1);
4508 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4509 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4511 cFYI(1, ("Error in LegacySetAttr = %d", rc));
4514 cifs_buf_release(pSMB);
4517 goto SetAttrLgcyRetry;
4521 #endif /* temporarily unneeded SetAttr legacy function */
4524 CIFSSMBUnixSetPerms(const int xid, struct cifsTconInfo *tcon,
4525 char *fileName, __u64 mode, __u64 uid, __u64 gid,
4526 dev_t device, const struct nls_table *nls_codepage,
4529 TRANSACTION2_SPI_REQ *pSMB = NULL;
4530 TRANSACTION2_SPI_RSP *pSMBr = NULL;
4533 int bytes_returned = 0;
4534 FILE_UNIX_BASIC_INFO *data_offset;
4535 __u16 params, param_offset, offset, count, byte_count;
4537 cFYI(1, ("In SetUID/GID/Mode"));
4539 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4544 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4546 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
4547 PATH_MAX, nls_codepage, remap);
4548 name_len++; /* trailing null */
4550 } else { /* BB improve the check for buffer overruns BB */
4551 name_len = strnlen(fileName, PATH_MAX);
4552 name_len++; /* trailing null */
4553 strncpy(pSMB->FileName, fileName, name_len);
4556 params = 6 + name_len;
4557 count = sizeof (FILE_UNIX_BASIC_INFO);
4558 pSMB->MaxParameterCount = cpu_to_le16(2);
4559 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
4560 pSMB->MaxSetupCount = 0;
4564 pSMB->Reserved2 = 0;
4565 param_offset = offsetof(struct smb_com_transaction2_spi_req,
4566 InformationLevel) - 4;
4567 offset = param_offset + params;
4569 (FILE_UNIX_BASIC_INFO *) ((char *) &pSMB->hdr.Protocol +
4571 memset(data_offset, 0, count);
4572 pSMB->DataOffset = cpu_to_le16(offset);
4573 pSMB->ParameterOffset = cpu_to_le16(param_offset);
4574 pSMB->SetupCount = 1;
4575 pSMB->Reserved3 = 0;
4576 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
4577 byte_count = 3 /* pad */ + params + count;
4578 pSMB->ParameterCount = cpu_to_le16(params);
4579 pSMB->DataCount = cpu_to_le16(count);
4580 pSMB->TotalParameterCount = pSMB->ParameterCount;
4581 pSMB->TotalDataCount = pSMB->DataCount;
4582 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_BASIC);
4583 pSMB->Reserved4 = 0;
4584 pSMB->hdr.smb_buf_length += byte_count;
4585 data_offset->Uid = cpu_to_le64(uid);
4586 data_offset->Gid = cpu_to_le64(gid);
4587 /* better to leave device as zero when it is */
4588 data_offset->DevMajor = cpu_to_le64(MAJOR(device));
4589 data_offset->DevMinor = cpu_to_le64(MINOR(device));
4590 data_offset->Permissions = cpu_to_le64(mode);
4593 data_offset->Type = cpu_to_le32(UNIX_FILE);
4594 else if(S_ISDIR(mode))
4595 data_offset->Type = cpu_to_le32(UNIX_DIR);
4596 else if(S_ISLNK(mode))
4597 data_offset->Type = cpu_to_le32(UNIX_SYMLINK);
4598 else if(S_ISCHR(mode))
4599 data_offset->Type = cpu_to_le32(UNIX_CHARDEV);
4600 else if(S_ISBLK(mode))
4601 data_offset->Type = cpu_to_le32(UNIX_BLOCKDEV);
4602 else if(S_ISFIFO(mode))
4603 data_offset->Type = cpu_to_le32(UNIX_FIFO);
4604 else if(S_ISSOCK(mode))
4605 data_offset->Type = cpu_to_le32(UNIX_SOCKET);
4608 pSMB->ByteCount = cpu_to_le16(byte_count);
4609 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4610 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4612 cFYI(1, ("SetPathInfo (perms) returned %d", rc));
4616 cifs_buf_release(pSMB);
4622 int CIFSSMBNotify(const int xid, struct cifsTconInfo *tcon,
4623 const int notify_subdirs, const __u16 netfid,
4624 __u32 filter, struct file * pfile, int multishot,
4625 const struct nls_table *nls_codepage)
4628 struct smb_com_transaction_change_notify_req * pSMB = NULL;
4629 struct smb_com_ntransaction_change_notify_rsp * pSMBr = NULL;
4630 struct dir_notify_req *dnotify_req;
4633 cFYI(1, ("In CIFSSMBNotify for file handle %d",(int)netfid));
4634 rc = smb_init(SMB_COM_NT_TRANSACT, 23, tcon, (void **) &pSMB,
4639 pSMB->TotalParameterCount = 0 ;
4640 pSMB->TotalDataCount = 0;
4641 pSMB->MaxParameterCount = cpu_to_le32(2);
4642 /* BB find exact data count max from sess structure BB */
4643 pSMB->MaxDataCount = 0; /* same in little endian or be */
4644 /* BB VERIFY verify which is correct for above BB */
4645 pSMB->MaxDataCount = cpu_to_le32((tcon->ses->server->maxBuf -
4646 MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
4648 pSMB->MaxSetupCount = 4;
4650 pSMB->ParameterOffset = 0;
4651 pSMB->DataCount = 0;
4652 pSMB->DataOffset = 0;
4653 pSMB->SetupCount = 4; /* single byte does not need le conversion */
4654 pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_NOTIFY_CHANGE);
4655 pSMB->ParameterCount = pSMB->TotalParameterCount;
4657 pSMB->WatchTree = 1; /* one byte - no le conversion needed */
4658 pSMB->Reserved2 = 0;
4659 pSMB->CompletionFilter = cpu_to_le32(filter);
4660 pSMB->Fid = netfid; /* file handle always le */
4661 pSMB->ByteCount = 0;
4663 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4664 (struct smb_hdr *) pSMBr, &bytes_returned, -1);
4666 cFYI(1, ("Error in Notify = %d", rc));
4668 /* Add file to outstanding requests */
4669 /* BB change to kmem cache alloc */
4670 dnotify_req = (struct dir_notify_req *) kmalloc(
4671 sizeof(struct dir_notify_req),
4674 dnotify_req->Pid = pSMB->hdr.Pid;
4675 dnotify_req->PidHigh = pSMB->hdr.PidHigh;
4676 dnotify_req->Mid = pSMB->hdr.Mid;
4677 dnotify_req->Tid = pSMB->hdr.Tid;
4678 dnotify_req->Uid = pSMB->hdr.Uid;
4679 dnotify_req->netfid = netfid;
4680 dnotify_req->pfile = pfile;
4681 dnotify_req->filter = filter;
4682 dnotify_req->multishot = multishot;
4683 spin_lock(&GlobalMid_Lock);
4684 list_add_tail(&dnotify_req->lhead,
4685 &GlobalDnotifyReqList);
4686 spin_unlock(&GlobalMid_Lock);
4690 cifs_buf_release(pSMB);
4693 #ifdef CONFIG_CIFS_XATTR
4695 CIFSSMBQAllEAs(const int xid, struct cifsTconInfo *tcon,
4696 const unsigned char *searchName,
4697 char * EAData, size_t buf_size,
4698 const struct nls_table *nls_codepage, int remap)
4700 /* BB assumes one setup word */
4701 TRANSACTION2_QPI_REQ *pSMB = NULL;
4702 TRANSACTION2_QPI_RSP *pSMBr = NULL;
4706 struct fea * temp_fea;
4708 __u16 params, byte_count;
4710 cFYI(1, ("In Query All EAs path %s", searchName));
4712 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4717 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4719 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
4720 PATH_MAX, nls_codepage, remap);
4721 name_len++; /* trailing null */
4723 } else { /* BB improve the check for buffer overruns BB */
4724 name_len = strnlen(searchName, PATH_MAX);
4725 name_len++; /* trailing null */
4726 strncpy(pSMB->FileName, searchName, name_len);
4729 params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */ ;
4730 pSMB->TotalDataCount = 0;
4731 pSMB->MaxParameterCount = cpu_to_le16(2);
4732 pSMB->MaxDataCount = cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
4733 pSMB->MaxSetupCount = 0;
4737 pSMB->Reserved2 = 0;
4738 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4739 struct smb_com_transaction2_qpi_req ,InformationLevel) - 4);
4740 pSMB->DataCount = 0;
4741 pSMB->DataOffset = 0;
4742 pSMB->SetupCount = 1;
4743 pSMB->Reserved3 = 0;
4744 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
4745 byte_count = params + 1 /* pad */ ;
4746 pSMB->TotalParameterCount = cpu_to_le16(params);
4747 pSMB->ParameterCount = pSMB->TotalParameterCount;
4748 pSMB->InformationLevel = cpu_to_le16(SMB_INFO_QUERY_ALL_EAS);
4749 pSMB->Reserved4 = 0;
4750 pSMB->hdr.smb_buf_length += byte_count;
4751 pSMB->ByteCount = cpu_to_le16(byte_count);
4753 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4754 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4756 cFYI(1, ("Send error in QueryAllEAs = %d", rc));
4757 } else { /* decode response */
4758 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4760 /* BB also check enough total bytes returned */
4761 /* BB we need to improve the validity checking
4762 of these trans2 responses */
4763 if (rc || (pSMBr->ByteCount < 4))
4764 rc = -EIO; /* bad smb */
4765 /* else if (pFindData){
4766 memcpy((char *) pFindData,
4767 (char *) &pSMBr->hdr.Protocol +
4770 /* check that length of list is not more than bcc */
4771 /* check that each entry does not go beyond length
4773 /* check that each element of each entry does not
4774 go beyond end of list */
4775 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4776 struct fealist * ea_response_data;
4778 /* validate_trans2_offsets() */
4779 /* BB to check if(start of smb + data_offset > &bcc+ bcc)*/
4780 ea_response_data = (struct fealist *)
4781 (((char *) &pSMBr->hdr.Protocol) +
4783 name_len = le32_to_cpu(ea_response_data->list_len);
4784 cFYI(1,("ea length %d", name_len));
4786 /* returned EA size zeroed at top of function */
4787 cFYI(1,("empty EA list returned from server"));
4789 /* account for ea list len */
4791 temp_fea = ea_response_data->list;
4792 temp_ptr = (char *)temp_fea;
4793 while(name_len > 0) {
4797 rc += temp_fea->name_len;
4798 /* account for prefix user. and trailing null */
4800 if(rc<(int)buf_size) {
4801 memcpy(EAData,"user.",5);
4803 memcpy(EAData,temp_ptr,temp_fea->name_len);
4804 EAData+=temp_fea->name_len;
4805 /* null terminate name */
4807 EAData = EAData + 1;
4808 } else if(buf_size == 0) {
4809 /* skip copy - calc size only */
4811 /* stop before overrun buffer */
4815 name_len -= temp_fea->name_len;
4816 temp_ptr += temp_fea->name_len;
4817 /* account for trailing null */
4820 value_len = le16_to_cpu(temp_fea->value_len);
4821 name_len -= value_len;
4822 temp_ptr += value_len;
4823 /* BB check that temp_ptr is still within smb BB*/
4824 /* no trailing null to account for in value len */
4825 /* go on to next EA */
4826 temp_fea = (struct fea *)temp_ptr;
4832 cifs_buf_release(pSMB);
4839 ssize_t CIFSSMBQueryEA(const int xid,struct cifsTconInfo * tcon,
4840 const unsigned char * searchName,const unsigned char * ea_name,
4841 unsigned char * ea_value, size_t buf_size,
4842 const struct nls_table *nls_codepage, int remap)
4844 TRANSACTION2_QPI_REQ *pSMB = NULL;
4845 TRANSACTION2_QPI_RSP *pSMBr = NULL;
4849 struct fea * temp_fea;
4851 __u16 params, byte_count;
4853 cFYI(1, ("In Query EA path %s", searchName));
4855 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4860 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4862 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
4863 PATH_MAX, nls_codepage, remap);
4864 name_len++; /* trailing null */
4866 } else { /* BB improve the check for buffer overruns BB */
4867 name_len = strnlen(searchName, PATH_MAX);
4868 name_len++; /* trailing null */
4869 strncpy(pSMB->FileName, searchName, name_len);
4872 params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */ ;
4873 pSMB->TotalDataCount = 0;
4874 pSMB->MaxParameterCount = cpu_to_le16(2);
4875 pSMB->MaxDataCount = cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
4876 pSMB->MaxSetupCount = 0;
4880 pSMB->Reserved2 = 0;
4881 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4882 struct smb_com_transaction2_qpi_req ,InformationLevel) - 4);
4883 pSMB->DataCount = 0;
4884 pSMB->DataOffset = 0;
4885 pSMB->SetupCount = 1;
4886 pSMB->Reserved3 = 0;
4887 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
4888 byte_count = params + 1 /* pad */ ;
4889 pSMB->TotalParameterCount = cpu_to_le16(params);
4890 pSMB->ParameterCount = pSMB->TotalParameterCount;
4891 pSMB->InformationLevel = cpu_to_le16(SMB_INFO_QUERY_ALL_EAS);
4892 pSMB->Reserved4 = 0;
4893 pSMB->hdr.smb_buf_length += byte_count;
4894 pSMB->ByteCount = cpu_to_le16(byte_count);
4896 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4897 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4899 cFYI(1, ("Send error in Query EA = %d", rc));
4900 } else { /* decode response */
4901 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4903 /* BB also check enough total bytes returned */
4904 /* BB we need to improve the validity checking
4905 of these trans2 responses */
4906 if (rc || (pSMBr->ByteCount < 4))
4907 rc = -EIO; /* bad smb */
4908 /* else if (pFindData){
4909 memcpy((char *) pFindData,
4910 (char *) &pSMBr->hdr.Protocol +
4913 /* check that length of list is not more than bcc */
4914 /* check that each entry does not go beyond length
4916 /* check that each element of each entry does not
4917 go beyond end of list */
4918 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4919 struct fealist * ea_response_data;
4921 /* validate_trans2_offsets() */
4922 /* BB to check if(start of smb + data_offset > &bcc+ bcc)*/
4923 ea_response_data = (struct fealist *)
4924 (((char *) &pSMBr->hdr.Protocol) +
4926 name_len = le32_to_cpu(ea_response_data->list_len);
4927 cFYI(1,("ea length %d", name_len));
4929 /* returned EA size zeroed at top of function */
4930 cFYI(1,("empty EA list returned from server"));
4932 /* account for ea list len */
4934 temp_fea = ea_response_data->list;
4935 temp_ptr = (char *)temp_fea;
4936 /* loop through checking if we have a matching
4937 name and then return the associated value */
4938 while(name_len > 0) {
4942 value_len = le16_to_cpu(temp_fea->value_len);
4943 /* BB validate that value_len falls within SMB,
4944 even though maximum for name_len is 255 */
4945 if(memcmp(temp_fea->name,ea_name,
4946 temp_fea->name_len) == 0) {
4949 /* account for prefix user. and trailing null */
4950 if(rc<=(int)buf_size) {
4952 temp_fea->name+temp_fea->name_len+1,
4954 /* ea values, unlike ea names,
4955 are not null terminated */
4956 } else if(buf_size == 0) {
4957 /* skip copy - calc size only */
4959 /* stop before overrun buffer */
4964 name_len -= temp_fea->name_len;
4965 temp_ptr += temp_fea->name_len;
4966 /* account for trailing null */
4969 name_len -= value_len;
4970 temp_ptr += value_len;
4971 /* no trailing null to account for in value len */
4972 /* go on to next EA */
4973 temp_fea = (struct fea *)temp_ptr;
4979 cifs_buf_release(pSMB);
4987 CIFSSMBSetEA(const int xid, struct cifsTconInfo *tcon, const char *fileName,
4988 const char * ea_name, const void * ea_value,
4989 const __u16 ea_value_len, const struct nls_table *nls_codepage,
4992 struct smb_com_transaction2_spi_req *pSMB = NULL;
4993 struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
4994 struct fealist *parm_data;
4997 int bytes_returned = 0;
4998 __u16 params, param_offset, byte_count, offset, count;
5000 cFYI(1, ("In SetEA"));
5002 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5007 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5009 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
5010 PATH_MAX, nls_codepage, remap);
5011 name_len++; /* trailing null */
5013 } else { /* BB improve the check for buffer overruns BB */
5014 name_len = strnlen(fileName, PATH_MAX);
5015 name_len++; /* trailing null */
5016 strncpy(pSMB->FileName, fileName, name_len);
5019 params = 6 + name_len;
5021 /* done calculating parms using name_len of file name,
5022 now use name_len to calculate length of ea name
5023 we are going to create in the inode xattrs */
5027 name_len = strnlen(ea_name,255);
5029 count = sizeof(*parm_data) + ea_value_len + name_len + 1;
5030 pSMB->MaxParameterCount = cpu_to_le16(2);
5031 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB size from sess */
5032 pSMB->MaxSetupCount = 0;
5036 pSMB->Reserved2 = 0;
5037 param_offset = offsetof(struct smb_com_transaction2_spi_req,
5038 InformationLevel) - 4;
5039 offset = param_offset + params;
5040 pSMB->InformationLevel =
5041 cpu_to_le16(SMB_SET_FILE_EA);
5044 (struct fealist *) (((char *) &pSMB->hdr.Protocol) +
5046 pSMB->ParameterOffset = cpu_to_le16(param_offset);
5047 pSMB->DataOffset = cpu_to_le16(offset);
5048 pSMB->SetupCount = 1;
5049 pSMB->Reserved3 = 0;
5050 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
5051 byte_count = 3 /* pad */ + params + count;
5052 pSMB->DataCount = cpu_to_le16(count);
5053 parm_data->list_len = cpu_to_le32(count);
5054 parm_data->list[0].EA_flags = 0;
5055 /* we checked above that name len is less than 255 */
5056 parm_data->list[0].name_len = (__u8)name_len;
5057 /* EA names are always ASCII */
5059 strncpy(parm_data->list[0].name,ea_name,name_len);
5060 parm_data->list[0].name[name_len] = 0;
5061 parm_data->list[0].value_len = cpu_to_le16(ea_value_len);
5062 /* caller ensures that ea_value_len is less than 64K but
5063 we need to ensure that it fits within the smb */
5065 /*BB add length check that it would fit in negotiated SMB buffer size BB */
5066 /* if(ea_value_len > buffer_size - 512 (enough for header)) */
5068 memcpy(parm_data->list[0].name+name_len+1,ea_value,ea_value_len);
5070 pSMB->TotalDataCount = pSMB->DataCount;
5071 pSMB->ParameterCount = cpu_to_le16(params);
5072 pSMB->TotalParameterCount = pSMB->ParameterCount;
5073 pSMB->Reserved4 = 0;
5074 pSMB->hdr.smb_buf_length += byte_count;
5075 pSMB->ByteCount = cpu_to_le16(byte_count);
5076 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5077 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5079 cFYI(1, ("SetPathInfo (EA) returned %d", rc));
5082 cifs_buf_release(pSMB);