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;
573 if(sign_CIFS_PDUs == FALSE) {
574 if(server->secMode & SECMODE_SIGN_REQUIRED)
575 cERROR(1,("Server requires "
576 "/proc/fs/cifs/PacketSigningEnabled to be on"));
578 ~(SECMODE_SIGN_ENABLED | SECMODE_SIGN_REQUIRED);
579 } else if(sign_CIFS_PDUs == 1) {
580 if((server->secMode & SECMODE_SIGN_REQUIRED) == 0)
582 ~(SECMODE_SIGN_ENABLED | SECMODE_SIGN_REQUIRED);
583 } else if(sign_CIFS_PDUs == 2) {
584 if((server->secMode &
585 (SECMODE_SIGN_ENABLED | SECMODE_SIGN_REQUIRED)) == 0) {
586 cERROR(1,("signing required but server lacks support"));
590 cifs_buf_release(pSMB);
592 cFYI(1,("negprot rc %d",rc));
597 CIFSSMBTDis(const int xid, struct cifsTconInfo *tcon)
599 struct smb_hdr *smb_buffer;
600 struct smb_hdr *smb_buffer_response; /* BB removeme BB */
604 cFYI(1, ("In tree disconnect"));
606 * If last user of the connection and
607 * connection alive - disconnect it
608 * If this is the last connection on the server session disconnect it
609 * (and inside session disconnect we should check if tcp socket needs
610 * to be freed and kernel thread woken up).
613 down(&tcon->tconSem);
617 atomic_dec(&tcon->useCount);
618 if (atomic_read(&tcon->useCount) > 0) {
623 /* No need to return error on this operation if tid invalidated and
624 closed on server already e.g. due to tcp session crashing */
625 if(tcon->tidStatus == CifsNeedReconnect) {
630 if((tcon->ses == NULL) || (tcon->ses->server == NULL)) {
634 rc = small_smb_init(SMB_COM_TREE_DISCONNECT, 0, tcon,
635 (void **)&smb_buffer);
640 smb_buffer_response = smb_buffer; /* BB removeme BB */
642 rc = SendReceive(xid, tcon->ses, smb_buffer, smb_buffer_response,
645 cFYI(1, ("Tree disconnect failed %d", rc));
648 cifs_small_buf_release(smb_buffer);
651 /* No need to return error on this operation if tid invalidated and
652 closed on server already e.g. due to tcp session crashing */
660 CIFSSMBLogoff(const int xid, struct cifsSesInfo *ses)
662 struct smb_hdr *smb_buffer_response;
663 LOGOFF_ANDX_REQ *pSMB;
667 cFYI(1, ("In SMBLogoff for session disconnect"));
673 atomic_dec(&ses->inUse);
674 if (atomic_read(&ses->inUse) > 0) {
678 rc = small_smb_init(SMB_COM_LOGOFF_ANDX, 2, NULL, (void **)&pSMB);
684 smb_buffer_response = (struct smb_hdr *)pSMB; /* BB removeme BB */
687 pSMB->hdr.Mid = GetNextMid(ses->server);
689 if(ses->server->secMode &
690 (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
691 pSMB->hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
694 pSMB->hdr.Uid = ses->Suid;
696 pSMB->AndXCommand = 0xFF;
697 rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB,
698 smb_buffer_response, &length, 0);
700 atomic_dec(&ses->server->socketUseCount);
701 if (atomic_read(&ses->server->socketUseCount) == 0) {
702 spin_lock(&GlobalMid_Lock);
703 ses->server->tcpStatus = CifsExiting;
704 spin_unlock(&GlobalMid_Lock);
709 cifs_small_buf_release(pSMB);
711 /* if session dead then we do not need to do ulogoff,
712 since server closed smb session, no sense reporting
720 CIFSSMBDelFile(const int xid, struct cifsTconInfo *tcon, const char *fileName,
721 const struct nls_table *nls_codepage, int remap)
723 DELETE_FILE_REQ *pSMB = NULL;
724 DELETE_FILE_RSP *pSMBr = NULL;
730 rc = smb_init(SMB_COM_DELETE, 1, tcon, (void **) &pSMB,
735 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
737 cifsConvertToUCS((__le16 *) pSMB->fileName, fileName,
738 PATH_MAX, nls_codepage, remap);
739 name_len++; /* trailing null */
741 } else { /* BB improve check for buffer overruns BB */
742 name_len = strnlen(fileName, PATH_MAX);
743 name_len++; /* trailing null */
744 strncpy(pSMB->fileName, fileName, name_len);
746 pSMB->SearchAttributes =
747 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM);
748 pSMB->BufferFormat = 0x04;
749 pSMB->hdr.smb_buf_length += name_len + 1;
750 pSMB->ByteCount = cpu_to_le16(name_len + 1);
751 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
752 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
753 cifs_stats_inc(&tcon->num_deletes);
755 cFYI(1, ("Error in RMFile = %d", rc));
758 cifs_buf_release(pSMB);
766 CIFSSMBRmDir(const int xid, struct cifsTconInfo *tcon, const char *dirName,
767 const struct nls_table *nls_codepage, int remap)
769 DELETE_DIRECTORY_REQ *pSMB = NULL;
770 DELETE_DIRECTORY_RSP *pSMBr = NULL;
775 cFYI(1, ("In CIFSSMBRmDir"));
777 rc = smb_init(SMB_COM_DELETE_DIRECTORY, 0, tcon, (void **) &pSMB,
782 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
783 name_len = cifsConvertToUCS((__le16 *) pSMB->DirName, dirName,
784 PATH_MAX, nls_codepage, remap);
785 name_len++; /* trailing null */
787 } else { /* BB improve check for buffer overruns BB */
788 name_len = strnlen(dirName, PATH_MAX);
789 name_len++; /* trailing null */
790 strncpy(pSMB->DirName, dirName, name_len);
793 pSMB->BufferFormat = 0x04;
794 pSMB->hdr.smb_buf_length += name_len + 1;
795 pSMB->ByteCount = cpu_to_le16(name_len + 1);
796 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
797 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
798 cifs_stats_inc(&tcon->num_rmdirs);
800 cFYI(1, ("Error in RMDir = %d", rc));
803 cifs_buf_release(pSMB);
810 CIFSSMBMkDir(const int xid, struct cifsTconInfo *tcon,
811 const char *name, const struct nls_table *nls_codepage, int remap)
814 CREATE_DIRECTORY_REQ *pSMB = NULL;
815 CREATE_DIRECTORY_RSP *pSMBr = NULL;
819 cFYI(1, ("In CIFSSMBMkDir"));
821 rc = smb_init(SMB_COM_CREATE_DIRECTORY, 0, tcon, (void **) &pSMB,
826 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
827 name_len = cifsConvertToUCS((__le16 *) pSMB->DirName, name,
828 PATH_MAX, nls_codepage, remap);
829 name_len++; /* trailing null */
831 } else { /* BB improve check for buffer overruns BB */
832 name_len = strnlen(name, PATH_MAX);
833 name_len++; /* trailing null */
834 strncpy(pSMB->DirName, name, name_len);
837 pSMB->BufferFormat = 0x04;
838 pSMB->hdr.smb_buf_length += name_len + 1;
839 pSMB->ByteCount = cpu_to_le16(name_len + 1);
840 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
841 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
842 cifs_stats_inc(&tcon->num_mkdirs);
844 cFYI(1, ("Error in Mkdir = %d", rc));
847 cifs_buf_release(pSMB);
853 static __u16 convert_disposition(int disposition)
857 switch (disposition) {
859 ofun = SMBOPEN_OCREATE | SMBOPEN_OTRUNC;
862 ofun = SMBOPEN_OAPPEND;
865 ofun = SMBOPEN_OCREATE;
868 ofun = SMBOPEN_OCREATE | SMBOPEN_OAPPEND;
871 ofun = SMBOPEN_OTRUNC;
873 case FILE_OVERWRITE_IF:
874 ofun = SMBOPEN_OCREATE | SMBOPEN_OTRUNC;
877 cFYI(1,("unknown disposition %d",disposition));
878 ofun = SMBOPEN_OAPPEND; /* regular open */
884 SMBLegacyOpen(const int xid, struct cifsTconInfo *tcon,
885 const char *fileName, const int openDisposition,
886 const int access_flags, const int create_options, __u16 * netfid,
887 int *pOplock, FILE_ALL_INFO * pfile_info,
888 const struct nls_table *nls_codepage, int remap)
891 OPENX_REQ *pSMB = NULL;
892 OPENX_RSP *pSMBr = NULL;
898 rc = smb_init(SMB_COM_OPEN_ANDX, 15, tcon, (void **) &pSMB,
903 pSMB->AndXCommand = 0xFF; /* none */
905 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
906 count = 1; /* account for one byte pad to word boundary */
908 cifsConvertToUCS((__le16 *) (pSMB->fileName + 1),
909 fileName, PATH_MAX, nls_codepage, remap);
910 name_len++; /* trailing null */
912 } else { /* BB improve check for buffer overruns BB */
913 count = 0; /* no pad */
914 name_len = strnlen(fileName, PATH_MAX);
915 name_len++; /* trailing null */
916 strncpy(pSMB->fileName, fileName, name_len);
918 if (*pOplock & REQ_OPLOCK)
919 pSMB->OpenFlags = cpu_to_le16(REQ_OPLOCK);
920 else if (*pOplock & REQ_BATCHOPLOCK) {
921 pSMB->OpenFlags = cpu_to_le16(REQ_BATCHOPLOCK);
923 pSMB->OpenFlags |= cpu_to_le16(REQ_MORE_INFO);
924 /* BB fixme add conversion for access_flags to bits 0 - 2 of mode */
930 pSMB->Mode = cpu_to_le16(2);
931 pSMB->Mode |= cpu_to_le16(0x40); /* deny none */
932 /* set file as system file if special file such
933 as fifo and server expecting SFU style and
934 no Unix extensions */
936 if(create_options & CREATE_OPTION_SPECIAL)
937 pSMB->FileAttributes = cpu_to_le16(ATTR_SYSTEM);
939 pSMB->FileAttributes = cpu_to_le16(0/*ATTR_NORMAL*/); /* BB FIXME */
941 /* if ((omode & S_IWUGO) == 0)
942 pSMB->FileAttributes |= cpu_to_le32(ATTR_READONLY);*/
943 /* Above line causes problems due to vfs splitting create into two
944 pieces - need to set mode after file created not while it is
948 /* pSMB->CreateOptions = cpu_to_le32(create_options & CREATE_OPTIONS_MASK); */
949 /* BB FIXME END BB */
951 pSMB->Sattr = cpu_to_le16(ATTR_HIDDEN | ATTR_SYSTEM | ATTR_DIRECTORY);
952 pSMB->OpenFunction = cpu_to_le16(convert_disposition(openDisposition));
954 pSMB->hdr.smb_buf_length += count;
956 pSMB->ByteCount = cpu_to_le16(count);
957 /* long_op set to 1 to allow for oplock break timeouts */
958 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
959 (struct smb_hdr *) pSMBr, &bytes_returned, 1);
960 cifs_stats_inc(&tcon->num_opens);
962 cFYI(1, ("Error in Open = %d", rc));
964 /* BB verify if wct == 15 */
966 /* *pOplock = pSMBr->OplockLevel; */ /* BB take from action field BB */
968 *netfid = pSMBr->Fid; /* cifs fid stays in le */
969 /* Let caller know file was created so we can set the mode. */
970 /* Do we care about the CreateAction in any other cases? */
972 /* if(cpu_to_le32(FILE_CREATE) == pSMBr->CreateAction)
973 *pOplock |= CIFS_CREATE_ACTION; */
977 pfile_info->CreationTime = 0; /* BB convert CreateTime*/
978 pfile_info->LastAccessTime = 0; /* BB fixme */
979 pfile_info->LastWriteTime = 0; /* BB fixme */
980 pfile_info->ChangeTime = 0; /* BB fixme */
981 pfile_info->Attributes =
982 cpu_to_le32(le16_to_cpu(pSMBr->FileAttributes));
983 /* the file_info buf is endian converted by caller */
984 pfile_info->AllocationSize =
985 cpu_to_le64(le32_to_cpu(pSMBr->EndOfFile));
986 pfile_info->EndOfFile = pfile_info->AllocationSize;
987 pfile_info->NumberOfLinks = cpu_to_le32(1);
991 cifs_buf_release(pSMB);
998 CIFSSMBOpen(const int xid, struct cifsTconInfo *tcon,
999 const char *fileName, const int openDisposition,
1000 const int access_flags, const int create_options, __u16 * netfid,
1001 int *pOplock, FILE_ALL_INFO * pfile_info,
1002 const struct nls_table *nls_codepage, int remap)
1005 OPEN_REQ *pSMB = NULL;
1006 OPEN_RSP *pSMBr = NULL;
1012 rc = smb_init(SMB_COM_NT_CREATE_ANDX, 24, tcon, (void **) &pSMB,
1017 pSMB->AndXCommand = 0xFF; /* none */
1019 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1020 count = 1; /* account for one byte pad to word boundary */
1022 cifsConvertToUCS((__le16 *) (pSMB->fileName + 1),
1023 fileName, PATH_MAX, nls_codepage, remap);
1024 name_len++; /* trailing null */
1026 pSMB->NameLength = cpu_to_le16(name_len);
1027 } else { /* BB improve check for buffer overruns BB */
1028 count = 0; /* no pad */
1029 name_len = strnlen(fileName, PATH_MAX);
1030 name_len++; /* trailing null */
1031 pSMB->NameLength = cpu_to_le16(name_len);
1032 strncpy(pSMB->fileName, fileName, name_len);
1034 if (*pOplock & REQ_OPLOCK)
1035 pSMB->OpenFlags = cpu_to_le32(REQ_OPLOCK);
1036 else if (*pOplock & REQ_BATCHOPLOCK) {
1037 pSMB->OpenFlags = cpu_to_le32(REQ_BATCHOPLOCK);
1039 pSMB->DesiredAccess = cpu_to_le32(access_flags);
1040 pSMB->AllocationSize = 0;
1041 /* set file as system file if special file such
1042 as fifo and server expecting SFU style and
1043 no Unix extensions */
1044 if(create_options & CREATE_OPTION_SPECIAL)
1045 pSMB->FileAttributes = cpu_to_le32(ATTR_SYSTEM);
1047 pSMB->FileAttributes = cpu_to_le32(ATTR_NORMAL);
1048 /* XP does not handle ATTR_POSIX_SEMANTICS */
1049 /* but it helps speed up case sensitive checks for other
1050 servers such as Samba */
1051 if (tcon->ses->capabilities & CAP_UNIX)
1052 pSMB->FileAttributes |= cpu_to_le32(ATTR_POSIX_SEMANTICS);
1054 /* if ((omode & S_IWUGO) == 0)
1055 pSMB->FileAttributes |= cpu_to_le32(ATTR_READONLY);*/
1056 /* Above line causes problems due to vfs splitting create into two
1057 pieces - need to set mode after file created not while it is
1059 pSMB->ShareAccess = cpu_to_le32(FILE_SHARE_ALL);
1060 pSMB->CreateDisposition = cpu_to_le32(openDisposition);
1061 pSMB->CreateOptions = cpu_to_le32(create_options & CREATE_OPTIONS_MASK);
1062 /* BB Expirement with various impersonation levels and verify */
1063 pSMB->ImpersonationLevel = cpu_to_le32(SECURITY_IMPERSONATION);
1064 pSMB->SecurityFlags =
1065 SECURITY_CONTEXT_TRACKING | SECURITY_EFFECTIVE_ONLY;
1068 pSMB->hdr.smb_buf_length += count;
1070 pSMB->ByteCount = cpu_to_le16(count);
1071 /* long_op set to 1 to allow for oplock break timeouts */
1072 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1073 (struct smb_hdr *) pSMBr, &bytes_returned, 1);
1074 cifs_stats_inc(&tcon->num_opens);
1076 cFYI(1, ("Error in Open = %d", rc));
1078 *pOplock = pSMBr->OplockLevel; /* 1 byte no need to le_to_cpu */
1079 *netfid = pSMBr->Fid; /* cifs fid stays in le */
1080 /* Let caller know file was created so we can set the mode. */
1081 /* Do we care about the CreateAction in any other cases? */
1082 if(cpu_to_le32(FILE_CREATE) == pSMBr->CreateAction)
1083 *pOplock |= CIFS_CREATE_ACTION;
1085 memcpy((char *)pfile_info,(char *)&pSMBr->CreationTime,
1086 36 /* CreationTime to Attributes */);
1087 /* the file_info buf is endian converted by caller */
1088 pfile_info->AllocationSize = pSMBr->AllocationSize;
1089 pfile_info->EndOfFile = pSMBr->EndOfFile;
1090 pfile_info->NumberOfLinks = cpu_to_le32(1);
1094 cifs_buf_release(pSMB);
1101 CIFSSMBRead(const int xid, struct cifsTconInfo *tcon,
1102 const int netfid, const unsigned int count,
1103 const __u64 lseek, unsigned int *nbytes, char **buf,
1107 READ_REQ *pSMB = NULL;
1108 READ_RSP *pSMBr = NULL;
1109 char *pReadData = NULL;
1111 int resp_buf_type = 0;
1114 cFYI(1,("Reading %d bytes on fid %d",count,netfid));
1115 if(tcon->ses->capabilities & CAP_LARGE_FILES)
1118 wct = 10; /* old style read */
1121 rc = small_smb_init(SMB_COM_READ_ANDX, wct, tcon, (void **) &pSMB);
1125 /* tcon and ses pointer are checked in smb_init */
1126 if (tcon->ses->server == NULL)
1127 return -ECONNABORTED;
1129 pSMB->AndXCommand = 0xFF; /* none */
1131 pSMB->OffsetLow = cpu_to_le32(lseek & 0xFFFFFFFF);
1133 pSMB->OffsetHigh = cpu_to_le32(lseek >> 32);
1134 else if((lseek >> 32) > 0) /* can not handle this big offset for old */
1137 pSMB->Remaining = 0;
1138 pSMB->MaxCount = cpu_to_le16(count & 0xFFFF);
1139 pSMB->MaxCountHigh = cpu_to_le32(count >> 16);
1141 pSMB->ByteCount = 0; /* no need to do le conversion since 0 */
1143 /* old style read */
1144 struct smb_com_readx_req * pSMBW =
1145 (struct smb_com_readx_req *)pSMB;
1146 pSMBW->ByteCount = 0;
1149 iov[0].iov_base = (char *)pSMB;
1150 iov[0].iov_len = pSMB->hdr.smb_buf_length + 4;
1151 rc = SendReceive2(xid, tcon->ses, iov,
1154 cifs_stats_inc(&tcon->num_reads);
1155 pSMBr = (READ_RSP *)iov[0].iov_base;
1157 cERROR(1, ("Send error in read = %d", rc));
1159 int data_length = le16_to_cpu(pSMBr->DataLengthHigh);
1160 data_length = data_length << 16;
1161 data_length += le16_to_cpu(pSMBr->DataLength);
1162 *nbytes = data_length;
1164 /*check that DataLength would not go beyond end of SMB */
1165 if ((data_length > CIFSMaxBufSize)
1166 || (data_length > count)) {
1167 cFYI(1,("bad length %d for count %d",data_length,count));
1171 pReadData = (char *) (&pSMBr->hdr.Protocol) +
1172 le16_to_cpu(pSMBr->DataOffset);
1173 /* if(rc = copy_to_user(buf, pReadData, data_length)) {
1174 cERROR(1,("Faulting on read rc = %d",rc));
1176 }*/ /* can not use copy_to_user when using page cache*/
1178 memcpy(*buf,pReadData,data_length);
1182 /* cifs_small_buf_release(pSMB); */ /* Freed earlier now in SendReceive2 */
1184 if(resp_buf_type == CIFS_SMALL_BUFFER)
1185 cifs_small_buf_release(iov[0].iov_base);
1186 else if(resp_buf_type == CIFS_LARGE_BUFFER)
1187 cifs_buf_release(iov[0].iov_base);
1188 } else if(resp_buf_type != CIFS_NO_BUFFER) {
1189 /* return buffer to caller to free */
1190 *buf = iov[0].iov_base;
1191 if(resp_buf_type == CIFS_SMALL_BUFFER)
1192 *pbuf_type = CIFS_SMALL_BUFFER;
1193 else if(resp_buf_type == CIFS_LARGE_BUFFER)
1194 *pbuf_type = CIFS_LARGE_BUFFER;
1195 } /* else no valid buffer on return - leave as null */
1197 /* Note: On -EAGAIN error only caller can retry on handle based calls
1198 since file handle passed in no longer valid */
1204 CIFSSMBWrite(const int xid, struct cifsTconInfo *tcon,
1205 const int netfid, const unsigned int count,
1206 const __u64 offset, unsigned int *nbytes, const char *buf,
1207 const char __user * ubuf, const int long_op)
1210 WRITE_REQ *pSMB = NULL;
1211 WRITE_RSP *pSMBr = NULL;
1212 int bytes_returned, wct;
1216 /* cFYI(1,("write at %lld %d bytes",offset,count));*/
1217 if(tcon->ses == NULL)
1218 return -ECONNABORTED;
1220 if(tcon->ses->capabilities & CAP_LARGE_FILES)
1225 rc = smb_init(SMB_COM_WRITE_ANDX, wct, tcon, (void **) &pSMB,
1229 /* tcon and ses pointer are checked in smb_init */
1230 if (tcon->ses->server == NULL)
1231 return -ECONNABORTED;
1233 pSMB->AndXCommand = 0xFF; /* none */
1235 pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF);
1237 pSMB->OffsetHigh = cpu_to_le32(offset >> 32);
1238 else if((offset >> 32) > 0) /* can not handle this big offset for old */
1241 pSMB->Reserved = 0xFFFFFFFF;
1242 pSMB->WriteMode = 0;
1243 pSMB->Remaining = 0;
1245 /* Can increase buffer size if buffer is big enough in some cases - ie we
1246 can send more if LARGE_WRITE_X capability returned by the server and if
1247 our buffer is big enough or if we convert to iovecs on socket writes
1248 and eliminate the copy to the CIFS buffer */
1249 if(tcon->ses->capabilities & CAP_LARGE_WRITE_X) {
1250 bytes_sent = min_t(const unsigned int, CIFSMaxBufSize, count);
1252 bytes_sent = (tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE)
1256 if (bytes_sent > count)
1259 cpu_to_le16(offsetof(struct smb_com_write_req,Data) - 4);
1261 memcpy(pSMB->Data,buf,bytes_sent);
1263 if(copy_from_user(pSMB->Data,ubuf,bytes_sent)) {
1264 cifs_buf_release(pSMB);
1267 } else if (count != 0) {
1269 cifs_buf_release(pSMB);
1271 } /* else setting file size with write of zero bytes */
1273 byte_count = bytes_sent + 1; /* pad */
1274 else /* wct == 12 */ {
1275 byte_count = bytes_sent + 5; /* bigger pad, smaller smb hdr */
1277 pSMB->DataLengthLow = cpu_to_le16(bytes_sent & 0xFFFF);
1278 pSMB->DataLengthHigh = cpu_to_le16(bytes_sent >> 16);
1279 pSMB->hdr.smb_buf_length += byte_count;
1282 pSMB->ByteCount = cpu_to_le16(byte_count);
1283 else { /* old style write has byte count 4 bytes earlier so 4 bytes pad */
1284 struct smb_com_writex_req * pSMBW =
1285 (struct smb_com_writex_req *)pSMB;
1286 pSMBW->ByteCount = cpu_to_le16(byte_count);
1289 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1290 (struct smb_hdr *) pSMBr, &bytes_returned, long_op);
1291 cifs_stats_inc(&tcon->num_writes);
1293 cFYI(1, ("Send error in write = %d", rc));
1296 *nbytes = le16_to_cpu(pSMBr->CountHigh);
1297 *nbytes = (*nbytes) << 16;
1298 *nbytes += le16_to_cpu(pSMBr->Count);
1301 cifs_buf_release(pSMB);
1303 /* Note: On -EAGAIN error only caller can retry on handle based calls
1304 since file handle passed in no longer valid */
1310 CIFSSMBWrite2(const int xid, struct cifsTconInfo *tcon,
1311 const int netfid, const unsigned int count,
1312 const __u64 offset, unsigned int *nbytes, struct kvec *iov,
1313 int n_vec, const int long_op)
1316 WRITE_REQ *pSMB = NULL;
1319 int resp_buf_type = 0;
1321 cFYI(1,("write2 at %lld %d bytes", (long long)offset, count));
1323 if(tcon->ses->capabilities & CAP_LARGE_FILES)
1327 rc = small_smb_init(SMB_COM_WRITE_ANDX, wct, tcon, (void **) &pSMB);
1330 /* tcon and ses pointer are checked in smb_init */
1331 if (tcon->ses->server == NULL)
1332 return -ECONNABORTED;
1334 pSMB->AndXCommand = 0xFF; /* none */
1336 pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF);
1338 pSMB->OffsetHigh = cpu_to_le32(offset >> 32);
1339 else if((offset >> 32) > 0) /* can not handle this big offset for old */
1341 pSMB->Reserved = 0xFFFFFFFF;
1342 pSMB->WriteMode = 0;
1343 pSMB->Remaining = 0;
1346 cpu_to_le16(offsetof(struct smb_com_write_req,Data) - 4);
1348 pSMB->DataLengthLow = cpu_to_le16(count & 0xFFFF);
1349 pSMB->DataLengthHigh = cpu_to_le16(count >> 16);
1350 smb_hdr_len = pSMB->hdr.smb_buf_length + 1; /* hdr + 1 byte pad */
1352 pSMB->hdr.smb_buf_length += count+1;
1353 else /* wct == 12 */
1354 pSMB->hdr.smb_buf_length += count+5; /* smb data starts later */
1356 pSMB->ByteCount = cpu_to_le16(count + 1);
1357 else /* wct == 12 */ /* bigger pad, smaller smb hdr, keep offset ok */ {
1358 struct smb_com_writex_req * pSMBW =
1359 (struct smb_com_writex_req *)pSMB;
1360 pSMBW->ByteCount = cpu_to_le16(count + 5);
1362 iov[0].iov_base = pSMB;
1364 iov[0].iov_len = smb_hdr_len + 4;
1365 else /* wct == 12 pad bigger by four bytes */
1366 iov[0].iov_len = smb_hdr_len + 8;
1369 rc = SendReceive2(xid, tcon->ses, iov, n_vec + 1, &resp_buf_type,
1371 cifs_stats_inc(&tcon->num_writes);
1373 cFYI(1, ("Send error Write2 = %d", rc));
1375 } else if(resp_buf_type == 0) {
1376 /* presumably this can not happen, but best to be safe */
1380 WRITE_RSP * pSMBr = (WRITE_RSP *)iov[0].iov_base;
1381 *nbytes = le16_to_cpu(pSMBr->CountHigh);
1382 *nbytes = (*nbytes) << 16;
1383 *nbytes += le16_to_cpu(pSMBr->Count);
1386 /* cifs_small_buf_release(pSMB); */ /* Freed earlier now in SendReceive2 */
1387 if(resp_buf_type == CIFS_SMALL_BUFFER)
1388 cifs_small_buf_release(iov[0].iov_base);
1389 else if(resp_buf_type == CIFS_LARGE_BUFFER)
1390 cifs_buf_release(iov[0].iov_base);
1392 /* Note: On -EAGAIN error only caller can retry on handle based calls
1393 since file handle passed in no longer valid */
1400 CIFSSMBLock(const int xid, struct cifsTconInfo *tcon,
1401 const __u16 smb_file_id, const __u64 len,
1402 const __u64 offset, const __u32 numUnlock,
1403 const __u32 numLock, const __u8 lockType, const int waitFlag)
1406 LOCK_REQ *pSMB = NULL;
1407 LOCK_RSP *pSMBr = NULL;
1412 cFYI(1, ("In CIFSSMBLock - timeout %d numLock %d",waitFlag,numLock));
1413 rc = small_smb_init(SMB_COM_LOCKING_ANDX, 8, tcon, (void **) &pSMB);
1418 pSMBr = (LOCK_RSP *)pSMB; /* BB removeme BB */
1420 if(lockType == LOCKING_ANDX_OPLOCK_RELEASE) {
1421 timeout = -1; /* no response expected */
1423 } else if (waitFlag == TRUE) {
1424 timeout = 3; /* blocking operation, no timeout */
1425 pSMB->Timeout = cpu_to_le32(-1);/* blocking - do not time out */
1430 pSMB->NumberOfLocks = cpu_to_le16(numLock);
1431 pSMB->NumberOfUnlocks = cpu_to_le16(numUnlock);
1432 pSMB->LockType = lockType;
1433 pSMB->AndXCommand = 0xFF; /* none */
1434 pSMB->Fid = smb_file_id; /* netfid stays le */
1436 if((numLock != 0) || (numUnlock != 0)) {
1437 pSMB->Locks[0].Pid = cpu_to_le16(current->tgid);
1438 /* BB where to store pid high? */
1439 pSMB->Locks[0].LengthLow = cpu_to_le32((u32)len);
1440 pSMB->Locks[0].LengthHigh = cpu_to_le32((u32)(len>>32));
1441 pSMB->Locks[0].OffsetLow = cpu_to_le32((u32)offset);
1442 pSMB->Locks[0].OffsetHigh = cpu_to_le32((u32)(offset>>32));
1443 count = sizeof(LOCKING_ANDX_RANGE);
1448 pSMB->hdr.smb_buf_length += count;
1449 pSMB->ByteCount = cpu_to_le16(count);
1451 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1452 (struct smb_hdr *) pSMBr, &bytes_returned, timeout);
1453 cifs_stats_inc(&tcon->num_locks);
1455 cFYI(1, ("Send error in Lock = %d", rc));
1457 cifs_small_buf_release(pSMB);
1459 /* Note: On -EAGAIN error only caller can retry on handle based calls
1460 since file handle passed in no longer valid */
1465 CIFSSMBPosixLock(const int xid, struct cifsTconInfo *tcon,
1466 const __u16 smb_file_id, const int get_flag, const __u64 len,
1467 struct file_lock *pLockData, const __u16 lock_type,
1470 struct smb_com_transaction2_sfi_req *pSMB = NULL;
1471 struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
1473 struct cifs_posix_lock *parm_data;
1475 int bytes_returned = 0;
1476 __u16 params, param_offset, offset, byte_count, count;
1478 cFYI(1, ("Posix Lock"));
1480 if(pLockData == NULL)
1483 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
1488 pSMBr = (struct smb_com_transaction2_sfi_rsp *)pSMB;
1491 pSMB->MaxSetupCount = 0;
1495 pSMB->Reserved2 = 0;
1496 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
1497 offset = param_offset + params;
1499 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
1501 count = sizeof(struct cifs_posix_lock);
1502 pSMB->MaxParameterCount = cpu_to_le16(2);
1503 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB PDU from sess */
1504 pSMB->SetupCount = 1;
1505 pSMB->Reserved3 = 0;
1507 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION);
1509 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
1510 byte_count = 3 /* pad */ + params + count;
1511 pSMB->DataCount = cpu_to_le16(count);
1512 pSMB->ParameterCount = cpu_to_le16(params);
1513 pSMB->TotalDataCount = pSMB->DataCount;
1514 pSMB->TotalParameterCount = pSMB->ParameterCount;
1515 pSMB->ParameterOffset = cpu_to_le16(param_offset);
1516 parm_data = (struct cifs_posix_lock *)
1517 (((char *) &pSMB->hdr.Protocol) + offset);
1519 parm_data->lock_type = cpu_to_le16(lock_type);
1521 parm_data->lock_flags = cpu_to_le16(1);
1522 parm_data->pid = cpu_to_le32(current->tgid);
1523 parm_data->start = cpu_to_le64(pLockData->fl_start);
1524 parm_data->length = cpu_to_le64(len); /* normalize negative numbers */
1526 pSMB->DataOffset = cpu_to_le16(offset);
1527 pSMB->Fid = smb_file_id;
1528 pSMB->InformationLevel = cpu_to_le16(SMB_SET_POSIX_LOCK);
1529 pSMB->Reserved4 = 0;
1530 pSMB->hdr.smb_buf_length += byte_count;
1531 pSMB->ByteCount = cpu_to_le16(byte_count);
1532 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1533 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1535 cFYI(1, ("Send error in Posix Lock = %d", rc));
1536 } else if (get_flag) {
1537 /* lock structure can be returned on get */
1540 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
1542 if (rc || (pSMBr->ByteCount < sizeof(struct cifs_posix_lock))) {
1543 rc = -EIO; /* bad smb */
1546 if(pLockData == NULL) {
1550 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
1551 data_count = le16_to_cpu(pSMBr->t2.DataCount);
1552 if(data_count < sizeof(struct cifs_posix_lock)) {
1556 parm_data = (struct cifs_posix_lock *)
1557 ((char *)&pSMBr->hdr.Protocol + data_offset);
1558 if(parm_data->lock_type == cpu_to_le16(CIFS_UNLCK))
1559 pLockData->fl_type = F_UNLCK;
1564 cifs_small_buf_release(pSMB);
1566 /* Note: On -EAGAIN error only caller can retry on handle based calls
1567 since file handle passed in no longer valid */
1574 CIFSSMBClose(const int xid, struct cifsTconInfo *tcon, int smb_file_id)
1577 CLOSE_REQ *pSMB = NULL;
1578 CLOSE_RSP *pSMBr = NULL;
1580 cFYI(1, ("In CIFSSMBClose"));
1582 /* do not retry on dead session on close */
1583 rc = small_smb_init(SMB_COM_CLOSE, 3, tcon, (void **) &pSMB);
1589 pSMBr = (CLOSE_RSP *)pSMB; /* BB removeme BB */
1591 pSMB->FileID = (__u16) smb_file_id;
1592 pSMB->LastWriteTime = 0;
1593 pSMB->ByteCount = 0;
1594 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1595 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1596 cifs_stats_inc(&tcon->num_closes);
1599 /* EINTR is expected when user ctl-c to kill app */
1600 cERROR(1, ("Send error in Close = %d", rc));
1604 cifs_small_buf_release(pSMB);
1606 /* Since session is dead, file will be closed on server already */
1614 CIFSSMBRename(const int xid, struct cifsTconInfo *tcon,
1615 const char *fromName, const char *toName,
1616 const struct nls_table *nls_codepage, int remap)
1619 RENAME_REQ *pSMB = NULL;
1620 RENAME_RSP *pSMBr = NULL;
1622 int name_len, name_len2;
1625 cFYI(1, ("In CIFSSMBRename"));
1627 rc = smb_init(SMB_COM_RENAME, 1, tcon, (void **) &pSMB,
1632 pSMB->BufferFormat = 0x04;
1633 pSMB->SearchAttributes =
1634 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
1637 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1639 cifsConvertToUCS((__le16 *) pSMB->OldFileName, fromName,
1640 PATH_MAX, nls_codepage, remap);
1641 name_len++; /* trailing null */
1643 pSMB->OldFileName[name_len] = 0x04; /* pad */
1644 /* protocol requires ASCII signature byte on Unicode string */
1645 pSMB->OldFileName[name_len + 1] = 0x00;
1647 cifsConvertToUCS((__le16 *) &pSMB->OldFileName[name_len + 2],
1648 toName, PATH_MAX, nls_codepage, remap);
1649 name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
1650 name_len2 *= 2; /* convert to bytes */
1651 } else { /* BB improve the check for buffer overruns BB */
1652 name_len = strnlen(fromName, PATH_MAX);
1653 name_len++; /* trailing null */
1654 strncpy(pSMB->OldFileName, fromName, name_len);
1655 name_len2 = strnlen(toName, PATH_MAX);
1656 name_len2++; /* trailing null */
1657 pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */
1658 strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2);
1659 name_len2++; /* trailing null */
1660 name_len2++; /* signature byte */
1663 count = 1 /* 1st signature byte */ + name_len + name_len2;
1664 pSMB->hdr.smb_buf_length += count;
1665 pSMB->ByteCount = cpu_to_le16(count);
1667 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1668 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1669 cifs_stats_inc(&tcon->num_renames);
1671 cFYI(1, ("Send error in rename = %d", rc));
1674 cifs_buf_release(pSMB);
1682 int CIFSSMBRenameOpenFile(const int xid,struct cifsTconInfo *pTcon,
1683 int netfid, char * target_name,
1684 const struct nls_table * nls_codepage, int remap)
1686 struct smb_com_transaction2_sfi_req *pSMB = NULL;
1687 struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
1688 struct set_file_rename * rename_info;
1690 char dummy_string[30];
1692 int bytes_returned = 0;
1694 __u16 params, param_offset, offset, count, byte_count;
1696 cFYI(1, ("Rename to File by handle"));
1697 rc = smb_init(SMB_COM_TRANSACTION2, 15, pTcon, (void **) &pSMB,
1703 pSMB->MaxSetupCount = 0;
1707 pSMB->Reserved2 = 0;
1708 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
1709 offset = param_offset + params;
1711 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
1712 rename_info = (struct set_file_rename *) data_offset;
1713 pSMB->MaxParameterCount = cpu_to_le16(2);
1714 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB PDU from sess */
1715 pSMB->SetupCount = 1;
1716 pSMB->Reserved3 = 0;
1717 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
1718 byte_count = 3 /* pad */ + params;
1719 pSMB->ParameterCount = cpu_to_le16(params);
1720 pSMB->TotalParameterCount = pSMB->ParameterCount;
1721 pSMB->ParameterOffset = cpu_to_le16(param_offset);
1722 pSMB->DataOffset = cpu_to_le16(offset);
1723 /* construct random name ".cifs_tmp<inodenum><mid>" */
1724 rename_info->overwrite = cpu_to_le32(1);
1725 rename_info->root_fid = 0;
1726 /* unicode only call */
1727 if(target_name == NULL) {
1728 sprintf(dummy_string,"cifs%x",pSMB->hdr.Mid);
1729 len_of_str = cifsConvertToUCS((__le16 *)rename_info->target_name,
1730 dummy_string, 24, nls_codepage, remap);
1732 len_of_str = cifsConvertToUCS((__le16 *)rename_info->target_name,
1733 target_name, PATH_MAX, nls_codepage, remap);
1735 rename_info->target_name_len = cpu_to_le32(2 * len_of_str);
1736 count = 12 /* sizeof(struct set_file_rename) */ + (2 * len_of_str) + 2;
1737 byte_count += count;
1738 pSMB->DataCount = cpu_to_le16(count);
1739 pSMB->TotalDataCount = pSMB->DataCount;
1741 pSMB->InformationLevel =
1742 cpu_to_le16(SMB_SET_FILE_RENAME_INFORMATION);
1743 pSMB->Reserved4 = 0;
1744 pSMB->hdr.smb_buf_length += byte_count;
1745 pSMB->ByteCount = cpu_to_le16(byte_count);
1746 rc = SendReceive(xid, pTcon->ses, (struct smb_hdr *) pSMB,
1747 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1748 cifs_stats_inc(&pTcon->num_t2renames);
1750 cFYI(1,("Send error in Rename (by file handle) = %d", rc));
1753 cifs_buf_release(pSMB);
1755 /* Note: On -EAGAIN error only caller can retry on handle based calls
1756 since file handle passed in no longer valid */
1762 CIFSSMBCopy(const int xid, struct cifsTconInfo *tcon, const char * fromName,
1763 const __u16 target_tid, const char *toName, const int flags,
1764 const struct nls_table *nls_codepage, int remap)
1767 COPY_REQ *pSMB = NULL;
1768 COPY_RSP *pSMBr = NULL;
1770 int name_len, name_len2;
1773 cFYI(1, ("In CIFSSMBCopy"));
1775 rc = smb_init(SMB_COM_COPY, 1, tcon, (void **) &pSMB,
1780 pSMB->BufferFormat = 0x04;
1781 pSMB->Tid2 = target_tid;
1783 pSMB->Flags = cpu_to_le16(flags & COPY_TREE);
1785 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1786 name_len = cifsConvertToUCS((__le16 *) pSMB->OldFileName,
1787 fromName, PATH_MAX, nls_codepage,
1789 name_len++; /* trailing null */
1791 pSMB->OldFileName[name_len] = 0x04; /* pad */
1792 /* protocol requires ASCII signature byte on Unicode string */
1793 pSMB->OldFileName[name_len + 1] = 0x00;
1794 name_len2 = cifsConvertToUCS((__le16 *)&pSMB->OldFileName[name_len + 2],
1795 toName, PATH_MAX, nls_codepage, remap);
1796 name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
1797 name_len2 *= 2; /* convert to bytes */
1798 } else { /* BB improve the check for buffer overruns BB */
1799 name_len = strnlen(fromName, PATH_MAX);
1800 name_len++; /* trailing null */
1801 strncpy(pSMB->OldFileName, fromName, name_len);
1802 name_len2 = strnlen(toName, PATH_MAX);
1803 name_len2++; /* trailing null */
1804 pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */
1805 strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2);
1806 name_len2++; /* trailing null */
1807 name_len2++; /* signature byte */
1810 count = 1 /* 1st signature byte */ + name_len + name_len2;
1811 pSMB->hdr.smb_buf_length += count;
1812 pSMB->ByteCount = cpu_to_le16(count);
1814 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1815 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1817 cFYI(1, ("Send error in copy = %d with %d files copied",
1818 rc, le16_to_cpu(pSMBr->CopyCount)));
1821 cifs_buf_release(pSMB);
1830 CIFSUnixCreateSymLink(const int xid, struct cifsTconInfo *tcon,
1831 const char *fromName, const char *toName,
1832 const struct nls_table *nls_codepage)
1834 TRANSACTION2_SPI_REQ *pSMB = NULL;
1835 TRANSACTION2_SPI_RSP *pSMBr = NULL;
1838 int name_len_target;
1840 int bytes_returned = 0;
1841 __u16 params, param_offset, offset, byte_count;
1843 cFYI(1, ("In Symlink Unix style"));
1845 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
1850 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1852 cifs_strtoUCS((__le16 *) pSMB->FileName, fromName, PATH_MAX
1853 /* find define for this maxpathcomponent */
1855 name_len++; /* trailing null */
1858 } else { /* BB improve the check for buffer overruns BB */
1859 name_len = strnlen(fromName, PATH_MAX);
1860 name_len++; /* trailing null */
1861 strncpy(pSMB->FileName, fromName, name_len);
1863 params = 6 + name_len;
1864 pSMB->MaxSetupCount = 0;
1868 pSMB->Reserved2 = 0;
1869 param_offset = offsetof(struct smb_com_transaction2_spi_req,
1870 InformationLevel) - 4;
1871 offset = param_offset + params;
1873 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
1874 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1876 cifs_strtoUCS((__le16 *) data_offset, toName, PATH_MAX
1877 /* find define for this maxpathcomponent */
1879 name_len_target++; /* trailing null */
1880 name_len_target *= 2;
1881 } else { /* BB improve the check for buffer overruns BB */
1882 name_len_target = strnlen(toName, PATH_MAX);
1883 name_len_target++; /* trailing null */
1884 strncpy(data_offset, toName, name_len_target);
1887 pSMB->MaxParameterCount = cpu_to_le16(2);
1888 /* BB find exact max on data count below from sess */
1889 pSMB->MaxDataCount = cpu_to_le16(1000);
1890 pSMB->SetupCount = 1;
1891 pSMB->Reserved3 = 0;
1892 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
1893 byte_count = 3 /* pad */ + params + name_len_target;
1894 pSMB->DataCount = cpu_to_le16(name_len_target);
1895 pSMB->ParameterCount = cpu_to_le16(params);
1896 pSMB->TotalDataCount = pSMB->DataCount;
1897 pSMB->TotalParameterCount = pSMB->ParameterCount;
1898 pSMB->ParameterOffset = cpu_to_le16(param_offset);
1899 pSMB->DataOffset = cpu_to_le16(offset);
1900 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_LINK);
1901 pSMB->Reserved4 = 0;
1902 pSMB->hdr.smb_buf_length += byte_count;
1903 pSMB->ByteCount = cpu_to_le16(byte_count);
1904 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1905 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1906 cifs_stats_inc(&tcon->num_symlinks);
1909 ("Send error in SetPathInfo (create symlink) = %d",
1914 cifs_buf_release(pSMB);
1917 goto createSymLinkRetry;
1923 CIFSUnixCreateHardLink(const int xid, struct cifsTconInfo *tcon,
1924 const char *fromName, const char *toName,
1925 const struct nls_table *nls_codepage, int remap)
1927 TRANSACTION2_SPI_REQ *pSMB = NULL;
1928 TRANSACTION2_SPI_RSP *pSMBr = NULL;
1931 int name_len_target;
1933 int bytes_returned = 0;
1934 __u16 params, param_offset, offset, byte_count;
1936 cFYI(1, ("In Create Hard link Unix style"));
1937 createHardLinkRetry:
1938 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
1943 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1944 name_len = cifsConvertToUCS((__le16 *) pSMB->FileName, toName,
1945 PATH_MAX, nls_codepage, remap);
1946 name_len++; /* trailing null */
1949 } else { /* BB improve the check for buffer overruns BB */
1950 name_len = strnlen(toName, PATH_MAX);
1951 name_len++; /* trailing null */
1952 strncpy(pSMB->FileName, toName, name_len);
1954 params = 6 + name_len;
1955 pSMB->MaxSetupCount = 0;
1959 pSMB->Reserved2 = 0;
1960 param_offset = offsetof(struct smb_com_transaction2_spi_req,
1961 InformationLevel) - 4;
1962 offset = param_offset + params;
1964 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
1965 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1967 cifsConvertToUCS((__le16 *) data_offset, fromName, PATH_MAX,
1968 nls_codepage, remap);
1969 name_len_target++; /* trailing null */
1970 name_len_target *= 2;
1971 } else { /* BB improve the check for buffer overruns BB */
1972 name_len_target = strnlen(fromName, PATH_MAX);
1973 name_len_target++; /* trailing null */
1974 strncpy(data_offset, fromName, name_len_target);
1977 pSMB->MaxParameterCount = cpu_to_le16(2);
1978 /* BB find exact max on data count below from sess*/
1979 pSMB->MaxDataCount = cpu_to_le16(1000);
1980 pSMB->SetupCount = 1;
1981 pSMB->Reserved3 = 0;
1982 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
1983 byte_count = 3 /* pad */ + params + name_len_target;
1984 pSMB->ParameterCount = cpu_to_le16(params);
1985 pSMB->TotalParameterCount = pSMB->ParameterCount;
1986 pSMB->DataCount = cpu_to_le16(name_len_target);
1987 pSMB->TotalDataCount = pSMB->DataCount;
1988 pSMB->ParameterOffset = cpu_to_le16(param_offset);
1989 pSMB->DataOffset = cpu_to_le16(offset);
1990 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_HLINK);
1991 pSMB->Reserved4 = 0;
1992 pSMB->hdr.smb_buf_length += byte_count;
1993 pSMB->ByteCount = cpu_to_le16(byte_count);
1994 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1995 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1996 cifs_stats_inc(&tcon->num_hardlinks);
1998 cFYI(1, ("Send error in SetPathInfo (hard link) = %d", rc));
2001 cifs_buf_release(pSMB);
2003 goto createHardLinkRetry;
2009 CIFSCreateHardLink(const int xid, struct cifsTconInfo *tcon,
2010 const char *fromName, const char *toName,
2011 const struct nls_table *nls_codepage, int remap)
2014 NT_RENAME_REQ *pSMB = NULL;
2015 RENAME_RSP *pSMBr = NULL;
2017 int name_len, name_len2;
2020 cFYI(1, ("In CIFSCreateHardLink"));
2021 winCreateHardLinkRetry:
2023 rc = smb_init(SMB_COM_NT_RENAME, 4, tcon, (void **) &pSMB,
2028 pSMB->SearchAttributes =
2029 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
2031 pSMB->Flags = cpu_to_le16(CREATE_HARD_LINK);
2032 pSMB->ClusterCount = 0;
2034 pSMB->BufferFormat = 0x04;
2036 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2038 cifsConvertToUCS((__le16 *) pSMB->OldFileName, fromName,
2039 PATH_MAX, nls_codepage, remap);
2040 name_len++; /* trailing null */
2042 pSMB->OldFileName[name_len] = 0; /* pad */
2043 pSMB->OldFileName[name_len + 1] = 0x04;
2045 cifsConvertToUCS((__le16 *)&pSMB->OldFileName[name_len + 2],
2046 toName, PATH_MAX, nls_codepage, remap);
2047 name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
2048 name_len2 *= 2; /* convert to bytes */
2049 } else { /* BB improve the check for buffer overruns BB */
2050 name_len = strnlen(fromName, PATH_MAX);
2051 name_len++; /* trailing null */
2052 strncpy(pSMB->OldFileName, fromName, name_len);
2053 name_len2 = strnlen(toName, PATH_MAX);
2054 name_len2++; /* trailing null */
2055 pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */
2056 strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2);
2057 name_len2++; /* trailing null */
2058 name_len2++; /* signature byte */
2061 count = 1 /* string type byte */ + name_len + name_len2;
2062 pSMB->hdr.smb_buf_length += count;
2063 pSMB->ByteCount = cpu_to_le16(count);
2065 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2066 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2067 cifs_stats_inc(&tcon->num_hardlinks);
2069 cFYI(1, ("Send error in hard link (NT rename) = %d", rc));
2071 cifs_buf_release(pSMB);
2073 goto winCreateHardLinkRetry;
2079 CIFSSMBUnixQuerySymLink(const int xid, struct cifsTconInfo *tcon,
2080 const unsigned char *searchName,
2081 char *symlinkinfo, const int buflen,
2082 const struct nls_table *nls_codepage)
2084 /* SMB_QUERY_FILE_UNIX_LINK */
2085 TRANSACTION2_QPI_REQ *pSMB = NULL;
2086 TRANSACTION2_QPI_RSP *pSMBr = NULL;
2090 __u16 params, byte_count;
2092 cFYI(1, ("In QPathSymLinkInfo (Unix) for path %s", searchName));
2095 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2100 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2102 cifs_strtoUCS((__le16 *) pSMB->FileName, searchName, PATH_MAX
2103 /* find define for this maxpathcomponent */
2105 name_len++; /* trailing null */
2107 } else { /* BB improve the check for buffer overruns BB */
2108 name_len = strnlen(searchName, PATH_MAX);
2109 name_len++; /* trailing null */
2110 strncpy(pSMB->FileName, searchName, name_len);
2113 params = 2 /* level */ + 4 /* rsrvd */ + name_len /* incl null */ ;
2114 pSMB->TotalDataCount = 0;
2115 pSMB->MaxParameterCount = cpu_to_le16(2);
2116 /* BB find exact max data count below from sess structure BB */
2117 pSMB->MaxDataCount = cpu_to_le16(4000);
2118 pSMB->MaxSetupCount = 0;
2122 pSMB->Reserved2 = 0;
2123 pSMB->ParameterOffset = cpu_to_le16(offsetof(
2124 struct smb_com_transaction2_qpi_req ,InformationLevel) - 4);
2125 pSMB->DataCount = 0;
2126 pSMB->DataOffset = 0;
2127 pSMB->SetupCount = 1;
2128 pSMB->Reserved3 = 0;
2129 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
2130 byte_count = params + 1 /* pad */ ;
2131 pSMB->TotalParameterCount = cpu_to_le16(params);
2132 pSMB->ParameterCount = pSMB->TotalParameterCount;
2133 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_LINK);
2134 pSMB->Reserved4 = 0;
2135 pSMB->hdr.smb_buf_length += byte_count;
2136 pSMB->ByteCount = cpu_to_le16(byte_count);
2138 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2139 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2141 cFYI(1, ("Send error in QuerySymLinkInfo = %d", rc));
2143 /* decode response */
2145 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
2146 if (rc || (pSMBr->ByteCount < 2))
2147 /* BB also check enough total bytes returned */
2148 rc = -EIO; /* bad smb */
2150 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
2151 __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
2153 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
2154 name_len = UniStrnlen((wchar_t *) ((char *)
2155 &pSMBr->hdr.Protocol +data_offset),
2156 min_t(const int, buflen,count) / 2);
2157 /* BB FIXME investigate remapping reserved chars here */
2158 cifs_strfromUCS_le(symlinkinfo,
2159 (__le16 *) ((char *)&pSMBr->hdr.Protocol +
2161 name_len, nls_codepage);
2163 strncpy(symlinkinfo,
2164 (char *) &pSMBr->hdr.Protocol +
2166 min_t(const int, buflen, count));
2168 symlinkinfo[buflen] = 0;
2169 /* just in case so calling code does not go off the end of buffer */
2172 cifs_buf_release(pSMB);
2174 goto querySymLinkRetry;
2178 /* Initialize NT TRANSACT SMB into small smb request buffer.
2179 This assumes that all NT TRANSACTS that we init here have
2180 total parm and data under about 400 bytes (to fit in small cifs
2181 buffer size), which is the case so far, it easily fits. NB:
2182 Setup words themselves and ByteCount
2183 MaxSetupCount (size of returned setup area) and
2184 MaxParameterCount (returned parms size) must be set by caller */
2186 smb_init_ntransact(const __u16 sub_command, const int setup_count,
2187 const int parm_len, struct cifsTconInfo *tcon,
2192 struct smb_com_ntransact_req * pSMB;
2194 rc = small_smb_init(SMB_COM_NT_TRANSACT, 19 + setup_count, tcon,
2198 *ret_buf = (void *)pSMB;
2200 pSMB->TotalParameterCount = cpu_to_le32(parm_len);
2201 pSMB->TotalDataCount = 0;
2202 pSMB->MaxDataCount = cpu_to_le32((tcon->ses->server->maxBuf -
2203 MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
2204 pSMB->ParameterCount = pSMB->TotalParameterCount;
2205 pSMB->DataCount = pSMB->TotalDataCount;
2206 temp_offset = offsetof(struct smb_com_ntransact_req, Parms) +
2207 (setup_count * 2) - 4 /* for rfc1001 length itself */;
2208 pSMB->ParameterOffset = cpu_to_le32(temp_offset);
2209 pSMB->DataOffset = cpu_to_le32(temp_offset + parm_len);
2210 pSMB->SetupCount = setup_count; /* no need to le convert byte fields */
2211 pSMB->SubCommand = cpu_to_le16(sub_command);
2216 validate_ntransact(char * buf, char ** ppparm, char ** ppdata,
2217 int * pdatalen, int * pparmlen)
2220 __u32 data_count, data_offset, parm_count, parm_offset;
2221 struct smb_com_ntransact_rsp * pSMBr;
2226 pSMBr = (struct smb_com_ntransact_rsp *)buf;
2228 /* ByteCount was converted from little endian in SendReceive */
2229 end_of_smb = 2 /* sizeof byte count */ + pSMBr->ByteCount +
2230 (char *)&pSMBr->ByteCount;
2233 data_offset = le32_to_cpu(pSMBr->DataOffset);
2234 data_count = le32_to_cpu(pSMBr->DataCount);
2235 parm_offset = le32_to_cpu(pSMBr->ParameterOffset);
2236 parm_count = le32_to_cpu(pSMBr->ParameterCount);
2238 *ppparm = (char *)&pSMBr->hdr.Protocol + parm_offset;
2239 *ppdata = (char *)&pSMBr->hdr.Protocol + data_offset;
2241 /* should we also check that parm and data areas do not overlap? */
2242 if(*ppparm > end_of_smb) {
2243 cFYI(1,("parms start after end of smb"));
2245 } else if(parm_count + *ppparm > end_of_smb) {
2246 cFYI(1,("parm end after end of smb"));
2248 } else if(*ppdata > end_of_smb) {
2249 cFYI(1,("data starts after end of smb"));
2251 } else if(data_count + *ppdata > end_of_smb) {
2252 cFYI(1,("data %p + count %d (%p) ends after end of smb %p start %p",
2253 *ppdata, data_count, (data_count + *ppdata), end_of_smb, pSMBr)); /* BB FIXME */
2255 } else if(parm_count + data_count > pSMBr->ByteCount) {
2256 cFYI(1,("parm count and data count larger than SMB"));
2263 CIFSSMBQueryReparseLinkInfo(const int xid, struct cifsTconInfo *tcon,
2264 const unsigned char *searchName,
2265 char *symlinkinfo, const int buflen,__u16 fid,
2266 const struct nls_table *nls_codepage)
2271 struct smb_com_transaction_ioctl_req * pSMB;
2272 struct smb_com_transaction_ioctl_rsp * pSMBr;
2274 cFYI(1, ("In Windows reparse style QueryLink for path %s", searchName));
2275 rc = smb_init(SMB_COM_NT_TRANSACT, 23, tcon, (void **) &pSMB,
2280 pSMB->TotalParameterCount = 0 ;
2281 pSMB->TotalDataCount = 0;
2282 pSMB->MaxParameterCount = cpu_to_le32(2);
2283 /* BB find exact data count max from sess structure BB */
2284 pSMB->MaxDataCount = cpu_to_le32((tcon->ses->server->maxBuf -
2285 MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
2286 pSMB->MaxSetupCount = 4;
2288 pSMB->ParameterOffset = 0;
2289 pSMB->DataCount = 0;
2290 pSMB->DataOffset = 0;
2291 pSMB->SetupCount = 4;
2292 pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_IOCTL);
2293 pSMB->ParameterCount = pSMB->TotalParameterCount;
2294 pSMB->FunctionCode = cpu_to_le32(FSCTL_GET_REPARSE_POINT);
2295 pSMB->IsFsctl = 1; /* FSCTL */
2296 pSMB->IsRootFlag = 0;
2297 pSMB->Fid = fid; /* file handle always le */
2298 pSMB->ByteCount = 0;
2300 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2301 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2303 cFYI(1, ("Send error in QueryReparseLinkInfo = %d", rc));
2304 } else { /* decode response */
2305 __u32 data_offset = le32_to_cpu(pSMBr->DataOffset);
2306 __u32 data_count = le32_to_cpu(pSMBr->DataCount);
2307 if ((pSMBr->ByteCount < 2) || (data_offset > 512))
2308 /* BB also check enough total bytes returned */
2309 rc = -EIO; /* bad smb */
2311 if(data_count && (data_count < 2048)) {
2312 char * end_of_smb = 2 /* sizeof byte count */ +
2314 (char *)&pSMBr->ByteCount;
2316 struct reparse_data * reparse_buf = (struct reparse_data *)
2317 ((char *)&pSMBr->hdr.Protocol + data_offset);
2318 if((char*)reparse_buf >= end_of_smb) {
2322 if((reparse_buf->LinkNamesBuf +
2323 reparse_buf->TargetNameOffset +
2324 reparse_buf->TargetNameLen) >
2326 cFYI(1,("reparse buf extended beyond SMB"));
2331 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
2332 name_len = UniStrnlen((wchar_t *)
2333 (reparse_buf->LinkNamesBuf +
2334 reparse_buf->TargetNameOffset),
2335 min(buflen/2, reparse_buf->TargetNameLen / 2));
2336 cifs_strfromUCS_le(symlinkinfo,
2337 (__le16 *) (reparse_buf->LinkNamesBuf +
2338 reparse_buf->TargetNameOffset),
2339 name_len, nls_codepage);
2340 } else { /* ASCII names */
2341 strncpy(symlinkinfo,reparse_buf->LinkNamesBuf +
2342 reparse_buf->TargetNameOffset,
2343 min_t(const int, buflen, reparse_buf->TargetNameLen));
2347 cFYI(1,("Invalid return data count on get reparse info ioctl"));
2349 symlinkinfo[buflen] = 0; /* just in case so the caller
2350 does not go off the end of the buffer */
2351 cFYI(1,("readlink result - %s",symlinkinfo));
2355 cifs_buf_release(pSMB);
2357 /* Note: On -EAGAIN error only caller can retry on handle based calls
2358 since file handle passed in no longer valid */
2363 #ifdef CONFIG_CIFS_POSIX
2365 /*Convert an Access Control Entry from wire format to local POSIX xattr format*/
2366 static void cifs_convert_ace(posix_acl_xattr_entry * ace, struct cifs_posix_ace * cifs_ace)
2368 /* u8 cifs fields do not need le conversion */
2369 ace->e_perm = cpu_to_le16(cifs_ace->cifs_e_perm);
2370 ace->e_tag = cpu_to_le16(cifs_ace->cifs_e_tag);
2371 ace->e_id = cpu_to_le32(le64_to_cpu(cifs_ace->cifs_uid));
2372 /* cFYI(1,("perm %d tag %d id %d",ace->e_perm,ace->e_tag,ace->e_id)); */
2377 /* Convert ACL from CIFS POSIX wire format to local Linux POSIX ACL xattr */
2378 static int cifs_copy_posix_acl(char * trgt,char * src, const int buflen,
2379 const int acl_type,const int size_of_data_area)
2384 struct cifs_posix_ace * pACE;
2385 struct cifs_posix_acl * cifs_acl = (struct cifs_posix_acl *)src;
2386 posix_acl_xattr_header * local_acl = (posix_acl_xattr_header *)trgt;
2388 if (le16_to_cpu(cifs_acl->version) != CIFS_ACL_VERSION)
2391 if(acl_type & ACL_TYPE_ACCESS) {
2392 count = le16_to_cpu(cifs_acl->access_entry_count);
2393 pACE = &cifs_acl->ace_array[0];
2394 size = sizeof(struct cifs_posix_acl);
2395 size += sizeof(struct cifs_posix_ace) * count;
2396 /* check if we would go beyond end of SMB */
2397 if(size_of_data_area < size) {
2398 cFYI(1,("bad CIFS POSIX ACL size %d vs. %d",size_of_data_area,size));
2401 } else if(acl_type & ACL_TYPE_DEFAULT) {
2402 count = le16_to_cpu(cifs_acl->access_entry_count);
2403 size = sizeof(struct cifs_posix_acl);
2404 size += sizeof(struct cifs_posix_ace) * count;
2405 /* skip past access ACEs to get to default ACEs */
2406 pACE = &cifs_acl->ace_array[count];
2407 count = le16_to_cpu(cifs_acl->default_entry_count);
2408 size += sizeof(struct cifs_posix_ace) * count;
2409 /* check if we would go beyond end of SMB */
2410 if(size_of_data_area < size)
2417 size = posix_acl_xattr_size(count);
2418 if((buflen == 0) || (local_acl == NULL)) {
2419 /* used to query ACL EA size */
2420 } else if(size > buflen) {
2422 } else /* buffer big enough */ {
2423 local_acl->a_version = cpu_to_le32(POSIX_ACL_XATTR_VERSION);
2424 for(i = 0;i < count ;i++) {
2425 cifs_convert_ace(&local_acl->a_entries[i],pACE);
2432 static __u16 convert_ace_to_cifs_ace(struct cifs_posix_ace * cifs_ace,
2433 const posix_acl_xattr_entry * local_ace)
2435 __u16 rc = 0; /* 0 = ACL converted ok */
2437 cifs_ace->cifs_e_perm = le16_to_cpu(local_ace->e_perm);
2438 cifs_ace->cifs_e_tag = le16_to_cpu(local_ace->e_tag);
2439 /* BB is there a better way to handle the large uid? */
2440 if(local_ace->e_id == cpu_to_le32(-1)) {
2441 /* Probably no need to le convert -1 on any arch but can not hurt */
2442 cifs_ace->cifs_uid = cpu_to_le64(-1);
2444 cifs_ace->cifs_uid = cpu_to_le64(le32_to_cpu(local_ace->e_id));
2445 /*cFYI(1,("perm %d tag %d id %d",ace->e_perm,ace->e_tag,ace->e_id));*/
2449 /* Convert ACL from local Linux POSIX xattr to CIFS POSIX ACL wire format */
2450 static __u16 ACL_to_cifs_posix(char * parm_data,const char * pACL,const int buflen,
2454 struct cifs_posix_acl * cifs_acl = (struct cifs_posix_acl *)parm_data;
2455 posix_acl_xattr_header * local_acl = (posix_acl_xattr_header *)pACL;
2459 if((buflen == 0) || (pACL == NULL) || (cifs_acl == NULL))
2462 count = posix_acl_xattr_count((size_t)buflen);
2463 cFYI(1,("setting acl with %d entries from buf of length %d and version of %d",
2464 count, buflen, le32_to_cpu(local_acl->a_version)));
2465 if(le32_to_cpu(local_acl->a_version) != 2) {
2466 cFYI(1,("unknown POSIX ACL version %d",
2467 le32_to_cpu(local_acl->a_version)));
2470 cifs_acl->version = cpu_to_le16(1);
2471 if(acl_type == ACL_TYPE_ACCESS)
2472 cifs_acl->access_entry_count = cpu_to_le16(count);
2473 else if(acl_type == ACL_TYPE_DEFAULT)
2474 cifs_acl->default_entry_count = cpu_to_le16(count);
2476 cFYI(1,("unknown ACL type %d",acl_type));
2479 for(i=0;i<count;i++) {
2480 rc = convert_ace_to_cifs_ace(&cifs_acl->ace_array[i],
2481 &local_acl->a_entries[i]);
2483 /* ACE not converted */
2488 rc = (__u16)(count * sizeof(struct cifs_posix_ace));
2489 rc += sizeof(struct cifs_posix_acl);
2490 /* BB add check to make sure ACL does not overflow SMB */
2496 CIFSSMBGetPosixACL(const int xid, struct cifsTconInfo *tcon,
2497 const unsigned char *searchName,
2498 char *acl_inf, const int buflen, const int acl_type,
2499 const struct nls_table *nls_codepage, int remap)
2501 /* SMB_QUERY_POSIX_ACL */
2502 TRANSACTION2_QPI_REQ *pSMB = NULL;
2503 TRANSACTION2_QPI_RSP *pSMBr = NULL;
2507 __u16 params, byte_count;
2509 cFYI(1, ("In GetPosixACL (Unix) for path %s", searchName));
2512 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2517 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2519 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
2520 PATH_MAX, nls_codepage, remap);
2521 name_len++; /* trailing null */
2523 pSMB->FileName[name_len] = 0;
2524 pSMB->FileName[name_len+1] = 0;
2525 } else { /* BB improve the check for buffer overruns BB */
2526 name_len = strnlen(searchName, PATH_MAX);
2527 name_len++; /* trailing null */
2528 strncpy(pSMB->FileName, searchName, name_len);
2531 params = 2 /* level */ + 4 /* rsrvd */ + name_len /* incl null */ ;
2532 pSMB->TotalDataCount = 0;
2533 pSMB->MaxParameterCount = cpu_to_le16(2);
2534 /* BB find exact max data count below from sess structure BB */
2535 pSMB->MaxDataCount = cpu_to_le16(4000);
2536 pSMB->MaxSetupCount = 0;
2540 pSMB->Reserved2 = 0;
2541 pSMB->ParameterOffset = cpu_to_le16(
2542 offsetof(struct smb_com_transaction2_qpi_req ,InformationLevel) - 4);
2543 pSMB->DataCount = 0;
2544 pSMB->DataOffset = 0;
2545 pSMB->SetupCount = 1;
2546 pSMB->Reserved3 = 0;
2547 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
2548 byte_count = params + 1 /* pad */ ;
2549 pSMB->TotalParameterCount = cpu_to_le16(params);
2550 pSMB->ParameterCount = pSMB->TotalParameterCount;
2551 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_POSIX_ACL);
2552 pSMB->Reserved4 = 0;
2553 pSMB->hdr.smb_buf_length += byte_count;
2554 pSMB->ByteCount = cpu_to_le16(byte_count);
2556 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2557 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2558 cifs_stats_inc(&tcon->num_acl_get);
2560 cFYI(1, ("Send error in Query POSIX ACL = %d", rc));
2562 /* decode response */
2564 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
2565 if (rc || (pSMBr->ByteCount < 2))
2566 /* BB also check enough total bytes returned */
2567 rc = -EIO; /* bad smb */
2569 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
2570 __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
2571 rc = cifs_copy_posix_acl(acl_inf,
2572 (char *)&pSMBr->hdr.Protocol+data_offset,
2573 buflen,acl_type,count);
2576 cifs_buf_release(pSMB);
2583 CIFSSMBSetPosixACL(const int xid, struct cifsTconInfo *tcon,
2584 const unsigned char *fileName,
2585 const char *local_acl, const int buflen,
2587 const struct nls_table *nls_codepage, int remap)
2589 struct smb_com_transaction2_spi_req *pSMB = NULL;
2590 struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
2594 int bytes_returned = 0;
2595 __u16 params, byte_count, data_count, param_offset, offset;
2597 cFYI(1, ("In SetPosixACL (Unix) for path %s", fileName));
2599 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2603 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2605 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
2606 PATH_MAX, nls_codepage, remap);
2607 name_len++; /* trailing null */
2609 } else { /* BB improve the check for buffer overruns BB */
2610 name_len = strnlen(fileName, PATH_MAX);
2611 name_len++; /* trailing null */
2612 strncpy(pSMB->FileName, fileName, name_len);
2614 params = 6 + name_len;
2615 pSMB->MaxParameterCount = cpu_to_le16(2);
2616 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB size from sess */
2617 pSMB->MaxSetupCount = 0;
2621 pSMB->Reserved2 = 0;
2622 param_offset = offsetof(struct smb_com_transaction2_spi_req,
2623 InformationLevel) - 4;
2624 offset = param_offset + params;
2625 parm_data = ((char *) &pSMB->hdr.Protocol) + offset;
2626 pSMB->ParameterOffset = cpu_to_le16(param_offset);
2628 /* convert to on the wire format for POSIX ACL */
2629 data_count = ACL_to_cifs_posix(parm_data,local_acl,buflen,acl_type);
2631 if(data_count == 0) {
2633 goto setACLerrorExit;
2635 pSMB->DataOffset = cpu_to_le16(offset);
2636 pSMB->SetupCount = 1;
2637 pSMB->Reserved3 = 0;
2638 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
2639 pSMB->InformationLevel = cpu_to_le16(SMB_SET_POSIX_ACL);
2640 byte_count = 3 /* pad */ + params + data_count;
2641 pSMB->DataCount = cpu_to_le16(data_count);
2642 pSMB->TotalDataCount = pSMB->DataCount;
2643 pSMB->ParameterCount = cpu_to_le16(params);
2644 pSMB->TotalParameterCount = pSMB->ParameterCount;
2645 pSMB->Reserved4 = 0;
2646 pSMB->hdr.smb_buf_length += byte_count;
2647 pSMB->ByteCount = cpu_to_le16(byte_count);
2648 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2649 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2651 cFYI(1, ("Set POSIX ACL returned %d", rc));
2655 cifs_buf_release(pSMB);
2661 /* BB fix tabs in this function FIXME BB */
2663 CIFSGetExtAttr(const int xid, struct cifsTconInfo *tcon,
2664 const int netfid, __u64 * pExtAttrBits, __u64 *pMask)
2667 struct smb_t2_qfi_req *pSMB = NULL;
2668 struct smb_t2_qfi_rsp *pSMBr = NULL;
2670 __u16 params, byte_count;
2672 cFYI(1,("In GetExtAttr"));
2677 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2682 params = 2 /* level */ +2 /* fid */;
2683 pSMB->t2.TotalDataCount = 0;
2684 pSMB->t2.MaxParameterCount = cpu_to_le16(4);
2685 /* BB find exact max data count below from sess structure BB */
2686 pSMB->t2.MaxDataCount = cpu_to_le16(4000);
2687 pSMB->t2.MaxSetupCount = 0;
2688 pSMB->t2.Reserved = 0;
2690 pSMB->t2.Timeout = 0;
2691 pSMB->t2.Reserved2 = 0;
2692 pSMB->t2.ParameterOffset = cpu_to_le16(offsetof(struct smb_t2_qfi_req,
2694 pSMB->t2.DataCount = 0;
2695 pSMB->t2.DataOffset = 0;
2696 pSMB->t2.SetupCount = 1;
2697 pSMB->t2.Reserved3 = 0;
2698 pSMB->t2.SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION);
2699 byte_count = params + 1 /* pad */ ;
2700 pSMB->t2.TotalParameterCount = cpu_to_le16(params);
2701 pSMB->t2.ParameterCount = pSMB->t2.TotalParameterCount;
2702 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_ATTR_FLAGS);
2705 pSMB->hdr.smb_buf_length += byte_count;
2706 pSMB->t2.ByteCount = cpu_to_le16(byte_count);
2708 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2709 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2711 cFYI(1, ("error %d in GetExtAttr", rc));
2713 /* decode response */
2714 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
2715 if (rc || (pSMBr->ByteCount < 2))
2716 /* BB also check enough total bytes returned */
2717 /* If rc should we check for EOPNOSUPP and
2718 disable the srvino flag? or in caller? */
2719 rc = -EIO; /* bad smb */
2721 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
2722 __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
2723 struct file_chattr_info * pfinfo;
2724 /* BB Do we need a cast or hash here ? */
2726 cFYI(1, ("Illegal size ret in GetExtAttr"));
2730 pfinfo = (struct file_chattr_info *)
2731 (data_offset + (char *) &pSMBr->hdr.Protocol);
2732 *pExtAttrBits = le64_to_cpu(pfinfo->mode);
2733 *pMask = le64_to_cpu(pfinfo->mask);
2737 cifs_buf_release(pSMB);
2739 goto GetExtAttrRetry;
2744 #endif /* CONFIG_POSIX */
2747 /* security id for everyone */
2748 const struct cifs_sid sid_everyone = {1, 1, {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0}};
2750 const struct cifs_sid sid_user = {1, 2 , {0, 0, 0, 0, 0, 5}, {32, 545, 0, 0}};
2752 /* Convert CIFS ACL to POSIX form */
2753 static int parse_sec_desc(struct cifs_sid * psec_desc, int acl_len)
2758 /* Get Security Descriptor (by handle) from remote server for a file or dir */
2760 CIFSSMBGetCIFSACL(const int xid, struct cifsTconInfo *tcon, __u16 fid,
2761 /* BB fix up return info */ char *acl_inf, const int buflen,
2762 const int acl_type /* ACCESS/DEFAULT not sure implication */)
2766 QUERY_SEC_DESC_REQ * pSMB;
2769 cFYI(1, ("GetCifsACL"));
2771 rc = smb_init_ntransact(NT_TRANSACT_QUERY_SECURITY_DESC, 0,
2772 8 /* parm len */, tcon, (void **) &pSMB);
2776 pSMB->MaxParameterCount = cpu_to_le32(4);
2777 /* BB TEST with big acls that might need to be e.g. larger than 16K */
2778 pSMB->MaxSetupCount = 0;
2779 pSMB->Fid = fid; /* file handle always le */
2780 pSMB->AclFlags = cpu_to_le32(CIFS_ACL_OWNER | CIFS_ACL_GROUP |
2782 pSMB->ByteCount = cpu_to_le16(11); /* 3 bytes pad + 8 bytes parm */
2783 pSMB->hdr.smb_buf_length += 11;
2784 iov[0].iov_base = (char *)pSMB;
2785 iov[0].iov_len = pSMB->hdr.smb_buf_length + 4;
2787 rc = SendReceive2(xid, tcon->ses, iov, 1 /* num iovec */, &buf_type, 0);
2788 cifs_stats_inc(&tcon->num_acl_get);
2790 cFYI(1, ("Send error in QuerySecDesc = %d", rc));
2791 } else { /* decode response */
2792 struct cifs_sid * psec_desc;
2797 struct smb_com_ntransact_rsp * pSMBr;
2799 /* validate_nttransact */
2800 rc = validate_ntransact(iov[0].iov_base, (char **)&parm,
2801 (char **)&psec_desc,
2802 &parm_len, &data_len);
2806 pSMBr = (struct smb_com_ntransact_rsp *)iov[0].iov_base;
2808 cERROR(1,("smb %p parm %p data %p",pSMBr,parm,psec_desc)); /* BB removeme BB */
2810 if (le32_to_cpu(pSMBr->ParameterCount) != 4) {
2811 rc = -EIO; /* bad smb */
2815 /* BB check that data area is minimum length and as big as acl_len */
2817 acl_len = le32_to_cpu(*(__le32 *)parm);
2818 /* BB check if(acl_len > bufsize) */
2820 parse_sec_desc(psec_desc, acl_len);
2823 if(buf_type == CIFS_SMALL_BUFFER)
2824 cifs_small_buf_release(iov[0].iov_base);
2825 else if(buf_type == CIFS_LARGE_BUFFER)
2826 cifs_buf_release(iov[0].iov_base);
2827 /* cifs_small_buf_release(pSMB); */ /* Freed earlier now in SendReceive2 */
2832 /* Legacy Query Path Information call for lookup to old servers such
2834 int SMBQueryInformation(const int xid, struct cifsTconInfo *tcon,
2835 const unsigned char *searchName,
2836 FILE_ALL_INFO * pFinfo,
2837 const struct nls_table *nls_codepage, int remap)
2839 QUERY_INFORMATION_REQ * pSMB;
2840 QUERY_INFORMATION_RSP * pSMBr;
2845 cFYI(1, ("In SMBQPath path %s", searchName));
2847 rc = smb_init(SMB_COM_QUERY_INFORMATION, 0, tcon, (void **) &pSMB,
2852 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2854 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
2855 PATH_MAX, nls_codepage, remap);
2856 name_len++; /* trailing null */
2859 name_len = strnlen(searchName, PATH_MAX);
2860 name_len++; /* trailing null */
2861 strncpy(pSMB->FileName, searchName, name_len);
2863 pSMB->BufferFormat = 0x04;
2864 name_len++; /* account for buffer type byte */
2865 pSMB->hdr.smb_buf_length += (__u16) name_len;
2866 pSMB->ByteCount = cpu_to_le16(name_len);
2868 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2869 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2871 cFYI(1, ("Send error in QueryInfo = %d", rc));
2872 } else if (pFinfo) { /* decode response */
2873 memset(pFinfo, 0, sizeof(FILE_ALL_INFO));
2874 pFinfo->AllocationSize =
2875 cpu_to_le64(le32_to_cpu(pSMBr->size));
2876 pFinfo->EndOfFile = pFinfo->AllocationSize;
2877 pFinfo->Attributes =
2878 cpu_to_le32(le16_to_cpu(pSMBr->attr));
2880 rc = -EIO; /* bad buffer passed in */
2882 cifs_buf_release(pSMB);
2894 CIFSSMBQPathInfo(const int xid, struct cifsTconInfo *tcon,
2895 const unsigned char *searchName,
2896 FILE_ALL_INFO * pFindData,
2897 const struct nls_table *nls_codepage, int remap)
2899 /* level 263 SMB_QUERY_FILE_ALL_INFO */
2900 TRANSACTION2_QPI_REQ *pSMB = NULL;
2901 TRANSACTION2_QPI_RSP *pSMBr = NULL;
2905 __u16 params, byte_count;
2907 /* cFYI(1, ("In QPathInfo path %s", searchName)); */
2909 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2914 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2916 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
2917 PATH_MAX, nls_codepage, remap);
2918 name_len++; /* trailing null */
2920 } else { /* BB improve the check for buffer overruns BB */
2921 name_len = strnlen(searchName, PATH_MAX);
2922 name_len++; /* trailing null */
2923 strncpy(pSMB->FileName, searchName, name_len);
2926 params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */ ;
2927 pSMB->TotalDataCount = 0;
2928 pSMB->MaxParameterCount = cpu_to_le16(2);
2929 pSMB->MaxDataCount = cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
2930 pSMB->MaxSetupCount = 0;
2934 pSMB->Reserved2 = 0;
2935 pSMB->ParameterOffset = cpu_to_le16(offsetof(
2936 struct smb_com_transaction2_qpi_req ,InformationLevel) - 4);
2937 pSMB->DataCount = 0;
2938 pSMB->DataOffset = 0;
2939 pSMB->SetupCount = 1;
2940 pSMB->Reserved3 = 0;
2941 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
2942 byte_count = params + 1 /* pad */ ;
2943 pSMB->TotalParameterCount = cpu_to_le16(params);
2944 pSMB->ParameterCount = pSMB->TotalParameterCount;
2945 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_ALL_INFO);
2946 pSMB->Reserved4 = 0;
2947 pSMB->hdr.smb_buf_length += byte_count;
2948 pSMB->ByteCount = cpu_to_le16(byte_count);
2950 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2951 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2953 cFYI(1, ("Send error in QPathInfo = %d", rc));
2954 } else { /* decode response */
2955 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
2957 if (rc || (pSMBr->ByteCount < 40))
2958 rc = -EIO; /* bad smb */
2959 else if (pFindData){
2960 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
2961 memcpy((char *) pFindData,
2962 (char *) &pSMBr->hdr.Protocol +
2963 data_offset, sizeof (FILE_ALL_INFO));
2967 cifs_buf_release(pSMB);
2969 goto QPathInfoRetry;
2975 CIFSSMBUnixQPathInfo(const int xid, struct cifsTconInfo *tcon,
2976 const unsigned char *searchName,
2977 FILE_UNIX_BASIC_INFO * pFindData,
2978 const struct nls_table *nls_codepage, int remap)
2980 /* SMB_QUERY_FILE_UNIX_BASIC */
2981 TRANSACTION2_QPI_REQ *pSMB = NULL;
2982 TRANSACTION2_QPI_RSP *pSMBr = NULL;
2984 int bytes_returned = 0;
2986 __u16 params, byte_count;
2988 cFYI(1, ("In QPathInfo (Unix) the path %s", searchName));
2990 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2995 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2997 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
2998 PATH_MAX, nls_codepage, remap);
2999 name_len++; /* trailing null */
3001 } else { /* BB improve the check for buffer overruns BB */
3002 name_len = strnlen(searchName, PATH_MAX);
3003 name_len++; /* trailing null */
3004 strncpy(pSMB->FileName, searchName, name_len);
3007 params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */ ;
3008 pSMB->TotalDataCount = 0;
3009 pSMB->MaxParameterCount = cpu_to_le16(2);
3010 /* BB find exact max SMB PDU from sess structure BB */
3011 pSMB->MaxDataCount = cpu_to_le16(4000);
3012 pSMB->MaxSetupCount = 0;
3016 pSMB->Reserved2 = 0;
3017 pSMB->ParameterOffset = cpu_to_le16(offsetof(
3018 struct smb_com_transaction2_qpi_req ,InformationLevel) - 4);
3019 pSMB->DataCount = 0;
3020 pSMB->DataOffset = 0;
3021 pSMB->SetupCount = 1;
3022 pSMB->Reserved3 = 0;
3023 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
3024 byte_count = params + 1 /* pad */ ;
3025 pSMB->TotalParameterCount = cpu_to_le16(params);
3026 pSMB->ParameterCount = pSMB->TotalParameterCount;
3027 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC);
3028 pSMB->Reserved4 = 0;
3029 pSMB->hdr.smb_buf_length += byte_count;
3030 pSMB->ByteCount = cpu_to_le16(byte_count);
3032 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3033 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3035 cFYI(1, ("Send error in QPathInfo = %d", rc));
3036 } else { /* decode response */
3037 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3039 if (rc || (pSMBr->ByteCount < sizeof(FILE_UNIX_BASIC_INFO))) {
3040 rc = -EIO; /* bad smb */
3042 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3043 memcpy((char *) pFindData,
3044 (char *) &pSMBr->hdr.Protocol +
3046 sizeof (FILE_UNIX_BASIC_INFO));
3049 cifs_buf_release(pSMB);
3051 goto UnixQPathInfoRetry;
3056 #if 0 /* function unused at present */
3057 int CIFSFindSingle(const int xid, struct cifsTconInfo *tcon,
3058 const char *searchName, FILE_ALL_INFO * findData,
3059 const struct nls_table *nls_codepage)
3061 /* level 257 SMB_ */
3062 TRANSACTION2_FFIRST_REQ *pSMB = NULL;
3063 TRANSACTION2_FFIRST_RSP *pSMBr = NULL;
3067 __u16 params, byte_count;
3069 cFYI(1, ("In FindUnique"));
3071 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3076 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3078 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName, PATH_MAX
3079 /* find define for this maxpathcomponent */
3081 name_len++; /* trailing null */
3083 } else { /* BB improve the check for buffer overruns BB */
3084 name_len = strnlen(searchName, PATH_MAX);
3085 name_len++; /* trailing null */
3086 strncpy(pSMB->FileName, searchName, name_len);
3089 params = 12 + name_len /* includes null */ ;
3090 pSMB->TotalDataCount = 0; /* no EAs */
3091 pSMB->MaxParameterCount = cpu_to_le16(2);
3092 pSMB->MaxDataCount = cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
3093 pSMB->MaxSetupCount = 0;
3097 pSMB->Reserved2 = 0;
3098 pSMB->ParameterOffset = cpu_to_le16(
3099 offsetof(struct smb_com_transaction2_ffirst_req,InformationLevel) - 4);
3100 pSMB->DataCount = 0;
3101 pSMB->DataOffset = 0;
3102 pSMB->SetupCount = 1; /* one byte, no need to le convert */
3103 pSMB->Reserved3 = 0;
3104 pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_FIRST);
3105 byte_count = params + 1 /* pad */ ;
3106 pSMB->TotalParameterCount = cpu_to_le16(params);
3107 pSMB->ParameterCount = pSMB->TotalParameterCount;
3108 pSMB->SearchAttributes =
3109 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
3111 pSMB->SearchCount = cpu_to_le16(16); /* BB increase */
3112 pSMB->SearchFlags = cpu_to_le16(1);
3113 pSMB->InformationLevel = cpu_to_le16(SMB_FIND_FILE_DIRECTORY_INFO);
3114 pSMB->SearchStorageType = 0; /* BB what should we set this to? BB */
3115 pSMB->hdr.smb_buf_length += byte_count;
3116 pSMB->ByteCount = cpu_to_le16(byte_count);
3118 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3119 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3122 cFYI(1, ("Send error in FindFileDirInfo = %d", rc));
3123 } else { /* decode response */
3124 cifs_stats_inc(&tcon->num_ffirst);
3128 cifs_buf_release(pSMB);
3130 goto findUniqueRetry;
3134 #endif /* end unused (temporarily) function */
3136 /* xid, tcon, searchName and codepage are input parms, rest are returned */
3138 CIFSFindFirst(const int xid, struct cifsTconInfo *tcon,
3139 const char *searchName,
3140 const struct nls_table *nls_codepage,
3142 struct cifs_search_info * psrch_inf, int remap, const char dirsep)
3144 /* level 257 SMB_ */
3145 TRANSACTION2_FFIRST_REQ *pSMB = NULL;
3146 TRANSACTION2_FFIRST_RSP *pSMBr = NULL;
3147 T2_FFIRST_RSP_PARMS * parms;
3149 int bytes_returned = 0;
3151 __u16 params, byte_count;
3153 cFYI(1, ("In FindFirst for %s",searchName));
3156 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3161 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3163 cifsConvertToUCS((__le16 *) pSMB->FileName,searchName,
3164 PATH_MAX, nls_codepage, remap);
3165 /* We can not add the asterik earlier in case
3166 it got remapped to 0xF03A as if it were part of the
3167 directory name instead of a wildcard */
3169 pSMB->FileName[name_len] = dirsep;
3170 pSMB->FileName[name_len+1] = 0;
3171 pSMB->FileName[name_len+2] = '*';
3172 pSMB->FileName[name_len+3] = 0;
3173 name_len += 4; /* now the trailing null */
3174 pSMB->FileName[name_len] = 0; /* null terminate just in case */
3175 pSMB->FileName[name_len+1] = 0;
3177 } else { /* BB add check for overrun of SMB buf BB */
3178 name_len = strnlen(searchName, PATH_MAX);
3179 /* BB fix here and in unicode clause above ie
3180 if(name_len > buffersize-header)
3181 free buffer exit; BB */
3182 strncpy(pSMB->FileName, searchName, name_len);
3183 pSMB->FileName[name_len] = dirsep;
3184 pSMB->FileName[name_len+1] = '*';
3185 pSMB->FileName[name_len+2] = 0;
3189 params = 12 + name_len /* includes null */ ;
3190 pSMB->TotalDataCount = 0; /* no EAs */
3191 pSMB->MaxParameterCount = cpu_to_le16(10);
3192 pSMB->MaxDataCount = cpu_to_le16((tcon->ses->server->maxBuf -
3193 MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
3194 pSMB->MaxSetupCount = 0;
3198 pSMB->Reserved2 = 0;
3199 byte_count = params + 1 /* pad */ ;
3200 pSMB->TotalParameterCount = cpu_to_le16(params);
3201 pSMB->ParameterCount = pSMB->TotalParameterCount;
3202 pSMB->ParameterOffset = cpu_to_le16(
3203 offsetof(struct smb_com_transaction2_ffirst_req, SearchAttributes)
3205 pSMB->DataCount = 0;
3206 pSMB->DataOffset = 0;
3207 pSMB->SetupCount = 1; /* one byte, no need to make endian neutral */
3208 pSMB->Reserved3 = 0;
3209 pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_FIRST);
3210 pSMB->SearchAttributes =
3211 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
3213 pSMB->SearchCount= cpu_to_le16(CIFSMaxBufSize/sizeof(FILE_UNIX_INFO));
3214 pSMB->SearchFlags = cpu_to_le16(CIFS_SEARCH_CLOSE_AT_END |
3215 CIFS_SEARCH_RETURN_RESUME);
3216 pSMB->InformationLevel = cpu_to_le16(psrch_inf->info_level);
3218 /* BB what should we set StorageType to? Does it matter? BB */
3219 pSMB->SearchStorageType = 0;
3220 pSMB->hdr.smb_buf_length += byte_count;
3221 pSMB->ByteCount = cpu_to_le16(byte_count);
3223 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3224 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3225 cifs_stats_inc(&tcon->num_ffirst);
3227 if (rc) {/* BB add logic to retry regular search if Unix search
3228 rejected unexpectedly by server */
3229 /* BB Add code to handle unsupported level rc */
3230 cFYI(1, ("Error in FindFirst = %d", rc));
3232 cifs_buf_release(pSMB);
3234 /* BB eventually could optimize out free and realloc of buf */
3237 goto findFirstRetry;
3238 } else { /* decode response */
3239 /* BB remember to free buffer if error BB */
3240 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3242 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
3243 psrch_inf->unicode = TRUE;
3245 psrch_inf->unicode = FALSE;
3247 psrch_inf->ntwrk_buf_start = (char *)pSMBr;
3248 psrch_inf->smallBuf = 0;
3249 psrch_inf->srch_entries_start =
3250 (char *) &pSMBr->hdr.Protocol +
3251 le16_to_cpu(pSMBr->t2.DataOffset);
3252 parms = (T2_FFIRST_RSP_PARMS *)((char *) &pSMBr->hdr.Protocol +
3253 le16_to_cpu(pSMBr->t2.ParameterOffset));
3255 if(parms->EndofSearch)
3256 psrch_inf->endOfSearch = TRUE;
3258 psrch_inf->endOfSearch = FALSE;
3260 psrch_inf->entries_in_buffer = le16_to_cpu(parms->SearchCount);
3261 psrch_inf->index_of_last_entry = 2 /* skip . and .. */ +
3262 psrch_inf->entries_in_buffer;
3263 *pnetfid = parms->SearchHandle;
3265 cifs_buf_release(pSMB);
3272 int CIFSFindNext(const int xid, struct cifsTconInfo *tcon,
3273 __u16 searchHandle, struct cifs_search_info * psrch_inf)
3275 TRANSACTION2_FNEXT_REQ *pSMB = NULL;
3276 TRANSACTION2_FNEXT_RSP *pSMBr = NULL;
3277 T2_FNEXT_RSP_PARMS * parms;
3278 char *response_data;
3280 int bytes_returned, name_len;
3281 __u16 params, byte_count;
3283 cFYI(1, ("In FindNext"));
3285 if(psrch_inf->endOfSearch == TRUE)
3288 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3293 params = 14; /* includes 2 bytes of null string, converted to LE below */
3295 pSMB->TotalDataCount = 0; /* no EAs */
3296 pSMB->MaxParameterCount = cpu_to_le16(8);
3297 pSMB->MaxDataCount =
3298 cpu_to_le16((tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
3299 pSMB->MaxSetupCount = 0;
3303 pSMB->Reserved2 = 0;
3304 pSMB->ParameterOffset = cpu_to_le16(
3305 offsetof(struct smb_com_transaction2_fnext_req,SearchHandle) - 4);
3306 pSMB->DataCount = 0;
3307 pSMB->DataOffset = 0;
3308 pSMB->SetupCount = 1;
3309 pSMB->Reserved3 = 0;
3310 pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_NEXT);
3311 pSMB->SearchHandle = searchHandle; /* always kept as le */
3313 cpu_to_le16(CIFSMaxBufSize / sizeof (FILE_UNIX_INFO));
3314 /* test for Unix extensions */
3315 /* if (tcon->ses->capabilities & CAP_UNIX) {
3316 pSMB->InformationLevel = cpu_to_le16(SMB_FIND_FILE_UNIX);
3317 psrch_inf->info_level = SMB_FIND_FILE_UNIX;
3319 pSMB->InformationLevel =
3320 cpu_to_le16(SMB_FIND_FILE_DIRECTORY_INFO);
3321 psrch_inf->info_level = SMB_FIND_FILE_DIRECTORY_INFO;
3323 pSMB->InformationLevel = cpu_to_le16(psrch_inf->info_level);
3324 pSMB->ResumeKey = psrch_inf->resume_key;
3326 cpu_to_le16(CIFS_SEARCH_CLOSE_AT_END | CIFS_SEARCH_RETURN_RESUME);
3328 name_len = psrch_inf->resume_name_len;
3330 if(name_len < PATH_MAX) {
3331 memcpy(pSMB->ResumeFileName, psrch_inf->presume_name, name_len);
3332 byte_count += name_len;
3333 /* 14 byte parm len above enough for 2 byte null terminator */
3334 pSMB->ResumeFileName[name_len] = 0;
3335 pSMB->ResumeFileName[name_len+1] = 0;
3338 goto FNext2_err_exit;
3340 byte_count = params + 1 /* pad */ ;
3341 pSMB->TotalParameterCount = cpu_to_le16(params);
3342 pSMB->ParameterCount = pSMB->TotalParameterCount;
3343 pSMB->hdr.smb_buf_length += byte_count;
3344 pSMB->ByteCount = cpu_to_le16(byte_count);
3346 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3347 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3348 cifs_stats_inc(&tcon->num_fnext);
3351 psrch_inf->endOfSearch = TRUE;
3352 rc = 0; /* search probably was closed at end of search above */
3354 cFYI(1, ("FindNext returned = %d", rc));
3355 } else { /* decode response */
3356 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3359 /* BB fixme add lock for file (srch_info) struct here */
3360 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
3361 psrch_inf->unicode = TRUE;
3363 psrch_inf->unicode = FALSE;
3364 response_data = (char *) &pSMBr->hdr.Protocol +
3365 le16_to_cpu(pSMBr->t2.ParameterOffset);
3366 parms = (T2_FNEXT_RSP_PARMS *)response_data;
3367 response_data = (char *)&pSMBr->hdr.Protocol +
3368 le16_to_cpu(pSMBr->t2.DataOffset);
3369 if(psrch_inf->smallBuf)
3370 cifs_small_buf_release(
3371 psrch_inf->ntwrk_buf_start);
3373 cifs_buf_release(psrch_inf->ntwrk_buf_start);
3374 psrch_inf->srch_entries_start = response_data;
3375 psrch_inf->ntwrk_buf_start = (char *)pSMB;
3376 psrch_inf->smallBuf = 0;
3377 if(parms->EndofSearch)
3378 psrch_inf->endOfSearch = TRUE;
3380 psrch_inf->endOfSearch = FALSE;
3382 psrch_inf->entries_in_buffer = le16_to_cpu(parms->SearchCount);
3383 psrch_inf->index_of_last_entry +=
3384 psrch_inf->entries_in_buffer;
3385 /* cFYI(1,("fnxt2 entries in buf %d index_of_last %d",psrch_inf->entries_in_buffer,psrch_inf->index_of_last_entry)); */
3387 /* BB fixme add unlock here */
3392 /* BB On error, should we leave previous search buf (and count and
3393 last entry fields) intact or free the previous one? */
3395 /* Note: On -EAGAIN error only caller can retry on handle based calls
3396 since file handle passed in no longer valid */
3399 cifs_buf_release(pSMB);
3405 CIFSFindClose(const int xid, struct cifsTconInfo *tcon, const __u16 searchHandle)
3408 FINDCLOSE_REQ *pSMB = NULL;
3409 CLOSE_RSP *pSMBr = NULL; /* BB removeme BB */
3412 cFYI(1, ("In CIFSSMBFindClose"));
3413 rc = small_smb_init(SMB_COM_FIND_CLOSE2, 1, tcon, (void **)&pSMB);
3415 /* no sense returning error if session restarted
3416 as file handle has been closed */
3422 pSMBr = (CLOSE_RSP *)pSMB; /* BB removeme BB */
3423 pSMB->FileID = searchHandle;
3424 pSMB->ByteCount = 0;
3425 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3426 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3428 cERROR(1, ("Send error in FindClose = %d", rc));
3430 cifs_stats_inc(&tcon->num_fclose);
3431 cifs_small_buf_release(pSMB);
3433 /* Since session is dead, search handle closed on server already */
3441 CIFSGetSrvInodeNumber(const int xid, struct cifsTconInfo *tcon,
3442 const unsigned char *searchName,
3443 __u64 * inode_number,
3444 const struct nls_table *nls_codepage, int remap)
3447 TRANSACTION2_QPI_REQ *pSMB = NULL;
3448 TRANSACTION2_QPI_RSP *pSMBr = NULL;
3449 int name_len, bytes_returned;
3450 __u16 params, byte_count;
3452 cFYI(1,("In GetSrvInodeNum for %s",searchName));
3456 GetInodeNumberRetry:
3457 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3463 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3465 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
3466 PATH_MAX,nls_codepage, remap);
3467 name_len++; /* trailing null */
3469 } else { /* BB improve the check for buffer overruns BB */
3470 name_len = strnlen(searchName, PATH_MAX);
3471 name_len++; /* trailing null */
3472 strncpy(pSMB->FileName, searchName, name_len);
3475 params = 2 /* level */ + 4 /* rsrvd */ + name_len /* incl null */ ;
3476 pSMB->TotalDataCount = 0;
3477 pSMB->MaxParameterCount = cpu_to_le16(2);
3478 /* BB find exact max data count below from sess structure BB */
3479 pSMB->MaxDataCount = cpu_to_le16(4000);
3480 pSMB->MaxSetupCount = 0;
3484 pSMB->Reserved2 = 0;
3485 pSMB->ParameterOffset = cpu_to_le16(offsetof(
3486 struct smb_com_transaction2_qpi_req ,InformationLevel) - 4);
3487 pSMB->DataCount = 0;
3488 pSMB->DataOffset = 0;
3489 pSMB->SetupCount = 1;
3490 pSMB->Reserved3 = 0;
3491 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
3492 byte_count = params + 1 /* pad */ ;
3493 pSMB->TotalParameterCount = cpu_to_le16(params);
3494 pSMB->ParameterCount = pSMB->TotalParameterCount;
3495 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_INTERNAL_INFO);
3496 pSMB->Reserved4 = 0;
3497 pSMB->hdr.smb_buf_length += byte_count;
3498 pSMB->ByteCount = cpu_to_le16(byte_count);
3500 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3501 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3503 cFYI(1, ("error %d in QueryInternalInfo", rc));
3505 /* decode response */
3506 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3507 if (rc || (pSMBr->ByteCount < 2))
3508 /* BB also check enough total bytes returned */
3509 /* If rc should we check for EOPNOSUPP and
3510 disable the srvino flag? or in caller? */
3511 rc = -EIO; /* bad smb */
3513 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3514 __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
3515 struct file_internal_info * pfinfo;
3516 /* BB Do we need a cast or hash here ? */
3518 cFYI(1, ("Illegal size ret in QryIntrnlInf"));
3520 goto GetInodeNumOut;
3522 pfinfo = (struct file_internal_info *)
3523 (data_offset + (char *) &pSMBr->hdr.Protocol);
3524 *inode_number = pfinfo->UniqueId;
3528 cifs_buf_release(pSMB);
3530 goto GetInodeNumberRetry;
3535 CIFSGetDFSRefer(const int xid, struct cifsSesInfo *ses,
3536 const unsigned char *searchName,
3537 unsigned char **targetUNCs,
3538 unsigned int *number_of_UNC_in_array,
3539 const struct nls_table *nls_codepage, int remap)
3541 /* TRANS2_GET_DFS_REFERRAL */
3542 TRANSACTION2_GET_DFS_REFER_REQ *pSMB = NULL;
3543 TRANSACTION2_GET_DFS_REFER_RSP *pSMBr = NULL;
3544 struct dfs_referral_level_3 * referrals = NULL;
3550 __u16 params, byte_count;
3551 *number_of_UNC_in_array = 0;
3554 cFYI(1, ("In GetDFSRefer the path %s", searchName));
3558 rc = smb_init(SMB_COM_TRANSACTION2, 15, NULL, (void **) &pSMB,
3563 /* server pointer checked in called function,
3564 but should never be null here anyway */
3565 pSMB->hdr.Mid = GetNextMid(ses->server);
3566 pSMB->hdr.Tid = ses->ipc_tid;
3567 pSMB->hdr.Uid = ses->Suid;
3568 if (ses->capabilities & CAP_STATUS32) {
3569 pSMB->hdr.Flags2 |= SMBFLG2_ERR_STATUS;
3571 if (ses->capabilities & CAP_DFS) {
3572 pSMB->hdr.Flags2 |= SMBFLG2_DFS;
3575 if (ses->capabilities & CAP_UNICODE) {
3576 pSMB->hdr.Flags2 |= SMBFLG2_UNICODE;
3578 cifsConvertToUCS((__le16 *) pSMB->RequestFileName,
3579 searchName, PATH_MAX, nls_codepage, remap);
3580 name_len++; /* trailing null */
3582 } else { /* BB improve the check for buffer overruns BB */
3583 name_len = strnlen(searchName, PATH_MAX);
3584 name_len++; /* trailing null */
3585 strncpy(pSMB->RequestFileName, searchName, name_len);
3588 params = 2 /* level */ + name_len /*includes null */ ;
3589 pSMB->TotalDataCount = 0;
3590 pSMB->DataCount = 0;
3591 pSMB->DataOffset = 0;
3592 pSMB->MaxParameterCount = 0;
3593 pSMB->MaxDataCount = cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
3594 pSMB->MaxSetupCount = 0;
3598 pSMB->Reserved2 = 0;
3599 pSMB->ParameterOffset = cpu_to_le16(offsetof(
3600 struct smb_com_transaction2_get_dfs_refer_req, MaxReferralLevel) - 4);
3601 pSMB->SetupCount = 1;
3602 pSMB->Reserved3 = 0;
3603 pSMB->SubCommand = cpu_to_le16(TRANS2_GET_DFS_REFERRAL);
3604 byte_count = params + 3 /* pad */ ;
3605 pSMB->ParameterCount = cpu_to_le16(params);
3606 pSMB->TotalParameterCount = pSMB->ParameterCount;
3607 pSMB->MaxReferralLevel = cpu_to_le16(3);
3608 pSMB->hdr.smb_buf_length += byte_count;
3609 pSMB->ByteCount = cpu_to_le16(byte_count);
3611 rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB,
3612 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3614 cFYI(1, ("Send error in GetDFSRefer = %d", rc));
3615 } else { /* decode response */
3616 /* BB Add logic to parse referrals here */
3617 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3619 if (rc || (pSMBr->ByteCount < 17)) /* BB also check enough total bytes returned */
3620 rc = -EIO; /* bad smb */
3622 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3623 __u16 data_count = le16_to_cpu(pSMBr->t2.DataCount);
3626 ("Decoding GetDFSRefer response. BCC: %d Offset %d",
3627 pSMBr->ByteCount, data_offset));
3629 (struct dfs_referral_level_3 *)
3630 (8 /* sizeof start of data block */ +
3632 (char *) &pSMBr->hdr.Protocol);
3633 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",
3634 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)));
3635 /* BB This field is actually two bytes in from start of
3636 data block so we could do safety check that DataBlock
3637 begins at address of pSMBr->NumberOfReferrals */
3638 *number_of_UNC_in_array = le16_to_cpu(pSMBr->NumberOfReferrals);
3640 /* BB Fix below so can return more than one referral */
3641 if(*number_of_UNC_in_array > 1)
3642 *number_of_UNC_in_array = 1;
3644 /* get the length of the strings describing refs */
3646 for(i=0;i<*number_of_UNC_in_array;i++) {
3647 /* make sure that DfsPathOffset not past end */
3648 __u16 offset = le16_to_cpu(referrals->DfsPathOffset);
3649 if (offset > data_count) {
3650 /* if invalid referral, stop here and do
3651 not try to copy any more */
3652 *number_of_UNC_in_array = i;
3655 temp = ((char *)referrals) + offset;
3657 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
3658 name_len += UniStrnlen((wchar_t *)temp,data_count);
3660 name_len += strnlen(temp,data_count);
3663 /* BB add check that referral pointer does not fall off end PDU */
3666 /* BB add check for name_len bigger than bcc */
3668 kmalloc(name_len+1+ (*number_of_UNC_in_array),GFP_KERNEL);
3669 if(*targetUNCs == NULL) {
3673 /* copy the ref strings */
3675 (struct dfs_referral_level_3 *)
3676 (8 /* sizeof data hdr */ +
3678 (char *) &pSMBr->hdr.Protocol);
3680 for(i=0;i<*number_of_UNC_in_array;i++) {
3681 temp = ((char *)referrals) + le16_to_cpu(referrals->DfsPathOffset);
3682 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
3683 cifs_strfromUCS_le(*targetUNCs,
3684 (__le16 *) temp, name_len, nls_codepage);
3686 strncpy(*targetUNCs,temp,name_len);
3688 /* BB update target_uncs pointers */
3698 cifs_buf_release(pSMB);
3706 /* Query File System Info such as free space to old servers such as Win 9x */
3708 SMBOldQFSInfo(const int xid, struct cifsTconInfo *tcon, struct kstatfs *FSData)
3710 /* level 0x01 SMB_QUERY_FILE_SYSTEM_INFO */
3711 TRANSACTION2_QFSI_REQ *pSMB = NULL;
3712 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
3713 FILE_SYSTEM_ALLOC_INFO *response_data;
3715 int bytes_returned = 0;
3716 __u16 params, byte_count;
3718 cFYI(1, ("OldQFSInfo"));
3720 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3724 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3729 params = 2; /* level */
3730 pSMB->TotalDataCount = 0;
3731 pSMB->MaxParameterCount = cpu_to_le16(2);
3732 pSMB->MaxDataCount = cpu_to_le16(1000);
3733 pSMB->MaxSetupCount = 0;
3737 pSMB->Reserved2 = 0;
3738 byte_count = params + 1 /* pad */ ;
3739 pSMB->TotalParameterCount = cpu_to_le16(params);
3740 pSMB->ParameterCount = pSMB->TotalParameterCount;
3741 pSMB->ParameterOffset = cpu_to_le16(offsetof(
3742 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
3743 pSMB->DataCount = 0;
3744 pSMB->DataOffset = 0;
3745 pSMB->SetupCount = 1;
3746 pSMB->Reserved3 = 0;
3747 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
3748 pSMB->InformationLevel = cpu_to_le16(SMB_INFO_ALLOCATION);
3749 pSMB->hdr.smb_buf_length += byte_count;
3750 pSMB->ByteCount = cpu_to_le16(byte_count);
3752 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3753 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3755 cFYI(1, ("Send error in QFSInfo = %d", rc));
3756 } else { /* decode response */
3757 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3759 if (rc || (pSMBr->ByteCount < 18))
3760 rc = -EIO; /* bad smb */
3762 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3763 cFYI(1,("qfsinf resp BCC: %d Offset %d",
3764 pSMBr->ByteCount, data_offset));
3767 (FILE_SYSTEM_ALLOC_INFO *)
3768 (((char *) &pSMBr->hdr.Protocol) + data_offset);
3770 le16_to_cpu(response_data->BytesPerSector) *
3771 le32_to_cpu(response_data->
3772 SectorsPerAllocationUnit);
3774 le32_to_cpu(response_data->TotalAllocationUnits);
3775 FSData->f_bfree = FSData->f_bavail =
3776 le32_to_cpu(response_data->FreeAllocationUnits);
3778 ("Blocks: %lld Free: %lld Block size %ld",
3779 (unsigned long long)FSData->f_blocks,
3780 (unsigned long long)FSData->f_bfree,
3784 cifs_buf_release(pSMB);
3787 goto oldQFSInfoRetry;
3793 CIFSSMBQFSInfo(const int xid, struct cifsTconInfo *tcon, struct kstatfs *FSData)
3795 /* level 0x103 SMB_QUERY_FILE_SYSTEM_INFO */
3796 TRANSACTION2_QFSI_REQ *pSMB = NULL;
3797 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
3798 FILE_SYSTEM_INFO *response_data;
3800 int bytes_returned = 0;
3801 __u16 params, byte_count;
3803 cFYI(1, ("In QFSInfo"));
3805 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3810 params = 2; /* level */
3811 pSMB->TotalDataCount = 0;
3812 pSMB->MaxParameterCount = cpu_to_le16(2);
3813 pSMB->MaxDataCount = cpu_to_le16(1000);
3814 pSMB->MaxSetupCount = 0;
3818 pSMB->Reserved2 = 0;
3819 byte_count = params + 1 /* pad */ ;
3820 pSMB->TotalParameterCount = cpu_to_le16(params);
3821 pSMB->ParameterCount = pSMB->TotalParameterCount;
3822 pSMB->ParameterOffset = cpu_to_le16(offsetof(
3823 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
3824 pSMB->DataCount = 0;
3825 pSMB->DataOffset = 0;
3826 pSMB->SetupCount = 1;
3827 pSMB->Reserved3 = 0;
3828 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
3829 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_SIZE_INFO);
3830 pSMB->hdr.smb_buf_length += byte_count;
3831 pSMB->ByteCount = cpu_to_le16(byte_count);
3833 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3834 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3836 cFYI(1, ("Send error in QFSInfo = %d", rc));
3837 } else { /* decode response */
3838 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3840 if (rc || (pSMBr->ByteCount < 24))
3841 rc = -EIO; /* bad smb */
3843 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3847 *) (((char *) &pSMBr->hdr.Protocol) +
3850 le32_to_cpu(response_data->BytesPerSector) *
3851 le32_to_cpu(response_data->
3852 SectorsPerAllocationUnit);
3854 le64_to_cpu(response_data->TotalAllocationUnits);
3855 FSData->f_bfree = FSData->f_bavail =
3856 le64_to_cpu(response_data->FreeAllocationUnits);
3858 ("Blocks: %lld Free: %lld Block size %ld",
3859 (unsigned long long)FSData->f_blocks,
3860 (unsigned long long)FSData->f_bfree,
3864 cifs_buf_release(pSMB);
3873 CIFSSMBQFSAttributeInfo(const int xid, struct cifsTconInfo *tcon)
3875 /* level 0x105 SMB_QUERY_FILE_SYSTEM_INFO */
3876 TRANSACTION2_QFSI_REQ *pSMB = NULL;
3877 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
3878 FILE_SYSTEM_ATTRIBUTE_INFO *response_data;
3880 int bytes_returned = 0;
3881 __u16 params, byte_count;
3883 cFYI(1, ("In QFSAttributeInfo"));
3885 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3890 params = 2; /* level */
3891 pSMB->TotalDataCount = 0;
3892 pSMB->MaxParameterCount = cpu_to_le16(2);
3893 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
3894 pSMB->MaxSetupCount = 0;
3898 pSMB->Reserved2 = 0;
3899 byte_count = params + 1 /* pad */ ;
3900 pSMB->TotalParameterCount = cpu_to_le16(params);
3901 pSMB->ParameterCount = pSMB->TotalParameterCount;
3902 pSMB->ParameterOffset = cpu_to_le16(offsetof(
3903 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
3904 pSMB->DataCount = 0;
3905 pSMB->DataOffset = 0;
3906 pSMB->SetupCount = 1;
3907 pSMB->Reserved3 = 0;
3908 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
3909 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_ATTRIBUTE_INFO);
3910 pSMB->hdr.smb_buf_length += byte_count;
3911 pSMB->ByteCount = cpu_to_le16(byte_count);
3913 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3914 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3916 cERROR(1, ("Send error in QFSAttributeInfo = %d", rc));
3917 } else { /* decode response */
3918 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3920 if (rc || (pSMBr->ByteCount < 13)) { /* BB also check enough bytes returned */
3921 rc = -EIO; /* bad smb */
3923 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3925 (FILE_SYSTEM_ATTRIBUTE_INFO
3926 *) (((char *) &pSMBr->hdr.Protocol) +
3928 memcpy(&tcon->fsAttrInfo, response_data,
3929 sizeof (FILE_SYSTEM_ATTRIBUTE_INFO));
3932 cifs_buf_release(pSMB);
3935 goto QFSAttributeRetry;
3941 CIFSSMBQFSDeviceInfo(const int xid, struct cifsTconInfo *tcon)
3943 /* level 0x104 SMB_QUERY_FILE_SYSTEM_INFO */
3944 TRANSACTION2_QFSI_REQ *pSMB = NULL;
3945 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
3946 FILE_SYSTEM_DEVICE_INFO *response_data;
3948 int bytes_returned = 0;
3949 __u16 params, byte_count;
3951 cFYI(1, ("In QFSDeviceInfo"));
3953 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3958 params = 2; /* level */
3959 pSMB->TotalDataCount = 0;
3960 pSMB->MaxParameterCount = cpu_to_le16(2);
3961 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
3962 pSMB->MaxSetupCount = 0;
3966 pSMB->Reserved2 = 0;
3967 byte_count = params + 1 /* pad */ ;
3968 pSMB->TotalParameterCount = cpu_to_le16(params);
3969 pSMB->ParameterCount = pSMB->TotalParameterCount;
3970 pSMB->ParameterOffset = cpu_to_le16(offsetof(
3971 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
3973 pSMB->DataCount = 0;
3974 pSMB->DataOffset = 0;
3975 pSMB->SetupCount = 1;
3976 pSMB->Reserved3 = 0;
3977 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
3978 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_DEVICE_INFO);
3979 pSMB->hdr.smb_buf_length += byte_count;
3980 pSMB->ByteCount = cpu_to_le16(byte_count);
3982 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3983 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3985 cFYI(1, ("Send error in QFSDeviceInfo = %d", rc));
3986 } else { /* decode response */
3987 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3989 if (rc || (pSMBr->ByteCount < sizeof (FILE_SYSTEM_DEVICE_INFO)))
3990 rc = -EIO; /* bad smb */
3992 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3994 (FILE_SYSTEM_DEVICE_INFO *)
3995 (((char *) &pSMBr->hdr.Protocol) +
3997 memcpy(&tcon->fsDevInfo, response_data,
3998 sizeof (FILE_SYSTEM_DEVICE_INFO));
4001 cifs_buf_release(pSMB);
4004 goto QFSDeviceRetry;
4010 CIFSSMBQFSUnixInfo(const int xid, struct cifsTconInfo *tcon)
4012 /* level 0x200 SMB_QUERY_CIFS_UNIX_INFO */
4013 TRANSACTION2_QFSI_REQ *pSMB = NULL;
4014 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4015 FILE_SYSTEM_UNIX_INFO *response_data;
4017 int bytes_returned = 0;
4018 __u16 params, byte_count;
4020 cFYI(1, ("In QFSUnixInfo"));
4022 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4027 params = 2; /* level */
4028 pSMB->TotalDataCount = 0;
4029 pSMB->DataCount = 0;
4030 pSMB->DataOffset = 0;
4031 pSMB->MaxParameterCount = cpu_to_le16(2);
4032 pSMB->MaxDataCount = cpu_to_le16(100); /* BB find exact max SMB PDU from sess structure BB */
4033 pSMB->MaxSetupCount = 0;
4037 pSMB->Reserved2 = 0;
4038 byte_count = params + 1 /* pad */ ;
4039 pSMB->ParameterCount = cpu_to_le16(params);
4040 pSMB->TotalParameterCount = pSMB->ParameterCount;
4041 pSMB->ParameterOffset = cpu_to_le16(offsetof(struct
4042 smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4043 pSMB->SetupCount = 1;
4044 pSMB->Reserved3 = 0;
4045 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4046 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_CIFS_UNIX_INFO);
4047 pSMB->hdr.smb_buf_length += byte_count;
4048 pSMB->ByteCount = cpu_to_le16(byte_count);
4050 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4051 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4053 cERROR(1, ("Send error in QFSUnixInfo = %d", rc));
4054 } else { /* decode response */
4055 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4057 if (rc || (pSMBr->ByteCount < 13)) {
4058 rc = -EIO; /* bad smb */
4060 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4062 (FILE_SYSTEM_UNIX_INFO
4063 *) (((char *) &pSMBr->hdr.Protocol) +
4065 memcpy(&tcon->fsUnixInfo, response_data,
4066 sizeof (FILE_SYSTEM_UNIX_INFO));
4069 cifs_buf_release(pSMB);
4079 CIFSSMBSetFSUnixInfo(const int xid, struct cifsTconInfo *tcon, __u64 cap)
4081 /* level 0x200 SMB_SET_CIFS_UNIX_INFO */
4082 TRANSACTION2_SETFSI_REQ *pSMB = NULL;
4083 TRANSACTION2_SETFSI_RSP *pSMBr = NULL;
4085 int bytes_returned = 0;
4086 __u16 params, param_offset, offset, byte_count;
4088 cFYI(1, ("In SETFSUnixInfo"));
4090 /* BB switch to small buf init to save memory */
4091 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4096 params = 4; /* 2 bytes zero followed by info level. */
4097 pSMB->MaxSetupCount = 0;
4101 pSMB->Reserved2 = 0;
4102 param_offset = offsetof(struct smb_com_transaction2_setfsi_req, FileNum) - 4;
4103 offset = param_offset + params;
4105 pSMB->MaxParameterCount = cpu_to_le16(4);
4106 pSMB->MaxDataCount = cpu_to_le16(100); /* BB find exact max SMB PDU from sess structure BB */
4107 pSMB->SetupCount = 1;
4108 pSMB->Reserved3 = 0;
4109 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FS_INFORMATION);
4110 byte_count = 1 /* pad */ + params + 12;
4112 pSMB->DataCount = cpu_to_le16(12);
4113 pSMB->ParameterCount = cpu_to_le16(params);
4114 pSMB->TotalDataCount = pSMB->DataCount;
4115 pSMB->TotalParameterCount = pSMB->ParameterCount;
4116 pSMB->ParameterOffset = cpu_to_le16(param_offset);
4117 pSMB->DataOffset = cpu_to_le16(offset);
4121 pSMB->InformationLevel = cpu_to_le16(SMB_SET_CIFS_UNIX_INFO);
4124 pSMB->ClientUnixMajor = cpu_to_le16(CIFS_UNIX_MAJOR_VERSION);
4125 pSMB->ClientUnixMinor = cpu_to_le16(CIFS_UNIX_MINOR_VERSION);
4126 pSMB->ClientUnixCap = cpu_to_le64(cap);
4128 pSMB->hdr.smb_buf_length += byte_count;
4129 pSMB->ByteCount = cpu_to_le16(byte_count);
4131 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4132 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4134 cERROR(1, ("Send error in SETFSUnixInfo = %d", rc));
4135 } else { /* decode response */
4136 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4138 rc = -EIO; /* bad smb */
4141 cifs_buf_release(pSMB);
4144 goto SETFSUnixRetry;
4152 CIFSSMBQFSPosixInfo(const int xid, struct cifsTconInfo *tcon,
4153 struct kstatfs *FSData)
4155 /* level 0x201 SMB_QUERY_CIFS_POSIX_INFO */
4156 TRANSACTION2_QFSI_REQ *pSMB = NULL;
4157 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4158 FILE_SYSTEM_POSIX_INFO *response_data;
4160 int bytes_returned = 0;
4161 __u16 params, byte_count;
4163 cFYI(1, ("In QFSPosixInfo"));
4165 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4170 params = 2; /* level */
4171 pSMB->TotalDataCount = 0;
4172 pSMB->DataCount = 0;
4173 pSMB->DataOffset = 0;
4174 pSMB->MaxParameterCount = cpu_to_le16(2);
4175 pSMB->MaxDataCount = cpu_to_le16(100); /* BB find exact max SMB PDU from sess structure BB */
4176 pSMB->MaxSetupCount = 0;
4180 pSMB->Reserved2 = 0;
4181 byte_count = params + 1 /* pad */ ;
4182 pSMB->ParameterCount = cpu_to_le16(params);
4183 pSMB->TotalParameterCount = pSMB->ParameterCount;
4184 pSMB->ParameterOffset = cpu_to_le16(offsetof(struct
4185 smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4186 pSMB->SetupCount = 1;
4187 pSMB->Reserved3 = 0;
4188 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4189 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_POSIX_FS_INFO);
4190 pSMB->hdr.smb_buf_length += byte_count;
4191 pSMB->ByteCount = cpu_to_le16(byte_count);
4193 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4194 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4196 cFYI(1, ("Send error in QFSUnixInfo = %d", rc));
4197 } else { /* decode response */
4198 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4200 if (rc || (pSMBr->ByteCount < 13)) {
4201 rc = -EIO; /* bad smb */
4203 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4205 (FILE_SYSTEM_POSIX_INFO
4206 *) (((char *) &pSMBr->hdr.Protocol) +
4209 le32_to_cpu(response_data->BlockSize);
4211 le64_to_cpu(response_data->TotalBlocks);
4213 le64_to_cpu(response_data->BlocksAvail);
4214 if(response_data->UserBlocksAvail == cpu_to_le64(-1)) {
4215 FSData->f_bavail = FSData->f_bfree;
4218 le64_to_cpu(response_data->UserBlocksAvail);
4220 if(response_data->TotalFileNodes != cpu_to_le64(-1))
4222 le64_to_cpu(response_data->TotalFileNodes);
4223 if(response_data->FreeFileNodes != cpu_to_le64(-1))
4225 le64_to_cpu(response_data->FreeFileNodes);
4228 cifs_buf_release(pSMB);
4237 /* We can not use write of zero bytes trick to
4238 set file size due to need for large file support. Also note that
4239 this SetPathInfo is preferred to SetFileInfo based method in next
4240 routine which is only needed to work around a sharing violation bug
4241 in Samba which this routine can run into */
4244 CIFSSMBSetEOF(const int xid, struct cifsTconInfo *tcon, const char *fileName,
4245 __u64 size, int SetAllocation,
4246 const struct nls_table *nls_codepage, int remap)
4248 struct smb_com_transaction2_spi_req *pSMB = NULL;
4249 struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
4250 struct file_end_of_file_info *parm_data;
4253 int bytes_returned = 0;
4254 __u16 params, byte_count, data_count, param_offset, offset;
4256 cFYI(1, ("In SetEOF"));
4258 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4263 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4265 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
4266 PATH_MAX, nls_codepage, remap);
4267 name_len++; /* trailing null */
4269 } else { /* BB improve the check for buffer overruns BB */
4270 name_len = strnlen(fileName, PATH_MAX);
4271 name_len++; /* trailing null */
4272 strncpy(pSMB->FileName, fileName, name_len);
4274 params = 6 + name_len;
4275 data_count = sizeof (struct file_end_of_file_info);
4276 pSMB->MaxParameterCount = cpu_to_le16(2);
4277 pSMB->MaxDataCount = cpu_to_le16(4100);
4278 pSMB->MaxSetupCount = 0;
4282 pSMB->Reserved2 = 0;
4283 param_offset = offsetof(struct smb_com_transaction2_spi_req,
4284 InformationLevel) - 4;
4285 offset = param_offset + params;
4287 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
4288 pSMB->InformationLevel =
4289 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2);
4291 pSMB->InformationLevel =
4292 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO);
4293 } else /* Set File Size */ {
4294 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
4295 pSMB->InformationLevel =
4296 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO2);
4298 pSMB->InformationLevel =
4299 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO);
4303 (struct file_end_of_file_info *) (((char *) &pSMB->hdr.Protocol) +
4305 pSMB->ParameterOffset = cpu_to_le16(param_offset);
4306 pSMB->DataOffset = cpu_to_le16(offset);
4307 pSMB->SetupCount = 1;
4308 pSMB->Reserved3 = 0;
4309 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
4310 byte_count = 3 /* pad */ + params + data_count;
4311 pSMB->DataCount = cpu_to_le16(data_count);
4312 pSMB->TotalDataCount = pSMB->DataCount;
4313 pSMB->ParameterCount = cpu_to_le16(params);
4314 pSMB->TotalParameterCount = pSMB->ParameterCount;
4315 pSMB->Reserved4 = 0;
4316 pSMB->hdr.smb_buf_length += byte_count;
4317 parm_data->FileSize = cpu_to_le64(size);
4318 pSMB->ByteCount = cpu_to_le16(byte_count);
4319 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4320 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4322 cFYI(1, ("SetPathInfo (file size) returned %d", rc));
4325 cifs_buf_release(pSMB);
4334 CIFSSMBSetFileSize(const int xid, struct cifsTconInfo *tcon, __u64 size,
4335 __u16 fid, __u32 pid_of_opener, int SetAllocation)
4337 struct smb_com_transaction2_sfi_req *pSMB = NULL;
4338 struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
4340 struct file_end_of_file_info *parm_data;
4342 int bytes_returned = 0;
4343 __u16 params, param_offset, offset, byte_count, count;
4345 cFYI(1, ("SetFileSize (via SetFileInfo) %lld",
4347 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
4352 pSMBr = (struct smb_com_transaction2_sfi_rsp *)pSMB;
4354 pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
4355 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));
4358 pSMB->MaxSetupCount = 0;
4362 pSMB->Reserved2 = 0;
4363 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
4364 offset = param_offset + params;
4366 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
4368 count = sizeof(struct file_end_of_file_info);
4369 pSMB->MaxParameterCount = cpu_to_le16(2);
4370 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB PDU from sess */
4371 pSMB->SetupCount = 1;
4372 pSMB->Reserved3 = 0;
4373 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
4374 byte_count = 3 /* pad */ + params + count;
4375 pSMB->DataCount = cpu_to_le16(count);
4376 pSMB->ParameterCount = cpu_to_le16(params);
4377 pSMB->TotalDataCount = pSMB->DataCount;
4378 pSMB->TotalParameterCount = pSMB->ParameterCount;
4379 pSMB->ParameterOffset = cpu_to_le16(param_offset);
4381 (struct file_end_of_file_info *) (((char *) &pSMB->hdr.Protocol) +
4383 pSMB->DataOffset = cpu_to_le16(offset);
4384 parm_data->FileSize = cpu_to_le64(size);
4387 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
4388 pSMB->InformationLevel =
4389 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2);
4391 pSMB->InformationLevel =
4392 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO);
4393 } else /* Set File Size */ {
4394 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
4395 pSMB->InformationLevel =
4396 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO2);
4398 pSMB->InformationLevel =
4399 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO);
4401 pSMB->Reserved4 = 0;
4402 pSMB->hdr.smb_buf_length += byte_count;
4403 pSMB->ByteCount = cpu_to_le16(byte_count);
4404 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4405 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4408 ("Send error in SetFileInfo (SetFileSize) = %d",
4413 cifs_small_buf_release(pSMB);
4415 /* Note: On -EAGAIN error only caller can retry on handle based calls
4416 since file handle passed in no longer valid */
4421 /* Some legacy servers such as NT4 require that the file times be set on
4422 an open handle, rather than by pathname - this is awkward due to
4423 potential access conflicts on the open, but it is unavoidable for these
4424 old servers since the only other choice is to go from 100 nanosecond DCE
4425 time and resort to the original setpathinfo level which takes the ancient
4426 DOS time format with 2 second granularity */
4428 CIFSSMBSetFileTimes(const int xid, struct cifsTconInfo *tcon, const FILE_BASIC_INFO * data,
4431 struct smb_com_transaction2_sfi_req *pSMB = NULL;
4432 struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
4435 int bytes_returned = 0;
4436 __u16 params, param_offset, offset, byte_count, count;
4438 cFYI(1, ("Set Times (via SetFileInfo)"));
4439 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
4444 pSMBr = (struct smb_com_transaction2_sfi_rsp *)pSMB;
4446 /* At this point there is no need to override the current pid
4447 with the pid of the opener, but that could change if we someday
4448 use an existing handle (rather than opening one on the fly) */
4449 /* pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
4450 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));*/
4453 pSMB->MaxSetupCount = 0;
4457 pSMB->Reserved2 = 0;
4458 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
4459 offset = param_offset + params;
4461 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
4463 count = sizeof (FILE_BASIC_INFO);
4464 pSMB->MaxParameterCount = cpu_to_le16(2);
4465 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB PDU from sess */
4466 pSMB->SetupCount = 1;
4467 pSMB->Reserved3 = 0;
4468 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
4469 byte_count = 3 /* pad */ + params + count;
4470 pSMB->DataCount = cpu_to_le16(count);
4471 pSMB->ParameterCount = cpu_to_le16(params);
4472 pSMB->TotalDataCount = pSMB->DataCount;
4473 pSMB->TotalParameterCount = pSMB->ParameterCount;
4474 pSMB->ParameterOffset = cpu_to_le16(param_offset);
4475 pSMB->DataOffset = cpu_to_le16(offset);
4477 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
4478 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO2);
4480 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO);
4481 pSMB->Reserved4 = 0;
4482 pSMB->hdr.smb_buf_length += byte_count;
4483 pSMB->ByteCount = cpu_to_le16(byte_count);
4484 memcpy(data_offset,data,sizeof(FILE_BASIC_INFO));
4485 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4486 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4488 cFYI(1,("Send error in Set Time (SetFileInfo) = %d",rc));
4491 cifs_small_buf_release(pSMB);
4493 /* Note: On -EAGAIN error only caller can retry on handle based calls
4494 since file handle passed in no longer valid */
4501 CIFSSMBSetTimes(const int xid, struct cifsTconInfo *tcon, const char *fileName,
4502 const FILE_BASIC_INFO * data,
4503 const struct nls_table *nls_codepage, int remap)
4505 TRANSACTION2_SPI_REQ *pSMB = NULL;
4506 TRANSACTION2_SPI_RSP *pSMBr = NULL;
4509 int bytes_returned = 0;
4511 __u16 params, param_offset, offset, byte_count, count;
4513 cFYI(1, ("In SetTimes"));
4516 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4521 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4523 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
4524 PATH_MAX, nls_codepage, remap);
4525 name_len++; /* trailing null */
4527 } else { /* BB improve the check for buffer overruns BB */
4528 name_len = strnlen(fileName, PATH_MAX);
4529 name_len++; /* trailing null */
4530 strncpy(pSMB->FileName, fileName, name_len);
4533 params = 6 + name_len;
4534 count = sizeof (FILE_BASIC_INFO);
4535 pSMB->MaxParameterCount = cpu_to_le16(2);
4536 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
4537 pSMB->MaxSetupCount = 0;
4541 pSMB->Reserved2 = 0;
4542 param_offset = offsetof(struct smb_com_transaction2_spi_req,
4543 InformationLevel) - 4;
4544 offset = param_offset + params;
4545 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
4546 pSMB->ParameterOffset = cpu_to_le16(param_offset);
4547 pSMB->DataOffset = cpu_to_le16(offset);
4548 pSMB->SetupCount = 1;
4549 pSMB->Reserved3 = 0;
4550 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
4551 byte_count = 3 /* pad */ + params + count;
4553 pSMB->DataCount = cpu_to_le16(count);
4554 pSMB->ParameterCount = cpu_to_le16(params);
4555 pSMB->TotalDataCount = pSMB->DataCount;
4556 pSMB->TotalParameterCount = pSMB->ParameterCount;
4557 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
4558 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO2);
4560 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO);
4561 pSMB->Reserved4 = 0;
4562 pSMB->hdr.smb_buf_length += byte_count;
4563 memcpy(data_offset, data, sizeof (FILE_BASIC_INFO));
4564 pSMB->ByteCount = cpu_to_le16(byte_count);
4565 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4566 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4568 cFYI(1, ("SetPathInfo (times) returned %d", rc));
4571 cifs_buf_release(pSMB);
4579 /* Can not be used to set time stamps yet (due to old DOS time format) */
4580 /* Can be used to set attributes */
4581 #if 0 /* Possibly not needed - since it turns out that strangely NT4 has a bug
4582 handling it anyway and NT4 was what we thought it would be needed for
4583 Do not delete it until we prove whether needed for Win9x though */
4585 CIFSSMBSetAttrLegacy(int xid, struct cifsTconInfo *tcon, char *fileName,
4586 __u16 dos_attrs, const struct nls_table *nls_codepage)
4588 SETATTR_REQ *pSMB = NULL;
4589 SETATTR_RSP *pSMBr = NULL;
4594 cFYI(1, ("In SetAttrLegacy"));
4597 rc = smb_init(SMB_COM_SETATTR, 8, tcon, (void **) &pSMB,
4602 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4604 ConvertToUCS((__le16 *) pSMB->fileName, fileName,
4605 PATH_MAX, nls_codepage);
4606 name_len++; /* trailing null */
4608 } else { /* BB improve the check for buffer overruns BB */
4609 name_len = strnlen(fileName, PATH_MAX);
4610 name_len++; /* trailing null */
4611 strncpy(pSMB->fileName, fileName, name_len);
4613 pSMB->attr = cpu_to_le16(dos_attrs);
4614 pSMB->BufferFormat = 0x04;
4615 pSMB->hdr.smb_buf_length += name_len + 1;
4616 pSMB->ByteCount = cpu_to_le16(name_len + 1);
4617 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4618 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4620 cFYI(1, ("Error in LegacySetAttr = %d", rc));
4623 cifs_buf_release(pSMB);
4626 goto SetAttrLgcyRetry;
4630 #endif /* temporarily unneeded SetAttr legacy function */
4633 CIFSSMBUnixSetPerms(const int xid, struct cifsTconInfo *tcon,
4634 char *fileName, __u64 mode, __u64 uid, __u64 gid,
4635 dev_t device, const struct nls_table *nls_codepage,
4638 TRANSACTION2_SPI_REQ *pSMB = NULL;
4639 TRANSACTION2_SPI_RSP *pSMBr = NULL;
4642 int bytes_returned = 0;
4643 FILE_UNIX_BASIC_INFO *data_offset;
4644 __u16 params, param_offset, offset, count, byte_count;
4646 cFYI(1, ("In SetUID/GID/Mode"));
4648 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4653 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4655 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
4656 PATH_MAX, nls_codepage, remap);
4657 name_len++; /* trailing null */
4659 } else { /* BB improve the check for buffer overruns BB */
4660 name_len = strnlen(fileName, PATH_MAX);
4661 name_len++; /* trailing null */
4662 strncpy(pSMB->FileName, fileName, name_len);
4665 params = 6 + name_len;
4666 count = sizeof (FILE_UNIX_BASIC_INFO);
4667 pSMB->MaxParameterCount = cpu_to_le16(2);
4668 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
4669 pSMB->MaxSetupCount = 0;
4673 pSMB->Reserved2 = 0;
4674 param_offset = offsetof(struct smb_com_transaction2_spi_req,
4675 InformationLevel) - 4;
4676 offset = param_offset + params;
4678 (FILE_UNIX_BASIC_INFO *) ((char *) &pSMB->hdr.Protocol +
4680 memset(data_offset, 0, count);
4681 pSMB->DataOffset = cpu_to_le16(offset);
4682 pSMB->ParameterOffset = cpu_to_le16(param_offset);
4683 pSMB->SetupCount = 1;
4684 pSMB->Reserved3 = 0;
4685 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
4686 byte_count = 3 /* pad */ + params + count;
4687 pSMB->ParameterCount = cpu_to_le16(params);
4688 pSMB->DataCount = cpu_to_le16(count);
4689 pSMB->TotalParameterCount = pSMB->ParameterCount;
4690 pSMB->TotalDataCount = pSMB->DataCount;
4691 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_BASIC);
4692 pSMB->Reserved4 = 0;
4693 pSMB->hdr.smb_buf_length += byte_count;
4694 data_offset->Uid = cpu_to_le64(uid);
4695 data_offset->Gid = cpu_to_le64(gid);
4696 /* better to leave device as zero when it is */
4697 data_offset->DevMajor = cpu_to_le64(MAJOR(device));
4698 data_offset->DevMinor = cpu_to_le64(MINOR(device));
4699 data_offset->Permissions = cpu_to_le64(mode);
4702 data_offset->Type = cpu_to_le32(UNIX_FILE);
4703 else if(S_ISDIR(mode))
4704 data_offset->Type = cpu_to_le32(UNIX_DIR);
4705 else if(S_ISLNK(mode))
4706 data_offset->Type = cpu_to_le32(UNIX_SYMLINK);
4707 else if(S_ISCHR(mode))
4708 data_offset->Type = cpu_to_le32(UNIX_CHARDEV);
4709 else if(S_ISBLK(mode))
4710 data_offset->Type = cpu_to_le32(UNIX_BLOCKDEV);
4711 else if(S_ISFIFO(mode))
4712 data_offset->Type = cpu_to_le32(UNIX_FIFO);
4713 else if(S_ISSOCK(mode))
4714 data_offset->Type = cpu_to_le32(UNIX_SOCKET);
4717 pSMB->ByteCount = cpu_to_le16(byte_count);
4718 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4719 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4721 cFYI(1, ("SetPathInfo (perms) returned %d", rc));
4725 cifs_buf_release(pSMB);
4731 int CIFSSMBNotify(const int xid, struct cifsTconInfo *tcon,
4732 const int notify_subdirs, const __u16 netfid,
4733 __u32 filter, struct file * pfile, int multishot,
4734 const struct nls_table *nls_codepage)
4737 struct smb_com_transaction_change_notify_req * pSMB = NULL;
4738 struct smb_com_ntransaction_change_notify_rsp * pSMBr = NULL;
4739 struct dir_notify_req *dnotify_req;
4742 cFYI(1, ("In CIFSSMBNotify for file handle %d",(int)netfid));
4743 rc = smb_init(SMB_COM_NT_TRANSACT, 23, tcon, (void **) &pSMB,
4748 pSMB->TotalParameterCount = 0 ;
4749 pSMB->TotalDataCount = 0;
4750 pSMB->MaxParameterCount = cpu_to_le32(2);
4751 /* BB find exact data count max from sess structure BB */
4752 pSMB->MaxDataCount = 0; /* same in little endian or be */
4753 /* BB VERIFY verify which is correct for above BB */
4754 pSMB->MaxDataCount = cpu_to_le32((tcon->ses->server->maxBuf -
4755 MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
4757 pSMB->MaxSetupCount = 4;
4759 pSMB->ParameterOffset = 0;
4760 pSMB->DataCount = 0;
4761 pSMB->DataOffset = 0;
4762 pSMB->SetupCount = 4; /* single byte does not need le conversion */
4763 pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_NOTIFY_CHANGE);
4764 pSMB->ParameterCount = pSMB->TotalParameterCount;
4766 pSMB->WatchTree = 1; /* one byte - no le conversion needed */
4767 pSMB->Reserved2 = 0;
4768 pSMB->CompletionFilter = cpu_to_le32(filter);
4769 pSMB->Fid = netfid; /* file handle always le */
4770 pSMB->ByteCount = 0;
4772 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4773 (struct smb_hdr *) pSMBr, &bytes_returned, -1);
4775 cFYI(1, ("Error in Notify = %d", rc));
4777 /* Add file to outstanding requests */
4778 /* BB change to kmem cache alloc */
4779 dnotify_req = (struct dir_notify_req *) kmalloc(
4780 sizeof(struct dir_notify_req),
4783 dnotify_req->Pid = pSMB->hdr.Pid;
4784 dnotify_req->PidHigh = pSMB->hdr.PidHigh;
4785 dnotify_req->Mid = pSMB->hdr.Mid;
4786 dnotify_req->Tid = pSMB->hdr.Tid;
4787 dnotify_req->Uid = pSMB->hdr.Uid;
4788 dnotify_req->netfid = netfid;
4789 dnotify_req->pfile = pfile;
4790 dnotify_req->filter = filter;
4791 dnotify_req->multishot = multishot;
4792 spin_lock(&GlobalMid_Lock);
4793 list_add_tail(&dnotify_req->lhead,
4794 &GlobalDnotifyReqList);
4795 spin_unlock(&GlobalMid_Lock);
4799 cifs_buf_release(pSMB);
4802 #ifdef CONFIG_CIFS_XATTR
4804 CIFSSMBQAllEAs(const int xid, struct cifsTconInfo *tcon,
4805 const unsigned char *searchName,
4806 char * EAData, size_t buf_size,
4807 const struct nls_table *nls_codepage, int remap)
4809 /* BB assumes one setup word */
4810 TRANSACTION2_QPI_REQ *pSMB = NULL;
4811 TRANSACTION2_QPI_RSP *pSMBr = NULL;
4815 struct fea * temp_fea;
4817 __u16 params, byte_count;
4819 cFYI(1, ("In Query All EAs path %s", searchName));
4821 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4826 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4828 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
4829 PATH_MAX, nls_codepage, remap);
4830 name_len++; /* trailing null */
4832 } else { /* BB improve the check for buffer overruns BB */
4833 name_len = strnlen(searchName, PATH_MAX);
4834 name_len++; /* trailing null */
4835 strncpy(pSMB->FileName, searchName, name_len);
4838 params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */ ;
4839 pSMB->TotalDataCount = 0;
4840 pSMB->MaxParameterCount = cpu_to_le16(2);
4841 pSMB->MaxDataCount = cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
4842 pSMB->MaxSetupCount = 0;
4846 pSMB->Reserved2 = 0;
4847 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4848 struct smb_com_transaction2_qpi_req ,InformationLevel) - 4);
4849 pSMB->DataCount = 0;
4850 pSMB->DataOffset = 0;
4851 pSMB->SetupCount = 1;
4852 pSMB->Reserved3 = 0;
4853 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
4854 byte_count = params + 1 /* pad */ ;
4855 pSMB->TotalParameterCount = cpu_to_le16(params);
4856 pSMB->ParameterCount = pSMB->TotalParameterCount;
4857 pSMB->InformationLevel = cpu_to_le16(SMB_INFO_QUERY_ALL_EAS);
4858 pSMB->Reserved4 = 0;
4859 pSMB->hdr.smb_buf_length += byte_count;
4860 pSMB->ByteCount = cpu_to_le16(byte_count);
4862 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4863 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4865 cFYI(1, ("Send error in QueryAllEAs = %d", rc));
4866 } else { /* decode response */
4867 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4869 /* BB also check enough total bytes returned */
4870 /* BB we need to improve the validity checking
4871 of these trans2 responses */
4872 if (rc || (pSMBr->ByteCount < 4))
4873 rc = -EIO; /* bad smb */
4874 /* else if (pFindData){
4875 memcpy((char *) pFindData,
4876 (char *) &pSMBr->hdr.Protocol +
4879 /* check that length of list is not more than bcc */
4880 /* check that each entry does not go beyond length
4882 /* check that each element of each entry does not
4883 go beyond end of list */
4884 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4885 struct fealist * ea_response_data;
4887 /* validate_trans2_offsets() */
4888 /* BB to check if(start of smb + data_offset > &bcc+ bcc)*/
4889 ea_response_data = (struct fealist *)
4890 (((char *) &pSMBr->hdr.Protocol) +
4892 name_len = le32_to_cpu(ea_response_data->list_len);
4893 cFYI(1,("ea length %d", name_len));
4895 /* returned EA size zeroed at top of function */
4896 cFYI(1,("empty EA list returned from server"));
4898 /* account for ea list len */
4900 temp_fea = ea_response_data->list;
4901 temp_ptr = (char *)temp_fea;
4902 while(name_len > 0) {
4906 rc += temp_fea->name_len;
4907 /* account for prefix user. and trailing null */
4909 if(rc<(int)buf_size) {
4910 memcpy(EAData,"user.",5);
4912 memcpy(EAData,temp_ptr,temp_fea->name_len);
4913 EAData+=temp_fea->name_len;
4914 /* null terminate name */
4916 EAData = EAData + 1;
4917 } else if(buf_size == 0) {
4918 /* skip copy - calc size only */
4920 /* stop before overrun buffer */
4924 name_len -= temp_fea->name_len;
4925 temp_ptr += temp_fea->name_len;
4926 /* account for trailing null */
4929 value_len = le16_to_cpu(temp_fea->value_len);
4930 name_len -= value_len;
4931 temp_ptr += value_len;
4932 /* BB check that temp_ptr is still within smb BB*/
4933 /* no trailing null to account for in value len */
4934 /* go on to next EA */
4935 temp_fea = (struct fea *)temp_ptr;
4941 cifs_buf_release(pSMB);
4948 ssize_t CIFSSMBQueryEA(const int xid,struct cifsTconInfo * tcon,
4949 const unsigned char * searchName,const unsigned char * ea_name,
4950 unsigned char * ea_value, size_t buf_size,
4951 const struct nls_table *nls_codepage, int remap)
4953 TRANSACTION2_QPI_REQ *pSMB = NULL;
4954 TRANSACTION2_QPI_RSP *pSMBr = NULL;
4958 struct fea * temp_fea;
4960 __u16 params, byte_count;
4962 cFYI(1, ("In Query EA path %s", searchName));
4964 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4969 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4971 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
4972 PATH_MAX, nls_codepage, remap);
4973 name_len++; /* trailing null */
4975 } else { /* BB improve the check for buffer overruns BB */
4976 name_len = strnlen(searchName, PATH_MAX);
4977 name_len++; /* trailing null */
4978 strncpy(pSMB->FileName, searchName, name_len);
4981 params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */ ;
4982 pSMB->TotalDataCount = 0;
4983 pSMB->MaxParameterCount = cpu_to_le16(2);
4984 pSMB->MaxDataCount = cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
4985 pSMB->MaxSetupCount = 0;
4989 pSMB->Reserved2 = 0;
4990 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4991 struct smb_com_transaction2_qpi_req ,InformationLevel) - 4);
4992 pSMB->DataCount = 0;
4993 pSMB->DataOffset = 0;
4994 pSMB->SetupCount = 1;
4995 pSMB->Reserved3 = 0;
4996 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
4997 byte_count = params + 1 /* pad */ ;
4998 pSMB->TotalParameterCount = cpu_to_le16(params);
4999 pSMB->ParameterCount = pSMB->TotalParameterCount;
5000 pSMB->InformationLevel = cpu_to_le16(SMB_INFO_QUERY_ALL_EAS);
5001 pSMB->Reserved4 = 0;
5002 pSMB->hdr.smb_buf_length += byte_count;
5003 pSMB->ByteCount = cpu_to_le16(byte_count);
5005 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5006 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5008 cFYI(1, ("Send error in Query EA = %d", rc));
5009 } else { /* decode response */
5010 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
5012 /* BB also check enough total bytes returned */
5013 /* BB we need to improve the validity checking
5014 of these trans2 responses */
5015 if (rc || (pSMBr->ByteCount < 4))
5016 rc = -EIO; /* bad smb */
5017 /* else if (pFindData){
5018 memcpy((char *) pFindData,
5019 (char *) &pSMBr->hdr.Protocol +
5022 /* check that length of list is not more than bcc */
5023 /* check that each entry does not go beyond length
5025 /* check that each element of each entry does not
5026 go beyond end of list */
5027 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
5028 struct fealist * ea_response_data;
5030 /* validate_trans2_offsets() */
5031 /* BB to check if(start of smb + data_offset > &bcc+ bcc)*/
5032 ea_response_data = (struct fealist *)
5033 (((char *) &pSMBr->hdr.Protocol) +
5035 name_len = le32_to_cpu(ea_response_data->list_len);
5036 cFYI(1,("ea length %d", name_len));
5038 /* returned EA size zeroed at top of function */
5039 cFYI(1,("empty EA list returned from server"));
5041 /* account for ea list len */
5043 temp_fea = ea_response_data->list;
5044 temp_ptr = (char *)temp_fea;
5045 /* loop through checking if we have a matching
5046 name and then return the associated value */
5047 while(name_len > 0) {
5051 value_len = le16_to_cpu(temp_fea->value_len);
5052 /* BB validate that value_len falls within SMB,
5053 even though maximum for name_len is 255 */
5054 if(memcmp(temp_fea->name,ea_name,
5055 temp_fea->name_len) == 0) {
5058 /* account for prefix user. and trailing null */
5059 if(rc<=(int)buf_size) {
5061 temp_fea->name+temp_fea->name_len+1,
5063 /* ea values, unlike ea names,
5064 are not null terminated */
5065 } else if(buf_size == 0) {
5066 /* skip copy - calc size only */
5068 /* stop before overrun buffer */
5073 name_len -= temp_fea->name_len;
5074 temp_ptr += temp_fea->name_len;
5075 /* account for trailing null */
5078 name_len -= value_len;
5079 temp_ptr += value_len;
5080 /* no trailing null to account for in value len */
5081 /* go on to next EA */
5082 temp_fea = (struct fea *)temp_ptr;
5088 cifs_buf_release(pSMB);
5096 CIFSSMBSetEA(const int xid, struct cifsTconInfo *tcon, const char *fileName,
5097 const char * ea_name, const void * ea_value,
5098 const __u16 ea_value_len, const struct nls_table *nls_codepage,
5101 struct smb_com_transaction2_spi_req *pSMB = NULL;
5102 struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
5103 struct fealist *parm_data;
5106 int bytes_returned = 0;
5107 __u16 params, param_offset, byte_count, offset, count;
5109 cFYI(1, ("In SetEA"));
5111 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5116 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5118 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
5119 PATH_MAX, nls_codepage, remap);
5120 name_len++; /* trailing null */
5122 } else { /* BB improve the check for buffer overruns BB */
5123 name_len = strnlen(fileName, PATH_MAX);
5124 name_len++; /* trailing null */
5125 strncpy(pSMB->FileName, fileName, name_len);
5128 params = 6 + name_len;
5130 /* done calculating parms using name_len of file name,
5131 now use name_len to calculate length of ea name
5132 we are going to create in the inode xattrs */
5136 name_len = strnlen(ea_name,255);
5138 count = sizeof(*parm_data) + ea_value_len + name_len + 1;
5139 pSMB->MaxParameterCount = cpu_to_le16(2);
5140 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB size from sess */
5141 pSMB->MaxSetupCount = 0;
5145 pSMB->Reserved2 = 0;
5146 param_offset = offsetof(struct smb_com_transaction2_spi_req,
5147 InformationLevel) - 4;
5148 offset = param_offset + params;
5149 pSMB->InformationLevel =
5150 cpu_to_le16(SMB_SET_FILE_EA);
5153 (struct fealist *) (((char *) &pSMB->hdr.Protocol) +
5155 pSMB->ParameterOffset = cpu_to_le16(param_offset);
5156 pSMB->DataOffset = cpu_to_le16(offset);
5157 pSMB->SetupCount = 1;
5158 pSMB->Reserved3 = 0;
5159 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
5160 byte_count = 3 /* pad */ + params + count;
5161 pSMB->DataCount = cpu_to_le16(count);
5162 parm_data->list_len = cpu_to_le32(count);
5163 parm_data->list[0].EA_flags = 0;
5164 /* we checked above that name len is less than 255 */
5165 parm_data->list[0].name_len = (__u8)name_len;
5166 /* EA names are always ASCII */
5168 strncpy(parm_data->list[0].name,ea_name,name_len);
5169 parm_data->list[0].name[name_len] = 0;
5170 parm_data->list[0].value_len = cpu_to_le16(ea_value_len);
5171 /* caller ensures that ea_value_len is less than 64K but
5172 we need to ensure that it fits within the smb */
5174 /*BB add length check that it would fit in negotiated SMB buffer size BB */
5175 /* if(ea_value_len > buffer_size - 512 (enough for header)) */
5177 memcpy(parm_data->list[0].name+name_len+1,ea_value,ea_value_len);
5179 pSMB->TotalDataCount = pSMB->DataCount;
5180 pSMB->ParameterCount = cpu_to_le16(params);
5181 pSMB->TotalParameterCount = pSMB->ParameterCount;
5182 pSMB->Reserved4 = 0;
5183 pSMB->hdr.smb_buf_length += byte_count;
5184 pSMB->ByteCount = cpu_to_le16(byte_count);
5185 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5186 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5188 cFYI(1, ("SetPathInfo (EA) returned %d", rc));
5191 cifs_buf_release(pSMB);