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)) {
451 struct lanman_neg_rsp * rsp = (struct lanman_neg_rsp *)pSMBr;
453 if((secFlags & CIFSSEC_MAY_LANMAN) ||
454 (secFlags & CIFSSEC_MAY_PLNTXT))
455 server->secType = LANMAN;
457 cERROR(1, ("mount failed weak security disabled"
458 " in /proc/fs/cifs/SecurityFlags"));
462 server->secMode = (__u8)le16_to_cpu(rsp->SecurityMode);
463 server->maxReq = le16_to_cpu(rsp->MaxMpxCount);
464 server->maxBuf = min((__u32)le16_to_cpu(rsp->MaxBufSize),
465 (__u32)CIFSMaxBufSize + MAX_CIFS_HDR_SIZE);
466 GETU32(server->sessid) = le32_to_cpu(rsp->SessionKey);
467 /* even though we do not use raw we might as well set this
468 accurately, in case we ever find a need for it */
469 if((le16_to_cpu(rsp->RawMode) & RAW_ENABLE) == RAW_ENABLE) {
470 server->maxRw = 0xFF00;
471 server->capabilities = CAP_MPX_MODE | CAP_RAW_MODE;
473 server->maxRw = 0;/* we do not need to use raw anyway */
474 server->capabilities = CAP_MPX_MODE;
476 tmp = le16_to_cpu(rsp->ServerTimeZone);
477 if (tmp == (int)0xffff) {
478 /* OS/2 often does not set timezone therefore
479 * we must use server time to calc time zone.
480 * Could deviate slightly from the right zone. Not easy
481 * to adjust, since timezones are not always a multiple
482 * of 60 (sometimes 30 minutes - are there smaller?)
484 struct timespec ts, utc;
486 ts = cnvrtDosUnixTm(le16_to_cpu(rsp->SrvTime.Date),
487 le16_to_cpu(rsp->SrvTime.Time));
488 cFYI(1,("SrvTime: %d sec since 1970 (utc: %d) diff: %d",
489 (int)ts.tv_sec, (int)utc.tv_sec,
490 (int)(utc.tv_sec - ts.tv_sec)));
491 tmp = (int)(utc.tv_sec - ts.tv_sec);
492 adjust = tmp < 0 ? -29 : 29;
493 tmp = ((tmp + adjust) / 60) * 60;
494 server->timeAdj = tmp;
496 server->timeAdj = tmp * 60; /* also in seconds */
498 cFYI(1,("server->timeAdj: %d seconds", server->timeAdj));
501 /* BB get server time for time conversions and add
502 code to use it and timezone since this is not UTC */
504 if (rsp->EncryptionKeyLength ==
505 cpu_to_le16(CIFS_CRYPTO_KEY_SIZE)) {
506 memcpy(server->cryptKey, rsp->EncryptionKey,
507 CIFS_CRYPTO_KEY_SIZE);
508 } else if (server->secMode & SECMODE_PW_ENCRYPT) {
509 rc = -EIO; /* need cryptkey unless plain text */
513 cFYI(1,("LANMAN negotiated"));
514 /* we will not end up setting signing flags - as no signing
515 was in LANMAN and server did not return the flags on */
517 #else /* weak security disabled */
518 } else if(pSMBr->hdr.WordCount == 13) {
519 cERROR(1,("mount failed, cifs module not built "
520 "with CIFS_WEAK_PW_HASH support"));
522 #endif /* WEAK_PW_HASH */
524 } else if(pSMBr->hdr.WordCount != 17) {
529 /* else wct == 17 NTLM */
530 server->secMode = pSMBr->SecurityMode;
531 if((server->secMode & SECMODE_USER) == 0)
532 cFYI(1,("share mode security"));
534 if((server->secMode & SECMODE_PW_ENCRYPT) == 0)
535 #ifdef CONFIG_CIFS_WEAK_PW_HASH
536 if ((secFlags & CIFSSEC_MAY_PLNTXT) == 0)
537 #endif /* CIFS_WEAK_PW_HASH */
538 cERROR(1,("Server requests plain text password"
539 " but client support disabled"));
541 if((secFlags & CIFSSEC_MUST_NTLMV2) == CIFSSEC_MUST_NTLMV2)
542 server->secType = NTLMv2;
543 else if(secFlags & CIFSSEC_MAY_NTLM)
544 server->secType = NTLM;
545 else if(secFlags & CIFSSEC_MAY_NTLMV2)
546 server->secType = NTLMv2;
547 /* else krb5 ... any others ... */
549 /* one byte, so no need to convert this or EncryptionKeyLen from
551 server->maxReq = le16_to_cpu(pSMBr->MaxMpxCount);
552 /* probably no need to store and check maxvcs */
553 server->maxBuf = min(le32_to_cpu(pSMBr->MaxBufferSize),
554 (__u32) CIFSMaxBufSize + MAX_CIFS_HDR_SIZE);
555 server->maxRw = le32_to_cpu(pSMBr->MaxRawSize);
556 cFYI(0, ("Max buf = %d", ses->server->maxBuf));
557 GETU32(ses->server->sessid) = le32_to_cpu(pSMBr->SessionKey);
558 server->capabilities = le32_to_cpu(pSMBr->Capabilities);
559 server->timeAdj = le16_to_cpu(pSMBr->ServerTimeZone) * 60;
560 if (pSMBr->EncryptionKeyLength == CIFS_CRYPTO_KEY_SIZE) {
561 memcpy(server->cryptKey, pSMBr->u.EncryptionKey,
562 CIFS_CRYPTO_KEY_SIZE);
563 } else if ((pSMBr->hdr.Flags2 & SMBFLG2_EXT_SEC)
564 && (pSMBr->EncryptionKeyLength == 0)) {
565 /* decode security blob */
566 } else if (server->secMode & SECMODE_PW_ENCRYPT) {
567 rc = -EIO; /* no crypt key only if plain text pwd */
571 /* BB might be helpful to save off the domain of server here */
573 if ((pSMBr->hdr.Flags2 & SMBFLG2_EXT_SEC) &&
574 (server->capabilities & CAP_EXTENDED_SECURITY)) {
575 count = pSMBr->ByteCount;
578 else if (count == 16) {
579 server->secType = RawNTLMSSP;
580 if (server->socketUseCount.counter > 1) {
581 if (memcmp(server->server_GUID,
582 pSMBr->u.extended_response.
584 cFYI(1, ("server UID changed"));
585 memcpy(server->server_GUID,
586 pSMBr->u.extended_response.GUID,
590 memcpy(server->server_GUID,
591 pSMBr->u.extended_response.GUID, 16);
593 rc = decode_negTokenInit(pSMBr->u.extended_response.
598 /* BB Need to fill struct for sessetup here */
605 server->capabilities &= ~CAP_EXTENDED_SECURITY;
607 #ifdef CONFIG_CIFS_WEAK_PW_HASH
610 if(sign_CIFS_PDUs == FALSE) {
611 if(server->secMode & SECMODE_SIGN_REQUIRED)
612 cERROR(1,("Server requires "
613 "/proc/fs/cifs/PacketSigningEnabled to be on"));
615 ~(SECMODE_SIGN_ENABLED | SECMODE_SIGN_REQUIRED);
616 } else if(sign_CIFS_PDUs == 1) {
617 if((server->secMode & SECMODE_SIGN_REQUIRED) == 0)
619 ~(SECMODE_SIGN_ENABLED | SECMODE_SIGN_REQUIRED);
620 } else if(sign_CIFS_PDUs == 2) {
621 if((server->secMode &
622 (SECMODE_SIGN_ENABLED | SECMODE_SIGN_REQUIRED)) == 0) {
623 cERROR(1,("signing required but server lacks support"));
627 cifs_buf_release(pSMB);
629 cFYI(1,("negprot rc %d",rc));
634 CIFSSMBTDis(const int xid, struct cifsTconInfo *tcon)
636 struct smb_hdr *smb_buffer;
637 struct smb_hdr *smb_buffer_response; /* BB removeme BB */
641 cFYI(1, ("In tree disconnect"));
643 * If last user of the connection and
644 * connection alive - disconnect it
645 * If this is the last connection on the server session disconnect it
646 * (and inside session disconnect we should check if tcp socket needs
647 * to be freed and kernel thread woken up).
650 down(&tcon->tconSem);
654 atomic_dec(&tcon->useCount);
655 if (atomic_read(&tcon->useCount) > 0) {
660 /* No need to return error on this operation if tid invalidated and
661 closed on server already e.g. due to tcp session crashing */
662 if(tcon->tidStatus == CifsNeedReconnect) {
667 if((tcon->ses == NULL) || (tcon->ses->server == NULL)) {
671 rc = small_smb_init(SMB_COM_TREE_DISCONNECT, 0, tcon,
672 (void **)&smb_buffer);
677 smb_buffer_response = smb_buffer; /* BB removeme BB */
679 rc = SendReceive(xid, tcon->ses, smb_buffer, smb_buffer_response,
682 cFYI(1, ("Tree disconnect failed %d", rc));
685 cifs_small_buf_release(smb_buffer);
688 /* No need to return error on this operation if tid invalidated and
689 closed on server already e.g. due to tcp session crashing */
697 CIFSSMBLogoff(const int xid, struct cifsSesInfo *ses)
699 struct smb_hdr *smb_buffer_response;
700 LOGOFF_ANDX_REQ *pSMB;
704 cFYI(1, ("In SMBLogoff for session disconnect"));
710 atomic_dec(&ses->inUse);
711 if (atomic_read(&ses->inUse) > 0) {
715 rc = small_smb_init(SMB_COM_LOGOFF_ANDX, 2, NULL, (void **)&pSMB);
721 smb_buffer_response = (struct smb_hdr *)pSMB; /* BB removeme BB */
724 pSMB->hdr.Mid = GetNextMid(ses->server);
726 if(ses->server->secMode &
727 (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
728 pSMB->hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
731 pSMB->hdr.Uid = ses->Suid;
733 pSMB->AndXCommand = 0xFF;
734 rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB,
735 smb_buffer_response, &length, 0);
737 atomic_dec(&ses->server->socketUseCount);
738 if (atomic_read(&ses->server->socketUseCount) == 0) {
739 spin_lock(&GlobalMid_Lock);
740 ses->server->tcpStatus = CifsExiting;
741 spin_unlock(&GlobalMid_Lock);
746 cifs_small_buf_release(pSMB);
748 /* if session dead then we do not need to do ulogoff,
749 since server closed smb session, no sense reporting
757 CIFSSMBDelFile(const int xid, struct cifsTconInfo *tcon, const char *fileName,
758 const struct nls_table *nls_codepage, int remap)
760 DELETE_FILE_REQ *pSMB = NULL;
761 DELETE_FILE_RSP *pSMBr = NULL;
767 rc = smb_init(SMB_COM_DELETE, 1, tcon, (void **) &pSMB,
772 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
774 cifsConvertToUCS((__le16 *) pSMB->fileName, fileName,
775 PATH_MAX, nls_codepage, remap);
776 name_len++; /* trailing null */
778 } else { /* BB improve check for buffer overruns BB */
779 name_len = strnlen(fileName, PATH_MAX);
780 name_len++; /* trailing null */
781 strncpy(pSMB->fileName, fileName, name_len);
783 pSMB->SearchAttributes =
784 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM);
785 pSMB->BufferFormat = 0x04;
786 pSMB->hdr.smb_buf_length += name_len + 1;
787 pSMB->ByteCount = cpu_to_le16(name_len + 1);
788 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
789 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
790 cifs_stats_inc(&tcon->num_deletes);
792 cFYI(1, ("Error in RMFile = %d", rc));
795 cifs_buf_release(pSMB);
803 CIFSSMBRmDir(const int xid, struct cifsTconInfo *tcon, const char *dirName,
804 const struct nls_table *nls_codepage, int remap)
806 DELETE_DIRECTORY_REQ *pSMB = NULL;
807 DELETE_DIRECTORY_RSP *pSMBr = NULL;
812 cFYI(1, ("In CIFSSMBRmDir"));
814 rc = smb_init(SMB_COM_DELETE_DIRECTORY, 0, tcon, (void **) &pSMB,
819 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
820 name_len = cifsConvertToUCS((__le16 *) pSMB->DirName, dirName,
821 PATH_MAX, nls_codepage, remap);
822 name_len++; /* trailing null */
824 } else { /* BB improve check for buffer overruns BB */
825 name_len = strnlen(dirName, PATH_MAX);
826 name_len++; /* trailing null */
827 strncpy(pSMB->DirName, dirName, name_len);
830 pSMB->BufferFormat = 0x04;
831 pSMB->hdr.smb_buf_length += name_len + 1;
832 pSMB->ByteCount = cpu_to_le16(name_len + 1);
833 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
834 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
835 cifs_stats_inc(&tcon->num_rmdirs);
837 cFYI(1, ("Error in RMDir = %d", rc));
840 cifs_buf_release(pSMB);
847 CIFSSMBMkDir(const int xid, struct cifsTconInfo *tcon,
848 const char *name, const struct nls_table *nls_codepage, int remap)
851 CREATE_DIRECTORY_REQ *pSMB = NULL;
852 CREATE_DIRECTORY_RSP *pSMBr = NULL;
856 cFYI(1, ("In CIFSSMBMkDir"));
858 rc = smb_init(SMB_COM_CREATE_DIRECTORY, 0, tcon, (void **) &pSMB,
863 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
864 name_len = cifsConvertToUCS((__le16 *) pSMB->DirName, name,
865 PATH_MAX, nls_codepage, remap);
866 name_len++; /* trailing null */
868 } else { /* BB improve check for buffer overruns BB */
869 name_len = strnlen(name, PATH_MAX);
870 name_len++; /* trailing null */
871 strncpy(pSMB->DirName, name, name_len);
874 pSMB->BufferFormat = 0x04;
875 pSMB->hdr.smb_buf_length += name_len + 1;
876 pSMB->ByteCount = cpu_to_le16(name_len + 1);
877 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
878 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
879 cifs_stats_inc(&tcon->num_mkdirs);
881 cFYI(1, ("Error in Mkdir = %d", rc));
884 cifs_buf_release(pSMB);
890 static __u16 convert_disposition(int disposition)
894 switch (disposition) {
896 ofun = SMBOPEN_OCREATE | SMBOPEN_OTRUNC;
899 ofun = SMBOPEN_OAPPEND;
902 ofun = SMBOPEN_OCREATE;
905 ofun = SMBOPEN_OCREATE | SMBOPEN_OAPPEND;
908 ofun = SMBOPEN_OTRUNC;
910 case FILE_OVERWRITE_IF:
911 ofun = SMBOPEN_OCREATE | SMBOPEN_OTRUNC;
914 cFYI(1,("unknown disposition %d",disposition));
915 ofun = SMBOPEN_OAPPEND; /* regular open */
921 SMBLegacyOpen(const int xid, struct cifsTconInfo *tcon,
922 const char *fileName, const int openDisposition,
923 const int access_flags, const int create_options, __u16 * netfid,
924 int *pOplock, FILE_ALL_INFO * pfile_info,
925 const struct nls_table *nls_codepage, int remap)
928 OPENX_REQ *pSMB = NULL;
929 OPENX_RSP *pSMBr = NULL;
935 rc = smb_init(SMB_COM_OPEN_ANDX, 15, tcon, (void **) &pSMB,
940 pSMB->AndXCommand = 0xFF; /* none */
942 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
943 count = 1; /* account for one byte pad to word boundary */
945 cifsConvertToUCS((__le16 *) (pSMB->fileName + 1),
946 fileName, PATH_MAX, nls_codepage, remap);
947 name_len++; /* trailing null */
949 } else { /* BB improve check for buffer overruns BB */
950 count = 0; /* no pad */
951 name_len = strnlen(fileName, PATH_MAX);
952 name_len++; /* trailing null */
953 strncpy(pSMB->fileName, fileName, name_len);
955 if (*pOplock & REQ_OPLOCK)
956 pSMB->OpenFlags = cpu_to_le16(REQ_OPLOCK);
957 else if (*pOplock & REQ_BATCHOPLOCK) {
958 pSMB->OpenFlags = cpu_to_le16(REQ_BATCHOPLOCK);
960 pSMB->OpenFlags |= cpu_to_le16(REQ_MORE_INFO);
961 /* BB fixme add conversion for access_flags to bits 0 - 2 of mode */
967 pSMB->Mode = cpu_to_le16(2);
968 pSMB->Mode |= cpu_to_le16(0x40); /* deny none */
969 /* set file as system file if special file such
970 as fifo and server expecting SFU style and
971 no Unix extensions */
973 if(create_options & CREATE_OPTION_SPECIAL)
974 pSMB->FileAttributes = cpu_to_le16(ATTR_SYSTEM);
976 pSMB->FileAttributes = cpu_to_le16(0/*ATTR_NORMAL*/); /* BB FIXME */
978 /* if ((omode & S_IWUGO) == 0)
979 pSMB->FileAttributes |= cpu_to_le32(ATTR_READONLY);*/
980 /* Above line causes problems due to vfs splitting create into two
981 pieces - need to set mode after file created not while it is
985 /* pSMB->CreateOptions = cpu_to_le32(create_options & CREATE_OPTIONS_MASK); */
986 /* BB FIXME END BB */
988 pSMB->Sattr = cpu_to_le16(ATTR_HIDDEN | ATTR_SYSTEM | ATTR_DIRECTORY);
989 pSMB->OpenFunction = cpu_to_le16(convert_disposition(openDisposition));
991 pSMB->hdr.smb_buf_length += count;
993 pSMB->ByteCount = cpu_to_le16(count);
994 /* long_op set to 1 to allow for oplock break timeouts */
995 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
996 (struct smb_hdr *) pSMBr, &bytes_returned, 1);
997 cifs_stats_inc(&tcon->num_opens);
999 cFYI(1, ("Error in Open = %d", rc));
1001 /* BB verify if wct == 15 */
1003 /* *pOplock = pSMBr->OplockLevel; */ /* BB take from action field BB */
1005 *netfid = pSMBr->Fid; /* cifs fid stays in le */
1006 /* Let caller know file was created so we can set the mode. */
1007 /* Do we care about the CreateAction in any other cases? */
1009 /* if(cpu_to_le32(FILE_CREATE) == pSMBr->CreateAction)
1010 *pOplock |= CIFS_CREATE_ACTION; */
1014 pfile_info->CreationTime = 0; /* BB convert CreateTime*/
1015 pfile_info->LastAccessTime = 0; /* BB fixme */
1016 pfile_info->LastWriteTime = 0; /* BB fixme */
1017 pfile_info->ChangeTime = 0; /* BB fixme */
1018 pfile_info->Attributes =
1019 cpu_to_le32(le16_to_cpu(pSMBr->FileAttributes));
1020 /* the file_info buf is endian converted by caller */
1021 pfile_info->AllocationSize =
1022 cpu_to_le64(le32_to_cpu(pSMBr->EndOfFile));
1023 pfile_info->EndOfFile = pfile_info->AllocationSize;
1024 pfile_info->NumberOfLinks = cpu_to_le32(1);
1028 cifs_buf_release(pSMB);
1035 CIFSSMBOpen(const int xid, struct cifsTconInfo *tcon,
1036 const char *fileName, const int openDisposition,
1037 const int access_flags, const int create_options, __u16 * netfid,
1038 int *pOplock, FILE_ALL_INFO * pfile_info,
1039 const struct nls_table *nls_codepage, int remap)
1042 OPEN_REQ *pSMB = NULL;
1043 OPEN_RSP *pSMBr = NULL;
1049 rc = smb_init(SMB_COM_NT_CREATE_ANDX, 24, tcon, (void **) &pSMB,
1054 pSMB->AndXCommand = 0xFF; /* none */
1056 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1057 count = 1; /* account for one byte pad to word boundary */
1059 cifsConvertToUCS((__le16 *) (pSMB->fileName + 1),
1060 fileName, PATH_MAX, nls_codepage, remap);
1061 name_len++; /* trailing null */
1063 pSMB->NameLength = cpu_to_le16(name_len);
1064 } else { /* BB improve check for buffer overruns BB */
1065 count = 0; /* no pad */
1066 name_len = strnlen(fileName, PATH_MAX);
1067 name_len++; /* trailing null */
1068 pSMB->NameLength = cpu_to_le16(name_len);
1069 strncpy(pSMB->fileName, fileName, name_len);
1071 if (*pOplock & REQ_OPLOCK)
1072 pSMB->OpenFlags = cpu_to_le32(REQ_OPLOCK);
1073 else if (*pOplock & REQ_BATCHOPLOCK) {
1074 pSMB->OpenFlags = cpu_to_le32(REQ_BATCHOPLOCK);
1076 pSMB->DesiredAccess = cpu_to_le32(access_flags);
1077 pSMB->AllocationSize = 0;
1078 /* set file as system file if special file such
1079 as fifo and server expecting SFU style and
1080 no Unix extensions */
1081 if(create_options & CREATE_OPTION_SPECIAL)
1082 pSMB->FileAttributes = cpu_to_le32(ATTR_SYSTEM);
1084 pSMB->FileAttributes = cpu_to_le32(ATTR_NORMAL);
1085 /* XP does not handle ATTR_POSIX_SEMANTICS */
1086 /* but it helps speed up case sensitive checks for other
1087 servers such as Samba */
1088 if (tcon->ses->capabilities & CAP_UNIX)
1089 pSMB->FileAttributes |= cpu_to_le32(ATTR_POSIX_SEMANTICS);
1091 /* if ((omode & S_IWUGO) == 0)
1092 pSMB->FileAttributes |= cpu_to_le32(ATTR_READONLY);*/
1093 /* Above line causes problems due to vfs splitting create into two
1094 pieces - need to set mode after file created not while it is
1096 pSMB->ShareAccess = cpu_to_le32(FILE_SHARE_ALL);
1097 pSMB->CreateDisposition = cpu_to_le32(openDisposition);
1098 pSMB->CreateOptions = cpu_to_le32(create_options & CREATE_OPTIONS_MASK);
1099 /* BB Expirement with various impersonation levels and verify */
1100 pSMB->ImpersonationLevel = cpu_to_le32(SECURITY_IMPERSONATION);
1101 pSMB->SecurityFlags =
1102 SECURITY_CONTEXT_TRACKING | SECURITY_EFFECTIVE_ONLY;
1105 pSMB->hdr.smb_buf_length += count;
1107 pSMB->ByteCount = cpu_to_le16(count);
1108 /* long_op set to 1 to allow for oplock break timeouts */
1109 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1110 (struct smb_hdr *) pSMBr, &bytes_returned, 1);
1111 cifs_stats_inc(&tcon->num_opens);
1113 cFYI(1, ("Error in Open = %d", rc));
1115 *pOplock = pSMBr->OplockLevel; /* 1 byte no need to le_to_cpu */
1116 *netfid = pSMBr->Fid; /* cifs fid stays in le */
1117 /* Let caller know file was created so we can set the mode. */
1118 /* Do we care about the CreateAction in any other cases? */
1119 if(cpu_to_le32(FILE_CREATE) == pSMBr->CreateAction)
1120 *pOplock |= CIFS_CREATE_ACTION;
1122 memcpy((char *)pfile_info,(char *)&pSMBr->CreationTime,
1123 36 /* CreationTime to Attributes */);
1124 /* the file_info buf is endian converted by caller */
1125 pfile_info->AllocationSize = pSMBr->AllocationSize;
1126 pfile_info->EndOfFile = pSMBr->EndOfFile;
1127 pfile_info->NumberOfLinks = cpu_to_le32(1);
1131 cifs_buf_release(pSMB);
1138 CIFSSMBRead(const int xid, struct cifsTconInfo *tcon,
1139 const int netfid, const unsigned int count,
1140 const __u64 lseek, unsigned int *nbytes, char **buf,
1144 READ_REQ *pSMB = NULL;
1145 READ_RSP *pSMBr = NULL;
1146 char *pReadData = NULL;
1148 int resp_buf_type = 0;
1151 cFYI(1,("Reading %d bytes on fid %d",count,netfid));
1152 if(tcon->ses->capabilities & CAP_LARGE_FILES)
1155 wct = 10; /* old style read */
1158 rc = small_smb_init(SMB_COM_READ_ANDX, wct, tcon, (void **) &pSMB);
1162 /* tcon and ses pointer are checked in smb_init */
1163 if (tcon->ses->server == NULL)
1164 return -ECONNABORTED;
1166 pSMB->AndXCommand = 0xFF; /* none */
1168 pSMB->OffsetLow = cpu_to_le32(lseek & 0xFFFFFFFF);
1170 pSMB->OffsetHigh = cpu_to_le32(lseek >> 32);
1171 else if((lseek >> 32) > 0) /* can not handle this big offset for old */
1174 pSMB->Remaining = 0;
1175 pSMB->MaxCount = cpu_to_le16(count & 0xFFFF);
1176 pSMB->MaxCountHigh = cpu_to_le32(count >> 16);
1178 pSMB->ByteCount = 0; /* no need to do le conversion since 0 */
1180 /* old style read */
1181 struct smb_com_readx_req * pSMBW =
1182 (struct smb_com_readx_req *)pSMB;
1183 pSMBW->ByteCount = 0;
1186 iov[0].iov_base = (char *)pSMB;
1187 iov[0].iov_len = pSMB->hdr.smb_buf_length + 4;
1188 rc = SendReceive2(xid, tcon->ses, iov,
1191 cifs_stats_inc(&tcon->num_reads);
1192 pSMBr = (READ_RSP *)iov[0].iov_base;
1194 cERROR(1, ("Send error in read = %d", rc));
1196 int data_length = le16_to_cpu(pSMBr->DataLengthHigh);
1197 data_length = data_length << 16;
1198 data_length += le16_to_cpu(pSMBr->DataLength);
1199 *nbytes = data_length;
1201 /*check that DataLength would not go beyond end of SMB */
1202 if ((data_length > CIFSMaxBufSize)
1203 || (data_length > count)) {
1204 cFYI(1,("bad length %d for count %d",data_length,count));
1208 pReadData = (char *) (&pSMBr->hdr.Protocol) +
1209 le16_to_cpu(pSMBr->DataOffset);
1210 /* if(rc = copy_to_user(buf, pReadData, data_length)) {
1211 cERROR(1,("Faulting on read rc = %d",rc));
1213 }*/ /* can not use copy_to_user when using page cache*/
1215 memcpy(*buf,pReadData,data_length);
1219 /* cifs_small_buf_release(pSMB); */ /* Freed earlier now in SendReceive2 */
1221 if(resp_buf_type == CIFS_SMALL_BUFFER)
1222 cifs_small_buf_release(iov[0].iov_base);
1223 else if(resp_buf_type == CIFS_LARGE_BUFFER)
1224 cifs_buf_release(iov[0].iov_base);
1225 } else if(resp_buf_type != CIFS_NO_BUFFER) {
1226 /* return buffer to caller to free */
1227 *buf = iov[0].iov_base;
1228 if(resp_buf_type == CIFS_SMALL_BUFFER)
1229 *pbuf_type = CIFS_SMALL_BUFFER;
1230 else if(resp_buf_type == CIFS_LARGE_BUFFER)
1231 *pbuf_type = CIFS_LARGE_BUFFER;
1232 } /* else no valid buffer on return - leave as null */
1234 /* Note: On -EAGAIN error only caller can retry on handle based calls
1235 since file handle passed in no longer valid */
1241 CIFSSMBWrite(const int xid, struct cifsTconInfo *tcon,
1242 const int netfid, const unsigned int count,
1243 const __u64 offset, unsigned int *nbytes, const char *buf,
1244 const char __user * ubuf, const int long_op)
1247 WRITE_REQ *pSMB = NULL;
1248 WRITE_RSP *pSMBr = NULL;
1249 int bytes_returned, wct;
1253 /* cFYI(1,("write at %lld %d bytes",offset,count));*/
1254 if(tcon->ses == NULL)
1255 return -ECONNABORTED;
1257 if(tcon->ses->capabilities & CAP_LARGE_FILES)
1262 rc = smb_init(SMB_COM_WRITE_ANDX, wct, tcon, (void **) &pSMB,
1266 /* tcon and ses pointer are checked in smb_init */
1267 if (tcon->ses->server == NULL)
1268 return -ECONNABORTED;
1270 pSMB->AndXCommand = 0xFF; /* none */
1272 pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF);
1274 pSMB->OffsetHigh = cpu_to_le32(offset >> 32);
1275 else if((offset >> 32) > 0) /* can not handle this big offset for old */
1278 pSMB->Reserved = 0xFFFFFFFF;
1279 pSMB->WriteMode = 0;
1280 pSMB->Remaining = 0;
1282 /* Can increase buffer size if buffer is big enough in some cases - ie we
1283 can send more if LARGE_WRITE_X capability returned by the server and if
1284 our buffer is big enough or if we convert to iovecs on socket writes
1285 and eliminate the copy to the CIFS buffer */
1286 if(tcon->ses->capabilities & CAP_LARGE_WRITE_X) {
1287 bytes_sent = min_t(const unsigned int, CIFSMaxBufSize, count);
1289 bytes_sent = (tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE)
1293 if (bytes_sent > count)
1296 cpu_to_le16(offsetof(struct smb_com_write_req,Data) - 4);
1298 memcpy(pSMB->Data,buf,bytes_sent);
1300 if(copy_from_user(pSMB->Data,ubuf,bytes_sent)) {
1301 cifs_buf_release(pSMB);
1304 } else if (count != 0) {
1306 cifs_buf_release(pSMB);
1308 } /* else setting file size with write of zero bytes */
1310 byte_count = bytes_sent + 1; /* pad */
1311 else /* wct == 12 */ {
1312 byte_count = bytes_sent + 5; /* bigger pad, smaller smb hdr */
1314 pSMB->DataLengthLow = cpu_to_le16(bytes_sent & 0xFFFF);
1315 pSMB->DataLengthHigh = cpu_to_le16(bytes_sent >> 16);
1316 pSMB->hdr.smb_buf_length += byte_count;
1319 pSMB->ByteCount = cpu_to_le16(byte_count);
1320 else { /* old style write has byte count 4 bytes earlier so 4 bytes pad */
1321 struct smb_com_writex_req * pSMBW =
1322 (struct smb_com_writex_req *)pSMB;
1323 pSMBW->ByteCount = cpu_to_le16(byte_count);
1326 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1327 (struct smb_hdr *) pSMBr, &bytes_returned, long_op);
1328 cifs_stats_inc(&tcon->num_writes);
1330 cFYI(1, ("Send error in write = %d", rc));
1333 *nbytes = le16_to_cpu(pSMBr->CountHigh);
1334 *nbytes = (*nbytes) << 16;
1335 *nbytes += le16_to_cpu(pSMBr->Count);
1338 cifs_buf_release(pSMB);
1340 /* Note: On -EAGAIN error only caller can retry on handle based calls
1341 since file handle passed in no longer valid */
1347 CIFSSMBWrite2(const int xid, struct cifsTconInfo *tcon,
1348 const int netfid, const unsigned int count,
1349 const __u64 offset, unsigned int *nbytes, struct kvec *iov,
1350 int n_vec, const int long_op)
1353 WRITE_REQ *pSMB = NULL;
1356 int resp_buf_type = 0;
1358 cFYI(1,("write2 at %lld %d bytes", (long long)offset, count));
1360 if(tcon->ses->capabilities & CAP_LARGE_FILES)
1364 rc = small_smb_init(SMB_COM_WRITE_ANDX, wct, tcon, (void **) &pSMB);
1367 /* tcon and ses pointer are checked in smb_init */
1368 if (tcon->ses->server == NULL)
1369 return -ECONNABORTED;
1371 pSMB->AndXCommand = 0xFF; /* none */
1373 pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF);
1375 pSMB->OffsetHigh = cpu_to_le32(offset >> 32);
1376 else if((offset >> 32) > 0) /* can not handle this big offset for old */
1378 pSMB->Reserved = 0xFFFFFFFF;
1379 pSMB->WriteMode = 0;
1380 pSMB->Remaining = 0;
1383 cpu_to_le16(offsetof(struct smb_com_write_req,Data) - 4);
1385 pSMB->DataLengthLow = cpu_to_le16(count & 0xFFFF);
1386 pSMB->DataLengthHigh = cpu_to_le16(count >> 16);
1387 smb_hdr_len = pSMB->hdr.smb_buf_length + 1; /* hdr + 1 byte pad */
1389 pSMB->hdr.smb_buf_length += count+1;
1390 else /* wct == 12 */
1391 pSMB->hdr.smb_buf_length += count+5; /* smb data starts later */
1393 pSMB->ByteCount = cpu_to_le16(count + 1);
1394 else /* wct == 12 */ /* bigger pad, smaller smb hdr, keep offset ok */ {
1395 struct smb_com_writex_req * pSMBW =
1396 (struct smb_com_writex_req *)pSMB;
1397 pSMBW->ByteCount = cpu_to_le16(count + 5);
1399 iov[0].iov_base = pSMB;
1401 iov[0].iov_len = smb_hdr_len + 4;
1402 else /* wct == 12 pad bigger by four bytes */
1403 iov[0].iov_len = smb_hdr_len + 8;
1406 rc = SendReceive2(xid, tcon->ses, iov, n_vec + 1, &resp_buf_type,
1408 cifs_stats_inc(&tcon->num_writes);
1410 cFYI(1, ("Send error Write2 = %d", rc));
1412 } else if(resp_buf_type == 0) {
1413 /* presumably this can not happen, but best to be safe */
1417 WRITE_RSP * pSMBr = (WRITE_RSP *)iov[0].iov_base;
1418 *nbytes = le16_to_cpu(pSMBr->CountHigh);
1419 *nbytes = (*nbytes) << 16;
1420 *nbytes += le16_to_cpu(pSMBr->Count);
1423 /* cifs_small_buf_release(pSMB); */ /* Freed earlier now in SendReceive2 */
1424 if(resp_buf_type == CIFS_SMALL_BUFFER)
1425 cifs_small_buf_release(iov[0].iov_base);
1426 else if(resp_buf_type == CIFS_LARGE_BUFFER)
1427 cifs_buf_release(iov[0].iov_base);
1429 /* Note: On -EAGAIN error only caller can retry on handle based calls
1430 since file handle passed in no longer valid */
1437 CIFSSMBLock(const int xid, struct cifsTconInfo *tcon,
1438 const __u16 smb_file_id, const __u64 len,
1439 const __u64 offset, const __u32 numUnlock,
1440 const __u32 numLock, const __u8 lockType, const int waitFlag)
1443 LOCK_REQ *pSMB = NULL;
1444 LOCK_RSP *pSMBr = NULL;
1449 cFYI(1, ("In CIFSSMBLock - timeout %d numLock %d",waitFlag,numLock));
1450 rc = small_smb_init(SMB_COM_LOCKING_ANDX, 8, tcon, (void **) &pSMB);
1455 pSMBr = (LOCK_RSP *)pSMB; /* BB removeme BB */
1457 if(lockType == LOCKING_ANDX_OPLOCK_RELEASE) {
1458 timeout = -1; /* no response expected */
1460 } else if (waitFlag == TRUE) {
1461 timeout = 3; /* blocking operation, no timeout */
1462 pSMB->Timeout = cpu_to_le32(-1);/* blocking - do not time out */
1467 pSMB->NumberOfLocks = cpu_to_le16(numLock);
1468 pSMB->NumberOfUnlocks = cpu_to_le16(numUnlock);
1469 pSMB->LockType = lockType;
1470 pSMB->AndXCommand = 0xFF; /* none */
1471 pSMB->Fid = smb_file_id; /* netfid stays le */
1473 if((numLock != 0) || (numUnlock != 0)) {
1474 pSMB->Locks[0].Pid = cpu_to_le16(current->tgid);
1475 /* BB where to store pid high? */
1476 pSMB->Locks[0].LengthLow = cpu_to_le32((u32)len);
1477 pSMB->Locks[0].LengthHigh = cpu_to_le32((u32)(len>>32));
1478 pSMB->Locks[0].OffsetLow = cpu_to_le32((u32)offset);
1479 pSMB->Locks[0].OffsetHigh = cpu_to_le32((u32)(offset>>32));
1480 count = sizeof(LOCKING_ANDX_RANGE);
1485 pSMB->hdr.smb_buf_length += count;
1486 pSMB->ByteCount = cpu_to_le16(count);
1489 rc = SendReceiveBlockingLock(xid, tcon, (struct smb_hdr *) pSMB,
1490 (struct smb_hdr *) pSMBr, &bytes_returned);
1492 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1493 (struct smb_hdr *) pSMBr, &bytes_returned, timeout);
1495 cifs_stats_inc(&tcon->num_locks);
1497 cFYI(1, ("Send error in Lock = %d", rc));
1499 cifs_small_buf_release(pSMB);
1501 /* Note: On -EAGAIN error only caller can retry on handle based calls
1502 since file handle passed in no longer valid */
1507 CIFSSMBPosixLock(const int xid, struct cifsTconInfo *tcon,
1508 const __u16 smb_file_id, const int get_flag, const __u64 len,
1509 struct file_lock *pLockData, const __u16 lock_type,
1512 struct smb_com_transaction2_sfi_req *pSMB = NULL;
1513 struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
1515 struct cifs_posix_lock *parm_data;
1518 int bytes_returned = 0;
1519 __u16 params, param_offset, offset, byte_count, count;
1521 cFYI(1, ("Posix Lock"));
1523 if(pLockData == NULL)
1526 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
1531 pSMBr = (struct smb_com_transaction2_sfi_rsp *)pSMB;
1534 pSMB->MaxSetupCount = 0;
1537 pSMB->Reserved2 = 0;
1538 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
1539 offset = param_offset + params;
1541 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
1543 count = sizeof(struct cifs_posix_lock);
1544 pSMB->MaxParameterCount = cpu_to_le16(2);
1545 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB PDU from sess */
1546 pSMB->SetupCount = 1;
1547 pSMB->Reserved3 = 0;
1549 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION);
1551 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
1552 byte_count = 3 /* pad */ + params + count;
1553 pSMB->DataCount = cpu_to_le16(count);
1554 pSMB->ParameterCount = cpu_to_le16(params);
1555 pSMB->TotalDataCount = pSMB->DataCount;
1556 pSMB->TotalParameterCount = pSMB->ParameterCount;
1557 pSMB->ParameterOffset = cpu_to_le16(param_offset);
1558 parm_data = (struct cifs_posix_lock *)
1559 (((char *) &pSMB->hdr.Protocol) + offset);
1561 parm_data->lock_type = cpu_to_le16(lock_type);
1563 timeout = 3; /* blocking operation, no timeout */
1564 parm_data->lock_flags = cpu_to_le16(1);
1565 pSMB->Timeout = cpu_to_le32(-1);
1569 parm_data->pid = cpu_to_le32(current->tgid);
1570 parm_data->start = cpu_to_le64(pLockData->fl_start);
1571 parm_data->length = cpu_to_le64(len); /* normalize negative numbers */
1573 pSMB->DataOffset = cpu_to_le16(offset);
1574 pSMB->Fid = smb_file_id;
1575 pSMB->InformationLevel = cpu_to_le16(SMB_SET_POSIX_LOCK);
1576 pSMB->Reserved4 = 0;
1577 pSMB->hdr.smb_buf_length += byte_count;
1578 pSMB->ByteCount = cpu_to_le16(byte_count);
1580 rc = SendReceiveBlockingLock(xid, tcon, (struct smb_hdr *) pSMB,
1581 (struct smb_hdr *) pSMBr, &bytes_returned);
1583 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1584 (struct smb_hdr *) pSMBr, &bytes_returned, timeout);
1588 cFYI(1, ("Send error in Posix Lock = %d", rc));
1589 } else if (get_flag) {
1590 /* lock structure can be returned on get */
1593 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
1595 if (rc || (pSMBr->ByteCount < sizeof(struct cifs_posix_lock))) {
1596 rc = -EIO; /* bad smb */
1599 if(pLockData == NULL) {
1603 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
1604 data_count = le16_to_cpu(pSMBr->t2.DataCount);
1605 if(data_count < sizeof(struct cifs_posix_lock)) {
1609 parm_data = (struct cifs_posix_lock *)
1610 ((char *)&pSMBr->hdr.Protocol + data_offset);
1611 if(parm_data->lock_type == cpu_to_le16(CIFS_UNLCK))
1612 pLockData->fl_type = F_UNLCK;
1617 cifs_small_buf_release(pSMB);
1619 /* Note: On -EAGAIN error only caller can retry on handle based calls
1620 since file handle passed in no longer valid */
1627 CIFSSMBClose(const int xid, struct cifsTconInfo *tcon, int smb_file_id)
1630 CLOSE_REQ *pSMB = NULL;
1631 CLOSE_RSP *pSMBr = NULL;
1633 cFYI(1, ("In CIFSSMBClose"));
1635 /* do not retry on dead session on close */
1636 rc = small_smb_init(SMB_COM_CLOSE, 3, tcon, (void **) &pSMB);
1642 pSMBr = (CLOSE_RSP *)pSMB; /* BB removeme BB */
1644 pSMB->FileID = (__u16) smb_file_id;
1645 pSMB->LastWriteTime = 0;
1646 pSMB->ByteCount = 0;
1647 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1648 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1649 cifs_stats_inc(&tcon->num_closes);
1652 /* EINTR is expected when user ctl-c to kill app */
1653 cERROR(1, ("Send error in Close = %d", rc));
1657 cifs_small_buf_release(pSMB);
1659 /* Since session is dead, file will be closed on server already */
1667 CIFSSMBRename(const int xid, struct cifsTconInfo *tcon,
1668 const char *fromName, const char *toName,
1669 const struct nls_table *nls_codepage, int remap)
1672 RENAME_REQ *pSMB = NULL;
1673 RENAME_RSP *pSMBr = NULL;
1675 int name_len, name_len2;
1678 cFYI(1, ("In CIFSSMBRename"));
1680 rc = smb_init(SMB_COM_RENAME, 1, tcon, (void **) &pSMB,
1685 pSMB->BufferFormat = 0x04;
1686 pSMB->SearchAttributes =
1687 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
1690 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1692 cifsConvertToUCS((__le16 *) pSMB->OldFileName, fromName,
1693 PATH_MAX, nls_codepage, remap);
1694 name_len++; /* trailing null */
1696 pSMB->OldFileName[name_len] = 0x04; /* pad */
1697 /* protocol requires ASCII signature byte on Unicode string */
1698 pSMB->OldFileName[name_len + 1] = 0x00;
1700 cifsConvertToUCS((__le16 *) &pSMB->OldFileName[name_len + 2],
1701 toName, PATH_MAX, nls_codepage, remap);
1702 name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
1703 name_len2 *= 2; /* convert to bytes */
1704 } else { /* BB improve the check for buffer overruns BB */
1705 name_len = strnlen(fromName, PATH_MAX);
1706 name_len++; /* trailing null */
1707 strncpy(pSMB->OldFileName, fromName, name_len);
1708 name_len2 = strnlen(toName, PATH_MAX);
1709 name_len2++; /* trailing null */
1710 pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */
1711 strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2);
1712 name_len2++; /* trailing null */
1713 name_len2++; /* signature byte */
1716 count = 1 /* 1st signature byte */ + name_len + name_len2;
1717 pSMB->hdr.smb_buf_length += count;
1718 pSMB->ByteCount = cpu_to_le16(count);
1720 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1721 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1722 cifs_stats_inc(&tcon->num_renames);
1724 cFYI(1, ("Send error in rename = %d", rc));
1727 cifs_buf_release(pSMB);
1735 int CIFSSMBRenameOpenFile(const int xid,struct cifsTconInfo *pTcon,
1736 int netfid, char * target_name,
1737 const struct nls_table * nls_codepage, int remap)
1739 struct smb_com_transaction2_sfi_req *pSMB = NULL;
1740 struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
1741 struct set_file_rename * rename_info;
1743 char dummy_string[30];
1745 int bytes_returned = 0;
1747 __u16 params, param_offset, offset, count, byte_count;
1749 cFYI(1, ("Rename to File by handle"));
1750 rc = smb_init(SMB_COM_TRANSACTION2, 15, pTcon, (void **) &pSMB,
1756 pSMB->MaxSetupCount = 0;
1760 pSMB->Reserved2 = 0;
1761 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
1762 offset = param_offset + params;
1764 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
1765 rename_info = (struct set_file_rename *) data_offset;
1766 pSMB->MaxParameterCount = cpu_to_le16(2);
1767 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB PDU from sess */
1768 pSMB->SetupCount = 1;
1769 pSMB->Reserved3 = 0;
1770 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
1771 byte_count = 3 /* pad */ + params;
1772 pSMB->ParameterCount = cpu_to_le16(params);
1773 pSMB->TotalParameterCount = pSMB->ParameterCount;
1774 pSMB->ParameterOffset = cpu_to_le16(param_offset);
1775 pSMB->DataOffset = cpu_to_le16(offset);
1776 /* construct random name ".cifs_tmp<inodenum><mid>" */
1777 rename_info->overwrite = cpu_to_le32(1);
1778 rename_info->root_fid = 0;
1779 /* unicode only call */
1780 if(target_name == NULL) {
1781 sprintf(dummy_string,"cifs%x",pSMB->hdr.Mid);
1782 len_of_str = cifsConvertToUCS((__le16 *)rename_info->target_name,
1783 dummy_string, 24, nls_codepage, remap);
1785 len_of_str = cifsConvertToUCS((__le16 *)rename_info->target_name,
1786 target_name, PATH_MAX, nls_codepage, remap);
1788 rename_info->target_name_len = cpu_to_le32(2 * len_of_str);
1789 count = 12 /* sizeof(struct set_file_rename) */ + (2 * len_of_str) + 2;
1790 byte_count += count;
1791 pSMB->DataCount = cpu_to_le16(count);
1792 pSMB->TotalDataCount = pSMB->DataCount;
1794 pSMB->InformationLevel =
1795 cpu_to_le16(SMB_SET_FILE_RENAME_INFORMATION);
1796 pSMB->Reserved4 = 0;
1797 pSMB->hdr.smb_buf_length += byte_count;
1798 pSMB->ByteCount = cpu_to_le16(byte_count);
1799 rc = SendReceive(xid, pTcon->ses, (struct smb_hdr *) pSMB,
1800 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1801 cifs_stats_inc(&pTcon->num_t2renames);
1803 cFYI(1,("Send error in Rename (by file handle) = %d", rc));
1806 cifs_buf_release(pSMB);
1808 /* Note: On -EAGAIN error only caller can retry on handle based calls
1809 since file handle passed in no longer valid */
1815 CIFSSMBCopy(const int xid, struct cifsTconInfo *tcon, const char * fromName,
1816 const __u16 target_tid, const char *toName, const int flags,
1817 const struct nls_table *nls_codepage, int remap)
1820 COPY_REQ *pSMB = NULL;
1821 COPY_RSP *pSMBr = NULL;
1823 int name_len, name_len2;
1826 cFYI(1, ("In CIFSSMBCopy"));
1828 rc = smb_init(SMB_COM_COPY, 1, tcon, (void **) &pSMB,
1833 pSMB->BufferFormat = 0x04;
1834 pSMB->Tid2 = target_tid;
1836 pSMB->Flags = cpu_to_le16(flags & COPY_TREE);
1838 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1839 name_len = cifsConvertToUCS((__le16 *) pSMB->OldFileName,
1840 fromName, PATH_MAX, nls_codepage,
1842 name_len++; /* trailing null */
1844 pSMB->OldFileName[name_len] = 0x04; /* pad */
1845 /* protocol requires ASCII signature byte on Unicode string */
1846 pSMB->OldFileName[name_len + 1] = 0x00;
1847 name_len2 = cifsConvertToUCS((__le16 *)&pSMB->OldFileName[name_len + 2],
1848 toName, PATH_MAX, nls_codepage, remap);
1849 name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
1850 name_len2 *= 2; /* convert to bytes */
1851 } else { /* BB improve the check for buffer overruns BB */
1852 name_len = strnlen(fromName, PATH_MAX);
1853 name_len++; /* trailing null */
1854 strncpy(pSMB->OldFileName, fromName, name_len);
1855 name_len2 = strnlen(toName, PATH_MAX);
1856 name_len2++; /* trailing null */
1857 pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */
1858 strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2);
1859 name_len2++; /* trailing null */
1860 name_len2++; /* signature byte */
1863 count = 1 /* 1st signature byte */ + name_len + name_len2;
1864 pSMB->hdr.smb_buf_length += count;
1865 pSMB->ByteCount = cpu_to_le16(count);
1867 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1868 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1870 cFYI(1, ("Send error in copy = %d with %d files copied",
1871 rc, le16_to_cpu(pSMBr->CopyCount)));
1874 cifs_buf_release(pSMB);
1883 CIFSUnixCreateSymLink(const int xid, struct cifsTconInfo *tcon,
1884 const char *fromName, const char *toName,
1885 const struct nls_table *nls_codepage)
1887 TRANSACTION2_SPI_REQ *pSMB = NULL;
1888 TRANSACTION2_SPI_RSP *pSMBr = NULL;
1891 int name_len_target;
1893 int bytes_returned = 0;
1894 __u16 params, param_offset, offset, byte_count;
1896 cFYI(1, ("In Symlink Unix style"));
1898 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
1903 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1905 cifs_strtoUCS((__le16 *) pSMB->FileName, fromName, PATH_MAX
1906 /* find define for this maxpathcomponent */
1908 name_len++; /* trailing null */
1911 } else { /* BB improve the check for buffer overruns BB */
1912 name_len = strnlen(fromName, PATH_MAX);
1913 name_len++; /* trailing null */
1914 strncpy(pSMB->FileName, fromName, name_len);
1916 params = 6 + name_len;
1917 pSMB->MaxSetupCount = 0;
1921 pSMB->Reserved2 = 0;
1922 param_offset = offsetof(struct smb_com_transaction2_spi_req,
1923 InformationLevel) - 4;
1924 offset = param_offset + params;
1926 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
1927 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1929 cifs_strtoUCS((__le16 *) data_offset, toName, PATH_MAX
1930 /* find define for this maxpathcomponent */
1932 name_len_target++; /* trailing null */
1933 name_len_target *= 2;
1934 } else { /* BB improve the check for buffer overruns BB */
1935 name_len_target = strnlen(toName, PATH_MAX);
1936 name_len_target++; /* trailing null */
1937 strncpy(data_offset, toName, name_len_target);
1940 pSMB->MaxParameterCount = cpu_to_le16(2);
1941 /* BB find exact max on data count below from sess */
1942 pSMB->MaxDataCount = cpu_to_le16(1000);
1943 pSMB->SetupCount = 1;
1944 pSMB->Reserved3 = 0;
1945 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
1946 byte_count = 3 /* pad */ + params + name_len_target;
1947 pSMB->DataCount = cpu_to_le16(name_len_target);
1948 pSMB->ParameterCount = cpu_to_le16(params);
1949 pSMB->TotalDataCount = pSMB->DataCount;
1950 pSMB->TotalParameterCount = pSMB->ParameterCount;
1951 pSMB->ParameterOffset = cpu_to_le16(param_offset);
1952 pSMB->DataOffset = cpu_to_le16(offset);
1953 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_LINK);
1954 pSMB->Reserved4 = 0;
1955 pSMB->hdr.smb_buf_length += byte_count;
1956 pSMB->ByteCount = cpu_to_le16(byte_count);
1957 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1958 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1959 cifs_stats_inc(&tcon->num_symlinks);
1962 ("Send error in SetPathInfo (create symlink) = %d",
1967 cifs_buf_release(pSMB);
1970 goto createSymLinkRetry;
1976 CIFSUnixCreateHardLink(const int xid, struct cifsTconInfo *tcon,
1977 const char *fromName, const char *toName,
1978 const struct nls_table *nls_codepage, int remap)
1980 TRANSACTION2_SPI_REQ *pSMB = NULL;
1981 TRANSACTION2_SPI_RSP *pSMBr = NULL;
1984 int name_len_target;
1986 int bytes_returned = 0;
1987 __u16 params, param_offset, offset, byte_count;
1989 cFYI(1, ("In Create Hard link Unix style"));
1990 createHardLinkRetry:
1991 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
1996 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1997 name_len = cifsConvertToUCS((__le16 *) pSMB->FileName, toName,
1998 PATH_MAX, nls_codepage, remap);
1999 name_len++; /* trailing null */
2002 } else { /* BB improve the check for buffer overruns BB */
2003 name_len = strnlen(toName, PATH_MAX);
2004 name_len++; /* trailing null */
2005 strncpy(pSMB->FileName, toName, name_len);
2007 params = 6 + name_len;
2008 pSMB->MaxSetupCount = 0;
2012 pSMB->Reserved2 = 0;
2013 param_offset = offsetof(struct smb_com_transaction2_spi_req,
2014 InformationLevel) - 4;
2015 offset = param_offset + params;
2017 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
2018 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2020 cifsConvertToUCS((__le16 *) data_offset, fromName, PATH_MAX,
2021 nls_codepage, remap);
2022 name_len_target++; /* trailing null */
2023 name_len_target *= 2;
2024 } else { /* BB improve the check for buffer overruns BB */
2025 name_len_target = strnlen(fromName, PATH_MAX);
2026 name_len_target++; /* trailing null */
2027 strncpy(data_offset, fromName, name_len_target);
2030 pSMB->MaxParameterCount = cpu_to_le16(2);
2031 /* BB find exact max on data count below from sess*/
2032 pSMB->MaxDataCount = cpu_to_le16(1000);
2033 pSMB->SetupCount = 1;
2034 pSMB->Reserved3 = 0;
2035 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
2036 byte_count = 3 /* pad */ + params + name_len_target;
2037 pSMB->ParameterCount = cpu_to_le16(params);
2038 pSMB->TotalParameterCount = pSMB->ParameterCount;
2039 pSMB->DataCount = cpu_to_le16(name_len_target);
2040 pSMB->TotalDataCount = pSMB->DataCount;
2041 pSMB->ParameterOffset = cpu_to_le16(param_offset);
2042 pSMB->DataOffset = cpu_to_le16(offset);
2043 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_HLINK);
2044 pSMB->Reserved4 = 0;
2045 pSMB->hdr.smb_buf_length += byte_count;
2046 pSMB->ByteCount = cpu_to_le16(byte_count);
2047 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2048 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2049 cifs_stats_inc(&tcon->num_hardlinks);
2051 cFYI(1, ("Send error in SetPathInfo (hard link) = %d", rc));
2054 cifs_buf_release(pSMB);
2056 goto createHardLinkRetry;
2062 CIFSCreateHardLink(const int xid, struct cifsTconInfo *tcon,
2063 const char *fromName, const char *toName,
2064 const struct nls_table *nls_codepage, int remap)
2067 NT_RENAME_REQ *pSMB = NULL;
2068 RENAME_RSP *pSMBr = NULL;
2070 int name_len, name_len2;
2073 cFYI(1, ("In CIFSCreateHardLink"));
2074 winCreateHardLinkRetry:
2076 rc = smb_init(SMB_COM_NT_RENAME, 4, tcon, (void **) &pSMB,
2081 pSMB->SearchAttributes =
2082 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
2084 pSMB->Flags = cpu_to_le16(CREATE_HARD_LINK);
2085 pSMB->ClusterCount = 0;
2087 pSMB->BufferFormat = 0x04;
2089 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2091 cifsConvertToUCS((__le16 *) pSMB->OldFileName, fromName,
2092 PATH_MAX, nls_codepage, remap);
2093 name_len++; /* trailing null */
2095 pSMB->OldFileName[name_len] = 0; /* pad */
2096 pSMB->OldFileName[name_len + 1] = 0x04;
2098 cifsConvertToUCS((__le16 *)&pSMB->OldFileName[name_len + 2],
2099 toName, PATH_MAX, nls_codepage, remap);
2100 name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
2101 name_len2 *= 2; /* convert to bytes */
2102 } else { /* BB improve the check for buffer overruns BB */
2103 name_len = strnlen(fromName, PATH_MAX);
2104 name_len++; /* trailing null */
2105 strncpy(pSMB->OldFileName, fromName, name_len);
2106 name_len2 = strnlen(toName, PATH_MAX);
2107 name_len2++; /* trailing null */
2108 pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */
2109 strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2);
2110 name_len2++; /* trailing null */
2111 name_len2++; /* signature byte */
2114 count = 1 /* string type byte */ + name_len + name_len2;
2115 pSMB->hdr.smb_buf_length += count;
2116 pSMB->ByteCount = cpu_to_le16(count);
2118 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2119 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2120 cifs_stats_inc(&tcon->num_hardlinks);
2122 cFYI(1, ("Send error in hard link (NT rename) = %d", rc));
2124 cifs_buf_release(pSMB);
2126 goto winCreateHardLinkRetry;
2132 CIFSSMBUnixQuerySymLink(const int xid, struct cifsTconInfo *tcon,
2133 const unsigned char *searchName,
2134 char *symlinkinfo, const int buflen,
2135 const struct nls_table *nls_codepage)
2137 /* SMB_QUERY_FILE_UNIX_LINK */
2138 TRANSACTION2_QPI_REQ *pSMB = NULL;
2139 TRANSACTION2_QPI_RSP *pSMBr = NULL;
2143 __u16 params, byte_count;
2145 cFYI(1, ("In QPathSymLinkInfo (Unix) for path %s", searchName));
2148 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2153 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2155 cifs_strtoUCS((__le16 *) pSMB->FileName, searchName, PATH_MAX
2156 /* find define for this maxpathcomponent */
2158 name_len++; /* trailing null */
2160 } else { /* BB improve the check for buffer overruns BB */
2161 name_len = strnlen(searchName, PATH_MAX);
2162 name_len++; /* trailing null */
2163 strncpy(pSMB->FileName, searchName, name_len);
2166 params = 2 /* level */ + 4 /* rsrvd */ + name_len /* incl null */ ;
2167 pSMB->TotalDataCount = 0;
2168 pSMB->MaxParameterCount = cpu_to_le16(2);
2169 /* BB find exact max data count below from sess structure BB */
2170 pSMB->MaxDataCount = cpu_to_le16(4000);
2171 pSMB->MaxSetupCount = 0;
2175 pSMB->Reserved2 = 0;
2176 pSMB->ParameterOffset = cpu_to_le16(offsetof(
2177 struct smb_com_transaction2_qpi_req ,InformationLevel) - 4);
2178 pSMB->DataCount = 0;
2179 pSMB->DataOffset = 0;
2180 pSMB->SetupCount = 1;
2181 pSMB->Reserved3 = 0;
2182 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
2183 byte_count = params + 1 /* pad */ ;
2184 pSMB->TotalParameterCount = cpu_to_le16(params);
2185 pSMB->ParameterCount = pSMB->TotalParameterCount;
2186 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_LINK);
2187 pSMB->Reserved4 = 0;
2188 pSMB->hdr.smb_buf_length += byte_count;
2189 pSMB->ByteCount = cpu_to_le16(byte_count);
2191 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2192 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2194 cFYI(1, ("Send error in QuerySymLinkInfo = %d", rc));
2196 /* decode response */
2198 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
2199 if (rc || (pSMBr->ByteCount < 2))
2200 /* BB also check enough total bytes returned */
2201 rc = -EIO; /* bad smb */
2203 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
2204 __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
2206 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
2207 name_len = UniStrnlen((wchar_t *) ((char *)
2208 &pSMBr->hdr.Protocol +data_offset),
2209 min_t(const int, buflen,count) / 2);
2210 /* BB FIXME investigate remapping reserved chars here */
2211 cifs_strfromUCS_le(symlinkinfo,
2212 (__le16 *) ((char *)&pSMBr->hdr.Protocol +
2214 name_len, nls_codepage);
2216 strncpy(symlinkinfo,
2217 (char *) &pSMBr->hdr.Protocol +
2219 min_t(const int, buflen, count));
2221 symlinkinfo[buflen] = 0;
2222 /* just in case so calling code does not go off the end of buffer */
2225 cifs_buf_release(pSMB);
2227 goto querySymLinkRetry;
2231 /* Initialize NT TRANSACT SMB into small smb request buffer.
2232 This assumes that all NT TRANSACTS that we init here have
2233 total parm and data under about 400 bytes (to fit in small cifs
2234 buffer size), which is the case so far, it easily fits. NB:
2235 Setup words themselves and ByteCount
2236 MaxSetupCount (size of returned setup area) and
2237 MaxParameterCount (returned parms size) must be set by caller */
2239 smb_init_ntransact(const __u16 sub_command, const int setup_count,
2240 const int parm_len, struct cifsTconInfo *tcon,
2245 struct smb_com_ntransact_req * pSMB;
2247 rc = small_smb_init(SMB_COM_NT_TRANSACT, 19 + setup_count, tcon,
2251 *ret_buf = (void *)pSMB;
2253 pSMB->TotalParameterCount = cpu_to_le32(parm_len);
2254 pSMB->TotalDataCount = 0;
2255 pSMB->MaxDataCount = cpu_to_le32((tcon->ses->server->maxBuf -
2256 MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
2257 pSMB->ParameterCount = pSMB->TotalParameterCount;
2258 pSMB->DataCount = pSMB->TotalDataCount;
2259 temp_offset = offsetof(struct smb_com_ntransact_req, Parms) +
2260 (setup_count * 2) - 4 /* for rfc1001 length itself */;
2261 pSMB->ParameterOffset = cpu_to_le32(temp_offset);
2262 pSMB->DataOffset = cpu_to_le32(temp_offset + parm_len);
2263 pSMB->SetupCount = setup_count; /* no need to le convert byte fields */
2264 pSMB->SubCommand = cpu_to_le16(sub_command);
2269 validate_ntransact(char * buf, char ** ppparm, char ** ppdata,
2270 int * pdatalen, int * pparmlen)
2273 __u32 data_count, data_offset, parm_count, parm_offset;
2274 struct smb_com_ntransact_rsp * pSMBr;
2279 pSMBr = (struct smb_com_ntransact_rsp *)buf;
2281 /* ByteCount was converted from little endian in SendReceive */
2282 end_of_smb = 2 /* sizeof byte count */ + pSMBr->ByteCount +
2283 (char *)&pSMBr->ByteCount;
2286 data_offset = le32_to_cpu(pSMBr->DataOffset);
2287 data_count = le32_to_cpu(pSMBr->DataCount);
2288 parm_offset = le32_to_cpu(pSMBr->ParameterOffset);
2289 parm_count = le32_to_cpu(pSMBr->ParameterCount);
2291 *ppparm = (char *)&pSMBr->hdr.Protocol + parm_offset;
2292 *ppdata = (char *)&pSMBr->hdr.Protocol + data_offset;
2294 /* should we also check that parm and data areas do not overlap? */
2295 if(*ppparm > end_of_smb) {
2296 cFYI(1,("parms start after end of smb"));
2298 } else if(parm_count + *ppparm > end_of_smb) {
2299 cFYI(1,("parm end after end of smb"));
2301 } else if(*ppdata > end_of_smb) {
2302 cFYI(1,("data starts after end of smb"));
2304 } else if(data_count + *ppdata > end_of_smb) {
2305 cFYI(1,("data %p + count %d (%p) ends after end of smb %p start %p",
2306 *ppdata, data_count, (data_count + *ppdata), end_of_smb, pSMBr)); /* BB FIXME */
2308 } else if(parm_count + data_count > pSMBr->ByteCount) {
2309 cFYI(1,("parm count and data count larger than SMB"));
2316 CIFSSMBQueryReparseLinkInfo(const int xid, struct cifsTconInfo *tcon,
2317 const unsigned char *searchName,
2318 char *symlinkinfo, const int buflen,__u16 fid,
2319 const struct nls_table *nls_codepage)
2324 struct smb_com_transaction_ioctl_req * pSMB;
2325 struct smb_com_transaction_ioctl_rsp * pSMBr;
2327 cFYI(1, ("In Windows reparse style QueryLink for path %s", searchName));
2328 rc = smb_init(SMB_COM_NT_TRANSACT, 23, tcon, (void **) &pSMB,
2333 pSMB->TotalParameterCount = 0 ;
2334 pSMB->TotalDataCount = 0;
2335 pSMB->MaxParameterCount = cpu_to_le32(2);
2336 /* BB find exact data count max from sess structure BB */
2337 pSMB->MaxDataCount = cpu_to_le32((tcon->ses->server->maxBuf -
2338 MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
2339 pSMB->MaxSetupCount = 4;
2341 pSMB->ParameterOffset = 0;
2342 pSMB->DataCount = 0;
2343 pSMB->DataOffset = 0;
2344 pSMB->SetupCount = 4;
2345 pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_IOCTL);
2346 pSMB->ParameterCount = pSMB->TotalParameterCount;
2347 pSMB->FunctionCode = cpu_to_le32(FSCTL_GET_REPARSE_POINT);
2348 pSMB->IsFsctl = 1; /* FSCTL */
2349 pSMB->IsRootFlag = 0;
2350 pSMB->Fid = fid; /* file handle always le */
2351 pSMB->ByteCount = 0;
2353 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2354 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2356 cFYI(1, ("Send error in QueryReparseLinkInfo = %d", rc));
2357 } else { /* decode response */
2358 __u32 data_offset = le32_to_cpu(pSMBr->DataOffset);
2359 __u32 data_count = le32_to_cpu(pSMBr->DataCount);
2360 if ((pSMBr->ByteCount < 2) || (data_offset > 512))
2361 /* BB also check enough total bytes returned */
2362 rc = -EIO; /* bad smb */
2364 if(data_count && (data_count < 2048)) {
2365 char * end_of_smb = 2 /* sizeof byte count */ +
2367 (char *)&pSMBr->ByteCount;
2369 struct reparse_data * reparse_buf = (struct reparse_data *)
2370 ((char *)&pSMBr->hdr.Protocol + data_offset);
2371 if((char*)reparse_buf >= end_of_smb) {
2375 if((reparse_buf->LinkNamesBuf +
2376 reparse_buf->TargetNameOffset +
2377 reparse_buf->TargetNameLen) >
2379 cFYI(1,("reparse buf extended beyond SMB"));
2384 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
2385 name_len = UniStrnlen((wchar_t *)
2386 (reparse_buf->LinkNamesBuf +
2387 reparse_buf->TargetNameOffset),
2388 min(buflen/2, reparse_buf->TargetNameLen / 2));
2389 cifs_strfromUCS_le(symlinkinfo,
2390 (__le16 *) (reparse_buf->LinkNamesBuf +
2391 reparse_buf->TargetNameOffset),
2392 name_len, nls_codepage);
2393 } else { /* ASCII names */
2394 strncpy(symlinkinfo,reparse_buf->LinkNamesBuf +
2395 reparse_buf->TargetNameOffset,
2396 min_t(const int, buflen, reparse_buf->TargetNameLen));
2400 cFYI(1,("Invalid return data count on get reparse info ioctl"));
2402 symlinkinfo[buflen] = 0; /* just in case so the caller
2403 does not go off the end of the buffer */
2404 cFYI(1,("readlink result - %s",symlinkinfo));
2408 cifs_buf_release(pSMB);
2410 /* Note: On -EAGAIN error only caller can retry on handle based calls
2411 since file handle passed in no longer valid */
2416 #ifdef CONFIG_CIFS_POSIX
2418 /*Convert an Access Control Entry from wire format to local POSIX xattr format*/
2419 static void cifs_convert_ace(posix_acl_xattr_entry * ace, struct cifs_posix_ace * cifs_ace)
2421 /* u8 cifs fields do not need le conversion */
2422 ace->e_perm = cpu_to_le16(cifs_ace->cifs_e_perm);
2423 ace->e_tag = cpu_to_le16(cifs_ace->cifs_e_tag);
2424 ace->e_id = cpu_to_le32(le64_to_cpu(cifs_ace->cifs_uid));
2425 /* cFYI(1,("perm %d tag %d id %d",ace->e_perm,ace->e_tag,ace->e_id)); */
2430 /* Convert ACL from CIFS POSIX wire format to local Linux POSIX ACL xattr */
2431 static int cifs_copy_posix_acl(char * trgt,char * src, const int buflen,
2432 const int acl_type,const int size_of_data_area)
2437 struct cifs_posix_ace * pACE;
2438 struct cifs_posix_acl * cifs_acl = (struct cifs_posix_acl *)src;
2439 posix_acl_xattr_header * local_acl = (posix_acl_xattr_header *)trgt;
2441 if (le16_to_cpu(cifs_acl->version) != CIFS_ACL_VERSION)
2444 if(acl_type & ACL_TYPE_ACCESS) {
2445 count = le16_to_cpu(cifs_acl->access_entry_count);
2446 pACE = &cifs_acl->ace_array[0];
2447 size = sizeof(struct cifs_posix_acl);
2448 size += sizeof(struct cifs_posix_ace) * count;
2449 /* check if we would go beyond end of SMB */
2450 if(size_of_data_area < size) {
2451 cFYI(1,("bad CIFS POSIX ACL size %d vs. %d",size_of_data_area,size));
2454 } else if(acl_type & ACL_TYPE_DEFAULT) {
2455 count = le16_to_cpu(cifs_acl->access_entry_count);
2456 size = sizeof(struct cifs_posix_acl);
2457 size += sizeof(struct cifs_posix_ace) * count;
2458 /* skip past access ACEs to get to default ACEs */
2459 pACE = &cifs_acl->ace_array[count];
2460 count = le16_to_cpu(cifs_acl->default_entry_count);
2461 size += sizeof(struct cifs_posix_ace) * count;
2462 /* check if we would go beyond end of SMB */
2463 if(size_of_data_area < size)
2470 size = posix_acl_xattr_size(count);
2471 if((buflen == 0) || (local_acl == NULL)) {
2472 /* used to query ACL EA size */
2473 } else if(size > buflen) {
2475 } else /* buffer big enough */ {
2476 local_acl->a_version = cpu_to_le32(POSIX_ACL_XATTR_VERSION);
2477 for(i = 0;i < count ;i++) {
2478 cifs_convert_ace(&local_acl->a_entries[i],pACE);
2485 static __u16 convert_ace_to_cifs_ace(struct cifs_posix_ace * cifs_ace,
2486 const posix_acl_xattr_entry * local_ace)
2488 __u16 rc = 0; /* 0 = ACL converted ok */
2490 cifs_ace->cifs_e_perm = le16_to_cpu(local_ace->e_perm);
2491 cifs_ace->cifs_e_tag = le16_to_cpu(local_ace->e_tag);
2492 /* BB is there a better way to handle the large uid? */
2493 if(local_ace->e_id == cpu_to_le32(-1)) {
2494 /* Probably no need to le convert -1 on any arch but can not hurt */
2495 cifs_ace->cifs_uid = cpu_to_le64(-1);
2497 cifs_ace->cifs_uid = cpu_to_le64(le32_to_cpu(local_ace->e_id));
2498 /*cFYI(1,("perm %d tag %d id %d",ace->e_perm,ace->e_tag,ace->e_id));*/
2502 /* Convert ACL from local Linux POSIX xattr to CIFS POSIX ACL wire format */
2503 static __u16 ACL_to_cifs_posix(char * parm_data,const char * pACL,const int buflen,
2507 struct cifs_posix_acl * cifs_acl = (struct cifs_posix_acl *)parm_data;
2508 posix_acl_xattr_header * local_acl = (posix_acl_xattr_header *)pACL;
2512 if((buflen == 0) || (pACL == NULL) || (cifs_acl == NULL))
2515 count = posix_acl_xattr_count((size_t)buflen);
2516 cFYI(1,("setting acl with %d entries from buf of length %d and version of %d",
2517 count, buflen, le32_to_cpu(local_acl->a_version)));
2518 if(le32_to_cpu(local_acl->a_version) != 2) {
2519 cFYI(1,("unknown POSIX ACL version %d",
2520 le32_to_cpu(local_acl->a_version)));
2523 cifs_acl->version = cpu_to_le16(1);
2524 if(acl_type == ACL_TYPE_ACCESS)
2525 cifs_acl->access_entry_count = cpu_to_le16(count);
2526 else if(acl_type == ACL_TYPE_DEFAULT)
2527 cifs_acl->default_entry_count = cpu_to_le16(count);
2529 cFYI(1,("unknown ACL type %d",acl_type));
2532 for(i=0;i<count;i++) {
2533 rc = convert_ace_to_cifs_ace(&cifs_acl->ace_array[i],
2534 &local_acl->a_entries[i]);
2536 /* ACE not converted */
2541 rc = (__u16)(count * sizeof(struct cifs_posix_ace));
2542 rc += sizeof(struct cifs_posix_acl);
2543 /* BB add check to make sure ACL does not overflow SMB */
2549 CIFSSMBGetPosixACL(const int xid, struct cifsTconInfo *tcon,
2550 const unsigned char *searchName,
2551 char *acl_inf, const int buflen, const int acl_type,
2552 const struct nls_table *nls_codepage, int remap)
2554 /* SMB_QUERY_POSIX_ACL */
2555 TRANSACTION2_QPI_REQ *pSMB = NULL;
2556 TRANSACTION2_QPI_RSP *pSMBr = NULL;
2560 __u16 params, byte_count;
2562 cFYI(1, ("In GetPosixACL (Unix) for path %s", searchName));
2565 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2570 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2572 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
2573 PATH_MAX, nls_codepage, remap);
2574 name_len++; /* trailing null */
2576 pSMB->FileName[name_len] = 0;
2577 pSMB->FileName[name_len+1] = 0;
2578 } else { /* BB improve the check for buffer overruns BB */
2579 name_len = strnlen(searchName, PATH_MAX);
2580 name_len++; /* trailing null */
2581 strncpy(pSMB->FileName, searchName, name_len);
2584 params = 2 /* level */ + 4 /* rsrvd */ + name_len /* incl null */ ;
2585 pSMB->TotalDataCount = 0;
2586 pSMB->MaxParameterCount = cpu_to_le16(2);
2587 /* BB find exact max data count below from sess structure BB */
2588 pSMB->MaxDataCount = cpu_to_le16(4000);
2589 pSMB->MaxSetupCount = 0;
2593 pSMB->Reserved2 = 0;
2594 pSMB->ParameterOffset = cpu_to_le16(
2595 offsetof(struct smb_com_transaction2_qpi_req ,InformationLevel) - 4);
2596 pSMB->DataCount = 0;
2597 pSMB->DataOffset = 0;
2598 pSMB->SetupCount = 1;
2599 pSMB->Reserved3 = 0;
2600 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
2601 byte_count = params + 1 /* pad */ ;
2602 pSMB->TotalParameterCount = cpu_to_le16(params);
2603 pSMB->ParameterCount = pSMB->TotalParameterCount;
2604 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_POSIX_ACL);
2605 pSMB->Reserved4 = 0;
2606 pSMB->hdr.smb_buf_length += byte_count;
2607 pSMB->ByteCount = cpu_to_le16(byte_count);
2609 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2610 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2611 cifs_stats_inc(&tcon->num_acl_get);
2613 cFYI(1, ("Send error in Query POSIX ACL = %d", rc));
2615 /* decode response */
2617 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
2618 if (rc || (pSMBr->ByteCount < 2))
2619 /* BB also check enough total bytes returned */
2620 rc = -EIO; /* bad smb */
2622 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
2623 __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
2624 rc = cifs_copy_posix_acl(acl_inf,
2625 (char *)&pSMBr->hdr.Protocol+data_offset,
2626 buflen,acl_type,count);
2629 cifs_buf_release(pSMB);
2636 CIFSSMBSetPosixACL(const int xid, struct cifsTconInfo *tcon,
2637 const unsigned char *fileName,
2638 const char *local_acl, const int buflen,
2640 const struct nls_table *nls_codepage, int remap)
2642 struct smb_com_transaction2_spi_req *pSMB = NULL;
2643 struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
2647 int bytes_returned = 0;
2648 __u16 params, byte_count, data_count, param_offset, offset;
2650 cFYI(1, ("In SetPosixACL (Unix) for path %s", fileName));
2652 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2656 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2658 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
2659 PATH_MAX, nls_codepage, remap);
2660 name_len++; /* trailing null */
2662 } else { /* BB improve the check for buffer overruns BB */
2663 name_len = strnlen(fileName, PATH_MAX);
2664 name_len++; /* trailing null */
2665 strncpy(pSMB->FileName, fileName, name_len);
2667 params = 6 + name_len;
2668 pSMB->MaxParameterCount = cpu_to_le16(2);
2669 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB size from sess */
2670 pSMB->MaxSetupCount = 0;
2674 pSMB->Reserved2 = 0;
2675 param_offset = offsetof(struct smb_com_transaction2_spi_req,
2676 InformationLevel) - 4;
2677 offset = param_offset + params;
2678 parm_data = ((char *) &pSMB->hdr.Protocol) + offset;
2679 pSMB->ParameterOffset = cpu_to_le16(param_offset);
2681 /* convert to on the wire format for POSIX ACL */
2682 data_count = ACL_to_cifs_posix(parm_data,local_acl,buflen,acl_type);
2684 if(data_count == 0) {
2686 goto setACLerrorExit;
2688 pSMB->DataOffset = cpu_to_le16(offset);
2689 pSMB->SetupCount = 1;
2690 pSMB->Reserved3 = 0;
2691 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
2692 pSMB->InformationLevel = cpu_to_le16(SMB_SET_POSIX_ACL);
2693 byte_count = 3 /* pad */ + params + data_count;
2694 pSMB->DataCount = cpu_to_le16(data_count);
2695 pSMB->TotalDataCount = pSMB->DataCount;
2696 pSMB->ParameterCount = cpu_to_le16(params);
2697 pSMB->TotalParameterCount = pSMB->ParameterCount;
2698 pSMB->Reserved4 = 0;
2699 pSMB->hdr.smb_buf_length += byte_count;
2700 pSMB->ByteCount = cpu_to_le16(byte_count);
2701 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2702 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2704 cFYI(1, ("Set POSIX ACL returned %d", rc));
2708 cifs_buf_release(pSMB);
2714 /* BB fix tabs in this function FIXME BB */
2716 CIFSGetExtAttr(const int xid, struct cifsTconInfo *tcon,
2717 const int netfid, __u64 * pExtAttrBits, __u64 *pMask)
2720 struct smb_t2_qfi_req *pSMB = NULL;
2721 struct smb_t2_qfi_rsp *pSMBr = NULL;
2723 __u16 params, byte_count;
2725 cFYI(1,("In GetExtAttr"));
2730 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2735 params = 2 /* level */ +2 /* fid */;
2736 pSMB->t2.TotalDataCount = 0;
2737 pSMB->t2.MaxParameterCount = cpu_to_le16(4);
2738 /* BB find exact max data count below from sess structure BB */
2739 pSMB->t2.MaxDataCount = cpu_to_le16(4000);
2740 pSMB->t2.MaxSetupCount = 0;
2741 pSMB->t2.Reserved = 0;
2743 pSMB->t2.Timeout = 0;
2744 pSMB->t2.Reserved2 = 0;
2745 pSMB->t2.ParameterOffset = cpu_to_le16(offsetof(struct smb_t2_qfi_req,
2747 pSMB->t2.DataCount = 0;
2748 pSMB->t2.DataOffset = 0;
2749 pSMB->t2.SetupCount = 1;
2750 pSMB->t2.Reserved3 = 0;
2751 pSMB->t2.SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION);
2752 byte_count = params + 1 /* pad */ ;
2753 pSMB->t2.TotalParameterCount = cpu_to_le16(params);
2754 pSMB->t2.ParameterCount = pSMB->t2.TotalParameterCount;
2755 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_ATTR_FLAGS);
2758 pSMB->hdr.smb_buf_length += byte_count;
2759 pSMB->t2.ByteCount = cpu_to_le16(byte_count);
2761 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2762 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2764 cFYI(1, ("error %d in GetExtAttr", rc));
2766 /* decode response */
2767 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
2768 if (rc || (pSMBr->ByteCount < 2))
2769 /* BB also check enough total bytes returned */
2770 /* If rc should we check for EOPNOSUPP and
2771 disable the srvino flag? or in caller? */
2772 rc = -EIO; /* bad smb */
2774 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
2775 __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
2776 struct file_chattr_info * pfinfo;
2777 /* BB Do we need a cast or hash here ? */
2779 cFYI(1, ("Illegal size ret in GetExtAttr"));
2783 pfinfo = (struct file_chattr_info *)
2784 (data_offset + (char *) &pSMBr->hdr.Protocol);
2785 *pExtAttrBits = le64_to_cpu(pfinfo->mode);
2786 *pMask = le64_to_cpu(pfinfo->mask);
2790 cifs_buf_release(pSMB);
2792 goto GetExtAttrRetry;
2797 #endif /* CONFIG_POSIX */
2800 /* security id for everyone */
2801 const static struct cifs_sid sid_everyone =
2802 {1, 1, {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0}};
2804 const static struct cifs_sid sid_user =
2805 {1, 2 , {0, 0, 0, 0, 0, 5}, {32, 545, 0, 0}};
2807 /* Convert CIFS ACL to POSIX form */
2808 static int parse_sec_desc(struct cifs_sid * psec_desc, int acl_len)
2813 /* Get Security Descriptor (by handle) from remote server for a file or dir */
2815 CIFSSMBGetCIFSACL(const int xid, struct cifsTconInfo *tcon, __u16 fid,
2816 /* BB fix up return info */ char *acl_inf, const int buflen,
2817 const int acl_type /* ACCESS/DEFAULT not sure implication */)
2821 QUERY_SEC_DESC_REQ * pSMB;
2824 cFYI(1, ("GetCifsACL"));
2826 rc = smb_init_ntransact(NT_TRANSACT_QUERY_SECURITY_DESC, 0,
2827 8 /* parm len */, tcon, (void **) &pSMB);
2831 pSMB->MaxParameterCount = cpu_to_le32(4);
2832 /* BB TEST with big acls that might need to be e.g. larger than 16K */
2833 pSMB->MaxSetupCount = 0;
2834 pSMB->Fid = fid; /* file handle always le */
2835 pSMB->AclFlags = cpu_to_le32(CIFS_ACL_OWNER | CIFS_ACL_GROUP |
2837 pSMB->ByteCount = cpu_to_le16(11); /* 3 bytes pad + 8 bytes parm */
2838 pSMB->hdr.smb_buf_length += 11;
2839 iov[0].iov_base = (char *)pSMB;
2840 iov[0].iov_len = pSMB->hdr.smb_buf_length + 4;
2842 rc = SendReceive2(xid, tcon->ses, iov, 1 /* num iovec */, &buf_type, 0);
2843 cifs_stats_inc(&tcon->num_acl_get);
2845 cFYI(1, ("Send error in QuerySecDesc = %d", rc));
2846 } else { /* decode response */
2847 struct cifs_sid * psec_desc;
2852 struct smb_com_ntransact_rsp * pSMBr;
2854 /* validate_nttransact */
2855 rc = validate_ntransact(iov[0].iov_base, (char **)&parm,
2856 (char **)&psec_desc,
2857 &parm_len, &data_len);
2861 pSMBr = (struct smb_com_ntransact_rsp *)iov[0].iov_base;
2863 cERROR(1,("smb %p parm %p data %p",pSMBr,parm,psec_desc)); /* BB removeme BB */
2865 if (le32_to_cpu(pSMBr->ParameterCount) != 4) {
2866 rc = -EIO; /* bad smb */
2870 /* BB check that data area is minimum length and as big as acl_len */
2872 acl_len = le32_to_cpu(*(__le32 *)parm);
2873 /* BB check if(acl_len > bufsize) */
2875 parse_sec_desc(psec_desc, acl_len);
2878 if(buf_type == CIFS_SMALL_BUFFER)
2879 cifs_small_buf_release(iov[0].iov_base);
2880 else if(buf_type == CIFS_LARGE_BUFFER)
2881 cifs_buf_release(iov[0].iov_base);
2882 /* cifs_small_buf_release(pSMB); */ /* Freed earlier now in SendReceive2 */
2886 /* Legacy Query Path Information call for lookup to old servers such
2888 int SMBQueryInformation(const int xid, struct cifsTconInfo *tcon,
2889 const unsigned char *searchName,
2890 FILE_ALL_INFO * pFinfo,
2891 const struct nls_table *nls_codepage, int remap)
2893 QUERY_INFORMATION_REQ * pSMB;
2894 QUERY_INFORMATION_RSP * pSMBr;
2899 cFYI(1, ("In SMBQPath path %s", searchName));
2901 rc = smb_init(SMB_COM_QUERY_INFORMATION, 0, tcon, (void **) &pSMB,
2906 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2908 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
2909 PATH_MAX, nls_codepage, remap);
2910 name_len++; /* trailing null */
2913 name_len = strnlen(searchName, PATH_MAX);
2914 name_len++; /* trailing null */
2915 strncpy(pSMB->FileName, searchName, name_len);
2917 pSMB->BufferFormat = 0x04;
2918 name_len++; /* account for buffer type byte */
2919 pSMB->hdr.smb_buf_length += (__u16) name_len;
2920 pSMB->ByteCount = cpu_to_le16(name_len);
2922 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2923 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2925 cFYI(1, ("Send error in QueryInfo = %d", rc));
2926 } else if (pFinfo) { /* decode response */
2928 __u32 time = le32_to_cpu(pSMBr->last_write_time);
2929 /* BB FIXME - add time zone adjustment BB */
2930 memset(pFinfo, 0, sizeof(FILE_ALL_INFO));
2933 /* decode time fields */
2934 pFinfo->ChangeTime = cifs_UnixTimeToNT(ts);
2935 pFinfo->LastWriteTime = pFinfo->ChangeTime;
2936 pFinfo->LastAccessTime = 0;
2937 pFinfo->AllocationSize =
2938 cpu_to_le64(le32_to_cpu(pSMBr->size));
2939 pFinfo->EndOfFile = pFinfo->AllocationSize;
2940 pFinfo->Attributes =
2941 cpu_to_le32(le16_to_cpu(pSMBr->attr));
2943 rc = -EIO; /* bad buffer passed in */
2945 cifs_buf_release(pSMB);
2957 CIFSSMBQPathInfo(const int xid, struct cifsTconInfo *tcon,
2958 const unsigned char *searchName,
2959 FILE_ALL_INFO * pFindData,
2960 const struct nls_table *nls_codepage, int remap)
2962 /* level 263 SMB_QUERY_FILE_ALL_INFO */
2963 TRANSACTION2_QPI_REQ *pSMB = NULL;
2964 TRANSACTION2_QPI_RSP *pSMBr = NULL;
2968 __u16 params, byte_count;
2970 /* cFYI(1, ("In QPathInfo path %s", searchName)); */
2972 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2977 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2979 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
2980 PATH_MAX, nls_codepage, remap);
2981 name_len++; /* trailing null */
2983 } else { /* BB improve the check for buffer overruns BB */
2984 name_len = strnlen(searchName, PATH_MAX);
2985 name_len++; /* trailing null */
2986 strncpy(pSMB->FileName, searchName, name_len);
2989 params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */ ;
2990 pSMB->TotalDataCount = 0;
2991 pSMB->MaxParameterCount = cpu_to_le16(2);
2992 pSMB->MaxDataCount = cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
2993 pSMB->MaxSetupCount = 0;
2997 pSMB->Reserved2 = 0;
2998 pSMB->ParameterOffset = cpu_to_le16(offsetof(
2999 struct smb_com_transaction2_qpi_req ,InformationLevel) - 4);
3000 pSMB->DataCount = 0;
3001 pSMB->DataOffset = 0;
3002 pSMB->SetupCount = 1;
3003 pSMB->Reserved3 = 0;
3004 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
3005 byte_count = params + 1 /* pad */ ;
3006 pSMB->TotalParameterCount = cpu_to_le16(params);
3007 pSMB->ParameterCount = pSMB->TotalParameterCount;
3008 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_ALL_INFO);
3009 pSMB->Reserved4 = 0;
3010 pSMB->hdr.smb_buf_length += byte_count;
3011 pSMB->ByteCount = cpu_to_le16(byte_count);
3013 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3014 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3016 cFYI(1, ("Send error in QPathInfo = %d", rc));
3017 } else { /* decode response */
3018 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3020 if (rc || (pSMBr->ByteCount < 40))
3021 rc = -EIO; /* bad smb */
3022 else if (pFindData){
3023 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3024 memcpy((char *) pFindData,
3025 (char *) &pSMBr->hdr.Protocol +
3026 data_offset, sizeof (FILE_ALL_INFO));
3030 cifs_buf_release(pSMB);
3032 goto QPathInfoRetry;
3038 CIFSSMBUnixQPathInfo(const int xid, struct cifsTconInfo *tcon,
3039 const unsigned char *searchName,
3040 FILE_UNIX_BASIC_INFO * pFindData,
3041 const struct nls_table *nls_codepage, int remap)
3043 /* SMB_QUERY_FILE_UNIX_BASIC */
3044 TRANSACTION2_QPI_REQ *pSMB = NULL;
3045 TRANSACTION2_QPI_RSP *pSMBr = NULL;
3047 int bytes_returned = 0;
3049 __u16 params, byte_count;
3051 cFYI(1, ("In QPathInfo (Unix) the path %s", searchName));
3053 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3058 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3060 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
3061 PATH_MAX, nls_codepage, remap);
3062 name_len++; /* trailing null */
3064 } else { /* BB improve the check for buffer overruns BB */
3065 name_len = strnlen(searchName, PATH_MAX);
3066 name_len++; /* trailing null */
3067 strncpy(pSMB->FileName, searchName, name_len);
3070 params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */ ;
3071 pSMB->TotalDataCount = 0;
3072 pSMB->MaxParameterCount = cpu_to_le16(2);
3073 /* BB find exact max SMB PDU from sess structure BB */
3074 pSMB->MaxDataCount = cpu_to_le16(4000);
3075 pSMB->MaxSetupCount = 0;
3079 pSMB->Reserved2 = 0;
3080 pSMB->ParameterOffset = cpu_to_le16(offsetof(
3081 struct smb_com_transaction2_qpi_req ,InformationLevel) - 4);
3082 pSMB->DataCount = 0;
3083 pSMB->DataOffset = 0;
3084 pSMB->SetupCount = 1;
3085 pSMB->Reserved3 = 0;
3086 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
3087 byte_count = params + 1 /* pad */ ;
3088 pSMB->TotalParameterCount = cpu_to_le16(params);
3089 pSMB->ParameterCount = pSMB->TotalParameterCount;
3090 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC);
3091 pSMB->Reserved4 = 0;
3092 pSMB->hdr.smb_buf_length += byte_count;
3093 pSMB->ByteCount = cpu_to_le16(byte_count);
3095 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3096 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3098 cFYI(1, ("Send error in QPathInfo = %d", rc));
3099 } else { /* decode response */
3100 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3102 if (rc || (pSMBr->ByteCount < sizeof(FILE_UNIX_BASIC_INFO))) {
3103 rc = -EIO; /* bad smb */
3105 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3106 memcpy((char *) pFindData,
3107 (char *) &pSMBr->hdr.Protocol +
3109 sizeof (FILE_UNIX_BASIC_INFO));
3112 cifs_buf_release(pSMB);
3114 goto UnixQPathInfoRetry;
3119 #if 0 /* function unused at present */
3120 int CIFSFindSingle(const int xid, struct cifsTconInfo *tcon,
3121 const char *searchName, FILE_ALL_INFO * findData,
3122 const struct nls_table *nls_codepage)
3124 /* level 257 SMB_ */
3125 TRANSACTION2_FFIRST_REQ *pSMB = NULL;
3126 TRANSACTION2_FFIRST_RSP *pSMBr = NULL;
3130 __u16 params, byte_count;
3132 cFYI(1, ("In FindUnique"));
3134 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3139 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3141 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName, PATH_MAX
3142 /* find define for this maxpathcomponent */
3144 name_len++; /* trailing null */
3146 } else { /* BB improve the check for buffer overruns BB */
3147 name_len = strnlen(searchName, PATH_MAX);
3148 name_len++; /* trailing null */
3149 strncpy(pSMB->FileName, searchName, name_len);
3152 params = 12 + name_len /* includes null */ ;
3153 pSMB->TotalDataCount = 0; /* no EAs */
3154 pSMB->MaxParameterCount = cpu_to_le16(2);
3155 pSMB->MaxDataCount = cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
3156 pSMB->MaxSetupCount = 0;
3160 pSMB->Reserved2 = 0;
3161 pSMB->ParameterOffset = cpu_to_le16(
3162 offsetof(struct smb_com_transaction2_ffirst_req,InformationLevel) - 4);
3163 pSMB->DataCount = 0;
3164 pSMB->DataOffset = 0;
3165 pSMB->SetupCount = 1; /* one byte, no need to le convert */
3166 pSMB->Reserved3 = 0;
3167 pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_FIRST);
3168 byte_count = params + 1 /* pad */ ;
3169 pSMB->TotalParameterCount = cpu_to_le16(params);
3170 pSMB->ParameterCount = pSMB->TotalParameterCount;
3171 pSMB->SearchAttributes =
3172 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
3174 pSMB->SearchCount = cpu_to_le16(16); /* BB increase */
3175 pSMB->SearchFlags = cpu_to_le16(1);
3176 pSMB->InformationLevel = cpu_to_le16(SMB_FIND_FILE_DIRECTORY_INFO);
3177 pSMB->SearchStorageType = 0; /* BB what should we set this to? BB */
3178 pSMB->hdr.smb_buf_length += byte_count;
3179 pSMB->ByteCount = cpu_to_le16(byte_count);
3181 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3182 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3185 cFYI(1, ("Send error in FindFileDirInfo = %d", rc));
3186 } else { /* decode response */
3187 cifs_stats_inc(&tcon->num_ffirst);
3191 cifs_buf_release(pSMB);
3193 goto findUniqueRetry;
3197 #endif /* end unused (temporarily) function */
3199 /* xid, tcon, searchName and codepage are input parms, rest are returned */
3201 CIFSFindFirst(const int xid, struct cifsTconInfo *tcon,
3202 const char *searchName,
3203 const struct nls_table *nls_codepage,
3205 struct cifs_search_info * psrch_inf, int remap, const char dirsep)
3207 /* level 257 SMB_ */
3208 TRANSACTION2_FFIRST_REQ *pSMB = NULL;
3209 TRANSACTION2_FFIRST_RSP *pSMBr = NULL;
3210 T2_FFIRST_RSP_PARMS * parms;
3212 int bytes_returned = 0;
3214 __u16 params, byte_count;
3216 cFYI(1, ("In FindFirst for %s",searchName));
3219 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3224 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3226 cifsConvertToUCS((__le16 *) pSMB->FileName,searchName,
3227 PATH_MAX, nls_codepage, remap);
3228 /* We can not add the asterik earlier in case
3229 it got remapped to 0xF03A as if it were part of the
3230 directory name instead of a wildcard */
3232 pSMB->FileName[name_len] = dirsep;
3233 pSMB->FileName[name_len+1] = 0;
3234 pSMB->FileName[name_len+2] = '*';
3235 pSMB->FileName[name_len+3] = 0;
3236 name_len += 4; /* now the trailing null */
3237 pSMB->FileName[name_len] = 0; /* null terminate just in case */
3238 pSMB->FileName[name_len+1] = 0;
3240 } else { /* BB add check for overrun of SMB buf BB */
3241 name_len = strnlen(searchName, PATH_MAX);
3242 /* BB fix here and in unicode clause above ie
3243 if(name_len > buffersize-header)
3244 free buffer exit; BB */
3245 strncpy(pSMB->FileName, searchName, name_len);
3246 pSMB->FileName[name_len] = dirsep;
3247 pSMB->FileName[name_len+1] = '*';
3248 pSMB->FileName[name_len+2] = 0;
3252 params = 12 + name_len /* includes null */ ;
3253 pSMB->TotalDataCount = 0; /* no EAs */
3254 pSMB->MaxParameterCount = cpu_to_le16(10);
3255 pSMB->MaxDataCount = cpu_to_le16((tcon->ses->server->maxBuf -
3256 MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
3257 pSMB->MaxSetupCount = 0;
3261 pSMB->Reserved2 = 0;
3262 byte_count = params + 1 /* pad */ ;
3263 pSMB->TotalParameterCount = cpu_to_le16(params);
3264 pSMB->ParameterCount = pSMB->TotalParameterCount;
3265 pSMB->ParameterOffset = cpu_to_le16(
3266 offsetof(struct smb_com_transaction2_ffirst_req, SearchAttributes)
3268 pSMB->DataCount = 0;
3269 pSMB->DataOffset = 0;
3270 pSMB->SetupCount = 1; /* one byte, no need to make endian neutral */
3271 pSMB->Reserved3 = 0;
3272 pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_FIRST);
3273 pSMB->SearchAttributes =
3274 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
3276 pSMB->SearchCount= cpu_to_le16(CIFSMaxBufSize/sizeof(FILE_UNIX_INFO));
3277 pSMB->SearchFlags = cpu_to_le16(CIFS_SEARCH_CLOSE_AT_END |
3278 CIFS_SEARCH_RETURN_RESUME);
3279 pSMB->InformationLevel = cpu_to_le16(psrch_inf->info_level);
3281 /* BB what should we set StorageType to? Does it matter? BB */
3282 pSMB->SearchStorageType = 0;
3283 pSMB->hdr.smb_buf_length += byte_count;
3284 pSMB->ByteCount = cpu_to_le16(byte_count);
3286 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3287 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3288 cifs_stats_inc(&tcon->num_ffirst);
3290 if (rc) {/* BB add logic to retry regular search if Unix search
3291 rejected unexpectedly by server */
3292 /* BB Add code to handle unsupported level rc */
3293 cFYI(1, ("Error in FindFirst = %d", rc));
3295 cifs_buf_release(pSMB);
3297 /* BB eventually could optimize out free and realloc of buf */
3300 goto findFirstRetry;
3301 } else { /* decode response */
3302 /* BB remember to free buffer if error BB */
3303 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3305 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
3306 psrch_inf->unicode = TRUE;
3308 psrch_inf->unicode = FALSE;
3310 psrch_inf->ntwrk_buf_start = (char *)pSMBr;
3311 psrch_inf->smallBuf = 0;
3312 psrch_inf->srch_entries_start =
3313 (char *) &pSMBr->hdr.Protocol +
3314 le16_to_cpu(pSMBr->t2.DataOffset);
3315 parms = (T2_FFIRST_RSP_PARMS *)((char *) &pSMBr->hdr.Protocol +
3316 le16_to_cpu(pSMBr->t2.ParameterOffset));
3318 if(parms->EndofSearch)
3319 psrch_inf->endOfSearch = TRUE;
3321 psrch_inf->endOfSearch = FALSE;
3323 psrch_inf->entries_in_buffer = le16_to_cpu(parms->SearchCount);
3324 psrch_inf->index_of_last_entry = 2 /* skip . and .. */ +
3325 psrch_inf->entries_in_buffer;
3326 *pnetfid = parms->SearchHandle;
3328 cifs_buf_release(pSMB);
3335 int CIFSFindNext(const int xid, struct cifsTconInfo *tcon,
3336 __u16 searchHandle, struct cifs_search_info * psrch_inf)
3338 TRANSACTION2_FNEXT_REQ *pSMB = NULL;
3339 TRANSACTION2_FNEXT_RSP *pSMBr = NULL;
3340 T2_FNEXT_RSP_PARMS * parms;
3341 char *response_data;
3343 int bytes_returned, name_len;
3344 __u16 params, byte_count;
3346 cFYI(1, ("In FindNext"));
3348 if(psrch_inf->endOfSearch == TRUE)
3351 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3356 params = 14; /* includes 2 bytes of null string, converted to LE below */
3358 pSMB->TotalDataCount = 0; /* no EAs */
3359 pSMB->MaxParameterCount = cpu_to_le16(8);
3360 pSMB->MaxDataCount =
3361 cpu_to_le16((tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
3362 pSMB->MaxSetupCount = 0;
3366 pSMB->Reserved2 = 0;
3367 pSMB->ParameterOffset = cpu_to_le16(
3368 offsetof(struct smb_com_transaction2_fnext_req,SearchHandle) - 4);
3369 pSMB->DataCount = 0;
3370 pSMB->DataOffset = 0;
3371 pSMB->SetupCount = 1;
3372 pSMB->Reserved3 = 0;
3373 pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_NEXT);
3374 pSMB->SearchHandle = searchHandle; /* always kept as le */
3376 cpu_to_le16(CIFSMaxBufSize / sizeof (FILE_UNIX_INFO));
3377 /* test for Unix extensions */
3378 /* if (tcon->ses->capabilities & CAP_UNIX) {
3379 pSMB->InformationLevel = cpu_to_le16(SMB_FIND_FILE_UNIX);
3380 psrch_inf->info_level = SMB_FIND_FILE_UNIX;
3382 pSMB->InformationLevel =
3383 cpu_to_le16(SMB_FIND_FILE_DIRECTORY_INFO);
3384 psrch_inf->info_level = SMB_FIND_FILE_DIRECTORY_INFO;
3386 pSMB->InformationLevel = cpu_to_le16(psrch_inf->info_level);
3387 pSMB->ResumeKey = psrch_inf->resume_key;
3389 cpu_to_le16(CIFS_SEARCH_CLOSE_AT_END | CIFS_SEARCH_RETURN_RESUME);
3391 name_len = psrch_inf->resume_name_len;
3393 if(name_len < PATH_MAX) {
3394 memcpy(pSMB->ResumeFileName, psrch_inf->presume_name, name_len);
3395 byte_count += name_len;
3396 /* 14 byte parm len above enough for 2 byte null terminator */
3397 pSMB->ResumeFileName[name_len] = 0;
3398 pSMB->ResumeFileName[name_len+1] = 0;
3401 goto FNext2_err_exit;
3403 byte_count = params + 1 /* pad */ ;
3404 pSMB->TotalParameterCount = cpu_to_le16(params);
3405 pSMB->ParameterCount = pSMB->TotalParameterCount;
3406 pSMB->hdr.smb_buf_length += byte_count;
3407 pSMB->ByteCount = cpu_to_le16(byte_count);
3409 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3410 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3411 cifs_stats_inc(&tcon->num_fnext);
3414 psrch_inf->endOfSearch = TRUE;
3415 rc = 0; /* search probably was closed at end of search above */
3417 cFYI(1, ("FindNext returned = %d", rc));
3418 } else { /* decode response */
3419 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3422 /* BB fixme add lock for file (srch_info) struct here */
3423 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
3424 psrch_inf->unicode = TRUE;
3426 psrch_inf->unicode = FALSE;
3427 response_data = (char *) &pSMBr->hdr.Protocol +
3428 le16_to_cpu(pSMBr->t2.ParameterOffset);
3429 parms = (T2_FNEXT_RSP_PARMS *)response_data;
3430 response_data = (char *)&pSMBr->hdr.Protocol +
3431 le16_to_cpu(pSMBr->t2.DataOffset);
3432 if(psrch_inf->smallBuf)
3433 cifs_small_buf_release(
3434 psrch_inf->ntwrk_buf_start);
3436 cifs_buf_release(psrch_inf->ntwrk_buf_start);
3437 psrch_inf->srch_entries_start = response_data;
3438 psrch_inf->ntwrk_buf_start = (char *)pSMB;
3439 psrch_inf->smallBuf = 0;
3440 if(parms->EndofSearch)
3441 psrch_inf->endOfSearch = TRUE;
3443 psrch_inf->endOfSearch = FALSE;
3445 psrch_inf->entries_in_buffer = le16_to_cpu(parms->SearchCount);
3446 psrch_inf->index_of_last_entry +=
3447 psrch_inf->entries_in_buffer;
3448 /* cFYI(1,("fnxt2 entries in buf %d index_of_last %d",psrch_inf->entries_in_buffer,psrch_inf->index_of_last_entry)); */
3450 /* BB fixme add unlock here */
3455 /* BB On error, should we leave previous search buf (and count and
3456 last entry fields) intact or free the previous one? */
3458 /* Note: On -EAGAIN error only caller can retry on handle based calls
3459 since file handle passed in no longer valid */
3462 cifs_buf_release(pSMB);
3468 CIFSFindClose(const int xid, struct cifsTconInfo *tcon, const __u16 searchHandle)
3471 FINDCLOSE_REQ *pSMB = NULL;
3472 CLOSE_RSP *pSMBr = NULL; /* BB removeme BB */
3475 cFYI(1, ("In CIFSSMBFindClose"));
3476 rc = small_smb_init(SMB_COM_FIND_CLOSE2, 1, tcon, (void **)&pSMB);
3478 /* no sense returning error if session restarted
3479 as file handle has been closed */
3485 pSMBr = (CLOSE_RSP *)pSMB; /* BB removeme BB */
3486 pSMB->FileID = searchHandle;
3487 pSMB->ByteCount = 0;
3488 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3489 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3491 cERROR(1, ("Send error in FindClose = %d", rc));
3493 cifs_stats_inc(&tcon->num_fclose);
3494 cifs_small_buf_release(pSMB);
3496 /* Since session is dead, search handle closed on server already */
3504 CIFSGetSrvInodeNumber(const int xid, struct cifsTconInfo *tcon,
3505 const unsigned char *searchName,
3506 __u64 * inode_number,
3507 const struct nls_table *nls_codepage, int remap)
3510 TRANSACTION2_QPI_REQ *pSMB = NULL;
3511 TRANSACTION2_QPI_RSP *pSMBr = NULL;
3512 int name_len, bytes_returned;
3513 __u16 params, byte_count;
3515 cFYI(1,("In GetSrvInodeNum for %s",searchName));
3519 GetInodeNumberRetry:
3520 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3526 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3528 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
3529 PATH_MAX,nls_codepage, remap);
3530 name_len++; /* trailing null */
3532 } else { /* BB improve the check for buffer overruns BB */
3533 name_len = strnlen(searchName, PATH_MAX);
3534 name_len++; /* trailing null */
3535 strncpy(pSMB->FileName, searchName, name_len);
3538 params = 2 /* level */ + 4 /* rsrvd */ + name_len /* incl null */ ;
3539 pSMB->TotalDataCount = 0;
3540 pSMB->MaxParameterCount = cpu_to_le16(2);
3541 /* BB find exact max data count below from sess structure BB */
3542 pSMB->MaxDataCount = cpu_to_le16(4000);
3543 pSMB->MaxSetupCount = 0;
3547 pSMB->Reserved2 = 0;
3548 pSMB->ParameterOffset = cpu_to_le16(offsetof(
3549 struct smb_com_transaction2_qpi_req ,InformationLevel) - 4);
3550 pSMB->DataCount = 0;
3551 pSMB->DataOffset = 0;
3552 pSMB->SetupCount = 1;
3553 pSMB->Reserved3 = 0;
3554 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
3555 byte_count = params + 1 /* pad */ ;
3556 pSMB->TotalParameterCount = cpu_to_le16(params);
3557 pSMB->ParameterCount = pSMB->TotalParameterCount;
3558 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_INTERNAL_INFO);
3559 pSMB->Reserved4 = 0;
3560 pSMB->hdr.smb_buf_length += byte_count;
3561 pSMB->ByteCount = cpu_to_le16(byte_count);
3563 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3564 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3566 cFYI(1, ("error %d in QueryInternalInfo", rc));
3568 /* decode response */
3569 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3570 if (rc || (pSMBr->ByteCount < 2))
3571 /* BB also check enough total bytes returned */
3572 /* If rc should we check for EOPNOSUPP and
3573 disable the srvino flag? or in caller? */
3574 rc = -EIO; /* bad smb */
3576 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3577 __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
3578 struct file_internal_info * pfinfo;
3579 /* BB Do we need a cast or hash here ? */
3581 cFYI(1, ("Illegal size ret in QryIntrnlInf"));
3583 goto GetInodeNumOut;
3585 pfinfo = (struct file_internal_info *)
3586 (data_offset + (char *) &pSMBr->hdr.Protocol);
3587 *inode_number = pfinfo->UniqueId;
3591 cifs_buf_release(pSMB);
3593 goto GetInodeNumberRetry;
3598 CIFSGetDFSRefer(const int xid, struct cifsSesInfo *ses,
3599 const unsigned char *searchName,
3600 unsigned char **targetUNCs,
3601 unsigned int *number_of_UNC_in_array,
3602 const struct nls_table *nls_codepage, int remap)
3604 /* TRANS2_GET_DFS_REFERRAL */
3605 TRANSACTION2_GET_DFS_REFER_REQ *pSMB = NULL;
3606 TRANSACTION2_GET_DFS_REFER_RSP *pSMBr = NULL;
3607 struct dfs_referral_level_3 * referrals = NULL;
3613 __u16 params, byte_count;
3614 *number_of_UNC_in_array = 0;
3617 cFYI(1, ("In GetDFSRefer the path %s", searchName));
3621 rc = smb_init(SMB_COM_TRANSACTION2, 15, NULL, (void **) &pSMB,
3626 /* server pointer checked in called function,
3627 but should never be null here anyway */
3628 pSMB->hdr.Mid = GetNextMid(ses->server);
3629 pSMB->hdr.Tid = ses->ipc_tid;
3630 pSMB->hdr.Uid = ses->Suid;
3631 if (ses->capabilities & CAP_STATUS32) {
3632 pSMB->hdr.Flags2 |= SMBFLG2_ERR_STATUS;
3634 if (ses->capabilities & CAP_DFS) {
3635 pSMB->hdr.Flags2 |= SMBFLG2_DFS;
3638 if (ses->capabilities & CAP_UNICODE) {
3639 pSMB->hdr.Flags2 |= SMBFLG2_UNICODE;
3641 cifsConvertToUCS((__le16 *) pSMB->RequestFileName,
3642 searchName, PATH_MAX, nls_codepage, remap);
3643 name_len++; /* trailing null */
3645 } else { /* BB improve the check for buffer overruns BB */
3646 name_len = strnlen(searchName, PATH_MAX);
3647 name_len++; /* trailing null */
3648 strncpy(pSMB->RequestFileName, searchName, name_len);
3651 params = 2 /* level */ + name_len /*includes null */ ;
3652 pSMB->TotalDataCount = 0;
3653 pSMB->DataCount = 0;
3654 pSMB->DataOffset = 0;
3655 pSMB->MaxParameterCount = 0;
3656 pSMB->MaxDataCount = cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
3657 pSMB->MaxSetupCount = 0;
3661 pSMB->Reserved2 = 0;
3662 pSMB->ParameterOffset = cpu_to_le16(offsetof(
3663 struct smb_com_transaction2_get_dfs_refer_req, MaxReferralLevel) - 4);
3664 pSMB->SetupCount = 1;
3665 pSMB->Reserved3 = 0;
3666 pSMB->SubCommand = cpu_to_le16(TRANS2_GET_DFS_REFERRAL);
3667 byte_count = params + 3 /* pad */ ;
3668 pSMB->ParameterCount = cpu_to_le16(params);
3669 pSMB->TotalParameterCount = pSMB->ParameterCount;
3670 pSMB->MaxReferralLevel = cpu_to_le16(3);
3671 pSMB->hdr.smb_buf_length += byte_count;
3672 pSMB->ByteCount = cpu_to_le16(byte_count);
3674 rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB,
3675 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3677 cFYI(1, ("Send error in GetDFSRefer = %d", rc));
3678 } else { /* decode response */
3679 /* BB Add logic to parse referrals here */
3680 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3682 if (rc || (pSMBr->ByteCount < 17)) /* BB also check enough total bytes returned */
3683 rc = -EIO; /* bad smb */
3685 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3686 __u16 data_count = le16_to_cpu(pSMBr->t2.DataCount);
3689 ("Decoding GetDFSRefer response. BCC: %d Offset %d",
3690 pSMBr->ByteCount, data_offset));
3692 (struct dfs_referral_level_3 *)
3693 (8 /* sizeof start of data block */ +
3695 (char *) &pSMBr->hdr.Protocol);
3696 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",
3697 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)));
3698 /* BB This field is actually two bytes in from start of
3699 data block so we could do safety check that DataBlock
3700 begins at address of pSMBr->NumberOfReferrals */
3701 *number_of_UNC_in_array = le16_to_cpu(pSMBr->NumberOfReferrals);
3703 /* BB Fix below so can return more than one referral */
3704 if(*number_of_UNC_in_array > 1)
3705 *number_of_UNC_in_array = 1;
3707 /* get the length of the strings describing refs */
3709 for(i=0;i<*number_of_UNC_in_array;i++) {
3710 /* make sure that DfsPathOffset not past end */
3711 __u16 offset = le16_to_cpu(referrals->DfsPathOffset);
3712 if (offset > data_count) {
3713 /* if invalid referral, stop here and do
3714 not try to copy any more */
3715 *number_of_UNC_in_array = i;
3718 temp = ((char *)referrals) + offset;
3720 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
3721 name_len += UniStrnlen((wchar_t *)temp,data_count);
3723 name_len += strnlen(temp,data_count);
3726 /* BB add check that referral pointer does not fall off end PDU */
3729 /* BB add check for name_len bigger than bcc */
3731 kmalloc(name_len+1+ (*number_of_UNC_in_array),GFP_KERNEL);
3732 if(*targetUNCs == NULL) {
3736 /* copy the ref strings */
3738 (struct dfs_referral_level_3 *)
3739 (8 /* sizeof data hdr */ +
3741 (char *) &pSMBr->hdr.Protocol);
3743 for(i=0;i<*number_of_UNC_in_array;i++) {
3744 temp = ((char *)referrals) + le16_to_cpu(referrals->DfsPathOffset);
3745 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
3746 cifs_strfromUCS_le(*targetUNCs,
3747 (__le16 *) temp, name_len, nls_codepage);
3749 strncpy(*targetUNCs,temp,name_len);
3751 /* BB update target_uncs pointers */
3761 cifs_buf_release(pSMB);
3769 /* Query File System Info such as free space to old servers such as Win 9x */
3771 SMBOldQFSInfo(const int xid, struct cifsTconInfo *tcon, struct kstatfs *FSData)
3773 /* level 0x01 SMB_QUERY_FILE_SYSTEM_INFO */
3774 TRANSACTION2_QFSI_REQ *pSMB = NULL;
3775 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
3776 FILE_SYSTEM_ALLOC_INFO *response_data;
3778 int bytes_returned = 0;
3779 __u16 params, byte_count;
3781 cFYI(1, ("OldQFSInfo"));
3783 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3787 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3792 params = 2; /* level */
3793 pSMB->TotalDataCount = 0;
3794 pSMB->MaxParameterCount = cpu_to_le16(2);
3795 pSMB->MaxDataCount = cpu_to_le16(1000);
3796 pSMB->MaxSetupCount = 0;
3800 pSMB->Reserved2 = 0;
3801 byte_count = params + 1 /* pad */ ;
3802 pSMB->TotalParameterCount = cpu_to_le16(params);
3803 pSMB->ParameterCount = pSMB->TotalParameterCount;
3804 pSMB->ParameterOffset = cpu_to_le16(offsetof(
3805 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
3806 pSMB->DataCount = 0;
3807 pSMB->DataOffset = 0;
3808 pSMB->SetupCount = 1;
3809 pSMB->Reserved3 = 0;
3810 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
3811 pSMB->InformationLevel = cpu_to_le16(SMB_INFO_ALLOCATION);
3812 pSMB->hdr.smb_buf_length += byte_count;
3813 pSMB->ByteCount = cpu_to_le16(byte_count);
3815 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3816 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3818 cFYI(1, ("Send error in QFSInfo = %d", rc));
3819 } else { /* decode response */
3820 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3822 if (rc || (pSMBr->ByteCount < 18))
3823 rc = -EIO; /* bad smb */
3825 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3826 cFYI(1,("qfsinf resp BCC: %d Offset %d",
3827 pSMBr->ByteCount, data_offset));
3830 (FILE_SYSTEM_ALLOC_INFO *)
3831 (((char *) &pSMBr->hdr.Protocol) + data_offset);
3833 le16_to_cpu(response_data->BytesPerSector) *
3834 le32_to_cpu(response_data->
3835 SectorsPerAllocationUnit);
3837 le32_to_cpu(response_data->TotalAllocationUnits);
3838 FSData->f_bfree = FSData->f_bavail =
3839 le32_to_cpu(response_data->FreeAllocationUnits);
3841 ("Blocks: %lld Free: %lld Block size %ld",
3842 (unsigned long long)FSData->f_blocks,
3843 (unsigned long long)FSData->f_bfree,
3847 cifs_buf_release(pSMB);
3850 goto oldQFSInfoRetry;
3856 CIFSSMBQFSInfo(const int xid, struct cifsTconInfo *tcon, struct kstatfs *FSData)
3858 /* level 0x103 SMB_QUERY_FILE_SYSTEM_INFO */
3859 TRANSACTION2_QFSI_REQ *pSMB = NULL;
3860 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
3861 FILE_SYSTEM_INFO *response_data;
3863 int bytes_returned = 0;
3864 __u16 params, byte_count;
3866 cFYI(1, ("In QFSInfo"));
3868 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3873 params = 2; /* level */
3874 pSMB->TotalDataCount = 0;
3875 pSMB->MaxParameterCount = cpu_to_le16(2);
3876 pSMB->MaxDataCount = cpu_to_le16(1000);
3877 pSMB->MaxSetupCount = 0;
3881 pSMB->Reserved2 = 0;
3882 byte_count = params + 1 /* pad */ ;
3883 pSMB->TotalParameterCount = cpu_to_le16(params);
3884 pSMB->ParameterCount = pSMB->TotalParameterCount;
3885 pSMB->ParameterOffset = cpu_to_le16(offsetof(
3886 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
3887 pSMB->DataCount = 0;
3888 pSMB->DataOffset = 0;
3889 pSMB->SetupCount = 1;
3890 pSMB->Reserved3 = 0;
3891 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
3892 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_SIZE_INFO);
3893 pSMB->hdr.smb_buf_length += byte_count;
3894 pSMB->ByteCount = cpu_to_le16(byte_count);
3896 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3897 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3899 cFYI(1, ("Send error in QFSInfo = %d", rc));
3900 } else { /* decode response */
3901 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3903 if (rc || (pSMBr->ByteCount < 24))
3904 rc = -EIO; /* bad smb */
3906 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3910 *) (((char *) &pSMBr->hdr.Protocol) +
3913 le32_to_cpu(response_data->BytesPerSector) *
3914 le32_to_cpu(response_data->
3915 SectorsPerAllocationUnit);
3917 le64_to_cpu(response_data->TotalAllocationUnits);
3918 FSData->f_bfree = FSData->f_bavail =
3919 le64_to_cpu(response_data->FreeAllocationUnits);
3921 ("Blocks: %lld Free: %lld Block size %ld",
3922 (unsigned long long)FSData->f_blocks,
3923 (unsigned long long)FSData->f_bfree,
3927 cifs_buf_release(pSMB);
3936 CIFSSMBQFSAttributeInfo(const int xid, struct cifsTconInfo *tcon)
3938 /* level 0x105 SMB_QUERY_FILE_SYSTEM_INFO */
3939 TRANSACTION2_QFSI_REQ *pSMB = NULL;
3940 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
3941 FILE_SYSTEM_ATTRIBUTE_INFO *response_data;
3943 int bytes_returned = 0;
3944 __u16 params, byte_count;
3946 cFYI(1, ("In QFSAttributeInfo"));
3948 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3953 params = 2; /* level */
3954 pSMB->TotalDataCount = 0;
3955 pSMB->MaxParameterCount = cpu_to_le16(2);
3956 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
3957 pSMB->MaxSetupCount = 0;
3961 pSMB->Reserved2 = 0;
3962 byte_count = params + 1 /* pad */ ;
3963 pSMB->TotalParameterCount = cpu_to_le16(params);
3964 pSMB->ParameterCount = pSMB->TotalParameterCount;
3965 pSMB->ParameterOffset = cpu_to_le16(offsetof(
3966 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
3967 pSMB->DataCount = 0;
3968 pSMB->DataOffset = 0;
3969 pSMB->SetupCount = 1;
3970 pSMB->Reserved3 = 0;
3971 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
3972 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_ATTRIBUTE_INFO);
3973 pSMB->hdr.smb_buf_length += byte_count;
3974 pSMB->ByteCount = cpu_to_le16(byte_count);
3976 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3977 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3979 cERROR(1, ("Send error in QFSAttributeInfo = %d", rc));
3980 } else { /* decode response */
3981 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3983 if (rc || (pSMBr->ByteCount < 13)) { /* BB also check enough bytes returned */
3984 rc = -EIO; /* bad smb */
3986 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3988 (FILE_SYSTEM_ATTRIBUTE_INFO
3989 *) (((char *) &pSMBr->hdr.Protocol) +
3991 memcpy(&tcon->fsAttrInfo, response_data,
3992 sizeof (FILE_SYSTEM_ATTRIBUTE_INFO));
3995 cifs_buf_release(pSMB);
3998 goto QFSAttributeRetry;
4004 CIFSSMBQFSDeviceInfo(const int xid, struct cifsTconInfo *tcon)
4006 /* level 0x104 SMB_QUERY_FILE_SYSTEM_INFO */
4007 TRANSACTION2_QFSI_REQ *pSMB = NULL;
4008 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4009 FILE_SYSTEM_DEVICE_INFO *response_data;
4011 int bytes_returned = 0;
4012 __u16 params, byte_count;
4014 cFYI(1, ("In QFSDeviceInfo"));
4016 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4021 params = 2; /* level */
4022 pSMB->TotalDataCount = 0;
4023 pSMB->MaxParameterCount = cpu_to_le16(2);
4024 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
4025 pSMB->MaxSetupCount = 0;
4029 pSMB->Reserved2 = 0;
4030 byte_count = params + 1 /* pad */ ;
4031 pSMB->TotalParameterCount = cpu_to_le16(params);
4032 pSMB->ParameterCount = pSMB->TotalParameterCount;
4033 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4034 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4036 pSMB->DataCount = 0;
4037 pSMB->DataOffset = 0;
4038 pSMB->SetupCount = 1;
4039 pSMB->Reserved3 = 0;
4040 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4041 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_DEVICE_INFO);
4042 pSMB->hdr.smb_buf_length += byte_count;
4043 pSMB->ByteCount = cpu_to_le16(byte_count);
4045 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4046 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4048 cFYI(1, ("Send error in QFSDeviceInfo = %d", rc));
4049 } else { /* decode response */
4050 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4052 if (rc || (pSMBr->ByteCount < sizeof (FILE_SYSTEM_DEVICE_INFO)))
4053 rc = -EIO; /* bad smb */
4055 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4057 (FILE_SYSTEM_DEVICE_INFO *)
4058 (((char *) &pSMBr->hdr.Protocol) +
4060 memcpy(&tcon->fsDevInfo, response_data,
4061 sizeof (FILE_SYSTEM_DEVICE_INFO));
4064 cifs_buf_release(pSMB);
4067 goto QFSDeviceRetry;
4073 CIFSSMBQFSUnixInfo(const int xid, struct cifsTconInfo *tcon)
4075 /* level 0x200 SMB_QUERY_CIFS_UNIX_INFO */
4076 TRANSACTION2_QFSI_REQ *pSMB = NULL;
4077 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4078 FILE_SYSTEM_UNIX_INFO *response_data;
4080 int bytes_returned = 0;
4081 __u16 params, byte_count;
4083 cFYI(1, ("In QFSUnixInfo"));
4085 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4090 params = 2; /* level */
4091 pSMB->TotalDataCount = 0;
4092 pSMB->DataCount = 0;
4093 pSMB->DataOffset = 0;
4094 pSMB->MaxParameterCount = cpu_to_le16(2);
4095 pSMB->MaxDataCount = cpu_to_le16(100); /* BB find exact max SMB PDU from sess structure BB */
4096 pSMB->MaxSetupCount = 0;
4100 pSMB->Reserved2 = 0;
4101 byte_count = params + 1 /* pad */ ;
4102 pSMB->ParameterCount = cpu_to_le16(params);
4103 pSMB->TotalParameterCount = pSMB->ParameterCount;
4104 pSMB->ParameterOffset = cpu_to_le16(offsetof(struct
4105 smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4106 pSMB->SetupCount = 1;
4107 pSMB->Reserved3 = 0;
4108 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4109 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_CIFS_UNIX_INFO);
4110 pSMB->hdr.smb_buf_length += byte_count;
4111 pSMB->ByteCount = cpu_to_le16(byte_count);
4113 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4114 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4116 cERROR(1, ("Send error in QFSUnixInfo = %d", rc));
4117 } else { /* decode response */
4118 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4120 if (rc || (pSMBr->ByteCount < 13)) {
4121 rc = -EIO; /* bad smb */
4123 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4125 (FILE_SYSTEM_UNIX_INFO
4126 *) (((char *) &pSMBr->hdr.Protocol) +
4128 memcpy(&tcon->fsUnixInfo, response_data,
4129 sizeof (FILE_SYSTEM_UNIX_INFO));
4132 cifs_buf_release(pSMB);
4142 CIFSSMBSetFSUnixInfo(const int xid, struct cifsTconInfo *tcon, __u64 cap)
4144 /* level 0x200 SMB_SET_CIFS_UNIX_INFO */
4145 TRANSACTION2_SETFSI_REQ *pSMB = NULL;
4146 TRANSACTION2_SETFSI_RSP *pSMBr = NULL;
4148 int bytes_returned = 0;
4149 __u16 params, param_offset, offset, byte_count;
4151 cFYI(1, ("In SETFSUnixInfo"));
4153 /* BB switch to small buf init to save memory */
4154 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4159 params = 4; /* 2 bytes zero followed by info level. */
4160 pSMB->MaxSetupCount = 0;
4164 pSMB->Reserved2 = 0;
4165 param_offset = offsetof(struct smb_com_transaction2_setfsi_req, FileNum) - 4;
4166 offset = param_offset + params;
4168 pSMB->MaxParameterCount = cpu_to_le16(4);
4169 pSMB->MaxDataCount = cpu_to_le16(100); /* BB find exact max SMB PDU from sess structure BB */
4170 pSMB->SetupCount = 1;
4171 pSMB->Reserved3 = 0;
4172 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FS_INFORMATION);
4173 byte_count = 1 /* pad */ + params + 12;
4175 pSMB->DataCount = cpu_to_le16(12);
4176 pSMB->ParameterCount = cpu_to_le16(params);
4177 pSMB->TotalDataCount = pSMB->DataCount;
4178 pSMB->TotalParameterCount = pSMB->ParameterCount;
4179 pSMB->ParameterOffset = cpu_to_le16(param_offset);
4180 pSMB->DataOffset = cpu_to_le16(offset);
4184 pSMB->InformationLevel = cpu_to_le16(SMB_SET_CIFS_UNIX_INFO);
4187 pSMB->ClientUnixMajor = cpu_to_le16(CIFS_UNIX_MAJOR_VERSION);
4188 pSMB->ClientUnixMinor = cpu_to_le16(CIFS_UNIX_MINOR_VERSION);
4189 pSMB->ClientUnixCap = cpu_to_le64(cap);
4191 pSMB->hdr.smb_buf_length += byte_count;
4192 pSMB->ByteCount = cpu_to_le16(byte_count);
4194 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4195 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4197 cERROR(1, ("Send error in SETFSUnixInfo = %d", rc));
4198 } else { /* decode response */
4199 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4201 rc = -EIO; /* bad smb */
4204 cifs_buf_release(pSMB);
4207 goto SETFSUnixRetry;
4215 CIFSSMBQFSPosixInfo(const int xid, struct cifsTconInfo *tcon,
4216 struct kstatfs *FSData)
4218 /* level 0x201 SMB_QUERY_CIFS_POSIX_INFO */
4219 TRANSACTION2_QFSI_REQ *pSMB = NULL;
4220 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4221 FILE_SYSTEM_POSIX_INFO *response_data;
4223 int bytes_returned = 0;
4224 __u16 params, byte_count;
4226 cFYI(1, ("In QFSPosixInfo"));
4228 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4233 params = 2; /* level */
4234 pSMB->TotalDataCount = 0;
4235 pSMB->DataCount = 0;
4236 pSMB->DataOffset = 0;
4237 pSMB->MaxParameterCount = cpu_to_le16(2);
4238 pSMB->MaxDataCount = cpu_to_le16(100); /* BB find exact max SMB PDU from sess structure BB */
4239 pSMB->MaxSetupCount = 0;
4243 pSMB->Reserved2 = 0;
4244 byte_count = params + 1 /* pad */ ;
4245 pSMB->ParameterCount = cpu_to_le16(params);
4246 pSMB->TotalParameterCount = pSMB->ParameterCount;
4247 pSMB->ParameterOffset = cpu_to_le16(offsetof(struct
4248 smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4249 pSMB->SetupCount = 1;
4250 pSMB->Reserved3 = 0;
4251 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4252 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_POSIX_FS_INFO);
4253 pSMB->hdr.smb_buf_length += byte_count;
4254 pSMB->ByteCount = cpu_to_le16(byte_count);
4256 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4257 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4259 cFYI(1, ("Send error in QFSUnixInfo = %d", rc));
4260 } else { /* decode response */
4261 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4263 if (rc || (pSMBr->ByteCount < 13)) {
4264 rc = -EIO; /* bad smb */
4266 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4268 (FILE_SYSTEM_POSIX_INFO
4269 *) (((char *) &pSMBr->hdr.Protocol) +
4272 le32_to_cpu(response_data->BlockSize);
4274 le64_to_cpu(response_data->TotalBlocks);
4276 le64_to_cpu(response_data->BlocksAvail);
4277 if(response_data->UserBlocksAvail == cpu_to_le64(-1)) {
4278 FSData->f_bavail = FSData->f_bfree;
4281 le64_to_cpu(response_data->UserBlocksAvail);
4283 if(response_data->TotalFileNodes != cpu_to_le64(-1))
4285 le64_to_cpu(response_data->TotalFileNodes);
4286 if(response_data->FreeFileNodes != cpu_to_le64(-1))
4288 le64_to_cpu(response_data->FreeFileNodes);
4291 cifs_buf_release(pSMB);
4300 /* We can not use write of zero bytes trick to
4301 set file size due to need for large file support. Also note that
4302 this SetPathInfo is preferred to SetFileInfo based method in next
4303 routine which is only needed to work around a sharing violation bug
4304 in Samba which this routine can run into */
4307 CIFSSMBSetEOF(const int xid, struct cifsTconInfo *tcon, const char *fileName,
4308 __u64 size, int SetAllocation,
4309 const struct nls_table *nls_codepage, int remap)
4311 struct smb_com_transaction2_spi_req *pSMB = NULL;
4312 struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
4313 struct file_end_of_file_info *parm_data;
4316 int bytes_returned = 0;
4317 __u16 params, byte_count, data_count, param_offset, offset;
4319 cFYI(1, ("In SetEOF"));
4321 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4326 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4328 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
4329 PATH_MAX, nls_codepage, remap);
4330 name_len++; /* trailing null */
4332 } else { /* BB improve the check for buffer overruns BB */
4333 name_len = strnlen(fileName, PATH_MAX);
4334 name_len++; /* trailing null */
4335 strncpy(pSMB->FileName, fileName, name_len);
4337 params = 6 + name_len;
4338 data_count = sizeof (struct file_end_of_file_info);
4339 pSMB->MaxParameterCount = cpu_to_le16(2);
4340 pSMB->MaxDataCount = cpu_to_le16(4100);
4341 pSMB->MaxSetupCount = 0;
4345 pSMB->Reserved2 = 0;
4346 param_offset = offsetof(struct smb_com_transaction2_spi_req,
4347 InformationLevel) - 4;
4348 offset = param_offset + params;
4350 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
4351 pSMB->InformationLevel =
4352 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2);
4354 pSMB->InformationLevel =
4355 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO);
4356 } else /* Set File Size */ {
4357 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
4358 pSMB->InformationLevel =
4359 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO2);
4361 pSMB->InformationLevel =
4362 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO);
4366 (struct file_end_of_file_info *) (((char *) &pSMB->hdr.Protocol) +
4368 pSMB->ParameterOffset = cpu_to_le16(param_offset);
4369 pSMB->DataOffset = cpu_to_le16(offset);
4370 pSMB->SetupCount = 1;
4371 pSMB->Reserved3 = 0;
4372 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
4373 byte_count = 3 /* pad */ + params + data_count;
4374 pSMB->DataCount = cpu_to_le16(data_count);
4375 pSMB->TotalDataCount = pSMB->DataCount;
4376 pSMB->ParameterCount = cpu_to_le16(params);
4377 pSMB->TotalParameterCount = pSMB->ParameterCount;
4378 pSMB->Reserved4 = 0;
4379 pSMB->hdr.smb_buf_length += byte_count;
4380 parm_data->FileSize = cpu_to_le64(size);
4381 pSMB->ByteCount = cpu_to_le16(byte_count);
4382 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4383 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4385 cFYI(1, ("SetPathInfo (file size) returned %d", rc));
4388 cifs_buf_release(pSMB);
4397 CIFSSMBSetFileSize(const int xid, struct cifsTconInfo *tcon, __u64 size,
4398 __u16 fid, __u32 pid_of_opener, int SetAllocation)
4400 struct smb_com_transaction2_sfi_req *pSMB = NULL;
4401 struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
4403 struct file_end_of_file_info *parm_data;
4405 int bytes_returned = 0;
4406 __u16 params, param_offset, offset, byte_count, count;
4408 cFYI(1, ("SetFileSize (via SetFileInfo) %lld",
4410 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
4415 pSMBr = (struct smb_com_transaction2_sfi_rsp *)pSMB;
4417 pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
4418 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));
4421 pSMB->MaxSetupCount = 0;
4425 pSMB->Reserved2 = 0;
4426 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
4427 offset = param_offset + params;
4429 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
4431 count = sizeof(struct file_end_of_file_info);
4432 pSMB->MaxParameterCount = cpu_to_le16(2);
4433 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB PDU from sess */
4434 pSMB->SetupCount = 1;
4435 pSMB->Reserved3 = 0;
4436 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
4437 byte_count = 3 /* pad */ + params + count;
4438 pSMB->DataCount = cpu_to_le16(count);
4439 pSMB->ParameterCount = cpu_to_le16(params);
4440 pSMB->TotalDataCount = pSMB->DataCount;
4441 pSMB->TotalParameterCount = pSMB->ParameterCount;
4442 pSMB->ParameterOffset = cpu_to_le16(param_offset);
4444 (struct file_end_of_file_info *) (((char *) &pSMB->hdr.Protocol) +
4446 pSMB->DataOffset = cpu_to_le16(offset);
4447 parm_data->FileSize = cpu_to_le64(size);
4450 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
4451 pSMB->InformationLevel =
4452 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2);
4454 pSMB->InformationLevel =
4455 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO);
4456 } else /* Set File Size */ {
4457 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
4458 pSMB->InformationLevel =
4459 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO2);
4461 pSMB->InformationLevel =
4462 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO);
4464 pSMB->Reserved4 = 0;
4465 pSMB->hdr.smb_buf_length += byte_count;
4466 pSMB->ByteCount = cpu_to_le16(byte_count);
4467 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4468 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4471 ("Send error in SetFileInfo (SetFileSize) = %d",
4476 cifs_small_buf_release(pSMB);
4478 /* Note: On -EAGAIN error only caller can retry on handle based calls
4479 since file handle passed in no longer valid */
4484 /* Some legacy servers such as NT4 require that the file times be set on
4485 an open handle, rather than by pathname - this is awkward due to
4486 potential access conflicts on the open, but it is unavoidable for these
4487 old servers since the only other choice is to go from 100 nanosecond DCE
4488 time and resort to the original setpathinfo level which takes the ancient
4489 DOS time format with 2 second granularity */
4491 CIFSSMBSetFileTimes(const int xid, struct cifsTconInfo *tcon, const FILE_BASIC_INFO * data,
4494 struct smb_com_transaction2_sfi_req *pSMB = NULL;
4495 struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
4498 int bytes_returned = 0;
4499 __u16 params, param_offset, offset, byte_count, count;
4501 cFYI(1, ("Set Times (via SetFileInfo)"));
4502 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
4507 pSMBr = (struct smb_com_transaction2_sfi_rsp *)pSMB;
4509 /* At this point there is no need to override the current pid
4510 with the pid of the opener, but that could change if we someday
4511 use an existing handle (rather than opening one on the fly) */
4512 /* pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
4513 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));*/
4516 pSMB->MaxSetupCount = 0;
4520 pSMB->Reserved2 = 0;
4521 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
4522 offset = param_offset + params;
4524 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
4526 count = sizeof (FILE_BASIC_INFO);
4527 pSMB->MaxParameterCount = cpu_to_le16(2);
4528 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB PDU from sess */
4529 pSMB->SetupCount = 1;
4530 pSMB->Reserved3 = 0;
4531 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
4532 byte_count = 3 /* pad */ + params + count;
4533 pSMB->DataCount = cpu_to_le16(count);
4534 pSMB->ParameterCount = cpu_to_le16(params);
4535 pSMB->TotalDataCount = pSMB->DataCount;
4536 pSMB->TotalParameterCount = pSMB->ParameterCount;
4537 pSMB->ParameterOffset = cpu_to_le16(param_offset);
4538 pSMB->DataOffset = cpu_to_le16(offset);
4540 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
4541 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO2);
4543 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO);
4544 pSMB->Reserved4 = 0;
4545 pSMB->hdr.smb_buf_length += byte_count;
4546 pSMB->ByteCount = cpu_to_le16(byte_count);
4547 memcpy(data_offset,data,sizeof(FILE_BASIC_INFO));
4548 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4549 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4551 cFYI(1,("Send error in Set Time (SetFileInfo) = %d",rc));
4554 cifs_small_buf_release(pSMB);
4556 /* Note: On -EAGAIN error only caller can retry on handle based calls
4557 since file handle passed in no longer valid */
4564 CIFSSMBSetTimes(const int xid, struct cifsTconInfo *tcon, const char *fileName,
4565 const FILE_BASIC_INFO * data,
4566 const struct nls_table *nls_codepage, int remap)
4568 TRANSACTION2_SPI_REQ *pSMB = NULL;
4569 TRANSACTION2_SPI_RSP *pSMBr = NULL;
4572 int bytes_returned = 0;
4574 __u16 params, param_offset, offset, byte_count, count;
4576 cFYI(1, ("In SetTimes"));
4579 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4584 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4586 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
4587 PATH_MAX, nls_codepage, remap);
4588 name_len++; /* trailing null */
4590 } else { /* BB improve the check for buffer overruns BB */
4591 name_len = strnlen(fileName, PATH_MAX);
4592 name_len++; /* trailing null */
4593 strncpy(pSMB->FileName, fileName, name_len);
4596 params = 6 + name_len;
4597 count = sizeof (FILE_BASIC_INFO);
4598 pSMB->MaxParameterCount = cpu_to_le16(2);
4599 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
4600 pSMB->MaxSetupCount = 0;
4604 pSMB->Reserved2 = 0;
4605 param_offset = offsetof(struct smb_com_transaction2_spi_req,
4606 InformationLevel) - 4;
4607 offset = param_offset + params;
4608 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
4609 pSMB->ParameterOffset = cpu_to_le16(param_offset);
4610 pSMB->DataOffset = cpu_to_le16(offset);
4611 pSMB->SetupCount = 1;
4612 pSMB->Reserved3 = 0;
4613 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
4614 byte_count = 3 /* pad */ + params + count;
4616 pSMB->DataCount = cpu_to_le16(count);
4617 pSMB->ParameterCount = cpu_to_le16(params);
4618 pSMB->TotalDataCount = pSMB->DataCount;
4619 pSMB->TotalParameterCount = pSMB->ParameterCount;
4620 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
4621 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO2);
4623 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO);
4624 pSMB->Reserved4 = 0;
4625 pSMB->hdr.smb_buf_length += byte_count;
4626 memcpy(data_offset, data, sizeof (FILE_BASIC_INFO));
4627 pSMB->ByteCount = cpu_to_le16(byte_count);
4628 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4629 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4631 cFYI(1, ("SetPathInfo (times) returned %d", rc));
4634 cifs_buf_release(pSMB);
4642 /* Can not be used to set time stamps yet (due to old DOS time format) */
4643 /* Can be used to set attributes */
4644 #if 0 /* Possibly not needed - since it turns out that strangely NT4 has a bug
4645 handling it anyway and NT4 was what we thought it would be needed for
4646 Do not delete it until we prove whether needed for Win9x though */
4648 CIFSSMBSetAttrLegacy(int xid, struct cifsTconInfo *tcon, char *fileName,
4649 __u16 dos_attrs, const struct nls_table *nls_codepage)
4651 SETATTR_REQ *pSMB = NULL;
4652 SETATTR_RSP *pSMBr = NULL;
4657 cFYI(1, ("In SetAttrLegacy"));
4660 rc = smb_init(SMB_COM_SETATTR, 8, tcon, (void **) &pSMB,
4665 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4667 ConvertToUCS((__le16 *) pSMB->fileName, fileName,
4668 PATH_MAX, nls_codepage);
4669 name_len++; /* trailing null */
4671 } else { /* BB improve the check for buffer overruns BB */
4672 name_len = strnlen(fileName, PATH_MAX);
4673 name_len++; /* trailing null */
4674 strncpy(pSMB->fileName, fileName, name_len);
4676 pSMB->attr = cpu_to_le16(dos_attrs);
4677 pSMB->BufferFormat = 0x04;
4678 pSMB->hdr.smb_buf_length += name_len + 1;
4679 pSMB->ByteCount = cpu_to_le16(name_len + 1);
4680 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4681 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4683 cFYI(1, ("Error in LegacySetAttr = %d", rc));
4686 cifs_buf_release(pSMB);
4689 goto SetAttrLgcyRetry;
4693 #endif /* temporarily unneeded SetAttr legacy function */
4696 CIFSSMBUnixSetPerms(const int xid, struct cifsTconInfo *tcon,
4697 char *fileName, __u64 mode, __u64 uid, __u64 gid,
4698 dev_t device, const struct nls_table *nls_codepage,
4701 TRANSACTION2_SPI_REQ *pSMB = NULL;
4702 TRANSACTION2_SPI_RSP *pSMBr = NULL;
4705 int bytes_returned = 0;
4706 FILE_UNIX_BASIC_INFO *data_offset;
4707 __u16 params, param_offset, offset, count, byte_count;
4709 cFYI(1, ("In SetUID/GID/Mode"));
4711 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4716 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4718 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
4719 PATH_MAX, nls_codepage, remap);
4720 name_len++; /* trailing null */
4722 } else { /* BB improve the check for buffer overruns BB */
4723 name_len = strnlen(fileName, PATH_MAX);
4724 name_len++; /* trailing null */
4725 strncpy(pSMB->FileName, fileName, name_len);
4728 params = 6 + name_len;
4729 count = sizeof (FILE_UNIX_BASIC_INFO);
4730 pSMB->MaxParameterCount = cpu_to_le16(2);
4731 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
4732 pSMB->MaxSetupCount = 0;
4736 pSMB->Reserved2 = 0;
4737 param_offset = offsetof(struct smb_com_transaction2_spi_req,
4738 InformationLevel) - 4;
4739 offset = param_offset + params;
4741 (FILE_UNIX_BASIC_INFO *) ((char *) &pSMB->hdr.Protocol +
4743 memset(data_offset, 0, count);
4744 pSMB->DataOffset = cpu_to_le16(offset);
4745 pSMB->ParameterOffset = cpu_to_le16(param_offset);
4746 pSMB->SetupCount = 1;
4747 pSMB->Reserved3 = 0;
4748 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
4749 byte_count = 3 /* pad */ + params + count;
4750 pSMB->ParameterCount = cpu_to_le16(params);
4751 pSMB->DataCount = cpu_to_le16(count);
4752 pSMB->TotalParameterCount = pSMB->ParameterCount;
4753 pSMB->TotalDataCount = pSMB->DataCount;
4754 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_BASIC);
4755 pSMB->Reserved4 = 0;
4756 pSMB->hdr.smb_buf_length += byte_count;
4757 data_offset->Uid = cpu_to_le64(uid);
4758 data_offset->Gid = cpu_to_le64(gid);
4759 /* better to leave device as zero when it is */
4760 data_offset->DevMajor = cpu_to_le64(MAJOR(device));
4761 data_offset->DevMinor = cpu_to_le64(MINOR(device));
4762 data_offset->Permissions = cpu_to_le64(mode);
4765 data_offset->Type = cpu_to_le32(UNIX_FILE);
4766 else if(S_ISDIR(mode))
4767 data_offset->Type = cpu_to_le32(UNIX_DIR);
4768 else if(S_ISLNK(mode))
4769 data_offset->Type = cpu_to_le32(UNIX_SYMLINK);
4770 else if(S_ISCHR(mode))
4771 data_offset->Type = cpu_to_le32(UNIX_CHARDEV);
4772 else if(S_ISBLK(mode))
4773 data_offset->Type = cpu_to_le32(UNIX_BLOCKDEV);
4774 else if(S_ISFIFO(mode))
4775 data_offset->Type = cpu_to_le32(UNIX_FIFO);
4776 else if(S_ISSOCK(mode))
4777 data_offset->Type = cpu_to_le32(UNIX_SOCKET);
4780 pSMB->ByteCount = cpu_to_le16(byte_count);
4781 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4782 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4784 cFYI(1, ("SetPathInfo (perms) returned %d", rc));
4788 cifs_buf_release(pSMB);
4794 int CIFSSMBNotify(const int xid, struct cifsTconInfo *tcon,
4795 const int notify_subdirs, const __u16 netfid,
4796 __u32 filter, struct file * pfile, int multishot,
4797 const struct nls_table *nls_codepage)
4800 struct smb_com_transaction_change_notify_req * pSMB = NULL;
4801 struct smb_com_ntransaction_change_notify_rsp * pSMBr = NULL;
4802 struct dir_notify_req *dnotify_req;
4805 cFYI(1, ("In CIFSSMBNotify for file handle %d",(int)netfid));
4806 rc = smb_init(SMB_COM_NT_TRANSACT, 23, tcon, (void **) &pSMB,
4811 pSMB->TotalParameterCount = 0 ;
4812 pSMB->TotalDataCount = 0;
4813 pSMB->MaxParameterCount = cpu_to_le32(2);
4814 /* BB find exact data count max from sess structure BB */
4815 pSMB->MaxDataCount = 0; /* same in little endian or be */
4816 /* BB VERIFY verify which is correct for above BB */
4817 pSMB->MaxDataCount = cpu_to_le32((tcon->ses->server->maxBuf -
4818 MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
4820 pSMB->MaxSetupCount = 4;
4822 pSMB->ParameterOffset = 0;
4823 pSMB->DataCount = 0;
4824 pSMB->DataOffset = 0;
4825 pSMB->SetupCount = 4; /* single byte does not need le conversion */
4826 pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_NOTIFY_CHANGE);
4827 pSMB->ParameterCount = pSMB->TotalParameterCount;
4829 pSMB->WatchTree = 1; /* one byte - no le conversion needed */
4830 pSMB->Reserved2 = 0;
4831 pSMB->CompletionFilter = cpu_to_le32(filter);
4832 pSMB->Fid = netfid; /* file handle always le */
4833 pSMB->ByteCount = 0;
4835 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4836 (struct smb_hdr *) pSMBr, &bytes_returned, -1);
4838 cFYI(1, ("Error in Notify = %d", rc));
4840 /* Add file to outstanding requests */
4841 /* BB change to kmem cache alloc */
4842 dnotify_req = (struct dir_notify_req *) kmalloc(
4843 sizeof(struct dir_notify_req),
4846 dnotify_req->Pid = pSMB->hdr.Pid;
4847 dnotify_req->PidHigh = pSMB->hdr.PidHigh;
4848 dnotify_req->Mid = pSMB->hdr.Mid;
4849 dnotify_req->Tid = pSMB->hdr.Tid;
4850 dnotify_req->Uid = pSMB->hdr.Uid;
4851 dnotify_req->netfid = netfid;
4852 dnotify_req->pfile = pfile;
4853 dnotify_req->filter = filter;
4854 dnotify_req->multishot = multishot;
4855 spin_lock(&GlobalMid_Lock);
4856 list_add_tail(&dnotify_req->lhead,
4857 &GlobalDnotifyReqList);
4858 spin_unlock(&GlobalMid_Lock);
4862 cifs_buf_release(pSMB);
4865 #ifdef CONFIG_CIFS_XATTR
4867 CIFSSMBQAllEAs(const int xid, struct cifsTconInfo *tcon,
4868 const unsigned char *searchName,
4869 char * EAData, size_t buf_size,
4870 const struct nls_table *nls_codepage, int remap)
4872 /* BB assumes one setup word */
4873 TRANSACTION2_QPI_REQ *pSMB = NULL;
4874 TRANSACTION2_QPI_RSP *pSMBr = NULL;
4878 struct fea * temp_fea;
4880 __u16 params, byte_count;
4882 cFYI(1, ("In Query All EAs path %s", searchName));
4884 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4889 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4891 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
4892 PATH_MAX, nls_codepage, remap);
4893 name_len++; /* trailing null */
4895 } else { /* BB improve the check for buffer overruns BB */
4896 name_len = strnlen(searchName, PATH_MAX);
4897 name_len++; /* trailing null */
4898 strncpy(pSMB->FileName, searchName, name_len);
4901 params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */ ;
4902 pSMB->TotalDataCount = 0;
4903 pSMB->MaxParameterCount = cpu_to_le16(2);
4904 pSMB->MaxDataCount = cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
4905 pSMB->MaxSetupCount = 0;
4909 pSMB->Reserved2 = 0;
4910 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4911 struct smb_com_transaction2_qpi_req ,InformationLevel) - 4);
4912 pSMB->DataCount = 0;
4913 pSMB->DataOffset = 0;
4914 pSMB->SetupCount = 1;
4915 pSMB->Reserved3 = 0;
4916 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
4917 byte_count = params + 1 /* pad */ ;
4918 pSMB->TotalParameterCount = cpu_to_le16(params);
4919 pSMB->ParameterCount = pSMB->TotalParameterCount;
4920 pSMB->InformationLevel = cpu_to_le16(SMB_INFO_QUERY_ALL_EAS);
4921 pSMB->Reserved4 = 0;
4922 pSMB->hdr.smb_buf_length += byte_count;
4923 pSMB->ByteCount = cpu_to_le16(byte_count);
4925 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4926 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4928 cFYI(1, ("Send error in QueryAllEAs = %d", rc));
4929 } else { /* decode response */
4930 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4932 /* BB also check enough total bytes returned */
4933 /* BB we need to improve the validity checking
4934 of these trans2 responses */
4935 if (rc || (pSMBr->ByteCount < 4))
4936 rc = -EIO; /* bad smb */
4937 /* else if (pFindData){
4938 memcpy((char *) pFindData,
4939 (char *) &pSMBr->hdr.Protocol +
4942 /* check that length of list is not more than bcc */
4943 /* check that each entry does not go beyond length
4945 /* check that each element of each entry does not
4946 go beyond end of list */
4947 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4948 struct fealist * ea_response_data;
4950 /* validate_trans2_offsets() */
4951 /* BB to check if(start of smb + data_offset > &bcc+ bcc)*/
4952 ea_response_data = (struct fealist *)
4953 (((char *) &pSMBr->hdr.Protocol) +
4955 name_len = le32_to_cpu(ea_response_data->list_len);
4956 cFYI(1,("ea length %d", name_len));
4958 /* returned EA size zeroed at top of function */
4959 cFYI(1,("empty EA list returned from server"));
4961 /* account for ea list len */
4963 temp_fea = ea_response_data->list;
4964 temp_ptr = (char *)temp_fea;
4965 while(name_len > 0) {
4969 rc += temp_fea->name_len;
4970 /* account for prefix user. and trailing null */
4972 if(rc<(int)buf_size) {
4973 memcpy(EAData,"user.",5);
4975 memcpy(EAData,temp_ptr,temp_fea->name_len);
4976 EAData+=temp_fea->name_len;
4977 /* null terminate name */
4979 EAData = EAData + 1;
4980 } else if(buf_size == 0) {
4981 /* skip copy - calc size only */
4983 /* stop before overrun buffer */
4987 name_len -= temp_fea->name_len;
4988 temp_ptr += temp_fea->name_len;
4989 /* account for trailing null */
4992 value_len = le16_to_cpu(temp_fea->value_len);
4993 name_len -= value_len;
4994 temp_ptr += value_len;
4995 /* BB check that temp_ptr is still within smb BB*/
4996 /* no trailing null to account for in value len */
4997 /* go on to next EA */
4998 temp_fea = (struct fea *)temp_ptr;
5004 cifs_buf_release(pSMB);
5011 ssize_t CIFSSMBQueryEA(const int xid,struct cifsTconInfo * tcon,
5012 const unsigned char * searchName,const unsigned char * ea_name,
5013 unsigned char * ea_value, size_t buf_size,
5014 const struct nls_table *nls_codepage, int remap)
5016 TRANSACTION2_QPI_REQ *pSMB = NULL;
5017 TRANSACTION2_QPI_RSP *pSMBr = NULL;
5021 struct fea * temp_fea;
5023 __u16 params, byte_count;
5025 cFYI(1, ("In Query EA path %s", searchName));
5027 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5032 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5034 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
5035 PATH_MAX, nls_codepage, remap);
5036 name_len++; /* trailing null */
5038 } else { /* BB improve the check for buffer overruns BB */
5039 name_len = strnlen(searchName, PATH_MAX);
5040 name_len++; /* trailing null */
5041 strncpy(pSMB->FileName, searchName, name_len);
5044 params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */ ;
5045 pSMB->TotalDataCount = 0;
5046 pSMB->MaxParameterCount = cpu_to_le16(2);
5047 pSMB->MaxDataCount = cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
5048 pSMB->MaxSetupCount = 0;
5052 pSMB->Reserved2 = 0;
5053 pSMB->ParameterOffset = cpu_to_le16(offsetof(
5054 struct smb_com_transaction2_qpi_req ,InformationLevel) - 4);
5055 pSMB->DataCount = 0;
5056 pSMB->DataOffset = 0;
5057 pSMB->SetupCount = 1;
5058 pSMB->Reserved3 = 0;
5059 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
5060 byte_count = params + 1 /* pad */ ;
5061 pSMB->TotalParameterCount = cpu_to_le16(params);
5062 pSMB->ParameterCount = pSMB->TotalParameterCount;
5063 pSMB->InformationLevel = cpu_to_le16(SMB_INFO_QUERY_ALL_EAS);
5064 pSMB->Reserved4 = 0;
5065 pSMB->hdr.smb_buf_length += byte_count;
5066 pSMB->ByteCount = cpu_to_le16(byte_count);
5068 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5069 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5071 cFYI(1, ("Send error in Query EA = %d", rc));
5072 } else { /* decode response */
5073 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
5075 /* BB also check enough total bytes returned */
5076 /* BB we need to improve the validity checking
5077 of these trans2 responses */
5078 if (rc || (pSMBr->ByteCount < 4))
5079 rc = -EIO; /* bad smb */
5080 /* else if (pFindData){
5081 memcpy((char *) pFindData,
5082 (char *) &pSMBr->hdr.Protocol +
5085 /* check that length of list is not more than bcc */
5086 /* check that each entry does not go beyond length
5088 /* check that each element of each entry does not
5089 go beyond end of list */
5090 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
5091 struct fealist * ea_response_data;
5093 /* validate_trans2_offsets() */
5094 /* BB to check if(start of smb + data_offset > &bcc+ bcc)*/
5095 ea_response_data = (struct fealist *)
5096 (((char *) &pSMBr->hdr.Protocol) +
5098 name_len = le32_to_cpu(ea_response_data->list_len);
5099 cFYI(1,("ea length %d", name_len));
5101 /* returned EA size zeroed at top of function */
5102 cFYI(1,("empty EA list returned from server"));
5104 /* account for ea list len */
5106 temp_fea = ea_response_data->list;
5107 temp_ptr = (char *)temp_fea;
5108 /* loop through checking if we have a matching
5109 name and then return the associated value */
5110 while(name_len > 0) {
5114 value_len = le16_to_cpu(temp_fea->value_len);
5115 /* BB validate that value_len falls within SMB,
5116 even though maximum for name_len is 255 */
5117 if(memcmp(temp_fea->name,ea_name,
5118 temp_fea->name_len) == 0) {
5121 /* account for prefix user. and trailing null */
5122 if(rc<=(int)buf_size) {
5124 temp_fea->name+temp_fea->name_len+1,
5126 /* ea values, unlike ea names,
5127 are not null terminated */
5128 } else if(buf_size == 0) {
5129 /* skip copy - calc size only */
5131 /* stop before overrun buffer */
5136 name_len -= temp_fea->name_len;
5137 temp_ptr += temp_fea->name_len;
5138 /* account for trailing null */
5141 name_len -= value_len;
5142 temp_ptr += value_len;
5143 /* no trailing null to account for in value len */
5144 /* go on to next EA */
5145 temp_fea = (struct fea *)temp_ptr;
5151 cifs_buf_release(pSMB);
5159 CIFSSMBSetEA(const int xid, struct cifsTconInfo *tcon, const char *fileName,
5160 const char * ea_name, const void * ea_value,
5161 const __u16 ea_value_len, const struct nls_table *nls_codepage,
5164 struct smb_com_transaction2_spi_req *pSMB = NULL;
5165 struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
5166 struct fealist *parm_data;
5169 int bytes_returned = 0;
5170 __u16 params, param_offset, byte_count, offset, count;
5172 cFYI(1, ("In SetEA"));
5174 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5179 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5181 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
5182 PATH_MAX, nls_codepage, remap);
5183 name_len++; /* trailing null */
5185 } else { /* BB improve the check for buffer overruns BB */
5186 name_len = strnlen(fileName, PATH_MAX);
5187 name_len++; /* trailing null */
5188 strncpy(pSMB->FileName, fileName, name_len);
5191 params = 6 + name_len;
5193 /* done calculating parms using name_len of file name,
5194 now use name_len to calculate length of ea name
5195 we are going to create in the inode xattrs */
5199 name_len = strnlen(ea_name,255);
5201 count = sizeof(*parm_data) + ea_value_len + name_len + 1;
5202 pSMB->MaxParameterCount = cpu_to_le16(2);
5203 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB size from sess */
5204 pSMB->MaxSetupCount = 0;
5208 pSMB->Reserved2 = 0;
5209 param_offset = offsetof(struct smb_com_transaction2_spi_req,
5210 InformationLevel) - 4;
5211 offset = param_offset + params;
5212 pSMB->InformationLevel =
5213 cpu_to_le16(SMB_SET_FILE_EA);
5216 (struct fealist *) (((char *) &pSMB->hdr.Protocol) +
5218 pSMB->ParameterOffset = cpu_to_le16(param_offset);
5219 pSMB->DataOffset = cpu_to_le16(offset);
5220 pSMB->SetupCount = 1;
5221 pSMB->Reserved3 = 0;
5222 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
5223 byte_count = 3 /* pad */ + params + count;
5224 pSMB->DataCount = cpu_to_le16(count);
5225 parm_data->list_len = cpu_to_le32(count);
5226 parm_data->list[0].EA_flags = 0;
5227 /* we checked above that name len is less than 255 */
5228 parm_data->list[0].name_len = (__u8)name_len;
5229 /* EA names are always ASCII */
5231 strncpy(parm_data->list[0].name,ea_name,name_len);
5232 parm_data->list[0].name[name_len] = 0;
5233 parm_data->list[0].value_len = cpu_to_le16(ea_value_len);
5234 /* caller ensures that ea_value_len is less than 64K but
5235 we need to ensure that it fits within the smb */
5237 /*BB add length check that it would fit in negotiated SMB buffer size BB */
5238 /* if(ea_value_len > buffer_size - 512 (enough for header)) */
5240 memcpy(parm_data->list[0].name+name_len+1,ea_value,ea_value_len);
5242 pSMB->TotalDataCount = pSMB->DataCount;
5243 pSMB->ParameterCount = cpu_to_le16(params);
5244 pSMB->TotalParameterCount = pSMB->ParameterCount;
5245 pSMB->Reserved4 = 0;
5246 pSMB->hdr.smb_buf_length += byte_count;
5247 pSMB->ByteCount = cpu_to_le16(byte_count);
5248 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5249 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5251 cFYI(1, ("SetPathInfo (EA) returned %d", rc));
5254 cifs_buf_release(pSMB);