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);
213 small_smb_init_no_tc(const int smb_command, const int wct,
214 struct cifsSesInfo *ses, void **request_buf)
217 struct smb_hdr * buffer;
219 rc = small_smb_init(smb_command, wct, NULL, request_buf);
223 buffer = (struct smb_hdr *)*request_buf;
224 buffer->Mid = GetNextMid(ses->server);
225 if (ses->capabilities & CAP_UNICODE)
226 buffer->Flags2 |= SMBFLG2_UNICODE;
227 if (ses->capabilities & CAP_STATUS32)
228 buffer->Flags2 |= SMBFLG2_ERR_STATUS;
230 /* uid, tid can stay at zero as set in header assemble */
232 /* BB add support for turning on the signing when
233 this function is used after 1st of session setup requests */
238 /* If the return code is zero, this function must fill in request_buf pointer */
240 smb_init(int smb_command, int wct, struct cifsTconInfo *tcon,
241 void **request_buf /* returned */ ,
242 void **response_buf /* returned */ )
246 /* SMBs NegProt, SessSetup, uLogoff do not have tcon yet so
247 check for tcp and smb session status done differently
248 for those three - in the calling routine */
250 if(tcon->tidStatus == CifsExiting) {
251 /* only tree disconnect, open, and write,
252 (and ulogoff which does not have tcon)
253 are allowed as we start force umount */
254 if((smb_command != SMB_COM_WRITE_ANDX) &&
255 (smb_command != SMB_COM_OPEN_ANDX) &&
256 (smb_command != SMB_COM_TREE_DISCONNECT)) {
257 cFYI(1,("can not send cmd %d while umounting",
263 if((tcon->ses) && (tcon->ses->status != CifsExiting) &&
264 (tcon->ses->server)){
265 struct nls_table *nls_codepage;
266 /* Give Demultiplex thread up to 10 seconds to
267 reconnect, should be greater than cifs socket
268 timeout which is 7 seconds */
269 while(tcon->ses->server->tcpStatus == CifsNeedReconnect) {
270 wait_event_interruptible_timeout(tcon->ses->server->response_q,
271 (tcon->ses->server->tcpStatus == CifsGood), 10 * HZ);
272 if(tcon->ses->server->tcpStatus ==
274 /* on "soft" mounts we wait once */
275 if((tcon->retry == FALSE) ||
276 (tcon->ses->status == CifsExiting)) {
277 cFYI(1,("gave up waiting on reconnect in smb_init"));
279 } /* else "hard" mount - keep retrying
280 until process is killed or server
282 } else /* TCP session is reestablished now */
287 nls_codepage = load_nls_default();
288 /* need to prevent multiple threads trying to
289 simultaneously reconnect the same SMB session */
290 down(&tcon->ses->sesSem);
291 if(tcon->ses->status == CifsNeedReconnect)
292 rc = cifs_setup_session(0, tcon->ses,
294 if(!rc && (tcon->tidStatus == CifsNeedReconnect)) {
295 mark_open_files_invalid(tcon);
296 rc = CIFSTCon(0, tcon->ses, tcon->treeName,
298 up(&tcon->ses->sesSem);
299 /* BB FIXME add code to check if wsize needs
300 update due to negotiated smb buffer size
303 atomic_inc(&tconInfoReconnectCount);
305 cFYI(1, ("reconnect tcon rc = %d", rc));
306 /* Removed call to reopen open files here -
307 it is safer (and faster) to reopen files
308 one at a time as needed in read and write */
310 /* Check if handle based operation so we
311 know whether we can continue or not without
312 returning to caller to reset file handle */
313 switch(smb_command) {
314 case SMB_COM_READ_ANDX:
315 case SMB_COM_WRITE_ANDX:
317 case SMB_COM_FIND_CLOSE2:
318 case SMB_COM_LOCKING_ANDX: {
319 unload_nls(nls_codepage);
324 up(&tcon->ses->sesSem);
326 unload_nls(nls_codepage);
335 *request_buf = cifs_buf_get();
336 if (*request_buf == NULL) {
337 /* BB should we add a retry in here if not a writepage? */
340 /* Although the original thought was we needed the response buf for */
341 /* potential retries of smb operations it turns out we can determine */
342 /* from the mid flags when the request buffer can be resent without */
343 /* having to use a second distinct buffer for the response */
345 *response_buf = *request_buf;
347 header_assemble((struct smb_hdr *) *request_buf, smb_command, tcon,
351 cifs_stats_inc(&tcon->num_smbs_sent);
356 static int validate_t2(struct smb_t2_rsp * pSMB)
362 /* check for plausible wct, bcc and t2 data and parm sizes */
363 /* check for parm and data offset going beyond end of smb */
364 if(pSMB->hdr.WordCount >= 10) {
365 if((le16_to_cpu(pSMB->t2_rsp.ParameterOffset) <= 1024) &&
366 (le16_to_cpu(pSMB->t2_rsp.DataOffset) <= 1024)) {
367 /* check that bcc is at least as big as parms + data */
368 /* check that bcc is less than negotiated smb buffer */
369 total_size = le16_to_cpu(pSMB->t2_rsp.ParameterCount);
370 if(total_size < 512) {
371 total_size+=le16_to_cpu(pSMB->t2_rsp.DataCount);
372 /* BCC le converted in SendReceive */
373 pBCC = (pSMB->hdr.WordCount * 2) +
374 sizeof(struct smb_hdr) +
376 if((total_size <= (*(u16 *)pBCC)) &&
378 CIFSMaxBufSize+MAX_CIFS_HDR_SIZE)) {
385 cifs_dump_mem("Invalid transact2 SMB: ",(char *)pSMB,
386 sizeof(struct smb_t2_rsp) + 16);
390 CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses)
393 NEGOTIATE_RSP *pSMBr;
397 struct TCP_Server_Info * server;
399 unsigned int secFlags;
402 server = ses->server;
407 rc = smb_init(SMB_COM_NEGOTIATE, 0, NULL /* no tcon yet */ ,
408 (void **) &pSMB, (void **) &pSMBr);
412 /* if any of auth flags (ie not sign or seal) are overriden use them */
413 if(ses->overrideSecFlg & (~(CIFSSEC_MUST_SIGN | CIFSSEC_MUST_SEAL)))
414 secFlags = ses->overrideSecFlg;
415 else /* if override flags set only sign/seal OR them with global auth */
416 secFlags = extended_security | ses->overrideSecFlg;
418 cFYI(1,("secFlags 0x%x",secFlags));
420 pSMB->hdr.Mid = GetNextMid(server);
421 pSMB->hdr.Flags2 |= SMBFLG2_UNICODE;
422 if((secFlags & CIFSSEC_MUST_KRB5) == CIFSSEC_MUST_KRB5)
423 pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC;
426 for(i=0;i<CIFS_NUM_PROT;i++) {
427 strncpy(pSMB->DialectsArray+count, protocols[i].name, 16);
428 count += strlen(protocols[i].name) + 1;
429 /* null at end of source and target buffers anyway */
431 pSMB->hdr.smb_buf_length += count;
432 pSMB->ByteCount = cpu_to_le16(count);
434 rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB,
435 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
439 cFYI(1,("Dialect: %d", pSMBr->DialectIndex));
440 /* Check wct = 1 error case */
441 if((pSMBr->hdr.WordCount < 13) || (pSMBr->DialectIndex == BAD_PROT)) {
442 /* core returns wct = 1, but we do not ask for core - otherwise
443 small wct just comes when dialect index is -1 indicating we
444 could not negotiate a common dialect */
447 #ifdef CONFIG_CIFS_WEAK_PW_HASH
448 } else if((pSMBr->hdr.WordCount == 13)
449 && (pSMBr->DialectIndex == LANMAN_PROT)) {
450 struct lanman_neg_rsp * rsp = (struct lanman_neg_rsp *)pSMBr;
452 if((secFlags & CIFSSEC_MAY_LANMAN) ||
453 (secFlags & CIFSSEC_MAY_PLNTXT))
454 server->secType = LANMAN;
456 cERROR(1, ("mount failed weak security disabled"
457 " in /proc/fs/cifs/SecurityFlags"));
461 server->secMode = (__u8)le16_to_cpu(rsp->SecurityMode);
462 server->maxReq = le16_to_cpu(rsp->MaxMpxCount);
463 server->maxBuf = min((__u32)le16_to_cpu(rsp->MaxBufSize),
464 (__u32)CIFSMaxBufSize + MAX_CIFS_HDR_SIZE);
465 GETU32(server->sessid) = le32_to_cpu(rsp->SessionKey);
466 /* even though we do not use raw we might as well set this
467 accurately, in case we ever find a need for it */
468 if((le16_to_cpu(rsp->RawMode) & RAW_ENABLE) == RAW_ENABLE) {
469 server->maxRw = 0xFF00;
470 server->capabilities = CAP_MPX_MODE | CAP_RAW_MODE;
472 server->maxRw = 0;/* we do not need to use raw anyway */
473 server->capabilities = CAP_MPX_MODE;
475 server->timeZone = le16_to_cpu(rsp->ServerTimeZone);
477 /* BB get server time for time conversions and add
478 code to use it and timezone since this is not UTC */
480 if (rsp->EncryptionKeyLength == cpu_to_le16(CIFS_CRYPTO_KEY_SIZE)) {
481 memcpy(server->cryptKey, rsp->EncryptionKey,
482 CIFS_CRYPTO_KEY_SIZE);
483 } else if (server->secMode & SECMODE_PW_ENCRYPT) {
484 rc = -EIO; /* need cryptkey unless plain text */
488 cFYI(1,("LANMAN negotiated"));
489 /* we will not end up setting signing flags - as no signing
490 was in LANMAN and server did not return the flags on */
492 #else /* weak security disabled */
493 } else if(pSMBr->hdr.WordCount == 13) {
494 cERROR(1,("mount failed, cifs module not built "
495 "with CIFS_WEAK_PW_HASH support"));
497 #endif /* WEAK_PW_HASH */
499 } else if(pSMBr->hdr.WordCount != 17) {
504 /* else wct == 17 NTLM */
505 server->secMode = pSMBr->SecurityMode;
506 if((server->secMode & SECMODE_USER) == 0)
507 cFYI(1,("share mode security"));
509 if((server->secMode & SECMODE_PW_ENCRYPT) == 0)
510 #ifdef CONFIG_CIFS_WEAK_PW_HASH
511 if ((secFlags & CIFSSEC_MAY_PLNTXT) == 0)
512 #endif /* CIFS_WEAK_PW_HASH */
513 cERROR(1,("Server requests plain text password"
514 " but client support disabled"));
516 if((secFlags & CIFSSEC_MUST_NTLMV2) == CIFSSEC_MUST_NTLMV2)
517 server->secType = NTLMv2;
518 else if(secFlags & CIFSSEC_MAY_NTLM)
519 server->secType = NTLM;
520 else if(secFlags & CIFSSEC_MAY_NTLMV2)
521 server->secType = NTLMv2;
522 /* else krb5 ... any others ... */
524 /* one byte, so no need to convert this or EncryptionKeyLen from
526 server->maxReq = le16_to_cpu(pSMBr->MaxMpxCount);
527 /* probably no need to store and check maxvcs */
528 server->maxBuf = min(le32_to_cpu(pSMBr->MaxBufferSize),
529 (__u32) CIFSMaxBufSize + MAX_CIFS_HDR_SIZE);
530 server->maxRw = le32_to_cpu(pSMBr->MaxRawSize);
531 cFYI(0, ("Max buf = %d", ses->server->maxBuf));
532 GETU32(ses->server->sessid) = le32_to_cpu(pSMBr->SessionKey);
533 server->capabilities = le32_to_cpu(pSMBr->Capabilities);
534 server->timeZone = le16_to_cpu(pSMBr->ServerTimeZone);
535 if (pSMBr->EncryptionKeyLength == CIFS_CRYPTO_KEY_SIZE) {
536 memcpy(server->cryptKey, pSMBr->u.EncryptionKey,
537 CIFS_CRYPTO_KEY_SIZE);
538 } else if ((pSMBr->hdr.Flags2 & SMBFLG2_EXT_SEC)
539 && (pSMBr->EncryptionKeyLength == 0)) {
540 /* decode security blob */
541 } else if (server->secMode & SECMODE_PW_ENCRYPT) {
542 rc = -EIO; /* no crypt key only if plain text pwd */
546 /* BB might be helpful to save off the domain of server here */
548 if ((pSMBr->hdr.Flags2 & SMBFLG2_EXT_SEC) &&
549 (server->capabilities & CAP_EXTENDED_SECURITY)) {
550 count = pSMBr->ByteCount;
553 else if (count == 16) {
554 server->secType = RawNTLMSSP;
555 if (server->socketUseCount.counter > 1) {
556 if (memcmp(server->server_GUID,
557 pSMBr->u.extended_response.
559 cFYI(1, ("server UID changed"));
560 memcpy(server->server_GUID,
561 pSMBr->u.extended_response.GUID,
565 memcpy(server->server_GUID,
566 pSMBr->u.extended_response.GUID, 16);
568 rc = decode_negTokenInit(pSMBr->u.extended_response.
573 /* BB Need to fill struct for sessetup here */
580 server->capabilities &= ~CAP_EXTENDED_SECURITY;
582 #ifdef CONFIG_CIFS_WEAK_PW_HASH
585 if(sign_CIFS_PDUs == FALSE) {
586 if(server->secMode & SECMODE_SIGN_REQUIRED)
587 cERROR(1,("Server requires "
588 "/proc/fs/cifs/PacketSigningEnabled to be on"));
590 ~(SECMODE_SIGN_ENABLED | SECMODE_SIGN_REQUIRED);
591 } else if(sign_CIFS_PDUs == 1) {
592 if((server->secMode & SECMODE_SIGN_REQUIRED) == 0)
594 ~(SECMODE_SIGN_ENABLED | SECMODE_SIGN_REQUIRED);
595 } else if(sign_CIFS_PDUs == 2) {
596 if((server->secMode &
597 (SECMODE_SIGN_ENABLED | SECMODE_SIGN_REQUIRED)) == 0) {
598 cERROR(1,("signing required but server lacks support"));
602 cifs_buf_release(pSMB);
604 cFYI(1,("negprot rc %d",rc));
609 CIFSSMBTDis(const int xid, struct cifsTconInfo *tcon)
611 struct smb_hdr *smb_buffer;
612 struct smb_hdr *smb_buffer_response; /* BB removeme BB */
616 cFYI(1, ("In tree disconnect"));
618 * If last user of the connection and
619 * connection alive - disconnect it
620 * If this is the last connection on the server session disconnect it
621 * (and inside session disconnect we should check if tcp socket needs
622 * to be freed and kernel thread woken up).
625 down(&tcon->tconSem);
629 atomic_dec(&tcon->useCount);
630 if (atomic_read(&tcon->useCount) > 0) {
635 /* No need to return error on this operation if tid invalidated and
636 closed on server already e.g. due to tcp session crashing */
637 if(tcon->tidStatus == CifsNeedReconnect) {
642 if((tcon->ses == NULL) || (tcon->ses->server == NULL)) {
646 rc = small_smb_init(SMB_COM_TREE_DISCONNECT, 0, tcon,
647 (void **)&smb_buffer);
652 smb_buffer_response = smb_buffer; /* BB removeme BB */
654 rc = SendReceive(xid, tcon->ses, smb_buffer, smb_buffer_response,
657 cFYI(1, ("Tree disconnect failed %d", rc));
660 cifs_small_buf_release(smb_buffer);
663 /* No need to return error on this operation if tid invalidated and
664 closed on server already e.g. due to tcp session crashing */
672 CIFSSMBLogoff(const int xid, struct cifsSesInfo *ses)
674 struct smb_hdr *smb_buffer_response;
675 LOGOFF_ANDX_REQ *pSMB;
679 cFYI(1, ("In SMBLogoff for session disconnect"));
685 atomic_dec(&ses->inUse);
686 if (atomic_read(&ses->inUse) > 0) {
690 rc = small_smb_init(SMB_COM_LOGOFF_ANDX, 2, NULL, (void **)&pSMB);
696 smb_buffer_response = (struct smb_hdr *)pSMB; /* BB removeme BB */
699 pSMB->hdr.Mid = GetNextMid(ses->server);
701 if(ses->server->secMode &
702 (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
703 pSMB->hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
706 pSMB->hdr.Uid = ses->Suid;
708 pSMB->AndXCommand = 0xFF;
709 rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB,
710 smb_buffer_response, &length, 0);
712 atomic_dec(&ses->server->socketUseCount);
713 if (atomic_read(&ses->server->socketUseCount) == 0) {
714 spin_lock(&GlobalMid_Lock);
715 ses->server->tcpStatus = CifsExiting;
716 spin_unlock(&GlobalMid_Lock);
721 cifs_small_buf_release(pSMB);
723 /* if session dead then we do not need to do ulogoff,
724 since server closed smb session, no sense reporting
732 CIFSSMBDelFile(const int xid, struct cifsTconInfo *tcon, const char *fileName,
733 const struct nls_table *nls_codepage, int remap)
735 DELETE_FILE_REQ *pSMB = NULL;
736 DELETE_FILE_RSP *pSMBr = NULL;
742 rc = smb_init(SMB_COM_DELETE, 1, tcon, (void **) &pSMB,
747 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
749 cifsConvertToUCS((__le16 *) pSMB->fileName, fileName,
750 PATH_MAX, nls_codepage, remap);
751 name_len++; /* trailing null */
753 } else { /* BB improve check for buffer overruns BB */
754 name_len = strnlen(fileName, PATH_MAX);
755 name_len++; /* trailing null */
756 strncpy(pSMB->fileName, fileName, name_len);
758 pSMB->SearchAttributes =
759 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM);
760 pSMB->BufferFormat = 0x04;
761 pSMB->hdr.smb_buf_length += name_len + 1;
762 pSMB->ByteCount = cpu_to_le16(name_len + 1);
763 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
764 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
765 cifs_stats_inc(&tcon->num_deletes);
767 cFYI(1, ("Error in RMFile = %d", rc));
770 cifs_buf_release(pSMB);
778 CIFSSMBRmDir(const int xid, struct cifsTconInfo *tcon, const char *dirName,
779 const struct nls_table *nls_codepage, int remap)
781 DELETE_DIRECTORY_REQ *pSMB = NULL;
782 DELETE_DIRECTORY_RSP *pSMBr = NULL;
787 cFYI(1, ("In CIFSSMBRmDir"));
789 rc = smb_init(SMB_COM_DELETE_DIRECTORY, 0, tcon, (void **) &pSMB,
794 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
795 name_len = cifsConvertToUCS((__le16 *) pSMB->DirName, dirName,
796 PATH_MAX, nls_codepage, remap);
797 name_len++; /* trailing null */
799 } else { /* BB improve check for buffer overruns BB */
800 name_len = strnlen(dirName, PATH_MAX);
801 name_len++; /* trailing null */
802 strncpy(pSMB->DirName, dirName, name_len);
805 pSMB->BufferFormat = 0x04;
806 pSMB->hdr.smb_buf_length += name_len + 1;
807 pSMB->ByteCount = cpu_to_le16(name_len + 1);
808 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
809 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
810 cifs_stats_inc(&tcon->num_rmdirs);
812 cFYI(1, ("Error in RMDir = %d", rc));
815 cifs_buf_release(pSMB);
822 CIFSSMBMkDir(const int xid, struct cifsTconInfo *tcon,
823 const char *name, const struct nls_table *nls_codepage, int remap)
826 CREATE_DIRECTORY_REQ *pSMB = NULL;
827 CREATE_DIRECTORY_RSP *pSMBr = NULL;
831 cFYI(1, ("In CIFSSMBMkDir"));
833 rc = smb_init(SMB_COM_CREATE_DIRECTORY, 0, tcon, (void **) &pSMB,
838 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
839 name_len = cifsConvertToUCS((__le16 *) pSMB->DirName, name,
840 PATH_MAX, nls_codepage, remap);
841 name_len++; /* trailing null */
843 } else { /* BB improve check for buffer overruns BB */
844 name_len = strnlen(name, PATH_MAX);
845 name_len++; /* trailing null */
846 strncpy(pSMB->DirName, name, name_len);
849 pSMB->BufferFormat = 0x04;
850 pSMB->hdr.smb_buf_length += name_len + 1;
851 pSMB->ByteCount = cpu_to_le16(name_len + 1);
852 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
853 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
854 cifs_stats_inc(&tcon->num_mkdirs);
856 cFYI(1, ("Error in Mkdir = %d", rc));
859 cifs_buf_release(pSMB);
865 static __u16 convert_disposition(int disposition)
869 switch (disposition) {
871 ofun = SMBOPEN_OCREATE | SMBOPEN_OTRUNC;
874 ofun = SMBOPEN_OAPPEND;
877 ofun = SMBOPEN_OCREATE;
880 ofun = SMBOPEN_OCREATE | SMBOPEN_OAPPEND;
883 ofun = SMBOPEN_OTRUNC;
885 case FILE_OVERWRITE_IF:
886 ofun = SMBOPEN_OCREATE | SMBOPEN_OTRUNC;
889 cFYI(1,("unknown disposition %d",disposition));
890 ofun = SMBOPEN_OAPPEND; /* regular open */
896 SMBLegacyOpen(const int xid, struct cifsTconInfo *tcon,
897 const char *fileName, const int openDisposition,
898 const int access_flags, const int create_options, __u16 * netfid,
899 int *pOplock, FILE_ALL_INFO * pfile_info,
900 const struct nls_table *nls_codepage, int remap)
903 OPENX_REQ *pSMB = NULL;
904 OPENX_RSP *pSMBr = NULL;
910 rc = smb_init(SMB_COM_OPEN_ANDX, 15, tcon, (void **) &pSMB,
915 pSMB->AndXCommand = 0xFF; /* none */
917 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
918 count = 1; /* account for one byte pad to word boundary */
920 cifsConvertToUCS((__le16 *) (pSMB->fileName + 1),
921 fileName, PATH_MAX, nls_codepage, remap);
922 name_len++; /* trailing null */
924 } else { /* BB improve check for buffer overruns BB */
925 count = 0; /* no pad */
926 name_len = strnlen(fileName, PATH_MAX);
927 name_len++; /* trailing null */
928 strncpy(pSMB->fileName, fileName, name_len);
930 if (*pOplock & REQ_OPLOCK)
931 pSMB->OpenFlags = cpu_to_le16(REQ_OPLOCK);
932 else if (*pOplock & REQ_BATCHOPLOCK) {
933 pSMB->OpenFlags = cpu_to_le16(REQ_BATCHOPLOCK);
935 pSMB->OpenFlags |= cpu_to_le16(REQ_MORE_INFO);
936 /* BB fixme add conversion for access_flags to bits 0 - 2 of mode */
942 pSMB->Mode = cpu_to_le16(2);
943 pSMB->Mode |= cpu_to_le16(0x40); /* deny none */
944 /* set file as system file if special file such
945 as fifo and server expecting SFU style and
946 no Unix extensions */
948 if(create_options & CREATE_OPTION_SPECIAL)
949 pSMB->FileAttributes = cpu_to_le16(ATTR_SYSTEM);
951 pSMB->FileAttributes = cpu_to_le16(0/*ATTR_NORMAL*/); /* BB FIXME */
953 /* if ((omode & S_IWUGO) == 0)
954 pSMB->FileAttributes |= cpu_to_le32(ATTR_READONLY);*/
955 /* Above line causes problems due to vfs splitting create into two
956 pieces - need to set mode after file created not while it is
960 /* pSMB->CreateOptions = cpu_to_le32(create_options & CREATE_OPTIONS_MASK); */
961 /* BB FIXME END BB */
963 pSMB->Sattr = cpu_to_le16(ATTR_HIDDEN | ATTR_SYSTEM | ATTR_DIRECTORY);
964 pSMB->OpenFunction = cpu_to_le16(convert_disposition(openDisposition));
966 pSMB->hdr.smb_buf_length += count;
968 pSMB->ByteCount = cpu_to_le16(count);
969 /* long_op set to 1 to allow for oplock break timeouts */
970 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
971 (struct smb_hdr *) pSMBr, &bytes_returned, 1);
972 cifs_stats_inc(&tcon->num_opens);
974 cFYI(1, ("Error in Open = %d", rc));
976 /* BB verify if wct == 15 */
978 /* *pOplock = pSMBr->OplockLevel; */ /* BB take from action field BB */
980 *netfid = pSMBr->Fid; /* cifs fid stays in le */
981 /* Let caller know file was created so we can set the mode. */
982 /* Do we care about the CreateAction in any other cases? */
984 /* if(cpu_to_le32(FILE_CREATE) == pSMBr->CreateAction)
985 *pOplock |= CIFS_CREATE_ACTION; */
989 pfile_info->CreationTime = 0; /* BB convert CreateTime*/
990 pfile_info->LastAccessTime = 0; /* BB fixme */
991 pfile_info->LastWriteTime = 0; /* BB fixme */
992 pfile_info->ChangeTime = 0; /* BB fixme */
993 pfile_info->Attributes =
994 cpu_to_le32(le16_to_cpu(pSMBr->FileAttributes));
995 /* the file_info buf is endian converted by caller */
996 pfile_info->AllocationSize =
997 cpu_to_le64(le32_to_cpu(pSMBr->EndOfFile));
998 pfile_info->EndOfFile = pfile_info->AllocationSize;
999 pfile_info->NumberOfLinks = cpu_to_le32(1);
1003 cifs_buf_release(pSMB);
1010 CIFSSMBOpen(const int xid, struct cifsTconInfo *tcon,
1011 const char *fileName, const int openDisposition,
1012 const int access_flags, const int create_options, __u16 * netfid,
1013 int *pOplock, FILE_ALL_INFO * pfile_info,
1014 const struct nls_table *nls_codepage, int remap)
1017 OPEN_REQ *pSMB = NULL;
1018 OPEN_RSP *pSMBr = NULL;
1024 rc = smb_init(SMB_COM_NT_CREATE_ANDX, 24, tcon, (void **) &pSMB,
1029 pSMB->AndXCommand = 0xFF; /* none */
1031 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1032 count = 1; /* account for one byte pad to word boundary */
1034 cifsConvertToUCS((__le16 *) (pSMB->fileName + 1),
1035 fileName, PATH_MAX, nls_codepage, remap);
1036 name_len++; /* trailing null */
1038 pSMB->NameLength = cpu_to_le16(name_len);
1039 } else { /* BB improve check for buffer overruns BB */
1040 count = 0; /* no pad */
1041 name_len = strnlen(fileName, PATH_MAX);
1042 name_len++; /* trailing null */
1043 pSMB->NameLength = cpu_to_le16(name_len);
1044 strncpy(pSMB->fileName, fileName, name_len);
1046 if (*pOplock & REQ_OPLOCK)
1047 pSMB->OpenFlags = cpu_to_le32(REQ_OPLOCK);
1048 else if (*pOplock & REQ_BATCHOPLOCK) {
1049 pSMB->OpenFlags = cpu_to_le32(REQ_BATCHOPLOCK);
1051 pSMB->DesiredAccess = cpu_to_le32(access_flags);
1052 pSMB->AllocationSize = 0;
1053 /* set file as system file if special file such
1054 as fifo and server expecting SFU style and
1055 no Unix extensions */
1056 if(create_options & CREATE_OPTION_SPECIAL)
1057 pSMB->FileAttributes = cpu_to_le32(ATTR_SYSTEM);
1059 pSMB->FileAttributes = cpu_to_le32(ATTR_NORMAL);
1060 /* XP does not handle ATTR_POSIX_SEMANTICS */
1061 /* but it helps speed up case sensitive checks for other
1062 servers such as Samba */
1063 if (tcon->ses->capabilities & CAP_UNIX)
1064 pSMB->FileAttributes |= cpu_to_le32(ATTR_POSIX_SEMANTICS);
1066 /* if ((omode & S_IWUGO) == 0)
1067 pSMB->FileAttributes |= cpu_to_le32(ATTR_READONLY);*/
1068 /* Above line causes problems due to vfs splitting create into two
1069 pieces - need to set mode after file created not while it is
1071 pSMB->ShareAccess = cpu_to_le32(FILE_SHARE_ALL);
1072 pSMB->CreateDisposition = cpu_to_le32(openDisposition);
1073 pSMB->CreateOptions = cpu_to_le32(create_options & CREATE_OPTIONS_MASK);
1074 /* BB Expirement with various impersonation levels and verify */
1075 pSMB->ImpersonationLevel = cpu_to_le32(SECURITY_IMPERSONATION);
1076 pSMB->SecurityFlags =
1077 SECURITY_CONTEXT_TRACKING | SECURITY_EFFECTIVE_ONLY;
1080 pSMB->hdr.smb_buf_length += count;
1082 pSMB->ByteCount = cpu_to_le16(count);
1083 /* long_op set to 1 to allow for oplock break timeouts */
1084 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1085 (struct smb_hdr *) pSMBr, &bytes_returned, 1);
1086 cifs_stats_inc(&tcon->num_opens);
1088 cFYI(1, ("Error in Open = %d", rc));
1090 *pOplock = pSMBr->OplockLevel; /* 1 byte no need to le_to_cpu */
1091 *netfid = pSMBr->Fid; /* cifs fid stays in le */
1092 /* Let caller know file was created so we can set the mode. */
1093 /* Do we care about the CreateAction in any other cases? */
1094 if(cpu_to_le32(FILE_CREATE) == pSMBr->CreateAction)
1095 *pOplock |= CIFS_CREATE_ACTION;
1097 memcpy((char *)pfile_info,(char *)&pSMBr->CreationTime,
1098 36 /* CreationTime to Attributes */);
1099 /* the file_info buf is endian converted by caller */
1100 pfile_info->AllocationSize = pSMBr->AllocationSize;
1101 pfile_info->EndOfFile = pSMBr->EndOfFile;
1102 pfile_info->NumberOfLinks = cpu_to_le32(1);
1106 cifs_buf_release(pSMB);
1113 CIFSSMBRead(const int xid, struct cifsTconInfo *tcon,
1114 const int netfid, const unsigned int count,
1115 const __u64 lseek, unsigned int *nbytes, char **buf,
1119 READ_REQ *pSMB = NULL;
1120 READ_RSP *pSMBr = NULL;
1121 char *pReadData = NULL;
1123 int resp_buf_type = 0;
1126 cFYI(1,("Reading %d bytes on fid %d",count,netfid));
1127 if(tcon->ses->capabilities & CAP_LARGE_FILES)
1130 wct = 10; /* old style read */
1133 rc = small_smb_init(SMB_COM_READ_ANDX, wct, tcon, (void **) &pSMB);
1137 /* tcon and ses pointer are checked in smb_init */
1138 if (tcon->ses->server == NULL)
1139 return -ECONNABORTED;
1141 pSMB->AndXCommand = 0xFF; /* none */
1143 pSMB->OffsetLow = cpu_to_le32(lseek & 0xFFFFFFFF);
1145 pSMB->OffsetHigh = cpu_to_le32(lseek >> 32);
1146 else if((lseek >> 32) > 0) /* can not handle this big offset for old */
1149 pSMB->Remaining = 0;
1150 pSMB->MaxCount = cpu_to_le16(count & 0xFFFF);
1151 pSMB->MaxCountHigh = cpu_to_le32(count >> 16);
1153 pSMB->ByteCount = 0; /* no need to do le conversion since 0 */
1155 /* old style read */
1156 struct smb_com_readx_req * pSMBW =
1157 (struct smb_com_readx_req *)pSMB;
1158 pSMBW->ByteCount = 0;
1161 iov[0].iov_base = (char *)pSMB;
1162 iov[0].iov_len = pSMB->hdr.smb_buf_length + 4;
1163 rc = SendReceive2(xid, tcon->ses, iov,
1166 cifs_stats_inc(&tcon->num_reads);
1167 pSMBr = (READ_RSP *)iov[0].iov_base;
1169 cERROR(1, ("Send error in read = %d", rc));
1171 int data_length = le16_to_cpu(pSMBr->DataLengthHigh);
1172 data_length = data_length << 16;
1173 data_length += le16_to_cpu(pSMBr->DataLength);
1174 *nbytes = data_length;
1176 /*check that DataLength would not go beyond end of SMB */
1177 if ((data_length > CIFSMaxBufSize)
1178 || (data_length > count)) {
1179 cFYI(1,("bad length %d for count %d",data_length,count));
1183 pReadData = (char *) (&pSMBr->hdr.Protocol) +
1184 le16_to_cpu(pSMBr->DataOffset);
1185 /* if(rc = copy_to_user(buf, pReadData, data_length)) {
1186 cERROR(1,("Faulting on read rc = %d",rc));
1188 }*/ /* can not use copy_to_user when using page cache*/
1190 memcpy(*buf,pReadData,data_length);
1194 /* cifs_small_buf_release(pSMB); */ /* Freed earlier now in SendReceive2 */
1196 if(resp_buf_type == CIFS_SMALL_BUFFER)
1197 cifs_small_buf_release(iov[0].iov_base);
1198 else if(resp_buf_type == CIFS_LARGE_BUFFER)
1199 cifs_buf_release(iov[0].iov_base);
1200 } else if(resp_buf_type != CIFS_NO_BUFFER) {
1201 /* return buffer to caller to free */
1202 *buf = iov[0].iov_base;
1203 if(resp_buf_type == CIFS_SMALL_BUFFER)
1204 *pbuf_type = CIFS_SMALL_BUFFER;
1205 else if(resp_buf_type == CIFS_LARGE_BUFFER)
1206 *pbuf_type = CIFS_LARGE_BUFFER;
1207 } /* else no valid buffer on return - leave as null */
1209 /* Note: On -EAGAIN error only caller can retry on handle based calls
1210 since file handle passed in no longer valid */
1216 CIFSSMBWrite(const int xid, struct cifsTconInfo *tcon,
1217 const int netfid, const unsigned int count,
1218 const __u64 offset, unsigned int *nbytes, const char *buf,
1219 const char __user * ubuf, const int long_op)
1222 WRITE_REQ *pSMB = NULL;
1223 WRITE_RSP *pSMBr = NULL;
1224 int bytes_returned, wct;
1228 /* cFYI(1,("write at %lld %d bytes",offset,count));*/
1229 if(tcon->ses == NULL)
1230 return -ECONNABORTED;
1232 if(tcon->ses->capabilities & CAP_LARGE_FILES)
1237 rc = smb_init(SMB_COM_WRITE_ANDX, wct, tcon, (void **) &pSMB,
1241 /* tcon and ses pointer are checked in smb_init */
1242 if (tcon->ses->server == NULL)
1243 return -ECONNABORTED;
1245 pSMB->AndXCommand = 0xFF; /* none */
1247 pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF);
1249 pSMB->OffsetHigh = cpu_to_le32(offset >> 32);
1250 else if((offset >> 32) > 0) /* can not handle this big offset for old */
1253 pSMB->Reserved = 0xFFFFFFFF;
1254 pSMB->WriteMode = 0;
1255 pSMB->Remaining = 0;
1257 /* Can increase buffer size if buffer is big enough in some cases - ie we
1258 can send more if LARGE_WRITE_X capability returned by the server and if
1259 our buffer is big enough or if we convert to iovecs on socket writes
1260 and eliminate the copy to the CIFS buffer */
1261 if(tcon->ses->capabilities & CAP_LARGE_WRITE_X) {
1262 bytes_sent = min_t(const unsigned int, CIFSMaxBufSize, count);
1264 bytes_sent = (tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE)
1268 if (bytes_sent > count)
1271 cpu_to_le16(offsetof(struct smb_com_write_req,Data) - 4);
1273 memcpy(pSMB->Data,buf,bytes_sent);
1275 if(copy_from_user(pSMB->Data,ubuf,bytes_sent)) {
1276 cifs_buf_release(pSMB);
1279 } else if (count != 0) {
1281 cifs_buf_release(pSMB);
1283 } /* else setting file size with write of zero bytes */
1285 byte_count = bytes_sent + 1; /* pad */
1286 else /* wct == 12 */ {
1287 byte_count = bytes_sent + 5; /* bigger pad, smaller smb hdr */
1289 pSMB->DataLengthLow = cpu_to_le16(bytes_sent & 0xFFFF);
1290 pSMB->DataLengthHigh = cpu_to_le16(bytes_sent >> 16);
1291 pSMB->hdr.smb_buf_length += byte_count;
1294 pSMB->ByteCount = cpu_to_le16(byte_count);
1295 else { /* old style write has byte count 4 bytes earlier so 4 bytes pad */
1296 struct smb_com_writex_req * pSMBW =
1297 (struct smb_com_writex_req *)pSMB;
1298 pSMBW->ByteCount = cpu_to_le16(byte_count);
1301 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1302 (struct smb_hdr *) pSMBr, &bytes_returned, long_op);
1303 cifs_stats_inc(&tcon->num_writes);
1305 cFYI(1, ("Send error in write = %d", rc));
1308 *nbytes = le16_to_cpu(pSMBr->CountHigh);
1309 *nbytes = (*nbytes) << 16;
1310 *nbytes += le16_to_cpu(pSMBr->Count);
1313 cifs_buf_release(pSMB);
1315 /* Note: On -EAGAIN error only caller can retry on handle based calls
1316 since file handle passed in no longer valid */
1322 CIFSSMBWrite2(const int xid, struct cifsTconInfo *tcon,
1323 const int netfid, const unsigned int count,
1324 const __u64 offset, unsigned int *nbytes, struct kvec *iov,
1325 int n_vec, const int long_op)
1328 WRITE_REQ *pSMB = NULL;
1331 int resp_buf_type = 0;
1333 cFYI(1,("write2 at %lld %d bytes", (long long)offset, count));
1335 if(tcon->ses->capabilities & CAP_LARGE_FILES)
1339 rc = small_smb_init(SMB_COM_WRITE_ANDX, wct, tcon, (void **) &pSMB);
1342 /* tcon and ses pointer are checked in smb_init */
1343 if (tcon->ses->server == NULL)
1344 return -ECONNABORTED;
1346 pSMB->AndXCommand = 0xFF; /* none */
1348 pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF);
1350 pSMB->OffsetHigh = cpu_to_le32(offset >> 32);
1351 else if((offset >> 32) > 0) /* can not handle this big offset for old */
1353 pSMB->Reserved = 0xFFFFFFFF;
1354 pSMB->WriteMode = 0;
1355 pSMB->Remaining = 0;
1358 cpu_to_le16(offsetof(struct smb_com_write_req,Data) - 4);
1360 pSMB->DataLengthLow = cpu_to_le16(count & 0xFFFF);
1361 pSMB->DataLengthHigh = cpu_to_le16(count >> 16);
1362 smb_hdr_len = pSMB->hdr.smb_buf_length + 1; /* hdr + 1 byte pad */
1364 pSMB->hdr.smb_buf_length += count+1;
1365 else /* wct == 12 */
1366 pSMB->hdr.smb_buf_length += count+5; /* smb data starts later */
1368 pSMB->ByteCount = cpu_to_le16(count + 1);
1369 else /* wct == 12 */ /* bigger pad, smaller smb hdr, keep offset ok */ {
1370 struct smb_com_writex_req * pSMBW =
1371 (struct smb_com_writex_req *)pSMB;
1372 pSMBW->ByteCount = cpu_to_le16(count + 5);
1374 iov[0].iov_base = pSMB;
1376 iov[0].iov_len = smb_hdr_len + 4;
1377 else /* wct == 12 pad bigger by four bytes */
1378 iov[0].iov_len = smb_hdr_len + 8;
1381 rc = SendReceive2(xid, tcon->ses, iov, n_vec + 1, &resp_buf_type,
1383 cifs_stats_inc(&tcon->num_writes);
1385 cFYI(1, ("Send error Write2 = %d", rc));
1387 } else if(resp_buf_type == 0) {
1388 /* presumably this can not happen, but best to be safe */
1392 WRITE_RSP * pSMBr = (WRITE_RSP *)iov[0].iov_base;
1393 *nbytes = le16_to_cpu(pSMBr->CountHigh);
1394 *nbytes = (*nbytes) << 16;
1395 *nbytes += le16_to_cpu(pSMBr->Count);
1398 /* cifs_small_buf_release(pSMB); */ /* Freed earlier now in SendReceive2 */
1399 if(resp_buf_type == CIFS_SMALL_BUFFER)
1400 cifs_small_buf_release(iov[0].iov_base);
1401 else if(resp_buf_type == CIFS_LARGE_BUFFER)
1402 cifs_buf_release(iov[0].iov_base);
1404 /* Note: On -EAGAIN error only caller can retry on handle based calls
1405 since file handle passed in no longer valid */
1412 CIFSSMBLock(const int xid, struct cifsTconInfo *tcon,
1413 const __u16 smb_file_id, const __u64 len,
1414 const __u64 offset, const __u32 numUnlock,
1415 const __u32 numLock, const __u8 lockType, const int waitFlag)
1418 LOCK_REQ *pSMB = NULL;
1419 LOCK_RSP *pSMBr = NULL;
1424 cFYI(1, ("In CIFSSMBLock - timeout %d numLock %d",waitFlag,numLock));
1425 rc = small_smb_init(SMB_COM_LOCKING_ANDX, 8, tcon, (void **) &pSMB);
1430 pSMBr = (LOCK_RSP *)pSMB; /* BB removeme BB */
1432 if(lockType == LOCKING_ANDX_OPLOCK_RELEASE) {
1433 timeout = -1; /* no response expected */
1435 } else if (waitFlag == TRUE) {
1436 timeout = 3; /* blocking operation, no timeout */
1437 pSMB->Timeout = cpu_to_le32(-1);/* blocking - do not time out */
1442 pSMB->NumberOfLocks = cpu_to_le16(numLock);
1443 pSMB->NumberOfUnlocks = cpu_to_le16(numUnlock);
1444 pSMB->LockType = lockType;
1445 pSMB->AndXCommand = 0xFF; /* none */
1446 pSMB->Fid = smb_file_id; /* netfid stays le */
1448 if((numLock != 0) || (numUnlock != 0)) {
1449 pSMB->Locks[0].Pid = cpu_to_le16(current->tgid);
1450 /* BB where to store pid high? */
1451 pSMB->Locks[0].LengthLow = cpu_to_le32((u32)len);
1452 pSMB->Locks[0].LengthHigh = cpu_to_le32((u32)(len>>32));
1453 pSMB->Locks[0].OffsetLow = cpu_to_le32((u32)offset);
1454 pSMB->Locks[0].OffsetHigh = cpu_to_le32((u32)(offset>>32));
1455 count = sizeof(LOCKING_ANDX_RANGE);
1460 pSMB->hdr.smb_buf_length += count;
1461 pSMB->ByteCount = cpu_to_le16(count);
1464 rc = SendReceiveBlockingLock(xid, tcon, (struct smb_hdr *) pSMB,
1465 (struct smb_hdr *) pSMBr, &bytes_returned);
1467 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1468 (struct smb_hdr *) pSMBr, &bytes_returned, timeout);
1470 cifs_stats_inc(&tcon->num_locks);
1472 cFYI(1, ("Send error in Lock = %d", rc));
1474 cifs_small_buf_release(pSMB);
1476 /* Note: On -EAGAIN error only caller can retry on handle based calls
1477 since file handle passed in no longer valid */
1482 CIFSSMBPosixLock(const int xid, struct cifsTconInfo *tcon,
1483 const __u16 smb_file_id, const int get_flag, const __u64 len,
1484 struct file_lock *pLockData, const __u16 lock_type,
1487 struct smb_com_transaction2_sfi_req *pSMB = NULL;
1488 struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
1490 struct cifs_posix_lock *parm_data;
1493 int bytes_returned = 0;
1494 __u16 params, param_offset, offset, byte_count, count;
1496 cFYI(1, ("Posix Lock"));
1498 if(pLockData == NULL)
1501 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
1506 pSMBr = (struct smb_com_transaction2_sfi_rsp *)pSMB;
1509 pSMB->MaxSetupCount = 0;
1512 pSMB->Reserved2 = 0;
1513 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
1514 offset = param_offset + params;
1516 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
1518 count = sizeof(struct cifs_posix_lock);
1519 pSMB->MaxParameterCount = cpu_to_le16(2);
1520 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB PDU from sess */
1521 pSMB->SetupCount = 1;
1522 pSMB->Reserved3 = 0;
1524 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION);
1526 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
1527 byte_count = 3 /* pad */ + params + count;
1528 pSMB->DataCount = cpu_to_le16(count);
1529 pSMB->ParameterCount = cpu_to_le16(params);
1530 pSMB->TotalDataCount = pSMB->DataCount;
1531 pSMB->TotalParameterCount = pSMB->ParameterCount;
1532 pSMB->ParameterOffset = cpu_to_le16(param_offset);
1533 parm_data = (struct cifs_posix_lock *)
1534 (((char *) &pSMB->hdr.Protocol) + offset);
1536 parm_data->lock_type = cpu_to_le16(lock_type);
1538 timeout = 3; /* blocking operation, no timeout */
1539 parm_data->lock_flags = cpu_to_le16(1);
1540 pSMB->Timeout = cpu_to_le32(-1);
1544 parm_data->pid = cpu_to_le32(current->tgid);
1545 parm_data->start = cpu_to_le64(pLockData->fl_start);
1546 parm_data->length = cpu_to_le64(len); /* normalize negative numbers */
1548 pSMB->DataOffset = cpu_to_le16(offset);
1549 pSMB->Fid = smb_file_id;
1550 pSMB->InformationLevel = cpu_to_le16(SMB_SET_POSIX_LOCK);
1551 pSMB->Reserved4 = 0;
1552 pSMB->hdr.smb_buf_length += byte_count;
1553 pSMB->ByteCount = cpu_to_le16(byte_count);
1555 rc = SendReceiveBlockingLock(xid, tcon, (struct smb_hdr *) pSMB,
1556 (struct smb_hdr *) pSMBr, &bytes_returned);
1558 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1559 (struct smb_hdr *) pSMBr, &bytes_returned, timeout);
1563 cFYI(1, ("Send error in Posix Lock = %d", rc));
1564 } else if (get_flag) {
1565 /* lock structure can be returned on get */
1568 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
1570 if (rc || (pSMBr->ByteCount < sizeof(struct cifs_posix_lock))) {
1571 rc = -EIO; /* bad smb */
1574 if(pLockData == NULL) {
1578 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
1579 data_count = le16_to_cpu(pSMBr->t2.DataCount);
1580 if(data_count < sizeof(struct cifs_posix_lock)) {
1584 parm_data = (struct cifs_posix_lock *)
1585 ((char *)&pSMBr->hdr.Protocol + data_offset);
1586 if(parm_data->lock_type == cpu_to_le16(CIFS_UNLCK))
1587 pLockData->fl_type = F_UNLCK;
1592 cifs_small_buf_release(pSMB);
1594 /* Note: On -EAGAIN error only caller can retry on handle based calls
1595 since file handle passed in no longer valid */
1602 CIFSSMBClose(const int xid, struct cifsTconInfo *tcon, int smb_file_id)
1605 CLOSE_REQ *pSMB = NULL;
1606 CLOSE_RSP *pSMBr = NULL;
1608 cFYI(1, ("In CIFSSMBClose"));
1610 /* do not retry on dead session on close */
1611 rc = small_smb_init(SMB_COM_CLOSE, 3, tcon, (void **) &pSMB);
1617 pSMBr = (CLOSE_RSP *)pSMB; /* BB removeme BB */
1619 pSMB->FileID = (__u16) smb_file_id;
1620 pSMB->LastWriteTime = 0;
1621 pSMB->ByteCount = 0;
1622 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1623 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1624 cifs_stats_inc(&tcon->num_closes);
1627 /* EINTR is expected when user ctl-c to kill app */
1628 cERROR(1, ("Send error in Close = %d", rc));
1632 cifs_small_buf_release(pSMB);
1634 /* Since session is dead, file will be closed on server already */
1642 CIFSSMBRename(const int xid, struct cifsTconInfo *tcon,
1643 const char *fromName, const char *toName,
1644 const struct nls_table *nls_codepage, int remap)
1647 RENAME_REQ *pSMB = NULL;
1648 RENAME_RSP *pSMBr = NULL;
1650 int name_len, name_len2;
1653 cFYI(1, ("In CIFSSMBRename"));
1655 rc = smb_init(SMB_COM_RENAME, 1, tcon, (void **) &pSMB,
1660 pSMB->BufferFormat = 0x04;
1661 pSMB->SearchAttributes =
1662 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
1665 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1667 cifsConvertToUCS((__le16 *) pSMB->OldFileName, fromName,
1668 PATH_MAX, nls_codepage, remap);
1669 name_len++; /* trailing null */
1671 pSMB->OldFileName[name_len] = 0x04; /* pad */
1672 /* protocol requires ASCII signature byte on Unicode string */
1673 pSMB->OldFileName[name_len + 1] = 0x00;
1675 cifsConvertToUCS((__le16 *) &pSMB->OldFileName[name_len + 2],
1676 toName, PATH_MAX, nls_codepage, remap);
1677 name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
1678 name_len2 *= 2; /* convert to bytes */
1679 } else { /* BB improve the check for buffer overruns BB */
1680 name_len = strnlen(fromName, PATH_MAX);
1681 name_len++; /* trailing null */
1682 strncpy(pSMB->OldFileName, fromName, name_len);
1683 name_len2 = strnlen(toName, PATH_MAX);
1684 name_len2++; /* trailing null */
1685 pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */
1686 strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2);
1687 name_len2++; /* trailing null */
1688 name_len2++; /* signature byte */
1691 count = 1 /* 1st signature byte */ + name_len + name_len2;
1692 pSMB->hdr.smb_buf_length += count;
1693 pSMB->ByteCount = cpu_to_le16(count);
1695 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1696 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1697 cifs_stats_inc(&tcon->num_renames);
1699 cFYI(1, ("Send error in rename = %d", rc));
1702 cifs_buf_release(pSMB);
1710 int CIFSSMBRenameOpenFile(const int xid,struct cifsTconInfo *pTcon,
1711 int netfid, char * target_name,
1712 const struct nls_table * nls_codepage, int remap)
1714 struct smb_com_transaction2_sfi_req *pSMB = NULL;
1715 struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
1716 struct set_file_rename * rename_info;
1718 char dummy_string[30];
1720 int bytes_returned = 0;
1722 __u16 params, param_offset, offset, count, byte_count;
1724 cFYI(1, ("Rename to File by handle"));
1725 rc = smb_init(SMB_COM_TRANSACTION2, 15, pTcon, (void **) &pSMB,
1731 pSMB->MaxSetupCount = 0;
1735 pSMB->Reserved2 = 0;
1736 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
1737 offset = param_offset + params;
1739 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
1740 rename_info = (struct set_file_rename *) data_offset;
1741 pSMB->MaxParameterCount = cpu_to_le16(2);
1742 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB PDU from sess */
1743 pSMB->SetupCount = 1;
1744 pSMB->Reserved3 = 0;
1745 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
1746 byte_count = 3 /* pad */ + params;
1747 pSMB->ParameterCount = cpu_to_le16(params);
1748 pSMB->TotalParameterCount = pSMB->ParameterCount;
1749 pSMB->ParameterOffset = cpu_to_le16(param_offset);
1750 pSMB->DataOffset = cpu_to_le16(offset);
1751 /* construct random name ".cifs_tmp<inodenum><mid>" */
1752 rename_info->overwrite = cpu_to_le32(1);
1753 rename_info->root_fid = 0;
1754 /* unicode only call */
1755 if(target_name == NULL) {
1756 sprintf(dummy_string,"cifs%x",pSMB->hdr.Mid);
1757 len_of_str = cifsConvertToUCS((__le16 *)rename_info->target_name,
1758 dummy_string, 24, nls_codepage, remap);
1760 len_of_str = cifsConvertToUCS((__le16 *)rename_info->target_name,
1761 target_name, PATH_MAX, nls_codepage, remap);
1763 rename_info->target_name_len = cpu_to_le32(2 * len_of_str);
1764 count = 12 /* sizeof(struct set_file_rename) */ + (2 * len_of_str) + 2;
1765 byte_count += count;
1766 pSMB->DataCount = cpu_to_le16(count);
1767 pSMB->TotalDataCount = pSMB->DataCount;
1769 pSMB->InformationLevel =
1770 cpu_to_le16(SMB_SET_FILE_RENAME_INFORMATION);
1771 pSMB->Reserved4 = 0;
1772 pSMB->hdr.smb_buf_length += byte_count;
1773 pSMB->ByteCount = cpu_to_le16(byte_count);
1774 rc = SendReceive(xid, pTcon->ses, (struct smb_hdr *) pSMB,
1775 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1776 cifs_stats_inc(&pTcon->num_t2renames);
1778 cFYI(1,("Send error in Rename (by file handle) = %d", rc));
1781 cifs_buf_release(pSMB);
1783 /* Note: On -EAGAIN error only caller can retry on handle based calls
1784 since file handle passed in no longer valid */
1790 CIFSSMBCopy(const int xid, struct cifsTconInfo *tcon, const char * fromName,
1791 const __u16 target_tid, const char *toName, const int flags,
1792 const struct nls_table *nls_codepage, int remap)
1795 COPY_REQ *pSMB = NULL;
1796 COPY_RSP *pSMBr = NULL;
1798 int name_len, name_len2;
1801 cFYI(1, ("In CIFSSMBCopy"));
1803 rc = smb_init(SMB_COM_COPY, 1, tcon, (void **) &pSMB,
1808 pSMB->BufferFormat = 0x04;
1809 pSMB->Tid2 = target_tid;
1811 pSMB->Flags = cpu_to_le16(flags & COPY_TREE);
1813 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1814 name_len = cifsConvertToUCS((__le16 *) pSMB->OldFileName,
1815 fromName, PATH_MAX, nls_codepage,
1817 name_len++; /* trailing null */
1819 pSMB->OldFileName[name_len] = 0x04; /* pad */
1820 /* protocol requires ASCII signature byte on Unicode string */
1821 pSMB->OldFileName[name_len + 1] = 0x00;
1822 name_len2 = cifsConvertToUCS((__le16 *)&pSMB->OldFileName[name_len + 2],
1823 toName, PATH_MAX, nls_codepage, remap);
1824 name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
1825 name_len2 *= 2; /* convert to bytes */
1826 } else { /* BB improve the check for buffer overruns BB */
1827 name_len = strnlen(fromName, PATH_MAX);
1828 name_len++; /* trailing null */
1829 strncpy(pSMB->OldFileName, fromName, name_len);
1830 name_len2 = strnlen(toName, PATH_MAX);
1831 name_len2++; /* trailing null */
1832 pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */
1833 strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2);
1834 name_len2++; /* trailing null */
1835 name_len2++; /* signature byte */
1838 count = 1 /* 1st signature byte */ + name_len + name_len2;
1839 pSMB->hdr.smb_buf_length += count;
1840 pSMB->ByteCount = cpu_to_le16(count);
1842 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1843 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1845 cFYI(1, ("Send error in copy = %d with %d files copied",
1846 rc, le16_to_cpu(pSMBr->CopyCount)));
1849 cifs_buf_release(pSMB);
1858 CIFSUnixCreateSymLink(const int xid, struct cifsTconInfo *tcon,
1859 const char *fromName, const char *toName,
1860 const struct nls_table *nls_codepage)
1862 TRANSACTION2_SPI_REQ *pSMB = NULL;
1863 TRANSACTION2_SPI_RSP *pSMBr = NULL;
1866 int name_len_target;
1868 int bytes_returned = 0;
1869 __u16 params, param_offset, offset, byte_count;
1871 cFYI(1, ("In Symlink Unix style"));
1873 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
1878 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1880 cifs_strtoUCS((__le16 *) pSMB->FileName, fromName, PATH_MAX
1881 /* find define for this maxpathcomponent */
1883 name_len++; /* trailing null */
1886 } else { /* BB improve the check for buffer overruns BB */
1887 name_len = strnlen(fromName, PATH_MAX);
1888 name_len++; /* trailing null */
1889 strncpy(pSMB->FileName, fromName, name_len);
1891 params = 6 + name_len;
1892 pSMB->MaxSetupCount = 0;
1896 pSMB->Reserved2 = 0;
1897 param_offset = offsetof(struct smb_com_transaction2_spi_req,
1898 InformationLevel) - 4;
1899 offset = param_offset + params;
1901 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
1902 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1904 cifs_strtoUCS((__le16 *) data_offset, toName, PATH_MAX
1905 /* find define for this maxpathcomponent */
1907 name_len_target++; /* trailing null */
1908 name_len_target *= 2;
1909 } else { /* BB improve the check for buffer overruns BB */
1910 name_len_target = strnlen(toName, PATH_MAX);
1911 name_len_target++; /* trailing null */
1912 strncpy(data_offset, toName, name_len_target);
1915 pSMB->MaxParameterCount = cpu_to_le16(2);
1916 /* BB find exact max on data count below from sess */
1917 pSMB->MaxDataCount = cpu_to_le16(1000);
1918 pSMB->SetupCount = 1;
1919 pSMB->Reserved3 = 0;
1920 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
1921 byte_count = 3 /* pad */ + params + name_len_target;
1922 pSMB->DataCount = cpu_to_le16(name_len_target);
1923 pSMB->ParameterCount = cpu_to_le16(params);
1924 pSMB->TotalDataCount = pSMB->DataCount;
1925 pSMB->TotalParameterCount = pSMB->ParameterCount;
1926 pSMB->ParameterOffset = cpu_to_le16(param_offset);
1927 pSMB->DataOffset = cpu_to_le16(offset);
1928 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_LINK);
1929 pSMB->Reserved4 = 0;
1930 pSMB->hdr.smb_buf_length += byte_count;
1931 pSMB->ByteCount = cpu_to_le16(byte_count);
1932 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1933 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1934 cifs_stats_inc(&tcon->num_symlinks);
1937 ("Send error in SetPathInfo (create symlink) = %d",
1942 cifs_buf_release(pSMB);
1945 goto createSymLinkRetry;
1951 CIFSUnixCreateHardLink(const int xid, struct cifsTconInfo *tcon,
1952 const char *fromName, const char *toName,
1953 const struct nls_table *nls_codepage, int remap)
1955 TRANSACTION2_SPI_REQ *pSMB = NULL;
1956 TRANSACTION2_SPI_RSP *pSMBr = NULL;
1959 int name_len_target;
1961 int bytes_returned = 0;
1962 __u16 params, param_offset, offset, byte_count;
1964 cFYI(1, ("In Create Hard link Unix style"));
1965 createHardLinkRetry:
1966 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
1971 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1972 name_len = cifsConvertToUCS((__le16 *) pSMB->FileName, toName,
1973 PATH_MAX, nls_codepage, remap);
1974 name_len++; /* trailing null */
1977 } else { /* BB improve the check for buffer overruns BB */
1978 name_len = strnlen(toName, PATH_MAX);
1979 name_len++; /* trailing null */
1980 strncpy(pSMB->FileName, toName, name_len);
1982 params = 6 + name_len;
1983 pSMB->MaxSetupCount = 0;
1987 pSMB->Reserved2 = 0;
1988 param_offset = offsetof(struct smb_com_transaction2_spi_req,
1989 InformationLevel) - 4;
1990 offset = param_offset + params;
1992 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
1993 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1995 cifsConvertToUCS((__le16 *) data_offset, fromName, PATH_MAX,
1996 nls_codepage, remap);
1997 name_len_target++; /* trailing null */
1998 name_len_target *= 2;
1999 } else { /* BB improve the check for buffer overruns BB */
2000 name_len_target = strnlen(fromName, PATH_MAX);
2001 name_len_target++; /* trailing null */
2002 strncpy(data_offset, fromName, name_len_target);
2005 pSMB->MaxParameterCount = cpu_to_le16(2);
2006 /* BB find exact max on data count below from sess*/
2007 pSMB->MaxDataCount = cpu_to_le16(1000);
2008 pSMB->SetupCount = 1;
2009 pSMB->Reserved3 = 0;
2010 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
2011 byte_count = 3 /* pad */ + params + name_len_target;
2012 pSMB->ParameterCount = cpu_to_le16(params);
2013 pSMB->TotalParameterCount = pSMB->ParameterCount;
2014 pSMB->DataCount = cpu_to_le16(name_len_target);
2015 pSMB->TotalDataCount = pSMB->DataCount;
2016 pSMB->ParameterOffset = cpu_to_le16(param_offset);
2017 pSMB->DataOffset = cpu_to_le16(offset);
2018 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_HLINK);
2019 pSMB->Reserved4 = 0;
2020 pSMB->hdr.smb_buf_length += byte_count;
2021 pSMB->ByteCount = cpu_to_le16(byte_count);
2022 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2023 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2024 cifs_stats_inc(&tcon->num_hardlinks);
2026 cFYI(1, ("Send error in SetPathInfo (hard link) = %d", rc));
2029 cifs_buf_release(pSMB);
2031 goto createHardLinkRetry;
2037 CIFSCreateHardLink(const int xid, struct cifsTconInfo *tcon,
2038 const char *fromName, const char *toName,
2039 const struct nls_table *nls_codepage, int remap)
2042 NT_RENAME_REQ *pSMB = NULL;
2043 RENAME_RSP *pSMBr = NULL;
2045 int name_len, name_len2;
2048 cFYI(1, ("In CIFSCreateHardLink"));
2049 winCreateHardLinkRetry:
2051 rc = smb_init(SMB_COM_NT_RENAME, 4, tcon, (void **) &pSMB,
2056 pSMB->SearchAttributes =
2057 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
2059 pSMB->Flags = cpu_to_le16(CREATE_HARD_LINK);
2060 pSMB->ClusterCount = 0;
2062 pSMB->BufferFormat = 0x04;
2064 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2066 cifsConvertToUCS((__le16 *) pSMB->OldFileName, fromName,
2067 PATH_MAX, nls_codepage, remap);
2068 name_len++; /* trailing null */
2070 pSMB->OldFileName[name_len] = 0; /* pad */
2071 pSMB->OldFileName[name_len + 1] = 0x04;
2073 cifsConvertToUCS((__le16 *)&pSMB->OldFileName[name_len + 2],
2074 toName, PATH_MAX, nls_codepage, remap);
2075 name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
2076 name_len2 *= 2; /* convert to bytes */
2077 } else { /* BB improve the check for buffer overruns BB */
2078 name_len = strnlen(fromName, PATH_MAX);
2079 name_len++; /* trailing null */
2080 strncpy(pSMB->OldFileName, fromName, name_len);
2081 name_len2 = strnlen(toName, PATH_MAX);
2082 name_len2++; /* trailing null */
2083 pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */
2084 strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2);
2085 name_len2++; /* trailing null */
2086 name_len2++; /* signature byte */
2089 count = 1 /* string type byte */ + name_len + name_len2;
2090 pSMB->hdr.smb_buf_length += count;
2091 pSMB->ByteCount = cpu_to_le16(count);
2093 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2094 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2095 cifs_stats_inc(&tcon->num_hardlinks);
2097 cFYI(1, ("Send error in hard link (NT rename) = %d", rc));
2099 cifs_buf_release(pSMB);
2101 goto winCreateHardLinkRetry;
2107 CIFSSMBUnixQuerySymLink(const int xid, struct cifsTconInfo *tcon,
2108 const unsigned char *searchName,
2109 char *symlinkinfo, const int buflen,
2110 const struct nls_table *nls_codepage)
2112 /* SMB_QUERY_FILE_UNIX_LINK */
2113 TRANSACTION2_QPI_REQ *pSMB = NULL;
2114 TRANSACTION2_QPI_RSP *pSMBr = NULL;
2118 __u16 params, byte_count;
2120 cFYI(1, ("In QPathSymLinkInfo (Unix) for path %s", searchName));
2123 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2128 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2130 cifs_strtoUCS((__le16 *) pSMB->FileName, searchName, PATH_MAX
2131 /* find define for this maxpathcomponent */
2133 name_len++; /* trailing null */
2135 } else { /* BB improve the check for buffer overruns BB */
2136 name_len = strnlen(searchName, PATH_MAX);
2137 name_len++; /* trailing null */
2138 strncpy(pSMB->FileName, searchName, name_len);
2141 params = 2 /* level */ + 4 /* rsrvd */ + name_len /* incl null */ ;
2142 pSMB->TotalDataCount = 0;
2143 pSMB->MaxParameterCount = cpu_to_le16(2);
2144 /* BB find exact max data count below from sess structure BB */
2145 pSMB->MaxDataCount = cpu_to_le16(4000);
2146 pSMB->MaxSetupCount = 0;
2150 pSMB->Reserved2 = 0;
2151 pSMB->ParameterOffset = cpu_to_le16(offsetof(
2152 struct smb_com_transaction2_qpi_req ,InformationLevel) - 4);
2153 pSMB->DataCount = 0;
2154 pSMB->DataOffset = 0;
2155 pSMB->SetupCount = 1;
2156 pSMB->Reserved3 = 0;
2157 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
2158 byte_count = params + 1 /* pad */ ;
2159 pSMB->TotalParameterCount = cpu_to_le16(params);
2160 pSMB->ParameterCount = pSMB->TotalParameterCount;
2161 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_LINK);
2162 pSMB->Reserved4 = 0;
2163 pSMB->hdr.smb_buf_length += byte_count;
2164 pSMB->ByteCount = cpu_to_le16(byte_count);
2166 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2167 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2169 cFYI(1, ("Send error in QuerySymLinkInfo = %d", rc));
2171 /* decode response */
2173 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
2174 if (rc || (pSMBr->ByteCount < 2))
2175 /* BB also check enough total bytes returned */
2176 rc = -EIO; /* bad smb */
2178 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
2179 __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
2181 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
2182 name_len = UniStrnlen((wchar_t *) ((char *)
2183 &pSMBr->hdr.Protocol +data_offset),
2184 min_t(const int, buflen,count) / 2);
2185 /* BB FIXME investigate remapping reserved chars here */
2186 cifs_strfromUCS_le(symlinkinfo,
2187 (__le16 *) ((char *)&pSMBr->hdr.Protocol +
2189 name_len, nls_codepage);
2191 strncpy(symlinkinfo,
2192 (char *) &pSMBr->hdr.Protocol +
2194 min_t(const int, buflen, count));
2196 symlinkinfo[buflen] = 0;
2197 /* just in case so calling code does not go off the end of buffer */
2200 cifs_buf_release(pSMB);
2202 goto querySymLinkRetry;
2206 /* Initialize NT TRANSACT SMB into small smb request buffer.
2207 This assumes that all NT TRANSACTS that we init here have
2208 total parm and data under about 400 bytes (to fit in small cifs
2209 buffer size), which is the case so far, it easily fits. NB:
2210 Setup words themselves and ByteCount
2211 MaxSetupCount (size of returned setup area) and
2212 MaxParameterCount (returned parms size) must be set by caller */
2214 smb_init_ntransact(const __u16 sub_command, const int setup_count,
2215 const int parm_len, struct cifsTconInfo *tcon,
2220 struct smb_com_ntransact_req * pSMB;
2222 rc = small_smb_init(SMB_COM_NT_TRANSACT, 19 + setup_count, tcon,
2226 *ret_buf = (void *)pSMB;
2228 pSMB->TotalParameterCount = cpu_to_le32(parm_len);
2229 pSMB->TotalDataCount = 0;
2230 pSMB->MaxDataCount = cpu_to_le32((tcon->ses->server->maxBuf -
2231 MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
2232 pSMB->ParameterCount = pSMB->TotalParameterCount;
2233 pSMB->DataCount = pSMB->TotalDataCount;
2234 temp_offset = offsetof(struct smb_com_ntransact_req, Parms) +
2235 (setup_count * 2) - 4 /* for rfc1001 length itself */;
2236 pSMB->ParameterOffset = cpu_to_le32(temp_offset);
2237 pSMB->DataOffset = cpu_to_le32(temp_offset + parm_len);
2238 pSMB->SetupCount = setup_count; /* no need to le convert byte fields */
2239 pSMB->SubCommand = cpu_to_le16(sub_command);
2244 validate_ntransact(char * buf, char ** ppparm, char ** ppdata,
2245 int * pdatalen, int * pparmlen)
2248 __u32 data_count, data_offset, parm_count, parm_offset;
2249 struct smb_com_ntransact_rsp * pSMBr;
2254 pSMBr = (struct smb_com_ntransact_rsp *)buf;
2256 /* ByteCount was converted from little endian in SendReceive */
2257 end_of_smb = 2 /* sizeof byte count */ + pSMBr->ByteCount +
2258 (char *)&pSMBr->ByteCount;
2261 data_offset = le32_to_cpu(pSMBr->DataOffset);
2262 data_count = le32_to_cpu(pSMBr->DataCount);
2263 parm_offset = le32_to_cpu(pSMBr->ParameterOffset);
2264 parm_count = le32_to_cpu(pSMBr->ParameterCount);
2266 *ppparm = (char *)&pSMBr->hdr.Protocol + parm_offset;
2267 *ppdata = (char *)&pSMBr->hdr.Protocol + data_offset;
2269 /* should we also check that parm and data areas do not overlap? */
2270 if(*ppparm > end_of_smb) {
2271 cFYI(1,("parms start after end of smb"));
2273 } else if(parm_count + *ppparm > end_of_smb) {
2274 cFYI(1,("parm end after end of smb"));
2276 } else if(*ppdata > end_of_smb) {
2277 cFYI(1,("data starts after end of smb"));
2279 } else if(data_count + *ppdata > end_of_smb) {
2280 cFYI(1,("data %p + count %d (%p) ends after end of smb %p start %p",
2281 *ppdata, data_count, (data_count + *ppdata), end_of_smb, pSMBr)); /* BB FIXME */
2283 } else if(parm_count + data_count > pSMBr->ByteCount) {
2284 cFYI(1,("parm count and data count larger than SMB"));
2291 CIFSSMBQueryReparseLinkInfo(const int xid, struct cifsTconInfo *tcon,
2292 const unsigned char *searchName,
2293 char *symlinkinfo, const int buflen,__u16 fid,
2294 const struct nls_table *nls_codepage)
2299 struct smb_com_transaction_ioctl_req * pSMB;
2300 struct smb_com_transaction_ioctl_rsp * pSMBr;
2302 cFYI(1, ("In Windows reparse style QueryLink for path %s", searchName));
2303 rc = smb_init(SMB_COM_NT_TRANSACT, 23, tcon, (void **) &pSMB,
2308 pSMB->TotalParameterCount = 0 ;
2309 pSMB->TotalDataCount = 0;
2310 pSMB->MaxParameterCount = cpu_to_le32(2);
2311 /* BB find exact data count max from sess structure BB */
2312 pSMB->MaxDataCount = cpu_to_le32((tcon->ses->server->maxBuf -
2313 MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
2314 pSMB->MaxSetupCount = 4;
2316 pSMB->ParameterOffset = 0;
2317 pSMB->DataCount = 0;
2318 pSMB->DataOffset = 0;
2319 pSMB->SetupCount = 4;
2320 pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_IOCTL);
2321 pSMB->ParameterCount = pSMB->TotalParameterCount;
2322 pSMB->FunctionCode = cpu_to_le32(FSCTL_GET_REPARSE_POINT);
2323 pSMB->IsFsctl = 1; /* FSCTL */
2324 pSMB->IsRootFlag = 0;
2325 pSMB->Fid = fid; /* file handle always le */
2326 pSMB->ByteCount = 0;
2328 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2329 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2331 cFYI(1, ("Send error in QueryReparseLinkInfo = %d", rc));
2332 } else { /* decode response */
2333 __u32 data_offset = le32_to_cpu(pSMBr->DataOffset);
2334 __u32 data_count = le32_to_cpu(pSMBr->DataCount);
2335 if ((pSMBr->ByteCount < 2) || (data_offset > 512))
2336 /* BB also check enough total bytes returned */
2337 rc = -EIO; /* bad smb */
2339 if(data_count && (data_count < 2048)) {
2340 char * end_of_smb = 2 /* sizeof byte count */ +
2342 (char *)&pSMBr->ByteCount;
2344 struct reparse_data * reparse_buf = (struct reparse_data *)
2345 ((char *)&pSMBr->hdr.Protocol + data_offset);
2346 if((char*)reparse_buf >= end_of_smb) {
2350 if((reparse_buf->LinkNamesBuf +
2351 reparse_buf->TargetNameOffset +
2352 reparse_buf->TargetNameLen) >
2354 cFYI(1,("reparse buf extended beyond SMB"));
2359 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
2360 name_len = UniStrnlen((wchar_t *)
2361 (reparse_buf->LinkNamesBuf +
2362 reparse_buf->TargetNameOffset),
2363 min(buflen/2, reparse_buf->TargetNameLen / 2));
2364 cifs_strfromUCS_le(symlinkinfo,
2365 (__le16 *) (reparse_buf->LinkNamesBuf +
2366 reparse_buf->TargetNameOffset),
2367 name_len, nls_codepage);
2368 } else { /* ASCII names */
2369 strncpy(symlinkinfo,reparse_buf->LinkNamesBuf +
2370 reparse_buf->TargetNameOffset,
2371 min_t(const int, buflen, reparse_buf->TargetNameLen));
2375 cFYI(1,("Invalid return data count on get reparse info ioctl"));
2377 symlinkinfo[buflen] = 0; /* just in case so the caller
2378 does not go off the end of the buffer */
2379 cFYI(1,("readlink result - %s",symlinkinfo));
2383 cifs_buf_release(pSMB);
2385 /* Note: On -EAGAIN error only caller can retry on handle based calls
2386 since file handle passed in no longer valid */
2391 #ifdef CONFIG_CIFS_POSIX
2393 /*Convert an Access Control Entry from wire format to local POSIX xattr format*/
2394 static void cifs_convert_ace(posix_acl_xattr_entry * ace, struct cifs_posix_ace * cifs_ace)
2396 /* u8 cifs fields do not need le conversion */
2397 ace->e_perm = cpu_to_le16(cifs_ace->cifs_e_perm);
2398 ace->e_tag = cpu_to_le16(cifs_ace->cifs_e_tag);
2399 ace->e_id = cpu_to_le32(le64_to_cpu(cifs_ace->cifs_uid));
2400 /* cFYI(1,("perm %d tag %d id %d",ace->e_perm,ace->e_tag,ace->e_id)); */
2405 /* Convert ACL from CIFS POSIX wire format to local Linux POSIX ACL xattr */
2406 static int cifs_copy_posix_acl(char * trgt,char * src, const int buflen,
2407 const int acl_type,const int size_of_data_area)
2412 struct cifs_posix_ace * pACE;
2413 struct cifs_posix_acl * cifs_acl = (struct cifs_posix_acl *)src;
2414 posix_acl_xattr_header * local_acl = (posix_acl_xattr_header *)trgt;
2416 if (le16_to_cpu(cifs_acl->version) != CIFS_ACL_VERSION)
2419 if(acl_type & ACL_TYPE_ACCESS) {
2420 count = le16_to_cpu(cifs_acl->access_entry_count);
2421 pACE = &cifs_acl->ace_array[0];
2422 size = sizeof(struct cifs_posix_acl);
2423 size += sizeof(struct cifs_posix_ace) * count;
2424 /* check if we would go beyond end of SMB */
2425 if(size_of_data_area < size) {
2426 cFYI(1,("bad CIFS POSIX ACL size %d vs. %d",size_of_data_area,size));
2429 } else if(acl_type & ACL_TYPE_DEFAULT) {
2430 count = le16_to_cpu(cifs_acl->access_entry_count);
2431 size = sizeof(struct cifs_posix_acl);
2432 size += sizeof(struct cifs_posix_ace) * count;
2433 /* skip past access ACEs to get to default ACEs */
2434 pACE = &cifs_acl->ace_array[count];
2435 count = le16_to_cpu(cifs_acl->default_entry_count);
2436 size += sizeof(struct cifs_posix_ace) * count;
2437 /* check if we would go beyond end of SMB */
2438 if(size_of_data_area < size)
2445 size = posix_acl_xattr_size(count);
2446 if((buflen == 0) || (local_acl == NULL)) {
2447 /* used to query ACL EA size */
2448 } else if(size > buflen) {
2450 } else /* buffer big enough */ {
2451 local_acl->a_version = cpu_to_le32(POSIX_ACL_XATTR_VERSION);
2452 for(i = 0;i < count ;i++) {
2453 cifs_convert_ace(&local_acl->a_entries[i],pACE);
2460 static __u16 convert_ace_to_cifs_ace(struct cifs_posix_ace * cifs_ace,
2461 const posix_acl_xattr_entry * local_ace)
2463 __u16 rc = 0; /* 0 = ACL converted ok */
2465 cifs_ace->cifs_e_perm = le16_to_cpu(local_ace->e_perm);
2466 cifs_ace->cifs_e_tag = le16_to_cpu(local_ace->e_tag);
2467 /* BB is there a better way to handle the large uid? */
2468 if(local_ace->e_id == cpu_to_le32(-1)) {
2469 /* Probably no need to le convert -1 on any arch but can not hurt */
2470 cifs_ace->cifs_uid = cpu_to_le64(-1);
2472 cifs_ace->cifs_uid = cpu_to_le64(le32_to_cpu(local_ace->e_id));
2473 /*cFYI(1,("perm %d tag %d id %d",ace->e_perm,ace->e_tag,ace->e_id));*/
2477 /* Convert ACL from local Linux POSIX xattr to CIFS POSIX ACL wire format */
2478 static __u16 ACL_to_cifs_posix(char * parm_data,const char * pACL,const int buflen,
2482 struct cifs_posix_acl * cifs_acl = (struct cifs_posix_acl *)parm_data;
2483 posix_acl_xattr_header * local_acl = (posix_acl_xattr_header *)pACL;
2487 if((buflen == 0) || (pACL == NULL) || (cifs_acl == NULL))
2490 count = posix_acl_xattr_count((size_t)buflen);
2491 cFYI(1,("setting acl with %d entries from buf of length %d and version of %d",
2492 count, buflen, le32_to_cpu(local_acl->a_version)));
2493 if(le32_to_cpu(local_acl->a_version) != 2) {
2494 cFYI(1,("unknown POSIX ACL version %d",
2495 le32_to_cpu(local_acl->a_version)));
2498 cifs_acl->version = cpu_to_le16(1);
2499 if(acl_type == ACL_TYPE_ACCESS)
2500 cifs_acl->access_entry_count = cpu_to_le16(count);
2501 else if(acl_type == ACL_TYPE_DEFAULT)
2502 cifs_acl->default_entry_count = cpu_to_le16(count);
2504 cFYI(1,("unknown ACL type %d",acl_type));
2507 for(i=0;i<count;i++) {
2508 rc = convert_ace_to_cifs_ace(&cifs_acl->ace_array[i],
2509 &local_acl->a_entries[i]);
2511 /* ACE not converted */
2516 rc = (__u16)(count * sizeof(struct cifs_posix_ace));
2517 rc += sizeof(struct cifs_posix_acl);
2518 /* BB add check to make sure ACL does not overflow SMB */
2524 CIFSSMBGetPosixACL(const int xid, struct cifsTconInfo *tcon,
2525 const unsigned char *searchName,
2526 char *acl_inf, const int buflen, const int acl_type,
2527 const struct nls_table *nls_codepage, int remap)
2529 /* SMB_QUERY_POSIX_ACL */
2530 TRANSACTION2_QPI_REQ *pSMB = NULL;
2531 TRANSACTION2_QPI_RSP *pSMBr = NULL;
2535 __u16 params, byte_count;
2537 cFYI(1, ("In GetPosixACL (Unix) for path %s", searchName));
2540 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2545 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2547 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
2548 PATH_MAX, nls_codepage, remap);
2549 name_len++; /* trailing null */
2551 pSMB->FileName[name_len] = 0;
2552 pSMB->FileName[name_len+1] = 0;
2553 } else { /* BB improve the check for buffer overruns BB */
2554 name_len = strnlen(searchName, PATH_MAX);
2555 name_len++; /* trailing null */
2556 strncpy(pSMB->FileName, searchName, name_len);
2559 params = 2 /* level */ + 4 /* rsrvd */ + name_len /* incl null */ ;
2560 pSMB->TotalDataCount = 0;
2561 pSMB->MaxParameterCount = cpu_to_le16(2);
2562 /* BB find exact max data count below from sess structure BB */
2563 pSMB->MaxDataCount = cpu_to_le16(4000);
2564 pSMB->MaxSetupCount = 0;
2568 pSMB->Reserved2 = 0;
2569 pSMB->ParameterOffset = cpu_to_le16(
2570 offsetof(struct smb_com_transaction2_qpi_req ,InformationLevel) - 4);
2571 pSMB->DataCount = 0;
2572 pSMB->DataOffset = 0;
2573 pSMB->SetupCount = 1;
2574 pSMB->Reserved3 = 0;
2575 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
2576 byte_count = params + 1 /* pad */ ;
2577 pSMB->TotalParameterCount = cpu_to_le16(params);
2578 pSMB->ParameterCount = pSMB->TotalParameterCount;
2579 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_POSIX_ACL);
2580 pSMB->Reserved4 = 0;
2581 pSMB->hdr.smb_buf_length += byte_count;
2582 pSMB->ByteCount = cpu_to_le16(byte_count);
2584 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2585 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2586 cifs_stats_inc(&tcon->num_acl_get);
2588 cFYI(1, ("Send error in Query POSIX ACL = %d", rc));
2590 /* decode response */
2592 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
2593 if (rc || (pSMBr->ByteCount < 2))
2594 /* BB also check enough total bytes returned */
2595 rc = -EIO; /* bad smb */
2597 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
2598 __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
2599 rc = cifs_copy_posix_acl(acl_inf,
2600 (char *)&pSMBr->hdr.Protocol+data_offset,
2601 buflen,acl_type,count);
2604 cifs_buf_release(pSMB);
2611 CIFSSMBSetPosixACL(const int xid, struct cifsTconInfo *tcon,
2612 const unsigned char *fileName,
2613 const char *local_acl, const int buflen,
2615 const struct nls_table *nls_codepage, int remap)
2617 struct smb_com_transaction2_spi_req *pSMB = NULL;
2618 struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
2622 int bytes_returned = 0;
2623 __u16 params, byte_count, data_count, param_offset, offset;
2625 cFYI(1, ("In SetPosixACL (Unix) for path %s", fileName));
2627 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2631 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2633 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
2634 PATH_MAX, nls_codepage, remap);
2635 name_len++; /* trailing null */
2637 } else { /* BB improve the check for buffer overruns BB */
2638 name_len = strnlen(fileName, PATH_MAX);
2639 name_len++; /* trailing null */
2640 strncpy(pSMB->FileName, fileName, name_len);
2642 params = 6 + name_len;
2643 pSMB->MaxParameterCount = cpu_to_le16(2);
2644 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB size from sess */
2645 pSMB->MaxSetupCount = 0;
2649 pSMB->Reserved2 = 0;
2650 param_offset = offsetof(struct smb_com_transaction2_spi_req,
2651 InformationLevel) - 4;
2652 offset = param_offset + params;
2653 parm_data = ((char *) &pSMB->hdr.Protocol) + offset;
2654 pSMB->ParameterOffset = cpu_to_le16(param_offset);
2656 /* convert to on the wire format for POSIX ACL */
2657 data_count = ACL_to_cifs_posix(parm_data,local_acl,buflen,acl_type);
2659 if(data_count == 0) {
2661 goto setACLerrorExit;
2663 pSMB->DataOffset = cpu_to_le16(offset);
2664 pSMB->SetupCount = 1;
2665 pSMB->Reserved3 = 0;
2666 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
2667 pSMB->InformationLevel = cpu_to_le16(SMB_SET_POSIX_ACL);
2668 byte_count = 3 /* pad */ + params + data_count;
2669 pSMB->DataCount = cpu_to_le16(data_count);
2670 pSMB->TotalDataCount = pSMB->DataCount;
2671 pSMB->ParameterCount = cpu_to_le16(params);
2672 pSMB->TotalParameterCount = pSMB->ParameterCount;
2673 pSMB->Reserved4 = 0;
2674 pSMB->hdr.smb_buf_length += byte_count;
2675 pSMB->ByteCount = cpu_to_le16(byte_count);
2676 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2677 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2679 cFYI(1, ("Set POSIX ACL returned %d", rc));
2683 cifs_buf_release(pSMB);
2689 /* BB fix tabs in this function FIXME BB */
2691 CIFSGetExtAttr(const int xid, struct cifsTconInfo *tcon,
2692 const int netfid, __u64 * pExtAttrBits, __u64 *pMask)
2695 struct smb_t2_qfi_req *pSMB = NULL;
2696 struct smb_t2_qfi_rsp *pSMBr = NULL;
2698 __u16 params, byte_count;
2700 cFYI(1,("In GetExtAttr"));
2705 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2710 params = 2 /* level */ +2 /* fid */;
2711 pSMB->t2.TotalDataCount = 0;
2712 pSMB->t2.MaxParameterCount = cpu_to_le16(4);
2713 /* BB find exact max data count below from sess structure BB */
2714 pSMB->t2.MaxDataCount = cpu_to_le16(4000);
2715 pSMB->t2.MaxSetupCount = 0;
2716 pSMB->t2.Reserved = 0;
2718 pSMB->t2.Timeout = 0;
2719 pSMB->t2.Reserved2 = 0;
2720 pSMB->t2.ParameterOffset = cpu_to_le16(offsetof(struct smb_t2_qfi_req,
2722 pSMB->t2.DataCount = 0;
2723 pSMB->t2.DataOffset = 0;
2724 pSMB->t2.SetupCount = 1;
2725 pSMB->t2.Reserved3 = 0;
2726 pSMB->t2.SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION);
2727 byte_count = params + 1 /* pad */ ;
2728 pSMB->t2.TotalParameterCount = cpu_to_le16(params);
2729 pSMB->t2.ParameterCount = pSMB->t2.TotalParameterCount;
2730 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_ATTR_FLAGS);
2733 pSMB->hdr.smb_buf_length += byte_count;
2734 pSMB->t2.ByteCount = cpu_to_le16(byte_count);
2736 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2737 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2739 cFYI(1, ("error %d in GetExtAttr", rc));
2741 /* decode response */
2742 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
2743 if (rc || (pSMBr->ByteCount < 2))
2744 /* BB also check enough total bytes returned */
2745 /* If rc should we check for EOPNOSUPP and
2746 disable the srvino flag? or in caller? */
2747 rc = -EIO; /* bad smb */
2749 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
2750 __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
2751 struct file_chattr_info * pfinfo;
2752 /* BB Do we need a cast or hash here ? */
2754 cFYI(1, ("Illegal size ret in GetExtAttr"));
2758 pfinfo = (struct file_chattr_info *)
2759 (data_offset + (char *) &pSMBr->hdr.Protocol);
2760 *pExtAttrBits = le64_to_cpu(pfinfo->mode);
2761 *pMask = le64_to_cpu(pfinfo->mask);
2765 cifs_buf_release(pSMB);
2767 goto GetExtAttrRetry;
2772 #endif /* CONFIG_POSIX */
2775 /* security id for everyone */
2776 const struct cifs_sid sid_everyone = {1, 1, {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0}};
2778 const struct cifs_sid sid_user = {1, 2 , {0, 0, 0, 0, 0, 5}, {32, 545, 0, 0}};
2780 /* Convert CIFS ACL to POSIX form */
2781 static int parse_sec_desc(struct cifs_sid * psec_desc, int acl_len)
2786 /* Get Security Descriptor (by handle) from remote server for a file or dir */
2788 CIFSSMBGetCIFSACL(const int xid, struct cifsTconInfo *tcon, __u16 fid,
2789 /* BB fix up return info */ char *acl_inf, const int buflen,
2790 const int acl_type /* ACCESS/DEFAULT not sure implication */)
2794 QUERY_SEC_DESC_REQ * pSMB;
2797 cFYI(1, ("GetCifsACL"));
2799 rc = smb_init_ntransact(NT_TRANSACT_QUERY_SECURITY_DESC, 0,
2800 8 /* parm len */, tcon, (void **) &pSMB);
2804 pSMB->MaxParameterCount = cpu_to_le32(4);
2805 /* BB TEST with big acls that might need to be e.g. larger than 16K */
2806 pSMB->MaxSetupCount = 0;
2807 pSMB->Fid = fid; /* file handle always le */
2808 pSMB->AclFlags = cpu_to_le32(CIFS_ACL_OWNER | CIFS_ACL_GROUP |
2810 pSMB->ByteCount = cpu_to_le16(11); /* 3 bytes pad + 8 bytes parm */
2811 pSMB->hdr.smb_buf_length += 11;
2812 iov[0].iov_base = (char *)pSMB;
2813 iov[0].iov_len = pSMB->hdr.smb_buf_length + 4;
2815 rc = SendReceive2(xid, tcon->ses, iov, 1 /* num iovec */, &buf_type, 0);
2816 cifs_stats_inc(&tcon->num_acl_get);
2818 cFYI(1, ("Send error in QuerySecDesc = %d", rc));
2819 } else { /* decode response */
2820 struct cifs_sid * psec_desc;
2825 struct smb_com_ntransact_rsp * pSMBr;
2827 /* validate_nttransact */
2828 rc = validate_ntransact(iov[0].iov_base, (char **)&parm,
2829 (char **)&psec_desc,
2830 &parm_len, &data_len);
2834 pSMBr = (struct smb_com_ntransact_rsp *)iov[0].iov_base;
2836 cERROR(1,("smb %p parm %p data %p",pSMBr,parm,psec_desc)); /* BB removeme BB */
2838 if (le32_to_cpu(pSMBr->ParameterCount) != 4) {
2839 rc = -EIO; /* bad smb */
2843 /* BB check that data area is minimum length and as big as acl_len */
2845 acl_len = le32_to_cpu(*(__le32 *)parm);
2846 /* BB check if(acl_len > bufsize) */
2848 parse_sec_desc(psec_desc, acl_len);
2851 if(buf_type == CIFS_SMALL_BUFFER)
2852 cifs_small_buf_release(iov[0].iov_base);
2853 else if(buf_type == CIFS_LARGE_BUFFER)
2854 cifs_buf_release(iov[0].iov_base);
2855 /* cifs_small_buf_release(pSMB); */ /* Freed earlier now in SendReceive2 */
2860 /* Legacy Query Path Information call for lookup to old servers such
2862 int SMBQueryInformation(const int xid, struct cifsTconInfo *tcon,
2863 const unsigned char *searchName,
2864 FILE_ALL_INFO * pFinfo,
2865 const struct nls_table *nls_codepage, int remap)
2867 QUERY_INFORMATION_REQ * pSMB;
2868 QUERY_INFORMATION_RSP * pSMBr;
2873 cFYI(1, ("In SMBQPath path %s", searchName));
2875 rc = smb_init(SMB_COM_QUERY_INFORMATION, 0, tcon, (void **) &pSMB,
2880 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2882 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
2883 PATH_MAX, nls_codepage, remap);
2884 name_len++; /* trailing null */
2887 name_len = strnlen(searchName, PATH_MAX);
2888 name_len++; /* trailing null */
2889 strncpy(pSMB->FileName, searchName, name_len);
2891 pSMB->BufferFormat = 0x04;
2892 name_len++; /* account for buffer type byte */
2893 pSMB->hdr.smb_buf_length += (__u16) name_len;
2894 pSMB->ByteCount = cpu_to_le16(name_len);
2896 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2897 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2899 cFYI(1, ("Send error in QueryInfo = %d", rc));
2900 } else if (pFinfo) { /* decode response */
2901 memset(pFinfo, 0, sizeof(FILE_ALL_INFO));
2902 pFinfo->AllocationSize =
2903 cpu_to_le64(le32_to_cpu(pSMBr->size));
2904 pFinfo->EndOfFile = pFinfo->AllocationSize;
2905 pFinfo->Attributes =
2906 cpu_to_le32(le16_to_cpu(pSMBr->attr));
2908 rc = -EIO; /* bad buffer passed in */
2910 cifs_buf_release(pSMB);
2922 CIFSSMBQPathInfo(const int xid, struct cifsTconInfo *tcon,
2923 const unsigned char *searchName,
2924 FILE_ALL_INFO * pFindData,
2925 const struct nls_table *nls_codepage, int remap)
2927 /* level 263 SMB_QUERY_FILE_ALL_INFO */
2928 TRANSACTION2_QPI_REQ *pSMB = NULL;
2929 TRANSACTION2_QPI_RSP *pSMBr = NULL;
2933 __u16 params, byte_count;
2935 /* cFYI(1, ("In QPathInfo path %s", searchName)); */
2937 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2942 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2944 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
2945 PATH_MAX, nls_codepage, remap);
2946 name_len++; /* trailing null */
2948 } else { /* BB improve the check for buffer overruns BB */
2949 name_len = strnlen(searchName, PATH_MAX);
2950 name_len++; /* trailing null */
2951 strncpy(pSMB->FileName, searchName, name_len);
2954 params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */ ;
2955 pSMB->TotalDataCount = 0;
2956 pSMB->MaxParameterCount = cpu_to_le16(2);
2957 pSMB->MaxDataCount = cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
2958 pSMB->MaxSetupCount = 0;
2962 pSMB->Reserved2 = 0;
2963 pSMB->ParameterOffset = cpu_to_le16(offsetof(
2964 struct smb_com_transaction2_qpi_req ,InformationLevel) - 4);
2965 pSMB->DataCount = 0;
2966 pSMB->DataOffset = 0;
2967 pSMB->SetupCount = 1;
2968 pSMB->Reserved3 = 0;
2969 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
2970 byte_count = params + 1 /* pad */ ;
2971 pSMB->TotalParameterCount = cpu_to_le16(params);
2972 pSMB->ParameterCount = pSMB->TotalParameterCount;
2973 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_ALL_INFO);
2974 pSMB->Reserved4 = 0;
2975 pSMB->hdr.smb_buf_length += byte_count;
2976 pSMB->ByteCount = cpu_to_le16(byte_count);
2978 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2979 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2981 cFYI(1, ("Send error in QPathInfo = %d", rc));
2982 } else { /* decode response */
2983 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
2985 if (rc || (pSMBr->ByteCount < 40))
2986 rc = -EIO; /* bad smb */
2987 else if (pFindData){
2988 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
2989 memcpy((char *) pFindData,
2990 (char *) &pSMBr->hdr.Protocol +
2991 data_offset, sizeof (FILE_ALL_INFO));
2995 cifs_buf_release(pSMB);
2997 goto QPathInfoRetry;
3003 CIFSSMBUnixQPathInfo(const int xid, struct cifsTconInfo *tcon,
3004 const unsigned char *searchName,
3005 FILE_UNIX_BASIC_INFO * pFindData,
3006 const struct nls_table *nls_codepage, int remap)
3008 /* SMB_QUERY_FILE_UNIX_BASIC */
3009 TRANSACTION2_QPI_REQ *pSMB = NULL;
3010 TRANSACTION2_QPI_RSP *pSMBr = NULL;
3012 int bytes_returned = 0;
3014 __u16 params, byte_count;
3016 cFYI(1, ("In QPathInfo (Unix) the path %s", searchName));
3018 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3023 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3025 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
3026 PATH_MAX, nls_codepage, remap);
3027 name_len++; /* trailing null */
3029 } else { /* BB improve the check for buffer overruns BB */
3030 name_len = strnlen(searchName, PATH_MAX);
3031 name_len++; /* trailing null */
3032 strncpy(pSMB->FileName, searchName, name_len);
3035 params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */ ;
3036 pSMB->TotalDataCount = 0;
3037 pSMB->MaxParameterCount = cpu_to_le16(2);
3038 /* BB find exact max SMB PDU from sess structure BB */
3039 pSMB->MaxDataCount = cpu_to_le16(4000);
3040 pSMB->MaxSetupCount = 0;
3044 pSMB->Reserved2 = 0;
3045 pSMB->ParameterOffset = cpu_to_le16(offsetof(
3046 struct smb_com_transaction2_qpi_req ,InformationLevel) - 4);
3047 pSMB->DataCount = 0;
3048 pSMB->DataOffset = 0;
3049 pSMB->SetupCount = 1;
3050 pSMB->Reserved3 = 0;
3051 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
3052 byte_count = params + 1 /* pad */ ;
3053 pSMB->TotalParameterCount = cpu_to_le16(params);
3054 pSMB->ParameterCount = pSMB->TotalParameterCount;
3055 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC);
3056 pSMB->Reserved4 = 0;
3057 pSMB->hdr.smb_buf_length += byte_count;
3058 pSMB->ByteCount = cpu_to_le16(byte_count);
3060 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3061 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3063 cFYI(1, ("Send error in QPathInfo = %d", rc));
3064 } else { /* decode response */
3065 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3067 if (rc || (pSMBr->ByteCount < sizeof(FILE_UNIX_BASIC_INFO))) {
3068 rc = -EIO; /* bad smb */
3070 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3071 memcpy((char *) pFindData,
3072 (char *) &pSMBr->hdr.Protocol +
3074 sizeof (FILE_UNIX_BASIC_INFO));
3077 cifs_buf_release(pSMB);
3079 goto UnixQPathInfoRetry;
3084 #if 0 /* function unused at present */
3085 int CIFSFindSingle(const int xid, struct cifsTconInfo *tcon,
3086 const char *searchName, FILE_ALL_INFO * findData,
3087 const struct nls_table *nls_codepage)
3089 /* level 257 SMB_ */
3090 TRANSACTION2_FFIRST_REQ *pSMB = NULL;
3091 TRANSACTION2_FFIRST_RSP *pSMBr = NULL;
3095 __u16 params, byte_count;
3097 cFYI(1, ("In FindUnique"));
3099 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3104 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3106 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName, PATH_MAX
3107 /* find define for this maxpathcomponent */
3109 name_len++; /* trailing null */
3111 } else { /* BB improve the check for buffer overruns BB */
3112 name_len = strnlen(searchName, PATH_MAX);
3113 name_len++; /* trailing null */
3114 strncpy(pSMB->FileName, searchName, name_len);
3117 params = 12 + name_len /* includes null */ ;
3118 pSMB->TotalDataCount = 0; /* no EAs */
3119 pSMB->MaxParameterCount = cpu_to_le16(2);
3120 pSMB->MaxDataCount = cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
3121 pSMB->MaxSetupCount = 0;
3125 pSMB->Reserved2 = 0;
3126 pSMB->ParameterOffset = cpu_to_le16(
3127 offsetof(struct smb_com_transaction2_ffirst_req,InformationLevel) - 4);
3128 pSMB->DataCount = 0;
3129 pSMB->DataOffset = 0;
3130 pSMB->SetupCount = 1; /* one byte, no need to le convert */
3131 pSMB->Reserved3 = 0;
3132 pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_FIRST);
3133 byte_count = params + 1 /* pad */ ;
3134 pSMB->TotalParameterCount = cpu_to_le16(params);
3135 pSMB->ParameterCount = pSMB->TotalParameterCount;
3136 pSMB->SearchAttributes =
3137 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
3139 pSMB->SearchCount = cpu_to_le16(16); /* BB increase */
3140 pSMB->SearchFlags = cpu_to_le16(1);
3141 pSMB->InformationLevel = cpu_to_le16(SMB_FIND_FILE_DIRECTORY_INFO);
3142 pSMB->SearchStorageType = 0; /* BB what should we set this to? BB */
3143 pSMB->hdr.smb_buf_length += byte_count;
3144 pSMB->ByteCount = cpu_to_le16(byte_count);
3146 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3147 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3150 cFYI(1, ("Send error in FindFileDirInfo = %d", rc));
3151 } else { /* decode response */
3152 cifs_stats_inc(&tcon->num_ffirst);
3156 cifs_buf_release(pSMB);
3158 goto findUniqueRetry;
3162 #endif /* end unused (temporarily) function */
3164 /* xid, tcon, searchName and codepage are input parms, rest are returned */
3166 CIFSFindFirst(const int xid, struct cifsTconInfo *tcon,
3167 const char *searchName,
3168 const struct nls_table *nls_codepage,
3170 struct cifs_search_info * psrch_inf, int remap, const char dirsep)
3172 /* level 257 SMB_ */
3173 TRANSACTION2_FFIRST_REQ *pSMB = NULL;
3174 TRANSACTION2_FFIRST_RSP *pSMBr = NULL;
3175 T2_FFIRST_RSP_PARMS * parms;
3177 int bytes_returned = 0;
3179 __u16 params, byte_count;
3181 cFYI(1, ("In FindFirst for %s",searchName));
3184 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3189 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3191 cifsConvertToUCS((__le16 *) pSMB->FileName,searchName,
3192 PATH_MAX, nls_codepage, remap);
3193 /* We can not add the asterik earlier in case
3194 it got remapped to 0xF03A as if it were part of the
3195 directory name instead of a wildcard */
3197 pSMB->FileName[name_len] = dirsep;
3198 pSMB->FileName[name_len+1] = 0;
3199 pSMB->FileName[name_len+2] = '*';
3200 pSMB->FileName[name_len+3] = 0;
3201 name_len += 4; /* now the trailing null */
3202 pSMB->FileName[name_len] = 0; /* null terminate just in case */
3203 pSMB->FileName[name_len+1] = 0;
3205 } else { /* BB add check for overrun of SMB buf BB */
3206 name_len = strnlen(searchName, PATH_MAX);
3207 /* BB fix here and in unicode clause above ie
3208 if(name_len > buffersize-header)
3209 free buffer exit; BB */
3210 strncpy(pSMB->FileName, searchName, name_len);
3211 pSMB->FileName[name_len] = dirsep;
3212 pSMB->FileName[name_len+1] = '*';
3213 pSMB->FileName[name_len+2] = 0;
3217 params = 12 + name_len /* includes null */ ;
3218 pSMB->TotalDataCount = 0; /* no EAs */
3219 pSMB->MaxParameterCount = cpu_to_le16(10);
3220 pSMB->MaxDataCount = cpu_to_le16((tcon->ses->server->maxBuf -
3221 MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
3222 pSMB->MaxSetupCount = 0;
3226 pSMB->Reserved2 = 0;
3227 byte_count = params + 1 /* pad */ ;
3228 pSMB->TotalParameterCount = cpu_to_le16(params);
3229 pSMB->ParameterCount = pSMB->TotalParameterCount;
3230 pSMB->ParameterOffset = cpu_to_le16(
3231 offsetof(struct smb_com_transaction2_ffirst_req, SearchAttributes)
3233 pSMB->DataCount = 0;
3234 pSMB->DataOffset = 0;
3235 pSMB->SetupCount = 1; /* one byte, no need to make endian neutral */
3236 pSMB->Reserved3 = 0;
3237 pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_FIRST);
3238 pSMB->SearchAttributes =
3239 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
3241 pSMB->SearchCount= cpu_to_le16(CIFSMaxBufSize/sizeof(FILE_UNIX_INFO));
3242 pSMB->SearchFlags = cpu_to_le16(CIFS_SEARCH_CLOSE_AT_END |
3243 CIFS_SEARCH_RETURN_RESUME);
3244 pSMB->InformationLevel = cpu_to_le16(psrch_inf->info_level);
3246 /* BB what should we set StorageType to? Does it matter? BB */
3247 pSMB->SearchStorageType = 0;
3248 pSMB->hdr.smb_buf_length += byte_count;
3249 pSMB->ByteCount = cpu_to_le16(byte_count);
3251 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3252 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3253 cifs_stats_inc(&tcon->num_ffirst);
3255 if (rc) {/* BB add logic to retry regular search if Unix search
3256 rejected unexpectedly by server */
3257 /* BB Add code to handle unsupported level rc */
3258 cFYI(1, ("Error in FindFirst = %d", rc));
3260 cifs_buf_release(pSMB);
3262 /* BB eventually could optimize out free and realloc of buf */
3265 goto findFirstRetry;
3266 } else { /* decode response */
3267 /* BB remember to free buffer if error BB */
3268 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3270 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
3271 psrch_inf->unicode = TRUE;
3273 psrch_inf->unicode = FALSE;
3275 psrch_inf->ntwrk_buf_start = (char *)pSMBr;
3276 psrch_inf->smallBuf = 0;
3277 psrch_inf->srch_entries_start =
3278 (char *) &pSMBr->hdr.Protocol +
3279 le16_to_cpu(pSMBr->t2.DataOffset);
3280 parms = (T2_FFIRST_RSP_PARMS *)((char *) &pSMBr->hdr.Protocol +
3281 le16_to_cpu(pSMBr->t2.ParameterOffset));
3283 if(parms->EndofSearch)
3284 psrch_inf->endOfSearch = TRUE;
3286 psrch_inf->endOfSearch = FALSE;
3288 psrch_inf->entries_in_buffer = le16_to_cpu(parms->SearchCount);
3289 psrch_inf->index_of_last_entry = 2 /* skip . and .. */ +
3290 psrch_inf->entries_in_buffer;
3291 *pnetfid = parms->SearchHandle;
3293 cifs_buf_release(pSMB);
3300 int CIFSFindNext(const int xid, struct cifsTconInfo *tcon,
3301 __u16 searchHandle, struct cifs_search_info * psrch_inf)
3303 TRANSACTION2_FNEXT_REQ *pSMB = NULL;
3304 TRANSACTION2_FNEXT_RSP *pSMBr = NULL;
3305 T2_FNEXT_RSP_PARMS * parms;
3306 char *response_data;
3308 int bytes_returned, name_len;
3309 __u16 params, byte_count;
3311 cFYI(1, ("In FindNext"));
3313 if(psrch_inf->endOfSearch == TRUE)
3316 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3321 params = 14; /* includes 2 bytes of null string, converted to LE below */
3323 pSMB->TotalDataCount = 0; /* no EAs */
3324 pSMB->MaxParameterCount = cpu_to_le16(8);
3325 pSMB->MaxDataCount =
3326 cpu_to_le16((tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
3327 pSMB->MaxSetupCount = 0;
3331 pSMB->Reserved2 = 0;
3332 pSMB->ParameterOffset = cpu_to_le16(
3333 offsetof(struct smb_com_transaction2_fnext_req,SearchHandle) - 4);
3334 pSMB->DataCount = 0;
3335 pSMB->DataOffset = 0;
3336 pSMB->SetupCount = 1;
3337 pSMB->Reserved3 = 0;
3338 pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_NEXT);
3339 pSMB->SearchHandle = searchHandle; /* always kept as le */
3341 cpu_to_le16(CIFSMaxBufSize / sizeof (FILE_UNIX_INFO));
3342 /* test for Unix extensions */
3343 /* if (tcon->ses->capabilities & CAP_UNIX) {
3344 pSMB->InformationLevel = cpu_to_le16(SMB_FIND_FILE_UNIX);
3345 psrch_inf->info_level = SMB_FIND_FILE_UNIX;
3347 pSMB->InformationLevel =
3348 cpu_to_le16(SMB_FIND_FILE_DIRECTORY_INFO);
3349 psrch_inf->info_level = SMB_FIND_FILE_DIRECTORY_INFO;
3351 pSMB->InformationLevel = cpu_to_le16(psrch_inf->info_level);
3352 pSMB->ResumeKey = psrch_inf->resume_key;
3354 cpu_to_le16(CIFS_SEARCH_CLOSE_AT_END | CIFS_SEARCH_RETURN_RESUME);
3356 name_len = psrch_inf->resume_name_len;
3358 if(name_len < PATH_MAX) {
3359 memcpy(pSMB->ResumeFileName, psrch_inf->presume_name, name_len);
3360 byte_count += name_len;
3361 /* 14 byte parm len above enough for 2 byte null terminator */
3362 pSMB->ResumeFileName[name_len] = 0;
3363 pSMB->ResumeFileName[name_len+1] = 0;
3366 goto FNext2_err_exit;
3368 byte_count = params + 1 /* pad */ ;
3369 pSMB->TotalParameterCount = cpu_to_le16(params);
3370 pSMB->ParameterCount = pSMB->TotalParameterCount;
3371 pSMB->hdr.smb_buf_length += byte_count;
3372 pSMB->ByteCount = cpu_to_le16(byte_count);
3374 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3375 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3376 cifs_stats_inc(&tcon->num_fnext);
3379 psrch_inf->endOfSearch = TRUE;
3380 rc = 0; /* search probably was closed at end of search above */
3382 cFYI(1, ("FindNext returned = %d", rc));
3383 } else { /* decode response */
3384 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3387 /* BB fixme add lock for file (srch_info) struct here */
3388 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
3389 psrch_inf->unicode = TRUE;
3391 psrch_inf->unicode = FALSE;
3392 response_data = (char *) &pSMBr->hdr.Protocol +
3393 le16_to_cpu(pSMBr->t2.ParameterOffset);
3394 parms = (T2_FNEXT_RSP_PARMS *)response_data;
3395 response_data = (char *)&pSMBr->hdr.Protocol +
3396 le16_to_cpu(pSMBr->t2.DataOffset);
3397 if(psrch_inf->smallBuf)
3398 cifs_small_buf_release(
3399 psrch_inf->ntwrk_buf_start);
3401 cifs_buf_release(psrch_inf->ntwrk_buf_start);
3402 psrch_inf->srch_entries_start = response_data;
3403 psrch_inf->ntwrk_buf_start = (char *)pSMB;
3404 psrch_inf->smallBuf = 0;
3405 if(parms->EndofSearch)
3406 psrch_inf->endOfSearch = TRUE;
3408 psrch_inf->endOfSearch = FALSE;
3410 psrch_inf->entries_in_buffer = le16_to_cpu(parms->SearchCount);
3411 psrch_inf->index_of_last_entry +=
3412 psrch_inf->entries_in_buffer;
3413 /* cFYI(1,("fnxt2 entries in buf %d index_of_last %d",psrch_inf->entries_in_buffer,psrch_inf->index_of_last_entry)); */
3415 /* BB fixme add unlock here */
3420 /* BB On error, should we leave previous search buf (and count and
3421 last entry fields) intact or free the previous one? */
3423 /* Note: On -EAGAIN error only caller can retry on handle based calls
3424 since file handle passed in no longer valid */
3427 cifs_buf_release(pSMB);
3433 CIFSFindClose(const int xid, struct cifsTconInfo *tcon, const __u16 searchHandle)
3436 FINDCLOSE_REQ *pSMB = NULL;
3437 CLOSE_RSP *pSMBr = NULL; /* BB removeme BB */
3440 cFYI(1, ("In CIFSSMBFindClose"));
3441 rc = small_smb_init(SMB_COM_FIND_CLOSE2, 1, tcon, (void **)&pSMB);
3443 /* no sense returning error if session restarted
3444 as file handle has been closed */
3450 pSMBr = (CLOSE_RSP *)pSMB; /* BB removeme BB */
3451 pSMB->FileID = searchHandle;
3452 pSMB->ByteCount = 0;
3453 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3454 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3456 cERROR(1, ("Send error in FindClose = %d", rc));
3458 cifs_stats_inc(&tcon->num_fclose);
3459 cifs_small_buf_release(pSMB);
3461 /* Since session is dead, search handle closed on server already */
3469 CIFSGetSrvInodeNumber(const int xid, struct cifsTconInfo *tcon,
3470 const unsigned char *searchName,
3471 __u64 * inode_number,
3472 const struct nls_table *nls_codepage, int remap)
3475 TRANSACTION2_QPI_REQ *pSMB = NULL;
3476 TRANSACTION2_QPI_RSP *pSMBr = NULL;
3477 int name_len, bytes_returned;
3478 __u16 params, byte_count;
3480 cFYI(1,("In GetSrvInodeNum for %s",searchName));
3484 GetInodeNumberRetry:
3485 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3491 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3493 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
3494 PATH_MAX,nls_codepage, remap);
3495 name_len++; /* trailing null */
3497 } else { /* BB improve the check for buffer overruns BB */
3498 name_len = strnlen(searchName, PATH_MAX);
3499 name_len++; /* trailing null */
3500 strncpy(pSMB->FileName, searchName, name_len);
3503 params = 2 /* level */ + 4 /* rsrvd */ + name_len /* incl null */ ;
3504 pSMB->TotalDataCount = 0;
3505 pSMB->MaxParameterCount = cpu_to_le16(2);
3506 /* BB find exact max data count below from sess structure BB */
3507 pSMB->MaxDataCount = cpu_to_le16(4000);
3508 pSMB->MaxSetupCount = 0;
3512 pSMB->Reserved2 = 0;
3513 pSMB->ParameterOffset = cpu_to_le16(offsetof(
3514 struct smb_com_transaction2_qpi_req ,InformationLevel) - 4);
3515 pSMB->DataCount = 0;
3516 pSMB->DataOffset = 0;
3517 pSMB->SetupCount = 1;
3518 pSMB->Reserved3 = 0;
3519 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
3520 byte_count = params + 1 /* pad */ ;
3521 pSMB->TotalParameterCount = cpu_to_le16(params);
3522 pSMB->ParameterCount = pSMB->TotalParameterCount;
3523 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_INTERNAL_INFO);
3524 pSMB->Reserved4 = 0;
3525 pSMB->hdr.smb_buf_length += byte_count;
3526 pSMB->ByteCount = cpu_to_le16(byte_count);
3528 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3529 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3531 cFYI(1, ("error %d in QueryInternalInfo", rc));
3533 /* decode response */
3534 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3535 if (rc || (pSMBr->ByteCount < 2))
3536 /* BB also check enough total bytes returned */
3537 /* If rc should we check for EOPNOSUPP and
3538 disable the srvino flag? or in caller? */
3539 rc = -EIO; /* bad smb */
3541 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3542 __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
3543 struct file_internal_info * pfinfo;
3544 /* BB Do we need a cast or hash here ? */
3546 cFYI(1, ("Illegal size ret in QryIntrnlInf"));
3548 goto GetInodeNumOut;
3550 pfinfo = (struct file_internal_info *)
3551 (data_offset + (char *) &pSMBr->hdr.Protocol);
3552 *inode_number = pfinfo->UniqueId;
3556 cifs_buf_release(pSMB);
3558 goto GetInodeNumberRetry;
3563 CIFSGetDFSRefer(const int xid, struct cifsSesInfo *ses,
3564 const unsigned char *searchName,
3565 unsigned char **targetUNCs,
3566 unsigned int *number_of_UNC_in_array,
3567 const struct nls_table *nls_codepage, int remap)
3569 /* TRANS2_GET_DFS_REFERRAL */
3570 TRANSACTION2_GET_DFS_REFER_REQ *pSMB = NULL;
3571 TRANSACTION2_GET_DFS_REFER_RSP *pSMBr = NULL;
3572 struct dfs_referral_level_3 * referrals = NULL;
3578 __u16 params, byte_count;
3579 *number_of_UNC_in_array = 0;
3582 cFYI(1, ("In GetDFSRefer the path %s", searchName));
3586 rc = smb_init(SMB_COM_TRANSACTION2, 15, NULL, (void **) &pSMB,
3591 /* server pointer checked in called function,
3592 but should never be null here anyway */
3593 pSMB->hdr.Mid = GetNextMid(ses->server);
3594 pSMB->hdr.Tid = ses->ipc_tid;
3595 pSMB->hdr.Uid = ses->Suid;
3596 if (ses->capabilities & CAP_STATUS32) {
3597 pSMB->hdr.Flags2 |= SMBFLG2_ERR_STATUS;
3599 if (ses->capabilities & CAP_DFS) {
3600 pSMB->hdr.Flags2 |= SMBFLG2_DFS;
3603 if (ses->capabilities & CAP_UNICODE) {
3604 pSMB->hdr.Flags2 |= SMBFLG2_UNICODE;
3606 cifsConvertToUCS((__le16 *) pSMB->RequestFileName,
3607 searchName, PATH_MAX, nls_codepage, remap);
3608 name_len++; /* trailing null */
3610 } else { /* BB improve the check for buffer overruns BB */
3611 name_len = strnlen(searchName, PATH_MAX);
3612 name_len++; /* trailing null */
3613 strncpy(pSMB->RequestFileName, searchName, name_len);
3616 params = 2 /* level */ + name_len /*includes null */ ;
3617 pSMB->TotalDataCount = 0;
3618 pSMB->DataCount = 0;
3619 pSMB->DataOffset = 0;
3620 pSMB->MaxParameterCount = 0;
3621 pSMB->MaxDataCount = cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
3622 pSMB->MaxSetupCount = 0;
3626 pSMB->Reserved2 = 0;
3627 pSMB->ParameterOffset = cpu_to_le16(offsetof(
3628 struct smb_com_transaction2_get_dfs_refer_req, MaxReferralLevel) - 4);
3629 pSMB->SetupCount = 1;
3630 pSMB->Reserved3 = 0;
3631 pSMB->SubCommand = cpu_to_le16(TRANS2_GET_DFS_REFERRAL);
3632 byte_count = params + 3 /* pad */ ;
3633 pSMB->ParameterCount = cpu_to_le16(params);
3634 pSMB->TotalParameterCount = pSMB->ParameterCount;
3635 pSMB->MaxReferralLevel = cpu_to_le16(3);
3636 pSMB->hdr.smb_buf_length += byte_count;
3637 pSMB->ByteCount = cpu_to_le16(byte_count);
3639 rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB,
3640 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3642 cFYI(1, ("Send error in GetDFSRefer = %d", rc));
3643 } else { /* decode response */
3644 /* BB Add logic to parse referrals here */
3645 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3647 if (rc || (pSMBr->ByteCount < 17)) /* BB also check enough total bytes returned */
3648 rc = -EIO; /* bad smb */
3650 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3651 __u16 data_count = le16_to_cpu(pSMBr->t2.DataCount);
3654 ("Decoding GetDFSRefer response. BCC: %d Offset %d",
3655 pSMBr->ByteCount, data_offset));
3657 (struct dfs_referral_level_3 *)
3658 (8 /* sizeof start of data block */ +
3660 (char *) &pSMBr->hdr.Protocol);
3661 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",
3662 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)));
3663 /* BB This field is actually two bytes in from start of
3664 data block so we could do safety check that DataBlock
3665 begins at address of pSMBr->NumberOfReferrals */
3666 *number_of_UNC_in_array = le16_to_cpu(pSMBr->NumberOfReferrals);
3668 /* BB Fix below so can return more than one referral */
3669 if(*number_of_UNC_in_array > 1)
3670 *number_of_UNC_in_array = 1;
3672 /* get the length of the strings describing refs */
3674 for(i=0;i<*number_of_UNC_in_array;i++) {
3675 /* make sure that DfsPathOffset not past end */
3676 __u16 offset = le16_to_cpu(referrals->DfsPathOffset);
3677 if (offset > data_count) {
3678 /* if invalid referral, stop here and do
3679 not try to copy any more */
3680 *number_of_UNC_in_array = i;
3683 temp = ((char *)referrals) + offset;
3685 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
3686 name_len += UniStrnlen((wchar_t *)temp,data_count);
3688 name_len += strnlen(temp,data_count);
3691 /* BB add check that referral pointer does not fall off end PDU */
3694 /* BB add check for name_len bigger than bcc */
3696 kmalloc(name_len+1+ (*number_of_UNC_in_array),GFP_KERNEL);
3697 if(*targetUNCs == NULL) {
3701 /* copy the ref strings */
3703 (struct dfs_referral_level_3 *)
3704 (8 /* sizeof data hdr */ +
3706 (char *) &pSMBr->hdr.Protocol);
3708 for(i=0;i<*number_of_UNC_in_array;i++) {
3709 temp = ((char *)referrals) + le16_to_cpu(referrals->DfsPathOffset);
3710 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
3711 cifs_strfromUCS_le(*targetUNCs,
3712 (__le16 *) temp, name_len, nls_codepage);
3714 strncpy(*targetUNCs,temp,name_len);
3716 /* BB update target_uncs pointers */
3726 cifs_buf_release(pSMB);
3734 /* Query File System Info such as free space to old servers such as Win 9x */
3736 SMBOldQFSInfo(const int xid, struct cifsTconInfo *tcon, struct kstatfs *FSData)
3738 /* level 0x01 SMB_QUERY_FILE_SYSTEM_INFO */
3739 TRANSACTION2_QFSI_REQ *pSMB = NULL;
3740 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
3741 FILE_SYSTEM_ALLOC_INFO *response_data;
3743 int bytes_returned = 0;
3744 __u16 params, byte_count;
3746 cFYI(1, ("OldQFSInfo"));
3748 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3752 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3757 params = 2; /* level */
3758 pSMB->TotalDataCount = 0;
3759 pSMB->MaxParameterCount = cpu_to_le16(2);
3760 pSMB->MaxDataCount = cpu_to_le16(1000);
3761 pSMB->MaxSetupCount = 0;
3765 pSMB->Reserved2 = 0;
3766 byte_count = params + 1 /* pad */ ;
3767 pSMB->TotalParameterCount = cpu_to_le16(params);
3768 pSMB->ParameterCount = pSMB->TotalParameterCount;
3769 pSMB->ParameterOffset = cpu_to_le16(offsetof(
3770 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
3771 pSMB->DataCount = 0;
3772 pSMB->DataOffset = 0;
3773 pSMB->SetupCount = 1;
3774 pSMB->Reserved3 = 0;
3775 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
3776 pSMB->InformationLevel = cpu_to_le16(SMB_INFO_ALLOCATION);
3777 pSMB->hdr.smb_buf_length += byte_count;
3778 pSMB->ByteCount = cpu_to_le16(byte_count);
3780 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3781 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3783 cFYI(1, ("Send error in QFSInfo = %d", rc));
3784 } else { /* decode response */
3785 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3787 if (rc || (pSMBr->ByteCount < 18))
3788 rc = -EIO; /* bad smb */
3790 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3791 cFYI(1,("qfsinf resp BCC: %d Offset %d",
3792 pSMBr->ByteCount, data_offset));
3795 (FILE_SYSTEM_ALLOC_INFO *)
3796 (((char *) &pSMBr->hdr.Protocol) + data_offset);
3798 le16_to_cpu(response_data->BytesPerSector) *
3799 le32_to_cpu(response_data->
3800 SectorsPerAllocationUnit);
3802 le32_to_cpu(response_data->TotalAllocationUnits);
3803 FSData->f_bfree = FSData->f_bavail =
3804 le32_to_cpu(response_data->FreeAllocationUnits);
3806 ("Blocks: %lld Free: %lld Block size %ld",
3807 (unsigned long long)FSData->f_blocks,
3808 (unsigned long long)FSData->f_bfree,
3812 cifs_buf_release(pSMB);
3815 goto oldQFSInfoRetry;
3821 CIFSSMBQFSInfo(const int xid, struct cifsTconInfo *tcon, struct kstatfs *FSData)
3823 /* level 0x103 SMB_QUERY_FILE_SYSTEM_INFO */
3824 TRANSACTION2_QFSI_REQ *pSMB = NULL;
3825 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
3826 FILE_SYSTEM_INFO *response_data;
3828 int bytes_returned = 0;
3829 __u16 params, byte_count;
3831 cFYI(1, ("In QFSInfo"));
3833 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3838 params = 2; /* level */
3839 pSMB->TotalDataCount = 0;
3840 pSMB->MaxParameterCount = cpu_to_le16(2);
3841 pSMB->MaxDataCount = cpu_to_le16(1000);
3842 pSMB->MaxSetupCount = 0;
3846 pSMB->Reserved2 = 0;
3847 byte_count = params + 1 /* pad */ ;
3848 pSMB->TotalParameterCount = cpu_to_le16(params);
3849 pSMB->ParameterCount = pSMB->TotalParameterCount;
3850 pSMB->ParameterOffset = cpu_to_le16(offsetof(
3851 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
3852 pSMB->DataCount = 0;
3853 pSMB->DataOffset = 0;
3854 pSMB->SetupCount = 1;
3855 pSMB->Reserved3 = 0;
3856 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
3857 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_SIZE_INFO);
3858 pSMB->hdr.smb_buf_length += byte_count;
3859 pSMB->ByteCount = cpu_to_le16(byte_count);
3861 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3862 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3864 cFYI(1, ("Send error in QFSInfo = %d", rc));
3865 } else { /* decode response */
3866 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3868 if (rc || (pSMBr->ByteCount < 24))
3869 rc = -EIO; /* bad smb */
3871 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3875 *) (((char *) &pSMBr->hdr.Protocol) +
3878 le32_to_cpu(response_data->BytesPerSector) *
3879 le32_to_cpu(response_data->
3880 SectorsPerAllocationUnit);
3882 le64_to_cpu(response_data->TotalAllocationUnits);
3883 FSData->f_bfree = FSData->f_bavail =
3884 le64_to_cpu(response_data->FreeAllocationUnits);
3886 ("Blocks: %lld Free: %lld Block size %ld",
3887 (unsigned long long)FSData->f_blocks,
3888 (unsigned long long)FSData->f_bfree,
3892 cifs_buf_release(pSMB);
3901 CIFSSMBQFSAttributeInfo(const int xid, struct cifsTconInfo *tcon)
3903 /* level 0x105 SMB_QUERY_FILE_SYSTEM_INFO */
3904 TRANSACTION2_QFSI_REQ *pSMB = NULL;
3905 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
3906 FILE_SYSTEM_ATTRIBUTE_INFO *response_data;
3908 int bytes_returned = 0;
3909 __u16 params, byte_count;
3911 cFYI(1, ("In QFSAttributeInfo"));
3913 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3918 params = 2; /* level */
3919 pSMB->TotalDataCount = 0;
3920 pSMB->MaxParameterCount = cpu_to_le16(2);
3921 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
3922 pSMB->MaxSetupCount = 0;
3926 pSMB->Reserved2 = 0;
3927 byte_count = params + 1 /* pad */ ;
3928 pSMB->TotalParameterCount = cpu_to_le16(params);
3929 pSMB->ParameterCount = pSMB->TotalParameterCount;
3930 pSMB->ParameterOffset = cpu_to_le16(offsetof(
3931 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
3932 pSMB->DataCount = 0;
3933 pSMB->DataOffset = 0;
3934 pSMB->SetupCount = 1;
3935 pSMB->Reserved3 = 0;
3936 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
3937 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_ATTRIBUTE_INFO);
3938 pSMB->hdr.smb_buf_length += byte_count;
3939 pSMB->ByteCount = cpu_to_le16(byte_count);
3941 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3942 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3944 cERROR(1, ("Send error in QFSAttributeInfo = %d", rc));
3945 } else { /* decode response */
3946 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3948 if (rc || (pSMBr->ByteCount < 13)) { /* BB also check enough bytes returned */
3949 rc = -EIO; /* bad smb */
3951 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3953 (FILE_SYSTEM_ATTRIBUTE_INFO
3954 *) (((char *) &pSMBr->hdr.Protocol) +
3956 memcpy(&tcon->fsAttrInfo, response_data,
3957 sizeof (FILE_SYSTEM_ATTRIBUTE_INFO));
3960 cifs_buf_release(pSMB);
3963 goto QFSAttributeRetry;
3969 CIFSSMBQFSDeviceInfo(const int xid, struct cifsTconInfo *tcon)
3971 /* level 0x104 SMB_QUERY_FILE_SYSTEM_INFO */
3972 TRANSACTION2_QFSI_REQ *pSMB = NULL;
3973 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
3974 FILE_SYSTEM_DEVICE_INFO *response_data;
3976 int bytes_returned = 0;
3977 __u16 params, byte_count;
3979 cFYI(1, ("In QFSDeviceInfo"));
3981 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3986 params = 2; /* level */
3987 pSMB->TotalDataCount = 0;
3988 pSMB->MaxParameterCount = cpu_to_le16(2);
3989 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
3990 pSMB->MaxSetupCount = 0;
3994 pSMB->Reserved2 = 0;
3995 byte_count = params + 1 /* pad */ ;
3996 pSMB->TotalParameterCount = cpu_to_le16(params);
3997 pSMB->ParameterCount = pSMB->TotalParameterCount;
3998 pSMB->ParameterOffset = cpu_to_le16(offsetof(
3999 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4001 pSMB->DataCount = 0;
4002 pSMB->DataOffset = 0;
4003 pSMB->SetupCount = 1;
4004 pSMB->Reserved3 = 0;
4005 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4006 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_DEVICE_INFO);
4007 pSMB->hdr.smb_buf_length += byte_count;
4008 pSMB->ByteCount = cpu_to_le16(byte_count);
4010 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4011 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4013 cFYI(1, ("Send error in QFSDeviceInfo = %d", rc));
4014 } else { /* decode response */
4015 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4017 if (rc || (pSMBr->ByteCount < sizeof (FILE_SYSTEM_DEVICE_INFO)))
4018 rc = -EIO; /* bad smb */
4020 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4022 (FILE_SYSTEM_DEVICE_INFO *)
4023 (((char *) &pSMBr->hdr.Protocol) +
4025 memcpy(&tcon->fsDevInfo, response_data,
4026 sizeof (FILE_SYSTEM_DEVICE_INFO));
4029 cifs_buf_release(pSMB);
4032 goto QFSDeviceRetry;
4038 CIFSSMBQFSUnixInfo(const int xid, struct cifsTconInfo *tcon)
4040 /* level 0x200 SMB_QUERY_CIFS_UNIX_INFO */
4041 TRANSACTION2_QFSI_REQ *pSMB = NULL;
4042 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4043 FILE_SYSTEM_UNIX_INFO *response_data;
4045 int bytes_returned = 0;
4046 __u16 params, byte_count;
4048 cFYI(1, ("In QFSUnixInfo"));
4050 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4055 params = 2; /* level */
4056 pSMB->TotalDataCount = 0;
4057 pSMB->DataCount = 0;
4058 pSMB->DataOffset = 0;
4059 pSMB->MaxParameterCount = cpu_to_le16(2);
4060 pSMB->MaxDataCount = cpu_to_le16(100); /* BB find exact max SMB PDU from sess structure BB */
4061 pSMB->MaxSetupCount = 0;
4065 pSMB->Reserved2 = 0;
4066 byte_count = params + 1 /* pad */ ;
4067 pSMB->ParameterCount = cpu_to_le16(params);
4068 pSMB->TotalParameterCount = pSMB->ParameterCount;
4069 pSMB->ParameterOffset = cpu_to_le16(offsetof(struct
4070 smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4071 pSMB->SetupCount = 1;
4072 pSMB->Reserved3 = 0;
4073 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4074 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_CIFS_UNIX_INFO);
4075 pSMB->hdr.smb_buf_length += byte_count;
4076 pSMB->ByteCount = cpu_to_le16(byte_count);
4078 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4079 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4081 cERROR(1, ("Send error in QFSUnixInfo = %d", rc));
4082 } else { /* decode response */
4083 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4085 if (rc || (pSMBr->ByteCount < 13)) {
4086 rc = -EIO; /* bad smb */
4088 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4090 (FILE_SYSTEM_UNIX_INFO
4091 *) (((char *) &pSMBr->hdr.Protocol) +
4093 memcpy(&tcon->fsUnixInfo, response_data,
4094 sizeof (FILE_SYSTEM_UNIX_INFO));
4097 cifs_buf_release(pSMB);
4107 CIFSSMBSetFSUnixInfo(const int xid, struct cifsTconInfo *tcon, __u64 cap)
4109 /* level 0x200 SMB_SET_CIFS_UNIX_INFO */
4110 TRANSACTION2_SETFSI_REQ *pSMB = NULL;
4111 TRANSACTION2_SETFSI_RSP *pSMBr = NULL;
4113 int bytes_returned = 0;
4114 __u16 params, param_offset, offset, byte_count;
4116 cFYI(1, ("In SETFSUnixInfo"));
4118 /* BB switch to small buf init to save memory */
4119 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4124 params = 4; /* 2 bytes zero followed by info level. */
4125 pSMB->MaxSetupCount = 0;
4129 pSMB->Reserved2 = 0;
4130 param_offset = offsetof(struct smb_com_transaction2_setfsi_req, FileNum) - 4;
4131 offset = param_offset + params;
4133 pSMB->MaxParameterCount = cpu_to_le16(4);
4134 pSMB->MaxDataCount = cpu_to_le16(100); /* BB find exact max SMB PDU from sess structure BB */
4135 pSMB->SetupCount = 1;
4136 pSMB->Reserved3 = 0;
4137 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FS_INFORMATION);
4138 byte_count = 1 /* pad */ + params + 12;
4140 pSMB->DataCount = cpu_to_le16(12);
4141 pSMB->ParameterCount = cpu_to_le16(params);
4142 pSMB->TotalDataCount = pSMB->DataCount;
4143 pSMB->TotalParameterCount = pSMB->ParameterCount;
4144 pSMB->ParameterOffset = cpu_to_le16(param_offset);
4145 pSMB->DataOffset = cpu_to_le16(offset);
4149 pSMB->InformationLevel = cpu_to_le16(SMB_SET_CIFS_UNIX_INFO);
4152 pSMB->ClientUnixMajor = cpu_to_le16(CIFS_UNIX_MAJOR_VERSION);
4153 pSMB->ClientUnixMinor = cpu_to_le16(CIFS_UNIX_MINOR_VERSION);
4154 pSMB->ClientUnixCap = cpu_to_le64(cap);
4156 pSMB->hdr.smb_buf_length += byte_count;
4157 pSMB->ByteCount = cpu_to_le16(byte_count);
4159 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4160 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4162 cERROR(1, ("Send error in SETFSUnixInfo = %d", rc));
4163 } else { /* decode response */
4164 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4166 rc = -EIO; /* bad smb */
4169 cifs_buf_release(pSMB);
4172 goto SETFSUnixRetry;
4180 CIFSSMBQFSPosixInfo(const int xid, struct cifsTconInfo *tcon,
4181 struct kstatfs *FSData)
4183 /* level 0x201 SMB_QUERY_CIFS_POSIX_INFO */
4184 TRANSACTION2_QFSI_REQ *pSMB = NULL;
4185 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4186 FILE_SYSTEM_POSIX_INFO *response_data;
4188 int bytes_returned = 0;
4189 __u16 params, byte_count;
4191 cFYI(1, ("In QFSPosixInfo"));
4193 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4198 params = 2; /* level */
4199 pSMB->TotalDataCount = 0;
4200 pSMB->DataCount = 0;
4201 pSMB->DataOffset = 0;
4202 pSMB->MaxParameterCount = cpu_to_le16(2);
4203 pSMB->MaxDataCount = cpu_to_le16(100); /* BB find exact max SMB PDU from sess structure BB */
4204 pSMB->MaxSetupCount = 0;
4208 pSMB->Reserved2 = 0;
4209 byte_count = params + 1 /* pad */ ;
4210 pSMB->ParameterCount = cpu_to_le16(params);
4211 pSMB->TotalParameterCount = pSMB->ParameterCount;
4212 pSMB->ParameterOffset = cpu_to_le16(offsetof(struct
4213 smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4214 pSMB->SetupCount = 1;
4215 pSMB->Reserved3 = 0;
4216 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4217 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_POSIX_FS_INFO);
4218 pSMB->hdr.smb_buf_length += byte_count;
4219 pSMB->ByteCount = cpu_to_le16(byte_count);
4221 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4222 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4224 cFYI(1, ("Send error in QFSUnixInfo = %d", rc));
4225 } else { /* decode response */
4226 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4228 if (rc || (pSMBr->ByteCount < 13)) {
4229 rc = -EIO; /* bad smb */
4231 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4233 (FILE_SYSTEM_POSIX_INFO
4234 *) (((char *) &pSMBr->hdr.Protocol) +
4237 le32_to_cpu(response_data->BlockSize);
4239 le64_to_cpu(response_data->TotalBlocks);
4241 le64_to_cpu(response_data->BlocksAvail);
4242 if(response_data->UserBlocksAvail == cpu_to_le64(-1)) {
4243 FSData->f_bavail = FSData->f_bfree;
4246 le64_to_cpu(response_data->UserBlocksAvail);
4248 if(response_data->TotalFileNodes != cpu_to_le64(-1))
4250 le64_to_cpu(response_data->TotalFileNodes);
4251 if(response_data->FreeFileNodes != cpu_to_le64(-1))
4253 le64_to_cpu(response_data->FreeFileNodes);
4256 cifs_buf_release(pSMB);
4265 /* We can not use write of zero bytes trick to
4266 set file size due to need for large file support. Also note that
4267 this SetPathInfo is preferred to SetFileInfo based method in next
4268 routine which is only needed to work around a sharing violation bug
4269 in Samba which this routine can run into */
4272 CIFSSMBSetEOF(const int xid, struct cifsTconInfo *tcon, const char *fileName,
4273 __u64 size, int SetAllocation,
4274 const struct nls_table *nls_codepage, int remap)
4276 struct smb_com_transaction2_spi_req *pSMB = NULL;
4277 struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
4278 struct file_end_of_file_info *parm_data;
4281 int bytes_returned = 0;
4282 __u16 params, byte_count, data_count, param_offset, offset;
4284 cFYI(1, ("In SetEOF"));
4286 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4291 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4293 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
4294 PATH_MAX, nls_codepage, remap);
4295 name_len++; /* trailing null */
4297 } else { /* BB improve the check for buffer overruns BB */
4298 name_len = strnlen(fileName, PATH_MAX);
4299 name_len++; /* trailing null */
4300 strncpy(pSMB->FileName, fileName, name_len);
4302 params = 6 + name_len;
4303 data_count = sizeof (struct file_end_of_file_info);
4304 pSMB->MaxParameterCount = cpu_to_le16(2);
4305 pSMB->MaxDataCount = cpu_to_le16(4100);
4306 pSMB->MaxSetupCount = 0;
4310 pSMB->Reserved2 = 0;
4311 param_offset = offsetof(struct smb_com_transaction2_spi_req,
4312 InformationLevel) - 4;
4313 offset = param_offset + params;
4315 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
4316 pSMB->InformationLevel =
4317 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2);
4319 pSMB->InformationLevel =
4320 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO);
4321 } else /* Set File Size */ {
4322 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
4323 pSMB->InformationLevel =
4324 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO2);
4326 pSMB->InformationLevel =
4327 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO);
4331 (struct file_end_of_file_info *) (((char *) &pSMB->hdr.Protocol) +
4333 pSMB->ParameterOffset = cpu_to_le16(param_offset);
4334 pSMB->DataOffset = cpu_to_le16(offset);
4335 pSMB->SetupCount = 1;
4336 pSMB->Reserved3 = 0;
4337 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
4338 byte_count = 3 /* pad */ + params + data_count;
4339 pSMB->DataCount = cpu_to_le16(data_count);
4340 pSMB->TotalDataCount = pSMB->DataCount;
4341 pSMB->ParameterCount = cpu_to_le16(params);
4342 pSMB->TotalParameterCount = pSMB->ParameterCount;
4343 pSMB->Reserved4 = 0;
4344 pSMB->hdr.smb_buf_length += byte_count;
4345 parm_data->FileSize = cpu_to_le64(size);
4346 pSMB->ByteCount = cpu_to_le16(byte_count);
4347 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4348 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4350 cFYI(1, ("SetPathInfo (file size) returned %d", rc));
4353 cifs_buf_release(pSMB);
4362 CIFSSMBSetFileSize(const int xid, struct cifsTconInfo *tcon, __u64 size,
4363 __u16 fid, __u32 pid_of_opener, int SetAllocation)
4365 struct smb_com_transaction2_sfi_req *pSMB = NULL;
4366 struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
4368 struct file_end_of_file_info *parm_data;
4370 int bytes_returned = 0;
4371 __u16 params, param_offset, offset, byte_count, count;
4373 cFYI(1, ("SetFileSize (via SetFileInfo) %lld",
4375 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
4380 pSMBr = (struct smb_com_transaction2_sfi_rsp *)pSMB;
4382 pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
4383 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));
4386 pSMB->MaxSetupCount = 0;
4390 pSMB->Reserved2 = 0;
4391 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
4392 offset = param_offset + params;
4394 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
4396 count = sizeof(struct file_end_of_file_info);
4397 pSMB->MaxParameterCount = cpu_to_le16(2);
4398 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB PDU from sess */
4399 pSMB->SetupCount = 1;
4400 pSMB->Reserved3 = 0;
4401 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
4402 byte_count = 3 /* pad */ + params + count;
4403 pSMB->DataCount = cpu_to_le16(count);
4404 pSMB->ParameterCount = cpu_to_le16(params);
4405 pSMB->TotalDataCount = pSMB->DataCount;
4406 pSMB->TotalParameterCount = pSMB->ParameterCount;
4407 pSMB->ParameterOffset = cpu_to_le16(param_offset);
4409 (struct file_end_of_file_info *) (((char *) &pSMB->hdr.Protocol) +
4411 pSMB->DataOffset = cpu_to_le16(offset);
4412 parm_data->FileSize = cpu_to_le64(size);
4415 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
4416 pSMB->InformationLevel =
4417 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2);
4419 pSMB->InformationLevel =
4420 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO);
4421 } else /* Set File Size */ {
4422 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
4423 pSMB->InformationLevel =
4424 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO2);
4426 pSMB->InformationLevel =
4427 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO);
4429 pSMB->Reserved4 = 0;
4430 pSMB->hdr.smb_buf_length += byte_count;
4431 pSMB->ByteCount = cpu_to_le16(byte_count);
4432 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4433 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4436 ("Send error in SetFileInfo (SetFileSize) = %d",
4441 cifs_small_buf_release(pSMB);
4443 /* Note: On -EAGAIN error only caller can retry on handle based calls
4444 since file handle passed in no longer valid */
4449 /* Some legacy servers such as NT4 require that the file times be set on
4450 an open handle, rather than by pathname - this is awkward due to
4451 potential access conflicts on the open, but it is unavoidable for these
4452 old servers since the only other choice is to go from 100 nanosecond DCE
4453 time and resort to the original setpathinfo level which takes the ancient
4454 DOS time format with 2 second granularity */
4456 CIFSSMBSetFileTimes(const int xid, struct cifsTconInfo *tcon, const FILE_BASIC_INFO * data,
4459 struct smb_com_transaction2_sfi_req *pSMB = NULL;
4460 struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
4463 int bytes_returned = 0;
4464 __u16 params, param_offset, offset, byte_count, count;
4466 cFYI(1, ("Set Times (via SetFileInfo)"));
4467 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
4472 pSMBr = (struct smb_com_transaction2_sfi_rsp *)pSMB;
4474 /* At this point there is no need to override the current pid
4475 with the pid of the opener, but that could change if we someday
4476 use an existing handle (rather than opening one on the fly) */
4477 /* pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
4478 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));*/
4481 pSMB->MaxSetupCount = 0;
4485 pSMB->Reserved2 = 0;
4486 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
4487 offset = param_offset + params;
4489 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
4491 count = sizeof (FILE_BASIC_INFO);
4492 pSMB->MaxParameterCount = cpu_to_le16(2);
4493 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB PDU from sess */
4494 pSMB->SetupCount = 1;
4495 pSMB->Reserved3 = 0;
4496 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
4497 byte_count = 3 /* pad */ + params + count;
4498 pSMB->DataCount = cpu_to_le16(count);
4499 pSMB->ParameterCount = cpu_to_le16(params);
4500 pSMB->TotalDataCount = pSMB->DataCount;
4501 pSMB->TotalParameterCount = pSMB->ParameterCount;
4502 pSMB->ParameterOffset = cpu_to_le16(param_offset);
4503 pSMB->DataOffset = cpu_to_le16(offset);
4505 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
4506 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO2);
4508 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO);
4509 pSMB->Reserved4 = 0;
4510 pSMB->hdr.smb_buf_length += byte_count;
4511 pSMB->ByteCount = cpu_to_le16(byte_count);
4512 memcpy(data_offset,data,sizeof(FILE_BASIC_INFO));
4513 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4514 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4516 cFYI(1,("Send error in Set Time (SetFileInfo) = %d",rc));
4519 cifs_small_buf_release(pSMB);
4521 /* Note: On -EAGAIN error only caller can retry on handle based calls
4522 since file handle passed in no longer valid */
4529 CIFSSMBSetTimes(const int xid, struct cifsTconInfo *tcon, const char *fileName,
4530 const FILE_BASIC_INFO * data,
4531 const struct nls_table *nls_codepage, int remap)
4533 TRANSACTION2_SPI_REQ *pSMB = NULL;
4534 TRANSACTION2_SPI_RSP *pSMBr = NULL;
4537 int bytes_returned = 0;
4539 __u16 params, param_offset, offset, byte_count, count;
4541 cFYI(1, ("In SetTimes"));
4544 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4549 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4551 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
4552 PATH_MAX, nls_codepage, remap);
4553 name_len++; /* trailing null */
4555 } else { /* BB improve the check for buffer overruns BB */
4556 name_len = strnlen(fileName, PATH_MAX);
4557 name_len++; /* trailing null */
4558 strncpy(pSMB->FileName, fileName, name_len);
4561 params = 6 + name_len;
4562 count = sizeof (FILE_BASIC_INFO);
4563 pSMB->MaxParameterCount = cpu_to_le16(2);
4564 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
4565 pSMB->MaxSetupCount = 0;
4569 pSMB->Reserved2 = 0;
4570 param_offset = offsetof(struct smb_com_transaction2_spi_req,
4571 InformationLevel) - 4;
4572 offset = param_offset + params;
4573 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
4574 pSMB->ParameterOffset = cpu_to_le16(param_offset);
4575 pSMB->DataOffset = cpu_to_le16(offset);
4576 pSMB->SetupCount = 1;
4577 pSMB->Reserved3 = 0;
4578 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
4579 byte_count = 3 /* pad */ + params + count;
4581 pSMB->DataCount = cpu_to_le16(count);
4582 pSMB->ParameterCount = cpu_to_le16(params);
4583 pSMB->TotalDataCount = pSMB->DataCount;
4584 pSMB->TotalParameterCount = pSMB->ParameterCount;
4585 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
4586 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO2);
4588 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO);
4589 pSMB->Reserved4 = 0;
4590 pSMB->hdr.smb_buf_length += byte_count;
4591 memcpy(data_offset, data, sizeof (FILE_BASIC_INFO));
4592 pSMB->ByteCount = cpu_to_le16(byte_count);
4593 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4594 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4596 cFYI(1, ("SetPathInfo (times) returned %d", rc));
4599 cifs_buf_release(pSMB);
4607 /* Can not be used to set time stamps yet (due to old DOS time format) */
4608 /* Can be used to set attributes */
4609 #if 0 /* Possibly not needed - since it turns out that strangely NT4 has a bug
4610 handling it anyway and NT4 was what we thought it would be needed for
4611 Do not delete it until we prove whether needed for Win9x though */
4613 CIFSSMBSetAttrLegacy(int xid, struct cifsTconInfo *tcon, char *fileName,
4614 __u16 dos_attrs, const struct nls_table *nls_codepage)
4616 SETATTR_REQ *pSMB = NULL;
4617 SETATTR_RSP *pSMBr = NULL;
4622 cFYI(1, ("In SetAttrLegacy"));
4625 rc = smb_init(SMB_COM_SETATTR, 8, tcon, (void **) &pSMB,
4630 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4632 ConvertToUCS((__le16 *) pSMB->fileName, fileName,
4633 PATH_MAX, nls_codepage);
4634 name_len++; /* trailing null */
4636 } else { /* BB improve the check for buffer overruns BB */
4637 name_len = strnlen(fileName, PATH_MAX);
4638 name_len++; /* trailing null */
4639 strncpy(pSMB->fileName, fileName, name_len);
4641 pSMB->attr = cpu_to_le16(dos_attrs);
4642 pSMB->BufferFormat = 0x04;
4643 pSMB->hdr.smb_buf_length += name_len + 1;
4644 pSMB->ByteCount = cpu_to_le16(name_len + 1);
4645 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4646 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4648 cFYI(1, ("Error in LegacySetAttr = %d", rc));
4651 cifs_buf_release(pSMB);
4654 goto SetAttrLgcyRetry;
4658 #endif /* temporarily unneeded SetAttr legacy function */
4661 CIFSSMBUnixSetPerms(const int xid, struct cifsTconInfo *tcon,
4662 char *fileName, __u64 mode, __u64 uid, __u64 gid,
4663 dev_t device, const struct nls_table *nls_codepage,
4666 TRANSACTION2_SPI_REQ *pSMB = NULL;
4667 TRANSACTION2_SPI_RSP *pSMBr = NULL;
4670 int bytes_returned = 0;
4671 FILE_UNIX_BASIC_INFO *data_offset;
4672 __u16 params, param_offset, offset, count, byte_count;
4674 cFYI(1, ("In SetUID/GID/Mode"));
4676 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4681 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4683 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
4684 PATH_MAX, nls_codepage, remap);
4685 name_len++; /* trailing null */
4687 } else { /* BB improve the check for buffer overruns BB */
4688 name_len = strnlen(fileName, PATH_MAX);
4689 name_len++; /* trailing null */
4690 strncpy(pSMB->FileName, fileName, name_len);
4693 params = 6 + name_len;
4694 count = sizeof (FILE_UNIX_BASIC_INFO);
4695 pSMB->MaxParameterCount = cpu_to_le16(2);
4696 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
4697 pSMB->MaxSetupCount = 0;
4701 pSMB->Reserved2 = 0;
4702 param_offset = offsetof(struct smb_com_transaction2_spi_req,
4703 InformationLevel) - 4;
4704 offset = param_offset + params;
4706 (FILE_UNIX_BASIC_INFO *) ((char *) &pSMB->hdr.Protocol +
4708 memset(data_offset, 0, count);
4709 pSMB->DataOffset = cpu_to_le16(offset);
4710 pSMB->ParameterOffset = cpu_to_le16(param_offset);
4711 pSMB->SetupCount = 1;
4712 pSMB->Reserved3 = 0;
4713 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
4714 byte_count = 3 /* pad */ + params + count;
4715 pSMB->ParameterCount = cpu_to_le16(params);
4716 pSMB->DataCount = cpu_to_le16(count);
4717 pSMB->TotalParameterCount = pSMB->ParameterCount;
4718 pSMB->TotalDataCount = pSMB->DataCount;
4719 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_BASIC);
4720 pSMB->Reserved4 = 0;
4721 pSMB->hdr.smb_buf_length += byte_count;
4722 data_offset->Uid = cpu_to_le64(uid);
4723 data_offset->Gid = cpu_to_le64(gid);
4724 /* better to leave device as zero when it is */
4725 data_offset->DevMajor = cpu_to_le64(MAJOR(device));
4726 data_offset->DevMinor = cpu_to_le64(MINOR(device));
4727 data_offset->Permissions = cpu_to_le64(mode);
4730 data_offset->Type = cpu_to_le32(UNIX_FILE);
4731 else if(S_ISDIR(mode))
4732 data_offset->Type = cpu_to_le32(UNIX_DIR);
4733 else if(S_ISLNK(mode))
4734 data_offset->Type = cpu_to_le32(UNIX_SYMLINK);
4735 else if(S_ISCHR(mode))
4736 data_offset->Type = cpu_to_le32(UNIX_CHARDEV);
4737 else if(S_ISBLK(mode))
4738 data_offset->Type = cpu_to_le32(UNIX_BLOCKDEV);
4739 else if(S_ISFIFO(mode))
4740 data_offset->Type = cpu_to_le32(UNIX_FIFO);
4741 else if(S_ISSOCK(mode))
4742 data_offset->Type = cpu_to_le32(UNIX_SOCKET);
4745 pSMB->ByteCount = cpu_to_le16(byte_count);
4746 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4747 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4749 cFYI(1, ("SetPathInfo (perms) returned %d", rc));
4753 cifs_buf_release(pSMB);
4759 int CIFSSMBNotify(const int xid, struct cifsTconInfo *tcon,
4760 const int notify_subdirs, const __u16 netfid,
4761 __u32 filter, struct file * pfile, int multishot,
4762 const struct nls_table *nls_codepage)
4765 struct smb_com_transaction_change_notify_req * pSMB = NULL;
4766 struct smb_com_ntransaction_change_notify_rsp * pSMBr = NULL;
4767 struct dir_notify_req *dnotify_req;
4770 cFYI(1, ("In CIFSSMBNotify for file handle %d",(int)netfid));
4771 rc = smb_init(SMB_COM_NT_TRANSACT, 23, tcon, (void **) &pSMB,
4776 pSMB->TotalParameterCount = 0 ;
4777 pSMB->TotalDataCount = 0;
4778 pSMB->MaxParameterCount = cpu_to_le32(2);
4779 /* BB find exact data count max from sess structure BB */
4780 pSMB->MaxDataCount = 0; /* same in little endian or be */
4781 /* BB VERIFY verify which is correct for above BB */
4782 pSMB->MaxDataCount = cpu_to_le32((tcon->ses->server->maxBuf -
4783 MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
4785 pSMB->MaxSetupCount = 4;
4787 pSMB->ParameterOffset = 0;
4788 pSMB->DataCount = 0;
4789 pSMB->DataOffset = 0;
4790 pSMB->SetupCount = 4; /* single byte does not need le conversion */
4791 pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_NOTIFY_CHANGE);
4792 pSMB->ParameterCount = pSMB->TotalParameterCount;
4794 pSMB->WatchTree = 1; /* one byte - no le conversion needed */
4795 pSMB->Reserved2 = 0;
4796 pSMB->CompletionFilter = cpu_to_le32(filter);
4797 pSMB->Fid = netfid; /* file handle always le */
4798 pSMB->ByteCount = 0;
4800 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4801 (struct smb_hdr *) pSMBr, &bytes_returned, -1);
4803 cFYI(1, ("Error in Notify = %d", rc));
4805 /* Add file to outstanding requests */
4806 /* BB change to kmem cache alloc */
4807 dnotify_req = (struct dir_notify_req *) kmalloc(
4808 sizeof(struct dir_notify_req),
4811 dnotify_req->Pid = pSMB->hdr.Pid;
4812 dnotify_req->PidHigh = pSMB->hdr.PidHigh;
4813 dnotify_req->Mid = pSMB->hdr.Mid;
4814 dnotify_req->Tid = pSMB->hdr.Tid;
4815 dnotify_req->Uid = pSMB->hdr.Uid;
4816 dnotify_req->netfid = netfid;
4817 dnotify_req->pfile = pfile;
4818 dnotify_req->filter = filter;
4819 dnotify_req->multishot = multishot;
4820 spin_lock(&GlobalMid_Lock);
4821 list_add_tail(&dnotify_req->lhead,
4822 &GlobalDnotifyReqList);
4823 spin_unlock(&GlobalMid_Lock);
4827 cifs_buf_release(pSMB);
4830 #ifdef CONFIG_CIFS_XATTR
4832 CIFSSMBQAllEAs(const int xid, struct cifsTconInfo *tcon,
4833 const unsigned char *searchName,
4834 char * EAData, size_t buf_size,
4835 const struct nls_table *nls_codepage, int remap)
4837 /* BB assumes one setup word */
4838 TRANSACTION2_QPI_REQ *pSMB = NULL;
4839 TRANSACTION2_QPI_RSP *pSMBr = NULL;
4843 struct fea * temp_fea;
4845 __u16 params, byte_count;
4847 cFYI(1, ("In Query All EAs path %s", searchName));
4849 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4854 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4856 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
4857 PATH_MAX, nls_codepage, remap);
4858 name_len++; /* trailing null */
4860 } else { /* BB improve the check for buffer overruns BB */
4861 name_len = strnlen(searchName, PATH_MAX);
4862 name_len++; /* trailing null */
4863 strncpy(pSMB->FileName, searchName, name_len);
4866 params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */ ;
4867 pSMB->TotalDataCount = 0;
4868 pSMB->MaxParameterCount = cpu_to_le16(2);
4869 pSMB->MaxDataCount = cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
4870 pSMB->MaxSetupCount = 0;
4874 pSMB->Reserved2 = 0;
4875 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4876 struct smb_com_transaction2_qpi_req ,InformationLevel) - 4);
4877 pSMB->DataCount = 0;
4878 pSMB->DataOffset = 0;
4879 pSMB->SetupCount = 1;
4880 pSMB->Reserved3 = 0;
4881 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
4882 byte_count = params + 1 /* pad */ ;
4883 pSMB->TotalParameterCount = cpu_to_le16(params);
4884 pSMB->ParameterCount = pSMB->TotalParameterCount;
4885 pSMB->InformationLevel = cpu_to_le16(SMB_INFO_QUERY_ALL_EAS);
4886 pSMB->Reserved4 = 0;
4887 pSMB->hdr.smb_buf_length += byte_count;
4888 pSMB->ByteCount = cpu_to_le16(byte_count);
4890 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4891 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4893 cFYI(1, ("Send error in QueryAllEAs = %d", rc));
4894 } else { /* decode response */
4895 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4897 /* BB also check enough total bytes returned */
4898 /* BB we need to improve the validity checking
4899 of these trans2 responses */
4900 if (rc || (pSMBr->ByteCount < 4))
4901 rc = -EIO; /* bad smb */
4902 /* else if (pFindData){
4903 memcpy((char *) pFindData,
4904 (char *) &pSMBr->hdr.Protocol +
4907 /* check that length of list is not more than bcc */
4908 /* check that each entry does not go beyond length
4910 /* check that each element of each entry does not
4911 go beyond end of list */
4912 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4913 struct fealist * ea_response_data;
4915 /* validate_trans2_offsets() */
4916 /* BB to check if(start of smb + data_offset > &bcc+ bcc)*/
4917 ea_response_data = (struct fealist *)
4918 (((char *) &pSMBr->hdr.Protocol) +
4920 name_len = le32_to_cpu(ea_response_data->list_len);
4921 cFYI(1,("ea length %d", name_len));
4923 /* returned EA size zeroed at top of function */
4924 cFYI(1,("empty EA list returned from server"));
4926 /* account for ea list len */
4928 temp_fea = ea_response_data->list;
4929 temp_ptr = (char *)temp_fea;
4930 while(name_len > 0) {
4934 rc += temp_fea->name_len;
4935 /* account for prefix user. and trailing null */
4937 if(rc<(int)buf_size) {
4938 memcpy(EAData,"user.",5);
4940 memcpy(EAData,temp_ptr,temp_fea->name_len);
4941 EAData+=temp_fea->name_len;
4942 /* null terminate name */
4944 EAData = EAData + 1;
4945 } else if(buf_size == 0) {
4946 /* skip copy - calc size only */
4948 /* stop before overrun buffer */
4952 name_len -= temp_fea->name_len;
4953 temp_ptr += temp_fea->name_len;
4954 /* account for trailing null */
4957 value_len = le16_to_cpu(temp_fea->value_len);
4958 name_len -= value_len;
4959 temp_ptr += value_len;
4960 /* BB check that temp_ptr is still within smb BB*/
4961 /* no trailing null to account for in value len */
4962 /* go on to next EA */
4963 temp_fea = (struct fea *)temp_ptr;
4969 cifs_buf_release(pSMB);
4976 ssize_t CIFSSMBQueryEA(const int xid,struct cifsTconInfo * tcon,
4977 const unsigned char * searchName,const unsigned char * ea_name,
4978 unsigned char * ea_value, size_t buf_size,
4979 const struct nls_table *nls_codepage, int remap)
4981 TRANSACTION2_QPI_REQ *pSMB = NULL;
4982 TRANSACTION2_QPI_RSP *pSMBr = NULL;
4986 struct fea * temp_fea;
4988 __u16 params, byte_count;
4990 cFYI(1, ("In Query EA path %s", searchName));
4992 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4997 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4999 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
5000 PATH_MAX, nls_codepage, remap);
5001 name_len++; /* trailing null */
5003 } else { /* BB improve the check for buffer overruns BB */
5004 name_len = strnlen(searchName, PATH_MAX);
5005 name_len++; /* trailing null */
5006 strncpy(pSMB->FileName, searchName, name_len);
5009 params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */ ;
5010 pSMB->TotalDataCount = 0;
5011 pSMB->MaxParameterCount = cpu_to_le16(2);
5012 pSMB->MaxDataCount = cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
5013 pSMB->MaxSetupCount = 0;
5017 pSMB->Reserved2 = 0;
5018 pSMB->ParameterOffset = cpu_to_le16(offsetof(
5019 struct smb_com_transaction2_qpi_req ,InformationLevel) - 4);
5020 pSMB->DataCount = 0;
5021 pSMB->DataOffset = 0;
5022 pSMB->SetupCount = 1;
5023 pSMB->Reserved3 = 0;
5024 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
5025 byte_count = params + 1 /* pad */ ;
5026 pSMB->TotalParameterCount = cpu_to_le16(params);
5027 pSMB->ParameterCount = pSMB->TotalParameterCount;
5028 pSMB->InformationLevel = cpu_to_le16(SMB_INFO_QUERY_ALL_EAS);
5029 pSMB->Reserved4 = 0;
5030 pSMB->hdr.smb_buf_length += byte_count;
5031 pSMB->ByteCount = cpu_to_le16(byte_count);
5033 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5034 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5036 cFYI(1, ("Send error in Query EA = %d", rc));
5037 } else { /* decode response */
5038 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
5040 /* BB also check enough total bytes returned */
5041 /* BB we need to improve the validity checking
5042 of these trans2 responses */
5043 if (rc || (pSMBr->ByteCount < 4))
5044 rc = -EIO; /* bad smb */
5045 /* else if (pFindData){
5046 memcpy((char *) pFindData,
5047 (char *) &pSMBr->hdr.Protocol +
5050 /* check that length of list is not more than bcc */
5051 /* check that each entry does not go beyond length
5053 /* check that each element of each entry does not
5054 go beyond end of list */
5055 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
5056 struct fealist * ea_response_data;
5058 /* validate_trans2_offsets() */
5059 /* BB to check if(start of smb + data_offset > &bcc+ bcc)*/
5060 ea_response_data = (struct fealist *)
5061 (((char *) &pSMBr->hdr.Protocol) +
5063 name_len = le32_to_cpu(ea_response_data->list_len);
5064 cFYI(1,("ea length %d", name_len));
5066 /* returned EA size zeroed at top of function */
5067 cFYI(1,("empty EA list returned from server"));
5069 /* account for ea list len */
5071 temp_fea = ea_response_data->list;
5072 temp_ptr = (char *)temp_fea;
5073 /* loop through checking if we have a matching
5074 name and then return the associated value */
5075 while(name_len > 0) {
5079 value_len = le16_to_cpu(temp_fea->value_len);
5080 /* BB validate that value_len falls within SMB,
5081 even though maximum for name_len is 255 */
5082 if(memcmp(temp_fea->name,ea_name,
5083 temp_fea->name_len) == 0) {
5086 /* account for prefix user. and trailing null */
5087 if(rc<=(int)buf_size) {
5089 temp_fea->name+temp_fea->name_len+1,
5091 /* ea values, unlike ea names,
5092 are not null terminated */
5093 } else if(buf_size == 0) {
5094 /* skip copy - calc size only */
5096 /* stop before overrun buffer */
5101 name_len -= temp_fea->name_len;
5102 temp_ptr += temp_fea->name_len;
5103 /* account for trailing null */
5106 name_len -= value_len;
5107 temp_ptr += value_len;
5108 /* no trailing null to account for in value len */
5109 /* go on to next EA */
5110 temp_fea = (struct fea *)temp_ptr;
5116 cifs_buf_release(pSMB);
5124 CIFSSMBSetEA(const int xid, struct cifsTconInfo *tcon, const char *fileName,
5125 const char * ea_name, const void * ea_value,
5126 const __u16 ea_value_len, const struct nls_table *nls_codepage,
5129 struct smb_com_transaction2_spi_req *pSMB = NULL;
5130 struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
5131 struct fealist *parm_data;
5134 int bytes_returned = 0;
5135 __u16 params, param_offset, byte_count, offset, count;
5137 cFYI(1, ("In SetEA"));
5139 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5144 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5146 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
5147 PATH_MAX, nls_codepage, remap);
5148 name_len++; /* trailing null */
5150 } else { /* BB improve the check for buffer overruns BB */
5151 name_len = strnlen(fileName, PATH_MAX);
5152 name_len++; /* trailing null */
5153 strncpy(pSMB->FileName, fileName, name_len);
5156 params = 6 + name_len;
5158 /* done calculating parms using name_len of file name,
5159 now use name_len to calculate length of ea name
5160 we are going to create in the inode xattrs */
5164 name_len = strnlen(ea_name,255);
5166 count = sizeof(*parm_data) + ea_value_len + name_len + 1;
5167 pSMB->MaxParameterCount = cpu_to_le16(2);
5168 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB size from sess */
5169 pSMB->MaxSetupCount = 0;
5173 pSMB->Reserved2 = 0;
5174 param_offset = offsetof(struct smb_com_transaction2_spi_req,
5175 InformationLevel) - 4;
5176 offset = param_offset + params;
5177 pSMB->InformationLevel =
5178 cpu_to_le16(SMB_SET_FILE_EA);
5181 (struct fealist *) (((char *) &pSMB->hdr.Protocol) +
5183 pSMB->ParameterOffset = cpu_to_le16(param_offset);
5184 pSMB->DataOffset = cpu_to_le16(offset);
5185 pSMB->SetupCount = 1;
5186 pSMB->Reserved3 = 0;
5187 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
5188 byte_count = 3 /* pad */ + params + count;
5189 pSMB->DataCount = cpu_to_le16(count);
5190 parm_data->list_len = cpu_to_le32(count);
5191 parm_data->list[0].EA_flags = 0;
5192 /* we checked above that name len is less than 255 */
5193 parm_data->list[0].name_len = (__u8)name_len;
5194 /* EA names are always ASCII */
5196 strncpy(parm_data->list[0].name,ea_name,name_len);
5197 parm_data->list[0].name[name_len] = 0;
5198 parm_data->list[0].value_len = cpu_to_le16(ea_value_len);
5199 /* caller ensures that ea_value_len is less than 64K but
5200 we need to ensure that it fits within the smb */
5202 /*BB add length check that it would fit in negotiated SMB buffer size BB */
5203 /* if(ea_value_len > buffer_size - 512 (enough for header)) */
5205 memcpy(parm_data->list[0].name+name_len+1,ea_value,ea_value_len);
5207 pSMB->TotalDataCount = pSMB->DataCount;
5208 pSMB->ParameterCount = cpu_to_le16(params);
5209 pSMB->TotalParameterCount = pSMB->ParameterCount;
5210 pSMB->Reserved4 = 0;
5211 pSMB->hdr.smb_buf_length += byte_count;
5212 pSMB->ByteCount = cpu_to_le16(byte_count);
5213 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5214 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5216 cFYI(1, ("SetPathInfo (EA) returned %d", rc));
5219 cifs_buf_release(pSMB);