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 #ifdef CONFIG_CIFS_WEAK_PW_HASH
48 {LANMAN_PROT, "\2LM1.2X002"},
49 #endif /* weak password hashing for legacy clients */
50 {CIFS_PROT, "\2NT LM 0.12"},
51 {POSIX_PROT, "\2POSIX 2"},
59 #ifdef CONFIG_CIFS_WEAK_PW_HASH
60 {LANMAN_PROT, "\2LM1.2X002"},
61 #endif /* weak password hashing for legacy clients */
62 {CIFS_PROT, "\2NT LM 0.12"},
67 /* define the number of elements in the cifs dialect array */
68 #ifdef CONFIG_CIFS_POSIX
69 #ifdef CONFIG_CIFS_WEAK_PW_HASH
70 #define CIFS_NUM_PROT 3
72 #define CIFS_NUM_PROT 2
73 #endif /* CIFS_WEAK_PW_HASH */
75 #ifdef CONFIG_CIFS_WEAK_PW_HASH
76 #define CIFS_NUM_PROT 2
78 #define CIFS_NUM_PROT 1
79 #endif /* CONFIG_CIFS_WEAK_PW_HASH */
80 #endif /* CIFS_POSIX */
83 /* Mark as invalid, all open files on tree connections since they
84 were closed when session to server was lost */
85 static void mark_open_files_invalid(struct cifsTconInfo * pTcon)
87 struct cifsFileInfo *open_file = NULL;
88 struct list_head * tmp;
89 struct list_head * tmp1;
91 /* list all files open on tree connection and mark them invalid */
92 write_lock(&GlobalSMBSeslock);
93 list_for_each_safe(tmp, tmp1, &pTcon->openFileList) {
94 open_file = list_entry(tmp,struct cifsFileInfo, tlist);
96 open_file->invalidHandle = TRUE;
99 write_unlock(&GlobalSMBSeslock);
100 /* BB Add call to invalidate_inodes(sb) for all superblocks mounted
104 /* If the return code is zero, this function must fill in request_buf pointer */
106 small_smb_init(int smb_command, int wct, struct cifsTconInfo *tcon,
107 void **request_buf /* returned */)
111 /* SMBs NegProt, SessSetup, uLogoff do not have tcon yet so
112 check for tcp and smb session status done differently
113 for those three - in the calling routine */
115 if(tcon->tidStatus == CifsExiting) {
116 /* only tree disconnect, open, and write,
117 (and ulogoff which does not have tcon)
118 are allowed as we start force umount */
119 if((smb_command != SMB_COM_WRITE_ANDX) &&
120 (smb_command != SMB_COM_OPEN_ANDX) &&
121 (smb_command != SMB_COM_TREE_DISCONNECT)) {
122 cFYI(1,("can not send cmd %d while umounting",
127 if((tcon->ses) && (tcon->ses->status != CifsExiting) &&
128 (tcon->ses->server)){
129 struct nls_table *nls_codepage;
130 /* Give Demultiplex thread up to 10 seconds to
131 reconnect, should be greater than cifs socket
132 timeout which is 7 seconds */
133 while(tcon->ses->server->tcpStatus == CifsNeedReconnect) {
134 wait_event_interruptible_timeout(tcon->ses->server->response_q,
135 (tcon->ses->server->tcpStatus == CifsGood), 10 * HZ);
136 if(tcon->ses->server->tcpStatus == CifsNeedReconnect) {
137 /* on "soft" mounts we wait once */
138 if((tcon->retry == FALSE) ||
139 (tcon->ses->status == CifsExiting)) {
140 cFYI(1,("gave up waiting on reconnect in smb_init"));
142 } /* else "hard" mount - keep retrying
143 until process is killed or server
144 comes back on-line */
145 } else /* TCP session is reestablished now */
150 nls_codepage = load_nls_default();
151 /* need to prevent multiple threads trying to
152 simultaneously reconnect the same SMB session */
153 down(&tcon->ses->sesSem);
154 if(tcon->ses->status == CifsNeedReconnect)
155 rc = cifs_setup_session(0, tcon->ses,
157 if(!rc && (tcon->tidStatus == CifsNeedReconnect)) {
158 mark_open_files_invalid(tcon);
159 rc = CIFSTCon(0, tcon->ses, tcon->treeName, tcon
161 up(&tcon->ses->sesSem);
162 /* BB FIXME add code to check if wsize needs
163 update due to negotiated smb buffer size
166 atomic_inc(&tconInfoReconnectCount);
168 cFYI(1, ("reconnect tcon rc = %d", rc));
169 /* Removed call to reopen open files here -
170 it is safer (and faster) to reopen files
171 one at a time as needed in read and write */
173 /* Check if handle based operation so we
174 know whether we can continue or not without
175 returning to caller to reset file handle */
176 switch(smb_command) {
177 case SMB_COM_READ_ANDX:
178 case SMB_COM_WRITE_ANDX:
180 case SMB_COM_FIND_CLOSE2:
181 case SMB_COM_LOCKING_ANDX: {
182 unload_nls(nls_codepage);
187 up(&tcon->ses->sesSem);
189 unload_nls(nls_codepage);
198 *request_buf = cifs_small_buf_get();
199 if (*request_buf == NULL) {
200 /* BB should we add a retry in here if not a writepage? */
204 header_assemble((struct smb_hdr *) *request_buf, smb_command, tcon,wct);
207 cifs_stats_inc(&tcon->num_smbs_sent);
212 #ifdef CONFIG_CIFS_EXPERIMENTAL
214 small_smb_init_no_tc(const int smb_command, const int wct,
215 struct cifsSesInfo *ses, void **request_buf)
218 struct smb_hdr * buffer;
220 rc = small_smb_init(smb_command, wct, NULL, request_buf);
224 buffer = (struct smb_hdr *)*request_buf;
225 buffer->Mid = GetNextMid(ses->server);
226 if (ses->capabilities & CAP_UNICODE)
227 buffer->Flags2 |= SMBFLG2_UNICODE;
228 if (ses->capabilities & CAP_STATUS32)
229 buffer->Flags2 |= SMBFLG2_ERR_STATUS;
231 /* uid, tid can stay at zero as set in header assemble */
233 /* BB add support for turning on the signing when
234 this function is used after 1st of session setup requests */
238 #endif /* CONFIG_CIFS_EXPERIMENTAL */
240 /* If the return code is zero, this function must fill in request_buf pointer */
242 smb_init(int smb_command, int wct, struct cifsTconInfo *tcon,
243 void **request_buf /* returned */ ,
244 void **response_buf /* returned */ )
248 /* SMBs NegProt, SessSetup, uLogoff do not have tcon yet so
249 check for tcp and smb session status done differently
250 for those three - in the calling routine */
252 if(tcon->tidStatus == CifsExiting) {
253 /* only tree disconnect, open, and write,
254 (and ulogoff which does not have tcon)
255 are allowed as we start force umount */
256 if((smb_command != SMB_COM_WRITE_ANDX) &&
257 (smb_command != SMB_COM_OPEN_ANDX) &&
258 (smb_command != SMB_COM_TREE_DISCONNECT)) {
259 cFYI(1,("can not send cmd %d while umounting",
265 if((tcon->ses) && (tcon->ses->status != CifsExiting) &&
266 (tcon->ses->server)){
267 struct nls_table *nls_codepage;
268 /* Give Demultiplex thread up to 10 seconds to
269 reconnect, should be greater than cifs socket
270 timeout which is 7 seconds */
271 while(tcon->ses->server->tcpStatus == CifsNeedReconnect) {
272 wait_event_interruptible_timeout(tcon->ses->server->response_q,
273 (tcon->ses->server->tcpStatus == CifsGood), 10 * HZ);
274 if(tcon->ses->server->tcpStatus ==
276 /* on "soft" mounts we wait once */
277 if((tcon->retry == FALSE) ||
278 (tcon->ses->status == CifsExiting)) {
279 cFYI(1,("gave up waiting on reconnect in smb_init"));
281 } /* else "hard" mount - keep retrying
282 until process is killed or server
284 } else /* TCP session is reestablished now */
289 nls_codepage = load_nls_default();
290 /* need to prevent multiple threads trying to
291 simultaneously reconnect the same SMB session */
292 down(&tcon->ses->sesSem);
293 if(tcon->ses->status == CifsNeedReconnect)
294 rc = cifs_setup_session(0, tcon->ses,
296 if(!rc && (tcon->tidStatus == CifsNeedReconnect)) {
297 mark_open_files_invalid(tcon);
298 rc = CIFSTCon(0, tcon->ses, tcon->treeName,
300 up(&tcon->ses->sesSem);
301 /* BB FIXME add code to check if wsize needs
302 update due to negotiated smb buffer size
305 atomic_inc(&tconInfoReconnectCount);
307 cFYI(1, ("reconnect tcon rc = %d", rc));
308 /* Removed call to reopen open files here -
309 it is safer (and faster) to reopen files
310 one at a time as needed in read and write */
312 /* Check if handle based operation so we
313 know whether we can continue or not without
314 returning to caller to reset file handle */
315 switch(smb_command) {
316 case SMB_COM_READ_ANDX:
317 case SMB_COM_WRITE_ANDX:
319 case SMB_COM_FIND_CLOSE2:
320 case SMB_COM_LOCKING_ANDX: {
321 unload_nls(nls_codepage);
326 up(&tcon->ses->sesSem);
328 unload_nls(nls_codepage);
337 *request_buf = cifs_buf_get();
338 if (*request_buf == NULL) {
339 /* BB should we add a retry in here if not a writepage? */
342 /* Although the original thought was we needed the response buf for */
343 /* potential retries of smb operations it turns out we can determine */
344 /* from the mid flags when the request buffer can be resent without */
345 /* having to use a second distinct buffer for the response */
347 *response_buf = *request_buf;
349 header_assemble((struct smb_hdr *) *request_buf, smb_command, tcon,
353 cifs_stats_inc(&tcon->num_smbs_sent);
358 static int validate_t2(struct smb_t2_rsp * pSMB)
364 /* check for plausible wct, bcc and t2 data and parm sizes */
365 /* check for parm and data offset going beyond end of smb */
366 if(pSMB->hdr.WordCount >= 10) {
367 if((le16_to_cpu(pSMB->t2_rsp.ParameterOffset) <= 1024) &&
368 (le16_to_cpu(pSMB->t2_rsp.DataOffset) <= 1024)) {
369 /* check that bcc is at least as big as parms + data */
370 /* check that bcc is less than negotiated smb buffer */
371 total_size = le16_to_cpu(pSMB->t2_rsp.ParameterCount);
372 if(total_size < 512) {
373 total_size+=le16_to_cpu(pSMB->t2_rsp.DataCount);
374 /* BCC le converted in SendReceive */
375 pBCC = (pSMB->hdr.WordCount * 2) +
376 sizeof(struct smb_hdr) +
378 if((total_size <= (*(u16 *)pBCC)) &&
380 CIFSMaxBufSize+MAX_CIFS_HDR_SIZE)) {
387 cifs_dump_mem("Invalid transact2 SMB: ",(char *)pSMB,
388 sizeof(struct smb_t2_rsp) + 16);
392 CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses)
395 NEGOTIATE_RSP *pSMBr;
399 struct TCP_Server_Info * server;
403 server = ses->server;
408 rc = smb_init(SMB_COM_NEGOTIATE, 0, NULL /* no tcon yet */ ,
409 (void **) &pSMB, (void **) &pSMBr);
412 pSMB->hdr.Mid = GetNextMid(server);
413 pSMB->hdr.Flags2 |= SMBFLG2_UNICODE;
414 /* if (extended_security)
415 pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC;*/
418 for(i=0;i<CIFS_NUM_PROT;i++) {
419 strncpy(pSMB->DialectsArray+count, protocols[i].name, 16);
420 count += strlen(protocols[i].name) + 1;
421 /* null at end of source and target buffers anyway */
423 pSMB->hdr.smb_buf_length += count;
424 pSMB->ByteCount = cpu_to_le16(count);
426 rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB,
427 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
429 cFYI(1,("Dialect: %d", pSMBr->DialectIndex));
430 /* Check wct = 1 error case */
431 if((pSMBr->hdr.WordCount < 13)
432 || (pSMBr->DialectIndex == BAD_PROT)) {
433 /* core returns wct = 1, but we do not ask for
434 core - otherwise it just comes when dialect
435 index is -1 indicating we could not negotiate
439 #ifdef CONFIG_CIFS_WEAK_PW_HASH
440 } else if((pSMBr->hdr.WordCount == 13)
441 && (pSMBr->DialectIndex == LANMAN_PROT)) {
442 struct lanman_neg_rsp * rsp =
443 (struct lanman_neg_rsp *)pSMBr;
445 if((extended_security & CIFSSEC_MAY_LANMAN) ||
446 (extended_security & CIFSSEC_MAY_PLNTXT))
447 server->secType = LANMAN;
449 cERROR(1, ("mount failed weak security disabled"
450 " in /proc/fs/cifs/SecurityFlags"));
454 server->secMode = (__u8)le16_to_cpu(rsp->SecurityMode);
455 server->maxReq = le16_to_cpu(rsp->MaxMpxCount);
456 server->maxBuf = min((__u32)le16_to_cpu(rsp->MaxBufSize),
457 (__u32)CIFSMaxBufSize + MAX_CIFS_HDR_SIZE);
459 /* BB what do we do with raw mode? BB */
460 server->timeZone = le16_to_cpu(rsp->ServerTimeZone);
461 /* Do we have to set signing flags? no signing
462 was available LANMAN - default should be ok */
464 /* BB FIXME set default dummy capabilities since
465 they are not returned by the server in this dialect */
467 /* get server time for time conversions and add
468 code to use it and timezone since this is not UTC */
470 if (rsp->EncryptionKeyLength == CIFS_CRYPTO_KEY_SIZE) {
471 memcpy(server->cryptKey, rsp->EncryptionKey,
472 CIFS_CRYPTO_KEY_SIZE);
478 cFYI(1,("LANMAN negotiated")); /* BB removeme BB */
479 #else /* weak security disabled */
480 } else if(pSMBr->hdr.WordCount == 13)
481 cERROR(1,("mount failed, cifs module not built "
482 "with CIFS_WEAK_PW_HASH support"));
484 #endif /* WEAK_PW_HASH */
486 } else if(pSMBr->hdr.WordCount != 17) {
492 server->secMode = pSMBr->SecurityMode;
493 if((server->secMode & SECMODE_USER) == 0)
494 cFYI(1,("share mode security"));
496 if(extended_security & CIFSSEC_MUST_NTLMV2)
497 server->secType = NTLMv2;
499 server->secType = NTLM;
502 /* one byte - no need to convert this or EncryptionKeyLen
503 from little endian */
504 server->maxReq = le16_to_cpu(pSMBr->MaxMpxCount);
505 /* probably no need to store and check maxvcs */
507 min(le32_to_cpu(pSMBr->MaxBufferSize),
508 (__u32) CIFSMaxBufSize + MAX_CIFS_HDR_SIZE);
509 server->maxRw = le32_to_cpu(pSMBr->MaxRawSize);
510 cFYI(0, ("Max buf = %d", ses->server->maxBuf));
511 GETU32(ses->server->sessid) = le32_to_cpu(pSMBr->SessionKey);
512 server->capabilities = le32_to_cpu(pSMBr->Capabilities);
513 server->timeZone = le16_to_cpu(pSMBr->ServerTimeZone);
514 /* BB with UTC do we ever need to be using srvr timezone? */
515 if (pSMBr->EncryptionKeyLength == CIFS_CRYPTO_KEY_SIZE) {
516 memcpy(server->cryptKey, pSMBr->u.EncryptionKey,
517 CIFS_CRYPTO_KEY_SIZE);
518 } else if ((pSMBr->hdr.Flags2 & SMBFLG2_EXT_SEC)
519 && (pSMBr->EncryptionKeyLength == 0)) {
520 /* decode security blob */
524 /* BB might be helpful to save off the domain of server here */
526 if ((pSMBr->hdr.Flags2 & SMBFLG2_EXT_SEC) &&
527 (server->capabilities & CAP_EXTENDED_SECURITY)) {
528 count = pSMBr->ByteCount;
531 else if (count == 16) {
532 server->secType = RawNTLMSSP;
533 if (server->socketUseCount.counter > 1) {
535 (server->server_GUID,
536 pSMBr->u.extended_response.
538 cFYI(1, ("server UID changed"));
546 memcpy(server->server_GUID,
547 pSMBr->u.extended_response.
550 rc = decode_negTokenInit(pSMBr->u.
556 /* BB Need to fill struct for sessetup here */
563 server->capabilities &= ~CAP_EXTENDED_SECURITY;
564 if(sign_CIFS_PDUs == FALSE) {
565 if(server->secMode & SECMODE_SIGN_REQUIRED)
567 ("Server requires /proc/fs/cifs/PacketSigningEnabled"));
568 server->secMode &= ~(SECMODE_SIGN_ENABLED | SECMODE_SIGN_REQUIRED);
569 } else if(sign_CIFS_PDUs == 1) {
570 if((server->secMode & SECMODE_SIGN_REQUIRED) == 0)
571 server->secMode &= ~(SECMODE_SIGN_ENABLED | SECMODE_SIGN_REQUIRED);
576 cifs_buf_release(pSMB);
581 CIFSSMBTDis(const int xid, struct cifsTconInfo *tcon)
583 struct smb_hdr *smb_buffer;
584 struct smb_hdr *smb_buffer_response; /* BB removeme BB */
588 cFYI(1, ("In tree disconnect"));
590 * If last user of the connection and
591 * connection alive - disconnect it
592 * If this is the last connection on the server session disconnect it
593 * (and inside session disconnect we should check if tcp socket needs
594 * to be freed and kernel thread woken up).
597 down(&tcon->tconSem);
601 atomic_dec(&tcon->useCount);
602 if (atomic_read(&tcon->useCount) > 0) {
607 /* No need to return error on this operation if tid invalidated and
608 closed on server already e.g. due to tcp session crashing */
609 if(tcon->tidStatus == CifsNeedReconnect) {
614 if((tcon->ses == NULL) || (tcon->ses->server == NULL)) {
618 rc = small_smb_init(SMB_COM_TREE_DISCONNECT, 0, tcon,
619 (void **)&smb_buffer);
624 smb_buffer_response = smb_buffer; /* BB removeme BB */
626 rc = SendReceive(xid, tcon->ses, smb_buffer, smb_buffer_response,
629 cFYI(1, ("Tree disconnect failed %d", rc));
632 cifs_small_buf_release(smb_buffer);
635 /* No need to return error on this operation if tid invalidated and
636 closed on server already e.g. due to tcp session crashing */
644 CIFSSMBLogoff(const int xid, struct cifsSesInfo *ses)
646 struct smb_hdr *smb_buffer_response;
647 LOGOFF_ANDX_REQ *pSMB;
651 cFYI(1, ("In SMBLogoff for session disconnect"));
657 atomic_dec(&ses->inUse);
658 if (atomic_read(&ses->inUse) > 0) {
662 rc = small_smb_init(SMB_COM_LOGOFF_ANDX, 2, NULL, (void **)&pSMB);
668 smb_buffer_response = (struct smb_hdr *)pSMB; /* BB removeme BB */
671 pSMB->hdr.Mid = GetNextMid(ses->server);
673 if(ses->server->secMode &
674 (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
675 pSMB->hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
678 pSMB->hdr.Uid = ses->Suid;
680 pSMB->AndXCommand = 0xFF;
681 rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB,
682 smb_buffer_response, &length, 0);
684 atomic_dec(&ses->server->socketUseCount);
685 if (atomic_read(&ses->server->socketUseCount) == 0) {
686 spin_lock(&GlobalMid_Lock);
687 ses->server->tcpStatus = CifsExiting;
688 spin_unlock(&GlobalMid_Lock);
693 cifs_small_buf_release(pSMB);
695 /* if session dead then we do not need to do ulogoff,
696 since server closed smb session, no sense reporting
704 CIFSSMBDelFile(const int xid, struct cifsTconInfo *tcon, const char *fileName,
705 const struct nls_table *nls_codepage, int remap)
707 DELETE_FILE_REQ *pSMB = NULL;
708 DELETE_FILE_RSP *pSMBr = NULL;
714 rc = smb_init(SMB_COM_DELETE, 1, tcon, (void **) &pSMB,
719 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
721 cifsConvertToUCS((__le16 *) pSMB->fileName, fileName,
722 PATH_MAX, nls_codepage, remap);
723 name_len++; /* trailing null */
725 } else { /* BB improve check for buffer overruns BB */
726 name_len = strnlen(fileName, PATH_MAX);
727 name_len++; /* trailing null */
728 strncpy(pSMB->fileName, fileName, name_len);
730 pSMB->SearchAttributes =
731 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM);
732 pSMB->BufferFormat = 0x04;
733 pSMB->hdr.smb_buf_length += name_len + 1;
734 pSMB->ByteCount = cpu_to_le16(name_len + 1);
735 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
736 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
737 cifs_stats_inc(&tcon->num_deletes);
739 cFYI(1, ("Error in RMFile = %d", rc));
742 cifs_buf_release(pSMB);
750 CIFSSMBRmDir(const int xid, struct cifsTconInfo *tcon, const char *dirName,
751 const struct nls_table *nls_codepage, int remap)
753 DELETE_DIRECTORY_REQ *pSMB = NULL;
754 DELETE_DIRECTORY_RSP *pSMBr = NULL;
759 cFYI(1, ("In CIFSSMBRmDir"));
761 rc = smb_init(SMB_COM_DELETE_DIRECTORY, 0, tcon, (void **) &pSMB,
766 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
767 name_len = cifsConvertToUCS((__le16 *) pSMB->DirName, dirName,
768 PATH_MAX, nls_codepage, remap);
769 name_len++; /* trailing null */
771 } else { /* BB improve check for buffer overruns BB */
772 name_len = strnlen(dirName, PATH_MAX);
773 name_len++; /* trailing null */
774 strncpy(pSMB->DirName, dirName, name_len);
777 pSMB->BufferFormat = 0x04;
778 pSMB->hdr.smb_buf_length += name_len + 1;
779 pSMB->ByteCount = cpu_to_le16(name_len + 1);
780 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
781 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
782 cifs_stats_inc(&tcon->num_rmdirs);
784 cFYI(1, ("Error in RMDir = %d", rc));
787 cifs_buf_release(pSMB);
794 CIFSSMBMkDir(const int xid, struct cifsTconInfo *tcon,
795 const char *name, const struct nls_table *nls_codepage, int remap)
798 CREATE_DIRECTORY_REQ *pSMB = NULL;
799 CREATE_DIRECTORY_RSP *pSMBr = NULL;
803 cFYI(1, ("In CIFSSMBMkDir"));
805 rc = smb_init(SMB_COM_CREATE_DIRECTORY, 0, tcon, (void **) &pSMB,
810 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
811 name_len = cifsConvertToUCS((__le16 *) pSMB->DirName, name,
812 PATH_MAX, nls_codepage, remap);
813 name_len++; /* trailing null */
815 } else { /* BB improve check for buffer overruns BB */
816 name_len = strnlen(name, PATH_MAX);
817 name_len++; /* trailing null */
818 strncpy(pSMB->DirName, name, name_len);
821 pSMB->BufferFormat = 0x04;
822 pSMB->hdr.smb_buf_length += name_len + 1;
823 pSMB->ByteCount = cpu_to_le16(name_len + 1);
824 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
825 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
826 cifs_stats_inc(&tcon->num_mkdirs);
828 cFYI(1, ("Error in Mkdir = %d", rc));
831 cifs_buf_release(pSMB);
837 static __u16 convert_disposition(int disposition)
841 switch (disposition) {
843 ofun = SMBOPEN_OCREATE | SMBOPEN_OTRUNC;
846 ofun = SMBOPEN_OAPPEND;
849 ofun = SMBOPEN_OCREATE;
852 ofun = SMBOPEN_OCREATE | SMBOPEN_OAPPEND;
855 ofun = SMBOPEN_OTRUNC;
857 case FILE_OVERWRITE_IF:
858 ofun = SMBOPEN_OCREATE | SMBOPEN_OTRUNC;
861 cFYI(1,("unknown disposition %d",disposition));
862 ofun = SMBOPEN_OAPPEND; /* regular open */
868 SMBLegacyOpen(const int xid, struct cifsTconInfo *tcon,
869 const char *fileName, const int openDisposition,
870 const int access_flags, const int create_options, __u16 * netfid,
871 int *pOplock, FILE_ALL_INFO * pfile_info,
872 const struct nls_table *nls_codepage, int remap)
875 OPENX_REQ *pSMB = NULL;
876 OPENX_RSP *pSMBr = NULL;
882 rc = smb_init(SMB_COM_OPEN_ANDX, 15, tcon, (void **) &pSMB,
887 pSMB->AndXCommand = 0xFF; /* none */
889 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
890 count = 1; /* account for one byte pad to word boundary */
892 cifsConvertToUCS((__le16 *) (pSMB->fileName + 1),
893 fileName, PATH_MAX, nls_codepage, remap);
894 name_len++; /* trailing null */
896 } else { /* BB improve check for buffer overruns BB */
897 count = 0; /* no pad */
898 name_len = strnlen(fileName, PATH_MAX);
899 name_len++; /* trailing null */
900 strncpy(pSMB->fileName, fileName, name_len);
902 if (*pOplock & REQ_OPLOCK)
903 pSMB->OpenFlags = cpu_to_le16(REQ_OPLOCK);
904 else if (*pOplock & REQ_BATCHOPLOCK) {
905 pSMB->OpenFlags = cpu_to_le16(REQ_BATCHOPLOCK);
907 pSMB->OpenFlags |= cpu_to_le16(REQ_MORE_INFO);
908 /* BB fixme add conversion for access_flags to bits 0 - 2 of mode */
914 pSMB->Mode = cpu_to_le16(2);
915 pSMB->Mode |= cpu_to_le16(0x40); /* deny none */
916 /* set file as system file if special file such
917 as fifo and server expecting SFU style and
918 no Unix extensions */
920 if(create_options & CREATE_OPTION_SPECIAL)
921 pSMB->FileAttributes = cpu_to_le16(ATTR_SYSTEM);
923 pSMB->FileAttributes = cpu_to_le16(0/*ATTR_NORMAL*/); /* BB FIXME */
925 /* if ((omode & S_IWUGO) == 0)
926 pSMB->FileAttributes |= cpu_to_le32(ATTR_READONLY);*/
927 /* Above line causes problems due to vfs splitting create into two
928 pieces - need to set mode after file created not while it is
932 /* pSMB->CreateOptions = cpu_to_le32(create_options & CREATE_OPTIONS_MASK); */
933 /* BB FIXME END BB */
935 pSMB->Sattr = cpu_to_le16(ATTR_HIDDEN | ATTR_SYSTEM | ATTR_DIRECTORY);
936 pSMB->OpenFunction = cpu_to_le16(convert_disposition(openDisposition));
938 pSMB->hdr.smb_buf_length += count;
940 pSMB->ByteCount = cpu_to_le16(count);
941 /* long_op set to 1 to allow for oplock break timeouts */
942 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
943 (struct smb_hdr *) pSMBr, &bytes_returned, 1);
944 cifs_stats_inc(&tcon->num_opens);
946 cFYI(1, ("Error in Open = %d", rc));
948 /* BB verify if wct == 15 */
950 /* *pOplock = pSMBr->OplockLevel; */ /* BB take from action field BB */
952 *netfid = pSMBr->Fid; /* cifs fid stays in le */
953 /* Let caller know file was created so we can set the mode. */
954 /* Do we care about the CreateAction in any other cases? */
956 /* if(cpu_to_le32(FILE_CREATE) == pSMBr->CreateAction)
957 *pOplock |= CIFS_CREATE_ACTION; */
961 pfile_info->CreationTime = 0; /* BB convert CreateTime*/
962 pfile_info->LastAccessTime = 0; /* BB fixme */
963 pfile_info->LastWriteTime = 0; /* BB fixme */
964 pfile_info->ChangeTime = 0; /* BB fixme */
965 pfile_info->Attributes =
966 cpu_to_le32(le16_to_cpu(pSMBr->FileAttributes));
967 /* the file_info buf is endian converted by caller */
968 pfile_info->AllocationSize =
969 cpu_to_le64(le32_to_cpu(pSMBr->EndOfFile));
970 pfile_info->EndOfFile = pfile_info->AllocationSize;
971 pfile_info->NumberOfLinks = cpu_to_le32(1);
975 cifs_buf_release(pSMB);
982 CIFSSMBOpen(const int xid, struct cifsTconInfo *tcon,
983 const char *fileName, const int openDisposition,
984 const int access_flags, const int create_options, __u16 * netfid,
985 int *pOplock, FILE_ALL_INFO * pfile_info,
986 const struct nls_table *nls_codepage, int remap)
989 OPEN_REQ *pSMB = NULL;
990 OPEN_RSP *pSMBr = NULL;
996 rc = smb_init(SMB_COM_NT_CREATE_ANDX, 24, tcon, (void **) &pSMB,
1001 pSMB->AndXCommand = 0xFF; /* none */
1003 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1004 count = 1; /* account for one byte pad to word boundary */
1006 cifsConvertToUCS((__le16 *) (pSMB->fileName + 1),
1007 fileName, PATH_MAX, nls_codepage, remap);
1008 name_len++; /* trailing null */
1010 pSMB->NameLength = cpu_to_le16(name_len);
1011 } else { /* BB improve check for buffer overruns BB */
1012 count = 0; /* no pad */
1013 name_len = strnlen(fileName, PATH_MAX);
1014 name_len++; /* trailing null */
1015 pSMB->NameLength = cpu_to_le16(name_len);
1016 strncpy(pSMB->fileName, fileName, name_len);
1018 if (*pOplock & REQ_OPLOCK)
1019 pSMB->OpenFlags = cpu_to_le32(REQ_OPLOCK);
1020 else if (*pOplock & REQ_BATCHOPLOCK) {
1021 pSMB->OpenFlags = cpu_to_le32(REQ_BATCHOPLOCK);
1023 pSMB->DesiredAccess = cpu_to_le32(access_flags);
1024 pSMB->AllocationSize = 0;
1025 /* set file as system file if special file such
1026 as fifo and server expecting SFU style and
1027 no Unix extensions */
1028 if(create_options & CREATE_OPTION_SPECIAL)
1029 pSMB->FileAttributes = cpu_to_le32(ATTR_SYSTEM);
1031 pSMB->FileAttributes = cpu_to_le32(ATTR_NORMAL);
1032 /* XP does not handle ATTR_POSIX_SEMANTICS */
1033 /* but it helps speed up case sensitive checks for other
1034 servers such as Samba */
1035 if (tcon->ses->capabilities & CAP_UNIX)
1036 pSMB->FileAttributes |= cpu_to_le32(ATTR_POSIX_SEMANTICS);
1038 /* if ((omode & S_IWUGO) == 0)
1039 pSMB->FileAttributes |= cpu_to_le32(ATTR_READONLY);*/
1040 /* Above line causes problems due to vfs splitting create into two
1041 pieces - need to set mode after file created not while it is
1043 pSMB->ShareAccess = cpu_to_le32(FILE_SHARE_ALL);
1044 pSMB->CreateDisposition = cpu_to_le32(openDisposition);
1045 pSMB->CreateOptions = cpu_to_le32(create_options & CREATE_OPTIONS_MASK);
1046 /* BB Expirement with various impersonation levels and verify */
1047 pSMB->ImpersonationLevel = cpu_to_le32(SECURITY_IMPERSONATION);
1048 pSMB->SecurityFlags =
1049 SECURITY_CONTEXT_TRACKING | SECURITY_EFFECTIVE_ONLY;
1052 pSMB->hdr.smb_buf_length += count;
1054 pSMB->ByteCount = cpu_to_le16(count);
1055 /* long_op set to 1 to allow for oplock break timeouts */
1056 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1057 (struct smb_hdr *) pSMBr, &bytes_returned, 1);
1058 cifs_stats_inc(&tcon->num_opens);
1060 cFYI(1, ("Error in Open = %d", rc));
1062 *pOplock = pSMBr->OplockLevel; /* 1 byte no need to le_to_cpu */
1063 *netfid = pSMBr->Fid; /* cifs fid stays in le */
1064 /* Let caller know file was created so we can set the mode. */
1065 /* Do we care about the CreateAction in any other cases? */
1066 if(cpu_to_le32(FILE_CREATE) == pSMBr->CreateAction)
1067 *pOplock |= CIFS_CREATE_ACTION;
1069 memcpy((char *)pfile_info,(char *)&pSMBr->CreationTime,
1070 36 /* CreationTime to Attributes */);
1071 /* the file_info buf is endian converted by caller */
1072 pfile_info->AllocationSize = pSMBr->AllocationSize;
1073 pfile_info->EndOfFile = pSMBr->EndOfFile;
1074 pfile_info->NumberOfLinks = cpu_to_le32(1);
1078 cifs_buf_release(pSMB);
1085 CIFSSMBRead(const int xid, struct cifsTconInfo *tcon,
1086 const int netfid, const unsigned int count,
1087 const __u64 lseek, unsigned int *nbytes, char **buf,
1091 READ_REQ *pSMB = NULL;
1092 READ_RSP *pSMBr = NULL;
1093 char *pReadData = NULL;
1095 int resp_buf_type = 0;
1098 cFYI(1,("Reading %d bytes on fid %d",count,netfid));
1099 if(tcon->ses->capabilities & CAP_LARGE_FILES)
1102 wct = 10; /* old style read */
1105 rc = small_smb_init(SMB_COM_READ_ANDX, wct, tcon, (void **) &pSMB);
1109 /* tcon and ses pointer are checked in smb_init */
1110 if (tcon->ses->server == NULL)
1111 return -ECONNABORTED;
1113 pSMB->AndXCommand = 0xFF; /* none */
1115 pSMB->OffsetLow = cpu_to_le32(lseek & 0xFFFFFFFF);
1117 pSMB->OffsetHigh = cpu_to_le32(lseek >> 32);
1118 else if((lseek >> 32) > 0) /* can not handle this big offset for old */
1121 pSMB->Remaining = 0;
1122 pSMB->MaxCount = cpu_to_le16(count & 0xFFFF);
1123 pSMB->MaxCountHigh = cpu_to_le32(count >> 16);
1125 pSMB->ByteCount = 0; /* no need to do le conversion since 0 */
1127 /* old style read */
1128 struct smb_com_readx_req * pSMBW =
1129 (struct smb_com_readx_req *)pSMB;
1130 pSMBW->ByteCount = 0;
1133 iov[0].iov_base = (char *)pSMB;
1134 iov[0].iov_len = pSMB->hdr.smb_buf_length + 4;
1135 rc = SendReceive2(xid, tcon->ses, iov,
1138 cifs_stats_inc(&tcon->num_reads);
1139 pSMBr = (READ_RSP *)iov[0].iov_base;
1141 cERROR(1, ("Send error in read = %d", rc));
1143 int data_length = le16_to_cpu(pSMBr->DataLengthHigh);
1144 data_length = data_length << 16;
1145 data_length += le16_to_cpu(pSMBr->DataLength);
1146 *nbytes = data_length;
1148 /*check that DataLength would not go beyond end of SMB */
1149 if ((data_length > CIFSMaxBufSize)
1150 || (data_length > count)) {
1151 cFYI(1,("bad length %d for count %d",data_length,count));
1155 pReadData = (char *) (&pSMBr->hdr.Protocol) +
1156 le16_to_cpu(pSMBr->DataOffset);
1157 /* if(rc = copy_to_user(buf, pReadData, data_length)) {
1158 cERROR(1,("Faulting on read rc = %d",rc));
1160 }*/ /* can not use copy_to_user when using page cache*/
1162 memcpy(*buf,pReadData,data_length);
1166 /* cifs_small_buf_release(pSMB); */ /* Freed earlier now in SendReceive2 */
1168 if(resp_buf_type == CIFS_SMALL_BUFFER)
1169 cifs_small_buf_release(iov[0].iov_base);
1170 else if(resp_buf_type == CIFS_LARGE_BUFFER)
1171 cifs_buf_release(iov[0].iov_base);
1172 } else if(resp_buf_type != CIFS_NO_BUFFER) {
1173 /* return buffer to caller to free */
1174 *buf = iov[0].iov_base;
1175 if(resp_buf_type == CIFS_SMALL_BUFFER)
1176 *pbuf_type = CIFS_SMALL_BUFFER;
1177 else if(resp_buf_type == CIFS_LARGE_BUFFER)
1178 *pbuf_type = CIFS_LARGE_BUFFER;
1179 } /* else no valid buffer on return - leave as null */
1181 /* Note: On -EAGAIN error only caller can retry on handle based calls
1182 since file handle passed in no longer valid */
1188 CIFSSMBWrite(const int xid, struct cifsTconInfo *tcon,
1189 const int netfid, const unsigned int count,
1190 const __u64 offset, unsigned int *nbytes, const char *buf,
1191 const char __user * ubuf, const int long_op)
1194 WRITE_REQ *pSMB = NULL;
1195 WRITE_RSP *pSMBr = NULL;
1196 int bytes_returned, wct;
1200 /* cFYI(1,("write at %lld %d bytes",offset,count));*/
1201 if(tcon->ses == NULL)
1202 return -ECONNABORTED;
1204 if(tcon->ses->capabilities & CAP_LARGE_FILES)
1209 rc = smb_init(SMB_COM_WRITE_ANDX, wct, tcon, (void **) &pSMB,
1213 /* tcon and ses pointer are checked in smb_init */
1214 if (tcon->ses->server == NULL)
1215 return -ECONNABORTED;
1217 pSMB->AndXCommand = 0xFF; /* none */
1219 pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF);
1221 pSMB->OffsetHigh = cpu_to_le32(offset >> 32);
1222 else if((offset >> 32) > 0) /* can not handle this big offset for old */
1225 pSMB->Reserved = 0xFFFFFFFF;
1226 pSMB->WriteMode = 0;
1227 pSMB->Remaining = 0;
1229 /* Can increase buffer size if buffer is big enough in some cases - ie we
1230 can send more if LARGE_WRITE_X capability returned by the server and if
1231 our buffer is big enough or if we convert to iovecs on socket writes
1232 and eliminate the copy to the CIFS buffer */
1233 if(tcon->ses->capabilities & CAP_LARGE_WRITE_X) {
1234 bytes_sent = min_t(const unsigned int, CIFSMaxBufSize, count);
1236 bytes_sent = (tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE)
1240 if (bytes_sent > count)
1243 cpu_to_le16(offsetof(struct smb_com_write_req,Data) - 4);
1245 memcpy(pSMB->Data,buf,bytes_sent);
1247 if(copy_from_user(pSMB->Data,ubuf,bytes_sent)) {
1248 cifs_buf_release(pSMB);
1251 } else if (count != 0) {
1253 cifs_buf_release(pSMB);
1255 } /* else setting file size with write of zero bytes */
1257 byte_count = bytes_sent + 1; /* pad */
1258 else /* wct == 12 */ {
1259 byte_count = bytes_sent + 5; /* bigger pad, smaller smb hdr */
1261 pSMB->DataLengthLow = cpu_to_le16(bytes_sent & 0xFFFF);
1262 pSMB->DataLengthHigh = cpu_to_le16(bytes_sent >> 16);
1263 pSMB->hdr.smb_buf_length += byte_count;
1266 pSMB->ByteCount = cpu_to_le16(byte_count);
1267 else { /* old style write has byte count 4 bytes earlier so 4 bytes pad */
1268 struct smb_com_writex_req * pSMBW =
1269 (struct smb_com_writex_req *)pSMB;
1270 pSMBW->ByteCount = cpu_to_le16(byte_count);
1273 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1274 (struct smb_hdr *) pSMBr, &bytes_returned, long_op);
1275 cifs_stats_inc(&tcon->num_writes);
1277 cFYI(1, ("Send error in write = %d", rc));
1280 *nbytes = le16_to_cpu(pSMBr->CountHigh);
1281 *nbytes = (*nbytes) << 16;
1282 *nbytes += le16_to_cpu(pSMBr->Count);
1285 cifs_buf_release(pSMB);
1287 /* Note: On -EAGAIN error only caller can retry on handle based calls
1288 since file handle passed in no longer valid */
1294 CIFSSMBWrite2(const int xid, struct cifsTconInfo *tcon,
1295 const int netfid, const unsigned int count,
1296 const __u64 offset, unsigned int *nbytes, struct kvec *iov,
1297 int n_vec, const int long_op)
1300 WRITE_REQ *pSMB = NULL;
1303 int resp_buf_type = 0;
1305 cFYI(1,("write2 at %lld %d bytes", (long long)offset, count));
1307 if(tcon->ses->capabilities & CAP_LARGE_FILES)
1311 rc = small_smb_init(SMB_COM_WRITE_ANDX, wct, tcon, (void **) &pSMB);
1314 /* tcon and ses pointer are checked in smb_init */
1315 if (tcon->ses->server == NULL)
1316 return -ECONNABORTED;
1318 pSMB->AndXCommand = 0xFF; /* none */
1320 pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF);
1322 pSMB->OffsetHigh = cpu_to_le32(offset >> 32);
1323 else if((offset >> 32) > 0) /* can not handle this big offset for old */
1325 pSMB->Reserved = 0xFFFFFFFF;
1326 pSMB->WriteMode = 0;
1327 pSMB->Remaining = 0;
1330 cpu_to_le16(offsetof(struct smb_com_write_req,Data) - 4);
1332 pSMB->DataLengthLow = cpu_to_le16(count & 0xFFFF);
1333 pSMB->DataLengthHigh = cpu_to_le16(count >> 16);
1334 smb_hdr_len = pSMB->hdr.smb_buf_length + 1; /* hdr + 1 byte pad */
1336 pSMB->hdr.smb_buf_length += count+1;
1337 else /* wct == 12 */
1338 pSMB->hdr.smb_buf_length += count+5; /* smb data starts later */
1340 pSMB->ByteCount = cpu_to_le16(count + 1);
1341 else /* wct == 12 */ /* bigger pad, smaller smb hdr, keep offset ok */ {
1342 struct smb_com_writex_req * pSMBW =
1343 (struct smb_com_writex_req *)pSMB;
1344 pSMBW->ByteCount = cpu_to_le16(count + 5);
1346 iov[0].iov_base = pSMB;
1348 iov[0].iov_len = smb_hdr_len + 4;
1349 else /* wct == 12 pad bigger by four bytes */
1350 iov[0].iov_len = smb_hdr_len + 8;
1353 rc = SendReceive2(xid, tcon->ses, iov, n_vec + 1, &resp_buf_type,
1355 cifs_stats_inc(&tcon->num_writes);
1357 cFYI(1, ("Send error Write2 = %d", rc));
1359 } else if(resp_buf_type == 0) {
1360 /* presumably this can not happen, but best to be safe */
1364 WRITE_RSP * pSMBr = (WRITE_RSP *)iov[0].iov_base;
1365 *nbytes = le16_to_cpu(pSMBr->CountHigh);
1366 *nbytes = (*nbytes) << 16;
1367 *nbytes += le16_to_cpu(pSMBr->Count);
1370 /* cifs_small_buf_release(pSMB); */ /* Freed earlier now in SendReceive2 */
1371 if(resp_buf_type == CIFS_SMALL_BUFFER)
1372 cifs_small_buf_release(iov[0].iov_base);
1373 else if(resp_buf_type == CIFS_LARGE_BUFFER)
1374 cifs_buf_release(iov[0].iov_base);
1376 /* Note: On -EAGAIN error only caller can retry on handle based calls
1377 since file handle passed in no longer valid */
1384 CIFSSMBLock(const int xid, struct cifsTconInfo *tcon,
1385 const __u16 smb_file_id, const __u64 len,
1386 const __u64 offset, const __u32 numUnlock,
1387 const __u32 numLock, const __u8 lockType, const int waitFlag)
1390 LOCK_REQ *pSMB = NULL;
1391 LOCK_RSP *pSMBr = NULL;
1396 cFYI(1, ("In CIFSSMBLock - timeout %d numLock %d",waitFlag,numLock));
1397 rc = small_smb_init(SMB_COM_LOCKING_ANDX, 8, tcon, (void **) &pSMB);
1402 pSMBr = (LOCK_RSP *)pSMB; /* BB removeme BB */
1404 if(lockType == LOCKING_ANDX_OPLOCK_RELEASE) {
1405 timeout = -1; /* no response expected */
1407 } else if (waitFlag == TRUE) {
1408 timeout = 3; /* blocking operation, no timeout */
1409 pSMB->Timeout = cpu_to_le32(-1);/* blocking - do not time out */
1414 pSMB->NumberOfLocks = cpu_to_le16(numLock);
1415 pSMB->NumberOfUnlocks = cpu_to_le16(numUnlock);
1416 pSMB->LockType = lockType;
1417 pSMB->AndXCommand = 0xFF; /* none */
1418 pSMB->Fid = smb_file_id; /* netfid stays le */
1420 if((numLock != 0) || (numUnlock != 0)) {
1421 pSMB->Locks[0].Pid = cpu_to_le16(current->tgid);
1422 /* BB where to store pid high? */
1423 pSMB->Locks[0].LengthLow = cpu_to_le32((u32)len);
1424 pSMB->Locks[0].LengthHigh = cpu_to_le32((u32)(len>>32));
1425 pSMB->Locks[0].OffsetLow = cpu_to_le32((u32)offset);
1426 pSMB->Locks[0].OffsetHigh = cpu_to_le32((u32)(offset>>32));
1427 count = sizeof(LOCKING_ANDX_RANGE);
1432 pSMB->hdr.smb_buf_length += count;
1433 pSMB->ByteCount = cpu_to_le16(count);
1435 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1436 (struct smb_hdr *) pSMBr, &bytes_returned, timeout);
1437 cifs_stats_inc(&tcon->num_locks);
1439 cFYI(1, ("Send error in Lock = %d", rc));
1441 cifs_small_buf_release(pSMB);
1443 /* Note: On -EAGAIN error only caller can retry on handle based calls
1444 since file handle passed in no longer valid */
1449 CIFSSMBPosixLock(const int xid, struct cifsTconInfo *tcon,
1450 const __u16 smb_file_id, const int get_flag, const __u64 len,
1451 struct file_lock *pLockData, const __u16 lock_type,
1454 struct smb_com_transaction2_sfi_req *pSMB = NULL;
1455 struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
1457 struct cifs_posix_lock *parm_data;
1459 int bytes_returned = 0;
1460 __u16 params, param_offset, offset, byte_count, count;
1462 cFYI(1, ("Posix Lock"));
1464 if(pLockData == NULL)
1467 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
1472 pSMBr = (struct smb_com_transaction2_sfi_rsp *)pSMB;
1475 pSMB->MaxSetupCount = 0;
1479 pSMB->Reserved2 = 0;
1480 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
1481 offset = param_offset + params;
1483 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
1485 count = sizeof(struct cifs_posix_lock);
1486 pSMB->MaxParameterCount = cpu_to_le16(2);
1487 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB PDU from sess */
1488 pSMB->SetupCount = 1;
1489 pSMB->Reserved3 = 0;
1491 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION);
1493 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
1494 byte_count = 3 /* pad */ + params + count;
1495 pSMB->DataCount = cpu_to_le16(count);
1496 pSMB->ParameterCount = cpu_to_le16(params);
1497 pSMB->TotalDataCount = pSMB->DataCount;
1498 pSMB->TotalParameterCount = pSMB->ParameterCount;
1499 pSMB->ParameterOffset = cpu_to_le16(param_offset);
1500 parm_data = (struct cifs_posix_lock *)
1501 (((char *) &pSMB->hdr.Protocol) + offset);
1503 parm_data->lock_type = cpu_to_le16(lock_type);
1505 parm_data->lock_flags = cpu_to_le16(1);
1506 parm_data->pid = cpu_to_le32(current->tgid);
1507 parm_data->start = cpu_to_le64(pLockData->fl_start);
1508 parm_data->length = cpu_to_le64(len); /* normalize negative numbers */
1510 pSMB->DataOffset = cpu_to_le16(offset);
1511 pSMB->Fid = smb_file_id;
1512 pSMB->InformationLevel = cpu_to_le16(SMB_SET_POSIX_LOCK);
1513 pSMB->Reserved4 = 0;
1514 pSMB->hdr.smb_buf_length += byte_count;
1515 pSMB->ByteCount = cpu_to_le16(byte_count);
1516 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1517 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1519 cFYI(1, ("Send error in Posix Lock = %d", rc));
1520 } else if (get_flag) {
1521 /* lock structure can be returned on get */
1524 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
1526 if (rc || (pSMBr->ByteCount < sizeof(struct cifs_posix_lock))) {
1527 rc = -EIO; /* bad smb */
1530 if(pLockData == NULL) {
1534 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
1535 data_count = le16_to_cpu(pSMBr->t2.DataCount);
1536 if(data_count < sizeof(struct cifs_posix_lock)) {
1540 parm_data = (struct cifs_posix_lock *)
1541 ((char *)&pSMBr->hdr.Protocol + data_offset);
1542 if(parm_data->lock_type == cpu_to_le16(CIFS_UNLCK))
1543 pLockData->fl_type = F_UNLCK;
1548 cifs_small_buf_release(pSMB);
1550 /* Note: On -EAGAIN error only caller can retry on handle based calls
1551 since file handle passed in no longer valid */
1558 CIFSSMBClose(const int xid, struct cifsTconInfo *tcon, int smb_file_id)
1561 CLOSE_REQ *pSMB = NULL;
1562 CLOSE_RSP *pSMBr = NULL;
1564 cFYI(1, ("In CIFSSMBClose"));
1566 /* do not retry on dead session on close */
1567 rc = small_smb_init(SMB_COM_CLOSE, 3, tcon, (void **) &pSMB);
1573 pSMBr = (CLOSE_RSP *)pSMB; /* BB removeme BB */
1575 pSMB->FileID = (__u16) smb_file_id;
1576 pSMB->LastWriteTime = 0;
1577 pSMB->ByteCount = 0;
1578 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1579 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1580 cifs_stats_inc(&tcon->num_closes);
1583 /* EINTR is expected when user ctl-c to kill app */
1584 cERROR(1, ("Send error in Close = %d", rc));
1588 cifs_small_buf_release(pSMB);
1590 /* Since session is dead, file will be closed on server already */
1598 CIFSSMBRename(const int xid, struct cifsTconInfo *tcon,
1599 const char *fromName, const char *toName,
1600 const struct nls_table *nls_codepage, int remap)
1603 RENAME_REQ *pSMB = NULL;
1604 RENAME_RSP *pSMBr = NULL;
1606 int name_len, name_len2;
1609 cFYI(1, ("In CIFSSMBRename"));
1611 rc = smb_init(SMB_COM_RENAME, 1, tcon, (void **) &pSMB,
1616 pSMB->BufferFormat = 0x04;
1617 pSMB->SearchAttributes =
1618 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
1621 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1623 cifsConvertToUCS((__le16 *) pSMB->OldFileName, fromName,
1624 PATH_MAX, nls_codepage, remap);
1625 name_len++; /* trailing null */
1627 pSMB->OldFileName[name_len] = 0x04; /* pad */
1628 /* protocol requires ASCII signature byte on Unicode string */
1629 pSMB->OldFileName[name_len + 1] = 0x00;
1631 cifsConvertToUCS((__le16 *) &pSMB->OldFileName[name_len + 2],
1632 toName, PATH_MAX, nls_codepage, remap);
1633 name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
1634 name_len2 *= 2; /* convert to bytes */
1635 } else { /* BB improve the check for buffer overruns BB */
1636 name_len = strnlen(fromName, PATH_MAX);
1637 name_len++; /* trailing null */
1638 strncpy(pSMB->OldFileName, fromName, name_len);
1639 name_len2 = strnlen(toName, PATH_MAX);
1640 name_len2++; /* trailing null */
1641 pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */
1642 strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2);
1643 name_len2++; /* trailing null */
1644 name_len2++; /* signature byte */
1647 count = 1 /* 1st signature byte */ + name_len + name_len2;
1648 pSMB->hdr.smb_buf_length += count;
1649 pSMB->ByteCount = cpu_to_le16(count);
1651 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1652 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1653 cifs_stats_inc(&tcon->num_renames);
1655 cFYI(1, ("Send error in rename = %d", rc));
1658 cifs_buf_release(pSMB);
1666 int CIFSSMBRenameOpenFile(const int xid,struct cifsTconInfo *pTcon,
1667 int netfid, char * target_name,
1668 const struct nls_table * nls_codepage, int remap)
1670 struct smb_com_transaction2_sfi_req *pSMB = NULL;
1671 struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
1672 struct set_file_rename * rename_info;
1674 char dummy_string[30];
1676 int bytes_returned = 0;
1678 __u16 params, param_offset, offset, count, byte_count;
1680 cFYI(1, ("Rename to File by handle"));
1681 rc = smb_init(SMB_COM_TRANSACTION2, 15, pTcon, (void **) &pSMB,
1687 pSMB->MaxSetupCount = 0;
1691 pSMB->Reserved2 = 0;
1692 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
1693 offset = param_offset + params;
1695 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
1696 rename_info = (struct set_file_rename *) data_offset;
1697 pSMB->MaxParameterCount = cpu_to_le16(2);
1698 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB PDU from sess */
1699 pSMB->SetupCount = 1;
1700 pSMB->Reserved3 = 0;
1701 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
1702 byte_count = 3 /* pad */ + params;
1703 pSMB->ParameterCount = cpu_to_le16(params);
1704 pSMB->TotalParameterCount = pSMB->ParameterCount;
1705 pSMB->ParameterOffset = cpu_to_le16(param_offset);
1706 pSMB->DataOffset = cpu_to_le16(offset);
1707 /* construct random name ".cifs_tmp<inodenum><mid>" */
1708 rename_info->overwrite = cpu_to_le32(1);
1709 rename_info->root_fid = 0;
1710 /* unicode only call */
1711 if(target_name == NULL) {
1712 sprintf(dummy_string,"cifs%x",pSMB->hdr.Mid);
1713 len_of_str = cifsConvertToUCS((__le16 *)rename_info->target_name,
1714 dummy_string, 24, nls_codepage, remap);
1716 len_of_str = cifsConvertToUCS((__le16 *)rename_info->target_name,
1717 target_name, PATH_MAX, nls_codepage, remap);
1719 rename_info->target_name_len = cpu_to_le32(2 * len_of_str);
1720 count = 12 /* sizeof(struct set_file_rename) */ + (2 * len_of_str) + 2;
1721 byte_count += count;
1722 pSMB->DataCount = cpu_to_le16(count);
1723 pSMB->TotalDataCount = pSMB->DataCount;
1725 pSMB->InformationLevel =
1726 cpu_to_le16(SMB_SET_FILE_RENAME_INFORMATION);
1727 pSMB->Reserved4 = 0;
1728 pSMB->hdr.smb_buf_length += byte_count;
1729 pSMB->ByteCount = cpu_to_le16(byte_count);
1730 rc = SendReceive(xid, pTcon->ses, (struct smb_hdr *) pSMB,
1731 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1732 cifs_stats_inc(&pTcon->num_t2renames);
1734 cFYI(1,("Send error in Rename (by file handle) = %d", rc));
1737 cifs_buf_release(pSMB);
1739 /* Note: On -EAGAIN error only caller can retry on handle based calls
1740 since file handle passed in no longer valid */
1746 CIFSSMBCopy(const int xid, struct cifsTconInfo *tcon, const char * fromName,
1747 const __u16 target_tid, const char *toName, const int flags,
1748 const struct nls_table *nls_codepage, int remap)
1751 COPY_REQ *pSMB = NULL;
1752 COPY_RSP *pSMBr = NULL;
1754 int name_len, name_len2;
1757 cFYI(1, ("In CIFSSMBCopy"));
1759 rc = smb_init(SMB_COM_COPY, 1, tcon, (void **) &pSMB,
1764 pSMB->BufferFormat = 0x04;
1765 pSMB->Tid2 = target_tid;
1767 pSMB->Flags = cpu_to_le16(flags & COPY_TREE);
1769 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1770 name_len = cifsConvertToUCS((__le16 *) pSMB->OldFileName,
1771 fromName, PATH_MAX, nls_codepage,
1773 name_len++; /* trailing null */
1775 pSMB->OldFileName[name_len] = 0x04; /* pad */
1776 /* protocol requires ASCII signature byte on Unicode string */
1777 pSMB->OldFileName[name_len + 1] = 0x00;
1778 name_len2 = cifsConvertToUCS((__le16 *)&pSMB->OldFileName[name_len + 2],
1779 toName, PATH_MAX, nls_codepage, remap);
1780 name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
1781 name_len2 *= 2; /* convert to bytes */
1782 } else { /* BB improve the check for buffer overruns BB */
1783 name_len = strnlen(fromName, PATH_MAX);
1784 name_len++; /* trailing null */
1785 strncpy(pSMB->OldFileName, fromName, name_len);
1786 name_len2 = strnlen(toName, PATH_MAX);
1787 name_len2++; /* trailing null */
1788 pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */
1789 strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2);
1790 name_len2++; /* trailing null */
1791 name_len2++; /* signature byte */
1794 count = 1 /* 1st signature byte */ + name_len + name_len2;
1795 pSMB->hdr.smb_buf_length += count;
1796 pSMB->ByteCount = cpu_to_le16(count);
1798 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1799 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1801 cFYI(1, ("Send error in copy = %d with %d files copied",
1802 rc, le16_to_cpu(pSMBr->CopyCount)));
1805 cifs_buf_release(pSMB);
1814 CIFSUnixCreateSymLink(const int xid, struct cifsTconInfo *tcon,
1815 const char *fromName, const char *toName,
1816 const struct nls_table *nls_codepage)
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 Symlink Unix style"));
1829 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
1834 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1836 cifs_strtoUCS((__le16 *) pSMB->FileName, fromName, PATH_MAX
1837 /* find define for this maxpathcomponent */
1839 name_len++; /* trailing null */
1842 } else { /* BB improve the check for buffer overruns BB */
1843 name_len = strnlen(fromName, PATH_MAX);
1844 name_len++; /* trailing null */
1845 strncpy(pSMB->FileName, fromName, name_len);
1847 params = 6 + name_len;
1848 pSMB->MaxSetupCount = 0;
1852 pSMB->Reserved2 = 0;
1853 param_offset = offsetof(struct smb_com_transaction2_spi_req,
1854 InformationLevel) - 4;
1855 offset = param_offset + params;
1857 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
1858 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1860 cifs_strtoUCS((__le16 *) data_offset, toName, PATH_MAX
1861 /* find define for this maxpathcomponent */
1863 name_len_target++; /* trailing null */
1864 name_len_target *= 2;
1865 } else { /* BB improve the check for buffer overruns BB */
1866 name_len_target = strnlen(toName, PATH_MAX);
1867 name_len_target++; /* trailing null */
1868 strncpy(data_offset, toName, name_len_target);
1871 pSMB->MaxParameterCount = cpu_to_le16(2);
1872 /* BB find exact max on data count below from sess */
1873 pSMB->MaxDataCount = cpu_to_le16(1000);
1874 pSMB->SetupCount = 1;
1875 pSMB->Reserved3 = 0;
1876 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
1877 byte_count = 3 /* pad */ + params + name_len_target;
1878 pSMB->DataCount = cpu_to_le16(name_len_target);
1879 pSMB->ParameterCount = cpu_to_le16(params);
1880 pSMB->TotalDataCount = pSMB->DataCount;
1881 pSMB->TotalParameterCount = pSMB->ParameterCount;
1882 pSMB->ParameterOffset = cpu_to_le16(param_offset);
1883 pSMB->DataOffset = cpu_to_le16(offset);
1884 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_LINK);
1885 pSMB->Reserved4 = 0;
1886 pSMB->hdr.smb_buf_length += byte_count;
1887 pSMB->ByteCount = cpu_to_le16(byte_count);
1888 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1889 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1890 cifs_stats_inc(&tcon->num_symlinks);
1893 ("Send error in SetPathInfo (create symlink) = %d",
1898 cifs_buf_release(pSMB);
1901 goto createSymLinkRetry;
1907 CIFSUnixCreateHardLink(const int xid, struct cifsTconInfo *tcon,
1908 const char *fromName, const char *toName,
1909 const struct nls_table *nls_codepage, int remap)
1911 TRANSACTION2_SPI_REQ *pSMB = NULL;
1912 TRANSACTION2_SPI_RSP *pSMBr = NULL;
1915 int name_len_target;
1917 int bytes_returned = 0;
1918 __u16 params, param_offset, offset, byte_count;
1920 cFYI(1, ("In Create Hard link Unix style"));
1921 createHardLinkRetry:
1922 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
1927 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1928 name_len = cifsConvertToUCS((__le16 *) pSMB->FileName, toName,
1929 PATH_MAX, nls_codepage, remap);
1930 name_len++; /* trailing null */
1933 } else { /* BB improve the check for buffer overruns BB */
1934 name_len = strnlen(toName, PATH_MAX);
1935 name_len++; /* trailing null */
1936 strncpy(pSMB->FileName, toName, name_len);
1938 params = 6 + name_len;
1939 pSMB->MaxSetupCount = 0;
1943 pSMB->Reserved2 = 0;
1944 param_offset = offsetof(struct smb_com_transaction2_spi_req,
1945 InformationLevel) - 4;
1946 offset = param_offset + params;
1948 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
1949 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1951 cifsConvertToUCS((__le16 *) data_offset, fromName, PATH_MAX,
1952 nls_codepage, remap);
1953 name_len_target++; /* trailing null */
1954 name_len_target *= 2;
1955 } else { /* BB improve the check for buffer overruns BB */
1956 name_len_target = strnlen(fromName, PATH_MAX);
1957 name_len_target++; /* trailing null */
1958 strncpy(data_offset, fromName, name_len_target);
1961 pSMB->MaxParameterCount = cpu_to_le16(2);
1962 /* BB find exact max on data count below from sess*/
1963 pSMB->MaxDataCount = cpu_to_le16(1000);
1964 pSMB->SetupCount = 1;
1965 pSMB->Reserved3 = 0;
1966 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
1967 byte_count = 3 /* pad */ + params + name_len_target;
1968 pSMB->ParameterCount = cpu_to_le16(params);
1969 pSMB->TotalParameterCount = pSMB->ParameterCount;
1970 pSMB->DataCount = cpu_to_le16(name_len_target);
1971 pSMB->TotalDataCount = pSMB->DataCount;
1972 pSMB->ParameterOffset = cpu_to_le16(param_offset);
1973 pSMB->DataOffset = cpu_to_le16(offset);
1974 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_HLINK);
1975 pSMB->Reserved4 = 0;
1976 pSMB->hdr.smb_buf_length += byte_count;
1977 pSMB->ByteCount = cpu_to_le16(byte_count);
1978 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1979 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1980 cifs_stats_inc(&tcon->num_hardlinks);
1982 cFYI(1, ("Send error in SetPathInfo (hard link) = %d", rc));
1985 cifs_buf_release(pSMB);
1987 goto createHardLinkRetry;
1993 CIFSCreateHardLink(const int xid, struct cifsTconInfo *tcon,
1994 const char *fromName, const char *toName,
1995 const struct nls_table *nls_codepage, int remap)
1998 NT_RENAME_REQ *pSMB = NULL;
1999 RENAME_RSP *pSMBr = NULL;
2001 int name_len, name_len2;
2004 cFYI(1, ("In CIFSCreateHardLink"));
2005 winCreateHardLinkRetry:
2007 rc = smb_init(SMB_COM_NT_RENAME, 4, tcon, (void **) &pSMB,
2012 pSMB->SearchAttributes =
2013 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
2015 pSMB->Flags = cpu_to_le16(CREATE_HARD_LINK);
2016 pSMB->ClusterCount = 0;
2018 pSMB->BufferFormat = 0x04;
2020 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2022 cifsConvertToUCS((__le16 *) pSMB->OldFileName, fromName,
2023 PATH_MAX, nls_codepage, remap);
2024 name_len++; /* trailing null */
2026 pSMB->OldFileName[name_len] = 0; /* pad */
2027 pSMB->OldFileName[name_len + 1] = 0x04;
2029 cifsConvertToUCS((__le16 *)&pSMB->OldFileName[name_len + 2],
2030 toName, PATH_MAX, nls_codepage, remap);
2031 name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
2032 name_len2 *= 2; /* convert to bytes */
2033 } else { /* BB improve the check for buffer overruns BB */
2034 name_len = strnlen(fromName, PATH_MAX);
2035 name_len++; /* trailing null */
2036 strncpy(pSMB->OldFileName, fromName, name_len);
2037 name_len2 = strnlen(toName, PATH_MAX);
2038 name_len2++; /* trailing null */
2039 pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */
2040 strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2);
2041 name_len2++; /* trailing null */
2042 name_len2++; /* signature byte */
2045 count = 1 /* string type byte */ + name_len + name_len2;
2046 pSMB->hdr.smb_buf_length += count;
2047 pSMB->ByteCount = cpu_to_le16(count);
2049 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2050 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2051 cifs_stats_inc(&tcon->num_hardlinks);
2053 cFYI(1, ("Send error in hard link (NT rename) = %d", rc));
2055 cifs_buf_release(pSMB);
2057 goto winCreateHardLinkRetry;
2063 CIFSSMBUnixQuerySymLink(const int xid, struct cifsTconInfo *tcon,
2064 const unsigned char *searchName,
2065 char *symlinkinfo, const int buflen,
2066 const struct nls_table *nls_codepage)
2068 /* SMB_QUERY_FILE_UNIX_LINK */
2069 TRANSACTION2_QPI_REQ *pSMB = NULL;
2070 TRANSACTION2_QPI_RSP *pSMBr = NULL;
2074 __u16 params, byte_count;
2076 cFYI(1, ("In QPathSymLinkInfo (Unix) for path %s", searchName));
2079 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2084 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2086 cifs_strtoUCS((__le16 *) pSMB->FileName, searchName, PATH_MAX
2087 /* find define for this maxpathcomponent */
2089 name_len++; /* trailing null */
2091 } else { /* BB improve the check for buffer overruns BB */
2092 name_len = strnlen(searchName, PATH_MAX);
2093 name_len++; /* trailing null */
2094 strncpy(pSMB->FileName, searchName, name_len);
2097 params = 2 /* level */ + 4 /* rsrvd */ + name_len /* incl null */ ;
2098 pSMB->TotalDataCount = 0;
2099 pSMB->MaxParameterCount = cpu_to_le16(2);
2100 /* BB find exact max data count below from sess structure BB */
2101 pSMB->MaxDataCount = cpu_to_le16(4000);
2102 pSMB->MaxSetupCount = 0;
2106 pSMB->Reserved2 = 0;
2107 pSMB->ParameterOffset = cpu_to_le16(offsetof(
2108 struct smb_com_transaction2_qpi_req ,InformationLevel) - 4);
2109 pSMB->DataCount = 0;
2110 pSMB->DataOffset = 0;
2111 pSMB->SetupCount = 1;
2112 pSMB->Reserved3 = 0;
2113 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
2114 byte_count = params + 1 /* pad */ ;
2115 pSMB->TotalParameterCount = cpu_to_le16(params);
2116 pSMB->ParameterCount = pSMB->TotalParameterCount;
2117 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_LINK);
2118 pSMB->Reserved4 = 0;
2119 pSMB->hdr.smb_buf_length += byte_count;
2120 pSMB->ByteCount = cpu_to_le16(byte_count);
2122 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2123 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2125 cFYI(1, ("Send error in QuerySymLinkInfo = %d", rc));
2127 /* decode response */
2129 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
2130 if (rc || (pSMBr->ByteCount < 2))
2131 /* BB also check enough total bytes returned */
2132 rc = -EIO; /* bad smb */
2134 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
2135 __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
2137 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
2138 name_len = UniStrnlen((wchar_t *) ((char *)
2139 &pSMBr->hdr.Protocol +data_offset),
2140 min_t(const int, buflen,count) / 2);
2141 /* BB FIXME investigate remapping reserved chars here */
2142 cifs_strfromUCS_le(symlinkinfo,
2143 (__le16 *) ((char *)&pSMBr->hdr.Protocol +
2145 name_len, nls_codepage);
2147 strncpy(symlinkinfo,
2148 (char *) &pSMBr->hdr.Protocol +
2150 min_t(const int, buflen, count));
2152 symlinkinfo[buflen] = 0;
2153 /* just in case so calling code does not go off the end of buffer */
2156 cifs_buf_release(pSMB);
2158 goto querySymLinkRetry;
2162 /* Initialize NT TRANSACT SMB into small smb request buffer.
2163 This assumes that all NT TRANSACTS that we init here have
2164 total parm and data under about 400 bytes (to fit in small cifs
2165 buffer size), which is the case so far, it easily fits. NB:
2166 Setup words themselves and ByteCount
2167 MaxSetupCount (size of returned setup area) and
2168 MaxParameterCount (returned parms size) must be set by caller */
2170 smb_init_ntransact(const __u16 sub_command, const int setup_count,
2171 const int parm_len, struct cifsTconInfo *tcon,
2176 struct smb_com_ntransact_req * pSMB;
2178 rc = small_smb_init(SMB_COM_NT_TRANSACT, 19 + setup_count, tcon,
2182 *ret_buf = (void *)pSMB;
2184 pSMB->TotalParameterCount = cpu_to_le32(parm_len);
2185 pSMB->TotalDataCount = 0;
2186 pSMB->MaxDataCount = cpu_to_le32((tcon->ses->server->maxBuf -
2187 MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
2188 pSMB->ParameterCount = pSMB->TotalParameterCount;
2189 pSMB->DataCount = pSMB->TotalDataCount;
2190 temp_offset = offsetof(struct smb_com_ntransact_req, Parms) +
2191 (setup_count * 2) - 4 /* for rfc1001 length itself */;
2192 pSMB->ParameterOffset = cpu_to_le32(temp_offset);
2193 pSMB->DataOffset = cpu_to_le32(temp_offset + parm_len);
2194 pSMB->SetupCount = setup_count; /* no need to le convert byte fields */
2195 pSMB->SubCommand = cpu_to_le16(sub_command);
2200 validate_ntransact(char * buf, char ** ppparm, char ** ppdata,
2201 int * pdatalen, int * pparmlen)
2204 __u32 data_count, data_offset, parm_count, parm_offset;
2205 struct smb_com_ntransact_rsp * pSMBr;
2210 pSMBr = (struct smb_com_ntransact_rsp *)buf;
2212 /* ByteCount was converted from little endian in SendReceive */
2213 end_of_smb = 2 /* sizeof byte count */ + pSMBr->ByteCount +
2214 (char *)&pSMBr->ByteCount;
2217 data_offset = le32_to_cpu(pSMBr->DataOffset);
2218 data_count = le32_to_cpu(pSMBr->DataCount);
2219 parm_offset = le32_to_cpu(pSMBr->ParameterOffset);
2220 parm_count = le32_to_cpu(pSMBr->ParameterCount);
2222 *ppparm = (char *)&pSMBr->hdr.Protocol + parm_offset;
2223 *ppdata = (char *)&pSMBr->hdr.Protocol + data_offset;
2225 /* should we also check that parm and data areas do not overlap? */
2226 if(*ppparm > end_of_smb) {
2227 cFYI(1,("parms start after end of smb"));
2229 } else if(parm_count + *ppparm > end_of_smb) {
2230 cFYI(1,("parm end after end of smb"));
2232 } else if(*ppdata > end_of_smb) {
2233 cFYI(1,("data starts after end of smb"));
2235 } else if(data_count + *ppdata > end_of_smb) {
2236 cFYI(1,("data %p + count %d (%p) ends after end of smb %p start %p",
2237 *ppdata, data_count, (data_count + *ppdata), end_of_smb, pSMBr)); /* BB FIXME */
2239 } else if(parm_count + data_count > pSMBr->ByteCount) {
2240 cFYI(1,("parm count and data count larger than SMB"));
2247 CIFSSMBQueryReparseLinkInfo(const int xid, struct cifsTconInfo *tcon,
2248 const unsigned char *searchName,
2249 char *symlinkinfo, const int buflen,__u16 fid,
2250 const struct nls_table *nls_codepage)
2255 struct smb_com_transaction_ioctl_req * pSMB;
2256 struct smb_com_transaction_ioctl_rsp * pSMBr;
2258 cFYI(1, ("In Windows reparse style QueryLink for path %s", searchName));
2259 rc = smb_init(SMB_COM_NT_TRANSACT, 23, tcon, (void **) &pSMB,
2264 pSMB->TotalParameterCount = 0 ;
2265 pSMB->TotalDataCount = 0;
2266 pSMB->MaxParameterCount = cpu_to_le32(2);
2267 /* BB find exact data count max from sess structure BB */
2268 pSMB->MaxDataCount = cpu_to_le32((tcon->ses->server->maxBuf -
2269 MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
2270 pSMB->MaxSetupCount = 4;
2272 pSMB->ParameterOffset = 0;
2273 pSMB->DataCount = 0;
2274 pSMB->DataOffset = 0;
2275 pSMB->SetupCount = 4;
2276 pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_IOCTL);
2277 pSMB->ParameterCount = pSMB->TotalParameterCount;
2278 pSMB->FunctionCode = cpu_to_le32(FSCTL_GET_REPARSE_POINT);
2279 pSMB->IsFsctl = 1; /* FSCTL */
2280 pSMB->IsRootFlag = 0;
2281 pSMB->Fid = fid; /* file handle always le */
2282 pSMB->ByteCount = 0;
2284 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2285 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2287 cFYI(1, ("Send error in QueryReparseLinkInfo = %d", rc));
2288 } else { /* decode response */
2289 __u32 data_offset = le32_to_cpu(pSMBr->DataOffset);
2290 __u32 data_count = le32_to_cpu(pSMBr->DataCount);
2291 if ((pSMBr->ByteCount < 2) || (data_offset > 512))
2292 /* BB also check enough total bytes returned */
2293 rc = -EIO; /* bad smb */
2295 if(data_count && (data_count < 2048)) {
2296 char * end_of_smb = 2 /* sizeof byte count */ +
2298 (char *)&pSMBr->ByteCount;
2300 struct reparse_data * reparse_buf = (struct reparse_data *)
2301 ((char *)&pSMBr->hdr.Protocol + data_offset);
2302 if((char*)reparse_buf >= end_of_smb) {
2306 if((reparse_buf->LinkNamesBuf +
2307 reparse_buf->TargetNameOffset +
2308 reparse_buf->TargetNameLen) >
2310 cFYI(1,("reparse buf extended beyond SMB"));
2315 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
2316 name_len = UniStrnlen((wchar_t *)
2317 (reparse_buf->LinkNamesBuf +
2318 reparse_buf->TargetNameOffset),
2319 min(buflen/2, reparse_buf->TargetNameLen / 2));
2320 cifs_strfromUCS_le(symlinkinfo,
2321 (__le16 *) (reparse_buf->LinkNamesBuf +
2322 reparse_buf->TargetNameOffset),
2323 name_len, nls_codepage);
2324 } else { /* ASCII names */
2325 strncpy(symlinkinfo,reparse_buf->LinkNamesBuf +
2326 reparse_buf->TargetNameOffset,
2327 min_t(const int, buflen, reparse_buf->TargetNameLen));
2331 cFYI(1,("Invalid return data count on get reparse info ioctl"));
2333 symlinkinfo[buflen] = 0; /* just in case so the caller
2334 does not go off the end of the buffer */
2335 cFYI(1,("readlink result - %s",symlinkinfo));
2339 cifs_buf_release(pSMB);
2341 /* Note: On -EAGAIN error only caller can retry on handle based calls
2342 since file handle passed in no longer valid */
2347 #ifdef CONFIG_CIFS_POSIX
2349 /*Convert an Access Control Entry from wire format to local POSIX xattr format*/
2350 static void cifs_convert_ace(posix_acl_xattr_entry * ace, struct cifs_posix_ace * cifs_ace)
2352 /* u8 cifs fields do not need le conversion */
2353 ace->e_perm = cpu_to_le16(cifs_ace->cifs_e_perm);
2354 ace->e_tag = cpu_to_le16(cifs_ace->cifs_e_tag);
2355 ace->e_id = cpu_to_le32(le64_to_cpu(cifs_ace->cifs_uid));
2356 /* cFYI(1,("perm %d tag %d id %d",ace->e_perm,ace->e_tag,ace->e_id)); */
2361 /* Convert ACL from CIFS POSIX wire format to local Linux POSIX ACL xattr */
2362 static int cifs_copy_posix_acl(char * trgt,char * src, const int buflen,
2363 const int acl_type,const int size_of_data_area)
2368 struct cifs_posix_ace * pACE;
2369 struct cifs_posix_acl * cifs_acl = (struct cifs_posix_acl *)src;
2370 posix_acl_xattr_header * local_acl = (posix_acl_xattr_header *)trgt;
2372 if (le16_to_cpu(cifs_acl->version) != CIFS_ACL_VERSION)
2375 if(acl_type & ACL_TYPE_ACCESS) {
2376 count = le16_to_cpu(cifs_acl->access_entry_count);
2377 pACE = &cifs_acl->ace_array[0];
2378 size = sizeof(struct cifs_posix_acl);
2379 size += sizeof(struct cifs_posix_ace) * count;
2380 /* check if we would go beyond end of SMB */
2381 if(size_of_data_area < size) {
2382 cFYI(1,("bad CIFS POSIX ACL size %d vs. %d",size_of_data_area,size));
2385 } else if(acl_type & ACL_TYPE_DEFAULT) {
2386 count = le16_to_cpu(cifs_acl->access_entry_count);
2387 size = sizeof(struct cifs_posix_acl);
2388 size += sizeof(struct cifs_posix_ace) * count;
2389 /* skip past access ACEs to get to default ACEs */
2390 pACE = &cifs_acl->ace_array[count];
2391 count = le16_to_cpu(cifs_acl->default_entry_count);
2392 size += sizeof(struct cifs_posix_ace) * count;
2393 /* check if we would go beyond end of SMB */
2394 if(size_of_data_area < size)
2401 size = posix_acl_xattr_size(count);
2402 if((buflen == 0) || (local_acl == NULL)) {
2403 /* used to query ACL EA size */
2404 } else if(size > buflen) {
2406 } else /* buffer big enough */ {
2407 local_acl->a_version = cpu_to_le32(POSIX_ACL_XATTR_VERSION);
2408 for(i = 0;i < count ;i++) {
2409 cifs_convert_ace(&local_acl->a_entries[i],pACE);
2416 static __u16 convert_ace_to_cifs_ace(struct cifs_posix_ace * cifs_ace,
2417 const posix_acl_xattr_entry * local_ace)
2419 __u16 rc = 0; /* 0 = ACL converted ok */
2421 cifs_ace->cifs_e_perm = le16_to_cpu(local_ace->e_perm);
2422 cifs_ace->cifs_e_tag = le16_to_cpu(local_ace->e_tag);
2423 /* BB is there a better way to handle the large uid? */
2424 if(local_ace->e_id == cpu_to_le32(-1)) {
2425 /* Probably no need to le convert -1 on any arch but can not hurt */
2426 cifs_ace->cifs_uid = cpu_to_le64(-1);
2428 cifs_ace->cifs_uid = cpu_to_le64(le32_to_cpu(local_ace->e_id));
2429 /*cFYI(1,("perm %d tag %d id %d",ace->e_perm,ace->e_tag,ace->e_id));*/
2433 /* Convert ACL from local Linux POSIX xattr to CIFS POSIX ACL wire format */
2434 static __u16 ACL_to_cifs_posix(char * parm_data,const char * pACL,const int buflen,
2438 struct cifs_posix_acl * cifs_acl = (struct cifs_posix_acl *)parm_data;
2439 posix_acl_xattr_header * local_acl = (posix_acl_xattr_header *)pACL;
2443 if((buflen == 0) || (pACL == NULL) || (cifs_acl == NULL))
2446 count = posix_acl_xattr_count((size_t)buflen);
2447 cFYI(1,("setting acl with %d entries from buf of length %d and version of %d",
2448 count, buflen, le32_to_cpu(local_acl->a_version)));
2449 if(le32_to_cpu(local_acl->a_version) != 2) {
2450 cFYI(1,("unknown POSIX ACL version %d",
2451 le32_to_cpu(local_acl->a_version)));
2454 cifs_acl->version = cpu_to_le16(1);
2455 if(acl_type == ACL_TYPE_ACCESS)
2456 cifs_acl->access_entry_count = cpu_to_le16(count);
2457 else if(acl_type == ACL_TYPE_DEFAULT)
2458 cifs_acl->default_entry_count = cpu_to_le16(count);
2460 cFYI(1,("unknown ACL type %d",acl_type));
2463 for(i=0;i<count;i++) {
2464 rc = convert_ace_to_cifs_ace(&cifs_acl->ace_array[i],
2465 &local_acl->a_entries[i]);
2467 /* ACE not converted */
2472 rc = (__u16)(count * sizeof(struct cifs_posix_ace));
2473 rc += sizeof(struct cifs_posix_acl);
2474 /* BB add check to make sure ACL does not overflow SMB */
2480 CIFSSMBGetPosixACL(const int xid, struct cifsTconInfo *tcon,
2481 const unsigned char *searchName,
2482 char *acl_inf, const int buflen, const int acl_type,
2483 const struct nls_table *nls_codepage, int remap)
2485 /* SMB_QUERY_POSIX_ACL */
2486 TRANSACTION2_QPI_REQ *pSMB = NULL;
2487 TRANSACTION2_QPI_RSP *pSMBr = NULL;
2491 __u16 params, byte_count;
2493 cFYI(1, ("In GetPosixACL (Unix) for path %s", searchName));
2496 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2501 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2503 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
2504 PATH_MAX, nls_codepage, remap);
2505 name_len++; /* trailing null */
2507 pSMB->FileName[name_len] = 0;
2508 pSMB->FileName[name_len+1] = 0;
2509 } else { /* BB improve the check for buffer overruns BB */
2510 name_len = strnlen(searchName, PATH_MAX);
2511 name_len++; /* trailing null */
2512 strncpy(pSMB->FileName, searchName, name_len);
2515 params = 2 /* level */ + 4 /* rsrvd */ + name_len /* incl null */ ;
2516 pSMB->TotalDataCount = 0;
2517 pSMB->MaxParameterCount = cpu_to_le16(2);
2518 /* BB find exact max data count below from sess structure BB */
2519 pSMB->MaxDataCount = cpu_to_le16(4000);
2520 pSMB->MaxSetupCount = 0;
2524 pSMB->Reserved2 = 0;
2525 pSMB->ParameterOffset = cpu_to_le16(
2526 offsetof(struct smb_com_transaction2_qpi_req ,InformationLevel) - 4);
2527 pSMB->DataCount = 0;
2528 pSMB->DataOffset = 0;
2529 pSMB->SetupCount = 1;
2530 pSMB->Reserved3 = 0;
2531 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
2532 byte_count = params + 1 /* pad */ ;
2533 pSMB->TotalParameterCount = cpu_to_le16(params);
2534 pSMB->ParameterCount = pSMB->TotalParameterCount;
2535 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_POSIX_ACL);
2536 pSMB->Reserved4 = 0;
2537 pSMB->hdr.smb_buf_length += byte_count;
2538 pSMB->ByteCount = cpu_to_le16(byte_count);
2540 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2541 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2542 cifs_stats_inc(&tcon->num_acl_get);
2544 cFYI(1, ("Send error in Query POSIX ACL = %d", rc));
2546 /* decode response */
2548 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
2549 if (rc || (pSMBr->ByteCount < 2))
2550 /* BB also check enough total bytes returned */
2551 rc = -EIO; /* bad smb */
2553 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
2554 __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
2555 rc = cifs_copy_posix_acl(acl_inf,
2556 (char *)&pSMBr->hdr.Protocol+data_offset,
2557 buflen,acl_type,count);
2560 cifs_buf_release(pSMB);
2567 CIFSSMBSetPosixACL(const int xid, struct cifsTconInfo *tcon,
2568 const unsigned char *fileName,
2569 const char *local_acl, const int buflen,
2571 const struct nls_table *nls_codepage, int remap)
2573 struct smb_com_transaction2_spi_req *pSMB = NULL;
2574 struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
2578 int bytes_returned = 0;
2579 __u16 params, byte_count, data_count, param_offset, offset;
2581 cFYI(1, ("In SetPosixACL (Unix) for path %s", fileName));
2583 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2587 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2589 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
2590 PATH_MAX, nls_codepage, remap);
2591 name_len++; /* trailing null */
2593 } else { /* BB improve the check for buffer overruns BB */
2594 name_len = strnlen(fileName, PATH_MAX);
2595 name_len++; /* trailing null */
2596 strncpy(pSMB->FileName, fileName, name_len);
2598 params = 6 + name_len;
2599 pSMB->MaxParameterCount = cpu_to_le16(2);
2600 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB size from sess */
2601 pSMB->MaxSetupCount = 0;
2605 pSMB->Reserved2 = 0;
2606 param_offset = offsetof(struct smb_com_transaction2_spi_req,
2607 InformationLevel) - 4;
2608 offset = param_offset + params;
2609 parm_data = ((char *) &pSMB->hdr.Protocol) + offset;
2610 pSMB->ParameterOffset = cpu_to_le16(param_offset);
2612 /* convert to on the wire format for POSIX ACL */
2613 data_count = ACL_to_cifs_posix(parm_data,local_acl,buflen,acl_type);
2615 if(data_count == 0) {
2617 goto setACLerrorExit;
2619 pSMB->DataOffset = cpu_to_le16(offset);
2620 pSMB->SetupCount = 1;
2621 pSMB->Reserved3 = 0;
2622 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
2623 pSMB->InformationLevel = cpu_to_le16(SMB_SET_POSIX_ACL);
2624 byte_count = 3 /* pad */ + params + data_count;
2625 pSMB->DataCount = cpu_to_le16(data_count);
2626 pSMB->TotalDataCount = pSMB->DataCount;
2627 pSMB->ParameterCount = cpu_to_le16(params);
2628 pSMB->TotalParameterCount = pSMB->ParameterCount;
2629 pSMB->Reserved4 = 0;
2630 pSMB->hdr.smb_buf_length += byte_count;
2631 pSMB->ByteCount = cpu_to_le16(byte_count);
2632 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2633 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2635 cFYI(1, ("Set POSIX ACL returned %d", rc));
2639 cifs_buf_release(pSMB);
2645 /* BB fix tabs in this function FIXME BB */
2647 CIFSGetExtAttr(const int xid, struct cifsTconInfo *tcon,
2648 const int netfid, __u64 * pExtAttrBits, __u64 *pMask)
2651 struct smb_t2_qfi_req *pSMB = NULL;
2652 struct smb_t2_qfi_rsp *pSMBr = NULL;
2654 __u16 params, byte_count;
2656 cFYI(1,("In GetExtAttr"));
2661 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2666 params = 2 /* level */ +2 /* fid */;
2667 pSMB->t2.TotalDataCount = 0;
2668 pSMB->t2.MaxParameterCount = cpu_to_le16(4);
2669 /* BB find exact max data count below from sess structure BB */
2670 pSMB->t2.MaxDataCount = cpu_to_le16(4000);
2671 pSMB->t2.MaxSetupCount = 0;
2672 pSMB->t2.Reserved = 0;
2674 pSMB->t2.Timeout = 0;
2675 pSMB->t2.Reserved2 = 0;
2676 pSMB->t2.ParameterOffset = cpu_to_le16(offsetof(struct smb_t2_qfi_req,
2678 pSMB->t2.DataCount = 0;
2679 pSMB->t2.DataOffset = 0;
2680 pSMB->t2.SetupCount = 1;
2681 pSMB->t2.Reserved3 = 0;
2682 pSMB->t2.SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION);
2683 byte_count = params + 1 /* pad */ ;
2684 pSMB->t2.TotalParameterCount = cpu_to_le16(params);
2685 pSMB->t2.ParameterCount = pSMB->t2.TotalParameterCount;
2686 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_ATTR_FLAGS);
2689 pSMB->hdr.smb_buf_length += byte_count;
2690 pSMB->t2.ByteCount = cpu_to_le16(byte_count);
2692 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2693 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2695 cFYI(1, ("error %d in GetExtAttr", rc));
2697 /* decode response */
2698 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
2699 if (rc || (pSMBr->ByteCount < 2))
2700 /* BB also check enough total bytes returned */
2701 /* If rc should we check for EOPNOSUPP and
2702 disable the srvino flag? or in caller? */
2703 rc = -EIO; /* bad smb */
2705 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
2706 __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
2707 struct file_chattr_info * pfinfo;
2708 /* BB Do we need a cast or hash here ? */
2710 cFYI(1, ("Illegal size ret in GetExtAttr"));
2714 pfinfo = (struct file_chattr_info *)
2715 (data_offset + (char *) &pSMBr->hdr.Protocol);
2716 *pExtAttrBits = le64_to_cpu(pfinfo->mode);
2717 *pMask = le64_to_cpu(pfinfo->mask);
2721 cifs_buf_release(pSMB);
2723 goto GetExtAttrRetry;
2728 #endif /* CONFIG_POSIX */
2731 /* security id for everyone */
2732 const struct cifs_sid sid_everyone = {1, 1, {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0}};
2734 const struct cifs_sid sid_user = {1, 2 , {0, 0, 0, 0, 0, 5}, {32, 545, 0, 0}};
2736 /* Convert CIFS ACL to POSIX form */
2737 static int parse_sec_desc(struct cifs_sid * psec_desc, int acl_len)
2742 /* Get Security Descriptor (by handle) from remote server for a file or dir */
2744 CIFSSMBGetCIFSACL(const int xid, struct cifsTconInfo *tcon, __u16 fid,
2745 /* BB fix up return info */ char *acl_inf, const int buflen,
2746 const int acl_type /* ACCESS/DEFAULT not sure implication */)
2750 QUERY_SEC_DESC_REQ * pSMB;
2753 cFYI(1, ("GetCifsACL"));
2755 rc = smb_init_ntransact(NT_TRANSACT_QUERY_SECURITY_DESC, 0,
2756 8 /* parm len */, tcon, (void **) &pSMB);
2760 pSMB->MaxParameterCount = cpu_to_le32(4);
2761 /* BB TEST with big acls that might need to be e.g. larger than 16K */
2762 pSMB->MaxSetupCount = 0;
2763 pSMB->Fid = fid; /* file handle always le */
2764 pSMB->AclFlags = cpu_to_le32(CIFS_ACL_OWNER | CIFS_ACL_GROUP |
2766 pSMB->ByteCount = cpu_to_le16(11); /* 3 bytes pad + 8 bytes parm */
2767 pSMB->hdr.smb_buf_length += 11;
2768 iov[0].iov_base = (char *)pSMB;
2769 iov[0].iov_len = pSMB->hdr.smb_buf_length + 4;
2771 rc = SendReceive2(xid, tcon->ses, iov, 1 /* num iovec */, &buf_type, 0);
2772 cifs_stats_inc(&tcon->num_acl_get);
2774 cFYI(1, ("Send error in QuerySecDesc = %d", rc));
2775 } else { /* decode response */
2776 struct cifs_sid * psec_desc;
2781 struct smb_com_ntransact_rsp * pSMBr;
2783 /* validate_nttransact */
2784 rc = validate_ntransact(iov[0].iov_base, (char **)&parm,
2785 (char **)&psec_desc,
2786 &parm_len, &data_len);
2790 pSMBr = (struct smb_com_ntransact_rsp *)iov[0].iov_base;
2792 cERROR(1,("smb %p parm %p data %p",pSMBr,parm,psec_desc)); /* BB removeme BB */
2794 if (le32_to_cpu(pSMBr->ParameterCount) != 4) {
2795 rc = -EIO; /* bad smb */
2799 /* BB check that data area is minimum length and as big as acl_len */
2801 acl_len = le32_to_cpu(*(__le32 *)parm);
2802 /* BB check if(acl_len > bufsize) */
2804 parse_sec_desc(psec_desc, acl_len);
2807 if(buf_type == CIFS_SMALL_BUFFER)
2808 cifs_small_buf_release(iov[0].iov_base);
2809 else if(buf_type == CIFS_LARGE_BUFFER)
2810 cifs_buf_release(iov[0].iov_base);
2811 /* cifs_small_buf_release(pSMB); */ /* Freed earlier now in SendReceive2 */
2816 /* Legacy Query Path Information call for lookup to old servers such
2818 int SMBQueryInformation(const int xid, struct cifsTconInfo *tcon,
2819 const unsigned char *searchName,
2820 FILE_ALL_INFO * pFinfo,
2821 const struct nls_table *nls_codepage, int remap)
2823 QUERY_INFORMATION_REQ * pSMB;
2824 QUERY_INFORMATION_RSP * pSMBr;
2829 cFYI(1, ("In SMBQPath path %s", searchName));
2831 rc = smb_init(SMB_COM_QUERY_INFORMATION, 0, tcon, (void **) &pSMB,
2836 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2838 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
2839 PATH_MAX, nls_codepage, remap);
2840 name_len++; /* trailing null */
2843 name_len = strnlen(searchName, PATH_MAX);
2844 name_len++; /* trailing null */
2845 strncpy(pSMB->FileName, searchName, name_len);
2847 pSMB->BufferFormat = 0x04;
2848 name_len++; /* account for buffer type byte */
2849 pSMB->hdr.smb_buf_length += (__u16) name_len;
2850 pSMB->ByteCount = cpu_to_le16(name_len);
2852 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2853 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2855 cFYI(1, ("Send error in QueryInfo = %d", rc));
2856 } else if (pFinfo) { /* decode response */
2857 memset(pFinfo, 0, sizeof(FILE_ALL_INFO));
2858 pFinfo->AllocationSize =
2859 cpu_to_le64(le32_to_cpu(pSMBr->size));
2860 pFinfo->EndOfFile = pFinfo->AllocationSize;
2861 pFinfo->Attributes =
2862 cpu_to_le32(le16_to_cpu(pSMBr->attr));
2864 rc = -EIO; /* bad buffer passed in */
2866 cifs_buf_release(pSMB);
2878 CIFSSMBQPathInfo(const int xid, struct cifsTconInfo *tcon,
2879 const unsigned char *searchName,
2880 FILE_ALL_INFO * pFindData,
2881 const struct nls_table *nls_codepage, int remap)
2883 /* level 263 SMB_QUERY_FILE_ALL_INFO */
2884 TRANSACTION2_QPI_REQ *pSMB = NULL;
2885 TRANSACTION2_QPI_RSP *pSMBr = NULL;
2889 __u16 params, byte_count;
2891 /* cFYI(1, ("In QPathInfo path %s", searchName)); */
2893 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2898 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2900 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
2901 PATH_MAX, nls_codepage, remap);
2902 name_len++; /* trailing null */
2904 } else { /* BB improve the check for buffer overruns BB */
2905 name_len = strnlen(searchName, PATH_MAX);
2906 name_len++; /* trailing null */
2907 strncpy(pSMB->FileName, searchName, name_len);
2910 params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */ ;
2911 pSMB->TotalDataCount = 0;
2912 pSMB->MaxParameterCount = cpu_to_le16(2);
2913 pSMB->MaxDataCount = cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
2914 pSMB->MaxSetupCount = 0;
2918 pSMB->Reserved2 = 0;
2919 pSMB->ParameterOffset = cpu_to_le16(offsetof(
2920 struct smb_com_transaction2_qpi_req ,InformationLevel) - 4);
2921 pSMB->DataCount = 0;
2922 pSMB->DataOffset = 0;
2923 pSMB->SetupCount = 1;
2924 pSMB->Reserved3 = 0;
2925 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
2926 byte_count = params + 1 /* pad */ ;
2927 pSMB->TotalParameterCount = cpu_to_le16(params);
2928 pSMB->ParameterCount = pSMB->TotalParameterCount;
2929 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_ALL_INFO);
2930 pSMB->Reserved4 = 0;
2931 pSMB->hdr.smb_buf_length += byte_count;
2932 pSMB->ByteCount = cpu_to_le16(byte_count);
2934 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2935 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2937 cFYI(1, ("Send error in QPathInfo = %d", rc));
2938 } else { /* decode response */
2939 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
2941 if (rc || (pSMBr->ByteCount < 40))
2942 rc = -EIO; /* bad smb */
2943 else if (pFindData){
2944 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
2945 memcpy((char *) pFindData,
2946 (char *) &pSMBr->hdr.Protocol +
2947 data_offset, sizeof (FILE_ALL_INFO));
2951 cifs_buf_release(pSMB);
2953 goto QPathInfoRetry;
2959 CIFSSMBUnixQPathInfo(const int xid, struct cifsTconInfo *tcon,
2960 const unsigned char *searchName,
2961 FILE_UNIX_BASIC_INFO * pFindData,
2962 const struct nls_table *nls_codepage, int remap)
2964 /* SMB_QUERY_FILE_UNIX_BASIC */
2965 TRANSACTION2_QPI_REQ *pSMB = NULL;
2966 TRANSACTION2_QPI_RSP *pSMBr = NULL;
2968 int bytes_returned = 0;
2970 __u16 params, byte_count;
2972 cFYI(1, ("In QPathInfo (Unix) the path %s", searchName));
2974 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2979 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2981 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
2982 PATH_MAX, nls_codepage, remap);
2983 name_len++; /* trailing null */
2985 } else { /* BB improve the check for buffer overruns BB */
2986 name_len = strnlen(searchName, PATH_MAX);
2987 name_len++; /* trailing null */
2988 strncpy(pSMB->FileName, searchName, name_len);
2991 params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */ ;
2992 pSMB->TotalDataCount = 0;
2993 pSMB->MaxParameterCount = cpu_to_le16(2);
2994 /* BB find exact max SMB PDU from sess structure BB */
2995 pSMB->MaxDataCount = cpu_to_le16(4000);
2996 pSMB->MaxSetupCount = 0;
3000 pSMB->Reserved2 = 0;
3001 pSMB->ParameterOffset = cpu_to_le16(offsetof(
3002 struct smb_com_transaction2_qpi_req ,InformationLevel) - 4);
3003 pSMB->DataCount = 0;
3004 pSMB->DataOffset = 0;
3005 pSMB->SetupCount = 1;
3006 pSMB->Reserved3 = 0;
3007 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
3008 byte_count = params + 1 /* pad */ ;
3009 pSMB->TotalParameterCount = cpu_to_le16(params);
3010 pSMB->ParameterCount = pSMB->TotalParameterCount;
3011 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC);
3012 pSMB->Reserved4 = 0;
3013 pSMB->hdr.smb_buf_length += byte_count;
3014 pSMB->ByteCount = cpu_to_le16(byte_count);
3016 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3017 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3019 cFYI(1, ("Send error in QPathInfo = %d", rc));
3020 } else { /* decode response */
3021 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3023 if (rc || (pSMBr->ByteCount < sizeof(FILE_UNIX_BASIC_INFO))) {
3024 rc = -EIO; /* bad smb */
3026 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3027 memcpy((char *) pFindData,
3028 (char *) &pSMBr->hdr.Protocol +
3030 sizeof (FILE_UNIX_BASIC_INFO));
3033 cifs_buf_release(pSMB);
3035 goto UnixQPathInfoRetry;
3040 #if 0 /* function unused at present */
3041 int CIFSFindSingle(const int xid, struct cifsTconInfo *tcon,
3042 const char *searchName, FILE_ALL_INFO * findData,
3043 const struct nls_table *nls_codepage)
3045 /* level 257 SMB_ */
3046 TRANSACTION2_FFIRST_REQ *pSMB = NULL;
3047 TRANSACTION2_FFIRST_RSP *pSMBr = NULL;
3051 __u16 params, byte_count;
3053 cFYI(1, ("In FindUnique"));
3055 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3060 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3062 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName, PATH_MAX
3063 /* find define for this maxpathcomponent */
3065 name_len++; /* trailing null */
3067 } else { /* BB improve the check for buffer overruns BB */
3068 name_len = strnlen(searchName, PATH_MAX);
3069 name_len++; /* trailing null */
3070 strncpy(pSMB->FileName, searchName, name_len);
3073 params = 12 + name_len /* includes null */ ;
3074 pSMB->TotalDataCount = 0; /* no EAs */
3075 pSMB->MaxParameterCount = cpu_to_le16(2);
3076 pSMB->MaxDataCount = cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
3077 pSMB->MaxSetupCount = 0;
3081 pSMB->Reserved2 = 0;
3082 pSMB->ParameterOffset = cpu_to_le16(
3083 offsetof(struct smb_com_transaction2_ffirst_req,InformationLevel) - 4);
3084 pSMB->DataCount = 0;
3085 pSMB->DataOffset = 0;
3086 pSMB->SetupCount = 1; /* one byte, no need to le convert */
3087 pSMB->Reserved3 = 0;
3088 pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_FIRST);
3089 byte_count = params + 1 /* pad */ ;
3090 pSMB->TotalParameterCount = cpu_to_le16(params);
3091 pSMB->ParameterCount = pSMB->TotalParameterCount;
3092 pSMB->SearchAttributes =
3093 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
3095 pSMB->SearchCount = cpu_to_le16(16); /* BB increase */
3096 pSMB->SearchFlags = cpu_to_le16(1);
3097 pSMB->InformationLevel = cpu_to_le16(SMB_FIND_FILE_DIRECTORY_INFO);
3098 pSMB->SearchStorageType = 0; /* BB what should we set this to? BB */
3099 pSMB->hdr.smb_buf_length += byte_count;
3100 pSMB->ByteCount = cpu_to_le16(byte_count);
3102 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3103 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3106 cFYI(1, ("Send error in FindFileDirInfo = %d", rc));
3107 } else { /* decode response */
3108 cifs_stats_inc(&tcon->num_ffirst);
3112 cifs_buf_release(pSMB);
3114 goto findUniqueRetry;
3118 #endif /* end unused (temporarily) function */
3120 /* xid, tcon, searchName and codepage are input parms, rest are returned */
3122 CIFSFindFirst(const int xid, struct cifsTconInfo *tcon,
3123 const char *searchName,
3124 const struct nls_table *nls_codepage,
3126 struct cifs_search_info * psrch_inf, int remap, const char dirsep)
3128 /* level 257 SMB_ */
3129 TRANSACTION2_FFIRST_REQ *pSMB = NULL;
3130 TRANSACTION2_FFIRST_RSP *pSMBr = NULL;
3131 T2_FFIRST_RSP_PARMS * parms;
3133 int bytes_returned = 0;
3135 __u16 params, byte_count;
3137 cFYI(1, ("In FindFirst for %s",searchName));
3140 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3145 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3147 cifsConvertToUCS((__le16 *) pSMB->FileName,searchName,
3148 PATH_MAX, nls_codepage, remap);
3149 /* We can not add the asterik earlier in case
3150 it got remapped to 0xF03A as if it were part of the
3151 directory name instead of a wildcard */
3153 pSMB->FileName[name_len] = dirsep;
3154 pSMB->FileName[name_len+1] = 0;
3155 pSMB->FileName[name_len+2] = '*';
3156 pSMB->FileName[name_len+3] = 0;
3157 name_len += 4; /* now the trailing null */
3158 pSMB->FileName[name_len] = 0; /* null terminate just in case */
3159 pSMB->FileName[name_len+1] = 0;
3161 } else { /* BB add check for overrun of SMB buf BB */
3162 name_len = strnlen(searchName, PATH_MAX);
3163 /* BB fix here and in unicode clause above ie
3164 if(name_len > buffersize-header)
3165 free buffer exit; BB */
3166 strncpy(pSMB->FileName, searchName, name_len);
3167 pSMB->FileName[name_len] = dirsep;
3168 pSMB->FileName[name_len+1] = '*';
3169 pSMB->FileName[name_len+2] = 0;
3173 params = 12 + name_len /* includes null */ ;
3174 pSMB->TotalDataCount = 0; /* no EAs */
3175 pSMB->MaxParameterCount = cpu_to_le16(10);
3176 pSMB->MaxDataCount = cpu_to_le16((tcon->ses->server->maxBuf -
3177 MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
3178 pSMB->MaxSetupCount = 0;
3182 pSMB->Reserved2 = 0;
3183 byte_count = params + 1 /* pad */ ;
3184 pSMB->TotalParameterCount = cpu_to_le16(params);
3185 pSMB->ParameterCount = pSMB->TotalParameterCount;
3186 pSMB->ParameterOffset = cpu_to_le16(
3187 offsetof(struct smb_com_transaction2_ffirst_req, SearchAttributes)
3189 pSMB->DataCount = 0;
3190 pSMB->DataOffset = 0;
3191 pSMB->SetupCount = 1; /* one byte, no need to make endian neutral */
3192 pSMB->Reserved3 = 0;
3193 pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_FIRST);
3194 pSMB->SearchAttributes =
3195 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
3197 pSMB->SearchCount= cpu_to_le16(CIFSMaxBufSize/sizeof(FILE_UNIX_INFO));
3198 pSMB->SearchFlags = cpu_to_le16(CIFS_SEARCH_CLOSE_AT_END |
3199 CIFS_SEARCH_RETURN_RESUME);
3200 pSMB->InformationLevel = cpu_to_le16(psrch_inf->info_level);
3202 /* BB what should we set StorageType to? Does it matter? BB */
3203 pSMB->SearchStorageType = 0;
3204 pSMB->hdr.smb_buf_length += byte_count;
3205 pSMB->ByteCount = cpu_to_le16(byte_count);
3207 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3208 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3209 cifs_stats_inc(&tcon->num_ffirst);
3211 if (rc) {/* BB add logic to retry regular search if Unix search
3212 rejected unexpectedly by server */
3213 /* BB Add code to handle unsupported level rc */
3214 cFYI(1, ("Error in FindFirst = %d", rc));
3216 cifs_buf_release(pSMB);
3218 /* BB eventually could optimize out free and realloc of buf */
3221 goto findFirstRetry;
3222 } else { /* decode response */
3223 /* BB remember to free buffer if error BB */
3224 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3226 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
3227 psrch_inf->unicode = TRUE;
3229 psrch_inf->unicode = FALSE;
3231 psrch_inf->ntwrk_buf_start = (char *)pSMBr;
3232 psrch_inf->smallBuf = 0;
3233 psrch_inf->srch_entries_start =
3234 (char *) &pSMBr->hdr.Protocol +
3235 le16_to_cpu(pSMBr->t2.DataOffset);
3236 parms = (T2_FFIRST_RSP_PARMS *)((char *) &pSMBr->hdr.Protocol +
3237 le16_to_cpu(pSMBr->t2.ParameterOffset));
3239 if(parms->EndofSearch)
3240 psrch_inf->endOfSearch = TRUE;
3242 psrch_inf->endOfSearch = FALSE;
3244 psrch_inf->entries_in_buffer = le16_to_cpu(parms->SearchCount);
3245 psrch_inf->index_of_last_entry = 2 /* skip . and .. */ +
3246 psrch_inf->entries_in_buffer;
3247 *pnetfid = parms->SearchHandle;
3249 cifs_buf_release(pSMB);
3256 int CIFSFindNext(const int xid, struct cifsTconInfo *tcon,
3257 __u16 searchHandle, struct cifs_search_info * psrch_inf)
3259 TRANSACTION2_FNEXT_REQ *pSMB = NULL;
3260 TRANSACTION2_FNEXT_RSP *pSMBr = NULL;
3261 T2_FNEXT_RSP_PARMS * parms;
3262 char *response_data;
3264 int bytes_returned, name_len;
3265 __u16 params, byte_count;
3267 cFYI(1, ("In FindNext"));
3269 if(psrch_inf->endOfSearch == TRUE)
3272 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3277 params = 14; /* includes 2 bytes of null string, converted to LE below */
3279 pSMB->TotalDataCount = 0; /* no EAs */
3280 pSMB->MaxParameterCount = cpu_to_le16(8);
3281 pSMB->MaxDataCount =
3282 cpu_to_le16((tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
3283 pSMB->MaxSetupCount = 0;
3287 pSMB->Reserved2 = 0;
3288 pSMB->ParameterOffset = cpu_to_le16(
3289 offsetof(struct smb_com_transaction2_fnext_req,SearchHandle) - 4);
3290 pSMB->DataCount = 0;
3291 pSMB->DataOffset = 0;
3292 pSMB->SetupCount = 1;
3293 pSMB->Reserved3 = 0;
3294 pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_NEXT);
3295 pSMB->SearchHandle = searchHandle; /* always kept as le */
3297 cpu_to_le16(CIFSMaxBufSize / sizeof (FILE_UNIX_INFO));
3298 /* test for Unix extensions */
3299 /* if (tcon->ses->capabilities & CAP_UNIX) {
3300 pSMB->InformationLevel = cpu_to_le16(SMB_FIND_FILE_UNIX);
3301 psrch_inf->info_level = SMB_FIND_FILE_UNIX;
3303 pSMB->InformationLevel =
3304 cpu_to_le16(SMB_FIND_FILE_DIRECTORY_INFO);
3305 psrch_inf->info_level = SMB_FIND_FILE_DIRECTORY_INFO;
3307 pSMB->InformationLevel = cpu_to_le16(psrch_inf->info_level);
3308 pSMB->ResumeKey = psrch_inf->resume_key;
3310 cpu_to_le16(CIFS_SEARCH_CLOSE_AT_END | CIFS_SEARCH_RETURN_RESUME);
3312 name_len = psrch_inf->resume_name_len;
3314 if(name_len < PATH_MAX) {
3315 memcpy(pSMB->ResumeFileName, psrch_inf->presume_name, name_len);
3316 byte_count += name_len;
3317 /* 14 byte parm len above enough for 2 byte null terminator */
3318 pSMB->ResumeFileName[name_len] = 0;
3319 pSMB->ResumeFileName[name_len+1] = 0;
3322 goto FNext2_err_exit;
3324 byte_count = params + 1 /* pad */ ;
3325 pSMB->TotalParameterCount = cpu_to_le16(params);
3326 pSMB->ParameterCount = pSMB->TotalParameterCount;
3327 pSMB->hdr.smb_buf_length += byte_count;
3328 pSMB->ByteCount = cpu_to_le16(byte_count);
3330 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3331 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3332 cifs_stats_inc(&tcon->num_fnext);
3335 psrch_inf->endOfSearch = TRUE;
3336 rc = 0; /* search probably was closed at end of search above */
3338 cFYI(1, ("FindNext returned = %d", rc));
3339 } else { /* decode response */
3340 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3343 /* BB fixme add lock for file (srch_info) struct here */
3344 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
3345 psrch_inf->unicode = TRUE;
3347 psrch_inf->unicode = FALSE;
3348 response_data = (char *) &pSMBr->hdr.Protocol +
3349 le16_to_cpu(pSMBr->t2.ParameterOffset);
3350 parms = (T2_FNEXT_RSP_PARMS *)response_data;
3351 response_data = (char *)&pSMBr->hdr.Protocol +
3352 le16_to_cpu(pSMBr->t2.DataOffset);
3353 if(psrch_inf->smallBuf)
3354 cifs_small_buf_release(
3355 psrch_inf->ntwrk_buf_start);
3357 cifs_buf_release(psrch_inf->ntwrk_buf_start);
3358 psrch_inf->srch_entries_start = response_data;
3359 psrch_inf->ntwrk_buf_start = (char *)pSMB;
3360 psrch_inf->smallBuf = 0;
3361 if(parms->EndofSearch)
3362 psrch_inf->endOfSearch = TRUE;
3364 psrch_inf->endOfSearch = FALSE;
3366 psrch_inf->entries_in_buffer = le16_to_cpu(parms->SearchCount);
3367 psrch_inf->index_of_last_entry +=
3368 psrch_inf->entries_in_buffer;
3369 /* cFYI(1,("fnxt2 entries in buf %d index_of_last %d",psrch_inf->entries_in_buffer,psrch_inf->index_of_last_entry)); */
3371 /* BB fixme add unlock here */
3376 /* BB On error, should we leave previous search buf (and count and
3377 last entry fields) intact or free the previous one? */
3379 /* Note: On -EAGAIN error only caller can retry on handle based calls
3380 since file handle passed in no longer valid */
3383 cifs_buf_release(pSMB);
3389 CIFSFindClose(const int xid, struct cifsTconInfo *tcon, const __u16 searchHandle)
3392 FINDCLOSE_REQ *pSMB = NULL;
3393 CLOSE_RSP *pSMBr = NULL; /* BB removeme BB */
3396 cFYI(1, ("In CIFSSMBFindClose"));
3397 rc = small_smb_init(SMB_COM_FIND_CLOSE2, 1, tcon, (void **)&pSMB);
3399 /* no sense returning error if session restarted
3400 as file handle has been closed */
3406 pSMBr = (CLOSE_RSP *)pSMB; /* BB removeme BB */
3407 pSMB->FileID = searchHandle;
3408 pSMB->ByteCount = 0;
3409 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3410 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3412 cERROR(1, ("Send error in FindClose = %d", rc));
3414 cifs_stats_inc(&tcon->num_fclose);
3415 cifs_small_buf_release(pSMB);
3417 /* Since session is dead, search handle closed on server already */
3425 CIFSGetSrvInodeNumber(const int xid, struct cifsTconInfo *tcon,
3426 const unsigned char *searchName,
3427 __u64 * inode_number,
3428 const struct nls_table *nls_codepage, int remap)
3431 TRANSACTION2_QPI_REQ *pSMB = NULL;
3432 TRANSACTION2_QPI_RSP *pSMBr = NULL;
3433 int name_len, bytes_returned;
3434 __u16 params, byte_count;
3436 cFYI(1,("In GetSrvInodeNum for %s",searchName));
3440 GetInodeNumberRetry:
3441 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3447 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3449 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
3450 PATH_MAX,nls_codepage, remap);
3451 name_len++; /* trailing null */
3453 } else { /* BB improve the check for buffer overruns BB */
3454 name_len = strnlen(searchName, PATH_MAX);
3455 name_len++; /* trailing null */
3456 strncpy(pSMB->FileName, searchName, name_len);
3459 params = 2 /* level */ + 4 /* rsrvd */ + name_len /* incl null */ ;
3460 pSMB->TotalDataCount = 0;
3461 pSMB->MaxParameterCount = cpu_to_le16(2);
3462 /* BB find exact max data count below from sess structure BB */
3463 pSMB->MaxDataCount = cpu_to_le16(4000);
3464 pSMB->MaxSetupCount = 0;
3468 pSMB->Reserved2 = 0;
3469 pSMB->ParameterOffset = cpu_to_le16(offsetof(
3470 struct smb_com_transaction2_qpi_req ,InformationLevel) - 4);
3471 pSMB->DataCount = 0;
3472 pSMB->DataOffset = 0;
3473 pSMB->SetupCount = 1;
3474 pSMB->Reserved3 = 0;
3475 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
3476 byte_count = params + 1 /* pad */ ;
3477 pSMB->TotalParameterCount = cpu_to_le16(params);
3478 pSMB->ParameterCount = pSMB->TotalParameterCount;
3479 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_INTERNAL_INFO);
3480 pSMB->Reserved4 = 0;
3481 pSMB->hdr.smb_buf_length += byte_count;
3482 pSMB->ByteCount = cpu_to_le16(byte_count);
3484 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3485 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3487 cFYI(1, ("error %d in QueryInternalInfo", rc));
3489 /* decode response */
3490 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3491 if (rc || (pSMBr->ByteCount < 2))
3492 /* BB also check enough total bytes returned */
3493 /* If rc should we check for EOPNOSUPP and
3494 disable the srvino flag? or in caller? */
3495 rc = -EIO; /* bad smb */
3497 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3498 __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
3499 struct file_internal_info * pfinfo;
3500 /* BB Do we need a cast or hash here ? */
3502 cFYI(1, ("Illegal size ret in QryIntrnlInf"));
3504 goto GetInodeNumOut;
3506 pfinfo = (struct file_internal_info *)
3507 (data_offset + (char *) &pSMBr->hdr.Protocol);
3508 *inode_number = pfinfo->UniqueId;
3512 cifs_buf_release(pSMB);
3514 goto GetInodeNumberRetry;
3519 CIFSGetDFSRefer(const int xid, struct cifsSesInfo *ses,
3520 const unsigned char *searchName,
3521 unsigned char **targetUNCs,
3522 unsigned int *number_of_UNC_in_array,
3523 const struct nls_table *nls_codepage, int remap)
3525 /* TRANS2_GET_DFS_REFERRAL */
3526 TRANSACTION2_GET_DFS_REFER_REQ *pSMB = NULL;
3527 TRANSACTION2_GET_DFS_REFER_RSP *pSMBr = NULL;
3528 struct dfs_referral_level_3 * referrals = NULL;
3534 __u16 params, byte_count;
3535 *number_of_UNC_in_array = 0;
3538 cFYI(1, ("In GetDFSRefer the path %s", searchName));
3542 rc = smb_init(SMB_COM_TRANSACTION2, 15, NULL, (void **) &pSMB,
3547 /* server pointer checked in called function,
3548 but should never be null here anyway */
3549 pSMB->hdr.Mid = GetNextMid(ses->server);
3550 pSMB->hdr.Tid = ses->ipc_tid;
3551 pSMB->hdr.Uid = ses->Suid;
3552 if (ses->capabilities & CAP_STATUS32) {
3553 pSMB->hdr.Flags2 |= SMBFLG2_ERR_STATUS;
3555 if (ses->capabilities & CAP_DFS) {
3556 pSMB->hdr.Flags2 |= SMBFLG2_DFS;
3559 if (ses->capabilities & CAP_UNICODE) {
3560 pSMB->hdr.Flags2 |= SMBFLG2_UNICODE;
3562 cifsConvertToUCS((__le16 *) pSMB->RequestFileName,
3563 searchName, PATH_MAX, nls_codepage, remap);
3564 name_len++; /* trailing null */
3566 } else { /* BB improve the check for buffer overruns BB */
3567 name_len = strnlen(searchName, PATH_MAX);
3568 name_len++; /* trailing null */
3569 strncpy(pSMB->RequestFileName, searchName, name_len);
3572 params = 2 /* level */ + name_len /*includes null */ ;
3573 pSMB->TotalDataCount = 0;
3574 pSMB->DataCount = 0;
3575 pSMB->DataOffset = 0;
3576 pSMB->MaxParameterCount = 0;
3577 pSMB->MaxDataCount = cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
3578 pSMB->MaxSetupCount = 0;
3582 pSMB->Reserved2 = 0;
3583 pSMB->ParameterOffset = cpu_to_le16(offsetof(
3584 struct smb_com_transaction2_get_dfs_refer_req, MaxReferralLevel) - 4);
3585 pSMB->SetupCount = 1;
3586 pSMB->Reserved3 = 0;
3587 pSMB->SubCommand = cpu_to_le16(TRANS2_GET_DFS_REFERRAL);
3588 byte_count = params + 3 /* pad */ ;
3589 pSMB->ParameterCount = cpu_to_le16(params);
3590 pSMB->TotalParameterCount = pSMB->ParameterCount;
3591 pSMB->MaxReferralLevel = cpu_to_le16(3);
3592 pSMB->hdr.smb_buf_length += byte_count;
3593 pSMB->ByteCount = cpu_to_le16(byte_count);
3595 rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB,
3596 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3598 cFYI(1, ("Send error in GetDFSRefer = %d", rc));
3599 } else { /* decode response */
3600 /* BB Add logic to parse referrals here */
3601 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3603 if (rc || (pSMBr->ByteCount < 17)) /* BB also check enough total bytes returned */
3604 rc = -EIO; /* bad smb */
3606 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3607 __u16 data_count = le16_to_cpu(pSMBr->t2.DataCount);
3610 ("Decoding GetDFSRefer response. BCC: %d Offset %d",
3611 pSMBr->ByteCount, data_offset));
3613 (struct dfs_referral_level_3 *)
3614 (8 /* sizeof start of data block */ +
3616 (char *) &pSMBr->hdr.Protocol);
3617 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",
3618 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)));
3619 /* BB This field is actually two bytes in from start of
3620 data block so we could do safety check that DataBlock
3621 begins at address of pSMBr->NumberOfReferrals */
3622 *number_of_UNC_in_array = le16_to_cpu(pSMBr->NumberOfReferrals);
3624 /* BB Fix below so can return more than one referral */
3625 if(*number_of_UNC_in_array > 1)
3626 *number_of_UNC_in_array = 1;
3628 /* get the length of the strings describing refs */
3630 for(i=0;i<*number_of_UNC_in_array;i++) {
3631 /* make sure that DfsPathOffset not past end */
3632 __u16 offset = le16_to_cpu(referrals->DfsPathOffset);
3633 if (offset > data_count) {
3634 /* if invalid referral, stop here and do
3635 not try to copy any more */
3636 *number_of_UNC_in_array = i;
3639 temp = ((char *)referrals) + offset;
3641 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
3642 name_len += UniStrnlen((wchar_t *)temp,data_count);
3644 name_len += strnlen(temp,data_count);
3647 /* BB add check that referral pointer does not fall off end PDU */
3650 /* BB add check for name_len bigger than bcc */
3652 kmalloc(name_len+1+ (*number_of_UNC_in_array),GFP_KERNEL);
3653 if(*targetUNCs == NULL) {
3657 /* copy the ref strings */
3659 (struct dfs_referral_level_3 *)
3660 (8 /* sizeof data hdr */ +
3662 (char *) &pSMBr->hdr.Protocol);
3664 for(i=0;i<*number_of_UNC_in_array;i++) {
3665 temp = ((char *)referrals) + le16_to_cpu(referrals->DfsPathOffset);
3666 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
3667 cifs_strfromUCS_le(*targetUNCs,
3668 (__le16 *) temp, name_len, nls_codepage);
3670 strncpy(*targetUNCs,temp,name_len);
3672 /* BB update target_uncs pointers */
3682 cifs_buf_release(pSMB);
3690 /* Query File System Info such as free space to old servers such as Win 9x */
3692 SMBOldQFSInfo(const int xid, struct cifsTconInfo *tcon, struct kstatfs *FSData)
3694 /* level 0x01 SMB_QUERY_FILE_SYSTEM_INFO */
3695 TRANSACTION2_QFSI_REQ *pSMB = NULL;
3696 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
3697 FILE_SYSTEM_ALLOC_INFO *response_data;
3699 int bytes_returned = 0;
3700 __u16 params, byte_count;
3702 cFYI(1, ("OldQFSInfo"));
3704 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3708 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3713 params = 2; /* level */
3714 pSMB->TotalDataCount = 0;
3715 pSMB->MaxParameterCount = cpu_to_le16(2);
3716 pSMB->MaxDataCount = cpu_to_le16(1000);
3717 pSMB->MaxSetupCount = 0;
3721 pSMB->Reserved2 = 0;
3722 byte_count = params + 1 /* pad */ ;
3723 pSMB->TotalParameterCount = cpu_to_le16(params);
3724 pSMB->ParameterCount = pSMB->TotalParameterCount;
3725 pSMB->ParameterOffset = cpu_to_le16(offsetof(
3726 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
3727 pSMB->DataCount = 0;
3728 pSMB->DataOffset = 0;
3729 pSMB->SetupCount = 1;
3730 pSMB->Reserved3 = 0;
3731 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
3732 pSMB->InformationLevel = cpu_to_le16(SMB_INFO_ALLOCATION);
3733 pSMB->hdr.smb_buf_length += byte_count;
3734 pSMB->ByteCount = cpu_to_le16(byte_count);
3736 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3737 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3739 cFYI(1, ("Send error in QFSInfo = %d", rc));
3740 } else { /* decode response */
3741 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3743 if (rc || (pSMBr->ByteCount < 18))
3744 rc = -EIO; /* bad smb */
3746 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3747 cFYI(1,("qfsinf resp BCC: %d Offset %d",
3748 pSMBr->ByteCount, data_offset));
3751 (FILE_SYSTEM_ALLOC_INFO *)
3752 (((char *) &pSMBr->hdr.Protocol) + data_offset);
3754 le16_to_cpu(response_data->BytesPerSector) *
3755 le32_to_cpu(response_data->
3756 SectorsPerAllocationUnit);
3758 le32_to_cpu(response_data->TotalAllocationUnits);
3759 FSData->f_bfree = FSData->f_bavail =
3760 le32_to_cpu(response_data->FreeAllocationUnits);
3762 ("Blocks: %lld Free: %lld Block size %ld",
3763 (unsigned long long)FSData->f_blocks,
3764 (unsigned long long)FSData->f_bfree,
3768 cifs_buf_release(pSMB);
3771 goto oldQFSInfoRetry;
3777 CIFSSMBQFSInfo(const int xid, struct cifsTconInfo *tcon, struct kstatfs *FSData)
3779 /* level 0x103 SMB_QUERY_FILE_SYSTEM_INFO */
3780 TRANSACTION2_QFSI_REQ *pSMB = NULL;
3781 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
3782 FILE_SYSTEM_INFO *response_data;
3784 int bytes_returned = 0;
3785 __u16 params, byte_count;
3787 cFYI(1, ("In QFSInfo"));
3789 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3794 params = 2; /* level */
3795 pSMB->TotalDataCount = 0;
3796 pSMB->MaxParameterCount = cpu_to_le16(2);
3797 pSMB->MaxDataCount = cpu_to_le16(1000);
3798 pSMB->MaxSetupCount = 0;
3802 pSMB->Reserved2 = 0;
3803 byte_count = params + 1 /* pad */ ;
3804 pSMB->TotalParameterCount = cpu_to_le16(params);
3805 pSMB->ParameterCount = pSMB->TotalParameterCount;
3806 pSMB->ParameterOffset = cpu_to_le16(offsetof(
3807 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
3808 pSMB->DataCount = 0;
3809 pSMB->DataOffset = 0;
3810 pSMB->SetupCount = 1;
3811 pSMB->Reserved3 = 0;
3812 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
3813 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_SIZE_INFO);
3814 pSMB->hdr.smb_buf_length += byte_count;
3815 pSMB->ByteCount = cpu_to_le16(byte_count);
3817 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3818 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3820 cFYI(1, ("Send error in QFSInfo = %d", rc));
3821 } else { /* decode response */
3822 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3824 if (rc || (pSMBr->ByteCount < 24))
3825 rc = -EIO; /* bad smb */
3827 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3831 *) (((char *) &pSMBr->hdr.Protocol) +
3834 le32_to_cpu(response_data->BytesPerSector) *
3835 le32_to_cpu(response_data->
3836 SectorsPerAllocationUnit);
3838 le64_to_cpu(response_data->TotalAllocationUnits);
3839 FSData->f_bfree = FSData->f_bavail =
3840 le64_to_cpu(response_data->FreeAllocationUnits);
3842 ("Blocks: %lld Free: %lld Block size %ld",
3843 (unsigned long long)FSData->f_blocks,
3844 (unsigned long long)FSData->f_bfree,
3848 cifs_buf_release(pSMB);
3857 CIFSSMBQFSAttributeInfo(const int xid, struct cifsTconInfo *tcon)
3859 /* level 0x105 SMB_QUERY_FILE_SYSTEM_INFO */
3860 TRANSACTION2_QFSI_REQ *pSMB = NULL;
3861 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
3862 FILE_SYSTEM_ATTRIBUTE_INFO *response_data;
3864 int bytes_returned = 0;
3865 __u16 params, byte_count;
3867 cFYI(1, ("In QFSAttributeInfo"));
3869 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3874 params = 2; /* level */
3875 pSMB->TotalDataCount = 0;
3876 pSMB->MaxParameterCount = cpu_to_le16(2);
3877 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
3878 pSMB->MaxSetupCount = 0;
3882 pSMB->Reserved2 = 0;
3883 byte_count = params + 1 /* pad */ ;
3884 pSMB->TotalParameterCount = cpu_to_le16(params);
3885 pSMB->ParameterCount = pSMB->TotalParameterCount;
3886 pSMB->ParameterOffset = cpu_to_le16(offsetof(
3887 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
3888 pSMB->DataCount = 0;
3889 pSMB->DataOffset = 0;
3890 pSMB->SetupCount = 1;
3891 pSMB->Reserved3 = 0;
3892 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
3893 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_ATTRIBUTE_INFO);
3894 pSMB->hdr.smb_buf_length += byte_count;
3895 pSMB->ByteCount = cpu_to_le16(byte_count);
3897 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3898 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3900 cERROR(1, ("Send error in QFSAttributeInfo = %d", rc));
3901 } else { /* decode response */
3902 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3904 if (rc || (pSMBr->ByteCount < 13)) { /* BB also check enough bytes returned */
3905 rc = -EIO; /* bad smb */
3907 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3909 (FILE_SYSTEM_ATTRIBUTE_INFO
3910 *) (((char *) &pSMBr->hdr.Protocol) +
3912 memcpy(&tcon->fsAttrInfo, response_data,
3913 sizeof (FILE_SYSTEM_ATTRIBUTE_INFO));
3916 cifs_buf_release(pSMB);
3919 goto QFSAttributeRetry;
3925 CIFSSMBQFSDeviceInfo(const int xid, struct cifsTconInfo *tcon)
3927 /* level 0x104 SMB_QUERY_FILE_SYSTEM_INFO */
3928 TRANSACTION2_QFSI_REQ *pSMB = NULL;
3929 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
3930 FILE_SYSTEM_DEVICE_INFO *response_data;
3932 int bytes_returned = 0;
3933 __u16 params, byte_count;
3935 cFYI(1, ("In QFSDeviceInfo"));
3937 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3942 params = 2; /* level */
3943 pSMB->TotalDataCount = 0;
3944 pSMB->MaxParameterCount = cpu_to_le16(2);
3945 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
3946 pSMB->MaxSetupCount = 0;
3950 pSMB->Reserved2 = 0;
3951 byte_count = params + 1 /* pad */ ;
3952 pSMB->TotalParameterCount = cpu_to_le16(params);
3953 pSMB->ParameterCount = pSMB->TotalParameterCount;
3954 pSMB->ParameterOffset = cpu_to_le16(offsetof(
3955 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
3957 pSMB->DataCount = 0;
3958 pSMB->DataOffset = 0;
3959 pSMB->SetupCount = 1;
3960 pSMB->Reserved3 = 0;
3961 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
3962 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_DEVICE_INFO);
3963 pSMB->hdr.smb_buf_length += byte_count;
3964 pSMB->ByteCount = cpu_to_le16(byte_count);
3966 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3967 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3969 cFYI(1, ("Send error in QFSDeviceInfo = %d", rc));
3970 } else { /* decode response */
3971 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3973 if (rc || (pSMBr->ByteCount < sizeof (FILE_SYSTEM_DEVICE_INFO)))
3974 rc = -EIO; /* bad smb */
3976 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3978 (FILE_SYSTEM_DEVICE_INFO *)
3979 (((char *) &pSMBr->hdr.Protocol) +
3981 memcpy(&tcon->fsDevInfo, response_data,
3982 sizeof (FILE_SYSTEM_DEVICE_INFO));
3985 cifs_buf_release(pSMB);
3988 goto QFSDeviceRetry;
3994 CIFSSMBQFSUnixInfo(const int xid, struct cifsTconInfo *tcon)
3996 /* level 0x200 SMB_QUERY_CIFS_UNIX_INFO */
3997 TRANSACTION2_QFSI_REQ *pSMB = NULL;
3998 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
3999 FILE_SYSTEM_UNIX_INFO *response_data;
4001 int bytes_returned = 0;
4002 __u16 params, byte_count;
4004 cFYI(1, ("In QFSUnixInfo"));
4006 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4011 params = 2; /* level */
4012 pSMB->TotalDataCount = 0;
4013 pSMB->DataCount = 0;
4014 pSMB->DataOffset = 0;
4015 pSMB->MaxParameterCount = cpu_to_le16(2);
4016 pSMB->MaxDataCount = cpu_to_le16(100); /* BB find exact max SMB PDU from sess structure BB */
4017 pSMB->MaxSetupCount = 0;
4021 pSMB->Reserved2 = 0;
4022 byte_count = params + 1 /* pad */ ;
4023 pSMB->ParameterCount = cpu_to_le16(params);
4024 pSMB->TotalParameterCount = pSMB->ParameterCount;
4025 pSMB->ParameterOffset = cpu_to_le16(offsetof(struct
4026 smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4027 pSMB->SetupCount = 1;
4028 pSMB->Reserved3 = 0;
4029 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4030 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_CIFS_UNIX_INFO);
4031 pSMB->hdr.smb_buf_length += byte_count;
4032 pSMB->ByteCount = cpu_to_le16(byte_count);
4034 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4035 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4037 cERROR(1, ("Send error in QFSUnixInfo = %d", rc));
4038 } else { /* decode response */
4039 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4041 if (rc || (pSMBr->ByteCount < 13)) {
4042 rc = -EIO; /* bad smb */
4044 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4046 (FILE_SYSTEM_UNIX_INFO
4047 *) (((char *) &pSMBr->hdr.Protocol) +
4049 memcpy(&tcon->fsUnixInfo, response_data,
4050 sizeof (FILE_SYSTEM_UNIX_INFO));
4053 cifs_buf_release(pSMB);
4063 CIFSSMBSetFSUnixInfo(const int xid, struct cifsTconInfo *tcon, __u64 cap)
4065 /* level 0x200 SMB_SET_CIFS_UNIX_INFO */
4066 TRANSACTION2_SETFSI_REQ *pSMB = NULL;
4067 TRANSACTION2_SETFSI_RSP *pSMBr = NULL;
4069 int bytes_returned = 0;
4070 __u16 params, param_offset, offset, byte_count;
4072 cFYI(1, ("In SETFSUnixInfo"));
4074 /* BB switch to small buf init to save memory */
4075 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4080 params = 4; /* 2 bytes zero followed by info level. */
4081 pSMB->MaxSetupCount = 0;
4085 pSMB->Reserved2 = 0;
4086 param_offset = offsetof(struct smb_com_transaction2_setfsi_req, FileNum) - 4;
4087 offset = param_offset + params;
4089 pSMB->MaxParameterCount = cpu_to_le16(4);
4090 pSMB->MaxDataCount = cpu_to_le16(100); /* BB find exact max SMB PDU from sess structure BB */
4091 pSMB->SetupCount = 1;
4092 pSMB->Reserved3 = 0;
4093 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FS_INFORMATION);
4094 byte_count = 1 /* pad */ + params + 12;
4096 pSMB->DataCount = cpu_to_le16(12);
4097 pSMB->ParameterCount = cpu_to_le16(params);
4098 pSMB->TotalDataCount = pSMB->DataCount;
4099 pSMB->TotalParameterCount = pSMB->ParameterCount;
4100 pSMB->ParameterOffset = cpu_to_le16(param_offset);
4101 pSMB->DataOffset = cpu_to_le16(offset);
4105 pSMB->InformationLevel = cpu_to_le16(SMB_SET_CIFS_UNIX_INFO);
4108 pSMB->ClientUnixMajor = cpu_to_le16(CIFS_UNIX_MAJOR_VERSION);
4109 pSMB->ClientUnixMinor = cpu_to_le16(CIFS_UNIX_MINOR_VERSION);
4110 pSMB->ClientUnixCap = cpu_to_le64(cap);
4112 pSMB->hdr.smb_buf_length += byte_count;
4113 pSMB->ByteCount = cpu_to_le16(byte_count);
4115 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4116 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4118 cERROR(1, ("Send error in SETFSUnixInfo = %d", rc));
4119 } else { /* decode response */
4120 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4122 rc = -EIO; /* bad smb */
4125 cifs_buf_release(pSMB);
4128 goto SETFSUnixRetry;
4136 CIFSSMBQFSPosixInfo(const int xid, struct cifsTconInfo *tcon,
4137 struct kstatfs *FSData)
4139 /* level 0x201 SMB_QUERY_CIFS_POSIX_INFO */
4140 TRANSACTION2_QFSI_REQ *pSMB = NULL;
4141 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4142 FILE_SYSTEM_POSIX_INFO *response_data;
4144 int bytes_returned = 0;
4145 __u16 params, byte_count;
4147 cFYI(1, ("In QFSPosixInfo"));
4149 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4154 params = 2; /* level */
4155 pSMB->TotalDataCount = 0;
4156 pSMB->DataCount = 0;
4157 pSMB->DataOffset = 0;
4158 pSMB->MaxParameterCount = cpu_to_le16(2);
4159 pSMB->MaxDataCount = cpu_to_le16(100); /* BB find exact max SMB PDU from sess structure BB */
4160 pSMB->MaxSetupCount = 0;
4164 pSMB->Reserved2 = 0;
4165 byte_count = params + 1 /* pad */ ;
4166 pSMB->ParameterCount = cpu_to_le16(params);
4167 pSMB->TotalParameterCount = pSMB->ParameterCount;
4168 pSMB->ParameterOffset = cpu_to_le16(offsetof(struct
4169 smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4170 pSMB->SetupCount = 1;
4171 pSMB->Reserved3 = 0;
4172 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4173 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_POSIX_FS_INFO);
4174 pSMB->hdr.smb_buf_length += byte_count;
4175 pSMB->ByteCount = cpu_to_le16(byte_count);
4177 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4178 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4180 cFYI(1, ("Send error in QFSUnixInfo = %d", rc));
4181 } else { /* decode response */
4182 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4184 if (rc || (pSMBr->ByteCount < 13)) {
4185 rc = -EIO; /* bad smb */
4187 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4189 (FILE_SYSTEM_POSIX_INFO
4190 *) (((char *) &pSMBr->hdr.Protocol) +
4193 le32_to_cpu(response_data->BlockSize);
4195 le64_to_cpu(response_data->TotalBlocks);
4197 le64_to_cpu(response_data->BlocksAvail);
4198 if(response_data->UserBlocksAvail == cpu_to_le64(-1)) {
4199 FSData->f_bavail = FSData->f_bfree;
4202 le64_to_cpu(response_data->UserBlocksAvail);
4204 if(response_data->TotalFileNodes != cpu_to_le64(-1))
4206 le64_to_cpu(response_data->TotalFileNodes);
4207 if(response_data->FreeFileNodes != cpu_to_le64(-1))
4209 le64_to_cpu(response_data->FreeFileNodes);
4212 cifs_buf_release(pSMB);
4221 /* We can not use write of zero bytes trick to
4222 set file size due to need for large file support. Also note that
4223 this SetPathInfo is preferred to SetFileInfo based method in next
4224 routine which is only needed to work around a sharing violation bug
4225 in Samba which this routine can run into */
4228 CIFSSMBSetEOF(const int xid, struct cifsTconInfo *tcon, const char *fileName,
4229 __u64 size, int SetAllocation,
4230 const struct nls_table *nls_codepage, int remap)
4232 struct smb_com_transaction2_spi_req *pSMB = NULL;
4233 struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
4234 struct file_end_of_file_info *parm_data;
4237 int bytes_returned = 0;
4238 __u16 params, byte_count, data_count, param_offset, offset;
4240 cFYI(1, ("In SetEOF"));
4242 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4247 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4249 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
4250 PATH_MAX, nls_codepage, remap);
4251 name_len++; /* trailing null */
4253 } else { /* BB improve the check for buffer overruns BB */
4254 name_len = strnlen(fileName, PATH_MAX);
4255 name_len++; /* trailing null */
4256 strncpy(pSMB->FileName, fileName, name_len);
4258 params = 6 + name_len;
4259 data_count = sizeof (struct file_end_of_file_info);
4260 pSMB->MaxParameterCount = cpu_to_le16(2);
4261 pSMB->MaxDataCount = cpu_to_le16(4100);
4262 pSMB->MaxSetupCount = 0;
4266 pSMB->Reserved2 = 0;
4267 param_offset = offsetof(struct smb_com_transaction2_spi_req,
4268 InformationLevel) - 4;
4269 offset = param_offset + params;
4271 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
4272 pSMB->InformationLevel =
4273 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2);
4275 pSMB->InformationLevel =
4276 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO);
4277 } else /* Set File Size */ {
4278 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
4279 pSMB->InformationLevel =
4280 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO2);
4282 pSMB->InformationLevel =
4283 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO);
4287 (struct file_end_of_file_info *) (((char *) &pSMB->hdr.Protocol) +
4289 pSMB->ParameterOffset = cpu_to_le16(param_offset);
4290 pSMB->DataOffset = cpu_to_le16(offset);
4291 pSMB->SetupCount = 1;
4292 pSMB->Reserved3 = 0;
4293 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
4294 byte_count = 3 /* pad */ + params + data_count;
4295 pSMB->DataCount = cpu_to_le16(data_count);
4296 pSMB->TotalDataCount = pSMB->DataCount;
4297 pSMB->ParameterCount = cpu_to_le16(params);
4298 pSMB->TotalParameterCount = pSMB->ParameterCount;
4299 pSMB->Reserved4 = 0;
4300 pSMB->hdr.smb_buf_length += byte_count;
4301 parm_data->FileSize = cpu_to_le64(size);
4302 pSMB->ByteCount = cpu_to_le16(byte_count);
4303 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4304 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4306 cFYI(1, ("SetPathInfo (file size) returned %d", rc));
4309 cifs_buf_release(pSMB);
4318 CIFSSMBSetFileSize(const int xid, struct cifsTconInfo *tcon, __u64 size,
4319 __u16 fid, __u32 pid_of_opener, int SetAllocation)
4321 struct smb_com_transaction2_sfi_req *pSMB = NULL;
4322 struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
4324 struct file_end_of_file_info *parm_data;
4326 int bytes_returned = 0;
4327 __u16 params, param_offset, offset, byte_count, count;
4329 cFYI(1, ("SetFileSize (via SetFileInfo) %lld",
4331 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
4336 pSMBr = (struct smb_com_transaction2_sfi_rsp *)pSMB;
4338 pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
4339 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));
4342 pSMB->MaxSetupCount = 0;
4346 pSMB->Reserved2 = 0;
4347 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
4348 offset = param_offset + params;
4350 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
4352 count = sizeof(struct file_end_of_file_info);
4353 pSMB->MaxParameterCount = cpu_to_le16(2);
4354 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB PDU from sess */
4355 pSMB->SetupCount = 1;
4356 pSMB->Reserved3 = 0;
4357 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
4358 byte_count = 3 /* pad */ + params + count;
4359 pSMB->DataCount = cpu_to_le16(count);
4360 pSMB->ParameterCount = cpu_to_le16(params);
4361 pSMB->TotalDataCount = pSMB->DataCount;
4362 pSMB->TotalParameterCount = pSMB->ParameterCount;
4363 pSMB->ParameterOffset = cpu_to_le16(param_offset);
4365 (struct file_end_of_file_info *) (((char *) &pSMB->hdr.Protocol) +
4367 pSMB->DataOffset = cpu_to_le16(offset);
4368 parm_data->FileSize = cpu_to_le64(size);
4371 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
4372 pSMB->InformationLevel =
4373 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2);
4375 pSMB->InformationLevel =
4376 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO);
4377 } else /* Set File Size */ {
4378 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
4379 pSMB->InformationLevel =
4380 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO2);
4382 pSMB->InformationLevel =
4383 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO);
4385 pSMB->Reserved4 = 0;
4386 pSMB->hdr.smb_buf_length += byte_count;
4387 pSMB->ByteCount = cpu_to_le16(byte_count);
4388 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4389 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4392 ("Send error in SetFileInfo (SetFileSize) = %d",
4397 cifs_small_buf_release(pSMB);
4399 /* Note: On -EAGAIN error only caller can retry on handle based calls
4400 since file handle passed in no longer valid */
4405 /* Some legacy servers such as NT4 require that the file times be set on
4406 an open handle, rather than by pathname - this is awkward due to
4407 potential access conflicts on the open, but it is unavoidable for these
4408 old servers since the only other choice is to go from 100 nanosecond DCE
4409 time and resort to the original setpathinfo level which takes the ancient
4410 DOS time format with 2 second granularity */
4412 CIFSSMBSetFileTimes(const int xid, struct cifsTconInfo *tcon, const FILE_BASIC_INFO * data,
4415 struct smb_com_transaction2_sfi_req *pSMB = NULL;
4416 struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
4419 int bytes_returned = 0;
4420 __u16 params, param_offset, offset, byte_count, count;
4422 cFYI(1, ("Set Times (via SetFileInfo)"));
4423 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
4428 pSMBr = (struct smb_com_transaction2_sfi_rsp *)pSMB;
4430 /* At this point there is no need to override the current pid
4431 with the pid of the opener, but that could change if we someday
4432 use an existing handle (rather than opening one on the fly) */
4433 /* pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
4434 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));*/
4437 pSMB->MaxSetupCount = 0;
4441 pSMB->Reserved2 = 0;
4442 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
4443 offset = param_offset + params;
4445 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
4447 count = sizeof (FILE_BASIC_INFO);
4448 pSMB->MaxParameterCount = cpu_to_le16(2);
4449 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB PDU from sess */
4450 pSMB->SetupCount = 1;
4451 pSMB->Reserved3 = 0;
4452 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
4453 byte_count = 3 /* pad */ + params + count;
4454 pSMB->DataCount = cpu_to_le16(count);
4455 pSMB->ParameterCount = cpu_to_le16(params);
4456 pSMB->TotalDataCount = pSMB->DataCount;
4457 pSMB->TotalParameterCount = pSMB->ParameterCount;
4458 pSMB->ParameterOffset = cpu_to_le16(param_offset);
4459 pSMB->DataOffset = cpu_to_le16(offset);
4461 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
4462 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO2);
4464 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO);
4465 pSMB->Reserved4 = 0;
4466 pSMB->hdr.smb_buf_length += byte_count;
4467 pSMB->ByteCount = cpu_to_le16(byte_count);
4468 memcpy(data_offset,data,sizeof(FILE_BASIC_INFO));
4469 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4470 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4472 cFYI(1,("Send error in Set Time (SetFileInfo) = %d",rc));
4475 cifs_small_buf_release(pSMB);
4477 /* Note: On -EAGAIN error only caller can retry on handle based calls
4478 since file handle passed in no longer valid */
4485 CIFSSMBSetTimes(const int xid, struct cifsTconInfo *tcon, const char *fileName,
4486 const FILE_BASIC_INFO * data,
4487 const struct nls_table *nls_codepage, int remap)
4489 TRANSACTION2_SPI_REQ *pSMB = NULL;
4490 TRANSACTION2_SPI_RSP *pSMBr = NULL;
4493 int bytes_returned = 0;
4495 __u16 params, param_offset, offset, byte_count, count;
4497 cFYI(1, ("In SetTimes"));
4500 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4505 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4507 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
4508 PATH_MAX, nls_codepage, remap);
4509 name_len++; /* trailing null */
4511 } else { /* BB improve the check for buffer overruns BB */
4512 name_len = strnlen(fileName, PATH_MAX);
4513 name_len++; /* trailing null */
4514 strncpy(pSMB->FileName, fileName, name_len);
4517 params = 6 + name_len;
4518 count = sizeof (FILE_BASIC_INFO);
4519 pSMB->MaxParameterCount = cpu_to_le16(2);
4520 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
4521 pSMB->MaxSetupCount = 0;
4525 pSMB->Reserved2 = 0;
4526 param_offset = offsetof(struct smb_com_transaction2_spi_req,
4527 InformationLevel) - 4;
4528 offset = param_offset + params;
4529 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
4530 pSMB->ParameterOffset = cpu_to_le16(param_offset);
4531 pSMB->DataOffset = cpu_to_le16(offset);
4532 pSMB->SetupCount = 1;
4533 pSMB->Reserved3 = 0;
4534 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
4535 byte_count = 3 /* pad */ + params + count;
4537 pSMB->DataCount = cpu_to_le16(count);
4538 pSMB->ParameterCount = cpu_to_le16(params);
4539 pSMB->TotalDataCount = pSMB->DataCount;
4540 pSMB->TotalParameterCount = pSMB->ParameterCount;
4541 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
4542 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO2);
4544 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO);
4545 pSMB->Reserved4 = 0;
4546 pSMB->hdr.smb_buf_length += byte_count;
4547 memcpy(data_offset, data, sizeof (FILE_BASIC_INFO));
4548 pSMB->ByteCount = cpu_to_le16(byte_count);
4549 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4550 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4552 cFYI(1, ("SetPathInfo (times) returned %d", rc));
4555 cifs_buf_release(pSMB);
4563 /* Can not be used to set time stamps yet (due to old DOS time format) */
4564 /* Can be used to set attributes */
4565 #if 0 /* Possibly not needed - since it turns out that strangely NT4 has a bug
4566 handling it anyway and NT4 was what we thought it would be needed for
4567 Do not delete it until we prove whether needed for Win9x though */
4569 CIFSSMBSetAttrLegacy(int xid, struct cifsTconInfo *tcon, char *fileName,
4570 __u16 dos_attrs, const struct nls_table *nls_codepage)
4572 SETATTR_REQ *pSMB = NULL;
4573 SETATTR_RSP *pSMBr = NULL;
4578 cFYI(1, ("In SetAttrLegacy"));
4581 rc = smb_init(SMB_COM_SETATTR, 8, tcon, (void **) &pSMB,
4586 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4588 ConvertToUCS((__le16 *) pSMB->fileName, fileName,
4589 PATH_MAX, nls_codepage);
4590 name_len++; /* trailing null */
4592 } else { /* BB improve the check for buffer overruns BB */
4593 name_len = strnlen(fileName, PATH_MAX);
4594 name_len++; /* trailing null */
4595 strncpy(pSMB->fileName, fileName, name_len);
4597 pSMB->attr = cpu_to_le16(dos_attrs);
4598 pSMB->BufferFormat = 0x04;
4599 pSMB->hdr.smb_buf_length += name_len + 1;
4600 pSMB->ByteCount = cpu_to_le16(name_len + 1);
4601 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4602 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4604 cFYI(1, ("Error in LegacySetAttr = %d", rc));
4607 cifs_buf_release(pSMB);
4610 goto SetAttrLgcyRetry;
4614 #endif /* temporarily unneeded SetAttr legacy function */
4617 CIFSSMBUnixSetPerms(const int xid, struct cifsTconInfo *tcon,
4618 char *fileName, __u64 mode, __u64 uid, __u64 gid,
4619 dev_t device, const struct nls_table *nls_codepage,
4622 TRANSACTION2_SPI_REQ *pSMB = NULL;
4623 TRANSACTION2_SPI_RSP *pSMBr = NULL;
4626 int bytes_returned = 0;
4627 FILE_UNIX_BASIC_INFO *data_offset;
4628 __u16 params, param_offset, offset, count, byte_count;
4630 cFYI(1, ("In SetUID/GID/Mode"));
4632 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4637 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4639 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
4640 PATH_MAX, nls_codepage, remap);
4641 name_len++; /* trailing null */
4643 } else { /* BB improve the check for buffer overruns BB */
4644 name_len = strnlen(fileName, PATH_MAX);
4645 name_len++; /* trailing null */
4646 strncpy(pSMB->FileName, fileName, name_len);
4649 params = 6 + name_len;
4650 count = sizeof (FILE_UNIX_BASIC_INFO);
4651 pSMB->MaxParameterCount = cpu_to_le16(2);
4652 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
4653 pSMB->MaxSetupCount = 0;
4657 pSMB->Reserved2 = 0;
4658 param_offset = offsetof(struct smb_com_transaction2_spi_req,
4659 InformationLevel) - 4;
4660 offset = param_offset + params;
4662 (FILE_UNIX_BASIC_INFO *) ((char *) &pSMB->hdr.Protocol +
4664 memset(data_offset, 0, count);
4665 pSMB->DataOffset = cpu_to_le16(offset);
4666 pSMB->ParameterOffset = cpu_to_le16(param_offset);
4667 pSMB->SetupCount = 1;
4668 pSMB->Reserved3 = 0;
4669 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
4670 byte_count = 3 /* pad */ + params + count;
4671 pSMB->ParameterCount = cpu_to_le16(params);
4672 pSMB->DataCount = cpu_to_le16(count);
4673 pSMB->TotalParameterCount = pSMB->ParameterCount;
4674 pSMB->TotalDataCount = pSMB->DataCount;
4675 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_BASIC);
4676 pSMB->Reserved4 = 0;
4677 pSMB->hdr.smb_buf_length += byte_count;
4678 data_offset->Uid = cpu_to_le64(uid);
4679 data_offset->Gid = cpu_to_le64(gid);
4680 /* better to leave device as zero when it is */
4681 data_offset->DevMajor = cpu_to_le64(MAJOR(device));
4682 data_offset->DevMinor = cpu_to_le64(MINOR(device));
4683 data_offset->Permissions = cpu_to_le64(mode);
4686 data_offset->Type = cpu_to_le32(UNIX_FILE);
4687 else if(S_ISDIR(mode))
4688 data_offset->Type = cpu_to_le32(UNIX_DIR);
4689 else if(S_ISLNK(mode))
4690 data_offset->Type = cpu_to_le32(UNIX_SYMLINK);
4691 else if(S_ISCHR(mode))
4692 data_offset->Type = cpu_to_le32(UNIX_CHARDEV);
4693 else if(S_ISBLK(mode))
4694 data_offset->Type = cpu_to_le32(UNIX_BLOCKDEV);
4695 else if(S_ISFIFO(mode))
4696 data_offset->Type = cpu_to_le32(UNIX_FIFO);
4697 else if(S_ISSOCK(mode))
4698 data_offset->Type = cpu_to_le32(UNIX_SOCKET);
4701 pSMB->ByteCount = cpu_to_le16(byte_count);
4702 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4703 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4705 cFYI(1, ("SetPathInfo (perms) returned %d", rc));
4709 cifs_buf_release(pSMB);
4715 int CIFSSMBNotify(const int xid, struct cifsTconInfo *tcon,
4716 const int notify_subdirs, const __u16 netfid,
4717 __u32 filter, struct file * pfile, int multishot,
4718 const struct nls_table *nls_codepage)
4721 struct smb_com_transaction_change_notify_req * pSMB = NULL;
4722 struct smb_com_ntransaction_change_notify_rsp * pSMBr = NULL;
4723 struct dir_notify_req *dnotify_req;
4726 cFYI(1, ("In CIFSSMBNotify for file handle %d",(int)netfid));
4727 rc = smb_init(SMB_COM_NT_TRANSACT, 23, tcon, (void **) &pSMB,
4732 pSMB->TotalParameterCount = 0 ;
4733 pSMB->TotalDataCount = 0;
4734 pSMB->MaxParameterCount = cpu_to_le32(2);
4735 /* BB find exact data count max from sess structure BB */
4736 pSMB->MaxDataCount = 0; /* same in little endian or be */
4737 /* BB VERIFY verify which is correct for above BB */
4738 pSMB->MaxDataCount = cpu_to_le32((tcon->ses->server->maxBuf -
4739 MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
4741 pSMB->MaxSetupCount = 4;
4743 pSMB->ParameterOffset = 0;
4744 pSMB->DataCount = 0;
4745 pSMB->DataOffset = 0;
4746 pSMB->SetupCount = 4; /* single byte does not need le conversion */
4747 pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_NOTIFY_CHANGE);
4748 pSMB->ParameterCount = pSMB->TotalParameterCount;
4750 pSMB->WatchTree = 1; /* one byte - no le conversion needed */
4751 pSMB->Reserved2 = 0;
4752 pSMB->CompletionFilter = cpu_to_le32(filter);
4753 pSMB->Fid = netfid; /* file handle always le */
4754 pSMB->ByteCount = 0;
4756 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4757 (struct smb_hdr *) pSMBr, &bytes_returned, -1);
4759 cFYI(1, ("Error in Notify = %d", rc));
4761 /* Add file to outstanding requests */
4762 /* BB change to kmem cache alloc */
4763 dnotify_req = (struct dir_notify_req *) kmalloc(
4764 sizeof(struct dir_notify_req),
4767 dnotify_req->Pid = pSMB->hdr.Pid;
4768 dnotify_req->PidHigh = pSMB->hdr.PidHigh;
4769 dnotify_req->Mid = pSMB->hdr.Mid;
4770 dnotify_req->Tid = pSMB->hdr.Tid;
4771 dnotify_req->Uid = pSMB->hdr.Uid;
4772 dnotify_req->netfid = netfid;
4773 dnotify_req->pfile = pfile;
4774 dnotify_req->filter = filter;
4775 dnotify_req->multishot = multishot;
4776 spin_lock(&GlobalMid_Lock);
4777 list_add_tail(&dnotify_req->lhead,
4778 &GlobalDnotifyReqList);
4779 spin_unlock(&GlobalMid_Lock);
4783 cifs_buf_release(pSMB);
4786 #ifdef CONFIG_CIFS_XATTR
4788 CIFSSMBQAllEAs(const int xid, struct cifsTconInfo *tcon,
4789 const unsigned char *searchName,
4790 char * EAData, size_t buf_size,
4791 const struct nls_table *nls_codepage, int remap)
4793 /* BB assumes one setup word */
4794 TRANSACTION2_QPI_REQ *pSMB = NULL;
4795 TRANSACTION2_QPI_RSP *pSMBr = NULL;
4799 struct fea * temp_fea;
4801 __u16 params, byte_count;
4803 cFYI(1, ("In Query All EAs path %s", searchName));
4805 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4810 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4812 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
4813 PATH_MAX, nls_codepage, remap);
4814 name_len++; /* trailing null */
4816 } else { /* BB improve the check for buffer overruns BB */
4817 name_len = strnlen(searchName, PATH_MAX);
4818 name_len++; /* trailing null */
4819 strncpy(pSMB->FileName, searchName, name_len);
4822 params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */ ;
4823 pSMB->TotalDataCount = 0;
4824 pSMB->MaxParameterCount = cpu_to_le16(2);
4825 pSMB->MaxDataCount = cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
4826 pSMB->MaxSetupCount = 0;
4830 pSMB->Reserved2 = 0;
4831 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4832 struct smb_com_transaction2_qpi_req ,InformationLevel) - 4);
4833 pSMB->DataCount = 0;
4834 pSMB->DataOffset = 0;
4835 pSMB->SetupCount = 1;
4836 pSMB->Reserved3 = 0;
4837 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
4838 byte_count = params + 1 /* pad */ ;
4839 pSMB->TotalParameterCount = cpu_to_le16(params);
4840 pSMB->ParameterCount = pSMB->TotalParameterCount;
4841 pSMB->InformationLevel = cpu_to_le16(SMB_INFO_QUERY_ALL_EAS);
4842 pSMB->Reserved4 = 0;
4843 pSMB->hdr.smb_buf_length += byte_count;
4844 pSMB->ByteCount = cpu_to_le16(byte_count);
4846 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4847 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4849 cFYI(1, ("Send error in QueryAllEAs = %d", rc));
4850 } else { /* decode response */
4851 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4853 /* BB also check enough total bytes returned */
4854 /* BB we need to improve the validity checking
4855 of these trans2 responses */
4856 if (rc || (pSMBr->ByteCount < 4))
4857 rc = -EIO; /* bad smb */
4858 /* else if (pFindData){
4859 memcpy((char *) pFindData,
4860 (char *) &pSMBr->hdr.Protocol +
4863 /* check that length of list is not more than bcc */
4864 /* check that each entry does not go beyond length
4866 /* check that each element of each entry does not
4867 go beyond end of list */
4868 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4869 struct fealist * ea_response_data;
4871 /* validate_trans2_offsets() */
4872 /* BB to check if(start of smb + data_offset > &bcc+ bcc)*/
4873 ea_response_data = (struct fealist *)
4874 (((char *) &pSMBr->hdr.Protocol) +
4876 name_len = le32_to_cpu(ea_response_data->list_len);
4877 cFYI(1,("ea length %d", name_len));
4879 /* returned EA size zeroed at top of function */
4880 cFYI(1,("empty EA list returned from server"));
4882 /* account for ea list len */
4884 temp_fea = ea_response_data->list;
4885 temp_ptr = (char *)temp_fea;
4886 while(name_len > 0) {
4890 rc += temp_fea->name_len;
4891 /* account for prefix user. and trailing null */
4893 if(rc<(int)buf_size) {
4894 memcpy(EAData,"user.",5);
4896 memcpy(EAData,temp_ptr,temp_fea->name_len);
4897 EAData+=temp_fea->name_len;
4898 /* null terminate name */
4900 EAData = EAData + 1;
4901 } else if(buf_size == 0) {
4902 /* skip copy - calc size only */
4904 /* stop before overrun buffer */
4908 name_len -= temp_fea->name_len;
4909 temp_ptr += temp_fea->name_len;
4910 /* account for trailing null */
4913 value_len = le16_to_cpu(temp_fea->value_len);
4914 name_len -= value_len;
4915 temp_ptr += value_len;
4916 /* BB check that temp_ptr is still within smb BB*/
4917 /* no trailing null to account for in value len */
4918 /* go on to next EA */
4919 temp_fea = (struct fea *)temp_ptr;
4925 cifs_buf_release(pSMB);
4932 ssize_t CIFSSMBQueryEA(const int xid,struct cifsTconInfo * tcon,
4933 const unsigned char * searchName,const unsigned char * ea_name,
4934 unsigned char * ea_value, size_t buf_size,
4935 const struct nls_table *nls_codepage, int remap)
4937 TRANSACTION2_QPI_REQ *pSMB = NULL;
4938 TRANSACTION2_QPI_RSP *pSMBr = NULL;
4942 struct fea * temp_fea;
4944 __u16 params, byte_count;
4946 cFYI(1, ("In Query EA path %s", searchName));
4948 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4953 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4955 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
4956 PATH_MAX, nls_codepage, remap);
4957 name_len++; /* trailing null */
4959 } else { /* BB improve the check for buffer overruns BB */
4960 name_len = strnlen(searchName, PATH_MAX);
4961 name_len++; /* trailing null */
4962 strncpy(pSMB->FileName, searchName, name_len);
4965 params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */ ;
4966 pSMB->TotalDataCount = 0;
4967 pSMB->MaxParameterCount = cpu_to_le16(2);
4968 pSMB->MaxDataCount = cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
4969 pSMB->MaxSetupCount = 0;
4973 pSMB->Reserved2 = 0;
4974 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4975 struct smb_com_transaction2_qpi_req ,InformationLevel) - 4);
4976 pSMB->DataCount = 0;
4977 pSMB->DataOffset = 0;
4978 pSMB->SetupCount = 1;
4979 pSMB->Reserved3 = 0;
4980 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
4981 byte_count = params + 1 /* pad */ ;
4982 pSMB->TotalParameterCount = cpu_to_le16(params);
4983 pSMB->ParameterCount = pSMB->TotalParameterCount;
4984 pSMB->InformationLevel = cpu_to_le16(SMB_INFO_QUERY_ALL_EAS);
4985 pSMB->Reserved4 = 0;
4986 pSMB->hdr.smb_buf_length += byte_count;
4987 pSMB->ByteCount = cpu_to_le16(byte_count);
4989 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4990 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4992 cFYI(1, ("Send error in Query EA = %d", rc));
4993 } else { /* decode response */
4994 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4996 /* BB also check enough total bytes returned */
4997 /* BB we need to improve the validity checking
4998 of these trans2 responses */
4999 if (rc || (pSMBr->ByteCount < 4))
5000 rc = -EIO; /* bad smb */
5001 /* else if (pFindData){
5002 memcpy((char *) pFindData,
5003 (char *) &pSMBr->hdr.Protocol +
5006 /* check that length of list is not more than bcc */
5007 /* check that each entry does not go beyond length
5009 /* check that each element of each entry does not
5010 go beyond end of list */
5011 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
5012 struct fealist * ea_response_data;
5014 /* validate_trans2_offsets() */
5015 /* BB to check if(start of smb + data_offset > &bcc+ bcc)*/
5016 ea_response_data = (struct fealist *)
5017 (((char *) &pSMBr->hdr.Protocol) +
5019 name_len = le32_to_cpu(ea_response_data->list_len);
5020 cFYI(1,("ea length %d", name_len));
5022 /* returned EA size zeroed at top of function */
5023 cFYI(1,("empty EA list returned from server"));
5025 /* account for ea list len */
5027 temp_fea = ea_response_data->list;
5028 temp_ptr = (char *)temp_fea;
5029 /* loop through checking if we have a matching
5030 name and then return the associated value */
5031 while(name_len > 0) {
5035 value_len = le16_to_cpu(temp_fea->value_len);
5036 /* BB validate that value_len falls within SMB,
5037 even though maximum for name_len is 255 */
5038 if(memcmp(temp_fea->name,ea_name,
5039 temp_fea->name_len) == 0) {
5042 /* account for prefix user. and trailing null */
5043 if(rc<=(int)buf_size) {
5045 temp_fea->name+temp_fea->name_len+1,
5047 /* ea values, unlike ea names,
5048 are not null terminated */
5049 } else if(buf_size == 0) {
5050 /* skip copy - calc size only */
5052 /* stop before overrun buffer */
5057 name_len -= temp_fea->name_len;
5058 temp_ptr += temp_fea->name_len;
5059 /* account for trailing null */
5062 name_len -= value_len;
5063 temp_ptr += value_len;
5064 /* no trailing null to account for in value len */
5065 /* go on to next EA */
5066 temp_fea = (struct fea *)temp_ptr;
5072 cifs_buf_release(pSMB);
5080 CIFSSMBSetEA(const int xid, struct cifsTconInfo *tcon, const char *fileName,
5081 const char * ea_name, const void * ea_value,
5082 const __u16 ea_value_len, const struct nls_table *nls_codepage,
5085 struct smb_com_transaction2_spi_req *pSMB = NULL;
5086 struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
5087 struct fealist *parm_data;
5090 int bytes_returned = 0;
5091 __u16 params, param_offset, byte_count, offset, count;
5093 cFYI(1, ("In SetEA"));
5095 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5100 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5102 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
5103 PATH_MAX, nls_codepage, remap);
5104 name_len++; /* trailing null */
5106 } else { /* BB improve the check for buffer overruns BB */
5107 name_len = strnlen(fileName, PATH_MAX);
5108 name_len++; /* trailing null */
5109 strncpy(pSMB->FileName, fileName, name_len);
5112 params = 6 + name_len;
5114 /* done calculating parms using name_len of file name,
5115 now use name_len to calculate length of ea name
5116 we are going to create in the inode xattrs */
5120 name_len = strnlen(ea_name,255);
5122 count = sizeof(*parm_data) + ea_value_len + name_len + 1;
5123 pSMB->MaxParameterCount = cpu_to_le16(2);
5124 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB size from sess */
5125 pSMB->MaxSetupCount = 0;
5129 pSMB->Reserved2 = 0;
5130 param_offset = offsetof(struct smb_com_transaction2_spi_req,
5131 InformationLevel) - 4;
5132 offset = param_offset + params;
5133 pSMB->InformationLevel =
5134 cpu_to_le16(SMB_SET_FILE_EA);
5137 (struct fealist *) (((char *) &pSMB->hdr.Protocol) +
5139 pSMB->ParameterOffset = cpu_to_le16(param_offset);
5140 pSMB->DataOffset = cpu_to_le16(offset);
5141 pSMB->SetupCount = 1;
5142 pSMB->Reserved3 = 0;
5143 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
5144 byte_count = 3 /* pad */ + params + count;
5145 pSMB->DataCount = cpu_to_le16(count);
5146 parm_data->list_len = cpu_to_le32(count);
5147 parm_data->list[0].EA_flags = 0;
5148 /* we checked above that name len is less than 255 */
5149 parm_data->list[0].name_len = (__u8)name_len;
5150 /* EA names are always ASCII */
5152 strncpy(parm_data->list[0].name,ea_name,name_len);
5153 parm_data->list[0].name[name_len] = 0;
5154 parm_data->list[0].value_len = cpu_to_le16(ea_value_len);
5155 /* caller ensures that ea_value_len is less than 64K but
5156 we need to ensure that it fits within the smb */
5158 /*BB add length check that it would fit in negotiated SMB buffer size BB */
5159 /* if(ea_value_len > buffer_size - 512 (enough for header)) */
5161 memcpy(parm_data->list[0].name+name_len+1,ea_value,ea_value_len);
5163 pSMB->TotalDataCount = pSMB->DataCount;
5164 pSMB->ParameterCount = cpu_to_le16(params);
5165 pSMB->TotalParameterCount = pSMB->ParameterCount;
5166 pSMB->Reserved4 = 0;
5167 pSMB->hdr.smb_buf_length += byte_count;
5168 pSMB->ByteCount = cpu_to_le16(byte_count);
5169 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5170 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5172 cFYI(1, ("SetPathInfo (EA) returned %d", rc));
5175 cifs_buf_release(pSMB);