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 <linux/uaccess.h>
42 #include "cifsproto.h"
43 #include "cifs_unicode.h"
44 #include "cifs_debug.h"
46 #include "smbdirect.h"
48 #ifdef CONFIG_CIFS_POSIX
53 #ifdef CONFIG_CIFS_WEAK_PW_HASH
54 {LANMAN_PROT, "\2LM1.2X002"},
55 {LANMAN2_PROT, "\2LANMAN2.1"},
56 #endif /* weak password hashing for legacy clients */
57 {CIFS_PROT, "\2NT LM 0.12"},
58 {POSIX_PROT, "\2POSIX 2"},
66 #ifdef CONFIG_CIFS_WEAK_PW_HASH
67 {LANMAN_PROT, "\2LM1.2X002"},
68 {LANMAN2_PROT, "\2LANMAN2.1"},
69 #endif /* weak password hashing for legacy clients */
70 {CIFS_PROT, "\2NT LM 0.12"},
75 /* define the number of elements in the cifs dialect array */
76 #ifdef CONFIG_CIFS_POSIX
77 #ifdef CONFIG_CIFS_WEAK_PW_HASH
78 #define CIFS_NUM_PROT 4
80 #define CIFS_NUM_PROT 2
81 #endif /* CIFS_WEAK_PW_HASH */
83 #ifdef CONFIG_CIFS_WEAK_PW_HASH
84 #define CIFS_NUM_PROT 3
86 #define CIFS_NUM_PROT 1
87 #endif /* CONFIG_CIFS_WEAK_PW_HASH */
88 #endif /* CIFS_POSIX */
91 * Mark as invalid, all open files on tree connections since they
92 * were closed when session to server was lost.
95 cifs_mark_open_files_invalid(struct cifs_tcon *tcon)
97 struct cifsFileInfo *open_file = NULL;
98 struct list_head *tmp;
99 struct list_head *tmp1;
101 /* list all files open on tree connection and mark them invalid */
102 spin_lock(&tcon->open_file_lock);
103 list_for_each_safe(tmp, tmp1, &tcon->openFileList) {
104 open_file = list_entry(tmp, struct cifsFileInfo, tlist);
105 open_file->invalidHandle = true;
106 open_file->oplock_break_cancelled = true;
108 spin_unlock(&tcon->open_file_lock);
110 * BB Add call to invalidate_inodes(sb) for all superblocks mounted
115 /* reconnect the socket, tcon, and smb session if needed */
117 cifs_reconnect_tcon(struct cifs_tcon *tcon, int smb_command)
120 struct cifs_ses *ses;
121 struct TCP_Server_Info *server;
122 struct nls_table *nls_codepage;
125 * SMBs NegProt, SessSetup, uLogoff do not have tcon yet so check for
126 * tcp and smb session status done differently for those three - in the
133 server = ses->server;
136 * only tree disconnect, open, and write, (and ulogoff which does not
137 * have tcon) are allowed as we start force umount
139 if (tcon->tidStatus == CifsExiting) {
140 if (smb_command != SMB_COM_WRITE_ANDX &&
141 smb_command != SMB_COM_OPEN_ANDX &&
142 smb_command != SMB_COM_TREE_DISCONNECT) {
143 cifs_dbg(FYI, "can not send cmd %d while umounting\n",
150 * Give demultiplex thread up to 10 seconds to reconnect, should be
151 * greater than cifs socket timeout which is 7 seconds
153 while (server->tcpStatus == CifsNeedReconnect) {
154 wait_event_interruptible_timeout(server->response_q,
155 (server->tcpStatus != CifsNeedReconnect), 10 * HZ);
157 /* are we still trying to reconnect? */
158 if (server->tcpStatus != CifsNeedReconnect)
162 * on "soft" mounts we wait once. Hard mounts keep
163 * retrying until process is killed or server comes
167 cifs_dbg(FYI, "gave up waiting on reconnect in smb_init\n");
172 if (!ses->need_reconnect && !tcon->need_reconnect)
175 nls_codepage = load_nls_default();
178 * need to prevent multiple threads trying to simultaneously
179 * reconnect the same SMB session
181 mutex_lock(&ses->session_mutex);
184 * Recheck after acquire mutex. If another thread is negotiating
185 * and the server never sends an answer the socket will be closed
186 * and tcpStatus set to reconnect.
188 if (server->tcpStatus == CifsNeedReconnect) {
190 mutex_unlock(&ses->session_mutex);
194 rc = cifs_negotiate_protocol(0, ses);
195 if (rc == 0 && ses->need_reconnect)
196 rc = cifs_setup_session(0, ses, nls_codepage);
198 /* do we need to reconnect tcon? */
199 if (rc || !tcon->need_reconnect) {
200 mutex_unlock(&ses->session_mutex);
204 cifs_mark_open_files_invalid(tcon);
205 rc = CIFSTCon(0, ses, tcon->treeName, tcon, nls_codepage);
206 mutex_unlock(&ses->session_mutex);
207 cifs_dbg(FYI, "reconnect tcon rc = %d\n", rc);
212 atomic_inc(&tconInfoReconnectCount);
214 /* tell server Unix caps we support */
215 if (ses->capabilities & CAP_UNIX)
216 reset_cifs_unix_caps(0, tcon, NULL, NULL);
219 * Removed call to reopen open files here. It is safer (and faster) to
220 * reopen files one at a time as needed in read and write.
222 * FIXME: what about file locks? don't we need to reclaim them ASAP?
227 * Check if handle based operation so we know whether we can continue
228 * or not without returning to caller to reset file handle
230 switch (smb_command) {
231 case SMB_COM_READ_ANDX:
232 case SMB_COM_WRITE_ANDX:
234 case SMB_COM_FIND_CLOSE2:
235 case SMB_COM_LOCKING_ANDX:
239 unload_nls(nls_codepage);
243 /* Allocate and return pointer to an SMB request buffer, and set basic
244 SMB information in the SMB header. If the return code is zero, this
245 function must have filled in request_buf pointer */
247 small_smb_init(int smb_command, int wct, struct cifs_tcon *tcon,
252 rc = cifs_reconnect_tcon(tcon, smb_command);
256 *request_buf = cifs_small_buf_get();
257 if (*request_buf == NULL) {
258 /* BB should we add a retry in here if not a writepage? */
262 header_assemble((struct smb_hdr *) *request_buf, smb_command,
266 cifs_stats_inc(&tcon->num_smbs_sent);
272 small_smb_init_no_tc(const int smb_command, const int wct,
273 struct cifs_ses *ses, void **request_buf)
276 struct smb_hdr *buffer;
278 rc = small_smb_init(smb_command, wct, NULL, request_buf);
282 buffer = (struct smb_hdr *)*request_buf;
283 buffer->Mid = get_next_mid(ses->server);
284 if (ses->capabilities & CAP_UNICODE)
285 buffer->Flags2 |= SMBFLG2_UNICODE;
286 if (ses->capabilities & CAP_STATUS32)
287 buffer->Flags2 |= SMBFLG2_ERR_STATUS;
289 /* uid, tid can stay at zero as set in header assemble */
291 /* BB add support for turning on the signing when
292 this function is used after 1st of session setup requests */
297 /* If the return code is zero, this function must fill in request_buf pointer */
299 __smb_init(int smb_command, int wct, struct cifs_tcon *tcon,
300 void **request_buf, void **response_buf)
302 *request_buf = cifs_buf_get();
303 if (*request_buf == NULL) {
304 /* BB should we add a retry in here if not a writepage? */
307 /* Although the original thought was we needed the response buf for */
308 /* potential retries of smb operations it turns out we can determine */
309 /* from the mid flags when the request buffer can be resent without */
310 /* having to use a second distinct buffer for the response */
312 *response_buf = *request_buf;
314 header_assemble((struct smb_hdr *) *request_buf, smb_command, tcon,
318 cifs_stats_inc(&tcon->num_smbs_sent);
323 /* If the return code is zero, this function must fill in request_buf pointer */
325 smb_init(int smb_command, int wct, struct cifs_tcon *tcon,
326 void **request_buf, void **response_buf)
330 rc = cifs_reconnect_tcon(tcon, smb_command);
334 return __smb_init(smb_command, wct, tcon, request_buf, response_buf);
338 smb_init_no_reconnect(int smb_command, int wct, struct cifs_tcon *tcon,
339 void **request_buf, void **response_buf)
341 if (tcon->ses->need_reconnect || tcon->need_reconnect)
344 return __smb_init(smb_command, wct, tcon, request_buf, response_buf);
347 static int validate_t2(struct smb_t2_rsp *pSMB)
349 unsigned int total_size;
351 /* check for plausible wct */
352 if (pSMB->hdr.WordCount < 10)
355 /* check for parm and data offset going beyond end of smb */
356 if (get_unaligned_le16(&pSMB->t2_rsp.ParameterOffset) > 1024 ||
357 get_unaligned_le16(&pSMB->t2_rsp.DataOffset) > 1024)
360 total_size = get_unaligned_le16(&pSMB->t2_rsp.ParameterCount);
361 if (total_size >= 512)
364 /* check that bcc is at least as big as parms + data, and that it is
365 * less than negotiated smb buffer
367 total_size += get_unaligned_le16(&pSMB->t2_rsp.DataCount);
368 if (total_size > get_bcc(&pSMB->hdr) ||
369 total_size >= CIFSMaxBufSize + MAX_CIFS_HDR_SIZE)
374 cifs_dump_mem("Invalid transact2 SMB: ", (char *)pSMB,
375 sizeof(struct smb_t2_rsp) + 16);
380 decode_ext_sec_blob(struct cifs_ses *ses, NEGOTIATE_RSP *pSMBr)
384 char *guid = pSMBr->u.extended_response.GUID;
385 struct TCP_Server_Info *server = ses->server;
387 count = get_bcc(&pSMBr->hdr);
388 if (count < SMB1_CLIENT_GUID_SIZE)
391 spin_lock(&cifs_tcp_ses_lock);
392 if (server->srv_count > 1) {
393 spin_unlock(&cifs_tcp_ses_lock);
394 if (memcmp(server->server_GUID, guid, SMB1_CLIENT_GUID_SIZE) != 0) {
395 cifs_dbg(FYI, "server UID changed\n");
396 memcpy(server->server_GUID, guid, SMB1_CLIENT_GUID_SIZE);
399 spin_unlock(&cifs_tcp_ses_lock);
400 memcpy(server->server_GUID, guid, SMB1_CLIENT_GUID_SIZE);
403 if (count == SMB1_CLIENT_GUID_SIZE) {
404 server->sec_ntlmssp = true;
406 count -= SMB1_CLIENT_GUID_SIZE;
407 rc = decode_negTokenInit(
408 pSMBr->u.extended_response.SecurityBlob, count, server);
417 cifs_enable_signing(struct TCP_Server_Info *server, bool mnt_sign_required)
419 bool srv_sign_required = server->sec_mode & server->vals->signing_required;
420 bool srv_sign_enabled = server->sec_mode & server->vals->signing_enabled;
421 bool mnt_sign_enabled = global_secflags & CIFSSEC_MAY_SIGN;
424 * Is signing required by mnt options? If not then check
425 * global_secflags to see if it is there.
427 if (!mnt_sign_required)
428 mnt_sign_required = ((global_secflags & CIFSSEC_MUST_SIGN) ==
432 * If signing is required then it's automatically enabled too,
433 * otherwise, check to see if the secflags allow it.
435 mnt_sign_enabled = mnt_sign_required ? mnt_sign_required :
436 (global_secflags & CIFSSEC_MAY_SIGN);
438 /* If server requires signing, does client allow it? */
439 if (srv_sign_required) {
440 if (!mnt_sign_enabled) {
441 cifs_dbg(VFS, "Server requires signing, but it's disabled in SecurityFlags!");
447 /* If client requires signing, does server allow it? */
448 if (mnt_sign_required) {
449 if (!srv_sign_enabled) {
450 cifs_dbg(VFS, "Server does not support signing!");
459 #ifdef CONFIG_CIFS_WEAK_PW_HASH
461 decode_lanman_negprot_rsp(struct TCP_Server_Info *server, NEGOTIATE_RSP *pSMBr)
464 struct lanman_neg_rsp *rsp = (struct lanman_neg_rsp *)pSMBr;
466 if (server->dialect != LANMAN_PROT && server->dialect != LANMAN2_PROT)
469 server->sec_mode = le16_to_cpu(rsp->SecurityMode);
470 server->maxReq = min_t(unsigned int,
471 le16_to_cpu(rsp->MaxMpxCount),
473 set_credits(server, server->maxReq);
474 server->maxBuf = le16_to_cpu(rsp->MaxBufSize);
475 /* even though we do not use raw we might as well set this
476 accurately, in case we ever find a need for it */
477 if ((le16_to_cpu(rsp->RawMode) & RAW_ENABLE) == RAW_ENABLE) {
478 server->max_rw = 0xFF00;
479 server->capabilities = CAP_MPX_MODE | CAP_RAW_MODE;
481 server->max_rw = 0;/* do not need to use raw anyway */
482 server->capabilities = CAP_MPX_MODE;
484 tmp = (__s16)le16_to_cpu(rsp->ServerTimeZone);
486 /* OS/2 often does not set timezone therefore
487 * we must use server time to calc time zone.
488 * Could deviate slightly from the right zone.
489 * Smallest defined timezone difference is 15 minutes
490 * (i.e. Nepal). Rounding up/down is done to match
493 int val, seconds, remain, result;
495 unsigned long utc = ktime_get_real_seconds();
496 ts = cnvrtDosUnixTm(rsp->SrvTime.Date,
497 rsp->SrvTime.Time, 0);
498 cifs_dbg(FYI, "SrvTime %d sec since 1970 (utc: %d) diff: %d\n",
499 (int)ts.tv_sec, (int)utc,
500 (int)(utc - ts.tv_sec));
501 val = (int)(utc - ts.tv_sec);
503 result = (seconds / MIN_TZ_ADJ) * MIN_TZ_ADJ;
504 remain = seconds % MIN_TZ_ADJ;
505 if (remain >= (MIN_TZ_ADJ / 2))
506 result += MIN_TZ_ADJ;
509 server->timeAdj = result;
511 server->timeAdj = (int)tmp;
512 server->timeAdj *= 60; /* also in seconds */
514 cifs_dbg(FYI, "server->timeAdj: %d seconds\n", server->timeAdj);
517 /* BB get server time for time conversions and add
518 code to use it and timezone since this is not UTC */
520 if (rsp->EncryptionKeyLength ==
521 cpu_to_le16(CIFS_CRYPTO_KEY_SIZE)) {
522 memcpy(server->cryptkey, rsp->EncryptionKey,
523 CIFS_CRYPTO_KEY_SIZE);
524 } else if (server->sec_mode & SECMODE_PW_ENCRYPT) {
525 return -EIO; /* need cryptkey unless plain text */
528 cifs_dbg(FYI, "LANMAN negotiated\n");
533 decode_lanman_negprot_rsp(struct TCP_Server_Info *server, NEGOTIATE_RSP *pSMBr)
535 cifs_dbg(VFS, "mount failed, cifs module not built with CIFS_WEAK_PW_HASH support\n");
541 should_set_ext_sec_flag(enum securityEnum sectype)
548 if (global_secflags &
549 (CIFSSEC_MAY_KRB5 | CIFSSEC_MAY_NTLMSSP))
558 CIFSSMBNegotiate(const unsigned int xid, struct cifs_ses *ses)
561 NEGOTIATE_RSP *pSMBr;
565 struct TCP_Server_Info *server = ses->server;
569 WARN(1, "%s: server is NULL!\n", __func__);
573 rc = smb_init(SMB_COM_NEGOTIATE, 0, NULL /* no tcon yet */ ,
574 (void **) &pSMB, (void **) &pSMBr);
578 pSMB->hdr.Mid = get_next_mid(server);
579 pSMB->hdr.Flags2 |= (SMBFLG2_UNICODE | SMBFLG2_ERR_STATUS);
581 if (should_set_ext_sec_flag(ses->sectype)) {
582 cifs_dbg(FYI, "Requesting extended security.");
583 pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC;
587 for (i = 0; i < CIFS_NUM_PROT; i++) {
588 strncpy(pSMB->DialectsArray+count, protocols[i].name, 16);
589 count += strlen(protocols[i].name) + 1;
590 /* null at end of source and target buffers anyway */
592 inc_rfc1001_len(pSMB, count);
593 pSMB->ByteCount = cpu_to_le16(count);
595 rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB,
596 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
600 server->dialect = le16_to_cpu(pSMBr->DialectIndex);
601 cifs_dbg(FYI, "Dialect: %d\n", server->dialect);
602 /* Check wct = 1 error case */
603 if ((pSMBr->hdr.WordCount < 13) || (server->dialect == BAD_PROT)) {
604 /* core returns wct = 1, but we do not ask for core - otherwise
605 small wct just comes when dialect index is -1 indicating we
606 could not negotiate a common dialect */
609 } else if (pSMBr->hdr.WordCount == 13) {
610 server->negflavor = CIFS_NEGFLAVOR_LANMAN;
611 rc = decode_lanman_negprot_rsp(server, pSMBr);
613 } else if (pSMBr->hdr.WordCount != 17) {
618 /* else wct == 17, NTLM or better */
620 server->sec_mode = pSMBr->SecurityMode;
621 if ((server->sec_mode & SECMODE_USER) == 0)
622 cifs_dbg(FYI, "share mode security\n");
624 /* one byte, so no need to convert this or EncryptionKeyLen from
626 server->maxReq = min_t(unsigned int, le16_to_cpu(pSMBr->MaxMpxCount),
628 set_credits(server, server->maxReq);
629 /* probably no need to store and check maxvcs */
630 server->maxBuf = le32_to_cpu(pSMBr->MaxBufferSize);
631 server->max_rw = le32_to_cpu(pSMBr->MaxRawSize);
632 cifs_dbg(NOISY, "Max buf = %d\n", ses->server->maxBuf);
633 server->capabilities = le32_to_cpu(pSMBr->Capabilities);
634 server->timeAdj = (int)(__s16)le16_to_cpu(pSMBr->ServerTimeZone);
635 server->timeAdj *= 60;
637 if (pSMBr->EncryptionKeyLength == CIFS_CRYPTO_KEY_SIZE) {
638 server->negflavor = CIFS_NEGFLAVOR_UNENCAP;
639 memcpy(ses->server->cryptkey, pSMBr->u.EncryptionKey,
640 CIFS_CRYPTO_KEY_SIZE);
641 } else if (pSMBr->hdr.Flags2 & SMBFLG2_EXT_SEC ||
642 server->capabilities & CAP_EXTENDED_SECURITY) {
643 server->negflavor = CIFS_NEGFLAVOR_EXTENDED;
644 rc = decode_ext_sec_blob(ses, pSMBr);
645 } else if (server->sec_mode & SECMODE_PW_ENCRYPT) {
646 rc = -EIO; /* no crypt key only if plain text pwd */
648 server->negflavor = CIFS_NEGFLAVOR_UNENCAP;
649 server->capabilities &= ~CAP_EXTENDED_SECURITY;
654 rc = cifs_enable_signing(server, ses->sign);
656 cifs_buf_release(pSMB);
658 cifs_dbg(FYI, "negprot rc %d\n", rc);
663 CIFSSMBTDis(const unsigned int xid, struct cifs_tcon *tcon)
665 struct smb_hdr *smb_buffer;
668 cifs_dbg(FYI, "In tree disconnect\n");
670 /* BB: do we need to check this? These should never be NULL. */
671 if ((tcon->ses == NULL) || (tcon->ses->server == NULL))
675 * No need to return error on this operation if tid invalidated and
676 * closed on server already e.g. due to tcp session crashing. Also,
677 * the tcon is no longer on the list, so no need to take lock before
680 if ((tcon->need_reconnect) || (tcon->ses->need_reconnect))
683 rc = small_smb_init(SMB_COM_TREE_DISCONNECT, 0, tcon,
684 (void **)&smb_buffer);
688 rc = SendReceiveNoRsp(xid, tcon->ses, (char *)smb_buffer, 0);
689 cifs_small_buf_release(smb_buffer);
691 cifs_dbg(FYI, "Tree disconnect failed %d\n", rc);
693 /* No need to return error on this operation if tid invalidated and
694 closed on server already e.g. due to tcp session crashing */
702 * This is a no-op for now. We're not really interested in the reply, but
703 * rather in the fact that the server sent one and that server->lstrp
706 * FIXME: maybe we should consider checking that the reply matches request?
709 cifs_echo_callback(struct mid_q_entry *mid)
711 struct TCP_Server_Info *server = mid->callback_data;
713 DeleteMidQEntry(mid);
714 add_credits(server, 1, CIFS_ECHO_OP);
718 CIFSSMBEcho(struct TCP_Server_Info *server)
723 struct smb_rqst rqst = { .rq_iov = iov,
726 cifs_dbg(FYI, "In echo request\n");
728 rc = small_smb_init(SMB_COM_ECHO, 0, NULL, (void **)&smb);
732 if (server->capabilities & CAP_UNICODE)
733 smb->hdr.Flags2 |= SMBFLG2_UNICODE;
735 /* set up echo request */
736 smb->hdr.Tid = 0xffff;
737 smb->hdr.WordCount = 1;
738 put_unaligned_le16(1, &smb->EchoCount);
739 put_bcc(1, &smb->hdr);
741 inc_rfc1001_len(smb, 3);
744 iov[0].iov_base = smb;
745 iov[1].iov_len = get_rfc1002_length(smb);
746 iov[1].iov_base = (char *)smb + 4;
748 rc = cifs_call_async(server, &rqst, NULL, cifs_echo_callback, NULL,
749 server, CIFS_ASYNC_OP | CIFS_ECHO_OP);
751 cifs_dbg(FYI, "Echo request failed: %d\n", rc);
753 cifs_small_buf_release(smb);
759 CIFSSMBLogoff(const unsigned int xid, struct cifs_ses *ses)
761 LOGOFF_ANDX_REQ *pSMB;
764 cifs_dbg(FYI, "In SMBLogoff for session disconnect\n");
767 * BB: do we need to check validity of ses and server? They should
768 * always be valid since we have an active reference. If not, that
769 * should probably be a BUG()
771 if (!ses || !ses->server)
774 mutex_lock(&ses->session_mutex);
775 if (ses->need_reconnect)
776 goto session_already_dead; /* no need to send SMBlogoff if uid
777 already closed due to reconnect */
778 rc = small_smb_init(SMB_COM_LOGOFF_ANDX, 2, NULL, (void **)&pSMB);
780 mutex_unlock(&ses->session_mutex);
784 pSMB->hdr.Mid = get_next_mid(ses->server);
786 if (ses->server->sign)
787 pSMB->hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
789 pSMB->hdr.Uid = ses->Suid;
791 pSMB->AndXCommand = 0xFF;
792 rc = SendReceiveNoRsp(xid, ses, (char *) pSMB, 0);
793 cifs_small_buf_release(pSMB);
794 session_already_dead:
795 mutex_unlock(&ses->session_mutex);
797 /* if session dead then we do not need to do ulogoff,
798 since server closed smb session, no sense reporting
806 CIFSPOSIXDelFile(const unsigned int xid, struct cifs_tcon *tcon,
807 const char *fileName, __u16 type,
808 const struct nls_table *nls_codepage, int remap)
810 TRANSACTION2_SPI_REQ *pSMB = NULL;
811 TRANSACTION2_SPI_RSP *pSMBr = NULL;
812 struct unlink_psx_rq *pRqD;
815 int bytes_returned = 0;
816 __u16 params, param_offset, offset, byte_count;
818 cifs_dbg(FYI, "In POSIX delete\n");
820 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
825 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
827 cifsConvertToUTF16((__le16 *) pSMB->FileName, fileName,
828 PATH_MAX, nls_codepage, remap);
829 name_len++; /* trailing null */
831 } else { /* BB add path length overrun check */
832 name_len = strnlen(fileName, PATH_MAX);
833 name_len++; /* trailing null */
834 strncpy(pSMB->FileName, fileName, name_len);
837 params = 6 + name_len;
838 pSMB->MaxParameterCount = cpu_to_le16(2);
839 pSMB->MaxDataCount = 0; /* BB double check this with jra */
840 pSMB->MaxSetupCount = 0;
845 param_offset = offsetof(struct smb_com_transaction2_spi_req,
846 InformationLevel) - 4;
847 offset = param_offset + params;
849 /* Setup pointer to Request Data (inode type) */
850 pRqD = (struct unlink_psx_rq *)(((char *)&pSMB->hdr.Protocol) + offset);
851 pRqD->type = cpu_to_le16(type);
852 pSMB->ParameterOffset = cpu_to_le16(param_offset);
853 pSMB->DataOffset = cpu_to_le16(offset);
854 pSMB->SetupCount = 1;
856 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
857 byte_count = 3 /* pad */ + params + sizeof(struct unlink_psx_rq);
859 pSMB->DataCount = cpu_to_le16(sizeof(struct unlink_psx_rq));
860 pSMB->TotalDataCount = cpu_to_le16(sizeof(struct unlink_psx_rq));
861 pSMB->ParameterCount = cpu_to_le16(params);
862 pSMB->TotalParameterCount = pSMB->ParameterCount;
863 pSMB->InformationLevel = cpu_to_le16(SMB_POSIX_UNLINK);
865 inc_rfc1001_len(pSMB, byte_count);
866 pSMB->ByteCount = cpu_to_le16(byte_count);
867 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
868 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
870 cifs_dbg(FYI, "Posix delete returned %d\n", rc);
871 cifs_buf_release(pSMB);
873 cifs_stats_inc(&tcon->stats.cifs_stats.num_deletes);
882 CIFSSMBDelFile(const unsigned int xid, struct cifs_tcon *tcon, const char *name,
883 struct cifs_sb_info *cifs_sb)
885 DELETE_FILE_REQ *pSMB = NULL;
886 DELETE_FILE_RSP *pSMBr = NULL;
890 int remap = cifs_remap(cifs_sb);
893 rc = smb_init(SMB_COM_DELETE, 1, tcon, (void **) &pSMB,
898 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
899 name_len = cifsConvertToUTF16((__le16 *) pSMB->fileName, name,
900 PATH_MAX, cifs_sb->local_nls,
902 name_len++; /* trailing null */
904 } else { /* BB improve check for buffer overruns BB */
905 name_len = strnlen(name, PATH_MAX);
906 name_len++; /* trailing null */
907 strncpy(pSMB->fileName, name, name_len);
909 pSMB->SearchAttributes =
910 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM);
911 pSMB->BufferFormat = 0x04;
912 inc_rfc1001_len(pSMB, name_len + 1);
913 pSMB->ByteCount = cpu_to_le16(name_len + 1);
914 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
915 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
916 cifs_stats_inc(&tcon->stats.cifs_stats.num_deletes);
918 cifs_dbg(FYI, "Error in RMFile = %d\n", rc);
920 cifs_buf_release(pSMB);
928 CIFSSMBRmDir(const unsigned int xid, struct cifs_tcon *tcon, const char *name,
929 struct cifs_sb_info *cifs_sb)
931 DELETE_DIRECTORY_REQ *pSMB = NULL;
932 DELETE_DIRECTORY_RSP *pSMBr = NULL;
936 int remap = cifs_remap(cifs_sb);
938 cifs_dbg(FYI, "In CIFSSMBRmDir\n");
940 rc = smb_init(SMB_COM_DELETE_DIRECTORY, 0, tcon, (void **) &pSMB,
945 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
946 name_len = cifsConvertToUTF16((__le16 *) pSMB->DirName, name,
947 PATH_MAX, cifs_sb->local_nls,
949 name_len++; /* trailing null */
951 } else { /* BB improve check for buffer overruns BB */
952 name_len = strnlen(name, PATH_MAX);
953 name_len++; /* trailing null */
954 strncpy(pSMB->DirName, name, name_len);
957 pSMB->BufferFormat = 0x04;
958 inc_rfc1001_len(pSMB, name_len + 1);
959 pSMB->ByteCount = cpu_to_le16(name_len + 1);
960 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
961 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
962 cifs_stats_inc(&tcon->stats.cifs_stats.num_rmdirs);
964 cifs_dbg(FYI, "Error in RMDir = %d\n", rc);
966 cifs_buf_release(pSMB);
973 CIFSSMBMkDir(const unsigned int xid, struct cifs_tcon *tcon, const char *name,
974 struct cifs_sb_info *cifs_sb)
977 CREATE_DIRECTORY_REQ *pSMB = NULL;
978 CREATE_DIRECTORY_RSP *pSMBr = NULL;
981 int remap = cifs_remap(cifs_sb);
983 cifs_dbg(FYI, "In CIFSSMBMkDir\n");
985 rc = smb_init(SMB_COM_CREATE_DIRECTORY, 0, tcon, (void **) &pSMB,
990 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
991 name_len = cifsConvertToUTF16((__le16 *) pSMB->DirName, name,
992 PATH_MAX, cifs_sb->local_nls,
994 name_len++; /* trailing null */
996 } else { /* BB improve check for buffer overruns BB */
997 name_len = strnlen(name, PATH_MAX);
998 name_len++; /* trailing null */
999 strncpy(pSMB->DirName, name, name_len);
1002 pSMB->BufferFormat = 0x04;
1003 inc_rfc1001_len(pSMB, name_len + 1);
1004 pSMB->ByteCount = cpu_to_le16(name_len + 1);
1005 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1006 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1007 cifs_stats_inc(&tcon->stats.cifs_stats.num_mkdirs);
1009 cifs_dbg(FYI, "Error in Mkdir = %d\n", rc);
1011 cifs_buf_release(pSMB);
1018 CIFSPOSIXCreate(const unsigned int xid, struct cifs_tcon *tcon,
1019 __u32 posix_flags, __u64 mode, __u16 *netfid,
1020 FILE_UNIX_BASIC_INFO *pRetData, __u32 *pOplock,
1021 const char *name, const struct nls_table *nls_codepage,
1024 TRANSACTION2_SPI_REQ *pSMB = NULL;
1025 TRANSACTION2_SPI_RSP *pSMBr = NULL;
1028 int bytes_returned = 0;
1029 __u16 params, param_offset, offset, byte_count, count;
1030 OPEN_PSX_REQ *pdata;
1031 OPEN_PSX_RSP *psx_rsp;
1033 cifs_dbg(FYI, "In POSIX Create\n");
1035 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
1040 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1042 cifsConvertToUTF16((__le16 *) pSMB->FileName, name,
1043 PATH_MAX, nls_codepage, remap);
1044 name_len++; /* trailing null */
1046 } else { /* BB improve the check for buffer overruns BB */
1047 name_len = strnlen(name, PATH_MAX);
1048 name_len++; /* trailing null */
1049 strncpy(pSMB->FileName, name, name_len);
1052 params = 6 + name_len;
1053 count = sizeof(OPEN_PSX_REQ);
1054 pSMB->MaxParameterCount = cpu_to_le16(2);
1055 pSMB->MaxDataCount = cpu_to_le16(1000); /* large enough */
1056 pSMB->MaxSetupCount = 0;
1060 pSMB->Reserved2 = 0;
1061 param_offset = offsetof(struct smb_com_transaction2_spi_req,
1062 InformationLevel) - 4;
1063 offset = param_offset + params;
1064 pdata = (OPEN_PSX_REQ *)(((char *)&pSMB->hdr.Protocol) + offset);
1065 pdata->Level = cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC);
1066 pdata->Permissions = cpu_to_le64(mode);
1067 pdata->PosixOpenFlags = cpu_to_le32(posix_flags);
1068 pdata->OpenFlags = cpu_to_le32(*pOplock);
1069 pSMB->ParameterOffset = cpu_to_le16(param_offset);
1070 pSMB->DataOffset = cpu_to_le16(offset);
1071 pSMB->SetupCount = 1;
1072 pSMB->Reserved3 = 0;
1073 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
1074 byte_count = 3 /* pad */ + params + count;
1076 pSMB->DataCount = cpu_to_le16(count);
1077 pSMB->ParameterCount = cpu_to_le16(params);
1078 pSMB->TotalDataCount = pSMB->DataCount;
1079 pSMB->TotalParameterCount = pSMB->ParameterCount;
1080 pSMB->InformationLevel = cpu_to_le16(SMB_POSIX_OPEN);
1081 pSMB->Reserved4 = 0;
1082 inc_rfc1001_len(pSMB, byte_count);
1083 pSMB->ByteCount = cpu_to_le16(byte_count);
1084 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1085 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1087 cifs_dbg(FYI, "Posix create returned %d\n", rc);
1088 goto psx_create_err;
1091 cifs_dbg(FYI, "copying inode info\n");
1092 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
1094 if (rc || get_bcc(&pSMBr->hdr) < sizeof(OPEN_PSX_RSP)) {
1095 rc = -EIO; /* bad smb */
1096 goto psx_create_err;
1099 /* copy return information to pRetData */
1100 psx_rsp = (OPEN_PSX_RSP *)((char *) &pSMBr->hdr.Protocol
1101 + le16_to_cpu(pSMBr->t2.DataOffset));
1103 *pOplock = le16_to_cpu(psx_rsp->OplockFlags);
1105 *netfid = psx_rsp->Fid; /* cifs fid stays in le */
1106 /* Let caller know file was created so we can set the mode. */
1107 /* Do we care about the CreateAction in any other cases? */
1108 if (cpu_to_le32(FILE_CREATE) == psx_rsp->CreateAction)
1109 *pOplock |= CIFS_CREATE_ACTION;
1110 /* check to make sure response data is there */
1111 if (psx_rsp->ReturnedLevel != cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC)) {
1112 pRetData->Type = cpu_to_le32(-1); /* unknown */
1113 cifs_dbg(NOISY, "unknown type\n");
1115 if (get_bcc(&pSMBr->hdr) < sizeof(OPEN_PSX_RSP)
1116 + sizeof(FILE_UNIX_BASIC_INFO)) {
1117 cifs_dbg(VFS, "Open response data too small\n");
1118 pRetData->Type = cpu_to_le32(-1);
1119 goto psx_create_err;
1121 memcpy((char *) pRetData,
1122 (char *)psx_rsp + sizeof(OPEN_PSX_RSP),
1123 sizeof(FILE_UNIX_BASIC_INFO));
1127 cifs_buf_release(pSMB);
1129 if (posix_flags & SMB_O_DIRECTORY)
1130 cifs_stats_inc(&tcon->stats.cifs_stats.num_posixmkdirs);
1132 cifs_stats_inc(&tcon->stats.cifs_stats.num_posixopens);
1140 static __u16 convert_disposition(int disposition)
1144 switch (disposition) {
1145 case FILE_SUPERSEDE:
1146 ofun = SMBOPEN_OCREATE | SMBOPEN_OTRUNC;
1149 ofun = SMBOPEN_OAPPEND;
1152 ofun = SMBOPEN_OCREATE;
1155 ofun = SMBOPEN_OCREATE | SMBOPEN_OAPPEND;
1157 case FILE_OVERWRITE:
1158 ofun = SMBOPEN_OTRUNC;
1160 case FILE_OVERWRITE_IF:
1161 ofun = SMBOPEN_OCREATE | SMBOPEN_OTRUNC;
1164 cifs_dbg(FYI, "unknown disposition %d\n", disposition);
1165 ofun = SMBOPEN_OAPPEND; /* regular open */
1171 access_flags_to_smbopen_mode(const int access_flags)
1173 int masked_flags = access_flags & (GENERIC_READ | GENERIC_WRITE);
1175 if (masked_flags == GENERIC_READ)
1176 return SMBOPEN_READ;
1177 else if (masked_flags == GENERIC_WRITE)
1178 return SMBOPEN_WRITE;
1180 /* just go for read/write */
1181 return SMBOPEN_READWRITE;
1185 SMBLegacyOpen(const unsigned int xid, struct cifs_tcon *tcon,
1186 const char *fileName, const int openDisposition,
1187 const int access_flags, const int create_options, __u16 *netfid,
1188 int *pOplock, FILE_ALL_INFO *pfile_info,
1189 const struct nls_table *nls_codepage, int remap)
1192 OPENX_REQ *pSMB = NULL;
1193 OPENX_RSP *pSMBr = NULL;
1199 rc = smb_init(SMB_COM_OPEN_ANDX, 15, tcon, (void **) &pSMB,
1204 pSMB->AndXCommand = 0xFF; /* none */
1206 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1207 count = 1; /* account for one byte pad to word boundary */
1209 cifsConvertToUTF16((__le16 *) (pSMB->fileName + 1),
1210 fileName, PATH_MAX, nls_codepage, remap);
1211 name_len++; /* trailing null */
1213 } else { /* BB improve check for buffer overruns BB */
1214 count = 0; /* no pad */
1215 name_len = strnlen(fileName, PATH_MAX);
1216 name_len++; /* trailing null */
1217 strncpy(pSMB->fileName, fileName, name_len);
1219 if (*pOplock & REQ_OPLOCK)
1220 pSMB->OpenFlags = cpu_to_le16(REQ_OPLOCK);
1221 else if (*pOplock & REQ_BATCHOPLOCK)
1222 pSMB->OpenFlags = cpu_to_le16(REQ_BATCHOPLOCK);
1224 pSMB->OpenFlags |= cpu_to_le16(REQ_MORE_INFO);
1225 pSMB->Mode = cpu_to_le16(access_flags_to_smbopen_mode(access_flags));
1226 pSMB->Mode |= cpu_to_le16(0x40); /* deny none */
1227 /* set file as system file if special file such
1228 as fifo and server expecting SFU style and
1229 no Unix extensions */
1231 if (create_options & CREATE_OPTION_SPECIAL)
1232 pSMB->FileAttributes = cpu_to_le16(ATTR_SYSTEM);
1233 else /* BB FIXME BB */
1234 pSMB->FileAttributes = cpu_to_le16(0/*ATTR_NORMAL*/);
1236 if (create_options & CREATE_OPTION_READONLY)
1237 pSMB->FileAttributes |= cpu_to_le16(ATTR_READONLY);
1240 /* pSMB->CreateOptions = cpu_to_le32(create_options &
1241 CREATE_OPTIONS_MASK); */
1242 /* BB FIXME END BB */
1244 pSMB->Sattr = cpu_to_le16(ATTR_HIDDEN | ATTR_SYSTEM | ATTR_DIRECTORY);
1245 pSMB->OpenFunction = cpu_to_le16(convert_disposition(openDisposition));
1247 inc_rfc1001_len(pSMB, count);
1249 pSMB->ByteCount = cpu_to_le16(count);
1250 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1251 (struct smb_hdr *)pSMBr, &bytes_returned, 0);
1252 cifs_stats_inc(&tcon->stats.cifs_stats.num_opens);
1254 cifs_dbg(FYI, "Error in Open = %d\n", rc);
1256 /* BB verify if wct == 15 */
1258 /* *pOplock = pSMBr->OplockLevel; */ /* BB take from action field*/
1260 *netfid = pSMBr->Fid; /* cifs fid stays in le */
1261 /* Let caller know file was created so we can set the mode. */
1262 /* Do we care about the CreateAction in any other cases? */
1264 /* if (cpu_to_le32(FILE_CREATE) == pSMBr->CreateAction)
1265 *pOplock |= CIFS_CREATE_ACTION; */
1269 pfile_info->CreationTime = 0; /* BB convert CreateTime*/
1270 pfile_info->LastAccessTime = 0; /* BB fixme */
1271 pfile_info->LastWriteTime = 0; /* BB fixme */
1272 pfile_info->ChangeTime = 0; /* BB fixme */
1273 pfile_info->Attributes =
1274 cpu_to_le32(le16_to_cpu(pSMBr->FileAttributes));
1275 /* the file_info buf is endian converted by caller */
1276 pfile_info->AllocationSize =
1277 cpu_to_le64(le32_to_cpu(pSMBr->EndOfFile));
1278 pfile_info->EndOfFile = pfile_info->AllocationSize;
1279 pfile_info->NumberOfLinks = cpu_to_le32(1);
1280 pfile_info->DeletePending = 0;
1284 cifs_buf_release(pSMB);
1291 CIFS_open(const unsigned int xid, struct cifs_open_parms *oparms, int *oplock,
1295 OPEN_REQ *req = NULL;
1296 OPEN_RSP *rsp = NULL;
1300 struct cifs_sb_info *cifs_sb = oparms->cifs_sb;
1301 struct cifs_tcon *tcon = oparms->tcon;
1302 int remap = cifs_remap(cifs_sb);
1303 const struct nls_table *nls = cifs_sb->local_nls;
1304 int create_options = oparms->create_options;
1305 int desired_access = oparms->desired_access;
1306 int disposition = oparms->disposition;
1307 const char *path = oparms->path;
1310 rc = smb_init(SMB_COM_NT_CREATE_ANDX, 24, tcon, (void **)&req,
1315 /* no commands go after this */
1316 req->AndXCommand = 0xFF;
1318 if (req->hdr.Flags2 & SMBFLG2_UNICODE) {
1319 /* account for one byte pad to word boundary */
1321 name_len = cifsConvertToUTF16((__le16 *)(req->fileName + 1),
1322 path, PATH_MAX, nls, remap);
1326 req->NameLength = cpu_to_le16(name_len);
1328 /* BB improve check for buffer overruns BB */
1331 name_len = strnlen(path, PATH_MAX);
1334 req->NameLength = cpu_to_le16(name_len);
1335 strncpy(req->fileName, path, name_len);
1338 if (*oplock & REQ_OPLOCK)
1339 req->OpenFlags = cpu_to_le32(REQ_OPLOCK);
1340 else if (*oplock & REQ_BATCHOPLOCK)
1341 req->OpenFlags = cpu_to_le32(REQ_BATCHOPLOCK);
1343 req->DesiredAccess = cpu_to_le32(desired_access);
1344 req->AllocationSize = 0;
1347 * Set file as system file if special file such as fifo and server
1348 * expecting SFU style and no Unix extensions.
1350 if (create_options & CREATE_OPTION_SPECIAL)
1351 req->FileAttributes = cpu_to_le32(ATTR_SYSTEM);
1353 req->FileAttributes = cpu_to_le32(ATTR_NORMAL);
1356 * XP does not handle ATTR_POSIX_SEMANTICS but it helps speed up case
1357 * sensitive checks for other servers such as Samba.
1359 if (tcon->ses->capabilities & CAP_UNIX)
1360 req->FileAttributes |= cpu_to_le32(ATTR_POSIX_SEMANTICS);
1362 if (create_options & CREATE_OPTION_READONLY)
1363 req->FileAttributes |= cpu_to_le32(ATTR_READONLY);
1365 req->ShareAccess = cpu_to_le32(FILE_SHARE_ALL);
1366 req->CreateDisposition = cpu_to_le32(disposition);
1367 req->CreateOptions = cpu_to_le32(create_options & CREATE_OPTIONS_MASK);
1369 /* BB Expirement with various impersonation levels and verify */
1370 req->ImpersonationLevel = cpu_to_le32(SECURITY_IMPERSONATION);
1371 req->SecurityFlags = SECURITY_CONTEXT_TRACKING|SECURITY_EFFECTIVE_ONLY;
1374 inc_rfc1001_len(req, count);
1376 req->ByteCount = cpu_to_le16(count);
1377 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *)req,
1378 (struct smb_hdr *)rsp, &bytes_returned, 0);
1379 cifs_stats_inc(&tcon->stats.cifs_stats.num_opens);
1381 cifs_dbg(FYI, "Error in Open = %d\n", rc);
1382 cifs_buf_release(req);
1388 /* 1 byte no need to le_to_cpu */
1389 *oplock = rsp->OplockLevel;
1390 /* cifs fid stays in le */
1391 oparms->fid->netfid = rsp->Fid;
1393 /* Let caller know file was created so we can set the mode. */
1394 /* Do we care about the CreateAction in any other cases? */
1395 if (cpu_to_le32(FILE_CREATE) == rsp->CreateAction)
1396 *oplock |= CIFS_CREATE_ACTION;
1399 /* copy from CreationTime to Attributes */
1400 memcpy((char *)buf, (char *)&rsp->CreationTime, 36);
1401 /* the file_info buf is endian converted by caller */
1402 buf->AllocationSize = rsp->AllocationSize;
1403 buf->EndOfFile = rsp->EndOfFile;
1404 buf->NumberOfLinks = cpu_to_le32(1);
1405 buf->DeletePending = 0;
1408 cifs_buf_release(req);
1413 * Discard any remaining data in the current SMB. To do this, we borrow the
1417 cifs_discard_remaining_data(struct TCP_Server_Info *server)
1419 unsigned int rfclen = get_rfc1002_length(server->smallbuf);
1420 int remaining = rfclen + 4 - server->total_read;
1422 while (remaining > 0) {
1425 length = cifs_read_from_socket(server, server->bigbuf,
1426 min_t(unsigned int, remaining,
1427 CIFSMaxBufSize + MAX_HEADER_SIZE(server)));
1430 server->total_read += length;
1431 remaining -= length;
1438 cifs_readv_discard(struct TCP_Server_Info *server, struct mid_q_entry *mid)
1441 struct cifs_readdata *rdata = mid->callback_data;
1443 length = cifs_discard_remaining_data(server);
1444 dequeue_mid(mid, rdata->result);
1445 mid->resp_buf = server->smallbuf;
1446 server->smallbuf = NULL;
1451 cifs_readv_receive(struct TCP_Server_Info *server, struct mid_q_entry *mid)
1454 unsigned int data_offset, data_len;
1455 struct cifs_readdata *rdata = mid->callback_data;
1456 char *buf = server->smallbuf;
1457 unsigned int buflen = get_rfc1002_length(buf) + 4;
1459 cifs_dbg(FYI, "%s: mid=%llu offset=%llu bytes=%u\n",
1460 __func__, mid->mid, rdata->offset, rdata->bytes);
1463 * read the rest of READ_RSP header (sans Data array), or whatever we
1464 * can if there's not enough data. At this point, we've read down to
1467 len = min_t(unsigned int, buflen, server->vals->read_rsp_size) -
1468 HEADER_SIZE(server) + 1;
1470 length = cifs_read_from_socket(server,
1471 buf + HEADER_SIZE(server) - 1, len);
1474 server->total_read += length;
1476 if (server->ops->is_session_expired &&
1477 server->ops->is_session_expired(buf)) {
1478 cifs_reconnect(server);
1479 wake_up(&server->response_q);
1483 if (server->ops->is_status_pending &&
1484 server->ops->is_status_pending(buf, server, 0)) {
1485 cifs_discard_remaining_data(server);
1489 /* Was the SMB read successful? */
1490 rdata->result = server->ops->map_error(buf, false);
1491 if (rdata->result != 0) {
1492 cifs_dbg(FYI, "%s: server returned error %d\n",
1493 __func__, rdata->result);
1494 return cifs_readv_discard(server, mid);
1497 /* Is there enough to get to the rest of the READ_RSP header? */
1498 if (server->total_read < server->vals->read_rsp_size) {
1499 cifs_dbg(FYI, "%s: server returned short header. got=%u expected=%zu\n",
1500 __func__, server->total_read,
1501 server->vals->read_rsp_size);
1502 rdata->result = -EIO;
1503 return cifs_readv_discard(server, mid);
1506 data_offset = server->ops->read_data_offset(buf) + 4;
1507 if (data_offset < server->total_read) {
1509 * win2k8 sometimes sends an offset of 0 when the read
1510 * is beyond the EOF. Treat it as if the data starts just after
1513 cifs_dbg(FYI, "%s: data offset (%u) inside read response header\n",
1514 __func__, data_offset);
1515 data_offset = server->total_read;
1516 } else if (data_offset > MAX_CIFS_SMALL_BUFFER_SIZE) {
1517 /* data_offset is beyond the end of smallbuf */
1518 cifs_dbg(FYI, "%s: data offset (%u) beyond end of smallbuf\n",
1519 __func__, data_offset);
1520 rdata->result = -EIO;
1521 return cifs_readv_discard(server, mid);
1524 cifs_dbg(FYI, "%s: total_read=%u data_offset=%u\n",
1525 __func__, server->total_read, data_offset);
1527 len = data_offset - server->total_read;
1529 /* read any junk before data into the rest of smallbuf */
1530 length = cifs_read_from_socket(server,
1531 buf + server->total_read, len);
1534 server->total_read += length;
1537 /* set up first iov for signature check */
1538 rdata->iov[0].iov_base = buf;
1539 rdata->iov[0].iov_len = 4;
1540 rdata->iov[1].iov_base = buf + 4;
1541 rdata->iov[1].iov_len = server->total_read - 4;
1542 cifs_dbg(FYI, "0: iov_base=%p iov_len=%u\n",
1543 rdata->iov[0].iov_base, server->total_read);
1545 /* how much data is in the response? */
1546 data_len = server->ops->read_data_length(buf);
1547 if (data_offset + data_len > buflen) {
1548 /* data_len is corrupt -- discard frame */
1549 rdata->result = -EIO;
1550 return cifs_readv_discard(server, mid);
1553 length = rdata->read_into_pages(server, rdata, data_len);
1557 server->total_read += length;
1559 cifs_dbg(FYI, "total_read=%u buflen=%u remaining=%u\n",
1560 server->total_read, buflen, data_len);
1562 /* discard anything left over */
1563 if (server->total_read < buflen)
1564 return cifs_readv_discard(server, mid);
1566 dequeue_mid(mid, false);
1567 mid->resp_buf = server->smallbuf;
1568 server->smallbuf = NULL;
1573 cifs_readv_callback(struct mid_q_entry *mid)
1575 struct cifs_readdata *rdata = mid->callback_data;
1576 struct cifs_tcon *tcon = tlink_tcon(rdata->cfile->tlink);
1577 struct TCP_Server_Info *server = tcon->ses->server;
1578 struct smb_rqst rqst = { .rq_iov = rdata->iov,
1580 .rq_pages = rdata->pages,
1581 .rq_npages = rdata->nr_pages,
1582 .rq_pagesz = rdata->pagesz,
1583 .rq_tailsz = rdata->tailsz };
1585 cifs_dbg(FYI, "%s: mid=%llu state=%d result=%d bytes=%u\n",
1586 __func__, mid->mid, mid->mid_state, rdata->result,
1589 switch (mid->mid_state) {
1590 case MID_RESPONSE_RECEIVED:
1591 /* result already set, check signature */
1595 rc = cifs_verify_signature(&rqst, server,
1596 mid->sequence_number);
1598 cifs_dbg(VFS, "SMB signature verification returned error = %d\n",
1601 /* FIXME: should this be counted toward the initiating task? */
1602 task_io_account_read(rdata->got_bytes);
1603 cifs_stats_bytes_read(tcon, rdata->got_bytes);
1605 case MID_REQUEST_SUBMITTED:
1606 case MID_RETRY_NEEDED:
1607 rdata->result = -EAGAIN;
1608 if (server->sign && rdata->got_bytes)
1609 /* reset bytes number since we can not check a sign */
1610 rdata->got_bytes = 0;
1611 /* FIXME: should this be counted toward the initiating task? */
1612 task_io_account_read(rdata->got_bytes);
1613 cifs_stats_bytes_read(tcon, rdata->got_bytes);
1616 rdata->result = -EIO;
1619 queue_work(cifsiod_wq, &rdata->work);
1620 DeleteMidQEntry(mid);
1621 add_credits(server, 1, 0);
1624 /* cifs_async_readv - send an async write, and set up mid to handle result */
1626 cifs_async_readv(struct cifs_readdata *rdata)
1629 READ_REQ *smb = NULL;
1631 struct cifs_tcon *tcon = tlink_tcon(rdata->cfile->tlink);
1632 struct smb_rqst rqst = { .rq_iov = rdata->iov,
1635 cifs_dbg(FYI, "%s: offset=%llu bytes=%u\n",
1636 __func__, rdata->offset, rdata->bytes);
1638 if (tcon->ses->capabilities & CAP_LARGE_FILES)
1641 wct = 10; /* old style read */
1642 if ((rdata->offset >> 32) > 0) {
1643 /* can not handle this big offset for old */
1648 rc = small_smb_init(SMB_COM_READ_ANDX, wct, tcon, (void **)&smb);
1652 smb->hdr.Pid = cpu_to_le16((__u16)rdata->pid);
1653 smb->hdr.PidHigh = cpu_to_le16((__u16)(rdata->pid >> 16));
1655 smb->AndXCommand = 0xFF; /* none */
1656 smb->Fid = rdata->cfile->fid.netfid;
1657 smb->OffsetLow = cpu_to_le32(rdata->offset & 0xFFFFFFFF);
1659 smb->OffsetHigh = cpu_to_le32(rdata->offset >> 32);
1661 smb->MaxCount = cpu_to_le16(rdata->bytes & 0xFFFF);
1662 smb->MaxCountHigh = cpu_to_le32(rdata->bytes >> 16);
1666 /* old style read */
1667 struct smb_com_readx_req *smbr =
1668 (struct smb_com_readx_req *)smb;
1669 smbr->ByteCount = 0;
1672 /* 4 for RFC1001 length + 1 for BCC */
1673 rdata->iov[0].iov_base = smb;
1674 rdata->iov[0].iov_len = 4;
1675 rdata->iov[1].iov_base = (char *)smb + 4;
1676 rdata->iov[1].iov_len = get_rfc1002_length(smb);
1678 kref_get(&rdata->refcount);
1679 rc = cifs_call_async(tcon->ses->server, &rqst, cifs_readv_receive,
1680 cifs_readv_callback, NULL, rdata, 0);
1683 cifs_stats_inc(&tcon->stats.cifs_stats.num_reads);
1685 kref_put(&rdata->refcount, cifs_readdata_release);
1687 cifs_small_buf_release(smb);
1692 CIFSSMBRead(const unsigned int xid, struct cifs_io_parms *io_parms,
1693 unsigned int *nbytes, char **buf, int *pbuf_type)
1696 READ_REQ *pSMB = NULL;
1697 READ_RSP *pSMBr = NULL;
1698 char *pReadData = NULL;
1700 int resp_buf_type = 0;
1702 struct kvec rsp_iov;
1703 __u32 pid = io_parms->pid;
1704 __u16 netfid = io_parms->netfid;
1705 __u64 offset = io_parms->offset;
1706 struct cifs_tcon *tcon = io_parms->tcon;
1707 unsigned int count = io_parms->length;
1709 cifs_dbg(FYI, "Reading %d bytes on fid %d\n", count, netfid);
1710 if (tcon->ses->capabilities & CAP_LARGE_FILES)
1713 wct = 10; /* old style read */
1714 if ((offset >> 32) > 0) {
1715 /* can not handle this big offset for old */
1721 rc = small_smb_init(SMB_COM_READ_ANDX, wct, tcon, (void **) &pSMB);
1725 pSMB->hdr.Pid = cpu_to_le16((__u16)pid);
1726 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid >> 16));
1728 /* tcon and ses pointer are checked in smb_init */
1729 if (tcon->ses->server == NULL)
1730 return -ECONNABORTED;
1732 pSMB->AndXCommand = 0xFF; /* none */
1734 pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF);
1736 pSMB->OffsetHigh = cpu_to_le32(offset >> 32);
1738 pSMB->Remaining = 0;
1739 pSMB->MaxCount = cpu_to_le16(count & 0xFFFF);
1740 pSMB->MaxCountHigh = cpu_to_le32(count >> 16);
1742 pSMB->ByteCount = 0; /* no need to do le conversion since 0 */
1744 /* old style read */
1745 struct smb_com_readx_req *pSMBW =
1746 (struct smb_com_readx_req *)pSMB;
1747 pSMBW->ByteCount = 0;
1750 iov[0].iov_base = (char *)pSMB;
1751 iov[0].iov_len = be32_to_cpu(pSMB->hdr.smb_buf_length) + 4;
1752 rc = SendReceive2(xid, tcon->ses, iov, 1, &resp_buf_type,
1753 CIFS_LOG_ERROR, &rsp_iov);
1754 cifs_small_buf_release(pSMB);
1755 cifs_stats_inc(&tcon->stats.cifs_stats.num_reads);
1756 pSMBr = (READ_RSP *)rsp_iov.iov_base;
1758 cifs_dbg(VFS, "Send error in read = %d\n", rc);
1760 int data_length = le16_to_cpu(pSMBr->DataLengthHigh);
1761 data_length = data_length << 16;
1762 data_length += le16_to_cpu(pSMBr->DataLength);
1763 *nbytes = data_length;
1765 /*check that DataLength would not go beyond end of SMB */
1766 if ((data_length > CIFSMaxBufSize)
1767 || (data_length > count)) {
1768 cifs_dbg(FYI, "bad length %d for count %d\n",
1769 data_length, count);
1773 pReadData = (char *) (&pSMBr->hdr.Protocol) +
1774 le16_to_cpu(pSMBr->DataOffset);
1775 /* if (rc = copy_to_user(buf, pReadData, data_length)) {
1776 cifs_dbg(VFS, "Faulting on read rc = %d\n",rc);
1778 }*/ /* can not use copy_to_user when using page cache*/
1780 memcpy(*buf, pReadData, data_length);
1785 free_rsp_buf(resp_buf_type, rsp_iov.iov_base);
1786 } else if (resp_buf_type != CIFS_NO_BUFFER) {
1787 /* return buffer to caller to free */
1788 *buf = rsp_iov.iov_base;
1789 if (resp_buf_type == CIFS_SMALL_BUFFER)
1790 *pbuf_type = CIFS_SMALL_BUFFER;
1791 else if (resp_buf_type == CIFS_LARGE_BUFFER)
1792 *pbuf_type = CIFS_LARGE_BUFFER;
1793 } /* else no valid buffer on return - leave as null */
1795 /* Note: On -EAGAIN error only caller can retry on handle based calls
1796 since file handle passed in no longer valid */
1802 CIFSSMBWrite(const unsigned int xid, struct cifs_io_parms *io_parms,
1803 unsigned int *nbytes, const char *buf)
1806 WRITE_REQ *pSMB = NULL;
1807 WRITE_RSP *pSMBr = NULL;
1808 int bytes_returned, wct;
1811 __u32 pid = io_parms->pid;
1812 __u16 netfid = io_parms->netfid;
1813 __u64 offset = io_parms->offset;
1814 struct cifs_tcon *tcon = io_parms->tcon;
1815 unsigned int count = io_parms->length;
1819 /* cifs_dbg(FYI, "write at %lld %d bytes\n", offset, count);*/
1820 if (tcon->ses == NULL)
1821 return -ECONNABORTED;
1823 if (tcon->ses->capabilities & CAP_LARGE_FILES)
1827 if ((offset >> 32) > 0) {
1828 /* can not handle big offset for old srv */
1833 rc = smb_init(SMB_COM_WRITE_ANDX, wct, tcon, (void **) &pSMB,
1838 pSMB->hdr.Pid = cpu_to_le16((__u16)pid);
1839 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid >> 16));
1841 /* tcon and ses pointer are checked in smb_init */
1842 if (tcon->ses->server == NULL)
1843 return -ECONNABORTED;
1845 pSMB->AndXCommand = 0xFF; /* none */
1847 pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF);
1849 pSMB->OffsetHigh = cpu_to_le32(offset >> 32);
1851 pSMB->Reserved = 0xFFFFFFFF;
1852 pSMB->WriteMode = 0;
1853 pSMB->Remaining = 0;
1855 /* Can increase buffer size if buffer is big enough in some cases ie we
1856 can send more if LARGE_WRITE_X capability returned by the server and if
1857 our buffer is big enough or if we convert to iovecs on socket writes
1858 and eliminate the copy to the CIFS buffer */
1859 if (tcon->ses->capabilities & CAP_LARGE_WRITE_X) {
1860 bytes_sent = min_t(const unsigned int, CIFSMaxBufSize, count);
1862 bytes_sent = (tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE)
1866 if (bytes_sent > count)
1869 cpu_to_le16(offsetof(struct smb_com_write_req, Data) - 4);
1871 memcpy(pSMB->Data, buf, bytes_sent);
1872 else if (count != 0) {
1874 cifs_buf_release(pSMB);
1876 } /* else setting file size with write of zero bytes */
1878 byte_count = bytes_sent + 1; /* pad */
1879 else /* wct == 12 */
1880 byte_count = bytes_sent + 5; /* bigger pad, smaller smb hdr */
1882 pSMB->DataLengthLow = cpu_to_le16(bytes_sent & 0xFFFF);
1883 pSMB->DataLengthHigh = cpu_to_le16(bytes_sent >> 16);
1884 inc_rfc1001_len(pSMB, byte_count);
1887 pSMB->ByteCount = cpu_to_le16(byte_count);
1888 else { /* old style write has byte count 4 bytes earlier
1890 struct smb_com_writex_req *pSMBW =
1891 (struct smb_com_writex_req *)pSMB;
1892 pSMBW->ByteCount = cpu_to_le16(byte_count);
1895 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1896 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1897 cifs_stats_inc(&tcon->stats.cifs_stats.num_writes);
1899 cifs_dbg(FYI, "Send error in write = %d\n", rc);
1901 *nbytes = le16_to_cpu(pSMBr->CountHigh);
1902 *nbytes = (*nbytes) << 16;
1903 *nbytes += le16_to_cpu(pSMBr->Count);
1906 * Mask off high 16 bits when bytes written as returned by the
1907 * server is greater than bytes requested by the client. Some
1908 * OS/2 servers are known to set incorrect CountHigh values.
1910 if (*nbytes > count)
1914 cifs_buf_release(pSMB);
1916 /* Note: On -EAGAIN error only caller can retry on handle based calls
1917 since file handle passed in no longer valid */
1923 cifs_writedata_release(struct kref *refcount)
1925 struct cifs_writedata *wdata = container_of(refcount,
1926 struct cifs_writedata, refcount);
1927 #ifdef CONFIG_CIFS_SMB_DIRECT
1929 smbd_deregister_mr(wdata->mr);
1935 cifsFileInfo_put(wdata->cfile);
1941 * Write failed with a retryable error. Resend the write request. It's also
1942 * possible that the page was redirtied so re-clean the page.
1945 cifs_writev_requeue(struct cifs_writedata *wdata)
1948 struct inode *inode = d_inode(wdata->cfile->dentry);
1949 struct TCP_Server_Info *server;
1950 unsigned int rest_len;
1952 server = tlink_tcon(wdata->cfile->tlink)->ses->server;
1954 rest_len = wdata->bytes;
1956 struct cifs_writedata *wdata2;
1957 unsigned int j, nr_pages, wsize, tailsz, cur_len;
1959 wsize = server->ops->wp_retry_size(inode);
1960 if (wsize < rest_len) {
1961 nr_pages = wsize / PAGE_SIZE;
1966 cur_len = nr_pages * PAGE_SIZE;
1969 nr_pages = DIV_ROUND_UP(rest_len, PAGE_SIZE);
1971 tailsz = rest_len - (nr_pages - 1) * PAGE_SIZE;
1974 wdata2 = cifs_writedata_alloc(nr_pages, cifs_writev_complete);
1980 for (j = 0; j < nr_pages; j++) {
1981 wdata2->pages[j] = wdata->pages[i + j];
1982 lock_page(wdata2->pages[j]);
1983 clear_page_dirty_for_io(wdata2->pages[j]);
1986 wdata2->sync_mode = wdata->sync_mode;
1987 wdata2->nr_pages = nr_pages;
1988 wdata2->offset = page_offset(wdata2->pages[0]);
1989 wdata2->pagesz = PAGE_SIZE;
1990 wdata2->tailsz = tailsz;
1991 wdata2->bytes = cur_len;
1993 wdata2->cfile = find_writable_file(CIFS_I(inode), false);
1994 if (!wdata2->cfile) {
1995 cifs_dbg(VFS, "No writable handles for inode\n");
1999 wdata2->pid = wdata2->cfile->pid;
2000 rc = server->ops->async_writev(wdata2, cifs_writedata_release);
2002 for (j = 0; j < nr_pages; j++) {
2003 unlock_page(wdata2->pages[j]);
2004 if (rc != 0 && rc != -EAGAIN) {
2005 SetPageError(wdata2->pages[j]);
2006 end_page_writeback(wdata2->pages[j]);
2007 put_page(wdata2->pages[j]);
2012 kref_put(&wdata2->refcount, cifs_writedata_release);
2018 rest_len -= cur_len;
2020 } while (i < wdata->nr_pages);
2022 mapping_set_error(inode->i_mapping, rc);
2023 kref_put(&wdata->refcount, cifs_writedata_release);
2027 cifs_writev_complete(struct work_struct *work)
2029 struct cifs_writedata *wdata = container_of(work,
2030 struct cifs_writedata, work);
2031 struct inode *inode = d_inode(wdata->cfile->dentry);
2034 if (wdata->result == 0) {
2035 spin_lock(&inode->i_lock);
2036 cifs_update_eof(CIFS_I(inode), wdata->offset, wdata->bytes);
2037 spin_unlock(&inode->i_lock);
2038 cifs_stats_bytes_written(tlink_tcon(wdata->cfile->tlink),
2040 } else if (wdata->sync_mode == WB_SYNC_ALL && wdata->result == -EAGAIN)
2041 return cifs_writev_requeue(wdata);
2043 for (i = 0; i < wdata->nr_pages; i++) {
2044 struct page *page = wdata->pages[i];
2045 if (wdata->result == -EAGAIN)
2046 __set_page_dirty_nobuffers(page);
2047 else if (wdata->result < 0)
2049 end_page_writeback(page);
2052 if (wdata->result != -EAGAIN)
2053 mapping_set_error(inode->i_mapping, wdata->result);
2054 kref_put(&wdata->refcount, cifs_writedata_release);
2057 struct cifs_writedata *
2058 cifs_writedata_alloc(unsigned int nr_pages, work_func_t complete)
2060 struct cifs_writedata *wdata;
2062 /* writedata + number of page pointers */
2063 wdata = kzalloc(sizeof(*wdata) +
2064 sizeof(struct page *) * nr_pages, GFP_NOFS);
2065 if (wdata != NULL) {
2066 kref_init(&wdata->refcount);
2067 INIT_LIST_HEAD(&wdata->list);
2068 init_completion(&wdata->done);
2069 INIT_WORK(&wdata->work, complete);
2075 * Check the mid_state and signature on received buffer (if any), and queue the
2076 * workqueue completion task.
2079 cifs_writev_callback(struct mid_q_entry *mid)
2081 struct cifs_writedata *wdata = mid->callback_data;
2082 struct cifs_tcon *tcon = tlink_tcon(wdata->cfile->tlink);
2083 unsigned int written;
2084 WRITE_RSP *smb = (WRITE_RSP *)mid->resp_buf;
2086 switch (mid->mid_state) {
2087 case MID_RESPONSE_RECEIVED:
2088 wdata->result = cifs_check_receive(mid, tcon->ses->server, 0);
2089 if (wdata->result != 0)
2092 written = le16_to_cpu(smb->CountHigh);
2094 written += le16_to_cpu(smb->Count);
2096 * Mask off high 16 bits when bytes written as returned
2097 * by the server is greater than bytes requested by the
2098 * client. OS/2 servers are known to set incorrect
2101 if (written > wdata->bytes)
2104 if (written < wdata->bytes)
2105 wdata->result = -ENOSPC;
2107 wdata->bytes = written;
2109 case MID_REQUEST_SUBMITTED:
2110 case MID_RETRY_NEEDED:
2111 wdata->result = -EAGAIN;
2114 wdata->result = -EIO;
2118 queue_work(cifsiod_wq, &wdata->work);
2119 DeleteMidQEntry(mid);
2120 add_credits(tcon->ses->server, 1, 0);
2123 /* cifs_async_writev - send an async write, and set up mid to handle result */
2125 cifs_async_writev(struct cifs_writedata *wdata,
2126 void (*release)(struct kref *kref))
2129 WRITE_REQ *smb = NULL;
2131 struct cifs_tcon *tcon = tlink_tcon(wdata->cfile->tlink);
2133 struct smb_rqst rqst = { };
2135 if (tcon->ses->capabilities & CAP_LARGE_FILES) {
2139 if (wdata->offset >> 32 > 0) {
2140 /* can not handle big offset for old srv */
2145 rc = small_smb_init(SMB_COM_WRITE_ANDX, wct, tcon, (void **)&smb);
2147 goto async_writev_out;
2149 smb->hdr.Pid = cpu_to_le16((__u16)wdata->pid);
2150 smb->hdr.PidHigh = cpu_to_le16((__u16)(wdata->pid >> 16));
2152 smb->AndXCommand = 0xFF; /* none */
2153 smb->Fid = wdata->cfile->fid.netfid;
2154 smb->OffsetLow = cpu_to_le32(wdata->offset & 0xFFFFFFFF);
2156 smb->OffsetHigh = cpu_to_le32(wdata->offset >> 32);
2157 smb->Reserved = 0xFFFFFFFF;
2162 cpu_to_le16(offsetof(struct smb_com_write_req, Data) - 4);
2164 /* 4 for RFC1001 length + 1 for BCC */
2166 iov[0].iov_base = smb;
2167 iov[1].iov_len = get_rfc1002_length(smb) + 1;
2168 iov[1].iov_base = (char *)smb + 4;
2172 rqst.rq_pages = wdata->pages;
2173 rqst.rq_npages = wdata->nr_pages;
2174 rqst.rq_pagesz = wdata->pagesz;
2175 rqst.rq_tailsz = wdata->tailsz;
2177 cifs_dbg(FYI, "async write at %llu %u bytes\n",
2178 wdata->offset, wdata->bytes);
2180 smb->DataLengthLow = cpu_to_le16(wdata->bytes & 0xFFFF);
2181 smb->DataLengthHigh = cpu_to_le16(wdata->bytes >> 16);
2184 inc_rfc1001_len(&smb->hdr, wdata->bytes + 1);
2185 put_bcc(wdata->bytes + 1, &smb->hdr);
2188 struct smb_com_writex_req *smbw =
2189 (struct smb_com_writex_req *)smb;
2190 inc_rfc1001_len(&smbw->hdr, wdata->bytes + 5);
2191 put_bcc(wdata->bytes + 5, &smbw->hdr);
2192 iov[1].iov_len += 4; /* pad bigger by four bytes */
2195 kref_get(&wdata->refcount);
2196 rc = cifs_call_async(tcon->ses->server, &rqst, NULL,
2197 cifs_writev_callback, NULL, wdata, 0);
2200 cifs_stats_inc(&tcon->stats.cifs_stats.num_writes);
2202 kref_put(&wdata->refcount, release);
2205 cifs_small_buf_release(smb);
2210 CIFSSMBWrite2(const unsigned int xid, struct cifs_io_parms *io_parms,
2211 unsigned int *nbytes, struct kvec *iov, int n_vec)
2214 WRITE_REQ *pSMB = NULL;
2217 int resp_buf_type = 0;
2218 __u32 pid = io_parms->pid;
2219 __u16 netfid = io_parms->netfid;
2220 __u64 offset = io_parms->offset;
2221 struct cifs_tcon *tcon = io_parms->tcon;
2222 unsigned int count = io_parms->length;
2223 struct kvec rsp_iov;
2227 cifs_dbg(FYI, "write2 at %lld %d bytes\n", (long long)offset, count);
2229 if (tcon->ses->capabilities & CAP_LARGE_FILES) {
2233 if ((offset >> 32) > 0) {
2234 /* can not handle big offset for old srv */
2238 rc = small_smb_init(SMB_COM_WRITE_ANDX, wct, tcon, (void **) &pSMB);
2242 pSMB->hdr.Pid = cpu_to_le16((__u16)pid);
2243 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid >> 16));
2245 /* tcon and ses pointer are checked in smb_init */
2246 if (tcon->ses->server == NULL)
2247 return -ECONNABORTED;
2249 pSMB->AndXCommand = 0xFF; /* none */
2251 pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF);
2253 pSMB->OffsetHigh = cpu_to_le32(offset >> 32);
2254 pSMB->Reserved = 0xFFFFFFFF;
2255 pSMB->WriteMode = 0;
2256 pSMB->Remaining = 0;
2259 cpu_to_le16(offsetof(struct smb_com_write_req, Data) - 4);
2261 pSMB->DataLengthLow = cpu_to_le16(count & 0xFFFF);
2262 pSMB->DataLengthHigh = cpu_to_le16(count >> 16);
2263 /* header + 1 byte pad */
2264 smb_hdr_len = be32_to_cpu(pSMB->hdr.smb_buf_length) + 1;
2266 inc_rfc1001_len(pSMB, count + 1);
2267 else /* wct == 12 */
2268 inc_rfc1001_len(pSMB, count + 5); /* smb data starts later */
2270 pSMB->ByteCount = cpu_to_le16(count + 1);
2271 else /* wct == 12 */ /* bigger pad, smaller smb hdr, keep offset ok */ {
2272 struct smb_com_writex_req *pSMBW =
2273 (struct smb_com_writex_req *)pSMB;
2274 pSMBW->ByteCount = cpu_to_le16(count + 5);
2276 iov[0].iov_base = pSMB;
2278 iov[0].iov_len = smb_hdr_len + 4;
2279 else /* wct == 12 pad bigger by four bytes */
2280 iov[0].iov_len = smb_hdr_len + 8;
2282 rc = SendReceive2(xid, tcon->ses, iov, n_vec + 1, &resp_buf_type, 0,
2284 cifs_small_buf_release(pSMB);
2285 cifs_stats_inc(&tcon->stats.cifs_stats.num_writes);
2287 cifs_dbg(FYI, "Send error Write2 = %d\n", rc);
2288 } else if (resp_buf_type == 0) {
2289 /* presumably this can not happen, but best to be safe */
2292 WRITE_RSP *pSMBr = (WRITE_RSP *)rsp_iov.iov_base;
2293 *nbytes = le16_to_cpu(pSMBr->CountHigh);
2294 *nbytes = (*nbytes) << 16;
2295 *nbytes += le16_to_cpu(pSMBr->Count);
2298 * Mask off high 16 bits when bytes written as returned by the
2299 * server is greater than bytes requested by the client. OS/2
2300 * servers are known to set incorrect CountHigh values.
2302 if (*nbytes > count)
2306 free_rsp_buf(resp_buf_type, rsp_iov.iov_base);
2308 /* Note: On -EAGAIN error only caller can retry on handle based calls
2309 since file handle passed in no longer valid */
2314 int cifs_lockv(const unsigned int xid, struct cifs_tcon *tcon,
2315 const __u16 netfid, const __u8 lock_type, const __u32 num_unlock,
2316 const __u32 num_lock, LOCKING_ANDX_RANGE *buf)
2319 LOCK_REQ *pSMB = NULL;
2321 struct kvec rsp_iov;
2325 cifs_dbg(FYI, "cifs_lockv num lock %d num unlock %d\n",
2326 num_lock, num_unlock);
2328 rc = small_smb_init(SMB_COM_LOCKING_ANDX, 8, tcon, (void **) &pSMB);
2333 pSMB->NumberOfLocks = cpu_to_le16(num_lock);
2334 pSMB->NumberOfUnlocks = cpu_to_le16(num_unlock);
2335 pSMB->LockType = lock_type;
2336 pSMB->AndXCommand = 0xFF; /* none */
2337 pSMB->Fid = netfid; /* netfid stays le */
2339 count = (num_unlock + num_lock) * sizeof(LOCKING_ANDX_RANGE);
2340 inc_rfc1001_len(pSMB, count);
2341 pSMB->ByteCount = cpu_to_le16(count);
2343 iov[0].iov_base = (char *)pSMB;
2344 iov[0].iov_len = be32_to_cpu(pSMB->hdr.smb_buf_length) + 4 -
2345 (num_unlock + num_lock) * sizeof(LOCKING_ANDX_RANGE);
2346 iov[1].iov_base = (char *)buf;
2347 iov[1].iov_len = (num_unlock + num_lock) * sizeof(LOCKING_ANDX_RANGE);
2349 cifs_stats_inc(&tcon->stats.cifs_stats.num_locks);
2350 rc = SendReceive2(xid, tcon->ses, iov, 2, &resp_buf_type, CIFS_NO_RESP,
2352 cifs_small_buf_release(pSMB);
2354 cifs_dbg(FYI, "Send error in cifs_lockv = %d\n", rc);
2360 CIFSSMBLock(const unsigned int xid, struct cifs_tcon *tcon,
2361 const __u16 smb_file_id, const __u32 netpid, const __u64 len,
2362 const __u64 offset, const __u32 numUnlock,
2363 const __u32 numLock, const __u8 lockType,
2364 const bool waitFlag, const __u8 oplock_level)
2367 LOCK_REQ *pSMB = NULL;
2368 /* LOCK_RSP *pSMBr = NULL; */ /* No response data other than rc to parse */
2373 cifs_dbg(FYI, "CIFSSMBLock timeout %d numLock %d\n",
2374 (int)waitFlag, numLock);
2375 rc = small_smb_init(SMB_COM_LOCKING_ANDX, 8, tcon, (void **) &pSMB);
2380 if (lockType == LOCKING_ANDX_OPLOCK_RELEASE) {
2381 /* no response expected */
2382 flags = CIFS_ASYNC_OP | CIFS_OBREAK_OP;
2384 } else if (waitFlag) {
2385 flags = CIFS_BLOCKING_OP; /* blocking operation, no timeout */
2386 pSMB->Timeout = cpu_to_le32(-1);/* blocking - do not time out */
2391 pSMB->NumberOfLocks = cpu_to_le16(numLock);
2392 pSMB->NumberOfUnlocks = cpu_to_le16(numUnlock);
2393 pSMB->LockType = lockType;
2394 pSMB->OplockLevel = oplock_level;
2395 pSMB->AndXCommand = 0xFF; /* none */
2396 pSMB->Fid = smb_file_id; /* netfid stays le */
2398 if ((numLock != 0) || (numUnlock != 0)) {
2399 pSMB->Locks[0].Pid = cpu_to_le16(netpid);
2400 /* BB where to store pid high? */
2401 pSMB->Locks[0].LengthLow = cpu_to_le32((u32)len);
2402 pSMB->Locks[0].LengthHigh = cpu_to_le32((u32)(len>>32));
2403 pSMB->Locks[0].OffsetLow = cpu_to_le32((u32)offset);
2404 pSMB->Locks[0].OffsetHigh = cpu_to_le32((u32)(offset>>32));
2405 count = sizeof(LOCKING_ANDX_RANGE);
2410 inc_rfc1001_len(pSMB, count);
2411 pSMB->ByteCount = cpu_to_le16(count);
2414 rc = SendReceiveBlockingLock(xid, tcon, (struct smb_hdr *) pSMB,
2415 (struct smb_hdr *) pSMB, &bytes_returned);
2417 rc = SendReceiveNoRsp(xid, tcon->ses, (char *)pSMB, flags);
2418 cifs_small_buf_release(pSMB);
2419 cifs_stats_inc(&tcon->stats.cifs_stats.num_locks);
2421 cifs_dbg(FYI, "Send error in Lock = %d\n", rc);
2423 /* Note: On -EAGAIN error only caller can retry on handle based calls
2424 since file handle passed in no longer valid */
2429 CIFSSMBPosixLock(const unsigned int xid, struct cifs_tcon *tcon,
2430 const __u16 smb_file_id, const __u32 netpid,
2431 const loff_t start_offset, const __u64 len,
2432 struct file_lock *pLockData, const __u16 lock_type,
2433 const bool waitFlag)
2435 struct smb_com_transaction2_sfi_req *pSMB = NULL;
2436 struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
2437 struct cifs_posix_lock *parm_data;
2440 int bytes_returned = 0;
2441 int resp_buf_type = 0;
2442 __u16 params, param_offset, offset, byte_count, count;
2444 struct kvec rsp_iov;
2446 cifs_dbg(FYI, "Posix Lock\n");
2448 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
2453 pSMBr = (struct smb_com_transaction2_sfi_rsp *)pSMB;
2456 pSMB->MaxSetupCount = 0;
2459 pSMB->Reserved2 = 0;
2460 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
2461 offset = param_offset + params;
2463 count = sizeof(struct cifs_posix_lock);
2464 pSMB->MaxParameterCount = cpu_to_le16(2);
2465 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB from sess */
2466 pSMB->SetupCount = 1;
2467 pSMB->Reserved3 = 0;
2469 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION);
2471 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
2472 byte_count = 3 /* pad */ + params + count;
2473 pSMB->DataCount = cpu_to_le16(count);
2474 pSMB->ParameterCount = cpu_to_le16(params);
2475 pSMB->TotalDataCount = pSMB->DataCount;
2476 pSMB->TotalParameterCount = pSMB->ParameterCount;
2477 pSMB->ParameterOffset = cpu_to_le16(param_offset);
2478 parm_data = (struct cifs_posix_lock *)
2479 (((char *) &pSMB->hdr.Protocol) + offset);
2481 parm_data->lock_type = cpu_to_le16(lock_type);
2483 timeout = CIFS_BLOCKING_OP; /* blocking operation, no timeout */
2484 parm_data->lock_flags = cpu_to_le16(1);
2485 pSMB->Timeout = cpu_to_le32(-1);
2489 parm_data->pid = cpu_to_le32(netpid);
2490 parm_data->start = cpu_to_le64(start_offset);
2491 parm_data->length = cpu_to_le64(len); /* normalize negative numbers */
2493 pSMB->DataOffset = cpu_to_le16(offset);
2494 pSMB->Fid = smb_file_id;
2495 pSMB->InformationLevel = cpu_to_le16(SMB_SET_POSIX_LOCK);
2496 pSMB->Reserved4 = 0;
2497 inc_rfc1001_len(pSMB, byte_count);
2498 pSMB->ByteCount = cpu_to_le16(byte_count);
2500 rc = SendReceiveBlockingLock(xid, tcon, (struct smb_hdr *) pSMB,
2501 (struct smb_hdr *) pSMBr, &bytes_returned);
2503 iov[0].iov_base = (char *)pSMB;
2504 iov[0].iov_len = be32_to_cpu(pSMB->hdr.smb_buf_length) + 4;
2505 rc = SendReceive2(xid, tcon->ses, iov, 1 /* num iovecs */,
2506 &resp_buf_type, timeout, &rsp_iov);
2507 pSMBr = (struct smb_com_transaction2_sfi_rsp *)rsp_iov.iov_base;
2509 cifs_small_buf_release(pSMB);
2512 cifs_dbg(FYI, "Send error in Posix Lock = %d\n", rc);
2513 } else if (pLockData) {
2514 /* lock structure can be returned on get */
2517 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
2519 if (rc || get_bcc(&pSMBr->hdr) < sizeof(*parm_data)) {
2520 rc = -EIO; /* bad smb */
2523 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
2524 data_count = le16_to_cpu(pSMBr->t2.DataCount);
2525 if (data_count < sizeof(struct cifs_posix_lock)) {
2529 parm_data = (struct cifs_posix_lock *)
2530 ((char *)&pSMBr->hdr.Protocol + data_offset);
2531 if (parm_data->lock_type == cpu_to_le16(CIFS_UNLCK))
2532 pLockData->fl_type = F_UNLCK;
2534 if (parm_data->lock_type ==
2535 cpu_to_le16(CIFS_RDLCK))
2536 pLockData->fl_type = F_RDLCK;
2537 else if (parm_data->lock_type ==
2538 cpu_to_le16(CIFS_WRLCK))
2539 pLockData->fl_type = F_WRLCK;
2541 pLockData->fl_start = le64_to_cpu(parm_data->start);
2542 pLockData->fl_end = pLockData->fl_start +
2543 le64_to_cpu(parm_data->length) - 1;
2544 pLockData->fl_pid = -le32_to_cpu(parm_data->pid);
2549 free_rsp_buf(resp_buf_type, rsp_iov.iov_base);
2551 /* Note: On -EAGAIN error only caller can retry on handle based calls
2552 since file handle passed in no longer valid */
2559 CIFSSMBClose(const unsigned int xid, struct cifs_tcon *tcon, int smb_file_id)
2562 CLOSE_REQ *pSMB = NULL;
2563 cifs_dbg(FYI, "In CIFSSMBClose\n");
2565 /* do not retry on dead session on close */
2566 rc = small_smb_init(SMB_COM_CLOSE, 3, tcon, (void **) &pSMB);
2572 pSMB->FileID = (__u16) smb_file_id;
2573 pSMB->LastWriteTime = 0xFFFFFFFF;
2574 pSMB->ByteCount = 0;
2575 rc = SendReceiveNoRsp(xid, tcon->ses, (char *) pSMB, 0);
2576 cifs_small_buf_release(pSMB);
2577 cifs_stats_inc(&tcon->stats.cifs_stats.num_closes);
2580 /* EINTR is expected when user ctl-c to kill app */
2581 cifs_dbg(VFS, "Send error in Close = %d\n", rc);
2585 /* Since session is dead, file will be closed on server already */
2593 CIFSSMBFlush(const unsigned int xid, struct cifs_tcon *tcon, int smb_file_id)
2596 FLUSH_REQ *pSMB = NULL;
2597 cifs_dbg(FYI, "In CIFSSMBFlush\n");
2599 rc = small_smb_init(SMB_COM_FLUSH, 1, tcon, (void **) &pSMB);
2603 pSMB->FileID = (__u16) smb_file_id;
2604 pSMB->ByteCount = 0;
2605 rc = SendReceiveNoRsp(xid, tcon->ses, (char *) pSMB, 0);
2606 cifs_small_buf_release(pSMB);
2607 cifs_stats_inc(&tcon->stats.cifs_stats.num_flushes);
2609 cifs_dbg(VFS, "Send error in Flush = %d\n", rc);
2615 CIFSSMBRename(const unsigned int xid, struct cifs_tcon *tcon,
2616 const char *from_name, const char *to_name,
2617 struct cifs_sb_info *cifs_sb)
2620 RENAME_REQ *pSMB = NULL;
2621 RENAME_RSP *pSMBr = NULL;
2623 int name_len, name_len2;
2625 int remap = cifs_remap(cifs_sb);
2627 cifs_dbg(FYI, "In CIFSSMBRename\n");
2629 rc = smb_init(SMB_COM_RENAME, 1, tcon, (void **) &pSMB,
2634 pSMB->BufferFormat = 0x04;
2635 pSMB->SearchAttributes =
2636 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
2639 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2640 name_len = cifsConvertToUTF16((__le16 *) pSMB->OldFileName,
2641 from_name, PATH_MAX,
2642 cifs_sb->local_nls, remap);
2643 name_len++; /* trailing null */
2645 pSMB->OldFileName[name_len] = 0x04; /* pad */
2646 /* protocol requires ASCII signature byte on Unicode string */
2647 pSMB->OldFileName[name_len + 1] = 0x00;
2649 cifsConvertToUTF16((__le16 *)&pSMB->OldFileName[name_len+2],
2650 to_name, PATH_MAX, cifs_sb->local_nls,
2652 name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
2653 name_len2 *= 2; /* convert to bytes */
2654 } else { /* BB improve the check for buffer overruns BB */
2655 name_len = strnlen(from_name, PATH_MAX);
2656 name_len++; /* trailing null */
2657 strncpy(pSMB->OldFileName, from_name, name_len);
2658 name_len2 = strnlen(to_name, PATH_MAX);
2659 name_len2++; /* trailing null */
2660 pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */
2661 strncpy(&pSMB->OldFileName[name_len + 1], to_name, name_len2);
2662 name_len2++; /* trailing null */
2663 name_len2++; /* signature byte */
2666 count = 1 /* 1st signature byte */ + name_len + name_len2;
2667 inc_rfc1001_len(pSMB, count);
2668 pSMB->ByteCount = cpu_to_le16(count);
2670 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2671 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2672 cifs_stats_inc(&tcon->stats.cifs_stats.num_renames);
2674 cifs_dbg(FYI, "Send error in rename = %d\n", rc);
2676 cifs_buf_release(pSMB);
2684 int CIFSSMBRenameOpenFile(const unsigned int xid, struct cifs_tcon *pTcon,
2685 int netfid, const char *target_name,
2686 const struct nls_table *nls_codepage, int remap)
2688 struct smb_com_transaction2_sfi_req *pSMB = NULL;
2689 struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
2690 struct set_file_rename *rename_info;
2692 char dummy_string[30];
2694 int bytes_returned = 0;
2696 __u16 params, param_offset, offset, count, byte_count;
2698 cifs_dbg(FYI, "Rename to File by handle\n");
2699 rc = smb_init(SMB_COM_TRANSACTION2, 15, pTcon, (void **) &pSMB,
2705 pSMB->MaxSetupCount = 0;
2709 pSMB->Reserved2 = 0;
2710 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
2711 offset = param_offset + params;
2713 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
2714 rename_info = (struct set_file_rename *) data_offset;
2715 pSMB->MaxParameterCount = cpu_to_le16(2);
2716 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB from sess */
2717 pSMB->SetupCount = 1;
2718 pSMB->Reserved3 = 0;
2719 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
2720 byte_count = 3 /* pad */ + params;
2721 pSMB->ParameterCount = cpu_to_le16(params);
2722 pSMB->TotalParameterCount = pSMB->ParameterCount;
2723 pSMB->ParameterOffset = cpu_to_le16(param_offset);
2724 pSMB->DataOffset = cpu_to_le16(offset);
2725 /* construct random name ".cifs_tmp<inodenum><mid>" */
2726 rename_info->overwrite = cpu_to_le32(1);
2727 rename_info->root_fid = 0;
2728 /* unicode only call */
2729 if (target_name == NULL) {
2730 sprintf(dummy_string, "cifs%x", pSMB->hdr.Mid);
2732 cifsConvertToUTF16((__le16 *)rename_info->target_name,
2733 dummy_string, 24, nls_codepage, remap);
2736 cifsConvertToUTF16((__le16 *)rename_info->target_name,
2737 target_name, PATH_MAX, nls_codepage,
2740 rename_info->target_name_len = cpu_to_le32(2 * len_of_str);
2741 count = 12 /* sizeof(struct set_file_rename) */ + (2 * len_of_str);
2742 byte_count += count;
2743 pSMB->DataCount = cpu_to_le16(count);
2744 pSMB->TotalDataCount = pSMB->DataCount;
2746 pSMB->InformationLevel =
2747 cpu_to_le16(SMB_SET_FILE_RENAME_INFORMATION);
2748 pSMB->Reserved4 = 0;
2749 inc_rfc1001_len(pSMB, byte_count);
2750 pSMB->ByteCount = cpu_to_le16(byte_count);
2751 rc = SendReceive(xid, pTcon->ses, (struct smb_hdr *) pSMB,
2752 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2753 cifs_stats_inc(&pTcon->stats.cifs_stats.num_t2renames);
2755 cifs_dbg(FYI, "Send error in Rename (by file handle) = %d\n",
2758 cifs_buf_release(pSMB);
2760 /* Note: On -EAGAIN error only caller can retry on handle based calls
2761 since file handle passed in no longer valid */
2767 CIFSSMBCopy(const unsigned int xid, struct cifs_tcon *tcon,
2768 const char *fromName, const __u16 target_tid, const char *toName,
2769 const int flags, const struct nls_table *nls_codepage, int remap)
2772 COPY_REQ *pSMB = NULL;
2773 COPY_RSP *pSMBr = NULL;
2775 int name_len, name_len2;
2778 cifs_dbg(FYI, "In CIFSSMBCopy\n");
2780 rc = smb_init(SMB_COM_COPY, 1, tcon, (void **) &pSMB,
2785 pSMB->BufferFormat = 0x04;
2786 pSMB->Tid2 = target_tid;
2788 pSMB->Flags = cpu_to_le16(flags & COPY_TREE);
2790 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2791 name_len = cifsConvertToUTF16((__le16 *) pSMB->OldFileName,
2792 fromName, PATH_MAX, nls_codepage,
2794 name_len++; /* trailing null */
2796 pSMB->OldFileName[name_len] = 0x04; /* pad */
2797 /* protocol requires ASCII signature byte on Unicode string */
2798 pSMB->OldFileName[name_len + 1] = 0x00;
2800 cifsConvertToUTF16((__le16 *)&pSMB->OldFileName[name_len+2],
2801 toName, PATH_MAX, nls_codepage, remap);
2802 name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
2803 name_len2 *= 2; /* convert to bytes */
2804 } else { /* BB improve the check for buffer overruns BB */
2805 name_len = strnlen(fromName, PATH_MAX);
2806 name_len++; /* trailing null */
2807 strncpy(pSMB->OldFileName, fromName, name_len);
2808 name_len2 = strnlen(toName, PATH_MAX);
2809 name_len2++; /* trailing null */
2810 pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */
2811 strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2);
2812 name_len2++; /* trailing null */
2813 name_len2++; /* signature byte */
2816 count = 1 /* 1st signature byte */ + name_len + name_len2;
2817 inc_rfc1001_len(pSMB, count);
2818 pSMB->ByteCount = cpu_to_le16(count);
2820 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2821 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2823 cifs_dbg(FYI, "Send error in copy = %d with %d files copied\n",
2824 rc, le16_to_cpu(pSMBr->CopyCount));
2826 cifs_buf_release(pSMB);
2835 CIFSUnixCreateSymLink(const unsigned int xid, struct cifs_tcon *tcon,
2836 const char *fromName, const char *toName,
2837 const struct nls_table *nls_codepage, int remap)
2839 TRANSACTION2_SPI_REQ *pSMB = NULL;
2840 TRANSACTION2_SPI_RSP *pSMBr = NULL;
2843 int name_len_target;
2845 int bytes_returned = 0;
2846 __u16 params, param_offset, offset, byte_count;
2848 cifs_dbg(FYI, "In Symlink Unix style\n");
2850 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2855 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2857 cifsConvertToUTF16((__le16 *) pSMB->FileName, fromName,
2858 /* find define for this maxpathcomponent */
2859 PATH_MAX, nls_codepage, remap);
2860 name_len++; /* trailing null */
2863 } else { /* BB improve the check for buffer overruns BB */
2864 name_len = strnlen(fromName, PATH_MAX);
2865 name_len++; /* trailing null */
2866 strncpy(pSMB->FileName, fromName, name_len);
2868 params = 6 + name_len;
2869 pSMB->MaxSetupCount = 0;
2873 pSMB->Reserved2 = 0;
2874 param_offset = offsetof(struct smb_com_transaction2_spi_req,
2875 InformationLevel) - 4;
2876 offset = param_offset + params;
2878 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
2879 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2881 cifsConvertToUTF16((__le16 *) data_offset, toName,
2882 /* find define for this maxpathcomponent */
2883 PATH_MAX, nls_codepage, remap);
2884 name_len_target++; /* trailing null */
2885 name_len_target *= 2;
2886 } else { /* BB improve the check for buffer overruns BB */
2887 name_len_target = strnlen(toName, PATH_MAX);
2888 name_len_target++; /* trailing null */
2889 strncpy(data_offset, toName, name_len_target);
2892 pSMB->MaxParameterCount = cpu_to_le16(2);
2893 /* BB find exact max on data count below from sess */
2894 pSMB->MaxDataCount = cpu_to_le16(1000);
2895 pSMB->SetupCount = 1;
2896 pSMB->Reserved3 = 0;
2897 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
2898 byte_count = 3 /* pad */ + params + name_len_target;
2899 pSMB->DataCount = cpu_to_le16(name_len_target);
2900 pSMB->ParameterCount = cpu_to_le16(params);
2901 pSMB->TotalDataCount = pSMB->DataCount;
2902 pSMB->TotalParameterCount = pSMB->ParameterCount;
2903 pSMB->ParameterOffset = cpu_to_le16(param_offset);
2904 pSMB->DataOffset = cpu_to_le16(offset);
2905 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_LINK);
2906 pSMB->Reserved4 = 0;
2907 inc_rfc1001_len(pSMB, byte_count);
2908 pSMB->ByteCount = cpu_to_le16(byte_count);
2909 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2910 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2911 cifs_stats_inc(&tcon->stats.cifs_stats.num_symlinks);
2913 cifs_dbg(FYI, "Send error in SetPathInfo create symlink = %d\n",
2916 cifs_buf_release(pSMB);
2919 goto createSymLinkRetry;
2925 CIFSUnixCreateHardLink(const unsigned int xid, struct cifs_tcon *tcon,
2926 const char *fromName, const char *toName,
2927 const struct nls_table *nls_codepage, int remap)
2929 TRANSACTION2_SPI_REQ *pSMB = NULL;
2930 TRANSACTION2_SPI_RSP *pSMBr = NULL;
2933 int name_len_target;
2935 int bytes_returned = 0;
2936 __u16 params, param_offset, offset, byte_count;
2938 cifs_dbg(FYI, "In Create Hard link Unix style\n");
2939 createHardLinkRetry:
2940 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2945 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2946 name_len = cifsConvertToUTF16((__le16 *) pSMB->FileName, toName,
2947 PATH_MAX, nls_codepage, remap);
2948 name_len++; /* trailing null */
2951 } else { /* BB improve the check for buffer overruns BB */
2952 name_len = strnlen(toName, PATH_MAX);
2953 name_len++; /* trailing null */
2954 strncpy(pSMB->FileName, toName, name_len);
2956 params = 6 + name_len;
2957 pSMB->MaxSetupCount = 0;
2961 pSMB->Reserved2 = 0;
2962 param_offset = offsetof(struct smb_com_transaction2_spi_req,
2963 InformationLevel) - 4;
2964 offset = param_offset + params;
2966 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
2967 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2969 cifsConvertToUTF16((__le16 *) data_offset, fromName,
2970 PATH_MAX, nls_codepage, remap);
2971 name_len_target++; /* trailing null */
2972 name_len_target *= 2;
2973 } else { /* BB improve the check for buffer overruns BB */
2974 name_len_target = strnlen(fromName, PATH_MAX);
2975 name_len_target++; /* trailing null */
2976 strncpy(data_offset, fromName, name_len_target);
2979 pSMB->MaxParameterCount = cpu_to_le16(2);
2980 /* BB find exact max on data count below from sess*/
2981 pSMB->MaxDataCount = cpu_to_le16(1000);
2982 pSMB->SetupCount = 1;
2983 pSMB->Reserved3 = 0;
2984 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
2985 byte_count = 3 /* pad */ + params + name_len_target;
2986 pSMB->ParameterCount = cpu_to_le16(params);
2987 pSMB->TotalParameterCount = pSMB->ParameterCount;
2988 pSMB->DataCount = cpu_to_le16(name_len_target);
2989 pSMB->TotalDataCount = pSMB->DataCount;
2990 pSMB->ParameterOffset = cpu_to_le16(param_offset);
2991 pSMB->DataOffset = cpu_to_le16(offset);
2992 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_HLINK);
2993 pSMB->Reserved4 = 0;
2994 inc_rfc1001_len(pSMB, byte_count);
2995 pSMB->ByteCount = cpu_to_le16(byte_count);
2996 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2997 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2998 cifs_stats_inc(&tcon->stats.cifs_stats.num_hardlinks);
3000 cifs_dbg(FYI, "Send error in SetPathInfo (hard link) = %d\n",
3003 cifs_buf_release(pSMB);
3005 goto createHardLinkRetry;
3011 CIFSCreateHardLink(const unsigned int xid, struct cifs_tcon *tcon,
3012 const char *from_name, const char *to_name,
3013 struct cifs_sb_info *cifs_sb)
3016 NT_RENAME_REQ *pSMB = NULL;
3017 RENAME_RSP *pSMBr = NULL;
3019 int name_len, name_len2;
3021 int remap = cifs_remap(cifs_sb);
3023 cifs_dbg(FYI, "In CIFSCreateHardLink\n");
3024 winCreateHardLinkRetry:
3026 rc = smb_init(SMB_COM_NT_RENAME, 4, tcon, (void **) &pSMB,
3031 pSMB->SearchAttributes =
3032 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
3034 pSMB->Flags = cpu_to_le16(CREATE_HARD_LINK);
3035 pSMB->ClusterCount = 0;
3037 pSMB->BufferFormat = 0x04;
3039 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3041 cifsConvertToUTF16((__le16 *) pSMB->OldFileName, from_name,
3042 PATH_MAX, cifs_sb->local_nls, remap);
3043 name_len++; /* trailing null */
3046 /* protocol specifies ASCII buffer format (0x04) for unicode */
3047 pSMB->OldFileName[name_len] = 0x04;
3048 pSMB->OldFileName[name_len + 1] = 0x00; /* pad */
3050 cifsConvertToUTF16((__le16 *)&pSMB->OldFileName[name_len+2],
3051 to_name, PATH_MAX, cifs_sb->local_nls,
3053 name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
3054 name_len2 *= 2; /* convert to bytes */
3055 } else { /* BB improve the check for buffer overruns BB */
3056 name_len = strnlen(from_name, PATH_MAX);
3057 name_len++; /* trailing null */
3058 strncpy(pSMB->OldFileName, from_name, name_len);
3059 name_len2 = strnlen(to_name, PATH_MAX);
3060 name_len2++; /* trailing null */
3061 pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */
3062 strncpy(&pSMB->OldFileName[name_len + 1], to_name, name_len2);
3063 name_len2++; /* trailing null */
3064 name_len2++; /* signature byte */
3067 count = 1 /* string type byte */ + name_len + name_len2;
3068 inc_rfc1001_len(pSMB, count);
3069 pSMB->ByteCount = cpu_to_le16(count);
3071 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3072 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3073 cifs_stats_inc(&tcon->stats.cifs_stats.num_hardlinks);
3075 cifs_dbg(FYI, "Send error in hard link (NT rename) = %d\n", rc);
3077 cifs_buf_release(pSMB);
3079 goto winCreateHardLinkRetry;
3085 CIFSSMBUnixQuerySymLink(const unsigned int xid, struct cifs_tcon *tcon,
3086 const unsigned char *searchName, char **symlinkinfo,
3087 const struct nls_table *nls_codepage, int remap)
3089 /* SMB_QUERY_FILE_UNIX_LINK */
3090 TRANSACTION2_QPI_REQ *pSMB = NULL;
3091 TRANSACTION2_QPI_RSP *pSMBr = NULL;
3095 __u16 params, byte_count;
3098 cifs_dbg(FYI, "In QPathSymLinkInfo (Unix) for path %s\n", searchName);
3101 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3106 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3108 cifsConvertToUTF16((__le16 *) pSMB->FileName,
3109 searchName, PATH_MAX, nls_codepage,
3111 name_len++; /* trailing null */
3113 } else { /* BB improve the check for buffer overruns BB */
3114 name_len = strnlen(searchName, PATH_MAX);
3115 name_len++; /* trailing null */
3116 strncpy(pSMB->FileName, searchName, name_len);
3119 params = 2 /* level */ + 4 /* rsrvd */ + name_len /* incl null */ ;
3120 pSMB->TotalDataCount = 0;
3121 pSMB->MaxParameterCount = cpu_to_le16(2);
3122 pSMB->MaxDataCount = cpu_to_le16(CIFSMaxBufSize);
3123 pSMB->MaxSetupCount = 0;
3127 pSMB->Reserved2 = 0;
3128 pSMB->ParameterOffset = cpu_to_le16(offsetof(
3129 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
3130 pSMB->DataCount = 0;
3131 pSMB->DataOffset = 0;
3132 pSMB->SetupCount = 1;
3133 pSMB->Reserved3 = 0;
3134 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
3135 byte_count = params + 1 /* pad */ ;
3136 pSMB->TotalParameterCount = cpu_to_le16(params);
3137 pSMB->ParameterCount = pSMB->TotalParameterCount;
3138 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_LINK);
3139 pSMB->Reserved4 = 0;
3140 inc_rfc1001_len(pSMB, byte_count);
3141 pSMB->ByteCount = cpu_to_le16(byte_count);
3143 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3144 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3146 cifs_dbg(FYI, "Send error in QuerySymLinkInfo = %d\n", rc);
3148 /* decode response */
3150 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3151 /* BB also check enough total bytes returned */
3152 if (rc || get_bcc(&pSMBr->hdr) < 2)
3156 u16 count = le16_to_cpu(pSMBr->t2.DataCount);
3158 data_start = ((char *) &pSMBr->hdr.Protocol) +
3159 le16_to_cpu(pSMBr->t2.DataOffset);
3161 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
3166 /* BB FIXME investigate remapping reserved chars here */
3167 *symlinkinfo = cifs_strndup_from_utf16(data_start,
3168 count, is_unicode, nls_codepage);
3173 cifs_buf_release(pSMB);
3175 goto querySymLinkRetry;
3180 * Recent Windows versions now create symlinks more frequently
3181 * and they use the "reparse point" mechanism below. We can of course
3182 * do symlinks nicely to Samba and other servers which support the
3183 * CIFS Unix Extensions and we can also do SFU symlinks and "client only"
3184 * "MF" symlinks optionally, but for recent Windows we really need to
3185 * reenable the code below and fix the cifs_symlink callers to handle this.
3186 * In the interim this code has been moved to its own config option so
3187 * it is not compiled in by default until callers fixed up and more tested.
3190 CIFSSMBQuerySymLink(const unsigned int xid, struct cifs_tcon *tcon,
3191 __u16 fid, char **symlinkinfo,
3192 const struct nls_table *nls_codepage)
3196 struct smb_com_transaction_ioctl_req *pSMB;
3197 struct smb_com_transaction_ioctl_rsp *pSMBr;
3199 unsigned int sub_len;
3201 struct reparse_symlink_data *reparse_buf;
3202 struct reparse_posix_data *posix_buf;
3203 __u32 data_offset, data_count;
3206 cifs_dbg(FYI, "In Windows reparse style QueryLink for fid %u\n", fid);
3207 rc = smb_init(SMB_COM_NT_TRANSACT, 23, tcon, (void **) &pSMB,
3212 pSMB->TotalParameterCount = 0 ;
3213 pSMB->TotalDataCount = 0;
3214 pSMB->MaxParameterCount = cpu_to_le32(2);
3215 /* BB find exact data count max from sess structure BB */
3216 pSMB->MaxDataCount = cpu_to_le32(CIFSMaxBufSize & 0xFFFFFF00);
3217 pSMB->MaxSetupCount = 4;
3219 pSMB->ParameterOffset = 0;
3220 pSMB->DataCount = 0;
3221 pSMB->DataOffset = 0;
3222 pSMB->SetupCount = 4;
3223 pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_IOCTL);
3224 pSMB->ParameterCount = pSMB->TotalParameterCount;
3225 pSMB->FunctionCode = cpu_to_le32(FSCTL_GET_REPARSE_POINT);
3226 pSMB->IsFsctl = 1; /* FSCTL */
3227 pSMB->IsRootFlag = 0;
3228 pSMB->Fid = fid; /* file handle always le */
3229 pSMB->ByteCount = 0;
3231 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3232 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3234 cifs_dbg(FYI, "Send error in QueryReparseLinkInfo = %d\n", rc);
3238 data_offset = le32_to_cpu(pSMBr->DataOffset);
3239 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)) {
3247 cifs_dbg(FYI, "Invalid return data count on get reparse info ioctl\n");
3250 end_of_smb = 2 + get_bcc(&pSMBr->hdr) + (char *)&pSMBr->ByteCount;
3251 reparse_buf = (struct reparse_symlink_data *)
3252 ((char *)&pSMBr->hdr.Protocol + data_offset);
3253 if ((char *)reparse_buf >= end_of_smb) {
3257 if (reparse_buf->ReparseTag == cpu_to_le32(IO_REPARSE_TAG_NFS)) {
3258 cifs_dbg(FYI, "NFS style reparse tag\n");
3259 posix_buf = (struct reparse_posix_data *)reparse_buf;
3261 if (posix_buf->InodeType != cpu_to_le64(NFS_SPECFILE_LNK)) {
3262 cifs_dbg(FYI, "unsupported file type 0x%llx\n",
3263 le64_to_cpu(posix_buf->InodeType));
3268 sub_len = le16_to_cpu(reparse_buf->ReparseDataLength);
3269 if (posix_buf->PathBuffer + sub_len > end_of_smb) {
3270 cifs_dbg(FYI, "reparse buf beyond SMB\n");
3274 *symlinkinfo = cifs_strndup_from_utf16(posix_buf->PathBuffer,
3275 sub_len, is_unicode, nls_codepage);
3277 } else if (reparse_buf->ReparseTag !=
3278 cpu_to_le32(IO_REPARSE_TAG_SYMLINK)) {
3283 /* Reparse tag is NTFS symlink */
3284 sub_start = le16_to_cpu(reparse_buf->SubstituteNameOffset) +
3285 reparse_buf->PathBuffer;
3286 sub_len = le16_to_cpu(reparse_buf->SubstituteNameLength);
3287 if (sub_start + sub_len > end_of_smb) {
3288 cifs_dbg(FYI, "reparse buf beyond SMB\n");
3292 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
3297 /* BB FIXME investigate remapping reserved chars here */
3298 *symlinkinfo = cifs_strndup_from_utf16(sub_start, sub_len, is_unicode,
3303 cifs_buf_release(pSMB);
3306 * Note: On -EAGAIN error only caller can retry on handle based calls
3307 * since file handle passed in no longer valid.
3313 CIFSSMB_set_compression(const unsigned int xid, struct cifs_tcon *tcon,
3318 struct smb_com_transaction_compr_ioctl_req *pSMB;
3319 struct smb_com_transaction_ioctl_rsp *pSMBr;
3321 cifs_dbg(FYI, "Set compression for %u\n", fid);
3322 rc = smb_init(SMB_COM_NT_TRANSACT, 23, tcon, (void **) &pSMB,
3327 pSMB->compression_state = cpu_to_le16(COMPRESSION_FORMAT_DEFAULT);
3329 pSMB->TotalParameterCount = 0;
3330 pSMB->TotalDataCount = cpu_to_le32(2);
3331 pSMB->MaxParameterCount = 0;
3332 pSMB->MaxDataCount = 0;
3333 pSMB->MaxSetupCount = 4;
3335 pSMB->ParameterOffset = 0;
3336 pSMB->DataCount = cpu_to_le32(2);
3338 cpu_to_le32(offsetof(struct smb_com_transaction_compr_ioctl_req,
3339 compression_state) - 4); /* 84 */
3340 pSMB->SetupCount = 4;
3341 pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_IOCTL);
3342 pSMB->ParameterCount = 0;
3343 pSMB->FunctionCode = cpu_to_le32(FSCTL_SET_COMPRESSION);
3344 pSMB->IsFsctl = 1; /* FSCTL */
3345 pSMB->IsRootFlag = 0;
3346 pSMB->Fid = fid; /* file handle always le */
3347 /* 3 byte pad, followed by 2 byte compress state */
3348 pSMB->ByteCount = cpu_to_le16(5);
3349 inc_rfc1001_len(pSMB, 5);
3351 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3352 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3354 cifs_dbg(FYI, "Send error in SetCompression = %d\n", rc);
3356 cifs_buf_release(pSMB);
3359 * Note: On -EAGAIN error only caller can retry on handle based calls
3360 * since file handle passed in no longer valid.
3366 #ifdef CONFIG_CIFS_POSIX
3368 /*Convert an Access Control Entry from wire format to local POSIX xattr format*/
3369 static void cifs_convert_ace(struct posix_acl_xattr_entry *ace,
3370 struct cifs_posix_ace *cifs_ace)
3372 /* u8 cifs fields do not need le conversion */
3373 ace->e_perm = cpu_to_le16(cifs_ace->cifs_e_perm);
3374 ace->e_tag = cpu_to_le16(cifs_ace->cifs_e_tag);
3375 ace->e_id = cpu_to_le32(le64_to_cpu(cifs_ace->cifs_uid));
3377 cifs_dbg(FYI, "perm %d tag %d id %d\n",
3378 ace->e_perm, ace->e_tag, ace->e_id);
3384 /* Convert ACL from CIFS POSIX wire format to local Linux POSIX ACL xattr */
3385 static int cifs_copy_posix_acl(char *trgt, char *src, const int buflen,
3386 const int acl_type, const int size_of_data_area)
3391 struct cifs_posix_ace *pACE;
3392 struct cifs_posix_acl *cifs_acl = (struct cifs_posix_acl *)src;
3393 struct posix_acl_xattr_header *local_acl = (void *)trgt;
3395 if (le16_to_cpu(cifs_acl->version) != CIFS_ACL_VERSION)
3398 if (acl_type == ACL_TYPE_ACCESS) {
3399 count = le16_to_cpu(cifs_acl->access_entry_count);
3400 pACE = &cifs_acl->ace_array[0];
3401 size = sizeof(struct cifs_posix_acl);
3402 size += sizeof(struct cifs_posix_ace) * count;
3403 /* check if we would go beyond end of SMB */
3404 if (size_of_data_area < size) {
3405 cifs_dbg(FYI, "bad CIFS POSIX ACL size %d vs. %d\n",
3406 size_of_data_area, size);
3409 } else if (acl_type == ACL_TYPE_DEFAULT) {
3410 count = le16_to_cpu(cifs_acl->access_entry_count);
3411 size = sizeof(struct cifs_posix_acl);
3412 size += sizeof(struct cifs_posix_ace) * count;
3413 /* skip past access ACEs to get to default ACEs */
3414 pACE = &cifs_acl->ace_array[count];
3415 count = le16_to_cpu(cifs_acl->default_entry_count);
3416 size += sizeof(struct cifs_posix_ace) * count;
3417 /* check if we would go beyond end of SMB */
3418 if (size_of_data_area < size)
3425 size = posix_acl_xattr_size(count);
3426 if ((buflen == 0) || (local_acl == NULL)) {
3427 /* used to query ACL EA size */
3428 } else if (size > buflen) {
3430 } else /* buffer big enough */ {
3431 struct posix_acl_xattr_entry *ace = (void *)(local_acl + 1);
3433 local_acl->a_version = cpu_to_le32(POSIX_ACL_XATTR_VERSION);
3434 for (i = 0; i < count ; i++) {
3435 cifs_convert_ace(&ace[i], pACE);
3442 static __u16 convert_ace_to_cifs_ace(struct cifs_posix_ace *cifs_ace,
3443 const struct posix_acl_xattr_entry *local_ace)
3445 __u16 rc = 0; /* 0 = ACL converted ok */
3447 cifs_ace->cifs_e_perm = le16_to_cpu(local_ace->e_perm);
3448 cifs_ace->cifs_e_tag = le16_to_cpu(local_ace->e_tag);
3449 /* BB is there a better way to handle the large uid? */
3450 if (local_ace->e_id == cpu_to_le32(-1)) {
3451 /* Probably no need to le convert -1 on any arch but can not hurt */
3452 cifs_ace->cifs_uid = cpu_to_le64(-1);
3454 cifs_ace->cifs_uid = cpu_to_le64(le32_to_cpu(local_ace->e_id));
3456 cifs_dbg(FYI, "perm %d tag %d id %d\n",
3457 ace->e_perm, ace->e_tag, ace->e_id);
3462 /* Convert ACL from local Linux POSIX xattr to CIFS POSIX ACL wire format */
3463 static __u16 ACL_to_cifs_posix(char *parm_data, const char *pACL,
3464 const int buflen, const int acl_type)
3467 struct cifs_posix_acl *cifs_acl = (struct cifs_posix_acl *)parm_data;
3468 struct posix_acl_xattr_header *local_acl = (void *)pACL;
3469 struct posix_acl_xattr_entry *ace = (void *)(local_acl + 1);
3473 if ((buflen == 0) || (pACL == NULL) || (cifs_acl == NULL))
3476 count = posix_acl_xattr_count((size_t)buflen);
3477 cifs_dbg(FYI, "setting acl with %d entries from buf of length %d and version of %d\n",
3478 count, buflen, le32_to_cpu(local_acl->a_version));
3479 if (le32_to_cpu(local_acl->a_version) != 2) {
3480 cifs_dbg(FYI, "unknown POSIX ACL version %d\n",
3481 le32_to_cpu(local_acl->a_version));
3484 cifs_acl->version = cpu_to_le16(1);
3485 if (acl_type == ACL_TYPE_ACCESS) {
3486 cifs_acl->access_entry_count = cpu_to_le16(count);
3487 cifs_acl->default_entry_count = cpu_to_le16(0xFFFF);
3488 } else if (acl_type == ACL_TYPE_DEFAULT) {
3489 cifs_acl->default_entry_count = cpu_to_le16(count);
3490 cifs_acl->access_entry_count = cpu_to_le16(0xFFFF);
3492 cifs_dbg(FYI, "unknown ACL type %d\n", acl_type);
3495 for (i = 0; i < count; i++) {
3496 rc = convert_ace_to_cifs_ace(&cifs_acl->ace_array[i], &ace[i]);
3498 /* ACE not converted */
3503 rc = (__u16)(count * sizeof(struct cifs_posix_ace));
3504 rc += sizeof(struct cifs_posix_acl);
3505 /* BB add check to make sure ACL does not overflow SMB */
3511 CIFSSMBGetPosixACL(const unsigned int xid, struct cifs_tcon *tcon,
3512 const unsigned char *searchName,
3513 char *acl_inf, const int buflen, const int acl_type,
3514 const struct nls_table *nls_codepage, int remap)
3516 /* SMB_QUERY_POSIX_ACL */
3517 TRANSACTION2_QPI_REQ *pSMB = NULL;
3518 TRANSACTION2_QPI_RSP *pSMBr = NULL;
3522 __u16 params, byte_count;
3524 cifs_dbg(FYI, "In GetPosixACL (Unix) for path %s\n", searchName);
3527 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3532 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3534 cifsConvertToUTF16((__le16 *) pSMB->FileName,
3535 searchName, PATH_MAX, nls_codepage,
3537 name_len++; /* trailing null */
3539 pSMB->FileName[name_len] = 0;
3540 pSMB->FileName[name_len+1] = 0;
3541 } else { /* BB improve the check for buffer overruns BB */
3542 name_len = strnlen(searchName, PATH_MAX);
3543 name_len++; /* trailing null */
3544 strncpy(pSMB->FileName, searchName, name_len);
3547 params = 2 /* level */ + 4 /* rsrvd */ + name_len /* incl null */ ;
3548 pSMB->TotalDataCount = 0;
3549 pSMB->MaxParameterCount = cpu_to_le16(2);
3550 /* BB find exact max data count below from sess structure BB */
3551 pSMB->MaxDataCount = cpu_to_le16(4000);
3552 pSMB->MaxSetupCount = 0;
3556 pSMB->Reserved2 = 0;
3557 pSMB->ParameterOffset = cpu_to_le16(
3558 offsetof(struct smb_com_transaction2_qpi_req,
3559 InformationLevel) - 4);
3560 pSMB->DataCount = 0;
3561 pSMB->DataOffset = 0;
3562 pSMB->SetupCount = 1;
3563 pSMB->Reserved3 = 0;
3564 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
3565 byte_count = params + 1 /* pad */ ;
3566 pSMB->TotalParameterCount = cpu_to_le16(params);
3567 pSMB->ParameterCount = pSMB->TotalParameterCount;
3568 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_POSIX_ACL);
3569 pSMB->Reserved4 = 0;
3570 inc_rfc1001_len(pSMB, byte_count);
3571 pSMB->ByteCount = cpu_to_le16(byte_count);
3573 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3574 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3575 cifs_stats_inc(&tcon->stats.cifs_stats.num_acl_get);
3577 cifs_dbg(FYI, "Send error in Query POSIX ACL = %d\n", rc);
3579 /* decode response */
3581 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3582 /* BB also check enough total bytes returned */
3583 if (rc || get_bcc(&pSMBr->hdr) < 2)
3584 rc = -EIO; /* bad smb */
3586 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3587 __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
3588 rc = cifs_copy_posix_acl(acl_inf,
3589 (char *)&pSMBr->hdr.Protocol+data_offset,
3590 buflen, acl_type, count);
3593 cifs_buf_release(pSMB);
3600 CIFSSMBSetPosixACL(const unsigned int xid, struct cifs_tcon *tcon,
3601 const unsigned char *fileName,
3602 const char *local_acl, const int buflen,
3604 const struct nls_table *nls_codepage, int remap)
3606 struct smb_com_transaction2_spi_req *pSMB = NULL;
3607 struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
3611 int bytes_returned = 0;
3612 __u16 params, byte_count, data_count, param_offset, offset;
3614 cifs_dbg(FYI, "In SetPosixACL (Unix) for path %s\n", fileName);
3616 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3620 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3622 cifsConvertToUTF16((__le16 *) pSMB->FileName, fileName,
3623 PATH_MAX, nls_codepage, remap);
3624 name_len++; /* trailing null */
3626 } else { /* BB improve the check for buffer overruns BB */
3627 name_len = strnlen(fileName, PATH_MAX);
3628 name_len++; /* trailing null */
3629 strncpy(pSMB->FileName, fileName, name_len);
3631 params = 6 + name_len;
3632 pSMB->MaxParameterCount = cpu_to_le16(2);
3633 /* BB find max SMB size from sess */
3634 pSMB->MaxDataCount = cpu_to_le16(1000);
3635 pSMB->MaxSetupCount = 0;
3639 pSMB->Reserved2 = 0;
3640 param_offset = offsetof(struct smb_com_transaction2_spi_req,
3641 InformationLevel) - 4;
3642 offset = param_offset + params;
3643 parm_data = ((char *) &pSMB->hdr.Protocol) + offset;
3644 pSMB->ParameterOffset = cpu_to_le16(param_offset);
3646 /* convert to on the wire format for POSIX ACL */
3647 data_count = ACL_to_cifs_posix(parm_data, local_acl, buflen, acl_type);
3649 if (data_count == 0) {
3651 goto setACLerrorExit;
3653 pSMB->DataOffset = cpu_to_le16(offset);
3654 pSMB->SetupCount = 1;
3655 pSMB->Reserved3 = 0;
3656 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
3657 pSMB->InformationLevel = cpu_to_le16(SMB_SET_POSIX_ACL);
3658 byte_count = 3 /* pad */ + params + data_count;
3659 pSMB->DataCount = cpu_to_le16(data_count);
3660 pSMB->TotalDataCount = pSMB->DataCount;
3661 pSMB->ParameterCount = cpu_to_le16(params);
3662 pSMB->TotalParameterCount = pSMB->ParameterCount;
3663 pSMB->Reserved4 = 0;
3664 inc_rfc1001_len(pSMB, byte_count);
3665 pSMB->ByteCount = cpu_to_le16(byte_count);
3666 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3667 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3669 cifs_dbg(FYI, "Set POSIX ACL returned %d\n", rc);
3672 cifs_buf_release(pSMB);
3678 /* BB fix tabs in this function FIXME BB */
3680 CIFSGetExtAttr(const unsigned int xid, struct cifs_tcon *tcon,
3681 const int netfid, __u64 *pExtAttrBits, __u64 *pMask)
3684 struct smb_t2_qfi_req *pSMB = NULL;
3685 struct smb_t2_qfi_rsp *pSMBr = NULL;
3687 __u16 params, byte_count;
3689 cifs_dbg(FYI, "In GetExtAttr\n");
3694 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3699 params = 2 /* level */ + 2 /* fid */;
3700 pSMB->t2.TotalDataCount = 0;
3701 pSMB->t2.MaxParameterCount = cpu_to_le16(4);
3702 /* BB find exact max data count below from sess structure BB */
3703 pSMB->t2.MaxDataCount = cpu_to_le16(4000);
3704 pSMB->t2.MaxSetupCount = 0;
3705 pSMB->t2.Reserved = 0;
3707 pSMB->t2.Timeout = 0;
3708 pSMB->t2.Reserved2 = 0;
3709 pSMB->t2.ParameterOffset = cpu_to_le16(offsetof(struct smb_t2_qfi_req,
3711 pSMB->t2.DataCount = 0;
3712 pSMB->t2.DataOffset = 0;
3713 pSMB->t2.SetupCount = 1;
3714 pSMB->t2.Reserved3 = 0;
3715 pSMB->t2.SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION);
3716 byte_count = params + 1 /* pad */ ;
3717 pSMB->t2.TotalParameterCount = cpu_to_le16(params);
3718 pSMB->t2.ParameterCount = pSMB->t2.TotalParameterCount;
3719 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_ATTR_FLAGS);
3722 inc_rfc1001_len(pSMB, byte_count);
3723 pSMB->t2.ByteCount = cpu_to_le16(byte_count);
3725 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3726 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3728 cifs_dbg(FYI, "error %d in GetExtAttr\n", rc);
3730 /* decode response */
3731 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3732 /* BB also check enough total bytes returned */
3733 if (rc || get_bcc(&pSMBr->hdr) < 2)
3734 /* If rc should we check for EOPNOSUPP and
3735 disable the srvino flag? or in caller? */
3736 rc = -EIO; /* bad smb */
3738 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3739 __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
3740 struct file_chattr_info *pfinfo;
3741 /* BB Do we need a cast or hash here ? */
3743 cifs_dbg(FYI, "Illegal size ret in GetExtAttr\n");
3747 pfinfo = (struct file_chattr_info *)
3748 (data_offset + (char *) &pSMBr->hdr.Protocol);
3749 *pExtAttrBits = le64_to_cpu(pfinfo->mode);
3750 *pMask = le64_to_cpu(pfinfo->mask);
3754 cifs_buf_release(pSMB);
3756 goto GetExtAttrRetry;
3760 #endif /* CONFIG_POSIX */
3762 #ifdef CONFIG_CIFS_ACL
3764 * Initialize NT TRANSACT SMB into small smb request buffer. This assumes that
3765 * all NT TRANSACTS that we init here have total parm and data under about 400
3766 * bytes (to fit in small cifs buffer size), which is the case so far, it
3767 * easily fits. NB: Setup words themselves and ByteCount MaxSetupCount (size of
3768 * returned setup area) and MaxParameterCount (returned parms size) must be set
3772 smb_init_nttransact(const __u16 sub_command, const int setup_count,
3773 const int parm_len, struct cifs_tcon *tcon,
3778 struct smb_com_ntransact_req *pSMB;
3780 rc = small_smb_init(SMB_COM_NT_TRANSACT, 19 + setup_count, tcon,
3784 *ret_buf = (void *)pSMB;
3786 pSMB->TotalParameterCount = cpu_to_le32(parm_len);
3787 pSMB->TotalDataCount = 0;
3788 pSMB->MaxDataCount = cpu_to_le32(CIFSMaxBufSize & 0xFFFFFF00);
3789 pSMB->ParameterCount = pSMB->TotalParameterCount;
3790 pSMB->DataCount = pSMB->TotalDataCount;
3791 temp_offset = offsetof(struct smb_com_ntransact_req, Parms) +
3792 (setup_count * 2) - 4 /* for rfc1001 length itself */;
3793 pSMB->ParameterOffset = cpu_to_le32(temp_offset);
3794 pSMB->DataOffset = cpu_to_le32(temp_offset + parm_len);
3795 pSMB->SetupCount = setup_count; /* no need to le convert byte fields */
3796 pSMB->SubCommand = cpu_to_le16(sub_command);
3801 validate_ntransact(char *buf, char **ppparm, char **ppdata,
3802 __u32 *pparmlen, __u32 *pdatalen)
3805 __u32 data_count, data_offset, parm_count, parm_offset;
3806 struct smb_com_ntransact_rsp *pSMBr;
3815 pSMBr = (struct smb_com_ntransact_rsp *)buf;
3817 bcc = get_bcc(&pSMBr->hdr);
3818 end_of_smb = 2 /* sizeof byte count */ + bcc +
3819 (char *)&pSMBr->ByteCount;
3821 data_offset = le32_to_cpu(pSMBr->DataOffset);
3822 data_count = le32_to_cpu(pSMBr->DataCount);
3823 parm_offset = le32_to_cpu(pSMBr->ParameterOffset);
3824 parm_count = le32_to_cpu(pSMBr->ParameterCount);
3826 *ppparm = (char *)&pSMBr->hdr.Protocol + parm_offset;
3827 *ppdata = (char *)&pSMBr->hdr.Protocol + data_offset;
3829 /* should we also check that parm and data areas do not overlap? */
3830 if (*ppparm > end_of_smb) {
3831 cifs_dbg(FYI, "parms start after end of smb\n");
3833 } else if (parm_count + *ppparm > end_of_smb) {
3834 cifs_dbg(FYI, "parm end after end of smb\n");
3836 } else if (*ppdata > end_of_smb) {
3837 cifs_dbg(FYI, "data starts after end of smb\n");
3839 } else if (data_count + *ppdata > end_of_smb) {
3840 cifs_dbg(FYI, "data %p + count %d (%p) past smb end %p start %p\n",
3841 *ppdata, data_count, (data_count + *ppdata),
3844 } else if (parm_count + data_count > bcc) {
3845 cifs_dbg(FYI, "parm count and data count larger than SMB\n");
3848 *pdatalen = data_count;
3849 *pparmlen = parm_count;
3853 /* Get Security Descriptor (by handle) from remote server for a file or dir */
3855 CIFSSMBGetCIFSACL(const unsigned int xid, struct cifs_tcon *tcon, __u16 fid,
3856 struct cifs_ntsd **acl_inf, __u32 *pbuflen)
3860 QUERY_SEC_DESC_REQ *pSMB;
3862 struct kvec rsp_iov;
3864 cifs_dbg(FYI, "GetCifsACL\n");
3869 rc = smb_init_nttransact(NT_TRANSACT_QUERY_SECURITY_DESC, 0,
3870 8 /* parm len */, tcon, (void **) &pSMB);
3874 pSMB->MaxParameterCount = cpu_to_le32(4);
3875 /* BB TEST with big acls that might need to be e.g. larger than 16K */
3876 pSMB->MaxSetupCount = 0;
3877 pSMB->Fid = fid; /* file handle always le */
3878 pSMB->AclFlags = cpu_to_le32(CIFS_ACL_OWNER | CIFS_ACL_GROUP |
3880 pSMB->ByteCount = cpu_to_le16(11); /* 3 bytes pad + 8 bytes parm */
3881 inc_rfc1001_len(pSMB, 11);
3882 iov[0].iov_base = (char *)pSMB;
3883 iov[0].iov_len = be32_to_cpu(pSMB->hdr.smb_buf_length) + 4;
3885 rc = SendReceive2(xid, tcon->ses, iov, 1 /* num iovec */, &buf_type,
3887 cifs_small_buf_release(pSMB);
3888 cifs_stats_inc(&tcon->stats.cifs_stats.num_acl_get);
3890 cifs_dbg(FYI, "Send error in QuerySecDesc = %d\n", rc);
3891 } else { /* decode response */
3895 struct smb_com_ntransact_rsp *pSMBr;
3898 /* validate_nttransact */
3899 rc = validate_ntransact(rsp_iov.iov_base, (char **)&parm,
3900 &pdata, &parm_len, pbuflen);
3903 pSMBr = (struct smb_com_ntransact_rsp *)rsp_iov.iov_base;
3905 cifs_dbg(FYI, "smb %p parm %p data %p\n",
3906 pSMBr, parm, *acl_inf);
3908 if (le32_to_cpu(pSMBr->ParameterCount) != 4) {
3909 rc = -EIO; /* bad smb */
3914 /* BB check that data area is minimum length and as big as acl_len */
3916 acl_len = le32_to_cpu(*parm);
3917 if (acl_len != *pbuflen) {
3918 cifs_dbg(VFS, "acl length %d does not match %d\n",
3920 if (*pbuflen > acl_len)
3924 /* check if buffer is big enough for the acl
3925 header followed by the smallest SID */
3926 if ((*pbuflen < sizeof(struct cifs_ntsd) + 8) ||
3927 (*pbuflen >= 64 * 1024)) {
3928 cifs_dbg(VFS, "bad acl length %d\n", *pbuflen);
3932 *acl_inf = kmemdup(pdata, *pbuflen, GFP_KERNEL);
3933 if (*acl_inf == NULL) {
3940 free_rsp_buf(buf_type, rsp_iov.iov_base);
3945 CIFSSMBSetCIFSACL(const unsigned int xid, struct cifs_tcon *tcon, __u16 fid,
3946 struct cifs_ntsd *pntsd, __u32 acllen, int aclflag)
3948 __u16 byte_count, param_count, data_count, param_offset, data_offset;
3950 int bytes_returned = 0;
3951 SET_SEC_DESC_REQ *pSMB = NULL;
3955 rc = smb_init(SMB_COM_NT_TRANSACT, 19, tcon, (void **) &pSMB, &pSMBr);
3959 pSMB->MaxSetupCount = 0;
3963 param_offset = offsetof(struct smb_com_transaction_ssec_req, Fid) - 4;
3964 data_count = acllen;
3965 data_offset = param_offset + param_count;
3966 byte_count = 3 /* pad */ + param_count;
3968 pSMB->DataCount = cpu_to_le32(data_count);
3969 pSMB->TotalDataCount = pSMB->DataCount;
3970 pSMB->MaxParameterCount = cpu_to_le32(4);
3971 pSMB->MaxDataCount = cpu_to_le32(16384);
3972 pSMB->ParameterCount = cpu_to_le32(param_count);
3973 pSMB->ParameterOffset = cpu_to_le32(param_offset);
3974 pSMB->TotalParameterCount = pSMB->ParameterCount;
3975 pSMB->DataOffset = cpu_to_le32(data_offset);
3976 pSMB->SetupCount = 0;
3977 pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_SET_SECURITY_DESC);
3978 pSMB->ByteCount = cpu_to_le16(byte_count+data_count);
3980 pSMB->Fid = fid; /* file handle always le */
3981 pSMB->Reserved2 = 0;
3982 pSMB->AclFlags = cpu_to_le32(aclflag);
3984 if (pntsd && acllen) {
3985 memcpy((char *)pSMBr + offsetof(struct smb_hdr, Protocol) +
3986 data_offset, pntsd, acllen);
3987 inc_rfc1001_len(pSMB, byte_count + data_count);
3989 inc_rfc1001_len(pSMB, byte_count);
3991 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3992 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3994 cifs_dbg(FYI, "SetCIFSACL bytes_returned: %d, rc: %d\n",
3995 bytes_returned, rc);
3997 cifs_dbg(FYI, "Set CIFS ACL returned %d\n", rc);
3998 cifs_buf_release(pSMB);
4001 goto setCifsAclRetry;
4006 #endif /* CONFIG_CIFS_ACL */
4008 /* Legacy Query Path Information call for lookup to old servers such
4011 SMBQueryInformation(const unsigned int xid, struct cifs_tcon *tcon,
4012 const char *search_name, FILE_ALL_INFO *data,
4013 const struct nls_table *nls_codepage, int remap)
4015 QUERY_INFORMATION_REQ *pSMB;
4016 QUERY_INFORMATION_RSP *pSMBr;
4021 cifs_dbg(FYI, "In SMBQPath path %s\n", search_name);
4023 rc = smb_init(SMB_COM_QUERY_INFORMATION, 0, tcon, (void **) &pSMB,
4028 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4030 cifsConvertToUTF16((__le16 *) pSMB->FileName,
4031 search_name, PATH_MAX, nls_codepage,
4033 name_len++; /* trailing null */
4036 name_len = strnlen(search_name, PATH_MAX);
4037 name_len++; /* trailing null */
4038 strncpy(pSMB->FileName, search_name, name_len);
4040 pSMB->BufferFormat = 0x04;
4041 name_len++; /* account for buffer type byte */
4042 inc_rfc1001_len(pSMB, (__u16)name_len);
4043 pSMB->ByteCount = cpu_to_le16(name_len);
4045 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4046 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4048 cifs_dbg(FYI, "Send error in QueryInfo = %d\n", rc);
4051 __u32 time = le32_to_cpu(pSMBr->last_write_time);
4053 /* decode response */
4054 /* BB FIXME - add time zone adjustment BB */
4055 memset(data, 0, sizeof(FILE_ALL_INFO));
4058 /* decode time fields */
4059 data->ChangeTime = cpu_to_le64(cifs_UnixTimeToNT(ts));
4060 data->LastWriteTime = data->ChangeTime;
4061 data->LastAccessTime = 0;
4062 data->AllocationSize =
4063 cpu_to_le64(le32_to_cpu(pSMBr->size));
4064 data->EndOfFile = data->AllocationSize;
4066 cpu_to_le32(le16_to_cpu(pSMBr->attr));
4068 rc = -EIO; /* bad buffer passed in */
4070 cifs_buf_release(pSMB);
4079 CIFSSMBQFileInfo(const unsigned int xid, struct cifs_tcon *tcon,
4080 u16 netfid, FILE_ALL_INFO *pFindData)
4082 struct smb_t2_qfi_req *pSMB = NULL;
4083 struct smb_t2_qfi_rsp *pSMBr = NULL;
4086 __u16 params, byte_count;
4089 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4094 params = 2 /* level */ + 2 /* fid */;
4095 pSMB->t2.TotalDataCount = 0;
4096 pSMB->t2.MaxParameterCount = cpu_to_le16(4);
4097 /* BB find exact max data count below from sess structure BB */
4098 pSMB->t2.MaxDataCount = cpu_to_le16(CIFSMaxBufSize);
4099 pSMB->t2.MaxSetupCount = 0;
4100 pSMB->t2.Reserved = 0;
4102 pSMB->t2.Timeout = 0;
4103 pSMB->t2.Reserved2 = 0;
4104 pSMB->t2.ParameterOffset = cpu_to_le16(offsetof(struct smb_t2_qfi_req,
4106 pSMB->t2.DataCount = 0;
4107 pSMB->t2.DataOffset = 0;
4108 pSMB->t2.SetupCount = 1;
4109 pSMB->t2.Reserved3 = 0;
4110 pSMB->t2.SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION);
4111 byte_count = params + 1 /* pad */ ;
4112 pSMB->t2.TotalParameterCount = cpu_to_le16(params);
4113 pSMB->t2.ParameterCount = pSMB->t2.TotalParameterCount;
4114 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_ALL_INFO);
4117 inc_rfc1001_len(pSMB, byte_count);
4118 pSMB->t2.ByteCount = cpu_to_le16(byte_count);
4120 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4121 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4123 cifs_dbg(FYI, "Send error in QFileInfo = %d", rc);
4124 } else { /* decode response */
4125 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4127 if (rc) /* BB add auto retry on EOPNOTSUPP? */
4129 else if (get_bcc(&pSMBr->hdr) < 40)
4130 rc = -EIO; /* bad smb */
4131 else if (pFindData) {
4132 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4133 memcpy((char *) pFindData,
4134 (char *) &pSMBr->hdr.Protocol +
4135 data_offset, sizeof(FILE_ALL_INFO));
4139 cifs_buf_release(pSMB);
4141 goto QFileInfoRetry;
4147 CIFSSMBQPathInfo(const unsigned int xid, struct cifs_tcon *tcon,
4148 const char *search_name, FILE_ALL_INFO *data,
4149 int legacy /* old style infolevel */,
4150 const struct nls_table *nls_codepage, int remap)
4152 /* level 263 SMB_QUERY_FILE_ALL_INFO */
4153 TRANSACTION2_QPI_REQ *pSMB = NULL;
4154 TRANSACTION2_QPI_RSP *pSMBr = NULL;
4158 __u16 params, byte_count;
4160 /* cifs_dbg(FYI, "In QPathInfo path %s\n", search_name); */
4162 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4167 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4169 cifsConvertToUTF16((__le16 *) pSMB->FileName, search_name,
4170 PATH_MAX, nls_codepage, remap);
4171 name_len++; /* trailing null */
4173 } else { /* BB improve the check for buffer overruns BB */
4174 name_len = strnlen(search_name, PATH_MAX);
4175 name_len++; /* trailing null */
4176 strncpy(pSMB->FileName, search_name, name_len);
4179 params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */;
4180 pSMB->TotalDataCount = 0;
4181 pSMB->MaxParameterCount = cpu_to_le16(2);
4182 /* BB find exact max SMB PDU from sess structure BB */
4183 pSMB->MaxDataCount = cpu_to_le16(4000);
4184 pSMB->MaxSetupCount = 0;
4188 pSMB->Reserved2 = 0;
4189 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4190 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
4191 pSMB->DataCount = 0;
4192 pSMB->DataOffset = 0;
4193 pSMB->SetupCount = 1;
4194 pSMB->Reserved3 = 0;
4195 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
4196 byte_count = params + 1 /* pad */ ;
4197 pSMB->TotalParameterCount = cpu_to_le16(params);
4198 pSMB->ParameterCount = pSMB->TotalParameterCount;
4200 pSMB->InformationLevel = cpu_to_le16(SMB_INFO_STANDARD);
4202 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_ALL_INFO);
4203 pSMB->Reserved4 = 0;
4204 inc_rfc1001_len(pSMB, byte_count);
4205 pSMB->ByteCount = cpu_to_le16(byte_count);
4207 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4208 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4210 cifs_dbg(FYI, "Send error in QPathInfo = %d\n", rc);
4211 } else { /* decode response */
4212 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4214 if (rc) /* BB add auto retry on EOPNOTSUPP? */
4216 else if (!legacy && get_bcc(&pSMBr->hdr) < 40)
4217 rc = -EIO; /* bad smb */
4218 else if (legacy && get_bcc(&pSMBr->hdr) < 24)
4219 rc = -EIO; /* 24 or 26 expected but we do not read
4223 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4226 * On legacy responses we do not read the last field,
4227 * EAsize, fortunately since it varies by subdialect and
4228 * also note it differs on Set vs Get, ie two bytes or 4
4229 * bytes depending but we don't care here.
4232 size = sizeof(FILE_INFO_STANDARD);
4234 size = sizeof(FILE_ALL_INFO);
4235 memcpy((char *) data, (char *) &pSMBr->hdr.Protocol +
4240 cifs_buf_release(pSMB);
4242 goto QPathInfoRetry;
4248 CIFSSMBUnixQFileInfo(const unsigned int xid, struct cifs_tcon *tcon,
4249 u16 netfid, FILE_UNIX_BASIC_INFO *pFindData)
4251 struct smb_t2_qfi_req *pSMB = NULL;
4252 struct smb_t2_qfi_rsp *pSMBr = NULL;
4255 __u16 params, byte_count;
4258 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4263 params = 2 /* level */ + 2 /* fid */;
4264 pSMB->t2.TotalDataCount = 0;
4265 pSMB->t2.MaxParameterCount = cpu_to_le16(4);
4266 /* BB find exact max data count below from sess structure BB */
4267 pSMB->t2.MaxDataCount = cpu_to_le16(CIFSMaxBufSize);
4268 pSMB->t2.MaxSetupCount = 0;
4269 pSMB->t2.Reserved = 0;
4271 pSMB->t2.Timeout = 0;
4272 pSMB->t2.Reserved2 = 0;
4273 pSMB->t2.ParameterOffset = cpu_to_le16(offsetof(struct smb_t2_qfi_req,
4275 pSMB->t2.DataCount = 0;
4276 pSMB->t2.DataOffset = 0;
4277 pSMB->t2.SetupCount = 1;
4278 pSMB->t2.Reserved3 = 0;
4279 pSMB->t2.SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION);
4280 byte_count = params + 1 /* pad */ ;
4281 pSMB->t2.TotalParameterCount = cpu_to_le16(params);
4282 pSMB->t2.ParameterCount = pSMB->t2.TotalParameterCount;
4283 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC);
4286 inc_rfc1001_len(pSMB, byte_count);
4287 pSMB->t2.ByteCount = cpu_to_le16(byte_count);
4289 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4290 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4292 cifs_dbg(FYI, "Send error in UnixQFileInfo = %d", rc);
4293 } else { /* decode response */
4294 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4296 if (rc || get_bcc(&pSMBr->hdr) < sizeof(FILE_UNIX_BASIC_INFO)) {
4297 cifs_dbg(VFS, "Malformed FILE_UNIX_BASIC_INFO response. Unix Extensions can be disabled on mount by specifying the nosfu mount option.\n");
4298 rc = -EIO; /* bad smb */
4300 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4301 memcpy((char *) pFindData,
4302 (char *) &pSMBr->hdr.Protocol +
4304 sizeof(FILE_UNIX_BASIC_INFO));
4308 cifs_buf_release(pSMB);
4310 goto UnixQFileInfoRetry;
4316 CIFSSMBUnixQPathInfo(const unsigned int xid, struct cifs_tcon *tcon,
4317 const unsigned char *searchName,
4318 FILE_UNIX_BASIC_INFO *pFindData,
4319 const struct nls_table *nls_codepage, int remap)
4321 /* SMB_QUERY_FILE_UNIX_BASIC */
4322 TRANSACTION2_QPI_REQ *pSMB = NULL;
4323 TRANSACTION2_QPI_RSP *pSMBr = NULL;
4325 int bytes_returned = 0;
4327 __u16 params, byte_count;
4329 cifs_dbg(FYI, "In QPathInfo (Unix) the path %s\n", searchName);
4331 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4336 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4338 cifsConvertToUTF16((__le16 *) pSMB->FileName, searchName,
4339 PATH_MAX, nls_codepage, remap);
4340 name_len++; /* trailing null */
4342 } else { /* BB improve the check for buffer overruns BB */
4343 name_len = strnlen(searchName, PATH_MAX);
4344 name_len++; /* trailing null */
4345 strncpy(pSMB->FileName, searchName, name_len);
4348 params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */;
4349 pSMB->TotalDataCount = 0;
4350 pSMB->MaxParameterCount = cpu_to_le16(2);
4351 /* BB find exact max SMB PDU from sess structure BB */
4352 pSMB->MaxDataCount = cpu_to_le16(4000);
4353 pSMB->MaxSetupCount = 0;
4357 pSMB->Reserved2 = 0;
4358 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4359 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
4360 pSMB->DataCount = 0;
4361 pSMB->DataOffset = 0;
4362 pSMB->SetupCount = 1;
4363 pSMB->Reserved3 = 0;
4364 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
4365 byte_count = params + 1 /* pad */ ;
4366 pSMB->TotalParameterCount = cpu_to_le16(params);
4367 pSMB->ParameterCount = pSMB->TotalParameterCount;
4368 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC);
4369 pSMB->Reserved4 = 0;
4370 inc_rfc1001_len(pSMB, byte_count);
4371 pSMB->ByteCount = cpu_to_le16(byte_count);
4373 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4374 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4376 cifs_dbg(FYI, "Send error in UnixQPathInfo = %d", rc);
4377 } else { /* decode response */
4378 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4380 if (rc || get_bcc(&pSMBr->hdr) < sizeof(FILE_UNIX_BASIC_INFO)) {
4381 cifs_dbg(VFS, "Malformed FILE_UNIX_BASIC_INFO response. Unix Extensions can be disabled on mount by specifying the nosfu mount option.\n");
4382 rc = -EIO; /* bad smb */
4384 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4385 memcpy((char *) pFindData,
4386 (char *) &pSMBr->hdr.Protocol +
4388 sizeof(FILE_UNIX_BASIC_INFO));
4391 cifs_buf_release(pSMB);
4393 goto UnixQPathInfoRetry;
4398 /* xid, tcon, searchName and codepage are input parms, rest are returned */
4400 CIFSFindFirst(const unsigned int xid, struct cifs_tcon *tcon,
4401 const char *searchName, struct cifs_sb_info *cifs_sb,
4402 __u16 *pnetfid, __u16 search_flags,
4403 struct cifs_search_info *psrch_inf, bool msearch)
4405 /* level 257 SMB_ */
4406 TRANSACTION2_FFIRST_REQ *pSMB = NULL;
4407 TRANSACTION2_FFIRST_RSP *pSMBr = NULL;
4408 T2_FFIRST_RSP_PARMS *parms;
4410 int bytes_returned = 0;
4411 int name_len, remap;
4412 __u16 params, byte_count;
4413 struct nls_table *nls_codepage;
4415 cifs_dbg(FYI, "In FindFirst for %s\n", searchName);
4418 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4423 nls_codepage = cifs_sb->local_nls;
4424 remap = cifs_remap(cifs_sb);
4426 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4428 cifsConvertToUTF16((__le16 *) pSMB->FileName, searchName,
4429 PATH_MAX, nls_codepage, remap);
4430 /* We can not add the asterik earlier in case
4431 it got remapped to 0xF03A as if it were part of the
4432 directory name instead of a wildcard */
4435 pSMB->FileName[name_len] = CIFS_DIR_SEP(cifs_sb);
4436 pSMB->FileName[name_len+1] = 0;
4437 pSMB->FileName[name_len+2] = '*';
4438 pSMB->FileName[name_len+3] = 0;
4439 name_len += 4; /* now the trailing null */
4440 /* null terminate just in case */
4441 pSMB->FileName[name_len] = 0;
4442 pSMB->FileName[name_len+1] = 0;
4445 } else { /* BB add check for overrun of SMB buf BB */
4446 name_len = strnlen(searchName, PATH_MAX);
4447 /* BB fix here and in unicode clause above ie
4448 if (name_len > buffersize-header)
4449 free buffer exit; BB */
4450 strncpy(pSMB->FileName, searchName, name_len);
4452 pSMB->FileName[name_len] = CIFS_DIR_SEP(cifs_sb);
4453 pSMB->FileName[name_len+1] = '*';
4454 pSMB->FileName[name_len+2] = 0;
4459 params = 12 + name_len /* includes null */ ;
4460 pSMB->TotalDataCount = 0; /* no EAs */
4461 pSMB->MaxParameterCount = cpu_to_le16(10);
4462 pSMB->MaxDataCount = cpu_to_le16(CIFSMaxBufSize & 0xFFFFFF00);
4463 pSMB->MaxSetupCount = 0;
4467 pSMB->Reserved2 = 0;
4468 byte_count = params + 1 /* pad */ ;
4469 pSMB->TotalParameterCount = cpu_to_le16(params);
4470 pSMB->ParameterCount = pSMB->TotalParameterCount;
4471 pSMB->ParameterOffset = cpu_to_le16(
4472 offsetof(struct smb_com_transaction2_ffirst_req, SearchAttributes)
4474 pSMB->DataCount = 0;
4475 pSMB->DataOffset = 0;
4476 pSMB->SetupCount = 1; /* one byte, no need to make endian neutral */
4477 pSMB->Reserved3 = 0;
4478 pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_FIRST);
4479 pSMB->SearchAttributes =
4480 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
4482 pSMB->SearchCount = cpu_to_le16(CIFSMaxBufSize/sizeof(FILE_UNIX_INFO));
4483 pSMB->SearchFlags = cpu_to_le16(search_flags);
4484 pSMB->InformationLevel = cpu_to_le16(psrch_inf->info_level);
4486 /* BB what should we set StorageType to? Does it matter? BB */
4487 pSMB->SearchStorageType = 0;
4488 inc_rfc1001_len(pSMB, byte_count);
4489 pSMB->ByteCount = cpu_to_le16(byte_count);
4491 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4492 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4493 cifs_stats_inc(&tcon->stats.cifs_stats.num_ffirst);
4495 if (rc) {/* BB add logic to retry regular search if Unix search
4496 rejected unexpectedly by server */
4497 /* BB Add code to handle unsupported level rc */
4498 cifs_dbg(FYI, "Error in FindFirst = %d\n", rc);
4500 cifs_buf_release(pSMB);
4502 /* BB eventually could optimize out free and realloc of buf */
4505 goto findFirstRetry;
4506 } else { /* decode response */
4507 /* BB remember to free buffer if error BB */
4508 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4512 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
4513 psrch_inf->unicode = true;
4515 psrch_inf->unicode = false;
4517 psrch_inf->ntwrk_buf_start = (char *)pSMBr;
4518 psrch_inf->smallBuf = 0;
4519 psrch_inf->srch_entries_start =
4520 (char *) &pSMBr->hdr.Protocol +
4521 le16_to_cpu(pSMBr->t2.DataOffset);
4522 parms = (T2_FFIRST_RSP_PARMS *)((char *) &pSMBr->hdr.Protocol +
4523 le16_to_cpu(pSMBr->t2.ParameterOffset));
4525 if (parms->EndofSearch)
4526 psrch_inf->endOfSearch = true;
4528 psrch_inf->endOfSearch = false;
4530 psrch_inf->entries_in_buffer =
4531 le16_to_cpu(parms->SearchCount);
4532 psrch_inf->index_of_last_entry = 2 /* skip . and .. */ +
4533 psrch_inf->entries_in_buffer;
4534 lnoff = le16_to_cpu(parms->LastNameOffset);
4535 if (CIFSMaxBufSize < lnoff) {
4536 cifs_dbg(VFS, "ignoring corrupt resume name\n");
4537 psrch_inf->last_entry = NULL;
4541 psrch_inf->last_entry = psrch_inf->srch_entries_start +
4545 *pnetfid = parms->SearchHandle;
4547 cifs_buf_release(pSMB);
4554 int CIFSFindNext(const unsigned int xid, struct cifs_tcon *tcon,
4555 __u16 searchHandle, __u16 search_flags,
4556 struct cifs_search_info *psrch_inf)
4558 TRANSACTION2_FNEXT_REQ *pSMB = NULL;
4559 TRANSACTION2_FNEXT_RSP *pSMBr = NULL;
4560 T2_FNEXT_RSP_PARMS *parms;
4561 char *response_data;
4564 unsigned int name_len;
4565 __u16 params, byte_count;
4567 cifs_dbg(FYI, "In FindNext\n");
4569 if (psrch_inf->endOfSearch)
4572 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4577 params = 14; /* includes 2 bytes of null string, converted to LE below*/
4579 pSMB->TotalDataCount = 0; /* no EAs */
4580 pSMB->MaxParameterCount = cpu_to_le16(8);
4581 pSMB->MaxDataCount = cpu_to_le16(CIFSMaxBufSize & 0xFFFFFF00);
4582 pSMB->MaxSetupCount = 0;
4586 pSMB->Reserved2 = 0;
4587 pSMB->ParameterOffset = cpu_to_le16(
4588 offsetof(struct smb_com_transaction2_fnext_req,SearchHandle) - 4);
4589 pSMB->DataCount = 0;
4590 pSMB->DataOffset = 0;
4591 pSMB->SetupCount = 1;
4592 pSMB->Reserved3 = 0;
4593 pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_NEXT);
4594 pSMB->SearchHandle = searchHandle; /* always kept as le */
4596 cpu_to_le16(CIFSMaxBufSize / sizeof(FILE_UNIX_INFO));
4597 pSMB->InformationLevel = cpu_to_le16(psrch_inf->info_level);
4598 pSMB->ResumeKey = psrch_inf->resume_key;
4599 pSMB->SearchFlags = cpu_to_le16(search_flags);
4601 name_len = psrch_inf->resume_name_len;
4603 if (name_len < PATH_MAX) {
4604 memcpy(pSMB->ResumeFileName, psrch_inf->presume_name, name_len);
4605 byte_count += name_len;
4606 /* 14 byte parm len above enough for 2 byte null terminator */
4607 pSMB->ResumeFileName[name_len] = 0;
4608 pSMB->ResumeFileName[name_len+1] = 0;
4611 goto FNext2_err_exit;
4613 byte_count = params + 1 /* pad */ ;
4614 pSMB->TotalParameterCount = cpu_to_le16(params);
4615 pSMB->ParameterCount = pSMB->TotalParameterCount;
4616 inc_rfc1001_len(pSMB, byte_count);
4617 pSMB->ByteCount = cpu_to_le16(byte_count);
4619 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4620 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4621 cifs_stats_inc(&tcon->stats.cifs_stats.num_fnext);
4624 psrch_inf->endOfSearch = true;
4625 cifs_buf_release(pSMB);
4626 rc = 0; /* search probably was closed at end of search*/
4628 cifs_dbg(FYI, "FindNext returned = %d\n", rc);
4629 } else { /* decode response */
4630 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4635 /* BB fixme add lock for file (srch_info) struct here */
4636 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
4637 psrch_inf->unicode = true;
4639 psrch_inf->unicode = false;
4640 response_data = (char *) &pSMBr->hdr.Protocol +
4641 le16_to_cpu(pSMBr->t2.ParameterOffset);
4642 parms = (T2_FNEXT_RSP_PARMS *)response_data;
4643 response_data = (char *)&pSMBr->hdr.Protocol +
4644 le16_to_cpu(pSMBr->t2.DataOffset);
4645 if (psrch_inf->smallBuf)
4646 cifs_small_buf_release(
4647 psrch_inf->ntwrk_buf_start);
4649 cifs_buf_release(psrch_inf->ntwrk_buf_start);
4650 psrch_inf->srch_entries_start = response_data;
4651 psrch_inf->ntwrk_buf_start = (char *)pSMB;
4652 psrch_inf->smallBuf = 0;
4653 if (parms->EndofSearch)
4654 psrch_inf->endOfSearch = true;
4656 psrch_inf->endOfSearch = false;
4657 psrch_inf->entries_in_buffer =
4658 le16_to_cpu(parms->SearchCount);
4659 psrch_inf->index_of_last_entry +=
4660 psrch_inf->entries_in_buffer;
4661 lnoff = le16_to_cpu(parms->LastNameOffset);
4662 if (CIFSMaxBufSize < lnoff) {
4663 cifs_dbg(VFS, "ignoring corrupt resume name\n");
4664 psrch_inf->last_entry = NULL;
4667 psrch_inf->last_entry =
4668 psrch_inf->srch_entries_start + lnoff;
4670 /* cifs_dbg(FYI, "fnxt2 entries in buf %d index_of_last %d\n",
4671 psrch_inf->entries_in_buffer, psrch_inf->index_of_last_entry); */
4673 /* BB fixme add unlock here */
4678 /* BB On error, should we leave previous search buf (and count and
4679 last entry fields) intact or free the previous one? */
4681 /* Note: On -EAGAIN error only caller can retry on handle based calls
4682 since file handle passed in no longer valid */
4685 cifs_buf_release(pSMB);
4690 CIFSFindClose(const unsigned int xid, struct cifs_tcon *tcon,
4691 const __u16 searchHandle)
4694 FINDCLOSE_REQ *pSMB = NULL;
4696 cifs_dbg(FYI, "In CIFSSMBFindClose\n");
4697 rc = small_smb_init(SMB_COM_FIND_CLOSE2, 1, tcon, (void **)&pSMB);
4699 /* no sense returning error if session restarted
4700 as file handle has been closed */
4706 pSMB->FileID = searchHandle;
4707 pSMB->ByteCount = 0;
4708 rc = SendReceiveNoRsp(xid, tcon->ses, (char *) pSMB, 0);
4709 cifs_small_buf_release(pSMB);
4711 cifs_dbg(VFS, "Send error in FindClose = %d\n", rc);
4713 cifs_stats_inc(&tcon->stats.cifs_stats.num_fclose);
4715 /* Since session is dead, search handle closed on server already */
4723 CIFSGetSrvInodeNumber(const unsigned int xid, struct cifs_tcon *tcon,
4724 const char *search_name, __u64 *inode_number,
4725 const struct nls_table *nls_codepage, int remap)
4728 TRANSACTION2_QPI_REQ *pSMB = NULL;
4729 TRANSACTION2_QPI_RSP *pSMBr = NULL;
4730 int name_len, bytes_returned;
4731 __u16 params, byte_count;
4733 cifs_dbg(FYI, "In GetSrvInodeNum for %s\n", search_name);
4737 GetInodeNumberRetry:
4738 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4743 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4745 cifsConvertToUTF16((__le16 *) pSMB->FileName,
4746 search_name, PATH_MAX, nls_codepage,
4748 name_len++; /* trailing null */
4750 } else { /* BB improve the check for buffer overruns BB */
4751 name_len = strnlen(search_name, PATH_MAX);
4752 name_len++; /* trailing null */
4753 strncpy(pSMB->FileName, search_name, name_len);
4756 params = 2 /* level */ + 4 /* rsrvd */ + name_len /* incl null */ ;
4757 pSMB->TotalDataCount = 0;
4758 pSMB->MaxParameterCount = cpu_to_le16(2);
4759 /* BB find exact max data count below from sess structure BB */
4760 pSMB->MaxDataCount = cpu_to_le16(4000);
4761 pSMB->MaxSetupCount = 0;
4765 pSMB->Reserved2 = 0;
4766 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4767 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
4768 pSMB->DataCount = 0;
4769 pSMB->DataOffset = 0;
4770 pSMB->SetupCount = 1;
4771 pSMB->Reserved3 = 0;
4772 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
4773 byte_count = params + 1 /* pad */ ;
4774 pSMB->TotalParameterCount = cpu_to_le16(params);
4775 pSMB->ParameterCount = pSMB->TotalParameterCount;
4776 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_INTERNAL_INFO);
4777 pSMB->Reserved4 = 0;
4778 inc_rfc1001_len(pSMB, byte_count);
4779 pSMB->ByteCount = cpu_to_le16(byte_count);
4781 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4782 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4784 cifs_dbg(FYI, "error %d in QueryInternalInfo\n", rc);
4786 /* decode response */
4787 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4788 /* BB also check enough total bytes returned */
4789 if (rc || get_bcc(&pSMBr->hdr) < 2)
4790 /* If rc should we check for EOPNOSUPP and
4791 disable the srvino flag? or in caller? */
4792 rc = -EIO; /* bad smb */
4794 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4795 __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
4796 struct file_internal_info *pfinfo;
4797 /* BB Do we need a cast or hash here ? */
4799 cifs_dbg(FYI, "Illegal size ret in QryIntrnlInf\n");
4801 goto GetInodeNumOut;
4803 pfinfo = (struct file_internal_info *)
4804 (data_offset + (char *) &pSMBr->hdr.Protocol);
4805 *inode_number = le64_to_cpu(pfinfo->UniqueId);
4809 cifs_buf_release(pSMB);
4811 goto GetInodeNumberRetry;
4816 CIFSGetDFSRefer(const unsigned int xid, struct cifs_ses *ses,
4817 const char *search_name, struct dfs_info3_param **target_nodes,
4818 unsigned int *num_of_nodes,
4819 const struct nls_table *nls_codepage, int remap)
4821 /* TRANS2_GET_DFS_REFERRAL */
4822 TRANSACTION2_GET_DFS_REFER_REQ *pSMB = NULL;
4823 TRANSACTION2_GET_DFS_REFER_RSP *pSMBr = NULL;
4827 __u16 params, byte_count;
4829 *target_nodes = NULL;
4831 cifs_dbg(FYI, "In GetDFSRefer the path %s\n", search_name);
4835 rc = smb_init(SMB_COM_TRANSACTION2, 15, NULL, (void **) &pSMB,
4840 /* server pointer checked in called function,
4841 but should never be null here anyway */
4842 pSMB->hdr.Mid = get_next_mid(ses->server);
4843 pSMB->hdr.Tid = ses->ipc_tid;
4844 pSMB->hdr.Uid = ses->Suid;
4845 if (ses->capabilities & CAP_STATUS32)
4846 pSMB->hdr.Flags2 |= SMBFLG2_ERR_STATUS;
4847 if (ses->capabilities & CAP_DFS)
4848 pSMB->hdr.Flags2 |= SMBFLG2_DFS;
4850 if (ses->capabilities & CAP_UNICODE) {
4851 pSMB->hdr.Flags2 |= SMBFLG2_UNICODE;
4853 cifsConvertToUTF16((__le16 *) pSMB->RequestFileName,
4854 search_name, PATH_MAX, nls_codepage,
4856 name_len++; /* trailing null */
4858 } else { /* BB improve the check for buffer overruns BB */
4859 name_len = strnlen(search_name, PATH_MAX);
4860 name_len++; /* trailing null */
4861 strncpy(pSMB->RequestFileName, search_name, name_len);
4864 if (ses->server->sign)
4865 pSMB->hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
4867 pSMB->hdr.Uid = ses->Suid;
4869 params = 2 /* level */ + name_len /*includes null */ ;
4870 pSMB->TotalDataCount = 0;
4871 pSMB->DataCount = 0;
4872 pSMB->DataOffset = 0;
4873 pSMB->MaxParameterCount = 0;
4874 /* BB find exact max SMB PDU from sess structure BB */
4875 pSMB->MaxDataCount = cpu_to_le16(4000);
4876 pSMB->MaxSetupCount = 0;
4880 pSMB->Reserved2 = 0;
4881 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4882 struct smb_com_transaction2_get_dfs_refer_req, MaxReferralLevel) - 4);
4883 pSMB->SetupCount = 1;
4884 pSMB->Reserved3 = 0;
4885 pSMB->SubCommand = cpu_to_le16(TRANS2_GET_DFS_REFERRAL);
4886 byte_count = params + 3 /* pad */ ;
4887 pSMB->ParameterCount = cpu_to_le16(params);
4888 pSMB->TotalParameterCount = pSMB->ParameterCount;
4889 pSMB->MaxReferralLevel = cpu_to_le16(3);
4890 inc_rfc1001_len(pSMB, byte_count);
4891 pSMB->ByteCount = cpu_to_le16(byte_count);
4893 rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB,
4894 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4896 cifs_dbg(FYI, "Send error in GetDFSRefer = %d\n", rc);
4899 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4901 /* BB Also check if enough total bytes returned? */
4902 if (rc || get_bcc(&pSMBr->hdr) < 17) {
4903 rc = -EIO; /* bad smb */
4907 cifs_dbg(FYI, "Decoding GetDFSRefer response BCC: %d Offset %d\n",
4908 get_bcc(&pSMBr->hdr), le16_to_cpu(pSMBr->t2.DataOffset));
4910 /* parse returned result into more usable form */
4911 rc = parse_dfs_referrals(&pSMBr->dfs_data,
4912 le16_to_cpu(pSMBr->t2.DataCount),
4913 num_of_nodes, target_nodes, nls_codepage,
4915 (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) != 0);
4918 cifs_buf_release(pSMB);
4926 /* Query File System Info such as free space to old servers such as Win 9x */
4928 SMBOldQFSInfo(const unsigned int xid, struct cifs_tcon *tcon,
4929 struct kstatfs *FSData)
4931 /* level 0x01 SMB_QUERY_FILE_SYSTEM_INFO */
4932 TRANSACTION2_QFSI_REQ *pSMB = NULL;
4933 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4934 FILE_SYSTEM_ALLOC_INFO *response_data;
4936 int bytes_returned = 0;
4937 __u16 params, byte_count;
4939 cifs_dbg(FYI, "OldQFSInfo\n");
4941 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4946 params = 2; /* level */
4947 pSMB->TotalDataCount = 0;
4948 pSMB->MaxParameterCount = cpu_to_le16(2);
4949 pSMB->MaxDataCount = cpu_to_le16(1000);
4950 pSMB->MaxSetupCount = 0;
4954 pSMB->Reserved2 = 0;
4955 byte_count = params + 1 /* pad */ ;
4956 pSMB->TotalParameterCount = cpu_to_le16(params);
4957 pSMB->ParameterCount = pSMB->TotalParameterCount;
4958 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4959 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4960 pSMB->DataCount = 0;
4961 pSMB->DataOffset = 0;
4962 pSMB->SetupCount = 1;
4963 pSMB->Reserved3 = 0;
4964 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4965 pSMB->InformationLevel = cpu_to_le16(SMB_INFO_ALLOCATION);
4966 inc_rfc1001_len(pSMB, byte_count);
4967 pSMB->ByteCount = cpu_to_le16(byte_count);
4969 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4970 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4972 cifs_dbg(FYI, "Send error in QFSInfo = %d\n", rc);
4973 } else { /* decode response */
4974 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4976 if (rc || get_bcc(&pSMBr->hdr) < 18)
4977 rc = -EIO; /* bad smb */
4979 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4980 cifs_dbg(FYI, "qfsinf resp BCC: %d Offset %d\n",
4981 get_bcc(&pSMBr->hdr), data_offset);
4983 response_data = (FILE_SYSTEM_ALLOC_INFO *)
4984 (((char *) &pSMBr->hdr.Protocol) + data_offset);
4986 le16_to_cpu(response_data->BytesPerSector) *
4987 le32_to_cpu(response_data->
4988 SectorsPerAllocationUnit);
4990 le32_to_cpu(response_data->TotalAllocationUnits);
4991 FSData->f_bfree = FSData->f_bavail =
4992 le32_to_cpu(response_data->FreeAllocationUnits);
4993 cifs_dbg(FYI, "Blocks: %lld Free: %lld Block size %ld\n",
4994 (unsigned long long)FSData->f_blocks,
4995 (unsigned long long)FSData->f_bfree,
4999 cifs_buf_release(pSMB);
5002 goto oldQFSInfoRetry;
5008 CIFSSMBQFSInfo(const unsigned int xid, struct cifs_tcon *tcon,
5009 struct kstatfs *FSData)
5011 /* level 0x103 SMB_QUERY_FILE_SYSTEM_INFO */
5012 TRANSACTION2_QFSI_REQ *pSMB = NULL;
5013 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
5014 FILE_SYSTEM_INFO *response_data;
5016 int bytes_returned = 0;
5017 __u16 params, byte_count;
5019 cifs_dbg(FYI, "In QFSInfo\n");
5021 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5026 params = 2; /* level */
5027 pSMB->TotalDataCount = 0;
5028 pSMB->MaxParameterCount = cpu_to_le16(2);
5029 pSMB->MaxDataCount = cpu_to_le16(1000);
5030 pSMB->MaxSetupCount = 0;
5034 pSMB->Reserved2 = 0;
5035 byte_count = params + 1 /* pad */ ;
5036 pSMB->TotalParameterCount = cpu_to_le16(params);
5037 pSMB->ParameterCount = pSMB->TotalParameterCount;
5038 pSMB->ParameterOffset = cpu_to_le16(offsetof(
5039 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
5040 pSMB->DataCount = 0;
5041 pSMB->DataOffset = 0;
5042 pSMB->SetupCount = 1;
5043 pSMB->Reserved3 = 0;
5044 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
5045 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_SIZE_INFO);
5046 inc_rfc1001_len(pSMB, byte_count);
5047 pSMB->ByteCount = cpu_to_le16(byte_count);
5049 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5050 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5052 cifs_dbg(FYI, "Send error in QFSInfo = %d\n", rc);
5053 } else { /* decode response */
5054 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
5056 if (rc || get_bcc(&pSMBr->hdr) < 24)
5057 rc = -EIO; /* bad smb */
5059 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
5063 *) (((char *) &pSMBr->hdr.Protocol) +
5066 le32_to_cpu(response_data->BytesPerSector) *
5067 le32_to_cpu(response_data->
5068 SectorsPerAllocationUnit);
5070 le64_to_cpu(response_data->TotalAllocationUnits);
5071 FSData->f_bfree = FSData->f_bavail =
5072 le64_to_cpu(response_data->FreeAllocationUnits);
5073 cifs_dbg(FYI, "Blocks: %lld Free: %lld Block size %ld\n",
5074 (unsigned long long)FSData->f_blocks,
5075 (unsigned long long)FSData->f_bfree,
5079 cifs_buf_release(pSMB);
5088 CIFSSMBQFSAttributeInfo(const unsigned int xid, struct cifs_tcon *tcon)
5090 /* level 0x105 SMB_QUERY_FILE_SYSTEM_INFO */
5091 TRANSACTION2_QFSI_REQ *pSMB = NULL;
5092 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
5093 FILE_SYSTEM_ATTRIBUTE_INFO *response_data;
5095 int bytes_returned = 0;
5096 __u16 params, byte_count;
5098 cifs_dbg(FYI, "In QFSAttributeInfo\n");
5100 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5105 params = 2; /* level */
5106 pSMB->TotalDataCount = 0;
5107 pSMB->MaxParameterCount = cpu_to_le16(2);
5108 /* BB find exact max SMB PDU from sess structure BB */
5109 pSMB->MaxDataCount = cpu_to_le16(1000);
5110 pSMB->MaxSetupCount = 0;
5114 pSMB->Reserved2 = 0;
5115 byte_count = params + 1 /* pad */ ;
5116 pSMB->TotalParameterCount = cpu_to_le16(params);
5117 pSMB->ParameterCount = pSMB->TotalParameterCount;
5118 pSMB->ParameterOffset = cpu_to_le16(offsetof(
5119 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
5120 pSMB->DataCount = 0;
5121 pSMB->DataOffset = 0;
5122 pSMB->SetupCount = 1;
5123 pSMB->Reserved3 = 0;
5124 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
5125 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_ATTRIBUTE_INFO);
5126 inc_rfc1001_len(pSMB, byte_count);
5127 pSMB->ByteCount = cpu_to_le16(byte_count);
5129 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5130 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5132 cifs_dbg(VFS, "Send error in QFSAttributeInfo = %d\n", rc);
5133 } else { /* decode response */
5134 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
5136 if (rc || get_bcc(&pSMBr->hdr) < 13) {
5137 /* BB also check if enough bytes returned */
5138 rc = -EIO; /* bad smb */
5140 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
5142 (FILE_SYSTEM_ATTRIBUTE_INFO
5143 *) (((char *) &pSMBr->hdr.Protocol) +
5145 memcpy(&tcon->fsAttrInfo, response_data,
5146 sizeof(FILE_SYSTEM_ATTRIBUTE_INFO));
5149 cifs_buf_release(pSMB);
5152 goto QFSAttributeRetry;
5158 CIFSSMBQFSDeviceInfo(const unsigned int xid, struct cifs_tcon *tcon)
5160 /* level 0x104 SMB_QUERY_FILE_SYSTEM_INFO */
5161 TRANSACTION2_QFSI_REQ *pSMB = NULL;
5162 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
5163 FILE_SYSTEM_DEVICE_INFO *response_data;
5165 int bytes_returned = 0;
5166 __u16 params, byte_count;
5168 cifs_dbg(FYI, "In QFSDeviceInfo\n");
5170 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5175 params = 2; /* level */
5176 pSMB->TotalDataCount = 0;
5177 pSMB->MaxParameterCount = cpu_to_le16(2);
5178 /* BB find exact max SMB PDU from sess structure BB */
5179 pSMB->MaxDataCount = cpu_to_le16(1000);
5180 pSMB->MaxSetupCount = 0;
5184 pSMB->Reserved2 = 0;
5185 byte_count = params + 1 /* pad */ ;
5186 pSMB->TotalParameterCount = cpu_to_le16(params);
5187 pSMB->ParameterCount = pSMB->TotalParameterCount;
5188 pSMB->ParameterOffset = cpu_to_le16(offsetof(
5189 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
5191 pSMB->DataCount = 0;
5192 pSMB->DataOffset = 0;
5193 pSMB->SetupCount = 1;
5194 pSMB->Reserved3 = 0;
5195 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
5196 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_DEVICE_INFO);
5197 inc_rfc1001_len(pSMB, byte_count);
5198 pSMB->ByteCount = cpu_to_le16(byte_count);
5200 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5201 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5203 cifs_dbg(FYI, "Send error in QFSDeviceInfo = %d\n", rc);
5204 } else { /* decode response */
5205 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
5207 if (rc || get_bcc(&pSMBr->hdr) <
5208 sizeof(FILE_SYSTEM_DEVICE_INFO))
5209 rc = -EIO; /* bad smb */
5211 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
5213 (FILE_SYSTEM_DEVICE_INFO *)
5214 (((char *) &pSMBr->hdr.Protocol) +
5216 memcpy(&tcon->fsDevInfo, response_data,
5217 sizeof(FILE_SYSTEM_DEVICE_INFO));
5220 cifs_buf_release(pSMB);
5223 goto QFSDeviceRetry;
5229 CIFSSMBQFSUnixInfo(const unsigned int xid, struct cifs_tcon *tcon)
5231 /* level 0x200 SMB_QUERY_CIFS_UNIX_INFO */
5232 TRANSACTION2_QFSI_REQ *pSMB = NULL;
5233 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
5234 FILE_SYSTEM_UNIX_INFO *response_data;
5236 int bytes_returned = 0;
5237 __u16 params, byte_count;
5239 cifs_dbg(FYI, "In QFSUnixInfo\n");
5241 rc = smb_init_no_reconnect(SMB_COM_TRANSACTION2, 15, tcon,
5242 (void **) &pSMB, (void **) &pSMBr);
5246 params = 2; /* level */
5247 pSMB->TotalDataCount = 0;
5248 pSMB->DataCount = 0;
5249 pSMB->DataOffset = 0;
5250 pSMB->MaxParameterCount = cpu_to_le16(2);
5251 /* BB find exact max SMB PDU from sess structure BB */
5252 pSMB->MaxDataCount = cpu_to_le16(100);
5253 pSMB->MaxSetupCount = 0;
5257 pSMB->Reserved2 = 0;
5258 byte_count = params + 1 /* pad */ ;
5259 pSMB->ParameterCount = cpu_to_le16(params);
5260 pSMB->TotalParameterCount = pSMB->ParameterCount;
5261 pSMB->ParameterOffset = cpu_to_le16(offsetof(struct
5262 smb_com_transaction2_qfsi_req, InformationLevel) - 4);
5263 pSMB->SetupCount = 1;
5264 pSMB->Reserved3 = 0;
5265 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
5266 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_CIFS_UNIX_INFO);
5267 inc_rfc1001_len(pSMB, byte_count);
5268 pSMB->ByteCount = cpu_to_le16(byte_count);
5270 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5271 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5273 cifs_dbg(VFS, "Send error in QFSUnixInfo = %d\n", rc);
5274 } else { /* decode response */
5275 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
5277 if (rc || get_bcc(&pSMBr->hdr) < 13) {
5278 rc = -EIO; /* bad smb */
5280 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
5282 (FILE_SYSTEM_UNIX_INFO
5283 *) (((char *) &pSMBr->hdr.Protocol) +
5285 memcpy(&tcon->fsUnixInfo, response_data,
5286 sizeof(FILE_SYSTEM_UNIX_INFO));
5289 cifs_buf_release(pSMB);
5299 CIFSSMBSetFSUnixInfo(const unsigned int xid, struct cifs_tcon *tcon, __u64 cap)
5301 /* level 0x200 SMB_SET_CIFS_UNIX_INFO */
5302 TRANSACTION2_SETFSI_REQ *pSMB = NULL;
5303 TRANSACTION2_SETFSI_RSP *pSMBr = NULL;
5305 int bytes_returned = 0;
5306 __u16 params, param_offset, offset, byte_count;
5308 cifs_dbg(FYI, "In SETFSUnixInfo\n");
5310 /* BB switch to small buf init to save memory */
5311 rc = smb_init_no_reconnect(SMB_COM_TRANSACTION2, 15, tcon,
5312 (void **) &pSMB, (void **) &pSMBr);
5316 params = 4; /* 2 bytes zero followed by info level. */
5317 pSMB->MaxSetupCount = 0;
5321 pSMB->Reserved2 = 0;
5322 param_offset = offsetof(struct smb_com_transaction2_setfsi_req, FileNum)
5324 offset = param_offset + params;
5326 pSMB->MaxParameterCount = cpu_to_le16(4);
5327 /* BB find exact max SMB PDU from sess structure BB */
5328 pSMB->MaxDataCount = cpu_to_le16(100);
5329 pSMB->SetupCount = 1;
5330 pSMB->Reserved3 = 0;
5331 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FS_INFORMATION);
5332 byte_count = 1 /* pad */ + params + 12;
5334 pSMB->DataCount = cpu_to_le16(12);
5335 pSMB->ParameterCount = cpu_to_le16(params);
5336 pSMB->TotalDataCount = pSMB->DataCount;
5337 pSMB->TotalParameterCount = pSMB->ParameterCount;
5338 pSMB->ParameterOffset = cpu_to_le16(param_offset);
5339 pSMB->DataOffset = cpu_to_le16(offset);
5343 pSMB->InformationLevel = cpu_to_le16(SMB_SET_CIFS_UNIX_INFO);
5346 pSMB->ClientUnixMajor = cpu_to_le16(CIFS_UNIX_MAJOR_VERSION);
5347 pSMB->ClientUnixMinor = cpu_to_le16(CIFS_UNIX_MINOR_VERSION);
5348 pSMB->ClientUnixCap = cpu_to_le64(cap);
5350 inc_rfc1001_len(pSMB, byte_count);
5351 pSMB->ByteCount = cpu_to_le16(byte_count);
5353 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5354 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5356 cifs_dbg(VFS, "Send error in SETFSUnixInfo = %d\n", rc);
5357 } else { /* decode response */
5358 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
5360 rc = -EIO; /* bad smb */
5362 cifs_buf_release(pSMB);
5365 goto SETFSUnixRetry;
5373 CIFSSMBQFSPosixInfo(const unsigned int xid, struct cifs_tcon *tcon,
5374 struct kstatfs *FSData)
5376 /* level 0x201 SMB_QUERY_CIFS_POSIX_INFO */
5377 TRANSACTION2_QFSI_REQ *pSMB = NULL;
5378 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
5379 FILE_SYSTEM_POSIX_INFO *response_data;
5381 int bytes_returned = 0;
5382 __u16 params, byte_count;
5384 cifs_dbg(FYI, "In QFSPosixInfo\n");
5386 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5391 params = 2; /* level */
5392 pSMB->TotalDataCount = 0;
5393 pSMB->DataCount = 0;
5394 pSMB->DataOffset = 0;
5395 pSMB->MaxParameterCount = cpu_to_le16(2);
5396 /* BB find exact max SMB PDU from sess structure BB */
5397 pSMB->MaxDataCount = cpu_to_le16(100);
5398 pSMB->MaxSetupCount = 0;
5402 pSMB->Reserved2 = 0;
5403 byte_count = params + 1 /* pad */ ;
5404 pSMB->ParameterCount = cpu_to_le16(params);
5405 pSMB->TotalParameterCount = pSMB->ParameterCount;
5406 pSMB->ParameterOffset = cpu_to_le16(offsetof(struct
5407 smb_com_transaction2_qfsi_req, InformationLevel) - 4);
5408 pSMB->SetupCount = 1;
5409 pSMB->Reserved3 = 0;
5410 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
5411 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_POSIX_FS_INFO);
5412 inc_rfc1001_len(pSMB, byte_count);
5413 pSMB->ByteCount = cpu_to_le16(byte_count);
5415 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5416 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5418 cifs_dbg(FYI, "Send error in QFSUnixInfo = %d\n", rc);
5419 } else { /* decode response */
5420 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
5422 if (rc || get_bcc(&pSMBr->hdr) < 13) {
5423 rc = -EIO; /* bad smb */
5425 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
5427 (FILE_SYSTEM_POSIX_INFO
5428 *) (((char *) &pSMBr->hdr.Protocol) +
5431 le32_to_cpu(response_data->BlockSize);
5433 le64_to_cpu(response_data->TotalBlocks);
5435 le64_to_cpu(response_data->BlocksAvail);
5436 if (response_data->UserBlocksAvail == cpu_to_le64(-1)) {
5437 FSData->f_bavail = FSData->f_bfree;
5440 le64_to_cpu(response_data->UserBlocksAvail);
5442 if (response_data->TotalFileNodes != cpu_to_le64(-1))
5444 le64_to_cpu(response_data->TotalFileNodes);
5445 if (response_data->FreeFileNodes != cpu_to_le64(-1))
5447 le64_to_cpu(response_data->FreeFileNodes);
5450 cifs_buf_release(pSMB);
5460 * We can not use write of zero bytes trick to set file size due to need for
5461 * large file support. Also note that this SetPathInfo is preferred to
5462 * SetFileInfo based method in next routine which is only needed to work around
5463 * a sharing violation bugin Samba which this routine can run into.
5466 CIFSSMBSetEOF(const unsigned int xid, struct cifs_tcon *tcon,
5467 const char *file_name, __u64 size, struct cifs_sb_info *cifs_sb,
5468 bool set_allocation)
5470 struct smb_com_transaction2_spi_req *pSMB = NULL;
5471 struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
5472 struct file_end_of_file_info *parm_data;
5475 int bytes_returned = 0;
5476 int remap = cifs_remap(cifs_sb);
5478 __u16 params, byte_count, data_count, param_offset, offset;
5480 cifs_dbg(FYI, "In SetEOF\n");
5482 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5487 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5489 cifsConvertToUTF16((__le16 *) pSMB->FileName, file_name,
5490 PATH_MAX, cifs_sb->local_nls, remap);
5491 name_len++; /* trailing null */
5493 } else { /* BB improve the check for buffer overruns BB */
5494 name_len = strnlen(file_name, PATH_MAX);
5495 name_len++; /* trailing null */
5496 strncpy(pSMB->FileName, file_name, name_len);
5498 params = 6 + name_len;
5499 data_count = sizeof(struct file_end_of_file_info);
5500 pSMB->MaxParameterCount = cpu_to_le16(2);
5501 pSMB->MaxDataCount = cpu_to_le16(4100);
5502 pSMB->MaxSetupCount = 0;
5506 pSMB->Reserved2 = 0;
5507 param_offset = offsetof(struct smb_com_transaction2_spi_req,
5508 InformationLevel) - 4;
5509 offset = param_offset + params;
5510 if (set_allocation) {
5511 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
5512 pSMB->InformationLevel =
5513 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2);
5515 pSMB->InformationLevel =
5516 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO);
5517 } else /* Set File Size */ {
5518 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
5519 pSMB->InformationLevel =
5520 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO2);
5522 pSMB->InformationLevel =
5523 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO);
5527 (struct file_end_of_file_info *) (((char *) &pSMB->hdr.Protocol) +
5529 pSMB->ParameterOffset = cpu_to_le16(param_offset);
5530 pSMB->DataOffset = cpu_to_le16(offset);
5531 pSMB->SetupCount = 1;
5532 pSMB->Reserved3 = 0;
5533 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
5534 byte_count = 3 /* pad */ + params + data_count;
5535 pSMB->DataCount = cpu_to_le16(data_count);
5536 pSMB->TotalDataCount = pSMB->DataCount;
5537 pSMB->ParameterCount = cpu_to_le16(params);
5538 pSMB->TotalParameterCount = pSMB->ParameterCount;
5539 pSMB->Reserved4 = 0;
5540 inc_rfc1001_len(pSMB, byte_count);
5541 parm_data->FileSize = cpu_to_le64(size);
5542 pSMB->ByteCount = cpu_to_le16(byte_count);
5543 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5544 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5546 cifs_dbg(FYI, "SetPathInfo (file size) returned %d\n", rc);
5548 cifs_buf_release(pSMB);
5557 CIFSSMBSetFileSize(const unsigned int xid, struct cifs_tcon *tcon,
5558 struct cifsFileInfo *cfile, __u64 size, bool set_allocation)
5560 struct smb_com_transaction2_sfi_req *pSMB = NULL;
5561 struct file_end_of_file_info *parm_data;
5563 __u16 params, param_offset, offset, byte_count, count;
5565 cifs_dbg(FYI, "SetFileSize (via SetFileInfo) %lld\n",
5567 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
5572 pSMB->hdr.Pid = cpu_to_le16((__u16)cfile->pid);
5573 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(cfile->pid >> 16));
5576 pSMB->MaxSetupCount = 0;
5580 pSMB->Reserved2 = 0;
5581 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
5582 offset = param_offset + params;
5584 count = sizeof(struct file_end_of_file_info);
5585 pSMB->MaxParameterCount = cpu_to_le16(2);
5586 /* BB find exact max SMB PDU from sess structure BB */
5587 pSMB->MaxDataCount = cpu_to_le16(1000);
5588 pSMB->SetupCount = 1;
5589 pSMB->Reserved3 = 0;
5590 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
5591 byte_count = 3 /* pad */ + params + count;
5592 pSMB->DataCount = cpu_to_le16(count);
5593 pSMB->ParameterCount = cpu_to_le16(params);
5594 pSMB->TotalDataCount = pSMB->DataCount;
5595 pSMB->TotalParameterCount = pSMB->ParameterCount;
5596 pSMB->ParameterOffset = cpu_to_le16(param_offset);
5598 (struct file_end_of_file_info *) (((char *) &pSMB->hdr.Protocol)
5600 pSMB->DataOffset = cpu_to_le16(offset);
5601 parm_data->FileSize = cpu_to_le64(size);
5602 pSMB->Fid = cfile->fid.netfid;
5603 if (set_allocation) {
5604 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
5605 pSMB->InformationLevel =
5606 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2);
5608 pSMB->InformationLevel =
5609 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO);
5610 } else /* Set File Size */ {
5611 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
5612 pSMB->InformationLevel =
5613 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO2);
5615 pSMB->InformationLevel =
5616 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO);
5618 pSMB->Reserved4 = 0;
5619 inc_rfc1001_len(pSMB, byte_count);
5620 pSMB->ByteCount = cpu_to_le16(byte_count);
5621 rc = SendReceiveNoRsp(xid, tcon->ses, (char *) pSMB, 0);
5622 cifs_small_buf_release(pSMB);
5624 cifs_dbg(FYI, "Send error in SetFileInfo (SetFileSize) = %d\n",
5628 /* Note: On -EAGAIN error only caller can retry on handle based calls
5629 since file handle passed in no longer valid */
5634 /* Some legacy servers such as NT4 require that the file times be set on
5635 an open handle, rather than by pathname - this is awkward due to
5636 potential access conflicts on the open, but it is unavoidable for these
5637 old servers since the only other choice is to go from 100 nanosecond DCE
5638 time and resort to the original setpathinfo level which takes the ancient
5639 DOS time format with 2 second granularity */
5641 CIFSSMBSetFileInfo(const unsigned int xid, struct cifs_tcon *tcon,
5642 const FILE_BASIC_INFO *data, __u16 fid, __u32 pid_of_opener)
5644 struct smb_com_transaction2_sfi_req *pSMB = NULL;
5647 __u16 params, param_offset, offset, byte_count, count;
5649 cifs_dbg(FYI, "Set Times (via SetFileInfo)\n");
5650 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
5655 pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
5656 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));
5659 pSMB->MaxSetupCount = 0;
5663 pSMB->Reserved2 = 0;
5664 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
5665 offset = param_offset + params;
5667 data_offset = (char *)pSMB +
5668 offsetof(struct smb_hdr, Protocol) + offset;
5670 count = sizeof(FILE_BASIC_INFO);
5671 pSMB->MaxParameterCount = cpu_to_le16(2);
5672 /* BB find max SMB PDU from sess */
5673 pSMB->MaxDataCount = cpu_to_le16(1000);
5674 pSMB->SetupCount = 1;
5675 pSMB->Reserved3 = 0;
5676 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
5677 byte_count = 3 /* pad */ + params + count;
5678 pSMB->DataCount = cpu_to_le16(count);
5679 pSMB->ParameterCount = cpu_to_le16(params);
5680 pSMB->TotalDataCount = pSMB->DataCount;
5681 pSMB->TotalParameterCount = pSMB->ParameterCount;
5682 pSMB->ParameterOffset = cpu_to_le16(param_offset);
5683 pSMB->DataOffset = cpu_to_le16(offset);
5685 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
5686 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO2);
5688 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO);
5689 pSMB->Reserved4 = 0;
5690 inc_rfc1001_len(pSMB, byte_count);
5691 pSMB->ByteCount = cpu_to_le16(byte_count);
5692 memcpy(data_offset, data, sizeof(FILE_BASIC_INFO));
5693 rc = SendReceiveNoRsp(xid, tcon->ses, (char *) pSMB, 0);
5694 cifs_small_buf_release(pSMB);
5696 cifs_dbg(FYI, "Send error in Set Time (SetFileInfo) = %d\n",
5699 /* Note: On -EAGAIN error only caller can retry on handle based calls
5700 since file handle passed in no longer valid */
5706 CIFSSMBSetFileDisposition(const unsigned int xid, struct cifs_tcon *tcon,
5707 bool delete_file, __u16 fid, __u32 pid_of_opener)
5709 struct smb_com_transaction2_sfi_req *pSMB = NULL;
5712 __u16 params, param_offset, offset, byte_count, count;
5714 cifs_dbg(FYI, "Set File Disposition (via SetFileInfo)\n");
5715 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
5720 pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
5721 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));
5724 pSMB->MaxSetupCount = 0;
5728 pSMB->Reserved2 = 0;
5729 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
5730 offset = param_offset + params;
5732 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
5735 pSMB->MaxParameterCount = cpu_to_le16(2);
5736 /* BB find max SMB PDU from sess */
5737 pSMB->MaxDataCount = cpu_to_le16(1000);
5738 pSMB->SetupCount = 1;
5739 pSMB->Reserved3 = 0;
5740 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
5741 byte_count = 3 /* pad */ + params + count;
5742 pSMB->DataCount = cpu_to_le16(count);
5743 pSMB->ParameterCount = cpu_to_le16(params);
5744 pSMB->TotalDataCount = pSMB->DataCount;
5745 pSMB->TotalParameterCount = pSMB->ParameterCount;
5746 pSMB->ParameterOffset = cpu_to_le16(param_offset);
5747 pSMB->DataOffset = cpu_to_le16(offset);
5749 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_DISPOSITION_INFO);
5750 pSMB->Reserved4 = 0;
5751 inc_rfc1001_len(pSMB, byte_count);
5752 pSMB->ByteCount = cpu_to_le16(byte_count);
5753 *data_offset = delete_file ? 1 : 0;
5754 rc = SendReceiveNoRsp(xid, tcon->ses, (char *) pSMB, 0);
5755 cifs_small_buf_release(pSMB);
5757 cifs_dbg(FYI, "Send error in SetFileDisposition = %d\n", rc);
5763 CIFSSMBSetPathInfo(const unsigned int xid, struct cifs_tcon *tcon,
5764 const char *fileName, const FILE_BASIC_INFO *data,
5765 const struct nls_table *nls_codepage, int remap)
5767 TRANSACTION2_SPI_REQ *pSMB = NULL;
5768 TRANSACTION2_SPI_RSP *pSMBr = NULL;
5771 int bytes_returned = 0;
5773 __u16 params, param_offset, offset, byte_count, count;
5775 cifs_dbg(FYI, "In SetTimes\n");
5778 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5783 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5785 cifsConvertToUTF16((__le16 *) pSMB->FileName, fileName,
5786 PATH_MAX, nls_codepage, remap);
5787 name_len++; /* trailing null */
5789 } else { /* BB improve the check for buffer overruns BB */
5790 name_len = strnlen(fileName, PATH_MAX);
5791 name_len++; /* trailing null */
5792 strncpy(pSMB->FileName, fileName, name_len);
5795 params = 6 + name_len;
5796 count = sizeof(FILE_BASIC_INFO);
5797 pSMB->MaxParameterCount = cpu_to_le16(2);
5798 /* BB find max SMB PDU from sess structure BB */
5799 pSMB->MaxDataCount = cpu_to_le16(1000);
5800 pSMB->MaxSetupCount = 0;
5804 pSMB->Reserved2 = 0;
5805 param_offset = offsetof(struct smb_com_transaction2_spi_req,
5806 InformationLevel) - 4;
5807 offset = param_offset + params;
5808 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
5809 pSMB->ParameterOffset = cpu_to_le16(param_offset);
5810 pSMB->DataOffset = cpu_to_le16(offset);
5811 pSMB->SetupCount = 1;
5812 pSMB->Reserved3 = 0;
5813 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
5814 byte_count = 3 /* pad */ + params + count;
5816 pSMB->DataCount = cpu_to_le16(count);
5817 pSMB->ParameterCount = cpu_to_le16(params);
5818 pSMB->TotalDataCount = pSMB->DataCount;
5819 pSMB->TotalParameterCount = pSMB->ParameterCount;
5820 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
5821 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO2);
5823 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO);
5824 pSMB->Reserved4 = 0;
5825 inc_rfc1001_len(pSMB, byte_count);
5826 memcpy(data_offset, data, sizeof(FILE_BASIC_INFO));
5827 pSMB->ByteCount = cpu_to_le16(byte_count);
5828 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5829 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5831 cifs_dbg(FYI, "SetPathInfo (times) returned %d\n", rc);
5833 cifs_buf_release(pSMB);
5841 /* Can not be used to set time stamps yet (due to old DOS time format) */
5842 /* Can be used to set attributes */
5843 #if 0 /* Possibly not needed - since it turns out that strangely NT4 has a bug
5844 handling it anyway and NT4 was what we thought it would be needed for
5845 Do not delete it until we prove whether needed for Win9x though */
5847 CIFSSMBSetAttrLegacy(unsigned int xid, struct cifs_tcon *tcon, char *fileName,
5848 __u16 dos_attrs, const struct nls_table *nls_codepage)
5850 SETATTR_REQ *pSMB = NULL;
5851 SETATTR_RSP *pSMBr = NULL;
5856 cifs_dbg(FYI, "In SetAttrLegacy\n");
5859 rc = smb_init(SMB_COM_SETATTR, 8, tcon, (void **) &pSMB,
5864 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5866 ConvertToUTF16((__le16 *) pSMB->fileName, fileName,
5867 PATH_MAX, nls_codepage);
5868 name_len++; /* trailing null */
5870 } else { /* BB improve the check for buffer overruns BB */
5871 name_len = strnlen(fileName, PATH_MAX);
5872 name_len++; /* trailing null */
5873 strncpy(pSMB->fileName, fileName, name_len);
5875 pSMB->attr = cpu_to_le16(dos_attrs);
5876 pSMB->BufferFormat = 0x04;
5877 inc_rfc1001_len(pSMB, name_len + 1);
5878 pSMB->ByteCount = cpu_to_le16(name_len + 1);
5879 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5880 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5882 cifs_dbg(FYI, "Error in LegacySetAttr = %d\n", rc);
5884 cifs_buf_release(pSMB);
5887 goto SetAttrLgcyRetry;
5891 #endif /* temporarily unneeded SetAttr legacy function */
5894 cifs_fill_unix_set_info(FILE_UNIX_BASIC_INFO *data_offset,
5895 const struct cifs_unix_set_info_args *args)
5897 u64 uid = NO_CHANGE_64, gid = NO_CHANGE_64;
5898 u64 mode = args->mode;
5900 if (uid_valid(args->uid))
5901 uid = from_kuid(&init_user_ns, args->uid);
5902 if (gid_valid(args->gid))
5903 gid = from_kgid(&init_user_ns, args->gid);
5906 * Samba server ignores set of file size to zero due to bugs in some
5907 * older clients, but we should be precise - we use SetFileSize to
5908 * set file size and do not want to truncate file size to zero
5909 * accidentally as happened on one Samba server beta by putting
5910 * zero instead of -1 here
5912 data_offset->EndOfFile = cpu_to_le64(NO_CHANGE_64);
5913 data_offset->NumOfBytes = cpu_to_le64(NO_CHANGE_64);
5914 data_offset->LastStatusChange = cpu_to_le64(args->ctime);
5915 data_offset->LastAccessTime = cpu_to_le64(args->atime);
5916 data_offset->LastModificationTime = cpu_to_le64(args->mtime);
5917 data_offset->Uid = cpu_to_le64(uid);
5918 data_offset->Gid = cpu_to_le64(gid);
5919 /* better to leave device as zero when it is */
5920 data_offset->DevMajor = cpu_to_le64(MAJOR(args->device));
5921 data_offset->DevMinor = cpu_to_le64(MINOR(args->device));
5922 data_offset->Permissions = cpu_to_le64(mode);
5925 data_offset->Type = cpu_to_le32(UNIX_FILE);
5926 else if (S_ISDIR(mode))
5927 data_offset->Type = cpu_to_le32(UNIX_DIR);
5928 else if (S_ISLNK(mode))
5929 data_offset->Type = cpu_to_le32(UNIX_SYMLINK);
5930 else if (S_ISCHR(mode))
5931 data_offset->Type = cpu_to_le32(UNIX_CHARDEV);
5932 else if (S_ISBLK(mode))
5933 data_offset->Type = cpu_to_le32(UNIX_BLOCKDEV);
5934 else if (S_ISFIFO(mode))
5935 data_offset->Type = cpu_to_le32(UNIX_FIFO);
5936 else if (S_ISSOCK(mode))
5937 data_offset->Type = cpu_to_le32(UNIX_SOCKET);
5941 CIFSSMBUnixSetFileInfo(const unsigned int xid, struct cifs_tcon *tcon,
5942 const struct cifs_unix_set_info_args *args,
5943 u16 fid, u32 pid_of_opener)
5945 struct smb_com_transaction2_sfi_req *pSMB = NULL;
5948 u16 params, param_offset, offset, byte_count, count;
5950 cifs_dbg(FYI, "Set Unix Info (via SetFileInfo)\n");
5951 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
5956 pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
5957 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));
5960 pSMB->MaxSetupCount = 0;
5964 pSMB->Reserved2 = 0;
5965 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
5966 offset = param_offset + params;
5968 data_offset = (char *)pSMB +
5969 offsetof(struct smb_hdr, Protocol) + offset;
5971 count = sizeof(FILE_UNIX_BASIC_INFO);
5973 pSMB->MaxParameterCount = cpu_to_le16(2);
5974 /* BB find max SMB PDU from sess */
5975 pSMB->MaxDataCount = cpu_to_le16(1000);
5976 pSMB->SetupCount = 1;
5977 pSMB->Reserved3 = 0;
5978 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
5979 byte_count = 3 /* pad */ + params + count;
5980 pSMB->DataCount = cpu_to_le16(count);
5981 pSMB->ParameterCount = cpu_to_le16(params);
5982 pSMB->TotalDataCount = pSMB->DataCount;
5983 pSMB->TotalParameterCount = pSMB->ParameterCount;
5984 pSMB->ParameterOffset = cpu_to_le16(param_offset);
5985 pSMB->DataOffset = cpu_to_le16(offset);
5987 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_BASIC);
5988 pSMB->Reserved4 = 0;
5989 inc_rfc1001_len(pSMB, byte_count);
5990 pSMB->ByteCount = cpu_to_le16(byte_count);
5992 cifs_fill_unix_set_info((FILE_UNIX_BASIC_INFO *)data_offset, args);
5994 rc = SendReceiveNoRsp(xid, tcon->ses, (char *) pSMB, 0);
5995 cifs_small_buf_release(pSMB);
5997 cifs_dbg(FYI, "Send error in Set Time (SetFileInfo) = %d\n",
6000 /* Note: On -EAGAIN error only caller can retry on handle based calls
6001 since file handle passed in no longer valid */
6007 CIFSSMBUnixSetPathInfo(const unsigned int xid, struct cifs_tcon *tcon,
6008 const char *file_name,
6009 const struct cifs_unix_set_info_args *args,
6010 const struct nls_table *nls_codepage, int remap)
6012 TRANSACTION2_SPI_REQ *pSMB = NULL;
6013 TRANSACTION2_SPI_RSP *pSMBr = NULL;
6016 int bytes_returned = 0;
6017 FILE_UNIX_BASIC_INFO *data_offset;
6018 __u16 params, param_offset, offset, count, byte_count;
6020 cifs_dbg(FYI, "In SetUID/GID/Mode\n");
6022 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
6027 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
6029 cifsConvertToUTF16((__le16 *) pSMB->FileName, file_name,
6030 PATH_MAX, nls_codepage, remap);
6031 name_len++; /* trailing null */
6033 } else { /* BB improve the check for buffer overruns BB */
6034 name_len = strnlen(file_name, PATH_MAX);
6035 name_len++; /* trailing null */
6036 strncpy(pSMB->FileName, file_name, name_len);
6039 params = 6 + name_len;
6040 count = sizeof(FILE_UNIX_BASIC_INFO);
6041 pSMB->MaxParameterCount = cpu_to_le16(2);
6042 /* BB find max SMB PDU from sess structure BB */
6043 pSMB->MaxDataCount = cpu_to_le16(1000);
6044 pSMB->MaxSetupCount = 0;
6048 pSMB->Reserved2 = 0;
6049 param_offset = offsetof(struct smb_com_transaction2_spi_req,
6050 InformationLevel) - 4;
6051 offset = param_offset + params;
6053 (FILE_UNIX_BASIC_INFO *) ((char *) &pSMB->hdr.Protocol +
6055 memset(data_offset, 0, count);
6056 pSMB->DataOffset = cpu_to_le16(offset);
6057 pSMB->ParameterOffset = cpu_to_le16(param_offset);
6058 pSMB->SetupCount = 1;
6059 pSMB->Reserved3 = 0;
6060 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
6061 byte_count = 3 /* pad */ + params + count;
6062 pSMB->ParameterCount = cpu_to_le16(params);
6063 pSMB->DataCount = cpu_to_le16(count);
6064 pSMB->TotalParameterCount = pSMB->ParameterCount;
6065 pSMB->TotalDataCount = pSMB->DataCount;
6066 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_BASIC);
6067 pSMB->Reserved4 = 0;
6068 inc_rfc1001_len(pSMB, byte_count);
6070 cifs_fill_unix_set_info(data_offset, args);
6072 pSMB->ByteCount = cpu_to_le16(byte_count);
6073 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
6074 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
6076 cifs_dbg(FYI, "SetPathInfo (perms) returned %d\n", rc);
6078 cifs_buf_release(pSMB);
6084 #ifdef CONFIG_CIFS_XATTR
6086 * Do a path-based QUERY_ALL_EAS call and parse the result. This is a common
6087 * function used by listxattr and getxattr type calls. When ea_name is set,
6088 * it looks for that attribute name and stuffs that value into the EAData
6089 * buffer. When ea_name is NULL, it stuffs a list of attribute names into the
6090 * buffer. In both cases, the return value is either the length of the
6091 * resulting data or a negative error code. If EAData is a NULL pointer then
6092 * the data isn't copied to it, but the length is returned.
6095 CIFSSMBQAllEAs(const unsigned int xid, struct cifs_tcon *tcon,
6096 const unsigned char *searchName, const unsigned char *ea_name,
6097 char *EAData, size_t buf_size,
6098 struct cifs_sb_info *cifs_sb)
6100 /* BB assumes one setup word */
6101 TRANSACTION2_QPI_REQ *pSMB = NULL;
6102 TRANSACTION2_QPI_RSP *pSMBr = NULL;
6103 int remap = cifs_remap(cifs_sb);
6104 struct nls_table *nls_codepage = cifs_sb->local_nls;
6108 struct fealist *ea_response_data;
6109 struct fea *temp_fea;
6112 __u16 params, byte_count, data_offset;
6113 unsigned int ea_name_len = ea_name ? strlen(ea_name) : 0;
6115 cifs_dbg(FYI, "In Query All EAs path %s\n", searchName);
6117 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
6122 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
6124 cifsConvertToUTF16((__le16 *) pSMB->FileName, searchName,
6125 PATH_MAX, nls_codepage, remap);
6126 list_len++; /* trailing null */
6128 } else { /* BB improve the check for buffer overruns BB */
6129 list_len = strnlen(searchName, PATH_MAX);
6130 list_len++; /* trailing null */
6131 strncpy(pSMB->FileName, searchName, list_len);
6134 params = 2 /* level */ + 4 /* reserved */ + list_len /* includes NUL */;
6135 pSMB->TotalDataCount = 0;
6136 pSMB->MaxParameterCount = cpu_to_le16(2);
6137 /* BB find exact max SMB PDU from sess structure BB */
6138 pSMB->MaxDataCount = cpu_to_le16(CIFSMaxBufSize);
6139 pSMB->MaxSetupCount = 0;
6143 pSMB->Reserved2 = 0;
6144 pSMB->ParameterOffset = cpu_to_le16(offsetof(
6145 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
6146 pSMB->DataCount = 0;
6147 pSMB->DataOffset = 0;
6148 pSMB->SetupCount = 1;
6149 pSMB->Reserved3 = 0;
6150 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
6151 byte_count = params + 1 /* pad */ ;
6152 pSMB->TotalParameterCount = cpu_to_le16(params);
6153 pSMB->ParameterCount = pSMB->TotalParameterCount;
6154 pSMB->InformationLevel = cpu_to_le16(SMB_INFO_QUERY_ALL_EAS);
6155 pSMB->Reserved4 = 0;
6156 inc_rfc1001_len(pSMB, byte_count);
6157 pSMB->ByteCount = cpu_to_le16(byte_count);
6159 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
6160 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
6162 cifs_dbg(FYI, "Send error in QueryAllEAs = %d\n", rc);
6167 /* BB also check enough total bytes returned */
6168 /* BB we need to improve the validity checking
6169 of these trans2 responses */
6171 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
6172 if (rc || get_bcc(&pSMBr->hdr) < 4) {
6173 rc = -EIO; /* bad smb */
6177 /* check that length of list is not more than bcc */
6178 /* check that each entry does not go beyond length
6180 /* check that each element of each entry does not
6181 go beyond end of list */
6182 /* validate_trans2_offsets() */
6183 /* BB check if start of smb + data_offset > &bcc+ bcc */
6185 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
6186 ea_response_data = (struct fealist *)
6187 (((char *) &pSMBr->hdr.Protocol) + data_offset);
6189 list_len = le32_to_cpu(ea_response_data->list_len);
6190 cifs_dbg(FYI, "ea length %d\n", list_len);
6191 if (list_len <= 8) {
6192 cifs_dbg(FYI, "empty EA list returned from server\n");
6193 /* didn't find the named attribute */
6199 /* make sure list_len doesn't go past end of SMB */
6200 end_of_smb = (char *)pByteArea(&pSMBr->hdr) + get_bcc(&pSMBr->hdr);
6201 if ((char *)ea_response_data + list_len > end_of_smb) {
6202 cifs_dbg(FYI, "EA list appears to go beyond SMB\n");
6207 /* account for ea list len */
6209 temp_fea = ea_response_data->list;
6210 temp_ptr = (char *)temp_fea;
6211 while (list_len > 0) {
6212 unsigned int name_len;
6217 /* make sure we can read name_len and value_len */
6219 cifs_dbg(FYI, "EA entry goes beyond length of list\n");
6224 name_len = temp_fea->name_len;
6225 value_len = le16_to_cpu(temp_fea->value_len);
6226 list_len -= name_len + 1 + value_len;
6228 cifs_dbg(FYI, "EA entry goes beyond length of list\n");
6234 if (ea_name_len == name_len &&
6235 memcmp(ea_name, temp_ptr, name_len) == 0) {
6236 temp_ptr += name_len + 1;
6240 if ((size_t)value_len > buf_size) {
6244 memcpy(EAData, temp_ptr, value_len);
6248 /* account for prefix user. and trailing null */
6249 rc += (5 + 1 + name_len);
6250 if (rc < (int) buf_size) {
6251 memcpy(EAData, "user.", 5);
6253 memcpy(EAData, temp_ptr, name_len);
6255 /* null terminate name */
6258 } else if (buf_size == 0) {
6259 /* skip copy - calc size only */
6261 /* stop before overrun buffer */
6266 temp_ptr += name_len + 1 + value_len;
6267 temp_fea = (struct fea *)temp_ptr;
6270 /* didn't find the named attribute */
6275 cifs_buf_release(pSMB);
6283 CIFSSMBSetEA(const unsigned int xid, struct cifs_tcon *tcon,
6284 const char *fileName, const char *ea_name, const void *ea_value,
6285 const __u16 ea_value_len, const struct nls_table *nls_codepage,
6286 struct cifs_sb_info *cifs_sb)
6288 struct smb_com_transaction2_spi_req *pSMB = NULL;
6289 struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
6290 struct fealist *parm_data;
6293 int bytes_returned = 0;
6294 __u16 params, param_offset, byte_count, offset, count;
6295 int remap = cifs_remap(cifs_sb);
6297 cifs_dbg(FYI, "In SetEA\n");
6299 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
6304 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
6306 cifsConvertToUTF16((__le16 *) pSMB->FileName, fileName,
6307 PATH_MAX, nls_codepage, remap);
6308 name_len++; /* trailing null */
6310 } else { /* BB improve the check for buffer overruns BB */
6311 name_len = strnlen(fileName, PATH_MAX);
6312 name_len++; /* trailing null */
6313 strncpy(pSMB->FileName, fileName, name_len);
6316 params = 6 + name_len;
6318 /* done calculating parms using name_len of file name,
6319 now use name_len to calculate length of ea name
6320 we are going to create in the inode xattrs */
6321 if (ea_name == NULL)
6324 name_len = strnlen(ea_name, 255);
6326 count = sizeof(*parm_data) + ea_value_len + name_len;
6327 pSMB->MaxParameterCount = cpu_to_le16(2);
6328 /* BB find max SMB PDU from sess */
6329 pSMB->MaxDataCount = cpu_to_le16(1000);
6330 pSMB->MaxSetupCount = 0;
6334 pSMB->Reserved2 = 0;
6335 param_offset = offsetof(struct smb_com_transaction2_spi_req,
6336 InformationLevel) - 4;
6337 offset = param_offset + params;
6338 pSMB->InformationLevel =
6339 cpu_to_le16(SMB_SET_FILE_EA);
6342 (struct fealist *) (((char *) &pSMB->hdr.Protocol) +
6344 pSMB->ParameterOffset = cpu_to_le16(param_offset);
6345 pSMB->DataOffset = cpu_to_le16(offset);
6346 pSMB->SetupCount = 1;
6347 pSMB->Reserved3 = 0;
6348 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
6349 byte_count = 3 /* pad */ + params + count;
6350 pSMB->DataCount = cpu_to_le16(count);
6351 parm_data->list_len = cpu_to_le32(count);
6352 parm_data->list[0].EA_flags = 0;
6353 /* we checked above that name len is less than 255 */
6354 parm_data->list[0].name_len = (__u8)name_len;
6355 /* EA names are always ASCII */
6357 strncpy(parm_data->list[0].name, ea_name, name_len);
6358 parm_data->list[0].name[name_len] = 0;
6359 parm_data->list[0].value_len = cpu_to_le16(ea_value_len);
6360 /* caller ensures that ea_value_len is less than 64K but
6361 we need to ensure that it fits within the smb */
6363 /*BB add length check to see if it would fit in
6364 negotiated SMB buffer size BB */
6365 /* if (ea_value_len > buffer_size - 512 (enough for header)) */
6367 memcpy(parm_data->list[0].name+name_len+1,
6368 ea_value, ea_value_len);
6370 pSMB->TotalDataCount = pSMB->DataCount;
6371 pSMB->ParameterCount = cpu_to_le16(params);
6372 pSMB->TotalParameterCount = pSMB->ParameterCount;
6373 pSMB->Reserved4 = 0;
6374 inc_rfc1001_len(pSMB, byte_count);
6375 pSMB->ByteCount = cpu_to_le16(byte_count);
6376 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
6377 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
6379 cifs_dbg(FYI, "SetPathInfo (EA) returned %d\n", rc);
6381 cifs_buf_release(pSMB);
6390 #ifdef CONFIG_CIFS_DNOTIFY_EXPERIMENTAL /* BB unused temporarily */
6392 * Years ago the kernel added a "dnotify" function for Samba server,
6393 * to allow network clients (such as Windows) to display updated
6394 * lists of files in directory listings automatically when
6395 * files are added by one user when another user has the
6396 * same directory open on their desktop. The Linux cifs kernel
6397 * client hooked into the kernel side of this interface for
6398 * the same reason, but ironically when the VFS moved from
6399 * "dnotify" to "inotify" it became harder to plug in Linux
6400 * network file system clients (the most obvious use case
6401 * for notify interfaces is when multiple users can update
6402 * the contents of the same directory - exactly what network
6403 * file systems can do) although the server (Samba) could
6404 * still use it. For the short term we leave the worker
6405 * function ifdeffed out (below) until inotify is fixed
6406 * in the VFS to make it easier to plug in network file
6407 * system clients. If inotify turns out to be permanently
6408 * incompatible for network fs clients, we could instead simply
6409 * expose this config flag by adding a future cifs (and smb2) notify ioctl.
6411 int CIFSSMBNotify(const unsigned int xid, struct cifs_tcon *tcon,
6412 const int notify_subdirs, const __u16 netfid,
6413 __u32 filter, struct file *pfile, int multishot,
6414 const struct nls_table *nls_codepage)
6417 struct smb_com_transaction_change_notify_req *pSMB = NULL;
6418 struct smb_com_ntransaction_change_notify_rsp *pSMBr = NULL;
6419 struct dir_notify_req *dnotify_req;
6422 cifs_dbg(FYI, "In CIFSSMBNotify for file handle %d\n", (int)netfid);
6423 rc = smb_init(SMB_COM_NT_TRANSACT, 23, tcon, (void **) &pSMB,
6428 pSMB->TotalParameterCount = 0 ;
6429 pSMB->TotalDataCount = 0;
6430 pSMB->MaxParameterCount = cpu_to_le32(2);
6431 pSMB->MaxDataCount = cpu_to_le32(CIFSMaxBufSize & 0xFFFFFF00);
6432 pSMB->MaxSetupCount = 4;
6434 pSMB->ParameterOffset = 0;
6435 pSMB->DataCount = 0;
6436 pSMB->DataOffset = 0;
6437 pSMB->SetupCount = 4; /* single byte does not need le conversion */
6438 pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_NOTIFY_CHANGE);
6439 pSMB->ParameterCount = pSMB->TotalParameterCount;
6441 pSMB->WatchTree = 1; /* one byte - no le conversion needed */
6442 pSMB->Reserved2 = 0;
6443 pSMB->CompletionFilter = cpu_to_le32(filter);
6444 pSMB->Fid = netfid; /* file handle always le */
6445 pSMB->ByteCount = 0;
6447 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
6448 (struct smb_hdr *)pSMBr, &bytes_returned,
6451 cifs_dbg(FYI, "Error in Notify = %d\n", rc);
6453 /* Add file to outstanding requests */
6454 /* BB change to kmem cache alloc */
6455 dnotify_req = kmalloc(
6456 sizeof(struct dir_notify_req),
6459 dnotify_req->Pid = pSMB->hdr.Pid;
6460 dnotify_req->PidHigh = pSMB->hdr.PidHigh;
6461 dnotify_req->Mid = pSMB->hdr.Mid;
6462 dnotify_req->Tid = pSMB->hdr.Tid;
6463 dnotify_req->Uid = pSMB->hdr.Uid;
6464 dnotify_req->netfid = netfid;
6465 dnotify_req->pfile = pfile;
6466 dnotify_req->filter = filter;
6467 dnotify_req->multishot = multishot;
6468 spin_lock(&GlobalMid_Lock);
6469 list_add_tail(&dnotify_req->lhead,
6470 &GlobalDnotifyReqList);
6471 spin_unlock(&GlobalMid_Lock);
6475 cifs_buf_release(pSMB);
6478 #endif /* was needed for dnotify, and will be needed for inotify when VFS fix */