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 <asm/uaccess.h>
40 #include "cifsproto.h"
41 #include "cifs_unicode.h"
42 #include "cifs_debug.h"
44 #ifdef CONFIG_CIFS_POSIX
49 #ifdef CONFIG_CIFS_WEAK_PW_HASH
50 {LANMAN_PROT, "\2LM1.2X002"},
51 {LANMAN2_PROT, "\2LANMAN2.1"},
52 #endif /* weak password hashing for legacy clients */
53 {CIFS_PROT, "\2NT LM 0.12"},
54 {POSIX_PROT, "\2POSIX 2"},
62 #ifdef CONFIG_CIFS_WEAK_PW_HASH
63 {LANMAN_PROT, "\2LM1.2X002"},
64 {LANMAN2_PROT, "\2LANMAN2.1"},
65 #endif /* weak password hashing for legacy clients */
66 {CIFS_PROT, "\2NT LM 0.12"},
71 /* define the number of elements in the cifs dialect array */
72 #ifdef CONFIG_CIFS_POSIX
73 #ifdef CONFIG_CIFS_WEAK_PW_HASH
74 #define CIFS_NUM_PROT 4
76 #define CIFS_NUM_PROT 2
77 #endif /* CIFS_WEAK_PW_HASH */
79 #ifdef CONFIG_CIFS_WEAK_PW_HASH
80 #define CIFS_NUM_PROT 3
82 #define CIFS_NUM_PROT 1
83 #endif /* CONFIG_CIFS_WEAK_PW_HASH */
84 #endif /* CIFS_POSIX */
86 /* Mark as invalid, all open files on tree connections since they
87 were closed when session to server was lost */
88 static void mark_open_files_invalid(struct cifsTconInfo *pTcon)
90 struct cifsFileInfo *open_file = NULL;
91 struct list_head *tmp;
92 struct list_head *tmp1;
94 /* list all files open on tree connection and mark them invalid */
95 spin_lock(&cifs_file_list_lock);
96 list_for_each_safe(tmp, tmp1, &pTcon->openFileList) {
97 open_file = list_entry(tmp, struct cifsFileInfo, tlist);
98 open_file->invalidHandle = true;
99 open_file->oplock_break_cancelled = true;
101 spin_unlock(&cifs_file_list_lock);
102 /* BB Add call to invalidate_inodes(sb) for all superblocks mounted
106 /* reconnect the socket, tcon, and smb session if needed */
108 cifs_reconnect_tcon(struct cifsTconInfo *tcon, int smb_command)
111 struct cifsSesInfo *ses;
112 struct TCP_Server_Info *server;
113 struct nls_table *nls_codepage;
116 * SMBs NegProt, SessSetup, uLogoff do not have tcon yet so check for
117 * tcp and smb session status done differently for those three - in the
124 server = ses->server;
127 * only tree disconnect, open, and write, (and ulogoff which does not
128 * have tcon) are allowed as we start force umount
130 if (tcon->tidStatus == CifsExiting) {
131 if (smb_command != SMB_COM_WRITE_ANDX &&
132 smb_command != SMB_COM_OPEN_ANDX &&
133 smb_command != SMB_COM_TREE_DISCONNECT) {
134 cFYI(1, "can not send cmd %d while umounting",
141 * Give demultiplex thread up to 10 seconds to reconnect, should be
142 * greater than cifs socket timeout which is 7 seconds
144 while (server->tcpStatus == CifsNeedReconnect) {
145 wait_event_interruptible_timeout(server->response_q,
146 (server->tcpStatus != CifsNeedReconnect), 10 * HZ);
148 /* are we still trying to reconnect? */
149 if (server->tcpStatus != CifsNeedReconnect)
153 * on "soft" mounts we wait once. Hard mounts keep
154 * retrying until process is killed or server comes
158 cFYI(1, "gave up waiting on reconnect in smb_init");
163 if (!ses->need_reconnect && !tcon->need_reconnect)
166 nls_codepage = load_nls_default();
169 * need to prevent multiple threads trying to simultaneously
170 * reconnect the same SMB session
172 mutex_lock(&ses->session_mutex);
173 rc = cifs_negotiate_protocol(0, ses);
174 if (rc == 0 && ses->need_reconnect)
175 rc = cifs_setup_session(0, ses, nls_codepage);
177 /* do we need to reconnect tcon? */
178 if (rc || !tcon->need_reconnect) {
179 mutex_unlock(&ses->session_mutex);
183 mark_open_files_invalid(tcon);
184 rc = CIFSTCon(0, ses, tcon->treeName, tcon, nls_codepage);
185 mutex_unlock(&ses->session_mutex);
186 cFYI(1, "reconnect tcon rc = %d", rc);
192 * FIXME: check if wsize needs updated due to negotiated smb buffer
195 atomic_inc(&tconInfoReconnectCount);
197 /* tell server Unix caps we support */
198 if (ses->capabilities & CAP_UNIX)
199 reset_cifs_unix_caps(0, tcon, NULL, NULL);
202 * Removed call to reopen open files here. It is safer (and faster) to
203 * reopen files one at a time as needed in read and write.
205 * FIXME: what about file locks? don't we need to reclaim them ASAP?
210 * Check if handle based operation so we know whether we can continue
211 * or not without returning to caller to reset file handle
213 switch (smb_command) {
214 case SMB_COM_READ_ANDX:
215 case SMB_COM_WRITE_ANDX:
217 case SMB_COM_FIND_CLOSE2:
218 case SMB_COM_LOCKING_ANDX:
222 unload_nls(nls_codepage);
226 /* Allocate and return pointer to an SMB request buffer, and set basic
227 SMB information in the SMB header. If the return code is zero, this
228 function must have filled in request_buf pointer */
230 small_smb_init(int smb_command, int wct, struct cifsTconInfo *tcon,
235 rc = cifs_reconnect_tcon(tcon, smb_command);
239 *request_buf = cifs_small_buf_get();
240 if (*request_buf == NULL) {
241 /* BB should we add a retry in here if not a writepage? */
245 header_assemble((struct smb_hdr *) *request_buf, smb_command,
249 cifs_stats_inc(&tcon->num_smbs_sent);
255 small_smb_init_no_tc(const int smb_command, const int wct,
256 struct cifsSesInfo *ses, void **request_buf)
259 struct smb_hdr *buffer;
261 rc = small_smb_init(smb_command, wct, NULL, request_buf);
265 buffer = (struct smb_hdr *)*request_buf;
266 buffer->Mid = GetNextMid(ses->server);
267 if (ses->capabilities & CAP_UNICODE)
268 buffer->Flags2 |= SMBFLG2_UNICODE;
269 if (ses->capabilities & CAP_STATUS32)
270 buffer->Flags2 |= SMBFLG2_ERR_STATUS;
272 /* uid, tid can stay at zero as set in header assemble */
274 /* BB add support for turning on the signing when
275 this function is used after 1st of session setup requests */
280 /* If the return code is zero, this function must fill in request_buf pointer */
282 __smb_init(int smb_command, int wct, struct cifsTconInfo *tcon,
283 void **request_buf, void **response_buf)
285 *request_buf = cifs_buf_get();
286 if (*request_buf == NULL) {
287 /* BB should we add a retry in here if not a writepage? */
290 /* Although the original thought was we needed the response buf for */
291 /* potential retries of smb operations it turns out we can determine */
292 /* from the mid flags when the request buffer can be resent without */
293 /* having to use a second distinct buffer for the response */
295 *response_buf = *request_buf;
297 header_assemble((struct smb_hdr *) *request_buf, smb_command, tcon,
301 cifs_stats_inc(&tcon->num_smbs_sent);
306 /* If the return code is zero, this function must fill in request_buf pointer */
308 smb_init(int smb_command, int wct, struct cifsTconInfo *tcon,
309 void **request_buf, void **response_buf)
313 rc = cifs_reconnect_tcon(tcon, smb_command);
317 return __smb_init(smb_command, wct, tcon, request_buf, response_buf);
321 smb_init_no_reconnect(int smb_command, int wct, struct cifsTconInfo *tcon,
322 void **request_buf, void **response_buf)
324 if (tcon->ses->need_reconnect || tcon->need_reconnect)
327 return __smb_init(smb_command, wct, tcon, request_buf, response_buf);
330 static int validate_t2(struct smb_t2_rsp *pSMB)
332 unsigned int total_size;
334 /* check for plausible wct */
335 if (pSMB->hdr.WordCount < 10)
338 /* check for parm and data offset going beyond end of smb */
339 if (get_unaligned_le16(&pSMB->t2_rsp.ParameterOffset) > 1024 ||
340 get_unaligned_le16(&pSMB->t2_rsp.DataOffset) > 1024)
343 total_size = get_unaligned_le16(&pSMB->t2_rsp.ParameterCount);
344 if (total_size >= 512)
347 /* check that bcc is at least as big as parms + data, and that it is
348 * less than negotiated smb buffer
350 total_size += get_unaligned_le16(&pSMB->t2_rsp.DataCount);
351 if (total_size > get_bcc(&pSMB->hdr) ||
352 total_size >= CIFSMaxBufSize + MAX_CIFS_HDR_SIZE)
357 cifs_dump_mem("Invalid transact2 SMB: ", (char *)pSMB,
358 sizeof(struct smb_t2_rsp) + 16);
362 static inline void inc_rfc1001_len(void *pSMB, int count)
364 struct smb_hdr *hdr = (struct smb_hdr *)pSMB;
366 be32_add_cpu(&hdr->smb_buf_length, count);
370 CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses)
373 NEGOTIATE_RSP *pSMBr;
377 struct TCP_Server_Info *server;
379 unsigned int secFlags;
382 server = ses->server;
387 rc = smb_init(SMB_COM_NEGOTIATE, 0, NULL /* no tcon yet */ ,
388 (void **) &pSMB, (void **) &pSMBr);
392 /* if any of auth flags (ie not sign or seal) are overriden use them */
393 if (ses->overrideSecFlg & (~(CIFSSEC_MUST_SIGN | CIFSSEC_MUST_SEAL)))
394 secFlags = ses->overrideSecFlg; /* BB FIXME fix sign flags? */
395 else /* if override flags set only sign/seal OR them with global auth */
396 secFlags = global_secflags | ses->overrideSecFlg;
398 cFYI(1, "secFlags 0x%x", secFlags);
400 pSMB->hdr.Mid = GetNextMid(server);
401 pSMB->hdr.Flags2 |= (SMBFLG2_UNICODE | SMBFLG2_ERR_STATUS);
403 if ((secFlags & CIFSSEC_MUST_KRB5) == CIFSSEC_MUST_KRB5)
404 pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC;
405 else if ((secFlags & CIFSSEC_AUTH_MASK) == CIFSSEC_MAY_KRB5) {
406 cFYI(1, "Kerberos only mechanism, enable extended security");
407 pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC;
408 } else if ((secFlags & CIFSSEC_MUST_NTLMSSP) == CIFSSEC_MUST_NTLMSSP)
409 pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC;
410 else if ((secFlags & CIFSSEC_AUTH_MASK) == CIFSSEC_MAY_NTLMSSP) {
411 cFYI(1, "NTLMSSP only mechanism, enable extended security");
412 pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC;
416 for (i = 0; i < CIFS_NUM_PROT; i++) {
417 strncpy(pSMB->DialectsArray+count, protocols[i].name, 16);
418 count += strlen(protocols[i].name) + 1;
419 /* null at end of source and target buffers anyway */
421 inc_rfc1001_len(pSMB, count);
422 pSMB->ByteCount = cpu_to_le16(count);
424 rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB,
425 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
429 server->dialect = le16_to_cpu(pSMBr->DialectIndex);
430 cFYI(1, "Dialect: %d", server->dialect);
431 /* Check wct = 1 error case */
432 if ((pSMBr->hdr.WordCount < 13) || (server->dialect == BAD_PROT)) {
433 /* core returns wct = 1, but we do not ask for core - otherwise
434 small wct just comes when dialect index is -1 indicating we
435 could not negotiate a common dialect */
438 #ifdef CONFIG_CIFS_WEAK_PW_HASH
439 } else if ((pSMBr->hdr.WordCount == 13)
440 && ((server->dialect == LANMAN_PROT)
441 || (server->dialect == LANMAN2_PROT))) {
443 struct lanman_neg_rsp *rsp = (struct lanman_neg_rsp *)pSMBr;
445 if ((secFlags & CIFSSEC_MAY_LANMAN) ||
446 (secFlags & CIFSSEC_MAY_PLNTXT))
447 server->secType = LANMAN;
449 cERROR(1, "mount failed weak security disabled"
450 " in /proc/fs/cifs/SecurityFlags");
454 server->secMode = (__u8)le16_to_cpu(rsp->SecurityMode);
455 server->maxReq = le16_to_cpu(rsp->MaxMpxCount);
456 server->maxBuf = min((__u32)le16_to_cpu(rsp->MaxBufSize),
457 (__u32)CIFSMaxBufSize + MAX_CIFS_HDR_SIZE);
458 server->max_vcs = le16_to_cpu(rsp->MaxNumberVcs);
459 /* even though we do not use raw we might as well set this
460 accurately, in case we ever find a need for it */
461 if ((le16_to_cpu(rsp->RawMode) & RAW_ENABLE) == RAW_ENABLE) {
462 server->max_rw = 0xFF00;
463 server->capabilities = CAP_MPX_MODE | CAP_RAW_MODE;
465 server->max_rw = 0;/* do not need to use raw anyway */
466 server->capabilities = CAP_MPX_MODE;
468 tmp = (__s16)le16_to_cpu(rsp->ServerTimeZone);
470 /* OS/2 often does not set timezone therefore
471 * we must use server time to calc time zone.
472 * Could deviate slightly from the right zone.
473 * Smallest defined timezone difference is 15 minutes
474 * (i.e. Nepal). Rounding up/down is done to match
477 int val, seconds, remain, result;
478 struct timespec ts, utc;
480 ts = cnvrtDosUnixTm(rsp->SrvTime.Date,
481 rsp->SrvTime.Time, 0);
482 cFYI(1, "SrvTime %d sec since 1970 (utc: %d) diff: %d",
483 (int)ts.tv_sec, (int)utc.tv_sec,
484 (int)(utc.tv_sec - ts.tv_sec));
485 val = (int)(utc.tv_sec - ts.tv_sec);
487 result = (seconds / MIN_TZ_ADJ) * MIN_TZ_ADJ;
488 remain = seconds % MIN_TZ_ADJ;
489 if (remain >= (MIN_TZ_ADJ / 2))
490 result += MIN_TZ_ADJ;
493 server->timeAdj = result;
495 server->timeAdj = (int)tmp;
496 server->timeAdj *= 60; /* also in seconds */
498 cFYI(1, "server->timeAdj: %d seconds", server->timeAdj);
501 /* BB get server time for time conversions and add
502 code to use it and timezone since this is not UTC */
504 if (rsp->EncryptionKeyLength ==
505 cpu_to_le16(CIFS_CRYPTO_KEY_SIZE)) {
506 memcpy(ses->server->cryptkey, rsp->EncryptionKey,
507 CIFS_CRYPTO_KEY_SIZE);
508 } else if (server->secMode & SECMODE_PW_ENCRYPT) {
509 rc = -EIO; /* need cryptkey unless plain text */
513 cFYI(1, "LANMAN negotiated");
514 /* we will not end up setting signing flags - as no signing
515 was in LANMAN and server did not return the flags on */
517 #else /* weak security disabled */
518 } else if (pSMBr->hdr.WordCount == 13) {
519 cERROR(1, "mount failed, cifs module not built "
520 "with CIFS_WEAK_PW_HASH support");
522 #endif /* WEAK_PW_HASH */
524 } else if (pSMBr->hdr.WordCount != 17) {
529 /* else wct == 17 NTLM */
530 server->secMode = pSMBr->SecurityMode;
531 if ((server->secMode & SECMODE_USER) == 0)
532 cFYI(1, "share mode security");
534 if ((server->secMode & SECMODE_PW_ENCRYPT) == 0)
535 #ifdef CONFIG_CIFS_WEAK_PW_HASH
536 if ((secFlags & CIFSSEC_MAY_PLNTXT) == 0)
537 #endif /* CIFS_WEAK_PW_HASH */
538 cERROR(1, "Server requests plain text password"
539 " but client support disabled");
541 if ((secFlags & CIFSSEC_MUST_NTLMV2) == CIFSSEC_MUST_NTLMV2)
542 server->secType = NTLMv2;
543 else if (secFlags & CIFSSEC_MAY_NTLM)
544 server->secType = NTLM;
545 else if (secFlags & CIFSSEC_MAY_NTLMV2)
546 server->secType = NTLMv2;
547 else if (secFlags & CIFSSEC_MAY_KRB5)
548 server->secType = Kerberos;
549 else if (secFlags & CIFSSEC_MAY_NTLMSSP)
550 server->secType = RawNTLMSSP;
551 else if (secFlags & CIFSSEC_MAY_LANMAN)
552 server->secType = LANMAN;
555 cERROR(1, "Invalid security type");
558 /* else ... any others ...? */
560 /* one byte, so no need to convert this or EncryptionKeyLen from
562 server->maxReq = le16_to_cpu(pSMBr->MaxMpxCount);
563 /* probably no need to store and check maxvcs */
564 server->maxBuf = min(le32_to_cpu(pSMBr->MaxBufferSize),
565 (__u32) CIFSMaxBufSize + MAX_CIFS_HDR_SIZE);
566 server->max_rw = le32_to_cpu(pSMBr->MaxRawSize);
567 cFYI(DBG2, "Max buf = %d", ses->server->maxBuf);
568 server->capabilities = le32_to_cpu(pSMBr->Capabilities);
569 server->timeAdj = (int)(__s16)le16_to_cpu(pSMBr->ServerTimeZone);
570 server->timeAdj *= 60;
571 if (pSMBr->EncryptionKeyLength == CIFS_CRYPTO_KEY_SIZE) {
572 memcpy(ses->server->cryptkey, pSMBr->u.EncryptionKey,
573 CIFS_CRYPTO_KEY_SIZE);
574 } else if ((pSMBr->hdr.Flags2 & SMBFLG2_EXT_SEC)
575 && (pSMBr->EncryptionKeyLength == 0)) {
576 /* decode security blob */
577 } else if (server->secMode & SECMODE_PW_ENCRYPT) {
578 rc = -EIO; /* no crypt key only if plain text pwd */
582 /* BB might be helpful to save off the domain of server here */
584 if ((pSMBr->hdr.Flags2 & SMBFLG2_EXT_SEC) &&
585 (server->capabilities & CAP_EXTENDED_SECURITY)) {
586 count = get_bcc(&pSMBr->hdr);
591 spin_lock(&cifs_tcp_ses_lock);
592 if (server->srv_count > 1) {
593 spin_unlock(&cifs_tcp_ses_lock);
594 if (memcmp(server->server_GUID,
595 pSMBr->u.extended_response.
597 cFYI(1, "server UID changed");
598 memcpy(server->server_GUID,
599 pSMBr->u.extended_response.GUID,
603 spin_unlock(&cifs_tcp_ses_lock);
604 memcpy(server->server_GUID,
605 pSMBr->u.extended_response.GUID, 16);
609 server->secType = RawNTLMSSP;
611 rc = decode_negTokenInit(pSMBr->u.extended_response.
612 SecurityBlob, count - 16,
618 if (server->secType == Kerberos) {
619 if (!server->sec_kerberos &&
620 !server->sec_mskerberos)
622 } else if (server->secType == RawNTLMSSP) {
623 if (!server->sec_ntlmssp)
629 server->capabilities &= ~CAP_EXTENDED_SECURITY;
631 #ifdef CONFIG_CIFS_WEAK_PW_HASH
634 if ((secFlags & CIFSSEC_MAY_SIGN) == 0) {
635 /* MUST_SIGN already includes the MAY_SIGN FLAG
636 so if this is zero it means that signing is disabled */
637 cFYI(1, "Signing disabled");
638 if (server->secMode & SECMODE_SIGN_REQUIRED) {
639 cERROR(1, "Server requires "
640 "packet signing to be enabled in "
641 "/proc/fs/cifs/SecurityFlags.");
645 ~(SECMODE_SIGN_ENABLED | SECMODE_SIGN_REQUIRED);
646 } else if ((secFlags & CIFSSEC_MUST_SIGN) == CIFSSEC_MUST_SIGN) {
647 /* signing required */
648 cFYI(1, "Must sign - secFlags 0x%x", secFlags);
649 if ((server->secMode &
650 (SECMODE_SIGN_ENABLED | SECMODE_SIGN_REQUIRED)) == 0) {
651 cERROR(1, "signing required but server lacks support");
654 server->secMode |= SECMODE_SIGN_REQUIRED;
656 /* signing optional ie CIFSSEC_MAY_SIGN */
657 if ((server->secMode & SECMODE_SIGN_REQUIRED) == 0)
659 ~(SECMODE_SIGN_ENABLED | SECMODE_SIGN_REQUIRED);
663 cifs_buf_release(pSMB);
665 cFYI(1, "negprot rc %d", rc);
670 CIFSSMBTDis(const int xid, struct cifsTconInfo *tcon)
672 struct smb_hdr *smb_buffer;
675 cFYI(1, "In tree disconnect");
677 /* BB: do we need to check this? These should never be NULL. */
678 if ((tcon->ses == NULL) || (tcon->ses->server == NULL))
682 * No need to return error on this operation if tid invalidated and
683 * closed on server already e.g. due to tcp session crashing. Also,
684 * the tcon is no longer on the list, so no need to take lock before
687 if ((tcon->need_reconnect) || (tcon->ses->need_reconnect))
690 rc = small_smb_init(SMB_COM_TREE_DISCONNECT, 0, tcon,
691 (void **)&smb_buffer);
695 rc = SendReceiveNoRsp(xid, tcon->ses, smb_buffer, 0);
697 cFYI(1, "Tree disconnect failed %d", rc);
699 /* No need to return error on this operation if tid invalidated and
700 closed on server already e.g. due to tcp session crashing */
708 * This is a no-op for now. We're not really interested in the reply, but
709 * rather in the fact that the server sent one and that server->lstrp
712 * FIXME: maybe we should consider checking that the reply matches request?
715 cifs_echo_callback(struct mid_q_entry *mid)
717 struct TCP_Server_Info *server = mid->callback_data;
719 DeleteMidQEntry(mid);
720 atomic_dec(&server->inFlight);
721 wake_up(&server->request_q);
725 CIFSSMBEcho(struct TCP_Server_Info *server)
731 cFYI(1, "In echo request");
733 rc = small_smb_init(SMB_COM_ECHO, 0, NULL, (void **)&smb);
737 /* set up echo request */
738 smb->hdr.Tid = 0xffff;
739 smb->hdr.WordCount = 1;
740 put_unaligned_le16(1, &smb->EchoCount);
741 put_bcc(1, &smb->hdr);
743 inc_rfc1001_len(smb, 3);
745 iov.iov_len = be32_to_cpu(smb->hdr.smb_buf_length) + 4;
747 rc = cifs_call_async(server, &iov, 1, cifs_echo_callback, server, true);
749 cFYI(1, "Echo request failed: %d", rc);
751 cifs_small_buf_release(smb);
757 CIFSSMBLogoff(const int xid, struct cifsSesInfo *ses)
759 LOGOFF_ANDX_REQ *pSMB;
762 cFYI(1, "In SMBLogoff for session disconnect");
765 * BB: do we need to check validity of ses and server? They should
766 * always be valid since we have an active reference. If not, that
767 * should probably be a BUG()
769 if (!ses || !ses->server)
772 mutex_lock(&ses->session_mutex);
773 if (ses->need_reconnect)
774 goto session_already_dead; /* no need to send SMBlogoff if uid
775 already closed due to reconnect */
776 rc = small_smb_init(SMB_COM_LOGOFF_ANDX, 2, NULL, (void **)&pSMB);
778 mutex_unlock(&ses->session_mutex);
782 pSMB->hdr.Mid = GetNextMid(ses->server);
784 if (ses->server->secMode &
785 (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
786 pSMB->hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
788 pSMB->hdr.Uid = ses->Suid;
790 pSMB->AndXCommand = 0xFF;
791 rc = SendReceiveNoRsp(xid, ses, (struct smb_hdr *) pSMB, 0);
792 session_already_dead:
793 mutex_unlock(&ses->session_mutex);
795 /* if session dead then we do not need to do ulogoff,
796 since server closed smb session, no sense reporting
804 CIFSPOSIXDelFile(const int xid, struct cifsTconInfo *tcon, const char *fileName,
805 __u16 type, const struct nls_table *nls_codepage, int remap)
807 TRANSACTION2_SPI_REQ *pSMB = NULL;
808 TRANSACTION2_SPI_RSP *pSMBr = NULL;
809 struct unlink_psx_rq *pRqD;
812 int bytes_returned = 0;
813 __u16 params, param_offset, offset, byte_count;
815 cFYI(1, "In POSIX delete");
817 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
822 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
824 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
825 PATH_MAX, nls_codepage, remap);
826 name_len++; /* trailing null */
828 } else { /* BB add path length overrun check */
829 name_len = strnlen(fileName, PATH_MAX);
830 name_len++; /* trailing null */
831 strncpy(pSMB->FileName, fileName, name_len);
834 params = 6 + name_len;
835 pSMB->MaxParameterCount = cpu_to_le16(2);
836 pSMB->MaxDataCount = 0; /* BB double check this with jra */
837 pSMB->MaxSetupCount = 0;
842 param_offset = offsetof(struct smb_com_transaction2_spi_req,
843 InformationLevel) - 4;
844 offset = param_offset + params;
846 /* Setup pointer to Request Data (inode type) */
847 pRqD = (struct unlink_psx_rq *)(((char *)&pSMB->hdr.Protocol) + offset);
848 pRqD->type = cpu_to_le16(type);
849 pSMB->ParameterOffset = cpu_to_le16(param_offset);
850 pSMB->DataOffset = cpu_to_le16(offset);
851 pSMB->SetupCount = 1;
853 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
854 byte_count = 3 /* pad */ + params + sizeof(struct unlink_psx_rq);
856 pSMB->DataCount = cpu_to_le16(sizeof(struct unlink_psx_rq));
857 pSMB->TotalDataCount = cpu_to_le16(sizeof(struct unlink_psx_rq));
858 pSMB->ParameterCount = cpu_to_le16(params);
859 pSMB->TotalParameterCount = pSMB->ParameterCount;
860 pSMB->InformationLevel = cpu_to_le16(SMB_POSIX_UNLINK);
862 inc_rfc1001_len(pSMB, byte_count);
863 pSMB->ByteCount = cpu_to_le16(byte_count);
864 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
865 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
867 cFYI(1, "Posix delete returned %d", rc);
868 cifs_buf_release(pSMB);
870 cifs_stats_inc(&tcon->num_deletes);
879 CIFSSMBDelFile(const int xid, struct cifsTconInfo *tcon, const char *fileName,
880 const struct nls_table *nls_codepage, int remap)
882 DELETE_FILE_REQ *pSMB = NULL;
883 DELETE_FILE_RSP *pSMBr = NULL;
889 rc = smb_init(SMB_COM_DELETE, 1, tcon, (void **) &pSMB,
894 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
896 cifsConvertToUCS((__le16 *) pSMB->fileName, fileName,
897 PATH_MAX, nls_codepage, remap);
898 name_len++; /* trailing null */
900 } else { /* BB improve check for buffer overruns BB */
901 name_len = strnlen(fileName, PATH_MAX);
902 name_len++; /* trailing null */
903 strncpy(pSMB->fileName, fileName, name_len);
905 pSMB->SearchAttributes =
906 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM);
907 pSMB->BufferFormat = 0x04;
908 inc_rfc1001_len(pSMB, name_len + 1);
909 pSMB->ByteCount = cpu_to_le16(name_len + 1);
910 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
911 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
912 cifs_stats_inc(&tcon->num_deletes);
914 cFYI(1, "Error in RMFile = %d", rc);
916 cifs_buf_release(pSMB);
924 CIFSSMBRmDir(const int xid, struct cifsTconInfo *tcon, const char *dirName,
925 const struct nls_table *nls_codepage, int remap)
927 DELETE_DIRECTORY_REQ *pSMB = NULL;
928 DELETE_DIRECTORY_RSP *pSMBr = NULL;
933 cFYI(1, "In CIFSSMBRmDir");
935 rc = smb_init(SMB_COM_DELETE_DIRECTORY, 0, tcon, (void **) &pSMB,
940 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
941 name_len = cifsConvertToUCS((__le16 *) pSMB->DirName, dirName,
942 PATH_MAX, nls_codepage, remap);
943 name_len++; /* trailing null */
945 } else { /* BB improve check for buffer overruns BB */
946 name_len = strnlen(dirName, PATH_MAX);
947 name_len++; /* trailing null */
948 strncpy(pSMB->DirName, dirName, name_len);
951 pSMB->BufferFormat = 0x04;
952 inc_rfc1001_len(pSMB, name_len + 1);
953 pSMB->ByteCount = cpu_to_le16(name_len + 1);
954 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
955 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
956 cifs_stats_inc(&tcon->num_rmdirs);
958 cFYI(1, "Error in RMDir = %d", rc);
960 cifs_buf_release(pSMB);
967 CIFSSMBMkDir(const int xid, struct cifsTconInfo *tcon,
968 const char *name, const struct nls_table *nls_codepage, int remap)
971 CREATE_DIRECTORY_REQ *pSMB = NULL;
972 CREATE_DIRECTORY_RSP *pSMBr = NULL;
976 cFYI(1, "In CIFSSMBMkDir");
978 rc = smb_init(SMB_COM_CREATE_DIRECTORY, 0, tcon, (void **) &pSMB,
983 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
984 name_len = cifsConvertToUCS((__le16 *) pSMB->DirName, name,
985 PATH_MAX, nls_codepage, remap);
986 name_len++; /* trailing null */
988 } else { /* BB improve check for buffer overruns BB */
989 name_len = strnlen(name, PATH_MAX);
990 name_len++; /* trailing null */
991 strncpy(pSMB->DirName, name, name_len);
994 pSMB->BufferFormat = 0x04;
995 inc_rfc1001_len(pSMB, name_len + 1);
996 pSMB->ByteCount = cpu_to_le16(name_len + 1);
997 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
998 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
999 cifs_stats_inc(&tcon->num_mkdirs);
1001 cFYI(1, "Error in Mkdir = %d", rc);
1003 cifs_buf_release(pSMB);
1010 CIFSPOSIXCreate(const int xid, struct cifsTconInfo *tcon, __u32 posix_flags,
1011 __u64 mode, __u16 *netfid, FILE_UNIX_BASIC_INFO *pRetData,
1012 __u32 *pOplock, const char *name,
1013 const struct nls_table *nls_codepage, int remap)
1015 TRANSACTION2_SPI_REQ *pSMB = NULL;
1016 TRANSACTION2_SPI_RSP *pSMBr = NULL;
1019 int bytes_returned = 0;
1020 __u16 params, param_offset, offset, byte_count, count;
1021 OPEN_PSX_REQ *pdata;
1022 OPEN_PSX_RSP *psx_rsp;
1024 cFYI(1, "In POSIX Create");
1026 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
1031 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1033 cifsConvertToUCS((__le16 *) pSMB->FileName, name,
1034 PATH_MAX, nls_codepage, remap);
1035 name_len++; /* trailing null */
1037 } else { /* BB improve the check for buffer overruns BB */
1038 name_len = strnlen(name, PATH_MAX);
1039 name_len++; /* trailing null */
1040 strncpy(pSMB->FileName, name, name_len);
1043 params = 6 + name_len;
1044 count = sizeof(OPEN_PSX_REQ);
1045 pSMB->MaxParameterCount = cpu_to_le16(2);
1046 pSMB->MaxDataCount = cpu_to_le16(1000); /* large enough */
1047 pSMB->MaxSetupCount = 0;
1051 pSMB->Reserved2 = 0;
1052 param_offset = offsetof(struct smb_com_transaction2_spi_req,
1053 InformationLevel) - 4;
1054 offset = param_offset + params;
1055 pdata = (OPEN_PSX_REQ *)(((char *)&pSMB->hdr.Protocol) + offset);
1056 pdata->Level = cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC);
1057 pdata->Permissions = cpu_to_le64(mode);
1058 pdata->PosixOpenFlags = cpu_to_le32(posix_flags);
1059 pdata->OpenFlags = cpu_to_le32(*pOplock);
1060 pSMB->ParameterOffset = cpu_to_le16(param_offset);
1061 pSMB->DataOffset = cpu_to_le16(offset);
1062 pSMB->SetupCount = 1;
1063 pSMB->Reserved3 = 0;
1064 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
1065 byte_count = 3 /* pad */ + params + count;
1067 pSMB->DataCount = cpu_to_le16(count);
1068 pSMB->ParameterCount = cpu_to_le16(params);
1069 pSMB->TotalDataCount = pSMB->DataCount;
1070 pSMB->TotalParameterCount = pSMB->ParameterCount;
1071 pSMB->InformationLevel = cpu_to_le16(SMB_POSIX_OPEN);
1072 pSMB->Reserved4 = 0;
1073 inc_rfc1001_len(pSMB, byte_count);
1074 pSMB->ByteCount = cpu_to_le16(byte_count);
1075 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1076 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1078 cFYI(1, "Posix create returned %d", rc);
1079 goto psx_create_err;
1082 cFYI(1, "copying inode info");
1083 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
1085 if (rc || get_bcc(&pSMBr->hdr) < sizeof(OPEN_PSX_RSP)) {
1086 rc = -EIO; /* bad smb */
1087 goto psx_create_err;
1090 /* copy return information to pRetData */
1091 psx_rsp = (OPEN_PSX_RSP *)((char *) &pSMBr->hdr.Protocol
1092 + le16_to_cpu(pSMBr->t2.DataOffset));
1094 *pOplock = le16_to_cpu(psx_rsp->OplockFlags);
1096 *netfid = psx_rsp->Fid; /* cifs fid stays in le */
1097 /* Let caller know file was created so we can set the mode. */
1098 /* Do we care about the CreateAction in any other cases? */
1099 if (cpu_to_le32(FILE_CREATE) == psx_rsp->CreateAction)
1100 *pOplock |= CIFS_CREATE_ACTION;
1101 /* check to make sure response data is there */
1102 if (psx_rsp->ReturnedLevel != cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC)) {
1103 pRetData->Type = cpu_to_le32(-1); /* unknown */
1104 cFYI(DBG2, "unknown type");
1106 if (get_bcc(&pSMBr->hdr) < sizeof(OPEN_PSX_RSP)
1107 + sizeof(FILE_UNIX_BASIC_INFO)) {
1108 cERROR(1, "Open response data too small");
1109 pRetData->Type = cpu_to_le32(-1);
1110 goto psx_create_err;
1112 memcpy((char *) pRetData,
1113 (char *)psx_rsp + sizeof(OPEN_PSX_RSP),
1114 sizeof(FILE_UNIX_BASIC_INFO));
1118 cifs_buf_release(pSMB);
1120 if (posix_flags & SMB_O_DIRECTORY)
1121 cifs_stats_inc(&tcon->num_posixmkdirs);
1123 cifs_stats_inc(&tcon->num_posixopens);
1131 static __u16 convert_disposition(int disposition)
1135 switch (disposition) {
1136 case FILE_SUPERSEDE:
1137 ofun = SMBOPEN_OCREATE | SMBOPEN_OTRUNC;
1140 ofun = SMBOPEN_OAPPEND;
1143 ofun = SMBOPEN_OCREATE;
1146 ofun = SMBOPEN_OCREATE | SMBOPEN_OAPPEND;
1148 case FILE_OVERWRITE:
1149 ofun = SMBOPEN_OTRUNC;
1151 case FILE_OVERWRITE_IF:
1152 ofun = SMBOPEN_OCREATE | SMBOPEN_OTRUNC;
1155 cFYI(1, "unknown disposition %d", disposition);
1156 ofun = SMBOPEN_OAPPEND; /* regular open */
1162 access_flags_to_smbopen_mode(const int access_flags)
1164 int masked_flags = access_flags & (GENERIC_READ | GENERIC_WRITE);
1166 if (masked_flags == GENERIC_READ)
1167 return SMBOPEN_READ;
1168 else if (masked_flags == GENERIC_WRITE)
1169 return SMBOPEN_WRITE;
1171 /* just go for read/write */
1172 return SMBOPEN_READWRITE;
1176 SMBLegacyOpen(const int xid, struct cifsTconInfo *tcon,
1177 const char *fileName, const int openDisposition,
1178 const int access_flags, const int create_options, __u16 *netfid,
1179 int *pOplock, FILE_ALL_INFO *pfile_info,
1180 const struct nls_table *nls_codepage, int remap)
1183 OPENX_REQ *pSMB = NULL;
1184 OPENX_RSP *pSMBr = NULL;
1190 rc = smb_init(SMB_COM_OPEN_ANDX, 15, tcon, (void **) &pSMB,
1195 pSMB->AndXCommand = 0xFF; /* none */
1197 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1198 count = 1; /* account for one byte pad to word boundary */
1200 cifsConvertToUCS((__le16 *) (pSMB->fileName + 1),
1201 fileName, PATH_MAX, nls_codepage, remap);
1202 name_len++; /* trailing null */
1204 } else { /* BB improve check for buffer overruns BB */
1205 count = 0; /* no pad */
1206 name_len = strnlen(fileName, PATH_MAX);
1207 name_len++; /* trailing null */
1208 strncpy(pSMB->fileName, fileName, name_len);
1210 if (*pOplock & REQ_OPLOCK)
1211 pSMB->OpenFlags = cpu_to_le16(REQ_OPLOCK);
1212 else if (*pOplock & REQ_BATCHOPLOCK)
1213 pSMB->OpenFlags = cpu_to_le16(REQ_BATCHOPLOCK);
1215 pSMB->OpenFlags |= cpu_to_le16(REQ_MORE_INFO);
1216 pSMB->Mode = cpu_to_le16(access_flags_to_smbopen_mode(access_flags));
1217 pSMB->Mode |= cpu_to_le16(0x40); /* deny none */
1218 /* set file as system file if special file such
1219 as fifo and server expecting SFU style and
1220 no Unix extensions */
1222 if (create_options & CREATE_OPTION_SPECIAL)
1223 pSMB->FileAttributes = cpu_to_le16(ATTR_SYSTEM);
1224 else /* BB FIXME BB */
1225 pSMB->FileAttributes = cpu_to_le16(0/*ATTR_NORMAL*/);
1227 if (create_options & CREATE_OPTION_READONLY)
1228 pSMB->FileAttributes |= cpu_to_le16(ATTR_READONLY);
1231 /* pSMB->CreateOptions = cpu_to_le32(create_options &
1232 CREATE_OPTIONS_MASK); */
1233 /* BB FIXME END BB */
1235 pSMB->Sattr = cpu_to_le16(ATTR_HIDDEN | ATTR_SYSTEM | ATTR_DIRECTORY);
1236 pSMB->OpenFunction = cpu_to_le16(convert_disposition(openDisposition));
1238 inc_rfc1001_len(pSMB, count);
1240 pSMB->ByteCount = cpu_to_le16(count);
1241 /* long_op set to 1 to allow for oplock break timeouts */
1242 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1243 (struct smb_hdr *)pSMBr, &bytes_returned, 0);
1244 cifs_stats_inc(&tcon->num_opens);
1246 cFYI(1, "Error in Open = %d", rc);
1248 /* BB verify if wct == 15 */
1250 /* *pOplock = pSMBr->OplockLevel; */ /* BB take from action field*/
1252 *netfid = pSMBr->Fid; /* cifs fid stays in le */
1253 /* Let caller know file was created so we can set the mode. */
1254 /* Do we care about the CreateAction in any other cases? */
1256 /* if (cpu_to_le32(FILE_CREATE) == pSMBr->CreateAction)
1257 *pOplock |= CIFS_CREATE_ACTION; */
1261 pfile_info->CreationTime = 0; /* BB convert CreateTime*/
1262 pfile_info->LastAccessTime = 0; /* BB fixme */
1263 pfile_info->LastWriteTime = 0; /* BB fixme */
1264 pfile_info->ChangeTime = 0; /* BB fixme */
1265 pfile_info->Attributes =
1266 cpu_to_le32(le16_to_cpu(pSMBr->FileAttributes));
1267 /* the file_info buf is endian converted by caller */
1268 pfile_info->AllocationSize =
1269 cpu_to_le64(le32_to_cpu(pSMBr->EndOfFile));
1270 pfile_info->EndOfFile = pfile_info->AllocationSize;
1271 pfile_info->NumberOfLinks = cpu_to_le32(1);
1272 pfile_info->DeletePending = 0;
1276 cifs_buf_release(pSMB);
1283 CIFSSMBOpen(const int xid, struct cifsTconInfo *tcon,
1284 const char *fileName, const int openDisposition,
1285 const int access_flags, const int create_options, __u16 *netfid,
1286 int *pOplock, FILE_ALL_INFO *pfile_info,
1287 const struct nls_table *nls_codepage, int remap)
1290 OPEN_REQ *pSMB = NULL;
1291 OPEN_RSP *pSMBr = NULL;
1297 rc = smb_init(SMB_COM_NT_CREATE_ANDX, 24, tcon, (void **) &pSMB,
1302 pSMB->AndXCommand = 0xFF; /* none */
1304 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1305 count = 1; /* account for one byte pad to word boundary */
1307 cifsConvertToUCS((__le16 *) (pSMB->fileName + 1),
1308 fileName, PATH_MAX, nls_codepage, remap);
1309 name_len++; /* trailing null */
1311 pSMB->NameLength = cpu_to_le16(name_len);
1312 } else { /* BB improve check for buffer overruns BB */
1313 count = 0; /* no pad */
1314 name_len = strnlen(fileName, PATH_MAX);
1315 name_len++; /* trailing null */
1316 pSMB->NameLength = cpu_to_le16(name_len);
1317 strncpy(pSMB->fileName, fileName, name_len);
1319 if (*pOplock & REQ_OPLOCK)
1320 pSMB->OpenFlags = cpu_to_le32(REQ_OPLOCK);
1321 else if (*pOplock & REQ_BATCHOPLOCK)
1322 pSMB->OpenFlags = cpu_to_le32(REQ_BATCHOPLOCK);
1323 pSMB->DesiredAccess = cpu_to_le32(access_flags);
1324 pSMB->AllocationSize = 0;
1325 /* set file as system file if special file such
1326 as fifo and server expecting SFU style and
1327 no Unix extensions */
1328 if (create_options & CREATE_OPTION_SPECIAL)
1329 pSMB->FileAttributes = cpu_to_le32(ATTR_SYSTEM);
1331 pSMB->FileAttributes = cpu_to_le32(ATTR_NORMAL);
1333 /* XP does not handle ATTR_POSIX_SEMANTICS */
1334 /* but it helps speed up case sensitive checks for other
1335 servers such as Samba */
1336 if (tcon->ses->capabilities & CAP_UNIX)
1337 pSMB->FileAttributes |= cpu_to_le32(ATTR_POSIX_SEMANTICS);
1339 if (create_options & CREATE_OPTION_READONLY)
1340 pSMB->FileAttributes |= cpu_to_le32(ATTR_READONLY);
1342 pSMB->ShareAccess = cpu_to_le32(FILE_SHARE_ALL);
1343 pSMB->CreateDisposition = cpu_to_le32(openDisposition);
1344 pSMB->CreateOptions = cpu_to_le32(create_options & CREATE_OPTIONS_MASK);
1345 /* BB Expirement with various impersonation levels and verify */
1346 pSMB->ImpersonationLevel = cpu_to_le32(SECURITY_IMPERSONATION);
1347 pSMB->SecurityFlags =
1348 SECURITY_CONTEXT_TRACKING | SECURITY_EFFECTIVE_ONLY;
1351 inc_rfc1001_len(pSMB, count);
1353 pSMB->ByteCount = cpu_to_le16(count);
1354 /* long_op set to 1 to allow for oplock break timeouts */
1355 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1356 (struct smb_hdr *)pSMBr, &bytes_returned, 0);
1357 cifs_stats_inc(&tcon->num_opens);
1359 cFYI(1, "Error in Open = %d", rc);
1361 *pOplock = pSMBr->OplockLevel; /* 1 byte no need to le_to_cpu */
1362 *netfid = pSMBr->Fid; /* cifs fid stays in le */
1363 /* Let caller know file was created so we can set the mode. */
1364 /* Do we care about the CreateAction in any other cases? */
1365 if (cpu_to_le32(FILE_CREATE) == pSMBr->CreateAction)
1366 *pOplock |= CIFS_CREATE_ACTION;
1368 memcpy((char *)pfile_info, (char *)&pSMBr->CreationTime,
1369 36 /* CreationTime to Attributes */);
1370 /* the file_info buf is endian converted by caller */
1371 pfile_info->AllocationSize = pSMBr->AllocationSize;
1372 pfile_info->EndOfFile = pSMBr->EndOfFile;
1373 pfile_info->NumberOfLinks = cpu_to_le32(1);
1374 pfile_info->DeletePending = 0;
1378 cifs_buf_release(pSMB);
1385 CIFSSMBRead(const int xid, struct cifs_io_parms *io_parms, unsigned int *nbytes,
1386 char **buf, int *pbuf_type)
1389 READ_REQ *pSMB = NULL;
1390 READ_RSP *pSMBr = NULL;
1391 char *pReadData = NULL;
1393 int resp_buf_type = 0;
1395 __u32 pid = io_parms->pid;
1396 __u16 netfid = io_parms->netfid;
1397 __u64 offset = io_parms->offset;
1398 struct cifsTconInfo *tcon = io_parms->tcon;
1399 unsigned int count = io_parms->length;
1401 cFYI(1, "Reading %d bytes on fid %d", count, netfid);
1402 if (tcon->ses->capabilities & CAP_LARGE_FILES)
1405 wct = 10; /* old style read */
1406 if ((offset >> 32) > 0) {
1407 /* can not handle this big offset for old */
1413 rc = small_smb_init(SMB_COM_READ_ANDX, wct, tcon, (void **) &pSMB);
1417 pSMB->hdr.Pid = cpu_to_le16((__u16)pid);
1418 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid >> 16));
1420 /* tcon and ses pointer are checked in smb_init */
1421 if (tcon->ses->server == NULL)
1422 return -ECONNABORTED;
1424 pSMB->AndXCommand = 0xFF; /* none */
1426 pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF);
1428 pSMB->OffsetHigh = cpu_to_le32(offset >> 32);
1430 pSMB->Remaining = 0;
1431 pSMB->MaxCount = cpu_to_le16(count & 0xFFFF);
1432 pSMB->MaxCountHigh = cpu_to_le32(count >> 16);
1434 pSMB->ByteCount = 0; /* no need to do le conversion since 0 */
1436 /* old style read */
1437 struct smb_com_readx_req *pSMBW =
1438 (struct smb_com_readx_req *)pSMB;
1439 pSMBW->ByteCount = 0;
1442 iov[0].iov_base = (char *)pSMB;
1443 iov[0].iov_len = be32_to_cpu(pSMB->hdr.smb_buf_length) + 4;
1444 rc = SendReceive2(xid, tcon->ses, iov, 1 /* num iovecs */,
1445 &resp_buf_type, CIFS_LOG_ERROR);
1446 cifs_stats_inc(&tcon->num_reads);
1447 pSMBr = (READ_RSP *)iov[0].iov_base;
1449 cERROR(1, "Send error in read = %d", rc);
1451 int data_length = le16_to_cpu(pSMBr->DataLengthHigh);
1452 data_length = data_length << 16;
1453 data_length += le16_to_cpu(pSMBr->DataLength);
1454 *nbytes = data_length;
1456 /*check that DataLength would not go beyond end of SMB */
1457 if ((data_length > CIFSMaxBufSize)
1458 || (data_length > count)) {
1459 cFYI(1, "bad length %d for count %d",
1460 data_length, count);
1464 pReadData = (char *) (&pSMBr->hdr.Protocol) +
1465 le16_to_cpu(pSMBr->DataOffset);
1466 /* if (rc = copy_to_user(buf, pReadData, data_length)) {
1467 cERROR(1, "Faulting on read rc = %d",rc);
1469 }*/ /* can not use copy_to_user when using page cache*/
1471 memcpy(*buf, pReadData, data_length);
1475 /* cifs_small_buf_release(pSMB); */ /* Freed earlier now in SendReceive2 */
1477 if (resp_buf_type == CIFS_SMALL_BUFFER)
1478 cifs_small_buf_release(iov[0].iov_base);
1479 else if (resp_buf_type == CIFS_LARGE_BUFFER)
1480 cifs_buf_release(iov[0].iov_base);
1481 } else if (resp_buf_type != CIFS_NO_BUFFER) {
1482 /* return buffer to caller to free */
1483 *buf = iov[0].iov_base;
1484 if (resp_buf_type == CIFS_SMALL_BUFFER)
1485 *pbuf_type = CIFS_SMALL_BUFFER;
1486 else if (resp_buf_type == CIFS_LARGE_BUFFER)
1487 *pbuf_type = CIFS_LARGE_BUFFER;
1488 } /* else no valid buffer on return - leave as null */
1490 /* Note: On -EAGAIN error only caller can retry on handle based calls
1491 since file handle passed in no longer valid */
1497 CIFSSMBWrite(const int xid, struct cifs_io_parms *io_parms,
1498 unsigned int *nbytes, const char *buf,
1499 const char __user *ubuf, const int long_op)
1502 WRITE_REQ *pSMB = NULL;
1503 WRITE_RSP *pSMBr = NULL;
1504 int bytes_returned, wct;
1507 __u32 pid = io_parms->pid;
1508 __u16 netfid = io_parms->netfid;
1509 __u64 offset = io_parms->offset;
1510 struct cifsTconInfo *tcon = io_parms->tcon;
1511 unsigned int count = io_parms->length;
1515 /* cFYI(1, "write at %lld %d bytes", offset, count);*/
1516 if (tcon->ses == NULL)
1517 return -ECONNABORTED;
1519 if (tcon->ses->capabilities & CAP_LARGE_FILES)
1523 if ((offset >> 32) > 0) {
1524 /* can not handle big offset for old srv */
1529 rc = smb_init(SMB_COM_WRITE_ANDX, wct, tcon, (void **) &pSMB,
1534 pSMB->hdr.Pid = cpu_to_le16((__u16)pid);
1535 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid >> 16));
1537 /* tcon and ses pointer are checked in smb_init */
1538 if (tcon->ses->server == NULL)
1539 return -ECONNABORTED;
1541 pSMB->AndXCommand = 0xFF; /* none */
1543 pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF);
1545 pSMB->OffsetHigh = cpu_to_le32(offset >> 32);
1547 pSMB->Reserved = 0xFFFFFFFF;
1548 pSMB->WriteMode = 0;
1549 pSMB->Remaining = 0;
1551 /* Can increase buffer size if buffer is big enough in some cases ie we
1552 can send more if LARGE_WRITE_X capability returned by the server and if
1553 our buffer is big enough or if we convert to iovecs on socket writes
1554 and eliminate the copy to the CIFS buffer */
1555 if (tcon->ses->capabilities & CAP_LARGE_WRITE_X) {
1556 bytes_sent = min_t(const unsigned int, CIFSMaxBufSize, count);
1558 bytes_sent = (tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE)
1562 if (bytes_sent > count)
1565 cpu_to_le16(offsetof(struct smb_com_write_req, Data) - 4);
1567 memcpy(pSMB->Data, buf, bytes_sent);
1569 if (copy_from_user(pSMB->Data, ubuf, bytes_sent)) {
1570 cifs_buf_release(pSMB);
1573 } else if (count != 0) {
1575 cifs_buf_release(pSMB);
1577 } /* else setting file size with write of zero bytes */
1579 byte_count = bytes_sent + 1; /* pad */
1580 else /* wct == 12 */
1581 byte_count = bytes_sent + 5; /* bigger pad, smaller smb hdr */
1583 pSMB->DataLengthLow = cpu_to_le16(bytes_sent & 0xFFFF);
1584 pSMB->DataLengthHigh = cpu_to_le16(bytes_sent >> 16);
1585 inc_rfc1001_len(pSMB, byte_count);
1588 pSMB->ByteCount = cpu_to_le16(byte_count);
1589 else { /* old style write has byte count 4 bytes earlier
1591 struct smb_com_writex_req *pSMBW =
1592 (struct smb_com_writex_req *)pSMB;
1593 pSMBW->ByteCount = cpu_to_le16(byte_count);
1596 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1597 (struct smb_hdr *) pSMBr, &bytes_returned, long_op);
1598 cifs_stats_inc(&tcon->num_writes);
1600 cFYI(1, "Send error in write = %d", rc);
1602 *nbytes = le16_to_cpu(pSMBr->CountHigh);
1603 *nbytes = (*nbytes) << 16;
1604 *nbytes += le16_to_cpu(pSMBr->Count);
1607 * Mask off high 16 bits when bytes written as returned by the
1608 * server is greater than bytes requested by the client. Some
1609 * OS/2 servers are known to set incorrect CountHigh values.
1611 if (*nbytes > count)
1615 cifs_buf_release(pSMB);
1617 /* Note: On -EAGAIN error only caller can retry on handle based calls
1618 since file handle passed in no longer valid */
1624 cifs_writedata_release(struct kref *refcount)
1626 struct cifs_writedata *wdata = container_of(refcount,
1627 struct cifs_writedata, refcount);
1630 cifsFileInfo_put(wdata->cfile);
1636 * Write failed with a retryable error. Resend the write request. It's also
1637 * possible that the page was redirtied so re-clean the page.
1640 cifs_writev_requeue(struct cifs_writedata *wdata)
1643 struct inode *inode = wdata->cfile->dentry->d_inode;
1645 for (i = 0; i < wdata->nr_pages; i++) {
1646 lock_page(wdata->pages[i]);
1647 clear_page_dirty_for_io(wdata->pages[i]);
1651 rc = cifs_async_writev(wdata);
1652 } while (rc == -EAGAIN);
1654 for (i = 0; i < wdata->nr_pages; i++) {
1656 SetPageError(wdata->pages[i]);
1657 unlock_page(wdata->pages[i]);
1660 mapping_set_error(inode->i_mapping, rc);
1661 kref_put(&wdata->refcount, cifs_writedata_release);
1665 cifs_writev_complete(struct work_struct *work)
1667 struct cifs_writedata *wdata = container_of(work,
1668 struct cifs_writedata, work);
1669 struct inode *inode = wdata->cfile->dentry->d_inode;
1672 if (wdata->result == 0) {
1673 cifs_update_eof(CIFS_I(inode), wdata->offset, wdata->bytes);
1674 cifs_stats_bytes_written(tlink_tcon(wdata->cfile->tlink),
1676 } else if (wdata->sync_mode == WB_SYNC_ALL && wdata->result == -EAGAIN)
1677 return cifs_writev_requeue(wdata);
1679 for (i = 0; i < wdata->nr_pages; i++) {
1680 struct page *page = wdata->pages[i];
1681 if (wdata->result == -EAGAIN)
1682 __set_page_dirty_nobuffers(page);
1683 else if (wdata->result < 0)
1685 end_page_writeback(page);
1686 page_cache_release(page);
1688 if (wdata->result != -EAGAIN)
1689 mapping_set_error(inode->i_mapping, wdata->result);
1690 kref_put(&wdata->refcount, cifs_writedata_release);
1693 struct cifs_writedata *
1694 cifs_writedata_alloc(unsigned int nr_pages)
1696 struct cifs_writedata *wdata;
1698 /* this would overflow */
1699 if (nr_pages == 0) {
1700 cERROR(1, "%s: called with nr_pages == 0!", __func__);
1704 /* writedata + number of page pointers */
1705 wdata = kzalloc(sizeof(*wdata) +
1706 sizeof(struct page *) * (nr_pages - 1), GFP_NOFS);
1707 if (wdata != NULL) {
1708 INIT_WORK(&wdata->work, cifs_writev_complete);
1709 kref_init(&wdata->refcount);
1715 * Check the midState and signature on received buffer (if any), and queue the
1716 * workqueue completion task.
1719 cifs_writev_callback(struct mid_q_entry *mid)
1721 struct cifs_writedata *wdata = mid->callback_data;
1722 struct cifsTconInfo *tcon = tlink_tcon(wdata->cfile->tlink);
1723 unsigned int written;
1724 WRITE_RSP *smb = (WRITE_RSP *)mid->resp_buf;
1726 switch (mid->midState) {
1727 case MID_RESPONSE_RECEIVED:
1728 wdata->result = cifs_check_receive(mid, tcon->ses->server, 0);
1729 if (wdata->result != 0)
1732 written = le16_to_cpu(smb->CountHigh);
1734 written += le16_to_cpu(smb->Count);
1736 * Mask off high 16 bits when bytes written as returned
1737 * by the server is greater than bytes requested by the
1738 * client. OS/2 servers are known to set incorrect
1741 if (written > wdata->bytes)
1744 if (written < wdata->bytes)
1745 wdata->result = -ENOSPC;
1747 wdata->bytes = written;
1749 case MID_REQUEST_SUBMITTED:
1750 case MID_RETRY_NEEDED:
1751 wdata->result = -EAGAIN;
1754 wdata->result = -EIO;
1758 queue_work(system_nrt_wq, &wdata->work);
1759 DeleteMidQEntry(mid);
1760 atomic_dec(&tcon->ses->server->inFlight);
1761 wake_up(&tcon->ses->server->request_q);
1764 /* cifs_async_writev - send an async write, and set up mid to handle result */
1766 cifs_async_writev(struct cifs_writedata *wdata)
1768 int i, rc = -EACCES;
1769 WRITE_REQ *smb = NULL;
1771 struct cifsTconInfo *tcon = tlink_tcon(wdata->cfile->tlink);
1772 struct inode *inode = wdata->cfile->dentry->d_inode;
1773 struct kvec *iov = NULL;
1775 if (tcon->ses->capabilities & CAP_LARGE_FILES) {
1779 if (wdata->offset >> 32 > 0) {
1780 /* can not handle big offset for old srv */
1785 rc = small_smb_init(SMB_COM_WRITE_ANDX, wct, tcon, (void **)&smb);
1787 goto async_writev_out;
1789 /* 1 iov per page + 1 for header */
1790 iov = kzalloc((wdata->nr_pages + 1) * sizeof(*iov), GFP_NOFS);
1793 goto async_writev_out;
1796 smb->hdr.Pid = cpu_to_le16((__u16)wdata->cfile->pid);
1797 smb->hdr.PidHigh = cpu_to_le16((__u16)(wdata->cfile->pid >> 16));
1799 smb->AndXCommand = 0xFF; /* none */
1800 smb->Fid = wdata->cfile->netfid;
1801 smb->OffsetLow = cpu_to_le32(wdata->offset & 0xFFFFFFFF);
1803 smb->OffsetHigh = cpu_to_le32(wdata->offset >> 32);
1804 smb->Reserved = 0xFFFFFFFF;
1809 cpu_to_le16(offsetof(struct smb_com_write_req, Data) - 4);
1811 /* 4 for RFC1001 length + 1 for BCC */
1812 iov[0].iov_len = be32_to_cpu(smb->hdr.smb_buf_length) + 4 + 1;
1813 iov[0].iov_base = smb;
1815 /* marshal up the pages into iov array */
1817 for (i = 0; i < wdata->nr_pages; i++) {
1818 iov[i + 1].iov_len = min(inode->i_size -
1819 page_offset(wdata->pages[i]),
1820 (loff_t)PAGE_CACHE_SIZE);
1821 iov[i + 1].iov_base = kmap(wdata->pages[i]);
1822 wdata->bytes += iov[i + 1].iov_len;
1825 cFYI(1, "async write at %llu %u bytes", wdata->offset, wdata->bytes);
1827 smb->DataLengthLow = cpu_to_le16(wdata->bytes & 0xFFFF);
1828 smb->DataLengthHigh = cpu_to_le16(wdata->bytes >> 16);
1831 inc_rfc1001_len(&smb->hdr, wdata->bytes + 1);
1832 put_bcc(wdata->bytes + 1, &smb->hdr);
1835 struct smb_com_writex_req *smbw =
1836 (struct smb_com_writex_req *)smb;
1837 inc_rfc1001_len(&smbw->hdr, wdata->bytes + 5);
1838 put_bcc(wdata->bytes + 5, &smbw->hdr);
1839 iov[0].iov_len += 4; /* pad bigger by four bytes */
1842 kref_get(&wdata->refcount);
1843 rc = cifs_call_async(tcon->ses->server, iov, wdata->nr_pages + 1,
1844 cifs_writev_callback, wdata, false);
1847 cifs_stats_inc(&tcon->num_writes);
1849 kref_put(&wdata->refcount, cifs_writedata_release);
1851 /* send is done, unmap pages */
1852 for (i = 0; i < wdata->nr_pages; i++)
1853 kunmap(wdata->pages[i]);
1856 cifs_small_buf_release(smb);
1862 CIFSSMBWrite2(const int xid, struct cifs_io_parms *io_parms,
1863 unsigned int *nbytes, struct kvec *iov, int n_vec,
1867 WRITE_REQ *pSMB = NULL;
1870 int resp_buf_type = 0;
1871 __u32 pid = io_parms->pid;
1872 __u16 netfid = io_parms->netfid;
1873 __u64 offset = io_parms->offset;
1874 struct cifsTconInfo *tcon = io_parms->tcon;
1875 unsigned int count = io_parms->length;
1879 cFYI(1, "write2 at %lld %d bytes", (long long)offset, count);
1881 if (tcon->ses->capabilities & CAP_LARGE_FILES) {
1885 if ((offset >> 32) > 0) {
1886 /* can not handle big offset for old srv */
1890 rc = small_smb_init(SMB_COM_WRITE_ANDX, wct, tcon, (void **) &pSMB);
1894 pSMB->hdr.Pid = cpu_to_le16((__u16)pid);
1895 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid >> 16));
1897 /* tcon and ses pointer are checked in smb_init */
1898 if (tcon->ses->server == NULL)
1899 return -ECONNABORTED;
1901 pSMB->AndXCommand = 0xFF; /* none */
1903 pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF);
1905 pSMB->OffsetHigh = cpu_to_le32(offset >> 32);
1906 pSMB->Reserved = 0xFFFFFFFF;
1907 pSMB->WriteMode = 0;
1908 pSMB->Remaining = 0;
1911 cpu_to_le16(offsetof(struct smb_com_write_req, Data) - 4);
1913 pSMB->DataLengthLow = cpu_to_le16(count & 0xFFFF);
1914 pSMB->DataLengthHigh = cpu_to_le16(count >> 16);
1915 /* header + 1 byte pad */
1916 smb_hdr_len = be32_to_cpu(pSMB->hdr.smb_buf_length) + 1;
1918 inc_rfc1001_len(pSMB, count + 1);
1919 else /* wct == 12 */
1920 inc_rfc1001_len(pSMB, count + 5); /* smb data starts later */
1922 pSMB->ByteCount = cpu_to_le16(count + 1);
1923 else /* wct == 12 */ /* bigger pad, smaller smb hdr, keep offset ok */ {
1924 struct smb_com_writex_req *pSMBW =
1925 (struct smb_com_writex_req *)pSMB;
1926 pSMBW->ByteCount = cpu_to_le16(count + 5);
1928 iov[0].iov_base = pSMB;
1930 iov[0].iov_len = smb_hdr_len + 4;
1931 else /* wct == 12 pad bigger by four bytes */
1932 iov[0].iov_len = smb_hdr_len + 8;
1935 rc = SendReceive2(xid, tcon->ses, iov, n_vec + 1, &resp_buf_type,
1937 cifs_stats_inc(&tcon->num_writes);
1939 cFYI(1, "Send error Write2 = %d", rc);
1940 } else if (resp_buf_type == 0) {
1941 /* presumably this can not happen, but best to be safe */
1944 WRITE_RSP *pSMBr = (WRITE_RSP *)iov[0].iov_base;
1945 *nbytes = le16_to_cpu(pSMBr->CountHigh);
1946 *nbytes = (*nbytes) << 16;
1947 *nbytes += le16_to_cpu(pSMBr->Count);
1950 * Mask off high 16 bits when bytes written as returned by the
1951 * server is greater than bytes requested by the client. OS/2
1952 * servers are known to set incorrect CountHigh values.
1954 if (*nbytes > count)
1958 /* cifs_small_buf_release(pSMB); */ /* Freed earlier now in SendReceive2 */
1959 if (resp_buf_type == CIFS_SMALL_BUFFER)
1960 cifs_small_buf_release(iov[0].iov_base);
1961 else if (resp_buf_type == CIFS_LARGE_BUFFER)
1962 cifs_buf_release(iov[0].iov_base);
1964 /* Note: On -EAGAIN error only caller can retry on handle based calls
1965 since file handle passed in no longer valid */
1972 CIFSSMBLock(const int xid, struct cifsTconInfo *tcon,
1973 const __u16 smb_file_id, const __u64 len,
1974 const __u64 offset, const __u32 numUnlock,
1975 const __u32 numLock, const __u8 lockType,
1976 const bool waitFlag, const __u8 oplock_level)
1979 LOCK_REQ *pSMB = NULL;
1980 /* LOCK_RSP *pSMBr = NULL; */ /* No response data other than rc to parse */
1985 cFYI(1, "CIFSSMBLock timeout %d numLock %d", (int)waitFlag, numLock);
1986 rc = small_smb_init(SMB_COM_LOCKING_ANDX, 8, tcon, (void **) &pSMB);
1991 if (lockType == LOCKING_ANDX_OPLOCK_RELEASE) {
1992 timeout = CIFS_ASYNC_OP; /* no response expected */
1994 } else if (waitFlag) {
1995 timeout = CIFS_BLOCKING_OP; /* blocking operation, no timeout */
1996 pSMB->Timeout = cpu_to_le32(-1);/* blocking - do not time out */
2001 pSMB->NumberOfLocks = cpu_to_le16(numLock);
2002 pSMB->NumberOfUnlocks = cpu_to_le16(numUnlock);
2003 pSMB->LockType = lockType;
2004 pSMB->OplockLevel = oplock_level;
2005 pSMB->AndXCommand = 0xFF; /* none */
2006 pSMB->Fid = smb_file_id; /* netfid stays le */
2008 if ((numLock != 0) || (numUnlock != 0)) {
2009 pSMB->Locks[0].Pid = cpu_to_le16(current->tgid);
2010 /* BB where to store pid high? */
2011 pSMB->Locks[0].LengthLow = cpu_to_le32((u32)len);
2012 pSMB->Locks[0].LengthHigh = cpu_to_le32((u32)(len>>32));
2013 pSMB->Locks[0].OffsetLow = cpu_to_le32((u32)offset);
2014 pSMB->Locks[0].OffsetHigh = cpu_to_le32((u32)(offset>>32));
2015 count = sizeof(LOCKING_ANDX_RANGE);
2020 inc_rfc1001_len(pSMB, count);
2021 pSMB->ByteCount = cpu_to_le16(count);
2024 rc = SendReceiveBlockingLock(xid, tcon, (struct smb_hdr *) pSMB,
2025 (struct smb_hdr *) pSMB, &bytes_returned);
2026 cifs_small_buf_release(pSMB);
2028 rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *)pSMB,
2030 /* SMB buffer freed by function above */
2032 cifs_stats_inc(&tcon->num_locks);
2034 cFYI(1, "Send error in Lock = %d", rc);
2036 /* Note: On -EAGAIN error only caller can retry on handle based calls
2037 since file handle passed in no longer valid */
2042 CIFSSMBPosixLock(const int xid, struct cifsTconInfo *tcon,
2043 const __u16 smb_file_id, const int get_flag, const __u64 len,
2044 struct file_lock *pLockData, const __u16 lock_type,
2045 const bool waitFlag)
2047 struct smb_com_transaction2_sfi_req *pSMB = NULL;
2048 struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
2049 struct cifs_posix_lock *parm_data;
2052 int bytes_returned = 0;
2053 int resp_buf_type = 0;
2054 __u16 params, param_offset, offset, byte_count, count;
2057 cFYI(1, "Posix Lock");
2059 if (pLockData == NULL)
2062 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
2067 pSMBr = (struct smb_com_transaction2_sfi_rsp *)pSMB;
2070 pSMB->MaxSetupCount = 0;
2073 pSMB->Reserved2 = 0;
2074 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
2075 offset = param_offset + params;
2077 count = sizeof(struct cifs_posix_lock);
2078 pSMB->MaxParameterCount = cpu_to_le16(2);
2079 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB from sess */
2080 pSMB->SetupCount = 1;
2081 pSMB->Reserved3 = 0;
2083 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION);
2085 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
2086 byte_count = 3 /* pad */ + params + count;
2087 pSMB->DataCount = cpu_to_le16(count);
2088 pSMB->ParameterCount = cpu_to_le16(params);
2089 pSMB->TotalDataCount = pSMB->DataCount;
2090 pSMB->TotalParameterCount = pSMB->ParameterCount;
2091 pSMB->ParameterOffset = cpu_to_le16(param_offset);
2092 parm_data = (struct cifs_posix_lock *)
2093 (((char *) &pSMB->hdr.Protocol) + offset);
2095 parm_data->lock_type = cpu_to_le16(lock_type);
2097 timeout = CIFS_BLOCKING_OP; /* blocking operation, no timeout */
2098 parm_data->lock_flags = cpu_to_le16(1);
2099 pSMB->Timeout = cpu_to_le32(-1);
2103 parm_data->pid = cpu_to_le32(current->tgid);
2104 parm_data->start = cpu_to_le64(pLockData->fl_start);
2105 parm_data->length = cpu_to_le64(len); /* normalize negative numbers */
2107 pSMB->DataOffset = cpu_to_le16(offset);
2108 pSMB->Fid = smb_file_id;
2109 pSMB->InformationLevel = cpu_to_le16(SMB_SET_POSIX_LOCK);
2110 pSMB->Reserved4 = 0;
2111 inc_rfc1001_len(pSMB, byte_count);
2112 pSMB->ByteCount = cpu_to_le16(byte_count);
2114 rc = SendReceiveBlockingLock(xid, tcon, (struct smb_hdr *) pSMB,
2115 (struct smb_hdr *) pSMBr, &bytes_returned);
2117 iov[0].iov_base = (char *)pSMB;
2118 iov[0].iov_len = be32_to_cpu(pSMB->hdr.smb_buf_length) + 4;
2119 rc = SendReceive2(xid, tcon->ses, iov, 1 /* num iovecs */,
2120 &resp_buf_type, timeout);
2121 pSMB = NULL; /* request buf already freed by SendReceive2. Do
2122 not try to free it twice below on exit */
2123 pSMBr = (struct smb_com_transaction2_sfi_rsp *)iov[0].iov_base;
2127 cFYI(1, "Send error in Posix Lock = %d", rc);
2128 } else if (get_flag) {
2129 /* lock structure can be returned on get */
2132 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
2134 if (rc || get_bcc(&pSMBr->hdr) < sizeof(*parm_data)) {
2135 rc = -EIO; /* bad smb */
2138 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
2139 data_count = le16_to_cpu(pSMBr->t2.DataCount);
2140 if (data_count < sizeof(struct cifs_posix_lock)) {
2144 parm_data = (struct cifs_posix_lock *)
2145 ((char *)&pSMBr->hdr.Protocol + data_offset);
2146 if (parm_data->lock_type == __constant_cpu_to_le16(CIFS_UNLCK))
2147 pLockData->fl_type = F_UNLCK;
2149 if (parm_data->lock_type ==
2150 __constant_cpu_to_le16(CIFS_RDLCK))
2151 pLockData->fl_type = F_RDLCK;
2152 else if (parm_data->lock_type ==
2153 __constant_cpu_to_le16(CIFS_WRLCK))
2154 pLockData->fl_type = F_WRLCK;
2156 pLockData->fl_start = le64_to_cpu(parm_data->start);
2157 pLockData->fl_end = pLockData->fl_start +
2158 le64_to_cpu(parm_data->length) - 1;
2159 pLockData->fl_pid = le32_to_cpu(parm_data->pid);
2165 cifs_small_buf_release(pSMB);
2167 if (resp_buf_type == CIFS_SMALL_BUFFER)
2168 cifs_small_buf_release(iov[0].iov_base);
2169 else if (resp_buf_type == CIFS_LARGE_BUFFER)
2170 cifs_buf_release(iov[0].iov_base);
2172 /* Note: On -EAGAIN error only caller can retry on handle based calls
2173 since file handle passed in no longer valid */
2180 CIFSSMBClose(const int xid, struct cifsTconInfo *tcon, int smb_file_id)
2183 CLOSE_REQ *pSMB = NULL;
2184 cFYI(1, "In CIFSSMBClose");
2186 /* do not retry on dead session on close */
2187 rc = small_smb_init(SMB_COM_CLOSE, 3, tcon, (void **) &pSMB);
2193 pSMB->FileID = (__u16) smb_file_id;
2194 pSMB->LastWriteTime = 0xFFFFFFFF;
2195 pSMB->ByteCount = 0;
2196 rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0);
2197 cifs_stats_inc(&tcon->num_closes);
2200 /* EINTR is expected when user ctl-c to kill app */
2201 cERROR(1, "Send error in Close = %d", rc);
2205 /* Since session is dead, file will be closed on server already */
2213 CIFSSMBFlush(const int xid, struct cifsTconInfo *tcon, int smb_file_id)
2216 FLUSH_REQ *pSMB = NULL;
2217 cFYI(1, "In CIFSSMBFlush");
2219 rc = small_smb_init(SMB_COM_FLUSH, 1, tcon, (void **) &pSMB);
2223 pSMB->FileID = (__u16) smb_file_id;
2224 pSMB->ByteCount = 0;
2225 rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0);
2226 cifs_stats_inc(&tcon->num_flushes);
2228 cERROR(1, "Send error in Flush = %d", rc);
2234 CIFSSMBRename(const int xid, struct cifsTconInfo *tcon,
2235 const char *fromName, const char *toName,
2236 const struct nls_table *nls_codepage, int remap)
2239 RENAME_REQ *pSMB = NULL;
2240 RENAME_RSP *pSMBr = NULL;
2242 int name_len, name_len2;
2245 cFYI(1, "In CIFSSMBRename");
2247 rc = smb_init(SMB_COM_RENAME, 1, tcon, (void **) &pSMB,
2252 pSMB->BufferFormat = 0x04;
2253 pSMB->SearchAttributes =
2254 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
2257 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2259 cifsConvertToUCS((__le16 *) pSMB->OldFileName, fromName,
2260 PATH_MAX, nls_codepage, remap);
2261 name_len++; /* trailing null */
2263 pSMB->OldFileName[name_len] = 0x04; /* pad */
2264 /* protocol requires ASCII signature byte on Unicode string */
2265 pSMB->OldFileName[name_len + 1] = 0x00;
2267 cifsConvertToUCS((__le16 *)&pSMB->OldFileName[name_len + 2],
2268 toName, PATH_MAX, nls_codepage, remap);
2269 name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
2270 name_len2 *= 2; /* convert to bytes */
2271 } else { /* BB improve the check for buffer overruns BB */
2272 name_len = strnlen(fromName, PATH_MAX);
2273 name_len++; /* trailing null */
2274 strncpy(pSMB->OldFileName, fromName, name_len);
2275 name_len2 = strnlen(toName, PATH_MAX);
2276 name_len2++; /* trailing null */
2277 pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */
2278 strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2);
2279 name_len2++; /* trailing null */
2280 name_len2++; /* signature byte */
2283 count = 1 /* 1st signature byte */ + name_len + name_len2;
2284 inc_rfc1001_len(pSMB, count);
2285 pSMB->ByteCount = cpu_to_le16(count);
2287 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2288 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2289 cifs_stats_inc(&tcon->num_renames);
2291 cFYI(1, "Send error in rename = %d", rc);
2293 cifs_buf_release(pSMB);
2301 int CIFSSMBRenameOpenFile(const int xid, struct cifsTconInfo *pTcon,
2302 int netfid, const char *target_name,
2303 const struct nls_table *nls_codepage, int remap)
2305 struct smb_com_transaction2_sfi_req *pSMB = NULL;
2306 struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
2307 struct set_file_rename *rename_info;
2309 char dummy_string[30];
2311 int bytes_returned = 0;
2313 __u16 params, param_offset, offset, count, byte_count;
2315 cFYI(1, "Rename to File by handle");
2316 rc = smb_init(SMB_COM_TRANSACTION2, 15, pTcon, (void **) &pSMB,
2322 pSMB->MaxSetupCount = 0;
2326 pSMB->Reserved2 = 0;
2327 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
2328 offset = param_offset + params;
2330 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
2331 rename_info = (struct set_file_rename *) data_offset;
2332 pSMB->MaxParameterCount = cpu_to_le16(2);
2333 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB from sess */
2334 pSMB->SetupCount = 1;
2335 pSMB->Reserved3 = 0;
2336 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
2337 byte_count = 3 /* pad */ + params;
2338 pSMB->ParameterCount = cpu_to_le16(params);
2339 pSMB->TotalParameterCount = pSMB->ParameterCount;
2340 pSMB->ParameterOffset = cpu_to_le16(param_offset);
2341 pSMB->DataOffset = cpu_to_le16(offset);
2342 /* construct random name ".cifs_tmp<inodenum><mid>" */
2343 rename_info->overwrite = cpu_to_le32(1);
2344 rename_info->root_fid = 0;
2345 /* unicode only call */
2346 if (target_name == NULL) {
2347 sprintf(dummy_string, "cifs%x", pSMB->hdr.Mid);
2348 len_of_str = cifsConvertToUCS((__le16 *)rename_info->target_name,
2349 dummy_string, 24, nls_codepage, remap);
2351 len_of_str = cifsConvertToUCS((__le16 *)rename_info->target_name,
2352 target_name, PATH_MAX, nls_codepage,
2355 rename_info->target_name_len = cpu_to_le32(2 * len_of_str);
2356 count = 12 /* sizeof(struct set_file_rename) */ + (2 * len_of_str);
2357 byte_count += count;
2358 pSMB->DataCount = cpu_to_le16(count);
2359 pSMB->TotalDataCount = pSMB->DataCount;
2361 pSMB->InformationLevel =
2362 cpu_to_le16(SMB_SET_FILE_RENAME_INFORMATION);
2363 pSMB->Reserved4 = 0;
2364 inc_rfc1001_len(pSMB, byte_count);
2365 pSMB->ByteCount = cpu_to_le16(byte_count);
2366 rc = SendReceive(xid, pTcon->ses, (struct smb_hdr *) pSMB,
2367 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2368 cifs_stats_inc(&pTcon->num_t2renames);
2370 cFYI(1, "Send error in Rename (by file handle) = %d", rc);
2372 cifs_buf_release(pSMB);
2374 /* Note: On -EAGAIN error only caller can retry on handle based calls
2375 since file handle passed in no longer valid */
2381 CIFSSMBCopy(const int xid, struct cifsTconInfo *tcon, const char *fromName,
2382 const __u16 target_tid, const char *toName, const int flags,
2383 const struct nls_table *nls_codepage, int remap)
2386 COPY_REQ *pSMB = NULL;
2387 COPY_RSP *pSMBr = NULL;
2389 int name_len, name_len2;
2392 cFYI(1, "In CIFSSMBCopy");
2394 rc = smb_init(SMB_COM_COPY, 1, tcon, (void **) &pSMB,
2399 pSMB->BufferFormat = 0x04;
2400 pSMB->Tid2 = target_tid;
2402 pSMB->Flags = cpu_to_le16(flags & COPY_TREE);
2404 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2405 name_len = cifsConvertToUCS((__le16 *) pSMB->OldFileName,
2406 fromName, PATH_MAX, nls_codepage,
2408 name_len++; /* trailing null */
2410 pSMB->OldFileName[name_len] = 0x04; /* pad */
2411 /* protocol requires ASCII signature byte on Unicode string */
2412 pSMB->OldFileName[name_len + 1] = 0x00;
2414 cifsConvertToUCS((__le16 *)&pSMB->OldFileName[name_len + 2],
2415 toName, PATH_MAX, nls_codepage, remap);
2416 name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
2417 name_len2 *= 2; /* convert to bytes */
2418 } else { /* BB improve the check for buffer overruns BB */
2419 name_len = strnlen(fromName, PATH_MAX);
2420 name_len++; /* trailing null */
2421 strncpy(pSMB->OldFileName, fromName, name_len);
2422 name_len2 = strnlen(toName, PATH_MAX);
2423 name_len2++; /* trailing null */
2424 pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */
2425 strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2);
2426 name_len2++; /* trailing null */
2427 name_len2++; /* signature byte */
2430 count = 1 /* 1st signature byte */ + name_len + name_len2;
2431 inc_rfc1001_len(pSMB, count);
2432 pSMB->ByteCount = cpu_to_le16(count);
2434 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2435 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2437 cFYI(1, "Send error in copy = %d with %d files copied",
2438 rc, le16_to_cpu(pSMBr->CopyCount));
2440 cifs_buf_release(pSMB);
2449 CIFSUnixCreateSymLink(const int xid, struct cifsTconInfo *tcon,
2450 const char *fromName, const char *toName,
2451 const struct nls_table *nls_codepage)
2453 TRANSACTION2_SPI_REQ *pSMB = NULL;
2454 TRANSACTION2_SPI_RSP *pSMBr = NULL;
2457 int name_len_target;
2459 int bytes_returned = 0;
2460 __u16 params, param_offset, offset, byte_count;
2462 cFYI(1, "In Symlink Unix style");
2464 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2469 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2471 cifs_strtoUCS((__le16 *) pSMB->FileName, fromName, PATH_MAX
2472 /* find define for this maxpathcomponent */
2474 name_len++; /* trailing null */
2477 } else { /* BB improve the check for buffer overruns BB */
2478 name_len = strnlen(fromName, PATH_MAX);
2479 name_len++; /* trailing null */
2480 strncpy(pSMB->FileName, fromName, name_len);
2482 params = 6 + name_len;
2483 pSMB->MaxSetupCount = 0;
2487 pSMB->Reserved2 = 0;
2488 param_offset = offsetof(struct smb_com_transaction2_spi_req,
2489 InformationLevel) - 4;
2490 offset = param_offset + params;
2492 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
2493 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2495 cifs_strtoUCS((__le16 *) data_offset, toName, PATH_MAX
2496 /* find define for this maxpathcomponent */
2498 name_len_target++; /* trailing null */
2499 name_len_target *= 2;
2500 } else { /* BB improve the check for buffer overruns BB */
2501 name_len_target = strnlen(toName, PATH_MAX);
2502 name_len_target++; /* trailing null */
2503 strncpy(data_offset, toName, name_len_target);
2506 pSMB->MaxParameterCount = cpu_to_le16(2);
2507 /* BB find exact max on data count below from sess */
2508 pSMB->MaxDataCount = cpu_to_le16(1000);
2509 pSMB->SetupCount = 1;
2510 pSMB->Reserved3 = 0;
2511 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
2512 byte_count = 3 /* pad */ + params + name_len_target;
2513 pSMB->DataCount = cpu_to_le16(name_len_target);
2514 pSMB->ParameterCount = cpu_to_le16(params);
2515 pSMB->TotalDataCount = pSMB->DataCount;
2516 pSMB->TotalParameterCount = pSMB->ParameterCount;
2517 pSMB->ParameterOffset = cpu_to_le16(param_offset);
2518 pSMB->DataOffset = cpu_to_le16(offset);
2519 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_LINK);
2520 pSMB->Reserved4 = 0;
2521 inc_rfc1001_len(pSMB, byte_count);
2522 pSMB->ByteCount = cpu_to_le16(byte_count);
2523 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2524 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2525 cifs_stats_inc(&tcon->num_symlinks);
2527 cFYI(1, "Send error in SetPathInfo create symlink = %d", rc);
2529 cifs_buf_release(pSMB);
2532 goto createSymLinkRetry;
2538 CIFSUnixCreateHardLink(const int xid, struct cifsTconInfo *tcon,
2539 const char *fromName, const char *toName,
2540 const struct nls_table *nls_codepage, int remap)
2542 TRANSACTION2_SPI_REQ *pSMB = NULL;
2543 TRANSACTION2_SPI_RSP *pSMBr = NULL;
2546 int name_len_target;
2548 int bytes_returned = 0;
2549 __u16 params, param_offset, offset, byte_count;
2551 cFYI(1, "In Create Hard link Unix style");
2552 createHardLinkRetry:
2553 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2558 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2559 name_len = cifsConvertToUCS((__le16 *) pSMB->FileName, toName,
2560 PATH_MAX, nls_codepage, remap);
2561 name_len++; /* trailing null */
2564 } else { /* BB improve the check for buffer overruns BB */
2565 name_len = strnlen(toName, PATH_MAX);
2566 name_len++; /* trailing null */
2567 strncpy(pSMB->FileName, toName, name_len);
2569 params = 6 + name_len;
2570 pSMB->MaxSetupCount = 0;
2574 pSMB->Reserved2 = 0;
2575 param_offset = offsetof(struct smb_com_transaction2_spi_req,
2576 InformationLevel) - 4;
2577 offset = param_offset + params;
2579 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
2580 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2582 cifsConvertToUCS((__le16 *) data_offset, fromName, PATH_MAX,
2583 nls_codepage, remap);
2584 name_len_target++; /* trailing null */
2585 name_len_target *= 2;
2586 } else { /* BB improve the check for buffer overruns BB */
2587 name_len_target = strnlen(fromName, PATH_MAX);
2588 name_len_target++; /* trailing null */
2589 strncpy(data_offset, fromName, name_len_target);
2592 pSMB->MaxParameterCount = cpu_to_le16(2);
2593 /* BB find exact max on data count below from sess*/
2594 pSMB->MaxDataCount = cpu_to_le16(1000);
2595 pSMB->SetupCount = 1;
2596 pSMB->Reserved3 = 0;
2597 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
2598 byte_count = 3 /* pad */ + params + name_len_target;
2599 pSMB->ParameterCount = cpu_to_le16(params);
2600 pSMB->TotalParameterCount = pSMB->ParameterCount;
2601 pSMB->DataCount = cpu_to_le16(name_len_target);
2602 pSMB->TotalDataCount = pSMB->DataCount;
2603 pSMB->ParameterOffset = cpu_to_le16(param_offset);
2604 pSMB->DataOffset = cpu_to_le16(offset);
2605 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_HLINK);
2606 pSMB->Reserved4 = 0;
2607 inc_rfc1001_len(pSMB, byte_count);
2608 pSMB->ByteCount = cpu_to_le16(byte_count);
2609 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2610 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2611 cifs_stats_inc(&tcon->num_hardlinks);
2613 cFYI(1, "Send error in SetPathInfo (hard link) = %d", rc);
2615 cifs_buf_release(pSMB);
2617 goto createHardLinkRetry;
2623 CIFSCreateHardLink(const int xid, struct cifsTconInfo *tcon,
2624 const char *fromName, const char *toName,
2625 const struct nls_table *nls_codepage, int remap)
2628 NT_RENAME_REQ *pSMB = NULL;
2629 RENAME_RSP *pSMBr = NULL;
2631 int name_len, name_len2;
2634 cFYI(1, "In CIFSCreateHardLink");
2635 winCreateHardLinkRetry:
2637 rc = smb_init(SMB_COM_NT_RENAME, 4, tcon, (void **) &pSMB,
2642 pSMB->SearchAttributes =
2643 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
2645 pSMB->Flags = cpu_to_le16(CREATE_HARD_LINK);
2646 pSMB->ClusterCount = 0;
2648 pSMB->BufferFormat = 0x04;
2650 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2652 cifsConvertToUCS((__le16 *) pSMB->OldFileName, fromName,
2653 PATH_MAX, nls_codepage, remap);
2654 name_len++; /* trailing null */
2657 /* protocol specifies ASCII buffer format (0x04) for unicode */
2658 pSMB->OldFileName[name_len] = 0x04;
2659 pSMB->OldFileName[name_len + 1] = 0x00; /* pad */
2661 cifsConvertToUCS((__le16 *)&pSMB->OldFileName[name_len + 2],
2662 toName, PATH_MAX, nls_codepage, remap);
2663 name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
2664 name_len2 *= 2; /* convert to bytes */
2665 } else { /* BB improve the check for buffer overruns BB */
2666 name_len = strnlen(fromName, PATH_MAX);
2667 name_len++; /* trailing null */
2668 strncpy(pSMB->OldFileName, fromName, name_len);
2669 name_len2 = strnlen(toName, PATH_MAX);
2670 name_len2++; /* trailing null */
2671 pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */
2672 strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2);
2673 name_len2++; /* trailing null */
2674 name_len2++; /* signature byte */
2677 count = 1 /* string type byte */ + name_len + name_len2;
2678 inc_rfc1001_len(pSMB, count);
2679 pSMB->ByteCount = cpu_to_le16(count);
2681 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2682 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2683 cifs_stats_inc(&tcon->num_hardlinks);
2685 cFYI(1, "Send error in hard link (NT rename) = %d", rc);
2687 cifs_buf_release(pSMB);
2689 goto winCreateHardLinkRetry;
2695 CIFSSMBUnixQuerySymLink(const int xid, struct cifsTconInfo *tcon,
2696 const unsigned char *searchName, char **symlinkinfo,
2697 const struct nls_table *nls_codepage)
2699 /* SMB_QUERY_FILE_UNIX_LINK */
2700 TRANSACTION2_QPI_REQ *pSMB = NULL;
2701 TRANSACTION2_QPI_RSP *pSMBr = NULL;
2705 __u16 params, byte_count;
2708 cFYI(1, "In QPathSymLinkInfo (Unix) for path %s", searchName);
2711 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2716 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2718 cifs_strtoUCS((__le16 *) pSMB->FileName, searchName,
2719 PATH_MAX, nls_codepage);
2720 name_len++; /* trailing null */
2722 } else { /* BB improve the check for buffer overruns BB */
2723 name_len = strnlen(searchName, PATH_MAX);
2724 name_len++; /* trailing null */
2725 strncpy(pSMB->FileName, searchName, name_len);
2728 params = 2 /* level */ + 4 /* rsrvd */ + name_len /* incl null */ ;
2729 pSMB->TotalDataCount = 0;
2730 pSMB->MaxParameterCount = cpu_to_le16(2);
2731 pSMB->MaxDataCount = cpu_to_le16(CIFSMaxBufSize);
2732 pSMB->MaxSetupCount = 0;
2736 pSMB->Reserved2 = 0;
2737 pSMB->ParameterOffset = cpu_to_le16(offsetof(
2738 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
2739 pSMB->DataCount = 0;
2740 pSMB->DataOffset = 0;
2741 pSMB->SetupCount = 1;
2742 pSMB->Reserved3 = 0;
2743 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
2744 byte_count = params + 1 /* pad */ ;
2745 pSMB->TotalParameterCount = cpu_to_le16(params);
2746 pSMB->ParameterCount = pSMB->TotalParameterCount;
2747 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_LINK);
2748 pSMB->Reserved4 = 0;
2749 inc_rfc1001_len(pSMB, byte_count);
2750 pSMB->ByteCount = cpu_to_le16(byte_count);
2752 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2753 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2755 cFYI(1, "Send error in QuerySymLinkInfo = %d", rc);
2757 /* decode response */
2759 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
2760 /* BB also check enough total bytes returned */
2761 if (rc || get_bcc(&pSMBr->hdr) < 2)
2765 u16 count = le16_to_cpu(pSMBr->t2.DataCount);
2767 data_start = ((char *) &pSMBr->hdr.Protocol) +
2768 le16_to_cpu(pSMBr->t2.DataOffset);
2770 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
2775 /* BB FIXME investigate remapping reserved chars here */
2776 *symlinkinfo = cifs_strndup_from_ucs(data_start, count,
2777 is_unicode, nls_codepage);
2782 cifs_buf_release(pSMB);
2784 goto querySymLinkRetry;
2788 #ifdef CONFIG_CIFS_SYMLINK_EXPERIMENTAL
2790 * Recent Windows versions now create symlinks more frequently
2791 * and they use the "reparse point" mechanism below. We can of course
2792 * do symlinks nicely to Samba and other servers which support the
2793 * CIFS Unix Extensions and we can also do SFU symlinks and "client only"
2794 * "MF" symlinks optionally, but for recent Windows we really need to
2795 * reenable the code below and fix the cifs_symlink callers to handle this.
2796 * In the interim this code has been moved to its own config option so
2797 * it is not compiled in by default until callers fixed up and more tested.
2800 CIFSSMBQueryReparseLinkInfo(const int xid, struct cifsTconInfo *tcon,
2801 const unsigned char *searchName,
2802 char *symlinkinfo, const int buflen, __u16 fid,
2803 const struct nls_table *nls_codepage)
2807 struct smb_com_transaction_ioctl_req *pSMB;
2808 struct smb_com_transaction_ioctl_rsp *pSMBr;
2810 cFYI(1, "In Windows reparse style QueryLink for path %s", searchName);
2811 rc = smb_init(SMB_COM_NT_TRANSACT, 23, tcon, (void **) &pSMB,
2816 pSMB->TotalParameterCount = 0 ;
2817 pSMB->TotalDataCount = 0;
2818 pSMB->MaxParameterCount = cpu_to_le32(2);
2819 /* BB find exact data count max from sess structure BB */
2820 pSMB->MaxDataCount = cpu_to_le32((tcon->ses->server->maxBuf -
2821 MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
2822 pSMB->MaxSetupCount = 4;
2824 pSMB->ParameterOffset = 0;
2825 pSMB->DataCount = 0;
2826 pSMB->DataOffset = 0;
2827 pSMB->SetupCount = 4;
2828 pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_IOCTL);
2829 pSMB->ParameterCount = pSMB->TotalParameterCount;
2830 pSMB->FunctionCode = cpu_to_le32(FSCTL_GET_REPARSE_POINT);
2831 pSMB->IsFsctl = 1; /* FSCTL */
2832 pSMB->IsRootFlag = 0;
2833 pSMB->Fid = fid; /* file handle always le */
2834 pSMB->ByteCount = 0;
2836 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2837 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2839 cFYI(1, "Send error in QueryReparseLinkInfo = %d", rc);
2840 } else { /* decode response */
2841 __u32 data_offset = le32_to_cpu(pSMBr->DataOffset);
2842 __u32 data_count = le32_to_cpu(pSMBr->DataCount);
2843 if (get_bcc(&pSMBr->hdr) < 2 || data_offset > 512) {
2844 /* BB also check enough total bytes returned */
2845 rc = -EIO; /* bad smb */
2848 if (data_count && (data_count < 2048)) {
2849 char *end_of_smb = 2 /* sizeof byte count */ +
2850 get_bcc(&pSMBr->hdr) + (char *)&pSMBr->ByteCount;
2852 struct reparse_data *reparse_buf =
2853 (struct reparse_data *)
2854 ((char *)&pSMBr->hdr.Protocol
2856 if ((char *)reparse_buf >= end_of_smb) {
2860 if ((reparse_buf->LinkNamesBuf +
2861 reparse_buf->TargetNameOffset +
2862 reparse_buf->TargetNameLen) > end_of_smb) {
2863 cFYI(1, "reparse buf beyond SMB");
2868 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
2869 cifs_from_ucs2(symlinkinfo, (__le16 *)
2870 (reparse_buf->LinkNamesBuf +
2871 reparse_buf->TargetNameOffset),
2873 reparse_buf->TargetNameLen,
2875 } else { /* ASCII names */
2876 strncpy(symlinkinfo,
2877 reparse_buf->LinkNamesBuf +
2878 reparse_buf->TargetNameOffset,
2879 min_t(const int, buflen,
2880 reparse_buf->TargetNameLen));
2884 cFYI(1, "Invalid return data count on "
2885 "get reparse info ioctl");
2887 symlinkinfo[buflen] = 0; /* just in case so the caller
2888 does not go off the end of the buffer */
2889 cFYI(1, "readlink result - %s", symlinkinfo);
2893 cifs_buf_release(pSMB);
2895 /* Note: On -EAGAIN error only caller can retry on handle based calls
2896 since file handle passed in no longer valid */
2900 #endif /* CIFS_SYMLINK_EXPERIMENTAL */ /* BB temporarily unused */
2902 #ifdef CONFIG_CIFS_POSIX
2904 /*Convert an Access Control Entry from wire format to local POSIX xattr format*/
2905 static void cifs_convert_ace(posix_acl_xattr_entry *ace,
2906 struct cifs_posix_ace *cifs_ace)
2908 /* u8 cifs fields do not need le conversion */
2909 ace->e_perm = cpu_to_le16(cifs_ace->cifs_e_perm);
2910 ace->e_tag = cpu_to_le16(cifs_ace->cifs_e_tag);
2911 ace->e_id = cpu_to_le32(le64_to_cpu(cifs_ace->cifs_uid));
2912 /* cFYI(1, "perm %d tag %d id %d",ace->e_perm,ace->e_tag,ace->e_id); */
2917 /* Convert ACL from CIFS POSIX wire format to local Linux POSIX ACL xattr */
2918 static int cifs_copy_posix_acl(char *trgt, char *src, const int buflen,
2919 const int acl_type, const int size_of_data_area)
2924 struct cifs_posix_ace *pACE;
2925 struct cifs_posix_acl *cifs_acl = (struct cifs_posix_acl *)src;
2926 posix_acl_xattr_header *local_acl = (posix_acl_xattr_header *)trgt;
2928 if (le16_to_cpu(cifs_acl->version) != CIFS_ACL_VERSION)
2931 if (acl_type & ACL_TYPE_ACCESS) {
2932 count = le16_to_cpu(cifs_acl->access_entry_count);
2933 pACE = &cifs_acl->ace_array[0];
2934 size = sizeof(struct cifs_posix_acl);
2935 size += sizeof(struct cifs_posix_ace) * count;
2936 /* check if we would go beyond end of SMB */
2937 if (size_of_data_area < size) {
2938 cFYI(1, "bad CIFS POSIX ACL size %d vs. %d",
2939 size_of_data_area, size);
2942 } else if (acl_type & ACL_TYPE_DEFAULT) {
2943 count = le16_to_cpu(cifs_acl->access_entry_count);
2944 size = sizeof(struct cifs_posix_acl);
2945 size += sizeof(struct cifs_posix_ace) * count;
2946 /* skip past access ACEs to get to default ACEs */
2947 pACE = &cifs_acl->ace_array[count];
2948 count = le16_to_cpu(cifs_acl->default_entry_count);
2949 size += sizeof(struct cifs_posix_ace) * count;
2950 /* check if we would go beyond end of SMB */
2951 if (size_of_data_area < size)
2958 size = posix_acl_xattr_size(count);
2959 if ((buflen == 0) || (local_acl == NULL)) {
2960 /* used to query ACL EA size */
2961 } else if (size > buflen) {
2963 } else /* buffer big enough */ {
2964 local_acl->a_version = cpu_to_le32(POSIX_ACL_XATTR_VERSION);
2965 for (i = 0; i < count ; i++) {
2966 cifs_convert_ace(&local_acl->a_entries[i], pACE);
2973 static __u16 convert_ace_to_cifs_ace(struct cifs_posix_ace *cifs_ace,
2974 const posix_acl_xattr_entry *local_ace)
2976 __u16 rc = 0; /* 0 = ACL converted ok */
2978 cifs_ace->cifs_e_perm = le16_to_cpu(local_ace->e_perm);
2979 cifs_ace->cifs_e_tag = le16_to_cpu(local_ace->e_tag);
2980 /* BB is there a better way to handle the large uid? */
2981 if (local_ace->e_id == cpu_to_le32(-1)) {
2982 /* Probably no need to le convert -1 on any arch but can not hurt */
2983 cifs_ace->cifs_uid = cpu_to_le64(-1);
2985 cifs_ace->cifs_uid = cpu_to_le64(le32_to_cpu(local_ace->e_id));
2986 /*cFYI(1, "perm %d tag %d id %d",ace->e_perm,ace->e_tag,ace->e_id);*/
2990 /* Convert ACL from local Linux POSIX xattr to CIFS POSIX ACL wire format */
2991 static __u16 ACL_to_cifs_posix(char *parm_data, const char *pACL,
2992 const int buflen, const int acl_type)
2995 struct cifs_posix_acl *cifs_acl = (struct cifs_posix_acl *)parm_data;
2996 posix_acl_xattr_header *local_acl = (posix_acl_xattr_header *)pACL;
3000 if ((buflen == 0) || (pACL == NULL) || (cifs_acl == NULL))
3003 count = posix_acl_xattr_count((size_t)buflen);
3004 cFYI(1, "setting acl with %d entries from buf of length %d and "
3006 count, buflen, le32_to_cpu(local_acl->a_version));
3007 if (le32_to_cpu(local_acl->a_version) != 2) {
3008 cFYI(1, "unknown POSIX ACL version %d",
3009 le32_to_cpu(local_acl->a_version));
3012 cifs_acl->version = cpu_to_le16(1);
3013 if (acl_type == ACL_TYPE_ACCESS)
3014 cifs_acl->access_entry_count = cpu_to_le16(count);
3015 else if (acl_type == ACL_TYPE_DEFAULT)
3016 cifs_acl->default_entry_count = cpu_to_le16(count);
3018 cFYI(1, "unknown ACL type %d", acl_type);
3021 for (i = 0; i < count; i++) {
3022 rc = convert_ace_to_cifs_ace(&cifs_acl->ace_array[i],
3023 &local_acl->a_entries[i]);
3025 /* ACE not converted */
3030 rc = (__u16)(count * sizeof(struct cifs_posix_ace));
3031 rc += sizeof(struct cifs_posix_acl);
3032 /* BB add check to make sure ACL does not overflow SMB */
3038 CIFSSMBGetPosixACL(const int xid, struct cifsTconInfo *tcon,
3039 const unsigned char *searchName,
3040 char *acl_inf, const int buflen, const int acl_type,
3041 const struct nls_table *nls_codepage, int remap)
3043 /* SMB_QUERY_POSIX_ACL */
3044 TRANSACTION2_QPI_REQ *pSMB = NULL;
3045 TRANSACTION2_QPI_RSP *pSMBr = NULL;
3049 __u16 params, byte_count;
3051 cFYI(1, "In GetPosixACL (Unix) for path %s", searchName);
3054 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3059 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3061 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
3062 PATH_MAX, nls_codepage, remap);
3063 name_len++; /* trailing null */
3065 pSMB->FileName[name_len] = 0;
3066 pSMB->FileName[name_len+1] = 0;
3067 } else { /* BB improve the check for buffer overruns BB */
3068 name_len = strnlen(searchName, PATH_MAX);
3069 name_len++; /* trailing null */
3070 strncpy(pSMB->FileName, searchName, name_len);
3073 params = 2 /* level */ + 4 /* rsrvd */ + name_len /* incl null */ ;
3074 pSMB->TotalDataCount = 0;
3075 pSMB->MaxParameterCount = cpu_to_le16(2);
3076 /* BB find exact max data count below from sess structure BB */
3077 pSMB->MaxDataCount = cpu_to_le16(4000);
3078 pSMB->MaxSetupCount = 0;
3082 pSMB->Reserved2 = 0;
3083 pSMB->ParameterOffset = cpu_to_le16(
3084 offsetof(struct smb_com_transaction2_qpi_req,
3085 InformationLevel) - 4);
3086 pSMB->DataCount = 0;
3087 pSMB->DataOffset = 0;
3088 pSMB->SetupCount = 1;
3089 pSMB->Reserved3 = 0;
3090 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
3091 byte_count = params + 1 /* pad */ ;
3092 pSMB->TotalParameterCount = cpu_to_le16(params);
3093 pSMB->ParameterCount = pSMB->TotalParameterCount;
3094 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_POSIX_ACL);
3095 pSMB->Reserved4 = 0;
3096 inc_rfc1001_len(pSMB, byte_count);
3097 pSMB->ByteCount = cpu_to_le16(byte_count);
3099 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3100 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3101 cifs_stats_inc(&tcon->num_acl_get);
3103 cFYI(1, "Send error in Query POSIX ACL = %d", rc);
3105 /* decode response */
3107 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3108 /* BB also check enough total bytes returned */
3109 if (rc || get_bcc(&pSMBr->hdr) < 2)
3110 rc = -EIO; /* bad smb */
3112 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3113 __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
3114 rc = cifs_copy_posix_acl(acl_inf,
3115 (char *)&pSMBr->hdr.Protocol+data_offset,
3116 buflen, acl_type, count);
3119 cifs_buf_release(pSMB);
3126 CIFSSMBSetPosixACL(const int xid, struct cifsTconInfo *tcon,
3127 const unsigned char *fileName,
3128 const char *local_acl, const int buflen,
3130 const struct nls_table *nls_codepage, int remap)
3132 struct smb_com_transaction2_spi_req *pSMB = NULL;
3133 struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
3137 int bytes_returned = 0;
3138 __u16 params, byte_count, data_count, param_offset, offset;
3140 cFYI(1, "In SetPosixACL (Unix) for path %s", fileName);
3142 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3146 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3148 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
3149 PATH_MAX, nls_codepage, remap);
3150 name_len++; /* trailing null */
3152 } else { /* BB improve the check for buffer overruns BB */
3153 name_len = strnlen(fileName, PATH_MAX);
3154 name_len++; /* trailing null */
3155 strncpy(pSMB->FileName, fileName, name_len);
3157 params = 6 + name_len;
3158 pSMB->MaxParameterCount = cpu_to_le16(2);
3159 /* BB find max SMB size from sess */
3160 pSMB->MaxDataCount = cpu_to_le16(1000);
3161 pSMB->MaxSetupCount = 0;
3165 pSMB->Reserved2 = 0;
3166 param_offset = offsetof(struct smb_com_transaction2_spi_req,
3167 InformationLevel) - 4;
3168 offset = param_offset + params;
3169 parm_data = ((char *) &pSMB->hdr.Protocol) + offset;
3170 pSMB->ParameterOffset = cpu_to_le16(param_offset);
3172 /* convert to on the wire format for POSIX ACL */
3173 data_count = ACL_to_cifs_posix(parm_data, local_acl, buflen, acl_type);
3175 if (data_count == 0) {
3177 goto setACLerrorExit;
3179 pSMB->DataOffset = cpu_to_le16(offset);
3180 pSMB->SetupCount = 1;
3181 pSMB->Reserved3 = 0;
3182 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
3183 pSMB->InformationLevel = cpu_to_le16(SMB_SET_POSIX_ACL);
3184 byte_count = 3 /* pad */ + params + data_count;
3185 pSMB->DataCount = cpu_to_le16(data_count);
3186 pSMB->TotalDataCount = pSMB->DataCount;
3187 pSMB->ParameterCount = cpu_to_le16(params);
3188 pSMB->TotalParameterCount = pSMB->ParameterCount;
3189 pSMB->Reserved4 = 0;
3190 inc_rfc1001_len(pSMB, byte_count);
3191 pSMB->ByteCount = cpu_to_le16(byte_count);
3192 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3193 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3195 cFYI(1, "Set POSIX ACL returned %d", rc);
3198 cifs_buf_release(pSMB);
3204 /* BB fix tabs in this function FIXME BB */
3206 CIFSGetExtAttr(const int xid, struct cifsTconInfo *tcon,
3207 const int netfid, __u64 *pExtAttrBits, __u64 *pMask)
3210 struct smb_t2_qfi_req *pSMB = NULL;
3211 struct smb_t2_qfi_rsp *pSMBr = NULL;
3213 __u16 params, byte_count;
3215 cFYI(1, "In GetExtAttr");
3220 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3225 params = 2 /* level */ + 2 /* fid */;
3226 pSMB->t2.TotalDataCount = 0;
3227 pSMB->t2.MaxParameterCount = cpu_to_le16(4);
3228 /* BB find exact max data count below from sess structure BB */
3229 pSMB->t2.MaxDataCount = cpu_to_le16(4000);
3230 pSMB->t2.MaxSetupCount = 0;
3231 pSMB->t2.Reserved = 0;
3233 pSMB->t2.Timeout = 0;
3234 pSMB->t2.Reserved2 = 0;
3235 pSMB->t2.ParameterOffset = cpu_to_le16(offsetof(struct smb_t2_qfi_req,
3237 pSMB->t2.DataCount = 0;
3238 pSMB->t2.DataOffset = 0;
3239 pSMB->t2.SetupCount = 1;
3240 pSMB->t2.Reserved3 = 0;
3241 pSMB->t2.SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION);
3242 byte_count = params + 1 /* pad */ ;
3243 pSMB->t2.TotalParameterCount = cpu_to_le16(params);
3244 pSMB->t2.ParameterCount = pSMB->t2.TotalParameterCount;
3245 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_ATTR_FLAGS);
3248 inc_rfc1001_len(pSMB, byte_count);
3249 pSMB->t2.ByteCount = cpu_to_le16(byte_count);
3251 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3252 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3254 cFYI(1, "error %d in GetExtAttr", rc);
3256 /* decode response */
3257 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3258 /* BB also check enough total bytes returned */
3259 if (rc || get_bcc(&pSMBr->hdr) < 2)
3260 /* If rc should we check for EOPNOSUPP and
3261 disable the srvino flag? or in caller? */
3262 rc = -EIO; /* bad smb */
3264 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3265 __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
3266 struct file_chattr_info *pfinfo;
3267 /* BB Do we need a cast or hash here ? */
3269 cFYI(1, "Illegal size ret in GetExtAttr");
3273 pfinfo = (struct file_chattr_info *)
3274 (data_offset + (char *) &pSMBr->hdr.Protocol);
3275 *pExtAttrBits = le64_to_cpu(pfinfo->mode);
3276 *pMask = le64_to_cpu(pfinfo->mask);
3280 cifs_buf_release(pSMB);
3282 goto GetExtAttrRetry;
3286 #endif /* CONFIG_POSIX */
3288 #ifdef CONFIG_CIFS_ACL
3290 * Initialize NT TRANSACT SMB into small smb request buffer. This assumes that
3291 * all NT TRANSACTS that we init here have total parm and data under about 400
3292 * bytes (to fit in small cifs buffer size), which is the case so far, it
3293 * easily fits. NB: Setup words themselves and ByteCount MaxSetupCount (size of
3294 * returned setup area) and MaxParameterCount (returned parms size) must be set
3298 smb_init_nttransact(const __u16 sub_command, const int setup_count,
3299 const int parm_len, struct cifsTconInfo *tcon,
3304 struct smb_com_ntransact_req *pSMB;
3306 rc = small_smb_init(SMB_COM_NT_TRANSACT, 19 + setup_count, tcon,
3310 *ret_buf = (void *)pSMB;
3312 pSMB->TotalParameterCount = cpu_to_le32(parm_len);
3313 pSMB->TotalDataCount = 0;
3314 pSMB->MaxDataCount = cpu_to_le32((tcon->ses->server->maxBuf -
3315 MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
3316 pSMB->ParameterCount = pSMB->TotalParameterCount;
3317 pSMB->DataCount = pSMB->TotalDataCount;
3318 temp_offset = offsetof(struct smb_com_ntransact_req, Parms) +
3319 (setup_count * 2) - 4 /* for rfc1001 length itself */;
3320 pSMB->ParameterOffset = cpu_to_le32(temp_offset);
3321 pSMB->DataOffset = cpu_to_le32(temp_offset + parm_len);
3322 pSMB->SetupCount = setup_count; /* no need to le convert byte fields */
3323 pSMB->SubCommand = cpu_to_le16(sub_command);
3328 validate_ntransact(char *buf, char **ppparm, char **ppdata,
3329 __u32 *pparmlen, __u32 *pdatalen)
3332 __u32 data_count, data_offset, parm_count, parm_offset;
3333 struct smb_com_ntransact_rsp *pSMBr;
3342 pSMBr = (struct smb_com_ntransact_rsp *)buf;
3344 bcc = get_bcc(&pSMBr->hdr);
3345 end_of_smb = 2 /* sizeof byte count */ + bcc +
3346 (char *)&pSMBr->ByteCount;
3348 data_offset = le32_to_cpu(pSMBr->DataOffset);
3349 data_count = le32_to_cpu(pSMBr->DataCount);
3350 parm_offset = le32_to_cpu(pSMBr->ParameterOffset);
3351 parm_count = le32_to_cpu(pSMBr->ParameterCount);
3353 *ppparm = (char *)&pSMBr->hdr.Protocol + parm_offset;
3354 *ppdata = (char *)&pSMBr->hdr.Protocol + data_offset;
3356 /* should we also check that parm and data areas do not overlap? */
3357 if (*ppparm > end_of_smb) {
3358 cFYI(1, "parms start after end of smb");
3360 } else if (parm_count + *ppparm > end_of_smb) {
3361 cFYI(1, "parm end after end of smb");
3363 } else if (*ppdata > end_of_smb) {
3364 cFYI(1, "data starts after end of smb");
3366 } else if (data_count + *ppdata > end_of_smb) {
3367 cFYI(1, "data %p + count %d (%p) past smb end %p start %p",
3368 *ppdata, data_count, (data_count + *ppdata),
3371 } else if (parm_count + data_count > bcc) {
3372 cFYI(1, "parm count and data count larger than SMB");
3375 *pdatalen = data_count;
3376 *pparmlen = parm_count;
3380 /* Get Security Descriptor (by handle) from remote server for a file or dir */
3382 CIFSSMBGetCIFSACL(const int xid, struct cifsTconInfo *tcon, __u16 fid,
3383 struct cifs_ntsd **acl_inf, __u32 *pbuflen)
3387 QUERY_SEC_DESC_REQ *pSMB;
3390 cFYI(1, "GetCifsACL");
3395 rc = smb_init_nttransact(NT_TRANSACT_QUERY_SECURITY_DESC, 0,
3396 8 /* parm len */, tcon, (void **) &pSMB);
3400 pSMB->MaxParameterCount = cpu_to_le32(4);
3401 /* BB TEST with big acls that might need to be e.g. larger than 16K */
3402 pSMB->MaxSetupCount = 0;
3403 pSMB->Fid = fid; /* file handle always le */
3404 pSMB->AclFlags = cpu_to_le32(CIFS_ACL_OWNER | CIFS_ACL_GROUP |
3406 pSMB->ByteCount = cpu_to_le16(11); /* 3 bytes pad + 8 bytes parm */
3407 inc_rfc1001_len(pSMB, 11);
3408 iov[0].iov_base = (char *)pSMB;
3409 iov[0].iov_len = be32_to_cpu(pSMB->hdr.smb_buf_length) + 4;
3411 rc = SendReceive2(xid, tcon->ses, iov, 1 /* num iovec */, &buf_type,
3413 cifs_stats_inc(&tcon->num_acl_get);
3415 cFYI(1, "Send error in QuerySecDesc = %d", rc);
3416 } else { /* decode response */
3420 struct smb_com_ntransact_rsp *pSMBr;
3423 /* validate_nttransact */
3424 rc = validate_ntransact(iov[0].iov_base, (char **)&parm,
3425 &pdata, &parm_len, pbuflen);
3428 pSMBr = (struct smb_com_ntransact_rsp *)iov[0].iov_base;
3430 cFYI(1, "smb %p parm %p data %p", pSMBr, parm, *acl_inf);
3432 if (le32_to_cpu(pSMBr->ParameterCount) != 4) {
3433 rc = -EIO; /* bad smb */
3438 /* BB check that data area is minimum length and as big as acl_len */
3440 acl_len = le32_to_cpu(*parm);
3441 if (acl_len != *pbuflen) {
3442 cERROR(1, "acl length %d does not match %d",
3444 if (*pbuflen > acl_len)
3448 /* check if buffer is big enough for the acl
3449 header followed by the smallest SID */
3450 if ((*pbuflen < sizeof(struct cifs_ntsd) + 8) ||
3451 (*pbuflen >= 64 * 1024)) {
3452 cERROR(1, "bad acl length %d", *pbuflen);
3456 *acl_inf = kmalloc(*pbuflen, GFP_KERNEL);
3457 if (*acl_inf == NULL) {
3461 memcpy(*acl_inf, pdata, *pbuflen);
3465 if (buf_type == CIFS_SMALL_BUFFER)
3466 cifs_small_buf_release(iov[0].iov_base);
3467 else if (buf_type == CIFS_LARGE_BUFFER)
3468 cifs_buf_release(iov[0].iov_base);
3469 /* cifs_small_buf_release(pSMB); */ /* Freed earlier now in SendReceive2 */
3474 CIFSSMBSetCIFSACL(const int xid, struct cifsTconInfo *tcon, __u16 fid,
3475 struct cifs_ntsd *pntsd, __u32 acllen)
3477 __u16 byte_count, param_count, data_count, param_offset, data_offset;
3479 int bytes_returned = 0;
3480 SET_SEC_DESC_REQ *pSMB = NULL;
3481 NTRANSACT_RSP *pSMBr = NULL;
3484 rc = smb_init(SMB_COM_NT_TRANSACT, 19, tcon, (void **) &pSMB,
3489 pSMB->MaxSetupCount = 0;
3493 param_offset = offsetof(struct smb_com_transaction_ssec_req, Fid) - 4;
3494 data_count = acllen;
3495 data_offset = param_offset + param_count;
3496 byte_count = 3 /* pad */ + param_count;
3498 pSMB->DataCount = cpu_to_le32(data_count);
3499 pSMB->TotalDataCount = pSMB->DataCount;
3500 pSMB->MaxParameterCount = cpu_to_le32(4);
3501 pSMB->MaxDataCount = cpu_to_le32(16384);
3502 pSMB->ParameterCount = cpu_to_le32(param_count);
3503 pSMB->ParameterOffset = cpu_to_le32(param_offset);
3504 pSMB->TotalParameterCount = pSMB->ParameterCount;
3505 pSMB->DataOffset = cpu_to_le32(data_offset);
3506 pSMB->SetupCount = 0;
3507 pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_SET_SECURITY_DESC);
3508 pSMB->ByteCount = cpu_to_le16(byte_count+data_count);
3510 pSMB->Fid = fid; /* file handle always le */
3511 pSMB->Reserved2 = 0;
3512 pSMB->AclFlags = cpu_to_le32(CIFS_ACL_DACL);
3514 if (pntsd && acllen) {
3515 memcpy((char *) &pSMBr->hdr.Protocol + data_offset,
3518 inc_rfc1001_len(pSMB, byte_count + data_count);
3520 inc_rfc1001_len(pSMB, byte_count);
3522 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3523 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3525 cFYI(1, "SetCIFSACL bytes_returned: %d, rc: %d", bytes_returned, rc);
3527 cFYI(1, "Set CIFS ACL returned %d", rc);
3528 cifs_buf_release(pSMB);
3531 goto setCifsAclRetry;
3536 #endif /* CONFIG_CIFS_ACL */
3538 /* Legacy Query Path Information call for lookup to old servers such
3540 int SMBQueryInformation(const int xid, struct cifsTconInfo *tcon,
3541 const unsigned char *searchName,
3542 FILE_ALL_INFO *pFinfo,
3543 const struct nls_table *nls_codepage, int remap)
3545 QUERY_INFORMATION_REQ *pSMB;
3546 QUERY_INFORMATION_RSP *pSMBr;
3551 cFYI(1, "In SMBQPath path %s", searchName);
3553 rc = smb_init(SMB_COM_QUERY_INFORMATION, 0, tcon, (void **) &pSMB,
3558 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3560 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
3561 PATH_MAX, nls_codepage, remap);
3562 name_len++; /* trailing null */
3565 name_len = strnlen(searchName, PATH_MAX);
3566 name_len++; /* trailing null */
3567 strncpy(pSMB->FileName, searchName, name_len);
3569 pSMB->BufferFormat = 0x04;
3570 name_len++; /* account for buffer type byte */
3571 inc_rfc1001_len(pSMB, (__u16)name_len);
3572 pSMB->ByteCount = cpu_to_le16(name_len);
3574 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3575 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3577 cFYI(1, "Send error in QueryInfo = %d", rc);
3578 } else if (pFinfo) {
3580 __u32 time = le32_to_cpu(pSMBr->last_write_time);
3582 /* decode response */
3583 /* BB FIXME - add time zone adjustment BB */
3584 memset(pFinfo, 0, sizeof(FILE_ALL_INFO));
3587 /* decode time fields */
3588 pFinfo->ChangeTime = cpu_to_le64(cifs_UnixTimeToNT(ts));
3589 pFinfo->LastWriteTime = pFinfo->ChangeTime;
3590 pFinfo->LastAccessTime = 0;
3591 pFinfo->AllocationSize =
3592 cpu_to_le64(le32_to_cpu(pSMBr->size));
3593 pFinfo->EndOfFile = pFinfo->AllocationSize;
3594 pFinfo->Attributes =
3595 cpu_to_le32(le16_to_cpu(pSMBr->attr));
3597 rc = -EIO; /* bad buffer passed in */
3599 cifs_buf_release(pSMB);
3608 CIFSSMBQFileInfo(const int xid, struct cifsTconInfo *tcon,
3609 u16 netfid, FILE_ALL_INFO *pFindData)
3611 struct smb_t2_qfi_req *pSMB = NULL;
3612 struct smb_t2_qfi_rsp *pSMBr = NULL;
3615 __u16 params, byte_count;
3618 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3623 params = 2 /* level */ + 2 /* fid */;
3624 pSMB->t2.TotalDataCount = 0;
3625 pSMB->t2.MaxParameterCount = cpu_to_le16(4);
3626 /* BB find exact max data count below from sess structure BB */
3627 pSMB->t2.MaxDataCount = cpu_to_le16(CIFSMaxBufSize);
3628 pSMB->t2.MaxSetupCount = 0;
3629 pSMB->t2.Reserved = 0;
3631 pSMB->t2.Timeout = 0;
3632 pSMB->t2.Reserved2 = 0;
3633 pSMB->t2.ParameterOffset = cpu_to_le16(offsetof(struct smb_t2_qfi_req,
3635 pSMB->t2.DataCount = 0;
3636 pSMB->t2.DataOffset = 0;
3637 pSMB->t2.SetupCount = 1;
3638 pSMB->t2.Reserved3 = 0;
3639 pSMB->t2.SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION);
3640 byte_count = params + 1 /* pad */ ;
3641 pSMB->t2.TotalParameterCount = cpu_to_le16(params);
3642 pSMB->t2.ParameterCount = pSMB->t2.TotalParameterCount;
3643 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_ALL_INFO);
3646 inc_rfc1001_len(pSMB, byte_count);
3648 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3649 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3651 cFYI(1, "Send error in QPathInfo = %d", rc);
3652 } else { /* decode response */
3653 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3655 if (rc) /* BB add auto retry on EOPNOTSUPP? */
3657 else if (get_bcc(&pSMBr->hdr) < 40)
3658 rc = -EIO; /* bad smb */
3659 else if (pFindData) {
3660 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3661 memcpy((char *) pFindData,
3662 (char *) &pSMBr->hdr.Protocol +
3663 data_offset, sizeof(FILE_ALL_INFO));
3667 cifs_buf_release(pSMB);
3669 goto QFileInfoRetry;
3675 CIFSSMBQPathInfo(const int xid, struct cifsTconInfo *tcon,
3676 const unsigned char *searchName,
3677 FILE_ALL_INFO *pFindData,
3678 int legacy /* old style infolevel */,
3679 const struct nls_table *nls_codepage, int remap)
3681 /* level 263 SMB_QUERY_FILE_ALL_INFO */
3682 TRANSACTION2_QPI_REQ *pSMB = NULL;
3683 TRANSACTION2_QPI_RSP *pSMBr = NULL;
3687 __u16 params, byte_count;
3689 /* cFYI(1, "In QPathInfo path %s", searchName); */
3691 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3696 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3698 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
3699 PATH_MAX, nls_codepage, remap);
3700 name_len++; /* trailing null */
3702 } else { /* BB improve the check for buffer overruns BB */
3703 name_len = strnlen(searchName, PATH_MAX);
3704 name_len++; /* trailing null */
3705 strncpy(pSMB->FileName, searchName, name_len);
3708 params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */;
3709 pSMB->TotalDataCount = 0;
3710 pSMB->MaxParameterCount = cpu_to_le16(2);
3711 /* BB find exact max SMB PDU from sess structure BB */
3712 pSMB->MaxDataCount = cpu_to_le16(4000);
3713 pSMB->MaxSetupCount = 0;
3717 pSMB->Reserved2 = 0;
3718 pSMB->ParameterOffset = cpu_to_le16(offsetof(
3719 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
3720 pSMB->DataCount = 0;
3721 pSMB->DataOffset = 0;
3722 pSMB->SetupCount = 1;
3723 pSMB->Reserved3 = 0;
3724 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
3725 byte_count = params + 1 /* pad */ ;
3726 pSMB->TotalParameterCount = cpu_to_le16(params);
3727 pSMB->ParameterCount = pSMB->TotalParameterCount;
3729 pSMB->InformationLevel = cpu_to_le16(SMB_INFO_STANDARD);
3731 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_ALL_INFO);
3732 pSMB->Reserved4 = 0;
3733 inc_rfc1001_len(pSMB, byte_count);
3734 pSMB->ByteCount = cpu_to_le16(byte_count);
3736 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3737 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3739 cFYI(1, "Send error in QPathInfo = %d", rc);
3740 } else { /* decode response */
3741 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3743 if (rc) /* BB add auto retry on EOPNOTSUPP? */
3745 else if (!legacy && get_bcc(&pSMBr->hdr) < 40)
3746 rc = -EIO; /* bad smb */
3747 else if (legacy && get_bcc(&pSMBr->hdr) < 24)
3748 rc = -EIO; /* 24 or 26 expected but we do not read
3750 else if (pFindData) {
3752 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3754 /* On legacy responses we do not read the last field,
3755 EAsize, fortunately since it varies by subdialect and
3756 also note it differs on Set vs. Get, ie two bytes or 4
3757 bytes depending but we don't care here */
3759 size = sizeof(FILE_INFO_STANDARD);
3761 size = sizeof(FILE_ALL_INFO);
3762 memcpy((char *) pFindData,
3763 (char *) &pSMBr->hdr.Protocol +
3768 cifs_buf_release(pSMB);
3770 goto QPathInfoRetry;
3776 CIFSSMBUnixQFileInfo(const int xid, struct cifsTconInfo *tcon,
3777 u16 netfid, FILE_UNIX_BASIC_INFO *pFindData)
3779 struct smb_t2_qfi_req *pSMB = NULL;
3780 struct smb_t2_qfi_rsp *pSMBr = NULL;
3783 __u16 params, byte_count;
3786 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3791 params = 2 /* level */ + 2 /* fid */;
3792 pSMB->t2.TotalDataCount = 0;
3793 pSMB->t2.MaxParameterCount = cpu_to_le16(4);
3794 /* BB find exact max data count below from sess structure BB */
3795 pSMB->t2.MaxDataCount = cpu_to_le16(CIFSMaxBufSize);
3796 pSMB->t2.MaxSetupCount = 0;
3797 pSMB->t2.Reserved = 0;
3799 pSMB->t2.Timeout = 0;
3800 pSMB->t2.Reserved2 = 0;
3801 pSMB->t2.ParameterOffset = cpu_to_le16(offsetof(struct smb_t2_qfi_req,
3803 pSMB->t2.DataCount = 0;
3804 pSMB->t2.DataOffset = 0;
3805 pSMB->t2.SetupCount = 1;
3806 pSMB->t2.Reserved3 = 0;
3807 pSMB->t2.SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION);
3808 byte_count = params + 1 /* pad */ ;
3809 pSMB->t2.TotalParameterCount = cpu_to_le16(params);
3810 pSMB->t2.ParameterCount = pSMB->t2.TotalParameterCount;
3811 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC);
3814 inc_rfc1001_len(pSMB, byte_count);
3816 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3817 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3819 cFYI(1, "Send error in QPathInfo = %d", rc);
3820 } else { /* decode response */
3821 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3823 if (rc || get_bcc(&pSMBr->hdr) < sizeof(FILE_UNIX_BASIC_INFO)) {
3824 cERROR(1, "Malformed FILE_UNIX_BASIC_INFO response.\n"
3825 "Unix Extensions can be disabled on mount "
3826 "by specifying the nosfu mount option.");
3827 rc = -EIO; /* bad smb */
3829 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3830 memcpy((char *) pFindData,
3831 (char *) &pSMBr->hdr.Protocol +
3833 sizeof(FILE_UNIX_BASIC_INFO));
3837 cifs_buf_release(pSMB);
3839 goto UnixQFileInfoRetry;
3845 CIFSSMBUnixQPathInfo(const int xid, struct cifsTconInfo *tcon,
3846 const unsigned char *searchName,
3847 FILE_UNIX_BASIC_INFO *pFindData,
3848 const struct nls_table *nls_codepage, int remap)
3850 /* SMB_QUERY_FILE_UNIX_BASIC */
3851 TRANSACTION2_QPI_REQ *pSMB = NULL;
3852 TRANSACTION2_QPI_RSP *pSMBr = NULL;
3854 int bytes_returned = 0;
3856 __u16 params, byte_count;
3858 cFYI(1, "In QPathInfo (Unix) the path %s", searchName);
3860 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3865 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3867 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
3868 PATH_MAX, nls_codepage, remap);
3869 name_len++; /* trailing null */
3871 } else { /* BB improve the check for buffer overruns BB */
3872 name_len = strnlen(searchName, PATH_MAX);
3873 name_len++; /* trailing null */
3874 strncpy(pSMB->FileName, searchName, name_len);
3877 params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */;
3878 pSMB->TotalDataCount = 0;
3879 pSMB->MaxParameterCount = cpu_to_le16(2);
3880 /* BB find exact max SMB PDU from sess structure BB */
3881 pSMB->MaxDataCount = cpu_to_le16(4000);
3882 pSMB->MaxSetupCount = 0;
3886 pSMB->Reserved2 = 0;
3887 pSMB->ParameterOffset = cpu_to_le16(offsetof(
3888 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
3889 pSMB->DataCount = 0;
3890 pSMB->DataOffset = 0;
3891 pSMB->SetupCount = 1;
3892 pSMB->Reserved3 = 0;
3893 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
3894 byte_count = params + 1 /* pad */ ;
3895 pSMB->TotalParameterCount = cpu_to_le16(params);
3896 pSMB->ParameterCount = pSMB->TotalParameterCount;
3897 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC);
3898 pSMB->Reserved4 = 0;
3899 inc_rfc1001_len(pSMB, byte_count);
3900 pSMB->ByteCount = cpu_to_le16(byte_count);
3902 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3903 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3905 cFYI(1, "Send error in QPathInfo = %d", rc);
3906 } else { /* decode response */
3907 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3909 if (rc || get_bcc(&pSMBr->hdr) < sizeof(FILE_UNIX_BASIC_INFO)) {
3910 cERROR(1, "Malformed FILE_UNIX_BASIC_INFO response.\n"
3911 "Unix Extensions can be disabled on mount "
3912 "by specifying the nosfu mount option.");
3913 rc = -EIO; /* bad smb */
3915 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3916 memcpy((char *) pFindData,
3917 (char *) &pSMBr->hdr.Protocol +
3919 sizeof(FILE_UNIX_BASIC_INFO));
3922 cifs_buf_release(pSMB);
3924 goto UnixQPathInfoRetry;
3929 /* xid, tcon, searchName and codepage are input parms, rest are returned */
3931 CIFSFindFirst(const int xid, struct cifsTconInfo *tcon,
3932 const char *searchName,
3933 const struct nls_table *nls_codepage,
3935 struct cifs_search_info *psrch_inf, int remap, const char dirsep)
3937 /* level 257 SMB_ */
3938 TRANSACTION2_FFIRST_REQ *pSMB = NULL;
3939 TRANSACTION2_FFIRST_RSP *pSMBr = NULL;
3940 T2_FFIRST_RSP_PARMS *parms;
3942 int bytes_returned = 0;
3944 __u16 params, byte_count;
3946 cFYI(1, "In FindFirst for %s", searchName);
3949 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3954 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3956 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
3957 PATH_MAX, nls_codepage, remap);
3958 /* We can not add the asterik earlier in case
3959 it got remapped to 0xF03A as if it were part of the
3960 directory name instead of a wildcard */
3962 pSMB->FileName[name_len] = dirsep;
3963 pSMB->FileName[name_len+1] = 0;
3964 pSMB->FileName[name_len+2] = '*';
3965 pSMB->FileName[name_len+3] = 0;
3966 name_len += 4; /* now the trailing null */
3967 pSMB->FileName[name_len] = 0; /* null terminate just in case */
3968 pSMB->FileName[name_len+1] = 0;
3970 } else { /* BB add check for overrun of SMB buf BB */
3971 name_len = strnlen(searchName, PATH_MAX);
3972 /* BB fix here and in unicode clause above ie
3973 if (name_len > buffersize-header)
3974 free buffer exit; BB */
3975 strncpy(pSMB->FileName, searchName, name_len);
3976 pSMB->FileName[name_len] = dirsep;
3977 pSMB->FileName[name_len+1] = '*';
3978 pSMB->FileName[name_len+2] = 0;
3982 params = 12 + name_len /* includes null */ ;
3983 pSMB->TotalDataCount = 0; /* no EAs */
3984 pSMB->MaxParameterCount = cpu_to_le16(10);
3985 pSMB->MaxDataCount = cpu_to_le16((tcon->ses->server->maxBuf -
3986 MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
3987 pSMB->MaxSetupCount = 0;
3991 pSMB->Reserved2 = 0;
3992 byte_count = params + 1 /* pad */ ;
3993 pSMB->TotalParameterCount = cpu_to_le16(params);
3994 pSMB->ParameterCount = pSMB->TotalParameterCount;
3995 pSMB->ParameterOffset = cpu_to_le16(
3996 offsetof(struct smb_com_transaction2_ffirst_req, SearchAttributes)
3998 pSMB->DataCount = 0;
3999 pSMB->DataOffset = 0;
4000 pSMB->SetupCount = 1; /* one byte, no need to make endian neutral */
4001 pSMB->Reserved3 = 0;
4002 pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_FIRST);
4003 pSMB->SearchAttributes =
4004 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
4006 pSMB->SearchCount = cpu_to_le16(CIFSMaxBufSize/sizeof(FILE_UNIX_INFO));
4007 pSMB->SearchFlags = cpu_to_le16(CIFS_SEARCH_CLOSE_AT_END |
4008 CIFS_SEARCH_RETURN_RESUME);
4009 pSMB->InformationLevel = cpu_to_le16(psrch_inf->info_level);
4011 /* BB what should we set StorageType to? Does it matter? BB */
4012 pSMB->SearchStorageType = 0;
4013 inc_rfc1001_len(pSMB, byte_count);
4014 pSMB->ByteCount = cpu_to_le16(byte_count);
4016 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4017 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4018 cifs_stats_inc(&tcon->num_ffirst);
4020 if (rc) {/* BB add logic to retry regular search if Unix search
4021 rejected unexpectedly by server */
4022 /* BB Add code to handle unsupported level rc */
4023 cFYI(1, "Error in FindFirst = %d", rc);
4025 cifs_buf_release(pSMB);
4027 /* BB eventually could optimize out free and realloc of buf */
4030 goto findFirstRetry;
4031 } else { /* decode response */
4032 /* BB remember to free buffer if error BB */
4033 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4037 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
4038 psrch_inf->unicode = true;
4040 psrch_inf->unicode = false;
4042 psrch_inf->ntwrk_buf_start = (char *)pSMBr;
4043 psrch_inf->smallBuf = 0;
4044 psrch_inf->srch_entries_start =
4045 (char *) &pSMBr->hdr.Protocol +
4046 le16_to_cpu(pSMBr->t2.DataOffset);
4047 parms = (T2_FFIRST_RSP_PARMS *)((char *) &pSMBr->hdr.Protocol +
4048 le16_to_cpu(pSMBr->t2.ParameterOffset));
4050 if (parms->EndofSearch)
4051 psrch_inf->endOfSearch = true;
4053 psrch_inf->endOfSearch = false;
4055 psrch_inf->entries_in_buffer =
4056 le16_to_cpu(parms->SearchCount);
4057 psrch_inf->index_of_last_entry = 2 /* skip . and .. */ +
4058 psrch_inf->entries_in_buffer;
4059 lnoff = le16_to_cpu(parms->LastNameOffset);
4060 if (tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE <
4062 cERROR(1, "ignoring corrupt resume name");
4063 psrch_inf->last_entry = NULL;
4067 psrch_inf->last_entry = psrch_inf->srch_entries_start +
4070 *pnetfid = parms->SearchHandle;
4072 cifs_buf_release(pSMB);
4079 int CIFSFindNext(const int xid, struct cifsTconInfo *tcon,
4080 __u16 searchHandle, struct cifs_search_info *psrch_inf)
4082 TRANSACTION2_FNEXT_REQ *pSMB = NULL;
4083 TRANSACTION2_FNEXT_RSP *pSMBr = NULL;
4084 T2_FNEXT_RSP_PARMS *parms;
4085 char *response_data;
4087 int bytes_returned, name_len;
4088 __u16 params, byte_count;
4090 cFYI(1, "In FindNext");
4092 if (psrch_inf->endOfSearch)
4095 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4100 params = 14; /* includes 2 bytes of null string, converted to LE below*/
4102 pSMB->TotalDataCount = 0; /* no EAs */
4103 pSMB->MaxParameterCount = cpu_to_le16(8);
4104 pSMB->MaxDataCount =
4105 cpu_to_le16((tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE) &
4107 pSMB->MaxSetupCount = 0;
4111 pSMB->Reserved2 = 0;
4112 pSMB->ParameterOffset = cpu_to_le16(
4113 offsetof(struct smb_com_transaction2_fnext_req,SearchHandle) - 4);
4114 pSMB->DataCount = 0;
4115 pSMB->DataOffset = 0;
4116 pSMB->SetupCount = 1;
4117 pSMB->Reserved3 = 0;
4118 pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_NEXT);
4119 pSMB->SearchHandle = searchHandle; /* always kept as le */
4121 cpu_to_le16(CIFSMaxBufSize / sizeof(FILE_UNIX_INFO));
4122 pSMB->InformationLevel = cpu_to_le16(psrch_inf->info_level);
4123 pSMB->ResumeKey = psrch_inf->resume_key;
4125 cpu_to_le16(CIFS_SEARCH_CLOSE_AT_END | CIFS_SEARCH_RETURN_RESUME);
4127 name_len = psrch_inf->resume_name_len;
4129 if (name_len < PATH_MAX) {
4130 memcpy(pSMB->ResumeFileName, psrch_inf->presume_name, name_len);
4131 byte_count += name_len;
4132 /* 14 byte parm len above enough for 2 byte null terminator */
4133 pSMB->ResumeFileName[name_len] = 0;
4134 pSMB->ResumeFileName[name_len+1] = 0;
4137 goto FNext2_err_exit;
4139 byte_count = params + 1 /* pad */ ;
4140 pSMB->TotalParameterCount = cpu_to_le16(params);
4141 pSMB->ParameterCount = pSMB->TotalParameterCount;
4142 inc_rfc1001_len(pSMB, byte_count);
4143 pSMB->ByteCount = cpu_to_le16(byte_count);
4145 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4146 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4147 cifs_stats_inc(&tcon->num_fnext);
4150 psrch_inf->endOfSearch = true;
4151 cifs_buf_release(pSMB);
4152 rc = 0; /* search probably was closed at end of search*/
4154 cFYI(1, "FindNext returned = %d", rc);
4155 } else { /* decode response */
4156 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4161 /* BB fixme add lock for file (srch_info) struct here */
4162 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
4163 psrch_inf->unicode = true;
4165 psrch_inf->unicode = false;
4166 response_data = (char *) &pSMBr->hdr.Protocol +
4167 le16_to_cpu(pSMBr->t2.ParameterOffset);
4168 parms = (T2_FNEXT_RSP_PARMS *)response_data;
4169 response_data = (char *)&pSMBr->hdr.Protocol +
4170 le16_to_cpu(pSMBr->t2.DataOffset);
4171 if (psrch_inf->smallBuf)
4172 cifs_small_buf_release(
4173 psrch_inf->ntwrk_buf_start);
4175 cifs_buf_release(psrch_inf->ntwrk_buf_start);
4176 psrch_inf->srch_entries_start = response_data;
4177 psrch_inf->ntwrk_buf_start = (char *)pSMB;
4178 psrch_inf->smallBuf = 0;
4179 if (parms->EndofSearch)
4180 psrch_inf->endOfSearch = true;
4182 psrch_inf->endOfSearch = false;
4183 psrch_inf->entries_in_buffer =
4184 le16_to_cpu(parms->SearchCount);
4185 psrch_inf->index_of_last_entry +=
4186 psrch_inf->entries_in_buffer;
4187 lnoff = le16_to_cpu(parms->LastNameOffset);
4188 if (tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE <
4190 cERROR(1, "ignoring corrupt resume name");
4191 psrch_inf->last_entry = NULL;
4194 psrch_inf->last_entry =
4195 psrch_inf->srch_entries_start + lnoff;
4197 /* cFYI(1, "fnxt2 entries in buf %d index_of_last %d",
4198 psrch_inf->entries_in_buffer, psrch_inf->index_of_last_entry); */
4200 /* BB fixme add unlock here */
4205 /* BB On error, should we leave previous search buf (and count and
4206 last entry fields) intact or free the previous one? */
4208 /* Note: On -EAGAIN error only caller can retry on handle based calls
4209 since file handle passed in no longer valid */
4212 cifs_buf_release(pSMB);
4217 CIFSFindClose(const int xid, struct cifsTconInfo *tcon,
4218 const __u16 searchHandle)
4221 FINDCLOSE_REQ *pSMB = NULL;
4223 cFYI(1, "In CIFSSMBFindClose");
4224 rc = small_smb_init(SMB_COM_FIND_CLOSE2, 1, tcon, (void **)&pSMB);
4226 /* no sense returning error if session restarted
4227 as file handle has been closed */
4233 pSMB->FileID = searchHandle;
4234 pSMB->ByteCount = 0;
4235 rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0);
4237 cERROR(1, "Send error in FindClose = %d", rc);
4239 cifs_stats_inc(&tcon->num_fclose);
4241 /* Since session is dead, search handle closed on server already */
4249 CIFSGetSrvInodeNumber(const int xid, struct cifsTconInfo *tcon,
4250 const unsigned char *searchName,
4251 __u64 *inode_number,
4252 const struct nls_table *nls_codepage, int remap)
4255 TRANSACTION2_QPI_REQ *pSMB = NULL;
4256 TRANSACTION2_QPI_RSP *pSMBr = NULL;
4257 int name_len, bytes_returned;
4258 __u16 params, byte_count;
4260 cFYI(1, "In GetSrvInodeNum for %s", searchName);
4264 GetInodeNumberRetry:
4265 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4270 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4272 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
4273 PATH_MAX, nls_codepage, remap);
4274 name_len++; /* trailing null */
4276 } else { /* BB improve the check for buffer overruns BB */
4277 name_len = strnlen(searchName, PATH_MAX);
4278 name_len++; /* trailing null */
4279 strncpy(pSMB->FileName, searchName, name_len);
4282 params = 2 /* level */ + 4 /* rsrvd */ + name_len /* incl null */ ;
4283 pSMB->TotalDataCount = 0;
4284 pSMB->MaxParameterCount = cpu_to_le16(2);
4285 /* BB find exact max data count below from sess structure BB */
4286 pSMB->MaxDataCount = cpu_to_le16(4000);
4287 pSMB->MaxSetupCount = 0;
4291 pSMB->Reserved2 = 0;
4292 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4293 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
4294 pSMB->DataCount = 0;
4295 pSMB->DataOffset = 0;
4296 pSMB->SetupCount = 1;
4297 pSMB->Reserved3 = 0;
4298 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
4299 byte_count = params + 1 /* pad */ ;
4300 pSMB->TotalParameterCount = cpu_to_le16(params);
4301 pSMB->ParameterCount = pSMB->TotalParameterCount;
4302 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_INTERNAL_INFO);
4303 pSMB->Reserved4 = 0;
4304 inc_rfc1001_len(pSMB, byte_count);
4305 pSMB->ByteCount = cpu_to_le16(byte_count);
4307 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4308 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4310 cFYI(1, "error %d in QueryInternalInfo", rc);
4312 /* decode response */
4313 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4314 /* BB also check enough total bytes returned */
4315 if (rc || get_bcc(&pSMBr->hdr) < 2)
4316 /* If rc should we check for EOPNOSUPP and
4317 disable the srvino flag? or in caller? */
4318 rc = -EIO; /* bad smb */
4320 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4321 __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
4322 struct file_internal_info *pfinfo;
4323 /* BB Do we need a cast or hash here ? */
4325 cFYI(1, "Illegal size ret in QryIntrnlInf");
4327 goto GetInodeNumOut;
4329 pfinfo = (struct file_internal_info *)
4330 (data_offset + (char *) &pSMBr->hdr.Protocol);
4331 *inode_number = le64_to_cpu(pfinfo->UniqueId);
4335 cifs_buf_release(pSMB);
4337 goto GetInodeNumberRetry;
4341 /* parses DFS refferal V3 structure
4342 * caller is responsible for freeing target_nodes
4345 * on failure - errno
4348 parse_DFS_referrals(TRANSACTION2_GET_DFS_REFER_RSP *pSMBr,
4349 unsigned int *num_of_nodes,
4350 struct dfs_info3_param **target_nodes,
4351 const struct nls_table *nls_codepage, int remap,
4352 const char *searchName)
4357 struct dfs_referral_level_3 *ref;
4359 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
4363 *num_of_nodes = le16_to_cpu(pSMBr->NumberOfReferrals);
4365 if (*num_of_nodes < 1) {
4366 cERROR(1, "num_referrals: must be at least > 0,"
4367 "but we get num_referrals = %d\n", *num_of_nodes);
4369 goto parse_DFS_referrals_exit;
4372 ref = (struct dfs_referral_level_3 *) &(pSMBr->referrals);
4373 if (ref->VersionNumber != cpu_to_le16(3)) {
4374 cERROR(1, "Referrals of V%d version are not supported,"
4375 "should be V3", le16_to_cpu(ref->VersionNumber));
4377 goto parse_DFS_referrals_exit;
4380 /* get the upper boundary of the resp buffer */
4381 data_end = (char *)(&(pSMBr->PathConsumed)) +
4382 le16_to_cpu(pSMBr->t2.DataCount);
4384 cFYI(1, "num_referrals: %d dfs flags: 0x%x ...\n",
4386 le32_to_cpu(pSMBr->DFSFlags));
4388 *target_nodes = kzalloc(sizeof(struct dfs_info3_param) *
4389 *num_of_nodes, GFP_KERNEL);
4390 if (*target_nodes == NULL) {
4391 cERROR(1, "Failed to allocate buffer for target_nodes\n");
4393 goto parse_DFS_referrals_exit;
4396 /* collect necessary data from referrals */
4397 for (i = 0; i < *num_of_nodes; i++) {
4400 struct dfs_info3_param *node = (*target_nodes)+i;
4402 node->flags = le32_to_cpu(pSMBr->DFSFlags);
4404 __le16 *tmp = kmalloc(strlen(searchName)*2 + 2,
4408 goto parse_DFS_referrals_exit;
4410 cifsConvertToUCS((__le16 *) tmp, searchName,
4411 PATH_MAX, nls_codepage, remap);
4412 node->path_consumed = cifs_ucs2_bytes(tmp,
4413 le16_to_cpu(pSMBr->PathConsumed),
4417 node->path_consumed = le16_to_cpu(pSMBr->PathConsumed);
4419 node->server_type = le16_to_cpu(ref->ServerType);
4420 node->ref_flag = le16_to_cpu(ref->ReferralEntryFlags);
4423 temp = (char *)ref + le16_to_cpu(ref->DfsPathOffset);
4424 max_len = data_end - temp;
4425 node->path_name = cifs_strndup_from_ucs(temp, max_len,
4426 is_unicode, nls_codepage);
4427 if (!node->path_name) {
4429 goto parse_DFS_referrals_exit;
4432 /* copy link target UNC */
4433 temp = (char *)ref + le16_to_cpu(ref->NetworkAddressOffset);
4434 max_len = data_end - temp;
4435 node->node_name = cifs_strndup_from_ucs(temp, max_len,
4436 is_unicode, nls_codepage);
4437 if (!node->node_name)
4441 parse_DFS_referrals_exit:
4443 free_dfs_info_array(*target_nodes, *num_of_nodes);
4444 *target_nodes = NULL;
4451 CIFSGetDFSRefer(const int xid, struct cifsSesInfo *ses,
4452 const unsigned char *searchName,
4453 struct dfs_info3_param **target_nodes,
4454 unsigned int *num_of_nodes,
4455 const struct nls_table *nls_codepage, int remap)
4457 /* TRANS2_GET_DFS_REFERRAL */
4458 TRANSACTION2_GET_DFS_REFER_REQ *pSMB = NULL;
4459 TRANSACTION2_GET_DFS_REFER_RSP *pSMBr = NULL;
4463 __u16 params, byte_count;
4465 *target_nodes = NULL;
4467 cFYI(1, "In GetDFSRefer the path %s", searchName);
4471 rc = smb_init(SMB_COM_TRANSACTION2, 15, NULL, (void **) &pSMB,
4476 /* server pointer checked in called function,
4477 but should never be null here anyway */
4478 pSMB->hdr.Mid = GetNextMid(ses->server);
4479 pSMB->hdr.Tid = ses->ipc_tid;
4480 pSMB->hdr.Uid = ses->Suid;
4481 if (ses->capabilities & CAP_STATUS32)
4482 pSMB->hdr.Flags2 |= SMBFLG2_ERR_STATUS;
4483 if (ses->capabilities & CAP_DFS)
4484 pSMB->hdr.Flags2 |= SMBFLG2_DFS;
4486 if (ses->capabilities & CAP_UNICODE) {
4487 pSMB->hdr.Flags2 |= SMBFLG2_UNICODE;
4489 cifsConvertToUCS((__le16 *) pSMB->RequestFileName,
4490 searchName, PATH_MAX, nls_codepage, remap);
4491 name_len++; /* trailing null */
4493 } else { /* BB improve the check for buffer overruns BB */
4494 name_len = strnlen(searchName, PATH_MAX);
4495 name_len++; /* trailing null */
4496 strncpy(pSMB->RequestFileName, searchName, name_len);
4500 if (ses->server->secMode &
4501 (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
4502 pSMB->hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
4505 pSMB->hdr.Uid = ses->Suid;
4507 params = 2 /* level */ + name_len /*includes null */ ;
4508 pSMB->TotalDataCount = 0;
4509 pSMB->DataCount = 0;
4510 pSMB->DataOffset = 0;
4511 pSMB->MaxParameterCount = 0;
4512 /* BB find exact max SMB PDU from sess structure BB */
4513 pSMB->MaxDataCount = cpu_to_le16(4000);
4514 pSMB->MaxSetupCount = 0;
4518 pSMB->Reserved2 = 0;
4519 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4520 struct smb_com_transaction2_get_dfs_refer_req, MaxReferralLevel) - 4);
4521 pSMB->SetupCount = 1;
4522 pSMB->Reserved3 = 0;
4523 pSMB->SubCommand = cpu_to_le16(TRANS2_GET_DFS_REFERRAL);
4524 byte_count = params + 3 /* pad */ ;
4525 pSMB->ParameterCount = cpu_to_le16(params);
4526 pSMB->TotalParameterCount = pSMB->ParameterCount;
4527 pSMB->MaxReferralLevel = cpu_to_le16(3);
4528 inc_rfc1001_len(pSMB, byte_count);
4529 pSMB->ByteCount = cpu_to_le16(byte_count);
4531 rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB,
4532 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4534 cFYI(1, "Send error in GetDFSRefer = %d", rc);
4537 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4539 /* BB Also check if enough total bytes returned? */
4540 if (rc || get_bcc(&pSMBr->hdr) < 17) {
4541 rc = -EIO; /* bad smb */
4545 cFYI(1, "Decoding GetDFSRefer response BCC: %d Offset %d",
4546 get_bcc(&pSMBr->hdr),
4547 le16_to_cpu(pSMBr->t2.DataOffset));
4549 /* parse returned result into more usable form */
4550 rc = parse_DFS_referrals(pSMBr, num_of_nodes,
4551 target_nodes, nls_codepage, remap,
4555 cifs_buf_release(pSMB);
4563 /* Query File System Info such as free space to old servers such as Win 9x */
4565 SMBOldQFSInfo(const int xid, struct cifsTconInfo *tcon, struct kstatfs *FSData)
4567 /* level 0x01 SMB_QUERY_FILE_SYSTEM_INFO */
4568 TRANSACTION2_QFSI_REQ *pSMB = NULL;
4569 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4570 FILE_SYSTEM_ALLOC_INFO *response_data;
4572 int bytes_returned = 0;
4573 __u16 params, byte_count;
4575 cFYI(1, "OldQFSInfo");
4577 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4582 params = 2; /* level */
4583 pSMB->TotalDataCount = 0;
4584 pSMB->MaxParameterCount = cpu_to_le16(2);
4585 pSMB->MaxDataCount = cpu_to_le16(1000);
4586 pSMB->MaxSetupCount = 0;
4590 pSMB->Reserved2 = 0;
4591 byte_count = params + 1 /* pad */ ;
4592 pSMB->TotalParameterCount = cpu_to_le16(params);
4593 pSMB->ParameterCount = pSMB->TotalParameterCount;
4594 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4595 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4596 pSMB->DataCount = 0;
4597 pSMB->DataOffset = 0;
4598 pSMB->SetupCount = 1;
4599 pSMB->Reserved3 = 0;
4600 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4601 pSMB->InformationLevel = cpu_to_le16(SMB_INFO_ALLOCATION);
4602 inc_rfc1001_len(pSMB, byte_count);
4603 pSMB->ByteCount = cpu_to_le16(byte_count);
4605 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4606 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4608 cFYI(1, "Send error in QFSInfo = %d", rc);
4609 } else { /* decode response */
4610 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4612 if (rc || get_bcc(&pSMBr->hdr) < 18)
4613 rc = -EIO; /* bad smb */
4615 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4616 cFYI(1, "qfsinf resp BCC: %d Offset %d",
4617 get_bcc(&pSMBr->hdr), data_offset);
4619 response_data = (FILE_SYSTEM_ALLOC_INFO *)
4620 (((char *) &pSMBr->hdr.Protocol) + data_offset);
4622 le16_to_cpu(response_data->BytesPerSector) *
4623 le32_to_cpu(response_data->
4624 SectorsPerAllocationUnit);
4626 le32_to_cpu(response_data->TotalAllocationUnits);
4627 FSData->f_bfree = FSData->f_bavail =
4628 le32_to_cpu(response_data->FreeAllocationUnits);
4629 cFYI(1, "Blocks: %lld Free: %lld Block size %ld",
4630 (unsigned long long)FSData->f_blocks,
4631 (unsigned long long)FSData->f_bfree,
4635 cifs_buf_release(pSMB);
4638 goto oldQFSInfoRetry;
4644 CIFSSMBQFSInfo(const int xid, struct cifsTconInfo *tcon, struct kstatfs *FSData)
4646 /* level 0x103 SMB_QUERY_FILE_SYSTEM_INFO */
4647 TRANSACTION2_QFSI_REQ *pSMB = NULL;
4648 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4649 FILE_SYSTEM_INFO *response_data;
4651 int bytes_returned = 0;
4652 __u16 params, byte_count;
4654 cFYI(1, "In QFSInfo");
4656 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4661 params = 2; /* level */
4662 pSMB->TotalDataCount = 0;
4663 pSMB->MaxParameterCount = cpu_to_le16(2);
4664 pSMB->MaxDataCount = cpu_to_le16(1000);
4665 pSMB->MaxSetupCount = 0;
4669 pSMB->Reserved2 = 0;
4670 byte_count = params + 1 /* pad */ ;
4671 pSMB->TotalParameterCount = cpu_to_le16(params);
4672 pSMB->ParameterCount = pSMB->TotalParameterCount;
4673 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4674 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4675 pSMB->DataCount = 0;
4676 pSMB->DataOffset = 0;
4677 pSMB->SetupCount = 1;
4678 pSMB->Reserved3 = 0;
4679 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4680 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_SIZE_INFO);
4681 inc_rfc1001_len(pSMB, byte_count);
4682 pSMB->ByteCount = cpu_to_le16(byte_count);
4684 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4685 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4687 cFYI(1, "Send error in QFSInfo = %d", rc);
4688 } else { /* decode response */
4689 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4691 if (rc || get_bcc(&pSMBr->hdr) < 24)
4692 rc = -EIO; /* bad smb */
4694 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4698 *) (((char *) &pSMBr->hdr.Protocol) +
4701 le32_to_cpu(response_data->BytesPerSector) *
4702 le32_to_cpu(response_data->
4703 SectorsPerAllocationUnit);
4705 le64_to_cpu(response_data->TotalAllocationUnits);
4706 FSData->f_bfree = FSData->f_bavail =
4707 le64_to_cpu(response_data->FreeAllocationUnits);
4708 cFYI(1, "Blocks: %lld Free: %lld Block size %ld",
4709 (unsigned long long)FSData->f_blocks,
4710 (unsigned long long)FSData->f_bfree,
4714 cifs_buf_release(pSMB);
4723 CIFSSMBQFSAttributeInfo(const int xid, struct cifsTconInfo *tcon)
4725 /* level 0x105 SMB_QUERY_FILE_SYSTEM_INFO */
4726 TRANSACTION2_QFSI_REQ *pSMB = NULL;
4727 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4728 FILE_SYSTEM_ATTRIBUTE_INFO *response_data;
4730 int bytes_returned = 0;
4731 __u16 params, byte_count;
4733 cFYI(1, "In QFSAttributeInfo");
4735 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4740 params = 2; /* level */
4741 pSMB->TotalDataCount = 0;
4742 pSMB->MaxParameterCount = cpu_to_le16(2);
4743 /* BB find exact max SMB PDU from sess structure BB */
4744 pSMB->MaxDataCount = cpu_to_le16(1000);
4745 pSMB->MaxSetupCount = 0;
4749 pSMB->Reserved2 = 0;
4750 byte_count = params + 1 /* pad */ ;
4751 pSMB->TotalParameterCount = cpu_to_le16(params);
4752 pSMB->ParameterCount = pSMB->TotalParameterCount;
4753 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4754 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4755 pSMB->DataCount = 0;
4756 pSMB->DataOffset = 0;
4757 pSMB->SetupCount = 1;
4758 pSMB->Reserved3 = 0;
4759 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4760 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_ATTRIBUTE_INFO);
4761 inc_rfc1001_len(pSMB, byte_count);
4762 pSMB->ByteCount = cpu_to_le16(byte_count);
4764 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4765 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4767 cERROR(1, "Send error in QFSAttributeInfo = %d", rc);
4768 } else { /* decode response */
4769 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4771 if (rc || get_bcc(&pSMBr->hdr) < 13) {
4772 /* BB also check if enough bytes returned */
4773 rc = -EIO; /* bad smb */
4775 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4777 (FILE_SYSTEM_ATTRIBUTE_INFO
4778 *) (((char *) &pSMBr->hdr.Protocol) +
4780 memcpy(&tcon->fsAttrInfo, response_data,
4781 sizeof(FILE_SYSTEM_ATTRIBUTE_INFO));
4784 cifs_buf_release(pSMB);
4787 goto QFSAttributeRetry;
4793 CIFSSMBQFSDeviceInfo(const int xid, struct cifsTconInfo *tcon)
4795 /* level 0x104 SMB_QUERY_FILE_SYSTEM_INFO */
4796 TRANSACTION2_QFSI_REQ *pSMB = NULL;
4797 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4798 FILE_SYSTEM_DEVICE_INFO *response_data;
4800 int bytes_returned = 0;
4801 __u16 params, byte_count;
4803 cFYI(1, "In QFSDeviceInfo");
4805 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4810 params = 2; /* level */
4811 pSMB->TotalDataCount = 0;
4812 pSMB->MaxParameterCount = cpu_to_le16(2);
4813 /* BB find exact max SMB PDU from sess structure BB */
4814 pSMB->MaxDataCount = cpu_to_le16(1000);
4815 pSMB->MaxSetupCount = 0;
4819 pSMB->Reserved2 = 0;
4820 byte_count = params + 1 /* pad */ ;
4821 pSMB->TotalParameterCount = cpu_to_le16(params);
4822 pSMB->ParameterCount = pSMB->TotalParameterCount;
4823 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4824 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4826 pSMB->DataCount = 0;
4827 pSMB->DataOffset = 0;
4828 pSMB->SetupCount = 1;
4829 pSMB->Reserved3 = 0;
4830 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4831 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_DEVICE_INFO);
4832 inc_rfc1001_len(pSMB, byte_count);
4833 pSMB->ByteCount = cpu_to_le16(byte_count);
4835 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4836 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4838 cFYI(1, "Send error in QFSDeviceInfo = %d", rc);
4839 } else { /* decode response */
4840 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4842 if (rc || get_bcc(&pSMBr->hdr) <
4843 sizeof(FILE_SYSTEM_DEVICE_INFO))
4844 rc = -EIO; /* bad smb */
4846 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4848 (FILE_SYSTEM_DEVICE_INFO *)
4849 (((char *) &pSMBr->hdr.Protocol) +
4851 memcpy(&tcon->fsDevInfo, response_data,
4852 sizeof(FILE_SYSTEM_DEVICE_INFO));
4855 cifs_buf_release(pSMB);
4858 goto QFSDeviceRetry;
4864 CIFSSMBQFSUnixInfo(const int xid, struct cifsTconInfo *tcon)
4866 /* level 0x200 SMB_QUERY_CIFS_UNIX_INFO */
4867 TRANSACTION2_QFSI_REQ *pSMB = NULL;
4868 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4869 FILE_SYSTEM_UNIX_INFO *response_data;
4871 int bytes_returned = 0;
4872 __u16 params, byte_count;
4874 cFYI(1, "In QFSUnixInfo");
4876 rc = smb_init_no_reconnect(SMB_COM_TRANSACTION2, 15, tcon,
4877 (void **) &pSMB, (void **) &pSMBr);
4881 params = 2; /* level */
4882 pSMB->TotalDataCount = 0;
4883 pSMB->DataCount = 0;
4884 pSMB->DataOffset = 0;
4885 pSMB->MaxParameterCount = cpu_to_le16(2);
4886 /* BB find exact max SMB PDU from sess structure BB */
4887 pSMB->MaxDataCount = cpu_to_le16(100);
4888 pSMB->MaxSetupCount = 0;
4892 pSMB->Reserved2 = 0;
4893 byte_count = params + 1 /* pad */ ;
4894 pSMB->ParameterCount = cpu_to_le16(params);
4895 pSMB->TotalParameterCount = pSMB->ParameterCount;
4896 pSMB->ParameterOffset = cpu_to_le16(offsetof(struct
4897 smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4898 pSMB->SetupCount = 1;
4899 pSMB->Reserved3 = 0;
4900 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4901 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_CIFS_UNIX_INFO);
4902 inc_rfc1001_len(pSMB, byte_count);
4903 pSMB->ByteCount = cpu_to_le16(byte_count);
4905 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4906 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4908 cERROR(1, "Send error in QFSUnixInfo = %d", rc);
4909 } else { /* decode response */
4910 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4912 if (rc || get_bcc(&pSMBr->hdr) < 13) {
4913 rc = -EIO; /* bad smb */
4915 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4917 (FILE_SYSTEM_UNIX_INFO
4918 *) (((char *) &pSMBr->hdr.Protocol) +
4920 memcpy(&tcon->fsUnixInfo, response_data,
4921 sizeof(FILE_SYSTEM_UNIX_INFO));
4924 cifs_buf_release(pSMB);
4934 CIFSSMBSetFSUnixInfo(const int xid, struct cifsTconInfo *tcon, __u64 cap)
4936 /* level 0x200 SMB_SET_CIFS_UNIX_INFO */
4937 TRANSACTION2_SETFSI_REQ *pSMB = NULL;
4938 TRANSACTION2_SETFSI_RSP *pSMBr = NULL;
4940 int bytes_returned = 0;
4941 __u16 params, param_offset, offset, byte_count;
4943 cFYI(1, "In SETFSUnixInfo");
4945 /* BB switch to small buf init to save memory */
4946 rc = smb_init_no_reconnect(SMB_COM_TRANSACTION2, 15, tcon,
4947 (void **) &pSMB, (void **) &pSMBr);
4951 params = 4; /* 2 bytes zero followed by info level. */
4952 pSMB->MaxSetupCount = 0;
4956 pSMB->Reserved2 = 0;
4957 param_offset = offsetof(struct smb_com_transaction2_setfsi_req, FileNum)
4959 offset = param_offset + params;
4961 pSMB->MaxParameterCount = cpu_to_le16(4);
4962 /* BB find exact max SMB PDU from sess structure BB */
4963 pSMB->MaxDataCount = cpu_to_le16(100);
4964 pSMB->SetupCount = 1;
4965 pSMB->Reserved3 = 0;
4966 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FS_INFORMATION);
4967 byte_count = 1 /* pad */ + params + 12;
4969 pSMB->DataCount = cpu_to_le16(12);
4970 pSMB->ParameterCount = cpu_to_le16(params);
4971 pSMB->TotalDataCount = pSMB->DataCount;
4972 pSMB->TotalParameterCount = pSMB->ParameterCount;
4973 pSMB->ParameterOffset = cpu_to_le16(param_offset);
4974 pSMB->DataOffset = cpu_to_le16(offset);
4978 pSMB->InformationLevel = cpu_to_le16(SMB_SET_CIFS_UNIX_INFO);
4981 pSMB->ClientUnixMajor = cpu_to_le16(CIFS_UNIX_MAJOR_VERSION);
4982 pSMB->ClientUnixMinor = cpu_to_le16(CIFS_UNIX_MINOR_VERSION);
4983 pSMB->ClientUnixCap = cpu_to_le64(cap);
4985 inc_rfc1001_len(pSMB, byte_count);
4986 pSMB->ByteCount = cpu_to_le16(byte_count);
4988 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4989 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4991 cERROR(1, "Send error in SETFSUnixInfo = %d", rc);
4992 } else { /* decode response */
4993 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4995 rc = -EIO; /* bad smb */
4997 cifs_buf_release(pSMB);
5000 goto SETFSUnixRetry;
5008 CIFSSMBQFSPosixInfo(const int xid, struct cifsTconInfo *tcon,
5009 struct kstatfs *FSData)
5011 /* level 0x201 SMB_QUERY_CIFS_POSIX_INFO */
5012 TRANSACTION2_QFSI_REQ *pSMB = NULL;
5013 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
5014 FILE_SYSTEM_POSIX_INFO *response_data;
5016 int bytes_returned = 0;
5017 __u16 params, byte_count;
5019 cFYI(1, "In QFSPosixInfo");
5021 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5026 params = 2; /* level */
5027 pSMB->TotalDataCount = 0;
5028 pSMB->DataCount = 0;
5029 pSMB->DataOffset = 0;
5030 pSMB->MaxParameterCount = cpu_to_le16(2);
5031 /* BB find exact max SMB PDU from sess structure BB */
5032 pSMB->MaxDataCount = cpu_to_le16(100);
5033 pSMB->MaxSetupCount = 0;
5037 pSMB->Reserved2 = 0;
5038 byte_count = params + 1 /* pad */ ;
5039 pSMB->ParameterCount = cpu_to_le16(params);
5040 pSMB->TotalParameterCount = pSMB->ParameterCount;
5041 pSMB->ParameterOffset = cpu_to_le16(offsetof(struct
5042 smb_com_transaction2_qfsi_req, InformationLevel) - 4);
5043 pSMB->SetupCount = 1;
5044 pSMB->Reserved3 = 0;
5045 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
5046 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_POSIX_FS_INFO);
5047 inc_rfc1001_len(pSMB, byte_count);
5048 pSMB->ByteCount = cpu_to_le16(byte_count);
5050 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5051 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5053 cFYI(1, "Send error in QFSUnixInfo = %d", rc);
5054 } else { /* decode response */
5055 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
5057 if (rc || get_bcc(&pSMBr->hdr) < 13) {
5058 rc = -EIO; /* bad smb */
5060 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
5062 (FILE_SYSTEM_POSIX_INFO
5063 *) (((char *) &pSMBr->hdr.Protocol) +
5066 le32_to_cpu(response_data->BlockSize);
5068 le64_to_cpu(response_data->TotalBlocks);
5070 le64_to_cpu(response_data->BlocksAvail);
5071 if (response_data->UserBlocksAvail == cpu_to_le64(-1)) {
5072 FSData->f_bavail = FSData->f_bfree;
5075 le64_to_cpu(response_data->UserBlocksAvail);
5077 if (response_data->TotalFileNodes != cpu_to_le64(-1))
5079 le64_to_cpu(response_data->TotalFileNodes);
5080 if (response_data->FreeFileNodes != cpu_to_le64(-1))
5082 le64_to_cpu(response_data->FreeFileNodes);
5085 cifs_buf_release(pSMB);
5094 /* We can not use write of zero bytes trick to
5095 set file size due to need for large file support. Also note that
5096 this SetPathInfo is preferred to SetFileInfo based method in next
5097 routine which is only needed to work around a sharing violation bug
5098 in Samba which this routine can run into */
5101 CIFSSMBSetEOF(const int xid, struct cifsTconInfo *tcon, const char *fileName,
5102 __u64 size, bool SetAllocation,
5103 const struct nls_table *nls_codepage, int remap)
5105 struct smb_com_transaction2_spi_req *pSMB = NULL;
5106 struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
5107 struct file_end_of_file_info *parm_data;
5110 int bytes_returned = 0;
5111 __u16 params, byte_count, data_count, param_offset, offset;
5113 cFYI(1, "In SetEOF");
5115 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5120 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5122 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
5123 PATH_MAX, nls_codepage, remap);
5124 name_len++; /* trailing null */
5126 } else { /* BB improve the check for buffer overruns BB */
5127 name_len = strnlen(fileName, PATH_MAX);
5128 name_len++; /* trailing null */
5129 strncpy(pSMB->FileName, fileName, name_len);
5131 params = 6 + name_len;
5132 data_count = sizeof(struct file_end_of_file_info);
5133 pSMB->MaxParameterCount = cpu_to_le16(2);
5134 pSMB->MaxDataCount = cpu_to_le16(4100);
5135 pSMB->MaxSetupCount = 0;
5139 pSMB->Reserved2 = 0;
5140 param_offset = offsetof(struct smb_com_transaction2_spi_req,
5141 InformationLevel) - 4;
5142 offset = param_offset + params;
5143 if (SetAllocation) {
5144 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
5145 pSMB->InformationLevel =
5146 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2);
5148 pSMB->InformationLevel =
5149 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO);
5150 } else /* Set File Size */ {
5151 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
5152 pSMB->InformationLevel =
5153 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO2);
5155 pSMB->InformationLevel =
5156 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO);
5160 (struct file_end_of_file_info *) (((char *) &pSMB->hdr.Protocol) +
5162 pSMB->ParameterOffset = cpu_to_le16(param_offset);
5163 pSMB->DataOffset = cpu_to_le16(offset);
5164 pSMB->SetupCount = 1;
5165 pSMB->Reserved3 = 0;
5166 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
5167 byte_count = 3 /* pad */ + params + data_count;
5168 pSMB->DataCount = cpu_to_le16(data_count);
5169 pSMB->TotalDataCount = pSMB->DataCount;
5170 pSMB->ParameterCount = cpu_to_le16(params);
5171 pSMB->TotalParameterCount = pSMB->ParameterCount;
5172 pSMB->Reserved4 = 0;
5173 inc_rfc1001_len(pSMB, byte_count);
5174 parm_data->FileSize = cpu_to_le64(size);
5175 pSMB->ByteCount = cpu_to_le16(byte_count);
5176 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5177 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5179 cFYI(1, "SetPathInfo (file size) returned %d", rc);
5181 cifs_buf_release(pSMB);
5190 CIFSSMBSetFileSize(const int xid, struct cifsTconInfo *tcon, __u64 size,
5191 __u16 fid, __u32 pid_of_opener, bool SetAllocation)
5193 struct smb_com_transaction2_sfi_req *pSMB = NULL;
5194 struct file_end_of_file_info *parm_data;
5196 __u16 params, param_offset, offset, byte_count, count;
5198 cFYI(1, "SetFileSize (via SetFileInfo) %lld",
5200 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
5205 pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
5206 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));
5209 pSMB->MaxSetupCount = 0;
5213 pSMB->Reserved2 = 0;
5214 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
5215 offset = param_offset + params;
5217 count = sizeof(struct file_end_of_file_info);
5218 pSMB->MaxParameterCount = cpu_to_le16(2);
5219 /* BB find exact max SMB PDU from sess structure BB */
5220 pSMB->MaxDataCount = cpu_to_le16(1000);
5221 pSMB->SetupCount = 1;
5222 pSMB->Reserved3 = 0;
5223 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
5224 byte_count = 3 /* pad */ + params + count;
5225 pSMB->DataCount = cpu_to_le16(count);
5226 pSMB->ParameterCount = cpu_to_le16(params);
5227 pSMB->TotalDataCount = pSMB->DataCount;
5228 pSMB->TotalParameterCount = pSMB->ParameterCount;
5229 pSMB->ParameterOffset = cpu_to_le16(param_offset);
5231 (struct file_end_of_file_info *) (((char *) &pSMB->hdr.Protocol)
5233 pSMB->DataOffset = cpu_to_le16(offset);
5234 parm_data->FileSize = cpu_to_le64(size);
5236 if (SetAllocation) {
5237 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
5238 pSMB->InformationLevel =
5239 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2);
5241 pSMB->InformationLevel =
5242 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO);
5243 } else /* Set File Size */ {
5244 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
5245 pSMB->InformationLevel =
5246 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO2);
5248 pSMB->InformationLevel =
5249 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO);
5251 pSMB->Reserved4 = 0;
5252 inc_rfc1001_len(pSMB, byte_count);
5253 pSMB->ByteCount = cpu_to_le16(byte_count);
5254 rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0);
5256 cFYI(1, "Send error in SetFileInfo (SetFileSize) = %d", rc);
5259 /* Note: On -EAGAIN error only caller can retry on handle based calls
5260 since file handle passed in no longer valid */
5265 /* Some legacy servers such as NT4 require that the file times be set on
5266 an open handle, rather than by pathname - this is awkward due to
5267 potential access conflicts on the open, but it is unavoidable for these
5268 old servers since the only other choice is to go from 100 nanosecond DCE
5269 time and resort to the original setpathinfo level which takes the ancient
5270 DOS time format with 2 second granularity */
5272 CIFSSMBSetFileInfo(const int xid, struct cifsTconInfo *tcon,
5273 const FILE_BASIC_INFO *data, __u16 fid, __u32 pid_of_opener)
5275 struct smb_com_transaction2_sfi_req *pSMB = NULL;
5278 __u16 params, param_offset, offset, byte_count, count;
5280 cFYI(1, "Set Times (via SetFileInfo)");
5281 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
5286 pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
5287 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));
5290 pSMB->MaxSetupCount = 0;
5294 pSMB->Reserved2 = 0;
5295 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
5296 offset = param_offset + params;
5298 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
5300 count = sizeof(FILE_BASIC_INFO);
5301 pSMB->MaxParameterCount = cpu_to_le16(2);
5302 /* BB find max SMB PDU from sess */
5303 pSMB->MaxDataCount = cpu_to_le16(1000);
5304 pSMB->SetupCount = 1;
5305 pSMB->Reserved3 = 0;
5306 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
5307 byte_count = 3 /* pad */ + params + count;
5308 pSMB->DataCount = cpu_to_le16(count);
5309 pSMB->ParameterCount = cpu_to_le16(params);
5310 pSMB->TotalDataCount = pSMB->DataCount;
5311 pSMB->TotalParameterCount = pSMB->ParameterCount;
5312 pSMB->ParameterOffset = cpu_to_le16(param_offset);
5313 pSMB->DataOffset = cpu_to_le16(offset);
5315 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
5316 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO2);
5318 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO);
5319 pSMB->Reserved4 = 0;
5320 inc_rfc1001_len(pSMB, byte_count);
5321 pSMB->ByteCount = cpu_to_le16(byte_count);
5322 memcpy(data_offset, data, sizeof(FILE_BASIC_INFO));
5323 rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0);
5325 cFYI(1, "Send error in Set Time (SetFileInfo) = %d", rc);
5327 /* Note: On -EAGAIN error only caller can retry on handle based calls
5328 since file handle passed in no longer valid */
5334 CIFSSMBSetFileDisposition(const int xid, struct cifsTconInfo *tcon,
5335 bool delete_file, __u16 fid, __u32 pid_of_opener)
5337 struct smb_com_transaction2_sfi_req *pSMB = NULL;
5340 __u16 params, param_offset, offset, byte_count, count;
5342 cFYI(1, "Set File Disposition (via SetFileInfo)");
5343 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
5348 pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
5349 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));
5352 pSMB->MaxSetupCount = 0;
5356 pSMB->Reserved2 = 0;
5357 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
5358 offset = param_offset + params;
5360 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
5363 pSMB->MaxParameterCount = cpu_to_le16(2);
5364 /* BB find max SMB PDU from sess */
5365 pSMB->MaxDataCount = cpu_to_le16(1000);
5366 pSMB->SetupCount = 1;
5367 pSMB->Reserved3 = 0;
5368 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
5369 byte_count = 3 /* pad */ + params + count;
5370 pSMB->DataCount = cpu_to_le16(count);
5371 pSMB->ParameterCount = cpu_to_le16(params);
5372 pSMB->TotalDataCount = pSMB->DataCount;
5373 pSMB->TotalParameterCount = pSMB->ParameterCount;
5374 pSMB->ParameterOffset = cpu_to_le16(param_offset);
5375 pSMB->DataOffset = cpu_to_le16(offset);
5377 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_DISPOSITION_INFO);
5378 pSMB->Reserved4 = 0;
5379 inc_rfc1001_len(pSMB, byte_count);
5380 pSMB->ByteCount = cpu_to_le16(byte_count);
5381 *data_offset = delete_file ? 1 : 0;
5382 rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0);
5384 cFYI(1, "Send error in SetFileDisposition = %d", rc);
5390 CIFSSMBSetPathInfo(const int xid, struct cifsTconInfo *tcon,
5391 const char *fileName, const FILE_BASIC_INFO *data,
5392 const struct nls_table *nls_codepage, int remap)
5394 TRANSACTION2_SPI_REQ *pSMB = NULL;
5395 TRANSACTION2_SPI_RSP *pSMBr = NULL;
5398 int bytes_returned = 0;
5400 __u16 params, param_offset, offset, byte_count, count;
5402 cFYI(1, "In SetTimes");
5405 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5410 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5412 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
5413 PATH_MAX, nls_codepage, remap);
5414 name_len++; /* trailing null */
5416 } else { /* BB improve the check for buffer overruns BB */
5417 name_len = strnlen(fileName, PATH_MAX);
5418 name_len++; /* trailing null */
5419 strncpy(pSMB->FileName, fileName, name_len);
5422 params = 6 + name_len;
5423 count = sizeof(FILE_BASIC_INFO);
5424 pSMB->MaxParameterCount = cpu_to_le16(2);
5425 /* BB find max SMB PDU from sess structure BB */
5426 pSMB->MaxDataCount = cpu_to_le16(1000);
5427 pSMB->MaxSetupCount = 0;
5431 pSMB->Reserved2 = 0;
5432 param_offset = offsetof(struct smb_com_transaction2_spi_req,
5433 InformationLevel) - 4;
5434 offset = param_offset + params;
5435 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
5436 pSMB->ParameterOffset = cpu_to_le16(param_offset);
5437 pSMB->DataOffset = cpu_to_le16(offset);
5438 pSMB->SetupCount = 1;
5439 pSMB->Reserved3 = 0;
5440 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
5441 byte_count = 3 /* pad */ + params + count;
5443 pSMB->DataCount = cpu_to_le16(count);
5444 pSMB->ParameterCount = cpu_to_le16(params);
5445 pSMB->TotalDataCount = pSMB->DataCount;
5446 pSMB->TotalParameterCount = pSMB->ParameterCount;
5447 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
5448 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO2);
5450 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO);
5451 pSMB->Reserved4 = 0;
5452 inc_rfc1001_len(pSMB, byte_count);
5453 memcpy(data_offset, data, sizeof(FILE_BASIC_INFO));
5454 pSMB->ByteCount = cpu_to_le16(byte_count);
5455 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5456 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5458 cFYI(1, "SetPathInfo (times) returned %d", rc);
5460 cifs_buf_release(pSMB);
5468 /* Can not be used to set time stamps yet (due to old DOS time format) */
5469 /* Can be used to set attributes */
5470 #if 0 /* Possibly not needed - since it turns out that strangely NT4 has a bug
5471 handling it anyway and NT4 was what we thought it would be needed for
5472 Do not delete it until we prove whether needed for Win9x though */
5474 CIFSSMBSetAttrLegacy(int xid, struct cifsTconInfo *tcon, char *fileName,
5475 __u16 dos_attrs, const struct nls_table *nls_codepage)
5477 SETATTR_REQ *pSMB = NULL;
5478 SETATTR_RSP *pSMBr = NULL;
5483 cFYI(1, "In SetAttrLegacy");
5486 rc = smb_init(SMB_COM_SETATTR, 8, tcon, (void **) &pSMB,
5491 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5493 ConvertToUCS((__le16 *) pSMB->fileName, fileName,
5494 PATH_MAX, nls_codepage);
5495 name_len++; /* trailing null */
5497 } else { /* BB improve the check for buffer overruns BB */
5498 name_len = strnlen(fileName, PATH_MAX);
5499 name_len++; /* trailing null */
5500 strncpy(pSMB->fileName, fileName, name_len);
5502 pSMB->attr = cpu_to_le16(dos_attrs);
5503 pSMB->BufferFormat = 0x04;
5504 inc_rfc1001_len(pSMB, name_len + 1);
5505 pSMB->ByteCount = cpu_to_le16(name_len + 1);
5506 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5507 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5509 cFYI(1, "Error in LegacySetAttr = %d", rc);
5511 cifs_buf_release(pSMB);
5514 goto SetAttrLgcyRetry;
5518 #endif /* temporarily unneeded SetAttr legacy function */
5521 cifs_fill_unix_set_info(FILE_UNIX_BASIC_INFO *data_offset,
5522 const struct cifs_unix_set_info_args *args)
5524 u64 mode = args->mode;
5527 * Samba server ignores set of file size to zero due to bugs in some
5528 * older clients, but we should be precise - we use SetFileSize to
5529 * set file size and do not want to truncate file size to zero
5530 * accidentally as happened on one Samba server beta by putting
5531 * zero instead of -1 here
5533 data_offset->EndOfFile = cpu_to_le64(NO_CHANGE_64);
5534 data_offset->NumOfBytes = cpu_to_le64(NO_CHANGE_64);
5535 data_offset->LastStatusChange = cpu_to_le64(args->ctime);
5536 data_offset->LastAccessTime = cpu_to_le64(args->atime);
5537 data_offset->LastModificationTime = cpu_to_le64(args->mtime);
5538 data_offset->Uid = cpu_to_le64(args->uid);
5539 data_offset->Gid = cpu_to_le64(args->gid);
5540 /* better to leave device as zero when it is */
5541 data_offset->DevMajor = cpu_to_le64(MAJOR(args->device));
5542 data_offset->DevMinor = cpu_to_le64(MINOR(args->device));
5543 data_offset->Permissions = cpu_to_le64(mode);
5546 data_offset->Type = cpu_to_le32(UNIX_FILE);
5547 else if (S_ISDIR(mode))
5548 data_offset->Type = cpu_to_le32(UNIX_DIR);
5549 else if (S_ISLNK(mode))
5550 data_offset->Type = cpu_to_le32(UNIX_SYMLINK);
5551 else if (S_ISCHR(mode))
5552 data_offset->Type = cpu_to_le32(UNIX_CHARDEV);
5553 else if (S_ISBLK(mode))
5554 data_offset->Type = cpu_to_le32(UNIX_BLOCKDEV);
5555 else if (S_ISFIFO(mode))
5556 data_offset->Type = cpu_to_le32(UNIX_FIFO);
5557 else if (S_ISSOCK(mode))
5558 data_offset->Type = cpu_to_le32(UNIX_SOCKET);
5562 CIFSSMBUnixSetFileInfo(const int xid, struct cifsTconInfo *tcon,
5563 const struct cifs_unix_set_info_args *args,
5564 u16 fid, u32 pid_of_opener)
5566 struct smb_com_transaction2_sfi_req *pSMB = NULL;
5567 FILE_UNIX_BASIC_INFO *data_offset;
5569 u16 params, param_offset, offset, byte_count, count;
5571 cFYI(1, "Set Unix Info (via SetFileInfo)");
5572 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
5577 pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
5578 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));
5581 pSMB->MaxSetupCount = 0;
5585 pSMB->Reserved2 = 0;
5586 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
5587 offset = param_offset + params;
5589 data_offset = (FILE_UNIX_BASIC_INFO *)
5590 ((char *)(&pSMB->hdr.Protocol) + offset);
5591 count = sizeof(FILE_UNIX_BASIC_INFO);
5593 pSMB->MaxParameterCount = cpu_to_le16(2);
5594 /* BB find max SMB PDU from sess */
5595 pSMB->MaxDataCount = cpu_to_le16(1000);
5596 pSMB->SetupCount = 1;
5597 pSMB->Reserved3 = 0;
5598 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
5599 byte_count = 3 /* pad */ + params + count;
5600 pSMB->DataCount = cpu_to_le16(count);
5601 pSMB->ParameterCount = cpu_to_le16(params);
5602 pSMB->TotalDataCount = pSMB->DataCount;
5603 pSMB->TotalParameterCount = pSMB->ParameterCount;
5604 pSMB->ParameterOffset = cpu_to_le16(param_offset);
5605 pSMB->DataOffset = cpu_to_le16(offset);
5607 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_BASIC);
5608 pSMB->Reserved4 = 0;
5609 inc_rfc1001_len(pSMB, byte_count);
5610 pSMB->ByteCount = cpu_to_le16(byte_count);
5612 cifs_fill_unix_set_info(data_offset, args);
5614 rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0);
5616 cFYI(1, "Send error in Set Time (SetFileInfo) = %d", rc);
5618 /* Note: On -EAGAIN error only caller can retry on handle based calls
5619 since file handle passed in no longer valid */
5625 CIFSSMBUnixSetPathInfo(const int xid, struct cifsTconInfo *tcon, char *fileName,
5626 const struct cifs_unix_set_info_args *args,
5627 const struct nls_table *nls_codepage, int remap)
5629 TRANSACTION2_SPI_REQ *pSMB = NULL;
5630 TRANSACTION2_SPI_RSP *pSMBr = NULL;
5633 int bytes_returned = 0;
5634 FILE_UNIX_BASIC_INFO *data_offset;
5635 __u16 params, param_offset, offset, count, byte_count;
5637 cFYI(1, "In SetUID/GID/Mode");
5639 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5644 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5646 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
5647 PATH_MAX, nls_codepage, remap);
5648 name_len++; /* trailing null */
5650 } else { /* BB improve the check for buffer overruns BB */
5651 name_len = strnlen(fileName, PATH_MAX);
5652 name_len++; /* trailing null */
5653 strncpy(pSMB->FileName, fileName, name_len);
5656 params = 6 + name_len;
5657 count = sizeof(FILE_UNIX_BASIC_INFO);
5658 pSMB->MaxParameterCount = cpu_to_le16(2);
5659 /* BB find max SMB PDU from sess structure BB */
5660 pSMB->MaxDataCount = cpu_to_le16(1000);
5661 pSMB->MaxSetupCount = 0;
5665 pSMB->Reserved2 = 0;
5666 param_offset = offsetof(struct smb_com_transaction2_spi_req,
5667 InformationLevel) - 4;
5668 offset = param_offset + params;
5670 (FILE_UNIX_BASIC_INFO *) ((char *) &pSMB->hdr.Protocol +
5672 memset(data_offset, 0, count);
5673 pSMB->DataOffset = cpu_to_le16(offset);
5674 pSMB->ParameterOffset = cpu_to_le16(param_offset);
5675 pSMB->SetupCount = 1;
5676 pSMB->Reserved3 = 0;
5677 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
5678 byte_count = 3 /* pad */ + params + count;
5679 pSMB->ParameterCount = cpu_to_le16(params);
5680 pSMB->DataCount = cpu_to_le16(count);
5681 pSMB->TotalParameterCount = pSMB->ParameterCount;
5682 pSMB->TotalDataCount = pSMB->DataCount;
5683 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_BASIC);
5684 pSMB->Reserved4 = 0;
5685 inc_rfc1001_len(pSMB, byte_count);
5687 cifs_fill_unix_set_info(data_offset, args);
5689 pSMB->ByteCount = cpu_to_le16(byte_count);
5690 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5691 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5693 cFYI(1, "SetPathInfo (perms) returned %d", rc);
5695 cifs_buf_release(pSMB);
5701 #ifdef CONFIG_CIFS_XATTR
5703 * Do a path-based QUERY_ALL_EAS call and parse the result. This is a common
5704 * function used by listxattr and getxattr type calls. When ea_name is set,
5705 * it looks for that attribute name and stuffs that value into the EAData
5706 * buffer. When ea_name is NULL, it stuffs a list of attribute names into the
5707 * buffer. In both cases, the return value is either the length of the
5708 * resulting data or a negative error code. If EAData is a NULL pointer then
5709 * the data isn't copied to it, but the length is returned.
5712 CIFSSMBQAllEAs(const int xid, struct cifsTconInfo *tcon,
5713 const unsigned char *searchName, const unsigned char *ea_name,
5714 char *EAData, size_t buf_size,
5715 const struct nls_table *nls_codepage, int remap)
5717 /* BB assumes one setup word */
5718 TRANSACTION2_QPI_REQ *pSMB = NULL;
5719 TRANSACTION2_QPI_RSP *pSMBr = NULL;
5723 struct fealist *ea_response_data;
5724 struct fea *temp_fea;
5727 __u16 params, byte_count, data_offset;
5729 cFYI(1, "In Query All EAs path %s", searchName);
5731 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5736 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5738 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
5739 PATH_MAX, nls_codepage, remap);
5740 list_len++; /* trailing null */
5742 } else { /* BB improve the check for buffer overruns BB */
5743 list_len = strnlen(searchName, PATH_MAX);
5744 list_len++; /* trailing null */
5745 strncpy(pSMB->FileName, searchName, list_len);
5748 params = 2 /* level */ + 4 /* reserved */ + list_len /* includes NUL */;
5749 pSMB->TotalDataCount = 0;
5750 pSMB->MaxParameterCount = cpu_to_le16(2);
5751 /* BB find exact max SMB PDU from sess structure BB */
5752 pSMB->MaxDataCount = cpu_to_le16(CIFSMaxBufSize);
5753 pSMB->MaxSetupCount = 0;
5757 pSMB->Reserved2 = 0;
5758 pSMB->ParameterOffset = cpu_to_le16(offsetof(
5759 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
5760 pSMB->DataCount = 0;
5761 pSMB->DataOffset = 0;
5762 pSMB->SetupCount = 1;
5763 pSMB->Reserved3 = 0;
5764 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
5765 byte_count = params + 1 /* pad */ ;
5766 pSMB->TotalParameterCount = cpu_to_le16(params);
5767 pSMB->ParameterCount = pSMB->TotalParameterCount;
5768 pSMB->InformationLevel = cpu_to_le16(SMB_INFO_QUERY_ALL_EAS);
5769 pSMB->Reserved4 = 0;
5770 inc_rfc1001_len(pSMB, byte_count);
5771 pSMB->ByteCount = cpu_to_le16(byte_count);
5773 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5774 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5776 cFYI(1, "Send error in QueryAllEAs = %d", rc);
5781 /* BB also check enough total bytes returned */
5782 /* BB we need to improve the validity checking
5783 of these trans2 responses */
5785 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
5786 if (rc || get_bcc(&pSMBr->hdr) < 4) {
5787 rc = -EIO; /* bad smb */
5791 /* check that length of list is not more than bcc */
5792 /* check that each entry does not go beyond length
5794 /* check that each element of each entry does not
5795 go beyond end of list */
5796 /* validate_trans2_offsets() */
5797 /* BB check if start of smb + data_offset > &bcc+ bcc */
5799 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
5800 ea_response_data = (struct fealist *)
5801 (((char *) &pSMBr->hdr.Protocol) + data_offset);
5803 list_len = le32_to_cpu(ea_response_data->list_len);
5804 cFYI(1, "ea length %d", list_len);
5805 if (list_len <= 8) {
5806 cFYI(1, "empty EA list returned from server");
5810 /* make sure list_len doesn't go past end of SMB */
5811 end_of_smb = (char *)pByteArea(&pSMBr->hdr) + get_bcc(&pSMBr->hdr);
5812 if ((char *)ea_response_data + list_len > end_of_smb) {
5813 cFYI(1, "EA list appears to go beyond SMB");
5818 /* account for ea list len */
5820 temp_fea = ea_response_data->list;
5821 temp_ptr = (char *)temp_fea;
5822 while (list_len > 0) {
5823 unsigned int name_len;
5828 /* make sure we can read name_len and value_len */
5830 cFYI(1, "EA entry goes beyond length of list");
5835 name_len = temp_fea->name_len;
5836 value_len = le16_to_cpu(temp_fea->value_len);
5837 list_len -= name_len + 1 + value_len;
5839 cFYI(1, "EA entry goes beyond length of list");
5845 if (strncmp(ea_name, temp_ptr, name_len) == 0) {
5846 temp_ptr += name_len + 1;
5850 if ((size_t)value_len > buf_size) {
5854 memcpy(EAData, temp_ptr, value_len);
5858 /* account for prefix user. and trailing null */
5859 rc += (5 + 1 + name_len);
5860 if (rc < (int) buf_size) {
5861 memcpy(EAData, "user.", 5);
5863 memcpy(EAData, temp_ptr, name_len);
5865 /* null terminate name */
5868 } else if (buf_size == 0) {
5869 /* skip copy - calc size only */
5871 /* stop before overrun buffer */
5876 temp_ptr += name_len + 1 + value_len;
5877 temp_fea = (struct fea *)temp_ptr;
5880 /* didn't find the named attribute */
5885 cifs_buf_release(pSMB);
5893 CIFSSMBSetEA(const int xid, struct cifsTconInfo *tcon, const char *fileName,
5894 const char *ea_name, const void *ea_value,
5895 const __u16 ea_value_len, const struct nls_table *nls_codepage,
5898 struct smb_com_transaction2_spi_req *pSMB = NULL;
5899 struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
5900 struct fealist *parm_data;
5903 int bytes_returned = 0;
5904 __u16 params, param_offset, byte_count, offset, count;
5906 cFYI(1, "In SetEA");
5908 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5913 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5915 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
5916 PATH_MAX, nls_codepage, remap);
5917 name_len++; /* trailing null */
5919 } else { /* BB improve the check for buffer overruns BB */
5920 name_len = strnlen(fileName, PATH_MAX);
5921 name_len++; /* trailing null */
5922 strncpy(pSMB->FileName, fileName, name_len);
5925 params = 6 + name_len;
5927 /* done calculating parms using name_len of file name,
5928 now use name_len to calculate length of ea name
5929 we are going to create in the inode xattrs */
5930 if (ea_name == NULL)
5933 name_len = strnlen(ea_name, 255);
5935 count = sizeof(*parm_data) + ea_value_len + name_len;
5936 pSMB->MaxParameterCount = cpu_to_le16(2);
5937 /* BB find max SMB PDU from sess */
5938 pSMB->MaxDataCount = cpu_to_le16(1000);
5939 pSMB->MaxSetupCount = 0;
5943 pSMB->Reserved2 = 0;
5944 param_offset = offsetof(struct smb_com_transaction2_spi_req,
5945 InformationLevel) - 4;
5946 offset = param_offset + params;
5947 pSMB->InformationLevel =
5948 cpu_to_le16(SMB_SET_FILE_EA);
5951 (struct fealist *) (((char *) &pSMB->hdr.Protocol) +
5953 pSMB->ParameterOffset = cpu_to_le16(param_offset);
5954 pSMB->DataOffset = cpu_to_le16(offset);
5955 pSMB->SetupCount = 1;
5956 pSMB->Reserved3 = 0;
5957 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
5958 byte_count = 3 /* pad */ + params + count;
5959 pSMB->DataCount = cpu_to_le16(count);
5960 parm_data->list_len = cpu_to_le32(count);
5961 parm_data->list[0].EA_flags = 0;
5962 /* we checked above that name len is less than 255 */
5963 parm_data->list[0].name_len = (__u8)name_len;
5964 /* EA names are always ASCII */
5966 strncpy(parm_data->list[0].name, ea_name, name_len);
5967 parm_data->list[0].name[name_len] = 0;
5968 parm_data->list[0].value_len = cpu_to_le16(ea_value_len);
5969 /* caller ensures that ea_value_len is less than 64K but
5970 we need to ensure that it fits within the smb */
5972 /*BB add length check to see if it would fit in
5973 negotiated SMB buffer size BB */
5974 /* if (ea_value_len > buffer_size - 512 (enough for header)) */
5976 memcpy(parm_data->list[0].name+name_len+1,
5977 ea_value, ea_value_len);
5979 pSMB->TotalDataCount = pSMB->DataCount;
5980 pSMB->ParameterCount = cpu_to_le16(params);
5981 pSMB->TotalParameterCount = pSMB->ParameterCount;
5982 pSMB->Reserved4 = 0;
5983 inc_rfc1001_len(pSMB, byte_count);
5984 pSMB->ByteCount = cpu_to_le16(byte_count);
5985 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5986 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5988 cFYI(1, "SetPathInfo (EA) returned %d", rc);
5990 cifs_buf_release(pSMB);
5999 #ifdef CONFIG_CIFS_DNOTIFY_EXPERIMENTAL /* BB unused temporarily */
6001 * Years ago the kernel added a "dnotify" function for Samba server,
6002 * to allow network clients (such as Windows) to display updated
6003 * lists of files in directory listings automatically when
6004 * files are added by one user when another user has the
6005 * same directory open on their desktop. The Linux cifs kernel
6006 * client hooked into the kernel side of this interface for
6007 * the same reason, but ironically when the VFS moved from
6008 * "dnotify" to "inotify" it became harder to plug in Linux
6009 * network file system clients (the most obvious use case
6010 * for notify interfaces is when multiple users can update
6011 * the contents of the same directory - exactly what network
6012 * file systems can do) although the server (Samba) could
6013 * still use it. For the short term we leave the worker
6014 * function ifdeffed out (below) until inotify is fixed
6015 * in the VFS to make it easier to plug in network file
6016 * system clients. If inotify turns out to be permanently
6017 * incompatible for network fs clients, we could instead simply
6018 * expose this config flag by adding a future cifs (and smb2) notify ioctl.
6020 int CIFSSMBNotify(const int xid, struct cifsTconInfo *tcon,
6021 const int notify_subdirs, const __u16 netfid,
6022 __u32 filter, struct file *pfile, int multishot,
6023 const struct nls_table *nls_codepage)
6026 struct smb_com_transaction_change_notify_req *pSMB = NULL;
6027 struct smb_com_ntransaction_change_notify_rsp *pSMBr = NULL;
6028 struct dir_notify_req *dnotify_req;
6031 cFYI(1, "In CIFSSMBNotify for file handle %d", (int)netfid);
6032 rc = smb_init(SMB_COM_NT_TRANSACT, 23, tcon, (void **) &pSMB,
6037 pSMB->TotalParameterCount = 0 ;
6038 pSMB->TotalDataCount = 0;
6039 pSMB->MaxParameterCount = cpu_to_le32(2);
6040 /* BB find exact data count max from sess structure BB */
6041 pSMB->MaxDataCount = 0; /* same in little endian or be */
6042 /* BB VERIFY verify which is correct for above BB */
6043 pSMB->MaxDataCount = cpu_to_le32((tcon->ses->server->maxBuf -
6044 MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
6046 pSMB->MaxSetupCount = 4;
6048 pSMB->ParameterOffset = 0;
6049 pSMB->DataCount = 0;
6050 pSMB->DataOffset = 0;
6051 pSMB->SetupCount = 4; /* single byte does not need le conversion */
6052 pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_NOTIFY_CHANGE);
6053 pSMB->ParameterCount = pSMB->TotalParameterCount;
6055 pSMB->WatchTree = 1; /* one byte - no le conversion needed */
6056 pSMB->Reserved2 = 0;
6057 pSMB->CompletionFilter = cpu_to_le32(filter);
6058 pSMB->Fid = netfid; /* file handle always le */
6059 pSMB->ByteCount = 0;
6061 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
6062 (struct smb_hdr *)pSMBr, &bytes_returned,
6065 cFYI(1, "Error in Notify = %d", rc);
6067 /* Add file to outstanding requests */
6068 /* BB change to kmem cache alloc */
6069 dnotify_req = kmalloc(
6070 sizeof(struct dir_notify_req),
6073 dnotify_req->Pid = pSMB->hdr.Pid;
6074 dnotify_req->PidHigh = pSMB->hdr.PidHigh;
6075 dnotify_req->Mid = pSMB->hdr.Mid;
6076 dnotify_req->Tid = pSMB->hdr.Tid;
6077 dnotify_req->Uid = pSMB->hdr.Uid;
6078 dnotify_req->netfid = netfid;
6079 dnotify_req->pfile = pfile;
6080 dnotify_req->filter = filter;
6081 dnotify_req->multishot = multishot;
6082 spin_lock(&GlobalMid_Lock);
6083 list_add_tail(&dnotify_req->lhead,
6084 &GlobalDnotifyReqList);
6085 spin_unlock(&GlobalMid_Lock);
6089 cifs_buf_release(pSMB);
6092 #endif /* was needed for dnotify, and will be needed for inotify when VFS fix */