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 <linux/pagemap.h>
36 #include <linux/swap.h>
37 #include <linux/task_io_accounting_ops.h>
38 #include <asm/uaccess.h>
42 #include "cifsproto.h"
43 #include "cifs_unicode.h"
44 #include "cifs_debug.h"
47 #ifdef CONFIG_CIFS_POSIX
52 #ifdef CONFIG_CIFS_WEAK_PW_HASH
53 {LANMAN_PROT, "\2LM1.2X002"},
54 {LANMAN2_PROT, "\2LANMAN2.1"},
55 #endif /* weak password hashing for legacy clients */
56 {CIFS_PROT, "\2NT LM 0.12"},
57 {POSIX_PROT, "\2POSIX 2"},
65 #ifdef CONFIG_CIFS_WEAK_PW_HASH
66 {LANMAN_PROT, "\2LM1.2X002"},
67 {LANMAN2_PROT, "\2LANMAN2.1"},
68 #endif /* weak password hashing for legacy clients */
69 {CIFS_PROT, "\2NT LM 0.12"},
74 /* define the number of elements in the cifs dialect array */
75 #ifdef CONFIG_CIFS_POSIX
76 #ifdef CONFIG_CIFS_WEAK_PW_HASH
77 #define CIFS_NUM_PROT 4
79 #define CIFS_NUM_PROT 2
80 #endif /* CIFS_WEAK_PW_HASH */
82 #ifdef CONFIG_CIFS_WEAK_PW_HASH
83 #define CIFS_NUM_PROT 3
85 #define CIFS_NUM_PROT 1
86 #endif /* CONFIG_CIFS_WEAK_PW_HASH */
87 #endif /* CIFS_POSIX */
89 /* Forward declarations */
90 static void cifs_readv_complete(struct work_struct *work);
92 /* Mark as invalid, all open files on tree connections since they
93 were closed when session to server was lost */
94 static void mark_open_files_invalid(struct cifs_tcon *pTcon)
96 struct cifsFileInfo *open_file = NULL;
97 struct list_head *tmp;
98 struct list_head *tmp1;
100 /* list all files open on tree connection and mark them invalid */
101 spin_lock(&cifs_file_list_lock);
102 list_for_each_safe(tmp, tmp1, &pTcon->openFileList) {
103 open_file = list_entry(tmp, struct cifsFileInfo, tlist);
104 open_file->invalidHandle = true;
105 open_file->oplock_break_cancelled = true;
107 spin_unlock(&cifs_file_list_lock);
108 /* BB Add call to invalidate_inodes(sb) for all superblocks mounted
112 /* reconnect the socket, tcon, and smb session if needed */
114 cifs_reconnect_tcon(struct cifs_tcon *tcon, int smb_command)
117 struct cifs_ses *ses;
118 struct TCP_Server_Info *server;
119 struct nls_table *nls_codepage;
122 * SMBs NegProt, SessSetup, uLogoff do not have tcon yet so check for
123 * tcp and smb session status done differently for those three - in the
130 server = ses->server;
133 * only tree disconnect, open, and write, (and ulogoff which does not
134 * have tcon) are allowed as we start force umount
136 if (tcon->tidStatus == CifsExiting) {
137 if (smb_command != SMB_COM_WRITE_ANDX &&
138 smb_command != SMB_COM_OPEN_ANDX &&
139 smb_command != SMB_COM_TREE_DISCONNECT) {
140 cFYI(1, "can not send cmd %d while umounting",
147 * Give demultiplex thread up to 10 seconds to reconnect, should be
148 * greater than cifs socket timeout which is 7 seconds
150 while (server->tcpStatus == CifsNeedReconnect) {
151 wait_event_interruptible_timeout(server->response_q,
152 (server->tcpStatus != CifsNeedReconnect), 10 * HZ);
154 /* are we still trying to reconnect? */
155 if (server->tcpStatus != CifsNeedReconnect)
159 * on "soft" mounts we wait once. Hard mounts keep
160 * retrying until process is killed or server comes
164 cFYI(1, "gave up waiting on reconnect in smb_init");
169 if (!ses->need_reconnect && !tcon->need_reconnect)
172 nls_codepage = load_nls_default();
175 * need to prevent multiple threads trying to simultaneously
176 * reconnect the same SMB session
178 mutex_lock(&ses->session_mutex);
179 rc = cifs_negotiate_protocol(0, ses);
180 if (rc == 0 && ses->need_reconnect)
181 rc = cifs_setup_session(0, ses, nls_codepage);
183 /* do we need to reconnect tcon? */
184 if (rc || !tcon->need_reconnect) {
185 mutex_unlock(&ses->session_mutex);
189 mark_open_files_invalid(tcon);
190 rc = CIFSTCon(0, ses, tcon->treeName, tcon, nls_codepage);
191 mutex_unlock(&ses->session_mutex);
192 cFYI(1, "reconnect tcon rc = %d", rc);
198 * FIXME: check if wsize needs updated due to negotiated smb buffer
201 atomic_inc(&tconInfoReconnectCount);
203 /* tell server Unix caps we support */
204 if (ses->capabilities & CAP_UNIX)
205 reset_cifs_unix_caps(0, tcon, NULL, NULL);
208 * Removed call to reopen open files here. It is safer (and faster) to
209 * reopen files one at a time as needed in read and write.
211 * FIXME: what about file locks? don't we need to reclaim them ASAP?
216 * Check if handle based operation so we know whether we can continue
217 * or not without returning to caller to reset file handle
219 switch (smb_command) {
220 case SMB_COM_READ_ANDX:
221 case SMB_COM_WRITE_ANDX:
223 case SMB_COM_FIND_CLOSE2:
224 case SMB_COM_LOCKING_ANDX:
228 unload_nls(nls_codepage);
232 /* Allocate and return pointer to an SMB request buffer, and set basic
233 SMB information in the SMB header. If the return code is zero, this
234 function must have filled in request_buf pointer */
236 small_smb_init(int smb_command, int wct, struct cifs_tcon *tcon,
241 rc = cifs_reconnect_tcon(tcon, smb_command);
245 *request_buf = cifs_small_buf_get();
246 if (*request_buf == NULL) {
247 /* BB should we add a retry in here if not a writepage? */
251 header_assemble((struct smb_hdr *) *request_buf, smb_command,
255 cifs_stats_inc(&tcon->num_smbs_sent);
261 small_smb_init_no_tc(const int smb_command, const int wct,
262 struct cifs_ses *ses, void **request_buf)
265 struct smb_hdr *buffer;
267 rc = small_smb_init(smb_command, wct, NULL, request_buf);
271 buffer = (struct smb_hdr *)*request_buf;
272 buffer->Mid = GetNextMid(ses->server);
273 if (ses->capabilities & CAP_UNICODE)
274 buffer->Flags2 |= SMBFLG2_UNICODE;
275 if (ses->capabilities & CAP_STATUS32)
276 buffer->Flags2 |= SMBFLG2_ERR_STATUS;
278 /* uid, tid can stay at zero as set in header assemble */
280 /* BB add support for turning on the signing when
281 this function is used after 1st of session setup requests */
286 /* If the return code is zero, this function must fill in request_buf pointer */
288 __smb_init(int smb_command, int wct, struct cifs_tcon *tcon,
289 void **request_buf, void **response_buf)
291 *request_buf = cifs_buf_get();
292 if (*request_buf == NULL) {
293 /* BB should we add a retry in here if not a writepage? */
296 /* Although the original thought was we needed the response buf for */
297 /* potential retries of smb operations it turns out we can determine */
298 /* from the mid flags when the request buffer can be resent without */
299 /* having to use a second distinct buffer for the response */
301 *response_buf = *request_buf;
303 header_assemble((struct smb_hdr *) *request_buf, smb_command, tcon,
307 cifs_stats_inc(&tcon->num_smbs_sent);
312 /* If the return code is zero, this function must fill in request_buf pointer */
314 smb_init(int smb_command, int wct, struct cifs_tcon *tcon,
315 void **request_buf, void **response_buf)
319 rc = cifs_reconnect_tcon(tcon, smb_command);
323 return __smb_init(smb_command, wct, tcon, request_buf, response_buf);
327 smb_init_no_reconnect(int smb_command, int wct, struct cifs_tcon *tcon,
328 void **request_buf, void **response_buf)
330 if (tcon->ses->need_reconnect || tcon->need_reconnect)
333 return __smb_init(smb_command, wct, tcon, request_buf, response_buf);
336 static int validate_t2(struct smb_t2_rsp *pSMB)
338 unsigned int total_size;
340 /* check for plausible wct */
341 if (pSMB->hdr.WordCount < 10)
344 /* check for parm and data offset going beyond end of smb */
345 if (get_unaligned_le16(&pSMB->t2_rsp.ParameterOffset) > 1024 ||
346 get_unaligned_le16(&pSMB->t2_rsp.DataOffset) > 1024)
349 total_size = get_unaligned_le16(&pSMB->t2_rsp.ParameterCount);
350 if (total_size >= 512)
353 /* check that bcc is at least as big as parms + data, and that it is
354 * less than negotiated smb buffer
356 total_size += get_unaligned_le16(&pSMB->t2_rsp.DataCount);
357 if (total_size > get_bcc(&pSMB->hdr) ||
358 total_size >= CIFSMaxBufSize + MAX_CIFS_HDR_SIZE)
363 cifs_dump_mem("Invalid transact2 SMB: ", (char *)pSMB,
364 sizeof(struct smb_t2_rsp) + 16);
368 static inline void inc_rfc1001_len(void *pSMB, int count)
370 struct smb_hdr *hdr = (struct smb_hdr *)pSMB;
372 be32_add_cpu(&hdr->smb_buf_length, count);
376 CIFSSMBNegotiate(unsigned int xid, struct cifs_ses *ses)
379 NEGOTIATE_RSP *pSMBr;
383 struct TCP_Server_Info *server;
385 unsigned int secFlags;
388 server = ses->server;
393 rc = smb_init(SMB_COM_NEGOTIATE, 0, NULL /* no tcon yet */ ,
394 (void **) &pSMB, (void **) &pSMBr);
398 /* if any of auth flags (ie not sign or seal) are overriden use them */
399 if (ses->overrideSecFlg & (~(CIFSSEC_MUST_SIGN | CIFSSEC_MUST_SEAL)))
400 secFlags = ses->overrideSecFlg; /* BB FIXME fix sign flags? */
401 else /* if override flags set only sign/seal OR them with global auth */
402 secFlags = global_secflags | ses->overrideSecFlg;
404 cFYI(1, "secFlags 0x%x", secFlags);
406 pSMB->hdr.Mid = GetNextMid(server);
407 pSMB->hdr.Flags2 |= (SMBFLG2_UNICODE | SMBFLG2_ERR_STATUS);
409 if ((secFlags & CIFSSEC_MUST_KRB5) == CIFSSEC_MUST_KRB5)
410 pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC;
411 else if ((secFlags & CIFSSEC_AUTH_MASK) == CIFSSEC_MAY_KRB5) {
412 cFYI(1, "Kerberos only mechanism, enable extended security");
413 pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC;
414 } else if ((secFlags & CIFSSEC_MUST_NTLMSSP) == CIFSSEC_MUST_NTLMSSP)
415 pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC;
416 else if ((secFlags & CIFSSEC_AUTH_MASK) == CIFSSEC_MAY_NTLMSSP) {
417 cFYI(1, "NTLMSSP only mechanism, enable extended security");
418 pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC;
422 for (i = 0; i < CIFS_NUM_PROT; i++) {
423 strncpy(pSMB->DialectsArray+count, protocols[i].name, 16);
424 count += strlen(protocols[i].name) + 1;
425 /* null at end of source and target buffers anyway */
427 inc_rfc1001_len(pSMB, count);
428 pSMB->ByteCount = cpu_to_le16(count);
430 rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB,
431 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
435 server->dialect = le16_to_cpu(pSMBr->DialectIndex);
436 cFYI(1, "Dialect: %d", server->dialect);
437 /* Check wct = 1 error case */
438 if ((pSMBr->hdr.WordCount < 13) || (server->dialect == BAD_PROT)) {
439 /* core returns wct = 1, but we do not ask for core - otherwise
440 small wct just comes when dialect index is -1 indicating we
441 could not negotiate a common dialect */
444 #ifdef CONFIG_CIFS_WEAK_PW_HASH
445 } else if ((pSMBr->hdr.WordCount == 13)
446 && ((server->dialect == LANMAN_PROT)
447 || (server->dialect == LANMAN2_PROT))) {
449 struct lanman_neg_rsp *rsp = (struct lanman_neg_rsp *)pSMBr;
451 if ((secFlags & CIFSSEC_MAY_LANMAN) ||
452 (secFlags & CIFSSEC_MAY_PLNTXT))
453 server->secType = LANMAN;
455 cERROR(1, "mount failed weak security disabled"
456 " in /proc/fs/cifs/SecurityFlags");
460 server->sec_mode = (__u8)le16_to_cpu(rsp->SecurityMode);
461 server->maxReq = min_t(unsigned int,
462 le16_to_cpu(rsp->MaxMpxCount),
464 server->oplocks = server->maxReq > 1 ? enable_oplocks : false;
465 server->maxBuf = le16_to_cpu(rsp->MaxBufSize);
466 server->max_vcs = le16_to_cpu(rsp->MaxNumberVcs);
467 /* even though we do not use raw we might as well set this
468 accurately, in case we ever find a need for it */
469 if ((le16_to_cpu(rsp->RawMode) & RAW_ENABLE) == RAW_ENABLE) {
470 server->max_rw = 0xFF00;
471 server->capabilities = CAP_MPX_MODE | CAP_RAW_MODE;
473 server->max_rw = 0;/* do not need to use raw anyway */
474 server->capabilities = CAP_MPX_MODE;
476 tmp = (__s16)le16_to_cpu(rsp->ServerTimeZone);
478 /* OS/2 often does not set timezone therefore
479 * we must use server time to calc time zone.
480 * Could deviate slightly from the right zone.
481 * Smallest defined timezone difference is 15 minutes
482 * (i.e. Nepal). Rounding up/down is done to match
485 int val, seconds, remain, result;
486 struct timespec ts, utc;
488 ts = cnvrtDosUnixTm(rsp->SrvTime.Date,
489 rsp->SrvTime.Time, 0);
490 cFYI(1, "SrvTime %d sec since 1970 (utc: %d) diff: %d",
491 (int)ts.tv_sec, (int)utc.tv_sec,
492 (int)(utc.tv_sec - ts.tv_sec));
493 val = (int)(utc.tv_sec - ts.tv_sec);
495 result = (seconds / MIN_TZ_ADJ) * MIN_TZ_ADJ;
496 remain = seconds % MIN_TZ_ADJ;
497 if (remain >= (MIN_TZ_ADJ / 2))
498 result += MIN_TZ_ADJ;
501 server->timeAdj = result;
503 server->timeAdj = (int)tmp;
504 server->timeAdj *= 60; /* also in seconds */
506 cFYI(1, "server->timeAdj: %d seconds", server->timeAdj);
509 /* BB get server time for time conversions and add
510 code to use it and timezone since this is not UTC */
512 if (rsp->EncryptionKeyLength ==
513 cpu_to_le16(CIFS_CRYPTO_KEY_SIZE)) {
514 memcpy(ses->server->cryptkey, rsp->EncryptionKey,
515 CIFS_CRYPTO_KEY_SIZE);
516 } else if (server->sec_mode & SECMODE_PW_ENCRYPT) {
517 rc = -EIO; /* need cryptkey unless plain text */
521 cFYI(1, "LANMAN negotiated");
522 /* we will not end up setting signing flags - as no signing
523 was in LANMAN and server did not return the flags on */
525 #else /* weak security disabled */
526 } else if (pSMBr->hdr.WordCount == 13) {
527 cERROR(1, "mount failed, cifs module not built "
528 "with CIFS_WEAK_PW_HASH support");
530 #endif /* WEAK_PW_HASH */
532 } else if (pSMBr->hdr.WordCount != 17) {
537 /* else wct == 17 NTLM */
538 server->sec_mode = pSMBr->SecurityMode;
539 if ((server->sec_mode & SECMODE_USER) == 0)
540 cFYI(1, "share mode security");
542 if ((server->sec_mode & SECMODE_PW_ENCRYPT) == 0)
543 #ifdef CONFIG_CIFS_WEAK_PW_HASH
544 if ((secFlags & CIFSSEC_MAY_PLNTXT) == 0)
545 #endif /* CIFS_WEAK_PW_HASH */
546 cERROR(1, "Server requests plain text password"
547 " but client support disabled");
549 if ((secFlags & CIFSSEC_MUST_NTLMV2) == CIFSSEC_MUST_NTLMV2)
550 server->secType = NTLMv2;
551 else if (secFlags & CIFSSEC_MAY_NTLM)
552 server->secType = NTLM;
553 else if (secFlags & CIFSSEC_MAY_NTLMV2)
554 server->secType = NTLMv2;
555 else if (secFlags & CIFSSEC_MAY_KRB5)
556 server->secType = Kerberos;
557 else if (secFlags & CIFSSEC_MAY_NTLMSSP)
558 server->secType = RawNTLMSSP;
559 else if (secFlags & CIFSSEC_MAY_LANMAN)
560 server->secType = LANMAN;
563 cERROR(1, "Invalid security type");
566 /* else ... any others ...? */
568 /* one byte, so no need to convert this or EncryptionKeyLen from
570 server->maxReq = min_t(unsigned int, le16_to_cpu(pSMBr->MaxMpxCount),
572 server->oplocks = server->maxReq > 1 ? enable_oplocks : false;
573 /* probably no need to store and check maxvcs */
574 server->maxBuf = le32_to_cpu(pSMBr->MaxBufferSize);
575 server->max_rw = le32_to_cpu(pSMBr->MaxRawSize);
576 cFYI(DBG2, "Max buf = %d", ses->server->maxBuf);
577 server->capabilities = le32_to_cpu(pSMBr->Capabilities);
578 server->timeAdj = (int)(__s16)le16_to_cpu(pSMBr->ServerTimeZone);
579 server->timeAdj *= 60;
580 if (pSMBr->EncryptionKeyLength == CIFS_CRYPTO_KEY_SIZE) {
581 memcpy(ses->server->cryptkey, pSMBr->u.EncryptionKey,
582 CIFS_CRYPTO_KEY_SIZE);
583 } else if ((pSMBr->hdr.Flags2 & SMBFLG2_EXT_SEC ||
584 server->capabilities & CAP_EXTENDED_SECURITY) &&
585 (pSMBr->EncryptionKeyLength == 0)) {
586 /* decode security blob */
587 count = get_bcc(&pSMBr->hdr);
592 spin_lock(&cifs_tcp_ses_lock);
593 if (server->srv_count > 1) {
594 spin_unlock(&cifs_tcp_ses_lock);
595 if (memcmp(server->server_GUID,
596 pSMBr->u.extended_response.
598 cFYI(1, "server UID changed");
599 memcpy(server->server_GUID,
600 pSMBr->u.extended_response.GUID,
604 spin_unlock(&cifs_tcp_ses_lock);
605 memcpy(server->server_GUID,
606 pSMBr->u.extended_response.GUID, 16);
610 server->secType = RawNTLMSSP;
612 rc = decode_negTokenInit(pSMBr->u.extended_response.
613 SecurityBlob, count - 16,
619 if (server->secType == Kerberos) {
620 if (!server->sec_kerberos &&
621 !server->sec_mskerberos)
623 } else if (server->secType == RawNTLMSSP) {
624 if (!server->sec_ntlmssp)
629 } else if (server->sec_mode & SECMODE_PW_ENCRYPT) {
630 rc = -EIO; /* no crypt key only if plain text pwd */
633 server->capabilities &= ~CAP_EXTENDED_SECURITY;
635 #ifdef CONFIG_CIFS_WEAK_PW_HASH
638 if ((secFlags & CIFSSEC_MAY_SIGN) == 0) {
639 /* MUST_SIGN already includes the MAY_SIGN FLAG
640 so if this is zero it means that signing is disabled */
641 cFYI(1, "Signing disabled");
642 if (server->sec_mode & SECMODE_SIGN_REQUIRED) {
643 cERROR(1, "Server requires "
644 "packet signing to be enabled in "
645 "/proc/fs/cifs/SecurityFlags.");
649 ~(SECMODE_SIGN_ENABLED | SECMODE_SIGN_REQUIRED);
650 } else if ((secFlags & CIFSSEC_MUST_SIGN) == CIFSSEC_MUST_SIGN) {
651 /* signing required */
652 cFYI(1, "Must sign - secFlags 0x%x", secFlags);
653 if ((server->sec_mode &
654 (SECMODE_SIGN_ENABLED | SECMODE_SIGN_REQUIRED)) == 0) {
655 cERROR(1, "signing required but server lacks support");
658 server->sec_mode |= SECMODE_SIGN_REQUIRED;
660 /* signing optional ie CIFSSEC_MAY_SIGN */
661 if ((server->sec_mode & SECMODE_SIGN_REQUIRED) == 0)
663 ~(SECMODE_SIGN_ENABLED | SECMODE_SIGN_REQUIRED);
667 cifs_buf_release(pSMB);
669 cFYI(1, "negprot rc %d", rc);
674 CIFSSMBTDis(const int xid, struct cifs_tcon *tcon)
676 struct smb_hdr *smb_buffer;
679 cFYI(1, "In tree disconnect");
681 /* BB: do we need to check this? These should never be NULL. */
682 if ((tcon->ses == NULL) || (tcon->ses->server == NULL))
686 * No need to return error on this operation if tid invalidated and
687 * closed on server already e.g. due to tcp session crashing. Also,
688 * the tcon is no longer on the list, so no need to take lock before
691 if ((tcon->need_reconnect) || (tcon->ses->need_reconnect))
694 rc = small_smb_init(SMB_COM_TREE_DISCONNECT, 0, tcon,
695 (void **)&smb_buffer);
699 rc = SendReceiveNoRsp(xid, tcon->ses, smb_buffer, 0);
701 cFYI(1, "Tree disconnect failed %d", rc);
703 /* No need to return error on this operation if tid invalidated and
704 closed on server already e.g. due to tcp session crashing */
712 * This is a no-op for now. We're not really interested in the reply, but
713 * rather in the fact that the server sent one and that server->lstrp
716 * FIXME: maybe we should consider checking that the reply matches request?
719 cifs_echo_callback(struct mid_q_entry *mid)
721 struct TCP_Server_Info *server = mid->callback_data;
723 DeleteMidQEntry(mid);
724 atomic_dec(&server->inFlight);
725 wake_up(&server->request_q);
729 CIFSSMBEcho(struct TCP_Server_Info *server)
735 cFYI(1, "In echo request");
737 rc = small_smb_init(SMB_COM_ECHO, 0, NULL, (void **)&smb);
741 /* set up echo request */
742 smb->hdr.Tid = 0xffff;
743 smb->hdr.WordCount = 1;
744 put_unaligned_le16(1, &smb->EchoCount);
745 put_bcc(1, &smb->hdr);
747 inc_rfc1001_len(smb, 3);
749 iov.iov_len = be32_to_cpu(smb->hdr.smb_buf_length) + 4;
751 rc = cifs_call_async(server, &iov, 1, NULL, cifs_echo_callback,
754 cFYI(1, "Echo request failed: %d", rc);
756 cifs_small_buf_release(smb);
762 CIFSSMBLogoff(const int xid, struct cifs_ses *ses)
764 LOGOFF_ANDX_REQ *pSMB;
767 cFYI(1, "In SMBLogoff for session disconnect");
770 * BB: do we need to check validity of ses and server? They should
771 * always be valid since we have an active reference. If not, that
772 * should probably be a BUG()
774 if (!ses || !ses->server)
777 mutex_lock(&ses->session_mutex);
778 if (ses->need_reconnect)
779 goto session_already_dead; /* no need to send SMBlogoff if uid
780 already closed due to reconnect */
781 rc = small_smb_init(SMB_COM_LOGOFF_ANDX, 2, NULL, (void **)&pSMB);
783 mutex_unlock(&ses->session_mutex);
787 pSMB->hdr.Mid = GetNextMid(ses->server);
789 if (ses->server->sec_mode &
790 (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
791 pSMB->hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
793 pSMB->hdr.Uid = ses->Suid;
795 pSMB->AndXCommand = 0xFF;
796 rc = SendReceiveNoRsp(xid, ses, (struct smb_hdr *) pSMB, 0);
797 session_already_dead:
798 mutex_unlock(&ses->session_mutex);
800 /* if session dead then we do not need to do ulogoff,
801 since server closed smb session, no sense reporting
809 CIFSPOSIXDelFile(const int xid, struct cifs_tcon *tcon, const char *fileName,
810 __u16 type, const struct nls_table *nls_codepage, int remap)
812 TRANSACTION2_SPI_REQ *pSMB = NULL;
813 TRANSACTION2_SPI_RSP *pSMBr = NULL;
814 struct unlink_psx_rq *pRqD;
817 int bytes_returned = 0;
818 __u16 params, param_offset, offset, byte_count;
820 cFYI(1, "In POSIX delete");
822 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
827 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
829 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
830 PATH_MAX, nls_codepage, remap);
831 name_len++; /* trailing null */
833 } else { /* BB add path length overrun check */
834 name_len = strnlen(fileName, PATH_MAX);
835 name_len++; /* trailing null */
836 strncpy(pSMB->FileName, fileName, name_len);
839 params = 6 + name_len;
840 pSMB->MaxParameterCount = cpu_to_le16(2);
841 pSMB->MaxDataCount = 0; /* BB double check this with jra */
842 pSMB->MaxSetupCount = 0;
847 param_offset = offsetof(struct smb_com_transaction2_spi_req,
848 InformationLevel) - 4;
849 offset = param_offset + params;
851 /* Setup pointer to Request Data (inode type) */
852 pRqD = (struct unlink_psx_rq *)(((char *)&pSMB->hdr.Protocol) + offset);
853 pRqD->type = cpu_to_le16(type);
854 pSMB->ParameterOffset = cpu_to_le16(param_offset);
855 pSMB->DataOffset = cpu_to_le16(offset);
856 pSMB->SetupCount = 1;
858 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
859 byte_count = 3 /* pad */ + params + sizeof(struct unlink_psx_rq);
861 pSMB->DataCount = cpu_to_le16(sizeof(struct unlink_psx_rq));
862 pSMB->TotalDataCount = cpu_to_le16(sizeof(struct unlink_psx_rq));
863 pSMB->ParameterCount = cpu_to_le16(params);
864 pSMB->TotalParameterCount = pSMB->ParameterCount;
865 pSMB->InformationLevel = cpu_to_le16(SMB_POSIX_UNLINK);
867 inc_rfc1001_len(pSMB, byte_count);
868 pSMB->ByteCount = cpu_to_le16(byte_count);
869 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
870 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
872 cFYI(1, "Posix delete returned %d", rc);
873 cifs_buf_release(pSMB);
875 cifs_stats_inc(&tcon->num_deletes);
884 CIFSSMBDelFile(const int xid, struct cifs_tcon *tcon, const char *fileName,
885 const struct nls_table *nls_codepage, int remap)
887 DELETE_FILE_REQ *pSMB = NULL;
888 DELETE_FILE_RSP *pSMBr = NULL;
894 rc = smb_init(SMB_COM_DELETE, 1, tcon, (void **) &pSMB,
899 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
901 cifsConvertToUCS((__le16 *) pSMB->fileName, fileName,
902 PATH_MAX, nls_codepage, remap);
903 name_len++; /* trailing null */
905 } else { /* BB improve check for buffer overruns BB */
906 name_len = strnlen(fileName, PATH_MAX);
907 name_len++; /* trailing null */
908 strncpy(pSMB->fileName, fileName, name_len);
910 pSMB->SearchAttributes =
911 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM);
912 pSMB->BufferFormat = 0x04;
913 inc_rfc1001_len(pSMB, name_len + 1);
914 pSMB->ByteCount = cpu_to_le16(name_len + 1);
915 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
916 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
917 cifs_stats_inc(&tcon->num_deletes);
919 cFYI(1, "Error in RMFile = %d", rc);
921 cifs_buf_release(pSMB);
929 CIFSSMBRmDir(const int xid, struct cifs_tcon *tcon, const char *dirName,
930 const struct nls_table *nls_codepage, int remap)
932 DELETE_DIRECTORY_REQ *pSMB = NULL;
933 DELETE_DIRECTORY_RSP *pSMBr = NULL;
938 cFYI(1, "In CIFSSMBRmDir");
940 rc = smb_init(SMB_COM_DELETE_DIRECTORY, 0, tcon, (void **) &pSMB,
945 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
946 name_len = cifsConvertToUCS((__le16 *) pSMB->DirName, dirName,
947 PATH_MAX, nls_codepage, remap);
948 name_len++; /* trailing null */
950 } else { /* BB improve check for buffer overruns BB */
951 name_len = strnlen(dirName, PATH_MAX);
952 name_len++; /* trailing null */
953 strncpy(pSMB->DirName, dirName, name_len);
956 pSMB->BufferFormat = 0x04;
957 inc_rfc1001_len(pSMB, name_len + 1);
958 pSMB->ByteCount = cpu_to_le16(name_len + 1);
959 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
960 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
961 cifs_stats_inc(&tcon->num_rmdirs);
963 cFYI(1, "Error in RMDir = %d", rc);
965 cifs_buf_release(pSMB);
972 CIFSSMBMkDir(const int xid, struct cifs_tcon *tcon,
973 const char *name, const struct nls_table *nls_codepage, int remap)
976 CREATE_DIRECTORY_REQ *pSMB = NULL;
977 CREATE_DIRECTORY_RSP *pSMBr = NULL;
981 cFYI(1, "In CIFSSMBMkDir");
983 rc = smb_init(SMB_COM_CREATE_DIRECTORY, 0, tcon, (void **) &pSMB,
988 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
989 name_len = cifsConvertToUCS((__le16 *) pSMB->DirName, name,
990 PATH_MAX, nls_codepage, remap);
991 name_len++; /* trailing null */
993 } else { /* BB improve check for buffer overruns BB */
994 name_len = strnlen(name, PATH_MAX);
995 name_len++; /* trailing null */
996 strncpy(pSMB->DirName, name, name_len);
999 pSMB->BufferFormat = 0x04;
1000 inc_rfc1001_len(pSMB, name_len + 1);
1001 pSMB->ByteCount = cpu_to_le16(name_len + 1);
1002 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1003 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1004 cifs_stats_inc(&tcon->num_mkdirs);
1006 cFYI(1, "Error in Mkdir = %d", rc);
1008 cifs_buf_release(pSMB);
1015 CIFSPOSIXCreate(const int xid, struct cifs_tcon *tcon, __u32 posix_flags,
1016 __u64 mode, __u16 *netfid, FILE_UNIX_BASIC_INFO *pRetData,
1017 __u32 *pOplock, const char *name,
1018 const struct nls_table *nls_codepage, int remap)
1020 TRANSACTION2_SPI_REQ *pSMB = NULL;
1021 TRANSACTION2_SPI_RSP *pSMBr = NULL;
1024 int bytes_returned = 0;
1025 __u16 params, param_offset, offset, byte_count, count;
1026 OPEN_PSX_REQ *pdata;
1027 OPEN_PSX_RSP *psx_rsp;
1029 cFYI(1, "In POSIX Create");
1031 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
1036 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1038 cifsConvertToUCS((__le16 *) pSMB->FileName, name,
1039 PATH_MAX, nls_codepage, remap);
1040 name_len++; /* trailing null */
1042 } else { /* BB improve the check for buffer overruns BB */
1043 name_len = strnlen(name, PATH_MAX);
1044 name_len++; /* trailing null */
1045 strncpy(pSMB->FileName, name, name_len);
1048 params = 6 + name_len;
1049 count = sizeof(OPEN_PSX_REQ);
1050 pSMB->MaxParameterCount = cpu_to_le16(2);
1051 pSMB->MaxDataCount = cpu_to_le16(1000); /* large enough */
1052 pSMB->MaxSetupCount = 0;
1056 pSMB->Reserved2 = 0;
1057 param_offset = offsetof(struct smb_com_transaction2_spi_req,
1058 InformationLevel) - 4;
1059 offset = param_offset + params;
1060 pdata = (OPEN_PSX_REQ *)(((char *)&pSMB->hdr.Protocol) + offset);
1061 pdata->Level = cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC);
1062 pdata->Permissions = cpu_to_le64(mode);
1063 pdata->PosixOpenFlags = cpu_to_le32(posix_flags);
1064 pdata->OpenFlags = cpu_to_le32(*pOplock);
1065 pSMB->ParameterOffset = cpu_to_le16(param_offset);
1066 pSMB->DataOffset = cpu_to_le16(offset);
1067 pSMB->SetupCount = 1;
1068 pSMB->Reserved3 = 0;
1069 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
1070 byte_count = 3 /* pad */ + params + count;
1072 pSMB->DataCount = cpu_to_le16(count);
1073 pSMB->ParameterCount = cpu_to_le16(params);
1074 pSMB->TotalDataCount = pSMB->DataCount;
1075 pSMB->TotalParameterCount = pSMB->ParameterCount;
1076 pSMB->InformationLevel = cpu_to_le16(SMB_POSIX_OPEN);
1077 pSMB->Reserved4 = 0;
1078 inc_rfc1001_len(pSMB, byte_count);
1079 pSMB->ByteCount = cpu_to_le16(byte_count);
1080 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1081 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1083 cFYI(1, "Posix create returned %d", rc);
1084 goto psx_create_err;
1087 cFYI(1, "copying inode info");
1088 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
1090 if (rc || get_bcc(&pSMBr->hdr) < sizeof(OPEN_PSX_RSP)) {
1091 rc = -EIO; /* bad smb */
1092 goto psx_create_err;
1095 /* copy return information to pRetData */
1096 psx_rsp = (OPEN_PSX_RSP *)((char *) &pSMBr->hdr.Protocol
1097 + le16_to_cpu(pSMBr->t2.DataOffset));
1099 *pOplock = le16_to_cpu(psx_rsp->OplockFlags);
1101 *netfid = psx_rsp->Fid; /* cifs fid stays in le */
1102 /* Let caller know file was created so we can set the mode. */
1103 /* Do we care about the CreateAction in any other cases? */
1104 if (cpu_to_le32(FILE_CREATE) == psx_rsp->CreateAction)
1105 *pOplock |= CIFS_CREATE_ACTION;
1106 /* check to make sure response data is there */
1107 if (psx_rsp->ReturnedLevel != cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC)) {
1108 pRetData->Type = cpu_to_le32(-1); /* unknown */
1109 cFYI(DBG2, "unknown type");
1111 if (get_bcc(&pSMBr->hdr) < sizeof(OPEN_PSX_RSP)
1112 + sizeof(FILE_UNIX_BASIC_INFO)) {
1113 cERROR(1, "Open response data too small");
1114 pRetData->Type = cpu_to_le32(-1);
1115 goto psx_create_err;
1117 memcpy((char *) pRetData,
1118 (char *)psx_rsp + sizeof(OPEN_PSX_RSP),
1119 sizeof(FILE_UNIX_BASIC_INFO));
1123 cifs_buf_release(pSMB);
1125 if (posix_flags & SMB_O_DIRECTORY)
1126 cifs_stats_inc(&tcon->num_posixmkdirs);
1128 cifs_stats_inc(&tcon->num_posixopens);
1136 static __u16 convert_disposition(int disposition)
1140 switch (disposition) {
1141 case FILE_SUPERSEDE:
1142 ofun = SMBOPEN_OCREATE | SMBOPEN_OTRUNC;
1145 ofun = SMBOPEN_OAPPEND;
1148 ofun = SMBOPEN_OCREATE;
1151 ofun = SMBOPEN_OCREATE | SMBOPEN_OAPPEND;
1153 case FILE_OVERWRITE:
1154 ofun = SMBOPEN_OTRUNC;
1156 case FILE_OVERWRITE_IF:
1157 ofun = SMBOPEN_OCREATE | SMBOPEN_OTRUNC;
1160 cFYI(1, "unknown disposition %d", disposition);
1161 ofun = SMBOPEN_OAPPEND; /* regular open */
1167 access_flags_to_smbopen_mode(const int access_flags)
1169 int masked_flags = access_flags & (GENERIC_READ | GENERIC_WRITE);
1171 if (masked_flags == GENERIC_READ)
1172 return SMBOPEN_READ;
1173 else if (masked_flags == GENERIC_WRITE)
1174 return SMBOPEN_WRITE;
1176 /* just go for read/write */
1177 return SMBOPEN_READWRITE;
1181 SMBLegacyOpen(const int xid, struct cifs_tcon *tcon,
1182 const char *fileName, const int openDisposition,
1183 const int access_flags, const int create_options, __u16 *netfid,
1184 int *pOplock, FILE_ALL_INFO *pfile_info,
1185 const struct nls_table *nls_codepage, int remap)
1188 OPENX_REQ *pSMB = NULL;
1189 OPENX_RSP *pSMBr = NULL;
1195 rc = smb_init(SMB_COM_OPEN_ANDX, 15, tcon, (void **) &pSMB,
1200 pSMB->AndXCommand = 0xFF; /* none */
1202 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1203 count = 1; /* account for one byte pad to word boundary */
1205 cifsConvertToUCS((__le16 *) (pSMB->fileName + 1),
1206 fileName, PATH_MAX, nls_codepage, remap);
1207 name_len++; /* trailing null */
1209 } else { /* BB improve check for buffer overruns BB */
1210 count = 0; /* no pad */
1211 name_len = strnlen(fileName, PATH_MAX);
1212 name_len++; /* trailing null */
1213 strncpy(pSMB->fileName, fileName, name_len);
1215 if (*pOplock & REQ_OPLOCK)
1216 pSMB->OpenFlags = cpu_to_le16(REQ_OPLOCK);
1217 else if (*pOplock & REQ_BATCHOPLOCK)
1218 pSMB->OpenFlags = cpu_to_le16(REQ_BATCHOPLOCK);
1220 pSMB->OpenFlags |= cpu_to_le16(REQ_MORE_INFO);
1221 pSMB->Mode = cpu_to_le16(access_flags_to_smbopen_mode(access_flags));
1222 pSMB->Mode |= cpu_to_le16(0x40); /* deny none */
1223 /* set file as system file if special file such
1224 as fifo and server expecting SFU style and
1225 no Unix extensions */
1227 if (create_options & CREATE_OPTION_SPECIAL)
1228 pSMB->FileAttributes = cpu_to_le16(ATTR_SYSTEM);
1229 else /* BB FIXME BB */
1230 pSMB->FileAttributes = cpu_to_le16(0/*ATTR_NORMAL*/);
1232 if (create_options & CREATE_OPTION_READONLY)
1233 pSMB->FileAttributes |= cpu_to_le16(ATTR_READONLY);
1236 /* pSMB->CreateOptions = cpu_to_le32(create_options &
1237 CREATE_OPTIONS_MASK); */
1238 /* BB FIXME END BB */
1240 pSMB->Sattr = cpu_to_le16(ATTR_HIDDEN | ATTR_SYSTEM | ATTR_DIRECTORY);
1241 pSMB->OpenFunction = cpu_to_le16(convert_disposition(openDisposition));
1243 inc_rfc1001_len(pSMB, count);
1245 pSMB->ByteCount = cpu_to_le16(count);
1246 /* long_op set to 1 to allow for oplock break timeouts */
1247 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1248 (struct smb_hdr *)pSMBr, &bytes_returned, 0);
1249 cifs_stats_inc(&tcon->num_opens);
1251 cFYI(1, "Error in Open = %d", rc);
1253 /* BB verify if wct == 15 */
1255 /* *pOplock = pSMBr->OplockLevel; */ /* BB take from action field*/
1257 *netfid = pSMBr->Fid; /* cifs fid stays in le */
1258 /* Let caller know file was created so we can set the mode. */
1259 /* Do we care about the CreateAction in any other cases? */
1261 /* if (cpu_to_le32(FILE_CREATE) == pSMBr->CreateAction)
1262 *pOplock |= CIFS_CREATE_ACTION; */
1266 pfile_info->CreationTime = 0; /* BB convert CreateTime*/
1267 pfile_info->LastAccessTime = 0; /* BB fixme */
1268 pfile_info->LastWriteTime = 0; /* BB fixme */
1269 pfile_info->ChangeTime = 0; /* BB fixme */
1270 pfile_info->Attributes =
1271 cpu_to_le32(le16_to_cpu(pSMBr->FileAttributes));
1272 /* the file_info buf is endian converted by caller */
1273 pfile_info->AllocationSize =
1274 cpu_to_le64(le32_to_cpu(pSMBr->EndOfFile));
1275 pfile_info->EndOfFile = pfile_info->AllocationSize;
1276 pfile_info->NumberOfLinks = cpu_to_le32(1);
1277 pfile_info->DeletePending = 0;
1281 cifs_buf_release(pSMB);
1288 CIFSSMBOpen(const int xid, struct cifs_tcon *tcon,
1289 const char *fileName, const int openDisposition,
1290 const int access_flags, const int create_options, __u16 *netfid,
1291 int *pOplock, FILE_ALL_INFO *pfile_info,
1292 const struct nls_table *nls_codepage, int remap)
1295 OPEN_REQ *pSMB = NULL;
1296 OPEN_RSP *pSMBr = NULL;
1302 rc = smb_init(SMB_COM_NT_CREATE_ANDX, 24, tcon, (void **) &pSMB,
1307 pSMB->AndXCommand = 0xFF; /* none */
1309 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1310 count = 1; /* account for one byte pad to word boundary */
1312 cifsConvertToUCS((__le16 *) (pSMB->fileName + 1),
1313 fileName, PATH_MAX, nls_codepage, remap);
1314 name_len++; /* trailing null */
1316 pSMB->NameLength = cpu_to_le16(name_len);
1317 } else { /* BB improve check for buffer overruns BB */
1318 count = 0; /* no pad */
1319 name_len = strnlen(fileName, PATH_MAX);
1320 name_len++; /* trailing null */
1321 pSMB->NameLength = cpu_to_le16(name_len);
1322 strncpy(pSMB->fileName, fileName, name_len);
1324 if (*pOplock & REQ_OPLOCK)
1325 pSMB->OpenFlags = cpu_to_le32(REQ_OPLOCK);
1326 else if (*pOplock & REQ_BATCHOPLOCK)
1327 pSMB->OpenFlags = cpu_to_le32(REQ_BATCHOPLOCK);
1328 pSMB->DesiredAccess = cpu_to_le32(access_flags);
1329 pSMB->AllocationSize = 0;
1330 /* set file as system file if special file such
1331 as fifo and server expecting SFU style and
1332 no Unix extensions */
1333 if (create_options & CREATE_OPTION_SPECIAL)
1334 pSMB->FileAttributes = cpu_to_le32(ATTR_SYSTEM);
1336 pSMB->FileAttributes = cpu_to_le32(ATTR_NORMAL);
1338 /* XP does not handle ATTR_POSIX_SEMANTICS */
1339 /* but it helps speed up case sensitive checks for other
1340 servers such as Samba */
1341 if (tcon->ses->capabilities & CAP_UNIX)
1342 pSMB->FileAttributes |= cpu_to_le32(ATTR_POSIX_SEMANTICS);
1344 if (create_options & CREATE_OPTION_READONLY)
1345 pSMB->FileAttributes |= cpu_to_le32(ATTR_READONLY);
1347 pSMB->ShareAccess = cpu_to_le32(FILE_SHARE_ALL);
1348 pSMB->CreateDisposition = cpu_to_le32(openDisposition);
1349 pSMB->CreateOptions = cpu_to_le32(create_options & CREATE_OPTIONS_MASK);
1350 /* BB Expirement with various impersonation levels and verify */
1351 pSMB->ImpersonationLevel = cpu_to_le32(SECURITY_IMPERSONATION);
1352 pSMB->SecurityFlags =
1353 SECURITY_CONTEXT_TRACKING | SECURITY_EFFECTIVE_ONLY;
1356 inc_rfc1001_len(pSMB, count);
1358 pSMB->ByteCount = cpu_to_le16(count);
1359 /* long_op set to 1 to allow for oplock break timeouts */
1360 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1361 (struct smb_hdr *)pSMBr, &bytes_returned, 0);
1362 cifs_stats_inc(&tcon->num_opens);
1364 cFYI(1, "Error in Open = %d", rc);
1366 *pOplock = pSMBr->OplockLevel; /* 1 byte no need to le_to_cpu */
1367 *netfid = pSMBr->Fid; /* cifs fid stays in le */
1368 /* Let caller know file was created so we can set the mode. */
1369 /* Do we care about the CreateAction in any other cases? */
1370 if (cpu_to_le32(FILE_CREATE) == pSMBr->CreateAction)
1371 *pOplock |= CIFS_CREATE_ACTION;
1373 memcpy((char *)pfile_info, (char *)&pSMBr->CreationTime,
1374 36 /* CreationTime to Attributes */);
1375 /* the file_info buf is endian converted by caller */
1376 pfile_info->AllocationSize = pSMBr->AllocationSize;
1377 pfile_info->EndOfFile = pSMBr->EndOfFile;
1378 pfile_info->NumberOfLinks = cpu_to_le32(1);
1379 pfile_info->DeletePending = 0;
1383 cifs_buf_release(pSMB);
1389 struct cifs_readdata *
1390 cifs_readdata_alloc(unsigned int nr_pages)
1392 struct cifs_readdata *rdata;
1394 /* readdata + 1 kvec for each page */
1395 rdata = kzalloc(sizeof(*rdata) +
1396 sizeof(struct kvec) * nr_pages, GFP_KERNEL);
1397 if (rdata != NULL) {
1398 INIT_WORK(&rdata->work, cifs_readv_complete);
1399 INIT_LIST_HEAD(&rdata->pages);
1405 cifs_readdata_free(struct cifs_readdata *rdata)
1407 cifsFileInfo_put(rdata->cfile);
1412 * Discard any remaining data in the current SMB. To do this, we borrow the
1416 cifs_readv_discard(struct TCP_Server_Info *server, struct mid_q_entry *mid)
1418 READ_RSP *rsp = (READ_RSP *)server->smallbuf;
1419 unsigned int rfclen = be32_to_cpu(rsp->hdr.smb_buf_length);
1420 int remaining = rfclen + 4 - server->total_read;
1421 struct cifs_readdata *rdata = mid->callback_data;
1423 while (remaining > 0) {
1426 length = cifs_read_from_socket(server, server->bigbuf,
1427 min_t(unsigned int, remaining,
1428 CIFSMaxBufSize + MAX_CIFS_HDR_SIZE));
1431 server->total_read += length;
1432 remaining -= length;
1435 dequeue_mid(mid, rdata->result);
1440 cifs_readv_receive(struct TCP_Server_Info *server, struct mid_q_entry *mid)
1443 unsigned int data_offset, remaining, data_len;
1444 struct cifs_readdata *rdata = mid->callback_data;
1445 READ_RSP *rsp = (READ_RSP *)server->smallbuf;
1446 unsigned int rfclen = be32_to_cpu(rsp->hdr.smb_buf_length) + 4;
1449 struct page *page, *tpage;
1451 cFYI(1, "%s: mid=%u offset=%llu bytes=%u", __func__,
1452 mid->mid, rdata->offset, rdata->bytes);
1455 * read the rest of READ_RSP header (sans Data array), or whatever we
1456 * can if there's not enough data. At this point, we've read down to
1459 len = min_t(unsigned int, rfclen, sizeof(*rsp)) -
1460 sizeof(struct smb_hdr) + 1;
1462 rdata->iov[0].iov_base = server->smallbuf + sizeof(struct smb_hdr) - 1;
1463 rdata->iov[0].iov_len = len;
1465 length = cifs_readv_from_socket(server, rdata->iov, 1, len);
1468 server->total_read += length;
1470 /* Was the SMB read successful? */
1471 rdata->result = map_smb_to_linux_error(&rsp->hdr, false);
1472 if (rdata->result != 0) {
1473 cFYI(1, "%s: server returned error %d", __func__,
1475 return cifs_readv_discard(server, mid);
1478 /* Is there enough to get to the rest of the READ_RSP header? */
1479 if (server->total_read < sizeof(READ_RSP)) {
1480 cFYI(1, "%s: server returned short header. got=%u expected=%zu",
1481 __func__, server->total_read, sizeof(READ_RSP));
1482 rdata->result = -EIO;
1483 return cifs_readv_discard(server, mid);
1486 data_offset = le16_to_cpu(rsp->DataOffset) + 4;
1487 if (data_offset < server->total_read) {
1489 * win2k8 sometimes sends an offset of 0 when the read
1490 * is beyond the EOF. Treat it as if the data starts just after
1493 cFYI(1, "%s: data offset (%u) inside read response header",
1494 __func__, data_offset);
1495 data_offset = server->total_read;
1496 } else if (data_offset > MAX_CIFS_SMALL_BUFFER_SIZE) {
1497 /* data_offset is beyond the end of smallbuf */
1498 cFYI(1, "%s: data offset (%u) beyond end of smallbuf",
1499 __func__, data_offset);
1500 rdata->result = -EIO;
1501 return cifs_readv_discard(server, mid);
1504 cFYI(1, "%s: total_read=%u data_offset=%u", __func__,
1505 server->total_read, data_offset);
1507 len = data_offset - server->total_read;
1509 /* read any junk before data into the rest of smallbuf */
1510 rdata->iov[0].iov_base = server->smallbuf + server->total_read;
1511 rdata->iov[0].iov_len = len;
1512 length = cifs_readv_from_socket(server, rdata->iov, 1, len);
1515 server->total_read += length;
1518 /* set up first iov for signature check */
1519 rdata->iov[0].iov_base = server->smallbuf;
1520 rdata->iov[0].iov_len = server->total_read;
1521 cFYI(1, "0: iov_base=%p iov_len=%zu",
1522 rdata->iov[0].iov_base, rdata->iov[0].iov_len);
1524 /* how much data is in the response? */
1525 data_len = le16_to_cpu(rsp->DataLengthHigh) << 16;
1526 data_len += le16_to_cpu(rsp->DataLength);
1527 if (data_offset + data_len > rfclen) {
1528 /* data_len is corrupt -- discard frame */
1529 rdata->result = -EIO;
1530 return cifs_readv_discard(server, mid);
1533 /* marshal up the page array */
1535 remaining = data_len;
1538 /* determine the eof that the server (probably) has */
1539 eof = CIFS_I(rdata->mapping->host)->server_eof;
1540 eof_index = eof ? (eof - 1) >> PAGE_CACHE_SHIFT : 0;
1541 cFYI(1, "eof=%llu eof_index=%lu", eof, eof_index);
1543 list_for_each_entry_safe(page, tpage, &rdata->pages, lru) {
1544 if (remaining >= PAGE_CACHE_SIZE) {
1545 /* enough data to fill the page */
1546 rdata->iov[rdata->nr_iov].iov_base = kmap(page);
1547 rdata->iov[rdata->nr_iov].iov_len = PAGE_CACHE_SIZE;
1548 cFYI(1, "%u: idx=%lu iov_base=%p iov_len=%zu",
1549 rdata->nr_iov, page->index,
1550 rdata->iov[rdata->nr_iov].iov_base,
1551 rdata->iov[rdata->nr_iov].iov_len);
1553 len += PAGE_CACHE_SIZE;
1554 remaining -= PAGE_CACHE_SIZE;
1555 } else if (remaining > 0) {
1556 /* enough for partial page, fill and zero the rest */
1557 rdata->iov[rdata->nr_iov].iov_base = kmap(page);
1558 rdata->iov[rdata->nr_iov].iov_len = remaining;
1559 cFYI(1, "%u: idx=%lu iov_base=%p iov_len=%zu",
1560 rdata->nr_iov, page->index,
1561 rdata->iov[rdata->nr_iov].iov_base,
1562 rdata->iov[rdata->nr_iov].iov_len);
1563 memset(rdata->iov[rdata->nr_iov].iov_base + remaining,
1564 '\0', PAGE_CACHE_SIZE - remaining);
1568 } else if (page->index > eof_index) {
1570 * The VFS will not try to do readahead past the
1571 * i_size, but it's possible that we have outstanding
1572 * writes with gaps in the middle and the i_size hasn't
1573 * caught up yet. Populate those with zeroed out pages
1574 * to prevent the VFS from repeatedly attempting to
1575 * fill them until the writes are flushed.
1577 zero_user(page, 0, PAGE_CACHE_SIZE);
1578 list_del(&page->lru);
1579 lru_cache_add_file(page);
1580 flush_dcache_page(page);
1581 SetPageUptodate(page);
1583 page_cache_release(page);
1585 /* no need to hold page hostage */
1586 list_del(&page->lru);
1587 lru_cache_add_file(page);
1589 page_cache_release(page);
1593 /* issue the read if we have any iovecs left to fill */
1594 if (rdata->nr_iov > 1) {
1595 length = cifs_readv_from_socket(server, &rdata->iov[1],
1596 rdata->nr_iov - 1, len);
1599 server->total_read += length;
1604 rdata->bytes = length;
1606 cFYI(1, "total_read=%u rfclen=%u remaining=%u", server->total_read,
1609 /* discard anything left over */
1610 if (server->total_read < rfclen)
1611 return cifs_readv_discard(server, mid);
1613 dequeue_mid(mid, false);
1618 cifs_readv_complete(struct work_struct *work)
1620 struct cifs_readdata *rdata = container_of(work,
1621 struct cifs_readdata, work);
1622 struct page *page, *tpage;
1624 list_for_each_entry_safe(page, tpage, &rdata->pages, lru) {
1625 list_del(&page->lru);
1626 lru_cache_add_file(page);
1628 if (rdata->result == 0) {
1630 flush_dcache_page(page);
1631 SetPageUptodate(page);
1636 if (rdata->result == 0)
1637 cifs_readpage_to_fscache(rdata->mapping->host, page);
1639 page_cache_release(page);
1641 cifs_readdata_free(rdata);
1645 cifs_readv_callback(struct mid_q_entry *mid)
1647 struct cifs_readdata *rdata = mid->callback_data;
1648 struct cifs_tcon *tcon = tlink_tcon(rdata->cfile->tlink);
1649 struct TCP_Server_Info *server = tcon->ses->server;
1651 cFYI(1, "%s: mid=%u state=%d result=%d bytes=%u", __func__,
1652 mid->mid, mid->midState, rdata->result, rdata->bytes);
1654 switch (mid->midState) {
1655 case MID_RESPONSE_RECEIVED:
1656 /* result already set, check signature */
1657 if (server->sec_mode &
1658 (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED)) {
1659 if (cifs_verify_signature(rdata->iov, rdata->nr_iov,
1660 server, mid->sequence_number + 1))
1661 cERROR(1, "Unexpected SMB signature");
1663 /* FIXME: should this be counted toward the initiating task? */
1664 task_io_account_read(rdata->bytes);
1665 cifs_stats_bytes_read(tcon, rdata->bytes);
1667 case MID_REQUEST_SUBMITTED:
1668 case MID_RETRY_NEEDED:
1669 rdata->result = -EAGAIN;
1672 rdata->result = -EIO;
1675 queue_work(system_nrt_wq, &rdata->work);
1676 DeleteMidQEntry(mid);
1677 atomic_dec(&server->inFlight);
1678 wake_up(&server->request_q);
1681 /* cifs_async_readv - send an async write, and set up mid to handle result */
1683 cifs_async_readv(struct cifs_readdata *rdata)
1686 READ_REQ *smb = NULL;
1688 struct cifs_tcon *tcon = tlink_tcon(rdata->cfile->tlink);
1690 cFYI(1, "%s: offset=%llu bytes=%u", __func__,
1691 rdata->offset, rdata->bytes);
1693 if (tcon->ses->capabilities & CAP_LARGE_FILES)
1696 wct = 10; /* old style read */
1697 if ((rdata->offset >> 32) > 0) {
1698 /* can not handle this big offset for old */
1703 rc = small_smb_init(SMB_COM_READ_ANDX, wct, tcon, (void **)&smb);
1707 smb->hdr.Pid = cpu_to_le16((__u16)rdata->pid);
1708 smb->hdr.PidHigh = cpu_to_le16((__u16)(rdata->pid >> 16));
1710 smb->AndXCommand = 0xFF; /* none */
1711 smb->Fid = rdata->cfile->netfid;
1712 smb->OffsetLow = cpu_to_le32(rdata->offset & 0xFFFFFFFF);
1714 smb->OffsetHigh = cpu_to_le32(rdata->offset >> 32);
1716 smb->MaxCount = cpu_to_le16(rdata->bytes & 0xFFFF);
1717 smb->MaxCountHigh = cpu_to_le32(rdata->bytes >> 16);
1721 /* old style read */
1722 struct smb_com_readx_req *smbr =
1723 (struct smb_com_readx_req *)smb;
1724 smbr->ByteCount = 0;
1727 /* 4 for RFC1001 length + 1 for BCC */
1728 rdata->iov[0].iov_base = smb;
1729 rdata->iov[0].iov_len = be32_to_cpu(smb->hdr.smb_buf_length) + 4;
1731 rc = cifs_call_async(tcon->ses->server, rdata->iov, 1,
1732 cifs_readv_receive, cifs_readv_callback,
1736 cifs_stats_inc(&tcon->num_reads);
1738 cifs_small_buf_release(smb);
1743 CIFSSMBRead(const int xid, struct cifs_io_parms *io_parms, unsigned int *nbytes,
1744 char **buf, int *pbuf_type)
1747 READ_REQ *pSMB = NULL;
1748 READ_RSP *pSMBr = NULL;
1749 char *pReadData = NULL;
1751 int resp_buf_type = 0;
1753 __u32 pid = io_parms->pid;
1754 __u16 netfid = io_parms->netfid;
1755 __u64 offset = io_parms->offset;
1756 struct cifs_tcon *tcon = io_parms->tcon;
1757 unsigned int count = io_parms->length;
1759 cFYI(1, "Reading %d bytes on fid %d", count, netfid);
1760 if (tcon->ses->capabilities & CAP_LARGE_FILES)
1763 wct = 10; /* old style read */
1764 if ((offset >> 32) > 0) {
1765 /* can not handle this big offset for old */
1771 rc = small_smb_init(SMB_COM_READ_ANDX, wct, tcon, (void **) &pSMB);
1775 pSMB->hdr.Pid = cpu_to_le16((__u16)pid);
1776 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid >> 16));
1778 /* tcon and ses pointer are checked in smb_init */
1779 if (tcon->ses->server == NULL)
1780 return -ECONNABORTED;
1782 pSMB->AndXCommand = 0xFF; /* none */
1784 pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF);
1786 pSMB->OffsetHigh = cpu_to_le32(offset >> 32);
1788 pSMB->Remaining = 0;
1789 pSMB->MaxCount = cpu_to_le16(count & 0xFFFF);
1790 pSMB->MaxCountHigh = cpu_to_le32(count >> 16);
1792 pSMB->ByteCount = 0; /* no need to do le conversion since 0 */
1794 /* old style read */
1795 struct smb_com_readx_req *pSMBW =
1796 (struct smb_com_readx_req *)pSMB;
1797 pSMBW->ByteCount = 0;
1800 iov[0].iov_base = (char *)pSMB;
1801 iov[0].iov_len = be32_to_cpu(pSMB->hdr.smb_buf_length) + 4;
1802 rc = SendReceive2(xid, tcon->ses, iov, 1 /* num iovecs */,
1803 &resp_buf_type, CIFS_LOG_ERROR);
1804 cifs_stats_inc(&tcon->num_reads);
1805 pSMBr = (READ_RSP *)iov[0].iov_base;
1807 cERROR(1, "Send error in read = %d", rc);
1809 int data_length = le16_to_cpu(pSMBr->DataLengthHigh);
1810 data_length = data_length << 16;
1811 data_length += le16_to_cpu(pSMBr->DataLength);
1812 *nbytes = data_length;
1814 /*check that DataLength would not go beyond end of SMB */
1815 if ((data_length > CIFSMaxBufSize)
1816 || (data_length > count)) {
1817 cFYI(1, "bad length %d for count %d",
1818 data_length, count);
1822 pReadData = (char *) (&pSMBr->hdr.Protocol) +
1823 le16_to_cpu(pSMBr->DataOffset);
1824 /* if (rc = copy_to_user(buf, pReadData, data_length)) {
1825 cERROR(1, "Faulting on read rc = %d",rc);
1827 }*/ /* can not use copy_to_user when using page cache*/
1829 memcpy(*buf, pReadData, data_length);
1833 /* cifs_small_buf_release(pSMB); */ /* Freed earlier now in SendReceive2 */
1835 if (resp_buf_type == CIFS_SMALL_BUFFER)
1836 cifs_small_buf_release(iov[0].iov_base);
1837 else if (resp_buf_type == CIFS_LARGE_BUFFER)
1838 cifs_buf_release(iov[0].iov_base);
1839 } else if (resp_buf_type != CIFS_NO_BUFFER) {
1840 /* return buffer to caller to free */
1841 *buf = iov[0].iov_base;
1842 if (resp_buf_type == CIFS_SMALL_BUFFER)
1843 *pbuf_type = CIFS_SMALL_BUFFER;
1844 else if (resp_buf_type == CIFS_LARGE_BUFFER)
1845 *pbuf_type = CIFS_LARGE_BUFFER;
1846 } /* else no valid buffer on return - leave as null */
1848 /* Note: On -EAGAIN error only caller can retry on handle based calls
1849 since file handle passed in no longer valid */
1855 CIFSSMBWrite(const int xid, struct cifs_io_parms *io_parms,
1856 unsigned int *nbytes, const char *buf,
1857 const char __user *ubuf, const int long_op)
1860 WRITE_REQ *pSMB = NULL;
1861 WRITE_RSP *pSMBr = NULL;
1862 int bytes_returned, wct;
1865 __u32 pid = io_parms->pid;
1866 __u16 netfid = io_parms->netfid;
1867 __u64 offset = io_parms->offset;
1868 struct cifs_tcon *tcon = io_parms->tcon;
1869 unsigned int count = io_parms->length;
1873 /* cFYI(1, "write at %lld %d bytes", offset, count);*/
1874 if (tcon->ses == NULL)
1875 return -ECONNABORTED;
1877 if (tcon->ses->capabilities & CAP_LARGE_FILES)
1881 if ((offset >> 32) > 0) {
1882 /* can not handle big offset for old srv */
1887 rc = smb_init(SMB_COM_WRITE_ANDX, wct, tcon, (void **) &pSMB,
1892 pSMB->hdr.Pid = cpu_to_le16((__u16)pid);
1893 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid >> 16));
1895 /* tcon and ses pointer are checked in smb_init */
1896 if (tcon->ses->server == NULL)
1897 return -ECONNABORTED;
1899 pSMB->AndXCommand = 0xFF; /* none */
1901 pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF);
1903 pSMB->OffsetHigh = cpu_to_le32(offset >> 32);
1905 pSMB->Reserved = 0xFFFFFFFF;
1906 pSMB->WriteMode = 0;
1907 pSMB->Remaining = 0;
1909 /* Can increase buffer size if buffer is big enough in some cases ie we
1910 can send more if LARGE_WRITE_X capability returned by the server and if
1911 our buffer is big enough or if we convert to iovecs on socket writes
1912 and eliminate the copy to the CIFS buffer */
1913 if (tcon->ses->capabilities & CAP_LARGE_WRITE_X) {
1914 bytes_sent = min_t(const unsigned int, CIFSMaxBufSize, count);
1916 bytes_sent = (tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE)
1920 if (bytes_sent > count)
1923 cpu_to_le16(offsetof(struct smb_com_write_req, Data) - 4);
1925 memcpy(pSMB->Data, buf, bytes_sent);
1927 if (copy_from_user(pSMB->Data, ubuf, bytes_sent)) {
1928 cifs_buf_release(pSMB);
1931 } else if (count != 0) {
1933 cifs_buf_release(pSMB);
1935 } /* else setting file size with write of zero bytes */
1937 byte_count = bytes_sent + 1; /* pad */
1938 else /* wct == 12 */
1939 byte_count = bytes_sent + 5; /* bigger pad, smaller smb hdr */
1941 pSMB->DataLengthLow = cpu_to_le16(bytes_sent & 0xFFFF);
1942 pSMB->DataLengthHigh = cpu_to_le16(bytes_sent >> 16);
1943 inc_rfc1001_len(pSMB, byte_count);
1946 pSMB->ByteCount = cpu_to_le16(byte_count);
1947 else { /* old style write has byte count 4 bytes earlier
1949 struct smb_com_writex_req *pSMBW =
1950 (struct smb_com_writex_req *)pSMB;
1951 pSMBW->ByteCount = cpu_to_le16(byte_count);
1954 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1955 (struct smb_hdr *) pSMBr, &bytes_returned, long_op);
1956 cifs_stats_inc(&tcon->num_writes);
1958 cFYI(1, "Send error in write = %d", rc);
1960 *nbytes = le16_to_cpu(pSMBr->CountHigh);
1961 *nbytes = (*nbytes) << 16;
1962 *nbytes += le16_to_cpu(pSMBr->Count);
1965 * Mask off high 16 bits when bytes written as returned by the
1966 * server is greater than bytes requested by the client. Some
1967 * OS/2 servers are known to set incorrect CountHigh values.
1969 if (*nbytes > count)
1973 cifs_buf_release(pSMB);
1975 /* Note: On -EAGAIN error only caller can retry on handle based calls
1976 since file handle passed in no longer valid */
1982 cifs_writedata_release(struct kref *refcount)
1984 struct cifs_writedata *wdata = container_of(refcount,
1985 struct cifs_writedata, refcount);
1988 cifsFileInfo_put(wdata->cfile);
1994 * Write failed with a retryable error. Resend the write request. It's also
1995 * possible that the page was redirtied so re-clean the page.
1998 cifs_writev_requeue(struct cifs_writedata *wdata)
2001 struct inode *inode = wdata->cfile->dentry->d_inode;
2003 for (i = 0; i < wdata->nr_pages; i++) {
2004 lock_page(wdata->pages[i]);
2005 clear_page_dirty_for_io(wdata->pages[i]);
2009 rc = cifs_async_writev(wdata);
2010 } while (rc == -EAGAIN);
2012 for (i = 0; i < wdata->nr_pages; i++) {
2014 SetPageError(wdata->pages[i]);
2015 unlock_page(wdata->pages[i]);
2018 mapping_set_error(inode->i_mapping, rc);
2019 kref_put(&wdata->refcount, cifs_writedata_release);
2023 cifs_writev_complete(struct work_struct *work)
2025 struct cifs_writedata *wdata = container_of(work,
2026 struct cifs_writedata, work);
2027 struct inode *inode = wdata->cfile->dentry->d_inode;
2030 if (wdata->result == 0) {
2031 cifs_update_eof(CIFS_I(inode), wdata->offset, wdata->bytes);
2032 cifs_stats_bytes_written(tlink_tcon(wdata->cfile->tlink),
2034 } else if (wdata->sync_mode == WB_SYNC_ALL && wdata->result == -EAGAIN)
2035 return cifs_writev_requeue(wdata);
2037 for (i = 0; i < wdata->nr_pages; i++) {
2038 struct page *page = wdata->pages[i];
2039 if (wdata->result == -EAGAIN)
2040 __set_page_dirty_nobuffers(page);
2041 else if (wdata->result < 0)
2043 end_page_writeback(page);
2044 page_cache_release(page);
2046 if (wdata->result != -EAGAIN)
2047 mapping_set_error(inode->i_mapping, wdata->result);
2048 kref_put(&wdata->refcount, cifs_writedata_release);
2051 struct cifs_writedata *
2052 cifs_writedata_alloc(unsigned int nr_pages)
2054 struct cifs_writedata *wdata;
2056 /* this would overflow */
2057 if (nr_pages == 0) {
2058 cERROR(1, "%s: called with nr_pages == 0!", __func__);
2062 /* writedata + number of page pointers */
2063 wdata = kzalloc(sizeof(*wdata) +
2064 sizeof(struct page *) * (nr_pages - 1), GFP_NOFS);
2065 if (wdata != NULL) {
2066 INIT_WORK(&wdata->work, cifs_writev_complete);
2067 kref_init(&wdata->refcount);
2073 * Check the midState and signature on received buffer (if any), and queue the
2074 * workqueue completion task.
2077 cifs_writev_callback(struct mid_q_entry *mid)
2079 struct cifs_writedata *wdata = mid->callback_data;
2080 struct cifs_tcon *tcon = tlink_tcon(wdata->cfile->tlink);
2081 unsigned int written;
2082 WRITE_RSP *smb = (WRITE_RSP *)mid->resp_buf;
2084 switch (mid->midState) {
2085 case MID_RESPONSE_RECEIVED:
2086 wdata->result = cifs_check_receive(mid, tcon->ses->server, 0);
2087 if (wdata->result != 0)
2090 written = le16_to_cpu(smb->CountHigh);
2092 written += le16_to_cpu(smb->Count);
2094 * Mask off high 16 bits when bytes written as returned
2095 * by the server is greater than bytes requested by the
2096 * client. OS/2 servers are known to set incorrect
2099 if (written > wdata->bytes)
2102 if (written < wdata->bytes)
2103 wdata->result = -ENOSPC;
2105 wdata->bytes = written;
2107 case MID_REQUEST_SUBMITTED:
2108 case MID_RETRY_NEEDED:
2109 wdata->result = -EAGAIN;
2112 wdata->result = -EIO;
2116 queue_work(system_nrt_wq, &wdata->work);
2117 DeleteMidQEntry(mid);
2118 atomic_dec(&tcon->ses->server->inFlight);
2119 wake_up(&tcon->ses->server->request_q);
2122 /* cifs_async_writev - send an async write, and set up mid to handle result */
2124 cifs_async_writev(struct cifs_writedata *wdata)
2126 int i, rc = -EACCES;
2127 WRITE_REQ *smb = NULL;
2129 struct cifs_tcon *tcon = tlink_tcon(wdata->cfile->tlink);
2130 struct inode *inode = wdata->cfile->dentry->d_inode;
2131 struct kvec *iov = NULL;
2133 if (tcon->ses->capabilities & CAP_LARGE_FILES) {
2137 if (wdata->offset >> 32 > 0) {
2138 /* can not handle big offset for old srv */
2143 rc = small_smb_init(SMB_COM_WRITE_ANDX, wct, tcon, (void **)&smb);
2145 goto async_writev_out;
2147 /* 1 iov per page + 1 for header */
2148 iov = kzalloc((wdata->nr_pages + 1) * sizeof(*iov), GFP_NOFS);
2151 goto async_writev_out;
2154 smb->hdr.Pid = cpu_to_le16((__u16)wdata->cfile->pid);
2155 smb->hdr.PidHigh = cpu_to_le16((__u16)(wdata->cfile->pid >> 16));
2157 smb->AndXCommand = 0xFF; /* none */
2158 smb->Fid = wdata->cfile->netfid;
2159 smb->OffsetLow = cpu_to_le32(wdata->offset & 0xFFFFFFFF);
2161 smb->OffsetHigh = cpu_to_le32(wdata->offset >> 32);
2162 smb->Reserved = 0xFFFFFFFF;
2167 cpu_to_le16(offsetof(struct smb_com_write_req, Data) - 4);
2169 /* 4 for RFC1001 length + 1 for BCC */
2170 iov[0].iov_len = be32_to_cpu(smb->hdr.smb_buf_length) + 4 + 1;
2171 iov[0].iov_base = smb;
2173 /* marshal up the pages into iov array */
2175 for (i = 0; i < wdata->nr_pages; i++) {
2176 iov[i + 1].iov_len = min(inode->i_size -
2177 page_offset(wdata->pages[i]),
2178 (loff_t)PAGE_CACHE_SIZE);
2179 iov[i + 1].iov_base = kmap(wdata->pages[i]);
2180 wdata->bytes += iov[i + 1].iov_len;
2183 cFYI(1, "async write at %llu %u bytes", wdata->offset, wdata->bytes);
2185 smb->DataLengthLow = cpu_to_le16(wdata->bytes & 0xFFFF);
2186 smb->DataLengthHigh = cpu_to_le16(wdata->bytes >> 16);
2189 inc_rfc1001_len(&smb->hdr, wdata->bytes + 1);
2190 put_bcc(wdata->bytes + 1, &smb->hdr);
2193 struct smb_com_writex_req *smbw =
2194 (struct smb_com_writex_req *)smb;
2195 inc_rfc1001_len(&smbw->hdr, wdata->bytes + 5);
2196 put_bcc(wdata->bytes + 5, &smbw->hdr);
2197 iov[0].iov_len += 4; /* pad bigger by four bytes */
2200 kref_get(&wdata->refcount);
2201 rc = cifs_call_async(tcon->ses->server, iov, wdata->nr_pages + 1,
2202 NULL, cifs_writev_callback, wdata, false);
2205 cifs_stats_inc(&tcon->num_writes);
2207 kref_put(&wdata->refcount, cifs_writedata_release);
2209 /* send is done, unmap pages */
2210 for (i = 0; i < wdata->nr_pages; i++)
2211 kunmap(wdata->pages[i]);
2214 cifs_small_buf_release(smb);
2220 CIFSSMBWrite2(const int xid, struct cifs_io_parms *io_parms,
2221 unsigned int *nbytes, struct kvec *iov, int n_vec,
2225 WRITE_REQ *pSMB = NULL;
2228 int resp_buf_type = 0;
2229 __u32 pid = io_parms->pid;
2230 __u16 netfid = io_parms->netfid;
2231 __u64 offset = io_parms->offset;
2232 struct cifs_tcon *tcon = io_parms->tcon;
2233 unsigned int count = io_parms->length;
2237 cFYI(1, "write2 at %lld %d bytes", (long long)offset, count);
2239 if (tcon->ses->capabilities & CAP_LARGE_FILES) {
2243 if ((offset >> 32) > 0) {
2244 /* can not handle big offset for old srv */
2248 rc = small_smb_init(SMB_COM_WRITE_ANDX, wct, tcon, (void **) &pSMB);
2252 pSMB->hdr.Pid = cpu_to_le16((__u16)pid);
2253 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid >> 16));
2255 /* tcon and ses pointer are checked in smb_init */
2256 if (tcon->ses->server == NULL)
2257 return -ECONNABORTED;
2259 pSMB->AndXCommand = 0xFF; /* none */
2261 pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF);
2263 pSMB->OffsetHigh = cpu_to_le32(offset >> 32);
2264 pSMB->Reserved = 0xFFFFFFFF;
2265 pSMB->WriteMode = 0;
2266 pSMB->Remaining = 0;
2269 cpu_to_le16(offsetof(struct smb_com_write_req, Data) - 4);
2271 pSMB->DataLengthLow = cpu_to_le16(count & 0xFFFF);
2272 pSMB->DataLengthHigh = cpu_to_le16(count >> 16);
2273 /* header + 1 byte pad */
2274 smb_hdr_len = be32_to_cpu(pSMB->hdr.smb_buf_length) + 1;
2276 inc_rfc1001_len(pSMB, count + 1);
2277 else /* wct == 12 */
2278 inc_rfc1001_len(pSMB, count + 5); /* smb data starts later */
2280 pSMB->ByteCount = cpu_to_le16(count + 1);
2281 else /* wct == 12 */ /* bigger pad, smaller smb hdr, keep offset ok */ {
2282 struct smb_com_writex_req *pSMBW =
2283 (struct smb_com_writex_req *)pSMB;
2284 pSMBW->ByteCount = cpu_to_le16(count + 5);
2286 iov[0].iov_base = pSMB;
2288 iov[0].iov_len = smb_hdr_len + 4;
2289 else /* wct == 12 pad bigger by four bytes */
2290 iov[0].iov_len = smb_hdr_len + 8;
2293 rc = SendReceive2(xid, tcon->ses, iov, n_vec + 1, &resp_buf_type,
2295 cifs_stats_inc(&tcon->num_writes);
2297 cFYI(1, "Send error Write2 = %d", rc);
2298 } else if (resp_buf_type == 0) {
2299 /* presumably this can not happen, but best to be safe */
2302 WRITE_RSP *pSMBr = (WRITE_RSP *)iov[0].iov_base;
2303 *nbytes = le16_to_cpu(pSMBr->CountHigh);
2304 *nbytes = (*nbytes) << 16;
2305 *nbytes += le16_to_cpu(pSMBr->Count);
2308 * Mask off high 16 bits when bytes written as returned by the
2309 * server is greater than bytes requested by the client. OS/2
2310 * servers are known to set incorrect CountHigh values.
2312 if (*nbytes > count)
2316 /* cifs_small_buf_release(pSMB); */ /* Freed earlier now in SendReceive2 */
2317 if (resp_buf_type == CIFS_SMALL_BUFFER)
2318 cifs_small_buf_release(iov[0].iov_base);
2319 else if (resp_buf_type == CIFS_LARGE_BUFFER)
2320 cifs_buf_release(iov[0].iov_base);
2322 /* Note: On -EAGAIN error only caller can retry on handle based calls
2323 since file handle passed in no longer valid */
2328 int cifs_lockv(const int xid, struct cifs_tcon *tcon, const __u16 netfid,
2329 const __u8 lock_type, const __u32 num_unlock,
2330 const __u32 num_lock, LOCKING_ANDX_RANGE *buf)
2333 LOCK_REQ *pSMB = NULL;
2338 cFYI(1, "cifs_lockv num lock %d num unlock %d", num_lock, num_unlock);
2340 rc = small_smb_init(SMB_COM_LOCKING_ANDX, 8, tcon, (void **) &pSMB);
2345 pSMB->NumberOfLocks = cpu_to_le16(num_lock);
2346 pSMB->NumberOfUnlocks = cpu_to_le16(num_unlock);
2347 pSMB->LockType = lock_type;
2348 pSMB->AndXCommand = 0xFF; /* none */
2349 pSMB->Fid = netfid; /* netfid stays le */
2351 count = (num_unlock + num_lock) * sizeof(LOCKING_ANDX_RANGE);
2352 inc_rfc1001_len(pSMB, count);
2353 pSMB->ByteCount = cpu_to_le16(count);
2355 iov[0].iov_base = (char *)pSMB;
2356 iov[0].iov_len = be32_to_cpu(pSMB->hdr.smb_buf_length) + 4 -
2357 (num_unlock + num_lock) * sizeof(LOCKING_ANDX_RANGE);
2358 iov[1].iov_base = (char *)buf;
2359 iov[1].iov_len = (num_unlock + num_lock) * sizeof(LOCKING_ANDX_RANGE);
2361 cifs_stats_inc(&tcon->num_locks);
2362 rc = SendReceive2(xid, tcon->ses, iov, 2, &resp_buf_type, CIFS_NO_RESP);
2364 cFYI(1, "Send error in cifs_lockv = %d", rc);
2370 CIFSSMBLock(const int xid, struct cifs_tcon *tcon,
2371 const __u16 smb_file_id, const __u32 netpid, const __u64 len,
2372 const __u64 offset, const __u32 numUnlock,
2373 const __u32 numLock, const __u8 lockType,
2374 const bool waitFlag, const __u8 oplock_level)
2377 LOCK_REQ *pSMB = NULL;
2378 /* LOCK_RSP *pSMBr = NULL; */ /* No response data other than rc to parse */
2383 cFYI(1, "CIFSSMBLock timeout %d numLock %d", (int)waitFlag, numLock);
2384 rc = small_smb_init(SMB_COM_LOCKING_ANDX, 8, tcon, (void **) &pSMB);
2389 if (lockType == LOCKING_ANDX_OPLOCK_RELEASE) {
2390 timeout = CIFS_ASYNC_OP; /* no response expected */
2392 } else if (waitFlag) {
2393 timeout = CIFS_BLOCKING_OP; /* blocking operation, no timeout */
2394 pSMB->Timeout = cpu_to_le32(-1);/* blocking - do not time out */
2399 pSMB->NumberOfLocks = cpu_to_le16(numLock);
2400 pSMB->NumberOfUnlocks = cpu_to_le16(numUnlock);
2401 pSMB->LockType = lockType;
2402 pSMB->OplockLevel = oplock_level;
2403 pSMB->AndXCommand = 0xFF; /* none */
2404 pSMB->Fid = smb_file_id; /* netfid stays le */
2406 if ((numLock != 0) || (numUnlock != 0)) {
2407 pSMB->Locks[0].Pid = cpu_to_le16(netpid);
2408 /* BB where to store pid high? */
2409 pSMB->Locks[0].LengthLow = cpu_to_le32((u32)len);
2410 pSMB->Locks[0].LengthHigh = cpu_to_le32((u32)(len>>32));
2411 pSMB->Locks[0].OffsetLow = cpu_to_le32((u32)offset);
2412 pSMB->Locks[0].OffsetHigh = cpu_to_le32((u32)(offset>>32));
2413 count = sizeof(LOCKING_ANDX_RANGE);
2418 inc_rfc1001_len(pSMB, count);
2419 pSMB->ByteCount = cpu_to_le16(count);
2422 rc = SendReceiveBlockingLock(xid, tcon, (struct smb_hdr *) pSMB,
2423 (struct smb_hdr *) pSMB, &bytes_returned);
2424 cifs_small_buf_release(pSMB);
2426 rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *)pSMB,
2428 /* SMB buffer freed by function above */
2430 cifs_stats_inc(&tcon->num_locks);
2432 cFYI(1, "Send error in Lock = %d", rc);
2434 /* Note: On -EAGAIN error only caller can retry on handle based calls
2435 since file handle passed in no longer valid */
2440 CIFSSMBPosixLock(const int xid, struct cifs_tcon *tcon,
2441 const __u16 smb_file_id, const __u32 netpid, const int get_flag,
2442 const __u64 len, struct file_lock *pLockData,
2443 const __u16 lock_type, const bool waitFlag)
2445 struct smb_com_transaction2_sfi_req *pSMB = NULL;
2446 struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
2447 struct cifs_posix_lock *parm_data;
2450 int bytes_returned = 0;
2451 int resp_buf_type = 0;
2452 __u16 params, param_offset, offset, byte_count, count;
2455 cFYI(1, "Posix Lock");
2457 if (pLockData == NULL)
2460 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
2465 pSMBr = (struct smb_com_transaction2_sfi_rsp *)pSMB;
2468 pSMB->MaxSetupCount = 0;
2471 pSMB->Reserved2 = 0;
2472 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
2473 offset = param_offset + params;
2475 count = sizeof(struct cifs_posix_lock);
2476 pSMB->MaxParameterCount = cpu_to_le16(2);
2477 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB from sess */
2478 pSMB->SetupCount = 1;
2479 pSMB->Reserved3 = 0;
2481 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION);
2483 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
2484 byte_count = 3 /* pad */ + params + count;
2485 pSMB->DataCount = cpu_to_le16(count);
2486 pSMB->ParameterCount = cpu_to_le16(params);
2487 pSMB->TotalDataCount = pSMB->DataCount;
2488 pSMB->TotalParameterCount = pSMB->ParameterCount;
2489 pSMB->ParameterOffset = cpu_to_le16(param_offset);
2490 parm_data = (struct cifs_posix_lock *)
2491 (((char *) &pSMB->hdr.Protocol) + offset);
2493 parm_data->lock_type = cpu_to_le16(lock_type);
2495 timeout = CIFS_BLOCKING_OP; /* blocking operation, no timeout */
2496 parm_data->lock_flags = cpu_to_le16(1);
2497 pSMB->Timeout = cpu_to_le32(-1);
2501 parm_data->pid = cpu_to_le32(netpid);
2502 parm_data->start = cpu_to_le64(pLockData->fl_start);
2503 parm_data->length = cpu_to_le64(len); /* normalize negative numbers */
2505 pSMB->DataOffset = cpu_to_le16(offset);
2506 pSMB->Fid = smb_file_id;
2507 pSMB->InformationLevel = cpu_to_le16(SMB_SET_POSIX_LOCK);
2508 pSMB->Reserved4 = 0;
2509 inc_rfc1001_len(pSMB, byte_count);
2510 pSMB->ByteCount = cpu_to_le16(byte_count);
2512 rc = SendReceiveBlockingLock(xid, tcon, (struct smb_hdr *) pSMB,
2513 (struct smb_hdr *) pSMBr, &bytes_returned);
2515 iov[0].iov_base = (char *)pSMB;
2516 iov[0].iov_len = be32_to_cpu(pSMB->hdr.smb_buf_length) + 4;
2517 rc = SendReceive2(xid, tcon->ses, iov, 1 /* num iovecs */,
2518 &resp_buf_type, timeout);
2519 pSMB = NULL; /* request buf already freed by SendReceive2. Do
2520 not try to free it twice below on exit */
2521 pSMBr = (struct smb_com_transaction2_sfi_rsp *)iov[0].iov_base;
2525 cFYI(1, "Send error in Posix Lock = %d", rc);
2526 } else if (get_flag) {
2527 /* lock structure can be returned on get */
2530 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
2532 if (rc || get_bcc(&pSMBr->hdr) < sizeof(*parm_data)) {
2533 rc = -EIO; /* bad smb */
2536 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
2537 data_count = le16_to_cpu(pSMBr->t2.DataCount);
2538 if (data_count < sizeof(struct cifs_posix_lock)) {
2542 parm_data = (struct cifs_posix_lock *)
2543 ((char *)&pSMBr->hdr.Protocol + data_offset);
2544 if (parm_data->lock_type == __constant_cpu_to_le16(CIFS_UNLCK))
2545 pLockData->fl_type = F_UNLCK;
2547 if (parm_data->lock_type ==
2548 __constant_cpu_to_le16(CIFS_RDLCK))
2549 pLockData->fl_type = F_RDLCK;
2550 else if (parm_data->lock_type ==
2551 __constant_cpu_to_le16(CIFS_WRLCK))
2552 pLockData->fl_type = F_WRLCK;
2554 pLockData->fl_start = le64_to_cpu(parm_data->start);
2555 pLockData->fl_end = pLockData->fl_start +
2556 le64_to_cpu(parm_data->length) - 1;
2557 pLockData->fl_pid = le32_to_cpu(parm_data->pid);
2563 cifs_small_buf_release(pSMB);
2565 if (resp_buf_type == CIFS_SMALL_BUFFER)
2566 cifs_small_buf_release(iov[0].iov_base);
2567 else if (resp_buf_type == CIFS_LARGE_BUFFER)
2568 cifs_buf_release(iov[0].iov_base);
2570 /* Note: On -EAGAIN error only caller can retry on handle based calls
2571 since file handle passed in no longer valid */
2578 CIFSSMBClose(const int xid, struct cifs_tcon *tcon, int smb_file_id)
2581 CLOSE_REQ *pSMB = NULL;
2582 cFYI(1, "In CIFSSMBClose");
2584 /* do not retry on dead session on close */
2585 rc = small_smb_init(SMB_COM_CLOSE, 3, tcon, (void **) &pSMB);
2591 pSMB->FileID = (__u16) smb_file_id;
2592 pSMB->LastWriteTime = 0xFFFFFFFF;
2593 pSMB->ByteCount = 0;
2594 rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0);
2595 cifs_stats_inc(&tcon->num_closes);
2598 /* EINTR is expected when user ctl-c to kill app */
2599 cERROR(1, "Send error in Close = %d", rc);
2603 /* Since session is dead, file will be closed on server already */
2611 CIFSSMBFlush(const int xid, struct cifs_tcon *tcon, int smb_file_id)
2614 FLUSH_REQ *pSMB = NULL;
2615 cFYI(1, "In CIFSSMBFlush");
2617 rc = small_smb_init(SMB_COM_FLUSH, 1, tcon, (void **) &pSMB);
2621 pSMB->FileID = (__u16) smb_file_id;
2622 pSMB->ByteCount = 0;
2623 rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0);
2624 cifs_stats_inc(&tcon->num_flushes);
2626 cERROR(1, "Send error in Flush = %d", rc);
2632 CIFSSMBRename(const int xid, struct cifs_tcon *tcon,
2633 const char *fromName, const char *toName,
2634 const struct nls_table *nls_codepage, int remap)
2637 RENAME_REQ *pSMB = NULL;
2638 RENAME_RSP *pSMBr = NULL;
2640 int name_len, name_len2;
2643 cFYI(1, "In CIFSSMBRename");
2645 rc = smb_init(SMB_COM_RENAME, 1, tcon, (void **) &pSMB,
2650 pSMB->BufferFormat = 0x04;
2651 pSMB->SearchAttributes =
2652 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
2655 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2657 cifsConvertToUCS((__le16 *) pSMB->OldFileName, fromName,
2658 PATH_MAX, nls_codepage, remap);
2659 name_len++; /* trailing null */
2661 pSMB->OldFileName[name_len] = 0x04; /* pad */
2662 /* protocol requires ASCII signature byte on Unicode string */
2663 pSMB->OldFileName[name_len + 1] = 0x00;
2665 cifsConvertToUCS((__le16 *)&pSMB->OldFileName[name_len + 2],
2666 toName, PATH_MAX, nls_codepage, remap);
2667 name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
2668 name_len2 *= 2; /* convert to bytes */
2669 } else { /* BB improve the check for buffer overruns BB */
2670 name_len = strnlen(fromName, PATH_MAX);
2671 name_len++; /* trailing null */
2672 strncpy(pSMB->OldFileName, fromName, name_len);
2673 name_len2 = strnlen(toName, PATH_MAX);
2674 name_len2++; /* trailing null */
2675 pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */
2676 strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2);
2677 name_len2++; /* trailing null */
2678 name_len2++; /* signature byte */
2681 count = 1 /* 1st signature byte */ + name_len + name_len2;
2682 inc_rfc1001_len(pSMB, count);
2683 pSMB->ByteCount = cpu_to_le16(count);
2685 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2686 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2687 cifs_stats_inc(&tcon->num_renames);
2689 cFYI(1, "Send error in rename = %d", rc);
2691 cifs_buf_release(pSMB);
2699 int CIFSSMBRenameOpenFile(const int xid, struct cifs_tcon *pTcon,
2700 int netfid, const char *target_name,
2701 const struct nls_table *nls_codepage, int remap)
2703 struct smb_com_transaction2_sfi_req *pSMB = NULL;
2704 struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
2705 struct set_file_rename *rename_info;
2707 char dummy_string[30];
2709 int bytes_returned = 0;
2711 __u16 params, param_offset, offset, count, byte_count;
2713 cFYI(1, "Rename to File by handle");
2714 rc = smb_init(SMB_COM_TRANSACTION2, 15, pTcon, (void **) &pSMB,
2720 pSMB->MaxSetupCount = 0;
2724 pSMB->Reserved2 = 0;
2725 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
2726 offset = param_offset + params;
2728 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
2729 rename_info = (struct set_file_rename *) data_offset;
2730 pSMB->MaxParameterCount = cpu_to_le16(2);
2731 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB from sess */
2732 pSMB->SetupCount = 1;
2733 pSMB->Reserved3 = 0;
2734 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
2735 byte_count = 3 /* pad */ + params;
2736 pSMB->ParameterCount = cpu_to_le16(params);
2737 pSMB->TotalParameterCount = pSMB->ParameterCount;
2738 pSMB->ParameterOffset = cpu_to_le16(param_offset);
2739 pSMB->DataOffset = cpu_to_le16(offset);
2740 /* construct random name ".cifs_tmp<inodenum><mid>" */
2741 rename_info->overwrite = cpu_to_le32(1);
2742 rename_info->root_fid = 0;
2743 /* unicode only call */
2744 if (target_name == NULL) {
2745 sprintf(dummy_string, "cifs%x", pSMB->hdr.Mid);
2746 len_of_str = cifsConvertToUCS((__le16 *)rename_info->target_name,
2747 dummy_string, 24, nls_codepage, remap);
2749 len_of_str = cifsConvertToUCS((__le16 *)rename_info->target_name,
2750 target_name, PATH_MAX, nls_codepage,
2753 rename_info->target_name_len = cpu_to_le32(2 * len_of_str);
2754 count = 12 /* sizeof(struct set_file_rename) */ + (2 * len_of_str);
2755 byte_count += count;
2756 pSMB->DataCount = cpu_to_le16(count);
2757 pSMB->TotalDataCount = pSMB->DataCount;
2759 pSMB->InformationLevel =
2760 cpu_to_le16(SMB_SET_FILE_RENAME_INFORMATION);
2761 pSMB->Reserved4 = 0;
2762 inc_rfc1001_len(pSMB, byte_count);
2763 pSMB->ByteCount = cpu_to_le16(byte_count);
2764 rc = SendReceive(xid, pTcon->ses, (struct smb_hdr *) pSMB,
2765 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2766 cifs_stats_inc(&pTcon->num_t2renames);
2768 cFYI(1, "Send error in Rename (by file handle) = %d", rc);
2770 cifs_buf_release(pSMB);
2772 /* Note: On -EAGAIN error only caller can retry on handle based calls
2773 since file handle passed in no longer valid */
2779 CIFSSMBCopy(const int xid, struct cifs_tcon *tcon, const char *fromName,
2780 const __u16 target_tid, const char *toName, const int flags,
2781 const struct nls_table *nls_codepage, int remap)
2784 COPY_REQ *pSMB = NULL;
2785 COPY_RSP *pSMBr = NULL;
2787 int name_len, name_len2;
2790 cFYI(1, "In CIFSSMBCopy");
2792 rc = smb_init(SMB_COM_COPY, 1, tcon, (void **) &pSMB,
2797 pSMB->BufferFormat = 0x04;
2798 pSMB->Tid2 = target_tid;
2800 pSMB->Flags = cpu_to_le16(flags & COPY_TREE);
2802 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2803 name_len = cifsConvertToUCS((__le16 *) pSMB->OldFileName,
2804 fromName, PATH_MAX, nls_codepage,
2806 name_len++; /* trailing null */
2808 pSMB->OldFileName[name_len] = 0x04; /* pad */
2809 /* protocol requires ASCII signature byte on Unicode string */
2810 pSMB->OldFileName[name_len + 1] = 0x00;
2812 cifsConvertToUCS((__le16 *)&pSMB->OldFileName[name_len + 2],
2813 toName, PATH_MAX, nls_codepage, remap);
2814 name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
2815 name_len2 *= 2; /* convert to bytes */
2816 } else { /* BB improve the check for buffer overruns BB */
2817 name_len = strnlen(fromName, PATH_MAX);
2818 name_len++; /* trailing null */
2819 strncpy(pSMB->OldFileName, fromName, name_len);
2820 name_len2 = strnlen(toName, PATH_MAX);
2821 name_len2++; /* trailing null */
2822 pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */
2823 strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2);
2824 name_len2++; /* trailing null */
2825 name_len2++; /* signature byte */
2828 count = 1 /* 1st signature byte */ + name_len + name_len2;
2829 inc_rfc1001_len(pSMB, count);
2830 pSMB->ByteCount = cpu_to_le16(count);
2832 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2833 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2835 cFYI(1, "Send error in copy = %d with %d files copied",
2836 rc, le16_to_cpu(pSMBr->CopyCount));
2838 cifs_buf_release(pSMB);
2847 CIFSUnixCreateSymLink(const int xid, struct cifs_tcon *tcon,
2848 const char *fromName, const char *toName,
2849 const struct nls_table *nls_codepage)
2851 TRANSACTION2_SPI_REQ *pSMB = NULL;
2852 TRANSACTION2_SPI_RSP *pSMBr = NULL;
2855 int name_len_target;
2857 int bytes_returned = 0;
2858 __u16 params, param_offset, offset, byte_count;
2860 cFYI(1, "In Symlink Unix style");
2862 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2867 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2869 cifs_strtoUCS((__le16 *) pSMB->FileName, fromName, PATH_MAX
2870 /* find define for this maxpathcomponent */
2872 name_len++; /* trailing null */
2875 } else { /* BB improve the check for buffer overruns BB */
2876 name_len = strnlen(fromName, PATH_MAX);
2877 name_len++; /* trailing null */
2878 strncpy(pSMB->FileName, fromName, name_len);
2880 params = 6 + name_len;
2881 pSMB->MaxSetupCount = 0;
2885 pSMB->Reserved2 = 0;
2886 param_offset = offsetof(struct smb_com_transaction2_spi_req,
2887 InformationLevel) - 4;
2888 offset = param_offset + params;
2890 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
2891 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2893 cifs_strtoUCS((__le16 *) data_offset, toName, PATH_MAX
2894 /* find define for this maxpathcomponent */
2896 name_len_target++; /* trailing null */
2897 name_len_target *= 2;
2898 } else { /* BB improve the check for buffer overruns BB */
2899 name_len_target = strnlen(toName, PATH_MAX);
2900 name_len_target++; /* trailing null */
2901 strncpy(data_offset, toName, name_len_target);
2904 pSMB->MaxParameterCount = cpu_to_le16(2);
2905 /* BB find exact max on data count below from sess */
2906 pSMB->MaxDataCount = cpu_to_le16(1000);
2907 pSMB->SetupCount = 1;
2908 pSMB->Reserved3 = 0;
2909 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
2910 byte_count = 3 /* pad */ + params + name_len_target;
2911 pSMB->DataCount = cpu_to_le16(name_len_target);
2912 pSMB->ParameterCount = cpu_to_le16(params);
2913 pSMB->TotalDataCount = pSMB->DataCount;
2914 pSMB->TotalParameterCount = pSMB->ParameterCount;
2915 pSMB->ParameterOffset = cpu_to_le16(param_offset);
2916 pSMB->DataOffset = cpu_to_le16(offset);
2917 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_LINK);
2918 pSMB->Reserved4 = 0;
2919 inc_rfc1001_len(pSMB, byte_count);
2920 pSMB->ByteCount = cpu_to_le16(byte_count);
2921 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2922 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2923 cifs_stats_inc(&tcon->num_symlinks);
2925 cFYI(1, "Send error in SetPathInfo create symlink = %d", rc);
2927 cifs_buf_release(pSMB);
2930 goto createSymLinkRetry;
2936 CIFSUnixCreateHardLink(const int xid, struct cifs_tcon *tcon,
2937 const char *fromName, const char *toName,
2938 const struct nls_table *nls_codepage, int remap)
2940 TRANSACTION2_SPI_REQ *pSMB = NULL;
2941 TRANSACTION2_SPI_RSP *pSMBr = NULL;
2944 int name_len_target;
2946 int bytes_returned = 0;
2947 __u16 params, param_offset, offset, byte_count;
2949 cFYI(1, "In Create Hard link Unix style");
2950 createHardLinkRetry:
2951 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2956 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2957 name_len = cifsConvertToUCS((__le16 *) pSMB->FileName, toName,
2958 PATH_MAX, nls_codepage, remap);
2959 name_len++; /* trailing null */
2962 } else { /* BB improve the check for buffer overruns BB */
2963 name_len = strnlen(toName, PATH_MAX);
2964 name_len++; /* trailing null */
2965 strncpy(pSMB->FileName, toName, name_len);
2967 params = 6 + name_len;
2968 pSMB->MaxSetupCount = 0;
2972 pSMB->Reserved2 = 0;
2973 param_offset = offsetof(struct smb_com_transaction2_spi_req,
2974 InformationLevel) - 4;
2975 offset = param_offset + params;
2977 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
2978 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2980 cifsConvertToUCS((__le16 *) data_offset, fromName, PATH_MAX,
2981 nls_codepage, remap);
2982 name_len_target++; /* trailing null */
2983 name_len_target *= 2;
2984 } else { /* BB improve the check for buffer overruns BB */
2985 name_len_target = strnlen(fromName, PATH_MAX);
2986 name_len_target++; /* trailing null */
2987 strncpy(data_offset, fromName, name_len_target);
2990 pSMB->MaxParameterCount = cpu_to_le16(2);
2991 /* BB find exact max on data count below from sess*/
2992 pSMB->MaxDataCount = cpu_to_le16(1000);
2993 pSMB->SetupCount = 1;
2994 pSMB->Reserved3 = 0;
2995 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
2996 byte_count = 3 /* pad */ + params + name_len_target;
2997 pSMB->ParameterCount = cpu_to_le16(params);
2998 pSMB->TotalParameterCount = pSMB->ParameterCount;
2999 pSMB->DataCount = cpu_to_le16(name_len_target);
3000 pSMB->TotalDataCount = pSMB->DataCount;
3001 pSMB->ParameterOffset = cpu_to_le16(param_offset);
3002 pSMB->DataOffset = cpu_to_le16(offset);
3003 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_HLINK);
3004 pSMB->Reserved4 = 0;
3005 inc_rfc1001_len(pSMB, byte_count);
3006 pSMB->ByteCount = cpu_to_le16(byte_count);
3007 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3008 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3009 cifs_stats_inc(&tcon->num_hardlinks);
3011 cFYI(1, "Send error in SetPathInfo (hard link) = %d", rc);
3013 cifs_buf_release(pSMB);
3015 goto createHardLinkRetry;
3021 CIFSCreateHardLink(const int xid, struct cifs_tcon *tcon,
3022 const char *fromName, const char *toName,
3023 const struct nls_table *nls_codepage, int remap)
3026 NT_RENAME_REQ *pSMB = NULL;
3027 RENAME_RSP *pSMBr = NULL;
3029 int name_len, name_len2;
3032 cFYI(1, "In CIFSCreateHardLink");
3033 winCreateHardLinkRetry:
3035 rc = smb_init(SMB_COM_NT_RENAME, 4, tcon, (void **) &pSMB,
3040 pSMB->SearchAttributes =
3041 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
3043 pSMB->Flags = cpu_to_le16(CREATE_HARD_LINK);
3044 pSMB->ClusterCount = 0;
3046 pSMB->BufferFormat = 0x04;
3048 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3050 cifsConvertToUCS((__le16 *) pSMB->OldFileName, fromName,
3051 PATH_MAX, nls_codepage, remap);
3052 name_len++; /* trailing null */
3055 /* protocol specifies ASCII buffer format (0x04) for unicode */
3056 pSMB->OldFileName[name_len] = 0x04;
3057 pSMB->OldFileName[name_len + 1] = 0x00; /* pad */
3059 cifsConvertToUCS((__le16 *)&pSMB->OldFileName[name_len + 2],
3060 toName, PATH_MAX, nls_codepage, remap);
3061 name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
3062 name_len2 *= 2; /* convert to bytes */
3063 } else { /* BB improve the check for buffer overruns BB */
3064 name_len = strnlen(fromName, PATH_MAX);
3065 name_len++; /* trailing null */
3066 strncpy(pSMB->OldFileName, fromName, name_len);
3067 name_len2 = strnlen(toName, PATH_MAX);
3068 name_len2++; /* trailing null */
3069 pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */
3070 strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2);
3071 name_len2++; /* trailing null */
3072 name_len2++; /* signature byte */
3075 count = 1 /* string type byte */ + name_len + name_len2;
3076 inc_rfc1001_len(pSMB, count);
3077 pSMB->ByteCount = cpu_to_le16(count);
3079 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3080 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3081 cifs_stats_inc(&tcon->num_hardlinks);
3083 cFYI(1, "Send error in hard link (NT rename) = %d", rc);
3085 cifs_buf_release(pSMB);
3087 goto winCreateHardLinkRetry;
3093 CIFSSMBUnixQuerySymLink(const int xid, struct cifs_tcon *tcon,
3094 const unsigned char *searchName, char **symlinkinfo,
3095 const struct nls_table *nls_codepage)
3097 /* SMB_QUERY_FILE_UNIX_LINK */
3098 TRANSACTION2_QPI_REQ *pSMB = NULL;
3099 TRANSACTION2_QPI_RSP *pSMBr = NULL;
3103 __u16 params, byte_count;
3106 cFYI(1, "In QPathSymLinkInfo (Unix) for path %s", searchName);
3109 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3114 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3116 cifs_strtoUCS((__le16 *) pSMB->FileName, searchName,
3117 PATH_MAX, nls_codepage);
3118 name_len++; /* trailing null */
3120 } else { /* BB improve the check for buffer overruns BB */
3121 name_len = strnlen(searchName, PATH_MAX);
3122 name_len++; /* trailing null */
3123 strncpy(pSMB->FileName, searchName, name_len);
3126 params = 2 /* level */ + 4 /* rsrvd */ + name_len /* incl null */ ;
3127 pSMB->TotalDataCount = 0;
3128 pSMB->MaxParameterCount = cpu_to_le16(2);
3129 pSMB->MaxDataCount = cpu_to_le16(CIFSMaxBufSize);
3130 pSMB->MaxSetupCount = 0;
3134 pSMB->Reserved2 = 0;
3135 pSMB->ParameterOffset = cpu_to_le16(offsetof(
3136 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
3137 pSMB->DataCount = 0;
3138 pSMB->DataOffset = 0;
3139 pSMB->SetupCount = 1;
3140 pSMB->Reserved3 = 0;
3141 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
3142 byte_count = params + 1 /* pad */ ;
3143 pSMB->TotalParameterCount = cpu_to_le16(params);
3144 pSMB->ParameterCount = pSMB->TotalParameterCount;
3145 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_LINK);
3146 pSMB->Reserved4 = 0;
3147 inc_rfc1001_len(pSMB, byte_count);
3148 pSMB->ByteCount = cpu_to_le16(byte_count);
3150 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3151 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3153 cFYI(1, "Send error in QuerySymLinkInfo = %d", rc);
3155 /* decode response */
3157 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3158 /* BB also check enough total bytes returned */
3159 if (rc || get_bcc(&pSMBr->hdr) < 2)
3163 u16 count = le16_to_cpu(pSMBr->t2.DataCount);
3165 data_start = ((char *) &pSMBr->hdr.Protocol) +
3166 le16_to_cpu(pSMBr->t2.DataOffset);
3168 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
3173 /* BB FIXME investigate remapping reserved chars here */
3174 *symlinkinfo = cifs_strndup_from_ucs(data_start, count,
3175 is_unicode, nls_codepage);
3180 cifs_buf_release(pSMB);
3182 goto querySymLinkRetry;
3186 #ifdef CONFIG_CIFS_SYMLINK_EXPERIMENTAL
3188 * Recent Windows versions now create symlinks more frequently
3189 * and they use the "reparse point" mechanism below. We can of course
3190 * do symlinks nicely to Samba and other servers which support the
3191 * CIFS Unix Extensions and we can also do SFU symlinks and "client only"
3192 * "MF" symlinks optionally, but for recent Windows we really need to
3193 * reenable the code below and fix the cifs_symlink callers to handle this.
3194 * In the interim this code has been moved to its own config option so
3195 * it is not compiled in by default until callers fixed up and more tested.
3198 CIFSSMBQueryReparseLinkInfo(const int xid, struct cifs_tcon *tcon,
3199 const unsigned char *searchName,
3200 char *symlinkinfo, const int buflen, __u16 fid,
3201 const struct nls_table *nls_codepage)
3205 struct smb_com_transaction_ioctl_req *pSMB;
3206 struct smb_com_transaction_ioctl_rsp *pSMBr;
3208 cFYI(1, "In Windows reparse style QueryLink for path %s", searchName);
3209 rc = smb_init(SMB_COM_NT_TRANSACT, 23, tcon, (void **) &pSMB,
3214 pSMB->TotalParameterCount = 0 ;
3215 pSMB->TotalDataCount = 0;
3216 pSMB->MaxParameterCount = cpu_to_le32(2);
3217 /* BB find exact data count max from sess structure BB */
3218 pSMB->MaxDataCount = cpu_to_le32(CIFSMaxBufSize & 0xFFFFFF00);
3219 pSMB->MaxSetupCount = 4;
3221 pSMB->ParameterOffset = 0;
3222 pSMB->DataCount = 0;
3223 pSMB->DataOffset = 0;
3224 pSMB->SetupCount = 4;
3225 pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_IOCTL);
3226 pSMB->ParameterCount = pSMB->TotalParameterCount;
3227 pSMB->FunctionCode = cpu_to_le32(FSCTL_GET_REPARSE_POINT);
3228 pSMB->IsFsctl = 1; /* FSCTL */
3229 pSMB->IsRootFlag = 0;
3230 pSMB->Fid = fid; /* file handle always le */
3231 pSMB->ByteCount = 0;
3233 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3234 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3236 cFYI(1, "Send error in QueryReparseLinkInfo = %d", rc);
3237 } else { /* decode response */
3238 __u32 data_offset = le32_to_cpu(pSMBr->DataOffset);
3239 __u32 data_count = le32_to_cpu(pSMBr->DataCount);
3240 if (get_bcc(&pSMBr->hdr) < 2 || data_offset > 512) {
3241 /* BB also check enough total bytes returned */
3242 rc = -EIO; /* bad smb */
3245 if (data_count && (data_count < 2048)) {
3246 char *end_of_smb = 2 /* sizeof byte count */ +
3247 get_bcc(&pSMBr->hdr) + (char *)&pSMBr->ByteCount;
3249 struct reparse_data *reparse_buf =
3250 (struct reparse_data *)
3251 ((char *)&pSMBr->hdr.Protocol
3253 if ((char *)reparse_buf >= end_of_smb) {
3257 if ((reparse_buf->LinkNamesBuf +
3258 reparse_buf->TargetNameOffset +
3259 reparse_buf->TargetNameLen) > end_of_smb) {
3260 cFYI(1, "reparse buf beyond SMB");
3265 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
3266 cifs_from_ucs2(symlinkinfo, (__le16 *)
3267 (reparse_buf->LinkNamesBuf +
3268 reparse_buf->TargetNameOffset),
3270 reparse_buf->TargetNameLen,
3272 } else { /* ASCII names */
3273 strncpy(symlinkinfo,
3274 reparse_buf->LinkNamesBuf +
3275 reparse_buf->TargetNameOffset,
3276 min_t(const int, buflen,
3277 reparse_buf->TargetNameLen));
3281 cFYI(1, "Invalid return data count on "
3282 "get reparse info ioctl");
3284 symlinkinfo[buflen] = 0; /* just in case so the caller
3285 does not go off the end of the buffer */
3286 cFYI(1, "readlink result - %s", symlinkinfo);
3290 cifs_buf_release(pSMB);
3292 /* Note: On -EAGAIN error only caller can retry on handle based calls
3293 since file handle passed in no longer valid */
3297 #endif /* CIFS_SYMLINK_EXPERIMENTAL */ /* BB temporarily unused */
3299 #ifdef CONFIG_CIFS_POSIX
3301 /*Convert an Access Control Entry from wire format to local POSIX xattr format*/
3302 static void cifs_convert_ace(posix_acl_xattr_entry *ace,
3303 struct cifs_posix_ace *cifs_ace)
3305 /* u8 cifs fields do not need le conversion */
3306 ace->e_perm = cpu_to_le16(cifs_ace->cifs_e_perm);
3307 ace->e_tag = cpu_to_le16(cifs_ace->cifs_e_tag);
3308 ace->e_id = cpu_to_le32(le64_to_cpu(cifs_ace->cifs_uid));
3309 /* cFYI(1, "perm %d tag %d id %d",ace->e_perm,ace->e_tag,ace->e_id); */
3314 /* Convert ACL from CIFS POSIX wire format to local Linux POSIX ACL xattr */
3315 static int cifs_copy_posix_acl(char *trgt, char *src, const int buflen,
3316 const int acl_type, const int size_of_data_area)
3321 struct cifs_posix_ace *pACE;
3322 struct cifs_posix_acl *cifs_acl = (struct cifs_posix_acl *)src;
3323 posix_acl_xattr_header *local_acl = (posix_acl_xattr_header *)trgt;
3325 if (le16_to_cpu(cifs_acl->version) != CIFS_ACL_VERSION)
3328 if (acl_type & ACL_TYPE_ACCESS) {
3329 count = le16_to_cpu(cifs_acl->access_entry_count);
3330 pACE = &cifs_acl->ace_array[0];
3331 size = sizeof(struct cifs_posix_acl);
3332 size += sizeof(struct cifs_posix_ace) * count;
3333 /* check if we would go beyond end of SMB */
3334 if (size_of_data_area < size) {
3335 cFYI(1, "bad CIFS POSIX ACL size %d vs. %d",
3336 size_of_data_area, size);
3339 } else if (acl_type & ACL_TYPE_DEFAULT) {
3340 count = le16_to_cpu(cifs_acl->access_entry_count);
3341 size = sizeof(struct cifs_posix_acl);
3342 size += sizeof(struct cifs_posix_ace) * count;
3343 /* skip past access ACEs to get to default ACEs */
3344 pACE = &cifs_acl->ace_array[count];
3345 count = le16_to_cpu(cifs_acl->default_entry_count);
3346 size += sizeof(struct cifs_posix_ace) * count;
3347 /* check if we would go beyond end of SMB */
3348 if (size_of_data_area < size)
3355 size = posix_acl_xattr_size(count);
3356 if ((buflen == 0) || (local_acl == NULL)) {
3357 /* used to query ACL EA size */
3358 } else if (size > buflen) {
3360 } else /* buffer big enough */ {
3361 local_acl->a_version = cpu_to_le32(POSIX_ACL_XATTR_VERSION);
3362 for (i = 0; i < count ; i++) {
3363 cifs_convert_ace(&local_acl->a_entries[i], pACE);
3370 static __u16 convert_ace_to_cifs_ace(struct cifs_posix_ace *cifs_ace,
3371 const posix_acl_xattr_entry *local_ace)
3373 __u16 rc = 0; /* 0 = ACL converted ok */
3375 cifs_ace->cifs_e_perm = le16_to_cpu(local_ace->e_perm);
3376 cifs_ace->cifs_e_tag = le16_to_cpu(local_ace->e_tag);
3377 /* BB is there a better way to handle the large uid? */
3378 if (local_ace->e_id == cpu_to_le32(-1)) {
3379 /* Probably no need to le convert -1 on any arch but can not hurt */
3380 cifs_ace->cifs_uid = cpu_to_le64(-1);
3382 cifs_ace->cifs_uid = cpu_to_le64(le32_to_cpu(local_ace->e_id));
3383 /*cFYI(1, "perm %d tag %d id %d",ace->e_perm,ace->e_tag,ace->e_id);*/
3387 /* Convert ACL from local Linux POSIX xattr to CIFS POSIX ACL wire format */
3388 static __u16 ACL_to_cifs_posix(char *parm_data, const char *pACL,
3389 const int buflen, const int acl_type)
3392 struct cifs_posix_acl *cifs_acl = (struct cifs_posix_acl *)parm_data;
3393 posix_acl_xattr_header *local_acl = (posix_acl_xattr_header *)pACL;
3397 if ((buflen == 0) || (pACL == NULL) || (cifs_acl == NULL))
3400 count = posix_acl_xattr_count((size_t)buflen);
3401 cFYI(1, "setting acl with %d entries from buf of length %d and "
3403 count, buflen, le32_to_cpu(local_acl->a_version));
3404 if (le32_to_cpu(local_acl->a_version) != 2) {
3405 cFYI(1, "unknown POSIX ACL version %d",
3406 le32_to_cpu(local_acl->a_version));
3409 cifs_acl->version = cpu_to_le16(1);
3410 if (acl_type == ACL_TYPE_ACCESS)
3411 cifs_acl->access_entry_count = cpu_to_le16(count);
3412 else if (acl_type == ACL_TYPE_DEFAULT)
3413 cifs_acl->default_entry_count = cpu_to_le16(count);
3415 cFYI(1, "unknown ACL type %d", acl_type);
3418 for (i = 0; i < count; i++) {
3419 rc = convert_ace_to_cifs_ace(&cifs_acl->ace_array[i],
3420 &local_acl->a_entries[i]);
3422 /* ACE not converted */
3427 rc = (__u16)(count * sizeof(struct cifs_posix_ace));
3428 rc += sizeof(struct cifs_posix_acl);
3429 /* BB add check to make sure ACL does not overflow SMB */
3435 CIFSSMBGetPosixACL(const int xid, struct cifs_tcon *tcon,
3436 const unsigned char *searchName,
3437 char *acl_inf, const int buflen, const int acl_type,
3438 const struct nls_table *nls_codepage, int remap)
3440 /* SMB_QUERY_POSIX_ACL */
3441 TRANSACTION2_QPI_REQ *pSMB = NULL;
3442 TRANSACTION2_QPI_RSP *pSMBr = NULL;
3446 __u16 params, byte_count;
3448 cFYI(1, "In GetPosixACL (Unix) for path %s", searchName);
3451 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3456 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3458 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
3459 PATH_MAX, nls_codepage, remap);
3460 name_len++; /* trailing null */
3462 pSMB->FileName[name_len] = 0;
3463 pSMB->FileName[name_len+1] = 0;
3464 } else { /* BB improve the check for buffer overruns BB */
3465 name_len = strnlen(searchName, PATH_MAX);
3466 name_len++; /* trailing null */
3467 strncpy(pSMB->FileName, searchName, name_len);
3470 params = 2 /* level */ + 4 /* rsrvd */ + name_len /* incl null */ ;
3471 pSMB->TotalDataCount = 0;
3472 pSMB->MaxParameterCount = cpu_to_le16(2);
3473 /* BB find exact max data count below from sess structure BB */
3474 pSMB->MaxDataCount = cpu_to_le16(4000);
3475 pSMB->MaxSetupCount = 0;
3479 pSMB->Reserved2 = 0;
3480 pSMB->ParameterOffset = cpu_to_le16(
3481 offsetof(struct smb_com_transaction2_qpi_req,
3482 InformationLevel) - 4);
3483 pSMB->DataCount = 0;
3484 pSMB->DataOffset = 0;
3485 pSMB->SetupCount = 1;
3486 pSMB->Reserved3 = 0;
3487 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
3488 byte_count = params + 1 /* pad */ ;
3489 pSMB->TotalParameterCount = cpu_to_le16(params);
3490 pSMB->ParameterCount = pSMB->TotalParameterCount;
3491 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_POSIX_ACL);
3492 pSMB->Reserved4 = 0;
3493 inc_rfc1001_len(pSMB, byte_count);
3494 pSMB->ByteCount = cpu_to_le16(byte_count);
3496 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3497 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3498 cifs_stats_inc(&tcon->num_acl_get);
3500 cFYI(1, "Send error in Query POSIX ACL = %d", rc);
3502 /* decode response */
3504 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3505 /* BB also check enough total bytes returned */
3506 if (rc || get_bcc(&pSMBr->hdr) < 2)
3507 rc = -EIO; /* bad smb */
3509 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3510 __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
3511 rc = cifs_copy_posix_acl(acl_inf,
3512 (char *)&pSMBr->hdr.Protocol+data_offset,
3513 buflen, acl_type, count);
3516 cifs_buf_release(pSMB);
3523 CIFSSMBSetPosixACL(const int xid, struct cifs_tcon *tcon,
3524 const unsigned char *fileName,
3525 const char *local_acl, const int buflen,
3527 const struct nls_table *nls_codepage, int remap)
3529 struct smb_com_transaction2_spi_req *pSMB = NULL;
3530 struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
3534 int bytes_returned = 0;
3535 __u16 params, byte_count, data_count, param_offset, offset;
3537 cFYI(1, "In SetPosixACL (Unix) for path %s", fileName);
3539 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3543 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3545 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
3546 PATH_MAX, nls_codepage, remap);
3547 name_len++; /* trailing null */
3549 } else { /* BB improve the check for buffer overruns BB */
3550 name_len = strnlen(fileName, PATH_MAX);
3551 name_len++; /* trailing null */
3552 strncpy(pSMB->FileName, fileName, name_len);
3554 params = 6 + name_len;
3555 pSMB->MaxParameterCount = cpu_to_le16(2);
3556 /* BB find max SMB size from sess */
3557 pSMB->MaxDataCount = cpu_to_le16(1000);
3558 pSMB->MaxSetupCount = 0;
3562 pSMB->Reserved2 = 0;
3563 param_offset = offsetof(struct smb_com_transaction2_spi_req,
3564 InformationLevel) - 4;
3565 offset = param_offset + params;
3566 parm_data = ((char *) &pSMB->hdr.Protocol) + offset;
3567 pSMB->ParameterOffset = cpu_to_le16(param_offset);
3569 /* convert to on the wire format for POSIX ACL */
3570 data_count = ACL_to_cifs_posix(parm_data, local_acl, buflen, acl_type);
3572 if (data_count == 0) {
3574 goto setACLerrorExit;
3576 pSMB->DataOffset = cpu_to_le16(offset);
3577 pSMB->SetupCount = 1;
3578 pSMB->Reserved3 = 0;
3579 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
3580 pSMB->InformationLevel = cpu_to_le16(SMB_SET_POSIX_ACL);
3581 byte_count = 3 /* pad */ + params + data_count;
3582 pSMB->DataCount = cpu_to_le16(data_count);
3583 pSMB->TotalDataCount = pSMB->DataCount;
3584 pSMB->ParameterCount = cpu_to_le16(params);
3585 pSMB->TotalParameterCount = pSMB->ParameterCount;
3586 pSMB->Reserved4 = 0;
3587 inc_rfc1001_len(pSMB, byte_count);
3588 pSMB->ByteCount = cpu_to_le16(byte_count);
3589 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3590 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3592 cFYI(1, "Set POSIX ACL returned %d", rc);
3595 cifs_buf_release(pSMB);
3601 /* BB fix tabs in this function FIXME BB */
3603 CIFSGetExtAttr(const int xid, struct cifs_tcon *tcon,
3604 const int netfid, __u64 *pExtAttrBits, __u64 *pMask)
3607 struct smb_t2_qfi_req *pSMB = NULL;
3608 struct smb_t2_qfi_rsp *pSMBr = NULL;
3610 __u16 params, byte_count;
3612 cFYI(1, "In GetExtAttr");
3617 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3622 params = 2 /* level */ + 2 /* fid */;
3623 pSMB->t2.TotalDataCount = 0;
3624 pSMB->t2.MaxParameterCount = cpu_to_le16(4);
3625 /* BB find exact max data count below from sess structure BB */
3626 pSMB->t2.MaxDataCount = cpu_to_le16(4000);
3627 pSMB->t2.MaxSetupCount = 0;
3628 pSMB->t2.Reserved = 0;
3630 pSMB->t2.Timeout = 0;
3631 pSMB->t2.Reserved2 = 0;
3632 pSMB->t2.ParameterOffset = cpu_to_le16(offsetof(struct smb_t2_qfi_req,
3634 pSMB->t2.DataCount = 0;
3635 pSMB->t2.DataOffset = 0;
3636 pSMB->t2.SetupCount = 1;
3637 pSMB->t2.Reserved3 = 0;
3638 pSMB->t2.SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION);
3639 byte_count = params + 1 /* pad */ ;
3640 pSMB->t2.TotalParameterCount = cpu_to_le16(params);
3641 pSMB->t2.ParameterCount = pSMB->t2.TotalParameterCount;
3642 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_ATTR_FLAGS);
3645 inc_rfc1001_len(pSMB, byte_count);
3646 pSMB->t2.ByteCount = cpu_to_le16(byte_count);
3648 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3649 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3651 cFYI(1, "error %d in GetExtAttr", rc);
3653 /* decode response */
3654 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3655 /* BB also check enough total bytes returned */
3656 if (rc || get_bcc(&pSMBr->hdr) < 2)
3657 /* If rc should we check for EOPNOSUPP and
3658 disable the srvino flag? or in caller? */
3659 rc = -EIO; /* bad smb */
3661 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3662 __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
3663 struct file_chattr_info *pfinfo;
3664 /* BB Do we need a cast or hash here ? */
3666 cFYI(1, "Illegal size ret in GetExtAttr");
3670 pfinfo = (struct file_chattr_info *)
3671 (data_offset + (char *) &pSMBr->hdr.Protocol);
3672 *pExtAttrBits = le64_to_cpu(pfinfo->mode);
3673 *pMask = le64_to_cpu(pfinfo->mask);
3677 cifs_buf_release(pSMB);
3679 goto GetExtAttrRetry;
3683 #endif /* CONFIG_POSIX */
3685 #ifdef CONFIG_CIFS_ACL
3687 * Initialize NT TRANSACT SMB into small smb request buffer. This assumes that
3688 * all NT TRANSACTS that we init here have total parm and data under about 400
3689 * bytes (to fit in small cifs buffer size), which is the case so far, it
3690 * easily fits. NB: Setup words themselves and ByteCount MaxSetupCount (size of
3691 * returned setup area) and MaxParameterCount (returned parms size) must be set
3695 smb_init_nttransact(const __u16 sub_command, const int setup_count,
3696 const int parm_len, struct cifs_tcon *tcon,
3701 struct smb_com_ntransact_req *pSMB;
3703 rc = small_smb_init(SMB_COM_NT_TRANSACT, 19 + setup_count, tcon,
3707 *ret_buf = (void *)pSMB;
3709 pSMB->TotalParameterCount = cpu_to_le32(parm_len);
3710 pSMB->TotalDataCount = 0;
3711 pSMB->MaxDataCount = cpu_to_le32(CIFSMaxBufSize & 0xFFFFFF00);
3712 pSMB->ParameterCount = pSMB->TotalParameterCount;
3713 pSMB->DataCount = pSMB->TotalDataCount;
3714 temp_offset = offsetof(struct smb_com_ntransact_req, Parms) +
3715 (setup_count * 2) - 4 /* for rfc1001 length itself */;
3716 pSMB->ParameterOffset = cpu_to_le32(temp_offset);
3717 pSMB->DataOffset = cpu_to_le32(temp_offset + parm_len);
3718 pSMB->SetupCount = setup_count; /* no need to le convert byte fields */
3719 pSMB->SubCommand = cpu_to_le16(sub_command);
3724 validate_ntransact(char *buf, char **ppparm, char **ppdata,
3725 __u32 *pparmlen, __u32 *pdatalen)
3728 __u32 data_count, data_offset, parm_count, parm_offset;
3729 struct smb_com_ntransact_rsp *pSMBr;
3738 pSMBr = (struct smb_com_ntransact_rsp *)buf;
3740 bcc = get_bcc(&pSMBr->hdr);
3741 end_of_smb = 2 /* sizeof byte count */ + bcc +
3742 (char *)&pSMBr->ByteCount;
3744 data_offset = le32_to_cpu(pSMBr->DataOffset);
3745 data_count = le32_to_cpu(pSMBr->DataCount);
3746 parm_offset = le32_to_cpu(pSMBr->ParameterOffset);
3747 parm_count = le32_to_cpu(pSMBr->ParameterCount);
3749 *ppparm = (char *)&pSMBr->hdr.Protocol + parm_offset;
3750 *ppdata = (char *)&pSMBr->hdr.Protocol + data_offset;
3752 /* should we also check that parm and data areas do not overlap? */
3753 if (*ppparm > end_of_smb) {
3754 cFYI(1, "parms start after end of smb");
3756 } else if (parm_count + *ppparm > end_of_smb) {
3757 cFYI(1, "parm end after end of smb");
3759 } else if (*ppdata > end_of_smb) {
3760 cFYI(1, "data starts after end of smb");
3762 } else if (data_count + *ppdata > end_of_smb) {
3763 cFYI(1, "data %p + count %d (%p) past smb end %p start %p",
3764 *ppdata, data_count, (data_count + *ppdata),
3767 } else if (parm_count + data_count > bcc) {
3768 cFYI(1, "parm count and data count larger than SMB");
3771 *pdatalen = data_count;
3772 *pparmlen = parm_count;
3776 /* Get Security Descriptor (by handle) from remote server for a file or dir */
3778 CIFSSMBGetCIFSACL(const int xid, struct cifs_tcon *tcon, __u16 fid,
3779 struct cifs_ntsd **acl_inf, __u32 *pbuflen)
3783 QUERY_SEC_DESC_REQ *pSMB;
3786 cFYI(1, "GetCifsACL");
3791 rc = smb_init_nttransact(NT_TRANSACT_QUERY_SECURITY_DESC, 0,
3792 8 /* parm len */, tcon, (void **) &pSMB);
3796 pSMB->MaxParameterCount = cpu_to_le32(4);
3797 /* BB TEST with big acls that might need to be e.g. larger than 16K */
3798 pSMB->MaxSetupCount = 0;
3799 pSMB->Fid = fid; /* file handle always le */
3800 pSMB->AclFlags = cpu_to_le32(CIFS_ACL_OWNER | CIFS_ACL_GROUP |
3802 pSMB->ByteCount = cpu_to_le16(11); /* 3 bytes pad + 8 bytes parm */
3803 inc_rfc1001_len(pSMB, 11);
3804 iov[0].iov_base = (char *)pSMB;
3805 iov[0].iov_len = be32_to_cpu(pSMB->hdr.smb_buf_length) + 4;
3807 rc = SendReceive2(xid, tcon->ses, iov, 1 /* num iovec */, &buf_type,
3809 cifs_stats_inc(&tcon->num_acl_get);
3811 cFYI(1, "Send error in QuerySecDesc = %d", rc);
3812 } else { /* decode response */
3816 struct smb_com_ntransact_rsp *pSMBr;
3819 /* validate_nttransact */
3820 rc = validate_ntransact(iov[0].iov_base, (char **)&parm,
3821 &pdata, &parm_len, pbuflen);
3824 pSMBr = (struct smb_com_ntransact_rsp *)iov[0].iov_base;
3826 cFYI(1, "smb %p parm %p data %p", pSMBr, parm, *acl_inf);
3828 if (le32_to_cpu(pSMBr->ParameterCount) != 4) {
3829 rc = -EIO; /* bad smb */
3834 /* BB check that data area is minimum length and as big as acl_len */
3836 acl_len = le32_to_cpu(*parm);
3837 if (acl_len != *pbuflen) {
3838 cERROR(1, "acl length %d does not match %d",
3840 if (*pbuflen > acl_len)
3844 /* check if buffer is big enough for the acl
3845 header followed by the smallest SID */
3846 if ((*pbuflen < sizeof(struct cifs_ntsd) + 8) ||
3847 (*pbuflen >= 64 * 1024)) {
3848 cERROR(1, "bad acl length %d", *pbuflen);
3852 *acl_inf = kmalloc(*pbuflen, GFP_KERNEL);
3853 if (*acl_inf == NULL) {
3857 memcpy(*acl_inf, pdata, *pbuflen);
3861 if (buf_type == CIFS_SMALL_BUFFER)
3862 cifs_small_buf_release(iov[0].iov_base);
3863 else if (buf_type == CIFS_LARGE_BUFFER)
3864 cifs_buf_release(iov[0].iov_base);
3865 /* cifs_small_buf_release(pSMB); */ /* Freed earlier now in SendReceive2 */
3870 CIFSSMBSetCIFSACL(const int xid, struct cifs_tcon *tcon, __u16 fid,
3871 struct cifs_ntsd *pntsd, __u32 acllen, int aclflag)
3873 __u16 byte_count, param_count, data_count, param_offset, data_offset;
3875 int bytes_returned = 0;
3876 SET_SEC_DESC_REQ *pSMB = NULL;
3877 NTRANSACT_RSP *pSMBr = NULL;
3880 rc = smb_init(SMB_COM_NT_TRANSACT, 19, tcon, (void **) &pSMB,
3885 pSMB->MaxSetupCount = 0;
3889 param_offset = offsetof(struct smb_com_transaction_ssec_req, Fid) - 4;
3890 data_count = acllen;
3891 data_offset = param_offset + param_count;
3892 byte_count = 3 /* pad */ + param_count;
3894 pSMB->DataCount = cpu_to_le32(data_count);
3895 pSMB->TotalDataCount = pSMB->DataCount;
3896 pSMB->MaxParameterCount = cpu_to_le32(4);
3897 pSMB->MaxDataCount = cpu_to_le32(16384);
3898 pSMB->ParameterCount = cpu_to_le32(param_count);
3899 pSMB->ParameterOffset = cpu_to_le32(param_offset);
3900 pSMB->TotalParameterCount = pSMB->ParameterCount;
3901 pSMB->DataOffset = cpu_to_le32(data_offset);
3902 pSMB->SetupCount = 0;
3903 pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_SET_SECURITY_DESC);
3904 pSMB->ByteCount = cpu_to_le16(byte_count+data_count);
3906 pSMB->Fid = fid; /* file handle always le */
3907 pSMB->Reserved2 = 0;
3908 pSMB->AclFlags = cpu_to_le32(aclflag);
3910 if (pntsd && acllen) {
3911 memcpy((char *) &pSMBr->hdr.Protocol + data_offset,
3914 inc_rfc1001_len(pSMB, byte_count + data_count);
3916 inc_rfc1001_len(pSMB, byte_count);
3918 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3919 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3921 cFYI(1, "SetCIFSACL bytes_returned: %d, rc: %d", bytes_returned, rc);
3923 cFYI(1, "Set CIFS ACL returned %d", rc);
3924 cifs_buf_release(pSMB);
3927 goto setCifsAclRetry;
3932 #endif /* CONFIG_CIFS_ACL */
3934 /* Legacy Query Path Information call for lookup to old servers such
3936 int SMBQueryInformation(const int xid, struct cifs_tcon *tcon,
3937 const unsigned char *searchName,
3938 FILE_ALL_INFO *pFinfo,
3939 const struct nls_table *nls_codepage, int remap)
3941 QUERY_INFORMATION_REQ *pSMB;
3942 QUERY_INFORMATION_RSP *pSMBr;
3947 cFYI(1, "In SMBQPath path %s", searchName);
3949 rc = smb_init(SMB_COM_QUERY_INFORMATION, 0, tcon, (void **) &pSMB,
3954 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3956 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
3957 PATH_MAX, nls_codepage, remap);
3958 name_len++; /* trailing null */
3961 name_len = strnlen(searchName, PATH_MAX);
3962 name_len++; /* trailing null */
3963 strncpy(pSMB->FileName, searchName, name_len);
3965 pSMB->BufferFormat = 0x04;
3966 name_len++; /* account for buffer type byte */
3967 inc_rfc1001_len(pSMB, (__u16)name_len);
3968 pSMB->ByteCount = cpu_to_le16(name_len);
3970 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3971 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3973 cFYI(1, "Send error in QueryInfo = %d", rc);
3974 } else if (pFinfo) {
3976 __u32 time = le32_to_cpu(pSMBr->last_write_time);
3978 /* decode response */
3979 /* BB FIXME - add time zone adjustment BB */
3980 memset(pFinfo, 0, sizeof(FILE_ALL_INFO));
3983 /* decode time fields */
3984 pFinfo->ChangeTime = cpu_to_le64(cifs_UnixTimeToNT(ts));
3985 pFinfo->LastWriteTime = pFinfo->ChangeTime;
3986 pFinfo->LastAccessTime = 0;
3987 pFinfo->AllocationSize =
3988 cpu_to_le64(le32_to_cpu(pSMBr->size));
3989 pFinfo->EndOfFile = pFinfo->AllocationSize;
3990 pFinfo->Attributes =
3991 cpu_to_le32(le16_to_cpu(pSMBr->attr));
3993 rc = -EIO; /* bad buffer passed in */
3995 cifs_buf_release(pSMB);
4004 CIFSSMBQFileInfo(const int xid, struct cifs_tcon *tcon,
4005 u16 netfid, FILE_ALL_INFO *pFindData)
4007 struct smb_t2_qfi_req *pSMB = NULL;
4008 struct smb_t2_qfi_rsp *pSMBr = NULL;
4011 __u16 params, byte_count;
4014 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4019 params = 2 /* level */ + 2 /* fid */;
4020 pSMB->t2.TotalDataCount = 0;
4021 pSMB->t2.MaxParameterCount = cpu_to_le16(4);
4022 /* BB find exact max data count below from sess structure BB */
4023 pSMB->t2.MaxDataCount = cpu_to_le16(CIFSMaxBufSize);
4024 pSMB->t2.MaxSetupCount = 0;
4025 pSMB->t2.Reserved = 0;
4027 pSMB->t2.Timeout = 0;
4028 pSMB->t2.Reserved2 = 0;
4029 pSMB->t2.ParameterOffset = cpu_to_le16(offsetof(struct smb_t2_qfi_req,
4031 pSMB->t2.DataCount = 0;
4032 pSMB->t2.DataOffset = 0;
4033 pSMB->t2.SetupCount = 1;
4034 pSMB->t2.Reserved3 = 0;
4035 pSMB->t2.SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION);
4036 byte_count = params + 1 /* pad */ ;
4037 pSMB->t2.TotalParameterCount = cpu_to_le16(params);
4038 pSMB->t2.ParameterCount = pSMB->t2.TotalParameterCount;
4039 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_ALL_INFO);
4042 inc_rfc1001_len(pSMB, byte_count);
4044 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4045 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4047 cFYI(1, "Send error in QPathInfo = %d", rc);
4048 } else { /* decode response */
4049 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4051 if (rc) /* BB add auto retry on EOPNOTSUPP? */
4053 else if (get_bcc(&pSMBr->hdr) < 40)
4054 rc = -EIO; /* bad smb */
4055 else if (pFindData) {
4056 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4057 memcpy((char *) pFindData,
4058 (char *) &pSMBr->hdr.Protocol +
4059 data_offset, sizeof(FILE_ALL_INFO));
4063 cifs_buf_release(pSMB);
4065 goto QFileInfoRetry;
4071 CIFSSMBQPathInfo(const int xid, struct cifs_tcon *tcon,
4072 const unsigned char *searchName,
4073 FILE_ALL_INFO *pFindData,
4074 int legacy /* old style infolevel */,
4075 const struct nls_table *nls_codepage, int remap)
4077 /* level 263 SMB_QUERY_FILE_ALL_INFO */
4078 TRANSACTION2_QPI_REQ *pSMB = NULL;
4079 TRANSACTION2_QPI_RSP *pSMBr = NULL;
4083 __u16 params, byte_count;
4085 /* cFYI(1, "In QPathInfo path %s", searchName); */
4087 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4092 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4094 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
4095 PATH_MAX, nls_codepage, remap);
4096 name_len++; /* trailing null */
4098 } else { /* BB improve the check for buffer overruns BB */
4099 name_len = strnlen(searchName, PATH_MAX);
4100 name_len++; /* trailing null */
4101 strncpy(pSMB->FileName, searchName, name_len);
4104 params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */;
4105 pSMB->TotalDataCount = 0;
4106 pSMB->MaxParameterCount = cpu_to_le16(2);
4107 /* BB find exact max SMB PDU from sess structure BB */
4108 pSMB->MaxDataCount = cpu_to_le16(4000);
4109 pSMB->MaxSetupCount = 0;
4113 pSMB->Reserved2 = 0;
4114 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4115 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
4116 pSMB->DataCount = 0;
4117 pSMB->DataOffset = 0;
4118 pSMB->SetupCount = 1;
4119 pSMB->Reserved3 = 0;
4120 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
4121 byte_count = params + 1 /* pad */ ;
4122 pSMB->TotalParameterCount = cpu_to_le16(params);
4123 pSMB->ParameterCount = pSMB->TotalParameterCount;
4125 pSMB->InformationLevel = cpu_to_le16(SMB_INFO_STANDARD);
4127 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_ALL_INFO);
4128 pSMB->Reserved4 = 0;
4129 inc_rfc1001_len(pSMB, byte_count);
4130 pSMB->ByteCount = cpu_to_le16(byte_count);
4132 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4133 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4135 cFYI(1, "Send error in QPathInfo = %d", rc);
4136 } else { /* decode response */
4137 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4139 if (rc) /* BB add auto retry on EOPNOTSUPP? */
4141 else if (!legacy && get_bcc(&pSMBr->hdr) < 40)
4142 rc = -EIO; /* bad smb */
4143 else if (legacy && get_bcc(&pSMBr->hdr) < 24)
4144 rc = -EIO; /* 24 or 26 expected but we do not read
4146 else if (pFindData) {
4148 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4150 /* On legacy responses we do not read the last field,
4151 EAsize, fortunately since it varies by subdialect and
4152 also note it differs on Set vs. Get, ie two bytes or 4
4153 bytes depending but we don't care here */
4155 size = sizeof(FILE_INFO_STANDARD);
4157 size = sizeof(FILE_ALL_INFO);
4158 memcpy((char *) pFindData,
4159 (char *) &pSMBr->hdr.Protocol +
4164 cifs_buf_release(pSMB);
4166 goto QPathInfoRetry;
4172 CIFSSMBUnixQFileInfo(const int xid, struct cifs_tcon *tcon,
4173 u16 netfid, FILE_UNIX_BASIC_INFO *pFindData)
4175 struct smb_t2_qfi_req *pSMB = NULL;
4176 struct smb_t2_qfi_rsp *pSMBr = NULL;
4179 __u16 params, byte_count;
4182 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4187 params = 2 /* level */ + 2 /* fid */;
4188 pSMB->t2.TotalDataCount = 0;
4189 pSMB->t2.MaxParameterCount = cpu_to_le16(4);
4190 /* BB find exact max data count below from sess structure BB */
4191 pSMB->t2.MaxDataCount = cpu_to_le16(CIFSMaxBufSize);
4192 pSMB->t2.MaxSetupCount = 0;
4193 pSMB->t2.Reserved = 0;
4195 pSMB->t2.Timeout = 0;
4196 pSMB->t2.Reserved2 = 0;
4197 pSMB->t2.ParameterOffset = cpu_to_le16(offsetof(struct smb_t2_qfi_req,
4199 pSMB->t2.DataCount = 0;
4200 pSMB->t2.DataOffset = 0;
4201 pSMB->t2.SetupCount = 1;
4202 pSMB->t2.Reserved3 = 0;
4203 pSMB->t2.SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION);
4204 byte_count = params + 1 /* pad */ ;
4205 pSMB->t2.TotalParameterCount = cpu_to_le16(params);
4206 pSMB->t2.ParameterCount = pSMB->t2.TotalParameterCount;
4207 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC);
4210 inc_rfc1001_len(pSMB, byte_count);
4212 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4213 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4215 cFYI(1, "Send error in QPathInfo = %d", rc);
4216 } else { /* decode response */
4217 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4219 if (rc || get_bcc(&pSMBr->hdr) < sizeof(FILE_UNIX_BASIC_INFO)) {
4220 cERROR(1, "Malformed FILE_UNIX_BASIC_INFO response.\n"
4221 "Unix Extensions can be disabled on mount "
4222 "by specifying the nosfu mount option.");
4223 rc = -EIO; /* bad smb */
4225 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4226 memcpy((char *) pFindData,
4227 (char *) &pSMBr->hdr.Protocol +
4229 sizeof(FILE_UNIX_BASIC_INFO));
4233 cifs_buf_release(pSMB);
4235 goto UnixQFileInfoRetry;
4241 CIFSSMBUnixQPathInfo(const int xid, struct cifs_tcon *tcon,
4242 const unsigned char *searchName,
4243 FILE_UNIX_BASIC_INFO *pFindData,
4244 const struct nls_table *nls_codepage, int remap)
4246 /* SMB_QUERY_FILE_UNIX_BASIC */
4247 TRANSACTION2_QPI_REQ *pSMB = NULL;
4248 TRANSACTION2_QPI_RSP *pSMBr = NULL;
4250 int bytes_returned = 0;
4252 __u16 params, byte_count;
4254 cFYI(1, "In QPathInfo (Unix) the path %s", searchName);
4256 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4261 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4263 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
4264 PATH_MAX, nls_codepage, remap);
4265 name_len++; /* trailing null */
4267 } else { /* BB improve the check for buffer overruns BB */
4268 name_len = strnlen(searchName, PATH_MAX);
4269 name_len++; /* trailing null */
4270 strncpy(pSMB->FileName, searchName, name_len);
4273 params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */;
4274 pSMB->TotalDataCount = 0;
4275 pSMB->MaxParameterCount = cpu_to_le16(2);
4276 /* BB find exact max SMB PDU from sess structure BB */
4277 pSMB->MaxDataCount = cpu_to_le16(4000);
4278 pSMB->MaxSetupCount = 0;
4282 pSMB->Reserved2 = 0;
4283 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4284 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
4285 pSMB->DataCount = 0;
4286 pSMB->DataOffset = 0;
4287 pSMB->SetupCount = 1;
4288 pSMB->Reserved3 = 0;
4289 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
4290 byte_count = params + 1 /* pad */ ;
4291 pSMB->TotalParameterCount = cpu_to_le16(params);
4292 pSMB->ParameterCount = pSMB->TotalParameterCount;
4293 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC);
4294 pSMB->Reserved4 = 0;
4295 inc_rfc1001_len(pSMB, byte_count);
4296 pSMB->ByteCount = cpu_to_le16(byte_count);
4298 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4299 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4301 cFYI(1, "Send error in QPathInfo = %d", rc);
4302 } else { /* decode response */
4303 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4305 if (rc || get_bcc(&pSMBr->hdr) < sizeof(FILE_UNIX_BASIC_INFO)) {
4306 cERROR(1, "Malformed FILE_UNIX_BASIC_INFO response.\n"
4307 "Unix Extensions can be disabled on mount "
4308 "by specifying the nosfu mount option.");
4309 rc = -EIO; /* bad smb */
4311 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4312 memcpy((char *) pFindData,
4313 (char *) &pSMBr->hdr.Protocol +
4315 sizeof(FILE_UNIX_BASIC_INFO));
4318 cifs_buf_release(pSMB);
4320 goto UnixQPathInfoRetry;
4325 /* xid, tcon, searchName and codepage are input parms, rest are returned */
4327 CIFSFindFirst(const int xid, struct cifs_tcon *tcon,
4328 const char *searchName,
4329 const struct nls_table *nls_codepage,
4331 struct cifs_search_info *psrch_inf, int remap, const char dirsep)
4333 /* level 257 SMB_ */
4334 TRANSACTION2_FFIRST_REQ *pSMB = NULL;
4335 TRANSACTION2_FFIRST_RSP *pSMBr = NULL;
4336 T2_FFIRST_RSP_PARMS *parms;
4338 int bytes_returned = 0;
4340 __u16 params, byte_count;
4342 cFYI(1, "In FindFirst for %s", searchName);
4345 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4350 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4352 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
4353 PATH_MAX, nls_codepage, remap);
4354 /* We can not add the asterik earlier in case
4355 it got remapped to 0xF03A as if it were part of the
4356 directory name instead of a wildcard */
4358 pSMB->FileName[name_len] = dirsep;
4359 pSMB->FileName[name_len+1] = 0;
4360 pSMB->FileName[name_len+2] = '*';
4361 pSMB->FileName[name_len+3] = 0;
4362 name_len += 4; /* now the trailing null */
4363 pSMB->FileName[name_len] = 0; /* null terminate just in case */
4364 pSMB->FileName[name_len+1] = 0;
4366 } else { /* BB add check for overrun of SMB buf BB */
4367 name_len = strnlen(searchName, PATH_MAX);
4368 /* BB fix here and in unicode clause above ie
4369 if (name_len > buffersize-header)
4370 free buffer exit; BB */
4371 strncpy(pSMB->FileName, searchName, name_len);
4372 pSMB->FileName[name_len] = dirsep;
4373 pSMB->FileName[name_len+1] = '*';
4374 pSMB->FileName[name_len+2] = 0;
4378 params = 12 + name_len /* includes null */ ;
4379 pSMB->TotalDataCount = 0; /* no EAs */
4380 pSMB->MaxParameterCount = cpu_to_le16(10);
4381 pSMB->MaxDataCount = cpu_to_le16(CIFSMaxBufSize & 0xFFFFFF00);
4382 pSMB->MaxSetupCount = 0;
4386 pSMB->Reserved2 = 0;
4387 byte_count = params + 1 /* pad */ ;
4388 pSMB->TotalParameterCount = cpu_to_le16(params);
4389 pSMB->ParameterCount = pSMB->TotalParameterCount;
4390 pSMB->ParameterOffset = cpu_to_le16(
4391 offsetof(struct smb_com_transaction2_ffirst_req, SearchAttributes)
4393 pSMB->DataCount = 0;
4394 pSMB->DataOffset = 0;
4395 pSMB->SetupCount = 1; /* one byte, no need to make endian neutral */
4396 pSMB->Reserved3 = 0;
4397 pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_FIRST);
4398 pSMB->SearchAttributes =
4399 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
4401 pSMB->SearchCount = cpu_to_le16(CIFSMaxBufSize/sizeof(FILE_UNIX_INFO));
4402 pSMB->SearchFlags = cpu_to_le16(CIFS_SEARCH_CLOSE_AT_END |
4403 CIFS_SEARCH_RETURN_RESUME);
4404 pSMB->InformationLevel = cpu_to_le16(psrch_inf->info_level);
4406 /* BB what should we set StorageType to? Does it matter? BB */
4407 pSMB->SearchStorageType = 0;
4408 inc_rfc1001_len(pSMB, byte_count);
4409 pSMB->ByteCount = cpu_to_le16(byte_count);
4411 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4412 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4413 cifs_stats_inc(&tcon->num_ffirst);
4415 if (rc) {/* BB add logic to retry regular search if Unix search
4416 rejected unexpectedly by server */
4417 /* BB Add code to handle unsupported level rc */
4418 cFYI(1, "Error in FindFirst = %d", rc);
4420 cifs_buf_release(pSMB);
4422 /* BB eventually could optimize out free and realloc of buf */
4425 goto findFirstRetry;
4426 } else { /* decode response */
4427 /* BB remember to free buffer if error BB */
4428 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4432 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
4433 psrch_inf->unicode = true;
4435 psrch_inf->unicode = false;
4437 psrch_inf->ntwrk_buf_start = (char *)pSMBr;
4438 psrch_inf->smallBuf = 0;
4439 psrch_inf->srch_entries_start =
4440 (char *) &pSMBr->hdr.Protocol +
4441 le16_to_cpu(pSMBr->t2.DataOffset);
4442 parms = (T2_FFIRST_RSP_PARMS *)((char *) &pSMBr->hdr.Protocol +
4443 le16_to_cpu(pSMBr->t2.ParameterOffset));
4445 if (parms->EndofSearch)
4446 psrch_inf->endOfSearch = true;
4448 psrch_inf->endOfSearch = false;
4450 psrch_inf->entries_in_buffer =
4451 le16_to_cpu(parms->SearchCount);
4452 psrch_inf->index_of_last_entry = 2 /* skip . and .. */ +
4453 psrch_inf->entries_in_buffer;
4454 lnoff = le16_to_cpu(parms->LastNameOffset);
4455 if (CIFSMaxBufSize < lnoff) {
4456 cERROR(1, "ignoring corrupt resume name");
4457 psrch_inf->last_entry = NULL;
4461 psrch_inf->last_entry = psrch_inf->srch_entries_start +
4464 *pnetfid = parms->SearchHandle;
4466 cifs_buf_release(pSMB);
4473 int CIFSFindNext(const int xid, struct cifs_tcon *tcon,
4474 __u16 searchHandle, struct cifs_search_info *psrch_inf)
4476 TRANSACTION2_FNEXT_REQ *pSMB = NULL;
4477 TRANSACTION2_FNEXT_RSP *pSMBr = NULL;
4478 T2_FNEXT_RSP_PARMS *parms;
4479 char *response_data;
4482 unsigned int name_len;
4483 __u16 params, byte_count;
4485 cFYI(1, "In FindNext");
4487 if (psrch_inf->endOfSearch)
4490 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4495 params = 14; /* includes 2 bytes of null string, converted to LE below*/
4497 pSMB->TotalDataCount = 0; /* no EAs */
4498 pSMB->MaxParameterCount = cpu_to_le16(8);
4499 pSMB->MaxDataCount = cpu_to_le16(CIFSMaxBufSize & 0xFFFFFF00);
4500 pSMB->MaxSetupCount = 0;
4504 pSMB->Reserved2 = 0;
4505 pSMB->ParameterOffset = cpu_to_le16(
4506 offsetof(struct smb_com_transaction2_fnext_req,SearchHandle) - 4);
4507 pSMB->DataCount = 0;
4508 pSMB->DataOffset = 0;
4509 pSMB->SetupCount = 1;
4510 pSMB->Reserved3 = 0;
4511 pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_NEXT);
4512 pSMB->SearchHandle = searchHandle; /* always kept as le */
4514 cpu_to_le16(CIFSMaxBufSize / sizeof(FILE_UNIX_INFO));
4515 pSMB->InformationLevel = cpu_to_le16(psrch_inf->info_level);
4516 pSMB->ResumeKey = psrch_inf->resume_key;
4518 cpu_to_le16(CIFS_SEARCH_CLOSE_AT_END | CIFS_SEARCH_RETURN_RESUME);
4520 name_len = psrch_inf->resume_name_len;
4522 if (name_len < PATH_MAX) {
4523 memcpy(pSMB->ResumeFileName, psrch_inf->presume_name, name_len);
4524 byte_count += name_len;
4525 /* 14 byte parm len above enough for 2 byte null terminator */
4526 pSMB->ResumeFileName[name_len] = 0;
4527 pSMB->ResumeFileName[name_len+1] = 0;
4530 goto FNext2_err_exit;
4532 byte_count = params + 1 /* pad */ ;
4533 pSMB->TotalParameterCount = cpu_to_le16(params);
4534 pSMB->ParameterCount = pSMB->TotalParameterCount;
4535 inc_rfc1001_len(pSMB, byte_count);
4536 pSMB->ByteCount = cpu_to_le16(byte_count);
4538 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4539 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4540 cifs_stats_inc(&tcon->num_fnext);
4543 psrch_inf->endOfSearch = true;
4544 cifs_buf_release(pSMB);
4545 rc = 0; /* search probably was closed at end of search*/
4547 cFYI(1, "FindNext returned = %d", rc);
4548 } else { /* decode response */
4549 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4554 /* BB fixme add lock for file (srch_info) struct here */
4555 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
4556 psrch_inf->unicode = true;
4558 psrch_inf->unicode = false;
4559 response_data = (char *) &pSMBr->hdr.Protocol +
4560 le16_to_cpu(pSMBr->t2.ParameterOffset);
4561 parms = (T2_FNEXT_RSP_PARMS *)response_data;
4562 response_data = (char *)&pSMBr->hdr.Protocol +
4563 le16_to_cpu(pSMBr->t2.DataOffset);
4564 if (psrch_inf->smallBuf)
4565 cifs_small_buf_release(
4566 psrch_inf->ntwrk_buf_start);
4568 cifs_buf_release(psrch_inf->ntwrk_buf_start);
4569 psrch_inf->srch_entries_start = response_data;
4570 psrch_inf->ntwrk_buf_start = (char *)pSMB;
4571 psrch_inf->smallBuf = 0;
4572 if (parms->EndofSearch)
4573 psrch_inf->endOfSearch = true;
4575 psrch_inf->endOfSearch = false;
4576 psrch_inf->entries_in_buffer =
4577 le16_to_cpu(parms->SearchCount);
4578 psrch_inf->index_of_last_entry +=
4579 psrch_inf->entries_in_buffer;
4580 lnoff = le16_to_cpu(parms->LastNameOffset);
4581 if (CIFSMaxBufSize < lnoff) {
4582 cERROR(1, "ignoring corrupt resume name");
4583 psrch_inf->last_entry = NULL;
4586 psrch_inf->last_entry =
4587 psrch_inf->srch_entries_start + lnoff;
4589 /* cFYI(1, "fnxt2 entries in buf %d index_of_last %d",
4590 psrch_inf->entries_in_buffer, psrch_inf->index_of_last_entry); */
4592 /* BB fixme add unlock here */
4597 /* BB On error, should we leave previous search buf (and count and
4598 last entry fields) intact or free the previous one? */
4600 /* Note: On -EAGAIN error only caller can retry on handle based calls
4601 since file handle passed in no longer valid */
4604 cifs_buf_release(pSMB);
4609 CIFSFindClose(const int xid, struct cifs_tcon *tcon,
4610 const __u16 searchHandle)
4613 FINDCLOSE_REQ *pSMB = NULL;
4615 cFYI(1, "In CIFSSMBFindClose");
4616 rc = small_smb_init(SMB_COM_FIND_CLOSE2, 1, tcon, (void **)&pSMB);
4618 /* no sense returning error if session restarted
4619 as file handle has been closed */
4625 pSMB->FileID = searchHandle;
4626 pSMB->ByteCount = 0;
4627 rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0);
4629 cERROR(1, "Send error in FindClose = %d", rc);
4631 cifs_stats_inc(&tcon->num_fclose);
4633 /* Since session is dead, search handle closed on server already */
4641 CIFSGetSrvInodeNumber(const int xid, struct cifs_tcon *tcon,
4642 const unsigned char *searchName,
4643 __u64 *inode_number,
4644 const struct nls_table *nls_codepage, int remap)
4647 TRANSACTION2_QPI_REQ *pSMB = NULL;
4648 TRANSACTION2_QPI_RSP *pSMBr = NULL;
4649 int name_len, bytes_returned;
4650 __u16 params, byte_count;
4652 cFYI(1, "In GetSrvInodeNum for %s", searchName);
4656 GetInodeNumberRetry:
4657 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4662 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4664 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
4665 PATH_MAX, nls_codepage, remap);
4666 name_len++; /* trailing null */
4668 } else { /* BB improve the check for buffer overruns BB */
4669 name_len = strnlen(searchName, PATH_MAX);
4670 name_len++; /* trailing null */
4671 strncpy(pSMB->FileName, searchName, name_len);
4674 params = 2 /* level */ + 4 /* rsrvd */ + name_len /* incl null */ ;
4675 pSMB->TotalDataCount = 0;
4676 pSMB->MaxParameterCount = cpu_to_le16(2);
4677 /* BB find exact max data count below from sess structure BB */
4678 pSMB->MaxDataCount = cpu_to_le16(4000);
4679 pSMB->MaxSetupCount = 0;
4683 pSMB->Reserved2 = 0;
4684 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4685 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
4686 pSMB->DataCount = 0;
4687 pSMB->DataOffset = 0;
4688 pSMB->SetupCount = 1;
4689 pSMB->Reserved3 = 0;
4690 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
4691 byte_count = params + 1 /* pad */ ;
4692 pSMB->TotalParameterCount = cpu_to_le16(params);
4693 pSMB->ParameterCount = pSMB->TotalParameterCount;
4694 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_INTERNAL_INFO);
4695 pSMB->Reserved4 = 0;
4696 inc_rfc1001_len(pSMB, byte_count);
4697 pSMB->ByteCount = cpu_to_le16(byte_count);
4699 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4700 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4702 cFYI(1, "error %d in QueryInternalInfo", rc);
4704 /* decode response */
4705 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4706 /* BB also check enough total bytes returned */
4707 if (rc || get_bcc(&pSMBr->hdr) < 2)
4708 /* If rc should we check for EOPNOSUPP and
4709 disable the srvino flag? or in caller? */
4710 rc = -EIO; /* bad smb */
4712 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4713 __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
4714 struct file_internal_info *pfinfo;
4715 /* BB Do we need a cast or hash here ? */
4717 cFYI(1, "Illegal size ret in QryIntrnlInf");
4719 goto GetInodeNumOut;
4721 pfinfo = (struct file_internal_info *)
4722 (data_offset + (char *) &pSMBr->hdr.Protocol);
4723 *inode_number = le64_to_cpu(pfinfo->UniqueId);
4727 cifs_buf_release(pSMB);
4729 goto GetInodeNumberRetry;
4733 /* parses DFS refferal V3 structure
4734 * caller is responsible for freeing target_nodes
4737 * on failure - errno
4740 parse_DFS_referrals(TRANSACTION2_GET_DFS_REFER_RSP *pSMBr,
4741 unsigned int *num_of_nodes,
4742 struct dfs_info3_param **target_nodes,
4743 const struct nls_table *nls_codepage, int remap,
4744 const char *searchName)
4749 struct dfs_referral_level_3 *ref;
4751 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
4755 *num_of_nodes = le16_to_cpu(pSMBr->NumberOfReferrals);
4757 if (*num_of_nodes < 1) {
4758 cERROR(1, "num_referrals: must be at least > 0,"
4759 "but we get num_referrals = %d\n", *num_of_nodes);
4761 goto parse_DFS_referrals_exit;
4764 ref = (struct dfs_referral_level_3 *) &(pSMBr->referrals);
4765 if (ref->VersionNumber != cpu_to_le16(3)) {
4766 cERROR(1, "Referrals of V%d version are not supported,"
4767 "should be V3", le16_to_cpu(ref->VersionNumber));
4769 goto parse_DFS_referrals_exit;
4772 /* get the upper boundary of the resp buffer */
4773 data_end = (char *)(&(pSMBr->PathConsumed)) +
4774 le16_to_cpu(pSMBr->t2.DataCount);
4776 cFYI(1, "num_referrals: %d dfs flags: 0x%x ...\n",
4778 le32_to_cpu(pSMBr->DFSFlags));
4780 *target_nodes = kzalloc(sizeof(struct dfs_info3_param) *
4781 *num_of_nodes, GFP_KERNEL);
4782 if (*target_nodes == NULL) {
4783 cERROR(1, "Failed to allocate buffer for target_nodes\n");
4785 goto parse_DFS_referrals_exit;
4788 /* collect necessary data from referrals */
4789 for (i = 0; i < *num_of_nodes; i++) {
4792 struct dfs_info3_param *node = (*target_nodes)+i;
4794 node->flags = le32_to_cpu(pSMBr->DFSFlags);
4796 __le16 *tmp = kmalloc(strlen(searchName)*2 + 2,
4800 goto parse_DFS_referrals_exit;
4802 cifsConvertToUCS((__le16 *) tmp, searchName,
4803 PATH_MAX, nls_codepage, remap);
4804 node->path_consumed = cifs_ucs2_bytes(tmp,
4805 le16_to_cpu(pSMBr->PathConsumed),
4809 node->path_consumed = le16_to_cpu(pSMBr->PathConsumed);
4811 node->server_type = le16_to_cpu(ref->ServerType);
4812 node->ref_flag = le16_to_cpu(ref->ReferralEntryFlags);
4815 temp = (char *)ref + le16_to_cpu(ref->DfsPathOffset);
4816 max_len = data_end - temp;
4817 node->path_name = cifs_strndup_from_ucs(temp, max_len,
4818 is_unicode, nls_codepage);
4819 if (!node->path_name) {
4821 goto parse_DFS_referrals_exit;
4824 /* copy link target UNC */
4825 temp = (char *)ref + le16_to_cpu(ref->NetworkAddressOffset);
4826 max_len = data_end - temp;
4827 node->node_name = cifs_strndup_from_ucs(temp, max_len,
4828 is_unicode, nls_codepage);
4829 if (!node->node_name) {
4831 goto parse_DFS_referrals_exit;
4837 parse_DFS_referrals_exit:
4839 free_dfs_info_array(*target_nodes, *num_of_nodes);
4840 *target_nodes = NULL;
4847 CIFSGetDFSRefer(const int xid, struct cifs_ses *ses,
4848 const unsigned char *searchName,
4849 struct dfs_info3_param **target_nodes,
4850 unsigned int *num_of_nodes,
4851 const struct nls_table *nls_codepage, int remap)
4853 /* TRANS2_GET_DFS_REFERRAL */
4854 TRANSACTION2_GET_DFS_REFER_REQ *pSMB = NULL;
4855 TRANSACTION2_GET_DFS_REFER_RSP *pSMBr = NULL;
4859 __u16 params, byte_count;
4861 *target_nodes = NULL;
4863 cFYI(1, "In GetDFSRefer the path %s", searchName);
4867 rc = smb_init(SMB_COM_TRANSACTION2, 15, NULL, (void **) &pSMB,
4872 /* server pointer checked in called function,
4873 but should never be null here anyway */
4874 pSMB->hdr.Mid = GetNextMid(ses->server);
4875 pSMB->hdr.Tid = ses->ipc_tid;
4876 pSMB->hdr.Uid = ses->Suid;
4877 if (ses->capabilities & CAP_STATUS32)
4878 pSMB->hdr.Flags2 |= SMBFLG2_ERR_STATUS;
4879 if (ses->capabilities & CAP_DFS)
4880 pSMB->hdr.Flags2 |= SMBFLG2_DFS;
4882 if (ses->capabilities & CAP_UNICODE) {
4883 pSMB->hdr.Flags2 |= SMBFLG2_UNICODE;
4885 cifsConvertToUCS((__le16 *) pSMB->RequestFileName,
4886 searchName, PATH_MAX, nls_codepage, remap);
4887 name_len++; /* trailing null */
4889 } else { /* BB improve the check for buffer overruns BB */
4890 name_len = strnlen(searchName, PATH_MAX);
4891 name_len++; /* trailing null */
4892 strncpy(pSMB->RequestFileName, searchName, name_len);
4896 if (ses->server->sec_mode &
4897 (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
4898 pSMB->hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
4901 pSMB->hdr.Uid = ses->Suid;
4903 params = 2 /* level */ + name_len /*includes null */ ;
4904 pSMB->TotalDataCount = 0;
4905 pSMB->DataCount = 0;
4906 pSMB->DataOffset = 0;
4907 pSMB->MaxParameterCount = 0;
4908 /* BB find exact max SMB PDU from sess structure BB */
4909 pSMB->MaxDataCount = cpu_to_le16(4000);
4910 pSMB->MaxSetupCount = 0;
4914 pSMB->Reserved2 = 0;
4915 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4916 struct smb_com_transaction2_get_dfs_refer_req, MaxReferralLevel) - 4);
4917 pSMB->SetupCount = 1;
4918 pSMB->Reserved3 = 0;
4919 pSMB->SubCommand = cpu_to_le16(TRANS2_GET_DFS_REFERRAL);
4920 byte_count = params + 3 /* pad */ ;
4921 pSMB->ParameterCount = cpu_to_le16(params);
4922 pSMB->TotalParameterCount = pSMB->ParameterCount;
4923 pSMB->MaxReferralLevel = cpu_to_le16(3);
4924 inc_rfc1001_len(pSMB, byte_count);
4925 pSMB->ByteCount = cpu_to_le16(byte_count);
4927 rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB,
4928 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4930 cFYI(1, "Send error in GetDFSRefer = %d", rc);
4933 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4935 /* BB Also check if enough total bytes returned? */
4936 if (rc || get_bcc(&pSMBr->hdr) < 17) {
4937 rc = -EIO; /* bad smb */
4941 cFYI(1, "Decoding GetDFSRefer response BCC: %d Offset %d",
4942 get_bcc(&pSMBr->hdr),
4943 le16_to_cpu(pSMBr->t2.DataOffset));
4945 /* parse returned result into more usable form */
4946 rc = parse_DFS_referrals(pSMBr, num_of_nodes,
4947 target_nodes, nls_codepage, remap,
4951 cifs_buf_release(pSMB);
4959 /* Query File System Info such as free space to old servers such as Win 9x */
4961 SMBOldQFSInfo(const int xid, struct cifs_tcon *tcon, struct kstatfs *FSData)
4963 /* level 0x01 SMB_QUERY_FILE_SYSTEM_INFO */
4964 TRANSACTION2_QFSI_REQ *pSMB = NULL;
4965 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4966 FILE_SYSTEM_ALLOC_INFO *response_data;
4968 int bytes_returned = 0;
4969 __u16 params, byte_count;
4971 cFYI(1, "OldQFSInfo");
4973 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4978 params = 2; /* level */
4979 pSMB->TotalDataCount = 0;
4980 pSMB->MaxParameterCount = cpu_to_le16(2);
4981 pSMB->MaxDataCount = cpu_to_le16(1000);
4982 pSMB->MaxSetupCount = 0;
4986 pSMB->Reserved2 = 0;
4987 byte_count = params + 1 /* pad */ ;
4988 pSMB->TotalParameterCount = cpu_to_le16(params);
4989 pSMB->ParameterCount = pSMB->TotalParameterCount;
4990 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4991 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4992 pSMB->DataCount = 0;
4993 pSMB->DataOffset = 0;
4994 pSMB->SetupCount = 1;
4995 pSMB->Reserved3 = 0;
4996 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4997 pSMB->InformationLevel = cpu_to_le16(SMB_INFO_ALLOCATION);
4998 inc_rfc1001_len(pSMB, byte_count);
4999 pSMB->ByteCount = cpu_to_le16(byte_count);
5001 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5002 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5004 cFYI(1, "Send error in QFSInfo = %d", rc);
5005 } else { /* decode response */
5006 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
5008 if (rc || get_bcc(&pSMBr->hdr) < 18)
5009 rc = -EIO; /* bad smb */
5011 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
5012 cFYI(1, "qfsinf resp BCC: %d Offset %d",
5013 get_bcc(&pSMBr->hdr), data_offset);
5015 response_data = (FILE_SYSTEM_ALLOC_INFO *)
5016 (((char *) &pSMBr->hdr.Protocol) + data_offset);
5018 le16_to_cpu(response_data->BytesPerSector) *
5019 le32_to_cpu(response_data->
5020 SectorsPerAllocationUnit);
5022 le32_to_cpu(response_data->TotalAllocationUnits);
5023 FSData->f_bfree = FSData->f_bavail =
5024 le32_to_cpu(response_data->FreeAllocationUnits);
5025 cFYI(1, "Blocks: %lld Free: %lld Block size %ld",
5026 (unsigned long long)FSData->f_blocks,
5027 (unsigned long long)FSData->f_bfree,
5031 cifs_buf_release(pSMB);
5034 goto oldQFSInfoRetry;
5040 CIFSSMBQFSInfo(const int xid, struct cifs_tcon *tcon, struct kstatfs *FSData)
5042 /* level 0x103 SMB_QUERY_FILE_SYSTEM_INFO */
5043 TRANSACTION2_QFSI_REQ *pSMB = NULL;
5044 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
5045 FILE_SYSTEM_INFO *response_data;
5047 int bytes_returned = 0;
5048 __u16 params, byte_count;
5050 cFYI(1, "In QFSInfo");
5052 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5057 params = 2; /* level */
5058 pSMB->TotalDataCount = 0;
5059 pSMB->MaxParameterCount = cpu_to_le16(2);
5060 pSMB->MaxDataCount = cpu_to_le16(1000);
5061 pSMB->MaxSetupCount = 0;
5065 pSMB->Reserved2 = 0;
5066 byte_count = params + 1 /* pad */ ;
5067 pSMB->TotalParameterCount = cpu_to_le16(params);
5068 pSMB->ParameterCount = pSMB->TotalParameterCount;
5069 pSMB->ParameterOffset = cpu_to_le16(offsetof(
5070 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
5071 pSMB->DataCount = 0;
5072 pSMB->DataOffset = 0;
5073 pSMB->SetupCount = 1;
5074 pSMB->Reserved3 = 0;
5075 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
5076 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_SIZE_INFO);
5077 inc_rfc1001_len(pSMB, byte_count);
5078 pSMB->ByteCount = cpu_to_le16(byte_count);
5080 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5081 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5083 cFYI(1, "Send error in QFSInfo = %d", rc);
5084 } else { /* decode response */
5085 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
5087 if (rc || get_bcc(&pSMBr->hdr) < 24)
5088 rc = -EIO; /* bad smb */
5090 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
5094 *) (((char *) &pSMBr->hdr.Protocol) +
5097 le32_to_cpu(response_data->BytesPerSector) *
5098 le32_to_cpu(response_data->
5099 SectorsPerAllocationUnit);
5101 le64_to_cpu(response_data->TotalAllocationUnits);
5102 FSData->f_bfree = FSData->f_bavail =
5103 le64_to_cpu(response_data->FreeAllocationUnits);
5104 cFYI(1, "Blocks: %lld Free: %lld Block size %ld",
5105 (unsigned long long)FSData->f_blocks,
5106 (unsigned long long)FSData->f_bfree,
5110 cifs_buf_release(pSMB);
5119 CIFSSMBQFSAttributeInfo(const int xid, struct cifs_tcon *tcon)
5121 /* level 0x105 SMB_QUERY_FILE_SYSTEM_INFO */
5122 TRANSACTION2_QFSI_REQ *pSMB = NULL;
5123 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
5124 FILE_SYSTEM_ATTRIBUTE_INFO *response_data;
5126 int bytes_returned = 0;
5127 __u16 params, byte_count;
5129 cFYI(1, "In QFSAttributeInfo");
5131 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5136 params = 2; /* level */
5137 pSMB->TotalDataCount = 0;
5138 pSMB->MaxParameterCount = cpu_to_le16(2);
5139 /* BB find exact max SMB PDU from sess structure BB */
5140 pSMB->MaxDataCount = cpu_to_le16(1000);
5141 pSMB->MaxSetupCount = 0;
5145 pSMB->Reserved2 = 0;
5146 byte_count = params + 1 /* pad */ ;
5147 pSMB->TotalParameterCount = cpu_to_le16(params);
5148 pSMB->ParameterCount = pSMB->TotalParameterCount;
5149 pSMB->ParameterOffset = cpu_to_le16(offsetof(
5150 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
5151 pSMB->DataCount = 0;
5152 pSMB->DataOffset = 0;
5153 pSMB->SetupCount = 1;
5154 pSMB->Reserved3 = 0;
5155 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
5156 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_ATTRIBUTE_INFO);
5157 inc_rfc1001_len(pSMB, byte_count);
5158 pSMB->ByteCount = cpu_to_le16(byte_count);
5160 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5161 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5163 cERROR(1, "Send error in QFSAttributeInfo = %d", rc);
5164 } else { /* decode response */
5165 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
5167 if (rc || get_bcc(&pSMBr->hdr) < 13) {
5168 /* BB also check if enough bytes returned */
5169 rc = -EIO; /* bad smb */
5171 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
5173 (FILE_SYSTEM_ATTRIBUTE_INFO
5174 *) (((char *) &pSMBr->hdr.Protocol) +
5176 memcpy(&tcon->fsAttrInfo, response_data,
5177 sizeof(FILE_SYSTEM_ATTRIBUTE_INFO));
5180 cifs_buf_release(pSMB);
5183 goto QFSAttributeRetry;
5189 CIFSSMBQFSDeviceInfo(const int xid, struct cifs_tcon *tcon)
5191 /* level 0x104 SMB_QUERY_FILE_SYSTEM_INFO */
5192 TRANSACTION2_QFSI_REQ *pSMB = NULL;
5193 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
5194 FILE_SYSTEM_DEVICE_INFO *response_data;
5196 int bytes_returned = 0;
5197 __u16 params, byte_count;
5199 cFYI(1, "In QFSDeviceInfo");
5201 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5206 params = 2; /* level */
5207 pSMB->TotalDataCount = 0;
5208 pSMB->MaxParameterCount = cpu_to_le16(2);
5209 /* BB find exact max SMB PDU from sess structure BB */
5210 pSMB->MaxDataCount = cpu_to_le16(1000);
5211 pSMB->MaxSetupCount = 0;
5215 pSMB->Reserved2 = 0;
5216 byte_count = params + 1 /* pad */ ;
5217 pSMB->TotalParameterCount = cpu_to_le16(params);
5218 pSMB->ParameterCount = pSMB->TotalParameterCount;
5219 pSMB->ParameterOffset = cpu_to_le16(offsetof(
5220 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
5222 pSMB->DataCount = 0;
5223 pSMB->DataOffset = 0;
5224 pSMB->SetupCount = 1;
5225 pSMB->Reserved3 = 0;
5226 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
5227 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_DEVICE_INFO);
5228 inc_rfc1001_len(pSMB, byte_count);
5229 pSMB->ByteCount = cpu_to_le16(byte_count);
5231 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5232 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5234 cFYI(1, "Send error in QFSDeviceInfo = %d", rc);
5235 } else { /* decode response */
5236 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
5238 if (rc || get_bcc(&pSMBr->hdr) <
5239 sizeof(FILE_SYSTEM_DEVICE_INFO))
5240 rc = -EIO; /* bad smb */
5242 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
5244 (FILE_SYSTEM_DEVICE_INFO *)
5245 (((char *) &pSMBr->hdr.Protocol) +
5247 memcpy(&tcon->fsDevInfo, response_data,
5248 sizeof(FILE_SYSTEM_DEVICE_INFO));
5251 cifs_buf_release(pSMB);
5254 goto QFSDeviceRetry;
5260 CIFSSMBQFSUnixInfo(const int xid, struct cifs_tcon *tcon)
5262 /* level 0x200 SMB_QUERY_CIFS_UNIX_INFO */
5263 TRANSACTION2_QFSI_REQ *pSMB = NULL;
5264 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
5265 FILE_SYSTEM_UNIX_INFO *response_data;
5267 int bytes_returned = 0;
5268 __u16 params, byte_count;
5270 cFYI(1, "In QFSUnixInfo");
5272 rc = smb_init_no_reconnect(SMB_COM_TRANSACTION2, 15, tcon,
5273 (void **) &pSMB, (void **) &pSMBr);
5277 params = 2; /* level */
5278 pSMB->TotalDataCount = 0;
5279 pSMB->DataCount = 0;
5280 pSMB->DataOffset = 0;
5281 pSMB->MaxParameterCount = cpu_to_le16(2);
5282 /* BB find exact max SMB PDU from sess structure BB */
5283 pSMB->MaxDataCount = cpu_to_le16(100);
5284 pSMB->MaxSetupCount = 0;
5288 pSMB->Reserved2 = 0;
5289 byte_count = params + 1 /* pad */ ;
5290 pSMB->ParameterCount = cpu_to_le16(params);
5291 pSMB->TotalParameterCount = pSMB->ParameterCount;
5292 pSMB->ParameterOffset = cpu_to_le16(offsetof(struct
5293 smb_com_transaction2_qfsi_req, InformationLevel) - 4);
5294 pSMB->SetupCount = 1;
5295 pSMB->Reserved3 = 0;
5296 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
5297 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_CIFS_UNIX_INFO);
5298 inc_rfc1001_len(pSMB, byte_count);
5299 pSMB->ByteCount = cpu_to_le16(byte_count);
5301 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5302 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5304 cERROR(1, "Send error in QFSUnixInfo = %d", rc);
5305 } else { /* decode response */
5306 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
5308 if (rc || get_bcc(&pSMBr->hdr) < 13) {
5309 rc = -EIO; /* bad smb */
5311 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
5313 (FILE_SYSTEM_UNIX_INFO
5314 *) (((char *) &pSMBr->hdr.Protocol) +
5316 memcpy(&tcon->fsUnixInfo, response_data,
5317 sizeof(FILE_SYSTEM_UNIX_INFO));
5320 cifs_buf_release(pSMB);
5330 CIFSSMBSetFSUnixInfo(const int xid, struct cifs_tcon *tcon, __u64 cap)
5332 /* level 0x200 SMB_SET_CIFS_UNIX_INFO */
5333 TRANSACTION2_SETFSI_REQ *pSMB = NULL;
5334 TRANSACTION2_SETFSI_RSP *pSMBr = NULL;
5336 int bytes_returned = 0;
5337 __u16 params, param_offset, offset, byte_count;
5339 cFYI(1, "In SETFSUnixInfo");
5341 /* BB switch to small buf init to save memory */
5342 rc = smb_init_no_reconnect(SMB_COM_TRANSACTION2, 15, tcon,
5343 (void **) &pSMB, (void **) &pSMBr);
5347 params = 4; /* 2 bytes zero followed by info level. */
5348 pSMB->MaxSetupCount = 0;
5352 pSMB->Reserved2 = 0;
5353 param_offset = offsetof(struct smb_com_transaction2_setfsi_req, FileNum)
5355 offset = param_offset + params;
5357 pSMB->MaxParameterCount = cpu_to_le16(4);
5358 /* BB find exact max SMB PDU from sess structure BB */
5359 pSMB->MaxDataCount = cpu_to_le16(100);
5360 pSMB->SetupCount = 1;
5361 pSMB->Reserved3 = 0;
5362 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FS_INFORMATION);
5363 byte_count = 1 /* pad */ + params + 12;
5365 pSMB->DataCount = cpu_to_le16(12);
5366 pSMB->ParameterCount = cpu_to_le16(params);
5367 pSMB->TotalDataCount = pSMB->DataCount;
5368 pSMB->TotalParameterCount = pSMB->ParameterCount;
5369 pSMB->ParameterOffset = cpu_to_le16(param_offset);
5370 pSMB->DataOffset = cpu_to_le16(offset);
5374 pSMB->InformationLevel = cpu_to_le16(SMB_SET_CIFS_UNIX_INFO);
5377 pSMB->ClientUnixMajor = cpu_to_le16(CIFS_UNIX_MAJOR_VERSION);
5378 pSMB->ClientUnixMinor = cpu_to_le16(CIFS_UNIX_MINOR_VERSION);
5379 pSMB->ClientUnixCap = cpu_to_le64(cap);
5381 inc_rfc1001_len(pSMB, byte_count);
5382 pSMB->ByteCount = cpu_to_le16(byte_count);
5384 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5385 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5387 cERROR(1, "Send error in SETFSUnixInfo = %d", rc);
5388 } else { /* decode response */
5389 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
5391 rc = -EIO; /* bad smb */
5393 cifs_buf_release(pSMB);
5396 goto SETFSUnixRetry;
5404 CIFSSMBQFSPosixInfo(const int xid, struct cifs_tcon *tcon,
5405 struct kstatfs *FSData)
5407 /* level 0x201 SMB_QUERY_CIFS_POSIX_INFO */
5408 TRANSACTION2_QFSI_REQ *pSMB = NULL;
5409 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
5410 FILE_SYSTEM_POSIX_INFO *response_data;
5412 int bytes_returned = 0;
5413 __u16 params, byte_count;
5415 cFYI(1, "In QFSPosixInfo");
5417 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5422 params = 2; /* level */
5423 pSMB->TotalDataCount = 0;
5424 pSMB->DataCount = 0;
5425 pSMB->DataOffset = 0;
5426 pSMB->MaxParameterCount = cpu_to_le16(2);
5427 /* BB find exact max SMB PDU from sess structure BB */
5428 pSMB->MaxDataCount = cpu_to_le16(100);
5429 pSMB->MaxSetupCount = 0;
5433 pSMB->Reserved2 = 0;
5434 byte_count = params + 1 /* pad */ ;
5435 pSMB->ParameterCount = cpu_to_le16(params);
5436 pSMB->TotalParameterCount = pSMB->ParameterCount;
5437 pSMB->ParameterOffset = cpu_to_le16(offsetof(struct
5438 smb_com_transaction2_qfsi_req, InformationLevel) - 4);
5439 pSMB->SetupCount = 1;
5440 pSMB->Reserved3 = 0;
5441 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
5442 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_POSIX_FS_INFO);
5443 inc_rfc1001_len(pSMB, byte_count);
5444 pSMB->ByteCount = cpu_to_le16(byte_count);
5446 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5447 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5449 cFYI(1, "Send error in QFSUnixInfo = %d", rc);
5450 } else { /* decode response */
5451 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
5453 if (rc || get_bcc(&pSMBr->hdr) < 13) {
5454 rc = -EIO; /* bad smb */
5456 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
5458 (FILE_SYSTEM_POSIX_INFO
5459 *) (((char *) &pSMBr->hdr.Protocol) +
5462 le32_to_cpu(response_data->BlockSize);
5464 le64_to_cpu(response_data->TotalBlocks);
5466 le64_to_cpu(response_data->BlocksAvail);
5467 if (response_data->UserBlocksAvail == cpu_to_le64(-1)) {
5468 FSData->f_bavail = FSData->f_bfree;
5471 le64_to_cpu(response_data->UserBlocksAvail);
5473 if (response_data->TotalFileNodes != cpu_to_le64(-1))
5475 le64_to_cpu(response_data->TotalFileNodes);
5476 if (response_data->FreeFileNodes != cpu_to_le64(-1))
5478 le64_to_cpu(response_data->FreeFileNodes);
5481 cifs_buf_release(pSMB);
5490 /* We can not use write of zero bytes trick to
5491 set file size due to need for large file support. Also note that
5492 this SetPathInfo is preferred to SetFileInfo based method in next
5493 routine which is only needed to work around a sharing violation bug
5494 in Samba which this routine can run into */
5497 CIFSSMBSetEOF(const int xid, struct cifs_tcon *tcon, const char *fileName,
5498 __u64 size, bool SetAllocation,
5499 const struct nls_table *nls_codepage, int remap)
5501 struct smb_com_transaction2_spi_req *pSMB = NULL;
5502 struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
5503 struct file_end_of_file_info *parm_data;
5506 int bytes_returned = 0;
5507 __u16 params, byte_count, data_count, param_offset, offset;
5509 cFYI(1, "In SetEOF");
5511 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5516 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5518 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
5519 PATH_MAX, nls_codepage, remap);
5520 name_len++; /* trailing null */
5522 } else { /* BB improve the check for buffer overruns BB */
5523 name_len = strnlen(fileName, PATH_MAX);
5524 name_len++; /* trailing null */
5525 strncpy(pSMB->FileName, fileName, name_len);
5527 params = 6 + name_len;
5528 data_count = sizeof(struct file_end_of_file_info);
5529 pSMB->MaxParameterCount = cpu_to_le16(2);
5530 pSMB->MaxDataCount = cpu_to_le16(4100);
5531 pSMB->MaxSetupCount = 0;
5535 pSMB->Reserved2 = 0;
5536 param_offset = offsetof(struct smb_com_transaction2_spi_req,
5537 InformationLevel) - 4;
5538 offset = param_offset + params;
5539 if (SetAllocation) {
5540 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
5541 pSMB->InformationLevel =
5542 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2);
5544 pSMB->InformationLevel =
5545 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO);
5546 } else /* Set File Size */ {
5547 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
5548 pSMB->InformationLevel =
5549 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO2);
5551 pSMB->InformationLevel =
5552 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO);
5556 (struct file_end_of_file_info *) (((char *) &pSMB->hdr.Protocol) +
5558 pSMB->ParameterOffset = cpu_to_le16(param_offset);
5559 pSMB->DataOffset = cpu_to_le16(offset);
5560 pSMB->SetupCount = 1;
5561 pSMB->Reserved3 = 0;
5562 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
5563 byte_count = 3 /* pad */ + params + data_count;
5564 pSMB->DataCount = cpu_to_le16(data_count);
5565 pSMB->TotalDataCount = pSMB->DataCount;
5566 pSMB->ParameterCount = cpu_to_le16(params);
5567 pSMB->TotalParameterCount = pSMB->ParameterCount;
5568 pSMB->Reserved4 = 0;
5569 inc_rfc1001_len(pSMB, byte_count);
5570 parm_data->FileSize = cpu_to_le64(size);
5571 pSMB->ByteCount = cpu_to_le16(byte_count);
5572 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5573 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5575 cFYI(1, "SetPathInfo (file size) returned %d", rc);
5577 cifs_buf_release(pSMB);
5586 CIFSSMBSetFileSize(const int xid, struct cifs_tcon *tcon, __u64 size,
5587 __u16 fid, __u32 pid_of_opener, bool SetAllocation)
5589 struct smb_com_transaction2_sfi_req *pSMB = NULL;
5590 struct file_end_of_file_info *parm_data;
5592 __u16 params, param_offset, offset, byte_count, count;
5594 cFYI(1, "SetFileSize (via SetFileInfo) %lld",
5596 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
5601 pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
5602 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));
5605 pSMB->MaxSetupCount = 0;
5609 pSMB->Reserved2 = 0;
5610 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
5611 offset = param_offset + params;
5613 count = sizeof(struct file_end_of_file_info);
5614 pSMB->MaxParameterCount = cpu_to_le16(2);
5615 /* BB find exact max SMB PDU from sess structure BB */
5616 pSMB->MaxDataCount = cpu_to_le16(1000);
5617 pSMB->SetupCount = 1;
5618 pSMB->Reserved3 = 0;
5619 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
5620 byte_count = 3 /* pad */ + params + count;
5621 pSMB->DataCount = cpu_to_le16(count);
5622 pSMB->ParameterCount = cpu_to_le16(params);
5623 pSMB->TotalDataCount = pSMB->DataCount;
5624 pSMB->TotalParameterCount = pSMB->ParameterCount;
5625 pSMB->ParameterOffset = cpu_to_le16(param_offset);
5627 (struct file_end_of_file_info *) (((char *) &pSMB->hdr.Protocol)
5629 pSMB->DataOffset = cpu_to_le16(offset);
5630 parm_data->FileSize = cpu_to_le64(size);
5632 if (SetAllocation) {
5633 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
5634 pSMB->InformationLevel =
5635 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2);
5637 pSMB->InformationLevel =
5638 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO);
5639 } else /* Set File Size */ {
5640 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
5641 pSMB->InformationLevel =
5642 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO2);
5644 pSMB->InformationLevel =
5645 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO);
5647 pSMB->Reserved4 = 0;
5648 inc_rfc1001_len(pSMB, byte_count);
5649 pSMB->ByteCount = cpu_to_le16(byte_count);
5650 rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0);
5652 cFYI(1, "Send error in SetFileInfo (SetFileSize) = %d", rc);
5655 /* Note: On -EAGAIN error only caller can retry on handle based calls
5656 since file handle passed in no longer valid */
5661 /* Some legacy servers such as NT4 require that the file times be set on
5662 an open handle, rather than by pathname - this is awkward due to
5663 potential access conflicts on the open, but it is unavoidable for these
5664 old servers since the only other choice is to go from 100 nanosecond DCE
5665 time and resort to the original setpathinfo level which takes the ancient
5666 DOS time format with 2 second granularity */
5668 CIFSSMBSetFileInfo(const int xid, struct cifs_tcon *tcon,
5669 const FILE_BASIC_INFO *data, __u16 fid, __u32 pid_of_opener)
5671 struct smb_com_transaction2_sfi_req *pSMB = NULL;
5674 __u16 params, param_offset, offset, byte_count, count;
5676 cFYI(1, "Set Times (via SetFileInfo)");
5677 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
5682 pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
5683 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));
5686 pSMB->MaxSetupCount = 0;
5690 pSMB->Reserved2 = 0;
5691 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
5692 offset = param_offset + params;
5694 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
5696 count = sizeof(FILE_BASIC_INFO);
5697 pSMB->MaxParameterCount = cpu_to_le16(2);
5698 /* BB find max SMB PDU from sess */
5699 pSMB->MaxDataCount = cpu_to_le16(1000);
5700 pSMB->SetupCount = 1;
5701 pSMB->Reserved3 = 0;
5702 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
5703 byte_count = 3 /* pad */ + params + count;
5704 pSMB->DataCount = cpu_to_le16(count);
5705 pSMB->ParameterCount = cpu_to_le16(params);
5706 pSMB->TotalDataCount = pSMB->DataCount;
5707 pSMB->TotalParameterCount = pSMB->ParameterCount;
5708 pSMB->ParameterOffset = cpu_to_le16(param_offset);
5709 pSMB->DataOffset = cpu_to_le16(offset);
5711 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
5712 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO2);
5714 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO);
5715 pSMB->Reserved4 = 0;
5716 inc_rfc1001_len(pSMB, byte_count);
5717 pSMB->ByteCount = cpu_to_le16(byte_count);
5718 memcpy(data_offset, data, sizeof(FILE_BASIC_INFO));
5719 rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0);
5721 cFYI(1, "Send error in Set Time (SetFileInfo) = %d", rc);
5723 /* Note: On -EAGAIN error only caller can retry on handle based calls
5724 since file handle passed in no longer valid */
5730 CIFSSMBSetFileDisposition(const int xid, struct cifs_tcon *tcon,
5731 bool delete_file, __u16 fid, __u32 pid_of_opener)
5733 struct smb_com_transaction2_sfi_req *pSMB = NULL;
5736 __u16 params, param_offset, offset, byte_count, count;
5738 cFYI(1, "Set File Disposition (via SetFileInfo)");
5739 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
5744 pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
5745 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));
5748 pSMB->MaxSetupCount = 0;
5752 pSMB->Reserved2 = 0;
5753 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
5754 offset = param_offset + params;
5756 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
5759 pSMB->MaxParameterCount = cpu_to_le16(2);
5760 /* BB find max SMB PDU from sess */
5761 pSMB->MaxDataCount = cpu_to_le16(1000);
5762 pSMB->SetupCount = 1;
5763 pSMB->Reserved3 = 0;
5764 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
5765 byte_count = 3 /* pad */ + params + count;
5766 pSMB->DataCount = cpu_to_le16(count);
5767 pSMB->ParameterCount = cpu_to_le16(params);
5768 pSMB->TotalDataCount = pSMB->DataCount;
5769 pSMB->TotalParameterCount = pSMB->ParameterCount;
5770 pSMB->ParameterOffset = cpu_to_le16(param_offset);
5771 pSMB->DataOffset = cpu_to_le16(offset);
5773 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_DISPOSITION_INFO);
5774 pSMB->Reserved4 = 0;
5775 inc_rfc1001_len(pSMB, byte_count);
5776 pSMB->ByteCount = cpu_to_le16(byte_count);
5777 *data_offset = delete_file ? 1 : 0;
5778 rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0);
5780 cFYI(1, "Send error in SetFileDisposition = %d", rc);
5786 CIFSSMBSetPathInfo(const int xid, struct cifs_tcon *tcon,
5787 const char *fileName, const FILE_BASIC_INFO *data,
5788 const struct nls_table *nls_codepage, int remap)
5790 TRANSACTION2_SPI_REQ *pSMB = NULL;
5791 TRANSACTION2_SPI_RSP *pSMBr = NULL;
5794 int bytes_returned = 0;
5796 __u16 params, param_offset, offset, byte_count, count;
5798 cFYI(1, "In SetTimes");
5801 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5806 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5808 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
5809 PATH_MAX, nls_codepage, remap);
5810 name_len++; /* trailing null */
5812 } else { /* BB improve the check for buffer overruns BB */
5813 name_len = strnlen(fileName, PATH_MAX);
5814 name_len++; /* trailing null */
5815 strncpy(pSMB->FileName, fileName, name_len);
5818 params = 6 + name_len;
5819 count = sizeof(FILE_BASIC_INFO);
5820 pSMB->MaxParameterCount = cpu_to_le16(2);
5821 /* BB find max SMB PDU from sess structure BB */
5822 pSMB->MaxDataCount = cpu_to_le16(1000);
5823 pSMB->MaxSetupCount = 0;
5827 pSMB->Reserved2 = 0;
5828 param_offset = offsetof(struct smb_com_transaction2_spi_req,
5829 InformationLevel) - 4;
5830 offset = param_offset + params;
5831 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
5832 pSMB->ParameterOffset = cpu_to_le16(param_offset);
5833 pSMB->DataOffset = cpu_to_le16(offset);
5834 pSMB->SetupCount = 1;
5835 pSMB->Reserved3 = 0;
5836 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
5837 byte_count = 3 /* pad */ + params + count;
5839 pSMB->DataCount = cpu_to_le16(count);
5840 pSMB->ParameterCount = cpu_to_le16(params);
5841 pSMB->TotalDataCount = pSMB->DataCount;
5842 pSMB->TotalParameterCount = pSMB->ParameterCount;
5843 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
5844 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO2);
5846 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO);
5847 pSMB->Reserved4 = 0;
5848 inc_rfc1001_len(pSMB, byte_count);
5849 memcpy(data_offset, data, sizeof(FILE_BASIC_INFO));
5850 pSMB->ByteCount = cpu_to_le16(byte_count);
5851 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5852 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5854 cFYI(1, "SetPathInfo (times) returned %d", rc);
5856 cifs_buf_release(pSMB);
5864 /* Can not be used to set time stamps yet (due to old DOS time format) */
5865 /* Can be used to set attributes */
5866 #if 0 /* Possibly not needed - since it turns out that strangely NT4 has a bug
5867 handling it anyway and NT4 was what we thought it would be needed for
5868 Do not delete it until we prove whether needed for Win9x though */
5870 CIFSSMBSetAttrLegacy(int xid, struct cifs_tcon *tcon, char *fileName,
5871 __u16 dos_attrs, const struct nls_table *nls_codepage)
5873 SETATTR_REQ *pSMB = NULL;
5874 SETATTR_RSP *pSMBr = NULL;
5879 cFYI(1, "In SetAttrLegacy");
5882 rc = smb_init(SMB_COM_SETATTR, 8, tcon, (void **) &pSMB,
5887 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5889 ConvertToUCS((__le16 *) pSMB->fileName, fileName,
5890 PATH_MAX, nls_codepage);
5891 name_len++; /* trailing null */
5893 } else { /* BB improve the check for buffer overruns BB */
5894 name_len = strnlen(fileName, PATH_MAX);
5895 name_len++; /* trailing null */
5896 strncpy(pSMB->fileName, fileName, name_len);
5898 pSMB->attr = cpu_to_le16(dos_attrs);
5899 pSMB->BufferFormat = 0x04;
5900 inc_rfc1001_len(pSMB, name_len + 1);
5901 pSMB->ByteCount = cpu_to_le16(name_len + 1);
5902 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5903 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5905 cFYI(1, "Error in LegacySetAttr = %d", rc);
5907 cifs_buf_release(pSMB);
5910 goto SetAttrLgcyRetry;
5914 #endif /* temporarily unneeded SetAttr legacy function */
5917 cifs_fill_unix_set_info(FILE_UNIX_BASIC_INFO *data_offset,
5918 const struct cifs_unix_set_info_args *args)
5920 u64 mode = args->mode;
5923 * Samba server ignores set of file size to zero due to bugs in some
5924 * older clients, but we should be precise - we use SetFileSize to
5925 * set file size and do not want to truncate file size to zero
5926 * accidentally as happened on one Samba server beta by putting
5927 * zero instead of -1 here
5929 data_offset->EndOfFile = cpu_to_le64(NO_CHANGE_64);
5930 data_offset->NumOfBytes = cpu_to_le64(NO_CHANGE_64);
5931 data_offset->LastStatusChange = cpu_to_le64(args->ctime);
5932 data_offset->LastAccessTime = cpu_to_le64(args->atime);
5933 data_offset->LastModificationTime = cpu_to_le64(args->mtime);
5934 data_offset->Uid = cpu_to_le64(args->uid);
5935 data_offset->Gid = cpu_to_le64(args->gid);
5936 /* better to leave device as zero when it is */
5937 data_offset->DevMajor = cpu_to_le64(MAJOR(args->device));
5938 data_offset->DevMinor = cpu_to_le64(MINOR(args->device));
5939 data_offset->Permissions = cpu_to_le64(mode);
5942 data_offset->Type = cpu_to_le32(UNIX_FILE);
5943 else if (S_ISDIR(mode))
5944 data_offset->Type = cpu_to_le32(UNIX_DIR);
5945 else if (S_ISLNK(mode))
5946 data_offset->Type = cpu_to_le32(UNIX_SYMLINK);
5947 else if (S_ISCHR(mode))
5948 data_offset->Type = cpu_to_le32(UNIX_CHARDEV);
5949 else if (S_ISBLK(mode))
5950 data_offset->Type = cpu_to_le32(UNIX_BLOCKDEV);
5951 else if (S_ISFIFO(mode))
5952 data_offset->Type = cpu_to_le32(UNIX_FIFO);
5953 else if (S_ISSOCK(mode))
5954 data_offset->Type = cpu_to_le32(UNIX_SOCKET);
5958 CIFSSMBUnixSetFileInfo(const int xid, struct cifs_tcon *tcon,
5959 const struct cifs_unix_set_info_args *args,
5960 u16 fid, u32 pid_of_opener)
5962 struct smb_com_transaction2_sfi_req *pSMB = NULL;
5963 FILE_UNIX_BASIC_INFO *data_offset;
5965 u16 params, param_offset, offset, byte_count, count;
5967 cFYI(1, "Set Unix Info (via SetFileInfo)");
5968 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
5973 pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
5974 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));
5977 pSMB->MaxSetupCount = 0;
5981 pSMB->Reserved2 = 0;
5982 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
5983 offset = param_offset + params;
5985 data_offset = (FILE_UNIX_BASIC_INFO *)
5986 ((char *)(&pSMB->hdr.Protocol) + offset);
5987 count = sizeof(FILE_UNIX_BASIC_INFO);
5989 pSMB->MaxParameterCount = cpu_to_le16(2);
5990 /* BB find max SMB PDU from sess */
5991 pSMB->MaxDataCount = cpu_to_le16(1000);
5992 pSMB->SetupCount = 1;
5993 pSMB->Reserved3 = 0;
5994 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
5995 byte_count = 3 /* pad */ + params + count;
5996 pSMB->DataCount = cpu_to_le16(count);
5997 pSMB->ParameterCount = cpu_to_le16(params);
5998 pSMB->TotalDataCount = pSMB->DataCount;
5999 pSMB->TotalParameterCount = pSMB->ParameterCount;
6000 pSMB->ParameterOffset = cpu_to_le16(param_offset);
6001 pSMB->DataOffset = cpu_to_le16(offset);
6003 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_BASIC);
6004 pSMB->Reserved4 = 0;
6005 inc_rfc1001_len(pSMB, byte_count);
6006 pSMB->ByteCount = cpu_to_le16(byte_count);
6008 cifs_fill_unix_set_info(data_offset, args);
6010 rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0);
6012 cFYI(1, "Send error in Set Time (SetFileInfo) = %d", rc);
6014 /* Note: On -EAGAIN error only caller can retry on handle based calls
6015 since file handle passed in no longer valid */
6021 CIFSSMBUnixSetPathInfo(const int xid, struct cifs_tcon *tcon, char *fileName,
6022 const struct cifs_unix_set_info_args *args,
6023 const struct nls_table *nls_codepage, int remap)
6025 TRANSACTION2_SPI_REQ *pSMB = NULL;
6026 TRANSACTION2_SPI_RSP *pSMBr = NULL;
6029 int bytes_returned = 0;
6030 FILE_UNIX_BASIC_INFO *data_offset;
6031 __u16 params, param_offset, offset, count, byte_count;
6033 cFYI(1, "In SetUID/GID/Mode");
6035 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
6040 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
6042 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
6043 PATH_MAX, nls_codepage, remap);
6044 name_len++; /* trailing null */
6046 } else { /* BB improve the check for buffer overruns BB */
6047 name_len = strnlen(fileName, PATH_MAX);
6048 name_len++; /* trailing null */
6049 strncpy(pSMB->FileName, fileName, name_len);
6052 params = 6 + name_len;
6053 count = sizeof(FILE_UNIX_BASIC_INFO);
6054 pSMB->MaxParameterCount = cpu_to_le16(2);
6055 /* BB find max SMB PDU from sess structure BB */
6056 pSMB->MaxDataCount = cpu_to_le16(1000);
6057 pSMB->MaxSetupCount = 0;
6061 pSMB->Reserved2 = 0;
6062 param_offset = offsetof(struct smb_com_transaction2_spi_req,
6063 InformationLevel) - 4;
6064 offset = param_offset + params;
6066 (FILE_UNIX_BASIC_INFO *) ((char *) &pSMB->hdr.Protocol +
6068 memset(data_offset, 0, count);
6069 pSMB->DataOffset = cpu_to_le16(offset);
6070 pSMB->ParameterOffset = cpu_to_le16(param_offset);
6071 pSMB->SetupCount = 1;
6072 pSMB->Reserved3 = 0;
6073 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
6074 byte_count = 3 /* pad */ + params + count;
6075 pSMB->ParameterCount = cpu_to_le16(params);
6076 pSMB->DataCount = cpu_to_le16(count);
6077 pSMB->TotalParameterCount = pSMB->ParameterCount;
6078 pSMB->TotalDataCount = pSMB->DataCount;
6079 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_BASIC);
6080 pSMB->Reserved4 = 0;
6081 inc_rfc1001_len(pSMB, byte_count);
6083 cifs_fill_unix_set_info(data_offset, args);
6085 pSMB->ByteCount = cpu_to_le16(byte_count);
6086 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
6087 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
6089 cFYI(1, "SetPathInfo (perms) returned %d", rc);
6091 cifs_buf_release(pSMB);
6097 #ifdef CONFIG_CIFS_XATTR
6099 * Do a path-based QUERY_ALL_EAS call and parse the result. This is a common
6100 * function used by listxattr and getxattr type calls. When ea_name is set,
6101 * it looks for that attribute name and stuffs that value into the EAData
6102 * buffer. When ea_name is NULL, it stuffs a list of attribute names into the
6103 * buffer. In both cases, the return value is either the length of the
6104 * resulting data or a negative error code. If EAData is a NULL pointer then
6105 * the data isn't copied to it, but the length is returned.
6108 CIFSSMBQAllEAs(const int xid, struct cifs_tcon *tcon,
6109 const unsigned char *searchName, const unsigned char *ea_name,
6110 char *EAData, size_t buf_size,
6111 const struct nls_table *nls_codepage, int remap)
6113 /* BB assumes one setup word */
6114 TRANSACTION2_QPI_REQ *pSMB = NULL;
6115 TRANSACTION2_QPI_RSP *pSMBr = NULL;
6119 struct fealist *ea_response_data;
6120 struct fea *temp_fea;
6123 __u16 params, byte_count, data_offset;
6124 unsigned int ea_name_len = ea_name ? strlen(ea_name) : 0;
6126 cFYI(1, "In Query All EAs path %s", searchName);
6128 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
6133 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
6135 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
6136 PATH_MAX, nls_codepage, remap);
6137 list_len++; /* trailing null */
6139 } else { /* BB improve the check for buffer overruns BB */
6140 list_len = strnlen(searchName, PATH_MAX);
6141 list_len++; /* trailing null */
6142 strncpy(pSMB->FileName, searchName, list_len);
6145 params = 2 /* level */ + 4 /* reserved */ + list_len /* includes NUL */;
6146 pSMB->TotalDataCount = 0;
6147 pSMB->MaxParameterCount = cpu_to_le16(2);
6148 /* BB find exact max SMB PDU from sess structure BB */
6149 pSMB->MaxDataCount = cpu_to_le16(CIFSMaxBufSize);
6150 pSMB->MaxSetupCount = 0;
6154 pSMB->Reserved2 = 0;
6155 pSMB->ParameterOffset = cpu_to_le16(offsetof(
6156 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
6157 pSMB->DataCount = 0;
6158 pSMB->DataOffset = 0;
6159 pSMB->SetupCount = 1;
6160 pSMB->Reserved3 = 0;
6161 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
6162 byte_count = params + 1 /* pad */ ;
6163 pSMB->TotalParameterCount = cpu_to_le16(params);
6164 pSMB->ParameterCount = pSMB->TotalParameterCount;
6165 pSMB->InformationLevel = cpu_to_le16(SMB_INFO_QUERY_ALL_EAS);
6166 pSMB->Reserved4 = 0;
6167 inc_rfc1001_len(pSMB, byte_count);
6168 pSMB->ByteCount = cpu_to_le16(byte_count);
6170 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
6171 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
6173 cFYI(1, "Send error in QueryAllEAs = %d", rc);
6178 /* BB also check enough total bytes returned */
6179 /* BB we need to improve the validity checking
6180 of these trans2 responses */
6182 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
6183 if (rc || get_bcc(&pSMBr->hdr) < 4) {
6184 rc = -EIO; /* bad smb */
6188 /* check that length of list is not more than bcc */
6189 /* check that each entry does not go beyond length
6191 /* check that each element of each entry does not
6192 go beyond end of list */
6193 /* validate_trans2_offsets() */
6194 /* BB check if start of smb + data_offset > &bcc+ bcc */
6196 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
6197 ea_response_data = (struct fealist *)
6198 (((char *) &pSMBr->hdr.Protocol) + data_offset);
6200 list_len = le32_to_cpu(ea_response_data->list_len);
6201 cFYI(1, "ea length %d", list_len);
6202 if (list_len <= 8) {
6203 cFYI(1, "empty EA list returned from server");
6207 /* make sure list_len doesn't go past end of SMB */
6208 end_of_smb = (char *)pByteArea(&pSMBr->hdr) + get_bcc(&pSMBr->hdr);
6209 if ((char *)ea_response_data + list_len > end_of_smb) {
6210 cFYI(1, "EA list appears to go beyond SMB");
6215 /* account for ea list len */
6217 temp_fea = ea_response_data->list;
6218 temp_ptr = (char *)temp_fea;
6219 while (list_len > 0) {
6220 unsigned int name_len;
6225 /* make sure we can read name_len and value_len */
6227 cFYI(1, "EA entry goes beyond length of list");
6232 name_len = temp_fea->name_len;
6233 value_len = le16_to_cpu(temp_fea->value_len);
6234 list_len -= name_len + 1 + value_len;
6236 cFYI(1, "EA entry goes beyond length of list");
6242 if (ea_name_len == name_len &&
6243 memcmp(ea_name, temp_ptr, name_len) == 0) {
6244 temp_ptr += name_len + 1;
6248 if ((size_t)value_len > buf_size) {
6252 memcpy(EAData, temp_ptr, value_len);
6256 /* account for prefix user. and trailing null */
6257 rc += (5 + 1 + name_len);
6258 if (rc < (int) buf_size) {
6259 memcpy(EAData, "user.", 5);
6261 memcpy(EAData, temp_ptr, name_len);
6263 /* null terminate name */
6266 } else if (buf_size == 0) {
6267 /* skip copy - calc size only */
6269 /* stop before overrun buffer */
6274 temp_ptr += name_len + 1 + value_len;
6275 temp_fea = (struct fea *)temp_ptr;
6278 /* didn't find the named attribute */
6283 cifs_buf_release(pSMB);
6291 CIFSSMBSetEA(const int xid, struct cifs_tcon *tcon, const char *fileName,
6292 const char *ea_name, const void *ea_value,
6293 const __u16 ea_value_len, const struct nls_table *nls_codepage,
6296 struct smb_com_transaction2_spi_req *pSMB = NULL;
6297 struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
6298 struct fealist *parm_data;
6301 int bytes_returned = 0;
6302 __u16 params, param_offset, byte_count, offset, count;
6304 cFYI(1, "In SetEA");
6306 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
6311 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
6313 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
6314 PATH_MAX, nls_codepage, remap);
6315 name_len++; /* trailing null */
6317 } else { /* BB improve the check for buffer overruns BB */
6318 name_len = strnlen(fileName, PATH_MAX);
6319 name_len++; /* trailing null */
6320 strncpy(pSMB->FileName, fileName, name_len);
6323 params = 6 + name_len;
6325 /* done calculating parms using name_len of file name,
6326 now use name_len to calculate length of ea name
6327 we are going to create in the inode xattrs */
6328 if (ea_name == NULL)
6331 name_len = strnlen(ea_name, 255);
6333 count = sizeof(*parm_data) + ea_value_len + name_len;
6334 pSMB->MaxParameterCount = cpu_to_le16(2);
6335 /* BB find max SMB PDU from sess */
6336 pSMB->MaxDataCount = cpu_to_le16(1000);
6337 pSMB->MaxSetupCount = 0;
6341 pSMB->Reserved2 = 0;
6342 param_offset = offsetof(struct smb_com_transaction2_spi_req,
6343 InformationLevel) - 4;
6344 offset = param_offset + params;
6345 pSMB->InformationLevel =
6346 cpu_to_le16(SMB_SET_FILE_EA);
6349 (struct fealist *) (((char *) &pSMB->hdr.Protocol) +
6351 pSMB->ParameterOffset = cpu_to_le16(param_offset);
6352 pSMB->DataOffset = cpu_to_le16(offset);
6353 pSMB->SetupCount = 1;
6354 pSMB->Reserved3 = 0;
6355 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
6356 byte_count = 3 /* pad */ + params + count;
6357 pSMB->DataCount = cpu_to_le16(count);
6358 parm_data->list_len = cpu_to_le32(count);
6359 parm_data->list[0].EA_flags = 0;
6360 /* we checked above that name len is less than 255 */
6361 parm_data->list[0].name_len = (__u8)name_len;
6362 /* EA names are always ASCII */
6364 strncpy(parm_data->list[0].name, ea_name, name_len);
6365 parm_data->list[0].name[name_len] = 0;
6366 parm_data->list[0].value_len = cpu_to_le16(ea_value_len);
6367 /* caller ensures that ea_value_len is less than 64K but
6368 we need to ensure that it fits within the smb */
6370 /*BB add length check to see if it would fit in
6371 negotiated SMB buffer size BB */
6372 /* if (ea_value_len > buffer_size - 512 (enough for header)) */
6374 memcpy(parm_data->list[0].name+name_len+1,
6375 ea_value, ea_value_len);
6377 pSMB->TotalDataCount = pSMB->DataCount;
6378 pSMB->ParameterCount = cpu_to_le16(params);
6379 pSMB->TotalParameterCount = pSMB->ParameterCount;
6380 pSMB->Reserved4 = 0;
6381 inc_rfc1001_len(pSMB, byte_count);
6382 pSMB->ByteCount = cpu_to_le16(byte_count);
6383 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
6384 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
6386 cFYI(1, "SetPathInfo (EA) returned %d", rc);
6388 cifs_buf_release(pSMB);
6397 #ifdef CONFIG_CIFS_DNOTIFY_EXPERIMENTAL /* BB unused temporarily */
6399 * Years ago the kernel added a "dnotify" function for Samba server,
6400 * to allow network clients (such as Windows) to display updated
6401 * lists of files in directory listings automatically when
6402 * files are added by one user when another user has the
6403 * same directory open on their desktop. The Linux cifs kernel
6404 * client hooked into the kernel side of this interface for
6405 * the same reason, but ironically when the VFS moved from
6406 * "dnotify" to "inotify" it became harder to plug in Linux
6407 * network file system clients (the most obvious use case
6408 * for notify interfaces is when multiple users can update
6409 * the contents of the same directory - exactly what network
6410 * file systems can do) although the server (Samba) could
6411 * still use it. For the short term we leave the worker
6412 * function ifdeffed out (below) until inotify is fixed
6413 * in the VFS to make it easier to plug in network file
6414 * system clients. If inotify turns out to be permanently
6415 * incompatible for network fs clients, we could instead simply
6416 * expose this config flag by adding a future cifs (and smb2) notify ioctl.
6418 int CIFSSMBNotify(const int xid, struct cifs_tcon *tcon,
6419 const int notify_subdirs, const __u16 netfid,
6420 __u32 filter, struct file *pfile, int multishot,
6421 const struct nls_table *nls_codepage)
6424 struct smb_com_transaction_change_notify_req *pSMB = NULL;
6425 struct smb_com_ntransaction_change_notify_rsp *pSMBr = NULL;
6426 struct dir_notify_req *dnotify_req;
6429 cFYI(1, "In CIFSSMBNotify for file handle %d", (int)netfid);
6430 rc = smb_init(SMB_COM_NT_TRANSACT, 23, tcon, (void **) &pSMB,
6435 pSMB->TotalParameterCount = 0 ;
6436 pSMB->TotalDataCount = 0;
6437 pSMB->MaxParameterCount = cpu_to_le32(2);
6438 pSMB->MaxDataCount = cpu_to_le32(CIFSMaxBufSize & 0xFFFFFF00);
6439 pSMB->MaxSetupCount = 4;
6441 pSMB->ParameterOffset = 0;
6442 pSMB->DataCount = 0;
6443 pSMB->DataOffset = 0;
6444 pSMB->SetupCount = 4; /* single byte does not need le conversion */
6445 pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_NOTIFY_CHANGE);
6446 pSMB->ParameterCount = pSMB->TotalParameterCount;
6448 pSMB->WatchTree = 1; /* one byte - no le conversion needed */
6449 pSMB->Reserved2 = 0;
6450 pSMB->CompletionFilter = cpu_to_le32(filter);
6451 pSMB->Fid = netfid; /* file handle always le */
6452 pSMB->ByteCount = 0;
6454 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
6455 (struct smb_hdr *)pSMBr, &bytes_returned,
6458 cFYI(1, "Error in Notify = %d", rc);
6460 /* Add file to outstanding requests */
6461 /* BB change to kmem cache alloc */
6462 dnotify_req = kmalloc(
6463 sizeof(struct dir_notify_req),
6466 dnotify_req->Pid = pSMB->hdr.Pid;
6467 dnotify_req->PidHigh = pSMB->hdr.PidHigh;
6468 dnotify_req->Mid = pSMB->hdr.Mid;
6469 dnotify_req->Tid = pSMB->hdr.Tid;
6470 dnotify_req->Uid = pSMB->hdr.Uid;
6471 dnotify_req->netfid = netfid;
6472 dnotify_req->pfile = pfile;
6473 dnotify_req->filter = filter;
6474 dnotify_req->multishot = multishot;
6475 spin_lock(&GlobalMid_Lock);
6476 list_add_tail(&dnotify_req->lhead,
6477 &GlobalDnotifyReqList);
6478 spin_unlock(&GlobalMid_Lock);
6482 cifs_buf_release(pSMB);
6485 #endif /* was needed for dnotify, and will be needed for inotify when VFS fix */