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)
338 /* check for plausible wct, bcc and t2 data and parm sizes */
339 /* check for parm and data offset going beyond end of smb */
340 if (pSMB->hdr.WordCount >= 10) {
341 if ((le16_to_cpu(pSMB->t2_rsp.ParameterOffset) <= 1024) &&
342 (le16_to_cpu(pSMB->t2_rsp.DataOffset) <= 1024)) {
343 /* check that bcc is at least as big as parms + data */
344 /* check that bcc is less than negotiated smb buffer */
345 total_size = le16_to_cpu(pSMB->t2_rsp.ParameterCount);
346 if (total_size < 512) {
348 le16_to_cpu(pSMB->t2_rsp.DataCount);
349 /* BCC le converted in SendReceive */
350 pBCC = (pSMB->hdr.WordCount * 2) +
351 sizeof(struct smb_hdr) +
353 if ((total_size <= (*(u16 *)pBCC)) &&
355 CIFSMaxBufSize+MAX_CIFS_HDR_SIZE)) {
361 cifs_dump_mem("Invalid transact2 SMB: ", (char *)pSMB,
362 sizeof(struct smb_t2_rsp) + 16);
366 CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses)
369 NEGOTIATE_RSP *pSMBr;
373 struct TCP_Server_Info *server;
375 unsigned int secFlags;
378 server = ses->server;
383 rc = smb_init(SMB_COM_NEGOTIATE, 0, NULL /* no tcon yet */ ,
384 (void **) &pSMB, (void **) &pSMBr);
388 /* if any of auth flags (ie not sign or seal) are overriden use them */
389 if (ses->overrideSecFlg & (~(CIFSSEC_MUST_SIGN | CIFSSEC_MUST_SEAL)))
390 secFlags = ses->overrideSecFlg; /* BB FIXME fix sign flags? */
391 else /* if override flags set only sign/seal OR them with global auth */
392 secFlags = global_secflags | ses->overrideSecFlg;
394 cFYI(1, "secFlags 0x%x", secFlags);
396 pSMB->hdr.Mid = GetNextMid(server);
397 pSMB->hdr.Flags2 |= (SMBFLG2_UNICODE | SMBFLG2_ERR_STATUS);
399 if ((secFlags & CIFSSEC_MUST_KRB5) == CIFSSEC_MUST_KRB5)
400 pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC;
401 else if ((secFlags & CIFSSEC_AUTH_MASK) == CIFSSEC_MAY_KRB5) {
402 cFYI(1, "Kerberos only mechanism, enable extended security");
403 pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC;
404 } else if ((secFlags & CIFSSEC_MUST_NTLMSSP) == CIFSSEC_MUST_NTLMSSP)
405 pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC;
406 else if ((secFlags & CIFSSEC_AUTH_MASK) == CIFSSEC_MAY_NTLMSSP) {
407 cFYI(1, "NTLMSSP only mechanism, enable extended security");
408 pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC;
412 for (i = 0; i < CIFS_NUM_PROT; i++) {
413 strncpy(pSMB->DialectsArray+count, protocols[i].name, 16);
414 count += strlen(protocols[i].name) + 1;
415 /* null at end of source and target buffers anyway */
417 pSMB->hdr.smb_buf_length += count;
418 pSMB->ByteCount = cpu_to_le16(count);
420 rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB,
421 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
425 server->dialect = le16_to_cpu(pSMBr->DialectIndex);
426 cFYI(1, "Dialect: %d", server->dialect);
427 /* Check wct = 1 error case */
428 if ((pSMBr->hdr.WordCount < 13) || (server->dialect == BAD_PROT)) {
429 /* core returns wct = 1, but we do not ask for core - otherwise
430 small wct just comes when dialect index is -1 indicating we
431 could not negotiate a common dialect */
434 #ifdef CONFIG_CIFS_WEAK_PW_HASH
435 } else if ((pSMBr->hdr.WordCount == 13)
436 && ((server->dialect == LANMAN_PROT)
437 || (server->dialect == LANMAN2_PROT))) {
439 struct lanman_neg_rsp *rsp = (struct lanman_neg_rsp *)pSMBr;
441 if ((secFlags & CIFSSEC_MAY_LANMAN) ||
442 (secFlags & CIFSSEC_MAY_PLNTXT))
443 server->secType = LANMAN;
445 cERROR(1, "mount failed weak security disabled"
446 " in /proc/fs/cifs/SecurityFlags");
450 server->secMode = (__u8)le16_to_cpu(rsp->SecurityMode);
451 server->maxReq = le16_to_cpu(rsp->MaxMpxCount);
452 server->maxBuf = min((__u32)le16_to_cpu(rsp->MaxBufSize),
453 (__u32)CIFSMaxBufSize + MAX_CIFS_HDR_SIZE);
454 server->max_vcs = le16_to_cpu(rsp->MaxNumberVcs);
455 GETU32(server->sessid) = le32_to_cpu(rsp->SessionKey);
456 /* even though we do not use raw we might as well set this
457 accurately, in case we ever find a need for it */
458 if ((le16_to_cpu(rsp->RawMode) & RAW_ENABLE) == RAW_ENABLE) {
459 server->max_rw = 0xFF00;
460 server->capabilities = CAP_MPX_MODE | CAP_RAW_MODE;
462 server->max_rw = 0;/* do not need to use raw anyway */
463 server->capabilities = CAP_MPX_MODE;
465 tmp = (__s16)le16_to_cpu(rsp->ServerTimeZone);
467 /* OS/2 often does not set timezone therefore
468 * we must use server time to calc time zone.
469 * Could deviate slightly from the right zone.
470 * Smallest defined timezone difference is 15 minutes
471 * (i.e. Nepal). Rounding up/down is done to match
474 int val, seconds, remain, result;
475 struct timespec ts, utc;
477 ts = cnvrtDosUnixTm(rsp->SrvTime.Date,
478 rsp->SrvTime.Time, 0);
479 cFYI(1, "SrvTime %d sec since 1970 (utc: %d) diff: %d",
480 (int)ts.tv_sec, (int)utc.tv_sec,
481 (int)(utc.tv_sec - ts.tv_sec));
482 val = (int)(utc.tv_sec - ts.tv_sec);
484 result = (seconds / MIN_TZ_ADJ) * MIN_TZ_ADJ;
485 remain = seconds % MIN_TZ_ADJ;
486 if (remain >= (MIN_TZ_ADJ / 2))
487 result += MIN_TZ_ADJ;
490 server->timeAdj = result;
492 server->timeAdj = (int)tmp;
493 server->timeAdj *= 60; /* also in seconds */
495 cFYI(1, "server->timeAdj: %d seconds", server->timeAdj);
498 /* BB get server time for time conversions and add
499 code to use it and timezone since this is not UTC */
501 if (rsp->EncryptionKeyLength ==
502 cpu_to_le16(CIFS_CRYPTO_KEY_SIZE)) {
503 memcpy(ses->server->cryptkey, rsp->EncryptionKey,
504 CIFS_CRYPTO_KEY_SIZE);
505 } else if (server->secMode & SECMODE_PW_ENCRYPT) {
506 rc = -EIO; /* need cryptkey unless plain text */
510 cFYI(1, "LANMAN negotiated");
511 /* we will not end up setting signing flags - as no signing
512 was in LANMAN and server did not return the flags on */
514 #else /* weak security disabled */
515 } else if (pSMBr->hdr.WordCount == 13) {
516 cERROR(1, "mount failed, cifs module not built "
517 "with CIFS_WEAK_PW_HASH support");
519 #endif /* WEAK_PW_HASH */
521 } else if (pSMBr->hdr.WordCount != 17) {
526 /* else wct == 17 NTLM */
527 server->secMode = pSMBr->SecurityMode;
528 if ((server->secMode & SECMODE_USER) == 0)
529 cFYI(1, "share mode security");
531 if ((server->secMode & SECMODE_PW_ENCRYPT) == 0)
532 #ifdef CONFIG_CIFS_WEAK_PW_HASH
533 if ((secFlags & CIFSSEC_MAY_PLNTXT) == 0)
534 #endif /* CIFS_WEAK_PW_HASH */
535 cERROR(1, "Server requests plain text password"
536 " but client support disabled");
538 if ((secFlags & CIFSSEC_MUST_NTLMV2) == CIFSSEC_MUST_NTLMV2)
539 server->secType = NTLMv2;
540 else if (secFlags & CIFSSEC_MAY_NTLM)
541 server->secType = NTLM;
542 else if (secFlags & CIFSSEC_MAY_NTLMV2)
543 server->secType = NTLMv2;
544 else if (secFlags & CIFSSEC_MAY_KRB5)
545 server->secType = Kerberos;
546 else if (secFlags & CIFSSEC_MAY_NTLMSSP)
547 server->secType = RawNTLMSSP;
548 else if (secFlags & CIFSSEC_MAY_LANMAN)
549 server->secType = LANMAN;
550 /* #ifdef CONFIG_CIFS_EXPERIMENTAL
551 else if (secFlags & CIFSSEC_MAY_PLNTXT)
556 cERROR(1, "Invalid security type");
559 /* else ... any others ...? */
561 /* one byte, so no need to convert this or EncryptionKeyLen from
563 server->maxReq = le16_to_cpu(pSMBr->MaxMpxCount);
564 /* probably no need to store and check maxvcs */
565 server->maxBuf = min(le32_to_cpu(pSMBr->MaxBufferSize),
566 (__u32) CIFSMaxBufSize + MAX_CIFS_HDR_SIZE);
567 server->max_rw = le32_to_cpu(pSMBr->MaxRawSize);
568 cFYI(DBG2, "Max buf = %d", ses->server->maxBuf);
569 GETU32(ses->server->sessid) = le32_to_cpu(pSMBr->SessionKey);
570 server->capabilities = le32_to_cpu(pSMBr->Capabilities);
571 server->timeAdj = (int)(__s16)le16_to_cpu(pSMBr->ServerTimeZone);
572 server->timeAdj *= 60;
573 if (pSMBr->EncryptionKeyLength == CIFS_CRYPTO_KEY_SIZE) {
574 memcpy(ses->server->cryptkey, pSMBr->u.EncryptionKey,
575 CIFS_CRYPTO_KEY_SIZE);
576 } else if ((pSMBr->hdr.Flags2 & SMBFLG2_EXT_SEC)
577 && (pSMBr->EncryptionKeyLength == 0)) {
578 /* decode security blob */
579 } else if (server->secMode & SECMODE_PW_ENCRYPT) {
580 rc = -EIO; /* no crypt key only if plain text pwd */
584 /* BB might be helpful to save off the domain of server here */
586 if ((pSMBr->hdr.Flags2 & SMBFLG2_EXT_SEC) &&
587 (server->capabilities & CAP_EXTENDED_SECURITY)) {
588 count = pSMBr->ByteCount;
593 spin_lock(&cifs_tcp_ses_lock);
594 if (server->srv_count > 1) {
595 spin_unlock(&cifs_tcp_ses_lock);
596 if (memcmp(server->server_GUID,
597 pSMBr->u.extended_response.
599 cFYI(1, "server UID changed");
600 memcpy(server->server_GUID,
601 pSMBr->u.extended_response.GUID,
605 spin_unlock(&cifs_tcp_ses_lock);
606 memcpy(server->server_GUID,
607 pSMBr->u.extended_response.GUID, 16);
611 server->secType = RawNTLMSSP;
613 rc = decode_negTokenInit(pSMBr->u.extended_response.
614 SecurityBlob, count - 16,
620 if (server->secType == Kerberos) {
621 if (!server->sec_kerberos &&
622 !server->sec_mskerberos)
624 } else if (server->secType == RawNTLMSSP) {
625 if (!server->sec_ntlmssp)
631 server->capabilities &= ~CAP_EXTENDED_SECURITY;
633 #ifdef CONFIG_CIFS_WEAK_PW_HASH
636 if ((secFlags & CIFSSEC_MAY_SIGN) == 0) {
637 /* MUST_SIGN already includes the MAY_SIGN FLAG
638 so if this is zero it means that signing is disabled */
639 cFYI(1, "Signing disabled");
640 if (server->secMode & SECMODE_SIGN_REQUIRED) {
641 cERROR(1, "Server requires "
642 "packet signing to be enabled in "
643 "/proc/fs/cifs/SecurityFlags.");
647 ~(SECMODE_SIGN_ENABLED | SECMODE_SIGN_REQUIRED);
648 } else if ((secFlags & CIFSSEC_MUST_SIGN) == CIFSSEC_MUST_SIGN) {
649 /* signing required */
650 cFYI(1, "Must sign - secFlags 0x%x", secFlags);
651 if ((server->secMode &
652 (SECMODE_SIGN_ENABLED | SECMODE_SIGN_REQUIRED)) == 0) {
653 cERROR(1, "signing required but server lacks support");
656 server->secMode |= SECMODE_SIGN_REQUIRED;
658 /* signing optional ie CIFSSEC_MAY_SIGN */
659 if ((server->secMode & SECMODE_SIGN_REQUIRED) == 0)
661 ~(SECMODE_SIGN_ENABLED | SECMODE_SIGN_REQUIRED);
665 cifs_buf_release(pSMB);
667 cFYI(1, "negprot rc %d", rc);
672 CIFSSMBTDis(const int xid, struct cifsTconInfo *tcon)
674 struct smb_hdr *smb_buffer;
677 cFYI(1, "In tree disconnect");
679 /* BB: do we need to check this? These should never be NULL. */
680 if ((tcon->ses == NULL) || (tcon->ses->server == NULL))
684 * No need to return error on this operation if tid invalidated and
685 * closed on server already e.g. due to tcp session crashing. Also,
686 * the tcon is no longer on the list, so no need to take lock before
689 if ((tcon->need_reconnect) || (tcon->ses->need_reconnect))
692 rc = small_smb_init(SMB_COM_TREE_DISCONNECT, 0, tcon,
693 (void **)&smb_buffer);
697 rc = SendReceiveNoRsp(xid, tcon->ses, smb_buffer, 0);
699 cFYI(1, "Tree disconnect failed %d", rc);
701 /* No need to return error on this operation if tid invalidated and
702 closed on server already e.g. due to tcp session crashing */
710 CIFSSMBLogoff(const int xid, struct cifsSesInfo *ses)
712 LOGOFF_ANDX_REQ *pSMB;
715 cFYI(1, "In SMBLogoff for session disconnect");
718 * BB: do we need to check validity of ses and server? They should
719 * always be valid since we have an active reference. If not, that
720 * should probably be a BUG()
722 if (!ses || !ses->server)
725 mutex_lock(&ses->session_mutex);
726 if (ses->need_reconnect)
727 goto session_already_dead; /* no need to send SMBlogoff if uid
728 already closed due to reconnect */
729 rc = small_smb_init(SMB_COM_LOGOFF_ANDX, 2, NULL, (void **)&pSMB);
731 mutex_unlock(&ses->session_mutex);
735 pSMB->hdr.Mid = GetNextMid(ses->server);
737 if (ses->server->secMode &
738 (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
739 pSMB->hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
741 pSMB->hdr.Uid = ses->Suid;
743 pSMB->AndXCommand = 0xFF;
744 rc = SendReceiveNoRsp(xid, ses, (struct smb_hdr *) pSMB, 0);
745 session_already_dead:
746 mutex_unlock(&ses->session_mutex);
748 /* if session dead then we do not need to do ulogoff,
749 since server closed smb session, no sense reporting
757 CIFSPOSIXDelFile(const int xid, struct cifsTconInfo *tcon, const char *fileName,
758 __u16 type, const struct nls_table *nls_codepage, int remap)
760 TRANSACTION2_SPI_REQ *pSMB = NULL;
761 TRANSACTION2_SPI_RSP *pSMBr = NULL;
762 struct unlink_psx_rq *pRqD;
765 int bytes_returned = 0;
766 __u16 params, param_offset, offset, byte_count;
768 cFYI(1, "In POSIX delete");
770 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
775 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
777 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
778 PATH_MAX, nls_codepage, remap);
779 name_len++; /* trailing null */
781 } else { /* BB add path length overrun check */
782 name_len = strnlen(fileName, PATH_MAX);
783 name_len++; /* trailing null */
784 strncpy(pSMB->FileName, fileName, name_len);
787 params = 6 + name_len;
788 pSMB->MaxParameterCount = cpu_to_le16(2);
789 pSMB->MaxDataCount = 0; /* BB double check this with jra */
790 pSMB->MaxSetupCount = 0;
795 param_offset = offsetof(struct smb_com_transaction2_spi_req,
796 InformationLevel) - 4;
797 offset = param_offset + params;
799 /* Setup pointer to Request Data (inode type) */
800 pRqD = (struct unlink_psx_rq *)(((char *)&pSMB->hdr.Protocol) + offset);
801 pRqD->type = cpu_to_le16(type);
802 pSMB->ParameterOffset = cpu_to_le16(param_offset);
803 pSMB->DataOffset = cpu_to_le16(offset);
804 pSMB->SetupCount = 1;
806 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
807 byte_count = 3 /* pad */ + params + sizeof(struct unlink_psx_rq);
809 pSMB->DataCount = cpu_to_le16(sizeof(struct unlink_psx_rq));
810 pSMB->TotalDataCount = cpu_to_le16(sizeof(struct unlink_psx_rq));
811 pSMB->ParameterCount = cpu_to_le16(params);
812 pSMB->TotalParameterCount = pSMB->ParameterCount;
813 pSMB->InformationLevel = cpu_to_le16(SMB_POSIX_UNLINK);
815 pSMB->hdr.smb_buf_length += byte_count;
816 pSMB->ByteCount = cpu_to_le16(byte_count);
817 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
818 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
820 cFYI(1, "Posix delete returned %d", rc);
821 cifs_buf_release(pSMB);
823 cifs_stats_inc(&tcon->num_deletes);
832 CIFSSMBDelFile(const int xid, struct cifsTconInfo *tcon, const char *fileName,
833 const struct nls_table *nls_codepage, int remap)
835 DELETE_FILE_REQ *pSMB = NULL;
836 DELETE_FILE_RSP *pSMBr = NULL;
842 rc = smb_init(SMB_COM_DELETE, 1, tcon, (void **) &pSMB,
847 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
849 cifsConvertToUCS((__le16 *) pSMB->fileName, fileName,
850 PATH_MAX, nls_codepage, remap);
851 name_len++; /* trailing null */
853 } else { /* BB improve check for buffer overruns BB */
854 name_len = strnlen(fileName, PATH_MAX);
855 name_len++; /* trailing null */
856 strncpy(pSMB->fileName, fileName, name_len);
858 pSMB->SearchAttributes =
859 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM);
860 pSMB->BufferFormat = 0x04;
861 pSMB->hdr.smb_buf_length += name_len + 1;
862 pSMB->ByteCount = cpu_to_le16(name_len + 1);
863 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
864 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
865 cifs_stats_inc(&tcon->num_deletes);
867 cFYI(1, "Error in RMFile = %d", rc);
869 cifs_buf_release(pSMB);
877 CIFSSMBRmDir(const int xid, struct cifsTconInfo *tcon, const char *dirName,
878 const struct nls_table *nls_codepage, int remap)
880 DELETE_DIRECTORY_REQ *pSMB = NULL;
881 DELETE_DIRECTORY_RSP *pSMBr = NULL;
886 cFYI(1, "In CIFSSMBRmDir");
888 rc = smb_init(SMB_COM_DELETE_DIRECTORY, 0, tcon, (void **) &pSMB,
893 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
894 name_len = cifsConvertToUCS((__le16 *) pSMB->DirName, dirName,
895 PATH_MAX, nls_codepage, remap);
896 name_len++; /* trailing null */
898 } else { /* BB improve check for buffer overruns BB */
899 name_len = strnlen(dirName, PATH_MAX);
900 name_len++; /* trailing null */
901 strncpy(pSMB->DirName, dirName, name_len);
904 pSMB->BufferFormat = 0x04;
905 pSMB->hdr.smb_buf_length += name_len + 1;
906 pSMB->ByteCount = cpu_to_le16(name_len + 1);
907 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
908 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
909 cifs_stats_inc(&tcon->num_rmdirs);
911 cFYI(1, "Error in RMDir = %d", rc);
913 cifs_buf_release(pSMB);
920 CIFSSMBMkDir(const int xid, struct cifsTconInfo *tcon,
921 const char *name, const struct nls_table *nls_codepage, int remap)
924 CREATE_DIRECTORY_REQ *pSMB = NULL;
925 CREATE_DIRECTORY_RSP *pSMBr = NULL;
929 cFYI(1, "In CIFSSMBMkDir");
931 rc = smb_init(SMB_COM_CREATE_DIRECTORY, 0, tcon, (void **) &pSMB,
936 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
937 name_len = cifsConvertToUCS((__le16 *) pSMB->DirName, name,
938 PATH_MAX, nls_codepage, remap);
939 name_len++; /* trailing null */
941 } else { /* BB improve check for buffer overruns BB */
942 name_len = strnlen(name, PATH_MAX);
943 name_len++; /* trailing null */
944 strncpy(pSMB->DirName, name, name_len);
947 pSMB->BufferFormat = 0x04;
948 pSMB->hdr.smb_buf_length += name_len + 1;
949 pSMB->ByteCount = cpu_to_le16(name_len + 1);
950 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
951 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
952 cifs_stats_inc(&tcon->num_mkdirs);
954 cFYI(1, "Error in Mkdir = %d", rc);
956 cifs_buf_release(pSMB);
963 CIFSPOSIXCreate(const int xid, struct cifsTconInfo *tcon, __u32 posix_flags,
964 __u64 mode, __u16 *netfid, FILE_UNIX_BASIC_INFO *pRetData,
965 __u32 *pOplock, const char *name,
966 const struct nls_table *nls_codepage, int remap)
968 TRANSACTION2_SPI_REQ *pSMB = NULL;
969 TRANSACTION2_SPI_RSP *pSMBr = NULL;
972 int bytes_returned = 0;
973 __u16 params, param_offset, offset, byte_count, count;
975 OPEN_PSX_RSP *psx_rsp;
977 cFYI(1, "In POSIX Create");
979 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
984 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
986 cifsConvertToUCS((__le16 *) pSMB->FileName, name,
987 PATH_MAX, nls_codepage, remap);
988 name_len++; /* trailing null */
990 } else { /* BB improve the check for buffer overruns BB */
991 name_len = strnlen(name, PATH_MAX);
992 name_len++; /* trailing null */
993 strncpy(pSMB->FileName, name, name_len);
996 params = 6 + name_len;
997 count = sizeof(OPEN_PSX_REQ);
998 pSMB->MaxParameterCount = cpu_to_le16(2);
999 pSMB->MaxDataCount = cpu_to_le16(1000); /* large enough */
1000 pSMB->MaxSetupCount = 0;
1004 pSMB->Reserved2 = 0;
1005 param_offset = offsetof(struct smb_com_transaction2_spi_req,
1006 InformationLevel) - 4;
1007 offset = param_offset + params;
1008 pdata = (OPEN_PSX_REQ *)(((char *)&pSMB->hdr.Protocol) + offset);
1009 pdata->Level = cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC);
1010 pdata->Permissions = cpu_to_le64(mode);
1011 pdata->PosixOpenFlags = cpu_to_le32(posix_flags);
1012 pdata->OpenFlags = cpu_to_le32(*pOplock);
1013 pSMB->ParameterOffset = cpu_to_le16(param_offset);
1014 pSMB->DataOffset = cpu_to_le16(offset);
1015 pSMB->SetupCount = 1;
1016 pSMB->Reserved3 = 0;
1017 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
1018 byte_count = 3 /* pad */ + params + count;
1020 pSMB->DataCount = cpu_to_le16(count);
1021 pSMB->ParameterCount = cpu_to_le16(params);
1022 pSMB->TotalDataCount = pSMB->DataCount;
1023 pSMB->TotalParameterCount = pSMB->ParameterCount;
1024 pSMB->InformationLevel = cpu_to_le16(SMB_POSIX_OPEN);
1025 pSMB->Reserved4 = 0;
1026 pSMB->hdr.smb_buf_length += byte_count;
1027 pSMB->ByteCount = cpu_to_le16(byte_count);
1028 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1029 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1031 cFYI(1, "Posix create returned %d", rc);
1032 goto psx_create_err;
1035 cFYI(1, "copying inode info");
1036 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
1038 if (rc || (pSMBr->ByteCount < sizeof(OPEN_PSX_RSP))) {
1039 rc = -EIO; /* bad smb */
1040 goto psx_create_err;
1043 /* copy return information to pRetData */
1044 psx_rsp = (OPEN_PSX_RSP *)((char *) &pSMBr->hdr.Protocol
1045 + le16_to_cpu(pSMBr->t2.DataOffset));
1047 *pOplock = le16_to_cpu(psx_rsp->OplockFlags);
1049 *netfid = psx_rsp->Fid; /* cifs fid stays in le */
1050 /* Let caller know file was created so we can set the mode. */
1051 /* Do we care about the CreateAction in any other cases? */
1052 if (cpu_to_le32(FILE_CREATE) == psx_rsp->CreateAction)
1053 *pOplock |= CIFS_CREATE_ACTION;
1054 /* check to make sure response data is there */
1055 if (psx_rsp->ReturnedLevel != cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC)) {
1056 pRetData->Type = cpu_to_le32(-1); /* unknown */
1057 cFYI(DBG2, "unknown type");
1059 if (pSMBr->ByteCount < sizeof(OPEN_PSX_RSP)
1060 + sizeof(FILE_UNIX_BASIC_INFO)) {
1061 cERROR(1, "Open response data too small");
1062 pRetData->Type = cpu_to_le32(-1);
1063 goto psx_create_err;
1065 memcpy((char *) pRetData,
1066 (char *)psx_rsp + sizeof(OPEN_PSX_RSP),
1067 sizeof(FILE_UNIX_BASIC_INFO));
1071 cifs_buf_release(pSMB);
1073 if (posix_flags & SMB_O_DIRECTORY)
1074 cifs_stats_inc(&tcon->num_posixmkdirs);
1076 cifs_stats_inc(&tcon->num_posixopens);
1084 static __u16 convert_disposition(int disposition)
1088 switch (disposition) {
1089 case FILE_SUPERSEDE:
1090 ofun = SMBOPEN_OCREATE | SMBOPEN_OTRUNC;
1093 ofun = SMBOPEN_OAPPEND;
1096 ofun = SMBOPEN_OCREATE;
1099 ofun = SMBOPEN_OCREATE | SMBOPEN_OAPPEND;
1101 case FILE_OVERWRITE:
1102 ofun = SMBOPEN_OTRUNC;
1104 case FILE_OVERWRITE_IF:
1105 ofun = SMBOPEN_OCREATE | SMBOPEN_OTRUNC;
1108 cFYI(1, "unknown disposition %d", disposition);
1109 ofun = SMBOPEN_OAPPEND; /* regular open */
1115 access_flags_to_smbopen_mode(const int access_flags)
1117 int masked_flags = access_flags & (GENERIC_READ | GENERIC_WRITE);
1119 if (masked_flags == GENERIC_READ)
1120 return SMBOPEN_READ;
1121 else if (masked_flags == GENERIC_WRITE)
1122 return SMBOPEN_WRITE;
1124 /* just go for read/write */
1125 return SMBOPEN_READWRITE;
1129 SMBLegacyOpen(const int xid, struct cifsTconInfo *tcon,
1130 const char *fileName, const int openDisposition,
1131 const int access_flags, const int create_options, __u16 *netfid,
1132 int *pOplock, FILE_ALL_INFO *pfile_info,
1133 const struct nls_table *nls_codepage, int remap)
1136 OPENX_REQ *pSMB = NULL;
1137 OPENX_RSP *pSMBr = NULL;
1143 rc = smb_init(SMB_COM_OPEN_ANDX, 15, tcon, (void **) &pSMB,
1148 pSMB->AndXCommand = 0xFF; /* none */
1150 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1151 count = 1; /* account for one byte pad to word boundary */
1153 cifsConvertToUCS((__le16 *) (pSMB->fileName + 1),
1154 fileName, PATH_MAX, nls_codepage, remap);
1155 name_len++; /* trailing null */
1157 } else { /* BB improve check for buffer overruns BB */
1158 count = 0; /* no pad */
1159 name_len = strnlen(fileName, PATH_MAX);
1160 name_len++; /* trailing null */
1161 strncpy(pSMB->fileName, fileName, name_len);
1163 if (*pOplock & REQ_OPLOCK)
1164 pSMB->OpenFlags = cpu_to_le16(REQ_OPLOCK);
1165 else if (*pOplock & REQ_BATCHOPLOCK)
1166 pSMB->OpenFlags = cpu_to_le16(REQ_BATCHOPLOCK);
1168 pSMB->OpenFlags |= cpu_to_le16(REQ_MORE_INFO);
1169 pSMB->Mode = cpu_to_le16(access_flags_to_smbopen_mode(access_flags));
1170 pSMB->Mode |= cpu_to_le16(0x40); /* deny none */
1171 /* set file as system file if special file such
1172 as fifo and server expecting SFU style and
1173 no Unix extensions */
1175 if (create_options & CREATE_OPTION_SPECIAL)
1176 pSMB->FileAttributes = cpu_to_le16(ATTR_SYSTEM);
1177 else /* BB FIXME BB */
1178 pSMB->FileAttributes = cpu_to_le16(0/*ATTR_NORMAL*/);
1180 if (create_options & CREATE_OPTION_READONLY)
1181 pSMB->FileAttributes |= cpu_to_le16(ATTR_READONLY);
1184 /* pSMB->CreateOptions = cpu_to_le32(create_options &
1185 CREATE_OPTIONS_MASK); */
1186 /* BB FIXME END BB */
1188 pSMB->Sattr = cpu_to_le16(ATTR_HIDDEN | ATTR_SYSTEM | ATTR_DIRECTORY);
1189 pSMB->OpenFunction = cpu_to_le16(convert_disposition(openDisposition));
1191 pSMB->hdr.smb_buf_length += count;
1193 pSMB->ByteCount = cpu_to_le16(count);
1194 /* long_op set to 1 to allow for oplock break timeouts */
1195 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1196 (struct smb_hdr *)pSMBr, &bytes_returned, CIFS_LONG_OP);
1197 cifs_stats_inc(&tcon->num_opens);
1199 cFYI(1, "Error in Open = %d", rc);
1201 /* BB verify if wct == 15 */
1203 /* *pOplock = pSMBr->OplockLevel; */ /* BB take from action field*/
1205 *netfid = pSMBr->Fid; /* cifs fid stays in le */
1206 /* Let caller know file was created so we can set the mode. */
1207 /* Do we care about the CreateAction in any other cases? */
1209 /* if (cpu_to_le32(FILE_CREATE) == pSMBr->CreateAction)
1210 *pOplock |= CIFS_CREATE_ACTION; */
1214 pfile_info->CreationTime = 0; /* BB convert CreateTime*/
1215 pfile_info->LastAccessTime = 0; /* BB fixme */
1216 pfile_info->LastWriteTime = 0; /* BB fixme */
1217 pfile_info->ChangeTime = 0; /* BB fixme */
1218 pfile_info->Attributes =
1219 cpu_to_le32(le16_to_cpu(pSMBr->FileAttributes));
1220 /* the file_info buf is endian converted by caller */
1221 pfile_info->AllocationSize =
1222 cpu_to_le64(le32_to_cpu(pSMBr->EndOfFile));
1223 pfile_info->EndOfFile = pfile_info->AllocationSize;
1224 pfile_info->NumberOfLinks = cpu_to_le32(1);
1225 pfile_info->DeletePending = 0;
1229 cifs_buf_release(pSMB);
1236 CIFSSMBOpen(const int xid, struct cifsTconInfo *tcon,
1237 const char *fileName, const int openDisposition,
1238 const int access_flags, const int create_options, __u16 *netfid,
1239 int *pOplock, FILE_ALL_INFO *pfile_info,
1240 const struct nls_table *nls_codepage, int remap)
1243 OPEN_REQ *pSMB = NULL;
1244 OPEN_RSP *pSMBr = NULL;
1250 rc = smb_init(SMB_COM_NT_CREATE_ANDX, 24, tcon, (void **) &pSMB,
1255 pSMB->AndXCommand = 0xFF; /* none */
1257 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1258 count = 1; /* account for one byte pad to word boundary */
1260 cifsConvertToUCS((__le16 *) (pSMB->fileName + 1),
1261 fileName, PATH_MAX, nls_codepage, remap);
1262 name_len++; /* trailing null */
1264 pSMB->NameLength = cpu_to_le16(name_len);
1265 } else { /* BB improve check for buffer overruns BB */
1266 count = 0; /* no pad */
1267 name_len = strnlen(fileName, PATH_MAX);
1268 name_len++; /* trailing null */
1269 pSMB->NameLength = cpu_to_le16(name_len);
1270 strncpy(pSMB->fileName, fileName, name_len);
1272 if (*pOplock & REQ_OPLOCK)
1273 pSMB->OpenFlags = cpu_to_le32(REQ_OPLOCK);
1274 else if (*pOplock & REQ_BATCHOPLOCK)
1275 pSMB->OpenFlags = cpu_to_le32(REQ_BATCHOPLOCK);
1276 pSMB->DesiredAccess = cpu_to_le32(access_flags);
1277 pSMB->AllocationSize = 0;
1278 /* set file as system file if special file such
1279 as fifo and server expecting SFU style and
1280 no Unix extensions */
1281 if (create_options & CREATE_OPTION_SPECIAL)
1282 pSMB->FileAttributes = cpu_to_le32(ATTR_SYSTEM);
1284 pSMB->FileAttributes = cpu_to_le32(ATTR_NORMAL);
1286 /* XP does not handle ATTR_POSIX_SEMANTICS */
1287 /* but it helps speed up case sensitive checks for other
1288 servers such as Samba */
1289 if (tcon->ses->capabilities & CAP_UNIX)
1290 pSMB->FileAttributes |= cpu_to_le32(ATTR_POSIX_SEMANTICS);
1292 if (create_options & CREATE_OPTION_READONLY)
1293 pSMB->FileAttributes |= cpu_to_le32(ATTR_READONLY);
1295 pSMB->ShareAccess = cpu_to_le32(FILE_SHARE_ALL);
1296 pSMB->CreateDisposition = cpu_to_le32(openDisposition);
1297 pSMB->CreateOptions = cpu_to_le32(create_options & CREATE_OPTIONS_MASK);
1298 /* BB Expirement with various impersonation levels and verify */
1299 pSMB->ImpersonationLevel = cpu_to_le32(SECURITY_IMPERSONATION);
1300 pSMB->SecurityFlags =
1301 SECURITY_CONTEXT_TRACKING | SECURITY_EFFECTIVE_ONLY;
1304 pSMB->hdr.smb_buf_length += count;
1306 pSMB->ByteCount = cpu_to_le16(count);
1307 /* long_op set to 1 to allow for oplock break timeouts */
1308 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1309 (struct smb_hdr *)pSMBr, &bytes_returned, CIFS_LONG_OP);
1310 cifs_stats_inc(&tcon->num_opens);
1312 cFYI(1, "Error in Open = %d", rc);
1314 *pOplock = pSMBr->OplockLevel; /* 1 byte no need to le_to_cpu */
1315 *netfid = pSMBr->Fid; /* cifs fid stays in le */
1316 /* Let caller know file was created so we can set the mode. */
1317 /* Do we care about the CreateAction in any other cases? */
1318 if (cpu_to_le32(FILE_CREATE) == pSMBr->CreateAction)
1319 *pOplock |= CIFS_CREATE_ACTION;
1321 memcpy((char *)pfile_info, (char *)&pSMBr->CreationTime,
1322 36 /* CreationTime to Attributes */);
1323 /* the file_info buf is endian converted by caller */
1324 pfile_info->AllocationSize = pSMBr->AllocationSize;
1325 pfile_info->EndOfFile = pSMBr->EndOfFile;
1326 pfile_info->NumberOfLinks = cpu_to_le32(1);
1327 pfile_info->DeletePending = 0;
1331 cifs_buf_release(pSMB);
1338 CIFSSMBRead(const int xid, struct cifsTconInfo *tcon, const int netfid,
1339 const unsigned int count, const __u64 lseek, unsigned int *nbytes,
1340 char **buf, int *pbuf_type)
1343 READ_REQ *pSMB = NULL;
1344 READ_RSP *pSMBr = NULL;
1345 char *pReadData = NULL;
1347 int resp_buf_type = 0;
1350 cFYI(1, "Reading %d bytes on fid %d", count, netfid);
1351 if (tcon->ses->capabilities & CAP_LARGE_FILES)
1354 wct = 10; /* old style read */
1355 if ((lseek >> 32) > 0) {
1356 /* can not handle this big offset for old */
1362 rc = small_smb_init(SMB_COM_READ_ANDX, wct, tcon, (void **) &pSMB);
1366 /* tcon and ses pointer are checked in smb_init */
1367 if (tcon->ses->server == NULL)
1368 return -ECONNABORTED;
1370 pSMB->AndXCommand = 0xFF; /* none */
1372 pSMB->OffsetLow = cpu_to_le32(lseek & 0xFFFFFFFF);
1374 pSMB->OffsetHigh = cpu_to_le32(lseek >> 32);
1376 pSMB->Remaining = 0;
1377 pSMB->MaxCount = cpu_to_le16(count & 0xFFFF);
1378 pSMB->MaxCountHigh = cpu_to_le32(count >> 16);
1380 pSMB->ByteCount = 0; /* no need to do le conversion since 0 */
1382 /* old style read */
1383 struct smb_com_readx_req *pSMBW =
1384 (struct smb_com_readx_req *)pSMB;
1385 pSMBW->ByteCount = 0;
1388 iov[0].iov_base = (char *)pSMB;
1389 iov[0].iov_len = pSMB->hdr.smb_buf_length + 4;
1390 rc = SendReceive2(xid, tcon->ses, iov, 1 /* num iovecs */,
1391 &resp_buf_type, CIFS_STD_OP | CIFS_LOG_ERROR);
1392 cifs_stats_inc(&tcon->num_reads);
1393 pSMBr = (READ_RSP *)iov[0].iov_base;
1395 cERROR(1, "Send error in read = %d", rc);
1397 int data_length = le16_to_cpu(pSMBr->DataLengthHigh);
1398 data_length = data_length << 16;
1399 data_length += le16_to_cpu(pSMBr->DataLength);
1400 *nbytes = data_length;
1402 /*check that DataLength would not go beyond end of SMB */
1403 if ((data_length > CIFSMaxBufSize)
1404 || (data_length > count)) {
1405 cFYI(1, "bad length %d for count %d",
1406 data_length, count);
1410 pReadData = (char *) (&pSMBr->hdr.Protocol) +
1411 le16_to_cpu(pSMBr->DataOffset);
1412 /* if (rc = copy_to_user(buf, pReadData, data_length)) {
1413 cERROR(1, "Faulting on read rc = %d",rc);
1415 }*/ /* can not use copy_to_user when using page cache*/
1417 memcpy(*buf, pReadData, data_length);
1421 /* cifs_small_buf_release(pSMB); */ /* Freed earlier now in SendReceive2 */
1423 if (resp_buf_type == CIFS_SMALL_BUFFER)
1424 cifs_small_buf_release(iov[0].iov_base);
1425 else if (resp_buf_type == CIFS_LARGE_BUFFER)
1426 cifs_buf_release(iov[0].iov_base);
1427 } else if (resp_buf_type != CIFS_NO_BUFFER) {
1428 /* return buffer to caller to free */
1429 *buf = iov[0].iov_base;
1430 if (resp_buf_type == CIFS_SMALL_BUFFER)
1431 *pbuf_type = CIFS_SMALL_BUFFER;
1432 else if (resp_buf_type == CIFS_LARGE_BUFFER)
1433 *pbuf_type = CIFS_LARGE_BUFFER;
1434 } /* else no valid buffer on return - leave as null */
1436 /* Note: On -EAGAIN error only caller can retry on handle based calls
1437 since file handle passed in no longer valid */
1443 CIFSSMBWrite(const int xid, struct cifsTconInfo *tcon,
1444 const int netfid, const unsigned int count,
1445 const __u64 offset, unsigned int *nbytes, const char *buf,
1446 const char __user *ubuf, const int long_op)
1449 WRITE_REQ *pSMB = NULL;
1450 WRITE_RSP *pSMBr = NULL;
1451 int bytes_returned, wct;
1457 /* cFYI(1, "write at %lld %d bytes", offset, count);*/
1458 if (tcon->ses == NULL)
1459 return -ECONNABORTED;
1461 if (tcon->ses->capabilities & CAP_LARGE_FILES)
1465 if ((offset >> 32) > 0) {
1466 /* can not handle big offset for old srv */
1471 rc = smb_init(SMB_COM_WRITE_ANDX, wct, tcon, (void **) &pSMB,
1475 /* tcon and ses pointer are checked in smb_init */
1476 if (tcon->ses->server == NULL)
1477 return -ECONNABORTED;
1479 pSMB->AndXCommand = 0xFF; /* none */
1481 pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF);
1483 pSMB->OffsetHigh = cpu_to_le32(offset >> 32);
1485 pSMB->Reserved = 0xFFFFFFFF;
1486 pSMB->WriteMode = 0;
1487 pSMB->Remaining = 0;
1489 /* Can increase buffer size if buffer is big enough in some cases ie we
1490 can send more if LARGE_WRITE_X capability returned by the server and if
1491 our buffer is big enough or if we convert to iovecs on socket writes
1492 and eliminate the copy to the CIFS buffer */
1493 if (tcon->ses->capabilities & CAP_LARGE_WRITE_X) {
1494 bytes_sent = min_t(const unsigned int, CIFSMaxBufSize, count);
1496 bytes_sent = (tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE)
1500 if (bytes_sent > count)
1503 cpu_to_le16(offsetof(struct smb_com_write_req, Data) - 4);
1505 memcpy(pSMB->Data, buf, bytes_sent);
1507 if (copy_from_user(pSMB->Data, ubuf, bytes_sent)) {
1508 cifs_buf_release(pSMB);
1511 } else if (count != 0) {
1513 cifs_buf_release(pSMB);
1515 } /* else setting file size with write of zero bytes */
1517 byte_count = bytes_sent + 1; /* pad */
1518 else /* wct == 12 */
1519 byte_count = bytes_sent + 5; /* bigger pad, smaller smb hdr */
1521 pSMB->DataLengthLow = cpu_to_le16(bytes_sent & 0xFFFF);
1522 pSMB->DataLengthHigh = cpu_to_le16(bytes_sent >> 16);
1523 pSMB->hdr.smb_buf_length += byte_count;
1526 pSMB->ByteCount = cpu_to_le16(byte_count);
1527 else { /* old style write has byte count 4 bytes earlier
1529 struct smb_com_writex_req *pSMBW =
1530 (struct smb_com_writex_req *)pSMB;
1531 pSMBW->ByteCount = cpu_to_le16(byte_count);
1534 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1535 (struct smb_hdr *) pSMBr, &bytes_returned, long_op);
1536 cifs_stats_inc(&tcon->num_writes);
1538 cFYI(1, "Send error in write = %d", rc);
1540 *nbytes = le16_to_cpu(pSMBr->CountHigh);
1541 *nbytes = (*nbytes) << 16;
1542 *nbytes += le16_to_cpu(pSMBr->Count);
1545 * Mask off high 16 bits when bytes written as returned by the
1546 * server is greater than bytes requested by the client. Some
1547 * OS/2 servers are known to set incorrect CountHigh values.
1549 if (*nbytes > count)
1553 cifs_buf_release(pSMB);
1555 /* Note: On -EAGAIN error only caller can retry on handle based calls
1556 since file handle passed in no longer valid */
1562 CIFSSMBWrite2(const int xid, struct cifsTconInfo *tcon,
1563 const int netfid, const unsigned int count,
1564 const __u64 offset, unsigned int *nbytes, struct kvec *iov,
1565 int n_vec, const int long_op)
1568 WRITE_REQ *pSMB = NULL;
1571 int resp_buf_type = 0;
1575 cFYI(1, "write2 at %lld %d bytes", (long long)offset, count);
1577 if (tcon->ses->capabilities & CAP_LARGE_FILES) {
1581 if ((offset >> 32) > 0) {
1582 /* can not handle big offset for old srv */
1586 rc = small_smb_init(SMB_COM_WRITE_ANDX, wct, tcon, (void **) &pSMB);
1589 /* tcon and ses pointer are checked in smb_init */
1590 if (tcon->ses->server == NULL)
1591 return -ECONNABORTED;
1593 pSMB->AndXCommand = 0xFF; /* none */
1595 pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF);
1597 pSMB->OffsetHigh = cpu_to_le32(offset >> 32);
1598 pSMB->Reserved = 0xFFFFFFFF;
1599 pSMB->WriteMode = 0;
1600 pSMB->Remaining = 0;
1603 cpu_to_le16(offsetof(struct smb_com_write_req, Data) - 4);
1605 pSMB->DataLengthLow = cpu_to_le16(count & 0xFFFF);
1606 pSMB->DataLengthHigh = cpu_to_le16(count >> 16);
1607 smb_hdr_len = pSMB->hdr.smb_buf_length + 1; /* hdr + 1 byte pad */
1609 pSMB->hdr.smb_buf_length += count+1;
1610 else /* wct == 12 */
1611 pSMB->hdr.smb_buf_length += count+5; /* smb data starts later */
1613 pSMB->ByteCount = cpu_to_le16(count + 1);
1614 else /* wct == 12 */ /* bigger pad, smaller smb hdr, keep offset ok */ {
1615 struct smb_com_writex_req *pSMBW =
1616 (struct smb_com_writex_req *)pSMB;
1617 pSMBW->ByteCount = cpu_to_le16(count + 5);
1619 iov[0].iov_base = pSMB;
1621 iov[0].iov_len = smb_hdr_len + 4;
1622 else /* wct == 12 pad bigger by four bytes */
1623 iov[0].iov_len = smb_hdr_len + 8;
1626 rc = SendReceive2(xid, tcon->ses, iov, n_vec + 1, &resp_buf_type,
1628 cifs_stats_inc(&tcon->num_writes);
1630 cFYI(1, "Send error Write2 = %d", rc);
1631 } else if (resp_buf_type == 0) {
1632 /* presumably this can not happen, but best to be safe */
1635 WRITE_RSP *pSMBr = (WRITE_RSP *)iov[0].iov_base;
1636 *nbytes = le16_to_cpu(pSMBr->CountHigh);
1637 *nbytes = (*nbytes) << 16;
1638 *nbytes += le16_to_cpu(pSMBr->Count);
1641 * Mask off high 16 bits when bytes written as returned by the
1642 * server is greater than bytes requested by the client. OS/2
1643 * servers are known to set incorrect CountHigh values.
1645 if (*nbytes > count)
1649 /* cifs_small_buf_release(pSMB); */ /* Freed earlier now in SendReceive2 */
1650 if (resp_buf_type == CIFS_SMALL_BUFFER)
1651 cifs_small_buf_release(iov[0].iov_base);
1652 else if (resp_buf_type == CIFS_LARGE_BUFFER)
1653 cifs_buf_release(iov[0].iov_base);
1655 /* Note: On -EAGAIN error only caller can retry on handle based calls
1656 since file handle passed in no longer valid */
1663 CIFSSMBLock(const int xid, struct cifsTconInfo *tcon,
1664 const __u16 smb_file_id, const __u64 len,
1665 const __u64 offset, const __u32 numUnlock,
1666 const __u32 numLock, const __u8 lockType,
1667 const bool waitFlag, const __u8 oplock_level)
1670 LOCK_REQ *pSMB = NULL;
1671 /* LOCK_RSP *pSMBr = NULL; */ /* No response data other than rc to parse */
1676 cFYI(1, "CIFSSMBLock timeout %d numLock %d", (int)waitFlag, numLock);
1677 rc = small_smb_init(SMB_COM_LOCKING_ANDX, 8, tcon, (void **) &pSMB);
1682 if (lockType == LOCKING_ANDX_OPLOCK_RELEASE) {
1683 timeout = CIFS_ASYNC_OP; /* no response expected */
1685 } else if (waitFlag) {
1686 timeout = CIFS_BLOCKING_OP; /* blocking operation, no timeout */
1687 pSMB->Timeout = cpu_to_le32(-1);/* blocking - do not time out */
1692 pSMB->NumberOfLocks = cpu_to_le16(numLock);
1693 pSMB->NumberOfUnlocks = cpu_to_le16(numUnlock);
1694 pSMB->LockType = lockType;
1695 pSMB->OplockLevel = oplock_level;
1696 pSMB->AndXCommand = 0xFF; /* none */
1697 pSMB->Fid = smb_file_id; /* netfid stays le */
1699 if ((numLock != 0) || (numUnlock != 0)) {
1700 pSMB->Locks[0].Pid = cpu_to_le16(current->tgid);
1701 /* BB where to store pid high? */
1702 pSMB->Locks[0].LengthLow = cpu_to_le32((u32)len);
1703 pSMB->Locks[0].LengthHigh = cpu_to_le32((u32)(len>>32));
1704 pSMB->Locks[0].OffsetLow = cpu_to_le32((u32)offset);
1705 pSMB->Locks[0].OffsetHigh = cpu_to_le32((u32)(offset>>32));
1706 count = sizeof(LOCKING_ANDX_RANGE);
1711 pSMB->hdr.smb_buf_length += count;
1712 pSMB->ByteCount = cpu_to_le16(count);
1715 rc = SendReceiveBlockingLock(xid, tcon, (struct smb_hdr *) pSMB,
1716 (struct smb_hdr *) pSMB, &bytes_returned);
1717 cifs_small_buf_release(pSMB);
1719 rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *)pSMB,
1721 /* SMB buffer freed by function above */
1723 cifs_stats_inc(&tcon->num_locks);
1725 cFYI(1, "Send error in Lock = %d", rc);
1727 /* Note: On -EAGAIN error only caller can retry on handle based calls
1728 since file handle passed in no longer valid */
1733 CIFSSMBPosixLock(const int xid, struct cifsTconInfo *tcon,
1734 const __u16 smb_file_id, const int get_flag, const __u64 len,
1735 struct file_lock *pLockData, const __u16 lock_type,
1736 const bool waitFlag)
1738 struct smb_com_transaction2_sfi_req *pSMB = NULL;
1739 struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
1740 struct cifs_posix_lock *parm_data;
1743 int bytes_returned = 0;
1744 int resp_buf_type = 0;
1745 __u16 params, param_offset, offset, byte_count, count;
1748 cFYI(1, "Posix Lock");
1750 if (pLockData == NULL)
1753 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
1758 pSMBr = (struct smb_com_transaction2_sfi_rsp *)pSMB;
1761 pSMB->MaxSetupCount = 0;
1764 pSMB->Reserved2 = 0;
1765 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
1766 offset = param_offset + params;
1768 count = sizeof(struct cifs_posix_lock);
1769 pSMB->MaxParameterCount = cpu_to_le16(2);
1770 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB from sess */
1771 pSMB->SetupCount = 1;
1772 pSMB->Reserved3 = 0;
1774 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION);
1776 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
1777 byte_count = 3 /* pad */ + params + count;
1778 pSMB->DataCount = cpu_to_le16(count);
1779 pSMB->ParameterCount = cpu_to_le16(params);
1780 pSMB->TotalDataCount = pSMB->DataCount;
1781 pSMB->TotalParameterCount = pSMB->ParameterCount;
1782 pSMB->ParameterOffset = cpu_to_le16(param_offset);
1783 parm_data = (struct cifs_posix_lock *)
1784 (((char *) &pSMB->hdr.Protocol) + offset);
1786 parm_data->lock_type = cpu_to_le16(lock_type);
1788 timeout = CIFS_BLOCKING_OP; /* blocking operation, no timeout */
1789 parm_data->lock_flags = cpu_to_le16(1);
1790 pSMB->Timeout = cpu_to_le32(-1);
1794 parm_data->pid = cpu_to_le32(current->tgid);
1795 parm_data->start = cpu_to_le64(pLockData->fl_start);
1796 parm_data->length = cpu_to_le64(len); /* normalize negative numbers */
1798 pSMB->DataOffset = cpu_to_le16(offset);
1799 pSMB->Fid = smb_file_id;
1800 pSMB->InformationLevel = cpu_to_le16(SMB_SET_POSIX_LOCK);
1801 pSMB->Reserved4 = 0;
1802 pSMB->hdr.smb_buf_length += byte_count;
1803 pSMB->ByteCount = cpu_to_le16(byte_count);
1805 rc = SendReceiveBlockingLock(xid, tcon, (struct smb_hdr *) pSMB,
1806 (struct smb_hdr *) pSMBr, &bytes_returned);
1808 iov[0].iov_base = (char *)pSMB;
1809 iov[0].iov_len = pSMB->hdr.smb_buf_length + 4;
1810 rc = SendReceive2(xid, tcon->ses, iov, 1 /* num iovecs */,
1811 &resp_buf_type, timeout);
1812 pSMB = NULL; /* request buf already freed by SendReceive2. Do
1813 not try to free it twice below on exit */
1814 pSMBr = (struct smb_com_transaction2_sfi_rsp *)iov[0].iov_base;
1818 cFYI(1, "Send error in Posix Lock = %d", rc);
1819 } else if (get_flag) {
1820 /* lock structure can be returned on get */
1823 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
1825 if (rc || (pSMBr->ByteCount < sizeof(struct cifs_posix_lock))) {
1826 rc = -EIO; /* bad smb */
1829 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
1830 data_count = le16_to_cpu(pSMBr->t2.DataCount);
1831 if (data_count < sizeof(struct cifs_posix_lock)) {
1835 parm_data = (struct cifs_posix_lock *)
1836 ((char *)&pSMBr->hdr.Protocol + data_offset);
1837 if (parm_data->lock_type == __constant_cpu_to_le16(CIFS_UNLCK))
1838 pLockData->fl_type = F_UNLCK;
1840 if (parm_data->lock_type ==
1841 __constant_cpu_to_le16(CIFS_RDLCK))
1842 pLockData->fl_type = F_RDLCK;
1843 else if (parm_data->lock_type ==
1844 __constant_cpu_to_le16(CIFS_WRLCK))
1845 pLockData->fl_type = F_WRLCK;
1847 pLockData->fl_start = parm_data->start;
1848 pLockData->fl_end = parm_data->start +
1849 parm_data->length - 1;
1850 pLockData->fl_pid = parm_data->pid;
1856 cifs_small_buf_release(pSMB);
1858 if (resp_buf_type == CIFS_SMALL_BUFFER)
1859 cifs_small_buf_release(iov[0].iov_base);
1860 else if (resp_buf_type == CIFS_LARGE_BUFFER)
1861 cifs_buf_release(iov[0].iov_base);
1863 /* Note: On -EAGAIN error only caller can retry on handle based calls
1864 since file handle passed in no longer valid */
1871 CIFSSMBClose(const int xid, struct cifsTconInfo *tcon, int smb_file_id)
1874 CLOSE_REQ *pSMB = NULL;
1875 cFYI(1, "In CIFSSMBClose");
1877 /* do not retry on dead session on close */
1878 rc = small_smb_init(SMB_COM_CLOSE, 3, tcon, (void **) &pSMB);
1884 pSMB->FileID = (__u16) smb_file_id;
1885 pSMB->LastWriteTime = 0xFFFFFFFF;
1886 pSMB->ByteCount = 0;
1887 rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0);
1888 cifs_stats_inc(&tcon->num_closes);
1891 /* EINTR is expected when user ctl-c to kill app */
1892 cERROR(1, "Send error in Close = %d", rc);
1896 /* Since session is dead, file will be closed on server already */
1904 CIFSSMBFlush(const int xid, struct cifsTconInfo *tcon, int smb_file_id)
1907 FLUSH_REQ *pSMB = NULL;
1908 cFYI(1, "In CIFSSMBFlush");
1910 rc = small_smb_init(SMB_COM_FLUSH, 1, tcon, (void **) &pSMB);
1914 pSMB->FileID = (__u16) smb_file_id;
1915 pSMB->ByteCount = 0;
1916 rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0);
1917 cifs_stats_inc(&tcon->num_flushes);
1919 cERROR(1, "Send error in Flush = %d", rc);
1925 CIFSSMBRename(const int xid, struct cifsTconInfo *tcon,
1926 const char *fromName, const char *toName,
1927 const struct nls_table *nls_codepage, int remap)
1930 RENAME_REQ *pSMB = NULL;
1931 RENAME_RSP *pSMBr = NULL;
1933 int name_len, name_len2;
1936 cFYI(1, "In CIFSSMBRename");
1938 rc = smb_init(SMB_COM_RENAME, 1, tcon, (void **) &pSMB,
1943 pSMB->BufferFormat = 0x04;
1944 pSMB->SearchAttributes =
1945 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
1948 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1950 cifsConvertToUCS((__le16 *) pSMB->OldFileName, fromName,
1951 PATH_MAX, nls_codepage, remap);
1952 name_len++; /* trailing null */
1954 pSMB->OldFileName[name_len] = 0x04; /* pad */
1955 /* protocol requires ASCII signature byte on Unicode string */
1956 pSMB->OldFileName[name_len + 1] = 0x00;
1958 cifsConvertToUCS((__le16 *)&pSMB->OldFileName[name_len + 2],
1959 toName, PATH_MAX, nls_codepage, remap);
1960 name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
1961 name_len2 *= 2; /* convert to bytes */
1962 } else { /* BB improve the check for buffer overruns BB */
1963 name_len = strnlen(fromName, PATH_MAX);
1964 name_len++; /* trailing null */
1965 strncpy(pSMB->OldFileName, fromName, name_len);
1966 name_len2 = strnlen(toName, PATH_MAX);
1967 name_len2++; /* trailing null */
1968 pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */
1969 strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2);
1970 name_len2++; /* trailing null */
1971 name_len2++; /* signature byte */
1974 count = 1 /* 1st signature byte */ + name_len + name_len2;
1975 pSMB->hdr.smb_buf_length += count;
1976 pSMB->ByteCount = cpu_to_le16(count);
1978 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1979 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1980 cifs_stats_inc(&tcon->num_renames);
1982 cFYI(1, "Send error in rename = %d", rc);
1984 cifs_buf_release(pSMB);
1992 int CIFSSMBRenameOpenFile(const int xid, struct cifsTconInfo *pTcon,
1993 int netfid, const char *target_name,
1994 const struct nls_table *nls_codepage, int remap)
1996 struct smb_com_transaction2_sfi_req *pSMB = NULL;
1997 struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
1998 struct set_file_rename *rename_info;
2000 char dummy_string[30];
2002 int bytes_returned = 0;
2004 __u16 params, param_offset, offset, count, byte_count;
2006 cFYI(1, "Rename to File by handle");
2007 rc = smb_init(SMB_COM_TRANSACTION2, 15, pTcon, (void **) &pSMB,
2013 pSMB->MaxSetupCount = 0;
2017 pSMB->Reserved2 = 0;
2018 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
2019 offset = param_offset + params;
2021 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
2022 rename_info = (struct set_file_rename *) data_offset;
2023 pSMB->MaxParameterCount = cpu_to_le16(2);
2024 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB from sess */
2025 pSMB->SetupCount = 1;
2026 pSMB->Reserved3 = 0;
2027 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
2028 byte_count = 3 /* pad */ + params;
2029 pSMB->ParameterCount = cpu_to_le16(params);
2030 pSMB->TotalParameterCount = pSMB->ParameterCount;
2031 pSMB->ParameterOffset = cpu_to_le16(param_offset);
2032 pSMB->DataOffset = cpu_to_le16(offset);
2033 /* construct random name ".cifs_tmp<inodenum><mid>" */
2034 rename_info->overwrite = cpu_to_le32(1);
2035 rename_info->root_fid = 0;
2036 /* unicode only call */
2037 if (target_name == NULL) {
2038 sprintf(dummy_string, "cifs%x", pSMB->hdr.Mid);
2039 len_of_str = cifsConvertToUCS((__le16 *)rename_info->target_name,
2040 dummy_string, 24, nls_codepage, remap);
2042 len_of_str = cifsConvertToUCS((__le16 *)rename_info->target_name,
2043 target_name, PATH_MAX, nls_codepage,
2046 rename_info->target_name_len = cpu_to_le32(2 * len_of_str);
2047 count = 12 /* sizeof(struct set_file_rename) */ + (2 * len_of_str);
2048 byte_count += count;
2049 pSMB->DataCount = cpu_to_le16(count);
2050 pSMB->TotalDataCount = pSMB->DataCount;
2052 pSMB->InformationLevel =
2053 cpu_to_le16(SMB_SET_FILE_RENAME_INFORMATION);
2054 pSMB->Reserved4 = 0;
2055 pSMB->hdr.smb_buf_length += byte_count;
2056 pSMB->ByteCount = cpu_to_le16(byte_count);
2057 rc = SendReceive(xid, pTcon->ses, (struct smb_hdr *) pSMB,
2058 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2059 cifs_stats_inc(&pTcon->num_t2renames);
2061 cFYI(1, "Send error in Rename (by file handle) = %d", rc);
2063 cifs_buf_release(pSMB);
2065 /* Note: On -EAGAIN error only caller can retry on handle based calls
2066 since file handle passed in no longer valid */
2072 CIFSSMBCopy(const int xid, struct cifsTconInfo *tcon, const char *fromName,
2073 const __u16 target_tid, const char *toName, const int flags,
2074 const struct nls_table *nls_codepage, int remap)
2077 COPY_REQ *pSMB = NULL;
2078 COPY_RSP *pSMBr = NULL;
2080 int name_len, name_len2;
2083 cFYI(1, "In CIFSSMBCopy");
2085 rc = smb_init(SMB_COM_COPY, 1, tcon, (void **) &pSMB,
2090 pSMB->BufferFormat = 0x04;
2091 pSMB->Tid2 = target_tid;
2093 pSMB->Flags = cpu_to_le16(flags & COPY_TREE);
2095 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2096 name_len = cifsConvertToUCS((__le16 *) pSMB->OldFileName,
2097 fromName, PATH_MAX, nls_codepage,
2099 name_len++; /* trailing null */
2101 pSMB->OldFileName[name_len] = 0x04; /* pad */
2102 /* protocol requires ASCII signature byte on Unicode string */
2103 pSMB->OldFileName[name_len + 1] = 0x00;
2105 cifsConvertToUCS((__le16 *)&pSMB->OldFileName[name_len + 2],
2106 toName, PATH_MAX, nls_codepage, remap);
2107 name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
2108 name_len2 *= 2; /* convert to bytes */
2109 } else { /* BB improve the check for buffer overruns BB */
2110 name_len = strnlen(fromName, PATH_MAX);
2111 name_len++; /* trailing null */
2112 strncpy(pSMB->OldFileName, fromName, name_len);
2113 name_len2 = strnlen(toName, PATH_MAX);
2114 name_len2++; /* trailing null */
2115 pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */
2116 strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2);
2117 name_len2++; /* trailing null */
2118 name_len2++; /* signature byte */
2121 count = 1 /* 1st signature byte */ + name_len + name_len2;
2122 pSMB->hdr.smb_buf_length += count;
2123 pSMB->ByteCount = cpu_to_le16(count);
2125 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2126 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2128 cFYI(1, "Send error in copy = %d with %d files copied",
2129 rc, le16_to_cpu(pSMBr->CopyCount));
2131 cifs_buf_release(pSMB);
2140 CIFSUnixCreateSymLink(const int xid, struct cifsTconInfo *tcon,
2141 const char *fromName, const char *toName,
2142 const struct nls_table *nls_codepage)
2144 TRANSACTION2_SPI_REQ *pSMB = NULL;
2145 TRANSACTION2_SPI_RSP *pSMBr = NULL;
2148 int name_len_target;
2150 int bytes_returned = 0;
2151 __u16 params, param_offset, offset, byte_count;
2153 cFYI(1, "In Symlink Unix style");
2155 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2160 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2162 cifs_strtoUCS((__le16 *) pSMB->FileName, fromName, PATH_MAX
2163 /* find define for this maxpathcomponent */
2165 name_len++; /* trailing null */
2168 } else { /* BB improve the check for buffer overruns BB */
2169 name_len = strnlen(fromName, PATH_MAX);
2170 name_len++; /* trailing null */
2171 strncpy(pSMB->FileName, fromName, name_len);
2173 params = 6 + name_len;
2174 pSMB->MaxSetupCount = 0;
2178 pSMB->Reserved2 = 0;
2179 param_offset = offsetof(struct smb_com_transaction2_spi_req,
2180 InformationLevel) - 4;
2181 offset = param_offset + params;
2183 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
2184 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2186 cifs_strtoUCS((__le16 *) data_offset, toName, PATH_MAX
2187 /* find define for this maxpathcomponent */
2189 name_len_target++; /* trailing null */
2190 name_len_target *= 2;
2191 } else { /* BB improve the check for buffer overruns BB */
2192 name_len_target = strnlen(toName, PATH_MAX);
2193 name_len_target++; /* trailing null */
2194 strncpy(data_offset, toName, name_len_target);
2197 pSMB->MaxParameterCount = cpu_to_le16(2);
2198 /* BB find exact max on data count below from sess */
2199 pSMB->MaxDataCount = cpu_to_le16(1000);
2200 pSMB->SetupCount = 1;
2201 pSMB->Reserved3 = 0;
2202 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
2203 byte_count = 3 /* pad */ + params + name_len_target;
2204 pSMB->DataCount = cpu_to_le16(name_len_target);
2205 pSMB->ParameterCount = cpu_to_le16(params);
2206 pSMB->TotalDataCount = pSMB->DataCount;
2207 pSMB->TotalParameterCount = pSMB->ParameterCount;
2208 pSMB->ParameterOffset = cpu_to_le16(param_offset);
2209 pSMB->DataOffset = cpu_to_le16(offset);
2210 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_LINK);
2211 pSMB->Reserved4 = 0;
2212 pSMB->hdr.smb_buf_length += byte_count;
2213 pSMB->ByteCount = cpu_to_le16(byte_count);
2214 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2215 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2216 cifs_stats_inc(&tcon->num_symlinks);
2218 cFYI(1, "Send error in SetPathInfo create symlink = %d", rc);
2220 cifs_buf_release(pSMB);
2223 goto createSymLinkRetry;
2229 CIFSUnixCreateHardLink(const int xid, struct cifsTconInfo *tcon,
2230 const char *fromName, const char *toName,
2231 const struct nls_table *nls_codepage, int remap)
2233 TRANSACTION2_SPI_REQ *pSMB = NULL;
2234 TRANSACTION2_SPI_RSP *pSMBr = NULL;
2237 int name_len_target;
2239 int bytes_returned = 0;
2240 __u16 params, param_offset, offset, byte_count;
2242 cFYI(1, "In Create Hard link Unix style");
2243 createHardLinkRetry:
2244 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2249 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2250 name_len = cifsConvertToUCS((__le16 *) pSMB->FileName, toName,
2251 PATH_MAX, nls_codepage, remap);
2252 name_len++; /* trailing null */
2255 } else { /* BB improve the check for buffer overruns BB */
2256 name_len = strnlen(toName, PATH_MAX);
2257 name_len++; /* trailing null */
2258 strncpy(pSMB->FileName, toName, name_len);
2260 params = 6 + name_len;
2261 pSMB->MaxSetupCount = 0;
2265 pSMB->Reserved2 = 0;
2266 param_offset = offsetof(struct smb_com_transaction2_spi_req,
2267 InformationLevel) - 4;
2268 offset = param_offset + params;
2270 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
2271 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2273 cifsConvertToUCS((__le16 *) data_offset, fromName, PATH_MAX,
2274 nls_codepage, remap);
2275 name_len_target++; /* trailing null */
2276 name_len_target *= 2;
2277 } else { /* BB improve the check for buffer overruns BB */
2278 name_len_target = strnlen(fromName, PATH_MAX);
2279 name_len_target++; /* trailing null */
2280 strncpy(data_offset, fromName, name_len_target);
2283 pSMB->MaxParameterCount = cpu_to_le16(2);
2284 /* BB find exact max on data count below from sess*/
2285 pSMB->MaxDataCount = cpu_to_le16(1000);
2286 pSMB->SetupCount = 1;
2287 pSMB->Reserved3 = 0;
2288 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
2289 byte_count = 3 /* pad */ + params + name_len_target;
2290 pSMB->ParameterCount = cpu_to_le16(params);
2291 pSMB->TotalParameterCount = pSMB->ParameterCount;
2292 pSMB->DataCount = cpu_to_le16(name_len_target);
2293 pSMB->TotalDataCount = pSMB->DataCount;
2294 pSMB->ParameterOffset = cpu_to_le16(param_offset);
2295 pSMB->DataOffset = cpu_to_le16(offset);
2296 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_HLINK);
2297 pSMB->Reserved4 = 0;
2298 pSMB->hdr.smb_buf_length += byte_count;
2299 pSMB->ByteCount = cpu_to_le16(byte_count);
2300 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2301 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2302 cifs_stats_inc(&tcon->num_hardlinks);
2304 cFYI(1, "Send error in SetPathInfo (hard link) = %d", rc);
2306 cifs_buf_release(pSMB);
2308 goto createHardLinkRetry;
2314 CIFSCreateHardLink(const int xid, struct cifsTconInfo *tcon,
2315 const char *fromName, const char *toName,
2316 const struct nls_table *nls_codepage, int remap)
2319 NT_RENAME_REQ *pSMB = NULL;
2320 RENAME_RSP *pSMBr = NULL;
2322 int name_len, name_len2;
2325 cFYI(1, "In CIFSCreateHardLink");
2326 winCreateHardLinkRetry:
2328 rc = smb_init(SMB_COM_NT_RENAME, 4, tcon, (void **) &pSMB,
2333 pSMB->SearchAttributes =
2334 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
2336 pSMB->Flags = cpu_to_le16(CREATE_HARD_LINK);
2337 pSMB->ClusterCount = 0;
2339 pSMB->BufferFormat = 0x04;
2341 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2343 cifsConvertToUCS((__le16 *) pSMB->OldFileName, fromName,
2344 PATH_MAX, nls_codepage, remap);
2345 name_len++; /* trailing null */
2348 /* protocol specifies ASCII buffer format (0x04) for unicode */
2349 pSMB->OldFileName[name_len] = 0x04;
2350 pSMB->OldFileName[name_len + 1] = 0x00; /* pad */
2352 cifsConvertToUCS((__le16 *)&pSMB->OldFileName[name_len + 2],
2353 toName, PATH_MAX, nls_codepage, remap);
2354 name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
2355 name_len2 *= 2; /* convert to bytes */
2356 } else { /* BB improve the check for buffer overruns BB */
2357 name_len = strnlen(fromName, PATH_MAX);
2358 name_len++; /* trailing null */
2359 strncpy(pSMB->OldFileName, fromName, name_len);
2360 name_len2 = strnlen(toName, PATH_MAX);
2361 name_len2++; /* trailing null */
2362 pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */
2363 strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2);
2364 name_len2++; /* trailing null */
2365 name_len2++; /* signature byte */
2368 count = 1 /* string type byte */ + name_len + name_len2;
2369 pSMB->hdr.smb_buf_length += count;
2370 pSMB->ByteCount = cpu_to_le16(count);
2372 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2373 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2374 cifs_stats_inc(&tcon->num_hardlinks);
2376 cFYI(1, "Send error in hard link (NT rename) = %d", rc);
2378 cifs_buf_release(pSMB);
2380 goto winCreateHardLinkRetry;
2386 CIFSSMBUnixQuerySymLink(const int xid, struct cifsTconInfo *tcon,
2387 const unsigned char *searchName, char **symlinkinfo,
2388 const struct nls_table *nls_codepage)
2390 /* SMB_QUERY_FILE_UNIX_LINK */
2391 TRANSACTION2_QPI_REQ *pSMB = NULL;
2392 TRANSACTION2_QPI_RSP *pSMBr = NULL;
2396 __u16 params, byte_count;
2399 cFYI(1, "In QPathSymLinkInfo (Unix) for path %s", searchName);
2402 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2407 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2409 cifs_strtoUCS((__le16 *) pSMB->FileName, searchName,
2410 PATH_MAX, nls_codepage);
2411 name_len++; /* trailing null */
2413 } else { /* BB improve the check for buffer overruns BB */
2414 name_len = strnlen(searchName, PATH_MAX);
2415 name_len++; /* trailing null */
2416 strncpy(pSMB->FileName, searchName, name_len);
2419 params = 2 /* level */ + 4 /* rsrvd */ + name_len /* incl null */ ;
2420 pSMB->TotalDataCount = 0;
2421 pSMB->MaxParameterCount = cpu_to_le16(2);
2422 pSMB->MaxDataCount = cpu_to_le16(CIFSMaxBufSize);
2423 pSMB->MaxSetupCount = 0;
2427 pSMB->Reserved2 = 0;
2428 pSMB->ParameterOffset = cpu_to_le16(offsetof(
2429 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
2430 pSMB->DataCount = 0;
2431 pSMB->DataOffset = 0;
2432 pSMB->SetupCount = 1;
2433 pSMB->Reserved3 = 0;
2434 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
2435 byte_count = params + 1 /* pad */ ;
2436 pSMB->TotalParameterCount = cpu_to_le16(params);
2437 pSMB->ParameterCount = pSMB->TotalParameterCount;
2438 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_LINK);
2439 pSMB->Reserved4 = 0;
2440 pSMB->hdr.smb_buf_length += byte_count;
2441 pSMB->ByteCount = cpu_to_le16(byte_count);
2443 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2444 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2446 cFYI(1, "Send error in QuerySymLinkInfo = %d", rc);
2448 /* decode response */
2450 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
2451 /* BB also check enough total bytes returned */
2452 if (rc || (pSMBr->ByteCount < 2))
2456 u16 count = le16_to_cpu(pSMBr->t2.DataCount);
2458 data_start = ((char *) &pSMBr->hdr.Protocol) +
2459 le16_to_cpu(pSMBr->t2.DataOffset);
2461 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
2466 /* BB FIXME investigate remapping reserved chars here */
2467 *symlinkinfo = cifs_strndup_from_ucs(data_start, count,
2468 is_unicode, nls_codepage);
2473 cifs_buf_release(pSMB);
2475 goto querySymLinkRetry;
2479 #ifdef CONFIG_CIFS_EXPERIMENTAL
2481 CIFSSMBQueryReparseLinkInfo(const int xid, struct cifsTconInfo *tcon,
2482 const unsigned char *searchName,
2483 char *symlinkinfo, const int buflen, __u16 fid,
2484 const struct nls_table *nls_codepage)
2488 struct smb_com_transaction_ioctl_req *pSMB;
2489 struct smb_com_transaction_ioctl_rsp *pSMBr;
2491 cFYI(1, "In Windows reparse style QueryLink for path %s", searchName);
2492 rc = smb_init(SMB_COM_NT_TRANSACT, 23, tcon, (void **) &pSMB,
2497 pSMB->TotalParameterCount = 0 ;
2498 pSMB->TotalDataCount = 0;
2499 pSMB->MaxParameterCount = cpu_to_le32(2);
2500 /* BB find exact data count max from sess structure BB */
2501 pSMB->MaxDataCount = cpu_to_le32((tcon->ses->server->maxBuf -
2502 MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
2503 pSMB->MaxSetupCount = 4;
2505 pSMB->ParameterOffset = 0;
2506 pSMB->DataCount = 0;
2507 pSMB->DataOffset = 0;
2508 pSMB->SetupCount = 4;
2509 pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_IOCTL);
2510 pSMB->ParameterCount = pSMB->TotalParameterCount;
2511 pSMB->FunctionCode = cpu_to_le32(FSCTL_GET_REPARSE_POINT);
2512 pSMB->IsFsctl = 1; /* FSCTL */
2513 pSMB->IsRootFlag = 0;
2514 pSMB->Fid = fid; /* file handle always le */
2515 pSMB->ByteCount = 0;
2517 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2518 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2520 cFYI(1, "Send error in QueryReparseLinkInfo = %d", rc);
2521 } else { /* decode response */
2522 __u32 data_offset = le32_to_cpu(pSMBr->DataOffset);
2523 __u32 data_count = le32_to_cpu(pSMBr->DataCount);
2524 if ((pSMBr->ByteCount < 2) || (data_offset > 512)) {
2525 /* BB also check enough total bytes returned */
2526 rc = -EIO; /* bad smb */
2529 if (data_count && (data_count < 2048)) {
2530 char *end_of_smb = 2 /* sizeof byte count */ +
2531 pSMBr->ByteCount + (char *)&pSMBr->ByteCount;
2533 struct reparse_data *reparse_buf =
2534 (struct reparse_data *)
2535 ((char *)&pSMBr->hdr.Protocol
2537 if ((char *)reparse_buf >= end_of_smb) {
2541 if ((reparse_buf->LinkNamesBuf +
2542 reparse_buf->TargetNameOffset +
2543 reparse_buf->TargetNameLen) > end_of_smb) {
2544 cFYI(1, "reparse buf beyond SMB");
2549 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
2550 cifs_from_ucs2(symlinkinfo, (__le16 *)
2551 (reparse_buf->LinkNamesBuf +
2552 reparse_buf->TargetNameOffset),
2554 reparse_buf->TargetNameLen,
2556 } else { /* ASCII names */
2557 strncpy(symlinkinfo,
2558 reparse_buf->LinkNamesBuf +
2559 reparse_buf->TargetNameOffset,
2560 min_t(const int, buflen,
2561 reparse_buf->TargetNameLen));
2565 cFYI(1, "Invalid return data count on "
2566 "get reparse info ioctl");
2568 symlinkinfo[buflen] = 0; /* just in case so the caller
2569 does not go off the end of the buffer */
2570 cFYI(1, "readlink result - %s", symlinkinfo);
2574 cifs_buf_release(pSMB);
2576 /* Note: On -EAGAIN error only caller can retry on handle based calls
2577 since file handle passed in no longer valid */
2581 #endif /* CIFS_EXPERIMENTAL */
2583 #ifdef CONFIG_CIFS_POSIX
2585 /*Convert an Access Control Entry from wire format to local POSIX xattr format*/
2586 static void cifs_convert_ace(posix_acl_xattr_entry *ace,
2587 struct cifs_posix_ace *cifs_ace)
2589 /* u8 cifs fields do not need le conversion */
2590 ace->e_perm = cpu_to_le16(cifs_ace->cifs_e_perm);
2591 ace->e_tag = cpu_to_le16(cifs_ace->cifs_e_tag);
2592 ace->e_id = cpu_to_le32(le64_to_cpu(cifs_ace->cifs_uid));
2593 /* cFYI(1, "perm %d tag %d id %d",ace->e_perm,ace->e_tag,ace->e_id); */
2598 /* Convert ACL from CIFS POSIX wire format to local Linux POSIX ACL xattr */
2599 static int cifs_copy_posix_acl(char *trgt, char *src, const int buflen,
2600 const int acl_type, const int size_of_data_area)
2605 struct cifs_posix_ace *pACE;
2606 struct cifs_posix_acl *cifs_acl = (struct cifs_posix_acl *)src;
2607 posix_acl_xattr_header *local_acl = (posix_acl_xattr_header *)trgt;
2609 if (le16_to_cpu(cifs_acl->version) != CIFS_ACL_VERSION)
2612 if (acl_type & ACL_TYPE_ACCESS) {
2613 count = le16_to_cpu(cifs_acl->access_entry_count);
2614 pACE = &cifs_acl->ace_array[0];
2615 size = sizeof(struct cifs_posix_acl);
2616 size += sizeof(struct cifs_posix_ace) * count;
2617 /* check if we would go beyond end of SMB */
2618 if (size_of_data_area < size) {
2619 cFYI(1, "bad CIFS POSIX ACL size %d vs. %d",
2620 size_of_data_area, size);
2623 } else if (acl_type & ACL_TYPE_DEFAULT) {
2624 count = le16_to_cpu(cifs_acl->access_entry_count);
2625 size = sizeof(struct cifs_posix_acl);
2626 size += sizeof(struct cifs_posix_ace) * count;
2627 /* skip past access ACEs to get to default ACEs */
2628 pACE = &cifs_acl->ace_array[count];
2629 count = le16_to_cpu(cifs_acl->default_entry_count);
2630 size += sizeof(struct cifs_posix_ace) * count;
2631 /* check if we would go beyond end of SMB */
2632 if (size_of_data_area < size)
2639 size = posix_acl_xattr_size(count);
2640 if ((buflen == 0) || (local_acl == NULL)) {
2641 /* used to query ACL EA size */
2642 } else if (size > buflen) {
2644 } else /* buffer big enough */ {
2645 local_acl->a_version = cpu_to_le32(POSIX_ACL_XATTR_VERSION);
2646 for (i = 0; i < count ; i++) {
2647 cifs_convert_ace(&local_acl->a_entries[i], pACE);
2654 static __u16 convert_ace_to_cifs_ace(struct cifs_posix_ace *cifs_ace,
2655 const posix_acl_xattr_entry *local_ace)
2657 __u16 rc = 0; /* 0 = ACL converted ok */
2659 cifs_ace->cifs_e_perm = le16_to_cpu(local_ace->e_perm);
2660 cifs_ace->cifs_e_tag = le16_to_cpu(local_ace->e_tag);
2661 /* BB is there a better way to handle the large uid? */
2662 if (local_ace->e_id == cpu_to_le32(-1)) {
2663 /* Probably no need to le convert -1 on any arch but can not hurt */
2664 cifs_ace->cifs_uid = cpu_to_le64(-1);
2666 cifs_ace->cifs_uid = cpu_to_le64(le32_to_cpu(local_ace->e_id));
2667 /*cFYI(1, "perm %d tag %d id %d",ace->e_perm,ace->e_tag,ace->e_id);*/
2671 /* Convert ACL from local Linux POSIX xattr to CIFS POSIX ACL wire format */
2672 static __u16 ACL_to_cifs_posix(char *parm_data, const char *pACL,
2673 const int buflen, const int acl_type)
2676 struct cifs_posix_acl *cifs_acl = (struct cifs_posix_acl *)parm_data;
2677 posix_acl_xattr_header *local_acl = (posix_acl_xattr_header *)pACL;
2681 if ((buflen == 0) || (pACL == NULL) || (cifs_acl == NULL))
2684 count = posix_acl_xattr_count((size_t)buflen);
2685 cFYI(1, "setting acl with %d entries from buf of length %d and "
2687 count, buflen, le32_to_cpu(local_acl->a_version));
2688 if (le32_to_cpu(local_acl->a_version) != 2) {
2689 cFYI(1, "unknown POSIX ACL version %d",
2690 le32_to_cpu(local_acl->a_version));
2693 cifs_acl->version = cpu_to_le16(1);
2694 if (acl_type == ACL_TYPE_ACCESS)
2695 cifs_acl->access_entry_count = cpu_to_le16(count);
2696 else if (acl_type == ACL_TYPE_DEFAULT)
2697 cifs_acl->default_entry_count = cpu_to_le16(count);
2699 cFYI(1, "unknown ACL type %d", acl_type);
2702 for (i = 0; i < count; i++) {
2703 rc = convert_ace_to_cifs_ace(&cifs_acl->ace_array[i],
2704 &local_acl->a_entries[i]);
2706 /* ACE not converted */
2711 rc = (__u16)(count * sizeof(struct cifs_posix_ace));
2712 rc += sizeof(struct cifs_posix_acl);
2713 /* BB add check to make sure ACL does not overflow SMB */
2719 CIFSSMBGetPosixACL(const int xid, struct cifsTconInfo *tcon,
2720 const unsigned char *searchName,
2721 char *acl_inf, const int buflen, const int acl_type,
2722 const struct nls_table *nls_codepage, int remap)
2724 /* SMB_QUERY_POSIX_ACL */
2725 TRANSACTION2_QPI_REQ *pSMB = NULL;
2726 TRANSACTION2_QPI_RSP *pSMBr = NULL;
2730 __u16 params, byte_count;
2732 cFYI(1, "In GetPosixACL (Unix) for path %s", searchName);
2735 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2740 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2742 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
2743 PATH_MAX, nls_codepage, remap);
2744 name_len++; /* trailing null */
2746 pSMB->FileName[name_len] = 0;
2747 pSMB->FileName[name_len+1] = 0;
2748 } else { /* BB improve the check for buffer overruns BB */
2749 name_len = strnlen(searchName, PATH_MAX);
2750 name_len++; /* trailing null */
2751 strncpy(pSMB->FileName, searchName, name_len);
2754 params = 2 /* level */ + 4 /* rsrvd */ + name_len /* incl null */ ;
2755 pSMB->TotalDataCount = 0;
2756 pSMB->MaxParameterCount = cpu_to_le16(2);
2757 /* BB find exact max data count below from sess structure BB */
2758 pSMB->MaxDataCount = cpu_to_le16(4000);
2759 pSMB->MaxSetupCount = 0;
2763 pSMB->Reserved2 = 0;
2764 pSMB->ParameterOffset = cpu_to_le16(
2765 offsetof(struct smb_com_transaction2_qpi_req,
2766 InformationLevel) - 4);
2767 pSMB->DataCount = 0;
2768 pSMB->DataOffset = 0;
2769 pSMB->SetupCount = 1;
2770 pSMB->Reserved3 = 0;
2771 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
2772 byte_count = params + 1 /* pad */ ;
2773 pSMB->TotalParameterCount = cpu_to_le16(params);
2774 pSMB->ParameterCount = pSMB->TotalParameterCount;
2775 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_POSIX_ACL);
2776 pSMB->Reserved4 = 0;
2777 pSMB->hdr.smb_buf_length += byte_count;
2778 pSMB->ByteCount = cpu_to_le16(byte_count);
2780 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2781 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2782 cifs_stats_inc(&tcon->num_acl_get);
2784 cFYI(1, "Send error in Query POSIX ACL = %d", rc);
2786 /* decode response */
2788 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
2789 if (rc || (pSMBr->ByteCount < 2))
2790 /* BB also check enough total bytes returned */
2791 rc = -EIO; /* bad smb */
2793 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
2794 __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
2795 rc = cifs_copy_posix_acl(acl_inf,
2796 (char *)&pSMBr->hdr.Protocol+data_offset,
2797 buflen, acl_type, count);
2800 cifs_buf_release(pSMB);
2807 CIFSSMBSetPosixACL(const int xid, struct cifsTconInfo *tcon,
2808 const unsigned char *fileName,
2809 const char *local_acl, const int buflen,
2811 const struct nls_table *nls_codepage, int remap)
2813 struct smb_com_transaction2_spi_req *pSMB = NULL;
2814 struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
2818 int bytes_returned = 0;
2819 __u16 params, byte_count, data_count, param_offset, offset;
2821 cFYI(1, "In SetPosixACL (Unix) for path %s", fileName);
2823 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2827 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2829 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
2830 PATH_MAX, nls_codepage, remap);
2831 name_len++; /* trailing null */
2833 } else { /* BB improve the check for buffer overruns BB */
2834 name_len = strnlen(fileName, PATH_MAX);
2835 name_len++; /* trailing null */
2836 strncpy(pSMB->FileName, fileName, name_len);
2838 params = 6 + name_len;
2839 pSMB->MaxParameterCount = cpu_to_le16(2);
2840 /* BB find max SMB size from sess */
2841 pSMB->MaxDataCount = cpu_to_le16(1000);
2842 pSMB->MaxSetupCount = 0;
2846 pSMB->Reserved2 = 0;
2847 param_offset = offsetof(struct smb_com_transaction2_spi_req,
2848 InformationLevel) - 4;
2849 offset = param_offset + params;
2850 parm_data = ((char *) &pSMB->hdr.Protocol) + offset;
2851 pSMB->ParameterOffset = cpu_to_le16(param_offset);
2853 /* convert to on the wire format for POSIX ACL */
2854 data_count = ACL_to_cifs_posix(parm_data, local_acl, buflen, acl_type);
2856 if (data_count == 0) {
2858 goto setACLerrorExit;
2860 pSMB->DataOffset = cpu_to_le16(offset);
2861 pSMB->SetupCount = 1;
2862 pSMB->Reserved3 = 0;
2863 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
2864 pSMB->InformationLevel = cpu_to_le16(SMB_SET_POSIX_ACL);
2865 byte_count = 3 /* pad */ + params + data_count;
2866 pSMB->DataCount = cpu_to_le16(data_count);
2867 pSMB->TotalDataCount = pSMB->DataCount;
2868 pSMB->ParameterCount = cpu_to_le16(params);
2869 pSMB->TotalParameterCount = pSMB->ParameterCount;
2870 pSMB->Reserved4 = 0;
2871 pSMB->hdr.smb_buf_length += byte_count;
2872 pSMB->ByteCount = cpu_to_le16(byte_count);
2873 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2874 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2876 cFYI(1, "Set POSIX ACL returned %d", rc);
2879 cifs_buf_release(pSMB);
2885 /* BB fix tabs in this function FIXME BB */
2887 CIFSGetExtAttr(const int xid, struct cifsTconInfo *tcon,
2888 const int netfid, __u64 *pExtAttrBits, __u64 *pMask)
2891 struct smb_t2_qfi_req *pSMB = NULL;
2892 struct smb_t2_qfi_rsp *pSMBr = NULL;
2894 __u16 params, byte_count;
2896 cFYI(1, "In GetExtAttr");
2901 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2906 params = 2 /* level */ + 2 /* fid */;
2907 pSMB->t2.TotalDataCount = 0;
2908 pSMB->t2.MaxParameterCount = cpu_to_le16(4);
2909 /* BB find exact max data count below from sess structure BB */
2910 pSMB->t2.MaxDataCount = cpu_to_le16(4000);
2911 pSMB->t2.MaxSetupCount = 0;
2912 pSMB->t2.Reserved = 0;
2914 pSMB->t2.Timeout = 0;
2915 pSMB->t2.Reserved2 = 0;
2916 pSMB->t2.ParameterOffset = cpu_to_le16(offsetof(struct smb_t2_qfi_req,
2918 pSMB->t2.DataCount = 0;
2919 pSMB->t2.DataOffset = 0;
2920 pSMB->t2.SetupCount = 1;
2921 pSMB->t2.Reserved3 = 0;
2922 pSMB->t2.SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION);
2923 byte_count = params + 1 /* pad */ ;
2924 pSMB->t2.TotalParameterCount = cpu_to_le16(params);
2925 pSMB->t2.ParameterCount = pSMB->t2.TotalParameterCount;
2926 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_ATTR_FLAGS);
2929 pSMB->hdr.smb_buf_length += byte_count;
2930 pSMB->t2.ByteCount = cpu_to_le16(byte_count);
2932 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2933 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2935 cFYI(1, "error %d in GetExtAttr", rc);
2937 /* decode response */
2938 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
2939 if (rc || (pSMBr->ByteCount < 2))
2940 /* BB also check enough total bytes returned */
2941 /* If rc should we check for EOPNOSUPP and
2942 disable the srvino flag? or in caller? */
2943 rc = -EIO; /* bad smb */
2945 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
2946 __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
2947 struct file_chattr_info *pfinfo;
2948 /* BB Do we need a cast or hash here ? */
2950 cFYI(1, "Illegal size ret in GetExtAttr");
2954 pfinfo = (struct file_chattr_info *)
2955 (data_offset + (char *) &pSMBr->hdr.Protocol);
2956 *pExtAttrBits = le64_to_cpu(pfinfo->mode);
2957 *pMask = le64_to_cpu(pfinfo->mask);
2961 cifs_buf_release(pSMB);
2963 goto GetExtAttrRetry;
2967 #endif /* CONFIG_POSIX */
2969 #ifdef CONFIG_CIFS_ACL
2971 * Initialize NT TRANSACT SMB into small smb request buffer. This assumes that
2972 * all NT TRANSACTS that we init here have total parm and data under about 400
2973 * bytes (to fit in small cifs buffer size), which is the case so far, it
2974 * easily fits. NB: Setup words themselves and ByteCount MaxSetupCount (size of
2975 * returned setup area) and MaxParameterCount (returned parms size) must be set
2979 smb_init_nttransact(const __u16 sub_command, const int setup_count,
2980 const int parm_len, struct cifsTconInfo *tcon,
2985 struct smb_com_ntransact_req *pSMB;
2987 rc = small_smb_init(SMB_COM_NT_TRANSACT, 19 + setup_count, tcon,
2991 *ret_buf = (void *)pSMB;
2993 pSMB->TotalParameterCount = cpu_to_le32(parm_len);
2994 pSMB->TotalDataCount = 0;
2995 pSMB->MaxDataCount = cpu_to_le32((tcon->ses->server->maxBuf -
2996 MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
2997 pSMB->ParameterCount = pSMB->TotalParameterCount;
2998 pSMB->DataCount = pSMB->TotalDataCount;
2999 temp_offset = offsetof(struct smb_com_ntransact_req, Parms) +
3000 (setup_count * 2) - 4 /* for rfc1001 length itself */;
3001 pSMB->ParameterOffset = cpu_to_le32(temp_offset);
3002 pSMB->DataOffset = cpu_to_le32(temp_offset + parm_len);
3003 pSMB->SetupCount = setup_count; /* no need to le convert byte fields */
3004 pSMB->SubCommand = cpu_to_le16(sub_command);
3009 validate_ntransact(char *buf, char **ppparm, char **ppdata,
3010 __u32 *pparmlen, __u32 *pdatalen)
3013 __u32 data_count, data_offset, parm_count, parm_offset;
3014 struct smb_com_ntransact_rsp *pSMBr;
3022 pSMBr = (struct smb_com_ntransact_rsp *)buf;
3024 /* ByteCount was converted from little endian in SendReceive */
3025 end_of_smb = 2 /* sizeof byte count */ + pSMBr->ByteCount +
3026 (char *)&pSMBr->ByteCount;
3028 data_offset = le32_to_cpu(pSMBr->DataOffset);
3029 data_count = le32_to_cpu(pSMBr->DataCount);
3030 parm_offset = le32_to_cpu(pSMBr->ParameterOffset);
3031 parm_count = le32_to_cpu(pSMBr->ParameterCount);
3033 *ppparm = (char *)&pSMBr->hdr.Protocol + parm_offset;
3034 *ppdata = (char *)&pSMBr->hdr.Protocol + data_offset;
3036 /* should we also check that parm and data areas do not overlap? */
3037 if (*ppparm > end_of_smb) {
3038 cFYI(1, "parms start after end of smb");
3040 } else if (parm_count + *ppparm > end_of_smb) {
3041 cFYI(1, "parm end after end of smb");
3043 } else if (*ppdata > end_of_smb) {
3044 cFYI(1, "data starts after end of smb");
3046 } else if (data_count + *ppdata > end_of_smb) {
3047 cFYI(1, "data %p + count %d (%p) past smb end %p start %p",
3048 *ppdata, data_count, (data_count + *ppdata),
3051 } else if (parm_count + data_count > pSMBr->ByteCount) {
3052 cFYI(1, "parm count and data count larger than SMB");
3055 *pdatalen = data_count;
3056 *pparmlen = parm_count;
3060 /* Get Security Descriptor (by handle) from remote server for a file or dir */
3062 CIFSSMBGetCIFSACL(const int xid, struct cifsTconInfo *tcon, __u16 fid,
3063 struct cifs_ntsd **acl_inf, __u32 *pbuflen)
3067 QUERY_SEC_DESC_REQ *pSMB;
3070 cFYI(1, "GetCifsACL");
3075 rc = smb_init_nttransact(NT_TRANSACT_QUERY_SECURITY_DESC, 0,
3076 8 /* parm len */, tcon, (void **) &pSMB);
3080 pSMB->MaxParameterCount = cpu_to_le32(4);
3081 /* BB TEST with big acls that might need to be e.g. larger than 16K */
3082 pSMB->MaxSetupCount = 0;
3083 pSMB->Fid = fid; /* file handle always le */
3084 pSMB->AclFlags = cpu_to_le32(CIFS_ACL_OWNER | CIFS_ACL_GROUP |
3086 pSMB->ByteCount = cpu_to_le16(11); /* 3 bytes pad + 8 bytes parm */
3087 pSMB->hdr.smb_buf_length += 11;
3088 iov[0].iov_base = (char *)pSMB;
3089 iov[0].iov_len = pSMB->hdr.smb_buf_length + 4;
3091 rc = SendReceive2(xid, tcon->ses, iov, 1 /* num iovec */, &buf_type,
3093 cifs_stats_inc(&tcon->num_acl_get);
3095 cFYI(1, "Send error in QuerySecDesc = %d", rc);
3096 } else { /* decode response */
3100 struct smb_com_ntransact_rsp *pSMBr;
3103 /* validate_nttransact */
3104 rc = validate_ntransact(iov[0].iov_base, (char **)&parm,
3105 &pdata, &parm_len, pbuflen);
3108 pSMBr = (struct smb_com_ntransact_rsp *)iov[0].iov_base;
3110 cFYI(1, "smb %p parm %p data %p", pSMBr, parm, *acl_inf);
3112 if (le32_to_cpu(pSMBr->ParameterCount) != 4) {
3113 rc = -EIO; /* bad smb */
3118 /* BB check that data area is minimum length and as big as acl_len */
3120 acl_len = le32_to_cpu(*parm);
3121 if (acl_len != *pbuflen) {
3122 cERROR(1, "acl length %d does not match %d",
3124 if (*pbuflen > acl_len)
3128 /* check if buffer is big enough for the acl
3129 header followed by the smallest SID */
3130 if ((*pbuflen < sizeof(struct cifs_ntsd) + 8) ||
3131 (*pbuflen >= 64 * 1024)) {
3132 cERROR(1, "bad acl length %d", *pbuflen);
3136 *acl_inf = kmalloc(*pbuflen, GFP_KERNEL);
3137 if (*acl_inf == NULL) {
3141 memcpy(*acl_inf, pdata, *pbuflen);
3145 if (buf_type == CIFS_SMALL_BUFFER)
3146 cifs_small_buf_release(iov[0].iov_base);
3147 else if (buf_type == CIFS_LARGE_BUFFER)
3148 cifs_buf_release(iov[0].iov_base);
3149 /* cifs_small_buf_release(pSMB); */ /* Freed earlier now in SendReceive2 */
3154 CIFSSMBSetCIFSACL(const int xid, struct cifsTconInfo *tcon, __u16 fid,
3155 struct cifs_ntsd *pntsd, __u32 acllen)
3157 __u16 byte_count, param_count, data_count, param_offset, data_offset;
3159 int bytes_returned = 0;
3160 SET_SEC_DESC_REQ *pSMB = NULL;
3161 NTRANSACT_RSP *pSMBr = NULL;
3164 rc = smb_init(SMB_COM_NT_TRANSACT, 19, tcon, (void **) &pSMB,
3169 pSMB->MaxSetupCount = 0;
3173 param_offset = offsetof(struct smb_com_transaction_ssec_req, Fid) - 4;
3174 data_count = acllen;
3175 data_offset = param_offset + param_count;
3176 byte_count = 3 /* pad */ + param_count;
3178 pSMB->DataCount = cpu_to_le32(data_count);
3179 pSMB->TotalDataCount = pSMB->DataCount;
3180 pSMB->MaxParameterCount = cpu_to_le32(4);
3181 pSMB->MaxDataCount = cpu_to_le32(16384);
3182 pSMB->ParameterCount = cpu_to_le32(param_count);
3183 pSMB->ParameterOffset = cpu_to_le32(param_offset);
3184 pSMB->TotalParameterCount = pSMB->ParameterCount;
3185 pSMB->DataOffset = cpu_to_le32(data_offset);
3186 pSMB->SetupCount = 0;
3187 pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_SET_SECURITY_DESC);
3188 pSMB->ByteCount = cpu_to_le16(byte_count+data_count);
3190 pSMB->Fid = fid; /* file handle always le */
3191 pSMB->Reserved2 = 0;
3192 pSMB->AclFlags = cpu_to_le32(CIFS_ACL_DACL);
3194 if (pntsd && acllen) {
3195 memcpy((char *) &pSMBr->hdr.Protocol + data_offset,
3198 pSMB->hdr.smb_buf_length += (byte_count + data_count);
3201 pSMB->hdr.smb_buf_length += byte_count;
3203 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3204 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3206 cFYI(1, "SetCIFSACL bytes_returned: %d, rc: %d", bytes_returned, rc);
3208 cFYI(1, "Set CIFS ACL returned %d", rc);
3209 cifs_buf_release(pSMB);
3212 goto setCifsAclRetry;
3217 #endif /* CONFIG_CIFS_ACL */
3219 /* Legacy Query Path Information call for lookup to old servers such
3221 int SMBQueryInformation(const int xid, struct cifsTconInfo *tcon,
3222 const unsigned char *searchName,
3223 FILE_ALL_INFO *pFinfo,
3224 const struct nls_table *nls_codepage, int remap)
3226 QUERY_INFORMATION_REQ *pSMB;
3227 QUERY_INFORMATION_RSP *pSMBr;
3232 cFYI(1, "In SMBQPath path %s", searchName);
3234 rc = smb_init(SMB_COM_QUERY_INFORMATION, 0, tcon, (void **) &pSMB,
3239 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3241 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
3242 PATH_MAX, nls_codepage, remap);
3243 name_len++; /* trailing null */
3246 name_len = strnlen(searchName, PATH_MAX);
3247 name_len++; /* trailing null */
3248 strncpy(pSMB->FileName, searchName, name_len);
3250 pSMB->BufferFormat = 0x04;
3251 name_len++; /* account for buffer type byte */
3252 pSMB->hdr.smb_buf_length += (__u16) name_len;
3253 pSMB->ByteCount = cpu_to_le16(name_len);
3255 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3256 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3258 cFYI(1, "Send error in QueryInfo = %d", rc);
3259 } else if (pFinfo) {
3261 __u32 time = le32_to_cpu(pSMBr->last_write_time);
3263 /* decode response */
3264 /* BB FIXME - add time zone adjustment BB */
3265 memset(pFinfo, 0, sizeof(FILE_ALL_INFO));
3268 /* decode time fields */
3269 pFinfo->ChangeTime = cpu_to_le64(cifs_UnixTimeToNT(ts));
3270 pFinfo->LastWriteTime = pFinfo->ChangeTime;
3271 pFinfo->LastAccessTime = 0;
3272 pFinfo->AllocationSize =
3273 cpu_to_le64(le32_to_cpu(pSMBr->size));
3274 pFinfo->EndOfFile = pFinfo->AllocationSize;
3275 pFinfo->Attributes =
3276 cpu_to_le32(le16_to_cpu(pSMBr->attr));
3278 rc = -EIO; /* bad buffer passed in */
3280 cifs_buf_release(pSMB);
3289 CIFSSMBQFileInfo(const int xid, struct cifsTconInfo *tcon,
3290 u16 netfid, FILE_ALL_INFO *pFindData)
3292 struct smb_t2_qfi_req *pSMB = NULL;
3293 struct smb_t2_qfi_rsp *pSMBr = NULL;
3296 __u16 params, byte_count;
3299 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3304 params = 2 /* level */ + 2 /* fid */;
3305 pSMB->t2.TotalDataCount = 0;
3306 pSMB->t2.MaxParameterCount = cpu_to_le16(4);
3307 /* BB find exact max data count below from sess structure BB */
3308 pSMB->t2.MaxDataCount = cpu_to_le16(CIFSMaxBufSize);
3309 pSMB->t2.MaxSetupCount = 0;
3310 pSMB->t2.Reserved = 0;
3312 pSMB->t2.Timeout = 0;
3313 pSMB->t2.Reserved2 = 0;
3314 pSMB->t2.ParameterOffset = cpu_to_le16(offsetof(struct smb_t2_qfi_req,
3316 pSMB->t2.DataCount = 0;
3317 pSMB->t2.DataOffset = 0;
3318 pSMB->t2.SetupCount = 1;
3319 pSMB->t2.Reserved3 = 0;
3320 pSMB->t2.SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION);
3321 byte_count = params + 1 /* pad */ ;
3322 pSMB->t2.TotalParameterCount = cpu_to_le16(params);
3323 pSMB->t2.ParameterCount = pSMB->t2.TotalParameterCount;
3324 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_ALL_INFO);
3327 pSMB->hdr.smb_buf_length += byte_count;
3329 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3330 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3332 cFYI(1, "Send error in QPathInfo = %d", rc);
3333 } else { /* decode response */
3334 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3336 if (rc) /* BB add auto retry on EOPNOTSUPP? */
3338 else if (pSMBr->ByteCount < 40)
3339 rc = -EIO; /* bad smb */
3340 else if (pFindData) {
3341 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3342 memcpy((char *) pFindData,
3343 (char *) &pSMBr->hdr.Protocol +
3344 data_offset, sizeof(FILE_ALL_INFO));
3348 cifs_buf_release(pSMB);
3350 goto QFileInfoRetry;
3356 CIFSSMBQPathInfo(const int xid, struct cifsTconInfo *tcon,
3357 const unsigned char *searchName,
3358 FILE_ALL_INFO *pFindData,
3359 int legacy /* old style infolevel */,
3360 const struct nls_table *nls_codepage, int remap)
3362 /* level 263 SMB_QUERY_FILE_ALL_INFO */
3363 TRANSACTION2_QPI_REQ *pSMB = NULL;
3364 TRANSACTION2_QPI_RSP *pSMBr = NULL;
3368 __u16 params, byte_count;
3370 /* cFYI(1, "In QPathInfo path %s", searchName); */
3372 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3377 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3379 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
3380 PATH_MAX, nls_codepage, remap);
3381 name_len++; /* trailing null */
3383 } else { /* BB improve the check for buffer overruns BB */
3384 name_len = strnlen(searchName, PATH_MAX);
3385 name_len++; /* trailing null */
3386 strncpy(pSMB->FileName, searchName, name_len);
3389 params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */;
3390 pSMB->TotalDataCount = 0;
3391 pSMB->MaxParameterCount = cpu_to_le16(2);
3392 /* BB find exact max SMB PDU from sess structure BB */
3393 pSMB->MaxDataCount = cpu_to_le16(4000);
3394 pSMB->MaxSetupCount = 0;
3398 pSMB->Reserved2 = 0;
3399 pSMB->ParameterOffset = cpu_to_le16(offsetof(
3400 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
3401 pSMB->DataCount = 0;
3402 pSMB->DataOffset = 0;
3403 pSMB->SetupCount = 1;
3404 pSMB->Reserved3 = 0;
3405 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
3406 byte_count = params + 1 /* pad */ ;
3407 pSMB->TotalParameterCount = cpu_to_le16(params);
3408 pSMB->ParameterCount = pSMB->TotalParameterCount;
3410 pSMB->InformationLevel = cpu_to_le16(SMB_INFO_STANDARD);
3412 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_ALL_INFO);
3413 pSMB->Reserved4 = 0;
3414 pSMB->hdr.smb_buf_length += byte_count;
3415 pSMB->ByteCount = cpu_to_le16(byte_count);
3417 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3418 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3420 cFYI(1, "Send error in QPathInfo = %d", rc);
3421 } else { /* decode response */
3422 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3424 if (rc) /* BB add auto retry on EOPNOTSUPP? */
3426 else if (!legacy && (pSMBr->ByteCount < 40))
3427 rc = -EIO; /* bad smb */
3428 else if (legacy && (pSMBr->ByteCount < 24))
3429 rc = -EIO; /* 24 or 26 expected but we do not read
3431 else if (pFindData) {
3433 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3435 /* On legacy responses we do not read the last field,
3436 EAsize, fortunately since it varies by subdialect and
3437 also note it differs on Set vs. Get, ie two bytes or 4
3438 bytes depending but we don't care here */
3440 size = sizeof(FILE_INFO_STANDARD);
3442 size = sizeof(FILE_ALL_INFO);
3443 memcpy((char *) pFindData,
3444 (char *) &pSMBr->hdr.Protocol +
3449 cifs_buf_release(pSMB);
3451 goto QPathInfoRetry;
3457 CIFSSMBUnixQFileInfo(const int xid, struct cifsTconInfo *tcon,
3458 u16 netfid, FILE_UNIX_BASIC_INFO *pFindData)
3460 struct smb_t2_qfi_req *pSMB = NULL;
3461 struct smb_t2_qfi_rsp *pSMBr = NULL;
3464 __u16 params, byte_count;
3467 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3472 params = 2 /* level */ + 2 /* fid */;
3473 pSMB->t2.TotalDataCount = 0;
3474 pSMB->t2.MaxParameterCount = cpu_to_le16(4);
3475 /* BB find exact max data count below from sess structure BB */
3476 pSMB->t2.MaxDataCount = cpu_to_le16(CIFSMaxBufSize);
3477 pSMB->t2.MaxSetupCount = 0;
3478 pSMB->t2.Reserved = 0;
3480 pSMB->t2.Timeout = 0;
3481 pSMB->t2.Reserved2 = 0;
3482 pSMB->t2.ParameterOffset = cpu_to_le16(offsetof(struct smb_t2_qfi_req,
3484 pSMB->t2.DataCount = 0;
3485 pSMB->t2.DataOffset = 0;
3486 pSMB->t2.SetupCount = 1;
3487 pSMB->t2.Reserved3 = 0;
3488 pSMB->t2.SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION);
3489 byte_count = params + 1 /* pad */ ;
3490 pSMB->t2.TotalParameterCount = cpu_to_le16(params);
3491 pSMB->t2.ParameterCount = pSMB->t2.TotalParameterCount;
3492 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC);
3495 pSMB->hdr.smb_buf_length += byte_count;
3497 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3498 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3500 cFYI(1, "Send error in QPathInfo = %d", rc);
3501 } else { /* decode response */
3502 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3504 if (rc || (pSMBr->ByteCount < sizeof(FILE_UNIX_BASIC_INFO))) {
3505 cERROR(1, "Malformed FILE_UNIX_BASIC_INFO response.\n"
3506 "Unix Extensions can be disabled on mount "
3507 "by specifying the nosfu mount option.");
3508 rc = -EIO; /* bad smb */
3510 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3511 memcpy((char *) pFindData,
3512 (char *) &pSMBr->hdr.Protocol +
3514 sizeof(FILE_UNIX_BASIC_INFO));
3518 cifs_buf_release(pSMB);
3520 goto UnixQFileInfoRetry;
3526 CIFSSMBUnixQPathInfo(const int xid, struct cifsTconInfo *tcon,
3527 const unsigned char *searchName,
3528 FILE_UNIX_BASIC_INFO *pFindData,
3529 const struct nls_table *nls_codepage, int remap)
3531 /* SMB_QUERY_FILE_UNIX_BASIC */
3532 TRANSACTION2_QPI_REQ *pSMB = NULL;
3533 TRANSACTION2_QPI_RSP *pSMBr = NULL;
3535 int bytes_returned = 0;
3537 __u16 params, byte_count;
3539 cFYI(1, "In QPathInfo (Unix) the path %s", searchName);
3541 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3546 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3548 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
3549 PATH_MAX, nls_codepage, remap);
3550 name_len++; /* trailing null */
3552 } else { /* BB improve the check for buffer overruns BB */
3553 name_len = strnlen(searchName, PATH_MAX);
3554 name_len++; /* trailing null */
3555 strncpy(pSMB->FileName, searchName, name_len);
3558 params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */;
3559 pSMB->TotalDataCount = 0;
3560 pSMB->MaxParameterCount = cpu_to_le16(2);
3561 /* BB find exact max SMB PDU from sess structure BB */
3562 pSMB->MaxDataCount = cpu_to_le16(4000);
3563 pSMB->MaxSetupCount = 0;
3567 pSMB->Reserved2 = 0;
3568 pSMB->ParameterOffset = cpu_to_le16(offsetof(
3569 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
3570 pSMB->DataCount = 0;
3571 pSMB->DataOffset = 0;
3572 pSMB->SetupCount = 1;
3573 pSMB->Reserved3 = 0;
3574 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
3575 byte_count = params + 1 /* pad */ ;
3576 pSMB->TotalParameterCount = cpu_to_le16(params);
3577 pSMB->ParameterCount = pSMB->TotalParameterCount;
3578 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC);
3579 pSMB->Reserved4 = 0;
3580 pSMB->hdr.smb_buf_length += byte_count;
3581 pSMB->ByteCount = cpu_to_le16(byte_count);
3583 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3584 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3586 cFYI(1, "Send error in QPathInfo = %d", rc);
3587 } else { /* decode response */
3588 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3590 if (rc || (pSMBr->ByteCount < sizeof(FILE_UNIX_BASIC_INFO))) {
3591 cERROR(1, "Malformed FILE_UNIX_BASIC_INFO response.\n"
3592 "Unix Extensions can be disabled on mount "
3593 "by specifying the nosfu mount option.");
3594 rc = -EIO; /* bad smb */
3596 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3597 memcpy((char *) pFindData,
3598 (char *) &pSMBr->hdr.Protocol +
3600 sizeof(FILE_UNIX_BASIC_INFO));
3603 cifs_buf_release(pSMB);
3605 goto UnixQPathInfoRetry;
3610 /* xid, tcon, searchName and codepage are input parms, rest are returned */
3612 CIFSFindFirst(const int xid, struct cifsTconInfo *tcon,
3613 const char *searchName,
3614 const struct nls_table *nls_codepage,
3616 struct cifs_search_info *psrch_inf, int remap, const char dirsep)
3618 /* level 257 SMB_ */
3619 TRANSACTION2_FFIRST_REQ *pSMB = NULL;
3620 TRANSACTION2_FFIRST_RSP *pSMBr = NULL;
3621 T2_FFIRST_RSP_PARMS *parms;
3623 int bytes_returned = 0;
3625 __u16 params, byte_count;
3627 cFYI(1, "In FindFirst for %s", searchName);
3630 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3635 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3637 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
3638 PATH_MAX, nls_codepage, remap);
3639 /* We can not add the asterik earlier in case
3640 it got remapped to 0xF03A as if it were part of the
3641 directory name instead of a wildcard */
3643 pSMB->FileName[name_len] = dirsep;
3644 pSMB->FileName[name_len+1] = 0;
3645 pSMB->FileName[name_len+2] = '*';
3646 pSMB->FileName[name_len+3] = 0;
3647 name_len += 4; /* now the trailing null */
3648 pSMB->FileName[name_len] = 0; /* null terminate just in case */
3649 pSMB->FileName[name_len+1] = 0;
3651 } else { /* BB add check for overrun of SMB buf BB */
3652 name_len = strnlen(searchName, PATH_MAX);
3653 /* BB fix here and in unicode clause above ie
3654 if (name_len > buffersize-header)
3655 free buffer exit; BB */
3656 strncpy(pSMB->FileName, searchName, name_len);
3657 pSMB->FileName[name_len] = dirsep;
3658 pSMB->FileName[name_len+1] = '*';
3659 pSMB->FileName[name_len+2] = 0;
3663 params = 12 + name_len /* includes null */ ;
3664 pSMB->TotalDataCount = 0; /* no EAs */
3665 pSMB->MaxParameterCount = cpu_to_le16(10);
3666 pSMB->MaxDataCount = cpu_to_le16((tcon->ses->server->maxBuf -
3667 MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
3668 pSMB->MaxSetupCount = 0;
3672 pSMB->Reserved2 = 0;
3673 byte_count = params + 1 /* pad */ ;
3674 pSMB->TotalParameterCount = cpu_to_le16(params);
3675 pSMB->ParameterCount = pSMB->TotalParameterCount;
3676 pSMB->ParameterOffset = cpu_to_le16(
3677 offsetof(struct smb_com_transaction2_ffirst_req, SearchAttributes)
3679 pSMB->DataCount = 0;
3680 pSMB->DataOffset = 0;
3681 pSMB->SetupCount = 1; /* one byte, no need to make endian neutral */
3682 pSMB->Reserved3 = 0;
3683 pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_FIRST);
3684 pSMB->SearchAttributes =
3685 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
3687 pSMB->SearchCount = cpu_to_le16(CIFSMaxBufSize/sizeof(FILE_UNIX_INFO));
3688 pSMB->SearchFlags = cpu_to_le16(CIFS_SEARCH_CLOSE_AT_END |
3689 CIFS_SEARCH_RETURN_RESUME);
3690 pSMB->InformationLevel = cpu_to_le16(psrch_inf->info_level);
3692 /* BB what should we set StorageType to? Does it matter? BB */
3693 pSMB->SearchStorageType = 0;
3694 pSMB->hdr.smb_buf_length += byte_count;
3695 pSMB->ByteCount = cpu_to_le16(byte_count);
3697 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3698 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3699 cifs_stats_inc(&tcon->num_ffirst);
3701 if (rc) {/* BB add logic to retry regular search if Unix search
3702 rejected unexpectedly by server */
3703 /* BB Add code to handle unsupported level rc */
3704 cFYI(1, "Error in FindFirst = %d", rc);
3706 cifs_buf_release(pSMB);
3708 /* BB eventually could optimize out free and realloc of buf */
3711 goto findFirstRetry;
3712 } else { /* decode response */
3713 /* BB remember to free buffer if error BB */
3714 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3718 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
3719 psrch_inf->unicode = true;
3721 psrch_inf->unicode = false;
3723 psrch_inf->ntwrk_buf_start = (char *)pSMBr;
3724 psrch_inf->smallBuf = 0;
3725 psrch_inf->srch_entries_start =
3726 (char *) &pSMBr->hdr.Protocol +
3727 le16_to_cpu(pSMBr->t2.DataOffset);
3728 parms = (T2_FFIRST_RSP_PARMS *)((char *) &pSMBr->hdr.Protocol +
3729 le16_to_cpu(pSMBr->t2.ParameterOffset));
3731 if (parms->EndofSearch)
3732 psrch_inf->endOfSearch = true;
3734 psrch_inf->endOfSearch = false;
3736 psrch_inf->entries_in_buffer =
3737 le16_to_cpu(parms->SearchCount);
3738 psrch_inf->index_of_last_entry = 2 /* skip . and .. */ +
3739 psrch_inf->entries_in_buffer;
3740 lnoff = le16_to_cpu(parms->LastNameOffset);
3741 if (tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE <
3743 cERROR(1, "ignoring corrupt resume name");
3744 psrch_inf->last_entry = NULL;
3748 psrch_inf->last_entry = psrch_inf->srch_entries_start +
3751 *pnetfid = parms->SearchHandle;
3753 cifs_buf_release(pSMB);
3760 int CIFSFindNext(const int xid, struct cifsTconInfo *tcon,
3761 __u16 searchHandle, struct cifs_search_info *psrch_inf)
3763 TRANSACTION2_FNEXT_REQ *pSMB = NULL;
3764 TRANSACTION2_FNEXT_RSP *pSMBr = NULL;
3765 T2_FNEXT_RSP_PARMS *parms;
3766 char *response_data;
3768 int bytes_returned, name_len;
3769 __u16 params, byte_count;
3771 cFYI(1, "In FindNext");
3773 if (psrch_inf->endOfSearch)
3776 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3781 params = 14; /* includes 2 bytes of null string, converted to LE below*/
3783 pSMB->TotalDataCount = 0; /* no EAs */
3784 pSMB->MaxParameterCount = cpu_to_le16(8);
3785 pSMB->MaxDataCount =
3786 cpu_to_le16((tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE) &
3788 pSMB->MaxSetupCount = 0;
3792 pSMB->Reserved2 = 0;
3793 pSMB->ParameterOffset = cpu_to_le16(
3794 offsetof(struct smb_com_transaction2_fnext_req,SearchHandle) - 4);
3795 pSMB->DataCount = 0;
3796 pSMB->DataOffset = 0;
3797 pSMB->SetupCount = 1;
3798 pSMB->Reserved3 = 0;
3799 pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_NEXT);
3800 pSMB->SearchHandle = searchHandle; /* always kept as le */
3802 cpu_to_le16(CIFSMaxBufSize / sizeof(FILE_UNIX_INFO));
3803 pSMB->InformationLevel = cpu_to_le16(psrch_inf->info_level);
3804 pSMB->ResumeKey = psrch_inf->resume_key;
3806 cpu_to_le16(CIFS_SEARCH_CLOSE_AT_END | CIFS_SEARCH_RETURN_RESUME);
3808 name_len = psrch_inf->resume_name_len;
3810 if (name_len < PATH_MAX) {
3811 memcpy(pSMB->ResumeFileName, psrch_inf->presume_name, name_len);
3812 byte_count += name_len;
3813 /* 14 byte parm len above enough for 2 byte null terminator */
3814 pSMB->ResumeFileName[name_len] = 0;
3815 pSMB->ResumeFileName[name_len+1] = 0;
3818 goto FNext2_err_exit;
3820 byte_count = params + 1 /* pad */ ;
3821 pSMB->TotalParameterCount = cpu_to_le16(params);
3822 pSMB->ParameterCount = pSMB->TotalParameterCount;
3823 pSMB->hdr.smb_buf_length += byte_count;
3824 pSMB->ByteCount = cpu_to_le16(byte_count);
3826 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3827 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3828 cifs_stats_inc(&tcon->num_fnext);
3831 psrch_inf->endOfSearch = true;
3832 cifs_buf_release(pSMB);
3833 rc = 0; /* search probably was closed at end of search*/
3835 cFYI(1, "FindNext returned = %d", rc);
3836 } else { /* decode response */
3837 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3842 /* BB fixme add lock for file (srch_info) struct here */
3843 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
3844 psrch_inf->unicode = true;
3846 psrch_inf->unicode = false;
3847 response_data = (char *) &pSMBr->hdr.Protocol +
3848 le16_to_cpu(pSMBr->t2.ParameterOffset);
3849 parms = (T2_FNEXT_RSP_PARMS *)response_data;
3850 response_data = (char *)&pSMBr->hdr.Protocol +
3851 le16_to_cpu(pSMBr->t2.DataOffset);
3852 if (psrch_inf->smallBuf)
3853 cifs_small_buf_release(
3854 psrch_inf->ntwrk_buf_start);
3856 cifs_buf_release(psrch_inf->ntwrk_buf_start);
3857 psrch_inf->srch_entries_start = response_data;
3858 psrch_inf->ntwrk_buf_start = (char *)pSMB;
3859 psrch_inf->smallBuf = 0;
3860 if (parms->EndofSearch)
3861 psrch_inf->endOfSearch = true;
3863 psrch_inf->endOfSearch = false;
3864 psrch_inf->entries_in_buffer =
3865 le16_to_cpu(parms->SearchCount);
3866 psrch_inf->index_of_last_entry +=
3867 psrch_inf->entries_in_buffer;
3868 lnoff = le16_to_cpu(parms->LastNameOffset);
3869 if (tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE <
3871 cERROR(1, "ignoring corrupt resume name");
3872 psrch_inf->last_entry = NULL;
3875 psrch_inf->last_entry =
3876 psrch_inf->srch_entries_start + lnoff;
3878 /* cFYI(1, "fnxt2 entries in buf %d index_of_last %d",
3879 psrch_inf->entries_in_buffer, psrch_inf->index_of_last_entry); */
3881 /* BB fixme add unlock here */
3886 /* BB On error, should we leave previous search buf (and count and
3887 last entry fields) intact or free the previous one? */
3889 /* Note: On -EAGAIN error only caller can retry on handle based calls
3890 since file handle passed in no longer valid */
3893 cifs_buf_release(pSMB);
3898 CIFSFindClose(const int xid, struct cifsTconInfo *tcon,
3899 const __u16 searchHandle)
3902 FINDCLOSE_REQ *pSMB = NULL;
3904 cFYI(1, "In CIFSSMBFindClose");
3905 rc = small_smb_init(SMB_COM_FIND_CLOSE2, 1, tcon, (void **)&pSMB);
3907 /* no sense returning error if session restarted
3908 as file handle has been closed */
3914 pSMB->FileID = searchHandle;
3915 pSMB->ByteCount = 0;
3916 rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0);
3918 cERROR(1, "Send error in FindClose = %d", rc);
3920 cifs_stats_inc(&tcon->num_fclose);
3922 /* Since session is dead, search handle closed on server already */
3930 CIFSGetSrvInodeNumber(const int xid, struct cifsTconInfo *tcon,
3931 const unsigned char *searchName,
3932 __u64 *inode_number,
3933 const struct nls_table *nls_codepage, int remap)
3936 TRANSACTION2_QPI_REQ *pSMB = NULL;
3937 TRANSACTION2_QPI_RSP *pSMBr = NULL;
3938 int name_len, bytes_returned;
3939 __u16 params, byte_count;
3941 cFYI(1, "In GetSrvInodeNum for %s", searchName);
3945 GetInodeNumberRetry:
3946 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3951 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3953 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
3954 PATH_MAX, nls_codepage, remap);
3955 name_len++; /* trailing null */
3957 } else { /* BB improve the check for buffer overruns BB */
3958 name_len = strnlen(searchName, PATH_MAX);
3959 name_len++; /* trailing null */
3960 strncpy(pSMB->FileName, searchName, name_len);
3963 params = 2 /* level */ + 4 /* rsrvd */ + name_len /* incl null */ ;
3964 pSMB->TotalDataCount = 0;
3965 pSMB->MaxParameterCount = cpu_to_le16(2);
3966 /* BB find exact max data count below from sess structure BB */
3967 pSMB->MaxDataCount = cpu_to_le16(4000);
3968 pSMB->MaxSetupCount = 0;
3972 pSMB->Reserved2 = 0;
3973 pSMB->ParameterOffset = cpu_to_le16(offsetof(
3974 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
3975 pSMB->DataCount = 0;
3976 pSMB->DataOffset = 0;
3977 pSMB->SetupCount = 1;
3978 pSMB->Reserved3 = 0;
3979 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
3980 byte_count = params + 1 /* pad */ ;
3981 pSMB->TotalParameterCount = cpu_to_le16(params);
3982 pSMB->ParameterCount = pSMB->TotalParameterCount;
3983 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_INTERNAL_INFO);
3984 pSMB->Reserved4 = 0;
3985 pSMB->hdr.smb_buf_length += byte_count;
3986 pSMB->ByteCount = cpu_to_le16(byte_count);
3988 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3989 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3991 cFYI(1, "error %d in QueryInternalInfo", rc);
3993 /* decode response */
3994 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3995 if (rc || (pSMBr->ByteCount < 2))
3996 /* BB also check enough total bytes returned */
3997 /* If rc should we check for EOPNOSUPP and
3998 disable the srvino flag? or in caller? */
3999 rc = -EIO; /* bad smb */
4001 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4002 __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
4003 struct file_internal_info *pfinfo;
4004 /* BB Do we need a cast or hash here ? */
4006 cFYI(1, "Illegal size ret in QryIntrnlInf");
4008 goto GetInodeNumOut;
4010 pfinfo = (struct file_internal_info *)
4011 (data_offset + (char *) &pSMBr->hdr.Protocol);
4012 *inode_number = le64_to_cpu(pfinfo->UniqueId);
4016 cifs_buf_release(pSMB);
4018 goto GetInodeNumberRetry;
4022 /* parses DFS refferal V3 structure
4023 * caller is responsible for freeing target_nodes
4026 * on failure - errno
4029 parse_DFS_referrals(TRANSACTION2_GET_DFS_REFER_RSP *pSMBr,
4030 unsigned int *num_of_nodes,
4031 struct dfs_info3_param **target_nodes,
4032 const struct nls_table *nls_codepage, int remap,
4033 const char *searchName)
4038 struct dfs_referral_level_3 *ref;
4040 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
4044 *num_of_nodes = le16_to_cpu(pSMBr->NumberOfReferrals);
4046 if (*num_of_nodes < 1) {
4047 cERROR(1, "num_referrals: must be at least > 0,"
4048 "but we get num_referrals = %d\n", *num_of_nodes);
4050 goto parse_DFS_referrals_exit;
4053 ref = (struct dfs_referral_level_3 *) &(pSMBr->referrals);
4054 if (ref->VersionNumber != cpu_to_le16(3)) {
4055 cERROR(1, "Referrals of V%d version are not supported,"
4056 "should be V3", le16_to_cpu(ref->VersionNumber));
4058 goto parse_DFS_referrals_exit;
4061 /* get the upper boundary of the resp buffer */
4062 data_end = (char *)(&(pSMBr->PathConsumed)) +
4063 le16_to_cpu(pSMBr->t2.DataCount);
4065 cFYI(1, "num_referrals: %d dfs flags: 0x%x ...\n",
4067 le32_to_cpu(pSMBr->DFSFlags));
4069 *target_nodes = kzalloc(sizeof(struct dfs_info3_param) *
4070 *num_of_nodes, GFP_KERNEL);
4071 if (*target_nodes == NULL) {
4072 cERROR(1, "Failed to allocate buffer for target_nodes\n");
4074 goto parse_DFS_referrals_exit;
4077 /* collect necessary data from referrals */
4078 for (i = 0; i < *num_of_nodes; i++) {
4081 struct dfs_info3_param *node = (*target_nodes)+i;
4083 node->flags = le32_to_cpu(pSMBr->DFSFlags);
4085 __le16 *tmp = kmalloc(strlen(searchName)*2 + 2,
4089 goto parse_DFS_referrals_exit;
4091 cifsConvertToUCS((__le16 *) tmp, searchName,
4092 PATH_MAX, nls_codepage, remap);
4093 node->path_consumed = cifs_ucs2_bytes(tmp,
4094 le16_to_cpu(pSMBr->PathConsumed),
4098 node->path_consumed = le16_to_cpu(pSMBr->PathConsumed);
4100 node->server_type = le16_to_cpu(ref->ServerType);
4101 node->ref_flag = le16_to_cpu(ref->ReferralEntryFlags);
4104 temp = (char *)ref + le16_to_cpu(ref->DfsPathOffset);
4105 max_len = data_end - temp;
4106 node->path_name = cifs_strndup_from_ucs(temp, max_len,
4107 is_unicode, nls_codepage);
4108 if (!node->path_name) {
4110 goto parse_DFS_referrals_exit;
4113 /* copy link target UNC */
4114 temp = (char *)ref + le16_to_cpu(ref->NetworkAddressOffset);
4115 max_len = data_end - temp;
4116 node->node_name = cifs_strndup_from_ucs(temp, max_len,
4117 is_unicode, nls_codepage);
4118 if (!node->node_name)
4122 parse_DFS_referrals_exit:
4124 free_dfs_info_array(*target_nodes, *num_of_nodes);
4125 *target_nodes = NULL;
4132 CIFSGetDFSRefer(const int xid, struct cifsSesInfo *ses,
4133 const unsigned char *searchName,
4134 struct dfs_info3_param **target_nodes,
4135 unsigned int *num_of_nodes,
4136 const struct nls_table *nls_codepage, int remap)
4138 /* TRANS2_GET_DFS_REFERRAL */
4139 TRANSACTION2_GET_DFS_REFER_REQ *pSMB = NULL;
4140 TRANSACTION2_GET_DFS_REFER_RSP *pSMBr = NULL;
4144 __u16 params, byte_count;
4146 *target_nodes = NULL;
4148 cFYI(1, "In GetDFSRefer the path %s", searchName);
4152 rc = smb_init(SMB_COM_TRANSACTION2, 15, NULL, (void **) &pSMB,
4157 /* server pointer checked in called function,
4158 but should never be null here anyway */
4159 pSMB->hdr.Mid = GetNextMid(ses->server);
4160 pSMB->hdr.Tid = ses->ipc_tid;
4161 pSMB->hdr.Uid = ses->Suid;
4162 if (ses->capabilities & CAP_STATUS32)
4163 pSMB->hdr.Flags2 |= SMBFLG2_ERR_STATUS;
4164 if (ses->capabilities & CAP_DFS)
4165 pSMB->hdr.Flags2 |= SMBFLG2_DFS;
4167 if (ses->capabilities & CAP_UNICODE) {
4168 pSMB->hdr.Flags2 |= SMBFLG2_UNICODE;
4170 cifsConvertToUCS((__le16 *) pSMB->RequestFileName,
4171 searchName, PATH_MAX, nls_codepage, remap);
4172 name_len++; /* trailing null */
4174 } else { /* BB improve the check for buffer overruns BB */
4175 name_len = strnlen(searchName, PATH_MAX);
4176 name_len++; /* trailing null */
4177 strncpy(pSMB->RequestFileName, searchName, name_len);
4181 if (ses->server->secMode &
4182 (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
4183 pSMB->hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
4186 pSMB->hdr.Uid = ses->Suid;
4188 params = 2 /* level */ + name_len /*includes null */ ;
4189 pSMB->TotalDataCount = 0;
4190 pSMB->DataCount = 0;
4191 pSMB->DataOffset = 0;
4192 pSMB->MaxParameterCount = 0;
4193 /* BB find exact max SMB PDU from sess structure BB */
4194 pSMB->MaxDataCount = cpu_to_le16(4000);
4195 pSMB->MaxSetupCount = 0;
4199 pSMB->Reserved2 = 0;
4200 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4201 struct smb_com_transaction2_get_dfs_refer_req, MaxReferralLevel) - 4);
4202 pSMB->SetupCount = 1;
4203 pSMB->Reserved3 = 0;
4204 pSMB->SubCommand = cpu_to_le16(TRANS2_GET_DFS_REFERRAL);
4205 byte_count = params + 3 /* pad */ ;
4206 pSMB->ParameterCount = cpu_to_le16(params);
4207 pSMB->TotalParameterCount = pSMB->ParameterCount;
4208 pSMB->MaxReferralLevel = cpu_to_le16(3);
4209 pSMB->hdr.smb_buf_length += byte_count;
4210 pSMB->ByteCount = cpu_to_le16(byte_count);
4212 rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB,
4213 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4215 cFYI(1, "Send error in GetDFSRefer = %d", rc);
4218 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4220 /* BB Also check if enough total bytes returned? */
4221 if (rc || (pSMBr->ByteCount < 17)) {
4222 rc = -EIO; /* bad smb */
4226 cFYI(1, "Decoding GetDFSRefer response BCC: %d Offset %d",
4228 le16_to_cpu(pSMBr->t2.DataOffset));
4230 /* parse returned result into more usable form */
4231 rc = parse_DFS_referrals(pSMBr, num_of_nodes,
4232 target_nodes, nls_codepage, remap,
4236 cifs_buf_release(pSMB);
4244 /* Query File System Info such as free space to old servers such as Win 9x */
4246 SMBOldQFSInfo(const int xid, struct cifsTconInfo *tcon, struct kstatfs *FSData)
4248 /* level 0x01 SMB_QUERY_FILE_SYSTEM_INFO */
4249 TRANSACTION2_QFSI_REQ *pSMB = NULL;
4250 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4251 FILE_SYSTEM_ALLOC_INFO *response_data;
4253 int bytes_returned = 0;
4254 __u16 params, byte_count;
4256 cFYI(1, "OldQFSInfo");
4258 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4263 params = 2; /* level */
4264 pSMB->TotalDataCount = 0;
4265 pSMB->MaxParameterCount = cpu_to_le16(2);
4266 pSMB->MaxDataCount = cpu_to_le16(1000);
4267 pSMB->MaxSetupCount = 0;
4271 pSMB->Reserved2 = 0;
4272 byte_count = params + 1 /* pad */ ;
4273 pSMB->TotalParameterCount = cpu_to_le16(params);
4274 pSMB->ParameterCount = pSMB->TotalParameterCount;
4275 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4276 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4277 pSMB->DataCount = 0;
4278 pSMB->DataOffset = 0;
4279 pSMB->SetupCount = 1;
4280 pSMB->Reserved3 = 0;
4281 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4282 pSMB->InformationLevel = cpu_to_le16(SMB_INFO_ALLOCATION);
4283 pSMB->hdr.smb_buf_length += byte_count;
4284 pSMB->ByteCount = cpu_to_le16(byte_count);
4286 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4287 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4289 cFYI(1, "Send error in QFSInfo = %d", rc);
4290 } else { /* decode response */
4291 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4293 if (rc || (pSMBr->ByteCount < 18))
4294 rc = -EIO; /* bad smb */
4296 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4297 cFYI(1, "qfsinf resp BCC: %d Offset %d",
4298 pSMBr->ByteCount, data_offset);
4300 response_data = (FILE_SYSTEM_ALLOC_INFO *)
4301 (((char *) &pSMBr->hdr.Protocol) + data_offset);
4303 le16_to_cpu(response_data->BytesPerSector) *
4304 le32_to_cpu(response_data->
4305 SectorsPerAllocationUnit);
4307 le32_to_cpu(response_data->TotalAllocationUnits);
4308 FSData->f_bfree = FSData->f_bavail =
4309 le32_to_cpu(response_data->FreeAllocationUnits);
4310 cFYI(1, "Blocks: %lld Free: %lld Block size %ld",
4311 (unsigned long long)FSData->f_blocks,
4312 (unsigned long long)FSData->f_bfree,
4316 cifs_buf_release(pSMB);
4319 goto oldQFSInfoRetry;
4325 CIFSSMBQFSInfo(const int xid, struct cifsTconInfo *tcon, struct kstatfs *FSData)
4327 /* level 0x103 SMB_QUERY_FILE_SYSTEM_INFO */
4328 TRANSACTION2_QFSI_REQ *pSMB = NULL;
4329 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4330 FILE_SYSTEM_INFO *response_data;
4332 int bytes_returned = 0;
4333 __u16 params, byte_count;
4335 cFYI(1, "In QFSInfo");
4337 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4342 params = 2; /* level */
4343 pSMB->TotalDataCount = 0;
4344 pSMB->MaxParameterCount = cpu_to_le16(2);
4345 pSMB->MaxDataCount = cpu_to_le16(1000);
4346 pSMB->MaxSetupCount = 0;
4350 pSMB->Reserved2 = 0;
4351 byte_count = params + 1 /* pad */ ;
4352 pSMB->TotalParameterCount = cpu_to_le16(params);
4353 pSMB->ParameterCount = pSMB->TotalParameterCount;
4354 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4355 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4356 pSMB->DataCount = 0;
4357 pSMB->DataOffset = 0;
4358 pSMB->SetupCount = 1;
4359 pSMB->Reserved3 = 0;
4360 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4361 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_SIZE_INFO);
4362 pSMB->hdr.smb_buf_length += byte_count;
4363 pSMB->ByteCount = cpu_to_le16(byte_count);
4365 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4366 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4368 cFYI(1, "Send error in QFSInfo = %d", rc);
4369 } else { /* decode response */
4370 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4372 if (rc || (pSMBr->ByteCount < 24))
4373 rc = -EIO; /* bad smb */
4375 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4379 *) (((char *) &pSMBr->hdr.Protocol) +
4382 le32_to_cpu(response_data->BytesPerSector) *
4383 le32_to_cpu(response_data->
4384 SectorsPerAllocationUnit);
4386 le64_to_cpu(response_data->TotalAllocationUnits);
4387 FSData->f_bfree = FSData->f_bavail =
4388 le64_to_cpu(response_data->FreeAllocationUnits);
4389 cFYI(1, "Blocks: %lld Free: %lld Block size %ld",
4390 (unsigned long long)FSData->f_blocks,
4391 (unsigned long long)FSData->f_bfree,
4395 cifs_buf_release(pSMB);
4404 CIFSSMBQFSAttributeInfo(const int xid, struct cifsTconInfo *tcon)
4406 /* level 0x105 SMB_QUERY_FILE_SYSTEM_INFO */
4407 TRANSACTION2_QFSI_REQ *pSMB = NULL;
4408 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4409 FILE_SYSTEM_ATTRIBUTE_INFO *response_data;
4411 int bytes_returned = 0;
4412 __u16 params, byte_count;
4414 cFYI(1, "In QFSAttributeInfo");
4416 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4421 params = 2; /* level */
4422 pSMB->TotalDataCount = 0;
4423 pSMB->MaxParameterCount = cpu_to_le16(2);
4424 /* BB find exact max SMB PDU from sess structure BB */
4425 pSMB->MaxDataCount = cpu_to_le16(1000);
4426 pSMB->MaxSetupCount = 0;
4430 pSMB->Reserved2 = 0;
4431 byte_count = params + 1 /* pad */ ;
4432 pSMB->TotalParameterCount = cpu_to_le16(params);
4433 pSMB->ParameterCount = pSMB->TotalParameterCount;
4434 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4435 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4436 pSMB->DataCount = 0;
4437 pSMB->DataOffset = 0;
4438 pSMB->SetupCount = 1;
4439 pSMB->Reserved3 = 0;
4440 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4441 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_ATTRIBUTE_INFO);
4442 pSMB->hdr.smb_buf_length += byte_count;
4443 pSMB->ByteCount = cpu_to_le16(byte_count);
4445 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4446 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4448 cERROR(1, "Send error in QFSAttributeInfo = %d", rc);
4449 } else { /* decode response */
4450 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4452 if (rc || (pSMBr->ByteCount < 13)) {
4453 /* BB also check if enough bytes returned */
4454 rc = -EIO; /* bad smb */
4456 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4458 (FILE_SYSTEM_ATTRIBUTE_INFO
4459 *) (((char *) &pSMBr->hdr.Protocol) +
4461 memcpy(&tcon->fsAttrInfo, response_data,
4462 sizeof(FILE_SYSTEM_ATTRIBUTE_INFO));
4465 cifs_buf_release(pSMB);
4468 goto QFSAttributeRetry;
4474 CIFSSMBQFSDeviceInfo(const int xid, struct cifsTconInfo *tcon)
4476 /* level 0x104 SMB_QUERY_FILE_SYSTEM_INFO */
4477 TRANSACTION2_QFSI_REQ *pSMB = NULL;
4478 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4479 FILE_SYSTEM_DEVICE_INFO *response_data;
4481 int bytes_returned = 0;
4482 __u16 params, byte_count;
4484 cFYI(1, "In QFSDeviceInfo");
4486 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4491 params = 2; /* level */
4492 pSMB->TotalDataCount = 0;
4493 pSMB->MaxParameterCount = cpu_to_le16(2);
4494 /* BB find exact max SMB PDU from sess structure BB */
4495 pSMB->MaxDataCount = cpu_to_le16(1000);
4496 pSMB->MaxSetupCount = 0;
4500 pSMB->Reserved2 = 0;
4501 byte_count = params + 1 /* pad */ ;
4502 pSMB->TotalParameterCount = cpu_to_le16(params);
4503 pSMB->ParameterCount = pSMB->TotalParameterCount;
4504 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4505 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4507 pSMB->DataCount = 0;
4508 pSMB->DataOffset = 0;
4509 pSMB->SetupCount = 1;
4510 pSMB->Reserved3 = 0;
4511 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4512 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_DEVICE_INFO);
4513 pSMB->hdr.smb_buf_length += byte_count;
4514 pSMB->ByteCount = cpu_to_le16(byte_count);
4516 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4517 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4519 cFYI(1, "Send error in QFSDeviceInfo = %d", rc);
4520 } else { /* decode response */
4521 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4523 if (rc || (pSMBr->ByteCount < sizeof(FILE_SYSTEM_DEVICE_INFO)))
4524 rc = -EIO; /* bad smb */
4526 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4528 (FILE_SYSTEM_DEVICE_INFO *)
4529 (((char *) &pSMBr->hdr.Protocol) +
4531 memcpy(&tcon->fsDevInfo, response_data,
4532 sizeof(FILE_SYSTEM_DEVICE_INFO));
4535 cifs_buf_release(pSMB);
4538 goto QFSDeviceRetry;
4544 CIFSSMBQFSUnixInfo(const int xid, struct cifsTconInfo *tcon)
4546 /* level 0x200 SMB_QUERY_CIFS_UNIX_INFO */
4547 TRANSACTION2_QFSI_REQ *pSMB = NULL;
4548 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4549 FILE_SYSTEM_UNIX_INFO *response_data;
4551 int bytes_returned = 0;
4552 __u16 params, byte_count;
4554 cFYI(1, "In QFSUnixInfo");
4556 rc = smb_init_no_reconnect(SMB_COM_TRANSACTION2, 15, tcon,
4557 (void **) &pSMB, (void **) &pSMBr);
4561 params = 2; /* level */
4562 pSMB->TotalDataCount = 0;
4563 pSMB->DataCount = 0;
4564 pSMB->DataOffset = 0;
4565 pSMB->MaxParameterCount = cpu_to_le16(2);
4566 /* BB find exact max SMB PDU from sess structure BB */
4567 pSMB->MaxDataCount = cpu_to_le16(100);
4568 pSMB->MaxSetupCount = 0;
4572 pSMB->Reserved2 = 0;
4573 byte_count = params + 1 /* pad */ ;
4574 pSMB->ParameterCount = cpu_to_le16(params);
4575 pSMB->TotalParameterCount = pSMB->ParameterCount;
4576 pSMB->ParameterOffset = cpu_to_le16(offsetof(struct
4577 smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4578 pSMB->SetupCount = 1;
4579 pSMB->Reserved3 = 0;
4580 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4581 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_CIFS_UNIX_INFO);
4582 pSMB->hdr.smb_buf_length += byte_count;
4583 pSMB->ByteCount = cpu_to_le16(byte_count);
4585 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4586 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4588 cERROR(1, "Send error in QFSUnixInfo = %d", rc);
4589 } else { /* decode response */
4590 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4592 if (rc || (pSMBr->ByteCount < 13)) {
4593 rc = -EIO; /* bad smb */
4595 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4597 (FILE_SYSTEM_UNIX_INFO
4598 *) (((char *) &pSMBr->hdr.Protocol) +
4600 memcpy(&tcon->fsUnixInfo, response_data,
4601 sizeof(FILE_SYSTEM_UNIX_INFO));
4604 cifs_buf_release(pSMB);
4614 CIFSSMBSetFSUnixInfo(const int xid, struct cifsTconInfo *tcon, __u64 cap)
4616 /* level 0x200 SMB_SET_CIFS_UNIX_INFO */
4617 TRANSACTION2_SETFSI_REQ *pSMB = NULL;
4618 TRANSACTION2_SETFSI_RSP *pSMBr = NULL;
4620 int bytes_returned = 0;
4621 __u16 params, param_offset, offset, byte_count;
4623 cFYI(1, "In SETFSUnixInfo");
4625 /* BB switch to small buf init to save memory */
4626 rc = smb_init_no_reconnect(SMB_COM_TRANSACTION2, 15, tcon,
4627 (void **) &pSMB, (void **) &pSMBr);
4631 params = 4; /* 2 bytes zero followed by info level. */
4632 pSMB->MaxSetupCount = 0;
4636 pSMB->Reserved2 = 0;
4637 param_offset = offsetof(struct smb_com_transaction2_setfsi_req, FileNum)
4639 offset = param_offset + params;
4641 pSMB->MaxParameterCount = cpu_to_le16(4);
4642 /* BB find exact max SMB PDU from sess structure BB */
4643 pSMB->MaxDataCount = cpu_to_le16(100);
4644 pSMB->SetupCount = 1;
4645 pSMB->Reserved3 = 0;
4646 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FS_INFORMATION);
4647 byte_count = 1 /* pad */ + params + 12;
4649 pSMB->DataCount = cpu_to_le16(12);
4650 pSMB->ParameterCount = cpu_to_le16(params);
4651 pSMB->TotalDataCount = pSMB->DataCount;
4652 pSMB->TotalParameterCount = pSMB->ParameterCount;
4653 pSMB->ParameterOffset = cpu_to_le16(param_offset);
4654 pSMB->DataOffset = cpu_to_le16(offset);
4658 pSMB->InformationLevel = cpu_to_le16(SMB_SET_CIFS_UNIX_INFO);
4661 pSMB->ClientUnixMajor = cpu_to_le16(CIFS_UNIX_MAJOR_VERSION);
4662 pSMB->ClientUnixMinor = cpu_to_le16(CIFS_UNIX_MINOR_VERSION);
4663 pSMB->ClientUnixCap = cpu_to_le64(cap);
4665 pSMB->hdr.smb_buf_length += byte_count;
4666 pSMB->ByteCount = cpu_to_le16(byte_count);
4668 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4669 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4671 cERROR(1, "Send error in SETFSUnixInfo = %d", rc);
4672 } else { /* decode response */
4673 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4675 rc = -EIO; /* bad smb */
4677 cifs_buf_release(pSMB);
4680 goto SETFSUnixRetry;
4688 CIFSSMBQFSPosixInfo(const int xid, struct cifsTconInfo *tcon,
4689 struct kstatfs *FSData)
4691 /* level 0x201 SMB_QUERY_CIFS_POSIX_INFO */
4692 TRANSACTION2_QFSI_REQ *pSMB = NULL;
4693 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4694 FILE_SYSTEM_POSIX_INFO *response_data;
4696 int bytes_returned = 0;
4697 __u16 params, byte_count;
4699 cFYI(1, "In QFSPosixInfo");
4701 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4706 params = 2; /* level */
4707 pSMB->TotalDataCount = 0;
4708 pSMB->DataCount = 0;
4709 pSMB->DataOffset = 0;
4710 pSMB->MaxParameterCount = cpu_to_le16(2);
4711 /* BB find exact max SMB PDU from sess structure BB */
4712 pSMB->MaxDataCount = cpu_to_le16(100);
4713 pSMB->MaxSetupCount = 0;
4717 pSMB->Reserved2 = 0;
4718 byte_count = params + 1 /* pad */ ;
4719 pSMB->ParameterCount = cpu_to_le16(params);
4720 pSMB->TotalParameterCount = pSMB->ParameterCount;
4721 pSMB->ParameterOffset = cpu_to_le16(offsetof(struct
4722 smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4723 pSMB->SetupCount = 1;
4724 pSMB->Reserved3 = 0;
4725 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4726 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_POSIX_FS_INFO);
4727 pSMB->hdr.smb_buf_length += byte_count;
4728 pSMB->ByteCount = cpu_to_le16(byte_count);
4730 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4731 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4733 cFYI(1, "Send error in QFSUnixInfo = %d", rc);
4734 } else { /* decode response */
4735 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4737 if (rc || (pSMBr->ByteCount < 13)) {
4738 rc = -EIO; /* bad smb */
4740 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4742 (FILE_SYSTEM_POSIX_INFO
4743 *) (((char *) &pSMBr->hdr.Protocol) +
4746 le32_to_cpu(response_data->BlockSize);
4748 le64_to_cpu(response_data->TotalBlocks);
4750 le64_to_cpu(response_data->BlocksAvail);
4751 if (response_data->UserBlocksAvail == cpu_to_le64(-1)) {
4752 FSData->f_bavail = FSData->f_bfree;
4755 le64_to_cpu(response_data->UserBlocksAvail);
4757 if (response_data->TotalFileNodes != cpu_to_le64(-1))
4759 le64_to_cpu(response_data->TotalFileNodes);
4760 if (response_data->FreeFileNodes != cpu_to_le64(-1))
4762 le64_to_cpu(response_data->FreeFileNodes);
4765 cifs_buf_release(pSMB);
4774 /* We can not use write of zero bytes trick to
4775 set file size due to need for large file support. Also note that
4776 this SetPathInfo is preferred to SetFileInfo based method in next
4777 routine which is only needed to work around a sharing violation bug
4778 in Samba which this routine can run into */
4781 CIFSSMBSetEOF(const int xid, struct cifsTconInfo *tcon, const char *fileName,
4782 __u64 size, bool SetAllocation,
4783 const struct nls_table *nls_codepage, int remap)
4785 struct smb_com_transaction2_spi_req *pSMB = NULL;
4786 struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
4787 struct file_end_of_file_info *parm_data;
4790 int bytes_returned = 0;
4791 __u16 params, byte_count, data_count, param_offset, offset;
4793 cFYI(1, "In SetEOF");
4795 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4800 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4802 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
4803 PATH_MAX, nls_codepage, remap);
4804 name_len++; /* trailing null */
4806 } else { /* BB improve the check for buffer overruns BB */
4807 name_len = strnlen(fileName, PATH_MAX);
4808 name_len++; /* trailing null */
4809 strncpy(pSMB->FileName, fileName, name_len);
4811 params = 6 + name_len;
4812 data_count = sizeof(struct file_end_of_file_info);
4813 pSMB->MaxParameterCount = cpu_to_le16(2);
4814 pSMB->MaxDataCount = cpu_to_le16(4100);
4815 pSMB->MaxSetupCount = 0;
4819 pSMB->Reserved2 = 0;
4820 param_offset = offsetof(struct smb_com_transaction2_spi_req,
4821 InformationLevel) - 4;
4822 offset = param_offset + params;
4823 if (SetAllocation) {
4824 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
4825 pSMB->InformationLevel =
4826 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2);
4828 pSMB->InformationLevel =
4829 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO);
4830 } else /* Set File Size */ {
4831 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
4832 pSMB->InformationLevel =
4833 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO2);
4835 pSMB->InformationLevel =
4836 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO);
4840 (struct file_end_of_file_info *) (((char *) &pSMB->hdr.Protocol) +
4842 pSMB->ParameterOffset = cpu_to_le16(param_offset);
4843 pSMB->DataOffset = cpu_to_le16(offset);
4844 pSMB->SetupCount = 1;
4845 pSMB->Reserved3 = 0;
4846 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
4847 byte_count = 3 /* pad */ + params + data_count;
4848 pSMB->DataCount = cpu_to_le16(data_count);
4849 pSMB->TotalDataCount = pSMB->DataCount;
4850 pSMB->ParameterCount = cpu_to_le16(params);
4851 pSMB->TotalParameterCount = pSMB->ParameterCount;
4852 pSMB->Reserved4 = 0;
4853 pSMB->hdr.smb_buf_length += byte_count;
4854 parm_data->FileSize = cpu_to_le64(size);
4855 pSMB->ByteCount = cpu_to_le16(byte_count);
4856 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4857 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4859 cFYI(1, "SetPathInfo (file size) returned %d", rc);
4861 cifs_buf_release(pSMB);
4870 CIFSSMBSetFileSize(const int xid, struct cifsTconInfo *tcon, __u64 size,
4871 __u16 fid, __u32 pid_of_opener, bool SetAllocation)
4873 struct smb_com_transaction2_sfi_req *pSMB = NULL;
4875 struct file_end_of_file_info *parm_data;
4877 __u16 params, param_offset, offset, byte_count, count;
4879 cFYI(1, "SetFileSize (via SetFileInfo) %lld",
4881 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
4886 pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
4887 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));
4890 pSMB->MaxSetupCount = 0;
4894 pSMB->Reserved2 = 0;
4895 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
4896 offset = param_offset + params;
4898 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
4900 count = sizeof(struct file_end_of_file_info);
4901 pSMB->MaxParameterCount = cpu_to_le16(2);
4902 /* BB find exact max SMB PDU from sess structure BB */
4903 pSMB->MaxDataCount = cpu_to_le16(1000);
4904 pSMB->SetupCount = 1;
4905 pSMB->Reserved3 = 0;
4906 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
4907 byte_count = 3 /* pad */ + params + count;
4908 pSMB->DataCount = cpu_to_le16(count);
4909 pSMB->ParameterCount = cpu_to_le16(params);
4910 pSMB->TotalDataCount = pSMB->DataCount;
4911 pSMB->TotalParameterCount = pSMB->ParameterCount;
4912 pSMB->ParameterOffset = cpu_to_le16(param_offset);
4914 (struct file_end_of_file_info *) (((char *) &pSMB->hdr.Protocol)
4916 pSMB->DataOffset = cpu_to_le16(offset);
4917 parm_data->FileSize = cpu_to_le64(size);
4919 if (SetAllocation) {
4920 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
4921 pSMB->InformationLevel =
4922 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2);
4924 pSMB->InformationLevel =
4925 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO);
4926 } else /* Set File Size */ {
4927 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
4928 pSMB->InformationLevel =
4929 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO2);
4931 pSMB->InformationLevel =
4932 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO);
4934 pSMB->Reserved4 = 0;
4935 pSMB->hdr.smb_buf_length += byte_count;
4936 pSMB->ByteCount = cpu_to_le16(byte_count);
4937 rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0);
4939 cFYI(1, "Send error in SetFileInfo (SetFileSize) = %d", rc);
4942 /* Note: On -EAGAIN error only caller can retry on handle based calls
4943 since file handle passed in no longer valid */
4948 /* Some legacy servers such as NT4 require that the file times be set on
4949 an open handle, rather than by pathname - this is awkward due to
4950 potential access conflicts on the open, but it is unavoidable for these
4951 old servers since the only other choice is to go from 100 nanosecond DCE
4952 time and resort to the original setpathinfo level which takes the ancient
4953 DOS time format with 2 second granularity */
4955 CIFSSMBSetFileInfo(const int xid, struct cifsTconInfo *tcon,
4956 const FILE_BASIC_INFO *data, __u16 fid, __u32 pid_of_opener)
4958 struct smb_com_transaction2_sfi_req *pSMB = NULL;
4961 __u16 params, param_offset, offset, byte_count, count;
4963 cFYI(1, "Set Times (via SetFileInfo)");
4964 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
4969 pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
4970 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));
4973 pSMB->MaxSetupCount = 0;
4977 pSMB->Reserved2 = 0;
4978 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
4979 offset = param_offset + params;
4981 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
4983 count = sizeof(FILE_BASIC_INFO);
4984 pSMB->MaxParameterCount = cpu_to_le16(2);
4985 /* BB find max SMB PDU from sess */
4986 pSMB->MaxDataCount = cpu_to_le16(1000);
4987 pSMB->SetupCount = 1;
4988 pSMB->Reserved3 = 0;
4989 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
4990 byte_count = 3 /* pad */ + params + count;
4991 pSMB->DataCount = cpu_to_le16(count);
4992 pSMB->ParameterCount = cpu_to_le16(params);
4993 pSMB->TotalDataCount = pSMB->DataCount;
4994 pSMB->TotalParameterCount = pSMB->ParameterCount;
4995 pSMB->ParameterOffset = cpu_to_le16(param_offset);
4996 pSMB->DataOffset = cpu_to_le16(offset);
4998 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
4999 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO2);
5001 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO);
5002 pSMB->Reserved4 = 0;
5003 pSMB->hdr.smb_buf_length += byte_count;
5004 pSMB->ByteCount = cpu_to_le16(byte_count);
5005 memcpy(data_offset, data, sizeof(FILE_BASIC_INFO));
5006 rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0);
5008 cFYI(1, "Send error in Set Time (SetFileInfo) = %d", rc);
5010 /* Note: On -EAGAIN error only caller can retry on handle based calls
5011 since file handle passed in no longer valid */
5017 CIFSSMBSetFileDisposition(const int xid, struct cifsTconInfo *tcon,
5018 bool delete_file, __u16 fid, __u32 pid_of_opener)
5020 struct smb_com_transaction2_sfi_req *pSMB = NULL;
5023 __u16 params, param_offset, offset, byte_count, count;
5025 cFYI(1, "Set File Disposition (via SetFileInfo)");
5026 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
5031 pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
5032 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));
5035 pSMB->MaxSetupCount = 0;
5039 pSMB->Reserved2 = 0;
5040 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
5041 offset = param_offset + params;
5043 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
5046 pSMB->MaxParameterCount = cpu_to_le16(2);
5047 /* BB find max SMB PDU from sess */
5048 pSMB->MaxDataCount = cpu_to_le16(1000);
5049 pSMB->SetupCount = 1;
5050 pSMB->Reserved3 = 0;
5051 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
5052 byte_count = 3 /* pad */ + params + count;
5053 pSMB->DataCount = cpu_to_le16(count);
5054 pSMB->ParameterCount = cpu_to_le16(params);
5055 pSMB->TotalDataCount = pSMB->DataCount;
5056 pSMB->TotalParameterCount = pSMB->ParameterCount;
5057 pSMB->ParameterOffset = cpu_to_le16(param_offset);
5058 pSMB->DataOffset = cpu_to_le16(offset);
5060 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_DISPOSITION_INFO);
5061 pSMB->Reserved4 = 0;
5062 pSMB->hdr.smb_buf_length += byte_count;
5063 pSMB->ByteCount = cpu_to_le16(byte_count);
5064 *data_offset = delete_file ? 1 : 0;
5065 rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0);
5067 cFYI(1, "Send error in SetFileDisposition = %d", rc);
5073 CIFSSMBSetPathInfo(const int xid, struct cifsTconInfo *tcon,
5074 const char *fileName, const FILE_BASIC_INFO *data,
5075 const struct nls_table *nls_codepage, int remap)
5077 TRANSACTION2_SPI_REQ *pSMB = NULL;
5078 TRANSACTION2_SPI_RSP *pSMBr = NULL;
5081 int bytes_returned = 0;
5083 __u16 params, param_offset, offset, byte_count, count;
5085 cFYI(1, "In SetTimes");
5088 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5093 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5095 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
5096 PATH_MAX, nls_codepage, remap);
5097 name_len++; /* trailing null */
5099 } else { /* BB improve the check for buffer overruns BB */
5100 name_len = strnlen(fileName, PATH_MAX);
5101 name_len++; /* trailing null */
5102 strncpy(pSMB->FileName, fileName, name_len);
5105 params = 6 + name_len;
5106 count = sizeof(FILE_BASIC_INFO);
5107 pSMB->MaxParameterCount = cpu_to_le16(2);
5108 /* BB find max SMB PDU from sess structure BB */
5109 pSMB->MaxDataCount = cpu_to_le16(1000);
5110 pSMB->MaxSetupCount = 0;
5114 pSMB->Reserved2 = 0;
5115 param_offset = offsetof(struct smb_com_transaction2_spi_req,
5116 InformationLevel) - 4;
5117 offset = param_offset + params;
5118 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
5119 pSMB->ParameterOffset = cpu_to_le16(param_offset);
5120 pSMB->DataOffset = cpu_to_le16(offset);
5121 pSMB->SetupCount = 1;
5122 pSMB->Reserved3 = 0;
5123 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
5124 byte_count = 3 /* pad */ + params + count;
5126 pSMB->DataCount = cpu_to_le16(count);
5127 pSMB->ParameterCount = cpu_to_le16(params);
5128 pSMB->TotalDataCount = pSMB->DataCount;
5129 pSMB->TotalParameterCount = pSMB->ParameterCount;
5130 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
5131 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO2);
5133 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO);
5134 pSMB->Reserved4 = 0;
5135 pSMB->hdr.smb_buf_length += byte_count;
5136 memcpy(data_offset, data, sizeof(FILE_BASIC_INFO));
5137 pSMB->ByteCount = cpu_to_le16(byte_count);
5138 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5139 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5141 cFYI(1, "SetPathInfo (times) returned %d", rc);
5143 cifs_buf_release(pSMB);
5151 /* Can not be used to set time stamps yet (due to old DOS time format) */
5152 /* Can be used to set attributes */
5153 #if 0 /* Possibly not needed - since it turns out that strangely NT4 has a bug
5154 handling it anyway and NT4 was what we thought it would be needed for
5155 Do not delete it until we prove whether needed for Win9x though */
5157 CIFSSMBSetAttrLegacy(int xid, struct cifsTconInfo *tcon, char *fileName,
5158 __u16 dos_attrs, const struct nls_table *nls_codepage)
5160 SETATTR_REQ *pSMB = NULL;
5161 SETATTR_RSP *pSMBr = NULL;
5166 cFYI(1, "In SetAttrLegacy");
5169 rc = smb_init(SMB_COM_SETATTR, 8, tcon, (void **) &pSMB,
5174 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5176 ConvertToUCS((__le16 *) pSMB->fileName, fileName,
5177 PATH_MAX, nls_codepage);
5178 name_len++; /* trailing null */
5180 } else { /* BB improve the check for buffer overruns BB */
5181 name_len = strnlen(fileName, PATH_MAX);
5182 name_len++; /* trailing null */
5183 strncpy(pSMB->fileName, fileName, name_len);
5185 pSMB->attr = cpu_to_le16(dos_attrs);
5186 pSMB->BufferFormat = 0x04;
5187 pSMB->hdr.smb_buf_length += name_len + 1;
5188 pSMB->ByteCount = cpu_to_le16(name_len + 1);
5189 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5190 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5192 cFYI(1, "Error in LegacySetAttr = %d", rc);
5194 cifs_buf_release(pSMB);
5197 goto SetAttrLgcyRetry;
5201 #endif /* temporarily unneeded SetAttr legacy function */
5204 cifs_fill_unix_set_info(FILE_UNIX_BASIC_INFO *data_offset,
5205 const struct cifs_unix_set_info_args *args)
5207 u64 mode = args->mode;
5210 * Samba server ignores set of file size to zero due to bugs in some
5211 * older clients, but we should be precise - we use SetFileSize to
5212 * set file size and do not want to truncate file size to zero
5213 * accidently as happened on one Samba server beta by putting
5214 * zero instead of -1 here
5216 data_offset->EndOfFile = cpu_to_le64(NO_CHANGE_64);
5217 data_offset->NumOfBytes = cpu_to_le64(NO_CHANGE_64);
5218 data_offset->LastStatusChange = cpu_to_le64(args->ctime);
5219 data_offset->LastAccessTime = cpu_to_le64(args->atime);
5220 data_offset->LastModificationTime = cpu_to_le64(args->mtime);
5221 data_offset->Uid = cpu_to_le64(args->uid);
5222 data_offset->Gid = cpu_to_le64(args->gid);
5223 /* better to leave device as zero when it is */
5224 data_offset->DevMajor = cpu_to_le64(MAJOR(args->device));
5225 data_offset->DevMinor = cpu_to_le64(MINOR(args->device));
5226 data_offset->Permissions = cpu_to_le64(mode);
5229 data_offset->Type = cpu_to_le32(UNIX_FILE);
5230 else if (S_ISDIR(mode))
5231 data_offset->Type = cpu_to_le32(UNIX_DIR);
5232 else if (S_ISLNK(mode))
5233 data_offset->Type = cpu_to_le32(UNIX_SYMLINK);
5234 else if (S_ISCHR(mode))
5235 data_offset->Type = cpu_to_le32(UNIX_CHARDEV);
5236 else if (S_ISBLK(mode))
5237 data_offset->Type = cpu_to_le32(UNIX_BLOCKDEV);
5238 else if (S_ISFIFO(mode))
5239 data_offset->Type = cpu_to_le32(UNIX_FIFO);
5240 else if (S_ISSOCK(mode))
5241 data_offset->Type = cpu_to_le32(UNIX_SOCKET);
5245 CIFSSMBUnixSetFileInfo(const int xid, struct cifsTconInfo *tcon,
5246 const struct cifs_unix_set_info_args *args,
5247 u16 fid, u32 pid_of_opener)
5249 struct smb_com_transaction2_sfi_req *pSMB = NULL;
5250 FILE_UNIX_BASIC_INFO *data_offset;
5252 u16 params, param_offset, offset, byte_count, count;
5254 cFYI(1, "Set Unix Info (via SetFileInfo)");
5255 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
5260 pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
5261 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));
5264 pSMB->MaxSetupCount = 0;
5268 pSMB->Reserved2 = 0;
5269 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
5270 offset = param_offset + params;
5272 data_offset = (FILE_UNIX_BASIC_INFO *)
5273 ((char *)(&pSMB->hdr.Protocol) + offset);
5274 count = sizeof(FILE_UNIX_BASIC_INFO);
5276 pSMB->MaxParameterCount = cpu_to_le16(2);
5277 /* BB find max SMB PDU from sess */
5278 pSMB->MaxDataCount = cpu_to_le16(1000);
5279 pSMB->SetupCount = 1;
5280 pSMB->Reserved3 = 0;
5281 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
5282 byte_count = 3 /* pad */ + params + count;
5283 pSMB->DataCount = cpu_to_le16(count);
5284 pSMB->ParameterCount = cpu_to_le16(params);
5285 pSMB->TotalDataCount = pSMB->DataCount;
5286 pSMB->TotalParameterCount = pSMB->ParameterCount;
5287 pSMB->ParameterOffset = cpu_to_le16(param_offset);
5288 pSMB->DataOffset = cpu_to_le16(offset);
5290 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_BASIC);
5291 pSMB->Reserved4 = 0;
5292 pSMB->hdr.smb_buf_length += byte_count;
5293 pSMB->ByteCount = cpu_to_le16(byte_count);
5295 cifs_fill_unix_set_info(data_offset, args);
5297 rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0);
5299 cFYI(1, "Send error in Set Time (SetFileInfo) = %d", rc);
5301 /* Note: On -EAGAIN error only caller can retry on handle based calls
5302 since file handle passed in no longer valid */
5308 CIFSSMBUnixSetPathInfo(const int xid, struct cifsTconInfo *tcon, char *fileName,
5309 const struct cifs_unix_set_info_args *args,
5310 const struct nls_table *nls_codepage, int remap)
5312 TRANSACTION2_SPI_REQ *pSMB = NULL;
5313 TRANSACTION2_SPI_RSP *pSMBr = NULL;
5316 int bytes_returned = 0;
5317 FILE_UNIX_BASIC_INFO *data_offset;
5318 __u16 params, param_offset, offset, count, byte_count;
5320 cFYI(1, "In SetUID/GID/Mode");
5322 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5327 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5329 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
5330 PATH_MAX, nls_codepage, remap);
5331 name_len++; /* trailing null */
5333 } else { /* BB improve the check for buffer overruns BB */
5334 name_len = strnlen(fileName, PATH_MAX);
5335 name_len++; /* trailing null */
5336 strncpy(pSMB->FileName, fileName, name_len);
5339 params = 6 + name_len;
5340 count = sizeof(FILE_UNIX_BASIC_INFO);
5341 pSMB->MaxParameterCount = cpu_to_le16(2);
5342 /* BB find max SMB PDU from sess structure BB */
5343 pSMB->MaxDataCount = cpu_to_le16(1000);
5344 pSMB->MaxSetupCount = 0;
5348 pSMB->Reserved2 = 0;
5349 param_offset = offsetof(struct smb_com_transaction2_spi_req,
5350 InformationLevel) - 4;
5351 offset = param_offset + params;
5353 (FILE_UNIX_BASIC_INFO *) ((char *) &pSMB->hdr.Protocol +
5355 memset(data_offset, 0, count);
5356 pSMB->DataOffset = cpu_to_le16(offset);
5357 pSMB->ParameterOffset = cpu_to_le16(param_offset);
5358 pSMB->SetupCount = 1;
5359 pSMB->Reserved3 = 0;
5360 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
5361 byte_count = 3 /* pad */ + params + count;
5362 pSMB->ParameterCount = cpu_to_le16(params);
5363 pSMB->DataCount = cpu_to_le16(count);
5364 pSMB->TotalParameterCount = pSMB->ParameterCount;
5365 pSMB->TotalDataCount = pSMB->DataCount;
5366 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_BASIC);
5367 pSMB->Reserved4 = 0;
5368 pSMB->hdr.smb_buf_length += byte_count;
5370 cifs_fill_unix_set_info(data_offset, args);
5372 pSMB->ByteCount = cpu_to_le16(byte_count);
5373 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5374 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5376 cFYI(1, "SetPathInfo (perms) returned %d", rc);
5378 cifs_buf_release(pSMB);
5384 int CIFSSMBNotify(const int xid, struct cifsTconInfo *tcon,
5385 const int notify_subdirs, const __u16 netfid,
5386 __u32 filter, struct file *pfile, int multishot,
5387 const struct nls_table *nls_codepage)
5390 struct smb_com_transaction_change_notify_req *pSMB = NULL;
5391 struct smb_com_ntransaction_change_notify_rsp *pSMBr = NULL;
5392 struct dir_notify_req *dnotify_req;
5395 cFYI(1, "In CIFSSMBNotify for file handle %d", (int)netfid);
5396 rc = smb_init(SMB_COM_NT_TRANSACT, 23, tcon, (void **) &pSMB,
5401 pSMB->TotalParameterCount = 0 ;
5402 pSMB->TotalDataCount = 0;
5403 pSMB->MaxParameterCount = cpu_to_le32(2);
5404 /* BB find exact data count max from sess structure BB */
5405 pSMB->MaxDataCount = 0; /* same in little endian or be */
5406 /* BB VERIFY verify which is correct for above BB */
5407 pSMB->MaxDataCount = cpu_to_le32((tcon->ses->server->maxBuf -
5408 MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
5410 pSMB->MaxSetupCount = 4;
5412 pSMB->ParameterOffset = 0;
5413 pSMB->DataCount = 0;
5414 pSMB->DataOffset = 0;
5415 pSMB->SetupCount = 4; /* single byte does not need le conversion */
5416 pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_NOTIFY_CHANGE);
5417 pSMB->ParameterCount = pSMB->TotalParameterCount;
5419 pSMB->WatchTree = 1; /* one byte - no le conversion needed */
5420 pSMB->Reserved2 = 0;
5421 pSMB->CompletionFilter = cpu_to_le32(filter);
5422 pSMB->Fid = netfid; /* file handle always le */
5423 pSMB->ByteCount = 0;
5425 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5426 (struct smb_hdr *)pSMBr, &bytes_returned,
5429 cFYI(1, "Error in Notify = %d", rc);
5431 /* Add file to outstanding requests */
5432 /* BB change to kmem cache alloc */
5433 dnotify_req = kmalloc(
5434 sizeof(struct dir_notify_req),
5437 dnotify_req->Pid = pSMB->hdr.Pid;
5438 dnotify_req->PidHigh = pSMB->hdr.PidHigh;
5439 dnotify_req->Mid = pSMB->hdr.Mid;
5440 dnotify_req->Tid = pSMB->hdr.Tid;
5441 dnotify_req->Uid = pSMB->hdr.Uid;
5442 dnotify_req->netfid = netfid;
5443 dnotify_req->pfile = pfile;
5444 dnotify_req->filter = filter;
5445 dnotify_req->multishot = multishot;
5446 spin_lock(&GlobalMid_Lock);
5447 list_add_tail(&dnotify_req->lhead,
5448 &GlobalDnotifyReqList);
5449 spin_unlock(&GlobalMid_Lock);
5453 cifs_buf_release(pSMB);
5457 #ifdef CONFIG_CIFS_XATTR
5459 * Do a path-based QUERY_ALL_EAS call and parse the result. This is a common
5460 * function used by listxattr and getxattr type calls. When ea_name is set,
5461 * it looks for that attribute name and stuffs that value into the EAData
5462 * buffer. When ea_name is NULL, it stuffs a list of attribute names into the
5463 * buffer. In both cases, the return value is either the length of the
5464 * resulting data or a negative error code. If EAData is a NULL pointer then
5465 * the data isn't copied to it, but the length is returned.
5468 CIFSSMBQAllEAs(const int xid, struct cifsTconInfo *tcon,
5469 const unsigned char *searchName, const unsigned char *ea_name,
5470 char *EAData, size_t buf_size,
5471 const struct nls_table *nls_codepage, int remap)
5473 /* BB assumes one setup word */
5474 TRANSACTION2_QPI_REQ *pSMB = NULL;
5475 TRANSACTION2_QPI_RSP *pSMBr = NULL;
5479 struct fealist *ea_response_data;
5480 struct fea *temp_fea;
5483 __u16 params, byte_count, data_offset;
5485 cFYI(1, "In Query All EAs path %s", searchName);
5487 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5492 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5494 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
5495 PATH_MAX, nls_codepage, remap);
5496 list_len++; /* trailing null */
5498 } else { /* BB improve the check for buffer overruns BB */
5499 list_len = strnlen(searchName, PATH_MAX);
5500 list_len++; /* trailing null */
5501 strncpy(pSMB->FileName, searchName, list_len);
5504 params = 2 /* level */ + 4 /* reserved */ + list_len /* includes NUL */;
5505 pSMB->TotalDataCount = 0;
5506 pSMB->MaxParameterCount = cpu_to_le16(2);
5507 /* BB find exact max SMB PDU from sess structure BB */
5508 pSMB->MaxDataCount = cpu_to_le16(CIFSMaxBufSize);
5509 pSMB->MaxSetupCount = 0;
5513 pSMB->Reserved2 = 0;
5514 pSMB->ParameterOffset = cpu_to_le16(offsetof(
5515 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
5516 pSMB->DataCount = 0;
5517 pSMB->DataOffset = 0;
5518 pSMB->SetupCount = 1;
5519 pSMB->Reserved3 = 0;
5520 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
5521 byte_count = params + 1 /* pad */ ;
5522 pSMB->TotalParameterCount = cpu_to_le16(params);
5523 pSMB->ParameterCount = pSMB->TotalParameterCount;
5524 pSMB->InformationLevel = cpu_to_le16(SMB_INFO_QUERY_ALL_EAS);
5525 pSMB->Reserved4 = 0;
5526 pSMB->hdr.smb_buf_length += byte_count;
5527 pSMB->ByteCount = cpu_to_le16(byte_count);
5529 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5530 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5532 cFYI(1, "Send error in QueryAllEAs = %d", rc);
5537 /* BB also check enough total bytes returned */
5538 /* BB we need to improve the validity checking
5539 of these trans2 responses */
5541 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
5542 if (rc || (pSMBr->ByteCount < 4)) {
5543 rc = -EIO; /* bad smb */
5547 /* check that length of list is not more than bcc */
5548 /* check that each entry does not go beyond length
5550 /* check that each element of each entry does not
5551 go beyond end of list */
5552 /* validate_trans2_offsets() */
5553 /* BB check if start of smb + data_offset > &bcc+ bcc */
5555 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
5556 ea_response_data = (struct fealist *)
5557 (((char *) &pSMBr->hdr.Protocol) + data_offset);
5559 list_len = le32_to_cpu(ea_response_data->list_len);
5560 cFYI(1, "ea length %d", list_len);
5561 if (list_len <= 8) {
5562 cFYI(1, "empty EA list returned from server");
5566 /* make sure list_len doesn't go past end of SMB */
5567 end_of_smb = (char *)pByteArea(&pSMBr->hdr) + BCC(&pSMBr->hdr);
5568 if ((char *)ea_response_data + list_len > end_of_smb) {
5569 cFYI(1, "EA list appears to go beyond SMB");
5574 /* account for ea list len */
5576 temp_fea = ea_response_data->list;
5577 temp_ptr = (char *)temp_fea;
5578 while (list_len > 0) {
5579 unsigned int name_len;
5584 /* make sure we can read name_len and value_len */
5586 cFYI(1, "EA entry goes beyond length of list");
5591 name_len = temp_fea->name_len;
5592 value_len = le16_to_cpu(temp_fea->value_len);
5593 list_len -= name_len + 1 + value_len;
5595 cFYI(1, "EA entry goes beyond length of list");
5601 if (strncmp(ea_name, temp_ptr, name_len) == 0) {
5602 temp_ptr += name_len + 1;
5606 if ((size_t)value_len > buf_size) {
5610 memcpy(EAData, temp_ptr, value_len);
5614 /* account for prefix user. and trailing null */
5615 rc += (5 + 1 + name_len);
5616 if (rc < (int) buf_size) {
5617 memcpy(EAData, "user.", 5);
5619 memcpy(EAData, temp_ptr, name_len);
5621 /* null terminate name */
5624 } else if (buf_size == 0) {
5625 /* skip copy - calc size only */
5627 /* stop before overrun buffer */
5632 temp_ptr += name_len + 1 + value_len;
5633 temp_fea = (struct fea *)temp_ptr;
5636 /* didn't find the named attribute */
5641 cifs_buf_release(pSMB);
5649 CIFSSMBSetEA(const int xid, struct cifsTconInfo *tcon, const char *fileName,
5650 const char *ea_name, const void *ea_value,
5651 const __u16 ea_value_len, const struct nls_table *nls_codepage,
5654 struct smb_com_transaction2_spi_req *pSMB = NULL;
5655 struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
5656 struct fealist *parm_data;
5659 int bytes_returned = 0;
5660 __u16 params, param_offset, byte_count, offset, count;
5662 cFYI(1, "In SetEA");
5664 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5669 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5671 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
5672 PATH_MAX, nls_codepage, remap);
5673 name_len++; /* trailing null */
5675 } else { /* BB improve the check for buffer overruns BB */
5676 name_len = strnlen(fileName, PATH_MAX);
5677 name_len++; /* trailing null */
5678 strncpy(pSMB->FileName, fileName, name_len);
5681 params = 6 + name_len;
5683 /* done calculating parms using name_len of file name,
5684 now use name_len to calculate length of ea name
5685 we are going to create in the inode xattrs */
5686 if (ea_name == NULL)
5689 name_len = strnlen(ea_name, 255);
5691 count = sizeof(*parm_data) + ea_value_len + name_len;
5692 pSMB->MaxParameterCount = cpu_to_le16(2);
5693 /* BB find max SMB PDU from sess */
5694 pSMB->MaxDataCount = cpu_to_le16(1000);
5695 pSMB->MaxSetupCount = 0;
5699 pSMB->Reserved2 = 0;
5700 param_offset = offsetof(struct smb_com_transaction2_spi_req,
5701 InformationLevel) - 4;
5702 offset = param_offset + params;
5703 pSMB->InformationLevel =
5704 cpu_to_le16(SMB_SET_FILE_EA);
5707 (struct fealist *) (((char *) &pSMB->hdr.Protocol) +
5709 pSMB->ParameterOffset = cpu_to_le16(param_offset);
5710 pSMB->DataOffset = cpu_to_le16(offset);
5711 pSMB->SetupCount = 1;
5712 pSMB->Reserved3 = 0;
5713 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
5714 byte_count = 3 /* pad */ + params + count;
5715 pSMB->DataCount = cpu_to_le16(count);
5716 parm_data->list_len = cpu_to_le32(count);
5717 parm_data->list[0].EA_flags = 0;
5718 /* we checked above that name len is less than 255 */
5719 parm_data->list[0].name_len = (__u8)name_len;
5720 /* EA names are always ASCII */
5722 strncpy(parm_data->list[0].name, ea_name, name_len);
5723 parm_data->list[0].name[name_len] = 0;
5724 parm_data->list[0].value_len = cpu_to_le16(ea_value_len);
5725 /* caller ensures that ea_value_len is less than 64K but
5726 we need to ensure that it fits within the smb */
5728 /*BB add length check to see if it would fit in
5729 negotiated SMB buffer size BB */
5730 /* if (ea_value_len > buffer_size - 512 (enough for header)) */
5732 memcpy(parm_data->list[0].name+name_len+1,
5733 ea_value, ea_value_len);
5735 pSMB->TotalDataCount = pSMB->DataCount;
5736 pSMB->ParameterCount = cpu_to_le16(params);
5737 pSMB->TotalParameterCount = pSMB->ParameterCount;
5738 pSMB->Reserved4 = 0;
5739 pSMB->hdr.smb_buf_length += byte_count;
5740 pSMB->ByteCount = cpu_to_le16(byte_count);
5741 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5742 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5744 cFYI(1, "SetPathInfo (EA) returned %d", rc);
5746 cifs_buf_release(pSMB);