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 & CIFSSEC_MUST_KRB5) == CIFSSEC_MUST_KRB5)
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);
431 cFYI(1,("Dialect: %d", pSMBr->DialectIndex));
432 /* Check wct = 1 error case */
433 if((pSMBr->hdr.WordCount < 13) || (pSMBr->DialectIndex == BAD_PROT)) {
434 /* core returns wct = 1, but we do not ask for core - otherwise
435 small wct just comes when dialect index is -1 indicating we
436 could not negotiate a common dialect */
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 = (struct lanman_neg_rsp *)pSMBr;
444 if((extended_security & CIFSSEC_MAY_LANMAN) ||
445 (extended_security & CIFSSEC_MAY_PLNTXT))
446 server->secType = LANMAN;
448 cERROR(1, ("mount failed weak security disabled"
449 " in /proc/fs/cifs/SecurityFlags"));
453 server->secMode = (__u8)le16_to_cpu(rsp->SecurityMode);
454 server->maxReq = le16_to_cpu(rsp->MaxMpxCount);
455 server->maxBuf = min((__u32)le16_to_cpu(rsp->MaxBufSize),
456 (__u32)CIFSMaxBufSize + MAX_CIFS_HDR_SIZE);
457 GETU32(server->sessid) = le32_to_cpu(rsp->SessionKey);
458 /* even though we do not use raw we might as well set this
459 accurately, in case we ever find a need for it */
460 if((le16_to_cpu(rsp->RawMode) & RAW_ENABLE) == RAW_ENABLE) {
461 server->maxRw = 0xFF00;
462 server->capabilities = CAP_MPX_MODE | CAP_RAW_MODE;
464 server->maxRw = 0;/* we do not need to use raw anyway */
465 server->capabilities = CAP_MPX_MODE;
467 server->timeZone = le16_to_cpu(rsp->ServerTimeZone);
469 /* BB get server time for time conversions and add
470 code to use it and timezone since this is not UTC */
472 if (rsp->EncryptionKeyLength == CIFS_CRYPTO_KEY_SIZE) {
473 memcpy(server->cryptKey, rsp->EncryptionKey,
474 CIFS_CRYPTO_KEY_SIZE);
475 } else if (server->secMode & SECMODE_PW_ENCRYPT) {
476 rc = -EIO; /* need cryptkey unless plain text */
480 cFYI(1,("LANMAN negotiated"));
481 /* we will not end up setting signing flags - as no signing
482 was in LANMAN and server did not return the flags on */
484 #else /* weak security disabled */
485 } else if(pSMBr->hdr.WordCount == 13) {
486 cERROR(1,("mount failed, cifs module not built "
487 "with CIFS_WEAK_PW_HASH support"));
489 #endif /* WEAK_PW_HASH */
491 } else if(pSMBr->hdr.WordCount != 17) {
496 /* else wct == 17 NTLM */
497 server->secMode = pSMBr->SecurityMode;
498 if((server->secMode & SECMODE_USER) == 0)
499 cFYI(1,("share mode security"));
501 if((server->secMode & SECMODE_PW_ENCRYPT) == 0)
502 #ifdef CONFIG_CIFS_WEAK_PW_HASH
503 if ((extended_security & CIFSSEC_MAY_PLNTXT) == 0)
504 #endif /* CIFS_WEAK_PW_HASH */
505 cERROR(1,("Server requests plain text password"
506 " but client support disabled"));
508 if(extended_security & CIFSSEC_MUST_NTLMV2)
509 server->secType = NTLMv2;
511 server->secType = NTLM;
514 /* one byte, so no need to convert this or EncryptionKeyLen from
516 server->maxReq = le16_to_cpu(pSMBr->MaxMpxCount);
517 /* probably no need to store and check maxvcs */
518 server->maxBuf = min(le32_to_cpu(pSMBr->MaxBufferSize),
519 (__u32) CIFSMaxBufSize + MAX_CIFS_HDR_SIZE);
520 server->maxRw = le32_to_cpu(pSMBr->MaxRawSize);
521 cFYI(0, ("Max buf = %d", ses->server->maxBuf));
522 GETU32(ses->server->sessid) = le32_to_cpu(pSMBr->SessionKey);
523 server->capabilities = le32_to_cpu(pSMBr->Capabilities);
524 server->timeZone = le16_to_cpu(pSMBr->ServerTimeZone);
525 if (pSMBr->EncryptionKeyLength == CIFS_CRYPTO_KEY_SIZE) {
526 memcpy(server->cryptKey, pSMBr->u.EncryptionKey,
527 CIFS_CRYPTO_KEY_SIZE);
528 } else if ((pSMBr->hdr.Flags2 & SMBFLG2_EXT_SEC)
529 && (pSMBr->EncryptionKeyLength == 0)) {
530 /* decode security blob */
531 } else if (server->secMode & SECMODE_PW_ENCRYPT) {
532 rc = -EIO; /* no crypt key only if plain text pwd */
536 /* BB might be helpful to save off the domain of server here */
538 if ((pSMBr->hdr.Flags2 & SMBFLG2_EXT_SEC) &&
539 (server->capabilities & CAP_EXTENDED_SECURITY)) {
540 count = pSMBr->ByteCount;
543 else if (count == 16) {
544 server->secType = RawNTLMSSP;
545 if (server->socketUseCount.counter > 1) {
546 if (memcmp(server->server_GUID,
547 pSMBr->u.extended_response.
549 cFYI(1, ("server UID changed"));
550 memcpy(server->server_GUID,
551 pSMBr->u.extended_response.GUID,
555 memcpy(server->server_GUID,
556 pSMBr->u.extended_response.GUID, 16);
558 rc = decode_negTokenInit(pSMBr->u.extended_response.
563 /* BB Need to fill struct for sessetup here */
570 server->capabilities &= ~CAP_EXTENDED_SECURITY;
572 #ifdef CONFIG_CIFS_WEAK_PW_HASH
575 if(sign_CIFS_PDUs == FALSE) {
576 if(server->secMode & SECMODE_SIGN_REQUIRED)
577 cERROR(1,("Server requires "
578 "/proc/fs/cifs/PacketSigningEnabled to be on"));
580 ~(SECMODE_SIGN_ENABLED | SECMODE_SIGN_REQUIRED);
581 } else if(sign_CIFS_PDUs == 1) {
582 if((server->secMode & SECMODE_SIGN_REQUIRED) == 0)
584 ~(SECMODE_SIGN_ENABLED | SECMODE_SIGN_REQUIRED);
585 } else if(sign_CIFS_PDUs == 2) {
586 if((server->secMode &
587 (SECMODE_SIGN_ENABLED | SECMODE_SIGN_REQUIRED)) == 0) {
588 cERROR(1,("signing required but server lacks support"));
592 cifs_buf_release(pSMB);
594 cFYI(1,("negprot rc %d",rc));
599 CIFSSMBTDis(const int xid, struct cifsTconInfo *tcon)
601 struct smb_hdr *smb_buffer;
602 struct smb_hdr *smb_buffer_response; /* BB removeme BB */
606 cFYI(1, ("In tree disconnect"));
608 * If last user of the connection and
609 * connection alive - disconnect it
610 * If this is the last connection on the server session disconnect it
611 * (and inside session disconnect we should check if tcp socket needs
612 * to be freed and kernel thread woken up).
615 down(&tcon->tconSem);
619 atomic_dec(&tcon->useCount);
620 if (atomic_read(&tcon->useCount) > 0) {
625 /* No need to return error on this operation if tid invalidated and
626 closed on server already e.g. due to tcp session crashing */
627 if(tcon->tidStatus == CifsNeedReconnect) {
632 if((tcon->ses == NULL) || (tcon->ses->server == NULL)) {
636 rc = small_smb_init(SMB_COM_TREE_DISCONNECT, 0, tcon,
637 (void **)&smb_buffer);
642 smb_buffer_response = smb_buffer; /* BB removeme BB */
644 rc = SendReceive(xid, tcon->ses, smb_buffer, smb_buffer_response,
647 cFYI(1, ("Tree disconnect failed %d", rc));
650 cifs_small_buf_release(smb_buffer);
653 /* No need to return error on this operation if tid invalidated and
654 closed on server already e.g. due to tcp session crashing */
662 CIFSSMBLogoff(const int xid, struct cifsSesInfo *ses)
664 struct smb_hdr *smb_buffer_response;
665 LOGOFF_ANDX_REQ *pSMB;
669 cFYI(1, ("In SMBLogoff for session disconnect"));
675 atomic_dec(&ses->inUse);
676 if (atomic_read(&ses->inUse) > 0) {
680 rc = small_smb_init(SMB_COM_LOGOFF_ANDX, 2, NULL, (void **)&pSMB);
686 smb_buffer_response = (struct smb_hdr *)pSMB; /* BB removeme BB */
689 pSMB->hdr.Mid = GetNextMid(ses->server);
691 if(ses->server->secMode &
692 (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
693 pSMB->hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
696 pSMB->hdr.Uid = ses->Suid;
698 pSMB->AndXCommand = 0xFF;
699 rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB,
700 smb_buffer_response, &length, 0);
702 atomic_dec(&ses->server->socketUseCount);
703 if (atomic_read(&ses->server->socketUseCount) == 0) {
704 spin_lock(&GlobalMid_Lock);
705 ses->server->tcpStatus = CifsExiting;
706 spin_unlock(&GlobalMid_Lock);
711 cifs_small_buf_release(pSMB);
713 /* if session dead then we do not need to do ulogoff,
714 since server closed smb session, no sense reporting
722 CIFSSMBDelFile(const int xid, struct cifsTconInfo *tcon, const char *fileName,
723 const struct nls_table *nls_codepage, int remap)
725 DELETE_FILE_REQ *pSMB = NULL;
726 DELETE_FILE_RSP *pSMBr = NULL;
732 rc = smb_init(SMB_COM_DELETE, 1, tcon, (void **) &pSMB,
737 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
739 cifsConvertToUCS((__le16 *) pSMB->fileName, fileName,
740 PATH_MAX, nls_codepage, remap);
741 name_len++; /* trailing null */
743 } else { /* BB improve check for buffer overruns BB */
744 name_len = strnlen(fileName, PATH_MAX);
745 name_len++; /* trailing null */
746 strncpy(pSMB->fileName, fileName, name_len);
748 pSMB->SearchAttributes =
749 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM);
750 pSMB->BufferFormat = 0x04;
751 pSMB->hdr.smb_buf_length += name_len + 1;
752 pSMB->ByteCount = cpu_to_le16(name_len + 1);
753 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
754 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
755 cifs_stats_inc(&tcon->num_deletes);
757 cFYI(1, ("Error in RMFile = %d", rc));
760 cifs_buf_release(pSMB);
768 CIFSSMBRmDir(const int xid, struct cifsTconInfo *tcon, const char *dirName,
769 const struct nls_table *nls_codepage, int remap)
771 DELETE_DIRECTORY_REQ *pSMB = NULL;
772 DELETE_DIRECTORY_RSP *pSMBr = NULL;
777 cFYI(1, ("In CIFSSMBRmDir"));
779 rc = smb_init(SMB_COM_DELETE_DIRECTORY, 0, tcon, (void **) &pSMB,
784 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
785 name_len = cifsConvertToUCS((__le16 *) pSMB->DirName, dirName,
786 PATH_MAX, nls_codepage, remap);
787 name_len++; /* trailing null */
789 } else { /* BB improve check for buffer overruns BB */
790 name_len = strnlen(dirName, PATH_MAX);
791 name_len++; /* trailing null */
792 strncpy(pSMB->DirName, dirName, name_len);
795 pSMB->BufferFormat = 0x04;
796 pSMB->hdr.smb_buf_length += name_len + 1;
797 pSMB->ByteCount = cpu_to_le16(name_len + 1);
798 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
799 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
800 cifs_stats_inc(&tcon->num_rmdirs);
802 cFYI(1, ("Error in RMDir = %d", rc));
805 cifs_buf_release(pSMB);
812 CIFSSMBMkDir(const int xid, struct cifsTconInfo *tcon,
813 const char *name, const struct nls_table *nls_codepage, int remap)
816 CREATE_DIRECTORY_REQ *pSMB = NULL;
817 CREATE_DIRECTORY_RSP *pSMBr = NULL;
821 cFYI(1, ("In CIFSSMBMkDir"));
823 rc = smb_init(SMB_COM_CREATE_DIRECTORY, 0, tcon, (void **) &pSMB,
828 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
829 name_len = cifsConvertToUCS((__le16 *) pSMB->DirName, name,
830 PATH_MAX, nls_codepage, remap);
831 name_len++; /* trailing null */
833 } else { /* BB improve check for buffer overruns BB */
834 name_len = strnlen(name, PATH_MAX);
835 name_len++; /* trailing null */
836 strncpy(pSMB->DirName, name, name_len);
839 pSMB->BufferFormat = 0x04;
840 pSMB->hdr.smb_buf_length += name_len + 1;
841 pSMB->ByteCount = cpu_to_le16(name_len + 1);
842 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
843 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
844 cifs_stats_inc(&tcon->num_mkdirs);
846 cFYI(1, ("Error in Mkdir = %d", rc));
849 cifs_buf_release(pSMB);
855 static __u16 convert_disposition(int disposition)
859 switch (disposition) {
861 ofun = SMBOPEN_OCREATE | SMBOPEN_OTRUNC;
864 ofun = SMBOPEN_OAPPEND;
867 ofun = SMBOPEN_OCREATE;
870 ofun = SMBOPEN_OCREATE | SMBOPEN_OAPPEND;
873 ofun = SMBOPEN_OTRUNC;
875 case FILE_OVERWRITE_IF:
876 ofun = SMBOPEN_OCREATE | SMBOPEN_OTRUNC;
879 cFYI(1,("unknown disposition %d",disposition));
880 ofun = SMBOPEN_OAPPEND; /* regular open */
886 SMBLegacyOpen(const int xid, struct cifsTconInfo *tcon,
887 const char *fileName, const int openDisposition,
888 const int access_flags, const int create_options, __u16 * netfid,
889 int *pOplock, FILE_ALL_INFO * pfile_info,
890 const struct nls_table *nls_codepage, int remap)
893 OPENX_REQ *pSMB = NULL;
894 OPENX_RSP *pSMBr = NULL;
900 rc = smb_init(SMB_COM_OPEN_ANDX, 15, tcon, (void **) &pSMB,
905 pSMB->AndXCommand = 0xFF; /* none */
907 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
908 count = 1; /* account for one byte pad to word boundary */
910 cifsConvertToUCS((__le16 *) (pSMB->fileName + 1),
911 fileName, PATH_MAX, nls_codepage, remap);
912 name_len++; /* trailing null */
914 } else { /* BB improve check for buffer overruns BB */
915 count = 0; /* no pad */
916 name_len = strnlen(fileName, PATH_MAX);
917 name_len++; /* trailing null */
918 strncpy(pSMB->fileName, fileName, name_len);
920 if (*pOplock & REQ_OPLOCK)
921 pSMB->OpenFlags = cpu_to_le16(REQ_OPLOCK);
922 else if (*pOplock & REQ_BATCHOPLOCK) {
923 pSMB->OpenFlags = cpu_to_le16(REQ_BATCHOPLOCK);
925 pSMB->OpenFlags |= cpu_to_le16(REQ_MORE_INFO);
926 /* BB fixme add conversion for access_flags to bits 0 - 2 of mode */
932 pSMB->Mode = cpu_to_le16(2);
933 pSMB->Mode |= cpu_to_le16(0x40); /* deny none */
934 /* set file as system file if special file such
935 as fifo and server expecting SFU style and
936 no Unix extensions */
938 if(create_options & CREATE_OPTION_SPECIAL)
939 pSMB->FileAttributes = cpu_to_le16(ATTR_SYSTEM);
941 pSMB->FileAttributes = cpu_to_le16(0/*ATTR_NORMAL*/); /* BB FIXME */
943 /* if ((omode & S_IWUGO) == 0)
944 pSMB->FileAttributes |= cpu_to_le32(ATTR_READONLY);*/
945 /* Above line causes problems due to vfs splitting create into two
946 pieces - need to set mode after file created not while it is
950 /* pSMB->CreateOptions = cpu_to_le32(create_options & CREATE_OPTIONS_MASK); */
951 /* BB FIXME END BB */
953 pSMB->Sattr = cpu_to_le16(ATTR_HIDDEN | ATTR_SYSTEM | ATTR_DIRECTORY);
954 pSMB->OpenFunction = cpu_to_le16(convert_disposition(openDisposition));
956 pSMB->hdr.smb_buf_length += count;
958 pSMB->ByteCount = cpu_to_le16(count);
959 /* long_op set to 1 to allow for oplock break timeouts */
960 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
961 (struct smb_hdr *) pSMBr, &bytes_returned, 1);
962 cifs_stats_inc(&tcon->num_opens);
964 cFYI(1, ("Error in Open = %d", rc));
966 /* BB verify if wct == 15 */
968 /* *pOplock = pSMBr->OplockLevel; */ /* BB take from action field BB */
970 *netfid = pSMBr->Fid; /* cifs fid stays in le */
971 /* Let caller know file was created so we can set the mode. */
972 /* Do we care about the CreateAction in any other cases? */
974 /* if(cpu_to_le32(FILE_CREATE) == pSMBr->CreateAction)
975 *pOplock |= CIFS_CREATE_ACTION; */
979 pfile_info->CreationTime = 0; /* BB convert CreateTime*/
980 pfile_info->LastAccessTime = 0; /* BB fixme */
981 pfile_info->LastWriteTime = 0; /* BB fixme */
982 pfile_info->ChangeTime = 0; /* BB fixme */
983 pfile_info->Attributes =
984 cpu_to_le32(le16_to_cpu(pSMBr->FileAttributes));
985 /* the file_info buf is endian converted by caller */
986 pfile_info->AllocationSize =
987 cpu_to_le64(le32_to_cpu(pSMBr->EndOfFile));
988 pfile_info->EndOfFile = pfile_info->AllocationSize;
989 pfile_info->NumberOfLinks = cpu_to_le32(1);
993 cifs_buf_release(pSMB);
1000 CIFSSMBOpen(const int xid, struct cifsTconInfo *tcon,
1001 const char *fileName, const int openDisposition,
1002 const int access_flags, const int create_options, __u16 * netfid,
1003 int *pOplock, FILE_ALL_INFO * pfile_info,
1004 const struct nls_table *nls_codepage, int remap)
1007 OPEN_REQ *pSMB = NULL;
1008 OPEN_RSP *pSMBr = NULL;
1014 rc = smb_init(SMB_COM_NT_CREATE_ANDX, 24, tcon, (void **) &pSMB,
1019 pSMB->AndXCommand = 0xFF; /* none */
1021 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1022 count = 1; /* account for one byte pad to word boundary */
1024 cifsConvertToUCS((__le16 *) (pSMB->fileName + 1),
1025 fileName, PATH_MAX, nls_codepage, remap);
1026 name_len++; /* trailing null */
1028 pSMB->NameLength = cpu_to_le16(name_len);
1029 } else { /* BB improve check for buffer overruns BB */
1030 count = 0; /* no pad */
1031 name_len = strnlen(fileName, PATH_MAX);
1032 name_len++; /* trailing null */
1033 pSMB->NameLength = cpu_to_le16(name_len);
1034 strncpy(pSMB->fileName, fileName, name_len);
1036 if (*pOplock & REQ_OPLOCK)
1037 pSMB->OpenFlags = cpu_to_le32(REQ_OPLOCK);
1038 else if (*pOplock & REQ_BATCHOPLOCK) {
1039 pSMB->OpenFlags = cpu_to_le32(REQ_BATCHOPLOCK);
1041 pSMB->DesiredAccess = cpu_to_le32(access_flags);
1042 pSMB->AllocationSize = 0;
1043 /* set file as system file if special file such
1044 as fifo and server expecting SFU style and
1045 no Unix extensions */
1046 if(create_options & CREATE_OPTION_SPECIAL)
1047 pSMB->FileAttributes = cpu_to_le32(ATTR_SYSTEM);
1049 pSMB->FileAttributes = cpu_to_le32(ATTR_NORMAL);
1050 /* XP does not handle ATTR_POSIX_SEMANTICS */
1051 /* but it helps speed up case sensitive checks for other
1052 servers such as Samba */
1053 if (tcon->ses->capabilities & CAP_UNIX)
1054 pSMB->FileAttributes |= cpu_to_le32(ATTR_POSIX_SEMANTICS);
1056 /* if ((omode & S_IWUGO) == 0)
1057 pSMB->FileAttributes |= cpu_to_le32(ATTR_READONLY);*/
1058 /* Above line causes problems due to vfs splitting create into two
1059 pieces - need to set mode after file created not while it is
1061 pSMB->ShareAccess = cpu_to_le32(FILE_SHARE_ALL);
1062 pSMB->CreateDisposition = cpu_to_le32(openDisposition);
1063 pSMB->CreateOptions = cpu_to_le32(create_options & CREATE_OPTIONS_MASK);
1064 /* BB Expirement with various impersonation levels and verify */
1065 pSMB->ImpersonationLevel = cpu_to_le32(SECURITY_IMPERSONATION);
1066 pSMB->SecurityFlags =
1067 SECURITY_CONTEXT_TRACKING | SECURITY_EFFECTIVE_ONLY;
1070 pSMB->hdr.smb_buf_length += count;
1072 pSMB->ByteCount = cpu_to_le16(count);
1073 /* long_op set to 1 to allow for oplock break timeouts */
1074 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1075 (struct smb_hdr *) pSMBr, &bytes_returned, 1);
1076 cifs_stats_inc(&tcon->num_opens);
1078 cFYI(1, ("Error in Open = %d", rc));
1080 *pOplock = pSMBr->OplockLevel; /* 1 byte no need to le_to_cpu */
1081 *netfid = pSMBr->Fid; /* cifs fid stays in le */
1082 /* Let caller know file was created so we can set the mode. */
1083 /* Do we care about the CreateAction in any other cases? */
1084 if(cpu_to_le32(FILE_CREATE) == pSMBr->CreateAction)
1085 *pOplock |= CIFS_CREATE_ACTION;
1087 memcpy((char *)pfile_info,(char *)&pSMBr->CreationTime,
1088 36 /* CreationTime to Attributes */);
1089 /* the file_info buf is endian converted by caller */
1090 pfile_info->AllocationSize = pSMBr->AllocationSize;
1091 pfile_info->EndOfFile = pSMBr->EndOfFile;
1092 pfile_info->NumberOfLinks = cpu_to_le32(1);
1096 cifs_buf_release(pSMB);
1103 CIFSSMBRead(const int xid, struct cifsTconInfo *tcon,
1104 const int netfid, const unsigned int count,
1105 const __u64 lseek, unsigned int *nbytes, char **buf,
1109 READ_REQ *pSMB = NULL;
1110 READ_RSP *pSMBr = NULL;
1111 char *pReadData = NULL;
1113 int resp_buf_type = 0;
1116 cFYI(1,("Reading %d bytes on fid %d",count,netfid));
1117 if(tcon->ses->capabilities & CAP_LARGE_FILES)
1120 wct = 10; /* old style read */
1123 rc = small_smb_init(SMB_COM_READ_ANDX, wct, tcon, (void **) &pSMB);
1127 /* tcon and ses pointer are checked in smb_init */
1128 if (tcon->ses->server == NULL)
1129 return -ECONNABORTED;
1131 pSMB->AndXCommand = 0xFF; /* none */
1133 pSMB->OffsetLow = cpu_to_le32(lseek & 0xFFFFFFFF);
1135 pSMB->OffsetHigh = cpu_to_le32(lseek >> 32);
1136 else if((lseek >> 32) > 0) /* can not handle this big offset for old */
1139 pSMB->Remaining = 0;
1140 pSMB->MaxCount = cpu_to_le16(count & 0xFFFF);
1141 pSMB->MaxCountHigh = cpu_to_le32(count >> 16);
1143 pSMB->ByteCount = 0; /* no need to do le conversion since 0 */
1145 /* old style read */
1146 struct smb_com_readx_req * pSMBW =
1147 (struct smb_com_readx_req *)pSMB;
1148 pSMBW->ByteCount = 0;
1151 iov[0].iov_base = (char *)pSMB;
1152 iov[0].iov_len = pSMB->hdr.smb_buf_length + 4;
1153 rc = SendReceive2(xid, tcon->ses, iov,
1156 cifs_stats_inc(&tcon->num_reads);
1157 pSMBr = (READ_RSP *)iov[0].iov_base;
1159 cERROR(1, ("Send error in read = %d", rc));
1161 int data_length = le16_to_cpu(pSMBr->DataLengthHigh);
1162 data_length = data_length << 16;
1163 data_length += le16_to_cpu(pSMBr->DataLength);
1164 *nbytes = data_length;
1166 /*check that DataLength would not go beyond end of SMB */
1167 if ((data_length > CIFSMaxBufSize)
1168 || (data_length > count)) {
1169 cFYI(1,("bad length %d for count %d",data_length,count));
1173 pReadData = (char *) (&pSMBr->hdr.Protocol) +
1174 le16_to_cpu(pSMBr->DataOffset);
1175 /* if(rc = copy_to_user(buf, pReadData, data_length)) {
1176 cERROR(1,("Faulting on read rc = %d",rc));
1178 }*/ /* can not use copy_to_user when using page cache*/
1180 memcpy(*buf,pReadData,data_length);
1184 /* cifs_small_buf_release(pSMB); */ /* Freed earlier now in SendReceive2 */
1186 if(resp_buf_type == CIFS_SMALL_BUFFER)
1187 cifs_small_buf_release(iov[0].iov_base);
1188 else if(resp_buf_type == CIFS_LARGE_BUFFER)
1189 cifs_buf_release(iov[0].iov_base);
1190 } else if(resp_buf_type != CIFS_NO_BUFFER) {
1191 /* return buffer to caller to free */
1192 *buf = iov[0].iov_base;
1193 if(resp_buf_type == CIFS_SMALL_BUFFER)
1194 *pbuf_type = CIFS_SMALL_BUFFER;
1195 else if(resp_buf_type == CIFS_LARGE_BUFFER)
1196 *pbuf_type = CIFS_LARGE_BUFFER;
1197 } /* else no valid buffer on return - leave as null */
1199 /* Note: On -EAGAIN error only caller can retry on handle based calls
1200 since file handle passed in no longer valid */
1206 CIFSSMBWrite(const int xid, struct cifsTconInfo *tcon,
1207 const int netfid, const unsigned int count,
1208 const __u64 offset, unsigned int *nbytes, const char *buf,
1209 const char __user * ubuf, const int long_op)
1212 WRITE_REQ *pSMB = NULL;
1213 WRITE_RSP *pSMBr = NULL;
1214 int bytes_returned, wct;
1218 /* cFYI(1,("write at %lld %d bytes",offset,count));*/
1219 if(tcon->ses == NULL)
1220 return -ECONNABORTED;
1222 if(tcon->ses->capabilities & CAP_LARGE_FILES)
1227 rc = smb_init(SMB_COM_WRITE_ANDX, wct, tcon, (void **) &pSMB,
1231 /* tcon and ses pointer are checked in smb_init */
1232 if (tcon->ses->server == NULL)
1233 return -ECONNABORTED;
1235 pSMB->AndXCommand = 0xFF; /* none */
1237 pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF);
1239 pSMB->OffsetHigh = cpu_to_le32(offset >> 32);
1240 else if((offset >> 32) > 0) /* can not handle this big offset for old */
1243 pSMB->Reserved = 0xFFFFFFFF;
1244 pSMB->WriteMode = 0;
1245 pSMB->Remaining = 0;
1247 /* Can increase buffer size if buffer is big enough in some cases - ie we
1248 can send more if LARGE_WRITE_X capability returned by the server and if
1249 our buffer is big enough or if we convert to iovecs on socket writes
1250 and eliminate the copy to the CIFS buffer */
1251 if(tcon->ses->capabilities & CAP_LARGE_WRITE_X) {
1252 bytes_sent = min_t(const unsigned int, CIFSMaxBufSize, count);
1254 bytes_sent = (tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE)
1258 if (bytes_sent > count)
1261 cpu_to_le16(offsetof(struct smb_com_write_req,Data) - 4);
1263 memcpy(pSMB->Data,buf,bytes_sent);
1265 if(copy_from_user(pSMB->Data,ubuf,bytes_sent)) {
1266 cifs_buf_release(pSMB);
1269 } else if (count != 0) {
1271 cifs_buf_release(pSMB);
1273 } /* else setting file size with write of zero bytes */
1275 byte_count = bytes_sent + 1; /* pad */
1276 else /* wct == 12 */ {
1277 byte_count = bytes_sent + 5; /* bigger pad, smaller smb hdr */
1279 pSMB->DataLengthLow = cpu_to_le16(bytes_sent & 0xFFFF);
1280 pSMB->DataLengthHigh = cpu_to_le16(bytes_sent >> 16);
1281 pSMB->hdr.smb_buf_length += byte_count;
1284 pSMB->ByteCount = cpu_to_le16(byte_count);
1285 else { /* old style write has byte count 4 bytes earlier so 4 bytes pad */
1286 struct smb_com_writex_req * pSMBW =
1287 (struct smb_com_writex_req *)pSMB;
1288 pSMBW->ByteCount = cpu_to_le16(byte_count);
1291 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1292 (struct smb_hdr *) pSMBr, &bytes_returned, long_op);
1293 cifs_stats_inc(&tcon->num_writes);
1295 cFYI(1, ("Send error in write = %d", rc));
1298 *nbytes = le16_to_cpu(pSMBr->CountHigh);
1299 *nbytes = (*nbytes) << 16;
1300 *nbytes += le16_to_cpu(pSMBr->Count);
1303 cifs_buf_release(pSMB);
1305 /* Note: On -EAGAIN error only caller can retry on handle based calls
1306 since file handle passed in no longer valid */
1312 CIFSSMBWrite2(const int xid, struct cifsTconInfo *tcon,
1313 const int netfid, const unsigned int count,
1314 const __u64 offset, unsigned int *nbytes, struct kvec *iov,
1315 int n_vec, const int long_op)
1318 WRITE_REQ *pSMB = NULL;
1321 int resp_buf_type = 0;
1323 cFYI(1,("write2 at %lld %d bytes", (long long)offset, count));
1325 if(tcon->ses->capabilities & CAP_LARGE_FILES)
1329 rc = small_smb_init(SMB_COM_WRITE_ANDX, wct, tcon, (void **) &pSMB);
1332 /* tcon and ses pointer are checked in smb_init */
1333 if (tcon->ses->server == NULL)
1334 return -ECONNABORTED;
1336 pSMB->AndXCommand = 0xFF; /* none */
1338 pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF);
1340 pSMB->OffsetHigh = cpu_to_le32(offset >> 32);
1341 else if((offset >> 32) > 0) /* can not handle this big offset for old */
1343 pSMB->Reserved = 0xFFFFFFFF;
1344 pSMB->WriteMode = 0;
1345 pSMB->Remaining = 0;
1348 cpu_to_le16(offsetof(struct smb_com_write_req,Data) - 4);
1350 pSMB->DataLengthLow = cpu_to_le16(count & 0xFFFF);
1351 pSMB->DataLengthHigh = cpu_to_le16(count >> 16);
1352 smb_hdr_len = pSMB->hdr.smb_buf_length + 1; /* hdr + 1 byte pad */
1354 pSMB->hdr.smb_buf_length += count+1;
1355 else /* wct == 12 */
1356 pSMB->hdr.smb_buf_length += count+5; /* smb data starts later */
1358 pSMB->ByteCount = cpu_to_le16(count + 1);
1359 else /* wct == 12 */ /* bigger pad, smaller smb hdr, keep offset ok */ {
1360 struct smb_com_writex_req * pSMBW =
1361 (struct smb_com_writex_req *)pSMB;
1362 pSMBW->ByteCount = cpu_to_le16(count + 5);
1364 iov[0].iov_base = pSMB;
1366 iov[0].iov_len = smb_hdr_len + 4;
1367 else /* wct == 12 pad bigger by four bytes */
1368 iov[0].iov_len = smb_hdr_len + 8;
1371 rc = SendReceive2(xid, tcon->ses, iov, n_vec + 1, &resp_buf_type,
1373 cifs_stats_inc(&tcon->num_writes);
1375 cFYI(1, ("Send error Write2 = %d", rc));
1377 } else if(resp_buf_type == 0) {
1378 /* presumably this can not happen, but best to be safe */
1382 WRITE_RSP * pSMBr = (WRITE_RSP *)iov[0].iov_base;
1383 *nbytes = le16_to_cpu(pSMBr->CountHigh);
1384 *nbytes = (*nbytes) << 16;
1385 *nbytes += le16_to_cpu(pSMBr->Count);
1388 /* cifs_small_buf_release(pSMB); */ /* Freed earlier now in SendReceive2 */
1389 if(resp_buf_type == CIFS_SMALL_BUFFER)
1390 cifs_small_buf_release(iov[0].iov_base);
1391 else if(resp_buf_type == CIFS_LARGE_BUFFER)
1392 cifs_buf_release(iov[0].iov_base);
1394 /* Note: On -EAGAIN error only caller can retry on handle based calls
1395 since file handle passed in no longer valid */
1402 CIFSSMBLock(const int xid, struct cifsTconInfo *tcon,
1403 const __u16 smb_file_id, const __u64 len,
1404 const __u64 offset, const __u32 numUnlock,
1405 const __u32 numLock, const __u8 lockType, const int waitFlag)
1408 LOCK_REQ *pSMB = NULL;
1409 LOCK_RSP *pSMBr = NULL;
1414 cFYI(1, ("In CIFSSMBLock - timeout %d numLock %d",waitFlag,numLock));
1415 rc = small_smb_init(SMB_COM_LOCKING_ANDX, 8, tcon, (void **) &pSMB);
1420 pSMBr = (LOCK_RSP *)pSMB; /* BB removeme BB */
1422 if(lockType == LOCKING_ANDX_OPLOCK_RELEASE) {
1423 timeout = -1; /* no response expected */
1425 } else if (waitFlag == TRUE) {
1426 timeout = 3; /* blocking operation, no timeout */
1427 pSMB->Timeout = cpu_to_le32(-1);/* blocking - do not time out */
1432 pSMB->NumberOfLocks = cpu_to_le16(numLock);
1433 pSMB->NumberOfUnlocks = cpu_to_le16(numUnlock);
1434 pSMB->LockType = lockType;
1435 pSMB->AndXCommand = 0xFF; /* none */
1436 pSMB->Fid = smb_file_id; /* netfid stays le */
1438 if((numLock != 0) || (numUnlock != 0)) {
1439 pSMB->Locks[0].Pid = cpu_to_le16(current->tgid);
1440 /* BB where to store pid high? */
1441 pSMB->Locks[0].LengthLow = cpu_to_le32((u32)len);
1442 pSMB->Locks[0].LengthHigh = cpu_to_le32((u32)(len>>32));
1443 pSMB->Locks[0].OffsetLow = cpu_to_le32((u32)offset);
1444 pSMB->Locks[0].OffsetHigh = cpu_to_le32((u32)(offset>>32));
1445 count = sizeof(LOCKING_ANDX_RANGE);
1450 pSMB->hdr.smb_buf_length += count;
1451 pSMB->ByteCount = cpu_to_le16(count);
1453 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1454 (struct smb_hdr *) pSMBr, &bytes_returned, timeout);
1455 cifs_stats_inc(&tcon->num_locks);
1457 cFYI(1, ("Send error in Lock = %d", rc));
1459 cifs_small_buf_release(pSMB);
1461 /* Note: On -EAGAIN error only caller can retry on handle based calls
1462 since file handle passed in no longer valid */
1467 CIFSSMBPosixLock(const int xid, struct cifsTconInfo *tcon,
1468 const __u16 smb_file_id, const int get_flag, const __u64 len,
1469 struct file_lock *pLockData, const __u16 lock_type,
1472 struct smb_com_transaction2_sfi_req *pSMB = NULL;
1473 struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
1475 struct cifs_posix_lock *parm_data;
1477 int bytes_returned = 0;
1478 __u16 params, param_offset, offset, byte_count, count;
1480 cFYI(1, ("Posix Lock"));
1482 if(pLockData == NULL)
1485 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
1490 pSMBr = (struct smb_com_transaction2_sfi_rsp *)pSMB;
1493 pSMB->MaxSetupCount = 0;
1497 pSMB->Reserved2 = 0;
1498 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
1499 offset = param_offset + params;
1501 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
1503 count = sizeof(struct cifs_posix_lock);
1504 pSMB->MaxParameterCount = cpu_to_le16(2);
1505 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB PDU from sess */
1506 pSMB->SetupCount = 1;
1507 pSMB->Reserved3 = 0;
1509 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION);
1511 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
1512 byte_count = 3 /* pad */ + params + count;
1513 pSMB->DataCount = cpu_to_le16(count);
1514 pSMB->ParameterCount = cpu_to_le16(params);
1515 pSMB->TotalDataCount = pSMB->DataCount;
1516 pSMB->TotalParameterCount = pSMB->ParameterCount;
1517 pSMB->ParameterOffset = cpu_to_le16(param_offset);
1518 parm_data = (struct cifs_posix_lock *)
1519 (((char *) &pSMB->hdr.Protocol) + offset);
1521 parm_data->lock_type = cpu_to_le16(lock_type);
1523 parm_data->lock_flags = cpu_to_le16(1);
1524 parm_data->pid = cpu_to_le32(current->tgid);
1525 parm_data->start = cpu_to_le64(pLockData->fl_start);
1526 parm_data->length = cpu_to_le64(len); /* normalize negative numbers */
1528 pSMB->DataOffset = cpu_to_le16(offset);
1529 pSMB->Fid = smb_file_id;
1530 pSMB->InformationLevel = cpu_to_le16(SMB_SET_POSIX_LOCK);
1531 pSMB->Reserved4 = 0;
1532 pSMB->hdr.smb_buf_length += byte_count;
1533 pSMB->ByteCount = cpu_to_le16(byte_count);
1534 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1535 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1537 cFYI(1, ("Send error in Posix Lock = %d", rc));
1538 } else if (get_flag) {
1539 /* lock structure can be returned on get */
1542 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
1544 if (rc || (pSMBr->ByteCount < sizeof(struct cifs_posix_lock))) {
1545 rc = -EIO; /* bad smb */
1548 if(pLockData == NULL) {
1552 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
1553 data_count = le16_to_cpu(pSMBr->t2.DataCount);
1554 if(data_count < sizeof(struct cifs_posix_lock)) {
1558 parm_data = (struct cifs_posix_lock *)
1559 ((char *)&pSMBr->hdr.Protocol + data_offset);
1560 if(parm_data->lock_type == cpu_to_le16(CIFS_UNLCK))
1561 pLockData->fl_type = F_UNLCK;
1566 cifs_small_buf_release(pSMB);
1568 /* Note: On -EAGAIN error only caller can retry on handle based calls
1569 since file handle passed in no longer valid */
1576 CIFSSMBClose(const int xid, struct cifsTconInfo *tcon, int smb_file_id)
1579 CLOSE_REQ *pSMB = NULL;
1580 CLOSE_RSP *pSMBr = NULL;
1582 cFYI(1, ("In CIFSSMBClose"));
1584 /* do not retry on dead session on close */
1585 rc = small_smb_init(SMB_COM_CLOSE, 3, tcon, (void **) &pSMB);
1591 pSMBr = (CLOSE_RSP *)pSMB; /* BB removeme BB */
1593 pSMB->FileID = (__u16) smb_file_id;
1594 pSMB->LastWriteTime = 0;
1595 pSMB->ByteCount = 0;
1596 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1597 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1598 cifs_stats_inc(&tcon->num_closes);
1601 /* EINTR is expected when user ctl-c to kill app */
1602 cERROR(1, ("Send error in Close = %d", rc));
1606 cifs_small_buf_release(pSMB);
1608 /* Since session is dead, file will be closed on server already */
1616 CIFSSMBRename(const int xid, struct cifsTconInfo *tcon,
1617 const char *fromName, const char *toName,
1618 const struct nls_table *nls_codepage, int remap)
1621 RENAME_REQ *pSMB = NULL;
1622 RENAME_RSP *pSMBr = NULL;
1624 int name_len, name_len2;
1627 cFYI(1, ("In CIFSSMBRename"));
1629 rc = smb_init(SMB_COM_RENAME, 1, tcon, (void **) &pSMB,
1634 pSMB->BufferFormat = 0x04;
1635 pSMB->SearchAttributes =
1636 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
1639 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1641 cifsConvertToUCS((__le16 *) pSMB->OldFileName, fromName,
1642 PATH_MAX, nls_codepage, remap);
1643 name_len++; /* trailing null */
1645 pSMB->OldFileName[name_len] = 0x04; /* pad */
1646 /* protocol requires ASCII signature byte on Unicode string */
1647 pSMB->OldFileName[name_len + 1] = 0x00;
1649 cifsConvertToUCS((__le16 *) &pSMB->OldFileName[name_len + 2],
1650 toName, PATH_MAX, nls_codepage, remap);
1651 name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
1652 name_len2 *= 2; /* convert to bytes */
1653 } else { /* BB improve the check for buffer overruns BB */
1654 name_len = strnlen(fromName, PATH_MAX);
1655 name_len++; /* trailing null */
1656 strncpy(pSMB->OldFileName, fromName, name_len);
1657 name_len2 = strnlen(toName, PATH_MAX);
1658 name_len2++; /* trailing null */
1659 pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */
1660 strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2);
1661 name_len2++; /* trailing null */
1662 name_len2++; /* signature byte */
1665 count = 1 /* 1st signature byte */ + name_len + name_len2;
1666 pSMB->hdr.smb_buf_length += count;
1667 pSMB->ByteCount = cpu_to_le16(count);
1669 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1670 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1671 cifs_stats_inc(&tcon->num_renames);
1673 cFYI(1, ("Send error in rename = %d", rc));
1676 cifs_buf_release(pSMB);
1684 int CIFSSMBRenameOpenFile(const int xid,struct cifsTconInfo *pTcon,
1685 int netfid, char * target_name,
1686 const struct nls_table * nls_codepage, int remap)
1688 struct smb_com_transaction2_sfi_req *pSMB = NULL;
1689 struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
1690 struct set_file_rename * rename_info;
1692 char dummy_string[30];
1694 int bytes_returned = 0;
1696 __u16 params, param_offset, offset, count, byte_count;
1698 cFYI(1, ("Rename to File by handle"));
1699 rc = smb_init(SMB_COM_TRANSACTION2, 15, pTcon, (void **) &pSMB,
1705 pSMB->MaxSetupCount = 0;
1709 pSMB->Reserved2 = 0;
1710 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
1711 offset = param_offset + params;
1713 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
1714 rename_info = (struct set_file_rename *) data_offset;
1715 pSMB->MaxParameterCount = cpu_to_le16(2);
1716 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB PDU from sess */
1717 pSMB->SetupCount = 1;
1718 pSMB->Reserved3 = 0;
1719 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
1720 byte_count = 3 /* pad */ + params;
1721 pSMB->ParameterCount = cpu_to_le16(params);
1722 pSMB->TotalParameterCount = pSMB->ParameterCount;
1723 pSMB->ParameterOffset = cpu_to_le16(param_offset);
1724 pSMB->DataOffset = cpu_to_le16(offset);
1725 /* construct random name ".cifs_tmp<inodenum><mid>" */
1726 rename_info->overwrite = cpu_to_le32(1);
1727 rename_info->root_fid = 0;
1728 /* unicode only call */
1729 if(target_name == NULL) {
1730 sprintf(dummy_string,"cifs%x",pSMB->hdr.Mid);
1731 len_of_str = cifsConvertToUCS((__le16 *)rename_info->target_name,
1732 dummy_string, 24, nls_codepage, remap);
1734 len_of_str = cifsConvertToUCS((__le16 *)rename_info->target_name,
1735 target_name, PATH_MAX, nls_codepage, remap);
1737 rename_info->target_name_len = cpu_to_le32(2 * len_of_str);
1738 count = 12 /* sizeof(struct set_file_rename) */ + (2 * len_of_str) + 2;
1739 byte_count += count;
1740 pSMB->DataCount = cpu_to_le16(count);
1741 pSMB->TotalDataCount = pSMB->DataCount;
1743 pSMB->InformationLevel =
1744 cpu_to_le16(SMB_SET_FILE_RENAME_INFORMATION);
1745 pSMB->Reserved4 = 0;
1746 pSMB->hdr.smb_buf_length += byte_count;
1747 pSMB->ByteCount = cpu_to_le16(byte_count);
1748 rc = SendReceive(xid, pTcon->ses, (struct smb_hdr *) pSMB,
1749 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1750 cifs_stats_inc(&pTcon->num_t2renames);
1752 cFYI(1,("Send error in Rename (by file handle) = %d", rc));
1755 cifs_buf_release(pSMB);
1757 /* Note: On -EAGAIN error only caller can retry on handle based calls
1758 since file handle passed in no longer valid */
1764 CIFSSMBCopy(const int xid, struct cifsTconInfo *tcon, const char * fromName,
1765 const __u16 target_tid, const char *toName, const int flags,
1766 const struct nls_table *nls_codepage, int remap)
1769 COPY_REQ *pSMB = NULL;
1770 COPY_RSP *pSMBr = NULL;
1772 int name_len, name_len2;
1775 cFYI(1, ("In CIFSSMBCopy"));
1777 rc = smb_init(SMB_COM_COPY, 1, tcon, (void **) &pSMB,
1782 pSMB->BufferFormat = 0x04;
1783 pSMB->Tid2 = target_tid;
1785 pSMB->Flags = cpu_to_le16(flags & COPY_TREE);
1787 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1788 name_len = cifsConvertToUCS((__le16 *) pSMB->OldFileName,
1789 fromName, PATH_MAX, nls_codepage,
1791 name_len++; /* trailing null */
1793 pSMB->OldFileName[name_len] = 0x04; /* pad */
1794 /* protocol requires ASCII signature byte on Unicode string */
1795 pSMB->OldFileName[name_len + 1] = 0x00;
1796 name_len2 = cifsConvertToUCS((__le16 *)&pSMB->OldFileName[name_len + 2],
1797 toName, PATH_MAX, nls_codepage, remap);
1798 name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
1799 name_len2 *= 2; /* convert to bytes */
1800 } else { /* BB improve the check for buffer overruns BB */
1801 name_len = strnlen(fromName, PATH_MAX);
1802 name_len++; /* trailing null */
1803 strncpy(pSMB->OldFileName, fromName, name_len);
1804 name_len2 = strnlen(toName, PATH_MAX);
1805 name_len2++; /* trailing null */
1806 pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */
1807 strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2);
1808 name_len2++; /* trailing null */
1809 name_len2++; /* signature byte */
1812 count = 1 /* 1st signature byte */ + name_len + name_len2;
1813 pSMB->hdr.smb_buf_length += count;
1814 pSMB->ByteCount = cpu_to_le16(count);
1816 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1817 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1819 cFYI(1, ("Send error in copy = %d with %d files copied",
1820 rc, le16_to_cpu(pSMBr->CopyCount)));
1823 cifs_buf_release(pSMB);
1832 CIFSUnixCreateSymLink(const int xid, struct cifsTconInfo *tcon,
1833 const char *fromName, const char *toName,
1834 const struct nls_table *nls_codepage)
1836 TRANSACTION2_SPI_REQ *pSMB = NULL;
1837 TRANSACTION2_SPI_RSP *pSMBr = NULL;
1840 int name_len_target;
1842 int bytes_returned = 0;
1843 __u16 params, param_offset, offset, byte_count;
1845 cFYI(1, ("In Symlink Unix style"));
1847 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
1852 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1854 cifs_strtoUCS((__le16 *) pSMB->FileName, fromName, PATH_MAX
1855 /* find define for this maxpathcomponent */
1857 name_len++; /* trailing null */
1860 } else { /* BB improve the check for buffer overruns BB */
1861 name_len = strnlen(fromName, PATH_MAX);
1862 name_len++; /* trailing null */
1863 strncpy(pSMB->FileName, fromName, name_len);
1865 params = 6 + name_len;
1866 pSMB->MaxSetupCount = 0;
1870 pSMB->Reserved2 = 0;
1871 param_offset = offsetof(struct smb_com_transaction2_spi_req,
1872 InformationLevel) - 4;
1873 offset = param_offset + params;
1875 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
1876 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1878 cifs_strtoUCS((__le16 *) data_offset, toName, PATH_MAX
1879 /* find define for this maxpathcomponent */
1881 name_len_target++; /* trailing null */
1882 name_len_target *= 2;
1883 } else { /* BB improve the check for buffer overruns BB */
1884 name_len_target = strnlen(toName, PATH_MAX);
1885 name_len_target++; /* trailing null */
1886 strncpy(data_offset, toName, name_len_target);
1889 pSMB->MaxParameterCount = cpu_to_le16(2);
1890 /* BB find exact max on data count below from sess */
1891 pSMB->MaxDataCount = cpu_to_le16(1000);
1892 pSMB->SetupCount = 1;
1893 pSMB->Reserved3 = 0;
1894 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
1895 byte_count = 3 /* pad */ + params + name_len_target;
1896 pSMB->DataCount = cpu_to_le16(name_len_target);
1897 pSMB->ParameterCount = cpu_to_le16(params);
1898 pSMB->TotalDataCount = pSMB->DataCount;
1899 pSMB->TotalParameterCount = pSMB->ParameterCount;
1900 pSMB->ParameterOffset = cpu_to_le16(param_offset);
1901 pSMB->DataOffset = cpu_to_le16(offset);
1902 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_LINK);
1903 pSMB->Reserved4 = 0;
1904 pSMB->hdr.smb_buf_length += byte_count;
1905 pSMB->ByteCount = cpu_to_le16(byte_count);
1906 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1907 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1908 cifs_stats_inc(&tcon->num_symlinks);
1911 ("Send error in SetPathInfo (create symlink) = %d",
1916 cifs_buf_release(pSMB);
1919 goto createSymLinkRetry;
1925 CIFSUnixCreateHardLink(const int xid, struct cifsTconInfo *tcon,
1926 const char *fromName, const char *toName,
1927 const struct nls_table *nls_codepage, int remap)
1929 TRANSACTION2_SPI_REQ *pSMB = NULL;
1930 TRANSACTION2_SPI_RSP *pSMBr = NULL;
1933 int name_len_target;
1935 int bytes_returned = 0;
1936 __u16 params, param_offset, offset, byte_count;
1938 cFYI(1, ("In Create Hard link Unix style"));
1939 createHardLinkRetry:
1940 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
1945 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1946 name_len = cifsConvertToUCS((__le16 *) pSMB->FileName, toName,
1947 PATH_MAX, nls_codepage, remap);
1948 name_len++; /* trailing null */
1951 } else { /* BB improve the check for buffer overruns BB */
1952 name_len = strnlen(toName, PATH_MAX);
1953 name_len++; /* trailing null */
1954 strncpy(pSMB->FileName, toName, name_len);
1956 params = 6 + name_len;
1957 pSMB->MaxSetupCount = 0;
1961 pSMB->Reserved2 = 0;
1962 param_offset = offsetof(struct smb_com_transaction2_spi_req,
1963 InformationLevel) - 4;
1964 offset = param_offset + params;
1966 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
1967 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1969 cifsConvertToUCS((__le16 *) data_offset, fromName, PATH_MAX,
1970 nls_codepage, remap);
1971 name_len_target++; /* trailing null */
1972 name_len_target *= 2;
1973 } else { /* BB improve the check for buffer overruns BB */
1974 name_len_target = strnlen(fromName, PATH_MAX);
1975 name_len_target++; /* trailing null */
1976 strncpy(data_offset, fromName, name_len_target);
1979 pSMB->MaxParameterCount = cpu_to_le16(2);
1980 /* BB find exact max on data count below from sess*/
1981 pSMB->MaxDataCount = cpu_to_le16(1000);
1982 pSMB->SetupCount = 1;
1983 pSMB->Reserved3 = 0;
1984 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
1985 byte_count = 3 /* pad */ + params + name_len_target;
1986 pSMB->ParameterCount = cpu_to_le16(params);
1987 pSMB->TotalParameterCount = pSMB->ParameterCount;
1988 pSMB->DataCount = cpu_to_le16(name_len_target);
1989 pSMB->TotalDataCount = pSMB->DataCount;
1990 pSMB->ParameterOffset = cpu_to_le16(param_offset);
1991 pSMB->DataOffset = cpu_to_le16(offset);
1992 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_HLINK);
1993 pSMB->Reserved4 = 0;
1994 pSMB->hdr.smb_buf_length += byte_count;
1995 pSMB->ByteCount = cpu_to_le16(byte_count);
1996 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1997 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1998 cifs_stats_inc(&tcon->num_hardlinks);
2000 cFYI(1, ("Send error in SetPathInfo (hard link) = %d", rc));
2003 cifs_buf_release(pSMB);
2005 goto createHardLinkRetry;
2011 CIFSCreateHardLink(const int xid, struct cifsTconInfo *tcon,
2012 const char *fromName, const char *toName,
2013 const struct nls_table *nls_codepage, int remap)
2016 NT_RENAME_REQ *pSMB = NULL;
2017 RENAME_RSP *pSMBr = NULL;
2019 int name_len, name_len2;
2022 cFYI(1, ("In CIFSCreateHardLink"));
2023 winCreateHardLinkRetry:
2025 rc = smb_init(SMB_COM_NT_RENAME, 4, tcon, (void **) &pSMB,
2030 pSMB->SearchAttributes =
2031 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
2033 pSMB->Flags = cpu_to_le16(CREATE_HARD_LINK);
2034 pSMB->ClusterCount = 0;
2036 pSMB->BufferFormat = 0x04;
2038 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2040 cifsConvertToUCS((__le16 *) pSMB->OldFileName, fromName,
2041 PATH_MAX, nls_codepage, remap);
2042 name_len++; /* trailing null */
2044 pSMB->OldFileName[name_len] = 0; /* pad */
2045 pSMB->OldFileName[name_len + 1] = 0x04;
2047 cifsConvertToUCS((__le16 *)&pSMB->OldFileName[name_len + 2],
2048 toName, PATH_MAX, nls_codepage, remap);
2049 name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
2050 name_len2 *= 2; /* convert to bytes */
2051 } else { /* BB improve the check for buffer overruns BB */
2052 name_len = strnlen(fromName, PATH_MAX);
2053 name_len++; /* trailing null */
2054 strncpy(pSMB->OldFileName, fromName, name_len);
2055 name_len2 = strnlen(toName, PATH_MAX);
2056 name_len2++; /* trailing null */
2057 pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */
2058 strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2);
2059 name_len2++; /* trailing null */
2060 name_len2++; /* signature byte */
2063 count = 1 /* string type byte */ + name_len + name_len2;
2064 pSMB->hdr.smb_buf_length += count;
2065 pSMB->ByteCount = cpu_to_le16(count);
2067 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2068 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2069 cifs_stats_inc(&tcon->num_hardlinks);
2071 cFYI(1, ("Send error in hard link (NT rename) = %d", rc));
2073 cifs_buf_release(pSMB);
2075 goto winCreateHardLinkRetry;
2081 CIFSSMBUnixQuerySymLink(const int xid, struct cifsTconInfo *tcon,
2082 const unsigned char *searchName,
2083 char *symlinkinfo, const int buflen,
2084 const struct nls_table *nls_codepage)
2086 /* SMB_QUERY_FILE_UNIX_LINK */
2087 TRANSACTION2_QPI_REQ *pSMB = NULL;
2088 TRANSACTION2_QPI_RSP *pSMBr = NULL;
2092 __u16 params, byte_count;
2094 cFYI(1, ("In QPathSymLinkInfo (Unix) for path %s", searchName));
2097 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2102 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2104 cifs_strtoUCS((__le16 *) pSMB->FileName, searchName, PATH_MAX
2105 /* find define for this maxpathcomponent */
2107 name_len++; /* trailing null */
2109 } else { /* BB improve the check for buffer overruns BB */
2110 name_len = strnlen(searchName, PATH_MAX);
2111 name_len++; /* trailing null */
2112 strncpy(pSMB->FileName, searchName, name_len);
2115 params = 2 /* level */ + 4 /* rsrvd */ + name_len /* incl null */ ;
2116 pSMB->TotalDataCount = 0;
2117 pSMB->MaxParameterCount = cpu_to_le16(2);
2118 /* BB find exact max data count below from sess structure BB */
2119 pSMB->MaxDataCount = cpu_to_le16(4000);
2120 pSMB->MaxSetupCount = 0;
2124 pSMB->Reserved2 = 0;
2125 pSMB->ParameterOffset = cpu_to_le16(offsetof(
2126 struct smb_com_transaction2_qpi_req ,InformationLevel) - 4);
2127 pSMB->DataCount = 0;
2128 pSMB->DataOffset = 0;
2129 pSMB->SetupCount = 1;
2130 pSMB->Reserved3 = 0;
2131 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
2132 byte_count = params + 1 /* pad */ ;
2133 pSMB->TotalParameterCount = cpu_to_le16(params);
2134 pSMB->ParameterCount = pSMB->TotalParameterCount;
2135 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_LINK);
2136 pSMB->Reserved4 = 0;
2137 pSMB->hdr.smb_buf_length += byte_count;
2138 pSMB->ByteCount = cpu_to_le16(byte_count);
2140 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2141 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2143 cFYI(1, ("Send error in QuerySymLinkInfo = %d", rc));
2145 /* decode response */
2147 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
2148 if (rc || (pSMBr->ByteCount < 2))
2149 /* BB also check enough total bytes returned */
2150 rc = -EIO; /* bad smb */
2152 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
2153 __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
2155 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
2156 name_len = UniStrnlen((wchar_t *) ((char *)
2157 &pSMBr->hdr.Protocol +data_offset),
2158 min_t(const int, buflen,count) / 2);
2159 /* BB FIXME investigate remapping reserved chars here */
2160 cifs_strfromUCS_le(symlinkinfo,
2161 (__le16 *) ((char *)&pSMBr->hdr.Protocol +
2163 name_len, nls_codepage);
2165 strncpy(symlinkinfo,
2166 (char *) &pSMBr->hdr.Protocol +
2168 min_t(const int, buflen, count));
2170 symlinkinfo[buflen] = 0;
2171 /* just in case so calling code does not go off the end of buffer */
2174 cifs_buf_release(pSMB);
2176 goto querySymLinkRetry;
2180 /* Initialize NT TRANSACT SMB into small smb request buffer.
2181 This assumes that all NT TRANSACTS that we init here have
2182 total parm and data under about 400 bytes (to fit in small cifs
2183 buffer size), which is the case so far, it easily fits. NB:
2184 Setup words themselves and ByteCount
2185 MaxSetupCount (size of returned setup area) and
2186 MaxParameterCount (returned parms size) must be set by caller */
2188 smb_init_ntransact(const __u16 sub_command, const int setup_count,
2189 const int parm_len, struct cifsTconInfo *tcon,
2194 struct smb_com_ntransact_req * pSMB;
2196 rc = small_smb_init(SMB_COM_NT_TRANSACT, 19 + setup_count, tcon,
2200 *ret_buf = (void *)pSMB;
2202 pSMB->TotalParameterCount = cpu_to_le32(parm_len);
2203 pSMB->TotalDataCount = 0;
2204 pSMB->MaxDataCount = cpu_to_le32((tcon->ses->server->maxBuf -
2205 MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
2206 pSMB->ParameterCount = pSMB->TotalParameterCount;
2207 pSMB->DataCount = pSMB->TotalDataCount;
2208 temp_offset = offsetof(struct smb_com_ntransact_req, Parms) +
2209 (setup_count * 2) - 4 /* for rfc1001 length itself */;
2210 pSMB->ParameterOffset = cpu_to_le32(temp_offset);
2211 pSMB->DataOffset = cpu_to_le32(temp_offset + parm_len);
2212 pSMB->SetupCount = setup_count; /* no need to le convert byte fields */
2213 pSMB->SubCommand = cpu_to_le16(sub_command);
2218 validate_ntransact(char * buf, char ** ppparm, char ** ppdata,
2219 int * pdatalen, int * pparmlen)
2222 __u32 data_count, data_offset, parm_count, parm_offset;
2223 struct smb_com_ntransact_rsp * pSMBr;
2228 pSMBr = (struct smb_com_ntransact_rsp *)buf;
2230 /* ByteCount was converted from little endian in SendReceive */
2231 end_of_smb = 2 /* sizeof byte count */ + pSMBr->ByteCount +
2232 (char *)&pSMBr->ByteCount;
2235 data_offset = le32_to_cpu(pSMBr->DataOffset);
2236 data_count = le32_to_cpu(pSMBr->DataCount);
2237 parm_offset = le32_to_cpu(pSMBr->ParameterOffset);
2238 parm_count = le32_to_cpu(pSMBr->ParameterCount);
2240 *ppparm = (char *)&pSMBr->hdr.Protocol + parm_offset;
2241 *ppdata = (char *)&pSMBr->hdr.Protocol + data_offset;
2243 /* should we also check that parm and data areas do not overlap? */
2244 if(*ppparm > end_of_smb) {
2245 cFYI(1,("parms start after end of smb"));
2247 } else if(parm_count + *ppparm > end_of_smb) {
2248 cFYI(1,("parm end after end of smb"));
2250 } else if(*ppdata > end_of_smb) {
2251 cFYI(1,("data starts after end of smb"));
2253 } else if(data_count + *ppdata > end_of_smb) {
2254 cFYI(1,("data %p + count %d (%p) ends after end of smb %p start %p",
2255 *ppdata, data_count, (data_count + *ppdata), end_of_smb, pSMBr)); /* BB FIXME */
2257 } else if(parm_count + data_count > pSMBr->ByteCount) {
2258 cFYI(1,("parm count and data count larger than SMB"));
2265 CIFSSMBQueryReparseLinkInfo(const int xid, struct cifsTconInfo *tcon,
2266 const unsigned char *searchName,
2267 char *symlinkinfo, const int buflen,__u16 fid,
2268 const struct nls_table *nls_codepage)
2273 struct smb_com_transaction_ioctl_req * pSMB;
2274 struct smb_com_transaction_ioctl_rsp * pSMBr;
2276 cFYI(1, ("In Windows reparse style QueryLink for path %s", searchName));
2277 rc = smb_init(SMB_COM_NT_TRANSACT, 23, tcon, (void **) &pSMB,
2282 pSMB->TotalParameterCount = 0 ;
2283 pSMB->TotalDataCount = 0;
2284 pSMB->MaxParameterCount = cpu_to_le32(2);
2285 /* BB find exact data count max from sess structure BB */
2286 pSMB->MaxDataCount = cpu_to_le32((tcon->ses->server->maxBuf -
2287 MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
2288 pSMB->MaxSetupCount = 4;
2290 pSMB->ParameterOffset = 0;
2291 pSMB->DataCount = 0;
2292 pSMB->DataOffset = 0;
2293 pSMB->SetupCount = 4;
2294 pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_IOCTL);
2295 pSMB->ParameterCount = pSMB->TotalParameterCount;
2296 pSMB->FunctionCode = cpu_to_le32(FSCTL_GET_REPARSE_POINT);
2297 pSMB->IsFsctl = 1; /* FSCTL */
2298 pSMB->IsRootFlag = 0;
2299 pSMB->Fid = fid; /* file handle always le */
2300 pSMB->ByteCount = 0;
2302 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2303 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2305 cFYI(1, ("Send error in QueryReparseLinkInfo = %d", rc));
2306 } else { /* decode response */
2307 __u32 data_offset = le32_to_cpu(pSMBr->DataOffset);
2308 __u32 data_count = le32_to_cpu(pSMBr->DataCount);
2309 if ((pSMBr->ByteCount < 2) || (data_offset > 512))
2310 /* BB also check enough total bytes returned */
2311 rc = -EIO; /* bad smb */
2313 if(data_count && (data_count < 2048)) {
2314 char * end_of_smb = 2 /* sizeof byte count */ +
2316 (char *)&pSMBr->ByteCount;
2318 struct reparse_data * reparse_buf = (struct reparse_data *)
2319 ((char *)&pSMBr->hdr.Protocol + data_offset);
2320 if((char*)reparse_buf >= end_of_smb) {
2324 if((reparse_buf->LinkNamesBuf +
2325 reparse_buf->TargetNameOffset +
2326 reparse_buf->TargetNameLen) >
2328 cFYI(1,("reparse buf extended beyond SMB"));
2333 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
2334 name_len = UniStrnlen((wchar_t *)
2335 (reparse_buf->LinkNamesBuf +
2336 reparse_buf->TargetNameOffset),
2337 min(buflen/2, reparse_buf->TargetNameLen / 2));
2338 cifs_strfromUCS_le(symlinkinfo,
2339 (__le16 *) (reparse_buf->LinkNamesBuf +
2340 reparse_buf->TargetNameOffset),
2341 name_len, nls_codepage);
2342 } else { /* ASCII names */
2343 strncpy(symlinkinfo,reparse_buf->LinkNamesBuf +
2344 reparse_buf->TargetNameOffset,
2345 min_t(const int, buflen, reparse_buf->TargetNameLen));
2349 cFYI(1,("Invalid return data count on get reparse info ioctl"));
2351 symlinkinfo[buflen] = 0; /* just in case so the caller
2352 does not go off the end of the buffer */
2353 cFYI(1,("readlink result - %s",symlinkinfo));
2357 cifs_buf_release(pSMB);
2359 /* Note: On -EAGAIN error only caller can retry on handle based calls
2360 since file handle passed in no longer valid */
2365 #ifdef CONFIG_CIFS_POSIX
2367 /*Convert an Access Control Entry from wire format to local POSIX xattr format*/
2368 static void cifs_convert_ace(posix_acl_xattr_entry * ace, struct cifs_posix_ace * cifs_ace)
2370 /* u8 cifs fields do not need le conversion */
2371 ace->e_perm = cpu_to_le16(cifs_ace->cifs_e_perm);
2372 ace->e_tag = cpu_to_le16(cifs_ace->cifs_e_tag);
2373 ace->e_id = cpu_to_le32(le64_to_cpu(cifs_ace->cifs_uid));
2374 /* cFYI(1,("perm %d tag %d id %d",ace->e_perm,ace->e_tag,ace->e_id)); */
2379 /* Convert ACL from CIFS POSIX wire format to local Linux POSIX ACL xattr */
2380 static int cifs_copy_posix_acl(char * trgt,char * src, const int buflen,
2381 const int acl_type,const int size_of_data_area)
2386 struct cifs_posix_ace * pACE;
2387 struct cifs_posix_acl * cifs_acl = (struct cifs_posix_acl *)src;
2388 posix_acl_xattr_header * local_acl = (posix_acl_xattr_header *)trgt;
2390 if (le16_to_cpu(cifs_acl->version) != CIFS_ACL_VERSION)
2393 if(acl_type & ACL_TYPE_ACCESS) {
2394 count = le16_to_cpu(cifs_acl->access_entry_count);
2395 pACE = &cifs_acl->ace_array[0];
2396 size = sizeof(struct cifs_posix_acl);
2397 size += sizeof(struct cifs_posix_ace) * count;
2398 /* check if we would go beyond end of SMB */
2399 if(size_of_data_area < size) {
2400 cFYI(1,("bad CIFS POSIX ACL size %d vs. %d",size_of_data_area,size));
2403 } else if(acl_type & ACL_TYPE_DEFAULT) {
2404 count = le16_to_cpu(cifs_acl->access_entry_count);
2405 size = sizeof(struct cifs_posix_acl);
2406 size += sizeof(struct cifs_posix_ace) * count;
2407 /* skip past access ACEs to get to default ACEs */
2408 pACE = &cifs_acl->ace_array[count];
2409 count = le16_to_cpu(cifs_acl->default_entry_count);
2410 size += sizeof(struct cifs_posix_ace) * count;
2411 /* check if we would go beyond end of SMB */
2412 if(size_of_data_area < size)
2419 size = posix_acl_xattr_size(count);
2420 if((buflen == 0) || (local_acl == NULL)) {
2421 /* used to query ACL EA size */
2422 } else if(size > buflen) {
2424 } else /* buffer big enough */ {
2425 local_acl->a_version = cpu_to_le32(POSIX_ACL_XATTR_VERSION);
2426 for(i = 0;i < count ;i++) {
2427 cifs_convert_ace(&local_acl->a_entries[i],pACE);
2434 static __u16 convert_ace_to_cifs_ace(struct cifs_posix_ace * cifs_ace,
2435 const posix_acl_xattr_entry * local_ace)
2437 __u16 rc = 0; /* 0 = ACL converted ok */
2439 cifs_ace->cifs_e_perm = le16_to_cpu(local_ace->e_perm);
2440 cifs_ace->cifs_e_tag = le16_to_cpu(local_ace->e_tag);
2441 /* BB is there a better way to handle the large uid? */
2442 if(local_ace->e_id == cpu_to_le32(-1)) {
2443 /* Probably no need to le convert -1 on any arch but can not hurt */
2444 cifs_ace->cifs_uid = cpu_to_le64(-1);
2446 cifs_ace->cifs_uid = cpu_to_le64(le32_to_cpu(local_ace->e_id));
2447 /*cFYI(1,("perm %d tag %d id %d",ace->e_perm,ace->e_tag,ace->e_id));*/
2451 /* Convert ACL from local Linux POSIX xattr to CIFS POSIX ACL wire format */
2452 static __u16 ACL_to_cifs_posix(char * parm_data,const char * pACL,const int buflen,
2456 struct cifs_posix_acl * cifs_acl = (struct cifs_posix_acl *)parm_data;
2457 posix_acl_xattr_header * local_acl = (posix_acl_xattr_header *)pACL;
2461 if((buflen == 0) || (pACL == NULL) || (cifs_acl == NULL))
2464 count = posix_acl_xattr_count((size_t)buflen);
2465 cFYI(1,("setting acl with %d entries from buf of length %d and version of %d",
2466 count, buflen, le32_to_cpu(local_acl->a_version)));
2467 if(le32_to_cpu(local_acl->a_version) != 2) {
2468 cFYI(1,("unknown POSIX ACL version %d",
2469 le32_to_cpu(local_acl->a_version)));
2472 cifs_acl->version = cpu_to_le16(1);
2473 if(acl_type == ACL_TYPE_ACCESS)
2474 cifs_acl->access_entry_count = cpu_to_le16(count);
2475 else if(acl_type == ACL_TYPE_DEFAULT)
2476 cifs_acl->default_entry_count = cpu_to_le16(count);
2478 cFYI(1,("unknown ACL type %d",acl_type));
2481 for(i=0;i<count;i++) {
2482 rc = convert_ace_to_cifs_ace(&cifs_acl->ace_array[i],
2483 &local_acl->a_entries[i]);
2485 /* ACE not converted */
2490 rc = (__u16)(count * sizeof(struct cifs_posix_ace));
2491 rc += sizeof(struct cifs_posix_acl);
2492 /* BB add check to make sure ACL does not overflow SMB */
2498 CIFSSMBGetPosixACL(const int xid, struct cifsTconInfo *tcon,
2499 const unsigned char *searchName,
2500 char *acl_inf, const int buflen, const int acl_type,
2501 const struct nls_table *nls_codepage, int remap)
2503 /* SMB_QUERY_POSIX_ACL */
2504 TRANSACTION2_QPI_REQ *pSMB = NULL;
2505 TRANSACTION2_QPI_RSP *pSMBr = NULL;
2509 __u16 params, byte_count;
2511 cFYI(1, ("In GetPosixACL (Unix) for path %s", searchName));
2514 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2519 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2521 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
2522 PATH_MAX, nls_codepage, remap);
2523 name_len++; /* trailing null */
2525 pSMB->FileName[name_len] = 0;
2526 pSMB->FileName[name_len+1] = 0;
2527 } else { /* BB improve the check for buffer overruns BB */
2528 name_len = strnlen(searchName, PATH_MAX);
2529 name_len++; /* trailing null */
2530 strncpy(pSMB->FileName, searchName, name_len);
2533 params = 2 /* level */ + 4 /* rsrvd */ + name_len /* incl null */ ;
2534 pSMB->TotalDataCount = 0;
2535 pSMB->MaxParameterCount = cpu_to_le16(2);
2536 /* BB find exact max data count below from sess structure BB */
2537 pSMB->MaxDataCount = cpu_to_le16(4000);
2538 pSMB->MaxSetupCount = 0;
2542 pSMB->Reserved2 = 0;
2543 pSMB->ParameterOffset = cpu_to_le16(
2544 offsetof(struct smb_com_transaction2_qpi_req ,InformationLevel) - 4);
2545 pSMB->DataCount = 0;
2546 pSMB->DataOffset = 0;
2547 pSMB->SetupCount = 1;
2548 pSMB->Reserved3 = 0;
2549 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
2550 byte_count = params + 1 /* pad */ ;
2551 pSMB->TotalParameterCount = cpu_to_le16(params);
2552 pSMB->ParameterCount = pSMB->TotalParameterCount;
2553 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_POSIX_ACL);
2554 pSMB->Reserved4 = 0;
2555 pSMB->hdr.smb_buf_length += byte_count;
2556 pSMB->ByteCount = cpu_to_le16(byte_count);
2558 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2559 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2560 cifs_stats_inc(&tcon->num_acl_get);
2562 cFYI(1, ("Send error in Query POSIX ACL = %d", rc));
2564 /* decode response */
2566 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
2567 if (rc || (pSMBr->ByteCount < 2))
2568 /* BB also check enough total bytes returned */
2569 rc = -EIO; /* bad smb */
2571 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
2572 __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
2573 rc = cifs_copy_posix_acl(acl_inf,
2574 (char *)&pSMBr->hdr.Protocol+data_offset,
2575 buflen,acl_type,count);
2578 cifs_buf_release(pSMB);
2585 CIFSSMBSetPosixACL(const int xid, struct cifsTconInfo *tcon,
2586 const unsigned char *fileName,
2587 const char *local_acl, const int buflen,
2589 const struct nls_table *nls_codepage, int remap)
2591 struct smb_com_transaction2_spi_req *pSMB = NULL;
2592 struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
2596 int bytes_returned = 0;
2597 __u16 params, byte_count, data_count, param_offset, offset;
2599 cFYI(1, ("In SetPosixACL (Unix) for path %s", fileName));
2601 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2605 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2607 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
2608 PATH_MAX, nls_codepage, remap);
2609 name_len++; /* trailing null */
2611 } else { /* BB improve the check for buffer overruns BB */
2612 name_len = strnlen(fileName, PATH_MAX);
2613 name_len++; /* trailing null */
2614 strncpy(pSMB->FileName, fileName, name_len);
2616 params = 6 + name_len;
2617 pSMB->MaxParameterCount = cpu_to_le16(2);
2618 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB size from sess */
2619 pSMB->MaxSetupCount = 0;
2623 pSMB->Reserved2 = 0;
2624 param_offset = offsetof(struct smb_com_transaction2_spi_req,
2625 InformationLevel) - 4;
2626 offset = param_offset + params;
2627 parm_data = ((char *) &pSMB->hdr.Protocol) + offset;
2628 pSMB->ParameterOffset = cpu_to_le16(param_offset);
2630 /* convert to on the wire format for POSIX ACL */
2631 data_count = ACL_to_cifs_posix(parm_data,local_acl,buflen,acl_type);
2633 if(data_count == 0) {
2635 goto setACLerrorExit;
2637 pSMB->DataOffset = cpu_to_le16(offset);
2638 pSMB->SetupCount = 1;
2639 pSMB->Reserved3 = 0;
2640 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
2641 pSMB->InformationLevel = cpu_to_le16(SMB_SET_POSIX_ACL);
2642 byte_count = 3 /* pad */ + params + data_count;
2643 pSMB->DataCount = cpu_to_le16(data_count);
2644 pSMB->TotalDataCount = pSMB->DataCount;
2645 pSMB->ParameterCount = cpu_to_le16(params);
2646 pSMB->TotalParameterCount = pSMB->ParameterCount;
2647 pSMB->Reserved4 = 0;
2648 pSMB->hdr.smb_buf_length += byte_count;
2649 pSMB->ByteCount = cpu_to_le16(byte_count);
2650 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2651 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2653 cFYI(1, ("Set POSIX ACL returned %d", rc));
2657 cifs_buf_release(pSMB);
2663 /* BB fix tabs in this function FIXME BB */
2665 CIFSGetExtAttr(const int xid, struct cifsTconInfo *tcon,
2666 const int netfid, __u64 * pExtAttrBits, __u64 *pMask)
2669 struct smb_t2_qfi_req *pSMB = NULL;
2670 struct smb_t2_qfi_rsp *pSMBr = NULL;
2672 __u16 params, byte_count;
2674 cFYI(1,("In GetExtAttr"));
2679 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2684 params = 2 /* level */ +2 /* fid */;
2685 pSMB->t2.TotalDataCount = 0;
2686 pSMB->t2.MaxParameterCount = cpu_to_le16(4);
2687 /* BB find exact max data count below from sess structure BB */
2688 pSMB->t2.MaxDataCount = cpu_to_le16(4000);
2689 pSMB->t2.MaxSetupCount = 0;
2690 pSMB->t2.Reserved = 0;
2692 pSMB->t2.Timeout = 0;
2693 pSMB->t2.Reserved2 = 0;
2694 pSMB->t2.ParameterOffset = cpu_to_le16(offsetof(struct smb_t2_qfi_req,
2696 pSMB->t2.DataCount = 0;
2697 pSMB->t2.DataOffset = 0;
2698 pSMB->t2.SetupCount = 1;
2699 pSMB->t2.Reserved3 = 0;
2700 pSMB->t2.SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION);
2701 byte_count = params + 1 /* pad */ ;
2702 pSMB->t2.TotalParameterCount = cpu_to_le16(params);
2703 pSMB->t2.ParameterCount = pSMB->t2.TotalParameterCount;
2704 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_ATTR_FLAGS);
2707 pSMB->hdr.smb_buf_length += byte_count;
2708 pSMB->t2.ByteCount = cpu_to_le16(byte_count);
2710 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2711 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2713 cFYI(1, ("error %d in GetExtAttr", rc));
2715 /* decode response */
2716 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
2717 if (rc || (pSMBr->ByteCount < 2))
2718 /* BB also check enough total bytes returned */
2719 /* If rc should we check for EOPNOSUPP and
2720 disable the srvino flag? or in caller? */
2721 rc = -EIO; /* bad smb */
2723 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
2724 __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
2725 struct file_chattr_info * pfinfo;
2726 /* BB Do we need a cast or hash here ? */
2728 cFYI(1, ("Illegal size ret in GetExtAttr"));
2732 pfinfo = (struct file_chattr_info *)
2733 (data_offset + (char *) &pSMBr->hdr.Protocol);
2734 *pExtAttrBits = le64_to_cpu(pfinfo->mode);
2735 *pMask = le64_to_cpu(pfinfo->mask);
2739 cifs_buf_release(pSMB);
2741 goto GetExtAttrRetry;
2746 #endif /* CONFIG_POSIX */
2749 /* security id for everyone */
2750 const struct cifs_sid sid_everyone = {1, 1, {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0}};
2752 const struct cifs_sid sid_user = {1, 2 , {0, 0, 0, 0, 0, 5}, {32, 545, 0, 0}};
2754 /* Convert CIFS ACL to POSIX form */
2755 static int parse_sec_desc(struct cifs_sid * psec_desc, int acl_len)
2760 /* Get Security Descriptor (by handle) from remote server for a file or dir */
2762 CIFSSMBGetCIFSACL(const int xid, struct cifsTconInfo *tcon, __u16 fid,
2763 /* BB fix up return info */ char *acl_inf, const int buflen,
2764 const int acl_type /* ACCESS/DEFAULT not sure implication */)
2768 QUERY_SEC_DESC_REQ * pSMB;
2771 cFYI(1, ("GetCifsACL"));
2773 rc = smb_init_ntransact(NT_TRANSACT_QUERY_SECURITY_DESC, 0,
2774 8 /* parm len */, tcon, (void **) &pSMB);
2778 pSMB->MaxParameterCount = cpu_to_le32(4);
2779 /* BB TEST with big acls that might need to be e.g. larger than 16K */
2780 pSMB->MaxSetupCount = 0;
2781 pSMB->Fid = fid; /* file handle always le */
2782 pSMB->AclFlags = cpu_to_le32(CIFS_ACL_OWNER | CIFS_ACL_GROUP |
2784 pSMB->ByteCount = cpu_to_le16(11); /* 3 bytes pad + 8 bytes parm */
2785 pSMB->hdr.smb_buf_length += 11;
2786 iov[0].iov_base = (char *)pSMB;
2787 iov[0].iov_len = pSMB->hdr.smb_buf_length + 4;
2789 rc = SendReceive2(xid, tcon->ses, iov, 1 /* num iovec */, &buf_type, 0);
2790 cifs_stats_inc(&tcon->num_acl_get);
2792 cFYI(1, ("Send error in QuerySecDesc = %d", rc));
2793 } else { /* decode response */
2794 struct cifs_sid * psec_desc;
2799 struct smb_com_ntransact_rsp * pSMBr;
2801 /* validate_nttransact */
2802 rc = validate_ntransact(iov[0].iov_base, (char **)&parm,
2803 (char **)&psec_desc,
2804 &parm_len, &data_len);
2808 pSMBr = (struct smb_com_ntransact_rsp *)iov[0].iov_base;
2810 cERROR(1,("smb %p parm %p data %p",pSMBr,parm,psec_desc)); /* BB removeme BB */
2812 if (le32_to_cpu(pSMBr->ParameterCount) != 4) {
2813 rc = -EIO; /* bad smb */
2817 /* BB check that data area is minimum length and as big as acl_len */
2819 acl_len = le32_to_cpu(*(__le32 *)parm);
2820 /* BB check if(acl_len > bufsize) */
2822 parse_sec_desc(psec_desc, acl_len);
2825 if(buf_type == CIFS_SMALL_BUFFER)
2826 cifs_small_buf_release(iov[0].iov_base);
2827 else if(buf_type == CIFS_LARGE_BUFFER)
2828 cifs_buf_release(iov[0].iov_base);
2829 /* cifs_small_buf_release(pSMB); */ /* Freed earlier now in SendReceive2 */
2834 /* Legacy Query Path Information call for lookup to old servers such
2836 int SMBQueryInformation(const int xid, struct cifsTconInfo *tcon,
2837 const unsigned char *searchName,
2838 FILE_ALL_INFO * pFinfo,
2839 const struct nls_table *nls_codepage, int remap)
2841 QUERY_INFORMATION_REQ * pSMB;
2842 QUERY_INFORMATION_RSP * pSMBr;
2847 cFYI(1, ("In SMBQPath path %s", searchName));
2849 rc = smb_init(SMB_COM_QUERY_INFORMATION, 0, tcon, (void **) &pSMB,
2854 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2856 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
2857 PATH_MAX, nls_codepage, remap);
2858 name_len++; /* trailing null */
2861 name_len = strnlen(searchName, PATH_MAX);
2862 name_len++; /* trailing null */
2863 strncpy(pSMB->FileName, searchName, name_len);
2865 pSMB->BufferFormat = 0x04;
2866 name_len++; /* account for buffer type byte */
2867 pSMB->hdr.smb_buf_length += (__u16) name_len;
2868 pSMB->ByteCount = cpu_to_le16(name_len);
2870 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2871 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2873 cFYI(1, ("Send error in QueryInfo = %d", rc));
2874 } else if (pFinfo) { /* decode response */
2875 memset(pFinfo, 0, sizeof(FILE_ALL_INFO));
2876 pFinfo->AllocationSize =
2877 cpu_to_le64(le32_to_cpu(pSMBr->size));
2878 pFinfo->EndOfFile = pFinfo->AllocationSize;
2879 pFinfo->Attributes =
2880 cpu_to_le32(le16_to_cpu(pSMBr->attr));
2882 rc = -EIO; /* bad buffer passed in */
2884 cifs_buf_release(pSMB);
2896 CIFSSMBQPathInfo(const int xid, struct cifsTconInfo *tcon,
2897 const unsigned char *searchName,
2898 FILE_ALL_INFO * pFindData,
2899 const struct nls_table *nls_codepage, int remap)
2901 /* level 263 SMB_QUERY_FILE_ALL_INFO */
2902 TRANSACTION2_QPI_REQ *pSMB = NULL;
2903 TRANSACTION2_QPI_RSP *pSMBr = NULL;
2907 __u16 params, byte_count;
2909 /* cFYI(1, ("In QPathInfo path %s", searchName)); */
2911 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2916 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2918 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
2919 PATH_MAX, nls_codepage, remap);
2920 name_len++; /* trailing null */
2922 } else { /* BB improve the check for buffer overruns BB */
2923 name_len = strnlen(searchName, PATH_MAX);
2924 name_len++; /* trailing null */
2925 strncpy(pSMB->FileName, searchName, name_len);
2928 params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */ ;
2929 pSMB->TotalDataCount = 0;
2930 pSMB->MaxParameterCount = cpu_to_le16(2);
2931 pSMB->MaxDataCount = cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
2932 pSMB->MaxSetupCount = 0;
2936 pSMB->Reserved2 = 0;
2937 pSMB->ParameterOffset = cpu_to_le16(offsetof(
2938 struct smb_com_transaction2_qpi_req ,InformationLevel) - 4);
2939 pSMB->DataCount = 0;
2940 pSMB->DataOffset = 0;
2941 pSMB->SetupCount = 1;
2942 pSMB->Reserved3 = 0;
2943 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
2944 byte_count = params + 1 /* pad */ ;
2945 pSMB->TotalParameterCount = cpu_to_le16(params);
2946 pSMB->ParameterCount = pSMB->TotalParameterCount;
2947 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_ALL_INFO);
2948 pSMB->Reserved4 = 0;
2949 pSMB->hdr.smb_buf_length += byte_count;
2950 pSMB->ByteCount = cpu_to_le16(byte_count);
2952 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2953 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2955 cFYI(1, ("Send error in QPathInfo = %d", rc));
2956 } else { /* decode response */
2957 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
2959 if (rc || (pSMBr->ByteCount < 40))
2960 rc = -EIO; /* bad smb */
2961 else if (pFindData){
2962 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
2963 memcpy((char *) pFindData,
2964 (char *) &pSMBr->hdr.Protocol +
2965 data_offset, sizeof (FILE_ALL_INFO));
2969 cifs_buf_release(pSMB);
2971 goto QPathInfoRetry;
2977 CIFSSMBUnixQPathInfo(const int xid, struct cifsTconInfo *tcon,
2978 const unsigned char *searchName,
2979 FILE_UNIX_BASIC_INFO * pFindData,
2980 const struct nls_table *nls_codepage, int remap)
2982 /* SMB_QUERY_FILE_UNIX_BASIC */
2983 TRANSACTION2_QPI_REQ *pSMB = NULL;
2984 TRANSACTION2_QPI_RSP *pSMBr = NULL;
2986 int bytes_returned = 0;
2988 __u16 params, byte_count;
2990 cFYI(1, ("In QPathInfo (Unix) the path %s", searchName));
2992 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2997 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2999 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
3000 PATH_MAX, nls_codepage, remap);
3001 name_len++; /* trailing null */
3003 } else { /* BB improve the check for buffer overruns BB */
3004 name_len = strnlen(searchName, PATH_MAX);
3005 name_len++; /* trailing null */
3006 strncpy(pSMB->FileName, searchName, name_len);
3009 params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */ ;
3010 pSMB->TotalDataCount = 0;
3011 pSMB->MaxParameterCount = cpu_to_le16(2);
3012 /* BB find exact max SMB PDU from sess structure BB */
3013 pSMB->MaxDataCount = cpu_to_le16(4000);
3014 pSMB->MaxSetupCount = 0;
3018 pSMB->Reserved2 = 0;
3019 pSMB->ParameterOffset = cpu_to_le16(offsetof(
3020 struct smb_com_transaction2_qpi_req ,InformationLevel) - 4);
3021 pSMB->DataCount = 0;
3022 pSMB->DataOffset = 0;
3023 pSMB->SetupCount = 1;
3024 pSMB->Reserved3 = 0;
3025 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
3026 byte_count = params + 1 /* pad */ ;
3027 pSMB->TotalParameterCount = cpu_to_le16(params);
3028 pSMB->ParameterCount = pSMB->TotalParameterCount;
3029 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC);
3030 pSMB->Reserved4 = 0;
3031 pSMB->hdr.smb_buf_length += byte_count;
3032 pSMB->ByteCount = cpu_to_le16(byte_count);
3034 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3035 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3037 cFYI(1, ("Send error in QPathInfo = %d", rc));
3038 } else { /* decode response */
3039 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3041 if (rc || (pSMBr->ByteCount < sizeof(FILE_UNIX_BASIC_INFO))) {
3042 rc = -EIO; /* bad smb */
3044 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3045 memcpy((char *) pFindData,
3046 (char *) &pSMBr->hdr.Protocol +
3048 sizeof (FILE_UNIX_BASIC_INFO));
3051 cifs_buf_release(pSMB);
3053 goto UnixQPathInfoRetry;
3058 #if 0 /* function unused at present */
3059 int CIFSFindSingle(const int xid, struct cifsTconInfo *tcon,
3060 const char *searchName, FILE_ALL_INFO * findData,
3061 const struct nls_table *nls_codepage)
3063 /* level 257 SMB_ */
3064 TRANSACTION2_FFIRST_REQ *pSMB = NULL;
3065 TRANSACTION2_FFIRST_RSP *pSMBr = NULL;
3069 __u16 params, byte_count;
3071 cFYI(1, ("In FindUnique"));
3073 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3078 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3080 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName, PATH_MAX
3081 /* find define for this maxpathcomponent */
3083 name_len++; /* trailing null */
3085 } else { /* BB improve the check for buffer overruns BB */
3086 name_len = strnlen(searchName, PATH_MAX);
3087 name_len++; /* trailing null */
3088 strncpy(pSMB->FileName, searchName, name_len);
3091 params = 12 + name_len /* includes null */ ;
3092 pSMB->TotalDataCount = 0; /* no EAs */
3093 pSMB->MaxParameterCount = cpu_to_le16(2);
3094 pSMB->MaxDataCount = cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
3095 pSMB->MaxSetupCount = 0;
3099 pSMB->Reserved2 = 0;
3100 pSMB->ParameterOffset = cpu_to_le16(
3101 offsetof(struct smb_com_transaction2_ffirst_req,InformationLevel) - 4);
3102 pSMB->DataCount = 0;
3103 pSMB->DataOffset = 0;
3104 pSMB->SetupCount = 1; /* one byte, no need to le convert */
3105 pSMB->Reserved3 = 0;
3106 pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_FIRST);
3107 byte_count = params + 1 /* pad */ ;
3108 pSMB->TotalParameterCount = cpu_to_le16(params);
3109 pSMB->ParameterCount = pSMB->TotalParameterCount;
3110 pSMB->SearchAttributes =
3111 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
3113 pSMB->SearchCount = cpu_to_le16(16); /* BB increase */
3114 pSMB->SearchFlags = cpu_to_le16(1);
3115 pSMB->InformationLevel = cpu_to_le16(SMB_FIND_FILE_DIRECTORY_INFO);
3116 pSMB->SearchStorageType = 0; /* BB what should we set this to? BB */
3117 pSMB->hdr.smb_buf_length += byte_count;
3118 pSMB->ByteCount = cpu_to_le16(byte_count);
3120 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3121 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3124 cFYI(1, ("Send error in FindFileDirInfo = %d", rc));
3125 } else { /* decode response */
3126 cifs_stats_inc(&tcon->num_ffirst);
3130 cifs_buf_release(pSMB);
3132 goto findUniqueRetry;
3136 #endif /* end unused (temporarily) function */
3138 /* xid, tcon, searchName and codepage are input parms, rest are returned */
3140 CIFSFindFirst(const int xid, struct cifsTconInfo *tcon,
3141 const char *searchName,
3142 const struct nls_table *nls_codepage,
3144 struct cifs_search_info * psrch_inf, int remap, const char dirsep)
3146 /* level 257 SMB_ */
3147 TRANSACTION2_FFIRST_REQ *pSMB = NULL;
3148 TRANSACTION2_FFIRST_RSP *pSMBr = NULL;
3149 T2_FFIRST_RSP_PARMS * parms;
3151 int bytes_returned = 0;
3153 __u16 params, byte_count;
3155 cFYI(1, ("In FindFirst for %s",searchName));
3158 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3163 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3165 cifsConvertToUCS((__le16 *) pSMB->FileName,searchName,
3166 PATH_MAX, nls_codepage, remap);
3167 /* We can not add the asterik earlier in case
3168 it got remapped to 0xF03A as if it were part of the
3169 directory name instead of a wildcard */
3171 pSMB->FileName[name_len] = dirsep;
3172 pSMB->FileName[name_len+1] = 0;
3173 pSMB->FileName[name_len+2] = '*';
3174 pSMB->FileName[name_len+3] = 0;
3175 name_len += 4; /* now the trailing null */
3176 pSMB->FileName[name_len] = 0; /* null terminate just in case */
3177 pSMB->FileName[name_len+1] = 0;
3179 } else { /* BB add check for overrun of SMB buf BB */
3180 name_len = strnlen(searchName, PATH_MAX);
3181 /* BB fix here and in unicode clause above ie
3182 if(name_len > buffersize-header)
3183 free buffer exit; BB */
3184 strncpy(pSMB->FileName, searchName, name_len);
3185 pSMB->FileName[name_len] = dirsep;
3186 pSMB->FileName[name_len+1] = '*';
3187 pSMB->FileName[name_len+2] = 0;
3191 params = 12 + name_len /* includes null */ ;
3192 pSMB->TotalDataCount = 0; /* no EAs */
3193 pSMB->MaxParameterCount = cpu_to_le16(10);
3194 pSMB->MaxDataCount = cpu_to_le16((tcon->ses->server->maxBuf -
3195 MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
3196 pSMB->MaxSetupCount = 0;
3200 pSMB->Reserved2 = 0;
3201 byte_count = params + 1 /* pad */ ;
3202 pSMB->TotalParameterCount = cpu_to_le16(params);
3203 pSMB->ParameterCount = pSMB->TotalParameterCount;
3204 pSMB->ParameterOffset = cpu_to_le16(
3205 offsetof(struct smb_com_transaction2_ffirst_req, SearchAttributes)
3207 pSMB->DataCount = 0;
3208 pSMB->DataOffset = 0;
3209 pSMB->SetupCount = 1; /* one byte, no need to make endian neutral */
3210 pSMB->Reserved3 = 0;
3211 pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_FIRST);
3212 pSMB->SearchAttributes =
3213 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
3215 pSMB->SearchCount= cpu_to_le16(CIFSMaxBufSize/sizeof(FILE_UNIX_INFO));
3216 pSMB->SearchFlags = cpu_to_le16(CIFS_SEARCH_CLOSE_AT_END |
3217 CIFS_SEARCH_RETURN_RESUME);
3218 pSMB->InformationLevel = cpu_to_le16(psrch_inf->info_level);
3220 /* BB what should we set StorageType to? Does it matter? BB */
3221 pSMB->SearchStorageType = 0;
3222 pSMB->hdr.smb_buf_length += byte_count;
3223 pSMB->ByteCount = cpu_to_le16(byte_count);
3225 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3226 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3227 cifs_stats_inc(&tcon->num_ffirst);
3229 if (rc) {/* BB add logic to retry regular search if Unix search
3230 rejected unexpectedly by server */
3231 /* BB Add code to handle unsupported level rc */
3232 cFYI(1, ("Error in FindFirst = %d", rc));
3234 cifs_buf_release(pSMB);
3236 /* BB eventually could optimize out free and realloc of buf */
3239 goto findFirstRetry;
3240 } else { /* decode response */
3241 /* BB remember to free buffer if error BB */
3242 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3244 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
3245 psrch_inf->unicode = TRUE;
3247 psrch_inf->unicode = FALSE;
3249 psrch_inf->ntwrk_buf_start = (char *)pSMBr;
3250 psrch_inf->smallBuf = 0;
3251 psrch_inf->srch_entries_start =
3252 (char *) &pSMBr->hdr.Protocol +
3253 le16_to_cpu(pSMBr->t2.DataOffset);
3254 parms = (T2_FFIRST_RSP_PARMS *)((char *) &pSMBr->hdr.Protocol +
3255 le16_to_cpu(pSMBr->t2.ParameterOffset));
3257 if(parms->EndofSearch)
3258 psrch_inf->endOfSearch = TRUE;
3260 psrch_inf->endOfSearch = FALSE;
3262 psrch_inf->entries_in_buffer = le16_to_cpu(parms->SearchCount);
3263 psrch_inf->index_of_last_entry = 2 /* skip . and .. */ +
3264 psrch_inf->entries_in_buffer;
3265 *pnetfid = parms->SearchHandle;
3267 cifs_buf_release(pSMB);
3274 int CIFSFindNext(const int xid, struct cifsTconInfo *tcon,
3275 __u16 searchHandle, struct cifs_search_info * psrch_inf)
3277 TRANSACTION2_FNEXT_REQ *pSMB = NULL;
3278 TRANSACTION2_FNEXT_RSP *pSMBr = NULL;
3279 T2_FNEXT_RSP_PARMS * parms;
3280 char *response_data;
3282 int bytes_returned, name_len;
3283 __u16 params, byte_count;
3285 cFYI(1, ("In FindNext"));
3287 if(psrch_inf->endOfSearch == TRUE)
3290 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3295 params = 14; /* includes 2 bytes of null string, converted to LE below */
3297 pSMB->TotalDataCount = 0; /* no EAs */
3298 pSMB->MaxParameterCount = cpu_to_le16(8);
3299 pSMB->MaxDataCount =
3300 cpu_to_le16((tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
3301 pSMB->MaxSetupCount = 0;
3305 pSMB->Reserved2 = 0;
3306 pSMB->ParameterOffset = cpu_to_le16(
3307 offsetof(struct smb_com_transaction2_fnext_req,SearchHandle) - 4);
3308 pSMB->DataCount = 0;
3309 pSMB->DataOffset = 0;
3310 pSMB->SetupCount = 1;
3311 pSMB->Reserved3 = 0;
3312 pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_NEXT);
3313 pSMB->SearchHandle = searchHandle; /* always kept as le */
3315 cpu_to_le16(CIFSMaxBufSize / sizeof (FILE_UNIX_INFO));
3316 /* test for Unix extensions */
3317 /* if (tcon->ses->capabilities & CAP_UNIX) {
3318 pSMB->InformationLevel = cpu_to_le16(SMB_FIND_FILE_UNIX);
3319 psrch_inf->info_level = SMB_FIND_FILE_UNIX;
3321 pSMB->InformationLevel =
3322 cpu_to_le16(SMB_FIND_FILE_DIRECTORY_INFO);
3323 psrch_inf->info_level = SMB_FIND_FILE_DIRECTORY_INFO;
3325 pSMB->InformationLevel = cpu_to_le16(psrch_inf->info_level);
3326 pSMB->ResumeKey = psrch_inf->resume_key;
3328 cpu_to_le16(CIFS_SEARCH_CLOSE_AT_END | CIFS_SEARCH_RETURN_RESUME);
3330 name_len = psrch_inf->resume_name_len;
3332 if(name_len < PATH_MAX) {
3333 memcpy(pSMB->ResumeFileName, psrch_inf->presume_name, name_len);
3334 byte_count += name_len;
3335 /* 14 byte parm len above enough for 2 byte null terminator */
3336 pSMB->ResumeFileName[name_len] = 0;
3337 pSMB->ResumeFileName[name_len+1] = 0;
3340 goto FNext2_err_exit;
3342 byte_count = params + 1 /* pad */ ;
3343 pSMB->TotalParameterCount = cpu_to_le16(params);
3344 pSMB->ParameterCount = pSMB->TotalParameterCount;
3345 pSMB->hdr.smb_buf_length += byte_count;
3346 pSMB->ByteCount = cpu_to_le16(byte_count);
3348 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3349 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3350 cifs_stats_inc(&tcon->num_fnext);
3353 psrch_inf->endOfSearch = TRUE;
3354 rc = 0; /* search probably was closed at end of search above */
3356 cFYI(1, ("FindNext returned = %d", rc));
3357 } else { /* decode response */
3358 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3361 /* BB fixme add lock for file (srch_info) struct here */
3362 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
3363 psrch_inf->unicode = TRUE;
3365 psrch_inf->unicode = FALSE;
3366 response_data = (char *) &pSMBr->hdr.Protocol +
3367 le16_to_cpu(pSMBr->t2.ParameterOffset);
3368 parms = (T2_FNEXT_RSP_PARMS *)response_data;
3369 response_data = (char *)&pSMBr->hdr.Protocol +
3370 le16_to_cpu(pSMBr->t2.DataOffset);
3371 if(psrch_inf->smallBuf)
3372 cifs_small_buf_release(
3373 psrch_inf->ntwrk_buf_start);
3375 cifs_buf_release(psrch_inf->ntwrk_buf_start);
3376 psrch_inf->srch_entries_start = response_data;
3377 psrch_inf->ntwrk_buf_start = (char *)pSMB;
3378 psrch_inf->smallBuf = 0;
3379 if(parms->EndofSearch)
3380 psrch_inf->endOfSearch = TRUE;
3382 psrch_inf->endOfSearch = FALSE;
3384 psrch_inf->entries_in_buffer = le16_to_cpu(parms->SearchCount);
3385 psrch_inf->index_of_last_entry +=
3386 psrch_inf->entries_in_buffer;
3387 /* cFYI(1,("fnxt2 entries in buf %d index_of_last %d",psrch_inf->entries_in_buffer,psrch_inf->index_of_last_entry)); */
3389 /* BB fixme add unlock here */
3394 /* BB On error, should we leave previous search buf (and count and
3395 last entry fields) intact or free the previous one? */
3397 /* Note: On -EAGAIN error only caller can retry on handle based calls
3398 since file handle passed in no longer valid */
3401 cifs_buf_release(pSMB);
3407 CIFSFindClose(const int xid, struct cifsTconInfo *tcon, const __u16 searchHandle)
3410 FINDCLOSE_REQ *pSMB = NULL;
3411 CLOSE_RSP *pSMBr = NULL; /* BB removeme BB */
3414 cFYI(1, ("In CIFSSMBFindClose"));
3415 rc = small_smb_init(SMB_COM_FIND_CLOSE2, 1, tcon, (void **)&pSMB);
3417 /* no sense returning error if session restarted
3418 as file handle has been closed */
3424 pSMBr = (CLOSE_RSP *)pSMB; /* BB removeme BB */
3425 pSMB->FileID = searchHandle;
3426 pSMB->ByteCount = 0;
3427 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3428 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3430 cERROR(1, ("Send error in FindClose = %d", rc));
3432 cifs_stats_inc(&tcon->num_fclose);
3433 cifs_small_buf_release(pSMB);
3435 /* Since session is dead, search handle closed on server already */
3443 CIFSGetSrvInodeNumber(const int xid, struct cifsTconInfo *tcon,
3444 const unsigned char *searchName,
3445 __u64 * inode_number,
3446 const struct nls_table *nls_codepage, int remap)
3449 TRANSACTION2_QPI_REQ *pSMB = NULL;
3450 TRANSACTION2_QPI_RSP *pSMBr = NULL;
3451 int name_len, bytes_returned;
3452 __u16 params, byte_count;
3454 cFYI(1,("In GetSrvInodeNum for %s",searchName));
3458 GetInodeNumberRetry:
3459 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3465 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3467 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
3468 PATH_MAX,nls_codepage, remap);
3469 name_len++; /* trailing null */
3471 } else { /* BB improve the check for buffer overruns BB */
3472 name_len = strnlen(searchName, PATH_MAX);
3473 name_len++; /* trailing null */
3474 strncpy(pSMB->FileName, searchName, name_len);
3477 params = 2 /* level */ + 4 /* rsrvd */ + name_len /* incl null */ ;
3478 pSMB->TotalDataCount = 0;
3479 pSMB->MaxParameterCount = cpu_to_le16(2);
3480 /* BB find exact max data count below from sess structure BB */
3481 pSMB->MaxDataCount = cpu_to_le16(4000);
3482 pSMB->MaxSetupCount = 0;
3486 pSMB->Reserved2 = 0;
3487 pSMB->ParameterOffset = cpu_to_le16(offsetof(
3488 struct smb_com_transaction2_qpi_req ,InformationLevel) - 4);
3489 pSMB->DataCount = 0;
3490 pSMB->DataOffset = 0;
3491 pSMB->SetupCount = 1;
3492 pSMB->Reserved3 = 0;
3493 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
3494 byte_count = params + 1 /* pad */ ;
3495 pSMB->TotalParameterCount = cpu_to_le16(params);
3496 pSMB->ParameterCount = pSMB->TotalParameterCount;
3497 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_INTERNAL_INFO);
3498 pSMB->Reserved4 = 0;
3499 pSMB->hdr.smb_buf_length += byte_count;
3500 pSMB->ByteCount = cpu_to_le16(byte_count);
3502 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3503 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3505 cFYI(1, ("error %d in QueryInternalInfo", rc));
3507 /* decode response */
3508 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3509 if (rc || (pSMBr->ByteCount < 2))
3510 /* BB also check enough total bytes returned */
3511 /* If rc should we check for EOPNOSUPP and
3512 disable the srvino flag? or in caller? */
3513 rc = -EIO; /* bad smb */
3515 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3516 __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
3517 struct file_internal_info * pfinfo;
3518 /* BB Do we need a cast or hash here ? */
3520 cFYI(1, ("Illegal size ret in QryIntrnlInf"));
3522 goto GetInodeNumOut;
3524 pfinfo = (struct file_internal_info *)
3525 (data_offset + (char *) &pSMBr->hdr.Protocol);
3526 *inode_number = pfinfo->UniqueId;
3530 cifs_buf_release(pSMB);
3532 goto GetInodeNumberRetry;
3537 CIFSGetDFSRefer(const int xid, struct cifsSesInfo *ses,
3538 const unsigned char *searchName,
3539 unsigned char **targetUNCs,
3540 unsigned int *number_of_UNC_in_array,
3541 const struct nls_table *nls_codepage, int remap)
3543 /* TRANS2_GET_DFS_REFERRAL */
3544 TRANSACTION2_GET_DFS_REFER_REQ *pSMB = NULL;
3545 TRANSACTION2_GET_DFS_REFER_RSP *pSMBr = NULL;
3546 struct dfs_referral_level_3 * referrals = NULL;
3552 __u16 params, byte_count;
3553 *number_of_UNC_in_array = 0;
3556 cFYI(1, ("In GetDFSRefer the path %s", searchName));
3560 rc = smb_init(SMB_COM_TRANSACTION2, 15, NULL, (void **) &pSMB,
3565 /* server pointer checked in called function,
3566 but should never be null here anyway */
3567 pSMB->hdr.Mid = GetNextMid(ses->server);
3568 pSMB->hdr.Tid = ses->ipc_tid;
3569 pSMB->hdr.Uid = ses->Suid;
3570 if (ses->capabilities & CAP_STATUS32) {
3571 pSMB->hdr.Flags2 |= SMBFLG2_ERR_STATUS;
3573 if (ses->capabilities & CAP_DFS) {
3574 pSMB->hdr.Flags2 |= SMBFLG2_DFS;
3577 if (ses->capabilities & CAP_UNICODE) {
3578 pSMB->hdr.Flags2 |= SMBFLG2_UNICODE;
3580 cifsConvertToUCS((__le16 *) pSMB->RequestFileName,
3581 searchName, PATH_MAX, nls_codepage, remap);
3582 name_len++; /* trailing null */
3584 } else { /* BB improve the check for buffer overruns BB */
3585 name_len = strnlen(searchName, PATH_MAX);
3586 name_len++; /* trailing null */
3587 strncpy(pSMB->RequestFileName, searchName, name_len);
3590 params = 2 /* level */ + name_len /*includes null */ ;
3591 pSMB->TotalDataCount = 0;
3592 pSMB->DataCount = 0;
3593 pSMB->DataOffset = 0;
3594 pSMB->MaxParameterCount = 0;
3595 pSMB->MaxDataCount = cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
3596 pSMB->MaxSetupCount = 0;
3600 pSMB->Reserved2 = 0;
3601 pSMB->ParameterOffset = cpu_to_le16(offsetof(
3602 struct smb_com_transaction2_get_dfs_refer_req, MaxReferralLevel) - 4);
3603 pSMB->SetupCount = 1;
3604 pSMB->Reserved3 = 0;
3605 pSMB->SubCommand = cpu_to_le16(TRANS2_GET_DFS_REFERRAL);
3606 byte_count = params + 3 /* pad */ ;
3607 pSMB->ParameterCount = cpu_to_le16(params);
3608 pSMB->TotalParameterCount = pSMB->ParameterCount;
3609 pSMB->MaxReferralLevel = cpu_to_le16(3);
3610 pSMB->hdr.smb_buf_length += byte_count;
3611 pSMB->ByteCount = cpu_to_le16(byte_count);
3613 rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB,
3614 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3616 cFYI(1, ("Send error in GetDFSRefer = %d", rc));
3617 } else { /* decode response */
3618 /* BB Add logic to parse referrals here */
3619 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3621 if (rc || (pSMBr->ByteCount < 17)) /* BB also check enough total bytes returned */
3622 rc = -EIO; /* bad smb */
3624 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3625 __u16 data_count = le16_to_cpu(pSMBr->t2.DataCount);
3628 ("Decoding GetDFSRefer response. BCC: %d Offset %d",
3629 pSMBr->ByteCount, data_offset));
3631 (struct dfs_referral_level_3 *)
3632 (8 /* sizeof start of data block */ +
3634 (char *) &pSMBr->hdr.Protocol);
3635 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",
3636 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)));
3637 /* BB This field is actually two bytes in from start of
3638 data block so we could do safety check that DataBlock
3639 begins at address of pSMBr->NumberOfReferrals */
3640 *number_of_UNC_in_array = le16_to_cpu(pSMBr->NumberOfReferrals);
3642 /* BB Fix below so can return more than one referral */
3643 if(*number_of_UNC_in_array > 1)
3644 *number_of_UNC_in_array = 1;
3646 /* get the length of the strings describing refs */
3648 for(i=0;i<*number_of_UNC_in_array;i++) {
3649 /* make sure that DfsPathOffset not past end */
3650 __u16 offset = le16_to_cpu(referrals->DfsPathOffset);
3651 if (offset > data_count) {
3652 /* if invalid referral, stop here and do
3653 not try to copy any more */
3654 *number_of_UNC_in_array = i;
3657 temp = ((char *)referrals) + offset;
3659 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
3660 name_len += UniStrnlen((wchar_t *)temp,data_count);
3662 name_len += strnlen(temp,data_count);
3665 /* BB add check that referral pointer does not fall off end PDU */
3668 /* BB add check for name_len bigger than bcc */
3670 kmalloc(name_len+1+ (*number_of_UNC_in_array),GFP_KERNEL);
3671 if(*targetUNCs == NULL) {
3675 /* copy the ref strings */
3677 (struct dfs_referral_level_3 *)
3678 (8 /* sizeof data hdr */ +
3680 (char *) &pSMBr->hdr.Protocol);
3682 for(i=0;i<*number_of_UNC_in_array;i++) {
3683 temp = ((char *)referrals) + le16_to_cpu(referrals->DfsPathOffset);
3684 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
3685 cifs_strfromUCS_le(*targetUNCs,
3686 (__le16 *) temp, name_len, nls_codepage);
3688 strncpy(*targetUNCs,temp,name_len);
3690 /* BB update target_uncs pointers */
3700 cifs_buf_release(pSMB);
3708 /* Query File System Info such as free space to old servers such as Win 9x */
3710 SMBOldQFSInfo(const int xid, struct cifsTconInfo *tcon, struct kstatfs *FSData)
3712 /* level 0x01 SMB_QUERY_FILE_SYSTEM_INFO */
3713 TRANSACTION2_QFSI_REQ *pSMB = NULL;
3714 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
3715 FILE_SYSTEM_ALLOC_INFO *response_data;
3717 int bytes_returned = 0;
3718 __u16 params, byte_count;
3720 cFYI(1, ("OldQFSInfo"));
3722 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3726 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3731 params = 2; /* level */
3732 pSMB->TotalDataCount = 0;
3733 pSMB->MaxParameterCount = cpu_to_le16(2);
3734 pSMB->MaxDataCount = cpu_to_le16(1000);
3735 pSMB->MaxSetupCount = 0;
3739 pSMB->Reserved2 = 0;
3740 byte_count = params + 1 /* pad */ ;
3741 pSMB->TotalParameterCount = cpu_to_le16(params);
3742 pSMB->ParameterCount = pSMB->TotalParameterCount;
3743 pSMB->ParameterOffset = cpu_to_le16(offsetof(
3744 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
3745 pSMB->DataCount = 0;
3746 pSMB->DataOffset = 0;
3747 pSMB->SetupCount = 1;
3748 pSMB->Reserved3 = 0;
3749 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
3750 pSMB->InformationLevel = cpu_to_le16(SMB_INFO_ALLOCATION);
3751 pSMB->hdr.smb_buf_length += byte_count;
3752 pSMB->ByteCount = cpu_to_le16(byte_count);
3754 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3755 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3757 cFYI(1, ("Send error in QFSInfo = %d", rc));
3758 } else { /* decode response */
3759 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3761 if (rc || (pSMBr->ByteCount < 18))
3762 rc = -EIO; /* bad smb */
3764 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3765 cFYI(1,("qfsinf resp BCC: %d Offset %d",
3766 pSMBr->ByteCount, data_offset));
3769 (FILE_SYSTEM_ALLOC_INFO *)
3770 (((char *) &pSMBr->hdr.Protocol) + data_offset);
3772 le16_to_cpu(response_data->BytesPerSector) *
3773 le32_to_cpu(response_data->
3774 SectorsPerAllocationUnit);
3776 le32_to_cpu(response_data->TotalAllocationUnits);
3777 FSData->f_bfree = FSData->f_bavail =
3778 le32_to_cpu(response_data->FreeAllocationUnits);
3780 ("Blocks: %lld Free: %lld Block size %ld",
3781 (unsigned long long)FSData->f_blocks,
3782 (unsigned long long)FSData->f_bfree,
3786 cifs_buf_release(pSMB);
3789 goto oldQFSInfoRetry;
3795 CIFSSMBQFSInfo(const int xid, struct cifsTconInfo *tcon, struct kstatfs *FSData)
3797 /* level 0x103 SMB_QUERY_FILE_SYSTEM_INFO */
3798 TRANSACTION2_QFSI_REQ *pSMB = NULL;
3799 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
3800 FILE_SYSTEM_INFO *response_data;
3802 int bytes_returned = 0;
3803 __u16 params, byte_count;
3805 cFYI(1, ("In QFSInfo"));
3807 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3812 params = 2; /* level */
3813 pSMB->TotalDataCount = 0;
3814 pSMB->MaxParameterCount = cpu_to_le16(2);
3815 pSMB->MaxDataCount = cpu_to_le16(1000);
3816 pSMB->MaxSetupCount = 0;
3820 pSMB->Reserved2 = 0;
3821 byte_count = params + 1 /* pad */ ;
3822 pSMB->TotalParameterCount = cpu_to_le16(params);
3823 pSMB->ParameterCount = pSMB->TotalParameterCount;
3824 pSMB->ParameterOffset = cpu_to_le16(offsetof(
3825 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
3826 pSMB->DataCount = 0;
3827 pSMB->DataOffset = 0;
3828 pSMB->SetupCount = 1;
3829 pSMB->Reserved3 = 0;
3830 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
3831 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_SIZE_INFO);
3832 pSMB->hdr.smb_buf_length += byte_count;
3833 pSMB->ByteCount = cpu_to_le16(byte_count);
3835 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3836 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3838 cFYI(1, ("Send error in QFSInfo = %d", rc));
3839 } else { /* decode response */
3840 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3842 if (rc || (pSMBr->ByteCount < 24))
3843 rc = -EIO; /* bad smb */
3845 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3849 *) (((char *) &pSMBr->hdr.Protocol) +
3852 le32_to_cpu(response_data->BytesPerSector) *
3853 le32_to_cpu(response_data->
3854 SectorsPerAllocationUnit);
3856 le64_to_cpu(response_data->TotalAllocationUnits);
3857 FSData->f_bfree = FSData->f_bavail =
3858 le64_to_cpu(response_data->FreeAllocationUnits);
3860 ("Blocks: %lld Free: %lld Block size %ld",
3861 (unsigned long long)FSData->f_blocks,
3862 (unsigned long long)FSData->f_bfree,
3866 cifs_buf_release(pSMB);
3875 CIFSSMBQFSAttributeInfo(const int xid, struct cifsTconInfo *tcon)
3877 /* level 0x105 SMB_QUERY_FILE_SYSTEM_INFO */
3878 TRANSACTION2_QFSI_REQ *pSMB = NULL;
3879 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
3880 FILE_SYSTEM_ATTRIBUTE_INFO *response_data;
3882 int bytes_returned = 0;
3883 __u16 params, byte_count;
3885 cFYI(1, ("In QFSAttributeInfo"));
3887 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3892 params = 2; /* level */
3893 pSMB->TotalDataCount = 0;
3894 pSMB->MaxParameterCount = cpu_to_le16(2);
3895 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
3896 pSMB->MaxSetupCount = 0;
3900 pSMB->Reserved2 = 0;
3901 byte_count = params + 1 /* pad */ ;
3902 pSMB->TotalParameterCount = cpu_to_le16(params);
3903 pSMB->ParameterCount = pSMB->TotalParameterCount;
3904 pSMB->ParameterOffset = cpu_to_le16(offsetof(
3905 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
3906 pSMB->DataCount = 0;
3907 pSMB->DataOffset = 0;
3908 pSMB->SetupCount = 1;
3909 pSMB->Reserved3 = 0;
3910 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
3911 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_ATTRIBUTE_INFO);
3912 pSMB->hdr.smb_buf_length += byte_count;
3913 pSMB->ByteCount = cpu_to_le16(byte_count);
3915 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3916 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3918 cERROR(1, ("Send error in QFSAttributeInfo = %d", rc));
3919 } else { /* decode response */
3920 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3922 if (rc || (pSMBr->ByteCount < 13)) { /* BB also check enough bytes returned */
3923 rc = -EIO; /* bad smb */
3925 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3927 (FILE_SYSTEM_ATTRIBUTE_INFO
3928 *) (((char *) &pSMBr->hdr.Protocol) +
3930 memcpy(&tcon->fsAttrInfo, response_data,
3931 sizeof (FILE_SYSTEM_ATTRIBUTE_INFO));
3934 cifs_buf_release(pSMB);
3937 goto QFSAttributeRetry;
3943 CIFSSMBQFSDeviceInfo(const int xid, struct cifsTconInfo *tcon)
3945 /* level 0x104 SMB_QUERY_FILE_SYSTEM_INFO */
3946 TRANSACTION2_QFSI_REQ *pSMB = NULL;
3947 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
3948 FILE_SYSTEM_DEVICE_INFO *response_data;
3950 int bytes_returned = 0;
3951 __u16 params, byte_count;
3953 cFYI(1, ("In QFSDeviceInfo"));
3955 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3960 params = 2; /* level */
3961 pSMB->TotalDataCount = 0;
3962 pSMB->MaxParameterCount = cpu_to_le16(2);
3963 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
3964 pSMB->MaxSetupCount = 0;
3968 pSMB->Reserved2 = 0;
3969 byte_count = params + 1 /* pad */ ;
3970 pSMB->TotalParameterCount = cpu_to_le16(params);
3971 pSMB->ParameterCount = pSMB->TotalParameterCount;
3972 pSMB->ParameterOffset = cpu_to_le16(offsetof(
3973 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
3975 pSMB->DataCount = 0;
3976 pSMB->DataOffset = 0;
3977 pSMB->SetupCount = 1;
3978 pSMB->Reserved3 = 0;
3979 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
3980 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_DEVICE_INFO);
3981 pSMB->hdr.smb_buf_length += byte_count;
3982 pSMB->ByteCount = cpu_to_le16(byte_count);
3984 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3985 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3987 cFYI(1, ("Send error in QFSDeviceInfo = %d", rc));
3988 } else { /* decode response */
3989 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3991 if (rc || (pSMBr->ByteCount < sizeof (FILE_SYSTEM_DEVICE_INFO)))
3992 rc = -EIO; /* bad smb */
3994 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3996 (FILE_SYSTEM_DEVICE_INFO *)
3997 (((char *) &pSMBr->hdr.Protocol) +
3999 memcpy(&tcon->fsDevInfo, response_data,
4000 sizeof (FILE_SYSTEM_DEVICE_INFO));
4003 cifs_buf_release(pSMB);
4006 goto QFSDeviceRetry;
4012 CIFSSMBQFSUnixInfo(const int xid, struct cifsTconInfo *tcon)
4014 /* level 0x200 SMB_QUERY_CIFS_UNIX_INFO */
4015 TRANSACTION2_QFSI_REQ *pSMB = NULL;
4016 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4017 FILE_SYSTEM_UNIX_INFO *response_data;
4019 int bytes_returned = 0;
4020 __u16 params, byte_count;
4022 cFYI(1, ("In QFSUnixInfo"));
4024 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4029 params = 2; /* level */
4030 pSMB->TotalDataCount = 0;
4031 pSMB->DataCount = 0;
4032 pSMB->DataOffset = 0;
4033 pSMB->MaxParameterCount = cpu_to_le16(2);
4034 pSMB->MaxDataCount = cpu_to_le16(100); /* BB find exact max SMB PDU from sess structure BB */
4035 pSMB->MaxSetupCount = 0;
4039 pSMB->Reserved2 = 0;
4040 byte_count = params + 1 /* pad */ ;
4041 pSMB->ParameterCount = cpu_to_le16(params);
4042 pSMB->TotalParameterCount = pSMB->ParameterCount;
4043 pSMB->ParameterOffset = cpu_to_le16(offsetof(struct
4044 smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4045 pSMB->SetupCount = 1;
4046 pSMB->Reserved3 = 0;
4047 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4048 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_CIFS_UNIX_INFO);
4049 pSMB->hdr.smb_buf_length += byte_count;
4050 pSMB->ByteCount = cpu_to_le16(byte_count);
4052 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4053 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4055 cERROR(1, ("Send error in QFSUnixInfo = %d", rc));
4056 } else { /* decode response */
4057 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4059 if (rc || (pSMBr->ByteCount < 13)) {
4060 rc = -EIO; /* bad smb */
4062 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4064 (FILE_SYSTEM_UNIX_INFO
4065 *) (((char *) &pSMBr->hdr.Protocol) +
4067 memcpy(&tcon->fsUnixInfo, response_data,
4068 sizeof (FILE_SYSTEM_UNIX_INFO));
4071 cifs_buf_release(pSMB);
4081 CIFSSMBSetFSUnixInfo(const int xid, struct cifsTconInfo *tcon, __u64 cap)
4083 /* level 0x200 SMB_SET_CIFS_UNIX_INFO */
4084 TRANSACTION2_SETFSI_REQ *pSMB = NULL;
4085 TRANSACTION2_SETFSI_RSP *pSMBr = NULL;
4087 int bytes_returned = 0;
4088 __u16 params, param_offset, offset, byte_count;
4090 cFYI(1, ("In SETFSUnixInfo"));
4092 /* BB switch to small buf init to save memory */
4093 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4098 params = 4; /* 2 bytes zero followed by info level. */
4099 pSMB->MaxSetupCount = 0;
4103 pSMB->Reserved2 = 0;
4104 param_offset = offsetof(struct smb_com_transaction2_setfsi_req, FileNum) - 4;
4105 offset = param_offset + params;
4107 pSMB->MaxParameterCount = cpu_to_le16(4);
4108 pSMB->MaxDataCount = cpu_to_le16(100); /* BB find exact max SMB PDU from sess structure BB */
4109 pSMB->SetupCount = 1;
4110 pSMB->Reserved3 = 0;
4111 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FS_INFORMATION);
4112 byte_count = 1 /* pad */ + params + 12;
4114 pSMB->DataCount = cpu_to_le16(12);
4115 pSMB->ParameterCount = cpu_to_le16(params);
4116 pSMB->TotalDataCount = pSMB->DataCount;
4117 pSMB->TotalParameterCount = pSMB->ParameterCount;
4118 pSMB->ParameterOffset = cpu_to_le16(param_offset);
4119 pSMB->DataOffset = cpu_to_le16(offset);
4123 pSMB->InformationLevel = cpu_to_le16(SMB_SET_CIFS_UNIX_INFO);
4126 pSMB->ClientUnixMajor = cpu_to_le16(CIFS_UNIX_MAJOR_VERSION);
4127 pSMB->ClientUnixMinor = cpu_to_le16(CIFS_UNIX_MINOR_VERSION);
4128 pSMB->ClientUnixCap = cpu_to_le64(cap);
4130 pSMB->hdr.smb_buf_length += byte_count;
4131 pSMB->ByteCount = cpu_to_le16(byte_count);
4133 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4134 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4136 cERROR(1, ("Send error in SETFSUnixInfo = %d", rc));
4137 } else { /* decode response */
4138 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4140 rc = -EIO; /* bad smb */
4143 cifs_buf_release(pSMB);
4146 goto SETFSUnixRetry;
4154 CIFSSMBQFSPosixInfo(const int xid, struct cifsTconInfo *tcon,
4155 struct kstatfs *FSData)
4157 /* level 0x201 SMB_QUERY_CIFS_POSIX_INFO */
4158 TRANSACTION2_QFSI_REQ *pSMB = NULL;
4159 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4160 FILE_SYSTEM_POSIX_INFO *response_data;
4162 int bytes_returned = 0;
4163 __u16 params, byte_count;
4165 cFYI(1, ("In QFSPosixInfo"));
4167 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4172 params = 2; /* level */
4173 pSMB->TotalDataCount = 0;
4174 pSMB->DataCount = 0;
4175 pSMB->DataOffset = 0;
4176 pSMB->MaxParameterCount = cpu_to_le16(2);
4177 pSMB->MaxDataCount = cpu_to_le16(100); /* BB find exact max SMB PDU from sess structure BB */
4178 pSMB->MaxSetupCount = 0;
4182 pSMB->Reserved2 = 0;
4183 byte_count = params + 1 /* pad */ ;
4184 pSMB->ParameterCount = cpu_to_le16(params);
4185 pSMB->TotalParameterCount = pSMB->ParameterCount;
4186 pSMB->ParameterOffset = cpu_to_le16(offsetof(struct
4187 smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4188 pSMB->SetupCount = 1;
4189 pSMB->Reserved3 = 0;
4190 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4191 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_POSIX_FS_INFO);
4192 pSMB->hdr.smb_buf_length += byte_count;
4193 pSMB->ByteCount = cpu_to_le16(byte_count);
4195 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4196 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4198 cFYI(1, ("Send error in QFSUnixInfo = %d", rc));
4199 } else { /* decode response */
4200 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4202 if (rc || (pSMBr->ByteCount < 13)) {
4203 rc = -EIO; /* bad smb */
4205 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4207 (FILE_SYSTEM_POSIX_INFO
4208 *) (((char *) &pSMBr->hdr.Protocol) +
4211 le32_to_cpu(response_data->BlockSize);
4213 le64_to_cpu(response_data->TotalBlocks);
4215 le64_to_cpu(response_data->BlocksAvail);
4216 if(response_data->UserBlocksAvail == cpu_to_le64(-1)) {
4217 FSData->f_bavail = FSData->f_bfree;
4220 le64_to_cpu(response_data->UserBlocksAvail);
4222 if(response_data->TotalFileNodes != cpu_to_le64(-1))
4224 le64_to_cpu(response_data->TotalFileNodes);
4225 if(response_data->FreeFileNodes != cpu_to_le64(-1))
4227 le64_to_cpu(response_data->FreeFileNodes);
4230 cifs_buf_release(pSMB);
4239 /* We can not use write of zero bytes trick to
4240 set file size due to need for large file support. Also note that
4241 this SetPathInfo is preferred to SetFileInfo based method in next
4242 routine which is only needed to work around a sharing violation bug
4243 in Samba which this routine can run into */
4246 CIFSSMBSetEOF(const int xid, struct cifsTconInfo *tcon, const char *fileName,
4247 __u64 size, int SetAllocation,
4248 const struct nls_table *nls_codepage, int remap)
4250 struct smb_com_transaction2_spi_req *pSMB = NULL;
4251 struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
4252 struct file_end_of_file_info *parm_data;
4255 int bytes_returned = 0;
4256 __u16 params, byte_count, data_count, param_offset, offset;
4258 cFYI(1, ("In SetEOF"));
4260 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4265 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4267 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
4268 PATH_MAX, nls_codepage, remap);
4269 name_len++; /* trailing null */
4271 } else { /* BB improve the check for buffer overruns BB */
4272 name_len = strnlen(fileName, PATH_MAX);
4273 name_len++; /* trailing null */
4274 strncpy(pSMB->FileName, fileName, name_len);
4276 params = 6 + name_len;
4277 data_count = sizeof (struct file_end_of_file_info);
4278 pSMB->MaxParameterCount = cpu_to_le16(2);
4279 pSMB->MaxDataCount = cpu_to_le16(4100);
4280 pSMB->MaxSetupCount = 0;
4284 pSMB->Reserved2 = 0;
4285 param_offset = offsetof(struct smb_com_transaction2_spi_req,
4286 InformationLevel) - 4;
4287 offset = param_offset + params;
4289 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
4290 pSMB->InformationLevel =
4291 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2);
4293 pSMB->InformationLevel =
4294 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO);
4295 } else /* Set File Size */ {
4296 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
4297 pSMB->InformationLevel =
4298 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO2);
4300 pSMB->InformationLevel =
4301 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO);
4305 (struct file_end_of_file_info *) (((char *) &pSMB->hdr.Protocol) +
4307 pSMB->ParameterOffset = cpu_to_le16(param_offset);
4308 pSMB->DataOffset = cpu_to_le16(offset);
4309 pSMB->SetupCount = 1;
4310 pSMB->Reserved3 = 0;
4311 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
4312 byte_count = 3 /* pad */ + params + data_count;
4313 pSMB->DataCount = cpu_to_le16(data_count);
4314 pSMB->TotalDataCount = pSMB->DataCount;
4315 pSMB->ParameterCount = cpu_to_le16(params);
4316 pSMB->TotalParameterCount = pSMB->ParameterCount;
4317 pSMB->Reserved4 = 0;
4318 pSMB->hdr.smb_buf_length += byte_count;
4319 parm_data->FileSize = cpu_to_le64(size);
4320 pSMB->ByteCount = cpu_to_le16(byte_count);
4321 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4322 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4324 cFYI(1, ("SetPathInfo (file size) returned %d", rc));
4327 cifs_buf_release(pSMB);
4336 CIFSSMBSetFileSize(const int xid, struct cifsTconInfo *tcon, __u64 size,
4337 __u16 fid, __u32 pid_of_opener, int SetAllocation)
4339 struct smb_com_transaction2_sfi_req *pSMB = NULL;
4340 struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
4342 struct file_end_of_file_info *parm_data;
4344 int bytes_returned = 0;
4345 __u16 params, param_offset, offset, byte_count, count;
4347 cFYI(1, ("SetFileSize (via SetFileInfo) %lld",
4349 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
4354 pSMBr = (struct smb_com_transaction2_sfi_rsp *)pSMB;
4356 pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
4357 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));
4360 pSMB->MaxSetupCount = 0;
4364 pSMB->Reserved2 = 0;
4365 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
4366 offset = param_offset + params;
4368 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
4370 count = sizeof(struct file_end_of_file_info);
4371 pSMB->MaxParameterCount = cpu_to_le16(2);
4372 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB PDU from sess */
4373 pSMB->SetupCount = 1;
4374 pSMB->Reserved3 = 0;
4375 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
4376 byte_count = 3 /* pad */ + params + count;
4377 pSMB->DataCount = cpu_to_le16(count);
4378 pSMB->ParameterCount = cpu_to_le16(params);
4379 pSMB->TotalDataCount = pSMB->DataCount;
4380 pSMB->TotalParameterCount = pSMB->ParameterCount;
4381 pSMB->ParameterOffset = cpu_to_le16(param_offset);
4383 (struct file_end_of_file_info *) (((char *) &pSMB->hdr.Protocol) +
4385 pSMB->DataOffset = cpu_to_le16(offset);
4386 parm_data->FileSize = cpu_to_le64(size);
4389 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
4390 pSMB->InformationLevel =
4391 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2);
4393 pSMB->InformationLevel =
4394 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO);
4395 } else /* Set File Size */ {
4396 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
4397 pSMB->InformationLevel =
4398 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO2);
4400 pSMB->InformationLevel =
4401 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO);
4403 pSMB->Reserved4 = 0;
4404 pSMB->hdr.smb_buf_length += byte_count;
4405 pSMB->ByteCount = cpu_to_le16(byte_count);
4406 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4407 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4410 ("Send error in SetFileInfo (SetFileSize) = %d",
4415 cifs_small_buf_release(pSMB);
4417 /* Note: On -EAGAIN error only caller can retry on handle based calls
4418 since file handle passed in no longer valid */
4423 /* Some legacy servers such as NT4 require that the file times be set on
4424 an open handle, rather than by pathname - this is awkward due to
4425 potential access conflicts on the open, but it is unavoidable for these
4426 old servers since the only other choice is to go from 100 nanosecond DCE
4427 time and resort to the original setpathinfo level which takes the ancient
4428 DOS time format with 2 second granularity */
4430 CIFSSMBSetFileTimes(const int xid, struct cifsTconInfo *tcon, const FILE_BASIC_INFO * data,
4433 struct smb_com_transaction2_sfi_req *pSMB = NULL;
4434 struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
4437 int bytes_returned = 0;
4438 __u16 params, param_offset, offset, byte_count, count;
4440 cFYI(1, ("Set Times (via SetFileInfo)"));
4441 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
4446 pSMBr = (struct smb_com_transaction2_sfi_rsp *)pSMB;
4448 /* At this point there is no need to override the current pid
4449 with the pid of the opener, but that could change if we someday
4450 use an existing handle (rather than opening one on the fly) */
4451 /* pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
4452 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));*/
4455 pSMB->MaxSetupCount = 0;
4459 pSMB->Reserved2 = 0;
4460 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
4461 offset = param_offset + params;
4463 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
4465 count = sizeof (FILE_BASIC_INFO);
4466 pSMB->MaxParameterCount = cpu_to_le16(2);
4467 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB PDU from sess */
4468 pSMB->SetupCount = 1;
4469 pSMB->Reserved3 = 0;
4470 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
4471 byte_count = 3 /* pad */ + params + count;
4472 pSMB->DataCount = cpu_to_le16(count);
4473 pSMB->ParameterCount = cpu_to_le16(params);
4474 pSMB->TotalDataCount = pSMB->DataCount;
4475 pSMB->TotalParameterCount = pSMB->ParameterCount;
4476 pSMB->ParameterOffset = cpu_to_le16(param_offset);
4477 pSMB->DataOffset = cpu_to_le16(offset);
4479 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
4480 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO2);
4482 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO);
4483 pSMB->Reserved4 = 0;
4484 pSMB->hdr.smb_buf_length += byte_count;
4485 pSMB->ByteCount = cpu_to_le16(byte_count);
4486 memcpy(data_offset,data,sizeof(FILE_BASIC_INFO));
4487 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4488 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4490 cFYI(1,("Send error in Set Time (SetFileInfo) = %d",rc));
4493 cifs_small_buf_release(pSMB);
4495 /* Note: On -EAGAIN error only caller can retry on handle based calls
4496 since file handle passed in no longer valid */
4503 CIFSSMBSetTimes(const int xid, struct cifsTconInfo *tcon, const char *fileName,
4504 const FILE_BASIC_INFO * data,
4505 const struct nls_table *nls_codepage, int remap)
4507 TRANSACTION2_SPI_REQ *pSMB = NULL;
4508 TRANSACTION2_SPI_RSP *pSMBr = NULL;
4511 int bytes_returned = 0;
4513 __u16 params, param_offset, offset, byte_count, count;
4515 cFYI(1, ("In SetTimes"));
4518 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4523 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4525 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
4526 PATH_MAX, nls_codepage, remap);
4527 name_len++; /* trailing null */
4529 } else { /* BB improve the check for buffer overruns BB */
4530 name_len = strnlen(fileName, PATH_MAX);
4531 name_len++; /* trailing null */
4532 strncpy(pSMB->FileName, fileName, name_len);
4535 params = 6 + name_len;
4536 count = sizeof (FILE_BASIC_INFO);
4537 pSMB->MaxParameterCount = cpu_to_le16(2);
4538 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
4539 pSMB->MaxSetupCount = 0;
4543 pSMB->Reserved2 = 0;
4544 param_offset = offsetof(struct smb_com_transaction2_spi_req,
4545 InformationLevel) - 4;
4546 offset = param_offset + params;
4547 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
4548 pSMB->ParameterOffset = cpu_to_le16(param_offset);
4549 pSMB->DataOffset = cpu_to_le16(offset);
4550 pSMB->SetupCount = 1;
4551 pSMB->Reserved3 = 0;
4552 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
4553 byte_count = 3 /* pad */ + params + count;
4555 pSMB->DataCount = cpu_to_le16(count);
4556 pSMB->ParameterCount = cpu_to_le16(params);
4557 pSMB->TotalDataCount = pSMB->DataCount;
4558 pSMB->TotalParameterCount = pSMB->ParameterCount;
4559 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
4560 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO2);
4562 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO);
4563 pSMB->Reserved4 = 0;
4564 pSMB->hdr.smb_buf_length += byte_count;
4565 memcpy(data_offset, data, sizeof (FILE_BASIC_INFO));
4566 pSMB->ByteCount = cpu_to_le16(byte_count);
4567 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4568 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4570 cFYI(1, ("SetPathInfo (times) returned %d", rc));
4573 cifs_buf_release(pSMB);
4581 /* Can not be used to set time stamps yet (due to old DOS time format) */
4582 /* Can be used to set attributes */
4583 #if 0 /* Possibly not needed - since it turns out that strangely NT4 has a bug
4584 handling it anyway and NT4 was what we thought it would be needed for
4585 Do not delete it until we prove whether needed for Win9x though */
4587 CIFSSMBSetAttrLegacy(int xid, struct cifsTconInfo *tcon, char *fileName,
4588 __u16 dos_attrs, const struct nls_table *nls_codepage)
4590 SETATTR_REQ *pSMB = NULL;
4591 SETATTR_RSP *pSMBr = NULL;
4596 cFYI(1, ("In SetAttrLegacy"));
4599 rc = smb_init(SMB_COM_SETATTR, 8, tcon, (void **) &pSMB,
4604 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4606 ConvertToUCS((__le16 *) pSMB->fileName, fileName,
4607 PATH_MAX, nls_codepage);
4608 name_len++; /* trailing null */
4610 } else { /* BB improve the check for buffer overruns BB */
4611 name_len = strnlen(fileName, PATH_MAX);
4612 name_len++; /* trailing null */
4613 strncpy(pSMB->fileName, fileName, name_len);
4615 pSMB->attr = cpu_to_le16(dos_attrs);
4616 pSMB->BufferFormat = 0x04;
4617 pSMB->hdr.smb_buf_length += name_len + 1;
4618 pSMB->ByteCount = cpu_to_le16(name_len + 1);
4619 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4620 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4622 cFYI(1, ("Error in LegacySetAttr = %d", rc));
4625 cifs_buf_release(pSMB);
4628 goto SetAttrLgcyRetry;
4632 #endif /* temporarily unneeded SetAttr legacy function */
4635 CIFSSMBUnixSetPerms(const int xid, struct cifsTconInfo *tcon,
4636 char *fileName, __u64 mode, __u64 uid, __u64 gid,
4637 dev_t device, const struct nls_table *nls_codepage,
4640 TRANSACTION2_SPI_REQ *pSMB = NULL;
4641 TRANSACTION2_SPI_RSP *pSMBr = NULL;
4644 int bytes_returned = 0;
4645 FILE_UNIX_BASIC_INFO *data_offset;
4646 __u16 params, param_offset, offset, count, byte_count;
4648 cFYI(1, ("In SetUID/GID/Mode"));
4650 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4655 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4657 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
4658 PATH_MAX, nls_codepage, remap);
4659 name_len++; /* trailing null */
4661 } else { /* BB improve the check for buffer overruns BB */
4662 name_len = strnlen(fileName, PATH_MAX);
4663 name_len++; /* trailing null */
4664 strncpy(pSMB->FileName, fileName, name_len);
4667 params = 6 + name_len;
4668 count = sizeof (FILE_UNIX_BASIC_INFO);
4669 pSMB->MaxParameterCount = cpu_to_le16(2);
4670 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
4671 pSMB->MaxSetupCount = 0;
4675 pSMB->Reserved2 = 0;
4676 param_offset = offsetof(struct smb_com_transaction2_spi_req,
4677 InformationLevel) - 4;
4678 offset = param_offset + params;
4680 (FILE_UNIX_BASIC_INFO *) ((char *) &pSMB->hdr.Protocol +
4682 memset(data_offset, 0, count);
4683 pSMB->DataOffset = cpu_to_le16(offset);
4684 pSMB->ParameterOffset = cpu_to_le16(param_offset);
4685 pSMB->SetupCount = 1;
4686 pSMB->Reserved3 = 0;
4687 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
4688 byte_count = 3 /* pad */ + params + count;
4689 pSMB->ParameterCount = cpu_to_le16(params);
4690 pSMB->DataCount = cpu_to_le16(count);
4691 pSMB->TotalParameterCount = pSMB->ParameterCount;
4692 pSMB->TotalDataCount = pSMB->DataCount;
4693 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_BASIC);
4694 pSMB->Reserved4 = 0;
4695 pSMB->hdr.smb_buf_length += byte_count;
4696 data_offset->Uid = cpu_to_le64(uid);
4697 data_offset->Gid = cpu_to_le64(gid);
4698 /* better to leave device as zero when it is */
4699 data_offset->DevMajor = cpu_to_le64(MAJOR(device));
4700 data_offset->DevMinor = cpu_to_le64(MINOR(device));
4701 data_offset->Permissions = cpu_to_le64(mode);
4704 data_offset->Type = cpu_to_le32(UNIX_FILE);
4705 else if(S_ISDIR(mode))
4706 data_offset->Type = cpu_to_le32(UNIX_DIR);
4707 else if(S_ISLNK(mode))
4708 data_offset->Type = cpu_to_le32(UNIX_SYMLINK);
4709 else if(S_ISCHR(mode))
4710 data_offset->Type = cpu_to_le32(UNIX_CHARDEV);
4711 else if(S_ISBLK(mode))
4712 data_offset->Type = cpu_to_le32(UNIX_BLOCKDEV);
4713 else if(S_ISFIFO(mode))
4714 data_offset->Type = cpu_to_le32(UNIX_FIFO);
4715 else if(S_ISSOCK(mode))
4716 data_offset->Type = cpu_to_le32(UNIX_SOCKET);
4719 pSMB->ByteCount = cpu_to_le16(byte_count);
4720 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4721 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4723 cFYI(1, ("SetPathInfo (perms) returned %d", rc));
4727 cifs_buf_release(pSMB);
4733 int CIFSSMBNotify(const int xid, struct cifsTconInfo *tcon,
4734 const int notify_subdirs, const __u16 netfid,
4735 __u32 filter, struct file * pfile, int multishot,
4736 const struct nls_table *nls_codepage)
4739 struct smb_com_transaction_change_notify_req * pSMB = NULL;
4740 struct smb_com_ntransaction_change_notify_rsp * pSMBr = NULL;
4741 struct dir_notify_req *dnotify_req;
4744 cFYI(1, ("In CIFSSMBNotify for file handle %d",(int)netfid));
4745 rc = smb_init(SMB_COM_NT_TRANSACT, 23, tcon, (void **) &pSMB,
4750 pSMB->TotalParameterCount = 0 ;
4751 pSMB->TotalDataCount = 0;
4752 pSMB->MaxParameterCount = cpu_to_le32(2);
4753 /* BB find exact data count max from sess structure BB */
4754 pSMB->MaxDataCount = 0; /* same in little endian or be */
4755 /* BB VERIFY verify which is correct for above BB */
4756 pSMB->MaxDataCount = cpu_to_le32((tcon->ses->server->maxBuf -
4757 MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
4759 pSMB->MaxSetupCount = 4;
4761 pSMB->ParameterOffset = 0;
4762 pSMB->DataCount = 0;
4763 pSMB->DataOffset = 0;
4764 pSMB->SetupCount = 4; /* single byte does not need le conversion */
4765 pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_NOTIFY_CHANGE);
4766 pSMB->ParameterCount = pSMB->TotalParameterCount;
4768 pSMB->WatchTree = 1; /* one byte - no le conversion needed */
4769 pSMB->Reserved2 = 0;
4770 pSMB->CompletionFilter = cpu_to_le32(filter);
4771 pSMB->Fid = netfid; /* file handle always le */
4772 pSMB->ByteCount = 0;
4774 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4775 (struct smb_hdr *) pSMBr, &bytes_returned, -1);
4777 cFYI(1, ("Error in Notify = %d", rc));
4779 /* Add file to outstanding requests */
4780 /* BB change to kmem cache alloc */
4781 dnotify_req = (struct dir_notify_req *) kmalloc(
4782 sizeof(struct dir_notify_req),
4785 dnotify_req->Pid = pSMB->hdr.Pid;
4786 dnotify_req->PidHigh = pSMB->hdr.PidHigh;
4787 dnotify_req->Mid = pSMB->hdr.Mid;
4788 dnotify_req->Tid = pSMB->hdr.Tid;
4789 dnotify_req->Uid = pSMB->hdr.Uid;
4790 dnotify_req->netfid = netfid;
4791 dnotify_req->pfile = pfile;
4792 dnotify_req->filter = filter;
4793 dnotify_req->multishot = multishot;
4794 spin_lock(&GlobalMid_Lock);
4795 list_add_tail(&dnotify_req->lhead,
4796 &GlobalDnotifyReqList);
4797 spin_unlock(&GlobalMid_Lock);
4801 cifs_buf_release(pSMB);
4804 #ifdef CONFIG_CIFS_XATTR
4806 CIFSSMBQAllEAs(const int xid, struct cifsTconInfo *tcon,
4807 const unsigned char *searchName,
4808 char * EAData, size_t buf_size,
4809 const struct nls_table *nls_codepage, int remap)
4811 /* BB assumes one setup word */
4812 TRANSACTION2_QPI_REQ *pSMB = NULL;
4813 TRANSACTION2_QPI_RSP *pSMBr = NULL;
4817 struct fea * temp_fea;
4819 __u16 params, byte_count;
4821 cFYI(1, ("In Query All EAs path %s", searchName));
4823 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4828 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4830 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
4831 PATH_MAX, nls_codepage, remap);
4832 name_len++; /* trailing null */
4834 } else { /* BB improve the check for buffer overruns BB */
4835 name_len = strnlen(searchName, PATH_MAX);
4836 name_len++; /* trailing null */
4837 strncpy(pSMB->FileName, searchName, name_len);
4840 params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */ ;
4841 pSMB->TotalDataCount = 0;
4842 pSMB->MaxParameterCount = cpu_to_le16(2);
4843 pSMB->MaxDataCount = cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
4844 pSMB->MaxSetupCount = 0;
4848 pSMB->Reserved2 = 0;
4849 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4850 struct smb_com_transaction2_qpi_req ,InformationLevel) - 4);
4851 pSMB->DataCount = 0;
4852 pSMB->DataOffset = 0;
4853 pSMB->SetupCount = 1;
4854 pSMB->Reserved3 = 0;
4855 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
4856 byte_count = params + 1 /* pad */ ;
4857 pSMB->TotalParameterCount = cpu_to_le16(params);
4858 pSMB->ParameterCount = pSMB->TotalParameterCount;
4859 pSMB->InformationLevel = cpu_to_le16(SMB_INFO_QUERY_ALL_EAS);
4860 pSMB->Reserved4 = 0;
4861 pSMB->hdr.smb_buf_length += byte_count;
4862 pSMB->ByteCount = cpu_to_le16(byte_count);
4864 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4865 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4867 cFYI(1, ("Send error in QueryAllEAs = %d", rc));
4868 } else { /* decode response */
4869 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4871 /* BB also check enough total bytes returned */
4872 /* BB we need to improve the validity checking
4873 of these trans2 responses */
4874 if (rc || (pSMBr->ByteCount < 4))
4875 rc = -EIO; /* bad smb */
4876 /* else if (pFindData){
4877 memcpy((char *) pFindData,
4878 (char *) &pSMBr->hdr.Protocol +
4881 /* check that length of list is not more than bcc */
4882 /* check that each entry does not go beyond length
4884 /* check that each element of each entry does not
4885 go beyond end of list */
4886 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4887 struct fealist * ea_response_data;
4889 /* validate_trans2_offsets() */
4890 /* BB to check if(start of smb + data_offset > &bcc+ bcc)*/
4891 ea_response_data = (struct fealist *)
4892 (((char *) &pSMBr->hdr.Protocol) +
4894 name_len = le32_to_cpu(ea_response_data->list_len);
4895 cFYI(1,("ea length %d", name_len));
4897 /* returned EA size zeroed at top of function */
4898 cFYI(1,("empty EA list returned from server"));
4900 /* account for ea list len */
4902 temp_fea = ea_response_data->list;
4903 temp_ptr = (char *)temp_fea;
4904 while(name_len > 0) {
4908 rc += temp_fea->name_len;
4909 /* account for prefix user. and trailing null */
4911 if(rc<(int)buf_size) {
4912 memcpy(EAData,"user.",5);
4914 memcpy(EAData,temp_ptr,temp_fea->name_len);
4915 EAData+=temp_fea->name_len;
4916 /* null terminate name */
4918 EAData = EAData + 1;
4919 } else if(buf_size == 0) {
4920 /* skip copy - calc size only */
4922 /* stop before overrun buffer */
4926 name_len -= temp_fea->name_len;
4927 temp_ptr += temp_fea->name_len;
4928 /* account for trailing null */
4931 value_len = le16_to_cpu(temp_fea->value_len);
4932 name_len -= value_len;
4933 temp_ptr += value_len;
4934 /* BB check that temp_ptr is still within smb BB*/
4935 /* no trailing null to account for in value len */
4936 /* go on to next EA */
4937 temp_fea = (struct fea *)temp_ptr;
4943 cifs_buf_release(pSMB);
4950 ssize_t CIFSSMBQueryEA(const int xid,struct cifsTconInfo * tcon,
4951 const unsigned char * searchName,const unsigned char * ea_name,
4952 unsigned char * ea_value, size_t buf_size,
4953 const struct nls_table *nls_codepage, int remap)
4955 TRANSACTION2_QPI_REQ *pSMB = NULL;
4956 TRANSACTION2_QPI_RSP *pSMBr = NULL;
4960 struct fea * temp_fea;
4962 __u16 params, byte_count;
4964 cFYI(1, ("In Query EA path %s", searchName));
4966 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4971 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4973 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
4974 PATH_MAX, nls_codepage, remap);
4975 name_len++; /* trailing null */
4977 } else { /* BB improve the check for buffer overruns BB */
4978 name_len = strnlen(searchName, PATH_MAX);
4979 name_len++; /* trailing null */
4980 strncpy(pSMB->FileName, searchName, name_len);
4983 params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */ ;
4984 pSMB->TotalDataCount = 0;
4985 pSMB->MaxParameterCount = cpu_to_le16(2);
4986 pSMB->MaxDataCount = cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
4987 pSMB->MaxSetupCount = 0;
4991 pSMB->Reserved2 = 0;
4992 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4993 struct smb_com_transaction2_qpi_req ,InformationLevel) - 4);
4994 pSMB->DataCount = 0;
4995 pSMB->DataOffset = 0;
4996 pSMB->SetupCount = 1;
4997 pSMB->Reserved3 = 0;
4998 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
4999 byte_count = params + 1 /* pad */ ;
5000 pSMB->TotalParameterCount = cpu_to_le16(params);
5001 pSMB->ParameterCount = pSMB->TotalParameterCount;
5002 pSMB->InformationLevel = cpu_to_le16(SMB_INFO_QUERY_ALL_EAS);
5003 pSMB->Reserved4 = 0;
5004 pSMB->hdr.smb_buf_length += byte_count;
5005 pSMB->ByteCount = cpu_to_le16(byte_count);
5007 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5008 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5010 cFYI(1, ("Send error in Query EA = %d", rc));
5011 } else { /* decode response */
5012 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
5014 /* BB also check enough total bytes returned */
5015 /* BB we need to improve the validity checking
5016 of these trans2 responses */
5017 if (rc || (pSMBr->ByteCount < 4))
5018 rc = -EIO; /* bad smb */
5019 /* else if (pFindData){
5020 memcpy((char *) pFindData,
5021 (char *) &pSMBr->hdr.Protocol +
5024 /* check that length of list is not more than bcc */
5025 /* check that each entry does not go beyond length
5027 /* check that each element of each entry does not
5028 go beyond end of list */
5029 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
5030 struct fealist * ea_response_data;
5032 /* validate_trans2_offsets() */
5033 /* BB to check if(start of smb + data_offset > &bcc+ bcc)*/
5034 ea_response_data = (struct fealist *)
5035 (((char *) &pSMBr->hdr.Protocol) +
5037 name_len = le32_to_cpu(ea_response_data->list_len);
5038 cFYI(1,("ea length %d", name_len));
5040 /* returned EA size zeroed at top of function */
5041 cFYI(1,("empty EA list returned from server"));
5043 /* account for ea list len */
5045 temp_fea = ea_response_data->list;
5046 temp_ptr = (char *)temp_fea;
5047 /* loop through checking if we have a matching
5048 name and then return the associated value */
5049 while(name_len > 0) {
5053 value_len = le16_to_cpu(temp_fea->value_len);
5054 /* BB validate that value_len falls within SMB,
5055 even though maximum for name_len is 255 */
5056 if(memcmp(temp_fea->name,ea_name,
5057 temp_fea->name_len) == 0) {
5060 /* account for prefix user. and trailing null */
5061 if(rc<=(int)buf_size) {
5063 temp_fea->name+temp_fea->name_len+1,
5065 /* ea values, unlike ea names,
5066 are not null terminated */
5067 } else if(buf_size == 0) {
5068 /* skip copy - calc size only */
5070 /* stop before overrun buffer */
5075 name_len -= temp_fea->name_len;
5076 temp_ptr += temp_fea->name_len;
5077 /* account for trailing null */
5080 name_len -= value_len;
5081 temp_ptr += value_len;
5082 /* no trailing null to account for in value len */
5083 /* go on to next EA */
5084 temp_fea = (struct fea *)temp_ptr;
5090 cifs_buf_release(pSMB);
5098 CIFSSMBSetEA(const int xid, struct cifsTconInfo *tcon, const char *fileName,
5099 const char * ea_name, const void * ea_value,
5100 const __u16 ea_value_len, const struct nls_table *nls_codepage,
5103 struct smb_com_transaction2_spi_req *pSMB = NULL;
5104 struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
5105 struct fealist *parm_data;
5108 int bytes_returned = 0;
5109 __u16 params, param_offset, byte_count, offset, count;
5111 cFYI(1, ("In SetEA"));
5113 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5118 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5120 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
5121 PATH_MAX, nls_codepage, remap);
5122 name_len++; /* trailing null */
5124 } else { /* BB improve the check for buffer overruns BB */
5125 name_len = strnlen(fileName, PATH_MAX);
5126 name_len++; /* trailing null */
5127 strncpy(pSMB->FileName, fileName, name_len);
5130 params = 6 + name_len;
5132 /* done calculating parms using name_len of file name,
5133 now use name_len to calculate length of ea name
5134 we are going to create in the inode xattrs */
5138 name_len = strnlen(ea_name,255);
5140 count = sizeof(*parm_data) + ea_value_len + name_len + 1;
5141 pSMB->MaxParameterCount = cpu_to_le16(2);
5142 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB size from sess */
5143 pSMB->MaxSetupCount = 0;
5147 pSMB->Reserved2 = 0;
5148 param_offset = offsetof(struct smb_com_transaction2_spi_req,
5149 InformationLevel) - 4;
5150 offset = param_offset + params;
5151 pSMB->InformationLevel =
5152 cpu_to_le16(SMB_SET_FILE_EA);
5155 (struct fealist *) (((char *) &pSMB->hdr.Protocol) +
5157 pSMB->ParameterOffset = cpu_to_le16(param_offset);
5158 pSMB->DataOffset = cpu_to_le16(offset);
5159 pSMB->SetupCount = 1;
5160 pSMB->Reserved3 = 0;
5161 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
5162 byte_count = 3 /* pad */ + params + count;
5163 pSMB->DataCount = cpu_to_le16(count);
5164 parm_data->list_len = cpu_to_le32(count);
5165 parm_data->list[0].EA_flags = 0;
5166 /* we checked above that name len is less than 255 */
5167 parm_data->list[0].name_len = (__u8)name_len;
5168 /* EA names are always ASCII */
5170 strncpy(parm_data->list[0].name,ea_name,name_len);
5171 parm_data->list[0].name[name_len] = 0;
5172 parm_data->list[0].value_len = cpu_to_le16(ea_value_len);
5173 /* caller ensures that ea_value_len is less than 64K but
5174 we need to ensure that it fits within the smb */
5176 /*BB add length check that it would fit in negotiated SMB buffer size BB */
5177 /* if(ea_value_len > buffer_size - 512 (enough for header)) */
5179 memcpy(parm_data->list[0].name+name_len+1,ea_value,ea_value_len);
5181 pSMB->TotalDataCount = pSMB->DataCount;
5182 pSMB->ParameterCount = cpu_to_le16(params);
5183 pSMB->TotalParameterCount = pSMB->ParameterCount;
5184 pSMB->Reserved4 = 0;
5185 pSMB->hdr.smb_buf_length += byte_count;
5186 pSMB->ByteCount = cpu_to_le16(byte_count);
5187 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5188 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5190 cFYI(1, ("SetPathInfo (EA) returned %d", rc));
5193 cifs_buf_release(pSMB);