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 total_size = get_unaligned_le16(&pSMB->t2_rsp.ParameterCount);
343 if (total_size >= 512)
346 /* check that bcc is at least as big as parms + data, and that it is
347 * less than negotiated smb buffer
349 total_size += get_unaligned_le16(&pSMB->t2_rsp.DataCount);
350 if (total_size > get_bcc(&pSMB->hdr) ||
351 total_size >= CIFSMaxBufSize + MAX_CIFS_HDR_SIZE)
356 cifs_dump_mem("Invalid transact2 SMB: ", (char *)pSMB,
357 sizeof(struct smb_t2_rsp) + 16);
361 static inline void inc_rfc1001_len(void *pSMB, int count)
363 struct smb_hdr *hdr = (struct smb_hdr *)pSMB;
365 be32_add_cpu(&hdr->smb_buf_length, count);
369 CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses)
372 NEGOTIATE_RSP *pSMBr;
376 struct TCP_Server_Info *server;
378 unsigned int secFlags;
381 server = ses->server;
386 rc = smb_init(SMB_COM_NEGOTIATE, 0, NULL /* no tcon yet */ ,
387 (void **) &pSMB, (void **) &pSMBr);
391 /* if any of auth flags (ie not sign or seal) are overriden use them */
392 if (ses->overrideSecFlg & (~(CIFSSEC_MUST_SIGN | CIFSSEC_MUST_SEAL)))
393 secFlags = ses->overrideSecFlg; /* BB FIXME fix sign flags? */
394 else /* if override flags set only sign/seal OR them with global auth */
395 secFlags = global_secflags | ses->overrideSecFlg;
397 cFYI(1, "secFlags 0x%x", secFlags);
399 pSMB->hdr.Mid = GetNextMid(server);
400 pSMB->hdr.Flags2 |= (SMBFLG2_UNICODE | SMBFLG2_ERR_STATUS);
402 if ((secFlags & CIFSSEC_MUST_KRB5) == CIFSSEC_MUST_KRB5)
403 pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC;
404 else if ((secFlags & CIFSSEC_AUTH_MASK) == CIFSSEC_MAY_KRB5) {
405 cFYI(1, "Kerberos only mechanism, enable extended security");
406 pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC;
407 } else if ((secFlags & CIFSSEC_MUST_NTLMSSP) == CIFSSEC_MUST_NTLMSSP)
408 pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC;
409 else if ((secFlags & CIFSSEC_AUTH_MASK) == CIFSSEC_MAY_NTLMSSP) {
410 cFYI(1, "NTLMSSP only mechanism, enable extended security");
411 pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC;
415 for (i = 0; i < CIFS_NUM_PROT; i++) {
416 strncpy(pSMB->DialectsArray+count, protocols[i].name, 16);
417 count += strlen(protocols[i].name) + 1;
418 /* null at end of source and target buffers anyway */
420 inc_rfc1001_len(pSMB, count);
421 pSMB->ByteCount = cpu_to_le16(count);
423 rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB,
424 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
428 server->dialect = le16_to_cpu(pSMBr->DialectIndex);
429 cFYI(1, "Dialect: %d", server->dialect);
430 /* Check wct = 1 error case */
431 if ((pSMBr->hdr.WordCount < 13) || (server->dialect == BAD_PROT)) {
432 /* core returns wct = 1, but we do not ask for core - otherwise
433 small wct just comes when dialect index is -1 indicating we
434 could not negotiate a common dialect */
437 #ifdef CONFIG_CIFS_WEAK_PW_HASH
438 } else if ((pSMBr->hdr.WordCount == 13)
439 && ((server->dialect == LANMAN_PROT)
440 || (server->dialect == LANMAN2_PROT))) {
442 struct lanman_neg_rsp *rsp = (struct lanman_neg_rsp *)pSMBr;
444 if ((secFlags & CIFSSEC_MAY_LANMAN) ||
445 (secFlags & CIFSSEC_MAY_PLNTXT))
446 server->secType = LANMAN;
448 cERROR(1, "mount failed weak security disabled"
449 " in /proc/fs/cifs/SecurityFlags");
453 server->secMode = (__u8)le16_to_cpu(rsp->SecurityMode);
454 server->maxReq = le16_to_cpu(rsp->MaxMpxCount);
455 server->maxBuf = min((__u32)le16_to_cpu(rsp->MaxBufSize),
456 (__u32)CIFSMaxBufSize + MAX_CIFS_HDR_SIZE);
457 server->max_vcs = le16_to_cpu(rsp->MaxNumberVcs);
458 /* even though we do not use raw we might as well set this
459 accurately, in case we ever find a need for it */
460 if ((le16_to_cpu(rsp->RawMode) & RAW_ENABLE) == RAW_ENABLE) {
461 server->max_rw = 0xFF00;
462 server->capabilities = CAP_MPX_MODE | CAP_RAW_MODE;
464 server->max_rw = 0;/* do not need to use raw anyway */
465 server->capabilities = CAP_MPX_MODE;
467 tmp = (__s16)le16_to_cpu(rsp->ServerTimeZone);
469 /* OS/2 often does not set timezone therefore
470 * we must use server time to calc time zone.
471 * Could deviate slightly from the right zone.
472 * Smallest defined timezone difference is 15 minutes
473 * (i.e. Nepal). Rounding up/down is done to match
476 int val, seconds, remain, result;
477 struct timespec ts, utc;
479 ts = cnvrtDosUnixTm(rsp->SrvTime.Date,
480 rsp->SrvTime.Time, 0);
481 cFYI(1, "SrvTime %d sec since 1970 (utc: %d) diff: %d",
482 (int)ts.tv_sec, (int)utc.tv_sec,
483 (int)(utc.tv_sec - ts.tv_sec));
484 val = (int)(utc.tv_sec - ts.tv_sec);
486 result = (seconds / MIN_TZ_ADJ) * MIN_TZ_ADJ;
487 remain = seconds % MIN_TZ_ADJ;
488 if (remain >= (MIN_TZ_ADJ / 2))
489 result += MIN_TZ_ADJ;
492 server->timeAdj = result;
494 server->timeAdj = (int)tmp;
495 server->timeAdj *= 60; /* also in seconds */
497 cFYI(1, "server->timeAdj: %d seconds", server->timeAdj);
500 /* BB get server time for time conversions and add
501 code to use it and timezone since this is not UTC */
503 if (rsp->EncryptionKeyLength ==
504 cpu_to_le16(CIFS_CRYPTO_KEY_SIZE)) {
505 memcpy(ses->server->cryptkey, rsp->EncryptionKey,
506 CIFS_CRYPTO_KEY_SIZE);
507 } else if (server->secMode & SECMODE_PW_ENCRYPT) {
508 rc = -EIO; /* need cryptkey unless plain text */
512 cFYI(1, "LANMAN negotiated");
513 /* we will not end up setting signing flags - as no signing
514 was in LANMAN and server did not return the flags on */
516 #else /* weak security disabled */
517 } else if (pSMBr->hdr.WordCount == 13) {
518 cERROR(1, "mount failed, cifs module not built "
519 "with CIFS_WEAK_PW_HASH support");
521 #endif /* WEAK_PW_HASH */
523 } else if (pSMBr->hdr.WordCount != 17) {
528 /* else wct == 17 NTLM */
529 server->secMode = pSMBr->SecurityMode;
530 if ((server->secMode & SECMODE_USER) == 0)
531 cFYI(1, "share mode security");
533 if ((server->secMode & SECMODE_PW_ENCRYPT) == 0)
534 #ifdef CONFIG_CIFS_WEAK_PW_HASH
535 if ((secFlags & CIFSSEC_MAY_PLNTXT) == 0)
536 #endif /* CIFS_WEAK_PW_HASH */
537 cERROR(1, "Server requests plain text password"
538 " but client support disabled");
540 if ((secFlags & CIFSSEC_MUST_NTLMV2) == CIFSSEC_MUST_NTLMV2)
541 server->secType = NTLMv2;
542 else if (secFlags & CIFSSEC_MAY_NTLM)
543 server->secType = NTLM;
544 else if (secFlags & CIFSSEC_MAY_NTLMV2)
545 server->secType = NTLMv2;
546 else if (secFlags & CIFSSEC_MAY_KRB5)
547 server->secType = Kerberos;
548 else if (secFlags & CIFSSEC_MAY_NTLMSSP)
549 server->secType = RawNTLMSSP;
550 else if (secFlags & CIFSSEC_MAY_LANMAN)
551 server->secType = LANMAN;
554 cERROR(1, "Invalid security type");
557 /* else ... any others ...? */
559 /* one byte, so no need to convert this or EncryptionKeyLen from
561 server->maxReq = le16_to_cpu(pSMBr->MaxMpxCount);
562 /* probably no need to store and check maxvcs */
563 server->maxBuf = min(le32_to_cpu(pSMBr->MaxBufferSize),
564 (__u32) CIFSMaxBufSize + MAX_CIFS_HDR_SIZE);
565 server->max_rw = le32_to_cpu(pSMBr->MaxRawSize);
566 cFYI(DBG2, "Max buf = %d", ses->server->maxBuf);
567 server->capabilities = le32_to_cpu(pSMBr->Capabilities);
568 server->timeAdj = (int)(__s16)le16_to_cpu(pSMBr->ServerTimeZone);
569 server->timeAdj *= 60;
570 if (pSMBr->EncryptionKeyLength == CIFS_CRYPTO_KEY_SIZE) {
571 memcpy(ses->server->cryptkey, pSMBr->u.EncryptionKey,
572 CIFS_CRYPTO_KEY_SIZE);
573 } else if ((pSMBr->hdr.Flags2 & SMBFLG2_EXT_SEC)
574 && (pSMBr->EncryptionKeyLength == 0)) {
575 /* decode security blob */
576 } else if (server->secMode & SECMODE_PW_ENCRYPT) {
577 rc = -EIO; /* no crypt key only if plain text pwd */
581 /* BB might be helpful to save off the domain of server here */
583 if ((pSMBr->hdr.Flags2 & SMBFLG2_EXT_SEC) &&
584 (server->capabilities & CAP_EXTENDED_SECURITY)) {
585 count = pSMBr->ByteCount;
590 spin_lock(&cifs_tcp_ses_lock);
591 if (server->srv_count > 1) {
592 spin_unlock(&cifs_tcp_ses_lock);
593 if (memcmp(server->server_GUID,
594 pSMBr->u.extended_response.
596 cFYI(1, "server UID changed");
597 memcpy(server->server_GUID,
598 pSMBr->u.extended_response.GUID,
602 spin_unlock(&cifs_tcp_ses_lock);
603 memcpy(server->server_GUID,
604 pSMBr->u.extended_response.GUID, 16);
608 server->secType = RawNTLMSSP;
610 rc = decode_negTokenInit(pSMBr->u.extended_response.
611 SecurityBlob, count - 16,
617 if (server->secType == Kerberos) {
618 if (!server->sec_kerberos &&
619 !server->sec_mskerberos)
621 } else if (server->secType == RawNTLMSSP) {
622 if (!server->sec_ntlmssp)
628 server->capabilities &= ~CAP_EXTENDED_SECURITY;
630 #ifdef CONFIG_CIFS_WEAK_PW_HASH
633 if ((secFlags & CIFSSEC_MAY_SIGN) == 0) {
634 /* MUST_SIGN already includes the MAY_SIGN FLAG
635 so if this is zero it means that signing is disabled */
636 cFYI(1, "Signing disabled");
637 if (server->secMode & SECMODE_SIGN_REQUIRED) {
638 cERROR(1, "Server requires "
639 "packet signing to be enabled in "
640 "/proc/fs/cifs/SecurityFlags.");
644 ~(SECMODE_SIGN_ENABLED | SECMODE_SIGN_REQUIRED);
645 } else if ((secFlags & CIFSSEC_MUST_SIGN) == CIFSSEC_MUST_SIGN) {
646 /* signing required */
647 cFYI(1, "Must sign - secFlags 0x%x", secFlags);
648 if ((server->secMode &
649 (SECMODE_SIGN_ENABLED | SECMODE_SIGN_REQUIRED)) == 0) {
650 cERROR(1, "signing required but server lacks support");
653 server->secMode |= SECMODE_SIGN_REQUIRED;
655 /* signing optional ie CIFSSEC_MAY_SIGN */
656 if ((server->secMode & SECMODE_SIGN_REQUIRED) == 0)
658 ~(SECMODE_SIGN_ENABLED | SECMODE_SIGN_REQUIRED);
662 cifs_buf_release(pSMB);
664 cFYI(1, "negprot rc %d", rc);
669 CIFSSMBTDis(const int xid, struct cifsTconInfo *tcon)
671 struct smb_hdr *smb_buffer;
674 cFYI(1, "In tree disconnect");
676 /* BB: do we need to check this? These should never be NULL. */
677 if ((tcon->ses == NULL) || (tcon->ses->server == NULL))
681 * No need to return error on this operation if tid invalidated and
682 * closed on server already e.g. due to tcp session crashing. Also,
683 * the tcon is no longer on the list, so no need to take lock before
686 if ((tcon->need_reconnect) || (tcon->ses->need_reconnect))
689 rc = small_smb_init(SMB_COM_TREE_DISCONNECT, 0, tcon,
690 (void **)&smb_buffer);
694 rc = SendReceiveNoRsp(xid, tcon->ses, smb_buffer, 0);
696 cFYI(1, "Tree disconnect failed %d", rc);
698 /* No need to return error on this operation if tid invalidated and
699 closed on server already e.g. due to tcp session crashing */
707 * This is a no-op for now. We're not really interested in the reply, but
708 * rather in the fact that the server sent one and that server->lstrp
711 * FIXME: maybe we should consider checking that the reply matches request?
714 cifs_echo_callback(struct mid_q_entry *mid)
716 struct TCP_Server_Info *server = mid->callback_data;
718 DeleteMidQEntry(mid);
719 atomic_dec(&server->inFlight);
720 wake_up(&server->request_q);
724 CIFSSMBEcho(struct TCP_Server_Info *server)
729 cFYI(1, "In echo request");
731 rc = small_smb_init(SMB_COM_ECHO, 0, NULL, (void **)&smb);
735 /* set up echo request */
736 smb->hdr.Tid = 0xffff;
737 smb->hdr.WordCount = 1;
738 put_unaligned_le16(1, &smb->EchoCount);
739 put_bcc_le(1, &smb->hdr);
741 inc_rfc1001_len(smb, 3);
743 rc = cifs_call_async(server, (struct smb_hdr *)smb,
744 cifs_echo_callback, server);
746 cFYI(1, "Echo request failed: %d", rc);
748 cifs_small_buf_release(smb);
754 CIFSSMBLogoff(const int xid, struct cifsSesInfo *ses)
756 LOGOFF_ANDX_REQ *pSMB;
759 cFYI(1, "In SMBLogoff for session disconnect");
762 * BB: do we need to check validity of ses and server? They should
763 * always be valid since we have an active reference. If not, that
764 * should probably be a BUG()
766 if (!ses || !ses->server)
769 mutex_lock(&ses->session_mutex);
770 if (ses->need_reconnect)
771 goto session_already_dead; /* no need to send SMBlogoff if uid
772 already closed due to reconnect */
773 rc = small_smb_init(SMB_COM_LOGOFF_ANDX, 2, NULL, (void **)&pSMB);
775 mutex_unlock(&ses->session_mutex);
779 pSMB->hdr.Mid = GetNextMid(ses->server);
781 if (ses->server->secMode &
782 (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
783 pSMB->hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
785 pSMB->hdr.Uid = ses->Suid;
787 pSMB->AndXCommand = 0xFF;
788 rc = SendReceiveNoRsp(xid, ses, (struct smb_hdr *) pSMB, 0);
789 session_already_dead:
790 mutex_unlock(&ses->session_mutex);
792 /* if session dead then we do not need to do ulogoff,
793 since server closed smb session, no sense reporting
801 CIFSPOSIXDelFile(const int xid, struct cifsTconInfo *tcon, const char *fileName,
802 __u16 type, const struct nls_table *nls_codepage, int remap)
804 TRANSACTION2_SPI_REQ *pSMB = NULL;
805 TRANSACTION2_SPI_RSP *pSMBr = NULL;
806 struct unlink_psx_rq *pRqD;
809 int bytes_returned = 0;
810 __u16 params, param_offset, offset, byte_count;
812 cFYI(1, "In POSIX delete");
814 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
819 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
821 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
822 PATH_MAX, nls_codepage, remap);
823 name_len++; /* trailing null */
825 } else { /* BB add path length overrun check */
826 name_len = strnlen(fileName, PATH_MAX);
827 name_len++; /* trailing null */
828 strncpy(pSMB->FileName, fileName, name_len);
831 params = 6 + name_len;
832 pSMB->MaxParameterCount = cpu_to_le16(2);
833 pSMB->MaxDataCount = 0; /* BB double check this with jra */
834 pSMB->MaxSetupCount = 0;
839 param_offset = offsetof(struct smb_com_transaction2_spi_req,
840 InformationLevel) - 4;
841 offset = param_offset + params;
843 /* Setup pointer to Request Data (inode type) */
844 pRqD = (struct unlink_psx_rq *)(((char *)&pSMB->hdr.Protocol) + offset);
845 pRqD->type = cpu_to_le16(type);
846 pSMB->ParameterOffset = cpu_to_le16(param_offset);
847 pSMB->DataOffset = cpu_to_le16(offset);
848 pSMB->SetupCount = 1;
850 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
851 byte_count = 3 /* pad */ + params + sizeof(struct unlink_psx_rq);
853 pSMB->DataCount = cpu_to_le16(sizeof(struct unlink_psx_rq));
854 pSMB->TotalDataCount = cpu_to_le16(sizeof(struct unlink_psx_rq));
855 pSMB->ParameterCount = cpu_to_le16(params);
856 pSMB->TotalParameterCount = pSMB->ParameterCount;
857 pSMB->InformationLevel = cpu_to_le16(SMB_POSIX_UNLINK);
859 inc_rfc1001_len(pSMB, byte_count);
860 pSMB->ByteCount = cpu_to_le16(byte_count);
861 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
862 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
864 cFYI(1, "Posix delete returned %d", rc);
865 cifs_buf_release(pSMB);
867 cifs_stats_inc(&tcon->num_deletes);
876 CIFSSMBDelFile(const int xid, struct cifsTconInfo *tcon, const char *fileName,
877 const struct nls_table *nls_codepage, int remap)
879 DELETE_FILE_REQ *pSMB = NULL;
880 DELETE_FILE_RSP *pSMBr = NULL;
886 rc = smb_init(SMB_COM_DELETE, 1, tcon, (void **) &pSMB,
891 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
893 cifsConvertToUCS((__le16 *) pSMB->fileName, fileName,
894 PATH_MAX, nls_codepage, remap);
895 name_len++; /* trailing null */
897 } else { /* BB improve check for buffer overruns BB */
898 name_len = strnlen(fileName, PATH_MAX);
899 name_len++; /* trailing null */
900 strncpy(pSMB->fileName, fileName, name_len);
902 pSMB->SearchAttributes =
903 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM);
904 pSMB->BufferFormat = 0x04;
905 inc_rfc1001_len(pSMB, name_len + 1);
906 pSMB->ByteCount = cpu_to_le16(name_len + 1);
907 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
908 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
909 cifs_stats_inc(&tcon->num_deletes);
911 cFYI(1, "Error in RMFile = %d", rc);
913 cifs_buf_release(pSMB);
921 CIFSSMBRmDir(const int xid, struct cifsTconInfo *tcon, const char *dirName,
922 const struct nls_table *nls_codepage, int remap)
924 DELETE_DIRECTORY_REQ *pSMB = NULL;
925 DELETE_DIRECTORY_RSP *pSMBr = NULL;
930 cFYI(1, "In CIFSSMBRmDir");
932 rc = smb_init(SMB_COM_DELETE_DIRECTORY, 0, tcon, (void **) &pSMB,
937 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
938 name_len = cifsConvertToUCS((__le16 *) pSMB->DirName, dirName,
939 PATH_MAX, nls_codepage, remap);
940 name_len++; /* trailing null */
942 } else { /* BB improve check for buffer overruns BB */
943 name_len = strnlen(dirName, PATH_MAX);
944 name_len++; /* trailing null */
945 strncpy(pSMB->DirName, dirName, name_len);
948 pSMB->BufferFormat = 0x04;
949 inc_rfc1001_len(pSMB, name_len + 1);
950 pSMB->ByteCount = cpu_to_le16(name_len + 1);
951 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
952 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
953 cifs_stats_inc(&tcon->num_rmdirs);
955 cFYI(1, "Error in RMDir = %d", rc);
957 cifs_buf_release(pSMB);
964 CIFSSMBMkDir(const int xid, struct cifsTconInfo *tcon,
965 const char *name, const struct nls_table *nls_codepage, int remap)
968 CREATE_DIRECTORY_REQ *pSMB = NULL;
969 CREATE_DIRECTORY_RSP *pSMBr = NULL;
973 cFYI(1, "In CIFSSMBMkDir");
975 rc = smb_init(SMB_COM_CREATE_DIRECTORY, 0, tcon, (void **) &pSMB,
980 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
981 name_len = cifsConvertToUCS((__le16 *) pSMB->DirName, name,
982 PATH_MAX, nls_codepage, remap);
983 name_len++; /* trailing null */
985 } else { /* BB improve check for buffer overruns BB */
986 name_len = strnlen(name, PATH_MAX);
987 name_len++; /* trailing null */
988 strncpy(pSMB->DirName, name, name_len);
991 pSMB->BufferFormat = 0x04;
992 inc_rfc1001_len(pSMB, name_len + 1);
993 pSMB->ByteCount = cpu_to_le16(name_len + 1);
994 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
995 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
996 cifs_stats_inc(&tcon->num_mkdirs);
998 cFYI(1, "Error in Mkdir = %d", rc);
1000 cifs_buf_release(pSMB);
1007 CIFSPOSIXCreate(const int xid, struct cifsTconInfo *tcon, __u32 posix_flags,
1008 __u64 mode, __u16 *netfid, FILE_UNIX_BASIC_INFO *pRetData,
1009 __u32 *pOplock, const char *name,
1010 const struct nls_table *nls_codepage, int remap)
1012 TRANSACTION2_SPI_REQ *pSMB = NULL;
1013 TRANSACTION2_SPI_RSP *pSMBr = NULL;
1016 int bytes_returned = 0;
1017 __u16 params, param_offset, offset, byte_count, count;
1018 OPEN_PSX_REQ *pdata;
1019 OPEN_PSX_RSP *psx_rsp;
1021 cFYI(1, "In POSIX Create");
1023 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
1028 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1030 cifsConvertToUCS((__le16 *) pSMB->FileName, name,
1031 PATH_MAX, nls_codepage, remap);
1032 name_len++; /* trailing null */
1034 } else { /* BB improve the check for buffer overruns BB */
1035 name_len = strnlen(name, PATH_MAX);
1036 name_len++; /* trailing null */
1037 strncpy(pSMB->FileName, name, name_len);
1040 params = 6 + name_len;
1041 count = sizeof(OPEN_PSX_REQ);
1042 pSMB->MaxParameterCount = cpu_to_le16(2);
1043 pSMB->MaxDataCount = cpu_to_le16(1000); /* large enough */
1044 pSMB->MaxSetupCount = 0;
1048 pSMB->Reserved2 = 0;
1049 param_offset = offsetof(struct smb_com_transaction2_spi_req,
1050 InformationLevel) - 4;
1051 offset = param_offset + params;
1052 pdata = (OPEN_PSX_REQ *)(((char *)&pSMB->hdr.Protocol) + offset);
1053 pdata->Level = cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC);
1054 pdata->Permissions = cpu_to_le64(mode);
1055 pdata->PosixOpenFlags = cpu_to_le32(posix_flags);
1056 pdata->OpenFlags = cpu_to_le32(*pOplock);
1057 pSMB->ParameterOffset = cpu_to_le16(param_offset);
1058 pSMB->DataOffset = cpu_to_le16(offset);
1059 pSMB->SetupCount = 1;
1060 pSMB->Reserved3 = 0;
1061 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
1062 byte_count = 3 /* pad */ + params + count;
1064 pSMB->DataCount = cpu_to_le16(count);
1065 pSMB->ParameterCount = cpu_to_le16(params);
1066 pSMB->TotalDataCount = pSMB->DataCount;
1067 pSMB->TotalParameterCount = pSMB->ParameterCount;
1068 pSMB->InformationLevel = cpu_to_le16(SMB_POSIX_OPEN);
1069 pSMB->Reserved4 = 0;
1070 inc_rfc1001_len(pSMB, byte_count);
1071 pSMB->ByteCount = cpu_to_le16(byte_count);
1072 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1073 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1075 cFYI(1, "Posix create returned %d", rc);
1076 goto psx_create_err;
1079 cFYI(1, "copying inode info");
1080 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
1082 if (rc || (pSMBr->ByteCount < sizeof(OPEN_PSX_RSP))) {
1083 rc = -EIO; /* bad smb */
1084 goto psx_create_err;
1087 /* copy return information to pRetData */
1088 psx_rsp = (OPEN_PSX_RSP *)((char *) &pSMBr->hdr.Protocol
1089 + le16_to_cpu(pSMBr->t2.DataOffset));
1091 *pOplock = le16_to_cpu(psx_rsp->OplockFlags);
1093 *netfid = psx_rsp->Fid; /* cifs fid stays in le */
1094 /* Let caller know file was created so we can set the mode. */
1095 /* Do we care about the CreateAction in any other cases? */
1096 if (cpu_to_le32(FILE_CREATE) == psx_rsp->CreateAction)
1097 *pOplock |= CIFS_CREATE_ACTION;
1098 /* check to make sure response data is there */
1099 if (psx_rsp->ReturnedLevel != cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC)) {
1100 pRetData->Type = cpu_to_le32(-1); /* unknown */
1101 cFYI(DBG2, "unknown type");
1103 if (pSMBr->ByteCount < sizeof(OPEN_PSX_RSP)
1104 + sizeof(FILE_UNIX_BASIC_INFO)) {
1105 cERROR(1, "Open response data too small");
1106 pRetData->Type = cpu_to_le32(-1);
1107 goto psx_create_err;
1109 memcpy((char *) pRetData,
1110 (char *)psx_rsp + sizeof(OPEN_PSX_RSP),
1111 sizeof(FILE_UNIX_BASIC_INFO));
1115 cifs_buf_release(pSMB);
1117 if (posix_flags & SMB_O_DIRECTORY)
1118 cifs_stats_inc(&tcon->num_posixmkdirs);
1120 cifs_stats_inc(&tcon->num_posixopens);
1128 static __u16 convert_disposition(int disposition)
1132 switch (disposition) {
1133 case FILE_SUPERSEDE:
1134 ofun = SMBOPEN_OCREATE | SMBOPEN_OTRUNC;
1137 ofun = SMBOPEN_OAPPEND;
1140 ofun = SMBOPEN_OCREATE;
1143 ofun = SMBOPEN_OCREATE | SMBOPEN_OAPPEND;
1145 case FILE_OVERWRITE:
1146 ofun = SMBOPEN_OTRUNC;
1148 case FILE_OVERWRITE_IF:
1149 ofun = SMBOPEN_OCREATE | SMBOPEN_OTRUNC;
1152 cFYI(1, "unknown disposition %d", disposition);
1153 ofun = SMBOPEN_OAPPEND; /* regular open */
1159 access_flags_to_smbopen_mode(const int access_flags)
1161 int masked_flags = access_flags & (GENERIC_READ | GENERIC_WRITE);
1163 if (masked_flags == GENERIC_READ)
1164 return SMBOPEN_READ;
1165 else if (masked_flags == GENERIC_WRITE)
1166 return SMBOPEN_WRITE;
1168 /* just go for read/write */
1169 return SMBOPEN_READWRITE;
1173 SMBLegacyOpen(const int xid, struct cifsTconInfo *tcon,
1174 const char *fileName, const int openDisposition,
1175 const int access_flags, const int create_options, __u16 *netfid,
1176 int *pOplock, FILE_ALL_INFO *pfile_info,
1177 const struct nls_table *nls_codepage, int remap)
1180 OPENX_REQ *pSMB = NULL;
1181 OPENX_RSP *pSMBr = NULL;
1187 rc = smb_init(SMB_COM_OPEN_ANDX, 15, tcon, (void **) &pSMB,
1192 pSMB->AndXCommand = 0xFF; /* none */
1194 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1195 count = 1; /* account for one byte pad to word boundary */
1197 cifsConvertToUCS((__le16 *) (pSMB->fileName + 1),
1198 fileName, PATH_MAX, nls_codepage, remap);
1199 name_len++; /* trailing null */
1201 } else { /* BB improve check for buffer overruns BB */
1202 count = 0; /* no pad */
1203 name_len = strnlen(fileName, PATH_MAX);
1204 name_len++; /* trailing null */
1205 strncpy(pSMB->fileName, fileName, name_len);
1207 if (*pOplock & REQ_OPLOCK)
1208 pSMB->OpenFlags = cpu_to_le16(REQ_OPLOCK);
1209 else if (*pOplock & REQ_BATCHOPLOCK)
1210 pSMB->OpenFlags = cpu_to_le16(REQ_BATCHOPLOCK);
1212 pSMB->OpenFlags |= cpu_to_le16(REQ_MORE_INFO);
1213 pSMB->Mode = cpu_to_le16(access_flags_to_smbopen_mode(access_flags));
1214 pSMB->Mode |= cpu_to_le16(0x40); /* deny none */
1215 /* set file as system file if special file such
1216 as fifo and server expecting SFU style and
1217 no Unix extensions */
1219 if (create_options & CREATE_OPTION_SPECIAL)
1220 pSMB->FileAttributes = cpu_to_le16(ATTR_SYSTEM);
1221 else /* BB FIXME BB */
1222 pSMB->FileAttributes = cpu_to_le16(0/*ATTR_NORMAL*/);
1224 if (create_options & CREATE_OPTION_READONLY)
1225 pSMB->FileAttributes |= cpu_to_le16(ATTR_READONLY);
1228 /* pSMB->CreateOptions = cpu_to_le32(create_options &
1229 CREATE_OPTIONS_MASK); */
1230 /* BB FIXME END BB */
1232 pSMB->Sattr = cpu_to_le16(ATTR_HIDDEN | ATTR_SYSTEM | ATTR_DIRECTORY);
1233 pSMB->OpenFunction = cpu_to_le16(convert_disposition(openDisposition));
1235 inc_rfc1001_len(pSMB, count);
1237 pSMB->ByteCount = cpu_to_le16(count);
1238 /* long_op set to 1 to allow for oplock break timeouts */
1239 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1240 (struct smb_hdr *)pSMBr, &bytes_returned, 0);
1241 cifs_stats_inc(&tcon->num_opens);
1243 cFYI(1, "Error in Open = %d", rc);
1245 /* BB verify if wct == 15 */
1247 /* *pOplock = pSMBr->OplockLevel; */ /* BB take from action field*/
1249 *netfid = pSMBr->Fid; /* cifs fid stays in le */
1250 /* Let caller know file was created so we can set the mode. */
1251 /* Do we care about the CreateAction in any other cases? */
1253 /* if (cpu_to_le32(FILE_CREATE) == pSMBr->CreateAction)
1254 *pOplock |= CIFS_CREATE_ACTION; */
1258 pfile_info->CreationTime = 0; /* BB convert CreateTime*/
1259 pfile_info->LastAccessTime = 0; /* BB fixme */
1260 pfile_info->LastWriteTime = 0; /* BB fixme */
1261 pfile_info->ChangeTime = 0; /* BB fixme */
1262 pfile_info->Attributes =
1263 cpu_to_le32(le16_to_cpu(pSMBr->FileAttributes));
1264 /* the file_info buf is endian converted by caller */
1265 pfile_info->AllocationSize =
1266 cpu_to_le64(le32_to_cpu(pSMBr->EndOfFile));
1267 pfile_info->EndOfFile = pfile_info->AllocationSize;
1268 pfile_info->NumberOfLinks = cpu_to_le32(1);
1269 pfile_info->DeletePending = 0;
1273 cifs_buf_release(pSMB);
1280 CIFSSMBOpen(const int xid, struct cifsTconInfo *tcon,
1281 const char *fileName, const int openDisposition,
1282 const int access_flags, const int create_options, __u16 *netfid,
1283 int *pOplock, FILE_ALL_INFO *pfile_info,
1284 const struct nls_table *nls_codepage, int remap)
1287 OPEN_REQ *pSMB = NULL;
1288 OPEN_RSP *pSMBr = NULL;
1294 rc = smb_init(SMB_COM_NT_CREATE_ANDX, 24, tcon, (void **) &pSMB,
1299 pSMB->AndXCommand = 0xFF; /* none */
1301 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1302 count = 1; /* account for one byte pad to word boundary */
1304 cifsConvertToUCS((__le16 *) (pSMB->fileName + 1),
1305 fileName, PATH_MAX, nls_codepage, remap);
1306 name_len++; /* trailing null */
1308 pSMB->NameLength = cpu_to_le16(name_len);
1309 } else { /* BB improve check for buffer overruns BB */
1310 count = 0; /* no pad */
1311 name_len = strnlen(fileName, PATH_MAX);
1312 name_len++; /* trailing null */
1313 pSMB->NameLength = cpu_to_le16(name_len);
1314 strncpy(pSMB->fileName, fileName, name_len);
1316 if (*pOplock & REQ_OPLOCK)
1317 pSMB->OpenFlags = cpu_to_le32(REQ_OPLOCK);
1318 else if (*pOplock & REQ_BATCHOPLOCK)
1319 pSMB->OpenFlags = cpu_to_le32(REQ_BATCHOPLOCK);
1320 pSMB->DesiredAccess = cpu_to_le32(access_flags);
1321 pSMB->AllocationSize = 0;
1322 /* set file as system file if special file such
1323 as fifo and server expecting SFU style and
1324 no Unix extensions */
1325 if (create_options & CREATE_OPTION_SPECIAL)
1326 pSMB->FileAttributes = cpu_to_le32(ATTR_SYSTEM);
1328 pSMB->FileAttributes = cpu_to_le32(ATTR_NORMAL);
1330 /* XP does not handle ATTR_POSIX_SEMANTICS */
1331 /* but it helps speed up case sensitive checks for other
1332 servers such as Samba */
1333 if (tcon->ses->capabilities & CAP_UNIX)
1334 pSMB->FileAttributes |= cpu_to_le32(ATTR_POSIX_SEMANTICS);
1336 if (create_options & CREATE_OPTION_READONLY)
1337 pSMB->FileAttributes |= cpu_to_le32(ATTR_READONLY);
1339 pSMB->ShareAccess = cpu_to_le32(FILE_SHARE_ALL);
1340 pSMB->CreateDisposition = cpu_to_le32(openDisposition);
1341 pSMB->CreateOptions = cpu_to_le32(create_options & CREATE_OPTIONS_MASK);
1342 /* BB Expirement with various impersonation levels and verify */
1343 pSMB->ImpersonationLevel = cpu_to_le32(SECURITY_IMPERSONATION);
1344 pSMB->SecurityFlags =
1345 SECURITY_CONTEXT_TRACKING | SECURITY_EFFECTIVE_ONLY;
1348 inc_rfc1001_len(pSMB, count);
1350 pSMB->ByteCount = cpu_to_le16(count);
1351 /* long_op set to 1 to allow for oplock break timeouts */
1352 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1353 (struct smb_hdr *)pSMBr, &bytes_returned, 0);
1354 cifs_stats_inc(&tcon->num_opens);
1356 cFYI(1, "Error in Open = %d", rc);
1358 *pOplock = pSMBr->OplockLevel; /* 1 byte no need to le_to_cpu */
1359 *netfid = pSMBr->Fid; /* cifs fid stays in le */
1360 /* Let caller know file was created so we can set the mode. */
1361 /* Do we care about the CreateAction in any other cases? */
1362 if (cpu_to_le32(FILE_CREATE) == pSMBr->CreateAction)
1363 *pOplock |= CIFS_CREATE_ACTION;
1365 memcpy((char *)pfile_info, (char *)&pSMBr->CreationTime,
1366 36 /* CreationTime to Attributes */);
1367 /* the file_info buf is endian converted by caller */
1368 pfile_info->AllocationSize = pSMBr->AllocationSize;
1369 pfile_info->EndOfFile = pSMBr->EndOfFile;
1370 pfile_info->NumberOfLinks = cpu_to_le32(1);
1371 pfile_info->DeletePending = 0;
1375 cifs_buf_release(pSMB);
1382 CIFSSMBRead(const int xid, struct cifsTconInfo *tcon, const int netfid,
1383 const unsigned int count, const __u64 lseek, unsigned int *nbytes,
1384 char **buf, int *pbuf_type)
1387 READ_REQ *pSMB = NULL;
1388 READ_RSP *pSMBr = NULL;
1389 char *pReadData = NULL;
1391 int resp_buf_type = 0;
1394 cFYI(1, "Reading %d bytes on fid %d", count, netfid);
1395 if (tcon->ses->capabilities & CAP_LARGE_FILES)
1398 wct = 10; /* old style read */
1399 if ((lseek >> 32) > 0) {
1400 /* can not handle this big offset for old */
1406 rc = small_smb_init(SMB_COM_READ_ANDX, wct, tcon, (void **) &pSMB);
1410 /* tcon and ses pointer are checked in smb_init */
1411 if (tcon->ses->server == NULL)
1412 return -ECONNABORTED;
1414 pSMB->AndXCommand = 0xFF; /* none */
1416 pSMB->OffsetLow = cpu_to_le32(lseek & 0xFFFFFFFF);
1418 pSMB->OffsetHigh = cpu_to_le32(lseek >> 32);
1420 pSMB->Remaining = 0;
1421 pSMB->MaxCount = cpu_to_le16(count & 0xFFFF);
1422 pSMB->MaxCountHigh = cpu_to_le32(count >> 16);
1424 pSMB->ByteCount = 0; /* no need to do le conversion since 0 */
1426 /* old style read */
1427 struct smb_com_readx_req *pSMBW =
1428 (struct smb_com_readx_req *)pSMB;
1429 pSMBW->ByteCount = 0;
1432 iov[0].iov_base = (char *)pSMB;
1433 iov[0].iov_len = be32_to_cpu(pSMB->hdr.smb_buf_length) + 4;
1434 rc = SendReceive2(xid, tcon->ses, iov, 1 /* num iovecs */,
1435 &resp_buf_type, CIFS_LOG_ERROR);
1436 cifs_stats_inc(&tcon->num_reads);
1437 pSMBr = (READ_RSP *)iov[0].iov_base;
1439 cERROR(1, "Send error in read = %d", rc);
1441 int data_length = le16_to_cpu(pSMBr->DataLengthHigh);
1442 data_length = data_length << 16;
1443 data_length += le16_to_cpu(pSMBr->DataLength);
1444 *nbytes = data_length;
1446 /*check that DataLength would not go beyond end of SMB */
1447 if ((data_length > CIFSMaxBufSize)
1448 || (data_length > count)) {
1449 cFYI(1, "bad length %d for count %d",
1450 data_length, count);
1454 pReadData = (char *) (&pSMBr->hdr.Protocol) +
1455 le16_to_cpu(pSMBr->DataOffset);
1456 /* if (rc = copy_to_user(buf, pReadData, data_length)) {
1457 cERROR(1, "Faulting on read rc = %d",rc);
1459 }*/ /* can not use copy_to_user when using page cache*/
1461 memcpy(*buf, pReadData, data_length);
1465 /* cifs_small_buf_release(pSMB); */ /* Freed earlier now in SendReceive2 */
1467 if (resp_buf_type == CIFS_SMALL_BUFFER)
1468 cifs_small_buf_release(iov[0].iov_base);
1469 else if (resp_buf_type == CIFS_LARGE_BUFFER)
1470 cifs_buf_release(iov[0].iov_base);
1471 } else if (resp_buf_type != CIFS_NO_BUFFER) {
1472 /* return buffer to caller to free */
1473 *buf = iov[0].iov_base;
1474 if (resp_buf_type == CIFS_SMALL_BUFFER)
1475 *pbuf_type = CIFS_SMALL_BUFFER;
1476 else if (resp_buf_type == CIFS_LARGE_BUFFER)
1477 *pbuf_type = CIFS_LARGE_BUFFER;
1478 } /* else no valid buffer on return - leave as null */
1480 /* Note: On -EAGAIN error only caller can retry on handle based calls
1481 since file handle passed in no longer valid */
1487 CIFSSMBWrite(const int xid, struct cifsTconInfo *tcon,
1488 const int netfid, const unsigned int count,
1489 const __u64 offset, unsigned int *nbytes, const char *buf,
1490 const char __user *ubuf, const int long_op)
1493 WRITE_REQ *pSMB = NULL;
1494 WRITE_RSP *pSMBr = NULL;
1495 int bytes_returned, wct;
1501 /* cFYI(1, "write at %lld %d bytes", offset, count);*/
1502 if (tcon->ses == NULL)
1503 return -ECONNABORTED;
1505 if (tcon->ses->capabilities & CAP_LARGE_FILES)
1509 if ((offset >> 32) > 0) {
1510 /* can not handle big offset for old srv */
1515 rc = smb_init(SMB_COM_WRITE_ANDX, wct, tcon, (void **) &pSMB,
1519 /* tcon and ses pointer are checked in smb_init */
1520 if (tcon->ses->server == NULL)
1521 return -ECONNABORTED;
1523 pSMB->AndXCommand = 0xFF; /* none */
1525 pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF);
1527 pSMB->OffsetHigh = cpu_to_le32(offset >> 32);
1529 pSMB->Reserved = 0xFFFFFFFF;
1530 pSMB->WriteMode = 0;
1531 pSMB->Remaining = 0;
1533 /* Can increase buffer size if buffer is big enough in some cases ie we
1534 can send more if LARGE_WRITE_X capability returned by the server and if
1535 our buffer is big enough or if we convert to iovecs on socket writes
1536 and eliminate the copy to the CIFS buffer */
1537 if (tcon->ses->capabilities & CAP_LARGE_WRITE_X) {
1538 bytes_sent = min_t(const unsigned int, CIFSMaxBufSize, count);
1540 bytes_sent = (tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE)
1544 if (bytes_sent > count)
1547 cpu_to_le16(offsetof(struct smb_com_write_req, Data) - 4);
1549 memcpy(pSMB->Data, buf, bytes_sent);
1551 if (copy_from_user(pSMB->Data, ubuf, bytes_sent)) {
1552 cifs_buf_release(pSMB);
1555 } else if (count != 0) {
1557 cifs_buf_release(pSMB);
1559 } /* else setting file size with write of zero bytes */
1561 byte_count = bytes_sent + 1; /* pad */
1562 else /* wct == 12 */
1563 byte_count = bytes_sent + 5; /* bigger pad, smaller smb hdr */
1565 pSMB->DataLengthLow = cpu_to_le16(bytes_sent & 0xFFFF);
1566 pSMB->DataLengthHigh = cpu_to_le16(bytes_sent >> 16);
1567 inc_rfc1001_len(pSMB, byte_count);
1570 pSMB->ByteCount = cpu_to_le16(byte_count);
1571 else { /* old style write has byte count 4 bytes earlier
1573 struct smb_com_writex_req *pSMBW =
1574 (struct smb_com_writex_req *)pSMB;
1575 pSMBW->ByteCount = cpu_to_le16(byte_count);
1578 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1579 (struct smb_hdr *) pSMBr, &bytes_returned, long_op);
1580 cifs_stats_inc(&tcon->num_writes);
1582 cFYI(1, "Send error in write = %d", rc);
1584 *nbytes = le16_to_cpu(pSMBr->CountHigh);
1585 *nbytes = (*nbytes) << 16;
1586 *nbytes += le16_to_cpu(pSMBr->Count);
1589 * Mask off high 16 bits when bytes written as returned by the
1590 * server is greater than bytes requested by the client. Some
1591 * OS/2 servers are known to set incorrect CountHigh values.
1593 if (*nbytes > count)
1597 cifs_buf_release(pSMB);
1599 /* Note: On -EAGAIN error only caller can retry on handle based calls
1600 since file handle passed in no longer valid */
1606 CIFSSMBWrite2(const int xid, struct cifsTconInfo *tcon,
1607 const int netfid, const unsigned int count,
1608 const __u64 offset, unsigned int *nbytes, struct kvec *iov,
1609 int n_vec, const int long_op)
1612 WRITE_REQ *pSMB = NULL;
1615 int resp_buf_type = 0;
1619 cFYI(1, "write2 at %lld %d bytes", (long long)offset, count);
1621 if (tcon->ses->capabilities & CAP_LARGE_FILES) {
1625 if ((offset >> 32) > 0) {
1626 /* can not handle big offset for old srv */
1630 rc = small_smb_init(SMB_COM_WRITE_ANDX, wct, tcon, (void **) &pSMB);
1633 /* tcon and ses pointer are checked in smb_init */
1634 if (tcon->ses->server == NULL)
1635 return -ECONNABORTED;
1637 pSMB->AndXCommand = 0xFF; /* none */
1639 pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF);
1641 pSMB->OffsetHigh = cpu_to_le32(offset >> 32);
1642 pSMB->Reserved = 0xFFFFFFFF;
1643 pSMB->WriteMode = 0;
1644 pSMB->Remaining = 0;
1647 cpu_to_le16(offsetof(struct smb_com_write_req, Data) - 4);
1649 pSMB->DataLengthLow = cpu_to_le16(count & 0xFFFF);
1650 pSMB->DataLengthHigh = cpu_to_le16(count >> 16);
1651 /* header + 1 byte pad */
1652 smb_hdr_len = be32_to_cpu(pSMB->hdr.smb_buf_length) + 1;
1654 inc_rfc1001_len(pSMB, count + 1);
1655 else /* wct == 12 */
1656 inc_rfc1001_len(pSMB, count + 5); /* smb data starts later */
1658 pSMB->ByteCount = cpu_to_le16(count + 1);
1659 else /* wct == 12 */ /* bigger pad, smaller smb hdr, keep offset ok */ {
1660 struct smb_com_writex_req *pSMBW =
1661 (struct smb_com_writex_req *)pSMB;
1662 pSMBW->ByteCount = cpu_to_le16(count + 5);
1664 iov[0].iov_base = pSMB;
1666 iov[0].iov_len = smb_hdr_len + 4;
1667 else /* wct == 12 pad bigger by four bytes */
1668 iov[0].iov_len = smb_hdr_len + 8;
1671 rc = SendReceive2(xid, tcon->ses, iov, n_vec + 1, &resp_buf_type,
1673 cifs_stats_inc(&tcon->num_writes);
1675 cFYI(1, "Send error Write2 = %d", rc);
1676 } else if (resp_buf_type == 0) {
1677 /* presumably this can not happen, but best to be safe */
1680 WRITE_RSP *pSMBr = (WRITE_RSP *)iov[0].iov_base;
1681 *nbytes = le16_to_cpu(pSMBr->CountHigh);
1682 *nbytes = (*nbytes) << 16;
1683 *nbytes += le16_to_cpu(pSMBr->Count);
1686 * Mask off high 16 bits when bytes written as returned by the
1687 * server is greater than bytes requested by the client. OS/2
1688 * servers are known to set incorrect CountHigh values.
1690 if (*nbytes > count)
1694 /* cifs_small_buf_release(pSMB); */ /* Freed earlier now in SendReceive2 */
1695 if (resp_buf_type == CIFS_SMALL_BUFFER)
1696 cifs_small_buf_release(iov[0].iov_base);
1697 else if (resp_buf_type == CIFS_LARGE_BUFFER)
1698 cifs_buf_release(iov[0].iov_base);
1700 /* Note: On -EAGAIN error only caller can retry on handle based calls
1701 since file handle passed in no longer valid */
1708 CIFSSMBLock(const int xid, struct cifsTconInfo *tcon,
1709 const __u16 smb_file_id, const __u64 len,
1710 const __u64 offset, const __u32 numUnlock,
1711 const __u32 numLock, const __u8 lockType,
1712 const bool waitFlag, const __u8 oplock_level)
1715 LOCK_REQ *pSMB = NULL;
1716 /* LOCK_RSP *pSMBr = NULL; */ /* No response data other than rc to parse */
1721 cFYI(1, "CIFSSMBLock timeout %d numLock %d", (int)waitFlag, numLock);
1722 rc = small_smb_init(SMB_COM_LOCKING_ANDX, 8, tcon, (void **) &pSMB);
1727 if (lockType == LOCKING_ANDX_OPLOCK_RELEASE) {
1728 timeout = CIFS_ASYNC_OP; /* no response expected */
1730 } else if (waitFlag) {
1731 timeout = CIFS_BLOCKING_OP; /* blocking operation, no timeout */
1732 pSMB->Timeout = cpu_to_le32(-1);/* blocking - do not time out */
1737 pSMB->NumberOfLocks = cpu_to_le16(numLock);
1738 pSMB->NumberOfUnlocks = cpu_to_le16(numUnlock);
1739 pSMB->LockType = lockType;
1740 pSMB->OplockLevel = oplock_level;
1741 pSMB->AndXCommand = 0xFF; /* none */
1742 pSMB->Fid = smb_file_id; /* netfid stays le */
1744 if ((numLock != 0) || (numUnlock != 0)) {
1745 pSMB->Locks[0].Pid = cpu_to_le16(current->tgid);
1746 /* BB where to store pid high? */
1747 pSMB->Locks[0].LengthLow = cpu_to_le32((u32)len);
1748 pSMB->Locks[0].LengthHigh = cpu_to_le32((u32)(len>>32));
1749 pSMB->Locks[0].OffsetLow = cpu_to_le32((u32)offset);
1750 pSMB->Locks[0].OffsetHigh = cpu_to_le32((u32)(offset>>32));
1751 count = sizeof(LOCKING_ANDX_RANGE);
1756 inc_rfc1001_len(pSMB, count);
1757 pSMB->ByteCount = cpu_to_le16(count);
1760 rc = SendReceiveBlockingLock(xid, tcon, (struct smb_hdr *) pSMB,
1761 (struct smb_hdr *) pSMB, &bytes_returned);
1762 cifs_small_buf_release(pSMB);
1764 rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *)pSMB,
1766 /* SMB buffer freed by function above */
1768 cifs_stats_inc(&tcon->num_locks);
1770 cFYI(1, "Send error in Lock = %d", rc);
1772 /* Note: On -EAGAIN error only caller can retry on handle based calls
1773 since file handle passed in no longer valid */
1778 CIFSSMBPosixLock(const int xid, struct cifsTconInfo *tcon,
1779 const __u16 smb_file_id, const int get_flag, const __u64 len,
1780 struct file_lock *pLockData, const __u16 lock_type,
1781 const bool waitFlag)
1783 struct smb_com_transaction2_sfi_req *pSMB = NULL;
1784 struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
1785 struct cifs_posix_lock *parm_data;
1788 int bytes_returned = 0;
1789 int resp_buf_type = 0;
1790 __u16 params, param_offset, offset, byte_count, count;
1793 cFYI(1, "Posix Lock");
1795 if (pLockData == NULL)
1798 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
1803 pSMBr = (struct smb_com_transaction2_sfi_rsp *)pSMB;
1806 pSMB->MaxSetupCount = 0;
1809 pSMB->Reserved2 = 0;
1810 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
1811 offset = param_offset + params;
1813 count = sizeof(struct cifs_posix_lock);
1814 pSMB->MaxParameterCount = cpu_to_le16(2);
1815 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB from sess */
1816 pSMB->SetupCount = 1;
1817 pSMB->Reserved3 = 0;
1819 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION);
1821 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
1822 byte_count = 3 /* pad */ + params + count;
1823 pSMB->DataCount = cpu_to_le16(count);
1824 pSMB->ParameterCount = cpu_to_le16(params);
1825 pSMB->TotalDataCount = pSMB->DataCount;
1826 pSMB->TotalParameterCount = pSMB->ParameterCount;
1827 pSMB->ParameterOffset = cpu_to_le16(param_offset);
1828 parm_data = (struct cifs_posix_lock *)
1829 (((char *) &pSMB->hdr.Protocol) + offset);
1831 parm_data->lock_type = cpu_to_le16(lock_type);
1833 timeout = CIFS_BLOCKING_OP; /* blocking operation, no timeout */
1834 parm_data->lock_flags = cpu_to_le16(1);
1835 pSMB->Timeout = cpu_to_le32(-1);
1839 parm_data->pid = cpu_to_le32(current->tgid);
1840 parm_data->start = cpu_to_le64(pLockData->fl_start);
1841 parm_data->length = cpu_to_le64(len); /* normalize negative numbers */
1843 pSMB->DataOffset = cpu_to_le16(offset);
1844 pSMB->Fid = smb_file_id;
1845 pSMB->InformationLevel = cpu_to_le16(SMB_SET_POSIX_LOCK);
1846 pSMB->Reserved4 = 0;
1847 inc_rfc1001_len(pSMB, byte_count);
1848 pSMB->ByteCount = cpu_to_le16(byte_count);
1850 rc = SendReceiveBlockingLock(xid, tcon, (struct smb_hdr *) pSMB,
1851 (struct smb_hdr *) pSMBr, &bytes_returned);
1853 iov[0].iov_base = (char *)pSMB;
1854 iov[0].iov_len = be32_to_cpu(pSMB->hdr.smb_buf_length) + 4;
1855 rc = SendReceive2(xid, tcon->ses, iov, 1 /* num iovecs */,
1856 &resp_buf_type, timeout);
1857 pSMB = NULL; /* request buf already freed by SendReceive2. Do
1858 not try to free it twice below on exit */
1859 pSMBr = (struct smb_com_transaction2_sfi_rsp *)iov[0].iov_base;
1863 cFYI(1, "Send error in Posix Lock = %d", rc);
1864 } else if (get_flag) {
1865 /* lock structure can be returned on get */
1868 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
1870 if (rc || (pSMBr->ByteCount < sizeof(struct cifs_posix_lock))) {
1871 rc = -EIO; /* bad smb */
1874 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
1875 data_count = le16_to_cpu(pSMBr->t2.DataCount);
1876 if (data_count < sizeof(struct cifs_posix_lock)) {
1880 parm_data = (struct cifs_posix_lock *)
1881 ((char *)&pSMBr->hdr.Protocol + data_offset);
1882 if (parm_data->lock_type == __constant_cpu_to_le16(CIFS_UNLCK))
1883 pLockData->fl_type = F_UNLCK;
1885 if (parm_data->lock_type ==
1886 __constant_cpu_to_le16(CIFS_RDLCK))
1887 pLockData->fl_type = F_RDLCK;
1888 else if (parm_data->lock_type ==
1889 __constant_cpu_to_le16(CIFS_WRLCK))
1890 pLockData->fl_type = F_WRLCK;
1892 pLockData->fl_start = le64_to_cpu(parm_data->start);
1893 pLockData->fl_end = pLockData->fl_start +
1894 le64_to_cpu(parm_data->length) - 1;
1895 pLockData->fl_pid = le32_to_cpu(parm_data->pid);
1901 cifs_small_buf_release(pSMB);
1903 if (resp_buf_type == CIFS_SMALL_BUFFER)
1904 cifs_small_buf_release(iov[0].iov_base);
1905 else if (resp_buf_type == CIFS_LARGE_BUFFER)
1906 cifs_buf_release(iov[0].iov_base);
1908 /* Note: On -EAGAIN error only caller can retry on handle based calls
1909 since file handle passed in no longer valid */
1916 CIFSSMBClose(const int xid, struct cifsTconInfo *tcon, int smb_file_id)
1919 CLOSE_REQ *pSMB = NULL;
1920 cFYI(1, "In CIFSSMBClose");
1922 /* do not retry on dead session on close */
1923 rc = small_smb_init(SMB_COM_CLOSE, 3, tcon, (void **) &pSMB);
1929 pSMB->FileID = (__u16) smb_file_id;
1930 pSMB->LastWriteTime = 0xFFFFFFFF;
1931 pSMB->ByteCount = 0;
1932 rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0);
1933 cifs_stats_inc(&tcon->num_closes);
1936 /* EINTR is expected when user ctl-c to kill app */
1937 cERROR(1, "Send error in Close = %d", rc);
1941 /* Since session is dead, file will be closed on server already */
1949 CIFSSMBFlush(const int xid, struct cifsTconInfo *tcon, int smb_file_id)
1952 FLUSH_REQ *pSMB = NULL;
1953 cFYI(1, "In CIFSSMBFlush");
1955 rc = small_smb_init(SMB_COM_FLUSH, 1, tcon, (void **) &pSMB);
1959 pSMB->FileID = (__u16) smb_file_id;
1960 pSMB->ByteCount = 0;
1961 rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0);
1962 cifs_stats_inc(&tcon->num_flushes);
1964 cERROR(1, "Send error in Flush = %d", rc);
1970 CIFSSMBRename(const int xid, struct cifsTconInfo *tcon,
1971 const char *fromName, const char *toName,
1972 const struct nls_table *nls_codepage, int remap)
1975 RENAME_REQ *pSMB = NULL;
1976 RENAME_RSP *pSMBr = NULL;
1978 int name_len, name_len2;
1981 cFYI(1, "In CIFSSMBRename");
1983 rc = smb_init(SMB_COM_RENAME, 1, tcon, (void **) &pSMB,
1988 pSMB->BufferFormat = 0x04;
1989 pSMB->SearchAttributes =
1990 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
1993 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1995 cifsConvertToUCS((__le16 *) pSMB->OldFileName, fromName,
1996 PATH_MAX, nls_codepage, remap);
1997 name_len++; /* trailing null */
1999 pSMB->OldFileName[name_len] = 0x04; /* pad */
2000 /* protocol requires ASCII signature byte on Unicode string */
2001 pSMB->OldFileName[name_len + 1] = 0x00;
2003 cifsConvertToUCS((__le16 *)&pSMB->OldFileName[name_len + 2],
2004 toName, PATH_MAX, nls_codepage, remap);
2005 name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
2006 name_len2 *= 2; /* convert to bytes */
2007 } else { /* BB improve the check for buffer overruns BB */
2008 name_len = strnlen(fromName, PATH_MAX);
2009 name_len++; /* trailing null */
2010 strncpy(pSMB->OldFileName, fromName, name_len);
2011 name_len2 = strnlen(toName, PATH_MAX);
2012 name_len2++; /* trailing null */
2013 pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */
2014 strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2);
2015 name_len2++; /* trailing null */
2016 name_len2++; /* signature byte */
2019 count = 1 /* 1st signature byte */ + name_len + name_len2;
2020 inc_rfc1001_len(pSMB, count);
2021 pSMB->ByteCount = cpu_to_le16(count);
2023 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2024 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2025 cifs_stats_inc(&tcon->num_renames);
2027 cFYI(1, "Send error in rename = %d", rc);
2029 cifs_buf_release(pSMB);
2037 int CIFSSMBRenameOpenFile(const int xid, struct cifsTconInfo *pTcon,
2038 int netfid, const char *target_name,
2039 const struct nls_table *nls_codepage, int remap)
2041 struct smb_com_transaction2_sfi_req *pSMB = NULL;
2042 struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
2043 struct set_file_rename *rename_info;
2045 char dummy_string[30];
2047 int bytes_returned = 0;
2049 __u16 params, param_offset, offset, count, byte_count;
2051 cFYI(1, "Rename to File by handle");
2052 rc = smb_init(SMB_COM_TRANSACTION2, 15, pTcon, (void **) &pSMB,
2058 pSMB->MaxSetupCount = 0;
2062 pSMB->Reserved2 = 0;
2063 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
2064 offset = param_offset + params;
2066 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
2067 rename_info = (struct set_file_rename *) data_offset;
2068 pSMB->MaxParameterCount = cpu_to_le16(2);
2069 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB from sess */
2070 pSMB->SetupCount = 1;
2071 pSMB->Reserved3 = 0;
2072 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
2073 byte_count = 3 /* pad */ + params;
2074 pSMB->ParameterCount = cpu_to_le16(params);
2075 pSMB->TotalParameterCount = pSMB->ParameterCount;
2076 pSMB->ParameterOffset = cpu_to_le16(param_offset);
2077 pSMB->DataOffset = cpu_to_le16(offset);
2078 /* construct random name ".cifs_tmp<inodenum><mid>" */
2079 rename_info->overwrite = cpu_to_le32(1);
2080 rename_info->root_fid = 0;
2081 /* unicode only call */
2082 if (target_name == NULL) {
2083 sprintf(dummy_string, "cifs%x", pSMB->hdr.Mid);
2084 len_of_str = cifsConvertToUCS((__le16 *)rename_info->target_name,
2085 dummy_string, 24, nls_codepage, remap);
2087 len_of_str = cifsConvertToUCS((__le16 *)rename_info->target_name,
2088 target_name, PATH_MAX, nls_codepage,
2091 rename_info->target_name_len = cpu_to_le32(2 * len_of_str);
2092 count = 12 /* sizeof(struct set_file_rename) */ + (2 * len_of_str);
2093 byte_count += count;
2094 pSMB->DataCount = cpu_to_le16(count);
2095 pSMB->TotalDataCount = pSMB->DataCount;
2097 pSMB->InformationLevel =
2098 cpu_to_le16(SMB_SET_FILE_RENAME_INFORMATION);
2099 pSMB->Reserved4 = 0;
2100 inc_rfc1001_len(pSMB, byte_count);
2101 pSMB->ByteCount = cpu_to_le16(byte_count);
2102 rc = SendReceive(xid, pTcon->ses, (struct smb_hdr *) pSMB,
2103 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2104 cifs_stats_inc(&pTcon->num_t2renames);
2106 cFYI(1, "Send error in Rename (by file handle) = %d", rc);
2108 cifs_buf_release(pSMB);
2110 /* Note: On -EAGAIN error only caller can retry on handle based calls
2111 since file handle passed in no longer valid */
2117 CIFSSMBCopy(const int xid, struct cifsTconInfo *tcon, const char *fromName,
2118 const __u16 target_tid, const char *toName, const int flags,
2119 const struct nls_table *nls_codepage, int remap)
2122 COPY_REQ *pSMB = NULL;
2123 COPY_RSP *pSMBr = NULL;
2125 int name_len, name_len2;
2128 cFYI(1, "In CIFSSMBCopy");
2130 rc = smb_init(SMB_COM_COPY, 1, tcon, (void **) &pSMB,
2135 pSMB->BufferFormat = 0x04;
2136 pSMB->Tid2 = target_tid;
2138 pSMB->Flags = cpu_to_le16(flags & COPY_TREE);
2140 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2141 name_len = cifsConvertToUCS((__le16 *) pSMB->OldFileName,
2142 fromName, PATH_MAX, nls_codepage,
2144 name_len++; /* trailing null */
2146 pSMB->OldFileName[name_len] = 0x04; /* pad */
2147 /* protocol requires ASCII signature byte on Unicode string */
2148 pSMB->OldFileName[name_len + 1] = 0x00;
2150 cifsConvertToUCS((__le16 *)&pSMB->OldFileName[name_len + 2],
2151 toName, PATH_MAX, nls_codepage, remap);
2152 name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
2153 name_len2 *= 2; /* convert to bytes */
2154 } else { /* BB improve the check for buffer overruns BB */
2155 name_len = strnlen(fromName, PATH_MAX);
2156 name_len++; /* trailing null */
2157 strncpy(pSMB->OldFileName, fromName, name_len);
2158 name_len2 = strnlen(toName, PATH_MAX);
2159 name_len2++; /* trailing null */
2160 pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */
2161 strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2);
2162 name_len2++; /* trailing null */
2163 name_len2++; /* signature byte */
2166 count = 1 /* 1st signature byte */ + name_len + name_len2;
2167 inc_rfc1001_len(pSMB, count);
2168 pSMB->ByteCount = cpu_to_le16(count);
2170 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2171 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2173 cFYI(1, "Send error in copy = %d with %d files copied",
2174 rc, le16_to_cpu(pSMBr->CopyCount));
2176 cifs_buf_release(pSMB);
2185 CIFSUnixCreateSymLink(const int xid, struct cifsTconInfo *tcon,
2186 const char *fromName, const char *toName,
2187 const struct nls_table *nls_codepage)
2189 TRANSACTION2_SPI_REQ *pSMB = NULL;
2190 TRANSACTION2_SPI_RSP *pSMBr = NULL;
2193 int name_len_target;
2195 int bytes_returned = 0;
2196 __u16 params, param_offset, offset, byte_count;
2198 cFYI(1, "In Symlink Unix style");
2200 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2205 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2207 cifs_strtoUCS((__le16 *) pSMB->FileName, fromName, PATH_MAX
2208 /* find define for this maxpathcomponent */
2210 name_len++; /* trailing null */
2213 } else { /* BB improve the check for buffer overruns BB */
2214 name_len = strnlen(fromName, PATH_MAX);
2215 name_len++; /* trailing null */
2216 strncpy(pSMB->FileName, fromName, name_len);
2218 params = 6 + name_len;
2219 pSMB->MaxSetupCount = 0;
2223 pSMB->Reserved2 = 0;
2224 param_offset = offsetof(struct smb_com_transaction2_spi_req,
2225 InformationLevel) - 4;
2226 offset = param_offset + params;
2228 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
2229 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2231 cifs_strtoUCS((__le16 *) data_offset, toName, PATH_MAX
2232 /* find define for this maxpathcomponent */
2234 name_len_target++; /* trailing null */
2235 name_len_target *= 2;
2236 } else { /* BB improve the check for buffer overruns BB */
2237 name_len_target = strnlen(toName, PATH_MAX);
2238 name_len_target++; /* trailing null */
2239 strncpy(data_offset, toName, name_len_target);
2242 pSMB->MaxParameterCount = cpu_to_le16(2);
2243 /* BB find exact max on data count below from sess */
2244 pSMB->MaxDataCount = cpu_to_le16(1000);
2245 pSMB->SetupCount = 1;
2246 pSMB->Reserved3 = 0;
2247 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
2248 byte_count = 3 /* pad */ + params + name_len_target;
2249 pSMB->DataCount = cpu_to_le16(name_len_target);
2250 pSMB->ParameterCount = cpu_to_le16(params);
2251 pSMB->TotalDataCount = pSMB->DataCount;
2252 pSMB->TotalParameterCount = pSMB->ParameterCount;
2253 pSMB->ParameterOffset = cpu_to_le16(param_offset);
2254 pSMB->DataOffset = cpu_to_le16(offset);
2255 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_LINK);
2256 pSMB->Reserved4 = 0;
2257 inc_rfc1001_len(pSMB, byte_count);
2258 pSMB->ByteCount = cpu_to_le16(byte_count);
2259 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2260 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2261 cifs_stats_inc(&tcon->num_symlinks);
2263 cFYI(1, "Send error in SetPathInfo create symlink = %d", rc);
2265 cifs_buf_release(pSMB);
2268 goto createSymLinkRetry;
2274 CIFSUnixCreateHardLink(const int xid, struct cifsTconInfo *tcon,
2275 const char *fromName, const char *toName,
2276 const struct nls_table *nls_codepage, int remap)
2278 TRANSACTION2_SPI_REQ *pSMB = NULL;
2279 TRANSACTION2_SPI_RSP *pSMBr = NULL;
2282 int name_len_target;
2284 int bytes_returned = 0;
2285 __u16 params, param_offset, offset, byte_count;
2287 cFYI(1, "In Create Hard link Unix style");
2288 createHardLinkRetry:
2289 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2294 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2295 name_len = cifsConvertToUCS((__le16 *) pSMB->FileName, toName,
2296 PATH_MAX, nls_codepage, remap);
2297 name_len++; /* trailing null */
2300 } else { /* BB improve the check for buffer overruns BB */
2301 name_len = strnlen(toName, PATH_MAX);
2302 name_len++; /* trailing null */
2303 strncpy(pSMB->FileName, toName, name_len);
2305 params = 6 + name_len;
2306 pSMB->MaxSetupCount = 0;
2310 pSMB->Reserved2 = 0;
2311 param_offset = offsetof(struct smb_com_transaction2_spi_req,
2312 InformationLevel) - 4;
2313 offset = param_offset + params;
2315 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
2316 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2318 cifsConvertToUCS((__le16 *) data_offset, fromName, PATH_MAX,
2319 nls_codepage, remap);
2320 name_len_target++; /* trailing null */
2321 name_len_target *= 2;
2322 } else { /* BB improve the check for buffer overruns BB */
2323 name_len_target = strnlen(fromName, PATH_MAX);
2324 name_len_target++; /* trailing null */
2325 strncpy(data_offset, fromName, name_len_target);
2328 pSMB->MaxParameterCount = cpu_to_le16(2);
2329 /* BB find exact max on data count below from sess*/
2330 pSMB->MaxDataCount = cpu_to_le16(1000);
2331 pSMB->SetupCount = 1;
2332 pSMB->Reserved3 = 0;
2333 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
2334 byte_count = 3 /* pad */ + params + name_len_target;
2335 pSMB->ParameterCount = cpu_to_le16(params);
2336 pSMB->TotalParameterCount = pSMB->ParameterCount;
2337 pSMB->DataCount = cpu_to_le16(name_len_target);
2338 pSMB->TotalDataCount = pSMB->DataCount;
2339 pSMB->ParameterOffset = cpu_to_le16(param_offset);
2340 pSMB->DataOffset = cpu_to_le16(offset);
2341 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_HLINK);
2342 pSMB->Reserved4 = 0;
2343 inc_rfc1001_len(pSMB, byte_count);
2344 pSMB->ByteCount = cpu_to_le16(byte_count);
2345 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2346 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2347 cifs_stats_inc(&tcon->num_hardlinks);
2349 cFYI(1, "Send error in SetPathInfo (hard link) = %d", rc);
2351 cifs_buf_release(pSMB);
2353 goto createHardLinkRetry;
2359 CIFSCreateHardLink(const int xid, struct cifsTconInfo *tcon,
2360 const char *fromName, const char *toName,
2361 const struct nls_table *nls_codepage, int remap)
2364 NT_RENAME_REQ *pSMB = NULL;
2365 RENAME_RSP *pSMBr = NULL;
2367 int name_len, name_len2;
2370 cFYI(1, "In CIFSCreateHardLink");
2371 winCreateHardLinkRetry:
2373 rc = smb_init(SMB_COM_NT_RENAME, 4, tcon, (void **) &pSMB,
2378 pSMB->SearchAttributes =
2379 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
2381 pSMB->Flags = cpu_to_le16(CREATE_HARD_LINK);
2382 pSMB->ClusterCount = 0;
2384 pSMB->BufferFormat = 0x04;
2386 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2388 cifsConvertToUCS((__le16 *) pSMB->OldFileName, fromName,
2389 PATH_MAX, nls_codepage, remap);
2390 name_len++; /* trailing null */
2393 /* protocol specifies ASCII buffer format (0x04) for unicode */
2394 pSMB->OldFileName[name_len] = 0x04;
2395 pSMB->OldFileName[name_len + 1] = 0x00; /* pad */
2397 cifsConvertToUCS((__le16 *)&pSMB->OldFileName[name_len + 2],
2398 toName, PATH_MAX, nls_codepage, remap);
2399 name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
2400 name_len2 *= 2; /* convert to bytes */
2401 } else { /* BB improve the check for buffer overruns BB */
2402 name_len = strnlen(fromName, PATH_MAX);
2403 name_len++; /* trailing null */
2404 strncpy(pSMB->OldFileName, fromName, name_len);
2405 name_len2 = strnlen(toName, PATH_MAX);
2406 name_len2++; /* trailing null */
2407 pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */
2408 strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2);
2409 name_len2++; /* trailing null */
2410 name_len2++; /* signature byte */
2413 count = 1 /* string type byte */ + name_len + name_len2;
2414 inc_rfc1001_len(pSMB, count);
2415 pSMB->ByteCount = cpu_to_le16(count);
2417 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2418 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2419 cifs_stats_inc(&tcon->num_hardlinks);
2421 cFYI(1, "Send error in hard link (NT rename) = %d", rc);
2423 cifs_buf_release(pSMB);
2425 goto winCreateHardLinkRetry;
2431 CIFSSMBUnixQuerySymLink(const int xid, struct cifsTconInfo *tcon,
2432 const unsigned char *searchName, char **symlinkinfo,
2433 const struct nls_table *nls_codepage)
2435 /* SMB_QUERY_FILE_UNIX_LINK */
2436 TRANSACTION2_QPI_REQ *pSMB = NULL;
2437 TRANSACTION2_QPI_RSP *pSMBr = NULL;
2441 __u16 params, byte_count;
2444 cFYI(1, "In QPathSymLinkInfo (Unix) for path %s", searchName);
2447 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2452 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2454 cifs_strtoUCS((__le16 *) pSMB->FileName, searchName,
2455 PATH_MAX, nls_codepage);
2456 name_len++; /* trailing null */
2458 } else { /* BB improve the check for buffer overruns BB */
2459 name_len = strnlen(searchName, PATH_MAX);
2460 name_len++; /* trailing null */
2461 strncpy(pSMB->FileName, searchName, name_len);
2464 params = 2 /* level */ + 4 /* rsrvd */ + name_len /* incl null */ ;
2465 pSMB->TotalDataCount = 0;
2466 pSMB->MaxParameterCount = cpu_to_le16(2);
2467 pSMB->MaxDataCount = cpu_to_le16(CIFSMaxBufSize);
2468 pSMB->MaxSetupCount = 0;
2472 pSMB->Reserved2 = 0;
2473 pSMB->ParameterOffset = cpu_to_le16(offsetof(
2474 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
2475 pSMB->DataCount = 0;
2476 pSMB->DataOffset = 0;
2477 pSMB->SetupCount = 1;
2478 pSMB->Reserved3 = 0;
2479 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
2480 byte_count = params + 1 /* pad */ ;
2481 pSMB->TotalParameterCount = cpu_to_le16(params);
2482 pSMB->ParameterCount = pSMB->TotalParameterCount;
2483 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_LINK);
2484 pSMB->Reserved4 = 0;
2485 inc_rfc1001_len(pSMB, byte_count);
2486 pSMB->ByteCount = cpu_to_le16(byte_count);
2488 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2489 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2491 cFYI(1, "Send error in QuerySymLinkInfo = %d", rc);
2493 /* decode response */
2495 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
2496 /* BB also check enough total bytes returned */
2497 if (rc || (pSMBr->ByteCount < 2))
2501 u16 count = le16_to_cpu(pSMBr->t2.DataCount);
2503 data_start = ((char *) &pSMBr->hdr.Protocol) +
2504 le16_to_cpu(pSMBr->t2.DataOffset);
2506 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
2511 /* BB FIXME investigate remapping reserved chars here */
2512 *symlinkinfo = cifs_strndup_from_ucs(data_start, count,
2513 is_unicode, nls_codepage);
2518 cifs_buf_release(pSMB);
2520 goto querySymLinkRetry;
2524 #ifdef CONFIG_CIFS_SYMLINK_EXPERIMENTAL
2526 * Recent Windows versions now create symlinks more frequently
2527 * and they use the "reparse point" mechanism below. We can of course
2528 * do symlinks nicely to Samba and other servers which support the
2529 * CIFS Unix Extensions and we can also do SFU symlinks and "client only"
2530 * "MF" symlinks optionally, but for recent Windows we really need to
2531 * reenable the code below and fix the cifs_symlink callers to handle this.
2532 * In the interim this code has been moved to its own config option so
2533 * it is not compiled in by default until callers fixed up and more tested.
2536 CIFSSMBQueryReparseLinkInfo(const int xid, struct cifsTconInfo *tcon,
2537 const unsigned char *searchName,
2538 char *symlinkinfo, const int buflen, __u16 fid,
2539 const struct nls_table *nls_codepage)
2543 struct smb_com_transaction_ioctl_req *pSMB;
2544 struct smb_com_transaction_ioctl_rsp *pSMBr;
2546 cFYI(1, "In Windows reparse style QueryLink for path %s", searchName);
2547 rc = smb_init(SMB_COM_NT_TRANSACT, 23, tcon, (void **) &pSMB,
2552 pSMB->TotalParameterCount = 0 ;
2553 pSMB->TotalDataCount = 0;
2554 pSMB->MaxParameterCount = cpu_to_le32(2);
2555 /* BB find exact data count max from sess structure BB */
2556 pSMB->MaxDataCount = cpu_to_le32((tcon->ses->server->maxBuf -
2557 MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
2558 pSMB->MaxSetupCount = 4;
2560 pSMB->ParameterOffset = 0;
2561 pSMB->DataCount = 0;
2562 pSMB->DataOffset = 0;
2563 pSMB->SetupCount = 4;
2564 pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_IOCTL);
2565 pSMB->ParameterCount = pSMB->TotalParameterCount;
2566 pSMB->FunctionCode = cpu_to_le32(FSCTL_GET_REPARSE_POINT);
2567 pSMB->IsFsctl = 1; /* FSCTL */
2568 pSMB->IsRootFlag = 0;
2569 pSMB->Fid = fid; /* file handle always le */
2570 pSMB->ByteCount = 0;
2572 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2573 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2575 cFYI(1, "Send error in QueryReparseLinkInfo = %d", rc);
2576 } else { /* decode response */
2577 __u32 data_offset = le32_to_cpu(pSMBr->DataOffset);
2578 __u32 data_count = le32_to_cpu(pSMBr->DataCount);
2579 if ((pSMBr->ByteCount < 2) || (data_offset > 512)) {
2580 /* BB also check enough total bytes returned */
2581 rc = -EIO; /* bad smb */
2584 if (data_count && (data_count < 2048)) {
2585 char *end_of_smb = 2 /* sizeof byte count */ +
2586 pSMBr->ByteCount + (char *)&pSMBr->ByteCount;
2588 struct reparse_data *reparse_buf =
2589 (struct reparse_data *)
2590 ((char *)&pSMBr->hdr.Protocol
2592 if ((char *)reparse_buf >= end_of_smb) {
2596 if ((reparse_buf->LinkNamesBuf +
2597 reparse_buf->TargetNameOffset +
2598 reparse_buf->TargetNameLen) > end_of_smb) {
2599 cFYI(1, "reparse buf beyond SMB");
2604 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
2605 cifs_from_ucs2(symlinkinfo, (__le16 *)
2606 (reparse_buf->LinkNamesBuf +
2607 reparse_buf->TargetNameOffset),
2609 reparse_buf->TargetNameLen,
2611 } else { /* ASCII names */
2612 strncpy(symlinkinfo,
2613 reparse_buf->LinkNamesBuf +
2614 reparse_buf->TargetNameOffset,
2615 min_t(const int, buflen,
2616 reparse_buf->TargetNameLen));
2620 cFYI(1, "Invalid return data count on "
2621 "get reparse info ioctl");
2623 symlinkinfo[buflen] = 0; /* just in case so the caller
2624 does not go off the end of the buffer */
2625 cFYI(1, "readlink result - %s", symlinkinfo);
2629 cifs_buf_release(pSMB);
2631 /* Note: On -EAGAIN error only caller can retry on handle based calls
2632 since file handle passed in no longer valid */
2636 #endif /* CIFS_SYMLINK_EXPERIMENTAL */ /* BB temporarily unused */
2638 #ifdef CONFIG_CIFS_POSIX
2640 /*Convert an Access Control Entry from wire format to local POSIX xattr format*/
2641 static void cifs_convert_ace(posix_acl_xattr_entry *ace,
2642 struct cifs_posix_ace *cifs_ace)
2644 /* u8 cifs fields do not need le conversion */
2645 ace->e_perm = cpu_to_le16(cifs_ace->cifs_e_perm);
2646 ace->e_tag = cpu_to_le16(cifs_ace->cifs_e_tag);
2647 ace->e_id = cpu_to_le32(le64_to_cpu(cifs_ace->cifs_uid));
2648 /* cFYI(1, "perm %d tag %d id %d",ace->e_perm,ace->e_tag,ace->e_id); */
2653 /* Convert ACL from CIFS POSIX wire format to local Linux POSIX ACL xattr */
2654 static int cifs_copy_posix_acl(char *trgt, char *src, const int buflen,
2655 const int acl_type, const int size_of_data_area)
2660 struct cifs_posix_ace *pACE;
2661 struct cifs_posix_acl *cifs_acl = (struct cifs_posix_acl *)src;
2662 posix_acl_xattr_header *local_acl = (posix_acl_xattr_header *)trgt;
2664 if (le16_to_cpu(cifs_acl->version) != CIFS_ACL_VERSION)
2667 if (acl_type & ACL_TYPE_ACCESS) {
2668 count = le16_to_cpu(cifs_acl->access_entry_count);
2669 pACE = &cifs_acl->ace_array[0];
2670 size = sizeof(struct cifs_posix_acl);
2671 size += sizeof(struct cifs_posix_ace) * count;
2672 /* check if we would go beyond end of SMB */
2673 if (size_of_data_area < size) {
2674 cFYI(1, "bad CIFS POSIX ACL size %d vs. %d",
2675 size_of_data_area, size);
2678 } else if (acl_type & ACL_TYPE_DEFAULT) {
2679 count = le16_to_cpu(cifs_acl->access_entry_count);
2680 size = sizeof(struct cifs_posix_acl);
2681 size += sizeof(struct cifs_posix_ace) * count;
2682 /* skip past access ACEs to get to default ACEs */
2683 pACE = &cifs_acl->ace_array[count];
2684 count = le16_to_cpu(cifs_acl->default_entry_count);
2685 size += sizeof(struct cifs_posix_ace) * count;
2686 /* check if we would go beyond end of SMB */
2687 if (size_of_data_area < size)
2694 size = posix_acl_xattr_size(count);
2695 if ((buflen == 0) || (local_acl == NULL)) {
2696 /* used to query ACL EA size */
2697 } else if (size > buflen) {
2699 } else /* buffer big enough */ {
2700 local_acl->a_version = cpu_to_le32(POSIX_ACL_XATTR_VERSION);
2701 for (i = 0; i < count ; i++) {
2702 cifs_convert_ace(&local_acl->a_entries[i], pACE);
2709 static __u16 convert_ace_to_cifs_ace(struct cifs_posix_ace *cifs_ace,
2710 const posix_acl_xattr_entry *local_ace)
2712 __u16 rc = 0; /* 0 = ACL converted ok */
2714 cifs_ace->cifs_e_perm = le16_to_cpu(local_ace->e_perm);
2715 cifs_ace->cifs_e_tag = le16_to_cpu(local_ace->e_tag);
2716 /* BB is there a better way to handle the large uid? */
2717 if (local_ace->e_id == cpu_to_le32(-1)) {
2718 /* Probably no need to le convert -1 on any arch but can not hurt */
2719 cifs_ace->cifs_uid = cpu_to_le64(-1);
2721 cifs_ace->cifs_uid = cpu_to_le64(le32_to_cpu(local_ace->e_id));
2722 /*cFYI(1, "perm %d tag %d id %d",ace->e_perm,ace->e_tag,ace->e_id);*/
2726 /* Convert ACL from local Linux POSIX xattr to CIFS POSIX ACL wire format */
2727 static __u16 ACL_to_cifs_posix(char *parm_data, const char *pACL,
2728 const int buflen, const int acl_type)
2731 struct cifs_posix_acl *cifs_acl = (struct cifs_posix_acl *)parm_data;
2732 posix_acl_xattr_header *local_acl = (posix_acl_xattr_header *)pACL;
2736 if ((buflen == 0) || (pACL == NULL) || (cifs_acl == NULL))
2739 count = posix_acl_xattr_count((size_t)buflen);
2740 cFYI(1, "setting acl with %d entries from buf of length %d and "
2742 count, buflen, le32_to_cpu(local_acl->a_version));
2743 if (le32_to_cpu(local_acl->a_version) != 2) {
2744 cFYI(1, "unknown POSIX ACL version %d",
2745 le32_to_cpu(local_acl->a_version));
2748 cifs_acl->version = cpu_to_le16(1);
2749 if (acl_type == ACL_TYPE_ACCESS)
2750 cifs_acl->access_entry_count = cpu_to_le16(count);
2751 else if (acl_type == ACL_TYPE_DEFAULT)
2752 cifs_acl->default_entry_count = cpu_to_le16(count);
2754 cFYI(1, "unknown ACL type %d", acl_type);
2757 for (i = 0; i < count; i++) {
2758 rc = convert_ace_to_cifs_ace(&cifs_acl->ace_array[i],
2759 &local_acl->a_entries[i]);
2761 /* ACE not converted */
2766 rc = (__u16)(count * sizeof(struct cifs_posix_ace));
2767 rc += sizeof(struct cifs_posix_acl);
2768 /* BB add check to make sure ACL does not overflow SMB */
2774 CIFSSMBGetPosixACL(const int xid, struct cifsTconInfo *tcon,
2775 const unsigned char *searchName,
2776 char *acl_inf, const int buflen, const int acl_type,
2777 const struct nls_table *nls_codepage, int remap)
2779 /* SMB_QUERY_POSIX_ACL */
2780 TRANSACTION2_QPI_REQ *pSMB = NULL;
2781 TRANSACTION2_QPI_RSP *pSMBr = NULL;
2785 __u16 params, byte_count;
2787 cFYI(1, "In GetPosixACL (Unix) for path %s", searchName);
2790 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2795 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2797 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
2798 PATH_MAX, nls_codepage, remap);
2799 name_len++; /* trailing null */
2801 pSMB->FileName[name_len] = 0;
2802 pSMB->FileName[name_len+1] = 0;
2803 } else { /* BB improve the check for buffer overruns BB */
2804 name_len = strnlen(searchName, PATH_MAX);
2805 name_len++; /* trailing null */
2806 strncpy(pSMB->FileName, searchName, name_len);
2809 params = 2 /* level */ + 4 /* rsrvd */ + name_len /* incl null */ ;
2810 pSMB->TotalDataCount = 0;
2811 pSMB->MaxParameterCount = cpu_to_le16(2);
2812 /* BB find exact max data count below from sess structure BB */
2813 pSMB->MaxDataCount = cpu_to_le16(4000);
2814 pSMB->MaxSetupCount = 0;
2818 pSMB->Reserved2 = 0;
2819 pSMB->ParameterOffset = cpu_to_le16(
2820 offsetof(struct smb_com_transaction2_qpi_req,
2821 InformationLevel) - 4);
2822 pSMB->DataCount = 0;
2823 pSMB->DataOffset = 0;
2824 pSMB->SetupCount = 1;
2825 pSMB->Reserved3 = 0;
2826 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
2827 byte_count = params + 1 /* pad */ ;
2828 pSMB->TotalParameterCount = cpu_to_le16(params);
2829 pSMB->ParameterCount = pSMB->TotalParameterCount;
2830 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_POSIX_ACL);
2831 pSMB->Reserved4 = 0;
2832 inc_rfc1001_len(pSMB, byte_count);
2833 pSMB->ByteCount = cpu_to_le16(byte_count);
2835 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2836 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2837 cifs_stats_inc(&tcon->num_acl_get);
2839 cFYI(1, "Send error in Query POSIX ACL = %d", rc);
2841 /* decode response */
2843 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
2844 if (rc || (pSMBr->ByteCount < 2))
2845 /* BB also check enough total bytes returned */
2846 rc = -EIO; /* bad smb */
2848 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
2849 __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
2850 rc = cifs_copy_posix_acl(acl_inf,
2851 (char *)&pSMBr->hdr.Protocol+data_offset,
2852 buflen, acl_type, count);
2855 cifs_buf_release(pSMB);
2862 CIFSSMBSetPosixACL(const int xid, struct cifsTconInfo *tcon,
2863 const unsigned char *fileName,
2864 const char *local_acl, const int buflen,
2866 const struct nls_table *nls_codepage, int remap)
2868 struct smb_com_transaction2_spi_req *pSMB = NULL;
2869 struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
2873 int bytes_returned = 0;
2874 __u16 params, byte_count, data_count, param_offset, offset;
2876 cFYI(1, "In SetPosixACL (Unix) for path %s", fileName);
2878 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2882 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2884 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
2885 PATH_MAX, nls_codepage, remap);
2886 name_len++; /* trailing null */
2888 } else { /* BB improve the check for buffer overruns BB */
2889 name_len = strnlen(fileName, PATH_MAX);
2890 name_len++; /* trailing null */
2891 strncpy(pSMB->FileName, fileName, name_len);
2893 params = 6 + name_len;
2894 pSMB->MaxParameterCount = cpu_to_le16(2);
2895 /* BB find max SMB size from sess */
2896 pSMB->MaxDataCount = cpu_to_le16(1000);
2897 pSMB->MaxSetupCount = 0;
2901 pSMB->Reserved2 = 0;
2902 param_offset = offsetof(struct smb_com_transaction2_spi_req,
2903 InformationLevel) - 4;
2904 offset = param_offset + params;
2905 parm_data = ((char *) &pSMB->hdr.Protocol) + offset;
2906 pSMB->ParameterOffset = cpu_to_le16(param_offset);
2908 /* convert to on the wire format for POSIX ACL */
2909 data_count = ACL_to_cifs_posix(parm_data, local_acl, buflen, acl_type);
2911 if (data_count == 0) {
2913 goto setACLerrorExit;
2915 pSMB->DataOffset = cpu_to_le16(offset);
2916 pSMB->SetupCount = 1;
2917 pSMB->Reserved3 = 0;
2918 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
2919 pSMB->InformationLevel = cpu_to_le16(SMB_SET_POSIX_ACL);
2920 byte_count = 3 /* pad */ + params + data_count;
2921 pSMB->DataCount = cpu_to_le16(data_count);
2922 pSMB->TotalDataCount = pSMB->DataCount;
2923 pSMB->ParameterCount = cpu_to_le16(params);
2924 pSMB->TotalParameterCount = pSMB->ParameterCount;
2925 pSMB->Reserved4 = 0;
2926 inc_rfc1001_len(pSMB, byte_count);
2927 pSMB->ByteCount = cpu_to_le16(byte_count);
2928 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2929 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2931 cFYI(1, "Set POSIX ACL returned %d", rc);
2934 cifs_buf_release(pSMB);
2940 /* BB fix tabs in this function FIXME BB */
2942 CIFSGetExtAttr(const int xid, struct cifsTconInfo *tcon,
2943 const int netfid, __u64 *pExtAttrBits, __u64 *pMask)
2946 struct smb_t2_qfi_req *pSMB = NULL;
2947 struct smb_t2_qfi_rsp *pSMBr = NULL;
2949 __u16 params, byte_count;
2951 cFYI(1, "In GetExtAttr");
2956 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2961 params = 2 /* level */ + 2 /* fid */;
2962 pSMB->t2.TotalDataCount = 0;
2963 pSMB->t2.MaxParameterCount = cpu_to_le16(4);
2964 /* BB find exact max data count below from sess structure BB */
2965 pSMB->t2.MaxDataCount = cpu_to_le16(4000);
2966 pSMB->t2.MaxSetupCount = 0;
2967 pSMB->t2.Reserved = 0;
2969 pSMB->t2.Timeout = 0;
2970 pSMB->t2.Reserved2 = 0;
2971 pSMB->t2.ParameterOffset = cpu_to_le16(offsetof(struct smb_t2_qfi_req,
2973 pSMB->t2.DataCount = 0;
2974 pSMB->t2.DataOffset = 0;
2975 pSMB->t2.SetupCount = 1;
2976 pSMB->t2.Reserved3 = 0;
2977 pSMB->t2.SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION);
2978 byte_count = params + 1 /* pad */ ;
2979 pSMB->t2.TotalParameterCount = cpu_to_le16(params);
2980 pSMB->t2.ParameterCount = pSMB->t2.TotalParameterCount;
2981 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_ATTR_FLAGS);
2984 inc_rfc1001_len(pSMB, byte_count);
2985 pSMB->t2.ByteCount = cpu_to_le16(byte_count);
2987 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2988 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2990 cFYI(1, "error %d in GetExtAttr", rc);
2992 /* decode response */
2993 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
2994 if (rc || (pSMBr->ByteCount < 2))
2995 /* BB also check enough total bytes returned */
2996 /* If rc should we check for EOPNOSUPP and
2997 disable the srvino flag? or in caller? */
2998 rc = -EIO; /* bad smb */
3000 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3001 __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
3002 struct file_chattr_info *pfinfo;
3003 /* BB Do we need a cast or hash here ? */
3005 cFYI(1, "Illegal size ret in GetExtAttr");
3009 pfinfo = (struct file_chattr_info *)
3010 (data_offset + (char *) &pSMBr->hdr.Protocol);
3011 *pExtAttrBits = le64_to_cpu(pfinfo->mode);
3012 *pMask = le64_to_cpu(pfinfo->mask);
3016 cifs_buf_release(pSMB);
3018 goto GetExtAttrRetry;
3022 #endif /* CONFIG_POSIX */
3024 #ifdef CONFIG_CIFS_ACL
3026 * Initialize NT TRANSACT SMB into small smb request buffer. This assumes that
3027 * all NT TRANSACTS that we init here have total parm and data under about 400
3028 * bytes (to fit in small cifs buffer size), which is the case so far, it
3029 * easily fits. NB: Setup words themselves and ByteCount MaxSetupCount (size of
3030 * returned setup area) and MaxParameterCount (returned parms size) must be set
3034 smb_init_nttransact(const __u16 sub_command, const int setup_count,
3035 const int parm_len, struct cifsTconInfo *tcon,
3040 struct smb_com_ntransact_req *pSMB;
3042 rc = small_smb_init(SMB_COM_NT_TRANSACT, 19 + setup_count, tcon,
3046 *ret_buf = (void *)pSMB;
3048 pSMB->TotalParameterCount = cpu_to_le32(parm_len);
3049 pSMB->TotalDataCount = 0;
3050 pSMB->MaxDataCount = cpu_to_le32((tcon->ses->server->maxBuf -
3051 MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
3052 pSMB->ParameterCount = pSMB->TotalParameterCount;
3053 pSMB->DataCount = pSMB->TotalDataCount;
3054 temp_offset = offsetof(struct smb_com_ntransact_req, Parms) +
3055 (setup_count * 2) - 4 /* for rfc1001 length itself */;
3056 pSMB->ParameterOffset = cpu_to_le32(temp_offset);
3057 pSMB->DataOffset = cpu_to_le32(temp_offset + parm_len);
3058 pSMB->SetupCount = setup_count; /* no need to le convert byte fields */
3059 pSMB->SubCommand = cpu_to_le16(sub_command);
3064 validate_ntransact(char *buf, char **ppparm, char **ppdata,
3065 __u32 *pparmlen, __u32 *pdatalen)
3068 __u32 data_count, data_offset, parm_count, parm_offset;
3069 struct smb_com_ntransact_rsp *pSMBr;
3077 pSMBr = (struct smb_com_ntransact_rsp *)buf;
3079 /* ByteCount was converted from little endian in SendReceive */
3080 end_of_smb = 2 /* sizeof byte count */ + pSMBr->ByteCount +
3081 (char *)&pSMBr->ByteCount;
3083 data_offset = le32_to_cpu(pSMBr->DataOffset);
3084 data_count = le32_to_cpu(pSMBr->DataCount);
3085 parm_offset = le32_to_cpu(pSMBr->ParameterOffset);
3086 parm_count = le32_to_cpu(pSMBr->ParameterCount);
3088 *ppparm = (char *)&pSMBr->hdr.Protocol + parm_offset;
3089 *ppdata = (char *)&pSMBr->hdr.Protocol + data_offset;
3091 /* should we also check that parm and data areas do not overlap? */
3092 if (*ppparm > end_of_smb) {
3093 cFYI(1, "parms start after end of smb");
3095 } else if (parm_count + *ppparm > end_of_smb) {
3096 cFYI(1, "parm end after end of smb");
3098 } else if (*ppdata > end_of_smb) {
3099 cFYI(1, "data starts after end of smb");
3101 } else if (data_count + *ppdata > end_of_smb) {
3102 cFYI(1, "data %p + count %d (%p) past smb end %p start %p",
3103 *ppdata, data_count, (data_count + *ppdata),
3106 } else if (parm_count + data_count > pSMBr->ByteCount) {
3107 cFYI(1, "parm count and data count larger than SMB");
3110 *pdatalen = data_count;
3111 *pparmlen = parm_count;
3115 /* Get Security Descriptor (by handle) from remote server for a file or dir */
3117 CIFSSMBGetCIFSACL(const int xid, struct cifsTconInfo *tcon, __u16 fid,
3118 struct cifs_ntsd **acl_inf, __u32 *pbuflen)
3122 QUERY_SEC_DESC_REQ *pSMB;
3125 cFYI(1, "GetCifsACL");
3130 rc = smb_init_nttransact(NT_TRANSACT_QUERY_SECURITY_DESC, 0,
3131 8 /* parm len */, tcon, (void **) &pSMB);
3135 pSMB->MaxParameterCount = cpu_to_le32(4);
3136 /* BB TEST with big acls that might need to be e.g. larger than 16K */
3137 pSMB->MaxSetupCount = 0;
3138 pSMB->Fid = fid; /* file handle always le */
3139 pSMB->AclFlags = cpu_to_le32(CIFS_ACL_OWNER | CIFS_ACL_GROUP |
3141 pSMB->ByteCount = cpu_to_le16(11); /* 3 bytes pad + 8 bytes parm */
3142 inc_rfc1001_len(pSMB, 11);
3143 iov[0].iov_base = (char *)pSMB;
3144 iov[0].iov_len = be32_to_cpu(pSMB->hdr.smb_buf_length) + 4;
3146 rc = SendReceive2(xid, tcon->ses, iov, 1 /* num iovec */, &buf_type,
3148 cifs_stats_inc(&tcon->num_acl_get);
3150 cFYI(1, "Send error in QuerySecDesc = %d", rc);
3151 } else { /* decode response */
3155 struct smb_com_ntransact_rsp *pSMBr;
3158 /* validate_nttransact */
3159 rc = validate_ntransact(iov[0].iov_base, (char **)&parm,
3160 &pdata, &parm_len, pbuflen);
3163 pSMBr = (struct smb_com_ntransact_rsp *)iov[0].iov_base;
3165 cFYI(1, "smb %p parm %p data %p", pSMBr, parm, *acl_inf);
3167 if (le32_to_cpu(pSMBr->ParameterCount) != 4) {
3168 rc = -EIO; /* bad smb */
3173 /* BB check that data area is minimum length and as big as acl_len */
3175 acl_len = le32_to_cpu(*parm);
3176 if (acl_len != *pbuflen) {
3177 cERROR(1, "acl length %d does not match %d",
3179 if (*pbuflen > acl_len)
3183 /* check if buffer is big enough for the acl
3184 header followed by the smallest SID */
3185 if ((*pbuflen < sizeof(struct cifs_ntsd) + 8) ||
3186 (*pbuflen >= 64 * 1024)) {
3187 cERROR(1, "bad acl length %d", *pbuflen);
3191 *acl_inf = kmalloc(*pbuflen, GFP_KERNEL);
3192 if (*acl_inf == NULL) {
3196 memcpy(*acl_inf, pdata, *pbuflen);
3200 if (buf_type == CIFS_SMALL_BUFFER)
3201 cifs_small_buf_release(iov[0].iov_base);
3202 else if (buf_type == CIFS_LARGE_BUFFER)
3203 cifs_buf_release(iov[0].iov_base);
3204 /* cifs_small_buf_release(pSMB); */ /* Freed earlier now in SendReceive2 */
3209 CIFSSMBSetCIFSACL(const int xid, struct cifsTconInfo *tcon, __u16 fid,
3210 struct cifs_ntsd *pntsd, __u32 acllen)
3212 __u16 byte_count, param_count, data_count, param_offset, data_offset;
3214 int bytes_returned = 0;
3215 SET_SEC_DESC_REQ *pSMB = NULL;
3216 NTRANSACT_RSP *pSMBr = NULL;
3219 rc = smb_init(SMB_COM_NT_TRANSACT, 19, tcon, (void **) &pSMB,
3224 pSMB->MaxSetupCount = 0;
3228 param_offset = offsetof(struct smb_com_transaction_ssec_req, Fid) - 4;
3229 data_count = acllen;
3230 data_offset = param_offset + param_count;
3231 byte_count = 3 /* pad */ + param_count;
3233 pSMB->DataCount = cpu_to_le32(data_count);
3234 pSMB->TotalDataCount = pSMB->DataCount;
3235 pSMB->MaxParameterCount = cpu_to_le32(4);
3236 pSMB->MaxDataCount = cpu_to_le32(16384);
3237 pSMB->ParameterCount = cpu_to_le32(param_count);
3238 pSMB->ParameterOffset = cpu_to_le32(param_offset);
3239 pSMB->TotalParameterCount = pSMB->ParameterCount;
3240 pSMB->DataOffset = cpu_to_le32(data_offset);
3241 pSMB->SetupCount = 0;
3242 pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_SET_SECURITY_DESC);
3243 pSMB->ByteCount = cpu_to_le16(byte_count+data_count);
3245 pSMB->Fid = fid; /* file handle always le */
3246 pSMB->Reserved2 = 0;
3247 pSMB->AclFlags = cpu_to_le32(CIFS_ACL_DACL);
3249 if (pntsd && acllen) {
3250 memcpy((char *) &pSMBr->hdr.Protocol + data_offset,
3253 inc_rfc1001_len(pSMB, byte_count + data_count);
3255 inc_rfc1001_len(pSMB, byte_count);
3257 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3258 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3260 cFYI(1, "SetCIFSACL bytes_returned: %d, rc: %d", bytes_returned, rc);
3262 cFYI(1, "Set CIFS ACL returned %d", rc);
3263 cifs_buf_release(pSMB);
3266 goto setCifsAclRetry;
3271 #endif /* CONFIG_CIFS_ACL */
3273 /* Legacy Query Path Information call for lookup to old servers such
3275 int SMBQueryInformation(const int xid, struct cifsTconInfo *tcon,
3276 const unsigned char *searchName,
3277 FILE_ALL_INFO *pFinfo,
3278 const struct nls_table *nls_codepage, int remap)
3280 QUERY_INFORMATION_REQ *pSMB;
3281 QUERY_INFORMATION_RSP *pSMBr;
3286 cFYI(1, "In SMBQPath path %s", searchName);
3288 rc = smb_init(SMB_COM_QUERY_INFORMATION, 0, tcon, (void **) &pSMB,
3293 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3295 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
3296 PATH_MAX, nls_codepage, remap);
3297 name_len++; /* trailing null */
3300 name_len = strnlen(searchName, PATH_MAX);
3301 name_len++; /* trailing null */
3302 strncpy(pSMB->FileName, searchName, name_len);
3304 pSMB->BufferFormat = 0x04;
3305 name_len++; /* account for buffer type byte */
3306 inc_rfc1001_len(pSMB, (__u16)name_len);
3307 pSMB->ByteCount = cpu_to_le16(name_len);
3309 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3310 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3312 cFYI(1, "Send error in QueryInfo = %d", rc);
3313 } else if (pFinfo) {
3315 __u32 time = le32_to_cpu(pSMBr->last_write_time);
3317 /* decode response */
3318 /* BB FIXME - add time zone adjustment BB */
3319 memset(pFinfo, 0, sizeof(FILE_ALL_INFO));
3322 /* decode time fields */
3323 pFinfo->ChangeTime = cpu_to_le64(cifs_UnixTimeToNT(ts));
3324 pFinfo->LastWriteTime = pFinfo->ChangeTime;
3325 pFinfo->LastAccessTime = 0;
3326 pFinfo->AllocationSize =
3327 cpu_to_le64(le32_to_cpu(pSMBr->size));
3328 pFinfo->EndOfFile = pFinfo->AllocationSize;
3329 pFinfo->Attributes =
3330 cpu_to_le32(le16_to_cpu(pSMBr->attr));
3332 rc = -EIO; /* bad buffer passed in */
3334 cifs_buf_release(pSMB);
3343 CIFSSMBQFileInfo(const int xid, struct cifsTconInfo *tcon,
3344 u16 netfid, FILE_ALL_INFO *pFindData)
3346 struct smb_t2_qfi_req *pSMB = NULL;
3347 struct smb_t2_qfi_rsp *pSMBr = NULL;
3350 __u16 params, byte_count;
3353 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3358 params = 2 /* level */ + 2 /* fid */;
3359 pSMB->t2.TotalDataCount = 0;
3360 pSMB->t2.MaxParameterCount = cpu_to_le16(4);
3361 /* BB find exact max data count below from sess structure BB */
3362 pSMB->t2.MaxDataCount = cpu_to_le16(CIFSMaxBufSize);
3363 pSMB->t2.MaxSetupCount = 0;
3364 pSMB->t2.Reserved = 0;
3366 pSMB->t2.Timeout = 0;
3367 pSMB->t2.Reserved2 = 0;
3368 pSMB->t2.ParameterOffset = cpu_to_le16(offsetof(struct smb_t2_qfi_req,
3370 pSMB->t2.DataCount = 0;
3371 pSMB->t2.DataOffset = 0;
3372 pSMB->t2.SetupCount = 1;
3373 pSMB->t2.Reserved3 = 0;
3374 pSMB->t2.SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION);
3375 byte_count = params + 1 /* pad */ ;
3376 pSMB->t2.TotalParameterCount = cpu_to_le16(params);
3377 pSMB->t2.ParameterCount = pSMB->t2.TotalParameterCount;
3378 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_ALL_INFO);
3381 inc_rfc1001_len(pSMB, byte_count);
3383 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3384 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3386 cFYI(1, "Send error in QPathInfo = %d", rc);
3387 } else { /* decode response */
3388 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3390 if (rc) /* BB add auto retry on EOPNOTSUPP? */
3392 else if (pSMBr->ByteCount < 40)
3393 rc = -EIO; /* bad smb */
3394 else if (pFindData) {
3395 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3396 memcpy((char *) pFindData,
3397 (char *) &pSMBr->hdr.Protocol +
3398 data_offset, sizeof(FILE_ALL_INFO));
3402 cifs_buf_release(pSMB);
3404 goto QFileInfoRetry;
3410 CIFSSMBQPathInfo(const int xid, struct cifsTconInfo *tcon,
3411 const unsigned char *searchName,
3412 FILE_ALL_INFO *pFindData,
3413 int legacy /* old style infolevel */,
3414 const struct nls_table *nls_codepage, int remap)
3416 /* level 263 SMB_QUERY_FILE_ALL_INFO */
3417 TRANSACTION2_QPI_REQ *pSMB = NULL;
3418 TRANSACTION2_QPI_RSP *pSMBr = NULL;
3422 __u16 params, byte_count;
3424 /* cFYI(1, "In QPathInfo path %s", searchName); */
3426 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3431 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3433 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
3434 PATH_MAX, nls_codepage, remap);
3435 name_len++; /* trailing null */
3437 } else { /* BB improve the check for buffer overruns BB */
3438 name_len = strnlen(searchName, PATH_MAX);
3439 name_len++; /* trailing null */
3440 strncpy(pSMB->FileName, searchName, name_len);
3443 params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */;
3444 pSMB->TotalDataCount = 0;
3445 pSMB->MaxParameterCount = cpu_to_le16(2);
3446 /* BB find exact max SMB PDU from sess structure BB */
3447 pSMB->MaxDataCount = cpu_to_le16(4000);
3448 pSMB->MaxSetupCount = 0;
3452 pSMB->Reserved2 = 0;
3453 pSMB->ParameterOffset = cpu_to_le16(offsetof(
3454 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
3455 pSMB->DataCount = 0;
3456 pSMB->DataOffset = 0;
3457 pSMB->SetupCount = 1;
3458 pSMB->Reserved3 = 0;
3459 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
3460 byte_count = params + 1 /* pad */ ;
3461 pSMB->TotalParameterCount = cpu_to_le16(params);
3462 pSMB->ParameterCount = pSMB->TotalParameterCount;
3464 pSMB->InformationLevel = cpu_to_le16(SMB_INFO_STANDARD);
3466 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_ALL_INFO);
3467 pSMB->Reserved4 = 0;
3468 inc_rfc1001_len(pSMB, byte_count);
3469 pSMB->ByteCount = cpu_to_le16(byte_count);
3471 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3472 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3474 cFYI(1, "Send error in QPathInfo = %d", rc);
3475 } else { /* decode response */
3476 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3478 if (rc) /* BB add auto retry on EOPNOTSUPP? */
3480 else if (!legacy && (pSMBr->ByteCount < 40))
3481 rc = -EIO; /* bad smb */
3482 else if (legacy && (pSMBr->ByteCount < 24))
3483 rc = -EIO; /* 24 or 26 expected but we do not read
3485 else if (pFindData) {
3487 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3489 /* On legacy responses we do not read the last field,
3490 EAsize, fortunately since it varies by subdialect and
3491 also note it differs on Set vs. Get, ie two bytes or 4
3492 bytes depending but we don't care here */
3494 size = sizeof(FILE_INFO_STANDARD);
3496 size = sizeof(FILE_ALL_INFO);
3497 memcpy((char *) pFindData,
3498 (char *) &pSMBr->hdr.Protocol +
3503 cifs_buf_release(pSMB);
3505 goto QPathInfoRetry;
3511 CIFSSMBUnixQFileInfo(const int xid, struct cifsTconInfo *tcon,
3512 u16 netfid, FILE_UNIX_BASIC_INFO *pFindData)
3514 struct smb_t2_qfi_req *pSMB = NULL;
3515 struct smb_t2_qfi_rsp *pSMBr = NULL;
3518 __u16 params, byte_count;
3521 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3526 params = 2 /* level */ + 2 /* fid */;
3527 pSMB->t2.TotalDataCount = 0;
3528 pSMB->t2.MaxParameterCount = cpu_to_le16(4);
3529 /* BB find exact max data count below from sess structure BB */
3530 pSMB->t2.MaxDataCount = cpu_to_le16(CIFSMaxBufSize);
3531 pSMB->t2.MaxSetupCount = 0;
3532 pSMB->t2.Reserved = 0;
3534 pSMB->t2.Timeout = 0;
3535 pSMB->t2.Reserved2 = 0;
3536 pSMB->t2.ParameterOffset = cpu_to_le16(offsetof(struct smb_t2_qfi_req,
3538 pSMB->t2.DataCount = 0;
3539 pSMB->t2.DataOffset = 0;
3540 pSMB->t2.SetupCount = 1;
3541 pSMB->t2.Reserved3 = 0;
3542 pSMB->t2.SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION);
3543 byte_count = params + 1 /* pad */ ;
3544 pSMB->t2.TotalParameterCount = cpu_to_le16(params);
3545 pSMB->t2.ParameterCount = pSMB->t2.TotalParameterCount;
3546 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC);
3549 inc_rfc1001_len(pSMB, byte_count);
3551 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3552 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3554 cFYI(1, "Send error in QPathInfo = %d", rc);
3555 } else { /* decode response */
3556 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3558 if (rc || (pSMBr->ByteCount < sizeof(FILE_UNIX_BASIC_INFO))) {
3559 cERROR(1, "Malformed FILE_UNIX_BASIC_INFO response.\n"
3560 "Unix Extensions can be disabled on mount "
3561 "by specifying the nosfu mount option.");
3562 rc = -EIO; /* bad smb */
3564 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3565 memcpy((char *) pFindData,
3566 (char *) &pSMBr->hdr.Protocol +
3568 sizeof(FILE_UNIX_BASIC_INFO));
3572 cifs_buf_release(pSMB);
3574 goto UnixQFileInfoRetry;
3580 CIFSSMBUnixQPathInfo(const int xid, struct cifsTconInfo *tcon,
3581 const unsigned char *searchName,
3582 FILE_UNIX_BASIC_INFO *pFindData,
3583 const struct nls_table *nls_codepage, int remap)
3585 /* SMB_QUERY_FILE_UNIX_BASIC */
3586 TRANSACTION2_QPI_REQ *pSMB = NULL;
3587 TRANSACTION2_QPI_RSP *pSMBr = NULL;
3589 int bytes_returned = 0;
3591 __u16 params, byte_count;
3593 cFYI(1, "In QPathInfo (Unix) the path %s", searchName);
3595 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3600 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3602 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
3603 PATH_MAX, nls_codepage, remap);
3604 name_len++; /* trailing null */
3606 } else { /* BB improve the check for buffer overruns BB */
3607 name_len = strnlen(searchName, PATH_MAX);
3608 name_len++; /* trailing null */
3609 strncpy(pSMB->FileName, searchName, name_len);
3612 params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */;
3613 pSMB->TotalDataCount = 0;
3614 pSMB->MaxParameterCount = cpu_to_le16(2);
3615 /* BB find exact max SMB PDU from sess structure BB */
3616 pSMB->MaxDataCount = cpu_to_le16(4000);
3617 pSMB->MaxSetupCount = 0;
3621 pSMB->Reserved2 = 0;
3622 pSMB->ParameterOffset = cpu_to_le16(offsetof(
3623 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
3624 pSMB->DataCount = 0;
3625 pSMB->DataOffset = 0;
3626 pSMB->SetupCount = 1;
3627 pSMB->Reserved3 = 0;
3628 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
3629 byte_count = params + 1 /* pad */ ;
3630 pSMB->TotalParameterCount = cpu_to_le16(params);
3631 pSMB->ParameterCount = pSMB->TotalParameterCount;
3632 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC);
3633 pSMB->Reserved4 = 0;
3634 inc_rfc1001_len(pSMB, byte_count);
3635 pSMB->ByteCount = cpu_to_le16(byte_count);
3637 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3638 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3640 cFYI(1, "Send error in QPathInfo = %d", rc);
3641 } else { /* decode response */
3642 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3644 if (rc || (pSMBr->ByteCount < sizeof(FILE_UNIX_BASIC_INFO))) {
3645 cERROR(1, "Malformed FILE_UNIX_BASIC_INFO response.\n"
3646 "Unix Extensions can be disabled on mount "
3647 "by specifying the nosfu mount option.");
3648 rc = -EIO; /* bad smb */
3650 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3651 memcpy((char *) pFindData,
3652 (char *) &pSMBr->hdr.Protocol +
3654 sizeof(FILE_UNIX_BASIC_INFO));
3657 cifs_buf_release(pSMB);
3659 goto UnixQPathInfoRetry;
3664 /* xid, tcon, searchName and codepage are input parms, rest are returned */
3666 CIFSFindFirst(const int xid, struct cifsTconInfo *tcon,
3667 const char *searchName,
3668 const struct nls_table *nls_codepage,
3670 struct cifs_search_info *psrch_inf, int remap, const char dirsep)
3672 /* level 257 SMB_ */
3673 TRANSACTION2_FFIRST_REQ *pSMB = NULL;
3674 TRANSACTION2_FFIRST_RSP *pSMBr = NULL;
3675 T2_FFIRST_RSP_PARMS *parms;
3677 int bytes_returned = 0;
3679 __u16 params, byte_count;
3681 cFYI(1, "In FindFirst for %s", searchName);
3684 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3689 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3691 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
3692 PATH_MAX, nls_codepage, remap);
3693 /* We can not add the asterik earlier in case
3694 it got remapped to 0xF03A as if it were part of the
3695 directory name instead of a wildcard */
3697 pSMB->FileName[name_len] = dirsep;
3698 pSMB->FileName[name_len+1] = 0;
3699 pSMB->FileName[name_len+2] = '*';
3700 pSMB->FileName[name_len+3] = 0;
3701 name_len += 4; /* now the trailing null */
3702 pSMB->FileName[name_len] = 0; /* null terminate just in case */
3703 pSMB->FileName[name_len+1] = 0;
3705 } else { /* BB add check for overrun of SMB buf BB */
3706 name_len = strnlen(searchName, PATH_MAX);
3707 /* BB fix here and in unicode clause above ie
3708 if (name_len > buffersize-header)
3709 free buffer exit; BB */
3710 strncpy(pSMB->FileName, searchName, name_len);
3711 pSMB->FileName[name_len] = dirsep;
3712 pSMB->FileName[name_len+1] = '*';
3713 pSMB->FileName[name_len+2] = 0;
3717 params = 12 + name_len /* includes null */ ;
3718 pSMB->TotalDataCount = 0; /* no EAs */
3719 pSMB->MaxParameterCount = cpu_to_le16(10);
3720 pSMB->MaxDataCount = cpu_to_le16((tcon->ses->server->maxBuf -
3721 MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
3722 pSMB->MaxSetupCount = 0;
3726 pSMB->Reserved2 = 0;
3727 byte_count = params + 1 /* pad */ ;
3728 pSMB->TotalParameterCount = cpu_to_le16(params);
3729 pSMB->ParameterCount = pSMB->TotalParameterCount;
3730 pSMB->ParameterOffset = cpu_to_le16(
3731 offsetof(struct smb_com_transaction2_ffirst_req, SearchAttributes)
3733 pSMB->DataCount = 0;
3734 pSMB->DataOffset = 0;
3735 pSMB->SetupCount = 1; /* one byte, no need to make endian neutral */
3736 pSMB->Reserved3 = 0;
3737 pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_FIRST);
3738 pSMB->SearchAttributes =
3739 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
3741 pSMB->SearchCount = cpu_to_le16(CIFSMaxBufSize/sizeof(FILE_UNIX_INFO));
3742 pSMB->SearchFlags = cpu_to_le16(CIFS_SEARCH_CLOSE_AT_END |
3743 CIFS_SEARCH_RETURN_RESUME);
3744 pSMB->InformationLevel = cpu_to_le16(psrch_inf->info_level);
3746 /* BB what should we set StorageType to? Does it matter? BB */
3747 pSMB->SearchStorageType = 0;
3748 inc_rfc1001_len(pSMB, byte_count);
3749 pSMB->ByteCount = cpu_to_le16(byte_count);
3751 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3752 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3753 cifs_stats_inc(&tcon->num_ffirst);
3755 if (rc) {/* BB add logic to retry regular search if Unix search
3756 rejected unexpectedly by server */
3757 /* BB Add code to handle unsupported level rc */
3758 cFYI(1, "Error in FindFirst = %d", rc);
3760 cifs_buf_release(pSMB);
3762 /* BB eventually could optimize out free and realloc of buf */
3765 goto findFirstRetry;
3766 } else { /* decode response */
3767 /* BB remember to free buffer if error BB */
3768 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3772 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
3773 psrch_inf->unicode = true;
3775 psrch_inf->unicode = false;
3777 psrch_inf->ntwrk_buf_start = (char *)pSMBr;
3778 psrch_inf->smallBuf = 0;
3779 psrch_inf->srch_entries_start =
3780 (char *) &pSMBr->hdr.Protocol +
3781 le16_to_cpu(pSMBr->t2.DataOffset);
3782 parms = (T2_FFIRST_RSP_PARMS *)((char *) &pSMBr->hdr.Protocol +
3783 le16_to_cpu(pSMBr->t2.ParameterOffset));
3785 if (parms->EndofSearch)
3786 psrch_inf->endOfSearch = true;
3788 psrch_inf->endOfSearch = false;
3790 psrch_inf->entries_in_buffer =
3791 le16_to_cpu(parms->SearchCount);
3792 psrch_inf->index_of_last_entry = 2 /* skip . and .. */ +
3793 psrch_inf->entries_in_buffer;
3794 lnoff = le16_to_cpu(parms->LastNameOffset);
3795 if (tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE <
3797 cERROR(1, "ignoring corrupt resume name");
3798 psrch_inf->last_entry = NULL;
3802 psrch_inf->last_entry = psrch_inf->srch_entries_start +
3805 *pnetfid = parms->SearchHandle;
3807 cifs_buf_release(pSMB);
3814 int CIFSFindNext(const int xid, struct cifsTconInfo *tcon,
3815 __u16 searchHandle, struct cifs_search_info *psrch_inf)
3817 TRANSACTION2_FNEXT_REQ *pSMB = NULL;
3818 TRANSACTION2_FNEXT_RSP *pSMBr = NULL;
3819 T2_FNEXT_RSP_PARMS *parms;
3820 char *response_data;
3822 int bytes_returned, name_len;
3823 __u16 params, byte_count;
3825 cFYI(1, "In FindNext");
3827 if (psrch_inf->endOfSearch)
3830 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3835 params = 14; /* includes 2 bytes of null string, converted to LE below*/
3837 pSMB->TotalDataCount = 0; /* no EAs */
3838 pSMB->MaxParameterCount = cpu_to_le16(8);
3839 pSMB->MaxDataCount =
3840 cpu_to_le16((tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE) &
3842 pSMB->MaxSetupCount = 0;
3846 pSMB->Reserved2 = 0;
3847 pSMB->ParameterOffset = cpu_to_le16(
3848 offsetof(struct smb_com_transaction2_fnext_req,SearchHandle) - 4);
3849 pSMB->DataCount = 0;
3850 pSMB->DataOffset = 0;
3851 pSMB->SetupCount = 1;
3852 pSMB->Reserved3 = 0;
3853 pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_NEXT);
3854 pSMB->SearchHandle = searchHandle; /* always kept as le */
3856 cpu_to_le16(CIFSMaxBufSize / sizeof(FILE_UNIX_INFO));
3857 pSMB->InformationLevel = cpu_to_le16(psrch_inf->info_level);
3858 pSMB->ResumeKey = psrch_inf->resume_key;
3860 cpu_to_le16(CIFS_SEARCH_CLOSE_AT_END | CIFS_SEARCH_RETURN_RESUME);
3862 name_len = psrch_inf->resume_name_len;
3864 if (name_len < PATH_MAX) {
3865 memcpy(pSMB->ResumeFileName, psrch_inf->presume_name, name_len);
3866 byte_count += name_len;
3867 /* 14 byte parm len above enough for 2 byte null terminator */
3868 pSMB->ResumeFileName[name_len] = 0;
3869 pSMB->ResumeFileName[name_len+1] = 0;
3872 goto FNext2_err_exit;
3874 byte_count = params + 1 /* pad */ ;
3875 pSMB->TotalParameterCount = cpu_to_le16(params);
3876 pSMB->ParameterCount = pSMB->TotalParameterCount;
3877 inc_rfc1001_len(pSMB, byte_count);
3878 pSMB->ByteCount = cpu_to_le16(byte_count);
3880 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3881 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3882 cifs_stats_inc(&tcon->num_fnext);
3885 psrch_inf->endOfSearch = true;
3886 cifs_buf_release(pSMB);
3887 rc = 0; /* search probably was closed at end of search*/
3889 cFYI(1, "FindNext returned = %d", rc);
3890 } else { /* decode response */
3891 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3896 /* BB fixme add lock for file (srch_info) struct here */
3897 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
3898 psrch_inf->unicode = true;
3900 psrch_inf->unicode = false;
3901 response_data = (char *) &pSMBr->hdr.Protocol +
3902 le16_to_cpu(pSMBr->t2.ParameterOffset);
3903 parms = (T2_FNEXT_RSP_PARMS *)response_data;
3904 response_data = (char *)&pSMBr->hdr.Protocol +
3905 le16_to_cpu(pSMBr->t2.DataOffset);
3906 if (psrch_inf->smallBuf)
3907 cifs_small_buf_release(
3908 psrch_inf->ntwrk_buf_start);
3910 cifs_buf_release(psrch_inf->ntwrk_buf_start);
3911 psrch_inf->srch_entries_start = response_data;
3912 psrch_inf->ntwrk_buf_start = (char *)pSMB;
3913 psrch_inf->smallBuf = 0;
3914 if (parms->EndofSearch)
3915 psrch_inf->endOfSearch = true;
3917 psrch_inf->endOfSearch = false;
3918 psrch_inf->entries_in_buffer =
3919 le16_to_cpu(parms->SearchCount);
3920 psrch_inf->index_of_last_entry +=
3921 psrch_inf->entries_in_buffer;
3922 lnoff = le16_to_cpu(parms->LastNameOffset);
3923 if (tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE <
3925 cERROR(1, "ignoring corrupt resume name");
3926 psrch_inf->last_entry = NULL;
3929 psrch_inf->last_entry =
3930 psrch_inf->srch_entries_start + lnoff;
3932 /* cFYI(1, "fnxt2 entries in buf %d index_of_last %d",
3933 psrch_inf->entries_in_buffer, psrch_inf->index_of_last_entry); */
3935 /* BB fixme add unlock here */
3940 /* BB On error, should we leave previous search buf (and count and
3941 last entry fields) intact or free the previous one? */
3943 /* Note: On -EAGAIN error only caller can retry on handle based calls
3944 since file handle passed in no longer valid */
3947 cifs_buf_release(pSMB);
3952 CIFSFindClose(const int xid, struct cifsTconInfo *tcon,
3953 const __u16 searchHandle)
3956 FINDCLOSE_REQ *pSMB = NULL;
3958 cFYI(1, "In CIFSSMBFindClose");
3959 rc = small_smb_init(SMB_COM_FIND_CLOSE2, 1, tcon, (void **)&pSMB);
3961 /* no sense returning error if session restarted
3962 as file handle has been closed */
3968 pSMB->FileID = searchHandle;
3969 pSMB->ByteCount = 0;
3970 rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0);
3972 cERROR(1, "Send error in FindClose = %d", rc);
3974 cifs_stats_inc(&tcon->num_fclose);
3976 /* Since session is dead, search handle closed on server already */
3984 CIFSGetSrvInodeNumber(const int xid, struct cifsTconInfo *tcon,
3985 const unsigned char *searchName,
3986 __u64 *inode_number,
3987 const struct nls_table *nls_codepage, int remap)
3990 TRANSACTION2_QPI_REQ *pSMB = NULL;
3991 TRANSACTION2_QPI_RSP *pSMBr = NULL;
3992 int name_len, bytes_returned;
3993 __u16 params, byte_count;
3995 cFYI(1, "In GetSrvInodeNum for %s", searchName);
3999 GetInodeNumberRetry:
4000 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4005 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4007 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
4008 PATH_MAX, nls_codepage, remap);
4009 name_len++; /* trailing null */
4011 } else { /* BB improve the check for buffer overruns BB */
4012 name_len = strnlen(searchName, PATH_MAX);
4013 name_len++; /* trailing null */
4014 strncpy(pSMB->FileName, searchName, name_len);
4017 params = 2 /* level */ + 4 /* rsrvd */ + name_len /* incl null */ ;
4018 pSMB->TotalDataCount = 0;
4019 pSMB->MaxParameterCount = cpu_to_le16(2);
4020 /* BB find exact max data count below from sess structure BB */
4021 pSMB->MaxDataCount = cpu_to_le16(4000);
4022 pSMB->MaxSetupCount = 0;
4026 pSMB->Reserved2 = 0;
4027 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4028 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
4029 pSMB->DataCount = 0;
4030 pSMB->DataOffset = 0;
4031 pSMB->SetupCount = 1;
4032 pSMB->Reserved3 = 0;
4033 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
4034 byte_count = params + 1 /* pad */ ;
4035 pSMB->TotalParameterCount = cpu_to_le16(params);
4036 pSMB->ParameterCount = pSMB->TotalParameterCount;
4037 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_INTERNAL_INFO);
4038 pSMB->Reserved4 = 0;
4039 inc_rfc1001_len(pSMB, byte_count);
4040 pSMB->ByteCount = cpu_to_le16(byte_count);
4042 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4043 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4045 cFYI(1, "error %d in QueryInternalInfo", rc);
4047 /* decode response */
4048 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4049 if (rc || (pSMBr->ByteCount < 2))
4050 /* BB also check enough total bytes returned */
4051 /* If rc should we check for EOPNOSUPP and
4052 disable the srvino flag? or in caller? */
4053 rc = -EIO; /* bad smb */
4055 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4056 __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
4057 struct file_internal_info *pfinfo;
4058 /* BB Do we need a cast or hash here ? */
4060 cFYI(1, "Illegal size ret in QryIntrnlInf");
4062 goto GetInodeNumOut;
4064 pfinfo = (struct file_internal_info *)
4065 (data_offset + (char *) &pSMBr->hdr.Protocol);
4066 *inode_number = le64_to_cpu(pfinfo->UniqueId);
4070 cifs_buf_release(pSMB);
4072 goto GetInodeNumberRetry;
4076 /* parses DFS refferal V3 structure
4077 * caller is responsible for freeing target_nodes
4080 * on failure - errno
4083 parse_DFS_referrals(TRANSACTION2_GET_DFS_REFER_RSP *pSMBr,
4084 unsigned int *num_of_nodes,
4085 struct dfs_info3_param **target_nodes,
4086 const struct nls_table *nls_codepage, int remap,
4087 const char *searchName)
4092 struct dfs_referral_level_3 *ref;
4094 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
4098 *num_of_nodes = le16_to_cpu(pSMBr->NumberOfReferrals);
4100 if (*num_of_nodes < 1) {
4101 cERROR(1, "num_referrals: must be at least > 0,"
4102 "but we get num_referrals = %d\n", *num_of_nodes);
4104 goto parse_DFS_referrals_exit;
4107 ref = (struct dfs_referral_level_3 *) &(pSMBr->referrals);
4108 if (ref->VersionNumber != cpu_to_le16(3)) {
4109 cERROR(1, "Referrals of V%d version are not supported,"
4110 "should be V3", le16_to_cpu(ref->VersionNumber));
4112 goto parse_DFS_referrals_exit;
4115 /* get the upper boundary of the resp buffer */
4116 data_end = (char *)(&(pSMBr->PathConsumed)) +
4117 le16_to_cpu(pSMBr->t2.DataCount);
4119 cFYI(1, "num_referrals: %d dfs flags: 0x%x ...\n",
4121 le32_to_cpu(pSMBr->DFSFlags));
4123 *target_nodes = kzalloc(sizeof(struct dfs_info3_param) *
4124 *num_of_nodes, GFP_KERNEL);
4125 if (*target_nodes == NULL) {
4126 cERROR(1, "Failed to allocate buffer for target_nodes\n");
4128 goto parse_DFS_referrals_exit;
4131 /* collect necessary data from referrals */
4132 for (i = 0; i < *num_of_nodes; i++) {
4135 struct dfs_info3_param *node = (*target_nodes)+i;
4137 node->flags = le32_to_cpu(pSMBr->DFSFlags);
4139 __le16 *tmp = kmalloc(strlen(searchName)*2 + 2,
4143 goto parse_DFS_referrals_exit;
4145 cifsConvertToUCS((__le16 *) tmp, searchName,
4146 PATH_MAX, nls_codepage, remap);
4147 node->path_consumed = cifs_ucs2_bytes(tmp,
4148 le16_to_cpu(pSMBr->PathConsumed),
4152 node->path_consumed = le16_to_cpu(pSMBr->PathConsumed);
4154 node->server_type = le16_to_cpu(ref->ServerType);
4155 node->ref_flag = le16_to_cpu(ref->ReferralEntryFlags);
4158 temp = (char *)ref + le16_to_cpu(ref->DfsPathOffset);
4159 max_len = data_end - temp;
4160 node->path_name = cifs_strndup_from_ucs(temp, max_len,
4161 is_unicode, nls_codepage);
4162 if (!node->path_name) {
4164 goto parse_DFS_referrals_exit;
4167 /* copy link target UNC */
4168 temp = (char *)ref + le16_to_cpu(ref->NetworkAddressOffset);
4169 max_len = data_end - temp;
4170 node->node_name = cifs_strndup_from_ucs(temp, max_len,
4171 is_unicode, nls_codepage);
4172 if (!node->node_name)
4176 parse_DFS_referrals_exit:
4178 free_dfs_info_array(*target_nodes, *num_of_nodes);
4179 *target_nodes = NULL;
4186 CIFSGetDFSRefer(const int xid, struct cifsSesInfo *ses,
4187 const unsigned char *searchName,
4188 struct dfs_info3_param **target_nodes,
4189 unsigned int *num_of_nodes,
4190 const struct nls_table *nls_codepage, int remap)
4192 /* TRANS2_GET_DFS_REFERRAL */
4193 TRANSACTION2_GET_DFS_REFER_REQ *pSMB = NULL;
4194 TRANSACTION2_GET_DFS_REFER_RSP *pSMBr = NULL;
4198 __u16 params, byte_count;
4200 *target_nodes = NULL;
4202 cFYI(1, "In GetDFSRefer the path %s", searchName);
4206 rc = smb_init(SMB_COM_TRANSACTION2, 15, NULL, (void **) &pSMB,
4211 /* server pointer checked in called function,
4212 but should never be null here anyway */
4213 pSMB->hdr.Mid = GetNextMid(ses->server);
4214 pSMB->hdr.Tid = ses->ipc_tid;
4215 pSMB->hdr.Uid = ses->Suid;
4216 if (ses->capabilities & CAP_STATUS32)
4217 pSMB->hdr.Flags2 |= SMBFLG2_ERR_STATUS;
4218 if (ses->capabilities & CAP_DFS)
4219 pSMB->hdr.Flags2 |= SMBFLG2_DFS;
4221 if (ses->capabilities & CAP_UNICODE) {
4222 pSMB->hdr.Flags2 |= SMBFLG2_UNICODE;
4224 cifsConvertToUCS((__le16 *) pSMB->RequestFileName,
4225 searchName, PATH_MAX, nls_codepage, remap);
4226 name_len++; /* trailing null */
4228 } else { /* BB improve the check for buffer overruns BB */
4229 name_len = strnlen(searchName, PATH_MAX);
4230 name_len++; /* trailing null */
4231 strncpy(pSMB->RequestFileName, searchName, name_len);
4235 if (ses->server->secMode &
4236 (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
4237 pSMB->hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
4240 pSMB->hdr.Uid = ses->Suid;
4242 params = 2 /* level */ + name_len /*includes null */ ;
4243 pSMB->TotalDataCount = 0;
4244 pSMB->DataCount = 0;
4245 pSMB->DataOffset = 0;
4246 pSMB->MaxParameterCount = 0;
4247 /* BB find exact max SMB PDU from sess structure BB */
4248 pSMB->MaxDataCount = cpu_to_le16(4000);
4249 pSMB->MaxSetupCount = 0;
4253 pSMB->Reserved2 = 0;
4254 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4255 struct smb_com_transaction2_get_dfs_refer_req, MaxReferralLevel) - 4);
4256 pSMB->SetupCount = 1;
4257 pSMB->Reserved3 = 0;
4258 pSMB->SubCommand = cpu_to_le16(TRANS2_GET_DFS_REFERRAL);
4259 byte_count = params + 3 /* pad */ ;
4260 pSMB->ParameterCount = cpu_to_le16(params);
4261 pSMB->TotalParameterCount = pSMB->ParameterCount;
4262 pSMB->MaxReferralLevel = cpu_to_le16(3);
4263 inc_rfc1001_len(pSMB, byte_count);
4264 pSMB->ByteCount = cpu_to_le16(byte_count);
4266 rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB,
4267 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4269 cFYI(1, "Send error in GetDFSRefer = %d", rc);
4272 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4274 /* BB Also check if enough total bytes returned? */
4275 if (rc || (pSMBr->ByteCount < 17)) {
4276 rc = -EIO; /* bad smb */
4280 cFYI(1, "Decoding GetDFSRefer response BCC: %d Offset %d",
4282 le16_to_cpu(pSMBr->t2.DataOffset));
4284 /* parse returned result into more usable form */
4285 rc = parse_DFS_referrals(pSMBr, num_of_nodes,
4286 target_nodes, nls_codepage, remap,
4290 cifs_buf_release(pSMB);
4298 /* Query File System Info such as free space to old servers such as Win 9x */
4300 SMBOldQFSInfo(const int xid, struct cifsTconInfo *tcon, struct kstatfs *FSData)
4302 /* level 0x01 SMB_QUERY_FILE_SYSTEM_INFO */
4303 TRANSACTION2_QFSI_REQ *pSMB = NULL;
4304 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4305 FILE_SYSTEM_ALLOC_INFO *response_data;
4307 int bytes_returned = 0;
4308 __u16 params, byte_count;
4310 cFYI(1, "OldQFSInfo");
4312 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4317 params = 2; /* level */
4318 pSMB->TotalDataCount = 0;
4319 pSMB->MaxParameterCount = cpu_to_le16(2);
4320 pSMB->MaxDataCount = cpu_to_le16(1000);
4321 pSMB->MaxSetupCount = 0;
4325 pSMB->Reserved2 = 0;
4326 byte_count = params + 1 /* pad */ ;
4327 pSMB->TotalParameterCount = cpu_to_le16(params);
4328 pSMB->ParameterCount = pSMB->TotalParameterCount;
4329 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4330 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4331 pSMB->DataCount = 0;
4332 pSMB->DataOffset = 0;
4333 pSMB->SetupCount = 1;
4334 pSMB->Reserved3 = 0;
4335 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4336 pSMB->InformationLevel = cpu_to_le16(SMB_INFO_ALLOCATION);
4337 inc_rfc1001_len(pSMB, byte_count);
4338 pSMB->ByteCount = cpu_to_le16(byte_count);
4340 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4341 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4343 cFYI(1, "Send error in QFSInfo = %d", rc);
4344 } else { /* decode response */
4345 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4347 if (rc || (pSMBr->ByteCount < 18))
4348 rc = -EIO; /* bad smb */
4350 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4351 cFYI(1, "qfsinf resp BCC: %d Offset %d",
4352 pSMBr->ByteCount, data_offset);
4354 response_data = (FILE_SYSTEM_ALLOC_INFO *)
4355 (((char *) &pSMBr->hdr.Protocol) + data_offset);
4357 le16_to_cpu(response_data->BytesPerSector) *
4358 le32_to_cpu(response_data->
4359 SectorsPerAllocationUnit);
4361 le32_to_cpu(response_data->TotalAllocationUnits);
4362 FSData->f_bfree = FSData->f_bavail =
4363 le32_to_cpu(response_data->FreeAllocationUnits);
4364 cFYI(1, "Blocks: %lld Free: %lld Block size %ld",
4365 (unsigned long long)FSData->f_blocks,
4366 (unsigned long long)FSData->f_bfree,
4370 cifs_buf_release(pSMB);
4373 goto oldQFSInfoRetry;
4379 CIFSSMBQFSInfo(const int xid, struct cifsTconInfo *tcon, struct kstatfs *FSData)
4381 /* level 0x103 SMB_QUERY_FILE_SYSTEM_INFO */
4382 TRANSACTION2_QFSI_REQ *pSMB = NULL;
4383 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4384 FILE_SYSTEM_INFO *response_data;
4386 int bytes_returned = 0;
4387 __u16 params, byte_count;
4389 cFYI(1, "In QFSInfo");
4391 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4396 params = 2; /* level */
4397 pSMB->TotalDataCount = 0;
4398 pSMB->MaxParameterCount = cpu_to_le16(2);
4399 pSMB->MaxDataCount = cpu_to_le16(1000);
4400 pSMB->MaxSetupCount = 0;
4404 pSMB->Reserved2 = 0;
4405 byte_count = params + 1 /* pad */ ;
4406 pSMB->TotalParameterCount = cpu_to_le16(params);
4407 pSMB->ParameterCount = pSMB->TotalParameterCount;
4408 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4409 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4410 pSMB->DataCount = 0;
4411 pSMB->DataOffset = 0;
4412 pSMB->SetupCount = 1;
4413 pSMB->Reserved3 = 0;
4414 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4415 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_SIZE_INFO);
4416 inc_rfc1001_len(pSMB, byte_count);
4417 pSMB->ByteCount = cpu_to_le16(byte_count);
4419 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4420 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4422 cFYI(1, "Send error in QFSInfo = %d", rc);
4423 } else { /* decode response */
4424 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4426 if (rc || (pSMBr->ByteCount < 24))
4427 rc = -EIO; /* bad smb */
4429 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4433 *) (((char *) &pSMBr->hdr.Protocol) +
4436 le32_to_cpu(response_data->BytesPerSector) *
4437 le32_to_cpu(response_data->
4438 SectorsPerAllocationUnit);
4440 le64_to_cpu(response_data->TotalAllocationUnits);
4441 FSData->f_bfree = FSData->f_bavail =
4442 le64_to_cpu(response_data->FreeAllocationUnits);
4443 cFYI(1, "Blocks: %lld Free: %lld Block size %ld",
4444 (unsigned long long)FSData->f_blocks,
4445 (unsigned long long)FSData->f_bfree,
4449 cifs_buf_release(pSMB);
4458 CIFSSMBQFSAttributeInfo(const int xid, struct cifsTconInfo *tcon)
4460 /* level 0x105 SMB_QUERY_FILE_SYSTEM_INFO */
4461 TRANSACTION2_QFSI_REQ *pSMB = NULL;
4462 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4463 FILE_SYSTEM_ATTRIBUTE_INFO *response_data;
4465 int bytes_returned = 0;
4466 __u16 params, byte_count;
4468 cFYI(1, "In QFSAttributeInfo");
4470 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4475 params = 2; /* level */
4476 pSMB->TotalDataCount = 0;
4477 pSMB->MaxParameterCount = cpu_to_le16(2);
4478 /* BB find exact max SMB PDU from sess structure BB */
4479 pSMB->MaxDataCount = cpu_to_le16(1000);
4480 pSMB->MaxSetupCount = 0;
4484 pSMB->Reserved2 = 0;
4485 byte_count = params + 1 /* pad */ ;
4486 pSMB->TotalParameterCount = cpu_to_le16(params);
4487 pSMB->ParameterCount = pSMB->TotalParameterCount;
4488 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4489 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4490 pSMB->DataCount = 0;
4491 pSMB->DataOffset = 0;
4492 pSMB->SetupCount = 1;
4493 pSMB->Reserved3 = 0;
4494 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4495 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_ATTRIBUTE_INFO);
4496 inc_rfc1001_len(pSMB, byte_count);
4497 pSMB->ByteCount = cpu_to_le16(byte_count);
4499 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4500 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4502 cERROR(1, "Send error in QFSAttributeInfo = %d", rc);
4503 } else { /* decode response */
4504 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4506 if (rc || (pSMBr->ByteCount < 13)) {
4507 /* BB also check if enough bytes returned */
4508 rc = -EIO; /* bad smb */
4510 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4512 (FILE_SYSTEM_ATTRIBUTE_INFO
4513 *) (((char *) &pSMBr->hdr.Protocol) +
4515 memcpy(&tcon->fsAttrInfo, response_data,
4516 sizeof(FILE_SYSTEM_ATTRIBUTE_INFO));
4519 cifs_buf_release(pSMB);
4522 goto QFSAttributeRetry;
4528 CIFSSMBQFSDeviceInfo(const int xid, struct cifsTconInfo *tcon)
4530 /* level 0x104 SMB_QUERY_FILE_SYSTEM_INFO */
4531 TRANSACTION2_QFSI_REQ *pSMB = NULL;
4532 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4533 FILE_SYSTEM_DEVICE_INFO *response_data;
4535 int bytes_returned = 0;
4536 __u16 params, byte_count;
4538 cFYI(1, "In QFSDeviceInfo");
4540 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4545 params = 2; /* level */
4546 pSMB->TotalDataCount = 0;
4547 pSMB->MaxParameterCount = cpu_to_le16(2);
4548 /* BB find exact max SMB PDU from sess structure BB */
4549 pSMB->MaxDataCount = cpu_to_le16(1000);
4550 pSMB->MaxSetupCount = 0;
4554 pSMB->Reserved2 = 0;
4555 byte_count = params + 1 /* pad */ ;
4556 pSMB->TotalParameterCount = cpu_to_le16(params);
4557 pSMB->ParameterCount = pSMB->TotalParameterCount;
4558 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4559 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4561 pSMB->DataCount = 0;
4562 pSMB->DataOffset = 0;
4563 pSMB->SetupCount = 1;
4564 pSMB->Reserved3 = 0;
4565 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4566 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_DEVICE_INFO);
4567 inc_rfc1001_len(pSMB, byte_count);
4568 pSMB->ByteCount = cpu_to_le16(byte_count);
4570 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4571 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4573 cFYI(1, "Send error in QFSDeviceInfo = %d", rc);
4574 } else { /* decode response */
4575 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4577 if (rc || (pSMBr->ByteCount < sizeof(FILE_SYSTEM_DEVICE_INFO)))
4578 rc = -EIO; /* bad smb */
4580 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4582 (FILE_SYSTEM_DEVICE_INFO *)
4583 (((char *) &pSMBr->hdr.Protocol) +
4585 memcpy(&tcon->fsDevInfo, response_data,
4586 sizeof(FILE_SYSTEM_DEVICE_INFO));
4589 cifs_buf_release(pSMB);
4592 goto QFSDeviceRetry;
4598 CIFSSMBQFSUnixInfo(const int xid, struct cifsTconInfo *tcon)
4600 /* level 0x200 SMB_QUERY_CIFS_UNIX_INFO */
4601 TRANSACTION2_QFSI_REQ *pSMB = NULL;
4602 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4603 FILE_SYSTEM_UNIX_INFO *response_data;
4605 int bytes_returned = 0;
4606 __u16 params, byte_count;
4608 cFYI(1, "In QFSUnixInfo");
4610 rc = smb_init_no_reconnect(SMB_COM_TRANSACTION2, 15, tcon,
4611 (void **) &pSMB, (void **) &pSMBr);
4615 params = 2; /* level */
4616 pSMB->TotalDataCount = 0;
4617 pSMB->DataCount = 0;
4618 pSMB->DataOffset = 0;
4619 pSMB->MaxParameterCount = cpu_to_le16(2);
4620 /* BB find exact max SMB PDU from sess structure BB */
4621 pSMB->MaxDataCount = cpu_to_le16(100);
4622 pSMB->MaxSetupCount = 0;
4626 pSMB->Reserved2 = 0;
4627 byte_count = params + 1 /* pad */ ;
4628 pSMB->ParameterCount = cpu_to_le16(params);
4629 pSMB->TotalParameterCount = pSMB->ParameterCount;
4630 pSMB->ParameterOffset = cpu_to_le16(offsetof(struct
4631 smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4632 pSMB->SetupCount = 1;
4633 pSMB->Reserved3 = 0;
4634 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4635 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_CIFS_UNIX_INFO);
4636 inc_rfc1001_len(pSMB, byte_count);
4637 pSMB->ByteCount = cpu_to_le16(byte_count);
4639 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4640 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4642 cERROR(1, "Send error in QFSUnixInfo = %d", rc);
4643 } else { /* decode response */
4644 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4646 if (rc || (pSMBr->ByteCount < 13)) {
4647 rc = -EIO; /* bad smb */
4649 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4651 (FILE_SYSTEM_UNIX_INFO
4652 *) (((char *) &pSMBr->hdr.Protocol) +
4654 memcpy(&tcon->fsUnixInfo, response_data,
4655 sizeof(FILE_SYSTEM_UNIX_INFO));
4658 cifs_buf_release(pSMB);
4668 CIFSSMBSetFSUnixInfo(const int xid, struct cifsTconInfo *tcon, __u64 cap)
4670 /* level 0x200 SMB_SET_CIFS_UNIX_INFO */
4671 TRANSACTION2_SETFSI_REQ *pSMB = NULL;
4672 TRANSACTION2_SETFSI_RSP *pSMBr = NULL;
4674 int bytes_returned = 0;
4675 __u16 params, param_offset, offset, byte_count;
4677 cFYI(1, "In SETFSUnixInfo");
4679 /* BB switch to small buf init to save memory */
4680 rc = smb_init_no_reconnect(SMB_COM_TRANSACTION2, 15, tcon,
4681 (void **) &pSMB, (void **) &pSMBr);
4685 params = 4; /* 2 bytes zero followed by info level. */
4686 pSMB->MaxSetupCount = 0;
4690 pSMB->Reserved2 = 0;
4691 param_offset = offsetof(struct smb_com_transaction2_setfsi_req, FileNum)
4693 offset = param_offset + params;
4695 pSMB->MaxParameterCount = cpu_to_le16(4);
4696 /* BB find exact max SMB PDU from sess structure BB */
4697 pSMB->MaxDataCount = cpu_to_le16(100);
4698 pSMB->SetupCount = 1;
4699 pSMB->Reserved3 = 0;
4700 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FS_INFORMATION);
4701 byte_count = 1 /* pad */ + params + 12;
4703 pSMB->DataCount = cpu_to_le16(12);
4704 pSMB->ParameterCount = cpu_to_le16(params);
4705 pSMB->TotalDataCount = pSMB->DataCount;
4706 pSMB->TotalParameterCount = pSMB->ParameterCount;
4707 pSMB->ParameterOffset = cpu_to_le16(param_offset);
4708 pSMB->DataOffset = cpu_to_le16(offset);
4712 pSMB->InformationLevel = cpu_to_le16(SMB_SET_CIFS_UNIX_INFO);
4715 pSMB->ClientUnixMajor = cpu_to_le16(CIFS_UNIX_MAJOR_VERSION);
4716 pSMB->ClientUnixMinor = cpu_to_le16(CIFS_UNIX_MINOR_VERSION);
4717 pSMB->ClientUnixCap = cpu_to_le64(cap);
4719 inc_rfc1001_len(pSMB, byte_count);
4720 pSMB->ByteCount = cpu_to_le16(byte_count);
4722 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4723 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4725 cERROR(1, "Send error in SETFSUnixInfo = %d", rc);
4726 } else { /* decode response */
4727 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4729 rc = -EIO; /* bad smb */
4731 cifs_buf_release(pSMB);
4734 goto SETFSUnixRetry;
4742 CIFSSMBQFSPosixInfo(const int xid, struct cifsTconInfo *tcon,
4743 struct kstatfs *FSData)
4745 /* level 0x201 SMB_QUERY_CIFS_POSIX_INFO */
4746 TRANSACTION2_QFSI_REQ *pSMB = NULL;
4747 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4748 FILE_SYSTEM_POSIX_INFO *response_data;
4750 int bytes_returned = 0;
4751 __u16 params, byte_count;
4753 cFYI(1, "In QFSPosixInfo");
4755 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4760 params = 2; /* level */
4761 pSMB->TotalDataCount = 0;
4762 pSMB->DataCount = 0;
4763 pSMB->DataOffset = 0;
4764 pSMB->MaxParameterCount = cpu_to_le16(2);
4765 /* BB find exact max SMB PDU from sess structure BB */
4766 pSMB->MaxDataCount = cpu_to_le16(100);
4767 pSMB->MaxSetupCount = 0;
4771 pSMB->Reserved2 = 0;
4772 byte_count = params + 1 /* pad */ ;
4773 pSMB->ParameterCount = cpu_to_le16(params);
4774 pSMB->TotalParameterCount = pSMB->ParameterCount;
4775 pSMB->ParameterOffset = cpu_to_le16(offsetof(struct
4776 smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4777 pSMB->SetupCount = 1;
4778 pSMB->Reserved3 = 0;
4779 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4780 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_POSIX_FS_INFO);
4781 inc_rfc1001_len(pSMB, byte_count);
4782 pSMB->ByteCount = cpu_to_le16(byte_count);
4784 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4785 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4787 cFYI(1, "Send error in QFSUnixInfo = %d", rc);
4788 } else { /* decode response */
4789 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4791 if (rc || (pSMBr->ByteCount < 13)) {
4792 rc = -EIO; /* bad smb */
4794 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4796 (FILE_SYSTEM_POSIX_INFO
4797 *) (((char *) &pSMBr->hdr.Protocol) +
4800 le32_to_cpu(response_data->BlockSize);
4802 le64_to_cpu(response_data->TotalBlocks);
4804 le64_to_cpu(response_data->BlocksAvail);
4805 if (response_data->UserBlocksAvail == cpu_to_le64(-1)) {
4806 FSData->f_bavail = FSData->f_bfree;
4809 le64_to_cpu(response_data->UserBlocksAvail);
4811 if (response_data->TotalFileNodes != cpu_to_le64(-1))
4813 le64_to_cpu(response_data->TotalFileNodes);
4814 if (response_data->FreeFileNodes != cpu_to_le64(-1))
4816 le64_to_cpu(response_data->FreeFileNodes);
4819 cifs_buf_release(pSMB);
4828 /* We can not use write of zero bytes trick to
4829 set file size due to need for large file support. Also note that
4830 this SetPathInfo is preferred to SetFileInfo based method in next
4831 routine which is only needed to work around a sharing violation bug
4832 in Samba which this routine can run into */
4835 CIFSSMBSetEOF(const int xid, struct cifsTconInfo *tcon, const char *fileName,
4836 __u64 size, bool SetAllocation,
4837 const struct nls_table *nls_codepage, int remap)
4839 struct smb_com_transaction2_spi_req *pSMB = NULL;
4840 struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
4841 struct file_end_of_file_info *parm_data;
4844 int bytes_returned = 0;
4845 __u16 params, byte_count, data_count, param_offset, offset;
4847 cFYI(1, "In SetEOF");
4849 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4854 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4856 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
4857 PATH_MAX, nls_codepage, remap);
4858 name_len++; /* trailing null */
4860 } else { /* BB improve the check for buffer overruns BB */
4861 name_len = strnlen(fileName, PATH_MAX);
4862 name_len++; /* trailing null */
4863 strncpy(pSMB->FileName, fileName, name_len);
4865 params = 6 + name_len;
4866 data_count = sizeof(struct file_end_of_file_info);
4867 pSMB->MaxParameterCount = cpu_to_le16(2);
4868 pSMB->MaxDataCount = cpu_to_le16(4100);
4869 pSMB->MaxSetupCount = 0;
4873 pSMB->Reserved2 = 0;
4874 param_offset = offsetof(struct smb_com_transaction2_spi_req,
4875 InformationLevel) - 4;
4876 offset = param_offset + params;
4877 if (SetAllocation) {
4878 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
4879 pSMB->InformationLevel =
4880 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2);
4882 pSMB->InformationLevel =
4883 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO);
4884 } else /* Set File Size */ {
4885 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
4886 pSMB->InformationLevel =
4887 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO2);
4889 pSMB->InformationLevel =
4890 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO);
4894 (struct file_end_of_file_info *) (((char *) &pSMB->hdr.Protocol) +
4896 pSMB->ParameterOffset = cpu_to_le16(param_offset);
4897 pSMB->DataOffset = cpu_to_le16(offset);
4898 pSMB->SetupCount = 1;
4899 pSMB->Reserved3 = 0;
4900 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
4901 byte_count = 3 /* pad */ + params + data_count;
4902 pSMB->DataCount = cpu_to_le16(data_count);
4903 pSMB->TotalDataCount = pSMB->DataCount;
4904 pSMB->ParameterCount = cpu_to_le16(params);
4905 pSMB->TotalParameterCount = pSMB->ParameterCount;
4906 pSMB->Reserved4 = 0;
4907 inc_rfc1001_len(pSMB, byte_count);
4908 parm_data->FileSize = cpu_to_le64(size);
4909 pSMB->ByteCount = cpu_to_le16(byte_count);
4910 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4911 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4913 cFYI(1, "SetPathInfo (file size) returned %d", rc);
4915 cifs_buf_release(pSMB);
4924 CIFSSMBSetFileSize(const int xid, struct cifsTconInfo *tcon, __u64 size,
4925 __u16 fid, __u32 pid_of_opener, bool SetAllocation)
4927 struct smb_com_transaction2_sfi_req *pSMB = NULL;
4928 struct file_end_of_file_info *parm_data;
4930 __u16 params, param_offset, offset, byte_count, count;
4932 cFYI(1, "SetFileSize (via SetFileInfo) %lld",
4934 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
4939 pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
4940 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));
4943 pSMB->MaxSetupCount = 0;
4947 pSMB->Reserved2 = 0;
4948 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
4949 offset = param_offset + params;
4951 count = sizeof(struct file_end_of_file_info);
4952 pSMB->MaxParameterCount = cpu_to_le16(2);
4953 /* BB find exact max SMB PDU from sess structure BB */
4954 pSMB->MaxDataCount = cpu_to_le16(1000);
4955 pSMB->SetupCount = 1;
4956 pSMB->Reserved3 = 0;
4957 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
4958 byte_count = 3 /* pad */ + params + count;
4959 pSMB->DataCount = cpu_to_le16(count);
4960 pSMB->ParameterCount = cpu_to_le16(params);
4961 pSMB->TotalDataCount = pSMB->DataCount;
4962 pSMB->TotalParameterCount = pSMB->ParameterCount;
4963 pSMB->ParameterOffset = cpu_to_le16(param_offset);
4965 (struct file_end_of_file_info *) (((char *) &pSMB->hdr.Protocol)
4967 pSMB->DataOffset = cpu_to_le16(offset);
4968 parm_data->FileSize = cpu_to_le64(size);
4970 if (SetAllocation) {
4971 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
4972 pSMB->InformationLevel =
4973 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2);
4975 pSMB->InformationLevel =
4976 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO);
4977 } else /* Set File Size */ {
4978 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
4979 pSMB->InformationLevel =
4980 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO2);
4982 pSMB->InformationLevel =
4983 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO);
4985 pSMB->Reserved4 = 0;
4986 inc_rfc1001_len(pSMB, byte_count);
4987 pSMB->ByteCount = cpu_to_le16(byte_count);
4988 rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0);
4990 cFYI(1, "Send error in SetFileInfo (SetFileSize) = %d", rc);
4993 /* Note: On -EAGAIN error only caller can retry on handle based calls
4994 since file handle passed in no longer valid */
4999 /* Some legacy servers such as NT4 require that the file times be set on
5000 an open handle, rather than by pathname - this is awkward due to
5001 potential access conflicts on the open, but it is unavoidable for these
5002 old servers since the only other choice is to go from 100 nanosecond DCE
5003 time and resort to the original setpathinfo level which takes the ancient
5004 DOS time format with 2 second granularity */
5006 CIFSSMBSetFileInfo(const int xid, struct cifsTconInfo *tcon,
5007 const FILE_BASIC_INFO *data, __u16 fid, __u32 pid_of_opener)
5009 struct smb_com_transaction2_sfi_req *pSMB = NULL;
5012 __u16 params, param_offset, offset, byte_count, count;
5014 cFYI(1, "Set Times (via SetFileInfo)");
5015 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
5020 pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
5021 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));
5024 pSMB->MaxSetupCount = 0;
5028 pSMB->Reserved2 = 0;
5029 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
5030 offset = param_offset + params;
5032 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
5034 count = sizeof(FILE_BASIC_INFO);
5035 pSMB->MaxParameterCount = cpu_to_le16(2);
5036 /* BB find max SMB PDU from sess */
5037 pSMB->MaxDataCount = cpu_to_le16(1000);
5038 pSMB->SetupCount = 1;
5039 pSMB->Reserved3 = 0;
5040 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
5041 byte_count = 3 /* pad */ + params + count;
5042 pSMB->DataCount = cpu_to_le16(count);
5043 pSMB->ParameterCount = cpu_to_le16(params);
5044 pSMB->TotalDataCount = pSMB->DataCount;
5045 pSMB->TotalParameterCount = pSMB->ParameterCount;
5046 pSMB->ParameterOffset = cpu_to_le16(param_offset);
5047 pSMB->DataOffset = cpu_to_le16(offset);
5049 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
5050 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO2);
5052 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO);
5053 pSMB->Reserved4 = 0;
5054 inc_rfc1001_len(pSMB, byte_count);
5055 pSMB->ByteCount = cpu_to_le16(byte_count);
5056 memcpy(data_offset, data, sizeof(FILE_BASIC_INFO));
5057 rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0);
5059 cFYI(1, "Send error in Set Time (SetFileInfo) = %d", rc);
5061 /* Note: On -EAGAIN error only caller can retry on handle based calls
5062 since file handle passed in no longer valid */
5068 CIFSSMBSetFileDisposition(const int xid, struct cifsTconInfo *tcon,
5069 bool delete_file, __u16 fid, __u32 pid_of_opener)
5071 struct smb_com_transaction2_sfi_req *pSMB = NULL;
5074 __u16 params, param_offset, offset, byte_count, count;
5076 cFYI(1, "Set File Disposition (via SetFileInfo)");
5077 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
5082 pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
5083 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));
5086 pSMB->MaxSetupCount = 0;
5090 pSMB->Reserved2 = 0;
5091 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
5092 offset = param_offset + params;
5094 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
5097 pSMB->MaxParameterCount = cpu_to_le16(2);
5098 /* BB find max SMB PDU from sess */
5099 pSMB->MaxDataCount = cpu_to_le16(1000);
5100 pSMB->SetupCount = 1;
5101 pSMB->Reserved3 = 0;
5102 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
5103 byte_count = 3 /* pad */ + params + count;
5104 pSMB->DataCount = cpu_to_le16(count);
5105 pSMB->ParameterCount = cpu_to_le16(params);
5106 pSMB->TotalDataCount = pSMB->DataCount;
5107 pSMB->TotalParameterCount = pSMB->ParameterCount;
5108 pSMB->ParameterOffset = cpu_to_le16(param_offset);
5109 pSMB->DataOffset = cpu_to_le16(offset);
5111 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_DISPOSITION_INFO);
5112 pSMB->Reserved4 = 0;
5113 inc_rfc1001_len(pSMB, byte_count);
5114 pSMB->ByteCount = cpu_to_le16(byte_count);
5115 *data_offset = delete_file ? 1 : 0;
5116 rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0);
5118 cFYI(1, "Send error in SetFileDisposition = %d", rc);
5124 CIFSSMBSetPathInfo(const int xid, struct cifsTconInfo *tcon,
5125 const char *fileName, const FILE_BASIC_INFO *data,
5126 const struct nls_table *nls_codepage, int remap)
5128 TRANSACTION2_SPI_REQ *pSMB = NULL;
5129 TRANSACTION2_SPI_RSP *pSMBr = NULL;
5132 int bytes_returned = 0;
5134 __u16 params, param_offset, offset, byte_count, count;
5136 cFYI(1, "In SetTimes");
5139 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5144 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5146 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
5147 PATH_MAX, nls_codepage, remap);
5148 name_len++; /* trailing null */
5150 } else { /* BB improve the check for buffer overruns BB */
5151 name_len = strnlen(fileName, PATH_MAX);
5152 name_len++; /* trailing null */
5153 strncpy(pSMB->FileName, fileName, name_len);
5156 params = 6 + name_len;
5157 count = sizeof(FILE_BASIC_INFO);
5158 pSMB->MaxParameterCount = cpu_to_le16(2);
5159 /* BB find max SMB PDU from sess structure BB */
5160 pSMB->MaxDataCount = cpu_to_le16(1000);
5161 pSMB->MaxSetupCount = 0;
5165 pSMB->Reserved2 = 0;
5166 param_offset = offsetof(struct smb_com_transaction2_spi_req,
5167 InformationLevel) - 4;
5168 offset = param_offset + params;
5169 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
5170 pSMB->ParameterOffset = cpu_to_le16(param_offset);
5171 pSMB->DataOffset = cpu_to_le16(offset);
5172 pSMB->SetupCount = 1;
5173 pSMB->Reserved3 = 0;
5174 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
5175 byte_count = 3 /* pad */ + params + count;
5177 pSMB->DataCount = cpu_to_le16(count);
5178 pSMB->ParameterCount = cpu_to_le16(params);
5179 pSMB->TotalDataCount = pSMB->DataCount;
5180 pSMB->TotalParameterCount = pSMB->ParameterCount;
5181 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
5182 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO2);
5184 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO);
5185 pSMB->Reserved4 = 0;
5186 inc_rfc1001_len(pSMB, byte_count);
5187 memcpy(data_offset, data, sizeof(FILE_BASIC_INFO));
5188 pSMB->ByteCount = cpu_to_le16(byte_count);
5189 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5190 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5192 cFYI(1, "SetPathInfo (times) returned %d", rc);
5194 cifs_buf_release(pSMB);
5202 /* Can not be used to set time stamps yet (due to old DOS time format) */
5203 /* Can be used to set attributes */
5204 #if 0 /* Possibly not needed - since it turns out that strangely NT4 has a bug
5205 handling it anyway and NT4 was what we thought it would be needed for
5206 Do not delete it until we prove whether needed for Win9x though */
5208 CIFSSMBSetAttrLegacy(int xid, struct cifsTconInfo *tcon, char *fileName,
5209 __u16 dos_attrs, const struct nls_table *nls_codepage)
5211 SETATTR_REQ *pSMB = NULL;
5212 SETATTR_RSP *pSMBr = NULL;
5217 cFYI(1, "In SetAttrLegacy");
5220 rc = smb_init(SMB_COM_SETATTR, 8, tcon, (void **) &pSMB,
5225 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5227 ConvertToUCS((__le16 *) pSMB->fileName, fileName,
5228 PATH_MAX, nls_codepage);
5229 name_len++; /* trailing null */
5231 } else { /* BB improve the check for buffer overruns BB */
5232 name_len = strnlen(fileName, PATH_MAX);
5233 name_len++; /* trailing null */
5234 strncpy(pSMB->fileName, fileName, name_len);
5236 pSMB->attr = cpu_to_le16(dos_attrs);
5237 pSMB->BufferFormat = 0x04;
5238 inc_rfc1001_len(pSMB, name_len + 1);
5239 pSMB->ByteCount = cpu_to_le16(name_len + 1);
5240 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5241 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5243 cFYI(1, "Error in LegacySetAttr = %d", rc);
5245 cifs_buf_release(pSMB);
5248 goto SetAttrLgcyRetry;
5252 #endif /* temporarily unneeded SetAttr legacy function */
5255 cifs_fill_unix_set_info(FILE_UNIX_BASIC_INFO *data_offset,
5256 const struct cifs_unix_set_info_args *args)
5258 u64 mode = args->mode;
5261 * Samba server ignores set of file size to zero due to bugs in some
5262 * older clients, but we should be precise - we use SetFileSize to
5263 * set file size and do not want to truncate file size to zero
5264 * accidentally as happened on one Samba server beta by putting
5265 * zero instead of -1 here
5267 data_offset->EndOfFile = cpu_to_le64(NO_CHANGE_64);
5268 data_offset->NumOfBytes = cpu_to_le64(NO_CHANGE_64);
5269 data_offset->LastStatusChange = cpu_to_le64(args->ctime);
5270 data_offset->LastAccessTime = cpu_to_le64(args->atime);
5271 data_offset->LastModificationTime = cpu_to_le64(args->mtime);
5272 data_offset->Uid = cpu_to_le64(args->uid);
5273 data_offset->Gid = cpu_to_le64(args->gid);
5274 /* better to leave device as zero when it is */
5275 data_offset->DevMajor = cpu_to_le64(MAJOR(args->device));
5276 data_offset->DevMinor = cpu_to_le64(MINOR(args->device));
5277 data_offset->Permissions = cpu_to_le64(mode);
5280 data_offset->Type = cpu_to_le32(UNIX_FILE);
5281 else if (S_ISDIR(mode))
5282 data_offset->Type = cpu_to_le32(UNIX_DIR);
5283 else if (S_ISLNK(mode))
5284 data_offset->Type = cpu_to_le32(UNIX_SYMLINK);
5285 else if (S_ISCHR(mode))
5286 data_offset->Type = cpu_to_le32(UNIX_CHARDEV);
5287 else if (S_ISBLK(mode))
5288 data_offset->Type = cpu_to_le32(UNIX_BLOCKDEV);
5289 else if (S_ISFIFO(mode))
5290 data_offset->Type = cpu_to_le32(UNIX_FIFO);
5291 else if (S_ISSOCK(mode))
5292 data_offset->Type = cpu_to_le32(UNIX_SOCKET);
5296 CIFSSMBUnixSetFileInfo(const int xid, struct cifsTconInfo *tcon,
5297 const struct cifs_unix_set_info_args *args,
5298 u16 fid, u32 pid_of_opener)
5300 struct smb_com_transaction2_sfi_req *pSMB = NULL;
5301 FILE_UNIX_BASIC_INFO *data_offset;
5303 u16 params, param_offset, offset, byte_count, count;
5305 cFYI(1, "Set Unix Info (via SetFileInfo)");
5306 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
5311 pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
5312 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));
5315 pSMB->MaxSetupCount = 0;
5319 pSMB->Reserved2 = 0;
5320 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
5321 offset = param_offset + params;
5323 data_offset = (FILE_UNIX_BASIC_INFO *)
5324 ((char *)(&pSMB->hdr.Protocol) + offset);
5325 count = sizeof(FILE_UNIX_BASIC_INFO);
5327 pSMB->MaxParameterCount = cpu_to_le16(2);
5328 /* BB find max SMB PDU from sess */
5329 pSMB->MaxDataCount = cpu_to_le16(1000);
5330 pSMB->SetupCount = 1;
5331 pSMB->Reserved3 = 0;
5332 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
5333 byte_count = 3 /* pad */ + params + count;
5334 pSMB->DataCount = cpu_to_le16(count);
5335 pSMB->ParameterCount = cpu_to_le16(params);
5336 pSMB->TotalDataCount = pSMB->DataCount;
5337 pSMB->TotalParameterCount = pSMB->ParameterCount;
5338 pSMB->ParameterOffset = cpu_to_le16(param_offset);
5339 pSMB->DataOffset = cpu_to_le16(offset);
5341 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_BASIC);
5342 pSMB->Reserved4 = 0;
5343 inc_rfc1001_len(pSMB, byte_count);
5344 pSMB->ByteCount = cpu_to_le16(byte_count);
5346 cifs_fill_unix_set_info(data_offset, args);
5348 rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0);
5350 cFYI(1, "Send error in Set Time (SetFileInfo) = %d", rc);
5352 /* Note: On -EAGAIN error only caller can retry on handle based calls
5353 since file handle passed in no longer valid */
5359 CIFSSMBUnixSetPathInfo(const int xid, struct cifsTconInfo *tcon, char *fileName,
5360 const struct cifs_unix_set_info_args *args,
5361 const struct nls_table *nls_codepage, int remap)
5363 TRANSACTION2_SPI_REQ *pSMB = NULL;
5364 TRANSACTION2_SPI_RSP *pSMBr = NULL;
5367 int bytes_returned = 0;
5368 FILE_UNIX_BASIC_INFO *data_offset;
5369 __u16 params, param_offset, offset, count, byte_count;
5371 cFYI(1, "In SetUID/GID/Mode");
5373 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5378 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5380 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
5381 PATH_MAX, nls_codepage, remap);
5382 name_len++; /* trailing null */
5384 } else { /* BB improve the check for buffer overruns BB */
5385 name_len = strnlen(fileName, PATH_MAX);
5386 name_len++; /* trailing null */
5387 strncpy(pSMB->FileName, fileName, name_len);
5390 params = 6 + name_len;
5391 count = sizeof(FILE_UNIX_BASIC_INFO);
5392 pSMB->MaxParameterCount = cpu_to_le16(2);
5393 /* BB find max SMB PDU from sess structure BB */
5394 pSMB->MaxDataCount = cpu_to_le16(1000);
5395 pSMB->MaxSetupCount = 0;
5399 pSMB->Reserved2 = 0;
5400 param_offset = offsetof(struct smb_com_transaction2_spi_req,
5401 InformationLevel) - 4;
5402 offset = param_offset + params;
5404 (FILE_UNIX_BASIC_INFO *) ((char *) &pSMB->hdr.Protocol +
5406 memset(data_offset, 0, count);
5407 pSMB->DataOffset = cpu_to_le16(offset);
5408 pSMB->ParameterOffset = cpu_to_le16(param_offset);
5409 pSMB->SetupCount = 1;
5410 pSMB->Reserved3 = 0;
5411 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
5412 byte_count = 3 /* pad */ + params + count;
5413 pSMB->ParameterCount = cpu_to_le16(params);
5414 pSMB->DataCount = cpu_to_le16(count);
5415 pSMB->TotalParameterCount = pSMB->ParameterCount;
5416 pSMB->TotalDataCount = pSMB->DataCount;
5417 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_BASIC);
5418 pSMB->Reserved4 = 0;
5419 inc_rfc1001_len(pSMB, byte_count);
5421 cifs_fill_unix_set_info(data_offset, args);
5423 pSMB->ByteCount = cpu_to_le16(byte_count);
5424 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5425 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5427 cFYI(1, "SetPathInfo (perms) returned %d", rc);
5429 cifs_buf_release(pSMB);
5435 #ifdef CONFIG_CIFS_XATTR
5437 * Do a path-based QUERY_ALL_EAS call and parse the result. This is a common
5438 * function used by listxattr and getxattr type calls. When ea_name is set,
5439 * it looks for that attribute name and stuffs that value into the EAData
5440 * buffer. When ea_name is NULL, it stuffs a list of attribute names into the
5441 * buffer. In both cases, the return value is either the length of the
5442 * resulting data or a negative error code. If EAData is a NULL pointer then
5443 * the data isn't copied to it, but the length is returned.
5446 CIFSSMBQAllEAs(const int xid, struct cifsTconInfo *tcon,
5447 const unsigned char *searchName, const unsigned char *ea_name,
5448 char *EAData, size_t buf_size,
5449 const struct nls_table *nls_codepage, int remap)
5451 /* BB assumes one setup word */
5452 TRANSACTION2_QPI_REQ *pSMB = NULL;
5453 TRANSACTION2_QPI_RSP *pSMBr = NULL;
5457 struct fealist *ea_response_data;
5458 struct fea *temp_fea;
5461 __u16 params, byte_count, data_offset;
5463 cFYI(1, "In Query All EAs path %s", searchName);
5465 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5470 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5472 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
5473 PATH_MAX, nls_codepage, remap);
5474 list_len++; /* trailing null */
5476 } else { /* BB improve the check for buffer overruns BB */
5477 list_len = strnlen(searchName, PATH_MAX);
5478 list_len++; /* trailing null */
5479 strncpy(pSMB->FileName, searchName, list_len);
5482 params = 2 /* level */ + 4 /* reserved */ + list_len /* includes NUL */;
5483 pSMB->TotalDataCount = 0;
5484 pSMB->MaxParameterCount = cpu_to_le16(2);
5485 /* BB find exact max SMB PDU from sess structure BB */
5486 pSMB->MaxDataCount = cpu_to_le16(CIFSMaxBufSize);
5487 pSMB->MaxSetupCount = 0;
5491 pSMB->Reserved2 = 0;
5492 pSMB->ParameterOffset = cpu_to_le16(offsetof(
5493 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
5494 pSMB->DataCount = 0;
5495 pSMB->DataOffset = 0;
5496 pSMB->SetupCount = 1;
5497 pSMB->Reserved3 = 0;
5498 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
5499 byte_count = params + 1 /* pad */ ;
5500 pSMB->TotalParameterCount = cpu_to_le16(params);
5501 pSMB->ParameterCount = pSMB->TotalParameterCount;
5502 pSMB->InformationLevel = cpu_to_le16(SMB_INFO_QUERY_ALL_EAS);
5503 pSMB->Reserved4 = 0;
5504 inc_rfc1001_len(pSMB, byte_count);
5505 pSMB->ByteCount = cpu_to_le16(byte_count);
5507 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5508 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5510 cFYI(1, "Send error in QueryAllEAs = %d", rc);
5515 /* BB also check enough total bytes returned */
5516 /* BB we need to improve the validity checking
5517 of these trans2 responses */
5519 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
5520 if (rc || (pSMBr->ByteCount < 4)) {
5521 rc = -EIO; /* bad smb */
5525 /* check that length of list is not more than bcc */
5526 /* check that each entry does not go beyond length
5528 /* check that each element of each entry does not
5529 go beyond end of list */
5530 /* validate_trans2_offsets() */
5531 /* BB check if start of smb + data_offset > &bcc+ bcc */
5533 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
5534 ea_response_data = (struct fealist *)
5535 (((char *) &pSMBr->hdr.Protocol) + data_offset);
5537 list_len = le32_to_cpu(ea_response_data->list_len);
5538 cFYI(1, "ea length %d", list_len);
5539 if (list_len <= 8) {
5540 cFYI(1, "empty EA list returned from server");
5544 /* make sure list_len doesn't go past end of SMB */
5545 end_of_smb = (char *)pByteArea(&pSMBr->hdr) + get_bcc(&pSMBr->hdr);
5546 if ((char *)ea_response_data + list_len > end_of_smb) {
5547 cFYI(1, "EA list appears to go beyond SMB");
5552 /* account for ea list len */
5554 temp_fea = ea_response_data->list;
5555 temp_ptr = (char *)temp_fea;
5556 while (list_len > 0) {
5557 unsigned int name_len;
5562 /* make sure we can read name_len and value_len */
5564 cFYI(1, "EA entry goes beyond length of list");
5569 name_len = temp_fea->name_len;
5570 value_len = le16_to_cpu(temp_fea->value_len);
5571 list_len -= name_len + 1 + value_len;
5573 cFYI(1, "EA entry goes beyond length of list");
5579 if (strncmp(ea_name, temp_ptr, name_len) == 0) {
5580 temp_ptr += name_len + 1;
5584 if ((size_t)value_len > buf_size) {
5588 memcpy(EAData, temp_ptr, value_len);
5592 /* account for prefix user. and trailing null */
5593 rc += (5 + 1 + name_len);
5594 if (rc < (int) buf_size) {
5595 memcpy(EAData, "user.", 5);
5597 memcpy(EAData, temp_ptr, name_len);
5599 /* null terminate name */
5602 } else if (buf_size == 0) {
5603 /* skip copy - calc size only */
5605 /* stop before overrun buffer */
5610 temp_ptr += name_len + 1 + value_len;
5611 temp_fea = (struct fea *)temp_ptr;
5614 /* didn't find the named attribute */
5619 cifs_buf_release(pSMB);
5627 CIFSSMBSetEA(const int xid, struct cifsTconInfo *tcon, const char *fileName,
5628 const char *ea_name, const void *ea_value,
5629 const __u16 ea_value_len, const struct nls_table *nls_codepage,
5632 struct smb_com_transaction2_spi_req *pSMB = NULL;
5633 struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
5634 struct fealist *parm_data;
5637 int bytes_returned = 0;
5638 __u16 params, param_offset, byte_count, offset, count;
5640 cFYI(1, "In SetEA");
5642 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5647 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5649 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
5650 PATH_MAX, nls_codepage, remap);
5651 name_len++; /* trailing null */
5653 } else { /* BB improve the check for buffer overruns BB */
5654 name_len = strnlen(fileName, PATH_MAX);
5655 name_len++; /* trailing null */
5656 strncpy(pSMB->FileName, fileName, name_len);
5659 params = 6 + name_len;
5661 /* done calculating parms using name_len of file name,
5662 now use name_len to calculate length of ea name
5663 we are going to create in the inode xattrs */
5664 if (ea_name == NULL)
5667 name_len = strnlen(ea_name, 255);
5669 count = sizeof(*parm_data) + ea_value_len + name_len;
5670 pSMB->MaxParameterCount = cpu_to_le16(2);
5671 /* BB find max SMB PDU from sess */
5672 pSMB->MaxDataCount = cpu_to_le16(1000);
5673 pSMB->MaxSetupCount = 0;
5677 pSMB->Reserved2 = 0;
5678 param_offset = offsetof(struct smb_com_transaction2_spi_req,
5679 InformationLevel) - 4;
5680 offset = param_offset + params;
5681 pSMB->InformationLevel =
5682 cpu_to_le16(SMB_SET_FILE_EA);
5685 (struct fealist *) (((char *) &pSMB->hdr.Protocol) +
5687 pSMB->ParameterOffset = cpu_to_le16(param_offset);
5688 pSMB->DataOffset = cpu_to_le16(offset);
5689 pSMB->SetupCount = 1;
5690 pSMB->Reserved3 = 0;
5691 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
5692 byte_count = 3 /* pad */ + params + count;
5693 pSMB->DataCount = cpu_to_le16(count);
5694 parm_data->list_len = cpu_to_le32(count);
5695 parm_data->list[0].EA_flags = 0;
5696 /* we checked above that name len is less than 255 */
5697 parm_data->list[0].name_len = (__u8)name_len;
5698 /* EA names are always ASCII */
5700 strncpy(parm_data->list[0].name, ea_name, name_len);
5701 parm_data->list[0].name[name_len] = 0;
5702 parm_data->list[0].value_len = cpu_to_le16(ea_value_len);
5703 /* caller ensures that ea_value_len is less than 64K but
5704 we need to ensure that it fits within the smb */
5706 /*BB add length check to see if it would fit in
5707 negotiated SMB buffer size BB */
5708 /* if (ea_value_len > buffer_size - 512 (enough for header)) */
5710 memcpy(parm_data->list[0].name+name_len+1,
5711 ea_value, ea_value_len);
5713 pSMB->TotalDataCount = pSMB->DataCount;
5714 pSMB->ParameterCount = cpu_to_le16(params);
5715 pSMB->TotalParameterCount = pSMB->ParameterCount;
5716 pSMB->Reserved4 = 0;
5717 inc_rfc1001_len(pSMB, byte_count);
5718 pSMB->ByteCount = cpu_to_le16(byte_count);
5719 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5720 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5722 cFYI(1, "SetPathInfo (EA) returned %d", rc);
5724 cifs_buf_release(pSMB);
5733 #ifdef CONFIG_CIFS_DNOTIFY_EXPERIMENTAL /* BB unused temporarily */
5735 * Years ago the kernel added a "dnotify" function for Samba server,
5736 * to allow network clients (such as Windows) to display updated
5737 * lists of files in directory listings automatically when
5738 * files are added by one user when another user has the
5739 * same directory open on their desktop. The Linux cifs kernel
5740 * client hooked into the kernel side of this interface for
5741 * the same reason, but ironically when the VFS moved from
5742 * "dnotify" to "inotify" it became harder to plug in Linux
5743 * network file system clients (the most obvious use case
5744 * for notify interfaces is when multiple users can update
5745 * the contents of the same directory - exactly what network
5746 * file systems can do) although the server (Samba) could
5747 * still use it. For the short term we leave the worker
5748 * function ifdeffed out (below) until inotify is fixed
5749 * in the VFS to make it easier to plug in network file
5750 * system clients. If inotify turns out to be permanently
5751 * incompatible for network fs clients, we could instead simply
5752 * expose this config flag by adding a future cifs (and smb2) notify ioctl.
5754 int CIFSSMBNotify(const int xid, struct cifsTconInfo *tcon,
5755 const int notify_subdirs, const __u16 netfid,
5756 __u32 filter, struct file *pfile, int multishot,
5757 const struct nls_table *nls_codepage)
5760 struct smb_com_transaction_change_notify_req *pSMB = NULL;
5761 struct smb_com_ntransaction_change_notify_rsp *pSMBr = NULL;
5762 struct dir_notify_req *dnotify_req;
5765 cFYI(1, "In CIFSSMBNotify for file handle %d", (int)netfid);
5766 rc = smb_init(SMB_COM_NT_TRANSACT, 23, tcon, (void **) &pSMB,
5771 pSMB->TotalParameterCount = 0 ;
5772 pSMB->TotalDataCount = 0;
5773 pSMB->MaxParameterCount = cpu_to_le32(2);
5774 /* BB find exact data count max from sess structure BB */
5775 pSMB->MaxDataCount = 0; /* same in little endian or be */
5776 /* BB VERIFY verify which is correct for above BB */
5777 pSMB->MaxDataCount = cpu_to_le32((tcon->ses->server->maxBuf -
5778 MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
5780 pSMB->MaxSetupCount = 4;
5782 pSMB->ParameterOffset = 0;
5783 pSMB->DataCount = 0;
5784 pSMB->DataOffset = 0;
5785 pSMB->SetupCount = 4; /* single byte does not need le conversion */
5786 pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_NOTIFY_CHANGE);
5787 pSMB->ParameterCount = pSMB->TotalParameterCount;
5789 pSMB->WatchTree = 1; /* one byte - no le conversion needed */
5790 pSMB->Reserved2 = 0;
5791 pSMB->CompletionFilter = cpu_to_le32(filter);
5792 pSMB->Fid = netfid; /* file handle always le */
5793 pSMB->ByteCount = 0;
5795 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5796 (struct smb_hdr *)pSMBr, &bytes_returned,
5799 cFYI(1, "Error in Notify = %d", rc);
5801 /* Add file to outstanding requests */
5802 /* BB change to kmem cache alloc */
5803 dnotify_req = kmalloc(
5804 sizeof(struct dir_notify_req),
5807 dnotify_req->Pid = pSMB->hdr.Pid;
5808 dnotify_req->PidHigh = pSMB->hdr.PidHigh;
5809 dnotify_req->Mid = pSMB->hdr.Mid;
5810 dnotify_req->Tid = pSMB->hdr.Tid;
5811 dnotify_req->Uid = pSMB->hdr.Uid;
5812 dnotify_req->netfid = netfid;
5813 dnotify_req->pfile = pfile;
5814 dnotify_req->filter = filter;
5815 dnotify_req->multishot = multishot;
5816 spin_lock(&GlobalMid_Lock);
5817 list_add_tail(&dnotify_req->lhead,
5818 &GlobalDnotifyReqList);
5819 spin_unlock(&GlobalMid_Lock);
5823 cifs_buf_release(pSMB);
5826 #endif /* was needed for dnotify, and will be needed for inotify when VFS fix */