4 * Copyright (C) International Business Machines Corp., 2002,2010
7 * Contains the routines for constructing the SMB PDUs themselves
9 * This library is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU Lesser General Public License as published
11 * by the Free Software Foundation; either version 2.1 of the License, or
12 * (at your option) any later version.
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
17 * the GNU Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public License
20 * along with this library; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 /* SMB/CIFS PDU handling routines here - except for leftovers in connect.c */
25 /* These are mostly routines that operate on a pathname, or on a tree id */
26 /* (mounted volume), but there are eight handle based routines which must be */
27 /* treated slightly differently for reconnection purposes since we never */
28 /* want to reuse a stale file handle and only the caller knows the file info */
31 #include <linux/kernel.h>
32 #include <linux/vfs.h>
33 #include <linux/slab.h>
34 #include <linux/posix_acl_xattr.h>
35 #include <linux/pagemap.h>
36 #include <linux/swap.h>
37 #include <linux/task_io_accounting_ops.h>
38 #include <linux/uaccess.h>
42 #include "cifsproto.h"
43 #include "cifs_unicode.h"
44 #include "cifs_debug.h"
46 #include "smbdirect.h"
48 #ifdef CONFIG_CIFS_POSIX
53 #ifdef CONFIG_CIFS_WEAK_PW_HASH
54 {LANMAN_PROT, "\2LM1.2X002"},
55 {LANMAN2_PROT, "\2LANMAN2.1"},
56 #endif /* weak password hashing for legacy clients */
57 {CIFS_PROT, "\2NT LM 0.12"},
58 {POSIX_PROT, "\2POSIX 2"},
66 #ifdef CONFIG_CIFS_WEAK_PW_HASH
67 {LANMAN_PROT, "\2LM1.2X002"},
68 {LANMAN2_PROT, "\2LANMAN2.1"},
69 #endif /* weak password hashing for legacy clients */
70 {CIFS_PROT, "\2NT LM 0.12"},
75 /* define the number of elements in the cifs dialect array */
76 #ifdef CONFIG_CIFS_POSIX
77 #ifdef CONFIG_CIFS_WEAK_PW_HASH
78 #define CIFS_NUM_PROT 4
80 #define CIFS_NUM_PROT 2
81 #endif /* CIFS_WEAK_PW_HASH */
83 #ifdef CONFIG_CIFS_WEAK_PW_HASH
84 #define CIFS_NUM_PROT 3
86 #define CIFS_NUM_PROT 1
87 #endif /* CONFIG_CIFS_WEAK_PW_HASH */
88 #endif /* CIFS_POSIX */
91 * Mark as invalid, all open files on tree connections since they
92 * were closed when session to server was lost.
95 cifs_mark_open_files_invalid(struct cifs_tcon *tcon)
97 struct cifsFileInfo *open_file = NULL;
98 struct list_head *tmp;
99 struct list_head *tmp1;
101 /* list all files open on tree connection and mark them invalid */
102 spin_lock(&tcon->open_file_lock);
103 list_for_each_safe(tmp, tmp1, &tcon->openFileList) {
104 open_file = list_entry(tmp, struct cifsFileInfo, tlist);
105 open_file->invalidHandle = true;
106 open_file->oplock_break_cancelled = true;
108 spin_unlock(&tcon->open_file_lock);
110 * BB Add call to invalidate_inodes(sb) for all superblocks mounted
115 /* reconnect the socket, tcon, and smb session if needed */
117 cifs_reconnect_tcon(struct cifs_tcon *tcon, int smb_command)
120 struct cifs_ses *ses;
121 struct TCP_Server_Info *server;
122 struct nls_table *nls_codepage;
125 * SMBs NegProt, SessSetup, uLogoff do not have tcon yet so check for
126 * tcp and smb session status done differently for those three - in the
133 server = ses->server;
136 * only tree disconnect, open, and write, (and ulogoff which does not
137 * have tcon) are allowed as we start force umount
139 if (tcon->tidStatus == CifsExiting) {
140 if (smb_command != SMB_COM_WRITE_ANDX &&
141 smb_command != SMB_COM_OPEN_ANDX &&
142 smb_command != SMB_COM_TREE_DISCONNECT) {
143 cifs_dbg(FYI, "can not send cmd %d while umounting\n",
150 * Give demultiplex thread up to 10 seconds to reconnect, should be
151 * greater than cifs socket timeout which is 7 seconds
153 while (server->tcpStatus == CifsNeedReconnect) {
154 wait_event_interruptible_timeout(server->response_q,
155 (server->tcpStatus != CifsNeedReconnect), 10 * HZ);
157 /* are we still trying to reconnect? */
158 if (server->tcpStatus != CifsNeedReconnect)
162 * on "soft" mounts we wait once. Hard mounts keep
163 * retrying until process is killed or server comes
167 cifs_dbg(FYI, "gave up waiting on reconnect in smb_init\n");
172 if (!ses->need_reconnect && !tcon->need_reconnect)
175 nls_codepage = load_nls_default();
178 * need to prevent multiple threads trying to simultaneously
179 * reconnect the same SMB session
181 mutex_lock(&ses->session_mutex);
184 * Recheck after acquire mutex. If another thread is negotiating
185 * and the server never sends an answer the socket will be closed
186 * and tcpStatus set to reconnect.
188 if (server->tcpStatus == CifsNeedReconnect) {
190 mutex_unlock(&ses->session_mutex);
194 rc = cifs_negotiate_protocol(0, ses);
195 if (rc == 0 && ses->need_reconnect)
196 rc = cifs_setup_session(0, ses, nls_codepage);
198 /* do we need to reconnect tcon? */
199 if (rc || !tcon->need_reconnect) {
200 mutex_unlock(&ses->session_mutex);
204 cifs_mark_open_files_invalid(tcon);
205 rc = CIFSTCon(0, ses, tcon->treeName, tcon, nls_codepage);
206 mutex_unlock(&ses->session_mutex);
207 cifs_dbg(FYI, "reconnect tcon rc = %d\n", rc);
210 printk_once(KERN_WARNING "reconnect tcon failed rc = %d\n", rc);
214 atomic_inc(&tconInfoReconnectCount);
216 /* tell server Unix caps we support */
217 if (ses->capabilities & CAP_UNIX)
218 reset_cifs_unix_caps(0, tcon, NULL, NULL);
221 * Removed call to reopen open files here. It is safer (and faster) to
222 * reopen files one at a time as needed in read and write.
224 * FIXME: what about file locks? don't we need to reclaim them ASAP?
229 * Check if handle based operation so we know whether we can continue
230 * or not without returning to caller to reset file handle
232 switch (smb_command) {
233 case SMB_COM_READ_ANDX:
234 case SMB_COM_WRITE_ANDX:
236 case SMB_COM_FIND_CLOSE2:
237 case SMB_COM_LOCKING_ANDX:
241 unload_nls(nls_codepage);
245 /* Allocate and return pointer to an SMB request buffer, and set basic
246 SMB information in the SMB header. If the return code is zero, this
247 function must have filled in request_buf pointer */
249 small_smb_init(int smb_command, int wct, struct cifs_tcon *tcon,
254 rc = cifs_reconnect_tcon(tcon, smb_command);
258 *request_buf = cifs_small_buf_get();
259 if (*request_buf == NULL) {
260 /* BB should we add a retry in here if not a writepage? */
264 header_assemble((struct smb_hdr *) *request_buf, smb_command,
268 cifs_stats_inc(&tcon->num_smbs_sent);
274 small_smb_init_no_tc(const int smb_command, const int wct,
275 struct cifs_ses *ses, void **request_buf)
278 struct smb_hdr *buffer;
280 rc = small_smb_init(smb_command, wct, NULL, request_buf);
284 buffer = (struct smb_hdr *)*request_buf;
285 buffer->Mid = get_next_mid(ses->server);
286 if (ses->capabilities & CAP_UNICODE)
287 buffer->Flags2 |= SMBFLG2_UNICODE;
288 if (ses->capabilities & CAP_STATUS32)
289 buffer->Flags2 |= SMBFLG2_ERR_STATUS;
291 /* uid, tid can stay at zero as set in header assemble */
293 /* BB add support for turning on the signing when
294 this function is used after 1st of session setup requests */
299 /* If the return code is zero, this function must fill in request_buf pointer */
301 __smb_init(int smb_command, int wct, struct cifs_tcon *tcon,
302 void **request_buf, void **response_buf)
304 *request_buf = cifs_buf_get();
305 if (*request_buf == NULL) {
306 /* BB should we add a retry in here if not a writepage? */
309 /* Although the original thought was we needed the response buf for */
310 /* potential retries of smb operations it turns out we can determine */
311 /* from the mid flags when the request buffer can be resent without */
312 /* having to use a second distinct buffer for the response */
314 *response_buf = *request_buf;
316 header_assemble((struct smb_hdr *) *request_buf, smb_command, tcon,
320 cifs_stats_inc(&tcon->num_smbs_sent);
325 /* If the return code is zero, this function must fill in request_buf pointer */
327 smb_init(int smb_command, int wct, struct cifs_tcon *tcon,
328 void **request_buf, void **response_buf)
332 rc = cifs_reconnect_tcon(tcon, smb_command);
336 return __smb_init(smb_command, wct, tcon, request_buf, response_buf);
340 smb_init_no_reconnect(int smb_command, int wct, struct cifs_tcon *tcon,
341 void **request_buf, void **response_buf)
343 if (tcon->ses->need_reconnect || tcon->need_reconnect)
346 return __smb_init(smb_command, wct, tcon, request_buf, response_buf);
349 static int validate_t2(struct smb_t2_rsp *pSMB)
351 unsigned int total_size;
353 /* check for plausible wct */
354 if (pSMB->hdr.WordCount < 10)
357 /* check for parm and data offset going beyond end of smb */
358 if (get_unaligned_le16(&pSMB->t2_rsp.ParameterOffset) > 1024 ||
359 get_unaligned_le16(&pSMB->t2_rsp.DataOffset) > 1024)
362 total_size = get_unaligned_le16(&pSMB->t2_rsp.ParameterCount);
363 if (total_size >= 512)
366 /* check that bcc is at least as big as parms + data, and that it is
367 * less than negotiated smb buffer
369 total_size += get_unaligned_le16(&pSMB->t2_rsp.DataCount);
370 if (total_size > get_bcc(&pSMB->hdr) ||
371 total_size >= CIFSMaxBufSize + MAX_CIFS_HDR_SIZE)
376 cifs_dump_mem("Invalid transact2 SMB: ", (char *)pSMB,
377 sizeof(struct smb_t2_rsp) + 16);
382 decode_ext_sec_blob(struct cifs_ses *ses, NEGOTIATE_RSP *pSMBr)
386 char *guid = pSMBr->u.extended_response.GUID;
387 struct TCP_Server_Info *server = ses->server;
389 count = get_bcc(&pSMBr->hdr);
390 if (count < SMB1_CLIENT_GUID_SIZE)
393 spin_lock(&cifs_tcp_ses_lock);
394 if (server->srv_count > 1) {
395 spin_unlock(&cifs_tcp_ses_lock);
396 if (memcmp(server->server_GUID, guid, SMB1_CLIENT_GUID_SIZE) != 0) {
397 cifs_dbg(FYI, "server UID changed\n");
398 memcpy(server->server_GUID, guid, SMB1_CLIENT_GUID_SIZE);
401 spin_unlock(&cifs_tcp_ses_lock);
402 memcpy(server->server_GUID, guid, SMB1_CLIENT_GUID_SIZE);
405 if (count == SMB1_CLIENT_GUID_SIZE) {
406 server->sec_ntlmssp = true;
408 count -= SMB1_CLIENT_GUID_SIZE;
409 rc = decode_negTokenInit(
410 pSMBr->u.extended_response.SecurityBlob, count, server);
419 cifs_enable_signing(struct TCP_Server_Info *server, bool mnt_sign_required)
421 bool srv_sign_required = server->sec_mode & server->vals->signing_required;
422 bool srv_sign_enabled = server->sec_mode & server->vals->signing_enabled;
423 bool mnt_sign_enabled = global_secflags & CIFSSEC_MAY_SIGN;
426 * Is signing required by mnt options? If not then check
427 * global_secflags to see if it is there.
429 if (!mnt_sign_required)
430 mnt_sign_required = ((global_secflags & CIFSSEC_MUST_SIGN) ==
434 * If signing is required then it's automatically enabled too,
435 * otherwise, check to see if the secflags allow it.
437 mnt_sign_enabled = mnt_sign_required ? mnt_sign_required :
438 (global_secflags & CIFSSEC_MAY_SIGN);
440 /* If server requires signing, does client allow it? */
441 if (srv_sign_required) {
442 if (!mnt_sign_enabled) {
443 cifs_dbg(VFS, "Server requires signing, but it's disabled in SecurityFlags!");
449 /* If client requires signing, does server allow it? */
450 if (mnt_sign_required) {
451 if (!srv_sign_enabled) {
452 cifs_dbg(VFS, "Server does not support signing!");
461 #ifdef CONFIG_CIFS_WEAK_PW_HASH
463 decode_lanman_negprot_rsp(struct TCP_Server_Info *server, NEGOTIATE_RSP *pSMBr)
466 struct lanman_neg_rsp *rsp = (struct lanman_neg_rsp *)pSMBr;
468 if (server->dialect != LANMAN_PROT && server->dialect != LANMAN2_PROT)
471 server->sec_mode = le16_to_cpu(rsp->SecurityMode);
472 server->maxReq = min_t(unsigned int,
473 le16_to_cpu(rsp->MaxMpxCount),
475 set_credits(server, server->maxReq);
476 server->maxBuf = le16_to_cpu(rsp->MaxBufSize);
477 /* even though we do not use raw we might as well set this
478 accurately, in case we ever find a need for it */
479 if ((le16_to_cpu(rsp->RawMode) & RAW_ENABLE) == RAW_ENABLE) {
480 server->max_rw = 0xFF00;
481 server->capabilities = CAP_MPX_MODE | CAP_RAW_MODE;
483 server->max_rw = 0;/* do not need to use raw anyway */
484 server->capabilities = CAP_MPX_MODE;
486 tmp = (__s16)le16_to_cpu(rsp->ServerTimeZone);
488 /* OS/2 often does not set timezone therefore
489 * we must use server time to calc time zone.
490 * Could deviate slightly from the right zone.
491 * Smallest defined timezone difference is 15 minutes
492 * (i.e. Nepal). Rounding up/down is done to match
495 int val, seconds, remain, result;
497 unsigned long utc = ktime_get_real_seconds();
498 ts = cnvrtDosUnixTm(rsp->SrvTime.Date,
499 rsp->SrvTime.Time, 0);
500 cifs_dbg(FYI, "SrvTime %d sec since 1970 (utc: %d) diff: %d\n",
501 (int)ts.tv_sec, (int)utc,
502 (int)(utc - ts.tv_sec));
503 val = (int)(utc - ts.tv_sec);
505 result = (seconds / MIN_TZ_ADJ) * MIN_TZ_ADJ;
506 remain = seconds % MIN_TZ_ADJ;
507 if (remain >= (MIN_TZ_ADJ / 2))
508 result += MIN_TZ_ADJ;
511 server->timeAdj = result;
513 server->timeAdj = (int)tmp;
514 server->timeAdj *= 60; /* also in seconds */
516 cifs_dbg(FYI, "server->timeAdj: %d seconds\n", server->timeAdj);
519 /* BB get server time for time conversions and add
520 code to use it and timezone since this is not UTC */
522 if (rsp->EncryptionKeyLength ==
523 cpu_to_le16(CIFS_CRYPTO_KEY_SIZE)) {
524 memcpy(server->cryptkey, rsp->EncryptionKey,
525 CIFS_CRYPTO_KEY_SIZE);
526 } else if (server->sec_mode & SECMODE_PW_ENCRYPT) {
527 return -EIO; /* need cryptkey unless plain text */
530 cifs_dbg(FYI, "LANMAN negotiated\n");
535 decode_lanman_negprot_rsp(struct TCP_Server_Info *server, NEGOTIATE_RSP *pSMBr)
537 cifs_dbg(VFS, "mount failed, cifs module not built with CIFS_WEAK_PW_HASH support\n");
543 should_set_ext_sec_flag(enum securityEnum sectype)
550 if (global_secflags &
551 (CIFSSEC_MAY_KRB5 | CIFSSEC_MAY_NTLMSSP))
560 CIFSSMBNegotiate(const unsigned int xid, struct cifs_ses *ses)
563 NEGOTIATE_RSP *pSMBr;
567 struct TCP_Server_Info *server = ses->server;
571 WARN(1, "%s: server is NULL!\n", __func__);
575 rc = smb_init(SMB_COM_NEGOTIATE, 0, NULL /* no tcon yet */ ,
576 (void **) &pSMB, (void **) &pSMBr);
580 pSMB->hdr.Mid = get_next_mid(server);
581 pSMB->hdr.Flags2 |= (SMBFLG2_UNICODE | SMBFLG2_ERR_STATUS);
583 if (should_set_ext_sec_flag(ses->sectype)) {
584 cifs_dbg(FYI, "Requesting extended security.");
585 pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC;
589 for (i = 0; i < CIFS_NUM_PROT; i++) {
590 strncpy(pSMB->DialectsArray+count, protocols[i].name, 16);
591 count += strlen(protocols[i].name) + 1;
592 /* null at end of source and target buffers anyway */
594 inc_rfc1001_len(pSMB, count);
595 pSMB->ByteCount = cpu_to_le16(count);
597 rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB,
598 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
602 server->dialect = le16_to_cpu(pSMBr->DialectIndex);
603 cifs_dbg(FYI, "Dialect: %d\n", server->dialect);
604 /* Check wct = 1 error case */
605 if ((pSMBr->hdr.WordCount < 13) || (server->dialect == BAD_PROT)) {
606 /* core returns wct = 1, but we do not ask for core - otherwise
607 small wct just comes when dialect index is -1 indicating we
608 could not negotiate a common dialect */
611 } else if (pSMBr->hdr.WordCount == 13) {
612 server->negflavor = CIFS_NEGFLAVOR_LANMAN;
613 rc = decode_lanman_negprot_rsp(server, pSMBr);
615 } else if (pSMBr->hdr.WordCount != 17) {
620 /* else wct == 17, NTLM or better */
622 server->sec_mode = pSMBr->SecurityMode;
623 if ((server->sec_mode & SECMODE_USER) == 0)
624 cifs_dbg(FYI, "share mode security\n");
626 /* one byte, so no need to convert this or EncryptionKeyLen from
628 server->maxReq = min_t(unsigned int, le16_to_cpu(pSMBr->MaxMpxCount),
630 set_credits(server, server->maxReq);
631 /* probably no need to store and check maxvcs */
632 server->maxBuf = le32_to_cpu(pSMBr->MaxBufferSize);
633 server->max_rw = le32_to_cpu(pSMBr->MaxRawSize);
634 cifs_dbg(NOISY, "Max buf = %d\n", ses->server->maxBuf);
635 server->capabilities = le32_to_cpu(pSMBr->Capabilities);
636 server->timeAdj = (int)(__s16)le16_to_cpu(pSMBr->ServerTimeZone);
637 server->timeAdj *= 60;
639 if (pSMBr->EncryptionKeyLength == CIFS_CRYPTO_KEY_SIZE) {
640 server->negflavor = CIFS_NEGFLAVOR_UNENCAP;
641 memcpy(ses->server->cryptkey, pSMBr->u.EncryptionKey,
642 CIFS_CRYPTO_KEY_SIZE);
643 } else if (pSMBr->hdr.Flags2 & SMBFLG2_EXT_SEC ||
644 server->capabilities & CAP_EXTENDED_SECURITY) {
645 server->negflavor = CIFS_NEGFLAVOR_EXTENDED;
646 rc = decode_ext_sec_blob(ses, pSMBr);
647 } else if (server->sec_mode & SECMODE_PW_ENCRYPT) {
648 rc = -EIO; /* no crypt key only if plain text pwd */
650 server->negflavor = CIFS_NEGFLAVOR_UNENCAP;
651 server->capabilities &= ~CAP_EXTENDED_SECURITY;
656 rc = cifs_enable_signing(server, ses->sign);
658 cifs_buf_release(pSMB);
660 cifs_dbg(FYI, "negprot rc %d\n", rc);
665 CIFSSMBTDis(const unsigned int xid, struct cifs_tcon *tcon)
667 struct smb_hdr *smb_buffer;
670 cifs_dbg(FYI, "In tree disconnect\n");
672 /* BB: do we need to check this? These should never be NULL. */
673 if ((tcon->ses == NULL) || (tcon->ses->server == NULL))
677 * No need to return error on this operation if tid invalidated and
678 * closed on server already e.g. due to tcp session crashing. Also,
679 * the tcon is no longer on the list, so no need to take lock before
682 if ((tcon->need_reconnect) || (tcon->ses->need_reconnect))
685 rc = small_smb_init(SMB_COM_TREE_DISCONNECT, 0, tcon,
686 (void **)&smb_buffer);
690 rc = SendReceiveNoRsp(xid, tcon->ses, (char *)smb_buffer, 0);
691 cifs_small_buf_release(smb_buffer);
693 cifs_dbg(FYI, "Tree disconnect failed %d\n", rc);
695 /* No need to return error on this operation if tid invalidated and
696 closed on server already e.g. due to tcp session crashing */
704 * This is a no-op for now. We're not really interested in the reply, but
705 * rather in the fact that the server sent one and that server->lstrp
708 * FIXME: maybe we should consider checking that the reply matches request?
711 cifs_echo_callback(struct mid_q_entry *mid)
713 struct TCP_Server_Info *server = mid->callback_data;
715 DeleteMidQEntry(mid);
716 add_credits(server, 1, CIFS_ECHO_OP);
720 CIFSSMBEcho(struct TCP_Server_Info *server)
725 struct smb_rqst rqst = { .rq_iov = iov,
728 cifs_dbg(FYI, "In echo request\n");
730 rc = small_smb_init(SMB_COM_ECHO, 0, NULL, (void **)&smb);
734 if (server->capabilities & CAP_UNICODE)
735 smb->hdr.Flags2 |= SMBFLG2_UNICODE;
737 /* set up echo request */
738 smb->hdr.Tid = 0xffff;
739 smb->hdr.WordCount = 1;
740 put_unaligned_le16(1, &smb->EchoCount);
741 put_bcc(1, &smb->hdr);
743 inc_rfc1001_len(smb, 3);
746 iov[0].iov_base = smb;
747 iov[1].iov_len = get_rfc1002_length(smb);
748 iov[1].iov_base = (char *)smb + 4;
750 rc = cifs_call_async(server, &rqst, NULL, cifs_echo_callback, NULL,
751 server, CIFS_ASYNC_OP | CIFS_ECHO_OP);
753 cifs_dbg(FYI, "Echo request failed: %d\n", rc);
755 cifs_small_buf_release(smb);
761 CIFSSMBLogoff(const unsigned int xid, struct cifs_ses *ses)
763 LOGOFF_ANDX_REQ *pSMB;
766 cifs_dbg(FYI, "In SMBLogoff for session disconnect\n");
769 * BB: do we need to check validity of ses and server? They should
770 * always be valid since we have an active reference. If not, that
771 * should probably be a BUG()
773 if (!ses || !ses->server)
776 mutex_lock(&ses->session_mutex);
777 if (ses->need_reconnect)
778 goto session_already_dead; /* no need to send SMBlogoff if uid
779 already closed due to reconnect */
780 rc = small_smb_init(SMB_COM_LOGOFF_ANDX, 2, NULL, (void **)&pSMB);
782 mutex_unlock(&ses->session_mutex);
786 pSMB->hdr.Mid = get_next_mid(ses->server);
788 if (ses->server->sign)
789 pSMB->hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
791 pSMB->hdr.Uid = ses->Suid;
793 pSMB->AndXCommand = 0xFF;
794 rc = SendReceiveNoRsp(xid, ses, (char *) pSMB, 0);
795 cifs_small_buf_release(pSMB);
796 session_already_dead:
797 mutex_unlock(&ses->session_mutex);
799 /* if session dead then we do not need to do ulogoff,
800 since server closed smb session, no sense reporting
808 CIFSPOSIXDelFile(const unsigned int xid, struct cifs_tcon *tcon,
809 const char *fileName, __u16 type,
810 const struct nls_table *nls_codepage, int remap)
812 TRANSACTION2_SPI_REQ *pSMB = NULL;
813 TRANSACTION2_SPI_RSP *pSMBr = NULL;
814 struct unlink_psx_rq *pRqD;
817 int bytes_returned = 0;
818 __u16 params, param_offset, offset, byte_count;
820 cifs_dbg(FYI, "In POSIX delete\n");
822 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
827 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
829 cifsConvertToUTF16((__le16 *) pSMB->FileName, fileName,
830 PATH_MAX, nls_codepage, remap);
831 name_len++; /* trailing null */
833 } else { /* BB add path length overrun check */
834 name_len = strnlen(fileName, PATH_MAX);
835 name_len++; /* trailing null */
836 strncpy(pSMB->FileName, fileName, name_len);
839 params = 6 + name_len;
840 pSMB->MaxParameterCount = cpu_to_le16(2);
841 pSMB->MaxDataCount = 0; /* BB double check this with jra */
842 pSMB->MaxSetupCount = 0;
847 param_offset = offsetof(struct smb_com_transaction2_spi_req,
848 InformationLevel) - 4;
849 offset = param_offset + params;
851 /* Setup pointer to Request Data (inode type) */
852 pRqD = (struct unlink_psx_rq *)(((char *)&pSMB->hdr.Protocol) + offset);
853 pRqD->type = cpu_to_le16(type);
854 pSMB->ParameterOffset = cpu_to_le16(param_offset);
855 pSMB->DataOffset = cpu_to_le16(offset);
856 pSMB->SetupCount = 1;
858 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
859 byte_count = 3 /* pad */ + params + sizeof(struct unlink_psx_rq);
861 pSMB->DataCount = cpu_to_le16(sizeof(struct unlink_psx_rq));
862 pSMB->TotalDataCount = cpu_to_le16(sizeof(struct unlink_psx_rq));
863 pSMB->ParameterCount = cpu_to_le16(params);
864 pSMB->TotalParameterCount = pSMB->ParameterCount;
865 pSMB->InformationLevel = cpu_to_le16(SMB_POSIX_UNLINK);
867 inc_rfc1001_len(pSMB, byte_count);
868 pSMB->ByteCount = cpu_to_le16(byte_count);
869 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
870 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
872 cifs_dbg(FYI, "Posix delete returned %d\n", rc);
873 cifs_buf_release(pSMB);
875 cifs_stats_inc(&tcon->stats.cifs_stats.num_deletes);
884 CIFSSMBDelFile(const unsigned int xid, struct cifs_tcon *tcon, const char *name,
885 struct cifs_sb_info *cifs_sb)
887 DELETE_FILE_REQ *pSMB = NULL;
888 DELETE_FILE_RSP *pSMBr = NULL;
892 int remap = cifs_remap(cifs_sb);
895 rc = smb_init(SMB_COM_DELETE, 1, tcon, (void **) &pSMB,
900 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
901 name_len = cifsConvertToUTF16((__le16 *) pSMB->fileName, name,
902 PATH_MAX, cifs_sb->local_nls,
904 name_len++; /* trailing null */
906 } else { /* BB improve check for buffer overruns BB */
907 name_len = strnlen(name, PATH_MAX);
908 name_len++; /* trailing null */
909 strncpy(pSMB->fileName, name, name_len);
911 pSMB->SearchAttributes =
912 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM);
913 pSMB->BufferFormat = 0x04;
914 inc_rfc1001_len(pSMB, name_len + 1);
915 pSMB->ByteCount = cpu_to_le16(name_len + 1);
916 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
917 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
918 cifs_stats_inc(&tcon->stats.cifs_stats.num_deletes);
920 cifs_dbg(FYI, "Error in RMFile = %d\n", rc);
922 cifs_buf_release(pSMB);
930 CIFSSMBRmDir(const unsigned int xid, struct cifs_tcon *tcon, const char *name,
931 struct cifs_sb_info *cifs_sb)
933 DELETE_DIRECTORY_REQ *pSMB = NULL;
934 DELETE_DIRECTORY_RSP *pSMBr = NULL;
938 int remap = cifs_remap(cifs_sb);
940 cifs_dbg(FYI, "In CIFSSMBRmDir\n");
942 rc = smb_init(SMB_COM_DELETE_DIRECTORY, 0, tcon, (void **) &pSMB,
947 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
948 name_len = cifsConvertToUTF16((__le16 *) pSMB->DirName, name,
949 PATH_MAX, cifs_sb->local_nls,
951 name_len++; /* trailing null */
953 } else { /* BB improve check for buffer overruns BB */
954 name_len = strnlen(name, PATH_MAX);
955 name_len++; /* trailing null */
956 strncpy(pSMB->DirName, name, name_len);
959 pSMB->BufferFormat = 0x04;
960 inc_rfc1001_len(pSMB, name_len + 1);
961 pSMB->ByteCount = cpu_to_le16(name_len + 1);
962 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
963 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
964 cifs_stats_inc(&tcon->stats.cifs_stats.num_rmdirs);
966 cifs_dbg(FYI, "Error in RMDir = %d\n", rc);
968 cifs_buf_release(pSMB);
975 CIFSSMBMkDir(const unsigned int xid, struct cifs_tcon *tcon, const char *name,
976 struct cifs_sb_info *cifs_sb)
979 CREATE_DIRECTORY_REQ *pSMB = NULL;
980 CREATE_DIRECTORY_RSP *pSMBr = NULL;
983 int remap = cifs_remap(cifs_sb);
985 cifs_dbg(FYI, "In CIFSSMBMkDir\n");
987 rc = smb_init(SMB_COM_CREATE_DIRECTORY, 0, tcon, (void **) &pSMB,
992 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
993 name_len = cifsConvertToUTF16((__le16 *) pSMB->DirName, name,
994 PATH_MAX, cifs_sb->local_nls,
996 name_len++; /* trailing null */
998 } else { /* BB improve check for buffer overruns BB */
999 name_len = strnlen(name, PATH_MAX);
1000 name_len++; /* trailing null */
1001 strncpy(pSMB->DirName, name, name_len);
1004 pSMB->BufferFormat = 0x04;
1005 inc_rfc1001_len(pSMB, name_len + 1);
1006 pSMB->ByteCount = cpu_to_le16(name_len + 1);
1007 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1008 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1009 cifs_stats_inc(&tcon->stats.cifs_stats.num_mkdirs);
1011 cifs_dbg(FYI, "Error in Mkdir = %d\n", rc);
1013 cifs_buf_release(pSMB);
1020 CIFSPOSIXCreate(const unsigned int xid, struct cifs_tcon *tcon,
1021 __u32 posix_flags, __u64 mode, __u16 *netfid,
1022 FILE_UNIX_BASIC_INFO *pRetData, __u32 *pOplock,
1023 const char *name, const struct nls_table *nls_codepage,
1026 TRANSACTION2_SPI_REQ *pSMB = NULL;
1027 TRANSACTION2_SPI_RSP *pSMBr = NULL;
1030 int bytes_returned = 0;
1031 __u16 params, param_offset, offset, byte_count, count;
1032 OPEN_PSX_REQ *pdata;
1033 OPEN_PSX_RSP *psx_rsp;
1035 cifs_dbg(FYI, "In POSIX Create\n");
1037 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
1042 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1044 cifsConvertToUTF16((__le16 *) pSMB->FileName, name,
1045 PATH_MAX, nls_codepage, remap);
1046 name_len++; /* trailing null */
1048 } else { /* BB improve the check for buffer overruns BB */
1049 name_len = strnlen(name, PATH_MAX);
1050 name_len++; /* trailing null */
1051 strncpy(pSMB->FileName, name, name_len);
1054 params = 6 + name_len;
1055 count = sizeof(OPEN_PSX_REQ);
1056 pSMB->MaxParameterCount = cpu_to_le16(2);
1057 pSMB->MaxDataCount = cpu_to_le16(1000); /* large enough */
1058 pSMB->MaxSetupCount = 0;
1062 pSMB->Reserved2 = 0;
1063 param_offset = offsetof(struct smb_com_transaction2_spi_req,
1064 InformationLevel) - 4;
1065 offset = param_offset + params;
1066 pdata = (OPEN_PSX_REQ *)(((char *)&pSMB->hdr.Protocol) + offset);
1067 pdata->Level = cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC);
1068 pdata->Permissions = cpu_to_le64(mode);
1069 pdata->PosixOpenFlags = cpu_to_le32(posix_flags);
1070 pdata->OpenFlags = cpu_to_le32(*pOplock);
1071 pSMB->ParameterOffset = cpu_to_le16(param_offset);
1072 pSMB->DataOffset = cpu_to_le16(offset);
1073 pSMB->SetupCount = 1;
1074 pSMB->Reserved3 = 0;
1075 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
1076 byte_count = 3 /* pad */ + params + count;
1078 pSMB->DataCount = cpu_to_le16(count);
1079 pSMB->ParameterCount = cpu_to_le16(params);
1080 pSMB->TotalDataCount = pSMB->DataCount;
1081 pSMB->TotalParameterCount = pSMB->ParameterCount;
1082 pSMB->InformationLevel = cpu_to_le16(SMB_POSIX_OPEN);
1083 pSMB->Reserved4 = 0;
1084 inc_rfc1001_len(pSMB, byte_count);
1085 pSMB->ByteCount = cpu_to_le16(byte_count);
1086 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1087 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1089 cifs_dbg(FYI, "Posix create returned %d\n", rc);
1090 goto psx_create_err;
1093 cifs_dbg(FYI, "copying inode info\n");
1094 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
1096 if (rc || get_bcc(&pSMBr->hdr) < sizeof(OPEN_PSX_RSP)) {
1097 rc = -EIO; /* bad smb */
1098 goto psx_create_err;
1101 /* copy return information to pRetData */
1102 psx_rsp = (OPEN_PSX_RSP *)((char *) &pSMBr->hdr.Protocol
1103 + le16_to_cpu(pSMBr->t2.DataOffset));
1105 *pOplock = le16_to_cpu(psx_rsp->OplockFlags);
1107 *netfid = psx_rsp->Fid; /* cifs fid stays in le */
1108 /* Let caller know file was created so we can set the mode. */
1109 /* Do we care about the CreateAction in any other cases? */
1110 if (cpu_to_le32(FILE_CREATE) == psx_rsp->CreateAction)
1111 *pOplock |= CIFS_CREATE_ACTION;
1112 /* check to make sure response data is there */
1113 if (psx_rsp->ReturnedLevel != cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC)) {
1114 pRetData->Type = cpu_to_le32(-1); /* unknown */
1115 cifs_dbg(NOISY, "unknown type\n");
1117 if (get_bcc(&pSMBr->hdr) < sizeof(OPEN_PSX_RSP)
1118 + sizeof(FILE_UNIX_BASIC_INFO)) {
1119 cifs_dbg(VFS, "Open response data too small\n");
1120 pRetData->Type = cpu_to_le32(-1);
1121 goto psx_create_err;
1123 memcpy((char *) pRetData,
1124 (char *)psx_rsp + sizeof(OPEN_PSX_RSP),
1125 sizeof(FILE_UNIX_BASIC_INFO));
1129 cifs_buf_release(pSMB);
1131 if (posix_flags & SMB_O_DIRECTORY)
1132 cifs_stats_inc(&tcon->stats.cifs_stats.num_posixmkdirs);
1134 cifs_stats_inc(&tcon->stats.cifs_stats.num_posixopens);
1142 static __u16 convert_disposition(int disposition)
1146 switch (disposition) {
1147 case FILE_SUPERSEDE:
1148 ofun = SMBOPEN_OCREATE | SMBOPEN_OTRUNC;
1151 ofun = SMBOPEN_OAPPEND;
1154 ofun = SMBOPEN_OCREATE;
1157 ofun = SMBOPEN_OCREATE | SMBOPEN_OAPPEND;
1159 case FILE_OVERWRITE:
1160 ofun = SMBOPEN_OTRUNC;
1162 case FILE_OVERWRITE_IF:
1163 ofun = SMBOPEN_OCREATE | SMBOPEN_OTRUNC;
1166 cifs_dbg(FYI, "unknown disposition %d\n", disposition);
1167 ofun = SMBOPEN_OAPPEND; /* regular open */
1173 access_flags_to_smbopen_mode(const int access_flags)
1175 int masked_flags = access_flags & (GENERIC_READ | GENERIC_WRITE);
1177 if (masked_flags == GENERIC_READ)
1178 return SMBOPEN_READ;
1179 else if (masked_flags == GENERIC_WRITE)
1180 return SMBOPEN_WRITE;
1182 /* just go for read/write */
1183 return SMBOPEN_READWRITE;
1187 SMBLegacyOpen(const unsigned int xid, struct cifs_tcon *tcon,
1188 const char *fileName, const int openDisposition,
1189 const int access_flags, const int create_options, __u16 *netfid,
1190 int *pOplock, FILE_ALL_INFO *pfile_info,
1191 const struct nls_table *nls_codepage, int remap)
1194 OPENX_REQ *pSMB = NULL;
1195 OPENX_RSP *pSMBr = NULL;
1201 rc = smb_init(SMB_COM_OPEN_ANDX, 15, tcon, (void **) &pSMB,
1206 pSMB->AndXCommand = 0xFF; /* none */
1208 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1209 count = 1; /* account for one byte pad to word boundary */
1211 cifsConvertToUTF16((__le16 *) (pSMB->fileName + 1),
1212 fileName, PATH_MAX, nls_codepage, remap);
1213 name_len++; /* trailing null */
1215 } else { /* BB improve check for buffer overruns BB */
1216 count = 0; /* no pad */
1217 name_len = strnlen(fileName, PATH_MAX);
1218 name_len++; /* trailing null */
1219 strncpy(pSMB->fileName, fileName, name_len);
1221 if (*pOplock & REQ_OPLOCK)
1222 pSMB->OpenFlags = cpu_to_le16(REQ_OPLOCK);
1223 else if (*pOplock & REQ_BATCHOPLOCK)
1224 pSMB->OpenFlags = cpu_to_le16(REQ_BATCHOPLOCK);
1226 pSMB->OpenFlags |= cpu_to_le16(REQ_MORE_INFO);
1227 pSMB->Mode = cpu_to_le16(access_flags_to_smbopen_mode(access_flags));
1228 pSMB->Mode |= cpu_to_le16(0x40); /* deny none */
1229 /* set file as system file if special file such
1230 as fifo and server expecting SFU style and
1231 no Unix extensions */
1233 if (create_options & CREATE_OPTION_SPECIAL)
1234 pSMB->FileAttributes = cpu_to_le16(ATTR_SYSTEM);
1235 else /* BB FIXME BB */
1236 pSMB->FileAttributes = cpu_to_le16(0/*ATTR_NORMAL*/);
1238 if (create_options & CREATE_OPTION_READONLY)
1239 pSMB->FileAttributes |= cpu_to_le16(ATTR_READONLY);
1242 /* pSMB->CreateOptions = cpu_to_le32(create_options &
1243 CREATE_OPTIONS_MASK); */
1244 /* BB FIXME END BB */
1246 pSMB->Sattr = cpu_to_le16(ATTR_HIDDEN | ATTR_SYSTEM | ATTR_DIRECTORY);
1247 pSMB->OpenFunction = cpu_to_le16(convert_disposition(openDisposition));
1249 inc_rfc1001_len(pSMB, count);
1251 pSMB->ByteCount = cpu_to_le16(count);
1252 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1253 (struct smb_hdr *)pSMBr, &bytes_returned, 0);
1254 cifs_stats_inc(&tcon->stats.cifs_stats.num_opens);
1256 cifs_dbg(FYI, "Error in Open = %d\n", rc);
1258 /* BB verify if wct == 15 */
1260 /* *pOplock = pSMBr->OplockLevel; */ /* BB take from action field*/
1262 *netfid = pSMBr->Fid; /* cifs fid stays in le */
1263 /* Let caller know file was created so we can set the mode. */
1264 /* Do we care about the CreateAction in any other cases? */
1266 /* if (cpu_to_le32(FILE_CREATE) == pSMBr->CreateAction)
1267 *pOplock |= CIFS_CREATE_ACTION; */
1271 pfile_info->CreationTime = 0; /* BB convert CreateTime*/
1272 pfile_info->LastAccessTime = 0; /* BB fixme */
1273 pfile_info->LastWriteTime = 0; /* BB fixme */
1274 pfile_info->ChangeTime = 0; /* BB fixme */
1275 pfile_info->Attributes =
1276 cpu_to_le32(le16_to_cpu(pSMBr->FileAttributes));
1277 /* the file_info buf is endian converted by caller */
1278 pfile_info->AllocationSize =
1279 cpu_to_le64(le32_to_cpu(pSMBr->EndOfFile));
1280 pfile_info->EndOfFile = pfile_info->AllocationSize;
1281 pfile_info->NumberOfLinks = cpu_to_le32(1);
1282 pfile_info->DeletePending = 0;
1286 cifs_buf_release(pSMB);
1293 CIFS_open(const unsigned int xid, struct cifs_open_parms *oparms, int *oplock,
1297 OPEN_REQ *req = NULL;
1298 OPEN_RSP *rsp = NULL;
1302 struct cifs_sb_info *cifs_sb = oparms->cifs_sb;
1303 struct cifs_tcon *tcon = oparms->tcon;
1304 int remap = cifs_remap(cifs_sb);
1305 const struct nls_table *nls = cifs_sb->local_nls;
1306 int create_options = oparms->create_options;
1307 int desired_access = oparms->desired_access;
1308 int disposition = oparms->disposition;
1309 const char *path = oparms->path;
1312 rc = smb_init(SMB_COM_NT_CREATE_ANDX, 24, tcon, (void **)&req,
1317 /* no commands go after this */
1318 req->AndXCommand = 0xFF;
1320 if (req->hdr.Flags2 & SMBFLG2_UNICODE) {
1321 /* account for one byte pad to word boundary */
1323 name_len = cifsConvertToUTF16((__le16 *)(req->fileName + 1),
1324 path, PATH_MAX, nls, remap);
1328 req->NameLength = cpu_to_le16(name_len);
1330 /* BB improve check for buffer overruns BB */
1333 name_len = strnlen(path, PATH_MAX);
1336 req->NameLength = cpu_to_le16(name_len);
1337 strncpy(req->fileName, path, name_len);
1340 if (*oplock & REQ_OPLOCK)
1341 req->OpenFlags = cpu_to_le32(REQ_OPLOCK);
1342 else if (*oplock & REQ_BATCHOPLOCK)
1343 req->OpenFlags = cpu_to_le32(REQ_BATCHOPLOCK);
1345 req->DesiredAccess = cpu_to_le32(desired_access);
1346 req->AllocationSize = 0;
1349 * Set file as system file if special file such as fifo and server
1350 * expecting SFU style and no Unix extensions.
1352 if (create_options & CREATE_OPTION_SPECIAL)
1353 req->FileAttributes = cpu_to_le32(ATTR_SYSTEM);
1355 req->FileAttributes = cpu_to_le32(ATTR_NORMAL);
1358 * XP does not handle ATTR_POSIX_SEMANTICS but it helps speed up case
1359 * sensitive checks for other servers such as Samba.
1361 if (tcon->ses->capabilities & CAP_UNIX)
1362 req->FileAttributes |= cpu_to_le32(ATTR_POSIX_SEMANTICS);
1364 if (create_options & CREATE_OPTION_READONLY)
1365 req->FileAttributes |= cpu_to_le32(ATTR_READONLY);
1367 req->ShareAccess = cpu_to_le32(FILE_SHARE_ALL);
1368 req->CreateDisposition = cpu_to_le32(disposition);
1369 req->CreateOptions = cpu_to_le32(create_options & CREATE_OPTIONS_MASK);
1371 /* BB Expirement with various impersonation levels and verify */
1372 req->ImpersonationLevel = cpu_to_le32(SECURITY_IMPERSONATION);
1373 req->SecurityFlags = SECURITY_CONTEXT_TRACKING|SECURITY_EFFECTIVE_ONLY;
1376 inc_rfc1001_len(req, count);
1378 req->ByteCount = cpu_to_le16(count);
1379 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *)req,
1380 (struct smb_hdr *)rsp, &bytes_returned, 0);
1381 cifs_stats_inc(&tcon->stats.cifs_stats.num_opens);
1383 cifs_dbg(FYI, "Error in Open = %d\n", rc);
1384 cifs_buf_release(req);
1390 /* 1 byte no need to le_to_cpu */
1391 *oplock = rsp->OplockLevel;
1392 /* cifs fid stays in le */
1393 oparms->fid->netfid = rsp->Fid;
1395 /* Let caller know file was created so we can set the mode. */
1396 /* Do we care about the CreateAction in any other cases? */
1397 if (cpu_to_le32(FILE_CREATE) == rsp->CreateAction)
1398 *oplock |= CIFS_CREATE_ACTION;
1401 /* copy from CreationTime to Attributes */
1402 memcpy((char *)buf, (char *)&rsp->CreationTime, 36);
1403 /* the file_info buf is endian converted by caller */
1404 buf->AllocationSize = rsp->AllocationSize;
1405 buf->EndOfFile = rsp->EndOfFile;
1406 buf->NumberOfLinks = cpu_to_le32(1);
1407 buf->DeletePending = 0;
1410 cifs_buf_release(req);
1415 * Discard any remaining data in the current SMB. To do this, we borrow the
1419 cifs_discard_remaining_data(struct TCP_Server_Info *server)
1421 unsigned int rfclen = server->pdu_size;
1422 int remaining = rfclen + server->vals->header_preamble_size -
1425 while (remaining > 0) {
1428 length = cifs_read_from_socket(server, server->bigbuf,
1429 min_t(unsigned int, remaining,
1430 CIFSMaxBufSize + MAX_HEADER_SIZE(server)));
1433 server->total_read += length;
1434 remaining -= length;
1441 cifs_readv_discard(struct TCP_Server_Info *server, struct mid_q_entry *mid)
1444 struct cifs_readdata *rdata = mid->callback_data;
1446 length = cifs_discard_remaining_data(server);
1447 dequeue_mid(mid, rdata->result);
1448 mid->resp_buf = server->smallbuf;
1449 server->smallbuf = NULL;
1454 cifs_readv_receive(struct TCP_Server_Info *server, struct mid_q_entry *mid)
1457 unsigned int data_offset, data_len;
1458 struct cifs_readdata *rdata = mid->callback_data;
1459 char *buf = server->smallbuf;
1460 unsigned int buflen = server->pdu_size +
1461 server->vals->header_preamble_size;
1462 bool use_rdma_mr = false;
1464 cifs_dbg(FYI, "%s: mid=%llu offset=%llu bytes=%u\n",
1465 __func__, mid->mid, rdata->offset, rdata->bytes);
1468 * read the rest of READ_RSP header (sans Data array), or whatever we
1469 * can if there's not enough data. At this point, we've read down to
1472 len = min_t(unsigned int, buflen, server->vals->read_rsp_size) -
1473 HEADER_SIZE(server) + 1;
1475 length = cifs_read_from_socket(server,
1476 buf + HEADER_SIZE(server) - 1, len);
1479 server->total_read += length;
1481 if (server->ops->is_session_expired &&
1482 server->ops->is_session_expired(buf)) {
1483 cifs_reconnect(server);
1484 wake_up(&server->response_q);
1488 if (server->ops->is_status_pending &&
1489 server->ops->is_status_pending(buf, server, 0)) {
1490 cifs_discard_remaining_data(server);
1494 /* Was the SMB read successful? */
1495 rdata->result = server->ops->map_error(buf, false);
1496 if (rdata->result != 0) {
1497 cifs_dbg(FYI, "%s: server returned error %d\n",
1498 __func__, rdata->result);
1499 return cifs_readv_discard(server, mid);
1502 /* Is there enough to get to the rest of the READ_RSP header? */
1503 if (server->total_read < server->vals->read_rsp_size) {
1504 cifs_dbg(FYI, "%s: server returned short header. got=%u expected=%zu\n",
1505 __func__, server->total_read,
1506 server->vals->read_rsp_size);
1507 rdata->result = -EIO;
1508 return cifs_readv_discard(server, mid);
1511 data_offset = server->ops->read_data_offset(buf) +
1512 server->vals->header_preamble_size;
1513 if (data_offset < server->total_read) {
1515 * win2k8 sometimes sends an offset of 0 when the read
1516 * is beyond the EOF. Treat it as if the data starts just after
1519 cifs_dbg(FYI, "%s: data offset (%u) inside read response header\n",
1520 __func__, data_offset);
1521 data_offset = server->total_read;
1522 } else if (data_offset > MAX_CIFS_SMALL_BUFFER_SIZE) {
1523 /* data_offset is beyond the end of smallbuf */
1524 cifs_dbg(FYI, "%s: data offset (%u) beyond end of smallbuf\n",
1525 __func__, data_offset);
1526 rdata->result = -EIO;
1527 return cifs_readv_discard(server, mid);
1530 cifs_dbg(FYI, "%s: total_read=%u data_offset=%u\n",
1531 __func__, server->total_read, data_offset);
1533 len = data_offset - server->total_read;
1535 /* read any junk before data into the rest of smallbuf */
1536 length = cifs_read_from_socket(server,
1537 buf + server->total_read, len);
1540 server->total_read += length;
1543 /* set up first iov for signature check */
1544 rdata->iov[0].iov_base = buf;
1545 rdata->iov[0].iov_len = 4;
1546 rdata->iov[1].iov_base = buf + 4;
1547 rdata->iov[1].iov_len = server->total_read - 4;
1548 cifs_dbg(FYI, "0: iov_base=%p iov_len=%u\n",
1549 rdata->iov[0].iov_base, server->total_read);
1551 /* how much data is in the response? */
1552 #ifdef CONFIG_CIFS_SMB_DIRECT
1553 use_rdma_mr = rdata->mr;
1555 data_len = server->ops->read_data_length(buf, use_rdma_mr);
1556 if (!use_rdma_mr && (data_offset + data_len > buflen)) {
1557 /* data_len is corrupt -- discard frame */
1558 rdata->result = -EIO;
1559 return cifs_readv_discard(server, mid);
1562 length = rdata->read_into_pages(server, rdata, data_len);
1566 server->total_read += length;
1568 cifs_dbg(FYI, "total_read=%u buflen=%u remaining=%u\n",
1569 server->total_read, buflen, data_len);
1571 /* discard anything left over */
1572 if (server->total_read < buflen)
1573 return cifs_readv_discard(server, mid);
1575 dequeue_mid(mid, false);
1576 mid->resp_buf = server->smallbuf;
1577 server->smallbuf = NULL;
1582 cifs_readv_callback(struct mid_q_entry *mid)
1584 struct cifs_readdata *rdata = mid->callback_data;
1585 struct cifs_tcon *tcon = tlink_tcon(rdata->cfile->tlink);
1586 struct TCP_Server_Info *server = tcon->ses->server;
1587 struct smb_rqst rqst = { .rq_iov = rdata->iov,
1589 .rq_pages = rdata->pages,
1590 .rq_npages = rdata->nr_pages,
1591 .rq_pagesz = rdata->pagesz,
1592 .rq_tailsz = rdata->tailsz };
1594 cifs_dbg(FYI, "%s: mid=%llu state=%d result=%d bytes=%u\n",
1595 __func__, mid->mid, mid->mid_state, rdata->result,
1598 switch (mid->mid_state) {
1599 case MID_RESPONSE_RECEIVED:
1600 /* result already set, check signature */
1604 rc = cifs_verify_signature(&rqst, server,
1605 mid->sequence_number);
1607 cifs_dbg(VFS, "SMB signature verification returned error = %d\n",
1610 /* FIXME: should this be counted toward the initiating task? */
1611 task_io_account_read(rdata->got_bytes);
1612 cifs_stats_bytes_read(tcon, rdata->got_bytes);
1614 case MID_REQUEST_SUBMITTED:
1615 case MID_RETRY_NEEDED:
1616 rdata->result = -EAGAIN;
1617 if (server->sign && rdata->got_bytes)
1618 /* reset bytes number since we can not check a sign */
1619 rdata->got_bytes = 0;
1620 /* FIXME: should this be counted toward the initiating task? */
1621 task_io_account_read(rdata->got_bytes);
1622 cifs_stats_bytes_read(tcon, rdata->got_bytes);
1625 rdata->result = -EIO;
1628 queue_work(cifsiod_wq, &rdata->work);
1629 DeleteMidQEntry(mid);
1630 add_credits(server, 1, 0);
1633 /* cifs_async_readv - send an async write, and set up mid to handle result */
1635 cifs_async_readv(struct cifs_readdata *rdata)
1638 READ_REQ *smb = NULL;
1640 struct cifs_tcon *tcon = tlink_tcon(rdata->cfile->tlink);
1641 struct smb_rqst rqst = { .rq_iov = rdata->iov,
1644 cifs_dbg(FYI, "%s: offset=%llu bytes=%u\n",
1645 __func__, rdata->offset, rdata->bytes);
1647 if (tcon->ses->capabilities & CAP_LARGE_FILES)
1650 wct = 10; /* old style read */
1651 if ((rdata->offset >> 32) > 0) {
1652 /* can not handle this big offset for old */
1657 rc = small_smb_init(SMB_COM_READ_ANDX, wct, tcon, (void **)&smb);
1661 smb->hdr.Pid = cpu_to_le16((__u16)rdata->pid);
1662 smb->hdr.PidHigh = cpu_to_le16((__u16)(rdata->pid >> 16));
1664 smb->AndXCommand = 0xFF; /* none */
1665 smb->Fid = rdata->cfile->fid.netfid;
1666 smb->OffsetLow = cpu_to_le32(rdata->offset & 0xFFFFFFFF);
1668 smb->OffsetHigh = cpu_to_le32(rdata->offset >> 32);
1670 smb->MaxCount = cpu_to_le16(rdata->bytes & 0xFFFF);
1671 smb->MaxCountHigh = cpu_to_le32(rdata->bytes >> 16);
1675 /* old style read */
1676 struct smb_com_readx_req *smbr =
1677 (struct smb_com_readx_req *)smb;
1678 smbr->ByteCount = 0;
1681 /* 4 for RFC1001 length + 1 for BCC */
1682 rdata->iov[0].iov_base = smb;
1683 rdata->iov[0].iov_len = 4;
1684 rdata->iov[1].iov_base = (char *)smb + 4;
1685 rdata->iov[1].iov_len = get_rfc1002_length(smb);
1687 kref_get(&rdata->refcount);
1688 rc = cifs_call_async(tcon->ses->server, &rqst, cifs_readv_receive,
1689 cifs_readv_callback, NULL, rdata, 0);
1692 cifs_stats_inc(&tcon->stats.cifs_stats.num_reads);
1694 kref_put(&rdata->refcount, cifs_readdata_release);
1696 cifs_small_buf_release(smb);
1701 CIFSSMBRead(const unsigned int xid, struct cifs_io_parms *io_parms,
1702 unsigned int *nbytes, char **buf, int *pbuf_type)
1705 READ_REQ *pSMB = NULL;
1706 READ_RSP *pSMBr = NULL;
1707 char *pReadData = NULL;
1709 int resp_buf_type = 0;
1711 struct kvec rsp_iov;
1712 __u32 pid = io_parms->pid;
1713 __u16 netfid = io_parms->netfid;
1714 __u64 offset = io_parms->offset;
1715 struct cifs_tcon *tcon = io_parms->tcon;
1716 unsigned int count = io_parms->length;
1718 cifs_dbg(FYI, "Reading %d bytes on fid %d\n", count, netfid);
1719 if (tcon->ses->capabilities & CAP_LARGE_FILES)
1722 wct = 10; /* old style read */
1723 if ((offset >> 32) > 0) {
1724 /* can not handle this big offset for old */
1730 rc = small_smb_init(SMB_COM_READ_ANDX, wct, tcon, (void **) &pSMB);
1734 pSMB->hdr.Pid = cpu_to_le16((__u16)pid);
1735 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid >> 16));
1737 /* tcon and ses pointer are checked in smb_init */
1738 if (tcon->ses->server == NULL)
1739 return -ECONNABORTED;
1741 pSMB->AndXCommand = 0xFF; /* none */
1743 pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF);
1745 pSMB->OffsetHigh = cpu_to_le32(offset >> 32);
1747 pSMB->Remaining = 0;
1748 pSMB->MaxCount = cpu_to_le16(count & 0xFFFF);
1749 pSMB->MaxCountHigh = cpu_to_le32(count >> 16);
1751 pSMB->ByteCount = 0; /* no need to do le conversion since 0 */
1753 /* old style read */
1754 struct smb_com_readx_req *pSMBW =
1755 (struct smb_com_readx_req *)pSMB;
1756 pSMBW->ByteCount = 0;
1759 iov[0].iov_base = (char *)pSMB;
1760 iov[0].iov_len = be32_to_cpu(pSMB->hdr.smb_buf_length) + 4;
1761 rc = SendReceive2(xid, tcon->ses, iov, 1, &resp_buf_type,
1762 CIFS_LOG_ERROR, &rsp_iov);
1763 cifs_small_buf_release(pSMB);
1764 cifs_stats_inc(&tcon->stats.cifs_stats.num_reads);
1765 pSMBr = (READ_RSP *)rsp_iov.iov_base;
1767 cifs_dbg(VFS, "Send error in read = %d\n", rc);
1769 int data_length = le16_to_cpu(pSMBr->DataLengthHigh);
1770 data_length = data_length << 16;
1771 data_length += le16_to_cpu(pSMBr->DataLength);
1772 *nbytes = data_length;
1774 /*check that DataLength would not go beyond end of SMB */
1775 if ((data_length > CIFSMaxBufSize)
1776 || (data_length > count)) {
1777 cifs_dbg(FYI, "bad length %d for count %d\n",
1778 data_length, count);
1782 pReadData = (char *) (&pSMBr->hdr.Protocol) +
1783 le16_to_cpu(pSMBr->DataOffset);
1784 /* if (rc = copy_to_user(buf, pReadData, data_length)) {
1785 cifs_dbg(VFS, "Faulting on read rc = %d\n",rc);
1787 }*/ /* can not use copy_to_user when using page cache*/
1789 memcpy(*buf, pReadData, data_length);
1794 free_rsp_buf(resp_buf_type, rsp_iov.iov_base);
1795 } else if (resp_buf_type != CIFS_NO_BUFFER) {
1796 /* return buffer to caller to free */
1797 *buf = rsp_iov.iov_base;
1798 if (resp_buf_type == CIFS_SMALL_BUFFER)
1799 *pbuf_type = CIFS_SMALL_BUFFER;
1800 else if (resp_buf_type == CIFS_LARGE_BUFFER)
1801 *pbuf_type = CIFS_LARGE_BUFFER;
1802 } /* else no valid buffer on return - leave as null */
1804 /* Note: On -EAGAIN error only caller can retry on handle based calls
1805 since file handle passed in no longer valid */
1811 CIFSSMBWrite(const unsigned int xid, struct cifs_io_parms *io_parms,
1812 unsigned int *nbytes, const char *buf)
1815 WRITE_REQ *pSMB = NULL;
1816 WRITE_RSP *pSMBr = NULL;
1817 int bytes_returned, wct;
1820 __u32 pid = io_parms->pid;
1821 __u16 netfid = io_parms->netfid;
1822 __u64 offset = io_parms->offset;
1823 struct cifs_tcon *tcon = io_parms->tcon;
1824 unsigned int count = io_parms->length;
1828 /* cifs_dbg(FYI, "write at %lld %d bytes\n", offset, count);*/
1829 if (tcon->ses == NULL)
1830 return -ECONNABORTED;
1832 if (tcon->ses->capabilities & CAP_LARGE_FILES)
1836 if ((offset >> 32) > 0) {
1837 /* can not handle big offset for old srv */
1842 rc = smb_init(SMB_COM_WRITE_ANDX, wct, tcon, (void **) &pSMB,
1847 pSMB->hdr.Pid = cpu_to_le16((__u16)pid);
1848 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid >> 16));
1850 /* tcon and ses pointer are checked in smb_init */
1851 if (tcon->ses->server == NULL)
1852 return -ECONNABORTED;
1854 pSMB->AndXCommand = 0xFF; /* none */
1856 pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF);
1858 pSMB->OffsetHigh = cpu_to_le32(offset >> 32);
1860 pSMB->Reserved = 0xFFFFFFFF;
1861 pSMB->WriteMode = 0;
1862 pSMB->Remaining = 0;
1864 /* Can increase buffer size if buffer is big enough in some cases ie we
1865 can send more if LARGE_WRITE_X capability returned by the server and if
1866 our buffer is big enough or if we convert to iovecs on socket writes
1867 and eliminate the copy to the CIFS buffer */
1868 if (tcon->ses->capabilities & CAP_LARGE_WRITE_X) {
1869 bytes_sent = min_t(const unsigned int, CIFSMaxBufSize, count);
1871 bytes_sent = (tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE)
1875 if (bytes_sent > count)
1878 cpu_to_le16(offsetof(struct smb_com_write_req, Data) - 4);
1880 memcpy(pSMB->Data, buf, bytes_sent);
1881 else if (count != 0) {
1883 cifs_buf_release(pSMB);
1885 } /* else setting file size with write of zero bytes */
1887 byte_count = bytes_sent + 1; /* pad */
1888 else /* wct == 12 */
1889 byte_count = bytes_sent + 5; /* bigger pad, smaller smb hdr */
1891 pSMB->DataLengthLow = cpu_to_le16(bytes_sent & 0xFFFF);
1892 pSMB->DataLengthHigh = cpu_to_le16(bytes_sent >> 16);
1893 inc_rfc1001_len(pSMB, byte_count);
1896 pSMB->ByteCount = cpu_to_le16(byte_count);
1897 else { /* old style write has byte count 4 bytes earlier
1899 struct smb_com_writex_req *pSMBW =
1900 (struct smb_com_writex_req *)pSMB;
1901 pSMBW->ByteCount = cpu_to_le16(byte_count);
1904 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1905 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1906 cifs_stats_inc(&tcon->stats.cifs_stats.num_writes);
1908 cifs_dbg(FYI, "Send error in write = %d\n", rc);
1910 *nbytes = le16_to_cpu(pSMBr->CountHigh);
1911 *nbytes = (*nbytes) << 16;
1912 *nbytes += le16_to_cpu(pSMBr->Count);
1915 * Mask off high 16 bits when bytes written as returned by the
1916 * server is greater than bytes requested by the client. Some
1917 * OS/2 servers are known to set incorrect CountHigh values.
1919 if (*nbytes > count)
1923 cifs_buf_release(pSMB);
1925 /* Note: On -EAGAIN error only caller can retry on handle based calls
1926 since file handle passed in no longer valid */
1932 cifs_writedata_release(struct kref *refcount)
1934 struct cifs_writedata *wdata = container_of(refcount,
1935 struct cifs_writedata, refcount);
1936 #ifdef CONFIG_CIFS_SMB_DIRECT
1938 smbd_deregister_mr(wdata->mr);
1944 cifsFileInfo_put(wdata->cfile);
1950 * Write failed with a retryable error. Resend the write request. It's also
1951 * possible that the page was redirtied so re-clean the page.
1954 cifs_writev_requeue(struct cifs_writedata *wdata)
1957 struct inode *inode = d_inode(wdata->cfile->dentry);
1958 struct TCP_Server_Info *server;
1959 unsigned int rest_len;
1961 server = tlink_tcon(wdata->cfile->tlink)->ses->server;
1963 rest_len = wdata->bytes;
1965 struct cifs_writedata *wdata2;
1966 unsigned int j, nr_pages, wsize, tailsz, cur_len;
1968 wsize = server->ops->wp_retry_size(inode);
1969 if (wsize < rest_len) {
1970 nr_pages = wsize / PAGE_SIZE;
1975 cur_len = nr_pages * PAGE_SIZE;
1978 nr_pages = DIV_ROUND_UP(rest_len, PAGE_SIZE);
1980 tailsz = rest_len - (nr_pages - 1) * PAGE_SIZE;
1983 wdata2 = cifs_writedata_alloc(nr_pages, cifs_writev_complete);
1989 for (j = 0; j < nr_pages; j++) {
1990 wdata2->pages[j] = wdata->pages[i + j];
1991 lock_page(wdata2->pages[j]);
1992 clear_page_dirty_for_io(wdata2->pages[j]);
1995 wdata2->sync_mode = wdata->sync_mode;
1996 wdata2->nr_pages = nr_pages;
1997 wdata2->offset = page_offset(wdata2->pages[0]);
1998 wdata2->pagesz = PAGE_SIZE;
1999 wdata2->tailsz = tailsz;
2000 wdata2->bytes = cur_len;
2002 wdata2->cfile = find_writable_file(CIFS_I(inode), false);
2003 if (!wdata2->cfile) {
2004 cifs_dbg(VFS, "No writable handles for inode\n");
2008 wdata2->pid = wdata2->cfile->pid;
2009 rc = server->ops->async_writev(wdata2, cifs_writedata_release);
2011 for (j = 0; j < nr_pages; j++) {
2012 unlock_page(wdata2->pages[j]);
2013 if (rc != 0 && rc != -EAGAIN) {
2014 SetPageError(wdata2->pages[j]);
2015 end_page_writeback(wdata2->pages[j]);
2016 put_page(wdata2->pages[j]);
2021 kref_put(&wdata2->refcount, cifs_writedata_release);
2027 rest_len -= cur_len;
2029 } while (i < wdata->nr_pages);
2031 mapping_set_error(inode->i_mapping, rc);
2032 kref_put(&wdata->refcount, cifs_writedata_release);
2036 cifs_writev_complete(struct work_struct *work)
2038 struct cifs_writedata *wdata = container_of(work,
2039 struct cifs_writedata, work);
2040 struct inode *inode = d_inode(wdata->cfile->dentry);
2043 if (wdata->result == 0) {
2044 spin_lock(&inode->i_lock);
2045 cifs_update_eof(CIFS_I(inode), wdata->offset, wdata->bytes);
2046 spin_unlock(&inode->i_lock);
2047 cifs_stats_bytes_written(tlink_tcon(wdata->cfile->tlink),
2049 } else if (wdata->sync_mode == WB_SYNC_ALL && wdata->result == -EAGAIN)
2050 return cifs_writev_requeue(wdata);
2052 for (i = 0; i < wdata->nr_pages; i++) {
2053 struct page *page = wdata->pages[i];
2054 if (wdata->result == -EAGAIN)
2055 __set_page_dirty_nobuffers(page);
2056 else if (wdata->result < 0)
2058 end_page_writeback(page);
2061 if (wdata->result != -EAGAIN)
2062 mapping_set_error(inode->i_mapping, wdata->result);
2063 kref_put(&wdata->refcount, cifs_writedata_release);
2066 struct cifs_writedata *
2067 cifs_writedata_alloc(unsigned int nr_pages, work_func_t complete)
2069 struct cifs_writedata *wdata;
2071 /* writedata + number of page pointers */
2072 wdata = kzalloc(sizeof(*wdata) +
2073 sizeof(struct page *) * nr_pages, GFP_NOFS);
2074 if (wdata != NULL) {
2075 kref_init(&wdata->refcount);
2076 INIT_LIST_HEAD(&wdata->list);
2077 init_completion(&wdata->done);
2078 INIT_WORK(&wdata->work, complete);
2084 * Check the mid_state and signature on received buffer (if any), and queue the
2085 * workqueue completion task.
2088 cifs_writev_callback(struct mid_q_entry *mid)
2090 struct cifs_writedata *wdata = mid->callback_data;
2091 struct cifs_tcon *tcon = tlink_tcon(wdata->cfile->tlink);
2092 unsigned int written;
2093 WRITE_RSP *smb = (WRITE_RSP *)mid->resp_buf;
2095 switch (mid->mid_state) {
2096 case MID_RESPONSE_RECEIVED:
2097 wdata->result = cifs_check_receive(mid, tcon->ses->server, 0);
2098 if (wdata->result != 0)
2101 written = le16_to_cpu(smb->CountHigh);
2103 written += le16_to_cpu(smb->Count);
2105 * Mask off high 16 bits when bytes written as returned
2106 * by the server is greater than bytes requested by the
2107 * client. OS/2 servers are known to set incorrect
2110 if (written > wdata->bytes)
2113 if (written < wdata->bytes)
2114 wdata->result = -ENOSPC;
2116 wdata->bytes = written;
2118 case MID_REQUEST_SUBMITTED:
2119 case MID_RETRY_NEEDED:
2120 wdata->result = -EAGAIN;
2123 wdata->result = -EIO;
2127 queue_work(cifsiod_wq, &wdata->work);
2128 DeleteMidQEntry(mid);
2129 add_credits(tcon->ses->server, 1, 0);
2132 /* cifs_async_writev - send an async write, and set up mid to handle result */
2134 cifs_async_writev(struct cifs_writedata *wdata,
2135 void (*release)(struct kref *kref))
2138 WRITE_REQ *smb = NULL;
2140 struct cifs_tcon *tcon = tlink_tcon(wdata->cfile->tlink);
2142 struct smb_rqst rqst = { };
2144 if (tcon->ses->capabilities & CAP_LARGE_FILES) {
2148 if (wdata->offset >> 32 > 0) {
2149 /* can not handle big offset for old srv */
2154 rc = small_smb_init(SMB_COM_WRITE_ANDX, wct, tcon, (void **)&smb);
2156 goto async_writev_out;
2158 smb->hdr.Pid = cpu_to_le16((__u16)wdata->pid);
2159 smb->hdr.PidHigh = cpu_to_le16((__u16)(wdata->pid >> 16));
2161 smb->AndXCommand = 0xFF; /* none */
2162 smb->Fid = wdata->cfile->fid.netfid;
2163 smb->OffsetLow = cpu_to_le32(wdata->offset & 0xFFFFFFFF);
2165 smb->OffsetHigh = cpu_to_le32(wdata->offset >> 32);
2166 smb->Reserved = 0xFFFFFFFF;
2171 cpu_to_le16(offsetof(struct smb_com_write_req, Data) - 4);
2173 /* 4 for RFC1001 length + 1 for BCC */
2175 iov[0].iov_base = smb;
2176 iov[1].iov_len = get_rfc1002_length(smb) + 1;
2177 iov[1].iov_base = (char *)smb + 4;
2181 rqst.rq_pages = wdata->pages;
2182 rqst.rq_npages = wdata->nr_pages;
2183 rqst.rq_pagesz = wdata->pagesz;
2184 rqst.rq_tailsz = wdata->tailsz;
2186 cifs_dbg(FYI, "async write at %llu %u bytes\n",
2187 wdata->offset, wdata->bytes);
2189 smb->DataLengthLow = cpu_to_le16(wdata->bytes & 0xFFFF);
2190 smb->DataLengthHigh = cpu_to_le16(wdata->bytes >> 16);
2193 inc_rfc1001_len(&smb->hdr, wdata->bytes + 1);
2194 put_bcc(wdata->bytes + 1, &smb->hdr);
2197 struct smb_com_writex_req *smbw =
2198 (struct smb_com_writex_req *)smb;
2199 inc_rfc1001_len(&smbw->hdr, wdata->bytes + 5);
2200 put_bcc(wdata->bytes + 5, &smbw->hdr);
2201 iov[1].iov_len += 4; /* pad bigger by four bytes */
2204 kref_get(&wdata->refcount);
2205 rc = cifs_call_async(tcon->ses->server, &rqst, NULL,
2206 cifs_writev_callback, NULL, wdata, 0);
2209 cifs_stats_inc(&tcon->stats.cifs_stats.num_writes);
2211 kref_put(&wdata->refcount, release);
2214 cifs_small_buf_release(smb);
2219 CIFSSMBWrite2(const unsigned int xid, struct cifs_io_parms *io_parms,
2220 unsigned int *nbytes, struct kvec *iov, int n_vec)
2223 WRITE_REQ *pSMB = NULL;
2226 int resp_buf_type = 0;
2227 __u32 pid = io_parms->pid;
2228 __u16 netfid = io_parms->netfid;
2229 __u64 offset = io_parms->offset;
2230 struct cifs_tcon *tcon = io_parms->tcon;
2231 unsigned int count = io_parms->length;
2232 struct kvec rsp_iov;
2236 cifs_dbg(FYI, "write2 at %lld %d bytes\n", (long long)offset, count);
2238 if (tcon->ses->capabilities & CAP_LARGE_FILES) {
2242 if ((offset >> 32) > 0) {
2243 /* can not handle big offset for old srv */
2247 rc = small_smb_init(SMB_COM_WRITE_ANDX, wct, tcon, (void **) &pSMB);
2251 pSMB->hdr.Pid = cpu_to_le16((__u16)pid);
2252 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid >> 16));
2254 /* tcon and ses pointer are checked in smb_init */
2255 if (tcon->ses->server == NULL)
2256 return -ECONNABORTED;
2258 pSMB->AndXCommand = 0xFF; /* none */
2260 pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF);
2262 pSMB->OffsetHigh = cpu_to_le32(offset >> 32);
2263 pSMB->Reserved = 0xFFFFFFFF;
2264 pSMB->WriteMode = 0;
2265 pSMB->Remaining = 0;
2268 cpu_to_le16(offsetof(struct smb_com_write_req, Data) - 4);
2270 pSMB->DataLengthLow = cpu_to_le16(count & 0xFFFF);
2271 pSMB->DataLengthHigh = cpu_to_le16(count >> 16);
2272 /* header + 1 byte pad */
2273 smb_hdr_len = be32_to_cpu(pSMB->hdr.smb_buf_length) + 1;
2275 inc_rfc1001_len(pSMB, count + 1);
2276 else /* wct == 12 */
2277 inc_rfc1001_len(pSMB, count + 5); /* smb data starts later */
2279 pSMB->ByteCount = cpu_to_le16(count + 1);
2280 else /* wct == 12 */ /* bigger pad, smaller smb hdr, keep offset ok */ {
2281 struct smb_com_writex_req *pSMBW =
2282 (struct smb_com_writex_req *)pSMB;
2283 pSMBW->ByteCount = cpu_to_le16(count + 5);
2285 iov[0].iov_base = pSMB;
2287 iov[0].iov_len = smb_hdr_len + 4;
2288 else /* wct == 12 pad bigger by four bytes */
2289 iov[0].iov_len = smb_hdr_len + 8;
2291 rc = SendReceive2(xid, tcon->ses, iov, n_vec + 1, &resp_buf_type, 0,
2293 cifs_small_buf_release(pSMB);
2294 cifs_stats_inc(&tcon->stats.cifs_stats.num_writes);
2296 cifs_dbg(FYI, "Send error Write2 = %d\n", rc);
2297 } else if (resp_buf_type == 0) {
2298 /* presumably this can not happen, but best to be safe */
2301 WRITE_RSP *pSMBr = (WRITE_RSP *)rsp_iov.iov_base;
2302 *nbytes = le16_to_cpu(pSMBr->CountHigh);
2303 *nbytes = (*nbytes) << 16;
2304 *nbytes += le16_to_cpu(pSMBr->Count);
2307 * Mask off high 16 bits when bytes written as returned by the
2308 * server is greater than bytes requested by the client. OS/2
2309 * servers are known to set incorrect CountHigh values.
2311 if (*nbytes > count)
2315 free_rsp_buf(resp_buf_type, rsp_iov.iov_base);
2317 /* Note: On -EAGAIN error only caller can retry on handle based calls
2318 since file handle passed in no longer valid */
2323 int cifs_lockv(const unsigned int xid, struct cifs_tcon *tcon,
2324 const __u16 netfid, const __u8 lock_type, const __u32 num_unlock,
2325 const __u32 num_lock, LOCKING_ANDX_RANGE *buf)
2328 LOCK_REQ *pSMB = NULL;
2330 struct kvec rsp_iov;
2334 cifs_dbg(FYI, "cifs_lockv num lock %d num unlock %d\n",
2335 num_lock, num_unlock);
2337 rc = small_smb_init(SMB_COM_LOCKING_ANDX, 8, tcon, (void **) &pSMB);
2342 pSMB->NumberOfLocks = cpu_to_le16(num_lock);
2343 pSMB->NumberOfUnlocks = cpu_to_le16(num_unlock);
2344 pSMB->LockType = lock_type;
2345 pSMB->AndXCommand = 0xFF; /* none */
2346 pSMB->Fid = netfid; /* netfid stays le */
2348 count = (num_unlock + num_lock) * sizeof(LOCKING_ANDX_RANGE);
2349 inc_rfc1001_len(pSMB, count);
2350 pSMB->ByteCount = cpu_to_le16(count);
2352 iov[0].iov_base = (char *)pSMB;
2353 iov[0].iov_len = be32_to_cpu(pSMB->hdr.smb_buf_length) + 4 -
2354 (num_unlock + num_lock) * sizeof(LOCKING_ANDX_RANGE);
2355 iov[1].iov_base = (char *)buf;
2356 iov[1].iov_len = (num_unlock + num_lock) * sizeof(LOCKING_ANDX_RANGE);
2358 cifs_stats_inc(&tcon->stats.cifs_stats.num_locks);
2359 rc = SendReceive2(xid, tcon->ses, iov, 2, &resp_buf_type, CIFS_NO_RESP,
2361 cifs_small_buf_release(pSMB);
2363 cifs_dbg(FYI, "Send error in cifs_lockv = %d\n", rc);
2369 CIFSSMBLock(const unsigned int xid, struct cifs_tcon *tcon,
2370 const __u16 smb_file_id, const __u32 netpid, const __u64 len,
2371 const __u64 offset, const __u32 numUnlock,
2372 const __u32 numLock, const __u8 lockType,
2373 const bool waitFlag, const __u8 oplock_level)
2376 LOCK_REQ *pSMB = NULL;
2377 /* LOCK_RSP *pSMBr = NULL; */ /* No response data other than rc to parse */
2382 cifs_dbg(FYI, "CIFSSMBLock timeout %d numLock %d\n",
2383 (int)waitFlag, numLock);
2384 rc = small_smb_init(SMB_COM_LOCKING_ANDX, 8, tcon, (void **) &pSMB);
2389 if (lockType == LOCKING_ANDX_OPLOCK_RELEASE) {
2390 /* no response expected */
2391 flags = CIFS_ASYNC_OP | CIFS_OBREAK_OP;
2393 } else if (waitFlag) {
2394 flags = CIFS_BLOCKING_OP; /* blocking operation, no timeout */
2395 pSMB->Timeout = cpu_to_le32(-1);/* blocking - do not time out */
2400 pSMB->NumberOfLocks = cpu_to_le16(numLock);
2401 pSMB->NumberOfUnlocks = cpu_to_le16(numUnlock);
2402 pSMB->LockType = lockType;
2403 pSMB->OplockLevel = oplock_level;
2404 pSMB->AndXCommand = 0xFF; /* none */
2405 pSMB->Fid = smb_file_id; /* netfid stays le */
2407 if ((numLock != 0) || (numUnlock != 0)) {
2408 pSMB->Locks[0].Pid = cpu_to_le16(netpid);
2409 /* BB where to store pid high? */
2410 pSMB->Locks[0].LengthLow = cpu_to_le32((u32)len);
2411 pSMB->Locks[0].LengthHigh = cpu_to_le32((u32)(len>>32));
2412 pSMB->Locks[0].OffsetLow = cpu_to_le32((u32)offset);
2413 pSMB->Locks[0].OffsetHigh = cpu_to_le32((u32)(offset>>32));
2414 count = sizeof(LOCKING_ANDX_RANGE);
2419 inc_rfc1001_len(pSMB, count);
2420 pSMB->ByteCount = cpu_to_le16(count);
2423 rc = SendReceiveBlockingLock(xid, tcon, (struct smb_hdr *) pSMB,
2424 (struct smb_hdr *) pSMB, &bytes_returned);
2426 rc = SendReceiveNoRsp(xid, tcon->ses, (char *)pSMB, flags);
2427 cifs_small_buf_release(pSMB);
2428 cifs_stats_inc(&tcon->stats.cifs_stats.num_locks);
2430 cifs_dbg(FYI, "Send error in Lock = %d\n", rc);
2432 /* Note: On -EAGAIN error only caller can retry on handle based calls
2433 since file handle passed in no longer valid */
2438 CIFSSMBPosixLock(const unsigned int xid, struct cifs_tcon *tcon,
2439 const __u16 smb_file_id, const __u32 netpid,
2440 const loff_t start_offset, const __u64 len,
2441 struct file_lock *pLockData, const __u16 lock_type,
2442 const bool waitFlag)
2444 struct smb_com_transaction2_sfi_req *pSMB = NULL;
2445 struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
2446 struct cifs_posix_lock *parm_data;
2449 int bytes_returned = 0;
2450 int resp_buf_type = 0;
2451 __u16 params, param_offset, offset, byte_count, count;
2453 struct kvec rsp_iov;
2455 cifs_dbg(FYI, "Posix Lock\n");
2457 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
2462 pSMBr = (struct smb_com_transaction2_sfi_rsp *)pSMB;
2465 pSMB->MaxSetupCount = 0;
2468 pSMB->Reserved2 = 0;
2469 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
2470 offset = param_offset + params;
2472 count = sizeof(struct cifs_posix_lock);
2473 pSMB->MaxParameterCount = cpu_to_le16(2);
2474 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB from sess */
2475 pSMB->SetupCount = 1;
2476 pSMB->Reserved3 = 0;
2478 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION);
2480 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
2481 byte_count = 3 /* pad */ + params + count;
2482 pSMB->DataCount = cpu_to_le16(count);
2483 pSMB->ParameterCount = cpu_to_le16(params);
2484 pSMB->TotalDataCount = pSMB->DataCount;
2485 pSMB->TotalParameterCount = pSMB->ParameterCount;
2486 pSMB->ParameterOffset = cpu_to_le16(param_offset);
2487 parm_data = (struct cifs_posix_lock *)
2488 (((char *) &pSMB->hdr.Protocol) + offset);
2490 parm_data->lock_type = cpu_to_le16(lock_type);
2492 timeout = CIFS_BLOCKING_OP; /* blocking operation, no timeout */
2493 parm_data->lock_flags = cpu_to_le16(1);
2494 pSMB->Timeout = cpu_to_le32(-1);
2498 parm_data->pid = cpu_to_le32(netpid);
2499 parm_data->start = cpu_to_le64(start_offset);
2500 parm_data->length = cpu_to_le64(len); /* normalize negative numbers */
2502 pSMB->DataOffset = cpu_to_le16(offset);
2503 pSMB->Fid = smb_file_id;
2504 pSMB->InformationLevel = cpu_to_le16(SMB_SET_POSIX_LOCK);
2505 pSMB->Reserved4 = 0;
2506 inc_rfc1001_len(pSMB, byte_count);
2507 pSMB->ByteCount = cpu_to_le16(byte_count);
2509 rc = SendReceiveBlockingLock(xid, tcon, (struct smb_hdr *) pSMB,
2510 (struct smb_hdr *) pSMBr, &bytes_returned);
2512 iov[0].iov_base = (char *)pSMB;
2513 iov[0].iov_len = be32_to_cpu(pSMB->hdr.smb_buf_length) + 4;
2514 rc = SendReceive2(xid, tcon->ses, iov, 1 /* num iovecs */,
2515 &resp_buf_type, timeout, &rsp_iov);
2516 pSMBr = (struct smb_com_transaction2_sfi_rsp *)rsp_iov.iov_base;
2518 cifs_small_buf_release(pSMB);
2521 cifs_dbg(FYI, "Send error in Posix Lock = %d\n", rc);
2522 } else if (pLockData) {
2523 /* lock structure can be returned on get */
2526 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
2528 if (rc || get_bcc(&pSMBr->hdr) < sizeof(*parm_data)) {
2529 rc = -EIO; /* bad smb */
2532 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
2533 data_count = le16_to_cpu(pSMBr->t2.DataCount);
2534 if (data_count < sizeof(struct cifs_posix_lock)) {
2538 parm_data = (struct cifs_posix_lock *)
2539 ((char *)&pSMBr->hdr.Protocol + data_offset);
2540 if (parm_data->lock_type == cpu_to_le16(CIFS_UNLCK))
2541 pLockData->fl_type = F_UNLCK;
2543 if (parm_data->lock_type ==
2544 cpu_to_le16(CIFS_RDLCK))
2545 pLockData->fl_type = F_RDLCK;
2546 else if (parm_data->lock_type ==
2547 cpu_to_le16(CIFS_WRLCK))
2548 pLockData->fl_type = F_WRLCK;
2550 pLockData->fl_start = le64_to_cpu(parm_data->start);
2551 pLockData->fl_end = pLockData->fl_start +
2552 le64_to_cpu(parm_data->length) - 1;
2553 pLockData->fl_pid = -le32_to_cpu(parm_data->pid);
2558 free_rsp_buf(resp_buf_type, rsp_iov.iov_base);
2560 /* Note: On -EAGAIN error only caller can retry on handle based calls
2561 since file handle passed in no longer valid */
2568 CIFSSMBClose(const unsigned int xid, struct cifs_tcon *tcon, int smb_file_id)
2571 CLOSE_REQ *pSMB = NULL;
2572 cifs_dbg(FYI, "In CIFSSMBClose\n");
2574 /* do not retry on dead session on close */
2575 rc = small_smb_init(SMB_COM_CLOSE, 3, tcon, (void **) &pSMB);
2581 pSMB->FileID = (__u16) smb_file_id;
2582 pSMB->LastWriteTime = 0xFFFFFFFF;
2583 pSMB->ByteCount = 0;
2584 rc = SendReceiveNoRsp(xid, tcon->ses, (char *) pSMB, 0);
2585 cifs_small_buf_release(pSMB);
2586 cifs_stats_inc(&tcon->stats.cifs_stats.num_closes);
2589 /* EINTR is expected when user ctl-c to kill app */
2590 cifs_dbg(VFS, "Send error in Close = %d\n", rc);
2594 /* Since session is dead, file will be closed on server already */
2602 CIFSSMBFlush(const unsigned int xid, struct cifs_tcon *tcon, int smb_file_id)
2605 FLUSH_REQ *pSMB = NULL;
2606 cifs_dbg(FYI, "In CIFSSMBFlush\n");
2608 rc = small_smb_init(SMB_COM_FLUSH, 1, tcon, (void **) &pSMB);
2612 pSMB->FileID = (__u16) smb_file_id;
2613 pSMB->ByteCount = 0;
2614 rc = SendReceiveNoRsp(xid, tcon->ses, (char *) pSMB, 0);
2615 cifs_small_buf_release(pSMB);
2616 cifs_stats_inc(&tcon->stats.cifs_stats.num_flushes);
2618 cifs_dbg(VFS, "Send error in Flush = %d\n", rc);
2624 CIFSSMBRename(const unsigned int xid, struct cifs_tcon *tcon,
2625 const char *from_name, const char *to_name,
2626 struct cifs_sb_info *cifs_sb)
2629 RENAME_REQ *pSMB = NULL;
2630 RENAME_RSP *pSMBr = NULL;
2632 int name_len, name_len2;
2634 int remap = cifs_remap(cifs_sb);
2636 cifs_dbg(FYI, "In CIFSSMBRename\n");
2638 rc = smb_init(SMB_COM_RENAME, 1, tcon, (void **) &pSMB,
2643 pSMB->BufferFormat = 0x04;
2644 pSMB->SearchAttributes =
2645 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
2648 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2649 name_len = cifsConvertToUTF16((__le16 *) pSMB->OldFileName,
2650 from_name, PATH_MAX,
2651 cifs_sb->local_nls, remap);
2652 name_len++; /* trailing null */
2654 pSMB->OldFileName[name_len] = 0x04; /* pad */
2655 /* protocol requires ASCII signature byte on Unicode string */
2656 pSMB->OldFileName[name_len + 1] = 0x00;
2658 cifsConvertToUTF16((__le16 *)&pSMB->OldFileName[name_len+2],
2659 to_name, PATH_MAX, cifs_sb->local_nls,
2661 name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
2662 name_len2 *= 2; /* convert to bytes */
2663 } else { /* BB improve the check for buffer overruns BB */
2664 name_len = strnlen(from_name, PATH_MAX);
2665 name_len++; /* trailing null */
2666 strncpy(pSMB->OldFileName, from_name, name_len);
2667 name_len2 = strnlen(to_name, PATH_MAX);
2668 name_len2++; /* trailing null */
2669 pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */
2670 strncpy(&pSMB->OldFileName[name_len + 1], to_name, name_len2);
2671 name_len2++; /* trailing null */
2672 name_len2++; /* signature byte */
2675 count = 1 /* 1st signature byte */ + name_len + name_len2;
2676 inc_rfc1001_len(pSMB, count);
2677 pSMB->ByteCount = cpu_to_le16(count);
2679 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2680 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2681 cifs_stats_inc(&tcon->stats.cifs_stats.num_renames);
2683 cifs_dbg(FYI, "Send error in rename = %d\n", rc);
2685 cifs_buf_release(pSMB);
2693 int CIFSSMBRenameOpenFile(const unsigned int xid, struct cifs_tcon *pTcon,
2694 int netfid, const char *target_name,
2695 const struct nls_table *nls_codepage, int remap)
2697 struct smb_com_transaction2_sfi_req *pSMB = NULL;
2698 struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
2699 struct set_file_rename *rename_info;
2701 char dummy_string[30];
2703 int bytes_returned = 0;
2705 __u16 params, param_offset, offset, count, byte_count;
2707 cifs_dbg(FYI, "Rename to File by handle\n");
2708 rc = smb_init(SMB_COM_TRANSACTION2, 15, pTcon, (void **) &pSMB,
2714 pSMB->MaxSetupCount = 0;
2718 pSMB->Reserved2 = 0;
2719 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
2720 offset = param_offset + params;
2722 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
2723 rename_info = (struct set_file_rename *) data_offset;
2724 pSMB->MaxParameterCount = cpu_to_le16(2);
2725 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB from sess */
2726 pSMB->SetupCount = 1;
2727 pSMB->Reserved3 = 0;
2728 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
2729 byte_count = 3 /* pad */ + params;
2730 pSMB->ParameterCount = cpu_to_le16(params);
2731 pSMB->TotalParameterCount = pSMB->ParameterCount;
2732 pSMB->ParameterOffset = cpu_to_le16(param_offset);
2733 pSMB->DataOffset = cpu_to_le16(offset);
2734 /* construct random name ".cifs_tmp<inodenum><mid>" */
2735 rename_info->overwrite = cpu_to_le32(1);
2736 rename_info->root_fid = 0;
2737 /* unicode only call */
2738 if (target_name == NULL) {
2739 sprintf(dummy_string, "cifs%x", pSMB->hdr.Mid);
2741 cifsConvertToUTF16((__le16 *)rename_info->target_name,
2742 dummy_string, 24, nls_codepage, remap);
2745 cifsConvertToUTF16((__le16 *)rename_info->target_name,
2746 target_name, PATH_MAX, nls_codepage,
2749 rename_info->target_name_len = cpu_to_le32(2 * len_of_str);
2750 count = 12 /* sizeof(struct set_file_rename) */ + (2 * len_of_str);
2751 byte_count += count;
2752 pSMB->DataCount = cpu_to_le16(count);
2753 pSMB->TotalDataCount = pSMB->DataCount;
2755 pSMB->InformationLevel =
2756 cpu_to_le16(SMB_SET_FILE_RENAME_INFORMATION);
2757 pSMB->Reserved4 = 0;
2758 inc_rfc1001_len(pSMB, byte_count);
2759 pSMB->ByteCount = cpu_to_le16(byte_count);
2760 rc = SendReceive(xid, pTcon->ses, (struct smb_hdr *) pSMB,
2761 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2762 cifs_stats_inc(&pTcon->stats.cifs_stats.num_t2renames);
2764 cifs_dbg(FYI, "Send error in Rename (by file handle) = %d\n",
2767 cifs_buf_release(pSMB);
2769 /* Note: On -EAGAIN error only caller can retry on handle based calls
2770 since file handle passed in no longer valid */
2776 CIFSSMBCopy(const unsigned int xid, struct cifs_tcon *tcon,
2777 const char *fromName, const __u16 target_tid, const char *toName,
2778 const int flags, const struct nls_table *nls_codepage, int remap)
2781 COPY_REQ *pSMB = NULL;
2782 COPY_RSP *pSMBr = NULL;
2784 int name_len, name_len2;
2787 cifs_dbg(FYI, "In CIFSSMBCopy\n");
2789 rc = smb_init(SMB_COM_COPY, 1, tcon, (void **) &pSMB,
2794 pSMB->BufferFormat = 0x04;
2795 pSMB->Tid2 = target_tid;
2797 pSMB->Flags = cpu_to_le16(flags & COPY_TREE);
2799 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2800 name_len = cifsConvertToUTF16((__le16 *) pSMB->OldFileName,
2801 fromName, PATH_MAX, nls_codepage,
2803 name_len++; /* trailing null */
2805 pSMB->OldFileName[name_len] = 0x04; /* pad */
2806 /* protocol requires ASCII signature byte on Unicode string */
2807 pSMB->OldFileName[name_len + 1] = 0x00;
2809 cifsConvertToUTF16((__le16 *)&pSMB->OldFileName[name_len+2],
2810 toName, PATH_MAX, nls_codepage, remap);
2811 name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
2812 name_len2 *= 2; /* convert to bytes */
2813 } else { /* BB improve the check for buffer overruns BB */
2814 name_len = strnlen(fromName, PATH_MAX);
2815 name_len++; /* trailing null */
2816 strncpy(pSMB->OldFileName, fromName, name_len);
2817 name_len2 = strnlen(toName, PATH_MAX);
2818 name_len2++; /* trailing null */
2819 pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */
2820 strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2);
2821 name_len2++; /* trailing null */
2822 name_len2++; /* signature byte */
2825 count = 1 /* 1st signature byte */ + name_len + name_len2;
2826 inc_rfc1001_len(pSMB, count);
2827 pSMB->ByteCount = cpu_to_le16(count);
2829 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2830 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2832 cifs_dbg(FYI, "Send error in copy = %d with %d files copied\n",
2833 rc, le16_to_cpu(pSMBr->CopyCount));
2835 cifs_buf_release(pSMB);
2844 CIFSUnixCreateSymLink(const unsigned int xid, struct cifs_tcon *tcon,
2845 const char *fromName, const char *toName,
2846 const struct nls_table *nls_codepage, int remap)
2848 TRANSACTION2_SPI_REQ *pSMB = NULL;
2849 TRANSACTION2_SPI_RSP *pSMBr = NULL;
2852 int name_len_target;
2854 int bytes_returned = 0;
2855 __u16 params, param_offset, offset, byte_count;
2857 cifs_dbg(FYI, "In Symlink Unix style\n");
2859 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2864 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2866 cifsConvertToUTF16((__le16 *) pSMB->FileName, fromName,
2867 /* find define for this maxpathcomponent */
2868 PATH_MAX, nls_codepage, remap);
2869 name_len++; /* trailing null */
2872 } else { /* BB improve the check for buffer overruns BB */
2873 name_len = strnlen(fromName, PATH_MAX);
2874 name_len++; /* trailing null */
2875 strncpy(pSMB->FileName, fromName, name_len);
2877 params = 6 + name_len;
2878 pSMB->MaxSetupCount = 0;
2882 pSMB->Reserved2 = 0;
2883 param_offset = offsetof(struct smb_com_transaction2_spi_req,
2884 InformationLevel) - 4;
2885 offset = param_offset + params;
2887 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
2888 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2890 cifsConvertToUTF16((__le16 *) data_offset, toName,
2891 /* find define for this maxpathcomponent */
2892 PATH_MAX, nls_codepage, remap);
2893 name_len_target++; /* trailing null */
2894 name_len_target *= 2;
2895 } else { /* BB improve the check for buffer overruns BB */
2896 name_len_target = strnlen(toName, PATH_MAX);
2897 name_len_target++; /* trailing null */
2898 strncpy(data_offset, toName, name_len_target);
2901 pSMB->MaxParameterCount = cpu_to_le16(2);
2902 /* BB find exact max on data count below from sess */
2903 pSMB->MaxDataCount = cpu_to_le16(1000);
2904 pSMB->SetupCount = 1;
2905 pSMB->Reserved3 = 0;
2906 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
2907 byte_count = 3 /* pad */ + params + name_len_target;
2908 pSMB->DataCount = cpu_to_le16(name_len_target);
2909 pSMB->ParameterCount = cpu_to_le16(params);
2910 pSMB->TotalDataCount = pSMB->DataCount;
2911 pSMB->TotalParameterCount = pSMB->ParameterCount;
2912 pSMB->ParameterOffset = cpu_to_le16(param_offset);
2913 pSMB->DataOffset = cpu_to_le16(offset);
2914 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_LINK);
2915 pSMB->Reserved4 = 0;
2916 inc_rfc1001_len(pSMB, byte_count);
2917 pSMB->ByteCount = cpu_to_le16(byte_count);
2918 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2919 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2920 cifs_stats_inc(&tcon->stats.cifs_stats.num_symlinks);
2922 cifs_dbg(FYI, "Send error in SetPathInfo create symlink = %d\n",
2925 cifs_buf_release(pSMB);
2928 goto createSymLinkRetry;
2934 CIFSUnixCreateHardLink(const unsigned int xid, struct cifs_tcon *tcon,
2935 const char *fromName, const char *toName,
2936 const struct nls_table *nls_codepage, int remap)
2938 TRANSACTION2_SPI_REQ *pSMB = NULL;
2939 TRANSACTION2_SPI_RSP *pSMBr = NULL;
2942 int name_len_target;
2944 int bytes_returned = 0;
2945 __u16 params, param_offset, offset, byte_count;
2947 cifs_dbg(FYI, "In Create Hard link Unix style\n");
2948 createHardLinkRetry:
2949 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2954 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2955 name_len = cifsConvertToUTF16((__le16 *) pSMB->FileName, toName,
2956 PATH_MAX, nls_codepage, remap);
2957 name_len++; /* trailing null */
2960 } else { /* BB improve the check for buffer overruns BB */
2961 name_len = strnlen(toName, PATH_MAX);
2962 name_len++; /* trailing null */
2963 strncpy(pSMB->FileName, toName, name_len);
2965 params = 6 + name_len;
2966 pSMB->MaxSetupCount = 0;
2970 pSMB->Reserved2 = 0;
2971 param_offset = offsetof(struct smb_com_transaction2_spi_req,
2972 InformationLevel) - 4;
2973 offset = param_offset + params;
2975 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
2976 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2978 cifsConvertToUTF16((__le16 *) data_offset, fromName,
2979 PATH_MAX, nls_codepage, remap);
2980 name_len_target++; /* trailing null */
2981 name_len_target *= 2;
2982 } else { /* BB improve the check for buffer overruns BB */
2983 name_len_target = strnlen(fromName, PATH_MAX);
2984 name_len_target++; /* trailing null */
2985 strncpy(data_offset, fromName, name_len_target);
2988 pSMB->MaxParameterCount = cpu_to_le16(2);
2989 /* BB find exact max on data count below from sess*/
2990 pSMB->MaxDataCount = cpu_to_le16(1000);
2991 pSMB->SetupCount = 1;
2992 pSMB->Reserved3 = 0;
2993 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
2994 byte_count = 3 /* pad */ + params + name_len_target;
2995 pSMB->ParameterCount = cpu_to_le16(params);
2996 pSMB->TotalParameterCount = pSMB->ParameterCount;
2997 pSMB->DataCount = cpu_to_le16(name_len_target);
2998 pSMB->TotalDataCount = pSMB->DataCount;
2999 pSMB->ParameterOffset = cpu_to_le16(param_offset);
3000 pSMB->DataOffset = cpu_to_le16(offset);
3001 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_HLINK);
3002 pSMB->Reserved4 = 0;
3003 inc_rfc1001_len(pSMB, byte_count);
3004 pSMB->ByteCount = cpu_to_le16(byte_count);
3005 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3006 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3007 cifs_stats_inc(&tcon->stats.cifs_stats.num_hardlinks);
3009 cifs_dbg(FYI, "Send error in SetPathInfo (hard link) = %d\n",
3012 cifs_buf_release(pSMB);
3014 goto createHardLinkRetry;
3020 CIFSCreateHardLink(const unsigned int xid, struct cifs_tcon *tcon,
3021 const char *from_name, const char *to_name,
3022 struct cifs_sb_info *cifs_sb)
3025 NT_RENAME_REQ *pSMB = NULL;
3026 RENAME_RSP *pSMBr = NULL;
3028 int name_len, name_len2;
3030 int remap = cifs_remap(cifs_sb);
3032 cifs_dbg(FYI, "In CIFSCreateHardLink\n");
3033 winCreateHardLinkRetry:
3035 rc = smb_init(SMB_COM_NT_RENAME, 4, tcon, (void **) &pSMB,
3040 pSMB->SearchAttributes =
3041 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
3043 pSMB->Flags = cpu_to_le16(CREATE_HARD_LINK);
3044 pSMB->ClusterCount = 0;
3046 pSMB->BufferFormat = 0x04;
3048 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3050 cifsConvertToUTF16((__le16 *) pSMB->OldFileName, from_name,
3051 PATH_MAX, cifs_sb->local_nls, remap);
3052 name_len++; /* trailing null */
3055 /* protocol specifies ASCII buffer format (0x04) for unicode */
3056 pSMB->OldFileName[name_len] = 0x04;
3057 pSMB->OldFileName[name_len + 1] = 0x00; /* pad */
3059 cifsConvertToUTF16((__le16 *)&pSMB->OldFileName[name_len+2],
3060 to_name, PATH_MAX, cifs_sb->local_nls,
3062 name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
3063 name_len2 *= 2; /* convert to bytes */
3064 } else { /* BB improve the check for buffer overruns BB */
3065 name_len = strnlen(from_name, PATH_MAX);
3066 name_len++; /* trailing null */
3067 strncpy(pSMB->OldFileName, from_name, name_len);
3068 name_len2 = strnlen(to_name, PATH_MAX);
3069 name_len2++; /* trailing null */
3070 pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */
3071 strncpy(&pSMB->OldFileName[name_len + 1], to_name, name_len2);
3072 name_len2++; /* trailing null */
3073 name_len2++; /* signature byte */
3076 count = 1 /* string type byte */ + name_len + name_len2;
3077 inc_rfc1001_len(pSMB, count);
3078 pSMB->ByteCount = cpu_to_le16(count);
3080 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3081 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3082 cifs_stats_inc(&tcon->stats.cifs_stats.num_hardlinks);
3084 cifs_dbg(FYI, "Send error in hard link (NT rename) = %d\n", rc);
3086 cifs_buf_release(pSMB);
3088 goto winCreateHardLinkRetry;
3094 CIFSSMBUnixQuerySymLink(const unsigned int xid, struct cifs_tcon *tcon,
3095 const unsigned char *searchName, char **symlinkinfo,
3096 const struct nls_table *nls_codepage, int remap)
3098 /* SMB_QUERY_FILE_UNIX_LINK */
3099 TRANSACTION2_QPI_REQ *pSMB = NULL;
3100 TRANSACTION2_QPI_RSP *pSMBr = NULL;
3104 __u16 params, byte_count;
3107 cifs_dbg(FYI, "In QPathSymLinkInfo (Unix) for path %s\n", searchName);
3110 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3115 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3117 cifsConvertToUTF16((__le16 *) pSMB->FileName,
3118 searchName, PATH_MAX, nls_codepage,
3120 name_len++; /* trailing null */
3122 } else { /* BB improve the check for buffer overruns BB */
3123 name_len = strnlen(searchName, PATH_MAX);
3124 name_len++; /* trailing null */
3125 strncpy(pSMB->FileName, searchName, name_len);
3128 params = 2 /* level */ + 4 /* rsrvd */ + name_len /* incl null */ ;
3129 pSMB->TotalDataCount = 0;
3130 pSMB->MaxParameterCount = cpu_to_le16(2);
3131 pSMB->MaxDataCount = cpu_to_le16(CIFSMaxBufSize);
3132 pSMB->MaxSetupCount = 0;
3136 pSMB->Reserved2 = 0;
3137 pSMB->ParameterOffset = cpu_to_le16(offsetof(
3138 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
3139 pSMB->DataCount = 0;
3140 pSMB->DataOffset = 0;
3141 pSMB->SetupCount = 1;
3142 pSMB->Reserved3 = 0;
3143 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
3144 byte_count = params + 1 /* pad */ ;
3145 pSMB->TotalParameterCount = cpu_to_le16(params);
3146 pSMB->ParameterCount = pSMB->TotalParameterCount;
3147 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_LINK);
3148 pSMB->Reserved4 = 0;
3149 inc_rfc1001_len(pSMB, byte_count);
3150 pSMB->ByteCount = cpu_to_le16(byte_count);
3152 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3153 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3155 cifs_dbg(FYI, "Send error in QuerySymLinkInfo = %d\n", rc);
3157 /* decode response */
3159 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3160 /* BB also check enough total bytes returned */
3161 if (rc || get_bcc(&pSMBr->hdr) < 2)
3165 u16 count = le16_to_cpu(pSMBr->t2.DataCount);
3167 data_start = ((char *) &pSMBr->hdr.Protocol) +
3168 le16_to_cpu(pSMBr->t2.DataOffset);
3170 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
3175 /* BB FIXME investigate remapping reserved chars here */
3176 *symlinkinfo = cifs_strndup_from_utf16(data_start,
3177 count, is_unicode, nls_codepage);
3182 cifs_buf_release(pSMB);
3184 goto querySymLinkRetry;
3189 * Recent Windows versions now create symlinks more frequently
3190 * and they use the "reparse point" mechanism below. We can of course
3191 * do symlinks nicely to Samba and other servers which support the
3192 * CIFS Unix Extensions and we can also do SFU symlinks and "client only"
3193 * "MF" symlinks optionally, but for recent Windows we really need to
3194 * reenable the code below and fix the cifs_symlink callers to handle this.
3195 * In the interim this code has been moved to its own config option so
3196 * it is not compiled in by default until callers fixed up and more tested.
3199 CIFSSMBQuerySymLink(const unsigned int xid, struct cifs_tcon *tcon,
3200 __u16 fid, char **symlinkinfo,
3201 const struct nls_table *nls_codepage)
3205 struct smb_com_transaction_ioctl_req *pSMB;
3206 struct smb_com_transaction_ioctl_rsp *pSMBr;
3208 unsigned int sub_len;
3210 struct reparse_symlink_data *reparse_buf;
3211 struct reparse_posix_data *posix_buf;
3212 __u32 data_offset, data_count;
3215 cifs_dbg(FYI, "In Windows reparse style QueryLink for fid %u\n", fid);
3216 rc = smb_init(SMB_COM_NT_TRANSACT, 23, tcon, (void **) &pSMB,
3221 pSMB->TotalParameterCount = 0 ;
3222 pSMB->TotalDataCount = 0;
3223 pSMB->MaxParameterCount = cpu_to_le32(2);
3224 /* BB find exact data count max from sess structure BB */
3225 pSMB->MaxDataCount = cpu_to_le32(CIFSMaxBufSize & 0xFFFFFF00);
3226 pSMB->MaxSetupCount = 4;
3228 pSMB->ParameterOffset = 0;
3229 pSMB->DataCount = 0;
3230 pSMB->DataOffset = 0;
3231 pSMB->SetupCount = 4;
3232 pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_IOCTL);
3233 pSMB->ParameterCount = pSMB->TotalParameterCount;
3234 pSMB->FunctionCode = cpu_to_le32(FSCTL_GET_REPARSE_POINT);
3235 pSMB->IsFsctl = 1; /* FSCTL */
3236 pSMB->IsRootFlag = 0;
3237 pSMB->Fid = fid; /* file handle always le */
3238 pSMB->ByteCount = 0;
3240 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3241 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3243 cifs_dbg(FYI, "Send error in QueryReparseLinkInfo = %d\n", rc);
3247 data_offset = le32_to_cpu(pSMBr->DataOffset);
3248 data_count = le32_to_cpu(pSMBr->DataCount);
3249 if (get_bcc(&pSMBr->hdr) < 2 || data_offset > 512) {
3250 /* BB also check enough total bytes returned */
3251 rc = -EIO; /* bad smb */
3254 if (!data_count || (data_count > 2048)) {
3256 cifs_dbg(FYI, "Invalid return data count on get reparse info ioctl\n");
3259 end_of_smb = 2 + get_bcc(&pSMBr->hdr) + (char *)&pSMBr->ByteCount;
3260 reparse_buf = (struct reparse_symlink_data *)
3261 ((char *)&pSMBr->hdr.Protocol + data_offset);
3262 if ((char *)reparse_buf >= end_of_smb) {
3266 if (reparse_buf->ReparseTag == cpu_to_le32(IO_REPARSE_TAG_NFS)) {
3267 cifs_dbg(FYI, "NFS style reparse tag\n");
3268 posix_buf = (struct reparse_posix_data *)reparse_buf;
3270 if (posix_buf->InodeType != cpu_to_le64(NFS_SPECFILE_LNK)) {
3271 cifs_dbg(FYI, "unsupported file type 0x%llx\n",
3272 le64_to_cpu(posix_buf->InodeType));
3277 sub_len = le16_to_cpu(reparse_buf->ReparseDataLength);
3278 if (posix_buf->PathBuffer + sub_len > end_of_smb) {
3279 cifs_dbg(FYI, "reparse buf beyond SMB\n");
3283 *symlinkinfo = cifs_strndup_from_utf16(posix_buf->PathBuffer,
3284 sub_len, is_unicode, nls_codepage);
3286 } else if (reparse_buf->ReparseTag !=
3287 cpu_to_le32(IO_REPARSE_TAG_SYMLINK)) {
3292 /* Reparse tag is NTFS symlink */
3293 sub_start = le16_to_cpu(reparse_buf->SubstituteNameOffset) +
3294 reparse_buf->PathBuffer;
3295 sub_len = le16_to_cpu(reparse_buf->SubstituteNameLength);
3296 if (sub_start + sub_len > end_of_smb) {
3297 cifs_dbg(FYI, "reparse buf beyond SMB\n");
3301 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
3306 /* BB FIXME investigate remapping reserved chars here */
3307 *symlinkinfo = cifs_strndup_from_utf16(sub_start, sub_len, is_unicode,
3312 cifs_buf_release(pSMB);
3315 * Note: On -EAGAIN error only caller can retry on handle based calls
3316 * since file handle passed in no longer valid.
3322 CIFSSMB_set_compression(const unsigned int xid, struct cifs_tcon *tcon,
3327 struct smb_com_transaction_compr_ioctl_req *pSMB;
3328 struct smb_com_transaction_ioctl_rsp *pSMBr;
3330 cifs_dbg(FYI, "Set compression for %u\n", fid);
3331 rc = smb_init(SMB_COM_NT_TRANSACT, 23, tcon, (void **) &pSMB,
3336 pSMB->compression_state = cpu_to_le16(COMPRESSION_FORMAT_DEFAULT);
3338 pSMB->TotalParameterCount = 0;
3339 pSMB->TotalDataCount = cpu_to_le32(2);
3340 pSMB->MaxParameterCount = 0;
3341 pSMB->MaxDataCount = 0;
3342 pSMB->MaxSetupCount = 4;
3344 pSMB->ParameterOffset = 0;
3345 pSMB->DataCount = cpu_to_le32(2);
3347 cpu_to_le32(offsetof(struct smb_com_transaction_compr_ioctl_req,
3348 compression_state) - 4); /* 84 */
3349 pSMB->SetupCount = 4;
3350 pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_IOCTL);
3351 pSMB->ParameterCount = 0;
3352 pSMB->FunctionCode = cpu_to_le32(FSCTL_SET_COMPRESSION);
3353 pSMB->IsFsctl = 1; /* FSCTL */
3354 pSMB->IsRootFlag = 0;
3355 pSMB->Fid = fid; /* file handle always le */
3356 /* 3 byte pad, followed by 2 byte compress state */
3357 pSMB->ByteCount = cpu_to_le16(5);
3358 inc_rfc1001_len(pSMB, 5);
3360 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3361 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3363 cifs_dbg(FYI, "Send error in SetCompression = %d\n", rc);
3365 cifs_buf_release(pSMB);
3368 * Note: On -EAGAIN error only caller can retry on handle based calls
3369 * since file handle passed in no longer valid.
3375 #ifdef CONFIG_CIFS_POSIX
3377 /*Convert an Access Control Entry from wire format to local POSIX xattr format*/
3378 static void cifs_convert_ace(struct posix_acl_xattr_entry *ace,
3379 struct cifs_posix_ace *cifs_ace)
3381 /* u8 cifs fields do not need le conversion */
3382 ace->e_perm = cpu_to_le16(cifs_ace->cifs_e_perm);
3383 ace->e_tag = cpu_to_le16(cifs_ace->cifs_e_tag);
3384 ace->e_id = cpu_to_le32(le64_to_cpu(cifs_ace->cifs_uid));
3386 cifs_dbg(FYI, "perm %d tag %d id %d\n",
3387 ace->e_perm, ace->e_tag, ace->e_id);
3393 /* Convert ACL from CIFS POSIX wire format to local Linux POSIX ACL xattr */
3394 static int cifs_copy_posix_acl(char *trgt, char *src, const int buflen,
3395 const int acl_type, const int size_of_data_area)
3400 struct cifs_posix_ace *pACE;
3401 struct cifs_posix_acl *cifs_acl = (struct cifs_posix_acl *)src;
3402 struct posix_acl_xattr_header *local_acl = (void *)trgt;
3404 if (le16_to_cpu(cifs_acl->version) != CIFS_ACL_VERSION)
3407 if (acl_type == ACL_TYPE_ACCESS) {
3408 count = le16_to_cpu(cifs_acl->access_entry_count);
3409 pACE = &cifs_acl->ace_array[0];
3410 size = sizeof(struct cifs_posix_acl);
3411 size += sizeof(struct cifs_posix_ace) * count;
3412 /* check if we would go beyond end of SMB */
3413 if (size_of_data_area < size) {
3414 cifs_dbg(FYI, "bad CIFS POSIX ACL size %d vs. %d\n",
3415 size_of_data_area, size);
3418 } else if (acl_type == ACL_TYPE_DEFAULT) {
3419 count = le16_to_cpu(cifs_acl->access_entry_count);
3420 size = sizeof(struct cifs_posix_acl);
3421 size += sizeof(struct cifs_posix_ace) * count;
3422 /* skip past access ACEs to get to default ACEs */
3423 pACE = &cifs_acl->ace_array[count];
3424 count = le16_to_cpu(cifs_acl->default_entry_count);
3425 size += sizeof(struct cifs_posix_ace) * count;
3426 /* check if we would go beyond end of SMB */
3427 if (size_of_data_area < size)
3434 size = posix_acl_xattr_size(count);
3435 if ((buflen == 0) || (local_acl == NULL)) {
3436 /* used to query ACL EA size */
3437 } else if (size > buflen) {
3439 } else /* buffer big enough */ {
3440 struct posix_acl_xattr_entry *ace = (void *)(local_acl + 1);
3442 local_acl->a_version = cpu_to_le32(POSIX_ACL_XATTR_VERSION);
3443 for (i = 0; i < count ; i++) {
3444 cifs_convert_ace(&ace[i], pACE);
3451 static __u16 convert_ace_to_cifs_ace(struct cifs_posix_ace *cifs_ace,
3452 const struct posix_acl_xattr_entry *local_ace)
3454 __u16 rc = 0; /* 0 = ACL converted ok */
3456 cifs_ace->cifs_e_perm = le16_to_cpu(local_ace->e_perm);
3457 cifs_ace->cifs_e_tag = le16_to_cpu(local_ace->e_tag);
3458 /* BB is there a better way to handle the large uid? */
3459 if (local_ace->e_id == cpu_to_le32(-1)) {
3460 /* Probably no need to le convert -1 on any arch but can not hurt */
3461 cifs_ace->cifs_uid = cpu_to_le64(-1);
3463 cifs_ace->cifs_uid = cpu_to_le64(le32_to_cpu(local_ace->e_id));
3465 cifs_dbg(FYI, "perm %d tag %d id %d\n",
3466 ace->e_perm, ace->e_tag, ace->e_id);
3471 /* Convert ACL from local Linux POSIX xattr to CIFS POSIX ACL wire format */
3472 static __u16 ACL_to_cifs_posix(char *parm_data, const char *pACL,
3473 const int buflen, const int acl_type)
3476 struct cifs_posix_acl *cifs_acl = (struct cifs_posix_acl *)parm_data;
3477 struct posix_acl_xattr_header *local_acl = (void *)pACL;
3478 struct posix_acl_xattr_entry *ace = (void *)(local_acl + 1);
3482 if ((buflen == 0) || (pACL == NULL) || (cifs_acl == NULL))
3485 count = posix_acl_xattr_count((size_t)buflen);
3486 cifs_dbg(FYI, "setting acl with %d entries from buf of length %d and version of %d\n",
3487 count, buflen, le32_to_cpu(local_acl->a_version));
3488 if (le32_to_cpu(local_acl->a_version) != 2) {
3489 cifs_dbg(FYI, "unknown POSIX ACL version %d\n",
3490 le32_to_cpu(local_acl->a_version));
3493 cifs_acl->version = cpu_to_le16(1);
3494 if (acl_type == ACL_TYPE_ACCESS) {
3495 cifs_acl->access_entry_count = cpu_to_le16(count);
3496 cifs_acl->default_entry_count = cpu_to_le16(0xFFFF);
3497 } else if (acl_type == ACL_TYPE_DEFAULT) {
3498 cifs_acl->default_entry_count = cpu_to_le16(count);
3499 cifs_acl->access_entry_count = cpu_to_le16(0xFFFF);
3501 cifs_dbg(FYI, "unknown ACL type %d\n", acl_type);
3504 for (i = 0; i < count; i++) {
3505 rc = convert_ace_to_cifs_ace(&cifs_acl->ace_array[i], &ace[i]);
3507 /* ACE not converted */
3512 rc = (__u16)(count * sizeof(struct cifs_posix_ace));
3513 rc += sizeof(struct cifs_posix_acl);
3514 /* BB add check to make sure ACL does not overflow SMB */
3520 CIFSSMBGetPosixACL(const unsigned int xid, struct cifs_tcon *tcon,
3521 const unsigned char *searchName,
3522 char *acl_inf, const int buflen, const int acl_type,
3523 const struct nls_table *nls_codepage, int remap)
3525 /* SMB_QUERY_POSIX_ACL */
3526 TRANSACTION2_QPI_REQ *pSMB = NULL;
3527 TRANSACTION2_QPI_RSP *pSMBr = NULL;
3531 __u16 params, byte_count;
3533 cifs_dbg(FYI, "In GetPosixACL (Unix) for path %s\n", searchName);
3536 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3541 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3543 cifsConvertToUTF16((__le16 *) pSMB->FileName,
3544 searchName, PATH_MAX, nls_codepage,
3546 name_len++; /* trailing null */
3548 pSMB->FileName[name_len] = 0;
3549 pSMB->FileName[name_len+1] = 0;
3550 } else { /* BB improve the check for buffer overruns BB */
3551 name_len = strnlen(searchName, PATH_MAX);
3552 name_len++; /* trailing null */
3553 strncpy(pSMB->FileName, searchName, name_len);
3556 params = 2 /* level */ + 4 /* rsrvd */ + name_len /* incl null */ ;
3557 pSMB->TotalDataCount = 0;
3558 pSMB->MaxParameterCount = cpu_to_le16(2);
3559 /* BB find exact max data count below from sess structure BB */
3560 pSMB->MaxDataCount = cpu_to_le16(4000);
3561 pSMB->MaxSetupCount = 0;
3565 pSMB->Reserved2 = 0;
3566 pSMB->ParameterOffset = cpu_to_le16(
3567 offsetof(struct smb_com_transaction2_qpi_req,
3568 InformationLevel) - 4);
3569 pSMB->DataCount = 0;
3570 pSMB->DataOffset = 0;
3571 pSMB->SetupCount = 1;
3572 pSMB->Reserved3 = 0;
3573 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
3574 byte_count = params + 1 /* pad */ ;
3575 pSMB->TotalParameterCount = cpu_to_le16(params);
3576 pSMB->ParameterCount = pSMB->TotalParameterCount;
3577 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_POSIX_ACL);
3578 pSMB->Reserved4 = 0;
3579 inc_rfc1001_len(pSMB, byte_count);
3580 pSMB->ByteCount = cpu_to_le16(byte_count);
3582 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3583 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3584 cifs_stats_inc(&tcon->stats.cifs_stats.num_acl_get);
3586 cifs_dbg(FYI, "Send error in Query POSIX ACL = %d\n", rc);
3588 /* decode response */
3590 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3591 /* BB also check enough total bytes returned */
3592 if (rc || get_bcc(&pSMBr->hdr) < 2)
3593 rc = -EIO; /* bad smb */
3595 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3596 __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
3597 rc = cifs_copy_posix_acl(acl_inf,
3598 (char *)&pSMBr->hdr.Protocol+data_offset,
3599 buflen, acl_type, count);
3602 cifs_buf_release(pSMB);
3609 CIFSSMBSetPosixACL(const unsigned int xid, struct cifs_tcon *tcon,
3610 const unsigned char *fileName,
3611 const char *local_acl, const int buflen,
3613 const struct nls_table *nls_codepage, int remap)
3615 struct smb_com_transaction2_spi_req *pSMB = NULL;
3616 struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
3620 int bytes_returned = 0;
3621 __u16 params, byte_count, data_count, param_offset, offset;
3623 cifs_dbg(FYI, "In SetPosixACL (Unix) for path %s\n", fileName);
3625 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3629 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3631 cifsConvertToUTF16((__le16 *) pSMB->FileName, fileName,
3632 PATH_MAX, nls_codepage, remap);
3633 name_len++; /* trailing null */
3635 } else { /* BB improve the check for buffer overruns BB */
3636 name_len = strnlen(fileName, PATH_MAX);
3637 name_len++; /* trailing null */
3638 strncpy(pSMB->FileName, fileName, name_len);
3640 params = 6 + name_len;
3641 pSMB->MaxParameterCount = cpu_to_le16(2);
3642 /* BB find max SMB size from sess */
3643 pSMB->MaxDataCount = cpu_to_le16(1000);
3644 pSMB->MaxSetupCount = 0;
3648 pSMB->Reserved2 = 0;
3649 param_offset = offsetof(struct smb_com_transaction2_spi_req,
3650 InformationLevel) - 4;
3651 offset = param_offset + params;
3652 parm_data = ((char *) &pSMB->hdr.Protocol) + offset;
3653 pSMB->ParameterOffset = cpu_to_le16(param_offset);
3655 /* convert to on the wire format for POSIX ACL */
3656 data_count = ACL_to_cifs_posix(parm_data, local_acl, buflen, acl_type);
3658 if (data_count == 0) {
3660 goto setACLerrorExit;
3662 pSMB->DataOffset = cpu_to_le16(offset);
3663 pSMB->SetupCount = 1;
3664 pSMB->Reserved3 = 0;
3665 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
3666 pSMB->InformationLevel = cpu_to_le16(SMB_SET_POSIX_ACL);
3667 byte_count = 3 /* pad */ + params + data_count;
3668 pSMB->DataCount = cpu_to_le16(data_count);
3669 pSMB->TotalDataCount = pSMB->DataCount;
3670 pSMB->ParameterCount = cpu_to_le16(params);
3671 pSMB->TotalParameterCount = pSMB->ParameterCount;
3672 pSMB->Reserved4 = 0;
3673 inc_rfc1001_len(pSMB, byte_count);
3674 pSMB->ByteCount = cpu_to_le16(byte_count);
3675 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3676 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3678 cifs_dbg(FYI, "Set POSIX ACL returned %d\n", rc);
3681 cifs_buf_release(pSMB);
3687 /* BB fix tabs in this function FIXME BB */
3689 CIFSGetExtAttr(const unsigned int xid, struct cifs_tcon *tcon,
3690 const int netfid, __u64 *pExtAttrBits, __u64 *pMask)
3693 struct smb_t2_qfi_req *pSMB = NULL;
3694 struct smb_t2_qfi_rsp *pSMBr = NULL;
3696 __u16 params, byte_count;
3698 cifs_dbg(FYI, "In GetExtAttr\n");
3703 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3708 params = 2 /* level */ + 2 /* fid */;
3709 pSMB->t2.TotalDataCount = 0;
3710 pSMB->t2.MaxParameterCount = cpu_to_le16(4);
3711 /* BB find exact max data count below from sess structure BB */
3712 pSMB->t2.MaxDataCount = cpu_to_le16(4000);
3713 pSMB->t2.MaxSetupCount = 0;
3714 pSMB->t2.Reserved = 0;
3716 pSMB->t2.Timeout = 0;
3717 pSMB->t2.Reserved2 = 0;
3718 pSMB->t2.ParameterOffset = cpu_to_le16(offsetof(struct smb_t2_qfi_req,
3720 pSMB->t2.DataCount = 0;
3721 pSMB->t2.DataOffset = 0;
3722 pSMB->t2.SetupCount = 1;
3723 pSMB->t2.Reserved3 = 0;
3724 pSMB->t2.SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION);
3725 byte_count = params + 1 /* pad */ ;
3726 pSMB->t2.TotalParameterCount = cpu_to_le16(params);
3727 pSMB->t2.ParameterCount = pSMB->t2.TotalParameterCount;
3728 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_ATTR_FLAGS);
3731 inc_rfc1001_len(pSMB, byte_count);
3732 pSMB->t2.ByteCount = cpu_to_le16(byte_count);
3734 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3735 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3737 cifs_dbg(FYI, "error %d in GetExtAttr\n", rc);
3739 /* decode response */
3740 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3741 /* BB also check enough total bytes returned */
3742 if (rc || get_bcc(&pSMBr->hdr) < 2)
3743 /* If rc should we check for EOPNOSUPP and
3744 disable the srvino flag? or in caller? */
3745 rc = -EIO; /* bad smb */
3747 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3748 __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
3749 struct file_chattr_info *pfinfo;
3750 /* BB Do we need a cast or hash here ? */
3752 cifs_dbg(FYI, "Illegal size ret in GetExtAttr\n");
3756 pfinfo = (struct file_chattr_info *)
3757 (data_offset + (char *) &pSMBr->hdr.Protocol);
3758 *pExtAttrBits = le64_to_cpu(pfinfo->mode);
3759 *pMask = le64_to_cpu(pfinfo->mask);
3763 cifs_buf_release(pSMB);
3765 goto GetExtAttrRetry;
3769 #endif /* CONFIG_POSIX */
3771 #ifdef CONFIG_CIFS_ACL
3773 * Initialize NT TRANSACT SMB into small smb request buffer. This assumes that
3774 * all NT TRANSACTS that we init here have total parm and data under about 400
3775 * bytes (to fit in small cifs buffer size), which is the case so far, it
3776 * easily fits. NB: Setup words themselves and ByteCount MaxSetupCount (size of
3777 * returned setup area) and MaxParameterCount (returned parms size) must be set
3781 smb_init_nttransact(const __u16 sub_command, const int setup_count,
3782 const int parm_len, struct cifs_tcon *tcon,
3787 struct smb_com_ntransact_req *pSMB;
3789 rc = small_smb_init(SMB_COM_NT_TRANSACT, 19 + setup_count, tcon,
3793 *ret_buf = (void *)pSMB;
3795 pSMB->TotalParameterCount = cpu_to_le32(parm_len);
3796 pSMB->TotalDataCount = 0;
3797 pSMB->MaxDataCount = cpu_to_le32(CIFSMaxBufSize & 0xFFFFFF00);
3798 pSMB->ParameterCount = pSMB->TotalParameterCount;
3799 pSMB->DataCount = pSMB->TotalDataCount;
3800 temp_offset = offsetof(struct smb_com_ntransact_req, Parms) +
3801 (setup_count * 2) - 4 /* for rfc1001 length itself */;
3802 pSMB->ParameterOffset = cpu_to_le32(temp_offset);
3803 pSMB->DataOffset = cpu_to_le32(temp_offset + parm_len);
3804 pSMB->SetupCount = setup_count; /* no need to le convert byte fields */
3805 pSMB->SubCommand = cpu_to_le16(sub_command);
3810 validate_ntransact(char *buf, char **ppparm, char **ppdata,
3811 __u32 *pparmlen, __u32 *pdatalen)
3814 __u32 data_count, data_offset, parm_count, parm_offset;
3815 struct smb_com_ntransact_rsp *pSMBr;
3824 pSMBr = (struct smb_com_ntransact_rsp *)buf;
3826 bcc = get_bcc(&pSMBr->hdr);
3827 end_of_smb = 2 /* sizeof byte count */ + bcc +
3828 (char *)&pSMBr->ByteCount;
3830 data_offset = le32_to_cpu(pSMBr->DataOffset);
3831 data_count = le32_to_cpu(pSMBr->DataCount);
3832 parm_offset = le32_to_cpu(pSMBr->ParameterOffset);
3833 parm_count = le32_to_cpu(pSMBr->ParameterCount);
3835 *ppparm = (char *)&pSMBr->hdr.Protocol + parm_offset;
3836 *ppdata = (char *)&pSMBr->hdr.Protocol + data_offset;
3838 /* should we also check that parm and data areas do not overlap? */
3839 if (*ppparm > end_of_smb) {
3840 cifs_dbg(FYI, "parms start after end of smb\n");
3842 } else if (parm_count + *ppparm > end_of_smb) {
3843 cifs_dbg(FYI, "parm end after end of smb\n");
3845 } else if (*ppdata > end_of_smb) {
3846 cifs_dbg(FYI, "data starts after end of smb\n");
3848 } else if (data_count + *ppdata > end_of_smb) {
3849 cifs_dbg(FYI, "data %p + count %d (%p) past smb end %p start %p\n",
3850 *ppdata, data_count, (data_count + *ppdata),
3853 } else if (parm_count + data_count > bcc) {
3854 cifs_dbg(FYI, "parm count and data count larger than SMB\n");
3857 *pdatalen = data_count;
3858 *pparmlen = parm_count;
3862 /* Get Security Descriptor (by handle) from remote server for a file or dir */
3864 CIFSSMBGetCIFSACL(const unsigned int xid, struct cifs_tcon *tcon, __u16 fid,
3865 struct cifs_ntsd **acl_inf, __u32 *pbuflen)
3869 QUERY_SEC_DESC_REQ *pSMB;
3871 struct kvec rsp_iov;
3873 cifs_dbg(FYI, "GetCifsACL\n");
3878 rc = smb_init_nttransact(NT_TRANSACT_QUERY_SECURITY_DESC, 0,
3879 8 /* parm len */, tcon, (void **) &pSMB);
3883 pSMB->MaxParameterCount = cpu_to_le32(4);
3884 /* BB TEST with big acls that might need to be e.g. larger than 16K */
3885 pSMB->MaxSetupCount = 0;
3886 pSMB->Fid = fid; /* file handle always le */
3887 pSMB->AclFlags = cpu_to_le32(CIFS_ACL_OWNER | CIFS_ACL_GROUP |
3889 pSMB->ByteCount = cpu_to_le16(11); /* 3 bytes pad + 8 bytes parm */
3890 inc_rfc1001_len(pSMB, 11);
3891 iov[0].iov_base = (char *)pSMB;
3892 iov[0].iov_len = be32_to_cpu(pSMB->hdr.smb_buf_length) + 4;
3894 rc = SendReceive2(xid, tcon->ses, iov, 1 /* num iovec */, &buf_type,
3896 cifs_small_buf_release(pSMB);
3897 cifs_stats_inc(&tcon->stats.cifs_stats.num_acl_get);
3899 cifs_dbg(FYI, "Send error in QuerySecDesc = %d\n", rc);
3900 } else { /* decode response */
3904 struct smb_com_ntransact_rsp *pSMBr;
3907 /* validate_nttransact */
3908 rc = validate_ntransact(rsp_iov.iov_base, (char **)&parm,
3909 &pdata, &parm_len, pbuflen);
3912 pSMBr = (struct smb_com_ntransact_rsp *)rsp_iov.iov_base;
3914 cifs_dbg(FYI, "smb %p parm %p data %p\n",
3915 pSMBr, parm, *acl_inf);
3917 if (le32_to_cpu(pSMBr->ParameterCount) != 4) {
3918 rc = -EIO; /* bad smb */
3923 /* BB check that data area is minimum length and as big as acl_len */
3925 acl_len = le32_to_cpu(*parm);
3926 if (acl_len != *pbuflen) {
3927 cifs_dbg(VFS, "acl length %d does not match %d\n",
3929 if (*pbuflen > acl_len)
3933 /* check if buffer is big enough for the acl
3934 header followed by the smallest SID */
3935 if ((*pbuflen < sizeof(struct cifs_ntsd) + 8) ||
3936 (*pbuflen >= 64 * 1024)) {
3937 cifs_dbg(VFS, "bad acl length %d\n", *pbuflen);
3941 *acl_inf = kmemdup(pdata, *pbuflen, GFP_KERNEL);
3942 if (*acl_inf == NULL) {
3949 free_rsp_buf(buf_type, rsp_iov.iov_base);
3954 CIFSSMBSetCIFSACL(const unsigned int xid, struct cifs_tcon *tcon, __u16 fid,
3955 struct cifs_ntsd *pntsd, __u32 acllen, int aclflag)
3957 __u16 byte_count, param_count, data_count, param_offset, data_offset;
3959 int bytes_returned = 0;
3960 SET_SEC_DESC_REQ *pSMB = NULL;
3964 rc = smb_init(SMB_COM_NT_TRANSACT, 19, tcon, (void **) &pSMB, &pSMBr);
3968 pSMB->MaxSetupCount = 0;
3972 param_offset = offsetof(struct smb_com_transaction_ssec_req, Fid) - 4;
3973 data_count = acllen;
3974 data_offset = param_offset + param_count;
3975 byte_count = 3 /* pad */ + param_count;
3977 pSMB->DataCount = cpu_to_le32(data_count);
3978 pSMB->TotalDataCount = pSMB->DataCount;
3979 pSMB->MaxParameterCount = cpu_to_le32(4);
3980 pSMB->MaxDataCount = cpu_to_le32(16384);
3981 pSMB->ParameterCount = cpu_to_le32(param_count);
3982 pSMB->ParameterOffset = cpu_to_le32(param_offset);
3983 pSMB->TotalParameterCount = pSMB->ParameterCount;
3984 pSMB->DataOffset = cpu_to_le32(data_offset);
3985 pSMB->SetupCount = 0;
3986 pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_SET_SECURITY_DESC);
3987 pSMB->ByteCount = cpu_to_le16(byte_count+data_count);
3989 pSMB->Fid = fid; /* file handle always le */
3990 pSMB->Reserved2 = 0;
3991 pSMB->AclFlags = cpu_to_le32(aclflag);
3993 if (pntsd && acllen) {
3994 memcpy((char *)pSMBr + offsetof(struct smb_hdr, Protocol) +
3995 data_offset, pntsd, acllen);
3996 inc_rfc1001_len(pSMB, byte_count + data_count);
3998 inc_rfc1001_len(pSMB, byte_count);
4000 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4001 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4003 cifs_dbg(FYI, "SetCIFSACL bytes_returned: %d, rc: %d\n",
4004 bytes_returned, rc);
4006 cifs_dbg(FYI, "Set CIFS ACL returned %d\n", rc);
4007 cifs_buf_release(pSMB);
4010 goto setCifsAclRetry;
4015 #endif /* CONFIG_CIFS_ACL */
4017 /* Legacy Query Path Information call for lookup to old servers such
4020 SMBQueryInformation(const unsigned int xid, struct cifs_tcon *tcon,
4021 const char *search_name, FILE_ALL_INFO *data,
4022 const struct nls_table *nls_codepage, int remap)
4024 QUERY_INFORMATION_REQ *pSMB;
4025 QUERY_INFORMATION_RSP *pSMBr;
4030 cifs_dbg(FYI, "In SMBQPath path %s\n", search_name);
4032 rc = smb_init(SMB_COM_QUERY_INFORMATION, 0, tcon, (void **) &pSMB,
4037 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4039 cifsConvertToUTF16((__le16 *) pSMB->FileName,
4040 search_name, PATH_MAX, nls_codepage,
4042 name_len++; /* trailing null */
4045 name_len = strnlen(search_name, PATH_MAX);
4046 name_len++; /* trailing null */
4047 strncpy(pSMB->FileName, search_name, name_len);
4049 pSMB->BufferFormat = 0x04;
4050 name_len++; /* account for buffer type byte */
4051 inc_rfc1001_len(pSMB, (__u16)name_len);
4052 pSMB->ByteCount = cpu_to_le16(name_len);
4054 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4055 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4057 cifs_dbg(FYI, "Send error in QueryInfo = %d\n", rc);
4060 __u32 time = le32_to_cpu(pSMBr->last_write_time);
4062 /* decode response */
4063 /* BB FIXME - add time zone adjustment BB */
4064 memset(data, 0, sizeof(FILE_ALL_INFO));
4067 /* decode time fields */
4068 data->ChangeTime = cpu_to_le64(cifs_UnixTimeToNT(ts));
4069 data->LastWriteTime = data->ChangeTime;
4070 data->LastAccessTime = 0;
4071 data->AllocationSize =
4072 cpu_to_le64(le32_to_cpu(pSMBr->size));
4073 data->EndOfFile = data->AllocationSize;
4075 cpu_to_le32(le16_to_cpu(pSMBr->attr));
4077 rc = -EIO; /* bad buffer passed in */
4079 cifs_buf_release(pSMB);
4088 CIFSSMBQFileInfo(const unsigned int xid, struct cifs_tcon *tcon,
4089 u16 netfid, FILE_ALL_INFO *pFindData)
4091 struct smb_t2_qfi_req *pSMB = NULL;
4092 struct smb_t2_qfi_rsp *pSMBr = NULL;
4095 __u16 params, byte_count;
4098 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4103 params = 2 /* level */ + 2 /* fid */;
4104 pSMB->t2.TotalDataCount = 0;
4105 pSMB->t2.MaxParameterCount = cpu_to_le16(4);
4106 /* BB find exact max data count below from sess structure BB */
4107 pSMB->t2.MaxDataCount = cpu_to_le16(CIFSMaxBufSize);
4108 pSMB->t2.MaxSetupCount = 0;
4109 pSMB->t2.Reserved = 0;
4111 pSMB->t2.Timeout = 0;
4112 pSMB->t2.Reserved2 = 0;
4113 pSMB->t2.ParameterOffset = cpu_to_le16(offsetof(struct smb_t2_qfi_req,
4115 pSMB->t2.DataCount = 0;
4116 pSMB->t2.DataOffset = 0;
4117 pSMB->t2.SetupCount = 1;
4118 pSMB->t2.Reserved3 = 0;
4119 pSMB->t2.SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION);
4120 byte_count = params + 1 /* pad */ ;
4121 pSMB->t2.TotalParameterCount = cpu_to_le16(params);
4122 pSMB->t2.ParameterCount = pSMB->t2.TotalParameterCount;
4123 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_ALL_INFO);
4126 inc_rfc1001_len(pSMB, byte_count);
4127 pSMB->t2.ByteCount = cpu_to_le16(byte_count);
4129 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4130 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4132 cifs_dbg(FYI, "Send error in QFileInfo = %d", rc);
4133 } else { /* decode response */
4134 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4136 if (rc) /* BB add auto retry on EOPNOTSUPP? */
4138 else if (get_bcc(&pSMBr->hdr) < 40)
4139 rc = -EIO; /* bad smb */
4140 else if (pFindData) {
4141 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4142 memcpy((char *) pFindData,
4143 (char *) &pSMBr->hdr.Protocol +
4144 data_offset, sizeof(FILE_ALL_INFO));
4148 cifs_buf_release(pSMB);
4150 goto QFileInfoRetry;
4156 CIFSSMBQPathInfo(const unsigned int xid, struct cifs_tcon *tcon,
4157 const char *search_name, FILE_ALL_INFO *data,
4158 int legacy /* old style infolevel */,
4159 const struct nls_table *nls_codepage, int remap)
4161 /* level 263 SMB_QUERY_FILE_ALL_INFO */
4162 TRANSACTION2_QPI_REQ *pSMB = NULL;
4163 TRANSACTION2_QPI_RSP *pSMBr = NULL;
4167 __u16 params, byte_count;
4169 /* cifs_dbg(FYI, "In QPathInfo path %s\n", search_name); */
4171 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4176 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4178 cifsConvertToUTF16((__le16 *) pSMB->FileName, search_name,
4179 PATH_MAX, nls_codepage, remap);
4180 name_len++; /* trailing null */
4182 } else { /* BB improve the check for buffer overruns BB */
4183 name_len = strnlen(search_name, PATH_MAX);
4184 name_len++; /* trailing null */
4185 strncpy(pSMB->FileName, search_name, name_len);
4188 params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */;
4189 pSMB->TotalDataCount = 0;
4190 pSMB->MaxParameterCount = cpu_to_le16(2);
4191 /* BB find exact max SMB PDU from sess structure BB */
4192 pSMB->MaxDataCount = cpu_to_le16(4000);
4193 pSMB->MaxSetupCount = 0;
4197 pSMB->Reserved2 = 0;
4198 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4199 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
4200 pSMB->DataCount = 0;
4201 pSMB->DataOffset = 0;
4202 pSMB->SetupCount = 1;
4203 pSMB->Reserved3 = 0;
4204 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
4205 byte_count = params + 1 /* pad */ ;
4206 pSMB->TotalParameterCount = cpu_to_le16(params);
4207 pSMB->ParameterCount = pSMB->TotalParameterCount;
4209 pSMB->InformationLevel = cpu_to_le16(SMB_INFO_STANDARD);
4211 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_ALL_INFO);
4212 pSMB->Reserved4 = 0;
4213 inc_rfc1001_len(pSMB, byte_count);
4214 pSMB->ByteCount = cpu_to_le16(byte_count);
4216 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4217 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4219 cifs_dbg(FYI, "Send error in QPathInfo = %d\n", rc);
4220 } else { /* decode response */
4221 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4223 if (rc) /* BB add auto retry on EOPNOTSUPP? */
4225 else if (!legacy && get_bcc(&pSMBr->hdr) < 40)
4226 rc = -EIO; /* bad smb */
4227 else if (legacy && get_bcc(&pSMBr->hdr) < 24)
4228 rc = -EIO; /* 24 or 26 expected but we do not read
4232 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4235 * On legacy responses we do not read the last field,
4236 * EAsize, fortunately since it varies by subdialect and
4237 * also note it differs on Set vs Get, ie two bytes or 4
4238 * bytes depending but we don't care here.
4241 size = sizeof(FILE_INFO_STANDARD);
4243 size = sizeof(FILE_ALL_INFO);
4244 memcpy((char *) data, (char *) &pSMBr->hdr.Protocol +
4249 cifs_buf_release(pSMB);
4251 goto QPathInfoRetry;
4257 CIFSSMBUnixQFileInfo(const unsigned int xid, struct cifs_tcon *tcon,
4258 u16 netfid, FILE_UNIX_BASIC_INFO *pFindData)
4260 struct smb_t2_qfi_req *pSMB = NULL;
4261 struct smb_t2_qfi_rsp *pSMBr = NULL;
4264 __u16 params, byte_count;
4267 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4272 params = 2 /* level */ + 2 /* fid */;
4273 pSMB->t2.TotalDataCount = 0;
4274 pSMB->t2.MaxParameterCount = cpu_to_le16(4);
4275 /* BB find exact max data count below from sess structure BB */
4276 pSMB->t2.MaxDataCount = cpu_to_le16(CIFSMaxBufSize);
4277 pSMB->t2.MaxSetupCount = 0;
4278 pSMB->t2.Reserved = 0;
4280 pSMB->t2.Timeout = 0;
4281 pSMB->t2.Reserved2 = 0;
4282 pSMB->t2.ParameterOffset = cpu_to_le16(offsetof(struct smb_t2_qfi_req,
4284 pSMB->t2.DataCount = 0;
4285 pSMB->t2.DataOffset = 0;
4286 pSMB->t2.SetupCount = 1;
4287 pSMB->t2.Reserved3 = 0;
4288 pSMB->t2.SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION);
4289 byte_count = params + 1 /* pad */ ;
4290 pSMB->t2.TotalParameterCount = cpu_to_le16(params);
4291 pSMB->t2.ParameterCount = pSMB->t2.TotalParameterCount;
4292 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC);
4295 inc_rfc1001_len(pSMB, byte_count);
4296 pSMB->t2.ByteCount = cpu_to_le16(byte_count);
4298 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4299 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4301 cifs_dbg(FYI, "Send error in UnixQFileInfo = %d", rc);
4302 } else { /* decode response */
4303 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4305 if (rc || get_bcc(&pSMBr->hdr) < sizeof(FILE_UNIX_BASIC_INFO)) {
4306 cifs_dbg(VFS, "Malformed FILE_UNIX_BASIC_INFO response. Unix Extensions can be disabled on mount by specifying the nosfu mount option.\n");
4307 rc = -EIO; /* bad smb */
4309 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4310 memcpy((char *) pFindData,
4311 (char *) &pSMBr->hdr.Protocol +
4313 sizeof(FILE_UNIX_BASIC_INFO));
4317 cifs_buf_release(pSMB);
4319 goto UnixQFileInfoRetry;
4325 CIFSSMBUnixQPathInfo(const unsigned int xid, struct cifs_tcon *tcon,
4326 const unsigned char *searchName,
4327 FILE_UNIX_BASIC_INFO *pFindData,
4328 const struct nls_table *nls_codepage, int remap)
4330 /* SMB_QUERY_FILE_UNIX_BASIC */
4331 TRANSACTION2_QPI_REQ *pSMB = NULL;
4332 TRANSACTION2_QPI_RSP *pSMBr = NULL;
4334 int bytes_returned = 0;
4336 __u16 params, byte_count;
4338 cifs_dbg(FYI, "In QPathInfo (Unix) the path %s\n", searchName);
4340 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4345 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4347 cifsConvertToUTF16((__le16 *) pSMB->FileName, searchName,
4348 PATH_MAX, nls_codepage, remap);
4349 name_len++; /* trailing null */
4351 } else { /* BB improve the check for buffer overruns BB */
4352 name_len = strnlen(searchName, PATH_MAX);
4353 name_len++; /* trailing null */
4354 strncpy(pSMB->FileName, searchName, name_len);
4357 params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */;
4358 pSMB->TotalDataCount = 0;
4359 pSMB->MaxParameterCount = cpu_to_le16(2);
4360 /* BB find exact max SMB PDU from sess structure BB */
4361 pSMB->MaxDataCount = cpu_to_le16(4000);
4362 pSMB->MaxSetupCount = 0;
4366 pSMB->Reserved2 = 0;
4367 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4368 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
4369 pSMB->DataCount = 0;
4370 pSMB->DataOffset = 0;
4371 pSMB->SetupCount = 1;
4372 pSMB->Reserved3 = 0;
4373 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
4374 byte_count = params + 1 /* pad */ ;
4375 pSMB->TotalParameterCount = cpu_to_le16(params);
4376 pSMB->ParameterCount = pSMB->TotalParameterCount;
4377 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC);
4378 pSMB->Reserved4 = 0;
4379 inc_rfc1001_len(pSMB, byte_count);
4380 pSMB->ByteCount = cpu_to_le16(byte_count);
4382 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4383 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4385 cifs_dbg(FYI, "Send error in UnixQPathInfo = %d", rc);
4386 } else { /* decode response */
4387 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4389 if (rc || get_bcc(&pSMBr->hdr) < sizeof(FILE_UNIX_BASIC_INFO)) {
4390 cifs_dbg(VFS, "Malformed FILE_UNIX_BASIC_INFO response. Unix Extensions can be disabled on mount by specifying the nosfu mount option.\n");
4391 rc = -EIO; /* bad smb */
4393 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4394 memcpy((char *) pFindData,
4395 (char *) &pSMBr->hdr.Protocol +
4397 sizeof(FILE_UNIX_BASIC_INFO));
4400 cifs_buf_release(pSMB);
4402 goto UnixQPathInfoRetry;
4407 /* xid, tcon, searchName and codepage are input parms, rest are returned */
4409 CIFSFindFirst(const unsigned int xid, struct cifs_tcon *tcon,
4410 const char *searchName, struct cifs_sb_info *cifs_sb,
4411 __u16 *pnetfid, __u16 search_flags,
4412 struct cifs_search_info *psrch_inf, bool msearch)
4414 /* level 257 SMB_ */
4415 TRANSACTION2_FFIRST_REQ *pSMB = NULL;
4416 TRANSACTION2_FFIRST_RSP *pSMBr = NULL;
4417 T2_FFIRST_RSP_PARMS *parms;
4419 int bytes_returned = 0;
4420 int name_len, remap;
4421 __u16 params, byte_count;
4422 struct nls_table *nls_codepage;
4424 cifs_dbg(FYI, "In FindFirst for %s\n", searchName);
4427 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4432 nls_codepage = cifs_sb->local_nls;
4433 remap = cifs_remap(cifs_sb);
4435 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4437 cifsConvertToUTF16((__le16 *) pSMB->FileName, searchName,
4438 PATH_MAX, nls_codepage, remap);
4439 /* We can not add the asterik earlier in case
4440 it got remapped to 0xF03A as if it were part of the
4441 directory name instead of a wildcard */
4444 pSMB->FileName[name_len] = CIFS_DIR_SEP(cifs_sb);
4445 pSMB->FileName[name_len+1] = 0;
4446 pSMB->FileName[name_len+2] = '*';
4447 pSMB->FileName[name_len+3] = 0;
4448 name_len += 4; /* now the trailing null */
4449 /* null terminate just in case */
4450 pSMB->FileName[name_len] = 0;
4451 pSMB->FileName[name_len+1] = 0;
4454 } else { /* BB add check for overrun of SMB buf BB */
4455 name_len = strnlen(searchName, PATH_MAX);
4456 /* BB fix here and in unicode clause above ie
4457 if (name_len > buffersize-header)
4458 free buffer exit; BB */
4459 strncpy(pSMB->FileName, searchName, name_len);
4461 pSMB->FileName[name_len] = CIFS_DIR_SEP(cifs_sb);
4462 pSMB->FileName[name_len+1] = '*';
4463 pSMB->FileName[name_len+2] = 0;
4468 params = 12 + name_len /* includes null */ ;
4469 pSMB->TotalDataCount = 0; /* no EAs */
4470 pSMB->MaxParameterCount = cpu_to_le16(10);
4471 pSMB->MaxDataCount = cpu_to_le16(CIFSMaxBufSize & 0xFFFFFF00);
4472 pSMB->MaxSetupCount = 0;
4476 pSMB->Reserved2 = 0;
4477 byte_count = params + 1 /* pad */ ;
4478 pSMB->TotalParameterCount = cpu_to_le16(params);
4479 pSMB->ParameterCount = pSMB->TotalParameterCount;
4480 pSMB->ParameterOffset = cpu_to_le16(
4481 offsetof(struct smb_com_transaction2_ffirst_req, SearchAttributes)
4483 pSMB->DataCount = 0;
4484 pSMB->DataOffset = 0;
4485 pSMB->SetupCount = 1; /* one byte, no need to make endian neutral */
4486 pSMB->Reserved3 = 0;
4487 pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_FIRST);
4488 pSMB->SearchAttributes =
4489 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
4491 pSMB->SearchCount = cpu_to_le16(CIFSMaxBufSize/sizeof(FILE_UNIX_INFO));
4492 pSMB->SearchFlags = cpu_to_le16(search_flags);
4493 pSMB->InformationLevel = cpu_to_le16(psrch_inf->info_level);
4495 /* BB what should we set StorageType to? Does it matter? BB */
4496 pSMB->SearchStorageType = 0;
4497 inc_rfc1001_len(pSMB, byte_count);
4498 pSMB->ByteCount = cpu_to_le16(byte_count);
4500 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4501 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4502 cifs_stats_inc(&tcon->stats.cifs_stats.num_ffirst);
4504 if (rc) {/* BB add logic to retry regular search if Unix search
4505 rejected unexpectedly by server */
4506 /* BB Add code to handle unsupported level rc */
4507 cifs_dbg(FYI, "Error in FindFirst = %d\n", rc);
4509 cifs_buf_release(pSMB);
4511 /* BB eventually could optimize out free and realloc of buf */
4514 goto findFirstRetry;
4515 } else { /* decode response */
4516 /* BB remember to free buffer if error BB */
4517 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4521 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
4522 psrch_inf->unicode = true;
4524 psrch_inf->unicode = false;
4526 psrch_inf->ntwrk_buf_start = (char *)pSMBr;
4527 psrch_inf->smallBuf = 0;
4528 psrch_inf->srch_entries_start =
4529 (char *) &pSMBr->hdr.Protocol +
4530 le16_to_cpu(pSMBr->t2.DataOffset);
4531 parms = (T2_FFIRST_RSP_PARMS *)((char *) &pSMBr->hdr.Protocol +
4532 le16_to_cpu(pSMBr->t2.ParameterOffset));
4534 if (parms->EndofSearch)
4535 psrch_inf->endOfSearch = true;
4537 psrch_inf->endOfSearch = false;
4539 psrch_inf->entries_in_buffer =
4540 le16_to_cpu(parms->SearchCount);
4541 psrch_inf->index_of_last_entry = 2 /* skip . and .. */ +
4542 psrch_inf->entries_in_buffer;
4543 lnoff = le16_to_cpu(parms->LastNameOffset);
4544 if (CIFSMaxBufSize < lnoff) {
4545 cifs_dbg(VFS, "ignoring corrupt resume name\n");
4546 psrch_inf->last_entry = NULL;
4550 psrch_inf->last_entry = psrch_inf->srch_entries_start +
4554 *pnetfid = parms->SearchHandle;
4556 cifs_buf_release(pSMB);
4563 int CIFSFindNext(const unsigned int xid, struct cifs_tcon *tcon,
4564 __u16 searchHandle, __u16 search_flags,
4565 struct cifs_search_info *psrch_inf)
4567 TRANSACTION2_FNEXT_REQ *pSMB = NULL;
4568 TRANSACTION2_FNEXT_RSP *pSMBr = NULL;
4569 T2_FNEXT_RSP_PARMS *parms;
4570 char *response_data;
4573 unsigned int name_len;
4574 __u16 params, byte_count;
4576 cifs_dbg(FYI, "In FindNext\n");
4578 if (psrch_inf->endOfSearch)
4581 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4586 params = 14; /* includes 2 bytes of null string, converted to LE below*/
4588 pSMB->TotalDataCount = 0; /* no EAs */
4589 pSMB->MaxParameterCount = cpu_to_le16(8);
4590 pSMB->MaxDataCount = cpu_to_le16(CIFSMaxBufSize & 0xFFFFFF00);
4591 pSMB->MaxSetupCount = 0;
4595 pSMB->Reserved2 = 0;
4596 pSMB->ParameterOffset = cpu_to_le16(
4597 offsetof(struct smb_com_transaction2_fnext_req,SearchHandle) - 4);
4598 pSMB->DataCount = 0;
4599 pSMB->DataOffset = 0;
4600 pSMB->SetupCount = 1;
4601 pSMB->Reserved3 = 0;
4602 pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_NEXT);
4603 pSMB->SearchHandle = searchHandle; /* always kept as le */
4605 cpu_to_le16(CIFSMaxBufSize / sizeof(FILE_UNIX_INFO));
4606 pSMB->InformationLevel = cpu_to_le16(psrch_inf->info_level);
4607 pSMB->ResumeKey = psrch_inf->resume_key;
4608 pSMB->SearchFlags = cpu_to_le16(search_flags);
4610 name_len = psrch_inf->resume_name_len;
4612 if (name_len < PATH_MAX) {
4613 memcpy(pSMB->ResumeFileName, psrch_inf->presume_name, name_len);
4614 byte_count += name_len;
4615 /* 14 byte parm len above enough for 2 byte null terminator */
4616 pSMB->ResumeFileName[name_len] = 0;
4617 pSMB->ResumeFileName[name_len+1] = 0;
4620 goto FNext2_err_exit;
4622 byte_count = params + 1 /* pad */ ;
4623 pSMB->TotalParameterCount = cpu_to_le16(params);
4624 pSMB->ParameterCount = pSMB->TotalParameterCount;
4625 inc_rfc1001_len(pSMB, byte_count);
4626 pSMB->ByteCount = cpu_to_le16(byte_count);
4628 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4629 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4630 cifs_stats_inc(&tcon->stats.cifs_stats.num_fnext);
4633 psrch_inf->endOfSearch = true;
4634 cifs_buf_release(pSMB);
4635 rc = 0; /* search probably was closed at end of search*/
4637 cifs_dbg(FYI, "FindNext returned = %d\n", rc);
4638 } else { /* decode response */
4639 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4644 /* BB fixme add lock for file (srch_info) struct here */
4645 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
4646 psrch_inf->unicode = true;
4648 psrch_inf->unicode = false;
4649 response_data = (char *) &pSMBr->hdr.Protocol +
4650 le16_to_cpu(pSMBr->t2.ParameterOffset);
4651 parms = (T2_FNEXT_RSP_PARMS *)response_data;
4652 response_data = (char *)&pSMBr->hdr.Protocol +
4653 le16_to_cpu(pSMBr->t2.DataOffset);
4654 if (psrch_inf->smallBuf)
4655 cifs_small_buf_release(
4656 psrch_inf->ntwrk_buf_start);
4658 cifs_buf_release(psrch_inf->ntwrk_buf_start);
4659 psrch_inf->srch_entries_start = response_data;
4660 psrch_inf->ntwrk_buf_start = (char *)pSMB;
4661 psrch_inf->smallBuf = 0;
4662 if (parms->EndofSearch)
4663 psrch_inf->endOfSearch = true;
4665 psrch_inf->endOfSearch = false;
4666 psrch_inf->entries_in_buffer =
4667 le16_to_cpu(parms->SearchCount);
4668 psrch_inf->index_of_last_entry +=
4669 psrch_inf->entries_in_buffer;
4670 lnoff = le16_to_cpu(parms->LastNameOffset);
4671 if (CIFSMaxBufSize < lnoff) {
4672 cifs_dbg(VFS, "ignoring corrupt resume name\n");
4673 psrch_inf->last_entry = NULL;
4676 psrch_inf->last_entry =
4677 psrch_inf->srch_entries_start + lnoff;
4679 /* cifs_dbg(FYI, "fnxt2 entries in buf %d index_of_last %d\n",
4680 psrch_inf->entries_in_buffer, psrch_inf->index_of_last_entry); */
4682 /* BB fixme add unlock here */
4687 /* BB On error, should we leave previous search buf (and count and
4688 last entry fields) intact or free the previous one? */
4690 /* Note: On -EAGAIN error only caller can retry on handle based calls
4691 since file handle passed in no longer valid */
4694 cifs_buf_release(pSMB);
4699 CIFSFindClose(const unsigned int xid, struct cifs_tcon *tcon,
4700 const __u16 searchHandle)
4703 FINDCLOSE_REQ *pSMB = NULL;
4705 cifs_dbg(FYI, "In CIFSSMBFindClose\n");
4706 rc = small_smb_init(SMB_COM_FIND_CLOSE2, 1, tcon, (void **)&pSMB);
4708 /* no sense returning error if session restarted
4709 as file handle has been closed */
4715 pSMB->FileID = searchHandle;
4716 pSMB->ByteCount = 0;
4717 rc = SendReceiveNoRsp(xid, tcon->ses, (char *) pSMB, 0);
4718 cifs_small_buf_release(pSMB);
4720 cifs_dbg(VFS, "Send error in FindClose = %d\n", rc);
4722 cifs_stats_inc(&tcon->stats.cifs_stats.num_fclose);
4724 /* Since session is dead, search handle closed on server already */
4732 CIFSGetSrvInodeNumber(const unsigned int xid, struct cifs_tcon *tcon,
4733 const char *search_name, __u64 *inode_number,
4734 const struct nls_table *nls_codepage, int remap)
4737 TRANSACTION2_QPI_REQ *pSMB = NULL;
4738 TRANSACTION2_QPI_RSP *pSMBr = NULL;
4739 int name_len, bytes_returned;
4740 __u16 params, byte_count;
4742 cifs_dbg(FYI, "In GetSrvInodeNum for %s\n", search_name);
4746 GetInodeNumberRetry:
4747 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4752 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4754 cifsConvertToUTF16((__le16 *) pSMB->FileName,
4755 search_name, PATH_MAX, nls_codepage,
4757 name_len++; /* trailing null */
4759 } else { /* BB improve the check for buffer overruns BB */
4760 name_len = strnlen(search_name, PATH_MAX);
4761 name_len++; /* trailing null */
4762 strncpy(pSMB->FileName, search_name, name_len);
4765 params = 2 /* level */ + 4 /* rsrvd */ + name_len /* incl null */ ;
4766 pSMB->TotalDataCount = 0;
4767 pSMB->MaxParameterCount = cpu_to_le16(2);
4768 /* BB find exact max data count below from sess structure BB */
4769 pSMB->MaxDataCount = cpu_to_le16(4000);
4770 pSMB->MaxSetupCount = 0;
4774 pSMB->Reserved2 = 0;
4775 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4776 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
4777 pSMB->DataCount = 0;
4778 pSMB->DataOffset = 0;
4779 pSMB->SetupCount = 1;
4780 pSMB->Reserved3 = 0;
4781 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
4782 byte_count = params + 1 /* pad */ ;
4783 pSMB->TotalParameterCount = cpu_to_le16(params);
4784 pSMB->ParameterCount = pSMB->TotalParameterCount;
4785 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_INTERNAL_INFO);
4786 pSMB->Reserved4 = 0;
4787 inc_rfc1001_len(pSMB, byte_count);
4788 pSMB->ByteCount = cpu_to_le16(byte_count);
4790 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4791 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4793 cifs_dbg(FYI, "error %d in QueryInternalInfo\n", rc);
4795 /* decode response */
4796 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4797 /* BB also check enough total bytes returned */
4798 if (rc || get_bcc(&pSMBr->hdr) < 2)
4799 /* If rc should we check for EOPNOSUPP and
4800 disable the srvino flag? or in caller? */
4801 rc = -EIO; /* bad smb */
4803 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4804 __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
4805 struct file_internal_info *pfinfo;
4806 /* BB Do we need a cast or hash here ? */
4808 cifs_dbg(FYI, "Illegal size ret in QryIntrnlInf\n");
4810 goto GetInodeNumOut;
4812 pfinfo = (struct file_internal_info *)
4813 (data_offset + (char *) &pSMBr->hdr.Protocol);
4814 *inode_number = le64_to_cpu(pfinfo->UniqueId);
4818 cifs_buf_release(pSMB);
4820 goto GetInodeNumberRetry;
4825 CIFSGetDFSRefer(const unsigned int xid, struct cifs_ses *ses,
4826 const char *search_name, struct dfs_info3_param **target_nodes,
4827 unsigned int *num_of_nodes,
4828 const struct nls_table *nls_codepage, int remap)
4830 /* TRANS2_GET_DFS_REFERRAL */
4831 TRANSACTION2_GET_DFS_REFER_REQ *pSMB = NULL;
4832 TRANSACTION2_GET_DFS_REFER_RSP *pSMBr = NULL;
4836 __u16 params, byte_count;
4838 *target_nodes = NULL;
4840 cifs_dbg(FYI, "In GetDFSRefer the path %s\n", search_name);
4841 if (ses == NULL || ses->tcon_ipc == NULL)
4845 rc = smb_init(SMB_COM_TRANSACTION2, 15, ses->tcon_ipc, (void **) &pSMB,
4850 /* server pointer checked in called function,
4851 but should never be null here anyway */
4852 pSMB->hdr.Mid = get_next_mid(ses->server);
4853 pSMB->hdr.Tid = ses->tcon_ipc->tid;
4854 pSMB->hdr.Uid = ses->Suid;
4855 if (ses->capabilities & CAP_STATUS32)
4856 pSMB->hdr.Flags2 |= SMBFLG2_ERR_STATUS;
4857 if (ses->capabilities & CAP_DFS)
4858 pSMB->hdr.Flags2 |= SMBFLG2_DFS;
4860 if (ses->capabilities & CAP_UNICODE) {
4861 pSMB->hdr.Flags2 |= SMBFLG2_UNICODE;
4863 cifsConvertToUTF16((__le16 *) pSMB->RequestFileName,
4864 search_name, PATH_MAX, nls_codepage,
4866 name_len++; /* trailing null */
4868 } else { /* BB improve the check for buffer overruns BB */
4869 name_len = strnlen(search_name, PATH_MAX);
4870 name_len++; /* trailing null */
4871 strncpy(pSMB->RequestFileName, search_name, name_len);
4874 if (ses->server->sign)
4875 pSMB->hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
4877 pSMB->hdr.Uid = ses->Suid;
4879 params = 2 /* level */ + name_len /*includes null */ ;
4880 pSMB->TotalDataCount = 0;
4881 pSMB->DataCount = 0;
4882 pSMB->DataOffset = 0;
4883 pSMB->MaxParameterCount = 0;
4884 /* BB find exact max SMB PDU from sess structure BB */
4885 pSMB->MaxDataCount = cpu_to_le16(4000);
4886 pSMB->MaxSetupCount = 0;
4890 pSMB->Reserved2 = 0;
4891 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4892 struct smb_com_transaction2_get_dfs_refer_req, MaxReferralLevel) - 4);
4893 pSMB->SetupCount = 1;
4894 pSMB->Reserved3 = 0;
4895 pSMB->SubCommand = cpu_to_le16(TRANS2_GET_DFS_REFERRAL);
4896 byte_count = params + 3 /* pad */ ;
4897 pSMB->ParameterCount = cpu_to_le16(params);
4898 pSMB->TotalParameterCount = pSMB->ParameterCount;
4899 pSMB->MaxReferralLevel = cpu_to_le16(3);
4900 inc_rfc1001_len(pSMB, byte_count);
4901 pSMB->ByteCount = cpu_to_le16(byte_count);
4903 rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB,
4904 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4906 cifs_dbg(FYI, "Send error in GetDFSRefer = %d\n", rc);
4909 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4911 /* BB Also check if enough total bytes returned? */
4912 if (rc || get_bcc(&pSMBr->hdr) < 17) {
4913 rc = -EIO; /* bad smb */
4917 cifs_dbg(FYI, "Decoding GetDFSRefer response BCC: %d Offset %d\n",
4918 get_bcc(&pSMBr->hdr), le16_to_cpu(pSMBr->t2.DataOffset));
4920 /* parse returned result into more usable form */
4921 rc = parse_dfs_referrals(&pSMBr->dfs_data,
4922 le16_to_cpu(pSMBr->t2.DataCount),
4923 num_of_nodes, target_nodes, nls_codepage,
4925 (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) != 0);
4928 cifs_buf_release(pSMB);
4936 /* Query File System Info such as free space to old servers such as Win 9x */
4938 SMBOldQFSInfo(const unsigned int xid, struct cifs_tcon *tcon,
4939 struct kstatfs *FSData)
4941 /* level 0x01 SMB_QUERY_FILE_SYSTEM_INFO */
4942 TRANSACTION2_QFSI_REQ *pSMB = NULL;
4943 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4944 FILE_SYSTEM_ALLOC_INFO *response_data;
4946 int bytes_returned = 0;
4947 __u16 params, byte_count;
4949 cifs_dbg(FYI, "OldQFSInfo\n");
4951 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4956 params = 2; /* level */
4957 pSMB->TotalDataCount = 0;
4958 pSMB->MaxParameterCount = cpu_to_le16(2);
4959 pSMB->MaxDataCount = cpu_to_le16(1000);
4960 pSMB->MaxSetupCount = 0;
4964 pSMB->Reserved2 = 0;
4965 byte_count = params + 1 /* pad */ ;
4966 pSMB->TotalParameterCount = cpu_to_le16(params);
4967 pSMB->ParameterCount = pSMB->TotalParameterCount;
4968 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4969 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4970 pSMB->DataCount = 0;
4971 pSMB->DataOffset = 0;
4972 pSMB->SetupCount = 1;
4973 pSMB->Reserved3 = 0;
4974 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4975 pSMB->InformationLevel = cpu_to_le16(SMB_INFO_ALLOCATION);
4976 inc_rfc1001_len(pSMB, byte_count);
4977 pSMB->ByteCount = cpu_to_le16(byte_count);
4979 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4980 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4982 cifs_dbg(FYI, "Send error in QFSInfo = %d\n", rc);
4983 } else { /* decode response */
4984 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4986 if (rc || get_bcc(&pSMBr->hdr) < 18)
4987 rc = -EIO; /* bad smb */
4989 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4990 cifs_dbg(FYI, "qfsinf resp BCC: %d Offset %d\n",
4991 get_bcc(&pSMBr->hdr), data_offset);
4993 response_data = (FILE_SYSTEM_ALLOC_INFO *)
4994 (((char *) &pSMBr->hdr.Protocol) + data_offset);
4996 le16_to_cpu(response_data->BytesPerSector) *
4997 le32_to_cpu(response_data->
4998 SectorsPerAllocationUnit);
5000 le32_to_cpu(response_data->TotalAllocationUnits);
5001 FSData->f_bfree = FSData->f_bavail =
5002 le32_to_cpu(response_data->FreeAllocationUnits);
5003 cifs_dbg(FYI, "Blocks: %lld Free: %lld Block size %ld\n",
5004 (unsigned long long)FSData->f_blocks,
5005 (unsigned long long)FSData->f_bfree,
5009 cifs_buf_release(pSMB);
5012 goto oldQFSInfoRetry;
5018 CIFSSMBQFSInfo(const unsigned int xid, struct cifs_tcon *tcon,
5019 struct kstatfs *FSData)
5021 /* level 0x103 SMB_QUERY_FILE_SYSTEM_INFO */
5022 TRANSACTION2_QFSI_REQ *pSMB = NULL;
5023 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
5024 FILE_SYSTEM_INFO *response_data;
5026 int bytes_returned = 0;
5027 __u16 params, byte_count;
5029 cifs_dbg(FYI, "In QFSInfo\n");
5031 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5036 params = 2; /* level */
5037 pSMB->TotalDataCount = 0;
5038 pSMB->MaxParameterCount = cpu_to_le16(2);
5039 pSMB->MaxDataCount = cpu_to_le16(1000);
5040 pSMB->MaxSetupCount = 0;
5044 pSMB->Reserved2 = 0;
5045 byte_count = params + 1 /* pad */ ;
5046 pSMB->TotalParameterCount = cpu_to_le16(params);
5047 pSMB->ParameterCount = pSMB->TotalParameterCount;
5048 pSMB->ParameterOffset = cpu_to_le16(offsetof(
5049 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
5050 pSMB->DataCount = 0;
5051 pSMB->DataOffset = 0;
5052 pSMB->SetupCount = 1;
5053 pSMB->Reserved3 = 0;
5054 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
5055 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_SIZE_INFO);
5056 inc_rfc1001_len(pSMB, byte_count);
5057 pSMB->ByteCount = cpu_to_le16(byte_count);
5059 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5060 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5062 cifs_dbg(FYI, "Send error in QFSInfo = %d\n", rc);
5063 } else { /* decode response */
5064 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
5066 if (rc || get_bcc(&pSMBr->hdr) < 24)
5067 rc = -EIO; /* bad smb */
5069 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
5073 *) (((char *) &pSMBr->hdr.Protocol) +
5076 le32_to_cpu(response_data->BytesPerSector) *
5077 le32_to_cpu(response_data->
5078 SectorsPerAllocationUnit);
5080 le64_to_cpu(response_data->TotalAllocationUnits);
5081 FSData->f_bfree = FSData->f_bavail =
5082 le64_to_cpu(response_data->FreeAllocationUnits);
5083 cifs_dbg(FYI, "Blocks: %lld Free: %lld Block size %ld\n",
5084 (unsigned long long)FSData->f_blocks,
5085 (unsigned long long)FSData->f_bfree,
5089 cifs_buf_release(pSMB);
5098 CIFSSMBQFSAttributeInfo(const unsigned int xid, struct cifs_tcon *tcon)
5100 /* level 0x105 SMB_QUERY_FILE_SYSTEM_INFO */
5101 TRANSACTION2_QFSI_REQ *pSMB = NULL;
5102 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
5103 FILE_SYSTEM_ATTRIBUTE_INFO *response_data;
5105 int bytes_returned = 0;
5106 __u16 params, byte_count;
5108 cifs_dbg(FYI, "In QFSAttributeInfo\n");
5110 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5115 params = 2; /* level */
5116 pSMB->TotalDataCount = 0;
5117 pSMB->MaxParameterCount = cpu_to_le16(2);
5118 /* BB find exact max SMB PDU from sess structure BB */
5119 pSMB->MaxDataCount = cpu_to_le16(1000);
5120 pSMB->MaxSetupCount = 0;
5124 pSMB->Reserved2 = 0;
5125 byte_count = params + 1 /* pad */ ;
5126 pSMB->TotalParameterCount = cpu_to_le16(params);
5127 pSMB->ParameterCount = pSMB->TotalParameterCount;
5128 pSMB->ParameterOffset = cpu_to_le16(offsetof(
5129 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
5130 pSMB->DataCount = 0;
5131 pSMB->DataOffset = 0;
5132 pSMB->SetupCount = 1;
5133 pSMB->Reserved3 = 0;
5134 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
5135 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_ATTRIBUTE_INFO);
5136 inc_rfc1001_len(pSMB, byte_count);
5137 pSMB->ByteCount = cpu_to_le16(byte_count);
5139 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5140 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5142 cifs_dbg(VFS, "Send error in QFSAttributeInfo = %d\n", rc);
5143 } else { /* decode response */
5144 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
5146 if (rc || get_bcc(&pSMBr->hdr) < 13) {
5147 /* BB also check if enough bytes returned */
5148 rc = -EIO; /* bad smb */
5150 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
5152 (FILE_SYSTEM_ATTRIBUTE_INFO
5153 *) (((char *) &pSMBr->hdr.Protocol) +
5155 memcpy(&tcon->fsAttrInfo, response_data,
5156 sizeof(FILE_SYSTEM_ATTRIBUTE_INFO));
5159 cifs_buf_release(pSMB);
5162 goto QFSAttributeRetry;
5168 CIFSSMBQFSDeviceInfo(const unsigned int xid, struct cifs_tcon *tcon)
5170 /* level 0x104 SMB_QUERY_FILE_SYSTEM_INFO */
5171 TRANSACTION2_QFSI_REQ *pSMB = NULL;
5172 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
5173 FILE_SYSTEM_DEVICE_INFO *response_data;
5175 int bytes_returned = 0;
5176 __u16 params, byte_count;
5178 cifs_dbg(FYI, "In QFSDeviceInfo\n");
5180 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5185 params = 2; /* level */
5186 pSMB->TotalDataCount = 0;
5187 pSMB->MaxParameterCount = cpu_to_le16(2);
5188 /* BB find exact max SMB PDU from sess structure BB */
5189 pSMB->MaxDataCount = cpu_to_le16(1000);
5190 pSMB->MaxSetupCount = 0;
5194 pSMB->Reserved2 = 0;
5195 byte_count = params + 1 /* pad */ ;
5196 pSMB->TotalParameterCount = cpu_to_le16(params);
5197 pSMB->ParameterCount = pSMB->TotalParameterCount;
5198 pSMB->ParameterOffset = cpu_to_le16(offsetof(
5199 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
5201 pSMB->DataCount = 0;
5202 pSMB->DataOffset = 0;
5203 pSMB->SetupCount = 1;
5204 pSMB->Reserved3 = 0;
5205 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
5206 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_DEVICE_INFO);
5207 inc_rfc1001_len(pSMB, byte_count);
5208 pSMB->ByteCount = cpu_to_le16(byte_count);
5210 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5211 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5213 cifs_dbg(FYI, "Send error in QFSDeviceInfo = %d\n", rc);
5214 } else { /* decode response */
5215 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
5217 if (rc || get_bcc(&pSMBr->hdr) <
5218 sizeof(FILE_SYSTEM_DEVICE_INFO))
5219 rc = -EIO; /* bad smb */
5221 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
5223 (FILE_SYSTEM_DEVICE_INFO *)
5224 (((char *) &pSMBr->hdr.Protocol) +
5226 memcpy(&tcon->fsDevInfo, response_data,
5227 sizeof(FILE_SYSTEM_DEVICE_INFO));
5230 cifs_buf_release(pSMB);
5233 goto QFSDeviceRetry;
5239 CIFSSMBQFSUnixInfo(const unsigned int xid, struct cifs_tcon *tcon)
5241 /* level 0x200 SMB_QUERY_CIFS_UNIX_INFO */
5242 TRANSACTION2_QFSI_REQ *pSMB = NULL;
5243 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
5244 FILE_SYSTEM_UNIX_INFO *response_data;
5246 int bytes_returned = 0;
5247 __u16 params, byte_count;
5249 cifs_dbg(FYI, "In QFSUnixInfo\n");
5251 rc = smb_init_no_reconnect(SMB_COM_TRANSACTION2, 15, tcon,
5252 (void **) &pSMB, (void **) &pSMBr);
5256 params = 2; /* level */
5257 pSMB->TotalDataCount = 0;
5258 pSMB->DataCount = 0;
5259 pSMB->DataOffset = 0;
5260 pSMB->MaxParameterCount = cpu_to_le16(2);
5261 /* BB find exact max SMB PDU from sess structure BB */
5262 pSMB->MaxDataCount = cpu_to_le16(100);
5263 pSMB->MaxSetupCount = 0;
5267 pSMB->Reserved2 = 0;
5268 byte_count = params + 1 /* pad */ ;
5269 pSMB->ParameterCount = cpu_to_le16(params);
5270 pSMB->TotalParameterCount = pSMB->ParameterCount;
5271 pSMB->ParameterOffset = cpu_to_le16(offsetof(struct
5272 smb_com_transaction2_qfsi_req, InformationLevel) - 4);
5273 pSMB->SetupCount = 1;
5274 pSMB->Reserved3 = 0;
5275 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
5276 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_CIFS_UNIX_INFO);
5277 inc_rfc1001_len(pSMB, byte_count);
5278 pSMB->ByteCount = cpu_to_le16(byte_count);
5280 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5281 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5283 cifs_dbg(VFS, "Send error in QFSUnixInfo = %d\n", rc);
5284 } else { /* decode response */
5285 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
5287 if (rc || get_bcc(&pSMBr->hdr) < 13) {
5288 rc = -EIO; /* bad smb */
5290 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
5292 (FILE_SYSTEM_UNIX_INFO
5293 *) (((char *) &pSMBr->hdr.Protocol) +
5295 memcpy(&tcon->fsUnixInfo, response_data,
5296 sizeof(FILE_SYSTEM_UNIX_INFO));
5299 cifs_buf_release(pSMB);
5309 CIFSSMBSetFSUnixInfo(const unsigned int xid, struct cifs_tcon *tcon, __u64 cap)
5311 /* level 0x200 SMB_SET_CIFS_UNIX_INFO */
5312 TRANSACTION2_SETFSI_REQ *pSMB = NULL;
5313 TRANSACTION2_SETFSI_RSP *pSMBr = NULL;
5315 int bytes_returned = 0;
5316 __u16 params, param_offset, offset, byte_count;
5318 cifs_dbg(FYI, "In SETFSUnixInfo\n");
5320 /* BB switch to small buf init to save memory */
5321 rc = smb_init_no_reconnect(SMB_COM_TRANSACTION2, 15, tcon,
5322 (void **) &pSMB, (void **) &pSMBr);
5326 params = 4; /* 2 bytes zero followed by info level. */
5327 pSMB->MaxSetupCount = 0;
5331 pSMB->Reserved2 = 0;
5332 param_offset = offsetof(struct smb_com_transaction2_setfsi_req, FileNum)
5334 offset = param_offset + params;
5336 pSMB->MaxParameterCount = cpu_to_le16(4);
5337 /* BB find exact max SMB PDU from sess structure BB */
5338 pSMB->MaxDataCount = cpu_to_le16(100);
5339 pSMB->SetupCount = 1;
5340 pSMB->Reserved3 = 0;
5341 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FS_INFORMATION);
5342 byte_count = 1 /* pad */ + params + 12;
5344 pSMB->DataCount = cpu_to_le16(12);
5345 pSMB->ParameterCount = cpu_to_le16(params);
5346 pSMB->TotalDataCount = pSMB->DataCount;
5347 pSMB->TotalParameterCount = pSMB->ParameterCount;
5348 pSMB->ParameterOffset = cpu_to_le16(param_offset);
5349 pSMB->DataOffset = cpu_to_le16(offset);
5353 pSMB->InformationLevel = cpu_to_le16(SMB_SET_CIFS_UNIX_INFO);
5356 pSMB->ClientUnixMajor = cpu_to_le16(CIFS_UNIX_MAJOR_VERSION);
5357 pSMB->ClientUnixMinor = cpu_to_le16(CIFS_UNIX_MINOR_VERSION);
5358 pSMB->ClientUnixCap = cpu_to_le64(cap);
5360 inc_rfc1001_len(pSMB, byte_count);
5361 pSMB->ByteCount = cpu_to_le16(byte_count);
5363 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5364 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5366 cifs_dbg(VFS, "Send error in SETFSUnixInfo = %d\n", rc);
5367 } else { /* decode response */
5368 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
5370 rc = -EIO; /* bad smb */
5372 cifs_buf_release(pSMB);
5375 goto SETFSUnixRetry;
5383 CIFSSMBQFSPosixInfo(const unsigned int xid, struct cifs_tcon *tcon,
5384 struct kstatfs *FSData)
5386 /* level 0x201 SMB_QUERY_CIFS_POSIX_INFO */
5387 TRANSACTION2_QFSI_REQ *pSMB = NULL;
5388 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
5389 FILE_SYSTEM_POSIX_INFO *response_data;
5391 int bytes_returned = 0;
5392 __u16 params, byte_count;
5394 cifs_dbg(FYI, "In QFSPosixInfo\n");
5396 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5401 params = 2; /* level */
5402 pSMB->TotalDataCount = 0;
5403 pSMB->DataCount = 0;
5404 pSMB->DataOffset = 0;
5405 pSMB->MaxParameterCount = cpu_to_le16(2);
5406 /* BB find exact max SMB PDU from sess structure BB */
5407 pSMB->MaxDataCount = cpu_to_le16(100);
5408 pSMB->MaxSetupCount = 0;
5412 pSMB->Reserved2 = 0;
5413 byte_count = params + 1 /* pad */ ;
5414 pSMB->ParameterCount = cpu_to_le16(params);
5415 pSMB->TotalParameterCount = pSMB->ParameterCount;
5416 pSMB->ParameterOffset = cpu_to_le16(offsetof(struct
5417 smb_com_transaction2_qfsi_req, InformationLevel) - 4);
5418 pSMB->SetupCount = 1;
5419 pSMB->Reserved3 = 0;
5420 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
5421 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_POSIX_FS_INFO);
5422 inc_rfc1001_len(pSMB, byte_count);
5423 pSMB->ByteCount = cpu_to_le16(byte_count);
5425 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5426 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5428 cifs_dbg(FYI, "Send error in QFSUnixInfo = %d\n", rc);
5429 } else { /* decode response */
5430 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
5432 if (rc || get_bcc(&pSMBr->hdr) < 13) {
5433 rc = -EIO; /* bad smb */
5435 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
5437 (FILE_SYSTEM_POSIX_INFO
5438 *) (((char *) &pSMBr->hdr.Protocol) +
5441 le32_to_cpu(response_data->BlockSize);
5443 le64_to_cpu(response_data->TotalBlocks);
5445 le64_to_cpu(response_data->BlocksAvail);
5446 if (response_data->UserBlocksAvail == cpu_to_le64(-1)) {
5447 FSData->f_bavail = FSData->f_bfree;
5450 le64_to_cpu(response_data->UserBlocksAvail);
5452 if (response_data->TotalFileNodes != cpu_to_le64(-1))
5454 le64_to_cpu(response_data->TotalFileNodes);
5455 if (response_data->FreeFileNodes != cpu_to_le64(-1))
5457 le64_to_cpu(response_data->FreeFileNodes);
5460 cifs_buf_release(pSMB);
5470 * We can not use write of zero bytes trick to set file size due to need for
5471 * large file support. Also note that this SetPathInfo is preferred to
5472 * SetFileInfo based method in next routine which is only needed to work around
5473 * a sharing violation bugin Samba which this routine can run into.
5476 CIFSSMBSetEOF(const unsigned int xid, struct cifs_tcon *tcon,
5477 const char *file_name, __u64 size, struct cifs_sb_info *cifs_sb,
5478 bool set_allocation)
5480 struct smb_com_transaction2_spi_req *pSMB = NULL;
5481 struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
5482 struct file_end_of_file_info *parm_data;
5485 int bytes_returned = 0;
5486 int remap = cifs_remap(cifs_sb);
5488 __u16 params, byte_count, data_count, param_offset, offset;
5490 cifs_dbg(FYI, "In SetEOF\n");
5492 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5497 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5499 cifsConvertToUTF16((__le16 *) pSMB->FileName, file_name,
5500 PATH_MAX, cifs_sb->local_nls, remap);
5501 name_len++; /* trailing null */
5503 } else { /* BB improve the check for buffer overruns BB */
5504 name_len = strnlen(file_name, PATH_MAX);
5505 name_len++; /* trailing null */
5506 strncpy(pSMB->FileName, file_name, name_len);
5508 params = 6 + name_len;
5509 data_count = sizeof(struct file_end_of_file_info);
5510 pSMB->MaxParameterCount = cpu_to_le16(2);
5511 pSMB->MaxDataCount = cpu_to_le16(4100);
5512 pSMB->MaxSetupCount = 0;
5516 pSMB->Reserved2 = 0;
5517 param_offset = offsetof(struct smb_com_transaction2_spi_req,
5518 InformationLevel) - 4;
5519 offset = param_offset + params;
5520 if (set_allocation) {
5521 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
5522 pSMB->InformationLevel =
5523 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2);
5525 pSMB->InformationLevel =
5526 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO);
5527 } else /* Set File Size */ {
5528 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
5529 pSMB->InformationLevel =
5530 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO2);
5532 pSMB->InformationLevel =
5533 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO);
5537 (struct file_end_of_file_info *) (((char *) &pSMB->hdr.Protocol) +
5539 pSMB->ParameterOffset = cpu_to_le16(param_offset);
5540 pSMB->DataOffset = cpu_to_le16(offset);
5541 pSMB->SetupCount = 1;
5542 pSMB->Reserved3 = 0;
5543 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
5544 byte_count = 3 /* pad */ + params + data_count;
5545 pSMB->DataCount = cpu_to_le16(data_count);
5546 pSMB->TotalDataCount = pSMB->DataCount;
5547 pSMB->ParameterCount = cpu_to_le16(params);
5548 pSMB->TotalParameterCount = pSMB->ParameterCount;
5549 pSMB->Reserved4 = 0;
5550 inc_rfc1001_len(pSMB, byte_count);
5551 parm_data->FileSize = cpu_to_le64(size);
5552 pSMB->ByteCount = cpu_to_le16(byte_count);
5553 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5554 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5556 cifs_dbg(FYI, "SetPathInfo (file size) returned %d\n", rc);
5558 cifs_buf_release(pSMB);
5567 CIFSSMBSetFileSize(const unsigned int xid, struct cifs_tcon *tcon,
5568 struct cifsFileInfo *cfile, __u64 size, bool set_allocation)
5570 struct smb_com_transaction2_sfi_req *pSMB = NULL;
5571 struct file_end_of_file_info *parm_data;
5573 __u16 params, param_offset, offset, byte_count, count;
5575 cifs_dbg(FYI, "SetFileSize (via SetFileInfo) %lld\n",
5577 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
5582 pSMB->hdr.Pid = cpu_to_le16((__u16)cfile->pid);
5583 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(cfile->pid >> 16));
5586 pSMB->MaxSetupCount = 0;
5590 pSMB->Reserved2 = 0;
5591 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
5592 offset = param_offset + params;
5594 count = sizeof(struct file_end_of_file_info);
5595 pSMB->MaxParameterCount = cpu_to_le16(2);
5596 /* BB find exact max SMB PDU from sess structure BB */
5597 pSMB->MaxDataCount = cpu_to_le16(1000);
5598 pSMB->SetupCount = 1;
5599 pSMB->Reserved3 = 0;
5600 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
5601 byte_count = 3 /* pad */ + params + count;
5602 pSMB->DataCount = cpu_to_le16(count);
5603 pSMB->ParameterCount = cpu_to_le16(params);
5604 pSMB->TotalDataCount = pSMB->DataCount;
5605 pSMB->TotalParameterCount = pSMB->ParameterCount;
5606 pSMB->ParameterOffset = cpu_to_le16(param_offset);
5608 (struct file_end_of_file_info *) (((char *) &pSMB->hdr.Protocol)
5610 pSMB->DataOffset = cpu_to_le16(offset);
5611 parm_data->FileSize = cpu_to_le64(size);
5612 pSMB->Fid = cfile->fid.netfid;
5613 if (set_allocation) {
5614 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
5615 pSMB->InformationLevel =
5616 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2);
5618 pSMB->InformationLevel =
5619 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO);
5620 } else /* Set File Size */ {
5621 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
5622 pSMB->InformationLevel =
5623 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO2);
5625 pSMB->InformationLevel =
5626 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO);
5628 pSMB->Reserved4 = 0;
5629 inc_rfc1001_len(pSMB, byte_count);
5630 pSMB->ByteCount = cpu_to_le16(byte_count);
5631 rc = SendReceiveNoRsp(xid, tcon->ses, (char *) pSMB, 0);
5632 cifs_small_buf_release(pSMB);
5634 cifs_dbg(FYI, "Send error in SetFileInfo (SetFileSize) = %d\n",
5638 /* Note: On -EAGAIN error only caller can retry on handle based calls
5639 since file handle passed in no longer valid */
5644 /* Some legacy servers such as NT4 require that the file times be set on
5645 an open handle, rather than by pathname - this is awkward due to
5646 potential access conflicts on the open, but it is unavoidable for these
5647 old servers since the only other choice is to go from 100 nanosecond DCE
5648 time and resort to the original setpathinfo level which takes the ancient
5649 DOS time format with 2 second granularity */
5651 CIFSSMBSetFileInfo(const unsigned int xid, struct cifs_tcon *tcon,
5652 const FILE_BASIC_INFO *data, __u16 fid, __u32 pid_of_opener)
5654 struct smb_com_transaction2_sfi_req *pSMB = NULL;
5657 __u16 params, param_offset, offset, byte_count, count;
5659 cifs_dbg(FYI, "Set Times (via SetFileInfo)\n");
5660 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
5665 pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
5666 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));
5669 pSMB->MaxSetupCount = 0;
5673 pSMB->Reserved2 = 0;
5674 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
5675 offset = param_offset + params;
5677 data_offset = (char *)pSMB +
5678 offsetof(struct smb_hdr, Protocol) + offset;
5680 count = sizeof(FILE_BASIC_INFO);
5681 pSMB->MaxParameterCount = cpu_to_le16(2);
5682 /* BB find max SMB PDU from sess */
5683 pSMB->MaxDataCount = cpu_to_le16(1000);
5684 pSMB->SetupCount = 1;
5685 pSMB->Reserved3 = 0;
5686 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
5687 byte_count = 3 /* pad */ + params + count;
5688 pSMB->DataCount = cpu_to_le16(count);
5689 pSMB->ParameterCount = cpu_to_le16(params);
5690 pSMB->TotalDataCount = pSMB->DataCount;
5691 pSMB->TotalParameterCount = pSMB->ParameterCount;
5692 pSMB->ParameterOffset = cpu_to_le16(param_offset);
5693 pSMB->DataOffset = cpu_to_le16(offset);
5695 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
5696 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO2);
5698 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO);
5699 pSMB->Reserved4 = 0;
5700 inc_rfc1001_len(pSMB, byte_count);
5701 pSMB->ByteCount = cpu_to_le16(byte_count);
5702 memcpy(data_offset, data, sizeof(FILE_BASIC_INFO));
5703 rc = SendReceiveNoRsp(xid, tcon->ses, (char *) pSMB, 0);
5704 cifs_small_buf_release(pSMB);
5706 cifs_dbg(FYI, "Send error in Set Time (SetFileInfo) = %d\n",
5709 /* Note: On -EAGAIN error only caller can retry on handle based calls
5710 since file handle passed in no longer valid */
5716 CIFSSMBSetFileDisposition(const unsigned int xid, struct cifs_tcon *tcon,
5717 bool delete_file, __u16 fid, __u32 pid_of_opener)
5719 struct smb_com_transaction2_sfi_req *pSMB = NULL;
5722 __u16 params, param_offset, offset, byte_count, count;
5724 cifs_dbg(FYI, "Set File Disposition (via SetFileInfo)\n");
5725 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
5730 pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
5731 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));
5734 pSMB->MaxSetupCount = 0;
5738 pSMB->Reserved2 = 0;
5739 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
5740 offset = param_offset + params;
5742 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
5745 pSMB->MaxParameterCount = cpu_to_le16(2);
5746 /* BB find max SMB PDU from sess */
5747 pSMB->MaxDataCount = cpu_to_le16(1000);
5748 pSMB->SetupCount = 1;
5749 pSMB->Reserved3 = 0;
5750 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
5751 byte_count = 3 /* pad */ + params + count;
5752 pSMB->DataCount = cpu_to_le16(count);
5753 pSMB->ParameterCount = cpu_to_le16(params);
5754 pSMB->TotalDataCount = pSMB->DataCount;
5755 pSMB->TotalParameterCount = pSMB->ParameterCount;
5756 pSMB->ParameterOffset = cpu_to_le16(param_offset);
5757 pSMB->DataOffset = cpu_to_le16(offset);
5759 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_DISPOSITION_INFO);
5760 pSMB->Reserved4 = 0;
5761 inc_rfc1001_len(pSMB, byte_count);
5762 pSMB->ByteCount = cpu_to_le16(byte_count);
5763 *data_offset = delete_file ? 1 : 0;
5764 rc = SendReceiveNoRsp(xid, tcon->ses, (char *) pSMB, 0);
5765 cifs_small_buf_release(pSMB);
5767 cifs_dbg(FYI, "Send error in SetFileDisposition = %d\n", rc);
5773 CIFSSMBSetPathInfo(const unsigned int xid, struct cifs_tcon *tcon,
5774 const char *fileName, const FILE_BASIC_INFO *data,
5775 const struct nls_table *nls_codepage, int remap)
5777 TRANSACTION2_SPI_REQ *pSMB = NULL;
5778 TRANSACTION2_SPI_RSP *pSMBr = NULL;
5781 int bytes_returned = 0;
5783 __u16 params, param_offset, offset, byte_count, count;
5785 cifs_dbg(FYI, "In SetTimes\n");
5788 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5793 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5795 cifsConvertToUTF16((__le16 *) pSMB->FileName, fileName,
5796 PATH_MAX, nls_codepage, remap);
5797 name_len++; /* trailing null */
5799 } else { /* BB improve the check for buffer overruns BB */
5800 name_len = strnlen(fileName, PATH_MAX);
5801 name_len++; /* trailing null */
5802 strncpy(pSMB->FileName, fileName, name_len);
5805 params = 6 + name_len;
5806 count = sizeof(FILE_BASIC_INFO);
5807 pSMB->MaxParameterCount = cpu_to_le16(2);
5808 /* BB find max SMB PDU from sess structure BB */
5809 pSMB->MaxDataCount = cpu_to_le16(1000);
5810 pSMB->MaxSetupCount = 0;
5814 pSMB->Reserved2 = 0;
5815 param_offset = offsetof(struct smb_com_transaction2_spi_req,
5816 InformationLevel) - 4;
5817 offset = param_offset + params;
5818 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
5819 pSMB->ParameterOffset = cpu_to_le16(param_offset);
5820 pSMB->DataOffset = cpu_to_le16(offset);
5821 pSMB->SetupCount = 1;
5822 pSMB->Reserved3 = 0;
5823 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
5824 byte_count = 3 /* pad */ + params + count;
5826 pSMB->DataCount = cpu_to_le16(count);
5827 pSMB->ParameterCount = cpu_to_le16(params);
5828 pSMB->TotalDataCount = pSMB->DataCount;
5829 pSMB->TotalParameterCount = pSMB->ParameterCount;
5830 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
5831 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO2);
5833 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO);
5834 pSMB->Reserved4 = 0;
5835 inc_rfc1001_len(pSMB, byte_count);
5836 memcpy(data_offset, data, sizeof(FILE_BASIC_INFO));
5837 pSMB->ByteCount = cpu_to_le16(byte_count);
5838 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5839 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5841 cifs_dbg(FYI, "SetPathInfo (times) returned %d\n", rc);
5843 cifs_buf_release(pSMB);
5851 /* Can not be used to set time stamps yet (due to old DOS time format) */
5852 /* Can be used to set attributes */
5853 #if 0 /* Possibly not needed - since it turns out that strangely NT4 has a bug
5854 handling it anyway and NT4 was what we thought it would be needed for
5855 Do not delete it until we prove whether needed for Win9x though */
5857 CIFSSMBSetAttrLegacy(unsigned int xid, struct cifs_tcon *tcon, char *fileName,
5858 __u16 dos_attrs, const struct nls_table *nls_codepage)
5860 SETATTR_REQ *pSMB = NULL;
5861 SETATTR_RSP *pSMBr = NULL;
5866 cifs_dbg(FYI, "In SetAttrLegacy\n");
5869 rc = smb_init(SMB_COM_SETATTR, 8, tcon, (void **) &pSMB,
5874 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5876 ConvertToUTF16((__le16 *) pSMB->fileName, fileName,
5877 PATH_MAX, nls_codepage);
5878 name_len++; /* trailing null */
5880 } else { /* BB improve the check for buffer overruns BB */
5881 name_len = strnlen(fileName, PATH_MAX);
5882 name_len++; /* trailing null */
5883 strncpy(pSMB->fileName, fileName, name_len);
5885 pSMB->attr = cpu_to_le16(dos_attrs);
5886 pSMB->BufferFormat = 0x04;
5887 inc_rfc1001_len(pSMB, name_len + 1);
5888 pSMB->ByteCount = cpu_to_le16(name_len + 1);
5889 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5890 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5892 cifs_dbg(FYI, "Error in LegacySetAttr = %d\n", rc);
5894 cifs_buf_release(pSMB);
5897 goto SetAttrLgcyRetry;
5901 #endif /* temporarily unneeded SetAttr legacy function */
5904 cifs_fill_unix_set_info(FILE_UNIX_BASIC_INFO *data_offset,
5905 const struct cifs_unix_set_info_args *args)
5907 u64 uid = NO_CHANGE_64, gid = NO_CHANGE_64;
5908 u64 mode = args->mode;
5910 if (uid_valid(args->uid))
5911 uid = from_kuid(&init_user_ns, args->uid);
5912 if (gid_valid(args->gid))
5913 gid = from_kgid(&init_user_ns, args->gid);
5916 * Samba server ignores set of file size to zero due to bugs in some
5917 * older clients, but we should be precise - we use SetFileSize to
5918 * set file size and do not want to truncate file size to zero
5919 * accidentally as happened on one Samba server beta by putting
5920 * zero instead of -1 here
5922 data_offset->EndOfFile = cpu_to_le64(NO_CHANGE_64);
5923 data_offset->NumOfBytes = cpu_to_le64(NO_CHANGE_64);
5924 data_offset->LastStatusChange = cpu_to_le64(args->ctime);
5925 data_offset->LastAccessTime = cpu_to_le64(args->atime);
5926 data_offset->LastModificationTime = cpu_to_le64(args->mtime);
5927 data_offset->Uid = cpu_to_le64(uid);
5928 data_offset->Gid = cpu_to_le64(gid);
5929 /* better to leave device as zero when it is */
5930 data_offset->DevMajor = cpu_to_le64(MAJOR(args->device));
5931 data_offset->DevMinor = cpu_to_le64(MINOR(args->device));
5932 data_offset->Permissions = cpu_to_le64(mode);
5935 data_offset->Type = cpu_to_le32(UNIX_FILE);
5936 else if (S_ISDIR(mode))
5937 data_offset->Type = cpu_to_le32(UNIX_DIR);
5938 else if (S_ISLNK(mode))
5939 data_offset->Type = cpu_to_le32(UNIX_SYMLINK);
5940 else if (S_ISCHR(mode))
5941 data_offset->Type = cpu_to_le32(UNIX_CHARDEV);
5942 else if (S_ISBLK(mode))
5943 data_offset->Type = cpu_to_le32(UNIX_BLOCKDEV);
5944 else if (S_ISFIFO(mode))
5945 data_offset->Type = cpu_to_le32(UNIX_FIFO);
5946 else if (S_ISSOCK(mode))
5947 data_offset->Type = cpu_to_le32(UNIX_SOCKET);
5951 CIFSSMBUnixSetFileInfo(const unsigned int xid, struct cifs_tcon *tcon,
5952 const struct cifs_unix_set_info_args *args,
5953 u16 fid, u32 pid_of_opener)
5955 struct smb_com_transaction2_sfi_req *pSMB = NULL;
5958 u16 params, param_offset, offset, byte_count, count;
5960 cifs_dbg(FYI, "Set Unix Info (via SetFileInfo)\n");
5961 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
5966 pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
5967 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));
5970 pSMB->MaxSetupCount = 0;
5974 pSMB->Reserved2 = 0;
5975 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
5976 offset = param_offset + params;
5978 data_offset = (char *)pSMB +
5979 offsetof(struct smb_hdr, Protocol) + offset;
5981 count = sizeof(FILE_UNIX_BASIC_INFO);
5983 pSMB->MaxParameterCount = cpu_to_le16(2);
5984 /* BB find max SMB PDU from sess */
5985 pSMB->MaxDataCount = cpu_to_le16(1000);
5986 pSMB->SetupCount = 1;
5987 pSMB->Reserved3 = 0;
5988 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
5989 byte_count = 3 /* pad */ + params + count;
5990 pSMB->DataCount = cpu_to_le16(count);
5991 pSMB->ParameterCount = cpu_to_le16(params);
5992 pSMB->TotalDataCount = pSMB->DataCount;
5993 pSMB->TotalParameterCount = pSMB->ParameterCount;
5994 pSMB->ParameterOffset = cpu_to_le16(param_offset);
5995 pSMB->DataOffset = cpu_to_le16(offset);
5997 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_BASIC);
5998 pSMB->Reserved4 = 0;
5999 inc_rfc1001_len(pSMB, byte_count);
6000 pSMB->ByteCount = cpu_to_le16(byte_count);
6002 cifs_fill_unix_set_info((FILE_UNIX_BASIC_INFO *)data_offset, args);
6004 rc = SendReceiveNoRsp(xid, tcon->ses, (char *) pSMB, 0);
6005 cifs_small_buf_release(pSMB);
6007 cifs_dbg(FYI, "Send error in Set Time (SetFileInfo) = %d\n",
6010 /* Note: On -EAGAIN error only caller can retry on handle based calls
6011 since file handle passed in no longer valid */
6017 CIFSSMBUnixSetPathInfo(const unsigned int xid, struct cifs_tcon *tcon,
6018 const char *file_name,
6019 const struct cifs_unix_set_info_args *args,
6020 const struct nls_table *nls_codepage, int remap)
6022 TRANSACTION2_SPI_REQ *pSMB = NULL;
6023 TRANSACTION2_SPI_RSP *pSMBr = NULL;
6026 int bytes_returned = 0;
6027 FILE_UNIX_BASIC_INFO *data_offset;
6028 __u16 params, param_offset, offset, count, byte_count;
6030 cifs_dbg(FYI, "In SetUID/GID/Mode\n");
6032 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
6037 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
6039 cifsConvertToUTF16((__le16 *) pSMB->FileName, file_name,
6040 PATH_MAX, nls_codepage, remap);
6041 name_len++; /* trailing null */
6043 } else { /* BB improve the check for buffer overruns BB */
6044 name_len = strnlen(file_name, PATH_MAX);
6045 name_len++; /* trailing null */
6046 strncpy(pSMB->FileName, file_name, name_len);
6049 params = 6 + name_len;
6050 count = sizeof(FILE_UNIX_BASIC_INFO);
6051 pSMB->MaxParameterCount = cpu_to_le16(2);
6052 /* BB find max SMB PDU from sess structure BB */
6053 pSMB->MaxDataCount = cpu_to_le16(1000);
6054 pSMB->MaxSetupCount = 0;
6058 pSMB->Reserved2 = 0;
6059 param_offset = offsetof(struct smb_com_transaction2_spi_req,
6060 InformationLevel) - 4;
6061 offset = param_offset + params;
6063 (FILE_UNIX_BASIC_INFO *) ((char *) &pSMB->hdr.Protocol +
6065 memset(data_offset, 0, count);
6066 pSMB->DataOffset = cpu_to_le16(offset);
6067 pSMB->ParameterOffset = cpu_to_le16(param_offset);
6068 pSMB->SetupCount = 1;
6069 pSMB->Reserved3 = 0;
6070 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
6071 byte_count = 3 /* pad */ + params + count;
6072 pSMB->ParameterCount = cpu_to_le16(params);
6073 pSMB->DataCount = cpu_to_le16(count);
6074 pSMB->TotalParameterCount = pSMB->ParameterCount;
6075 pSMB->TotalDataCount = pSMB->DataCount;
6076 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_BASIC);
6077 pSMB->Reserved4 = 0;
6078 inc_rfc1001_len(pSMB, byte_count);
6080 cifs_fill_unix_set_info(data_offset, args);
6082 pSMB->ByteCount = cpu_to_le16(byte_count);
6083 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
6084 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
6086 cifs_dbg(FYI, "SetPathInfo (perms) returned %d\n", rc);
6088 cifs_buf_release(pSMB);
6094 #ifdef CONFIG_CIFS_XATTR
6096 * Do a path-based QUERY_ALL_EAS call and parse the result. This is a common
6097 * function used by listxattr and getxattr type calls. When ea_name is set,
6098 * it looks for that attribute name and stuffs that value into the EAData
6099 * buffer. When ea_name is NULL, it stuffs a list of attribute names into the
6100 * buffer. In both cases, the return value is either the length of the
6101 * resulting data or a negative error code. If EAData is a NULL pointer then
6102 * the data isn't copied to it, but the length is returned.
6105 CIFSSMBQAllEAs(const unsigned int xid, struct cifs_tcon *tcon,
6106 const unsigned char *searchName, const unsigned char *ea_name,
6107 char *EAData, size_t buf_size,
6108 struct cifs_sb_info *cifs_sb)
6110 /* BB assumes one setup word */
6111 TRANSACTION2_QPI_REQ *pSMB = NULL;
6112 TRANSACTION2_QPI_RSP *pSMBr = NULL;
6113 int remap = cifs_remap(cifs_sb);
6114 struct nls_table *nls_codepage = cifs_sb->local_nls;
6118 struct fealist *ea_response_data;
6119 struct fea *temp_fea;
6122 __u16 params, byte_count, data_offset;
6123 unsigned int ea_name_len = ea_name ? strlen(ea_name) : 0;
6125 cifs_dbg(FYI, "In Query All EAs path %s\n", searchName);
6127 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
6132 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
6134 cifsConvertToUTF16((__le16 *) pSMB->FileName, searchName,
6135 PATH_MAX, nls_codepage, remap);
6136 list_len++; /* trailing null */
6138 } else { /* BB improve the check for buffer overruns BB */
6139 list_len = strnlen(searchName, PATH_MAX);
6140 list_len++; /* trailing null */
6141 strncpy(pSMB->FileName, searchName, list_len);
6144 params = 2 /* level */ + 4 /* reserved */ + list_len /* includes NUL */;
6145 pSMB->TotalDataCount = 0;
6146 pSMB->MaxParameterCount = cpu_to_le16(2);
6147 /* BB find exact max SMB PDU from sess structure BB */
6148 pSMB->MaxDataCount = cpu_to_le16(CIFSMaxBufSize);
6149 pSMB->MaxSetupCount = 0;
6153 pSMB->Reserved2 = 0;
6154 pSMB->ParameterOffset = cpu_to_le16(offsetof(
6155 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
6156 pSMB->DataCount = 0;
6157 pSMB->DataOffset = 0;
6158 pSMB->SetupCount = 1;
6159 pSMB->Reserved3 = 0;
6160 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
6161 byte_count = params + 1 /* pad */ ;
6162 pSMB->TotalParameterCount = cpu_to_le16(params);
6163 pSMB->ParameterCount = pSMB->TotalParameterCount;
6164 pSMB->InformationLevel = cpu_to_le16(SMB_INFO_QUERY_ALL_EAS);
6165 pSMB->Reserved4 = 0;
6166 inc_rfc1001_len(pSMB, byte_count);
6167 pSMB->ByteCount = cpu_to_le16(byte_count);
6169 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
6170 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
6172 cifs_dbg(FYI, "Send error in QueryAllEAs = %d\n", rc);
6177 /* BB also check enough total bytes returned */
6178 /* BB we need to improve the validity checking
6179 of these trans2 responses */
6181 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
6182 if (rc || get_bcc(&pSMBr->hdr) < 4) {
6183 rc = -EIO; /* bad smb */
6187 /* check that length of list is not more than bcc */
6188 /* check that each entry does not go beyond length
6190 /* check that each element of each entry does not
6191 go beyond end of list */
6192 /* validate_trans2_offsets() */
6193 /* BB check if start of smb + data_offset > &bcc+ bcc */
6195 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
6196 ea_response_data = (struct fealist *)
6197 (((char *) &pSMBr->hdr.Protocol) + data_offset);
6199 list_len = le32_to_cpu(ea_response_data->list_len);
6200 cifs_dbg(FYI, "ea length %d\n", list_len);
6201 if (list_len <= 8) {
6202 cifs_dbg(FYI, "empty EA list returned from server\n");
6203 /* didn't find the named attribute */
6209 /* make sure list_len doesn't go past end of SMB */
6210 end_of_smb = (char *)pByteArea(&pSMBr->hdr) + get_bcc(&pSMBr->hdr);
6211 if ((char *)ea_response_data + list_len > end_of_smb) {
6212 cifs_dbg(FYI, "EA list appears to go beyond SMB\n");
6217 /* account for ea list len */
6219 temp_fea = ea_response_data->list;
6220 temp_ptr = (char *)temp_fea;
6221 while (list_len > 0) {
6222 unsigned int name_len;
6227 /* make sure we can read name_len and value_len */
6229 cifs_dbg(FYI, "EA entry goes beyond length of list\n");
6234 name_len = temp_fea->name_len;
6235 value_len = le16_to_cpu(temp_fea->value_len);
6236 list_len -= name_len + 1 + value_len;
6238 cifs_dbg(FYI, "EA entry goes beyond length of list\n");
6244 if (ea_name_len == name_len &&
6245 memcmp(ea_name, temp_ptr, name_len) == 0) {
6246 temp_ptr += name_len + 1;
6250 if ((size_t)value_len > buf_size) {
6254 memcpy(EAData, temp_ptr, value_len);
6258 /* account for prefix user. and trailing null */
6259 rc += (5 + 1 + name_len);
6260 if (rc < (int) buf_size) {
6261 memcpy(EAData, "user.", 5);
6263 memcpy(EAData, temp_ptr, name_len);
6265 /* null terminate name */
6268 } else if (buf_size == 0) {
6269 /* skip copy - calc size only */
6271 /* stop before overrun buffer */
6276 temp_ptr += name_len + 1 + value_len;
6277 temp_fea = (struct fea *)temp_ptr;
6280 /* didn't find the named attribute */
6285 cifs_buf_release(pSMB);
6293 CIFSSMBSetEA(const unsigned int xid, struct cifs_tcon *tcon,
6294 const char *fileName, const char *ea_name, const void *ea_value,
6295 const __u16 ea_value_len, const struct nls_table *nls_codepage,
6296 struct cifs_sb_info *cifs_sb)
6298 struct smb_com_transaction2_spi_req *pSMB = NULL;
6299 struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
6300 struct fealist *parm_data;
6303 int bytes_returned = 0;
6304 __u16 params, param_offset, byte_count, offset, count;
6305 int remap = cifs_remap(cifs_sb);
6307 cifs_dbg(FYI, "In SetEA\n");
6309 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
6314 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
6316 cifsConvertToUTF16((__le16 *) pSMB->FileName, fileName,
6317 PATH_MAX, nls_codepage, remap);
6318 name_len++; /* trailing null */
6320 } else { /* BB improve the check for buffer overruns BB */
6321 name_len = strnlen(fileName, PATH_MAX);
6322 name_len++; /* trailing null */
6323 strncpy(pSMB->FileName, fileName, name_len);
6326 params = 6 + name_len;
6328 /* done calculating parms using name_len of file name,
6329 now use name_len to calculate length of ea name
6330 we are going to create in the inode xattrs */
6331 if (ea_name == NULL)
6334 name_len = strnlen(ea_name, 255);
6336 count = sizeof(*parm_data) + ea_value_len + name_len;
6337 pSMB->MaxParameterCount = cpu_to_le16(2);
6338 /* BB find max SMB PDU from sess */
6339 pSMB->MaxDataCount = cpu_to_le16(1000);
6340 pSMB->MaxSetupCount = 0;
6344 pSMB->Reserved2 = 0;
6345 param_offset = offsetof(struct smb_com_transaction2_spi_req,
6346 InformationLevel) - 4;
6347 offset = param_offset + params;
6348 pSMB->InformationLevel =
6349 cpu_to_le16(SMB_SET_FILE_EA);
6351 parm_data = (void *)pSMB + offsetof(struct smb_hdr, Protocol) + offset;
6352 pSMB->ParameterOffset = cpu_to_le16(param_offset);
6353 pSMB->DataOffset = cpu_to_le16(offset);
6354 pSMB->SetupCount = 1;
6355 pSMB->Reserved3 = 0;
6356 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
6357 byte_count = 3 /* pad */ + params + count;
6358 pSMB->DataCount = cpu_to_le16(count);
6359 parm_data->list_len = cpu_to_le32(count);
6360 parm_data->list[0].EA_flags = 0;
6361 /* we checked above that name len is less than 255 */
6362 parm_data->list[0].name_len = (__u8)name_len;
6363 /* EA names are always ASCII */
6365 strncpy(parm_data->list[0].name, ea_name, name_len);
6366 parm_data->list[0].name[name_len] = 0;
6367 parm_data->list[0].value_len = cpu_to_le16(ea_value_len);
6368 /* caller ensures that ea_value_len is less than 64K but
6369 we need to ensure that it fits within the smb */
6371 /*BB add length check to see if it would fit in
6372 negotiated SMB buffer size BB */
6373 /* if (ea_value_len > buffer_size - 512 (enough for header)) */
6375 memcpy(parm_data->list[0].name+name_len+1,
6376 ea_value, ea_value_len);
6378 pSMB->TotalDataCount = pSMB->DataCount;
6379 pSMB->ParameterCount = cpu_to_le16(params);
6380 pSMB->TotalParameterCount = pSMB->ParameterCount;
6381 pSMB->Reserved4 = 0;
6382 inc_rfc1001_len(pSMB, byte_count);
6383 pSMB->ByteCount = cpu_to_le16(byte_count);
6384 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
6385 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
6387 cifs_dbg(FYI, "SetPathInfo (EA) returned %d\n", rc);
6389 cifs_buf_release(pSMB);
6398 #ifdef CONFIG_CIFS_DNOTIFY_EXPERIMENTAL /* BB unused temporarily */
6400 * Years ago the kernel added a "dnotify" function for Samba server,
6401 * to allow network clients (such as Windows) to display updated
6402 * lists of files in directory listings automatically when
6403 * files are added by one user when another user has the
6404 * same directory open on their desktop. The Linux cifs kernel
6405 * client hooked into the kernel side of this interface for
6406 * the same reason, but ironically when the VFS moved from
6407 * "dnotify" to "inotify" it became harder to plug in Linux
6408 * network file system clients (the most obvious use case
6409 * for notify interfaces is when multiple users can update
6410 * the contents of the same directory - exactly what network
6411 * file systems can do) although the server (Samba) could
6412 * still use it. For the short term we leave the worker
6413 * function ifdeffed out (below) until inotify is fixed
6414 * in the VFS to make it easier to plug in network file
6415 * system clients. If inotify turns out to be permanently
6416 * incompatible for network fs clients, we could instead simply
6417 * expose this config flag by adding a future cifs (and smb2) notify ioctl.
6419 int CIFSSMBNotify(const unsigned int xid, struct cifs_tcon *tcon,
6420 const int notify_subdirs, const __u16 netfid,
6421 __u32 filter, struct file *pfile, int multishot,
6422 const struct nls_table *nls_codepage)
6425 struct smb_com_transaction_change_notify_req *pSMB = NULL;
6426 struct smb_com_ntransaction_change_notify_rsp *pSMBr = NULL;
6427 struct dir_notify_req *dnotify_req;
6430 cifs_dbg(FYI, "In CIFSSMBNotify for file handle %d\n", (int)netfid);
6431 rc = smb_init(SMB_COM_NT_TRANSACT, 23, tcon, (void **) &pSMB,
6436 pSMB->TotalParameterCount = 0 ;
6437 pSMB->TotalDataCount = 0;
6438 pSMB->MaxParameterCount = cpu_to_le32(2);
6439 pSMB->MaxDataCount = cpu_to_le32(CIFSMaxBufSize & 0xFFFFFF00);
6440 pSMB->MaxSetupCount = 4;
6442 pSMB->ParameterOffset = 0;
6443 pSMB->DataCount = 0;
6444 pSMB->DataOffset = 0;
6445 pSMB->SetupCount = 4; /* single byte does not need le conversion */
6446 pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_NOTIFY_CHANGE);
6447 pSMB->ParameterCount = pSMB->TotalParameterCount;
6449 pSMB->WatchTree = 1; /* one byte - no le conversion needed */
6450 pSMB->Reserved2 = 0;
6451 pSMB->CompletionFilter = cpu_to_le32(filter);
6452 pSMB->Fid = netfid; /* file handle always le */
6453 pSMB->ByteCount = 0;
6455 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
6456 (struct smb_hdr *)pSMBr, &bytes_returned,
6459 cifs_dbg(FYI, "Error in Notify = %d\n", rc);
6461 /* Add file to outstanding requests */
6462 /* BB change to kmem cache alloc */
6463 dnotify_req = kmalloc(
6464 sizeof(struct dir_notify_req),
6467 dnotify_req->Pid = pSMB->hdr.Pid;
6468 dnotify_req->PidHigh = pSMB->hdr.PidHigh;
6469 dnotify_req->Mid = pSMB->hdr.Mid;
6470 dnotify_req->Tid = pSMB->hdr.Tid;
6471 dnotify_req->Uid = pSMB->hdr.Uid;
6472 dnotify_req->netfid = netfid;
6473 dnotify_req->pfile = pfile;
6474 dnotify_req->filter = filter;
6475 dnotify_req->multishot = multishot;
6476 spin_lock(&GlobalMid_Lock);
6477 list_add_tail(&dnotify_req->lhead,
6478 &GlobalDnotifyReqList);
6479 spin_unlock(&GlobalMid_Lock);
6483 cifs_buf_release(pSMB);
6486 #endif /* was needed for dnotify, and will be needed for inotify when VFS fix */