4 * Copyright (C) International Business Machines Corp., 2002,2010
5 * Author(s): Steve French (sfrench@us.ibm.com)
7 * Contains the routines for constructing the SMB PDUs themselves
9 * This library is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU Lesser General Public License as published
11 * by the Free Software Foundation; either version 2.1 of the License, or
12 * (at your option) any later version.
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
17 * the GNU Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public License
20 * along with this library; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 /* SMB/CIFS PDU handling routines here - except for leftovers in connect.c */
25 /* These are mostly routines that operate on a pathname, or on a tree id */
26 /* (mounted volume), but there are eight handle based routines which must be */
27 /* treated slightly differently for reconnection purposes since we never */
28 /* want to reuse a stale file handle and only the caller knows the file info */
31 #include <linux/kernel.h>
32 #include <linux/vfs.h>
33 #include <linux/slab.h>
34 #include <linux/posix_acl_xattr.h>
35 #include <linux/pagemap.h>
36 #include <linux/swap.h>
37 #include <linux/task_io_accounting_ops.h>
38 #include <linux/uaccess.h>
42 #include "cifsproto.h"
43 #include "cifs_unicode.h"
44 #include "cifs_debug.h"
47 #ifdef CONFIG_CIFS_POSIX
52 #ifdef CONFIG_CIFS_WEAK_PW_HASH
53 {LANMAN_PROT, "\2LM1.2X002"},
54 {LANMAN2_PROT, "\2LANMAN2.1"},
55 #endif /* weak password hashing for legacy clients */
56 {CIFS_PROT, "\2NT LM 0.12"},
57 {POSIX_PROT, "\2POSIX 2"},
65 #ifdef CONFIG_CIFS_WEAK_PW_HASH
66 {LANMAN_PROT, "\2LM1.2X002"},
67 {LANMAN2_PROT, "\2LANMAN2.1"},
68 #endif /* weak password hashing for legacy clients */
69 {CIFS_PROT, "\2NT LM 0.12"},
74 /* define the number of elements in the cifs dialect array */
75 #ifdef CONFIG_CIFS_POSIX
76 #ifdef CONFIG_CIFS_WEAK_PW_HASH
77 #define CIFS_NUM_PROT 4
79 #define CIFS_NUM_PROT 2
80 #endif /* CIFS_WEAK_PW_HASH */
82 #ifdef CONFIG_CIFS_WEAK_PW_HASH
83 #define CIFS_NUM_PROT 3
85 #define CIFS_NUM_PROT 1
86 #endif /* CONFIG_CIFS_WEAK_PW_HASH */
87 #endif /* CIFS_POSIX */
90 * Mark as invalid, all open files on tree connections since they
91 * were closed when session to server was lost.
94 cifs_mark_open_files_invalid(struct cifs_tcon *tcon)
96 struct cifsFileInfo *open_file = NULL;
97 struct list_head *tmp;
98 struct list_head *tmp1;
100 /* list all files open on tree connection and mark them invalid */
101 spin_lock(&tcon->open_file_lock);
102 list_for_each_safe(tmp, tmp1, &tcon->openFileList) {
103 open_file = list_entry(tmp, struct cifsFileInfo, tlist);
104 open_file->invalidHandle = true;
105 open_file->oplock_break_cancelled = true;
107 spin_unlock(&tcon->open_file_lock);
109 * BB Add call to invalidate_inodes(sb) for all superblocks mounted
114 /* reconnect the socket, tcon, and smb session if needed */
116 cifs_reconnect_tcon(struct cifs_tcon *tcon, int smb_command)
119 struct cifs_ses *ses;
120 struct TCP_Server_Info *server;
121 struct nls_table *nls_codepage;
124 * SMBs NegProt, SessSetup, uLogoff do not have tcon yet so check for
125 * tcp and smb session status done differently for those three - in the
132 server = ses->server;
135 * only tree disconnect, open, and write, (and ulogoff which does not
136 * have tcon) are allowed as we start force umount
138 if (tcon->tidStatus == CifsExiting) {
139 if (smb_command != SMB_COM_WRITE_ANDX &&
140 smb_command != SMB_COM_OPEN_ANDX &&
141 smb_command != SMB_COM_TREE_DISCONNECT) {
142 cifs_dbg(FYI, "can not send cmd %d while umounting\n",
149 * Give demultiplex thread up to 10 seconds to reconnect, should be
150 * greater than cifs socket timeout which is 7 seconds
152 while (server->tcpStatus == CifsNeedReconnect) {
153 rc = wait_event_interruptible_timeout(server->response_q,
154 (server->tcpStatus != CifsNeedReconnect),
157 cifs_dbg(FYI, "%s: aborting reconnect due to a received"
158 " signal by the process\n", __func__);
162 /* are we still trying to reconnect? */
163 if (server->tcpStatus != CifsNeedReconnect)
167 * on "soft" mounts we wait once. Hard mounts keep
168 * retrying until process is killed or server comes
172 cifs_dbg(FYI, "gave up waiting on reconnect in smb_init\n");
177 if (!ses->need_reconnect && !tcon->need_reconnect)
180 nls_codepage = load_nls_default();
183 * need to prevent multiple threads trying to simultaneously
184 * reconnect the same SMB session
186 mutex_lock(&ses->session_mutex);
189 * Recheck after acquire mutex. If another thread is negotiating
190 * and the server never sends an answer the socket will be closed
191 * and tcpStatus set to reconnect.
193 if (server->tcpStatus == CifsNeedReconnect) {
195 mutex_unlock(&ses->session_mutex);
199 rc = cifs_negotiate_protocol(0, ses);
200 if (rc == 0 && ses->need_reconnect)
201 rc = cifs_setup_session(0, ses, nls_codepage);
203 /* do we need to reconnect tcon? */
204 if (rc || !tcon->need_reconnect) {
205 mutex_unlock(&ses->session_mutex);
209 cifs_mark_open_files_invalid(tcon);
210 rc = CIFSTCon(0, ses, tcon->treeName, tcon, nls_codepage);
211 mutex_unlock(&ses->session_mutex);
212 cifs_dbg(FYI, "reconnect tcon rc = %d\n", rc);
217 atomic_inc(&tconInfoReconnectCount);
219 /* tell server Unix caps we support */
220 if (ses->capabilities & CAP_UNIX)
221 reset_cifs_unix_caps(0, tcon, NULL, NULL);
224 * Removed call to reopen open files here. It is safer (and faster) to
225 * reopen files one at a time as needed in read and write.
227 * FIXME: what about file locks? don't we need to reclaim them ASAP?
232 * Check if handle based operation so we know whether we can continue
233 * or not without returning to caller to reset file handle
235 switch (smb_command) {
236 case SMB_COM_READ_ANDX:
237 case SMB_COM_WRITE_ANDX:
239 case SMB_COM_FIND_CLOSE2:
240 case SMB_COM_LOCKING_ANDX:
244 unload_nls(nls_codepage);
248 /* Allocate and return pointer to an SMB request buffer, and set basic
249 SMB information in the SMB header. If the return code is zero, this
250 function must have filled in request_buf pointer */
252 small_smb_init(int smb_command, int wct, struct cifs_tcon *tcon,
257 rc = cifs_reconnect_tcon(tcon, smb_command);
261 *request_buf = cifs_small_buf_get();
262 if (*request_buf == NULL) {
263 /* BB should we add a retry in here if not a writepage? */
267 header_assemble((struct smb_hdr *) *request_buf, smb_command,
271 cifs_stats_inc(&tcon->num_smbs_sent);
277 small_smb_init_no_tc(const int smb_command, const int wct,
278 struct cifs_ses *ses, void **request_buf)
281 struct smb_hdr *buffer;
283 rc = small_smb_init(smb_command, wct, NULL, request_buf);
287 buffer = (struct smb_hdr *)*request_buf;
288 buffer->Mid = get_next_mid(ses->server);
289 if (ses->capabilities & CAP_UNICODE)
290 buffer->Flags2 |= SMBFLG2_UNICODE;
291 if (ses->capabilities & CAP_STATUS32)
292 buffer->Flags2 |= SMBFLG2_ERR_STATUS;
294 /* uid, tid can stay at zero as set in header assemble */
296 /* BB add support for turning on the signing when
297 this function is used after 1st of session setup requests */
302 /* If the return code is zero, this function must fill in request_buf pointer */
304 __smb_init(int smb_command, int wct, struct cifs_tcon *tcon,
305 void **request_buf, void **response_buf)
307 *request_buf = cifs_buf_get();
308 if (*request_buf == NULL) {
309 /* BB should we add a retry in here if not a writepage? */
312 /* Although the original thought was we needed the response buf for */
313 /* potential retries of smb operations it turns out we can determine */
314 /* from the mid flags when the request buffer can be resent without */
315 /* having to use a second distinct buffer for the response */
317 *response_buf = *request_buf;
319 header_assemble((struct smb_hdr *) *request_buf, smb_command, tcon,
323 cifs_stats_inc(&tcon->num_smbs_sent);
328 /* If the return code is zero, this function must fill in request_buf pointer */
330 smb_init(int smb_command, int wct, struct cifs_tcon *tcon,
331 void **request_buf, void **response_buf)
335 rc = cifs_reconnect_tcon(tcon, smb_command);
339 return __smb_init(smb_command, wct, tcon, request_buf, response_buf);
343 smb_init_no_reconnect(int smb_command, int wct, struct cifs_tcon *tcon,
344 void **request_buf, void **response_buf)
346 if (tcon->ses->need_reconnect || tcon->need_reconnect)
349 return __smb_init(smb_command, wct, tcon, request_buf, response_buf);
352 static int validate_t2(struct smb_t2_rsp *pSMB)
354 unsigned int total_size;
356 /* check for plausible wct */
357 if (pSMB->hdr.WordCount < 10)
360 /* check for parm and data offset going beyond end of smb */
361 if (get_unaligned_le16(&pSMB->t2_rsp.ParameterOffset) > 1024 ||
362 get_unaligned_le16(&pSMB->t2_rsp.DataOffset) > 1024)
365 total_size = get_unaligned_le16(&pSMB->t2_rsp.ParameterCount);
366 if (total_size >= 512)
369 /* check that bcc is at least as big as parms + data, and that it is
370 * less than negotiated smb buffer
372 total_size += get_unaligned_le16(&pSMB->t2_rsp.DataCount);
373 if (total_size > get_bcc(&pSMB->hdr) ||
374 total_size >= CIFSMaxBufSize + MAX_CIFS_HDR_SIZE)
379 cifs_dump_mem("Invalid transact2 SMB: ", (char *)pSMB,
380 sizeof(struct smb_t2_rsp) + 16);
385 decode_ext_sec_blob(struct cifs_ses *ses, NEGOTIATE_RSP *pSMBr)
389 char *guid = pSMBr->u.extended_response.GUID;
390 struct TCP_Server_Info *server = ses->server;
392 count = get_bcc(&pSMBr->hdr);
393 if (count < SMB1_CLIENT_GUID_SIZE)
396 spin_lock(&cifs_tcp_ses_lock);
397 if (server->srv_count > 1) {
398 spin_unlock(&cifs_tcp_ses_lock);
399 if (memcmp(server->server_GUID, guid, SMB1_CLIENT_GUID_SIZE) != 0) {
400 cifs_dbg(FYI, "server UID changed\n");
401 memcpy(server->server_GUID, guid, SMB1_CLIENT_GUID_SIZE);
404 spin_unlock(&cifs_tcp_ses_lock);
405 memcpy(server->server_GUID, guid, SMB1_CLIENT_GUID_SIZE);
408 if (count == SMB1_CLIENT_GUID_SIZE) {
409 server->sec_ntlmssp = true;
411 count -= SMB1_CLIENT_GUID_SIZE;
412 rc = decode_negTokenInit(
413 pSMBr->u.extended_response.SecurityBlob, count, server);
422 cifs_enable_signing(struct TCP_Server_Info *server, bool mnt_sign_required)
424 bool srv_sign_required = server->sec_mode & server->vals->signing_required;
425 bool srv_sign_enabled = server->sec_mode & server->vals->signing_enabled;
426 bool mnt_sign_enabled = global_secflags & CIFSSEC_MAY_SIGN;
429 * Is signing required by mnt options? If not then check
430 * global_secflags to see if it is there.
432 if (!mnt_sign_required)
433 mnt_sign_required = ((global_secflags & CIFSSEC_MUST_SIGN) ==
437 * If signing is required then it's automatically enabled too,
438 * otherwise, check to see if the secflags allow it.
440 mnt_sign_enabled = mnt_sign_required ? mnt_sign_required :
441 (global_secflags & CIFSSEC_MAY_SIGN);
443 /* If server requires signing, does client allow it? */
444 if (srv_sign_required) {
445 if (!mnt_sign_enabled) {
446 cifs_dbg(VFS, "Server requires signing, but it's disabled in SecurityFlags!");
452 /* If client requires signing, does server allow it? */
453 if (mnt_sign_required) {
454 if (!srv_sign_enabled) {
455 cifs_dbg(VFS, "Server does not support signing!");
464 #ifdef CONFIG_CIFS_WEAK_PW_HASH
466 decode_lanman_negprot_rsp(struct TCP_Server_Info *server, NEGOTIATE_RSP *pSMBr)
469 struct lanman_neg_rsp *rsp = (struct lanman_neg_rsp *)pSMBr;
471 if (server->dialect != LANMAN_PROT && server->dialect != LANMAN2_PROT)
474 server->sec_mode = le16_to_cpu(rsp->SecurityMode);
475 server->maxReq = min_t(unsigned int,
476 le16_to_cpu(rsp->MaxMpxCount),
478 set_credits(server, server->maxReq);
479 server->maxBuf = le16_to_cpu(rsp->MaxBufSize);
480 /* even though we do not use raw we might as well set this
481 accurately, in case we ever find a need for it */
482 if ((le16_to_cpu(rsp->RawMode) & RAW_ENABLE) == RAW_ENABLE) {
483 server->max_rw = 0xFF00;
484 server->capabilities = CAP_MPX_MODE | CAP_RAW_MODE;
486 server->max_rw = 0;/* do not need to use raw anyway */
487 server->capabilities = CAP_MPX_MODE;
489 tmp = (__s16)le16_to_cpu(rsp->ServerTimeZone);
491 /* OS/2 often does not set timezone therefore
492 * we must use server time to calc time zone.
493 * Could deviate slightly from the right zone.
494 * Smallest defined timezone difference is 15 minutes
495 * (i.e. Nepal). Rounding up/down is done to match
498 int val, seconds, remain, result;
500 unsigned long utc = ktime_get_real_seconds();
501 ts = cnvrtDosUnixTm(rsp->SrvTime.Date,
502 rsp->SrvTime.Time, 0);
503 cifs_dbg(FYI, "SrvTime %d sec since 1970 (utc: %d) diff: %d\n",
504 (int)ts.tv_sec, (int)utc,
505 (int)(utc - ts.tv_sec));
506 val = (int)(utc - ts.tv_sec);
508 result = (seconds / MIN_TZ_ADJ) * MIN_TZ_ADJ;
509 remain = seconds % MIN_TZ_ADJ;
510 if (remain >= (MIN_TZ_ADJ / 2))
511 result += MIN_TZ_ADJ;
514 server->timeAdj = result;
516 server->timeAdj = (int)tmp;
517 server->timeAdj *= 60; /* also in seconds */
519 cifs_dbg(FYI, "server->timeAdj: %d seconds\n", server->timeAdj);
522 /* BB get server time for time conversions and add
523 code to use it and timezone since this is not UTC */
525 if (rsp->EncryptionKeyLength ==
526 cpu_to_le16(CIFS_CRYPTO_KEY_SIZE)) {
527 memcpy(server->cryptkey, rsp->EncryptionKey,
528 CIFS_CRYPTO_KEY_SIZE);
529 } else if (server->sec_mode & SECMODE_PW_ENCRYPT) {
530 return -EIO; /* need cryptkey unless plain text */
533 cifs_dbg(FYI, "LANMAN negotiated\n");
538 decode_lanman_negprot_rsp(struct TCP_Server_Info *server, NEGOTIATE_RSP *pSMBr)
540 cifs_dbg(VFS, "mount failed, cifs module not built with CIFS_WEAK_PW_HASH support\n");
546 should_set_ext_sec_flag(enum securityEnum sectype)
553 if (global_secflags &
554 (CIFSSEC_MAY_KRB5 | CIFSSEC_MAY_NTLMSSP))
563 CIFSSMBNegotiate(const unsigned int xid, struct cifs_ses *ses)
566 NEGOTIATE_RSP *pSMBr;
570 struct TCP_Server_Info *server = ses->server;
574 WARN(1, "%s: server is NULL!\n", __func__);
578 rc = smb_init(SMB_COM_NEGOTIATE, 0, NULL /* no tcon yet */ ,
579 (void **) &pSMB, (void **) &pSMBr);
583 pSMB->hdr.Mid = get_next_mid(server);
584 pSMB->hdr.Flags2 |= (SMBFLG2_UNICODE | SMBFLG2_ERR_STATUS);
586 if (should_set_ext_sec_flag(ses->sectype)) {
587 cifs_dbg(FYI, "Requesting extended security.");
588 pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC;
593 * We know that all the name entries in the protocols array
594 * are short (< 16 bytes anyway) and are NUL terminated.
596 for (i = 0; i < CIFS_NUM_PROT; i++) {
597 size_t len = strlen(protocols[i].name) + 1;
599 memcpy(pSMB->DialectsArray+count, protocols[i].name, len);
602 inc_rfc1001_len(pSMB, count);
603 pSMB->ByteCount = cpu_to_le16(count);
605 rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB,
606 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
610 server->dialect = le16_to_cpu(pSMBr->DialectIndex);
611 cifs_dbg(FYI, "Dialect: %d\n", server->dialect);
612 /* Check wct = 1 error case */
613 if ((pSMBr->hdr.WordCount < 13) || (server->dialect == BAD_PROT)) {
614 /* core returns wct = 1, but we do not ask for core - otherwise
615 small wct just comes when dialect index is -1 indicating we
616 could not negotiate a common dialect */
619 } else if (pSMBr->hdr.WordCount == 13) {
620 server->negflavor = CIFS_NEGFLAVOR_LANMAN;
621 rc = decode_lanman_negprot_rsp(server, pSMBr);
623 } else if (pSMBr->hdr.WordCount != 17) {
628 /* else wct == 17, NTLM or better */
630 server->sec_mode = pSMBr->SecurityMode;
631 if ((server->sec_mode & SECMODE_USER) == 0)
632 cifs_dbg(FYI, "share mode security\n");
634 /* one byte, so no need to convert this or EncryptionKeyLen from
636 server->maxReq = min_t(unsigned int, le16_to_cpu(pSMBr->MaxMpxCount),
638 set_credits(server, server->maxReq);
639 /* probably no need to store and check maxvcs */
640 server->maxBuf = le32_to_cpu(pSMBr->MaxBufferSize);
641 server->max_rw = le32_to_cpu(pSMBr->MaxRawSize);
642 cifs_dbg(NOISY, "Max buf = %d\n", ses->server->maxBuf);
643 server->capabilities = le32_to_cpu(pSMBr->Capabilities);
644 server->timeAdj = (int)(__s16)le16_to_cpu(pSMBr->ServerTimeZone);
645 server->timeAdj *= 60;
647 if (pSMBr->EncryptionKeyLength == CIFS_CRYPTO_KEY_SIZE) {
648 server->negflavor = CIFS_NEGFLAVOR_UNENCAP;
649 memcpy(ses->server->cryptkey, pSMBr->u.EncryptionKey,
650 CIFS_CRYPTO_KEY_SIZE);
651 } else if (pSMBr->hdr.Flags2 & SMBFLG2_EXT_SEC ||
652 server->capabilities & CAP_EXTENDED_SECURITY) {
653 server->negflavor = CIFS_NEGFLAVOR_EXTENDED;
654 rc = decode_ext_sec_blob(ses, pSMBr);
655 } else if (server->sec_mode & SECMODE_PW_ENCRYPT) {
656 rc = -EIO; /* no crypt key only if plain text pwd */
658 server->negflavor = CIFS_NEGFLAVOR_UNENCAP;
659 server->capabilities &= ~CAP_EXTENDED_SECURITY;
664 rc = cifs_enable_signing(server, ses->sign);
666 cifs_buf_release(pSMB);
668 cifs_dbg(FYI, "negprot rc %d\n", rc);
673 CIFSSMBTDis(const unsigned int xid, struct cifs_tcon *tcon)
675 struct smb_hdr *smb_buffer;
678 cifs_dbg(FYI, "In tree disconnect\n");
680 /* BB: do we need to check this? These should never be NULL. */
681 if ((tcon->ses == NULL) || (tcon->ses->server == NULL))
685 * No need to return error on this operation if tid invalidated and
686 * closed on server already e.g. due to tcp session crashing. Also,
687 * the tcon is no longer on the list, so no need to take lock before
690 if ((tcon->need_reconnect) || (tcon->ses->need_reconnect))
693 rc = small_smb_init(SMB_COM_TREE_DISCONNECT, 0, tcon,
694 (void **)&smb_buffer);
698 rc = SendReceiveNoRsp(xid, tcon->ses, (char *)smb_buffer, 0);
699 cifs_small_buf_release(smb_buffer);
701 cifs_dbg(FYI, "Tree disconnect failed %d\n", rc);
703 /* No need to return error on this operation if tid invalidated and
704 closed on server already e.g. due to tcp session crashing */
712 * This is a no-op for now. We're not really interested in the reply, but
713 * rather in the fact that the server sent one and that server->lstrp
716 * FIXME: maybe we should consider checking that the reply matches request?
719 cifs_echo_callback(struct mid_q_entry *mid)
721 struct TCP_Server_Info *server = mid->callback_data;
723 DeleteMidQEntry(mid);
724 add_credits(server, 1, CIFS_ECHO_OP);
728 CIFSSMBEcho(struct TCP_Server_Info *server)
733 struct smb_rqst rqst = { .rq_iov = iov,
736 cifs_dbg(FYI, "In echo request\n");
738 rc = small_smb_init(SMB_COM_ECHO, 0, NULL, (void **)&smb);
742 if (server->capabilities & CAP_UNICODE)
743 smb->hdr.Flags2 |= SMBFLG2_UNICODE;
745 /* set up echo request */
746 smb->hdr.Tid = 0xffff;
747 smb->hdr.WordCount = 1;
748 put_unaligned_le16(1, &smb->EchoCount);
749 put_bcc(1, &smb->hdr);
751 inc_rfc1001_len(smb, 3);
754 iov[0].iov_base = smb;
755 iov[1].iov_len = get_rfc1002_length(smb);
756 iov[1].iov_base = (char *)smb + 4;
758 rc = cifs_call_async(server, &rqst, NULL, cifs_echo_callback, NULL,
759 server, CIFS_ASYNC_OP | CIFS_ECHO_OP);
761 cifs_dbg(FYI, "Echo request failed: %d\n", rc);
763 cifs_small_buf_release(smb);
769 CIFSSMBLogoff(const unsigned int xid, struct cifs_ses *ses)
771 LOGOFF_ANDX_REQ *pSMB;
774 cifs_dbg(FYI, "In SMBLogoff for session disconnect\n");
777 * BB: do we need to check validity of ses and server? They should
778 * always be valid since we have an active reference. If not, that
779 * should probably be a BUG()
781 if (!ses || !ses->server)
784 mutex_lock(&ses->session_mutex);
785 if (ses->need_reconnect)
786 goto session_already_dead; /* no need to send SMBlogoff if uid
787 already closed due to reconnect */
788 rc = small_smb_init(SMB_COM_LOGOFF_ANDX, 2, NULL, (void **)&pSMB);
790 mutex_unlock(&ses->session_mutex);
794 pSMB->hdr.Mid = get_next_mid(ses->server);
796 if (ses->server->sign)
797 pSMB->hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
799 pSMB->hdr.Uid = ses->Suid;
801 pSMB->AndXCommand = 0xFF;
802 rc = SendReceiveNoRsp(xid, ses, (char *) pSMB, 0);
803 cifs_small_buf_release(pSMB);
804 session_already_dead:
805 mutex_unlock(&ses->session_mutex);
807 /* if session dead then we do not need to do ulogoff,
808 since server closed smb session, no sense reporting
816 CIFSPOSIXDelFile(const unsigned int xid, struct cifs_tcon *tcon,
817 const char *fileName, __u16 type,
818 const struct nls_table *nls_codepage, int remap)
820 TRANSACTION2_SPI_REQ *pSMB = NULL;
821 TRANSACTION2_SPI_RSP *pSMBr = NULL;
822 struct unlink_psx_rq *pRqD;
825 int bytes_returned = 0;
826 __u16 params, param_offset, offset, byte_count;
828 cifs_dbg(FYI, "In POSIX delete\n");
830 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
835 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
837 cifsConvertToUTF16((__le16 *) pSMB->FileName, fileName,
838 PATH_MAX, nls_codepage, remap);
839 name_len++; /* trailing null */
841 } else { /* BB add path length overrun check */
842 name_len = strnlen(fileName, PATH_MAX);
843 name_len++; /* trailing null */
844 strncpy(pSMB->FileName, fileName, name_len);
847 params = 6 + name_len;
848 pSMB->MaxParameterCount = cpu_to_le16(2);
849 pSMB->MaxDataCount = 0; /* BB double check this with jra */
850 pSMB->MaxSetupCount = 0;
855 param_offset = offsetof(struct smb_com_transaction2_spi_req,
856 InformationLevel) - 4;
857 offset = param_offset + params;
859 /* Setup pointer to Request Data (inode type) */
860 pRqD = (struct unlink_psx_rq *)(((char *)&pSMB->hdr.Protocol) + offset);
861 pRqD->type = cpu_to_le16(type);
862 pSMB->ParameterOffset = cpu_to_le16(param_offset);
863 pSMB->DataOffset = cpu_to_le16(offset);
864 pSMB->SetupCount = 1;
866 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
867 byte_count = 3 /* pad */ + params + sizeof(struct unlink_psx_rq);
869 pSMB->DataCount = cpu_to_le16(sizeof(struct unlink_psx_rq));
870 pSMB->TotalDataCount = cpu_to_le16(sizeof(struct unlink_psx_rq));
871 pSMB->ParameterCount = cpu_to_le16(params);
872 pSMB->TotalParameterCount = pSMB->ParameterCount;
873 pSMB->InformationLevel = cpu_to_le16(SMB_POSIX_UNLINK);
875 inc_rfc1001_len(pSMB, byte_count);
876 pSMB->ByteCount = cpu_to_le16(byte_count);
877 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
878 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
880 cifs_dbg(FYI, "Posix delete returned %d\n", rc);
881 cifs_buf_release(pSMB);
883 cifs_stats_inc(&tcon->stats.cifs_stats.num_deletes);
892 CIFSSMBDelFile(const unsigned int xid, struct cifs_tcon *tcon, const char *name,
893 struct cifs_sb_info *cifs_sb)
895 DELETE_FILE_REQ *pSMB = NULL;
896 DELETE_FILE_RSP *pSMBr = NULL;
900 int remap = cifs_remap(cifs_sb);
903 rc = smb_init(SMB_COM_DELETE, 1, tcon, (void **) &pSMB,
908 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
909 name_len = cifsConvertToUTF16((__le16 *) pSMB->fileName, name,
910 PATH_MAX, cifs_sb->local_nls,
912 name_len++; /* trailing null */
914 } else { /* BB improve check for buffer overruns BB */
915 name_len = strnlen(name, PATH_MAX);
916 name_len++; /* trailing null */
917 strncpy(pSMB->fileName, name, name_len);
919 pSMB->SearchAttributes =
920 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM);
921 pSMB->BufferFormat = 0x04;
922 inc_rfc1001_len(pSMB, name_len + 1);
923 pSMB->ByteCount = cpu_to_le16(name_len + 1);
924 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
925 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
926 cifs_stats_inc(&tcon->stats.cifs_stats.num_deletes);
928 cifs_dbg(FYI, "Error in RMFile = %d\n", rc);
930 cifs_buf_release(pSMB);
938 CIFSSMBRmDir(const unsigned int xid, struct cifs_tcon *tcon, const char *name,
939 struct cifs_sb_info *cifs_sb)
941 DELETE_DIRECTORY_REQ *pSMB = NULL;
942 DELETE_DIRECTORY_RSP *pSMBr = NULL;
946 int remap = cifs_remap(cifs_sb);
948 cifs_dbg(FYI, "In CIFSSMBRmDir\n");
950 rc = smb_init(SMB_COM_DELETE_DIRECTORY, 0, tcon, (void **) &pSMB,
955 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
956 name_len = cifsConvertToUTF16((__le16 *) pSMB->DirName, name,
957 PATH_MAX, cifs_sb->local_nls,
959 name_len++; /* trailing null */
961 } else { /* BB improve check for buffer overruns BB */
962 name_len = strnlen(name, PATH_MAX);
963 name_len++; /* trailing null */
964 strncpy(pSMB->DirName, name, name_len);
967 pSMB->BufferFormat = 0x04;
968 inc_rfc1001_len(pSMB, name_len + 1);
969 pSMB->ByteCount = cpu_to_le16(name_len + 1);
970 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
971 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
972 cifs_stats_inc(&tcon->stats.cifs_stats.num_rmdirs);
974 cifs_dbg(FYI, "Error in RMDir = %d\n", rc);
976 cifs_buf_release(pSMB);
983 CIFSSMBMkDir(const unsigned int xid, struct cifs_tcon *tcon, const char *name,
984 struct cifs_sb_info *cifs_sb)
987 CREATE_DIRECTORY_REQ *pSMB = NULL;
988 CREATE_DIRECTORY_RSP *pSMBr = NULL;
991 int remap = cifs_remap(cifs_sb);
993 cifs_dbg(FYI, "In CIFSSMBMkDir\n");
995 rc = smb_init(SMB_COM_CREATE_DIRECTORY, 0, tcon, (void **) &pSMB,
1000 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1001 name_len = cifsConvertToUTF16((__le16 *) pSMB->DirName, name,
1002 PATH_MAX, cifs_sb->local_nls,
1004 name_len++; /* trailing null */
1006 } else { /* BB improve check for buffer overruns BB */
1007 name_len = strnlen(name, PATH_MAX);
1008 name_len++; /* trailing null */
1009 strncpy(pSMB->DirName, name, name_len);
1012 pSMB->BufferFormat = 0x04;
1013 inc_rfc1001_len(pSMB, name_len + 1);
1014 pSMB->ByteCount = cpu_to_le16(name_len + 1);
1015 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1016 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1017 cifs_stats_inc(&tcon->stats.cifs_stats.num_mkdirs);
1019 cifs_dbg(FYI, "Error in Mkdir = %d\n", rc);
1021 cifs_buf_release(pSMB);
1028 CIFSPOSIXCreate(const unsigned int xid, struct cifs_tcon *tcon,
1029 __u32 posix_flags, __u64 mode, __u16 *netfid,
1030 FILE_UNIX_BASIC_INFO *pRetData, __u32 *pOplock,
1031 const char *name, const struct nls_table *nls_codepage,
1034 TRANSACTION2_SPI_REQ *pSMB = NULL;
1035 TRANSACTION2_SPI_RSP *pSMBr = NULL;
1038 int bytes_returned = 0;
1039 __u16 params, param_offset, offset, byte_count, count;
1040 OPEN_PSX_REQ *pdata;
1041 OPEN_PSX_RSP *psx_rsp;
1043 cifs_dbg(FYI, "In POSIX Create\n");
1045 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
1050 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1052 cifsConvertToUTF16((__le16 *) pSMB->FileName, name,
1053 PATH_MAX, nls_codepage, remap);
1054 name_len++; /* trailing null */
1056 } else { /* BB improve the check for buffer overruns BB */
1057 name_len = strnlen(name, PATH_MAX);
1058 name_len++; /* trailing null */
1059 strncpy(pSMB->FileName, name, name_len);
1062 params = 6 + name_len;
1063 count = sizeof(OPEN_PSX_REQ);
1064 pSMB->MaxParameterCount = cpu_to_le16(2);
1065 pSMB->MaxDataCount = cpu_to_le16(1000); /* large enough */
1066 pSMB->MaxSetupCount = 0;
1070 pSMB->Reserved2 = 0;
1071 param_offset = offsetof(struct smb_com_transaction2_spi_req,
1072 InformationLevel) - 4;
1073 offset = param_offset + params;
1074 pdata = (OPEN_PSX_REQ *)(((char *)&pSMB->hdr.Protocol) + offset);
1075 pdata->Level = cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC);
1076 pdata->Permissions = cpu_to_le64(mode);
1077 pdata->PosixOpenFlags = cpu_to_le32(posix_flags);
1078 pdata->OpenFlags = cpu_to_le32(*pOplock);
1079 pSMB->ParameterOffset = cpu_to_le16(param_offset);
1080 pSMB->DataOffset = cpu_to_le16(offset);
1081 pSMB->SetupCount = 1;
1082 pSMB->Reserved3 = 0;
1083 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
1084 byte_count = 3 /* pad */ + params + count;
1086 pSMB->DataCount = cpu_to_le16(count);
1087 pSMB->ParameterCount = cpu_to_le16(params);
1088 pSMB->TotalDataCount = pSMB->DataCount;
1089 pSMB->TotalParameterCount = pSMB->ParameterCount;
1090 pSMB->InformationLevel = cpu_to_le16(SMB_POSIX_OPEN);
1091 pSMB->Reserved4 = 0;
1092 inc_rfc1001_len(pSMB, byte_count);
1093 pSMB->ByteCount = cpu_to_le16(byte_count);
1094 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1095 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1097 cifs_dbg(FYI, "Posix create returned %d\n", rc);
1098 goto psx_create_err;
1101 cifs_dbg(FYI, "copying inode info\n");
1102 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
1104 if (rc || get_bcc(&pSMBr->hdr) < sizeof(OPEN_PSX_RSP)) {
1105 rc = -EIO; /* bad smb */
1106 goto psx_create_err;
1109 /* copy return information to pRetData */
1110 psx_rsp = (OPEN_PSX_RSP *)((char *) &pSMBr->hdr.Protocol
1111 + le16_to_cpu(pSMBr->t2.DataOffset));
1113 *pOplock = le16_to_cpu(psx_rsp->OplockFlags);
1115 *netfid = psx_rsp->Fid; /* cifs fid stays in le */
1116 /* Let caller know file was created so we can set the mode. */
1117 /* Do we care about the CreateAction in any other cases? */
1118 if (cpu_to_le32(FILE_CREATE) == psx_rsp->CreateAction)
1119 *pOplock |= CIFS_CREATE_ACTION;
1120 /* check to make sure response data is there */
1121 if (psx_rsp->ReturnedLevel != cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC)) {
1122 pRetData->Type = cpu_to_le32(-1); /* unknown */
1123 cifs_dbg(NOISY, "unknown type\n");
1125 if (get_bcc(&pSMBr->hdr) < sizeof(OPEN_PSX_RSP)
1126 + sizeof(FILE_UNIX_BASIC_INFO)) {
1127 cifs_dbg(VFS, "Open response data too small\n");
1128 pRetData->Type = cpu_to_le32(-1);
1129 goto psx_create_err;
1131 memcpy((char *) pRetData,
1132 (char *)psx_rsp + sizeof(OPEN_PSX_RSP),
1133 sizeof(FILE_UNIX_BASIC_INFO));
1137 cifs_buf_release(pSMB);
1139 if (posix_flags & SMB_O_DIRECTORY)
1140 cifs_stats_inc(&tcon->stats.cifs_stats.num_posixmkdirs);
1142 cifs_stats_inc(&tcon->stats.cifs_stats.num_posixopens);
1150 static __u16 convert_disposition(int disposition)
1154 switch (disposition) {
1155 case FILE_SUPERSEDE:
1156 ofun = SMBOPEN_OCREATE | SMBOPEN_OTRUNC;
1159 ofun = SMBOPEN_OAPPEND;
1162 ofun = SMBOPEN_OCREATE;
1165 ofun = SMBOPEN_OCREATE | SMBOPEN_OAPPEND;
1167 case FILE_OVERWRITE:
1168 ofun = SMBOPEN_OTRUNC;
1170 case FILE_OVERWRITE_IF:
1171 ofun = SMBOPEN_OCREATE | SMBOPEN_OTRUNC;
1174 cifs_dbg(FYI, "unknown disposition %d\n", disposition);
1175 ofun = SMBOPEN_OAPPEND; /* regular open */
1181 access_flags_to_smbopen_mode(const int access_flags)
1183 int masked_flags = access_flags & (GENERIC_READ | GENERIC_WRITE);
1185 if (masked_flags == GENERIC_READ)
1186 return SMBOPEN_READ;
1187 else if (masked_flags == GENERIC_WRITE)
1188 return SMBOPEN_WRITE;
1190 /* just go for read/write */
1191 return SMBOPEN_READWRITE;
1195 SMBLegacyOpen(const unsigned int xid, struct cifs_tcon *tcon,
1196 const char *fileName, const int openDisposition,
1197 const int access_flags, const int create_options, __u16 *netfid,
1198 int *pOplock, FILE_ALL_INFO *pfile_info,
1199 const struct nls_table *nls_codepage, int remap)
1202 OPENX_REQ *pSMB = NULL;
1203 OPENX_RSP *pSMBr = NULL;
1209 rc = smb_init(SMB_COM_OPEN_ANDX, 15, tcon, (void **) &pSMB,
1214 pSMB->AndXCommand = 0xFF; /* none */
1216 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1217 count = 1; /* account for one byte pad to word boundary */
1219 cifsConvertToUTF16((__le16 *) (pSMB->fileName + 1),
1220 fileName, PATH_MAX, nls_codepage, remap);
1221 name_len++; /* trailing null */
1223 } else { /* BB improve check for buffer overruns BB */
1224 count = 0; /* no pad */
1225 name_len = strnlen(fileName, PATH_MAX);
1226 name_len++; /* trailing null */
1227 strncpy(pSMB->fileName, fileName, name_len);
1229 if (*pOplock & REQ_OPLOCK)
1230 pSMB->OpenFlags = cpu_to_le16(REQ_OPLOCK);
1231 else if (*pOplock & REQ_BATCHOPLOCK)
1232 pSMB->OpenFlags = cpu_to_le16(REQ_BATCHOPLOCK);
1234 pSMB->OpenFlags |= cpu_to_le16(REQ_MORE_INFO);
1235 pSMB->Mode = cpu_to_le16(access_flags_to_smbopen_mode(access_flags));
1236 pSMB->Mode |= cpu_to_le16(0x40); /* deny none */
1237 /* set file as system file if special file such
1238 as fifo and server expecting SFU style and
1239 no Unix extensions */
1241 if (create_options & CREATE_OPTION_SPECIAL)
1242 pSMB->FileAttributes = cpu_to_le16(ATTR_SYSTEM);
1243 else /* BB FIXME BB */
1244 pSMB->FileAttributes = cpu_to_le16(0/*ATTR_NORMAL*/);
1246 if (create_options & CREATE_OPTION_READONLY)
1247 pSMB->FileAttributes |= cpu_to_le16(ATTR_READONLY);
1250 /* pSMB->CreateOptions = cpu_to_le32(create_options &
1251 CREATE_OPTIONS_MASK); */
1252 /* BB FIXME END BB */
1254 pSMB->Sattr = cpu_to_le16(ATTR_HIDDEN | ATTR_SYSTEM | ATTR_DIRECTORY);
1255 pSMB->OpenFunction = cpu_to_le16(convert_disposition(openDisposition));
1257 inc_rfc1001_len(pSMB, count);
1259 pSMB->ByteCount = cpu_to_le16(count);
1260 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1261 (struct smb_hdr *)pSMBr, &bytes_returned, 0);
1262 cifs_stats_inc(&tcon->stats.cifs_stats.num_opens);
1264 cifs_dbg(FYI, "Error in Open = %d\n", rc);
1266 /* BB verify if wct == 15 */
1268 /* *pOplock = pSMBr->OplockLevel; */ /* BB take from action field*/
1270 *netfid = pSMBr->Fid; /* cifs fid stays in le */
1271 /* Let caller know file was created so we can set the mode. */
1272 /* Do we care about the CreateAction in any other cases? */
1274 /* if (cpu_to_le32(FILE_CREATE) == pSMBr->CreateAction)
1275 *pOplock |= CIFS_CREATE_ACTION; */
1279 pfile_info->CreationTime = 0; /* BB convert CreateTime*/
1280 pfile_info->LastAccessTime = 0; /* BB fixme */
1281 pfile_info->LastWriteTime = 0; /* BB fixme */
1282 pfile_info->ChangeTime = 0; /* BB fixme */
1283 pfile_info->Attributes =
1284 cpu_to_le32(le16_to_cpu(pSMBr->FileAttributes));
1285 /* the file_info buf is endian converted by caller */
1286 pfile_info->AllocationSize =
1287 cpu_to_le64(le32_to_cpu(pSMBr->EndOfFile));
1288 pfile_info->EndOfFile = pfile_info->AllocationSize;
1289 pfile_info->NumberOfLinks = cpu_to_le32(1);
1290 pfile_info->DeletePending = 0;
1294 cifs_buf_release(pSMB);
1301 CIFS_open(const unsigned int xid, struct cifs_open_parms *oparms, int *oplock,
1305 OPEN_REQ *req = NULL;
1306 OPEN_RSP *rsp = NULL;
1310 struct cifs_sb_info *cifs_sb = oparms->cifs_sb;
1311 struct cifs_tcon *tcon = oparms->tcon;
1312 int remap = cifs_remap(cifs_sb);
1313 const struct nls_table *nls = cifs_sb->local_nls;
1314 int create_options = oparms->create_options;
1315 int desired_access = oparms->desired_access;
1316 int disposition = oparms->disposition;
1317 const char *path = oparms->path;
1320 rc = smb_init(SMB_COM_NT_CREATE_ANDX, 24, tcon, (void **)&req,
1325 /* no commands go after this */
1326 req->AndXCommand = 0xFF;
1328 if (req->hdr.Flags2 & SMBFLG2_UNICODE) {
1329 /* account for one byte pad to word boundary */
1331 name_len = cifsConvertToUTF16((__le16 *)(req->fileName + 1),
1332 path, PATH_MAX, nls, remap);
1336 req->NameLength = cpu_to_le16(name_len);
1338 /* BB improve check for buffer overruns BB */
1341 name_len = strnlen(path, PATH_MAX);
1344 req->NameLength = cpu_to_le16(name_len);
1345 strncpy(req->fileName, path, name_len);
1348 if (*oplock & REQ_OPLOCK)
1349 req->OpenFlags = cpu_to_le32(REQ_OPLOCK);
1350 else if (*oplock & REQ_BATCHOPLOCK)
1351 req->OpenFlags = cpu_to_le32(REQ_BATCHOPLOCK);
1353 req->DesiredAccess = cpu_to_le32(desired_access);
1354 req->AllocationSize = 0;
1357 * Set file as system file if special file such as fifo and server
1358 * expecting SFU style and no Unix extensions.
1360 if (create_options & CREATE_OPTION_SPECIAL)
1361 req->FileAttributes = cpu_to_le32(ATTR_SYSTEM);
1363 req->FileAttributes = cpu_to_le32(ATTR_NORMAL);
1366 * XP does not handle ATTR_POSIX_SEMANTICS but it helps speed up case
1367 * sensitive checks for other servers such as Samba.
1369 if (tcon->ses->capabilities & CAP_UNIX)
1370 req->FileAttributes |= cpu_to_le32(ATTR_POSIX_SEMANTICS);
1372 if (create_options & CREATE_OPTION_READONLY)
1373 req->FileAttributes |= cpu_to_le32(ATTR_READONLY);
1375 req->ShareAccess = cpu_to_le32(FILE_SHARE_ALL);
1376 req->CreateDisposition = cpu_to_le32(disposition);
1377 req->CreateOptions = cpu_to_le32(create_options & CREATE_OPTIONS_MASK);
1379 /* BB Expirement with various impersonation levels and verify */
1380 req->ImpersonationLevel = cpu_to_le32(SECURITY_IMPERSONATION);
1381 req->SecurityFlags = SECURITY_CONTEXT_TRACKING|SECURITY_EFFECTIVE_ONLY;
1384 inc_rfc1001_len(req, count);
1386 req->ByteCount = cpu_to_le16(count);
1387 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *)req,
1388 (struct smb_hdr *)rsp, &bytes_returned, 0);
1389 cifs_stats_inc(&tcon->stats.cifs_stats.num_opens);
1391 cifs_dbg(FYI, "Error in Open = %d\n", rc);
1392 cifs_buf_release(req);
1398 /* 1 byte no need to le_to_cpu */
1399 *oplock = rsp->OplockLevel;
1400 /* cifs fid stays in le */
1401 oparms->fid->netfid = rsp->Fid;
1403 /* Let caller know file was created so we can set the mode. */
1404 /* Do we care about the CreateAction in any other cases? */
1405 if (cpu_to_le32(FILE_CREATE) == rsp->CreateAction)
1406 *oplock |= CIFS_CREATE_ACTION;
1409 /* copy from CreationTime to Attributes */
1410 memcpy((char *)buf, (char *)&rsp->CreationTime, 36);
1411 /* the file_info buf is endian converted by caller */
1412 buf->AllocationSize = rsp->AllocationSize;
1413 buf->EndOfFile = rsp->EndOfFile;
1414 buf->NumberOfLinks = cpu_to_le32(1);
1415 buf->DeletePending = 0;
1418 cifs_buf_release(req);
1423 * Discard any remaining data in the current SMB. To do this, we borrow the
1427 cifs_discard_remaining_data(struct TCP_Server_Info *server)
1429 unsigned int rfclen = get_rfc1002_length(server->smallbuf);
1430 int remaining = rfclen + 4 - server->total_read;
1432 while (remaining > 0) {
1435 length = cifs_read_from_socket(server, server->bigbuf,
1436 min_t(unsigned int, remaining,
1437 CIFSMaxBufSize + MAX_HEADER_SIZE(server)));
1440 server->total_read += length;
1441 remaining -= length;
1448 __cifs_readv_discard(struct TCP_Server_Info *server, struct mid_q_entry *mid,
1453 length = cifs_discard_remaining_data(server);
1454 dequeue_mid(mid, malformed);
1455 mid->resp_buf = server->smallbuf;
1456 server->smallbuf = NULL;
1461 cifs_readv_discard(struct TCP_Server_Info *server, struct mid_q_entry *mid)
1463 struct cifs_readdata *rdata = mid->callback_data;
1465 return __cifs_readv_discard(server, mid, rdata->result);
1469 cifs_readv_receive(struct TCP_Server_Info *server, struct mid_q_entry *mid)
1472 unsigned int data_offset, data_len;
1473 struct cifs_readdata *rdata = mid->callback_data;
1474 char *buf = server->smallbuf;
1475 unsigned int buflen = get_rfc1002_length(buf) + 4;
1477 cifs_dbg(FYI, "%s: mid=%llu offset=%llu bytes=%u\n",
1478 __func__, mid->mid, rdata->offset, rdata->bytes);
1481 * read the rest of READ_RSP header (sans Data array), or whatever we
1482 * can if there's not enough data. At this point, we've read down to
1485 len = min_t(unsigned int, buflen, server->vals->read_rsp_size) -
1486 HEADER_SIZE(server) + 1;
1488 length = cifs_read_from_socket(server,
1489 buf + HEADER_SIZE(server) - 1, len);
1492 server->total_read += length;
1494 if (server->ops->is_session_expired &&
1495 server->ops->is_session_expired(buf)) {
1496 cifs_reconnect(server);
1497 wake_up(&server->response_q);
1501 if (server->ops->is_status_pending &&
1502 server->ops->is_status_pending(buf, server, 0)) {
1503 cifs_discard_remaining_data(server);
1507 /* set up first two iov for signature check and to get credits */
1508 rdata->iov[0].iov_base = buf;
1509 rdata->iov[0].iov_len = 4;
1510 rdata->iov[1].iov_base = buf + 4;
1511 rdata->iov[1].iov_len = server->total_read - 4;
1512 cifs_dbg(FYI, "0: iov_base=%p iov_len=%zu\n",
1513 rdata->iov[0].iov_base, rdata->iov[0].iov_len);
1514 cifs_dbg(FYI, "1: iov_base=%p iov_len=%zu\n",
1515 rdata->iov[1].iov_base, rdata->iov[1].iov_len);
1517 /* Was the SMB read successful? */
1518 rdata->result = server->ops->map_error(buf, false);
1519 if (rdata->result != 0) {
1520 cifs_dbg(FYI, "%s: server returned error %d\n",
1521 __func__, rdata->result);
1522 /* normal error on read response */
1523 return __cifs_readv_discard(server, mid, false);
1526 /* Is there enough to get to the rest of the READ_RSP header? */
1527 if (server->total_read < server->vals->read_rsp_size) {
1528 cifs_dbg(FYI, "%s: server returned short header. got=%u expected=%zu\n",
1529 __func__, server->total_read,
1530 server->vals->read_rsp_size);
1531 rdata->result = -EIO;
1532 return cifs_readv_discard(server, mid);
1535 data_offset = server->ops->read_data_offset(buf) + 4;
1536 if (data_offset < server->total_read) {
1538 * win2k8 sometimes sends an offset of 0 when the read
1539 * is beyond the EOF. Treat it as if the data starts just after
1542 cifs_dbg(FYI, "%s: data offset (%u) inside read response header\n",
1543 __func__, data_offset);
1544 data_offset = server->total_read;
1545 } else if (data_offset > MAX_CIFS_SMALL_BUFFER_SIZE) {
1546 /* data_offset is beyond the end of smallbuf */
1547 cifs_dbg(FYI, "%s: data offset (%u) beyond end of smallbuf\n",
1548 __func__, data_offset);
1549 rdata->result = -EIO;
1550 return cifs_readv_discard(server, mid);
1553 cifs_dbg(FYI, "%s: total_read=%u data_offset=%u\n",
1554 __func__, server->total_read, data_offset);
1556 len = data_offset - server->total_read;
1558 /* read any junk before data into the rest of smallbuf */
1559 length = cifs_read_from_socket(server,
1560 buf + server->total_read, len);
1563 server->total_read += length;
1566 /* how much data is in the response? */
1567 data_len = server->ops->read_data_length(buf);
1568 if (data_offset + data_len > buflen) {
1569 /* data_len is corrupt -- discard frame */
1570 rdata->result = -EIO;
1571 return cifs_readv_discard(server, mid);
1574 length = rdata->read_into_pages(server, rdata, data_len);
1578 server->total_read += length;
1580 cifs_dbg(FYI, "total_read=%u buflen=%u remaining=%u\n",
1581 server->total_read, buflen, data_len);
1583 /* discard anything left over */
1584 if (server->total_read < buflen)
1585 return cifs_readv_discard(server, mid);
1587 dequeue_mid(mid, false);
1588 mid->resp_buf = server->smallbuf;
1589 server->smallbuf = NULL;
1594 cifs_readv_callback(struct mid_q_entry *mid)
1596 struct cifs_readdata *rdata = mid->callback_data;
1597 struct cifs_tcon *tcon = tlink_tcon(rdata->cfile->tlink);
1598 struct TCP_Server_Info *server = tcon->ses->server;
1599 struct smb_rqst rqst = { .rq_iov = rdata->iov,
1601 .rq_pages = rdata->pages,
1602 .rq_npages = rdata->nr_pages,
1603 .rq_pagesz = rdata->pagesz,
1604 .rq_tailsz = rdata->tailsz };
1606 cifs_dbg(FYI, "%s: mid=%llu state=%d result=%d bytes=%u\n",
1607 __func__, mid->mid, mid->mid_state, rdata->result,
1610 switch (mid->mid_state) {
1611 case MID_RESPONSE_RECEIVED:
1612 /* result already set, check signature */
1616 rc = cifs_verify_signature(&rqst, server,
1617 mid->sequence_number);
1619 cifs_dbg(VFS, "SMB signature verification returned error = %d\n",
1622 /* FIXME: should this be counted toward the initiating task? */
1623 task_io_account_read(rdata->got_bytes);
1624 cifs_stats_bytes_read(tcon, rdata->got_bytes);
1626 case MID_REQUEST_SUBMITTED:
1627 case MID_RETRY_NEEDED:
1628 rdata->result = -EAGAIN;
1629 if (server->sign && rdata->got_bytes)
1630 /* reset bytes number since we can not check a sign */
1631 rdata->got_bytes = 0;
1632 /* FIXME: should this be counted toward the initiating task? */
1633 task_io_account_read(rdata->got_bytes);
1634 cifs_stats_bytes_read(tcon, rdata->got_bytes);
1637 rdata->result = -EIO;
1640 queue_work(cifsiod_wq, &rdata->work);
1641 DeleteMidQEntry(mid);
1642 add_credits(server, 1, 0);
1645 /* cifs_async_readv - send an async write, and set up mid to handle result */
1647 cifs_async_readv(struct cifs_readdata *rdata)
1650 READ_REQ *smb = NULL;
1652 struct cifs_tcon *tcon = tlink_tcon(rdata->cfile->tlink);
1653 struct smb_rqst rqst = { .rq_iov = rdata->iov,
1656 cifs_dbg(FYI, "%s: offset=%llu bytes=%u\n",
1657 __func__, rdata->offset, rdata->bytes);
1659 if (tcon->ses->capabilities & CAP_LARGE_FILES)
1662 wct = 10; /* old style read */
1663 if ((rdata->offset >> 32) > 0) {
1664 /* can not handle this big offset for old */
1669 rc = small_smb_init(SMB_COM_READ_ANDX, wct, tcon, (void **)&smb);
1673 smb->hdr.Pid = cpu_to_le16((__u16)rdata->pid);
1674 smb->hdr.PidHigh = cpu_to_le16((__u16)(rdata->pid >> 16));
1676 smb->AndXCommand = 0xFF; /* none */
1677 smb->Fid = rdata->cfile->fid.netfid;
1678 smb->OffsetLow = cpu_to_le32(rdata->offset & 0xFFFFFFFF);
1680 smb->OffsetHigh = cpu_to_le32(rdata->offset >> 32);
1682 smb->MaxCount = cpu_to_le16(rdata->bytes & 0xFFFF);
1683 smb->MaxCountHigh = cpu_to_le32(rdata->bytes >> 16);
1687 /* old style read */
1688 struct smb_com_readx_req *smbr =
1689 (struct smb_com_readx_req *)smb;
1690 smbr->ByteCount = 0;
1693 /* 4 for RFC1001 length + 1 for BCC */
1694 rdata->iov[0].iov_base = smb;
1695 rdata->iov[0].iov_len = 4;
1696 rdata->iov[1].iov_base = (char *)smb + 4;
1697 rdata->iov[1].iov_len = get_rfc1002_length(smb);
1699 kref_get(&rdata->refcount);
1700 rc = cifs_call_async(tcon->ses->server, &rqst, cifs_readv_receive,
1701 cifs_readv_callback, NULL, rdata, 0);
1704 cifs_stats_inc(&tcon->stats.cifs_stats.num_reads);
1706 kref_put(&rdata->refcount, cifs_readdata_release);
1708 cifs_small_buf_release(smb);
1713 CIFSSMBRead(const unsigned int xid, struct cifs_io_parms *io_parms,
1714 unsigned int *nbytes, char **buf, int *pbuf_type)
1717 READ_REQ *pSMB = NULL;
1718 READ_RSP *pSMBr = NULL;
1719 char *pReadData = NULL;
1721 int resp_buf_type = 0;
1723 struct kvec rsp_iov;
1724 __u32 pid = io_parms->pid;
1725 __u16 netfid = io_parms->netfid;
1726 __u64 offset = io_parms->offset;
1727 struct cifs_tcon *tcon = io_parms->tcon;
1728 unsigned int count = io_parms->length;
1730 cifs_dbg(FYI, "Reading %d bytes on fid %d\n", count, netfid);
1731 if (tcon->ses->capabilities & CAP_LARGE_FILES)
1734 wct = 10; /* old style read */
1735 if ((offset >> 32) > 0) {
1736 /* can not handle this big offset for old */
1742 rc = small_smb_init(SMB_COM_READ_ANDX, wct, tcon, (void **) &pSMB);
1746 pSMB->hdr.Pid = cpu_to_le16((__u16)pid);
1747 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid >> 16));
1749 /* tcon and ses pointer are checked in smb_init */
1750 if (tcon->ses->server == NULL)
1751 return -ECONNABORTED;
1753 pSMB->AndXCommand = 0xFF; /* none */
1755 pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF);
1757 pSMB->OffsetHigh = cpu_to_le32(offset >> 32);
1759 pSMB->Remaining = 0;
1760 pSMB->MaxCount = cpu_to_le16(count & 0xFFFF);
1761 pSMB->MaxCountHigh = cpu_to_le32(count >> 16);
1763 pSMB->ByteCount = 0; /* no need to do le conversion since 0 */
1765 /* old style read */
1766 struct smb_com_readx_req *pSMBW =
1767 (struct smb_com_readx_req *)pSMB;
1768 pSMBW->ByteCount = 0;
1771 iov[0].iov_base = (char *)pSMB;
1772 iov[0].iov_len = be32_to_cpu(pSMB->hdr.smb_buf_length) + 4;
1773 rc = SendReceive2(xid, tcon->ses, iov, 1, &resp_buf_type,
1774 CIFS_LOG_ERROR, &rsp_iov);
1775 cifs_small_buf_release(pSMB);
1776 cifs_stats_inc(&tcon->stats.cifs_stats.num_reads);
1777 pSMBr = (READ_RSP *)rsp_iov.iov_base;
1779 cifs_dbg(VFS, "Send error in read = %d\n", rc);
1781 int data_length = le16_to_cpu(pSMBr->DataLengthHigh);
1782 data_length = data_length << 16;
1783 data_length += le16_to_cpu(pSMBr->DataLength);
1784 *nbytes = data_length;
1786 /*check that DataLength would not go beyond end of SMB */
1787 if ((data_length > CIFSMaxBufSize)
1788 || (data_length > count)) {
1789 cifs_dbg(FYI, "bad length %d for count %d\n",
1790 data_length, count);
1794 pReadData = (char *) (&pSMBr->hdr.Protocol) +
1795 le16_to_cpu(pSMBr->DataOffset);
1796 /* if (rc = copy_to_user(buf, pReadData, data_length)) {
1797 cifs_dbg(VFS, "Faulting on read rc = %d\n",rc);
1799 }*/ /* can not use copy_to_user when using page cache*/
1801 memcpy(*buf, pReadData, data_length);
1806 free_rsp_buf(resp_buf_type, rsp_iov.iov_base);
1807 } else if (resp_buf_type != CIFS_NO_BUFFER) {
1808 /* return buffer to caller to free */
1809 *buf = rsp_iov.iov_base;
1810 if (resp_buf_type == CIFS_SMALL_BUFFER)
1811 *pbuf_type = CIFS_SMALL_BUFFER;
1812 else if (resp_buf_type == CIFS_LARGE_BUFFER)
1813 *pbuf_type = CIFS_LARGE_BUFFER;
1814 } /* else no valid buffer on return - leave as null */
1816 /* Note: On -EAGAIN error only caller can retry on handle based calls
1817 since file handle passed in no longer valid */
1823 CIFSSMBWrite(const unsigned int xid, struct cifs_io_parms *io_parms,
1824 unsigned int *nbytes, const char *buf)
1827 WRITE_REQ *pSMB = NULL;
1828 WRITE_RSP *pSMBr = NULL;
1829 int bytes_returned, wct;
1832 __u32 pid = io_parms->pid;
1833 __u16 netfid = io_parms->netfid;
1834 __u64 offset = io_parms->offset;
1835 struct cifs_tcon *tcon = io_parms->tcon;
1836 unsigned int count = io_parms->length;
1840 /* cifs_dbg(FYI, "write at %lld %d bytes\n", offset, count);*/
1841 if (tcon->ses == NULL)
1842 return -ECONNABORTED;
1844 if (tcon->ses->capabilities & CAP_LARGE_FILES)
1848 if ((offset >> 32) > 0) {
1849 /* can not handle big offset for old srv */
1854 rc = smb_init(SMB_COM_WRITE_ANDX, wct, tcon, (void **) &pSMB,
1859 pSMB->hdr.Pid = cpu_to_le16((__u16)pid);
1860 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid >> 16));
1862 /* tcon and ses pointer are checked in smb_init */
1863 if (tcon->ses->server == NULL)
1864 return -ECONNABORTED;
1866 pSMB->AndXCommand = 0xFF; /* none */
1868 pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF);
1870 pSMB->OffsetHigh = cpu_to_le32(offset >> 32);
1872 pSMB->Reserved = 0xFFFFFFFF;
1873 pSMB->WriteMode = 0;
1874 pSMB->Remaining = 0;
1876 /* Can increase buffer size if buffer is big enough in some cases ie we
1877 can send more if LARGE_WRITE_X capability returned by the server and if
1878 our buffer is big enough or if we convert to iovecs on socket writes
1879 and eliminate the copy to the CIFS buffer */
1880 if (tcon->ses->capabilities & CAP_LARGE_WRITE_X) {
1881 bytes_sent = min_t(const unsigned int, CIFSMaxBufSize, count);
1883 bytes_sent = (tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE)
1887 if (bytes_sent > count)
1890 cpu_to_le16(offsetof(struct smb_com_write_req, Data) - 4);
1892 memcpy(pSMB->Data, buf, bytes_sent);
1893 else if (count != 0) {
1895 cifs_buf_release(pSMB);
1897 } /* else setting file size with write of zero bytes */
1899 byte_count = bytes_sent + 1; /* pad */
1900 else /* wct == 12 */
1901 byte_count = bytes_sent + 5; /* bigger pad, smaller smb hdr */
1903 pSMB->DataLengthLow = cpu_to_le16(bytes_sent & 0xFFFF);
1904 pSMB->DataLengthHigh = cpu_to_le16(bytes_sent >> 16);
1905 inc_rfc1001_len(pSMB, byte_count);
1908 pSMB->ByteCount = cpu_to_le16(byte_count);
1909 else { /* old style write has byte count 4 bytes earlier
1911 struct smb_com_writex_req *pSMBW =
1912 (struct smb_com_writex_req *)pSMB;
1913 pSMBW->ByteCount = cpu_to_le16(byte_count);
1916 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1917 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1918 cifs_stats_inc(&tcon->stats.cifs_stats.num_writes);
1920 cifs_dbg(FYI, "Send error in write = %d\n", rc);
1922 *nbytes = le16_to_cpu(pSMBr->CountHigh);
1923 *nbytes = (*nbytes) << 16;
1924 *nbytes += le16_to_cpu(pSMBr->Count);
1927 * Mask off high 16 bits when bytes written as returned by the
1928 * server is greater than bytes requested by the client. Some
1929 * OS/2 servers are known to set incorrect CountHigh values.
1931 if (*nbytes > count)
1935 cifs_buf_release(pSMB);
1937 /* Note: On -EAGAIN error only caller can retry on handle based calls
1938 since file handle passed in no longer valid */
1944 cifs_writedata_release(struct kref *refcount)
1946 struct cifs_writedata *wdata = container_of(refcount,
1947 struct cifs_writedata, refcount);
1950 cifsFileInfo_put(wdata->cfile);
1956 * Write failed with a retryable error. Resend the write request. It's also
1957 * possible that the page was redirtied so re-clean the page.
1960 cifs_writev_requeue(struct cifs_writedata *wdata)
1963 struct inode *inode = d_inode(wdata->cfile->dentry);
1964 struct TCP_Server_Info *server;
1965 unsigned int rest_len;
1967 server = tlink_tcon(wdata->cfile->tlink)->ses->server;
1969 rest_len = wdata->bytes;
1971 struct cifs_writedata *wdata2;
1972 unsigned int j, nr_pages, wsize, tailsz, cur_len;
1974 wsize = server->ops->wp_retry_size(inode);
1975 if (wsize < rest_len) {
1976 nr_pages = wsize / PAGE_SIZE;
1981 cur_len = nr_pages * PAGE_SIZE;
1984 nr_pages = DIV_ROUND_UP(rest_len, PAGE_SIZE);
1986 tailsz = rest_len - (nr_pages - 1) * PAGE_SIZE;
1989 wdata2 = cifs_writedata_alloc(nr_pages, cifs_writev_complete);
1995 for (j = 0; j < nr_pages; j++) {
1996 wdata2->pages[j] = wdata->pages[i + j];
1997 lock_page(wdata2->pages[j]);
1998 clear_page_dirty_for_io(wdata2->pages[j]);
2001 wdata2->sync_mode = wdata->sync_mode;
2002 wdata2->nr_pages = nr_pages;
2003 wdata2->offset = page_offset(wdata2->pages[0]);
2004 wdata2->pagesz = PAGE_SIZE;
2005 wdata2->tailsz = tailsz;
2006 wdata2->bytes = cur_len;
2008 wdata2->cfile = find_writable_file(CIFS_I(inode), false);
2009 if (!wdata2->cfile) {
2010 cifs_dbg(VFS, "No writable handles for inode\n");
2014 wdata2->pid = wdata2->cfile->pid;
2015 rc = server->ops->async_writev(wdata2, cifs_writedata_release);
2017 for (j = 0; j < nr_pages; j++) {
2018 unlock_page(wdata2->pages[j]);
2019 if (rc != 0 && rc != -EAGAIN) {
2020 SetPageError(wdata2->pages[j]);
2021 end_page_writeback(wdata2->pages[j]);
2022 put_page(wdata2->pages[j]);
2027 kref_put(&wdata2->refcount, cifs_writedata_release);
2033 rest_len -= cur_len;
2035 } while (i < wdata->nr_pages);
2037 mapping_set_error(inode->i_mapping, rc);
2038 kref_put(&wdata->refcount, cifs_writedata_release);
2042 cifs_writev_complete(struct work_struct *work)
2044 struct cifs_writedata *wdata = container_of(work,
2045 struct cifs_writedata, work);
2046 struct inode *inode = d_inode(wdata->cfile->dentry);
2049 if (wdata->result == 0) {
2050 spin_lock(&inode->i_lock);
2051 cifs_update_eof(CIFS_I(inode), wdata->offset, wdata->bytes);
2052 spin_unlock(&inode->i_lock);
2053 cifs_stats_bytes_written(tlink_tcon(wdata->cfile->tlink),
2055 } else if (wdata->sync_mode == WB_SYNC_ALL && wdata->result == -EAGAIN)
2056 return cifs_writev_requeue(wdata);
2058 for (i = 0; i < wdata->nr_pages; i++) {
2059 struct page *page = wdata->pages[i];
2060 if (wdata->result == -EAGAIN)
2061 __set_page_dirty_nobuffers(page);
2062 else if (wdata->result < 0)
2064 end_page_writeback(page);
2067 if (wdata->result != -EAGAIN)
2068 mapping_set_error(inode->i_mapping, wdata->result);
2069 kref_put(&wdata->refcount, cifs_writedata_release);
2072 struct cifs_writedata *
2073 cifs_writedata_alloc(unsigned int nr_pages, work_func_t complete)
2075 struct cifs_writedata *wdata;
2077 /* writedata + number of page pointers */
2078 wdata = kzalloc(sizeof(*wdata) +
2079 sizeof(struct page *) * nr_pages, GFP_NOFS);
2080 if (wdata != NULL) {
2081 kref_init(&wdata->refcount);
2082 INIT_LIST_HEAD(&wdata->list);
2083 init_completion(&wdata->done);
2084 INIT_WORK(&wdata->work, complete);
2090 * Check the mid_state and signature on received buffer (if any), and queue the
2091 * workqueue completion task.
2094 cifs_writev_callback(struct mid_q_entry *mid)
2096 struct cifs_writedata *wdata = mid->callback_data;
2097 struct cifs_tcon *tcon = tlink_tcon(wdata->cfile->tlink);
2098 unsigned int written;
2099 WRITE_RSP *smb = (WRITE_RSP *)mid->resp_buf;
2101 switch (mid->mid_state) {
2102 case MID_RESPONSE_RECEIVED:
2103 wdata->result = cifs_check_receive(mid, tcon->ses->server, 0);
2104 if (wdata->result != 0)
2107 written = le16_to_cpu(smb->CountHigh);
2109 written += le16_to_cpu(smb->Count);
2111 * Mask off high 16 bits when bytes written as returned
2112 * by the server is greater than bytes requested by the
2113 * client. OS/2 servers are known to set incorrect
2116 if (written > wdata->bytes)
2119 if (written < wdata->bytes)
2120 wdata->result = -ENOSPC;
2122 wdata->bytes = written;
2124 case MID_REQUEST_SUBMITTED:
2125 case MID_RETRY_NEEDED:
2126 wdata->result = -EAGAIN;
2129 wdata->result = -EIO;
2133 queue_work(cifsiod_wq, &wdata->work);
2134 DeleteMidQEntry(mid);
2135 add_credits(tcon->ses->server, 1, 0);
2138 /* cifs_async_writev - send an async write, and set up mid to handle result */
2140 cifs_async_writev(struct cifs_writedata *wdata,
2141 void (*release)(struct kref *kref))
2144 WRITE_REQ *smb = NULL;
2146 struct cifs_tcon *tcon = tlink_tcon(wdata->cfile->tlink);
2148 struct smb_rqst rqst = { };
2150 if (tcon->ses->capabilities & CAP_LARGE_FILES) {
2154 if (wdata->offset >> 32 > 0) {
2155 /* can not handle big offset for old srv */
2160 rc = small_smb_init(SMB_COM_WRITE_ANDX, wct, tcon, (void **)&smb);
2162 goto async_writev_out;
2164 smb->hdr.Pid = cpu_to_le16((__u16)wdata->pid);
2165 smb->hdr.PidHigh = cpu_to_le16((__u16)(wdata->pid >> 16));
2167 smb->AndXCommand = 0xFF; /* none */
2168 smb->Fid = wdata->cfile->fid.netfid;
2169 smb->OffsetLow = cpu_to_le32(wdata->offset & 0xFFFFFFFF);
2171 smb->OffsetHigh = cpu_to_le32(wdata->offset >> 32);
2172 smb->Reserved = 0xFFFFFFFF;
2177 cpu_to_le16(offsetof(struct smb_com_write_req, Data) - 4);
2179 /* 4 for RFC1001 length + 1 for BCC */
2181 iov[0].iov_base = smb;
2182 iov[1].iov_len = get_rfc1002_length(smb) + 1;
2183 iov[1].iov_base = (char *)smb + 4;
2187 rqst.rq_pages = wdata->pages;
2188 rqst.rq_npages = wdata->nr_pages;
2189 rqst.rq_pagesz = wdata->pagesz;
2190 rqst.rq_tailsz = wdata->tailsz;
2192 cifs_dbg(FYI, "async write at %llu %u bytes\n",
2193 wdata->offset, wdata->bytes);
2195 smb->DataLengthLow = cpu_to_le16(wdata->bytes & 0xFFFF);
2196 smb->DataLengthHigh = cpu_to_le16(wdata->bytes >> 16);
2199 inc_rfc1001_len(&smb->hdr, wdata->bytes + 1);
2200 put_bcc(wdata->bytes + 1, &smb->hdr);
2203 struct smb_com_writex_req *smbw =
2204 (struct smb_com_writex_req *)smb;
2205 inc_rfc1001_len(&smbw->hdr, wdata->bytes + 5);
2206 put_bcc(wdata->bytes + 5, &smbw->hdr);
2207 iov[1].iov_len += 4; /* pad bigger by four bytes */
2210 kref_get(&wdata->refcount);
2211 rc = cifs_call_async(tcon->ses->server, &rqst, NULL,
2212 cifs_writev_callback, NULL, wdata, 0);
2215 cifs_stats_inc(&tcon->stats.cifs_stats.num_writes);
2217 kref_put(&wdata->refcount, release);
2220 cifs_small_buf_release(smb);
2225 CIFSSMBWrite2(const unsigned int xid, struct cifs_io_parms *io_parms,
2226 unsigned int *nbytes, struct kvec *iov, int n_vec)
2229 WRITE_REQ *pSMB = NULL;
2232 int resp_buf_type = 0;
2233 __u32 pid = io_parms->pid;
2234 __u16 netfid = io_parms->netfid;
2235 __u64 offset = io_parms->offset;
2236 struct cifs_tcon *tcon = io_parms->tcon;
2237 unsigned int count = io_parms->length;
2238 struct kvec rsp_iov;
2242 cifs_dbg(FYI, "write2 at %lld %d bytes\n", (long long)offset, count);
2244 if (tcon->ses->capabilities & CAP_LARGE_FILES) {
2248 if ((offset >> 32) > 0) {
2249 /* can not handle big offset for old srv */
2253 rc = small_smb_init(SMB_COM_WRITE_ANDX, wct, tcon, (void **) &pSMB);
2257 pSMB->hdr.Pid = cpu_to_le16((__u16)pid);
2258 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid >> 16));
2260 /* tcon and ses pointer are checked in smb_init */
2261 if (tcon->ses->server == NULL)
2262 return -ECONNABORTED;
2264 pSMB->AndXCommand = 0xFF; /* none */
2266 pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF);
2268 pSMB->OffsetHigh = cpu_to_le32(offset >> 32);
2269 pSMB->Reserved = 0xFFFFFFFF;
2270 pSMB->WriteMode = 0;
2271 pSMB->Remaining = 0;
2274 cpu_to_le16(offsetof(struct smb_com_write_req, Data) - 4);
2276 pSMB->DataLengthLow = cpu_to_le16(count & 0xFFFF);
2277 pSMB->DataLengthHigh = cpu_to_le16(count >> 16);
2278 /* header + 1 byte pad */
2279 smb_hdr_len = be32_to_cpu(pSMB->hdr.smb_buf_length) + 1;
2281 inc_rfc1001_len(pSMB, count + 1);
2282 else /* wct == 12 */
2283 inc_rfc1001_len(pSMB, count + 5); /* smb data starts later */
2285 pSMB->ByteCount = cpu_to_le16(count + 1);
2286 else /* wct == 12 */ /* bigger pad, smaller smb hdr, keep offset ok */ {
2287 struct smb_com_writex_req *pSMBW =
2288 (struct smb_com_writex_req *)pSMB;
2289 pSMBW->ByteCount = cpu_to_le16(count + 5);
2291 iov[0].iov_base = pSMB;
2293 iov[0].iov_len = smb_hdr_len + 4;
2294 else /* wct == 12 pad bigger by four bytes */
2295 iov[0].iov_len = smb_hdr_len + 8;
2297 rc = SendReceive2(xid, tcon->ses, iov, n_vec + 1, &resp_buf_type, 0,
2299 cifs_small_buf_release(pSMB);
2300 cifs_stats_inc(&tcon->stats.cifs_stats.num_writes);
2302 cifs_dbg(FYI, "Send error Write2 = %d\n", rc);
2303 } else if (resp_buf_type == 0) {
2304 /* presumably this can not happen, but best to be safe */
2307 WRITE_RSP *pSMBr = (WRITE_RSP *)rsp_iov.iov_base;
2308 *nbytes = le16_to_cpu(pSMBr->CountHigh);
2309 *nbytes = (*nbytes) << 16;
2310 *nbytes += le16_to_cpu(pSMBr->Count);
2313 * Mask off high 16 bits when bytes written as returned by the
2314 * server is greater than bytes requested by the client. OS/2
2315 * servers are known to set incorrect CountHigh values.
2317 if (*nbytes > count)
2321 free_rsp_buf(resp_buf_type, rsp_iov.iov_base);
2323 /* Note: On -EAGAIN error only caller can retry on handle based calls
2324 since file handle passed in no longer valid */
2329 int cifs_lockv(const unsigned int xid, struct cifs_tcon *tcon,
2330 const __u16 netfid, const __u8 lock_type, const __u32 num_unlock,
2331 const __u32 num_lock, LOCKING_ANDX_RANGE *buf)
2334 LOCK_REQ *pSMB = NULL;
2336 struct kvec rsp_iov;
2340 cifs_dbg(FYI, "cifs_lockv num lock %d num unlock %d\n",
2341 num_lock, num_unlock);
2343 rc = small_smb_init(SMB_COM_LOCKING_ANDX, 8, tcon, (void **) &pSMB);
2348 pSMB->NumberOfLocks = cpu_to_le16(num_lock);
2349 pSMB->NumberOfUnlocks = cpu_to_le16(num_unlock);
2350 pSMB->LockType = lock_type;
2351 pSMB->AndXCommand = 0xFF; /* none */
2352 pSMB->Fid = netfid; /* netfid stays le */
2354 count = (num_unlock + num_lock) * sizeof(LOCKING_ANDX_RANGE);
2355 inc_rfc1001_len(pSMB, count);
2356 pSMB->ByteCount = cpu_to_le16(count);
2358 iov[0].iov_base = (char *)pSMB;
2359 iov[0].iov_len = be32_to_cpu(pSMB->hdr.smb_buf_length) + 4 -
2360 (num_unlock + num_lock) * sizeof(LOCKING_ANDX_RANGE);
2361 iov[1].iov_base = (char *)buf;
2362 iov[1].iov_len = (num_unlock + num_lock) * sizeof(LOCKING_ANDX_RANGE);
2364 cifs_stats_inc(&tcon->stats.cifs_stats.num_locks);
2365 rc = SendReceive2(xid, tcon->ses, iov, 2, &resp_buf_type, CIFS_NO_RESP,
2367 cifs_small_buf_release(pSMB);
2369 cifs_dbg(FYI, "Send error in cifs_lockv = %d\n", rc);
2375 CIFSSMBLock(const unsigned int xid, struct cifs_tcon *tcon,
2376 const __u16 smb_file_id, const __u32 netpid, const __u64 len,
2377 const __u64 offset, const __u32 numUnlock,
2378 const __u32 numLock, const __u8 lockType,
2379 const bool waitFlag, const __u8 oplock_level)
2382 LOCK_REQ *pSMB = NULL;
2383 /* LOCK_RSP *pSMBr = NULL; */ /* No response data other than rc to parse */
2388 cifs_dbg(FYI, "CIFSSMBLock timeout %d numLock %d\n",
2389 (int)waitFlag, numLock);
2390 rc = small_smb_init(SMB_COM_LOCKING_ANDX, 8, tcon, (void **) &pSMB);
2395 if (lockType == LOCKING_ANDX_OPLOCK_RELEASE) {
2396 /* no response expected */
2397 flags = CIFS_ASYNC_OP | CIFS_OBREAK_OP;
2399 } else if (waitFlag) {
2400 flags = CIFS_BLOCKING_OP; /* blocking operation, no timeout */
2401 pSMB->Timeout = cpu_to_le32(-1);/* blocking - do not time out */
2406 pSMB->NumberOfLocks = cpu_to_le16(numLock);
2407 pSMB->NumberOfUnlocks = cpu_to_le16(numUnlock);
2408 pSMB->LockType = lockType;
2409 pSMB->OplockLevel = oplock_level;
2410 pSMB->AndXCommand = 0xFF; /* none */
2411 pSMB->Fid = smb_file_id; /* netfid stays le */
2413 if ((numLock != 0) || (numUnlock != 0)) {
2414 pSMB->Locks[0].Pid = cpu_to_le16(netpid);
2415 /* BB where to store pid high? */
2416 pSMB->Locks[0].LengthLow = cpu_to_le32((u32)len);
2417 pSMB->Locks[0].LengthHigh = cpu_to_le32((u32)(len>>32));
2418 pSMB->Locks[0].OffsetLow = cpu_to_le32((u32)offset);
2419 pSMB->Locks[0].OffsetHigh = cpu_to_le32((u32)(offset>>32));
2420 count = sizeof(LOCKING_ANDX_RANGE);
2425 inc_rfc1001_len(pSMB, count);
2426 pSMB->ByteCount = cpu_to_le16(count);
2429 rc = SendReceiveBlockingLock(xid, tcon, (struct smb_hdr *) pSMB,
2430 (struct smb_hdr *) pSMB, &bytes_returned);
2432 rc = SendReceiveNoRsp(xid, tcon->ses, (char *)pSMB, flags);
2433 cifs_small_buf_release(pSMB);
2434 cifs_stats_inc(&tcon->stats.cifs_stats.num_locks);
2436 cifs_dbg(FYI, "Send error in Lock = %d\n", rc);
2438 /* Note: On -EAGAIN error only caller can retry on handle based calls
2439 since file handle passed in no longer valid */
2444 CIFSSMBPosixLock(const unsigned int xid, struct cifs_tcon *tcon,
2445 const __u16 smb_file_id, const __u32 netpid,
2446 const loff_t start_offset, const __u64 len,
2447 struct file_lock *pLockData, const __u16 lock_type,
2448 const bool waitFlag)
2450 struct smb_com_transaction2_sfi_req *pSMB = NULL;
2451 struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
2452 struct cifs_posix_lock *parm_data;
2455 int bytes_returned = 0;
2456 int resp_buf_type = 0;
2457 __u16 params, param_offset, offset, byte_count, count;
2459 struct kvec rsp_iov;
2461 cifs_dbg(FYI, "Posix Lock\n");
2463 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
2468 pSMBr = (struct smb_com_transaction2_sfi_rsp *)pSMB;
2471 pSMB->MaxSetupCount = 0;
2474 pSMB->Reserved2 = 0;
2475 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
2476 offset = param_offset + params;
2478 count = sizeof(struct cifs_posix_lock);
2479 pSMB->MaxParameterCount = cpu_to_le16(2);
2480 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB from sess */
2481 pSMB->SetupCount = 1;
2482 pSMB->Reserved3 = 0;
2484 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION);
2486 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
2487 byte_count = 3 /* pad */ + params + count;
2488 pSMB->DataCount = cpu_to_le16(count);
2489 pSMB->ParameterCount = cpu_to_le16(params);
2490 pSMB->TotalDataCount = pSMB->DataCount;
2491 pSMB->TotalParameterCount = pSMB->ParameterCount;
2492 pSMB->ParameterOffset = cpu_to_le16(param_offset);
2493 parm_data = (struct cifs_posix_lock *)
2494 (((char *) &pSMB->hdr.Protocol) + offset);
2496 parm_data->lock_type = cpu_to_le16(lock_type);
2498 timeout = CIFS_BLOCKING_OP; /* blocking operation, no timeout */
2499 parm_data->lock_flags = cpu_to_le16(1);
2500 pSMB->Timeout = cpu_to_le32(-1);
2504 parm_data->pid = cpu_to_le32(netpid);
2505 parm_data->start = cpu_to_le64(start_offset);
2506 parm_data->length = cpu_to_le64(len); /* normalize negative numbers */
2508 pSMB->DataOffset = cpu_to_le16(offset);
2509 pSMB->Fid = smb_file_id;
2510 pSMB->InformationLevel = cpu_to_le16(SMB_SET_POSIX_LOCK);
2511 pSMB->Reserved4 = 0;
2512 inc_rfc1001_len(pSMB, byte_count);
2513 pSMB->ByteCount = cpu_to_le16(byte_count);
2515 rc = SendReceiveBlockingLock(xid, tcon, (struct smb_hdr *) pSMB,
2516 (struct smb_hdr *) pSMBr, &bytes_returned);
2518 iov[0].iov_base = (char *)pSMB;
2519 iov[0].iov_len = be32_to_cpu(pSMB->hdr.smb_buf_length) + 4;
2520 rc = SendReceive2(xid, tcon->ses, iov, 1 /* num iovecs */,
2521 &resp_buf_type, timeout, &rsp_iov);
2522 pSMBr = (struct smb_com_transaction2_sfi_rsp *)rsp_iov.iov_base;
2524 cifs_small_buf_release(pSMB);
2527 cifs_dbg(FYI, "Send error in Posix Lock = %d\n", rc);
2528 } else if (pLockData) {
2529 /* lock structure can be returned on get */
2532 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
2534 if (rc || get_bcc(&pSMBr->hdr) < sizeof(*parm_data)) {
2535 rc = -EIO; /* bad smb */
2538 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
2539 data_count = le16_to_cpu(pSMBr->t2.DataCount);
2540 if (data_count < sizeof(struct cifs_posix_lock)) {
2544 parm_data = (struct cifs_posix_lock *)
2545 ((char *)&pSMBr->hdr.Protocol + data_offset);
2546 if (parm_data->lock_type == cpu_to_le16(CIFS_UNLCK))
2547 pLockData->fl_type = F_UNLCK;
2549 if (parm_data->lock_type ==
2550 cpu_to_le16(CIFS_RDLCK))
2551 pLockData->fl_type = F_RDLCK;
2552 else if (parm_data->lock_type ==
2553 cpu_to_le16(CIFS_WRLCK))
2554 pLockData->fl_type = F_WRLCK;
2556 pLockData->fl_start = le64_to_cpu(parm_data->start);
2557 pLockData->fl_end = pLockData->fl_start +
2558 le64_to_cpu(parm_data->length) - 1;
2559 pLockData->fl_pid = -le32_to_cpu(parm_data->pid);
2564 free_rsp_buf(resp_buf_type, rsp_iov.iov_base);
2566 /* Note: On -EAGAIN error only caller can retry on handle based calls
2567 since file handle passed in no longer valid */
2574 CIFSSMBClose(const unsigned int xid, struct cifs_tcon *tcon, int smb_file_id)
2577 CLOSE_REQ *pSMB = NULL;
2578 cifs_dbg(FYI, "In CIFSSMBClose\n");
2580 /* do not retry on dead session on close */
2581 rc = small_smb_init(SMB_COM_CLOSE, 3, tcon, (void **) &pSMB);
2587 pSMB->FileID = (__u16) smb_file_id;
2588 pSMB->LastWriteTime = 0xFFFFFFFF;
2589 pSMB->ByteCount = 0;
2590 rc = SendReceiveNoRsp(xid, tcon->ses, (char *) pSMB, 0);
2591 cifs_small_buf_release(pSMB);
2592 cifs_stats_inc(&tcon->stats.cifs_stats.num_closes);
2595 /* EINTR is expected when user ctl-c to kill app */
2596 cifs_dbg(VFS, "Send error in Close = %d\n", rc);
2600 /* Since session is dead, file will be closed on server already */
2608 CIFSSMBFlush(const unsigned int xid, struct cifs_tcon *tcon, int smb_file_id)
2611 FLUSH_REQ *pSMB = NULL;
2612 cifs_dbg(FYI, "In CIFSSMBFlush\n");
2614 rc = small_smb_init(SMB_COM_FLUSH, 1, tcon, (void **) &pSMB);
2618 pSMB->FileID = (__u16) smb_file_id;
2619 pSMB->ByteCount = 0;
2620 rc = SendReceiveNoRsp(xid, tcon->ses, (char *) pSMB, 0);
2621 cifs_small_buf_release(pSMB);
2622 cifs_stats_inc(&tcon->stats.cifs_stats.num_flushes);
2624 cifs_dbg(VFS, "Send error in Flush = %d\n", rc);
2630 CIFSSMBRename(const unsigned int xid, struct cifs_tcon *tcon,
2631 const char *from_name, const char *to_name,
2632 struct cifs_sb_info *cifs_sb)
2635 RENAME_REQ *pSMB = NULL;
2636 RENAME_RSP *pSMBr = NULL;
2638 int name_len, name_len2;
2640 int remap = cifs_remap(cifs_sb);
2642 cifs_dbg(FYI, "In CIFSSMBRename\n");
2644 rc = smb_init(SMB_COM_RENAME, 1, tcon, (void **) &pSMB,
2649 pSMB->BufferFormat = 0x04;
2650 pSMB->SearchAttributes =
2651 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
2654 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2655 name_len = cifsConvertToUTF16((__le16 *) pSMB->OldFileName,
2656 from_name, PATH_MAX,
2657 cifs_sb->local_nls, remap);
2658 name_len++; /* trailing null */
2660 pSMB->OldFileName[name_len] = 0x04; /* pad */
2661 /* protocol requires ASCII signature byte on Unicode string */
2662 pSMB->OldFileName[name_len + 1] = 0x00;
2664 cifsConvertToUTF16((__le16 *)&pSMB->OldFileName[name_len+2],
2665 to_name, PATH_MAX, cifs_sb->local_nls,
2667 name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
2668 name_len2 *= 2; /* convert to bytes */
2669 } else { /* BB improve the check for buffer overruns BB */
2670 name_len = strnlen(from_name, PATH_MAX);
2671 name_len++; /* trailing null */
2672 strncpy(pSMB->OldFileName, from_name, name_len);
2673 name_len2 = strnlen(to_name, PATH_MAX);
2674 name_len2++; /* trailing null */
2675 pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */
2676 strncpy(&pSMB->OldFileName[name_len + 1], to_name, name_len2);
2677 name_len2++; /* trailing null */
2678 name_len2++; /* signature byte */
2681 count = 1 /* 1st signature byte */ + name_len + name_len2;
2682 inc_rfc1001_len(pSMB, count);
2683 pSMB->ByteCount = cpu_to_le16(count);
2685 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2686 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2687 cifs_stats_inc(&tcon->stats.cifs_stats.num_renames);
2689 cifs_dbg(FYI, "Send error in rename = %d\n", rc);
2691 cifs_buf_release(pSMB);
2699 int CIFSSMBRenameOpenFile(const unsigned int xid, struct cifs_tcon *pTcon,
2700 int netfid, const char *target_name,
2701 const struct nls_table *nls_codepage, int remap)
2703 struct smb_com_transaction2_sfi_req *pSMB = NULL;
2704 struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
2705 struct set_file_rename *rename_info;
2707 char dummy_string[30];
2709 int bytes_returned = 0;
2711 __u16 params, param_offset, offset, count, byte_count;
2713 cifs_dbg(FYI, "Rename to File by handle\n");
2714 rc = smb_init(SMB_COM_TRANSACTION2, 15, pTcon, (void **) &pSMB,
2720 pSMB->MaxSetupCount = 0;
2724 pSMB->Reserved2 = 0;
2725 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
2726 offset = param_offset + params;
2728 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
2729 rename_info = (struct set_file_rename *) data_offset;
2730 pSMB->MaxParameterCount = cpu_to_le16(2);
2731 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB from sess */
2732 pSMB->SetupCount = 1;
2733 pSMB->Reserved3 = 0;
2734 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
2735 byte_count = 3 /* pad */ + params;
2736 pSMB->ParameterCount = cpu_to_le16(params);
2737 pSMB->TotalParameterCount = pSMB->ParameterCount;
2738 pSMB->ParameterOffset = cpu_to_le16(param_offset);
2739 pSMB->DataOffset = cpu_to_le16(offset);
2740 /* construct random name ".cifs_tmp<inodenum><mid>" */
2741 rename_info->overwrite = cpu_to_le32(1);
2742 rename_info->root_fid = 0;
2743 /* unicode only call */
2744 if (target_name == NULL) {
2745 sprintf(dummy_string, "cifs%x", pSMB->hdr.Mid);
2747 cifsConvertToUTF16((__le16 *)rename_info->target_name,
2748 dummy_string, 24, nls_codepage, remap);
2751 cifsConvertToUTF16((__le16 *)rename_info->target_name,
2752 target_name, PATH_MAX, nls_codepage,
2755 rename_info->target_name_len = cpu_to_le32(2 * len_of_str);
2756 count = 12 /* sizeof(struct set_file_rename) */ + (2 * len_of_str);
2757 byte_count += count;
2758 pSMB->DataCount = cpu_to_le16(count);
2759 pSMB->TotalDataCount = pSMB->DataCount;
2761 pSMB->InformationLevel =
2762 cpu_to_le16(SMB_SET_FILE_RENAME_INFORMATION);
2763 pSMB->Reserved4 = 0;
2764 inc_rfc1001_len(pSMB, byte_count);
2765 pSMB->ByteCount = cpu_to_le16(byte_count);
2766 rc = SendReceive(xid, pTcon->ses, (struct smb_hdr *) pSMB,
2767 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2768 cifs_stats_inc(&pTcon->stats.cifs_stats.num_t2renames);
2770 cifs_dbg(FYI, "Send error in Rename (by file handle) = %d\n",
2773 cifs_buf_release(pSMB);
2775 /* Note: On -EAGAIN error only caller can retry on handle based calls
2776 since file handle passed in no longer valid */
2782 CIFSSMBCopy(const unsigned int xid, struct cifs_tcon *tcon,
2783 const char *fromName, const __u16 target_tid, const char *toName,
2784 const int flags, const struct nls_table *nls_codepage, int remap)
2787 COPY_REQ *pSMB = NULL;
2788 COPY_RSP *pSMBr = NULL;
2790 int name_len, name_len2;
2793 cifs_dbg(FYI, "In CIFSSMBCopy\n");
2795 rc = smb_init(SMB_COM_COPY, 1, tcon, (void **) &pSMB,
2800 pSMB->BufferFormat = 0x04;
2801 pSMB->Tid2 = target_tid;
2803 pSMB->Flags = cpu_to_le16(flags & COPY_TREE);
2805 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2806 name_len = cifsConvertToUTF16((__le16 *) pSMB->OldFileName,
2807 fromName, PATH_MAX, nls_codepage,
2809 name_len++; /* trailing null */
2811 pSMB->OldFileName[name_len] = 0x04; /* pad */
2812 /* protocol requires ASCII signature byte on Unicode string */
2813 pSMB->OldFileName[name_len + 1] = 0x00;
2815 cifsConvertToUTF16((__le16 *)&pSMB->OldFileName[name_len+2],
2816 toName, PATH_MAX, nls_codepage, remap);
2817 name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
2818 name_len2 *= 2; /* convert to bytes */
2819 } else { /* BB improve the check for buffer overruns BB */
2820 name_len = strnlen(fromName, PATH_MAX);
2821 name_len++; /* trailing null */
2822 strncpy(pSMB->OldFileName, fromName, name_len);
2823 name_len2 = strnlen(toName, PATH_MAX);
2824 name_len2++; /* trailing null */
2825 pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */
2826 strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2);
2827 name_len2++; /* trailing null */
2828 name_len2++; /* signature byte */
2831 count = 1 /* 1st signature byte */ + name_len + name_len2;
2832 inc_rfc1001_len(pSMB, count);
2833 pSMB->ByteCount = cpu_to_le16(count);
2835 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2836 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2838 cifs_dbg(FYI, "Send error in copy = %d with %d files copied\n",
2839 rc, le16_to_cpu(pSMBr->CopyCount));
2841 cifs_buf_release(pSMB);
2850 CIFSUnixCreateSymLink(const unsigned int xid, struct cifs_tcon *tcon,
2851 const char *fromName, const char *toName,
2852 const struct nls_table *nls_codepage, int remap)
2854 TRANSACTION2_SPI_REQ *pSMB = NULL;
2855 TRANSACTION2_SPI_RSP *pSMBr = NULL;
2858 int name_len_target;
2860 int bytes_returned = 0;
2861 __u16 params, param_offset, offset, byte_count;
2863 cifs_dbg(FYI, "In Symlink Unix style\n");
2865 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2870 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2872 cifsConvertToUTF16((__le16 *) pSMB->FileName, fromName,
2873 /* find define for this maxpathcomponent */
2874 PATH_MAX, nls_codepage, remap);
2875 name_len++; /* trailing null */
2878 } else { /* BB improve the check for buffer overruns BB */
2879 name_len = strnlen(fromName, PATH_MAX);
2880 name_len++; /* trailing null */
2881 strncpy(pSMB->FileName, fromName, name_len);
2883 params = 6 + name_len;
2884 pSMB->MaxSetupCount = 0;
2888 pSMB->Reserved2 = 0;
2889 param_offset = offsetof(struct smb_com_transaction2_spi_req,
2890 InformationLevel) - 4;
2891 offset = param_offset + params;
2893 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
2894 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2896 cifsConvertToUTF16((__le16 *) data_offset, toName,
2897 /* find define for this maxpathcomponent */
2898 PATH_MAX, nls_codepage, remap);
2899 name_len_target++; /* trailing null */
2900 name_len_target *= 2;
2901 } else { /* BB improve the check for buffer overruns BB */
2902 name_len_target = strnlen(toName, PATH_MAX);
2903 name_len_target++; /* trailing null */
2904 strncpy(data_offset, toName, name_len_target);
2907 pSMB->MaxParameterCount = cpu_to_le16(2);
2908 /* BB find exact max on data count below from sess */
2909 pSMB->MaxDataCount = cpu_to_le16(1000);
2910 pSMB->SetupCount = 1;
2911 pSMB->Reserved3 = 0;
2912 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
2913 byte_count = 3 /* pad */ + params + name_len_target;
2914 pSMB->DataCount = cpu_to_le16(name_len_target);
2915 pSMB->ParameterCount = cpu_to_le16(params);
2916 pSMB->TotalDataCount = pSMB->DataCount;
2917 pSMB->TotalParameterCount = pSMB->ParameterCount;
2918 pSMB->ParameterOffset = cpu_to_le16(param_offset);
2919 pSMB->DataOffset = cpu_to_le16(offset);
2920 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_LINK);
2921 pSMB->Reserved4 = 0;
2922 inc_rfc1001_len(pSMB, byte_count);
2923 pSMB->ByteCount = cpu_to_le16(byte_count);
2924 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2925 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2926 cifs_stats_inc(&tcon->stats.cifs_stats.num_symlinks);
2928 cifs_dbg(FYI, "Send error in SetPathInfo create symlink = %d\n",
2931 cifs_buf_release(pSMB);
2934 goto createSymLinkRetry;
2940 CIFSUnixCreateHardLink(const unsigned int xid, struct cifs_tcon *tcon,
2941 const char *fromName, const char *toName,
2942 const struct nls_table *nls_codepage, int remap)
2944 TRANSACTION2_SPI_REQ *pSMB = NULL;
2945 TRANSACTION2_SPI_RSP *pSMBr = NULL;
2948 int name_len_target;
2950 int bytes_returned = 0;
2951 __u16 params, param_offset, offset, byte_count;
2953 cifs_dbg(FYI, "In Create Hard link Unix style\n");
2954 createHardLinkRetry:
2955 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2960 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2961 name_len = cifsConvertToUTF16((__le16 *) pSMB->FileName, toName,
2962 PATH_MAX, nls_codepage, remap);
2963 name_len++; /* trailing null */
2966 } else { /* BB improve the check for buffer overruns BB */
2967 name_len = strnlen(toName, PATH_MAX);
2968 name_len++; /* trailing null */
2969 strncpy(pSMB->FileName, toName, name_len);
2971 params = 6 + name_len;
2972 pSMB->MaxSetupCount = 0;
2976 pSMB->Reserved2 = 0;
2977 param_offset = offsetof(struct smb_com_transaction2_spi_req,
2978 InformationLevel) - 4;
2979 offset = param_offset + params;
2981 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
2982 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2984 cifsConvertToUTF16((__le16 *) data_offset, fromName,
2985 PATH_MAX, nls_codepage, remap);
2986 name_len_target++; /* trailing null */
2987 name_len_target *= 2;
2988 } else { /* BB improve the check for buffer overruns BB */
2989 name_len_target = strnlen(fromName, PATH_MAX);
2990 name_len_target++; /* trailing null */
2991 strncpy(data_offset, fromName, name_len_target);
2994 pSMB->MaxParameterCount = cpu_to_le16(2);
2995 /* BB find exact max on data count below from sess*/
2996 pSMB->MaxDataCount = cpu_to_le16(1000);
2997 pSMB->SetupCount = 1;
2998 pSMB->Reserved3 = 0;
2999 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
3000 byte_count = 3 /* pad */ + params + name_len_target;
3001 pSMB->ParameterCount = cpu_to_le16(params);
3002 pSMB->TotalParameterCount = pSMB->ParameterCount;
3003 pSMB->DataCount = cpu_to_le16(name_len_target);
3004 pSMB->TotalDataCount = pSMB->DataCount;
3005 pSMB->ParameterOffset = cpu_to_le16(param_offset);
3006 pSMB->DataOffset = cpu_to_le16(offset);
3007 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_HLINK);
3008 pSMB->Reserved4 = 0;
3009 inc_rfc1001_len(pSMB, byte_count);
3010 pSMB->ByteCount = cpu_to_le16(byte_count);
3011 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3012 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3013 cifs_stats_inc(&tcon->stats.cifs_stats.num_hardlinks);
3015 cifs_dbg(FYI, "Send error in SetPathInfo (hard link) = %d\n",
3018 cifs_buf_release(pSMB);
3020 goto createHardLinkRetry;
3026 CIFSCreateHardLink(const unsigned int xid, struct cifs_tcon *tcon,
3027 const char *from_name, const char *to_name,
3028 struct cifs_sb_info *cifs_sb)
3031 NT_RENAME_REQ *pSMB = NULL;
3032 RENAME_RSP *pSMBr = NULL;
3034 int name_len, name_len2;
3036 int remap = cifs_remap(cifs_sb);
3038 cifs_dbg(FYI, "In CIFSCreateHardLink\n");
3039 winCreateHardLinkRetry:
3041 rc = smb_init(SMB_COM_NT_RENAME, 4, tcon, (void **) &pSMB,
3046 pSMB->SearchAttributes =
3047 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
3049 pSMB->Flags = cpu_to_le16(CREATE_HARD_LINK);
3050 pSMB->ClusterCount = 0;
3052 pSMB->BufferFormat = 0x04;
3054 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3056 cifsConvertToUTF16((__le16 *) pSMB->OldFileName, from_name,
3057 PATH_MAX, cifs_sb->local_nls, remap);
3058 name_len++; /* trailing null */
3061 /* protocol specifies ASCII buffer format (0x04) for unicode */
3062 pSMB->OldFileName[name_len] = 0x04;
3063 pSMB->OldFileName[name_len + 1] = 0x00; /* pad */
3065 cifsConvertToUTF16((__le16 *)&pSMB->OldFileName[name_len+2],
3066 to_name, PATH_MAX, cifs_sb->local_nls,
3068 name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
3069 name_len2 *= 2; /* convert to bytes */
3070 } else { /* BB improve the check for buffer overruns BB */
3071 name_len = strnlen(from_name, PATH_MAX);
3072 name_len++; /* trailing null */
3073 strncpy(pSMB->OldFileName, from_name, name_len);
3074 name_len2 = strnlen(to_name, PATH_MAX);
3075 name_len2++; /* trailing null */
3076 pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */
3077 strncpy(&pSMB->OldFileName[name_len + 1], to_name, name_len2);
3078 name_len2++; /* trailing null */
3079 name_len2++; /* signature byte */
3082 count = 1 /* string type byte */ + name_len + name_len2;
3083 inc_rfc1001_len(pSMB, count);
3084 pSMB->ByteCount = cpu_to_le16(count);
3086 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3087 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3088 cifs_stats_inc(&tcon->stats.cifs_stats.num_hardlinks);
3090 cifs_dbg(FYI, "Send error in hard link (NT rename) = %d\n", rc);
3092 cifs_buf_release(pSMB);
3094 goto winCreateHardLinkRetry;
3100 CIFSSMBUnixQuerySymLink(const unsigned int xid, struct cifs_tcon *tcon,
3101 const unsigned char *searchName, char **symlinkinfo,
3102 const struct nls_table *nls_codepage, int remap)
3104 /* SMB_QUERY_FILE_UNIX_LINK */
3105 TRANSACTION2_QPI_REQ *pSMB = NULL;
3106 TRANSACTION2_QPI_RSP *pSMBr = NULL;
3110 __u16 params, byte_count;
3113 cifs_dbg(FYI, "In QPathSymLinkInfo (Unix) for path %s\n", searchName);
3116 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3121 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3123 cifsConvertToUTF16((__le16 *) pSMB->FileName,
3124 searchName, PATH_MAX, nls_codepage,
3126 name_len++; /* trailing null */
3128 } else { /* BB improve the check for buffer overruns BB */
3129 name_len = strnlen(searchName, PATH_MAX);
3130 name_len++; /* trailing null */
3131 strncpy(pSMB->FileName, searchName, name_len);
3134 params = 2 /* level */ + 4 /* rsrvd */ + name_len /* incl null */ ;
3135 pSMB->TotalDataCount = 0;
3136 pSMB->MaxParameterCount = cpu_to_le16(2);
3137 pSMB->MaxDataCount = cpu_to_le16(CIFSMaxBufSize);
3138 pSMB->MaxSetupCount = 0;
3142 pSMB->Reserved2 = 0;
3143 pSMB->ParameterOffset = cpu_to_le16(offsetof(
3144 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
3145 pSMB->DataCount = 0;
3146 pSMB->DataOffset = 0;
3147 pSMB->SetupCount = 1;
3148 pSMB->Reserved3 = 0;
3149 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
3150 byte_count = params + 1 /* pad */ ;
3151 pSMB->TotalParameterCount = cpu_to_le16(params);
3152 pSMB->ParameterCount = pSMB->TotalParameterCount;
3153 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_LINK);
3154 pSMB->Reserved4 = 0;
3155 inc_rfc1001_len(pSMB, byte_count);
3156 pSMB->ByteCount = cpu_to_le16(byte_count);
3158 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3159 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3161 cifs_dbg(FYI, "Send error in QuerySymLinkInfo = %d\n", rc);
3163 /* decode response */
3165 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3166 /* BB also check enough total bytes returned */
3167 if (rc || get_bcc(&pSMBr->hdr) < 2)
3171 u16 count = le16_to_cpu(pSMBr->t2.DataCount);
3173 data_start = ((char *) &pSMBr->hdr.Protocol) +
3174 le16_to_cpu(pSMBr->t2.DataOffset);
3176 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
3181 /* BB FIXME investigate remapping reserved chars here */
3182 *symlinkinfo = cifs_strndup_from_utf16(data_start,
3183 count, is_unicode, nls_codepage);
3188 cifs_buf_release(pSMB);
3190 goto querySymLinkRetry;
3195 * Recent Windows versions now create symlinks more frequently
3196 * and they use the "reparse point" mechanism below. We can of course
3197 * do symlinks nicely to Samba and other servers which support the
3198 * CIFS Unix Extensions and we can also do SFU symlinks and "client only"
3199 * "MF" symlinks optionally, but for recent Windows we really need to
3200 * reenable the code below and fix the cifs_symlink callers to handle this.
3201 * In the interim this code has been moved to its own config option so
3202 * it is not compiled in by default until callers fixed up and more tested.
3205 CIFSSMBQuerySymLink(const unsigned int xid, struct cifs_tcon *tcon,
3206 __u16 fid, char **symlinkinfo,
3207 const struct nls_table *nls_codepage)
3211 struct smb_com_transaction_ioctl_req *pSMB;
3212 struct smb_com_transaction_ioctl_rsp *pSMBr;
3214 unsigned int sub_len;
3216 struct reparse_symlink_data *reparse_buf;
3217 struct reparse_posix_data *posix_buf;
3218 __u32 data_offset, data_count;
3221 cifs_dbg(FYI, "In Windows reparse style QueryLink for fid %u\n", fid);
3222 rc = smb_init(SMB_COM_NT_TRANSACT, 23, tcon, (void **) &pSMB,
3227 pSMB->TotalParameterCount = 0 ;
3228 pSMB->TotalDataCount = 0;
3229 pSMB->MaxParameterCount = cpu_to_le32(2);
3230 /* BB find exact data count max from sess structure BB */
3231 pSMB->MaxDataCount = cpu_to_le32(CIFSMaxBufSize & 0xFFFFFF00);
3232 pSMB->MaxSetupCount = 4;
3234 pSMB->ParameterOffset = 0;
3235 pSMB->DataCount = 0;
3236 pSMB->DataOffset = 0;
3237 pSMB->SetupCount = 4;
3238 pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_IOCTL);
3239 pSMB->ParameterCount = pSMB->TotalParameterCount;
3240 pSMB->FunctionCode = cpu_to_le32(FSCTL_GET_REPARSE_POINT);
3241 pSMB->IsFsctl = 1; /* FSCTL */
3242 pSMB->IsRootFlag = 0;
3243 pSMB->Fid = fid; /* file handle always le */
3244 pSMB->ByteCount = 0;
3246 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3247 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3249 cifs_dbg(FYI, "Send error in QueryReparseLinkInfo = %d\n", rc);
3253 data_offset = le32_to_cpu(pSMBr->DataOffset);
3254 data_count = le32_to_cpu(pSMBr->DataCount);
3255 if (get_bcc(&pSMBr->hdr) < 2 || data_offset > 512) {
3256 /* BB also check enough total bytes returned */
3257 rc = -EIO; /* bad smb */
3260 if (!data_count || (data_count > 2048)) {
3262 cifs_dbg(FYI, "Invalid return data count on get reparse info ioctl\n");
3265 end_of_smb = 2 + get_bcc(&pSMBr->hdr) + (char *)&pSMBr->ByteCount;
3266 reparse_buf = (struct reparse_symlink_data *)
3267 ((char *)&pSMBr->hdr.Protocol + data_offset);
3268 if ((char *)reparse_buf >= end_of_smb) {
3272 if (reparse_buf->ReparseTag == cpu_to_le32(IO_REPARSE_TAG_NFS)) {
3273 cifs_dbg(FYI, "NFS style reparse tag\n");
3274 posix_buf = (struct reparse_posix_data *)reparse_buf;
3276 if (posix_buf->InodeType != cpu_to_le64(NFS_SPECFILE_LNK)) {
3277 cifs_dbg(FYI, "unsupported file type 0x%llx\n",
3278 le64_to_cpu(posix_buf->InodeType));
3283 sub_len = le16_to_cpu(reparse_buf->ReparseDataLength);
3284 if (posix_buf->PathBuffer + sub_len > end_of_smb) {
3285 cifs_dbg(FYI, "reparse buf beyond SMB\n");
3289 *symlinkinfo = cifs_strndup_from_utf16(posix_buf->PathBuffer,
3290 sub_len, is_unicode, nls_codepage);
3292 } else if (reparse_buf->ReparseTag !=
3293 cpu_to_le32(IO_REPARSE_TAG_SYMLINK)) {
3298 /* Reparse tag is NTFS symlink */
3299 sub_start = le16_to_cpu(reparse_buf->SubstituteNameOffset) +
3300 reparse_buf->PathBuffer;
3301 sub_len = le16_to_cpu(reparse_buf->SubstituteNameLength);
3302 if (sub_start + sub_len > end_of_smb) {
3303 cifs_dbg(FYI, "reparse buf beyond SMB\n");
3307 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
3312 /* BB FIXME investigate remapping reserved chars here */
3313 *symlinkinfo = cifs_strndup_from_utf16(sub_start, sub_len, is_unicode,
3318 cifs_buf_release(pSMB);
3321 * Note: On -EAGAIN error only caller can retry on handle based calls
3322 * since file handle passed in no longer valid.
3328 CIFSSMB_set_compression(const unsigned int xid, struct cifs_tcon *tcon,
3333 struct smb_com_transaction_compr_ioctl_req *pSMB;
3334 struct smb_com_transaction_ioctl_rsp *pSMBr;
3336 cifs_dbg(FYI, "Set compression for %u\n", fid);
3337 rc = smb_init(SMB_COM_NT_TRANSACT, 23, tcon, (void **) &pSMB,
3342 pSMB->compression_state = cpu_to_le16(COMPRESSION_FORMAT_DEFAULT);
3344 pSMB->TotalParameterCount = 0;
3345 pSMB->TotalDataCount = cpu_to_le32(2);
3346 pSMB->MaxParameterCount = 0;
3347 pSMB->MaxDataCount = 0;
3348 pSMB->MaxSetupCount = 4;
3350 pSMB->ParameterOffset = 0;
3351 pSMB->DataCount = cpu_to_le32(2);
3353 cpu_to_le32(offsetof(struct smb_com_transaction_compr_ioctl_req,
3354 compression_state) - 4); /* 84 */
3355 pSMB->SetupCount = 4;
3356 pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_IOCTL);
3357 pSMB->ParameterCount = 0;
3358 pSMB->FunctionCode = cpu_to_le32(FSCTL_SET_COMPRESSION);
3359 pSMB->IsFsctl = 1; /* FSCTL */
3360 pSMB->IsRootFlag = 0;
3361 pSMB->Fid = fid; /* file handle always le */
3362 /* 3 byte pad, followed by 2 byte compress state */
3363 pSMB->ByteCount = cpu_to_le16(5);
3364 inc_rfc1001_len(pSMB, 5);
3366 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3367 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3369 cifs_dbg(FYI, "Send error in SetCompression = %d\n", rc);
3371 cifs_buf_release(pSMB);
3374 * Note: On -EAGAIN error only caller can retry on handle based calls
3375 * since file handle passed in no longer valid.
3381 #ifdef CONFIG_CIFS_POSIX
3383 /*Convert an Access Control Entry from wire format to local POSIX xattr format*/
3384 static void cifs_convert_ace(struct posix_acl_xattr_entry *ace,
3385 struct cifs_posix_ace *cifs_ace)
3387 /* u8 cifs fields do not need le conversion */
3388 ace->e_perm = cpu_to_le16(cifs_ace->cifs_e_perm);
3389 ace->e_tag = cpu_to_le16(cifs_ace->cifs_e_tag);
3390 ace->e_id = cpu_to_le32(le64_to_cpu(cifs_ace->cifs_uid));
3392 cifs_dbg(FYI, "perm %d tag %d id %d\n",
3393 ace->e_perm, ace->e_tag, ace->e_id);
3399 /* Convert ACL from CIFS POSIX wire format to local Linux POSIX ACL xattr */
3400 static int cifs_copy_posix_acl(char *trgt, char *src, const int buflen,
3401 const int acl_type, const int size_of_data_area)
3406 struct cifs_posix_ace *pACE;
3407 struct cifs_posix_acl *cifs_acl = (struct cifs_posix_acl *)src;
3408 struct posix_acl_xattr_header *local_acl = (void *)trgt;
3410 if (le16_to_cpu(cifs_acl->version) != CIFS_ACL_VERSION)
3413 if (acl_type == ACL_TYPE_ACCESS) {
3414 count = le16_to_cpu(cifs_acl->access_entry_count);
3415 pACE = &cifs_acl->ace_array[0];
3416 size = sizeof(struct cifs_posix_acl);
3417 size += sizeof(struct cifs_posix_ace) * count;
3418 /* check if we would go beyond end of SMB */
3419 if (size_of_data_area < size) {
3420 cifs_dbg(FYI, "bad CIFS POSIX ACL size %d vs. %d\n",
3421 size_of_data_area, size);
3424 } else if (acl_type == ACL_TYPE_DEFAULT) {
3425 count = le16_to_cpu(cifs_acl->access_entry_count);
3426 size = sizeof(struct cifs_posix_acl);
3427 size += sizeof(struct cifs_posix_ace) * count;
3428 /* skip past access ACEs to get to default ACEs */
3429 pACE = &cifs_acl->ace_array[count];
3430 count = le16_to_cpu(cifs_acl->default_entry_count);
3431 size += sizeof(struct cifs_posix_ace) * count;
3432 /* check if we would go beyond end of SMB */
3433 if (size_of_data_area < size)
3440 size = posix_acl_xattr_size(count);
3441 if ((buflen == 0) || (local_acl == NULL)) {
3442 /* used to query ACL EA size */
3443 } else if (size > buflen) {
3445 } else /* buffer big enough */ {
3446 struct posix_acl_xattr_entry *ace = (void *)(local_acl + 1);
3448 local_acl->a_version = cpu_to_le32(POSIX_ACL_XATTR_VERSION);
3449 for (i = 0; i < count ; i++) {
3450 cifs_convert_ace(&ace[i], pACE);
3457 static __u16 convert_ace_to_cifs_ace(struct cifs_posix_ace *cifs_ace,
3458 const struct posix_acl_xattr_entry *local_ace)
3460 __u16 rc = 0; /* 0 = ACL converted ok */
3462 cifs_ace->cifs_e_perm = le16_to_cpu(local_ace->e_perm);
3463 cifs_ace->cifs_e_tag = le16_to_cpu(local_ace->e_tag);
3464 /* BB is there a better way to handle the large uid? */
3465 if (local_ace->e_id == cpu_to_le32(-1)) {
3466 /* Probably no need to le convert -1 on any arch but can not hurt */
3467 cifs_ace->cifs_uid = cpu_to_le64(-1);
3469 cifs_ace->cifs_uid = cpu_to_le64(le32_to_cpu(local_ace->e_id));
3471 cifs_dbg(FYI, "perm %d tag %d id %d\n",
3472 ace->e_perm, ace->e_tag, ace->e_id);
3477 /* Convert ACL from local Linux POSIX xattr to CIFS POSIX ACL wire format */
3478 static __u16 ACL_to_cifs_posix(char *parm_data, const char *pACL,
3479 const int buflen, const int acl_type)
3482 struct cifs_posix_acl *cifs_acl = (struct cifs_posix_acl *)parm_data;
3483 struct posix_acl_xattr_header *local_acl = (void *)pACL;
3484 struct posix_acl_xattr_entry *ace = (void *)(local_acl + 1);
3488 if ((buflen == 0) || (pACL == NULL) || (cifs_acl == NULL))
3491 count = posix_acl_xattr_count((size_t)buflen);
3492 cifs_dbg(FYI, "setting acl with %d entries from buf of length %d and version of %d\n",
3493 count, buflen, le32_to_cpu(local_acl->a_version));
3494 if (le32_to_cpu(local_acl->a_version) != 2) {
3495 cifs_dbg(FYI, "unknown POSIX ACL version %d\n",
3496 le32_to_cpu(local_acl->a_version));
3499 cifs_acl->version = cpu_to_le16(1);
3500 if (acl_type == ACL_TYPE_ACCESS) {
3501 cifs_acl->access_entry_count = cpu_to_le16(count);
3502 cifs_acl->default_entry_count = cpu_to_le16(0xFFFF);
3503 } else if (acl_type == ACL_TYPE_DEFAULT) {
3504 cifs_acl->default_entry_count = cpu_to_le16(count);
3505 cifs_acl->access_entry_count = cpu_to_le16(0xFFFF);
3507 cifs_dbg(FYI, "unknown ACL type %d\n", acl_type);
3510 for (i = 0; i < count; i++) {
3511 rc = convert_ace_to_cifs_ace(&cifs_acl->ace_array[i], &ace[i]);
3513 /* ACE not converted */
3518 rc = (__u16)(count * sizeof(struct cifs_posix_ace));
3519 rc += sizeof(struct cifs_posix_acl);
3520 /* BB add check to make sure ACL does not overflow SMB */
3526 CIFSSMBGetPosixACL(const unsigned int xid, struct cifs_tcon *tcon,
3527 const unsigned char *searchName,
3528 char *acl_inf, const int buflen, const int acl_type,
3529 const struct nls_table *nls_codepage, int remap)
3531 /* SMB_QUERY_POSIX_ACL */
3532 TRANSACTION2_QPI_REQ *pSMB = NULL;
3533 TRANSACTION2_QPI_RSP *pSMBr = NULL;
3537 __u16 params, byte_count;
3539 cifs_dbg(FYI, "In GetPosixACL (Unix) for path %s\n", searchName);
3542 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3547 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3549 cifsConvertToUTF16((__le16 *) pSMB->FileName,
3550 searchName, PATH_MAX, nls_codepage,
3552 name_len++; /* trailing null */
3554 pSMB->FileName[name_len] = 0;
3555 pSMB->FileName[name_len+1] = 0;
3556 } else { /* BB improve the check for buffer overruns BB */
3557 name_len = strnlen(searchName, PATH_MAX);
3558 name_len++; /* trailing null */
3559 strncpy(pSMB->FileName, searchName, name_len);
3562 params = 2 /* level */ + 4 /* rsrvd */ + name_len /* incl null */ ;
3563 pSMB->TotalDataCount = 0;
3564 pSMB->MaxParameterCount = cpu_to_le16(2);
3565 /* BB find exact max data count below from sess structure BB */
3566 pSMB->MaxDataCount = cpu_to_le16(4000);
3567 pSMB->MaxSetupCount = 0;
3571 pSMB->Reserved2 = 0;
3572 pSMB->ParameterOffset = cpu_to_le16(
3573 offsetof(struct smb_com_transaction2_qpi_req,
3574 InformationLevel) - 4);
3575 pSMB->DataCount = 0;
3576 pSMB->DataOffset = 0;
3577 pSMB->SetupCount = 1;
3578 pSMB->Reserved3 = 0;
3579 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
3580 byte_count = params + 1 /* pad */ ;
3581 pSMB->TotalParameterCount = cpu_to_le16(params);
3582 pSMB->ParameterCount = pSMB->TotalParameterCount;
3583 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_POSIX_ACL);
3584 pSMB->Reserved4 = 0;
3585 inc_rfc1001_len(pSMB, byte_count);
3586 pSMB->ByteCount = cpu_to_le16(byte_count);
3588 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3589 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3590 cifs_stats_inc(&tcon->stats.cifs_stats.num_acl_get);
3592 cifs_dbg(FYI, "Send error in Query POSIX ACL = %d\n", rc);
3594 /* decode response */
3596 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3597 /* BB also check enough total bytes returned */
3598 if (rc || get_bcc(&pSMBr->hdr) < 2)
3599 rc = -EIO; /* bad smb */
3601 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3602 __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
3603 rc = cifs_copy_posix_acl(acl_inf,
3604 (char *)&pSMBr->hdr.Protocol+data_offset,
3605 buflen, acl_type, count);
3608 cifs_buf_release(pSMB);
3615 CIFSSMBSetPosixACL(const unsigned int xid, struct cifs_tcon *tcon,
3616 const unsigned char *fileName,
3617 const char *local_acl, const int buflen,
3619 const struct nls_table *nls_codepage, int remap)
3621 struct smb_com_transaction2_spi_req *pSMB = NULL;
3622 struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
3626 int bytes_returned = 0;
3627 __u16 params, byte_count, data_count, param_offset, offset;
3629 cifs_dbg(FYI, "In SetPosixACL (Unix) for path %s\n", fileName);
3631 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3635 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3637 cifsConvertToUTF16((__le16 *) pSMB->FileName, fileName,
3638 PATH_MAX, nls_codepage, remap);
3639 name_len++; /* trailing null */
3641 } else { /* BB improve the check for buffer overruns BB */
3642 name_len = strnlen(fileName, PATH_MAX);
3643 name_len++; /* trailing null */
3644 strncpy(pSMB->FileName, fileName, name_len);
3646 params = 6 + name_len;
3647 pSMB->MaxParameterCount = cpu_to_le16(2);
3648 /* BB find max SMB size from sess */
3649 pSMB->MaxDataCount = cpu_to_le16(1000);
3650 pSMB->MaxSetupCount = 0;
3654 pSMB->Reserved2 = 0;
3655 param_offset = offsetof(struct smb_com_transaction2_spi_req,
3656 InformationLevel) - 4;
3657 offset = param_offset + params;
3658 parm_data = ((char *) &pSMB->hdr.Protocol) + offset;
3659 pSMB->ParameterOffset = cpu_to_le16(param_offset);
3661 /* convert to on the wire format for POSIX ACL */
3662 data_count = ACL_to_cifs_posix(parm_data, local_acl, buflen, acl_type);
3664 if (data_count == 0) {
3666 goto setACLerrorExit;
3668 pSMB->DataOffset = cpu_to_le16(offset);
3669 pSMB->SetupCount = 1;
3670 pSMB->Reserved3 = 0;
3671 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
3672 pSMB->InformationLevel = cpu_to_le16(SMB_SET_POSIX_ACL);
3673 byte_count = 3 /* pad */ + params + data_count;
3674 pSMB->DataCount = cpu_to_le16(data_count);
3675 pSMB->TotalDataCount = pSMB->DataCount;
3676 pSMB->ParameterCount = cpu_to_le16(params);
3677 pSMB->TotalParameterCount = pSMB->ParameterCount;
3678 pSMB->Reserved4 = 0;
3679 inc_rfc1001_len(pSMB, byte_count);
3680 pSMB->ByteCount = cpu_to_le16(byte_count);
3681 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3682 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3684 cifs_dbg(FYI, "Set POSIX ACL returned %d\n", rc);
3687 cifs_buf_release(pSMB);
3693 /* BB fix tabs in this function FIXME BB */
3695 CIFSGetExtAttr(const unsigned int xid, struct cifs_tcon *tcon,
3696 const int netfid, __u64 *pExtAttrBits, __u64 *pMask)
3699 struct smb_t2_qfi_req *pSMB = NULL;
3700 struct smb_t2_qfi_rsp *pSMBr = NULL;
3702 __u16 params, byte_count;
3704 cifs_dbg(FYI, "In GetExtAttr\n");
3709 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3714 params = 2 /* level */ + 2 /* fid */;
3715 pSMB->t2.TotalDataCount = 0;
3716 pSMB->t2.MaxParameterCount = cpu_to_le16(4);
3717 /* BB find exact max data count below from sess structure BB */
3718 pSMB->t2.MaxDataCount = cpu_to_le16(4000);
3719 pSMB->t2.MaxSetupCount = 0;
3720 pSMB->t2.Reserved = 0;
3722 pSMB->t2.Timeout = 0;
3723 pSMB->t2.Reserved2 = 0;
3724 pSMB->t2.ParameterOffset = cpu_to_le16(offsetof(struct smb_t2_qfi_req,
3726 pSMB->t2.DataCount = 0;
3727 pSMB->t2.DataOffset = 0;
3728 pSMB->t2.SetupCount = 1;
3729 pSMB->t2.Reserved3 = 0;
3730 pSMB->t2.SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION);
3731 byte_count = params + 1 /* pad */ ;
3732 pSMB->t2.TotalParameterCount = cpu_to_le16(params);
3733 pSMB->t2.ParameterCount = pSMB->t2.TotalParameterCount;
3734 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_ATTR_FLAGS);
3737 inc_rfc1001_len(pSMB, byte_count);
3738 pSMB->t2.ByteCount = cpu_to_le16(byte_count);
3740 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3741 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3743 cifs_dbg(FYI, "error %d in GetExtAttr\n", rc);
3745 /* decode response */
3746 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3747 /* BB also check enough total bytes returned */
3748 if (rc || get_bcc(&pSMBr->hdr) < 2)
3749 /* If rc should we check for EOPNOSUPP and
3750 disable the srvino flag? or in caller? */
3751 rc = -EIO; /* bad smb */
3753 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3754 __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
3755 struct file_chattr_info *pfinfo;
3756 /* BB Do we need a cast or hash here ? */
3758 cifs_dbg(FYI, "Illegal size ret in GetExtAttr\n");
3762 pfinfo = (struct file_chattr_info *)
3763 (data_offset + (char *) &pSMBr->hdr.Protocol);
3764 *pExtAttrBits = le64_to_cpu(pfinfo->mode);
3765 *pMask = le64_to_cpu(pfinfo->mask);
3769 cifs_buf_release(pSMB);
3771 goto GetExtAttrRetry;
3775 #endif /* CONFIG_POSIX */
3777 #ifdef CONFIG_CIFS_ACL
3779 * Initialize NT TRANSACT SMB into small smb request buffer. This assumes that
3780 * all NT TRANSACTS that we init here have total parm and data under about 400
3781 * bytes (to fit in small cifs buffer size), which is the case so far, it
3782 * easily fits. NB: Setup words themselves and ByteCount MaxSetupCount (size of
3783 * returned setup area) and MaxParameterCount (returned parms size) must be set
3787 smb_init_nttransact(const __u16 sub_command, const int setup_count,
3788 const int parm_len, struct cifs_tcon *tcon,
3793 struct smb_com_ntransact_req *pSMB;
3795 rc = small_smb_init(SMB_COM_NT_TRANSACT, 19 + setup_count, tcon,
3799 *ret_buf = (void *)pSMB;
3801 pSMB->TotalParameterCount = cpu_to_le32(parm_len);
3802 pSMB->TotalDataCount = 0;
3803 pSMB->MaxDataCount = cpu_to_le32(CIFSMaxBufSize & 0xFFFFFF00);
3804 pSMB->ParameterCount = pSMB->TotalParameterCount;
3805 pSMB->DataCount = pSMB->TotalDataCount;
3806 temp_offset = offsetof(struct smb_com_ntransact_req, Parms) +
3807 (setup_count * 2) - 4 /* for rfc1001 length itself */;
3808 pSMB->ParameterOffset = cpu_to_le32(temp_offset);
3809 pSMB->DataOffset = cpu_to_le32(temp_offset + parm_len);
3810 pSMB->SetupCount = setup_count; /* no need to le convert byte fields */
3811 pSMB->SubCommand = cpu_to_le16(sub_command);
3816 validate_ntransact(char *buf, char **ppparm, char **ppdata,
3817 __u32 *pparmlen, __u32 *pdatalen)
3820 __u32 data_count, data_offset, parm_count, parm_offset;
3821 struct smb_com_ntransact_rsp *pSMBr;
3830 pSMBr = (struct smb_com_ntransact_rsp *)buf;
3832 bcc = get_bcc(&pSMBr->hdr);
3833 end_of_smb = 2 /* sizeof byte count */ + bcc +
3834 (char *)&pSMBr->ByteCount;
3836 data_offset = le32_to_cpu(pSMBr->DataOffset);
3837 data_count = le32_to_cpu(pSMBr->DataCount);
3838 parm_offset = le32_to_cpu(pSMBr->ParameterOffset);
3839 parm_count = le32_to_cpu(pSMBr->ParameterCount);
3841 *ppparm = (char *)&pSMBr->hdr.Protocol + parm_offset;
3842 *ppdata = (char *)&pSMBr->hdr.Protocol + data_offset;
3844 /* should we also check that parm and data areas do not overlap? */
3845 if (*ppparm > end_of_smb) {
3846 cifs_dbg(FYI, "parms start after end of smb\n");
3848 } else if (parm_count + *ppparm > end_of_smb) {
3849 cifs_dbg(FYI, "parm end after end of smb\n");
3851 } else if (*ppdata > end_of_smb) {
3852 cifs_dbg(FYI, "data starts after end of smb\n");
3854 } else if (data_count + *ppdata > end_of_smb) {
3855 cifs_dbg(FYI, "data %p + count %d (%p) past smb end %p start %p\n",
3856 *ppdata, data_count, (data_count + *ppdata),
3859 } else if (parm_count + data_count > bcc) {
3860 cifs_dbg(FYI, "parm count and data count larger than SMB\n");
3863 *pdatalen = data_count;
3864 *pparmlen = parm_count;
3868 /* Get Security Descriptor (by handle) from remote server for a file or dir */
3870 CIFSSMBGetCIFSACL(const unsigned int xid, struct cifs_tcon *tcon, __u16 fid,
3871 struct cifs_ntsd **acl_inf, __u32 *pbuflen)
3875 QUERY_SEC_DESC_REQ *pSMB;
3877 struct kvec rsp_iov;
3879 cifs_dbg(FYI, "GetCifsACL\n");
3884 rc = smb_init_nttransact(NT_TRANSACT_QUERY_SECURITY_DESC, 0,
3885 8 /* parm len */, tcon, (void **) &pSMB);
3889 pSMB->MaxParameterCount = cpu_to_le32(4);
3890 /* BB TEST with big acls that might need to be e.g. larger than 16K */
3891 pSMB->MaxSetupCount = 0;
3892 pSMB->Fid = fid; /* file handle always le */
3893 pSMB->AclFlags = cpu_to_le32(CIFS_ACL_OWNER | CIFS_ACL_GROUP |
3895 pSMB->ByteCount = cpu_to_le16(11); /* 3 bytes pad + 8 bytes parm */
3896 inc_rfc1001_len(pSMB, 11);
3897 iov[0].iov_base = (char *)pSMB;
3898 iov[0].iov_len = be32_to_cpu(pSMB->hdr.smb_buf_length) + 4;
3900 rc = SendReceive2(xid, tcon->ses, iov, 1 /* num iovec */, &buf_type,
3902 cifs_small_buf_release(pSMB);
3903 cifs_stats_inc(&tcon->stats.cifs_stats.num_acl_get);
3905 cifs_dbg(FYI, "Send error in QuerySecDesc = %d\n", rc);
3906 } else { /* decode response */
3910 struct smb_com_ntransact_rsp *pSMBr;
3913 /* validate_nttransact */
3914 rc = validate_ntransact(rsp_iov.iov_base, (char **)&parm,
3915 &pdata, &parm_len, pbuflen);
3918 pSMBr = (struct smb_com_ntransact_rsp *)rsp_iov.iov_base;
3920 cifs_dbg(FYI, "smb %p parm %p data %p\n",
3921 pSMBr, parm, *acl_inf);
3923 if (le32_to_cpu(pSMBr->ParameterCount) != 4) {
3924 rc = -EIO; /* bad smb */
3929 /* BB check that data area is minimum length and as big as acl_len */
3931 acl_len = le32_to_cpu(*parm);
3932 if (acl_len != *pbuflen) {
3933 cifs_dbg(VFS, "acl length %d does not match %d\n",
3935 if (*pbuflen > acl_len)
3939 /* check if buffer is big enough for the acl
3940 header followed by the smallest SID */
3941 if ((*pbuflen < sizeof(struct cifs_ntsd) + 8) ||
3942 (*pbuflen >= 64 * 1024)) {
3943 cifs_dbg(VFS, "bad acl length %d\n", *pbuflen);
3947 *acl_inf = kmemdup(pdata, *pbuflen, GFP_KERNEL);
3948 if (*acl_inf == NULL) {
3955 free_rsp_buf(buf_type, rsp_iov.iov_base);
3960 CIFSSMBSetCIFSACL(const unsigned int xid, struct cifs_tcon *tcon, __u16 fid,
3961 struct cifs_ntsd *pntsd, __u32 acllen, int aclflag)
3963 __u16 byte_count, param_count, data_count, param_offset, data_offset;
3965 int bytes_returned = 0;
3966 SET_SEC_DESC_REQ *pSMB = NULL;
3970 rc = smb_init(SMB_COM_NT_TRANSACT, 19, tcon, (void **) &pSMB, &pSMBr);
3974 pSMB->MaxSetupCount = 0;
3978 param_offset = offsetof(struct smb_com_transaction_ssec_req, Fid) - 4;
3979 data_count = acllen;
3980 data_offset = param_offset + param_count;
3981 byte_count = 3 /* pad */ + param_count;
3983 pSMB->DataCount = cpu_to_le32(data_count);
3984 pSMB->TotalDataCount = pSMB->DataCount;
3985 pSMB->MaxParameterCount = cpu_to_le32(4);
3986 pSMB->MaxDataCount = cpu_to_le32(16384);
3987 pSMB->ParameterCount = cpu_to_le32(param_count);
3988 pSMB->ParameterOffset = cpu_to_le32(param_offset);
3989 pSMB->TotalParameterCount = pSMB->ParameterCount;
3990 pSMB->DataOffset = cpu_to_le32(data_offset);
3991 pSMB->SetupCount = 0;
3992 pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_SET_SECURITY_DESC);
3993 pSMB->ByteCount = cpu_to_le16(byte_count+data_count);
3995 pSMB->Fid = fid; /* file handle always le */
3996 pSMB->Reserved2 = 0;
3997 pSMB->AclFlags = cpu_to_le32(aclflag);
3999 if (pntsd && acllen) {
4000 memcpy((char *)pSMBr + offsetof(struct smb_hdr, Protocol) +
4001 data_offset, pntsd, acllen);
4002 inc_rfc1001_len(pSMB, byte_count + data_count);
4004 inc_rfc1001_len(pSMB, byte_count);
4006 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4007 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4009 cifs_dbg(FYI, "SetCIFSACL bytes_returned: %d, rc: %d\n",
4010 bytes_returned, rc);
4012 cifs_dbg(FYI, "Set CIFS ACL returned %d\n", rc);
4013 cifs_buf_release(pSMB);
4016 goto setCifsAclRetry;
4021 #endif /* CONFIG_CIFS_ACL */
4023 /* Legacy Query Path Information call for lookup to old servers such
4026 SMBQueryInformation(const unsigned int xid, struct cifs_tcon *tcon,
4027 const char *search_name, FILE_ALL_INFO *data,
4028 const struct nls_table *nls_codepage, int remap)
4030 QUERY_INFORMATION_REQ *pSMB;
4031 QUERY_INFORMATION_RSP *pSMBr;
4036 cifs_dbg(FYI, "In SMBQPath path %s\n", search_name);
4038 rc = smb_init(SMB_COM_QUERY_INFORMATION, 0, tcon, (void **) &pSMB,
4043 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4045 cifsConvertToUTF16((__le16 *) pSMB->FileName,
4046 search_name, PATH_MAX, nls_codepage,
4048 name_len++; /* trailing null */
4051 name_len = strnlen(search_name, PATH_MAX);
4052 name_len++; /* trailing null */
4053 strncpy(pSMB->FileName, search_name, name_len);
4055 pSMB->BufferFormat = 0x04;
4056 name_len++; /* account for buffer type byte */
4057 inc_rfc1001_len(pSMB, (__u16)name_len);
4058 pSMB->ByteCount = cpu_to_le16(name_len);
4060 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4061 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4063 cifs_dbg(FYI, "Send error in QueryInfo = %d\n", rc);
4066 __u32 time = le32_to_cpu(pSMBr->last_write_time);
4068 /* decode response */
4069 /* BB FIXME - add time zone adjustment BB */
4070 memset(data, 0, sizeof(FILE_ALL_INFO));
4073 /* decode time fields */
4074 data->ChangeTime = cpu_to_le64(cifs_UnixTimeToNT(ts));
4075 data->LastWriteTime = data->ChangeTime;
4076 data->LastAccessTime = 0;
4077 data->AllocationSize =
4078 cpu_to_le64(le32_to_cpu(pSMBr->size));
4079 data->EndOfFile = data->AllocationSize;
4081 cpu_to_le32(le16_to_cpu(pSMBr->attr));
4083 rc = -EIO; /* bad buffer passed in */
4085 cifs_buf_release(pSMB);
4094 CIFSSMBQFileInfo(const unsigned int xid, struct cifs_tcon *tcon,
4095 u16 netfid, FILE_ALL_INFO *pFindData)
4097 struct smb_t2_qfi_req *pSMB = NULL;
4098 struct smb_t2_qfi_rsp *pSMBr = NULL;
4101 __u16 params, byte_count;
4104 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4109 params = 2 /* level */ + 2 /* fid */;
4110 pSMB->t2.TotalDataCount = 0;
4111 pSMB->t2.MaxParameterCount = cpu_to_le16(4);
4112 /* BB find exact max data count below from sess structure BB */
4113 pSMB->t2.MaxDataCount = cpu_to_le16(CIFSMaxBufSize);
4114 pSMB->t2.MaxSetupCount = 0;
4115 pSMB->t2.Reserved = 0;
4117 pSMB->t2.Timeout = 0;
4118 pSMB->t2.Reserved2 = 0;
4119 pSMB->t2.ParameterOffset = cpu_to_le16(offsetof(struct smb_t2_qfi_req,
4121 pSMB->t2.DataCount = 0;
4122 pSMB->t2.DataOffset = 0;
4123 pSMB->t2.SetupCount = 1;
4124 pSMB->t2.Reserved3 = 0;
4125 pSMB->t2.SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION);
4126 byte_count = params + 1 /* pad */ ;
4127 pSMB->t2.TotalParameterCount = cpu_to_le16(params);
4128 pSMB->t2.ParameterCount = pSMB->t2.TotalParameterCount;
4129 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_ALL_INFO);
4132 inc_rfc1001_len(pSMB, byte_count);
4133 pSMB->t2.ByteCount = cpu_to_le16(byte_count);
4135 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4136 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4138 cifs_dbg(FYI, "Send error in QFileInfo = %d", rc);
4139 } else { /* decode response */
4140 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4142 if (rc) /* BB add auto retry on EOPNOTSUPP? */
4144 else if (get_bcc(&pSMBr->hdr) < 40)
4145 rc = -EIO; /* bad smb */
4146 else if (pFindData) {
4147 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4148 memcpy((char *) pFindData,
4149 (char *) &pSMBr->hdr.Protocol +
4150 data_offset, sizeof(FILE_ALL_INFO));
4154 cifs_buf_release(pSMB);
4156 goto QFileInfoRetry;
4162 CIFSSMBQPathInfo(const unsigned int xid, struct cifs_tcon *tcon,
4163 const char *search_name, FILE_ALL_INFO *data,
4164 int legacy /* old style infolevel */,
4165 const struct nls_table *nls_codepage, int remap)
4167 /* level 263 SMB_QUERY_FILE_ALL_INFO */
4168 TRANSACTION2_QPI_REQ *pSMB = NULL;
4169 TRANSACTION2_QPI_RSP *pSMBr = NULL;
4173 __u16 params, byte_count;
4175 /* cifs_dbg(FYI, "In QPathInfo path %s\n", search_name); */
4177 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4182 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4184 cifsConvertToUTF16((__le16 *) pSMB->FileName, search_name,
4185 PATH_MAX, nls_codepage, remap);
4186 name_len++; /* trailing null */
4188 } else { /* BB improve the check for buffer overruns BB */
4189 name_len = strnlen(search_name, PATH_MAX);
4190 name_len++; /* trailing null */
4191 strncpy(pSMB->FileName, search_name, name_len);
4194 params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */;
4195 pSMB->TotalDataCount = 0;
4196 pSMB->MaxParameterCount = cpu_to_le16(2);
4197 /* BB find exact max SMB PDU from sess structure BB */
4198 pSMB->MaxDataCount = cpu_to_le16(4000);
4199 pSMB->MaxSetupCount = 0;
4203 pSMB->Reserved2 = 0;
4204 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4205 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
4206 pSMB->DataCount = 0;
4207 pSMB->DataOffset = 0;
4208 pSMB->SetupCount = 1;
4209 pSMB->Reserved3 = 0;
4210 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
4211 byte_count = params + 1 /* pad */ ;
4212 pSMB->TotalParameterCount = cpu_to_le16(params);
4213 pSMB->ParameterCount = pSMB->TotalParameterCount;
4215 pSMB->InformationLevel = cpu_to_le16(SMB_INFO_STANDARD);
4217 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_ALL_INFO);
4218 pSMB->Reserved4 = 0;
4219 inc_rfc1001_len(pSMB, byte_count);
4220 pSMB->ByteCount = cpu_to_le16(byte_count);
4222 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4223 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4225 cifs_dbg(FYI, "Send error in QPathInfo = %d\n", rc);
4226 } else { /* decode response */
4227 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4229 if (rc) /* BB add auto retry on EOPNOTSUPP? */
4231 else if (!legacy && get_bcc(&pSMBr->hdr) < 40)
4232 rc = -EIO; /* bad smb */
4233 else if (legacy && get_bcc(&pSMBr->hdr) < 24)
4234 rc = -EIO; /* 24 or 26 expected but we do not read
4238 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4241 * On legacy responses we do not read the last field,
4242 * EAsize, fortunately since it varies by subdialect and
4243 * also note it differs on Set vs Get, ie two bytes or 4
4244 * bytes depending but we don't care here.
4247 size = sizeof(FILE_INFO_STANDARD);
4249 size = sizeof(FILE_ALL_INFO);
4250 memcpy((char *) data, (char *) &pSMBr->hdr.Protocol +
4255 cifs_buf_release(pSMB);
4257 goto QPathInfoRetry;
4263 CIFSSMBUnixQFileInfo(const unsigned int xid, struct cifs_tcon *tcon,
4264 u16 netfid, FILE_UNIX_BASIC_INFO *pFindData)
4266 struct smb_t2_qfi_req *pSMB = NULL;
4267 struct smb_t2_qfi_rsp *pSMBr = NULL;
4270 __u16 params, byte_count;
4273 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4278 params = 2 /* level */ + 2 /* fid */;
4279 pSMB->t2.TotalDataCount = 0;
4280 pSMB->t2.MaxParameterCount = cpu_to_le16(4);
4281 /* BB find exact max data count below from sess structure BB */
4282 pSMB->t2.MaxDataCount = cpu_to_le16(CIFSMaxBufSize);
4283 pSMB->t2.MaxSetupCount = 0;
4284 pSMB->t2.Reserved = 0;
4286 pSMB->t2.Timeout = 0;
4287 pSMB->t2.Reserved2 = 0;
4288 pSMB->t2.ParameterOffset = cpu_to_le16(offsetof(struct smb_t2_qfi_req,
4290 pSMB->t2.DataCount = 0;
4291 pSMB->t2.DataOffset = 0;
4292 pSMB->t2.SetupCount = 1;
4293 pSMB->t2.Reserved3 = 0;
4294 pSMB->t2.SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION);
4295 byte_count = params + 1 /* pad */ ;
4296 pSMB->t2.TotalParameterCount = cpu_to_le16(params);
4297 pSMB->t2.ParameterCount = pSMB->t2.TotalParameterCount;
4298 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC);
4301 inc_rfc1001_len(pSMB, byte_count);
4302 pSMB->t2.ByteCount = cpu_to_le16(byte_count);
4304 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4305 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4307 cifs_dbg(FYI, "Send error in UnixQFileInfo = %d", rc);
4308 } else { /* decode response */
4309 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4311 if (rc || get_bcc(&pSMBr->hdr) < sizeof(FILE_UNIX_BASIC_INFO)) {
4312 cifs_dbg(VFS, "Malformed FILE_UNIX_BASIC_INFO response. Unix Extensions can be disabled on mount by specifying the nosfu mount option.\n");
4313 rc = -EIO; /* bad smb */
4315 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4316 memcpy((char *) pFindData,
4317 (char *) &pSMBr->hdr.Protocol +
4319 sizeof(FILE_UNIX_BASIC_INFO));
4323 cifs_buf_release(pSMB);
4325 goto UnixQFileInfoRetry;
4331 CIFSSMBUnixQPathInfo(const unsigned int xid, struct cifs_tcon *tcon,
4332 const unsigned char *searchName,
4333 FILE_UNIX_BASIC_INFO *pFindData,
4334 const struct nls_table *nls_codepage, int remap)
4336 /* SMB_QUERY_FILE_UNIX_BASIC */
4337 TRANSACTION2_QPI_REQ *pSMB = NULL;
4338 TRANSACTION2_QPI_RSP *pSMBr = NULL;
4340 int bytes_returned = 0;
4342 __u16 params, byte_count;
4344 cifs_dbg(FYI, "In QPathInfo (Unix) the path %s\n", searchName);
4346 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4351 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4353 cifsConvertToUTF16((__le16 *) pSMB->FileName, searchName,
4354 PATH_MAX, nls_codepage, remap);
4355 name_len++; /* trailing null */
4357 } else { /* BB improve the check for buffer overruns BB */
4358 name_len = strnlen(searchName, PATH_MAX);
4359 name_len++; /* trailing null */
4360 strncpy(pSMB->FileName, searchName, name_len);
4363 params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */;
4364 pSMB->TotalDataCount = 0;
4365 pSMB->MaxParameterCount = cpu_to_le16(2);
4366 /* BB find exact max SMB PDU from sess structure BB */
4367 pSMB->MaxDataCount = cpu_to_le16(4000);
4368 pSMB->MaxSetupCount = 0;
4372 pSMB->Reserved2 = 0;
4373 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4374 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
4375 pSMB->DataCount = 0;
4376 pSMB->DataOffset = 0;
4377 pSMB->SetupCount = 1;
4378 pSMB->Reserved3 = 0;
4379 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
4380 byte_count = params + 1 /* pad */ ;
4381 pSMB->TotalParameterCount = cpu_to_le16(params);
4382 pSMB->ParameterCount = pSMB->TotalParameterCount;
4383 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC);
4384 pSMB->Reserved4 = 0;
4385 inc_rfc1001_len(pSMB, byte_count);
4386 pSMB->ByteCount = cpu_to_le16(byte_count);
4388 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4389 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4391 cifs_dbg(FYI, "Send error in UnixQPathInfo = %d", rc);
4392 } else { /* decode response */
4393 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4395 if (rc || get_bcc(&pSMBr->hdr) < sizeof(FILE_UNIX_BASIC_INFO)) {
4396 cifs_dbg(VFS, "Malformed FILE_UNIX_BASIC_INFO response. Unix Extensions can be disabled on mount by specifying the nosfu mount option.\n");
4397 rc = -EIO; /* bad smb */
4399 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4400 memcpy((char *) pFindData,
4401 (char *) &pSMBr->hdr.Protocol +
4403 sizeof(FILE_UNIX_BASIC_INFO));
4406 cifs_buf_release(pSMB);
4408 goto UnixQPathInfoRetry;
4413 /* xid, tcon, searchName and codepage are input parms, rest are returned */
4415 CIFSFindFirst(const unsigned int xid, struct cifs_tcon *tcon,
4416 const char *searchName, struct cifs_sb_info *cifs_sb,
4417 __u16 *pnetfid, __u16 search_flags,
4418 struct cifs_search_info *psrch_inf, bool msearch)
4420 /* level 257 SMB_ */
4421 TRANSACTION2_FFIRST_REQ *pSMB = NULL;
4422 TRANSACTION2_FFIRST_RSP *pSMBr = NULL;
4423 T2_FFIRST_RSP_PARMS *parms;
4425 int bytes_returned = 0;
4426 int name_len, remap;
4427 __u16 params, byte_count;
4428 struct nls_table *nls_codepage;
4430 cifs_dbg(FYI, "In FindFirst for %s\n", searchName);
4433 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4438 nls_codepage = cifs_sb->local_nls;
4439 remap = cifs_remap(cifs_sb);
4441 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4443 cifsConvertToUTF16((__le16 *) pSMB->FileName, searchName,
4444 PATH_MAX, nls_codepage, remap);
4445 /* We can not add the asterik earlier in case
4446 it got remapped to 0xF03A as if it were part of the
4447 directory name instead of a wildcard */
4450 pSMB->FileName[name_len] = CIFS_DIR_SEP(cifs_sb);
4451 pSMB->FileName[name_len+1] = 0;
4452 pSMB->FileName[name_len+2] = '*';
4453 pSMB->FileName[name_len+3] = 0;
4454 name_len += 4; /* now the trailing null */
4455 /* null terminate just in case */
4456 pSMB->FileName[name_len] = 0;
4457 pSMB->FileName[name_len+1] = 0;
4460 } else { /* BB add check for overrun of SMB buf BB */
4461 name_len = strnlen(searchName, PATH_MAX);
4462 /* BB fix here and in unicode clause above ie
4463 if (name_len > buffersize-header)
4464 free buffer exit; BB */
4465 strncpy(pSMB->FileName, searchName, name_len);
4467 pSMB->FileName[name_len] = CIFS_DIR_SEP(cifs_sb);
4468 pSMB->FileName[name_len+1] = '*';
4469 pSMB->FileName[name_len+2] = 0;
4474 params = 12 + name_len /* includes null */ ;
4475 pSMB->TotalDataCount = 0; /* no EAs */
4476 pSMB->MaxParameterCount = cpu_to_le16(10);
4477 pSMB->MaxDataCount = cpu_to_le16(CIFSMaxBufSize & 0xFFFFFF00);
4478 pSMB->MaxSetupCount = 0;
4482 pSMB->Reserved2 = 0;
4483 byte_count = params + 1 /* pad */ ;
4484 pSMB->TotalParameterCount = cpu_to_le16(params);
4485 pSMB->ParameterCount = pSMB->TotalParameterCount;
4486 pSMB->ParameterOffset = cpu_to_le16(
4487 offsetof(struct smb_com_transaction2_ffirst_req, SearchAttributes)
4489 pSMB->DataCount = 0;
4490 pSMB->DataOffset = 0;
4491 pSMB->SetupCount = 1; /* one byte, no need to make endian neutral */
4492 pSMB->Reserved3 = 0;
4493 pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_FIRST);
4494 pSMB->SearchAttributes =
4495 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
4497 pSMB->SearchCount = cpu_to_le16(CIFSMaxBufSize/sizeof(FILE_UNIX_INFO));
4498 pSMB->SearchFlags = cpu_to_le16(search_flags);
4499 pSMB->InformationLevel = cpu_to_le16(psrch_inf->info_level);
4501 /* BB what should we set StorageType to? Does it matter? BB */
4502 pSMB->SearchStorageType = 0;
4503 inc_rfc1001_len(pSMB, byte_count);
4504 pSMB->ByteCount = cpu_to_le16(byte_count);
4506 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4507 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4508 cifs_stats_inc(&tcon->stats.cifs_stats.num_ffirst);
4510 if (rc) {/* BB add logic to retry regular search if Unix search
4511 rejected unexpectedly by server */
4512 /* BB Add code to handle unsupported level rc */
4513 cifs_dbg(FYI, "Error in FindFirst = %d\n", rc);
4515 cifs_buf_release(pSMB);
4517 /* BB eventually could optimize out free and realloc of buf */
4520 goto findFirstRetry;
4521 } else { /* decode response */
4522 /* BB remember to free buffer if error BB */
4523 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4527 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
4528 psrch_inf->unicode = true;
4530 psrch_inf->unicode = false;
4532 psrch_inf->ntwrk_buf_start = (char *)pSMBr;
4533 psrch_inf->smallBuf = 0;
4534 psrch_inf->srch_entries_start =
4535 (char *) &pSMBr->hdr.Protocol +
4536 le16_to_cpu(pSMBr->t2.DataOffset);
4537 parms = (T2_FFIRST_RSP_PARMS *)((char *) &pSMBr->hdr.Protocol +
4538 le16_to_cpu(pSMBr->t2.ParameterOffset));
4540 if (parms->EndofSearch)
4541 psrch_inf->endOfSearch = true;
4543 psrch_inf->endOfSearch = false;
4545 psrch_inf->entries_in_buffer =
4546 le16_to_cpu(parms->SearchCount);
4547 psrch_inf->index_of_last_entry = 2 /* skip . and .. */ +
4548 psrch_inf->entries_in_buffer;
4549 lnoff = le16_to_cpu(parms->LastNameOffset);
4550 if (CIFSMaxBufSize < lnoff) {
4551 cifs_dbg(VFS, "ignoring corrupt resume name\n");
4552 psrch_inf->last_entry = NULL;
4556 psrch_inf->last_entry = psrch_inf->srch_entries_start +
4560 *pnetfid = parms->SearchHandle;
4562 cifs_buf_release(pSMB);
4569 int CIFSFindNext(const unsigned int xid, struct cifs_tcon *tcon,
4570 __u16 searchHandle, __u16 search_flags,
4571 struct cifs_search_info *psrch_inf)
4573 TRANSACTION2_FNEXT_REQ *pSMB = NULL;
4574 TRANSACTION2_FNEXT_RSP *pSMBr = NULL;
4575 T2_FNEXT_RSP_PARMS *parms;
4576 char *response_data;
4579 unsigned int name_len;
4580 __u16 params, byte_count;
4582 cifs_dbg(FYI, "In FindNext\n");
4584 if (psrch_inf->endOfSearch)
4587 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4592 params = 14; /* includes 2 bytes of null string, converted to LE below*/
4594 pSMB->TotalDataCount = 0; /* no EAs */
4595 pSMB->MaxParameterCount = cpu_to_le16(8);
4596 pSMB->MaxDataCount = cpu_to_le16(CIFSMaxBufSize & 0xFFFFFF00);
4597 pSMB->MaxSetupCount = 0;
4601 pSMB->Reserved2 = 0;
4602 pSMB->ParameterOffset = cpu_to_le16(
4603 offsetof(struct smb_com_transaction2_fnext_req,SearchHandle) - 4);
4604 pSMB->DataCount = 0;
4605 pSMB->DataOffset = 0;
4606 pSMB->SetupCount = 1;
4607 pSMB->Reserved3 = 0;
4608 pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_NEXT);
4609 pSMB->SearchHandle = searchHandle; /* always kept as le */
4611 cpu_to_le16(CIFSMaxBufSize / sizeof(FILE_UNIX_INFO));
4612 pSMB->InformationLevel = cpu_to_le16(psrch_inf->info_level);
4613 pSMB->ResumeKey = psrch_inf->resume_key;
4614 pSMB->SearchFlags = cpu_to_le16(search_flags);
4616 name_len = psrch_inf->resume_name_len;
4618 if (name_len < PATH_MAX) {
4619 memcpy(pSMB->ResumeFileName, psrch_inf->presume_name, name_len);
4620 byte_count += name_len;
4621 /* 14 byte parm len above enough for 2 byte null terminator */
4622 pSMB->ResumeFileName[name_len] = 0;
4623 pSMB->ResumeFileName[name_len+1] = 0;
4626 goto FNext2_err_exit;
4628 byte_count = params + 1 /* pad */ ;
4629 pSMB->TotalParameterCount = cpu_to_le16(params);
4630 pSMB->ParameterCount = pSMB->TotalParameterCount;
4631 inc_rfc1001_len(pSMB, byte_count);
4632 pSMB->ByteCount = cpu_to_le16(byte_count);
4634 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4635 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4636 cifs_stats_inc(&tcon->stats.cifs_stats.num_fnext);
4639 psrch_inf->endOfSearch = true;
4640 cifs_buf_release(pSMB);
4641 rc = 0; /* search probably was closed at end of search*/
4643 cifs_dbg(FYI, "FindNext returned = %d\n", rc);
4644 } else { /* decode response */
4645 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4650 /* BB fixme add lock for file (srch_info) struct here */
4651 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
4652 psrch_inf->unicode = true;
4654 psrch_inf->unicode = false;
4655 response_data = (char *) &pSMBr->hdr.Protocol +
4656 le16_to_cpu(pSMBr->t2.ParameterOffset);
4657 parms = (T2_FNEXT_RSP_PARMS *)response_data;
4658 response_data = (char *)&pSMBr->hdr.Protocol +
4659 le16_to_cpu(pSMBr->t2.DataOffset);
4660 if (psrch_inf->smallBuf)
4661 cifs_small_buf_release(
4662 psrch_inf->ntwrk_buf_start);
4664 cifs_buf_release(psrch_inf->ntwrk_buf_start);
4665 psrch_inf->srch_entries_start = response_data;
4666 psrch_inf->ntwrk_buf_start = (char *)pSMB;
4667 psrch_inf->smallBuf = 0;
4668 if (parms->EndofSearch)
4669 psrch_inf->endOfSearch = true;
4671 psrch_inf->endOfSearch = false;
4672 psrch_inf->entries_in_buffer =
4673 le16_to_cpu(parms->SearchCount);
4674 psrch_inf->index_of_last_entry +=
4675 psrch_inf->entries_in_buffer;
4676 lnoff = le16_to_cpu(parms->LastNameOffset);
4677 if (CIFSMaxBufSize < lnoff) {
4678 cifs_dbg(VFS, "ignoring corrupt resume name\n");
4679 psrch_inf->last_entry = NULL;
4682 psrch_inf->last_entry =
4683 psrch_inf->srch_entries_start + lnoff;
4685 /* cifs_dbg(FYI, "fnxt2 entries in buf %d index_of_last %d\n",
4686 psrch_inf->entries_in_buffer, psrch_inf->index_of_last_entry); */
4688 /* BB fixme add unlock here */
4693 /* BB On error, should we leave previous search buf (and count and
4694 last entry fields) intact or free the previous one? */
4696 /* Note: On -EAGAIN error only caller can retry on handle based calls
4697 since file handle passed in no longer valid */
4700 cifs_buf_release(pSMB);
4705 CIFSFindClose(const unsigned int xid, struct cifs_tcon *tcon,
4706 const __u16 searchHandle)
4709 FINDCLOSE_REQ *pSMB = NULL;
4711 cifs_dbg(FYI, "In CIFSSMBFindClose\n");
4712 rc = small_smb_init(SMB_COM_FIND_CLOSE2, 1, tcon, (void **)&pSMB);
4714 /* no sense returning error if session restarted
4715 as file handle has been closed */
4721 pSMB->FileID = searchHandle;
4722 pSMB->ByteCount = 0;
4723 rc = SendReceiveNoRsp(xid, tcon->ses, (char *) pSMB, 0);
4724 cifs_small_buf_release(pSMB);
4726 cifs_dbg(VFS, "Send error in FindClose = %d\n", rc);
4728 cifs_stats_inc(&tcon->stats.cifs_stats.num_fclose);
4730 /* Since session is dead, search handle closed on server already */
4738 CIFSGetSrvInodeNumber(const unsigned int xid, struct cifs_tcon *tcon,
4739 const char *search_name, __u64 *inode_number,
4740 const struct nls_table *nls_codepage, int remap)
4743 TRANSACTION2_QPI_REQ *pSMB = NULL;
4744 TRANSACTION2_QPI_RSP *pSMBr = NULL;
4745 int name_len, bytes_returned;
4746 __u16 params, byte_count;
4748 cifs_dbg(FYI, "In GetSrvInodeNum for %s\n", search_name);
4752 GetInodeNumberRetry:
4753 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4758 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4760 cifsConvertToUTF16((__le16 *) pSMB->FileName,
4761 search_name, PATH_MAX, nls_codepage,
4763 name_len++; /* trailing null */
4765 } else { /* BB improve the check for buffer overruns BB */
4766 name_len = strnlen(search_name, PATH_MAX);
4767 name_len++; /* trailing null */
4768 strncpy(pSMB->FileName, search_name, name_len);
4771 params = 2 /* level */ + 4 /* rsrvd */ + name_len /* incl null */ ;
4772 pSMB->TotalDataCount = 0;
4773 pSMB->MaxParameterCount = cpu_to_le16(2);
4774 /* BB find exact max data count below from sess structure BB */
4775 pSMB->MaxDataCount = cpu_to_le16(4000);
4776 pSMB->MaxSetupCount = 0;
4780 pSMB->Reserved2 = 0;
4781 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4782 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
4783 pSMB->DataCount = 0;
4784 pSMB->DataOffset = 0;
4785 pSMB->SetupCount = 1;
4786 pSMB->Reserved3 = 0;
4787 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
4788 byte_count = params + 1 /* pad */ ;
4789 pSMB->TotalParameterCount = cpu_to_le16(params);
4790 pSMB->ParameterCount = pSMB->TotalParameterCount;
4791 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_INTERNAL_INFO);
4792 pSMB->Reserved4 = 0;
4793 inc_rfc1001_len(pSMB, byte_count);
4794 pSMB->ByteCount = cpu_to_le16(byte_count);
4796 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4797 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4799 cifs_dbg(FYI, "error %d in QueryInternalInfo\n", rc);
4801 /* decode response */
4802 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4803 /* BB also check enough total bytes returned */
4804 if (rc || get_bcc(&pSMBr->hdr) < 2)
4805 /* If rc should we check for EOPNOSUPP and
4806 disable the srvino flag? or in caller? */
4807 rc = -EIO; /* bad smb */
4809 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4810 __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
4811 struct file_internal_info *pfinfo;
4812 /* BB Do we need a cast or hash here ? */
4814 cifs_dbg(FYI, "Illegal size ret in QryIntrnlInf\n");
4816 goto GetInodeNumOut;
4818 pfinfo = (struct file_internal_info *)
4819 (data_offset + (char *) &pSMBr->hdr.Protocol);
4820 *inode_number = le64_to_cpu(pfinfo->UniqueId);
4824 cifs_buf_release(pSMB);
4826 goto GetInodeNumberRetry;
4831 CIFSGetDFSRefer(const unsigned int xid, struct cifs_ses *ses,
4832 const char *search_name, struct dfs_info3_param **target_nodes,
4833 unsigned int *num_of_nodes,
4834 const struct nls_table *nls_codepage, int remap)
4836 /* TRANS2_GET_DFS_REFERRAL */
4837 TRANSACTION2_GET_DFS_REFER_REQ *pSMB = NULL;
4838 TRANSACTION2_GET_DFS_REFER_RSP *pSMBr = NULL;
4842 __u16 params, byte_count;
4844 *target_nodes = NULL;
4846 cifs_dbg(FYI, "In GetDFSRefer the path %s\n", search_name);
4850 rc = smb_init(SMB_COM_TRANSACTION2, 15, NULL, (void **) &pSMB,
4855 /* server pointer checked in called function,
4856 but should never be null here anyway */
4857 pSMB->hdr.Mid = get_next_mid(ses->server);
4858 pSMB->hdr.Tid = ses->ipc_tid;
4859 pSMB->hdr.Uid = ses->Suid;
4860 if (ses->capabilities & CAP_STATUS32)
4861 pSMB->hdr.Flags2 |= SMBFLG2_ERR_STATUS;
4862 if (ses->capabilities & CAP_DFS)
4863 pSMB->hdr.Flags2 |= SMBFLG2_DFS;
4865 if (ses->capabilities & CAP_UNICODE) {
4866 pSMB->hdr.Flags2 |= SMBFLG2_UNICODE;
4868 cifsConvertToUTF16((__le16 *) pSMB->RequestFileName,
4869 search_name, PATH_MAX, nls_codepage,
4871 name_len++; /* trailing null */
4873 } else { /* BB improve the check for buffer overruns BB */
4874 name_len = strnlen(search_name, PATH_MAX);
4875 name_len++; /* trailing null */
4876 strncpy(pSMB->RequestFileName, search_name, name_len);
4879 if (ses->server->sign)
4880 pSMB->hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
4882 pSMB->hdr.Uid = ses->Suid;
4884 params = 2 /* level */ + name_len /*includes null */ ;
4885 pSMB->TotalDataCount = 0;
4886 pSMB->DataCount = 0;
4887 pSMB->DataOffset = 0;
4888 pSMB->MaxParameterCount = 0;
4889 /* BB find exact max SMB PDU from sess structure BB */
4890 pSMB->MaxDataCount = cpu_to_le16(4000);
4891 pSMB->MaxSetupCount = 0;
4895 pSMB->Reserved2 = 0;
4896 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4897 struct smb_com_transaction2_get_dfs_refer_req, MaxReferralLevel) - 4);
4898 pSMB->SetupCount = 1;
4899 pSMB->Reserved3 = 0;
4900 pSMB->SubCommand = cpu_to_le16(TRANS2_GET_DFS_REFERRAL);
4901 byte_count = params + 3 /* pad */ ;
4902 pSMB->ParameterCount = cpu_to_le16(params);
4903 pSMB->TotalParameterCount = pSMB->ParameterCount;
4904 pSMB->MaxReferralLevel = cpu_to_le16(3);
4905 inc_rfc1001_len(pSMB, byte_count);
4906 pSMB->ByteCount = cpu_to_le16(byte_count);
4908 rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB,
4909 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4911 cifs_dbg(FYI, "Send error in GetDFSRefer = %d\n", rc);
4914 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4916 /* BB Also check if enough total bytes returned? */
4917 if (rc || get_bcc(&pSMBr->hdr) < 17) {
4918 rc = -EIO; /* bad smb */
4922 cifs_dbg(FYI, "Decoding GetDFSRefer response BCC: %d Offset %d\n",
4923 get_bcc(&pSMBr->hdr), le16_to_cpu(pSMBr->t2.DataOffset));
4925 /* parse returned result into more usable form */
4926 rc = parse_dfs_referrals(&pSMBr->dfs_data,
4927 le16_to_cpu(pSMBr->t2.DataCount),
4928 num_of_nodes, target_nodes, nls_codepage,
4930 (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) != 0);
4933 cifs_buf_release(pSMB);
4941 /* Query File System Info such as free space to old servers such as Win 9x */
4943 SMBOldQFSInfo(const unsigned int xid, struct cifs_tcon *tcon,
4944 struct kstatfs *FSData)
4946 /* level 0x01 SMB_QUERY_FILE_SYSTEM_INFO */
4947 TRANSACTION2_QFSI_REQ *pSMB = NULL;
4948 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4949 FILE_SYSTEM_ALLOC_INFO *response_data;
4951 int bytes_returned = 0;
4952 __u16 params, byte_count;
4954 cifs_dbg(FYI, "OldQFSInfo\n");
4956 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4961 params = 2; /* level */
4962 pSMB->TotalDataCount = 0;
4963 pSMB->MaxParameterCount = cpu_to_le16(2);
4964 pSMB->MaxDataCount = cpu_to_le16(1000);
4965 pSMB->MaxSetupCount = 0;
4969 pSMB->Reserved2 = 0;
4970 byte_count = params + 1 /* pad */ ;
4971 pSMB->TotalParameterCount = cpu_to_le16(params);
4972 pSMB->ParameterCount = pSMB->TotalParameterCount;
4973 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4974 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4975 pSMB->DataCount = 0;
4976 pSMB->DataOffset = 0;
4977 pSMB->SetupCount = 1;
4978 pSMB->Reserved3 = 0;
4979 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4980 pSMB->InformationLevel = cpu_to_le16(SMB_INFO_ALLOCATION);
4981 inc_rfc1001_len(pSMB, byte_count);
4982 pSMB->ByteCount = cpu_to_le16(byte_count);
4984 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4985 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4987 cifs_dbg(FYI, "Send error in QFSInfo = %d\n", rc);
4988 } else { /* decode response */
4989 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4991 if (rc || get_bcc(&pSMBr->hdr) < 18)
4992 rc = -EIO; /* bad smb */
4994 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4995 cifs_dbg(FYI, "qfsinf resp BCC: %d Offset %d\n",
4996 get_bcc(&pSMBr->hdr), data_offset);
4998 response_data = (FILE_SYSTEM_ALLOC_INFO *)
4999 (((char *) &pSMBr->hdr.Protocol) + data_offset);
5001 le16_to_cpu(response_data->BytesPerSector) *
5002 le32_to_cpu(response_data->
5003 SectorsPerAllocationUnit);
5005 le32_to_cpu(response_data->TotalAllocationUnits);
5006 FSData->f_bfree = FSData->f_bavail =
5007 le32_to_cpu(response_data->FreeAllocationUnits);
5008 cifs_dbg(FYI, "Blocks: %lld Free: %lld Block size %ld\n",
5009 (unsigned long long)FSData->f_blocks,
5010 (unsigned long long)FSData->f_bfree,
5014 cifs_buf_release(pSMB);
5017 goto oldQFSInfoRetry;
5023 CIFSSMBQFSInfo(const unsigned int xid, struct cifs_tcon *tcon,
5024 struct kstatfs *FSData)
5026 /* level 0x103 SMB_QUERY_FILE_SYSTEM_INFO */
5027 TRANSACTION2_QFSI_REQ *pSMB = NULL;
5028 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
5029 FILE_SYSTEM_INFO *response_data;
5031 int bytes_returned = 0;
5032 __u16 params, byte_count;
5034 cifs_dbg(FYI, "In QFSInfo\n");
5036 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5041 params = 2; /* level */
5042 pSMB->TotalDataCount = 0;
5043 pSMB->MaxParameterCount = cpu_to_le16(2);
5044 pSMB->MaxDataCount = cpu_to_le16(1000);
5045 pSMB->MaxSetupCount = 0;
5049 pSMB->Reserved2 = 0;
5050 byte_count = params + 1 /* pad */ ;
5051 pSMB->TotalParameterCount = cpu_to_le16(params);
5052 pSMB->ParameterCount = pSMB->TotalParameterCount;
5053 pSMB->ParameterOffset = cpu_to_le16(offsetof(
5054 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
5055 pSMB->DataCount = 0;
5056 pSMB->DataOffset = 0;
5057 pSMB->SetupCount = 1;
5058 pSMB->Reserved3 = 0;
5059 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
5060 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_SIZE_INFO);
5061 inc_rfc1001_len(pSMB, byte_count);
5062 pSMB->ByteCount = cpu_to_le16(byte_count);
5064 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5065 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5067 cifs_dbg(FYI, "Send error in QFSInfo = %d\n", rc);
5068 } else { /* decode response */
5069 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
5071 if (rc || get_bcc(&pSMBr->hdr) < 24)
5072 rc = -EIO; /* bad smb */
5074 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
5078 *) (((char *) &pSMBr->hdr.Protocol) +
5081 le32_to_cpu(response_data->BytesPerSector) *
5082 le32_to_cpu(response_data->
5083 SectorsPerAllocationUnit);
5085 le64_to_cpu(response_data->TotalAllocationUnits);
5086 FSData->f_bfree = FSData->f_bavail =
5087 le64_to_cpu(response_data->FreeAllocationUnits);
5088 cifs_dbg(FYI, "Blocks: %lld Free: %lld Block size %ld\n",
5089 (unsigned long long)FSData->f_blocks,
5090 (unsigned long long)FSData->f_bfree,
5094 cifs_buf_release(pSMB);
5103 CIFSSMBQFSAttributeInfo(const unsigned int xid, struct cifs_tcon *tcon)
5105 /* level 0x105 SMB_QUERY_FILE_SYSTEM_INFO */
5106 TRANSACTION2_QFSI_REQ *pSMB = NULL;
5107 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
5108 FILE_SYSTEM_ATTRIBUTE_INFO *response_data;
5110 int bytes_returned = 0;
5111 __u16 params, byte_count;
5113 cifs_dbg(FYI, "In QFSAttributeInfo\n");
5115 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5120 params = 2; /* level */
5121 pSMB->TotalDataCount = 0;
5122 pSMB->MaxParameterCount = cpu_to_le16(2);
5123 /* BB find exact max SMB PDU from sess structure BB */
5124 pSMB->MaxDataCount = cpu_to_le16(1000);
5125 pSMB->MaxSetupCount = 0;
5129 pSMB->Reserved2 = 0;
5130 byte_count = params + 1 /* pad */ ;
5131 pSMB->TotalParameterCount = cpu_to_le16(params);
5132 pSMB->ParameterCount = pSMB->TotalParameterCount;
5133 pSMB->ParameterOffset = cpu_to_le16(offsetof(
5134 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
5135 pSMB->DataCount = 0;
5136 pSMB->DataOffset = 0;
5137 pSMB->SetupCount = 1;
5138 pSMB->Reserved3 = 0;
5139 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
5140 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_ATTRIBUTE_INFO);
5141 inc_rfc1001_len(pSMB, byte_count);
5142 pSMB->ByteCount = cpu_to_le16(byte_count);
5144 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5145 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5147 cifs_dbg(VFS, "Send error in QFSAttributeInfo = %d\n", rc);
5148 } else { /* decode response */
5149 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
5151 if (rc || get_bcc(&pSMBr->hdr) < 13) {
5152 /* BB also check if enough bytes returned */
5153 rc = -EIO; /* bad smb */
5155 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
5157 (FILE_SYSTEM_ATTRIBUTE_INFO
5158 *) (((char *) &pSMBr->hdr.Protocol) +
5160 memcpy(&tcon->fsAttrInfo, response_data,
5161 sizeof(FILE_SYSTEM_ATTRIBUTE_INFO));
5164 cifs_buf_release(pSMB);
5167 goto QFSAttributeRetry;
5173 CIFSSMBQFSDeviceInfo(const unsigned int xid, struct cifs_tcon *tcon)
5175 /* level 0x104 SMB_QUERY_FILE_SYSTEM_INFO */
5176 TRANSACTION2_QFSI_REQ *pSMB = NULL;
5177 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
5178 FILE_SYSTEM_DEVICE_INFO *response_data;
5180 int bytes_returned = 0;
5181 __u16 params, byte_count;
5183 cifs_dbg(FYI, "In QFSDeviceInfo\n");
5185 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5190 params = 2; /* level */
5191 pSMB->TotalDataCount = 0;
5192 pSMB->MaxParameterCount = cpu_to_le16(2);
5193 /* BB find exact max SMB PDU from sess structure BB */
5194 pSMB->MaxDataCount = cpu_to_le16(1000);
5195 pSMB->MaxSetupCount = 0;
5199 pSMB->Reserved2 = 0;
5200 byte_count = params + 1 /* pad */ ;
5201 pSMB->TotalParameterCount = cpu_to_le16(params);
5202 pSMB->ParameterCount = pSMB->TotalParameterCount;
5203 pSMB->ParameterOffset = cpu_to_le16(offsetof(
5204 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
5206 pSMB->DataCount = 0;
5207 pSMB->DataOffset = 0;
5208 pSMB->SetupCount = 1;
5209 pSMB->Reserved3 = 0;
5210 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
5211 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_DEVICE_INFO);
5212 inc_rfc1001_len(pSMB, byte_count);
5213 pSMB->ByteCount = cpu_to_le16(byte_count);
5215 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5216 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5218 cifs_dbg(FYI, "Send error in QFSDeviceInfo = %d\n", rc);
5219 } else { /* decode response */
5220 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
5222 if (rc || get_bcc(&pSMBr->hdr) <
5223 sizeof(FILE_SYSTEM_DEVICE_INFO))
5224 rc = -EIO; /* bad smb */
5226 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
5228 (FILE_SYSTEM_DEVICE_INFO *)
5229 (((char *) &pSMBr->hdr.Protocol) +
5231 memcpy(&tcon->fsDevInfo, response_data,
5232 sizeof(FILE_SYSTEM_DEVICE_INFO));
5235 cifs_buf_release(pSMB);
5238 goto QFSDeviceRetry;
5244 CIFSSMBQFSUnixInfo(const unsigned int xid, struct cifs_tcon *tcon)
5246 /* level 0x200 SMB_QUERY_CIFS_UNIX_INFO */
5247 TRANSACTION2_QFSI_REQ *pSMB = NULL;
5248 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
5249 FILE_SYSTEM_UNIX_INFO *response_data;
5251 int bytes_returned = 0;
5252 __u16 params, byte_count;
5254 cifs_dbg(FYI, "In QFSUnixInfo\n");
5256 rc = smb_init_no_reconnect(SMB_COM_TRANSACTION2, 15, tcon,
5257 (void **) &pSMB, (void **) &pSMBr);
5261 params = 2; /* level */
5262 pSMB->TotalDataCount = 0;
5263 pSMB->DataCount = 0;
5264 pSMB->DataOffset = 0;
5265 pSMB->MaxParameterCount = cpu_to_le16(2);
5266 /* BB find exact max SMB PDU from sess structure BB */
5267 pSMB->MaxDataCount = cpu_to_le16(100);
5268 pSMB->MaxSetupCount = 0;
5272 pSMB->Reserved2 = 0;
5273 byte_count = params + 1 /* pad */ ;
5274 pSMB->ParameterCount = cpu_to_le16(params);
5275 pSMB->TotalParameterCount = pSMB->ParameterCount;
5276 pSMB->ParameterOffset = cpu_to_le16(offsetof(struct
5277 smb_com_transaction2_qfsi_req, InformationLevel) - 4);
5278 pSMB->SetupCount = 1;
5279 pSMB->Reserved3 = 0;
5280 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
5281 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_CIFS_UNIX_INFO);
5282 inc_rfc1001_len(pSMB, byte_count);
5283 pSMB->ByteCount = cpu_to_le16(byte_count);
5285 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5286 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5288 cifs_dbg(VFS, "Send error in QFSUnixInfo = %d\n", rc);
5289 } else { /* decode response */
5290 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
5292 if (rc || get_bcc(&pSMBr->hdr) < 13) {
5293 rc = -EIO; /* bad smb */
5295 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
5297 (FILE_SYSTEM_UNIX_INFO
5298 *) (((char *) &pSMBr->hdr.Protocol) +
5300 memcpy(&tcon->fsUnixInfo, response_data,
5301 sizeof(FILE_SYSTEM_UNIX_INFO));
5304 cifs_buf_release(pSMB);
5314 CIFSSMBSetFSUnixInfo(const unsigned int xid, struct cifs_tcon *tcon, __u64 cap)
5316 /* level 0x200 SMB_SET_CIFS_UNIX_INFO */
5317 TRANSACTION2_SETFSI_REQ *pSMB = NULL;
5318 TRANSACTION2_SETFSI_RSP *pSMBr = NULL;
5320 int bytes_returned = 0;
5321 __u16 params, param_offset, offset, byte_count;
5323 cifs_dbg(FYI, "In SETFSUnixInfo\n");
5325 /* BB switch to small buf init to save memory */
5326 rc = smb_init_no_reconnect(SMB_COM_TRANSACTION2, 15, tcon,
5327 (void **) &pSMB, (void **) &pSMBr);
5331 params = 4; /* 2 bytes zero followed by info level. */
5332 pSMB->MaxSetupCount = 0;
5336 pSMB->Reserved2 = 0;
5337 param_offset = offsetof(struct smb_com_transaction2_setfsi_req, FileNum)
5339 offset = param_offset + params;
5341 pSMB->MaxParameterCount = cpu_to_le16(4);
5342 /* BB find exact max SMB PDU from sess structure BB */
5343 pSMB->MaxDataCount = cpu_to_le16(100);
5344 pSMB->SetupCount = 1;
5345 pSMB->Reserved3 = 0;
5346 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FS_INFORMATION);
5347 byte_count = 1 /* pad */ + params + 12;
5349 pSMB->DataCount = cpu_to_le16(12);
5350 pSMB->ParameterCount = cpu_to_le16(params);
5351 pSMB->TotalDataCount = pSMB->DataCount;
5352 pSMB->TotalParameterCount = pSMB->ParameterCount;
5353 pSMB->ParameterOffset = cpu_to_le16(param_offset);
5354 pSMB->DataOffset = cpu_to_le16(offset);
5358 pSMB->InformationLevel = cpu_to_le16(SMB_SET_CIFS_UNIX_INFO);
5361 pSMB->ClientUnixMajor = cpu_to_le16(CIFS_UNIX_MAJOR_VERSION);
5362 pSMB->ClientUnixMinor = cpu_to_le16(CIFS_UNIX_MINOR_VERSION);
5363 pSMB->ClientUnixCap = cpu_to_le64(cap);
5365 inc_rfc1001_len(pSMB, byte_count);
5366 pSMB->ByteCount = cpu_to_le16(byte_count);
5368 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5369 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5371 cifs_dbg(VFS, "Send error in SETFSUnixInfo = %d\n", rc);
5372 } else { /* decode response */
5373 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
5375 rc = -EIO; /* bad smb */
5377 cifs_buf_release(pSMB);
5380 goto SETFSUnixRetry;
5388 CIFSSMBQFSPosixInfo(const unsigned int xid, struct cifs_tcon *tcon,
5389 struct kstatfs *FSData)
5391 /* level 0x201 SMB_QUERY_CIFS_POSIX_INFO */
5392 TRANSACTION2_QFSI_REQ *pSMB = NULL;
5393 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
5394 FILE_SYSTEM_POSIX_INFO *response_data;
5396 int bytes_returned = 0;
5397 __u16 params, byte_count;
5399 cifs_dbg(FYI, "In QFSPosixInfo\n");
5401 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5406 params = 2; /* level */
5407 pSMB->TotalDataCount = 0;
5408 pSMB->DataCount = 0;
5409 pSMB->DataOffset = 0;
5410 pSMB->MaxParameterCount = cpu_to_le16(2);
5411 /* BB find exact max SMB PDU from sess structure BB */
5412 pSMB->MaxDataCount = cpu_to_le16(100);
5413 pSMB->MaxSetupCount = 0;
5417 pSMB->Reserved2 = 0;
5418 byte_count = params + 1 /* pad */ ;
5419 pSMB->ParameterCount = cpu_to_le16(params);
5420 pSMB->TotalParameterCount = pSMB->ParameterCount;
5421 pSMB->ParameterOffset = cpu_to_le16(offsetof(struct
5422 smb_com_transaction2_qfsi_req, InformationLevel) - 4);
5423 pSMB->SetupCount = 1;
5424 pSMB->Reserved3 = 0;
5425 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
5426 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_POSIX_FS_INFO);
5427 inc_rfc1001_len(pSMB, byte_count);
5428 pSMB->ByteCount = cpu_to_le16(byte_count);
5430 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5431 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5433 cifs_dbg(FYI, "Send error in QFSUnixInfo = %d\n", rc);
5434 } else { /* decode response */
5435 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
5437 if (rc || get_bcc(&pSMBr->hdr) < 13) {
5438 rc = -EIO; /* bad smb */
5440 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
5442 (FILE_SYSTEM_POSIX_INFO
5443 *) (((char *) &pSMBr->hdr.Protocol) +
5446 le32_to_cpu(response_data->BlockSize);
5448 le64_to_cpu(response_data->TotalBlocks);
5450 le64_to_cpu(response_data->BlocksAvail);
5451 if (response_data->UserBlocksAvail == cpu_to_le64(-1)) {
5452 FSData->f_bavail = FSData->f_bfree;
5455 le64_to_cpu(response_data->UserBlocksAvail);
5457 if (response_data->TotalFileNodes != cpu_to_le64(-1))
5459 le64_to_cpu(response_data->TotalFileNodes);
5460 if (response_data->FreeFileNodes != cpu_to_le64(-1))
5462 le64_to_cpu(response_data->FreeFileNodes);
5465 cifs_buf_release(pSMB);
5475 * We can not use write of zero bytes trick to set file size due to need for
5476 * large file support. Also note that this SetPathInfo is preferred to
5477 * SetFileInfo based method in next routine which is only needed to work around
5478 * a sharing violation bugin Samba which this routine can run into.
5481 CIFSSMBSetEOF(const unsigned int xid, struct cifs_tcon *tcon,
5482 const char *file_name, __u64 size, struct cifs_sb_info *cifs_sb,
5483 bool set_allocation)
5485 struct smb_com_transaction2_spi_req *pSMB = NULL;
5486 struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
5487 struct file_end_of_file_info *parm_data;
5490 int bytes_returned = 0;
5491 int remap = cifs_remap(cifs_sb);
5493 __u16 params, byte_count, data_count, param_offset, offset;
5495 cifs_dbg(FYI, "In SetEOF\n");
5497 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5502 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5504 cifsConvertToUTF16((__le16 *) pSMB->FileName, file_name,
5505 PATH_MAX, cifs_sb->local_nls, remap);
5506 name_len++; /* trailing null */
5508 } else { /* BB improve the check for buffer overruns BB */
5509 name_len = strnlen(file_name, PATH_MAX);
5510 name_len++; /* trailing null */
5511 strncpy(pSMB->FileName, file_name, name_len);
5513 params = 6 + name_len;
5514 data_count = sizeof(struct file_end_of_file_info);
5515 pSMB->MaxParameterCount = cpu_to_le16(2);
5516 pSMB->MaxDataCount = cpu_to_le16(4100);
5517 pSMB->MaxSetupCount = 0;
5521 pSMB->Reserved2 = 0;
5522 param_offset = offsetof(struct smb_com_transaction2_spi_req,
5523 InformationLevel) - 4;
5524 offset = param_offset + params;
5525 if (set_allocation) {
5526 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
5527 pSMB->InformationLevel =
5528 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2);
5530 pSMB->InformationLevel =
5531 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO);
5532 } else /* Set File Size */ {
5533 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
5534 pSMB->InformationLevel =
5535 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO2);
5537 pSMB->InformationLevel =
5538 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO);
5542 (struct file_end_of_file_info *) (((char *) &pSMB->hdr.Protocol) +
5544 pSMB->ParameterOffset = cpu_to_le16(param_offset);
5545 pSMB->DataOffset = cpu_to_le16(offset);
5546 pSMB->SetupCount = 1;
5547 pSMB->Reserved3 = 0;
5548 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
5549 byte_count = 3 /* pad */ + params + data_count;
5550 pSMB->DataCount = cpu_to_le16(data_count);
5551 pSMB->TotalDataCount = pSMB->DataCount;
5552 pSMB->ParameterCount = cpu_to_le16(params);
5553 pSMB->TotalParameterCount = pSMB->ParameterCount;
5554 pSMB->Reserved4 = 0;
5555 inc_rfc1001_len(pSMB, byte_count);
5556 parm_data->FileSize = cpu_to_le64(size);
5557 pSMB->ByteCount = cpu_to_le16(byte_count);
5558 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5559 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5561 cifs_dbg(FYI, "SetPathInfo (file size) returned %d\n", rc);
5563 cifs_buf_release(pSMB);
5572 CIFSSMBSetFileSize(const unsigned int xid, struct cifs_tcon *tcon,
5573 struct cifsFileInfo *cfile, __u64 size, bool set_allocation)
5575 struct smb_com_transaction2_sfi_req *pSMB = NULL;
5576 struct file_end_of_file_info *parm_data;
5578 __u16 params, param_offset, offset, byte_count, count;
5580 cifs_dbg(FYI, "SetFileSize (via SetFileInfo) %lld\n",
5582 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
5587 pSMB->hdr.Pid = cpu_to_le16((__u16)cfile->pid);
5588 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(cfile->pid >> 16));
5591 pSMB->MaxSetupCount = 0;
5595 pSMB->Reserved2 = 0;
5596 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
5597 offset = param_offset + params;
5599 count = sizeof(struct file_end_of_file_info);
5600 pSMB->MaxParameterCount = cpu_to_le16(2);
5601 /* BB find exact max SMB PDU from sess structure BB */
5602 pSMB->MaxDataCount = cpu_to_le16(1000);
5603 pSMB->SetupCount = 1;
5604 pSMB->Reserved3 = 0;
5605 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
5606 byte_count = 3 /* pad */ + params + count;
5607 pSMB->DataCount = cpu_to_le16(count);
5608 pSMB->ParameterCount = cpu_to_le16(params);
5609 pSMB->TotalDataCount = pSMB->DataCount;
5610 pSMB->TotalParameterCount = pSMB->ParameterCount;
5611 pSMB->ParameterOffset = cpu_to_le16(param_offset);
5613 (struct file_end_of_file_info *) (((char *) &pSMB->hdr.Protocol)
5615 pSMB->DataOffset = cpu_to_le16(offset);
5616 parm_data->FileSize = cpu_to_le64(size);
5617 pSMB->Fid = cfile->fid.netfid;
5618 if (set_allocation) {
5619 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
5620 pSMB->InformationLevel =
5621 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2);
5623 pSMB->InformationLevel =
5624 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO);
5625 } else /* Set File Size */ {
5626 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
5627 pSMB->InformationLevel =
5628 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO2);
5630 pSMB->InformationLevel =
5631 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO);
5633 pSMB->Reserved4 = 0;
5634 inc_rfc1001_len(pSMB, byte_count);
5635 pSMB->ByteCount = cpu_to_le16(byte_count);
5636 rc = SendReceiveNoRsp(xid, tcon->ses, (char *) pSMB, 0);
5637 cifs_small_buf_release(pSMB);
5639 cifs_dbg(FYI, "Send error in SetFileInfo (SetFileSize) = %d\n",
5643 /* Note: On -EAGAIN error only caller can retry on handle based calls
5644 since file handle passed in no longer valid */
5649 /* Some legacy servers such as NT4 require that the file times be set on
5650 an open handle, rather than by pathname - this is awkward due to
5651 potential access conflicts on the open, but it is unavoidable for these
5652 old servers since the only other choice is to go from 100 nanosecond DCE
5653 time and resort to the original setpathinfo level which takes the ancient
5654 DOS time format with 2 second granularity */
5656 CIFSSMBSetFileInfo(const unsigned int xid, struct cifs_tcon *tcon,
5657 const FILE_BASIC_INFO *data, __u16 fid, __u32 pid_of_opener)
5659 struct smb_com_transaction2_sfi_req *pSMB = NULL;
5662 __u16 params, param_offset, offset, byte_count, count;
5664 cifs_dbg(FYI, "Set Times (via SetFileInfo)\n");
5665 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
5670 pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
5671 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));
5674 pSMB->MaxSetupCount = 0;
5678 pSMB->Reserved2 = 0;
5679 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
5680 offset = param_offset + params;
5682 data_offset = (char *)pSMB +
5683 offsetof(struct smb_hdr, Protocol) + offset;
5685 count = sizeof(FILE_BASIC_INFO);
5686 pSMB->MaxParameterCount = cpu_to_le16(2);
5687 /* BB find max SMB PDU from sess */
5688 pSMB->MaxDataCount = cpu_to_le16(1000);
5689 pSMB->SetupCount = 1;
5690 pSMB->Reserved3 = 0;
5691 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
5692 byte_count = 3 /* pad */ + params + count;
5693 pSMB->DataCount = cpu_to_le16(count);
5694 pSMB->ParameterCount = cpu_to_le16(params);
5695 pSMB->TotalDataCount = pSMB->DataCount;
5696 pSMB->TotalParameterCount = pSMB->ParameterCount;
5697 pSMB->ParameterOffset = cpu_to_le16(param_offset);
5698 pSMB->DataOffset = cpu_to_le16(offset);
5700 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
5701 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO2);
5703 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO);
5704 pSMB->Reserved4 = 0;
5705 inc_rfc1001_len(pSMB, byte_count);
5706 pSMB->ByteCount = cpu_to_le16(byte_count);
5707 memcpy(data_offset, data, sizeof(FILE_BASIC_INFO));
5708 rc = SendReceiveNoRsp(xid, tcon->ses, (char *) pSMB, 0);
5709 cifs_small_buf_release(pSMB);
5711 cifs_dbg(FYI, "Send error in Set Time (SetFileInfo) = %d\n",
5714 /* Note: On -EAGAIN error only caller can retry on handle based calls
5715 since file handle passed in no longer valid */
5721 CIFSSMBSetFileDisposition(const unsigned int xid, struct cifs_tcon *tcon,
5722 bool delete_file, __u16 fid, __u32 pid_of_opener)
5724 struct smb_com_transaction2_sfi_req *pSMB = NULL;
5727 __u16 params, param_offset, offset, byte_count, count;
5729 cifs_dbg(FYI, "Set File Disposition (via SetFileInfo)\n");
5730 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
5735 pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
5736 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));
5739 pSMB->MaxSetupCount = 0;
5743 pSMB->Reserved2 = 0;
5744 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
5745 offset = param_offset + params;
5747 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
5750 pSMB->MaxParameterCount = cpu_to_le16(2);
5751 /* BB find max SMB PDU from sess */
5752 pSMB->MaxDataCount = cpu_to_le16(1000);
5753 pSMB->SetupCount = 1;
5754 pSMB->Reserved3 = 0;
5755 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
5756 byte_count = 3 /* pad */ + params + count;
5757 pSMB->DataCount = cpu_to_le16(count);
5758 pSMB->ParameterCount = cpu_to_le16(params);
5759 pSMB->TotalDataCount = pSMB->DataCount;
5760 pSMB->TotalParameterCount = pSMB->ParameterCount;
5761 pSMB->ParameterOffset = cpu_to_le16(param_offset);
5762 pSMB->DataOffset = cpu_to_le16(offset);
5764 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_DISPOSITION_INFO);
5765 pSMB->Reserved4 = 0;
5766 inc_rfc1001_len(pSMB, byte_count);
5767 pSMB->ByteCount = cpu_to_le16(byte_count);
5768 *data_offset = delete_file ? 1 : 0;
5769 rc = SendReceiveNoRsp(xid, tcon->ses, (char *) pSMB, 0);
5770 cifs_small_buf_release(pSMB);
5772 cifs_dbg(FYI, "Send error in SetFileDisposition = %d\n", rc);
5778 CIFSSMBSetPathInfo(const unsigned int xid, struct cifs_tcon *tcon,
5779 const char *fileName, const FILE_BASIC_INFO *data,
5780 const struct nls_table *nls_codepage, int remap)
5782 TRANSACTION2_SPI_REQ *pSMB = NULL;
5783 TRANSACTION2_SPI_RSP *pSMBr = NULL;
5786 int bytes_returned = 0;
5788 __u16 params, param_offset, offset, byte_count, count;
5790 cifs_dbg(FYI, "In SetTimes\n");
5793 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5798 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5800 cifsConvertToUTF16((__le16 *) pSMB->FileName, fileName,
5801 PATH_MAX, nls_codepage, remap);
5802 name_len++; /* trailing null */
5804 } else { /* BB improve the check for buffer overruns BB */
5805 name_len = strnlen(fileName, PATH_MAX);
5806 name_len++; /* trailing null */
5807 strncpy(pSMB->FileName, fileName, name_len);
5810 params = 6 + name_len;
5811 count = sizeof(FILE_BASIC_INFO);
5812 pSMB->MaxParameterCount = cpu_to_le16(2);
5813 /* BB find max SMB PDU from sess structure BB */
5814 pSMB->MaxDataCount = cpu_to_le16(1000);
5815 pSMB->MaxSetupCount = 0;
5819 pSMB->Reserved2 = 0;
5820 param_offset = offsetof(struct smb_com_transaction2_spi_req,
5821 InformationLevel) - 4;
5822 offset = param_offset + params;
5823 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
5824 pSMB->ParameterOffset = cpu_to_le16(param_offset);
5825 pSMB->DataOffset = cpu_to_le16(offset);
5826 pSMB->SetupCount = 1;
5827 pSMB->Reserved3 = 0;
5828 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
5829 byte_count = 3 /* pad */ + params + count;
5831 pSMB->DataCount = cpu_to_le16(count);
5832 pSMB->ParameterCount = cpu_to_le16(params);
5833 pSMB->TotalDataCount = pSMB->DataCount;
5834 pSMB->TotalParameterCount = pSMB->ParameterCount;
5835 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
5836 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO2);
5838 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO);
5839 pSMB->Reserved4 = 0;
5840 inc_rfc1001_len(pSMB, byte_count);
5841 memcpy(data_offset, data, sizeof(FILE_BASIC_INFO));
5842 pSMB->ByteCount = cpu_to_le16(byte_count);
5843 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5844 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5846 cifs_dbg(FYI, "SetPathInfo (times) returned %d\n", rc);
5848 cifs_buf_release(pSMB);
5856 /* Can not be used to set time stamps yet (due to old DOS time format) */
5857 /* Can be used to set attributes */
5858 #if 0 /* Possibly not needed - since it turns out that strangely NT4 has a bug
5859 handling it anyway and NT4 was what we thought it would be needed for
5860 Do not delete it until we prove whether needed for Win9x though */
5862 CIFSSMBSetAttrLegacy(unsigned int xid, struct cifs_tcon *tcon, char *fileName,
5863 __u16 dos_attrs, const struct nls_table *nls_codepage)
5865 SETATTR_REQ *pSMB = NULL;
5866 SETATTR_RSP *pSMBr = NULL;
5871 cifs_dbg(FYI, "In SetAttrLegacy\n");
5874 rc = smb_init(SMB_COM_SETATTR, 8, tcon, (void **) &pSMB,
5879 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5881 ConvertToUTF16((__le16 *) pSMB->fileName, fileName,
5882 PATH_MAX, nls_codepage);
5883 name_len++; /* trailing null */
5885 } else { /* BB improve the check for buffer overruns BB */
5886 name_len = strnlen(fileName, PATH_MAX);
5887 name_len++; /* trailing null */
5888 strncpy(pSMB->fileName, fileName, name_len);
5890 pSMB->attr = cpu_to_le16(dos_attrs);
5891 pSMB->BufferFormat = 0x04;
5892 inc_rfc1001_len(pSMB, name_len + 1);
5893 pSMB->ByteCount = cpu_to_le16(name_len + 1);
5894 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5895 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5897 cifs_dbg(FYI, "Error in LegacySetAttr = %d\n", rc);
5899 cifs_buf_release(pSMB);
5902 goto SetAttrLgcyRetry;
5906 #endif /* temporarily unneeded SetAttr legacy function */
5909 cifs_fill_unix_set_info(FILE_UNIX_BASIC_INFO *data_offset,
5910 const struct cifs_unix_set_info_args *args)
5912 u64 uid = NO_CHANGE_64, gid = NO_CHANGE_64;
5913 u64 mode = args->mode;
5915 if (uid_valid(args->uid))
5916 uid = from_kuid(&init_user_ns, args->uid);
5917 if (gid_valid(args->gid))
5918 gid = from_kgid(&init_user_ns, args->gid);
5921 * Samba server ignores set of file size to zero due to bugs in some
5922 * older clients, but we should be precise - we use SetFileSize to
5923 * set file size and do not want to truncate file size to zero
5924 * accidentally as happened on one Samba server beta by putting
5925 * zero instead of -1 here
5927 data_offset->EndOfFile = cpu_to_le64(NO_CHANGE_64);
5928 data_offset->NumOfBytes = cpu_to_le64(NO_CHANGE_64);
5929 data_offset->LastStatusChange = cpu_to_le64(args->ctime);
5930 data_offset->LastAccessTime = cpu_to_le64(args->atime);
5931 data_offset->LastModificationTime = cpu_to_le64(args->mtime);
5932 data_offset->Uid = cpu_to_le64(uid);
5933 data_offset->Gid = cpu_to_le64(gid);
5934 /* better to leave device as zero when it is */
5935 data_offset->DevMajor = cpu_to_le64(MAJOR(args->device));
5936 data_offset->DevMinor = cpu_to_le64(MINOR(args->device));
5937 data_offset->Permissions = cpu_to_le64(mode);
5940 data_offset->Type = cpu_to_le32(UNIX_FILE);
5941 else if (S_ISDIR(mode))
5942 data_offset->Type = cpu_to_le32(UNIX_DIR);
5943 else if (S_ISLNK(mode))
5944 data_offset->Type = cpu_to_le32(UNIX_SYMLINK);
5945 else if (S_ISCHR(mode))
5946 data_offset->Type = cpu_to_le32(UNIX_CHARDEV);
5947 else if (S_ISBLK(mode))
5948 data_offset->Type = cpu_to_le32(UNIX_BLOCKDEV);
5949 else if (S_ISFIFO(mode))
5950 data_offset->Type = cpu_to_le32(UNIX_FIFO);
5951 else if (S_ISSOCK(mode))
5952 data_offset->Type = cpu_to_le32(UNIX_SOCKET);
5956 CIFSSMBUnixSetFileInfo(const unsigned int xid, struct cifs_tcon *tcon,
5957 const struct cifs_unix_set_info_args *args,
5958 u16 fid, u32 pid_of_opener)
5960 struct smb_com_transaction2_sfi_req *pSMB = NULL;
5963 u16 params, param_offset, offset, byte_count, count;
5965 cifs_dbg(FYI, "Set Unix Info (via SetFileInfo)\n");
5966 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
5971 pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
5972 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));
5975 pSMB->MaxSetupCount = 0;
5979 pSMB->Reserved2 = 0;
5980 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
5981 offset = param_offset + params;
5983 data_offset = (char *)pSMB +
5984 offsetof(struct smb_hdr, Protocol) + offset;
5986 count = sizeof(FILE_UNIX_BASIC_INFO);
5988 pSMB->MaxParameterCount = cpu_to_le16(2);
5989 /* BB find max SMB PDU from sess */
5990 pSMB->MaxDataCount = cpu_to_le16(1000);
5991 pSMB->SetupCount = 1;
5992 pSMB->Reserved3 = 0;
5993 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
5994 byte_count = 3 /* pad */ + params + count;
5995 pSMB->DataCount = cpu_to_le16(count);
5996 pSMB->ParameterCount = cpu_to_le16(params);
5997 pSMB->TotalDataCount = pSMB->DataCount;
5998 pSMB->TotalParameterCount = pSMB->ParameterCount;
5999 pSMB->ParameterOffset = cpu_to_le16(param_offset);
6000 pSMB->DataOffset = cpu_to_le16(offset);
6002 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_BASIC);
6003 pSMB->Reserved4 = 0;
6004 inc_rfc1001_len(pSMB, byte_count);
6005 pSMB->ByteCount = cpu_to_le16(byte_count);
6007 cifs_fill_unix_set_info((FILE_UNIX_BASIC_INFO *)data_offset, args);
6009 rc = SendReceiveNoRsp(xid, tcon->ses, (char *) pSMB, 0);
6010 cifs_small_buf_release(pSMB);
6012 cifs_dbg(FYI, "Send error in Set Time (SetFileInfo) = %d\n",
6015 /* Note: On -EAGAIN error only caller can retry on handle based calls
6016 since file handle passed in no longer valid */
6022 CIFSSMBUnixSetPathInfo(const unsigned int xid, struct cifs_tcon *tcon,
6023 const char *file_name,
6024 const struct cifs_unix_set_info_args *args,
6025 const struct nls_table *nls_codepage, int remap)
6027 TRANSACTION2_SPI_REQ *pSMB = NULL;
6028 TRANSACTION2_SPI_RSP *pSMBr = NULL;
6031 int bytes_returned = 0;
6032 FILE_UNIX_BASIC_INFO *data_offset;
6033 __u16 params, param_offset, offset, count, byte_count;
6035 cifs_dbg(FYI, "In SetUID/GID/Mode\n");
6037 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
6042 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
6044 cifsConvertToUTF16((__le16 *) pSMB->FileName, file_name,
6045 PATH_MAX, nls_codepage, remap);
6046 name_len++; /* trailing null */
6048 } else { /* BB improve the check for buffer overruns BB */
6049 name_len = strnlen(file_name, PATH_MAX);
6050 name_len++; /* trailing null */
6051 strncpy(pSMB->FileName, file_name, name_len);
6054 params = 6 + name_len;
6055 count = sizeof(FILE_UNIX_BASIC_INFO);
6056 pSMB->MaxParameterCount = cpu_to_le16(2);
6057 /* BB find max SMB PDU from sess structure BB */
6058 pSMB->MaxDataCount = cpu_to_le16(1000);
6059 pSMB->MaxSetupCount = 0;
6063 pSMB->Reserved2 = 0;
6064 param_offset = offsetof(struct smb_com_transaction2_spi_req,
6065 InformationLevel) - 4;
6066 offset = param_offset + params;
6068 (FILE_UNIX_BASIC_INFO *) ((char *) &pSMB->hdr.Protocol +
6070 memset(data_offset, 0, count);
6071 pSMB->DataOffset = cpu_to_le16(offset);
6072 pSMB->ParameterOffset = cpu_to_le16(param_offset);
6073 pSMB->SetupCount = 1;
6074 pSMB->Reserved3 = 0;
6075 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
6076 byte_count = 3 /* pad */ + params + count;
6077 pSMB->ParameterCount = cpu_to_le16(params);
6078 pSMB->DataCount = cpu_to_le16(count);
6079 pSMB->TotalParameterCount = pSMB->ParameterCount;
6080 pSMB->TotalDataCount = pSMB->DataCount;
6081 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_BASIC);
6082 pSMB->Reserved4 = 0;
6083 inc_rfc1001_len(pSMB, byte_count);
6085 cifs_fill_unix_set_info(data_offset, args);
6087 pSMB->ByteCount = cpu_to_le16(byte_count);
6088 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
6089 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
6091 cifs_dbg(FYI, "SetPathInfo (perms) returned %d\n", rc);
6093 cifs_buf_release(pSMB);
6099 #ifdef CONFIG_CIFS_XATTR
6101 * Do a path-based QUERY_ALL_EAS call and parse the result. This is a common
6102 * function used by listxattr and getxattr type calls. When ea_name is set,
6103 * it looks for that attribute name and stuffs that value into the EAData
6104 * buffer. When ea_name is NULL, it stuffs a list of attribute names into the
6105 * buffer. In both cases, the return value is either the length of the
6106 * resulting data or a negative error code. If EAData is a NULL pointer then
6107 * the data isn't copied to it, but the length is returned.
6110 CIFSSMBQAllEAs(const unsigned int xid, struct cifs_tcon *tcon,
6111 const unsigned char *searchName, const unsigned char *ea_name,
6112 char *EAData, size_t buf_size,
6113 struct cifs_sb_info *cifs_sb)
6115 /* BB assumes one setup word */
6116 TRANSACTION2_QPI_REQ *pSMB = NULL;
6117 TRANSACTION2_QPI_RSP *pSMBr = NULL;
6118 int remap = cifs_remap(cifs_sb);
6119 struct nls_table *nls_codepage = cifs_sb->local_nls;
6123 struct fealist *ea_response_data;
6124 struct fea *temp_fea;
6127 __u16 params, byte_count, data_offset;
6128 unsigned int ea_name_len = ea_name ? strlen(ea_name) : 0;
6130 cifs_dbg(FYI, "In Query All EAs path %s\n", searchName);
6132 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
6137 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
6139 cifsConvertToUTF16((__le16 *) pSMB->FileName, searchName,
6140 PATH_MAX, nls_codepage, remap);
6141 list_len++; /* trailing null */
6143 } else { /* BB improve the check for buffer overruns BB */
6144 list_len = strnlen(searchName, PATH_MAX);
6145 list_len++; /* trailing null */
6146 strncpy(pSMB->FileName, searchName, list_len);
6149 params = 2 /* level */ + 4 /* reserved */ + list_len /* includes NUL */;
6150 pSMB->TotalDataCount = 0;
6151 pSMB->MaxParameterCount = cpu_to_le16(2);
6152 /* BB find exact max SMB PDU from sess structure BB */
6153 pSMB->MaxDataCount = cpu_to_le16(CIFSMaxBufSize);
6154 pSMB->MaxSetupCount = 0;
6158 pSMB->Reserved2 = 0;
6159 pSMB->ParameterOffset = cpu_to_le16(offsetof(
6160 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
6161 pSMB->DataCount = 0;
6162 pSMB->DataOffset = 0;
6163 pSMB->SetupCount = 1;
6164 pSMB->Reserved3 = 0;
6165 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
6166 byte_count = params + 1 /* pad */ ;
6167 pSMB->TotalParameterCount = cpu_to_le16(params);
6168 pSMB->ParameterCount = pSMB->TotalParameterCount;
6169 pSMB->InformationLevel = cpu_to_le16(SMB_INFO_QUERY_ALL_EAS);
6170 pSMB->Reserved4 = 0;
6171 inc_rfc1001_len(pSMB, byte_count);
6172 pSMB->ByteCount = cpu_to_le16(byte_count);
6174 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
6175 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
6177 cifs_dbg(FYI, "Send error in QueryAllEAs = %d\n", rc);
6182 /* BB also check enough total bytes returned */
6183 /* BB we need to improve the validity checking
6184 of these trans2 responses */
6186 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
6187 if (rc || get_bcc(&pSMBr->hdr) < 4) {
6188 rc = -EIO; /* bad smb */
6192 /* check that length of list is not more than bcc */
6193 /* check that each entry does not go beyond length
6195 /* check that each element of each entry does not
6196 go beyond end of list */
6197 /* validate_trans2_offsets() */
6198 /* BB check if start of smb + data_offset > &bcc+ bcc */
6200 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
6201 ea_response_data = (struct fealist *)
6202 (((char *) &pSMBr->hdr.Protocol) + data_offset);
6204 list_len = le32_to_cpu(ea_response_data->list_len);
6205 cifs_dbg(FYI, "ea length %d\n", list_len);
6206 if (list_len <= 8) {
6207 cifs_dbg(FYI, "empty EA list returned from server\n");
6208 /* didn't find the named attribute */
6214 /* make sure list_len doesn't go past end of SMB */
6215 end_of_smb = (char *)pByteArea(&pSMBr->hdr) + get_bcc(&pSMBr->hdr);
6216 if ((char *)ea_response_data + list_len > end_of_smb) {
6217 cifs_dbg(FYI, "EA list appears to go beyond SMB\n");
6222 /* account for ea list len */
6224 temp_fea = ea_response_data->list;
6225 temp_ptr = (char *)temp_fea;
6226 while (list_len > 0) {
6227 unsigned int name_len;
6232 /* make sure we can read name_len and value_len */
6234 cifs_dbg(FYI, "EA entry goes beyond length of list\n");
6239 name_len = temp_fea->name_len;
6240 value_len = le16_to_cpu(temp_fea->value_len);
6241 list_len -= name_len + 1 + value_len;
6243 cifs_dbg(FYI, "EA entry goes beyond length of list\n");
6249 if (ea_name_len == name_len &&
6250 memcmp(ea_name, temp_ptr, name_len) == 0) {
6251 temp_ptr += name_len + 1;
6255 if ((size_t)value_len > buf_size) {
6259 memcpy(EAData, temp_ptr, value_len);
6263 /* account for prefix user. and trailing null */
6264 rc += (5 + 1 + name_len);
6265 if (rc < (int) buf_size) {
6266 memcpy(EAData, "user.", 5);
6268 memcpy(EAData, temp_ptr, name_len);
6270 /* null terminate name */
6273 } else if (buf_size == 0) {
6274 /* skip copy - calc size only */
6276 /* stop before overrun buffer */
6281 temp_ptr += name_len + 1 + value_len;
6282 temp_fea = (struct fea *)temp_ptr;
6285 /* didn't find the named attribute */
6290 cifs_buf_release(pSMB);
6298 CIFSSMBSetEA(const unsigned int xid, struct cifs_tcon *tcon,
6299 const char *fileName, const char *ea_name, const void *ea_value,
6300 const __u16 ea_value_len, const struct nls_table *nls_codepage,
6301 struct cifs_sb_info *cifs_sb)
6303 struct smb_com_transaction2_spi_req *pSMB = NULL;
6304 struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
6305 struct fealist *parm_data;
6308 int bytes_returned = 0;
6309 __u16 params, param_offset, byte_count, offset, count;
6310 int remap = cifs_remap(cifs_sb);
6312 cifs_dbg(FYI, "In SetEA\n");
6314 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
6319 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
6321 cifsConvertToUTF16((__le16 *) pSMB->FileName, fileName,
6322 PATH_MAX, nls_codepage, remap);
6323 name_len++; /* trailing null */
6325 } else { /* BB improve the check for buffer overruns BB */
6326 name_len = strnlen(fileName, PATH_MAX);
6327 name_len++; /* trailing null */
6328 strncpy(pSMB->FileName, fileName, name_len);
6331 params = 6 + name_len;
6333 /* done calculating parms using name_len of file name,
6334 now use name_len to calculate length of ea name
6335 we are going to create in the inode xattrs */
6336 if (ea_name == NULL)
6339 name_len = strnlen(ea_name, 255);
6341 count = sizeof(*parm_data) + ea_value_len + name_len;
6342 pSMB->MaxParameterCount = cpu_to_le16(2);
6343 /* BB find max SMB PDU from sess */
6344 pSMB->MaxDataCount = cpu_to_le16(1000);
6345 pSMB->MaxSetupCount = 0;
6349 pSMB->Reserved2 = 0;
6350 param_offset = offsetof(struct smb_com_transaction2_spi_req,
6351 InformationLevel) - 4;
6352 offset = param_offset + params;
6353 pSMB->InformationLevel =
6354 cpu_to_le16(SMB_SET_FILE_EA);
6356 parm_data = (void *)pSMB + offsetof(struct smb_hdr, Protocol) + offset;
6357 pSMB->ParameterOffset = cpu_to_le16(param_offset);
6358 pSMB->DataOffset = cpu_to_le16(offset);
6359 pSMB->SetupCount = 1;
6360 pSMB->Reserved3 = 0;
6361 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
6362 byte_count = 3 /* pad */ + params + count;
6363 pSMB->DataCount = cpu_to_le16(count);
6364 parm_data->list_len = cpu_to_le32(count);
6365 parm_data->list[0].EA_flags = 0;
6366 /* we checked above that name len is less than 255 */
6367 parm_data->list[0].name_len = (__u8)name_len;
6368 /* EA names are always ASCII */
6370 strncpy(parm_data->list[0].name, ea_name, name_len);
6371 parm_data->list[0].name[name_len] = 0;
6372 parm_data->list[0].value_len = cpu_to_le16(ea_value_len);
6373 /* caller ensures that ea_value_len is less than 64K but
6374 we need to ensure that it fits within the smb */
6376 /*BB add length check to see if it would fit in
6377 negotiated SMB buffer size BB */
6378 /* if (ea_value_len > buffer_size - 512 (enough for header)) */
6380 memcpy(parm_data->list[0].name+name_len+1,
6381 ea_value, ea_value_len);
6383 pSMB->TotalDataCount = pSMB->DataCount;
6384 pSMB->ParameterCount = cpu_to_le16(params);
6385 pSMB->TotalParameterCount = pSMB->ParameterCount;
6386 pSMB->Reserved4 = 0;
6387 inc_rfc1001_len(pSMB, byte_count);
6388 pSMB->ByteCount = cpu_to_le16(byte_count);
6389 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
6390 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
6392 cifs_dbg(FYI, "SetPathInfo (EA) returned %d\n", rc);
6394 cifs_buf_release(pSMB);
6403 #ifdef CONFIG_CIFS_DNOTIFY_EXPERIMENTAL /* BB unused temporarily */
6405 * Years ago the kernel added a "dnotify" function for Samba server,
6406 * to allow network clients (such as Windows) to display updated
6407 * lists of files in directory listings automatically when
6408 * files are added by one user when another user has the
6409 * same directory open on their desktop. The Linux cifs kernel
6410 * client hooked into the kernel side of this interface for
6411 * the same reason, but ironically when the VFS moved from
6412 * "dnotify" to "inotify" it became harder to plug in Linux
6413 * network file system clients (the most obvious use case
6414 * for notify interfaces is when multiple users can update
6415 * the contents of the same directory - exactly what network
6416 * file systems can do) although the server (Samba) could
6417 * still use it. For the short term we leave the worker
6418 * function ifdeffed out (below) until inotify is fixed
6419 * in the VFS to make it easier to plug in network file
6420 * system clients. If inotify turns out to be permanently
6421 * incompatible for network fs clients, we could instead simply
6422 * expose this config flag by adding a future cifs (and smb2) notify ioctl.
6424 int CIFSSMBNotify(const unsigned int xid, struct cifs_tcon *tcon,
6425 const int notify_subdirs, const __u16 netfid,
6426 __u32 filter, struct file *pfile, int multishot,
6427 const struct nls_table *nls_codepage)
6430 struct smb_com_transaction_change_notify_req *pSMB = NULL;
6431 struct smb_com_ntransaction_change_notify_rsp *pSMBr = NULL;
6432 struct dir_notify_req *dnotify_req;
6435 cifs_dbg(FYI, "In CIFSSMBNotify for file handle %d\n", (int)netfid);
6436 rc = smb_init(SMB_COM_NT_TRANSACT, 23, tcon, (void **) &pSMB,
6441 pSMB->TotalParameterCount = 0 ;
6442 pSMB->TotalDataCount = 0;
6443 pSMB->MaxParameterCount = cpu_to_le32(2);
6444 pSMB->MaxDataCount = cpu_to_le32(CIFSMaxBufSize & 0xFFFFFF00);
6445 pSMB->MaxSetupCount = 4;
6447 pSMB->ParameterOffset = 0;
6448 pSMB->DataCount = 0;
6449 pSMB->DataOffset = 0;
6450 pSMB->SetupCount = 4; /* single byte does not need le conversion */
6451 pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_NOTIFY_CHANGE);
6452 pSMB->ParameterCount = pSMB->TotalParameterCount;
6454 pSMB->WatchTree = 1; /* one byte - no le conversion needed */
6455 pSMB->Reserved2 = 0;
6456 pSMB->CompletionFilter = cpu_to_le32(filter);
6457 pSMB->Fid = netfid; /* file handle always le */
6458 pSMB->ByteCount = 0;
6460 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
6461 (struct smb_hdr *)pSMBr, &bytes_returned,
6464 cifs_dbg(FYI, "Error in Notify = %d\n", rc);
6466 /* Add file to outstanding requests */
6467 /* BB change to kmem cache alloc */
6468 dnotify_req = kmalloc(
6469 sizeof(struct dir_notify_req),
6472 dnotify_req->Pid = pSMB->hdr.Pid;
6473 dnotify_req->PidHigh = pSMB->hdr.PidHigh;
6474 dnotify_req->Mid = pSMB->hdr.Mid;
6475 dnotify_req->Tid = pSMB->hdr.Tid;
6476 dnotify_req->Uid = pSMB->hdr.Uid;
6477 dnotify_req->netfid = netfid;
6478 dnotify_req->pfile = pfile;
6479 dnotify_req->filter = filter;
6480 dnotify_req->multishot = multishot;
6481 spin_lock(&GlobalMid_Lock);
6482 list_add_tail(&dnotify_req->lhead,
6483 &GlobalDnotifyReqList);
6484 spin_unlock(&GlobalMid_Lock);
6488 cifs_buf_release(pSMB);
6491 #endif /* was needed for dnotify, and will be needed for inotify when VFS fix */