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 <asm/uaccess.h>
39 #include "cifsproto.h"
40 #include "cifs_unicode.h"
41 #include "cifs_debug.h"
43 #ifdef CONFIG_CIFS_POSIX
48 #ifdef CONFIG_CIFS_WEAK_PW_HASH
49 {LANMAN_PROT, "\2LM1.2X002"},
50 {LANMAN2_PROT, "\2LANMAN2.1"},
51 #endif /* weak password hashing for legacy clients */
52 {CIFS_PROT, "\2NT LM 0.12"},
53 {POSIX_PROT, "\2POSIX 2"},
61 #ifdef CONFIG_CIFS_WEAK_PW_HASH
62 {LANMAN_PROT, "\2LM1.2X002"},
63 {LANMAN2_PROT, "\2LANMAN2.1"},
64 #endif /* weak password hashing for legacy clients */
65 {CIFS_PROT, "\2NT LM 0.12"},
70 /* define the number of elements in the cifs dialect array */
71 #ifdef CONFIG_CIFS_POSIX
72 #ifdef CONFIG_CIFS_WEAK_PW_HASH
73 #define CIFS_NUM_PROT 4
75 #define CIFS_NUM_PROT 2
76 #endif /* CIFS_WEAK_PW_HASH */
78 #ifdef CONFIG_CIFS_WEAK_PW_HASH
79 #define CIFS_NUM_PROT 3
81 #define CIFS_NUM_PROT 1
82 #endif /* CONFIG_CIFS_WEAK_PW_HASH */
83 #endif /* CIFS_POSIX */
85 /* Mark as invalid, all open files on tree connections since they
86 were closed when session to server was lost */
87 static void mark_open_files_invalid(struct cifsTconInfo *pTcon)
89 struct cifsFileInfo *open_file = NULL;
90 struct list_head *tmp;
91 struct list_head *tmp1;
93 /* list all files open on tree connection and mark them invalid */
94 spin_lock(&cifs_file_list_lock);
95 list_for_each_safe(tmp, tmp1, &pTcon->openFileList) {
96 open_file = list_entry(tmp, struct cifsFileInfo, tlist);
97 open_file->invalidHandle = true;
98 open_file->oplock_break_cancelled = true;
100 spin_unlock(&cifs_file_list_lock);
101 /* BB Add call to invalidate_inodes(sb) for all superblocks mounted
105 /* reconnect the socket, tcon, and smb session if needed */
107 cifs_reconnect_tcon(struct cifsTconInfo *tcon, int smb_command)
110 struct cifsSesInfo *ses;
111 struct TCP_Server_Info *server;
112 struct nls_table *nls_codepage;
115 * SMBs NegProt, SessSetup, uLogoff do not have tcon yet so check for
116 * tcp and smb session status done differently for those three - in the
123 server = ses->server;
126 * only tree disconnect, open, and write, (and ulogoff which does not
127 * have tcon) are allowed as we start force umount
129 if (tcon->tidStatus == CifsExiting) {
130 if (smb_command != SMB_COM_WRITE_ANDX &&
131 smb_command != SMB_COM_OPEN_ANDX &&
132 smb_command != SMB_COM_TREE_DISCONNECT) {
133 cFYI(1, "can not send cmd %d while umounting",
139 if (ses->status == CifsExiting)
143 * Give demultiplex thread up to 10 seconds to reconnect, should be
144 * greater than cifs socket timeout which is 7 seconds
146 while (server->tcpStatus == CifsNeedReconnect) {
147 wait_event_interruptible_timeout(server->response_q,
148 (server->tcpStatus == CifsGood), 10 * HZ);
150 /* is TCP session is reestablished now ?*/
151 if (server->tcpStatus != CifsNeedReconnect)
155 * on "soft" mounts we wait once. Hard mounts keep
156 * retrying until process is killed or server comes
159 if (!tcon->retry || ses->status == CifsExiting) {
160 cFYI(1, "gave up waiting on reconnect in smb_init");
165 if (!ses->need_reconnect && !tcon->need_reconnect)
168 nls_codepage = load_nls_default();
171 * need to prevent multiple threads trying to simultaneously
172 * reconnect the same SMB session
174 mutex_lock(&ses->session_mutex);
175 rc = cifs_negotiate_protocol(0, ses);
176 if (rc == 0 && ses->need_reconnect)
177 rc = cifs_setup_session(0, ses, nls_codepage);
179 /* do we need to reconnect tcon? */
180 if (rc || !tcon->need_reconnect) {
181 mutex_unlock(&ses->session_mutex);
185 mark_open_files_invalid(tcon);
186 rc = CIFSTCon(0, ses, tcon->treeName, tcon, nls_codepage);
187 mutex_unlock(&ses->session_mutex);
188 cFYI(1, "reconnect tcon rc = %d", rc);
194 * FIXME: check if wsize needs updated due to negotiated smb buffer
197 atomic_inc(&tconInfoReconnectCount);
199 /* tell server Unix caps we support */
200 if (ses->capabilities & CAP_UNIX)
201 reset_cifs_unix_caps(0, tcon, NULL, NULL);
204 * Removed call to reopen open files here. It is safer (and faster) to
205 * reopen files one at a time as needed in read and write.
207 * FIXME: what about file locks? don't we need to reclaim them ASAP?
212 * Check if handle based operation so we know whether we can continue
213 * or not without returning to caller to reset file handle
215 switch (smb_command) {
216 case SMB_COM_READ_ANDX:
217 case SMB_COM_WRITE_ANDX:
219 case SMB_COM_FIND_CLOSE2:
220 case SMB_COM_LOCKING_ANDX:
224 unload_nls(nls_codepage);
228 /* Allocate and return pointer to an SMB request buffer, and set basic
229 SMB information in the SMB header. If the return code is zero, this
230 function must have filled in request_buf pointer */
232 small_smb_init(int smb_command, int wct, struct cifsTconInfo *tcon,
237 rc = cifs_reconnect_tcon(tcon, smb_command);
241 *request_buf = cifs_small_buf_get();
242 if (*request_buf == NULL) {
243 /* BB should we add a retry in here if not a writepage? */
247 header_assemble((struct smb_hdr *) *request_buf, smb_command,
251 cifs_stats_inc(&tcon->num_smbs_sent);
257 small_smb_init_no_tc(const int smb_command, const int wct,
258 struct cifsSesInfo *ses, void **request_buf)
261 struct smb_hdr *buffer;
263 rc = small_smb_init(smb_command, wct, NULL, request_buf);
267 buffer = (struct smb_hdr *)*request_buf;
268 buffer->Mid = GetNextMid(ses->server);
269 if (ses->capabilities & CAP_UNICODE)
270 buffer->Flags2 |= SMBFLG2_UNICODE;
271 if (ses->capabilities & CAP_STATUS32)
272 buffer->Flags2 |= SMBFLG2_ERR_STATUS;
274 /* uid, tid can stay at zero as set in header assemble */
276 /* BB add support for turning on the signing when
277 this function is used after 1st of session setup requests */
282 /* If the return code is zero, this function must fill in request_buf pointer */
284 __smb_init(int smb_command, int wct, struct cifsTconInfo *tcon,
285 void **request_buf, void **response_buf)
287 *request_buf = cifs_buf_get();
288 if (*request_buf == NULL) {
289 /* BB should we add a retry in here if not a writepage? */
292 /* Although the original thought was we needed the response buf for */
293 /* potential retries of smb operations it turns out we can determine */
294 /* from the mid flags when the request buffer can be resent without */
295 /* having to use a second distinct buffer for the response */
297 *response_buf = *request_buf;
299 header_assemble((struct smb_hdr *) *request_buf, smb_command, tcon,
303 cifs_stats_inc(&tcon->num_smbs_sent);
308 /* If the return code is zero, this function must fill in request_buf pointer */
310 smb_init(int smb_command, int wct, struct cifsTconInfo *tcon,
311 void **request_buf, void **response_buf)
315 rc = cifs_reconnect_tcon(tcon, smb_command);
319 return __smb_init(smb_command, wct, tcon, request_buf, response_buf);
323 smb_init_no_reconnect(int smb_command, int wct, struct cifsTconInfo *tcon,
324 void **request_buf, void **response_buf)
326 if (tcon->ses->need_reconnect || tcon->need_reconnect)
329 return __smb_init(smb_command, wct, tcon, request_buf, response_buf);
332 static int validate_t2(struct smb_t2_rsp *pSMB)
337 /* check for plausible wct, bcc and t2 data and parm sizes */
338 /* check for parm and data offset going beyond end of smb */
339 if (pSMB->hdr.WordCount >= 10) {
340 if ((le16_to_cpu(pSMB->t2_rsp.ParameterOffset) <= 1024) &&
341 (le16_to_cpu(pSMB->t2_rsp.DataOffset) <= 1024)) {
342 /* check that bcc is at least as big as parms + data */
343 /* check that bcc is less than negotiated smb buffer */
344 total_size = le16_to_cpu(pSMB->t2_rsp.ParameterCount);
345 if (total_size < 512) {
347 le16_to_cpu(pSMB->t2_rsp.DataCount);
348 if (total_size <= get_bcc(&pSMB->hdr) &&
350 CIFSMaxBufSize + MAX_CIFS_HDR_SIZE) {
356 cifs_dump_mem("Invalid transact2 SMB: ", (char *)pSMB,
357 sizeof(struct smb_t2_rsp) + 16);
362 CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses)
365 NEGOTIATE_RSP *pSMBr;
369 struct TCP_Server_Info *server;
371 unsigned int secFlags;
374 server = ses->server;
379 rc = smb_init(SMB_COM_NEGOTIATE, 0, NULL /* no tcon yet */ ,
380 (void **) &pSMB, (void **) &pSMBr);
384 /* if any of auth flags (ie not sign or seal) are overriden use them */
385 if (ses->overrideSecFlg & (~(CIFSSEC_MUST_SIGN | CIFSSEC_MUST_SEAL)))
386 secFlags = ses->overrideSecFlg; /* BB FIXME fix sign flags? */
387 else /* if override flags set only sign/seal OR them with global auth */
388 secFlags = global_secflags | ses->overrideSecFlg;
390 cFYI(1, "secFlags 0x%x", secFlags);
392 pSMB->hdr.Mid = GetNextMid(server);
393 pSMB->hdr.Flags2 |= (SMBFLG2_UNICODE | SMBFLG2_ERR_STATUS);
395 if ((secFlags & CIFSSEC_MUST_KRB5) == CIFSSEC_MUST_KRB5)
396 pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC;
397 else if ((secFlags & CIFSSEC_AUTH_MASK) == CIFSSEC_MAY_KRB5) {
398 cFYI(1, "Kerberos only mechanism, enable extended security");
399 pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC;
400 } else if ((secFlags & CIFSSEC_MUST_NTLMSSP) == CIFSSEC_MUST_NTLMSSP)
401 pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC;
402 else if ((secFlags & CIFSSEC_AUTH_MASK) == CIFSSEC_MAY_NTLMSSP) {
403 cFYI(1, "NTLMSSP only mechanism, enable extended security");
404 pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC;
408 for (i = 0; i < CIFS_NUM_PROT; i++) {
409 strncpy(pSMB->DialectsArray+count, protocols[i].name, 16);
410 count += strlen(protocols[i].name) + 1;
411 /* null at end of source and target buffers anyway */
413 pSMB->hdr.smb_buf_length += count;
414 pSMB->ByteCount = cpu_to_le16(count);
416 rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB,
417 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
421 server->dialect = le16_to_cpu(pSMBr->DialectIndex);
422 cFYI(1, "Dialect: %d", server->dialect);
423 /* Check wct = 1 error case */
424 if ((pSMBr->hdr.WordCount < 13) || (server->dialect == BAD_PROT)) {
425 /* core returns wct = 1, but we do not ask for core - otherwise
426 small wct just comes when dialect index is -1 indicating we
427 could not negotiate a common dialect */
430 #ifdef CONFIG_CIFS_WEAK_PW_HASH
431 } else if ((pSMBr->hdr.WordCount == 13)
432 && ((server->dialect == LANMAN_PROT)
433 || (server->dialect == LANMAN2_PROT))) {
435 struct lanman_neg_rsp *rsp = (struct lanman_neg_rsp *)pSMBr;
437 if ((secFlags & CIFSSEC_MAY_LANMAN) ||
438 (secFlags & CIFSSEC_MAY_PLNTXT))
439 server->secType = LANMAN;
441 cERROR(1, "mount failed weak security disabled"
442 " in /proc/fs/cifs/SecurityFlags");
446 server->secMode = (__u8)le16_to_cpu(rsp->SecurityMode);
447 server->maxReq = le16_to_cpu(rsp->MaxMpxCount);
448 server->maxBuf = min((__u32)le16_to_cpu(rsp->MaxBufSize),
449 (__u32)CIFSMaxBufSize + MAX_CIFS_HDR_SIZE);
450 server->max_vcs = le16_to_cpu(rsp->MaxNumberVcs);
451 /* even though we do not use raw we might as well set this
452 accurately, in case we ever find a need for it */
453 if ((le16_to_cpu(rsp->RawMode) & RAW_ENABLE) == RAW_ENABLE) {
454 server->max_rw = 0xFF00;
455 server->capabilities = CAP_MPX_MODE | CAP_RAW_MODE;
457 server->max_rw = 0;/* do not need to use raw anyway */
458 server->capabilities = CAP_MPX_MODE;
460 tmp = (__s16)le16_to_cpu(rsp->ServerTimeZone);
462 /* OS/2 often does not set timezone therefore
463 * we must use server time to calc time zone.
464 * Could deviate slightly from the right zone.
465 * Smallest defined timezone difference is 15 minutes
466 * (i.e. Nepal). Rounding up/down is done to match
469 int val, seconds, remain, result;
470 struct timespec ts, utc;
472 ts = cnvrtDosUnixTm(rsp->SrvTime.Date,
473 rsp->SrvTime.Time, 0);
474 cFYI(1, "SrvTime %d sec since 1970 (utc: %d) diff: %d",
475 (int)ts.tv_sec, (int)utc.tv_sec,
476 (int)(utc.tv_sec - ts.tv_sec));
477 val = (int)(utc.tv_sec - ts.tv_sec);
479 result = (seconds / MIN_TZ_ADJ) * MIN_TZ_ADJ;
480 remain = seconds % MIN_TZ_ADJ;
481 if (remain >= (MIN_TZ_ADJ / 2))
482 result += MIN_TZ_ADJ;
485 server->timeAdj = result;
487 server->timeAdj = (int)tmp;
488 server->timeAdj *= 60; /* also in seconds */
490 cFYI(1, "server->timeAdj: %d seconds", server->timeAdj);
493 /* BB get server time for time conversions and add
494 code to use it and timezone since this is not UTC */
496 if (rsp->EncryptionKeyLength ==
497 cpu_to_le16(CIFS_CRYPTO_KEY_SIZE)) {
498 memcpy(ses->server->cryptkey, rsp->EncryptionKey,
499 CIFS_CRYPTO_KEY_SIZE);
500 } else if (server->secMode & SECMODE_PW_ENCRYPT) {
501 rc = -EIO; /* need cryptkey unless plain text */
505 cFYI(1, "LANMAN negotiated");
506 /* we will not end up setting signing flags - as no signing
507 was in LANMAN and server did not return the flags on */
509 #else /* weak security disabled */
510 } else if (pSMBr->hdr.WordCount == 13) {
511 cERROR(1, "mount failed, cifs module not built "
512 "with CIFS_WEAK_PW_HASH support");
514 #endif /* WEAK_PW_HASH */
516 } else if (pSMBr->hdr.WordCount != 17) {
521 /* else wct == 17 NTLM */
522 server->secMode = pSMBr->SecurityMode;
523 if ((server->secMode & SECMODE_USER) == 0)
524 cFYI(1, "share mode security");
526 if ((server->secMode & SECMODE_PW_ENCRYPT) == 0)
527 #ifdef CONFIG_CIFS_WEAK_PW_HASH
528 if ((secFlags & CIFSSEC_MAY_PLNTXT) == 0)
529 #endif /* CIFS_WEAK_PW_HASH */
530 cERROR(1, "Server requests plain text password"
531 " but client support disabled");
533 if ((secFlags & CIFSSEC_MUST_NTLMV2) == CIFSSEC_MUST_NTLMV2)
534 server->secType = NTLMv2;
535 else if (secFlags & CIFSSEC_MAY_NTLM)
536 server->secType = NTLM;
537 else if (secFlags & CIFSSEC_MAY_NTLMV2)
538 server->secType = NTLMv2;
539 else if (secFlags & CIFSSEC_MAY_KRB5)
540 server->secType = Kerberos;
541 else if (secFlags & CIFSSEC_MAY_NTLMSSP)
542 server->secType = RawNTLMSSP;
543 else if (secFlags & CIFSSEC_MAY_LANMAN)
544 server->secType = LANMAN;
545 /* #ifdef CONFIG_CIFS_EXPERIMENTAL
546 else if (secFlags & CIFSSEC_MAY_PLNTXT)
551 cERROR(1, "Invalid security type");
554 /* else ... any others ...? */
556 /* one byte, so no need to convert this or EncryptionKeyLen from
558 server->maxReq = le16_to_cpu(pSMBr->MaxMpxCount);
559 /* probably no need to store and check maxvcs */
560 server->maxBuf = min(le32_to_cpu(pSMBr->MaxBufferSize),
561 (__u32) CIFSMaxBufSize + MAX_CIFS_HDR_SIZE);
562 server->max_rw = le32_to_cpu(pSMBr->MaxRawSize);
563 cFYI(DBG2, "Max buf = %d", ses->server->maxBuf);
564 server->capabilities = le32_to_cpu(pSMBr->Capabilities);
565 server->timeAdj = (int)(__s16)le16_to_cpu(pSMBr->ServerTimeZone);
566 server->timeAdj *= 60;
567 if (pSMBr->EncryptionKeyLength == CIFS_CRYPTO_KEY_SIZE) {
568 memcpy(ses->server->cryptkey, pSMBr->u.EncryptionKey,
569 CIFS_CRYPTO_KEY_SIZE);
570 } else if ((pSMBr->hdr.Flags2 & SMBFLG2_EXT_SEC)
571 && (pSMBr->EncryptionKeyLength == 0)) {
572 /* decode security blob */
573 } else if (server->secMode & SECMODE_PW_ENCRYPT) {
574 rc = -EIO; /* no crypt key only if plain text pwd */
578 /* BB might be helpful to save off the domain of server here */
580 if ((pSMBr->hdr.Flags2 & SMBFLG2_EXT_SEC) &&
581 (server->capabilities & CAP_EXTENDED_SECURITY)) {
582 count = pSMBr->ByteCount;
587 spin_lock(&cifs_tcp_ses_lock);
588 if (server->srv_count > 1) {
589 spin_unlock(&cifs_tcp_ses_lock);
590 if (memcmp(server->server_GUID,
591 pSMBr->u.extended_response.
593 cFYI(1, "server UID changed");
594 memcpy(server->server_GUID,
595 pSMBr->u.extended_response.GUID,
599 spin_unlock(&cifs_tcp_ses_lock);
600 memcpy(server->server_GUID,
601 pSMBr->u.extended_response.GUID, 16);
605 server->secType = RawNTLMSSP;
607 rc = decode_negTokenInit(pSMBr->u.extended_response.
608 SecurityBlob, count - 16,
614 if (server->secType == Kerberos) {
615 if (!server->sec_kerberos &&
616 !server->sec_mskerberos)
618 } else if (server->secType == RawNTLMSSP) {
619 if (!server->sec_ntlmssp)
625 server->capabilities &= ~CAP_EXTENDED_SECURITY;
627 #ifdef CONFIG_CIFS_WEAK_PW_HASH
630 if ((secFlags & CIFSSEC_MAY_SIGN) == 0) {
631 /* MUST_SIGN already includes the MAY_SIGN FLAG
632 so if this is zero it means that signing is disabled */
633 cFYI(1, "Signing disabled");
634 if (server->secMode & SECMODE_SIGN_REQUIRED) {
635 cERROR(1, "Server requires "
636 "packet signing to be enabled in "
637 "/proc/fs/cifs/SecurityFlags.");
641 ~(SECMODE_SIGN_ENABLED | SECMODE_SIGN_REQUIRED);
642 } else if ((secFlags & CIFSSEC_MUST_SIGN) == CIFSSEC_MUST_SIGN) {
643 /* signing required */
644 cFYI(1, "Must sign - secFlags 0x%x", secFlags);
645 if ((server->secMode &
646 (SECMODE_SIGN_ENABLED | SECMODE_SIGN_REQUIRED)) == 0) {
647 cERROR(1, "signing required but server lacks support");
650 server->secMode |= SECMODE_SIGN_REQUIRED;
652 /* signing optional ie CIFSSEC_MAY_SIGN */
653 if ((server->secMode & SECMODE_SIGN_REQUIRED) == 0)
655 ~(SECMODE_SIGN_ENABLED | SECMODE_SIGN_REQUIRED);
659 cifs_buf_release(pSMB);
661 cFYI(1, "negprot rc %d", rc);
666 CIFSSMBTDis(const int xid, struct cifsTconInfo *tcon)
668 struct smb_hdr *smb_buffer;
671 cFYI(1, "In tree disconnect");
673 /* BB: do we need to check this? These should never be NULL. */
674 if ((tcon->ses == NULL) || (tcon->ses->server == NULL))
678 * No need to return error on this operation if tid invalidated and
679 * closed on server already e.g. due to tcp session crashing. Also,
680 * the tcon is no longer on the list, so no need to take lock before
683 if ((tcon->need_reconnect) || (tcon->ses->need_reconnect))
686 rc = small_smb_init(SMB_COM_TREE_DISCONNECT, 0, tcon,
687 (void **)&smb_buffer);
691 rc = SendReceiveNoRsp(xid, tcon->ses, smb_buffer, 0);
693 cFYI(1, "Tree disconnect failed %d", rc);
695 /* No need to return error on this operation if tid invalidated and
696 closed on server already e.g. due to tcp session crashing */
704 * This is a no-op for now. We're not really interested in the reply, but
705 * rather in the fact that the server sent one and that server->lstrp
708 * FIXME: maybe we should consider checking that the reply matches request?
711 cifs_echo_callback(struct mid_q_entry *mid)
713 struct TCP_Server_Info *server = mid->callback_data;
715 DeleteMidQEntry(mid);
716 atomic_dec(&server->inFlight);
717 wake_up(&server->request_q);
721 CIFSSMBEcho(struct TCP_Server_Info *server)
726 cFYI(1, "In echo request");
728 rc = small_smb_init(SMB_COM_ECHO, 0, NULL, (void **)&smb);
732 /* set up echo request */
733 smb->hdr.Tid = cpu_to_le16(0xffff);
734 smb->hdr.WordCount = cpu_to_le16(1);
735 smb->EchoCount = cpu_to_le16(1);
736 smb->ByteCount = cpu_to_le16(1);
738 smb->hdr.smb_buf_length += 3;
740 rc = cifs_call_async(server, (struct smb_hdr *)smb,
741 cifs_echo_callback, server);
743 cFYI(1, "Echo request failed: %d", rc);
745 cifs_small_buf_release(smb);
751 CIFSSMBLogoff(const int xid, struct cifsSesInfo *ses)
753 LOGOFF_ANDX_REQ *pSMB;
756 cFYI(1, "In SMBLogoff for session disconnect");
759 * BB: do we need to check validity of ses and server? They should
760 * always be valid since we have an active reference. If not, that
761 * should probably be a BUG()
763 if (!ses || !ses->server)
766 mutex_lock(&ses->session_mutex);
767 if (ses->need_reconnect)
768 goto session_already_dead; /* no need to send SMBlogoff if uid
769 already closed due to reconnect */
770 rc = small_smb_init(SMB_COM_LOGOFF_ANDX, 2, NULL, (void **)&pSMB);
772 mutex_unlock(&ses->session_mutex);
776 pSMB->hdr.Mid = GetNextMid(ses->server);
778 if (ses->server->secMode &
779 (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
780 pSMB->hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
782 pSMB->hdr.Uid = ses->Suid;
784 pSMB->AndXCommand = 0xFF;
785 rc = SendReceiveNoRsp(xid, ses, (struct smb_hdr *) pSMB, 0);
786 session_already_dead:
787 mutex_unlock(&ses->session_mutex);
789 /* if session dead then we do not need to do ulogoff,
790 since server closed smb session, no sense reporting
798 CIFSPOSIXDelFile(const int xid, struct cifsTconInfo *tcon, const char *fileName,
799 __u16 type, const struct nls_table *nls_codepage, int remap)
801 TRANSACTION2_SPI_REQ *pSMB = NULL;
802 TRANSACTION2_SPI_RSP *pSMBr = NULL;
803 struct unlink_psx_rq *pRqD;
806 int bytes_returned = 0;
807 __u16 params, param_offset, offset, byte_count;
809 cFYI(1, "In POSIX delete");
811 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
816 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
818 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
819 PATH_MAX, nls_codepage, remap);
820 name_len++; /* trailing null */
822 } else { /* BB add path length overrun check */
823 name_len = strnlen(fileName, PATH_MAX);
824 name_len++; /* trailing null */
825 strncpy(pSMB->FileName, fileName, name_len);
828 params = 6 + name_len;
829 pSMB->MaxParameterCount = cpu_to_le16(2);
830 pSMB->MaxDataCount = 0; /* BB double check this with jra */
831 pSMB->MaxSetupCount = 0;
836 param_offset = offsetof(struct smb_com_transaction2_spi_req,
837 InformationLevel) - 4;
838 offset = param_offset + params;
840 /* Setup pointer to Request Data (inode type) */
841 pRqD = (struct unlink_psx_rq *)(((char *)&pSMB->hdr.Protocol) + offset);
842 pRqD->type = cpu_to_le16(type);
843 pSMB->ParameterOffset = cpu_to_le16(param_offset);
844 pSMB->DataOffset = cpu_to_le16(offset);
845 pSMB->SetupCount = 1;
847 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
848 byte_count = 3 /* pad */ + params + sizeof(struct unlink_psx_rq);
850 pSMB->DataCount = cpu_to_le16(sizeof(struct unlink_psx_rq));
851 pSMB->TotalDataCount = cpu_to_le16(sizeof(struct unlink_psx_rq));
852 pSMB->ParameterCount = cpu_to_le16(params);
853 pSMB->TotalParameterCount = pSMB->ParameterCount;
854 pSMB->InformationLevel = cpu_to_le16(SMB_POSIX_UNLINK);
856 pSMB->hdr.smb_buf_length += byte_count;
857 pSMB->ByteCount = cpu_to_le16(byte_count);
858 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
859 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
861 cFYI(1, "Posix delete returned %d", rc);
862 cifs_buf_release(pSMB);
864 cifs_stats_inc(&tcon->num_deletes);
873 CIFSSMBDelFile(const int xid, struct cifsTconInfo *tcon, const char *fileName,
874 const struct nls_table *nls_codepage, int remap)
876 DELETE_FILE_REQ *pSMB = NULL;
877 DELETE_FILE_RSP *pSMBr = NULL;
883 rc = smb_init(SMB_COM_DELETE, 1, tcon, (void **) &pSMB,
888 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
890 cifsConvertToUCS((__le16 *) pSMB->fileName, fileName,
891 PATH_MAX, nls_codepage, remap);
892 name_len++; /* trailing null */
894 } else { /* BB improve check for buffer overruns BB */
895 name_len = strnlen(fileName, PATH_MAX);
896 name_len++; /* trailing null */
897 strncpy(pSMB->fileName, fileName, name_len);
899 pSMB->SearchAttributes =
900 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM);
901 pSMB->BufferFormat = 0x04;
902 pSMB->hdr.smb_buf_length += name_len + 1;
903 pSMB->ByteCount = cpu_to_le16(name_len + 1);
904 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
905 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
906 cifs_stats_inc(&tcon->num_deletes);
908 cFYI(1, "Error in RMFile = %d", rc);
910 cifs_buf_release(pSMB);
918 CIFSSMBRmDir(const int xid, struct cifsTconInfo *tcon, const char *dirName,
919 const struct nls_table *nls_codepage, int remap)
921 DELETE_DIRECTORY_REQ *pSMB = NULL;
922 DELETE_DIRECTORY_RSP *pSMBr = NULL;
927 cFYI(1, "In CIFSSMBRmDir");
929 rc = smb_init(SMB_COM_DELETE_DIRECTORY, 0, tcon, (void **) &pSMB,
934 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
935 name_len = cifsConvertToUCS((__le16 *) pSMB->DirName, dirName,
936 PATH_MAX, nls_codepage, remap);
937 name_len++; /* trailing null */
939 } else { /* BB improve check for buffer overruns BB */
940 name_len = strnlen(dirName, PATH_MAX);
941 name_len++; /* trailing null */
942 strncpy(pSMB->DirName, dirName, name_len);
945 pSMB->BufferFormat = 0x04;
946 pSMB->hdr.smb_buf_length += name_len + 1;
947 pSMB->ByteCount = cpu_to_le16(name_len + 1);
948 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
949 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
950 cifs_stats_inc(&tcon->num_rmdirs);
952 cFYI(1, "Error in RMDir = %d", rc);
954 cifs_buf_release(pSMB);
961 CIFSSMBMkDir(const int xid, struct cifsTconInfo *tcon,
962 const char *name, const struct nls_table *nls_codepage, int remap)
965 CREATE_DIRECTORY_REQ *pSMB = NULL;
966 CREATE_DIRECTORY_RSP *pSMBr = NULL;
970 cFYI(1, "In CIFSSMBMkDir");
972 rc = smb_init(SMB_COM_CREATE_DIRECTORY, 0, tcon, (void **) &pSMB,
977 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
978 name_len = cifsConvertToUCS((__le16 *) pSMB->DirName, name,
979 PATH_MAX, nls_codepage, remap);
980 name_len++; /* trailing null */
982 } else { /* BB improve check for buffer overruns BB */
983 name_len = strnlen(name, PATH_MAX);
984 name_len++; /* trailing null */
985 strncpy(pSMB->DirName, name, name_len);
988 pSMB->BufferFormat = 0x04;
989 pSMB->hdr.smb_buf_length += name_len + 1;
990 pSMB->ByteCount = cpu_to_le16(name_len + 1);
991 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
992 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
993 cifs_stats_inc(&tcon->num_mkdirs);
995 cFYI(1, "Error in Mkdir = %d", rc);
997 cifs_buf_release(pSMB);
1004 CIFSPOSIXCreate(const int xid, struct cifsTconInfo *tcon, __u32 posix_flags,
1005 __u64 mode, __u16 *netfid, FILE_UNIX_BASIC_INFO *pRetData,
1006 __u32 *pOplock, const char *name,
1007 const struct nls_table *nls_codepage, int remap)
1009 TRANSACTION2_SPI_REQ *pSMB = NULL;
1010 TRANSACTION2_SPI_RSP *pSMBr = NULL;
1013 int bytes_returned = 0;
1014 __u16 params, param_offset, offset, byte_count, count;
1015 OPEN_PSX_REQ *pdata;
1016 OPEN_PSX_RSP *psx_rsp;
1018 cFYI(1, "In POSIX Create");
1020 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
1025 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1027 cifsConvertToUCS((__le16 *) pSMB->FileName, name,
1028 PATH_MAX, nls_codepage, remap);
1029 name_len++; /* trailing null */
1031 } else { /* BB improve the check for buffer overruns BB */
1032 name_len = strnlen(name, PATH_MAX);
1033 name_len++; /* trailing null */
1034 strncpy(pSMB->FileName, name, name_len);
1037 params = 6 + name_len;
1038 count = sizeof(OPEN_PSX_REQ);
1039 pSMB->MaxParameterCount = cpu_to_le16(2);
1040 pSMB->MaxDataCount = cpu_to_le16(1000); /* large enough */
1041 pSMB->MaxSetupCount = 0;
1045 pSMB->Reserved2 = 0;
1046 param_offset = offsetof(struct smb_com_transaction2_spi_req,
1047 InformationLevel) - 4;
1048 offset = param_offset + params;
1049 pdata = (OPEN_PSX_REQ *)(((char *)&pSMB->hdr.Protocol) + offset);
1050 pdata->Level = cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC);
1051 pdata->Permissions = cpu_to_le64(mode);
1052 pdata->PosixOpenFlags = cpu_to_le32(posix_flags);
1053 pdata->OpenFlags = cpu_to_le32(*pOplock);
1054 pSMB->ParameterOffset = cpu_to_le16(param_offset);
1055 pSMB->DataOffset = cpu_to_le16(offset);
1056 pSMB->SetupCount = 1;
1057 pSMB->Reserved3 = 0;
1058 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
1059 byte_count = 3 /* pad */ + params + count;
1061 pSMB->DataCount = cpu_to_le16(count);
1062 pSMB->ParameterCount = cpu_to_le16(params);
1063 pSMB->TotalDataCount = pSMB->DataCount;
1064 pSMB->TotalParameterCount = pSMB->ParameterCount;
1065 pSMB->InformationLevel = cpu_to_le16(SMB_POSIX_OPEN);
1066 pSMB->Reserved4 = 0;
1067 pSMB->hdr.smb_buf_length += byte_count;
1068 pSMB->ByteCount = cpu_to_le16(byte_count);
1069 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1070 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1072 cFYI(1, "Posix create returned %d", rc);
1073 goto psx_create_err;
1076 cFYI(1, "copying inode info");
1077 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
1079 if (rc || (pSMBr->ByteCount < sizeof(OPEN_PSX_RSP))) {
1080 rc = -EIO; /* bad smb */
1081 goto psx_create_err;
1084 /* copy return information to pRetData */
1085 psx_rsp = (OPEN_PSX_RSP *)((char *) &pSMBr->hdr.Protocol
1086 + le16_to_cpu(pSMBr->t2.DataOffset));
1088 *pOplock = le16_to_cpu(psx_rsp->OplockFlags);
1090 *netfid = psx_rsp->Fid; /* cifs fid stays in le */
1091 /* Let caller know file was created so we can set the mode. */
1092 /* Do we care about the CreateAction in any other cases? */
1093 if (cpu_to_le32(FILE_CREATE) == psx_rsp->CreateAction)
1094 *pOplock |= CIFS_CREATE_ACTION;
1095 /* check to make sure response data is there */
1096 if (psx_rsp->ReturnedLevel != cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC)) {
1097 pRetData->Type = cpu_to_le32(-1); /* unknown */
1098 cFYI(DBG2, "unknown type");
1100 if (pSMBr->ByteCount < sizeof(OPEN_PSX_RSP)
1101 + sizeof(FILE_UNIX_BASIC_INFO)) {
1102 cERROR(1, "Open response data too small");
1103 pRetData->Type = cpu_to_le32(-1);
1104 goto psx_create_err;
1106 memcpy((char *) pRetData,
1107 (char *)psx_rsp + sizeof(OPEN_PSX_RSP),
1108 sizeof(FILE_UNIX_BASIC_INFO));
1112 cifs_buf_release(pSMB);
1114 if (posix_flags & SMB_O_DIRECTORY)
1115 cifs_stats_inc(&tcon->num_posixmkdirs);
1117 cifs_stats_inc(&tcon->num_posixopens);
1125 static __u16 convert_disposition(int disposition)
1129 switch (disposition) {
1130 case FILE_SUPERSEDE:
1131 ofun = SMBOPEN_OCREATE | SMBOPEN_OTRUNC;
1134 ofun = SMBOPEN_OAPPEND;
1137 ofun = SMBOPEN_OCREATE;
1140 ofun = SMBOPEN_OCREATE | SMBOPEN_OAPPEND;
1142 case FILE_OVERWRITE:
1143 ofun = SMBOPEN_OTRUNC;
1145 case FILE_OVERWRITE_IF:
1146 ofun = SMBOPEN_OCREATE | SMBOPEN_OTRUNC;
1149 cFYI(1, "unknown disposition %d", disposition);
1150 ofun = SMBOPEN_OAPPEND; /* regular open */
1156 access_flags_to_smbopen_mode(const int access_flags)
1158 int masked_flags = access_flags & (GENERIC_READ | GENERIC_WRITE);
1160 if (masked_flags == GENERIC_READ)
1161 return SMBOPEN_READ;
1162 else if (masked_flags == GENERIC_WRITE)
1163 return SMBOPEN_WRITE;
1165 /* just go for read/write */
1166 return SMBOPEN_READWRITE;
1170 SMBLegacyOpen(const int xid, struct cifsTconInfo *tcon,
1171 const char *fileName, const int openDisposition,
1172 const int access_flags, const int create_options, __u16 *netfid,
1173 int *pOplock, FILE_ALL_INFO *pfile_info,
1174 const struct nls_table *nls_codepage, int remap)
1177 OPENX_REQ *pSMB = NULL;
1178 OPENX_RSP *pSMBr = NULL;
1184 rc = smb_init(SMB_COM_OPEN_ANDX, 15, tcon, (void **) &pSMB,
1189 pSMB->AndXCommand = 0xFF; /* none */
1191 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1192 count = 1; /* account for one byte pad to word boundary */
1194 cifsConvertToUCS((__le16 *) (pSMB->fileName + 1),
1195 fileName, PATH_MAX, nls_codepage, remap);
1196 name_len++; /* trailing null */
1198 } else { /* BB improve check for buffer overruns BB */
1199 count = 0; /* no pad */
1200 name_len = strnlen(fileName, PATH_MAX);
1201 name_len++; /* trailing null */
1202 strncpy(pSMB->fileName, fileName, name_len);
1204 if (*pOplock & REQ_OPLOCK)
1205 pSMB->OpenFlags = cpu_to_le16(REQ_OPLOCK);
1206 else if (*pOplock & REQ_BATCHOPLOCK)
1207 pSMB->OpenFlags = cpu_to_le16(REQ_BATCHOPLOCK);
1209 pSMB->OpenFlags |= cpu_to_le16(REQ_MORE_INFO);
1210 pSMB->Mode = cpu_to_le16(access_flags_to_smbopen_mode(access_flags));
1211 pSMB->Mode |= cpu_to_le16(0x40); /* deny none */
1212 /* set file as system file if special file such
1213 as fifo and server expecting SFU style and
1214 no Unix extensions */
1216 if (create_options & CREATE_OPTION_SPECIAL)
1217 pSMB->FileAttributes = cpu_to_le16(ATTR_SYSTEM);
1218 else /* BB FIXME BB */
1219 pSMB->FileAttributes = cpu_to_le16(0/*ATTR_NORMAL*/);
1221 if (create_options & CREATE_OPTION_READONLY)
1222 pSMB->FileAttributes |= cpu_to_le16(ATTR_READONLY);
1225 /* pSMB->CreateOptions = cpu_to_le32(create_options &
1226 CREATE_OPTIONS_MASK); */
1227 /* BB FIXME END BB */
1229 pSMB->Sattr = cpu_to_le16(ATTR_HIDDEN | ATTR_SYSTEM | ATTR_DIRECTORY);
1230 pSMB->OpenFunction = cpu_to_le16(convert_disposition(openDisposition));
1232 pSMB->hdr.smb_buf_length += count;
1234 pSMB->ByteCount = cpu_to_le16(count);
1235 /* long_op set to 1 to allow for oplock break timeouts */
1236 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1237 (struct smb_hdr *)pSMBr, &bytes_returned, 0);
1238 cifs_stats_inc(&tcon->num_opens);
1240 cFYI(1, "Error in Open = %d", rc);
1242 /* BB verify if wct == 15 */
1244 /* *pOplock = pSMBr->OplockLevel; */ /* BB take from action field*/
1246 *netfid = pSMBr->Fid; /* cifs fid stays in le */
1247 /* Let caller know file was created so we can set the mode. */
1248 /* Do we care about the CreateAction in any other cases? */
1250 /* if (cpu_to_le32(FILE_CREATE) == pSMBr->CreateAction)
1251 *pOplock |= CIFS_CREATE_ACTION; */
1255 pfile_info->CreationTime = 0; /* BB convert CreateTime*/
1256 pfile_info->LastAccessTime = 0; /* BB fixme */
1257 pfile_info->LastWriteTime = 0; /* BB fixme */
1258 pfile_info->ChangeTime = 0; /* BB fixme */
1259 pfile_info->Attributes =
1260 cpu_to_le32(le16_to_cpu(pSMBr->FileAttributes));
1261 /* the file_info buf is endian converted by caller */
1262 pfile_info->AllocationSize =
1263 cpu_to_le64(le32_to_cpu(pSMBr->EndOfFile));
1264 pfile_info->EndOfFile = pfile_info->AllocationSize;
1265 pfile_info->NumberOfLinks = cpu_to_le32(1);
1266 pfile_info->DeletePending = 0;
1270 cifs_buf_release(pSMB);
1277 CIFSSMBOpen(const int xid, struct cifsTconInfo *tcon,
1278 const char *fileName, const int openDisposition,
1279 const int access_flags, const int create_options, __u16 *netfid,
1280 int *pOplock, FILE_ALL_INFO *pfile_info,
1281 const struct nls_table *nls_codepage, int remap)
1284 OPEN_REQ *pSMB = NULL;
1285 OPEN_RSP *pSMBr = NULL;
1291 rc = smb_init(SMB_COM_NT_CREATE_ANDX, 24, tcon, (void **) &pSMB,
1296 pSMB->AndXCommand = 0xFF; /* none */
1298 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1299 count = 1; /* account for one byte pad to word boundary */
1301 cifsConvertToUCS((__le16 *) (pSMB->fileName + 1),
1302 fileName, PATH_MAX, nls_codepage, remap);
1303 name_len++; /* trailing null */
1305 pSMB->NameLength = cpu_to_le16(name_len);
1306 } else { /* BB improve check for buffer overruns BB */
1307 count = 0; /* no pad */
1308 name_len = strnlen(fileName, PATH_MAX);
1309 name_len++; /* trailing null */
1310 pSMB->NameLength = cpu_to_le16(name_len);
1311 strncpy(pSMB->fileName, fileName, name_len);
1313 if (*pOplock & REQ_OPLOCK)
1314 pSMB->OpenFlags = cpu_to_le32(REQ_OPLOCK);
1315 else if (*pOplock & REQ_BATCHOPLOCK)
1316 pSMB->OpenFlags = cpu_to_le32(REQ_BATCHOPLOCK);
1317 pSMB->DesiredAccess = cpu_to_le32(access_flags);
1318 pSMB->AllocationSize = 0;
1319 /* set file as system file if special file such
1320 as fifo and server expecting SFU style and
1321 no Unix extensions */
1322 if (create_options & CREATE_OPTION_SPECIAL)
1323 pSMB->FileAttributes = cpu_to_le32(ATTR_SYSTEM);
1325 pSMB->FileAttributes = cpu_to_le32(ATTR_NORMAL);
1327 /* XP does not handle ATTR_POSIX_SEMANTICS */
1328 /* but it helps speed up case sensitive checks for other
1329 servers such as Samba */
1330 if (tcon->ses->capabilities & CAP_UNIX)
1331 pSMB->FileAttributes |= cpu_to_le32(ATTR_POSIX_SEMANTICS);
1333 if (create_options & CREATE_OPTION_READONLY)
1334 pSMB->FileAttributes |= cpu_to_le32(ATTR_READONLY);
1336 pSMB->ShareAccess = cpu_to_le32(FILE_SHARE_ALL);
1337 pSMB->CreateDisposition = cpu_to_le32(openDisposition);
1338 pSMB->CreateOptions = cpu_to_le32(create_options & CREATE_OPTIONS_MASK);
1339 /* BB Expirement with various impersonation levels and verify */
1340 pSMB->ImpersonationLevel = cpu_to_le32(SECURITY_IMPERSONATION);
1341 pSMB->SecurityFlags =
1342 SECURITY_CONTEXT_TRACKING | SECURITY_EFFECTIVE_ONLY;
1345 pSMB->hdr.smb_buf_length += count;
1347 pSMB->ByteCount = cpu_to_le16(count);
1348 /* long_op set to 1 to allow for oplock break timeouts */
1349 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1350 (struct smb_hdr *)pSMBr, &bytes_returned, 0);
1351 cifs_stats_inc(&tcon->num_opens);
1353 cFYI(1, "Error in Open = %d", rc);
1355 *pOplock = pSMBr->OplockLevel; /* 1 byte no need to le_to_cpu */
1356 *netfid = pSMBr->Fid; /* cifs fid stays in le */
1357 /* Let caller know file was created so we can set the mode. */
1358 /* Do we care about the CreateAction in any other cases? */
1359 if (cpu_to_le32(FILE_CREATE) == pSMBr->CreateAction)
1360 *pOplock |= CIFS_CREATE_ACTION;
1362 memcpy((char *)pfile_info, (char *)&pSMBr->CreationTime,
1363 36 /* CreationTime to Attributes */);
1364 /* the file_info buf is endian converted by caller */
1365 pfile_info->AllocationSize = pSMBr->AllocationSize;
1366 pfile_info->EndOfFile = pSMBr->EndOfFile;
1367 pfile_info->NumberOfLinks = cpu_to_le32(1);
1368 pfile_info->DeletePending = 0;
1372 cifs_buf_release(pSMB);
1379 CIFSSMBRead(const int xid, struct cifsTconInfo *tcon, const int netfid,
1380 const unsigned int count, const __u64 lseek, unsigned int *nbytes,
1381 char **buf, int *pbuf_type)
1384 READ_REQ *pSMB = NULL;
1385 READ_RSP *pSMBr = NULL;
1386 char *pReadData = NULL;
1388 int resp_buf_type = 0;
1391 cFYI(1, "Reading %d bytes on fid %d", count, netfid);
1392 if (tcon->ses->capabilities & CAP_LARGE_FILES)
1395 wct = 10; /* old style read */
1396 if ((lseek >> 32) > 0) {
1397 /* can not handle this big offset for old */
1403 rc = small_smb_init(SMB_COM_READ_ANDX, wct, tcon, (void **) &pSMB);
1407 /* tcon and ses pointer are checked in smb_init */
1408 if (tcon->ses->server == NULL)
1409 return -ECONNABORTED;
1411 pSMB->AndXCommand = 0xFF; /* none */
1413 pSMB->OffsetLow = cpu_to_le32(lseek & 0xFFFFFFFF);
1415 pSMB->OffsetHigh = cpu_to_le32(lseek >> 32);
1417 pSMB->Remaining = 0;
1418 pSMB->MaxCount = cpu_to_le16(count & 0xFFFF);
1419 pSMB->MaxCountHigh = cpu_to_le32(count >> 16);
1421 pSMB->ByteCount = 0; /* no need to do le conversion since 0 */
1423 /* old style read */
1424 struct smb_com_readx_req *pSMBW =
1425 (struct smb_com_readx_req *)pSMB;
1426 pSMBW->ByteCount = 0;
1429 iov[0].iov_base = (char *)pSMB;
1430 iov[0].iov_len = pSMB->hdr.smb_buf_length + 4;
1431 rc = SendReceive2(xid, tcon->ses, iov, 1 /* num iovecs */,
1432 &resp_buf_type, CIFS_LOG_ERROR);
1433 cifs_stats_inc(&tcon->num_reads);
1434 pSMBr = (READ_RSP *)iov[0].iov_base;
1436 cERROR(1, "Send error in read = %d", rc);
1438 int data_length = le16_to_cpu(pSMBr->DataLengthHigh);
1439 data_length = data_length << 16;
1440 data_length += le16_to_cpu(pSMBr->DataLength);
1441 *nbytes = data_length;
1443 /*check that DataLength would not go beyond end of SMB */
1444 if ((data_length > CIFSMaxBufSize)
1445 || (data_length > count)) {
1446 cFYI(1, "bad length %d for count %d",
1447 data_length, count);
1451 pReadData = (char *) (&pSMBr->hdr.Protocol) +
1452 le16_to_cpu(pSMBr->DataOffset);
1453 /* if (rc = copy_to_user(buf, pReadData, data_length)) {
1454 cERROR(1, "Faulting on read rc = %d",rc);
1456 }*/ /* can not use copy_to_user when using page cache*/
1458 memcpy(*buf, pReadData, data_length);
1462 /* cifs_small_buf_release(pSMB); */ /* Freed earlier now in SendReceive2 */
1464 if (resp_buf_type == CIFS_SMALL_BUFFER)
1465 cifs_small_buf_release(iov[0].iov_base);
1466 else if (resp_buf_type == CIFS_LARGE_BUFFER)
1467 cifs_buf_release(iov[0].iov_base);
1468 } else if (resp_buf_type != CIFS_NO_BUFFER) {
1469 /* return buffer to caller to free */
1470 *buf = iov[0].iov_base;
1471 if (resp_buf_type == CIFS_SMALL_BUFFER)
1472 *pbuf_type = CIFS_SMALL_BUFFER;
1473 else if (resp_buf_type == CIFS_LARGE_BUFFER)
1474 *pbuf_type = CIFS_LARGE_BUFFER;
1475 } /* else no valid buffer on return - leave as null */
1477 /* Note: On -EAGAIN error only caller can retry on handle based calls
1478 since file handle passed in no longer valid */
1484 CIFSSMBWrite(const int xid, struct cifsTconInfo *tcon,
1485 const int netfid, const unsigned int count,
1486 const __u64 offset, unsigned int *nbytes, const char *buf,
1487 const char __user *ubuf, const int long_op)
1490 WRITE_REQ *pSMB = NULL;
1491 WRITE_RSP *pSMBr = NULL;
1492 int bytes_returned, wct;
1498 /* cFYI(1, "write at %lld %d bytes", offset, count);*/
1499 if (tcon->ses == NULL)
1500 return -ECONNABORTED;
1502 if (tcon->ses->capabilities & CAP_LARGE_FILES)
1506 if ((offset >> 32) > 0) {
1507 /* can not handle big offset for old srv */
1512 rc = smb_init(SMB_COM_WRITE_ANDX, wct, tcon, (void **) &pSMB,
1516 /* tcon and ses pointer are checked in smb_init */
1517 if (tcon->ses->server == NULL)
1518 return -ECONNABORTED;
1520 pSMB->AndXCommand = 0xFF; /* none */
1522 pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF);
1524 pSMB->OffsetHigh = cpu_to_le32(offset >> 32);
1526 pSMB->Reserved = 0xFFFFFFFF;
1527 pSMB->WriteMode = 0;
1528 pSMB->Remaining = 0;
1530 /* Can increase buffer size if buffer is big enough in some cases ie we
1531 can send more if LARGE_WRITE_X capability returned by the server and if
1532 our buffer is big enough or if we convert to iovecs on socket writes
1533 and eliminate the copy to the CIFS buffer */
1534 if (tcon->ses->capabilities & CAP_LARGE_WRITE_X) {
1535 bytes_sent = min_t(const unsigned int, CIFSMaxBufSize, count);
1537 bytes_sent = (tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE)
1541 if (bytes_sent > count)
1544 cpu_to_le16(offsetof(struct smb_com_write_req, Data) - 4);
1546 memcpy(pSMB->Data, buf, bytes_sent);
1548 if (copy_from_user(pSMB->Data, ubuf, bytes_sent)) {
1549 cifs_buf_release(pSMB);
1552 } else if (count != 0) {
1554 cifs_buf_release(pSMB);
1556 } /* else setting file size with write of zero bytes */
1558 byte_count = bytes_sent + 1; /* pad */
1559 else /* wct == 12 */
1560 byte_count = bytes_sent + 5; /* bigger pad, smaller smb hdr */
1562 pSMB->DataLengthLow = cpu_to_le16(bytes_sent & 0xFFFF);
1563 pSMB->DataLengthHigh = cpu_to_le16(bytes_sent >> 16);
1564 pSMB->hdr.smb_buf_length += byte_count;
1567 pSMB->ByteCount = cpu_to_le16(byte_count);
1568 else { /* old style write has byte count 4 bytes earlier
1570 struct smb_com_writex_req *pSMBW =
1571 (struct smb_com_writex_req *)pSMB;
1572 pSMBW->ByteCount = cpu_to_le16(byte_count);
1575 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1576 (struct smb_hdr *) pSMBr, &bytes_returned, long_op);
1577 cifs_stats_inc(&tcon->num_writes);
1579 cFYI(1, "Send error in write = %d", rc);
1581 *nbytes = le16_to_cpu(pSMBr->CountHigh);
1582 *nbytes = (*nbytes) << 16;
1583 *nbytes += le16_to_cpu(pSMBr->Count);
1586 * Mask off high 16 bits when bytes written as returned by the
1587 * server is greater than bytes requested by the client. Some
1588 * OS/2 servers are known to set incorrect CountHigh values.
1590 if (*nbytes > count)
1594 cifs_buf_release(pSMB);
1596 /* Note: On -EAGAIN error only caller can retry on handle based calls
1597 since file handle passed in no longer valid */
1603 CIFSSMBWrite2(const int xid, struct cifsTconInfo *tcon,
1604 const int netfid, const unsigned int count,
1605 const __u64 offset, unsigned int *nbytes, struct kvec *iov,
1606 int n_vec, const int long_op)
1609 WRITE_REQ *pSMB = NULL;
1612 int resp_buf_type = 0;
1616 cFYI(1, "write2 at %lld %d bytes", (long long)offset, count);
1618 if (tcon->ses->capabilities & CAP_LARGE_FILES) {
1622 if ((offset >> 32) > 0) {
1623 /* can not handle big offset for old srv */
1627 rc = small_smb_init(SMB_COM_WRITE_ANDX, wct, tcon, (void **) &pSMB);
1630 /* tcon and ses pointer are checked in smb_init */
1631 if (tcon->ses->server == NULL)
1632 return -ECONNABORTED;
1634 pSMB->AndXCommand = 0xFF; /* none */
1636 pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF);
1638 pSMB->OffsetHigh = cpu_to_le32(offset >> 32);
1639 pSMB->Reserved = 0xFFFFFFFF;
1640 pSMB->WriteMode = 0;
1641 pSMB->Remaining = 0;
1644 cpu_to_le16(offsetof(struct smb_com_write_req, Data) - 4);
1646 pSMB->DataLengthLow = cpu_to_le16(count & 0xFFFF);
1647 pSMB->DataLengthHigh = cpu_to_le16(count >> 16);
1648 smb_hdr_len = pSMB->hdr.smb_buf_length + 1; /* hdr + 1 byte pad */
1650 pSMB->hdr.smb_buf_length += count+1;
1651 else /* wct == 12 */
1652 pSMB->hdr.smb_buf_length += count+5; /* smb data starts later */
1654 pSMB->ByteCount = cpu_to_le16(count + 1);
1655 else /* wct == 12 */ /* bigger pad, smaller smb hdr, keep offset ok */ {
1656 struct smb_com_writex_req *pSMBW =
1657 (struct smb_com_writex_req *)pSMB;
1658 pSMBW->ByteCount = cpu_to_le16(count + 5);
1660 iov[0].iov_base = pSMB;
1662 iov[0].iov_len = smb_hdr_len + 4;
1663 else /* wct == 12 pad bigger by four bytes */
1664 iov[0].iov_len = smb_hdr_len + 8;
1667 rc = SendReceive2(xid, tcon->ses, iov, n_vec + 1, &resp_buf_type,
1669 cifs_stats_inc(&tcon->num_writes);
1671 cFYI(1, "Send error Write2 = %d", rc);
1672 } else if (resp_buf_type == 0) {
1673 /* presumably this can not happen, but best to be safe */
1676 WRITE_RSP *pSMBr = (WRITE_RSP *)iov[0].iov_base;
1677 *nbytes = le16_to_cpu(pSMBr->CountHigh);
1678 *nbytes = (*nbytes) << 16;
1679 *nbytes += le16_to_cpu(pSMBr->Count);
1682 * Mask off high 16 bits when bytes written as returned by the
1683 * server is greater than bytes requested by the client. OS/2
1684 * servers are known to set incorrect CountHigh values.
1686 if (*nbytes > count)
1690 /* cifs_small_buf_release(pSMB); */ /* Freed earlier now in SendReceive2 */
1691 if (resp_buf_type == CIFS_SMALL_BUFFER)
1692 cifs_small_buf_release(iov[0].iov_base);
1693 else if (resp_buf_type == CIFS_LARGE_BUFFER)
1694 cifs_buf_release(iov[0].iov_base);
1696 /* Note: On -EAGAIN error only caller can retry on handle based calls
1697 since file handle passed in no longer valid */
1704 CIFSSMBLock(const int xid, struct cifsTconInfo *tcon,
1705 const __u16 smb_file_id, const __u64 len,
1706 const __u64 offset, const __u32 numUnlock,
1707 const __u32 numLock, const __u8 lockType,
1708 const bool waitFlag, const __u8 oplock_level)
1711 LOCK_REQ *pSMB = NULL;
1712 /* LOCK_RSP *pSMBr = NULL; */ /* No response data other than rc to parse */
1717 cFYI(1, "CIFSSMBLock timeout %d numLock %d", (int)waitFlag, numLock);
1718 rc = small_smb_init(SMB_COM_LOCKING_ANDX, 8, tcon, (void **) &pSMB);
1723 if (lockType == LOCKING_ANDX_OPLOCK_RELEASE) {
1724 timeout = CIFS_ASYNC_OP; /* no response expected */
1726 } else if (waitFlag) {
1727 timeout = CIFS_BLOCKING_OP; /* blocking operation, no timeout */
1728 pSMB->Timeout = cpu_to_le32(-1);/* blocking - do not time out */
1733 pSMB->NumberOfLocks = cpu_to_le16(numLock);
1734 pSMB->NumberOfUnlocks = cpu_to_le16(numUnlock);
1735 pSMB->LockType = lockType;
1736 pSMB->OplockLevel = oplock_level;
1737 pSMB->AndXCommand = 0xFF; /* none */
1738 pSMB->Fid = smb_file_id; /* netfid stays le */
1740 if ((numLock != 0) || (numUnlock != 0)) {
1741 pSMB->Locks[0].Pid = cpu_to_le16(current->tgid);
1742 /* BB where to store pid high? */
1743 pSMB->Locks[0].LengthLow = cpu_to_le32((u32)len);
1744 pSMB->Locks[0].LengthHigh = cpu_to_le32((u32)(len>>32));
1745 pSMB->Locks[0].OffsetLow = cpu_to_le32((u32)offset);
1746 pSMB->Locks[0].OffsetHigh = cpu_to_le32((u32)(offset>>32));
1747 count = sizeof(LOCKING_ANDX_RANGE);
1752 pSMB->hdr.smb_buf_length += count;
1753 pSMB->ByteCount = cpu_to_le16(count);
1756 rc = SendReceiveBlockingLock(xid, tcon, (struct smb_hdr *) pSMB,
1757 (struct smb_hdr *) pSMB, &bytes_returned);
1758 cifs_small_buf_release(pSMB);
1760 rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *)pSMB,
1762 /* SMB buffer freed by function above */
1764 cifs_stats_inc(&tcon->num_locks);
1766 cFYI(1, "Send error in Lock = %d", rc);
1768 /* Note: On -EAGAIN error only caller can retry on handle based calls
1769 since file handle passed in no longer valid */
1774 CIFSSMBPosixLock(const int xid, struct cifsTconInfo *tcon,
1775 const __u16 smb_file_id, const int get_flag, const __u64 len,
1776 struct file_lock *pLockData, const __u16 lock_type,
1777 const bool waitFlag)
1779 struct smb_com_transaction2_sfi_req *pSMB = NULL;
1780 struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
1781 struct cifs_posix_lock *parm_data;
1784 int bytes_returned = 0;
1785 int resp_buf_type = 0;
1786 __u16 params, param_offset, offset, byte_count, count;
1789 cFYI(1, "Posix Lock");
1791 if (pLockData == NULL)
1794 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
1799 pSMBr = (struct smb_com_transaction2_sfi_rsp *)pSMB;
1802 pSMB->MaxSetupCount = 0;
1805 pSMB->Reserved2 = 0;
1806 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
1807 offset = param_offset + params;
1809 count = sizeof(struct cifs_posix_lock);
1810 pSMB->MaxParameterCount = cpu_to_le16(2);
1811 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB from sess */
1812 pSMB->SetupCount = 1;
1813 pSMB->Reserved3 = 0;
1815 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION);
1817 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
1818 byte_count = 3 /* pad */ + params + count;
1819 pSMB->DataCount = cpu_to_le16(count);
1820 pSMB->ParameterCount = cpu_to_le16(params);
1821 pSMB->TotalDataCount = pSMB->DataCount;
1822 pSMB->TotalParameterCount = pSMB->ParameterCount;
1823 pSMB->ParameterOffset = cpu_to_le16(param_offset);
1824 parm_data = (struct cifs_posix_lock *)
1825 (((char *) &pSMB->hdr.Protocol) + offset);
1827 parm_data->lock_type = cpu_to_le16(lock_type);
1829 timeout = CIFS_BLOCKING_OP; /* blocking operation, no timeout */
1830 parm_data->lock_flags = cpu_to_le16(1);
1831 pSMB->Timeout = cpu_to_le32(-1);
1835 parm_data->pid = cpu_to_le32(current->tgid);
1836 parm_data->start = cpu_to_le64(pLockData->fl_start);
1837 parm_data->length = cpu_to_le64(len); /* normalize negative numbers */
1839 pSMB->DataOffset = cpu_to_le16(offset);
1840 pSMB->Fid = smb_file_id;
1841 pSMB->InformationLevel = cpu_to_le16(SMB_SET_POSIX_LOCK);
1842 pSMB->Reserved4 = 0;
1843 pSMB->hdr.smb_buf_length += byte_count;
1844 pSMB->ByteCount = cpu_to_le16(byte_count);
1846 rc = SendReceiveBlockingLock(xid, tcon, (struct smb_hdr *) pSMB,
1847 (struct smb_hdr *) pSMBr, &bytes_returned);
1849 iov[0].iov_base = (char *)pSMB;
1850 iov[0].iov_len = pSMB->hdr.smb_buf_length + 4;
1851 rc = SendReceive2(xid, tcon->ses, iov, 1 /* num iovecs */,
1852 &resp_buf_type, timeout);
1853 pSMB = NULL; /* request buf already freed by SendReceive2. Do
1854 not try to free it twice below on exit */
1855 pSMBr = (struct smb_com_transaction2_sfi_rsp *)iov[0].iov_base;
1859 cFYI(1, "Send error in Posix Lock = %d", rc);
1860 } else if (get_flag) {
1861 /* lock structure can be returned on get */
1864 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
1866 if (rc || (pSMBr->ByteCount < sizeof(struct cifs_posix_lock))) {
1867 rc = -EIO; /* bad smb */
1870 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
1871 data_count = le16_to_cpu(pSMBr->t2.DataCount);
1872 if (data_count < sizeof(struct cifs_posix_lock)) {
1876 parm_data = (struct cifs_posix_lock *)
1877 ((char *)&pSMBr->hdr.Protocol + data_offset);
1878 if (parm_data->lock_type == __constant_cpu_to_le16(CIFS_UNLCK))
1879 pLockData->fl_type = F_UNLCK;
1881 if (parm_data->lock_type ==
1882 __constant_cpu_to_le16(CIFS_RDLCK))
1883 pLockData->fl_type = F_RDLCK;
1884 else if (parm_data->lock_type ==
1885 __constant_cpu_to_le16(CIFS_WRLCK))
1886 pLockData->fl_type = F_WRLCK;
1888 pLockData->fl_start = parm_data->start;
1889 pLockData->fl_end = parm_data->start +
1890 parm_data->length - 1;
1891 pLockData->fl_pid = parm_data->pid;
1897 cifs_small_buf_release(pSMB);
1899 if (resp_buf_type == CIFS_SMALL_BUFFER)
1900 cifs_small_buf_release(iov[0].iov_base);
1901 else if (resp_buf_type == CIFS_LARGE_BUFFER)
1902 cifs_buf_release(iov[0].iov_base);
1904 /* Note: On -EAGAIN error only caller can retry on handle based calls
1905 since file handle passed in no longer valid */
1912 CIFSSMBClose(const int xid, struct cifsTconInfo *tcon, int smb_file_id)
1915 CLOSE_REQ *pSMB = NULL;
1916 cFYI(1, "In CIFSSMBClose");
1918 /* do not retry on dead session on close */
1919 rc = small_smb_init(SMB_COM_CLOSE, 3, tcon, (void **) &pSMB);
1925 pSMB->FileID = (__u16) smb_file_id;
1926 pSMB->LastWriteTime = 0xFFFFFFFF;
1927 pSMB->ByteCount = 0;
1928 rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0);
1929 cifs_stats_inc(&tcon->num_closes);
1932 /* EINTR is expected when user ctl-c to kill app */
1933 cERROR(1, "Send error in Close = %d", rc);
1937 /* Since session is dead, file will be closed on server already */
1945 CIFSSMBFlush(const int xid, struct cifsTconInfo *tcon, int smb_file_id)
1948 FLUSH_REQ *pSMB = NULL;
1949 cFYI(1, "In CIFSSMBFlush");
1951 rc = small_smb_init(SMB_COM_FLUSH, 1, tcon, (void **) &pSMB);
1955 pSMB->FileID = (__u16) smb_file_id;
1956 pSMB->ByteCount = 0;
1957 rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0);
1958 cifs_stats_inc(&tcon->num_flushes);
1960 cERROR(1, "Send error in Flush = %d", rc);
1966 CIFSSMBRename(const int xid, struct cifsTconInfo *tcon,
1967 const char *fromName, const char *toName,
1968 const struct nls_table *nls_codepage, int remap)
1971 RENAME_REQ *pSMB = NULL;
1972 RENAME_RSP *pSMBr = NULL;
1974 int name_len, name_len2;
1977 cFYI(1, "In CIFSSMBRename");
1979 rc = smb_init(SMB_COM_RENAME, 1, tcon, (void **) &pSMB,
1984 pSMB->BufferFormat = 0x04;
1985 pSMB->SearchAttributes =
1986 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
1989 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1991 cifsConvertToUCS((__le16 *) pSMB->OldFileName, fromName,
1992 PATH_MAX, nls_codepage, remap);
1993 name_len++; /* trailing null */
1995 pSMB->OldFileName[name_len] = 0x04; /* pad */
1996 /* protocol requires ASCII signature byte on Unicode string */
1997 pSMB->OldFileName[name_len + 1] = 0x00;
1999 cifsConvertToUCS((__le16 *)&pSMB->OldFileName[name_len + 2],
2000 toName, PATH_MAX, nls_codepage, remap);
2001 name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
2002 name_len2 *= 2; /* convert to bytes */
2003 } else { /* BB improve the check for buffer overruns BB */
2004 name_len = strnlen(fromName, PATH_MAX);
2005 name_len++; /* trailing null */
2006 strncpy(pSMB->OldFileName, fromName, name_len);
2007 name_len2 = strnlen(toName, PATH_MAX);
2008 name_len2++; /* trailing null */
2009 pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */
2010 strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2);
2011 name_len2++; /* trailing null */
2012 name_len2++; /* signature byte */
2015 count = 1 /* 1st signature byte */ + name_len + name_len2;
2016 pSMB->hdr.smb_buf_length += count;
2017 pSMB->ByteCount = cpu_to_le16(count);
2019 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2020 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2021 cifs_stats_inc(&tcon->num_renames);
2023 cFYI(1, "Send error in rename = %d", rc);
2025 cifs_buf_release(pSMB);
2033 int CIFSSMBRenameOpenFile(const int xid, struct cifsTconInfo *pTcon,
2034 int netfid, const char *target_name,
2035 const struct nls_table *nls_codepage, int remap)
2037 struct smb_com_transaction2_sfi_req *pSMB = NULL;
2038 struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
2039 struct set_file_rename *rename_info;
2041 char dummy_string[30];
2043 int bytes_returned = 0;
2045 __u16 params, param_offset, offset, count, byte_count;
2047 cFYI(1, "Rename to File by handle");
2048 rc = smb_init(SMB_COM_TRANSACTION2, 15, pTcon, (void **) &pSMB,
2054 pSMB->MaxSetupCount = 0;
2058 pSMB->Reserved2 = 0;
2059 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
2060 offset = param_offset + params;
2062 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
2063 rename_info = (struct set_file_rename *) data_offset;
2064 pSMB->MaxParameterCount = cpu_to_le16(2);
2065 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB from sess */
2066 pSMB->SetupCount = 1;
2067 pSMB->Reserved3 = 0;
2068 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
2069 byte_count = 3 /* pad */ + params;
2070 pSMB->ParameterCount = cpu_to_le16(params);
2071 pSMB->TotalParameterCount = pSMB->ParameterCount;
2072 pSMB->ParameterOffset = cpu_to_le16(param_offset);
2073 pSMB->DataOffset = cpu_to_le16(offset);
2074 /* construct random name ".cifs_tmp<inodenum><mid>" */
2075 rename_info->overwrite = cpu_to_le32(1);
2076 rename_info->root_fid = 0;
2077 /* unicode only call */
2078 if (target_name == NULL) {
2079 sprintf(dummy_string, "cifs%x", pSMB->hdr.Mid);
2080 len_of_str = cifsConvertToUCS((__le16 *)rename_info->target_name,
2081 dummy_string, 24, nls_codepage, remap);
2083 len_of_str = cifsConvertToUCS((__le16 *)rename_info->target_name,
2084 target_name, PATH_MAX, nls_codepage,
2087 rename_info->target_name_len = cpu_to_le32(2 * len_of_str);
2088 count = 12 /* sizeof(struct set_file_rename) */ + (2 * len_of_str);
2089 byte_count += count;
2090 pSMB->DataCount = cpu_to_le16(count);
2091 pSMB->TotalDataCount = pSMB->DataCount;
2093 pSMB->InformationLevel =
2094 cpu_to_le16(SMB_SET_FILE_RENAME_INFORMATION);
2095 pSMB->Reserved4 = 0;
2096 pSMB->hdr.smb_buf_length += byte_count;
2097 pSMB->ByteCount = cpu_to_le16(byte_count);
2098 rc = SendReceive(xid, pTcon->ses, (struct smb_hdr *) pSMB,
2099 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2100 cifs_stats_inc(&pTcon->num_t2renames);
2102 cFYI(1, "Send error in Rename (by file handle) = %d", rc);
2104 cifs_buf_release(pSMB);
2106 /* Note: On -EAGAIN error only caller can retry on handle based calls
2107 since file handle passed in no longer valid */
2113 CIFSSMBCopy(const int xid, struct cifsTconInfo *tcon, const char *fromName,
2114 const __u16 target_tid, const char *toName, const int flags,
2115 const struct nls_table *nls_codepage, int remap)
2118 COPY_REQ *pSMB = NULL;
2119 COPY_RSP *pSMBr = NULL;
2121 int name_len, name_len2;
2124 cFYI(1, "In CIFSSMBCopy");
2126 rc = smb_init(SMB_COM_COPY, 1, tcon, (void **) &pSMB,
2131 pSMB->BufferFormat = 0x04;
2132 pSMB->Tid2 = target_tid;
2134 pSMB->Flags = cpu_to_le16(flags & COPY_TREE);
2136 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2137 name_len = cifsConvertToUCS((__le16 *) pSMB->OldFileName,
2138 fromName, PATH_MAX, nls_codepage,
2140 name_len++; /* trailing null */
2142 pSMB->OldFileName[name_len] = 0x04; /* pad */
2143 /* protocol requires ASCII signature byte on Unicode string */
2144 pSMB->OldFileName[name_len + 1] = 0x00;
2146 cifsConvertToUCS((__le16 *)&pSMB->OldFileName[name_len + 2],
2147 toName, PATH_MAX, nls_codepage, remap);
2148 name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
2149 name_len2 *= 2; /* convert to bytes */
2150 } else { /* BB improve the check for buffer overruns BB */
2151 name_len = strnlen(fromName, PATH_MAX);
2152 name_len++; /* trailing null */
2153 strncpy(pSMB->OldFileName, fromName, name_len);
2154 name_len2 = strnlen(toName, PATH_MAX);
2155 name_len2++; /* trailing null */
2156 pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */
2157 strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2);
2158 name_len2++; /* trailing null */
2159 name_len2++; /* signature byte */
2162 count = 1 /* 1st signature byte */ + name_len + name_len2;
2163 pSMB->hdr.smb_buf_length += count;
2164 pSMB->ByteCount = cpu_to_le16(count);
2166 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2167 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2169 cFYI(1, "Send error in copy = %d with %d files copied",
2170 rc, le16_to_cpu(pSMBr->CopyCount));
2172 cifs_buf_release(pSMB);
2181 CIFSUnixCreateSymLink(const int xid, struct cifsTconInfo *tcon,
2182 const char *fromName, const char *toName,
2183 const struct nls_table *nls_codepage)
2185 TRANSACTION2_SPI_REQ *pSMB = NULL;
2186 TRANSACTION2_SPI_RSP *pSMBr = NULL;
2189 int name_len_target;
2191 int bytes_returned = 0;
2192 __u16 params, param_offset, offset, byte_count;
2194 cFYI(1, "In Symlink Unix style");
2196 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2201 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2203 cifs_strtoUCS((__le16 *) pSMB->FileName, fromName, PATH_MAX
2204 /* find define for this maxpathcomponent */
2206 name_len++; /* trailing null */
2209 } else { /* BB improve the check for buffer overruns BB */
2210 name_len = strnlen(fromName, PATH_MAX);
2211 name_len++; /* trailing null */
2212 strncpy(pSMB->FileName, fromName, name_len);
2214 params = 6 + name_len;
2215 pSMB->MaxSetupCount = 0;
2219 pSMB->Reserved2 = 0;
2220 param_offset = offsetof(struct smb_com_transaction2_spi_req,
2221 InformationLevel) - 4;
2222 offset = param_offset + params;
2224 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
2225 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2227 cifs_strtoUCS((__le16 *) data_offset, toName, PATH_MAX
2228 /* find define for this maxpathcomponent */
2230 name_len_target++; /* trailing null */
2231 name_len_target *= 2;
2232 } else { /* BB improve the check for buffer overruns BB */
2233 name_len_target = strnlen(toName, PATH_MAX);
2234 name_len_target++; /* trailing null */
2235 strncpy(data_offset, toName, name_len_target);
2238 pSMB->MaxParameterCount = cpu_to_le16(2);
2239 /* BB find exact max on data count below from sess */
2240 pSMB->MaxDataCount = cpu_to_le16(1000);
2241 pSMB->SetupCount = 1;
2242 pSMB->Reserved3 = 0;
2243 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
2244 byte_count = 3 /* pad */ + params + name_len_target;
2245 pSMB->DataCount = cpu_to_le16(name_len_target);
2246 pSMB->ParameterCount = cpu_to_le16(params);
2247 pSMB->TotalDataCount = pSMB->DataCount;
2248 pSMB->TotalParameterCount = pSMB->ParameterCount;
2249 pSMB->ParameterOffset = cpu_to_le16(param_offset);
2250 pSMB->DataOffset = cpu_to_le16(offset);
2251 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_LINK);
2252 pSMB->Reserved4 = 0;
2253 pSMB->hdr.smb_buf_length += byte_count;
2254 pSMB->ByteCount = cpu_to_le16(byte_count);
2255 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2256 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2257 cifs_stats_inc(&tcon->num_symlinks);
2259 cFYI(1, "Send error in SetPathInfo create symlink = %d", rc);
2261 cifs_buf_release(pSMB);
2264 goto createSymLinkRetry;
2270 CIFSUnixCreateHardLink(const int xid, struct cifsTconInfo *tcon,
2271 const char *fromName, const char *toName,
2272 const struct nls_table *nls_codepage, int remap)
2274 TRANSACTION2_SPI_REQ *pSMB = NULL;
2275 TRANSACTION2_SPI_RSP *pSMBr = NULL;
2278 int name_len_target;
2280 int bytes_returned = 0;
2281 __u16 params, param_offset, offset, byte_count;
2283 cFYI(1, "In Create Hard link Unix style");
2284 createHardLinkRetry:
2285 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2290 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2291 name_len = cifsConvertToUCS((__le16 *) pSMB->FileName, toName,
2292 PATH_MAX, nls_codepage, remap);
2293 name_len++; /* trailing null */
2296 } else { /* BB improve the check for buffer overruns BB */
2297 name_len = strnlen(toName, PATH_MAX);
2298 name_len++; /* trailing null */
2299 strncpy(pSMB->FileName, toName, name_len);
2301 params = 6 + name_len;
2302 pSMB->MaxSetupCount = 0;
2306 pSMB->Reserved2 = 0;
2307 param_offset = offsetof(struct smb_com_transaction2_spi_req,
2308 InformationLevel) - 4;
2309 offset = param_offset + params;
2311 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
2312 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2314 cifsConvertToUCS((__le16 *) data_offset, fromName, PATH_MAX,
2315 nls_codepage, remap);
2316 name_len_target++; /* trailing null */
2317 name_len_target *= 2;
2318 } else { /* BB improve the check for buffer overruns BB */
2319 name_len_target = strnlen(fromName, PATH_MAX);
2320 name_len_target++; /* trailing null */
2321 strncpy(data_offset, fromName, name_len_target);
2324 pSMB->MaxParameterCount = cpu_to_le16(2);
2325 /* BB find exact max on data count below from sess*/
2326 pSMB->MaxDataCount = cpu_to_le16(1000);
2327 pSMB->SetupCount = 1;
2328 pSMB->Reserved3 = 0;
2329 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
2330 byte_count = 3 /* pad */ + params + name_len_target;
2331 pSMB->ParameterCount = cpu_to_le16(params);
2332 pSMB->TotalParameterCount = pSMB->ParameterCount;
2333 pSMB->DataCount = cpu_to_le16(name_len_target);
2334 pSMB->TotalDataCount = pSMB->DataCount;
2335 pSMB->ParameterOffset = cpu_to_le16(param_offset);
2336 pSMB->DataOffset = cpu_to_le16(offset);
2337 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_HLINK);
2338 pSMB->Reserved4 = 0;
2339 pSMB->hdr.smb_buf_length += byte_count;
2340 pSMB->ByteCount = cpu_to_le16(byte_count);
2341 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2342 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2343 cifs_stats_inc(&tcon->num_hardlinks);
2345 cFYI(1, "Send error in SetPathInfo (hard link) = %d", rc);
2347 cifs_buf_release(pSMB);
2349 goto createHardLinkRetry;
2355 CIFSCreateHardLink(const int xid, struct cifsTconInfo *tcon,
2356 const char *fromName, const char *toName,
2357 const struct nls_table *nls_codepage, int remap)
2360 NT_RENAME_REQ *pSMB = NULL;
2361 RENAME_RSP *pSMBr = NULL;
2363 int name_len, name_len2;
2366 cFYI(1, "In CIFSCreateHardLink");
2367 winCreateHardLinkRetry:
2369 rc = smb_init(SMB_COM_NT_RENAME, 4, tcon, (void **) &pSMB,
2374 pSMB->SearchAttributes =
2375 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
2377 pSMB->Flags = cpu_to_le16(CREATE_HARD_LINK);
2378 pSMB->ClusterCount = 0;
2380 pSMB->BufferFormat = 0x04;
2382 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2384 cifsConvertToUCS((__le16 *) pSMB->OldFileName, fromName,
2385 PATH_MAX, nls_codepage, remap);
2386 name_len++; /* trailing null */
2389 /* protocol specifies ASCII buffer format (0x04) for unicode */
2390 pSMB->OldFileName[name_len] = 0x04;
2391 pSMB->OldFileName[name_len + 1] = 0x00; /* pad */
2393 cifsConvertToUCS((__le16 *)&pSMB->OldFileName[name_len + 2],
2394 toName, PATH_MAX, nls_codepage, remap);
2395 name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
2396 name_len2 *= 2; /* convert to bytes */
2397 } else { /* BB improve the check for buffer overruns BB */
2398 name_len = strnlen(fromName, PATH_MAX);
2399 name_len++; /* trailing null */
2400 strncpy(pSMB->OldFileName, fromName, name_len);
2401 name_len2 = strnlen(toName, PATH_MAX);
2402 name_len2++; /* trailing null */
2403 pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */
2404 strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2);
2405 name_len2++; /* trailing null */
2406 name_len2++; /* signature byte */
2409 count = 1 /* string type byte */ + name_len + name_len2;
2410 pSMB->hdr.smb_buf_length += count;
2411 pSMB->ByteCount = cpu_to_le16(count);
2413 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2414 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2415 cifs_stats_inc(&tcon->num_hardlinks);
2417 cFYI(1, "Send error in hard link (NT rename) = %d", rc);
2419 cifs_buf_release(pSMB);
2421 goto winCreateHardLinkRetry;
2427 CIFSSMBUnixQuerySymLink(const int xid, struct cifsTconInfo *tcon,
2428 const unsigned char *searchName, char **symlinkinfo,
2429 const struct nls_table *nls_codepage)
2431 /* SMB_QUERY_FILE_UNIX_LINK */
2432 TRANSACTION2_QPI_REQ *pSMB = NULL;
2433 TRANSACTION2_QPI_RSP *pSMBr = NULL;
2437 __u16 params, byte_count;
2440 cFYI(1, "In QPathSymLinkInfo (Unix) for path %s", searchName);
2443 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2448 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2450 cifs_strtoUCS((__le16 *) pSMB->FileName, searchName,
2451 PATH_MAX, nls_codepage);
2452 name_len++; /* trailing null */
2454 } else { /* BB improve the check for buffer overruns BB */
2455 name_len = strnlen(searchName, PATH_MAX);
2456 name_len++; /* trailing null */
2457 strncpy(pSMB->FileName, searchName, name_len);
2460 params = 2 /* level */ + 4 /* rsrvd */ + name_len /* incl null */ ;
2461 pSMB->TotalDataCount = 0;
2462 pSMB->MaxParameterCount = cpu_to_le16(2);
2463 pSMB->MaxDataCount = cpu_to_le16(CIFSMaxBufSize);
2464 pSMB->MaxSetupCount = 0;
2468 pSMB->Reserved2 = 0;
2469 pSMB->ParameterOffset = cpu_to_le16(offsetof(
2470 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
2471 pSMB->DataCount = 0;
2472 pSMB->DataOffset = 0;
2473 pSMB->SetupCount = 1;
2474 pSMB->Reserved3 = 0;
2475 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
2476 byte_count = params + 1 /* pad */ ;
2477 pSMB->TotalParameterCount = cpu_to_le16(params);
2478 pSMB->ParameterCount = pSMB->TotalParameterCount;
2479 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_LINK);
2480 pSMB->Reserved4 = 0;
2481 pSMB->hdr.smb_buf_length += byte_count;
2482 pSMB->ByteCount = cpu_to_le16(byte_count);
2484 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2485 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2487 cFYI(1, "Send error in QuerySymLinkInfo = %d", rc);
2489 /* decode response */
2491 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
2492 /* BB also check enough total bytes returned */
2493 if (rc || (pSMBr->ByteCount < 2))
2497 u16 count = le16_to_cpu(pSMBr->t2.DataCount);
2499 data_start = ((char *) &pSMBr->hdr.Protocol) +
2500 le16_to_cpu(pSMBr->t2.DataOffset);
2502 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
2507 /* BB FIXME investigate remapping reserved chars here */
2508 *symlinkinfo = cifs_strndup_from_ucs(data_start, count,
2509 is_unicode, nls_codepage);
2514 cifs_buf_release(pSMB);
2516 goto querySymLinkRetry;
2520 #ifdef CONFIG_CIFS_EXPERIMENTAL
2522 CIFSSMBQueryReparseLinkInfo(const int xid, struct cifsTconInfo *tcon,
2523 const unsigned char *searchName,
2524 char *symlinkinfo, const int buflen, __u16 fid,
2525 const struct nls_table *nls_codepage)
2529 struct smb_com_transaction_ioctl_req *pSMB;
2530 struct smb_com_transaction_ioctl_rsp *pSMBr;
2532 cFYI(1, "In Windows reparse style QueryLink for path %s", searchName);
2533 rc = smb_init(SMB_COM_NT_TRANSACT, 23, tcon, (void **) &pSMB,
2538 pSMB->TotalParameterCount = 0 ;
2539 pSMB->TotalDataCount = 0;
2540 pSMB->MaxParameterCount = cpu_to_le32(2);
2541 /* BB find exact data count max from sess structure BB */
2542 pSMB->MaxDataCount = cpu_to_le32((tcon->ses->server->maxBuf -
2543 MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
2544 pSMB->MaxSetupCount = 4;
2546 pSMB->ParameterOffset = 0;
2547 pSMB->DataCount = 0;
2548 pSMB->DataOffset = 0;
2549 pSMB->SetupCount = 4;
2550 pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_IOCTL);
2551 pSMB->ParameterCount = pSMB->TotalParameterCount;
2552 pSMB->FunctionCode = cpu_to_le32(FSCTL_GET_REPARSE_POINT);
2553 pSMB->IsFsctl = 1; /* FSCTL */
2554 pSMB->IsRootFlag = 0;
2555 pSMB->Fid = fid; /* file handle always le */
2556 pSMB->ByteCount = 0;
2558 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2559 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2561 cFYI(1, "Send error in QueryReparseLinkInfo = %d", rc);
2562 } else { /* decode response */
2563 __u32 data_offset = le32_to_cpu(pSMBr->DataOffset);
2564 __u32 data_count = le32_to_cpu(pSMBr->DataCount);
2565 if ((pSMBr->ByteCount < 2) || (data_offset > 512)) {
2566 /* BB also check enough total bytes returned */
2567 rc = -EIO; /* bad smb */
2570 if (data_count && (data_count < 2048)) {
2571 char *end_of_smb = 2 /* sizeof byte count */ +
2572 pSMBr->ByteCount + (char *)&pSMBr->ByteCount;
2574 struct reparse_data *reparse_buf =
2575 (struct reparse_data *)
2576 ((char *)&pSMBr->hdr.Protocol
2578 if ((char *)reparse_buf >= end_of_smb) {
2582 if ((reparse_buf->LinkNamesBuf +
2583 reparse_buf->TargetNameOffset +
2584 reparse_buf->TargetNameLen) > end_of_smb) {
2585 cFYI(1, "reparse buf beyond SMB");
2590 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
2591 cifs_from_ucs2(symlinkinfo, (__le16 *)
2592 (reparse_buf->LinkNamesBuf +
2593 reparse_buf->TargetNameOffset),
2595 reparse_buf->TargetNameLen,
2597 } else { /* ASCII names */
2598 strncpy(symlinkinfo,
2599 reparse_buf->LinkNamesBuf +
2600 reparse_buf->TargetNameOffset,
2601 min_t(const int, buflen,
2602 reparse_buf->TargetNameLen));
2606 cFYI(1, "Invalid return data count on "
2607 "get reparse info ioctl");
2609 symlinkinfo[buflen] = 0; /* just in case so the caller
2610 does not go off the end of the buffer */
2611 cFYI(1, "readlink result - %s", symlinkinfo);
2615 cifs_buf_release(pSMB);
2617 /* Note: On -EAGAIN error only caller can retry on handle based calls
2618 since file handle passed in no longer valid */
2622 #endif /* CIFS_EXPERIMENTAL */
2624 #ifdef CONFIG_CIFS_POSIX
2626 /*Convert an Access Control Entry from wire format to local POSIX xattr format*/
2627 static void cifs_convert_ace(posix_acl_xattr_entry *ace,
2628 struct cifs_posix_ace *cifs_ace)
2630 /* u8 cifs fields do not need le conversion */
2631 ace->e_perm = cpu_to_le16(cifs_ace->cifs_e_perm);
2632 ace->e_tag = cpu_to_le16(cifs_ace->cifs_e_tag);
2633 ace->e_id = cpu_to_le32(le64_to_cpu(cifs_ace->cifs_uid));
2634 /* cFYI(1, "perm %d tag %d id %d",ace->e_perm,ace->e_tag,ace->e_id); */
2639 /* Convert ACL from CIFS POSIX wire format to local Linux POSIX ACL xattr */
2640 static int cifs_copy_posix_acl(char *trgt, char *src, const int buflen,
2641 const int acl_type, const int size_of_data_area)
2646 struct cifs_posix_ace *pACE;
2647 struct cifs_posix_acl *cifs_acl = (struct cifs_posix_acl *)src;
2648 posix_acl_xattr_header *local_acl = (posix_acl_xattr_header *)trgt;
2650 if (le16_to_cpu(cifs_acl->version) != CIFS_ACL_VERSION)
2653 if (acl_type & ACL_TYPE_ACCESS) {
2654 count = le16_to_cpu(cifs_acl->access_entry_count);
2655 pACE = &cifs_acl->ace_array[0];
2656 size = sizeof(struct cifs_posix_acl);
2657 size += sizeof(struct cifs_posix_ace) * count;
2658 /* check if we would go beyond end of SMB */
2659 if (size_of_data_area < size) {
2660 cFYI(1, "bad CIFS POSIX ACL size %d vs. %d",
2661 size_of_data_area, size);
2664 } else if (acl_type & ACL_TYPE_DEFAULT) {
2665 count = le16_to_cpu(cifs_acl->access_entry_count);
2666 size = sizeof(struct cifs_posix_acl);
2667 size += sizeof(struct cifs_posix_ace) * count;
2668 /* skip past access ACEs to get to default ACEs */
2669 pACE = &cifs_acl->ace_array[count];
2670 count = le16_to_cpu(cifs_acl->default_entry_count);
2671 size += sizeof(struct cifs_posix_ace) * count;
2672 /* check if we would go beyond end of SMB */
2673 if (size_of_data_area < size)
2680 size = posix_acl_xattr_size(count);
2681 if ((buflen == 0) || (local_acl == NULL)) {
2682 /* used to query ACL EA size */
2683 } else if (size > buflen) {
2685 } else /* buffer big enough */ {
2686 local_acl->a_version = cpu_to_le32(POSIX_ACL_XATTR_VERSION);
2687 for (i = 0; i < count ; i++) {
2688 cifs_convert_ace(&local_acl->a_entries[i], pACE);
2695 static __u16 convert_ace_to_cifs_ace(struct cifs_posix_ace *cifs_ace,
2696 const posix_acl_xattr_entry *local_ace)
2698 __u16 rc = 0; /* 0 = ACL converted ok */
2700 cifs_ace->cifs_e_perm = le16_to_cpu(local_ace->e_perm);
2701 cifs_ace->cifs_e_tag = le16_to_cpu(local_ace->e_tag);
2702 /* BB is there a better way to handle the large uid? */
2703 if (local_ace->e_id == cpu_to_le32(-1)) {
2704 /* Probably no need to le convert -1 on any arch but can not hurt */
2705 cifs_ace->cifs_uid = cpu_to_le64(-1);
2707 cifs_ace->cifs_uid = cpu_to_le64(le32_to_cpu(local_ace->e_id));
2708 /*cFYI(1, "perm %d tag %d id %d",ace->e_perm,ace->e_tag,ace->e_id);*/
2712 /* Convert ACL from local Linux POSIX xattr to CIFS POSIX ACL wire format */
2713 static __u16 ACL_to_cifs_posix(char *parm_data, const char *pACL,
2714 const int buflen, const int acl_type)
2717 struct cifs_posix_acl *cifs_acl = (struct cifs_posix_acl *)parm_data;
2718 posix_acl_xattr_header *local_acl = (posix_acl_xattr_header *)pACL;
2722 if ((buflen == 0) || (pACL == NULL) || (cifs_acl == NULL))
2725 count = posix_acl_xattr_count((size_t)buflen);
2726 cFYI(1, "setting acl with %d entries from buf of length %d and "
2728 count, buflen, le32_to_cpu(local_acl->a_version));
2729 if (le32_to_cpu(local_acl->a_version) != 2) {
2730 cFYI(1, "unknown POSIX ACL version %d",
2731 le32_to_cpu(local_acl->a_version));
2734 cifs_acl->version = cpu_to_le16(1);
2735 if (acl_type == ACL_TYPE_ACCESS)
2736 cifs_acl->access_entry_count = cpu_to_le16(count);
2737 else if (acl_type == ACL_TYPE_DEFAULT)
2738 cifs_acl->default_entry_count = cpu_to_le16(count);
2740 cFYI(1, "unknown ACL type %d", acl_type);
2743 for (i = 0; i < count; i++) {
2744 rc = convert_ace_to_cifs_ace(&cifs_acl->ace_array[i],
2745 &local_acl->a_entries[i]);
2747 /* ACE not converted */
2752 rc = (__u16)(count * sizeof(struct cifs_posix_ace));
2753 rc += sizeof(struct cifs_posix_acl);
2754 /* BB add check to make sure ACL does not overflow SMB */
2760 CIFSSMBGetPosixACL(const int xid, struct cifsTconInfo *tcon,
2761 const unsigned char *searchName,
2762 char *acl_inf, const int buflen, const int acl_type,
2763 const struct nls_table *nls_codepage, int remap)
2765 /* SMB_QUERY_POSIX_ACL */
2766 TRANSACTION2_QPI_REQ *pSMB = NULL;
2767 TRANSACTION2_QPI_RSP *pSMBr = NULL;
2771 __u16 params, byte_count;
2773 cFYI(1, "In GetPosixACL (Unix) for path %s", searchName);
2776 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2781 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2783 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
2784 PATH_MAX, nls_codepage, remap);
2785 name_len++; /* trailing null */
2787 pSMB->FileName[name_len] = 0;
2788 pSMB->FileName[name_len+1] = 0;
2789 } else { /* BB improve the check for buffer overruns BB */
2790 name_len = strnlen(searchName, PATH_MAX);
2791 name_len++; /* trailing null */
2792 strncpy(pSMB->FileName, searchName, name_len);
2795 params = 2 /* level */ + 4 /* rsrvd */ + name_len /* incl null */ ;
2796 pSMB->TotalDataCount = 0;
2797 pSMB->MaxParameterCount = cpu_to_le16(2);
2798 /* BB find exact max data count below from sess structure BB */
2799 pSMB->MaxDataCount = cpu_to_le16(4000);
2800 pSMB->MaxSetupCount = 0;
2804 pSMB->Reserved2 = 0;
2805 pSMB->ParameterOffset = cpu_to_le16(
2806 offsetof(struct smb_com_transaction2_qpi_req,
2807 InformationLevel) - 4);
2808 pSMB->DataCount = 0;
2809 pSMB->DataOffset = 0;
2810 pSMB->SetupCount = 1;
2811 pSMB->Reserved3 = 0;
2812 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
2813 byte_count = params + 1 /* pad */ ;
2814 pSMB->TotalParameterCount = cpu_to_le16(params);
2815 pSMB->ParameterCount = pSMB->TotalParameterCount;
2816 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_POSIX_ACL);
2817 pSMB->Reserved4 = 0;
2818 pSMB->hdr.smb_buf_length += byte_count;
2819 pSMB->ByteCount = cpu_to_le16(byte_count);
2821 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2822 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2823 cifs_stats_inc(&tcon->num_acl_get);
2825 cFYI(1, "Send error in Query POSIX ACL = %d", rc);
2827 /* decode response */
2829 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
2830 if (rc || (pSMBr->ByteCount < 2))
2831 /* BB also check enough total bytes returned */
2832 rc = -EIO; /* bad smb */
2834 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
2835 __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
2836 rc = cifs_copy_posix_acl(acl_inf,
2837 (char *)&pSMBr->hdr.Protocol+data_offset,
2838 buflen, acl_type, count);
2841 cifs_buf_release(pSMB);
2848 CIFSSMBSetPosixACL(const int xid, struct cifsTconInfo *tcon,
2849 const unsigned char *fileName,
2850 const char *local_acl, const int buflen,
2852 const struct nls_table *nls_codepage, int remap)
2854 struct smb_com_transaction2_spi_req *pSMB = NULL;
2855 struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
2859 int bytes_returned = 0;
2860 __u16 params, byte_count, data_count, param_offset, offset;
2862 cFYI(1, "In SetPosixACL (Unix) for path %s", fileName);
2864 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2868 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2870 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
2871 PATH_MAX, nls_codepage, remap);
2872 name_len++; /* trailing null */
2874 } else { /* BB improve the check for buffer overruns BB */
2875 name_len = strnlen(fileName, PATH_MAX);
2876 name_len++; /* trailing null */
2877 strncpy(pSMB->FileName, fileName, name_len);
2879 params = 6 + name_len;
2880 pSMB->MaxParameterCount = cpu_to_le16(2);
2881 /* BB find max SMB size from sess */
2882 pSMB->MaxDataCount = cpu_to_le16(1000);
2883 pSMB->MaxSetupCount = 0;
2887 pSMB->Reserved2 = 0;
2888 param_offset = offsetof(struct smb_com_transaction2_spi_req,
2889 InformationLevel) - 4;
2890 offset = param_offset + params;
2891 parm_data = ((char *) &pSMB->hdr.Protocol) + offset;
2892 pSMB->ParameterOffset = cpu_to_le16(param_offset);
2894 /* convert to on the wire format for POSIX ACL */
2895 data_count = ACL_to_cifs_posix(parm_data, local_acl, buflen, acl_type);
2897 if (data_count == 0) {
2899 goto setACLerrorExit;
2901 pSMB->DataOffset = cpu_to_le16(offset);
2902 pSMB->SetupCount = 1;
2903 pSMB->Reserved3 = 0;
2904 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
2905 pSMB->InformationLevel = cpu_to_le16(SMB_SET_POSIX_ACL);
2906 byte_count = 3 /* pad */ + params + data_count;
2907 pSMB->DataCount = cpu_to_le16(data_count);
2908 pSMB->TotalDataCount = pSMB->DataCount;
2909 pSMB->ParameterCount = cpu_to_le16(params);
2910 pSMB->TotalParameterCount = pSMB->ParameterCount;
2911 pSMB->Reserved4 = 0;
2912 pSMB->hdr.smb_buf_length += byte_count;
2913 pSMB->ByteCount = cpu_to_le16(byte_count);
2914 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2915 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2917 cFYI(1, "Set POSIX ACL returned %d", rc);
2920 cifs_buf_release(pSMB);
2926 /* BB fix tabs in this function FIXME BB */
2928 CIFSGetExtAttr(const int xid, struct cifsTconInfo *tcon,
2929 const int netfid, __u64 *pExtAttrBits, __u64 *pMask)
2932 struct smb_t2_qfi_req *pSMB = NULL;
2933 struct smb_t2_qfi_rsp *pSMBr = NULL;
2935 __u16 params, byte_count;
2937 cFYI(1, "In GetExtAttr");
2942 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2947 params = 2 /* level */ + 2 /* fid */;
2948 pSMB->t2.TotalDataCount = 0;
2949 pSMB->t2.MaxParameterCount = cpu_to_le16(4);
2950 /* BB find exact max data count below from sess structure BB */
2951 pSMB->t2.MaxDataCount = cpu_to_le16(4000);
2952 pSMB->t2.MaxSetupCount = 0;
2953 pSMB->t2.Reserved = 0;
2955 pSMB->t2.Timeout = 0;
2956 pSMB->t2.Reserved2 = 0;
2957 pSMB->t2.ParameterOffset = cpu_to_le16(offsetof(struct smb_t2_qfi_req,
2959 pSMB->t2.DataCount = 0;
2960 pSMB->t2.DataOffset = 0;
2961 pSMB->t2.SetupCount = 1;
2962 pSMB->t2.Reserved3 = 0;
2963 pSMB->t2.SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION);
2964 byte_count = params + 1 /* pad */ ;
2965 pSMB->t2.TotalParameterCount = cpu_to_le16(params);
2966 pSMB->t2.ParameterCount = pSMB->t2.TotalParameterCount;
2967 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_ATTR_FLAGS);
2970 pSMB->hdr.smb_buf_length += byte_count;
2971 pSMB->t2.ByteCount = cpu_to_le16(byte_count);
2973 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2974 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2976 cFYI(1, "error %d in GetExtAttr", rc);
2978 /* decode response */
2979 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
2980 if (rc || (pSMBr->ByteCount < 2))
2981 /* BB also check enough total bytes returned */
2982 /* If rc should we check for EOPNOSUPP and
2983 disable the srvino flag? or in caller? */
2984 rc = -EIO; /* bad smb */
2986 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
2987 __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
2988 struct file_chattr_info *pfinfo;
2989 /* BB Do we need a cast or hash here ? */
2991 cFYI(1, "Illegal size ret in GetExtAttr");
2995 pfinfo = (struct file_chattr_info *)
2996 (data_offset + (char *) &pSMBr->hdr.Protocol);
2997 *pExtAttrBits = le64_to_cpu(pfinfo->mode);
2998 *pMask = le64_to_cpu(pfinfo->mask);
3002 cifs_buf_release(pSMB);
3004 goto GetExtAttrRetry;
3008 #endif /* CONFIG_POSIX */
3010 #ifdef CONFIG_CIFS_ACL
3012 * Initialize NT TRANSACT SMB into small smb request buffer. This assumes that
3013 * all NT TRANSACTS that we init here have total parm and data under about 400
3014 * bytes (to fit in small cifs buffer size), which is the case so far, it
3015 * easily fits. NB: Setup words themselves and ByteCount MaxSetupCount (size of
3016 * returned setup area) and MaxParameterCount (returned parms size) must be set
3020 smb_init_nttransact(const __u16 sub_command, const int setup_count,
3021 const int parm_len, struct cifsTconInfo *tcon,
3026 struct smb_com_ntransact_req *pSMB;
3028 rc = small_smb_init(SMB_COM_NT_TRANSACT, 19 + setup_count, tcon,
3032 *ret_buf = (void *)pSMB;
3034 pSMB->TotalParameterCount = cpu_to_le32(parm_len);
3035 pSMB->TotalDataCount = 0;
3036 pSMB->MaxDataCount = cpu_to_le32((tcon->ses->server->maxBuf -
3037 MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
3038 pSMB->ParameterCount = pSMB->TotalParameterCount;
3039 pSMB->DataCount = pSMB->TotalDataCount;
3040 temp_offset = offsetof(struct smb_com_ntransact_req, Parms) +
3041 (setup_count * 2) - 4 /* for rfc1001 length itself */;
3042 pSMB->ParameterOffset = cpu_to_le32(temp_offset);
3043 pSMB->DataOffset = cpu_to_le32(temp_offset + parm_len);
3044 pSMB->SetupCount = setup_count; /* no need to le convert byte fields */
3045 pSMB->SubCommand = cpu_to_le16(sub_command);
3050 validate_ntransact(char *buf, char **ppparm, char **ppdata,
3051 __u32 *pparmlen, __u32 *pdatalen)
3054 __u32 data_count, data_offset, parm_count, parm_offset;
3055 struct smb_com_ntransact_rsp *pSMBr;
3063 pSMBr = (struct smb_com_ntransact_rsp *)buf;
3065 /* ByteCount was converted from little endian in SendReceive */
3066 end_of_smb = 2 /* sizeof byte count */ + pSMBr->ByteCount +
3067 (char *)&pSMBr->ByteCount;
3069 data_offset = le32_to_cpu(pSMBr->DataOffset);
3070 data_count = le32_to_cpu(pSMBr->DataCount);
3071 parm_offset = le32_to_cpu(pSMBr->ParameterOffset);
3072 parm_count = le32_to_cpu(pSMBr->ParameterCount);
3074 *ppparm = (char *)&pSMBr->hdr.Protocol + parm_offset;
3075 *ppdata = (char *)&pSMBr->hdr.Protocol + data_offset;
3077 /* should we also check that parm and data areas do not overlap? */
3078 if (*ppparm > end_of_smb) {
3079 cFYI(1, "parms start after end of smb");
3081 } else if (parm_count + *ppparm > end_of_smb) {
3082 cFYI(1, "parm end after end of smb");
3084 } else if (*ppdata > end_of_smb) {
3085 cFYI(1, "data starts after end of smb");
3087 } else if (data_count + *ppdata > end_of_smb) {
3088 cFYI(1, "data %p + count %d (%p) past smb end %p start %p",
3089 *ppdata, data_count, (data_count + *ppdata),
3092 } else if (parm_count + data_count > pSMBr->ByteCount) {
3093 cFYI(1, "parm count and data count larger than SMB");
3096 *pdatalen = data_count;
3097 *pparmlen = parm_count;
3101 /* Get Security Descriptor (by handle) from remote server for a file or dir */
3103 CIFSSMBGetCIFSACL(const int xid, struct cifsTconInfo *tcon, __u16 fid,
3104 struct cifs_ntsd **acl_inf, __u32 *pbuflen)
3108 QUERY_SEC_DESC_REQ *pSMB;
3111 cFYI(1, "GetCifsACL");
3116 rc = smb_init_nttransact(NT_TRANSACT_QUERY_SECURITY_DESC, 0,
3117 8 /* parm len */, tcon, (void **) &pSMB);
3121 pSMB->MaxParameterCount = cpu_to_le32(4);
3122 /* BB TEST with big acls that might need to be e.g. larger than 16K */
3123 pSMB->MaxSetupCount = 0;
3124 pSMB->Fid = fid; /* file handle always le */
3125 pSMB->AclFlags = cpu_to_le32(CIFS_ACL_OWNER | CIFS_ACL_GROUP |
3127 pSMB->ByteCount = cpu_to_le16(11); /* 3 bytes pad + 8 bytes parm */
3128 pSMB->hdr.smb_buf_length += 11;
3129 iov[0].iov_base = (char *)pSMB;
3130 iov[0].iov_len = pSMB->hdr.smb_buf_length + 4;
3132 rc = SendReceive2(xid, tcon->ses, iov, 1 /* num iovec */, &buf_type,
3134 cifs_stats_inc(&tcon->num_acl_get);
3136 cFYI(1, "Send error in QuerySecDesc = %d", rc);
3137 } else { /* decode response */
3141 struct smb_com_ntransact_rsp *pSMBr;
3144 /* validate_nttransact */
3145 rc = validate_ntransact(iov[0].iov_base, (char **)&parm,
3146 &pdata, &parm_len, pbuflen);
3149 pSMBr = (struct smb_com_ntransact_rsp *)iov[0].iov_base;
3151 cFYI(1, "smb %p parm %p data %p", pSMBr, parm, *acl_inf);
3153 if (le32_to_cpu(pSMBr->ParameterCount) != 4) {
3154 rc = -EIO; /* bad smb */
3159 /* BB check that data area is minimum length and as big as acl_len */
3161 acl_len = le32_to_cpu(*parm);
3162 if (acl_len != *pbuflen) {
3163 cERROR(1, "acl length %d does not match %d",
3165 if (*pbuflen > acl_len)
3169 /* check if buffer is big enough for the acl
3170 header followed by the smallest SID */
3171 if ((*pbuflen < sizeof(struct cifs_ntsd) + 8) ||
3172 (*pbuflen >= 64 * 1024)) {
3173 cERROR(1, "bad acl length %d", *pbuflen);
3177 *acl_inf = kmalloc(*pbuflen, GFP_KERNEL);
3178 if (*acl_inf == NULL) {
3182 memcpy(*acl_inf, pdata, *pbuflen);
3186 if (buf_type == CIFS_SMALL_BUFFER)
3187 cifs_small_buf_release(iov[0].iov_base);
3188 else if (buf_type == CIFS_LARGE_BUFFER)
3189 cifs_buf_release(iov[0].iov_base);
3190 /* cifs_small_buf_release(pSMB); */ /* Freed earlier now in SendReceive2 */
3195 CIFSSMBSetCIFSACL(const int xid, struct cifsTconInfo *tcon, __u16 fid,
3196 struct cifs_ntsd *pntsd, __u32 acllen)
3198 __u16 byte_count, param_count, data_count, param_offset, data_offset;
3200 int bytes_returned = 0;
3201 SET_SEC_DESC_REQ *pSMB = NULL;
3202 NTRANSACT_RSP *pSMBr = NULL;
3205 rc = smb_init(SMB_COM_NT_TRANSACT, 19, tcon, (void **) &pSMB,
3210 pSMB->MaxSetupCount = 0;
3214 param_offset = offsetof(struct smb_com_transaction_ssec_req, Fid) - 4;
3215 data_count = acllen;
3216 data_offset = param_offset + param_count;
3217 byte_count = 3 /* pad */ + param_count;
3219 pSMB->DataCount = cpu_to_le32(data_count);
3220 pSMB->TotalDataCount = pSMB->DataCount;
3221 pSMB->MaxParameterCount = cpu_to_le32(4);
3222 pSMB->MaxDataCount = cpu_to_le32(16384);
3223 pSMB->ParameterCount = cpu_to_le32(param_count);
3224 pSMB->ParameterOffset = cpu_to_le32(param_offset);
3225 pSMB->TotalParameterCount = pSMB->ParameterCount;
3226 pSMB->DataOffset = cpu_to_le32(data_offset);
3227 pSMB->SetupCount = 0;
3228 pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_SET_SECURITY_DESC);
3229 pSMB->ByteCount = cpu_to_le16(byte_count+data_count);
3231 pSMB->Fid = fid; /* file handle always le */
3232 pSMB->Reserved2 = 0;
3233 pSMB->AclFlags = cpu_to_le32(CIFS_ACL_DACL);
3235 if (pntsd && acllen) {
3236 memcpy((char *) &pSMBr->hdr.Protocol + data_offset,
3239 pSMB->hdr.smb_buf_length += (byte_count + data_count);
3242 pSMB->hdr.smb_buf_length += byte_count;
3244 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3245 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3247 cFYI(1, "SetCIFSACL bytes_returned: %d, rc: %d", bytes_returned, rc);
3249 cFYI(1, "Set CIFS ACL returned %d", rc);
3250 cifs_buf_release(pSMB);
3253 goto setCifsAclRetry;
3258 #endif /* CONFIG_CIFS_ACL */
3260 /* Legacy Query Path Information call for lookup to old servers such
3262 int SMBQueryInformation(const int xid, struct cifsTconInfo *tcon,
3263 const unsigned char *searchName,
3264 FILE_ALL_INFO *pFinfo,
3265 const struct nls_table *nls_codepage, int remap)
3267 QUERY_INFORMATION_REQ *pSMB;
3268 QUERY_INFORMATION_RSP *pSMBr;
3273 cFYI(1, "In SMBQPath path %s", searchName);
3275 rc = smb_init(SMB_COM_QUERY_INFORMATION, 0, tcon, (void **) &pSMB,
3280 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3282 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
3283 PATH_MAX, nls_codepage, remap);
3284 name_len++; /* trailing null */
3287 name_len = strnlen(searchName, PATH_MAX);
3288 name_len++; /* trailing null */
3289 strncpy(pSMB->FileName, searchName, name_len);
3291 pSMB->BufferFormat = 0x04;
3292 name_len++; /* account for buffer type byte */
3293 pSMB->hdr.smb_buf_length += (__u16) name_len;
3294 pSMB->ByteCount = cpu_to_le16(name_len);
3296 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3297 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3299 cFYI(1, "Send error in QueryInfo = %d", rc);
3300 } else if (pFinfo) {
3302 __u32 time = le32_to_cpu(pSMBr->last_write_time);
3304 /* decode response */
3305 /* BB FIXME - add time zone adjustment BB */
3306 memset(pFinfo, 0, sizeof(FILE_ALL_INFO));
3309 /* decode time fields */
3310 pFinfo->ChangeTime = cpu_to_le64(cifs_UnixTimeToNT(ts));
3311 pFinfo->LastWriteTime = pFinfo->ChangeTime;
3312 pFinfo->LastAccessTime = 0;
3313 pFinfo->AllocationSize =
3314 cpu_to_le64(le32_to_cpu(pSMBr->size));
3315 pFinfo->EndOfFile = pFinfo->AllocationSize;
3316 pFinfo->Attributes =
3317 cpu_to_le32(le16_to_cpu(pSMBr->attr));
3319 rc = -EIO; /* bad buffer passed in */
3321 cifs_buf_release(pSMB);
3330 CIFSSMBQFileInfo(const int xid, struct cifsTconInfo *tcon,
3331 u16 netfid, FILE_ALL_INFO *pFindData)
3333 struct smb_t2_qfi_req *pSMB = NULL;
3334 struct smb_t2_qfi_rsp *pSMBr = NULL;
3337 __u16 params, byte_count;
3340 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3345 params = 2 /* level */ + 2 /* fid */;
3346 pSMB->t2.TotalDataCount = 0;
3347 pSMB->t2.MaxParameterCount = cpu_to_le16(4);
3348 /* BB find exact max data count below from sess structure BB */
3349 pSMB->t2.MaxDataCount = cpu_to_le16(CIFSMaxBufSize);
3350 pSMB->t2.MaxSetupCount = 0;
3351 pSMB->t2.Reserved = 0;
3353 pSMB->t2.Timeout = 0;
3354 pSMB->t2.Reserved2 = 0;
3355 pSMB->t2.ParameterOffset = cpu_to_le16(offsetof(struct smb_t2_qfi_req,
3357 pSMB->t2.DataCount = 0;
3358 pSMB->t2.DataOffset = 0;
3359 pSMB->t2.SetupCount = 1;
3360 pSMB->t2.Reserved3 = 0;
3361 pSMB->t2.SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION);
3362 byte_count = params + 1 /* pad */ ;
3363 pSMB->t2.TotalParameterCount = cpu_to_le16(params);
3364 pSMB->t2.ParameterCount = pSMB->t2.TotalParameterCount;
3365 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_ALL_INFO);
3368 pSMB->hdr.smb_buf_length += byte_count;
3370 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3371 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3373 cFYI(1, "Send error in QPathInfo = %d", rc);
3374 } else { /* decode response */
3375 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3377 if (rc) /* BB add auto retry on EOPNOTSUPP? */
3379 else if (pSMBr->ByteCount < 40)
3380 rc = -EIO; /* bad smb */
3381 else if (pFindData) {
3382 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3383 memcpy((char *) pFindData,
3384 (char *) &pSMBr->hdr.Protocol +
3385 data_offset, sizeof(FILE_ALL_INFO));
3389 cifs_buf_release(pSMB);
3391 goto QFileInfoRetry;
3397 CIFSSMBQPathInfo(const int xid, struct cifsTconInfo *tcon,
3398 const unsigned char *searchName,
3399 FILE_ALL_INFO *pFindData,
3400 int legacy /* old style infolevel */,
3401 const struct nls_table *nls_codepage, int remap)
3403 /* level 263 SMB_QUERY_FILE_ALL_INFO */
3404 TRANSACTION2_QPI_REQ *pSMB = NULL;
3405 TRANSACTION2_QPI_RSP *pSMBr = NULL;
3409 __u16 params, byte_count;
3411 /* cFYI(1, "In QPathInfo path %s", searchName); */
3413 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3418 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3420 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
3421 PATH_MAX, nls_codepage, remap);
3422 name_len++; /* trailing null */
3424 } else { /* BB improve the check for buffer overruns BB */
3425 name_len = strnlen(searchName, PATH_MAX);
3426 name_len++; /* trailing null */
3427 strncpy(pSMB->FileName, searchName, name_len);
3430 params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */;
3431 pSMB->TotalDataCount = 0;
3432 pSMB->MaxParameterCount = cpu_to_le16(2);
3433 /* BB find exact max SMB PDU from sess structure BB */
3434 pSMB->MaxDataCount = cpu_to_le16(4000);
3435 pSMB->MaxSetupCount = 0;
3439 pSMB->Reserved2 = 0;
3440 pSMB->ParameterOffset = cpu_to_le16(offsetof(
3441 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
3442 pSMB->DataCount = 0;
3443 pSMB->DataOffset = 0;
3444 pSMB->SetupCount = 1;
3445 pSMB->Reserved3 = 0;
3446 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
3447 byte_count = params + 1 /* pad */ ;
3448 pSMB->TotalParameterCount = cpu_to_le16(params);
3449 pSMB->ParameterCount = pSMB->TotalParameterCount;
3451 pSMB->InformationLevel = cpu_to_le16(SMB_INFO_STANDARD);
3453 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_ALL_INFO);
3454 pSMB->Reserved4 = 0;
3455 pSMB->hdr.smb_buf_length += byte_count;
3456 pSMB->ByteCount = cpu_to_le16(byte_count);
3458 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3459 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3461 cFYI(1, "Send error in QPathInfo = %d", rc);
3462 } else { /* decode response */
3463 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3465 if (rc) /* BB add auto retry on EOPNOTSUPP? */
3467 else if (!legacy && (pSMBr->ByteCount < 40))
3468 rc = -EIO; /* bad smb */
3469 else if (legacy && (pSMBr->ByteCount < 24))
3470 rc = -EIO; /* 24 or 26 expected but we do not read
3472 else if (pFindData) {
3474 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3476 /* On legacy responses we do not read the last field,
3477 EAsize, fortunately since it varies by subdialect and
3478 also note it differs on Set vs. Get, ie two bytes or 4
3479 bytes depending but we don't care here */
3481 size = sizeof(FILE_INFO_STANDARD);
3483 size = sizeof(FILE_ALL_INFO);
3484 memcpy((char *) pFindData,
3485 (char *) &pSMBr->hdr.Protocol +
3490 cifs_buf_release(pSMB);
3492 goto QPathInfoRetry;
3498 CIFSSMBUnixQFileInfo(const int xid, struct cifsTconInfo *tcon,
3499 u16 netfid, FILE_UNIX_BASIC_INFO *pFindData)
3501 struct smb_t2_qfi_req *pSMB = NULL;
3502 struct smb_t2_qfi_rsp *pSMBr = NULL;
3505 __u16 params, byte_count;
3508 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3513 params = 2 /* level */ + 2 /* fid */;
3514 pSMB->t2.TotalDataCount = 0;
3515 pSMB->t2.MaxParameterCount = cpu_to_le16(4);
3516 /* BB find exact max data count below from sess structure BB */
3517 pSMB->t2.MaxDataCount = cpu_to_le16(CIFSMaxBufSize);
3518 pSMB->t2.MaxSetupCount = 0;
3519 pSMB->t2.Reserved = 0;
3521 pSMB->t2.Timeout = 0;
3522 pSMB->t2.Reserved2 = 0;
3523 pSMB->t2.ParameterOffset = cpu_to_le16(offsetof(struct smb_t2_qfi_req,
3525 pSMB->t2.DataCount = 0;
3526 pSMB->t2.DataOffset = 0;
3527 pSMB->t2.SetupCount = 1;
3528 pSMB->t2.Reserved3 = 0;
3529 pSMB->t2.SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION);
3530 byte_count = params + 1 /* pad */ ;
3531 pSMB->t2.TotalParameterCount = cpu_to_le16(params);
3532 pSMB->t2.ParameterCount = pSMB->t2.TotalParameterCount;
3533 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC);
3536 pSMB->hdr.smb_buf_length += byte_count;
3538 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3539 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3541 cFYI(1, "Send error in QPathInfo = %d", rc);
3542 } else { /* decode response */
3543 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3545 if (rc || (pSMBr->ByteCount < sizeof(FILE_UNIX_BASIC_INFO))) {
3546 cERROR(1, "Malformed FILE_UNIX_BASIC_INFO response.\n"
3547 "Unix Extensions can be disabled on mount "
3548 "by specifying the nosfu mount option.");
3549 rc = -EIO; /* bad smb */
3551 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3552 memcpy((char *) pFindData,
3553 (char *) &pSMBr->hdr.Protocol +
3555 sizeof(FILE_UNIX_BASIC_INFO));
3559 cifs_buf_release(pSMB);
3561 goto UnixQFileInfoRetry;
3567 CIFSSMBUnixQPathInfo(const int xid, struct cifsTconInfo *tcon,
3568 const unsigned char *searchName,
3569 FILE_UNIX_BASIC_INFO *pFindData,
3570 const struct nls_table *nls_codepage, int remap)
3572 /* SMB_QUERY_FILE_UNIX_BASIC */
3573 TRANSACTION2_QPI_REQ *pSMB = NULL;
3574 TRANSACTION2_QPI_RSP *pSMBr = NULL;
3576 int bytes_returned = 0;
3578 __u16 params, byte_count;
3580 cFYI(1, "In QPathInfo (Unix) the path %s", searchName);
3582 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3587 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3589 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
3590 PATH_MAX, nls_codepage, remap);
3591 name_len++; /* trailing null */
3593 } else { /* BB improve the check for buffer overruns BB */
3594 name_len = strnlen(searchName, PATH_MAX);
3595 name_len++; /* trailing null */
3596 strncpy(pSMB->FileName, searchName, name_len);
3599 params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */;
3600 pSMB->TotalDataCount = 0;
3601 pSMB->MaxParameterCount = cpu_to_le16(2);
3602 /* BB find exact max SMB PDU from sess structure BB */
3603 pSMB->MaxDataCount = cpu_to_le16(4000);
3604 pSMB->MaxSetupCount = 0;
3608 pSMB->Reserved2 = 0;
3609 pSMB->ParameterOffset = cpu_to_le16(offsetof(
3610 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
3611 pSMB->DataCount = 0;
3612 pSMB->DataOffset = 0;
3613 pSMB->SetupCount = 1;
3614 pSMB->Reserved3 = 0;
3615 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
3616 byte_count = params + 1 /* pad */ ;
3617 pSMB->TotalParameterCount = cpu_to_le16(params);
3618 pSMB->ParameterCount = pSMB->TotalParameterCount;
3619 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC);
3620 pSMB->Reserved4 = 0;
3621 pSMB->hdr.smb_buf_length += byte_count;
3622 pSMB->ByteCount = cpu_to_le16(byte_count);
3624 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3625 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3627 cFYI(1, "Send error in QPathInfo = %d", rc);
3628 } else { /* decode response */
3629 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3631 if (rc || (pSMBr->ByteCount < sizeof(FILE_UNIX_BASIC_INFO))) {
3632 cERROR(1, "Malformed FILE_UNIX_BASIC_INFO response.\n"
3633 "Unix Extensions can be disabled on mount "
3634 "by specifying the nosfu mount option.");
3635 rc = -EIO; /* bad smb */
3637 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3638 memcpy((char *) pFindData,
3639 (char *) &pSMBr->hdr.Protocol +
3641 sizeof(FILE_UNIX_BASIC_INFO));
3644 cifs_buf_release(pSMB);
3646 goto UnixQPathInfoRetry;
3651 /* xid, tcon, searchName and codepage are input parms, rest are returned */
3653 CIFSFindFirst(const int xid, struct cifsTconInfo *tcon,
3654 const char *searchName,
3655 const struct nls_table *nls_codepage,
3657 struct cifs_search_info *psrch_inf, int remap, const char dirsep)
3659 /* level 257 SMB_ */
3660 TRANSACTION2_FFIRST_REQ *pSMB = NULL;
3661 TRANSACTION2_FFIRST_RSP *pSMBr = NULL;
3662 T2_FFIRST_RSP_PARMS *parms;
3664 int bytes_returned = 0;
3666 __u16 params, byte_count;
3668 cFYI(1, "In FindFirst for %s", searchName);
3671 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3676 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3678 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
3679 PATH_MAX, nls_codepage, remap);
3680 /* We can not add the asterik earlier in case
3681 it got remapped to 0xF03A as if it were part of the
3682 directory name instead of a wildcard */
3684 pSMB->FileName[name_len] = dirsep;
3685 pSMB->FileName[name_len+1] = 0;
3686 pSMB->FileName[name_len+2] = '*';
3687 pSMB->FileName[name_len+3] = 0;
3688 name_len += 4; /* now the trailing null */
3689 pSMB->FileName[name_len] = 0; /* null terminate just in case */
3690 pSMB->FileName[name_len+1] = 0;
3692 } else { /* BB add check for overrun of SMB buf BB */
3693 name_len = strnlen(searchName, PATH_MAX);
3694 /* BB fix here and in unicode clause above ie
3695 if (name_len > buffersize-header)
3696 free buffer exit; BB */
3697 strncpy(pSMB->FileName, searchName, name_len);
3698 pSMB->FileName[name_len] = dirsep;
3699 pSMB->FileName[name_len+1] = '*';
3700 pSMB->FileName[name_len+2] = 0;
3704 params = 12 + name_len /* includes null */ ;
3705 pSMB->TotalDataCount = 0; /* no EAs */
3706 pSMB->MaxParameterCount = cpu_to_le16(10);
3707 pSMB->MaxDataCount = cpu_to_le16((tcon->ses->server->maxBuf -
3708 MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
3709 pSMB->MaxSetupCount = 0;
3713 pSMB->Reserved2 = 0;
3714 byte_count = params + 1 /* pad */ ;
3715 pSMB->TotalParameterCount = cpu_to_le16(params);
3716 pSMB->ParameterCount = pSMB->TotalParameterCount;
3717 pSMB->ParameterOffset = cpu_to_le16(
3718 offsetof(struct smb_com_transaction2_ffirst_req, SearchAttributes)
3720 pSMB->DataCount = 0;
3721 pSMB->DataOffset = 0;
3722 pSMB->SetupCount = 1; /* one byte, no need to make endian neutral */
3723 pSMB->Reserved3 = 0;
3724 pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_FIRST);
3725 pSMB->SearchAttributes =
3726 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
3728 pSMB->SearchCount = cpu_to_le16(CIFSMaxBufSize/sizeof(FILE_UNIX_INFO));
3729 pSMB->SearchFlags = cpu_to_le16(CIFS_SEARCH_CLOSE_AT_END |
3730 CIFS_SEARCH_RETURN_RESUME);
3731 pSMB->InformationLevel = cpu_to_le16(psrch_inf->info_level);
3733 /* BB what should we set StorageType to? Does it matter? BB */
3734 pSMB->SearchStorageType = 0;
3735 pSMB->hdr.smb_buf_length += byte_count;
3736 pSMB->ByteCount = cpu_to_le16(byte_count);
3738 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3739 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3740 cifs_stats_inc(&tcon->num_ffirst);
3742 if (rc) {/* BB add logic to retry regular search if Unix search
3743 rejected unexpectedly by server */
3744 /* BB Add code to handle unsupported level rc */
3745 cFYI(1, "Error in FindFirst = %d", rc);
3747 cifs_buf_release(pSMB);
3749 /* BB eventually could optimize out free and realloc of buf */
3752 goto findFirstRetry;
3753 } else { /* decode response */
3754 /* BB remember to free buffer if error BB */
3755 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3759 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
3760 psrch_inf->unicode = true;
3762 psrch_inf->unicode = false;
3764 psrch_inf->ntwrk_buf_start = (char *)pSMBr;
3765 psrch_inf->smallBuf = 0;
3766 psrch_inf->srch_entries_start =
3767 (char *) &pSMBr->hdr.Protocol +
3768 le16_to_cpu(pSMBr->t2.DataOffset);
3769 parms = (T2_FFIRST_RSP_PARMS *)((char *) &pSMBr->hdr.Protocol +
3770 le16_to_cpu(pSMBr->t2.ParameterOffset));
3772 if (parms->EndofSearch)
3773 psrch_inf->endOfSearch = true;
3775 psrch_inf->endOfSearch = false;
3777 psrch_inf->entries_in_buffer =
3778 le16_to_cpu(parms->SearchCount);
3779 psrch_inf->index_of_last_entry = 2 /* skip . and .. */ +
3780 psrch_inf->entries_in_buffer;
3781 lnoff = le16_to_cpu(parms->LastNameOffset);
3782 if (tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE <
3784 cERROR(1, "ignoring corrupt resume name");
3785 psrch_inf->last_entry = NULL;
3789 psrch_inf->last_entry = psrch_inf->srch_entries_start +
3792 *pnetfid = parms->SearchHandle;
3794 cifs_buf_release(pSMB);
3801 int CIFSFindNext(const int xid, struct cifsTconInfo *tcon,
3802 __u16 searchHandle, struct cifs_search_info *psrch_inf)
3804 TRANSACTION2_FNEXT_REQ *pSMB = NULL;
3805 TRANSACTION2_FNEXT_RSP *pSMBr = NULL;
3806 T2_FNEXT_RSP_PARMS *parms;
3807 char *response_data;
3809 int bytes_returned, name_len;
3810 __u16 params, byte_count;
3812 cFYI(1, "In FindNext");
3814 if (psrch_inf->endOfSearch)
3817 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3822 params = 14; /* includes 2 bytes of null string, converted to LE below*/
3824 pSMB->TotalDataCount = 0; /* no EAs */
3825 pSMB->MaxParameterCount = cpu_to_le16(8);
3826 pSMB->MaxDataCount =
3827 cpu_to_le16((tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE) &
3829 pSMB->MaxSetupCount = 0;
3833 pSMB->Reserved2 = 0;
3834 pSMB->ParameterOffset = cpu_to_le16(
3835 offsetof(struct smb_com_transaction2_fnext_req,SearchHandle) - 4);
3836 pSMB->DataCount = 0;
3837 pSMB->DataOffset = 0;
3838 pSMB->SetupCount = 1;
3839 pSMB->Reserved3 = 0;
3840 pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_NEXT);
3841 pSMB->SearchHandle = searchHandle; /* always kept as le */
3843 cpu_to_le16(CIFSMaxBufSize / sizeof(FILE_UNIX_INFO));
3844 pSMB->InformationLevel = cpu_to_le16(psrch_inf->info_level);
3845 pSMB->ResumeKey = psrch_inf->resume_key;
3847 cpu_to_le16(CIFS_SEARCH_CLOSE_AT_END | CIFS_SEARCH_RETURN_RESUME);
3849 name_len = psrch_inf->resume_name_len;
3851 if (name_len < PATH_MAX) {
3852 memcpy(pSMB->ResumeFileName, psrch_inf->presume_name, name_len);
3853 byte_count += name_len;
3854 /* 14 byte parm len above enough for 2 byte null terminator */
3855 pSMB->ResumeFileName[name_len] = 0;
3856 pSMB->ResumeFileName[name_len+1] = 0;
3859 goto FNext2_err_exit;
3861 byte_count = params + 1 /* pad */ ;
3862 pSMB->TotalParameterCount = cpu_to_le16(params);
3863 pSMB->ParameterCount = pSMB->TotalParameterCount;
3864 pSMB->hdr.smb_buf_length += byte_count;
3865 pSMB->ByteCount = cpu_to_le16(byte_count);
3867 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3868 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3869 cifs_stats_inc(&tcon->num_fnext);
3872 psrch_inf->endOfSearch = true;
3873 cifs_buf_release(pSMB);
3874 rc = 0; /* search probably was closed at end of search*/
3876 cFYI(1, "FindNext returned = %d", rc);
3877 } else { /* decode response */
3878 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3883 /* BB fixme add lock for file (srch_info) struct here */
3884 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
3885 psrch_inf->unicode = true;
3887 psrch_inf->unicode = false;
3888 response_data = (char *) &pSMBr->hdr.Protocol +
3889 le16_to_cpu(pSMBr->t2.ParameterOffset);
3890 parms = (T2_FNEXT_RSP_PARMS *)response_data;
3891 response_data = (char *)&pSMBr->hdr.Protocol +
3892 le16_to_cpu(pSMBr->t2.DataOffset);
3893 if (psrch_inf->smallBuf)
3894 cifs_small_buf_release(
3895 psrch_inf->ntwrk_buf_start);
3897 cifs_buf_release(psrch_inf->ntwrk_buf_start);
3898 psrch_inf->srch_entries_start = response_data;
3899 psrch_inf->ntwrk_buf_start = (char *)pSMB;
3900 psrch_inf->smallBuf = 0;
3901 if (parms->EndofSearch)
3902 psrch_inf->endOfSearch = true;
3904 psrch_inf->endOfSearch = false;
3905 psrch_inf->entries_in_buffer =
3906 le16_to_cpu(parms->SearchCount);
3907 psrch_inf->index_of_last_entry +=
3908 psrch_inf->entries_in_buffer;
3909 lnoff = le16_to_cpu(parms->LastNameOffset);
3910 if (tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE <
3912 cERROR(1, "ignoring corrupt resume name");
3913 psrch_inf->last_entry = NULL;
3916 psrch_inf->last_entry =
3917 psrch_inf->srch_entries_start + lnoff;
3919 /* cFYI(1, "fnxt2 entries in buf %d index_of_last %d",
3920 psrch_inf->entries_in_buffer, psrch_inf->index_of_last_entry); */
3922 /* BB fixme add unlock here */
3927 /* BB On error, should we leave previous search buf (and count and
3928 last entry fields) intact or free the previous one? */
3930 /* Note: On -EAGAIN error only caller can retry on handle based calls
3931 since file handle passed in no longer valid */
3934 cifs_buf_release(pSMB);
3939 CIFSFindClose(const int xid, struct cifsTconInfo *tcon,
3940 const __u16 searchHandle)
3943 FINDCLOSE_REQ *pSMB = NULL;
3945 cFYI(1, "In CIFSSMBFindClose");
3946 rc = small_smb_init(SMB_COM_FIND_CLOSE2, 1, tcon, (void **)&pSMB);
3948 /* no sense returning error if session restarted
3949 as file handle has been closed */
3955 pSMB->FileID = searchHandle;
3956 pSMB->ByteCount = 0;
3957 rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0);
3959 cERROR(1, "Send error in FindClose = %d", rc);
3961 cifs_stats_inc(&tcon->num_fclose);
3963 /* Since session is dead, search handle closed on server already */
3971 CIFSGetSrvInodeNumber(const int xid, struct cifsTconInfo *tcon,
3972 const unsigned char *searchName,
3973 __u64 *inode_number,
3974 const struct nls_table *nls_codepage, int remap)
3977 TRANSACTION2_QPI_REQ *pSMB = NULL;
3978 TRANSACTION2_QPI_RSP *pSMBr = NULL;
3979 int name_len, bytes_returned;
3980 __u16 params, byte_count;
3982 cFYI(1, "In GetSrvInodeNum for %s", searchName);
3986 GetInodeNumberRetry:
3987 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3992 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3994 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
3995 PATH_MAX, nls_codepage, remap);
3996 name_len++; /* trailing null */
3998 } else { /* BB improve the check for buffer overruns BB */
3999 name_len = strnlen(searchName, PATH_MAX);
4000 name_len++; /* trailing null */
4001 strncpy(pSMB->FileName, searchName, name_len);
4004 params = 2 /* level */ + 4 /* rsrvd */ + name_len /* incl null */ ;
4005 pSMB->TotalDataCount = 0;
4006 pSMB->MaxParameterCount = cpu_to_le16(2);
4007 /* BB find exact max data count below from sess structure BB */
4008 pSMB->MaxDataCount = cpu_to_le16(4000);
4009 pSMB->MaxSetupCount = 0;
4013 pSMB->Reserved2 = 0;
4014 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4015 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
4016 pSMB->DataCount = 0;
4017 pSMB->DataOffset = 0;
4018 pSMB->SetupCount = 1;
4019 pSMB->Reserved3 = 0;
4020 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
4021 byte_count = params + 1 /* pad */ ;
4022 pSMB->TotalParameterCount = cpu_to_le16(params);
4023 pSMB->ParameterCount = pSMB->TotalParameterCount;
4024 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_INTERNAL_INFO);
4025 pSMB->Reserved4 = 0;
4026 pSMB->hdr.smb_buf_length += byte_count;
4027 pSMB->ByteCount = cpu_to_le16(byte_count);
4029 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4030 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4032 cFYI(1, "error %d in QueryInternalInfo", rc);
4034 /* decode response */
4035 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4036 if (rc || (pSMBr->ByteCount < 2))
4037 /* BB also check enough total bytes returned */
4038 /* If rc should we check for EOPNOSUPP and
4039 disable the srvino flag? or in caller? */
4040 rc = -EIO; /* bad smb */
4042 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4043 __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
4044 struct file_internal_info *pfinfo;
4045 /* BB Do we need a cast or hash here ? */
4047 cFYI(1, "Illegal size ret in QryIntrnlInf");
4049 goto GetInodeNumOut;
4051 pfinfo = (struct file_internal_info *)
4052 (data_offset + (char *) &pSMBr->hdr.Protocol);
4053 *inode_number = le64_to_cpu(pfinfo->UniqueId);
4057 cifs_buf_release(pSMB);
4059 goto GetInodeNumberRetry;
4063 /* parses DFS refferal V3 structure
4064 * caller is responsible for freeing target_nodes
4067 * on failure - errno
4070 parse_DFS_referrals(TRANSACTION2_GET_DFS_REFER_RSP *pSMBr,
4071 unsigned int *num_of_nodes,
4072 struct dfs_info3_param **target_nodes,
4073 const struct nls_table *nls_codepage, int remap,
4074 const char *searchName)
4079 struct dfs_referral_level_3 *ref;
4081 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
4085 *num_of_nodes = le16_to_cpu(pSMBr->NumberOfReferrals);
4087 if (*num_of_nodes < 1) {
4088 cERROR(1, "num_referrals: must be at least > 0,"
4089 "but we get num_referrals = %d\n", *num_of_nodes);
4091 goto parse_DFS_referrals_exit;
4094 ref = (struct dfs_referral_level_3 *) &(pSMBr->referrals);
4095 if (ref->VersionNumber != cpu_to_le16(3)) {
4096 cERROR(1, "Referrals of V%d version are not supported,"
4097 "should be V3", le16_to_cpu(ref->VersionNumber));
4099 goto parse_DFS_referrals_exit;
4102 /* get the upper boundary of the resp buffer */
4103 data_end = (char *)(&(pSMBr->PathConsumed)) +
4104 le16_to_cpu(pSMBr->t2.DataCount);
4106 cFYI(1, "num_referrals: %d dfs flags: 0x%x ...\n",
4108 le32_to_cpu(pSMBr->DFSFlags));
4110 *target_nodes = kzalloc(sizeof(struct dfs_info3_param) *
4111 *num_of_nodes, GFP_KERNEL);
4112 if (*target_nodes == NULL) {
4113 cERROR(1, "Failed to allocate buffer for target_nodes\n");
4115 goto parse_DFS_referrals_exit;
4118 /* collect necessary data from referrals */
4119 for (i = 0; i < *num_of_nodes; i++) {
4122 struct dfs_info3_param *node = (*target_nodes)+i;
4124 node->flags = le32_to_cpu(pSMBr->DFSFlags);
4126 __le16 *tmp = kmalloc(strlen(searchName)*2 + 2,
4130 goto parse_DFS_referrals_exit;
4132 cifsConvertToUCS((__le16 *) tmp, searchName,
4133 PATH_MAX, nls_codepage, remap);
4134 node->path_consumed = cifs_ucs2_bytes(tmp,
4135 le16_to_cpu(pSMBr->PathConsumed),
4139 node->path_consumed = le16_to_cpu(pSMBr->PathConsumed);
4141 node->server_type = le16_to_cpu(ref->ServerType);
4142 node->ref_flag = le16_to_cpu(ref->ReferralEntryFlags);
4145 temp = (char *)ref + le16_to_cpu(ref->DfsPathOffset);
4146 max_len = data_end - temp;
4147 node->path_name = cifs_strndup_from_ucs(temp, max_len,
4148 is_unicode, nls_codepage);
4149 if (!node->path_name) {
4151 goto parse_DFS_referrals_exit;
4154 /* copy link target UNC */
4155 temp = (char *)ref + le16_to_cpu(ref->NetworkAddressOffset);
4156 max_len = data_end - temp;
4157 node->node_name = cifs_strndup_from_ucs(temp, max_len,
4158 is_unicode, nls_codepage);
4159 if (!node->node_name)
4163 parse_DFS_referrals_exit:
4165 free_dfs_info_array(*target_nodes, *num_of_nodes);
4166 *target_nodes = NULL;
4173 CIFSGetDFSRefer(const int xid, struct cifsSesInfo *ses,
4174 const unsigned char *searchName,
4175 struct dfs_info3_param **target_nodes,
4176 unsigned int *num_of_nodes,
4177 const struct nls_table *nls_codepage, int remap)
4179 /* TRANS2_GET_DFS_REFERRAL */
4180 TRANSACTION2_GET_DFS_REFER_REQ *pSMB = NULL;
4181 TRANSACTION2_GET_DFS_REFER_RSP *pSMBr = NULL;
4185 __u16 params, byte_count;
4187 *target_nodes = NULL;
4189 cFYI(1, "In GetDFSRefer the path %s", searchName);
4193 rc = smb_init(SMB_COM_TRANSACTION2, 15, NULL, (void **) &pSMB,
4198 /* server pointer checked in called function,
4199 but should never be null here anyway */
4200 pSMB->hdr.Mid = GetNextMid(ses->server);
4201 pSMB->hdr.Tid = ses->ipc_tid;
4202 pSMB->hdr.Uid = ses->Suid;
4203 if (ses->capabilities & CAP_STATUS32)
4204 pSMB->hdr.Flags2 |= SMBFLG2_ERR_STATUS;
4205 if (ses->capabilities & CAP_DFS)
4206 pSMB->hdr.Flags2 |= SMBFLG2_DFS;
4208 if (ses->capabilities & CAP_UNICODE) {
4209 pSMB->hdr.Flags2 |= SMBFLG2_UNICODE;
4211 cifsConvertToUCS((__le16 *) pSMB->RequestFileName,
4212 searchName, PATH_MAX, nls_codepage, remap);
4213 name_len++; /* trailing null */
4215 } else { /* BB improve the check for buffer overruns BB */
4216 name_len = strnlen(searchName, PATH_MAX);
4217 name_len++; /* trailing null */
4218 strncpy(pSMB->RequestFileName, searchName, name_len);
4222 if (ses->server->secMode &
4223 (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
4224 pSMB->hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
4227 pSMB->hdr.Uid = ses->Suid;
4229 params = 2 /* level */ + name_len /*includes null */ ;
4230 pSMB->TotalDataCount = 0;
4231 pSMB->DataCount = 0;
4232 pSMB->DataOffset = 0;
4233 pSMB->MaxParameterCount = 0;
4234 /* BB find exact max SMB PDU from sess structure BB */
4235 pSMB->MaxDataCount = cpu_to_le16(4000);
4236 pSMB->MaxSetupCount = 0;
4240 pSMB->Reserved2 = 0;
4241 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4242 struct smb_com_transaction2_get_dfs_refer_req, MaxReferralLevel) - 4);
4243 pSMB->SetupCount = 1;
4244 pSMB->Reserved3 = 0;
4245 pSMB->SubCommand = cpu_to_le16(TRANS2_GET_DFS_REFERRAL);
4246 byte_count = params + 3 /* pad */ ;
4247 pSMB->ParameterCount = cpu_to_le16(params);
4248 pSMB->TotalParameterCount = pSMB->ParameterCount;
4249 pSMB->MaxReferralLevel = cpu_to_le16(3);
4250 pSMB->hdr.smb_buf_length += byte_count;
4251 pSMB->ByteCount = cpu_to_le16(byte_count);
4253 rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB,
4254 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4256 cFYI(1, "Send error in GetDFSRefer = %d", rc);
4259 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4261 /* BB Also check if enough total bytes returned? */
4262 if (rc || (pSMBr->ByteCount < 17)) {
4263 rc = -EIO; /* bad smb */
4267 cFYI(1, "Decoding GetDFSRefer response BCC: %d Offset %d",
4269 le16_to_cpu(pSMBr->t2.DataOffset));
4271 /* parse returned result into more usable form */
4272 rc = parse_DFS_referrals(pSMBr, num_of_nodes,
4273 target_nodes, nls_codepage, remap,
4277 cifs_buf_release(pSMB);
4285 /* Query File System Info such as free space to old servers such as Win 9x */
4287 SMBOldQFSInfo(const int xid, struct cifsTconInfo *tcon, struct kstatfs *FSData)
4289 /* level 0x01 SMB_QUERY_FILE_SYSTEM_INFO */
4290 TRANSACTION2_QFSI_REQ *pSMB = NULL;
4291 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4292 FILE_SYSTEM_ALLOC_INFO *response_data;
4294 int bytes_returned = 0;
4295 __u16 params, byte_count;
4297 cFYI(1, "OldQFSInfo");
4299 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4304 params = 2; /* level */
4305 pSMB->TotalDataCount = 0;
4306 pSMB->MaxParameterCount = cpu_to_le16(2);
4307 pSMB->MaxDataCount = cpu_to_le16(1000);
4308 pSMB->MaxSetupCount = 0;
4312 pSMB->Reserved2 = 0;
4313 byte_count = params + 1 /* pad */ ;
4314 pSMB->TotalParameterCount = cpu_to_le16(params);
4315 pSMB->ParameterCount = pSMB->TotalParameterCount;
4316 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4317 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4318 pSMB->DataCount = 0;
4319 pSMB->DataOffset = 0;
4320 pSMB->SetupCount = 1;
4321 pSMB->Reserved3 = 0;
4322 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4323 pSMB->InformationLevel = cpu_to_le16(SMB_INFO_ALLOCATION);
4324 pSMB->hdr.smb_buf_length += byte_count;
4325 pSMB->ByteCount = cpu_to_le16(byte_count);
4327 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4328 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4330 cFYI(1, "Send error in QFSInfo = %d", rc);
4331 } else { /* decode response */
4332 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4334 if (rc || (pSMBr->ByteCount < 18))
4335 rc = -EIO; /* bad smb */
4337 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4338 cFYI(1, "qfsinf resp BCC: %d Offset %d",
4339 pSMBr->ByteCount, data_offset);
4341 response_data = (FILE_SYSTEM_ALLOC_INFO *)
4342 (((char *) &pSMBr->hdr.Protocol) + data_offset);
4344 le16_to_cpu(response_data->BytesPerSector) *
4345 le32_to_cpu(response_data->
4346 SectorsPerAllocationUnit);
4348 le32_to_cpu(response_data->TotalAllocationUnits);
4349 FSData->f_bfree = FSData->f_bavail =
4350 le32_to_cpu(response_data->FreeAllocationUnits);
4351 cFYI(1, "Blocks: %lld Free: %lld Block size %ld",
4352 (unsigned long long)FSData->f_blocks,
4353 (unsigned long long)FSData->f_bfree,
4357 cifs_buf_release(pSMB);
4360 goto oldQFSInfoRetry;
4366 CIFSSMBQFSInfo(const int xid, struct cifsTconInfo *tcon, struct kstatfs *FSData)
4368 /* level 0x103 SMB_QUERY_FILE_SYSTEM_INFO */
4369 TRANSACTION2_QFSI_REQ *pSMB = NULL;
4370 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4371 FILE_SYSTEM_INFO *response_data;
4373 int bytes_returned = 0;
4374 __u16 params, byte_count;
4376 cFYI(1, "In QFSInfo");
4378 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4383 params = 2; /* level */
4384 pSMB->TotalDataCount = 0;
4385 pSMB->MaxParameterCount = cpu_to_le16(2);
4386 pSMB->MaxDataCount = cpu_to_le16(1000);
4387 pSMB->MaxSetupCount = 0;
4391 pSMB->Reserved2 = 0;
4392 byte_count = params + 1 /* pad */ ;
4393 pSMB->TotalParameterCount = cpu_to_le16(params);
4394 pSMB->ParameterCount = pSMB->TotalParameterCount;
4395 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4396 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4397 pSMB->DataCount = 0;
4398 pSMB->DataOffset = 0;
4399 pSMB->SetupCount = 1;
4400 pSMB->Reserved3 = 0;
4401 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4402 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_SIZE_INFO);
4403 pSMB->hdr.smb_buf_length += byte_count;
4404 pSMB->ByteCount = cpu_to_le16(byte_count);
4406 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4407 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4409 cFYI(1, "Send error in QFSInfo = %d", rc);
4410 } else { /* decode response */
4411 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4413 if (rc || (pSMBr->ByteCount < 24))
4414 rc = -EIO; /* bad smb */
4416 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4420 *) (((char *) &pSMBr->hdr.Protocol) +
4423 le32_to_cpu(response_data->BytesPerSector) *
4424 le32_to_cpu(response_data->
4425 SectorsPerAllocationUnit);
4427 le64_to_cpu(response_data->TotalAllocationUnits);
4428 FSData->f_bfree = FSData->f_bavail =
4429 le64_to_cpu(response_data->FreeAllocationUnits);
4430 cFYI(1, "Blocks: %lld Free: %lld Block size %ld",
4431 (unsigned long long)FSData->f_blocks,
4432 (unsigned long long)FSData->f_bfree,
4436 cifs_buf_release(pSMB);
4445 CIFSSMBQFSAttributeInfo(const int xid, struct cifsTconInfo *tcon)
4447 /* level 0x105 SMB_QUERY_FILE_SYSTEM_INFO */
4448 TRANSACTION2_QFSI_REQ *pSMB = NULL;
4449 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4450 FILE_SYSTEM_ATTRIBUTE_INFO *response_data;
4452 int bytes_returned = 0;
4453 __u16 params, byte_count;
4455 cFYI(1, "In QFSAttributeInfo");
4457 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4462 params = 2; /* level */
4463 pSMB->TotalDataCount = 0;
4464 pSMB->MaxParameterCount = cpu_to_le16(2);
4465 /* BB find exact max SMB PDU from sess structure BB */
4466 pSMB->MaxDataCount = cpu_to_le16(1000);
4467 pSMB->MaxSetupCount = 0;
4471 pSMB->Reserved2 = 0;
4472 byte_count = params + 1 /* pad */ ;
4473 pSMB->TotalParameterCount = cpu_to_le16(params);
4474 pSMB->ParameterCount = pSMB->TotalParameterCount;
4475 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4476 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4477 pSMB->DataCount = 0;
4478 pSMB->DataOffset = 0;
4479 pSMB->SetupCount = 1;
4480 pSMB->Reserved3 = 0;
4481 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4482 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_ATTRIBUTE_INFO);
4483 pSMB->hdr.smb_buf_length += byte_count;
4484 pSMB->ByteCount = cpu_to_le16(byte_count);
4486 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4487 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4489 cERROR(1, "Send error in QFSAttributeInfo = %d", rc);
4490 } else { /* decode response */
4491 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4493 if (rc || (pSMBr->ByteCount < 13)) {
4494 /* BB also check if enough bytes returned */
4495 rc = -EIO; /* bad smb */
4497 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4499 (FILE_SYSTEM_ATTRIBUTE_INFO
4500 *) (((char *) &pSMBr->hdr.Protocol) +
4502 memcpy(&tcon->fsAttrInfo, response_data,
4503 sizeof(FILE_SYSTEM_ATTRIBUTE_INFO));
4506 cifs_buf_release(pSMB);
4509 goto QFSAttributeRetry;
4515 CIFSSMBQFSDeviceInfo(const int xid, struct cifsTconInfo *tcon)
4517 /* level 0x104 SMB_QUERY_FILE_SYSTEM_INFO */
4518 TRANSACTION2_QFSI_REQ *pSMB = NULL;
4519 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4520 FILE_SYSTEM_DEVICE_INFO *response_data;
4522 int bytes_returned = 0;
4523 __u16 params, byte_count;
4525 cFYI(1, "In QFSDeviceInfo");
4527 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4532 params = 2; /* level */
4533 pSMB->TotalDataCount = 0;
4534 pSMB->MaxParameterCount = cpu_to_le16(2);
4535 /* BB find exact max SMB PDU from sess structure BB */
4536 pSMB->MaxDataCount = cpu_to_le16(1000);
4537 pSMB->MaxSetupCount = 0;
4541 pSMB->Reserved2 = 0;
4542 byte_count = params + 1 /* pad */ ;
4543 pSMB->TotalParameterCount = cpu_to_le16(params);
4544 pSMB->ParameterCount = pSMB->TotalParameterCount;
4545 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4546 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4548 pSMB->DataCount = 0;
4549 pSMB->DataOffset = 0;
4550 pSMB->SetupCount = 1;
4551 pSMB->Reserved3 = 0;
4552 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4553 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_DEVICE_INFO);
4554 pSMB->hdr.smb_buf_length += byte_count;
4555 pSMB->ByteCount = cpu_to_le16(byte_count);
4557 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4558 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4560 cFYI(1, "Send error in QFSDeviceInfo = %d", rc);
4561 } else { /* decode response */
4562 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4564 if (rc || (pSMBr->ByteCount < sizeof(FILE_SYSTEM_DEVICE_INFO)))
4565 rc = -EIO; /* bad smb */
4567 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4569 (FILE_SYSTEM_DEVICE_INFO *)
4570 (((char *) &pSMBr->hdr.Protocol) +
4572 memcpy(&tcon->fsDevInfo, response_data,
4573 sizeof(FILE_SYSTEM_DEVICE_INFO));
4576 cifs_buf_release(pSMB);
4579 goto QFSDeviceRetry;
4585 CIFSSMBQFSUnixInfo(const int xid, struct cifsTconInfo *tcon)
4587 /* level 0x200 SMB_QUERY_CIFS_UNIX_INFO */
4588 TRANSACTION2_QFSI_REQ *pSMB = NULL;
4589 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4590 FILE_SYSTEM_UNIX_INFO *response_data;
4592 int bytes_returned = 0;
4593 __u16 params, byte_count;
4595 cFYI(1, "In QFSUnixInfo");
4597 rc = smb_init_no_reconnect(SMB_COM_TRANSACTION2, 15, tcon,
4598 (void **) &pSMB, (void **) &pSMBr);
4602 params = 2; /* level */
4603 pSMB->TotalDataCount = 0;
4604 pSMB->DataCount = 0;
4605 pSMB->DataOffset = 0;
4606 pSMB->MaxParameterCount = cpu_to_le16(2);
4607 /* BB find exact max SMB PDU from sess structure BB */
4608 pSMB->MaxDataCount = cpu_to_le16(100);
4609 pSMB->MaxSetupCount = 0;
4613 pSMB->Reserved2 = 0;
4614 byte_count = params + 1 /* pad */ ;
4615 pSMB->ParameterCount = cpu_to_le16(params);
4616 pSMB->TotalParameterCount = pSMB->ParameterCount;
4617 pSMB->ParameterOffset = cpu_to_le16(offsetof(struct
4618 smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4619 pSMB->SetupCount = 1;
4620 pSMB->Reserved3 = 0;
4621 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4622 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_CIFS_UNIX_INFO);
4623 pSMB->hdr.smb_buf_length += byte_count;
4624 pSMB->ByteCount = cpu_to_le16(byte_count);
4626 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4627 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4629 cERROR(1, "Send error in QFSUnixInfo = %d", rc);
4630 } else { /* decode response */
4631 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4633 if (rc || (pSMBr->ByteCount < 13)) {
4634 rc = -EIO; /* bad smb */
4636 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4638 (FILE_SYSTEM_UNIX_INFO
4639 *) (((char *) &pSMBr->hdr.Protocol) +
4641 memcpy(&tcon->fsUnixInfo, response_data,
4642 sizeof(FILE_SYSTEM_UNIX_INFO));
4645 cifs_buf_release(pSMB);
4655 CIFSSMBSetFSUnixInfo(const int xid, struct cifsTconInfo *tcon, __u64 cap)
4657 /* level 0x200 SMB_SET_CIFS_UNIX_INFO */
4658 TRANSACTION2_SETFSI_REQ *pSMB = NULL;
4659 TRANSACTION2_SETFSI_RSP *pSMBr = NULL;
4661 int bytes_returned = 0;
4662 __u16 params, param_offset, offset, byte_count;
4664 cFYI(1, "In SETFSUnixInfo");
4666 /* BB switch to small buf init to save memory */
4667 rc = smb_init_no_reconnect(SMB_COM_TRANSACTION2, 15, tcon,
4668 (void **) &pSMB, (void **) &pSMBr);
4672 params = 4; /* 2 bytes zero followed by info level. */
4673 pSMB->MaxSetupCount = 0;
4677 pSMB->Reserved2 = 0;
4678 param_offset = offsetof(struct smb_com_transaction2_setfsi_req, FileNum)
4680 offset = param_offset + params;
4682 pSMB->MaxParameterCount = cpu_to_le16(4);
4683 /* BB find exact max SMB PDU from sess structure BB */
4684 pSMB->MaxDataCount = cpu_to_le16(100);
4685 pSMB->SetupCount = 1;
4686 pSMB->Reserved3 = 0;
4687 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FS_INFORMATION);
4688 byte_count = 1 /* pad */ + params + 12;
4690 pSMB->DataCount = cpu_to_le16(12);
4691 pSMB->ParameterCount = cpu_to_le16(params);
4692 pSMB->TotalDataCount = pSMB->DataCount;
4693 pSMB->TotalParameterCount = pSMB->ParameterCount;
4694 pSMB->ParameterOffset = cpu_to_le16(param_offset);
4695 pSMB->DataOffset = cpu_to_le16(offset);
4699 pSMB->InformationLevel = cpu_to_le16(SMB_SET_CIFS_UNIX_INFO);
4702 pSMB->ClientUnixMajor = cpu_to_le16(CIFS_UNIX_MAJOR_VERSION);
4703 pSMB->ClientUnixMinor = cpu_to_le16(CIFS_UNIX_MINOR_VERSION);
4704 pSMB->ClientUnixCap = cpu_to_le64(cap);
4706 pSMB->hdr.smb_buf_length += byte_count;
4707 pSMB->ByteCount = cpu_to_le16(byte_count);
4709 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4710 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4712 cERROR(1, "Send error in SETFSUnixInfo = %d", rc);
4713 } else { /* decode response */
4714 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4716 rc = -EIO; /* bad smb */
4718 cifs_buf_release(pSMB);
4721 goto SETFSUnixRetry;
4729 CIFSSMBQFSPosixInfo(const int xid, struct cifsTconInfo *tcon,
4730 struct kstatfs *FSData)
4732 /* level 0x201 SMB_QUERY_CIFS_POSIX_INFO */
4733 TRANSACTION2_QFSI_REQ *pSMB = NULL;
4734 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4735 FILE_SYSTEM_POSIX_INFO *response_data;
4737 int bytes_returned = 0;
4738 __u16 params, byte_count;
4740 cFYI(1, "In QFSPosixInfo");
4742 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4747 params = 2; /* level */
4748 pSMB->TotalDataCount = 0;
4749 pSMB->DataCount = 0;
4750 pSMB->DataOffset = 0;
4751 pSMB->MaxParameterCount = cpu_to_le16(2);
4752 /* BB find exact max SMB PDU from sess structure BB */
4753 pSMB->MaxDataCount = cpu_to_le16(100);
4754 pSMB->MaxSetupCount = 0;
4758 pSMB->Reserved2 = 0;
4759 byte_count = params + 1 /* pad */ ;
4760 pSMB->ParameterCount = cpu_to_le16(params);
4761 pSMB->TotalParameterCount = pSMB->ParameterCount;
4762 pSMB->ParameterOffset = cpu_to_le16(offsetof(struct
4763 smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4764 pSMB->SetupCount = 1;
4765 pSMB->Reserved3 = 0;
4766 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4767 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_POSIX_FS_INFO);
4768 pSMB->hdr.smb_buf_length += byte_count;
4769 pSMB->ByteCount = cpu_to_le16(byte_count);
4771 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4772 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4774 cFYI(1, "Send error in QFSUnixInfo = %d", rc);
4775 } else { /* decode response */
4776 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4778 if (rc || (pSMBr->ByteCount < 13)) {
4779 rc = -EIO; /* bad smb */
4781 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4783 (FILE_SYSTEM_POSIX_INFO
4784 *) (((char *) &pSMBr->hdr.Protocol) +
4787 le32_to_cpu(response_data->BlockSize);
4789 le64_to_cpu(response_data->TotalBlocks);
4791 le64_to_cpu(response_data->BlocksAvail);
4792 if (response_data->UserBlocksAvail == cpu_to_le64(-1)) {
4793 FSData->f_bavail = FSData->f_bfree;
4796 le64_to_cpu(response_data->UserBlocksAvail);
4798 if (response_data->TotalFileNodes != cpu_to_le64(-1))
4800 le64_to_cpu(response_data->TotalFileNodes);
4801 if (response_data->FreeFileNodes != cpu_to_le64(-1))
4803 le64_to_cpu(response_data->FreeFileNodes);
4806 cifs_buf_release(pSMB);
4815 /* We can not use write of zero bytes trick to
4816 set file size due to need for large file support. Also note that
4817 this SetPathInfo is preferred to SetFileInfo based method in next
4818 routine which is only needed to work around a sharing violation bug
4819 in Samba which this routine can run into */
4822 CIFSSMBSetEOF(const int xid, struct cifsTconInfo *tcon, const char *fileName,
4823 __u64 size, bool SetAllocation,
4824 const struct nls_table *nls_codepage, int remap)
4826 struct smb_com_transaction2_spi_req *pSMB = NULL;
4827 struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
4828 struct file_end_of_file_info *parm_data;
4831 int bytes_returned = 0;
4832 __u16 params, byte_count, data_count, param_offset, offset;
4834 cFYI(1, "In SetEOF");
4836 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4841 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4843 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
4844 PATH_MAX, nls_codepage, remap);
4845 name_len++; /* trailing null */
4847 } else { /* BB improve the check for buffer overruns BB */
4848 name_len = strnlen(fileName, PATH_MAX);
4849 name_len++; /* trailing null */
4850 strncpy(pSMB->FileName, fileName, name_len);
4852 params = 6 + name_len;
4853 data_count = sizeof(struct file_end_of_file_info);
4854 pSMB->MaxParameterCount = cpu_to_le16(2);
4855 pSMB->MaxDataCount = cpu_to_le16(4100);
4856 pSMB->MaxSetupCount = 0;
4860 pSMB->Reserved2 = 0;
4861 param_offset = offsetof(struct smb_com_transaction2_spi_req,
4862 InformationLevel) - 4;
4863 offset = param_offset + params;
4864 if (SetAllocation) {
4865 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
4866 pSMB->InformationLevel =
4867 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2);
4869 pSMB->InformationLevel =
4870 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO);
4871 } else /* Set File Size */ {
4872 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
4873 pSMB->InformationLevel =
4874 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO2);
4876 pSMB->InformationLevel =
4877 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO);
4881 (struct file_end_of_file_info *) (((char *) &pSMB->hdr.Protocol) +
4883 pSMB->ParameterOffset = cpu_to_le16(param_offset);
4884 pSMB->DataOffset = cpu_to_le16(offset);
4885 pSMB->SetupCount = 1;
4886 pSMB->Reserved3 = 0;
4887 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
4888 byte_count = 3 /* pad */ + params + data_count;
4889 pSMB->DataCount = cpu_to_le16(data_count);
4890 pSMB->TotalDataCount = pSMB->DataCount;
4891 pSMB->ParameterCount = cpu_to_le16(params);
4892 pSMB->TotalParameterCount = pSMB->ParameterCount;
4893 pSMB->Reserved4 = 0;
4894 pSMB->hdr.smb_buf_length += byte_count;
4895 parm_data->FileSize = cpu_to_le64(size);
4896 pSMB->ByteCount = cpu_to_le16(byte_count);
4897 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4898 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4900 cFYI(1, "SetPathInfo (file size) returned %d", rc);
4902 cifs_buf_release(pSMB);
4911 CIFSSMBSetFileSize(const int xid, struct cifsTconInfo *tcon, __u64 size,
4912 __u16 fid, __u32 pid_of_opener, bool SetAllocation)
4914 struct smb_com_transaction2_sfi_req *pSMB = NULL;
4916 struct file_end_of_file_info *parm_data;
4918 __u16 params, param_offset, offset, byte_count, count;
4920 cFYI(1, "SetFileSize (via SetFileInfo) %lld",
4922 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
4927 pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
4928 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));
4931 pSMB->MaxSetupCount = 0;
4935 pSMB->Reserved2 = 0;
4936 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
4937 offset = param_offset + params;
4939 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
4941 count = sizeof(struct file_end_of_file_info);
4942 pSMB->MaxParameterCount = cpu_to_le16(2);
4943 /* BB find exact max SMB PDU from sess structure BB */
4944 pSMB->MaxDataCount = cpu_to_le16(1000);
4945 pSMB->SetupCount = 1;
4946 pSMB->Reserved3 = 0;
4947 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
4948 byte_count = 3 /* pad */ + params + count;
4949 pSMB->DataCount = cpu_to_le16(count);
4950 pSMB->ParameterCount = cpu_to_le16(params);
4951 pSMB->TotalDataCount = pSMB->DataCount;
4952 pSMB->TotalParameterCount = pSMB->ParameterCount;
4953 pSMB->ParameterOffset = cpu_to_le16(param_offset);
4955 (struct file_end_of_file_info *) (((char *) &pSMB->hdr.Protocol)
4957 pSMB->DataOffset = cpu_to_le16(offset);
4958 parm_data->FileSize = cpu_to_le64(size);
4960 if (SetAllocation) {
4961 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
4962 pSMB->InformationLevel =
4963 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2);
4965 pSMB->InformationLevel =
4966 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO);
4967 } else /* Set File Size */ {
4968 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
4969 pSMB->InformationLevel =
4970 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO2);
4972 pSMB->InformationLevel =
4973 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO);
4975 pSMB->Reserved4 = 0;
4976 pSMB->hdr.smb_buf_length += byte_count;
4977 pSMB->ByteCount = cpu_to_le16(byte_count);
4978 rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0);
4980 cFYI(1, "Send error in SetFileInfo (SetFileSize) = %d", rc);
4983 /* Note: On -EAGAIN error only caller can retry on handle based calls
4984 since file handle passed in no longer valid */
4989 /* Some legacy servers such as NT4 require that the file times be set on
4990 an open handle, rather than by pathname - this is awkward due to
4991 potential access conflicts on the open, but it is unavoidable for these
4992 old servers since the only other choice is to go from 100 nanosecond DCE
4993 time and resort to the original setpathinfo level which takes the ancient
4994 DOS time format with 2 second granularity */
4996 CIFSSMBSetFileInfo(const int xid, struct cifsTconInfo *tcon,
4997 const FILE_BASIC_INFO *data, __u16 fid, __u32 pid_of_opener)
4999 struct smb_com_transaction2_sfi_req *pSMB = NULL;
5002 __u16 params, param_offset, offset, byte_count, count;
5004 cFYI(1, "Set Times (via SetFileInfo)");
5005 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
5010 pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
5011 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));
5014 pSMB->MaxSetupCount = 0;
5018 pSMB->Reserved2 = 0;
5019 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
5020 offset = param_offset + params;
5022 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
5024 count = sizeof(FILE_BASIC_INFO);
5025 pSMB->MaxParameterCount = cpu_to_le16(2);
5026 /* BB find max SMB PDU from sess */
5027 pSMB->MaxDataCount = cpu_to_le16(1000);
5028 pSMB->SetupCount = 1;
5029 pSMB->Reserved3 = 0;
5030 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
5031 byte_count = 3 /* pad */ + params + count;
5032 pSMB->DataCount = cpu_to_le16(count);
5033 pSMB->ParameterCount = cpu_to_le16(params);
5034 pSMB->TotalDataCount = pSMB->DataCount;
5035 pSMB->TotalParameterCount = pSMB->ParameterCount;
5036 pSMB->ParameterOffset = cpu_to_le16(param_offset);
5037 pSMB->DataOffset = cpu_to_le16(offset);
5039 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
5040 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO2);
5042 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO);
5043 pSMB->Reserved4 = 0;
5044 pSMB->hdr.smb_buf_length += byte_count;
5045 pSMB->ByteCount = cpu_to_le16(byte_count);
5046 memcpy(data_offset, data, sizeof(FILE_BASIC_INFO));
5047 rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0);
5049 cFYI(1, "Send error in Set Time (SetFileInfo) = %d", rc);
5051 /* Note: On -EAGAIN error only caller can retry on handle based calls
5052 since file handle passed in no longer valid */
5058 CIFSSMBSetFileDisposition(const int xid, struct cifsTconInfo *tcon,
5059 bool delete_file, __u16 fid, __u32 pid_of_opener)
5061 struct smb_com_transaction2_sfi_req *pSMB = NULL;
5064 __u16 params, param_offset, offset, byte_count, count;
5066 cFYI(1, "Set File Disposition (via SetFileInfo)");
5067 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
5072 pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
5073 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));
5076 pSMB->MaxSetupCount = 0;
5080 pSMB->Reserved2 = 0;
5081 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
5082 offset = param_offset + params;
5084 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
5087 pSMB->MaxParameterCount = cpu_to_le16(2);
5088 /* BB find max SMB PDU from sess */
5089 pSMB->MaxDataCount = cpu_to_le16(1000);
5090 pSMB->SetupCount = 1;
5091 pSMB->Reserved3 = 0;
5092 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
5093 byte_count = 3 /* pad */ + params + count;
5094 pSMB->DataCount = cpu_to_le16(count);
5095 pSMB->ParameterCount = cpu_to_le16(params);
5096 pSMB->TotalDataCount = pSMB->DataCount;
5097 pSMB->TotalParameterCount = pSMB->ParameterCount;
5098 pSMB->ParameterOffset = cpu_to_le16(param_offset);
5099 pSMB->DataOffset = cpu_to_le16(offset);
5101 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_DISPOSITION_INFO);
5102 pSMB->Reserved4 = 0;
5103 pSMB->hdr.smb_buf_length += byte_count;
5104 pSMB->ByteCount = cpu_to_le16(byte_count);
5105 *data_offset = delete_file ? 1 : 0;
5106 rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0);
5108 cFYI(1, "Send error in SetFileDisposition = %d", rc);
5114 CIFSSMBSetPathInfo(const int xid, struct cifsTconInfo *tcon,
5115 const char *fileName, const FILE_BASIC_INFO *data,
5116 const struct nls_table *nls_codepage, int remap)
5118 TRANSACTION2_SPI_REQ *pSMB = NULL;
5119 TRANSACTION2_SPI_RSP *pSMBr = NULL;
5122 int bytes_returned = 0;
5124 __u16 params, param_offset, offset, byte_count, count;
5126 cFYI(1, "In SetTimes");
5129 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5134 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5136 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
5137 PATH_MAX, nls_codepage, remap);
5138 name_len++; /* trailing null */
5140 } else { /* BB improve the check for buffer overruns BB */
5141 name_len = strnlen(fileName, PATH_MAX);
5142 name_len++; /* trailing null */
5143 strncpy(pSMB->FileName, fileName, name_len);
5146 params = 6 + name_len;
5147 count = sizeof(FILE_BASIC_INFO);
5148 pSMB->MaxParameterCount = cpu_to_le16(2);
5149 /* BB find max SMB PDU from sess structure BB */
5150 pSMB->MaxDataCount = cpu_to_le16(1000);
5151 pSMB->MaxSetupCount = 0;
5155 pSMB->Reserved2 = 0;
5156 param_offset = offsetof(struct smb_com_transaction2_spi_req,
5157 InformationLevel) - 4;
5158 offset = param_offset + params;
5159 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
5160 pSMB->ParameterOffset = cpu_to_le16(param_offset);
5161 pSMB->DataOffset = cpu_to_le16(offset);
5162 pSMB->SetupCount = 1;
5163 pSMB->Reserved3 = 0;
5164 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
5165 byte_count = 3 /* pad */ + params + count;
5167 pSMB->DataCount = cpu_to_le16(count);
5168 pSMB->ParameterCount = cpu_to_le16(params);
5169 pSMB->TotalDataCount = pSMB->DataCount;
5170 pSMB->TotalParameterCount = pSMB->ParameterCount;
5171 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
5172 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO2);
5174 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO);
5175 pSMB->Reserved4 = 0;
5176 pSMB->hdr.smb_buf_length += byte_count;
5177 memcpy(data_offset, data, sizeof(FILE_BASIC_INFO));
5178 pSMB->ByteCount = cpu_to_le16(byte_count);
5179 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5180 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5182 cFYI(1, "SetPathInfo (times) returned %d", rc);
5184 cifs_buf_release(pSMB);
5192 /* Can not be used to set time stamps yet (due to old DOS time format) */
5193 /* Can be used to set attributes */
5194 #if 0 /* Possibly not needed - since it turns out that strangely NT4 has a bug
5195 handling it anyway and NT4 was what we thought it would be needed for
5196 Do not delete it until we prove whether needed for Win9x though */
5198 CIFSSMBSetAttrLegacy(int xid, struct cifsTconInfo *tcon, char *fileName,
5199 __u16 dos_attrs, const struct nls_table *nls_codepage)
5201 SETATTR_REQ *pSMB = NULL;
5202 SETATTR_RSP *pSMBr = NULL;
5207 cFYI(1, "In SetAttrLegacy");
5210 rc = smb_init(SMB_COM_SETATTR, 8, tcon, (void **) &pSMB,
5215 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5217 ConvertToUCS((__le16 *) pSMB->fileName, fileName,
5218 PATH_MAX, nls_codepage);
5219 name_len++; /* trailing null */
5221 } else { /* BB improve the check for buffer overruns BB */
5222 name_len = strnlen(fileName, PATH_MAX);
5223 name_len++; /* trailing null */
5224 strncpy(pSMB->fileName, fileName, name_len);
5226 pSMB->attr = cpu_to_le16(dos_attrs);
5227 pSMB->BufferFormat = 0x04;
5228 pSMB->hdr.smb_buf_length += name_len + 1;
5229 pSMB->ByteCount = cpu_to_le16(name_len + 1);
5230 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5231 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5233 cFYI(1, "Error in LegacySetAttr = %d", rc);
5235 cifs_buf_release(pSMB);
5238 goto SetAttrLgcyRetry;
5242 #endif /* temporarily unneeded SetAttr legacy function */
5245 cifs_fill_unix_set_info(FILE_UNIX_BASIC_INFO *data_offset,
5246 const struct cifs_unix_set_info_args *args)
5248 u64 mode = args->mode;
5251 * Samba server ignores set of file size to zero due to bugs in some
5252 * older clients, but we should be precise - we use SetFileSize to
5253 * set file size and do not want to truncate file size to zero
5254 * accidently as happened on one Samba server beta by putting
5255 * zero instead of -1 here
5257 data_offset->EndOfFile = cpu_to_le64(NO_CHANGE_64);
5258 data_offset->NumOfBytes = cpu_to_le64(NO_CHANGE_64);
5259 data_offset->LastStatusChange = cpu_to_le64(args->ctime);
5260 data_offset->LastAccessTime = cpu_to_le64(args->atime);
5261 data_offset->LastModificationTime = cpu_to_le64(args->mtime);
5262 data_offset->Uid = cpu_to_le64(args->uid);
5263 data_offset->Gid = cpu_to_le64(args->gid);
5264 /* better to leave device as zero when it is */
5265 data_offset->DevMajor = cpu_to_le64(MAJOR(args->device));
5266 data_offset->DevMinor = cpu_to_le64(MINOR(args->device));
5267 data_offset->Permissions = cpu_to_le64(mode);
5270 data_offset->Type = cpu_to_le32(UNIX_FILE);
5271 else if (S_ISDIR(mode))
5272 data_offset->Type = cpu_to_le32(UNIX_DIR);
5273 else if (S_ISLNK(mode))
5274 data_offset->Type = cpu_to_le32(UNIX_SYMLINK);
5275 else if (S_ISCHR(mode))
5276 data_offset->Type = cpu_to_le32(UNIX_CHARDEV);
5277 else if (S_ISBLK(mode))
5278 data_offset->Type = cpu_to_le32(UNIX_BLOCKDEV);
5279 else if (S_ISFIFO(mode))
5280 data_offset->Type = cpu_to_le32(UNIX_FIFO);
5281 else if (S_ISSOCK(mode))
5282 data_offset->Type = cpu_to_le32(UNIX_SOCKET);
5286 CIFSSMBUnixSetFileInfo(const int xid, struct cifsTconInfo *tcon,
5287 const struct cifs_unix_set_info_args *args,
5288 u16 fid, u32 pid_of_opener)
5290 struct smb_com_transaction2_sfi_req *pSMB = NULL;
5291 FILE_UNIX_BASIC_INFO *data_offset;
5293 u16 params, param_offset, offset, byte_count, count;
5295 cFYI(1, "Set Unix Info (via SetFileInfo)");
5296 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
5301 pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
5302 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));
5305 pSMB->MaxSetupCount = 0;
5309 pSMB->Reserved2 = 0;
5310 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
5311 offset = param_offset + params;
5313 data_offset = (FILE_UNIX_BASIC_INFO *)
5314 ((char *)(&pSMB->hdr.Protocol) + offset);
5315 count = sizeof(FILE_UNIX_BASIC_INFO);
5317 pSMB->MaxParameterCount = cpu_to_le16(2);
5318 /* BB find max SMB PDU from sess */
5319 pSMB->MaxDataCount = cpu_to_le16(1000);
5320 pSMB->SetupCount = 1;
5321 pSMB->Reserved3 = 0;
5322 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
5323 byte_count = 3 /* pad */ + params + count;
5324 pSMB->DataCount = cpu_to_le16(count);
5325 pSMB->ParameterCount = cpu_to_le16(params);
5326 pSMB->TotalDataCount = pSMB->DataCount;
5327 pSMB->TotalParameterCount = pSMB->ParameterCount;
5328 pSMB->ParameterOffset = cpu_to_le16(param_offset);
5329 pSMB->DataOffset = cpu_to_le16(offset);
5331 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_BASIC);
5332 pSMB->Reserved4 = 0;
5333 pSMB->hdr.smb_buf_length += byte_count;
5334 pSMB->ByteCount = cpu_to_le16(byte_count);
5336 cifs_fill_unix_set_info(data_offset, args);
5338 rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0);
5340 cFYI(1, "Send error in Set Time (SetFileInfo) = %d", rc);
5342 /* Note: On -EAGAIN error only caller can retry on handle based calls
5343 since file handle passed in no longer valid */
5349 CIFSSMBUnixSetPathInfo(const int xid, struct cifsTconInfo *tcon, char *fileName,
5350 const struct cifs_unix_set_info_args *args,
5351 const struct nls_table *nls_codepage, int remap)
5353 TRANSACTION2_SPI_REQ *pSMB = NULL;
5354 TRANSACTION2_SPI_RSP *pSMBr = NULL;
5357 int bytes_returned = 0;
5358 FILE_UNIX_BASIC_INFO *data_offset;
5359 __u16 params, param_offset, offset, count, byte_count;
5361 cFYI(1, "In SetUID/GID/Mode");
5363 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5368 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5370 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
5371 PATH_MAX, nls_codepage, remap);
5372 name_len++; /* trailing null */
5374 } else { /* BB improve the check for buffer overruns BB */
5375 name_len = strnlen(fileName, PATH_MAX);
5376 name_len++; /* trailing null */
5377 strncpy(pSMB->FileName, fileName, name_len);
5380 params = 6 + name_len;
5381 count = sizeof(FILE_UNIX_BASIC_INFO);
5382 pSMB->MaxParameterCount = cpu_to_le16(2);
5383 /* BB find max SMB PDU from sess structure BB */
5384 pSMB->MaxDataCount = cpu_to_le16(1000);
5385 pSMB->MaxSetupCount = 0;
5389 pSMB->Reserved2 = 0;
5390 param_offset = offsetof(struct smb_com_transaction2_spi_req,
5391 InformationLevel) - 4;
5392 offset = param_offset + params;
5394 (FILE_UNIX_BASIC_INFO *) ((char *) &pSMB->hdr.Protocol +
5396 memset(data_offset, 0, count);
5397 pSMB->DataOffset = cpu_to_le16(offset);
5398 pSMB->ParameterOffset = cpu_to_le16(param_offset);
5399 pSMB->SetupCount = 1;
5400 pSMB->Reserved3 = 0;
5401 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
5402 byte_count = 3 /* pad */ + params + count;
5403 pSMB->ParameterCount = cpu_to_le16(params);
5404 pSMB->DataCount = cpu_to_le16(count);
5405 pSMB->TotalParameterCount = pSMB->ParameterCount;
5406 pSMB->TotalDataCount = pSMB->DataCount;
5407 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_BASIC);
5408 pSMB->Reserved4 = 0;
5409 pSMB->hdr.smb_buf_length += byte_count;
5411 cifs_fill_unix_set_info(data_offset, args);
5413 pSMB->ByteCount = cpu_to_le16(byte_count);
5414 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5415 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5417 cFYI(1, "SetPathInfo (perms) returned %d", rc);
5419 cifs_buf_release(pSMB);
5425 int CIFSSMBNotify(const int xid, struct cifsTconInfo *tcon,
5426 const int notify_subdirs, const __u16 netfid,
5427 __u32 filter, struct file *pfile, int multishot,
5428 const struct nls_table *nls_codepage)
5431 struct smb_com_transaction_change_notify_req *pSMB = NULL;
5432 struct smb_com_ntransaction_change_notify_rsp *pSMBr = NULL;
5433 struct dir_notify_req *dnotify_req;
5436 cFYI(1, "In CIFSSMBNotify for file handle %d", (int)netfid);
5437 rc = smb_init(SMB_COM_NT_TRANSACT, 23, tcon, (void **) &pSMB,
5442 pSMB->TotalParameterCount = 0 ;
5443 pSMB->TotalDataCount = 0;
5444 pSMB->MaxParameterCount = cpu_to_le32(2);
5445 /* BB find exact data count max from sess structure BB */
5446 pSMB->MaxDataCount = 0; /* same in little endian or be */
5447 /* BB VERIFY verify which is correct for above BB */
5448 pSMB->MaxDataCount = cpu_to_le32((tcon->ses->server->maxBuf -
5449 MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
5451 pSMB->MaxSetupCount = 4;
5453 pSMB->ParameterOffset = 0;
5454 pSMB->DataCount = 0;
5455 pSMB->DataOffset = 0;
5456 pSMB->SetupCount = 4; /* single byte does not need le conversion */
5457 pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_NOTIFY_CHANGE);
5458 pSMB->ParameterCount = pSMB->TotalParameterCount;
5460 pSMB->WatchTree = 1; /* one byte - no le conversion needed */
5461 pSMB->Reserved2 = 0;
5462 pSMB->CompletionFilter = cpu_to_le32(filter);
5463 pSMB->Fid = netfid; /* file handle always le */
5464 pSMB->ByteCount = 0;
5466 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5467 (struct smb_hdr *)pSMBr, &bytes_returned,
5470 cFYI(1, "Error in Notify = %d", rc);
5472 /* Add file to outstanding requests */
5473 /* BB change to kmem cache alloc */
5474 dnotify_req = kmalloc(
5475 sizeof(struct dir_notify_req),
5478 dnotify_req->Pid = pSMB->hdr.Pid;
5479 dnotify_req->PidHigh = pSMB->hdr.PidHigh;
5480 dnotify_req->Mid = pSMB->hdr.Mid;
5481 dnotify_req->Tid = pSMB->hdr.Tid;
5482 dnotify_req->Uid = pSMB->hdr.Uid;
5483 dnotify_req->netfid = netfid;
5484 dnotify_req->pfile = pfile;
5485 dnotify_req->filter = filter;
5486 dnotify_req->multishot = multishot;
5487 spin_lock(&GlobalMid_Lock);
5488 list_add_tail(&dnotify_req->lhead,
5489 &GlobalDnotifyReqList);
5490 spin_unlock(&GlobalMid_Lock);
5494 cifs_buf_release(pSMB);
5498 #ifdef CONFIG_CIFS_XATTR
5500 * Do a path-based QUERY_ALL_EAS call and parse the result. This is a common
5501 * function used by listxattr and getxattr type calls. When ea_name is set,
5502 * it looks for that attribute name and stuffs that value into the EAData
5503 * buffer. When ea_name is NULL, it stuffs a list of attribute names into the
5504 * buffer. In both cases, the return value is either the length of the
5505 * resulting data or a negative error code. If EAData is a NULL pointer then
5506 * the data isn't copied to it, but the length is returned.
5509 CIFSSMBQAllEAs(const int xid, struct cifsTconInfo *tcon,
5510 const unsigned char *searchName, const unsigned char *ea_name,
5511 char *EAData, size_t buf_size,
5512 const struct nls_table *nls_codepage, int remap)
5514 /* BB assumes one setup word */
5515 TRANSACTION2_QPI_REQ *pSMB = NULL;
5516 TRANSACTION2_QPI_RSP *pSMBr = NULL;
5520 struct fealist *ea_response_data;
5521 struct fea *temp_fea;
5524 __u16 params, byte_count, data_offset;
5526 cFYI(1, "In Query All EAs path %s", searchName);
5528 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5533 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5535 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
5536 PATH_MAX, nls_codepage, remap);
5537 list_len++; /* trailing null */
5539 } else { /* BB improve the check for buffer overruns BB */
5540 list_len = strnlen(searchName, PATH_MAX);
5541 list_len++; /* trailing null */
5542 strncpy(pSMB->FileName, searchName, list_len);
5545 params = 2 /* level */ + 4 /* reserved */ + list_len /* includes NUL */;
5546 pSMB->TotalDataCount = 0;
5547 pSMB->MaxParameterCount = cpu_to_le16(2);
5548 /* BB find exact max SMB PDU from sess structure BB */
5549 pSMB->MaxDataCount = cpu_to_le16(CIFSMaxBufSize);
5550 pSMB->MaxSetupCount = 0;
5554 pSMB->Reserved2 = 0;
5555 pSMB->ParameterOffset = cpu_to_le16(offsetof(
5556 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
5557 pSMB->DataCount = 0;
5558 pSMB->DataOffset = 0;
5559 pSMB->SetupCount = 1;
5560 pSMB->Reserved3 = 0;
5561 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
5562 byte_count = params + 1 /* pad */ ;
5563 pSMB->TotalParameterCount = cpu_to_le16(params);
5564 pSMB->ParameterCount = pSMB->TotalParameterCount;
5565 pSMB->InformationLevel = cpu_to_le16(SMB_INFO_QUERY_ALL_EAS);
5566 pSMB->Reserved4 = 0;
5567 pSMB->hdr.smb_buf_length += byte_count;
5568 pSMB->ByteCount = cpu_to_le16(byte_count);
5570 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5571 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5573 cFYI(1, "Send error in QueryAllEAs = %d", rc);
5578 /* BB also check enough total bytes returned */
5579 /* BB we need to improve the validity checking
5580 of these trans2 responses */
5582 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
5583 if (rc || (pSMBr->ByteCount < 4)) {
5584 rc = -EIO; /* bad smb */
5588 /* check that length of list is not more than bcc */
5589 /* check that each entry does not go beyond length
5591 /* check that each element of each entry does not
5592 go beyond end of list */
5593 /* validate_trans2_offsets() */
5594 /* BB check if start of smb + data_offset > &bcc+ bcc */
5596 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
5597 ea_response_data = (struct fealist *)
5598 (((char *) &pSMBr->hdr.Protocol) + data_offset);
5600 list_len = le32_to_cpu(ea_response_data->list_len);
5601 cFYI(1, "ea length %d", list_len);
5602 if (list_len <= 8) {
5603 cFYI(1, "empty EA list returned from server");
5607 /* make sure list_len doesn't go past end of SMB */
5608 end_of_smb = (char *)pByteArea(&pSMBr->hdr) + get_bcc(&pSMBr->hdr);
5609 if ((char *)ea_response_data + list_len > end_of_smb) {
5610 cFYI(1, "EA list appears to go beyond SMB");
5615 /* account for ea list len */
5617 temp_fea = ea_response_data->list;
5618 temp_ptr = (char *)temp_fea;
5619 while (list_len > 0) {
5620 unsigned int name_len;
5625 /* make sure we can read name_len and value_len */
5627 cFYI(1, "EA entry goes beyond length of list");
5632 name_len = temp_fea->name_len;
5633 value_len = le16_to_cpu(temp_fea->value_len);
5634 list_len -= name_len + 1 + value_len;
5636 cFYI(1, "EA entry goes beyond length of list");
5642 if (strncmp(ea_name, temp_ptr, name_len) == 0) {
5643 temp_ptr += name_len + 1;
5647 if ((size_t)value_len > buf_size) {
5651 memcpy(EAData, temp_ptr, value_len);
5655 /* account for prefix user. and trailing null */
5656 rc += (5 + 1 + name_len);
5657 if (rc < (int) buf_size) {
5658 memcpy(EAData, "user.", 5);
5660 memcpy(EAData, temp_ptr, name_len);
5662 /* null terminate name */
5665 } else if (buf_size == 0) {
5666 /* skip copy - calc size only */
5668 /* stop before overrun buffer */
5673 temp_ptr += name_len + 1 + value_len;
5674 temp_fea = (struct fea *)temp_ptr;
5677 /* didn't find the named attribute */
5682 cifs_buf_release(pSMB);
5690 CIFSSMBSetEA(const int xid, struct cifsTconInfo *tcon, const char *fileName,
5691 const char *ea_name, const void *ea_value,
5692 const __u16 ea_value_len, const struct nls_table *nls_codepage,
5695 struct smb_com_transaction2_spi_req *pSMB = NULL;
5696 struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
5697 struct fealist *parm_data;
5700 int bytes_returned = 0;
5701 __u16 params, param_offset, byte_count, offset, count;
5703 cFYI(1, "In SetEA");
5705 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5710 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5712 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
5713 PATH_MAX, nls_codepage, remap);
5714 name_len++; /* trailing null */
5716 } else { /* BB improve the check for buffer overruns BB */
5717 name_len = strnlen(fileName, PATH_MAX);
5718 name_len++; /* trailing null */
5719 strncpy(pSMB->FileName, fileName, name_len);
5722 params = 6 + name_len;
5724 /* done calculating parms using name_len of file name,
5725 now use name_len to calculate length of ea name
5726 we are going to create in the inode xattrs */
5727 if (ea_name == NULL)
5730 name_len = strnlen(ea_name, 255);
5732 count = sizeof(*parm_data) + ea_value_len + name_len;
5733 pSMB->MaxParameterCount = cpu_to_le16(2);
5734 /* BB find max SMB PDU from sess */
5735 pSMB->MaxDataCount = cpu_to_le16(1000);
5736 pSMB->MaxSetupCount = 0;
5740 pSMB->Reserved2 = 0;
5741 param_offset = offsetof(struct smb_com_transaction2_spi_req,
5742 InformationLevel) - 4;
5743 offset = param_offset + params;
5744 pSMB->InformationLevel =
5745 cpu_to_le16(SMB_SET_FILE_EA);
5748 (struct fealist *) (((char *) &pSMB->hdr.Protocol) +
5750 pSMB->ParameterOffset = cpu_to_le16(param_offset);
5751 pSMB->DataOffset = cpu_to_le16(offset);
5752 pSMB->SetupCount = 1;
5753 pSMB->Reserved3 = 0;
5754 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
5755 byte_count = 3 /* pad */ + params + count;
5756 pSMB->DataCount = cpu_to_le16(count);
5757 parm_data->list_len = cpu_to_le32(count);
5758 parm_data->list[0].EA_flags = 0;
5759 /* we checked above that name len is less than 255 */
5760 parm_data->list[0].name_len = (__u8)name_len;
5761 /* EA names are always ASCII */
5763 strncpy(parm_data->list[0].name, ea_name, name_len);
5764 parm_data->list[0].name[name_len] = 0;
5765 parm_data->list[0].value_len = cpu_to_le16(ea_value_len);
5766 /* caller ensures that ea_value_len is less than 64K but
5767 we need to ensure that it fits within the smb */
5769 /*BB add length check to see if it would fit in
5770 negotiated SMB buffer size BB */
5771 /* if (ea_value_len > buffer_size - 512 (enough for header)) */
5773 memcpy(parm_data->list[0].name+name_len+1,
5774 ea_value, ea_value_len);
5776 pSMB->TotalDataCount = pSMB->DataCount;
5777 pSMB->ParameterCount = cpu_to_le16(params);
5778 pSMB->TotalParameterCount = pSMB->ParameterCount;
5779 pSMB->Reserved4 = 0;
5780 pSMB->hdr.smb_buf_length += byte_count;
5781 pSMB->ByteCount = cpu_to_le16(byte_count);
5782 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5783 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5785 cFYI(1, "SetPathInfo (EA) returned %d", rc);
5787 cifs_buf_release(pSMB);