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 {LANMAN2_PROT, "\2LANMAN2.1"},
50 #endif /* weak password hashing for legacy clients */
51 {CIFS_PROT, "\2NT LM 0.12"},
52 {POSIX_PROT, "\2POSIX 2"},
60 #ifdef CONFIG_CIFS_WEAK_PW_HASH
61 {LANMAN_PROT, "\2LM1.2X002"},
62 {LANMAN2_PROT, "\2LANMAN2.1"},
63 #endif /* weak password hashing for legacy clients */
64 {CIFS_PROT, "\2NT LM 0.12"},
69 /* define the number of elements in the cifs dialect array */
70 #ifdef CONFIG_CIFS_POSIX
71 #ifdef CONFIG_CIFS_WEAK_PW_HASH
72 #define CIFS_NUM_PROT 4
74 #define CIFS_NUM_PROT 2
75 #endif /* CIFS_WEAK_PW_HASH */
77 #ifdef CONFIG_CIFS_WEAK_PW_HASH
78 #define CIFS_NUM_PROT 3
80 #define CIFS_NUM_PROT 1
81 #endif /* CONFIG_CIFS_WEAK_PW_HASH */
82 #endif /* CIFS_POSIX */
85 /* Mark as invalid, all open files on tree connections since they
86 were closed when session to server was lost */
87 static void mark_open_files_invalid(struct cifsTconInfo * pTcon)
89 struct cifsFileInfo *open_file = NULL;
90 struct list_head * tmp;
91 struct list_head * tmp1;
93 /* list all files open on tree connection and mark them invalid */
94 write_lock(&GlobalSMBSeslock);
95 list_for_each_safe(tmp, tmp1, &pTcon->openFileList) {
96 open_file = list_entry(tmp,struct cifsFileInfo, tlist);
98 open_file->invalidHandle = TRUE;
101 write_unlock(&GlobalSMBSeslock);
102 /* BB Add call to invalidate_inodes(sb) for all superblocks mounted
106 /* If the return code is zero, this function must fill in request_buf pointer */
108 small_smb_init(int smb_command, int wct, struct cifsTconInfo *tcon,
109 void **request_buf /* returned */)
113 /* SMBs NegProt, SessSetup, uLogoff do not have tcon yet so
114 check for tcp and smb session status done differently
115 for those three - in the calling routine */
117 if(tcon->tidStatus == CifsExiting) {
118 /* only tree disconnect, open, and write,
119 (and ulogoff which does not have tcon)
120 are allowed as we start force umount */
121 if((smb_command != SMB_COM_WRITE_ANDX) &&
122 (smb_command != SMB_COM_OPEN_ANDX) &&
123 (smb_command != SMB_COM_TREE_DISCONNECT)) {
124 cFYI(1,("can not send cmd %d while umounting",
129 if((tcon->ses) && (tcon->ses->status != CifsExiting) &&
130 (tcon->ses->server)){
131 struct nls_table *nls_codepage;
132 /* Give Demultiplex thread up to 10 seconds to
133 reconnect, should be greater than cifs socket
134 timeout which is 7 seconds */
135 while(tcon->ses->server->tcpStatus == CifsNeedReconnect) {
136 wait_event_interruptible_timeout(tcon->ses->server->response_q,
137 (tcon->ses->server->tcpStatus == CifsGood), 10 * HZ);
138 if(tcon->ses->server->tcpStatus == CifsNeedReconnect) {
139 /* on "soft" mounts we wait once */
140 if((tcon->retry == FALSE) ||
141 (tcon->ses->status == CifsExiting)) {
142 cFYI(1,("gave up waiting on reconnect in smb_init"));
144 } /* else "hard" mount - keep retrying
145 until process is killed or server
146 comes back on-line */
147 } else /* TCP session is reestablished now */
152 nls_codepage = load_nls_default();
153 /* need to prevent multiple threads trying to
154 simultaneously reconnect the same SMB session */
155 down(&tcon->ses->sesSem);
156 if(tcon->ses->status == CifsNeedReconnect)
157 rc = cifs_setup_session(0, tcon->ses,
159 if(!rc && (tcon->tidStatus == CifsNeedReconnect)) {
160 mark_open_files_invalid(tcon);
161 rc = CIFSTCon(0, tcon->ses, tcon->treeName, tcon
163 up(&tcon->ses->sesSem);
164 /* BB FIXME add code to check if wsize needs
165 update due to negotiated smb buffer size
168 atomic_inc(&tconInfoReconnectCount);
170 cFYI(1, ("reconnect tcon rc = %d", rc));
171 /* Removed call to reopen open files here -
172 it is safer (and faster) to reopen files
173 one at a time as needed in read and write */
175 /* Check if handle based operation so we
176 know whether we can continue or not without
177 returning to caller to reset file handle */
178 switch(smb_command) {
179 case SMB_COM_READ_ANDX:
180 case SMB_COM_WRITE_ANDX:
182 case SMB_COM_FIND_CLOSE2:
183 case SMB_COM_LOCKING_ANDX: {
184 unload_nls(nls_codepage);
189 up(&tcon->ses->sesSem);
191 unload_nls(nls_codepage);
200 *request_buf = cifs_small_buf_get();
201 if (*request_buf == NULL) {
202 /* BB should we add a retry in here if not a writepage? */
206 header_assemble((struct smb_hdr *) *request_buf, smb_command, tcon,wct);
209 cifs_stats_inc(&tcon->num_smbs_sent);
215 small_smb_init_no_tc(const int smb_command, const int wct,
216 struct cifsSesInfo *ses, void **request_buf)
219 struct smb_hdr * buffer;
221 rc = small_smb_init(smb_command, wct, NULL, request_buf);
225 buffer = (struct smb_hdr *)*request_buf;
226 buffer->Mid = GetNextMid(ses->server);
227 if (ses->capabilities & CAP_UNICODE)
228 buffer->Flags2 |= SMBFLG2_UNICODE;
229 if (ses->capabilities & CAP_STATUS32)
230 buffer->Flags2 |= SMBFLG2_ERR_STATUS;
232 /* uid, tid can stay at zero as set in header assemble */
234 /* BB add support for turning on the signing when
235 this function is used after 1st of session setup requests */
240 /* If the return code is zero, this function must fill in request_buf pointer */
242 smb_init(int smb_command, int wct, struct cifsTconInfo *tcon,
243 void **request_buf /* returned */ ,
244 void **response_buf /* returned */ )
248 /* SMBs NegProt, SessSetup, uLogoff do not have tcon yet so
249 check for tcp and smb session status done differently
250 for those three - in the calling routine */
252 if(tcon->tidStatus == CifsExiting) {
253 /* only tree disconnect, open, and write,
254 (and ulogoff which does not have tcon)
255 are allowed as we start force umount */
256 if((smb_command != SMB_COM_WRITE_ANDX) &&
257 (smb_command != SMB_COM_OPEN_ANDX) &&
258 (smb_command != SMB_COM_TREE_DISCONNECT)) {
259 cFYI(1,("can not send cmd %d while umounting",
265 if((tcon->ses) && (tcon->ses->status != CifsExiting) &&
266 (tcon->ses->server)){
267 struct nls_table *nls_codepage;
268 /* Give Demultiplex thread up to 10 seconds to
269 reconnect, should be greater than cifs socket
270 timeout which is 7 seconds */
271 while(tcon->ses->server->tcpStatus == CifsNeedReconnect) {
272 wait_event_interruptible_timeout(tcon->ses->server->response_q,
273 (tcon->ses->server->tcpStatus == CifsGood), 10 * HZ);
274 if(tcon->ses->server->tcpStatus ==
276 /* on "soft" mounts we wait once */
277 if((tcon->retry == FALSE) ||
278 (tcon->ses->status == CifsExiting)) {
279 cFYI(1,("gave up waiting on reconnect in smb_init"));
281 } /* else "hard" mount - keep retrying
282 until process is killed or server
284 } else /* TCP session is reestablished now */
289 nls_codepage = load_nls_default();
290 /* need to prevent multiple threads trying to
291 simultaneously reconnect the same SMB session */
292 down(&tcon->ses->sesSem);
293 if(tcon->ses->status == CifsNeedReconnect)
294 rc = cifs_setup_session(0, tcon->ses,
296 if(!rc && (tcon->tidStatus == CifsNeedReconnect)) {
297 mark_open_files_invalid(tcon);
298 rc = CIFSTCon(0, tcon->ses, tcon->treeName,
300 up(&tcon->ses->sesSem);
301 /* BB FIXME add code to check if wsize needs
302 update due to negotiated smb buffer size
305 atomic_inc(&tconInfoReconnectCount);
307 cFYI(1, ("reconnect tcon rc = %d", rc));
308 /* Removed call to reopen open files here -
309 it is safer (and faster) to reopen files
310 one at a time as needed in read and write */
312 /* Check if handle based operation so we
313 know whether we can continue or not without
314 returning to caller to reset file handle */
315 switch(smb_command) {
316 case SMB_COM_READ_ANDX:
317 case SMB_COM_WRITE_ANDX:
319 case SMB_COM_FIND_CLOSE2:
320 case SMB_COM_LOCKING_ANDX: {
321 unload_nls(nls_codepage);
326 up(&tcon->ses->sesSem);
328 unload_nls(nls_codepage);
337 *request_buf = cifs_buf_get();
338 if (*request_buf == NULL) {
339 /* BB should we add a retry in here if not a writepage? */
342 /* Although the original thought was we needed the response buf for */
343 /* potential retries of smb operations it turns out we can determine */
344 /* from the mid flags when the request buffer can be resent without */
345 /* having to use a second distinct buffer for the response */
347 *response_buf = *request_buf;
349 header_assemble((struct smb_hdr *) *request_buf, smb_command, tcon,
353 cifs_stats_inc(&tcon->num_smbs_sent);
358 static int validate_t2(struct smb_t2_rsp * pSMB)
364 /* check for plausible wct, bcc and t2 data and parm sizes */
365 /* check for parm and data offset going beyond end of smb */
366 if(pSMB->hdr.WordCount >= 10) {
367 if((le16_to_cpu(pSMB->t2_rsp.ParameterOffset) <= 1024) &&
368 (le16_to_cpu(pSMB->t2_rsp.DataOffset) <= 1024)) {
369 /* check that bcc is at least as big as parms + data */
370 /* check that bcc is less than negotiated smb buffer */
371 total_size = le16_to_cpu(pSMB->t2_rsp.ParameterCount);
372 if(total_size < 512) {
373 total_size+=le16_to_cpu(pSMB->t2_rsp.DataCount);
374 /* BCC le converted in SendReceive */
375 pBCC = (pSMB->hdr.WordCount * 2) +
376 sizeof(struct smb_hdr) +
378 if((total_size <= (*(u16 *)pBCC)) &&
380 CIFSMaxBufSize+MAX_CIFS_HDR_SIZE)) {
387 cifs_dump_mem("Invalid transact2 SMB: ",(char *)pSMB,
388 sizeof(struct smb_t2_rsp) + 16);
392 CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses)
395 NEGOTIATE_RSP *pSMBr;
399 struct TCP_Server_Info * server;
401 unsigned int secFlags;
404 server = ses->server;
409 rc = smb_init(SMB_COM_NEGOTIATE, 0, NULL /* no tcon yet */ ,
410 (void **) &pSMB, (void **) &pSMBr);
414 /* if any of auth flags (ie not sign or seal) are overriden use them */
415 if(ses->overrideSecFlg & (~(CIFSSEC_MUST_SIGN | CIFSSEC_MUST_SEAL)))
416 secFlags = ses->overrideSecFlg;
417 else /* if override flags set only sign/seal OR them with global auth */
418 secFlags = extended_security | ses->overrideSecFlg;
420 cFYI(1,("secFlags 0x%x",secFlags));
422 pSMB->hdr.Mid = GetNextMid(server);
423 pSMB->hdr.Flags2 |= SMBFLG2_UNICODE;
424 if((secFlags & CIFSSEC_MUST_KRB5) == CIFSSEC_MUST_KRB5)
425 pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC;
428 for(i=0;i<CIFS_NUM_PROT;i++) {
429 strncpy(pSMB->DialectsArray+count, protocols[i].name, 16);
430 count += strlen(protocols[i].name) + 1;
431 /* null at end of source and target buffers anyway */
433 pSMB->hdr.smb_buf_length += count;
434 pSMB->ByteCount = cpu_to_le16(count);
436 rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB,
437 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
441 cFYI(1,("Dialect: %d", pSMBr->DialectIndex));
442 /* Check wct = 1 error case */
443 if((pSMBr->hdr.WordCount < 13) || (pSMBr->DialectIndex == BAD_PROT)) {
444 /* core returns wct = 1, but we do not ask for core - otherwise
445 small wct just comes when dialect index is -1 indicating we
446 could not negotiate a common dialect */
449 #ifdef CONFIG_CIFS_WEAK_PW_HASH
450 } else if((pSMBr->hdr.WordCount == 13)
451 && ((pSMBr->DialectIndex == LANMAN_PROT)
452 || (pSMBr->DialectIndex == LANMAN2_PROT))) {
454 struct lanman_neg_rsp * rsp = (struct lanman_neg_rsp *)pSMBr;
456 if((secFlags & CIFSSEC_MAY_LANMAN) ||
457 (secFlags & CIFSSEC_MAY_PLNTXT))
458 server->secType = LANMAN;
460 cERROR(1, ("mount failed weak security disabled"
461 " in /proc/fs/cifs/SecurityFlags"));
465 server->secMode = (__u8)le16_to_cpu(rsp->SecurityMode);
466 server->maxReq = le16_to_cpu(rsp->MaxMpxCount);
467 server->maxBuf = min((__u32)le16_to_cpu(rsp->MaxBufSize),
468 (__u32)CIFSMaxBufSize + MAX_CIFS_HDR_SIZE);
469 GETU32(server->sessid) = le32_to_cpu(rsp->SessionKey);
470 /* even though we do not use raw we might as well set this
471 accurately, in case we ever find a need for it */
472 if((le16_to_cpu(rsp->RawMode) & RAW_ENABLE) == RAW_ENABLE) {
473 server->maxRw = 0xFF00;
474 server->capabilities = CAP_MPX_MODE | CAP_RAW_MODE;
476 server->maxRw = 0;/* we do not need to use raw anyway */
477 server->capabilities = CAP_MPX_MODE;
479 tmp = (__s16)le16_to_cpu(rsp->ServerTimeZone);
481 /* OS/2 often does not set timezone therefore
482 * we must use server time to calc time zone.
483 * Could deviate slightly from the right zone.
484 * Smallest defined timezone difference is 15 minutes
485 * (i.e. Nepal). Rounding up/down is done to match
488 int val, seconds, remain, result;
489 struct timespec ts, utc;
491 ts = cnvrtDosUnixTm(le16_to_cpu(rsp->SrvTime.Date),
492 le16_to_cpu(rsp->SrvTime.Time));
493 cFYI(1,("SrvTime: %d sec since 1970 (utc: %d) diff: %d",
494 (int)ts.tv_sec, (int)utc.tv_sec,
495 (int)(utc.tv_sec - ts.tv_sec)));
496 val = (int)(utc.tv_sec - ts.tv_sec);
497 seconds = val < 0 ? -val : val;
498 result = (seconds / MIN_TZ_ADJ) * MIN_TZ_ADJ;
499 remain = seconds % MIN_TZ_ADJ;
500 if(remain >= (MIN_TZ_ADJ / 2))
501 result += MIN_TZ_ADJ;
504 server->timeAdj = result;
506 server->timeAdj = (int)tmp;
507 server->timeAdj *= 60; /* also in seconds */
509 cFYI(1,("server->timeAdj: %d seconds", server->timeAdj));
512 /* BB get server time for time conversions and add
513 code to use it and timezone since this is not UTC */
515 if (rsp->EncryptionKeyLength ==
516 cpu_to_le16(CIFS_CRYPTO_KEY_SIZE)) {
517 memcpy(server->cryptKey, rsp->EncryptionKey,
518 CIFS_CRYPTO_KEY_SIZE);
519 } else if (server->secMode & SECMODE_PW_ENCRYPT) {
520 rc = -EIO; /* need cryptkey unless plain text */
524 cFYI(1,("LANMAN negotiated"));
525 /* we will not end up setting signing flags - as no signing
526 was in LANMAN and server did not return the flags on */
528 #else /* weak security disabled */
529 } else if(pSMBr->hdr.WordCount == 13) {
530 cERROR(1,("mount failed, cifs module not built "
531 "with CIFS_WEAK_PW_HASH support"));
533 #endif /* WEAK_PW_HASH */
535 } else if(pSMBr->hdr.WordCount != 17) {
540 /* else wct == 17 NTLM */
541 server->secMode = pSMBr->SecurityMode;
542 if((server->secMode & SECMODE_USER) == 0)
543 cFYI(1,("share mode security"));
545 if((server->secMode & SECMODE_PW_ENCRYPT) == 0)
546 #ifdef CONFIG_CIFS_WEAK_PW_HASH
547 if ((secFlags & CIFSSEC_MAY_PLNTXT) == 0)
548 #endif /* CIFS_WEAK_PW_HASH */
549 cERROR(1,("Server requests plain text password"
550 " but client support disabled"));
552 if((secFlags & CIFSSEC_MUST_NTLMV2) == CIFSSEC_MUST_NTLMV2)
553 server->secType = NTLMv2;
554 else if(secFlags & CIFSSEC_MAY_NTLM)
555 server->secType = NTLM;
556 else if(secFlags & CIFSSEC_MAY_NTLMV2)
557 server->secType = NTLMv2;
558 /* else krb5 ... any others ... */
560 /* one byte, so no need to convert this or EncryptionKeyLen from
562 server->maxReq = le16_to_cpu(pSMBr->MaxMpxCount);
563 /* probably no need to store and check maxvcs */
564 server->maxBuf = min(le32_to_cpu(pSMBr->MaxBufferSize),
565 (__u32) CIFSMaxBufSize + MAX_CIFS_HDR_SIZE);
566 server->maxRw = le32_to_cpu(pSMBr->MaxRawSize);
567 cFYI(0, ("Max buf = %d", ses->server->maxBuf));
568 GETU32(ses->server->sessid) = le32_to_cpu(pSMBr->SessionKey);
569 server->capabilities = le32_to_cpu(pSMBr->Capabilities);
570 server->timeAdj = (int)(__s16)le16_to_cpu(pSMBr->ServerTimeZone);
571 server->timeAdj *= 60;
572 if (pSMBr->EncryptionKeyLength == CIFS_CRYPTO_KEY_SIZE) {
573 memcpy(server->cryptKey, pSMBr->u.EncryptionKey,
574 CIFS_CRYPTO_KEY_SIZE);
575 } else if ((pSMBr->hdr.Flags2 & SMBFLG2_EXT_SEC)
576 && (pSMBr->EncryptionKeyLength == 0)) {
577 /* decode security blob */
578 } else if (server->secMode & SECMODE_PW_ENCRYPT) {
579 rc = -EIO; /* no crypt key only if plain text pwd */
583 /* BB might be helpful to save off the domain of server here */
585 if ((pSMBr->hdr.Flags2 & SMBFLG2_EXT_SEC) &&
586 (server->capabilities & CAP_EXTENDED_SECURITY)) {
587 count = pSMBr->ByteCount;
590 else if (count == 16) {
591 server->secType = RawNTLMSSP;
592 if (server->socketUseCount.counter > 1) {
593 if (memcmp(server->server_GUID,
594 pSMBr->u.extended_response.
596 cFYI(1, ("server UID changed"));
597 memcpy(server->server_GUID,
598 pSMBr->u.extended_response.GUID,
602 memcpy(server->server_GUID,
603 pSMBr->u.extended_response.GUID, 16);
605 rc = decode_negTokenInit(pSMBr->u.extended_response.
610 /* BB Need to fill struct for sessetup here */
617 server->capabilities &= ~CAP_EXTENDED_SECURITY;
619 #ifdef CONFIG_CIFS_WEAK_PW_HASH
622 if(sign_CIFS_PDUs == FALSE) {
623 if(server->secMode & SECMODE_SIGN_REQUIRED)
624 cERROR(1,("Server requires "
625 "/proc/fs/cifs/PacketSigningEnabled to be on"));
627 ~(SECMODE_SIGN_ENABLED | SECMODE_SIGN_REQUIRED);
628 } else if(sign_CIFS_PDUs == 1) {
629 if((server->secMode & SECMODE_SIGN_REQUIRED) == 0)
631 ~(SECMODE_SIGN_ENABLED | SECMODE_SIGN_REQUIRED);
632 } else if(sign_CIFS_PDUs == 2) {
633 if((server->secMode &
634 (SECMODE_SIGN_ENABLED | SECMODE_SIGN_REQUIRED)) == 0) {
635 cERROR(1,("signing required but server lacks support"));
639 cifs_buf_release(pSMB);
641 cFYI(1,("negprot rc %d",rc));
646 CIFSSMBTDis(const int xid, struct cifsTconInfo *tcon)
648 struct smb_hdr *smb_buffer;
649 struct smb_hdr *smb_buffer_response; /* BB removeme BB */
653 cFYI(1, ("In tree disconnect"));
655 * If last user of the connection and
656 * connection alive - disconnect it
657 * If this is the last connection on the server session disconnect it
658 * (and inside session disconnect we should check if tcp socket needs
659 * to be freed and kernel thread woken up).
662 down(&tcon->tconSem);
666 atomic_dec(&tcon->useCount);
667 if (atomic_read(&tcon->useCount) > 0) {
672 /* No need to return error on this operation if tid invalidated and
673 closed on server already e.g. due to tcp session crashing */
674 if(tcon->tidStatus == CifsNeedReconnect) {
679 if((tcon->ses == NULL) || (tcon->ses->server == NULL)) {
683 rc = small_smb_init(SMB_COM_TREE_DISCONNECT, 0, tcon,
684 (void **)&smb_buffer);
689 smb_buffer_response = smb_buffer; /* BB removeme BB */
691 rc = SendReceive(xid, tcon->ses, smb_buffer, smb_buffer_response,
694 cFYI(1, ("Tree disconnect failed %d", rc));
697 cifs_small_buf_release(smb_buffer);
700 /* No need to return error on this operation if tid invalidated and
701 closed on server already e.g. due to tcp session crashing */
709 CIFSSMBLogoff(const int xid, struct cifsSesInfo *ses)
711 struct smb_hdr *smb_buffer_response;
712 LOGOFF_ANDX_REQ *pSMB;
716 cFYI(1, ("In SMBLogoff for session disconnect"));
722 atomic_dec(&ses->inUse);
723 if (atomic_read(&ses->inUse) > 0) {
727 rc = small_smb_init(SMB_COM_LOGOFF_ANDX, 2, NULL, (void **)&pSMB);
733 smb_buffer_response = (struct smb_hdr *)pSMB; /* BB removeme BB */
736 pSMB->hdr.Mid = GetNextMid(ses->server);
738 if(ses->server->secMode &
739 (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
740 pSMB->hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
743 pSMB->hdr.Uid = ses->Suid;
745 pSMB->AndXCommand = 0xFF;
746 rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB,
747 smb_buffer_response, &length, 0);
749 atomic_dec(&ses->server->socketUseCount);
750 if (atomic_read(&ses->server->socketUseCount) == 0) {
751 spin_lock(&GlobalMid_Lock);
752 ses->server->tcpStatus = CifsExiting;
753 spin_unlock(&GlobalMid_Lock);
758 cifs_small_buf_release(pSMB);
760 /* if session dead then we do not need to do ulogoff,
761 since server closed smb session, no sense reporting
769 CIFSSMBDelFile(const int xid, struct cifsTconInfo *tcon, const char *fileName,
770 const struct nls_table *nls_codepage, int remap)
772 DELETE_FILE_REQ *pSMB = NULL;
773 DELETE_FILE_RSP *pSMBr = NULL;
779 rc = smb_init(SMB_COM_DELETE, 1, tcon, (void **) &pSMB,
784 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
786 cifsConvertToUCS((__le16 *) pSMB->fileName, fileName,
787 PATH_MAX, nls_codepage, remap);
788 name_len++; /* trailing null */
790 } else { /* BB improve check for buffer overruns BB */
791 name_len = strnlen(fileName, PATH_MAX);
792 name_len++; /* trailing null */
793 strncpy(pSMB->fileName, fileName, name_len);
795 pSMB->SearchAttributes =
796 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM);
797 pSMB->BufferFormat = 0x04;
798 pSMB->hdr.smb_buf_length += name_len + 1;
799 pSMB->ByteCount = cpu_to_le16(name_len + 1);
800 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
801 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
802 cifs_stats_inc(&tcon->num_deletes);
804 cFYI(1, ("Error in RMFile = %d", rc));
807 cifs_buf_release(pSMB);
815 CIFSSMBRmDir(const int xid, struct cifsTconInfo *tcon, const char *dirName,
816 const struct nls_table *nls_codepage, int remap)
818 DELETE_DIRECTORY_REQ *pSMB = NULL;
819 DELETE_DIRECTORY_RSP *pSMBr = NULL;
824 cFYI(1, ("In CIFSSMBRmDir"));
826 rc = smb_init(SMB_COM_DELETE_DIRECTORY, 0, tcon, (void **) &pSMB,
831 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
832 name_len = cifsConvertToUCS((__le16 *) pSMB->DirName, dirName,
833 PATH_MAX, nls_codepage, remap);
834 name_len++; /* trailing null */
836 } else { /* BB improve check for buffer overruns BB */
837 name_len = strnlen(dirName, PATH_MAX);
838 name_len++; /* trailing null */
839 strncpy(pSMB->DirName, dirName, name_len);
842 pSMB->BufferFormat = 0x04;
843 pSMB->hdr.smb_buf_length += name_len + 1;
844 pSMB->ByteCount = cpu_to_le16(name_len + 1);
845 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
846 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
847 cifs_stats_inc(&tcon->num_rmdirs);
849 cFYI(1, ("Error in RMDir = %d", rc));
852 cifs_buf_release(pSMB);
859 CIFSSMBMkDir(const int xid, struct cifsTconInfo *tcon,
860 const char *name, const struct nls_table *nls_codepage, int remap)
863 CREATE_DIRECTORY_REQ *pSMB = NULL;
864 CREATE_DIRECTORY_RSP *pSMBr = NULL;
868 cFYI(1, ("In CIFSSMBMkDir"));
870 rc = smb_init(SMB_COM_CREATE_DIRECTORY, 0, tcon, (void **) &pSMB,
875 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
876 name_len = cifsConvertToUCS((__le16 *) pSMB->DirName, name,
877 PATH_MAX, nls_codepage, remap);
878 name_len++; /* trailing null */
880 } else { /* BB improve check for buffer overruns BB */
881 name_len = strnlen(name, PATH_MAX);
882 name_len++; /* trailing null */
883 strncpy(pSMB->DirName, name, name_len);
886 pSMB->BufferFormat = 0x04;
887 pSMB->hdr.smb_buf_length += name_len + 1;
888 pSMB->ByteCount = cpu_to_le16(name_len + 1);
889 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
890 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
891 cifs_stats_inc(&tcon->num_mkdirs);
893 cFYI(1, ("Error in Mkdir = %d", rc));
896 cifs_buf_release(pSMB);
902 static __u16 convert_disposition(int disposition)
906 switch (disposition) {
908 ofun = SMBOPEN_OCREATE | SMBOPEN_OTRUNC;
911 ofun = SMBOPEN_OAPPEND;
914 ofun = SMBOPEN_OCREATE;
917 ofun = SMBOPEN_OCREATE | SMBOPEN_OAPPEND;
920 ofun = SMBOPEN_OTRUNC;
922 case FILE_OVERWRITE_IF:
923 ofun = SMBOPEN_OCREATE | SMBOPEN_OTRUNC;
926 cFYI(1,("unknown disposition %d",disposition));
927 ofun = SMBOPEN_OAPPEND; /* regular open */
933 SMBLegacyOpen(const int xid, struct cifsTconInfo *tcon,
934 const char *fileName, const int openDisposition,
935 const int access_flags, const int create_options, __u16 * netfid,
936 int *pOplock, FILE_ALL_INFO * pfile_info,
937 const struct nls_table *nls_codepage, int remap)
940 OPENX_REQ *pSMB = NULL;
941 OPENX_RSP *pSMBr = NULL;
947 rc = smb_init(SMB_COM_OPEN_ANDX, 15, tcon, (void **) &pSMB,
952 pSMB->AndXCommand = 0xFF; /* none */
954 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
955 count = 1; /* account for one byte pad to word boundary */
957 cifsConvertToUCS((__le16 *) (pSMB->fileName + 1),
958 fileName, PATH_MAX, nls_codepage, remap);
959 name_len++; /* trailing null */
961 } else { /* BB improve check for buffer overruns BB */
962 count = 0; /* no pad */
963 name_len = strnlen(fileName, PATH_MAX);
964 name_len++; /* trailing null */
965 strncpy(pSMB->fileName, fileName, name_len);
967 if (*pOplock & REQ_OPLOCK)
968 pSMB->OpenFlags = cpu_to_le16(REQ_OPLOCK);
969 else if (*pOplock & REQ_BATCHOPLOCK) {
970 pSMB->OpenFlags = cpu_to_le16(REQ_BATCHOPLOCK);
972 pSMB->OpenFlags |= cpu_to_le16(REQ_MORE_INFO);
973 /* BB fixme add conversion for access_flags to bits 0 - 2 of mode */
979 pSMB->Mode = cpu_to_le16(2);
980 pSMB->Mode |= cpu_to_le16(0x40); /* deny none */
981 /* set file as system file if special file such
982 as fifo and server expecting SFU style and
983 no Unix extensions */
985 if(create_options & CREATE_OPTION_SPECIAL)
986 pSMB->FileAttributes = cpu_to_le16(ATTR_SYSTEM);
988 pSMB->FileAttributes = cpu_to_le16(0/*ATTR_NORMAL*/); /* BB FIXME */
990 /* if ((omode & S_IWUGO) == 0)
991 pSMB->FileAttributes |= cpu_to_le32(ATTR_READONLY);*/
992 /* Above line causes problems due to vfs splitting create into two
993 pieces - need to set mode after file created not while it is
997 /* pSMB->CreateOptions = cpu_to_le32(create_options & CREATE_OPTIONS_MASK); */
998 /* BB FIXME END BB */
1000 pSMB->Sattr = cpu_to_le16(ATTR_HIDDEN | ATTR_SYSTEM | ATTR_DIRECTORY);
1001 pSMB->OpenFunction = cpu_to_le16(convert_disposition(openDisposition));
1003 pSMB->hdr.smb_buf_length += count;
1005 pSMB->ByteCount = cpu_to_le16(count);
1006 /* long_op set to 1 to allow for oplock break timeouts */
1007 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1008 (struct smb_hdr *) pSMBr, &bytes_returned, 1);
1009 cifs_stats_inc(&tcon->num_opens);
1011 cFYI(1, ("Error in Open = %d", rc));
1013 /* BB verify if wct == 15 */
1015 /* *pOplock = pSMBr->OplockLevel; */ /* BB take from action field BB */
1017 *netfid = pSMBr->Fid; /* cifs fid stays in le */
1018 /* Let caller know file was created so we can set the mode. */
1019 /* Do we care about the CreateAction in any other cases? */
1021 /* if(cpu_to_le32(FILE_CREATE) == pSMBr->CreateAction)
1022 *pOplock |= CIFS_CREATE_ACTION; */
1026 pfile_info->CreationTime = 0; /* BB convert CreateTime*/
1027 pfile_info->LastAccessTime = 0; /* BB fixme */
1028 pfile_info->LastWriteTime = 0; /* BB fixme */
1029 pfile_info->ChangeTime = 0; /* BB fixme */
1030 pfile_info->Attributes =
1031 cpu_to_le32(le16_to_cpu(pSMBr->FileAttributes));
1032 /* the file_info buf is endian converted by caller */
1033 pfile_info->AllocationSize =
1034 cpu_to_le64(le32_to_cpu(pSMBr->EndOfFile));
1035 pfile_info->EndOfFile = pfile_info->AllocationSize;
1036 pfile_info->NumberOfLinks = cpu_to_le32(1);
1040 cifs_buf_release(pSMB);
1047 CIFSSMBOpen(const int xid, struct cifsTconInfo *tcon,
1048 const char *fileName, const int openDisposition,
1049 const int access_flags, const int create_options, __u16 * netfid,
1050 int *pOplock, FILE_ALL_INFO * pfile_info,
1051 const struct nls_table *nls_codepage, int remap)
1054 OPEN_REQ *pSMB = NULL;
1055 OPEN_RSP *pSMBr = NULL;
1061 rc = smb_init(SMB_COM_NT_CREATE_ANDX, 24, tcon, (void **) &pSMB,
1066 pSMB->AndXCommand = 0xFF; /* none */
1068 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1069 count = 1; /* account for one byte pad to word boundary */
1071 cifsConvertToUCS((__le16 *) (pSMB->fileName + 1),
1072 fileName, PATH_MAX, nls_codepage, remap);
1073 name_len++; /* trailing null */
1075 pSMB->NameLength = cpu_to_le16(name_len);
1076 } else { /* BB improve check for buffer overruns BB */
1077 count = 0; /* no pad */
1078 name_len = strnlen(fileName, PATH_MAX);
1079 name_len++; /* trailing null */
1080 pSMB->NameLength = cpu_to_le16(name_len);
1081 strncpy(pSMB->fileName, fileName, name_len);
1083 if (*pOplock & REQ_OPLOCK)
1084 pSMB->OpenFlags = cpu_to_le32(REQ_OPLOCK);
1085 else if (*pOplock & REQ_BATCHOPLOCK) {
1086 pSMB->OpenFlags = cpu_to_le32(REQ_BATCHOPLOCK);
1088 pSMB->DesiredAccess = cpu_to_le32(access_flags);
1089 pSMB->AllocationSize = 0;
1090 /* set file as system file if special file such
1091 as fifo and server expecting SFU style and
1092 no Unix extensions */
1093 if(create_options & CREATE_OPTION_SPECIAL)
1094 pSMB->FileAttributes = cpu_to_le32(ATTR_SYSTEM);
1096 pSMB->FileAttributes = cpu_to_le32(ATTR_NORMAL);
1097 /* XP does not handle ATTR_POSIX_SEMANTICS */
1098 /* but it helps speed up case sensitive checks for other
1099 servers such as Samba */
1100 if (tcon->ses->capabilities & CAP_UNIX)
1101 pSMB->FileAttributes |= cpu_to_le32(ATTR_POSIX_SEMANTICS);
1103 /* if ((omode & S_IWUGO) == 0)
1104 pSMB->FileAttributes |= cpu_to_le32(ATTR_READONLY);*/
1105 /* Above line causes problems due to vfs splitting create into two
1106 pieces - need to set mode after file created not while it is
1108 pSMB->ShareAccess = cpu_to_le32(FILE_SHARE_ALL);
1109 pSMB->CreateDisposition = cpu_to_le32(openDisposition);
1110 pSMB->CreateOptions = cpu_to_le32(create_options & CREATE_OPTIONS_MASK);
1111 /* BB Expirement with various impersonation levels and verify */
1112 pSMB->ImpersonationLevel = cpu_to_le32(SECURITY_IMPERSONATION);
1113 pSMB->SecurityFlags =
1114 SECURITY_CONTEXT_TRACKING | SECURITY_EFFECTIVE_ONLY;
1117 pSMB->hdr.smb_buf_length += count;
1119 pSMB->ByteCount = cpu_to_le16(count);
1120 /* long_op set to 1 to allow for oplock break timeouts */
1121 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1122 (struct smb_hdr *) pSMBr, &bytes_returned, 1);
1123 cifs_stats_inc(&tcon->num_opens);
1125 cFYI(1, ("Error in Open = %d", rc));
1127 *pOplock = pSMBr->OplockLevel; /* 1 byte no need to le_to_cpu */
1128 *netfid = pSMBr->Fid; /* cifs fid stays in le */
1129 /* Let caller know file was created so we can set the mode. */
1130 /* Do we care about the CreateAction in any other cases? */
1131 if(cpu_to_le32(FILE_CREATE) == pSMBr->CreateAction)
1132 *pOplock |= CIFS_CREATE_ACTION;
1134 memcpy((char *)pfile_info,(char *)&pSMBr->CreationTime,
1135 36 /* CreationTime to Attributes */);
1136 /* the file_info buf is endian converted by caller */
1137 pfile_info->AllocationSize = pSMBr->AllocationSize;
1138 pfile_info->EndOfFile = pSMBr->EndOfFile;
1139 pfile_info->NumberOfLinks = cpu_to_le32(1);
1143 cifs_buf_release(pSMB);
1150 CIFSSMBRead(const int xid, struct cifsTconInfo *tcon,
1151 const int netfid, const unsigned int count,
1152 const __u64 lseek, unsigned int *nbytes, char **buf,
1156 READ_REQ *pSMB = NULL;
1157 READ_RSP *pSMBr = NULL;
1158 char *pReadData = NULL;
1160 int resp_buf_type = 0;
1163 cFYI(1,("Reading %d bytes on fid %d",count,netfid));
1164 if(tcon->ses->capabilities & CAP_LARGE_FILES)
1167 wct = 10; /* old style read */
1170 rc = small_smb_init(SMB_COM_READ_ANDX, wct, tcon, (void **) &pSMB);
1174 /* tcon and ses pointer are checked in smb_init */
1175 if (tcon->ses->server == NULL)
1176 return -ECONNABORTED;
1178 pSMB->AndXCommand = 0xFF; /* none */
1180 pSMB->OffsetLow = cpu_to_le32(lseek & 0xFFFFFFFF);
1182 pSMB->OffsetHigh = cpu_to_le32(lseek >> 32);
1183 else if((lseek >> 32) > 0) /* can not handle this big offset for old */
1186 pSMB->Remaining = 0;
1187 pSMB->MaxCount = cpu_to_le16(count & 0xFFFF);
1188 pSMB->MaxCountHigh = cpu_to_le32(count >> 16);
1190 pSMB->ByteCount = 0; /* no need to do le conversion since 0 */
1192 /* old style read */
1193 struct smb_com_readx_req * pSMBW =
1194 (struct smb_com_readx_req *)pSMB;
1195 pSMBW->ByteCount = 0;
1198 iov[0].iov_base = (char *)pSMB;
1199 iov[0].iov_len = pSMB->hdr.smb_buf_length + 4;
1200 rc = SendReceive2(xid, tcon->ses, iov,
1203 cifs_stats_inc(&tcon->num_reads);
1204 pSMBr = (READ_RSP *)iov[0].iov_base;
1206 cERROR(1, ("Send error in read = %d", rc));
1208 int data_length = le16_to_cpu(pSMBr->DataLengthHigh);
1209 data_length = data_length << 16;
1210 data_length += le16_to_cpu(pSMBr->DataLength);
1211 *nbytes = data_length;
1213 /*check that DataLength would not go beyond end of SMB */
1214 if ((data_length > CIFSMaxBufSize)
1215 || (data_length > count)) {
1216 cFYI(1,("bad length %d for count %d",data_length,count));
1220 pReadData = (char *) (&pSMBr->hdr.Protocol) +
1221 le16_to_cpu(pSMBr->DataOffset);
1222 /* if(rc = copy_to_user(buf, pReadData, data_length)) {
1223 cERROR(1,("Faulting on read rc = %d",rc));
1225 }*/ /* can not use copy_to_user when using page cache*/
1227 memcpy(*buf,pReadData,data_length);
1231 /* cifs_small_buf_release(pSMB); */ /* Freed earlier now in SendReceive2 */
1233 if(resp_buf_type == CIFS_SMALL_BUFFER)
1234 cifs_small_buf_release(iov[0].iov_base);
1235 else if(resp_buf_type == CIFS_LARGE_BUFFER)
1236 cifs_buf_release(iov[0].iov_base);
1237 } else if(resp_buf_type != CIFS_NO_BUFFER) {
1238 /* return buffer to caller to free */
1239 *buf = iov[0].iov_base;
1240 if(resp_buf_type == CIFS_SMALL_BUFFER)
1241 *pbuf_type = CIFS_SMALL_BUFFER;
1242 else if(resp_buf_type == CIFS_LARGE_BUFFER)
1243 *pbuf_type = CIFS_LARGE_BUFFER;
1244 } /* else no valid buffer on return - leave as null */
1246 /* Note: On -EAGAIN error only caller can retry on handle based calls
1247 since file handle passed in no longer valid */
1253 CIFSSMBWrite(const int xid, struct cifsTconInfo *tcon,
1254 const int netfid, const unsigned int count,
1255 const __u64 offset, unsigned int *nbytes, const char *buf,
1256 const char __user * ubuf, const int long_op)
1259 WRITE_REQ *pSMB = NULL;
1260 WRITE_RSP *pSMBr = NULL;
1261 int bytes_returned, wct;
1265 /* cFYI(1,("write at %lld %d bytes",offset,count));*/
1266 if(tcon->ses == NULL)
1267 return -ECONNABORTED;
1269 if(tcon->ses->capabilities & CAP_LARGE_FILES)
1274 rc = smb_init(SMB_COM_WRITE_ANDX, wct, tcon, (void **) &pSMB,
1278 /* tcon and ses pointer are checked in smb_init */
1279 if (tcon->ses->server == NULL)
1280 return -ECONNABORTED;
1282 pSMB->AndXCommand = 0xFF; /* none */
1284 pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF);
1286 pSMB->OffsetHigh = cpu_to_le32(offset >> 32);
1287 else if((offset >> 32) > 0) /* can not handle this big offset for old */
1290 pSMB->Reserved = 0xFFFFFFFF;
1291 pSMB->WriteMode = 0;
1292 pSMB->Remaining = 0;
1294 /* Can increase buffer size if buffer is big enough in some cases - ie we
1295 can send more if LARGE_WRITE_X capability returned by the server and if
1296 our buffer is big enough or if we convert to iovecs on socket writes
1297 and eliminate the copy to the CIFS buffer */
1298 if(tcon->ses->capabilities & CAP_LARGE_WRITE_X) {
1299 bytes_sent = min_t(const unsigned int, CIFSMaxBufSize, count);
1301 bytes_sent = (tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE)
1305 if (bytes_sent > count)
1308 cpu_to_le16(offsetof(struct smb_com_write_req,Data) - 4);
1310 memcpy(pSMB->Data,buf,bytes_sent);
1312 if(copy_from_user(pSMB->Data,ubuf,bytes_sent)) {
1313 cifs_buf_release(pSMB);
1316 } else if (count != 0) {
1318 cifs_buf_release(pSMB);
1320 } /* else setting file size with write of zero bytes */
1322 byte_count = bytes_sent + 1; /* pad */
1323 else /* wct == 12 */ {
1324 byte_count = bytes_sent + 5; /* bigger pad, smaller smb hdr */
1326 pSMB->DataLengthLow = cpu_to_le16(bytes_sent & 0xFFFF);
1327 pSMB->DataLengthHigh = cpu_to_le16(bytes_sent >> 16);
1328 pSMB->hdr.smb_buf_length += byte_count;
1331 pSMB->ByteCount = cpu_to_le16(byte_count);
1332 else { /* old style write has byte count 4 bytes earlier so 4 bytes pad */
1333 struct smb_com_writex_req * pSMBW =
1334 (struct smb_com_writex_req *)pSMB;
1335 pSMBW->ByteCount = cpu_to_le16(byte_count);
1338 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1339 (struct smb_hdr *) pSMBr, &bytes_returned, long_op);
1340 cifs_stats_inc(&tcon->num_writes);
1342 cFYI(1, ("Send error in write = %d", rc));
1345 *nbytes = le16_to_cpu(pSMBr->CountHigh);
1346 *nbytes = (*nbytes) << 16;
1347 *nbytes += le16_to_cpu(pSMBr->Count);
1350 cifs_buf_release(pSMB);
1352 /* Note: On -EAGAIN error only caller can retry on handle based calls
1353 since file handle passed in no longer valid */
1359 CIFSSMBWrite2(const int xid, struct cifsTconInfo *tcon,
1360 const int netfid, const unsigned int count,
1361 const __u64 offset, unsigned int *nbytes, struct kvec *iov,
1362 int n_vec, const int long_op)
1365 WRITE_REQ *pSMB = NULL;
1368 int resp_buf_type = 0;
1370 cFYI(1,("write2 at %lld %d bytes", (long long)offset, count));
1372 if(tcon->ses->capabilities & CAP_LARGE_FILES)
1376 rc = small_smb_init(SMB_COM_WRITE_ANDX, wct, tcon, (void **) &pSMB);
1379 /* tcon and ses pointer are checked in smb_init */
1380 if (tcon->ses->server == NULL)
1381 return -ECONNABORTED;
1383 pSMB->AndXCommand = 0xFF; /* none */
1385 pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF);
1387 pSMB->OffsetHigh = cpu_to_le32(offset >> 32);
1388 else if((offset >> 32) > 0) /* can not handle this big offset for old */
1390 pSMB->Reserved = 0xFFFFFFFF;
1391 pSMB->WriteMode = 0;
1392 pSMB->Remaining = 0;
1395 cpu_to_le16(offsetof(struct smb_com_write_req,Data) - 4);
1397 pSMB->DataLengthLow = cpu_to_le16(count & 0xFFFF);
1398 pSMB->DataLengthHigh = cpu_to_le16(count >> 16);
1399 smb_hdr_len = pSMB->hdr.smb_buf_length + 1; /* hdr + 1 byte pad */
1401 pSMB->hdr.smb_buf_length += count+1;
1402 else /* wct == 12 */
1403 pSMB->hdr.smb_buf_length += count+5; /* smb data starts later */
1405 pSMB->ByteCount = cpu_to_le16(count + 1);
1406 else /* wct == 12 */ /* bigger pad, smaller smb hdr, keep offset ok */ {
1407 struct smb_com_writex_req * pSMBW =
1408 (struct smb_com_writex_req *)pSMB;
1409 pSMBW->ByteCount = cpu_to_le16(count + 5);
1411 iov[0].iov_base = pSMB;
1413 iov[0].iov_len = smb_hdr_len + 4;
1414 else /* wct == 12 pad bigger by four bytes */
1415 iov[0].iov_len = smb_hdr_len + 8;
1418 rc = SendReceive2(xid, tcon->ses, iov, n_vec + 1, &resp_buf_type,
1420 cifs_stats_inc(&tcon->num_writes);
1422 cFYI(1, ("Send error Write2 = %d", rc));
1424 } else if(resp_buf_type == 0) {
1425 /* presumably this can not happen, but best to be safe */
1429 WRITE_RSP * pSMBr = (WRITE_RSP *)iov[0].iov_base;
1430 *nbytes = le16_to_cpu(pSMBr->CountHigh);
1431 *nbytes = (*nbytes) << 16;
1432 *nbytes += le16_to_cpu(pSMBr->Count);
1435 /* cifs_small_buf_release(pSMB); */ /* Freed earlier now in SendReceive2 */
1436 if(resp_buf_type == CIFS_SMALL_BUFFER)
1437 cifs_small_buf_release(iov[0].iov_base);
1438 else if(resp_buf_type == CIFS_LARGE_BUFFER)
1439 cifs_buf_release(iov[0].iov_base);
1441 /* Note: On -EAGAIN error only caller can retry on handle based calls
1442 since file handle passed in no longer valid */
1449 CIFSSMBLock(const int xid, struct cifsTconInfo *tcon,
1450 const __u16 smb_file_id, const __u64 len,
1451 const __u64 offset, const __u32 numUnlock,
1452 const __u32 numLock, const __u8 lockType, const int waitFlag)
1455 LOCK_REQ *pSMB = NULL;
1456 LOCK_RSP *pSMBr = NULL;
1461 cFYI(1, ("In CIFSSMBLock - timeout %d numLock %d",waitFlag,numLock));
1462 rc = small_smb_init(SMB_COM_LOCKING_ANDX, 8, tcon, (void **) &pSMB);
1467 pSMBr = (LOCK_RSP *)pSMB; /* BB removeme BB */
1469 if(lockType == LOCKING_ANDX_OPLOCK_RELEASE) {
1470 timeout = -1; /* no response expected */
1472 } else if (waitFlag == TRUE) {
1473 timeout = 3; /* blocking operation, no timeout */
1474 pSMB->Timeout = cpu_to_le32(-1);/* blocking - do not time out */
1479 pSMB->NumberOfLocks = cpu_to_le16(numLock);
1480 pSMB->NumberOfUnlocks = cpu_to_le16(numUnlock);
1481 pSMB->LockType = lockType;
1482 pSMB->AndXCommand = 0xFF; /* none */
1483 pSMB->Fid = smb_file_id; /* netfid stays le */
1485 if((numLock != 0) || (numUnlock != 0)) {
1486 pSMB->Locks[0].Pid = cpu_to_le16(current->tgid);
1487 /* BB where to store pid high? */
1488 pSMB->Locks[0].LengthLow = cpu_to_le32((u32)len);
1489 pSMB->Locks[0].LengthHigh = cpu_to_le32((u32)(len>>32));
1490 pSMB->Locks[0].OffsetLow = cpu_to_le32((u32)offset);
1491 pSMB->Locks[0].OffsetHigh = cpu_to_le32((u32)(offset>>32));
1492 count = sizeof(LOCKING_ANDX_RANGE);
1497 pSMB->hdr.smb_buf_length += count;
1498 pSMB->ByteCount = cpu_to_le16(count);
1501 rc = SendReceiveBlockingLock(xid, tcon, (struct smb_hdr *) pSMB,
1502 (struct smb_hdr *) pSMBr, &bytes_returned);
1504 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1505 (struct smb_hdr *) pSMBr, &bytes_returned, timeout);
1507 cifs_stats_inc(&tcon->num_locks);
1509 cFYI(1, ("Send error in Lock = %d", rc));
1511 cifs_small_buf_release(pSMB);
1513 /* Note: On -EAGAIN error only caller can retry on handle based calls
1514 since file handle passed in no longer valid */
1519 CIFSSMBPosixLock(const int xid, struct cifsTconInfo *tcon,
1520 const __u16 smb_file_id, const int get_flag, const __u64 len,
1521 struct file_lock *pLockData, const __u16 lock_type,
1524 struct smb_com_transaction2_sfi_req *pSMB = NULL;
1525 struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
1527 struct cifs_posix_lock *parm_data;
1530 int bytes_returned = 0;
1531 __u16 params, param_offset, offset, byte_count, count;
1533 cFYI(1, ("Posix Lock"));
1535 if(pLockData == NULL)
1538 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
1543 pSMBr = (struct smb_com_transaction2_sfi_rsp *)pSMB;
1546 pSMB->MaxSetupCount = 0;
1549 pSMB->Reserved2 = 0;
1550 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
1551 offset = param_offset + params;
1553 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
1555 count = sizeof(struct cifs_posix_lock);
1556 pSMB->MaxParameterCount = cpu_to_le16(2);
1557 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB PDU from sess */
1558 pSMB->SetupCount = 1;
1559 pSMB->Reserved3 = 0;
1561 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION);
1563 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
1564 byte_count = 3 /* pad */ + params + count;
1565 pSMB->DataCount = cpu_to_le16(count);
1566 pSMB->ParameterCount = cpu_to_le16(params);
1567 pSMB->TotalDataCount = pSMB->DataCount;
1568 pSMB->TotalParameterCount = pSMB->ParameterCount;
1569 pSMB->ParameterOffset = cpu_to_le16(param_offset);
1570 parm_data = (struct cifs_posix_lock *)
1571 (((char *) &pSMB->hdr.Protocol) + offset);
1573 parm_data->lock_type = cpu_to_le16(lock_type);
1575 timeout = 3; /* blocking operation, no timeout */
1576 parm_data->lock_flags = cpu_to_le16(1);
1577 pSMB->Timeout = cpu_to_le32(-1);
1581 parm_data->pid = cpu_to_le32(current->tgid);
1582 parm_data->start = cpu_to_le64(pLockData->fl_start);
1583 parm_data->length = cpu_to_le64(len); /* normalize negative numbers */
1585 pSMB->DataOffset = cpu_to_le16(offset);
1586 pSMB->Fid = smb_file_id;
1587 pSMB->InformationLevel = cpu_to_le16(SMB_SET_POSIX_LOCK);
1588 pSMB->Reserved4 = 0;
1589 pSMB->hdr.smb_buf_length += byte_count;
1590 pSMB->ByteCount = cpu_to_le16(byte_count);
1592 rc = SendReceiveBlockingLock(xid, tcon, (struct smb_hdr *) pSMB,
1593 (struct smb_hdr *) pSMBr, &bytes_returned);
1595 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1596 (struct smb_hdr *) pSMBr, &bytes_returned, timeout);
1600 cFYI(1, ("Send error in Posix Lock = %d", rc));
1601 } else if (get_flag) {
1602 /* lock structure can be returned on get */
1605 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
1607 if (rc || (pSMBr->ByteCount < sizeof(struct cifs_posix_lock))) {
1608 rc = -EIO; /* bad smb */
1611 if(pLockData == NULL) {
1615 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
1616 data_count = le16_to_cpu(pSMBr->t2.DataCount);
1617 if(data_count < sizeof(struct cifs_posix_lock)) {
1621 parm_data = (struct cifs_posix_lock *)
1622 ((char *)&pSMBr->hdr.Protocol + data_offset);
1623 if(parm_data->lock_type == cpu_to_le16(CIFS_UNLCK))
1624 pLockData->fl_type = F_UNLCK;
1629 cifs_small_buf_release(pSMB);
1631 /* Note: On -EAGAIN error only caller can retry on handle based calls
1632 since file handle passed in no longer valid */
1639 CIFSSMBClose(const int xid, struct cifsTconInfo *tcon, int smb_file_id)
1642 CLOSE_REQ *pSMB = NULL;
1643 CLOSE_RSP *pSMBr = NULL;
1645 cFYI(1, ("In CIFSSMBClose"));
1647 /* do not retry on dead session on close */
1648 rc = small_smb_init(SMB_COM_CLOSE, 3, tcon, (void **) &pSMB);
1654 pSMBr = (CLOSE_RSP *)pSMB; /* BB removeme BB */
1656 pSMB->FileID = (__u16) smb_file_id;
1657 pSMB->LastWriteTime = 0xFFFFFFFF;
1658 pSMB->ByteCount = 0;
1659 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1660 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1661 cifs_stats_inc(&tcon->num_closes);
1664 /* EINTR is expected when user ctl-c to kill app */
1665 cERROR(1, ("Send error in Close = %d", rc));
1669 cifs_small_buf_release(pSMB);
1671 /* Since session is dead, file will be closed on server already */
1679 CIFSSMBRename(const int xid, struct cifsTconInfo *tcon,
1680 const char *fromName, const char *toName,
1681 const struct nls_table *nls_codepage, int remap)
1684 RENAME_REQ *pSMB = NULL;
1685 RENAME_RSP *pSMBr = NULL;
1687 int name_len, name_len2;
1690 cFYI(1, ("In CIFSSMBRename"));
1692 rc = smb_init(SMB_COM_RENAME, 1, tcon, (void **) &pSMB,
1697 pSMB->BufferFormat = 0x04;
1698 pSMB->SearchAttributes =
1699 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
1702 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1704 cifsConvertToUCS((__le16 *) pSMB->OldFileName, fromName,
1705 PATH_MAX, nls_codepage, remap);
1706 name_len++; /* trailing null */
1708 pSMB->OldFileName[name_len] = 0x04; /* pad */
1709 /* protocol requires ASCII signature byte on Unicode string */
1710 pSMB->OldFileName[name_len + 1] = 0x00;
1712 cifsConvertToUCS((__le16 *) &pSMB->OldFileName[name_len + 2],
1713 toName, PATH_MAX, nls_codepage, remap);
1714 name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
1715 name_len2 *= 2; /* convert to bytes */
1716 } else { /* BB improve the check for buffer overruns BB */
1717 name_len = strnlen(fromName, PATH_MAX);
1718 name_len++; /* trailing null */
1719 strncpy(pSMB->OldFileName, fromName, name_len);
1720 name_len2 = strnlen(toName, PATH_MAX);
1721 name_len2++; /* trailing null */
1722 pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */
1723 strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2);
1724 name_len2++; /* trailing null */
1725 name_len2++; /* signature byte */
1728 count = 1 /* 1st signature byte */ + name_len + name_len2;
1729 pSMB->hdr.smb_buf_length += count;
1730 pSMB->ByteCount = cpu_to_le16(count);
1732 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1733 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1734 cifs_stats_inc(&tcon->num_renames);
1736 cFYI(1, ("Send error in rename = %d", rc));
1739 cifs_buf_release(pSMB);
1747 int CIFSSMBRenameOpenFile(const int xid,struct cifsTconInfo *pTcon,
1748 int netfid, char * target_name,
1749 const struct nls_table * nls_codepage, int remap)
1751 struct smb_com_transaction2_sfi_req *pSMB = NULL;
1752 struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
1753 struct set_file_rename * rename_info;
1755 char dummy_string[30];
1757 int bytes_returned = 0;
1759 __u16 params, param_offset, offset, count, byte_count;
1761 cFYI(1, ("Rename to File by handle"));
1762 rc = smb_init(SMB_COM_TRANSACTION2, 15, pTcon, (void **) &pSMB,
1768 pSMB->MaxSetupCount = 0;
1772 pSMB->Reserved2 = 0;
1773 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
1774 offset = param_offset + params;
1776 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
1777 rename_info = (struct set_file_rename *) data_offset;
1778 pSMB->MaxParameterCount = cpu_to_le16(2);
1779 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB PDU from sess */
1780 pSMB->SetupCount = 1;
1781 pSMB->Reserved3 = 0;
1782 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
1783 byte_count = 3 /* pad */ + params;
1784 pSMB->ParameterCount = cpu_to_le16(params);
1785 pSMB->TotalParameterCount = pSMB->ParameterCount;
1786 pSMB->ParameterOffset = cpu_to_le16(param_offset);
1787 pSMB->DataOffset = cpu_to_le16(offset);
1788 /* construct random name ".cifs_tmp<inodenum><mid>" */
1789 rename_info->overwrite = cpu_to_le32(1);
1790 rename_info->root_fid = 0;
1791 /* unicode only call */
1792 if(target_name == NULL) {
1793 sprintf(dummy_string,"cifs%x",pSMB->hdr.Mid);
1794 len_of_str = cifsConvertToUCS((__le16 *)rename_info->target_name,
1795 dummy_string, 24, nls_codepage, remap);
1797 len_of_str = cifsConvertToUCS((__le16 *)rename_info->target_name,
1798 target_name, PATH_MAX, nls_codepage, remap);
1800 rename_info->target_name_len = cpu_to_le32(2 * len_of_str);
1801 count = 12 /* sizeof(struct set_file_rename) */ + (2 * len_of_str) + 2;
1802 byte_count += count;
1803 pSMB->DataCount = cpu_to_le16(count);
1804 pSMB->TotalDataCount = pSMB->DataCount;
1806 pSMB->InformationLevel =
1807 cpu_to_le16(SMB_SET_FILE_RENAME_INFORMATION);
1808 pSMB->Reserved4 = 0;
1809 pSMB->hdr.smb_buf_length += byte_count;
1810 pSMB->ByteCount = cpu_to_le16(byte_count);
1811 rc = SendReceive(xid, pTcon->ses, (struct smb_hdr *) pSMB,
1812 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1813 cifs_stats_inc(&pTcon->num_t2renames);
1815 cFYI(1,("Send error in Rename (by file handle) = %d", rc));
1818 cifs_buf_release(pSMB);
1820 /* Note: On -EAGAIN error only caller can retry on handle based calls
1821 since file handle passed in no longer valid */
1827 CIFSSMBCopy(const int xid, struct cifsTconInfo *tcon, const char * fromName,
1828 const __u16 target_tid, const char *toName, const int flags,
1829 const struct nls_table *nls_codepage, int remap)
1832 COPY_REQ *pSMB = NULL;
1833 COPY_RSP *pSMBr = NULL;
1835 int name_len, name_len2;
1838 cFYI(1, ("In CIFSSMBCopy"));
1840 rc = smb_init(SMB_COM_COPY, 1, tcon, (void **) &pSMB,
1845 pSMB->BufferFormat = 0x04;
1846 pSMB->Tid2 = target_tid;
1848 pSMB->Flags = cpu_to_le16(flags & COPY_TREE);
1850 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1851 name_len = cifsConvertToUCS((__le16 *) pSMB->OldFileName,
1852 fromName, PATH_MAX, nls_codepage,
1854 name_len++; /* trailing null */
1856 pSMB->OldFileName[name_len] = 0x04; /* pad */
1857 /* protocol requires ASCII signature byte on Unicode string */
1858 pSMB->OldFileName[name_len + 1] = 0x00;
1859 name_len2 = cifsConvertToUCS((__le16 *)&pSMB->OldFileName[name_len + 2],
1860 toName, PATH_MAX, nls_codepage, remap);
1861 name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
1862 name_len2 *= 2; /* convert to bytes */
1863 } else { /* BB improve the check for buffer overruns BB */
1864 name_len = strnlen(fromName, PATH_MAX);
1865 name_len++; /* trailing null */
1866 strncpy(pSMB->OldFileName, fromName, name_len);
1867 name_len2 = strnlen(toName, PATH_MAX);
1868 name_len2++; /* trailing null */
1869 pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */
1870 strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2);
1871 name_len2++; /* trailing null */
1872 name_len2++; /* signature byte */
1875 count = 1 /* 1st signature byte */ + name_len + name_len2;
1876 pSMB->hdr.smb_buf_length += count;
1877 pSMB->ByteCount = cpu_to_le16(count);
1879 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1880 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1882 cFYI(1, ("Send error in copy = %d with %d files copied",
1883 rc, le16_to_cpu(pSMBr->CopyCount)));
1886 cifs_buf_release(pSMB);
1895 CIFSUnixCreateSymLink(const int xid, struct cifsTconInfo *tcon,
1896 const char *fromName, const char *toName,
1897 const struct nls_table *nls_codepage)
1899 TRANSACTION2_SPI_REQ *pSMB = NULL;
1900 TRANSACTION2_SPI_RSP *pSMBr = NULL;
1903 int name_len_target;
1905 int bytes_returned = 0;
1906 __u16 params, param_offset, offset, byte_count;
1908 cFYI(1, ("In Symlink Unix style"));
1910 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
1915 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1917 cifs_strtoUCS((__le16 *) pSMB->FileName, fromName, PATH_MAX
1918 /* find define for this maxpathcomponent */
1920 name_len++; /* trailing null */
1923 } else { /* BB improve the check for buffer overruns BB */
1924 name_len = strnlen(fromName, PATH_MAX);
1925 name_len++; /* trailing null */
1926 strncpy(pSMB->FileName, fromName, name_len);
1928 params = 6 + name_len;
1929 pSMB->MaxSetupCount = 0;
1933 pSMB->Reserved2 = 0;
1934 param_offset = offsetof(struct smb_com_transaction2_spi_req,
1935 InformationLevel) - 4;
1936 offset = param_offset + params;
1938 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
1939 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1941 cifs_strtoUCS((__le16 *) data_offset, toName, PATH_MAX
1942 /* find define for this maxpathcomponent */
1944 name_len_target++; /* trailing null */
1945 name_len_target *= 2;
1946 } else { /* BB improve the check for buffer overruns BB */
1947 name_len_target = strnlen(toName, PATH_MAX);
1948 name_len_target++; /* trailing null */
1949 strncpy(data_offset, toName, name_len_target);
1952 pSMB->MaxParameterCount = cpu_to_le16(2);
1953 /* BB find exact max on data count below from sess */
1954 pSMB->MaxDataCount = cpu_to_le16(1000);
1955 pSMB->SetupCount = 1;
1956 pSMB->Reserved3 = 0;
1957 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
1958 byte_count = 3 /* pad */ + params + name_len_target;
1959 pSMB->DataCount = cpu_to_le16(name_len_target);
1960 pSMB->ParameterCount = cpu_to_le16(params);
1961 pSMB->TotalDataCount = pSMB->DataCount;
1962 pSMB->TotalParameterCount = pSMB->ParameterCount;
1963 pSMB->ParameterOffset = cpu_to_le16(param_offset);
1964 pSMB->DataOffset = cpu_to_le16(offset);
1965 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_LINK);
1966 pSMB->Reserved4 = 0;
1967 pSMB->hdr.smb_buf_length += byte_count;
1968 pSMB->ByteCount = cpu_to_le16(byte_count);
1969 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1970 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1971 cifs_stats_inc(&tcon->num_symlinks);
1974 ("Send error in SetPathInfo (create symlink) = %d",
1979 cifs_buf_release(pSMB);
1982 goto createSymLinkRetry;
1988 CIFSUnixCreateHardLink(const int xid, struct cifsTconInfo *tcon,
1989 const char *fromName, const char *toName,
1990 const struct nls_table *nls_codepage, int remap)
1992 TRANSACTION2_SPI_REQ *pSMB = NULL;
1993 TRANSACTION2_SPI_RSP *pSMBr = NULL;
1996 int name_len_target;
1998 int bytes_returned = 0;
1999 __u16 params, param_offset, offset, byte_count;
2001 cFYI(1, ("In Create Hard link Unix style"));
2002 createHardLinkRetry:
2003 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2008 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2009 name_len = cifsConvertToUCS((__le16 *) pSMB->FileName, toName,
2010 PATH_MAX, nls_codepage, remap);
2011 name_len++; /* trailing null */
2014 } else { /* BB improve the check for buffer overruns BB */
2015 name_len = strnlen(toName, PATH_MAX);
2016 name_len++; /* trailing null */
2017 strncpy(pSMB->FileName, toName, name_len);
2019 params = 6 + name_len;
2020 pSMB->MaxSetupCount = 0;
2024 pSMB->Reserved2 = 0;
2025 param_offset = offsetof(struct smb_com_transaction2_spi_req,
2026 InformationLevel) - 4;
2027 offset = param_offset + params;
2029 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
2030 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2032 cifsConvertToUCS((__le16 *) data_offset, fromName, PATH_MAX,
2033 nls_codepage, remap);
2034 name_len_target++; /* trailing null */
2035 name_len_target *= 2;
2036 } else { /* BB improve the check for buffer overruns BB */
2037 name_len_target = strnlen(fromName, PATH_MAX);
2038 name_len_target++; /* trailing null */
2039 strncpy(data_offset, fromName, name_len_target);
2042 pSMB->MaxParameterCount = cpu_to_le16(2);
2043 /* BB find exact max on data count below from sess*/
2044 pSMB->MaxDataCount = cpu_to_le16(1000);
2045 pSMB->SetupCount = 1;
2046 pSMB->Reserved3 = 0;
2047 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
2048 byte_count = 3 /* pad */ + params + name_len_target;
2049 pSMB->ParameterCount = cpu_to_le16(params);
2050 pSMB->TotalParameterCount = pSMB->ParameterCount;
2051 pSMB->DataCount = cpu_to_le16(name_len_target);
2052 pSMB->TotalDataCount = pSMB->DataCount;
2053 pSMB->ParameterOffset = cpu_to_le16(param_offset);
2054 pSMB->DataOffset = cpu_to_le16(offset);
2055 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_HLINK);
2056 pSMB->Reserved4 = 0;
2057 pSMB->hdr.smb_buf_length += byte_count;
2058 pSMB->ByteCount = cpu_to_le16(byte_count);
2059 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2060 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2061 cifs_stats_inc(&tcon->num_hardlinks);
2063 cFYI(1, ("Send error in SetPathInfo (hard link) = %d", rc));
2066 cifs_buf_release(pSMB);
2068 goto createHardLinkRetry;
2074 CIFSCreateHardLink(const int xid, struct cifsTconInfo *tcon,
2075 const char *fromName, const char *toName,
2076 const struct nls_table *nls_codepage, int remap)
2079 NT_RENAME_REQ *pSMB = NULL;
2080 RENAME_RSP *pSMBr = NULL;
2082 int name_len, name_len2;
2085 cFYI(1, ("In CIFSCreateHardLink"));
2086 winCreateHardLinkRetry:
2088 rc = smb_init(SMB_COM_NT_RENAME, 4, tcon, (void **) &pSMB,
2093 pSMB->SearchAttributes =
2094 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
2096 pSMB->Flags = cpu_to_le16(CREATE_HARD_LINK);
2097 pSMB->ClusterCount = 0;
2099 pSMB->BufferFormat = 0x04;
2101 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2103 cifsConvertToUCS((__le16 *) pSMB->OldFileName, fromName,
2104 PATH_MAX, nls_codepage, remap);
2105 name_len++; /* trailing null */
2107 pSMB->OldFileName[name_len] = 0; /* pad */
2108 pSMB->OldFileName[name_len + 1] = 0x04;
2110 cifsConvertToUCS((__le16 *)&pSMB->OldFileName[name_len + 2],
2111 toName, PATH_MAX, nls_codepage, remap);
2112 name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
2113 name_len2 *= 2; /* convert to bytes */
2114 } else { /* BB improve the check for buffer overruns BB */
2115 name_len = strnlen(fromName, PATH_MAX);
2116 name_len++; /* trailing null */
2117 strncpy(pSMB->OldFileName, fromName, name_len);
2118 name_len2 = strnlen(toName, PATH_MAX);
2119 name_len2++; /* trailing null */
2120 pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */
2121 strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2);
2122 name_len2++; /* trailing null */
2123 name_len2++; /* signature byte */
2126 count = 1 /* string type byte */ + name_len + name_len2;
2127 pSMB->hdr.smb_buf_length += count;
2128 pSMB->ByteCount = cpu_to_le16(count);
2130 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2131 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2132 cifs_stats_inc(&tcon->num_hardlinks);
2134 cFYI(1, ("Send error in hard link (NT rename) = %d", rc));
2136 cifs_buf_release(pSMB);
2138 goto winCreateHardLinkRetry;
2144 CIFSSMBUnixQuerySymLink(const int xid, struct cifsTconInfo *tcon,
2145 const unsigned char *searchName,
2146 char *symlinkinfo, const int buflen,
2147 const struct nls_table *nls_codepage)
2149 /* SMB_QUERY_FILE_UNIX_LINK */
2150 TRANSACTION2_QPI_REQ *pSMB = NULL;
2151 TRANSACTION2_QPI_RSP *pSMBr = NULL;
2155 __u16 params, byte_count;
2157 cFYI(1, ("In QPathSymLinkInfo (Unix) for path %s", searchName));
2160 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2165 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2167 cifs_strtoUCS((__le16 *) pSMB->FileName, searchName, PATH_MAX
2168 /* find define for this maxpathcomponent */
2170 name_len++; /* trailing null */
2172 } else { /* BB improve the check for buffer overruns BB */
2173 name_len = strnlen(searchName, PATH_MAX);
2174 name_len++; /* trailing null */
2175 strncpy(pSMB->FileName, searchName, name_len);
2178 params = 2 /* level */ + 4 /* rsrvd */ + name_len /* incl null */ ;
2179 pSMB->TotalDataCount = 0;
2180 pSMB->MaxParameterCount = cpu_to_le16(2);
2181 /* BB find exact max data count below from sess structure BB */
2182 pSMB->MaxDataCount = cpu_to_le16(4000);
2183 pSMB->MaxSetupCount = 0;
2187 pSMB->Reserved2 = 0;
2188 pSMB->ParameterOffset = cpu_to_le16(offsetof(
2189 struct smb_com_transaction2_qpi_req ,InformationLevel) - 4);
2190 pSMB->DataCount = 0;
2191 pSMB->DataOffset = 0;
2192 pSMB->SetupCount = 1;
2193 pSMB->Reserved3 = 0;
2194 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
2195 byte_count = params + 1 /* pad */ ;
2196 pSMB->TotalParameterCount = cpu_to_le16(params);
2197 pSMB->ParameterCount = pSMB->TotalParameterCount;
2198 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_LINK);
2199 pSMB->Reserved4 = 0;
2200 pSMB->hdr.smb_buf_length += byte_count;
2201 pSMB->ByteCount = cpu_to_le16(byte_count);
2203 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2204 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2206 cFYI(1, ("Send error in QuerySymLinkInfo = %d", rc));
2208 /* decode response */
2210 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
2211 if (rc || (pSMBr->ByteCount < 2))
2212 /* BB also check enough total bytes returned */
2213 rc = -EIO; /* bad smb */
2215 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
2216 __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
2218 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
2219 name_len = UniStrnlen((wchar_t *) ((char *)
2220 &pSMBr->hdr.Protocol +data_offset),
2221 min_t(const int, buflen,count) / 2);
2222 /* BB FIXME investigate remapping reserved chars here */
2223 cifs_strfromUCS_le(symlinkinfo,
2224 (__le16 *) ((char *)&pSMBr->hdr.Protocol +
2226 name_len, nls_codepage);
2228 strncpy(symlinkinfo,
2229 (char *) &pSMBr->hdr.Protocol +
2231 min_t(const int, buflen, count));
2233 symlinkinfo[buflen] = 0;
2234 /* just in case so calling code does not go off the end of buffer */
2237 cifs_buf_release(pSMB);
2239 goto querySymLinkRetry;
2243 /* Initialize NT TRANSACT SMB into small smb request buffer.
2244 This assumes that all NT TRANSACTS that we init here have
2245 total parm and data under about 400 bytes (to fit in small cifs
2246 buffer size), which is the case so far, it easily fits. NB:
2247 Setup words themselves and ByteCount
2248 MaxSetupCount (size of returned setup area) and
2249 MaxParameterCount (returned parms size) must be set by caller */
2251 smb_init_ntransact(const __u16 sub_command, const int setup_count,
2252 const int parm_len, struct cifsTconInfo *tcon,
2257 struct smb_com_ntransact_req * pSMB;
2259 rc = small_smb_init(SMB_COM_NT_TRANSACT, 19 + setup_count, tcon,
2263 *ret_buf = (void *)pSMB;
2265 pSMB->TotalParameterCount = cpu_to_le32(parm_len);
2266 pSMB->TotalDataCount = 0;
2267 pSMB->MaxDataCount = cpu_to_le32((tcon->ses->server->maxBuf -
2268 MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
2269 pSMB->ParameterCount = pSMB->TotalParameterCount;
2270 pSMB->DataCount = pSMB->TotalDataCount;
2271 temp_offset = offsetof(struct smb_com_ntransact_req, Parms) +
2272 (setup_count * 2) - 4 /* for rfc1001 length itself */;
2273 pSMB->ParameterOffset = cpu_to_le32(temp_offset);
2274 pSMB->DataOffset = cpu_to_le32(temp_offset + parm_len);
2275 pSMB->SetupCount = setup_count; /* no need to le convert byte fields */
2276 pSMB->SubCommand = cpu_to_le16(sub_command);
2281 validate_ntransact(char * buf, char ** ppparm, char ** ppdata,
2282 int * pdatalen, int * pparmlen)
2285 __u32 data_count, data_offset, parm_count, parm_offset;
2286 struct smb_com_ntransact_rsp * pSMBr;
2291 pSMBr = (struct smb_com_ntransact_rsp *)buf;
2293 /* ByteCount was converted from little endian in SendReceive */
2294 end_of_smb = 2 /* sizeof byte count */ + pSMBr->ByteCount +
2295 (char *)&pSMBr->ByteCount;
2298 data_offset = le32_to_cpu(pSMBr->DataOffset);
2299 data_count = le32_to_cpu(pSMBr->DataCount);
2300 parm_offset = le32_to_cpu(pSMBr->ParameterOffset);
2301 parm_count = le32_to_cpu(pSMBr->ParameterCount);
2303 *ppparm = (char *)&pSMBr->hdr.Protocol + parm_offset;
2304 *ppdata = (char *)&pSMBr->hdr.Protocol + data_offset;
2306 /* should we also check that parm and data areas do not overlap? */
2307 if(*ppparm > end_of_smb) {
2308 cFYI(1,("parms start after end of smb"));
2310 } else if(parm_count + *ppparm > end_of_smb) {
2311 cFYI(1,("parm end after end of smb"));
2313 } else if(*ppdata > end_of_smb) {
2314 cFYI(1,("data starts after end of smb"));
2316 } else if(data_count + *ppdata > end_of_smb) {
2317 cFYI(1,("data %p + count %d (%p) ends after end of smb %p start %p",
2318 *ppdata, data_count, (data_count + *ppdata), end_of_smb, pSMBr)); /* BB FIXME */
2320 } else if(parm_count + data_count > pSMBr->ByteCount) {
2321 cFYI(1,("parm count and data count larger than SMB"));
2328 CIFSSMBQueryReparseLinkInfo(const int xid, struct cifsTconInfo *tcon,
2329 const unsigned char *searchName,
2330 char *symlinkinfo, const int buflen,__u16 fid,
2331 const struct nls_table *nls_codepage)
2336 struct smb_com_transaction_ioctl_req * pSMB;
2337 struct smb_com_transaction_ioctl_rsp * pSMBr;
2339 cFYI(1, ("In Windows reparse style QueryLink for path %s", searchName));
2340 rc = smb_init(SMB_COM_NT_TRANSACT, 23, tcon, (void **) &pSMB,
2345 pSMB->TotalParameterCount = 0 ;
2346 pSMB->TotalDataCount = 0;
2347 pSMB->MaxParameterCount = cpu_to_le32(2);
2348 /* BB find exact data count max from sess structure BB */
2349 pSMB->MaxDataCount = cpu_to_le32((tcon->ses->server->maxBuf -
2350 MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
2351 pSMB->MaxSetupCount = 4;
2353 pSMB->ParameterOffset = 0;
2354 pSMB->DataCount = 0;
2355 pSMB->DataOffset = 0;
2356 pSMB->SetupCount = 4;
2357 pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_IOCTL);
2358 pSMB->ParameterCount = pSMB->TotalParameterCount;
2359 pSMB->FunctionCode = cpu_to_le32(FSCTL_GET_REPARSE_POINT);
2360 pSMB->IsFsctl = 1; /* FSCTL */
2361 pSMB->IsRootFlag = 0;
2362 pSMB->Fid = fid; /* file handle always le */
2363 pSMB->ByteCount = 0;
2365 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2366 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2368 cFYI(1, ("Send error in QueryReparseLinkInfo = %d", rc));
2369 } else { /* decode response */
2370 __u32 data_offset = le32_to_cpu(pSMBr->DataOffset);
2371 __u32 data_count = le32_to_cpu(pSMBr->DataCount);
2372 if ((pSMBr->ByteCount < 2) || (data_offset > 512))
2373 /* BB also check enough total bytes returned */
2374 rc = -EIO; /* bad smb */
2376 if(data_count && (data_count < 2048)) {
2377 char * end_of_smb = 2 /* sizeof byte count */ +
2379 (char *)&pSMBr->ByteCount;
2381 struct reparse_data * reparse_buf = (struct reparse_data *)
2382 ((char *)&pSMBr->hdr.Protocol + data_offset);
2383 if((char*)reparse_buf >= end_of_smb) {
2387 if((reparse_buf->LinkNamesBuf +
2388 reparse_buf->TargetNameOffset +
2389 reparse_buf->TargetNameLen) >
2391 cFYI(1,("reparse buf extended beyond SMB"));
2396 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
2397 name_len = UniStrnlen((wchar_t *)
2398 (reparse_buf->LinkNamesBuf +
2399 reparse_buf->TargetNameOffset),
2400 min(buflen/2, reparse_buf->TargetNameLen / 2));
2401 cifs_strfromUCS_le(symlinkinfo,
2402 (__le16 *) (reparse_buf->LinkNamesBuf +
2403 reparse_buf->TargetNameOffset),
2404 name_len, nls_codepage);
2405 } else { /* ASCII names */
2406 strncpy(symlinkinfo,reparse_buf->LinkNamesBuf +
2407 reparse_buf->TargetNameOffset,
2408 min_t(const int, buflen, reparse_buf->TargetNameLen));
2412 cFYI(1,("Invalid return data count on get reparse info ioctl"));
2414 symlinkinfo[buflen] = 0; /* just in case so the caller
2415 does not go off the end of the buffer */
2416 cFYI(1,("readlink result - %s",symlinkinfo));
2420 cifs_buf_release(pSMB);
2422 /* Note: On -EAGAIN error only caller can retry on handle based calls
2423 since file handle passed in no longer valid */
2428 #ifdef CONFIG_CIFS_POSIX
2430 /*Convert an Access Control Entry from wire format to local POSIX xattr format*/
2431 static void cifs_convert_ace(posix_acl_xattr_entry * ace, struct cifs_posix_ace * cifs_ace)
2433 /* u8 cifs fields do not need le conversion */
2434 ace->e_perm = cpu_to_le16(cifs_ace->cifs_e_perm);
2435 ace->e_tag = cpu_to_le16(cifs_ace->cifs_e_tag);
2436 ace->e_id = cpu_to_le32(le64_to_cpu(cifs_ace->cifs_uid));
2437 /* cFYI(1,("perm %d tag %d id %d",ace->e_perm,ace->e_tag,ace->e_id)); */
2442 /* Convert ACL from CIFS POSIX wire format to local Linux POSIX ACL xattr */
2443 static int cifs_copy_posix_acl(char * trgt,char * src, const int buflen,
2444 const int acl_type,const int size_of_data_area)
2449 struct cifs_posix_ace * pACE;
2450 struct cifs_posix_acl * cifs_acl = (struct cifs_posix_acl *)src;
2451 posix_acl_xattr_header * local_acl = (posix_acl_xattr_header *)trgt;
2453 if (le16_to_cpu(cifs_acl->version) != CIFS_ACL_VERSION)
2456 if(acl_type & ACL_TYPE_ACCESS) {
2457 count = le16_to_cpu(cifs_acl->access_entry_count);
2458 pACE = &cifs_acl->ace_array[0];
2459 size = sizeof(struct cifs_posix_acl);
2460 size += sizeof(struct cifs_posix_ace) * count;
2461 /* check if we would go beyond end of SMB */
2462 if(size_of_data_area < size) {
2463 cFYI(1,("bad CIFS POSIX ACL size %d vs. %d",size_of_data_area,size));
2466 } else if(acl_type & ACL_TYPE_DEFAULT) {
2467 count = le16_to_cpu(cifs_acl->access_entry_count);
2468 size = sizeof(struct cifs_posix_acl);
2469 size += sizeof(struct cifs_posix_ace) * count;
2470 /* skip past access ACEs to get to default ACEs */
2471 pACE = &cifs_acl->ace_array[count];
2472 count = le16_to_cpu(cifs_acl->default_entry_count);
2473 size += sizeof(struct cifs_posix_ace) * count;
2474 /* check if we would go beyond end of SMB */
2475 if(size_of_data_area < size)
2482 size = posix_acl_xattr_size(count);
2483 if((buflen == 0) || (local_acl == NULL)) {
2484 /* used to query ACL EA size */
2485 } else if(size > buflen) {
2487 } else /* buffer big enough */ {
2488 local_acl->a_version = cpu_to_le32(POSIX_ACL_XATTR_VERSION);
2489 for(i = 0;i < count ;i++) {
2490 cifs_convert_ace(&local_acl->a_entries[i],pACE);
2497 static __u16 convert_ace_to_cifs_ace(struct cifs_posix_ace * cifs_ace,
2498 const posix_acl_xattr_entry * local_ace)
2500 __u16 rc = 0; /* 0 = ACL converted ok */
2502 cifs_ace->cifs_e_perm = le16_to_cpu(local_ace->e_perm);
2503 cifs_ace->cifs_e_tag = le16_to_cpu(local_ace->e_tag);
2504 /* BB is there a better way to handle the large uid? */
2505 if(local_ace->e_id == cpu_to_le32(-1)) {
2506 /* Probably no need to le convert -1 on any arch but can not hurt */
2507 cifs_ace->cifs_uid = cpu_to_le64(-1);
2509 cifs_ace->cifs_uid = cpu_to_le64(le32_to_cpu(local_ace->e_id));
2510 /*cFYI(1,("perm %d tag %d id %d",ace->e_perm,ace->e_tag,ace->e_id));*/
2514 /* Convert ACL from local Linux POSIX xattr to CIFS POSIX ACL wire format */
2515 static __u16 ACL_to_cifs_posix(char * parm_data,const char * pACL,const int buflen,
2519 struct cifs_posix_acl * cifs_acl = (struct cifs_posix_acl *)parm_data;
2520 posix_acl_xattr_header * local_acl = (posix_acl_xattr_header *)pACL;
2524 if((buflen == 0) || (pACL == NULL) || (cifs_acl == NULL))
2527 count = posix_acl_xattr_count((size_t)buflen);
2528 cFYI(1,("setting acl with %d entries from buf of length %d and version of %d",
2529 count, buflen, le32_to_cpu(local_acl->a_version)));
2530 if(le32_to_cpu(local_acl->a_version) != 2) {
2531 cFYI(1,("unknown POSIX ACL version %d",
2532 le32_to_cpu(local_acl->a_version)));
2535 cifs_acl->version = cpu_to_le16(1);
2536 if(acl_type == ACL_TYPE_ACCESS)
2537 cifs_acl->access_entry_count = cpu_to_le16(count);
2538 else if(acl_type == ACL_TYPE_DEFAULT)
2539 cifs_acl->default_entry_count = cpu_to_le16(count);
2541 cFYI(1,("unknown ACL type %d",acl_type));
2544 for(i=0;i<count;i++) {
2545 rc = convert_ace_to_cifs_ace(&cifs_acl->ace_array[i],
2546 &local_acl->a_entries[i]);
2548 /* ACE not converted */
2553 rc = (__u16)(count * sizeof(struct cifs_posix_ace));
2554 rc += sizeof(struct cifs_posix_acl);
2555 /* BB add check to make sure ACL does not overflow SMB */
2561 CIFSSMBGetPosixACL(const int xid, struct cifsTconInfo *tcon,
2562 const unsigned char *searchName,
2563 char *acl_inf, const int buflen, const int acl_type,
2564 const struct nls_table *nls_codepage, int remap)
2566 /* SMB_QUERY_POSIX_ACL */
2567 TRANSACTION2_QPI_REQ *pSMB = NULL;
2568 TRANSACTION2_QPI_RSP *pSMBr = NULL;
2572 __u16 params, byte_count;
2574 cFYI(1, ("In GetPosixACL (Unix) for path %s", searchName));
2577 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2582 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2584 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
2585 PATH_MAX, nls_codepage, remap);
2586 name_len++; /* trailing null */
2588 pSMB->FileName[name_len] = 0;
2589 pSMB->FileName[name_len+1] = 0;
2590 } else { /* BB improve the check for buffer overruns BB */
2591 name_len = strnlen(searchName, PATH_MAX);
2592 name_len++; /* trailing null */
2593 strncpy(pSMB->FileName, searchName, name_len);
2596 params = 2 /* level */ + 4 /* rsrvd */ + name_len /* incl null */ ;
2597 pSMB->TotalDataCount = 0;
2598 pSMB->MaxParameterCount = cpu_to_le16(2);
2599 /* BB find exact max data count below from sess structure BB */
2600 pSMB->MaxDataCount = cpu_to_le16(4000);
2601 pSMB->MaxSetupCount = 0;
2605 pSMB->Reserved2 = 0;
2606 pSMB->ParameterOffset = cpu_to_le16(
2607 offsetof(struct smb_com_transaction2_qpi_req ,InformationLevel) - 4);
2608 pSMB->DataCount = 0;
2609 pSMB->DataOffset = 0;
2610 pSMB->SetupCount = 1;
2611 pSMB->Reserved3 = 0;
2612 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
2613 byte_count = params + 1 /* pad */ ;
2614 pSMB->TotalParameterCount = cpu_to_le16(params);
2615 pSMB->ParameterCount = pSMB->TotalParameterCount;
2616 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_POSIX_ACL);
2617 pSMB->Reserved4 = 0;
2618 pSMB->hdr.smb_buf_length += byte_count;
2619 pSMB->ByteCount = cpu_to_le16(byte_count);
2621 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2622 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2623 cifs_stats_inc(&tcon->num_acl_get);
2625 cFYI(1, ("Send error in Query POSIX ACL = %d", rc));
2627 /* decode response */
2629 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
2630 if (rc || (pSMBr->ByteCount < 2))
2631 /* BB also check enough total bytes returned */
2632 rc = -EIO; /* bad smb */
2634 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
2635 __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
2636 rc = cifs_copy_posix_acl(acl_inf,
2637 (char *)&pSMBr->hdr.Protocol+data_offset,
2638 buflen,acl_type,count);
2641 cifs_buf_release(pSMB);
2648 CIFSSMBSetPosixACL(const int xid, struct cifsTconInfo *tcon,
2649 const unsigned char *fileName,
2650 const char *local_acl, const int buflen,
2652 const struct nls_table *nls_codepage, int remap)
2654 struct smb_com_transaction2_spi_req *pSMB = NULL;
2655 struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
2659 int bytes_returned = 0;
2660 __u16 params, byte_count, data_count, param_offset, offset;
2662 cFYI(1, ("In SetPosixACL (Unix) for path %s", fileName));
2664 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2668 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2670 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
2671 PATH_MAX, nls_codepage, remap);
2672 name_len++; /* trailing null */
2674 } else { /* BB improve the check for buffer overruns BB */
2675 name_len = strnlen(fileName, PATH_MAX);
2676 name_len++; /* trailing null */
2677 strncpy(pSMB->FileName, fileName, name_len);
2679 params = 6 + name_len;
2680 pSMB->MaxParameterCount = cpu_to_le16(2);
2681 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB size from sess */
2682 pSMB->MaxSetupCount = 0;
2686 pSMB->Reserved2 = 0;
2687 param_offset = offsetof(struct smb_com_transaction2_spi_req,
2688 InformationLevel) - 4;
2689 offset = param_offset + params;
2690 parm_data = ((char *) &pSMB->hdr.Protocol) + offset;
2691 pSMB->ParameterOffset = cpu_to_le16(param_offset);
2693 /* convert to on the wire format for POSIX ACL */
2694 data_count = ACL_to_cifs_posix(parm_data,local_acl,buflen,acl_type);
2696 if(data_count == 0) {
2698 goto setACLerrorExit;
2700 pSMB->DataOffset = cpu_to_le16(offset);
2701 pSMB->SetupCount = 1;
2702 pSMB->Reserved3 = 0;
2703 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
2704 pSMB->InformationLevel = cpu_to_le16(SMB_SET_POSIX_ACL);
2705 byte_count = 3 /* pad */ + params + data_count;
2706 pSMB->DataCount = cpu_to_le16(data_count);
2707 pSMB->TotalDataCount = pSMB->DataCount;
2708 pSMB->ParameterCount = cpu_to_le16(params);
2709 pSMB->TotalParameterCount = pSMB->ParameterCount;
2710 pSMB->Reserved4 = 0;
2711 pSMB->hdr.smb_buf_length += byte_count;
2712 pSMB->ByteCount = cpu_to_le16(byte_count);
2713 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2714 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2716 cFYI(1, ("Set POSIX ACL returned %d", rc));
2720 cifs_buf_release(pSMB);
2726 /* BB fix tabs in this function FIXME BB */
2728 CIFSGetExtAttr(const int xid, struct cifsTconInfo *tcon,
2729 const int netfid, __u64 * pExtAttrBits, __u64 *pMask)
2732 struct smb_t2_qfi_req *pSMB = NULL;
2733 struct smb_t2_qfi_rsp *pSMBr = NULL;
2735 __u16 params, byte_count;
2737 cFYI(1,("In GetExtAttr"));
2742 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2747 params = 2 /* level */ +2 /* fid */;
2748 pSMB->t2.TotalDataCount = 0;
2749 pSMB->t2.MaxParameterCount = cpu_to_le16(4);
2750 /* BB find exact max data count below from sess structure BB */
2751 pSMB->t2.MaxDataCount = cpu_to_le16(4000);
2752 pSMB->t2.MaxSetupCount = 0;
2753 pSMB->t2.Reserved = 0;
2755 pSMB->t2.Timeout = 0;
2756 pSMB->t2.Reserved2 = 0;
2757 pSMB->t2.ParameterOffset = cpu_to_le16(offsetof(struct smb_t2_qfi_req,
2759 pSMB->t2.DataCount = 0;
2760 pSMB->t2.DataOffset = 0;
2761 pSMB->t2.SetupCount = 1;
2762 pSMB->t2.Reserved3 = 0;
2763 pSMB->t2.SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION);
2764 byte_count = params + 1 /* pad */ ;
2765 pSMB->t2.TotalParameterCount = cpu_to_le16(params);
2766 pSMB->t2.ParameterCount = pSMB->t2.TotalParameterCount;
2767 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_ATTR_FLAGS);
2770 pSMB->hdr.smb_buf_length += byte_count;
2771 pSMB->t2.ByteCount = cpu_to_le16(byte_count);
2773 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2774 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2776 cFYI(1, ("error %d in GetExtAttr", rc));
2778 /* decode response */
2779 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
2780 if (rc || (pSMBr->ByteCount < 2))
2781 /* BB also check enough total bytes returned */
2782 /* If rc should we check for EOPNOSUPP and
2783 disable the srvino flag? or in caller? */
2784 rc = -EIO; /* bad smb */
2786 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
2787 __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
2788 struct file_chattr_info * pfinfo;
2789 /* BB Do we need a cast or hash here ? */
2791 cFYI(1, ("Illegal size ret in GetExtAttr"));
2795 pfinfo = (struct file_chattr_info *)
2796 (data_offset + (char *) &pSMBr->hdr.Protocol);
2797 *pExtAttrBits = le64_to_cpu(pfinfo->mode);
2798 *pMask = le64_to_cpu(pfinfo->mask);
2802 cifs_buf_release(pSMB);
2804 goto GetExtAttrRetry;
2809 #endif /* CONFIG_POSIX */
2812 /* security id for everyone */
2813 const static struct cifs_sid sid_everyone =
2814 {1, 1, {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0}};
2816 const static struct cifs_sid sid_user =
2817 {1, 2 , {0, 0, 0, 0, 0, 5}, {32, 545, 0, 0}};
2819 /* Convert CIFS ACL to POSIX form */
2820 static int parse_sec_desc(struct cifs_sid * psec_desc, int acl_len)
2825 /* Get Security Descriptor (by handle) from remote server for a file or dir */
2827 CIFSSMBGetCIFSACL(const int xid, struct cifsTconInfo *tcon, __u16 fid,
2828 /* BB fix up return info */ char *acl_inf, const int buflen,
2829 const int acl_type /* ACCESS/DEFAULT not sure implication */)
2833 QUERY_SEC_DESC_REQ * pSMB;
2836 cFYI(1, ("GetCifsACL"));
2838 rc = smb_init_ntransact(NT_TRANSACT_QUERY_SECURITY_DESC, 0,
2839 8 /* parm len */, tcon, (void **) &pSMB);
2843 pSMB->MaxParameterCount = cpu_to_le32(4);
2844 /* BB TEST with big acls that might need to be e.g. larger than 16K */
2845 pSMB->MaxSetupCount = 0;
2846 pSMB->Fid = fid; /* file handle always le */
2847 pSMB->AclFlags = cpu_to_le32(CIFS_ACL_OWNER | CIFS_ACL_GROUP |
2849 pSMB->ByteCount = cpu_to_le16(11); /* 3 bytes pad + 8 bytes parm */
2850 pSMB->hdr.smb_buf_length += 11;
2851 iov[0].iov_base = (char *)pSMB;
2852 iov[0].iov_len = pSMB->hdr.smb_buf_length + 4;
2854 rc = SendReceive2(xid, tcon->ses, iov, 1 /* num iovec */, &buf_type, 0);
2855 cifs_stats_inc(&tcon->num_acl_get);
2857 cFYI(1, ("Send error in QuerySecDesc = %d", rc));
2858 } else { /* decode response */
2859 struct cifs_sid * psec_desc;
2864 struct smb_com_ntransact_rsp * pSMBr;
2866 /* validate_nttransact */
2867 rc = validate_ntransact(iov[0].iov_base, (char **)&parm,
2868 (char **)&psec_desc,
2869 &parm_len, &data_len);
2873 pSMBr = (struct smb_com_ntransact_rsp *)iov[0].iov_base;
2875 cERROR(1,("smb %p parm %p data %p",pSMBr,parm,psec_desc)); /* BB removeme BB */
2877 if (le32_to_cpu(pSMBr->ParameterCount) != 4) {
2878 rc = -EIO; /* bad smb */
2882 /* BB check that data area is minimum length and as big as acl_len */
2884 acl_len = le32_to_cpu(*(__le32 *)parm);
2885 /* BB check if(acl_len > bufsize) */
2887 parse_sec_desc(psec_desc, acl_len);
2890 if(buf_type == CIFS_SMALL_BUFFER)
2891 cifs_small_buf_release(iov[0].iov_base);
2892 else if(buf_type == CIFS_LARGE_BUFFER)
2893 cifs_buf_release(iov[0].iov_base);
2894 /* cifs_small_buf_release(pSMB); */ /* Freed earlier now in SendReceive2 */
2898 /* Legacy Query Path Information call for lookup to old servers such
2900 int SMBQueryInformation(const int xid, struct cifsTconInfo *tcon,
2901 const unsigned char *searchName,
2902 FILE_ALL_INFO * pFinfo,
2903 const struct nls_table *nls_codepage, int remap)
2905 QUERY_INFORMATION_REQ * pSMB;
2906 QUERY_INFORMATION_RSP * pSMBr;
2911 cFYI(1, ("In SMBQPath path %s", searchName));
2913 rc = smb_init(SMB_COM_QUERY_INFORMATION, 0, tcon, (void **) &pSMB,
2918 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2920 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
2921 PATH_MAX, nls_codepage, remap);
2922 name_len++; /* trailing null */
2925 name_len = strnlen(searchName, PATH_MAX);
2926 name_len++; /* trailing null */
2927 strncpy(pSMB->FileName, searchName, name_len);
2929 pSMB->BufferFormat = 0x04;
2930 name_len++; /* account for buffer type byte */
2931 pSMB->hdr.smb_buf_length += (__u16) name_len;
2932 pSMB->ByteCount = cpu_to_le16(name_len);
2934 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2935 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2937 cFYI(1, ("Send error in QueryInfo = %d", rc));
2938 } else if (pFinfo) { /* decode response */
2940 __u32 time = le32_to_cpu(pSMBr->last_write_time);
2941 /* BB FIXME - add time zone adjustment BB */
2942 memset(pFinfo, 0, sizeof(FILE_ALL_INFO));
2945 /* decode time fields */
2946 pFinfo->ChangeTime = cifs_UnixTimeToNT(ts);
2947 pFinfo->LastWriteTime = pFinfo->ChangeTime;
2948 pFinfo->LastAccessTime = 0;
2949 pFinfo->AllocationSize =
2950 cpu_to_le64(le32_to_cpu(pSMBr->size));
2951 pFinfo->EndOfFile = pFinfo->AllocationSize;
2952 pFinfo->Attributes =
2953 cpu_to_le32(le16_to_cpu(pSMBr->attr));
2955 rc = -EIO; /* bad buffer passed in */
2957 cifs_buf_release(pSMB);
2969 CIFSSMBQPathInfo(const int xid, struct cifsTconInfo *tcon,
2970 const unsigned char *searchName,
2971 FILE_ALL_INFO * pFindData,
2972 const struct nls_table *nls_codepage, int remap)
2974 /* level 263 SMB_QUERY_FILE_ALL_INFO */
2975 TRANSACTION2_QPI_REQ *pSMB = NULL;
2976 TRANSACTION2_QPI_RSP *pSMBr = NULL;
2980 __u16 params, byte_count;
2982 /* cFYI(1, ("In QPathInfo path %s", searchName)); */
2984 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2989 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2991 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
2992 PATH_MAX, nls_codepage, remap);
2993 name_len++; /* trailing null */
2995 } else { /* BB improve the check for buffer overruns BB */
2996 name_len = strnlen(searchName, PATH_MAX);
2997 name_len++; /* trailing null */
2998 strncpy(pSMB->FileName, searchName, name_len);
3001 params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */ ;
3002 pSMB->TotalDataCount = 0;
3003 pSMB->MaxParameterCount = cpu_to_le16(2);
3004 pSMB->MaxDataCount = cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
3005 pSMB->MaxSetupCount = 0;
3009 pSMB->Reserved2 = 0;
3010 pSMB->ParameterOffset = cpu_to_le16(offsetof(
3011 struct smb_com_transaction2_qpi_req ,InformationLevel) - 4);
3012 pSMB->DataCount = 0;
3013 pSMB->DataOffset = 0;
3014 pSMB->SetupCount = 1;
3015 pSMB->Reserved3 = 0;
3016 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
3017 byte_count = params + 1 /* pad */ ;
3018 pSMB->TotalParameterCount = cpu_to_le16(params);
3019 pSMB->ParameterCount = pSMB->TotalParameterCount;
3020 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_ALL_INFO);
3021 pSMB->Reserved4 = 0;
3022 pSMB->hdr.smb_buf_length += byte_count;
3023 pSMB->ByteCount = cpu_to_le16(byte_count);
3025 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3026 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3028 cFYI(1, ("Send error in QPathInfo = %d", rc));
3029 } else { /* decode response */
3030 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3032 if (rc || (pSMBr->ByteCount < 40))
3033 rc = -EIO; /* bad smb */
3034 else if (pFindData){
3035 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3036 memcpy((char *) pFindData,
3037 (char *) &pSMBr->hdr.Protocol +
3038 data_offset, sizeof (FILE_ALL_INFO));
3042 cifs_buf_release(pSMB);
3044 goto QPathInfoRetry;
3050 CIFSSMBUnixQPathInfo(const int xid, struct cifsTconInfo *tcon,
3051 const unsigned char *searchName,
3052 FILE_UNIX_BASIC_INFO * pFindData,
3053 const struct nls_table *nls_codepage, int remap)
3055 /* SMB_QUERY_FILE_UNIX_BASIC */
3056 TRANSACTION2_QPI_REQ *pSMB = NULL;
3057 TRANSACTION2_QPI_RSP *pSMBr = NULL;
3059 int bytes_returned = 0;
3061 __u16 params, byte_count;
3063 cFYI(1, ("In QPathInfo (Unix) the path %s", searchName));
3065 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3070 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3072 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
3073 PATH_MAX, nls_codepage, remap);
3074 name_len++; /* trailing null */
3076 } else { /* BB improve the check for buffer overruns BB */
3077 name_len = strnlen(searchName, PATH_MAX);
3078 name_len++; /* trailing null */
3079 strncpy(pSMB->FileName, searchName, name_len);
3082 params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */ ;
3083 pSMB->TotalDataCount = 0;
3084 pSMB->MaxParameterCount = cpu_to_le16(2);
3085 /* BB find exact max SMB PDU from sess structure BB */
3086 pSMB->MaxDataCount = cpu_to_le16(4000);
3087 pSMB->MaxSetupCount = 0;
3091 pSMB->Reserved2 = 0;
3092 pSMB->ParameterOffset = cpu_to_le16(offsetof(
3093 struct smb_com_transaction2_qpi_req ,InformationLevel) - 4);
3094 pSMB->DataCount = 0;
3095 pSMB->DataOffset = 0;
3096 pSMB->SetupCount = 1;
3097 pSMB->Reserved3 = 0;
3098 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
3099 byte_count = params + 1 /* pad */ ;
3100 pSMB->TotalParameterCount = cpu_to_le16(params);
3101 pSMB->ParameterCount = pSMB->TotalParameterCount;
3102 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC);
3103 pSMB->Reserved4 = 0;
3104 pSMB->hdr.smb_buf_length += byte_count;
3105 pSMB->ByteCount = cpu_to_le16(byte_count);
3107 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3108 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3110 cFYI(1, ("Send error in QPathInfo = %d", rc));
3111 } else { /* decode response */
3112 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3114 if (rc || (pSMBr->ByteCount < sizeof(FILE_UNIX_BASIC_INFO))) {
3115 rc = -EIO; /* bad smb */
3117 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3118 memcpy((char *) pFindData,
3119 (char *) &pSMBr->hdr.Protocol +
3121 sizeof (FILE_UNIX_BASIC_INFO));
3124 cifs_buf_release(pSMB);
3126 goto UnixQPathInfoRetry;
3131 #if 0 /* function unused at present */
3132 int CIFSFindSingle(const int xid, struct cifsTconInfo *tcon,
3133 const char *searchName, FILE_ALL_INFO * findData,
3134 const struct nls_table *nls_codepage)
3136 /* level 257 SMB_ */
3137 TRANSACTION2_FFIRST_REQ *pSMB = NULL;
3138 TRANSACTION2_FFIRST_RSP *pSMBr = NULL;
3142 __u16 params, byte_count;
3144 cFYI(1, ("In FindUnique"));
3146 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3151 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3153 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName, PATH_MAX
3154 /* find define for this maxpathcomponent */
3156 name_len++; /* trailing null */
3158 } else { /* BB improve the check for buffer overruns BB */
3159 name_len = strnlen(searchName, PATH_MAX);
3160 name_len++; /* trailing null */
3161 strncpy(pSMB->FileName, searchName, name_len);
3164 params = 12 + name_len /* includes null */ ;
3165 pSMB->TotalDataCount = 0; /* no EAs */
3166 pSMB->MaxParameterCount = cpu_to_le16(2);
3167 pSMB->MaxDataCount = cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
3168 pSMB->MaxSetupCount = 0;
3172 pSMB->Reserved2 = 0;
3173 pSMB->ParameterOffset = cpu_to_le16(
3174 offsetof(struct smb_com_transaction2_ffirst_req,InformationLevel) - 4);
3175 pSMB->DataCount = 0;
3176 pSMB->DataOffset = 0;
3177 pSMB->SetupCount = 1; /* one byte, no need to le convert */
3178 pSMB->Reserved3 = 0;
3179 pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_FIRST);
3180 byte_count = params + 1 /* pad */ ;
3181 pSMB->TotalParameterCount = cpu_to_le16(params);
3182 pSMB->ParameterCount = pSMB->TotalParameterCount;
3183 pSMB->SearchAttributes =
3184 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
3186 pSMB->SearchCount = cpu_to_le16(16); /* BB increase */
3187 pSMB->SearchFlags = cpu_to_le16(1);
3188 pSMB->InformationLevel = cpu_to_le16(SMB_FIND_FILE_DIRECTORY_INFO);
3189 pSMB->SearchStorageType = 0; /* BB what should we set this to? BB */
3190 pSMB->hdr.smb_buf_length += byte_count;
3191 pSMB->ByteCount = cpu_to_le16(byte_count);
3193 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3194 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3197 cFYI(1, ("Send error in FindFileDirInfo = %d", rc));
3198 } else { /* decode response */
3199 cifs_stats_inc(&tcon->num_ffirst);
3203 cifs_buf_release(pSMB);
3205 goto findUniqueRetry;
3209 #endif /* end unused (temporarily) function */
3211 /* xid, tcon, searchName and codepage are input parms, rest are returned */
3213 CIFSFindFirst(const int xid, struct cifsTconInfo *tcon,
3214 const char *searchName,
3215 const struct nls_table *nls_codepage,
3217 struct cifs_search_info * psrch_inf, int remap, const char dirsep)
3219 /* level 257 SMB_ */
3220 TRANSACTION2_FFIRST_REQ *pSMB = NULL;
3221 TRANSACTION2_FFIRST_RSP *pSMBr = NULL;
3222 T2_FFIRST_RSP_PARMS * parms;
3224 int bytes_returned = 0;
3226 __u16 params, byte_count;
3228 cFYI(1, ("In FindFirst for %s",searchName));
3231 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3236 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3238 cifsConvertToUCS((__le16 *) pSMB->FileName,searchName,
3239 PATH_MAX, nls_codepage, remap);
3240 /* We can not add the asterik earlier in case
3241 it got remapped to 0xF03A as if it were part of the
3242 directory name instead of a wildcard */
3244 pSMB->FileName[name_len] = dirsep;
3245 pSMB->FileName[name_len+1] = 0;
3246 pSMB->FileName[name_len+2] = '*';
3247 pSMB->FileName[name_len+3] = 0;
3248 name_len += 4; /* now the trailing null */
3249 pSMB->FileName[name_len] = 0; /* null terminate just in case */
3250 pSMB->FileName[name_len+1] = 0;
3252 } else { /* BB add check for overrun of SMB buf BB */
3253 name_len = strnlen(searchName, PATH_MAX);
3254 /* BB fix here and in unicode clause above ie
3255 if(name_len > buffersize-header)
3256 free buffer exit; BB */
3257 strncpy(pSMB->FileName, searchName, name_len);
3258 pSMB->FileName[name_len] = dirsep;
3259 pSMB->FileName[name_len+1] = '*';
3260 pSMB->FileName[name_len+2] = 0;
3264 params = 12 + name_len /* includes null */ ;
3265 pSMB->TotalDataCount = 0; /* no EAs */
3266 pSMB->MaxParameterCount = cpu_to_le16(10);
3267 pSMB->MaxDataCount = cpu_to_le16((tcon->ses->server->maxBuf -
3268 MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
3269 pSMB->MaxSetupCount = 0;
3273 pSMB->Reserved2 = 0;
3274 byte_count = params + 1 /* pad */ ;
3275 pSMB->TotalParameterCount = cpu_to_le16(params);
3276 pSMB->ParameterCount = pSMB->TotalParameterCount;
3277 pSMB->ParameterOffset = cpu_to_le16(
3278 offsetof(struct smb_com_transaction2_ffirst_req, SearchAttributes)
3280 pSMB->DataCount = 0;
3281 pSMB->DataOffset = 0;
3282 pSMB->SetupCount = 1; /* one byte, no need to make endian neutral */
3283 pSMB->Reserved3 = 0;
3284 pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_FIRST);
3285 pSMB->SearchAttributes =
3286 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
3288 pSMB->SearchCount= cpu_to_le16(CIFSMaxBufSize/sizeof(FILE_UNIX_INFO));
3289 pSMB->SearchFlags = cpu_to_le16(CIFS_SEARCH_CLOSE_AT_END |
3290 CIFS_SEARCH_RETURN_RESUME);
3291 pSMB->InformationLevel = cpu_to_le16(psrch_inf->info_level);
3293 /* BB what should we set StorageType to? Does it matter? BB */
3294 pSMB->SearchStorageType = 0;
3295 pSMB->hdr.smb_buf_length += byte_count;
3296 pSMB->ByteCount = cpu_to_le16(byte_count);
3298 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3299 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3300 cifs_stats_inc(&tcon->num_ffirst);
3302 if (rc) {/* BB add logic to retry regular search if Unix search
3303 rejected unexpectedly by server */
3304 /* BB Add code to handle unsupported level rc */
3305 cFYI(1, ("Error in FindFirst = %d", rc));
3307 cifs_buf_release(pSMB);
3309 /* BB eventually could optimize out free and realloc of buf */
3312 goto findFirstRetry;
3313 } else { /* decode response */
3314 /* BB remember to free buffer if error BB */
3315 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3317 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
3318 psrch_inf->unicode = TRUE;
3320 psrch_inf->unicode = FALSE;
3322 psrch_inf->ntwrk_buf_start = (char *)pSMBr;
3323 psrch_inf->smallBuf = 0;
3324 psrch_inf->srch_entries_start =
3325 (char *) &pSMBr->hdr.Protocol +
3326 le16_to_cpu(pSMBr->t2.DataOffset);
3327 parms = (T2_FFIRST_RSP_PARMS *)((char *) &pSMBr->hdr.Protocol +
3328 le16_to_cpu(pSMBr->t2.ParameterOffset));
3330 if(parms->EndofSearch)
3331 psrch_inf->endOfSearch = TRUE;
3333 psrch_inf->endOfSearch = FALSE;
3335 psrch_inf->entries_in_buffer = le16_to_cpu(parms->SearchCount);
3336 psrch_inf->index_of_last_entry = 2 /* skip . and .. */ +
3337 psrch_inf->entries_in_buffer;
3338 *pnetfid = parms->SearchHandle;
3340 cifs_buf_release(pSMB);
3347 int CIFSFindNext(const int xid, struct cifsTconInfo *tcon,
3348 __u16 searchHandle, struct cifs_search_info * psrch_inf)
3350 TRANSACTION2_FNEXT_REQ *pSMB = NULL;
3351 TRANSACTION2_FNEXT_RSP *pSMBr = NULL;
3352 T2_FNEXT_RSP_PARMS * parms;
3353 char *response_data;
3355 int bytes_returned, name_len;
3356 __u16 params, byte_count;
3358 cFYI(1, ("In FindNext"));
3360 if(psrch_inf->endOfSearch == TRUE)
3363 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3368 params = 14; /* includes 2 bytes of null string, converted to LE below */
3370 pSMB->TotalDataCount = 0; /* no EAs */
3371 pSMB->MaxParameterCount = cpu_to_le16(8);
3372 pSMB->MaxDataCount =
3373 cpu_to_le16((tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
3374 pSMB->MaxSetupCount = 0;
3378 pSMB->Reserved2 = 0;
3379 pSMB->ParameterOffset = cpu_to_le16(
3380 offsetof(struct smb_com_transaction2_fnext_req,SearchHandle) - 4);
3381 pSMB->DataCount = 0;
3382 pSMB->DataOffset = 0;
3383 pSMB->SetupCount = 1;
3384 pSMB->Reserved3 = 0;
3385 pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_NEXT);
3386 pSMB->SearchHandle = searchHandle; /* always kept as le */
3388 cpu_to_le16(CIFSMaxBufSize / sizeof (FILE_UNIX_INFO));
3389 /* test for Unix extensions */
3390 /* if (tcon->ses->capabilities & CAP_UNIX) {
3391 pSMB->InformationLevel = cpu_to_le16(SMB_FIND_FILE_UNIX);
3392 psrch_inf->info_level = SMB_FIND_FILE_UNIX;
3394 pSMB->InformationLevel =
3395 cpu_to_le16(SMB_FIND_FILE_DIRECTORY_INFO);
3396 psrch_inf->info_level = SMB_FIND_FILE_DIRECTORY_INFO;
3398 pSMB->InformationLevel = cpu_to_le16(psrch_inf->info_level);
3399 pSMB->ResumeKey = psrch_inf->resume_key;
3401 cpu_to_le16(CIFS_SEARCH_CLOSE_AT_END | CIFS_SEARCH_RETURN_RESUME);
3403 name_len = psrch_inf->resume_name_len;
3405 if(name_len < PATH_MAX) {
3406 memcpy(pSMB->ResumeFileName, psrch_inf->presume_name, name_len);
3407 byte_count += name_len;
3408 /* 14 byte parm len above enough for 2 byte null terminator */
3409 pSMB->ResumeFileName[name_len] = 0;
3410 pSMB->ResumeFileName[name_len+1] = 0;
3413 goto FNext2_err_exit;
3415 byte_count = params + 1 /* pad */ ;
3416 pSMB->TotalParameterCount = cpu_to_le16(params);
3417 pSMB->ParameterCount = pSMB->TotalParameterCount;
3418 pSMB->hdr.smb_buf_length += byte_count;
3419 pSMB->ByteCount = cpu_to_le16(byte_count);
3421 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3422 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3423 cifs_stats_inc(&tcon->num_fnext);
3426 psrch_inf->endOfSearch = TRUE;
3427 rc = 0; /* search probably was closed at end of search above */
3429 cFYI(1, ("FindNext returned = %d", rc));
3430 } else { /* decode response */
3431 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3434 /* BB fixme add lock for file (srch_info) struct here */
3435 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
3436 psrch_inf->unicode = TRUE;
3438 psrch_inf->unicode = FALSE;
3439 response_data = (char *) &pSMBr->hdr.Protocol +
3440 le16_to_cpu(pSMBr->t2.ParameterOffset);
3441 parms = (T2_FNEXT_RSP_PARMS *)response_data;
3442 response_data = (char *)&pSMBr->hdr.Protocol +
3443 le16_to_cpu(pSMBr->t2.DataOffset);
3444 if(psrch_inf->smallBuf)
3445 cifs_small_buf_release(
3446 psrch_inf->ntwrk_buf_start);
3448 cifs_buf_release(psrch_inf->ntwrk_buf_start);
3449 psrch_inf->srch_entries_start = response_data;
3450 psrch_inf->ntwrk_buf_start = (char *)pSMB;
3451 psrch_inf->smallBuf = 0;
3452 if(parms->EndofSearch)
3453 psrch_inf->endOfSearch = TRUE;
3455 psrch_inf->endOfSearch = FALSE;
3457 psrch_inf->entries_in_buffer = le16_to_cpu(parms->SearchCount);
3458 psrch_inf->index_of_last_entry +=
3459 psrch_inf->entries_in_buffer;
3460 /* cFYI(1,("fnxt2 entries in buf %d index_of_last %d",psrch_inf->entries_in_buffer,psrch_inf->index_of_last_entry)); */
3462 /* BB fixme add unlock here */
3467 /* BB On error, should we leave previous search buf (and count and
3468 last entry fields) intact or free the previous one? */
3470 /* Note: On -EAGAIN error only caller can retry on handle based calls
3471 since file handle passed in no longer valid */
3474 cifs_buf_release(pSMB);
3480 CIFSFindClose(const int xid, struct cifsTconInfo *tcon, const __u16 searchHandle)
3483 FINDCLOSE_REQ *pSMB = NULL;
3484 CLOSE_RSP *pSMBr = NULL; /* BB removeme BB */
3487 cFYI(1, ("In CIFSSMBFindClose"));
3488 rc = small_smb_init(SMB_COM_FIND_CLOSE2, 1, tcon, (void **)&pSMB);
3490 /* no sense returning error if session restarted
3491 as file handle has been closed */
3497 pSMBr = (CLOSE_RSP *)pSMB; /* BB removeme BB */
3498 pSMB->FileID = searchHandle;
3499 pSMB->ByteCount = 0;
3500 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3501 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3503 cERROR(1, ("Send error in FindClose = %d", rc));
3505 cifs_stats_inc(&tcon->num_fclose);
3506 cifs_small_buf_release(pSMB);
3508 /* Since session is dead, search handle closed on server already */
3516 CIFSGetSrvInodeNumber(const int xid, struct cifsTconInfo *tcon,
3517 const unsigned char *searchName,
3518 __u64 * inode_number,
3519 const struct nls_table *nls_codepage, int remap)
3522 TRANSACTION2_QPI_REQ *pSMB = NULL;
3523 TRANSACTION2_QPI_RSP *pSMBr = NULL;
3524 int name_len, bytes_returned;
3525 __u16 params, byte_count;
3527 cFYI(1,("In GetSrvInodeNum for %s",searchName));
3531 GetInodeNumberRetry:
3532 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3538 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3540 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
3541 PATH_MAX,nls_codepage, remap);
3542 name_len++; /* trailing null */
3544 } else { /* BB improve the check for buffer overruns BB */
3545 name_len = strnlen(searchName, PATH_MAX);
3546 name_len++; /* trailing null */
3547 strncpy(pSMB->FileName, searchName, name_len);
3550 params = 2 /* level */ + 4 /* rsrvd */ + name_len /* incl null */ ;
3551 pSMB->TotalDataCount = 0;
3552 pSMB->MaxParameterCount = cpu_to_le16(2);
3553 /* BB find exact max data count below from sess structure BB */
3554 pSMB->MaxDataCount = cpu_to_le16(4000);
3555 pSMB->MaxSetupCount = 0;
3559 pSMB->Reserved2 = 0;
3560 pSMB->ParameterOffset = cpu_to_le16(offsetof(
3561 struct smb_com_transaction2_qpi_req ,InformationLevel) - 4);
3562 pSMB->DataCount = 0;
3563 pSMB->DataOffset = 0;
3564 pSMB->SetupCount = 1;
3565 pSMB->Reserved3 = 0;
3566 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
3567 byte_count = params + 1 /* pad */ ;
3568 pSMB->TotalParameterCount = cpu_to_le16(params);
3569 pSMB->ParameterCount = pSMB->TotalParameterCount;
3570 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_INTERNAL_INFO);
3571 pSMB->Reserved4 = 0;
3572 pSMB->hdr.smb_buf_length += byte_count;
3573 pSMB->ByteCount = cpu_to_le16(byte_count);
3575 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3576 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3578 cFYI(1, ("error %d in QueryInternalInfo", rc));
3580 /* decode response */
3581 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3582 if (rc || (pSMBr->ByteCount < 2))
3583 /* BB also check enough total bytes returned */
3584 /* If rc should we check for EOPNOSUPP and
3585 disable the srvino flag? or in caller? */
3586 rc = -EIO; /* bad smb */
3588 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3589 __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
3590 struct file_internal_info * pfinfo;
3591 /* BB Do we need a cast or hash here ? */
3593 cFYI(1, ("Illegal size ret in QryIntrnlInf"));
3595 goto GetInodeNumOut;
3597 pfinfo = (struct file_internal_info *)
3598 (data_offset + (char *) &pSMBr->hdr.Protocol);
3599 *inode_number = pfinfo->UniqueId;
3603 cifs_buf_release(pSMB);
3605 goto GetInodeNumberRetry;
3610 CIFSGetDFSRefer(const int xid, struct cifsSesInfo *ses,
3611 const unsigned char *searchName,
3612 unsigned char **targetUNCs,
3613 unsigned int *number_of_UNC_in_array,
3614 const struct nls_table *nls_codepage, int remap)
3616 /* TRANS2_GET_DFS_REFERRAL */
3617 TRANSACTION2_GET_DFS_REFER_REQ *pSMB = NULL;
3618 TRANSACTION2_GET_DFS_REFER_RSP *pSMBr = NULL;
3619 struct dfs_referral_level_3 * referrals = NULL;
3625 __u16 params, byte_count;
3626 *number_of_UNC_in_array = 0;
3629 cFYI(1, ("In GetDFSRefer the path %s", searchName));
3633 rc = smb_init(SMB_COM_TRANSACTION2, 15, NULL, (void **) &pSMB,
3638 /* server pointer checked in called function,
3639 but should never be null here anyway */
3640 pSMB->hdr.Mid = GetNextMid(ses->server);
3641 pSMB->hdr.Tid = ses->ipc_tid;
3642 pSMB->hdr.Uid = ses->Suid;
3643 if (ses->capabilities & CAP_STATUS32) {
3644 pSMB->hdr.Flags2 |= SMBFLG2_ERR_STATUS;
3646 if (ses->capabilities & CAP_DFS) {
3647 pSMB->hdr.Flags2 |= SMBFLG2_DFS;
3650 if (ses->capabilities & CAP_UNICODE) {
3651 pSMB->hdr.Flags2 |= SMBFLG2_UNICODE;
3653 cifsConvertToUCS((__le16 *) pSMB->RequestFileName,
3654 searchName, PATH_MAX, nls_codepage, remap);
3655 name_len++; /* trailing null */
3657 } else { /* BB improve the check for buffer overruns BB */
3658 name_len = strnlen(searchName, PATH_MAX);
3659 name_len++; /* trailing null */
3660 strncpy(pSMB->RequestFileName, searchName, name_len);
3663 params = 2 /* level */ + name_len /*includes null */ ;
3664 pSMB->TotalDataCount = 0;
3665 pSMB->DataCount = 0;
3666 pSMB->DataOffset = 0;
3667 pSMB->MaxParameterCount = 0;
3668 pSMB->MaxDataCount = cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
3669 pSMB->MaxSetupCount = 0;
3673 pSMB->Reserved2 = 0;
3674 pSMB->ParameterOffset = cpu_to_le16(offsetof(
3675 struct smb_com_transaction2_get_dfs_refer_req, MaxReferralLevel) - 4);
3676 pSMB->SetupCount = 1;
3677 pSMB->Reserved3 = 0;
3678 pSMB->SubCommand = cpu_to_le16(TRANS2_GET_DFS_REFERRAL);
3679 byte_count = params + 3 /* pad */ ;
3680 pSMB->ParameterCount = cpu_to_le16(params);
3681 pSMB->TotalParameterCount = pSMB->ParameterCount;
3682 pSMB->MaxReferralLevel = cpu_to_le16(3);
3683 pSMB->hdr.smb_buf_length += byte_count;
3684 pSMB->ByteCount = cpu_to_le16(byte_count);
3686 rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB,
3687 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3689 cFYI(1, ("Send error in GetDFSRefer = %d", rc));
3690 } else { /* decode response */
3691 /* BB Add logic to parse referrals here */
3692 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3694 if (rc || (pSMBr->ByteCount < 17)) /* BB also check enough total bytes returned */
3695 rc = -EIO; /* bad smb */
3697 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3698 __u16 data_count = le16_to_cpu(pSMBr->t2.DataCount);
3701 ("Decoding GetDFSRefer response. BCC: %d Offset %d",
3702 pSMBr->ByteCount, data_offset));
3704 (struct dfs_referral_level_3 *)
3705 (8 /* sizeof start of data block */ +
3707 (char *) &pSMBr->hdr.Protocol);
3708 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",
3709 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)));
3710 /* BB This field is actually two bytes in from start of
3711 data block so we could do safety check that DataBlock
3712 begins at address of pSMBr->NumberOfReferrals */
3713 *number_of_UNC_in_array = le16_to_cpu(pSMBr->NumberOfReferrals);
3715 /* BB Fix below so can return more than one referral */
3716 if(*number_of_UNC_in_array > 1)
3717 *number_of_UNC_in_array = 1;
3719 /* get the length of the strings describing refs */
3721 for(i=0;i<*number_of_UNC_in_array;i++) {
3722 /* make sure that DfsPathOffset not past end */
3723 __u16 offset = le16_to_cpu(referrals->DfsPathOffset);
3724 if (offset > data_count) {
3725 /* if invalid referral, stop here and do
3726 not try to copy any more */
3727 *number_of_UNC_in_array = i;
3730 temp = ((char *)referrals) + offset;
3732 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
3733 name_len += UniStrnlen((wchar_t *)temp,data_count);
3735 name_len += strnlen(temp,data_count);
3738 /* BB add check that referral pointer does not fall off end PDU */
3741 /* BB add check for name_len bigger than bcc */
3743 kmalloc(name_len+1+ (*number_of_UNC_in_array),GFP_KERNEL);
3744 if(*targetUNCs == NULL) {
3748 /* copy the ref strings */
3750 (struct dfs_referral_level_3 *)
3751 (8 /* sizeof data hdr */ +
3753 (char *) &pSMBr->hdr.Protocol);
3755 for(i=0;i<*number_of_UNC_in_array;i++) {
3756 temp = ((char *)referrals) + le16_to_cpu(referrals->DfsPathOffset);
3757 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
3758 cifs_strfromUCS_le(*targetUNCs,
3759 (__le16 *) temp, name_len, nls_codepage);
3761 strncpy(*targetUNCs,temp,name_len);
3763 /* BB update target_uncs pointers */
3773 cifs_buf_release(pSMB);
3781 /* Query File System Info such as free space to old servers such as Win 9x */
3783 SMBOldQFSInfo(const int xid, struct cifsTconInfo *tcon, struct kstatfs *FSData)
3785 /* level 0x01 SMB_QUERY_FILE_SYSTEM_INFO */
3786 TRANSACTION2_QFSI_REQ *pSMB = NULL;
3787 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
3788 FILE_SYSTEM_ALLOC_INFO *response_data;
3790 int bytes_returned = 0;
3791 __u16 params, byte_count;
3793 cFYI(1, ("OldQFSInfo"));
3795 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3799 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3804 params = 2; /* level */
3805 pSMB->TotalDataCount = 0;
3806 pSMB->MaxParameterCount = cpu_to_le16(2);
3807 pSMB->MaxDataCount = cpu_to_le16(1000);
3808 pSMB->MaxSetupCount = 0;
3812 pSMB->Reserved2 = 0;
3813 byte_count = params + 1 /* pad */ ;
3814 pSMB->TotalParameterCount = cpu_to_le16(params);
3815 pSMB->ParameterCount = pSMB->TotalParameterCount;
3816 pSMB->ParameterOffset = cpu_to_le16(offsetof(
3817 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
3818 pSMB->DataCount = 0;
3819 pSMB->DataOffset = 0;
3820 pSMB->SetupCount = 1;
3821 pSMB->Reserved3 = 0;
3822 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
3823 pSMB->InformationLevel = cpu_to_le16(SMB_INFO_ALLOCATION);
3824 pSMB->hdr.smb_buf_length += byte_count;
3825 pSMB->ByteCount = cpu_to_le16(byte_count);
3827 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3828 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3830 cFYI(1, ("Send error in QFSInfo = %d", rc));
3831 } else { /* decode response */
3832 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3834 if (rc || (pSMBr->ByteCount < 18))
3835 rc = -EIO; /* bad smb */
3837 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3838 cFYI(1,("qfsinf resp BCC: %d Offset %d",
3839 pSMBr->ByteCount, data_offset));
3842 (FILE_SYSTEM_ALLOC_INFO *)
3843 (((char *) &pSMBr->hdr.Protocol) + data_offset);
3845 le16_to_cpu(response_data->BytesPerSector) *
3846 le32_to_cpu(response_data->
3847 SectorsPerAllocationUnit);
3849 le32_to_cpu(response_data->TotalAllocationUnits);
3850 FSData->f_bfree = FSData->f_bavail =
3851 le32_to_cpu(response_data->FreeAllocationUnits);
3853 ("Blocks: %lld Free: %lld Block size %ld",
3854 (unsigned long long)FSData->f_blocks,
3855 (unsigned long long)FSData->f_bfree,
3859 cifs_buf_release(pSMB);
3862 goto oldQFSInfoRetry;
3868 CIFSSMBQFSInfo(const int xid, struct cifsTconInfo *tcon, struct kstatfs *FSData)
3870 /* level 0x103 SMB_QUERY_FILE_SYSTEM_INFO */
3871 TRANSACTION2_QFSI_REQ *pSMB = NULL;
3872 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
3873 FILE_SYSTEM_INFO *response_data;
3875 int bytes_returned = 0;
3876 __u16 params, byte_count;
3878 cFYI(1, ("In QFSInfo"));
3880 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3885 params = 2; /* level */
3886 pSMB->TotalDataCount = 0;
3887 pSMB->MaxParameterCount = cpu_to_le16(2);
3888 pSMB->MaxDataCount = cpu_to_le16(1000);
3889 pSMB->MaxSetupCount = 0;
3893 pSMB->Reserved2 = 0;
3894 byte_count = params + 1 /* pad */ ;
3895 pSMB->TotalParameterCount = cpu_to_le16(params);
3896 pSMB->ParameterCount = pSMB->TotalParameterCount;
3897 pSMB->ParameterOffset = cpu_to_le16(offsetof(
3898 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
3899 pSMB->DataCount = 0;
3900 pSMB->DataOffset = 0;
3901 pSMB->SetupCount = 1;
3902 pSMB->Reserved3 = 0;
3903 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
3904 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_SIZE_INFO);
3905 pSMB->hdr.smb_buf_length += byte_count;
3906 pSMB->ByteCount = cpu_to_le16(byte_count);
3908 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3909 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3911 cFYI(1, ("Send error in QFSInfo = %d", rc));
3912 } else { /* decode response */
3913 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3915 if (rc || (pSMBr->ByteCount < 24))
3916 rc = -EIO; /* bad smb */
3918 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3922 *) (((char *) &pSMBr->hdr.Protocol) +
3925 le32_to_cpu(response_data->BytesPerSector) *
3926 le32_to_cpu(response_data->
3927 SectorsPerAllocationUnit);
3929 le64_to_cpu(response_data->TotalAllocationUnits);
3930 FSData->f_bfree = FSData->f_bavail =
3931 le64_to_cpu(response_data->FreeAllocationUnits);
3933 ("Blocks: %lld Free: %lld Block size %ld",
3934 (unsigned long long)FSData->f_blocks,
3935 (unsigned long long)FSData->f_bfree,
3939 cifs_buf_release(pSMB);
3948 CIFSSMBQFSAttributeInfo(const int xid, struct cifsTconInfo *tcon)
3950 /* level 0x105 SMB_QUERY_FILE_SYSTEM_INFO */
3951 TRANSACTION2_QFSI_REQ *pSMB = NULL;
3952 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
3953 FILE_SYSTEM_ATTRIBUTE_INFO *response_data;
3955 int bytes_returned = 0;
3956 __u16 params, byte_count;
3958 cFYI(1, ("In QFSAttributeInfo"));
3960 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3965 params = 2; /* level */
3966 pSMB->TotalDataCount = 0;
3967 pSMB->MaxParameterCount = cpu_to_le16(2);
3968 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
3969 pSMB->MaxSetupCount = 0;
3973 pSMB->Reserved2 = 0;
3974 byte_count = params + 1 /* pad */ ;
3975 pSMB->TotalParameterCount = cpu_to_le16(params);
3976 pSMB->ParameterCount = pSMB->TotalParameterCount;
3977 pSMB->ParameterOffset = cpu_to_le16(offsetof(
3978 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
3979 pSMB->DataCount = 0;
3980 pSMB->DataOffset = 0;
3981 pSMB->SetupCount = 1;
3982 pSMB->Reserved3 = 0;
3983 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
3984 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_ATTRIBUTE_INFO);
3985 pSMB->hdr.smb_buf_length += byte_count;
3986 pSMB->ByteCount = cpu_to_le16(byte_count);
3988 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3989 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3991 cERROR(1, ("Send error in QFSAttributeInfo = %d", rc));
3992 } else { /* decode response */
3993 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3995 if (rc || (pSMBr->ByteCount < 13)) { /* BB also check enough bytes returned */
3996 rc = -EIO; /* bad smb */
3998 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4000 (FILE_SYSTEM_ATTRIBUTE_INFO
4001 *) (((char *) &pSMBr->hdr.Protocol) +
4003 memcpy(&tcon->fsAttrInfo, response_data,
4004 sizeof (FILE_SYSTEM_ATTRIBUTE_INFO));
4007 cifs_buf_release(pSMB);
4010 goto QFSAttributeRetry;
4016 CIFSSMBQFSDeviceInfo(const int xid, struct cifsTconInfo *tcon)
4018 /* level 0x104 SMB_QUERY_FILE_SYSTEM_INFO */
4019 TRANSACTION2_QFSI_REQ *pSMB = NULL;
4020 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4021 FILE_SYSTEM_DEVICE_INFO *response_data;
4023 int bytes_returned = 0;
4024 __u16 params, byte_count;
4026 cFYI(1, ("In QFSDeviceInfo"));
4028 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4033 params = 2; /* level */
4034 pSMB->TotalDataCount = 0;
4035 pSMB->MaxParameterCount = cpu_to_le16(2);
4036 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
4037 pSMB->MaxSetupCount = 0;
4041 pSMB->Reserved2 = 0;
4042 byte_count = params + 1 /* pad */ ;
4043 pSMB->TotalParameterCount = cpu_to_le16(params);
4044 pSMB->ParameterCount = pSMB->TotalParameterCount;
4045 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4046 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4048 pSMB->DataCount = 0;
4049 pSMB->DataOffset = 0;
4050 pSMB->SetupCount = 1;
4051 pSMB->Reserved3 = 0;
4052 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4053 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_DEVICE_INFO);
4054 pSMB->hdr.smb_buf_length += byte_count;
4055 pSMB->ByteCount = cpu_to_le16(byte_count);
4057 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4058 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4060 cFYI(1, ("Send error in QFSDeviceInfo = %d", rc));
4061 } else { /* decode response */
4062 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4064 if (rc || (pSMBr->ByteCount < sizeof (FILE_SYSTEM_DEVICE_INFO)))
4065 rc = -EIO; /* bad smb */
4067 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4069 (FILE_SYSTEM_DEVICE_INFO *)
4070 (((char *) &pSMBr->hdr.Protocol) +
4072 memcpy(&tcon->fsDevInfo, response_data,
4073 sizeof (FILE_SYSTEM_DEVICE_INFO));
4076 cifs_buf_release(pSMB);
4079 goto QFSDeviceRetry;
4085 CIFSSMBQFSUnixInfo(const int xid, struct cifsTconInfo *tcon)
4087 /* level 0x200 SMB_QUERY_CIFS_UNIX_INFO */
4088 TRANSACTION2_QFSI_REQ *pSMB = NULL;
4089 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4090 FILE_SYSTEM_UNIX_INFO *response_data;
4092 int bytes_returned = 0;
4093 __u16 params, byte_count;
4095 cFYI(1, ("In QFSUnixInfo"));
4097 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4102 params = 2; /* level */
4103 pSMB->TotalDataCount = 0;
4104 pSMB->DataCount = 0;
4105 pSMB->DataOffset = 0;
4106 pSMB->MaxParameterCount = cpu_to_le16(2);
4107 pSMB->MaxDataCount = cpu_to_le16(100); /* BB find exact max SMB PDU from sess structure BB */
4108 pSMB->MaxSetupCount = 0;
4112 pSMB->Reserved2 = 0;
4113 byte_count = params + 1 /* pad */ ;
4114 pSMB->ParameterCount = cpu_to_le16(params);
4115 pSMB->TotalParameterCount = pSMB->ParameterCount;
4116 pSMB->ParameterOffset = cpu_to_le16(offsetof(struct
4117 smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4118 pSMB->SetupCount = 1;
4119 pSMB->Reserved3 = 0;
4120 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4121 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_CIFS_UNIX_INFO);
4122 pSMB->hdr.smb_buf_length += byte_count;
4123 pSMB->ByteCount = cpu_to_le16(byte_count);
4125 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4126 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4128 cERROR(1, ("Send error in QFSUnixInfo = %d", rc));
4129 } else { /* decode response */
4130 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4132 if (rc || (pSMBr->ByteCount < 13)) {
4133 rc = -EIO; /* bad smb */
4135 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4137 (FILE_SYSTEM_UNIX_INFO
4138 *) (((char *) &pSMBr->hdr.Protocol) +
4140 memcpy(&tcon->fsUnixInfo, response_data,
4141 sizeof (FILE_SYSTEM_UNIX_INFO));
4144 cifs_buf_release(pSMB);
4154 CIFSSMBSetFSUnixInfo(const int xid, struct cifsTconInfo *tcon, __u64 cap)
4156 /* level 0x200 SMB_SET_CIFS_UNIX_INFO */
4157 TRANSACTION2_SETFSI_REQ *pSMB = NULL;
4158 TRANSACTION2_SETFSI_RSP *pSMBr = NULL;
4160 int bytes_returned = 0;
4161 __u16 params, param_offset, offset, byte_count;
4163 cFYI(1, ("In SETFSUnixInfo"));
4165 /* BB switch to small buf init to save memory */
4166 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4171 params = 4; /* 2 bytes zero followed by info level. */
4172 pSMB->MaxSetupCount = 0;
4176 pSMB->Reserved2 = 0;
4177 param_offset = offsetof(struct smb_com_transaction2_setfsi_req, FileNum) - 4;
4178 offset = param_offset + params;
4180 pSMB->MaxParameterCount = cpu_to_le16(4);
4181 pSMB->MaxDataCount = cpu_to_le16(100); /* BB find exact max SMB PDU from sess structure BB */
4182 pSMB->SetupCount = 1;
4183 pSMB->Reserved3 = 0;
4184 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FS_INFORMATION);
4185 byte_count = 1 /* pad */ + params + 12;
4187 pSMB->DataCount = cpu_to_le16(12);
4188 pSMB->ParameterCount = cpu_to_le16(params);
4189 pSMB->TotalDataCount = pSMB->DataCount;
4190 pSMB->TotalParameterCount = pSMB->ParameterCount;
4191 pSMB->ParameterOffset = cpu_to_le16(param_offset);
4192 pSMB->DataOffset = cpu_to_le16(offset);
4196 pSMB->InformationLevel = cpu_to_le16(SMB_SET_CIFS_UNIX_INFO);
4199 pSMB->ClientUnixMajor = cpu_to_le16(CIFS_UNIX_MAJOR_VERSION);
4200 pSMB->ClientUnixMinor = cpu_to_le16(CIFS_UNIX_MINOR_VERSION);
4201 pSMB->ClientUnixCap = cpu_to_le64(cap);
4203 pSMB->hdr.smb_buf_length += byte_count;
4204 pSMB->ByteCount = cpu_to_le16(byte_count);
4206 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4207 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4209 cERROR(1, ("Send error in SETFSUnixInfo = %d", rc));
4210 } else { /* decode response */
4211 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4213 rc = -EIO; /* bad smb */
4216 cifs_buf_release(pSMB);
4219 goto SETFSUnixRetry;
4227 CIFSSMBQFSPosixInfo(const int xid, struct cifsTconInfo *tcon,
4228 struct kstatfs *FSData)
4230 /* level 0x201 SMB_QUERY_CIFS_POSIX_INFO */
4231 TRANSACTION2_QFSI_REQ *pSMB = NULL;
4232 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4233 FILE_SYSTEM_POSIX_INFO *response_data;
4235 int bytes_returned = 0;
4236 __u16 params, byte_count;
4238 cFYI(1, ("In QFSPosixInfo"));
4240 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4245 params = 2; /* level */
4246 pSMB->TotalDataCount = 0;
4247 pSMB->DataCount = 0;
4248 pSMB->DataOffset = 0;
4249 pSMB->MaxParameterCount = cpu_to_le16(2);
4250 pSMB->MaxDataCount = cpu_to_le16(100); /* BB find exact max SMB PDU from sess structure BB */
4251 pSMB->MaxSetupCount = 0;
4255 pSMB->Reserved2 = 0;
4256 byte_count = params + 1 /* pad */ ;
4257 pSMB->ParameterCount = cpu_to_le16(params);
4258 pSMB->TotalParameterCount = pSMB->ParameterCount;
4259 pSMB->ParameterOffset = cpu_to_le16(offsetof(struct
4260 smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4261 pSMB->SetupCount = 1;
4262 pSMB->Reserved3 = 0;
4263 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4264 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_POSIX_FS_INFO);
4265 pSMB->hdr.smb_buf_length += byte_count;
4266 pSMB->ByteCount = cpu_to_le16(byte_count);
4268 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4269 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4271 cFYI(1, ("Send error in QFSUnixInfo = %d", rc));
4272 } else { /* decode response */
4273 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4275 if (rc || (pSMBr->ByteCount < 13)) {
4276 rc = -EIO; /* bad smb */
4278 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4280 (FILE_SYSTEM_POSIX_INFO
4281 *) (((char *) &pSMBr->hdr.Protocol) +
4284 le32_to_cpu(response_data->BlockSize);
4286 le64_to_cpu(response_data->TotalBlocks);
4288 le64_to_cpu(response_data->BlocksAvail);
4289 if(response_data->UserBlocksAvail == cpu_to_le64(-1)) {
4290 FSData->f_bavail = FSData->f_bfree;
4293 le64_to_cpu(response_data->UserBlocksAvail);
4295 if(response_data->TotalFileNodes != cpu_to_le64(-1))
4297 le64_to_cpu(response_data->TotalFileNodes);
4298 if(response_data->FreeFileNodes != cpu_to_le64(-1))
4300 le64_to_cpu(response_data->FreeFileNodes);
4303 cifs_buf_release(pSMB);
4312 /* We can not use write of zero bytes trick to
4313 set file size due to need for large file support. Also note that
4314 this SetPathInfo is preferred to SetFileInfo based method in next
4315 routine which is only needed to work around a sharing violation bug
4316 in Samba which this routine can run into */
4319 CIFSSMBSetEOF(const int xid, struct cifsTconInfo *tcon, const char *fileName,
4320 __u64 size, int SetAllocation,
4321 const struct nls_table *nls_codepage, int remap)
4323 struct smb_com_transaction2_spi_req *pSMB = NULL;
4324 struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
4325 struct file_end_of_file_info *parm_data;
4328 int bytes_returned = 0;
4329 __u16 params, byte_count, data_count, param_offset, offset;
4331 cFYI(1, ("In SetEOF"));
4333 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4338 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4340 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
4341 PATH_MAX, nls_codepage, remap);
4342 name_len++; /* trailing null */
4344 } else { /* BB improve the check for buffer overruns BB */
4345 name_len = strnlen(fileName, PATH_MAX);
4346 name_len++; /* trailing null */
4347 strncpy(pSMB->FileName, fileName, name_len);
4349 params = 6 + name_len;
4350 data_count = sizeof (struct file_end_of_file_info);
4351 pSMB->MaxParameterCount = cpu_to_le16(2);
4352 pSMB->MaxDataCount = cpu_to_le16(4100);
4353 pSMB->MaxSetupCount = 0;
4357 pSMB->Reserved2 = 0;
4358 param_offset = offsetof(struct smb_com_transaction2_spi_req,
4359 InformationLevel) - 4;
4360 offset = param_offset + params;
4362 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
4363 pSMB->InformationLevel =
4364 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2);
4366 pSMB->InformationLevel =
4367 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO);
4368 } else /* Set File Size */ {
4369 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
4370 pSMB->InformationLevel =
4371 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO2);
4373 pSMB->InformationLevel =
4374 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO);
4378 (struct file_end_of_file_info *) (((char *) &pSMB->hdr.Protocol) +
4380 pSMB->ParameterOffset = cpu_to_le16(param_offset);
4381 pSMB->DataOffset = cpu_to_le16(offset);
4382 pSMB->SetupCount = 1;
4383 pSMB->Reserved3 = 0;
4384 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
4385 byte_count = 3 /* pad */ + params + data_count;
4386 pSMB->DataCount = cpu_to_le16(data_count);
4387 pSMB->TotalDataCount = pSMB->DataCount;
4388 pSMB->ParameterCount = cpu_to_le16(params);
4389 pSMB->TotalParameterCount = pSMB->ParameterCount;
4390 pSMB->Reserved4 = 0;
4391 pSMB->hdr.smb_buf_length += byte_count;
4392 parm_data->FileSize = cpu_to_le64(size);
4393 pSMB->ByteCount = cpu_to_le16(byte_count);
4394 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4395 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4397 cFYI(1, ("SetPathInfo (file size) returned %d", rc));
4400 cifs_buf_release(pSMB);
4409 CIFSSMBSetFileSize(const int xid, struct cifsTconInfo *tcon, __u64 size,
4410 __u16 fid, __u32 pid_of_opener, int SetAllocation)
4412 struct smb_com_transaction2_sfi_req *pSMB = NULL;
4413 struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
4415 struct file_end_of_file_info *parm_data;
4417 int bytes_returned = 0;
4418 __u16 params, param_offset, offset, byte_count, count;
4420 cFYI(1, ("SetFileSize (via SetFileInfo) %lld",
4422 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
4427 pSMBr = (struct smb_com_transaction2_sfi_rsp *)pSMB;
4429 pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
4430 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));
4433 pSMB->MaxSetupCount = 0;
4437 pSMB->Reserved2 = 0;
4438 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
4439 offset = param_offset + params;
4441 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
4443 count = sizeof(struct file_end_of_file_info);
4444 pSMB->MaxParameterCount = cpu_to_le16(2);
4445 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB PDU from sess */
4446 pSMB->SetupCount = 1;
4447 pSMB->Reserved3 = 0;
4448 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
4449 byte_count = 3 /* pad */ + params + count;
4450 pSMB->DataCount = cpu_to_le16(count);
4451 pSMB->ParameterCount = cpu_to_le16(params);
4452 pSMB->TotalDataCount = pSMB->DataCount;
4453 pSMB->TotalParameterCount = pSMB->ParameterCount;
4454 pSMB->ParameterOffset = cpu_to_le16(param_offset);
4456 (struct file_end_of_file_info *) (((char *) &pSMB->hdr.Protocol) +
4458 pSMB->DataOffset = cpu_to_le16(offset);
4459 parm_data->FileSize = cpu_to_le64(size);
4462 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
4463 pSMB->InformationLevel =
4464 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2);
4466 pSMB->InformationLevel =
4467 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO);
4468 } else /* Set File Size */ {
4469 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
4470 pSMB->InformationLevel =
4471 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO2);
4473 pSMB->InformationLevel =
4474 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO);
4476 pSMB->Reserved4 = 0;
4477 pSMB->hdr.smb_buf_length += byte_count;
4478 pSMB->ByteCount = cpu_to_le16(byte_count);
4479 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4480 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4483 ("Send error in SetFileInfo (SetFileSize) = %d",
4488 cifs_small_buf_release(pSMB);
4490 /* Note: On -EAGAIN error only caller can retry on handle based calls
4491 since file handle passed in no longer valid */
4496 /* Some legacy servers such as NT4 require that the file times be set on
4497 an open handle, rather than by pathname - this is awkward due to
4498 potential access conflicts on the open, but it is unavoidable for these
4499 old servers since the only other choice is to go from 100 nanosecond DCE
4500 time and resort to the original setpathinfo level which takes the ancient
4501 DOS time format with 2 second granularity */
4503 CIFSSMBSetFileTimes(const int xid, struct cifsTconInfo *tcon, const FILE_BASIC_INFO * data,
4506 struct smb_com_transaction2_sfi_req *pSMB = NULL;
4507 struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
4510 int bytes_returned = 0;
4511 __u16 params, param_offset, offset, byte_count, count;
4513 cFYI(1, ("Set Times (via SetFileInfo)"));
4514 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
4519 pSMBr = (struct smb_com_transaction2_sfi_rsp *)pSMB;
4521 /* At this point there is no need to override the current pid
4522 with the pid of the opener, but that could change if we someday
4523 use an existing handle (rather than opening one on the fly) */
4524 /* pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
4525 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));*/
4528 pSMB->MaxSetupCount = 0;
4532 pSMB->Reserved2 = 0;
4533 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
4534 offset = param_offset + params;
4536 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
4538 count = sizeof (FILE_BASIC_INFO);
4539 pSMB->MaxParameterCount = cpu_to_le16(2);
4540 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB PDU from sess */
4541 pSMB->SetupCount = 1;
4542 pSMB->Reserved3 = 0;
4543 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
4544 byte_count = 3 /* pad */ + params + count;
4545 pSMB->DataCount = cpu_to_le16(count);
4546 pSMB->ParameterCount = cpu_to_le16(params);
4547 pSMB->TotalDataCount = pSMB->DataCount;
4548 pSMB->TotalParameterCount = pSMB->ParameterCount;
4549 pSMB->ParameterOffset = cpu_to_le16(param_offset);
4550 pSMB->DataOffset = cpu_to_le16(offset);
4552 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
4553 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO2);
4555 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO);
4556 pSMB->Reserved4 = 0;
4557 pSMB->hdr.smb_buf_length += byte_count;
4558 pSMB->ByteCount = cpu_to_le16(byte_count);
4559 memcpy(data_offset,data,sizeof(FILE_BASIC_INFO));
4560 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4561 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4563 cFYI(1,("Send error in Set Time (SetFileInfo) = %d",rc));
4566 cifs_small_buf_release(pSMB);
4568 /* Note: On -EAGAIN error only caller can retry on handle based calls
4569 since file handle passed in no longer valid */
4576 CIFSSMBSetTimes(const int xid, struct cifsTconInfo *tcon, const char *fileName,
4577 const FILE_BASIC_INFO * data,
4578 const struct nls_table *nls_codepage, int remap)
4580 TRANSACTION2_SPI_REQ *pSMB = NULL;
4581 TRANSACTION2_SPI_RSP *pSMBr = NULL;
4584 int bytes_returned = 0;
4586 __u16 params, param_offset, offset, byte_count, count;
4588 cFYI(1, ("In SetTimes"));
4591 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4596 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4598 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
4599 PATH_MAX, nls_codepage, remap);
4600 name_len++; /* trailing null */
4602 } else { /* BB improve the check for buffer overruns BB */
4603 name_len = strnlen(fileName, PATH_MAX);
4604 name_len++; /* trailing null */
4605 strncpy(pSMB->FileName, fileName, name_len);
4608 params = 6 + name_len;
4609 count = sizeof (FILE_BASIC_INFO);
4610 pSMB->MaxParameterCount = cpu_to_le16(2);
4611 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
4612 pSMB->MaxSetupCount = 0;
4616 pSMB->Reserved2 = 0;
4617 param_offset = offsetof(struct smb_com_transaction2_spi_req,
4618 InformationLevel) - 4;
4619 offset = param_offset + params;
4620 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
4621 pSMB->ParameterOffset = cpu_to_le16(param_offset);
4622 pSMB->DataOffset = cpu_to_le16(offset);
4623 pSMB->SetupCount = 1;
4624 pSMB->Reserved3 = 0;
4625 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
4626 byte_count = 3 /* pad */ + params + count;
4628 pSMB->DataCount = cpu_to_le16(count);
4629 pSMB->ParameterCount = cpu_to_le16(params);
4630 pSMB->TotalDataCount = pSMB->DataCount;
4631 pSMB->TotalParameterCount = pSMB->ParameterCount;
4632 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
4633 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO2);
4635 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO);
4636 pSMB->Reserved4 = 0;
4637 pSMB->hdr.smb_buf_length += byte_count;
4638 memcpy(data_offset, data, sizeof (FILE_BASIC_INFO));
4639 pSMB->ByteCount = cpu_to_le16(byte_count);
4640 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4641 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4643 cFYI(1, ("SetPathInfo (times) returned %d", rc));
4646 cifs_buf_release(pSMB);
4654 /* Can not be used to set time stamps yet (due to old DOS time format) */
4655 /* Can be used to set attributes */
4656 #if 0 /* Possibly not needed - since it turns out that strangely NT4 has a bug
4657 handling it anyway and NT4 was what we thought it would be needed for
4658 Do not delete it until we prove whether needed for Win9x though */
4660 CIFSSMBSetAttrLegacy(int xid, struct cifsTconInfo *tcon, char *fileName,
4661 __u16 dos_attrs, const struct nls_table *nls_codepage)
4663 SETATTR_REQ *pSMB = NULL;
4664 SETATTR_RSP *pSMBr = NULL;
4669 cFYI(1, ("In SetAttrLegacy"));
4672 rc = smb_init(SMB_COM_SETATTR, 8, tcon, (void **) &pSMB,
4677 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4679 ConvertToUCS((__le16 *) pSMB->fileName, fileName,
4680 PATH_MAX, nls_codepage);
4681 name_len++; /* trailing null */
4683 } else { /* BB improve the check for buffer overruns BB */
4684 name_len = strnlen(fileName, PATH_MAX);
4685 name_len++; /* trailing null */
4686 strncpy(pSMB->fileName, fileName, name_len);
4688 pSMB->attr = cpu_to_le16(dos_attrs);
4689 pSMB->BufferFormat = 0x04;
4690 pSMB->hdr.smb_buf_length += name_len + 1;
4691 pSMB->ByteCount = cpu_to_le16(name_len + 1);
4692 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4693 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4695 cFYI(1, ("Error in LegacySetAttr = %d", rc));
4698 cifs_buf_release(pSMB);
4701 goto SetAttrLgcyRetry;
4705 #endif /* temporarily unneeded SetAttr legacy function */
4708 CIFSSMBUnixSetPerms(const int xid, struct cifsTconInfo *tcon,
4709 char *fileName, __u64 mode, __u64 uid, __u64 gid,
4710 dev_t device, const struct nls_table *nls_codepage,
4713 TRANSACTION2_SPI_REQ *pSMB = NULL;
4714 TRANSACTION2_SPI_RSP *pSMBr = NULL;
4717 int bytes_returned = 0;
4718 FILE_UNIX_BASIC_INFO *data_offset;
4719 __u16 params, param_offset, offset, count, byte_count;
4721 cFYI(1, ("In SetUID/GID/Mode"));
4723 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4728 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4730 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
4731 PATH_MAX, nls_codepage, remap);
4732 name_len++; /* trailing null */
4734 } else { /* BB improve the check for buffer overruns BB */
4735 name_len = strnlen(fileName, PATH_MAX);
4736 name_len++; /* trailing null */
4737 strncpy(pSMB->FileName, fileName, name_len);
4740 params = 6 + name_len;
4741 count = sizeof (FILE_UNIX_BASIC_INFO);
4742 pSMB->MaxParameterCount = cpu_to_le16(2);
4743 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
4744 pSMB->MaxSetupCount = 0;
4748 pSMB->Reserved2 = 0;
4749 param_offset = offsetof(struct smb_com_transaction2_spi_req,
4750 InformationLevel) - 4;
4751 offset = param_offset + params;
4753 (FILE_UNIX_BASIC_INFO *) ((char *) &pSMB->hdr.Protocol +
4755 memset(data_offset, 0, count);
4756 pSMB->DataOffset = cpu_to_le16(offset);
4757 pSMB->ParameterOffset = cpu_to_le16(param_offset);
4758 pSMB->SetupCount = 1;
4759 pSMB->Reserved3 = 0;
4760 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
4761 byte_count = 3 /* pad */ + params + count;
4762 pSMB->ParameterCount = cpu_to_le16(params);
4763 pSMB->DataCount = cpu_to_le16(count);
4764 pSMB->TotalParameterCount = pSMB->ParameterCount;
4765 pSMB->TotalDataCount = pSMB->DataCount;
4766 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_BASIC);
4767 pSMB->Reserved4 = 0;
4768 pSMB->hdr.smb_buf_length += byte_count;
4769 data_offset->Uid = cpu_to_le64(uid);
4770 data_offset->Gid = cpu_to_le64(gid);
4771 /* better to leave device as zero when it is */
4772 data_offset->DevMajor = cpu_to_le64(MAJOR(device));
4773 data_offset->DevMinor = cpu_to_le64(MINOR(device));
4774 data_offset->Permissions = cpu_to_le64(mode);
4777 data_offset->Type = cpu_to_le32(UNIX_FILE);
4778 else if(S_ISDIR(mode))
4779 data_offset->Type = cpu_to_le32(UNIX_DIR);
4780 else if(S_ISLNK(mode))
4781 data_offset->Type = cpu_to_le32(UNIX_SYMLINK);
4782 else if(S_ISCHR(mode))
4783 data_offset->Type = cpu_to_le32(UNIX_CHARDEV);
4784 else if(S_ISBLK(mode))
4785 data_offset->Type = cpu_to_le32(UNIX_BLOCKDEV);
4786 else if(S_ISFIFO(mode))
4787 data_offset->Type = cpu_to_le32(UNIX_FIFO);
4788 else if(S_ISSOCK(mode))
4789 data_offset->Type = cpu_to_le32(UNIX_SOCKET);
4792 pSMB->ByteCount = cpu_to_le16(byte_count);
4793 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4794 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4796 cFYI(1, ("SetPathInfo (perms) returned %d", rc));
4800 cifs_buf_release(pSMB);
4806 int CIFSSMBNotify(const int xid, struct cifsTconInfo *tcon,
4807 const int notify_subdirs, const __u16 netfid,
4808 __u32 filter, struct file * pfile, int multishot,
4809 const struct nls_table *nls_codepage)
4812 struct smb_com_transaction_change_notify_req * pSMB = NULL;
4813 struct smb_com_ntransaction_change_notify_rsp * pSMBr = NULL;
4814 struct dir_notify_req *dnotify_req;
4817 cFYI(1, ("In CIFSSMBNotify for file handle %d",(int)netfid));
4818 rc = smb_init(SMB_COM_NT_TRANSACT, 23, tcon, (void **) &pSMB,
4823 pSMB->TotalParameterCount = 0 ;
4824 pSMB->TotalDataCount = 0;
4825 pSMB->MaxParameterCount = cpu_to_le32(2);
4826 /* BB find exact data count max from sess structure BB */
4827 pSMB->MaxDataCount = 0; /* same in little endian or be */
4828 /* BB VERIFY verify which is correct for above BB */
4829 pSMB->MaxDataCount = cpu_to_le32((tcon->ses->server->maxBuf -
4830 MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
4832 pSMB->MaxSetupCount = 4;
4834 pSMB->ParameterOffset = 0;
4835 pSMB->DataCount = 0;
4836 pSMB->DataOffset = 0;
4837 pSMB->SetupCount = 4; /* single byte does not need le conversion */
4838 pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_NOTIFY_CHANGE);
4839 pSMB->ParameterCount = pSMB->TotalParameterCount;
4841 pSMB->WatchTree = 1; /* one byte - no le conversion needed */
4842 pSMB->Reserved2 = 0;
4843 pSMB->CompletionFilter = cpu_to_le32(filter);
4844 pSMB->Fid = netfid; /* file handle always le */
4845 pSMB->ByteCount = 0;
4847 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4848 (struct smb_hdr *) pSMBr, &bytes_returned, -1);
4850 cFYI(1, ("Error in Notify = %d", rc));
4852 /* Add file to outstanding requests */
4853 /* BB change to kmem cache alloc */
4854 dnotify_req = (struct dir_notify_req *) kmalloc(
4855 sizeof(struct dir_notify_req),
4858 dnotify_req->Pid = pSMB->hdr.Pid;
4859 dnotify_req->PidHigh = pSMB->hdr.PidHigh;
4860 dnotify_req->Mid = pSMB->hdr.Mid;
4861 dnotify_req->Tid = pSMB->hdr.Tid;
4862 dnotify_req->Uid = pSMB->hdr.Uid;
4863 dnotify_req->netfid = netfid;
4864 dnotify_req->pfile = pfile;
4865 dnotify_req->filter = filter;
4866 dnotify_req->multishot = multishot;
4867 spin_lock(&GlobalMid_Lock);
4868 list_add_tail(&dnotify_req->lhead,
4869 &GlobalDnotifyReqList);
4870 spin_unlock(&GlobalMid_Lock);
4874 cifs_buf_release(pSMB);
4877 #ifdef CONFIG_CIFS_XATTR
4879 CIFSSMBQAllEAs(const int xid, struct cifsTconInfo *tcon,
4880 const unsigned char *searchName,
4881 char * EAData, size_t buf_size,
4882 const struct nls_table *nls_codepage, int remap)
4884 /* BB assumes one setup word */
4885 TRANSACTION2_QPI_REQ *pSMB = NULL;
4886 TRANSACTION2_QPI_RSP *pSMBr = NULL;
4890 struct fea * temp_fea;
4892 __u16 params, byte_count;
4894 cFYI(1, ("In Query All EAs path %s", searchName));
4896 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4901 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4903 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
4904 PATH_MAX, nls_codepage, remap);
4905 name_len++; /* trailing null */
4907 } else { /* BB improve the check for buffer overruns BB */
4908 name_len = strnlen(searchName, PATH_MAX);
4909 name_len++; /* trailing null */
4910 strncpy(pSMB->FileName, searchName, name_len);
4913 params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */ ;
4914 pSMB->TotalDataCount = 0;
4915 pSMB->MaxParameterCount = cpu_to_le16(2);
4916 pSMB->MaxDataCount = cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
4917 pSMB->MaxSetupCount = 0;
4921 pSMB->Reserved2 = 0;
4922 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4923 struct smb_com_transaction2_qpi_req ,InformationLevel) - 4);
4924 pSMB->DataCount = 0;
4925 pSMB->DataOffset = 0;
4926 pSMB->SetupCount = 1;
4927 pSMB->Reserved3 = 0;
4928 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
4929 byte_count = params + 1 /* pad */ ;
4930 pSMB->TotalParameterCount = cpu_to_le16(params);
4931 pSMB->ParameterCount = pSMB->TotalParameterCount;
4932 pSMB->InformationLevel = cpu_to_le16(SMB_INFO_QUERY_ALL_EAS);
4933 pSMB->Reserved4 = 0;
4934 pSMB->hdr.smb_buf_length += byte_count;
4935 pSMB->ByteCount = cpu_to_le16(byte_count);
4937 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4938 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4940 cFYI(1, ("Send error in QueryAllEAs = %d", rc));
4941 } else { /* decode response */
4942 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4944 /* BB also check enough total bytes returned */
4945 /* BB we need to improve the validity checking
4946 of these trans2 responses */
4947 if (rc || (pSMBr->ByteCount < 4))
4948 rc = -EIO; /* bad smb */
4949 /* else if (pFindData){
4950 memcpy((char *) pFindData,
4951 (char *) &pSMBr->hdr.Protocol +
4954 /* check that length of list is not more than bcc */
4955 /* check that each entry does not go beyond length
4957 /* check that each element of each entry does not
4958 go beyond end of list */
4959 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4960 struct fealist * ea_response_data;
4962 /* validate_trans2_offsets() */
4963 /* BB to check if(start of smb + data_offset > &bcc+ bcc)*/
4964 ea_response_data = (struct fealist *)
4965 (((char *) &pSMBr->hdr.Protocol) +
4967 name_len = le32_to_cpu(ea_response_data->list_len);
4968 cFYI(1,("ea length %d", name_len));
4970 /* returned EA size zeroed at top of function */
4971 cFYI(1,("empty EA list returned from server"));
4973 /* account for ea list len */
4975 temp_fea = ea_response_data->list;
4976 temp_ptr = (char *)temp_fea;
4977 while(name_len > 0) {
4981 rc += temp_fea->name_len;
4982 /* account for prefix user. and trailing null */
4984 if(rc<(int)buf_size) {
4985 memcpy(EAData,"user.",5);
4987 memcpy(EAData,temp_ptr,temp_fea->name_len);
4988 EAData+=temp_fea->name_len;
4989 /* null terminate name */
4991 EAData = EAData + 1;
4992 } else if(buf_size == 0) {
4993 /* skip copy - calc size only */
4995 /* stop before overrun buffer */
4999 name_len -= temp_fea->name_len;
5000 temp_ptr += temp_fea->name_len;
5001 /* account for trailing null */
5004 value_len = le16_to_cpu(temp_fea->value_len);
5005 name_len -= value_len;
5006 temp_ptr += value_len;
5007 /* BB check that temp_ptr is still within smb BB*/
5008 /* no trailing null to account for in value len */
5009 /* go on to next EA */
5010 temp_fea = (struct fea *)temp_ptr;
5016 cifs_buf_release(pSMB);
5023 ssize_t CIFSSMBQueryEA(const int xid,struct cifsTconInfo * tcon,
5024 const unsigned char * searchName,const unsigned char * ea_name,
5025 unsigned char * ea_value, size_t buf_size,
5026 const struct nls_table *nls_codepage, int remap)
5028 TRANSACTION2_QPI_REQ *pSMB = NULL;
5029 TRANSACTION2_QPI_RSP *pSMBr = NULL;
5033 struct fea * temp_fea;
5035 __u16 params, byte_count;
5037 cFYI(1, ("In Query EA path %s", searchName));
5039 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5044 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5046 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
5047 PATH_MAX, nls_codepage, remap);
5048 name_len++; /* trailing null */
5050 } else { /* BB improve the check for buffer overruns BB */
5051 name_len = strnlen(searchName, PATH_MAX);
5052 name_len++; /* trailing null */
5053 strncpy(pSMB->FileName, searchName, name_len);
5056 params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */ ;
5057 pSMB->TotalDataCount = 0;
5058 pSMB->MaxParameterCount = cpu_to_le16(2);
5059 pSMB->MaxDataCount = cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
5060 pSMB->MaxSetupCount = 0;
5064 pSMB->Reserved2 = 0;
5065 pSMB->ParameterOffset = cpu_to_le16(offsetof(
5066 struct smb_com_transaction2_qpi_req ,InformationLevel) - 4);
5067 pSMB->DataCount = 0;
5068 pSMB->DataOffset = 0;
5069 pSMB->SetupCount = 1;
5070 pSMB->Reserved3 = 0;
5071 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
5072 byte_count = params + 1 /* pad */ ;
5073 pSMB->TotalParameterCount = cpu_to_le16(params);
5074 pSMB->ParameterCount = pSMB->TotalParameterCount;
5075 pSMB->InformationLevel = cpu_to_le16(SMB_INFO_QUERY_ALL_EAS);
5076 pSMB->Reserved4 = 0;
5077 pSMB->hdr.smb_buf_length += byte_count;
5078 pSMB->ByteCount = cpu_to_le16(byte_count);
5080 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5081 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5083 cFYI(1, ("Send error in Query EA = %d", rc));
5084 } else { /* decode response */
5085 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
5087 /* BB also check enough total bytes returned */
5088 /* BB we need to improve the validity checking
5089 of these trans2 responses */
5090 if (rc || (pSMBr->ByteCount < 4))
5091 rc = -EIO; /* bad smb */
5092 /* else if (pFindData){
5093 memcpy((char *) pFindData,
5094 (char *) &pSMBr->hdr.Protocol +
5097 /* check that length of list is not more than bcc */
5098 /* check that each entry does not go beyond length
5100 /* check that each element of each entry does not
5101 go beyond end of list */
5102 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
5103 struct fealist * ea_response_data;
5105 /* validate_trans2_offsets() */
5106 /* BB to check if(start of smb + data_offset > &bcc+ bcc)*/
5107 ea_response_data = (struct fealist *)
5108 (((char *) &pSMBr->hdr.Protocol) +
5110 name_len = le32_to_cpu(ea_response_data->list_len);
5111 cFYI(1,("ea length %d", name_len));
5113 /* returned EA size zeroed at top of function */
5114 cFYI(1,("empty EA list returned from server"));
5116 /* account for ea list len */
5118 temp_fea = ea_response_data->list;
5119 temp_ptr = (char *)temp_fea;
5120 /* loop through checking if we have a matching
5121 name and then return the associated value */
5122 while(name_len > 0) {
5126 value_len = le16_to_cpu(temp_fea->value_len);
5127 /* BB validate that value_len falls within SMB,
5128 even though maximum for name_len is 255 */
5129 if(memcmp(temp_fea->name,ea_name,
5130 temp_fea->name_len) == 0) {
5133 /* account for prefix user. and trailing null */
5134 if(rc<=(int)buf_size) {
5136 temp_fea->name+temp_fea->name_len+1,
5138 /* ea values, unlike ea names,
5139 are not null terminated */
5140 } else if(buf_size == 0) {
5141 /* skip copy - calc size only */
5143 /* stop before overrun buffer */
5148 name_len -= temp_fea->name_len;
5149 temp_ptr += temp_fea->name_len;
5150 /* account for trailing null */
5153 name_len -= value_len;
5154 temp_ptr += value_len;
5155 /* no trailing null to account for in value len */
5156 /* go on to next EA */
5157 temp_fea = (struct fea *)temp_ptr;
5163 cifs_buf_release(pSMB);
5171 CIFSSMBSetEA(const int xid, struct cifsTconInfo *tcon, const char *fileName,
5172 const char * ea_name, const void * ea_value,
5173 const __u16 ea_value_len, const struct nls_table *nls_codepage,
5176 struct smb_com_transaction2_spi_req *pSMB = NULL;
5177 struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
5178 struct fealist *parm_data;
5181 int bytes_returned = 0;
5182 __u16 params, param_offset, byte_count, offset, count;
5184 cFYI(1, ("In SetEA"));
5186 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5191 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5193 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
5194 PATH_MAX, nls_codepage, remap);
5195 name_len++; /* trailing null */
5197 } else { /* BB improve the check for buffer overruns BB */
5198 name_len = strnlen(fileName, PATH_MAX);
5199 name_len++; /* trailing null */
5200 strncpy(pSMB->FileName, fileName, name_len);
5203 params = 6 + name_len;
5205 /* done calculating parms using name_len of file name,
5206 now use name_len to calculate length of ea name
5207 we are going to create in the inode xattrs */
5211 name_len = strnlen(ea_name,255);
5213 count = sizeof(*parm_data) + ea_value_len + name_len + 1;
5214 pSMB->MaxParameterCount = cpu_to_le16(2);
5215 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB size from sess */
5216 pSMB->MaxSetupCount = 0;
5220 pSMB->Reserved2 = 0;
5221 param_offset = offsetof(struct smb_com_transaction2_spi_req,
5222 InformationLevel) - 4;
5223 offset = param_offset + params;
5224 pSMB->InformationLevel =
5225 cpu_to_le16(SMB_SET_FILE_EA);
5228 (struct fealist *) (((char *) &pSMB->hdr.Protocol) +
5230 pSMB->ParameterOffset = cpu_to_le16(param_offset);
5231 pSMB->DataOffset = cpu_to_le16(offset);
5232 pSMB->SetupCount = 1;
5233 pSMB->Reserved3 = 0;
5234 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
5235 byte_count = 3 /* pad */ + params + count;
5236 pSMB->DataCount = cpu_to_le16(count);
5237 parm_data->list_len = cpu_to_le32(count);
5238 parm_data->list[0].EA_flags = 0;
5239 /* we checked above that name len is less than 255 */
5240 parm_data->list[0].name_len = (__u8)name_len;
5241 /* EA names are always ASCII */
5243 strncpy(parm_data->list[0].name,ea_name,name_len);
5244 parm_data->list[0].name[name_len] = 0;
5245 parm_data->list[0].value_len = cpu_to_le16(ea_value_len);
5246 /* caller ensures that ea_value_len is less than 64K but
5247 we need to ensure that it fits within the smb */
5249 /*BB add length check that it would fit in negotiated SMB buffer size BB */
5250 /* if(ea_value_len > buffer_size - 512 (enough for header)) */
5252 memcpy(parm_data->list[0].name+name_len+1,ea_value,ea_value_len);
5254 pSMB->TotalDataCount = pSMB->DataCount;
5255 pSMB->ParameterCount = cpu_to_le16(params);
5256 pSMB->TotalParameterCount = pSMB->ParameterCount;
5257 pSMB->Reserved4 = 0;
5258 pSMB->hdr.smb_buf_length += byte_count;
5259 pSMB->ByteCount = cpu_to_le16(byte_count);
5260 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5261 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5263 cFYI(1, ("SetPathInfo (EA) returned %d", rc));
5266 cifs_buf_release(pSMB);