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 cifsTconInfo *tcon, const int netfid,
1386 const unsigned int count, const __u64 lseek, unsigned int *nbytes,
1387 char **buf, int *pbuf_type)
1390 READ_REQ *pSMB = NULL;
1391 READ_RSP *pSMBr = NULL;
1392 char *pReadData = NULL;
1394 int resp_buf_type = 0;
1397 cFYI(1, "Reading %d bytes on fid %d", count, netfid);
1398 if (tcon->ses->capabilities & CAP_LARGE_FILES)
1401 wct = 10; /* old style read */
1402 if ((lseek >> 32) > 0) {
1403 /* can not handle this big offset for old */
1409 rc = small_smb_init(SMB_COM_READ_ANDX, wct, tcon, (void **) &pSMB);
1413 /* tcon and ses pointer are checked in smb_init */
1414 if (tcon->ses->server == NULL)
1415 return -ECONNABORTED;
1417 pSMB->AndXCommand = 0xFF; /* none */
1419 pSMB->OffsetLow = cpu_to_le32(lseek & 0xFFFFFFFF);
1421 pSMB->OffsetHigh = cpu_to_le32(lseek >> 32);
1423 pSMB->Remaining = 0;
1424 pSMB->MaxCount = cpu_to_le16(count & 0xFFFF);
1425 pSMB->MaxCountHigh = cpu_to_le32(count >> 16);
1427 pSMB->ByteCount = 0; /* no need to do le conversion since 0 */
1429 /* old style read */
1430 struct smb_com_readx_req *pSMBW =
1431 (struct smb_com_readx_req *)pSMB;
1432 pSMBW->ByteCount = 0;
1435 iov[0].iov_base = (char *)pSMB;
1436 iov[0].iov_len = be32_to_cpu(pSMB->hdr.smb_buf_length) + 4;
1437 rc = SendReceive2(xid, tcon->ses, iov, 1 /* num iovecs */,
1438 &resp_buf_type, CIFS_LOG_ERROR);
1439 cifs_stats_inc(&tcon->num_reads);
1440 pSMBr = (READ_RSP *)iov[0].iov_base;
1442 cERROR(1, "Send error in read = %d", rc);
1444 int data_length = le16_to_cpu(pSMBr->DataLengthHigh);
1445 data_length = data_length << 16;
1446 data_length += le16_to_cpu(pSMBr->DataLength);
1447 *nbytes = data_length;
1449 /*check that DataLength would not go beyond end of SMB */
1450 if ((data_length > CIFSMaxBufSize)
1451 || (data_length > count)) {
1452 cFYI(1, "bad length %d for count %d",
1453 data_length, count);
1457 pReadData = (char *) (&pSMBr->hdr.Protocol) +
1458 le16_to_cpu(pSMBr->DataOffset);
1459 /* if (rc = copy_to_user(buf, pReadData, data_length)) {
1460 cERROR(1, "Faulting on read rc = %d",rc);
1462 }*/ /* can not use copy_to_user when using page cache*/
1464 memcpy(*buf, pReadData, data_length);
1468 /* cifs_small_buf_release(pSMB); */ /* Freed earlier now in SendReceive2 */
1470 if (resp_buf_type == CIFS_SMALL_BUFFER)
1471 cifs_small_buf_release(iov[0].iov_base);
1472 else if (resp_buf_type == CIFS_LARGE_BUFFER)
1473 cifs_buf_release(iov[0].iov_base);
1474 } else if (resp_buf_type != CIFS_NO_BUFFER) {
1475 /* return buffer to caller to free */
1476 *buf = iov[0].iov_base;
1477 if (resp_buf_type == CIFS_SMALL_BUFFER)
1478 *pbuf_type = CIFS_SMALL_BUFFER;
1479 else if (resp_buf_type == CIFS_LARGE_BUFFER)
1480 *pbuf_type = CIFS_LARGE_BUFFER;
1481 } /* else no valid buffer on return - leave as null */
1483 /* Note: On -EAGAIN error only caller can retry on handle based calls
1484 since file handle passed in no longer valid */
1490 CIFSSMBWrite(const int xid, struct cifsTconInfo *tcon,
1491 const int netfid, const unsigned int count,
1492 const __u64 offset, unsigned int *nbytes, const char *buf,
1493 const char __user *ubuf, const int long_op)
1496 WRITE_REQ *pSMB = NULL;
1497 WRITE_RSP *pSMBr = NULL;
1498 int bytes_returned, wct;
1504 /* cFYI(1, "write at %lld %d bytes", offset, count);*/
1505 if (tcon->ses == NULL)
1506 return -ECONNABORTED;
1508 if (tcon->ses->capabilities & CAP_LARGE_FILES)
1512 if ((offset >> 32) > 0) {
1513 /* can not handle big offset for old srv */
1518 rc = smb_init(SMB_COM_WRITE_ANDX, wct, tcon, (void **) &pSMB,
1522 /* tcon and ses pointer are checked in smb_init */
1523 if (tcon->ses->server == NULL)
1524 return -ECONNABORTED;
1526 pSMB->AndXCommand = 0xFF; /* none */
1528 pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF);
1530 pSMB->OffsetHigh = cpu_to_le32(offset >> 32);
1532 pSMB->Reserved = 0xFFFFFFFF;
1533 pSMB->WriteMode = 0;
1534 pSMB->Remaining = 0;
1536 /* Can increase buffer size if buffer is big enough in some cases ie we
1537 can send more if LARGE_WRITE_X capability returned by the server and if
1538 our buffer is big enough or if we convert to iovecs on socket writes
1539 and eliminate the copy to the CIFS buffer */
1540 if (tcon->ses->capabilities & CAP_LARGE_WRITE_X) {
1541 bytes_sent = min_t(const unsigned int, CIFSMaxBufSize, count);
1543 bytes_sent = (tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE)
1547 if (bytes_sent > count)
1550 cpu_to_le16(offsetof(struct smb_com_write_req, Data) - 4);
1552 memcpy(pSMB->Data, buf, bytes_sent);
1554 if (copy_from_user(pSMB->Data, ubuf, bytes_sent)) {
1555 cifs_buf_release(pSMB);
1558 } else if (count != 0) {
1560 cifs_buf_release(pSMB);
1562 } /* else setting file size with write of zero bytes */
1564 byte_count = bytes_sent + 1; /* pad */
1565 else /* wct == 12 */
1566 byte_count = bytes_sent + 5; /* bigger pad, smaller smb hdr */
1568 pSMB->DataLengthLow = cpu_to_le16(bytes_sent & 0xFFFF);
1569 pSMB->DataLengthHigh = cpu_to_le16(bytes_sent >> 16);
1570 inc_rfc1001_len(pSMB, byte_count);
1573 pSMB->ByteCount = cpu_to_le16(byte_count);
1574 else { /* old style write has byte count 4 bytes earlier
1576 struct smb_com_writex_req *pSMBW =
1577 (struct smb_com_writex_req *)pSMB;
1578 pSMBW->ByteCount = cpu_to_le16(byte_count);
1581 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1582 (struct smb_hdr *) pSMBr, &bytes_returned, long_op);
1583 cifs_stats_inc(&tcon->num_writes);
1585 cFYI(1, "Send error in write = %d", rc);
1587 *nbytes = le16_to_cpu(pSMBr->CountHigh);
1588 *nbytes = (*nbytes) << 16;
1589 *nbytes += le16_to_cpu(pSMBr->Count);
1592 * Mask off high 16 bits when bytes written as returned by the
1593 * server is greater than bytes requested by the client. Some
1594 * OS/2 servers are known to set incorrect CountHigh values.
1596 if (*nbytes > count)
1600 cifs_buf_release(pSMB);
1602 /* Note: On -EAGAIN error only caller can retry on handle based calls
1603 since file handle passed in no longer valid */
1609 cifs_writedata_release(struct kref *refcount)
1611 struct cifs_writedata *wdata = container_of(refcount,
1612 struct cifs_writedata, refcount);
1615 cifsFileInfo_put(wdata->cfile);
1621 * Write failed with a retryable error. Resend the write request. It's also
1622 * possible that the page was redirtied so re-clean the page.
1625 cifs_writev_requeue(struct cifs_writedata *wdata)
1628 struct inode *inode = wdata->cfile->dentry->d_inode;
1630 for (i = 0; i < wdata->nr_pages; i++) {
1631 lock_page(wdata->pages[i]);
1632 clear_page_dirty_for_io(wdata->pages[i]);
1636 rc = cifs_async_writev(wdata);
1637 } while (rc == -EAGAIN);
1639 for (i = 0; i < wdata->nr_pages; i++) {
1641 SetPageError(wdata->pages[i]);
1642 unlock_page(wdata->pages[i]);
1645 mapping_set_error(inode->i_mapping, rc);
1646 kref_put(&wdata->refcount, cifs_writedata_release);
1650 cifs_writev_complete(struct work_struct *work)
1652 struct cifs_writedata *wdata = container_of(work,
1653 struct cifs_writedata, work);
1654 struct inode *inode = wdata->cfile->dentry->d_inode;
1657 if (wdata->result == 0) {
1658 cifs_update_eof(CIFS_I(inode), wdata->offset, wdata->bytes);
1659 cifs_stats_bytes_written(tlink_tcon(wdata->cfile->tlink),
1661 } else if (wdata->sync_mode == WB_SYNC_ALL && wdata->result == -EAGAIN)
1662 return cifs_writev_requeue(wdata);
1664 for (i = 0; i < wdata->nr_pages; i++) {
1665 struct page *page = wdata->pages[i];
1666 if (wdata->result == -EAGAIN)
1667 __set_page_dirty_nobuffers(page);
1668 else if (wdata->result < 0)
1670 end_page_writeback(page);
1671 page_cache_release(page);
1673 if (wdata->result != -EAGAIN)
1674 mapping_set_error(inode->i_mapping, wdata->result);
1675 kref_put(&wdata->refcount, cifs_writedata_release);
1678 struct cifs_writedata *
1679 cifs_writedata_alloc(unsigned int nr_pages)
1681 struct cifs_writedata *wdata;
1683 /* this would overflow */
1684 if (nr_pages == 0) {
1685 cERROR(1, "%s: called with nr_pages == 0!", __func__);
1689 /* writedata + number of page pointers */
1690 wdata = kzalloc(sizeof(*wdata) +
1691 sizeof(struct page *) * (nr_pages - 1), GFP_NOFS);
1692 if (wdata != NULL) {
1693 INIT_WORK(&wdata->work, cifs_writev_complete);
1694 kref_init(&wdata->refcount);
1700 * Check the midState and signature on received buffer (if any), and queue the
1701 * workqueue completion task.
1704 cifs_writev_callback(struct mid_q_entry *mid)
1706 struct cifs_writedata *wdata = mid->callback_data;
1707 struct cifsTconInfo *tcon = tlink_tcon(wdata->cfile->tlink);
1708 unsigned int written;
1709 WRITE_RSP *smb = (WRITE_RSP *)mid->resp_buf;
1711 switch (mid->midState) {
1712 case MID_RESPONSE_RECEIVED:
1713 wdata->result = cifs_check_receive(mid, tcon->ses->server, 0);
1714 if (wdata->result != 0)
1717 written = le16_to_cpu(smb->CountHigh);
1719 written += le16_to_cpu(smb->Count);
1721 * Mask off high 16 bits when bytes written as returned
1722 * by the server is greater than bytes requested by the
1723 * client. OS/2 servers are known to set incorrect
1726 if (written > wdata->bytes)
1729 if (written < wdata->bytes)
1730 wdata->result = -ENOSPC;
1732 wdata->bytes = written;
1734 case MID_REQUEST_SUBMITTED:
1735 case MID_RETRY_NEEDED:
1736 wdata->result = -EAGAIN;
1739 wdata->result = -EIO;
1743 queue_work(system_nrt_wq, &wdata->work);
1744 DeleteMidQEntry(mid);
1745 atomic_dec(&tcon->ses->server->inFlight);
1746 wake_up(&tcon->ses->server->request_q);
1749 /* cifs_async_writev - send an async write, and set up mid to handle result */
1751 cifs_async_writev(struct cifs_writedata *wdata)
1753 int i, rc = -EACCES;
1754 WRITE_REQ *smb = NULL;
1756 struct cifsTconInfo *tcon = tlink_tcon(wdata->cfile->tlink);
1757 struct inode *inode = wdata->cfile->dentry->d_inode;
1758 struct kvec *iov = NULL;
1760 if (tcon->ses->capabilities & CAP_LARGE_FILES) {
1764 if (wdata->offset >> 32 > 0) {
1765 /* can not handle big offset for old srv */
1770 rc = small_smb_init(SMB_COM_WRITE_ANDX, wct, tcon, (void **)&smb);
1772 goto async_writev_out;
1774 /* 1 iov per page + 1 for header */
1775 iov = kzalloc((wdata->nr_pages + 1) * sizeof(*iov), GFP_NOFS);
1778 goto async_writev_out;
1781 smb->AndXCommand = 0xFF; /* none */
1782 smb->Fid = wdata->cfile->netfid;
1783 smb->OffsetLow = cpu_to_le32(wdata->offset & 0xFFFFFFFF);
1785 smb->OffsetHigh = cpu_to_le32(wdata->offset >> 32);
1786 smb->Reserved = 0xFFFFFFFF;
1791 cpu_to_le16(offsetof(struct smb_com_write_req, Data) - 4);
1793 /* 4 for RFC1001 length + 1 for BCC */
1794 iov[0].iov_len = be32_to_cpu(smb->hdr.smb_buf_length) + 4 + 1;
1795 iov[0].iov_base = smb;
1797 /* marshal up the pages into iov array */
1799 for (i = 0; i < wdata->nr_pages; i++) {
1800 iov[i + 1].iov_len = min(inode->i_size -
1801 page_offset(wdata->pages[i]),
1802 (loff_t)PAGE_CACHE_SIZE);
1803 iov[i + 1].iov_base = kmap(wdata->pages[i]);
1804 wdata->bytes += iov[i + 1].iov_len;
1807 cFYI(1, "async write at %llu %u bytes", wdata->offset, wdata->bytes);
1809 smb->DataLengthLow = cpu_to_le16(wdata->bytes & 0xFFFF);
1810 smb->DataLengthHigh = cpu_to_le16(wdata->bytes >> 16);
1813 inc_rfc1001_len(&smb->hdr, wdata->bytes + 1);
1814 put_bcc(wdata->bytes + 1, &smb->hdr);
1817 struct smb_com_writex_req *smbw =
1818 (struct smb_com_writex_req *)smb;
1819 inc_rfc1001_len(&smbw->hdr, wdata->bytes + 5);
1820 put_bcc(wdata->bytes + 5, &smbw->hdr);
1821 iov[0].iov_len += 4; /* pad bigger by four bytes */
1824 kref_get(&wdata->refcount);
1825 rc = cifs_call_async(tcon->ses->server, iov, wdata->nr_pages + 1,
1826 cifs_writev_callback, wdata, false);
1829 cifs_stats_inc(&tcon->num_writes);
1831 kref_put(&wdata->refcount, cifs_writedata_release);
1833 /* send is done, unmap pages */
1834 for (i = 0; i < wdata->nr_pages; i++)
1835 kunmap(wdata->pages[i]);
1838 cifs_small_buf_release(smb);
1844 CIFSSMBWrite2(const int xid, struct cifsTconInfo *tcon,
1845 const int netfid, const unsigned int count,
1846 const __u64 offset, unsigned int *nbytes, struct kvec *iov,
1847 int n_vec, const int long_op)
1850 WRITE_REQ *pSMB = NULL;
1853 int resp_buf_type = 0;
1857 cFYI(1, "write2 at %lld %d bytes", (long long)offset, count);
1859 if (tcon->ses->capabilities & CAP_LARGE_FILES) {
1863 if ((offset >> 32) > 0) {
1864 /* can not handle big offset for old srv */
1868 rc = small_smb_init(SMB_COM_WRITE_ANDX, wct, tcon, (void **) &pSMB);
1871 /* tcon and ses pointer are checked in smb_init */
1872 if (tcon->ses->server == NULL)
1873 return -ECONNABORTED;
1875 pSMB->AndXCommand = 0xFF; /* none */
1877 pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF);
1879 pSMB->OffsetHigh = cpu_to_le32(offset >> 32);
1880 pSMB->Reserved = 0xFFFFFFFF;
1881 pSMB->WriteMode = 0;
1882 pSMB->Remaining = 0;
1885 cpu_to_le16(offsetof(struct smb_com_write_req, Data) - 4);
1887 pSMB->DataLengthLow = cpu_to_le16(count & 0xFFFF);
1888 pSMB->DataLengthHigh = cpu_to_le16(count >> 16);
1889 /* header + 1 byte pad */
1890 smb_hdr_len = be32_to_cpu(pSMB->hdr.smb_buf_length) + 1;
1892 inc_rfc1001_len(pSMB, count + 1);
1893 else /* wct == 12 */
1894 inc_rfc1001_len(pSMB, count + 5); /* smb data starts later */
1896 pSMB->ByteCount = cpu_to_le16(count + 1);
1897 else /* wct == 12 */ /* bigger pad, smaller smb hdr, keep offset ok */ {
1898 struct smb_com_writex_req *pSMBW =
1899 (struct smb_com_writex_req *)pSMB;
1900 pSMBW->ByteCount = cpu_to_le16(count + 5);
1902 iov[0].iov_base = pSMB;
1904 iov[0].iov_len = smb_hdr_len + 4;
1905 else /* wct == 12 pad bigger by four bytes */
1906 iov[0].iov_len = smb_hdr_len + 8;
1909 rc = SendReceive2(xid, tcon->ses, iov, n_vec + 1, &resp_buf_type,
1911 cifs_stats_inc(&tcon->num_writes);
1913 cFYI(1, "Send error Write2 = %d", rc);
1914 } else if (resp_buf_type == 0) {
1915 /* presumably this can not happen, but best to be safe */
1918 WRITE_RSP *pSMBr = (WRITE_RSP *)iov[0].iov_base;
1919 *nbytes = le16_to_cpu(pSMBr->CountHigh);
1920 *nbytes = (*nbytes) << 16;
1921 *nbytes += le16_to_cpu(pSMBr->Count);
1924 * Mask off high 16 bits when bytes written as returned by the
1925 * server is greater than bytes requested by the client. OS/2
1926 * servers are known to set incorrect CountHigh values.
1928 if (*nbytes > count)
1932 /* cifs_small_buf_release(pSMB); */ /* Freed earlier now in SendReceive2 */
1933 if (resp_buf_type == CIFS_SMALL_BUFFER)
1934 cifs_small_buf_release(iov[0].iov_base);
1935 else if (resp_buf_type == CIFS_LARGE_BUFFER)
1936 cifs_buf_release(iov[0].iov_base);
1938 /* Note: On -EAGAIN error only caller can retry on handle based calls
1939 since file handle passed in no longer valid */
1946 CIFSSMBLock(const int xid, struct cifsTconInfo *tcon,
1947 const __u16 smb_file_id, const __u64 len,
1948 const __u64 offset, const __u32 numUnlock,
1949 const __u32 numLock, const __u8 lockType,
1950 const bool waitFlag, const __u8 oplock_level)
1953 LOCK_REQ *pSMB = NULL;
1954 /* LOCK_RSP *pSMBr = NULL; */ /* No response data other than rc to parse */
1959 cFYI(1, "CIFSSMBLock timeout %d numLock %d", (int)waitFlag, numLock);
1960 rc = small_smb_init(SMB_COM_LOCKING_ANDX, 8, tcon, (void **) &pSMB);
1965 if (lockType == LOCKING_ANDX_OPLOCK_RELEASE) {
1966 timeout = CIFS_ASYNC_OP; /* no response expected */
1968 } else if (waitFlag) {
1969 timeout = CIFS_BLOCKING_OP; /* blocking operation, no timeout */
1970 pSMB->Timeout = cpu_to_le32(-1);/* blocking - do not time out */
1975 pSMB->NumberOfLocks = cpu_to_le16(numLock);
1976 pSMB->NumberOfUnlocks = cpu_to_le16(numUnlock);
1977 pSMB->LockType = lockType;
1978 pSMB->OplockLevel = oplock_level;
1979 pSMB->AndXCommand = 0xFF; /* none */
1980 pSMB->Fid = smb_file_id; /* netfid stays le */
1982 if ((numLock != 0) || (numUnlock != 0)) {
1983 pSMB->Locks[0].Pid = cpu_to_le16(current->tgid);
1984 /* BB where to store pid high? */
1985 pSMB->Locks[0].LengthLow = cpu_to_le32((u32)len);
1986 pSMB->Locks[0].LengthHigh = cpu_to_le32((u32)(len>>32));
1987 pSMB->Locks[0].OffsetLow = cpu_to_le32((u32)offset);
1988 pSMB->Locks[0].OffsetHigh = cpu_to_le32((u32)(offset>>32));
1989 count = sizeof(LOCKING_ANDX_RANGE);
1994 inc_rfc1001_len(pSMB, count);
1995 pSMB->ByteCount = cpu_to_le16(count);
1998 rc = SendReceiveBlockingLock(xid, tcon, (struct smb_hdr *) pSMB,
1999 (struct smb_hdr *) pSMB, &bytes_returned);
2000 cifs_small_buf_release(pSMB);
2002 rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *)pSMB,
2004 /* SMB buffer freed by function above */
2006 cifs_stats_inc(&tcon->num_locks);
2008 cFYI(1, "Send error in Lock = %d", rc);
2010 /* Note: On -EAGAIN error only caller can retry on handle based calls
2011 since file handle passed in no longer valid */
2016 CIFSSMBPosixLock(const int xid, struct cifsTconInfo *tcon,
2017 const __u16 smb_file_id, const int get_flag, const __u64 len,
2018 struct file_lock *pLockData, const __u16 lock_type,
2019 const bool waitFlag)
2021 struct smb_com_transaction2_sfi_req *pSMB = NULL;
2022 struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
2023 struct cifs_posix_lock *parm_data;
2026 int bytes_returned = 0;
2027 int resp_buf_type = 0;
2028 __u16 params, param_offset, offset, byte_count, count;
2031 cFYI(1, "Posix Lock");
2033 if (pLockData == NULL)
2036 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
2041 pSMBr = (struct smb_com_transaction2_sfi_rsp *)pSMB;
2044 pSMB->MaxSetupCount = 0;
2047 pSMB->Reserved2 = 0;
2048 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
2049 offset = param_offset + params;
2051 count = sizeof(struct cifs_posix_lock);
2052 pSMB->MaxParameterCount = cpu_to_le16(2);
2053 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB from sess */
2054 pSMB->SetupCount = 1;
2055 pSMB->Reserved3 = 0;
2057 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION);
2059 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
2060 byte_count = 3 /* pad */ + params + count;
2061 pSMB->DataCount = cpu_to_le16(count);
2062 pSMB->ParameterCount = cpu_to_le16(params);
2063 pSMB->TotalDataCount = pSMB->DataCount;
2064 pSMB->TotalParameterCount = pSMB->ParameterCount;
2065 pSMB->ParameterOffset = cpu_to_le16(param_offset);
2066 parm_data = (struct cifs_posix_lock *)
2067 (((char *) &pSMB->hdr.Protocol) + offset);
2069 parm_data->lock_type = cpu_to_le16(lock_type);
2071 timeout = CIFS_BLOCKING_OP; /* blocking operation, no timeout */
2072 parm_data->lock_flags = cpu_to_le16(1);
2073 pSMB->Timeout = cpu_to_le32(-1);
2077 parm_data->pid = cpu_to_le32(current->tgid);
2078 parm_data->start = cpu_to_le64(pLockData->fl_start);
2079 parm_data->length = cpu_to_le64(len); /* normalize negative numbers */
2081 pSMB->DataOffset = cpu_to_le16(offset);
2082 pSMB->Fid = smb_file_id;
2083 pSMB->InformationLevel = cpu_to_le16(SMB_SET_POSIX_LOCK);
2084 pSMB->Reserved4 = 0;
2085 inc_rfc1001_len(pSMB, byte_count);
2086 pSMB->ByteCount = cpu_to_le16(byte_count);
2088 rc = SendReceiveBlockingLock(xid, tcon, (struct smb_hdr *) pSMB,
2089 (struct smb_hdr *) pSMBr, &bytes_returned);
2091 iov[0].iov_base = (char *)pSMB;
2092 iov[0].iov_len = be32_to_cpu(pSMB->hdr.smb_buf_length) + 4;
2093 rc = SendReceive2(xid, tcon->ses, iov, 1 /* num iovecs */,
2094 &resp_buf_type, timeout);
2095 pSMB = NULL; /* request buf already freed by SendReceive2. Do
2096 not try to free it twice below on exit */
2097 pSMBr = (struct smb_com_transaction2_sfi_rsp *)iov[0].iov_base;
2101 cFYI(1, "Send error in Posix Lock = %d", rc);
2102 } else if (get_flag) {
2103 /* lock structure can be returned on get */
2106 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
2108 if (rc || get_bcc(&pSMBr->hdr) < sizeof(*parm_data)) {
2109 rc = -EIO; /* bad smb */
2112 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
2113 data_count = le16_to_cpu(pSMBr->t2.DataCount);
2114 if (data_count < sizeof(struct cifs_posix_lock)) {
2118 parm_data = (struct cifs_posix_lock *)
2119 ((char *)&pSMBr->hdr.Protocol + data_offset);
2120 if (parm_data->lock_type == __constant_cpu_to_le16(CIFS_UNLCK))
2121 pLockData->fl_type = F_UNLCK;
2123 if (parm_data->lock_type ==
2124 __constant_cpu_to_le16(CIFS_RDLCK))
2125 pLockData->fl_type = F_RDLCK;
2126 else if (parm_data->lock_type ==
2127 __constant_cpu_to_le16(CIFS_WRLCK))
2128 pLockData->fl_type = F_WRLCK;
2130 pLockData->fl_start = le64_to_cpu(parm_data->start);
2131 pLockData->fl_end = pLockData->fl_start +
2132 le64_to_cpu(parm_data->length) - 1;
2133 pLockData->fl_pid = le32_to_cpu(parm_data->pid);
2139 cifs_small_buf_release(pSMB);
2141 if (resp_buf_type == CIFS_SMALL_BUFFER)
2142 cifs_small_buf_release(iov[0].iov_base);
2143 else if (resp_buf_type == CIFS_LARGE_BUFFER)
2144 cifs_buf_release(iov[0].iov_base);
2146 /* Note: On -EAGAIN error only caller can retry on handle based calls
2147 since file handle passed in no longer valid */
2154 CIFSSMBClose(const int xid, struct cifsTconInfo *tcon, int smb_file_id)
2157 CLOSE_REQ *pSMB = NULL;
2158 cFYI(1, "In CIFSSMBClose");
2160 /* do not retry on dead session on close */
2161 rc = small_smb_init(SMB_COM_CLOSE, 3, tcon, (void **) &pSMB);
2167 pSMB->FileID = (__u16) smb_file_id;
2168 pSMB->LastWriteTime = 0xFFFFFFFF;
2169 pSMB->ByteCount = 0;
2170 rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0);
2171 cifs_stats_inc(&tcon->num_closes);
2174 /* EINTR is expected when user ctl-c to kill app */
2175 cERROR(1, "Send error in Close = %d", rc);
2179 /* Since session is dead, file will be closed on server already */
2187 CIFSSMBFlush(const int xid, struct cifsTconInfo *tcon, int smb_file_id)
2190 FLUSH_REQ *pSMB = NULL;
2191 cFYI(1, "In CIFSSMBFlush");
2193 rc = small_smb_init(SMB_COM_FLUSH, 1, tcon, (void **) &pSMB);
2197 pSMB->FileID = (__u16) smb_file_id;
2198 pSMB->ByteCount = 0;
2199 rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0);
2200 cifs_stats_inc(&tcon->num_flushes);
2202 cERROR(1, "Send error in Flush = %d", rc);
2208 CIFSSMBRename(const int xid, struct cifsTconInfo *tcon,
2209 const char *fromName, const char *toName,
2210 const struct nls_table *nls_codepage, int remap)
2213 RENAME_REQ *pSMB = NULL;
2214 RENAME_RSP *pSMBr = NULL;
2216 int name_len, name_len2;
2219 cFYI(1, "In CIFSSMBRename");
2221 rc = smb_init(SMB_COM_RENAME, 1, tcon, (void **) &pSMB,
2226 pSMB->BufferFormat = 0x04;
2227 pSMB->SearchAttributes =
2228 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
2231 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2233 cifsConvertToUCS((__le16 *) pSMB->OldFileName, fromName,
2234 PATH_MAX, nls_codepage, remap);
2235 name_len++; /* trailing null */
2237 pSMB->OldFileName[name_len] = 0x04; /* pad */
2238 /* protocol requires ASCII signature byte on Unicode string */
2239 pSMB->OldFileName[name_len + 1] = 0x00;
2241 cifsConvertToUCS((__le16 *)&pSMB->OldFileName[name_len + 2],
2242 toName, PATH_MAX, nls_codepage, remap);
2243 name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
2244 name_len2 *= 2; /* convert to bytes */
2245 } else { /* BB improve the check for buffer overruns BB */
2246 name_len = strnlen(fromName, PATH_MAX);
2247 name_len++; /* trailing null */
2248 strncpy(pSMB->OldFileName, fromName, name_len);
2249 name_len2 = strnlen(toName, PATH_MAX);
2250 name_len2++; /* trailing null */
2251 pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */
2252 strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2);
2253 name_len2++; /* trailing null */
2254 name_len2++; /* signature byte */
2257 count = 1 /* 1st signature byte */ + name_len + name_len2;
2258 inc_rfc1001_len(pSMB, count);
2259 pSMB->ByteCount = cpu_to_le16(count);
2261 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2262 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2263 cifs_stats_inc(&tcon->num_renames);
2265 cFYI(1, "Send error in rename = %d", rc);
2267 cifs_buf_release(pSMB);
2275 int CIFSSMBRenameOpenFile(const int xid, struct cifsTconInfo *pTcon,
2276 int netfid, const char *target_name,
2277 const struct nls_table *nls_codepage, int remap)
2279 struct smb_com_transaction2_sfi_req *pSMB = NULL;
2280 struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
2281 struct set_file_rename *rename_info;
2283 char dummy_string[30];
2285 int bytes_returned = 0;
2287 __u16 params, param_offset, offset, count, byte_count;
2289 cFYI(1, "Rename to File by handle");
2290 rc = smb_init(SMB_COM_TRANSACTION2, 15, pTcon, (void **) &pSMB,
2296 pSMB->MaxSetupCount = 0;
2300 pSMB->Reserved2 = 0;
2301 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
2302 offset = param_offset + params;
2304 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
2305 rename_info = (struct set_file_rename *) data_offset;
2306 pSMB->MaxParameterCount = cpu_to_le16(2);
2307 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB from sess */
2308 pSMB->SetupCount = 1;
2309 pSMB->Reserved3 = 0;
2310 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
2311 byte_count = 3 /* pad */ + params;
2312 pSMB->ParameterCount = cpu_to_le16(params);
2313 pSMB->TotalParameterCount = pSMB->ParameterCount;
2314 pSMB->ParameterOffset = cpu_to_le16(param_offset);
2315 pSMB->DataOffset = cpu_to_le16(offset);
2316 /* construct random name ".cifs_tmp<inodenum><mid>" */
2317 rename_info->overwrite = cpu_to_le32(1);
2318 rename_info->root_fid = 0;
2319 /* unicode only call */
2320 if (target_name == NULL) {
2321 sprintf(dummy_string, "cifs%x", pSMB->hdr.Mid);
2322 len_of_str = cifsConvertToUCS((__le16 *)rename_info->target_name,
2323 dummy_string, 24, nls_codepage, remap);
2325 len_of_str = cifsConvertToUCS((__le16 *)rename_info->target_name,
2326 target_name, PATH_MAX, nls_codepage,
2329 rename_info->target_name_len = cpu_to_le32(2 * len_of_str);
2330 count = 12 /* sizeof(struct set_file_rename) */ + (2 * len_of_str);
2331 byte_count += count;
2332 pSMB->DataCount = cpu_to_le16(count);
2333 pSMB->TotalDataCount = pSMB->DataCount;
2335 pSMB->InformationLevel =
2336 cpu_to_le16(SMB_SET_FILE_RENAME_INFORMATION);
2337 pSMB->Reserved4 = 0;
2338 inc_rfc1001_len(pSMB, byte_count);
2339 pSMB->ByteCount = cpu_to_le16(byte_count);
2340 rc = SendReceive(xid, pTcon->ses, (struct smb_hdr *) pSMB,
2341 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2342 cifs_stats_inc(&pTcon->num_t2renames);
2344 cFYI(1, "Send error in Rename (by file handle) = %d", rc);
2346 cifs_buf_release(pSMB);
2348 /* Note: On -EAGAIN error only caller can retry on handle based calls
2349 since file handle passed in no longer valid */
2355 CIFSSMBCopy(const int xid, struct cifsTconInfo *tcon, const char *fromName,
2356 const __u16 target_tid, const char *toName, const int flags,
2357 const struct nls_table *nls_codepage, int remap)
2360 COPY_REQ *pSMB = NULL;
2361 COPY_RSP *pSMBr = NULL;
2363 int name_len, name_len2;
2366 cFYI(1, "In CIFSSMBCopy");
2368 rc = smb_init(SMB_COM_COPY, 1, tcon, (void **) &pSMB,
2373 pSMB->BufferFormat = 0x04;
2374 pSMB->Tid2 = target_tid;
2376 pSMB->Flags = cpu_to_le16(flags & COPY_TREE);
2378 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2379 name_len = cifsConvertToUCS((__le16 *) pSMB->OldFileName,
2380 fromName, PATH_MAX, nls_codepage,
2382 name_len++; /* trailing null */
2384 pSMB->OldFileName[name_len] = 0x04; /* pad */
2385 /* protocol requires ASCII signature byte on Unicode string */
2386 pSMB->OldFileName[name_len + 1] = 0x00;
2388 cifsConvertToUCS((__le16 *)&pSMB->OldFileName[name_len + 2],
2389 toName, PATH_MAX, nls_codepage, remap);
2390 name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
2391 name_len2 *= 2; /* convert to bytes */
2392 } else { /* BB improve the check for buffer overruns BB */
2393 name_len = strnlen(fromName, PATH_MAX);
2394 name_len++; /* trailing null */
2395 strncpy(pSMB->OldFileName, fromName, name_len);
2396 name_len2 = strnlen(toName, PATH_MAX);
2397 name_len2++; /* trailing null */
2398 pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */
2399 strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2);
2400 name_len2++; /* trailing null */
2401 name_len2++; /* signature byte */
2404 count = 1 /* 1st signature byte */ + name_len + name_len2;
2405 inc_rfc1001_len(pSMB, count);
2406 pSMB->ByteCount = cpu_to_le16(count);
2408 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2409 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2411 cFYI(1, "Send error in copy = %d with %d files copied",
2412 rc, le16_to_cpu(pSMBr->CopyCount));
2414 cifs_buf_release(pSMB);
2423 CIFSUnixCreateSymLink(const int xid, struct cifsTconInfo *tcon,
2424 const char *fromName, const char *toName,
2425 const struct nls_table *nls_codepage)
2427 TRANSACTION2_SPI_REQ *pSMB = NULL;
2428 TRANSACTION2_SPI_RSP *pSMBr = NULL;
2431 int name_len_target;
2433 int bytes_returned = 0;
2434 __u16 params, param_offset, offset, byte_count;
2436 cFYI(1, "In Symlink Unix style");
2438 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2443 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2445 cifs_strtoUCS((__le16 *) pSMB->FileName, fromName, PATH_MAX
2446 /* find define for this maxpathcomponent */
2448 name_len++; /* trailing null */
2451 } else { /* BB improve the check for buffer overruns BB */
2452 name_len = strnlen(fromName, PATH_MAX);
2453 name_len++; /* trailing null */
2454 strncpy(pSMB->FileName, fromName, name_len);
2456 params = 6 + name_len;
2457 pSMB->MaxSetupCount = 0;
2461 pSMB->Reserved2 = 0;
2462 param_offset = offsetof(struct smb_com_transaction2_spi_req,
2463 InformationLevel) - 4;
2464 offset = param_offset + params;
2466 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
2467 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2469 cifs_strtoUCS((__le16 *) data_offset, toName, PATH_MAX
2470 /* find define for this maxpathcomponent */
2472 name_len_target++; /* trailing null */
2473 name_len_target *= 2;
2474 } else { /* BB improve the check for buffer overruns BB */
2475 name_len_target = strnlen(toName, PATH_MAX);
2476 name_len_target++; /* trailing null */
2477 strncpy(data_offset, toName, name_len_target);
2480 pSMB->MaxParameterCount = cpu_to_le16(2);
2481 /* BB find exact max on data count below from sess */
2482 pSMB->MaxDataCount = cpu_to_le16(1000);
2483 pSMB->SetupCount = 1;
2484 pSMB->Reserved3 = 0;
2485 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
2486 byte_count = 3 /* pad */ + params + name_len_target;
2487 pSMB->DataCount = cpu_to_le16(name_len_target);
2488 pSMB->ParameterCount = cpu_to_le16(params);
2489 pSMB->TotalDataCount = pSMB->DataCount;
2490 pSMB->TotalParameterCount = pSMB->ParameterCount;
2491 pSMB->ParameterOffset = cpu_to_le16(param_offset);
2492 pSMB->DataOffset = cpu_to_le16(offset);
2493 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_LINK);
2494 pSMB->Reserved4 = 0;
2495 inc_rfc1001_len(pSMB, byte_count);
2496 pSMB->ByteCount = cpu_to_le16(byte_count);
2497 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2498 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2499 cifs_stats_inc(&tcon->num_symlinks);
2501 cFYI(1, "Send error in SetPathInfo create symlink = %d", rc);
2503 cifs_buf_release(pSMB);
2506 goto createSymLinkRetry;
2512 CIFSUnixCreateHardLink(const int xid, struct cifsTconInfo *tcon,
2513 const char *fromName, const char *toName,
2514 const struct nls_table *nls_codepage, int remap)
2516 TRANSACTION2_SPI_REQ *pSMB = NULL;
2517 TRANSACTION2_SPI_RSP *pSMBr = NULL;
2520 int name_len_target;
2522 int bytes_returned = 0;
2523 __u16 params, param_offset, offset, byte_count;
2525 cFYI(1, "In Create Hard link Unix style");
2526 createHardLinkRetry:
2527 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2532 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2533 name_len = cifsConvertToUCS((__le16 *) pSMB->FileName, toName,
2534 PATH_MAX, nls_codepage, remap);
2535 name_len++; /* trailing null */
2538 } else { /* BB improve the check for buffer overruns BB */
2539 name_len = strnlen(toName, PATH_MAX);
2540 name_len++; /* trailing null */
2541 strncpy(pSMB->FileName, toName, name_len);
2543 params = 6 + name_len;
2544 pSMB->MaxSetupCount = 0;
2548 pSMB->Reserved2 = 0;
2549 param_offset = offsetof(struct smb_com_transaction2_spi_req,
2550 InformationLevel) - 4;
2551 offset = param_offset + params;
2553 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
2554 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2556 cifsConvertToUCS((__le16 *) data_offset, fromName, PATH_MAX,
2557 nls_codepage, remap);
2558 name_len_target++; /* trailing null */
2559 name_len_target *= 2;
2560 } else { /* BB improve the check for buffer overruns BB */
2561 name_len_target = strnlen(fromName, PATH_MAX);
2562 name_len_target++; /* trailing null */
2563 strncpy(data_offset, fromName, name_len_target);
2566 pSMB->MaxParameterCount = cpu_to_le16(2);
2567 /* BB find exact max on data count below from sess*/
2568 pSMB->MaxDataCount = cpu_to_le16(1000);
2569 pSMB->SetupCount = 1;
2570 pSMB->Reserved3 = 0;
2571 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
2572 byte_count = 3 /* pad */ + params + name_len_target;
2573 pSMB->ParameterCount = cpu_to_le16(params);
2574 pSMB->TotalParameterCount = pSMB->ParameterCount;
2575 pSMB->DataCount = cpu_to_le16(name_len_target);
2576 pSMB->TotalDataCount = pSMB->DataCount;
2577 pSMB->ParameterOffset = cpu_to_le16(param_offset);
2578 pSMB->DataOffset = cpu_to_le16(offset);
2579 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_HLINK);
2580 pSMB->Reserved4 = 0;
2581 inc_rfc1001_len(pSMB, byte_count);
2582 pSMB->ByteCount = cpu_to_le16(byte_count);
2583 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2584 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2585 cifs_stats_inc(&tcon->num_hardlinks);
2587 cFYI(1, "Send error in SetPathInfo (hard link) = %d", rc);
2589 cifs_buf_release(pSMB);
2591 goto createHardLinkRetry;
2597 CIFSCreateHardLink(const int xid, struct cifsTconInfo *tcon,
2598 const char *fromName, const char *toName,
2599 const struct nls_table *nls_codepage, int remap)
2602 NT_RENAME_REQ *pSMB = NULL;
2603 RENAME_RSP *pSMBr = NULL;
2605 int name_len, name_len2;
2608 cFYI(1, "In CIFSCreateHardLink");
2609 winCreateHardLinkRetry:
2611 rc = smb_init(SMB_COM_NT_RENAME, 4, tcon, (void **) &pSMB,
2616 pSMB->SearchAttributes =
2617 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
2619 pSMB->Flags = cpu_to_le16(CREATE_HARD_LINK);
2620 pSMB->ClusterCount = 0;
2622 pSMB->BufferFormat = 0x04;
2624 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2626 cifsConvertToUCS((__le16 *) pSMB->OldFileName, fromName,
2627 PATH_MAX, nls_codepage, remap);
2628 name_len++; /* trailing null */
2631 /* protocol specifies ASCII buffer format (0x04) for unicode */
2632 pSMB->OldFileName[name_len] = 0x04;
2633 pSMB->OldFileName[name_len + 1] = 0x00; /* pad */
2635 cifsConvertToUCS((__le16 *)&pSMB->OldFileName[name_len + 2],
2636 toName, PATH_MAX, nls_codepage, remap);
2637 name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
2638 name_len2 *= 2; /* convert to bytes */
2639 } else { /* BB improve the check for buffer overruns BB */
2640 name_len = strnlen(fromName, PATH_MAX);
2641 name_len++; /* trailing null */
2642 strncpy(pSMB->OldFileName, fromName, name_len);
2643 name_len2 = strnlen(toName, PATH_MAX);
2644 name_len2++; /* trailing null */
2645 pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */
2646 strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2);
2647 name_len2++; /* trailing null */
2648 name_len2++; /* signature byte */
2651 count = 1 /* string type byte */ + name_len + name_len2;
2652 inc_rfc1001_len(pSMB, count);
2653 pSMB->ByteCount = cpu_to_le16(count);
2655 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2656 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2657 cifs_stats_inc(&tcon->num_hardlinks);
2659 cFYI(1, "Send error in hard link (NT rename) = %d", rc);
2661 cifs_buf_release(pSMB);
2663 goto winCreateHardLinkRetry;
2669 CIFSSMBUnixQuerySymLink(const int xid, struct cifsTconInfo *tcon,
2670 const unsigned char *searchName, char **symlinkinfo,
2671 const struct nls_table *nls_codepage)
2673 /* SMB_QUERY_FILE_UNIX_LINK */
2674 TRANSACTION2_QPI_REQ *pSMB = NULL;
2675 TRANSACTION2_QPI_RSP *pSMBr = NULL;
2679 __u16 params, byte_count;
2682 cFYI(1, "In QPathSymLinkInfo (Unix) for path %s", searchName);
2685 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2690 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2692 cifs_strtoUCS((__le16 *) pSMB->FileName, searchName,
2693 PATH_MAX, nls_codepage);
2694 name_len++; /* trailing null */
2696 } else { /* BB improve the check for buffer overruns BB */
2697 name_len = strnlen(searchName, PATH_MAX);
2698 name_len++; /* trailing null */
2699 strncpy(pSMB->FileName, searchName, name_len);
2702 params = 2 /* level */ + 4 /* rsrvd */ + name_len /* incl null */ ;
2703 pSMB->TotalDataCount = 0;
2704 pSMB->MaxParameterCount = cpu_to_le16(2);
2705 pSMB->MaxDataCount = cpu_to_le16(CIFSMaxBufSize);
2706 pSMB->MaxSetupCount = 0;
2710 pSMB->Reserved2 = 0;
2711 pSMB->ParameterOffset = cpu_to_le16(offsetof(
2712 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
2713 pSMB->DataCount = 0;
2714 pSMB->DataOffset = 0;
2715 pSMB->SetupCount = 1;
2716 pSMB->Reserved3 = 0;
2717 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
2718 byte_count = params + 1 /* pad */ ;
2719 pSMB->TotalParameterCount = cpu_to_le16(params);
2720 pSMB->ParameterCount = pSMB->TotalParameterCount;
2721 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_LINK);
2722 pSMB->Reserved4 = 0;
2723 inc_rfc1001_len(pSMB, byte_count);
2724 pSMB->ByteCount = cpu_to_le16(byte_count);
2726 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2727 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2729 cFYI(1, "Send error in QuerySymLinkInfo = %d", rc);
2731 /* decode response */
2733 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
2734 /* BB also check enough total bytes returned */
2735 if (rc || get_bcc(&pSMBr->hdr) < 2)
2739 u16 count = le16_to_cpu(pSMBr->t2.DataCount);
2741 data_start = ((char *) &pSMBr->hdr.Protocol) +
2742 le16_to_cpu(pSMBr->t2.DataOffset);
2744 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
2749 /* BB FIXME investigate remapping reserved chars here */
2750 *symlinkinfo = cifs_strndup_from_ucs(data_start, count,
2751 is_unicode, nls_codepage);
2756 cifs_buf_release(pSMB);
2758 goto querySymLinkRetry;
2762 #ifdef CONFIG_CIFS_SYMLINK_EXPERIMENTAL
2764 * Recent Windows versions now create symlinks more frequently
2765 * and they use the "reparse point" mechanism below. We can of course
2766 * do symlinks nicely to Samba and other servers which support the
2767 * CIFS Unix Extensions and we can also do SFU symlinks and "client only"
2768 * "MF" symlinks optionally, but for recent Windows we really need to
2769 * reenable the code below and fix the cifs_symlink callers to handle this.
2770 * In the interim this code has been moved to its own config option so
2771 * it is not compiled in by default until callers fixed up and more tested.
2774 CIFSSMBQueryReparseLinkInfo(const int xid, struct cifsTconInfo *tcon,
2775 const unsigned char *searchName,
2776 char *symlinkinfo, const int buflen, __u16 fid,
2777 const struct nls_table *nls_codepage)
2781 struct smb_com_transaction_ioctl_req *pSMB;
2782 struct smb_com_transaction_ioctl_rsp *pSMBr;
2784 cFYI(1, "In Windows reparse style QueryLink for path %s", searchName);
2785 rc = smb_init(SMB_COM_NT_TRANSACT, 23, tcon, (void **) &pSMB,
2790 pSMB->TotalParameterCount = 0 ;
2791 pSMB->TotalDataCount = 0;
2792 pSMB->MaxParameterCount = cpu_to_le32(2);
2793 /* BB find exact data count max from sess structure BB */
2794 pSMB->MaxDataCount = cpu_to_le32((tcon->ses->server->maxBuf -
2795 MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
2796 pSMB->MaxSetupCount = 4;
2798 pSMB->ParameterOffset = 0;
2799 pSMB->DataCount = 0;
2800 pSMB->DataOffset = 0;
2801 pSMB->SetupCount = 4;
2802 pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_IOCTL);
2803 pSMB->ParameterCount = pSMB->TotalParameterCount;
2804 pSMB->FunctionCode = cpu_to_le32(FSCTL_GET_REPARSE_POINT);
2805 pSMB->IsFsctl = 1; /* FSCTL */
2806 pSMB->IsRootFlag = 0;
2807 pSMB->Fid = fid; /* file handle always le */
2808 pSMB->ByteCount = 0;
2810 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2811 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2813 cFYI(1, "Send error in QueryReparseLinkInfo = %d", rc);
2814 } else { /* decode response */
2815 __u32 data_offset = le32_to_cpu(pSMBr->DataOffset);
2816 __u32 data_count = le32_to_cpu(pSMBr->DataCount);
2817 if (get_bcc(&pSMBr->hdr) < 2 || data_offset > 512) {
2818 /* BB also check enough total bytes returned */
2819 rc = -EIO; /* bad smb */
2822 if (data_count && (data_count < 2048)) {
2823 char *end_of_smb = 2 /* sizeof byte count */ +
2824 get_bcc(&pSMBr->hdr) + (char *)&pSMBr->ByteCount;
2826 struct reparse_data *reparse_buf =
2827 (struct reparse_data *)
2828 ((char *)&pSMBr->hdr.Protocol
2830 if ((char *)reparse_buf >= end_of_smb) {
2834 if ((reparse_buf->LinkNamesBuf +
2835 reparse_buf->TargetNameOffset +
2836 reparse_buf->TargetNameLen) > end_of_smb) {
2837 cFYI(1, "reparse buf beyond SMB");
2842 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
2843 cifs_from_ucs2(symlinkinfo, (__le16 *)
2844 (reparse_buf->LinkNamesBuf +
2845 reparse_buf->TargetNameOffset),
2847 reparse_buf->TargetNameLen,
2849 } else { /* ASCII names */
2850 strncpy(symlinkinfo,
2851 reparse_buf->LinkNamesBuf +
2852 reparse_buf->TargetNameOffset,
2853 min_t(const int, buflen,
2854 reparse_buf->TargetNameLen));
2858 cFYI(1, "Invalid return data count on "
2859 "get reparse info ioctl");
2861 symlinkinfo[buflen] = 0; /* just in case so the caller
2862 does not go off the end of the buffer */
2863 cFYI(1, "readlink result - %s", symlinkinfo);
2867 cifs_buf_release(pSMB);
2869 /* Note: On -EAGAIN error only caller can retry on handle based calls
2870 since file handle passed in no longer valid */
2874 #endif /* CIFS_SYMLINK_EXPERIMENTAL */ /* BB temporarily unused */
2876 #ifdef CONFIG_CIFS_POSIX
2878 /*Convert an Access Control Entry from wire format to local POSIX xattr format*/
2879 static void cifs_convert_ace(posix_acl_xattr_entry *ace,
2880 struct cifs_posix_ace *cifs_ace)
2882 /* u8 cifs fields do not need le conversion */
2883 ace->e_perm = cpu_to_le16(cifs_ace->cifs_e_perm);
2884 ace->e_tag = cpu_to_le16(cifs_ace->cifs_e_tag);
2885 ace->e_id = cpu_to_le32(le64_to_cpu(cifs_ace->cifs_uid));
2886 /* cFYI(1, "perm %d tag %d id %d",ace->e_perm,ace->e_tag,ace->e_id); */
2891 /* Convert ACL from CIFS POSIX wire format to local Linux POSIX ACL xattr */
2892 static int cifs_copy_posix_acl(char *trgt, char *src, const int buflen,
2893 const int acl_type, const int size_of_data_area)
2898 struct cifs_posix_ace *pACE;
2899 struct cifs_posix_acl *cifs_acl = (struct cifs_posix_acl *)src;
2900 posix_acl_xattr_header *local_acl = (posix_acl_xattr_header *)trgt;
2902 if (le16_to_cpu(cifs_acl->version) != CIFS_ACL_VERSION)
2905 if (acl_type & ACL_TYPE_ACCESS) {
2906 count = le16_to_cpu(cifs_acl->access_entry_count);
2907 pACE = &cifs_acl->ace_array[0];
2908 size = sizeof(struct cifs_posix_acl);
2909 size += sizeof(struct cifs_posix_ace) * count;
2910 /* check if we would go beyond end of SMB */
2911 if (size_of_data_area < size) {
2912 cFYI(1, "bad CIFS POSIX ACL size %d vs. %d",
2913 size_of_data_area, size);
2916 } else if (acl_type & ACL_TYPE_DEFAULT) {
2917 count = le16_to_cpu(cifs_acl->access_entry_count);
2918 size = sizeof(struct cifs_posix_acl);
2919 size += sizeof(struct cifs_posix_ace) * count;
2920 /* skip past access ACEs to get to default ACEs */
2921 pACE = &cifs_acl->ace_array[count];
2922 count = le16_to_cpu(cifs_acl->default_entry_count);
2923 size += sizeof(struct cifs_posix_ace) * count;
2924 /* check if we would go beyond end of SMB */
2925 if (size_of_data_area < size)
2932 size = posix_acl_xattr_size(count);
2933 if ((buflen == 0) || (local_acl == NULL)) {
2934 /* used to query ACL EA size */
2935 } else if (size > buflen) {
2937 } else /* buffer big enough */ {
2938 local_acl->a_version = cpu_to_le32(POSIX_ACL_XATTR_VERSION);
2939 for (i = 0; i < count ; i++) {
2940 cifs_convert_ace(&local_acl->a_entries[i], pACE);
2947 static __u16 convert_ace_to_cifs_ace(struct cifs_posix_ace *cifs_ace,
2948 const posix_acl_xattr_entry *local_ace)
2950 __u16 rc = 0; /* 0 = ACL converted ok */
2952 cifs_ace->cifs_e_perm = le16_to_cpu(local_ace->e_perm);
2953 cifs_ace->cifs_e_tag = le16_to_cpu(local_ace->e_tag);
2954 /* BB is there a better way to handle the large uid? */
2955 if (local_ace->e_id == cpu_to_le32(-1)) {
2956 /* Probably no need to le convert -1 on any arch but can not hurt */
2957 cifs_ace->cifs_uid = cpu_to_le64(-1);
2959 cifs_ace->cifs_uid = cpu_to_le64(le32_to_cpu(local_ace->e_id));
2960 /*cFYI(1, "perm %d tag %d id %d",ace->e_perm,ace->e_tag,ace->e_id);*/
2964 /* Convert ACL from local Linux POSIX xattr to CIFS POSIX ACL wire format */
2965 static __u16 ACL_to_cifs_posix(char *parm_data, const char *pACL,
2966 const int buflen, const int acl_type)
2969 struct cifs_posix_acl *cifs_acl = (struct cifs_posix_acl *)parm_data;
2970 posix_acl_xattr_header *local_acl = (posix_acl_xattr_header *)pACL;
2974 if ((buflen == 0) || (pACL == NULL) || (cifs_acl == NULL))
2977 count = posix_acl_xattr_count((size_t)buflen);
2978 cFYI(1, "setting acl with %d entries from buf of length %d and "
2980 count, buflen, le32_to_cpu(local_acl->a_version));
2981 if (le32_to_cpu(local_acl->a_version) != 2) {
2982 cFYI(1, "unknown POSIX ACL version %d",
2983 le32_to_cpu(local_acl->a_version));
2986 cifs_acl->version = cpu_to_le16(1);
2987 if (acl_type == ACL_TYPE_ACCESS)
2988 cifs_acl->access_entry_count = cpu_to_le16(count);
2989 else if (acl_type == ACL_TYPE_DEFAULT)
2990 cifs_acl->default_entry_count = cpu_to_le16(count);
2992 cFYI(1, "unknown ACL type %d", acl_type);
2995 for (i = 0; i < count; i++) {
2996 rc = convert_ace_to_cifs_ace(&cifs_acl->ace_array[i],
2997 &local_acl->a_entries[i]);
2999 /* ACE not converted */
3004 rc = (__u16)(count * sizeof(struct cifs_posix_ace));
3005 rc += sizeof(struct cifs_posix_acl);
3006 /* BB add check to make sure ACL does not overflow SMB */
3012 CIFSSMBGetPosixACL(const int xid, struct cifsTconInfo *tcon,
3013 const unsigned char *searchName,
3014 char *acl_inf, const int buflen, const int acl_type,
3015 const struct nls_table *nls_codepage, int remap)
3017 /* SMB_QUERY_POSIX_ACL */
3018 TRANSACTION2_QPI_REQ *pSMB = NULL;
3019 TRANSACTION2_QPI_RSP *pSMBr = NULL;
3023 __u16 params, byte_count;
3025 cFYI(1, "In GetPosixACL (Unix) for path %s", searchName);
3028 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3033 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3035 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
3036 PATH_MAX, nls_codepage, remap);
3037 name_len++; /* trailing null */
3039 pSMB->FileName[name_len] = 0;
3040 pSMB->FileName[name_len+1] = 0;
3041 } else { /* BB improve the check for buffer overruns BB */
3042 name_len = strnlen(searchName, PATH_MAX);
3043 name_len++; /* trailing null */
3044 strncpy(pSMB->FileName, searchName, name_len);
3047 params = 2 /* level */ + 4 /* rsrvd */ + name_len /* incl null */ ;
3048 pSMB->TotalDataCount = 0;
3049 pSMB->MaxParameterCount = cpu_to_le16(2);
3050 /* BB find exact max data count below from sess structure BB */
3051 pSMB->MaxDataCount = cpu_to_le16(4000);
3052 pSMB->MaxSetupCount = 0;
3056 pSMB->Reserved2 = 0;
3057 pSMB->ParameterOffset = cpu_to_le16(
3058 offsetof(struct smb_com_transaction2_qpi_req,
3059 InformationLevel) - 4);
3060 pSMB->DataCount = 0;
3061 pSMB->DataOffset = 0;
3062 pSMB->SetupCount = 1;
3063 pSMB->Reserved3 = 0;
3064 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
3065 byte_count = params + 1 /* pad */ ;
3066 pSMB->TotalParameterCount = cpu_to_le16(params);
3067 pSMB->ParameterCount = pSMB->TotalParameterCount;
3068 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_POSIX_ACL);
3069 pSMB->Reserved4 = 0;
3070 inc_rfc1001_len(pSMB, byte_count);
3071 pSMB->ByteCount = cpu_to_le16(byte_count);
3073 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3074 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3075 cifs_stats_inc(&tcon->num_acl_get);
3077 cFYI(1, "Send error in Query POSIX ACL = %d", rc);
3079 /* decode response */
3081 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3082 /* BB also check enough total bytes returned */
3083 if (rc || get_bcc(&pSMBr->hdr) < 2)
3084 rc = -EIO; /* bad smb */
3086 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3087 __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
3088 rc = cifs_copy_posix_acl(acl_inf,
3089 (char *)&pSMBr->hdr.Protocol+data_offset,
3090 buflen, acl_type, count);
3093 cifs_buf_release(pSMB);
3100 CIFSSMBSetPosixACL(const int xid, struct cifsTconInfo *tcon,
3101 const unsigned char *fileName,
3102 const char *local_acl, const int buflen,
3104 const struct nls_table *nls_codepage, int remap)
3106 struct smb_com_transaction2_spi_req *pSMB = NULL;
3107 struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
3111 int bytes_returned = 0;
3112 __u16 params, byte_count, data_count, param_offset, offset;
3114 cFYI(1, "In SetPosixACL (Unix) for path %s", fileName);
3116 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3120 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3122 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
3123 PATH_MAX, nls_codepage, remap);
3124 name_len++; /* trailing null */
3126 } else { /* BB improve the check for buffer overruns BB */
3127 name_len = strnlen(fileName, PATH_MAX);
3128 name_len++; /* trailing null */
3129 strncpy(pSMB->FileName, fileName, name_len);
3131 params = 6 + name_len;
3132 pSMB->MaxParameterCount = cpu_to_le16(2);
3133 /* BB find max SMB size from sess */
3134 pSMB->MaxDataCount = cpu_to_le16(1000);
3135 pSMB->MaxSetupCount = 0;
3139 pSMB->Reserved2 = 0;
3140 param_offset = offsetof(struct smb_com_transaction2_spi_req,
3141 InformationLevel) - 4;
3142 offset = param_offset + params;
3143 parm_data = ((char *) &pSMB->hdr.Protocol) + offset;
3144 pSMB->ParameterOffset = cpu_to_le16(param_offset);
3146 /* convert to on the wire format for POSIX ACL */
3147 data_count = ACL_to_cifs_posix(parm_data, local_acl, buflen, acl_type);
3149 if (data_count == 0) {
3151 goto setACLerrorExit;
3153 pSMB->DataOffset = cpu_to_le16(offset);
3154 pSMB->SetupCount = 1;
3155 pSMB->Reserved3 = 0;
3156 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
3157 pSMB->InformationLevel = cpu_to_le16(SMB_SET_POSIX_ACL);
3158 byte_count = 3 /* pad */ + params + data_count;
3159 pSMB->DataCount = cpu_to_le16(data_count);
3160 pSMB->TotalDataCount = pSMB->DataCount;
3161 pSMB->ParameterCount = cpu_to_le16(params);
3162 pSMB->TotalParameterCount = pSMB->ParameterCount;
3163 pSMB->Reserved4 = 0;
3164 inc_rfc1001_len(pSMB, byte_count);
3165 pSMB->ByteCount = cpu_to_le16(byte_count);
3166 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3167 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3169 cFYI(1, "Set POSIX ACL returned %d", rc);
3172 cifs_buf_release(pSMB);
3178 /* BB fix tabs in this function FIXME BB */
3180 CIFSGetExtAttr(const int xid, struct cifsTconInfo *tcon,
3181 const int netfid, __u64 *pExtAttrBits, __u64 *pMask)
3184 struct smb_t2_qfi_req *pSMB = NULL;
3185 struct smb_t2_qfi_rsp *pSMBr = NULL;
3187 __u16 params, byte_count;
3189 cFYI(1, "In GetExtAttr");
3194 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3199 params = 2 /* level */ + 2 /* fid */;
3200 pSMB->t2.TotalDataCount = 0;
3201 pSMB->t2.MaxParameterCount = cpu_to_le16(4);
3202 /* BB find exact max data count below from sess structure BB */
3203 pSMB->t2.MaxDataCount = cpu_to_le16(4000);
3204 pSMB->t2.MaxSetupCount = 0;
3205 pSMB->t2.Reserved = 0;
3207 pSMB->t2.Timeout = 0;
3208 pSMB->t2.Reserved2 = 0;
3209 pSMB->t2.ParameterOffset = cpu_to_le16(offsetof(struct smb_t2_qfi_req,
3211 pSMB->t2.DataCount = 0;
3212 pSMB->t2.DataOffset = 0;
3213 pSMB->t2.SetupCount = 1;
3214 pSMB->t2.Reserved3 = 0;
3215 pSMB->t2.SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION);
3216 byte_count = params + 1 /* pad */ ;
3217 pSMB->t2.TotalParameterCount = cpu_to_le16(params);
3218 pSMB->t2.ParameterCount = pSMB->t2.TotalParameterCount;
3219 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_ATTR_FLAGS);
3222 inc_rfc1001_len(pSMB, byte_count);
3223 pSMB->t2.ByteCount = cpu_to_le16(byte_count);
3225 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3226 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3228 cFYI(1, "error %d in GetExtAttr", rc);
3230 /* decode response */
3231 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3232 /* BB also check enough total bytes returned */
3233 if (rc || get_bcc(&pSMBr->hdr) < 2)
3234 /* If rc should we check for EOPNOSUPP and
3235 disable the srvino flag? or in caller? */
3236 rc = -EIO; /* bad smb */
3238 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3239 __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
3240 struct file_chattr_info *pfinfo;
3241 /* BB Do we need a cast or hash here ? */
3243 cFYI(1, "Illegal size ret in GetExtAttr");
3247 pfinfo = (struct file_chattr_info *)
3248 (data_offset + (char *) &pSMBr->hdr.Protocol);
3249 *pExtAttrBits = le64_to_cpu(pfinfo->mode);
3250 *pMask = le64_to_cpu(pfinfo->mask);
3254 cifs_buf_release(pSMB);
3256 goto GetExtAttrRetry;
3260 #endif /* CONFIG_POSIX */
3262 #ifdef CONFIG_CIFS_ACL
3264 * Initialize NT TRANSACT SMB into small smb request buffer. This assumes that
3265 * all NT TRANSACTS that we init here have total parm and data under about 400
3266 * bytes (to fit in small cifs buffer size), which is the case so far, it
3267 * easily fits. NB: Setup words themselves and ByteCount MaxSetupCount (size of
3268 * returned setup area) and MaxParameterCount (returned parms size) must be set
3272 smb_init_nttransact(const __u16 sub_command, const int setup_count,
3273 const int parm_len, struct cifsTconInfo *tcon,
3278 struct smb_com_ntransact_req *pSMB;
3280 rc = small_smb_init(SMB_COM_NT_TRANSACT, 19 + setup_count, tcon,
3284 *ret_buf = (void *)pSMB;
3286 pSMB->TotalParameterCount = cpu_to_le32(parm_len);
3287 pSMB->TotalDataCount = 0;
3288 pSMB->MaxDataCount = cpu_to_le32((tcon->ses->server->maxBuf -
3289 MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
3290 pSMB->ParameterCount = pSMB->TotalParameterCount;
3291 pSMB->DataCount = pSMB->TotalDataCount;
3292 temp_offset = offsetof(struct smb_com_ntransact_req, Parms) +
3293 (setup_count * 2) - 4 /* for rfc1001 length itself */;
3294 pSMB->ParameterOffset = cpu_to_le32(temp_offset);
3295 pSMB->DataOffset = cpu_to_le32(temp_offset + parm_len);
3296 pSMB->SetupCount = setup_count; /* no need to le convert byte fields */
3297 pSMB->SubCommand = cpu_to_le16(sub_command);
3302 validate_ntransact(char *buf, char **ppparm, char **ppdata,
3303 __u32 *pparmlen, __u32 *pdatalen)
3306 __u32 data_count, data_offset, parm_count, parm_offset;
3307 struct smb_com_ntransact_rsp *pSMBr;
3316 pSMBr = (struct smb_com_ntransact_rsp *)buf;
3318 bcc = get_bcc(&pSMBr->hdr);
3319 end_of_smb = 2 /* sizeof byte count */ + bcc +
3320 (char *)&pSMBr->ByteCount;
3322 data_offset = le32_to_cpu(pSMBr->DataOffset);
3323 data_count = le32_to_cpu(pSMBr->DataCount);
3324 parm_offset = le32_to_cpu(pSMBr->ParameterOffset);
3325 parm_count = le32_to_cpu(pSMBr->ParameterCount);
3327 *ppparm = (char *)&pSMBr->hdr.Protocol + parm_offset;
3328 *ppdata = (char *)&pSMBr->hdr.Protocol + data_offset;
3330 /* should we also check that parm and data areas do not overlap? */
3331 if (*ppparm > end_of_smb) {
3332 cFYI(1, "parms start after end of smb");
3334 } else if (parm_count + *ppparm > end_of_smb) {
3335 cFYI(1, "parm end after end of smb");
3337 } else if (*ppdata > end_of_smb) {
3338 cFYI(1, "data starts after end of smb");
3340 } else if (data_count + *ppdata > end_of_smb) {
3341 cFYI(1, "data %p + count %d (%p) past smb end %p start %p",
3342 *ppdata, data_count, (data_count + *ppdata),
3345 } else if (parm_count + data_count > bcc) {
3346 cFYI(1, "parm count and data count larger than SMB");
3349 *pdatalen = data_count;
3350 *pparmlen = parm_count;
3354 /* Get Security Descriptor (by handle) from remote server for a file or dir */
3356 CIFSSMBGetCIFSACL(const int xid, struct cifsTconInfo *tcon, __u16 fid,
3357 struct cifs_ntsd **acl_inf, __u32 *pbuflen)
3361 QUERY_SEC_DESC_REQ *pSMB;
3364 cFYI(1, "GetCifsACL");
3369 rc = smb_init_nttransact(NT_TRANSACT_QUERY_SECURITY_DESC, 0,
3370 8 /* parm len */, tcon, (void **) &pSMB);
3374 pSMB->MaxParameterCount = cpu_to_le32(4);
3375 /* BB TEST with big acls that might need to be e.g. larger than 16K */
3376 pSMB->MaxSetupCount = 0;
3377 pSMB->Fid = fid; /* file handle always le */
3378 pSMB->AclFlags = cpu_to_le32(CIFS_ACL_OWNER | CIFS_ACL_GROUP |
3380 pSMB->ByteCount = cpu_to_le16(11); /* 3 bytes pad + 8 bytes parm */
3381 inc_rfc1001_len(pSMB, 11);
3382 iov[0].iov_base = (char *)pSMB;
3383 iov[0].iov_len = be32_to_cpu(pSMB->hdr.smb_buf_length) + 4;
3385 rc = SendReceive2(xid, tcon->ses, iov, 1 /* num iovec */, &buf_type,
3387 cifs_stats_inc(&tcon->num_acl_get);
3389 cFYI(1, "Send error in QuerySecDesc = %d", rc);
3390 } else { /* decode response */
3394 struct smb_com_ntransact_rsp *pSMBr;
3397 /* validate_nttransact */
3398 rc = validate_ntransact(iov[0].iov_base, (char **)&parm,
3399 &pdata, &parm_len, pbuflen);
3402 pSMBr = (struct smb_com_ntransact_rsp *)iov[0].iov_base;
3404 cFYI(1, "smb %p parm %p data %p", pSMBr, parm, *acl_inf);
3406 if (le32_to_cpu(pSMBr->ParameterCount) != 4) {
3407 rc = -EIO; /* bad smb */
3412 /* BB check that data area is minimum length and as big as acl_len */
3414 acl_len = le32_to_cpu(*parm);
3415 if (acl_len != *pbuflen) {
3416 cERROR(1, "acl length %d does not match %d",
3418 if (*pbuflen > acl_len)
3422 /* check if buffer is big enough for the acl
3423 header followed by the smallest SID */
3424 if ((*pbuflen < sizeof(struct cifs_ntsd) + 8) ||
3425 (*pbuflen >= 64 * 1024)) {
3426 cERROR(1, "bad acl length %d", *pbuflen);
3430 *acl_inf = kmalloc(*pbuflen, GFP_KERNEL);
3431 if (*acl_inf == NULL) {
3435 memcpy(*acl_inf, pdata, *pbuflen);
3439 if (buf_type == CIFS_SMALL_BUFFER)
3440 cifs_small_buf_release(iov[0].iov_base);
3441 else if (buf_type == CIFS_LARGE_BUFFER)
3442 cifs_buf_release(iov[0].iov_base);
3443 /* cifs_small_buf_release(pSMB); */ /* Freed earlier now in SendReceive2 */
3448 CIFSSMBSetCIFSACL(const int xid, struct cifsTconInfo *tcon, __u16 fid,
3449 struct cifs_ntsd *pntsd, __u32 acllen)
3451 __u16 byte_count, param_count, data_count, param_offset, data_offset;
3453 int bytes_returned = 0;
3454 SET_SEC_DESC_REQ *pSMB = NULL;
3455 NTRANSACT_RSP *pSMBr = NULL;
3458 rc = smb_init(SMB_COM_NT_TRANSACT, 19, tcon, (void **) &pSMB,
3463 pSMB->MaxSetupCount = 0;
3467 param_offset = offsetof(struct smb_com_transaction_ssec_req, Fid) - 4;
3468 data_count = acllen;
3469 data_offset = param_offset + param_count;
3470 byte_count = 3 /* pad */ + param_count;
3472 pSMB->DataCount = cpu_to_le32(data_count);
3473 pSMB->TotalDataCount = pSMB->DataCount;
3474 pSMB->MaxParameterCount = cpu_to_le32(4);
3475 pSMB->MaxDataCount = cpu_to_le32(16384);
3476 pSMB->ParameterCount = cpu_to_le32(param_count);
3477 pSMB->ParameterOffset = cpu_to_le32(param_offset);
3478 pSMB->TotalParameterCount = pSMB->ParameterCount;
3479 pSMB->DataOffset = cpu_to_le32(data_offset);
3480 pSMB->SetupCount = 0;
3481 pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_SET_SECURITY_DESC);
3482 pSMB->ByteCount = cpu_to_le16(byte_count+data_count);
3484 pSMB->Fid = fid; /* file handle always le */
3485 pSMB->Reserved2 = 0;
3486 pSMB->AclFlags = cpu_to_le32(CIFS_ACL_DACL);
3488 if (pntsd && acllen) {
3489 memcpy((char *) &pSMBr->hdr.Protocol + data_offset,
3492 inc_rfc1001_len(pSMB, byte_count + data_count);
3494 inc_rfc1001_len(pSMB, byte_count);
3496 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3497 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3499 cFYI(1, "SetCIFSACL bytes_returned: %d, rc: %d", bytes_returned, rc);
3501 cFYI(1, "Set CIFS ACL returned %d", rc);
3502 cifs_buf_release(pSMB);
3505 goto setCifsAclRetry;
3510 #endif /* CONFIG_CIFS_ACL */
3512 /* Legacy Query Path Information call for lookup to old servers such
3514 int SMBQueryInformation(const int xid, struct cifsTconInfo *tcon,
3515 const unsigned char *searchName,
3516 FILE_ALL_INFO *pFinfo,
3517 const struct nls_table *nls_codepage, int remap)
3519 QUERY_INFORMATION_REQ *pSMB;
3520 QUERY_INFORMATION_RSP *pSMBr;
3525 cFYI(1, "In SMBQPath path %s", searchName);
3527 rc = smb_init(SMB_COM_QUERY_INFORMATION, 0, tcon, (void **) &pSMB,
3532 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3534 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
3535 PATH_MAX, nls_codepage, remap);
3536 name_len++; /* trailing null */
3539 name_len = strnlen(searchName, PATH_MAX);
3540 name_len++; /* trailing null */
3541 strncpy(pSMB->FileName, searchName, name_len);
3543 pSMB->BufferFormat = 0x04;
3544 name_len++; /* account for buffer type byte */
3545 inc_rfc1001_len(pSMB, (__u16)name_len);
3546 pSMB->ByteCount = cpu_to_le16(name_len);
3548 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3549 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3551 cFYI(1, "Send error in QueryInfo = %d", rc);
3552 } else if (pFinfo) {
3554 __u32 time = le32_to_cpu(pSMBr->last_write_time);
3556 /* decode response */
3557 /* BB FIXME - add time zone adjustment BB */
3558 memset(pFinfo, 0, sizeof(FILE_ALL_INFO));
3561 /* decode time fields */
3562 pFinfo->ChangeTime = cpu_to_le64(cifs_UnixTimeToNT(ts));
3563 pFinfo->LastWriteTime = pFinfo->ChangeTime;
3564 pFinfo->LastAccessTime = 0;
3565 pFinfo->AllocationSize =
3566 cpu_to_le64(le32_to_cpu(pSMBr->size));
3567 pFinfo->EndOfFile = pFinfo->AllocationSize;
3568 pFinfo->Attributes =
3569 cpu_to_le32(le16_to_cpu(pSMBr->attr));
3571 rc = -EIO; /* bad buffer passed in */
3573 cifs_buf_release(pSMB);
3582 CIFSSMBQFileInfo(const int xid, struct cifsTconInfo *tcon,
3583 u16 netfid, FILE_ALL_INFO *pFindData)
3585 struct smb_t2_qfi_req *pSMB = NULL;
3586 struct smb_t2_qfi_rsp *pSMBr = NULL;
3589 __u16 params, byte_count;
3592 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3597 params = 2 /* level */ + 2 /* fid */;
3598 pSMB->t2.TotalDataCount = 0;
3599 pSMB->t2.MaxParameterCount = cpu_to_le16(4);
3600 /* BB find exact max data count below from sess structure BB */
3601 pSMB->t2.MaxDataCount = cpu_to_le16(CIFSMaxBufSize);
3602 pSMB->t2.MaxSetupCount = 0;
3603 pSMB->t2.Reserved = 0;
3605 pSMB->t2.Timeout = 0;
3606 pSMB->t2.Reserved2 = 0;
3607 pSMB->t2.ParameterOffset = cpu_to_le16(offsetof(struct smb_t2_qfi_req,
3609 pSMB->t2.DataCount = 0;
3610 pSMB->t2.DataOffset = 0;
3611 pSMB->t2.SetupCount = 1;
3612 pSMB->t2.Reserved3 = 0;
3613 pSMB->t2.SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION);
3614 byte_count = params + 1 /* pad */ ;
3615 pSMB->t2.TotalParameterCount = cpu_to_le16(params);
3616 pSMB->t2.ParameterCount = pSMB->t2.TotalParameterCount;
3617 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_ALL_INFO);
3620 inc_rfc1001_len(pSMB, byte_count);
3622 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3623 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3625 cFYI(1, "Send error in QPathInfo = %d", rc);
3626 } else { /* decode response */
3627 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3629 if (rc) /* BB add auto retry on EOPNOTSUPP? */
3631 else if (get_bcc(&pSMBr->hdr) < 40)
3632 rc = -EIO; /* bad smb */
3633 else if (pFindData) {
3634 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3635 memcpy((char *) pFindData,
3636 (char *) &pSMBr->hdr.Protocol +
3637 data_offset, sizeof(FILE_ALL_INFO));
3641 cifs_buf_release(pSMB);
3643 goto QFileInfoRetry;
3649 CIFSSMBQPathInfo(const int xid, struct cifsTconInfo *tcon,
3650 const unsigned char *searchName,
3651 FILE_ALL_INFO *pFindData,
3652 int legacy /* old style infolevel */,
3653 const struct nls_table *nls_codepage, int remap)
3655 /* level 263 SMB_QUERY_FILE_ALL_INFO */
3656 TRANSACTION2_QPI_REQ *pSMB = NULL;
3657 TRANSACTION2_QPI_RSP *pSMBr = NULL;
3661 __u16 params, byte_count;
3663 /* cFYI(1, "In QPathInfo path %s", searchName); */
3665 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3670 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3672 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
3673 PATH_MAX, nls_codepage, remap);
3674 name_len++; /* trailing null */
3676 } else { /* BB improve the check for buffer overruns BB */
3677 name_len = strnlen(searchName, PATH_MAX);
3678 name_len++; /* trailing null */
3679 strncpy(pSMB->FileName, searchName, name_len);
3682 params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */;
3683 pSMB->TotalDataCount = 0;
3684 pSMB->MaxParameterCount = cpu_to_le16(2);
3685 /* BB find exact max SMB PDU from sess structure BB */
3686 pSMB->MaxDataCount = cpu_to_le16(4000);
3687 pSMB->MaxSetupCount = 0;
3691 pSMB->Reserved2 = 0;
3692 pSMB->ParameterOffset = cpu_to_le16(offsetof(
3693 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
3694 pSMB->DataCount = 0;
3695 pSMB->DataOffset = 0;
3696 pSMB->SetupCount = 1;
3697 pSMB->Reserved3 = 0;
3698 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
3699 byte_count = params + 1 /* pad */ ;
3700 pSMB->TotalParameterCount = cpu_to_le16(params);
3701 pSMB->ParameterCount = pSMB->TotalParameterCount;
3703 pSMB->InformationLevel = cpu_to_le16(SMB_INFO_STANDARD);
3705 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_ALL_INFO);
3706 pSMB->Reserved4 = 0;
3707 inc_rfc1001_len(pSMB, byte_count);
3708 pSMB->ByteCount = cpu_to_le16(byte_count);
3710 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3711 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3713 cFYI(1, "Send error in QPathInfo = %d", rc);
3714 } else { /* decode response */
3715 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3717 if (rc) /* BB add auto retry on EOPNOTSUPP? */
3719 else if (!legacy && get_bcc(&pSMBr->hdr) < 40)
3720 rc = -EIO; /* bad smb */
3721 else if (legacy && get_bcc(&pSMBr->hdr) < 24)
3722 rc = -EIO; /* 24 or 26 expected but we do not read
3724 else if (pFindData) {
3726 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3728 /* On legacy responses we do not read the last field,
3729 EAsize, fortunately since it varies by subdialect and
3730 also note it differs on Set vs. Get, ie two bytes or 4
3731 bytes depending but we don't care here */
3733 size = sizeof(FILE_INFO_STANDARD);
3735 size = sizeof(FILE_ALL_INFO);
3736 memcpy((char *) pFindData,
3737 (char *) &pSMBr->hdr.Protocol +
3742 cifs_buf_release(pSMB);
3744 goto QPathInfoRetry;
3750 CIFSSMBUnixQFileInfo(const int xid, struct cifsTconInfo *tcon,
3751 u16 netfid, FILE_UNIX_BASIC_INFO *pFindData)
3753 struct smb_t2_qfi_req *pSMB = NULL;
3754 struct smb_t2_qfi_rsp *pSMBr = NULL;
3757 __u16 params, byte_count;
3760 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3765 params = 2 /* level */ + 2 /* fid */;
3766 pSMB->t2.TotalDataCount = 0;
3767 pSMB->t2.MaxParameterCount = cpu_to_le16(4);
3768 /* BB find exact max data count below from sess structure BB */
3769 pSMB->t2.MaxDataCount = cpu_to_le16(CIFSMaxBufSize);
3770 pSMB->t2.MaxSetupCount = 0;
3771 pSMB->t2.Reserved = 0;
3773 pSMB->t2.Timeout = 0;
3774 pSMB->t2.Reserved2 = 0;
3775 pSMB->t2.ParameterOffset = cpu_to_le16(offsetof(struct smb_t2_qfi_req,
3777 pSMB->t2.DataCount = 0;
3778 pSMB->t2.DataOffset = 0;
3779 pSMB->t2.SetupCount = 1;
3780 pSMB->t2.Reserved3 = 0;
3781 pSMB->t2.SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION);
3782 byte_count = params + 1 /* pad */ ;
3783 pSMB->t2.TotalParameterCount = cpu_to_le16(params);
3784 pSMB->t2.ParameterCount = pSMB->t2.TotalParameterCount;
3785 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC);
3788 inc_rfc1001_len(pSMB, byte_count);
3790 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3791 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3793 cFYI(1, "Send error in QPathInfo = %d", rc);
3794 } else { /* decode response */
3795 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3797 if (rc || get_bcc(&pSMBr->hdr) < sizeof(FILE_UNIX_BASIC_INFO)) {
3798 cERROR(1, "Malformed FILE_UNIX_BASIC_INFO response.\n"
3799 "Unix Extensions can be disabled on mount "
3800 "by specifying the nosfu mount option.");
3801 rc = -EIO; /* bad smb */
3803 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3804 memcpy((char *) pFindData,
3805 (char *) &pSMBr->hdr.Protocol +
3807 sizeof(FILE_UNIX_BASIC_INFO));
3811 cifs_buf_release(pSMB);
3813 goto UnixQFileInfoRetry;
3819 CIFSSMBUnixQPathInfo(const int xid, struct cifsTconInfo *tcon,
3820 const unsigned char *searchName,
3821 FILE_UNIX_BASIC_INFO *pFindData,
3822 const struct nls_table *nls_codepage, int remap)
3824 /* SMB_QUERY_FILE_UNIX_BASIC */
3825 TRANSACTION2_QPI_REQ *pSMB = NULL;
3826 TRANSACTION2_QPI_RSP *pSMBr = NULL;
3828 int bytes_returned = 0;
3830 __u16 params, byte_count;
3832 cFYI(1, "In QPathInfo (Unix) the path %s", searchName);
3834 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3839 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3841 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
3842 PATH_MAX, nls_codepage, remap);
3843 name_len++; /* trailing null */
3845 } else { /* BB improve the check for buffer overruns BB */
3846 name_len = strnlen(searchName, PATH_MAX);
3847 name_len++; /* trailing null */
3848 strncpy(pSMB->FileName, searchName, name_len);
3851 params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */;
3852 pSMB->TotalDataCount = 0;
3853 pSMB->MaxParameterCount = cpu_to_le16(2);
3854 /* BB find exact max SMB PDU from sess structure BB */
3855 pSMB->MaxDataCount = cpu_to_le16(4000);
3856 pSMB->MaxSetupCount = 0;
3860 pSMB->Reserved2 = 0;
3861 pSMB->ParameterOffset = cpu_to_le16(offsetof(
3862 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
3863 pSMB->DataCount = 0;
3864 pSMB->DataOffset = 0;
3865 pSMB->SetupCount = 1;
3866 pSMB->Reserved3 = 0;
3867 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
3868 byte_count = params + 1 /* pad */ ;
3869 pSMB->TotalParameterCount = cpu_to_le16(params);
3870 pSMB->ParameterCount = pSMB->TotalParameterCount;
3871 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC);
3872 pSMB->Reserved4 = 0;
3873 inc_rfc1001_len(pSMB, byte_count);
3874 pSMB->ByteCount = cpu_to_le16(byte_count);
3876 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3877 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3879 cFYI(1, "Send error in QPathInfo = %d", rc);
3880 } else { /* decode response */
3881 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3883 if (rc || get_bcc(&pSMBr->hdr) < sizeof(FILE_UNIX_BASIC_INFO)) {
3884 cERROR(1, "Malformed FILE_UNIX_BASIC_INFO response.\n"
3885 "Unix Extensions can be disabled on mount "
3886 "by specifying the nosfu mount option.");
3887 rc = -EIO; /* bad smb */
3889 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3890 memcpy((char *) pFindData,
3891 (char *) &pSMBr->hdr.Protocol +
3893 sizeof(FILE_UNIX_BASIC_INFO));
3896 cifs_buf_release(pSMB);
3898 goto UnixQPathInfoRetry;
3903 /* xid, tcon, searchName and codepage are input parms, rest are returned */
3905 CIFSFindFirst(const int xid, struct cifsTconInfo *tcon,
3906 const char *searchName,
3907 const struct nls_table *nls_codepage,
3909 struct cifs_search_info *psrch_inf, int remap, const char dirsep)
3911 /* level 257 SMB_ */
3912 TRANSACTION2_FFIRST_REQ *pSMB = NULL;
3913 TRANSACTION2_FFIRST_RSP *pSMBr = NULL;
3914 T2_FFIRST_RSP_PARMS *parms;
3916 int bytes_returned = 0;
3918 __u16 params, byte_count;
3920 cFYI(1, "In FindFirst for %s", searchName);
3923 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3928 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3930 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
3931 PATH_MAX, nls_codepage, remap);
3932 /* We can not add the asterik earlier in case
3933 it got remapped to 0xF03A as if it were part of the
3934 directory name instead of a wildcard */
3936 pSMB->FileName[name_len] = dirsep;
3937 pSMB->FileName[name_len+1] = 0;
3938 pSMB->FileName[name_len+2] = '*';
3939 pSMB->FileName[name_len+3] = 0;
3940 name_len += 4; /* now the trailing null */
3941 pSMB->FileName[name_len] = 0; /* null terminate just in case */
3942 pSMB->FileName[name_len+1] = 0;
3944 } else { /* BB add check for overrun of SMB buf BB */
3945 name_len = strnlen(searchName, PATH_MAX);
3946 /* BB fix here and in unicode clause above ie
3947 if (name_len > buffersize-header)
3948 free buffer exit; BB */
3949 strncpy(pSMB->FileName, searchName, name_len);
3950 pSMB->FileName[name_len] = dirsep;
3951 pSMB->FileName[name_len+1] = '*';
3952 pSMB->FileName[name_len+2] = 0;
3956 params = 12 + name_len /* includes null */ ;
3957 pSMB->TotalDataCount = 0; /* no EAs */
3958 pSMB->MaxParameterCount = cpu_to_le16(10);
3959 pSMB->MaxDataCount = cpu_to_le16((tcon->ses->server->maxBuf -
3960 MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
3961 pSMB->MaxSetupCount = 0;
3965 pSMB->Reserved2 = 0;
3966 byte_count = params + 1 /* pad */ ;
3967 pSMB->TotalParameterCount = cpu_to_le16(params);
3968 pSMB->ParameterCount = pSMB->TotalParameterCount;
3969 pSMB->ParameterOffset = cpu_to_le16(
3970 offsetof(struct smb_com_transaction2_ffirst_req, SearchAttributes)
3972 pSMB->DataCount = 0;
3973 pSMB->DataOffset = 0;
3974 pSMB->SetupCount = 1; /* one byte, no need to make endian neutral */
3975 pSMB->Reserved3 = 0;
3976 pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_FIRST);
3977 pSMB->SearchAttributes =
3978 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
3980 pSMB->SearchCount = cpu_to_le16(CIFSMaxBufSize/sizeof(FILE_UNIX_INFO));
3981 pSMB->SearchFlags = cpu_to_le16(CIFS_SEARCH_CLOSE_AT_END |
3982 CIFS_SEARCH_RETURN_RESUME);
3983 pSMB->InformationLevel = cpu_to_le16(psrch_inf->info_level);
3985 /* BB what should we set StorageType to? Does it matter? BB */
3986 pSMB->SearchStorageType = 0;
3987 inc_rfc1001_len(pSMB, byte_count);
3988 pSMB->ByteCount = cpu_to_le16(byte_count);
3990 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3991 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3992 cifs_stats_inc(&tcon->num_ffirst);
3994 if (rc) {/* BB add logic to retry regular search if Unix search
3995 rejected unexpectedly by server */
3996 /* BB Add code to handle unsupported level rc */
3997 cFYI(1, "Error in FindFirst = %d", rc);
3999 cifs_buf_release(pSMB);
4001 /* BB eventually could optimize out free and realloc of buf */
4004 goto findFirstRetry;
4005 } else { /* decode response */
4006 /* BB remember to free buffer if error BB */
4007 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4011 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
4012 psrch_inf->unicode = true;
4014 psrch_inf->unicode = false;
4016 psrch_inf->ntwrk_buf_start = (char *)pSMBr;
4017 psrch_inf->smallBuf = 0;
4018 psrch_inf->srch_entries_start =
4019 (char *) &pSMBr->hdr.Protocol +
4020 le16_to_cpu(pSMBr->t2.DataOffset);
4021 parms = (T2_FFIRST_RSP_PARMS *)((char *) &pSMBr->hdr.Protocol +
4022 le16_to_cpu(pSMBr->t2.ParameterOffset));
4024 if (parms->EndofSearch)
4025 psrch_inf->endOfSearch = true;
4027 psrch_inf->endOfSearch = false;
4029 psrch_inf->entries_in_buffer =
4030 le16_to_cpu(parms->SearchCount);
4031 psrch_inf->index_of_last_entry = 2 /* skip . and .. */ +
4032 psrch_inf->entries_in_buffer;
4033 lnoff = le16_to_cpu(parms->LastNameOffset);
4034 if (tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE <
4036 cERROR(1, "ignoring corrupt resume name");
4037 psrch_inf->last_entry = NULL;
4041 psrch_inf->last_entry = psrch_inf->srch_entries_start +
4044 *pnetfid = parms->SearchHandle;
4046 cifs_buf_release(pSMB);
4053 int CIFSFindNext(const int xid, struct cifsTconInfo *tcon,
4054 __u16 searchHandle, struct cifs_search_info *psrch_inf)
4056 TRANSACTION2_FNEXT_REQ *pSMB = NULL;
4057 TRANSACTION2_FNEXT_RSP *pSMBr = NULL;
4058 T2_FNEXT_RSP_PARMS *parms;
4059 char *response_data;
4061 int bytes_returned, name_len;
4062 __u16 params, byte_count;
4064 cFYI(1, "In FindNext");
4066 if (psrch_inf->endOfSearch)
4069 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4074 params = 14; /* includes 2 bytes of null string, converted to LE below*/
4076 pSMB->TotalDataCount = 0; /* no EAs */
4077 pSMB->MaxParameterCount = cpu_to_le16(8);
4078 pSMB->MaxDataCount =
4079 cpu_to_le16((tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE) &
4081 pSMB->MaxSetupCount = 0;
4085 pSMB->Reserved2 = 0;
4086 pSMB->ParameterOffset = cpu_to_le16(
4087 offsetof(struct smb_com_transaction2_fnext_req,SearchHandle) - 4);
4088 pSMB->DataCount = 0;
4089 pSMB->DataOffset = 0;
4090 pSMB->SetupCount = 1;
4091 pSMB->Reserved3 = 0;
4092 pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_NEXT);
4093 pSMB->SearchHandle = searchHandle; /* always kept as le */
4095 cpu_to_le16(CIFSMaxBufSize / sizeof(FILE_UNIX_INFO));
4096 pSMB->InformationLevel = cpu_to_le16(psrch_inf->info_level);
4097 pSMB->ResumeKey = psrch_inf->resume_key;
4099 cpu_to_le16(CIFS_SEARCH_CLOSE_AT_END | CIFS_SEARCH_RETURN_RESUME);
4101 name_len = psrch_inf->resume_name_len;
4103 if (name_len < PATH_MAX) {
4104 memcpy(pSMB->ResumeFileName, psrch_inf->presume_name, name_len);
4105 byte_count += name_len;
4106 /* 14 byte parm len above enough for 2 byte null terminator */
4107 pSMB->ResumeFileName[name_len] = 0;
4108 pSMB->ResumeFileName[name_len+1] = 0;
4111 goto FNext2_err_exit;
4113 byte_count = params + 1 /* pad */ ;
4114 pSMB->TotalParameterCount = cpu_to_le16(params);
4115 pSMB->ParameterCount = pSMB->TotalParameterCount;
4116 inc_rfc1001_len(pSMB, byte_count);
4117 pSMB->ByteCount = cpu_to_le16(byte_count);
4119 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4120 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4121 cifs_stats_inc(&tcon->num_fnext);
4124 psrch_inf->endOfSearch = true;
4125 cifs_buf_release(pSMB);
4126 rc = 0; /* search probably was closed at end of search*/
4128 cFYI(1, "FindNext returned = %d", rc);
4129 } else { /* decode response */
4130 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4135 /* BB fixme add lock for file (srch_info) struct here */
4136 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
4137 psrch_inf->unicode = true;
4139 psrch_inf->unicode = false;
4140 response_data = (char *) &pSMBr->hdr.Protocol +
4141 le16_to_cpu(pSMBr->t2.ParameterOffset);
4142 parms = (T2_FNEXT_RSP_PARMS *)response_data;
4143 response_data = (char *)&pSMBr->hdr.Protocol +
4144 le16_to_cpu(pSMBr->t2.DataOffset);
4145 if (psrch_inf->smallBuf)
4146 cifs_small_buf_release(
4147 psrch_inf->ntwrk_buf_start);
4149 cifs_buf_release(psrch_inf->ntwrk_buf_start);
4150 psrch_inf->srch_entries_start = response_data;
4151 psrch_inf->ntwrk_buf_start = (char *)pSMB;
4152 psrch_inf->smallBuf = 0;
4153 if (parms->EndofSearch)
4154 psrch_inf->endOfSearch = true;
4156 psrch_inf->endOfSearch = false;
4157 psrch_inf->entries_in_buffer =
4158 le16_to_cpu(parms->SearchCount);
4159 psrch_inf->index_of_last_entry +=
4160 psrch_inf->entries_in_buffer;
4161 lnoff = le16_to_cpu(parms->LastNameOffset);
4162 if (tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE <
4164 cERROR(1, "ignoring corrupt resume name");
4165 psrch_inf->last_entry = NULL;
4168 psrch_inf->last_entry =
4169 psrch_inf->srch_entries_start + lnoff;
4171 /* cFYI(1, "fnxt2 entries in buf %d index_of_last %d",
4172 psrch_inf->entries_in_buffer, psrch_inf->index_of_last_entry); */
4174 /* BB fixme add unlock here */
4179 /* BB On error, should we leave previous search buf (and count and
4180 last entry fields) intact or free the previous one? */
4182 /* Note: On -EAGAIN error only caller can retry on handle based calls
4183 since file handle passed in no longer valid */
4186 cifs_buf_release(pSMB);
4191 CIFSFindClose(const int xid, struct cifsTconInfo *tcon,
4192 const __u16 searchHandle)
4195 FINDCLOSE_REQ *pSMB = NULL;
4197 cFYI(1, "In CIFSSMBFindClose");
4198 rc = small_smb_init(SMB_COM_FIND_CLOSE2, 1, tcon, (void **)&pSMB);
4200 /* no sense returning error if session restarted
4201 as file handle has been closed */
4207 pSMB->FileID = searchHandle;
4208 pSMB->ByteCount = 0;
4209 rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0);
4211 cERROR(1, "Send error in FindClose = %d", rc);
4213 cifs_stats_inc(&tcon->num_fclose);
4215 /* Since session is dead, search handle closed on server already */
4223 CIFSGetSrvInodeNumber(const int xid, struct cifsTconInfo *tcon,
4224 const unsigned char *searchName,
4225 __u64 *inode_number,
4226 const struct nls_table *nls_codepage, int remap)
4229 TRANSACTION2_QPI_REQ *pSMB = NULL;
4230 TRANSACTION2_QPI_RSP *pSMBr = NULL;
4231 int name_len, bytes_returned;
4232 __u16 params, byte_count;
4234 cFYI(1, "In GetSrvInodeNum for %s", searchName);
4238 GetInodeNumberRetry:
4239 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4244 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4246 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
4247 PATH_MAX, nls_codepage, remap);
4248 name_len++; /* trailing null */
4250 } else { /* BB improve the check for buffer overruns BB */
4251 name_len = strnlen(searchName, PATH_MAX);
4252 name_len++; /* trailing null */
4253 strncpy(pSMB->FileName, searchName, name_len);
4256 params = 2 /* level */ + 4 /* rsrvd */ + name_len /* incl null */ ;
4257 pSMB->TotalDataCount = 0;
4258 pSMB->MaxParameterCount = cpu_to_le16(2);
4259 /* BB find exact max data count below from sess structure BB */
4260 pSMB->MaxDataCount = cpu_to_le16(4000);
4261 pSMB->MaxSetupCount = 0;
4265 pSMB->Reserved2 = 0;
4266 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4267 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
4268 pSMB->DataCount = 0;
4269 pSMB->DataOffset = 0;
4270 pSMB->SetupCount = 1;
4271 pSMB->Reserved3 = 0;
4272 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
4273 byte_count = params + 1 /* pad */ ;
4274 pSMB->TotalParameterCount = cpu_to_le16(params);
4275 pSMB->ParameterCount = pSMB->TotalParameterCount;
4276 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_INTERNAL_INFO);
4277 pSMB->Reserved4 = 0;
4278 inc_rfc1001_len(pSMB, byte_count);
4279 pSMB->ByteCount = cpu_to_le16(byte_count);
4281 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4282 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4284 cFYI(1, "error %d in QueryInternalInfo", rc);
4286 /* decode response */
4287 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4288 /* BB also check enough total bytes returned */
4289 if (rc || get_bcc(&pSMBr->hdr) < 2)
4290 /* If rc should we check for EOPNOSUPP and
4291 disable the srvino flag? or in caller? */
4292 rc = -EIO; /* bad smb */
4294 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4295 __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
4296 struct file_internal_info *pfinfo;
4297 /* BB Do we need a cast or hash here ? */
4299 cFYI(1, "Illegal size ret in QryIntrnlInf");
4301 goto GetInodeNumOut;
4303 pfinfo = (struct file_internal_info *)
4304 (data_offset + (char *) &pSMBr->hdr.Protocol);
4305 *inode_number = le64_to_cpu(pfinfo->UniqueId);
4309 cifs_buf_release(pSMB);
4311 goto GetInodeNumberRetry;
4315 /* parses DFS refferal V3 structure
4316 * caller is responsible for freeing target_nodes
4319 * on failure - errno
4322 parse_DFS_referrals(TRANSACTION2_GET_DFS_REFER_RSP *pSMBr,
4323 unsigned int *num_of_nodes,
4324 struct dfs_info3_param **target_nodes,
4325 const struct nls_table *nls_codepage, int remap,
4326 const char *searchName)
4331 struct dfs_referral_level_3 *ref;
4333 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
4337 *num_of_nodes = le16_to_cpu(pSMBr->NumberOfReferrals);
4339 if (*num_of_nodes < 1) {
4340 cERROR(1, "num_referrals: must be at least > 0,"
4341 "but we get num_referrals = %d\n", *num_of_nodes);
4343 goto parse_DFS_referrals_exit;
4346 ref = (struct dfs_referral_level_3 *) &(pSMBr->referrals);
4347 if (ref->VersionNumber != cpu_to_le16(3)) {
4348 cERROR(1, "Referrals of V%d version are not supported,"
4349 "should be V3", le16_to_cpu(ref->VersionNumber));
4351 goto parse_DFS_referrals_exit;
4354 /* get the upper boundary of the resp buffer */
4355 data_end = (char *)(&(pSMBr->PathConsumed)) +
4356 le16_to_cpu(pSMBr->t2.DataCount);
4358 cFYI(1, "num_referrals: %d dfs flags: 0x%x ...\n",
4360 le32_to_cpu(pSMBr->DFSFlags));
4362 *target_nodes = kzalloc(sizeof(struct dfs_info3_param) *
4363 *num_of_nodes, GFP_KERNEL);
4364 if (*target_nodes == NULL) {
4365 cERROR(1, "Failed to allocate buffer for target_nodes\n");
4367 goto parse_DFS_referrals_exit;
4370 /* collect necessary data from referrals */
4371 for (i = 0; i < *num_of_nodes; i++) {
4374 struct dfs_info3_param *node = (*target_nodes)+i;
4376 node->flags = le32_to_cpu(pSMBr->DFSFlags);
4378 __le16 *tmp = kmalloc(strlen(searchName)*2 + 2,
4382 goto parse_DFS_referrals_exit;
4384 cifsConvertToUCS((__le16 *) tmp, searchName,
4385 PATH_MAX, nls_codepage, remap);
4386 node->path_consumed = cifs_ucs2_bytes(tmp,
4387 le16_to_cpu(pSMBr->PathConsumed),
4391 node->path_consumed = le16_to_cpu(pSMBr->PathConsumed);
4393 node->server_type = le16_to_cpu(ref->ServerType);
4394 node->ref_flag = le16_to_cpu(ref->ReferralEntryFlags);
4397 temp = (char *)ref + le16_to_cpu(ref->DfsPathOffset);
4398 max_len = data_end - temp;
4399 node->path_name = cifs_strndup_from_ucs(temp, max_len,
4400 is_unicode, nls_codepage);
4401 if (!node->path_name) {
4403 goto parse_DFS_referrals_exit;
4406 /* copy link target UNC */
4407 temp = (char *)ref + le16_to_cpu(ref->NetworkAddressOffset);
4408 max_len = data_end - temp;
4409 node->node_name = cifs_strndup_from_ucs(temp, max_len,
4410 is_unicode, nls_codepage);
4411 if (!node->node_name)
4415 parse_DFS_referrals_exit:
4417 free_dfs_info_array(*target_nodes, *num_of_nodes);
4418 *target_nodes = NULL;
4425 CIFSGetDFSRefer(const int xid, struct cifsSesInfo *ses,
4426 const unsigned char *searchName,
4427 struct dfs_info3_param **target_nodes,
4428 unsigned int *num_of_nodes,
4429 const struct nls_table *nls_codepage, int remap)
4431 /* TRANS2_GET_DFS_REFERRAL */
4432 TRANSACTION2_GET_DFS_REFER_REQ *pSMB = NULL;
4433 TRANSACTION2_GET_DFS_REFER_RSP *pSMBr = NULL;
4437 __u16 params, byte_count;
4439 *target_nodes = NULL;
4441 cFYI(1, "In GetDFSRefer the path %s", searchName);
4445 rc = smb_init(SMB_COM_TRANSACTION2, 15, NULL, (void **) &pSMB,
4450 /* server pointer checked in called function,
4451 but should never be null here anyway */
4452 pSMB->hdr.Mid = GetNextMid(ses->server);
4453 pSMB->hdr.Tid = ses->ipc_tid;
4454 pSMB->hdr.Uid = ses->Suid;
4455 if (ses->capabilities & CAP_STATUS32)
4456 pSMB->hdr.Flags2 |= SMBFLG2_ERR_STATUS;
4457 if (ses->capabilities & CAP_DFS)
4458 pSMB->hdr.Flags2 |= SMBFLG2_DFS;
4460 if (ses->capabilities & CAP_UNICODE) {
4461 pSMB->hdr.Flags2 |= SMBFLG2_UNICODE;
4463 cifsConvertToUCS((__le16 *) pSMB->RequestFileName,
4464 searchName, PATH_MAX, nls_codepage, remap);
4465 name_len++; /* trailing null */
4467 } else { /* BB improve the check for buffer overruns BB */
4468 name_len = strnlen(searchName, PATH_MAX);
4469 name_len++; /* trailing null */
4470 strncpy(pSMB->RequestFileName, searchName, name_len);
4474 if (ses->server->secMode &
4475 (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
4476 pSMB->hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
4479 pSMB->hdr.Uid = ses->Suid;
4481 params = 2 /* level */ + name_len /*includes null */ ;
4482 pSMB->TotalDataCount = 0;
4483 pSMB->DataCount = 0;
4484 pSMB->DataOffset = 0;
4485 pSMB->MaxParameterCount = 0;
4486 /* BB find exact max SMB PDU from sess structure BB */
4487 pSMB->MaxDataCount = cpu_to_le16(4000);
4488 pSMB->MaxSetupCount = 0;
4492 pSMB->Reserved2 = 0;
4493 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4494 struct smb_com_transaction2_get_dfs_refer_req, MaxReferralLevel) - 4);
4495 pSMB->SetupCount = 1;
4496 pSMB->Reserved3 = 0;
4497 pSMB->SubCommand = cpu_to_le16(TRANS2_GET_DFS_REFERRAL);
4498 byte_count = params + 3 /* pad */ ;
4499 pSMB->ParameterCount = cpu_to_le16(params);
4500 pSMB->TotalParameterCount = pSMB->ParameterCount;
4501 pSMB->MaxReferralLevel = cpu_to_le16(3);
4502 inc_rfc1001_len(pSMB, byte_count);
4503 pSMB->ByteCount = cpu_to_le16(byte_count);
4505 rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB,
4506 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4508 cFYI(1, "Send error in GetDFSRefer = %d", rc);
4511 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4513 /* BB Also check if enough total bytes returned? */
4514 if (rc || get_bcc(&pSMBr->hdr) < 17) {
4515 rc = -EIO; /* bad smb */
4519 cFYI(1, "Decoding GetDFSRefer response BCC: %d Offset %d",
4520 get_bcc(&pSMBr->hdr),
4521 le16_to_cpu(pSMBr->t2.DataOffset));
4523 /* parse returned result into more usable form */
4524 rc = parse_DFS_referrals(pSMBr, num_of_nodes,
4525 target_nodes, nls_codepage, remap,
4529 cifs_buf_release(pSMB);
4537 /* Query File System Info such as free space to old servers such as Win 9x */
4539 SMBOldQFSInfo(const int xid, struct cifsTconInfo *tcon, struct kstatfs *FSData)
4541 /* level 0x01 SMB_QUERY_FILE_SYSTEM_INFO */
4542 TRANSACTION2_QFSI_REQ *pSMB = NULL;
4543 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4544 FILE_SYSTEM_ALLOC_INFO *response_data;
4546 int bytes_returned = 0;
4547 __u16 params, byte_count;
4549 cFYI(1, "OldQFSInfo");
4551 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4556 params = 2; /* level */
4557 pSMB->TotalDataCount = 0;
4558 pSMB->MaxParameterCount = cpu_to_le16(2);
4559 pSMB->MaxDataCount = cpu_to_le16(1000);
4560 pSMB->MaxSetupCount = 0;
4564 pSMB->Reserved2 = 0;
4565 byte_count = params + 1 /* pad */ ;
4566 pSMB->TotalParameterCount = cpu_to_le16(params);
4567 pSMB->ParameterCount = pSMB->TotalParameterCount;
4568 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4569 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4570 pSMB->DataCount = 0;
4571 pSMB->DataOffset = 0;
4572 pSMB->SetupCount = 1;
4573 pSMB->Reserved3 = 0;
4574 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4575 pSMB->InformationLevel = cpu_to_le16(SMB_INFO_ALLOCATION);
4576 inc_rfc1001_len(pSMB, byte_count);
4577 pSMB->ByteCount = cpu_to_le16(byte_count);
4579 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4580 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4582 cFYI(1, "Send error in QFSInfo = %d", rc);
4583 } else { /* decode response */
4584 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4586 if (rc || get_bcc(&pSMBr->hdr) < 18)
4587 rc = -EIO; /* bad smb */
4589 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4590 cFYI(1, "qfsinf resp BCC: %d Offset %d",
4591 get_bcc(&pSMBr->hdr), data_offset);
4593 response_data = (FILE_SYSTEM_ALLOC_INFO *)
4594 (((char *) &pSMBr->hdr.Protocol) + data_offset);
4596 le16_to_cpu(response_data->BytesPerSector) *
4597 le32_to_cpu(response_data->
4598 SectorsPerAllocationUnit);
4600 le32_to_cpu(response_data->TotalAllocationUnits);
4601 FSData->f_bfree = FSData->f_bavail =
4602 le32_to_cpu(response_data->FreeAllocationUnits);
4603 cFYI(1, "Blocks: %lld Free: %lld Block size %ld",
4604 (unsigned long long)FSData->f_blocks,
4605 (unsigned long long)FSData->f_bfree,
4609 cifs_buf_release(pSMB);
4612 goto oldQFSInfoRetry;
4618 CIFSSMBQFSInfo(const int xid, struct cifsTconInfo *tcon, struct kstatfs *FSData)
4620 /* level 0x103 SMB_QUERY_FILE_SYSTEM_INFO */
4621 TRANSACTION2_QFSI_REQ *pSMB = NULL;
4622 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4623 FILE_SYSTEM_INFO *response_data;
4625 int bytes_returned = 0;
4626 __u16 params, byte_count;
4628 cFYI(1, "In QFSInfo");
4630 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4635 params = 2; /* level */
4636 pSMB->TotalDataCount = 0;
4637 pSMB->MaxParameterCount = cpu_to_le16(2);
4638 pSMB->MaxDataCount = cpu_to_le16(1000);
4639 pSMB->MaxSetupCount = 0;
4643 pSMB->Reserved2 = 0;
4644 byte_count = params + 1 /* pad */ ;
4645 pSMB->TotalParameterCount = cpu_to_le16(params);
4646 pSMB->ParameterCount = pSMB->TotalParameterCount;
4647 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4648 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4649 pSMB->DataCount = 0;
4650 pSMB->DataOffset = 0;
4651 pSMB->SetupCount = 1;
4652 pSMB->Reserved3 = 0;
4653 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4654 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_SIZE_INFO);
4655 inc_rfc1001_len(pSMB, byte_count);
4656 pSMB->ByteCount = cpu_to_le16(byte_count);
4658 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4659 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4661 cFYI(1, "Send error in QFSInfo = %d", rc);
4662 } else { /* decode response */
4663 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4665 if (rc || get_bcc(&pSMBr->hdr) < 24)
4666 rc = -EIO; /* bad smb */
4668 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4672 *) (((char *) &pSMBr->hdr.Protocol) +
4675 le32_to_cpu(response_data->BytesPerSector) *
4676 le32_to_cpu(response_data->
4677 SectorsPerAllocationUnit);
4679 le64_to_cpu(response_data->TotalAllocationUnits);
4680 FSData->f_bfree = FSData->f_bavail =
4681 le64_to_cpu(response_data->FreeAllocationUnits);
4682 cFYI(1, "Blocks: %lld Free: %lld Block size %ld",
4683 (unsigned long long)FSData->f_blocks,
4684 (unsigned long long)FSData->f_bfree,
4688 cifs_buf_release(pSMB);
4697 CIFSSMBQFSAttributeInfo(const int xid, struct cifsTconInfo *tcon)
4699 /* level 0x105 SMB_QUERY_FILE_SYSTEM_INFO */
4700 TRANSACTION2_QFSI_REQ *pSMB = NULL;
4701 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4702 FILE_SYSTEM_ATTRIBUTE_INFO *response_data;
4704 int bytes_returned = 0;
4705 __u16 params, byte_count;
4707 cFYI(1, "In QFSAttributeInfo");
4709 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4714 params = 2; /* level */
4715 pSMB->TotalDataCount = 0;
4716 pSMB->MaxParameterCount = cpu_to_le16(2);
4717 /* BB find exact max SMB PDU from sess structure BB */
4718 pSMB->MaxDataCount = cpu_to_le16(1000);
4719 pSMB->MaxSetupCount = 0;
4723 pSMB->Reserved2 = 0;
4724 byte_count = params + 1 /* pad */ ;
4725 pSMB->TotalParameterCount = cpu_to_le16(params);
4726 pSMB->ParameterCount = pSMB->TotalParameterCount;
4727 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4728 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4729 pSMB->DataCount = 0;
4730 pSMB->DataOffset = 0;
4731 pSMB->SetupCount = 1;
4732 pSMB->Reserved3 = 0;
4733 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4734 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_ATTRIBUTE_INFO);
4735 inc_rfc1001_len(pSMB, byte_count);
4736 pSMB->ByteCount = cpu_to_le16(byte_count);
4738 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4739 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4741 cERROR(1, "Send error in QFSAttributeInfo = %d", rc);
4742 } else { /* decode response */
4743 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4745 if (rc || get_bcc(&pSMBr->hdr) < 13) {
4746 /* BB also check if enough bytes returned */
4747 rc = -EIO; /* bad smb */
4749 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4751 (FILE_SYSTEM_ATTRIBUTE_INFO
4752 *) (((char *) &pSMBr->hdr.Protocol) +
4754 memcpy(&tcon->fsAttrInfo, response_data,
4755 sizeof(FILE_SYSTEM_ATTRIBUTE_INFO));
4758 cifs_buf_release(pSMB);
4761 goto QFSAttributeRetry;
4767 CIFSSMBQFSDeviceInfo(const int xid, struct cifsTconInfo *tcon)
4769 /* level 0x104 SMB_QUERY_FILE_SYSTEM_INFO */
4770 TRANSACTION2_QFSI_REQ *pSMB = NULL;
4771 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4772 FILE_SYSTEM_DEVICE_INFO *response_data;
4774 int bytes_returned = 0;
4775 __u16 params, byte_count;
4777 cFYI(1, "In QFSDeviceInfo");
4779 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4784 params = 2; /* level */
4785 pSMB->TotalDataCount = 0;
4786 pSMB->MaxParameterCount = cpu_to_le16(2);
4787 /* BB find exact max SMB PDU from sess structure BB */
4788 pSMB->MaxDataCount = cpu_to_le16(1000);
4789 pSMB->MaxSetupCount = 0;
4793 pSMB->Reserved2 = 0;
4794 byte_count = params + 1 /* pad */ ;
4795 pSMB->TotalParameterCount = cpu_to_le16(params);
4796 pSMB->ParameterCount = pSMB->TotalParameterCount;
4797 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4798 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4800 pSMB->DataCount = 0;
4801 pSMB->DataOffset = 0;
4802 pSMB->SetupCount = 1;
4803 pSMB->Reserved3 = 0;
4804 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4805 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_DEVICE_INFO);
4806 inc_rfc1001_len(pSMB, byte_count);
4807 pSMB->ByteCount = cpu_to_le16(byte_count);
4809 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4810 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4812 cFYI(1, "Send error in QFSDeviceInfo = %d", rc);
4813 } else { /* decode response */
4814 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4816 if (rc || get_bcc(&pSMBr->hdr) <
4817 sizeof(FILE_SYSTEM_DEVICE_INFO))
4818 rc = -EIO; /* bad smb */
4820 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4822 (FILE_SYSTEM_DEVICE_INFO *)
4823 (((char *) &pSMBr->hdr.Protocol) +
4825 memcpy(&tcon->fsDevInfo, response_data,
4826 sizeof(FILE_SYSTEM_DEVICE_INFO));
4829 cifs_buf_release(pSMB);
4832 goto QFSDeviceRetry;
4838 CIFSSMBQFSUnixInfo(const int xid, struct cifsTconInfo *tcon)
4840 /* level 0x200 SMB_QUERY_CIFS_UNIX_INFO */
4841 TRANSACTION2_QFSI_REQ *pSMB = NULL;
4842 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4843 FILE_SYSTEM_UNIX_INFO *response_data;
4845 int bytes_returned = 0;
4846 __u16 params, byte_count;
4848 cFYI(1, "In QFSUnixInfo");
4850 rc = smb_init_no_reconnect(SMB_COM_TRANSACTION2, 15, tcon,
4851 (void **) &pSMB, (void **) &pSMBr);
4855 params = 2; /* level */
4856 pSMB->TotalDataCount = 0;
4857 pSMB->DataCount = 0;
4858 pSMB->DataOffset = 0;
4859 pSMB->MaxParameterCount = cpu_to_le16(2);
4860 /* BB find exact max SMB PDU from sess structure BB */
4861 pSMB->MaxDataCount = cpu_to_le16(100);
4862 pSMB->MaxSetupCount = 0;
4866 pSMB->Reserved2 = 0;
4867 byte_count = params + 1 /* pad */ ;
4868 pSMB->ParameterCount = cpu_to_le16(params);
4869 pSMB->TotalParameterCount = pSMB->ParameterCount;
4870 pSMB->ParameterOffset = cpu_to_le16(offsetof(struct
4871 smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4872 pSMB->SetupCount = 1;
4873 pSMB->Reserved3 = 0;
4874 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4875 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_CIFS_UNIX_INFO);
4876 inc_rfc1001_len(pSMB, byte_count);
4877 pSMB->ByteCount = cpu_to_le16(byte_count);
4879 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4880 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4882 cERROR(1, "Send error in QFSUnixInfo = %d", rc);
4883 } else { /* decode response */
4884 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4886 if (rc || get_bcc(&pSMBr->hdr) < 13) {
4887 rc = -EIO; /* bad smb */
4889 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4891 (FILE_SYSTEM_UNIX_INFO
4892 *) (((char *) &pSMBr->hdr.Protocol) +
4894 memcpy(&tcon->fsUnixInfo, response_data,
4895 sizeof(FILE_SYSTEM_UNIX_INFO));
4898 cifs_buf_release(pSMB);
4908 CIFSSMBSetFSUnixInfo(const int xid, struct cifsTconInfo *tcon, __u64 cap)
4910 /* level 0x200 SMB_SET_CIFS_UNIX_INFO */
4911 TRANSACTION2_SETFSI_REQ *pSMB = NULL;
4912 TRANSACTION2_SETFSI_RSP *pSMBr = NULL;
4914 int bytes_returned = 0;
4915 __u16 params, param_offset, offset, byte_count;
4917 cFYI(1, "In SETFSUnixInfo");
4919 /* BB switch to small buf init to save memory */
4920 rc = smb_init_no_reconnect(SMB_COM_TRANSACTION2, 15, tcon,
4921 (void **) &pSMB, (void **) &pSMBr);
4925 params = 4; /* 2 bytes zero followed by info level. */
4926 pSMB->MaxSetupCount = 0;
4930 pSMB->Reserved2 = 0;
4931 param_offset = offsetof(struct smb_com_transaction2_setfsi_req, FileNum)
4933 offset = param_offset + params;
4935 pSMB->MaxParameterCount = cpu_to_le16(4);
4936 /* BB find exact max SMB PDU from sess structure BB */
4937 pSMB->MaxDataCount = cpu_to_le16(100);
4938 pSMB->SetupCount = 1;
4939 pSMB->Reserved3 = 0;
4940 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FS_INFORMATION);
4941 byte_count = 1 /* pad */ + params + 12;
4943 pSMB->DataCount = cpu_to_le16(12);
4944 pSMB->ParameterCount = cpu_to_le16(params);
4945 pSMB->TotalDataCount = pSMB->DataCount;
4946 pSMB->TotalParameterCount = pSMB->ParameterCount;
4947 pSMB->ParameterOffset = cpu_to_le16(param_offset);
4948 pSMB->DataOffset = cpu_to_le16(offset);
4952 pSMB->InformationLevel = cpu_to_le16(SMB_SET_CIFS_UNIX_INFO);
4955 pSMB->ClientUnixMajor = cpu_to_le16(CIFS_UNIX_MAJOR_VERSION);
4956 pSMB->ClientUnixMinor = cpu_to_le16(CIFS_UNIX_MINOR_VERSION);
4957 pSMB->ClientUnixCap = cpu_to_le64(cap);
4959 inc_rfc1001_len(pSMB, byte_count);
4960 pSMB->ByteCount = cpu_to_le16(byte_count);
4962 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4963 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4965 cERROR(1, "Send error in SETFSUnixInfo = %d", rc);
4966 } else { /* decode response */
4967 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4969 rc = -EIO; /* bad smb */
4971 cifs_buf_release(pSMB);
4974 goto SETFSUnixRetry;
4982 CIFSSMBQFSPosixInfo(const int xid, struct cifsTconInfo *tcon,
4983 struct kstatfs *FSData)
4985 /* level 0x201 SMB_QUERY_CIFS_POSIX_INFO */
4986 TRANSACTION2_QFSI_REQ *pSMB = NULL;
4987 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4988 FILE_SYSTEM_POSIX_INFO *response_data;
4990 int bytes_returned = 0;
4991 __u16 params, byte_count;
4993 cFYI(1, "In QFSPosixInfo");
4995 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5000 params = 2; /* level */
5001 pSMB->TotalDataCount = 0;
5002 pSMB->DataCount = 0;
5003 pSMB->DataOffset = 0;
5004 pSMB->MaxParameterCount = cpu_to_le16(2);
5005 /* BB find exact max SMB PDU from sess structure BB */
5006 pSMB->MaxDataCount = cpu_to_le16(100);
5007 pSMB->MaxSetupCount = 0;
5011 pSMB->Reserved2 = 0;
5012 byte_count = params + 1 /* pad */ ;
5013 pSMB->ParameterCount = cpu_to_le16(params);
5014 pSMB->TotalParameterCount = pSMB->ParameterCount;
5015 pSMB->ParameterOffset = cpu_to_le16(offsetof(struct
5016 smb_com_transaction2_qfsi_req, InformationLevel) - 4);
5017 pSMB->SetupCount = 1;
5018 pSMB->Reserved3 = 0;
5019 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
5020 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_POSIX_FS_INFO);
5021 inc_rfc1001_len(pSMB, byte_count);
5022 pSMB->ByteCount = cpu_to_le16(byte_count);
5024 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5025 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5027 cFYI(1, "Send error in QFSUnixInfo = %d", rc);
5028 } else { /* decode response */
5029 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
5031 if (rc || get_bcc(&pSMBr->hdr) < 13) {
5032 rc = -EIO; /* bad smb */
5034 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
5036 (FILE_SYSTEM_POSIX_INFO
5037 *) (((char *) &pSMBr->hdr.Protocol) +
5040 le32_to_cpu(response_data->BlockSize);
5042 le64_to_cpu(response_data->TotalBlocks);
5044 le64_to_cpu(response_data->BlocksAvail);
5045 if (response_data->UserBlocksAvail == cpu_to_le64(-1)) {
5046 FSData->f_bavail = FSData->f_bfree;
5049 le64_to_cpu(response_data->UserBlocksAvail);
5051 if (response_data->TotalFileNodes != cpu_to_le64(-1))
5053 le64_to_cpu(response_data->TotalFileNodes);
5054 if (response_data->FreeFileNodes != cpu_to_le64(-1))
5056 le64_to_cpu(response_data->FreeFileNodes);
5059 cifs_buf_release(pSMB);
5068 /* We can not use write of zero bytes trick to
5069 set file size due to need for large file support. Also note that
5070 this SetPathInfo is preferred to SetFileInfo based method in next
5071 routine which is only needed to work around a sharing violation bug
5072 in Samba which this routine can run into */
5075 CIFSSMBSetEOF(const int xid, struct cifsTconInfo *tcon, const char *fileName,
5076 __u64 size, bool SetAllocation,
5077 const struct nls_table *nls_codepage, int remap)
5079 struct smb_com_transaction2_spi_req *pSMB = NULL;
5080 struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
5081 struct file_end_of_file_info *parm_data;
5084 int bytes_returned = 0;
5085 __u16 params, byte_count, data_count, param_offset, offset;
5087 cFYI(1, "In SetEOF");
5089 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5094 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5096 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
5097 PATH_MAX, nls_codepage, remap);
5098 name_len++; /* trailing null */
5100 } else { /* BB improve the check for buffer overruns BB */
5101 name_len = strnlen(fileName, PATH_MAX);
5102 name_len++; /* trailing null */
5103 strncpy(pSMB->FileName, fileName, name_len);
5105 params = 6 + name_len;
5106 data_count = sizeof(struct file_end_of_file_info);
5107 pSMB->MaxParameterCount = cpu_to_le16(2);
5108 pSMB->MaxDataCount = cpu_to_le16(4100);
5109 pSMB->MaxSetupCount = 0;
5113 pSMB->Reserved2 = 0;
5114 param_offset = offsetof(struct smb_com_transaction2_spi_req,
5115 InformationLevel) - 4;
5116 offset = param_offset + params;
5117 if (SetAllocation) {
5118 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
5119 pSMB->InformationLevel =
5120 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2);
5122 pSMB->InformationLevel =
5123 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO);
5124 } else /* Set File Size */ {
5125 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
5126 pSMB->InformationLevel =
5127 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO2);
5129 pSMB->InformationLevel =
5130 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO);
5134 (struct file_end_of_file_info *) (((char *) &pSMB->hdr.Protocol) +
5136 pSMB->ParameterOffset = cpu_to_le16(param_offset);
5137 pSMB->DataOffset = cpu_to_le16(offset);
5138 pSMB->SetupCount = 1;
5139 pSMB->Reserved3 = 0;
5140 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
5141 byte_count = 3 /* pad */ + params + data_count;
5142 pSMB->DataCount = cpu_to_le16(data_count);
5143 pSMB->TotalDataCount = pSMB->DataCount;
5144 pSMB->ParameterCount = cpu_to_le16(params);
5145 pSMB->TotalParameterCount = pSMB->ParameterCount;
5146 pSMB->Reserved4 = 0;
5147 inc_rfc1001_len(pSMB, byte_count);
5148 parm_data->FileSize = cpu_to_le64(size);
5149 pSMB->ByteCount = cpu_to_le16(byte_count);
5150 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5151 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5153 cFYI(1, "SetPathInfo (file size) returned %d", rc);
5155 cifs_buf_release(pSMB);
5164 CIFSSMBSetFileSize(const int xid, struct cifsTconInfo *tcon, __u64 size,
5165 __u16 fid, __u32 pid_of_opener, bool SetAllocation)
5167 struct smb_com_transaction2_sfi_req *pSMB = NULL;
5168 struct file_end_of_file_info *parm_data;
5170 __u16 params, param_offset, offset, byte_count, count;
5172 cFYI(1, "SetFileSize (via SetFileInfo) %lld",
5174 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
5179 pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
5180 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));
5183 pSMB->MaxSetupCount = 0;
5187 pSMB->Reserved2 = 0;
5188 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
5189 offset = param_offset + params;
5191 count = sizeof(struct file_end_of_file_info);
5192 pSMB->MaxParameterCount = cpu_to_le16(2);
5193 /* BB find exact max SMB PDU from sess structure BB */
5194 pSMB->MaxDataCount = cpu_to_le16(1000);
5195 pSMB->SetupCount = 1;
5196 pSMB->Reserved3 = 0;
5197 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
5198 byte_count = 3 /* pad */ + params + count;
5199 pSMB->DataCount = cpu_to_le16(count);
5200 pSMB->ParameterCount = cpu_to_le16(params);
5201 pSMB->TotalDataCount = pSMB->DataCount;
5202 pSMB->TotalParameterCount = pSMB->ParameterCount;
5203 pSMB->ParameterOffset = cpu_to_le16(param_offset);
5205 (struct file_end_of_file_info *) (((char *) &pSMB->hdr.Protocol)
5207 pSMB->DataOffset = cpu_to_le16(offset);
5208 parm_data->FileSize = cpu_to_le64(size);
5210 if (SetAllocation) {
5211 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
5212 pSMB->InformationLevel =
5213 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2);
5215 pSMB->InformationLevel =
5216 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO);
5217 } else /* Set File Size */ {
5218 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
5219 pSMB->InformationLevel =
5220 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO2);
5222 pSMB->InformationLevel =
5223 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO);
5225 pSMB->Reserved4 = 0;
5226 inc_rfc1001_len(pSMB, byte_count);
5227 pSMB->ByteCount = cpu_to_le16(byte_count);
5228 rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0);
5230 cFYI(1, "Send error in SetFileInfo (SetFileSize) = %d", rc);
5233 /* Note: On -EAGAIN error only caller can retry on handle based calls
5234 since file handle passed in no longer valid */
5239 /* Some legacy servers such as NT4 require that the file times be set on
5240 an open handle, rather than by pathname - this is awkward due to
5241 potential access conflicts on the open, but it is unavoidable for these
5242 old servers since the only other choice is to go from 100 nanosecond DCE
5243 time and resort to the original setpathinfo level which takes the ancient
5244 DOS time format with 2 second granularity */
5246 CIFSSMBSetFileInfo(const int xid, struct cifsTconInfo *tcon,
5247 const FILE_BASIC_INFO *data, __u16 fid, __u32 pid_of_opener)
5249 struct smb_com_transaction2_sfi_req *pSMB = NULL;
5252 __u16 params, param_offset, offset, byte_count, count;
5254 cFYI(1, "Set Times (via SetFileInfo)");
5255 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
5260 pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
5261 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));
5264 pSMB->MaxSetupCount = 0;
5268 pSMB->Reserved2 = 0;
5269 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
5270 offset = param_offset + params;
5272 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
5274 count = sizeof(FILE_BASIC_INFO);
5275 pSMB->MaxParameterCount = cpu_to_le16(2);
5276 /* BB find max SMB PDU from sess */
5277 pSMB->MaxDataCount = cpu_to_le16(1000);
5278 pSMB->SetupCount = 1;
5279 pSMB->Reserved3 = 0;
5280 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
5281 byte_count = 3 /* pad */ + params + count;
5282 pSMB->DataCount = cpu_to_le16(count);
5283 pSMB->ParameterCount = cpu_to_le16(params);
5284 pSMB->TotalDataCount = pSMB->DataCount;
5285 pSMB->TotalParameterCount = pSMB->ParameterCount;
5286 pSMB->ParameterOffset = cpu_to_le16(param_offset);
5287 pSMB->DataOffset = cpu_to_le16(offset);
5289 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
5290 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO2);
5292 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO);
5293 pSMB->Reserved4 = 0;
5294 inc_rfc1001_len(pSMB, byte_count);
5295 pSMB->ByteCount = cpu_to_le16(byte_count);
5296 memcpy(data_offset, data, sizeof(FILE_BASIC_INFO));
5297 rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0);
5299 cFYI(1, "Send error in Set Time (SetFileInfo) = %d", rc);
5301 /* Note: On -EAGAIN error only caller can retry on handle based calls
5302 since file handle passed in no longer valid */
5308 CIFSSMBSetFileDisposition(const int xid, struct cifsTconInfo *tcon,
5309 bool delete_file, __u16 fid, __u32 pid_of_opener)
5311 struct smb_com_transaction2_sfi_req *pSMB = NULL;
5314 __u16 params, param_offset, offset, byte_count, count;
5316 cFYI(1, "Set File Disposition (via SetFileInfo)");
5317 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
5322 pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
5323 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));
5326 pSMB->MaxSetupCount = 0;
5330 pSMB->Reserved2 = 0;
5331 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
5332 offset = param_offset + params;
5334 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
5337 pSMB->MaxParameterCount = cpu_to_le16(2);
5338 /* BB find max SMB PDU from sess */
5339 pSMB->MaxDataCount = cpu_to_le16(1000);
5340 pSMB->SetupCount = 1;
5341 pSMB->Reserved3 = 0;
5342 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
5343 byte_count = 3 /* pad */ + params + count;
5344 pSMB->DataCount = cpu_to_le16(count);
5345 pSMB->ParameterCount = cpu_to_le16(params);
5346 pSMB->TotalDataCount = pSMB->DataCount;
5347 pSMB->TotalParameterCount = pSMB->ParameterCount;
5348 pSMB->ParameterOffset = cpu_to_le16(param_offset);
5349 pSMB->DataOffset = cpu_to_le16(offset);
5351 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_DISPOSITION_INFO);
5352 pSMB->Reserved4 = 0;
5353 inc_rfc1001_len(pSMB, byte_count);
5354 pSMB->ByteCount = cpu_to_le16(byte_count);
5355 *data_offset = delete_file ? 1 : 0;
5356 rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0);
5358 cFYI(1, "Send error in SetFileDisposition = %d", rc);
5364 CIFSSMBSetPathInfo(const int xid, struct cifsTconInfo *tcon,
5365 const char *fileName, const FILE_BASIC_INFO *data,
5366 const struct nls_table *nls_codepage, int remap)
5368 TRANSACTION2_SPI_REQ *pSMB = NULL;
5369 TRANSACTION2_SPI_RSP *pSMBr = NULL;
5372 int bytes_returned = 0;
5374 __u16 params, param_offset, offset, byte_count, count;
5376 cFYI(1, "In SetTimes");
5379 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5384 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5386 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
5387 PATH_MAX, nls_codepage, remap);
5388 name_len++; /* trailing null */
5390 } else { /* BB improve the check for buffer overruns BB */
5391 name_len = strnlen(fileName, PATH_MAX);
5392 name_len++; /* trailing null */
5393 strncpy(pSMB->FileName, fileName, name_len);
5396 params = 6 + name_len;
5397 count = sizeof(FILE_BASIC_INFO);
5398 pSMB->MaxParameterCount = cpu_to_le16(2);
5399 /* BB find max SMB PDU from sess structure BB */
5400 pSMB->MaxDataCount = cpu_to_le16(1000);
5401 pSMB->MaxSetupCount = 0;
5405 pSMB->Reserved2 = 0;
5406 param_offset = offsetof(struct smb_com_transaction2_spi_req,
5407 InformationLevel) - 4;
5408 offset = param_offset + params;
5409 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
5410 pSMB->ParameterOffset = cpu_to_le16(param_offset);
5411 pSMB->DataOffset = cpu_to_le16(offset);
5412 pSMB->SetupCount = 1;
5413 pSMB->Reserved3 = 0;
5414 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
5415 byte_count = 3 /* pad */ + params + count;
5417 pSMB->DataCount = cpu_to_le16(count);
5418 pSMB->ParameterCount = cpu_to_le16(params);
5419 pSMB->TotalDataCount = pSMB->DataCount;
5420 pSMB->TotalParameterCount = pSMB->ParameterCount;
5421 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
5422 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO2);
5424 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO);
5425 pSMB->Reserved4 = 0;
5426 inc_rfc1001_len(pSMB, byte_count);
5427 memcpy(data_offset, data, sizeof(FILE_BASIC_INFO));
5428 pSMB->ByteCount = cpu_to_le16(byte_count);
5429 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5430 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5432 cFYI(1, "SetPathInfo (times) returned %d", rc);
5434 cifs_buf_release(pSMB);
5442 /* Can not be used to set time stamps yet (due to old DOS time format) */
5443 /* Can be used to set attributes */
5444 #if 0 /* Possibly not needed - since it turns out that strangely NT4 has a bug
5445 handling it anyway and NT4 was what we thought it would be needed for
5446 Do not delete it until we prove whether needed for Win9x though */
5448 CIFSSMBSetAttrLegacy(int xid, struct cifsTconInfo *tcon, char *fileName,
5449 __u16 dos_attrs, const struct nls_table *nls_codepage)
5451 SETATTR_REQ *pSMB = NULL;
5452 SETATTR_RSP *pSMBr = NULL;
5457 cFYI(1, "In SetAttrLegacy");
5460 rc = smb_init(SMB_COM_SETATTR, 8, tcon, (void **) &pSMB,
5465 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5467 ConvertToUCS((__le16 *) pSMB->fileName, fileName,
5468 PATH_MAX, nls_codepage);
5469 name_len++; /* trailing null */
5471 } else { /* BB improve the check for buffer overruns BB */
5472 name_len = strnlen(fileName, PATH_MAX);
5473 name_len++; /* trailing null */
5474 strncpy(pSMB->fileName, fileName, name_len);
5476 pSMB->attr = cpu_to_le16(dos_attrs);
5477 pSMB->BufferFormat = 0x04;
5478 inc_rfc1001_len(pSMB, name_len + 1);
5479 pSMB->ByteCount = cpu_to_le16(name_len + 1);
5480 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5481 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5483 cFYI(1, "Error in LegacySetAttr = %d", rc);
5485 cifs_buf_release(pSMB);
5488 goto SetAttrLgcyRetry;
5492 #endif /* temporarily unneeded SetAttr legacy function */
5495 cifs_fill_unix_set_info(FILE_UNIX_BASIC_INFO *data_offset,
5496 const struct cifs_unix_set_info_args *args)
5498 u64 mode = args->mode;
5501 * Samba server ignores set of file size to zero due to bugs in some
5502 * older clients, but we should be precise - we use SetFileSize to
5503 * set file size and do not want to truncate file size to zero
5504 * accidentally as happened on one Samba server beta by putting
5505 * zero instead of -1 here
5507 data_offset->EndOfFile = cpu_to_le64(NO_CHANGE_64);
5508 data_offset->NumOfBytes = cpu_to_le64(NO_CHANGE_64);
5509 data_offset->LastStatusChange = cpu_to_le64(args->ctime);
5510 data_offset->LastAccessTime = cpu_to_le64(args->atime);
5511 data_offset->LastModificationTime = cpu_to_le64(args->mtime);
5512 data_offset->Uid = cpu_to_le64(args->uid);
5513 data_offset->Gid = cpu_to_le64(args->gid);
5514 /* better to leave device as zero when it is */
5515 data_offset->DevMajor = cpu_to_le64(MAJOR(args->device));
5516 data_offset->DevMinor = cpu_to_le64(MINOR(args->device));
5517 data_offset->Permissions = cpu_to_le64(mode);
5520 data_offset->Type = cpu_to_le32(UNIX_FILE);
5521 else if (S_ISDIR(mode))
5522 data_offset->Type = cpu_to_le32(UNIX_DIR);
5523 else if (S_ISLNK(mode))
5524 data_offset->Type = cpu_to_le32(UNIX_SYMLINK);
5525 else if (S_ISCHR(mode))
5526 data_offset->Type = cpu_to_le32(UNIX_CHARDEV);
5527 else if (S_ISBLK(mode))
5528 data_offset->Type = cpu_to_le32(UNIX_BLOCKDEV);
5529 else if (S_ISFIFO(mode))
5530 data_offset->Type = cpu_to_le32(UNIX_FIFO);
5531 else if (S_ISSOCK(mode))
5532 data_offset->Type = cpu_to_le32(UNIX_SOCKET);
5536 CIFSSMBUnixSetFileInfo(const int xid, struct cifsTconInfo *tcon,
5537 const struct cifs_unix_set_info_args *args,
5538 u16 fid, u32 pid_of_opener)
5540 struct smb_com_transaction2_sfi_req *pSMB = NULL;
5541 FILE_UNIX_BASIC_INFO *data_offset;
5543 u16 params, param_offset, offset, byte_count, count;
5545 cFYI(1, "Set Unix Info (via SetFileInfo)");
5546 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
5551 pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
5552 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));
5555 pSMB->MaxSetupCount = 0;
5559 pSMB->Reserved2 = 0;
5560 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
5561 offset = param_offset + params;
5563 data_offset = (FILE_UNIX_BASIC_INFO *)
5564 ((char *)(&pSMB->hdr.Protocol) + offset);
5565 count = sizeof(FILE_UNIX_BASIC_INFO);
5567 pSMB->MaxParameterCount = cpu_to_le16(2);
5568 /* BB find max SMB PDU from sess */
5569 pSMB->MaxDataCount = cpu_to_le16(1000);
5570 pSMB->SetupCount = 1;
5571 pSMB->Reserved3 = 0;
5572 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
5573 byte_count = 3 /* pad */ + params + count;
5574 pSMB->DataCount = cpu_to_le16(count);
5575 pSMB->ParameterCount = cpu_to_le16(params);
5576 pSMB->TotalDataCount = pSMB->DataCount;
5577 pSMB->TotalParameterCount = pSMB->ParameterCount;
5578 pSMB->ParameterOffset = cpu_to_le16(param_offset);
5579 pSMB->DataOffset = cpu_to_le16(offset);
5581 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_BASIC);
5582 pSMB->Reserved4 = 0;
5583 inc_rfc1001_len(pSMB, byte_count);
5584 pSMB->ByteCount = cpu_to_le16(byte_count);
5586 cifs_fill_unix_set_info(data_offset, args);
5588 rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0);
5590 cFYI(1, "Send error in Set Time (SetFileInfo) = %d", rc);
5592 /* Note: On -EAGAIN error only caller can retry on handle based calls
5593 since file handle passed in no longer valid */
5599 CIFSSMBUnixSetPathInfo(const int xid, struct cifsTconInfo *tcon, char *fileName,
5600 const struct cifs_unix_set_info_args *args,
5601 const struct nls_table *nls_codepage, int remap)
5603 TRANSACTION2_SPI_REQ *pSMB = NULL;
5604 TRANSACTION2_SPI_RSP *pSMBr = NULL;
5607 int bytes_returned = 0;
5608 FILE_UNIX_BASIC_INFO *data_offset;
5609 __u16 params, param_offset, offset, count, byte_count;
5611 cFYI(1, "In SetUID/GID/Mode");
5613 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5618 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5620 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
5621 PATH_MAX, nls_codepage, remap);
5622 name_len++; /* trailing null */
5624 } else { /* BB improve the check for buffer overruns BB */
5625 name_len = strnlen(fileName, PATH_MAX);
5626 name_len++; /* trailing null */
5627 strncpy(pSMB->FileName, fileName, name_len);
5630 params = 6 + name_len;
5631 count = sizeof(FILE_UNIX_BASIC_INFO);
5632 pSMB->MaxParameterCount = cpu_to_le16(2);
5633 /* BB find max SMB PDU from sess structure BB */
5634 pSMB->MaxDataCount = cpu_to_le16(1000);
5635 pSMB->MaxSetupCount = 0;
5639 pSMB->Reserved2 = 0;
5640 param_offset = offsetof(struct smb_com_transaction2_spi_req,
5641 InformationLevel) - 4;
5642 offset = param_offset + params;
5644 (FILE_UNIX_BASIC_INFO *) ((char *) &pSMB->hdr.Protocol +
5646 memset(data_offset, 0, count);
5647 pSMB->DataOffset = cpu_to_le16(offset);
5648 pSMB->ParameterOffset = cpu_to_le16(param_offset);
5649 pSMB->SetupCount = 1;
5650 pSMB->Reserved3 = 0;
5651 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
5652 byte_count = 3 /* pad */ + params + count;
5653 pSMB->ParameterCount = cpu_to_le16(params);
5654 pSMB->DataCount = cpu_to_le16(count);
5655 pSMB->TotalParameterCount = pSMB->ParameterCount;
5656 pSMB->TotalDataCount = pSMB->DataCount;
5657 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_BASIC);
5658 pSMB->Reserved4 = 0;
5659 inc_rfc1001_len(pSMB, byte_count);
5661 cifs_fill_unix_set_info(data_offset, args);
5663 pSMB->ByteCount = cpu_to_le16(byte_count);
5664 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5665 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5667 cFYI(1, "SetPathInfo (perms) returned %d", rc);
5669 cifs_buf_release(pSMB);
5675 #ifdef CONFIG_CIFS_XATTR
5677 * Do a path-based QUERY_ALL_EAS call and parse the result. This is a common
5678 * function used by listxattr and getxattr type calls. When ea_name is set,
5679 * it looks for that attribute name and stuffs that value into the EAData
5680 * buffer. When ea_name is NULL, it stuffs a list of attribute names into the
5681 * buffer. In both cases, the return value is either the length of the
5682 * resulting data or a negative error code. If EAData is a NULL pointer then
5683 * the data isn't copied to it, but the length is returned.
5686 CIFSSMBQAllEAs(const int xid, struct cifsTconInfo *tcon,
5687 const unsigned char *searchName, const unsigned char *ea_name,
5688 char *EAData, size_t buf_size,
5689 const struct nls_table *nls_codepage, int remap)
5691 /* BB assumes one setup word */
5692 TRANSACTION2_QPI_REQ *pSMB = NULL;
5693 TRANSACTION2_QPI_RSP *pSMBr = NULL;
5697 struct fealist *ea_response_data;
5698 struct fea *temp_fea;
5701 __u16 params, byte_count, data_offset;
5703 cFYI(1, "In Query All EAs path %s", searchName);
5705 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5710 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5712 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
5713 PATH_MAX, nls_codepage, remap);
5714 list_len++; /* trailing null */
5716 } else { /* BB improve the check for buffer overruns BB */
5717 list_len = strnlen(searchName, PATH_MAX);
5718 list_len++; /* trailing null */
5719 strncpy(pSMB->FileName, searchName, list_len);
5722 params = 2 /* level */ + 4 /* reserved */ + list_len /* includes NUL */;
5723 pSMB->TotalDataCount = 0;
5724 pSMB->MaxParameterCount = cpu_to_le16(2);
5725 /* BB find exact max SMB PDU from sess structure BB */
5726 pSMB->MaxDataCount = cpu_to_le16(CIFSMaxBufSize);
5727 pSMB->MaxSetupCount = 0;
5731 pSMB->Reserved2 = 0;
5732 pSMB->ParameterOffset = cpu_to_le16(offsetof(
5733 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
5734 pSMB->DataCount = 0;
5735 pSMB->DataOffset = 0;
5736 pSMB->SetupCount = 1;
5737 pSMB->Reserved3 = 0;
5738 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
5739 byte_count = params + 1 /* pad */ ;
5740 pSMB->TotalParameterCount = cpu_to_le16(params);
5741 pSMB->ParameterCount = pSMB->TotalParameterCount;
5742 pSMB->InformationLevel = cpu_to_le16(SMB_INFO_QUERY_ALL_EAS);
5743 pSMB->Reserved4 = 0;
5744 inc_rfc1001_len(pSMB, byte_count);
5745 pSMB->ByteCount = cpu_to_le16(byte_count);
5747 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5748 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5750 cFYI(1, "Send error in QueryAllEAs = %d", rc);
5755 /* BB also check enough total bytes returned */
5756 /* BB we need to improve the validity checking
5757 of these trans2 responses */
5759 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
5760 if (rc || get_bcc(&pSMBr->hdr) < 4) {
5761 rc = -EIO; /* bad smb */
5765 /* check that length of list is not more than bcc */
5766 /* check that each entry does not go beyond length
5768 /* check that each element of each entry does not
5769 go beyond end of list */
5770 /* validate_trans2_offsets() */
5771 /* BB check if start of smb + data_offset > &bcc+ bcc */
5773 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
5774 ea_response_data = (struct fealist *)
5775 (((char *) &pSMBr->hdr.Protocol) + data_offset);
5777 list_len = le32_to_cpu(ea_response_data->list_len);
5778 cFYI(1, "ea length %d", list_len);
5779 if (list_len <= 8) {
5780 cFYI(1, "empty EA list returned from server");
5784 /* make sure list_len doesn't go past end of SMB */
5785 end_of_smb = (char *)pByteArea(&pSMBr->hdr) + get_bcc(&pSMBr->hdr);
5786 if ((char *)ea_response_data + list_len > end_of_smb) {
5787 cFYI(1, "EA list appears to go beyond SMB");
5792 /* account for ea list len */
5794 temp_fea = ea_response_data->list;
5795 temp_ptr = (char *)temp_fea;
5796 while (list_len > 0) {
5797 unsigned int name_len;
5802 /* make sure we can read name_len and value_len */
5804 cFYI(1, "EA entry goes beyond length of list");
5809 name_len = temp_fea->name_len;
5810 value_len = le16_to_cpu(temp_fea->value_len);
5811 list_len -= name_len + 1 + value_len;
5813 cFYI(1, "EA entry goes beyond length of list");
5819 if (strncmp(ea_name, temp_ptr, name_len) == 0) {
5820 temp_ptr += name_len + 1;
5824 if ((size_t)value_len > buf_size) {
5828 memcpy(EAData, temp_ptr, value_len);
5832 /* account for prefix user. and trailing null */
5833 rc += (5 + 1 + name_len);
5834 if (rc < (int) buf_size) {
5835 memcpy(EAData, "user.", 5);
5837 memcpy(EAData, temp_ptr, name_len);
5839 /* null terminate name */
5842 } else if (buf_size == 0) {
5843 /* skip copy - calc size only */
5845 /* stop before overrun buffer */
5850 temp_ptr += name_len + 1 + value_len;
5851 temp_fea = (struct fea *)temp_ptr;
5854 /* didn't find the named attribute */
5859 cifs_buf_release(pSMB);
5867 CIFSSMBSetEA(const int xid, struct cifsTconInfo *tcon, const char *fileName,
5868 const char *ea_name, const void *ea_value,
5869 const __u16 ea_value_len, const struct nls_table *nls_codepage,
5872 struct smb_com_transaction2_spi_req *pSMB = NULL;
5873 struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
5874 struct fealist *parm_data;
5877 int bytes_returned = 0;
5878 __u16 params, param_offset, byte_count, offset, count;
5880 cFYI(1, "In SetEA");
5882 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5887 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5889 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
5890 PATH_MAX, nls_codepage, remap);
5891 name_len++; /* trailing null */
5893 } else { /* BB improve the check for buffer overruns BB */
5894 name_len = strnlen(fileName, PATH_MAX);
5895 name_len++; /* trailing null */
5896 strncpy(pSMB->FileName, fileName, name_len);
5899 params = 6 + name_len;
5901 /* done calculating parms using name_len of file name,
5902 now use name_len to calculate length of ea name
5903 we are going to create in the inode xattrs */
5904 if (ea_name == NULL)
5907 name_len = strnlen(ea_name, 255);
5909 count = sizeof(*parm_data) + ea_value_len + name_len;
5910 pSMB->MaxParameterCount = cpu_to_le16(2);
5911 /* BB find max SMB PDU from sess */
5912 pSMB->MaxDataCount = cpu_to_le16(1000);
5913 pSMB->MaxSetupCount = 0;
5917 pSMB->Reserved2 = 0;
5918 param_offset = offsetof(struct smb_com_transaction2_spi_req,
5919 InformationLevel) - 4;
5920 offset = param_offset + params;
5921 pSMB->InformationLevel =
5922 cpu_to_le16(SMB_SET_FILE_EA);
5925 (struct fealist *) (((char *) &pSMB->hdr.Protocol) +
5927 pSMB->ParameterOffset = cpu_to_le16(param_offset);
5928 pSMB->DataOffset = cpu_to_le16(offset);
5929 pSMB->SetupCount = 1;
5930 pSMB->Reserved3 = 0;
5931 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
5932 byte_count = 3 /* pad */ + params + count;
5933 pSMB->DataCount = cpu_to_le16(count);
5934 parm_data->list_len = cpu_to_le32(count);
5935 parm_data->list[0].EA_flags = 0;
5936 /* we checked above that name len is less than 255 */
5937 parm_data->list[0].name_len = (__u8)name_len;
5938 /* EA names are always ASCII */
5940 strncpy(parm_data->list[0].name, ea_name, name_len);
5941 parm_data->list[0].name[name_len] = 0;
5942 parm_data->list[0].value_len = cpu_to_le16(ea_value_len);
5943 /* caller ensures that ea_value_len is less than 64K but
5944 we need to ensure that it fits within the smb */
5946 /*BB add length check to see if it would fit in
5947 negotiated SMB buffer size BB */
5948 /* if (ea_value_len > buffer_size - 512 (enough for header)) */
5950 memcpy(parm_data->list[0].name+name_len+1,
5951 ea_value, ea_value_len);
5953 pSMB->TotalDataCount = pSMB->DataCount;
5954 pSMB->ParameterCount = cpu_to_le16(params);
5955 pSMB->TotalParameterCount = pSMB->ParameterCount;
5956 pSMB->Reserved4 = 0;
5957 inc_rfc1001_len(pSMB, byte_count);
5958 pSMB->ByteCount = cpu_to_le16(byte_count);
5959 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5960 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5962 cFYI(1, "SetPathInfo (EA) returned %d", rc);
5964 cifs_buf_release(pSMB);
5973 #ifdef CONFIG_CIFS_DNOTIFY_EXPERIMENTAL /* BB unused temporarily */
5975 * Years ago the kernel added a "dnotify" function for Samba server,
5976 * to allow network clients (such as Windows) to display updated
5977 * lists of files in directory listings automatically when
5978 * files are added by one user when another user has the
5979 * same directory open on their desktop. The Linux cifs kernel
5980 * client hooked into the kernel side of this interface for
5981 * the same reason, but ironically when the VFS moved from
5982 * "dnotify" to "inotify" it became harder to plug in Linux
5983 * network file system clients (the most obvious use case
5984 * for notify interfaces is when multiple users can update
5985 * the contents of the same directory - exactly what network
5986 * file systems can do) although the server (Samba) could
5987 * still use it. For the short term we leave the worker
5988 * function ifdeffed out (below) until inotify is fixed
5989 * in the VFS to make it easier to plug in network file
5990 * system clients. If inotify turns out to be permanently
5991 * incompatible for network fs clients, we could instead simply
5992 * expose this config flag by adding a future cifs (and smb2) notify ioctl.
5994 int CIFSSMBNotify(const int xid, struct cifsTconInfo *tcon,
5995 const int notify_subdirs, const __u16 netfid,
5996 __u32 filter, struct file *pfile, int multishot,
5997 const struct nls_table *nls_codepage)
6000 struct smb_com_transaction_change_notify_req *pSMB = NULL;
6001 struct smb_com_ntransaction_change_notify_rsp *pSMBr = NULL;
6002 struct dir_notify_req *dnotify_req;
6005 cFYI(1, "In CIFSSMBNotify for file handle %d", (int)netfid);
6006 rc = smb_init(SMB_COM_NT_TRANSACT, 23, tcon, (void **) &pSMB,
6011 pSMB->TotalParameterCount = 0 ;
6012 pSMB->TotalDataCount = 0;
6013 pSMB->MaxParameterCount = cpu_to_le32(2);
6014 /* BB find exact data count max from sess structure BB */
6015 pSMB->MaxDataCount = 0; /* same in little endian or be */
6016 /* BB VERIFY verify which is correct for above BB */
6017 pSMB->MaxDataCount = cpu_to_le32((tcon->ses->server->maxBuf -
6018 MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
6020 pSMB->MaxSetupCount = 4;
6022 pSMB->ParameterOffset = 0;
6023 pSMB->DataCount = 0;
6024 pSMB->DataOffset = 0;
6025 pSMB->SetupCount = 4; /* single byte does not need le conversion */
6026 pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_NOTIFY_CHANGE);
6027 pSMB->ParameterCount = pSMB->TotalParameterCount;
6029 pSMB->WatchTree = 1; /* one byte - no le conversion needed */
6030 pSMB->Reserved2 = 0;
6031 pSMB->CompletionFilter = cpu_to_le32(filter);
6032 pSMB->Fid = netfid; /* file handle always le */
6033 pSMB->ByteCount = 0;
6035 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
6036 (struct smb_hdr *)pSMBr, &bytes_returned,
6039 cFYI(1, "Error in Notify = %d", rc);
6041 /* Add file to outstanding requests */
6042 /* BB change to kmem cache alloc */
6043 dnotify_req = kmalloc(
6044 sizeof(struct dir_notify_req),
6047 dnotify_req->Pid = pSMB->hdr.Pid;
6048 dnotify_req->PidHigh = pSMB->hdr.PidHigh;
6049 dnotify_req->Mid = pSMB->hdr.Mid;
6050 dnotify_req->Tid = pSMB->hdr.Tid;
6051 dnotify_req->Uid = pSMB->hdr.Uid;
6052 dnotify_req->netfid = netfid;
6053 dnotify_req->pfile = pfile;
6054 dnotify_req->filter = filter;
6055 dnotify_req->multishot = multishot;
6056 spin_lock(&GlobalMid_Lock);
6057 list_add_tail(&dnotify_req->lhead,
6058 &GlobalDnotifyReqList);
6059 spin_unlock(&GlobalMid_Lock);
6063 cifs_buf_release(pSMB);
6066 #endif /* was needed for dnotify, and will be needed for inotify when VFS fix */