4 * Copyright (C) International Business Machines Corp., 2002,2010
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 differently for reconnection purposes since we never */
28 /* want to reuse a stale file handle and only the caller knows the file info */
31 #include <linux/kernel.h>
32 #include <linux/vfs.h>
33 #include <linux/slab.h>
34 #include <linux/posix_acl_xattr.h>
35 #include <asm/uaccess.h>
39 #include "cifsproto.h"
40 #include "cifs_unicode.h"
41 #include "cifs_debug.h"
43 #ifdef CONFIG_CIFS_POSIX
48 #ifdef CONFIG_CIFS_WEAK_PW_HASH
49 {LANMAN_PROT, "\2LM1.2X002"},
50 {LANMAN2_PROT, "\2LANMAN2.1"},
51 #endif /* weak password hashing for legacy clients */
52 {CIFS_PROT, "\2NT LM 0.12"},
53 {POSIX_PROT, "\2POSIX 2"},
61 #ifdef CONFIG_CIFS_WEAK_PW_HASH
62 {LANMAN_PROT, "\2LM1.2X002"},
63 {LANMAN2_PROT, "\2LANMAN2.1"},
64 #endif /* weak password hashing for legacy clients */
65 {CIFS_PROT, "\2NT LM 0.12"},
70 /* define the number of elements in the cifs dialect array */
71 #ifdef CONFIG_CIFS_POSIX
72 #ifdef CONFIG_CIFS_WEAK_PW_HASH
73 #define CIFS_NUM_PROT 4
75 #define CIFS_NUM_PROT 2
76 #endif /* CIFS_WEAK_PW_HASH */
78 #ifdef CONFIG_CIFS_WEAK_PW_HASH
79 #define CIFS_NUM_PROT 3
81 #define CIFS_NUM_PROT 1
82 #endif /* CONFIG_CIFS_WEAK_PW_HASH */
83 #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 spin_lock(&cifs_file_list_lock);
95 list_for_each_safe(tmp, tmp1, &pTcon->openFileList) {
96 open_file = list_entry(tmp, struct cifsFileInfo, tlist);
97 open_file->invalidHandle = true;
98 open_file->oplock_break_cancelled = true;
100 spin_unlock(&cifs_file_list_lock);
101 /* BB Add call to invalidate_inodes(sb) for all superblocks mounted
105 /* reconnect the socket, tcon, and smb session if needed */
107 cifs_reconnect_tcon(struct cifsTconInfo *tcon, int smb_command)
110 struct cifsSesInfo *ses;
111 struct TCP_Server_Info *server;
112 struct nls_table *nls_codepage;
115 * SMBs NegProt, SessSetup, uLogoff do not have tcon yet so check for
116 * tcp and smb session status done differently for those three - in the
123 server = ses->server;
126 * only tree disconnect, open, and write, (and ulogoff which does not
127 * have tcon) are allowed as we start force umount
129 if (tcon->tidStatus == CifsExiting) {
130 if (smb_command != SMB_COM_WRITE_ANDX &&
131 smb_command != SMB_COM_OPEN_ANDX &&
132 smb_command != SMB_COM_TREE_DISCONNECT) {
133 cFYI(1, "can not send cmd %d while umounting",
140 * Give demultiplex thread up to 10 seconds to reconnect, should be
141 * greater than cifs socket timeout which is 7 seconds
143 while (server->tcpStatus == CifsNeedReconnect) {
144 wait_event_interruptible_timeout(server->response_q,
145 (server->tcpStatus != CifsNeedReconnect), 10 * HZ);
147 /* are we still trying to reconnect? */
148 if (server->tcpStatus != CifsNeedReconnect)
152 * on "soft" mounts we wait once. Hard mounts keep
153 * retrying until process is killed or server comes
157 cFYI(1, "gave up waiting on reconnect in smb_init");
162 if (!ses->need_reconnect && !tcon->need_reconnect)
165 nls_codepage = load_nls_default();
168 * need to prevent multiple threads trying to simultaneously
169 * reconnect the same SMB session
171 mutex_lock(&ses->session_mutex);
172 rc = cifs_negotiate_protocol(0, ses);
173 if (rc == 0 && ses->need_reconnect)
174 rc = cifs_setup_session(0, ses, nls_codepage);
176 /* do we need to reconnect tcon? */
177 if (rc || !tcon->need_reconnect) {
178 mutex_unlock(&ses->session_mutex);
182 mark_open_files_invalid(tcon);
183 rc = CIFSTCon(0, ses, tcon->treeName, tcon, nls_codepage);
184 mutex_unlock(&ses->session_mutex);
185 cFYI(1, "reconnect tcon rc = %d", rc);
191 * FIXME: check if wsize needs updated due to negotiated smb buffer
194 atomic_inc(&tconInfoReconnectCount);
196 /* tell server Unix caps we support */
197 if (ses->capabilities & CAP_UNIX)
198 reset_cifs_unix_caps(0, tcon, NULL, NULL);
201 * Removed call to reopen open files here. It is safer (and faster) to
202 * reopen files one at a time as needed in read and write.
204 * FIXME: what about file locks? don't we need to reclaim them ASAP?
209 * Check if handle based operation so we know whether we can continue
210 * or not without returning to caller to reset file handle
212 switch (smb_command) {
213 case SMB_COM_READ_ANDX:
214 case SMB_COM_WRITE_ANDX:
216 case SMB_COM_FIND_CLOSE2:
217 case SMB_COM_LOCKING_ANDX:
221 unload_nls(nls_codepage);
225 /* Allocate and return pointer to an SMB request buffer, and set basic
226 SMB information in the SMB header. If the return code is zero, this
227 function must have filled in request_buf pointer */
229 small_smb_init(int smb_command, int wct, struct cifsTconInfo *tcon,
234 rc = cifs_reconnect_tcon(tcon, smb_command);
238 *request_buf = cifs_small_buf_get();
239 if (*request_buf == NULL) {
240 /* BB should we add a retry in here if not a writepage? */
244 header_assemble((struct smb_hdr *) *request_buf, smb_command,
248 cifs_stats_inc(&tcon->num_smbs_sent);
254 small_smb_init_no_tc(const int smb_command, const int wct,
255 struct cifsSesInfo *ses, void **request_buf)
258 struct smb_hdr *buffer;
260 rc = small_smb_init(smb_command, wct, NULL, request_buf);
264 buffer = (struct smb_hdr *)*request_buf;
265 buffer->Mid = GetNextMid(ses->server);
266 if (ses->capabilities & CAP_UNICODE)
267 buffer->Flags2 |= SMBFLG2_UNICODE;
268 if (ses->capabilities & CAP_STATUS32)
269 buffer->Flags2 |= SMBFLG2_ERR_STATUS;
271 /* uid, tid can stay at zero as set in header assemble */
273 /* BB add support for turning on the signing when
274 this function is used after 1st of session setup requests */
279 /* If the return code is zero, this function must fill in request_buf pointer */
281 __smb_init(int smb_command, int wct, struct cifsTconInfo *tcon,
282 void **request_buf, void **response_buf)
284 *request_buf = cifs_buf_get();
285 if (*request_buf == NULL) {
286 /* BB should we add a retry in here if not a writepage? */
289 /* Although the original thought was we needed the response buf for */
290 /* potential retries of smb operations it turns out we can determine */
291 /* from the mid flags when the request buffer can be resent without */
292 /* having to use a second distinct buffer for the response */
294 *response_buf = *request_buf;
296 header_assemble((struct smb_hdr *) *request_buf, smb_command, tcon,
300 cifs_stats_inc(&tcon->num_smbs_sent);
305 /* If the return code is zero, this function must fill in request_buf pointer */
307 smb_init(int smb_command, int wct, struct cifsTconInfo *tcon,
308 void **request_buf, void **response_buf)
312 rc = cifs_reconnect_tcon(tcon, smb_command);
316 return __smb_init(smb_command, wct, tcon, request_buf, response_buf);
320 smb_init_no_reconnect(int smb_command, int wct, struct cifsTconInfo *tcon,
321 void **request_buf, void **response_buf)
323 if (tcon->ses->need_reconnect || tcon->need_reconnect)
326 return __smb_init(smb_command, wct, tcon, request_buf, response_buf);
329 static int validate_t2(struct smb_t2_rsp *pSMB)
331 unsigned int total_size;
333 /* check for plausible wct */
334 if (pSMB->hdr.WordCount < 10)
337 /* check for parm and data offset going beyond end of smb */
338 if (get_unaligned_le16(&pSMB->t2_rsp.ParameterOffset) > 1024 ||
339 get_unaligned_le16(&pSMB->t2_rsp.DataOffset) > 1024)
342 /* check that bcc is at least as big as parms + data */
343 /* check that bcc is less than negotiated smb buffer */
344 total_size = get_unaligned_le16(&pSMB->t2_rsp.ParameterCount);
345 if (total_size >= 512)
348 total_size += get_unaligned_le16(&pSMB->t2_rsp.DataCount);
349 if (total_size > get_bcc(&pSMB->hdr) ||
350 total_size >= CIFSMaxBufSize + MAX_CIFS_HDR_SIZE)
355 cifs_dump_mem("Invalid transact2 SMB: ", (char *)pSMB,
356 sizeof(struct smb_t2_rsp) + 16);
361 CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses)
364 NEGOTIATE_RSP *pSMBr;
368 struct TCP_Server_Info *server;
370 unsigned int secFlags;
373 server = ses->server;
378 rc = smb_init(SMB_COM_NEGOTIATE, 0, NULL /* no tcon yet */ ,
379 (void **) &pSMB, (void **) &pSMBr);
383 /* if any of auth flags (ie not sign or seal) are overriden use them */
384 if (ses->overrideSecFlg & (~(CIFSSEC_MUST_SIGN | CIFSSEC_MUST_SEAL)))
385 secFlags = ses->overrideSecFlg; /* BB FIXME fix sign flags? */
386 else /* if override flags set only sign/seal OR them with global auth */
387 secFlags = global_secflags | ses->overrideSecFlg;
389 cFYI(1, "secFlags 0x%x", secFlags);
391 pSMB->hdr.Mid = GetNextMid(server);
392 pSMB->hdr.Flags2 |= (SMBFLG2_UNICODE | SMBFLG2_ERR_STATUS);
394 if ((secFlags & CIFSSEC_MUST_KRB5) == CIFSSEC_MUST_KRB5)
395 pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC;
396 else if ((secFlags & CIFSSEC_AUTH_MASK) == CIFSSEC_MAY_KRB5) {
397 cFYI(1, "Kerberos only mechanism, enable extended security");
398 pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC;
399 } else if ((secFlags & CIFSSEC_MUST_NTLMSSP) == CIFSSEC_MUST_NTLMSSP)
400 pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC;
401 else if ((secFlags & CIFSSEC_AUTH_MASK) == CIFSSEC_MAY_NTLMSSP) {
402 cFYI(1, "NTLMSSP only mechanism, enable extended security");
403 pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC;
407 for (i = 0; i < CIFS_NUM_PROT; i++) {
408 strncpy(pSMB->DialectsArray+count, protocols[i].name, 16);
409 count += strlen(protocols[i].name) + 1;
410 /* null at end of source and target buffers anyway */
412 pSMB->hdr.smb_buf_length += count;
413 pSMB->ByteCount = cpu_to_le16(count);
415 rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB,
416 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
420 server->dialect = le16_to_cpu(pSMBr->DialectIndex);
421 cFYI(1, "Dialect: %d", server->dialect);
422 /* Check wct = 1 error case */
423 if ((pSMBr->hdr.WordCount < 13) || (server->dialect == BAD_PROT)) {
424 /* core returns wct = 1, but we do not ask for core - otherwise
425 small wct just comes when dialect index is -1 indicating we
426 could not negotiate a common dialect */
429 #ifdef CONFIG_CIFS_WEAK_PW_HASH
430 } else if ((pSMBr->hdr.WordCount == 13)
431 && ((server->dialect == LANMAN_PROT)
432 || (server->dialect == LANMAN2_PROT))) {
434 struct lanman_neg_rsp *rsp = (struct lanman_neg_rsp *)pSMBr;
436 if ((secFlags & CIFSSEC_MAY_LANMAN) ||
437 (secFlags & CIFSSEC_MAY_PLNTXT))
438 server->secType = LANMAN;
440 cERROR(1, "mount failed weak security disabled"
441 " in /proc/fs/cifs/SecurityFlags");
445 server->secMode = (__u8)le16_to_cpu(rsp->SecurityMode);
446 server->maxReq = le16_to_cpu(rsp->MaxMpxCount);
447 server->maxBuf = min((__u32)le16_to_cpu(rsp->MaxBufSize),
448 (__u32)CIFSMaxBufSize + MAX_CIFS_HDR_SIZE);
449 server->max_vcs = le16_to_cpu(rsp->MaxNumberVcs);
450 /* even though we do not use raw we might as well set this
451 accurately, in case we ever find a need for it */
452 if ((le16_to_cpu(rsp->RawMode) & RAW_ENABLE) == RAW_ENABLE) {
453 server->max_rw = 0xFF00;
454 server->capabilities = CAP_MPX_MODE | CAP_RAW_MODE;
456 server->max_rw = 0;/* do not need to use raw anyway */
457 server->capabilities = CAP_MPX_MODE;
459 tmp = (__s16)le16_to_cpu(rsp->ServerTimeZone);
461 /* OS/2 often does not set timezone therefore
462 * we must use server time to calc time zone.
463 * Could deviate slightly from the right zone.
464 * Smallest defined timezone difference is 15 minutes
465 * (i.e. Nepal). Rounding up/down is done to match
468 int val, seconds, remain, result;
469 struct timespec ts, utc;
471 ts = cnvrtDosUnixTm(rsp->SrvTime.Date,
472 rsp->SrvTime.Time, 0);
473 cFYI(1, "SrvTime %d sec since 1970 (utc: %d) diff: %d",
474 (int)ts.tv_sec, (int)utc.tv_sec,
475 (int)(utc.tv_sec - ts.tv_sec));
476 val = (int)(utc.tv_sec - ts.tv_sec);
478 result = (seconds / MIN_TZ_ADJ) * MIN_TZ_ADJ;
479 remain = seconds % MIN_TZ_ADJ;
480 if (remain >= (MIN_TZ_ADJ / 2))
481 result += MIN_TZ_ADJ;
484 server->timeAdj = result;
486 server->timeAdj = (int)tmp;
487 server->timeAdj *= 60; /* also in seconds */
489 cFYI(1, "server->timeAdj: %d seconds", server->timeAdj);
492 /* BB get server time for time conversions and add
493 code to use it and timezone since this is not UTC */
495 if (rsp->EncryptionKeyLength ==
496 cpu_to_le16(CIFS_CRYPTO_KEY_SIZE)) {
497 memcpy(ses->server->cryptkey, rsp->EncryptionKey,
498 CIFS_CRYPTO_KEY_SIZE);
499 } else if (server->secMode & SECMODE_PW_ENCRYPT) {
500 rc = -EIO; /* need cryptkey unless plain text */
504 cFYI(1, "LANMAN negotiated");
505 /* we will not end up setting signing flags - as no signing
506 was in LANMAN and server did not return the flags on */
508 #else /* weak security disabled */
509 } else if (pSMBr->hdr.WordCount == 13) {
510 cERROR(1, "mount failed, cifs module not built "
511 "with CIFS_WEAK_PW_HASH support");
513 #endif /* WEAK_PW_HASH */
515 } else if (pSMBr->hdr.WordCount != 17) {
520 /* else wct == 17 NTLM */
521 server->secMode = pSMBr->SecurityMode;
522 if ((server->secMode & SECMODE_USER) == 0)
523 cFYI(1, "share mode security");
525 if ((server->secMode & SECMODE_PW_ENCRYPT) == 0)
526 #ifdef CONFIG_CIFS_WEAK_PW_HASH
527 if ((secFlags & CIFSSEC_MAY_PLNTXT) == 0)
528 #endif /* CIFS_WEAK_PW_HASH */
529 cERROR(1, "Server requests plain text password"
530 " but client support disabled");
532 if ((secFlags & CIFSSEC_MUST_NTLMV2) == CIFSSEC_MUST_NTLMV2)
533 server->secType = NTLMv2;
534 else if (secFlags & CIFSSEC_MAY_NTLM)
535 server->secType = NTLM;
536 else if (secFlags & CIFSSEC_MAY_NTLMV2)
537 server->secType = NTLMv2;
538 else if (secFlags & CIFSSEC_MAY_KRB5)
539 server->secType = Kerberos;
540 else if (secFlags & CIFSSEC_MAY_NTLMSSP)
541 server->secType = RawNTLMSSP;
542 else if (secFlags & CIFSSEC_MAY_LANMAN)
543 server->secType = LANMAN;
544 /* #ifdef CONFIG_CIFS_EXPERIMENTAL
545 else if (secFlags & CIFSSEC_MAY_PLNTXT)
550 cERROR(1, "Invalid security type");
553 /* else ... any others ...? */
555 /* one byte, so no need to convert this or EncryptionKeyLen from
557 server->maxReq = le16_to_cpu(pSMBr->MaxMpxCount);
558 /* probably no need to store and check maxvcs */
559 server->maxBuf = min(le32_to_cpu(pSMBr->MaxBufferSize),
560 (__u32) CIFSMaxBufSize + MAX_CIFS_HDR_SIZE);
561 server->max_rw = le32_to_cpu(pSMBr->MaxRawSize);
562 cFYI(DBG2, "Max buf = %d", ses->server->maxBuf);
563 server->capabilities = le32_to_cpu(pSMBr->Capabilities);
564 server->timeAdj = (int)(__s16)le16_to_cpu(pSMBr->ServerTimeZone);
565 server->timeAdj *= 60;
566 if (pSMBr->EncryptionKeyLength == CIFS_CRYPTO_KEY_SIZE) {
567 memcpy(ses->server->cryptkey, pSMBr->u.EncryptionKey,
568 CIFS_CRYPTO_KEY_SIZE);
569 } else if ((pSMBr->hdr.Flags2 & SMBFLG2_EXT_SEC)
570 && (pSMBr->EncryptionKeyLength == 0)) {
571 /* decode security blob */
572 } else if (server->secMode & SECMODE_PW_ENCRYPT) {
573 rc = -EIO; /* no crypt key only if plain text pwd */
577 /* BB might be helpful to save off the domain of server here */
579 if ((pSMBr->hdr.Flags2 & SMBFLG2_EXT_SEC) &&
580 (server->capabilities & CAP_EXTENDED_SECURITY)) {
581 count = pSMBr->ByteCount;
586 spin_lock(&cifs_tcp_ses_lock);
587 if (server->srv_count > 1) {
588 spin_unlock(&cifs_tcp_ses_lock);
589 if (memcmp(server->server_GUID,
590 pSMBr->u.extended_response.
592 cFYI(1, "server UID changed");
593 memcpy(server->server_GUID,
594 pSMBr->u.extended_response.GUID,
598 spin_unlock(&cifs_tcp_ses_lock);
599 memcpy(server->server_GUID,
600 pSMBr->u.extended_response.GUID, 16);
604 server->secType = RawNTLMSSP;
606 rc = decode_negTokenInit(pSMBr->u.extended_response.
607 SecurityBlob, count - 16,
613 if (server->secType == Kerberos) {
614 if (!server->sec_kerberos &&
615 !server->sec_mskerberos)
617 } else if (server->secType == RawNTLMSSP) {
618 if (!server->sec_ntlmssp)
624 server->capabilities &= ~CAP_EXTENDED_SECURITY;
626 #ifdef CONFIG_CIFS_WEAK_PW_HASH
629 if ((secFlags & CIFSSEC_MAY_SIGN) == 0) {
630 /* MUST_SIGN already includes the MAY_SIGN FLAG
631 so if this is zero it means that signing is disabled */
632 cFYI(1, "Signing disabled");
633 if (server->secMode & SECMODE_SIGN_REQUIRED) {
634 cERROR(1, "Server requires "
635 "packet signing to be enabled in "
636 "/proc/fs/cifs/SecurityFlags.");
640 ~(SECMODE_SIGN_ENABLED | SECMODE_SIGN_REQUIRED);
641 } else if ((secFlags & CIFSSEC_MUST_SIGN) == CIFSSEC_MUST_SIGN) {
642 /* signing required */
643 cFYI(1, "Must sign - secFlags 0x%x", secFlags);
644 if ((server->secMode &
645 (SECMODE_SIGN_ENABLED | SECMODE_SIGN_REQUIRED)) == 0) {
646 cERROR(1, "signing required but server lacks support");
649 server->secMode |= SECMODE_SIGN_REQUIRED;
651 /* signing optional ie CIFSSEC_MAY_SIGN */
652 if ((server->secMode & SECMODE_SIGN_REQUIRED) == 0)
654 ~(SECMODE_SIGN_ENABLED | SECMODE_SIGN_REQUIRED);
658 cifs_buf_release(pSMB);
660 cFYI(1, "negprot rc %d", rc);
665 CIFSSMBTDis(const int xid, struct cifsTconInfo *tcon)
667 struct smb_hdr *smb_buffer;
670 cFYI(1, "In tree disconnect");
672 /* BB: do we need to check this? These should never be NULL. */
673 if ((tcon->ses == NULL) || (tcon->ses->server == NULL))
677 * No need to return error on this operation if tid invalidated and
678 * closed on server already e.g. due to tcp session crashing. Also,
679 * the tcon is no longer on the list, so no need to take lock before
682 if ((tcon->need_reconnect) || (tcon->ses->need_reconnect))
685 rc = small_smb_init(SMB_COM_TREE_DISCONNECT, 0, tcon,
686 (void **)&smb_buffer);
690 rc = SendReceiveNoRsp(xid, tcon->ses, smb_buffer, 0);
692 cFYI(1, "Tree disconnect failed %d", rc);
694 /* No need to return error on this operation if tid invalidated and
695 closed on server already e.g. due to tcp session crashing */
703 * This is a no-op for now. We're not really interested in the reply, but
704 * rather in the fact that the server sent one and that server->lstrp
707 * FIXME: maybe we should consider checking that the reply matches request?
710 cifs_echo_callback(struct mid_q_entry *mid)
712 struct TCP_Server_Info *server = mid->callback_data;
714 DeleteMidQEntry(mid);
715 atomic_dec(&server->inFlight);
716 wake_up(&server->request_q);
720 CIFSSMBEcho(struct TCP_Server_Info *server)
725 cFYI(1, "In echo request");
727 rc = small_smb_init(SMB_COM_ECHO, 0, NULL, (void **)&smb);
731 /* set up echo request */
732 smb->hdr.Tid = 0xffff;
733 smb->hdr.WordCount = 1;
734 put_unaligned_le16(1, &smb->EchoCount);
735 put_bcc_le(1, &smb->hdr);
737 smb->hdr.smb_buf_length += 3;
739 rc = cifs_call_async(server, (struct smb_hdr *)smb,
740 cifs_echo_callback, server);
742 cFYI(1, "Echo request failed: %d", rc);
744 cifs_small_buf_release(smb);
750 CIFSSMBLogoff(const int xid, struct cifsSesInfo *ses)
752 LOGOFF_ANDX_REQ *pSMB;
755 cFYI(1, "In SMBLogoff for session disconnect");
758 * BB: do we need to check validity of ses and server? They should
759 * always be valid since we have an active reference. If not, that
760 * should probably be a BUG()
762 if (!ses || !ses->server)
765 mutex_lock(&ses->session_mutex);
766 if (ses->need_reconnect)
767 goto session_already_dead; /* no need to send SMBlogoff if uid
768 already closed due to reconnect */
769 rc = small_smb_init(SMB_COM_LOGOFF_ANDX, 2, NULL, (void **)&pSMB);
771 mutex_unlock(&ses->session_mutex);
775 pSMB->hdr.Mid = GetNextMid(ses->server);
777 if (ses->server->secMode &
778 (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
779 pSMB->hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
781 pSMB->hdr.Uid = ses->Suid;
783 pSMB->AndXCommand = 0xFF;
784 rc = SendReceiveNoRsp(xid, ses, (struct smb_hdr *) pSMB, 0);
785 session_already_dead:
786 mutex_unlock(&ses->session_mutex);
788 /* if session dead then we do not need to do ulogoff,
789 since server closed smb session, no sense reporting
797 CIFSPOSIXDelFile(const int xid, struct cifsTconInfo *tcon, const char *fileName,
798 __u16 type, const struct nls_table *nls_codepage, int remap)
800 TRANSACTION2_SPI_REQ *pSMB = NULL;
801 TRANSACTION2_SPI_RSP *pSMBr = NULL;
802 struct unlink_psx_rq *pRqD;
805 int bytes_returned = 0;
806 __u16 params, param_offset, offset, byte_count;
808 cFYI(1, "In POSIX delete");
810 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
815 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
817 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
818 PATH_MAX, nls_codepage, remap);
819 name_len++; /* trailing null */
821 } else { /* BB add path length overrun check */
822 name_len = strnlen(fileName, PATH_MAX);
823 name_len++; /* trailing null */
824 strncpy(pSMB->FileName, fileName, name_len);
827 params = 6 + name_len;
828 pSMB->MaxParameterCount = cpu_to_le16(2);
829 pSMB->MaxDataCount = 0; /* BB double check this with jra */
830 pSMB->MaxSetupCount = 0;
835 param_offset = offsetof(struct smb_com_transaction2_spi_req,
836 InformationLevel) - 4;
837 offset = param_offset + params;
839 /* Setup pointer to Request Data (inode type) */
840 pRqD = (struct unlink_psx_rq *)(((char *)&pSMB->hdr.Protocol) + offset);
841 pRqD->type = cpu_to_le16(type);
842 pSMB->ParameterOffset = cpu_to_le16(param_offset);
843 pSMB->DataOffset = cpu_to_le16(offset);
844 pSMB->SetupCount = 1;
846 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
847 byte_count = 3 /* pad */ + params + sizeof(struct unlink_psx_rq);
849 pSMB->DataCount = cpu_to_le16(sizeof(struct unlink_psx_rq));
850 pSMB->TotalDataCount = cpu_to_le16(sizeof(struct unlink_psx_rq));
851 pSMB->ParameterCount = cpu_to_le16(params);
852 pSMB->TotalParameterCount = pSMB->ParameterCount;
853 pSMB->InformationLevel = cpu_to_le16(SMB_POSIX_UNLINK);
855 pSMB->hdr.smb_buf_length += byte_count;
856 pSMB->ByteCount = cpu_to_le16(byte_count);
857 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
858 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
860 cFYI(1, "Posix delete returned %d", rc);
861 cifs_buf_release(pSMB);
863 cifs_stats_inc(&tcon->num_deletes);
872 CIFSSMBDelFile(const int xid, struct cifsTconInfo *tcon, const char *fileName,
873 const struct nls_table *nls_codepage, int remap)
875 DELETE_FILE_REQ *pSMB = NULL;
876 DELETE_FILE_RSP *pSMBr = NULL;
882 rc = smb_init(SMB_COM_DELETE, 1, tcon, (void **) &pSMB,
887 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
889 cifsConvertToUCS((__le16 *) pSMB->fileName, fileName,
890 PATH_MAX, nls_codepage, remap);
891 name_len++; /* trailing null */
893 } else { /* BB improve check for buffer overruns BB */
894 name_len = strnlen(fileName, PATH_MAX);
895 name_len++; /* trailing null */
896 strncpy(pSMB->fileName, fileName, name_len);
898 pSMB->SearchAttributes =
899 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM);
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_deletes);
907 cFYI(1, "Error in RMFile = %d", rc);
909 cifs_buf_release(pSMB);
917 CIFSSMBRmDir(const int xid, struct cifsTconInfo *tcon, const char *dirName,
918 const struct nls_table *nls_codepage, int remap)
920 DELETE_DIRECTORY_REQ *pSMB = NULL;
921 DELETE_DIRECTORY_RSP *pSMBr = NULL;
926 cFYI(1, "In CIFSSMBRmDir");
928 rc = smb_init(SMB_COM_DELETE_DIRECTORY, 0, tcon, (void **) &pSMB,
933 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
934 name_len = cifsConvertToUCS((__le16 *) pSMB->DirName, dirName,
935 PATH_MAX, nls_codepage, remap);
936 name_len++; /* trailing null */
938 } else { /* BB improve check for buffer overruns BB */
939 name_len = strnlen(dirName, PATH_MAX);
940 name_len++; /* trailing null */
941 strncpy(pSMB->DirName, dirName, name_len);
944 pSMB->BufferFormat = 0x04;
945 pSMB->hdr.smb_buf_length += name_len + 1;
946 pSMB->ByteCount = cpu_to_le16(name_len + 1);
947 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
948 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
949 cifs_stats_inc(&tcon->num_rmdirs);
951 cFYI(1, "Error in RMDir = %d", rc);
953 cifs_buf_release(pSMB);
960 CIFSSMBMkDir(const int xid, struct cifsTconInfo *tcon,
961 const char *name, const struct nls_table *nls_codepage, int remap)
964 CREATE_DIRECTORY_REQ *pSMB = NULL;
965 CREATE_DIRECTORY_RSP *pSMBr = NULL;
969 cFYI(1, "In CIFSSMBMkDir");
971 rc = smb_init(SMB_COM_CREATE_DIRECTORY, 0, tcon, (void **) &pSMB,
976 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
977 name_len = cifsConvertToUCS((__le16 *) pSMB->DirName, name,
978 PATH_MAX, nls_codepage, remap);
979 name_len++; /* trailing null */
981 } else { /* BB improve check for buffer overruns BB */
982 name_len = strnlen(name, PATH_MAX);
983 name_len++; /* trailing null */
984 strncpy(pSMB->DirName, name, name_len);
987 pSMB->BufferFormat = 0x04;
988 pSMB->hdr.smb_buf_length += name_len + 1;
989 pSMB->ByteCount = cpu_to_le16(name_len + 1);
990 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
991 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
992 cifs_stats_inc(&tcon->num_mkdirs);
994 cFYI(1, "Error in Mkdir = %d", rc);
996 cifs_buf_release(pSMB);
1003 CIFSPOSIXCreate(const int xid, struct cifsTconInfo *tcon, __u32 posix_flags,
1004 __u64 mode, __u16 *netfid, FILE_UNIX_BASIC_INFO *pRetData,
1005 __u32 *pOplock, const char *name,
1006 const struct nls_table *nls_codepage, int remap)
1008 TRANSACTION2_SPI_REQ *pSMB = NULL;
1009 TRANSACTION2_SPI_RSP *pSMBr = NULL;
1012 int bytes_returned = 0;
1013 __u16 params, param_offset, offset, byte_count, count;
1014 OPEN_PSX_REQ *pdata;
1015 OPEN_PSX_RSP *psx_rsp;
1017 cFYI(1, "In POSIX Create");
1019 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
1024 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1026 cifsConvertToUCS((__le16 *) pSMB->FileName, name,
1027 PATH_MAX, nls_codepage, remap);
1028 name_len++; /* trailing null */
1030 } else { /* BB improve the check for buffer overruns BB */
1031 name_len = strnlen(name, PATH_MAX);
1032 name_len++; /* trailing null */
1033 strncpy(pSMB->FileName, name, name_len);
1036 params = 6 + name_len;
1037 count = sizeof(OPEN_PSX_REQ);
1038 pSMB->MaxParameterCount = cpu_to_le16(2);
1039 pSMB->MaxDataCount = cpu_to_le16(1000); /* large enough */
1040 pSMB->MaxSetupCount = 0;
1044 pSMB->Reserved2 = 0;
1045 param_offset = offsetof(struct smb_com_transaction2_spi_req,
1046 InformationLevel) - 4;
1047 offset = param_offset + params;
1048 pdata = (OPEN_PSX_REQ *)(((char *)&pSMB->hdr.Protocol) + offset);
1049 pdata->Level = cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC);
1050 pdata->Permissions = cpu_to_le64(mode);
1051 pdata->PosixOpenFlags = cpu_to_le32(posix_flags);
1052 pdata->OpenFlags = cpu_to_le32(*pOplock);
1053 pSMB->ParameterOffset = cpu_to_le16(param_offset);
1054 pSMB->DataOffset = cpu_to_le16(offset);
1055 pSMB->SetupCount = 1;
1056 pSMB->Reserved3 = 0;
1057 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
1058 byte_count = 3 /* pad */ + params + count;
1060 pSMB->DataCount = cpu_to_le16(count);
1061 pSMB->ParameterCount = cpu_to_le16(params);
1062 pSMB->TotalDataCount = pSMB->DataCount;
1063 pSMB->TotalParameterCount = pSMB->ParameterCount;
1064 pSMB->InformationLevel = cpu_to_le16(SMB_POSIX_OPEN);
1065 pSMB->Reserved4 = 0;
1066 pSMB->hdr.smb_buf_length += byte_count;
1067 pSMB->ByteCount = cpu_to_le16(byte_count);
1068 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1069 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1071 cFYI(1, "Posix create returned %d", rc);
1072 goto psx_create_err;
1075 cFYI(1, "copying inode info");
1076 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
1078 if (rc || (pSMBr->ByteCount < sizeof(OPEN_PSX_RSP))) {
1079 rc = -EIO; /* bad smb */
1080 goto psx_create_err;
1083 /* copy return information to pRetData */
1084 psx_rsp = (OPEN_PSX_RSP *)((char *) &pSMBr->hdr.Protocol
1085 + le16_to_cpu(pSMBr->t2.DataOffset));
1087 *pOplock = le16_to_cpu(psx_rsp->OplockFlags);
1089 *netfid = psx_rsp->Fid; /* cifs fid stays in le */
1090 /* Let caller know file was created so we can set the mode. */
1091 /* Do we care about the CreateAction in any other cases? */
1092 if (cpu_to_le32(FILE_CREATE) == psx_rsp->CreateAction)
1093 *pOplock |= CIFS_CREATE_ACTION;
1094 /* check to make sure response data is there */
1095 if (psx_rsp->ReturnedLevel != cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC)) {
1096 pRetData->Type = cpu_to_le32(-1); /* unknown */
1097 cFYI(DBG2, "unknown type");
1099 if (pSMBr->ByteCount < sizeof(OPEN_PSX_RSP)
1100 + sizeof(FILE_UNIX_BASIC_INFO)) {
1101 cERROR(1, "Open response data too small");
1102 pRetData->Type = cpu_to_le32(-1);
1103 goto psx_create_err;
1105 memcpy((char *) pRetData,
1106 (char *)psx_rsp + sizeof(OPEN_PSX_RSP),
1107 sizeof(FILE_UNIX_BASIC_INFO));
1111 cifs_buf_release(pSMB);
1113 if (posix_flags & SMB_O_DIRECTORY)
1114 cifs_stats_inc(&tcon->num_posixmkdirs);
1116 cifs_stats_inc(&tcon->num_posixopens);
1124 static __u16 convert_disposition(int disposition)
1128 switch (disposition) {
1129 case FILE_SUPERSEDE:
1130 ofun = SMBOPEN_OCREATE | SMBOPEN_OTRUNC;
1133 ofun = SMBOPEN_OAPPEND;
1136 ofun = SMBOPEN_OCREATE;
1139 ofun = SMBOPEN_OCREATE | SMBOPEN_OAPPEND;
1141 case FILE_OVERWRITE:
1142 ofun = SMBOPEN_OTRUNC;
1144 case FILE_OVERWRITE_IF:
1145 ofun = SMBOPEN_OCREATE | SMBOPEN_OTRUNC;
1148 cFYI(1, "unknown disposition %d", disposition);
1149 ofun = SMBOPEN_OAPPEND; /* regular open */
1155 access_flags_to_smbopen_mode(const int access_flags)
1157 int masked_flags = access_flags & (GENERIC_READ | GENERIC_WRITE);
1159 if (masked_flags == GENERIC_READ)
1160 return SMBOPEN_READ;
1161 else if (masked_flags == GENERIC_WRITE)
1162 return SMBOPEN_WRITE;
1164 /* just go for read/write */
1165 return SMBOPEN_READWRITE;
1169 SMBLegacyOpen(const int xid, struct cifsTconInfo *tcon,
1170 const char *fileName, const int openDisposition,
1171 const int access_flags, const int create_options, __u16 *netfid,
1172 int *pOplock, FILE_ALL_INFO *pfile_info,
1173 const struct nls_table *nls_codepage, int remap)
1176 OPENX_REQ *pSMB = NULL;
1177 OPENX_RSP *pSMBr = NULL;
1183 rc = smb_init(SMB_COM_OPEN_ANDX, 15, tcon, (void **) &pSMB,
1188 pSMB->AndXCommand = 0xFF; /* none */
1190 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1191 count = 1; /* account for one byte pad to word boundary */
1193 cifsConvertToUCS((__le16 *) (pSMB->fileName + 1),
1194 fileName, PATH_MAX, nls_codepage, remap);
1195 name_len++; /* trailing null */
1197 } else { /* BB improve check for buffer overruns BB */
1198 count = 0; /* no pad */
1199 name_len = strnlen(fileName, PATH_MAX);
1200 name_len++; /* trailing null */
1201 strncpy(pSMB->fileName, fileName, name_len);
1203 if (*pOplock & REQ_OPLOCK)
1204 pSMB->OpenFlags = cpu_to_le16(REQ_OPLOCK);
1205 else if (*pOplock & REQ_BATCHOPLOCK)
1206 pSMB->OpenFlags = cpu_to_le16(REQ_BATCHOPLOCK);
1208 pSMB->OpenFlags |= cpu_to_le16(REQ_MORE_INFO);
1209 pSMB->Mode = cpu_to_le16(access_flags_to_smbopen_mode(access_flags));
1210 pSMB->Mode |= cpu_to_le16(0x40); /* deny none */
1211 /* set file as system file if special file such
1212 as fifo and server expecting SFU style and
1213 no Unix extensions */
1215 if (create_options & CREATE_OPTION_SPECIAL)
1216 pSMB->FileAttributes = cpu_to_le16(ATTR_SYSTEM);
1217 else /* BB FIXME BB */
1218 pSMB->FileAttributes = cpu_to_le16(0/*ATTR_NORMAL*/);
1220 if (create_options & CREATE_OPTION_READONLY)
1221 pSMB->FileAttributes |= cpu_to_le16(ATTR_READONLY);
1224 /* pSMB->CreateOptions = cpu_to_le32(create_options &
1225 CREATE_OPTIONS_MASK); */
1226 /* BB FIXME END BB */
1228 pSMB->Sattr = cpu_to_le16(ATTR_HIDDEN | ATTR_SYSTEM | ATTR_DIRECTORY);
1229 pSMB->OpenFunction = cpu_to_le16(convert_disposition(openDisposition));
1231 pSMB->hdr.smb_buf_length += count;
1233 pSMB->ByteCount = cpu_to_le16(count);
1234 /* long_op set to 1 to allow for oplock break timeouts */
1235 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1236 (struct smb_hdr *)pSMBr, &bytes_returned, 0);
1237 cifs_stats_inc(&tcon->num_opens);
1239 cFYI(1, "Error in Open = %d", rc);
1241 /* BB verify if wct == 15 */
1243 /* *pOplock = pSMBr->OplockLevel; */ /* BB take from action field*/
1245 *netfid = pSMBr->Fid; /* cifs fid stays in le */
1246 /* Let caller know file was created so we can set the mode. */
1247 /* Do we care about the CreateAction in any other cases? */
1249 /* if (cpu_to_le32(FILE_CREATE) == pSMBr->CreateAction)
1250 *pOplock |= CIFS_CREATE_ACTION; */
1254 pfile_info->CreationTime = 0; /* BB convert CreateTime*/
1255 pfile_info->LastAccessTime = 0; /* BB fixme */
1256 pfile_info->LastWriteTime = 0; /* BB fixme */
1257 pfile_info->ChangeTime = 0; /* BB fixme */
1258 pfile_info->Attributes =
1259 cpu_to_le32(le16_to_cpu(pSMBr->FileAttributes));
1260 /* the file_info buf is endian converted by caller */
1261 pfile_info->AllocationSize =
1262 cpu_to_le64(le32_to_cpu(pSMBr->EndOfFile));
1263 pfile_info->EndOfFile = pfile_info->AllocationSize;
1264 pfile_info->NumberOfLinks = cpu_to_le32(1);
1265 pfile_info->DeletePending = 0;
1269 cifs_buf_release(pSMB);
1276 CIFSSMBOpen(const int xid, struct cifsTconInfo *tcon,
1277 const char *fileName, const int openDisposition,
1278 const int access_flags, const int create_options, __u16 *netfid,
1279 int *pOplock, FILE_ALL_INFO *pfile_info,
1280 const struct nls_table *nls_codepage, int remap)
1283 OPEN_REQ *pSMB = NULL;
1284 OPEN_RSP *pSMBr = NULL;
1290 rc = smb_init(SMB_COM_NT_CREATE_ANDX, 24, tcon, (void **) &pSMB,
1295 pSMB->AndXCommand = 0xFF; /* none */
1297 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1298 count = 1; /* account for one byte pad to word boundary */
1300 cifsConvertToUCS((__le16 *) (pSMB->fileName + 1),
1301 fileName, PATH_MAX, nls_codepage, remap);
1302 name_len++; /* trailing null */
1304 pSMB->NameLength = cpu_to_le16(name_len);
1305 } else { /* BB improve check for buffer overruns BB */
1306 count = 0; /* no pad */
1307 name_len = strnlen(fileName, PATH_MAX);
1308 name_len++; /* trailing null */
1309 pSMB->NameLength = cpu_to_le16(name_len);
1310 strncpy(pSMB->fileName, fileName, name_len);
1312 if (*pOplock & REQ_OPLOCK)
1313 pSMB->OpenFlags = cpu_to_le32(REQ_OPLOCK);
1314 else if (*pOplock & REQ_BATCHOPLOCK)
1315 pSMB->OpenFlags = cpu_to_le32(REQ_BATCHOPLOCK);
1316 pSMB->DesiredAccess = cpu_to_le32(access_flags);
1317 pSMB->AllocationSize = 0;
1318 /* set file as system file if special file such
1319 as fifo and server expecting SFU style and
1320 no Unix extensions */
1321 if (create_options & CREATE_OPTION_SPECIAL)
1322 pSMB->FileAttributes = cpu_to_le32(ATTR_SYSTEM);
1324 pSMB->FileAttributes = cpu_to_le32(ATTR_NORMAL);
1326 /* XP does not handle ATTR_POSIX_SEMANTICS */
1327 /* but it helps speed up case sensitive checks for other
1328 servers such as Samba */
1329 if (tcon->ses->capabilities & CAP_UNIX)
1330 pSMB->FileAttributes |= cpu_to_le32(ATTR_POSIX_SEMANTICS);
1332 if (create_options & CREATE_OPTION_READONLY)
1333 pSMB->FileAttributes |= cpu_to_le32(ATTR_READONLY);
1335 pSMB->ShareAccess = cpu_to_le32(FILE_SHARE_ALL);
1336 pSMB->CreateDisposition = cpu_to_le32(openDisposition);
1337 pSMB->CreateOptions = cpu_to_le32(create_options & CREATE_OPTIONS_MASK);
1338 /* BB Expirement with various impersonation levels and verify */
1339 pSMB->ImpersonationLevel = cpu_to_le32(SECURITY_IMPERSONATION);
1340 pSMB->SecurityFlags =
1341 SECURITY_CONTEXT_TRACKING | SECURITY_EFFECTIVE_ONLY;
1344 pSMB->hdr.smb_buf_length += count;
1346 pSMB->ByteCount = cpu_to_le16(count);
1347 /* long_op set to 1 to allow for oplock break timeouts */
1348 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1349 (struct smb_hdr *)pSMBr, &bytes_returned, 0);
1350 cifs_stats_inc(&tcon->num_opens);
1352 cFYI(1, "Error in Open = %d", rc);
1354 *pOplock = pSMBr->OplockLevel; /* 1 byte no need to le_to_cpu */
1355 *netfid = pSMBr->Fid; /* cifs fid stays in le */
1356 /* Let caller know file was created so we can set the mode. */
1357 /* Do we care about the CreateAction in any other cases? */
1358 if (cpu_to_le32(FILE_CREATE) == pSMBr->CreateAction)
1359 *pOplock |= CIFS_CREATE_ACTION;
1361 memcpy((char *)pfile_info, (char *)&pSMBr->CreationTime,
1362 36 /* CreationTime to Attributes */);
1363 /* the file_info buf is endian converted by caller */
1364 pfile_info->AllocationSize = pSMBr->AllocationSize;
1365 pfile_info->EndOfFile = pSMBr->EndOfFile;
1366 pfile_info->NumberOfLinks = cpu_to_le32(1);
1367 pfile_info->DeletePending = 0;
1371 cifs_buf_release(pSMB);
1378 CIFSSMBRead(const int xid, struct cifsTconInfo *tcon, const int netfid,
1379 const unsigned int count, const __u64 lseek, unsigned int *nbytes,
1380 char **buf, int *pbuf_type)
1383 READ_REQ *pSMB = NULL;
1384 READ_RSP *pSMBr = NULL;
1385 char *pReadData = NULL;
1387 int resp_buf_type = 0;
1390 cFYI(1, "Reading %d bytes on fid %d", count, netfid);
1391 if (tcon->ses->capabilities & CAP_LARGE_FILES)
1394 wct = 10; /* old style read */
1395 if ((lseek >> 32) > 0) {
1396 /* can not handle this big offset for old */
1402 rc = small_smb_init(SMB_COM_READ_ANDX, wct, tcon, (void **) &pSMB);
1406 /* tcon and ses pointer are checked in smb_init */
1407 if (tcon->ses->server == NULL)
1408 return -ECONNABORTED;
1410 pSMB->AndXCommand = 0xFF; /* none */
1412 pSMB->OffsetLow = cpu_to_le32(lseek & 0xFFFFFFFF);
1414 pSMB->OffsetHigh = cpu_to_le32(lseek >> 32);
1416 pSMB->Remaining = 0;
1417 pSMB->MaxCount = cpu_to_le16(count & 0xFFFF);
1418 pSMB->MaxCountHigh = cpu_to_le32(count >> 16);
1420 pSMB->ByteCount = 0; /* no need to do le conversion since 0 */
1422 /* old style read */
1423 struct smb_com_readx_req *pSMBW =
1424 (struct smb_com_readx_req *)pSMB;
1425 pSMBW->ByteCount = 0;
1428 iov[0].iov_base = (char *)pSMB;
1429 iov[0].iov_len = pSMB->hdr.smb_buf_length + 4;
1430 rc = SendReceive2(xid, tcon->ses, iov, 1 /* num iovecs */,
1431 &resp_buf_type, CIFS_LOG_ERROR);
1432 cifs_stats_inc(&tcon->num_reads);
1433 pSMBr = (READ_RSP *)iov[0].iov_base;
1435 cERROR(1, "Send error in read = %d", rc);
1437 int data_length = le16_to_cpu(pSMBr->DataLengthHigh);
1438 data_length = data_length << 16;
1439 data_length += le16_to_cpu(pSMBr->DataLength);
1440 *nbytes = data_length;
1442 /*check that DataLength would not go beyond end of SMB */
1443 if ((data_length > CIFSMaxBufSize)
1444 || (data_length > count)) {
1445 cFYI(1, "bad length %d for count %d",
1446 data_length, count);
1450 pReadData = (char *) (&pSMBr->hdr.Protocol) +
1451 le16_to_cpu(pSMBr->DataOffset);
1452 /* if (rc = copy_to_user(buf, pReadData, data_length)) {
1453 cERROR(1, "Faulting on read rc = %d",rc);
1455 }*/ /* can not use copy_to_user when using page cache*/
1457 memcpy(*buf, pReadData, data_length);
1461 /* cifs_small_buf_release(pSMB); */ /* Freed earlier now in SendReceive2 */
1463 if (resp_buf_type == CIFS_SMALL_BUFFER)
1464 cifs_small_buf_release(iov[0].iov_base);
1465 else if (resp_buf_type == CIFS_LARGE_BUFFER)
1466 cifs_buf_release(iov[0].iov_base);
1467 } else if (resp_buf_type != CIFS_NO_BUFFER) {
1468 /* return buffer to caller to free */
1469 *buf = iov[0].iov_base;
1470 if (resp_buf_type == CIFS_SMALL_BUFFER)
1471 *pbuf_type = CIFS_SMALL_BUFFER;
1472 else if (resp_buf_type == CIFS_LARGE_BUFFER)
1473 *pbuf_type = CIFS_LARGE_BUFFER;
1474 } /* else no valid buffer on return - leave as null */
1476 /* Note: On -EAGAIN error only caller can retry on handle based calls
1477 since file handle passed in no longer valid */
1483 CIFSSMBWrite(const int xid, struct cifsTconInfo *tcon,
1484 const int netfid, const unsigned int count,
1485 const __u64 offset, unsigned int *nbytes, const char *buf,
1486 const char __user *ubuf, const int long_op)
1489 WRITE_REQ *pSMB = NULL;
1490 WRITE_RSP *pSMBr = NULL;
1491 int bytes_returned, wct;
1497 /* cFYI(1, "write at %lld %d bytes", offset, count);*/
1498 if (tcon->ses == NULL)
1499 return -ECONNABORTED;
1501 if (tcon->ses->capabilities & CAP_LARGE_FILES)
1505 if ((offset >> 32) > 0) {
1506 /* can not handle big offset for old srv */
1511 rc = smb_init(SMB_COM_WRITE_ANDX, wct, tcon, (void **) &pSMB,
1515 /* tcon and ses pointer are checked in smb_init */
1516 if (tcon->ses->server == NULL)
1517 return -ECONNABORTED;
1519 pSMB->AndXCommand = 0xFF; /* none */
1521 pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF);
1523 pSMB->OffsetHigh = cpu_to_le32(offset >> 32);
1525 pSMB->Reserved = 0xFFFFFFFF;
1526 pSMB->WriteMode = 0;
1527 pSMB->Remaining = 0;
1529 /* Can increase buffer size if buffer is big enough in some cases ie we
1530 can send more if LARGE_WRITE_X capability returned by the server and if
1531 our buffer is big enough or if we convert to iovecs on socket writes
1532 and eliminate the copy to the CIFS buffer */
1533 if (tcon->ses->capabilities & CAP_LARGE_WRITE_X) {
1534 bytes_sent = min_t(const unsigned int, CIFSMaxBufSize, count);
1536 bytes_sent = (tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE)
1540 if (bytes_sent > count)
1543 cpu_to_le16(offsetof(struct smb_com_write_req, Data) - 4);
1545 memcpy(pSMB->Data, buf, bytes_sent);
1547 if (copy_from_user(pSMB->Data, ubuf, bytes_sent)) {
1548 cifs_buf_release(pSMB);
1551 } else if (count != 0) {
1553 cifs_buf_release(pSMB);
1555 } /* else setting file size with write of zero bytes */
1557 byte_count = bytes_sent + 1; /* pad */
1558 else /* wct == 12 */
1559 byte_count = bytes_sent + 5; /* bigger pad, smaller smb hdr */
1561 pSMB->DataLengthLow = cpu_to_le16(bytes_sent & 0xFFFF);
1562 pSMB->DataLengthHigh = cpu_to_le16(bytes_sent >> 16);
1563 pSMB->hdr.smb_buf_length += byte_count;
1566 pSMB->ByteCount = cpu_to_le16(byte_count);
1567 else { /* old style write has byte count 4 bytes earlier
1569 struct smb_com_writex_req *pSMBW =
1570 (struct smb_com_writex_req *)pSMB;
1571 pSMBW->ByteCount = cpu_to_le16(byte_count);
1574 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1575 (struct smb_hdr *) pSMBr, &bytes_returned, long_op);
1576 cifs_stats_inc(&tcon->num_writes);
1578 cFYI(1, "Send error in write = %d", rc);
1580 *nbytes = le16_to_cpu(pSMBr->CountHigh);
1581 *nbytes = (*nbytes) << 16;
1582 *nbytes += le16_to_cpu(pSMBr->Count);
1585 * Mask off high 16 bits when bytes written as returned by the
1586 * server is greater than bytes requested by the client. Some
1587 * OS/2 servers are known to set incorrect CountHigh values.
1589 if (*nbytes > count)
1593 cifs_buf_release(pSMB);
1595 /* Note: On -EAGAIN error only caller can retry on handle based calls
1596 since file handle passed in no longer valid */
1602 CIFSSMBWrite2(const int xid, struct cifsTconInfo *tcon,
1603 const int netfid, const unsigned int count,
1604 const __u64 offset, unsigned int *nbytes, struct kvec *iov,
1605 int n_vec, const int long_op)
1608 WRITE_REQ *pSMB = NULL;
1611 int resp_buf_type = 0;
1615 cFYI(1, "write2 at %lld %d bytes", (long long)offset, count);
1617 if (tcon->ses->capabilities & CAP_LARGE_FILES) {
1621 if ((offset >> 32) > 0) {
1622 /* can not handle big offset for old srv */
1626 rc = small_smb_init(SMB_COM_WRITE_ANDX, wct, tcon, (void **) &pSMB);
1629 /* tcon and ses pointer are checked in smb_init */
1630 if (tcon->ses->server == NULL)
1631 return -ECONNABORTED;
1633 pSMB->AndXCommand = 0xFF; /* none */
1635 pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF);
1637 pSMB->OffsetHigh = cpu_to_le32(offset >> 32);
1638 pSMB->Reserved = 0xFFFFFFFF;
1639 pSMB->WriteMode = 0;
1640 pSMB->Remaining = 0;
1643 cpu_to_le16(offsetof(struct smb_com_write_req, Data) - 4);
1645 pSMB->DataLengthLow = cpu_to_le16(count & 0xFFFF);
1646 pSMB->DataLengthHigh = cpu_to_le16(count >> 16);
1647 smb_hdr_len = pSMB->hdr.smb_buf_length + 1; /* hdr + 1 byte pad */
1649 pSMB->hdr.smb_buf_length += count+1;
1650 else /* wct == 12 */
1651 pSMB->hdr.smb_buf_length += count+5; /* smb data starts later */
1653 pSMB->ByteCount = cpu_to_le16(count + 1);
1654 else /* wct == 12 */ /* bigger pad, smaller smb hdr, keep offset ok */ {
1655 struct smb_com_writex_req *pSMBW =
1656 (struct smb_com_writex_req *)pSMB;
1657 pSMBW->ByteCount = cpu_to_le16(count + 5);
1659 iov[0].iov_base = pSMB;
1661 iov[0].iov_len = smb_hdr_len + 4;
1662 else /* wct == 12 pad bigger by four bytes */
1663 iov[0].iov_len = smb_hdr_len + 8;
1666 rc = SendReceive2(xid, tcon->ses, iov, n_vec + 1, &resp_buf_type,
1668 cifs_stats_inc(&tcon->num_writes);
1670 cFYI(1, "Send error Write2 = %d", rc);
1671 } else if (resp_buf_type == 0) {
1672 /* presumably this can not happen, but best to be safe */
1675 WRITE_RSP *pSMBr = (WRITE_RSP *)iov[0].iov_base;
1676 *nbytes = le16_to_cpu(pSMBr->CountHigh);
1677 *nbytes = (*nbytes) << 16;
1678 *nbytes += le16_to_cpu(pSMBr->Count);
1681 * Mask off high 16 bits when bytes written as returned by the
1682 * server is greater than bytes requested by the client. OS/2
1683 * servers are known to set incorrect CountHigh values.
1685 if (*nbytes > count)
1689 /* cifs_small_buf_release(pSMB); */ /* Freed earlier now in SendReceive2 */
1690 if (resp_buf_type == CIFS_SMALL_BUFFER)
1691 cifs_small_buf_release(iov[0].iov_base);
1692 else if (resp_buf_type == CIFS_LARGE_BUFFER)
1693 cifs_buf_release(iov[0].iov_base);
1695 /* Note: On -EAGAIN error only caller can retry on handle based calls
1696 since file handle passed in no longer valid */
1703 CIFSSMBLock(const int xid, struct cifsTconInfo *tcon,
1704 const __u16 smb_file_id, const __u64 len,
1705 const __u64 offset, const __u32 numUnlock,
1706 const __u32 numLock, const __u8 lockType,
1707 const bool waitFlag, const __u8 oplock_level)
1710 LOCK_REQ *pSMB = NULL;
1711 /* LOCK_RSP *pSMBr = NULL; */ /* No response data other than rc to parse */
1716 cFYI(1, "CIFSSMBLock timeout %d numLock %d", (int)waitFlag, numLock);
1717 rc = small_smb_init(SMB_COM_LOCKING_ANDX, 8, tcon, (void **) &pSMB);
1722 if (lockType == LOCKING_ANDX_OPLOCK_RELEASE) {
1723 timeout = CIFS_ASYNC_OP; /* no response expected */
1725 } else if (waitFlag) {
1726 timeout = CIFS_BLOCKING_OP; /* blocking operation, no timeout */
1727 pSMB->Timeout = cpu_to_le32(-1);/* blocking - do not time out */
1732 pSMB->NumberOfLocks = cpu_to_le16(numLock);
1733 pSMB->NumberOfUnlocks = cpu_to_le16(numUnlock);
1734 pSMB->LockType = lockType;
1735 pSMB->OplockLevel = oplock_level;
1736 pSMB->AndXCommand = 0xFF; /* none */
1737 pSMB->Fid = smb_file_id; /* netfid stays le */
1739 if ((numLock != 0) || (numUnlock != 0)) {
1740 pSMB->Locks[0].Pid = cpu_to_le16(current->tgid);
1741 /* BB where to store pid high? */
1742 pSMB->Locks[0].LengthLow = cpu_to_le32((u32)len);
1743 pSMB->Locks[0].LengthHigh = cpu_to_le32((u32)(len>>32));
1744 pSMB->Locks[0].OffsetLow = cpu_to_le32((u32)offset);
1745 pSMB->Locks[0].OffsetHigh = cpu_to_le32((u32)(offset>>32));
1746 count = sizeof(LOCKING_ANDX_RANGE);
1751 pSMB->hdr.smb_buf_length += count;
1752 pSMB->ByteCount = cpu_to_le16(count);
1755 rc = SendReceiveBlockingLock(xid, tcon, (struct smb_hdr *) pSMB,
1756 (struct smb_hdr *) pSMB, &bytes_returned);
1757 cifs_small_buf_release(pSMB);
1759 rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *)pSMB,
1761 /* SMB buffer freed by function above */
1763 cifs_stats_inc(&tcon->num_locks);
1765 cFYI(1, "Send error in Lock = %d", rc);
1767 /* Note: On -EAGAIN error only caller can retry on handle based calls
1768 since file handle passed in no longer valid */
1773 CIFSSMBPosixLock(const int xid, struct cifsTconInfo *tcon,
1774 const __u16 smb_file_id, const int get_flag, const __u64 len,
1775 struct file_lock *pLockData, const __u16 lock_type,
1776 const bool waitFlag)
1778 struct smb_com_transaction2_sfi_req *pSMB = NULL;
1779 struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
1780 struct cifs_posix_lock *parm_data;
1783 int bytes_returned = 0;
1784 int resp_buf_type = 0;
1785 __u16 params, param_offset, offset, byte_count, count;
1788 cFYI(1, "Posix Lock");
1790 if (pLockData == NULL)
1793 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
1798 pSMBr = (struct smb_com_transaction2_sfi_rsp *)pSMB;
1801 pSMB->MaxSetupCount = 0;
1804 pSMB->Reserved2 = 0;
1805 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
1806 offset = param_offset + params;
1808 count = sizeof(struct cifs_posix_lock);
1809 pSMB->MaxParameterCount = cpu_to_le16(2);
1810 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB from sess */
1811 pSMB->SetupCount = 1;
1812 pSMB->Reserved3 = 0;
1814 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION);
1816 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
1817 byte_count = 3 /* pad */ + params + count;
1818 pSMB->DataCount = cpu_to_le16(count);
1819 pSMB->ParameterCount = cpu_to_le16(params);
1820 pSMB->TotalDataCount = pSMB->DataCount;
1821 pSMB->TotalParameterCount = pSMB->ParameterCount;
1822 pSMB->ParameterOffset = cpu_to_le16(param_offset);
1823 parm_data = (struct cifs_posix_lock *)
1824 (((char *) &pSMB->hdr.Protocol) + offset);
1826 parm_data->lock_type = cpu_to_le16(lock_type);
1828 timeout = CIFS_BLOCKING_OP; /* blocking operation, no timeout */
1829 parm_data->lock_flags = cpu_to_le16(1);
1830 pSMB->Timeout = cpu_to_le32(-1);
1834 parm_data->pid = cpu_to_le32(current->tgid);
1835 parm_data->start = cpu_to_le64(pLockData->fl_start);
1836 parm_data->length = cpu_to_le64(len); /* normalize negative numbers */
1838 pSMB->DataOffset = cpu_to_le16(offset);
1839 pSMB->Fid = smb_file_id;
1840 pSMB->InformationLevel = cpu_to_le16(SMB_SET_POSIX_LOCK);
1841 pSMB->Reserved4 = 0;
1842 pSMB->hdr.smb_buf_length += byte_count;
1843 pSMB->ByteCount = cpu_to_le16(byte_count);
1845 rc = SendReceiveBlockingLock(xid, tcon, (struct smb_hdr *) pSMB,
1846 (struct smb_hdr *) pSMBr, &bytes_returned);
1848 iov[0].iov_base = (char *)pSMB;
1849 iov[0].iov_len = pSMB->hdr.smb_buf_length + 4;
1850 rc = SendReceive2(xid, tcon->ses, iov, 1 /* num iovecs */,
1851 &resp_buf_type, timeout);
1852 pSMB = NULL; /* request buf already freed by SendReceive2. Do
1853 not try to free it twice below on exit */
1854 pSMBr = (struct smb_com_transaction2_sfi_rsp *)iov[0].iov_base;
1858 cFYI(1, "Send error in Posix Lock = %d", rc);
1859 } else if (get_flag) {
1860 /* lock structure can be returned on get */
1863 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
1865 if (rc || (pSMBr->ByteCount < sizeof(struct cifs_posix_lock))) {
1866 rc = -EIO; /* bad smb */
1869 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
1870 data_count = le16_to_cpu(pSMBr->t2.DataCount);
1871 if (data_count < sizeof(struct cifs_posix_lock)) {
1875 parm_data = (struct cifs_posix_lock *)
1876 ((char *)&pSMBr->hdr.Protocol + data_offset);
1877 if (parm_data->lock_type == __constant_cpu_to_le16(CIFS_UNLCK))
1878 pLockData->fl_type = F_UNLCK;
1880 if (parm_data->lock_type ==
1881 __constant_cpu_to_le16(CIFS_RDLCK))
1882 pLockData->fl_type = F_RDLCK;
1883 else if (parm_data->lock_type ==
1884 __constant_cpu_to_le16(CIFS_WRLCK))
1885 pLockData->fl_type = F_WRLCK;
1887 pLockData->fl_start = le64_to_cpu(parm_data->start);
1888 pLockData->fl_end = pLockData->fl_start +
1889 le64_to_cpu(parm_data->length) - 1;
1890 pLockData->fl_pid = le32_to_cpu(parm_data->pid);
1896 cifs_small_buf_release(pSMB);
1898 if (resp_buf_type == CIFS_SMALL_BUFFER)
1899 cifs_small_buf_release(iov[0].iov_base);
1900 else if (resp_buf_type == CIFS_LARGE_BUFFER)
1901 cifs_buf_release(iov[0].iov_base);
1903 /* Note: On -EAGAIN error only caller can retry on handle based calls
1904 since file handle passed in no longer valid */
1911 CIFSSMBClose(const int xid, struct cifsTconInfo *tcon, int smb_file_id)
1914 CLOSE_REQ *pSMB = NULL;
1915 cFYI(1, "In CIFSSMBClose");
1917 /* do not retry on dead session on close */
1918 rc = small_smb_init(SMB_COM_CLOSE, 3, tcon, (void **) &pSMB);
1924 pSMB->FileID = (__u16) smb_file_id;
1925 pSMB->LastWriteTime = 0xFFFFFFFF;
1926 pSMB->ByteCount = 0;
1927 rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0);
1928 cifs_stats_inc(&tcon->num_closes);
1931 /* EINTR is expected when user ctl-c to kill app */
1932 cERROR(1, "Send error in Close = %d", rc);
1936 /* Since session is dead, file will be closed on server already */
1944 CIFSSMBFlush(const int xid, struct cifsTconInfo *tcon, int smb_file_id)
1947 FLUSH_REQ *pSMB = NULL;
1948 cFYI(1, "In CIFSSMBFlush");
1950 rc = small_smb_init(SMB_COM_FLUSH, 1, tcon, (void **) &pSMB);
1954 pSMB->FileID = (__u16) smb_file_id;
1955 pSMB->ByteCount = 0;
1956 rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0);
1957 cifs_stats_inc(&tcon->num_flushes);
1959 cERROR(1, "Send error in Flush = %d", rc);
1965 CIFSSMBRename(const int xid, struct cifsTconInfo *tcon,
1966 const char *fromName, const char *toName,
1967 const struct nls_table *nls_codepage, int remap)
1970 RENAME_REQ *pSMB = NULL;
1971 RENAME_RSP *pSMBr = NULL;
1973 int name_len, name_len2;
1976 cFYI(1, "In CIFSSMBRename");
1978 rc = smb_init(SMB_COM_RENAME, 1, tcon, (void **) &pSMB,
1983 pSMB->BufferFormat = 0x04;
1984 pSMB->SearchAttributes =
1985 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
1988 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1990 cifsConvertToUCS((__le16 *) pSMB->OldFileName, fromName,
1991 PATH_MAX, nls_codepage, remap);
1992 name_len++; /* trailing null */
1994 pSMB->OldFileName[name_len] = 0x04; /* pad */
1995 /* protocol requires ASCII signature byte on Unicode string */
1996 pSMB->OldFileName[name_len + 1] = 0x00;
1998 cifsConvertToUCS((__le16 *)&pSMB->OldFileName[name_len + 2],
1999 toName, PATH_MAX, nls_codepage, remap);
2000 name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
2001 name_len2 *= 2; /* convert to bytes */
2002 } else { /* BB improve the check for buffer overruns BB */
2003 name_len = strnlen(fromName, PATH_MAX);
2004 name_len++; /* trailing null */
2005 strncpy(pSMB->OldFileName, fromName, name_len);
2006 name_len2 = strnlen(toName, PATH_MAX);
2007 name_len2++; /* trailing null */
2008 pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */
2009 strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2);
2010 name_len2++; /* trailing null */
2011 name_len2++; /* signature byte */
2014 count = 1 /* 1st signature byte */ + name_len + name_len2;
2015 pSMB->hdr.smb_buf_length += count;
2016 pSMB->ByteCount = cpu_to_le16(count);
2018 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2019 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2020 cifs_stats_inc(&tcon->num_renames);
2022 cFYI(1, "Send error in rename = %d", rc);
2024 cifs_buf_release(pSMB);
2032 int CIFSSMBRenameOpenFile(const int xid, struct cifsTconInfo *pTcon,
2033 int netfid, const char *target_name,
2034 const struct nls_table *nls_codepage, int remap)
2036 struct smb_com_transaction2_sfi_req *pSMB = NULL;
2037 struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
2038 struct set_file_rename *rename_info;
2040 char dummy_string[30];
2042 int bytes_returned = 0;
2044 __u16 params, param_offset, offset, count, byte_count;
2046 cFYI(1, "Rename to File by handle");
2047 rc = smb_init(SMB_COM_TRANSACTION2, 15, pTcon, (void **) &pSMB,
2053 pSMB->MaxSetupCount = 0;
2057 pSMB->Reserved2 = 0;
2058 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
2059 offset = param_offset + params;
2061 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
2062 rename_info = (struct set_file_rename *) data_offset;
2063 pSMB->MaxParameterCount = cpu_to_le16(2);
2064 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB from sess */
2065 pSMB->SetupCount = 1;
2066 pSMB->Reserved3 = 0;
2067 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
2068 byte_count = 3 /* pad */ + params;
2069 pSMB->ParameterCount = cpu_to_le16(params);
2070 pSMB->TotalParameterCount = pSMB->ParameterCount;
2071 pSMB->ParameterOffset = cpu_to_le16(param_offset);
2072 pSMB->DataOffset = cpu_to_le16(offset);
2073 /* construct random name ".cifs_tmp<inodenum><mid>" */
2074 rename_info->overwrite = cpu_to_le32(1);
2075 rename_info->root_fid = 0;
2076 /* unicode only call */
2077 if (target_name == NULL) {
2078 sprintf(dummy_string, "cifs%x", pSMB->hdr.Mid);
2079 len_of_str = cifsConvertToUCS((__le16 *)rename_info->target_name,
2080 dummy_string, 24, nls_codepage, remap);
2082 len_of_str = cifsConvertToUCS((__le16 *)rename_info->target_name,
2083 target_name, PATH_MAX, nls_codepage,
2086 rename_info->target_name_len = cpu_to_le32(2 * len_of_str);
2087 count = 12 /* sizeof(struct set_file_rename) */ + (2 * len_of_str);
2088 byte_count += count;
2089 pSMB->DataCount = cpu_to_le16(count);
2090 pSMB->TotalDataCount = pSMB->DataCount;
2092 pSMB->InformationLevel =
2093 cpu_to_le16(SMB_SET_FILE_RENAME_INFORMATION);
2094 pSMB->Reserved4 = 0;
2095 pSMB->hdr.smb_buf_length += byte_count;
2096 pSMB->ByteCount = cpu_to_le16(byte_count);
2097 rc = SendReceive(xid, pTcon->ses, (struct smb_hdr *) pSMB,
2098 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2099 cifs_stats_inc(&pTcon->num_t2renames);
2101 cFYI(1, "Send error in Rename (by file handle) = %d", rc);
2103 cifs_buf_release(pSMB);
2105 /* Note: On -EAGAIN error only caller can retry on handle based calls
2106 since file handle passed in no longer valid */
2112 CIFSSMBCopy(const int xid, struct cifsTconInfo *tcon, const char *fromName,
2113 const __u16 target_tid, const char *toName, const int flags,
2114 const struct nls_table *nls_codepage, int remap)
2117 COPY_REQ *pSMB = NULL;
2118 COPY_RSP *pSMBr = NULL;
2120 int name_len, name_len2;
2123 cFYI(1, "In CIFSSMBCopy");
2125 rc = smb_init(SMB_COM_COPY, 1, tcon, (void **) &pSMB,
2130 pSMB->BufferFormat = 0x04;
2131 pSMB->Tid2 = target_tid;
2133 pSMB->Flags = cpu_to_le16(flags & COPY_TREE);
2135 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2136 name_len = cifsConvertToUCS((__le16 *) pSMB->OldFileName,
2137 fromName, PATH_MAX, nls_codepage,
2139 name_len++; /* trailing null */
2141 pSMB->OldFileName[name_len] = 0x04; /* pad */
2142 /* protocol requires ASCII signature byte on Unicode string */
2143 pSMB->OldFileName[name_len + 1] = 0x00;
2145 cifsConvertToUCS((__le16 *)&pSMB->OldFileName[name_len + 2],
2146 toName, PATH_MAX, nls_codepage, remap);
2147 name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
2148 name_len2 *= 2; /* convert to bytes */
2149 } else { /* BB improve the check for buffer overruns BB */
2150 name_len = strnlen(fromName, PATH_MAX);
2151 name_len++; /* trailing null */
2152 strncpy(pSMB->OldFileName, fromName, name_len);
2153 name_len2 = strnlen(toName, PATH_MAX);
2154 name_len2++; /* trailing null */
2155 pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */
2156 strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2);
2157 name_len2++; /* trailing null */
2158 name_len2++; /* signature byte */
2161 count = 1 /* 1st signature byte */ + name_len + name_len2;
2162 pSMB->hdr.smb_buf_length += count;
2163 pSMB->ByteCount = cpu_to_le16(count);
2165 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2166 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2168 cFYI(1, "Send error in copy = %d with %d files copied",
2169 rc, le16_to_cpu(pSMBr->CopyCount));
2171 cifs_buf_release(pSMB);
2180 CIFSUnixCreateSymLink(const int xid, struct cifsTconInfo *tcon,
2181 const char *fromName, const char *toName,
2182 const struct nls_table *nls_codepage)
2184 TRANSACTION2_SPI_REQ *pSMB = NULL;
2185 TRANSACTION2_SPI_RSP *pSMBr = NULL;
2188 int name_len_target;
2190 int bytes_returned = 0;
2191 __u16 params, param_offset, offset, byte_count;
2193 cFYI(1, "In Symlink Unix style");
2195 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2200 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2202 cifs_strtoUCS((__le16 *) pSMB->FileName, fromName, PATH_MAX
2203 /* find define for this maxpathcomponent */
2205 name_len++; /* trailing null */
2208 } else { /* BB improve the check for buffer overruns BB */
2209 name_len = strnlen(fromName, PATH_MAX);
2210 name_len++; /* trailing null */
2211 strncpy(pSMB->FileName, fromName, name_len);
2213 params = 6 + name_len;
2214 pSMB->MaxSetupCount = 0;
2218 pSMB->Reserved2 = 0;
2219 param_offset = offsetof(struct smb_com_transaction2_spi_req,
2220 InformationLevel) - 4;
2221 offset = param_offset + params;
2223 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
2224 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2226 cifs_strtoUCS((__le16 *) data_offset, toName, PATH_MAX
2227 /* find define for this maxpathcomponent */
2229 name_len_target++; /* trailing null */
2230 name_len_target *= 2;
2231 } else { /* BB improve the check for buffer overruns BB */
2232 name_len_target = strnlen(toName, PATH_MAX);
2233 name_len_target++; /* trailing null */
2234 strncpy(data_offset, toName, name_len_target);
2237 pSMB->MaxParameterCount = cpu_to_le16(2);
2238 /* BB find exact max on data count below from sess */
2239 pSMB->MaxDataCount = cpu_to_le16(1000);
2240 pSMB->SetupCount = 1;
2241 pSMB->Reserved3 = 0;
2242 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
2243 byte_count = 3 /* pad */ + params + name_len_target;
2244 pSMB->DataCount = cpu_to_le16(name_len_target);
2245 pSMB->ParameterCount = cpu_to_le16(params);
2246 pSMB->TotalDataCount = pSMB->DataCount;
2247 pSMB->TotalParameterCount = pSMB->ParameterCount;
2248 pSMB->ParameterOffset = cpu_to_le16(param_offset);
2249 pSMB->DataOffset = cpu_to_le16(offset);
2250 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_LINK);
2251 pSMB->Reserved4 = 0;
2252 pSMB->hdr.smb_buf_length += byte_count;
2253 pSMB->ByteCount = cpu_to_le16(byte_count);
2254 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2255 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2256 cifs_stats_inc(&tcon->num_symlinks);
2258 cFYI(1, "Send error in SetPathInfo create symlink = %d", rc);
2260 cifs_buf_release(pSMB);
2263 goto createSymLinkRetry;
2269 CIFSUnixCreateHardLink(const int xid, struct cifsTconInfo *tcon,
2270 const char *fromName, const char *toName,
2271 const struct nls_table *nls_codepage, int remap)
2273 TRANSACTION2_SPI_REQ *pSMB = NULL;
2274 TRANSACTION2_SPI_RSP *pSMBr = NULL;
2277 int name_len_target;
2279 int bytes_returned = 0;
2280 __u16 params, param_offset, offset, byte_count;
2282 cFYI(1, "In Create Hard link Unix style");
2283 createHardLinkRetry:
2284 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2289 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2290 name_len = cifsConvertToUCS((__le16 *) pSMB->FileName, toName,
2291 PATH_MAX, nls_codepage, remap);
2292 name_len++; /* trailing null */
2295 } else { /* BB improve the check for buffer overruns BB */
2296 name_len = strnlen(toName, PATH_MAX);
2297 name_len++; /* trailing null */
2298 strncpy(pSMB->FileName, toName, name_len);
2300 params = 6 + name_len;
2301 pSMB->MaxSetupCount = 0;
2305 pSMB->Reserved2 = 0;
2306 param_offset = offsetof(struct smb_com_transaction2_spi_req,
2307 InformationLevel) - 4;
2308 offset = param_offset + params;
2310 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
2311 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2313 cifsConvertToUCS((__le16 *) data_offset, fromName, PATH_MAX,
2314 nls_codepage, remap);
2315 name_len_target++; /* trailing null */
2316 name_len_target *= 2;
2317 } else { /* BB improve the check for buffer overruns BB */
2318 name_len_target = strnlen(fromName, PATH_MAX);
2319 name_len_target++; /* trailing null */
2320 strncpy(data_offset, fromName, name_len_target);
2323 pSMB->MaxParameterCount = cpu_to_le16(2);
2324 /* BB find exact max on data count below from sess*/
2325 pSMB->MaxDataCount = cpu_to_le16(1000);
2326 pSMB->SetupCount = 1;
2327 pSMB->Reserved3 = 0;
2328 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
2329 byte_count = 3 /* pad */ + params + name_len_target;
2330 pSMB->ParameterCount = cpu_to_le16(params);
2331 pSMB->TotalParameterCount = pSMB->ParameterCount;
2332 pSMB->DataCount = cpu_to_le16(name_len_target);
2333 pSMB->TotalDataCount = pSMB->DataCount;
2334 pSMB->ParameterOffset = cpu_to_le16(param_offset);
2335 pSMB->DataOffset = cpu_to_le16(offset);
2336 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_HLINK);
2337 pSMB->Reserved4 = 0;
2338 pSMB->hdr.smb_buf_length += byte_count;
2339 pSMB->ByteCount = cpu_to_le16(byte_count);
2340 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2341 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2342 cifs_stats_inc(&tcon->num_hardlinks);
2344 cFYI(1, "Send error in SetPathInfo (hard link) = %d", rc);
2346 cifs_buf_release(pSMB);
2348 goto createHardLinkRetry;
2354 CIFSCreateHardLink(const int xid, struct cifsTconInfo *tcon,
2355 const char *fromName, const char *toName,
2356 const struct nls_table *nls_codepage, int remap)
2359 NT_RENAME_REQ *pSMB = NULL;
2360 RENAME_RSP *pSMBr = NULL;
2362 int name_len, name_len2;
2365 cFYI(1, "In CIFSCreateHardLink");
2366 winCreateHardLinkRetry:
2368 rc = smb_init(SMB_COM_NT_RENAME, 4, tcon, (void **) &pSMB,
2373 pSMB->SearchAttributes =
2374 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
2376 pSMB->Flags = cpu_to_le16(CREATE_HARD_LINK);
2377 pSMB->ClusterCount = 0;
2379 pSMB->BufferFormat = 0x04;
2381 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2383 cifsConvertToUCS((__le16 *) pSMB->OldFileName, fromName,
2384 PATH_MAX, nls_codepage, remap);
2385 name_len++; /* trailing null */
2388 /* protocol specifies ASCII buffer format (0x04) for unicode */
2389 pSMB->OldFileName[name_len] = 0x04;
2390 pSMB->OldFileName[name_len + 1] = 0x00; /* pad */
2392 cifsConvertToUCS((__le16 *)&pSMB->OldFileName[name_len + 2],
2393 toName, PATH_MAX, nls_codepage, remap);
2394 name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
2395 name_len2 *= 2; /* convert to bytes */
2396 } else { /* BB improve the check for buffer overruns BB */
2397 name_len = strnlen(fromName, PATH_MAX);
2398 name_len++; /* trailing null */
2399 strncpy(pSMB->OldFileName, fromName, name_len);
2400 name_len2 = strnlen(toName, PATH_MAX);
2401 name_len2++; /* trailing null */
2402 pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */
2403 strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2);
2404 name_len2++; /* trailing null */
2405 name_len2++; /* signature byte */
2408 count = 1 /* string type byte */ + name_len + name_len2;
2409 pSMB->hdr.smb_buf_length += count;
2410 pSMB->ByteCount = cpu_to_le16(count);
2412 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2413 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2414 cifs_stats_inc(&tcon->num_hardlinks);
2416 cFYI(1, "Send error in hard link (NT rename) = %d", rc);
2418 cifs_buf_release(pSMB);
2420 goto winCreateHardLinkRetry;
2426 CIFSSMBUnixQuerySymLink(const int xid, struct cifsTconInfo *tcon,
2427 const unsigned char *searchName, char **symlinkinfo,
2428 const struct nls_table *nls_codepage)
2430 /* SMB_QUERY_FILE_UNIX_LINK */
2431 TRANSACTION2_QPI_REQ *pSMB = NULL;
2432 TRANSACTION2_QPI_RSP *pSMBr = NULL;
2436 __u16 params, byte_count;
2439 cFYI(1, "In QPathSymLinkInfo (Unix) for path %s", searchName);
2442 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2447 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2449 cifs_strtoUCS((__le16 *) pSMB->FileName, searchName,
2450 PATH_MAX, nls_codepage);
2451 name_len++; /* trailing null */
2453 } else { /* BB improve the check for buffer overruns BB */
2454 name_len = strnlen(searchName, PATH_MAX);
2455 name_len++; /* trailing null */
2456 strncpy(pSMB->FileName, searchName, name_len);
2459 params = 2 /* level */ + 4 /* rsrvd */ + name_len /* incl null */ ;
2460 pSMB->TotalDataCount = 0;
2461 pSMB->MaxParameterCount = cpu_to_le16(2);
2462 pSMB->MaxDataCount = cpu_to_le16(CIFSMaxBufSize);
2463 pSMB->MaxSetupCount = 0;
2467 pSMB->Reserved2 = 0;
2468 pSMB->ParameterOffset = cpu_to_le16(offsetof(
2469 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
2470 pSMB->DataCount = 0;
2471 pSMB->DataOffset = 0;
2472 pSMB->SetupCount = 1;
2473 pSMB->Reserved3 = 0;
2474 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
2475 byte_count = params + 1 /* pad */ ;
2476 pSMB->TotalParameterCount = cpu_to_le16(params);
2477 pSMB->ParameterCount = pSMB->TotalParameterCount;
2478 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_LINK);
2479 pSMB->Reserved4 = 0;
2480 pSMB->hdr.smb_buf_length += byte_count;
2481 pSMB->ByteCount = cpu_to_le16(byte_count);
2483 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2484 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2486 cFYI(1, "Send error in QuerySymLinkInfo = %d", rc);
2488 /* decode response */
2490 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
2491 /* BB also check enough total bytes returned */
2492 if (rc || (pSMBr->ByteCount < 2))
2496 u16 count = le16_to_cpu(pSMBr->t2.DataCount);
2498 data_start = ((char *) &pSMBr->hdr.Protocol) +
2499 le16_to_cpu(pSMBr->t2.DataOffset);
2501 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
2506 /* BB FIXME investigate remapping reserved chars here */
2507 *symlinkinfo = cifs_strndup_from_ucs(data_start, count,
2508 is_unicode, nls_codepage);
2513 cifs_buf_release(pSMB);
2515 goto querySymLinkRetry;
2519 #ifdef CONFIG_CIFS_SYMLINK_EXPERIMENTAL
2521 * Recent Windows versions now create symlinks more frequently
2522 * and they use the "reparse point" mechanism below. We can of course
2523 * do symlinks nicely to Samba and other servers which support the
2524 * CIFS Unix Extensions and we can also do SFU symlinks and "client only"
2525 * "MF" symlinks optionally, but for recent Windows we really need to
2526 * reenable the code below and fix the cifs_symlink callers to handle this.
2527 * In the interim this code has been moved to its own config option so
2528 * it is not compiled in by default until callers fixed up and more tested.
2531 CIFSSMBQueryReparseLinkInfo(const int xid, struct cifsTconInfo *tcon,
2532 const unsigned char *searchName,
2533 char *symlinkinfo, const int buflen, __u16 fid,
2534 const struct nls_table *nls_codepage)
2538 struct smb_com_transaction_ioctl_req *pSMB;
2539 struct smb_com_transaction_ioctl_rsp *pSMBr;
2541 cFYI(1, "In Windows reparse style QueryLink for path %s", searchName);
2542 rc = smb_init(SMB_COM_NT_TRANSACT, 23, tcon, (void **) &pSMB,
2547 pSMB->TotalParameterCount = 0 ;
2548 pSMB->TotalDataCount = 0;
2549 pSMB->MaxParameterCount = cpu_to_le32(2);
2550 /* BB find exact data count max from sess structure BB */
2551 pSMB->MaxDataCount = cpu_to_le32((tcon->ses->server->maxBuf -
2552 MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
2553 pSMB->MaxSetupCount = 4;
2555 pSMB->ParameterOffset = 0;
2556 pSMB->DataCount = 0;
2557 pSMB->DataOffset = 0;
2558 pSMB->SetupCount = 4;
2559 pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_IOCTL);
2560 pSMB->ParameterCount = pSMB->TotalParameterCount;
2561 pSMB->FunctionCode = cpu_to_le32(FSCTL_GET_REPARSE_POINT);
2562 pSMB->IsFsctl = 1; /* FSCTL */
2563 pSMB->IsRootFlag = 0;
2564 pSMB->Fid = fid; /* file handle always le */
2565 pSMB->ByteCount = 0;
2567 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2568 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2570 cFYI(1, "Send error in QueryReparseLinkInfo = %d", rc);
2571 } else { /* decode response */
2572 __u32 data_offset = le32_to_cpu(pSMBr->DataOffset);
2573 __u32 data_count = le32_to_cpu(pSMBr->DataCount);
2574 if ((pSMBr->ByteCount < 2) || (data_offset > 512)) {
2575 /* BB also check enough total bytes returned */
2576 rc = -EIO; /* bad smb */
2579 if (data_count && (data_count < 2048)) {
2580 char *end_of_smb = 2 /* sizeof byte count */ +
2581 pSMBr->ByteCount + (char *)&pSMBr->ByteCount;
2583 struct reparse_data *reparse_buf =
2584 (struct reparse_data *)
2585 ((char *)&pSMBr->hdr.Protocol
2587 if ((char *)reparse_buf >= end_of_smb) {
2591 if ((reparse_buf->LinkNamesBuf +
2592 reparse_buf->TargetNameOffset +
2593 reparse_buf->TargetNameLen) > end_of_smb) {
2594 cFYI(1, "reparse buf beyond SMB");
2599 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
2600 cifs_from_ucs2(symlinkinfo, (__le16 *)
2601 (reparse_buf->LinkNamesBuf +
2602 reparse_buf->TargetNameOffset),
2604 reparse_buf->TargetNameLen,
2606 } else { /* ASCII names */
2607 strncpy(symlinkinfo,
2608 reparse_buf->LinkNamesBuf +
2609 reparse_buf->TargetNameOffset,
2610 min_t(const int, buflen,
2611 reparse_buf->TargetNameLen));
2615 cFYI(1, "Invalid return data count on "
2616 "get reparse info ioctl");
2618 symlinkinfo[buflen] = 0; /* just in case so the caller
2619 does not go off the end of the buffer */
2620 cFYI(1, "readlink result - %s", symlinkinfo);
2624 cifs_buf_release(pSMB);
2626 /* Note: On -EAGAIN error only caller can retry on handle based calls
2627 since file handle passed in no longer valid */
2631 #endif /* CIFS_SYMLINK_EXPERIMENTAL */ /* BB temporarily unused */
2633 #ifdef CONFIG_CIFS_POSIX
2635 /*Convert an Access Control Entry from wire format to local POSIX xattr format*/
2636 static void cifs_convert_ace(posix_acl_xattr_entry *ace,
2637 struct cifs_posix_ace *cifs_ace)
2639 /* u8 cifs fields do not need le conversion */
2640 ace->e_perm = cpu_to_le16(cifs_ace->cifs_e_perm);
2641 ace->e_tag = cpu_to_le16(cifs_ace->cifs_e_tag);
2642 ace->e_id = cpu_to_le32(le64_to_cpu(cifs_ace->cifs_uid));
2643 /* cFYI(1, "perm %d tag %d id %d",ace->e_perm,ace->e_tag,ace->e_id); */
2648 /* Convert ACL from CIFS POSIX wire format to local Linux POSIX ACL xattr */
2649 static int cifs_copy_posix_acl(char *trgt, char *src, const int buflen,
2650 const int acl_type, const int size_of_data_area)
2655 struct cifs_posix_ace *pACE;
2656 struct cifs_posix_acl *cifs_acl = (struct cifs_posix_acl *)src;
2657 posix_acl_xattr_header *local_acl = (posix_acl_xattr_header *)trgt;
2659 if (le16_to_cpu(cifs_acl->version) != CIFS_ACL_VERSION)
2662 if (acl_type & ACL_TYPE_ACCESS) {
2663 count = le16_to_cpu(cifs_acl->access_entry_count);
2664 pACE = &cifs_acl->ace_array[0];
2665 size = sizeof(struct cifs_posix_acl);
2666 size += sizeof(struct cifs_posix_ace) * count;
2667 /* check if we would go beyond end of SMB */
2668 if (size_of_data_area < size) {
2669 cFYI(1, "bad CIFS POSIX ACL size %d vs. %d",
2670 size_of_data_area, size);
2673 } else if (acl_type & ACL_TYPE_DEFAULT) {
2674 count = le16_to_cpu(cifs_acl->access_entry_count);
2675 size = sizeof(struct cifs_posix_acl);
2676 size += sizeof(struct cifs_posix_ace) * count;
2677 /* skip past access ACEs to get to default ACEs */
2678 pACE = &cifs_acl->ace_array[count];
2679 count = le16_to_cpu(cifs_acl->default_entry_count);
2680 size += sizeof(struct cifs_posix_ace) * count;
2681 /* check if we would go beyond end of SMB */
2682 if (size_of_data_area < size)
2689 size = posix_acl_xattr_size(count);
2690 if ((buflen == 0) || (local_acl == NULL)) {
2691 /* used to query ACL EA size */
2692 } else if (size > buflen) {
2694 } else /* buffer big enough */ {
2695 local_acl->a_version = cpu_to_le32(POSIX_ACL_XATTR_VERSION);
2696 for (i = 0; i < count ; i++) {
2697 cifs_convert_ace(&local_acl->a_entries[i], pACE);
2704 static __u16 convert_ace_to_cifs_ace(struct cifs_posix_ace *cifs_ace,
2705 const posix_acl_xattr_entry *local_ace)
2707 __u16 rc = 0; /* 0 = ACL converted ok */
2709 cifs_ace->cifs_e_perm = le16_to_cpu(local_ace->e_perm);
2710 cifs_ace->cifs_e_tag = le16_to_cpu(local_ace->e_tag);
2711 /* BB is there a better way to handle the large uid? */
2712 if (local_ace->e_id == cpu_to_le32(-1)) {
2713 /* Probably no need to le convert -1 on any arch but can not hurt */
2714 cifs_ace->cifs_uid = cpu_to_le64(-1);
2716 cifs_ace->cifs_uid = cpu_to_le64(le32_to_cpu(local_ace->e_id));
2717 /*cFYI(1, "perm %d tag %d id %d",ace->e_perm,ace->e_tag,ace->e_id);*/
2721 /* Convert ACL from local Linux POSIX xattr to CIFS POSIX ACL wire format */
2722 static __u16 ACL_to_cifs_posix(char *parm_data, const char *pACL,
2723 const int buflen, const int acl_type)
2726 struct cifs_posix_acl *cifs_acl = (struct cifs_posix_acl *)parm_data;
2727 posix_acl_xattr_header *local_acl = (posix_acl_xattr_header *)pACL;
2731 if ((buflen == 0) || (pACL == NULL) || (cifs_acl == NULL))
2734 count = posix_acl_xattr_count((size_t)buflen);
2735 cFYI(1, "setting acl with %d entries from buf of length %d and "
2737 count, buflen, le32_to_cpu(local_acl->a_version));
2738 if (le32_to_cpu(local_acl->a_version) != 2) {
2739 cFYI(1, "unknown POSIX ACL version %d",
2740 le32_to_cpu(local_acl->a_version));
2743 cifs_acl->version = cpu_to_le16(1);
2744 if (acl_type == ACL_TYPE_ACCESS)
2745 cifs_acl->access_entry_count = cpu_to_le16(count);
2746 else if (acl_type == ACL_TYPE_DEFAULT)
2747 cifs_acl->default_entry_count = cpu_to_le16(count);
2749 cFYI(1, "unknown ACL type %d", acl_type);
2752 for (i = 0; i < count; i++) {
2753 rc = convert_ace_to_cifs_ace(&cifs_acl->ace_array[i],
2754 &local_acl->a_entries[i]);
2756 /* ACE not converted */
2761 rc = (__u16)(count * sizeof(struct cifs_posix_ace));
2762 rc += sizeof(struct cifs_posix_acl);
2763 /* BB add check to make sure ACL does not overflow SMB */
2769 CIFSSMBGetPosixACL(const int xid, struct cifsTconInfo *tcon,
2770 const unsigned char *searchName,
2771 char *acl_inf, const int buflen, const int acl_type,
2772 const struct nls_table *nls_codepage, int remap)
2774 /* SMB_QUERY_POSIX_ACL */
2775 TRANSACTION2_QPI_REQ *pSMB = NULL;
2776 TRANSACTION2_QPI_RSP *pSMBr = NULL;
2780 __u16 params, byte_count;
2782 cFYI(1, "In GetPosixACL (Unix) for path %s", searchName);
2785 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2790 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2792 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
2793 PATH_MAX, nls_codepage, remap);
2794 name_len++; /* trailing null */
2796 pSMB->FileName[name_len] = 0;
2797 pSMB->FileName[name_len+1] = 0;
2798 } else { /* BB improve the check for buffer overruns BB */
2799 name_len = strnlen(searchName, PATH_MAX);
2800 name_len++; /* trailing null */
2801 strncpy(pSMB->FileName, searchName, name_len);
2804 params = 2 /* level */ + 4 /* rsrvd */ + name_len /* incl null */ ;
2805 pSMB->TotalDataCount = 0;
2806 pSMB->MaxParameterCount = cpu_to_le16(2);
2807 /* BB find exact max data count below from sess structure BB */
2808 pSMB->MaxDataCount = cpu_to_le16(4000);
2809 pSMB->MaxSetupCount = 0;
2813 pSMB->Reserved2 = 0;
2814 pSMB->ParameterOffset = cpu_to_le16(
2815 offsetof(struct smb_com_transaction2_qpi_req,
2816 InformationLevel) - 4);
2817 pSMB->DataCount = 0;
2818 pSMB->DataOffset = 0;
2819 pSMB->SetupCount = 1;
2820 pSMB->Reserved3 = 0;
2821 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
2822 byte_count = params + 1 /* pad */ ;
2823 pSMB->TotalParameterCount = cpu_to_le16(params);
2824 pSMB->ParameterCount = pSMB->TotalParameterCount;
2825 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_POSIX_ACL);
2826 pSMB->Reserved4 = 0;
2827 pSMB->hdr.smb_buf_length += byte_count;
2828 pSMB->ByteCount = cpu_to_le16(byte_count);
2830 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2831 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2832 cifs_stats_inc(&tcon->num_acl_get);
2834 cFYI(1, "Send error in Query POSIX ACL = %d", rc);
2836 /* decode response */
2838 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
2839 if (rc || (pSMBr->ByteCount < 2))
2840 /* BB also check enough total bytes returned */
2841 rc = -EIO; /* bad smb */
2843 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
2844 __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
2845 rc = cifs_copy_posix_acl(acl_inf,
2846 (char *)&pSMBr->hdr.Protocol+data_offset,
2847 buflen, acl_type, count);
2850 cifs_buf_release(pSMB);
2857 CIFSSMBSetPosixACL(const int xid, struct cifsTconInfo *tcon,
2858 const unsigned char *fileName,
2859 const char *local_acl, const int buflen,
2861 const struct nls_table *nls_codepage, int remap)
2863 struct smb_com_transaction2_spi_req *pSMB = NULL;
2864 struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
2868 int bytes_returned = 0;
2869 __u16 params, byte_count, data_count, param_offset, offset;
2871 cFYI(1, "In SetPosixACL (Unix) for path %s", fileName);
2873 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2877 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2879 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
2880 PATH_MAX, nls_codepage, remap);
2881 name_len++; /* trailing null */
2883 } else { /* BB improve the check for buffer overruns BB */
2884 name_len = strnlen(fileName, PATH_MAX);
2885 name_len++; /* trailing null */
2886 strncpy(pSMB->FileName, fileName, name_len);
2888 params = 6 + name_len;
2889 pSMB->MaxParameterCount = cpu_to_le16(2);
2890 /* BB find max SMB size from sess */
2891 pSMB->MaxDataCount = cpu_to_le16(1000);
2892 pSMB->MaxSetupCount = 0;
2896 pSMB->Reserved2 = 0;
2897 param_offset = offsetof(struct smb_com_transaction2_spi_req,
2898 InformationLevel) - 4;
2899 offset = param_offset + params;
2900 parm_data = ((char *) &pSMB->hdr.Protocol) + offset;
2901 pSMB->ParameterOffset = cpu_to_le16(param_offset);
2903 /* convert to on the wire format for POSIX ACL */
2904 data_count = ACL_to_cifs_posix(parm_data, local_acl, buflen, acl_type);
2906 if (data_count == 0) {
2908 goto setACLerrorExit;
2910 pSMB->DataOffset = cpu_to_le16(offset);
2911 pSMB->SetupCount = 1;
2912 pSMB->Reserved3 = 0;
2913 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
2914 pSMB->InformationLevel = cpu_to_le16(SMB_SET_POSIX_ACL);
2915 byte_count = 3 /* pad */ + params + data_count;
2916 pSMB->DataCount = cpu_to_le16(data_count);
2917 pSMB->TotalDataCount = pSMB->DataCount;
2918 pSMB->ParameterCount = cpu_to_le16(params);
2919 pSMB->TotalParameterCount = pSMB->ParameterCount;
2920 pSMB->Reserved4 = 0;
2921 pSMB->hdr.smb_buf_length += byte_count;
2922 pSMB->ByteCount = cpu_to_le16(byte_count);
2923 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2924 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2926 cFYI(1, "Set POSIX ACL returned %d", rc);
2929 cifs_buf_release(pSMB);
2935 /* BB fix tabs in this function FIXME BB */
2937 CIFSGetExtAttr(const int xid, struct cifsTconInfo *tcon,
2938 const int netfid, __u64 *pExtAttrBits, __u64 *pMask)
2941 struct smb_t2_qfi_req *pSMB = NULL;
2942 struct smb_t2_qfi_rsp *pSMBr = NULL;
2944 __u16 params, byte_count;
2946 cFYI(1, "In GetExtAttr");
2951 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2956 params = 2 /* level */ + 2 /* fid */;
2957 pSMB->t2.TotalDataCount = 0;
2958 pSMB->t2.MaxParameterCount = cpu_to_le16(4);
2959 /* BB find exact max data count below from sess structure BB */
2960 pSMB->t2.MaxDataCount = cpu_to_le16(4000);
2961 pSMB->t2.MaxSetupCount = 0;
2962 pSMB->t2.Reserved = 0;
2964 pSMB->t2.Timeout = 0;
2965 pSMB->t2.Reserved2 = 0;
2966 pSMB->t2.ParameterOffset = cpu_to_le16(offsetof(struct smb_t2_qfi_req,
2968 pSMB->t2.DataCount = 0;
2969 pSMB->t2.DataOffset = 0;
2970 pSMB->t2.SetupCount = 1;
2971 pSMB->t2.Reserved3 = 0;
2972 pSMB->t2.SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION);
2973 byte_count = params + 1 /* pad */ ;
2974 pSMB->t2.TotalParameterCount = cpu_to_le16(params);
2975 pSMB->t2.ParameterCount = pSMB->t2.TotalParameterCount;
2976 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_ATTR_FLAGS);
2979 pSMB->hdr.smb_buf_length += byte_count;
2980 pSMB->t2.ByteCount = cpu_to_le16(byte_count);
2982 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2983 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2985 cFYI(1, "error %d in GetExtAttr", rc);
2987 /* decode response */
2988 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
2989 if (rc || (pSMBr->ByteCount < 2))
2990 /* BB also check enough total bytes returned */
2991 /* If rc should we check for EOPNOSUPP and
2992 disable the srvino flag? or in caller? */
2993 rc = -EIO; /* bad smb */
2995 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
2996 __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
2997 struct file_chattr_info *pfinfo;
2998 /* BB Do we need a cast or hash here ? */
3000 cFYI(1, "Illegal size ret in GetExtAttr");
3004 pfinfo = (struct file_chattr_info *)
3005 (data_offset + (char *) &pSMBr->hdr.Protocol);
3006 *pExtAttrBits = le64_to_cpu(pfinfo->mode);
3007 *pMask = le64_to_cpu(pfinfo->mask);
3011 cifs_buf_release(pSMB);
3013 goto GetExtAttrRetry;
3017 #endif /* CONFIG_POSIX */
3019 #ifdef CONFIG_CIFS_ACL
3021 * Initialize NT TRANSACT SMB into small smb request buffer. This assumes that
3022 * all NT TRANSACTS that we init here have total parm and data under about 400
3023 * bytes (to fit in small cifs buffer size), which is the case so far, it
3024 * easily fits. NB: Setup words themselves and ByteCount MaxSetupCount (size of
3025 * returned setup area) and MaxParameterCount (returned parms size) must be set
3029 smb_init_nttransact(const __u16 sub_command, const int setup_count,
3030 const int parm_len, struct cifsTconInfo *tcon,
3035 struct smb_com_ntransact_req *pSMB;
3037 rc = small_smb_init(SMB_COM_NT_TRANSACT, 19 + setup_count, tcon,
3041 *ret_buf = (void *)pSMB;
3043 pSMB->TotalParameterCount = cpu_to_le32(parm_len);
3044 pSMB->TotalDataCount = 0;
3045 pSMB->MaxDataCount = cpu_to_le32((tcon->ses->server->maxBuf -
3046 MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
3047 pSMB->ParameterCount = pSMB->TotalParameterCount;
3048 pSMB->DataCount = pSMB->TotalDataCount;
3049 temp_offset = offsetof(struct smb_com_ntransact_req, Parms) +
3050 (setup_count * 2) - 4 /* for rfc1001 length itself */;
3051 pSMB->ParameterOffset = cpu_to_le32(temp_offset);
3052 pSMB->DataOffset = cpu_to_le32(temp_offset + parm_len);
3053 pSMB->SetupCount = setup_count; /* no need to le convert byte fields */
3054 pSMB->SubCommand = cpu_to_le16(sub_command);
3059 validate_ntransact(char *buf, char **ppparm, char **ppdata,
3060 __u32 *pparmlen, __u32 *pdatalen)
3063 __u32 data_count, data_offset, parm_count, parm_offset;
3064 struct smb_com_ntransact_rsp *pSMBr;
3072 pSMBr = (struct smb_com_ntransact_rsp *)buf;
3074 /* ByteCount was converted from little endian in SendReceive */
3075 end_of_smb = 2 /* sizeof byte count */ + pSMBr->ByteCount +
3076 (char *)&pSMBr->ByteCount;
3078 data_offset = le32_to_cpu(pSMBr->DataOffset);
3079 data_count = le32_to_cpu(pSMBr->DataCount);
3080 parm_offset = le32_to_cpu(pSMBr->ParameterOffset);
3081 parm_count = le32_to_cpu(pSMBr->ParameterCount);
3083 *ppparm = (char *)&pSMBr->hdr.Protocol + parm_offset;
3084 *ppdata = (char *)&pSMBr->hdr.Protocol + data_offset;
3086 /* should we also check that parm and data areas do not overlap? */
3087 if (*ppparm > end_of_smb) {
3088 cFYI(1, "parms start after end of smb");
3090 } else if (parm_count + *ppparm > end_of_smb) {
3091 cFYI(1, "parm end after end of smb");
3093 } else if (*ppdata > end_of_smb) {
3094 cFYI(1, "data starts after end of smb");
3096 } else if (data_count + *ppdata > end_of_smb) {
3097 cFYI(1, "data %p + count %d (%p) past smb end %p start %p",
3098 *ppdata, data_count, (data_count + *ppdata),
3101 } else if (parm_count + data_count > pSMBr->ByteCount) {
3102 cFYI(1, "parm count and data count larger than SMB");
3105 *pdatalen = data_count;
3106 *pparmlen = parm_count;
3110 /* Get Security Descriptor (by handle) from remote server for a file or dir */
3112 CIFSSMBGetCIFSACL(const int xid, struct cifsTconInfo *tcon, __u16 fid,
3113 struct cifs_ntsd **acl_inf, __u32 *pbuflen)
3117 QUERY_SEC_DESC_REQ *pSMB;
3120 cFYI(1, "GetCifsACL");
3125 rc = smb_init_nttransact(NT_TRANSACT_QUERY_SECURITY_DESC, 0,
3126 8 /* parm len */, tcon, (void **) &pSMB);
3130 pSMB->MaxParameterCount = cpu_to_le32(4);
3131 /* BB TEST with big acls that might need to be e.g. larger than 16K */
3132 pSMB->MaxSetupCount = 0;
3133 pSMB->Fid = fid; /* file handle always le */
3134 pSMB->AclFlags = cpu_to_le32(CIFS_ACL_OWNER | CIFS_ACL_GROUP |
3136 pSMB->ByteCount = cpu_to_le16(11); /* 3 bytes pad + 8 bytes parm */
3137 pSMB->hdr.smb_buf_length += 11;
3138 iov[0].iov_base = (char *)pSMB;
3139 iov[0].iov_len = pSMB->hdr.smb_buf_length + 4;
3141 rc = SendReceive2(xid, tcon->ses, iov, 1 /* num iovec */, &buf_type,
3143 cifs_stats_inc(&tcon->num_acl_get);
3145 cFYI(1, "Send error in QuerySecDesc = %d", rc);
3146 } else { /* decode response */
3150 struct smb_com_ntransact_rsp *pSMBr;
3153 /* validate_nttransact */
3154 rc = validate_ntransact(iov[0].iov_base, (char **)&parm,
3155 &pdata, &parm_len, pbuflen);
3158 pSMBr = (struct smb_com_ntransact_rsp *)iov[0].iov_base;
3160 cFYI(1, "smb %p parm %p data %p", pSMBr, parm, *acl_inf);
3162 if (le32_to_cpu(pSMBr->ParameterCount) != 4) {
3163 rc = -EIO; /* bad smb */
3168 /* BB check that data area is minimum length and as big as acl_len */
3170 acl_len = le32_to_cpu(*parm);
3171 if (acl_len != *pbuflen) {
3172 cERROR(1, "acl length %d does not match %d",
3174 if (*pbuflen > acl_len)
3178 /* check if buffer is big enough for the acl
3179 header followed by the smallest SID */
3180 if ((*pbuflen < sizeof(struct cifs_ntsd) + 8) ||
3181 (*pbuflen >= 64 * 1024)) {
3182 cERROR(1, "bad acl length %d", *pbuflen);
3186 *acl_inf = kmalloc(*pbuflen, GFP_KERNEL);
3187 if (*acl_inf == NULL) {
3191 memcpy(*acl_inf, pdata, *pbuflen);
3195 if (buf_type == CIFS_SMALL_BUFFER)
3196 cifs_small_buf_release(iov[0].iov_base);
3197 else if (buf_type == CIFS_LARGE_BUFFER)
3198 cifs_buf_release(iov[0].iov_base);
3199 /* cifs_small_buf_release(pSMB); */ /* Freed earlier now in SendReceive2 */
3204 CIFSSMBSetCIFSACL(const int xid, struct cifsTconInfo *tcon, __u16 fid,
3205 struct cifs_ntsd *pntsd, __u32 acllen)
3207 __u16 byte_count, param_count, data_count, param_offset, data_offset;
3209 int bytes_returned = 0;
3210 SET_SEC_DESC_REQ *pSMB = NULL;
3211 NTRANSACT_RSP *pSMBr = NULL;
3214 rc = smb_init(SMB_COM_NT_TRANSACT, 19, tcon, (void **) &pSMB,
3219 pSMB->MaxSetupCount = 0;
3223 param_offset = offsetof(struct smb_com_transaction_ssec_req, Fid) - 4;
3224 data_count = acllen;
3225 data_offset = param_offset + param_count;
3226 byte_count = 3 /* pad */ + param_count;
3228 pSMB->DataCount = cpu_to_le32(data_count);
3229 pSMB->TotalDataCount = pSMB->DataCount;
3230 pSMB->MaxParameterCount = cpu_to_le32(4);
3231 pSMB->MaxDataCount = cpu_to_le32(16384);
3232 pSMB->ParameterCount = cpu_to_le32(param_count);
3233 pSMB->ParameterOffset = cpu_to_le32(param_offset);
3234 pSMB->TotalParameterCount = pSMB->ParameterCount;
3235 pSMB->DataOffset = cpu_to_le32(data_offset);
3236 pSMB->SetupCount = 0;
3237 pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_SET_SECURITY_DESC);
3238 pSMB->ByteCount = cpu_to_le16(byte_count+data_count);
3240 pSMB->Fid = fid; /* file handle always le */
3241 pSMB->Reserved2 = 0;
3242 pSMB->AclFlags = cpu_to_le32(CIFS_ACL_DACL);
3244 if (pntsd && acllen) {
3245 memcpy((char *) &pSMBr->hdr.Protocol + data_offset,
3248 pSMB->hdr.smb_buf_length += (byte_count + data_count);
3251 pSMB->hdr.smb_buf_length += byte_count;
3253 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3254 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3256 cFYI(1, "SetCIFSACL bytes_returned: %d, rc: %d", bytes_returned, rc);
3258 cFYI(1, "Set CIFS ACL returned %d", rc);
3259 cifs_buf_release(pSMB);
3262 goto setCifsAclRetry;
3267 #endif /* CONFIG_CIFS_ACL */
3269 /* Legacy Query Path Information call for lookup to old servers such
3271 int SMBQueryInformation(const int xid, struct cifsTconInfo *tcon,
3272 const unsigned char *searchName,
3273 FILE_ALL_INFO *pFinfo,
3274 const struct nls_table *nls_codepage, int remap)
3276 QUERY_INFORMATION_REQ *pSMB;
3277 QUERY_INFORMATION_RSP *pSMBr;
3282 cFYI(1, "In SMBQPath path %s", searchName);
3284 rc = smb_init(SMB_COM_QUERY_INFORMATION, 0, tcon, (void **) &pSMB,
3289 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3291 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
3292 PATH_MAX, nls_codepage, remap);
3293 name_len++; /* trailing null */
3296 name_len = strnlen(searchName, PATH_MAX);
3297 name_len++; /* trailing null */
3298 strncpy(pSMB->FileName, searchName, name_len);
3300 pSMB->BufferFormat = 0x04;
3301 name_len++; /* account for buffer type byte */
3302 pSMB->hdr.smb_buf_length += (__u16) name_len;
3303 pSMB->ByteCount = cpu_to_le16(name_len);
3305 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3306 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3308 cFYI(1, "Send error in QueryInfo = %d", rc);
3309 } else if (pFinfo) {
3311 __u32 time = le32_to_cpu(pSMBr->last_write_time);
3313 /* decode response */
3314 /* BB FIXME - add time zone adjustment BB */
3315 memset(pFinfo, 0, sizeof(FILE_ALL_INFO));
3318 /* decode time fields */
3319 pFinfo->ChangeTime = cpu_to_le64(cifs_UnixTimeToNT(ts));
3320 pFinfo->LastWriteTime = pFinfo->ChangeTime;
3321 pFinfo->LastAccessTime = 0;
3322 pFinfo->AllocationSize =
3323 cpu_to_le64(le32_to_cpu(pSMBr->size));
3324 pFinfo->EndOfFile = pFinfo->AllocationSize;
3325 pFinfo->Attributes =
3326 cpu_to_le32(le16_to_cpu(pSMBr->attr));
3328 rc = -EIO; /* bad buffer passed in */
3330 cifs_buf_release(pSMB);
3339 CIFSSMBQFileInfo(const int xid, struct cifsTconInfo *tcon,
3340 u16 netfid, FILE_ALL_INFO *pFindData)
3342 struct smb_t2_qfi_req *pSMB = NULL;
3343 struct smb_t2_qfi_rsp *pSMBr = NULL;
3346 __u16 params, byte_count;
3349 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3354 params = 2 /* level */ + 2 /* fid */;
3355 pSMB->t2.TotalDataCount = 0;
3356 pSMB->t2.MaxParameterCount = cpu_to_le16(4);
3357 /* BB find exact max data count below from sess structure BB */
3358 pSMB->t2.MaxDataCount = cpu_to_le16(CIFSMaxBufSize);
3359 pSMB->t2.MaxSetupCount = 0;
3360 pSMB->t2.Reserved = 0;
3362 pSMB->t2.Timeout = 0;
3363 pSMB->t2.Reserved2 = 0;
3364 pSMB->t2.ParameterOffset = cpu_to_le16(offsetof(struct smb_t2_qfi_req,
3366 pSMB->t2.DataCount = 0;
3367 pSMB->t2.DataOffset = 0;
3368 pSMB->t2.SetupCount = 1;
3369 pSMB->t2.Reserved3 = 0;
3370 pSMB->t2.SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION);
3371 byte_count = params + 1 /* pad */ ;
3372 pSMB->t2.TotalParameterCount = cpu_to_le16(params);
3373 pSMB->t2.ParameterCount = pSMB->t2.TotalParameterCount;
3374 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_ALL_INFO);
3377 pSMB->hdr.smb_buf_length += byte_count;
3379 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3380 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3382 cFYI(1, "Send error in QPathInfo = %d", rc);
3383 } else { /* decode response */
3384 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3386 if (rc) /* BB add auto retry on EOPNOTSUPP? */
3388 else if (pSMBr->ByteCount < 40)
3389 rc = -EIO; /* bad smb */
3390 else if (pFindData) {
3391 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3392 memcpy((char *) pFindData,
3393 (char *) &pSMBr->hdr.Protocol +
3394 data_offset, sizeof(FILE_ALL_INFO));
3398 cifs_buf_release(pSMB);
3400 goto QFileInfoRetry;
3406 CIFSSMBQPathInfo(const int xid, struct cifsTconInfo *tcon,
3407 const unsigned char *searchName,
3408 FILE_ALL_INFO *pFindData,
3409 int legacy /* old style infolevel */,
3410 const struct nls_table *nls_codepage, int remap)
3412 /* level 263 SMB_QUERY_FILE_ALL_INFO */
3413 TRANSACTION2_QPI_REQ *pSMB = NULL;
3414 TRANSACTION2_QPI_RSP *pSMBr = NULL;
3418 __u16 params, byte_count;
3420 /* cFYI(1, "In QPathInfo path %s", searchName); */
3422 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3427 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3429 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
3430 PATH_MAX, nls_codepage, remap);
3431 name_len++; /* trailing null */
3433 } else { /* BB improve the check for buffer overruns BB */
3434 name_len = strnlen(searchName, PATH_MAX);
3435 name_len++; /* trailing null */
3436 strncpy(pSMB->FileName, searchName, name_len);
3439 params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */;
3440 pSMB->TotalDataCount = 0;
3441 pSMB->MaxParameterCount = cpu_to_le16(2);
3442 /* BB find exact max SMB PDU from sess structure BB */
3443 pSMB->MaxDataCount = cpu_to_le16(4000);
3444 pSMB->MaxSetupCount = 0;
3448 pSMB->Reserved2 = 0;
3449 pSMB->ParameterOffset = cpu_to_le16(offsetof(
3450 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
3451 pSMB->DataCount = 0;
3452 pSMB->DataOffset = 0;
3453 pSMB->SetupCount = 1;
3454 pSMB->Reserved3 = 0;
3455 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
3456 byte_count = params + 1 /* pad */ ;
3457 pSMB->TotalParameterCount = cpu_to_le16(params);
3458 pSMB->ParameterCount = pSMB->TotalParameterCount;
3460 pSMB->InformationLevel = cpu_to_le16(SMB_INFO_STANDARD);
3462 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_ALL_INFO);
3463 pSMB->Reserved4 = 0;
3464 pSMB->hdr.smb_buf_length += byte_count;
3465 pSMB->ByteCount = cpu_to_le16(byte_count);
3467 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3468 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3470 cFYI(1, "Send error in QPathInfo = %d", rc);
3471 } else { /* decode response */
3472 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3474 if (rc) /* BB add auto retry on EOPNOTSUPP? */
3476 else if (!legacy && (pSMBr->ByteCount < 40))
3477 rc = -EIO; /* bad smb */
3478 else if (legacy && (pSMBr->ByteCount < 24))
3479 rc = -EIO; /* 24 or 26 expected but we do not read
3481 else if (pFindData) {
3483 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3485 /* On legacy responses we do not read the last field,
3486 EAsize, fortunately since it varies by subdialect and
3487 also note it differs on Set vs. Get, ie two bytes or 4
3488 bytes depending but we don't care here */
3490 size = sizeof(FILE_INFO_STANDARD);
3492 size = sizeof(FILE_ALL_INFO);
3493 memcpy((char *) pFindData,
3494 (char *) &pSMBr->hdr.Protocol +
3499 cifs_buf_release(pSMB);
3501 goto QPathInfoRetry;
3507 CIFSSMBUnixQFileInfo(const int xid, struct cifsTconInfo *tcon,
3508 u16 netfid, FILE_UNIX_BASIC_INFO *pFindData)
3510 struct smb_t2_qfi_req *pSMB = NULL;
3511 struct smb_t2_qfi_rsp *pSMBr = NULL;
3514 __u16 params, byte_count;
3517 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3522 params = 2 /* level */ + 2 /* fid */;
3523 pSMB->t2.TotalDataCount = 0;
3524 pSMB->t2.MaxParameterCount = cpu_to_le16(4);
3525 /* BB find exact max data count below from sess structure BB */
3526 pSMB->t2.MaxDataCount = cpu_to_le16(CIFSMaxBufSize);
3527 pSMB->t2.MaxSetupCount = 0;
3528 pSMB->t2.Reserved = 0;
3530 pSMB->t2.Timeout = 0;
3531 pSMB->t2.Reserved2 = 0;
3532 pSMB->t2.ParameterOffset = cpu_to_le16(offsetof(struct smb_t2_qfi_req,
3534 pSMB->t2.DataCount = 0;
3535 pSMB->t2.DataOffset = 0;
3536 pSMB->t2.SetupCount = 1;
3537 pSMB->t2.Reserved3 = 0;
3538 pSMB->t2.SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION);
3539 byte_count = params + 1 /* pad */ ;
3540 pSMB->t2.TotalParameterCount = cpu_to_le16(params);
3541 pSMB->t2.ParameterCount = pSMB->t2.TotalParameterCount;
3542 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC);
3545 pSMB->hdr.smb_buf_length += byte_count;
3547 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3548 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3550 cFYI(1, "Send error in QPathInfo = %d", rc);
3551 } else { /* decode response */
3552 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3554 if (rc || (pSMBr->ByteCount < sizeof(FILE_UNIX_BASIC_INFO))) {
3555 cERROR(1, "Malformed FILE_UNIX_BASIC_INFO response.\n"
3556 "Unix Extensions can be disabled on mount "
3557 "by specifying the nosfu mount option.");
3558 rc = -EIO; /* bad smb */
3560 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3561 memcpy((char *) pFindData,
3562 (char *) &pSMBr->hdr.Protocol +
3564 sizeof(FILE_UNIX_BASIC_INFO));
3568 cifs_buf_release(pSMB);
3570 goto UnixQFileInfoRetry;
3576 CIFSSMBUnixQPathInfo(const int xid, struct cifsTconInfo *tcon,
3577 const unsigned char *searchName,
3578 FILE_UNIX_BASIC_INFO *pFindData,
3579 const struct nls_table *nls_codepage, int remap)
3581 /* SMB_QUERY_FILE_UNIX_BASIC */
3582 TRANSACTION2_QPI_REQ *pSMB = NULL;
3583 TRANSACTION2_QPI_RSP *pSMBr = NULL;
3585 int bytes_returned = 0;
3587 __u16 params, byte_count;
3589 cFYI(1, "In QPathInfo (Unix) the path %s", searchName);
3591 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3596 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3598 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
3599 PATH_MAX, nls_codepage, remap);
3600 name_len++; /* trailing null */
3602 } else { /* BB improve the check for buffer overruns BB */
3603 name_len = strnlen(searchName, PATH_MAX);
3604 name_len++; /* trailing null */
3605 strncpy(pSMB->FileName, searchName, name_len);
3608 params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */;
3609 pSMB->TotalDataCount = 0;
3610 pSMB->MaxParameterCount = cpu_to_le16(2);
3611 /* BB find exact max SMB PDU from sess structure BB */
3612 pSMB->MaxDataCount = cpu_to_le16(4000);
3613 pSMB->MaxSetupCount = 0;
3617 pSMB->Reserved2 = 0;
3618 pSMB->ParameterOffset = cpu_to_le16(offsetof(
3619 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
3620 pSMB->DataCount = 0;
3621 pSMB->DataOffset = 0;
3622 pSMB->SetupCount = 1;
3623 pSMB->Reserved3 = 0;
3624 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
3625 byte_count = params + 1 /* pad */ ;
3626 pSMB->TotalParameterCount = cpu_to_le16(params);
3627 pSMB->ParameterCount = pSMB->TotalParameterCount;
3628 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC);
3629 pSMB->Reserved4 = 0;
3630 pSMB->hdr.smb_buf_length += byte_count;
3631 pSMB->ByteCount = cpu_to_le16(byte_count);
3633 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3634 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3636 cFYI(1, "Send error in QPathInfo = %d", rc);
3637 } else { /* decode response */
3638 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3640 if (rc || (pSMBr->ByteCount < sizeof(FILE_UNIX_BASIC_INFO))) {
3641 cERROR(1, "Malformed FILE_UNIX_BASIC_INFO response.\n"
3642 "Unix Extensions can be disabled on mount "
3643 "by specifying the nosfu mount option.");
3644 rc = -EIO; /* bad smb */
3646 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3647 memcpy((char *) pFindData,
3648 (char *) &pSMBr->hdr.Protocol +
3650 sizeof(FILE_UNIX_BASIC_INFO));
3653 cifs_buf_release(pSMB);
3655 goto UnixQPathInfoRetry;
3660 /* xid, tcon, searchName and codepage are input parms, rest are returned */
3662 CIFSFindFirst(const int xid, struct cifsTconInfo *tcon,
3663 const char *searchName,
3664 const struct nls_table *nls_codepage,
3666 struct cifs_search_info *psrch_inf, int remap, const char dirsep)
3668 /* level 257 SMB_ */
3669 TRANSACTION2_FFIRST_REQ *pSMB = NULL;
3670 TRANSACTION2_FFIRST_RSP *pSMBr = NULL;
3671 T2_FFIRST_RSP_PARMS *parms;
3673 int bytes_returned = 0;
3675 __u16 params, byte_count;
3677 cFYI(1, "In FindFirst for %s", searchName);
3680 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3685 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3687 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
3688 PATH_MAX, nls_codepage, remap);
3689 /* We can not add the asterik earlier in case
3690 it got remapped to 0xF03A as if it were part of the
3691 directory name instead of a wildcard */
3693 pSMB->FileName[name_len] = dirsep;
3694 pSMB->FileName[name_len+1] = 0;
3695 pSMB->FileName[name_len+2] = '*';
3696 pSMB->FileName[name_len+3] = 0;
3697 name_len += 4; /* now the trailing null */
3698 pSMB->FileName[name_len] = 0; /* null terminate just in case */
3699 pSMB->FileName[name_len+1] = 0;
3701 } else { /* BB add check for overrun of SMB buf BB */
3702 name_len = strnlen(searchName, PATH_MAX);
3703 /* BB fix here and in unicode clause above ie
3704 if (name_len > buffersize-header)
3705 free buffer exit; BB */
3706 strncpy(pSMB->FileName, searchName, name_len);
3707 pSMB->FileName[name_len] = dirsep;
3708 pSMB->FileName[name_len+1] = '*';
3709 pSMB->FileName[name_len+2] = 0;
3713 params = 12 + name_len /* includes null */ ;
3714 pSMB->TotalDataCount = 0; /* no EAs */
3715 pSMB->MaxParameterCount = cpu_to_le16(10);
3716 pSMB->MaxDataCount = cpu_to_le16((tcon->ses->server->maxBuf -
3717 MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
3718 pSMB->MaxSetupCount = 0;
3722 pSMB->Reserved2 = 0;
3723 byte_count = params + 1 /* pad */ ;
3724 pSMB->TotalParameterCount = cpu_to_le16(params);
3725 pSMB->ParameterCount = pSMB->TotalParameterCount;
3726 pSMB->ParameterOffset = cpu_to_le16(
3727 offsetof(struct smb_com_transaction2_ffirst_req, SearchAttributes)
3729 pSMB->DataCount = 0;
3730 pSMB->DataOffset = 0;
3731 pSMB->SetupCount = 1; /* one byte, no need to make endian neutral */
3732 pSMB->Reserved3 = 0;
3733 pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_FIRST);
3734 pSMB->SearchAttributes =
3735 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
3737 pSMB->SearchCount = cpu_to_le16(CIFSMaxBufSize/sizeof(FILE_UNIX_INFO));
3738 pSMB->SearchFlags = cpu_to_le16(CIFS_SEARCH_CLOSE_AT_END |
3739 CIFS_SEARCH_RETURN_RESUME);
3740 pSMB->InformationLevel = cpu_to_le16(psrch_inf->info_level);
3742 /* BB what should we set StorageType to? Does it matter? BB */
3743 pSMB->SearchStorageType = 0;
3744 pSMB->hdr.smb_buf_length += byte_count;
3745 pSMB->ByteCount = cpu_to_le16(byte_count);
3747 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3748 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3749 cifs_stats_inc(&tcon->num_ffirst);
3751 if (rc) {/* BB add logic to retry regular search if Unix search
3752 rejected unexpectedly by server */
3753 /* BB Add code to handle unsupported level rc */
3754 cFYI(1, "Error in FindFirst = %d", rc);
3756 cifs_buf_release(pSMB);
3758 /* BB eventually could optimize out free and realloc of buf */
3761 goto findFirstRetry;
3762 } else { /* decode response */
3763 /* BB remember to free buffer if error BB */
3764 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3768 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
3769 psrch_inf->unicode = true;
3771 psrch_inf->unicode = false;
3773 psrch_inf->ntwrk_buf_start = (char *)pSMBr;
3774 psrch_inf->smallBuf = 0;
3775 psrch_inf->srch_entries_start =
3776 (char *) &pSMBr->hdr.Protocol +
3777 le16_to_cpu(pSMBr->t2.DataOffset);
3778 parms = (T2_FFIRST_RSP_PARMS *)((char *) &pSMBr->hdr.Protocol +
3779 le16_to_cpu(pSMBr->t2.ParameterOffset));
3781 if (parms->EndofSearch)
3782 psrch_inf->endOfSearch = true;
3784 psrch_inf->endOfSearch = false;
3786 psrch_inf->entries_in_buffer =
3787 le16_to_cpu(parms->SearchCount);
3788 psrch_inf->index_of_last_entry = 2 /* skip . and .. */ +
3789 psrch_inf->entries_in_buffer;
3790 lnoff = le16_to_cpu(parms->LastNameOffset);
3791 if (tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE <
3793 cERROR(1, "ignoring corrupt resume name");
3794 psrch_inf->last_entry = NULL;
3798 psrch_inf->last_entry = psrch_inf->srch_entries_start +
3801 *pnetfid = parms->SearchHandle;
3803 cifs_buf_release(pSMB);
3810 int CIFSFindNext(const int xid, struct cifsTconInfo *tcon,
3811 __u16 searchHandle, struct cifs_search_info *psrch_inf)
3813 TRANSACTION2_FNEXT_REQ *pSMB = NULL;
3814 TRANSACTION2_FNEXT_RSP *pSMBr = NULL;
3815 T2_FNEXT_RSP_PARMS *parms;
3816 char *response_data;
3818 int bytes_returned, name_len;
3819 __u16 params, byte_count;
3821 cFYI(1, "In FindNext");
3823 if (psrch_inf->endOfSearch)
3826 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3831 params = 14; /* includes 2 bytes of null string, converted to LE below*/
3833 pSMB->TotalDataCount = 0; /* no EAs */
3834 pSMB->MaxParameterCount = cpu_to_le16(8);
3835 pSMB->MaxDataCount =
3836 cpu_to_le16((tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE) &
3838 pSMB->MaxSetupCount = 0;
3842 pSMB->Reserved2 = 0;
3843 pSMB->ParameterOffset = cpu_to_le16(
3844 offsetof(struct smb_com_transaction2_fnext_req,SearchHandle) - 4);
3845 pSMB->DataCount = 0;
3846 pSMB->DataOffset = 0;
3847 pSMB->SetupCount = 1;
3848 pSMB->Reserved3 = 0;
3849 pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_NEXT);
3850 pSMB->SearchHandle = searchHandle; /* always kept as le */
3852 cpu_to_le16(CIFSMaxBufSize / sizeof(FILE_UNIX_INFO));
3853 pSMB->InformationLevel = cpu_to_le16(psrch_inf->info_level);
3854 pSMB->ResumeKey = psrch_inf->resume_key;
3856 cpu_to_le16(CIFS_SEARCH_CLOSE_AT_END | CIFS_SEARCH_RETURN_RESUME);
3858 name_len = psrch_inf->resume_name_len;
3860 if (name_len < PATH_MAX) {
3861 memcpy(pSMB->ResumeFileName, psrch_inf->presume_name, name_len);
3862 byte_count += name_len;
3863 /* 14 byte parm len above enough for 2 byte null terminator */
3864 pSMB->ResumeFileName[name_len] = 0;
3865 pSMB->ResumeFileName[name_len+1] = 0;
3868 goto FNext2_err_exit;
3870 byte_count = params + 1 /* pad */ ;
3871 pSMB->TotalParameterCount = cpu_to_le16(params);
3872 pSMB->ParameterCount = pSMB->TotalParameterCount;
3873 pSMB->hdr.smb_buf_length += byte_count;
3874 pSMB->ByteCount = cpu_to_le16(byte_count);
3876 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3877 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3878 cifs_stats_inc(&tcon->num_fnext);
3881 psrch_inf->endOfSearch = true;
3882 cifs_buf_release(pSMB);
3883 rc = 0; /* search probably was closed at end of search*/
3885 cFYI(1, "FindNext returned = %d", rc);
3886 } else { /* decode response */
3887 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3892 /* BB fixme add lock for file (srch_info) struct here */
3893 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
3894 psrch_inf->unicode = true;
3896 psrch_inf->unicode = false;
3897 response_data = (char *) &pSMBr->hdr.Protocol +
3898 le16_to_cpu(pSMBr->t2.ParameterOffset);
3899 parms = (T2_FNEXT_RSP_PARMS *)response_data;
3900 response_data = (char *)&pSMBr->hdr.Protocol +
3901 le16_to_cpu(pSMBr->t2.DataOffset);
3902 if (psrch_inf->smallBuf)
3903 cifs_small_buf_release(
3904 psrch_inf->ntwrk_buf_start);
3906 cifs_buf_release(psrch_inf->ntwrk_buf_start);
3907 psrch_inf->srch_entries_start = response_data;
3908 psrch_inf->ntwrk_buf_start = (char *)pSMB;
3909 psrch_inf->smallBuf = 0;
3910 if (parms->EndofSearch)
3911 psrch_inf->endOfSearch = true;
3913 psrch_inf->endOfSearch = false;
3914 psrch_inf->entries_in_buffer =
3915 le16_to_cpu(parms->SearchCount);
3916 psrch_inf->index_of_last_entry +=
3917 psrch_inf->entries_in_buffer;
3918 lnoff = le16_to_cpu(parms->LastNameOffset);
3919 if (tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE <
3921 cERROR(1, "ignoring corrupt resume name");
3922 psrch_inf->last_entry = NULL;
3925 psrch_inf->last_entry =
3926 psrch_inf->srch_entries_start + lnoff;
3928 /* cFYI(1, "fnxt2 entries in buf %d index_of_last %d",
3929 psrch_inf->entries_in_buffer, psrch_inf->index_of_last_entry); */
3931 /* BB fixme add unlock here */
3936 /* BB On error, should we leave previous search buf (and count and
3937 last entry fields) intact or free the previous one? */
3939 /* Note: On -EAGAIN error only caller can retry on handle based calls
3940 since file handle passed in no longer valid */
3943 cifs_buf_release(pSMB);
3948 CIFSFindClose(const int xid, struct cifsTconInfo *tcon,
3949 const __u16 searchHandle)
3952 FINDCLOSE_REQ *pSMB = NULL;
3954 cFYI(1, "In CIFSSMBFindClose");
3955 rc = small_smb_init(SMB_COM_FIND_CLOSE2, 1, tcon, (void **)&pSMB);
3957 /* no sense returning error if session restarted
3958 as file handle has been closed */
3964 pSMB->FileID = searchHandle;
3965 pSMB->ByteCount = 0;
3966 rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0);
3968 cERROR(1, "Send error in FindClose = %d", rc);
3970 cifs_stats_inc(&tcon->num_fclose);
3972 /* Since session is dead, search handle closed on server already */
3980 CIFSGetSrvInodeNumber(const int xid, struct cifsTconInfo *tcon,
3981 const unsigned char *searchName,
3982 __u64 *inode_number,
3983 const struct nls_table *nls_codepage, int remap)
3986 TRANSACTION2_QPI_REQ *pSMB = NULL;
3987 TRANSACTION2_QPI_RSP *pSMBr = NULL;
3988 int name_len, bytes_returned;
3989 __u16 params, byte_count;
3991 cFYI(1, "In GetSrvInodeNum for %s", searchName);
3995 GetInodeNumberRetry:
3996 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4001 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4003 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
4004 PATH_MAX, nls_codepage, remap);
4005 name_len++; /* trailing null */
4007 } else { /* BB improve the check for buffer overruns BB */
4008 name_len = strnlen(searchName, PATH_MAX);
4009 name_len++; /* trailing null */
4010 strncpy(pSMB->FileName, searchName, name_len);
4013 params = 2 /* level */ + 4 /* rsrvd */ + name_len /* incl null */ ;
4014 pSMB->TotalDataCount = 0;
4015 pSMB->MaxParameterCount = cpu_to_le16(2);
4016 /* BB find exact max data count below from sess structure BB */
4017 pSMB->MaxDataCount = cpu_to_le16(4000);
4018 pSMB->MaxSetupCount = 0;
4022 pSMB->Reserved2 = 0;
4023 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4024 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
4025 pSMB->DataCount = 0;
4026 pSMB->DataOffset = 0;
4027 pSMB->SetupCount = 1;
4028 pSMB->Reserved3 = 0;
4029 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
4030 byte_count = params + 1 /* pad */ ;
4031 pSMB->TotalParameterCount = cpu_to_le16(params);
4032 pSMB->ParameterCount = pSMB->TotalParameterCount;
4033 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_INTERNAL_INFO);
4034 pSMB->Reserved4 = 0;
4035 pSMB->hdr.smb_buf_length += byte_count;
4036 pSMB->ByteCount = cpu_to_le16(byte_count);
4038 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4039 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4041 cFYI(1, "error %d in QueryInternalInfo", rc);
4043 /* decode response */
4044 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4045 if (rc || (pSMBr->ByteCount < 2))
4046 /* BB also check enough total bytes returned */
4047 /* If rc should we check for EOPNOSUPP and
4048 disable the srvino flag? or in caller? */
4049 rc = -EIO; /* bad smb */
4051 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4052 __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
4053 struct file_internal_info *pfinfo;
4054 /* BB Do we need a cast or hash here ? */
4056 cFYI(1, "Illegal size ret in QryIntrnlInf");
4058 goto GetInodeNumOut;
4060 pfinfo = (struct file_internal_info *)
4061 (data_offset + (char *) &pSMBr->hdr.Protocol);
4062 *inode_number = le64_to_cpu(pfinfo->UniqueId);
4066 cifs_buf_release(pSMB);
4068 goto GetInodeNumberRetry;
4072 /* parses DFS refferal V3 structure
4073 * caller is responsible for freeing target_nodes
4076 * on failure - errno
4079 parse_DFS_referrals(TRANSACTION2_GET_DFS_REFER_RSP *pSMBr,
4080 unsigned int *num_of_nodes,
4081 struct dfs_info3_param **target_nodes,
4082 const struct nls_table *nls_codepage, int remap,
4083 const char *searchName)
4088 struct dfs_referral_level_3 *ref;
4090 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
4094 *num_of_nodes = le16_to_cpu(pSMBr->NumberOfReferrals);
4096 if (*num_of_nodes < 1) {
4097 cERROR(1, "num_referrals: must be at least > 0,"
4098 "but we get num_referrals = %d\n", *num_of_nodes);
4100 goto parse_DFS_referrals_exit;
4103 ref = (struct dfs_referral_level_3 *) &(pSMBr->referrals);
4104 if (ref->VersionNumber != cpu_to_le16(3)) {
4105 cERROR(1, "Referrals of V%d version are not supported,"
4106 "should be V3", le16_to_cpu(ref->VersionNumber));
4108 goto parse_DFS_referrals_exit;
4111 /* get the upper boundary of the resp buffer */
4112 data_end = (char *)(&(pSMBr->PathConsumed)) +
4113 le16_to_cpu(pSMBr->t2.DataCount);
4115 cFYI(1, "num_referrals: %d dfs flags: 0x%x ...\n",
4117 le32_to_cpu(pSMBr->DFSFlags));
4119 *target_nodes = kzalloc(sizeof(struct dfs_info3_param) *
4120 *num_of_nodes, GFP_KERNEL);
4121 if (*target_nodes == NULL) {
4122 cERROR(1, "Failed to allocate buffer for target_nodes\n");
4124 goto parse_DFS_referrals_exit;
4127 /* collect necessary data from referrals */
4128 for (i = 0; i < *num_of_nodes; i++) {
4131 struct dfs_info3_param *node = (*target_nodes)+i;
4133 node->flags = le32_to_cpu(pSMBr->DFSFlags);
4135 __le16 *tmp = kmalloc(strlen(searchName)*2 + 2,
4139 goto parse_DFS_referrals_exit;
4141 cifsConvertToUCS((__le16 *) tmp, searchName,
4142 PATH_MAX, nls_codepage, remap);
4143 node->path_consumed = cifs_ucs2_bytes(tmp,
4144 le16_to_cpu(pSMBr->PathConsumed),
4148 node->path_consumed = le16_to_cpu(pSMBr->PathConsumed);
4150 node->server_type = le16_to_cpu(ref->ServerType);
4151 node->ref_flag = le16_to_cpu(ref->ReferralEntryFlags);
4154 temp = (char *)ref + le16_to_cpu(ref->DfsPathOffset);
4155 max_len = data_end - temp;
4156 node->path_name = cifs_strndup_from_ucs(temp, max_len,
4157 is_unicode, nls_codepage);
4158 if (!node->path_name) {
4160 goto parse_DFS_referrals_exit;
4163 /* copy link target UNC */
4164 temp = (char *)ref + le16_to_cpu(ref->NetworkAddressOffset);
4165 max_len = data_end - temp;
4166 node->node_name = cifs_strndup_from_ucs(temp, max_len,
4167 is_unicode, nls_codepage);
4168 if (!node->node_name)
4172 parse_DFS_referrals_exit:
4174 free_dfs_info_array(*target_nodes, *num_of_nodes);
4175 *target_nodes = NULL;
4182 CIFSGetDFSRefer(const int xid, struct cifsSesInfo *ses,
4183 const unsigned char *searchName,
4184 struct dfs_info3_param **target_nodes,
4185 unsigned int *num_of_nodes,
4186 const struct nls_table *nls_codepage, int remap)
4188 /* TRANS2_GET_DFS_REFERRAL */
4189 TRANSACTION2_GET_DFS_REFER_REQ *pSMB = NULL;
4190 TRANSACTION2_GET_DFS_REFER_RSP *pSMBr = NULL;
4194 __u16 params, byte_count;
4196 *target_nodes = NULL;
4198 cFYI(1, "In GetDFSRefer the path %s", searchName);
4202 rc = smb_init(SMB_COM_TRANSACTION2, 15, NULL, (void **) &pSMB,
4207 /* server pointer checked in called function,
4208 but should never be null here anyway */
4209 pSMB->hdr.Mid = GetNextMid(ses->server);
4210 pSMB->hdr.Tid = ses->ipc_tid;
4211 pSMB->hdr.Uid = ses->Suid;
4212 if (ses->capabilities & CAP_STATUS32)
4213 pSMB->hdr.Flags2 |= SMBFLG2_ERR_STATUS;
4214 if (ses->capabilities & CAP_DFS)
4215 pSMB->hdr.Flags2 |= SMBFLG2_DFS;
4217 if (ses->capabilities & CAP_UNICODE) {
4218 pSMB->hdr.Flags2 |= SMBFLG2_UNICODE;
4220 cifsConvertToUCS((__le16 *) pSMB->RequestFileName,
4221 searchName, PATH_MAX, nls_codepage, remap);
4222 name_len++; /* trailing null */
4224 } else { /* BB improve the check for buffer overruns BB */
4225 name_len = strnlen(searchName, PATH_MAX);
4226 name_len++; /* trailing null */
4227 strncpy(pSMB->RequestFileName, searchName, name_len);
4231 if (ses->server->secMode &
4232 (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
4233 pSMB->hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
4236 pSMB->hdr.Uid = ses->Suid;
4238 params = 2 /* level */ + name_len /*includes null */ ;
4239 pSMB->TotalDataCount = 0;
4240 pSMB->DataCount = 0;
4241 pSMB->DataOffset = 0;
4242 pSMB->MaxParameterCount = 0;
4243 /* BB find exact max SMB PDU from sess structure BB */
4244 pSMB->MaxDataCount = cpu_to_le16(4000);
4245 pSMB->MaxSetupCount = 0;
4249 pSMB->Reserved2 = 0;
4250 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4251 struct smb_com_transaction2_get_dfs_refer_req, MaxReferralLevel) - 4);
4252 pSMB->SetupCount = 1;
4253 pSMB->Reserved3 = 0;
4254 pSMB->SubCommand = cpu_to_le16(TRANS2_GET_DFS_REFERRAL);
4255 byte_count = params + 3 /* pad */ ;
4256 pSMB->ParameterCount = cpu_to_le16(params);
4257 pSMB->TotalParameterCount = pSMB->ParameterCount;
4258 pSMB->MaxReferralLevel = cpu_to_le16(3);
4259 pSMB->hdr.smb_buf_length += byte_count;
4260 pSMB->ByteCount = cpu_to_le16(byte_count);
4262 rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB,
4263 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4265 cFYI(1, "Send error in GetDFSRefer = %d", rc);
4268 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4270 /* BB Also check if enough total bytes returned? */
4271 if (rc || (pSMBr->ByteCount < 17)) {
4272 rc = -EIO; /* bad smb */
4276 cFYI(1, "Decoding GetDFSRefer response BCC: %d Offset %d",
4278 le16_to_cpu(pSMBr->t2.DataOffset));
4280 /* parse returned result into more usable form */
4281 rc = parse_DFS_referrals(pSMBr, num_of_nodes,
4282 target_nodes, nls_codepage, remap,
4286 cifs_buf_release(pSMB);
4294 /* Query File System Info such as free space to old servers such as Win 9x */
4296 SMBOldQFSInfo(const int xid, struct cifsTconInfo *tcon, struct kstatfs *FSData)
4298 /* level 0x01 SMB_QUERY_FILE_SYSTEM_INFO */
4299 TRANSACTION2_QFSI_REQ *pSMB = NULL;
4300 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4301 FILE_SYSTEM_ALLOC_INFO *response_data;
4303 int bytes_returned = 0;
4304 __u16 params, byte_count;
4306 cFYI(1, "OldQFSInfo");
4308 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4313 params = 2; /* level */
4314 pSMB->TotalDataCount = 0;
4315 pSMB->MaxParameterCount = cpu_to_le16(2);
4316 pSMB->MaxDataCount = cpu_to_le16(1000);
4317 pSMB->MaxSetupCount = 0;
4321 pSMB->Reserved2 = 0;
4322 byte_count = params + 1 /* pad */ ;
4323 pSMB->TotalParameterCount = cpu_to_le16(params);
4324 pSMB->ParameterCount = pSMB->TotalParameterCount;
4325 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4326 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4327 pSMB->DataCount = 0;
4328 pSMB->DataOffset = 0;
4329 pSMB->SetupCount = 1;
4330 pSMB->Reserved3 = 0;
4331 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4332 pSMB->InformationLevel = cpu_to_le16(SMB_INFO_ALLOCATION);
4333 pSMB->hdr.smb_buf_length += byte_count;
4334 pSMB->ByteCount = cpu_to_le16(byte_count);
4336 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4337 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4339 cFYI(1, "Send error in QFSInfo = %d", rc);
4340 } else { /* decode response */
4341 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4343 if (rc || (pSMBr->ByteCount < 18))
4344 rc = -EIO; /* bad smb */
4346 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4347 cFYI(1, "qfsinf resp BCC: %d Offset %d",
4348 pSMBr->ByteCount, data_offset);
4350 response_data = (FILE_SYSTEM_ALLOC_INFO *)
4351 (((char *) &pSMBr->hdr.Protocol) + data_offset);
4353 le16_to_cpu(response_data->BytesPerSector) *
4354 le32_to_cpu(response_data->
4355 SectorsPerAllocationUnit);
4357 le32_to_cpu(response_data->TotalAllocationUnits);
4358 FSData->f_bfree = FSData->f_bavail =
4359 le32_to_cpu(response_data->FreeAllocationUnits);
4360 cFYI(1, "Blocks: %lld Free: %lld Block size %ld",
4361 (unsigned long long)FSData->f_blocks,
4362 (unsigned long long)FSData->f_bfree,
4366 cifs_buf_release(pSMB);
4369 goto oldQFSInfoRetry;
4375 CIFSSMBQFSInfo(const int xid, struct cifsTconInfo *tcon, struct kstatfs *FSData)
4377 /* level 0x103 SMB_QUERY_FILE_SYSTEM_INFO */
4378 TRANSACTION2_QFSI_REQ *pSMB = NULL;
4379 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4380 FILE_SYSTEM_INFO *response_data;
4382 int bytes_returned = 0;
4383 __u16 params, byte_count;
4385 cFYI(1, "In QFSInfo");
4387 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4392 params = 2; /* level */
4393 pSMB->TotalDataCount = 0;
4394 pSMB->MaxParameterCount = cpu_to_le16(2);
4395 pSMB->MaxDataCount = cpu_to_le16(1000);
4396 pSMB->MaxSetupCount = 0;
4400 pSMB->Reserved2 = 0;
4401 byte_count = params + 1 /* pad */ ;
4402 pSMB->TotalParameterCount = cpu_to_le16(params);
4403 pSMB->ParameterCount = pSMB->TotalParameterCount;
4404 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4405 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4406 pSMB->DataCount = 0;
4407 pSMB->DataOffset = 0;
4408 pSMB->SetupCount = 1;
4409 pSMB->Reserved3 = 0;
4410 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4411 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_SIZE_INFO);
4412 pSMB->hdr.smb_buf_length += byte_count;
4413 pSMB->ByteCount = cpu_to_le16(byte_count);
4415 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4416 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4418 cFYI(1, "Send error in QFSInfo = %d", rc);
4419 } else { /* decode response */
4420 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4422 if (rc || (pSMBr->ByteCount < 24))
4423 rc = -EIO; /* bad smb */
4425 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4429 *) (((char *) &pSMBr->hdr.Protocol) +
4432 le32_to_cpu(response_data->BytesPerSector) *
4433 le32_to_cpu(response_data->
4434 SectorsPerAllocationUnit);
4436 le64_to_cpu(response_data->TotalAllocationUnits);
4437 FSData->f_bfree = FSData->f_bavail =
4438 le64_to_cpu(response_data->FreeAllocationUnits);
4439 cFYI(1, "Blocks: %lld Free: %lld Block size %ld",
4440 (unsigned long long)FSData->f_blocks,
4441 (unsigned long long)FSData->f_bfree,
4445 cifs_buf_release(pSMB);
4454 CIFSSMBQFSAttributeInfo(const int xid, struct cifsTconInfo *tcon)
4456 /* level 0x105 SMB_QUERY_FILE_SYSTEM_INFO */
4457 TRANSACTION2_QFSI_REQ *pSMB = NULL;
4458 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4459 FILE_SYSTEM_ATTRIBUTE_INFO *response_data;
4461 int bytes_returned = 0;
4462 __u16 params, byte_count;
4464 cFYI(1, "In QFSAttributeInfo");
4466 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4471 params = 2; /* level */
4472 pSMB->TotalDataCount = 0;
4473 pSMB->MaxParameterCount = cpu_to_le16(2);
4474 /* BB find exact max SMB PDU from sess structure BB */
4475 pSMB->MaxDataCount = cpu_to_le16(1000);
4476 pSMB->MaxSetupCount = 0;
4480 pSMB->Reserved2 = 0;
4481 byte_count = params + 1 /* pad */ ;
4482 pSMB->TotalParameterCount = cpu_to_le16(params);
4483 pSMB->ParameterCount = pSMB->TotalParameterCount;
4484 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4485 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4486 pSMB->DataCount = 0;
4487 pSMB->DataOffset = 0;
4488 pSMB->SetupCount = 1;
4489 pSMB->Reserved3 = 0;
4490 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4491 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_ATTRIBUTE_INFO);
4492 pSMB->hdr.smb_buf_length += byte_count;
4493 pSMB->ByteCount = cpu_to_le16(byte_count);
4495 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4496 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4498 cERROR(1, "Send error in QFSAttributeInfo = %d", rc);
4499 } else { /* decode response */
4500 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4502 if (rc || (pSMBr->ByteCount < 13)) {
4503 /* BB also check if enough bytes returned */
4504 rc = -EIO; /* bad smb */
4506 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4508 (FILE_SYSTEM_ATTRIBUTE_INFO
4509 *) (((char *) &pSMBr->hdr.Protocol) +
4511 memcpy(&tcon->fsAttrInfo, response_data,
4512 sizeof(FILE_SYSTEM_ATTRIBUTE_INFO));
4515 cifs_buf_release(pSMB);
4518 goto QFSAttributeRetry;
4524 CIFSSMBQFSDeviceInfo(const int xid, struct cifsTconInfo *tcon)
4526 /* level 0x104 SMB_QUERY_FILE_SYSTEM_INFO */
4527 TRANSACTION2_QFSI_REQ *pSMB = NULL;
4528 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4529 FILE_SYSTEM_DEVICE_INFO *response_data;
4531 int bytes_returned = 0;
4532 __u16 params, byte_count;
4534 cFYI(1, "In QFSDeviceInfo");
4536 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4541 params = 2; /* level */
4542 pSMB->TotalDataCount = 0;
4543 pSMB->MaxParameterCount = cpu_to_le16(2);
4544 /* BB find exact max SMB PDU from sess structure BB */
4545 pSMB->MaxDataCount = cpu_to_le16(1000);
4546 pSMB->MaxSetupCount = 0;
4550 pSMB->Reserved2 = 0;
4551 byte_count = params + 1 /* pad */ ;
4552 pSMB->TotalParameterCount = cpu_to_le16(params);
4553 pSMB->ParameterCount = pSMB->TotalParameterCount;
4554 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4555 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4557 pSMB->DataCount = 0;
4558 pSMB->DataOffset = 0;
4559 pSMB->SetupCount = 1;
4560 pSMB->Reserved3 = 0;
4561 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4562 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_DEVICE_INFO);
4563 pSMB->hdr.smb_buf_length += byte_count;
4564 pSMB->ByteCount = cpu_to_le16(byte_count);
4566 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4567 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4569 cFYI(1, "Send error in QFSDeviceInfo = %d", rc);
4570 } else { /* decode response */
4571 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4573 if (rc || (pSMBr->ByteCount < sizeof(FILE_SYSTEM_DEVICE_INFO)))
4574 rc = -EIO; /* bad smb */
4576 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4578 (FILE_SYSTEM_DEVICE_INFO *)
4579 (((char *) &pSMBr->hdr.Protocol) +
4581 memcpy(&tcon->fsDevInfo, response_data,
4582 sizeof(FILE_SYSTEM_DEVICE_INFO));
4585 cifs_buf_release(pSMB);
4588 goto QFSDeviceRetry;
4594 CIFSSMBQFSUnixInfo(const int xid, struct cifsTconInfo *tcon)
4596 /* level 0x200 SMB_QUERY_CIFS_UNIX_INFO */
4597 TRANSACTION2_QFSI_REQ *pSMB = NULL;
4598 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4599 FILE_SYSTEM_UNIX_INFO *response_data;
4601 int bytes_returned = 0;
4602 __u16 params, byte_count;
4604 cFYI(1, "In QFSUnixInfo");
4606 rc = smb_init_no_reconnect(SMB_COM_TRANSACTION2, 15, tcon,
4607 (void **) &pSMB, (void **) &pSMBr);
4611 params = 2; /* level */
4612 pSMB->TotalDataCount = 0;
4613 pSMB->DataCount = 0;
4614 pSMB->DataOffset = 0;
4615 pSMB->MaxParameterCount = cpu_to_le16(2);
4616 /* BB find exact max SMB PDU from sess structure BB */
4617 pSMB->MaxDataCount = cpu_to_le16(100);
4618 pSMB->MaxSetupCount = 0;
4622 pSMB->Reserved2 = 0;
4623 byte_count = params + 1 /* pad */ ;
4624 pSMB->ParameterCount = cpu_to_le16(params);
4625 pSMB->TotalParameterCount = pSMB->ParameterCount;
4626 pSMB->ParameterOffset = cpu_to_le16(offsetof(struct
4627 smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4628 pSMB->SetupCount = 1;
4629 pSMB->Reserved3 = 0;
4630 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4631 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_CIFS_UNIX_INFO);
4632 pSMB->hdr.smb_buf_length += byte_count;
4633 pSMB->ByteCount = cpu_to_le16(byte_count);
4635 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4636 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4638 cERROR(1, "Send error in QFSUnixInfo = %d", rc);
4639 } else { /* decode response */
4640 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4642 if (rc || (pSMBr->ByteCount < 13)) {
4643 rc = -EIO; /* bad smb */
4645 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4647 (FILE_SYSTEM_UNIX_INFO
4648 *) (((char *) &pSMBr->hdr.Protocol) +
4650 memcpy(&tcon->fsUnixInfo, response_data,
4651 sizeof(FILE_SYSTEM_UNIX_INFO));
4654 cifs_buf_release(pSMB);
4664 CIFSSMBSetFSUnixInfo(const int xid, struct cifsTconInfo *tcon, __u64 cap)
4666 /* level 0x200 SMB_SET_CIFS_UNIX_INFO */
4667 TRANSACTION2_SETFSI_REQ *pSMB = NULL;
4668 TRANSACTION2_SETFSI_RSP *pSMBr = NULL;
4670 int bytes_returned = 0;
4671 __u16 params, param_offset, offset, byte_count;
4673 cFYI(1, "In SETFSUnixInfo");
4675 /* BB switch to small buf init to save memory */
4676 rc = smb_init_no_reconnect(SMB_COM_TRANSACTION2, 15, tcon,
4677 (void **) &pSMB, (void **) &pSMBr);
4681 params = 4; /* 2 bytes zero followed by info level. */
4682 pSMB->MaxSetupCount = 0;
4686 pSMB->Reserved2 = 0;
4687 param_offset = offsetof(struct smb_com_transaction2_setfsi_req, FileNum)
4689 offset = param_offset + params;
4691 pSMB->MaxParameterCount = cpu_to_le16(4);
4692 /* BB find exact max SMB PDU from sess structure BB */
4693 pSMB->MaxDataCount = cpu_to_le16(100);
4694 pSMB->SetupCount = 1;
4695 pSMB->Reserved3 = 0;
4696 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FS_INFORMATION);
4697 byte_count = 1 /* pad */ + params + 12;
4699 pSMB->DataCount = cpu_to_le16(12);
4700 pSMB->ParameterCount = cpu_to_le16(params);
4701 pSMB->TotalDataCount = pSMB->DataCount;
4702 pSMB->TotalParameterCount = pSMB->ParameterCount;
4703 pSMB->ParameterOffset = cpu_to_le16(param_offset);
4704 pSMB->DataOffset = cpu_to_le16(offset);
4708 pSMB->InformationLevel = cpu_to_le16(SMB_SET_CIFS_UNIX_INFO);
4711 pSMB->ClientUnixMajor = cpu_to_le16(CIFS_UNIX_MAJOR_VERSION);
4712 pSMB->ClientUnixMinor = cpu_to_le16(CIFS_UNIX_MINOR_VERSION);
4713 pSMB->ClientUnixCap = cpu_to_le64(cap);
4715 pSMB->hdr.smb_buf_length += byte_count;
4716 pSMB->ByteCount = cpu_to_le16(byte_count);
4718 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4719 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4721 cERROR(1, "Send error in SETFSUnixInfo = %d", rc);
4722 } else { /* decode response */
4723 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4725 rc = -EIO; /* bad smb */
4727 cifs_buf_release(pSMB);
4730 goto SETFSUnixRetry;
4738 CIFSSMBQFSPosixInfo(const int xid, struct cifsTconInfo *tcon,
4739 struct kstatfs *FSData)
4741 /* level 0x201 SMB_QUERY_CIFS_POSIX_INFO */
4742 TRANSACTION2_QFSI_REQ *pSMB = NULL;
4743 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4744 FILE_SYSTEM_POSIX_INFO *response_data;
4746 int bytes_returned = 0;
4747 __u16 params, byte_count;
4749 cFYI(1, "In QFSPosixInfo");
4751 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4756 params = 2; /* level */
4757 pSMB->TotalDataCount = 0;
4758 pSMB->DataCount = 0;
4759 pSMB->DataOffset = 0;
4760 pSMB->MaxParameterCount = cpu_to_le16(2);
4761 /* BB find exact max SMB PDU from sess structure BB */
4762 pSMB->MaxDataCount = cpu_to_le16(100);
4763 pSMB->MaxSetupCount = 0;
4767 pSMB->Reserved2 = 0;
4768 byte_count = params + 1 /* pad */ ;
4769 pSMB->ParameterCount = cpu_to_le16(params);
4770 pSMB->TotalParameterCount = pSMB->ParameterCount;
4771 pSMB->ParameterOffset = cpu_to_le16(offsetof(struct
4772 smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4773 pSMB->SetupCount = 1;
4774 pSMB->Reserved3 = 0;
4775 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4776 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_POSIX_FS_INFO);
4777 pSMB->hdr.smb_buf_length += byte_count;
4778 pSMB->ByteCount = cpu_to_le16(byte_count);
4780 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4781 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4783 cFYI(1, "Send error in QFSUnixInfo = %d", rc);
4784 } else { /* decode response */
4785 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4787 if (rc || (pSMBr->ByteCount < 13)) {
4788 rc = -EIO; /* bad smb */
4790 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4792 (FILE_SYSTEM_POSIX_INFO
4793 *) (((char *) &pSMBr->hdr.Protocol) +
4796 le32_to_cpu(response_data->BlockSize);
4798 le64_to_cpu(response_data->TotalBlocks);
4800 le64_to_cpu(response_data->BlocksAvail);
4801 if (response_data->UserBlocksAvail == cpu_to_le64(-1)) {
4802 FSData->f_bavail = FSData->f_bfree;
4805 le64_to_cpu(response_data->UserBlocksAvail);
4807 if (response_data->TotalFileNodes != cpu_to_le64(-1))
4809 le64_to_cpu(response_data->TotalFileNodes);
4810 if (response_data->FreeFileNodes != cpu_to_le64(-1))
4812 le64_to_cpu(response_data->FreeFileNodes);
4815 cifs_buf_release(pSMB);
4824 /* We can not use write of zero bytes trick to
4825 set file size due to need for large file support. Also note that
4826 this SetPathInfo is preferred to SetFileInfo based method in next
4827 routine which is only needed to work around a sharing violation bug
4828 in Samba which this routine can run into */
4831 CIFSSMBSetEOF(const int xid, struct cifsTconInfo *tcon, const char *fileName,
4832 __u64 size, bool SetAllocation,
4833 const struct nls_table *nls_codepage, int remap)
4835 struct smb_com_transaction2_spi_req *pSMB = NULL;
4836 struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
4837 struct file_end_of_file_info *parm_data;
4840 int bytes_returned = 0;
4841 __u16 params, byte_count, data_count, param_offset, offset;
4843 cFYI(1, "In SetEOF");
4845 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4850 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4852 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
4853 PATH_MAX, nls_codepage, remap);
4854 name_len++; /* trailing null */
4856 } else { /* BB improve the check for buffer overruns BB */
4857 name_len = strnlen(fileName, PATH_MAX);
4858 name_len++; /* trailing null */
4859 strncpy(pSMB->FileName, fileName, name_len);
4861 params = 6 + name_len;
4862 data_count = sizeof(struct file_end_of_file_info);
4863 pSMB->MaxParameterCount = cpu_to_le16(2);
4864 pSMB->MaxDataCount = cpu_to_le16(4100);
4865 pSMB->MaxSetupCount = 0;
4869 pSMB->Reserved2 = 0;
4870 param_offset = offsetof(struct smb_com_transaction2_spi_req,
4871 InformationLevel) - 4;
4872 offset = param_offset + params;
4873 if (SetAllocation) {
4874 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
4875 pSMB->InformationLevel =
4876 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2);
4878 pSMB->InformationLevel =
4879 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO);
4880 } else /* Set File Size */ {
4881 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
4882 pSMB->InformationLevel =
4883 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO2);
4885 pSMB->InformationLevel =
4886 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO);
4890 (struct file_end_of_file_info *) (((char *) &pSMB->hdr.Protocol) +
4892 pSMB->ParameterOffset = cpu_to_le16(param_offset);
4893 pSMB->DataOffset = cpu_to_le16(offset);
4894 pSMB->SetupCount = 1;
4895 pSMB->Reserved3 = 0;
4896 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
4897 byte_count = 3 /* pad */ + params + data_count;
4898 pSMB->DataCount = cpu_to_le16(data_count);
4899 pSMB->TotalDataCount = pSMB->DataCount;
4900 pSMB->ParameterCount = cpu_to_le16(params);
4901 pSMB->TotalParameterCount = pSMB->ParameterCount;
4902 pSMB->Reserved4 = 0;
4903 pSMB->hdr.smb_buf_length += byte_count;
4904 parm_data->FileSize = cpu_to_le64(size);
4905 pSMB->ByteCount = cpu_to_le16(byte_count);
4906 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4907 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4909 cFYI(1, "SetPathInfo (file size) returned %d", rc);
4911 cifs_buf_release(pSMB);
4920 CIFSSMBSetFileSize(const int xid, struct cifsTconInfo *tcon, __u64 size,
4921 __u16 fid, __u32 pid_of_opener, bool SetAllocation)
4923 struct smb_com_transaction2_sfi_req *pSMB = NULL;
4924 struct file_end_of_file_info *parm_data;
4926 __u16 params, param_offset, offset, byte_count, count;
4928 cFYI(1, "SetFileSize (via SetFileInfo) %lld",
4930 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
4935 pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
4936 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));
4939 pSMB->MaxSetupCount = 0;
4943 pSMB->Reserved2 = 0;
4944 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
4945 offset = param_offset + params;
4947 count = sizeof(struct file_end_of_file_info);
4948 pSMB->MaxParameterCount = cpu_to_le16(2);
4949 /* BB find exact max SMB PDU from sess structure BB */
4950 pSMB->MaxDataCount = cpu_to_le16(1000);
4951 pSMB->SetupCount = 1;
4952 pSMB->Reserved3 = 0;
4953 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
4954 byte_count = 3 /* pad */ + params + count;
4955 pSMB->DataCount = cpu_to_le16(count);
4956 pSMB->ParameterCount = cpu_to_le16(params);
4957 pSMB->TotalDataCount = pSMB->DataCount;
4958 pSMB->TotalParameterCount = pSMB->ParameterCount;
4959 pSMB->ParameterOffset = cpu_to_le16(param_offset);
4961 (struct file_end_of_file_info *) (((char *) &pSMB->hdr.Protocol)
4963 pSMB->DataOffset = cpu_to_le16(offset);
4964 parm_data->FileSize = cpu_to_le64(size);
4966 if (SetAllocation) {
4967 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
4968 pSMB->InformationLevel =
4969 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2);
4971 pSMB->InformationLevel =
4972 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO);
4973 } else /* Set File Size */ {
4974 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
4975 pSMB->InformationLevel =
4976 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO2);
4978 pSMB->InformationLevel =
4979 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO);
4981 pSMB->Reserved4 = 0;
4982 pSMB->hdr.smb_buf_length += byte_count;
4983 pSMB->ByteCount = cpu_to_le16(byte_count);
4984 rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0);
4986 cFYI(1, "Send error in SetFileInfo (SetFileSize) = %d", rc);
4989 /* Note: On -EAGAIN error only caller can retry on handle based calls
4990 since file handle passed in no longer valid */
4995 /* Some legacy servers such as NT4 require that the file times be set on
4996 an open handle, rather than by pathname - this is awkward due to
4997 potential access conflicts on the open, but it is unavoidable for these
4998 old servers since the only other choice is to go from 100 nanosecond DCE
4999 time and resort to the original setpathinfo level which takes the ancient
5000 DOS time format with 2 second granularity */
5002 CIFSSMBSetFileInfo(const int xid, struct cifsTconInfo *tcon,
5003 const FILE_BASIC_INFO *data, __u16 fid, __u32 pid_of_opener)
5005 struct smb_com_transaction2_sfi_req *pSMB = NULL;
5008 __u16 params, param_offset, offset, byte_count, count;
5010 cFYI(1, "Set Times (via SetFileInfo)");
5011 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
5016 pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
5017 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));
5020 pSMB->MaxSetupCount = 0;
5024 pSMB->Reserved2 = 0;
5025 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
5026 offset = param_offset + params;
5028 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
5030 count = sizeof(FILE_BASIC_INFO);
5031 pSMB->MaxParameterCount = cpu_to_le16(2);
5032 /* BB find max SMB PDU from sess */
5033 pSMB->MaxDataCount = cpu_to_le16(1000);
5034 pSMB->SetupCount = 1;
5035 pSMB->Reserved3 = 0;
5036 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
5037 byte_count = 3 /* pad */ + params + count;
5038 pSMB->DataCount = cpu_to_le16(count);
5039 pSMB->ParameterCount = cpu_to_le16(params);
5040 pSMB->TotalDataCount = pSMB->DataCount;
5041 pSMB->TotalParameterCount = pSMB->ParameterCount;
5042 pSMB->ParameterOffset = cpu_to_le16(param_offset);
5043 pSMB->DataOffset = cpu_to_le16(offset);
5045 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
5046 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO2);
5048 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO);
5049 pSMB->Reserved4 = 0;
5050 pSMB->hdr.smb_buf_length += byte_count;
5051 pSMB->ByteCount = cpu_to_le16(byte_count);
5052 memcpy(data_offset, data, sizeof(FILE_BASIC_INFO));
5053 rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0);
5055 cFYI(1, "Send error in Set Time (SetFileInfo) = %d", rc);
5057 /* Note: On -EAGAIN error only caller can retry on handle based calls
5058 since file handle passed in no longer valid */
5064 CIFSSMBSetFileDisposition(const int xid, struct cifsTconInfo *tcon,
5065 bool delete_file, __u16 fid, __u32 pid_of_opener)
5067 struct smb_com_transaction2_sfi_req *pSMB = NULL;
5070 __u16 params, param_offset, offset, byte_count, count;
5072 cFYI(1, "Set File Disposition (via SetFileInfo)");
5073 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
5078 pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
5079 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));
5082 pSMB->MaxSetupCount = 0;
5086 pSMB->Reserved2 = 0;
5087 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
5088 offset = param_offset + params;
5090 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
5093 pSMB->MaxParameterCount = cpu_to_le16(2);
5094 /* BB find max SMB PDU from sess */
5095 pSMB->MaxDataCount = cpu_to_le16(1000);
5096 pSMB->SetupCount = 1;
5097 pSMB->Reserved3 = 0;
5098 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
5099 byte_count = 3 /* pad */ + params + count;
5100 pSMB->DataCount = cpu_to_le16(count);
5101 pSMB->ParameterCount = cpu_to_le16(params);
5102 pSMB->TotalDataCount = pSMB->DataCount;
5103 pSMB->TotalParameterCount = pSMB->ParameterCount;
5104 pSMB->ParameterOffset = cpu_to_le16(param_offset);
5105 pSMB->DataOffset = cpu_to_le16(offset);
5107 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_DISPOSITION_INFO);
5108 pSMB->Reserved4 = 0;
5109 pSMB->hdr.smb_buf_length += byte_count;
5110 pSMB->ByteCount = cpu_to_le16(byte_count);
5111 *data_offset = delete_file ? 1 : 0;
5112 rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0);
5114 cFYI(1, "Send error in SetFileDisposition = %d", rc);
5120 CIFSSMBSetPathInfo(const int xid, struct cifsTconInfo *tcon,
5121 const char *fileName, const FILE_BASIC_INFO *data,
5122 const struct nls_table *nls_codepage, int remap)
5124 TRANSACTION2_SPI_REQ *pSMB = NULL;
5125 TRANSACTION2_SPI_RSP *pSMBr = NULL;
5128 int bytes_returned = 0;
5130 __u16 params, param_offset, offset, byte_count, count;
5132 cFYI(1, "In SetTimes");
5135 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5140 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5142 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
5143 PATH_MAX, nls_codepage, remap);
5144 name_len++; /* trailing null */
5146 } else { /* BB improve the check for buffer overruns BB */
5147 name_len = strnlen(fileName, PATH_MAX);
5148 name_len++; /* trailing null */
5149 strncpy(pSMB->FileName, fileName, name_len);
5152 params = 6 + name_len;
5153 count = sizeof(FILE_BASIC_INFO);
5154 pSMB->MaxParameterCount = cpu_to_le16(2);
5155 /* BB find max SMB PDU from sess structure BB */
5156 pSMB->MaxDataCount = cpu_to_le16(1000);
5157 pSMB->MaxSetupCount = 0;
5161 pSMB->Reserved2 = 0;
5162 param_offset = offsetof(struct smb_com_transaction2_spi_req,
5163 InformationLevel) - 4;
5164 offset = param_offset + params;
5165 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
5166 pSMB->ParameterOffset = cpu_to_le16(param_offset);
5167 pSMB->DataOffset = cpu_to_le16(offset);
5168 pSMB->SetupCount = 1;
5169 pSMB->Reserved3 = 0;
5170 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
5171 byte_count = 3 /* pad */ + params + count;
5173 pSMB->DataCount = cpu_to_le16(count);
5174 pSMB->ParameterCount = cpu_to_le16(params);
5175 pSMB->TotalDataCount = pSMB->DataCount;
5176 pSMB->TotalParameterCount = pSMB->ParameterCount;
5177 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
5178 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO2);
5180 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO);
5181 pSMB->Reserved4 = 0;
5182 pSMB->hdr.smb_buf_length += byte_count;
5183 memcpy(data_offset, data, sizeof(FILE_BASIC_INFO));
5184 pSMB->ByteCount = cpu_to_le16(byte_count);
5185 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5186 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5188 cFYI(1, "SetPathInfo (times) returned %d", rc);
5190 cifs_buf_release(pSMB);
5198 /* Can not be used to set time stamps yet (due to old DOS time format) */
5199 /* Can be used to set attributes */
5200 #if 0 /* Possibly not needed - since it turns out that strangely NT4 has a bug
5201 handling it anyway and NT4 was what we thought it would be needed for
5202 Do not delete it until we prove whether needed for Win9x though */
5204 CIFSSMBSetAttrLegacy(int xid, struct cifsTconInfo *tcon, char *fileName,
5205 __u16 dos_attrs, const struct nls_table *nls_codepage)
5207 SETATTR_REQ *pSMB = NULL;
5208 SETATTR_RSP *pSMBr = NULL;
5213 cFYI(1, "In SetAttrLegacy");
5216 rc = smb_init(SMB_COM_SETATTR, 8, tcon, (void **) &pSMB,
5221 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5223 ConvertToUCS((__le16 *) pSMB->fileName, fileName,
5224 PATH_MAX, nls_codepage);
5225 name_len++; /* trailing null */
5227 } else { /* BB improve the check for buffer overruns BB */
5228 name_len = strnlen(fileName, PATH_MAX);
5229 name_len++; /* trailing null */
5230 strncpy(pSMB->fileName, fileName, name_len);
5232 pSMB->attr = cpu_to_le16(dos_attrs);
5233 pSMB->BufferFormat = 0x04;
5234 pSMB->hdr.smb_buf_length += name_len + 1;
5235 pSMB->ByteCount = cpu_to_le16(name_len + 1);
5236 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5237 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5239 cFYI(1, "Error in LegacySetAttr = %d", rc);
5241 cifs_buf_release(pSMB);
5244 goto SetAttrLgcyRetry;
5248 #endif /* temporarily unneeded SetAttr legacy function */
5251 cifs_fill_unix_set_info(FILE_UNIX_BASIC_INFO *data_offset,
5252 const struct cifs_unix_set_info_args *args)
5254 u64 mode = args->mode;
5257 * Samba server ignores set of file size to zero due to bugs in some
5258 * older clients, but we should be precise - we use SetFileSize to
5259 * set file size and do not want to truncate file size to zero
5260 * accidentally as happened on one Samba server beta by putting
5261 * zero instead of -1 here
5263 data_offset->EndOfFile = cpu_to_le64(NO_CHANGE_64);
5264 data_offset->NumOfBytes = cpu_to_le64(NO_CHANGE_64);
5265 data_offset->LastStatusChange = cpu_to_le64(args->ctime);
5266 data_offset->LastAccessTime = cpu_to_le64(args->atime);
5267 data_offset->LastModificationTime = cpu_to_le64(args->mtime);
5268 data_offset->Uid = cpu_to_le64(args->uid);
5269 data_offset->Gid = cpu_to_le64(args->gid);
5270 /* better to leave device as zero when it is */
5271 data_offset->DevMajor = cpu_to_le64(MAJOR(args->device));
5272 data_offset->DevMinor = cpu_to_le64(MINOR(args->device));
5273 data_offset->Permissions = cpu_to_le64(mode);
5276 data_offset->Type = cpu_to_le32(UNIX_FILE);
5277 else if (S_ISDIR(mode))
5278 data_offset->Type = cpu_to_le32(UNIX_DIR);
5279 else if (S_ISLNK(mode))
5280 data_offset->Type = cpu_to_le32(UNIX_SYMLINK);
5281 else if (S_ISCHR(mode))
5282 data_offset->Type = cpu_to_le32(UNIX_CHARDEV);
5283 else if (S_ISBLK(mode))
5284 data_offset->Type = cpu_to_le32(UNIX_BLOCKDEV);
5285 else if (S_ISFIFO(mode))
5286 data_offset->Type = cpu_to_le32(UNIX_FIFO);
5287 else if (S_ISSOCK(mode))
5288 data_offset->Type = cpu_to_le32(UNIX_SOCKET);
5292 CIFSSMBUnixSetFileInfo(const int xid, struct cifsTconInfo *tcon,
5293 const struct cifs_unix_set_info_args *args,
5294 u16 fid, u32 pid_of_opener)
5296 struct smb_com_transaction2_sfi_req *pSMB = NULL;
5297 FILE_UNIX_BASIC_INFO *data_offset;
5299 u16 params, param_offset, offset, byte_count, count;
5301 cFYI(1, "Set Unix Info (via SetFileInfo)");
5302 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
5307 pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
5308 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));
5311 pSMB->MaxSetupCount = 0;
5315 pSMB->Reserved2 = 0;
5316 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
5317 offset = param_offset + params;
5319 data_offset = (FILE_UNIX_BASIC_INFO *)
5320 ((char *)(&pSMB->hdr.Protocol) + offset);
5321 count = sizeof(FILE_UNIX_BASIC_INFO);
5323 pSMB->MaxParameterCount = cpu_to_le16(2);
5324 /* BB find max SMB PDU from sess */
5325 pSMB->MaxDataCount = cpu_to_le16(1000);
5326 pSMB->SetupCount = 1;
5327 pSMB->Reserved3 = 0;
5328 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
5329 byte_count = 3 /* pad */ + params + count;
5330 pSMB->DataCount = cpu_to_le16(count);
5331 pSMB->ParameterCount = cpu_to_le16(params);
5332 pSMB->TotalDataCount = pSMB->DataCount;
5333 pSMB->TotalParameterCount = pSMB->ParameterCount;
5334 pSMB->ParameterOffset = cpu_to_le16(param_offset);
5335 pSMB->DataOffset = cpu_to_le16(offset);
5337 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_BASIC);
5338 pSMB->Reserved4 = 0;
5339 pSMB->hdr.smb_buf_length += byte_count;
5340 pSMB->ByteCount = cpu_to_le16(byte_count);
5342 cifs_fill_unix_set_info(data_offset, args);
5344 rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0);
5346 cFYI(1, "Send error in Set Time (SetFileInfo) = %d", rc);
5348 /* Note: On -EAGAIN error only caller can retry on handle based calls
5349 since file handle passed in no longer valid */
5355 CIFSSMBUnixSetPathInfo(const int xid, struct cifsTconInfo *tcon, char *fileName,
5356 const struct cifs_unix_set_info_args *args,
5357 const struct nls_table *nls_codepage, int remap)
5359 TRANSACTION2_SPI_REQ *pSMB = NULL;
5360 TRANSACTION2_SPI_RSP *pSMBr = NULL;
5363 int bytes_returned = 0;
5364 FILE_UNIX_BASIC_INFO *data_offset;
5365 __u16 params, param_offset, offset, count, byte_count;
5367 cFYI(1, "In SetUID/GID/Mode");
5369 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5374 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5376 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
5377 PATH_MAX, nls_codepage, remap);
5378 name_len++; /* trailing null */
5380 } else { /* BB improve the check for buffer overruns BB */
5381 name_len = strnlen(fileName, PATH_MAX);
5382 name_len++; /* trailing null */
5383 strncpy(pSMB->FileName, fileName, name_len);
5386 params = 6 + name_len;
5387 count = sizeof(FILE_UNIX_BASIC_INFO);
5388 pSMB->MaxParameterCount = cpu_to_le16(2);
5389 /* BB find max SMB PDU from sess structure BB */
5390 pSMB->MaxDataCount = cpu_to_le16(1000);
5391 pSMB->MaxSetupCount = 0;
5395 pSMB->Reserved2 = 0;
5396 param_offset = offsetof(struct smb_com_transaction2_spi_req,
5397 InformationLevel) - 4;
5398 offset = param_offset + params;
5400 (FILE_UNIX_BASIC_INFO *) ((char *) &pSMB->hdr.Protocol +
5402 memset(data_offset, 0, count);
5403 pSMB->DataOffset = cpu_to_le16(offset);
5404 pSMB->ParameterOffset = cpu_to_le16(param_offset);
5405 pSMB->SetupCount = 1;
5406 pSMB->Reserved3 = 0;
5407 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
5408 byte_count = 3 /* pad */ + params + count;
5409 pSMB->ParameterCount = cpu_to_le16(params);
5410 pSMB->DataCount = cpu_to_le16(count);
5411 pSMB->TotalParameterCount = pSMB->ParameterCount;
5412 pSMB->TotalDataCount = pSMB->DataCount;
5413 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_BASIC);
5414 pSMB->Reserved4 = 0;
5415 pSMB->hdr.smb_buf_length += byte_count;
5417 cifs_fill_unix_set_info(data_offset, args);
5419 pSMB->ByteCount = cpu_to_le16(byte_count);
5420 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5421 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5423 cFYI(1, "SetPathInfo (perms) returned %d", rc);
5425 cifs_buf_release(pSMB);
5431 #ifdef CONFIG_CIFS_XATTR
5433 * Do a path-based QUERY_ALL_EAS call and parse the result. This is a common
5434 * function used by listxattr and getxattr type calls. When ea_name is set,
5435 * it looks for that attribute name and stuffs that value into the EAData
5436 * buffer. When ea_name is NULL, it stuffs a list of attribute names into the
5437 * buffer. In both cases, the return value is either the length of the
5438 * resulting data or a negative error code. If EAData is a NULL pointer then
5439 * the data isn't copied to it, but the length is returned.
5442 CIFSSMBQAllEAs(const int xid, struct cifsTconInfo *tcon,
5443 const unsigned char *searchName, const unsigned char *ea_name,
5444 char *EAData, size_t buf_size,
5445 const struct nls_table *nls_codepage, int remap)
5447 /* BB assumes one setup word */
5448 TRANSACTION2_QPI_REQ *pSMB = NULL;
5449 TRANSACTION2_QPI_RSP *pSMBr = NULL;
5453 struct fealist *ea_response_data;
5454 struct fea *temp_fea;
5457 __u16 params, byte_count, data_offset;
5459 cFYI(1, "In Query All EAs path %s", searchName);
5461 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5466 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5468 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
5469 PATH_MAX, nls_codepage, remap);
5470 list_len++; /* trailing null */
5472 } else { /* BB improve the check for buffer overruns BB */
5473 list_len = strnlen(searchName, PATH_MAX);
5474 list_len++; /* trailing null */
5475 strncpy(pSMB->FileName, searchName, list_len);
5478 params = 2 /* level */ + 4 /* reserved */ + list_len /* includes NUL */;
5479 pSMB->TotalDataCount = 0;
5480 pSMB->MaxParameterCount = cpu_to_le16(2);
5481 /* BB find exact max SMB PDU from sess structure BB */
5482 pSMB->MaxDataCount = cpu_to_le16(CIFSMaxBufSize);
5483 pSMB->MaxSetupCount = 0;
5487 pSMB->Reserved2 = 0;
5488 pSMB->ParameterOffset = cpu_to_le16(offsetof(
5489 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
5490 pSMB->DataCount = 0;
5491 pSMB->DataOffset = 0;
5492 pSMB->SetupCount = 1;
5493 pSMB->Reserved3 = 0;
5494 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
5495 byte_count = params + 1 /* pad */ ;
5496 pSMB->TotalParameterCount = cpu_to_le16(params);
5497 pSMB->ParameterCount = pSMB->TotalParameterCount;
5498 pSMB->InformationLevel = cpu_to_le16(SMB_INFO_QUERY_ALL_EAS);
5499 pSMB->Reserved4 = 0;
5500 pSMB->hdr.smb_buf_length += byte_count;
5501 pSMB->ByteCount = cpu_to_le16(byte_count);
5503 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5504 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5506 cFYI(1, "Send error in QueryAllEAs = %d", rc);
5511 /* BB also check enough total bytes returned */
5512 /* BB we need to improve the validity checking
5513 of these trans2 responses */
5515 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
5516 if (rc || (pSMBr->ByteCount < 4)) {
5517 rc = -EIO; /* bad smb */
5521 /* check that length of list is not more than bcc */
5522 /* check that each entry does not go beyond length
5524 /* check that each element of each entry does not
5525 go beyond end of list */
5526 /* validate_trans2_offsets() */
5527 /* BB check if start of smb + data_offset > &bcc+ bcc */
5529 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
5530 ea_response_data = (struct fealist *)
5531 (((char *) &pSMBr->hdr.Protocol) + data_offset);
5533 list_len = le32_to_cpu(ea_response_data->list_len);
5534 cFYI(1, "ea length %d", list_len);
5535 if (list_len <= 8) {
5536 cFYI(1, "empty EA list returned from server");
5540 /* make sure list_len doesn't go past end of SMB */
5541 end_of_smb = (char *)pByteArea(&pSMBr->hdr) + get_bcc(&pSMBr->hdr);
5542 if ((char *)ea_response_data + list_len > end_of_smb) {
5543 cFYI(1, "EA list appears to go beyond SMB");
5548 /* account for ea list len */
5550 temp_fea = ea_response_data->list;
5551 temp_ptr = (char *)temp_fea;
5552 while (list_len > 0) {
5553 unsigned int name_len;
5558 /* make sure we can read name_len and value_len */
5560 cFYI(1, "EA entry goes beyond length of list");
5565 name_len = temp_fea->name_len;
5566 value_len = le16_to_cpu(temp_fea->value_len);
5567 list_len -= name_len + 1 + value_len;
5569 cFYI(1, "EA entry goes beyond length of list");
5575 if (strncmp(ea_name, temp_ptr, name_len) == 0) {
5576 temp_ptr += name_len + 1;
5580 if ((size_t)value_len > buf_size) {
5584 memcpy(EAData, temp_ptr, value_len);
5588 /* account for prefix user. and trailing null */
5589 rc += (5 + 1 + name_len);
5590 if (rc < (int) buf_size) {
5591 memcpy(EAData, "user.", 5);
5593 memcpy(EAData, temp_ptr, name_len);
5595 /* null terminate name */
5598 } else if (buf_size == 0) {
5599 /* skip copy - calc size only */
5601 /* stop before overrun buffer */
5606 temp_ptr += name_len + 1 + value_len;
5607 temp_fea = (struct fea *)temp_ptr;
5610 /* didn't find the named attribute */
5615 cifs_buf_release(pSMB);
5623 CIFSSMBSetEA(const int xid, struct cifsTconInfo *tcon, const char *fileName,
5624 const char *ea_name, const void *ea_value,
5625 const __u16 ea_value_len, const struct nls_table *nls_codepage,
5628 struct smb_com_transaction2_spi_req *pSMB = NULL;
5629 struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
5630 struct fealist *parm_data;
5633 int bytes_returned = 0;
5634 __u16 params, param_offset, byte_count, offset, count;
5636 cFYI(1, "In SetEA");
5638 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5643 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5645 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
5646 PATH_MAX, nls_codepage, remap);
5647 name_len++; /* trailing null */
5649 } else { /* BB improve the check for buffer overruns BB */
5650 name_len = strnlen(fileName, PATH_MAX);
5651 name_len++; /* trailing null */
5652 strncpy(pSMB->FileName, fileName, name_len);
5655 params = 6 + name_len;
5657 /* done calculating parms using name_len of file name,
5658 now use name_len to calculate length of ea name
5659 we are going to create in the inode xattrs */
5660 if (ea_name == NULL)
5663 name_len = strnlen(ea_name, 255);
5665 count = sizeof(*parm_data) + ea_value_len + name_len;
5666 pSMB->MaxParameterCount = cpu_to_le16(2);
5667 /* BB find max SMB PDU from sess */
5668 pSMB->MaxDataCount = cpu_to_le16(1000);
5669 pSMB->MaxSetupCount = 0;
5673 pSMB->Reserved2 = 0;
5674 param_offset = offsetof(struct smb_com_transaction2_spi_req,
5675 InformationLevel) - 4;
5676 offset = param_offset + params;
5677 pSMB->InformationLevel =
5678 cpu_to_le16(SMB_SET_FILE_EA);
5681 (struct fealist *) (((char *) &pSMB->hdr.Protocol) +
5683 pSMB->ParameterOffset = cpu_to_le16(param_offset);
5684 pSMB->DataOffset = cpu_to_le16(offset);
5685 pSMB->SetupCount = 1;
5686 pSMB->Reserved3 = 0;
5687 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
5688 byte_count = 3 /* pad */ + params + count;
5689 pSMB->DataCount = cpu_to_le16(count);
5690 parm_data->list_len = cpu_to_le32(count);
5691 parm_data->list[0].EA_flags = 0;
5692 /* we checked above that name len is less than 255 */
5693 parm_data->list[0].name_len = (__u8)name_len;
5694 /* EA names are always ASCII */
5696 strncpy(parm_data->list[0].name, ea_name, name_len);
5697 parm_data->list[0].name[name_len] = 0;
5698 parm_data->list[0].value_len = cpu_to_le16(ea_value_len);
5699 /* caller ensures that ea_value_len is less than 64K but
5700 we need to ensure that it fits within the smb */
5702 /*BB add length check to see if it would fit in
5703 negotiated SMB buffer size BB */
5704 /* if (ea_value_len > buffer_size - 512 (enough for header)) */
5706 memcpy(parm_data->list[0].name+name_len+1,
5707 ea_value, ea_value_len);
5709 pSMB->TotalDataCount = pSMB->DataCount;
5710 pSMB->ParameterCount = cpu_to_le16(params);
5711 pSMB->TotalParameterCount = pSMB->ParameterCount;
5712 pSMB->Reserved4 = 0;
5713 pSMB->hdr.smb_buf_length += byte_count;
5714 pSMB->ByteCount = cpu_to_le16(byte_count);
5715 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5716 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5718 cFYI(1, "SetPathInfo (EA) returned %d", rc);
5720 cifs_buf_release(pSMB);
5729 #ifdef CONFIG_CIFS_DNOTIFY_EXPERIMENTAL /* BB unused temporarily */
5731 * Years ago the kernel added a "dnotify" function for Samba server,
5732 * to allow network clients (such as Windows) to display updated
5733 * lists of files in directory listings automatically when
5734 * files are added by one user when another user has the
5735 * same directory open on their desktop. The Linux cifs kernel
5736 * client hooked into the kernel side of this interface for
5737 * the same reason, but ironically when the VFS moved from
5738 * "dnotify" to "inotify" it became harder to plug in Linux
5739 * network file system clients (the most obvious use case
5740 * for notify interfaces is when multiple users can update
5741 * the contents of the same directory - exactly what network
5742 * file systems can do) although the server (Samba) could
5743 * still use it. For the short term we leave the worker
5744 * function ifdeffed out (below) until inotify is fixed
5745 * in the VFS to make it easier to plug in network file
5746 * system clients. If inotify turns out to be permanently
5747 * incompatible for network fs clients, we could instead simply
5748 * expose this config flag by adding a future cifs (and smb2) notify ioctl.
5750 int CIFSSMBNotify(const int xid, struct cifsTconInfo *tcon,
5751 const int notify_subdirs, const __u16 netfid,
5752 __u32 filter, struct file *pfile, int multishot,
5753 const struct nls_table *nls_codepage)
5756 struct smb_com_transaction_change_notify_req *pSMB = NULL;
5757 struct smb_com_ntransaction_change_notify_rsp *pSMBr = NULL;
5758 struct dir_notify_req *dnotify_req;
5761 cFYI(1, "In CIFSSMBNotify for file handle %d", (int)netfid);
5762 rc = smb_init(SMB_COM_NT_TRANSACT, 23, tcon, (void **) &pSMB,
5767 pSMB->TotalParameterCount = 0 ;
5768 pSMB->TotalDataCount = 0;
5769 pSMB->MaxParameterCount = cpu_to_le32(2);
5770 /* BB find exact data count max from sess structure BB */
5771 pSMB->MaxDataCount = 0; /* same in little endian or be */
5772 /* BB VERIFY verify which is correct for above BB */
5773 pSMB->MaxDataCount = cpu_to_le32((tcon->ses->server->maxBuf -
5774 MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
5776 pSMB->MaxSetupCount = 4;
5778 pSMB->ParameterOffset = 0;
5779 pSMB->DataCount = 0;
5780 pSMB->DataOffset = 0;
5781 pSMB->SetupCount = 4; /* single byte does not need le conversion */
5782 pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_NOTIFY_CHANGE);
5783 pSMB->ParameterCount = pSMB->TotalParameterCount;
5785 pSMB->WatchTree = 1; /* one byte - no le conversion needed */
5786 pSMB->Reserved2 = 0;
5787 pSMB->CompletionFilter = cpu_to_le32(filter);
5788 pSMB->Fid = netfid; /* file handle always le */
5789 pSMB->ByteCount = 0;
5791 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5792 (struct smb_hdr *)pSMBr, &bytes_returned,
5795 cFYI(1, "Error in Notify = %d", rc);
5797 /* Add file to outstanding requests */
5798 /* BB change to kmem cache alloc */
5799 dnotify_req = kmalloc(
5800 sizeof(struct dir_notify_req),
5803 dnotify_req->Pid = pSMB->hdr.Pid;
5804 dnotify_req->PidHigh = pSMB->hdr.PidHigh;
5805 dnotify_req->Mid = pSMB->hdr.Mid;
5806 dnotify_req->Tid = pSMB->hdr.Tid;
5807 dnotify_req->Uid = pSMB->hdr.Uid;
5808 dnotify_req->netfid = netfid;
5809 dnotify_req->pfile = pfile;
5810 dnotify_req->filter = filter;
5811 dnotify_req->multishot = multishot;
5812 spin_lock(&GlobalMid_Lock);
5813 list_add_tail(&dnotify_req->lhead,
5814 &GlobalDnotifyReqList);
5815 spin_unlock(&GlobalMid_Lock);
5819 cifs_buf_release(pSMB);
5822 #endif /* was needed for dnotify, and will be needed for inotify when VFS fix */