brintos

brintos / linux-shallow public Read only

0
0
Text · 171.7 KiB · c6f15db Raw
5931 lines · c
1// SPDX-License-Identifier: LGPL-2.12/*3 *4 *   Copyright (C) International Business Machines  Corp., 2002,20105 *   Author(s): Steve French (sfrench@us.ibm.com)6 *7 *   Contains the routines for constructing the SMB PDUs themselves8 *9 */10 11 /* SMB/CIFS PDU handling routines here - except for leftovers in connect.c   */12 /* These are mostly routines that operate on a pathname, or on a tree id     */13 /* (mounted volume), but there are eight handle based routines which must be */14 /* treated slightly differently for reconnection purposes since we never     */15 /* want to reuse a stale file handle and only the caller knows the file info */16 17#include <linux/fs.h>18#include <linux/filelock.h>19#include <linux/kernel.h>20#include <linux/vfs.h>21#include <linux/slab.h>22#include <linux/posix_acl_xattr.h>23#include <linux/pagemap.h>24#include <linux/swap.h>25#include <linux/task_io_accounting_ops.h>26#include <linux/uaccess.h>27#include <linux/netfs.h>28#include <trace/events/netfs.h>29#include "cifspdu.h"30#include "cifsfs.h"31#include "cifsglob.h"32#include "cifsacl.h"33#include "cifsproto.h"34#include "cifs_unicode.h"35#include "cifs_debug.h"36#include "fscache.h"37#include "smbdirect.h"38#ifdef CONFIG_CIFS_DFS_UPCALL39#include "dfs_cache.h"40#endif41 42#ifdef CONFIG_CIFS_POSIX43static struct {44	int index;45	char *name;46} protocols[] = {47	{CIFS_PROT, "\2NT LM 0.12"},48	{POSIX_PROT, "\2POSIX 2"},49	{BAD_PROT, "\2"}50};51#else52static struct {53	int index;54	char *name;55} protocols[] = {56	{CIFS_PROT, "\2NT LM 0.12"},57	{BAD_PROT, "\2"}58};59#endif60 61/* define the number of elements in the cifs dialect array */62#ifdef CONFIG_CIFS_POSIX63#define CIFS_NUM_PROT 264#else /* not posix */65#define CIFS_NUM_PROT 166#endif /* CIFS_POSIX */67 68 69/* reconnect the socket, tcon, and smb session if needed */70static int71cifs_reconnect_tcon(struct cifs_tcon *tcon, int smb_command)72{73	int rc;74	struct cifs_ses *ses;75	struct TCP_Server_Info *server;76	struct nls_table *nls_codepage = NULL;77 78	/*79	 * SMBs NegProt, SessSetup, uLogoff do not have tcon yet so check for80	 * tcp and smb session status done differently for those three - in the81	 * calling routine82	 */83	if (!tcon)84		return 0;85 86	ses = tcon->ses;87	server = ses->server;88 89	/*90	 * only tree disconnect, open, and write, (and ulogoff which does not91	 * have tcon) are allowed as we start umount92	 */93	spin_lock(&tcon->tc_lock);94	if (tcon->status == TID_EXITING) {95		if (smb_command != SMB_COM_TREE_DISCONNECT) {96			spin_unlock(&tcon->tc_lock);97			cifs_dbg(FYI, "can not send cmd %d while umounting\n",98				 smb_command);99			return -ENODEV;100		}101	}102	spin_unlock(&tcon->tc_lock);103 104again:105	rc = cifs_wait_for_server_reconnect(server, tcon->retry);106	if (rc)107		return rc;108 109	spin_lock(&ses->chan_lock);110	if (!cifs_chan_needs_reconnect(ses, server) && !tcon->need_reconnect) {111		spin_unlock(&ses->chan_lock);112		return 0;113	}114	spin_unlock(&ses->chan_lock);115 116	mutex_lock(&ses->session_mutex);117	/*118	 * Recheck after acquire mutex. If another thread is negotiating119	 * and the server never sends an answer the socket will be closed120	 * and tcpStatus set to reconnect.121	 */122	spin_lock(&server->srv_lock);123	if (server->tcpStatus == CifsNeedReconnect) {124		spin_unlock(&server->srv_lock);125		mutex_unlock(&ses->session_mutex);126 127		if (tcon->retry)128			goto again;129		rc = -EHOSTDOWN;130		goto out;131	}132	spin_unlock(&server->srv_lock);133 134	nls_codepage = ses->local_nls;135 136	/*137	 * need to prevent multiple threads trying to simultaneously138	 * reconnect the same SMB session139	 */140	spin_lock(&ses->ses_lock);141	spin_lock(&ses->chan_lock);142	if (!cifs_chan_needs_reconnect(ses, server) &&143	    ses->ses_status == SES_GOOD) {144		spin_unlock(&ses->chan_lock);145		spin_unlock(&ses->ses_lock);146 147		/* this means that we only need to tree connect */148		if (tcon->need_reconnect)149			goto skip_sess_setup;150 151		mutex_unlock(&ses->session_mutex);152		goto out;153	}154	spin_unlock(&ses->chan_lock);155	spin_unlock(&ses->ses_lock);156 157	rc = cifs_negotiate_protocol(0, ses, server);158	if (!rc)159		rc = cifs_setup_session(0, ses, server, nls_codepage);160 161	/* do we need to reconnect tcon? */162	if (rc || !tcon->need_reconnect) {163		mutex_unlock(&ses->session_mutex);164		goto out;165	}166 167skip_sess_setup:168	cifs_mark_open_files_invalid(tcon);169	rc = cifs_tree_connect(0, tcon, nls_codepage);170	mutex_unlock(&ses->session_mutex);171	cifs_dbg(FYI, "reconnect tcon rc = %d\n", rc);172 173	if (rc) {174		pr_warn_once("reconnect tcon failed rc = %d\n", rc);175		goto out;176	}177 178	atomic_inc(&tconInfoReconnectCount);179 180	/* tell server Unix caps we support */181	if (cap_unix(ses))182		reset_cifs_unix_caps(0, tcon, NULL, NULL);183 184	/*185	 * Removed call to reopen open files here. It is safer (and faster) to186	 * reopen files one at a time as needed in read and write.187	 *188	 * FIXME: what about file locks? don't we need to reclaim them ASAP?189	 */190 191out:192	/*193	 * Check if handle based operation so we know whether we can continue194	 * or not without returning to caller to reset file handle195	 */196	switch (smb_command) {197	case SMB_COM_READ_ANDX:198	case SMB_COM_WRITE_ANDX:199	case SMB_COM_CLOSE:200	case SMB_COM_FIND_CLOSE2:201	case SMB_COM_LOCKING_ANDX:202		rc = -EAGAIN;203	}204 205	return rc;206}207 208/* Allocate and return pointer to an SMB request buffer, and set basic209   SMB information in the SMB header.  If the return code is zero, this210   function must have filled in request_buf pointer */211static int212small_smb_init(int smb_command, int wct, struct cifs_tcon *tcon,213		void **request_buf)214{215	int rc;216 217	rc = cifs_reconnect_tcon(tcon, smb_command);218	if (rc)219		return rc;220 221	*request_buf = cifs_small_buf_get();222	if (*request_buf == NULL) {223		/* BB should we add a retry in here if not a writepage? */224		return -ENOMEM;225	}226 227	header_assemble((struct smb_hdr *) *request_buf, smb_command,228			tcon, wct);229 230	if (tcon != NULL)231		cifs_stats_inc(&tcon->num_smbs_sent);232 233	return 0;234}235 236int237small_smb_init_no_tc(const int smb_command, const int wct,238		     struct cifs_ses *ses, void **request_buf)239{240	int rc;241	struct smb_hdr *buffer;242 243	rc = small_smb_init(smb_command, wct, NULL, request_buf);244	if (rc)245		return rc;246 247	buffer = (struct smb_hdr *)*request_buf;248	buffer->Mid = get_next_mid(ses->server);249	if (ses->capabilities & CAP_UNICODE)250		buffer->Flags2 |= SMBFLG2_UNICODE;251	if (ses->capabilities & CAP_STATUS32)252		buffer->Flags2 |= SMBFLG2_ERR_STATUS;253 254	/* uid, tid can stay at zero as set in header assemble */255 256	/* BB add support for turning on the signing when257	this function is used after 1st of session setup requests */258 259	return rc;260}261 262/* If the return code is zero, this function must fill in request_buf pointer */263static int264__smb_init(int smb_command, int wct, struct cifs_tcon *tcon,265			void **request_buf, void **response_buf)266{267	*request_buf = cifs_buf_get();268	if (*request_buf == NULL) {269		/* BB should we add a retry in here if not a writepage? */270		return -ENOMEM;271	}272    /* Although the original thought was we needed the response buf for  */273    /* potential retries of smb operations it turns out we can determine */274    /* from the mid flags when the request buffer can be resent without  */275    /* having to use a second distinct buffer for the response */276	if (response_buf)277		*response_buf = *request_buf;278 279	header_assemble((struct smb_hdr *) *request_buf, smb_command, tcon,280			wct);281 282	if (tcon != NULL)283		cifs_stats_inc(&tcon->num_smbs_sent);284 285	return 0;286}287 288/* If the return code is zero, this function must fill in request_buf pointer */289static int290smb_init(int smb_command, int wct, struct cifs_tcon *tcon,291	 void **request_buf, void **response_buf)292{293	int rc;294 295	rc = cifs_reconnect_tcon(tcon, smb_command);296	if (rc)297		return rc;298 299	return __smb_init(smb_command, wct, tcon, request_buf, response_buf);300}301 302static int303smb_init_no_reconnect(int smb_command, int wct, struct cifs_tcon *tcon,304			void **request_buf, void **response_buf)305{306	spin_lock(&tcon->ses->chan_lock);307	if (cifs_chan_needs_reconnect(tcon->ses, tcon->ses->server) ||308	    tcon->need_reconnect) {309		spin_unlock(&tcon->ses->chan_lock);310		return -EHOSTDOWN;311	}312	spin_unlock(&tcon->ses->chan_lock);313 314	return __smb_init(smb_command, wct, tcon, request_buf, response_buf);315}316 317static int validate_t2(struct smb_t2_rsp *pSMB)318{319	unsigned int total_size;320 321	/* check for plausible wct */322	if (pSMB->hdr.WordCount < 10)323		goto vt2_err;324 325	/* check for parm and data offset going beyond end of smb */326	if (get_unaligned_le16(&pSMB->t2_rsp.ParameterOffset) > 1024 ||327	    get_unaligned_le16(&pSMB->t2_rsp.DataOffset) > 1024)328		goto vt2_err;329 330	total_size = get_unaligned_le16(&pSMB->t2_rsp.ParameterCount);331	if (total_size >= 512)332		goto vt2_err;333 334	/* check that bcc is at least as big as parms + data, and that it is335	 * less than negotiated smb buffer336	 */337	total_size += get_unaligned_le16(&pSMB->t2_rsp.DataCount);338	if (total_size > get_bcc(&pSMB->hdr) ||339	    total_size >= CIFSMaxBufSize + MAX_CIFS_HDR_SIZE)340		goto vt2_err;341 342	return 0;343vt2_err:344	cifs_dump_mem("Invalid transact2 SMB: ", (char *)pSMB,345		sizeof(struct smb_t2_rsp) + 16);346	return -EINVAL;347}348 349static int350decode_ext_sec_blob(struct cifs_ses *ses, NEGOTIATE_RSP *pSMBr)351{352	int	rc = 0;353	u16	count;354	char	*guid = pSMBr->u.extended_response.GUID;355	struct TCP_Server_Info *server = ses->server;356 357	count = get_bcc(&pSMBr->hdr);358	if (count < SMB1_CLIENT_GUID_SIZE)359		return -EIO;360 361	spin_lock(&cifs_tcp_ses_lock);362	if (server->srv_count > 1) {363		spin_unlock(&cifs_tcp_ses_lock);364		if (memcmp(server->server_GUID, guid, SMB1_CLIENT_GUID_SIZE) != 0) {365			cifs_dbg(FYI, "server UID changed\n");366			memcpy(server->server_GUID, guid, SMB1_CLIENT_GUID_SIZE);367		}368	} else {369		spin_unlock(&cifs_tcp_ses_lock);370		memcpy(server->server_GUID, guid, SMB1_CLIENT_GUID_SIZE);371	}372 373	if (count == SMB1_CLIENT_GUID_SIZE) {374		server->sec_ntlmssp = true;375	} else {376		count -= SMB1_CLIENT_GUID_SIZE;377		rc = decode_negTokenInit(378			pSMBr->u.extended_response.SecurityBlob, count, server);379		if (rc != 1)380			return -EINVAL;381	}382 383	return 0;384}385 386static bool387should_set_ext_sec_flag(enum securityEnum sectype)388{389	switch (sectype) {390	case RawNTLMSSP:391	case Kerberos:392		return true;393	case Unspecified:394		if (global_secflags &395		    (CIFSSEC_MAY_KRB5 | CIFSSEC_MAY_NTLMSSP))396			return true;397		fallthrough;398	default:399		return false;400	}401}402 403int404CIFSSMBNegotiate(const unsigned int xid,405		 struct cifs_ses *ses,406		 struct TCP_Server_Info *server)407{408	NEGOTIATE_REQ *pSMB;409	NEGOTIATE_RSP *pSMBr;410	int rc = 0;411	int bytes_returned;412	int i;413	u16 count;414 415	if (!server) {416		WARN(1, "%s: server is NULL!\n", __func__);417		return -EIO;418	}419 420	rc = smb_init(SMB_COM_NEGOTIATE, 0, NULL /* no tcon yet */ ,421		      (void **) &pSMB, (void **) &pSMBr);422	if (rc)423		return rc;424 425	pSMB->hdr.Mid = get_next_mid(server);426	pSMB->hdr.Flags2 |= (SMBFLG2_UNICODE | SMBFLG2_ERR_STATUS);427 428	if (should_set_ext_sec_flag(ses->sectype)) {429		cifs_dbg(FYI, "Requesting extended security\n");430		pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC;431	}432 433	count = 0;434	/*435	 * We know that all the name entries in the protocols array436	 * are short (< 16 bytes anyway) and are NUL terminated.437	 */438	for (i = 0; i < CIFS_NUM_PROT; i++) {439		size_t len = strlen(protocols[i].name) + 1;440 441		memcpy(&pSMB->DialectsArray[count], protocols[i].name, len);442		count += len;443	}444	inc_rfc1001_len(pSMB, count);445	pSMB->ByteCount = cpu_to_le16(count);446 447	rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB,448			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);449	if (rc != 0)450		goto neg_err_exit;451 452	server->dialect = le16_to_cpu(pSMBr->DialectIndex);453	cifs_dbg(FYI, "Dialect: %d\n", server->dialect);454	/* Check wct = 1 error case */455	if ((pSMBr->hdr.WordCount <= 13) || (server->dialect == BAD_PROT)) {456		/* core returns wct = 1, but we do not ask for core - otherwise457		small wct just comes when dialect index is -1 indicating we458		could not negotiate a common dialect */459		rc = -EOPNOTSUPP;460		goto neg_err_exit;461	} else if (pSMBr->hdr.WordCount != 17) {462		/* unknown wct */463		rc = -EOPNOTSUPP;464		goto neg_err_exit;465	}466	/* else wct == 17, NTLM or better */467 468	server->sec_mode = pSMBr->SecurityMode;469	if ((server->sec_mode & SECMODE_USER) == 0)470		cifs_dbg(FYI, "share mode security\n");471 472	/* one byte, so no need to convert this or EncryptionKeyLen from473	   little endian */474	server->maxReq = min_t(unsigned int, le16_to_cpu(pSMBr->MaxMpxCount),475			       cifs_max_pending);476	set_credits(server, server->maxReq);477	/* probably no need to store and check maxvcs */478	server->maxBuf = le32_to_cpu(pSMBr->MaxBufferSize);479	/* set up max_read for readahead check */480	server->max_read = server->maxBuf;481	server->max_rw = le32_to_cpu(pSMBr->MaxRawSize);482	cifs_dbg(NOISY, "Max buf = %d\n", ses->server->maxBuf);483	server->capabilities = le32_to_cpu(pSMBr->Capabilities);484	server->timeAdj = (int)(__s16)le16_to_cpu(pSMBr->ServerTimeZone);485	server->timeAdj *= 60;486 487	if (pSMBr->EncryptionKeyLength == CIFS_CRYPTO_KEY_SIZE) {488		server->negflavor = CIFS_NEGFLAVOR_UNENCAP;489		memcpy(ses->server->cryptkey, pSMBr->u.EncryptionKey,490		       CIFS_CRYPTO_KEY_SIZE);491	} else if (pSMBr->hdr.Flags2 & SMBFLG2_EXT_SEC ||492			server->capabilities & CAP_EXTENDED_SECURITY) {493		server->negflavor = CIFS_NEGFLAVOR_EXTENDED;494		rc = decode_ext_sec_blob(ses, pSMBr);495	} else if (server->sec_mode & SECMODE_PW_ENCRYPT) {496		rc = -EIO; /* no crypt key only if plain text pwd */497	} else {498		server->negflavor = CIFS_NEGFLAVOR_UNENCAP;499		server->capabilities &= ~CAP_EXTENDED_SECURITY;500	}501 502	if (!rc)503		rc = cifs_enable_signing(server, ses->sign);504neg_err_exit:505	cifs_buf_release(pSMB);506 507	cifs_dbg(FYI, "negprot rc %d\n", rc);508	return rc;509}510 511int512CIFSSMBTDis(const unsigned int xid, struct cifs_tcon *tcon)513{514	struct smb_hdr *smb_buffer;515	int rc = 0;516 517	cifs_dbg(FYI, "In tree disconnect\n");518 519	/* BB: do we need to check this? These should never be NULL. */520	if ((tcon->ses == NULL) || (tcon->ses->server == NULL))521		return -EIO;522 523	/*524	 * No need to return error on this operation if tid invalidated and525	 * closed on server already e.g. due to tcp session crashing. Also,526	 * the tcon is no longer on the list, so no need to take lock before527	 * checking this.528	 */529	spin_lock(&tcon->ses->chan_lock);530	if ((tcon->need_reconnect) || CIFS_ALL_CHANS_NEED_RECONNECT(tcon->ses)) {531		spin_unlock(&tcon->ses->chan_lock);532		return -EIO;533	}534	spin_unlock(&tcon->ses->chan_lock);535 536	rc = small_smb_init(SMB_COM_TREE_DISCONNECT, 0, tcon,537			    (void **)&smb_buffer);538	if (rc)539		return rc;540 541	rc = SendReceiveNoRsp(xid, tcon->ses, (char *)smb_buffer, 0);542	cifs_small_buf_release(smb_buffer);543	if (rc)544		cifs_dbg(FYI, "Tree disconnect failed %d\n", rc);545 546	/* No need to return error on this operation if tid invalidated and547	   closed on server already e.g. due to tcp session crashing */548	if (rc == -EAGAIN)549		rc = 0;550 551	return rc;552}553 554/*555 * This is a no-op for now. We're not really interested in the reply, but556 * rather in the fact that the server sent one and that server->lstrp557 * gets updated.558 *559 * FIXME: maybe we should consider checking that the reply matches request?560 */561static void562cifs_echo_callback(struct mid_q_entry *mid)563{564	struct TCP_Server_Info *server = mid->callback_data;565	struct cifs_credits credits = { .value = 1, .instance = 0 };566 567	release_mid(mid);568	add_credits(server, &credits, CIFS_ECHO_OP);569}570 571int572CIFSSMBEcho(struct TCP_Server_Info *server)573{574	ECHO_REQ *smb;575	int rc = 0;576	struct kvec iov[2];577	struct smb_rqst rqst = { .rq_iov = iov,578				 .rq_nvec = 2 };579 580	cifs_dbg(FYI, "In echo request\n");581 582	rc = small_smb_init(SMB_COM_ECHO, 0, NULL, (void **)&smb);583	if (rc)584		return rc;585 586	if (server->capabilities & CAP_UNICODE)587		smb->hdr.Flags2 |= SMBFLG2_UNICODE;588 589	/* set up echo request */590	smb->hdr.Tid = 0xffff;591	smb->hdr.WordCount = 1;592	put_unaligned_le16(1, &smb->EchoCount);593	put_bcc(1, &smb->hdr);594	smb->Data[0] = 'a';595	inc_rfc1001_len(smb, 3);596 597	iov[0].iov_len = 4;598	iov[0].iov_base = smb;599	iov[1].iov_len = get_rfc1002_length(smb);600	iov[1].iov_base = (char *)smb + 4;601 602	rc = cifs_call_async(server, &rqst, NULL, cifs_echo_callback, NULL,603			     server, CIFS_NON_BLOCKING | CIFS_ECHO_OP, NULL);604	if (rc)605		cifs_dbg(FYI, "Echo request failed: %d\n", rc);606 607	cifs_small_buf_release(smb);608 609	return rc;610}611 612int613CIFSSMBLogoff(const unsigned int xid, struct cifs_ses *ses)614{615	LOGOFF_ANDX_REQ *pSMB;616	int rc = 0;617 618	cifs_dbg(FYI, "In SMBLogoff for session disconnect\n");619 620	/*621	 * BB: do we need to check validity of ses and server? They should622	 * always be valid since we have an active reference. If not, that623	 * should probably be a BUG()624	 */625	if (!ses || !ses->server)626		return -EIO;627 628	mutex_lock(&ses->session_mutex);629	spin_lock(&ses->chan_lock);630	if (CIFS_ALL_CHANS_NEED_RECONNECT(ses)) {631		spin_unlock(&ses->chan_lock);632		goto session_already_dead; /* no need to send SMBlogoff if uid633					      already closed due to reconnect */634	}635	spin_unlock(&ses->chan_lock);636 637	rc = small_smb_init(SMB_COM_LOGOFF_ANDX, 2, NULL, (void **)&pSMB);638	if (rc) {639		mutex_unlock(&ses->session_mutex);640		return rc;641	}642 643	pSMB->hdr.Mid = get_next_mid(ses->server);644 645	if (ses->server->sign)646		pSMB->hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE;647 648	pSMB->hdr.Uid = ses->Suid;649 650	pSMB->AndXCommand = 0xFF;651	rc = SendReceiveNoRsp(xid, ses, (char *) pSMB, 0);652	cifs_small_buf_release(pSMB);653session_already_dead:654	mutex_unlock(&ses->session_mutex);655 656	/* if session dead then we do not need to do ulogoff,657		since server closed smb session, no sense reporting658		error */659	if (rc == -EAGAIN)660		rc = 0;661	return rc;662}663 664int665CIFSPOSIXDelFile(const unsigned int xid, struct cifs_tcon *tcon,666		 const char *fileName, __u16 type,667		 const struct nls_table *nls_codepage, int remap)668{669	TRANSACTION2_SPI_REQ *pSMB = NULL;670	TRANSACTION2_SPI_RSP *pSMBr = NULL;671	struct unlink_psx_rq *pRqD;672	int name_len;673	int rc = 0;674	int bytes_returned = 0;675	__u16 params, param_offset, offset, byte_count;676 677	cifs_dbg(FYI, "In POSIX delete\n");678PsxDelete:679	rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,680		      (void **) &pSMBr);681	if (rc)682		return rc;683 684	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {685		name_len =686		    cifsConvertToUTF16((__le16 *) pSMB->FileName, fileName,687				       PATH_MAX, nls_codepage, remap);688		name_len++;	/* trailing null */689		name_len *= 2;690	} else {691		name_len = copy_path_name(pSMB->FileName, fileName);692	}693 694	params = 6 + name_len;695	pSMB->MaxParameterCount = cpu_to_le16(2);696	pSMB->MaxDataCount = 0; /* BB double check this with jra */697	pSMB->MaxSetupCount = 0;698	pSMB->Reserved = 0;699	pSMB->Flags = 0;700	pSMB->Timeout = 0;701	pSMB->Reserved2 = 0;702	param_offset = offsetof(struct smb_com_transaction2_spi_req,703				InformationLevel) - 4;704	offset = param_offset + params;705 706	/* Setup pointer to Request Data (inode type).707	 * Note that SMB offsets are from the beginning of SMB which is 4 bytes708	 * in, after RFC1001 field709	 */710	pRqD = (struct unlink_psx_rq *)((char *)(pSMB) + offset + 4);711	pRqD->type = cpu_to_le16(type);712	pSMB->ParameterOffset = cpu_to_le16(param_offset);713	pSMB->DataOffset = cpu_to_le16(offset);714	pSMB->SetupCount = 1;715	pSMB->Reserved3 = 0;716	pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);717	byte_count = 3 /* pad */  + params + sizeof(struct unlink_psx_rq);718 719	pSMB->DataCount = cpu_to_le16(sizeof(struct unlink_psx_rq));720	pSMB->TotalDataCount = cpu_to_le16(sizeof(struct unlink_psx_rq));721	pSMB->ParameterCount = cpu_to_le16(params);722	pSMB->TotalParameterCount = pSMB->ParameterCount;723	pSMB->InformationLevel = cpu_to_le16(SMB_POSIX_UNLINK);724	pSMB->Reserved4 = 0;725	inc_rfc1001_len(pSMB, byte_count);726	pSMB->ByteCount = cpu_to_le16(byte_count);727	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,728			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);729	if (rc)730		cifs_dbg(FYI, "Posix delete returned %d\n", rc);731	cifs_buf_release(pSMB);732 733	cifs_stats_inc(&tcon->stats.cifs_stats.num_deletes);734 735	if (rc == -EAGAIN)736		goto PsxDelete;737 738	return rc;739}740 741int742CIFSSMBDelFile(const unsigned int xid, struct cifs_tcon *tcon, const char *name,743	       struct cifs_sb_info *cifs_sb, struct dentry *dentry)744{745	DELETE_FILE_REQ *pSMB = NULL;746	DELETE_FILE_RSP *pSMBr = NULL;747	int rc = 0;748	int bytes_returned;749	int name_len;750	int remap = cifs_remap(cifs_sb);751 752DelFileRetry:753	rc = smb_init(SMB_COM_DELETE, 1, tcon, (void **) &pSMB,754		      (void **) &pSMBr);755	if (rc)756		return rc;757 758	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {759		name_len = cifsConvertToUTF16((__le16 *) pSMB->fileName, name,760					      PATH_MAX, cifs_sb->local_nls,761					      remap);762		name_len++;	/* trailing null */763		name_len *= 2;764	} else {765		name_len = copy_path_name(pSMB->fileName, name);766	}767	pSMB->SearchAttributes =768	    cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM);769	pSMB->BufferFormat = 0x04;770	inc_rfc1001_len(pSMB, name_len + 1);771	pSMB->ByteCount = cpu_to_le16(name_len + 1);772	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,773			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);774	cifs_stats_inc(&tcon->stats.cifs_stats.num_deletes);775	if (rc)776		cifs_dbg(FYI, "Error in RMFile = %d\n", rc);777 778	cifs_buf_release(pSMB);779	if (rc == -EAGAIN)780		goto DelFileRetry;781 782	return rc;783}784 785int786CIFSSMBRmDir(const unsigned int xid, struct cifs_tcon *tcon, const char *name,787	     struct cifs_sb_info *cifs_sb)788{789	DELETE_DIRECTORY_REQ *pSMB = NULL;790	DELETE_DIRECTORY_RSP *pSMBr = NULL;791	int rc = 0;792	int bytes_returned;793	int name_len;794	int remap = cifs_remap(cifs_sb);795 796	cifs_dbg(FYI, "In CIFSSMBRmDir\n");797RmDirRetry:798	rc = smb_init(SMB_COM_DELETE_DIRECTORY, 0, tcon, (void **) &pSMB,799		      (void **) &pSMBr);800	if (rc)801		return rc;802 803	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {804		name_len = cifsConvertToUTF16((__le16 *) pSMB->DirName, name,805					      PATH_MAX, cifs_sb->local_nls,806					      remap);807		name_len++;	/* trailing null */808		name_len *= 2;809	} else {810		name_len = copy_path_name(pSMB->DirName, name);811	}812 813	pSMB->BufferFormat = 0x04;814	inc_rfc1001_len(pSMB, name_len + 1);815	pSMB->ByteCount = cpu_to_le16(name_len + 1);816	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,817			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);818	cifs_stats_inc(&tcon->stats.cifs_stats.num_rmdirs);819	if (rc)820		cifs_dbg(FYI, "Error in RMDir = %d\n", rc);821 822	cifs_buf_release(pSMB);823	if (rc == -EAGAIN)824		goto RmDirRetry;825	return rc;826}827 828int829CIFSSMBMkDir(const unsigned int xid, struct inode *inode, umode_t mode,830	     struct cifs_tcon *tcon, const char *name,831	     struct cifs_sb_info *cifs_sb)832{833	int rc = 0;834	CREATE_DIRECTORY_REQ *pSMB = NULL;835	CREATE_DIRECTORY_RSP *pSMBr = NULL;836	int bytes_returned;837	int name_len;838	int remap = cifs_remap(cifs_sb);839 840	cifs_dbg(FYI, "In CIFSSMBMkDir\n");841MkDirRetry:842	rc = smb_init(SMB_COM_CREATE_DIRECTORY, 0, tcon, (void **) &pSMB,843		      (void **) &pSMBr);844	if (rc)845		return rc;846 847	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {848		name_len = cifsConvertToUTF16((__le16 *) pSMB->DirName, name,849					      PATH_MAX, cifs_sb->local_nls,850					      remap);851		name_len++;	/* trailing null */852		name_len *= 2;853	} else {854		name_len = copy_path_name(pSMB->DirName, name);855	}856 857	pSMB->BufferFormat = 0x04;858	inc_rfc1001_len(pSMB, name_len + 1);859	pSMB->ByteCount = cpu_to_le16(name_len + 1);860	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,861			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);862	cifs_stats_inc(&tcon->stats.cifs_stats.num_mkdirs);863	if (rc)864		cifs_dbg(FYI, "Error in Mkdir = %d\n", rc);865 866	cifs_buf_release(pSMB);867	if (rc == -EAGAIN)868		goto MkDirRetry;869	return rc;870}871 872int873CIFSPOSIXCreate(const unsigned int xid, struct cifs_tcon *tcon,874		__u32 posix_flags, __u64 mode, __u16 *netfid,875		FILE_UNIX_BASIC_INFO *pRetData, __u32 *pOplock,876		const char *name, const struct nls_table *nls_codepage,877		int remap)878{879	TRANSACTION2_SPI_REQ *pSMB = NULL;880	TRANSACTION2_SPI_RSP *pSMBr = NULL;881	int name_len;882	int rc = 0;883	int bytes_returned = 0;884	__u16 params, param_offset, offset, byte_count, count;885	OPEN_PSX_REQ *pdata;886	OPEN_PSX_RSP *psx_rsp;887 888	cifs_dbg(FYI, "In POSIX Create\n");889PsxCreat:890	rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,891		      (void **) &pSMBr);892	if (rc)893		return rc;894 895	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {896		name_len =897		    cifsConvertToUTF16((__le16 *) pSMB->FileName, name,898				       PATH_MAX, nls_codepage, remap);899		name_len++;	/* trailing null */900		name_len *= 2;901	} else {902		name_len = copy_path_name(pSMB->FileName, name);903	}904 905	params = 6 + name_len;906	count = sizeof(OPEN_PSX_REQ);907	pSMB->MaxParameterCount = cpu_to_le16(2);908	pSMB->MaxDataCount = cpu_to_le16(1000);	/* large enough */909	pSMB->MaxSetupCount = 0;910	pSMB->Reserved = 0;911	pSMB->Flags = 0;912	pSMB->Timeout = 0;913	pSMB->Reserved2 = 0;914	param_offset = offsetof(struct smb_com_transaction2_spi_req,915				InformationLevel) - 4;916	offset = param_offset + params;917	/* SMB offsets are from the beginning of SMB which is 4 bytes in, after RFC1001 field */918	pdata = (OPEN_PSX_REQ *)((char *)(pSMB) + offset + 4);919	pdata->Level = cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC);920	pdata->Permissions = cpu_to_le64(mode);921	pdata->PosixOpenFlags = cpu_to_le32(posix_flags);922	pdata->OpenFlags =  cpu_to_le32(*pOplock);923	pSMB->ParameterOffset = cpu_to_le16(param_offset);924	pSMB->DataOffset = cpu_to_le16(offset);925	pSMB->SetupCount = 1;926	pSMB->Reserved3 = 0;927	pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);928	byte_count = 3 /* pad */  + params + count;929 930	pSMB->DataCount = cpu_to_le16(count);931	pSMB->ParameterCount = cpu_to_le16(params);932	pSMB->TotalDataCount = pSMB->DataCount;933	pSMB->TotalParameterCount = pSMB->ParameterCount;934	pSMB->InformationLevel = cpu_to_le16(SMB_POSIX_OPEN);935	pSMB->Reserved4 = 0;936	inc_rfc1001_len(pSMB, byte_count);937	pSMB->ByteCount = cpu_to_le16(byte_count);938	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,939			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);940	if (rc) {941		cifs_dbg(FYI, "Posix create returned %d\n", rc);942		goto psx_create_err;943	}944 945	cifs_dbg(FYI, "copying inode info\n");946	rc = validate_t2((struct smb_t2_rsp *)pSMBr);947 948	if (rc || get_bcc(&pSMBr->hdr) < sizeof(OPEN_PSX_RSP)) {949		rc = -EIO;	/* bad smb */950		goto psx_create_err;951	}952 953	/* copy return information to pRetData */954	psx_rsp = (OPEN_PSX_RSP *)((char *) &pSMBr->hdr.Protocol955			+ le16_to_cpu(pSMBr->t2.DataOffset));956 957	*pOplock = le16_to_cpu(psx_rsp->OplockFlags);958	if (netfid)959		*netfid = psx_rsp->Fid;   /* cifs fid stays in le */960	/* Let caller know file was created so we can set the mode. */961	/* Do we care about the CreateAction in any other cases? */962	if (cpu_to_le32(FILE_CREATE) == psx_rsp->CreateAction)963		*pOplock |= CIFS_CREATE_ACTION;964	/* check to make sure response data is there */965	if (psx_rsp->ReturnedLevel != cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC)) {966		pRetData->Type = cpu_to_le32(-1); /* unknown */967		cifs_dbg(NOISY, "unknown type\n");968	} else {969		if (get_bcc(&pSMBr->hdr) < sizeof(OPEN_PSX_RSP)970					+ sizeof(FILE_UNIX_BASIC_INFO)) {971			cifs_dbg(VFS, "Open response data too small\n");972			pRetData->Type = cpu_to_le32(-1);973			goto psx_create_err;974		}975		memcpy((char *) pRetData,976			(char *)psx_rsp + sizeof(OPEN_PSX_RSP),977			sizeof(FILE_UNIX_BASIC_INFO));978	}979 980psx_create_err:981	cifs_buf_release(pSMB);982 983	if (posix_flags & SMB_O_DIRECTORY)984		cifs_stats_inc(&tcon->stats.cifs_stats.num_posixmkdirs);985	else986		cifs_stats_inc(&tcon->stats.cifs_stats.num_posixopens);987 988	if (rc == -EAGAIN)989		goto PsxCreat;990 991	return rc;992}993 994static __u16 convert_disposition(int disposition)995{996	__u16 ofun = 0;997 998	switch (disposition) {999		case FILE_SUPERSEDE:1000			ofun = SMBOPEN_OCREATE | SMBOPEN_OTRUNC;1001			break;1002		case FILE_OPEN:1003			ofun = SMBOPEN_OAPPEND;1004			break;1005		case FILE_CREATE:1006			ofun = SMBOPEN_OCREATE;1007			break;1008		case FILE_OPEN_IF:1009			ofun = SMBOPEN_OCREATE | SMBOPEN_OAPPEND;1010			break;1011		case FILE_OVERWRITE:1012			ofun = SMBOPEN_OTRUNC;1013			break;1014		case FILE_OVERWRITE_IF:1015			ofun = SMBOPEN_OCREATE | SMBOPEN_OTRUNC;1016			break;1017		default:1018			cifs_dbg(FYI, "unknown disposition %d\n", disposition);1019			ofun =  SMBOPEN_OAPPEND; /* regular open */1020	}1021	return ofun;1022}1023 1024static int1025access_flags_to_smbopen_mode(const int access_flags)1026{1027	int masked_flags = access_flags & (GENERIC_READ | GENERIC_WRITE);1028 1029	if (masked_flags == GENERIC_READ)1030		return SMBOPEN_READ;1031	else if (masked_flags == GENERIC_WRITE)1032		return SMBOPEN_WRITE;1033 1034	/* just go for read/write */1035	return SMBOPEN_READWRITE;1036}1037 1038int1039SMBLegacyOpen(const unsigned int xid, struct cifs_tcon *tcon,1040	    const char *fileName, const int openDisposition,1041	    const int access_flags, const int create_options, __u16 *netfid,1042	    int *pOplock, FILE_ALL_INFO *pfile_info,1043	    const struct nls_table *nls_codepage, int remap)1044{1045	int rc;1046	OPENX_REQ *pSMB = NULL;1047	OPENX_RSP *pSMBr = NULL;1048	int bytes_returned;1049	int name_len;1050	__u16 count;1051 1052OldOpenRetry:1053	rc = smb_init(SMB_COM_OPEN_ANDX, 15, tcon, (void **) &pSMB,1054		      (void **) &pSMBr);1055	if (rc)1056		return rc;1057 1058	pSMB->AndXCommand = 0xFF;       /* none */1059 1060	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {1061		count = 1;      /* account for one byte pad to word boundary */1062		name_len =1063		   cifsConvertToUTF16((__le16 *) (pSMB->fileName + 1),1064				      fileName, PATH_MAX, nls_codepage, remap);1065		name_len++;     /* trailing null */1066		name_len *= 2;1067	} else {1068		count = 0;      /* no pad */1069		name_len = copy_path_name(pSMB->fileName, fileName);1070	}1071	if (*pOplock & REQ_OPLOCK)1072		pSMB->OpenFlags = cpu_to_le16(REQ_OPLOCK);1073	else if (*pOplock & REQ_BATCHOPLOCK)1074		pSMB->OpenFlags = cpu_to_le16(REQ_BATCHOPLOCK);1075 1076	pSMB->OpenFlags |= cpu_to_le16(REQ_MORE_INFO);1077	pSMB->Mode = cpu_to_le16(access_flags_to_smbopen_mode(access_flags));1078	pSMB->Mode |= cpu_to_le16(0x40); /* deny none */1079	/* set file as system file if special file such as fifo,1080	 * socket, char or block and server expecting SFU style and1081	   no Unix extensions */1082 1083	if (create_options & CREATE_OPTION_SPECIAL)1084		pSMB->FileAttributes = cpu_to_le16(ATTR_SYSTEM);1085	else /* BB FIXME BB */1086		pSMB->FileAttributes = cpu_to_le16(0/*ATTR_NORMAL*/);1087 1088	if (create_options & CREATE_OPTION_READONLY)1089		pSMB->FileAttributes |= cpu_to_le16(ATTR_READONLY);1090 1091	/* BB FIXME BB */1092/*	pSMB->CreateOptions = cpu_to_le32(create_options &1093						 CREATE_OPTIONS_MASK); */1094	/* BB FIXME END BB */1095 1096	pSMB->Sattr = cpu_to_le16(ATTR_HIDDEN | ATTR_SYSTEM | ATTR_DIRECTORY);1097	pSMB->OpenFunction = cpu_to_le16(convert_disposition(openDisposition));1098	count += name_len;1099	inc_rfc1001_len(pSMB, count);1100 1101	pSMB->ByteCount = cpu_to_le16(count);1102	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,1103			(struct smb_hdr *)pSMBr, &bytes_returned, 0);1104	cifs_stats_inc(&tcon->stats.cifs_stats.num_opens);1105	if (rc) {1106		cifs_dbg(FYI, "Error in Open = %d\n", rc);1107	} else {1108	/* BB verify if wct == 15 */1109 1110/*		*pOplock = pSMBr->OplockLevel; */ /* BB take from action field*/1111 1112		*netfid = pSMBr->Fid;   /* cifs fid stays in le */1113		/* Let caller know file was created so we can set the mode. */1114		/* Do we care about the CreateAction in any other cases? */1115	/* BB FIXME BB */1116/*		if (cpu_to_le32(FILE_CREATE) == pSMBr->CreateAction)1117			*pOplock |= CIFS_CREATE_ACTION; */1118	/* BB FIXME END */1119 1120		if (pfile_info) {1121			pfile_info->CreationTime = 0; /* BB convert CreateTime*/1122			pfile_info->LastAccessTime = 0; /* BB fixme */1123			pfile_info->LastWriteTime = 0; /* BB fixme */1124			pfile_info->ChangeTime = 0;  /* BB fixme */1125			pfile_info->Attributes =1126				cpu_to_le32(le16_to_cpu(pSMBr->FileAttributes));1127			/* the file_info buf is endian converted by caller */1128			pfile_info->AllocationSize =1129				cpu_to_le64(le32_to_cpu(pSMBr->EndOfFile));1130			pfile_info->EndOfFile = pfile_info->AllocationSize;1131			pfile_info->NumberOfLinks = cpu_to_le32(1);1132			pfile_info->DeletePending = 0;1133		}1134	}1135 1136	cifs_buf_release(pSMB);1137	if (rc == -EAGAIN)1138		goto OldOpenRetry;1139	return rc;1140}1141 1142int1143CIFS_open(const unsigned int xid, struct cifs_open_parms *oparms, int *oplock,1144	  FILE_ALL_INFO *buf)1145{1146	int rc;1147	OPEN_REQ *req = NULL;1148	OPEN_RSP *rsp = NULL;1149	int bytes_returned;1150	int name_len;1151	__u16 count;1152	struct cifs_sb_info *cifs_sb = oparms->cifs_sb;1153	struct cifs_tcon *tcon = oparms->tcon;1154	int remap = cifs_remap(cifs_sb);1155	const struct nls_table *nls = cifs_sb->local_nls;1156	int create_options = oparms->create_options;1157	int desired_access = oparms->desired_access;1158	int disposition = oparms->disposition;1159	const char *path = oparms->path;1160 1161openRetry:1162	rc = smb_init(SMB_COM_NT_CREATE_ANDX, 24, tcon, (void **)&req,1163		      (void **)&rsp);1164	if (rc)1165		return rc;1166 1167	/* no commands go after this */1168	req->AndXCommand = 0xFF;1169 1170	if (req->hdr.Flags2 & SMBFLG2_UNICODE) {1171		/* account for one byte pad to word boundary */1172		count = 1;1173		name_len = cifsConvertToUTF16((__le16 *)(req->fileName + 1),1174					      path, PATH_MAX, nls, remap);1175		/* trailing null */1176		name_len++;1177		name_len *= 2;1178		req->NameLength = cpu_to_le16(name_len);1179	} else {1180		/* BB improve check for buffer overruns BB */1181		/* no pad */1182		count = 0;1183		name_len = copy_path_name(req->fileName, path);1184		req->NameLength = cpu_to_le16(name_len);1185	}1186 1187	if (*oplock & REQ_OPLOCK)1188		req->OpenFlags = cpu_to_le32(REQ_OPLOCK);1189	else if (*oplock & REQ_BATCHOPLOCK)1190		req->OpenFlags = cpu_to_le32(REQ_BATCHOPLOCK);1191 1192	req->DesiredAccess = cpu_to_le32(desired_access);1193	req->AllocationSize = 0;1194 1195	/*1196	 * Set file as system file if special file such as fifo, socket, char1197	 * or block and server expecting SFU style and no Unix extensions.1198	 */1199	if (create_options & CREATE_OPTION_SPECIAL)1200		req->FileAttributes = cpu_to_le32(ATTR_SYSTEM);1201	else1202		req->FileAttributes = cpu_to_le32(ATTR_NORMAL);1203 1204	/*1205	 * XP does not handle ATTR_POSIX_SEMANTICS but it helps speed up case1206	 * sensitive checks for other servers such as Samba.1207	 */1208	if (tcon->ses->capabilities & CAP_UNIX)1209		req->FileAttributes |= cpu_to_le32(ATTR_POSIX_SEMANTICS);1210 1211	if (create_options & CREATE_OPTION_READONLY)1212		req->FileAttributes |= cpu_to_le32(ATTR_READONLY);1213 1214	req->ShareAccess = cpu_to_le32(FILE_SHARE_ALL);1215	req->CreateDisposition = cpu_to_le32(disposition);1216	req->CreateOptions = cpu_to_le32(create_options & CREATE_OPTIONS_MASK);1217 1218	/* BB Experiment with various impersonation levels and verify */1219	req->ImpersonationLevel = cpu_to_le32(SECURITY_IMPERSONATION);1220	req->SecurityFlags = SECURITY_CONTEXT_TRACKING|SECURITY_EFFECTIVE_ONLY;1221 1222	count += name_len;1223	inc_rfc1001_len(req, count);1224 1225	req->ByteCount = cpu_to_le16(count);1226	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *)req,1227			 (struct smb_hdr *)rsp, &bytes_returned, 0);1228	cifs_stats_inc(&tcon->stats.cifs_stats.num_opens);1229	if (rc) {1230		cifs_dbg(FYI, "Error in Open = %d\n", rc);1231		cifs_buf_release(req);1232		if (rc == -EAGAIN)1233			goto openRetry;1234		return rc;1235	}1236 1237	/* 1 byte no need to le_to_cpu */1238	*oplock = rsp->OplockLevel;1239	/* cifs fid stays in le */1240	oparms->fid->netfid = rsp->Fid;1241	oparms->fid->access = desired_access;1242 1243	/* Let caller know file was created so we can set the mode. */1244	/* Do we care about the CreateAction in any other cases? */1245	if (cpu_to_le32(FILE_CREATE) == rsp->CreateAction)1246		*oplock |= CIFS_CREATE_ACTION;1247 1248	if (buf) {1249		/* copy commonly used attributes */1250		memcpy(&buf->common_attributes,1251		       &rsp->common_attributes,1252		       sizeof(buf->common_attributes));1253		/* the file_info buf is endian converted by caller */1254		buf->AllocationSize = rsp->AllocationSize;1255		buf->EndOfFile = rsp->EndOfFile;1256		buf->NumberOfLinks = cpu_to_le32(1);1257		buf->DeletePending = 0;1258	}1259 1260	cifs_buf_release(req);1261	return rc;1262}1263 1264static void cifs_readv_worker(struct work_struct *work)1265{1266	struct cifs_io_subrequest *rdata =1267		container_of(work, struct cifs_io_subrequest, subreq.work);1268 1269	netfs_read_subreq_terminated(&rdata->subreq, rdata->result, false);1270}1271 1272static void1273cifs_readv_callback(struct mid_q_entry *mid)1274{1275	struct cifs_io_subrequest *rdata = mid->callback_data;1276	struct netfs_inode *ictx = netfs_inode(rdata->rreq->inode);1277	struct cifs_tcon *tcon = tlink_tcon(rdata->req->cfile->tlink);1278	struct TCP_Server_Info *server = tcon->ses->server;1279	struct smb_rqst rqst = { .rq_iov = rdata->iov,1280				 .rq_nvec = 2,1281				 .rq_iter = rdata->subreq.io_iter };1282	struct cifs_credits credits = {1283		.value = 1,1284		.instance = 0,1285		.rreq_debug_id = rdata->rreq->debug_id,1286		.rreq_debug_index = rdata->subreq.debug_index,1287	};1288 1289	cifs_dbg(FYI, "%s: mid=%llu state=%d result=%d bytes=%zu\n",1290		 __func__, mid->mid, mid->mid_state, rdata->result,1291		 rdata->subreq.len);1292 1293	switch (mid->mid_state) {1294	case MID_RESPONSE_RECEIVED:1295		/* result already set, check signature */1296		if (server->sign) {1297			int rc = 0;1298 1299			iov_iter_truncate(&rqst.rq_iter, rdata->got_bytes);1300			rc = cifs_verify_signature(&rqst, server,1301						  mid->sequence_number);1302			if (rc)1303				cifs_dbg(VFS, "SMB signature verification returned error = %d\n",1304					 rc);1305		}1306		/* FIXME: should this be counted toward the initiating task? */1307		task_io_account_read(rdata->got_bytes);1308		cifs_stats_bytes_read(tcon, rdata->got_bytes);1309		break;1310	case MID_REQUEST_SUBMITTED:1311	case MID_RETRY_NEEDED:1312		rdata->result = -EAGAIN;1313		if (server->sign && rdata->got_bytes)1314			/* reset bytes number since we can not check a sign */1315			rdata->got_bytes = 0;1316		/* FIXME: should this be counted toward the initiating task? */1317		task_io_account_read(rdata->got_bytes);1318		cifs_stats_bytes_read(tcon, rdata->got_bytes);1319		break;1320	default:1321		rdata->result = -EIO;1322	}1323 1324	if (rdata->result == -ENODATA) {1325		__set_bit(NETFS_SREQ_HIT_EOF, &rdata->subreq.flags);1326		rdata->result = 0;1327	} else {1328		size_t trans = rdata->subreq.transferred + rdata->got_bytes;1329		if (trans < rdata->subreq.len &&1330		    rdata->subreq.start + trans == ictx->remote_i_size) {1331			__set_bit(NETFS_SREQ_HIT_EOF, &rdata->subreq.flags);1332			rdata->result = 0;1333		}1334	}1335 1336	rdata->credits.value = 0;1337	rdata->subreq.transferred += rdata->got_bytes;1338	INIT_WORK(&rdata->subreq.work, cifs_readv_worker);1339	queue_work(cifsiod_wq, &rdata->subreq.work);1340	release_mid(mid);1341	add_credits(server, &credits, 0);1342}1343 1344/* cifs_async_readv - send an async write, and set up mid to handle result */1345int1346cifs_async_readv(struct cifs_io_subrequest *rdata)1347{1348	int rc;1349	READ_REQ *smb = NULL;1350	int wct;1351	struct cifs_tcon *tcon = tlink_tcon(rdata->req->cfile->tlink);1352	struct smb_rqst rqst = { .rq_iov = rdata->iov,1353				 .rq_nvec = 2 };1354 1355	cifs_dbg(FYI, "%s: offset=%llu bytes=%zu\n",1356		 __func__, rdata->subreq.start, rdata->subreq.len);1357 1358	if (tcon->ses->capabilities & CAP_LARGE_FILES)1359		wct = 12;1360	else {1361		wct = 10; /* old style read */1362		if ((rdata->subreq.start >> 32) > 0)  {1363			/* can not handle this big offset for old */1364			return -EIO;1365		}1366	}1367 1368	rc = small_smb_init(SMB_COM_READ_ANDX, wct, tcon, (void **)&smb);1369	if (rc)1370		return rc;1371 1372	smb->hdr.Pid = cpu_to_le16((__u16)rdata->req->pid);1373	smb->hdr.PidHigh = cpu_to_le16((__u16)(rdata->req->pid >> 16));1374 1375	smb->AndXCommand = 0xFF;	/* none */1376	smb->Fid = rdata->req->cfile->fid.netfid;1377	smb->OffsetLow = cpu_to_le32(rdata->subreq.start & 0xFFFFFFFF);1378	if (wct == 12)1379		smb->OffsetHigh = cpu_to_le32(rdata->subreq.start >> 32);1380	smb->Remaining = 0;1381	smb->MaxCount = cpu_to_le16(rdata->subreq.len & 0xFFFF);1382	smb->MaxCountHigh = cpu_to_le32(rdata->subreq.len >> 16);1383	if (wct == 12)1384		smb->ByteCount = 0;1385	else {1386		/* old style read */1387		struct smb_com_readx_req *smbr =1388			(struct smb_com_readx_req *)smb;1389		smbr->ByteCount = 0;1390	}1391 1392	/* 4 for RFC1001 length + 1 for BCC */1393	rdata->iov[0].iov_base = smb;1394	rdata->iov[0].iov_len = 4;1395	rdata->iov[1].iov_base = (char *)smb + 4;1396	rdata->iov[1].iov_len = get_rfc1002_length(smb);1397 1398	rc = cifs_call_async(tcon->ses->server, &rqst, cifs_readv_receive,1399			     cifs_readv_callback, NULL, rdata, 0, NULL);1400 1401	if (rc == 0)1402		cifs_stats_inc(&tcon->stats.cifs_stats.num_reads);1403	cifs_small_buf_release(smb);1404	return rc;1405}1406 1407int1408CIFSSMBRead(const unsigned int xid, struct cifs_io_parms *io_parms,1409	    unsigned int *nbytes, char **buf, int *pbuf_type)1410{1411	int rc = -EACCES;1412	READ_REQ *pSMB = NULL;1413	READ_RSP *pSMBr = NULL;1414	char *pReadData = NULL;1415	int wct;1416	int resp_buf_type = 0;1417	struct kvec iov[1];1418	struct kvec rsp_iov;1419	__u32 pid = io_parms->pid;1420	__u16 netfid = io_parms->netfid;1421	__u64 offset = io_parms->offset;1422	struct cifs_tcon *tcon = io_parms->tcon;1423	unsigned int count = io_parms->length;1424 1425	cifs_dbg(FYI, "Reading %d bytes on fid %d\n", count, netfid);1426	if (tcon->ses->capabilities & CAP_LARGE_FILES)1427		wct = 12;1428	else {1429		wct = 10; /* old style read */1430		if ((offset >> 32) > 0)  {1431			/* can not handle this big offset for old */1432			return -EIO;1433		}1434	}1435 1436	*nbytes = 0;1437	rc = small_smb_init(SMB_COM_READ_ANDX, wct, tcon, (void **) &pSMB);1438	if (rc)1439		return rc;1440 1441	pSMB->hdr.Pid = cpu_to_le16((__u16)pid);1442	pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid >> 16));1443 1444	/* tcon and ses pointer are checked in smb_init */1445	if (tcon->ses->server == NULL)1446		return -ECONNABORTED;1447 1448	pSMB->AndXCommand = 0xFF;       /* none */1449	pSMB->Fid = netfid;1450	pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF);1451	if (wct == 12)1452		pSMB->OffsetHigh = cpu_to_le32(offset >> 32);1453 1454	pSMB->Remaining = 0;1455	pSMB->MaxCount = cpu_to_le16(count & 0xFFFF);1456	pSMB->MaxCountHigh = cpu_to_le32(count >> 16);1457	if (wct == 12)1458		pSMB->ByteCount = 0;  /* no need to do le conversion since 0 */1459	else {1460		/* old style read */1461		struct smb_com_readx_req *pSMBW =1462			(struct smb_com_readx_req *)pSMB;1463		pSMBW->ByteCount = 0;1464	}1465 1466	iov[0].iov_base = (char *)pSMB;1467	iov[0].iov_len = be32_to_cpu(pSMB->hdr.smb_buf_length) + 4;1468	rc = SendReceive2(xid, tcon->ses, iov, 1, &resp_buf_type,1469			  CIFS_LOG_ERROR, &rsp_iov);1470	cifs_small_buf_release(pSMB);1471	cifs_stats_inc(&tcon->stats.cifs_stats.num_reads);1472	pSMBr = (READ_RSP *)rsp_iov.iov_base;1473	if (rc) {1474		cifs_dbg(VFS, "Send error in read = %d\n", rc);1475	} else {1476		int data_length = le16_to_cpu(pSMBr->DataLengthHigh);1477		data_length = data_length << 16;1478		data_length += le16_to_cpu(pSMBr->DataLength);1479		*nbytes = data_length;1480 1481		/*check that DataLength would not go beyond end of SMB */1482		if ((data_length > CIFSMaxBufSize)1483				|| (data_length > count)) {1484			cifs_dbg(FYI, "bad length %d for count %d\n",1485				 data_length, count);1486			rc = -EIO;1487			*nbytes = 0;1488		} else {1489			pReadData = (char *) (&pSMBr->hdr.Protocol) +1490					le16_to_cpu(pSMBr->DataOffset);1491/*			if (rc = copy_to_user(buf, pReadData, data_length)) {1492				cifs_dbg(VFS, "Faulting on read rc = %d\n",rc);1493				rc = -EFAULT;1494			}*/ /* can not use copy_to_user when using page cache*/1495			if (*buf)1496				memcpy(*buf, pReadData, data_length);1497		}1498	}1499 1500	if (*buf) {1501		free_rsp_buf(resp_buf_type, rsp_iov.iov_base);1502	} else if (resp_buf_type != CIFS_NO_BUFFER) {1503		/* return buffer to caller to free */1504		*buf = rsp_iov.iov_base;1505		if (resp_buf_type == CIFS_SMALL_BUFFER)1506			*pbuf_type = CIFS_SMALL_BUFFER;1507		else if (resp_buf_type == CIFS_LARGE_BUFFER)1508			*pbuf_type = CIFS_LARGE_BUFFER;1509	} /* else no valid buffer on return - leave as null */1510 1511	/* Note: On -EAGAIN error only caller can retry on handle based calls1512		since file handle passed in no longer valid */1513	return rc;1514}1515 1516 1517int1518CIFSSMBWrite(const unsigned int xid, struct cifs_io_parms *io_parms,1519	     unsigned int *nbytes, const char *buf)1520{1521	int rc = -EACCES;1522	WRITE_REQ *pSMB = NULL;1523	WRITE_RSP *pSMBr = NULL;1524	int bytes_returned, wct;1525	__u32 bytes_sent;1526	__u16 byte_count;1527	__u32 pid = io_parms->pid;1528	__u16 netfid = io_parms->netfid;1529	__u64 offset = io_parms->offset;1530	struct cifs_tcon *tcon = io_parms->tcon;1531	unsigned int count = io_parms->length;1532 1533	*nbytes = 0;1534 1535	/* cifs_dbg(FYI, "write at %lld %d bytes\n", offset, count);*/1536	if (tcon->ses == NULL)1537		return -ECONNABORTED;1538 1539	if (tcon->ses->capabilities & CAP_LARGE_FILES)1540		wct = 14;1541	else {1542		wct = 12;1543		if ((offset >> 32) > 0) {1544			/* can not handle big offset for old srv */1545			return -EIO;1546		}1547	}1548 1549	rc = smb_init(SMB_COM_WRITE_ANDX, wct, tcon, (void **) &pSMB,1550		      (void **) &pSMBr);1551	if (rc)1552		return rc;1553 1554	pSMB->hdr.Pid = cpu_to_le16((__u16)pid);1555	pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid >> 16));1556 1557	/* tcon and ses pointer are checked in smb_init */1558	if (tcon->ses->server == NULL)1559		return -ECONNABORTED;1560 1561	pSMB->AndXCommand = 0xFF;	/* none */1562	pSMB->Fid = netfid;1563	pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF);1564	if (wct == 14)1565		pSMB->OffsetHigh = cpu_to_le32(offset >> 32);1566 1567	pSMB->Reserved = 0xFFFFFFFF;1568	pSMB->WriteMode = 0;1569	pSMB->Remaining = 0;1570 1571	/* Can increase buffer size if buffer is big enough in some cases ie we1572	can send more if LARGE_WRITE_X capability returned by the server and if1573	our buffer is big enough or if we convert to iovecs on socket writes1574	and eliminate the copy to the CIFS buffer */1575	if (tcon->ses->capabilities & CAP_LARGE_WRITE_X) {1576		bytes_sent = min_t(const unsigned int, CIFSMaxBufSize, count);1577	} else {1578		bytes_sent = (tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE)1579			 & ~0xFF;1580	}1581 1582	if (bytes_sent > count)1583		bytes_sent = count;1584	pSMB->DataOffset =1585		cpu_to_le16(offsetof(struct smb_com_write_req, Data) - 4);1586	if (buf)1587		memcpy(pSMB->Data, buf, bytes_sent);1588	else if (count != 0) {1589		/* No buffer */1590		cifs_buf_release(pSMB);1591		return -EINVAL;1592	} /* else setting file size with write of zero bytes */1593	if (wct == 14)1594		byte_count = bytes_sent + 1; /* pad */1595	else /* wct == 12 */1596		byte_count = bytes_sent + 5; /* bigger pad, smaller smb hdr */1597 1598	pSMB->DataLengthLow = cpu_to_le16(bytes_sent & 0xFFFF);1599	pSMB->DataLengthHigh = cpu_to_le16(bytes_sent >> 16);1600	inc_rfc1001_len(pSMB, byte_count);1601 1602	if (wct == 14)1603		pSMB->ByteCount = cpu_to_le16(byte_count);1604	else { /* old style write has byte count 4 bytes earlier1605		  so 4 bytes pad  */1606		struct smb_com_writex_req *pSMBW =1607			(struct smb_com_writex_req *)pSMB;1608		pSMBW->ByteCount = cpu_to_le16(byte_count);1609	}1610 1611	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,1612			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);1613	cifs_stats_inc(&tcon->stats.cifs_stats.num_writes);1614	if (rc) {1615		cifs_dbg(FYI, "Send error in write = %d\n", rc);1616	} else {1617		*nbytes = le16_to_cpu(pSMBr->CountHigh);1618		*nbytes = (*nbytes) << 16;1619		*nbytes += le16_to_cpu(pSMBr->Count);1620 1621		/*1622		 * Mask off high 16 bits when bytes written as returned by the1623		 * server is greater than bytes requested by the client. Some1624		 * OS/2 servers are known to set incorrect CountHigh values.1625		 */1626		if (*nbytes > count)1627			*nbytes &= 0xFFFF;1628	}1629 1630	cifs_buf_release(pSMB);1631 1632	/* Note: On -EAGAIN error only caller can retry on handle based calls1633		since file handle passed in no longer valid */1634 1635	return rc;1636}1637 1638/*1639 * Check the mid_state and signature on received buffer (if any), and queue the1640 * workqueue completion task.1641 */1642static void1643cifs_writev_callback(struct mid_q_entry *mid)1644{1645	struct cifs_io_subrequest *wdata = mid->callback_data;1646	struct TCP_Server_Info *server = wdata->server;1647	struct cifs_tcon *tcon = tlink_tcon(wdata->req->cfile->tlink);1648	WRITE_RSP *smb = (WRITE_RSP *)mid->resp_buf;1649	struct cifs_credits credits = {1650		.value = 1,1651		.instance = 0,1652		.rreq_debug_id = wdata->rreq->debug_id,1653		.rreq_debug_index = wdata->subreq.debug_index,1654	};1655	ssize_t result;1656	size_t written;1657 1658	switch (mid->mid_state) {1659	case MID_RESPONSE_RECEIVED:1660		result = cifs_check_receive(mid, tcon->ses->server, 0);1661		if (result != 0)1662			break;1663 1664		written = le16_to_cpu(smb->CountHigh);1665		written <<= 16;1666		written += le16_to_cpu(smb->Count);1667		/*1668		 * Mask off high 16 bits when bytes written as returned1669		 * by the server is greater than bytes requested by the1670		 * client. OS/2 servers are known to set incorrect1671		 * CountHigh values.1672		 */1673		if (written > wdata->subreq.len)1674			written &= 0xFFFF;1675 1676		if (written < wdata->subreq.len)1677			result = -ENOSPC;1678		else1679			result = written;1680		break;1681	case MID_REQUEST_SUBMITTED:1682	case MID_RETRY_NEEDED:1683		result = -EAGAIN;1684		break;1685	default:1686		result = -EIO;1687		break;1688	}1689 1690	trace_smb3_rw_credits(credits.rreq_debug_id, credits.rreq_debug_index,1691			      wdata->credits.value,1692			      server->credits, server->in_flight,1693			      0, cifs_trace_rw_credits_write_response_clear);1694	wdata->credits.value = 0;1695	cifs_write_subrequest_terminated(wdata, result, true);1696	release_mid(mid);1697	trace_smb3_rw_credits(credits.rreq_debug_id, credits.rreq_debug_index, 0,1698			      server->credits, server->in_flight,1699			      credits.value, cifs_trace_rw_credits_write_response_add);1700	add_credits(tcon->ses->server, &credits, 0);1701}1702 1703/* cifs_async_writev - send an async write, and set up mid to handle result */1704void1705cifs_async_writev(struct cifs_io_subrequest *wdata)1706{1707	int rc = -EACCES;1708	WRITE_REQ *smb = NULL;1709	int wct;1710	struct cifs_tcon *tcon = tlink_tcon(wdata->req->cfile->tlink);1711	struct kvec iov[2];1712	struct smb_rqst rqst = { };1713 1714	if (tcon->ses->capabilities & CAP_LARGE_FILES) {1715		wct = 14;1716	} else {1717		wct = 12;1718		if (wdata->subreq.start >> 32 > 0) {1719			/* can not handle big offset for old srv */1720			rc = -EIO;1721			goto out;1722		}1723	}1724 1725	rc = small_smb_init(SMB_COM_WRITE_ANDX, wct, tcon, (void **)&smb);1726	if (rc)1727		goto async_writev_out;1728 1729	smb->hdr.Pid = cpu_to_le16((__u16)wdata->req->pid);1730	smb->hdr.PidHigh = cpu_to_le16((__u16)(wdata->req->pid >> 16));1731 1732	smb->AndXCommand = 0xFF;	/* none */1733	smb->Fid = wdata->req->cfile->fid.netfid;1734	smb->OffsetLow = cpu_to_le32(wdata->subreq.start & 0xFFFFFFFF);1735	if (wct == 14)1736		smb->OffsetHigh = cpu_to_le32(wdata->subreq.start >> 32);1737	smb->Reserved = 0xFFFFFFFF;1738	smb->WriteMode = 0;1739	smb->Remaining = 0;1740 1741	smb->DataOffset =1742	    cpu_to_le16(offsetof(struct smb_com_write_req, Data) - 4);1743 1744	/* 4 for RFC1001 length + 1 for BCC */1745	iov[0].iov_len = 4;1746	iov[0].iov_base = smb;1747	iov[1].iov_len = get_rfc1002_length(smb) + 1;1748	iov[1].iov_base = (char *)smb + 4;1749 1750	rqst.rq_iov = iov;1751	rqst.rq_nvec = 2;1752	rqst.rq_iter = wdata->subreq.io_iter;1753 1754	cifs_dbg(FYI, "async write at %llu %zu bytes\n",1755		 wdata->subreq.start, wdata->subreq.len);1756 1757	smb->DataLengthLow = cpu_to_le16(wdata->subreq.len & 0xFFFF);1758	smb->DataLengthHigh = cpu_to_le16(wdata->subreq.len >> 16);1759 1760	if (wct == 14) {1761		inc_rfc1001_len(&smb->hdr, wdata->subreq.len + 1);1762		put_bcc(wdata->subreq.len + 1, &smb->hdr);1763	} else {1764		/* wct == 12 */1765		struct smb_com_writex_req *smbw =1766				(struct smb_com_writex_req *)smb;1767		inc_rfc1001_len(&smbw->hdr, wdata->subreq.len + 5);1768		put_bcc(wdata->subreq.len + 5, &smbw->hdr);1769		iov[1].iov_len += 4; /* pad bigger by four bytes */1770	}1771 1772	rc = cifs_call_async(tcon->ses->server, &rqst, NULL,1773			     cifs_writev_callback, NULL, wdata, 0, NULL);1774	/* Can't touch wdata if rc == 0 */1775	if (rc == 0)1776		cifs_stats_inc(&tcon->stats.cifs_stats.num_writes);1777 1778async_writev_out:1779	cifs_small_buf_release(smb);1780out:1781	if (rc) {1782		add_credits_and_wake_if(wdata->server, &wdata->credits, 0);1783		cifs_write_subrequest_terminated(wdata, rc, false);1784	}1785}1786 1787int1788CIFSSMBWrite2(const unsigned int xid, struct cifs_io_parms *io_parms,1789	      unsigned int *nbytes, struct kvec *iov, int n_vec)1790{1791	int rc;1792	WRITE_REQ *pSMB = NULL;1793	int wct;1794	int smb_hdr_len;1795	int resp_buf_type = 0;1796	__u32 pid = io_parms->pid;1797	__u16 netfid = io_parms->netfid;1798	__u64 offset = io_parms->offset;1799	struct cifs_tcon *tcon = io_parms->tcon;1800	unsigned int count = io_parms->length;1801	struct kvec rsp_iov;1802 1803	*nbytes = 0;1804 1805	cifs_dbg(FYI, "write2 at %lld %d bytes\n", (long long)offset, count);1806 1807	if (tcon->ses->capabilities & CAP_LARGE_FILES) {1808		wct = 14;1809	} else {1810		wct = 12;1811		if ((offset >> 32) > 0) {1812			/* can not handle big offset for old srv */1813			return -EIO;1814		}1815	}1816	rc = small_smb_init(SMB_COM_WRITE_ANDX, wct, tcon, (void **) &pSMB);1817	if (rc)1818		return rc;1819 1820	pSMB->hdr.Pid = cpu_to_le16((__u16)pid);1821	pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid >> 16));1822 1823	/* tcon and ses pointer are checked in smb_init */1824	if (tcon->ses->server == NULL)1825		return -ECONNABORTED;1826 1827	pSMB->AndXCommand = 0xFF;	/* none */1828	pSMB->Fid = netfid;1829	pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF);1830	if (wct == 14)1831		pSMB->OffsetHigh = cpu_to_le32(offset >> 32);1832	pSMB->Reserved = 0xFFFFFFFF;1833	pSMB->WriteMode = 0;1834	pSMB->Remaining = 0;1835 1836	pSMB->DataOffset =1837	    cpu_to_le16(offsetof(struct smb_com_write_req, Data) - 4);1838 1839	pSMB->DataLengthLow = cpu_to_le16(count & 0xFFFF);1840	pSMB->DataLengthHigh = cpu_to_le16(count >> 16);1841	/* header + 1 byte pad */1842	smb_hdr_len = be32_to_cpu(pSMB->hdr.smb_buf_length) + 1;1843	if (wct == 14)1844		inc_rfc1001_len(pSMB, count + 1);1845	else /* wct == 12 */1846		inc_rfc1001_len(pSMB, count + 5); /* smb data starts later */1847	if (wct == 14)1848		pSMB->ByteCount = cpu_to_le16(count + 1);1849	else /* wct == 12 */ /* bigger pad, smaller smb hdr, keep offset ok */ {1850		struct smb_com_writex_req *pSMBW =1851				(struct smb_com_writex_req *)pSMB;1852		pSMBW->ByteCount = cpu_to_le16(count + 5);1853	}1854	iov[0].iov_base = pSMB;1855	if (wct == 14)1856		iov[0].iov_len = smb_hdr_len + 4;1857	else /* wct == 12 pad bigger by four bytes */1858		iov[0].iov_len = smb_hdr_len + 8;1859 1860	rc = SendReceive2(xid, tcon->ses, iov, n_vec + 1, &resp_buf_type, 0,1861			  &rsp_iov);1862	cifs_small_buf_release(pSMB);1863	cifs_stats_inc(&tcon->stats.cifs_stats.num_writes);1864	if (rc) {1865		cifs_dbg(FYI, "Send error Write2 = %d\n", rc);1866	} else if (resp_buf_type == 0) {1867		/* presumably this can not happen, but best to be safe */1868		rc = -EIO;1869	} else {1870		WRITE_RSP *pSMBr = (WRITE_RSP *)rsp_iov.iov_base;1871		*nbytes = le16_to_cpu(pSMBr->CountHigh);1872		*nbytes = (*nbytes) << 16;1873		*nbytes += le16_to_cpu(pSMBr->Count);1874 1875		/*1876		 * Mask off high 16 bits when bytes written as returned by the1877		 * server is greater than bytes requested by the client. OS/21878		 * servers are known to set incorrect CountHigh values.1879		 */1880		if (*nbytes > count)1881			*nbytes &= 0xFFFF;1882	}1883 1884	free_rsp_buf(resp_buf_type, rsp_iov.iov_base);1885 1886	/* Note: On -EAGAIN error only caller can retry on handle based calls1887		since file handle passed in no longer valid */1888 1889	return rc;1890}1891 1892int cifs_lockv(const unsigned int xid, struct cifs_tcon *tcon,1893	       const __u16 netfid, const __u8 lock_type, const __u32 num_unlock,1894	       const __u32 num_lock, LOCKING_ANDX_RANGE *buf)1895{1896	int rc = 0;1897	LOCK_REQ *pSMB = NULL;1898	struct kvec iov[2];1899	struct kvec rsp_iov;1900	int resp_buf_type;1901	__u16 count;1902 1903	cifs_dbg(FYI, "cifs_lockv num lock %d num unlock %d\n",1904		 num_lock, num_unlock);1905 1906	rc = small_smb_init(SMB_COM_LOCKING_ANDX, 8, tcon, (void **) &pSMB);1907	if (rc)1908		return rc;1909 1910	pSMB->Timeout = 0;1911	pSMB->NumberOfLocks = cpu_to_le16(num_lock);1912	pSMB->NumberOfUnlocks = cpu_to_le16(num_unlock);1913	pSMB->LockType = lock_type;1914	pSMB->AndXCommand = 0xFF; /* none */1915	pSMB->Fid = netfid; /* netfid stays le */1916 1917	count = (num_unlock + num_lock) * sizeof(LOCKING_ANDX_RANGE);1918	inc_rfc1001_len(pSMB, count);1919	pSMB->ByteCount = cpu_to_le16(count);1920 1921	iov[0].iov_base = (char *)pSMB;1922	iov[0].iov_len = be32_to_cpu(pSMB->hdr.smb_buf_length) + 4 -1923			 (num_unlock + num_lock) * sizeof(LOCKING_ANDX_RANGE);1924	iov[1].iov_base = (char *)buf;1925	iov[1].iov_len = (num_unlock + num_lock) * sizeof(LOCKING_ANDX_RANGE);1926 1927	cifs_stats_inc(&tcon->stats.cifs_stats.num_locks);1928	rc = SendReceive2(xid, tcon->ses, iov, 2, &resp_buf_type,1929			  CIFS_NO_RSP_BUF, &rsp_iov);1930	cifs_small_buf_release(pSMB);1931	if (rc)1932		cifs_dbg(FYI, "Send error in cifs_lockv = %d\n", rc);1933 1934	return rc;1935}1936 1937int1938CIFSSMBLock(const unsigned int xid, struct cifs_tcon *tcon,1939	    const __u16 smb_file_id, const __u32 netpid, const __u64 len,1940	    const __u64 offset, const __u32 numUnlock,1941	    const __u32 numLock, const __u8 lockType,1942	    const bool waitFlag, const __u8 oplock_level)1943{1944	int rc = 0;1945	LOCK_REQ *pSMB = NULL;1946/*	LOCK_RSP *pSMBr = NULL; */ /* No response data other than rc to parse */1947	int bytes_returned;1948	int flags = 0;1949	__u16 count;1950 1951	cifs_dbg(FYI, "CIFSSMBLock timeout %d numLock %d\n",1952		 (int)waitFlag, numLock);1953	rc = small_smb_init(SMB_COM_LOCKING_ANDX, 8, tcon, (void **) &pSMB);1954 1955	if (rc)1956		return rc;1957 1958	if (lockType == LOCKING_ANDX_OPLOCK_RELEASE) {1959		/* no response expected */1960		flags = CIFS_NO_SRV_RSP | CIFS_NON_BLOCKING | CIFS_OBREAK_OP;1961		pSMB->Timeout = 0;1962	} else if (waitFlag) {1963		flags = CIFS_BLOCKING_OP; /* blocking operation, no timeout */1964		pSMB->Timeout = cpu_to_le32(-1);/* blocking - do not time out */1965	} else {1966		pSMB->Timeout = 0;1967	}1968 1969	pSMB->NumberOfLocks = cpu_to_le16(numLock);1970	pSMB->NumberOfUnlocks = cpu_to_le16(numUnlock);1971	pSMB->LockType = lockType;1972	pSMB->OplockLevel = oplock_level;1973	pSMB->AndXCommand = 0xFF;	/* none */1974	pSMB->Fid = smb_file_id; /* netfid stays le */1975 1976	if ((numLock != 0) || (numUnlock != 0)) {1977		pSMB->Locks[0].Pid = cpu_to_le16(netpid);1978		/* BB where to store pid high? */1979		pSMB->Locks[0].LengthLow = cpu_to_le32((u32)len);1980		pSMB->Locks[0].LengthHigh = cpu_to_le32((u32)(len>>32));1981		pSMB->Locks[0].OffsetLow = cpu_to_le32((u32)offset);1982		pSMB->Locks[0].OffsetHigh = cpu_to_le32((u32)(offset>>32));1983		count = sizeof(LOCKING_ANDX_RANGE);1984	} else {1985		/* oplock break */1986		count = 0;1987	}1988	inc_rfc1001_len(pSMB, count);1989	pSMB->ByteCount = cpu_to_le16(count);1990 1991	if (waitFlag)1992		rc = SendReceiveBlockingLock(xid, tcon, (struct smb_hdr *) pSMB,1993			(struct smb_hdr *) pSMB, &bytes_returned);1994	else1995		rc = SendReceiveNoRsp(xid, tcon->ses, (char *)pSMB, flags);1996	cifs_small_buf_release(pSMB);1997	cifs_stats_inc(&tcon->stats.cifs_stats.num_locks);1998	if (rc)1999		cifs_dbg(FYI, "Send error in Lock = %d\n", rc);2000 2001	/* Note: On -EAGAIN error only caller can retry on handle based calls2002	since file handle passed in no longer valid */2003	return rc;2004}2005 2006int2007CIFSSMBPosixLock(const unsigned int xid, struct cifs_tcon *tcon,2008		const __u16 smb_file_id, const __u32 netpid,2009		const loff_t start_offset, const __u64 len,2010		struct file_lock *pLockData, const __u16 lock_type,2011		const bool waitFlag)2012{2013	struct smb_com_transaction2_sfi_req *pSMB  = NULL;2014	struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;2015	struct cifs_posix_lock *parm_data;2016	int rc = 0;2017	int timeout = 0;2018	int bytes_returned = 0;2019	int resp_buf_type = 0;2020	__u16 params, param_offset, offset, byte_count, count;2021	struct kvec iov[1];2022	struct kvec rsp_iov;2023 2024	cifs_dbg(FYI, "Posix Lock\n");2025 2026	rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);2027 2028	if (rc)2029		return rc;2030 2031	pSMBr = (struct smb_com_transaction2_sfi_rsp *)pSMB;2032 2033	params = 6;2034	pSMB->MaxSetupCount = 0;2035	pSMB->Reserved = 0;2036	pSMB->Flags = 0;2037	pSMB->Reserved2 = 0;2038	param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;2039	offset = param_offset + params;2040 2041	count = sizeof(struct cifs_posix_lock);2042	pSMB->MaxParameterCount = cpu_to_le16(2);2043	pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB from sess */2044	pSMB->SetupCount = 1;2045	pSMB->Reserved3 = 0;2046	if (pLockData)2047		pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION);2048	else2049		pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);2050	byte_count = 3 /* pad */  + params + count;2051	pSMB->DataCount = cpu_to_le16(count);2052	pSMB->ParameterCount = cpu_to_le16(params);2053	pSMB->TotalDataCount = pSMB->DataCount;2054	pSMB->TotalParameterCount = pSMB->ParameterCount;2055	pSMB->ParameterOffset = cpu_to_le16(param_offset);2056	/* SMB offsets are from the beginning of SMB which is 4 bytes in, after RFC1001 field */2057	parm_data = (struct cifs_posix_lock *)2058			(((char *)pSMB) + offset + 4);2059 2060	parm_data->lock_type = cpu_to_le16(lock_type);2061	if (waitFlag) {2062		timeout = CIFS_BLOCKING_OP; /* blocking operation, no timeout */2063		parm_data->lock_flags = cpu_to_le16(1);2064		pSMB->Timeout = cpu_to_le32(-1);2065	} else2066		pSMB->Timeout = 0;2067 2068	parm_data->pid = cpu_to_le32(netpid);2069	parm_data->start = cpu_to_le64(start_offset);2070	parm_data->length = cpu_to_le64(len);  /* normalize negative numbers */2071 2072	pSMB->DataOffset = cpu_to_le16(offset);2073	pSMB->Fid = smb_file_id;2074	pSMB->InformationLevel = cpu_to_le16(SMB_SET_POSIX_LOCK);2075	pSMB->Reserved4 = 0;2076	inc_rfc1001_len(pSMB, byte_count);2077	pSMB->ByteCount = cpu_to_le16(byte_count);2078	if (waitFlag) {2079		rc = SendReceiveBlockingLock(xid, tcon, (struct smb_hdr *) pSMB,2080			(struct smb_hdr *) pSMBr, &bytes_returned);2081	} else {2082		iov[0].iov_base = (char *)pSMB;2083		iov[0].iov_len = be32_to_cpu(pSMB->hdr.smb_buf_length) + 4;2084		rc = SendReceive2(xid, tcon->ses, iov, 1 /* num iovecs */,2085				&resp_buf_type, timeout, &rsp_iov);2086		pSMBr = (struct smb_com_transaction2_sfi_rsp *)rsp_iov.iov_base;2087	}2088	cifs_small_buf_release(pSMB);2089 2090	if (rc) {2091		cifs_dbg(FYI, "Send error in Posix Lock = %d\n", rc);2092	} else if (pLockData) {2093		/* lock structure can be returned on get */2094		__u16 data_offset;2095		__u16 data_count;2096		rc = validate_t2((struct smb_t2_rsp *)pSMBr);2097 2098		if (rc || get_bcc(&pSMBr->hdr) < sizeof(*parm_data)) {2099			rc = -EIO;      /* bad smb */2100			goto plk_err_exit;2101		}2102		data_offset = le16_to_cpu(pSMBr->t2.DataOffset);2103		data_count  = le16_to_cpu(pSMBr->t2.DataCount);2104		if (data_count < sizeof(struct cifs_posix_lock)) {2105			rc = -EIO;2106			goto plk_err_exit;2107		}2108		parm_data = (struct cifs_posix_lock *)2109			((char *)&pSMBr->hdr.Protocol + data_offset);2110		if (parm_data->lock_type == cpu_to_le16(CIFS_UNLCK))2111			pLockData->c.flc_type = F_UNLCK;2112		else {2113			if (parm_data->lock_type ==2114					cpu_to_le16(CIFS_RDLCK))2115				pLockData->c.flc_type = F_RDLCK;2116			else if (parm_data->lock_type ==2117					cpu_to_le16(CIFS_WRLCK))2118				pLockData->c.flc_type = F_WRLCK;2119 2120			pLockData->fl_start = le64_to_cpu(parm_data->start);2121			pLockData->fl_end = pLockData->fl_start +2122				(le64_to_cpu(parm_data->length) ?2123				 le64_to_cpu(parm_data->length) - 1 : 0);2124			pLockData->c.flc_pid = -le32_to_cpu(parm_data->pid);2125		}2126	}2127 2128plk_err_exit:2129	free_rsp_buf(resp_buf_type, rsp_iov.iov_base);2130 2131	/* Note: On -EAGAIN error only caller can retry on handle based calls2132	   since file handle passed in no longer valid */2133 2134	return rc;2135}2136 2137 2138int2139CIFSSMBClose(const unsigned int xid, struct cifs_tcon *tcon, int smb_file_id)2140{2141	int rc = 0;2142	CLOSE_REQ *pSMB = NULL;2143	cifs_dbg(FYI, "In CIFSSMBClose\n");2144 2145/* do not retry on dead session on close */2146	rc = small_smb_init(SMB_COM_CLOSE, 3, tcon, (void **) &pSMB);2147	if (rc == -EAGAIN)2148		return 0;2149	if (rc)2150		return rc;2151 2152	pSMB->FileID = (__u16) smb_file_id;2153	pSMB->LastWriteTime = 0xFFFFFFFF;2154	pSMB->ByteCount = 0;2155	rc = SendReceiveNoRsp(xid, tcon->ses, (char *) pSMB, 0);2156	cifs_small_buf_release(pSMB);2157	cifs_stats_inc(&tcon->stats.cifs_stats.num_closes);2158	if (rc) {2159		if (rc != -EINTR) {2160			/* EINTR is expected when user ctl-c to kill app */2161			cifs_dbg(VFS, "Send error in Close = %d\n", rc);2162		}2163	}2164 2165	/* Since session is dead, file will be closed on server already */2166	if (rc == -EAGAIN)2167		rc = 0;2168 2169	return rc;2170}2171 2172int2173CIFSSMBFlush(const unsigned int xid, struct cifs_tcon *tcon, int smb_file_id)2174{2175	int rc = 0;2176	FLUSH_REQ *pSMB = NULL;2177	cifs_dbg(FYI, "In CIFSSMBFlush\n");2178 2179	rc = small_smb_init(SMB_COM_FLUSH, 1, tcon, (void **) &pSMB);2180	if (rc)2181		return rc;2182 2183	pSMB->FileID = (__u16) smb_file_id;2184	pSMB->ByteCount = 0;2185	rc = SendReceiveNoRsp(xid, tcon->ses, (char *) pSMB, 0);2186	cifs_small_buf_release(pSMB);2187	cifs_stats_inc(&tcon->stats.cifs_stats.num_flushes);2188	if (rc)2189		cifs_dbg(VFS, "Send error in Flush = %d\n", rc);2190 2191	return rc;2192}2193 2194int CIFSSMBRename(const unsigned int xid, struct cifs_tcon *tcon,2195		  struct dentry *source_dentry,2196		  const char *from_name, const char *to_name,2197		  struct cifs_sb_info *cifs_sb)2198{2199	int rc = 0;2200	RENAME_REQ *pSMB = NULL;2201	RENAME_RSP *pSMBr = NULL;2202	int bytes_returned;2203	int name_len, name_len2;2204	__u16 count;2205	int remap = cifs_remap(cifs_sb);2206 2207	cifs_dbg(FYI, "In CIFSSMBRename\n");2208renameRetry:2209	rc = smb_init(SMB_COM_RENAME, 1, tcon, (void **) &pSMB,2210		      (void **) &pSMBr);2211	if (rc)2212		return rc;2213 2214	pSMB->BufferFormat = 0x04;2215	pSMB->SearchAttributes =2216	    cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |2217			ATTR_DIRECTORY);2218 2219	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {2220		name_len = cifsConvertToUTF16((__le16 *) pSMB->OldFileName,2221					      from_name, PATH_MAX,2222					      cifs_sb->local_nls, remap);2223		name_len++;	/* trailing null */2224		name_len *= 2;2225		pSMB->OldFileName[name_len] = 0x04;	/* pad */2226	/* protocol requires ASCII signature byte on Unicode string */2227		pSMB->OldFileName[name_len + 1] = 0x00;2228		name_len2 =2229		    cifsConvertToUTF16((__le16 *)&pSMB->OldFileName[name_len+2],2230				       to_name, PATH_MAX, cifs_sb->local_nls,2231				       remap);2232		name_len2 += 1 /* trailing null */  + 1 /* Signature word */ ;2233		name_len2 *= 2;	/* convert to bytes */2234	} else {2235		name_len = copy_path_name(pSMB->OldFileName, from_name);2236		name_len2 = copy_path_name(pSMB->OldFileName+name_len+1, to_name);2237		pSMB->OldFileName[name_len] = 0x04;  /* 2nd buffer format */2238		name_len2++;	/* signature byte */2239	}2240 2241	count = 1 /* 1st signature byte */  + name_len + name_len2;2242	inc_rfc1001_len(pSMB, count);2243	pSMB->ByteCount = cpu_to_le16(count);2244 2245	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,2246			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);2247	cifs_stats_inc(&tcon->stats.cifs_stats.num_renames);2248	if (rc)2249		cifs_dbg(FYI, "Send error in rename = %d\n", rc);2250 2251	cifs_buf_release(pSMB);2252 2253	if (rc == -EAGAIN)2254		goto renameRetry;2255 2256	return rc;2257}2258 2259int CIFSSMBRenameOpenFile(const unsigned int xid, struct cifs_tcon *pTcon,2260		int netfid, const char *target_name,2261		const struct nls_table *nls_codepage, int remap)2262{2263	struct smb_com_transaction2_sfi_req *pSMB  = NULL;2264	struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;2265	struct set_file_rename *rename_info;2266	char *data_offset;2267	char dummy_string[30];2268	int rc = 0;2269	int bytes_returned = 0;2270	int len_of_str;2271	__u16 params, param_offset, offset, count, byte_count;2272 2273	cifs_dbg(FYI, "Rename to File by handle\n");2274	rc = smb_init(SMB_COM_TRANSACTION2, 15, pTcon, (void **) &pSMB,2275			(void **) &pSMBr);2276	if (rc)2277		return rc;2278 2279	params = 6;2280	pSMB->MaxSetupCount = 0;2281	pSMB->Reserved = 0;2282	pSMB->Flags = 0;2283	pSMB->Timeout = 0;2284	pSMB->Reserved2 = 0;2285	param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;2286	offset = param_offset + params;2287 2288	/* SMB offsets are from the beginning of SMB which is 4 bytes in, after RFC1001 field */2289	data_offset = (char *)(pSMB) + offset + 4;2290	rename_info = (struct set_file_rename *) data_offset;2291	pSMB->MaxParameterCount = cpu_to_le16(2);2292	pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB from sess */2293	pSMB->SetupCount = 1;2294	pSMB->Reserved3 = 0;2295	pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);2296	byte_count = 3 /* pad */  + params;2297	pSMB->ParameterCount = cpu_to_le16(params);2298	pSMB->TotalParameterCount = pSMB->ParameterCount;2299	pSMB->ParameterOffset = cpu_to_le16(param_offset);2300	pSMB->DataOffset = cpu_to_le16(offset);2301	/* construct random name ".cifs_tmp<inodenum><mid>" */2302	rename_info->overwrite = cpu_to_le32(1);2303	rename_info->root_fid  = 0;2304	/* unicode only call */2305	if (target_name == NULL) {2306		sprintf(dummy_string, "cifs%x", pSMB->hdr.Mid);2307		len_of_str =2308			cifsConvertToUTF16((__le16 *)rename_info->target_name,2309					dummy_string, 24, nls_codepage, remap);2310	} else {2311		len_of_str =2312			cifsConvertToUTF16((__le16 *)rename_info->target_name,2313					target_name, PATH_MAX, nls_codepage,2314					remap);2315	}2316	rename_info->target_name_len = cpu_to_le32(2 * len_of_str);2317	count = sizeof(struct set_file_rename) + (2 * len_of_str);2318	byte_count += count;2319	pSMB->DataCount = cpu_to_le16(count);2320	pSMB->TotalDataCount = pSMB->DataCount;2321	pSMB->Fid = netfid;2322	pSMB->InformationLevel =2323		cpu_to_le16(SMB_SET_FILE_RENAME_INFORMATION);2324	pSMB->Reserved4 = 0;2325	inc_rfc1001_len(pSMB, byte_count);2326	pSMB->ByteCount = cpu_to_le16(byte_count);2327	rc = SendReceive(xid, pTcon->ses, (struct smb_hdr *) pSMB,2328			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);2329	cifs_stats_inc(&pTcon->stats.cifs_stats.num_t2renames);2330	if (rc)2331		cifs_dbg(FYI, "Send error in Rename (by file handle) = %d\n",2332			 rc);2333 2334	cifs_buf_release(pSMB);2335 2336	/* Note: On -EAGAIN error only caller can retry on handle based calls2337		since file handle passed in no longer valid */2338 2339	return rc;2340}2341 2342int2343CIFSSMBCopy(const unsigned int xid, struct cifs_tcon *tcon,2344	    const char *fromName, const __u16 target_tid, const char *toName,2345	    const int flags, const struct nls_table *nls_codepage, int remap)2346{2347	int rc = 0;2348	COPY_REQ *pSMB = NULL;2349	COPY_RSP *pSMBr = NULL;2350	int bytes_returned;2351	int name_len, name_len2;2352	__u16 count;2353 2354	cifs_dbg(FYI, "In CIFSSMBCopy\n");2355copyRetry:2356	rc = smb_init(SMB_COM_COPY, 1, tcon, (void **) &pSMB,2357			(void **) &pSMBr);2358	if (rc)2359		return rc;2360 2361	pSMB->BufferFormat = 0x04;2362	pSMB->Tid2 = target_tid;2363 2364	pSMB->Flags = cpu_to_le16(flags & COPY_TREE);2365 2366	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {2367		name_len = cifsConvertToUTF16((__le16 *) pSMB->OldFileName,2368					      fromName, PATH_MAX, nls_codepage,2369					      remap);2370		name_len++;     /* trailing null */2371		name_len *= 2;2372		pSMB->OldFileName[name_len] = 0x04;     /* pad */2373		/* protocol requires ASCII signature byte on Unicode string */2374		pSMB->OldFileName[name_len + 1] = 0x00;2375		name_len2 =2376		    cifsConvertToUTF16((__le16 *)&pSMB->OldFileName[name_len+2],2377				       toName, PATH_MAX, nls_codepage, remap);2378		name_len2 += 1 /* trailing null */  + 1 /* Signature word */ ;2379		name_len2 *= 2; /* convert to bytes */2380	} else {2381		name_len = copy_path_name(pSMB->OldFileName, fromName);2382		pSMB->OldFileName[name_len] = 0x04;  /* 2nd buffer format */2383		name_len2 = copy_path_name(pSMB->OldFileName+name_len+1, toName);2384		name_len2++;    /* signature byte */2385	}2386 2387	count = 1 /* 1st signature byte */  + name_len + name_len2;2388	inc_rfc1001_len(pSMB, count);2389	pSMB->ByteCount = cpu_to_le16(count);2390 2391	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,2392		(struct smb_hdr *) pSMBr, &bytes_returned, 0);2393	if (rc) {2394		cifs_dbg(FYI, "Send error in copy = %d with %d files copied\n",2395			 rc, le16_to_cpu(pSMBr->CopyCount));2396	}2397	cifs_buf_release(pSMB);2398 2399	if (rc == -EAGAIN)2400		goto copyRetry;2401 2402	return rc;2403}2404 2405int2406CIFSUnixCreateSymLink(const unsigned int xid, struct cifs_tcon *tcon,2407		      const char *fromName, const char *toName,2408		      const struct nls_table *nls_codepage, int remap)2409{2410	TRANSACTION2_SPI_REQ *pSMB = NULL;2411	TRANSACTION2_SPI_RSP *pSMBr = NULL;2412	char *data_offset;2413	int name_len;2414	int name_len_target;2415	int rc = 0;2416	int bytes_returned = 0;2417	__u16 params, param_offset, offset, byte_count;2418 2419	cifs_dbg(FYI, "In Symlink Unix style\n");2420createSymLinkRetry:2421	rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,2422		      (void **) &pSMBr);2423	if (rc)2424		return rc;2425 2426	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {2427		name_len =2428		    cifsConvertToUTF16((__le16 *) pSMB->FileName, fromName,2429				/* find define for this maxpathcomponent */2430					PATH_MAX, nls_codepage, remap);2431		name_len++;	/* trailing null */2432		name_len *= 2;2433 2434	} else {2435		name_len = copy_path_name(pSMB->FileName, fromName);2436	}2437	params = 6 + name_len;2438	pSMB->MaxSetupCount = 0;2439	pSMB->Reserved = 0;2440	pSMB->Flags = 0;2441	pSMB->Timeout = 0;2442	pSMB->Reserved2 = 0;2443	param_offset = offsetof(struct smb_com_transaction2_spi_req,2444				InformationLevel) - 4;2445	offset = param_offset + params;2446 2447	/* SMB offsets are from the beginning of SMB which is 4 bytes in, after RFC1001 field */2448	data_offset = (char *)pSMB + offset + 4;2449	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {2450		name_len_target =2451		    cifsConvertToUTF16((__le16 *) data_offset, toName,2452				/* find define for this maxpathcomponent */2453					PATH_MAX, nls_codepage, remap);2454		name_len_target++;	/* trailing null */2455		name_len_target *= 2;2456	} else {2457		name_len_target = copy_path_name(data_offset, toName);2458	}2459 2460	pSMB->MaxParameterCount = cpu_to_le16(2);2461	/* BB find exact max on data count below from sess */2462	pSMB->MaxDataCount = cpu_to_le16(1000);2463	pSMB->SetupCount = 1;2464	pSMB->Reserved3 = 0;2465	pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);2466	byte_count = 3 /* pad */  + params + name_len_target;2467	pSMB->DataCount = cpu_to_le16(name_len_target);2468	pSMB->ParameterCount = cpu_to_le16(params);2469	pSMB->TotalDataCount = pSMB->DataCount;2470	pSMB->TotalParameterCount = pSMB->ParameterCount;2471	pSMB->ParameterOffset = cpu_to_le16(param_offset);2472	pSMB->DataOffset = cpu_to_le16(offset);2473	pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_LINK);2474	pSMB->Reserved4 = 0;2475	inc_rfc1001_len(pSMB, byte_count);2476	pSMB->ByteCount = cpu_to_le16(byte_count);2477	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,2478			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);2479	cifs_stats_inc(&tcon->stats.cifs_stats.num_symlinks);2480	if (rc)2481		cifs_dbg(FYI, "Send error in SetPathInfo create symlink = %d\n",2482			 rc);2483 2484	cifs_buf_release(pSMB);2485 2486	if (rc == -EAGAIN)2487		goto createSymLinkRetry;2488 2489	return rc;2490}2491 2492int2493CIFSUnixCreateHardLink(const unsigned int xid, struct cifs_tcon *tcon,2494		       const char *fromName, const char *toName,2495		       const struct nls_table *nls_codepage, int remap)2496{2497	TRANSACTION2_SPI_REQ *pSMB = NULL;2498	TRANSACTION2_SPI_RSP *pSMBr = NULL;2499	char *data_offset;2500	int name_len;2501	int name_len_target;2502	int rc = 0;2503	int bytes_returned = 0;2504	__u16 params, param_offset, offset, byte_count;2505 2506	cifs_dbg(FYI, "In Create Hard link Unix style\n");2507createHardLinkRetry:2508	rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,2509		      (void **) &pSMBr);2510	if (rc)2511		return rc;2512 2513	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {2514		name_len = cifsConvertToUTF16((__le16 *) pSMB->FileName, toName,2515					      PATH_MAX, nls_codepage, remap);2516		name_len++;	/* trailing null */2517		name_len *= 2;2518 2519	} else {2520		name_len = copy_path_name(pSMB->FileName, toName);2521	}2522	params = 6 + name_len;2523	pSMB->MaxSetupCount = 0;2524	pSMB->Reserved = 0;2525	pSMB->Flags = 0;2526	pSMB->Timeout = 0;2527	pSMB->Reserved2 = 0;2528	param_offset = offsetof(struct smb_com_transaction2_spi_req,2529				InformationLevel) - 4;2530	offset = param_offset + params;2531 2532	/* SMB offsets are from the beginning of SMB which is 4 bytes in, after RFC1001 field */2533	data_offset = (char *)pSMB + offset + 4;2534	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {2535		name_len_target =2536		    cifsConvertToUTF16((__le16 *) data_offset, fromName,2537				       PATH_MAX, nls_codepage, remap);2538		name_len_target++;	/* trailing null */2539		name_len_target *= 2;2540	} else {2541		name_len_target = copy_path_name(data_offset, fromName);2542	}2543 2544	pSMB->MaxParameterCount = cpu_to_le16(2);2545	/* BB find exact max on data count below from sess*/2546	pSMB->MaxDataCount = cpu_to_le16(1000);2547	pSMB->SetupCount = 1;2548	pSMB->Reserved3 = 0;2549	pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);2550	byte_count = 3 /* pad */  + params + name_len_target;2551	pSMB->ParameterCount = cpu_to_le16(params);2552	pSMB->TotalParameterCount = pSMB->ParameterCount;2553	pSMB->DataCount = cpu_to_le16(name_len_target);2554	pSMB->TotalDataCount = pSMB->DataCount;2555	pSMB->ParameterOffset = cpu_to_le16(param_offset);2556	pSMB->DataOffset = cpu_to_le16(offset);2557	pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_HLINK);2558	pSMB->Reserved4 = 0;2559	inc_rfc1001_len(pSMB, byte_count);2560	pSMB->ByteCount = cpu_to_le16(byte_count);2561	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,2562			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);2563	cifs_stats_inc(&tcon->stats.cifs_stats.num_hardlinks);2564	if (rc)2565		cifs_dbg(FYI, "Send error in SetPathInfo (hard link) = %d\n",2566			 rc);2567 2568	cifs_buf_release(pSMB);2569	if (rc == -EAGAIN)2570		goto createHardLinkRetry;2571 2572	return rc;2573}2574 2575int CIFSCreateHardLink(const unsigned int xid,2576		       struct cifs_tcon *tcon,2577		       struct dentry *source_dentry,2578		       const char *from_name, const char *to_name,2579		       struct cifs_sb_info *cifs_sb)2580{2581	int rc = 0;2582	NT_RENAME_REQ *pSMB = NULL;2583	RENAME_RSP *pSMBr = NULL;2584	int bytes_returned;2585	int name_len, name_len2;2586	__u16 count;2587	int remap = cifs_remap(cifs_sb);2588 2589	cifs_dbg(FYI, "In CIFSCreateHardLink\n");2590winCreateHardLinkRetry:2591 2592	rc = smb_init(SMB_COM_NT_RENAME, 4, tcon, (void **) &pSMB,2593		      (void **) &pSMBr);2594	if (rc)2595		return rc;2596 2597	pSMB->SearchAttributes =2598	    cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |2599			ATTR_DIRECTORY);2600	pSMB->Flags = cpu_to_le16(CREATE_HARD_LINK);2601	pSMB->ClusterCount = 0;2602 2603	pSMB->BufferFormat = 0x04;2604 2605	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {2606		name_len =2607		    cifsConvertToUTF16((__le16 *) pSMB->OldFileName, from_name,2608				       PATH_MAX, cifs_sb->local_nls, remap);2609		name_len++;	/* trailing null */2610		name_len *= 2;2611 2612		/* protocol specifies ASCII buffer format (0x04) for unicode */2613		pSMB->OldFileName[name_len] = 0x04;2614		pSMB->OldFileName[name_len + 1] = 0x00; /* pad */2615		name_len2 =2616		    cifsConvertToUTF16((__le16 *)&pSMB->OldFileName[name_len+2],2617				       to_name, PATH_MAX, cifs_sb->local_nls,2618				       remap);2619		name_len2 += 1 /* trailing null */  + 1 /* Signature word */ ;2620		name_len2 *= 2;	/* convert to bytes */2621	} else {2622		name_len = copy_path_name(pSMB->OldFileName, from_name);2623		pSMB->OldFileName[name_len] = 0x04;	/* 2nd buffer format */2624		name_len2 = copy_path_name(pSMB->OldFileName+name_len+1, to_name);2625		name_len2++;	/* signature byte */2626	}2627 2628	count = 1 /* string type byte */  + name_len + name_len2;2629	inc_rfc1001_len(pSMB, count);2630	pSMB->ByteCount = cpu_to_le16(count);2631 2632	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,2633			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);2634	cifs_stats_inc(&tcon->stats.cifs_stats.num_hardlinks);2635	if (rc)2636		cifs_dbg(FYI, "Send error in hard link (NT rename) = %d\n", rc);2637 2638	cifs_buf_release(pSMB);2639	if (rc == -EAGAIN)2640		goto winCreateHardLinkRetry;2641 2642	return rc;2643}2644 2645int2646CIFSSMBUnixQuerySymLink(const unsigned int xid, struct cifs_tcon *tcon,2647			const unsigned char *searchName, char **symlinkinfo,2648			const struct nls_table *nls_codepage, int remap)2649{2650/* SMB_QUERY_FILE_UNIX_LINK */2651	TRANSACTION2_QPI_REQ *pSMB = NULL;2652	TRANSACTION2_QPI_RSP *pSMBr = NULL;2653	int rc = 0;2654	int bytes_returned;2655	int name_len;2656	__u16 params, byte_count;2657	char *data_start;2658 2659	cifs_dbg(FYI, "In QPathSymLinkInfo (Unix) for path %s\n", searchName);2660 2661querySymLinkRetry:2662	rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,2663		      (void **) &pSMBr);2664	if (rc)2665		return rc;2666 2667	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {2668		name_len =2669			cifsConvertToUTF16((__le16 *) pSMB->FileName,2670					   searchName, PATH_MAX, nls_codepage,2671					   remap);2672		name_len++;	/* trailing null */2673		name_len *= 2;2674	} else {2675		name_len = copy_path_name(pSMB->FileName, searchName);2676	}2677 2678	params = 2 /* level */  + 4 /* rsrvd */  + name_len /* incl null */ ;2679	pSMB->TotalDataCount = 0;2680	pSMB->MaxParameterCount = cpu_to_le16(2);2681	pSMB->MaxDataCount = cpu_to_le16(CIFSMaxBufSize);2682	pSMB->MaxSetupCount = 0;2683	pSMB->Reserved = 0;2684	pSMB->Flags = 0;2685	pSMB->Timeout = 0;2686	pSMB->Reserved2 = 0;2687	pSMB->ParameterOffset = cpu_to_le16(offsetof(2688	struct smb_com_transaction2_qpi_req, InformationLevel) - 4);2689	pSMB->DataCount = 0;2690	pSMB->DataOffset = 0;2691	pSMB->SetupCount = 1;2692	pSMB->Reserved3 = 0;2693	pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);2694	byte_count = params + 1 /* pad */ ;2695	pSMB->TotalParameterCount = cpu_to_le16(params);2696	pSMB->ParameterCount = pSMB->TotalParameterCount;2697	pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_LINK);2698	pSMB->Reserved4 = 0;2699	inc_rfc1001_len(pSMB, byte_count);2700	pSMB->ByteCount = cpu_to_le16(byte_count);2701 2702	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,2703			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);2704	if (rc) {2705		cifs_dbg(FYI, "Send error in QuerySymLinkInfo = %d\n", rc);2706	} else {2707		/* decode response */2708 2709		rc = validate_t2((struct smb_t2_rsp *)pSMBr);2710		/* BB also check enough total bytes returned */2711		if (rc || get_bcc(&pSMBr->hdr) < 2)2712			rc = -EIO;2713		else {2714			bool is_unicode;2715			u16 count = le16_to_cpu(pSMBr->t2.DataCount);2716 2717			data_start = ((char *) &pSMBr->hdr.Protocol) +2718					   le16_to_cpu(pSMBr->t2.DataOffset);2719 2720			if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)2721				is_unicode = true;2722			else2723				is_unicode = false;2724 2725			/* BB FIXME investigate remapping reserved chars here */2726			*symlinkinfo = cifs_strndup_from_utf16(data_start,2727					count, is_unicode, nls_codepage);2728			if (!*symlinkinfo)2729				rc = -ENOMEM;2730		}2731	}2732	cifs_buf_release(pSMB);2733	if (rc == -EAGAIN)2734		goto querySymLinkRetry;2735	return rc;2736}2737 2738int cifs_query_reparse_point(const unsigned int xid,2739			     struct cifs_tcon *tcon,2740			     struct cifs_sb_info *cifs_sb,2741			     const char *full_path,2742			     u32 *tag, struct kvec *rsp,2743			     int *rsp_buftype)2744{2745	struct reparse_data_buffer *buf;2746	struct cifs_open_parms oparms;2747	TRANSACT_IOCTL_REQ *io_req = NULL;2748	TRANSACT_IOCTL_RSP *io_rsp = NULL;2749	struct cifs_fid fid;2750	__u32 data_offset, data_count, len;2751	__u8 *start, *end;2752	int io_rsp_len;2753	int oplock = 0;2754	int rc;2755 2756	cifs_tcon_dbg(FYI, "%s: path=%s\n", __func__, full_path);2757 2758	if (cap_unix(tcon->ses))2759		return -EOPNOTSUPP;2760 2761	oparms = (struct cifs_open_parms) {2762		.tcon = tcon,2763		.cifs_sb = cifs_sb,2764		.desired_access = FILE_READ_ATTRIBUTES,2765		.create_options = cifs_create_options(cifs_sb,2766						      OPEN_REPARSE_POINT),2767		.disposition = FILE_OPEN,2768		.path = full_path,2769		.fid = &fid,2770	};2771 2772	rc = CIFS_open(xid, &oparms, &oplock, NULL);2773	if (rc)2774		return rc;2775 2776	rc = smb_init(SMB_COM_NT_TRANSACT, 23, tcon,2777		      (void **)&io_req, (void **)&io_rsp);2778	if (rc)2779		goto error;2780 2781	io_req->TotalParameterCount = 0;2782	io_req->TotalDataCount = 0;2783	io_req->MaxParameterCount = cpu_to_le32(2);2784	/* BB find exact data count max from sess structure BB */2785	io_req->MaxDataCount = cpu_to_le32(CIFSMaxBufSize & 0xFFFFFF00);2786	io_req->MaxSetupCount = 4;2787	io_req->Reserved = 0;2788	io_req->ParameterOffset = 0;2789	io_req->DataCount = 0;2790	io_req->DataOffset = 0;2791	io_req->SetupCount = 4;2792	io_req->SubCommand = cpu_to_le16(NT_TRANSACT_IOCTL);2793	io_req->ParameterCount = io_req->TotalParameterCount;2794	io_req->FunctionCode = cpu_to_le32(FSCTL_GET_REPARSE_POINT);2795	io_req->IsFsctl = 1;2796	io_req->IsRootFlag = 0;2797	io_req->Fid = fid.netfid;2798	io_req->ByteCount = 0;2799 2800	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *)io_req,2801			 (struct smb_hdr *)io_rsp, &io_rsp_len, 0);2802	if (rc)2803		goto error;2804 2805	data_offset = le32_to_cpu(io_rsp->DataOffset);2806	data_count = le32_to_cpu(io_rsp->DataCount);2807	if (get_bcc(&io_rsp->hdr) < 2 || data_offset > 512 ||2808	    !data_count || data_count > 2048) {2809		rc = -EIO;2810		goto error;2811	}2812 2813	end = 2 + get_bcc(&io_rsp->hdr) + (__u8 *)&io_rsp->ByteCount;2814	start = (__u8 *)&io_rsp->hdr.Protocol + data_offset;2815	if (start >= end) {2816		rc = -EIO;2817		goto error;2818	}2819 2820	data_count = le16_to_cpu(io_rsp->ByteCount);2821	buf = (struct reparse_data_buffer *)start;2822	len = sizeof(*buf);2823	if (data_count < len ||2824	    data_count < le16_to_cpu(buf->ReparseDataLength) + len) {2825		rc = -EIO;2826		goto error;2827	}2828 2829	*tag = le32_to_cpu(buf->ReparseTag);2830	rsp->iov_base = io_rsp;2831	rsp->iov_len = io_rsp_len;2832	*rsp_buftype = CIFS_LARGE_BUFFER;2833	CIFSSMBClose(xid, tcon, fid.netfid);2834	return 0;2835 2836error:2837	cifs_buf_release(io_req);2838	CIFSSMBClose(xid, tcon, fid.netfid);2839	return rc;2840}2841 2842int2843CIFSSMB_set_compression(const unsigned int xid, struct cifs_tcon *tcon,2844		    __u16 fid)2845{2846	int rc = 0;2847	int bytes_returned;2848	struct smb_com_transaction_compr_ioctl_req *pSMB;2849	struct smb_com_transaction_ioctl_rsp *pSMBr;2850 2851	cifs_dbg(FYI, "Set compression for %u\n", fid);2852	rc = smb_init(SMB_COM_NT_TRANSACT, 23, tcon, (void **) &pSMB,2853		      (void **) &pSMBr);2854	if (rc)2855		return rc;2856 2857	pSMB->compression_state = cpu_to_le16(COMPRESSION_FORMAT_DEFAULT);2858 2859	pSMB->TotalParameterCount = 0;2860	pSMB->TotalDataCount = cpu_to_le32(2);2861	pSMB->MaxParameterCount = 0;2862	pSMB->MaxDataCount = 0;2863	pSMB->MaxSetupCount = 4;2864	pSMB->Reserved = 0;2865	pSMB->ParameterOffset = 0;2866	pSMB->DataCount = cpu_to_le32(2);2867	pSMB->DataOffset =2868		cpu_to_le32(offsetof(struct smb_com_transaction_compr_ioctl_req,2869				compression_state) - 4);  /* 84 */2870	pSMB->SetupCount = 4;2871	pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_IOCTL);2872	pSMB->ParameterCount = 0;2873	pSMB->FunctionCode = cpu_to_le32(FSCTL_SET_COMPRESSION);2874	pSMB->IsFsctl = 1; /* FSCTL */2875	pSMB->IsRootFlag = 0;2876	pSMB->Fid = fid; /* file handle always le */2877	/* 3 byte pad, followed by 2 byte compress state */2878	pSMB->ByteCount = cpu_to_le16(5);2879	inc_rfc1001_len(pSMB, 5);2880 2881	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,2882			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);2883	if (rc)2884		cifs_dbg(FYI, "Send error in SetCompression = %d\n", rc);2885 2886	cifs_buf_release(pSMB);2887 2888	/*2889	 * Note: On -EAGAIN error only caller can retry on handle based calls2890	 * since file handle passed in no longer valid.2891	 */2892	return rc;2893}2894 2895 2896#ifdef CONFIG_CIFS_POSIX2897 2898#ifdef CONFIG_FS_POSIX_ACL2899/**2900 * cifs_init_posix_acl - convert ACL from cifs to POSIX ACL format2901 * @ace: POSIX ACL entry to store converted ACL into2902 * @cifs_ace: ACL in cifs format2903 *2904 * Convert an Access Control Entry from wire format to local POSIX xattr2905 * format.2906 *2907 * Note that the @cifs_uid member is used to store both {g,u}id_t.2908 */2909static void cifs_init_posix_acl(struct posix_acl_entry *ace,2910				struct cifs_posix_ace *cifs_ace)2911{2912	/* u8 cifs fields do not need le conversion */2913	ace->e_perm = cifs_ace->cifs_e_perm;2914	ace->e_tag = cifs_ace->cifs_e_tag;2915 2916	switch (ace->e_tag) {2917	case ACL_USER:2918		ace->e_uid = make_kuid(&init_user_ns,2919				       le64_to_cpu(cifs_ace->cifs_uid));2920		break;2921	case ACL_GROUP:2922		ace->e_gid = make_kgid(&init_user_ns,2923				       le64_to_cpu(cifs_ace->cifs_uid));2924		break;2925	}2926	return;2927}2928 2929/**2930 * cifs_to_posix_acl - copy cifs ACL format to POSIX ACL format2931 * @acl: ACLs returned in POSIX ACL format2932 * @src: ACLs in cifs format2933 * @acl_type: type of POSIX ACL requested2934 * @size_of_data_area: size of SMB we got2935 *2936 * This function converts ACLs from cifs format to POSIX ACL format.2937 * If @acl is NULL then the size of the buffer required to store POSIX ACLs in2938 * their uapi format is returned.2939 */2940static int cifs_to_posix_acl(struct posix_acl **acl, char *src,2941			     const int acl_type, const int size_of_data_area)2942{2943	int size =  0;2944	__u16 count;2945	struct cifs_posix_ace *pACE;2946	struct cifs_posix_acl *cifs_acl = (struct cifs_posix_acl *)src;2947	struct posix_acl *kacl = NULL;2948	struct posix_acl_entry *pa, *pe;2949 2950	if (le16_to_cpu(cifs_acl->version) != CIFS_ACL_VERSION)2951		return -EOPNOTSUPP;2952 2953	if (acl_type == ACL_TYPE_ACCESS) {2954		count = le16_to_cpu(cifs_acl->access_entry_count);2955		pACE = &cifs_acl->ace_array[0];2956		size = sizeof(struct cifs_posix_acl);2957		size += sizeof(struct cifs_posix_ace) * count;2958		/* check if we would go beyond end of SMB */2959		if (size_of_data_area < size) {2960			cifs_dbg(FYI, "bad CIFS POSIX ACL size %d vs. %d\n",2961				 size_of_data_area, size);2962			return -EINVAL;2963		}2964	} else if (acl_type == ACL_TYPE_DEFAULT) {2965		count = le16_to_cpu(cifs_acl->access_entry_count);2966		size = sizeof(struct cifs_posix_acl);2967		size += sizeof(struct cifs_posix_ace) * count;2968		/* skip past access ACEs to get to default ACEs */2969		pACE = &cifs_acl->ace_array[count];2970		count = le16_to_cpu(cifs_acl->default_entry_count);2971		size += sizeof(struct cifs_posix_ace) * count;2972		/* check if we would go beyond end of SMB */2973		if (size_of_data_area < size)2974			return -EINVAL;2975	} else {2976		/* illegal type */2977		return -EINVAL;2978	}2979 2980	/* Allocate number of POSIX ACLs to store in VFS format. */2981	kacl = posix_acl_alloc(count, GFP_NOFS);2982	if (!kacl)2983		return -ENOMEM;2984 2985	FOREACH_ACL_ENTRY(pa, kacl, pe) {2986		cifs_init_posix_acl(pa, pACE);2987		pACE++;2988	}2989 2990	*acl = kacl;2991	return 0;2992}2993 2994/**2995 * cifs_init_ace - convert ACL entry from POSIX ACL to cifs format2996 * @cifs_ace: the cifs ACL entry to store into2997 * @local_ace: the POSIX ACL entry to convert2998 */2999static void cifs_init_ace(struct cifs_posix_ace *cifs_ace,3000			  const struct posix_acl_entry *local_ace)3001{3002	cifs_ace->cifs_e_perm = local_ace->e_perm;3003	cifs_ace->cifs_e_tag =  local_ace->e_tag;3004 3005	switch (local_ace->e_tag) {3006	case ACL_USER:3007		cifs_ace->cifs_uid =3008			cpu_to_le64(from_kuid(&init_user_ns, local_ace->e_uid));3009		break;3010	case ACL_GROUP:3011		cifs_ace->cifs_uid =3012			cpu_to_le64(from_kgid(&init_user_ns, local_ace->e_gid));3013		break;3014	default:3015		cifs_ace->cifs_uid = cpu_to_le64(-1);3016	}3017}3018 3019/**3020 * posix_acl_to_cifs - convert ACLs from POSIX ACL to cifs format3021 * @parm_data: ACLs in cifs format to convert to3022 * @acl: ACLs in POSIX ACL format to convert from3023 * @acl_type: the type of POSIX ACLs stored in @acl3024 *3025 * Return: the number cifs ACL entries after conversion3026 */3027static __u16 posix_acl_to_cifs(char *parm_data, const struct posix_acl *acl,3028			       const int acl_type)3029{3030	__u16 rc = 0;3031	struct cifs_posix_acl *cifs_acl = (struct cifs_posix_acl *)parm_data;3032	const struct posix_acl_entry *pa, *pe;3033	int count;3034	int i = 0;3035 3036	if ((acl == NULL) || (cifs_acl == NULL))3037		return 0;3038 3039	count = acl->a_count;3040	cifs_dbg(FYI, "setting acl with %d entries\n", count);3041 3042	/*3043	 * Note that the uapi POSIX ACL version is verified by the VFS and is3044	 * independent of the cifs ACL version. Changing the POSIX ACL version3045	 * is a uapi change and if it's changed we will pass down the POSIX ACL3046	 * version in struct posix_acl from the VFS. For now there's really3047	 * only one that all filesystems know how to deal with.3048	 */3049	cifs_acl->version = cpu_to_le16(1);3050	if (acl_type == ACL_TYPE_ACCESS) {3051		cifs_acl->access_entry_count = cpu_to_le16(count);3052		cifs_acl->default_entry_count = cpu_to_le16(0xFFFF);3053	} else if (acl_type == ACL_TYPE_DEFAULT) {3054		cifs_acl->default_entry_count = cpu_to_le16(count);3055		cifs_acl->access_entry_count = cpu_to_le16(0xFFFF);3056	} else {3057		cifs_dbg(FYI, "unknown ACL type %d\n", acl_type);3058		return 0;3059	}3060	FOREACH_ACL_ENTRY(pa, acl, pe) {3061		cifs_init_ace(&cifs_acl->ace_array[i++], pa);3062	}3063	if (rc == 0) {3064		rc = (__u16)(count * sizeof(struct cifs_posix_ace));3065		rc += sizeof(struct cifs_posix_acl);3066		/* BB add check to make sure ACL does not overflow SMB */3067	}3068	return rc;3069}3070 3071int cifs_do_get_acl(const unsigned int xid, struct cifs_tcon *tcon,3072		    const unsigned char *searchName, struct posix_acl **acl,3073		    const int acl_type, const struct nls_table *nls_codepage,3074		    int remap)3075{3076/* SMB_QUERY_POSIX_ACL */3077	TRANSACTION2_QPI_REQ *pSMB = NULL;3078	TRANSACTION2_QPI_RSP *pSMBr = NULL;3079	int rc = 0;3080	int bytes_returned;3081	int name_len;3082	__u16 params, byte_count;3083 3084	cifs_dbg(FYI, "In GetPosixACL (Unix) for path %s\n", searchName);3085 3086queryAclRetry:3087	rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,3088		(void **) &pSMBr);3089	if (rc)3090		return rc;3091 3092	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {3093		name_len =3094			cifsConvertToUTF16((__le16 *) pSMB->FileName,3095					   searchName, PATH_MAX, nls_codepage,3096					   remap);3097		name_len++;     /* trailing null */3098		name_len *= 2;3099		pSMB->FileName[name_len] = 0;3100		pSMB->FileName[name_len+1] = 0;3101	} else {3102		name_len = copy_path_name(pSMB->FileName, searchName);3103	}3104 3105	params = 2 /* level */  + 4 /* rsrvd */  + name_len /* incl null */ ;3106	pSMB->TotalDataCount = 0;3107	pSMB->MaxParameterCount = cpu_to_le16(2);3108	/* BB find exact max data count below from sess structure BB */3109	pSMB->MaxDataCount = cpu_to_le16(4000);3110	pSMB->MaxSetupCount = 0;3111	pSMB->Reserved = 0;3112	pSMB->Flags = 0;3113	pSMB->Timeout = 0;3114	pSMB->Reserved2 = 0;3115	pSMB->ParameterOffset = cpu_to_le16(3116		offsetof(struct smb_com_transaction2_qpi_req,3117			 InformationLevel) - 4);3118	pSMB->DataCount = 0;3119	pSMB->DataOffset = 0;3120	pSMB->SetupCount = 1;3121	pSMB->Reserved3 = 0;3122	pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);3123	byte_count = params + 1 /* pad */ ;3124	pSMB->TotalParameterCount = cpu_to_le16(params);3125	pSMB->ParameterCount = pSMB->TotalParameterCount;3126	pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_POSIX_ACL);3127	pSMB->Reserved4 = 0;3128	inc_rfc1001_len(pSMB, byte_count);3129	pSMB->ByteCount = cpu_to_le16(byte_count);3130 3131	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,3132		(struct smb_hdr *) pSMBr, &bytes_returned, 0);3133	cifs_stats_inc(&tcon->stats.cifs_stats.num_acl_get);3134	if (rc) {3135		cifs_dbg(FYI, "Send error in Query POSIX ACL = %d\n", rc);3136	} else {3137		/* decode response */3138 3139		rc = validate_t2((struct smb_t2_rsp *)pSMBr);3140		/* BB also check enough total bytes returned */3141		if (rc || get_bcc(&pSMBr->hdr) < 2)3142			rc = -EIO;      /* bad smb */3143		else {3144			__u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);3145			__u16 count = le16_to_cpu(pSMBr->t2.DataCount);3146			rc = cifs_to_posix_acl(acl,3147				(char *)&pSMBr->hdr.Protocol+data_offset,3148				acl_type, count);3149		}3150	}3151	cifs_buf_release(pSMB);3152	/*3153	 * The else branch after SendReceive() doesn't return EAGAIN so if we3154	 * allocated @acl in cifs_to_posix_acl() we are guaranteed to return3155	 * here and don't leak POSIX ACLs.3156	 */3157	if (rc == -EAGAIN)3158		goto queryAclRetry;3159	return rc;3160}3161 3162int cifs_do_set_acl(const unsigned int xid, struct cifs_tcon *tcon,3163		    const unsigned char *fileName, const struct posix_acl *acl,3164		    const int acl_type, const struct nls_table *nls_codepage,3165		    int remap)3166{3167	struct smb_com_transaction2_spi_req *pSMB = NULL;3168	struct smb_com_transaction2_spi_rsp *pSMBr = NULL;3169	char *parm_data;3170	int name_len;3171	int rc = 0;3172	int bytes_returned = 0;3173	__u16 params, byte_count, data_count, param_offset, offset;3174 3175	cifs_dbg(FYI, "In SetPosixACL (Unix) for path %s\n", fileName);3176setAclRetry:3177	rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,3178		      (void **) &pSMBr);3179	if (rc)3180		return rc;3181	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {3182		name_len =3183			cifsConvertToUTF16((__le16 *) pSMB->FileName, fileName,3184					   PATH_MAX, nls_codepage, remap);3185		name_len++;     /* trailing null */3186		name_len *= 2;3187	} else {3188		name_len = copy_path_name(pSMB->FileName, fileName);3189	}3190	params = 6 + name_len;3191	pSMB->MaxParameterCount = cpu_to_le16(2);3192	/* BB find max SMB size from sess */3193	pSMB->MaxDataCount = cpu_to_le16(1000);3194	pSMB->MaxSetupCount = 0;3195	pSMB->Reserved = 0;3196	pSMB->Flags = 0;3197	pSMB->Timeout = 0;3198	pSMB->Reserved2 = 0;3199	param_offset = offsetof(struct smb_com_transaction2_spi_req,3200				InformationLevel) - 4;3201	offset = param_offset + params;3202	parm_data = ((char *)pSMB) + sizeof(pSMB->hdr.smb_buf_length) + offset;3203	pSMB->ParameterOffset = cpu_to_le16(param_offset);3204 3205	/* convert to on the wire format for POSIX ACL */3206	data_count = posix_acl_to_cifs(parm_data, acl, acl_type);3207 3208	if (data_count == 0) {3209		rc = -EOPNOTSUPP;3210		goto setACLerrorExit;3211	}3212	pSMB->DataOffset = cpu_to_le16(offset);3213	pSMB->SetupCount = 1;3214	pSMB->Reserved3 = 0;3215	pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);3216	pSMB->InformationLevel = cpu_to_le16(SMB_SET_POSIX_ACL);3217	byte_count = 3 /* pad */  + params + data_count;3218	pSMB->DataCount = cpu_to_le16(data_count);3219	pSMB->TotalDataCount = pSMB->DataCount;3220	pSMB->ParameterCount = cpu_to_le16(params);3221	pSMB->TotalParameterCount = pSMB->ParameterCount;3222	pSMB->Reserved4 = 0;3223	inc_rfc1001_len(pSMB, byte_count);3224	pSMB->ByteCount = cpu_to_le16(byte_count);3225	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,3226			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);3227	if (rc)3228		cifs_dbg(FYI, "Set POSIX ACL returned %d\n", rc);3229 3230setACLerrorExit:3231	cifs_buf_release(pSMB);3232	if (rc == -EAGAIN)3233		goto setAclRetry;3234	return rc;3235}3236#else3237int cifs_do_get_acl(const unsigned int xid, struct cifs_tcon *tcon,3238		    const unsigned char *searchName, struct posix_acl **acl,3239		    const int acl_type, const struct nls_table *nls_codepage,3240		    int remap)3241{3242	return -EOPNOTSUPP;3243}3244 3245int cifs_do_set_acl(const unsigned int xid, struct cifs_tcon *tcon,3246		    const unsigned char *fileName, const struct posix_acl *acl,3247		    const int acl_type, const struct nls_table *nls_codepage,3248		    int remap)3249{3250	return -EOPNOTSUPP;3251}3252#endif /* CONFIG_FS_POSIX_ACL */3253 3254int3255CIFSGetExtAttr(const unsigned int xid, struct cifs_tcon *tcon,3256	       const int netfid, __u64 *pExtAttrBits, __u64 *pMask)3257{3258	int rc = 0;3259	struct smb_t2_qfi_req *pSMB = NULL;3260	struct smb_t2_qfi_rsp *pSMBr = NULL;3261	int bytes_returned;3262	__u16 params, byte_count;3263 3264	cifs_dbg(FYI, "In GetExtAttr\n");3265	if (tcon == NULL)3266		return -ENODEV;3267 3268GetExtAttrRetry:3269	rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,3270		      (void **) &pSMBr);3271	if (rc)3272		return rc;3273 3274	params = 2 /* level */ + 2 /* fid */;3275	pSMB->t2.TotalDataCount = 0;3276	pSMB->t2.MaxParameterCount = cpu_to_le16(4);3277	/* BB find exact max data count below from sess structure BB */3278	pSMB->t2.MaxDataCount = cpu_to_le16(4000);3279	pSMB->t2.MaxSetupCount = 0;3280	pSMB->t2.Reserved = 0;3281	pSMB->t2.Flags = 0;3282	pSMB->t2.Timeout = 0;3283	pSMB->t2.Reserved2 = 0;3284	pSMB->t2.ParameterOffset = cpu_to_le16(offsetof(struct smb_t2_qfi_req,3285					       Fid) - 4);3286	pSMB->t2.DataCount = 0;3287	pSMB->t2.DataOffset = 0;3288	pSMB->t2.SetupCount = 1;3289	pSMB->t2.Reserved3 = 0;3290	pSMB->t2.SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION);3291	byte_count = params + 1 /* pad */ ;3292	pSMB->t2.TotalParameterCount = cpu_to_le16(params);3293	pSMB->t2.ParameterCount = pSMB->t2.TotalParameterCount;3294	pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_ATTR_FLAGS);3295	pSMB->Pad = 0;3296	pSMB->Fid = netfid;3297	inc_rfc1001_len(pSMB, byte_count);3298	pSMB->t2.ByteCount = cpu_to_le16(byte_count);3299 3300	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,3301			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);3302	if (rc) {3303		cifs_dbg(FYI, "error %d in GetExtAttr\n", rc);3304	} else {3305		/* decode response */3306		rc = validate_t2((struct smb_t2_rsp *)pSMBr);3307		/* BB also check enough total bytes returned */3308		if (rc || get_bcc(&pSMBr->hdr) < 2)3309			/* If rc should we check for EOPNOSUPP and3310			   disable the srvino flag? or in caller? */3311			rc = -EIO;      /* bad smb */3312		else {3313			__u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);3314			__u16 count = le16_to_cpu(pSMBr->t2.DataCount);3315			struct file_chattr_info *pfinfo;3316 3317			if (count != 16) {3318				cifs_dbg(FYI, "Invalid size ret in GetExtAttr\n");3319				rc = -EIO;3320				goto GetExtAttrOut;3321			}3322			pfinfo = (struct file_chattr_info *)3323				 (data_offset + (char *) &pSMBr->hdr.Protocol);3324			*pExtAttrBits = le64_to_cpu(pfinfo->mode);3325			*pMask = le64_to_cpu(pfinfo->mask);3326		}3327	}3328GetExtAttrOut:3329	cifs_buf_release(pSMB);3330	if (rc == -EAGAIN)3331		goto GetExtAttrRetry;3332	return rc;3333}3334 3335#endif /* CONFIG_POSIX */3336 3337/*3338 * Initialize NT TRANSACT SMB into small smb request buffer.  This assumes that3339 * all NT TRANSACTS that we init here have total parm and data under about 4003340 * bytes (to fit in small cifs buffer size), which is the case so far, it3341 * easily fits. NB: Setup words themselves and ByteCount MaxSetupCount (size of3342 * returned setup area) and MaxParameterCount (returned parms size) must be set3343 * by caller3344 */3345static int3346smb_init_nttransact(const __u16 sub_command, const int setup_count,3347		   const int parm_len, struct cifs_tcon *tcon,3348		   void **ret_buf)3349{3350	int rc;3351	__u32 temp_offset;3352	struct smb_com_ntransact_req *pSMB;3353 3354	rc = small_smb_init(SMB_COM_NT_TRANSACT, 19 + setup_count, tcon,3355				(void **)&pSMB);3356	if (rc)3357		return rc;3358	*ret_buf = (void *)pSMB;3359	pSMB->Reserved = 0;3360	pSMB->TotalParameterCount = cpu_to_le32(parm_len);3361	pSMB->TotalDataCount  = 0;3362	pSMB->MaxDataCount = cpu_to_le32(CIFSMaxBufSize & 0xFFFFFF00);3363	pSMB->ParameterCount = pSMB->TotalParameterCount;3364	pSMB->DataCount  = pSMB->TotalDataCount;3365	temp_offset = offsetof(struct smb_com_ntransact_req, Parms) +3366			(setup_count * 2) - 4 /* for rfc1001 length itself */;3367	pSMB->ParameterOffset = cpu_to_le32(temp_offset);3368	pSMB->DataOffset = cpu_to_le32(temp_offset + parm_len);3369	pSMB->SetupCount = setup_count; /* no need to le convert byte fields */3370	pSMB->SubCommand = cpu_to_le16(sub_command);3371	return 0;3372}3373 3374static int3375validate_ntransact(char *buf, char **ppparm, char **ppdata,3376		   __u32 *pparmlen, __u32 *pdatalen)3377{3378	char *end_of_smb;3379	__u32 data_count, data_offset, parm_count, parm_offset;3380	struct smb_com_ntransact_rsp *pSMBr;3381	u16 bcc;3382 3383	*pdatalen = 0;3384	*pparmlen = 0;3385 3386	if (buf == NULL)3387		return -EINVAL;3388 3389	pSMBr = (struct smb_com_ntransact_rsp *)buf;3390 3391	bcc = get_bcc(&pSMBr->hdr);3392	end_of_smb = 2 /* sizeof byte count */ + bcc +3393			(char *)&pSMBr->ByteCount;3394 3395	data_offset = le32_to_cpu(pSMBr->DataOffset);3396	data_count = le32_to_cpu(pSMBr->DataCount);3397	parm_offset = le32_to_cpu(pSMBr->ParameterOffset);3398	parm_count = le32_to_cpu(pSMBr->ParameterCount);3399 3400	*ppparm = (char *)&pSMBr->hdr.Protocol + parm_offset;3401	*ppdata = (char *)&pSMBr->hdr.Protocol + data_offset;3402 3403	/* should we also check that parm and data areas do not overlap? */3404	if (*ppparm > end_of_smb) {3405		cifs_dbg(FYI, "parms start after end of smb\n");3406		return -EINVAL;3407	} else if (parm_count + *ppparm > end_of_smb) {3408		cifs_dbg(FYI, "parm end after end of smb\n");3409		return -EINVAL;3410	} else if (*ppdata > end_of_smb) {3411		cifs_dbg(FYI, "data starts after end of smb\n");3412		return -EINVAL;3413	} else if (data_count + *ppdata > end_of_smb) {3414		cifs_dbg(FYI, "data %p + count %d (%p) past smb end %p start %p\n",3415			 *ppdata, data_count, (data_count + *ppdata),3416			 end_of_smb, pSMBr);3417		return -EINVAL;3418	} else if (parm_count + data_count > bcc) {3419		cifs_dbg(FYI, "parm count and data count larger than SMB\n");3420		return -EINVAL;3421	}3422	*pdatalen = data_count;3423	*pparmlen = parm_count;3424	return 0;3425}3426 3427/* Get Security Descriptor (by handle) from remote server for a file or dir */3428int3429CIFSSMBGetCIFSACL(const unsigned int xid, struct cifs_tcon *tcon, __u16 fid,3430		  struct smb_ntsd **acl_inf, __u32 *pbuflen)3431{3432	int rc = 0;3433	int buf_type = 0;3434	QUERY_SEC_DESC_REQ *pSMB;3435	struct kvec iov[1];3436	struct kvec rsp_iov;3437 3438	cifs_dbg(FYI, "GetCifsACL\n");3439 3440	*pbuflen = 0;3441	*acl_inf = NULL;3442 3443	rc = smb_init_nttransact(NT_TRANSACT_QUERY_SECURITY_DESC, 0,3444			8 /* parm len */, tcon, (void **) &pSMB);3445	if (rc)3446		return rc;3447 3448	pSMB->MaxParameterCount = cpu_to_le32(4);3449	/* BB TEST with big acls that might need to be e.g. larger than 16K */3450	pSMB->MaxSetupCount = 0;3451	pSMB->Fid = fid; /* file handle always le */3452	pSMB->AclFlags = cpu_to_le32(CIFS_ACL_OWNER | CIFS_ACL_GROUP |3453				     CIFS_ACL_DACL);3454	pSMB->ByteCount = cpu_to_le16(11); /* 3 bytes pad + 8 bytes parm */3455	inc_rfc1001_len(pSMB, 11);3456	iov[0].iov_base = (char *)pSMB;3457	iov[0].iov_len = be32_to_cpu(pSMB->hdr.smb_buf_length) + 4;3458 3459	rc = SendReceive2(xid, tcon->ses, iov, 1 /* num iovec */, &buf_type,3460			  0, &rsp_iov);3461	cifs_small_buf_release(pSMB);3462	cifs_stats_inc(&tcon->stats.cifs_stats.num_acl_get);3463	if (rc) {3464		cifs_dbg(FYI, "Send error in QuerySecDesc = %d\n", rc);3465	} else {                /* decode response */3466		__le32 *parm;3467		__u32 parm_len;3468		__u32 acl_len;3469		struct smb_com_ntransact_rsp *pSMBr;3470		char *pdata;3471 3472/* validate_nttransact */3473		rc = validate_ntransact(rsp_iov.iov_base, (char **)&parm,3474					&pdata, &parm_len, pbuflen);3475		if (rc)3476			goto qsec_out;3477		pSMBr = (struct smb_com_ntransact_rsp *)rsp_iov.iov_base;3478 3479		cifs_dbg(FYI, "smb %p parm %p data %p\n",3480			 pSMBr, parm, *acl_inf);3481 3482		if (le32_to_cpu(pSMBr->ParameterCount) != 4) {3483			rc = -EIO;      /* bad smb */3484			*pbuflen = 0;3485			goto qsec_out;3486		}3487 3488/* BB check that data area is minimum length and as big as acl_len */3489 3490		acl_len = le32_to_cpu(*parm);3491		if (acl_len != *pbuflen) {3492			cifs_dbg(VFS, "acl length %d does not match %d\n",3493				 acl_len, *pbuflen);3494			if (*pbuflen > acl_len)3495				*pbuflen = acl_len;3496		}3497 3498		/* check if buffer is big enough for the acl3499		   header followed by the smallest SID */3500		if ((*pbuflen < sizeof(struct smb_ntsd) + 8) ||3501		    (*pbuflen >= 64 * 1024)) {3502			cifs_dbg(VFS, "bad acl length %d\n", *pbuflen);3503			rc = -EINVAL;3504			*pbuflen = 0;3505		} else {3506			*acl_inf = kmemdup(pdata, *pbuflen, GFP_KERNEL);3507			if (*acl_inf == NULL) {3508				*pbuflen = 0;3509				rc = -ENOMEM;3510			}3511		}3512	}3513qsec_out:3514	free_rsp_buf(buf_type, rsp_iov.iov_base);3515	return rc;3516}3517 3518int3519CIFSSMBSetCIFSACL(const unsigned int xid, struct cifs_tcon *tcon, __u16 fid,3520			struct smb_ntsd *pntsd, __u32 acllen, int aclflag)3521{3522	__u16 byte_count, param_count, data_count, param_offset, data_offset;3523	int rc = 0;3524	int bytes_returned = 0;3525	SET_SEC_DESC_REQ *pSMB = NULL;3526	void *pSMBr;3527 3528setCifsAclRetry:3529	rc = smb_init(SMB_COM_NT_TRANSACT, 19, tcon, (void **) &pSMB, &pSMBr);3530	if (rc)3531		return rc;3532 3533	pSMB->MaxSetupCount = 0;3534	pSMB->Reserved = 0;3535 3536	param_count = 8;3537	param_offset = offsetof(struct smb_com_transaction_ssec_req, Fid) - 4;3538	data_count = acllen;3539	data_offset = param_offset + param_count;3540	byte_count = 3 /* pad */  + param_count;3541 3542	pSMB->DataCount = cpu_to_le32(data_count);3543	pSMB->TotalDataCount = pSMB->DataCount;3544	pSMB->MaxParameterCount = cpu_to_le32(4);3545	pSMB->MaxDataCount = cpu_to_le32(16384);3546	pSMB->ParameterCount = cpu_to_le32(param_count);3547	pSMB->ParameterOffset = cpu_to_le32(param_offset);3548	pSMB->TotalParameterCount = pSMB->ParameterCount;3549	pSMB->DataOffset = cpu_to_le32(data_offset);3550	pSMB->SetupCount = 0;3551	pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_SET_SECURITY_DESC);3552	pSMB->ByteCount = cpu_to_le16(byte_count+data_count);3553 3554	pSMB->Fid = fid; /* file handle always le */3555	pSMB->Reserved2 = 0;3556	pSMB->AclFlags = cpu_to_le32(aclflag);3557 3558	if (pntsd && acllen) {3559		memcpy((char *)pSMBr + offsetof(struct smb_hdr, Protocol) +3560				data_offset, pntsd, acllen);3561		inc_rfc1001_len(pSMB, byte_count + data_count);3562	} else3563		inc_rfc1001_len(pSMB, byte_count);3564 3565	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,3566		(struct smb_hdr *) pSMBr, &bytes_returned, 0);3567 3568	cifs_dbg(FYI, "SetCIFSACL bytes_returned: %d, rc: %d\n",3569		 bytes_returned, rc);3570	if (rc)3571		cifs_dbg(FYI, "Set CIFS ACL returned %d\n", rc);3572	cifs_buf_release(pSMB);3573 3574	if (rc == -EAGAIN)3575		goto setCifsAclRetry;3576 3577	return (rc);3578}3579 3580 3581/* Legacy Query Path Information call for lookup to old servers such3582   as Win9x/WinME */3583int3584SMBQueryInformation(const unsigned int xid, struct cifs_tcon *tcon,3585		    const char *search_name, FILE_ALL_INFO *data,3586		    const struct nls_table *nls_codepage, int remap)3587{3588	QUERY_INFORMATION_REQ *pSMB;3589	QUERY_INFORMATION_RSP *pSMBr;3590	int rc = 0;3591	int bytes_returned;3592	int name_len;3593 3594	cifs_dbg(FYI, "In SMBQPath path %s\n", search_name);3595QInfRetry:3596	rc = smb_init(SMB_COM_QUERY_INFORMATION, 0, tcon, (void **) &pSMB,3597		      (void **) &pSMBr);3598	if (rc)3599		return rc;3600 3601	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {3602		name_len =3603			cifsConvertToUTF16((__le16 *) pSMB->FileName,3604					   search_name, PATH_MAX, nls_codepage,3605					   remap);3606		name_len++;     /* trailing null */3607		name_len *= 2;3608	} else {3609		name_len = copy_path_name(pSMB->FileName, search_name);3610	}3611	pSMB->BufferFormat = 0x04;3612	name_len++; /* account for buffer type byte */3613	inc_rfc1001_len(pSMB, (__u16)name_len);3614	pSMB->ByteCount = cpu_to_le16(name_len);3615 3616	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,3617			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);3618	if (rc) {3619		cifs_dbg(FYI, "Send error in QueryInfo = %d\n", rc);3620	} else if (data) {3621		struct timespec64 ts;3622		__u32 time = le32_to_cpu(pSMBr->last_write_time);3623 3624		/* decode response */3625		/* BB FIXME - add time zone adjustment BB */3626		memset(data, 0, sizeof(FILE_ALL_INFO));3627		ts.tv_nsec = 0;3628		ts.tv_sec = time;3629		/* decode time fields */3630		data->ChangeTime = cpu_to_le64(cifs_UnixTimeToNT(ts));3631		data->LastWriteTime = data->ChangeTime;3632		data->LastAccessTime = 0;3633		data->AllocationSize =3634			cpu_to_le64(le32_to_cpu(pSMBr->size));3635		data->EndOfFile = data->AllocationSize;3636		data->Attributes =3637			cpu_to_le32(le16_to_cpu(pSMBr->attr));3638	} else3639		rc = -EIO; /* bad buffer passed in */3640 3641	cifs_buf_release(pSMB);3642 3643	if (rc == -EAGAIN)3644		goto QInfRetry;3645 3646	return rc;3647}3648 3649int3650CIFSSMBQFileInfo(const unsigned int xid, struct cifs_tcon *tcon,3651		 u16 netfid, FILE_ALL_INFO *pFindData)3652{3653	struct smb_t2_qfi_req *pSMB = NULL;3654	struct smb_t2_qfi_rsp *pSMBr = NULL;3655	int rc = 0;3656	int bytes_returned;3657	__u16 params, byte_count;3658 3659QFileInfoRetry:3660	rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,3661		      (void **) &pSMBr);3662	if (rc)3663		return rc;3664 3665	params = 2 /* level */ + 2 /* fid */;3666	pSMB->t2.TotalDataCount = 0;3667	pSMB->t2.MaxParameterCount = cpu_to_le16(4);3668	/* BB find exact max data count below from sess structure BB */3669	pSMB->t2.MaxDataCount = cpu_to_le16(CIFSMaxBufSize);3670	pSMB->t2.MaxSetupCount = 0;3671	pSMB->t2.Reserved = 0;3672	pSMB->t2.Flags = 0;3673	pSMB->t2.Timeout = 0;3674	pSMB->t2.Reserved2 = 0;3675	pSMB->t2.ParameterOffset = cpu_to_le16(offsetof(struct smb_t2_qfi_req,3676					       Fid) - 4);3677	pSMB->t2.DataCount = 0;3678	pSMB->t2.DataOffset = 0;3679	pSMB->t2.SetupCount = 1;3680	pSMB->t2.Reserved3 = 0;3681	pSMB->t2.SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION);3682	byte_count = params + 1 /* pad */ ;3683	pSMB->t2.TotalParameterCount = cpu_to_le16(params);3684	pSMB->t2.ParameterCount = pSMB->t2.TotalParameterCount;3685	pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_ALL_INFO);3686	pSMB->Pad = 0;3687	pSMB->Fid = netfid;3688	inc_rfc1001_len(pSMB, byte_count);3689	pSMB->t2.ByteCount = cpu_to_le16(byte_count);3690 3691	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,3692			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);3693	if (rc) {3694		cifs_dbg(FYI, "Send error in QFileInfo = %d\n", rc);3695	} else {		/* decode response */3696		rc = validate_t2((struct smb_t2_rsp *)pSMBr);3697 3698		if (rc) /* BB add auto retry on EOPNOTSUPP? */3699			rc = -EIO;3700		else if (get_bcc(&pSMBr->hdr) < 40)3701			rc = -EIO;	/* bad smb */3702		else if (pFindData) {3703			__u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);3704			memcpy((char *) pFindData,3705			       (char *) &pSMBr->hdr.Protocol +3706			       data_offset, sizeof(FILE_ALL_INFO));3707		} else3708		    rc = -ENOMEM;3709	}3710	cifs_buf_release(pSMB);3711	if (rc == -EAGAIN)3712		goto QFileInfoRetry;3713 3714	return rc;3715}3716 3717int3718CIFSSMBQPathInfo(const unsigned int xid, struct cifs_tcon *tcon,3719		 const char *search_name, FILE_ALL_INFO *data,3720		 int legacy /* old style infolevel */,3721		 const struct nls_table *nls_codepage, int remap)3722{3723	/* level 263 SMB_QUERY_FILE_ALL_INFO */3724	TRANSACTION2_QPI_REQ *pSMB = NULL;3725	TRANSACTION2_QPI_RSP *pSMBr = NULL;3726	int rc = 0;3727	int bytes_returned;3728	int name_len;3729	__u16 params, byte_count;3730 3731	/* cifs_dbg(FYI, "In QPathInfo path %s\n", search_name); */3732QPathInfoRetry:3733	rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,3734		      (void **) &pSMBr);3735	if (rc)3736		return rc;3737 3738	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {3739		name_len =3740		    cifsConvertToUTF16((__le16 *) pSMB->FileName, search_name,3741				       PATH_MAX, nls_codepage, remap);3742		name_len++;	/* trailing null */3743		name_len *= 2;3744	} else {3745		name_len = copy_path_name(pSMB->FileName, search_name);3746	}3747 3748	params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */;3749	pSMB->TotalDataCount = 0;3750	pSMB->MaxParameterCount = cpu_to_le16(2);3751	/* BB find exact max SMB PDU from sess structure BB */3752	pSMB->MaxDataCount = cpu_to_le16(4000);3753	pSMB->MaxSetupCount = 0;3754	pSMB->Reserved = 0;3755	pSMB->Flags = 0;3756	pSMB->Timeout = 0;3757	pSMB->Reserved2 = 0;3758	pSMB->ParameterOffset = cpu_to_le16(offsetof(3759	struct smb_com_transaction2_qpi_req, InformationLevel) - 4);3760	pSMB->DataCount = 0;3761	pSMB->DataOffset = 0;3762	pSMB->SetupCount = 1;3763	pSMB->Reserved3 = 0;3764	pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);3765	byte_count = params + 1 /* pad */ ;3766	pSMB->TotalParameterCount = cpu_to_le16(params);3767	pSMB->ParameterCount = pSMB->TotalParameterCount;3768	if (legacy)3769		pSMB->InformationLevel = cpu_to_le16(SMB_INFO_STANDARD);3770	else3771		pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_ALL_INFO);3772	pSMB->Reserved4 = 0;3773	inc_rfc1001_len(pSMB, byte_count);3774	pSMB->ByteCount = cpu_to_le16(byte_count);3775 3776	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,3777			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);3778	if (rc) {3779		cifs_dbg(FYI, "Send error in QPathInfo = %d\n", rc);3780	} else {		/* decode response */3781		rc = validate_t2((struct smb_t2_rsp *)pSMBr);3782 3783		if (rc) /* BB add auto retry on EOPNOTSUPP? */3784			rc = -EIO;3785		else if (!legacy && get_bcc(&pSMBr->hdr) < 40)3786			rc = -EIO;	/* bad smb */3787		else if (legacy && get_bcc(&pSMBr->hdr) < 24)3788			rc = -EIO;  /* 24 or 26 expected but we do not read3789					last field */3790		else if (data) {3791			int size;3792			__u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);3793 3794			/*3795			 * On legacy responses we do not read the last field,3796			 * EAsize, fortunately since it varies by subdialect and3797			 * also note it differs on Set vs Get, ie two bytes or 43798			 * bytes depending but we don't care here.3799			 */3800			if (legacy)3801				size = sizeof(FILE_INFO_STANDARD);3802			else3803				size = sizeof(FILE_ALL_INFO);3804			memcpy((char *) data, (char *) &pSMBr->hdr.Protocol +3805			       data_offset, size);3806		} else3807		    rc = -ENOMEM;3808	}3809	cifs_buf_release(pSMB);3810	if (rc == -EAGAIN)3811		goto QPathInfoRetry;3812 3813	return rc;3814}3815 3816int3817CIFSSMBUnixQFileInfo(const unsigned int xid, struct cifs_tcon *tcon,3818		 u16 netfid, FILE_UNIX_BASIC_INFO *pFindData)3819{3820	struct smb_t2_qfi_req *pSMB = NULL;3821	struct smb_t2_qfi_rsp *pSMBr = NULL;3822	int rc = 0;3823	int bytes_returned;3824	__u16 params, byte_count;3825 3826UnixQFileInfoRetry:3827	rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,3828		      (void **) &pSMBr);3829	if (rc)3830		return rc;3831 3832	params = 2 /* level */ + 2 /* fid */;3833	pSMB->t2.TotalDataCount = 0;3834	pSMB->t2.MaxParameterCount = cpu_to_le16(4);3835	/* BB find exact max data count below from sess structure BB */3836	pSMB->t2.MaxDataCount = cpu_to_le16(CIFSMaxBufSize);3837	pSMB->t2.MaxSetupCount = 0;3838	pSMB->t2.Reserved = 0;3839	pSMB->t2.Flags = 0;3840	pSMB->t2.Timeout = 0;3841	pSMB->t2.Reserved2 = 0;3842	pSMB->t2.ParameterOffset = cpu_to_le16(offsetof(struct smb_t2_qfi_req,3843					       Fid) - 4);3844	pSMB->t2.DataCount = 0;3845	pSMB->t2.DataOffset = 0;3846	pSMB->t2.SetupCount = 1;3847	pSMB->t2.Reserved3 = 0;3848	pSMB->t2.SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION);3849	byte_count = params + 1 /* pad */ ;3850	pSMB->t2.TotalParameterCount = cpu_to_le16(params);3851	pSMB->t2.ParameterCount = pSMB->t2.TotalParameterCount;3852	pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC);3853	pSMB->Pad = 0;3854	pSMB->Fid = netfid;3855	inc_rfc1001_len(pSMB, byte_count);3856	pSMB->t2.ByteCount = cpu_to_le16(byte_count);3857 3858	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,3859			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);3860	if (rc) {3861		cifs_dbg(FYI, "Send error in UnixQFileInfo = %d\n", rc);3862	} else {		/* decode response */3863		rc = validate_t2((struct smb_t2_rsp *)pSMBr);3864 3865		if (rc || get_bcc(&pSMBr->hdr) < sizeof(FILE_UNIX_BASIC_INFO)) {3866			cifs_dbg(VFS, "Malformed FILE_UNIX_BASIC_INFO response. Unix Extensions can be disabled on mount by specifying the nosfu mount option.\n");3867			rc = -EIO;	/* bad smb */3868		} else {3869			__u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);3870			memcpy((char *) pFindData,3871			       (char *) &pSMBr->hdr.Protocol +3872			       data_offset,3873			       sizeof(FILE_UNIX_BASIC_INFO));3874		}3875	}3876 3877	cifs_buf_release(pSMB);3878	if (rc == -EAGAIN)3879		goto UnixQFileInfoRetry;3880 3881	return rc;3882}3883 3884int3885CIFSSMBUnixQPathInfo(const unsigned int xid, struct cifs_tcon *tcon,3886		     const unsigned char *searchName,3887		     FILE_UNIX_BASIC_INFO *pFindData,3888		     const struct nls_table *nls_codepage, int remap)3889{3890/* SMB_QUERY_FILE_UNIX_BASIC */3891	TRANSACTION2_QPI_REQ *pSMB = NULL;3892	TRANSACTION2_QPI_RSP *pSMBr = NULL;3893	int rc = 0;3894	int bytes_returned = 0;3895	int name_len;3896	__u16 params, byte_count;3897 3898	cifs_dbg(FYI, "In QPathInfo (Unix) the path %s\n", searchName);3899UnixQPathInfoRetry:3900	rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,3901		      (void **) &pSMBr);3902	if (rc)3903		return rc;3904 3905	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {3906		name_len =3907		    cifsConvertToUTF16((__le16 *) pSMB->FileName, searchName,3908				       PATH_MAX, nls_codepage, remap);3909		name_len++;	/* trailing null */3910		name_len *= 2;3911	} else {3912		name_len = copy_path_name(pSMB->FileName, searchName);3913	}3914 3915	params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */;3916	pSMB->TotalDataCount = 0;3917	pSMB->MaxParameterCount = cpu_to_le16(2);3918	/* BB find exact max SMB PDU from sess structure BB */3919	pSMB->MaxDataCount = cpu_to_le16(4000);3920	pSMB->MaxSetupCount = 0;3921	pSMB->Reserved = 0;3922	pSMB->Flags = 0;3923	pSMB->Timeout = 0;3924	pSMB->Reserved2 = 0;3925	pSMB->ParameterOffset = cpu_to_le16(offsetof(3926	struct smb_com_transaction2_qpi_req, InformationLevel) - 4);3927	pSMB->DataCount = 0;3928	pSMB->DataOffset = 0;3929	pSMB->SetupCount = 1;3930	pSMB->Reserved3 = 0;3931	pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);3932	byte_count = params + 1 /* pad */ ;3933	pSMB->TotalParameterCount = cpu_to_le16(params);3934	pSMB->ParameterCount = pSMB->TotalParameterCount;3935	pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC);3936	pSMB->Reserved4 = 0;3937	inc_rfc1001_len(pSMB, byte_count);3938	pSMB->ByteCount = cpu_to_le16(byte_count);3939 3940	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,3941			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);3942	if (rc) {3943		cifs_dbg(FYI, "Send error in UnixQPathInfo = %d\n", rc);3944	} else {		/* decode response */3945		rc = validate_t2((struct smb_t2_rsp *)pSMBr);3946 3947		if (rc || get_bcc(&pSMBr->hdr) < sizeof(FILE_UNIX_BASIC_INFO)) {3948			cifs_dbg(VFS, "Malformed FILE_UNIX_BASIC_INFO response. Unix Extensions can be disabled on mount by specifying the nosfu mount option.\n");3949			rc = -EIO;	/* bad smb */3950		} else {3951			__u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);3952			memcpy((char *) pFindData,3953			       (char *) &pSMBr->hdr.Protocol +3954			       data_offset,3955			       sizeof(FILE_UNIX_BASIC_INFO));3956		}3957	}3958	cifs_buf_release(pSMB);3959	if (rc == -EAGAIN)3960		goto UnixQPathInfoRetry;3961 3962	return rc;3963}3964 3965/* xid, tcon, searchName and codepage are input parms, rest are returned */3966int3967CIFSFindFirst(const unsigned int xid, struct cifs_tcon *tcon,3968	      const char *searchName, struct cifs_sb_info *cifs_sb,3969	      __u16 *pnetfid, __u16 search_flags,3970	      struct cifs_search_info *psrch_inf, bool msearch)3971{3972/* level 257 SMB_ */3973	TRANSACTION2_FFIRST_REQ *pSMB = NULL;3974	TRANSACTION2_FFIRST_RSP *pSMBr = NULL;3975	T2_FFIRST_RSP_PARMS *parms;3976	struct nls_table *nls_codepage;3977	unsigned int lnoff;3978	__u16 params, byte_count;3979	int bytes_returned = 0;3980	int name_len, remap;3981	int rc = 0;3982 3983	cifs_dbg(FYI, "In FindFirst for %s\n", searchName);3984 3985findFirstRetry:3986	rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,3987		      (void **) &pSMBr);3988	if (rc)3989		return rc;3990 3991	nls_codepage = cifs_sb->local_nls;3992	remap = cifs_remap(cifs_sb);3993 3994	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {3995		name_len =3996		    cifsConvertToUTF16((__le16 *) pSMB->FileName, searchName,3997				       PATH_MAX, nls_codepage, remap);3998		/* We can not add the asterisk earlier in case3999		it got remapped to 0xF03A as if it were part of the4000		directory name instead of a wildcard */4001		name_len *= 2;4002		if (msearch) {4003			pSMB->FileName[name_len] = CIFS_DIR_SEP(cifs_sb);4004			pSMB->FileName[name_len+1] = 0;4005			pSMB->FileName[name_len+2] = '*';4006			pSMB->FileName[name_len+3] = 0;4007			name_len += 4; /* now the trailing null */4008			/* null terminate just in case */4009			pSMB->FileName[name_len] = 0;4010			pSMB->FileName[name_len+1] = 0;4011			name_len += 2;4012		}4013	} else {4014		name_len = copy_path_name(pSMB->FileName, searchName);4015		if (msearch) {4016			if (WARN_ON_ONCE(name_len > PATH_MAX-2))4017				name_len = PATH_MAX-2;4018			/* overwrite nul byte */4019			pSMB->FileName[name_len-1] = CIFS_DIR_SEP(cifs_sb);4020			pSMB->FileName[name_len] = '*';4021			pSMB->FileName[name_len+1] = 0;4022			name_len += 2;4023		}4024	}4025 4026	params = 12 + name_len /* includes null */ ;4027	pSMB->TotalDataCount = 0;	/* no EAs */4028	pSMB->MaxParameterCount = cpu_to_le16(10);4029	pSMB->MaxDataCount = cpu_to_le16(CIFSMaxBufSize & 0xFFFFFF00);4030	pSMB->MaxSetupCount = 0;4031	pSMB->Reserved = 0;4032	pSMB->Flags = 0;4033	pSMB->Timeout = 0;4034	pSMB->Reserved2 = 0;4035	byte_count = params + 1 /* pad */ ;4036	pSMB->TotalParameterCount = cpu_to_le16(params);4037	pSMB->ParameterCount = pSMB->TotalParameterCount;4038	pSMB->ParameterOffset = cpu_to_le16(4039	      offsetof(struct smb_com_transaction2_ffirst_req, SearchAttributes)4040		- 4);4041	pSMB->DataCount = 0;4042	pSMB->DataOffset = 0;4043	pSMB->SetupCount = 1;	/* one byte, no need to make endian neutral */4044	pSMB->Reserved3 = 0;4045	pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_FIRST);4046	pSMB->SearchAttributes =4047	    cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |4048			ATTR_DIRECTORY);4049	pSMB->SearchCount = cpu_to_le16(CIFSMaxBufSize/sizeof(FILE_UNIX_INFO));4050	pSMB->SearchFlags = cpu_to_le16(search_flags);4051	pSMB->InformationLevel = cpu_to_le16(psrch_inf->info_level);4052 4053	/* BB what should we set StorageType to? Does it matter? BB */4054	pSMB->SearchStorageType = 0;4055	inc_rfc1001_len(pSMB, byte_count);4056	pSMB->ByteCount = cpu_to_le16(byte_count);4057 4058	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,4059			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);4060	cifs_stats_inc(&tcon->stats.cifs_stats.num_ffirst);4061 4062	if (rc) {4063		/*4064		 * BB: add logic to retry regular search if Unix search rejected4065		 * unexpectedly by server.4066		 */4067		/* BB: add code to handle unsupported level rc */4068		cifs_dbg(FYI, "Error in FindFirst = %d\n", rc);4069		cifs_buf_release(pSMB);4070		/*4071		 * BB: eventually could optimize out free and realloc of buf for4072		 * this case.4073		 */4074		if (rc == -EAGAIN)4075			goto findFirstRetry;4076		return rc;4077	}4078	/* decode response */4079	rc = validate_t2((struct smb_t2_rsp *)pSMBr);4080	if (rc) {4081		cifs_buf_release(pSMB);4082		return rc;4083	}4084 4085	psrch_inf->unicode = !!(pSMBr->hdr.Flags2 & SMBFLG2_UNICODE);4086	psrch_inf->ntwrk_buf_start = (char *)pSMBr;4087	psrch_inf->smallBuf = false;4088	psrch_inf->srch_entries_start = (char *)&pSMBr->hdr.Protocol +4089		le16_to_cpu(pSMBr->t2.DataOffset);4090 4091	parms = (T2_FFIRST_RSP_PARMS *)((char *)&pSMBr->hdr.Protocol +4092					le16_to_cpu(pSMBr->t2.ParameterOffset));4093	psrch_inf->endOfSearch = !!parms->EndofSearch;4094 4095	psrch_inf->entries_in_buffer = le16_to_cpu(parms->SearchCount);4096	psrch_inf->index_of_last_entry = 2 /* skip . and .. */ +4097		psrch_inf->entries_in_buffer;4098	lnoff = le16_to_cpu(parms->LastNameOffset);4099	if (CIFSMaxBufSize < lnoff) {4100		cifs_dbg(VFS, "ignoring corrupt resume name\n");4101		psrch_inf->last_entry = NULL;4102	} else {4103		psrch_inf->last_entry = psrch_inf->srch_entries_start + lnoff;4104		if (pnetfid)4105			*pnetfid = parms->SearchHandle;4106	}4107	return 0;4108}4109 4110int CIFSFindNext(const unsigned int xid, struct cifs_tcon *tcon,4111		 __u16 searchHandle, __u16 search_flags,4112		 struct cifs_search_info *psrch_inf)4113{4114	TRANSACTION2_FNEXT_REQ *pSMB = NULL;4115	TRANSACTION2_FNEXT_RSP *pSMBr = NULL;4116	T2_FNEXT_RSP_PARMS *parms;4117	unsigned int name_len;4118	unsigned int lnoff;4119	__u16 params, byte_count;4120	char *response_data;4121	int bytes_returned;4122	int rc = 0;4123 4124	cifs_dbg(FYI, "In FindNext\n");4125 4126	if (psrch_inf->endOfSearch)4127		return -ENOENT;4128 4129	rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,4130		(void **) &pSMBr);4131	if (rc)4132		return rc;4133 4134	params = 14; /* includes 2 bytes of null string, converted to LE below*/4135	byte_count = 0;4136	pSMB->TotalDataCount = 0;       /* no EAs */4137	pSMB->MaxParameterCount = cpu_to_le16(8);4138	pSMB->MaxDataCount = cpu_to_le16(CIFSMaxBufSize & 0xFFFFFF00);4139	pSMB->MaxSetupCount = 0;4140	pSMB->Reserved = 0;4141	pSMB->Flags = 0;4142	pSMB->Timeout = 0;4143	pSMB->Reserved2 = 0;4144	pSMB->ParameterOffset =  cpu_to_le16(4145	      offsetof(struct smb_com_transaction2_fnext_req,SearchHandle) - 4);4146	pSMB->DataCount = 0;4147	pSMB->DataOffset = 0;4148	pSMB->SetupCount = 1;4149	pSMB->Reserved3 = 0;4150	pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_NEXT);4151	pSMB->SearchHandle = searchHandle;      /* always kept as le */4152	pSMB->SearchCount =4153		cpu_to_le16(CIFSMaxBufSize / sizeof(FILE_UNIX_INFO));4154	pSMB->InformationLevel = cpu_to_le16(psrch_inf->info_level);4155	pSMB->ResumeKey = psrch_inf->resume_key;4156	pSMB->SearchFlags = cpu_to_le16(search_flags);4157 4158	name_len = psrch_inf->resume_name_len;4159	params += name_len;4160	if (name_len < PATH_MAX) {4161		memcpy(pSMB->ResumeFileName, psrch_inf->presume_name, name_len);4162		byte_count += name_len;4163		/* 14 byte parm len above enough for 2 byte null terminator */4164		pSMB->ResumeFileName[name_len] = 0;4165		pSMB->ResumeFileName[name_len+1] = 0;4166	} else {4167		cifs_buf_release(pSMB);4168		return -EINVAL;4169	}4170	byte_count = params + 1 /* pad */ ;4171	pSMB->TotalParameterCount = cpu_to_le16(params);4172	pSMB->ParameterCount = pSMB->TotalParameterCount;4173	inc_rfc1001_len(pSMB, byte_count);4174	pSMB->ByteCount = cpu_to_le16(byte_count);4175 4176	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,4177			(struct smb_hdr *) pSMBr, &bytes_returned, 0);4178	cifs_stats_inc(&tcon->stats.cifs_stats.num_fnext);4179 4180	if (rc) {4181		cifs_buf_release(pSMB);4182		if (rc == -EBADF) {4183			psrch_inf->endOfSearch = true;4184			rc = 0; /* search probably was closed at end of search*/4185		} else {4186			cifs_dbg(FYI, "FindNext returned = %d\n", rc);4187		}4188		return rc;4189	}4190 4191	/* decode response */4192	rc = validate_t2((struct smb_t2_rsp *)pSMBr);4193	if (rc) {4194		cifs_buf_release(pSMB);4195		return rc;4196	}4197	/* BB fixme add lock for file (srch_info) struct here */4198	psrch_inf->unicode = !!(pSMBr->hdr.Flags2 & SMBFLG2_UNICODE);4199	response_data = (char *)&pSMBr->hdr.Protocol +4200		le16_to_cpu(pSMBr->t2.ParameterOffset);4201	parms = (T2_FNEXT_RSP_PARMS *)response_data;4202	response_data = (char *)&pSMBr->hdr.Protocol +4203		le16_to_cpu(pSMBr->t2.DataOffset);4204 4205	if (psrch_inf->smallBuf)4206		cifs_small_buf_release(psrch_inf->ntwrk_buf_start);4207	else4208		cifs_buf_release(psrch_inf->ntwrk_buf_start);4209 4210	psrch_inf->srch_entries_start = response_data;4211	psrch_inf->ntwrk_buf_start = (char *)pSMB;4212	psrch_inf->smallBuf = false;4213	psrch_inf->endOfSearch = !!parms->EndofSearch;4214	psrch_inf->entries_in_buffer = le16_to_cpu(parms->SearchCount);4215	psrch_inf->index_of_last_entry += psrch_inf->entries_in_buffer;4216	lnoff = le16_to_cpu(parms->LastNameOffset);4217	if (CIFSMaxBufSize < lnoff) {4218		cifs_dbg(VFS, "ignoring corrupt resume name\n");4219		psrch_inf->last_entry = NULL;4220	} else {4221		psrch_inf->last_entry =4222			psrch_inf->srch_entries_start + lnoff;4223	}4224	/* BB fixme add unlock here */4225 4226	/*4227	 * BB: On error, should we leave previous search buf4228	 * (and count and last entry fields) intact or free the previous one?4229	 *4230	 * Note: On -EAGAIN error only caller can retry on handle based calls4231	 * since file handle passed in no longer valid.4232	 */4233	return 0;4234}4235 4236int4237CIFSFindClose(const unsigned int xid, struct cifs_tcon *tcon,4238	      const __u16 searchHandle)4239{4240	int rc = 0;4241	FINDCLOSE_REQ *pSMB = NULL;4242 4243	cifs_dbg(FYI, "In CIFSSMBFindClose\n");4244	rc = small_smb_init(SMB_COM_FIND_CLOSE2, 1, tcon, (void **)&pSMB);4245 4246	/* no sense returning error if session restarted4247		as file handle has been closed */4248	if (rc == -EAGAIN)4249		return 0;4250	if (rc)4251		return rc;4252 4253	pSMB->FileID = searchHandle;4254	pSMB->ByteCount = 0;4255	rc = SendReceiveNoRsp(xid, tcon->ses, (char *) pSMB, 0);4256	cifs_small_buf_release(pSMB);4257	if (rc)4258		cifs_dbg(VFS, "Send error in FindClose = %d\n", rc);4259 4260	cifs_stats_inc(&tcon->stats.cifs_stats.num_fclose);4261 4262	/* Since session is dead, search handle closed on server already */4263	if (rc == -EAGAIN)4264		rc = 0;4265 4266	return rc;4267}4268 4269int4270CIFSGetSrvInodeNumber(const unsigned int xid, struct cifs_tcon *tcon,4271		      const char *search_name, __u64 *inode_number,4272		      const struct nls_table *nls_codepage, int remap)4273{4274	int rc = 0;4275	TRANSACTION2_QPI_REQ *pSMB = NULL;4276	TRANSACTION2_QPI_RSP *pSMBr = NULL;4277	int name_len, bytes_returned;4278	__u16 params, byte_count;4279 4280	cifs_dbg(FYI, "In GetSrvInodeNum for %s\n", search_name);4281	if (tcon == NULL)4282		return -ENODEV;4283 4284GetInodeNumberRetry:4285	rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,4286		      (void **) &pSMBr);4287	if (rc)4288		return rc;4289 4290	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {4291		name_len =4292			cifsConvertToUTF16((__le16 *) pSMB->FileName,4293					   search_name, PATH_MAX, nls_codepage,4294					   remap);4295		name_len++;     /* trailing null */4296		name_len *= 2;4297	} else {4298		name_len = copy_path_name(pSMB->FileName, search_name);4299	}4300 4301	params = 2 /* level */  + 4 /* rsrvd */  + name_len /* incl null */ ;4302	pSMB->TotalDataCount = 0;4303	pSMB->MaxParameterCount = cpu_to_le16(2);4304	/* BB find exact max data count below from sess structure BB */4305	pSMB->MaxDataCount = cpu_to_le16(4000);4306	pSMB->MaxSetupCount = 0;4307	pSMB->Reserved = 0;4308	pSMB->Flags = 0;4309	pSMB->Timeout = 0;4310	pSMB->Reserved2 = 0;4311	pSMB->ParameterOffset = cpu_to_le16(offsetof(4312		struct smb_com_transaction2_qpi_req, InformationLevel) - 4);4313	pSMB->DataCount = 0;4314	pSMB->DataOffset = 0;4315	pSMB->SetupCount = 1;4316	pSMB->Reserved3 = 0;4317	pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);4318	byte_count = params + 1 /* pad */ ;4319	pSMB->TotalParameterCount = cpu_to_le16(params);4320	pSMB->ParameterCount = pSMB->TotalParameterCount;4321	pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_INTERNAL_INFO);4322	pSMB->Reserved4 = 0;4323	inc_rfc1001_len(pSMB, byte_count);4324	pSMB->ByteCount = cpu_to_le16(byte_count);4325 4326	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,4327		(struct smb_hdr *) pSMBr, &bytes_returned, 0);4328	if (rc) {4329		cifs_dbg(FYI, "error %d in QueryInternalInfo\n", rc);4330	} else {4331		/* decode response */4332		rc = validate_t2((struct smb_t2_rsp *)pSMBr);4333		/* BB also check enough total bytes returned */4334		if (rc || get_bcc(&pSMBr->hdr) < 2)4335			/* If rc should we check for EOPNOSUPP and4336			disable the srvino flag? or in caller? */4337			rc = -EIO;      /* bad smb */4338		else {4339			__u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);4340			__u16 count = le16_to_cpu(pSMBr->t2.DataCount);4341			struct file_internal_info *pfinfo;4342			/* BB Do we need a cast or hash here ? */4343			if (count < 8) {4344				cifs_dbg(FYI, "Invalid size ret in QryIntrnlInf\n");4345				rc = -EIO;4346				goto GetInodeNumOut;4347			}4348			pfinfo = (struct file_internal_info *)4349				(data_offset + (char *) &pSMBr->hdr.Protocol);4350			*inode_number = le64_to_cpu(pfinfo->UniqueId);4351		}4352	}4353GetInodeNumOut:4354	cifs_buf_release(pSMB);4355	if (rc == -EAGAIN)4356		goto GetInodeNumberRetry;4357	return rc;4358}4359 4360int4361CIFSGetDFSRefer(const unsigned int xid, struct cifs_ses *ses,4362		const char *search_name, struct dfs_info3_param **target_nodes,4363		unsigned int *num_of_nodes,4364		const struct nls_table *nls_codepage, int remap)4365{4366/* TRANS2_GET_DFS_REFERRAL */4367	TRANSACTION2_GET_DFS_REFER_REQ *pSMB = NULL;4368	TRANSACTION2_GET_DFS_REFER_RSP *pSMBr = NULL;4369	int rc = 0;4370	int bytes_returned;4371	int name_len;4372	__u16 params, byte_count;4373	*num_of_nodes = 0;4374	*target_nodes = NULL;4375 4376	cifs_dbg(FYI, "In GetDFSRefer the path %s\n", search_name);4377	if (ses == NULL || ses->tcon_ipc == NULL)4378		return -ENODEV;4379 4380getDFSRetry:4381	/*4382	 * Use smb_init_no_reconnect() instead of smb_init() as4383	 * CIFSGetDFSRefer() may be called from cifs_reconnect_tcon() and thus4384	 * causing an infinite recursion.4385	 */4386	rc = smb_init_no_reconnect(SMB_COM_TRANSACTION2, 15, ses->tcon_ipc,4387				   (void **)&pSMB, (void **)&pSMBr);4388	if (rc)4389		return rc;4390 4391	/* server pointer checked in called function,4392	but should never be null here anyway */4393	pSMB->hdr.Mid = get_next_mid(ses->server);4394	pSMB->hdr.Tid = ses->tcon_ipc->tid;4395	pSMB->hdr.Uid = ses->Suid;4396	if (ses->capabilities & CAP_STATUS32)4397		pSMB->hdr.Flags2 |= SMBFLG2_ERR_STATUS;4398	if (ses->capabilities & CAP_DFS)4399		pSMB->hdr.Flags2 |= SMBFLG2_DFS;4400 4401	if (ses->capabilities & CAP_UNICODE) {4402		pSMB->hdr.Flags2 |= SMBFLG2_UNICODE;4403		name_len =4404		    cifsConvertToUTF16((__le16 *) pSMB->RequestFileName,4405				       search_name, PATH_MAX, nls_codepage,4406				       remap);4407		name_len++;	/* trailing null */4408		name_len *= 2;4409	} else {	/* BB improve the check for buffer overruns BB */4410		name_len = copy_path_name(pSMB->RequestFileName, search_name);4411	}4412 4413	if (ses->server->sign)4414		pSMB->hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE;4415 4416	pSMB->hdr.Uid = ses->Suid;4417 4418	params = 2 /* level */  + name_len /*includes null */ ;4419	pSMB->TotalDataCount = 0;4420	pSMB->DataCount = 0;4421	pSMB->DataOffset = 0;4422	pSMB->MaxParameterCount = 0;4423	/* BB find exact max SMB PDU from sess structure BB */4424	pSMB->MaxDataCount = cpu_to_le16(4000);4425	pSMB->MaxSetupCount = 0;4426	pSMB->Reserved = 0;4427	pSMB->Flags = 0;4428	pSMB->Timeout = 0;4429	pSMB->Reserved2 = 0;4430	pSMB->ParameterOffset = cpu_to_le16(offsetof(4431	  struct smb_com_transaction2_get_dfs_refer_req, MaxReferralLevel) - 4);4432	pSMB->SetupCount = 1;4433	pSMB->Reserved3 = 0;4434	pSMB->SubCommand = cpu_to_le16(TRANS2_GET_DFS_REFERRAL);4435	byte_count = params + 3 /* pad */ ;4436	pSMB->ParameterCount = cpu_to_le16(params);4437	pSMB->TotalParameterCount = pSMB->ParameterCount;4438	pSMB->MaxReferralLevel = cpu_to_le16(3);4439	inc_rfc1001_len(pSMB, byte_count);4440	pSMB->ByteCount = cpu_to_le16(byte_count);4441 4442	rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB,4443			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);4444	if (rc) {4445		cifs_dbg(FYI, "Send error in GetDFSRefer = %d\n", rc);4446		goto GetDFSRefExit;4447	}4448	rc = validate_t2((struct smb_t2_rsp *)pSMBr);4449 4450	/* BB Also check if enough total bytes returned? */4451	if (rc || get_bcc(&pSMBr->hdr) < 17) {4452		rc = -EIO;      /* bad smb */4453		goto GetDFSRefExit;4454	}4455 4456	cifs_dbg(FYI, "Decoding GetDFSRefer response BCC: %d  Offset %d\n",4457		 get_bcc(&pSMBr->hdr), le16_to_cpu(pSMBr->t2.DataOffset));4458 4459	/* parse returned result into more usable form */4460	rc = parse_dfs_referrals(&pSMBr->dfs_data,4461				 le16_to_cpu(pSMBr->t2.DataCount),4462				 num_of_nodes, target_nodes, nls_codepage,4463				 remap, search_name,4464				 (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) != 0);4465 4466GetDFSRefExit:4467	cifs_buf_release(pSMB);4468 4469	if (rc == -EAGAIN)4470		goto getDFSRetry;4471 4472	return rc;4473}4474 4475/* Query File System Info such as free space to old servers such as Win 9x */4476int4477SMBOldQFSInfo(const unsigned int xid, struct cifs_tcon *tcon,4478	      struct kstatfs *FSData)4479{4480/* level 0x01 SMB_QUERY_FILE_SYSTEM_INFO */4481	TRANSACTION2_QFSI_REQ *pSMB = NULL;4482	TRANSACTION2_QFSI_RSP *pSMBr = NULL;4483	FILE_SYSTEM_ALLOC_INFO *response_data;4484	int rc = 0;4485	int bytes_returned = 0;4486	__u16 params, byte_count;4487 4488	cifs_dbg(FYI, "OldQFSInfo\n");4489oldQFSInfoRetry:4490	rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,4491		(void **) &pSMBr);4492	if (rc)4493		return rc;4494 4495	params = 2;     /* level */4496	pSMB->TotalDataCount = 0;4497	pSMB->MaxParameterCount = cpu_to_le16(2);4498	pSMB->MaxDataCount = cpu_to_le16(1000);4499	pSMB->MaxSetupCount = 0;4500	pSMB->Reserved = 0;4501	pSMB->Flags = 0;4502	pSMB->Timeout = 0;4503	pSMB->Reserved2 = 0;4504	byte_count = params + 1 /* pad */ ;4505	pSMB->TotalParameterCount = cpu_to_le16(params);4506	pSMB->ParameterCount = pSMB->TotalParameterCount;4507	pSMB->ParameterOffset = cpu_to_le16(offsetof(4508	struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);4509	pSMB->DataCount = 0;4510	pSMB->DataOffset = 0;4511	pSMB->SetupCount = 1;4512	pSMB->Reserved3 = 0;4513	pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);4514	pSMB->InformationLevel = cpu_to_le16(SMB_INFO_ALLOCATION);4515	inc_rfc1001_len(pSMB, byte_count);4516	pSMB->ByteCount = cpu_to_le16(byte_count);4517 4518	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,4519		(struct smb_hdr *) pSMBr, &bytes_returned, 0);4520	if (rc) {4521		cifs_dbg(FYI, "Send error in QFSInfo = %d\n", rc);4522	} else {                /* decode response */4523		rc = validate_t2((struct smb_t2_rsp *)pSMBr);4524 4525		if (rc || get_bcc(&pSMBr->hdr) < 18)4526			rc = -EIO;      /* bad smb */4527		else {4528			__u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);4529			cifs_dbg(FYI, "qfsinf resp BCC: %d  Offset %d\n",4530				 get_bcc(&pSMBr->hdr), data_offset);4531 4532			response_data = (FILE_SYSTEM_ALLOC_INFO *)4533				(((char *) &pSMBr->hdr.Protocol) + data_offset);4534			FSData->f_bsize =4535				le16_to_cpu(response_data->BytesPerSector) *4536				le32_to_cpu(response_data->4537					SectorsPerAllocationUnit);4538			/*4539			 * much prefer larger but if server doesn't report4540			 * a valid size than 4K is a reasonable minimum4541			 */4542			if (FSData->f_bsize < 512)4543				FSData->f_bsize = 4096;4544 4545			FSData->f_blocks =4546			       le32_to_cpu(response_data->TotalAllocationUnits);4547			FSData->f_bfree = FSData->f_bavail =4548				le32_to_cpu(response_data->FreeAllocationUnits);4549			cifs_dbg(FYI, "Blocks: %lld  Free: %lld Block size %ld\n",4550				 (unsigned long long)FSData->f_blocks,4551				 (unsigned long long)FSData->f_bfree,4552				 FSData->f_bsize);4553		}4554	}4555	cifs_buf_release(pSMB);4556 4557	if (rc == -EAGAIN)4558		goto oldQFSInfoRetry;4559 4560	return rc;4561}4562 4563int4564CIFSSMBQFSInfo(const unsigned int xid, struct cifs_tcon *tcon,4565	       struct kstatfs *FSData)4566{4567/* level 0x103 SMB_QUERY_FILE_SYSTEM_INFO */4568	TRANSACTION2_QFSI_REQ *pSMB = NULL;4569	TRANSACTION2_QFSI_RSP *pSMBr = NULL;4570	FILE_SYSTEM_INFO *response_data;4571	int rc = 0;4572	int bytes_returned = 0;4573	__u16 params, byte_count;4574 4575	cifs_dbg(FYI, "In QFSInfo\n");4576QFSInfoRetry:4577	rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,4578		      (void **) &pSMBr);4579	if (rc)4580		return rc;4581 4582	params = 2;	/* level */4583	pSMB->TotalDataCount = 0;4584	pSMB->MaxParameterCount = cpu_to_le16(2);4585	pSMB->MaxDataCount = cpu_to_le16(1000);4586	pSMB->MaxSetupCount = 0;4587	pSMB->Reserved = 0;4588	pSMB->Flags = 0;4589	pSMB->Timeout = 0;4590	pSMB->Reserved2 = 0;4591	byte_count = params + 1 /* pad */ ;4592	pSMB->TotalParameterCount = cpu_to_le16(params);4593	pSMB->ParameterCount = pSMB->TotalParameterCount;4594	pSMB->ParameterOffset = cpu_to_le16(offsetof(4595		struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);4596	pSMB->DataCount = 0;4597	pSMB->DataOffset = 0;4598	pSMB->SetupCount = 1;4599	pSMB->Reserved3 = 0;4600	pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);4601	pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_SIZE_INFO);4602	inc_rfc1001_len(pSMB, byte_count);4603	pSMB->ByteCount = cpu_to_le16(byte_count);4604 4605	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,4606			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);4607	if (rc) {4608		cifs_dbg(FYI, "Send error in QFSInfo = %d\n", rc);4609	} else {		/* decode response */4610		rc = validate_t2((struct smb_t2_rsp *)pSMBr);4611 4612		if (rc || get_bcc(&pSMBr->hdr) < 24)4613			rc = -EIO;	/* bad smb */4614		else {4615			__u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);4616 4617			response_data =4618			    (FILE_SYSTEM_INFO4619			     *) (((char *) &pSMBr->hdr.Protocol) +4620				 data_offset);4621			FSData->f_bsize =4622			    le32_to_cpu(response_data->BytesPerSector) *4623			    le32_to_cpu(response_data->4624					SectorsPerAllocationUnit);4625			/*4626			 * much prefer larger but if server doesn't report4627			 * a valid size than 4K is a reasonable minimum4628			 */4629			if (FSData->f_bsize < 512)4630				FSData->f_bsize = 4096;4631 4632			FSData->f_blocks =4633			    le64_to_cpu(response_data->TotalAllocationUnits);4634			FSData->f_bfree = FSData->f_bavail =4635			    le64_to_cpu(response_data->FreeAllocationUnits);4636			cifs_dbg(FYI, "Blocks: %lld  Free: %lld Block size %ld\n",4637				 (unsigned long long)FSData->f_blocks,4638				 (unsigned long long)FSData->f_bfree,4639				 FSData->f_bsize);4640		}4641	}4642	cifs_buf_release(pSMB);4643 4644	if (rc == -EAGAIN)4645		goto QFSInfoRetry;4646 4647	return rc;4648}4649 4650int4651CIFSSMBQFSAttributeInfo(const unsigned int xid, struct cifs_tcon *tcon)4652{4653/* level 0x105  SMB_QUERY_FILE_SYSTEM_INFO */4654	TRANSACTION2_QFSI_REQ *pSMB = NULL;4655	TRANSACTION2_QFSI_RSP *pSMBr = NULL;4656	FILE_SYSTEM_ATTRIBUTE_INFO *response_data;4657	int rc = 0;4658	int bytes_returned = 0;4659	__u16 params, byte_count;4660 4661	cifs_dbg(FYI, "In QFSAttributeInfo\n");4662QFSAttributeRetry:4663	rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,4664		      (void **) &pSMBr);4665	if (rc)4666		return rc;4667 4668	params = 2;	/* level */4669	pSMB->TotalDataCount = 0;4670	pSMB->MaxParameterCount = cpu_to_le16(2);4671	/* BB find exact max SMB PDU from sess structure BB */4672	pSMB->MaxDataCount = cpu_to_le16(1000);4673	pSMB->MaxSetupCount = 0;4674	pSMB->Reserved = 0;4675	pSMB->Flags = 0;4676	pSMB->Timeout = 0;4677	pSMB->Reserved2 = 0;4678	byte_count = params + 1 /* pad */ ;4679	pSMB->TotalParameterCount = cpu_to_le16(params);4680	pSMB->ParameterCount = pSMB->TotalParameterCount;4681	pSMB->ParameterOffset = cpu_to_le16(offsetof(4682		struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);4683	pSMB->DataCount = 0;4684	pSMB->DataOffset = 0;4685	pSMB->SetupCount = 1;4686	pSMB->Reserved3 = 0;4687	pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);4688	pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_ATTRIBUTE_INFO);4689	inc_rfc1001_len(pSMB, byte_count);4690	pSMB->ByteCount = cpu_to_le16(byte_count);4691 4692	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,4693			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);4694	if (rc) {4695		cifs_dbg(VFS, "Send error in QFSAttributeInfo = %d\n", rc);4696	} else {		/* decode response */4697		rc = validate_t2((struct smb_t2_rsp *)pSMBr);4698 4699		if (rc || get_bcc(&pSMBr->hdr) < 13) {4700			/* BB also check if enough bytes returned */4701			rc = -EIO;	/* bad smb */4702		} else {4703			__u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);4704			response_data =4705			    (FILE_SYSTEM_ATTRIBUTE_INFO4706			     *) (((char *) &pSMBr->hdr.Protocol) +4707				 data_offset);4708			memcpy(&tcon->fsAttrInfo, response_data,4709			       sizeof(FILE_SYSTEM_ATTRIBUTE_INFO));4710		}4711	}4712	cifs_buf_release(pSMB);4713 4714	if (rc == -EAGAIN)4715		goto QFSAttributeRetry;4716 4717	return rc;4718}4719 4720int4721CIFSSMBQFSDeviceInfo(const unsigned int xid, struct cifs_tcon *tcon)4722{4723/* level 0x104 SMB_QUERY_FILE_SYSTEM_INFO */4724	TRANSACTION2_QFSI_REQ *pSMB = NULL;4725	TRANSACTION2_QFSI_RSP *pSMBr = NULL;4726	FILE_SYSTEM_DEVICE_INFO *response_data;4727	int rc = 0;4728	int bytes_returned = 0;4729	__u16 params, byte_count;4730 4731	cifs_dbg(FYI, "In QFSDeviceInfo\n");4732QFSDeviceRetry:4733	rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,4734		      (void **) &pSMBr);4735	if (rc)4736		return rc;4737 4738	params = 2;	/* level */4739	pSMB->TotalDataCount = 0;4740	pSMB->MaxParameterCount = cpu_to_le16(2);4741	/* BB find exact max SMB PDU from sess structure BB */4742	pSMB->MaxDataCount = cpu_to_le16(1000);4743	pSMB->MaxSetupCount = 0;4744	pSMB->Reserved = 0;4745	pSMB->Flags = 0;4746	pSMB->Timeout = 0;4747	pSMB->Reserved2 = 0;4748	byte_count = params + 1 /* pad */ ;4749	pSMB->TotalParameterCount = cpu_to_le16(params);4750	pSMB->ParameterCount = pSMB->TotalParameterCount;4751	pSMB->ParameterOffset = cpu_to_le16(offsetof(4752		struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);4753 4754	pSMB->DataCount = 0;4755	pSMB->DataOffset = 0;4756	pSMB->SetupCount = 1;4757	pSMB->Reserved3 = 0;4758	pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);4759	pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_DEVICE_INFO);4760	inc_rfc1001_len(pSMB, byte_count);4761	pSMB->ByteCount = cpu_to_le16(byte_count);4762 4763	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,4764			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);4765	if (rc) {4766		cifs_dbg(FYI, "Send error in QFSDeviceInfo = %d\n", rc);4767	} else {		/* decode response */4768		rc = validate_t2((struct smb_t2_rsp *)pSMBr);4769 4770		if (rc || get_bcc(&pSMBr->hdr) <4771			  sizeof(FILE_SYSTEM_DEVICE_INFO))4772			rc = -EIO;	/* bad smb */4773		else {4774			__u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);4775			response_data =4776			    (FILE_SYSTEM_DEVICE_INFO *)4777				(((char *) &pSMBr->hdr.Protocol) +4778				 data_offset);4779			memcpy(&tcon->fsDevInfo, response_data,4780			       sizeof(FILE_SYSTEM_DEVICE_INFO));4781		}4782	}4783	cifs_buf_release(pSMB);4784 4785	if (rc == -EAGAIN)4786		goto QFSDeviceRetry;4787 4788	return rc;4789}4790 4791int4792CIFSSMBQFSUnixInfo(const unsigned int xid, struct cifs_tcon *tcon)4793{4794/* level 0x200  SMB_QUERY_CIFS_UNIX_INFO */4795	TRANSACTION2_QFSI_REQ *pSMB = NULL;4796	TRANSACTION2_QFSI_RSP *pSMBr = NULL;4797	FILE_SYSTEM_UNIX_INFO *response_data;4798	int rc = 0;4799	int bytes_returned = 0;4800	__u16 params, byte_count;4801 4802	cifs_dbg(FYI, "In QFSUnixInfo\n");4803QFSUnixRetry:4804	rc = smb_init_no_reconnect(SMB_COM_TRANSACTION2, 15, tcon,4805				   (void **) &pSMB, (void **) &pSMBr);4806	if (rc)4807		return rc;4808 4809	params = 2;	/* level */4810	pSMB->TotalDataCount = 0;4811	pSMB->DataCount = 0;4812	pSMB->DataOffset = 0;4813	pSMB->MaxParameterCount = cpu_to_le16(2);4814	/* BB find exact max SMB PDU from sess structure BB */4815	pSMB->MaxDataCount = cpu_to_le16(100);4816	pSMB->MaxSetupCount = 0;4817	pSMB->Reserved = 0;4818	pSMB->Flags = 0;4819	pSMB->Timeout = 0;4820	pSMB->Reserved2 = 0;4821	byte_count = params + 1 /* pad */ ;4822	pSMB->ParameterCount = cpu_to_le16(params);4823	pSMB->TotalParameterCount = pSMB->ParameterCount;4824	pSMB->ParameterOffset = cpu_to_le16(offsetof(struct4825			smb_com_transaction2_qfsi_req, InformationLevel) - 4);4826	pSMB->SetupCount = 1;4827	pSMB->Reserved3 = 0;4828	pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);4829	pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_CIFS_UNIX_INFO);4830	inc_rfc1001_len(pSMB, byte_count);4831	pSMB->ByteCount = cpu_to_le16(byte_count);4832 4833	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,4834			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);4835	if (rc) {4836		cifs_dbg(VFS, "Send error in QFSUnixInfo = %d\n", rc);4837	} else {		/* decode response */4838		rc = validate_t2((struct smb_t2_rsp *)pSMBr);4839 4840		if (rc || get_bcc(&pSMBr->hdr) < 13) {4841			rc = -EIO;	/* bad smb */4842		} else {4843			__u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);4844			response_data =4845			    (FILE_SYSTEM_UNIX_INFO4846			     *) (((char *) &pSMBr->hdr.Protocol) +4847				 data_offset);4848			memcpy(&tcon->fsUnixInfo, response_data,4849			       sizeof(FILE_SYSTEM_UNIX_INFO));4850		}4851	}4852	cifs_buf_release(pSMB);4853 4854	if (rc == -EAGAIN)4855		goto QFSUnixRetry;4856 4857 4858	return rc;4859}4860 4861int4862CIFSSMBSetFSUnixInfo(const unsigned int xid, struct cifs_tcon *tcon, __u64 cap)4863{4864/* level 0x200  SMB_SET_CIFS_UNIX_INFO */4865	TRANSACTION2_SETFSI_REQ *pSMB = NULL;4866	TRANSACTION2_SETFSI_RSP *pSMBr = NULL;4867	int rc = 0;4868	int bytes_returned = 0;4869	__u16 params, param_offset, offset, byte_count;4870 4871	cifs_dbg(FYI, "In SETFSUnixInfo\n");4872SETFSUnixRetry:4873	/* BB switch to small buf init to save memory */4874	rc = smb_init_no_reconnect(SMB_COM_TRANSACTION2, 15, tcon,4875					(void **) &pSMB, (void **) &pSMBr);4876	if (rc)4877		return rc;4878 4879	params = 4;	/* 2 bytes zero followed by info level. */4880	pSMB->MaxSetupCount = 0;4881	pSMB->Reserved = 0;4882	pSMB->Flags = 0;4883	pSMB->Timeout = 0;4884	pSMB->Reserved2 = 0;4885	param_offset = offsetof(struct smb_com_transaction2_setfsi_req, FileNum)4886				- 4;4887	offset = param_offset + params;4888 4889	pSMB->MaxParameterCount = cpu_to_le16(4);4890	/* BB find exact max SMB PDU from sess structure BB */4891	pSMB->MaxDataCount = cpu_to_le16(100);4892	pSMB->SetupCount = 1;4893	pSMB->Reserved3 = 0;4894	pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FS_INFORMATION);4895	byte_count = 1 /* pad */ + params + 12;4896 4897	pSMB->DataCount = cpu_to_le16(12);4898	pSMB->ParameterCount = cpu_to_le16(params);4899	pSMB->TotalDataCount = pSMB->DataCount;4900	pSMB->TotalParameterCount = pSMB->ParameterCount;4901	pSMB->ParameterOffset = cpu_to_le16(param_offset);4902	pSMB->DataOffset = cpu_to_le16(offset);4903 4904	/* Params. */4905	pSMB->FileNum = 0;4906	pSMB->InformationLevel = cpu_to_le16(SMB_SET_CIFS_UNIX_INFO);4907 4908	/* Data. */4909	pSMB->ClientUnixMajor = cpu_to_le16(CIFS_UNIX_MAJOR_VERSION);4910	pSMB->ClientUnixMinor = cpu_to_le16(CIFS_UNIX_MINOR_VERSION);4911	pSMB->ClientUnixCap = cpu_to_le64(cap);4912 4913	inc_rfc1001_len(pSMB, byte_count);4914	pSMB->ByteCount = cpu_to_le16(byte_count);4915 4916	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,4917			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);4918	if (rc) {4919		cifs_dbg(VFS, "Send error in SETFSUnixInfo = %d\n", rc);4920	} else {		/* decode response */4921		rc = validate_t2((struct smb_t2_rsp *)pSMBr);4922		if (rc)4923			rc = -EIO;	/* bad smb */4924	}4925	cifs_buf_release(pSMB);4926 4927	if (rc == -EAGAIN)4928		goto SETFSUnixRetry;4929 4930	return rc;4931}4932 4933 4934 4935int4936CIFSSMBQFSPosixInfo(const unsigned int xid, struct cifs_tcon *tcon,4937		   struct kstatfs *FSData)4938{4939/* level 0x201  SMB_QUERY_CIFS_POSIX_INFO */4940	TRANSACTION2_QFSI_REQ *pSMB = NULL;4941	TRANSACTION2_QFSI_RSP *pSMBr = NULL;4942	FILE_SYSTEM_POSIX_INFO *response_data;4943	int rc = 0;4944	int bytes_returned = 0;4945	__u16 params, byte_count;4946 4947	cifs_dbg(FYI, "In QFSPosixInfo\n");4948QFSPosixRetry:4949	rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,4950		      (void **) &pSMBr);4951	if (rc)4952		return rc;4953 4954	params = 2;	/* level */4955	pSMB->TotalDataCount = 0;4956	pSMB->DataCount = 0;4957	pSMB->DataOffset = 0;4958	pSMB->MaxParameterCount = cpu_to_le16(2);4959	/* BB find exact max SMB PDU from sess structure BB */4960	pSMB->MaxDataCount = cpu_to_le16(100);4961	pSMB->MaxSetupCount = 0;4962	pSMB->Reserved = 0;4963	pSMB->Flags = 0;4964	pSMB->Timeout = 0;4965	pSMB->Reserved2 = 0;4966	byte_count = params + 1 /* pad */ ;4967	pSMB->ParameterCount = cpu_to_le16(params);4968	pSMB->TotalParameterCount = pSMB->ParameterCount;4969	pSMB->ParameterOffset = cpu_to_le16(offsetof(struct4970			smb_com_transaction2_qfsi_req, InformationLevel) - 4);4971	pSMB->SetupCount = 1;4972	pSMB->Reserved3 = 0;4973	pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);4974	pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_POSIX_FS_INFO);4975	inc_rfc1001_len(pSMB, byte_count);4976	pSMB->ByteCount = cpu_to_le16(byte_count);4977 4978	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,4979			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);4980	if (rc) {4981		cifs_dbg(FYI, "Send error in QFSUnixInfo = %d\n", rc);4982	} else {		/* decode response */4983		rc = validate_t2((struct smb_t2_rsp *)pSMBr);4984 4985		if (rc || get_bcc(&pSMBr->hdr) < 13) {4986			rc = -EIO;	/* bad smb */4987		} else {4988			__u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);4989			response_data =4990			    (FILE_SYSTEM_POSIX_INFO4991			     *) (((char *) &pSMBr->hdr.Protocol) +4992				 data_offset);4993			FSData->f_bsize =4994					le32_to_cpu(response_data->BlockSize);4995			/*4996			 * much prefer larger but if server doesn't report4997			 * a valid size than 4K is a reasonable minimum4998			 */4999			if (FSData->f_bsize < 512)5000				FSData->f_bsize = 4096;5001 5002			FSData->f_blocks =5003					le64_to_cpu(response_data->TotalBlocks);5004			FSData->f_bfree =5005			    le64_to_cpu(response_data->BlocksAvail);5006			if (response_data->UserBlocksAvail == cpu_to_le64(-1)) {5007				FSData->f_bavail = FSData->f_bfree;5008			} else {5009				FSData->f_bavail =5010				    le64_to_cpu(response_data->UserBlocksAvail);5011			}5012			if (response_data->TotalFileNodes != cpu_to_le64(-1))5013				FSData->f_files =5014				     le64_to_cpu(response_data->TotalFileNodes);5015			if (response_data->FreeFileNodes != cpu_to_le64(-1))5016				FSData->f_ffree =5017				      le64_to_cpu(response_data->FreeFileNodes);5018		}5019	}5020	cifs_buf_release(pSMB);5021 5022	if (rc == -EAGAIN)5023		goto QFSPosixRetry;5024 5025	return rc;5026}5027 5028 5029/*5030 * We can not use write of zero bytes trick to set file size due to need for5031 * large file support. Also note that this SetPathInfo is preferred to5032 * SetFileInfo based method in next routine which is only needed to work around5033 * a sharing violation bugin Samba which this routine can run into.5034 */5035int5036CIFSSMBSetEOF(const unsigned int xid, struct cifs_tcon *tcon,5037	      const char *file_name, __u64 size, struct cifs_sb_info *cifs_sb,5038	      bool set_allocation, struct dentry *dentry)5039{5040	struct smb_com_transaction2_spi_req *pSMB = NULL;5041	struct smb_com_transaction2_spi_rsp *pSMBr = NULL;5042	struct file_end_of_file_info *parm_data;5043	int name_len;5044	int rc = 0;5045	int bytes_returned = 0;5046	int remap = cifs_remap(cifs_sb);5047 5048	__u16 params, byte_count, data_count, param_offset, offset;5049 5050	cifs_dbg(FYI, "In SetEOF\n");5051SetEOFRetry:5052	rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,5053		      (void **) &pSMBr);5054	if (rc)5055		return rc;5056 5057	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {5058		name_len =5059		    cifsConvertToUTF16((__le16 *) pSMB->FileName, file_name,5060				       PATH_MAX, cifs_sb->local_nls, remap);5061		name_len++;	/* trailing null */5062		name_len *= 2;5063	} else {5064		name_len = copy_path_name(pSMB->FileName, file_name);5065	}5066	params = 6 + name_len;5067	data_count = sizeof(struct file_end_of_file_info);5068	pSMB->MaxParameterCount = cpu_to_le16(2);5069	pSMB->MaxDataCount = cpu_to_le16(4100);5070	pSMB->MaxSetupCount = 0;5071	pSMB->Reserved = 0;5072	pSMB->Flags = 0;5073	pSMB->Timeout = 0;5074	pSMB->Reserved2 = 0;5075	param_offset = offsetof(struct smb_com_transaction2_spi_req,5076				InformationLevel) - 4;5077	offset = param_offset + params;5078	if (set_allocation) {5079		if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)5080			pSMB->InformationLevel =5081				cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2);5082		else5083			pSMB->InformationLevel =5084				cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO);5085	} else /* Set File Size */  {5086	    if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)5087		    pSMB->InformationLevel =5088				cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO2);5089	    else5090		    pSMB->InformationLevel =5091				cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO);5092	}5093 5094	parm_data =5095	    (struct file_end_of_file_info *) (((char *) &pSMB->hdr.Protocol) +5096				       offset);5097	pSMB->ParameterOffset = cpu_to_le16(param_offset);5098	pSMB->DataOffset = cpu_to_le16(offset);5099	pSMB->SetupCount = 1;5100	pSMB->Reserved3 = 0;5101	pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);5102	byte_count = 3 /* pad */  + params + data_count;5103	pSMB->DataCount = cpu_to_le16(data_count);5104	pSMB->TotalDataCount = pSMB->DataCount;5105	pSMB->ParameterCount = cpu_to_le16(params);5106	pSMB->TotalParameterCount = pSMB->ParameterCount;5107	pSMB->Reserved4 = 0;5108	inc_rfc1001_len(pSMB, byte_count);5109	parm_data->FileSize = cpu_to_le64(size);5110	pSMB->ByteCount = cpu_to_le16(byte_count);5111	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,5112			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);5113	if (rc)5114		cifs_dbg(FYI, "SetPathInfo (file size) returned %d\n", rc);5115 5116	cifs_buf_release(pSMB);5117 5118	if (rc == -EAGAIN)5119		goto SetEOFRetry;5120 5121	return rc;5122}5123 5124int5125CIFSSMBSetFileSize(const unsigned int xid, struct cifs_tcon *tcon,5126		   struct cifsFileInfo *cfile, __u64 size, bool set_allocation)5127{5128	struct smb_com_transaction2_sfi_req *pSMB  = NULL;5129	struct file_end_of_file_info *parm_data;5130	int rc = 0;5131	__u16 params, param_offset, offset, byte_count, count;5132 5133	cifs_dbg(FYI, "SetFileSize (via SetFileInfo) %lld\n",5134		 (long long)size);5135	rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);5136 5137	if (rc)5138		return rc;5139 5140	pSMB->hdr.Pid = cpu_to_le16((__u16)cfile->pid);5141	pSMB->hdr.PidHigh = cpu_to_le16((__u16)(cfile->pid >> 16));5142 5143	params = 6;5144	pSMB->MaxSetupCount = 0;5145	pSMB->Reserved = 0;5146	pSMB->Flags = 0;5147	pSMB->Timeout = 0;5148	pSMB->Reserved2 = 0;5149	param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;5150	offset = param_offset + params;5151 5152	count = sizeof(struct file_end_of_file_info);5153	pSMB->MaxParameterCount = cpu_to_le16(2);5154	/* BB find exact max SMB PDU from sess structure BB */5155	pSMB->MaxDataCount = cpu_to_le16(1000);5156	pSMB->SetupCount = 1;5157	pSMB->Reserved3 = 0;5158	pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);5159	byte_count = 3 /* pad */  + params + count;5160	pSMB->DataCount = cpu_to_le16(count);5161	pSMB->ParameterCount = cpu_to_le16(params);5162	pSMB->TotalDataCount = pSMB->DataCount;5163	pSMB->TotalParameterCount = pSMB->ParameterCount;5164	pSMB->ParameterOffset = cpu_to_le16(param_offset);5165	/* SMB offsets are from the beginning of SMB which is 4 bytes in, after RFC1001 field */5166	parm_data =5167		(struct file_end_of_file_info *)(((char *)pSMB) + offset + 4);5168	pSMB->DataOffset = cpu_to_le16(offset);5169	parm_data->FileSize = cpu_to_le64(size);5170	pSMB->Fid = cfile->fid.netfid;5171	if (set_allocation) {5172		if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)5173			pSMB->InformationLevel =5174				cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2);5175		else5176			pSMB->InformationLevel =5177				cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO);5178	} else /* Set File Size */  {5179	    if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)5180		    pSMB->InformationLevel =5181				cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO2);5182	    else5183		    pSMB->InformationLevel =5184				cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO);5185	}5186	pSMB->Reserved4 = 0;5187	inc_rfc1001_len(pSMB, byte_count);5188	pSMB->ByteCount = cpu_to_le16(byte_count);5189	rc = SendReceiveNoRsp(xid, tcon->ses, (char *) pSMB, 0);5190	cifs_small_buf_release(pSMB);5191	if (rc) {5192		cifs_dbg(FYI, "Send error in SetFileInfo (SetFileSize) = %d\n",5193			 rc);5194	}5195 5196	/* Note: On -EAGAIN error only caller can retry on handle based calls5197		since file handle passed in no longer valid */5198 5199	return rc;5200}5201 5202/* Some legacy servers such as NT4 require that the file times be set on5203   an open handle, rather than by pathname - this is awkward due to5204   potential access conflicts on the open, but it is unavoidable for these5205   old servers since the only other choice is to go from 100 nanosecond DCE5206   time and resort to the original setpathinfo level which takes the ancient5207   DOS time format with 2 second granularity */5208int5209CIFSSMBSetFileInfo(const unsigned int xid, struct cifs_tcon *tcon,5210		    const FILE_BASIC_INFO *data, __u16 fid, __u32 pid_of_opener)5211{5212	struct smb_com_transaction2_sfi_req *pSMB  = NULL;5213	char *data_offset;5214	int rc = 0;5215	__u16 params, param_offset, offset, byte_count, count;5216 5217	cifs_dbg(FYI, "Set Times (via SetFileInfo)\n");5218	rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);5219 5220	if (rc)5221		return rc;5222 5223	pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);5224	pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));5225 5226	params = 6;5227	pSMB->MaxSetupCount = 0;5228	pSMB->Reserved = 0;5229	pSMB->Flags = 0;5230	pSMB->Timeout = 0;5231	pSMB->Reserved2 = 0;5232	param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;5233	offset = param_offset + params;5234 5235	data_offset = (char *)pSMB +5236			offsetof(struct smb_hdr, Protocol) + offset;5237 5238	count = sizeof(FILE_BASIC_INFO);5239	pSMB->MaxParameterCount = cpu_to_le16(2);5240	/* BB find max SMB PDU from sess */5241	pSMB->MaxDataCount = cpu_to_le16(1000);5242	pSMB->SetupCount = 1;5243	pSMB->Reserved3 = 0;5244	pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);5245	byte_count = 3 /* pad */  + params + count;5246	pSMB->DataCount = cpu_to_le16(count);5247	pSMB->ParameterCount = cpu_to_le16(params);5248	pSMB->TotalDataCount = pSMB->DataCount;5249	pSMB->TotalParameterCount = pSMB->ParameterCount;5250	pSMB->ParameterOffset = cpu_to_le16(param_offset);5251	pSMB->DataOffset = cpu_to_le16(offset);5252	pSMB->Fid = fid;5253	if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)5254		pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO2);5255	else5256		pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO);5257	pSMB->Reserved4 = 0;5258	inc_rfc1001_len(pSMB, byte_count);5259	pSMB->ByteCount = cpu_to_le16(byte_count);5260	memcpy(data_offset, data, sizeof(FILE_BASIC_INFO));5261	rc = SendReceiveNoRsp(xid, tcon->ses, (char *) pSMB, 0);5262	cifs_small_buf_release(pSMB);5263	if (rc)5264		cifs_dbg(FYI, "Send error in Set Time (SetFileInfo) = %d\n",5265			 rc);5266 5267	/* Note: On -EAGAIN error only caller can retry on handle based calls5268		since file handle passed in no longer valid */5269 5270	return rc;5271}5272 5273int5274CIFSSMBSetFileDisposition(const unsigned int xid, struct cifs_tcon *tcon,5275			  bool delete_file, __u16 fid, __u32 pid_of_opener)5276{5277	struct smb_com_transaction2_sfi_req *pSMB  = NULL;5278	char *data_offset;5279	int rc = 0;5280	__u16 params, param_offset, offset, byte_count, count;5281 5282	cifs_dbg(FYI, "Set File Disposition (via SetFileInfo)\n");5283	rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);5284 5285	if (rc)5286		return rc;5287 5288	pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);5289	pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));5290 5291	params = 6;5292	pSMB->MaxSetupCount = 0;5293	pSMB->Reserved = 0;5294	pSMB->Flags = 0;5295	pSMB->Timeout = 0;5296	pSMB->Reserved2 = 0;5297	param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;5298	offset = param_offset + params;5299 5300	/* SMB offsets are from the beginning of SMB which is 4 bytes in, after RFC1001 field */5301	data_offset = (char *)(pSMB) + offset + 4;5302 5303	count = 1;5304	pSMB->MaxParameterCount = cpu_to_le16(2);5305	/* BB find max SMB PDU from sess */5306	pSMB->MaxDataCount = cpu_to_le16(1000);5307	pSMB->SetupCount = 1;5308	pSMB->Reserved3 = 0;5309	pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);5310	byte_count = 3 /* pad */  + params + count;5311	pSMB->DataCount = cpu_to_le16(count);5312	pSMB->ParameterCount = cpu_to_le16(params);5313	pSMB->TotalDataCount = pSMB->DataCount;5314	pSMB->TotalParameterCount = pSMB->ParameterCount;5315	pSMB->ParameterOffset = cpu_to_le16(param_offset);5316	pSMB->DataOffset = cpu_to_le16(offset);5317	pSMB->Fid = fid;5318	pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_DISPOSITION_INFO);5319	pSMB->Reserved4 = 0;5320	inc_rfc1001_len(pSMB, byte_count);5321	pSMB->ByteCount = cpu_to_le16(byte_count);5322	*data_offset = delete_file ? 1 : 0;5323	rc = SendReceiveNoRsp(xid, tcon->ses, (char *) pSMB, 0);5324	cifs_small_buf_release(pSMB);5325	if (rc)5326		cifs_dbg(FYI, "Send error in SetFileDisposition = %d\n", rc);5327 5328	return rc;5329}5330 5331static int5332CIFSSMBSetPathInfoFB(const unsigned int xid, struct cifs_tcon *tcon,5333		     const char *fileName, const FILE_BASIC_INFO *data,5334		     const struct nls_table *nls_codepage,5335		     struct cifs_sb_info *cifs_sb)5336{5337	int oplock = 0;5338	struct cifs_open_parms oparms;5339	struct cifs_fid fid;5340	int rc;5341 5342	oparms = (struct cifs_open_parms) {5343		.tcon = tcon,5344		.cifs_sb = cifs_sb,5345		.desired_access = GENERIC_WRITE,5346		.create_options = cifs_create_options(cifs_sb, 0),5347		.disposition = FILE_OPEN,5348		.path = fileName,5349		.fid = &fid,5350	};5351 5352	rc = CIFS_open(xid, &oparms, &oplock, NULL);5353	if (rc)5354		goto out;5355 5356	rc = CIFSSMBSetFileInfo(xid, tcon, data, fid.netfid, current->tgid);5357	CIFSSMBClose(xid, tcon, fid.netfid);5358out:5359 5360	return rc;5361}5362 5363int5364CIFSSMBSetPathInfo(const unsigned int xid, struct cifs_tcon *tcon,5365		   const char *fileName, const FILE_BASIC_INFO *data,5366		   const struct nls_table *nls_codepage,5367		     struct cifs_sb_info *cifs_sb)5368{5369	TRANSACTION2_SPI_REQ *pSMB = NULL;5370	TRANSACTION2_SPI_RSP *pSMBr = NULL;5371	int name_len;5372	int rc = 0;5373	int bytes_returned = 0;5374	char *data_offset;5375	__u16 params, param_offset, offset, byte_count, count;5376	int remap = cifs_remap(cifs_sb);5377 5378	cifs_dbg(FYI, "In SetTimes\n");5379 5380SetTimesRetry:5381	rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,5382		      (void **) &pSMBr);5383	if (rc)5384		return rc;5385 5386	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {5387		name_len =5388		    cifsConvertToUTF16((__le16 *) pSMB->FileName, fileName,5389				       PATH_MAX, nls_codepage, remap);5390		name_len++;	/* trailing null */5391		name_len *= 2;5392	} else {5393		name_len = copy_path_name(pSMB->FileName, fileName);5394	}5395 5396	params = 6 + name_len;5397	count = sizeof(FILE_BASIC_INFO);5398	pSMB->MaxParameterCount = cpu_to_le16(2);5399	/* BB find max SMB PDU from sess structure BB */5400	pSMB->MaxDataCount = cpu_to_le16(1000);5401	pSMB->MaxSetupCount = 0;5402	pSMB->Reserved = 0;5403	pSMB->Flags = 0;5404	pSMB->Timeout = 0;5405	pSMB->Reserved2 = 0;5406	param_offset = offsetof(struct smb_com_transaction2_spi_req,5407				InformationLevel) - 4;5408	offset = param_offset + params;5409	data_offset = (char *) (&pSMB->hdr.Protocol) + offset;5410	pSMB->ParameterOffset = cpu_to_le16(param_offset);5411	pSMB->DataOffset = cpu_to_le16(offset);5412	pSMB->SetupCount = 1;5413	pSMB->Reserved3 = 0;5414	pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);5415	byte_count = 3 /* pad */  + params + count;5416 5417	pSMB->DataCount = cpu_to_le16(count);5418	pSMB->ParameterCount = cpu_to_le16(params);5419	pSMB->TotalDataCount = pSMB->DataCount;5420	pSMB->TotalParameterCount = pSMB->ParameterCount;5421	if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)5422		pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO2);5423	else5424		pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO);5425	pSMB->Reserved4 = 0;5426	inc_rfc1001_len(pSMB, byte_count);5427	memcpy(data_offset, data, sizeof(FILE_BASIC_INFO));5428	pSMB->ByteCount = cpu_to_le16(byte_count);5429	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,5430			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);5431	if (rc)5432		cifs_dbg(FYI, "SetPathInfo (times) returned %d\n", rc);5433 5434	cifs_buf_release(pSMB);5435 5436	if (rc == -EAGAIN)5437		goto SetTimesRetry;5438 5439	if (rc == -EOPNOTSUPP)5440		return CIFSSMBSetPathInfoFB(xid, tcon, fileName, data,5441					    nls_codepage, cifs_sb);5442 5443	return rc;5444}5445 5446static void5447cifs_fill_unix_set_info(FILE_UNIX_BASIC_INFO *data_offset,5448			const struct cifs_unix_set_info_args *args)5449{5450	u64 uid = NO_CHANGE_64, gid = NO_CHANGE_64;5451	u64 mode = args->mode;5452 5453	if (uid_valid(args->uid))5454		uid = from_kuid(&init_user_ns, args->uid);5455	if (gid_valid(args->gid))5456		gid = from_kgid(&init_user_ns, args->gid);5457 5458	/*5459	 * Samba server ignores set of file size to zero due to bugs in some5460	 * older clients, but we should be precise - we use SetFileSize to5461	 * set file size and do not want to truncate file size to zero5462	 * accidentally as happened on one Samba server beta by putting5463	 * zero instead of -1 here5464	 */5465	data_offset->EndOfFile = cpu_to_le64(NO_CHANGE_64);5466	data_offset->NumOfBytes = cpu_to_le64(NO_CHANGE_64);5467	data_offset->LastStatusChange = cpu_to_le64(args->ctime);5468	data_offset->LastAccessTime = cpu_to_le64(args->atime);5469	data_offset->LastModificationTime = cpu_to_le64(args->mtime);5470	data_offset->Uid = cpu_to_le64(uid);5471	data_offset->Gid = cpu_to_le64(gid);5472	/* better to leave device as zero when it is  */5473	data_offset->DevMajor = cpu_to_le64(MAJOR(args->device));5474	data_offset->DevMinor = cpu_to_le64(MINOR(args->device));5475	data_offset->Permissions = cpu_to_le64(mode);5476 5477	if (S_ISREG(mode))5478		data_offset->Type = cpu_to_le32(UNIX_FILE);5479	else if (S_ISDIR(mode))5480		data_offset->Type = cpu_to_le32(UNIX_DIR);5481	else if (S_ISLNK(mode))5482		data_offset->Type = cpu_to_le32(UNIX_SYMLINK);5483	else if (S_ISCHR(mode))5484		data_offset->Type = cpu_to_le32(UNIX_CHARDEV);5485	else if (S_ISBLK(mode))5486		data_offset->Type = cpu_to_le32(UNIX_BLOCKDEV);5487	else if (S_ISFIFO(mode))5488		data_offset->Type = cpu_to_le32(UNIX_FIFO);5489	else if (S_ISSOCK(mode))5490		data_offset->Type = cpu_to_le32(UNIX_SOCKET);5491}5492 5493int5494CIFSSMBUnixSetFileInfo(const unsigned int xid, struct cifs_tcon *tcon,5495		       const struct cifs_unix_set_info_args *args,5496		       u16 fid, u32 pid_of_opener)5497{5498	struct smb_com_transaction2_sfi_req *pSMB  = NULL;5499	char *data_offset;5500	int rc = 0;5501	u16 params, param_offset, offset, byte_count, count;5502 5503	cifs_dbg(FYI, "Set Unix Info (via SetFileInfo)\n");5504	rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);5505 5506	if (rc)5507		return rc;5508 5509	pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);5510	pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));5511 5512	params = 6;5513	pSMB->MaxSetupCount = 0;5514	pSMB->Reserved = 0;5515	pSMB->Flags = 0;5516	pSMB->Timeout = 0;5517	pSMB->Reserved2 = 0;5518	param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;5519	offset = param_offset + params;5520 5521	data_offset = (char *)pSMB +5522			offsetof(struct smb_hdr, Protocol) + offset;5523 5524	count = sizeof(FILE_UNIX_BASIC_INFO);5525 5526	pSMB->MaxParameterCount = cpu_to_le16(2);5527	/* BB find max SMB PDU from sess */5528	pSMB->MaxDataCount = cpu_to_le16(1000);5529	pSMB->SetupCount = 1;5530	pSMB->Reserved3 = 0;5531	pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);5532	byte_count = 3 /* pad */  + params + count;5533	pSMB->DataCount = cpu_to_le16(count);5534	pSMB->ParameterCount = cpu_to_le16(params);5535	pSMB->TotalDataCount = pSMB->DataCount;5536	pSMB->TotalParameterCount = pSMB->ParameterCount;5537	pSMB->ParameterOffset = cpu_to_le16(param_offset);5538	pSMB->DataOffset = cpu_to_le16(offset);5539	pSMB->Fid = fid;5540	pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_BASIC);5541	pSMB->Reserved4 = 0;5542	inc_rfc1001_len(pSMB, byte_count);5543	pSMB->ByteCount = cpu_to_le16(byte_count);5544 5545	cifs_fill_unix_set_info((FILE_UNIX_BASIC_INFO *)data_offset, args);5546 5547	rc = SendReceiveNoRsp(xid, tcon->ses, (char *) pSMB, 0);5548	cifs_small_buf_release(pSMB);5549	if (rc)5550		cifs_dbg(FYI, "Send error in Set Time (SetFileInfo) = %d\n",5551			 rc);5552 5553	/* Note: On -EAGAIN error only caller can retry on handle based calls5554		since file handle passed in no longer valid */5555 5556	return rc;5557}5558 5559int5560CIFSSMBUnixSetPathInfo(const unsigned int xid, struct cifs_tcon *tcon,5561		       const char *file_name,5562		       const struct cifs_unix_set_info_args *args,5563		       const struct nls_table *nls_codepage, int remap)5564{5565	TRANSACTION2_SPI_REQ *pSMB = NULL;5566	TRANSACTION2_SPI_RSP *pSMBr = NULL;5567	int name_len;5568	int rc = 0;5569	int bytes_returned = 0;5570	FILE_UNIX_BASIC_INFO *data_offset;5571	__u16 params, param_offset, offset, count, byte_count;5572 5573	cifs_dbg(FYI, "In SetUID/GID/Mode\n");5574setPermsRetry:5575	rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,5576		      (void **) &pSMBr);5577	if (rc)5578		return rc;5579 5580	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {5581		name_len =5582		    cifsConvertToUTF16((__le16 *) pSMB->FileName, file_name,5583				       PATH_MAX, nls_codepage, remap);5584		name_len++;	/* trailing null */5585		name_len *= 2;5586	} else {5587		name_len = copy_path_name(pSMB->FileName, file_name);5588	}5589 5590	params = 6 + name_len;5591	count = sizeof(FILE_UNIX_BASIC_INFO);5592	pSMB->MaxParameterCount = cpu_to_le16(2);5593	/* BB find max SMB PDU from sess structure BB */5594	pSMB->MaxDataCount = cpu_to_le16(1000);5595	pSMB->MaxSetupCount = 0;5596	pSMB->Reserved = 0;5597	pSMB->Flags = 0;5598	pSMB->Timeout = 0;5599	pSMB->Reserved2 = 0;5600	param_offset = offsetof(struct smb_com_transaction2_spi_req,5601				InformationLevel) - 4;5602	offset = param_offset + params;5603	/* SMB offsets are from the beginning of SMB which is 4 bytes in, after RFC1001 field */5604	data_offset = (FILE_UNIX_BASIC_INFO *)((char *) pSMB + offset + 4);5605	memset(data_offset, 0, count);5606	pSMB->DataOffset = cpu_to_le16(offset);5607	pSMB->ParameterOffset = cpu_to_le16(param_offset);5608	pSMB->SetupCount = 1;5609	pSMB->Reserved3 = 0;5610	pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);5611	byte_count = 3 /* pad */  + params + count;5612	pSMB->ParameterCount = cpu_to_le16(params);5613	pSMB->DataCount = cpu_to_le16(count);5614	pSMB->TotalParameterCount = pSMB->ParameterCount;5615	pSMB->TotalDataCount = pSMB->DataCount;5616	pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_BASIC);5617	pSMB->Reserved4 = 0;5618	inc_rfc1001_len(pSMB, byte_count);5619 5620	cifs_fill_unix_set_info(data_offset, args);5621 5622	pSMB->ByteCount = cpu_to_le16(byte_count);5623	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,5624			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);5625	if (rc)5626		cifs_dbg(FYI, "SetPathInfo (perms) returned %d\n", rc);5627 5628	cifs_buf_release(pSMB);5629	if (rc == -EAGAIN)5630		goto setPermsRetry;5631	return rc;5632}5633 5634#ifdef CONFIG_CIFS_XATTR5635/*5636 * Do a path-based QUERY_ALL_EAS call and parse the result. This is a common5637 * function used by listxattr and getxattr type calls. When ea_name is set,5638 * it looks for that attribute name and stuffs that value into the EAData5639 * buffer. When ea_name is NULL, it stuffs a list of attribute names into the5640 * buffer. In both cases, the return value is either the length of the5641 * resulting data or a negative error code. If EAData is a NULL pointer then5642 * the data isn't copied to it, but the length is returned.5643 */5644ssize_t5645CIFSSMBQAllEAs(const unsigned int xid, struct cifs_tcon *tcon,5646		const unsigned char *searchName, const unsigned char *ea_name,5647		char *EAData, size_t buf_size,5648		struct cifs_sb_info *cifs_sb)5649{5650		/* BB assumes one setup word */5651	TRANSACTION2_QPI_REQ *pSMB = NULL;5652	TRANSACTION2_QPI_RSP *pSMBr = NULL;5653	int remap = cifs_remap(cifs_sb);5654	struct nls_table *nls_codepage = cifs_sb->local_nls;5655	int rc = 0;5656	int bytes_returned;5657	int list_len;5658	struct fealist *ea_response_data;5659	struct fea *temp_fea;5660	char *temp_ptr;5661	char *end_of_smb;5662	__u16 params, byte_count, data_offset;5663	unsigned int ea_name_len = ea_name ? strlen(ea_name) : 0;5664 5665	cifs_dbg(FYI, "In Query All EAs path %s\n", searchName);5666QAllEAsRetry:5667	rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,5668		      (void **) &pSMBr);5669	if (rc)5670		return rc;5671 5672	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {5673		list_len =5674		    cifsConvertToUTF16((__le16 *) pSMB->FileName, searchName,5675				       PATH_MAX, nls_codepage, remap);5676		list_len++;	/* trailing null */5677		list_len *= 2;5678	} else {5679		list_len = copy_path_name(pSMB->FileName, searchName);5680	}5681 5682	params = 2 /* level */ + 4 /* reserved */ + list_len /* includes NUL */;5683	pSMB->TotalDataCount = 0;5684	pSMB->MaxParameterCount = cpu_to_le16(2);5685	/* BB find exact max SMB PDU from sess structure BB */5686	pSMB->MaxDataCount = cpu_to_le16(CIFSMaxBufSize);5687	pSMB->MaxSetupCount = 0;5688	pSMB->Reserved = 0;5689	pSMB->Flags = 0;5690	pSMB->Timeout = 0;5691	pSMB->Reserved2 = 0;5692	pSMB->ParameterOffset = cpu_to_le16(offsetof(5693	struct smb_com_transaction2_qpi_req, InformationLevel) - 4);5694	pSMB->DataCount = 0;5695	pSMB->DataOffset = 0;5696	pSMB->SetupCount = 1;5697	pSMB->Reserved3 = 0;5698	pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);5699	byte_count = params + 1 /* pad */ ;5700	pSMB->TotalParameterCount = cpu_to_le16(params);5701	pSMB->ParameterCount = pSMB->TotalParameterCount;5702	pSMB->InformationLevel = cpu_to_le16(SMB_INFO_QUERY_ALL_EAS);5703	pSMB->Reserved4 = 0;5704	inc_rfc1001_len(pSMB, byte_count);5705	pSMB->ByteCount = cpu_to_le16(byte_count);5706 5707	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,5708			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);5709	if (rc) {5710		cifs_dbg(FYI, "Send error in QueryAllEAs = %d\n", rc);5711		goto QAllEAsOut;5712	}5713 5714 5715	/* BB also check enough total bytes returned */5716	/* BB we need to improve the validity checking5717	of these trans2 responses */5718 5719	rc = validate_t2((struct smb_t2_rsp *)pSMBr);5720	if (rc || get_bcc(&pSMBr->hdr) < 4) {5721		rc = -EIO;	/* bad smb */5722		goto QAllEAsOut;5723	}5724 5725	/* check that length of list is not more than bcc */5726	/* check that each entry does not go beyond length5727	   of list */5728	/* check that each element of each entry does not5729	   go beyond end of list */5730	/* validate_trans2_offsets() */5731	/* BB check if start of smb + data_offset > &bcc+ bcc */5732 5733	data_offset = le16_to_cpu(pSMBr->t2.DataOffset);5734	ea_response_data = (struct fealist *)5735				(((char *) &pSMBr->hdr.Protocol) + data_offset);5736 5737	list_len = le32_to_cpu(ea_response_data->list_len);5738	cifs_dbg(FYI, "ea length %d\n", list_len);5739	if (list_len <= 8) {5740		cifs_dbg(FYI, "empty EA list returned from server\n");5741		/* didn't find the named attribute */5742		if (ea_name)5743			rc = -ENODATA;5744		goto QAllEAsOut;5745	}5746 5747	/* make sure list_len doesn't go past end of SMB */5748	end_of_smb = (char *)pByteArea(&pSMBr->hdr) + get_bcc(&pSMBr->hdr);5749	if ((char *)ea_response_data + list_len > end_of_smb) {5750		cifs_dbg(FYI, "EA list appears to go beyond SMB\n");5751		rc = -EIO;5752		goto QAllEAsOut;5753	}5754 5755	/* account for ea list len */5756	list_len -= 4;5757	temp_fea = &ea_response_data->list;5758	temp_ptr = (char *)temp_fea;5759	while (list_len > 0) {5760		unsigned int name_len;5761		__u16 value_len;5762 5763		list_len -= 4;5764		temp_ptr += 4;5765		/* make sure we can read name_len and value_len */5766		if (list_len < 0) {5767			cifs_dbg(FYI, "EA entry goes beyond length of list\n");5768			rc = -EIO;5769			goto QAllEAsOut;5770		}5771 5772		name_len = temp_fea->name_len;5773		value_len = le16_to_cpu(temp_fea->value_len);5774		list_len -= name_len + 1 + value_len;5775		if (list_len < 0) {5776			cifs_dbg(FYI, "EA entry goes beyond length of list\n");5777			rc = -EIO;5778			goto QAllEAsOut;5779		}5780 5781		if (ea_name) {5782			if (ea_name_len == name_len &&5783			    memcmp(ea_name, temp_ptr, name_len) == 0) {5784				temp_ptr += name_len + 1;5785				rc = value_len;5786				if (buf_size == 0)5787					goto QAllEAsOut;5788				if ((size_t)value_len > buf_size) {5789					rc = -ERANGE;5790					goto QAllEAsOut;5791				}5792				memcpy(EAData, temp_ptr, value_len);5793				goto QAllEAsOut;5794			}5795		} else {5796			/* account for prefix user. and trailing null */5797			rc += (5 + 1 + name_len);5798			if (rc < (int) buf_size) {5799				memcpy(EAData, "user.", 5);5800				EAData += 5;5801				memcpy(EAData, temp_ptr, name_len);5802				EAData += name_len;5803				/* null terminate name */5804				*EAData = 0;5805				++EAData;5806			} else if (buf_size == 0) {5807				/* skip copy - calc size only */5808			} else {5809				/* stop before overrun buffer */5810				rc = -ERANGE;5811				break;5812			}5813		}5814		temp_ptr += name_len + 1 + value_len;5815		temp_fea = (struct fea *)temp_ptr;5816	}5817 5818	/* didn't find the named attribute */5819	if (ea_name)5820		rc = -ENODATA;5821 5822QAllEAsOut:5823	cifs_buf_release(pSMB);5824	if (rc == -EAGAIN)5825		goto QAllEAsRetry;5826 5827	return (ssize_t)rc;5828}5829 5830int5831CIFSSMBSetEA(const unsigned int xid, struct cifs_tcon *tcon,5832	     const char *fileName, const char *ea_name, const void *ea_value,5833	     const __u16 ea_value_len, const struct nls_table *nls_codepage,5834	     struct cifs_sb_info *cifs_sb)5835{5836	struct smb_com_transaction2_spi_req *pSMB = NULL;5837	struct smb_com_transaction2_spi_rsp *pSMBr = NULL;5838	struct fealist *parm_data;5839	int name_len;5840	int rc = 0;5841	int bytes_returned = 0;5842	__u16 params, param_offset, byte_count, offset, count;5843	int remap = cifs_remap(cifs_sb);5844 5845	cifs_dbg(FYI, "In SetEA\n");5846SetEARetry:5847	rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,5848		      (void **) &pSMBr);5849	if (rc)5850		return rc;5851 5852	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {5853		name_len =5854		    cifsConvertToUTF16((__le16 *) pSMB->FileName, fileName,5855				       PATH_MAX, nls_codepage, remap);5856		name_len++;	/* trailing null */5857		name_len *= 2;5858	} else {5859		name_len = copy_path_name(pSMB->FileName, fileName);5860	}5861 5862	params = 6 + name_len;5863 5864	/* done calculating parms using name_len of file name,5865	now use name_len to calculate length of ea name5866	we are going to create in the inode xattrs */5867	if (ea_name == NULL)5868		name_len = 0;5869	else5870		name_len = strnlen(ea_name, 255);5871 5872	count = sizeof(*parm_data) + 1 + ea_value_len + name_len;5873	pSMB->MaxParameterCount = cpu_to_le16(2);5874	/* BB find max SMB PDU from sess */5875	pSMB->MaxDataCount = cpu_to_le16(1000);5876	pSMB->MaxSetupCount = 0;5877	pSMB->Reserved = 0;5878	pSMB->Flags = 0;5879	pSMB->Timeout = 0;5880	pSMB->Reserved2 = 0;5881	param_offset = offsetof(struct smb_com_transaction2_spi_req,5882				InformationLevel) - 4;5883	offset = param_offset + params;5884	pSMB->InformationLevel =5885		cpu_to_le16(SMB_SET_FILE_EA);5886 5887	parm_data = (void *)pSMB + offsetof(struct smb_hdr, Protocol) + offset;5888	pSMB->ParameterOffset = cpu_to_le16(param_offset);5889	pSMB->DataOffset = cpu_to_le16(offset);5890	pSMB->SetupCount = 1;5891	pSMB->Reserved3 = 0;5892	pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);5893	byte_count = 3 /* pad */  + params + count;5894	pSMB->DataCount = cpu_to_le16(count);5895	parm_data->list_len = cpu_to_le32(count);5896	parm_data->list.EA_flags = 0;5897	/* we checked above that name len is less than 255 */5898	parm_data->list.name_len = (__u8)name_len;5899	/* EA names are always ASCII and NUL-terminated */5900	strscpy(parm_data->list.name, ea_name ?: "", name_len + 1);5901	parm_data->list.value_len = cpu_to_le16(ea_value_len);5902	/* caller ensures that ea_value_len is less than 64K but5903	we need to ensure that it fits within the smb */5904 5905	/*BB add length check to see if it would fit in5906	     negotiated SMB buffer size BB */5907	/* if (ea_value_len > buffer_size - 512 (enough for header)) */5908	if (ea_value_len)5909		memcpy(parm_data->list.name + name_len + 1,5910		       ea_value, ea_value_len);5911 5912	pSMB->TotalDataCount = pSMB->DataCount;5913	pSMB->ParameterCount = cpu_to_le16(params);5914	pSMB->TotalParameterCount = pSMB->ParameterCount;5915	pSMB->Reserved4 = 0;5916	inc_rfc1001_len(pSMB, byte_count);5917	pSMB->ByteCount = cpu_to_le16(byte_count);5918	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,5919			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);5920	if (rc)5921		cifs_dbg(FYI, "SetPathInfo (EA) returned %d\n", rc);5922 5923	cifs_buf_release(pSMB);5924 5925	if (rc == -EAGAIN)5926		goto SetEARetry;5927 5928	return rc;5929}5930#endif5931