4 * Copyright (C) International Business Machines Corp., 2002,2006
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 int legacy /* old style infolevel */,
2973 const struct nls_table *nls_codepage, int remap)
2975 /* level 263 SMB_QUERY_FILE_ALL_INFO */
2976 TRANSACTION2_QPI_REQ *pSMB = NULL;
2977 TRANSACTION2_QPI_RSP *pSMBr = NULL;
2981 __u16 params, byte_count;
2983 /* cFYI(1, ("In QPathInfo path %s", searchName)); */
2985 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2990 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2992 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
2993 PATH_MAX, nls_codepage, remap);
2994 name_len++; /* trailing null */
2996 } else { /* BB improve the check for buffer overruns BB */
2997 name_len = strnlen(searchName, PATH_MAX);
2998 name_len++; /* trailing null */
2999 strncpy(pSMB->FileName, searchName, name_len);
3002 params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */ ;
3003 pSMB->TotalDataCount = 0;
3004 pSMB->MaxParameterCount = cpu_to_le16(2);
3005 pSMB->MaxDataCount = cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
3006 pSMB->MaxSetupCount = 0;
3010 pSMB->Reserved2 = 0;
3011 pSMB->ParameterOffset = cpu_to_le16(offsetof(
3012 struct smb_com_transaction2_qpi_req ,InformationLevel) - 4);
3013 pSMB->DataCount = 0;
3014 pSMB->DataOffset = 0;
3015 pSMB->SetupCount = 1;
3016 pSMB->Reserved3 = 0;
3017 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
3018 byte_count = params + 1 /* pad */ ;
3019 pSMB->TotalParameterCount = cpu_to_le16(params);
3020 pSMB->ParameterCount = pSMB->TotalParameterCount;
3022 pSMB->InformationLevel = cpu_to_le16(SMB_INFO_STANDARD);
3024 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_ALL_INFO);
3025 pSMB->Reserved4 = 0;
3026 pSMB->hdr.smb_buf_length += byte_count;
3027 pSMB->ByteCount = cpu_to_le16(byte_count);
3029 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3030 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3032 cFYI(1, ("Send error in QPathInfo = %d", rc));
3033 } else { /* decode response */
3034 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3036 if (rc) /* BB add auto retry on EOPNOTSUPP? */
3038 else if (!legacy && (pSMBr->ByteCount < 40))
3039 rc = -EIO; /* bad smb */
3040 else if(legacy && (pSMBr->ByteCount < 24))
3041 rc = -EIO; /* 24 or 26 expected but we do not read last field */
3042 else if (pFindData){
3044 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3045 if(legacy) /* we do not read the last field, EAsize, fortunately
3046 since it varies by subdialect and on Set vs. Get, is
3047 two bytes or 4 bytes depending but we don't care here */
3048 size = sizeof(FILE_INFO_STANDARD);
3050 size = sizeof(FILE_ALL_INFO);
3051 memcpy((char *) pFindData,
3052 (char *) &pSMBr->hdr.Protocol +
3057 cifs_buf_release(pSMB);
3059 goto QPathInfoRetry;
3065 CIFSSMBUnixQPathInfo(const int xid, struct cifsTconInfo *tcon,
3066 const unsigned char *searchName,
3067 FILE_UNIX_BASIC_INFO * pFindData,
3068 const struct nls_table *nls_codepage, int remap)
3070 /* SMB_QUERY_FILE_UNIX_BASIC */
3071 TRANSACTION2_QPI_REQ *pSMB = NULL;
3072 TRANSACTION2_QPI_RSP *pSMBr = NULL;
3074 int bytes_returned = 0;
3076 __u16 params, byte_count;
3078 cFYI(1, ("In QPathInfo (Unix) the path %s", searchName));
3080 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3085 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3087 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
3088 PATH_MAX, nls_codepage, remap);
3089 name_len++; /* trailing null */
3091 } else { /* BB improve the check for buffer overruns BB */
3092 name_len = strnlen(searchName, PATH_MAX);
3093 name_len++; /* trailing null */
3094 strncpy(pSMB->FileName, searchName, name_len);
3097 params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */ ;
3098 pSMB->TotalDataCount = 0;
3099 pSMB->MaxParameterCount = cpu_to_le16(2);
3100 /* BB find exact max SMB PDU from sess structure BB */
3101 pSMB->MaxDataCount = cpu_to_le16(4000);
3102 pSMB->MaxSetupCount = 0;
3106 pSMB->Reserved2 = 0;
3107 pSMB->ParameterOffset = cpu_to_le16(offsetof(
3108 struct smb_com_transaction2_qpi_req ,InformationLevel) - 4);
3109 pSMB->DataCount = 0;
3110 pSMB->DataOffset = 0;
3111 pSMB->SetupCount = 1;
3112 pSMB->Reserved3 = 0;
3113 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
3114 byte_count = params + 1 /* pad */ ;
3115 pSMB->TotalParameterCount = cpu_to_le16(params);
3116 pSMB->ParameterCount = pSMB->TotalParameterCount;
3117 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC);
3118 pSMB->Reserved4 = 0;
3119 pSMB->hdr.smb_buf_length += byte_count;
3120 pSMB->ByteCount = cpu_to_le16(byte_count);
3122 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3123 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3125 cFYI(1, ("Send error in QPathInfo = %d", rc));
3126 } else { /* decode response */
3127 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3129 if (rc || (pSMBr->ByteCount < sizeof(FILE_UNIX_BASIC_INFO))) {
3130 rc = -EIO; /* bad smb */
3132 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3133 memcpy((char *) pFindData,
3134 (char *) &pSMBr->hdr.Protocol +
3136 sizeof (FILE_UNIX_BASIC_INFO));
3139 cifs_buf_release(pSMB);
3141 goto UnixQPathInfoRetry;
3146 #if 0 /* function unused at present */
3147 int CIFSFindSingle(const int xid, struct cifsTconInfo *tcon,
3148 const char *searchName, FILE_ALL_INFO * findData,
3149 const struct nls_table *nls_codepage)
3151 /* level 257 SMB_ */
3152 TRANSACTION2_FFIRST_REQ *pSMB = NULL;
3153 TRANSACTION2_FFIRST_RSP *pSMBr = NULL;
3157 __u16 params, byte_count;
3159 cFYI(1, ("In FindUnique"));
3161 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3166 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3168 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName, PATH_MAX
3169 /* find define for this maxpathcomponent */
3171 name_len++; /* trailing null */
3173 } else { /* BB improve the check for buffer overruns BB */
3174 name_len = strnlen(searchName, PATH_MAX);
3175 name_len++; /* trailing null */
3176 strncpy(pSMB->FileName, searchName, name_len);
3179 params = 12 + name_len /* includes null */ ;
3180 pSMB->TotalDataCount = 0; /* no EAs */
3181 pSMB->MaxParameterCount = cpu_to_le16(2);
3182 pSMB->MaxDataCount = cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
3183 pSMB->MaxSetupCount = 0;
3187 pSMB->Reserved2 = 0;
3188 pSMB->ParameterOffset = cpu_to_le16(
3189 offsetof(struct smb_com_transaction2_ffirst_req,InformationLevel) - 4);
3190 pSMB->DataCount = 0;
3191 pSMB->DataOffset = 0;
3192 pSMB->SetupCount = 1; /* one byte, no need to le convert */
3193 pSMB->Reserved3 = 0;
3194 pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_FIRST);
3195 byte_count = params + 1 /* pad */ ;
3196 pSMB->TotalParameterCount = cpu_to_le16(params);
3197 pSMB->ParameterCount = pSMB->TotalParameterCount;
3198 pSMB->SearchAttributes =
3199 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
3201 pSMB->SearchCount = cpu_to_le16(16); /* BB increase */
3202 pSMB->SearchFlags = cpu_to_le16(1);
3203 pSMB->InformationLevel = cpu_to_le16(SMB_FIND_FILE_DIRECTORY_INFO);
3204 pSMB->SearchStorageType = 0; /* BB what should we set this to? BB */
3205 pSMB->hdr.smb_buf_length += byte_count;
3206 pSMB->ByteCount = cpu_to_le16(byte_count);
3208 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3209 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3212 cFYI(1, ("Send error in FindFileDirInfo = %d", rc));
3213 } else { /* decode response */
3214 cifs_stats_inc(&tcon->num_ffirst);
3218 cifs_buf_release(pSMB);
3220 goto findUniqueRetry;
3224 #endif /* end unused (temporarily) function */
3226 /* xid, tcon, searchName and codepage are input parms, rest are returned */
3228 CIFSFindFirst(const int xid, struct cifsTconInfo *tcon,
3229 const char *searchName,
3230 const struct nls_table *nls_codepage,
3232 struct cifs_search_info * psrch_inf, int remap, const char dirsep)
3234 /* level 257 SMB_ */
3235 TRANSACTION2_FFIRST_REQ *pSMB = NULL;
3236 TRANSACTION2_FFIRST_RSP *pSMBr = NULL;
3237 T2_FFIRST_RSP_PARMS * parms;
3239 int bytes_returned = 0;
3241 __u16 params, byte_count;
3243 cFYI(1, ("In FindFirst for %s",searchName));
3246 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3251 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3253 cifsConvertToUCS((__le16 *) pSMB->FileName,searchName,
3254 PATH_MAX, nls_codepage, remap);
3255 /* We can not add the asterik earlier in case
3256 it got remapped to 0xF03A as if it were part of the
3257 directory name instead of a wildcard */
3259 pSMB->FileName[name_len] = dirsep;
3260 pSMB->FileName[name_len+1] = 0;
3261 pSMB->FileName[name_len+2] = '*';
3262 pSMB->FileName[name_len+3] = 0;
3263 name_len += 4; /* now the trailing null */
3264 pSMB->FileName[name_len] = 0; /* null terminate just in case */
3265 pSMB->FileName[name_len+1] = 0;
3267 } else { /* BB add check for overrun of SMB buf BB */
3268 name_len = strnlen(searchName, PATH_MAX);
3269 /* BB fix here and in unicode clause above ie
3270 if(name_len > buffersize-header)
3271 free buffer exit; BB */
3272 strncpy(pSMB->FileName, searchName, name_len);
3273 pSMB->FileName[name_len] = dirsep;
3274 pSMB->FileName[name_len+1] = '*';
3275 pSMB->FileName[name_len+2] = 0;
3279 params = 12 + name_len /* includes null */ ;
3280 pSMB->TotalDataCount = 0; /* no EAs */
3281 pSMB->MaxParameterCount = cpu_to_le16(10);
3282 pSMB->MaxDataCount = cpu_to_le16((tcon->ses->server->maxBuf -
3283 MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
3284 pSMB->MaxSetupCount = 0;
3288 pSMB->Reserved2 = 0;
3289 byte_count = params + 1 /* pad */ ;
3290 pSMB->TotalParameterCount = cpu_to_le16(params);
3291 pSMB->ParameterCount = pSMB->TotalParameterCount;
3292 pSMB->ParameterOffset = cpu_to_le16(
3293 offsetof(struct smb_com_transaction2_ffirst_req, SearchAttributes)
3295 pSMB->DataCount = 0;
3296 pSMB->DataOffset = 0;
3297 pSMB->SetupCount = 1; /* one byte, no need to make endian neutral */
3298 pSMB->Reserved3 = 0;
3299 pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_FIRST);
3300 pSMB->SearchAttributes =
3301 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
3303 pSMB->SearchCount= cpu_to_le16(CIFSMaxBufSize/sizeof(FILE_UNIX_INFO));
3304 pSMB->SearchFlags = cpu_to_le16(CIFS_SEARCH_CLOSE_AT_END |
3305 CIFS_SEARCH_RETURN_RESUME);
3306 pSMB->InformationLevel = cpu_to_le16(psrch_inf->info_level);
3308 /* BB what should we set StorageType to? Does it matter? BB */
3309 pSMB->SearchStorageType = 0;
3310 pSMB->hdr.smb_buf_length += byte_count;
3311 pSMB->ByteCount = cpu_to_le16(byte_count);
3313 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3314 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3315 cifs_stats_inc(&tcon->num_ffirst);
3317 if (rc) {/* BB add logic to retry regular search if Unix search
3318 rejected unexpectedly by server */
3319 /* BB Add code to handle unsupported level rc */
3320 cFYI(1, ("Error in FindFirst = %d", rc));
3322 cifs_buf_release(pSMB);
3324 /* BB eventually could optimize out free and realloc of buf */
3327 goto findFirstRetry;
3328 } else { /* decode response */
3329 /* BB remember to free buffer if error BB */
3330 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3332 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
3333 psrch_inf->unicode = TRUE;
3335 psrch_inf->unicode = FALSE;
3337 psrch_inf->ntwrk_buf_start = (char *)pSMBr;
3338 psrch_inf->smallBuf = 0;
3339 psrch_inf->srch_entries_start =
3340 (char *) &pSMBr->hdr.Protocol +
3341 le16_to_cpu(pSMBr->t2.DataOffset);
3342 parms = (T2_FFIRST_RSP_PARMS *)((char *) &pSMBr->hdr.Protocol +
3343 le16_to_cpu(pSMBr->t2.ParameterOffset));
3345 if(parms->EndofSearch)
3346 psrch_inf->endOfSearch = TRUE;
3348 psrch_inf->endOfSearch = FALSE;
3350 psrch_inf->entries_in_buffer = le16_to_cpu(parms->SearchCount);
3351 psrch_inf->index_of_last_entry = 2 /* skip . and .. */ +
3352 psrch_inf->entries_in_buffer;
3353 *pnetfid = parms->SearchHandle;
3355 cifs_buf_release(pSMB);
3362 int CIFSFindNext(const int xid, struct cifsTconInfo *tcon,
3363 __u16 searchHandle, struct cifs_search_info * psrch_inf)
3365 TRANSACTION2_FNEXT_REQ *pSMB = NULL;
3366 TRANSACTION2_FNEXT_RSP *pSMBr = NULL;
3367 T2_FNEXT_RSP_PARMS * parms;
3368 char *response_data;
3370 int bytes_returned, name_len;
3371 __u16 params, byte_count;
3373 cFYI(1, ("In FindNext"));
3375 if(psrch_inf->endOfSearch == TRUE)
3378 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3383 params = 14; /* includes 2 bytes of null string, converted to LE below */
3385 pSMB->TotalDataCount = 0; /* no EAs */
3386 pSMB->MaxParameterCount = cpu_to_le16(8);
3387 pSMB->MaxDataCount =
3388 cpu_to_le16((tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
3389 pSMB->MaxSetupCount = 0;
3393 pSMB->Reserved2 = 0;
3394 pSMB->ParameterOffset = cpu_to_le16(
3395 offsetof(struct smb_com_transaction2_fnext_req,SearchHandle) - 4);
3396 pSMB->DataCount = 0;
3397 pSMB->DataOffset = 0;
3398 pSMB->SetupCount = 1;
3399 pSMB->Reserved3 = 0;
3400 pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_NEXT);
3401 pSMB->SearchHandle = searchHandle; /* always kept as le */
3403 cpu_to_le16(CIFSMaxBufSize / sizeof (FILE_UNIX_INFO));
3404 /* test for Unix extensions */
3405 /* if (tcon->ses->capabilities & CAP_UNIX) {
3406 pSMB->InformationLevel = cpu_to_le16(SMB_FIND_FILE_UNIX);
3407 psrch_inf->info_level = SMB_FIND_FILE_UNIX;
3409 pSMB->InformationLevel =
3410 cpu_to_le16(SMB_FIND_FILE_DIRECTORY_INFO);
3411 psrch_inf->info_level = SMB_FIND_FILE_DIRECTORY_INFO;
3413 pSMB->InformationLevel = cpu_to_le16(psrch_inf->info_level);
3414 pSMB->ResumeKey = psrch_inf->resume_key;
3416 cpu_to_le16(CIFS_SEARCH_CLOSE_AT_END | CIFS_SEARCH_RETURN_RESUME);
3418 name_len = psrch_inf->resume_name_len;
3420 if(name_len < PATH_MAX) {
3421 memcpy(pSMB->ResumeFileName, psrch_inf->presume_name, name_len);
3422 byte_count += name_len;
3423 /* 14 byte parm len above enough for 2 byte null terminator */
3424 pSMB->ResumeFileName[name_len] = 0;
3425 pSMB->ResumeFileName[name_len+1] = 0;
3428 goto FNext2_err_exit;
3430 byte_count = params + 1 /* pad */ ;
3431 pSMB->TotalParameterCount = cpu_to_le16(params);
3432 pSMB->ParameterCount = pSMB->TotalParameterCount;
3433 pSMB->hdr.smb_buf_length += byte_count;
3434 pSMB->ByteCount = cpu_to_le16(byte_count);
3436 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3437 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3438 cifs_stats_inc(&tcon->num_fnext);
3441 psrch_inf->endOfSearch = TRUE;
3442 rc = 0; /* search probably was closed at end of search above */
3444 cFYI(1, ("FindNext returned = %d", rc));
3445 } else { /* decode response */
3446 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3449 /* BB fixme add lock for file (srch_info) struct here */
3450 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
3451 psrch_inf->unicode = TRUE;
3453 psrch_inf->unicode = FALSE;
3454 response_data = (char *) &pSMBr->hdr.Protocol +
3455 le16_to_cpu(pSMBr->t2.ParameterOffset);
3456 parms = (T2_FNEXT_RSP_PARMS *)response_data;
3457 response_data = (char *)&pSMBr->hdr.Protocol +
3458 le16_to_cpu(pSMBr->t2.DataOffset);
3459 if(psrch_inf->smallBuf)
3460 cifs_small_buf_release(
3461 psrch_inf->ntwrk_buf_start);
3463 cifs_buf_release(psrch_inf->ntwrk_buf_start);
3464 psrch_inf->srch_entries_start = response_data;
3465 psrch_inf->ntwrk_buf_start = (char *)pSMB;
3466 psrch_inf->smallBuf = 0;
3467 if(parms->EndofSearch)
3468 psrch_inf->endOfSearch = TRUE;
3470 psrch_inf->endOfSearch = FALSE;
3472 psrch_inf->entries_in_buffer = le16_to_cpu(parms->SearchCount);
3473 psrch_inf->index_of_last_entry +=
3474 psrch_inf->entries_in_buffer;
3475 /* cFYI(1,("fnxt2 entries in buf %d index_of_last %d",psrch_inf->entries_in_buffer,psrch_inf->index_of_last_entry)); */
3477 /* BB fixme add unlock here */
3482 /* BB On error, should we leave previous search buf (and count and
3483 last entry fields) intact or free the previous one? */
3485 /* Note: On -EAGAIN error only caller can retry on handle based calls
3486 since file handle passed in no longer valid */
3489 cifs_buf_release(pSMB);
3495 CIFSFindClose(const int xid, struct cifsTconInfo *tcon, const __u16 searchHandle)
3498 FINDCLOSE_REQ *pSMB = NULL;
3499 CLOSE_RSP *pSMBr = NULL; /* BB removeme BB */
3502 cFYI(1, ("In CIFSSMBFindClose"));
3503 rc = small_smb_init(SMB_COM_FIND_CLOSE2, 1, tcon, (void **)&pSMB);
3505 /* no sense returning error if session restarted
3506 as file handle has been closed */
3512 pSMBr = (CLOSE_RSP *)pSMB; /* BB removeme BB */
3513 pSMB->FileID = searchHandle;
3514 pSMB->ByteCount = 0;
3515 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3516 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3518 cERROR(1, ("Send error in FindClose = %d", rc));
3520 cifs_stats_inc(&tcon->num_fclose);
3521 cifs_small_buf_release(pSMB);
3523 /* Since session is dead, search handle closed on server already */
3531 CIFSGetSrvInodeNumber(const int xid, struct cifsTconInfo *tcon,
3532 const unsigned char *searchName,
3533 __u64 * inode_number,
3534 const struct nls_table *nls_codepage, int remap)
3537 TRANSACTION2_QPI_REQ *pSMB = NULL;
3538 TRANSACTION2_QPI_RSP *pSMBr = NULL;
3539 int name_len, bytes_returned;
3540 __u16 params, byte_count;
3542 cFYI(1,("In GetSrvInodeNum for %s",searchName));
3546 GetInodeNumberRetry:
3547 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3553 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3555 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
3556 PATH_MAX,nls_codepage, remap);
3557 name_len++; /* trailing null */
3559 } else { /* BB improve the check for buffer overruns BB */
3560 name_len = strnlen(searchName, PATH_MAX);
3561 name_len++; /* trailing null */
3562 strncpy(pSMB->FileName, searchName, name_len);
3565 params = 2 /* level */ + 4 /* rsrvd */ + name_len /* incl null */ ;
3566 pSMB->TotalDataCount = 0;
3567 pSMB->MaxParameterCount = cpu_to_le16(2);
3568 /* BB find exact max data count below from sess structure BB */
3569 pSMB->MaxDataCount = cpu_to_le16(4000);
3570 pSMB->MaxSetupCount = 0;
3574 pSMB->Reserved2 = 0;
3575 pSMB->ParameterOffset = cpu_to_le16(offsetof(
3576 struct smb_com_transaction2_qpi_req ,InformationLevel) - 4);
3577 pSMB->DataCount = 0;
3578 pSMB->DataOffset = 0;
3579 pSMB->SetupCount = 1;
3580 pSMB->Reserved3 = 0;
3581 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
3582 byte_count = params + 1 /* pad */ ;
3583 pSMB->TotalParameterCount = cpu_to_le16(params);
3584 pSMB->ParameterCount = pSMB->TotalParameterCount;
3585 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_INTERNAL_INFO);
3586 pSMB->Reserved4 = 0;
3587 pSMB->hdr.smb_buf_length += byte_count;
3588 pSMB->ByteCount = cpu_to_le16(byte_count);
3590 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3591 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3593 cFYI(1, ("error %d in QueryInternalInfo", rc));
3595 /* decode response */
3596 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3597 if (rc || (pSMBr->ByteCount < 2))
3598 /* BB also check enough total bytes returned */
3599 /* If rc should we check for EOPNOSUPP and
3600 disable the srvino flag? or in caller? */
3601 rc = -EIO; /* bad smb */
3603 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3604 __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
3605 struct file_internal_info * pfinfo;
3606 /* BB Do we need a cast or hash here ? */
3608 cFYI(1, ("Illegal size ret in QryIntrnlInf"));
3610 goto GetInodeNumOut;
3612 pfinfo = (struct file_internal_info *)
3613 (data_offset + (char *) &pSMBr->hdr.Protocol);
3614 *inode_number = pfinfo->UniqueId;
3618 cifs_buf_release(pSMB);
3620 goto GetInodeNumberRetry;
3625 CIFSGetDFSRefer(const int xid, struct cifsSesInfo *ses,
3626 const unsigned char *searchName,
3627 unsigned char **targetUNCs,
3628 unsigned int *number_of_UNC_in_array,
3629 const struct nls_table *nls_codepage, int remap)
3631 /* TRANS2_GET_DFS_REFERRAL */
3632 TRANSACTION2_GET_DFS_REFER_REQ *pSMB = NULL;
3633 TRANSACTION2_GET_DFS_REFER_RSP *pSMBr = NULL;
3634 struct dfs_referral_level_3 * referrals = NULL;
3640 __u16 params, byte_count;
3641 *number_of_UNC_in_array = 0;
3644 cFYI(1, ("In GetDFSRefer the path %s", searchName));
3648 rc = smb_init(SMB_COM_TRANSACTION2, 15, NULL, (void **) &pSMB,
3653 /* server pointer checked in called function,
3654 but should never be null here anyway */
3655 pSMB->hdr.Mid = GetNextMid(ses->server);
3656 pSMB->hdr.Tid = ses->ipc_tid;
3657 pSMB->hdr.Uid = ses->Suid;
3658 if (ses->capabilities & CAP_STATUS32) {
3659 pSMB->hdr.Flags2 |= SMBFLG2_ERR_STATUS;
3661 if (ses->capabilities & CAP_DFS) {
3662 pSMB->hdr.Flags2 |= SMBFLG2_DFS;
3665 if (ses->capabilities & CAP_UNICODE) {
3666 pSMB->hdr.Flags2 |= SMBFLG2_UNICODE;
3668 cifsConvertToUCS((__le16 *) pSMB->RequestFileName,
3669 searchName, PATH_MAX, nls_codepage, remap);
3670 name_len++; /* trailing null */
3672 } else { /* BB improve the check for buffer overruns BB */
3673 name_len = strnlen(searchName, PATH_MAX);
3674 name_len++; /* trailing null */
3675 strncpy(pSMB->RequestFileName, searchName, name_len);
3679 if(ses->server->secMode &
3680 (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
3681 pSMB->hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
3684 pSMB->hdr.Uid = ses->Suid;
3686 params = 2 /* level */ + name_len /*includes null */ ;
3687 pSMB->TotalDataCount = 0;
3688 pSMB->DataCount = 0;
3689 pSMB->DataOffset = 0;
3690 pSMB->MaxParameterCount = 0;
3691 pSMB->MaxDataCount = cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
3692 pSMB->MaxSetupCount = 0;
3696 pSMB->Reserved2 = 0;
3697 pSMB->ParameterOffset = cpu_to_le16(offsetof(
3698 struct smb_com_transaction2_get_dfs_refer_req, MaxReferralLevel) - 4);
3699 pSMB->SetupCount = 1;
3700 pSMB->Reserved3 = 0;
3701 pSMB->SubCommand = cpu_to_le16(TRANS2_GET_DFS_REFERRAL);
3702 byte_count = params + 3 /* pad */ ;
3703 pSMB->ParameterCount = cpu_to_le16(params);
3704 pSMB->TotalParameterCount = pSMB->ParameterCount;
3705 pSMB->MaxReferralLevel = cpu_to_le16(3);
3706 pSMB->hdr.smb_buf_length += byte_count;
3707 pSMB->ByteCount = cpu_to_le16(byte_count);
3709 rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB,
3710 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3712 cFYI(1, ("Send error in GetDFSRefer = %d", rc));
3713 } else { /* decode response */
3714 /* BB Add logic to parse referrals here */
3715 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3717 if (rc || (pSMBr->ByteCount < 17)) /* BB also check enough total bytes returned */
3718 rc = -EIO; /* bad smb */
3720 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3721 __u16 data_count = le16_to_cpu(pSMBr->t2.DataCount);
3724 ("Decoding GetDFSRefer response. BCC: %d Offset %d",
3725 pSMBr->ByteCount, data_offset));
3727 (struct dfs_referral_level_3 *)
3728 (8 /* sizeof start of data block */ +
3730 (char *) &pSMBr->hdr.Protocol);
3731 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",
3732 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)));
3733 /* BB This field is actually two bytes in from start of
3734 data block so we could do safety check that DataBlock
3735 begins at address of pSMBr->NumberOfReferrals */
3736 *number_of_UNC_in_array = le16_to_cpu(pSMBr->NumberOfReferrals);
3738 /* BB Fix below so can return more than one referral */
3739 if(*number_of_UNC_in_array > 1)
3740 *number_of_UNC_in_array = 1;
3742 /* get the length of the strings describing refs */
3744 for(i=0;i<*number_of_UNC_in_array;i++) {
3745 /* make sure that DfsPathOffset not past end */
3746 __u16 offset = le16_to_cpu(referrals->DfsPathOffset);
3747 if (offset > data_count) {
3748 /* if invalid referral, stop here and do
3749 not try to copy any more */
3750 *number_of_UNC_in_array = i;
3753 temp = ((char *)referrals) + offset;
3755 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
3756 name_len += UniStrnlen((wchar_t *)temp,data_count);
3758 name_len += strnlen(temp,data_count);
3761 /* BB add check that referral pointer does not fall off end PDU */
3764 /* BB add check for name_len bigger than bcc */
3766 kmalloc(name_len+1+ (*number_of_UNC_in_array),GFP_KERNEL);
3767 if(*targetUNCs == NULL) {
3771 /* copy the ref strings */
3773 (struct dfs_referral_level_3 *)
3774 (8 /* sizeof data hdr */ +
3776 (char *) &pSMBr->hdr.Protocol);
3778 for(i=0;i<*number_of_UNC_in_array;i++) {
3779 temp = ((char *)referrals) + le16_to_cpu(referrals->DfsPathOffset);
3780 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
3781 cifs_strfromUCS_le(*targetUNCs,
3782 (__le16 *) temp, name_len, nls_codepage);
3784 strncpy(*targetUNCs,temp,name_len);
3786 /* BB update target_uncs pointers */
3796 cifs_buf_release(pSMB);
3804 /* Query File System Info such as free space to old servers such as Win 9x */
3806 SMBOldQFSInfo(const int xid, struct cifsTconInfo *tcon, struct kstatfs *FSData)
3808 /* level 0x01 SMB_QUERY_FILE_SYSTEM_INFO */
3809 TRANSACTION2_QFSI_REQ *pSMB = NULL;
3810 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
3811 FILE_SYSTEM_ALLOC_INFO *response_data;
3813 int bytes_returned = 0;
3814 __u16 params, byte_count;
3816 cFYI(1, ("OldQFSInfo"));
3818 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3822 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3827 params = 2; /* level */
3828 pSMB->TotalDataCount = 0;
3829 pSMB->MaxParameterCount = cpu_to_le16(2);
3830 pSMB->MaxDataCount = cpu_to_le16(1000);
3831 pSMB->MaxSetupCount = 0;
3835 pSMB->Reserved2 = 0;
3836 byte_count = params + 1 /* pad */ ;
3837 pSMB->TotalParameterCount = cpu_to_le16(params);
3838 pSMB->ParameterCount = pSMB->TotalParameterCount;
3839 pSMB->ParameterOffset = cpu_to_le16(offsetof(
3840 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
3841 pSMB->DataCount = 0;
3842 pSMB->DataOffset = 0;
3843 pSMB->SetupCount = 1;
3844 pSMB->Reserved3 = 0;
3845 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
3846 pSMB->InformationLevel = cpu_to_le16(SMB_INFO_ALLOCATION);
3847 pSMB->hdr.smb_buf_length += byte_count;
3848 pSMB->ByteCount = cpu_to_le16(byte_count);
3850 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3851 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3853 cFYI(1, ("Send error in QFSInfo = %d", rc));
3854 } else { /* decode response */
3855 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3857 if (rc || (pSMBr->ByteCount < 18))
3858 rc = -EIO; /* bad smb */
3860 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3861 cFYI(1,("qfsinf resp BCC: %d Offset %d",
3862 pSMBr->ByteCount, data_offset));
3865 (FILE_SYSTEM_ALLOC_INFO *)
3866 (((char *) &pSMBr->hdr.Protocol) + data_offset);
3868 le16_to_cpu(response_data->BytesPerSector) *
3869 le32_to_cpu(response_data->
3870 SectorsPerAllocationUnit);
3872 le32_to_cpu(response_data->TotalAllocationUnits);
3873 FSData->f_bfree = FSData->f_bavail =
3874 le32_to_cpu(response_data->FreeAllocationUnits);
3876 ("Blocks: %lld Free: %lld Block size %ld",
3877 (unsigned long long)FSData->f_blocks,
3878 (unsigned long long)FSData->f_bfree,
3882 cifs_buf_release(pSMB);
3885 goto oldQFSInfoRetry;
3891 CIFSSMBQFSInfo(const int xid, struct cifsTconInfo *tcon, struct kstatfs *FSData)
3893 /* level 0x103 SMB_QUERY_FILE_SYSTEM_INFO */
3894 TRANSACTION2_QFSI_REQ *pSMB = NULL;
3895 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
3896 FILE_SYSTEM_INFO *response_data;
3898 int bytes_returned = 0;
3899 __u16 params, byte_count;
3901 cFYI(1, ("In QFSInfo"));
3903 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3908 params = 2; /* level */
3909 pSMB->TotalDataCount = 0;
3910 pSMB->MaxParameterCount = cpu_to_le16(2);
3911 pSMB->MaxDataCount = cpu_to_le16(1000);
3912 pSMB->MaxSetupCount = 0;
3916 pSMB->Reserved2 = 0;
3917 byte_count = params + 1 /* pad */ ;
3918 pSMB->TotalParameterCount = cpu_to_le16(params);
3919 pSMB->ParameterCount = pSMB->TotalParameterCount;
3920 pSMB->ParameterOffset = cpu_to_le16(offsetof(
3921 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
3922 pSMB->DataCount = 0;
3923 pSMB->DataOffset = 0;
3924 pSMB->SetupCount = 1;
3925 pSMB->Reserved3 = 0;
3926 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
3927 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_SIZE_INFO);
3928 pSMB->hdr.smb_buf_length += byte_count;
3929 pSMB->ByteCount = cpu_to_le16(byte_count);
3931 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3932 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3934 cFYI(1, ("Send error in QFSInfo = %d", rc));
3935 } else { /* decode response */
3936 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3938 if (rc || (pSMBr->ByteCount < 24))
3939 rc = -EIO; /* bad smb */
3941 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3945 *) (((char *) &pSMBr->hdr.Protocol) +
3948 le32_to_cpu(response_data->BytesPerSector) *
3949 le32_to_cpu(response_data->
3950 SectorsPerAllocationUnit);
3952 le64_to_cpu(response_data->TotalAllocationUnits);
3953 FSData->f_bfree = FSData->f_bavail =
3954 le64_to_cpu(response_data->FreeAllocationUnits);
3956 ("Blocks: %lld Free: %lld Block size %ld",
3957 (unsigned long long)FSData->f_blocks,
3958 (unsigned long long)FSData->f_bfree,
3962 cifs_buf_release(pSMB);
3971 CIFSSMBQFSAttributeInfo(const int xid, struct cifsTconInfo *tcon)
3973 /* level 0x105 SMB_QUERY_FILE_SYSTEM_INFO */
3974 TRANSACTION2_QFSI_REQ *pSMB = NULL;
3975 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
3976 FILE_SYSTEM_ATTRIBUTE_INFO *response_data;
3978 int bytes_returned = 0;
3979 __u16 params, byte_count;
3981 cFYI(1, ("In QFSAttributeInfo"));
3983 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3988 params = 2; /* level */
3989 pSMB->TotalDataCount = 0;
3990 pSMB->MaxParameterCount = cpu_to_le16(2);
3991 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
3992 pSMB->MaxSetupCount = 0;
3996 pSMB->Reserved2 = 0;
3997 byte_count = params + 1 /* pad */ ;
3998 pSMB->TotalParameterCount = cpu_to_le16(params);
3999 pSMB->ParameterCount = pSMB->TotalParameterCount;
4000 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4001 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4002 pSMB->DataCount = 0;
4003 pSMB->DataOffset = 0;
4004 pSMB->SetupCount = 1;
4005 pSMB->Reserved3 = 0;
4006 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4007 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_ATTRIBUTE_INFO);
4008 pSMB->hdr.smb_buf_length += byte_count;
4009 pSMB->ByteCount = cpu_to_le16(byte_count);
4011 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4012 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4014 cERROR(1, ("Send error in QFSAttributeInfo = %d", rc));
4015 } else { /* decode response */
4016 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4018 if (rc || (pSMBr->ByteCount < 13)) { /* BB also check enough bytes returned */
4019 rc = -EIO; /* bad smb */
4021 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4023 (FILE_SYSTEM_ATTRIBUTE_INFO
4024 *) (((char *) &pSMBr->hdr.Protocol) +
4026 memcpy(&tcon->fsAttrInfo, response_data,
4027 sizeof (FILE_SYSTEM_ATTRIBUTE_INFO));
4030 cifs_buf_release(pSMB);
4033 goto QFSAttributeRetry;
4039 CIFSSMBQFSDeviceInfo(const int xid, struct cifsTconInfo *tcon)
4041 /* level 0x104 SMB_QUERY_FILE_SYSTEM_INFO */
4042 TRANSACTION2_QFSI_REQ *pSMB = NULL;
4043 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4044 FILE_SYSTEM_DEVICE_INFO *response_data;
4046 int bytes_returned = 0;
4047 __u16 params, byte_count;
4049 cFYI(1, ("In QFSDeviceInfo"));
4051 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4056 params = 2; /* level */
4057 pSMB->TotalDataCount = 0;
4058 pSMB->MaxParameterCount = cpu_to_le16(2);
4059 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
4060 pSMB->MaxSetupCount = 0;
4064 pSMB->Reserved2 = 0;
4065 byte_count = params + 1 /* pad */ ;
4066 pSMB->TotalParameterCount = cpu_to_le16(params);
4067 pSMB->ParameterCount = pSMB->TotalParameterCount;
4068 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4069 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4071 pSMB->DataCount = 0;
4072 pSMB->DataOffset = 0;
4073 pSMB->SetupCount = 1;
4074 pSMB->Reserved3 = 0;
4075 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4076 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_DEVICE_INFO);
4077 pSMB->hdr.smb_buf_length += byte_count;
4078 pSMB->ByteCount = cpu_to_le16(byte_count);
4080 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4081 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4083 cFYI(1, ("Send error in QFSDeviceInfo = %d", rc));
4084 } else { /* decode response */
4085 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4087 if (rc || (pSMBr->ByteCount < sizeof (FILE_SYSTEM_DEVICE_INFO)))
4088 rc = -EIO; /* bad smb */
4090 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4092 (FILE_SYSTEM_DEVICE_INFO *)
4093 (((char *) &pSMBr->hdr.Protocol) +
4095 memcpy(&tcon->fsDevInfo, response_data,
4096 sizeof (FILE_SYSTEM_DEVICE_INFO));
4099 cifs_buf_release(pSMB);
4102 goto QFSDeviceRetry;
4108 CIFSSMBQFSUnixInfo(const int xid, struct cifsTconInfo *tcon)
4110 /* level 0x200 SMB_QUERY_CIFS_UNIX_INFO */
4111 TRANSACTION2_QFSI_REQ *pSMB = NULL;
4112 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4113 FILE_SYSTEM_UNIX_INFO *response_data;
4115 int bytes_returned = 0;
4116 __u16 params, byte_count;
4118 cFYI(1, ("In QFSUnixInfo"));
4120 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4125 params = 2; /* level */
4126 pSMB->TotalDataCount = 0;
4127 pSMB->DataCount = 0;
4128 pSMB->DataOffset = 0;
4129 pSMB->MaxParameterCount = cpu_to_le16(2);
4130 pSMB->MaxDataCount = cpu_to_le16(100); /* BB find exact max SMB PDU from sess structure BB */
4131 pSMB->MaxSetupCount = 0;
4135 pSMB->Reserved2 = 0;
4136 byte_count = params + 1 /* pad */ ;
4137 pSMB->ParameterCount = cpu_to_le16(params);
4138 pSMB->TotalParameterCount = pSMB->ParameterCount;
4139 pSMB->ParameterOffset = cpu_to_le16(offsetof(struct
4140 smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4141 pSMB->SetupCount = 1;
4142 pSMB->Reserved3 = 0;
4143 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4144 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_CIFS_UNIX_INFO);
4145 pSMB->hdr.smb_buf_length += byte_count;
4146 pSMB->ByteCount = cpu_to_le16(byte_count);
4148 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4149 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4151 cERROR(1, ("Send error in QFSUnixInfo = %d", rc));
4152 } else { /* decode response */
4153 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4155 if (rc || (pSMBr->ByteCount < 13)) {
4156 rc = -EIO; /* bad smb */
4158 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4160 (FILE_SYSTEM_UNIX_INFO
4161 *) (((char *) &pSMBr->hdr.Protocol) +
4163 memcpy(&tcon->fsUnixInfo, response_data,
4164 sizeof (FILE_SYSTEM_UNIX_INFO));
4167 cifs_buf_release(pSMB);
4177 CIFSSMBSetFSUnixInfo(const int xid, struct cifsTconInfo *tcon, __u64 cap)
4179 /* level 0x200 SMB_SET_CIFS_UNIX_INFO */
4180 TRANSACTION2_SETFSI_REQ *pSMB = NULL;
4181 TRANSACTION2_SETFSI_RSP *pSMBr = NULL;
4183 int bytes_returned = 0;
4184 __u16 params, param_offset, offset, byte_count;
4186 cFYI(1, ("In SETFSUnixInfo"));
4188 /* BB switch to small buf init to save memory */
4189 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4194 params = 4; /* 2 bytes zero followed by info level. */
4195 pSMB->MaxSetupCount = 0;
4199 pSMB->Reserved2 = 0;
4200 param_offset = offsetof(struct smb_com_transaction2_setfsi_req, FileNum) - 4;
4201 offset = param_offset + params;
4203 pSMB->MaxParameterCount = cpu_to_le16(4);
4204 pSMB->MaxDataCount = cpu_to_le16(100); /* BB find exact max SMB PDU from sess structure BB */
4205 pSMB->SetupCount = 1;
4206 pSMB->Reserved3 = 0;
4207 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FS_INFORMATION);
4208 byte_count = 1 /* pad */ + params + 12;
4210 pSMB->DataCount = cpu_to_le16(12);
4211 pSMB->ParameterCount = cpu_to_le16(params);
4212 pSMB->TotalDataCount = pSMB->DataCount;
4213 pSMB->TotalParameterCount = pSMB->ParameterCount;
4214 pSMB->ParameterOffset = cpu_to_le16(param_offset);
4215 pSMB->DataOffset = cpu_to_le16(offset);
4219 pSMB->InformationLevel = cpu_to_le16(SMB_SET_CIFS_UNIX_INFO);
4222 pSMB->ClientUnixMajor = cpu_to_le16(CIFS_UNIX_MAJOR_VERSION);
4223 pSMB->ClientUnixMinor = cpu_to_le16(CIFS_UNIX_MINOR_VERSION);
4224 pSMB->ClientUnixCap = cpu_to_le64(cap);
4226 pSMB->hdr.smb_buf_length += byte_count;
4227 pSMB->ByteCount = cpu_to_le16(byte_count);
4229 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4230 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4232 cERROR(1, ("Send error in SETFSUnixInfo = %d", rc));
4233 } else { /* decode response */
4234 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4236 rc = -EIO; /* bad smb */
4239 cifs_buf_release(pSMB);
4242 goto SETFSUnixRetry;
4250 CIFSSMBQFSPosixInfo(const int xid, struct cifsTconInfo *tcon,
4251 struct kstatfs *FSData)
4253 /* level 0x201 SMB_QUERY_CIFS_POSIX_INFO */
4254 TRANSACTION2_QFSI_REQ *pSMB = NULL;
4255 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4256 FILE_SYSTEM_POSIX_INFO *response_data;
4258 int bytes_returned = 0;
4259 __u16 params, byte_count;
4261 cFYI(1, ("In QFSPosixInfo"));
4263 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4268 params = 2; /* level */
4269 pSMB->TotalDataCount = 0;
4270 pSMB->DataCount = 0;
4271 pSMB->DataOffset = 0;
4272 pSMB->MaxParameterCount = cpu_to_le16(2);
4273 pSMB->MaxDataCount = cpu_to_le16(100); /* BB find exact max SMB PDU from sess structure BB */
4274 pSMB->MaxSetupCount = 0;
4278 pSMB->Reserved2 = 0;
4279 byte_count = params + 1 /* pad */ ;
4280 pSMB->ParameterCount = cpu_to_le16(params);
4281 pSMB->TotalParameterCount = pSMB->ParameterCount;
4282 pSMB->ParameterOffset = cpu_to_le16(offsetof(struct
4283 smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4284 pSMB->SetupCount = 1;
4285 pSMB->Reserved3 = 0;
4286 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4287 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_POSIX_FS_INFO);
4288 pSMB->hdr.smb_buf_length += byte_count;
4289 pSMB->ByteCount = cpu_to_le16(byte_count);
4291 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4292 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4294 cFYI(1, ("Send error in QFSUnixInfo = %d", rc));
4295 } else { /* decode response */
4296 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4298 if (rc || (pSMBr->ByteCount < 13)) {
4299 rc = -EIO; /* bad smb */
4301 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4303 (FILE_SYSTEM_POSIX_INFO
4304 *) (((char *) &pSMBr->hdr.Protocol) +
4307 le32_to_cpu(response_data->BlockSize);
4309 le64_to_cpu(response_data->TotalBlocks);
4311 le64_to_cpu(response_data->BlocksAvail);
4312 if(response_data->UserBlocksAvail == cpu_to_le64(-1)) {
4313 FSData->f_bavail = FSData->f_bfree;
4316 le64_to_cpu(response_data->UserBlocksAvail);
4318 if(response_data->TotalFileNodes != cpu_to_le64(-1))
4320 le64_to_cpu(response_data->TotalFileNodes);
4321 if(response_data->FreeFileNodes != cpu_to_le64(-1))
4323 le64_to_cpu(response_data->FreeFileNodes);
4326 cifs_buf_release(pSMB);
4335 /* We can not use write of zero bytes trick to
4336 set file size due to need for large file support. Also note that
4337 this SetPathInfo is preferred to SetFileInfo based method in next
4338 routine which is only needed to work around a sharing violation bug
4339 in Samba which this routine can run into */
4342 CIFSSMBSetEOF(const int xid, struct cifsTconInfo *tcon, const char *fileName,
4343 __u64 size, int SetAllocation,
4344 const struct nls_table *nls_codepage, int remap)
4346 struct smb_com_transaction2_spi_req *pSMB = NULL;
4347 struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
4348 struct file_end_of_file_info *parm_data;
4351 int bytes_returned = 0;
4352 __u16 params, byte_count, data_count, param_offset, offset;
4354 cFYI(1, ("In SetEOF"));
4356 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4361 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4363 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
4364 PATH_MAX, nls_codepage, remap);
4365 name_len++; /* trailing null */
4367 } else { /* BB improve the check for buffer overruns BB */
4368 name_len = strnlen(fileName, PATH_MAX);
4369 name_len++; /* trailing null */
4370 strncpy(pSMB->FileName, fileName, name_len);
4372 params = 6 + name_len;
4373 data_count = sizeof (struct file_end_of_file_info);
4374 pSMB->MaxParameterCount = cpu_to_le16(2);
4375 pSMB->MaxDataCount = cpu_to_le16(4100);
4376 pSMB->MaxSetupCount = 0;
4380 pSMB->Reserved2 = 0;
4381 param_offset = offsetof(struct smb_com_transaction2_spi_req,
4382 InformationLevel) - 4;
4383 offset = param_offset + params;
4385 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
4386 pSMB->InformationLevel =
4387 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2);
4389 pSMB->InformationLevel =
4390 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO);
4391 } else /* Set File Size */ {
4392 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
4393 pSMB->InformationLevel =
4394 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO2);
4396 pSMB->InformationLevel =
4397 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO);
4401 (struct file_end_of_file_info *) (((char *) &pSMB->hdr.Protocol) +
4403 pSMB->ParameterOffset = cpu_to_le16(param_offset);
4404 pSMB->DataOffset = cpu_to_le16(offset);
4405 pSMB->SetupCount = 1;
4406 pSMB->Reserved3 = 0;
4407 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
4408 byte_count = 3 /* pad */ + params + data_count;
4409 pSMB->DataCount = cpu_to_le16(data_count);
4410 pSMB->TotalDataCount = pSMB->DataCount;
4411 pSMB->ParameterCount = cpu_to_le16(params);
4412 pSMB->TotalParameterCount = pSMB->ParameterCount;
4413 pSMB->Reserved4 = 0;
4414 pSMB->hdr.smb_buf_length += byte_count;
4415 parm_data->FileSize = cpu_to_le64(size);
4416 pSMB->ByteCount = cpu_to_le16(byte_count);
4417 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4418 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4420 cFYI(1, ("SetPathInfo (file size) returned %d", rc));
4423 cifs_buf_release(pSMB);
4432 CIFSSMBSetFileSize(const int xid, struct cifsTconInfo *tcon, __u64 size,
4433 __u16 fid, __u32 pid_of_opener, int SetAllocation)
4435 struct smb_com_transaction2_sfi_req *pSMB = NULL;
4436 struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
4438 struct file_end_of_file_info *parm_data;
4440 int bytes_returned = 0;
4441 __u16 params, param_offset, offset, byte_count, count;
4443 cFYI(1, ("SetFileSize (via SetFileInfo) %lld",
4445 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
4450 pSMBr = (struct smb_com_transaction2_sfi_rsp *)pSMB;
4452 pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
4453 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));
4456 pSMB->MaxSetupCount = 0;
4460 pSMB->Reserved2 = 0;
4461 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
4462 offset = param_offset + params;
4464 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
4466 count = sizeof(struct file_end_of_file_info);
4467 pSMB->MaxParameterCount = cpu_to_le16(2);
4468 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB PDU from sess */
4469 pSMB->SetupCount = 1;
4470 pSMB->Reserved3 = 0;
4471 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
4472 byte_count = 3 /* pad */ + params + count;
4473 pSMB->DataCount = cpu_to_le16(count);
4474 pSMB->ParameterCount = cpu_to_le16(params);
4475 pSMB->TotalDataCount = pSMB->DataCount;
4476 pSMB->TotalParameterCount = pSMB->ParameterCount;
4477 pSMB->ParameterOffset = cpu_to_le16(param_offset);
4479 (struct file_end_of_file_info *) (((char *) &pSMB->hdr.Protocol) +
4481 pSMB->DataOffset = cpu_to_le16(offset);
4482 parm_data->FileSize = cpu_to_le64(size);
4485 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
4486 pSMB->InformationLevel =
4487 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2);
4489 pSMB->InformationLevel =
4490 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO);
4491 } else /* Set File Size */ {
4492 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
4493 pSMB->InformationLevel =
4494 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO2);
4496 pSMB->InformationLevel =
4497 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO);
4499 pSMB->Reserved4 = 0;
4500 pSMB->hdr.smb_buf_length += byte_count;
4501 pSMB->ByteCount = cpu_to_le16(byte_count);
4502 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4503 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4506 ("Send error in SetFileInfo (SetFileSize) = %d",
4511 cifs_small_buf_release(pSMB);
4513 /* Note: On -EAGAIN error only caller can retry on handle based calls
4514 since file handle passed in no longer valid */
4519 /* Some legacy servers such as NT4 require that the file times be set on
4520 an open handle, rather than by pathname - this is awkward due to
4521 potential access conflicts on the open, but it is unavoidable for these
4522 old servers since the only other choice is to go from 100 nanosecond DCE
4523 time and resort to the original setpathinfo level which takes the ancient
4524 DOS time format with 2 second granularity */
4526 CIFSSMBSetFileTimes(const int xid, struct cifsTconInfo *tcon, const FILE_BASIC_INFO * data,
4529 struct smb_com_transaction2_sfi_req *pSMB = NULL;
4530 struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
4533 int bytes_returned = 0;
4534 __u16 params, param_offset, offset, byte_count, count;
4536 cFYI(1, ("Set Times (via SetFileInfo)"));
4537 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
4542 pSMBr = (struct smb_com_transaction2_sfi_rsp *)pSMB;
4544 /* At this point there is no need to override the current pid
4545 with the pid of the opener, but that could change if we someday
4546 use an existing handle (rather than opening one on the fly) */
4547 /* pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
4548 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));*/
4551 pSMB->MaxSetupCount = 0;
4555 pSMB->Reserved2 = 0;
4556 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
4557 offset = param_offset + params;
4559 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
4561 count = sizeof (FILE_BASIC_INFO);
4562 pSMB->MaxParameterCount = cpu_to_le16(2);
4563 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB PDU from sess */
4564 pSMB->SetupCount = 1;
4565 pSMB->Reserved3 = 0;
4566 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
4567 byte_count = 3 /* pad */ + params + count;
4568 pSMB->DataCount = cpu_to_le16(count);
4569 pSMB->ParameterCount = cpu_to_le16(params);
4570 pSMB->TotalDataCount = pSMB->DataCount;
4571 pSMB->TotalParameterCount = pSMB->ParameterCount;
4572 pSMB->ParameterOffset = cpu_to_le16(param_offset);
4573 pSMB->DataOffset = cpu_to_le16(offset);
4575 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
4576 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO2);
4578 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO);
4579 pSMB->Reserved4 = 0;
4580 pSMB->hdr.smb_buf_length += byte_count;
4581 pSMB->ByteCount = cpu_to_le16(byte_count);
4582 memcpy(data_offset,data,sizeof(FILE_BASIC_INFO));
4583 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4584 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4586 cFYI(1,("Send error in Set Time (SetFileInfo) = %d",rc));
4589 cifs_small_buf_release(pSMB);
4591 /* Note: On -EAGAIN error only caller can retry on handle based calls
4592 since file handle passed in no longer valid */
4599 CIFSSMBSetTimes(const int xid, struct cifsTconInfo *tcon, const char *fileName,
4600 const FILE_BASIC_INFO * data,
4601 const struct nls_table *nls_codepage, int remap)
4603 TRANSACTION2_SPI_REQ *pSMB = NULL;
4604 TRANSACTION2_SPI_RSP *pSMBr = NULL;
4607 int bytes_returned = 0;
4609 __u16 params, param_offset, offset, byte_count, count;
4611 cFYI(1, ("In SetTimes"));
4614 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4619 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4621 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
4622 PATH_MAX, nls_codepage, remap);
4623 name_len++; /* trailing null */
4625 } else { /* BB improve the check for buffer overruns BB */
4626 name_len = strnlen(fileName, PATH_MAX);
4627 name_len++; /* trailing null */
4628 strncpy(pSMB->FileName, fileName, name_len);
4631 params = 6 + name_len;
4632 count = sizeof (FILE_BASIC_INFO);
4633 pSMB->MaxParameterCount = cpu_to_le16(2);
4634 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
4635 pSMB->MaxSetupCount = 0;
4639 pSMB->Reserved2 = 0;
4640 param_offset = offsetof(struct smb_com_transaction2_spi_req,
4641 InformationLevel) - 4;
4642 offset = param_offset + params;
4643 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
4644 pSMB->ParameterOffset = cpu_to_le16(param_offset);
4645 pSMB->DataOffset = cpu_to_le16(offset);
4646 pSMB->SetupCount = 1;
4647 pSMB->Reserved3 = 0;
4648 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
4649 byte_count = 3 /* pad */ + params + count;
4651 pSMB->DataCount = cpu_to_le16(count);
4652 pSMB->ParameterCount = cpu_to_le16(params);
4653 pSMB->TotalDataCount = pSMB->DataCount;
4654 pSMB->TotalParameterCount = pSMB->ParameterCount;
4655 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
4656 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO2);
4658 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO);
4659 pSMB->Reserved4 = 0;
4660 pSMB->hdr.smb_buf_length += byte_count;
4661 memcpy(data_offset, data, sizeof (FILE_BASIC_INFO));
4662 pSMB->ByteCount = cpu_to_le16(byte_count);
4663 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4664 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4666 cFYI(1, ("SetPathInfo (times) returned %d", rc));
4669 cifs_buf_release(pSMB);
4677 /* Can not be used to set time stamps yet (due to old DOS time format) */
4678 /* Can be used to set attributes */
4679 #if 0 /* Possibly not needed - since it turns out that strangely NT4 has a bug
4680 handling it anyway and NT4 was what we thought it would be needed for
4681 Do not delete it until we prove whether needed for Win9x though */
4683 CIFSSMBSetAttrLegacy(int xid, struct cifsTconInfo *tcon, char *fileName,
4684 __u16 dos_attrs, const struct nls_table *nls_codepage)
4686 SETATTR_REQ *pSMB = NULL;
4687 SETATTR_RSP *pSMBr = NULL;
4692 cFYI(1, ("In SetAttrLegacy"));
4695 rc = smb_init(SMB_COM_SETATTR, 8, tcon, (void **) &pSMB,
4700 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4702 ConvertToUCS((__le16 *) pSMB->fileName, fileName,
4703 PATH_MAX, nls_codepage);
4704 name_len++; /* trailing null */
4706 } else { /* BB improve the check for buffer overruns BB */
4707 name_len = strnlen(fileName, PATH_MAX);
4708 name_len++; /* trailing null */
4709 strncpy(pSMB->fileName, fileName, name_len);
4711 pSMB->attr = cpu_to_le16(dos_attrs);
4712 pSMB->BufferFormat = 0x04;
4713 pSMB->hdr.smb_buf_length += name_len + 1;
4714 pSMB->ByteCount = cpu_to_le16(name_len + 1);
4715 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4716 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4718 cFYI(1, ("Error in LegacySetAttr = %d", rc));
4721 cifs_buf_release(pSMB);
4724 goto SetAttrLgcyRetry;
4728 #endif /* temporarily unneeded SetAttr legacy function */
4731 CIFSSMBUnixSetPerms(const int xid, struct cifsTconInfo *tcon,
4732 char *fileName, __u64 mode, __u64 uid, __u64 gid,
4733 dev_t device, const struct nls_table *nls_codepage,
4736 TRANSACTION2_SPI_REQ *pSMB = NULL;
4737 TRANSACTION2_SPI_RSP *pSMBr = NULL;
4740 int bytes_returned = 0;
4741 FILE_UNIX_BASIC_INFO *data_offset;
4742 __u16 params, param_offset, offset, count, byte_count;
4744 cFYI(1, ("In SetUID/GID/Mode"));
4746 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4751 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4753 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
4754 PATH_MAX, nls_codepage, remap);
4755 name_len++; /* trailing null */
4757 } else { /* BB improve the check for buffer overruns BB */
4758 name_len = strnlen(fileName, PATH_MAX);
4759 name_len++; /* trailing null */
4760 strncpy(pSMB->FileName, fileName, name_len);
4763 params = 6 + name_len;
4764 count = sizeof (FILE_UNIX_BASIC_INFO);
4765 pSMB->MaxParameterCount = cpu_to_le16(2);
4766 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
4767 pSMB->MaxSetupCount = 0;
4771 pSMB->Reserved2 = 0;
4772 param_offset = offsetof(struct smb_com_transaction2_spi_req,
4773 InformationLevel) - 4;
4774 offset = param_offset + params;
4776 (FILE_UNIX_BASIC_INFO *) ((char *) &pSMB->hdr.Protocol +
4778 memset(data_offset, 0, count);
4779 pSMB->DataOffset = cpu_to_le16(offset);
4780 pSMB->ParameterOffset = cpu_to_le16(param_offset);
4781 pSMB->SetupCount = 1;
4782 pSMB->Reserved3 = 0;
4783 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
4784 byte_count = 3 /* pad */ + params + count;
4785 pSMB->ParameterCount = cpu_to_le16(params);
4786 pSMB->DataCount = cpu_to_le16(count);
4787 pSMB->TotalParameterCount = pSMB->ParameterCount;
4788 pSMB->TotalDataCount = pSMB->DataCount;
4789 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_BASIC);
4790 pSMB->Reserved4 = 0;
4791 pSMB->hdr.smb_buf_length += byte_count;
4792 data_offset->Uid = cpu_to_le64(uid);
4793 data_offset->Gid = cpu_to_le64(gid);
4794 /* better to leave device as zero when it is */
4795 data_offset->DevMajor = cpu_to_le64(MAJOR(device));
4796 data_offset->DevMinor = cpu_to_le64(MINOR(device));
4797 data_offset->Permissions = cpu_to_le64(mode);
4800 data_offset->Type = cpu_to_le32(UNIX_FILE);
4801 else if(S_ISDIR(mode))
4802 data_offset->Type = cpu_to_le32(UNIX_DIR);
4803 else if(S_ISLNK(mode))
4804 data_offset->Type = cpu_to_le32(UNIX_SYMLINK);
4805 else if(S_ISCHR(mode))
4806 data_offset->Type = cpu_to_le32(UNIX_CHARDEV);
4807 else if(S_ISBLK(mode))
4808 data_offset->Type = cpu_to_le32(UNIX_BLOCKDEV);
4809 else if(S_ISFIFO(mode))
4810 data_offset->Type = cpu_to_le32(UNIX_FIFO);
4811 else if(S_ISSOCK(mode))
4812 data_offset->Type = cpu_to_le32(UNIX_SOCKET);
4815 pSMB->ByteCount = cpu_to_le16(byte_count);
4816 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4817 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4819 cFYI(1, ("SetPathInfo (perms) returned %d", rc));
4823 cifs_buf_release(pSMB);
4829 int CIFSSMBNotify(const int xid, struct cifsTconInfo *tcon,
4830 const int notify_subdirs, const __u16 netfid,
4831 __u32 filter, struct file * pfile, int multishot,
4832 const struct nls_table *nls_codepage)
4835 struct smb_com_transaction_change_notify_req * pSMB = NULL;
4836 struct smb_com_ntransaction_change_notify_rsp * pSMBr = NULL;
4837 struct dir_notify_req *dnotify_req;
4840 cFYI(1, ("In CIFSSMBNotify for file handle %d",(int)netfid));
4841 rc = smb_init(SMB_COM_NT_TRANSACT, 23, tcon, (void **) &pSMB,
4846 pSMB->TotalParameterCount = 0 ;
4847 pSMB->TotalDataCount = 0;
4848 pSMB->MaxParameterCount = cpu_to_le32(2);
4849 /* BB find exact data count max from sess structure BB */
4850 pSMB->MaxDataCount = 0; /* same in little endian or be */
4851 /* BB VERIFY verify which is correct for above BB */
4852 pSMB->MaxDataCount = cpu_to_le32((tcon->ses->server->maxBuf -
4853 MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
4855 pSMB->MaxSetupCount = 4;
4857 pSMB->ParameterOffset = 0;
4858 pSMB->DataCount = 0;
4859 pSMB->DataOffset = 0;
4860 pSMB->SetupCount = 4; /* single byte does not need le conversion */
4861 pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_NOTIFY_CHANGE);
4862 pSMB->ParameterCount = pSMB->TotalParameterCount;
4864 pSMB->WatchTree = 1; /* one byte - no le conversion needed */
4865 pSMB->Reserved2 = 0;
4866 pSMB->CompletionFilter = cpu_to_le32(filter);
4867 pSMB->Fid = netfid; /* file handle always le */
4868 pSMB->ByteCount = 0;
4870 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4871 (struct smb_hdr *) pSMBr, &bytes_returned, -1);
4873 cFYI(1, ("Error in Notify = %d", rc));
4875 /* Add file to outstanding requests */
4876 /* BB change to kmem cache alloc */
4877 dnotify_req = (struct dir_notify_req *) kmalloc(
4878 sizeof(struct dir_notify_req),
4881 dnotify_req->Pid = pSMB->hdr.Pid;
4882 dnotify_req->PidHigh = pSMB->hdr.PidHigh;
4883 dnotify_req->Mid = pSMB->hdr.Mid;
4884 dnotify_req->Tid = pSMB->hdr.Tid;
4885 dnotify_req->Uid = pSMB->hdr.Uid;
4886 dnotify_req->netfid = netfid;
4887 dnotify_req->pfile = pfile;
4888 dnotify_req->filter = filter;
4889 dnotify_req->multishot = multishot;
4890 spin_lock(&GlobalMid_Lock);
4891 list_add_tail(&dnotify_req->lhead,
4892 &GlobalDnotifyReqList);
4893 spin_unlock(&GlobalMid_Lock);
4897 cifs_buf_release(pSMB);
4900 #ifdef CONFIG_CIFS_XATTR
4902 CIFSSMBQAllEAs(const int xid, struct cifsTconInfo *tcon,
4903 const unsigned char *searchName,
4904 char * EAData, size_t buf_size,
4905 const struct nls_table *nls_codepage, int remap)
4907 /* BB assumes one setup word */
4908 TRANSACTION2_QPI_REQ *pSMB = NULL;
4909 TRANSACTION2_QPI_RSP *pSMBr = NULL;
4913 struct fea * temp_fea;
4915 __u16 params, byte_count;
4917 cFYI(1, ("In Query All EAs path %s", searchName));
4919 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4924 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4926 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
4927 PATH_MAX, nls_codepage, remap);
4928 name_len++; /* trailing null */
4930 } else { /* BB improve the check for buffer overruns BB */
4931 name_len = strnlen(searchName, PATH_MAX);
4932 name_len++; /* trailing null */
4933 strncpy(pSMB->FileName, searchName, name_len);
4936 params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */ ;
4937 pSMB->TotalDataCount = 0;
4938 pSMB->MaxParameterCount = cpu_to_le16(2);
4939 pSMB->MaxDataCount = cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
4940 pSMB->MaxSetupCount = 0;
4944 pSMB->Reserved2 = 0;
4945 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4946 struct smb_com_transaction2_qpi_req ,InformationLevel) - 4);
4947 pSMB->DataCount = 0;
4948 pSMB->DataOffset = 0;
4949 pSMB->SetupCount = 1;
4950 pSMB->Reserved3 = 0;
4951 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
4952 byte_count = params + 1 /* pad */ ;
4953 pSMB->TotalParameterCount = cpu_to_le16(params);
4954 pSMB->ParameterCount = pSMB->TotalParameterCount;
4955 pSMB->InformationLevel = cpu_to_le16(SMB_INFO_QUERY_ALL_EAS);
4956 pSMB->Reserved4 = 0;
4957 pSMB->hdr.smb_buf_length += byte_count;
4958 pSMB->ByteCount = cpu_to_le16(byte_count);
4960 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4961 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4963 cFYI(1, ("Send error in QueryAllEAs = %d", rc));
4964 } else { /* decode response */
4965 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4967 /* BB also check enough total bytes returned */
4968 /* BB we need to improve the validity checking
4969 of these trans2 responses */
4970 if (rc || (pSMBr->ByteCount < 4))
4971 rc = -EIO; /* bad smb */
4972 /* else if (pFindData){
4973 memcpy((char *) pFindData,
4974 (char *) &pSMBr->hdr.Protocol +
4977 /* check that length of list is not more than bcc */
4978 /* check that each entry does not go beyond length
4980 /* check that each element of each entry does not
4981 go beyond end of list */
4982 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4983 struct fealist * ea_response_data;
4985 /* validate_trans2_offsets() */
4986 /* BB to check if(start of smb + data_offset > &bcc+ bcc)*/
4987 ea_response_data = (struct fealist *)
4988 (((char *) &pSMBr->hdr.Protocol) +
4990 name_len = le32_to_cpu(ea_response_data->list_len);
4991 cFYI(1,("ea length %d", name_len));
4993 /* returned EA size zeroed at top of function */
4994 cFYI(1,("empty EA list returned from server"));
4996 /* account for ea list len */
4998 temp_fea = ea_response_data->list;
4999 temp_ptr = (char *)temp_fea;
5000 while(name_len > 0) {
5004 rc += temp_fea->name_len;
5005 /* account for prefix user. and trailing null */
5007 if(rc<(int)buf_size) {
5008 memcpy(EAData,"user.",5);
5010 memcpy(EAData,temp_ptr,temp_fea->name_len);
5011 EAData+=temp_fea->name_len;
5012 /* null terminate name */
5014 EAData = EAData + 1;
5015 } else if(buf_size == 0) {
5016 /* skip copy - calc size only */
5018 /* stop before overrun buffer */
5022 name_len -= temp_fea->name_len;
5023 temp_ptr += temp_fea->name_len;
5024 /* account for trailing null */
5027 value_len = le16_to_cpu(temp_fea->value_len);
5028 name_len -= value_len;
5029 temp_ptr += value_len;
5030 /* BB check that temp_ptr is still within smb BB*/
5031 /* no trailing null to account for in value len */
5032 /* go on to next EA */
5033 temp_fea = (struct fea *)temp_ptr;
5039 cifs_buf_release(pSMB);
5046 ssize_t CIFSSMBQueryEA(const int xid,struct cifsTconInfo * tcon,
5047 const unsigned char * searchName,const unsigned char * ea_name,
5048 unsigned char * ea_value, size_t buf_size,
5049 const struct nls_table *nls_codepage, int remap)
5051 TRANSACTION2_QPI_REQ *pSMB = NULL;
5052 TRANSACTION2_QPI_RSP *pSMBr = NULL;
5056 struct fea * temp_fea;
5058 __u16 params, byte_count;
5060 cFYI(1, ("In Query EA path %s", searchName));
5062 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5067 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5069 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
5070 PATH_MAX, nls_codepage, remap);
5071 name_len++; /* trailing null */
5073 } else { /* BB improve the check for buffer overruns BB */
5074 name_len = strnlen(searchName, PATH_MAX);
5075 name_len++; /* trailing null */
5076 strncpy(pSMB->FileName, searchName, name_len);
5079 params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */ ;
5080 pSMB->TotalDataCount = 0;
5081 pSMB->MaxParameterCount = cpu_to_le16(2);
5082 pSMB->MaxDataCount = cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
5083 pSMB->MaxSetupCount = 0;
5087 pSMB->Reserved2 = 0;
5088 pSMB->ParameterOffset = cpu_to_le16(offsetof(
5089 struct smb_com_transaction2_qpi_req ,InformationLevel) - 4);
5090 pSMB->DataCount = 0;
5091 pSMB->DataOffset = 0;
5092 pSMB->SetupCount = 1;
5093 pSMB->Reserved3 = 0;
5094 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
5095 byte_count = params + 1 /* pad */ ;
5096 pSMB->TotalParameterCount = cpu_to_le16(params);
5097 pSMB->ParameterCount = pSMB->TotalParameterCount;
5098 pSMB->InformationLevel = cpu_to_le16(SMB_INFO_QUERY_ALL_EAS);
5099 pSMB->Reserved4 = 0;
5100 pSMB->hdr.smb_buf_length += byte_count;
5101 pSMB->ByteCount = cpu_to_le16(byte_count);
5103 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5104 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5106 cFYI(1, ("Send error in Query EA = %d", rc));
5107 } else { /* decode response */
5108 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
5110 /* BB also check enough total bytes returned */
5111 /* BB we need to improve the validity checking
5112 of these trans2 responses */
5113 if (rc || (pSMBr->ByteCount < 4))
5114 rc = -EIO; /* bad smb */
5115 /* else if (pFindData){
5116 memcpy((char *) pFindData,
5117 (char *) &pSMBr->hdr.Protocol +
5120 /* check that length of list is not more than bcc */
5121 /* check that each entry does not go beyond length
5123 /* check that each element of each entry does not
5124 go beyond end of list */
5125 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
5126 struct fealist * ea_response_data;
5128 /* validate_trans2_offsets() */
5129 /* BB to check if(start of smb + data_offset > &bcc+ bcc)*/
5130 ea_response_data = (struct fealist *)
5131 (((char *) &pSMBr->hdr.Protocol) +
5133 name_len = le32_to_cpu(ea_response_data->list_len);
5134 cFYI(1,("ea length %d", name_len));
5136 /* returned EA size zeroed at top of function */
5137 cFYI(1,("empty EA list returned from server"));
5139 /* account for ea list len */
5141 temp_fea = ea_response_data->list;
5142 temp_ptr = (char *)temp_fea;
5143 /* loop through checking if we have a matching
5144 name and then return the associated value */
5145 while(name_len > 0) {
5149 value_len = le16_to_cpu(temp_fea->value_len);
5150 /* BB validate that value_len falls within SMB,
5151 even though maximum for name_len is 255 */
5152 if(memcmp(temp_fea->name,ea_name,
5153 temp_fea->name_len) == 0) {
5156 /* account for prefix user. and trailing null */
5157 if(rc<=(int)buf_size) {
5159 temp_fea->name+temp_fea->name_len+1,
5161 /* ea values, unlike ea names,
5162 are not null terminated */
5163 } else if(buf_size == 0) {
5164 /* skip copy - calc size only */
5166 /* stop before overrun buffer */
5171 name_len -= temp_fea->name_len;
5172 temp_ptr += temp_fea->name_len;
5173 /* account for trailing null */
5176 name_len -= value_len;
5177 temp_ptr += value_len;
5178 /* no trailing null to account for in value len */
5179 /* go on to next EA */
5180 temp_fea = (struct fea *)temp_ptr;
5186 cifs_buf_release(pSMB);
5194 CIFSSMBSetEA(const int xid, struct cifsTconInfo *tcon, const char *fileName,
5195 const char * ea_name, const void * ea_value,
5196 const __u16 ea_value_len, const struct nls_table *nls_codepage,
5199 struct smb_com_transaction2_spi_req *pSMB = NULL;
5200 struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
5201 struct fealist *parm_data;
5204 int bytes_returned = 0;
5205 __u16 params, param_offset, byte_count, offset, count;
5207 cFYI(1, ("In SetEA"));
5209 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5214 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5216 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
5217 PATH_MAX, nls_codepage, remap);
5218 name_len++; /* trailing null */
5220 } else { /* BB improve the check for buffer overruns BB */
5221 name_len = strnlen(fileName, PATH_MAX);
5222 name_len++; /* trailing null */
5223 strncpy(pSMB->FileName, fileName, name_len);
5226 params = 6 + name_len;
5228 /* done calculating parms using name_len of file name,
5229 now use name_len to calculate length of ea name
5230 we are going to create in the inode xattrs */
5234 name_len = strnlen(ea_name,255);
5236 count = sizeof(*parm_data) + ea_value_len + name_len + 1;
5237 pSMB->MaxParameterCount = cpu_to_le16(2);
5238 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB size from sess */
5239 pSMB->MaxSetupCount = 0;
5243 pSMB->Reserved2 = 0;
5244 param_offset = offsetof(struct smb_com_transaction2_spi_req,
5245 InformationLevel) - 4;
5246 offset = param_offset + params;
5247 pSMB->InformationLevel =
5248 cpu_to_le16(SMB_SET_FILE_EA);
5251 (struct fealist *) (((char *) &pSMB->hdr.Protocol) +
5253 pSMB->ParameterOffset = cpu_to_le16(param_offset);
5254 pSMB->DataOffset = cpu_to_le16(offset);
5255 pSMB->SetupCount = 1;
5256 pSMB->Reserved3 = 0;
5257 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
5258 byte_count = 3 /* pad */ + params + count;
5259 pSMB->DataCount = cpu_to_le16(count);
5260 parm_data->list_len = cpu_to_le32(count);
5261 parm_data->list[0].EA_flags = 0;
5262 /* we checked above that name len is less than 255 */
5263 parm_data->list[0].name_len = (__u8)name_len;
5264 /* EA names are always ASCII */
5266 strncpy(parm_data->list[0].name,ea_name,name_len);
5267 parm_data->list[0].name[name_len] = 0;
5268 parm_data->list[0].value_len = cpu_to_le16(ea_value_len);
5269 /* caller ensures that ea_value_len is less than 64K but
5270 we need to ensure that it fits within the smb */
5272 /*BB add length check that it would fit in negotiated SMB buffer size BB */
5273 /* if(ea_value_len > buffer_size - 512 (enough for header)) */
5275 memcpy(parm_data->list[0].name+name_len+1,ea_value,ea_value_len);
5277 pSMB->TotalDataCount = pSMB->DataCount;
5278 pSMB->ParameterCount = cpu_to_le16(params);
5279 pSMB->TotalParameterCount = pSMB->ParameterCount;
5280 pSMB->Reserved4 = 0;
5281 pSMB->hdr.smb_buf_length += byte_count;
5282 pSMB->ByteCount = cpu_to_le16(byte_count);
5283 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5284 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5286 cFYI(1, ("SetPathInfo (EA) returned %d", rc));
5289 cifs_buf_release(pSMB);