4 * Copyright (C) International Business Machines Corp., 2002,2006
5 * Author(s): Steve French (sfrench@us.ibm.com)
7 * Contains the routines for constructing the SMB PDUs themselves
9 * This library is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU Lesser General Public License as published
11 * by the Free Software Foundation; either version 2.1 of the License, or
12 * (at your option) any later version.
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
17 * the GNU Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public License
20 * along with this library; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 /* SMB/CIFS PDU handling routines here - except for leftovers in connect.c */
25 /* These are mostly routines that operate on a pathname, or on a tree id */
26 /* (mounted volume), but there are eight handle based routines which must be */
27 /* treated slightly different for reconnection purposes since we never want */
28 /* to reuse a stale file handle and the caller knows the file handle */
31 #include <linux/kernel.h>
32 #include <linux/vfs.h>
33 #include <linux/posix_acl_xattr.h>
34 #include <asm/uaccess.h>
37 #include "cifsproto.h"
38 #include "cifs_unicode.h"
39 #include "cifs_debug.h"
42 #ifdef CONFIG_CIFS_POSIX
47 #ifdef CONFIG_CIFS_WEAK_PW_HASH
48 {LANMAN_PROT, "\2LM1.2X002"},
49 {LANMAN2_PROT, "\2LANMAN2.1"},
50 #endif /* weak password hashing for legacy clients */
51 {CIFS_PROT, "\2NT LM 0.12"},
52 {POSIX_PROT, "\2POSIX 2"},
60 #ifdef CONFIG_CIFS_WEAK_PW_HASH
61 {LANMAN_PROT, "\2LM1.2X002"},
62 {LANMAN2_PROT, "\2LANMAN2.1"},
63 #endif /* weak password hashing for legacy clients */
64 {CIFS_PROT, "\2NT LM 0.12"},
69 /* define the number of elements in the cifs dialect array */
70 #ifdef CONFIG_CIFS_POSIX
71 #ifdef CONFIG_CIFS_WEAK_PW_HASH
72 #define CIFS_NUM_PROT 4
74 #define CIFS_NUM_PROT 2
75 #endif /* CIFS_WEAK_PW_HASH */
77 #ifdef CONFIG_CIFS_WEAK_PW_HASH
78 #define CIFS_NUM_PROT 3
80 #define CIFS_NUM_PROT 1
81 #endif /* CONFIG_CIFS_WEAK_PW_HASH */
82 #endif /* CIFS_POSIX */
85 /* Mark as invalid, all open files on tree connections since they
86 were closed when session to server was lost */
87 static void mark_open_files_invalid(struct cifsTconInfo * pTcon)
89 struct cifsFileInfo *open_file = NULL;
90 struct list_head * tmp;
91 struct list_head * tmp1;
93 /* list all files open on tree connection and mark them invalid */
94 write_lock(&GlobalSMBSeslock);
95 list_for_each_safe(tmp, tmp1, &pTcon->openFileList) {
96 open_file = list_entry(tmp,struct cifsFileInfo, tlist);
98 open_file->invalidHandle = TRUE;
101 write_unlock(&GlobalSMBSeslock);
102 /* BB Add call to invalidate_inodes(sb) for all superblocks mounted
106 /* If the return code is zero, this function must fill in request_buf pointer */
108 small_smb_init(int smb_command, int wct, struct cifsTconInfo *tcon,
109 void **request_buf /* returned */)
113 /* SMBs NegProt, SessSetup, uLogoff do not have tcon yet so
114 check for tcp and smb session status done differently
115 for those three - in the calling routine */
117 if(tcon->tidStatus == CifsExiting) {
118 /* only tree disconnect, open, and write,
119 (and ulogoff which does not have tcon)
120 are allowed as we start force umount */
121 if((smb_command != SMB_COM_WRITE_ANDX) &&
122 (smb_command != SMB_COM_OPEN_ANDX) &&
123 (smb_command != SMB_COM_TREE_DISCONNECT)) {
124 cFYI(1,("can not send cmd %d while umounting",
129 if((tcon->ses) && (tcon->ses->status != CifsExiting) &&
130 (tcon->ses->server)){
131 struct nls_table *nls_codepage;
132 /* Give Demultiplex thread up to 10 seconds to
133 reconnect, should be greater than cifs socket
134 timeout which is 7 seconds */
135 while(tcon->ses->server->tcpStatus == CifsNeedReconnect) {
136 wait_event_interruptible_timeout(tcon->ses->server->response_q,
137 (tcon->ses->server->tcpStatus == CifsGood), 10 * HZ);
138 if(tcon->ses->server->tcpStatus == CifsNeedReconnect) {
139 /* on "soft" mounts we wait once */
140 if((tcon->retry == FALSE) ||
141 (tcon->ses->status == CifsExiting)) {
142 cFYI(1,("gave up waiting on reconnect in smb_init"));
144 } /* else "hard" mount - keep retrying
145 until process is killed or server
146 comes back on-line */
147 } else /* TCP session is reestablished now */
152 nls_codepage = load_nls_default();
153 /* need to prevent multiple threads trying to
154 simultaneously reconnect the same SMB session */
155 down(&tcon->ses->sesSem);
156 if(tcon->ses->status == CifsNeedReconnect)
157 rc = cifs_setup_session(0, tcon->ses,
159 if(!rc && (tcon->tidStatus == CifsNeedReconnect)) {
160 mark_open_files_invalid(tcon);
161 rc = CIFSTCon(0, tcon->ses, tcon->treeName,
163 up(&tcon->ses->sesSem);
164 /* tell server which Unix caps we support */
165 if (tcon->ses->capabilities & CAP_UNIX)
166 reset_cifs_unix_caps(0 /* no xid */,
168 NULL /* we do not know sb */,
169 NULL /* no vol info */);
170 /* BB FIXME add code to check if wsize needs
171 update due to negotiated smb buffer size
174 atomic_inc(&tconInfoReconnectCount);
176 cFYI(1, ("reconnect tcon rc = %d", rc));
177 /* Removed call to reopen open files here -
178 it is safer (and faster) to reopen files
179 one at a time as needed in read and write */
181 /* Check if handle based operation so we
182 know whether we can continue or not without
183 returning to caller to reset file handle */
184 switch(smb_command) {
185 case SMB_COM_READ_ANDX:
186 case SMB_COM_WRITE_ANDX:
188 case SMB_COM_FIND_CLOSE2:
189 case SMB_COM_LOCKING_ANDX: {
190 unload_nls(nls_codepage);
195 up(&tcon->ses->sesSem);
197 unload_nls(nls_codepage);
206 *request_buf = cifs_small_buf_get();
207 if (*request_buf == NULL) {
208 /* BB should we add a retry in here if not a writepage? */
212 header_assemble((struct smb_hdr *) *request_buf, smb_command, tcon,wct);
215 cifs_stats_inc(&tcon->num_smbs_sent);
221 small_smb_init_no_tc(const int smb_command, const int wct,
222 struct cifsSesInfo *ses, void **request_buf)
225 struct smb_hdr * buffer;
227 rc = small_smb_init(smb_command, wct, NULL, request_buf);
231 buffer = (struct smb_hdr *)*request_buf;
232 buffer->Mid = GetNextMid(ses->server);
233 if (ses->capabilities & CAP_UNICODE)
234 buffer->Flags2 |= SMBFLG2_UNICODE;
235 if (ses->capabilities & CAP_STATUS32)
236 buffer->Flags2 |= SMBFLG2_ERR_STATUS;
238 /* uid, tid can stay at zero as set in header assemble */
240 /* BB add support for turning on the signing when
241 this function is used after 1st of session setup requests */
246 /* If the return code is zero, this function must fill in request_buf pointer */
248 smb_init(int smb_command, int wct, struct cifsTconInfo *tcon,
249 void **request_buf /* returned */ ,
250 void **response_buf /* returned */ )
254 /* SMBs NegProt, SessSetup, uLogoff do not have tcon yet so
255 check for tcp and smb session status done differently
256 for those three - in the calling routine */
258 if(tcon->tidStatus == CifsExiting) {
259 /* only tree disconnect, open, and write,
260 (and ulogoff which does not have tcon)
261 are allowed as we start force umount */
262 if((smb_command != SMB_COM_WRITE_ANDX) &&
263 (smb_command != SMB_COM_OPEN_ANDX) &&
264 (smb_command != SMB_COM_TREE_DISCONNECT)) {
265 cFYI(1,("can not send cmd %d while umounting",
271 if((tcon->ses) && (tcon->ses->status != CifsExiting) &&
272 (tcon->ses->server)){
273 struct nls_table *nls_codepage;
274 /* Give Demultiplex thread up to 10 seconds to
275 reconnect, should be greater than cifs socket
276 timeout which is 7 seconds */
277 while(tcon->ses->server->tcpStatus == CifsNeedReconnect) {
278 wait_event_interruptible_timeout(tcon->ses->server->response_q,
279 (tcon->ses->server->tcpStatus == CifsGood), 10 * HZ);
280 if(tcon->ses->server->tcpStatus ==
282 /* on "soft" mounts we wait once */
283 if((tcon->retry == FALSE) ||
284 (tcon->ses->status == CifsExiting)) {
285 cFYI(1,("gave up waiting on reconnect in smb_init"));
287 } /* else "hard" mount - keep retrying
288 until process is killed or server
290 } else /* TCP session is reestablished now */
295 nls_codepage = load_nls_default();
296 /* need to prevent multiple threads trying to
297 simultaneously reconnect the same SMB session */
298 down(&tcon->ses->sesSem);
299 if(tcon->ses->status == CifsNeedReconnect)
300 rc = cifs_setup_session(0, tcon->ses,
302 if(!rc && (tcon->tidStatus == CifsNeedReconnect)) {
303 mark_open_files_invalid(tcon);
304 rc = CIFSTCon(0, tcon->ses, tcon->treeName,
306 up(&tcon->ses->sesSem);
307 /* tell server which Unix caps we support */
308 if (tcon->ses->capabilities & CAP_UNIX)
309 reset_cifs_unix_caps(0 /* no xid */,
311 NULL /* do not know sb */,
312 NULL /* no vol info */);
313 /* BB FIXME add code to check if wsize needs
314 update due to negotiated smb buffer size
317 atomic_inc(&tconInfoReconnectCount);
319 cFYI(1, ("reconnect tcon rc = %d", rc));
320 /* Removed call to reopen open files here -
321 it is safer (and faster) to reopen files
322 one at a time as needed in read and write */
324 /* Check if handle based operation so we
325 know whether we can continue or not without
326 returning to caller to reset file handle */
327 switch(smb_command) {
328 case SMB_COM_READ_ANDX:
329 case SMB_COM_WRITE_ANDX:
331 case SMB_COM_FIND_CLOSE2:
332 case SMB_COM_LOCKING_ANDX: {
333 unload_nls(nls_codepage);
338 up(&tcon->ses->sesSem);
340 unload_nls(nls_codepage);
349 *request_buf = cifs_buf_get();
350 if (*request_buf == NULL) {
351 /* BB should we add a retry in here if not a writepage? */
354 /* Although the original thought was we needed the response buf for */
355 /* potential retries of smb operations it turns out we can determine */
356 /* from the mid flags when the request buffer can be resent without */
357 /* having to use a second distinct buffer for the response */
359 *response_buf = *request_buf;
361 header_assemble((struct smb_hdr *) *request_buf, smb_command, tcon,
365 cifs_stats_inc(&tcon->num_smbs_sent);
370 static int validate_t2(struct smb_t2_rsp * pSMB)
376 /* check for plausible wct, bcc and t2 data and parm sizes */
377 /* check for parm and data offset going beyond end of smb */
378 if(pSMB->hdr.WordCount >= 10) {
379 if((le16_to_cpu(pSMB->t2_rsp.ParameterOffset) <= 1024) &&
380 (le16_to_cpu(pSMB->t2_rsp.DataOffset) <= 1024)) {
381 /* check that bcc is at least as big as parms + data */
382 /* check that bcc is less than negotiated smb buffer */
383 total_size = le16_to_cpu(pSMB->t2_rsp.ParameterCount);
384 if(total_size < 512) {
385 total_size+=le16_to_cpu(pSMB->t2_rsp.DataCount);
386 /* BCC le converted in SendReceive */
387 pBCC = (pSMB->hdr.WordCount * 2) +
388 sizeof(struct smb_hdr) +
390 if((total_size <= (*(u16 *)pBCC)) &&
392 CIFSMaxBufSize+MAX_CIFS_HDR_SIZE)) {
399 cifs_dump_mem("Invalid transact2 SMB: ",(char *)pSMB,
400 sizeof(struct smb_t2_rsp) + 16);
404 CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses)
407 NEGOTIATE_RSP *pSMBr;
411 struct TCP_Server_Info * server;
413 unsigned int secFlags;
417 server = ses->server;
422 rc = smb_init(SMB_COM_NEGOTIATE, 0, NULL /* no tcon yet */ ,
423 (void **) &pSMB, (void **) &pSMBr);
427 /* if any of auth flags (ie not sign or seal) are overriden use them */
428 if(ses->overrideSecFlg & (~(CIFSSEC_MUST_SIGN | CIFSSEC_MUST_SEAL)))
429 secFlags = ses->overrideSecFlg;
430 else /* if override flags set only sign/seal OR them with global auth */
431 secFlags = extended_security | ses->overrideSecFlg;
433 cFYI(1,("secFlags 0x%x",secFlags));
435 pSMB->hdr.Mid = GetNextMid(server);
436 pSMB->hdr.Flags2 |= SMBFLG2_UNICODE;
437 if((secFlags & CIFSSEC_MUST_KRB5) == CIFSSEC_MUST_KRB5)
438 pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC;
441 for(i=0;i<CIFS_NUM_PROT;i++) {
442 strncpy(pSMB->DialectsArray+count, protocols[i].name, 16);
443 count += strlen(protocols[i].name) + 1;
444 /* null at end of source and target buffers anyway */
446 pSMB->hdr.smb_buf_length += count;
447 pSMB->ByteCount = cpu_to_le16(count);
449 rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB,
450 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
454 dialect = le16_to_cpu(pSMBr->DialectIndex);
455 cFYI(1,("Dialect: %d", dialect));
456 /* Check wct = 1 error case */
457 if((pSMBr->hdr.WordCount < 13) || (dialect == BAD_PROT)) {
458 /* core returns wct = 1, but we do not ask for core - otherwise
459 small wct just comes when dialect index is -1 indicating we
460 could not negotiate a common dialect */
463 #ifdef CONFIG_CIFS_WEAK_PW_HASH
464 } else if((pSMBr->hdr.WordCount == 13)
465 && ((dialect == LANMAN_PROT)
466 || (dialect == LANMAN2_PROT))) {
468 struct lanman_neg_rsp * rsp = (struct lanman_neg_rsp *)pSMBr;
470 if((secFlags & CIFSSEC_MAY_LANMAN) ||
471 (secFlags & CIFSSEC_MAY_PLNTXT))
472 server->secType = LANMAN;
474 cERROR(1, ("mount failed weak security disabled"
475 " in /proc/fs/cifs/SecurityFlags"));
479 server->secMode = (__u8)le16_to_cpu(rsp->SecurityMode);
480 server->maxReq = le16_to_cpu(rsp->MaxMpxCount);
481 server->maxBuf = min((__u32)le16_to_cpu(rsp->MaxBufSize),
482 (__u32)CIFSMaxBufSize + MAX_CIFS_HDR_SIZE);
483 GETU32(server->sessid) = le32_to_cpu(rsp->SessionKey);
484 /* even though we do not use raw we might as well set this
485 accurately, in case we ever find a need for it */
486 if((le16_to_cpu(rsp->RawMode) & RAW_ENABLE) == RAW_ENABLE) {
487 server->maxRw = 0xFF00;
488 server->capabilities = CAP_MPX_MODE | CAP_RAW_MODE;
490 server->maxRw = 0;/* we do not need to use raw anyway */
491 server->capabilities = CAP_MPX_MODE;
493 tmp = (__s16)le16_to_cpu(rsp->ServerTimeZone);
495 /* OS/2 often does not set timezone therefore
496 * we must use server time to calc time zone.
497 * Could deviate slightly from the right zone.
498 * Smallest defined timezone difference is 15 minutes
499 * (i.e. Nepal). Rounding up/down is done to match
502 int val, seconds, remain, result;
503 struct timespec ts, utc;
505 ts = cnvrtDosUnixTm(le16_to_cpu(rsp->SrvTime.Date),
506 le16_to_cpu(rsp->SrvTime.Time));
507 cFYI(1,("SrvTime: %d sec since 1970 (utc: %d) diff: %d",
508 (int)ts.tv_sec, (int)utc.tv_sec,
509 (int)(utc.tv_sec - ts.tv_sec)));
510 val = (int)(utc.tv_sec - ts.tv_sec);
511 seconds = val < 0 ? -val : val;
512 result = (seconds / MIN_TZ_ADJ) * MIN_TZ_ADJ;
513 remain = seconds % MIN_TZ_ADJ;
514 if(remain >= (MIN_TZ_ADJ / 2))
515 result += MIN_TZ_ADJ;
518 server->timeAdj = result;
520 server->timeAdj = (int)tmp;
521 server->timeAdj *= 60; /* also in seconds */
523 cFYI(1,("server->timeAdj: %d seconds", server->timeAdj));
526 /* BB get server time for time conversions and add
527 code to use it and timezone since this is not UTC */
529 if (rsp->EncryptionKeyLength ==
530 cpu_to_le16(CIFS_CRYPTO_KEY_SIZE)) {
531 memcpy(server->cryptKey, rsp->EncryptionKey,
532 CIFS_CRYPTO_KEY_SIZE);
533 } else if (server->secMode & SECMODE_PW_ENCRYPT) {
534 rc = -EIO; /* need cryptkey unless plain text */
538 cFYI(1,("LANMAN negotiated"));
539 /* we will not end up setting signing flags - as no signing
540 was in LANMAN and server did not return the flags on */
542 #else /* weak security disabled */
543 } else if(pSMBr->hdr.WordCount == 13) {
544 cERROR(1,("mount failed, cifs module not built "
545 "with CIFS_WEAK_PW_HASH support"));
547 #endif /* WEAK_PW_HASH */
549 } else if(pSMBr->hdr.WordCount != 17) {
554 /* else wct == 17 NTLM */
555 server->secMode = pSMBr->SecurityMode;
556 if((server->secMode & SECMODE_USER) == 0)
557 cFYI(1,("share mode security"));
559 if((server->secMode & SECMODE_PW_ENCRYPT) == 0)
560 #ifdef CONFIG_CIFS_WEAK_PW_HASH
561 if ((secFlags & CIFSSEC_MAY_PLNTXT) == 0)
562 #endif /* CIFS_WEAK_PW_HASH */
563 cERROR(1,("Server requests plain text password"
564 " but client support disabled"));
566 if((secFlags & CIFSSEC_MUST_NTLMV2) == CIFSSEC_MUST_NTLMV2)
567 server->secType = NTLMv2;
568 else if(secFlags & CIFSSEC_MAY_NTLM)
569 server->secType = NTLM;
570 else if(secFlags & CIFSSEC_MAY_NTLMV2)
571 server->secType = NTLMv2;
572 /* else krb5 ... any others ... */
574 /* one byte, so no need to convert this or EncryptionKeyLen from
576 server->maxReq = le16_to_cpu(pSMBr->MaxMpxCount);
577 /* probably no need to store and check maxvcs */
578 server->maxBuf = min(le32_to_cpu(pSMBr->MaxBufferSize),
579 (__u32) CIFSMaxBufSize + MAX_CIFS_HDR_SIZE);
580 server->maxRw = le32_to_cpu(pSMBr->MaxRawSize);
581 cFYI(0, ("Max buf = %d", ses->server->maxBuf));
582 GETU32(ses->server->sessid) = le32_to_cpu(pSMBr->SessionKey);
583 server->capabilities = le32_to_cpu(pSMBr->Capabilities);
584 server->timeAdj = (int)(__s16)le16_to_cpu(pSMBr->ServerTimeZone);
585 server->timeAdj *= 60;
586 if (pSMBr->EncryptionKeyLength == CIFS_CRYPTO_KEY_SIZE) {
587 memcpy(server->cryptKey, pSMBr->u.EncryptionKey,
588 CIFS_CRYPTO_KEY_SIZE);
589 } else if ((pSMBr->hdr.Flags2 & SMBFLG2_EXT_SEC)
590 && (pSMBr->EncryptionKeyLength == 0)) {
591 /* decode security blob */
592 } else if (server->secMode & SECMODE_PW_ENCRYPT) {
593 rc = -EIO; /* no crypt key only if plain text pwd */
597 /* BB might be helpful to save off the domain of server here */
599 if ((pSMBr->hdr.Flags2 & SMBFLG2_EXT_SEC) &&
600 (server->capabilities & CAP_EXTENDED_SECURITY)) {
601 count = pSMBr->ByteCount;
604 else if (count == 16) {
605 server->secType = RawNTLMSSP;
606 if (server->socketUseCount.counter > 1) {
607 if (memcmp(server->server_GUID,
608 pSMBr->u.extended_response.
610 cFYI(1, ("server UID changed"));
611 memcpy(server->server_GUID,
612 pSMBr->u.extended_response.GUID,
616 memcpy(server->server_GUID,
617 pSMBr->u.extended_response.GUID, 16);
619 rc = decode_negTokenInit(pSMBr->u.extended_response.
624 /* BB Need to fill struct for sessetup here */
631 server->capabilities &= ~CAP_EXTENDED_SECURITY;
633 #ifdef CONFIG_CIFS_WEAK_PW_HASH
636 if(sign_CIFS_PDUs == FALSE) {
637 if(server->secMode & SECMODE_SIGN_REQUIRED)
638 cERROR(1,("Server requires "
639 "/proc/fs/cifs/PacketSigningEnabled to be on"));
641 ~(SECMODE_SIGN_ENABLED | SECMODE_SIGN_REQUIRED);
642 } else if(sign_CIFS_PDUs == 1) {
643 if((server->secMode & SECMODE_SIGN_REQUIRED) == 0)
645 ~(SECMODE_SIGN_ENABLED | SECMODE_SIGN_REQUIRED);
646 } else if(sign_CIFS_PDUs == 2) {
647 if((server->secMode &
648 (SECMODE_SIGN_ENABLED | SECMODE_SIGN_REQUIRED)) == 0) {
649 cERROR(1,("signing required but server lacks support"));
653 cifs_buf_release(pSMB);
655 cFYI(1,("negprot rc %d",rc));
660 CIFSSMBTDis(const int xid, struct cifsTconInfo *tcon)
662 struct smb_hdr *smb_buffer;
663 struct smb_hdr *smb_buffer_response; /* BB removeme BB */
667 cFYI(1, ("In tree disconnect"));
669 * If last user of the connection and
670 * connection alive - disconnect it
671 * If this is the last connection on the server session disconnect it
672 * (and inside session disconnect we should check if tcp socket needs
673 * to be freed and kernel thread woken up).
676 down(&tcon->tconSem);
680 atomic_dec(&tcon->useCount);
681 if (atomic_read(&tcon->useCount) > 0) {
686 /* No need to return error on this operation if tid invalidated and
687 closed on server already e.g. due to tcp session crashing */
688 if(tcon->tidStatus == CifsNeedReconnect) {
693 if((tcon->ses == NULL) || (tcon->ses->server == NULL)) {
697 rc = small_smb_init(SMB_COM_TREE_DISCONNECT, 0, tcon,
698 (void **)&smb_buffer);
703 smb_buffer_response = smb_buffer; /* BB removeme BB */
705 rc = SendReceive(xid, tcon->ses, smb_buffer, smb_buffer_response,
708 cFYI(1, ("Tree disconnect failed %d", rc));
711 cifs_small_buf_release(smb_buffer);
714 /* No need to return error on this operation if tid invalidated and
715 closed on server already e.g. due to tcp session crashing */
723 CIFSSMBLogoff(const int xid, struct cifsSesInfo *ses)
725 struct smb_hdr *smb_buffer_response;
726 LOGOFF_ANDX_REQ *pSMB;
730 cFYI(1, ("In SMBLogoff for session disconnect"));
736 atomic_dec(&ses->inUse);
737 if (atomic_read(&ses->inUse) > 0) {
741 rc = small_smb_init(SMB_COM_LOGOFF_ANDX, 2, NULL, (void **)&pSMB);
747 smb_buffer_response = (struct smb_hdr *)pSMB; /* BB removeme BB */
750 pSMB->hdr.Mid = GetNextMid(ses->server);
752 if(ses->server->secMode &
753 (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
754 pSMB->hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
757 pSMB->hdr.Uid = ses->Suid;
759 pSMB->AndXCommand = 0xFF;
760 rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB,
761 smb_buffer_response, &length, 0);
763 atomic_dec(&ses->server->socketUseCount);
764 if (atomic_read(&ses->server->socketUseCount) == 0) {
765 spin_lock(&GlobalMid_Lock);
766 ses->server->tcpStatus = CifsExiting;
767 spin_unlock(&GlobalMid_Lock);
772 cifs_small_buf_release(pSMB);
774 /* if session dead then we do not need to do ulogoff,
775 since server closed smb session, no sense reporting
783 CIFSSMBDelFile(const int xid, struct cifsTconInfo *tcon, const char *fileName,
784 const struct nls_table *nls_codepage, int remap)
786 DELETE_FILE_REQ *pSMB = NULL;
787 DELETE_FILE_RSP *pSMBr = NULL;
793 rc = smb_init(SMB_COM_DELETE, 1, tcon, (void **) &pSMB,
798 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
800 cifsConvertToUCS((__le16 *) pSMB->fileName, fileName,
801 PATH_MAX, nls_codepage, remap);
802 name_len++; /* trailing null */
804 } else { /* BB improve check for buffer overruns BB */
805 name_len = strnlen(fileName, PATH_MAX);
806 name_len++; /* trailing null */
807 strncpy(pSMB->fileName, fileName, name_len);
809 pSMB->SearchAttributes =
810 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM);
811 pSMB->BufferFormat = 0x04;
812 pSMB->hdr.smb_buf_length += name_len + 1;
813 pSMB->ByteCount = cpu_to_le16(name_len + 1);
814 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
815 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
816 cifs_stats_inc(&tcon->num_deletes);
818 cFYI(1, ("Error in RMFile = %d", rc));
821 cifs_buf_release(pSMB);
829 CIFSSMBRmDir(const int xid, struct cifsTconInfo *tcon, const char *dirName,
830 const struct nls_table *nls_codepage, int remap)
832 DELETE_DIRECTORY_REQ *pSMB = NULL;
833 DELETE_DIRECTORY_RSP *pSMBr = NULL;
838 cFYI(1, ("In CIFSSMBRmDir"));
840 rc = smb_init(SMB_COM_DELETE_DIRECTORY, 0, tcon, (void **) &pSMB,
845 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
846 name_len = cifsConvertToUCS((__le16 *) pSMB->DirName, dirName,
847 PATH_MAX, nls_codepage, remap);
848 name_len++; /* trailing null */
850 } else { /* BB improve check for buffer overruns BB */
851 name_len = strnlen(dirName, PATH_MAX);
852 name_len++; /* trailing null */
853 strncpy(pSMB->DirName, dirName, name_len);
856 pSMB->BufferFormat = 0x04;
857 pSMB->hdr.smb_buf_length += name_len + 1;
858 pSMB->ByteCount = cpu_to_le16(name_len + 1);
859 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
860 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
861 cifs_stats_inc(&tcon->num_rmdirs);
863 cFYI(1, ("Error in RMDir = %d", rc));
866 cifs_buf_release(pSMB);
873 CIFSSMBMkDir(const int xid, struct cifsTconInfo *tcon,
874 const char *name, const struct nls_table *nls_codepage, int remap)
877 CREATE_DIRECTORY_REQ *pSMB = NULL;
878 CREATE_DIRECTORY_RSP *pSMBr = NULL;
882 cFYI(1, ("In CIFSSMBMkDir"));
884 rc = smb_init(SMB_COM_CREATE_DIRECTORY, 0, tcon, (void **) &pSMB,
889 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
890 name_len = cifsConvertToUCS((__le16 *) pSMB->DirName, name,
891 PATH_MAX, nls_codepage, remap);
892 name_len++; /* trailing null */
894 } else { /* BB improve check for buffer overruns BB */
895 name_len = strnlen(name, PATH_MAX);
896 name_len++; /* trailing null */
897 strncpy(pSMB->DirName, name, name_len);
900 pSMB->BufferFormat = 0x04;
901 pSMB->hdr.smb_buf_length += name_len + 1;
902 pSMB->ByteCount = cpu_to_le16(name_len + 1);
903 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
904 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
905 cifs_stats_inc(&tcon->num_mkdirs);
907 cFYI(1, ("Error in Mkdir = %d", rc));
910 cifs_buf_release(pSMB);
916 static __u16 convert_disposition(int disposition)
920 switch (disposition) {
922 ofun = SMBOPEN_OCREATE | SMBOPEN_OTRUNC;
925 ofun = SMBOPEN_OAPPEND;
928 ofun = SMBOPEN_OCREATE;
931 ofun = SMBOPEN_OCREATE | SMBOPEN_OAPPEND;
934 ofun = SMBOPEN_OTRUNC;
936 case FILE_OVERWRITE_IF:
937 ofun = SMBOPEN_OCREATE | SMBOPEN_OTRUNC;
940 cFYI(1,("unknown disposition %d",disposition));
941 ofun = SMBOPEN_OAPPEND; /* regular open */
947 SMBLegacyOpen(const int xid, struct cifsTconInfo *tcon,
948 const char *fileName, const int openDisposition,
949 const int access_flags, const int create_options, __u16 * netfid,
950 int *pOplock, FILE_ALL_INFO * pfile_info,
951 const struct nls_table *nls_codepage, int remap)
954 OPENX_REQ *pSMB = NULL;
955 OPENX_RSP *pSMBr = NULL;
961 rc = smb_init(SMB_COM_OPEN_ANDX, 15, tcon, (void **) &pSMB,
966 pSMB->AndXCommand = 0xFF; /* none */
968 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
969 count = 1; /* account for one byte pad to word boundary */
971 cifsConvertToUCS((__le16 *) (pSMB->fileName + 1),
972 fileName, PATH_MAX, nls_codepage, remap);
973 name_len++; /* trailing null */
975 } else { /* BB improve check for buffer overruns BB */
976 count = 0; /* no pad */
977 name_len = strnlen(fileName, PATH_MAX);
978 name_len++; /* trailing null */
979 strncpy(pSMB->fileName, fileName, name_len);
981 if (*pOplock & REQ_OPLOCK)
982 pSMB->OpenFlags = cpu_to_le16(REQ_OPLOCK);
983 else if (*pOplock & REQ_BATCHOPLOCK) {
984 pSMB->OpenFlags = cpu_to_le16(REQ_BATCHOPLOCK);
986 pSMB->OpenFlags |= cpu_to_le16(REQ_MORE_INFO);
987 /* BB fixme add conversion for access_flags to bits 0 - 2 of mode */
993 pSMB->Mode = cpu_to_le16(2);
994 pSMB->Mode |= cpu_to_le16(0x40); /* deny none */
995 /* set file as system file if special file such
996 as fifo and server expecting SFU style and
997 no Unix extensions */
999 if(create_options & CREATE_OPTION_SPECIAL)
1000 pSMB->FileAttributes = cpu_to_le16(ATTR_SYSTEM);
1002 pSMB->FileAttributes = cpu_to_le16(0/*ATTR_NORMAL*/); /* BB FIXME */
1004 /* if ((omode & S_IWUGO) == 0)
1005 pSMB->FileAttributes |= cpu_to_le32(ATTR_READONLY);*/
1006 /* Above line causes problems due to vfs splitting create into two
1007 pieces - need to set mode after file created not while it is
1011 /* pSMB->CreateOptions = cpu_to_le32(create_options & CREATE_OPTIONS_MASK); */
1012 /* BB FIXME END BB */
1014 pSMB->Sattr = cpu_to_le16(ATTR_HIDDEN | ATTR_SYSTEM | ATTR_DIRECTORY);
1015 pSMB->OpenFunction = cpu_to_le16(convert_disposition(openDisposition));
1017 pSMB->hdr.smb_buf_length += count;
1019 pSMB->ByteCount = cpu_to_le16(count);
1020 /* long_op set to 1 to allow for oplock break timeouts */
1021 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1022 (struct smb_hdr *) pSMBr, &bytes_returned, 1);
1023 cifs_stats_inc(&tcon->num_opens);
1025 cFYI(1, ("Error in Open = %d", rc));
1027 /* BB verify if wct == 15 */
1029 /* *pOplock = pSMBr->OplockLevel; */ /* BB take from action field BB */
1031 *netfid = pSMBr->Fid; /* cifs fid stays in le */
1032 /* Let caller know file was created so we can set the mode. */
1033 /* Do we care about the CreateAction in any other cases? */
1035 /* if(cpu_to_le32(FILE_CREATE) == pSMBr->CreateAction)
1036 *pOplock |= CIFS_CREATE_ACTION; */
1040 pfile_info->CreationTime = 0; /* BB convert CreateTime*/
1041 pfile_info->LastAccessTime = 0; /* BB fixme */
1042 pfile_info->LastWriteTime = 0; /* BB fixme */
1043 pfile_info->ChangeTime = 0; /* BB fixme */
1044 pfile_info->Attributes =
1045 cpu_to_le32(le16_to_cpu(pSMBr->FileAttributes));
1046 /* the file_info buf is endian converted by caller */
1047 pfile_info->AllocationSize =
1048 cpu_to_le64(le32_to_cpu(pSMBr->EndOfFile));
1049 pfile_info->EndOfFile = pfile_info->AllocationSize;
1050 pfile_info->NumberOfLinks = cpu_to_le32(1);
1054 cifs_buf_release(pSMB);
1061 CIFSSMBOpen(const int xid, struct cifsTconInfo *tcon,
1062 const char *fileName, const int openDisposition,
1063 const int access_flags, const int create_options, __u16 * netfid,
1064 int *pOplock, FILE_ALL_INFO * pfile_info,
1065 const struct nls_table *nls_codepage, int remap)
1068 OPEN_REQ *pSMB = NULL;
1069 OPEN_RSP *pSMBr = NULL;
1075 rc = smb_init(SMB_COM_NT_CREATE_ANDX, 24, tcon, (void **) &pSMB,
1080 pSMB->AndXCommand = 0xFF; /* none */
1082 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1083 count = 1; /* account for one byte pad to word boundary */
1085 cifsConvertToUCS((__le16 *) (pSMB->fileName + 1),
1086 fileName, PATH_MAX, nls_codepage, remap);
1087 name_len++; /* trailing null */
1089 pSMB->NameLength = cpu_to_le16(name_len);
1090 } else { /* BB improve check for buffer overruns BB */
1091 count = 0; /* no pad */
1092 name_len = strnlen(fileName, PATH_MAX);
1093 name_len++; /* trailing null */
1094 pSMB->NameLength = cpu_to_le16(name_len);
1095 strncpy(pSMB->fileName, fileName, name_len);
1097 if (*pOplock & REQ_OPLOCK)
1098 pSMB->OpenFlags = cpu_to_le32(REQ_OPLOCK);
1099 else if (*pOplock & REQ_BATCHOPLOCK) {
1100 pSMB->OpenFlags = cpu_to_le32(REQ_BATCHOPLOCK);
1102 pSMB->DesiredAccess = cpu_to_le32(access_flags);
1103 pSMB->AllocationSize = 0;
1104 /* set file as system file if special file such
1105 as fifo and server expecting SFU style and
1106 no Unix extensions */
1107 if(create_options & CREATE_OPTION_SPECIAL)
1108 pSMB->FileAttributes = cpu_to_le32(ATTR_SYSTEM);
1110 pSMB->FileAttributes = cpu_to_le32(ATTR_NORMAL);
1111 /* XP does not handle ATTR_POSIX_SEMANTICS */
1112 /* but it helps speed up case sensitive checks for other
1113 servers such as Samba */
1114 if (tcon->ses->capabilities & CAP_UNIX)
1115 pSMB->FileAttributes |= cpu_to_le32(ATTR_POSIX_SEMANTICS);
1117 /* if ((omode & S_IWUGO) == 0)
1118 pSMB->FileAttributes |= cpu_to_le32(ATTR_READONLY);*/
1119 /* Above line causes problems due to vfs splitting create into two
1120 pieces - need to set mode after file created not while it is
1122 pSMB->ShareAccess = cpu_to_le32(FILE_SHARE_ALL);
1123 pSMB->CreateDisposition = cpu_to_le32(openDisposition);
1124 pSMB->CreateOptions = cpu_to_le32(create_options & CREATE_OPTIONS_MASK);
1125 /* BB Expirement with various impersonation levels and verify */
1126 pSMB->ImpersonationLevel = cpu_to_le32(SECURITY_IMPERSONATION);
1127 pSMB->SecurityFlags =
1128 SECURITY_CONTEXT_TRACKING | SECURITY_EFFECTIVE_ONLY;
1131 pSMB->hdr.smb_buf_length += count;
1133 pSMB->ByteCount = cpu_to_le16(count);
1134 /* long_op set to 1 to allow for oplock break timeouts */
1135 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1136 (struct smb_hdr *) pSMBr, &bytes_returned, 1);
1137 cifs_stats_inc(&tcon->num_opens);
1139 cFYI(1, ("Error in Open = %d", rc));
1141 *pOplock = pSMBr->OplockLevel; /* 1 byte no need to le_to_cpu */
1142 *netfid = pSMBr->Fid; /* cifs fid stays in le */
1143 /* Let caller know file was created so we can set the mode. */
1144 /* Do we care about the CreateAction in any other cases? */
1145 if(cpu_to_le32(FILE_CREATE) == pSMBr->CreateAction)
1146 *pOplock |= CIFS_CREATE_ACTION;
1148 memcpy((char *)pfile_info,(char *)&pSMBr->CreationTime,
1149 36 /* CreationTime to Attributes */);
1150 /* the file_info buf is endian converted by caller */
1151 pfile_info->AllocationSize = pSMBr->AllocationSize;
1152 pfile_info->EndOfFile = pSMBr->EndOfFile;
1153 pfile_info->NumberOfLinks = cpu_to_le32(1);
1157 cifs_buf_release(pSMB);
1164 CIFSSMBRead(const int xid, struct cifsTconInfo *tcon,
1165 const int netfid, const unsigned int count,
1166 const __u64 lseek, unsigned int *nbytes, char **buf,
1170 READ_REQ *pSMB = NULL;
1171 READ_RSP *pSMBr = NULL;
1172 char *pReadData = NULL;
1174 int resp_buf_type = 0;
1177 cFYI(1,("Reading %d bytes on fid %d",count,netfid));
1178 if(tcon->ses->capabilities & CAP_LARGE_FILES)
1181 wct = 10; /* old style read */
1184 rc = small_smb_init(SMB_COM_READ_ANDX, wct, tcon, (void **) &pSMB);
1188 /* tcon and ses pointer are checked in smb_init */
1189 if (tcon->ses->server == NULL)
1190 return -ECONNABORTED;
1192 pSMB->AndXCommand = 0xFF; /* none */
1194 pSMB->OffsetLow = cpu_to_le32(lseek & 0xFFFFFFFF);
1196 pSMB->OffsetHigh = cpu_to_le32(lseek >> 32);
1197 else if((lseek >> 32) > 0) /* can not handle this big offset for old */
1200 pSMB->Remaining = 0;
1201 pSMB->MaxCount = cpu_to_le16(count & 0xFFFF);
1202 pSMB->MaxCountHigh = cpu_to_le32(count >> 16);
1204 pSMB->ByteCount = 0; /* no need to do le conversion since 0 */
1206 /* old style read */
1207 struct smb_com_readx_req * pSMBW =
1208 (struct smb_com_readx_req *)pSMB;
1209 pSMBW->ByteCount = 0;
1212 iov[0].iov_base = (char *)pSMB;
1213 iov[0].iov_len = pSMB->hdr.smb_buf_length + 4;
1214 rc = SendReceive2(xid, tcon->ses, iov,
1217 cifs_stats_inc(&tcon->num_reads);
1218 pSMBr = (READ_RSP *)iov[0].iov_base;
1220 cERROR(1, ("Send error in read = %d", rc));
1222 int data_length = le16_to_cpu(pSMBr->DataLengthHigh);
1223 data_length = data_length << 16;
1224 data_length += le16_to_cpu(pSMBr->DataLength);
1225 *nbytes = data_length;
1227 /*check that DataLength would not go beyond end of SMB */
1228 if ((data_length > CIFSMaxBufSize)
1229 || (data_length > count)) {
1230 cFYI(1,("bad length %d for count %d",data_length,count));
1234 pReadData = (char *) (&pSMBr->hdr.Protocol) +
1235 le16_to_cpu(pSMBr->DataOffset);
1236 /* if(rc = copy_to_user(buf, pReadData, data_length)) {
1237 cERROR(1,("Faulting on read rc = %d",rc));
1239 }*/ /* can not use copy_to_user when using page cache*/
1241 memcpy(*buf,pReadData,data_length);
1245 /* cifs_small_buf_release(pSMB); */ /* Freed earlier now in SendReceive2 */
1247 if(resp_buf_type == CIFS_SMALL_BUFFER)
1248 cifs_small_buf_release(iov[0].iov_base);
1249 else if(resp_buf_type == CIFS_LARGE_BUFFER)
1250 cifs_buf_release(iov[0].iov_base);
1251 } else if(resp_buf_type != CIFS_NO_BUFFER) {
1252 /* return buffer to caller to free */
1253 *buf = iov[0].iov_base;
1254 if(resp_buf_type == CIFS_SMALL_BUFFER)
1255 *pbuf_type = CIFS_SMALL_BUFFER;
1256 else if(resp_buf_type == CIFS_LARGE_BUFFER)
1257 *pbuf_type = CIFS_LARGE_BUFFER;
1258 } /* else no valid buffer on return - leave as null */
1260 /* Note: On -EAGAIN error only caller can retry on handle based calls
1261 since file handle passed in no longer valid */
1267 CIFSSMBWrite(const int xid, struct cifsTconInfo *tcon,
1268 const int netfid, const unsigned int count,
1269 const __u64 offset, unsigned int *nbytes, const char *buf,
1270 const char __user * ubuf, const int long_op)
1273 WRITE_REQ *pSMB = NULL;
1274 WRITE_RSP *pSMBr = NULL;
1275 int bytes_returned, wct;
1279 /* cFYI(1,("write at %lld %d bytes",offset,count));*/
1280 if(tcon->ses == NULL)
1281 return -ECONNABORTED;
1283 if(tcon->ses->capabilities & CAP_LARGE_FILES)
1288 rc = smb_init(SMB_COM_WRITE_ANDX, wct, tcon, (void **) &pSMB,
1292 /* tcon and ses pointer are checked in smb_init */
1293 if (tcon->ses->server == NULL)
1294 return -ECONNABORTED;
1296 pSMB->AndXCommand = 0xFF; /* none */
1298 pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF);
1300 pSMB->OffsetHigh = cpu_to_le32(offset >> 32);
1301 else if((offset >> 32) > 0) /* can not handle this big offset for old */
1304 pSMB->Reserved = 0xFFFFFFFF;
1305 pSMB->WriteMode = 0;
1306 pSMB->Remaining = 0;
1308 /* Can increase buffer size if buffer is big enough in some cases - ie we
1309 can send more if LARGE_WRITE_X capability returned by the server and if
1310 our buffer is big enough or if we convert to iovecs on socket writes
1311 and eliminate the copy to the CIFS buffer */
1312 if(tcon->ses->capabilities & CAP_LARGE_WRITE_X) {
1313 bytes_sent = min_t(const unsigned int, CIFSMaxBufSize, count);
1315 bytes_sent = (tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE)
1319 if (bytes_sent > count)
1322 cpu_to_le16(offsetof(struct smb_com_write_req,Data) - 4);
1324 memcpy(pSMB->Data,buf,bytes_sent);
1326 if(copy_from_user(pSMB->Data,ubuf,bytes_sent)) {
1327 cifs_buf_release(pSMB);
1330 } else if (count != 0) {
1332 cifs_buf_release(pSMB);
1334 } /* else setting file size with write of zero bytes */
1336 byte_count = bytes_sent + 1; /* pad */
1337 else /* wct == 12 */ {
1338 byte_count = bytes_sent + 5; /* bigger pad, smaller smb hdr */
1340 pSMB->DataLengthLow = cpu_to_le16(bytes_sent & 0xFFFF);
1341 pSMB->DataLengthHigh = cpu_to_le16(bytes_sent >> 16);
1342 pSMB->hdr.smb_buf_length += byte_count;
1345 pSMB->ByteCount = cpu_to_le16(byte_count);
1346 else { /* old style write has byte count 4 bytes earlier so 4 bytes pad */
1347 struct smb_com_writex_req * pSMBW =
1348 (struct smb_com_writex_req *)pSMB;
1349 pSMBW->ByteCount = cpu_to_le16(byte_count);
1352 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1353 (struct smb_hdr *) pSMBr, &bytes_returned, long_op);
1354 cifs_stats_inc(&tcon->num_writes);
1356 cFYI(1, ("Send error in write = %d", rc));
1359 *nbytes = le16_to_cpu(pSMBr->CountHigh);
1360 *nbytes = (*nbytes) << 16;
1361 *nbytes += le16_to_cpu(pSMBr->Count);
1364 cifs_buf_release(pSMB);
1366 /* Note: On -EAGAIN error only caller can retry on handle based calls
1367 since file handle passed in no longer valid */
1373 CIFSSMBWrite2(const int xid, struct cifsTconInfo *tcon,
1374 const int netfid, const unsigned int count,
1375 const __u64 offset, unsigned int *nbytes, struct kvec *iov,
1376 int n_vec, const int long_op)
1379 WRITE_REQ *pSMB = NULL;
1382 int resp_buf_type = 0;
1384 cFYI(1,("write2 at %lld %d bytes", (long long)offset, count));
1386 if(tcon->ses->capabilities & CAP_LARGE_FILES)
1390 rc = small_smb_init(SMB_COM_WRITE_ANDX, wct, tcon, (void **) &pSMB);
1393 /* tcon and ses pointer are checked in smb_init */
1394 if (tcon->ses->server == NULL)
1395 return -ECONNABORTED;
1397 pSMB->AndXCommand = 0xFF; /* none */
1399 pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF);
1401 pSMB->OffsetHigh = cpu_to_le32(offset >> 32);
1402 else if((offset >> 32) > 0) /* can not handle this big offset for old */
1404 pSMB->Reserved = 0xFFFFFFFF;
1405 pSMB->WriteMode = 0;
1406 pSMB->Remaining = 0;
1409 cpu_to_le16(offsetof(struct smb_com_write_req,Data) - 4);
1411 pSMB->DataLengthLow = cpu_to_le16(count & 0xFFFF);
1412 pSMB->DataLengthHigh = cpu_to_le16(count >> 16);
1413 smb_hdr_len = pSMB->hdr.smb_buf_length + 1; /* hdr + 1 byte pad */
1415 pSMB->hdr.smb_buf_length += count+1;
1416 else /* wct == 12 */
1417 pSMB->hdr.smb_buf_length += count+5; /* smb data starts later */
1419 pSMB->ByteCount = cpu_to_le16(count + 1);
1420 else /* wct == 12 */ /* bigger pad, smaller smb hdr, keep offset ok */ {
1421 struct smb_com_writex_req * pSMBW =
1422 (struct smb_com_writex_req *)pSMB;
1423 pSMBW->ByteCount = cpu_to_le16(count + 5);
1425 iov[0].iov_base = pSMB;
1427 iov[0].iov_len = smb_hdr_len + 4;
1428 else /* wct == 12 pad bigger by four bytes */
1429 iov[0].iov_len = smb_hdr_len + 8;
1432 rc = SendReceive2(xid, tcon->ses, iov, n_vec + 1, &resp_buf_type,
1434 cifs_stats_inc(&tcon->num_writes);
1436 cFYI(1, ("Send error Write2 = %d", rc));
1438 } else if(resp_buf_type == 0) {
1439 /* presumably this can not happen, but best to be safe */
1443 WRITE_RSP * pSMBr = (WRITE_RSP *)iov[0].iov_base;
1444 *nbytes = le16_to_cpu(pSMBr->CountHigh);
1445 *nbytes = (*nbytes) << 16;
1446 *nbytes += le16_to_cpu(pSMBr->Count);
1449 /* cifs_small_buf_release(pSMB); */ /* Freed earlier now in SendReceive2 */
1450 if(resp_buf_type == CIFS_SMALL_BUFFER)
1451 cifs_small_buf_release(iov[0].iov_base);
1452 else if(resp_buf_type == CIFS_LARGE_BUFFER)
1453 cifs_buf_release(iov[0].iov_base);
1455 /* Note: On -EAGAIN error only caller can retry on handle based calls
1456 since file handle passed in no longer valid */
1463 CIFSSMBLock(const int xid, struct cifsTconInfo *tcon,
1464 const __u16 smb_file_id, const __u64 len,
1465 const __u64 offset, const __u32 numUnlock,
1466 const __u32 numLock, const __u8 lockType, const int waitFlag)
1469 LOCK_REQ *pSMB = NULL;
1470 LOCK_RSP *pSMBr = NULL;
1475 cFYI(1, ("In CIFSSMBLock - timeout %d numLock %d",waitFlag,numLock));
1476 rc = small_smb_init(SMB_COM_LOCKING_ANDX, 8, tcon, (void **) &pSMB);
1481 pSMBr = (LOCK_RSP *)pSMB; /* BB removeme BB */
1483 if(lockType == LOCKING_ANDX_OPLOCK_RELEASE) {
1484 timeout = -1; /* no response expected */
1486 } else if (waitFlag == TRUE) {
1487 timeout = 3; /* blocking operation, no timeout */
1488 pSMB->Timeout = cpu_to_le32(-1);/* blocking - do not time out */
1493 pSMB->NumberOfLocks = cpu_to_le16(numLock);
1494 pSMB->NumberOfUnlocks = cpu_to_le16(numUnlock);
1495 pSMB->LockType = lockType;
1496 pSMB->AndXCommand = 0xFF; /* none */
1497 pSMB->Fid = smb_file_id; /* netfid stays le */
1499 if((numLock != 0) || (numUnlock != 0)) {
1500 pSMB->Locks[0].Pid = cpu_to_le16(current->tgid);
1501 /* BB where to store pid high? */
1502 pSMB->Locks[0].LengthLow = cpu_to_le32((u32)len);
1503 pSMB->Locks[0].LengthHigh = cpu_to_le32((u32)(len>>32));
1504 pSMB->Locks[0].OffsetLow = cpu_to_le32((u32)offset);
1505 pSMB->Locks[0].OffsetHigh = cpu_to_le32((u32)(offset>>32));
1506 count = sizeof(LOCKING_ANDX_RANGE);
1511 pSMB->hdr.smb_buf_length += count;
1512 pSMB->ByteCount = cpu_to_le16(count);
1515 rc = SendReceiveBlockingLock(xid, tcon, (struct smb_hdr *) pSMB,
1516 (struct smb_hdr *) pSMBr, &bytes_returned);
1518 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1519 (struct smb_hdr *) pSMBr, &bytes_returned, timeout);
1521 cifs_stats_inc(&tcon->num_locks);
1523 cFYI(1, ("Send error in Lock = %d", rc));
1525 cifs_small_buf_release(pSMB);
1527 /* Note: On -EAGAIN error only caller can retry on handle based calls
1528 since file handle passed in no longer valid */
1533 CIFSSMBPosixLock(const int xid, struct cifsTconInfo *tcon,
1534 const __u16 smb_file_id, const int get_flag, const __u64 len,
1535 struct file_lock *pLockData, const __u16 lock_type,
1538 struct smb_com_transaction2_sfi_req *pSMB = NULL;
1539 struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
1541 struct cifs_posix_lock *parm_data;
1544 int bytes_returned = 0;
1545 __u16 params, param_offset, offset, byte_count, count;
1547 cFYI(1, ("Posix Lock"));
1549 if(pLockData == NULL)
1552 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
1557 pSMBr = (struct smb_com_transaction2_sfi_rsp *)pSMB;
1560 pSMB->MaxSetupCount = 0;
1563 pSMB->Reserved2 = 0;
1564 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
1565 offset = param_offset + params;
1567 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
1569 count = sizeof(struct cifs_posix_lock);
1570 pSMB->MaxParameterCount = cpu_to_le16(2);
1571 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB PDU from sess */
1572 pSMB->SetupCount = 1;
1573 pSMB->Reserved3 = 0;
1575 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION);
1577 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
1578 byte_count = 3 /* pad */ + params + count;
1579 pSMB->DataCount = cpu_to_le16(count);
1580 pSMB->ParameterCount = cpu_to_le16(params);
1581 pSMB->TotalDataCount = pSMB->DataCount;
1582 pSMB->TotalParameterCount = pSMB->ParameterCount;
1583 pSMB->ParameterOffset = cpu_to_le16(param_offset);
1584 parm_data = (struct cifs_posix_lock *)
1585 (((char *) &pSMB->hdr.Protocol) + offset);
1587 parm_data->lock_type = cpu_to_le16(lock_type);
1589 timeout = 3; /* blocking operation, no timeout */
1590 parm_data->lock_flags = cpu_to_le16(1);
1591 pSMB->Timeout = cpu_to_le32(-1);
1595 parm_data->pid = cpu_to_le32(current->tgid);
1596 parm_data->start = cpu_to_le64(pLockData->fl_start);
1597 parm_data->length = cpu_to_le64(len); /* normalize negative numbers */
1599 pSMB->DataOffset = cpu_to_le16(offset);
1600 pSMB->Fid = smb_file_id;
1601 pSMB->InformationLevel = cpu_to_le16(SMB_SET_POSIX_LOCK);
1602 pSMB->Reserved4 = 0;
1603 pSMB->hdr.smb_buf_length += byte_count;
1604 pSMB->ByteCount = cpu_to_le16(byte_count);
1606 rc = SendReceiveBlockingLock(xid, tcon, (struct smb_hdr *) pSMB,
1607 (struct smb_hdr *) pSMBr, &bytes_returned);
1609 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1610 (struct smb_hdr *) pSMBr, &bytes_returned, timeout);
1614 cFYI(1, ("Send error in Posix Lock = %d", rc));
1615 } else if (get_flag) {
1616 /* lock structure can be returned on get */
1619 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
1621 if (rc || (pSMBr->ByteCount < sizeof(struct cifs_posix_lock))) {
1622 rc = -EIO; /* bad smb */
1625 if(pLockData == NULL) {
1629 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
1630 data_count = le16_to_cpu(pSMBr->t2.DataCount);
1631 if(data_count < sizeof(struct cifs_posix_lock)) {
1635 parm_data = (struct cifs_posix_lock *)
1636 ((char *)&pSMBr->hdr.Protocol + data_offset);
1637 if(parm_data->lock_type == cpu_to_le16(CIFS_UNLCK))
1638 pLockData->fl_type = F_UNLCK;
1643 cifs_small_buf_release(pSMB);
1645 /* Note: On -EAGAIN error only caller can retry on handle based calls
1646 since file handle passed in no longer valid */
1653 CIFSSMBClose(const int xid, struct cifsTconInfo *tcon, int smb_file_id)
1656 CLOSE_REQ *pSMB = NULL;
1657 CLOSE_RSP *pSMBr = NULL;
1659 cFYI(1, ("In CIFSSMBClose"));
1661 /* do not retry on dead session on close */
1662 rc = small_smb_init(SMB_COM_CLOSE, 3, tcon, (void **) &pSMB);
1668 pSMBr = (CLOSE_RSP *)pSMB; /* BB removeme BB */
1670 pSMB->FileID = (__u16) smb_file_id;
1671 pSMB->LastWriteTime = 0xFFFFFFFF;
1672 pSMB->ByteCount = 0;
1673 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1674 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1675 cifs_stats_inc(&tcon->num_closes);
1678 /* EINTR is expected when user ctl-c to kill app */
1679 cERROR(1, ("Send error in Close = %d", rc));
1683 cifs_small_buf_release(pSMB);
1685 /* Since session is dead, file will be closed on server already */
1693 CIFSSMBRename(const int xid, struct cifsTconInfo *tcon,
1694 const char *fromName, const char *toName,
1695 const struct nls_table *nls_codepage, int remap)
1698 RENAME_REQ *pSMB = NULL;
1699 RENAME_RSP *pSMBr = NULL;
1701 int name_len, name_len2;
1704 cFYI(1, ("In CIFSSMBRename"));
1706 rc = smb_init(SMB_COM_RENAME, 1, tcon, (void **) &pSMB,
1711 pSMB->BufferFormat = 0x04;
1712 pSMB->SearchAttributes =
1713 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
1716 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1718 cifsConvertToUCS((__le16 *) pSMB->OldFileName, fromName,
1719 PATH_MAX, nls_codepage, remap);
1720 name_len++; /* trailing null */
1722 pSMB->OldFileName[name_len] = 0x04; /* pad */
1723 /* protocol requires ASCII signature byte on Unicode string */
1724 pSMB->OldFileName[name_len + 1] = 0x00;
1726 cifsConvertToUCS((__le16 *) &pSMB->OldFileName[name_len + 2],
1727 toName, PATH_MAX, nls_codepage, remap);
1728 name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
1729 name_len2 *= 2; /* convert to bytes */
1730 } else { /* BB improve the check for buffer overruns BB */
1731 name_len = strnlen(fromName, PATH_MAX);
1732 name_len++; /* trailing null */
1733 strncpy(pSMB->OldFileName, fromName, name_len);
1734 name_len2 = strnlen(toName, PATH_MAX);
1735 name_len2++; /* trailing null */
1736 pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */
1737 strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2);
1738 name_len2++; /* trailing null */
1739 name_len2++; /* signature byte */
1742 count = 1 /* 1st signature byte */ + name_len + name_len2;
1743 pSMB->hdr.smb_buf_length += count;
1744 pSMB->ByteCount = cpu_to_le16(count);
1746 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1747 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1748 cifs_stats_inc(&tcon->num_renames);
1750 cFYI(1, ("Send error in rename = %d", rc));
1753 cifs_buf_release(pSMB);
1761 int CIFSSMBRenameOpenFile(const int xid,struct cifsTconInfo *pTcon,
1762 int netfid, char * target_name,
1763 const struct nls_table * nls_codepage, int remap)
1765 struct smb_com_transaction2_sfi_req *pSMB = NULL;
1766 struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
1767 struct set_file_rename * rename_info;
1769 char dummy_string[30];
1771 int bytes_returned = 0;
1773 __u16 params, param_offset, offset, count, byte_count;
1775 cFYI(1, ("Rename to File by handle"));
1776 rc = smb_init(SMB_COM_TRANSACTION2, 15, pTcon, (void **) &pSMB,
1782 pSMB->MaxSetupCount = 0;
1786 pSMB->Reserved2 = 0;
1787 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
1788 offset = param_offset + params;
1790 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
1791 rename_info = (struct set_file_rename *) data_offset;
1792 pSMB->MaxParameterCount = cpu_to_le16(2);
1793 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB PDU from sess */
1794 pSMB->SetupCount = 1;
1795 pSMB->Reserved3 = 0;
1796 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
1797 byte_count = 3 /* pad */ + params;
1798 pSMB->ParameterCount = cpu_to_le16(params);
1799 pSMB->TotalParameterCount = pSMB->ParameterCount;
1800 pSMB->ParameterOffset = cpu_to_le16(param_offset);
1801 pSMB->DataOffset = cpu_to_le16(offset);
1802 /* construct random name ".cifs_tmp<inodenum><mid>" */
1803 rename_info->overwrite = cpu_to_le32(1);
1804 rename_info->root_fid = 0;
1805 /* unicode only call */
1806 if(target_name == NULL) {
1807 sprintf(dummy_string,"cifs%x",pSMB->hdr.Mid);
1808 len_of_str = cifsConvertToUCS((__le16 *)rename_info->target_name,
1809 dummy_string, 24, nls_codepage, remap);
1811 len_of_str = cifsConvertToUCS((__le16 *)rename_info->target_name,
1812 target_name, PATH_MAX, nls_codepage, remap);
1814 rename_info->target_name_len = cpu_to_le32(2 * len_of_str);
1815 count = 12 /* sizeof(struct set_file_rename) */ + (2 * len_of_str) + 2;
1816 byte_count += count;
1817 pSMB->DataCount = cpu_to_le16(count);
1818 pSMB->TotalDataCount = pSMB->DataCount;
1820 pSMB->InformationLevel =
1821 cpu_to_le16(SMB_SET_FILE_RENAME_INFORMATION);
1822 pSMB->Reserved4 = 0;
1823 pSMB->hdr.smb_buf_length += byte_count;
1824 pSMB->ByteCount = cpu_to_le16(byte_count);
1825 rc = SendReceive(xid, pTcon->ses, (struct smb_hdr *) pSMB,
1826 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1827 cifs_stats_inc(&pTcon->num_t2renames);
1829 cFYI(1,("Send error in Rename (by file handle) = %d", rc));
1832 cifs_buf_release(pSMB);
1834 /* Note: On -EAGAIN error only caller can retry on handle based calls
1835 since file handle passed in no longer valid */
1841 CIFSSMBCopy(const int xid, struct cifsTconInfo *tcon, const char * fromName,
1842 const __u16 target_tid, const char *toName, const int flags,
1843 const struct nls_table *nls_codepage, int remap)
1846 COPY_REQ *pSMB = NULL;
1847 COPY_RSP *pSMBr = NULL;
1849 int name_len, name_len2;
1852 cFYI(1, ("In CIFSSMBCopy"));
1854 rc = smb_init(SMB_COM_COPY, 1, tcon, (void **) &pSMB,
1859 pSMB->BufferFormat = 0x04;
1860 pSMB->Tid2 = target_tid;
1862 pSMB->Flags = cpu_to_le16(flags & COPY_TREE);
1864 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1865 name_len = cifsConvertToUCS((__le16 *) pSMB->OldFileName,
1866 fromName, PATH_MAX, nls_codepage,
1868 name_len++; /* trailing null */
1870 pSMB->OldFileName[name_len] = 0x04; /* pad */
1871 /* protocol requires ASCII signature byte on Unicode string */
1872 pSMB->OldFileName[name_len + 1] = 0x00;
1873 name_len2 = cifsConvertToUCS((__le16 *)&pSMB->OldFileName[name_len + 2],
1874 toName, PATH_MAX, nls_codepage, remap);
1875 name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
1876 name_len2 *= 2; /* convert to bytes */
1877 } else { /* BB improve the check for buffer overruns BB */
1878 name_len = strnlen(fromName, PATH_MAX);
1879 name_len++; /* trailing null */
1880 strncpy(pSMB->OldFileName, fromName, name_len);
1881 name_len2 = strnlen(toName, PATH_MAX);
1882 name_len2++; /* trailing null */
1883 pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */
1884 strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2);
1885 name_len2++; /* trailing null */
1886 name_len2++; /* signature byte */
1889 count = 1 /* 1st signature byte */ + name_len + name_len2;
1890 pSMB->hdr.smb_buf_length += count;
1891 pSMB->ByteCount = cpu_to_le16(count);
1893 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1894 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1896 cFYI(1, ("Send error in copy = %d with %d files copied",
1897 rc, le16_to_cpu(pSMBr->CopyCount)));
1900 cifs_buf_release(pSMB);
1909 CIFSUnixCreateSymLink(const int xid, struct cifsTconInfo *tcon,
1910 const char *fromName, const char *toName,
1911 const struct nls_table *nls_codepage)
1913 TRANSACTION2_SPI_REQ *pSMB = NULL;
1914 TRANSACTION2_SPI_RSP *pSMBr = NULL;
1917 int name_len_target;
1919 int bytes_returned = 0;
1920 __u16 params, param_offset, offset, byte_count;
1922 cFYI(1, ("In Symlink Unix style"));
1924 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
1929 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1931 cifs_strtoUCS((__le16 *) pSMB->FileName, fromName, PATH_MAX
1932 /* find define for this maxpathcomponent */
1934 name_len++; /* trailing null */
1937 } else { /* BB improve the check for buffer overruns BB */
1938 name_len = strnlen(fromName, PATH_MAX);
1939 name_len++; /* trailing null */
1940 strncpy(pSMB->FileName, fromName, name_len);
1942 params = 6 + name_len;
1943 pSMB->MaxSetupCount = 0;
1947 pSMB->Reserved2 = 0;
1948 param_offset = offsetof(struct smb_com_transaction2_spi_req,
1949 InformationLevel) - 4;
1950 offset = param_offset + params;
1952 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
1953 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1955 cifs_strtoUCS((__le16 *) data_offset, toName, PATH_MAX
1956 /* find define for this maxpathcomponent */
1958 name_len_target++; /* trailing null */
1959 name_len_target *= 2;
1960 } else { /* BB improve the check for buffer overruns BB */
1961 name_len_target = strnlen(toName, PATH_MAX);
1962 name_len_target++; /* trailing null */
1963 strncpy(data_offset, toName, name_len_target);
1966 pSMB->MaxParameterCount = cpu_to_le16(2);
1967 /* BB find exact max on data count below from sess */
1968 pSMB->MaxDataCount = cpu_to_le16(1000);
1969 pSMB->SetupCount = 1;
1970 pSMB->Reserved3 = 0;
1971 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
1972 byte_count = 3 /* pad */ + params + name_len_target;
1973 pSMB->DataCount = cpu_to_le16(name_len_target);
1974 pSMB->ParameterCount = cpu_to_le16(params);
1975 pSMB->TotalDataCount = pSMB->DataCount;
1976 pSMB->TotalParameterCount = pSMB->ParameterCount;
1977 pSMB->ParameterOffset = cpu_to_le16(param_offset);
1978 pSMB->DataOffset = cpu_to_le16(offset);
1979 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_LINK);
1980 pSMB->Reserved4 = 0;
1981 pSMB->hdr.smb_buf_length += byte_count;
1982 pSMB->ByteCount = cpu_to_le16(byte_count);
1983 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1984 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1985 cifs_stats_inc(&tcon->num_symlinks);
1988 ("Send error in SetPathInfo (create symlink) = %d",
1993 cifs_buf_release(pSMB);
1996 goto createSymLinkRetry;
2002 CIFSUnixCreateHardLink(const int xid, struct cifsTconInfo *tcon,
2003 const char *fromName, const char *toName,
2004 const struct nls_table *nls_codepage, int remap)
2006 TRANSACTION2_SPI_REQ *pSMB = NULL;
2007 TRANSACTION2_SPI_RSP *pSMBr = NULL;
2010 int name_len_target;
2012 int bytes_returned = 0;
2013 __u16 params, param_offset, offset, byte_count;
2015 cFYI(1, ("In Create Hard link Unix style"));
2016 createHardLinkRetry:
2017 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2022 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2023 name_len = cifsConvertToUCS((__le16 *) pSMB->FileName, toName,
2024 PATH_MAX, nls_codepage, remap);
2025 name_len++; /* trailing null */
2028 } else { /* BB improve the check for buffer overruns BB */
2029 name_len = strnlen(toName, PATH_MAX);
2030 name_len++; /* trailing null */
2031 strncpy(pSMB->FileName, toName, name_len);
2033 params = 6 + name_len;
2034 pSMB->MaxSetupCount = 0;
2038 pSMB->Reserved2 = 0;
2039 param_offset = offsetof(struct smb_com_transaction2_spi_req,
2040 InformationLevel) - 4;
2041 offset = param_offset + params;
2043 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
2044 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2046 cifsConvertToUCS((__le16 *) data_offset, fromName, PATH_MAX,
2047 nls_codepage, remap);
2048 name_len_target++; /* trailing null */
2049 name_len_target *= 2;
2050 } else { /* BB improve the check for buffer overruns BB */
2051 name_len_target = strnlen(fromName, PATH_MAX);
2052 name_len_target++; /* trailing null */
2053 strncpy(data_offset, fromName, name_len_target);
2056 pSMB->MaxParameterCount = cpu_to_le16(2);
2057 /* BB find exact max on data count below from sess*/
2058 pSMB->MaxDataCount = cpu_to_le16(1000);
2059 pSMB->SetupCount = 1;
2060 pSMB->Reserved3 = 0;
2061 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
2062 byte_count = 3 /* pad */ + params + name_len_target;
2063 pSMB->ParameterCount = cpu_to_le16(params);
2064 pSMB->TotalParameterCount = pSMB->ParameterCount;
2065 pSMB->DataCount = cpu_to_le16(name_len_target);
2066 pSMB->TotalDataCount = pSMB->DataCount;
2067 pSMB->ParameterOffset = cpu_to_le16(param_offset);
2068 pSMB->DataOffset = cpu_to_le16(offset);
2069 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_HLINK);
2070 pSMB->Reserved4 = 0;
2071 pSMB->hdr.smb_buf_length += byte_count;
2072 pSMB->ByteCount = cpu_to_le16(byte_count);
2073 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2074 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2075 cifs_stats_inc(&tcon->num_hardlinks);
2077 cFYI(1, ("Send error in SetPathInfo (hard link) = %d", rc));
2080 cifs_buf_release(pSMB);
2082 goto createHardLinkRetry;
2088 CIFSCreateHardLink(const int xid, struct cifsTconInfo *tcon,
2089 const char *fromName, const char *toName,
2090 const struct nls_table *nls_codepage, int remap)
2093 NT_RENAME_REQ *pSMB = NULL;
2094 RENAME_RSP *pSMBr = NULL;
2096 int name_len, name_len2;
2099 cFYI(1, ("In CIFSCreateHardLink"));
2100 winCreateHardLinkRetry:
2102 rc = smb_init(SMB_COM_NT_RENAME, 4, tcon, (void **) &pSMB,
2107 pSMB->SearchAttributes =
2108 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
2110 pSMB->Flags = cpu_to_le16(CREATE_HARD_LINK);
2111 pSMB->ClusterCount = 0;
2113 pSMB->BufferFormat = 0x04;
2115 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2117 cifsConvertToUCS((__le16 *) pSMB->OldFileName, fromName,
2118 PATH_MAX, nls_codepage, remap);
2119 name_len++; /* trailing null */
2121 pSMB->OldFileName[name_len] = 0; /* pad */
2122 pSMB->OldFileName[name_len + 1] = 0x04;
2124 cifsConvertToUCS((__le16 *)&pSMB->OldFileName[name_len + 2],
2125 toName, PATH_MAX, nls_codepage, remap);
2126 name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
2127 name_len2 *= 2; /* convert to bytes */
2128 } else { /* BB improve the check for buffer overruns BB */
2129 name_len = strnlen(fromName, PATH_MAX);
2130 name_len++; /* trailing null */
2131 strncpy(pSMB->OldFileName, fromName, name_len);
2132 name_len2 = strnlen(toName, PATH_MAX);
2133 name_len2++; /* trailing null */
2134 pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */
2135 strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2);
2136 name_len2++; /* trailing null */
2137 name_len2++; /* signature byte */
2140 count = 1 /* string type byte */ + name_len + name_len2;
2141 pSMB->hdr.smb_buf_length += count;
2142 pSMB->ByteCount = cpu_to_le16(count);
2144 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2145 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2146 cifs_stats_inc(&tcon->num_hardlinks);
2148 cFYI(1, ("Send error in hard link (NT rename) = %d", rc));
2150 cifs_buf_release(pSMB);
2152 goto winCreateHardLinkRetry;
2158 CIFSSMBUnixQuerySymLink(const int xid, struct cifsTconInfo *tcon,
2159 const unsigned char *searchName,
2160 char *symlinkinfo, const int buflen,
2161 const struct nls_table *nls_codepage)
2163 /* SMB_QUERY_FILE_UNIX_LINK */
2164 TRANSACTION2_QPI_REQ *pSMB = NULL;
2165 TRANSACTION2_QPI_RSP *pSMBr = NULL;
2169 __u16 params, byte_count;
2171 cFYI(1, ("In QPathSymLinkInfo (Unix) for path %s", searchName));
2174 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2179 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2181 cifs_strtoUCS((__le16 *) pSMB->FileName, searchName, PATH_MAX
2182 /* find define for this maxpathcomponent */
2184 name_len++; /* trailing null */
2186 } else { /* BB improve the check for buffer overruns BB */
2187 name_len = strnlen(searchName, PATH_MAX);
2188 name_len++; /* trailing null */
2189 strncpy(pSMB->FileName, searchName, name_len);
2192 params = 2 /* level */ + 4 /* rsrvd */ + name_len /* incl null */ ;
2193 pSMB->TotalDataCount = 0;
2194 pSMB->MaxParameterCount = cpu_to_le16(2);
2195 /* BB find exact max data count below from sess structure BB */
2196 pSMB->MaxDataCount = cpu_to_le16(4000);
2197 pSMB->MaxSetupCount = 0;
2201 pSMB->Reserved2 = 0;
2202 pSMB->ParameterOffset = cpu_to_le16(offsetof(
2203 struct smb_com_transaction2_qpi_req ,InformationLevel) - 4);
2204 pSMB->DataCount = 0;
2205 pSMB->DataOffset = 0;
2206 pSMB->SetupCount = 1;
2207 pSMB->Reserved3 = 0;
2208 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
2209 byte_count = params + 1 /* pad */ ;
2210 pSMB->TotalParameterCount = cpu_to_le16(params);
2211 pSMB->ParameterCount = pSMB->TotalParameterCount;
2212 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_LINK);
2213 pSMB->Reserved4 = 0;
2214 pSMB->hdr.smb_buf_length += byte_count;
2215 pSMB->ByteCount = cpu_to_le16(byte_count);
2217 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2218 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2220 cFYI(1, ("Send error in QuerySymLinkInfo = %d", rc));
2222 /* decode response */
2224 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
2225 if (rc || (pSMBr->ByteCount < 2))
2226 /* BB also check enough total bytes returned */
2227 rc = -EIO; /* bad smb */
2229 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
2230 __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
2232 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
2233 name_len = UniStrnlen((wchar_t *) ((char *)
2234 &pSMBr->hdr.Protocol +data_offset),
2235 min_t(const int, buflen,count) / 2);
2236 /* BB FIXME investigate remapping reserved chars here */
2237 cifs_strfromUCS_le(symlinkinfo,
2238 (__le16 *) ((char *)&pSMBr->hdr.Protocol +
2240 name_len, nls_codepage);
2242 strncpy(symlinkinfo,
2243 (char *) &pSMBr->hdr.Protocol +
2245 min_t(const int, buflen, count));
2247 symlinkinfo[buflen] = 0;
2248 /* just in case so calling code does not go off the end of buffer */
2251 cifs_buf_release(pSMB);
2253 goto querySymLinkRetry;
2257 /* Initialize NT TRANSACT SMB into small smb request buffer.
2258 This assumes that all NT TRANSACTS that we init here have
2259 total parm and data under about 400 bytes (to fit in small cifs
2260 buffer size), which is the case so far, it easily fits. NB:
2261 Setup words themselves and ByteCount
2262 MaxSetupCount (size of returned setup area) and
2263 MaxParameterCount (returned parms size) must be set by caller */
2265 smb_init_ntransact(const __u16 sub_command, const int setup_count,
2266 const int parm_len, struct cifsTconInfo *tcon,
2271 struct smb_com_ntransact_req * pSMB;
2273 rc = small_smb_init(SMB_COM_NT_TRANSACT, 19 + setup_count, tcon,
2277 *ret_buf = (void *)pSMB;
2279 pSMB->TotalParameterCount = cpu_to_le32(parm_len);
2280 pSMB->TotalDataCount = 0;
2281 pSMB->MaxDataCount = cpu_to_le32((tcon->ses->server->maxBuf -
2282 MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
2283 pSMB->ParameterCount = pSMB->TotalParameterCount;
2284 pSMB->DataCount = pSMB->TotalDataCount;
2285 temp_offset = offsetof(struct smb_com_ntransact_req, Parms) +
2286 (setup_count * 2) - 4 /* for rfc1001 length itself */;
2287 pSMB->ParameterOffset = cpu_to_le32(temp_offset);
2288 pSMB->DataOffset = cpu_to_le32(temp_offset + parm_len);
2289 pSMB->SetupCount = setup_count; /* no need to le convert byte fields */
2290 pSMB->SubCommand = cpu_to_le16(sub_command);
2295 validate_ntransact(char * buf, char ** ppparm, char ** ppdata,
2296 int * pdatalen, int * pparmlen)
2299 __u32 data_count, data_offset, parm_count, parm_offset;
2300 struct smb_com_ntransact_rsp * pSMBr;
2305 pSMBr = (struct smb_com_ntransact_rsp *)buf;
2307 /* ByteCount was converted from little endian in SendReceive */
2308 end_of_smb = 2 /* sizeof byte count */ + pSMBr->ByteCount +
2309 (char *)&pSMBr->ByteCount;
2312 data_offset = le32_to_cpu(pSMBr->DataOffset);
2313 data_count = le32_to_cpu(pSMBr->DataCount);
2314 parm_offset = le32_to_cpu(pSMBr->ParameterOffset);
2315 parm_count = le32_to_cpu(pSMBr->ParameterCount);
2317 *ppparm = (char *)&pSMBr->hdr.Protocol + parm_offset;
2318 *ppdata = (char *)&pSMBr->hdr.Protocol + data_offset;
2320 /* should we also check that parm and data areas do not overlap? */
2321 if(*ppparm > end_of_smb) {
2322 cFYI(1,("parms start after end of smb"));
2324 } else if(parm_count + *ppparm > end_of_smb) {
2325 cFYI(1,("parm end after end of smb"));
2327 } else if(*ppdata > end_of_smb) {
2328 cFYI(1,("data starts after end of smb"));
2330 } else if(data_count + *ppdata > end_of_smb) {
2331 cFYI(1,("data %p + count %d (%p) ends after end of smb %p start %p",
2332 *ppdata, data_count, (data_count + *ppdata), end_of_smb, pSMBr)); /* BB FIXME */
2334 } else if(parm_count + data_count > pSMBr->ByteCount) {
2335 cFYI(1,("parm count and data count larger than SMB"));
2342 CIFSSMBQueryReparseLinkInfo(const int xid, struct cifsTconInfo *tcon,
2343 const unsigned char *searchName,
2344 char *symlinkinfo, const int buflen,__u16 fid,
2345 const struct nls_table *nls_codepage)
2350 struct smb_com_transaction_ioctl_req * pSMB;
2351 struct smb_com_transaction_ioctl_rsp * pSMBr;
2353 cFYI(1, ("In Windows reparse style QueryLink for path %s", searchName));
2354 rc = smb_init(SMB_COM_NT_TRANSACT, 23, tcon, (void **) &pSMB,
2359 pSMB->TotalParameterCount = 0 ;
2360 pSMB->TotalDataCount = 0;
2361 pSMB->MaxParameterCount = cpu_to_le32(2);
2362 /* BB find exact data count max from sess structure BB */
2363 pSMB->MaxDataCount = cpu_to_le32((tcon->ses->server->maxBuf -
2364 MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
2365 pSMB->MaxSetupCount = 4;
2367 pSMB->ParameterOffset = 0;
2368 pSMB->DataCount = 0;
2369 pSMB->DataOffset = 0;
2370 pSMB->SetupCount = 4;
2371 pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_IOCTL);
2372 pSMB->ParameterCount = pSMB->TotalParameterCount;
2373 pSMB->FunctionCode = cpu_to_le32(FSCTL_GET_REPARSE_POINT);
2374 pSMB->IsFsctl = 1; /* FSCTL */
2375 pSMB->IsRootFlag = 0;
2376 pSMB->Fid = fid; /* file handle always le */
2377 pSMB->ByteCount = 0;
2379 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2380 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2382 cFYI(1, ("Send error in QueryReparseLinkInfo = %d", rc));
2383 } else { /* decode response */
2384 __u32 data_offset = le32_to_cpu(pSMBr->DataOffset);
2385 __u32 data_count = le32_to_cpu(pSMBr->DataCount);
2386 if ((pSMBr->ByteCount < 2) || (data_offset > 512))
2387 /* BB also check enough total bytes returned */
2388 rc = -EIO; /* bad smb */
2390 if(data_count && (data_count < 2048)) {
2391 char * end_of_smb = 2 /* sizeof byte count */ +
2393 (char *)&pSMBr->ByteCount;
2395 struct reparse_data * reparse_buf = (struct reparse_data *)
2396 ((char *)&pSMBr->hdr.Protocol + data_offset);
2397 if((char*)reparse_buf >= end_of_smb) {
2401 if((reparse_buf->LinkNamesBuf +
2402 reparse_buf->TargetNameOffset +
2403 reparse_buf->TargetNameLen) >
2405 cFYI(1,("reparse buf extended beyond SMB"));
2410 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
2411 name_len = UniStrnlen((wchar_t *)
2412 (reparse_buf->LinkNamesBuf +
2413 reparse_buf->TargetNameOffset),
2414 min(buflen/2, reparse_buf->TargetNameLen / 2));
2415 cifs_strfromUCS_le(symlinkinfo,
2416 (__le16 *) (reparse_buf->LinkNamesBuf +
2417 reparse_buf->TargetNameOffset),
2418 name_len, nls_codepage);
2419 } else { /* ASCII names */
2420 strncpy(symlinkinfo,reparse_buf->LinkNamesBuf +
2421 reparse_buf->TargetNameOffset,
2422 min_t(const int, buflen, reparse_buf->TargetNameLen));
2426 cFYI(1,("Invalid return data count on get reparse info ioctl"));
2428 symlinkinfo[buflen] = 0; /* just in case so the caller
2429 does not go off the end of the buffer */
2430 cFYI(1,("readlink result - %s",symlinkinfo));
2434 cifs_buf_release(pSMB);
2436 /* Note: On -EAGAIN error only caller can retry on handle based calls
2437 since file handle passed in no longer valid */
2442 #ifdef CONFIG_CIFS_POSIX
2444 /*Convert an Access Control Entry from wire format to local POSIX xattr format*/
2445 static void cifs_convert_ace(posix_acl_xattr_entry * ace, struct cifs_posix_ace * cifs_ace)
2447 /* u8 cifs fields do not need le conversion */
2448 ace->e_perm = cpu_to_le16(cifs_ace->cifs_e_perm);
2449 ace->e_tag = cpu_to_le16(cifs_ace->cifs_e_tag);
2450 ace->e_id = cpu_to_le32(le64_to_cpu(cifs_ace->cifs_uid));
2451 /* cFYI(1,("perm %d tag %d id %d",ace->e_perm,ace->e_tag,ace->e_id)); */
2456 /* Convert ACL from CIFS POSIX wire format to local Linux POSIX ACL xattr */
2457 static int cifs_copy_posix_acl(char * trgt,char * src, const int buflen,
2458 const int acl_type,const int size_of_data_area)
2463 struct cifs_posix_ace * pACE;
2464 struct cifs_posix_acl * cifs_acl = (struct cifs_posix_acl *)src;
2465 posix_acl_xattr_header * local_acl = (posix_acl_xattr_header *)trgt;
2467 if (le16_to_cpu(cifs_acl->version) != CIFS_ACL_VERSION)
2470 if(acl_type & ACL_TYPE_ACCESS) {
2471 count = le16_to_cpu(cifs_acl->access_entry_count);
2472 pACE = &cifs_acl->ace_array[0];
2473 size = sizeof(struct cifs_posix_acl);
2474 size += sizeof(struct cifs_posix_ace) * count;
2475 /* check if we would go beyond end of SMB */
2476 if(size_of_data_area < size) {
2477 cFYI(1,("bad CIFS POSIX ACL size %d vs. %d",size_of_data_area,size));
2480 } else if(acl_type & ACL_TYPE_DEFAULT) {
2481 count = le16_to_cpu(cifs_acl->access_entry_count);
2482 size = sizeof(struct cifs_posix_acl);
2483 size += sizeof(struct cifs_posix_ace) * count;
2484 /* skip past access ACEs to get to default ACEs */
2485 pACE = &cifs_acl->ace_array[count];
2486 count = le16_to_cpu(cifs_acl->default_entry_count);
2487 size += sizeof(struct cifs_posix_ace) * count;
2488 /* check if we would go beyond end of SMB */
2489 if(size_of_data_area < size)
2496 size = posix_acl_xattr_size(count);
2497 if((buflen == 0) || (local_acl == NULL)) {
2498 /* used to query ACL EA size */
2499 } else if(size > buflen) {
2501 } else /* buffer big enough */ {
2502 local_acl->a_version = cpu_to_le32(POSIX_ACL_XATTR_VERSION);
2503 for(i = 0;i < count ;i++) {
2504 cifs_convert_ace(&local_acl->a_entries[i],pACE);
2511 static __u16 convert_ace_to_cifs_ace(struct cifs_posix_ace * cifs_ace,
2512 const posix_acl_xattr_entry * local_ace)
2514 __u16 rc = 0; /* 0 = ACL converted ok */
2516 cifs_ace->cifs_e_perm = le16_to_cpu(local_ace->e_perm);
2517 cifs_ace->cifs_e_tag = le16_to_cpu(local_ace->e_tag);
2518 /* BB is there a better way to handle the large uid? */
2519 if(local_ace->e_id == cpu_to_le32(-1)) {
2520 /* Probably no need to le convert -1 on any arch but can not hurt */
2521 cifs_ace->cifs_uid = cpu_to_le64(-1);
2523 cifs_ace->cifs_uid = cpu_to_le64(le32_to_cpu(local_ace->e_id));
2524 /*cFYI(1,("perm %d tag %d id %d",ace->e_perm,ace->e_tag,ace->e_id));*/
2528 /* Convert ACL from local Linux POSIX xattr to CIFS POSIX ACL wire format */
2529 static __u16 ACL_to_cifs_posix(char * parm_data,const char * pACL,const int buflen,
2533 struct cifs_posix_acl * cifs_acl = (struct cifs_posix_acl *)parm_data;
2534 posix_acl_xattr_header * local_acl = (posix_acl_xattr_header *)pACL;
2538 if((buflen == 0) || (pACL == NULL) || (cifs_acl == NULL))
2541 count = posix_acl_xattr_count((size_t)buflen);
2542 cFYI(1,("setting acl with %d entries from buf of length %d and version of %d",
2543 count, buflen, le32_to_cpu(local_acl->a_version)));
2544 if(le32_to_cpu(local_acl->a_version) != 2) {
2545 cFYI(1,("unknown POSIX ACL version %d",
2546 le32_to_cpu(local_acl->a_version)));
2549 cifs_acl->version = cpu_to_le16(1);
2550 if(acl_type == ACL_TYPE_ACCESS)
2551 cifs_acl->access_entry_count = cpu_to_le16(count);
2552 else if(acl_type == ACL_TYPE_DEFAULT)
2553 cifs_acl->default_entry_count = cpu_to_le16(count);
2555 cFYI(1,("unknown ACL type %d",acl_type));
2558 for(i=0;i<count;i++) {
2559 rc = convert_ace_to_cifs_ace(&cifs_acl->ace_array[i],
2560 &local_acl->a_entries[i]);
2562 /* ACE not converted */
2567 rc = (__u16)(count * sizeof(struct cifs_posix_ace));
2568 rc += sizeof(struct cifs_posix_acl);
2569 /* BB add check to make sure ACL does not overflow SMB */
2575 CIFSSMBGetPosixACL(const int xid, struct cifsTconInfo *tcon,
2576 const unsigned char *searchName,
2577 char *acl_inf, const int buflen, const int acl_type,
2578 const struct nls_table *nls_codepage, int remap)
2580 /* SMB_QUERY_POSIX_ACL */
2581 TRANSACTION2_QPI_REQ *pSMB = NULL;
2582 TRANSACTION2_QPI_RSP *pSMBr = NULL;
2586 __u16 params, byte_count;
2588 cFYI(1, ("In GetPosixACL (Unix) for path %s", searchName));
2591 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2596 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2598 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
2599 PATH_MAX, nls_codepage, remap);
2600 name_len++; /* trailing null */
2602 pSMB->FileName[name_len] = 0;
2603 pSMB->FileName[name_len+1] = 0;
2604 } else { /* BB improve the check for buffer overruns BB */
2605 name_len = strnlen(searchName, PATH_MAX);
2606 name_len++; /* trailing null */
2607 strncpy(pSMB->FileName, searchName, name_len);
2610 params = 2 /* level */ + 4 /* rsrvd */ + name_len /* incl null */ ;
2611 pSMB->TotalDataCount = 0;
2612 pSMB->MaxParameterCount = cpu_to_le16(2);
2613 /* BB find exact max data count below from sess structure BB */
2614 pSMB->MaxDataCount = cpu_to_le16(4000);
2615 pSMB->MaxSetupCount = 0;
2619 pSMB->Reserved2 = 0;
2620 pSMB->ParameterOffset = cpu_to_le16(
2621 offsetof(struct smb_com_transaction2_qpi_req ,InformationLevel) - 4);
2622 pSMB->DataCount = 0;
2623 pSMB->DataOffset = 0;
2624 pSMB->SetupCount = 1;
2625 pSMB->Reserved3 = 0;
2626 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
2627 byte_count = params + 1 /* pad */ ;
2628 pSMB->TotalParameterCount = cpu_to_le16(params);
2629 pSMB->ParameterCount = pSMB->TotalParameterCount;
2630 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_POSIX_ACL);
2631 pSMB->Reserved4 = 0;
2632 pSMB->hdr.smb_buf_length += byte_count;
2633 pSMB->ByteCount = cpu_to_le16(byte_count);
2635 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2636 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2637 cifs_stats_inc(&tcon->num_acl_get);
2639 cFYI(1, ("Send error in Query POSIX ACL = %d", rc));
2641 /* decode response */
2643 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
2644 if (rc || (pSMBr->ByteCount < 2))
2645 /* BB also check enough total bytes returned */
2646 rc = -EIO; /* bad smb */
2648 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
2649 __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
2650 rc = cifs_copy_posix_acl(acl_inf,
2651 (char *)&pSMBr->hdr.Protocol+data_offset,
2652 buflen,acl_type,count);
2655 cifs_buf_release(pSMB);
2662 CIFSSMBSetPosixACL(const int xid, struct cifsTconInfo *tcon,
2663 const unsigned char *fileName,
2664 const char *local_acl, const int buflen,
2666 const struct nls_table *nls_codepage, int remap)
2668 struct smb_com_transaction2_spi_req *pSMB = NULL;
2669 struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
2673 int bytes_returned = 0;
2674 __u16 params, byte_count, data_count, param_offset, offset;
2676 cFYI(1, ("In SetPosixACL (Unix) for path %s", fileName));
2678 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2682 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2684 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
2685 PATH_MAX, nls_codepage, remap);
2686 name_len++; /* trailing null */
2688 } else { /* BB improve the check for buffer overruns BB */
2689 name_len = strnlen(fileName, PATH_MAX);
2690 name_len++; /* trailing null */
2691 strncpy(pSMB->FileName, fileName, name_len);
2693 params = 6 + name_len;
2694 pSMB->MaxParameterCount = cpu_to_le16(2);
2695 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB size from sess */
2696 pSMB->MaxSetupCount = 0;
2700 pSMB->Reserved2 = 0;
2701 param_offset = offsetof(struct smb_com_transaction2_spi_req,
2702 InformationLevel) - 4;
2703 offset = param_offset + params;
2704 parm_data = ((char *) &pSMB->hdr.Protocol) + offset;
2705 pSMB->ParameterOffset = cpu_to_le16(param_offset);
2707 /* convert to on the wire format for POSIX ACL */
2708 data_count = ACL_to_cifs_posix(parm_data,local_acl,buflen,acl_type);
2710 if(data_count == 0) {
2712 goto setACLerrorExit;
2714 pSMB->DataOffset = cpu_to_le16(offset);
2715 pSMB->SetupCount = 1;
2716 pSMB->Reserved3 = 0;
2717 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
2718 pSMB->InformationLevel = cpu_to_le16(SMB_SET_POSIX_ACL);
2719 byte_count = 3 /* pad */ + params + data_count;
2720 pSMB->DataCount = cpu_to_le16(data_count);
2721 pSMB->TotalDataCount = pSMB->DataCount;
2722 pSMB->ParameterCount = cpu_to_le16(params);
2723 pSMB->TotalParameterCount = pSMB->ParameterCount;
2724 pSMB->Reserved4 = 0;
2725 pSMB->hdr.smb_buf_length += byte_count;
2726 pSMB->ByteCount = cpu_to_le16(byte_count);
2727 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2728 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2730 cFYI(1, ("Set POSIX ACL returned %d", rc));
2734 cifs_buf_release(pSMB);
2740 /* BB fix tabs in this function FIXME BB */
2742 CIFSGetExtAttr(const int xid, struct cifsTconInfo *tcon,
2743 const int netfid, __u64 * pExtAttrBits, __u64 *pMask)
2746 struct smb_t2_qfi_req *pSMB = NULL;
2747 struct smb_t2_qfi_rsp *pSMBr = NULL;
2749 __u16 params, byte_count;
2751 cFYI(1,("In GetExtAttr"));
2756 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2761 params = 2 /* level */ +2 /* fid */;
2762 pSMB->t2.TotalDataCount = 0;
2763 pSMB->t2.MaxParameterCount = cpu_to_le16(4);
2764 /* BB find exact max data count below from sess structure BB */
2765 pSMB->t2.MaxDataCount = cpu_to_le16(4000);
2766 pSMB->t2.MaxSetupCount = 0;
2767 pSMB->t2.Reserved = 0;
2769 pSMB->t2.Timeout = 0;
2770 pSMB->t2.Reserved2 = 0;
2771 pSMB->t2.ParameterOffset = cpu_to_le16(offsetof(struct smb_t2_qfi_req,
2773 pSMB->t2.DataCount = 0;
2774 pSMB->t2.DataOffset = 0;
2775 pSMB->t2.SetupCount = 1;
2776 pSMB->t2.Reserved3 = 0;
2777 pSMB->t2.SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION);
2778 byte_count = params + 1 /* pad */ ;
2779 pSMB->t2.TotalParameterCount = cpu_to_le16(params);
2780 pSMB->t2.ParameterCount = pSMB->t2.TotalParameterCount;
2781 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_ATTR_FLAGS);
2784 pSMB->hdr.smb_buf_length += byte_count;
2785 pSMB->t2.ByteCount = cpu_to_le16(byte_count);
2787 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2788 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2790 cFYI(1, ("error %d in GetExtAttr", rc));
2792 /* decode response */
2793 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
2794 if (rc || (pSMBr->ByteCount < 2))
2795 /* BB also check enough total bytes returned */
2796 /* If rc should we check for EOPNOSUPP and
2797 disable the srvino flag? or in caller? */
2798 rc = -EIO; /* bad smb */
2800 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
2801 __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
2802 struct file_chattr_info * pfinfo;
2803 /* BB Do we need a cast or hash here ? */
2805 cFYI(1, ("Illegal size ret in GetExtAttr"));
2809 pfinfo = (struct file_chattr_info *)
2810 (data_offset + (char *) &pSMBr->hdr.Protocol);
2811 *pExtAttrBits = le64_to_cpu(pfinfo->mode);
2812 *pMask = le64_to_cpu(pfinfo->mask);
2816 cifs_buf_release(pSMB);
2818 goto GetExtAttrRetry;
2823 #endif /* CONFIG_POSIX */
2826 /* security id for everyone */
2827 static const struct cifs_sid sid_everyone =
2828 {1, 1, {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0}};
2830 static const struct cifs_sid sid_user =
2831 {1, 2 , {0, 0, 0, 0, 0, 5}, {32, 545, 0, 0}};
2833 /* Convert CIFS ACL to POSIX form */
2834 static int parse_sec_desc(struct cifs_sid * psec_desc, int acl_len)
2839 /* Get Security Descriptor (by handle) from remote server for a file or dir */
2841 CIFSSMBGetCIFSACL(const int xid, struct cifsTconInfo *tcon, __u16 fid,
2842 /* BB fix up return info */ char *acl_inf, const int buflen,
2843 const int acl_type /* ACCESS/DEFAULT not sure implication */)
2847 QUERY_SEC_DESC_REQ * pSMB;
2850 cFYI(1, ("GetCifsACL"));
2852 rc = smb_init_ntransact(NT_TRANSACT_QUERY_SECURITY_DESC, 0,
2853 8 /* parm len */, tcon, (void **) &pSMB);
2857 pSMB->MaxParameterCount = cpu_to_le32(4);
2858 /* BB TEST with big acls that might need to be e.g. larger than 16K */
2859 pSMB->MaxSetupCount = 0;
2860 pSMB->Fid = fid; /* file handle always le */
2861 pSMB->AclFlags = cpu_to_le32(CIFS_ACL_OWNER | CIFS_ACL_GROUP |
2863 pSMB->ByteCount = cpu_to_le16(11); /* 3 bytes pad + 8 bytes parm */
2864 pSMB->hdr.smb_buf_length += 11;
2865 iov[0].iov_base = (char *)pSMB;
2866 iov[0].iov_len = pSMB->hdr.smb_buf_length + 4;
2868 rc = SendReceive2(xid, tcon->ses, iov, 1 /* num iovec */, &buf_type, 0);
2869 cifs_stats_inc(&tcon->num_acl_get);
2871 cFYI(1, ("Send error in QuerySecDesc = %d", rc));
2872 } else { /* decode response */
2873 struct cifs_sid * psec_desc;
2878 struct smb_com_ntransact_rsp * pSMBr;
2880 /* validate_nttransact */
2881 rc = validate_ntransact(iov[0].iov_base, (char **)&parm,
2882 (char **)&psec_desc,
2883 &parm_len, &data_len);
2887 pSMBr = (struct smb_com_ntransact_rsp *)iov[0].iov_base;
2889 cERROR(1,("smb %p parm %p data %p",pSMBr,parm,psec_desc)); /* BB removeme BB */
2891 if (le32_to_cpu(pSMBr->ParameterCount) != 4) {
2892 rc = -EIO; /* bad smb */
2896 /* BB check that data area is minimum length and as big as acl_len */
2898 acl_len = le32_to_cpu(*(__le32 *)parm);
2899 /* BB check if(acl_len > bufsize) */
2901 parse_sec_desc(psec_desc, acl_len);
2904 if(buf_type == CIFS_SMALL_BUFFER)
2905 cifs_small_buf_release(iov[0].iov_base);
2906 else if(buf_type == CIFS_LARGE_BUFFER)
2907 cifs_buf_release(iov[0].iov_base);
2908 /* cifs_small_buf_release(pSMB); */ /* Freed earlier now in SendReceive2 */
2912 /* Legacy Query Path Information call for lookup to old servers such
2914 int SMBQueryInformation(const int xid, struct cifsTconInfo *tcon,
2915 const unsigned char *searchName,
2916 FILE_ALL_INFO * pFinfo,
2917 const struct nls_table *nls_codepage, int remap)
2919 QUERY_INFORMATION_REQ * pSMB;
2920 QUERY_INFORMATION_RSP * pSMBr;
2925 cFYI(1, ("In SMBQPath path %s", searchName));
2927 rc = smb_init(SMB_COM_QUERY_INFORMATION, 0, tcon, (void **) &pSMB,
2932 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2934 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
2935 PATH_MAX, nls_codepage, remap);
2936 name_len++; /* trailing null */
2939 name_len = strnlen(searchName, PATH_MAX);
2940 name_len++; /* trailing null */
2941 strncpy(pSMB->FileName, searchName, name_len);
2943 pSMB->BufferFormat = 0x04;
2944 name_len++; /* account for buffer type byte */
2945 pSMB->hdr.smb_buf_length += (__u16) name_len;
2946 pSMB->ByteCount = cpu_to_le16(name_len);
2948 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2949 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2951 cFYI(1, ("Send error in QueryInfo = %d", rc));
2952 } else if (pFinfo) { /* decode response */
2954 __u32 time = le32_to_cpu(pSMBr->last_write_time);
2955 /* BB FIXME - add time zone adjustment BB */
2956 memset(pFinfo, 0, sizeof(FILE_ALL_INFO));
2959 /* decode time fields */
2960 pFinfo->ChangeTime = cpu_to_le64(cifs_UnixTimeToNT(ts));
2961 pFinfo->LastWriteTime = pFinfo->ChangeTime;
2962 pFinfo->LastAccessTime = 0;
2963 pFinfo->AllocationSize =
2964 cpu_to_le64(le32_to_cpu(pSMBr->size));
2965 pFinfo->EndOfFile = pFinfo->AllocationSize;
2966 pFinfo->Attributes =
2967 cpu_to_le32(le16_to_cpu(pSMBr->attr));
2969 rc = -EIO; /* bad buffer passed in */
2971 cifs_buf_release(pSMB);
2983 CIFSSMBQPathInfo(const int xid, struct cifsTconInfo *tcon,
2984 const unsigned char *searchName,
2985 FILE_ALL_INFO * pFindData,
2986 int legacy /* old style infolevel */,
2987 const struct nls_table *nls_codepage, int remap)
2989 /* level 263 SMB_QUERY_FILE_ALL_INFO */
2990 TRANSACTION2_QPI_REQ *pSMB = NULL;
2991 TRANSACTION2_QPI_RSP *pSMBr = NULL;
2995 __u16 params, byte_count;
2997 /* cFYI(1, ("In QPathInfo path %s", searchName)); */
2999 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3004 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3006 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
3007 PATH_MAX, nls_codepage, remap);
3008 name_len++; /* trailing null */
3010 } else { /* BB improve the check for buffer overruns BB */
3011 name_len = strnlen(searchName, PATH_MAX);
3012 name_len++; /* trailing null */
3013 strncpy(pSMB->FileName, searchName, name_len);
3016 params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */ ;
3017 pSMB->TotalDataCount = 0;
3018 pSMB->MaxParameterCount = cpu_to_le16(2);
3019 pSMB->MaxDataCount = cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
3020 pSMB->MaxSetupCount = 0;
3024 pSMB->Reserved2 = 0;
3025 pSMB->ParameterOffset = cpu_to_le16(offsetof(
3026 struct smb_com_transaction2_qpi_req ,InformationLevel) - 4);
3027 pSMB->DataCount = 0;
3028 pSMB->DataOffset = 0;
3029 pSMB->SetupCount = 1;
3030 pSMB->Reserved3 = 0;
3031 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
3032 byte_count = params + 1 /* pad */ ;
3033 pSMB->TotalParameterCount = cpu_to_le16(params);
3034 pSMB->ParameterCount = pSMB->TotalParameterCount;
3036 pSMB->InformationLevel = cpu_to_le16(SMB_INFO_STANDARD);
3038 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_ALL_INFO);
3039 pSMB->Reserved4 = 0;
3040 pSMB->hdr.smb_buf_length += byte_count;
3041 pSMB->ByteCount = cpu_to_le16(byte_count);
3043 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3044 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3046 cFYI(1, ("Send error in QPathInfo = %d", rc));
3047 } else { /* decode response */
3048 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3050 if (rc) /* BB add auto retry on EOPNOTSUPP? */
3052 else if (!legacy && (pSMBr->ByteCount < 40))
3053 rc = -EIO; /* bad smb */
3054 else if(legacy && (pSMBr->ByteCount < 24))
3055 rc = -EIO; /* 24 or 26 expected but we do not read last field */
3056 else if (pFindData){
3058 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3059 if(legacy) /* we do not read the last field, EAsize, fortunately
3060 since it varies by subdialect and on Set vs. Get, is
3061 two bytes or 4 bytes depending but we don't care here */
3062 size = sizeof(FILE_INFO_STANDARD);
3064 size = sizeof(FILE_ALL_INFO);
3065 memcpy((char *) pFindData,
3066 (char *) &pSMBr->hdr.Protocol +
3071 cifs_buf_release(pSMB);
3073 goto QPathInfoRetry;
3079 CIFSSMBUnixQPathInfo(const int xid, struct cifsTconInfo *tcon,
3080 const unsigned char *searchName,
3081 FILE_UNIX_BASIC_INFO * pFindData,
3082 const struct nls_table *nls_codepage, int remap)
3084 /* SMB_QUERY_FILE_UNIX_BASIC */
3085 TRANSACTION2_QPI_REQ *pSMB = NULL;
3086 TRANSACTION2_QPI_RSP *pSMBr = NULL;
3088 int bytes_returned = 0;
3090 __u16 params, byte_count;
3092 cFYI(1, ("In QPathInfo (Unix) the path %s", searchName));
3094 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3099 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3101 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
3102 PATH_MAX, nls_codepage, remap);
3103 name_len++; /* trailing null */
3105 } else { /* BB improve the check for buffer overruns BB */
3106 name_len = strnlen(searchName, PATH_MAX);
3107 name_len++; /* trailing null */
3108 strncpy(pSMB->FileName, searchName, name_len);
3111 params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */ ;
3112 pSMB->TotalDataCount = 0;
3113 pSMB->MaxParameterCount = cpu_to_le16(2);
3114 /* BB find exact max SMB PDU from sess structure BB */
3115 pSMB->MaxDataCount = cpu_to_le16(4000);
3116 pSMB->MaxSetupCount = 0;
3120 pSMB->Reserved2 = 0;
3121 pSMB->ParameterOffset = cpu_to_le16(offsetof(
3122 struct smb_com_transaction2_qpi_req ,InformationLevel) - 4);
3123 pSMB->DataCount = 0;
3124 pSMB->DataOffset = 0;
3125 pSMB->SetupCount = 1;
3126 pSMB->Reserved3 = 0;
3127 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
3128 byte_count = params + 1 /* pad */ ;
3129 pSMB->TotalParameterCount = cpu_to_le16(params);
3130 pSMB->ParameterCount = pSMB->TotalParameterCount;
3131 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC);
3132 pSMB->Reserved4 = 0;
3133 pSMB->hdr.smb_buf_length += byte_count;
3134 pSMB->ByteCount = cpu_to_le16(byte_count);
3136 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3137 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3139 cFYI(1, ("Send error in QPathInfo = %d", rc));
3140 } else { /* decode response */
3141 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3143 if (rc || (pSMBr->ByteCount < sizeof(FILE_UNIX_BASIC_INFO))) {
3144 rc = -EIO; /* bad smb */
3146 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3147 memcpy((char *) pFindData,
3148 (char *) &pSMBr->hdr.Protocol +
3150 sizeof (FILE_UNIX_BASIC_INFO));
3153 cifs_buf_release(pSMB);
3155 goto UnixQPathInfoRetry;
3160 #if 0 /* function unused at present */
3161 int CIFSFindSingle(const int xid, struct cifsTconInfo *tcon,
3162 const char *searchName, FILE_ALL_INFO * findData,
3163 const struct nls_table *nls_codepage)
3165 /* level 257 SMB_ */
3166 TRANSACTION2_FFIRST_REQ *pSMB = NULL;
3167 TRANSACTION2_FFIRST_RSP *pSMBr = NULL;
3171 __u16 params, byte_count;
3173 cFYI(1, ("In FindUnique"));
3175 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3180 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3182 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName, PATH_MAX
3183 /* find define for this maxpathcomponent */
3185 name_len++; /* trailing null */
3187 } else { /* BB improve the check for buffer overruns BB */
3188 name_len = strnlen(searchName, PATH_MAX);
3189 name_len++; /* trailing null */
3190 strncpy(pSMB->FileName, searchName, name_len);
3193 params = 12 + name_len /* includes null */ ;
3194 pSMB->TotalDataCount = 0; /* no EAs */
3195 pSMB->MaxParameterCount = cpu_to_le16(2);
3196 pSMB->MaxDataCount = cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
3197 pSMB->MaxSetupCount = 0;
3201 pSMB->Reserved2 = 0;
3202 pSMB->ParameterOffset = cpu_to_le16(
3203 offsetof(struct smb_com_transaction2_ffirst_req,InformationLevel) - 4);
3204 pSMB->DataCount = 0;
3205 pSMB->DataOffset = 0;
3206 pSMB->SetupCount = 1; /* one byte, no need to le convert */
3207 pSMB->Reserved3 = 0;
3208 pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_FIRST);
3209 byte_count = params + 1 /* pad */ ;
3210 pSMB->TotalParameterCount = cpu_to_le16(params);
3211 pSMB->ParameterCount = pSMB->TotalParameterCount;
3212 pSMB->SearchAttributes =
3213 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
3215 pSMB->SearchCount = cpu_to_le16(16); /* BB increase */
3216 pSMB->SearchFlags = cpu_to_le16(1);
3217 pSMB->InformationLevel = cpu_to_le16(SMB_FIND_FILE_DIRECTORY_INFO);
3218 pSMB->SearchStorageType = 0; /* BB what should we set this to? BB */
3219 pSMB->hdr.smb_buf_length += byte_count;
3220 pSMB->ByteCount = cpu_to_le16(byte_count);
3222 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3223 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3226 cFYI(1, ("Send error in FindFileDirInfo = %d", rc));
3227 } else { /* decode response */
3228 cifs_stats_inc(&tcon->num_ffirst);
3232 cifs_buf_release(pSMB);
3234 goto findUniqueRetry;
3238 #endif /* end unused (temporarily) function */
3240 /* xid, tcon, searchName and codepage are input parms, rest are returned */
3242 CIFSFindFirst(const int xid, struct cifsTconInfo *tcon,
3243 const char *searchName,
3244 const struct nls_table *nls_codepage,
3246 struct cifs_search_info * psrch_inf, int remap, const char dirsep)
3248 /* level 257 SMB_ */
3249 TRANSACTION2_FFIRST_REQ *pSMB = NULL;
3250 TRANSACTION2_FFIRST_RSP *pSMBr = NULL;
3251 T2_FFIRST_RSP_PARMS * parms;
3253 int bytes_returned = 0;
3255 __u16 params, byte_count;
3257 cFYI(1, ("In FindFirst for %s",searchName));
3260 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3265 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3267 cifsConvertToUCS((__le16 *) pSMB->FileName,searchName,
3268 PATH_MAX, nls_codepage, remap);
3269 /* We can not add the asterik earlier in case
3270 it got remapped to 0xF03A as if it were part of the
3271 directory name instead of a wildcard */
3273 pSMB->FileName[name_len] = dirsep;
3274 pSMB->FileName[name_len+1] = 0;
3275 pSMB->FileName[name_len+2] = '*';
3276 pSMB->FileName[name_len+3] = 0;
3277 name_len += 4; /* now the trailing null */
3278 pSMB->FileName[name_len] = 0; /* null terminate just in case */
3279 pSMB->FileName[name_len+1] = 0;
3281 } else { /* BB add check for overrun of SMB buf BB */
3282 name_len = strnlen(searchName, PATH_MAX);
3283 /* BB fix here and in unicode clause above ie
3284 if(name_len > buffersize-header)
3285 free buffer exit; BB */
3286 strncpy(pSMB->FileName, searchName, name_len);
3287 pSMB->FileName[name_len] = dirsep;
3288 pSMB->FileName[name_len+1] = '*';
3289 pSMB->FileName[name_len+2] = 0;
3293 params = 12 + name_len /* includes null */ ;
3294 pSMB->TotalDataCount = 0; /* no EAs */
3295 pSMB->MaxParameterCount = cpu_to_le16(10);
3296 pSMB->MaxDataCount = cpu_to_le16((tcon->ses->server->maxBuf -
3297 MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
3298 pSMB->MaxSetupCount = 0;
3302 pSMB->Reserved2 = 0;
3303 byte_count = params + 1 /* pad */ ;
3304 pSMB->TotalParameterCount = cpu_to_le16(params);
3305 pSMB->ParameterCount = pSMB->TotalParameterCount;
3306 pSMB->ParameterOffset = cpu_to_le16(
3307 offsetof(struct smb_com_transaction2_ffirst_req, SearchAttributes)
3309 pSMB->DataCount = 0;
3310 pSMB->DataOffset = 0;
3311 pSMB->SetupCount = 1; /* one byte, no need to make endian neutral */
3312 pSMB->Reserved3 = 0;
3313 pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_FIRST);
3314 pSMB->SearchAttributes =
3315 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
3317 pSMB->SearchCount= cpu_to_le16(CIFSMaxBufSize/sizeof(FILE_UNIX_INFO));
3318 pSMB->SearchFlags = cpu_to_le16(CIFS_SEARCH_CLOSE_AT_END |
3319 CIFS_SEARCH_RETURN_RESUME);
3320 pSMB->InformationLevel = cpu_to_le16(psrch_inf->info_level);
3322 /* BB what should we set StorageType to? Does it matter? BB */
3323 pSMB->SearchStorageType = 0;
3324 pSMB->hdr.smb_buf_length += byte_count;
3325 pSMB->ByteCount = cpu_to_le16(byte_count);
3327 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3328 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3329 cifs_stats_inc(&tcon->num_ffirst);
3331 if (rc) {/* BB add logic to retry regular search if Unix search
3332 rejected unexpectedly by server */
3333 /* BB Add code to handle unsupported level rc */
3334 cFYI(1, ("Error in FindFirst = %d", rc));
3336 cifs_buf_release(pSMB);
3338 /* BB eventually could optimize out free and realloc of buf */
3341 goto findFirstRetry;
3342 } else { /* decode response */
3343 /* BB remember to free buffer if error BB */
3344 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3346 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
3347 psrch_inf->unicode = TRUE;
3349 psrch_inf->unicode = FALSE;
3351 psrch_inf->ntwrk_buf_start = (char *)pSMBr;
3352 psrch_inf->smallBuf = 0;
3353 psrch_inf->srch_entries_start =
3354 (char *) &pSMBr->hdr.Protocol +
3355 le16_to_cpu(pSMBr->t2.DataOffset);
3356 parms = (T2_FFIRST_RSP_PARMS *)((char *) &pSMBr->hdr.Protocol +
3357 le16_to_cpu(pSMBr->t2.ParameterOffset));
3359 if(parms->EndofSearch)
3360 psrch_inf->endOfSearch = TRUE;
3362 psrch_inf->endOfSearch = FALSE;
3364 psrch_inf->entries_in_buffer = le16_to_cpu(parms->SearchCount);
3365 psrch_inf->index_of_last_entry = 2 /* skip . and .. */ +
3366 psrch_inf->entries_in_buffer;
3367 *pnetfid = parms->SearchHandle;
3369 cifs_buf_release(pSMB);
3376 int CIFSFindNext(const int xid, struct cifsTconInfo *tcon,
3377 __u16 searchHandle, struct cifs_search_info * psrch_inf)
3379 TRANSACTION2_FNEXT_REQ *pSMB = NULL;
3380 TRANSACTION2_FNEXT_RSP *pSMBr = NULL;
3381 T2_FNEXT_RSP_PARMS * parms;
3382 char *response_data;
3384 int bytes_returned, name_len;
3385 __u16 params, byte_count;
3387 cFYI(1, ("In FindNext"));
3389 if(psrch_inf->endOfSearch == TRUE)
3392 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3397 params = 14; /* includes 2 bytes of null string, converted to LE below */
3399 pSMB->TotalDataCount = 0; /* no EAs */
3400 pSMB->MaxParameterCount = cpu_to_le16(8);
3401 pSMB->MaxDataCount =
3402 cpu_to_le16((tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
3403 pSMB->MaxSetupCount = 0;
3407 pSMB->Reserved2 = 0;
3408 pSMB->ParameterOffset = cpu_to_le16(
3409 offsetof(struct smb_com_transaction2_fnext_req,SearchHandle) - 4);
3410 pSMB->DataCount = 0;
3411 pSMB->DataOffset = 0;
3412 pSMB->SetupCount = 1;
3413 pSMB->Reserved3 = 0;
3414 pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_NEXT);
3415 pSMB->SearchHandle = searchHandle; /* always kept as le */
3417 cpu_to_le16(CIFSMaxBufSize / sizeof (FILE_UNIX_INFO));
3418 /* test for Unix extensions */
3419 /* if (tcon->ses->capabilities & CAP_UNIX) {
3420 pSMB->InformationLevel = cpu_to_le16(SMB_FIND_FILE_UNIX);
3421 psrch_inf->info_level = SMB_FIND_FILE_UNIX;
3423 pSMB->InformationLevel =
3424 cpu_to_le16(SMB_FIND_FILE_DIRECTORY_INFO);
3425 psrch_inf->info_level = SMB_FIND_FILE_DIRECTORY_INFO;
3427 pSMB->InformationLevel = cpu_to_le16(psrch_inf->info_level);
3428 pSMB->ResumeKey = psrch_inf->resume_key;
3430 cpu_to_le16(CIFS_SEARCH_CLOSE_AT_END | CIFS_SEARCH_RETURN_RESUME);
3432 name_len = psrch_inf->resume_name_len;
3434 if(name_len < PATH_MAX) {
3435 memcpy(pSMB->ResumeFileName, psrch_inf->presume_name, name_len);
3436 byte_count += name_len;
3437 /* 14 byte parm len above enough for 2 byte null terminator */
3438 pSMB->ResumeFileName[name_len] = 0;
3439 pSMB->ResumeFileName[name_len+1] = 0;
3442 goto FNext2_err_exit;
3444 byte_count = params + 1 /* pad */ ;
3445 pSMB->TotalParameterCount = cpu_to_le16(params);
3446 pSMB->ParameterCount = pSMB->TotalParameterCount;
3447 pSMB->hdr.smb_buf_length += byte_count;
3448 pSMB->ByteCount = cpu_to_le16(byte_count);
3450 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3451 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3452 cifs_stats_inc(&tcon->num_fnext);
3455 psrch_inf->endOfSearch = TRUE;
3456 rc = 0; /* search probably was closed at end of search above */
3458 cFYI(1, ("FindNext returned = %d", rc));
3459 } else { /* decode response */
3460 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3463 /* BB fixme add lock for file (srch_info) struct here */
3464 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
3465 psrch_inf->unicode = TRUE;
3467 psrch_inf->unicode = FALSE;
3468 response_data = (char *) &pSMBr->hdr.Protocol +
3469 le16_to_cpu(pSMBr->t2.ParameterOffset);
3470 parms = (T2_FNEXT_RSP_PARMS *)response_data;
3471 response_data = (char *)&pSMBr->hdr.Protocol +
3472 le16_to_cpu(pSMBr->t2.DataOffset);
3473 if(psrch_inf->smallBuf)
3474 cifs_small_buf_release(
3475 psrch_inf->ntwrk_buf_start);
3477 cifs_buf_release(psrch_inf->ntwrk_buf_start);
3478 psrch_inf->srch_entries_start = response_data;
3479 psrch_inf->ntwrk_buf_start = (char *)pSMB;
3480 psrch_inf->smallBuf = 0;
3481 if(parms->EndofSearch)
3482 psrch_inf->endOfSearch = TRUE;
3484 psrch_inf->endOfSearch = FALSE;
3486 psrch_inf->entries_in_buffer = le16_to_cpu(parms->SearchCount);
3487 psrch_inf->index_of_last_entry +=
3488 psrch_inf->entries_in_buffer;
3489 /* cFYI(1,("fnxt2 entries in buf %d index_of_last %d",psrch_inf->entries_in_buffer,psrch_inf->index_of_last_entry)); */
3491 /* BB fixme add unlock here */
3496 /* BB On error, should we leave previous search buf (and count and
3497 last entry fields) intact or free the previous one? */
3499 /* Note: On -EAGAIN error only caller can retry on handle based calls
3500 since file handle passed in no longer valid */
3503 cifs_buf_release(pSMB);
3509 CIFSFindClose(const int xid, struct cifsTconInfo *tcon, const __u16 searchHandle)
3512 FINDCLOSE_REQ *pSMB = NULL;
3513 CLOSE_RSP *pSMBr = NULL; /* BB removeme BB */
3516 cFYI(1, ("In CIFSSMBFindClose"));
3517 rc = small_smb_init(SMB_COM_FIND_CLOSE2, 1, tcon, (void **)&pSMB);
3519 /* no sense returning error if session restarted
3520 as file handle has been closed */
3526 pSMBr = (CLOSE_RSP *)pSMB; /* BB removeme BB */
3527 pSMB->FileID = searchHandle;
3528 pSMB->ByteCount = 0;
3529 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3530 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3532 cERROR(1, ("Send error in FindClose = %d", rc));
3534 cifs_stats_inc(&tcon->num_fclose);
3535 cifs_small_buf_release(pSMB);
3537 /* Since session is dead, search handle closed on server already */
3545 CIFSGetSrvInodeNumber(const int xid, struct cifsTconInfo *tcon,
3546 const unsigned char *searchName,
3547 __u64 * inode_number,
3548 const struct nls_table *nls_codepage, int remap)
3551 TRANSACTION2_QPI_REQ *pSMB = NULL;
3552 TRANSACTION2_QPI_RSP *pSMBr = NULL;
3553 int name_len, bytes_returned;
3554 __u16 params, byte_count;
3556 cFYI(1,("In GetSrvInodeNum for %s",searchName));
3560 GetInodeNumberRetry:
3561 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3567 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3569 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
3570 PATH_MAX,nls_codepage, remap);
3571 name_len++; /* trailing null */
3573 } else { /* BB improve the check for buffer overruns BB */
3574 name_len = strnlen(searchName, PATH_MAX);
3575 name_len++; /* trailing null */
3576 strncpy(pSMB->FileName, searchName, name_len);
3579 params = 2 /* level */ + 4 /* rsrvd */ + name_len /* incl null */ ;
3580 pSMB->TotalDataCount = 0;
3581 pSMB->MaxParameterCount = cpu_to_le16(2);
3582 /* BB find exact max data count below from sess structure BB */
3583 pSMB->MaxDataCount = cpu_to_le16(4000);
3584 pSMB->MaxSetupCount = 0;
3588 pSMB->Reserved2 = 0;
3589 pSMB->ParameterOffset = cpu_to_le16(offsetof(
3590 struct smb_com_transaction2_qpi_req ,InformationLevel) - 4);
3591 pSMB->DataCount = 0;
3592 pSMB->DataOffset = 0;
3593 pSMB->SetupCount = 1;
3594 pSMB->Reserved3 = 0;
3595 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
3596 byte_count = params + 1 /* pad */ ;
3597 pSMB->TotalParameterCount = cpu_to_le16(params);
3598 pSMB->ParameterCount = pSMB->TotalParameterCount;
3599 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_INTERNAL_INFO);
3600 pSMB->Reserved4 = 0;
3601 pSMB->hdr.smb_buf_length += byte_count;
3602 pSMB->ByteCount = cpu_to_le16(byte_count);
3604 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3605 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3607 cFYI(1, ("error %d in QueryInternalInfo", rc));
3609 /* decode response */
3610 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3611 if (rc || (pSMBr->ByteCount < 2))
3612 /* BB also check enough total bytes returned */
3613 /* If rc should we check for EOPNOSUPP and
3614 disable the srvino flag? or in caller? */
3615 rc = -EIO; /* bad smb */
3617 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3618 __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
3619 struct file_internal_info * pfinfo;
3620 /* BB Do we need a cast or hash here ? */
3622 cFYI(1, ("Illegal size ret in QryIntrnlInf"));
3624 goto GetInodeNumOut;
3626 pfinfo = (struct file_internal_info *)
3627 (data_offset + (char *) &pSMBr->hdr.Protocol);
3628 *inode_number = pfinfo->UniqueId;
3632 cifs_buf_release(pSMB);
3634 goto GetInodeNumberRetry;
3639 CIFSGetDFSRefer(const int xid, struct cifsSesInfo *ses,
3640 const unsigned char *searchName,
3641 unsigned char **targetUNCs,
3642 unsigned int *number_of_UNC_in_array,
3643 const struct nls_table *nls_codepage, int remap)
3645 /* TRANS2_GET_DFS_REFERRAL */
3646 TRANSACTION2_GET_DFS_REFER_REQ *pSMB = NULL;
3647 TRANSACTION2_GET_DFS_REFER_RSP *pSMBr = NULL;
3648 struct dfs_referral_level_3 * referrals = NULL;
3654 __u16 params, byte_count;
3655 *number_of_UNC_in_array = 0;
3658 cFYI(1, ("In GetDFSRefer the path %s", searchName));
3662 rc = smb_init(SMB_COM_TRANSACTION2, 15, NULL, (void **) &pSMB,
3667 /* server pointer checked in called function,
3668 but should never be null here anyway */
3669 pSMB->hdr.Mid = GetNextMid(ses->server);
3670 pSMB->hdr.Tid = ses->ipc_tid;
3671 pSMB->hdr.Uid = ses->Suid;
3672 if (ses->capabilities & CAP_STATUS32) {
3673 pSMB->hdr.Flags2 |= SMBFLG2_ERR_STATUS;
3675 if (ses->capabilities & CAP_DFS) {
3676 pSMB->hdr.Flags2 |= SMBFLG2_DFS;
3679 if (ses->capabilities & CAP_UNICODE) {
3680 pSMB->hdr.Flags2 |= SMBFLG2_UNICODE;
3682 cifsConvertToUCS((__le16 *) pSMB->RequestFileName,
3683 searchName, PATH_MAX, nls_codepage, remap);
3684 name_len++; /* trailing null */
3686 } else { /* BB improve the check for buffer overruns BB */
3687 name_len = strnlen(searchName, PATH_MAX);
3688 name_len++; /* trailing null */
3689 strncpy(pSMB->RequestFileName, searchName, name_len);
3693 if(ses->server->secMode &
3694 (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
3695 pSMB->hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
3698 pSMB->hdr.Uid = ses->Suid;
3700 params = 2 /* level */ + name_len /*includes null */ ;
3701 pSMB->TotalDataCount = 0;
3702 pSMB->DataCount = 0;
3703 pSMB->DataOffset = 0;
3704 pSMB->MaxParameterCount = 0;
3705 pSMB->MaxDataCount = cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
3706 pSMB->MaxSetupCount = 0;
3710 pSMB->Reserved2 = 0;
3711 pSMB->ParameterOffset = cpu_to_le16(offsetof(
3712 struct smb_com_transaction2_get_dfs_refer_req, MaxReferralLevel) - 4);
3713 pSMB->SetupCount = 1;
3714 pSMB->Reserved3 = 0;
3715 pSMB->SubCommand = cpu_to_le16(TRANS2_GET_DFS_REFERRAL);
3716 byte_count = params + 3 /* pad */ ;
3717 pSMB->ParameterCount = cpu_to_le16(params);
3718 pSMB->TotalParameterCount = pSMB->ParameterCount;
3719 pSMB->MaxReferralLevel = cpu_to_le16(3);
3720 pSMB->hdr.smb_buf_length += byte_count;
3721 pSMB->ByteCount = cpu_to_le16(byte_count);
3723 rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB,
3724 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3726 cFYI(1, ("Send error in GetDFSRefer = %d", rc));
3727 } else { /* decode response */
3728 /* BB Add logic to parse referrals here */
3729 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3731 if (rc || (pSMBr->ByteCount < 17)) /* BB also check enough total bytes returned */
3732 rc = -EIO; /* bad smb */
3734 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3735 __u16 data_count = le16_to_cpu(pSMBr->t2.DataCount);
3738 ("Decoding GetDFSRefer response. BCC: %d Offset %d",
3739 pSMBr->ByteCount, data_offset));
3741 (struct dfs_referral_level_3 *)
3742 (8 /* sizeof start of data block */ +
3744 (char *) &pSMBr->hdr.Protocol);
3745 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",
3746 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)));
3747 /* BB This field is actually two bytes in from start of
3748 data block so we could do safety check that DataBlock
3749 begins at address of pSMBr->NumberOfReferrals */
3750 *number_of_UNC_in_array = le16_to_cpu(pSMBr->NumberOfReferrals);
3752 /* BB Fix below so can return more than one referral */
3753 if(*number_of_UNC_in_array > 1)
3754 *number_of_UNC_in_array = 1;
3756 /* get the length of the strings describing refs */
3758 for(i=0;i<*number_of_UNC_in_array;i++) {
3759 /* make sure that DfsPathOffset not past end */
3760 __u16 offset = le16_to_cpu(referrals->DfsPathOffset);
3761 if (offset > data_count) {
3762 /* if invalid referral, stop here and do
3763 not try to copy any more */
3764 *number_of_UNC_in_array = i;
3767 temp = ((char *)referrals) + offset;
3769 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
3770 name_len += UniStrnlen((wchar_t *)temp,data_count);
3772 name_len += strnlen(temp,data_count);
3775 /* BB add check that referral pointer does not fall off end PDU */
3778 /* BB add check for name_len bigger than bcc */
3780 kmalloc(name_len+1+ (*number_of_UNC_in_array),GFP_KERNEL);
3781 if(*targetUNCs == NULL) {
3785 /* copy the ref strings */
3787 (struct dfs_referral_level_3 *)
3788 (8 /* sizeof data hdr */ +
3790 (char *) &pSMBr->hdr.Protocol);
3792 for(i=0;i<*number_of_UNC_in_array;i++) {
3793 temp = ((char *)referrals) + le16_to_cpu(referrals->DfsPathOffset);
3794 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
3795 cifs_strfromUCS_le(*targetUNCs,
3796 (__le16 *) temp, name_len, nls_codepage);
3798 strncpy(*targetUNCs,temp,name_len);
3800 /* BB update target_uncs pointers */
3810 cifs_buf_release(pSMB);
3818 /* Query File System Info such as free space to old servers such as Win 9x */
3820 SMBOldQFSInfo(const int xid, struct cifsTconInfo *tcon, struct kstatfs *FSData)
3822 /* level 0x01 SMB_QUERY_FILE_SYSTEM_INFO */
3823 TRANSACTION2_QFSI_REQ *pSMB = NULL;
3824 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
3825 FILE_SYSTEM_ALLOC_INFO *response_data;
3827 int bytes_returned = 0;
3828 __u16 params, byte_count;
3830 cFYI(1, ("OldQFSInfo"));
3832 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3836 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3841 params = 2; /* level */
3842 pSMB->TotalDataCount = 0;
3843 pSMB->MaxParameterCount = cpu_to_le16(2);
3844 pSMB->MaxDataCount = cpu_to_le16(1000);
3845 pSMB->MaxSetupCount = 0;
3849 pSMB->Reserved2 = 0;
3850 byte_count = params + 1 /* pad */ ;
3851 pSMB->TotalParameterCount = cpu_to_le16(params);
3852 pSMB->ParameterCount = pSMB->TotalParameterCount;
3853 pSMB->ParameterOffset = cpu_to_le16(offsetof(
3854 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
3855 pSMB->DataCount = 0;
3856 pSMB->DataOffset = 0;
3857 pSMB->SetupCount = 1;
3858 pSMB->Reserved3 = 0;
3859 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
3860 pSMB->InformationLevel = cpu_to_le16(SMB_INFO_ALLOCATION);
3861 pSMB->hdr.smb_buf_length += byte_count;
3862 pSMB->ByteCount = cpu_to_le16(byte_count);
3864 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3865 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3867 cFYI(1, ("Send error in QFSInfo = %d", rc));
3868 } else { /* decode response */
3869 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3871 if (rc || (pSMBr->ByteCount < 18))
3872 rc = -EIO; /* bad smb */
3874 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3875 cFYI(1,("qfsinf resp BCC: %d Offset %d",
3876 pSMBr->ByteCount, data_offset));
3879 (FILE_SYSTEM_ALLOC_INFO *)
3880 (((char *) &pSMBr->hdr.Protocol) + data_offset);
3882 le16_to_cpu(response_data->BytesPerSector) *
3883 le32_to_cpu(response_data->
3884 SectorsPerAllocationUnit);
3886 le32_to_cpu(response_data->TotalAllocationUnits);
3887 FSData->f_bfree = FSData->f_bavail =
3888 le32_to_cpu(response_data->FreeAllocationUnits);
3890 ("Blocks: %lld Free: %lld Block size %ld",
3891 (unsigned long long)FSData->f_blocks,
3892 (unsigned long long)FSData->f_bfree,
3896 cifs_buf_release(pSMB);
3899 goto oldQFSInfoRetry;
3905 CIFSSMBQFSInfo(const int xid, struct cifsTconInfo *tcon, struct kstatfs *FSData)
3907 /* level 0x103 SMB_QUERY_FILE_SYSTEM_INFO */
3908 TRANSACTION2_QFSI_REQ *pSMB = NULL;
3909 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
3910 FILE_SYSTEM_INFO *response_data;
3912 int bytes_returned = 0;
3913 __u16 params, byte_count;
3915 cFYI(1, ("In QFSInfo"));
3917 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3922 params = 2; /* level */
3923 pSMB->TotalDataCount = 0;
3924 pSMB->MaxParameterCount = cpu_to_le16(2);
3925 pSMB->MaxDataCount = cpu_to_le16(1000);
3926 pSMB->MaxSetupCount = 0;
3930 pSMB->Reserved2 = 0;
3931 byte_count = params + 1 /* pad */ ;
3932 pSMB->TotalParameterCount = cpu_to_le16(params);
3933 pSMB->ParameterCount = pSMB->TotalParameterCount;
3934 pSMB->ParameterOffset = cpu_to_le16(offsetof(
3935 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
3936 pSMB->DataCount = 0;
3937 pSMB->DataOffset = 0;
3938 pSMB->SetupCount = 1;
3939 pSMB->Reserved3 = 0;
3940 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
3941 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_SIZE_INFO);
3942 pSMB->hdr.smb_buf_length += byte_count;
3943 pSMB->ByteCount = cpu_to_le16(byte_count);
3945 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3946 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3948 cFYI(1, ("Send error in QFSInfo = %d", rc));
3949 } else { /* decode response */
3950 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3952 if (rc || (pSMBr->ByteCount < 24))
3953 rc = -EIO; /* bad smb */
3955 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3959 *) (((char *) &pSMBr->hdr.Protocol) +
3962 le32_to_cpu(response_data->BytesPerSector) *
3963 le32_to_cpu(response_data->
3964 SectorsPerAllocationUnit);
3966 le64_to_cpu(response_data->TotalAllocationUnits);
3967 FSData->f_bfree = FSData->f_bavail =
3968 le64_to_cpu(response_data->FreeAllocationUnits);
3970 ("Blocks: %lld Free: %lld Block size %ld",
3971 (unsigned long long)FSData->f_blocks,
3972 (unsigned long long)FSData->f_bfree,
3976 cifs_buf_release(pSMB);
3985 CIFSSMBQFSAttributeInfo(const int xid, struct cifsTconInfo *tcon)
3987 /* level 0x105 SMB_QUERY_FILE_SYSTEM_INFO */
3988 TRANSACTION2_QFSI_REQ *pSMB = NULL;
3989 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
3990 FILE_SYSTEM_ATTRIBUTE_INFO *response_data;
3992 int bytes_returned = 0;
3993 __u16 params, byte_count;
3995 cFYI(1, ("In QFSAttributeInfo"));
3997 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4002 params = 2; /* level */
4003 pSMB->TotalDataCount = 0;
4004 pSMB->MaxParameterCount = cpu_to_le16(2);
4005 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
4006 pSMB->MaxSetupCount = 0;
4010 pSMB->Reserved2 = 0;
4011 byte_count = params + 1 /* pad */ ;
4012 pSMB->TotalParameterCount = cpu_to_le16(params);
4013 pSMB->ParameterCount = pSMB->TotalParameterCount;
4014 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4015 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4016 pSMB->DataCount = 0;
4017 pSMB->DataOffset = 0;
4018 pSMB->SetupCount = 1;
4019 pSMB->Reserved3 = 0;
4020 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4021 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_ATTRIBUTE_INFO);
4022 pSMB->hdr.smb_buf_length += byte_count;
4023 pSMB->ByteCount = cpu_to_le16(byte_count);
4025 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4026 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4028 cERROR(1, ("Send error in QFSAttributeInfo = %d", rc));
4029 } else { /* decode response */
4030 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4032 if (rc || (pSMBr->ByteCount < 13)) { /* BB also check enough bytes returned */
4033 rc = -EIO; /* bad smb */
4035 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4037 (FILE_SYSTEM_ATTRIBUTE_INFO
4038 *) (((char *) &pSMBr->hdr.Protocol) +
4040 memcpy(&tcon->fsAttrInfo, response_data,
4041 sizeof (FILE_SYSTEM_ATTRIBUTE_INFO));
4044 cifs_buf_release(pSMB);
4047 goto QFSAttributeRetry;
4053 CIFSSMBQFSDeviceInfo(const int xid, struct cifsTconInfo *tcon)
4055 /* level 0x104 SMB_QUERY_FILE_SYSTEM_INFO */
4056 TRANSACTION2_QFSI_REQ *pSMB = NULL;
4057 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4058 FILE_SYSTEM_DEVICE_INFO *response_data;
4060 int bytes_returned = 0;
4061 __u16 params, byte_count;
4063 cFYI(1, ("In QFSDeviceInfo"));
4065 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4070 params = 2; /* level */
4071 pSMB->TotalDataCount = 0;
4072 pSMB->MaxParameterCount = cpu_to_le16(2);
4073 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
4074 pSMB->MaxSetupCount = 0;
4078 pSMB->Reserved2 = 0;
4079 byte_count = params + 1 /* pad */ ;
4080 pSMB->TotalParameterCount = cpu_to_le16(params);
4081 pSMB->ParameterCount = pSMB->TotalParameterCount;
4082 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4083 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4085 pSMB->DataCount = 0;
4086 pSMB->DataOffset = 0;
4087 pSMB->SetupCount = 1;
4088 pSMB->Reserved3 = 0;
4089 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4090 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_DEVICE_INFO);
4091 pSMB->hdr.smb_buf_length += byte_count;
4092 pSMB->ByteCount = cpu_to_le16(byte_count);
4094 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4095 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4097 cFYI(1, ("Send error in QFSDeviceInfo = %d", rc));
4098 } else { /* decode response */
4099 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4101 if (rc || (pSMBr->ByteCount < sizeof (FILE_SYSTEM_DEVICE_INFO)))
4102 rc = -EIO; /* bad smb */
4104 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4106 (FILE_SYSTEM_DEVICE_INFO *)
4107 (((char *) &pSMBr->hdr.Protocol) +
4109 memcpy(&tcon->fsDevInfo, response_data,
4110 sizeof (FILE_SYSTEM_DEVICE_INFO));
4113 cifs_buf_release(pSMB);
4116 goto QFSDeviceRetry;
4122 CIFSSMBQFSUnixInfo(const int xid, struct cifsTconInfo *tcon)
4124 /* level 0x200 SMB_QUERY_CIFS_UNIX_INFO */
4125 TRANSACTION2_QFSI_REQ *pSMB = NULL;
4126 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4127 FILE_SYSTEM_UNIX_INFO *response_data;
4129 int bytes_returned = 0;
4130 __u16 params, byte_count;
4132 cFYI(1, ("In QFSUnixInfo"));
4134 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4139 params = 2; /* level */
4140 pSMB->TotalDataCount = 0;
4141 pSMB->DataCount = 0;
4142 pSMB->DataOffset = 0;
4143 pSMB->MaxParameterCount = cpu_to_le16(2);
4144 pSMB->MaxDataCount = cpu_to_le16(100); /* BB find exact max SMB PDU from sess structure BB */
4145 pSMB->MaxSetupCount = 0;
4149 pSMB->Reserved2 = 0;
4150 byte_count = params + 1 /* pad */ ;
4151 pSMB->ParameterCount = cpu_to_le16(params);
4152 pSMB->TotalParameterCount = pSMB->ParameterCount;
4153 pSMB->ParameterOffset = cpu_to_le16(offsetof(struct
4154 smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4155 pSMB->SetupCount = 1;
4156 pSMB->Reserved3 = 0;
4157 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4158 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_CIFS_UNIX_INFO);
4159 pSMB->hdr.smb_buf_length += byte_count;
4160 pSMB->ByteCount = cpu_to_le16(byte_count);
4162 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4163 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4165 cERROR(1, ("Send error in QFSUnixInfo = %d", rc));
4166 } else { /* decode response */
4167 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4169 if (rc || (pSMBr->ByteCount < 13)) {
4170 rc = -EIO; /* bad smb */
4172 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4174 (FILE_SYSTEM_UNIX_INFO
4175 *) (((char *) &pSMBr->hdr.Protocol) +
4177 memcpy(&tcon->fsUnixInfo, response_data,
4178 sizeof (FILE_SYSTEM_UNIX_INFO));
4181 cifs_buf_release(pSMB);
4191 CIFSSMBSetFSUnixInfo(const int xid, struct cifsTconInfo *tcon, __u64 cap)
4193 /* level 0x200 SMB_SET_CIFS_UNIX_INFO */
4194 TRANSACTION2_SETFSI_REQ *pSMB = NULL;
4195 TRANSACTION2_SETFSI_RSP *pSMBr = NULL;
4197 int bytes_returned = 0;
4198 __u16 params, param_offset, offset, byte_count;
4200 cFYI(1, ("In SETFSUnixInfo"));
4202 /* BB switch to small buf init to save memory */
4203 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4208 params = 4; /* 2 bytes zero followed by info level. */
4209 pSMB->MaxSetupCount = 0;
4213 pSMB->Reserved2 = 0;
4214 param_offset = offsetof(struct smb_com_transaction2_setfsi_req, FileNum) - 4;
4215 offset = param_offset + params;
4217 pSMB->MaxParameterCount = cpu_to_le16(4);
4218 pSMB->MaxDataCount = cpu_to_le16(100); /* BB find exact max SMB PDU from sess structure BB */
4219 pSMB->SetupCount = 1;
4220 pSMB->Reserved3 = 0;
4221 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FS_INFORMATION);
4222 byte_count = 1 /* pad */ + params + 12;
4224 pSMB->DataCount = cpu_to_le16(12);
4225 pSMB->ParameterCount = cpu_to_le16(params);
4226 pSMB->TotalDataCount = pSMB->DataCount;
4227 pSMB->TotalParameterCount = pSMB->ParameterCount;
4228 pSMB->ParameterOffset = cpu_to_le16(param_offset);
4229 pSMB->DataOffset = cpu_to_le16(offset);
4233 pSMB->InformationLevel = cpu_to_le16(SMB_SET_CIFS_UNIX_INFO);
4236 pSMB->ClientUnixMajor = cpu_to_le16(CIFS_UNIX_MAJOR_VERSION);
4237 pSMB->ClientUnixMinor = cpu_to_le16(CIFS_UNIX_MINOR_VERSION);
4238 pSMB->ClientUnixCap = cpu_to_le64(cap);
4240 pSMB->hdr.smb_buf_length += byte_count;
4241 pSMB->ByteCount = cpu_to_le16(byte_count);
4243 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4244 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4246 cERROR(1, ("Send error in SETFSUnixInfo = %d", rc));
4247 } else { /* decode response */
4248 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4250 rc = -EIO; /* bad smb */
4253 cifs_buf_release(pSMB);
4256 goto SETFSUnixRetry;
4264 CIFSSMBQFSPosixInfo(const int xid, struct cifsTconInfo *tcon,
4265 struct kstatfs *FSData)
4267 /* level 0x201 SMB_QUERY_CIFS_POSIX_INFO */
4268 TRANSACTION2_QFSI_REQ *pSMB = NULL;
4269 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4270 FILE_SYSTEM_POSIX_INFO *response_data;
4272 int bytes_returned = 0;
4273 __u16 params, byte_count;
4275 cFYI(1, ("In QFSPosixInfo"));
4277 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4282 params = 2; /* level */
4283 pSMB->TotalDataCount = 0;
4284 pSMB->DataCount = 0;
4285 pSMB->DataOffset = 0;
4286 pSMB->MaxParameterCount = cpu_to_le16(2);
4287 pSMB->MaxDataCount = cpu_to_le16(100); /* BB find exact max SMB PDU from sess structure BB */
4288 pSMB->MaxSetupCount = 0;
4292 pSMB->Reserved2 = 0;
4293 byte_count = params + 1 /* pad */ ;
4294 pSMB->ParameterCount = cpu_to_le16(params);
4295 pSMB->TotalParameterCount = pSMB->ParameterCount;
4296 pSMB->ParameterOffset = cpu_to_le16(offsetof(struct
4297 smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4298 pSMB->SetupCount = 1;
4299 pSMB->Reserved3 = 0;
4300 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4301 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_POSIX_FS_INFO);
4302 pSMB->hdr.smb_buf_length += byte_count;
4303 pSMB->ByteCount = cpu_to_le16(byte_count);
4305 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4306 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4308 cFYI(1, ("Send error in QFSUnixInfo = %d", rc));
4309 } else { /* decode response */
4310 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4312 if (rc || (pSMBr->ByteCount < 13)) {
4313 rc = -EIO; /* bad smb */
4315 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4317 (FILE_SYSTEM_POSIX_INFO
4318 *) (((char *) &pSMBr->hdr.Protocol) +
4321 le32_to_cpu(response_data->BlockSize);
4323 le64_to_cpu(response_data->TotalBlocks);
4325 le64_to_cpu(response_data->BlocksAvail);
4326 if(response_data->UserBlocksAvail == cpu_to_le64(-1)) {
4327 FSData->f_bavail = FSData->f_bfree;
4330 le64_to_cpu(response_data->UserBlocksAvail);
4332 if(response_data->TotalFileNodes != cpu_to_le64(-1))
4334 le64_to_cpu(response_data->TotalFileNodes);
4335 if(response_data->FreeFileNodes != cpu_to_le64(-1))
4337 le64_to_cpu(response_data->FreeFileNodes);
4340 cifs_buf_release(pSMB);
4349 /* We can not use write of zero bytes trick to
4350 set file size due to need for large file support. Also note that
4351 this SetPathInfo is preferred to SetFileInfo based method in next
4352 routine which is only needed to work around a sharing violation bug
4353 in Samba which this routine can run into */
4356 CIFSSMBSetEOF(const int xid, struct cifsTconInfo *tcon, const char *fileName,
4357 __u64 size, int SetAllocation,
4358 const struct nls_table *nls_codepage, int remap)
4360 struct smb_com_transaction2_spi_req *pSMB = NULL;
4361 struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
4362 struct file_end_of_file_info *parm_data;
4365 int bytes_returned = 0;
4366 __u16 params, byte_count, data_count, param_offset, offset;
4368 cFYI(1, ("In SetEOF"));
4370 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4375 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4377 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
4378 PATH_MAX, nls_codepage, remap);
4379 name_len++; /* trailing null */
4381 } else { /* BB improve the check for buffer overruns BB */
4382 name_len = strnlen(fileName, PATH_MAX);
4383 name_len++; /* trailing null */
4384 strncpy(pSMB->FileName, fileName, name_len);
4386 params = 6 + name_len;
4387 data_count = sizeof (struct file_end_of_file_info);
4388 pSMB->MaxParameterCount = cpu_to_le16(2);
4389 pSMB->MaxDataCount = cpu_to_le16(4100);
4390 pSMB->MaxSetupCount = 0;
4394 pSMB->Reserved2 = 0;
4395 param_offset = offsetof(struct smb_com_transaction2_spi_req,
4396 InformationLevel) - 4;
4397 offset = param_offset + params;
4399 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
4400 pSMB->InformationLevel =
4401 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2);
4403 pSMB->InformationLevel =
4404 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO);
4405 } else /* Set File Size */ {
4406 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
4407 pSMB->InformationLevel =
4408 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO2);
4410 pSMB->InformationLevel =
4411 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO);
4415 (struct file_end_of_file_info *) (((char *) &pSMB->hdr.Protocol) +
4417 pSMB->ParameterOffset = cpu_to_le16(param_offset);
4418 pSMB->DataOffset = cpu_to_le16(offset);
4419 pSMB->SetupCount = 1;
4420 pSMB->Reserved3 = 0;
4421 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
4422 byte_count = 3 /* pad */ + params + data_count;
4423 pSMB->DataCount = cpu_to_le16(data_count);
4424 pSMB->TotalDataCount = pSMB->DataCount;
4425 pSMB->ParameterCount = cpu_to_le16(params);
4426 pSMB->TotalParameterCount = pSMB->ParameterCount;
4427 pSMB->Reserved4 = 0;
4428 pSMB->hdr.smb_buf_length += byte_count;
4429 parm_data->FileSize = cpu_to_le64(size);
4430 pSMB->ByteCount = cpu_to_le16(byte_count);
4431 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4432 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4434 cFYI(1, ("SetPathInfo (file size) returned %d", rc));
4437 cifs_buf_release(pSMB);
4446 CIFSSMBSetFileSize(const int xid, struct cifsTconInfo *tcon, __u64 size,
4447 __u16 fid, __u32 pid_of_opener, int SetAllocation)
4449 struct smb_com_transaction2_sfi_req *pSMB = NULL;
4450 struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
4452 struct file_end_of_file_info *parm_data;
4454 int bytes_returned = 0;
4455 __u16 params, param_offset, offset, byte_count, count;
4457 cFYI(1, ("SetFileSize (via SetFileInfo) %lld",
4459 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
4464 pSMBr = (struct smb_com_transaction2_sfi_rsp *)pSMB;
4466 pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
4467 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));
4470 pSMB->MaxSetupCount = 0;
4474 pSMB->Reserved2 = 0;
4475 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
4476 offset = param_offset + params;
4478 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
4480 count = sizeof(struct file_end_of_file_info);
4481 pSMB->MaxParameterCount = cpu_to_le16(2);
4482 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB PDU from sess */
4483 pSMB->SetupCount = 1;
4484 pSMB->Reserved3 = 0;
4485 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
4486 byte_count = 3 /* pad */ + params + count;
4487 pSMB->DataCount = cpu_to_le16(count);
4488 pSMB->ParameterCount = cpu_to_le16(params);
4489 pSMB->TotalDataCount = pSMB->DataCount;
4490 pSMB->TotalParameterCount = pSMB->ParameterCount;
4491 pSMB->ParameterOffset = cpu_to_le16(param_offset);
4493 (struct file_end_of_file_info *) (((char *) &pSMB->hdr.Protocol) +
4495 pSMB->DataOffset = cpu_to_le16(offset);
4496 parm_data->FileSize = cpu_to_le64(size);
4499 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
4500 pSMB->InformationLevel =
4501 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2);
4503 pSMB->InformationLevel =
4504 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO);
4505 } else /* Set File Size */ {
4506 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
4507 pSMB->InformationLevel =
4508 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO2);
4510 pSMB->InformationLevel =
4511 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO);
4513 pSMB->Reserved4 = 0;
4514 pSMB->hdr.smb_buf_length += byte_count;
4515 pSMB->ByteCount = cpu_to_le16(byte_count);
4516 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4517 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4520 ("Send error in SetFileInfo (SetFileSize) = %d",
4525 cifs_small_buf_release(pSMB);
4527 /* Note: On -EAGAIN error only caller can retry on handle based calls
4528 since file handle passed in no longer valid */
4533 /* Some legacy servers such as NT4 require that the file times be set on
4534 an open handle, rather than by pathname - this is awkward due to
4535 potential access conflicts on the open, but it is unavoidable for these
4536 old servers since the only other choice is to go from 100 nanosecond DCE
4537 time and resort to the original setpathinfo level which takes the ancient
4538 DOS time format with 2 second granularity */
4540 CIFSSMBSetFileTimes(const int xid, struct cifsTconInfo *tcon, const FILE_BASIC_INFO * data,
4543 struct smb_com_transaction2_sfi_req *pSMB = NULL;
4544 struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
4547 int bytes_returned = 0;
4548 __u16 params, param_offset, offset, byte_count, count;
4550 cFYI(1, ("Set Times (via SetFileInfo)"));
4551 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
4556 pSMBr = (struct smb_com_transaction2_sfi_rsp *)pSMB;
4558 /* At this point there is no need to override the current pid
4559 with the pid of the opener, but that could change if we someday
4560 use an existing handle (rather than opening one on the fly) */
4561 /* pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
4562 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));*/
4565 pSMB->MaxSetupCount = 0;
4569 pSMB->Reserved2 = 0;
4570 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
4571 offset = param_offset + params;
4573 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
4575 count = sizeof (FILE_BASIC_INFO);
4576 pSMB->MaxParameterCount = cpu_to_le16(2);
4577 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB PDU from sess */
4578 pSMB->SetupCount = 1;
4579 pSMB->Reserved3 = 0;
4580 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
4581 byte_count = 3 /* pad */ + params + count;
4582 pSMB->DataCount = cpu_to_le16(count);
4583 pSMB->ParameterCount = cpu_to_le16(params);
4584 pSMB->TotalDataCount = pSMB->DataCount;
4585 pSMB->TotalParameterCount = pSMB->ParameterCount;
4586 pSMB->ParameterOffset = cpu_to_le16(param_offset);
4587 pSMB->DataOffset = cpu_to_le16(offset);
4589 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
4590 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO2);
4592 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO);
4593 pSMB->Reserved4 = 0;
4594 pSMB->hdr.smb_buf_length += byte_count;
4595 pSMB->ByteCount = cpu_to_le16(byte_count);
4596 memcpy(data_offset,data,sizeof(FILE_BASIC_INFO));
4597 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4598 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4600 cFYI(1,("Send error in Set Time (SetFileInfo) = %d",rc));
4603 cifs_small_buf_release(pSMB);
4605 /* Note: On -EAGAIN error only caller can retry on handle based calls
4606 since file handle passed in no longer valid */
4613 CIFSSMBSetTimes(const int xid, struct cifsTconInfo *tcon, const char *fileName,
4614 const FILE_BASIC_INFO * data,
4615 const struct nls_table *nls_codepage, int remap)
4617 TRANSACTION2_SPI_REQ *pSMB = NULL;
4618 TRANSACTION2_SPI_RSP *pSMBr = NULL;
4621 int bytes_returned = 0;
4623 __u16 params, param_offset, offset, byte_count, count;
4625 cFYI(1, ("In SetTimes"));
4628 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4633 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4635 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
4636 PATH_MAX, nls_codepage, remap);
4637 name_len++; /* trailing null */
4639 } else { /* BB improve the check for buffer overruns BB */
4640 name_len = strnlen(fileName, PATH_MAX);
4641 name_len++; /* trailing null */
4642 strncpy(pSMB->FileName, fileName, name_len);
4645 params = 6 + name_len;
4646 count = sizeof (FILE_BASIC_INFO);
4647 pSMB->MaxParameterCount = cpu_to_le16(2);
4648 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
4649 pSMB->MaxSetupCount = 0;
4653 pSMB->Reserved2 = 0;
4654 param_offset = offsetof(struct smb_com_transaction2_spi_req,
4655 InformationLevel) - 4;
4656 offset = param_offset + params;
4657 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
4658 pSMB->ParameterOffset = cpu_to_le16(param_offset);
4659 pSMB->DataOffset = cpu_to_le16(offset);
4660 pSMB->SetupCount = 1;
4661 pSMB->Reserved3 = 0;
4662 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
4663 byte_count = 3 /* pad */ + params + count;
4665 pSMB->DataCount = cpu_to_le16(count);
4666 pSMB->ParameterCount = cpu_to_le16(params);
4667 pSMB->TotalDataCount = pSMB->DataCount;
4668 pSMB->TotalParameterCount = pSMB->ParameterCount;
4669 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
4670 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO2);
4672 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO);
4673 pSMB->Reserved4 = 0;
4674 pSMB->hdr.smb_buf_length += byte_count;
4675 memcpy(data_offset, data, sizeof (FILE_BASIC_INFO));
4676 pSMB->ByteCount = cpu_to_le16(byte_count);
4677 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4678 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4680 cFYI(1, ("SetPathInfo (times) returned %d", rc));
4683 cifs_buf_release(pSMB);
4691 /* Can not be used to set time stamps yet (due to old DOS time format) */
4692 /* Can be used to set attributes */
4693 #if 0 /* Possibly not needed - since it turns out that strangely NT4 has a bug
4694 handling it anyway and NT4 was what we thought it would be needed for
4695 Do not delete it until we prove whether needed for Win9x though */
4697 CIFSSMBSetAttrLegacy(int xid, struct cifsTconInfo *tcon, char *fileName,
4698 __u16 dos_attrs, const struct nls_table *nls_codepage)
4700 SETATTR_REQ *pSMB = NULL;
4701 SETATTR_RSP *pSMBr = NULL;
4706 cFYI(1, ("In SetAttrLegacy"));
4709 rc = smb_init(SMB_COM_SETATTR, 8, tcon, (void **) &pSMB,
4714 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4716 ConvertToUCS((__le16 *) pSMB->fileName, fileName,
4717 PATH_MAX, nls_codepage);
4718 name_len++; /* trailing null */
4720 } else { /* BB improve the check for buffer overruns BB */
4721 name_len = strnlen(fileName, PATH_MAX);
4722 name_len++; /* trailing null */
4723 strncpy(pSMB->fileName, fileName, name_len);
4725 pSMB->attr = cpu_to_le16(dos_attrs);
4726 pSMB->BufferFormat = 0x04;
4727 pSMB->hdr.smb_buf_length += name_len + 1;
4728 pSMB->ByteCount = cpu_to_le16(name_len + 1);
4729 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4730 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4732 cFYI(1, ("Error in LegacySetAttr = %d", rc));
4735 cifs_buf_release(pSMB);
4738 goto SetAttrLgcyRetry;
4742 #endif /* temporarily unneeded SetAttr legacy function */
4745 CIFSSMBUnixSetPerms(const int xid, struct cifsTconInfo *tcon,
4746 char *fileName, __u64 mode, __u64 uid, __u64 gid,
4747 dev_t device, const struct nls_table *nls_codepage,
4750 TRANSACTION2_SPI_REQ *pSMB = NULL;
4751 TRANSACTION2_SPI_RSP *pSMBr = NULL;
4754 int bytes_returned = 0;
4755 FILE_UNIX_BASIC_INFO *data_offset;
4756 __u16 params, param_offset, offset, count, byte_count;
4758 cFYI(1, ("In SetUID/GID/Mode"));
4760 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4765 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4767 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
4768 PATH_MAX, nls_codepage, remap);
4769 name_len++; /* trailing null */
4771 } else { /* BB improve the check for buffer overruns BB */
4772 name_len = strnlen(fileName, PATH_MAX);
4773 name_len++; /* trailing null */
4774 strncpy(pSMB->FileName, fileName, name_len);
4777 params = 6 + name_len;
4778 count = sizeof (FILE_UNIX_BASIC_INFO);
4779 pSMB->MaxParameterCount = cpu_to_le16(2);
4780 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
4781 pSMB->MaxSetupCount = 0;
4785 pSMB->Reserved2 = 0;
4786 param_offset = offsetof(struct smb_com_transaction2_spi_req,
4787 InformationLevel) - 4;
4788 offset = param_offset + params;
4790 (FILE_UNIX_BASIC_INFO *) ((char *) &pSMB->hdr.Protocol +
4792 memset(data_offset, 0, count);
4793 pSMB->DataOffset = cpu_to_le16(offset);
4794 pSMB->ParameterOffset = cpu_to_le16(param_offset);
4795 pSMB->SetupCount = 1;
4796 pSMB->Reserved3 = 0;
4797 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
4798 byte_count = 3 /* pad */ + params + count;
4799 pSMB->ParameterCount = cpu_to_le16(params);
4800 pSMB->DataCount = cpu_to_le16(count);
4801 pSMB->TotalParameterCount = pSMB->ParameterCount;
4802 pSMB->TotalDataCount = pSMB->DataCount;
4803 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_BASIC);
4804 pSMB->Reserved4 = 0;
4805 pSMB->hdr.smb_buf_length += byte_count;
4806 data_offset->Uid = cpu_to_le64(uid);
4807 data_offset->Gid = cpu_to_le64(gid);
4808 /* better to leave device as zero when it is */
4809 data_offset->DevMajor = cpu_to_le64(MAJOR(device));
4810 data_offset->DevMinor = cpu_to_le64(MINOR(device));
4811 data_offset->Permissions = cpu_to_le64(mode);
4814 data_offset->Type = cpu_to_le32(UNIX_FILE);
4815 else if(S_ISDIR(mode))
4816 data_offset->Type = cpu_to_le32(UNIX_DIR);
4817 else if(S_ISLNK(mode))
4818 data_offset->Type = cpu_to_le32(UNIX_SYMLINK);
4819 else if(S_ISCHR(mode))
4820 data_offset->Type = cpu_to_le32(UNIX_CHARDEV);
4821 else if(S_ISBLK(mode))
4822 data_offset->Type = cpu_to_le32(UNIX_BLOCKDEV);
4823 else if(S_ISFIFO(mode))
4824 data_offset->Type = cpu_to_le32(UNIX_FIFO);
4825 else if(S_ISSOCK(mode))
4826 data_offset->Type = cpu_to_le32(UNIX_SOCKET);
4829 pSMB->ByteCount = cpu_to_le16(byte_count);
4830 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4831 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4833 cFYI(1, ("SetPathInfo (perms) returned %d", rc));
4837 cifs_buf_release(pSMB);
4843 int CIFSSMBNotify(const int xid, struct cifsTconInfo *tcon,
4844 const int notify_subdirs, const __u16 netfid,
4845 __u32 filter, struct file * pfile, int multishot,
4846 const struct nls_table *nls_codepage)
4849 struct smb_com_transaction_change_notify_req * pSMB = NULL;
4850 struct smb_com_ntransaction_change_notify_rsp * pSMBr = NULL;
4851 struct dir_notify_req *dnotify_req;
4854 cFYI(1, ("In CIFSSMBNotify for file handle %d",(int)netfid));
4855 rc = smb_init(SMB_COM_NT_TRANSACT, 23, tcon, (void **) &pSMB,
4860 pSMB->TotalParameterCount = 0 ;
4861 pSMB->TotalDataCount = 0;
4862 pSMB->MaxParameterCount = cpu_to_le32(2);
4863 /* BB find exact data count max from sess structure BB */
4864 pSMB->MaxDataCount = 0; /* same in little endian or be */
4865 /* BB VERIFY verify which is correct for above BB */
4866 pSMB->MaxDataCount = cpu_to_le32((tcon->ses->server->maxBuf -
4867 MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
4869 pSMB->MaxSetupCount = 4;
4871 pSMB->ParameterOffset = 0;
4872 pSMB->DataCount = 0;
4873 pSMB->DataOffset = 0;
4874 pSMB->SetupCount = 4; /* single byte does not need le conversion */
4875 pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_NOTIFY_CHANGE);
4876 pSMB->ParameterCount = pSMB->TotalParameterCount;
4878 pSMB->WatchTree = 1; /* one byte - no le conversion needed */
4879 pSMB->Reserved2 = 0;
4880 pSMB->CompletionFilter = cpu_to_le32(filter);
4881 pSMB->Fid = netfid; /* file handle always le */
4882 pSMB->ByteCount = 0;
4884 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4885 (struct smb_hdr *) pSMBr, &bytes_returned, -1);
4887 cFYI(1, ("Error in Notify = %d", rc));
4889 /* Add file to outstanding requests */
4890 /* BB change to kmem cache alloc */
4891 dnotify_req = kmalloc(
4892 sizeof(struct dir_notify_req),
4895 dnotify_req->Pid = pSMB->hdr.Pid;
4896 dnotify_req->PidHigh = pSMB->hdr.PidHigh;
4897 dnotify_req->Mid = pSMB->hdr.Mid;
4898 dnotify_req->Tid = pSMB->hdr.Tid;
4899 dnotify_req->Uid = pSMB->hdr.Uid;
4900 dnotify_req->netfid = netfid;
4901 dnotify_req->pfile = pfile;
4902 dnotify_req->filter = filter;
4903 dnotify_req->multishot = multishot;
4904 spin_lock(&GlobalMid_Lock);
4905 list_add_tail(&dnotify_req->lhead,
4906 &GlobalDnotifyReqList);
4907 spin_unlock(&GlobalMid_Lock);
4911 cifs_buf_release(pSMB);
4914 #ifdef CONFIG_CIFS_XATTR
4916 CIFSSMBQAllEAs(const int xid, struct cifsTconInfo *tcon,
4917 const unsigned char *searchName,
4918 char * EAData, size_t buf_size,
4919 const struct nls_table *nls_codepage, int remap)
4921 /* BB assumes one setup word */
4922 TRANSACTION2_QPI_REQ *pSMB = NULL;
4923 TRANSACTION2_QPI_RSP *pSMBr = NULL;
4927 struct fea * temp_fea;
4929 __u16 params, byte_count;
4931 cFYI(1, ("In Query All EAs path %s", searchName));
4933 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4938 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4940 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
4941 PATH_MAX, nls_codepage, remap);
4942 name_len++; /* trailing null */
4944 } else { /* BB improve the check for buffer overruns BB */
4945 name_len = strnlen(searchName, PATH_MAX);
4946 name_len++; /* trailing null */
4947 strncpy(pSMB->FileName, searchName, name_len);
4950 params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */ ;
4951 pSMB->TotalDataCount = 0;
4952 pSMB->MaxParameterCount = cpu_to_le16(2);
4953 pSMB->MaxDataCount = cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
4954 pSMB->MaxSetupCount = 0;
4958 pSMB->Reserved2 = 0;
4959 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4960 struct smb_com_transaction2_qpi_req ,InformationLevel) - 4);
4961 pSMB->DataCount = 0;
4962 pSMB->DataOffset = 0;
4963 pSMB->SetupCount = 1;
4964 pSMB->Reserved3 = 0;
4965 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
4966 byte_count = params + 1 /* pad */ ;
4967 pSMB->TotalParameterCount = cpu_to_le16(params);
4968 pSMB->ParameterCount = pSMB->TotalParameterCount;
4969 pSMB->InformationLevel = cpu_to_le16(SMB_INFO_QUERY_ALL_EAS);
4970 pSMB->Reserved4 = 0;
4971 pSMB->hdr.smb_buf_length += byte_count;
4972 pSMB->ByteCount = cpu_to_le16(byte_count);
4974 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4975 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4977 cFYI(1, ("Send error in QueryAllEAs = %d", rc));
4978 } else { /* decode response */
4979 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4981 /* BB also check enough total bytes returned */
4982 /* BB we need to improve the validity checking
4983 of these trans2 responses */
4984 if (rc || (pSMBr->ByteCount < 4))
4985 rc = -EIO; /* bad smb */
4986 /* else if (pFindData){
4987 memcpy((char *) pFindData,
4988 (char *) &pSMBr->hdr.Protocol +
4991 /* check that length of list is not more than bcc */
4992 /* check that each entry does not go beyond length
4994 /* check that each element of each entry does not
4995 go beyond end of list */
4996 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4997 struct fealist * ea_response_data;
4999 /* validate_trans2_offsets() */
5000 /* BB to check if(start of smb + data_offset > &bcc+ bcc)*/
5001 ea_response_data = (struct fealist *)
5002 (((char *) &pSMBr->hdr.Protocol) +
5004 name_len = le32_to_cpu(ea_response_data->list_len);
5005 cFYI(1,("ea length %d", name_len));
5007 /* returned EA size zeroed at top of function */
5008 cFYI(1,("empty EA list returned from server"));
5010 /* account for ea list len */
5012 temp_fea = ea_response_data->list;
5013 temp_ptr = (char *)temp_fea;
5014 while(name_len > 0) {
5018 rc += temp_fea->name_len;
5019 /* account for prefix user. and trailing null */
5021 if(rc<(int)buf_size) {
5022 memcpy(EAData,"user.",5);
5024 memcpy(EAData,temp_ptr,temp_fea->name_len);
5025 EAData+=temp_fea->name_len;
5026 /* null terminate name */
5028 EAData = EAData + 1;
5029 } else if(buf_size == 0) {
5030 /* skip copy - calc size only */
5032 /* stop before overrun buffer */
5036 name_len -= temp_fea->name_len;
5037 temp_ptr += temp_fea->name_len;
5038 /* account for trailing null */
5041 value_len = le16_to_cpu(temp_fea->value_len);
5042 name_len -= value_len;
5043 temp_ptr += value_len;
5044 /* BB check that temp_ptr is still within smb BB*/
5045 /* no trailing null to account for in value len */
5046 /* go on to next EA */
5047 temp_fea = (struct fea *)temp_ptr;
5053 cifs_buf_release(pSMB);
5060 ssize_t CIFSSMBQueryEA(const int xid,struct cifsTconInfo * tcon,
5061 const unsigned char * searchName,const unsigned char * ea_name,
5062 unsigned char * ea_value, size_t buf_size,
5063 const struct nls_table *nls_codepage, int remap)
5065 TRANSACTION2_QPI_REQ *pSMB = NULL;
5066 TRANSACTION2_QPI_RSP *pSMBr = NULL;
5070 struct fea * temp_fea;
5072 __u16 params, byte_count;
5074 cFYI(1, ("In Query EA path %s", searchName));
5076 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5081 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5083 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
5084 PATH_MAX, nls_codepage, remap);
5085 name_len++; /* trailing null */
5087 } else { /* BB improve the check for buffer overruns BB */
5088 name_len = strnlen(searchName, PATH_MAX);
5089 name_len++; /* trailing null */
5090 strncpy(pSMB->FileName, searchName, name_len);
5093 params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */ ;
5094 pSMB->TotalDataCount = 0;
5095 pSMB->MaxParameterCount = cpu_to_le16(2);
5096 pSMB->MaxDataCount = cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
5097 pSMB->MaxSetupCount = 0;
5101 pSMB->Reserved2 = 0;
5102 pSMB->ParameterOffset = cpu_to_le16(offsetof(
5103 struct smb_com_transaction2_qpi_req ,InformationLevel) - 4);
5104 pSMB->DataCount = 0;
5105 pSMB->DataOffset = 0;
5106 pSMB->SetupCount = 1;
5107 pSMB->Reserved3 = 0;
5108 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
5109 byte_count = params + 1 /* pad */ ;
5110 pSMB->TotalParameterCount = cpu_to_le16(params);
5111 pSMB->ParameterCount = pSMB->TotalParameterCount;
5112 pSMB->InformationLevel = cpu_to_le16(SMB_INFO_QUERY_ALL_EAS);
5113 pSMB->Reserved4 = 0;
5114 pSMB->hdr.smb_buf_length += byte_count;
5115 pSMB->ByteCount = cpu_to_le16(byte_count);
5117 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5118 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5120 cFYI(1, ("Send error in Query EA = %d", rc));
5121 } else { /* decode response */
5122 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
5124 /* BB also check enough total bytes returned */
5125 /* BB we need to improve the validity checking
5126 of these trans2 responses */
5127 if (rc || (pSMBr->ByteCount < 4))
5128 rc = -EIO; /* bad smb */
5129 /* else if (pFindData){
5130 memcpy((char *) pFindData,
5131 (char *) &pSMBr->hdr.Protocol +
5134 /* check that length of list is not more than bcc */
5135 /* check that each entry does not go beyond length
5137 /* check that each element of each entry does not
5138 go beyond end of list */
5139 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
5140 struct fealist * ea_response_data;
5142 /* validate_trans2_offsets() */
5143 /* BB to check if(start of smb + data_offset > &bcc+ bcc)*/
5144 ea_response_data = (struct fealist *)
5145 (((char *) &pSMBr->hdr.Protocol) +
5147 name_len = le32_to_cpu(ea_response_data->list_len);
5148 cFYI(1,("ea length %d", name_len));
5150 /* returned EA size zeroed at top of function */
5151 cFYI(1,("empty EA list returned from server"));
5153 /* account for ea list len */
5155 temp_fea = ea_response_data->list;
5156 temp_ptr = (char *)temp_fea;
5157 /* loop through checking if we have a matching
5158 name and then return the associated value */
5159 while(name_len > 0) {
5163 value_len = le16_to_cpu(temp_fea->value_len);
5164 /* BB validate that value_len falls within SMB,
5165 even though maximum for name_len is 255 */
5166 if(memcmp(temp_fea->name,ea_name,
5167 temp_fea->name_len) == 0) {
5170 /* account for prefix user. and trailing null */
5171 if(rc<=(int)buf_size) {
5173 temp_fea->name+temp_fea->name_len+1,
5175 /* ea values, unlike ea names,
5176 are not null terminated */
5177 } else if(buf_size == 0) {
5178 /* skip copy - calc size only */
5180 /* stop before overrun buffer */
5185 name_len -= temp_fea->name_len;
5186 temp_ptr += temp_fea->name_len;
5187 /* account for trailing null */
5190 name_len -= value_len;
5191 temp_ptr += value_len;
5192 /* no trailing null to account for in value len */
5193 /* go on to next EA */
5194 temp_fea = (struct fea *)temp_ptr;
5200 cifs_buf_release(pSMB);
5208 CIFSSMBSetEA(const int xid, struct cifsTconInfo *tcon, const char *fileName,
5209 const char * ea_name, const void * ea_value,
5210 const __u16 ea_value_len, const struct nls_table *nls_codepage,
5213 struct smb_com_transaction2_spi_req *pSMB = NULL;
5214 struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
5215 struct fealist *parm_data;
5218 int bytes_returned = 0;
5219 __u16 params, param_offset, byte_count, offset, count;
5221 cFYI(1, ("In SetEA"));
5223 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5228 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5230 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
5231 PATH_MAX, nls_codepage, remap);
5232 name_len++; /* trailing null */
5234 } else { /* BB improve the check for buffer overruns BB */
5235 name_len = strnlen(fileName, PATH_MAX);
5236 name_len++; /* trailing null */
5237 strncpy(pSMB->FileName, fileName, name_len);
5240 params = 6 + name_len;
5242 /* done calculating parms using name_len of file name,
5243 now use name_len to calculate length of ea name
5244 we are going to create in the inode xattrs */
5248 name_len = strnlen(ea_name,255);
5250 count = sizeof(*parm_data) + ea_value_len + name_len + 1;
5251 pSMB->MaxParameterCount = cpu_to_le16(2);
5252 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB size from sess */
5253 pSMB->MaxSetupCount = 0;
5257 pSMB->Reserved2 = 0;
5258 param_offset = offsetof(struct smb_com_transaction2_spi_req,
5259 InformationLevel) - 4;
5260 offset = param_offset + params;
5261 pSMB->InformationLevel =
5262 cpu_to_le16(SMB_SET_FILE_EA);
5265 (struct fealist *) (((char *) &pSMB->hdr.Protocol) +
5267 pSMB->ParameterOffset = cpu_to_le16(param_offset);
5268 pSMB->DataOffset = cpu_to_le16(offset);
5269 pSMB->SetupCount = 1;
5270 pSMB->Reserved3 = 0;
5271 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
5272 byte_count = 3 /* pad */ + params + count;
5273 pSMB->DataCount = cpu_to_le16(count);
5274 parm_data->list_len = cpu_to_le32(count);
5275 parm_data->list[0].EA_flags = 0;
5276 /* we checked above that name len is less than 255 */
5277 parm_data->list[0].name_len = (__u8)name_len;
5278 /* EA names are always ASCII */
5280 strncpy(parm_data->list[0].name,ea_name,name_len);
5281 parm_data->list[0].name[name_len] = 0;
5282 parm_data->list[0].value_len = cpu_to_le16(ea_value_len);
5283 /* caller ensures that ea_value_len is less than 64K but
5284 we need to ensure that it fits within the smb */
5286 /*BB add length check that it would fit in negotiated SMB buffer size BB */
5287 /* if(ea_value_len > buffer_size - 512 (enough for header)) */
5289 memcpy(parm_data->list[0].name+name_len+1,ea_value,ea_value_len);
5291 pSMB->TotalDataCount = pSMB->DataCount;
5292 pSMB->ParameterCount = cpu_to_le16(params);
5293 pSMB->TotalParameterCount = pSMB->ParameterCount;
5294 pSMB->Reserved4 = 0;
5295 pSMB->hdr.smb_buf_length += byte_count;
5296 pSMB->ByteCount = cpu_to_le16(byte_count);
5297 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5298 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5300 cFYI(1, ("SetPathInfo (EA) returned %d", rc));
5303 cifs_buf_release(pSMB);