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, const bool waitFlag)
1669 LOCK_REQ *pSMB = NULL;
1670 /* LOCK_RSP *pSMBr = NULL; */ /* No response data other than rc to parse */
1675 cFYI(1, "CIFSSMBLock timeout %d numLock %d", (int)waitFlag, numLock);
1676 rc = small_smb_init(SMB_COM_LOCKING_ANDX, 8, tcon, (void **) &pSMB);
1681 if (lockType == LOCKING_ANDX_OPLOCK_RELEASE) {
1682 timeout = CIFS_ASYNC_OP; /* no response expected */
1684 } else if (waitFlag) {
1685 timeout = CIFS_BLOCKING_OP; /* blocking operation, no timeout */
1686 pSMB->Timeout = cpu_to_le32(-1);/* blocking - do not time out */
1691 pSMB->NumberOfLocks = cpu_to_le16(numLock);
1692 pSMB->NumberOfUnlocks = cpu_to_le16(numUnlock);
1693 pSMB->LockType = lockType;
1694 pSMB->AndXCommand = 0xFF; /* none */
1695 pSMB->Fid = smb_file_id; /* netfid stays le */
1697 if ((numLock != 0) || (numUnlock != 0)) {
1698 pSMB->Locks[0].Pid = cpu_to_le16(current->tgid);
1699 /* BB where to store pid high? */
1700 pSMB->Locks[0].LengthLow = cpu_to_le32((u32)len);
1701 pSMB->Locks[0].LengthHigh = cpu_to_le32((u32)(len>>32));
1702 pSMB->Locks[0].OffsetLow = cpu_to_le32((u32)offset);
1703 pSMB->Locks[0].OffsetHigh = cpu_to_le32((u32)(offset>>32));
1704 count = sizeof(LOCKING_ANDX_RANGE);
1709 pSMB->hdr.smb_buf_length += count;
1710 pSMB->ByteCount = cpu_to_le16(count);
1713 rc = SendReceiveBlockingLock(xid, tcon, (struct smb_hdr *) pSMB,
1714 (struct smb_hdr *) pSMB, &bytes_returned);
1715 cifs_small_buf_release(pSMB);
1717 rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *)pSMB,
1719 /* SMB buffer freed by function above */
1721 cifs_stats_inc(&tcon->num_locks);
1723 cFYI(1, "Send error in Lock = %d", rc);
1725 /* Note: On -EAGAIN error only caller can retry on handle based calls
1726 since file handle passed in no longer valid */
1731 CIFSSMBPosixLock(const int xid, struct cifsTconInfo *tcon,
1732 const __u16 smb_file_id, const int get_flag, const __u64 len,
1733 struct file_lock *pLockData, const __u16 lock_type,
1734 const bool waitFlag)
1736 struct smb_com_transaction2_sfi_req *pSMB = NULL;
1737 struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
1738 struct cifs_posix_lock *parm_data;
1741 int bytes_returned = 0;
1742 int resp_buf_type = 0;
1743 __u16 params, param_offset, offset, byte_count, count;
1746 cFYI(1, "Posix Lock");
1748 if (pLockData == NULL)
1751 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
1756 pSMBr = (struct smb_com_transaction2_sfi_rsp *)pSMB;
1759 pSMB->MaxSetupCount = 0;
1762 pSMB->Reserved2 = 0;
1763 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
1764 offset = param_offset + params;
1766 count = sizeof(struct cifs_posix_lock);
1767 pSMB->MaxParameterCount = cpu_to_le16(2);
1768 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB from sess */
1769 pSMB->SetupCount = 1;
1770 pSMB->Reserved3 = 0;
1772 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION);
1774 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
1775 byte_count = 3 /* pad */ + params + count;
1776 pSMB->DataCount = cpu_to_le16(count);
1777 pSMB->ParameterCount = cpu_to_le16(params);
1778 pSMB->TotalDataCount = pSMB->DataCount;
1779 pSMB->TotalParameterCount = pSMB->ParameterCount;
1780 pSMB->ParameterOffset = cpu_to_le16(param_offset);
1781 parm_data = (struct cifs_posix_lock *)
1782 (((char *) &pSMB->hdr.Protocol) + offset);
1784 parm_data->lock_type = cpu_to_le16(lock_type);
1786 timeout = CIFS_BLOCKING_OP; /* blocking operation, no timeout */
1787 parm_data->lock_flags = cpu_to_le16(1);
1788 pSMB->Timeout = cpu_to_le32(-1);
1792 parm_data->pid = cpu_to_le32(current->tgid);
1793 parm_data->start = cpu_to_le64(pLockData->fl_start);
1794 parm_data->length = cpu_to_le64(len); /* normalize negative numbers */
1796 pSMB->DataOffset = cpu_to_le16(offset);
1797 pSMB->Fid = smb_file_id;
1798 pSMB->InformationLevel = cpu_to_le16(SMB_SET_POSIX_LOCK);
1799 pSMB->Reserved4 = 0;
1800 pSMB->hdr.smb_buf_length += byte_count;
1801 pSMB->ByteCount = cpu_to_le16(byte_count);
1803 rc = SendReceiveBlockingLock(xid, tcon, (struct smb_hdr *) pSMB,
1804 (struct smb_hdr *) pSMBr, &bytes_returned);
1806 iov[0].iov_base = (char *)pSMB;
1807 iov[0].iov_len = pSMB->hdr.smb_buf_length + 4;
1808 rc = SendReceive2(xid, tcon->ses, iov, 1 /* num iovecs */,
1809 &resp_buf_type, timeout);
1810 pSMB = NULL; /* request buf already freed by SendReceive2. Do
1811 not try to free it twice below on exit */
1812 pSMBr = (struct smb_com_transaction2_sfi_rsp *)iov[0].iov_base;
1816 cFYI(1, "Send error in Posix Lock = %d", rc);
1817 } else if (get_flag) {
1818 /* lock structure can be returned on get */
1821 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
1823 if (rc || (pSMBr->ByteCount < sizeof(struct cifs_posix_lock))) {
1824 rc = -EIO; /* bad smb */
1827 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
1828 data_count = le16_to_cpu(pSMBr->t2.DataCount);
1829 if (data_count < sizeof(struct cifs_posix_lock)) {
1833 parm_data = (struct cifs_posix_lock *)
1834 ((char *)&pSMBr->hdr.Protocol + data_offset);
1835 if (parm_data->lock_type == __constant_cpu_to_le16(CIFS_UNLCK))
1836 pLockData->fl_type = F_UNLCK;
1838 if (parm_data->lock_type ==
1839 __constant_cpu_to_le16(CIFS_RDLCK))
1840 pLockData->fl_type = F_RDLCK;
1841 else if (parm_data->lock_type ==
1842 __constant_cpu_to_le16(CIFS_WRLCK))
1843 pLockData->fl_type = F_WRLCK;
1845 pLockData->fl_start = parm_data->start;
1846 pLockData->fl_end = parm_data->start +
1847 parm_data->length - 1;
1848 pLockData->fl_pid = parm_data->pid;
1854 cifs_small_buf_release(pSMB);
1856 if (resp_buf_type == CIFS_SMALL_BUFFER)
1857 cifs_small_buf_release(iov[0].iov_base);
1858 else if (resp_buf_type == CIFS_LARGE_BUFFER)
1859 cifs_buf_release(iov[0].iov_base);
1861 /* Note: On -EAGAIN error only caller can retry on handle based calls
1862 since file handle passed in no longer valid */
1869 CIFSSMBClose(const int xid, struct cifsTconInfo *tcon, int smb_file_id)
1872 CLOSE_REQ *pSMB = NULL;
1873 cFYI(1, "In CIFSSMBClose");
1875 /* do not retry on dead session on close */
1876 rc = small_smb_init(SMB_COM_CLOSE, 3, tcon, (void **) &pSMB);
1882 pSMB->FileID = (__u16) smb_file_id;
1883 pSMB->LastWriteTime = 0xFFFFFFFF;
1884 pSMB->ByteCount = 0;
1885 rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0);
1886 cifs_stats_inc(&tcon->num_closes);
1889 /* EINTR is expected when user ctl-c to kill app */
1890 cERROR(1, "Send error in Close = %d", rc);
1894 /* Since session is dead, file will be closed on server already */
1902 CIFSSMBFlush(const int xid, struct cifsTconInfo *tcon, int smb_file_id)
1905 FLUSH_REQ *pSMB = NULL;
1906 cFYI(1, "In CIFSSMBFlush");
1908 rc = small_smb_init(SMB_COM_FLUSH, 1, tcon, (void **) &pSMB);
1912 pSMB->FileID = (__u16) smb_file_id;
1913 pSMB->ByteCount = 0;
1914 rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0);
1915 cifs_stats_inc(&tcon->num_flushes);
1917 cERROR(1, "Send error in Flush = %d", rc);
1923 CIFSSMBRename(const int xid, struct cifsTconInfo *tcon,
1924 const char *fromName, const char *toName,
1925 const struct nls_table *nls_codepage, int remap)
1928 RENAME_REQ *pSMB = NULL;
1929 RENAME_RSP *pSMBr = NULL;
1931 int name_len, name_len2;
1934 cFYI(1, "In CIFSSMBRename");
1936 rc = smb_init(SMB_COM_RENAME, 1, tcon, (void **) &pSMB,
1941 pSMB->BufferFormat = 0x04;
1942 pSMB->SearchAttributes =
1943 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
1946 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1948 cifsConvertToUCS((__le16 *) pSMB->OldFileName, fromName,
1949 PATH_MAX, nls_codepage, remap);
1950 name_len++; /* trailing null */
1952 pSMB->OldFileName[name_len] = 0x04; /* pad */
1953 /* protocol requires ASCII signature byte on Unicode string */
1954 pSMB->OldFileName[name_len + 1] = 0x00;
1956 cifsConvertToUCS((__le16 *)&pSMB->OldFileName[name_len + 2],
1957 toName, PATH_MAX, nls_codepage, remap);
1958 name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
1959 name_len2 *= 2; /* convert to bytes */
1960 } else { /* BB improve the check for buffer overruns BB */
1961 name_len = strnlen(fromName, PATH_MAX);
1962 name_len++; /* trailing null */
1963 strncpy(pSMB->OldFileName, fromName, name_len);
1964 name_len2 = strnlen(toName, PATH_MAX);
1965 name_len2++; /* trailing null */
1966 pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */
1967 strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2);
1968 name_len2++; /* trailing null */
1969 name_len2++; /* signature byte */
1972 count = 1 /* 1st signature byte */ + name_len + name_len2;
1973 pSMB->hdr.smb_buf_length += count;
1974 pSMB->ByteCount = cpu_to_le16(count);
1976 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1977 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1978 cifs_stats_inc(&tcon->num_renames);
1980 cFYI(1, "Send error in rename = %d", rc);
1982 cifs_buf_release(pSMB);
1990 int CIFSSMBRenameOpenFile(const int xid, struct cifsTconInfo *pTcon,
1991 int netfid, const char *target_name,
1992 const struct nls_table *nls_codepage, int remap)
1994 struct smb_com_transaction2_sfi_req *pSMB = NULL;
1995 struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
1996 struct set_file_rename *rename_info;
1998 char dummy_string[30];
2000 int bytes_returned = 0;
2002 __u16 params, param_offset, offset, count, byte_count;
2004 cFYI(1, "Rename to File by handle");
2005 rc = smb_init(SMB_COM_TRANSACTION2, 15, pTcon, (void **) &pSMB,
2011 pSMB->MaxSetupCount = 0;
2015 pSMB->Reserved2 = 0;
2016 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
2017 offset = param_offset + params;
2019 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
2020 rename_info = (struct set_file_rename *) data_offset;
2021 pSMB->MaxParameterCount = cpu_to_le16(2);
2022 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB from sess */
2023 pSMB->SetupCount = 1;
2024 pSMB->Reserved3 = 0;
2025 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
2026 byte_count = 3 /* pad */ + params;
2027 pSMB->ParameterCount = cpu_to_le16(params);
2028 pSMB->TotalParameterCount = pSMB->ParameterCount;
2029 pSMB->ParameterOffset = cpu_to_le16(param_offset);
2030 pSMB->DataOffset = cpu_to_le16(offset);
2031 /* construct random name ".cifs_tmp<inodenum><mid>" */
2032 rename_info->overwrite = cpu_to_le32(1);
2033 rename_info->root_fid = 0;
2034 /* unicode only call */
2035 if (target_name == NULL) {
2036 sprintf(dummy_string, "cifs%x", pSMB->hdr.Mid);
2037 len_of_str = cifsConvertToUCS((__le16 *)rename_info->target_name,
2038 dummy_string, 24, nls_codepage, remap);
2040 len_of_str = cifsConvertToUCS((__le16 *)rename_info->target_name,
2041 target_name, PATH_MAX, nls_codepage,
2044 rename_info->target_name_len = cpu_to_le32(2 * len_of_str);
2045 count = 12 /* sizeof(struct set_file_rename) */ + (2 * len_of_str);
2046 byte_count += count;
2047 pSMB->DataCount = cpu_to_le16(count);
2048 pSMB->TotalDataCount = pSMB->DataCount;
2050 pSMB->InformationLevel =
2051 cpu_to_le16(SMB_SET_FILE_RENAME_INFORMATION);
2052 pSMB->Reserved4 = 0;
2053 pSMB->hdr.smb_buf_length += byte_count;
2054 pSMB->ByteCount = cpu_to_le16(byte_count);
2055 rc = SendReceive(xid, pTcon->ses, (struct smb_hdr *) pSMB,
2056 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2057 cifs_stats_inc(&pTcon->num_t2renames);
2059 cFYI(1, "Send error in Rename (by file handle) = %d", rc);
2061 cifs_buf_release(pSMB);
2063 /* Note: On -EAGAIN error only caller can retry on handle based calls
2064 since file handle passed in no longer valid */
2070 CIFSSMBCopy(const int xid, struct cifsTconInfo *tcon, const char *fromName,
2071 const __u16 target_tid, const char *toName, const int flags,
2072 const struct nls_table *nls_codepage, int remap)
2075 COPY_REQ *pSMB = NULL;
2076 COPY_RSP *pSMBr = NULL;
2078 int name_len, name_len2;
2081 cFYI(1, "In CIFSSMBCopy");
2083 rc = smb_init(SMB_COM_COPY, 1, tcon, (void **) &pSMB,
2088 pSMB->BufferFormat = 0x04;
2089 pSMB->Tid2 = target_tid;
2091 pSMB->Flags = cpu_to_le16(flags & COPY_TREE);
2093 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2094 name_len = cifsConvertToUCS((__le16 *) pSMB->OldFileName,
2095 fromName, PATH_MAX, nls_codepage,
2097 name_len++; /* trailing null */
2099 pSMB->OldFileName[name_len] = 0x04; /* pad */
2100 /* protocol requires ASCII signature byte on Unicode string */
2101 pSMB->OldFileName[name_len + 1] = 0x00;
2103 cifsConvertToUCS((__le16 *)&pSMB->OldFileName[name_len + 2],
2104 toName, PATH_MAX, nls_codepage, remap);
2105 name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
2106 name_len2 *= 2; /* convert to bytes */
2107 } else { /* BB improve the check for buffer overruns BB */
2108 name_len = strnlen(fromName, PATH_MAX);
2109 name_len++; /* trailing null */
2110 strncpy(pSMB->OldFileName, fromName, name_len);
2111 name_len2 = strnlen(toName, PATH_MAX);
2112 name_len2++; /* trailing null */
2113 pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */
2114 strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2);
2115 name_len2++; /* trailing null */
2116 name_len2++; /* signature byte */
2119 count = 1 /* 1st signature byte */ + name_len + name_len2;
2120 pSMB->hdr.smb_buf_length += count;
2121 pSMB->ByteCount = cpu_to_le16(count);
2123 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2124 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2126 cFYI(1, "Send error in copy = %d with %d files copied",
2127 rc, le16_to_cpu(pSMBr->CopyCount));
2129 cifs_buf_release(pSMB);
2138 CIFSUnixCreateSymLink(const int xid, struct cifsTconInfo *tcon,
2139 const char *fromName, const char *toName,
2140 const struct nls_table *nls_codepage)
2142 TRANSACTION2_SPI_REQ *pSMB = NULL;
2143 TRANSACTION2_SPI_RSP *pSMBr = NULL;
2146 int name_len_target;
2148 int bytes_returned = 0;
2149 __u16 params, param_offset, offset, byte_count;
2151 cFYI(1, "In Symlink Unix style");
2153 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2158 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2160 cifs_strtoUCS((__le16 *) pSMB->FileName, fromName, PATH_MAX
2161 /* find define for this maxpathcomponent */
2163 name_len++; /* trailing null */
2166 } else { /* BB improve the check for buffer overruns BB */
2167 name_len = strnlen(fromName, PATH_MAX);
2168 name_len++; /* trailing null */
2169 strncpy(pSMB->FileName, fromName, name_len);
2171 params = 6 + name_len;
2172 pSMB->MaxSetupCount = 0;
2176 pSMB->Reserved2 = 0;
2177 param_offset = offsetof(struct smb_com_transaction2_spi_req,
2178 InformationLevel) - 4;
2179 offset = param_offset + params;
2181 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
2182 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2184 cifs_strtoUCS((__le16 *) data_offset, toName, PATH_MAX
2185 /* find define for this maxpathcomponent */
2187 name_len_target++; /* trailing null */
2188 name_len_target *= 2;
2189 } else { /* BB improve the check for buffer overruns BB */
2190 name_len_target = strnlen(toName, PATH_MAX);
2191 name_len_target++; /* trailing null */
2192 strncpy(data_offset, toName, name_len_target);
2195 pSMB->MaxParameterCount = cpu_to_le16(2);
2196 /* BB find exact max on data count below from sess */
2197 pSMB->MaxDataCount = cpu_to_le16(1000);
2198 pSMB->SetupCount = 1;
2199 pSMB->Reserved3 = 0;
2200 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
2201 byte_count = 3 /* pad */ + params + name_len_target;
2202 pSMB->DataCount = cpu_to_le16(name_len_target);
2203 pSMB->ParameterCount = cpu_to_le16(params);
2204 pSMB->TotalDataCount = pSMB->DataCount;
2205 pSMB->TotalParameterCount = pSMB->ParameterCount;
2206 pSMB->ParameterOffset = cpu_to_le16(param_offset);
2207 pSMB->DataOffset = cpu_to_le16(offset);
2208 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_LINK);
2209 pSMB->Reserved4 = 0;
2210 pSMB->hdr.smb_buf_length += byte_count;
2211 pSMB->ByteCount = cpu_to_le16(byte_count);
2212 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2213 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2214 cifs_stats_inc(&tcon->num_symlinks);
2216 cFYI(1, "Send error in SetPathInfo create symlink = %d", rc);
2218 cifs_buf_release(pSMB);
2221 goto createSymLinkRetry;
2227 CIFSUnixCreateHardLink(const int xid, struct cifsTconInfo *tcon,
2228 const char *fromName, const char *toName,
2229 const struct nls_table *nls_codepage, int remap)
2231 TRANSACTION2_SPI_REQ *pSMB = NULL;
2232 TRANSACTION2_SPI_RSP *pSMBr = NULL;
2235 int name_len_target;
2237 int bytes_returned = 0;
2238 __u16 params, param_offset, offset, byte_count;
2240 cFYI(1, "In Create Hard link Unix style");
2241 createHardLinkRetry:
2242 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2247 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2248 name_len = cifsConvertToUCS((__le16 *) pSMB->FileName, toName,
2249 PATH_MAX, nls_codepage, remap);
2250 name_len++; /* trailing null */
2253 } else { /* BB improve the check for buffer overruns BB */
2254 name_len = strnlen(toName, PATH_MAX);
2255 name_len++; /* trailing null */
2256 strncpy(pSMB->FileName, toName, name_len);
2258 params = 6 + name_len;
2259 pSMB->MaxSetupCount = 0;
2263 pSMB->Reserved2 = 0;
2264 param_offset = offsetof(struct smb_com_transaction2_spi_req,
2265 InformationLevel) - 4;
2266 offset = param_offset + params;
2268 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
2269 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2271 cifsConvertToUCS((__le16 *) data_offset, fromName, PATH_MAX,
2272 nls_codepage, remap);
2273 name_len_target++; /* trailing null */
2274 name_len_target *= 2;
2275 } else { /* BB improve the check for buffer overruns BB */
2276 name_len_target = strnlen(fromName, PATH_MAX);
2277 name_len_target++; /* trailing null */
2278 strncpy(data_offset, fromName, name_len_target);
2281 pSMB->MaxParameterCount = cpu_to_le16(2);
2282 /* BB find exact max on data count below from sess*/
2283 pSMB->MaxDataCount = cpu_to_le16(1000);
2284 pSMB->SetupCount = 1;
2285 pSMB->Reserved3 = 0;
2286 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
2287 byte_count = 3 /* pad */ + params + name_len_target;
2288 pSMB->ParameterCount = cpu_to_le16(params);
2289 pSMB->TotalParameterCount = pSMB->ParameterCount;
2290 pSMB->DataCount = cpu_to_le16(name_len_target);
2291 pSMB->TotalDataCount = pSMB->DataCount;
2292 pSMB->ParameterOffset = cpu_to_le16(param_offset);
2293 pSMB->DataOffset = cpu_to_le16(offset);
2294 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_HLINK);
2295 pSMB->Reserved4 = 0;
2296 pSMB->hdr.smb_buf_length += byte_count;
2297 pSMB->ByteCount = cpu_to_le16(byte_count);
2298 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2299 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2300 cifs_stats_inc(&tcon->num_hardlinks);
2302 cFYI(1, "Send error in SetPathInfo (hard link) = %d", rc);
2304 cifs_buf_release(pSMB);
2306 goto createHardLinkRetry;
2312 CIFSCreateHardLink(const int xid, struct cifsTconInfo *tcon,
2313 const char *fromName, const char *toName,
2314 const struct nls_table *nls_codepage, int remap)
2317 NT_RENAME_REQ *pSMB = NULL;
2318 RENAME_RSP *pSMBr = NULL;
2320 int name_len, name_len2;
2323 cFYI(1, "In CIFSCreateHardLink");
2324 winCreateHardLinkRetry:
2326 rc = smb_init(SMB_COM_NT_RENAME, 4, tcon, (void **) &pSMB,
2331 pSMB->SearchAttributes =
2332 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
2334 pSMB->Flags = cpu_to_le16(CREATE_HARD_LINK);
2335 pSMB->ClusterCount = 0;
2337 pSMB->BufferFormat = 0x04;
2339 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2341 cifsConvertToUCS((__le16 *) pSMB->OldFileName, fromName,
2342 PATH_MAX, nls_codepage, remap);
2343 name_len++; /* trailing null */
2346 /* protocol specifies ASCII buffer format (0x04) for unicode */
2347 pSMB->OldFileName[name_len] = 0x04;
2348 pSMB->OldFileName[name_len + 1] = 0x00; /* pad */
2350 cifsConvertToUCS((__le16 *)&pSMB->OldFileName[name_len + 2],
2351 toName, PATH_MAX, nls_codepage, remap);
2352 name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
2353 name_len2 *= 2; /* convert to bytes */
2354 } else { /* BB improve the check for buffer overruns BB */
2355 name_len = strnlen(fromName, PATH_MAX);
2356 name_len++; /* trailing null */
2357 strncpy(pSMB->OldFileName, fromName, name_len);
2358 name_len2 = strnlen(toName, PATH_MAX);
2359 name_len2++; /* trailing null */
2360 pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */
2361 strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2);
2362 name_len2++; /* trailing null */
2363 name_len2++; /* signature byte */
2366 count = 1 /* string type byte */ + name_len + name_len2;
2367 pSMB->hdr.smb_buf_length += count;
2368 pSMB->ByteCount = cpu_to_le16(count);
2370 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2371 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2372 cifs_stats_inc(&tcon->num_hardlinks);
2374 cFYI(1, "Send error in hard link (NT rename) = %d", rc);
2376 cifs_buf_release(pSMB);
2378 goto winCreateHardLinkRetry;
2384 CIFSSMBUnixQuerySymLink(const int xid, struct cifsTconInfo *tcon,
2385 const unsigned char *searchName, char **symlinkinfo,
2386 const struct nls_table *nls_codepage)
2388 /* SMB_QUERY_FILE_UNIX_LINK */
2389 TRANSACTION2_QPI_REQ *pSMB = NULL;
2390 TRANSACTION2_QPI_RSP *pSMBr = NULL;
2394 __u16 params, byte_count;
2397 cFYI(1, "In QPathSymLinkInfo (Unix) for path %s", searchName);
2400 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2405 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2407 cifs_strtoUCS((__le16 *) pSMB->FileName, searchName,
2408 PATH_MAX, nls_codepage);
2409 name_len++; /* trailing null */
2411 } else { /* BB improve the check for buffer overruns BB */
2412 name_len = strnlen(searchName, PATH_MAX);
2413 name_len++; /* trailing null */
2414 strncpy(pSMB->FileName, searchName, name_len);
2417 params = 2 /* level */ + 4 /* rsrvd */ + name_len /* incl null */ ;
2418 pSMB->TotalDataCount = 0;
2419 pSMB->MaxParameterCount = cpu_to_le16(2);
2420 pSMB->MaxDataCount = cpu_to_le16(CIFSMaxBufSize);
2421 pSMB->MaxSetupCount = 0;
2425 pSMB->Reserved2 = 0;
2426 pSMB->ParameterOffset = cpu_to_le16(offsetof(
2427 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
2428 pSMB->DataCount = 0;
2429 pSMB->DataOffset = 0;
2430 pSMB->SetupCount = 1;
2431 pSMB->Reserved3 = 0;
2432 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
2433 byte_count = params + 1 /* pad */ ;
2434 pSMB->TotalParameterCount = cpu_to_le16(params);
2435 pSMB->ParameterCount = pSMB->TotalParameterCount;
2436 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_LINK);
2437 pSMB->Reserved4 = 0;
2438 pSMB->hdr.smb_buf_length += byte_count;
2439 pSMB->ByteCount = cpu_to_le16(byte_count);
2441 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2442 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2444 cFYI(1, "Send error in QuerySymLinkInfo = %d", rc);
2446 /* decode response */
2448 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
2449 /* BB also check enough total bytes returned */
2450 if (rc || (pSMBr->ByteCount < 2))
2454 u16 count = le16_to_cpu(pSMBr->t2.DataCount);
2456 data_start = ((char *) &pSMBr->hdr.Protocol) +
2457 le16_to_cpu(pSMBr->t2.DataOffset);
2459 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
2464 /* BB FIXME investigate remapping reserved chars here */
2465 *symlinkinfo = cifs_strndup_from_ucs(data_start, count,
2466 is_unicode, nls_codepage);
2471 cifs_buf_release(pSMB);
2473 goto querySymLinkRetry;
2477 #ifdef CONFIG_CIFS_EXPERIMENTAL
2479 CIFSSMBQueryReparseLinkInfo(const int xid, struct cifsTconInfo *tcon,
2480 const unsigned char *searchName,
2481 char *symlinkinfo, const int buflen, __u16 fid,
2482 const struct nls_table *nls_codepage)
2486 struct smb_com_transaction_ioctl_req *pSMB;
2487 struct smb_com_transaction_ioctl_rsp *pSMBr;
2489 cFYI(1, "In Windows reparse style QueryLink for path %s", searchName);
2490 rc = smb_init(SMB_COM_NT_TRANSACT, 23, tcon, (void **) &pSMB,
2495 pSMB->TotalParameterCount = 0 ;
2496 pSMB->TotalDataCount = 0;
2497 pSMB->MaxParameterCount = cpu_to_le32(2);
2498 /* BB find exact data count max from sess structure BB */
2499 pSMB->MaxDataCount = cpu_to_le32((tcon->ses->server->maxBuf -
2500 MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
2501 pSMB->MaxSetupCount = 4;
2503 pSMB->ParameterOffset = 0;
2504 pSMB->DataCount = 0;
2505 pSMB->DataOffset = 0;
2506 pSMB->SetupCount = 4;
2507 pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_IOCTL);
2508 pSMB->ParameterCount = pSMB->TotalParameterCount;
2509 pSMB->FunctionCode = cpu_to_le32(FSCTL_GET_REPARSE_POINT);
2510 pSMB->IsFsctl = 1; /* FSCTL */
2511 pSMB->IsRootFlag = 0;
2512 pSMB->Fid = fid; /* file handle always le */
2513 pSMB->ByteCount = 0;
2515 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2516 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2518 cFYI(1, "Send error in QueryReparseLinkInfo = %d", rc);
2519 } else { /* decode response */
2520 __u32 data_offset = le32_to_cpu(pSMBr->DataOffset);
2521 __u32 data_count = le32_to_cpu(pSMBr->DataCount);
2522 if ((pSMBr->ByteCount < 2) || (data_offset > 512)) {
2523 /* BB also check enough total bytes returned */
2524 rc = -EIO; /* bad smb */
2527 if (data_count && (data_count < 2048)) {
2528 char *end_of_smb = 2 /* sizeof byte count */ +
2529 pSMBr->ByteCount + (char *)&pSMBr->ByteCount;
2531 struct reparse_data *reparse_buf =
2532 (struct reparse_data *)
2533 ((char *)&pSMBr->hdr.Protocol
2535 if ((char *)reparse_buf >= end_of_smb) {
2539 if ((reparse_buf->LinkNamesBuf +
2540 reparse_buf->TargetNameOffset +
2541 reparse_buf->TargetNameLen) > end_of_smb) {
2542 cFYI(1, "reparse buf beyond SMB");
2547 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
2548 cifs_from_ucs2(symlinkinfo, (__le16 *)
2549 (reparse_buf->LinkNamesBuf +
2550 reparse_buf->TargetNameOffset),
2552 reparse_buf->TargetNameLen,
2554 } else { /* ASCII names */
2555 strncpy(symlinkinfo,
2556 reparse_buf->LinkNamesBuf +
2557 reparse_buf->TargetNameOffset,
2558 min_t(const int, buflen,
2559 reparse_buf->TargetNameLen));
2563 cFYI(1, "Invalid return data count on "
2564 "get reparse info ioctl");
2566 symlinkinfo[buflen] = 0; /* just in case so the caller
2567 does not go off the end of the buffer */
2568 cFYI(1, "readlink result - %s", symlinkinfo);
2572 cifs_buf_release(pSMB);
2574 /* Note: On -EAGAIN error only caller can retry on handle based calls
2575 since file handle passed in no longer valid */
2579 #endif /* CIFS_EXPERIMENTAL */
2581 #ifdef CONFIG_CIFS_POSIX
2583 /*Convert an Access Control Entry from wire format to local POSIX xattr format*/
2584 static void cifs_convert_ace(posix_acl_xattr_entry *ace,
2585 struct cifs_posix_ace *cifs_ace)
2587 /* u8 cifs fields do not need le conversion */
2588 ace->e_perm = cpu_to_le16(cifs_ace->cifs_e_perm);
2589 ace->e_tag = cpu_to_le16(cifs_ace->cifs_e_tag);
2590 ace->e_id = cpu_to_le32(le64_to_cpu(cifs_ace->cifs_uid));
2591 /* cFYI(1, "perm %d tag %d id %d",ace->e_perm,ace->e_tag,ace->e_id); */
2596 /* Convert ACL from CIFS POSIX wire format to local Linux POSIX ACL xattr */
2597 static int cifs_copy_posix_acl(char *trgt, char *src, const int buflen,
2598 const int acl_type, const int size_of_data_area)
2603 struct cifs_posix_ace *pACE;
2604 struct cifs_posix_acl *cifs_acl = (struct cifs_posix_acl *)src;
2605 posix_acl_xattr_header *local_acl = (posix_acl_xattr_header *)trgt;
2607 if (le16_to_cpu(cifs_acl->version) != CIFS_ACL_VERSION)
2610 if (acl_type & ACL_TYPE_ACCESS) {
2611 count = le16_to_cpu(cifs_acl->access_entry_count);
2612 pACE = &cifs_acl->ace_array[0];
2613 size = sizeof(struct cifs_posix_acl);
2614 size += sizeof(struct cifs_posix_ace) * count;
2615 /* check if we would go beyond end of SMB */
2616 if (size_of_data_area < size) {
2617 cFYI(1, "bad CIFS POSIX ACL size %d vs. %d",
2618 size_of_data_area, size);
2621 } else if (acl_type & ACL_TYPE_DEFAULT) {
2622 count = le16_to_cpu(cifs_acl->access_entry_count);
2623 size = sizeof(struct cifs_posix_acl);
2624 size += sizeof(struct cifs_posix_ace) * count;
2625 /* skip past access ACEs to get to default ACEs */
2626 pACE = &cifs_acl->ace_array[count];
2627 count = le16_to_cpu(cifs_acl->default_entry_count);
2628 size += sizeof(struct cifs_posix_ace) * count;
2629 /* check if we would go beyond end of SMB */
2630 if (size_of_data_area < size)
2637 size = posix_acl_xattr_size(count);
2638 if ((buflen == 0) || (local_acl == NULL)) {
2639 /* used to query ACL EA size */
2640 } else if (size > buflen) {
2642 } else /* buffer big enough */ {
2643 local_acl->a_version = cpu_to_le32(POSIX_ACL_XATTR_VERSION);
2644 for (i = 0; i < count ; i++) {
2645 cifs_convert_ace(&local_acl->a_entries[i], pACE);
2652 static __u16 convert_ace_to_cifs_ace(struct cifs_posix_ace *cifs_ace,
2653 const posix_acl_xattr_entry *local_ace)
2655 __u16 rc = 0; /* 0 = ACL converted ok */
2657 cifs_ace->cifs_e_perm = le16_to_cpu(local_ace->e_perm);
2658 cifs_ace->cifs_e_tag = le16_to_cpu(local_ace->e_tag);
2659 /* BB is there a better way to handle the large uid? */
2660 if (local_ace->e_id == cpu_to_le32(-1)) {
2661 /* Probably no need to le convert -1 on any arch but can not hurt */
2662 cifs_ace->cifs_uid = cpu_to_le64(-1);
2664 cifs_ace->cifs_uid = cpu_to_le64(le32_to_cpu(local_ace->e_id));
2665 /*cFYI(1, "perm %d tag %d id %d",ace->e_perm,ace->e_tag,ace->e_id);*/
2669 /* Convert ACL from local Linux POSIX xattr to CIFS POSIX ACL wire format */
2670 static __u16 ACL_to_cifs_posix(char *parm_data, const char *pACL,
2671 const int buflen, const int acl_type)
2674 struct cifs_posix_acl *cifs_acl = (struct cifs_posix_acl *)parm_data;
2675 posix_acl_xattr_header *local_acl = (posix_acl_xattr_header *)pACL;
2679 if ((buflen == 0) || (pACL == NULL) || (cifs_acl == NULL))
2682 count = posix_acl_xattr_count((size_t)buflen);
2683 cFYI(1, "setting acl with %d entries from buf of length %d and "
2685 count, buflen, le32_to_cpu(local_acl->a_version));
2686 if (le32_to_cpu(local_acl->a_version) != 2) {
2687 cFYI(1, "unknown POSIX ACL version %d",
2688 le32_to_cpu(local_acl->a_version));
2691 cifs_acl->version = cpu_to_le16(1);
2692 if (acl_type == ACL_TYPE_ACCESS)
2693 cifs_acl->access_entry_count = cpu_to_le16(count);
2694 else if (acl_type == ACL_TYPE_DEFAULT)
2695 cifs_acl->default_entry_count = cpu_to_le16(count);
2697 cFYI(1, "unknown ACL type %d", acl_type);
2700 for (i = 0; i < count; i++) {
2701 rc = convert_ace_to_cifs_ace(&cifs_acl->ace_array[i],
2702 &local_acl->a_entries[i]);
2704 /* ACE not converted */
2709 rc = (__u16)(count * sizeof(struct cifs_posix_ace));
2710 rc += sizeof(struct cifs_posix_acl);
2711 /* BB add check to make sure ACL does not overflow SMB */
2717 CIFSSMBGetPosixACL(const int xid, struct cifsTconInfo *tcon,
2718 const unsigned char *searchName,
2719 char *acl_inf, const int buflen, const int acl_type,
2720 const struct nls_table *nls_codepage, int remap)
2722 /* SMB_QUERY_POSIX_ACL */
2723 TRANSACTION2_QPI_REQ *pSMB = NULL;
2724 TRANSACTION2_QPI_RSP *pSMBr = NULL;
2728 __u16 params, byte_count;
2730 cFYI(1, "In GetPosixACL (Unix) for path %s", searchName);
2733 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2738 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2740 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
2741 PATH_MAX, nls_codepage, remap);
2742 name_len++; /* trailing null */
2744 pSMB->FileName[name_len] = 0;
2745 pSMB->FileName[name_len+1] = 0;
2746 } else { /* BB improve the check for buffer overruns BB */
2747 name_len = strnlen(searchName, PATH_MAX);
2748 name_len++; /* trailing null */
2749 strncpy(pSMB->FileName, searchName, name_len);
2752 params = 2 /* level */ + 4 /* rsrvd */ + name_len /* incl null */ ;
2753 pSMB->TotalDataCount = 0;
2754 pSMB->MaxParameterCount = cpu_to_le16(2);
2755 /* BB find exact max data count below from sess structure BB */
2756 pSMB->MaxDataCount = cpu_to_le16(4000);
2757 pSMB->MaxSetupCount = 0;
2761 pSMB->Reserved2 = 0;
2762 pSMB->ParameterOffset = cpu_to_le16(
2763 offsetof(struct smb_com_transaction2_qpi_req,
2764 InformationLevel) - 4);
2765 pSMB->DataCount = 0;
2766 pSMB->DataOffset = 0;
2767 pSMB->SetupCount = 1;
2768 pSMB->Reserved3 = 0;
2769 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
2770 byte_count = params + 1 /* pad */ ;
2771 pSMB->TotalParameterCount = cpu_to_le16(params);
2772 pSMB->ParameterCount = pSMB->TotalParameterCount;
2773 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_POSIX_ACL);
2774 pSMB->Reserved4 = 0;
2775 pSMB->hdr.smb_buf_length += byte_count;
2776 pSMB->ByteCount = cpu_to_le16(byte_count);
2778 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2779 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2780 cifs_stats_inc(&tcon->num_acl_get);
2782 cFYI(1, "Send error in Query POSIX ACL = %d", rc);
2784 /* decode response */
2786 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
2787 if (rc || (pSMBr->ByteCount < 2))
2788 /* BB also check enough total bytes returned */
2789 rc = -EIO; /* bad smb */
2791 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
2792 __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
2793 rc = cifs_copy_posix_acl(acl_inf,
2794 (char *)&pSMBr->hdr.Protocol+data_offset,
2795 buflen, acl_type, count);
2798 cifs_buf_release(pSMB);
2805 CIFSSMBSetPosixACL(const int xid, struct cifsTconInfo *tcon,
2806 const unsigned char *fileName,
2807 const char *local_acl, const int buflen,
2809 const struct nls_table *nls_codepage, int remap)
2811 struct smb_com_transaction2_spi_req *pSMB = NULL;
2812 struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
2816 int bytes_returned = 0;
2817 __u16 params, byte_count, data_count, param_offset, offset;
2819 cFYI(1, "In SetPosixACL (Unix) for path %s", fileName);
2821 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2825 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2827 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
2828 PATH_MAX, nls_codepage, remap);
2829 name_len++; /* trailing null */
2831 } else { /* BB improve the check for buffer overruns BB */
2832 name_len = strnlen(fileName, PATH_MAX);
2833 name_len++; /* trailing null */
2834 strncpy(pSMB->FileName, fileName, name_len);
2836 params = 6 + name_len;
2837 pSMB->MaxParameterCount = cpu_to_le16(2);
2838 /* BB find max SMB size from sess */
2839 pSMB->MaxDataCount = cpu_to_le16(1000);
2840 pSMB->MaxSetupCount = 0;
2844 pSMB->Reserved2 = 0;
2845 param_offset = offsetof(struct smb_com_transaction2_spi_req,
2846 InformationLevel) - 4;
2847 offset = param_offset + params;
2848 parm_data = ((char *) &pSMB->hdr.Protocol) + offset;
2849 pSMB->ParameterOffset = cpu_to_le16(param_offset);
2851 /* convert to on the wire format for POSIX ACL */
2852 data_count = ACL_to_cifs_posix(parm_data, local_acl, buflen, acl_type);
2854 if (data_count == 0) {
2856 goto setACLerrorExit;
2858 pSMB->DataOffset = cpu_to_le16(offset);
2859 pSMB->SetupCount = 1;
2860 pSMB->Reserved3 = 0;
2861 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
2862 pSMB->InformationLevel = cpu_to_le16(SMB_SET_POSIX_ACL);
2863 byte_count = 3 /* pad */ + params + data_count;
2864 pSMB->DataCount = cpu_to_le16(data_count);
2865 pSMB->TotalDataCount = pSMB->DataCount;
2866 pSMB->ParameterCount = cpu_to_le16(params);
2867 pSMB->TotalParameterCount = pSMB->ParameterCount;
2868 pSMB->Reserved4 = 0;
2869 pSMB->hdr.smb_buf_length += byte_count;
2870 pSMB->ByteCount = cpu_to_le16(byte_count);
2871 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2872 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2874 cFYI(1, "Set POSIX ACL returned %d", rc);
2877 cifs_buf_release(pSMB);
2883 /* BB fix tabs in this function FIXME BB */
2885 CIFSGetExtAttr(const int xid, struct cifsTconInfo *tcon,
2886 const int netfid, __u64 *pExtAttrBits, __u64 *pMask)
2889 struct smb_t2_qfi_req *pSMB = NULL;
2890 struct smb_t2_qfi_rsp *pSMBr = NULL;
2892 __u16 params, byte_count;
2894 cFYI(1, "In GetExtAttr");
2899 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2904 params = 2 /* level */ + 2 /* fid */;
2905 pSMB->t2.TotalDataCount = 0;
2906 pSMB->t2.MaxParameterCount = cpu_to_le16(4);
2907 /* BB find exact max data count below from sess structure BB */
2908 pSMB->t2.MaxDataCount = cpu_to_le16(4000);
2909 pSMB->t2.MaxSetupCount = 0;
2910 pSMB->t2.Reserved = 0;
2912 pSMB->t2.Timeout = 0;
2913 pSMB->t2.Reserved2 = 0;
2914 pSMB->t2.ParameterOffset = cpu_to_le16(offsetof(struct smb_t2_qfi_req,
2916 pSMB->t2.DataCount = 0;
2917 pSMB->t2.DataOffset = 0;
2918 pSMB->t2.SetupCount = 1;
2919 pSMB->t2.Reserved3 = 0;
2920 pSMB->t2.SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION);
2921 byte_count = params + 1 /* pad */ ;
2922 pSMB->t2.TotalParameterCount = cpu_to_le16(params);
2923 pSMB->t2.ParameterCount = pSMB->t2.TotalParameterCount;
2924 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_ATTR_FLAGS);
2927 pSMB->hdr.smb_buf_length += byte_count;
2928 pSMB->t2.ByteCount = cpu_to_le16(byte_count);
2930 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2931 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2933 cFYI(1, "error %d in GetExtAttr", rc);
2935 /* decode response */
2936 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
2937 if (rc || (pSMBr->ByteCount < 2))
2938 /* BB also check enough total bytes returned */
2939 /* If rc should we check for EOPNOSUPP and
2940 disable the srvino flag? or in caller? */
2941 rc = -EIO; /* bad smb */
2943 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
2944 __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
2945 struct file_chattr_info *pfinfo;
2946 /* BB Do we need a cast or hash here ? */
2948 cFYI(1, "Illegal size ret in GetExtAttr");
2952 pfinfo = (struct file_chattr_info *)
2953 (data_offset + (char *) &pSMBr->hdr.Protocol);
2954 *pExtAttrBits = le64_to_cpu(pfinfo->mode);
2955 *pMask = le64_to_cpu(pfinfo->mask);
2959 cifs_buf_release(pSMB);
2961 goto GetExtAttrRetry;
2965 #endif /* CONFIG_POSIX */
2967 #ifdef CONFIG_CIFS_ACL
2969 * Initialize NT TRANSACT SMB into small smb request buffer. This assumes that
2970 * all NT TRANSACTS that we init here have total parm and data under about 400
2971 * bytes (to fit in small cifs buffer size), which is the case so far, it
2972 * easily fits. NB: Setup words themselves and ByteCount MaxSetupCount (size of
2973 * returned setup area) and MaxParameterCount (returned parms size) must be set
2977 smb_init_nttransact(const __u16 sub_command, const int setup_count,
2978 const int parm_len, struct cifsTconInfo *tcon,
2983 struct smb_com_ntransact_req *pSMB;
2985 rc = small_smb_init(SMB_COM_NT_TRANSACT, 19 + setup_count, tcon,
2989 *ret_buf = (void *)pSMB;
2991 pSMB->TotalParameterCount = cpu_to_le32(parm_len);
2992 pSMB->TotalDataCount = 0;
2993 pSMB->MaxDataCount = cpu_to_le32((tcon->ses->server->maxBuf -
2994 MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
2995 pSMB->ParameterCount = pSMB->TotalParameterCount;
2996 pSMB->DataCount = pSMB->TotalDataCount;
2997 temp_offset = offsetof(struct smb_com_ntransact_req, Parms) +
2998 (setup_count * 2) - 4 /* for rfc1001 length itself */;
2999 pSMB->ParameterOffset = cpu_to_le32(temp_offset);
3000 pSMB->DataOffset = cpu_to_le32(temp_offset + parm_len);
3001 pSMB->SetupCount = setup_count; /* no need to le convert byte fields */
3002 pSMB->SubCommand = cpu_to_le16(sub_command);
3007 validate_ntransact(char *buf, char **ppparm, char **ppdata,
3008 __u32 *pparmlen, __u32 *pdatalen)
3011 __u32 data_count, data_offset, parm_count, parm_offset;
3012 struct smb_com_ntransact_rsp *pSMBr;
3020 pSMBr = (struct smb_com_ntransact_rsp *)buf;
3022 /* ByteCount was converted from little endian in SendReceive */
3023 end_of_smb = 2 /* sizeof byte count */ + pSMBr->ByteCount +
3024 (char *)&pSMBr->ByteCount;
3026 data_offset = le32_to_cpu(pSMBr->DataOffset);
3027 data_count = le32_to_cpu(pSMBr->DataCount);
3028 parm_offset = le32_to_cpu(pSMBr->ParameterOffset);
3029 parm_count = le32_to_cpu(pSMBr->ParameterCount);
3031 *ppparm = (char *)&pSMBr->hdr.Protocol + parm_offset;
3032 *ppdata = (char *)&pSMBr->hdr.Protocol + data_offset;
3034 /* should we also check that parm and data areas do not overlap? */
3035 if (*ppparm > end_of_smb) {
3036 cFYI(1, "parms start after end of smb");
3038 } else if (parm_count + *ppparm > end_of_smb) {
3039 cFYI(1, "parm end after end of smb");
3041 } else if (*ppdata > end_of_smb) {
3042 cFYI(1, "data starts after end of smb");
3044 } else if (data_count + *ppdata > end_of_smb) {
3045 cFYI(1, "data %p + count %d (%p) past smb end %p start %p",
3046 *ppdata, data_count, (data_count + *ppdata),
3049 } else if (parm_count + data_count > pSMBr->ByteCount) {
3050 cFYI(1, "parm count and data count larger than SMB");
3053 *pdatalen = data_count;
3054 *pparmlen = parm_count;
3058 /* Get Security Descriptor (by handle) from remote server for a file or dir */
3060 CIFSSMBGetCIFSACL(const int xid, struct cifsTconInfo *tcon, __u16 fid,
3061 struct cifs_ntsd **acl_inf, __u32 *pbuflen)
3065 QUERY_SEC_DESC_REQ *pSMB;
3068 cFYI(1, "GetCifsACL");
3073 rc = smb_init_nttransact(NT_TRANSACT_QUERY_SECURITY_DESC, 0,
3074 8 /* parm len */, tcon, (void **) &pSMB);
3078 pSMB->MaxParameterCount = cpu_to_le32(4);
3079 /* BB TEST with big acls that might need to be e.g. larger than 16K */
3080 pSMB->MaxSetupCount = 0;
3081 pSMB->Fid = fid; /* file handle always le */
3082 pSMB->AclFlags = cpu_to_le32(CIFS_ACL_OWNER | CIFS_ACL_GROUP |
3084 pSMB->ByteCount = cpu_to_le16(11); /* 3 bytes pad + 8 bytes parm */
3085 pSMB->hdr.smb_buf_length += 11;
3086 iov[0].iov_base = (char *)pSMB;
3087 iov[0].iov_len = pSMB->hdr.smb_buf_length + 4;
3089 rc = SendReceive2(xid, tcon->ses, iov, 1 /* num iovec */, &buf_type,
3091 cifs_stats_inc(&tcon->num_acl_get);
3093 cFYI(1, "Send error in QuerySecDesc = %d", rc);
3094 } else { /* decode response */
3098 struct smb_com_ntransact_rsp *pSMBr;
3101 /* validate_nttransact */
3102 rc = validate_ntransact(iov[0].iov_base, (char **)&parm,
3103 &pdata, &parm_len, pbuflen);
3106 pSMBr = (struct smb_com_ntransact_rsp *)iov[0].iov_base;
3108 cFYI(1, "smb %p parm %p data %p", pSMBr, parm, *acl_inf);
3110 if (le32_to_cpu(pSMBr->ParameterCount) != 4) {
3111 rc = -EIO; /* bad smb */
3116 /* BB check that data area is minimum length and as big as acl_len */
3118 acl_len = le32_to_cpu(*parm);
3119 if (acl_len != *pbuflen) {
3120 cERROR(1, "acl length %d does not match %d",
3122 if (*pbuflen > acl_len)
3126 /* check if buffer is big enough for the acl
3127 header followed by the smallest SID */
3128 if ((*pbuflen < sizeof(struct cifs_ntsd) + 8) ||
3129 (*pbuflen >= 64 * 1024)) {
3130 cERROR(1, "bad acl length %d", *pbuflen);
3134 *acl_inf = kmalloc(*pbuflen, GFP_KERNEL);
3135 if (*acl_inf == NULL) {
3139 memcpy(*acl_inf, pdata, *pbuflen);
3143 if (buf_type == CIFS_SMALL_BUFFER)
3144 cifs_small_buf_release(iov[0].iov_base);
3145 else if (buf_type == CIFS_LARGE_BUFFER)
3146 cifs_buf_release(iov[0].iov_base);
3147 /* cifs_small_buf_release(pSMB); */ /* Freed earlier now in SendReceive2 */
3152 CIFSSMBSetCIFSACL(const int xid, struct cifsTconInfo *tcon, __u16 fid,
3153 struct cifs_ntsd *pntsd, __u32 acllen)
3155 __u16 byte_count, param_count, data_count, param_offset, data_offset;
3157 int bytes_returned = 0;
3158 SET_SEC_DESC_REQ *pSMB = NULL;
3159 NTRANSACT_RSP *pSMBr = NULL;
3162 rc = smb_init(SMB_COM_NT_TRANSACT, 19, tcon, (void **) &pSMB,
3167 pSMB->MaxSetupCount = 0;
3171 param_offset = offsetof(struct smb_com_transaction_ssec_req, Fid) - 4;
3172 data_count = acllen;
3173 data_offset = param_offset + param_count;
3174 byte_count = 3 /* pad */ + param_count;
3176 pSMB->DataCount = cpu_to_le32(data_count);
3177 pSMB->TotalDataCount = pSMB->DataCount;
3178 pSMB->MaxParameterCount = cpu_to_le32(4);
3179 pSMB->MaxDataCount = cpu_to_le32(16384);
3180 pSMB->ParameterCount = cpu_to_le32(param_count);
3181 pSMB->ParameterOffset = cpu_to_le32(param_offset);
3182 pSMB->TotalParameterCount = pSMB->ParameterCount;
3183 pSMB->DataOffset = cpu_to_le32(data_offset);
3184 pSMB->SetupCount = 0;
3185 pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_SET_SECURITY_DESC);
3186 pSMB->ByteCount = cpu_to_le16(byte_count+data_count);
3188 pSMB->Fid = fid; /* file handle always le */
3189 pSMB->Reserved2 = 0;
3190 pSMB->AclFlags = cpu_to_le32(CIFS_ACL_DACL);
3192 if (pntsd && acllen) {
3193 memcpy((char *) &pSMBr->hdr.Protocol + data_offset,
3196 pSMB->hdr.smb_buf_length += (byte_count + data_count);
3199 pSMB->hdr.smb_buf_length += byte_count;
3201 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3202 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3204 cFYI(1, "SetCIFSACL bytes_returned: %d, rc: %d", bytes_returned, rc);
3206 cFYI(1, "Set CIFS ACL returned %d", rc);
3207 cifs_buf_release(pSMB);
3210 goto setCifsAclRetry;
3215 #endif /* CONFIG_CIFS_ACL */
3217 /* Legacy Query Path Information call for lookup to old servers such
3219 int SMBQueryInformation(const int xid, struct cifsTconInfo *tcon,
3220 const unsigned char *searchName,
3221 FILE_ALL_INFO *pFinfo,
3222 const struct nls_table *nls_codepage, int remap)
3224 QUERY_INFORMATION_REQ *pSMB;
3225 QUERY_INFORMATION_RSP *pSMBr;
3230 cFYI(1, "In SMBQPath path %s", searchName);
3232 rc = smb_init(SMB_COM_QUERY_INFORMATION, 0, tcon, (void **) &pSMB,
3237 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3239 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
3240 PATH_MAX, nls_codepage, remap);
3241 name_len++; /* trailing null */
3244 name_len = strnlen(searchName, PATH_MAX);
3245 name_len++; /* trailing null */
3246 strncpy(pSMB->FileName, searchName, name_len);
3248 pSMB->BufferFormat = 0x04;
3249 name_len++; /* account for buffer type byte */
3250 pSMB->hdr.smb_buf_length += (__u16) name_len;
3251 pSMB->ByteCount = cpu_to_le16(name_len);
3253 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3254 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3256 cFYI(1, "Send error in QueryInfo = %d", rc);
3257 } else if (pFinfo) {
3259 __u32 time = le32_to_cpu(pSMBr->last_write_time);
3261 /* decode response */
3262 /* BB FIXME - add time zone adjustment BB */
3263 memset(pFinfo, 0, sizeof(FILE_ALL_INFO));
3266 /* decode time fields */
3267 pFinfo->ChangeTime = cpu_to_le64(cifs_UnixTimeToNT(ts));
3268 pFinfo->LastWriteTime = pFinfo->ChangeTime;
3269 pFinfo->LastAccessTime = 0;
3270 pFinfo->AllocationSize =
3271 cpu_to_le64(le32_to_cpu(pSMBr->size));
3272 pFinfo->EndOfFile = pFinfo->AllocationSize;
3273 pFinfo->Attributes =
3274 cpu_to_le32(le16_to_cpu(pSMBr->attr));
3276 rc = -EIO; /* bad buffer passed in */
3278 cifs_buf_release(pSMB);
3287 CIFSSMBQFileInfo(const int xid, struct cifsTconInfo *tcon,
3288 u16 netfid, FILE_ALL_INFO *pFindData)
3290 struct smb_t2_qfi_req *pSMB = NULL;
3291 struct smb_t2_qfi_rsp *pSMBr = NULL;
3294 __u16 params, byte_count;
3297 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3302 params = 2 /* level */ + 2 /* fid */;
3303 pSMB->t2.TotalDataCount = 0;
3304 pSMB->t2.MaxParameterCount = cpu_to_le16(4);
3305 /* BB find exact max data count below from sess structure BB */
3306 pSMB->t2.MaxDataCount = cpu_to_le16(CIFSMaxBufSize);
3307 pSMB->t2.MaxSetupCount = 0;
3308 pSMB->t2.Reserved = 0;
3310 pSMB->t2.Timeout = 0;
3311 pSMB->t2.Reserved2 = 0;
3312 pSMB->t2.ParameterOffset = cpu_to_le16(offsetof(struct smb_t2_qfi_req,
3314 pSMB->t2.DataCount = 0;
3315 pSMB->t2.DataOffset = 0;
3316 pSMB->t2.SetupCount = 1;
3317 pSMB->t2.Reserved3 = 0;
3318 pSMB->t2.SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION);
3319 byte_count = params + 1 /* pad */ ;
3320 pSMB->t2.TotalParameterCount = cpu_to_le16(params);
3321 pSMB->t2.ParameterCount = pSMB->t2.TotalParameterCount;
3322 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_ALL_INFO);
3325 pSMB->hdr.smb_buf_length += byte_count;
3327 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3328 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3330 cFYI(1, "Send error in QPathInfo = %d", rc);
3331 } else { /* decode response */
3332 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3334 if (rc) /* BB add auto retry on EOPNOTSUPP? */
3336 else if (pSMBr->ByteCount < 40)
3337 rc = -EIO; /* bad smb */
3338 else if (pFindData) {
3339 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3340 memcpy((char *) pFindData,
3341 (char *) &pSMBr->hdr.Protocol +
3342 data_offset, sizeof(FILE_ALL_INFO));
3346 cifs_buf_release(pSMB);
3348 goto QFileInfoRetry;
3354 CIFSSMBQPathInfo(const int xid, struct cifsTconInfo *tcon,
3355 const unsigned char *searchName,
3356 FILE_ALL_INFO *pFindData,
3357 int legacy /* old style infolevel */,
3358 const struct nls_table *nls_codepage, int remap)
3360 /* level 263 SMB_QUERY_FILE_ALL_INFO */
3361 TRANSACTION2_QPI_REQ *pSMB = NULL;
3362 TRANSACTION2_QPI_RSP *pSMBr = NULL;
3366 __u16 params, byte_count;
3368 /* cFYI(1, "In QPathInfo path %s", searchName); */
3370 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3375 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3377 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
3378 PATH_MAX, nls_codepage, remap);
3379 name_len++; /* trailing null */
3381 } else { /* BB improve the check for buffer overruns BB */
3382 name_len = strnlen(searchName, PATH_MAX);
3383 name_len++; /* trailing null */
3384 strncpy(pSMB->FileName, searchName, name_len);
3387 params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */;
3388 pSMB->TotalDataCount = 0;
3389 pSMB->MaxParameterCount = cpu_to_le16(2);
3390 /* BB find exact max SMB PDU from sess structure BB */
3391 pSMB->MaxDataCount = cpu_to_le16(4000);
3392 pSMB->MaxSetupCount = 0;
3396 pSMB->Reserved2 = 0;
3397 pSMB->ParameterOffset = cpu_to_le16(offsetof(
3398 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
3399 pSMB->DataCount = 0;
3400 pSMB->DataOffset = 0;
3401 pSMB->SetupCount = 1;
3402 pSMB->Reserved3 = 0;
3403 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
3404 byte_count = params + 1 /* pad */ ;
3405 pSMB->TotalParameterCount = cpu_to_le16(params);
3406 pSMB->ParameterCount = pSMB->TotalParameterCount;
3408 pSMB->InformationLevel = cpu_to_le16(SMB_INFO_STANDARD);
3410 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_ALL_INFO);
3411 pSMB->Reserved4 = 0;
3412 pSMB->hdr.smb_buf_length += byte_count;
3413 pSMB->ByteCount = cpu_to_le16(byte_count);
3415 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3416 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3418 cFYI(1, "Send error in QPathInfo = %d", rc);
3419 } else { /* decode response */
3420 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3422 if (rc) /* BB add auto retry on EOPNOTSUPP? */
3424 else if (!legacy && (pSMBr->ByteCount < 40))
3425 rc = -EIO; /* bad smb */
3426 else if (legacy && (pSMBr->ByteCount < 24))
3427 rc = -EIO; /* 24 or 26 expected but we do not read
3429 else if (pFindData) {
3431 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3433 /* On legacy responses we do not read the last field,
3434 EAsize, fortunately since it varies by subdialect and
3435 also note it differs on Set vs. Get, ie two bytes or 4
3436 bytes depending but we don't care here */
3438 size = sizeof(FILE_INFO_STANDARD);
3440 size = sizeof(FILE_ALL_INFO);
3441 memcpy((char *) pFindData,
3442 (char *) &pSMBr->hdr.Protocol +
3447 cifs_buf_release(pSMB);
3449 goto QPathInfoRetry;
3455 CIFSSMBUnixQFileInfo(const int xid, struct cifsTconInfo *tcon,
3456 u16 netfid, FILE_UNIX_BASIC_INFO *pFindData)
3458 struct smb_t2_qfi_req *pSMB = NULL;
3459 struct smb_t2_qfi_rsp *pSMBr = NULL;
3462 __u16 params, byte_count;
3465 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3470 params = 2 /* level */ + 2 /* fid */;
3471 pSMB->t2.TotalDataCount = 0;
3472 pSMB->t2.MaxParameterCount = cpu_to_le16(4);
3473 /* BB find exact max data count below from sess structure BB */
3474 pSMB->t2.MaxDataCount = cpu_to_le16(CIFSMaxBufSize);
3475 pSMB->t2.MaxSetupCount = 0;
3476 pSMB->t2.Reserved = 0;
3478 pSMB->t2.Timeout = 0;
3479 pSMB->t2.Reserved2 = 0;
3480 pSMB->t2.ParameterOffset = cpu_to_le16(offsetof(struct smb_t2_qfi_req,
3482 pSMB->t2.DataCount = 0;
3483 pSMB->t2.DataOffset = 0;
3484 pSMB->t2.SetupCount = 1;
3485 pSMB->t2.Reserved3 = 0;
3486 pSMB->t2.SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION);
3487 byte_count = params + 1 /* pad */ ;
3488 pSMB->t2.TotalParameterCount = cpu_to_le16(params);
3489 pSMB->t2.ParameterCount = pSMB->t2.TotalParameterCount;
3490 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC);
3493 pSMB->hdr.smb_buf_length += byte_count;
3495 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3496 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3498 cFYI(1, "Send error in QPathInfo = %d", rc);
3499 } else { /* decode response */
3500 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3502 if (rc || (pSMBr->ByteCount < sizeof(FILE_UNIX_BASIC_INFO))) {
3503 cERROR(1, "Malformed FILE_UNIX_BASIC_INFO response.\n"
3504 "Unix Extensions can be disabled on mount "
3505 "by specifying the nosfu mount option.");
3506 rc = -EIO; /* bad smb */
3508 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3509 memcpy((char *) pFindData,
3510 (char *) &pSMBr->hdr.Protocol +
3512 sizeof(FILE_UNIX_BASIC_INFO));
3516 cifs_buf_release(pSMB);
3518 goto UnixQFileInfoRetry;
3524 CIFSSMBUnixQPathInfo(const int xid, struct cifsTconInfo *tcon,
3525 const unsigned char *searchName,
3526 FILE_UNIX_BASIC_INFO *pFindData,
3527 const struct nls_table *nls_codepage, int remap)
3529 /* SMB_QUERY_FILE_UNIX_BASIC */
3530 TRANSACTION2_QPI_REQ *pSMB = NULL;
3531 TRANSACTION2_QPI_RSP *pSMBr = NULL;
3533 int bytes_returned = 0;
3535 __u16 params, byte_count;
3537 cFYI(1, "In QPathInfo (Unix) the path %s", searchName);
3539 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3544 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3546 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
3547 PATH_MAX, nls_codepage, remap);
3548 name_len++; /* trailing null */
3550 } else { /* BB improve the check for buffer overruns BB */
3551 name_len = strnlen(searchName, PATH_MAX);
3552 name_len++; /* trailing null */
3553 strncpy(pSMB->FileName, searchName, name_len);
3556 params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */;
3557 pSMB->TotalDataCount = 0;
3558 pSMB->MaxParameterCount = cpu_to_le16(2);
3559 /* BB find exact max SMB PDU from sess structure BB */
3560 pSMB->MaxDataCount = cpu_to_le16(4000);
3561 pSMB->MaxSetupCount = 0;
3565 pSMB->Reserved2 = 0;
3566 pSMB->ParameterOffset = cpu_to_le16(offsetof(
3567 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
3568 pSMB->DataCount = 0;
3569 pSMB->DataOffset = 0;
3570 pSMB->SetupCount = 1;
3571 pSMB->Reserved3 = 0;
3572 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
3573 byte_count = params + 1 /* pad */ ;
3574 pSMB->TotalParameterCount = cpu_to_le16(params);
3575 pSMB->ParameterCount = pSMB->TotalParameterCount;
3576 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC);
3577 pSMB->Reserved4 = 0;
3578 pSMB->hdr.smb_buf_length += byte_count;
3579 pSMB->ByteCount = cpu_to_le16(byte_count);
3581 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3582 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3584 cFYI(1, "Send error in QPathInfo = %d", rc);
3585 } else { /* decode response */
3586 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3588 if (rc || (pSMBr->ByteCount < sizeof(FILE_UNIX_BASIC_INFO))) {
3589 cERROR(1, "Malformed FILE_UNIX_BASIC_INFO response.\n"
3590 "Unix Extensions can be disabled on mount "
3591 "by specifying the nosfu mount option.");
3592 rc = -EIO; /* bad smb */
3594 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3595 memcpy((char *) pFindData,
3596 (char *) &pSMBr->hdr.Protocol +
3598 sizeof(FILE_UNIX_BASIC_INFO));
3601 cifs_buf_release(pSMB);
3603 goto UnixQPathInfoRetry;
3608 /* xid, tcon, searchName and codepage are input parms, rest are returned */
3610 CIFSFindFirst(const int xid, struct cifsTconInfo *tcon,
3611 const char *searchName,
3612 const struct nls_table *nls_codepage,
3614 struct cifs_search_info *psrch_inf, int remap, const char dirsep)
3616 /* level 257 SMB_ */
3617 TRANSACTION2_FFIRST_REQ *pSMB = NULL;
3618 TRANSACTION2_FFIRST_RSP *pSMBr = NULL;
3619 T2_FFIRST_RSP_PARMS *parms;
3621 int bytes_returned = 0;
3623 __u16 params, byte_count;
3625 cFYI(1, "In FindFirst for %s", searchName);
3628 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3633 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3635 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
3636 PATH_MAX, nls_codepage, remap);
3637 /* We can not add the asterik earlier in case
3638 it got remapped to 0xF03A as if it were part of the
3639 directory name instead of a wildcard */
3641 pSMB->FileName[name_len] = dirsep;
3642 pSMB->FileName[name_len+1] = 0;
3643 pSMB->FileName[name_len+2] = '*';
3644 pSMB->FileName[name_len+3] = 0;
3645 name_len += 4; /* now the trailing null */
3646 pSMB->FileName[name_len] = 0; /* null terminate just in case */
3647 pSMB->FileName[name_len+1] = 0;
3649 } else { /* BB add check for overrun of SMB buf BB */
3650 name_len = strnlen(searchName, PATH_MAX);
3651 /* BB fix here and in unicode clause above ie
3652 if (name_len > buffersize-header)
3653 free buffer exit; BB */
3654 strncpy(pSMB->FileName, searchName, name_len);
3655 pSMB->FileName[name_len] = dirsep;
3656 pSMB->FileName[name_len+1] = '*';
3657 pSMB->FileName[name_len+2] = 0;
3661 params = 12 + name_len /* includes null */ ;
3662 pSMB->TotalDataCount = 0; /* no EAs */
3663 pSMB->MaxParameterCount = cpu_to_le16(10);
3664 pSMB->MaxDataCount = cpu_to_le16((tcon->ses->server->maxBuf -
3665 MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
3666 pSMB->MaxSetupCount = 0;
3670 pSMB->Reserved2 = 0;
3671 byte_count = params + 1 /* pad */ ;
3672 pSMB->TotalParameterCount = cpu_to_le16(params);
3673 pSMB->ParameterCount = pSMB->TotalParameterCount;
3674 pSMB->ParameterOffset = cpu_to_le16(
3675 offsetof(struct smb_com_transaction2_ffirst_req, SearchAttributes)
3677 pSMB->DataCount = 0;
3678 pSMB->DataOffset = 0;
3679 pSMB->SetupCount = 1; /* one byte, no need to make endian neutral */
3680 pSMB->Reserved3 = 0;
3681 pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_FIRST);
3682 pSMB->SearchAttributes =
3683 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
3685 pSMB->SearchCount = cpu_to_le16(CIFSMaxBufSize/sizeof(FILE_UNIX_INFO));
3686 pSMB->SearchFlags = cpu_to_le16(CIFS_SEARCH_CLOSE_AT_END |
3687 CIFS_SEARCH_RETURN_RESUME);
3688 pSMB->InformationLevel = cpu_to_le16(psrch_inf->info_level);
3690 /* BB what should we set StorageType to? Does it matter? BB */
3691 pSMB->SearchStorageType = 0;
3692 pSMB->hdr.smb_buf_length += byte_count;
3693 pSMB->ByteCount = cpu_to_le16(byte_count);
3695 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3696 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3697 cifs_stats_inc(&tcon->num_ffirst);
3699 if (rc) {/* BB add logic to retry regular search if Unix search
3700 rejected unexpectedly by server */
3701 /* BB Add code to handle unsupported level rc */
3702 cFYI(1, "Error in FindFirst = %d", rc);
3704 cifs_buf_release(pSMB);
3706 /* BB eventually could optimize out free and realloc of buf */
3709 goto findFirstRetry;
3710 } else { /* decode response */
3711 /* BB remember to free buffer if error BB */
3712 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3716 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
3717 psrch_inf->unicode = true;
3719 psrch_inf->unicode = false;
3721 psrch_inf->ntwrk_buf_start = (char *)pSMBr;
3722 psrch_inf->smallBuf = 0;
3723 psrch_inf->srch_entries_start =
3724 (char *) &pSMBr->hdr.Protocol +
3725 le16_to_cpu(pSMBr->t2.DataOffset);
3726 parms = (T2_FFIRST_RSP_PARMS *)((char *) &pSMBr->hdr.Protocol +
3727 le16_to_cpu(pSMBr->t2.ParameterOffset));
3729 if (parms->EndofSearch)
3730 psrch_inf->endOfSearch = true;
3732 psrch_inf->endOfSearch = false;
3734 psrch_inf->entries_in_buffer =
3735 le16_to_cpu(parms->SearchCount);
3736 psrch_inf->index_of_last_entry = 2 /* skip . and .. */ +
3737 psrch_inf->entries_in_buffer;
3738 lnoff = le16_to_cpu(parms->LastNameOffset);
3739 if (tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE <
3741 cERROR(1, "ignoring corrupt resume name");
3742 psrch_inf->last_entry = NULL;
3746 psrch_inf->last_entry = psrch_inf->srch_entries_start +
3749 *pnetfid = parms->SearchHandle;
3751 cifs_buf_release(pSMB);
3758 int CIFSFindNext(const int xid, struct cifsTconInfo *tcon,
3759 __u16 searchHandle, struct cifs_search_info *psrch_inf)
3761 TRANSACTION2_FNEXT_REQ *pSMB = NULL;
3762 TRANSACTION2_FNEXT_RSP *pSMBr = NULL;
3763 T2_FNEXT_RSP_PARMS *parms;
3764 char *response_data;
3766 int bytes_returned, name_len;
3767 __u16 params, byte_count;
3769 cFYI(1, "In FindNext");
3771 if (psrch_inf->endOfSearch)
3774 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3779 params = 14; /* includes 2 bytes of null string, converted to LE below*/
3781 pSMB->TotalDataCount = 0; /* no EAs */
3782 pSMB->MaxParameterCount = cpu_to_le16(8);
3783 pSMB->MaxDataCount =
3784 cpu_to_le16((tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE) &
3786 pSMB->MaxSetupCount = 0;
3790 pSMB->Reserved2 = 0;
3791 pSMB->ParameterOffset = cpu_to_le16(
3792 offsetof(struct smb_com_transaction2_fnext_req,SearchHandle) - 4);
3793 pSMB->DataCount = 0;
3794 pSMB->DataOffset = 0;
3795 pSMB->SetupCount = 1;
3796 pSMB->Reserved3 = 0;
3797 pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_NEXT);
3798 pSMB->SearchHandle = searchHandle; /* always kept as le */
3800 cpu_to_le16(CIFSMaxBufSize / sizeof(FILE_UNIX_INFO));
3801 pSMB->InformationLevel = cpu_to_le16(psrch_inf->info_level);
3802 pSMB->ResumeKey = psrch_inf->resume_key;
3804 cpu_to_le16(CIFS_SEARCH_CLOSE_AT_END | CIFS_SEARCH_RETURN_RESUME);
3806 name_len = psrch_inf->resume_name_len;
3808 if (name_len < PATH_MAX) {
3809 memcpy(pSMB->ResumeFileName, psrch_inf->presume_name, name_len);
3810 byte_count += name_len;
3811 /* 14 byte parm len above enough for 2 byte null terminator */
3812 pSMB->ResumeFileName[name_len] = 0;
3813 pSMB->ResumeFileName[name_len+1] = 0;
3816 goto FNext2_err_exit;
3818 byte_count = params + 1 /* pad */ ;
3819 pSMB->TotalParameterCount = cpu_to_le16(params);
3820 pSMB->ParameterCount = pSMB->TotalParameterCount;
3821 pSMB->hdr.smb_buf_length += byte_count;
3822 pSMB->ByteCount = cpu_to_le16(byte_count);
3824 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3825 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3826 cifs_stats_inc(&tcon->num_fnext);
3829 psrch_inf->endOfSearch = true;
3830 cifs_buf_release(pSMB);
3831 rc = 0; /* search probably was closed at end of search*/
3833 cFYI(1, "FindNext returned = %d", rc);
3834 } else { /* decode response */
3835 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3840 /* BB fixme add lock for file (srch_info) struct here */
3841 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
3842 psrch_inf->unicode = true;
3844 psrch_inf->unicode = false;
3845 response_data = (char *) &pSMBr->hdr.Protocol +
3846 le16_to_cpu(pSMBr->t2.ParameterOffset);
3847 parms = (T2_FNEXT_RSP_PARMS *)response_data;
3848 response_data = (char *)&pSMBr->hdr.Protocol +
3849 le16_to_cpu(pSMBr->t2.DataOffset);
3850 if (psrch_inf->smallBuf)
3851 cifs_small_buf_release(
3852 psrch_inf->ntwrk_buf_start);
3854 cifs_buf_release(psrch_inf->ntwrk_buf_start);
3855 psrch_inf->srch_entries_start = response_data;
3856 psrch_inf->ntwrk_buf_start = (char *)pSMB;
3857 psrch_inf->smallBuf = 0;
3858 if (parms->EndofSearch)
3859 psrch_inf->endOfSearch = true;
3861 psrch_inf->endOfSearch = false;
3862 psrch_inf->entries_in_buffer =
3863 le16_to_cpu(parms->SearchCount);
3864 psrch_inf->index_of_last_entry +=
3865 psrch_inf->entries_in_buffer;
3866 lnoff = le16_to_cpu(parms->LastNameOffset);
3867 if (tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE <
3869 cERROR(1, "ignoring corrupt resume name");
3870 psrch_inf->last_entry = NULL;
3873 psrch_inf->last_entry =
3874 psrch_inf->srch_entries_start + lnoff;
3876 /* cFYI(1, "fnxt2 entries in buf %d index_of_last %d",
3877 psrch_inf->entries_in_buffer, psrch_inf->index_of_last_entry); */
3879 /* BB fixme add unlock here */
3884 /* BB On error, should we leave previous search buf (and count and
3885 last entry fields) intact or free the previous one? */
3887 /* Note: On -EAGAIN error only caller can retry on handle based calls
3888 since file handle passed in no longer valid */
3891 cifs_buf_release(pSMB);
3896 CIFSFindClose(const int xid, struct cifsTconInfo *tcon,
3897 const __u16 searchHandle)
3900 FINDCLOSE_REQ *pSMB = NULL;
3902 cFYI(1, "In CIFSSMBFindClose");
3903 rc = small_smb_init(SMB_COM_FIND_CLOSE2, 1, tcon, (void **)&pSMB);
3905 /* no sense returning error if session restarted
3906 as file handle has been closed */
3912 pSMB->FileID = searchHandle;
3913 pSMB->ByteCount = 0;
3914 rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0);
3916 cERROR(1, "Send error in FindClose = %d", rc);
3918 cifs_stats_inc(&tcon->num_fclose);
3920 /* Since session is dead, search handle closed on server already */
3928 CIFSGetSrvInodeNumber(const int xid, struct cifsTconInfo *tcon,
3929 const unsigned char *searchName,
3930 __u64 *inode_number,
3931 const struct nls_table *nls_codepage, int remap)
3934 TRANSACTION2_QPI_REQ *pSMB = NULL;
3935 TRANSACTION2_QPI_RSP *pSMBr = NULL;
3936 int name_len, bytes_returned;
3937 __u16 params, byte_count;
3939 cFYI(1, "In GetSrvInodeNum for %s", searchName);
3943 GetInodeNumberRetry:
3944 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3949 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3951 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
3952 PATH_MAX, nls_codepage, remap);
3953 name_len++; /* trailing null */
3955 } else { /* BB improve the check for buffer overruns BB */
3956 name_len = strnlen(searchName, PATH_MAX);
3957 name_len++; /* trailing null */
3958 strncpy(pSMB->FileName, searchName, name_len);
3961 params = 2 /* level */ + 4 /* rsrvd */ + name_len /* incl null */ ;
3962 pSMB->TotalDataCount = 0;
3963 pSMB->MaxParameterCount = cpu_to_le16(2);
3964 /* BB find exact max data count below from sess structure BB */
3965 pSMB->MaxDataCount = cpu_to_le16(4000);
3966 pSMB->MaxSetupCount = 0;
3970 pSMB->Reserved2 = 0;
3971 pSMB->ParameterOffset = cpu_to_le16(offsetof(
3972 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
3973 pSMB->DataCount = 0;
3974 pSMB->DataOffset = 0;
3975 pSMB->SetupCount = 1;
3976 pSMB->Reserved3 = 0;
3977 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
3978 byte_count = params + 1 /* pad */ ;
3979 pSMB->TotalParameterCount = cpu_to_le16(params);
3980 pSMB->ParameterCount = pSMB->TotalParameterCount;
3981 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_INTERNAL_INFO);
3982 pSMB->Reserved4 = 0;
3983 pSMB->hdr.smb_buf_length += byte_count;
3984 pSMB->ByteCount = cpu_to_le16(byte_count);
3986 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3987 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3989 cFYI(1, "error %d in QueryInternalInfo", rc);
3991 /* decode response */
3992 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3993 if (rc || (pSMBr->ByteCount < 2))
3994 /* BB also check enough total bytes returned */
3995 /* If rc should we check for EOPNOSUPP and
3996 disable the srvino flag? or in caller? */
3997 rc = -EIO; /* bad smb */
3999 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4000 __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
4001 struct file_internal_info *pfinfo;
4002 /* BB Do we need a cast or hash here ? */
4004 cFYI(1, "Illegal size ret in QryIntrnlInf");
4006 goto GetInodeNumOut;
4008 pfinfo = (struct file_internal_info *)
4009 (data_offset + (char *) &pSMBr->hdr.Protocol);
4010 *inode_number = le64_to_cpu(pfinfo->UniqueId);
4014 cifs_buf_release(pSMB);
4016 goto GetInodeNumberRetry;
4020 /* parses DFS refferal V3 structure
4021 * caller is responsible for freeing target_nodes
4024 * on failure - errno
4027 parse_DFS_referrals(TRANSACTION2_GET_DFS_REFER_RSP *pSMBr,
4028 unsigned int *num_of_nodes,
4029 struct dfs_info3_param **target_nodes,
4030 const struct nls_table *nls_codepage, int remap,
4031 const char *searchName)
4036 struct dfs_referral_level_3 *ref;
4038 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
4042 *num_of_nodes = le16_to_cpu(pSMBr->NumberOfReferrals);
4044 if (*num_of_nodes < 1) {
4045 cERROR(1, "num_referrals: must be at least > 0,"
4046 "but we get num_referrals = %d\n", *num_of_nodes);
4048 goto parse_DFS_referrals_exit;
4051 ref = (struct dfs_referral_level_3 *) &(pSMBr->referrals);
4052 if (ref->VersionNumber != cpu_to_le16(3)) {
4053 cERROR(1, "Referrals of V%d version are not supported,"
4054 "should be V3", le16_to_cpu(ref->VersionNumber));
4056 goto parse_DFS_referrals_exit;
4059 /* get the upper boundary of the resp buffer */
4060 data_end = (char *)(&(pSMBr->PathConsumed)) +
4061 le16_to_cpu(pSMBr->t2.DataCount);
4063 cFYI(1, "num_referrals: %d dfs flags: 0x%x ...\n",
4065 le32_to_cpu(pSMBr->DFSFlags));
4067 *target_nodes = kzalloc(sizeof(struct dfs_info3_param) *
4068 *num_of_nodes, GFP_KERNEL);
4069 if (*target_nodes == NULL) {
4070 cERROR(1, "Failed to allocate buffer for target_nodes\n");
4072 goto parse_DFS_referrals_exit;
4075 /* collect necessary data from referrals */
4076 for (i = 0; i < *num_of_nodes; i++) {
4079 struct dfs_info3_param *node = (*target_nodes)+i;
4081 node->flags = le32_to_cpu(pSMBr->DFSFlags);
4083 __le16 *tmp = kmalloc(strlen(searchName)*2 + 2,
4087 goto parse_DFS_referrals_exit;
4089 cifsConvertToUCS((__le16 *) tmp, searchName,
4090 PATH_MAX, nls_codepage, remap);
4091 node->path_consumed = cifs_ucs2_bytes(tmp,
4092 le16_to_cpu(pSMBr->PathConsumed),
4096 node->path_consumed = le16_to_cpu(pSMBr->PathConsumed);
4098 node->server_type = le16_to_cpu(ref->ServerType);
4099 node->ref_flag = le16_to_cpu(ref->ReferralEntryFlags);
4102 temp = (char *)ref + le16_to_cpu(ref->DfsPathOffset);
4103 max_len = data_end - temp;
4104 node->path_name = cifs_strndup_from_ucs(temp, max_len,
4105 is_unicode, nls_codepage);
4106 if (!node->path_name) {
4108 goto parse_DFS_referrals_exit;
4111 /* copy link target UNC */
4112 temp = (char *)ref + le16_to_cpu(ref->NetworkAddressOffset);
4113 max_len = data_end - temp;
4114 node->node_name = cifs_strndup_from_ucs(temp, max_len,
4115 is_unicode, nls_codepage);
4116 if (!node->node_name)
4120 parse_DFS_referrals_exit:
4122 free_dfs_info_array(*target_nodes, *num_of_nodes);
4123 *target_nodes = NULL;
4130 CIFSGetDFSRefer(const int xid, struct cifsSesInfo *ses,
4131 const unsigned char *searchName,
4132 struct dfs_info3_param **target_nodes,
4133 unsigned int *num_of_nodes,
4134 const struct nls_table *nls_codepage, int remap)
4136 /* TRANS2_GET_DFS_REFERRAL */
4137 TRANSACTION2_GET_DFS_REFER_REQ *pSMB = NULL;
4138 TRANSACTION2_GET_DFS_REFER_RSP *pSMBr = NULL;
4142 __u16 params, byte_count;
4144 *target_nodes = NULL;
4146 cFYI(1, "In GetDFSRefer the path %s", searchName);
4150 rc = smb_init(SMB_COM_TRANSACTION2, 15, NULL, (void **) &pSMB,
4155 /* server pointer checked in called function,
4156 but should never be null here anyway */
4157 pSMB->hdr.Mid = GetNextMid(ses->server);
4158 pSMB->hdr.Tid = ses->ipc_tid;
4159 pSMB->hdr.Uid = ses->Suid;
4160 if (ses->capabilities & CAP_STATUS32)
4161 pSMB->hdr.Flags2 |= SMBFLG2_ERR_STATUS;
4162 if (ses->capabilities & CAP_DFS)
4163 pSMB->hdr.Flags2 |= SMBFLG2_DFS;
4165 if (ses->capabilities & CAP_UNICODE) {
4166 pSMB->hdr.Flags2 |= SMBFLG2_UNICODE;
4168 cifsConvertToUCS((__le16 *) pSMB->RequestFileName,
4169 searchName, PATH_MAX, nls_codepage, remap);
4170 name_len++; /* trailing null */
4172 } else { /* BB improve the check for buffer overruns BB */
4173 name_len = strnlen(searchName, PATH_MAX);
4174 name_len++; /* trailing null */
4175 strncpy(pSMB->RequestFileName, searchName, name_len);
4179 if (ses->server->secMode &
4180 (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
4181 pSMB->hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
4184 pSMB->hdr.Uid = ses->Suid;
4186 params = 2 /* level */ + name_len /*includes null */ ;
4187 pSMB->TotalDataCount = 0;
4188 pSMB->DataCount = 0;
4189 pSMB->DataOffset = 0;
4190 pSMB->MaxParameterCount = 0;
4191 /* BB find exact max SMB PDU from sess structure BB */
4192 pSMB->MaxDataCount = cpu_to_le16(4000);
4193 pSMB->MaxSetupCount = 0;
4197 pSMB->Reserved2 = 0;
4198 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4199 struct smb_com_transaction2_get_dfs_refer_req, MaxReferralLevel) - 4);
4200 pSMB->SetupCount = 1;
4201 pSMB->Reserved3 = 0;
4202 pSMB->SubCommand = cpu_to_le16(TRANS2_GET_DFS_REFERRAL);
4203 byte_count = params + 3 /* pad */ ;
4204 pSMB->ParameterCount = cpu_to_le16(params);
4205 pSMB->TotalParameterCount = pSMB->ParameterCount;
4206 pSMB->MaxReferralLevel = cpu_to_le16(3);
4207 pSMB->hdr.smb_buf_length += byte_count;
4208 pSMB->ByteCount = cpu_to_le16(byte_count);
4210 rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB,
4211 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4213 cFYI(1, "Send error in GetDFSRefer = %d", rc);
4216 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4218 /* BB Also check if enough total bytes returned? */
4219 if (rc || (pSMBr->ByteCount < 17)) {
4220 rc = -EIO; /* bad smb */
4224 cFYI(1, "Decoding GetDFSRefer response BCC: %d Offset %d",
4226 le16_to_cpu(pSMBr->t2.DataOffset));
4228 /* parse returned result into more usable form */
4229 rc = parse_DFS_referrals(pSMBr, num_of_nodes,
4230 target_nodes, nls_codepage, remap,
4234 cifs_buf_release(pSMB);
4242 /* Query File System Info such as free space to old servers such as Win 9x */
4244 SMBOldQFSInfo(const int xid, struct cifsTconInfo *tcon, struct kstatfs *FSData)
4246 /* level 0x01 SMB_QUERY_FILE_SYSTEM_INFO */
4247 TRANSACTION2_QFSI_REQ *pSMB = NULL;
4248 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4249 FILE_SYSTEM_ALLOC_INFO *response_data;
4251 int bytes_returned = 0;
4252 __u16 params, byte_count;
4254 cFYI(1, "OldQFSInfo");
4256 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4261 params = 2; /* level */
4262 pSMB->TotalDataCount = 0;
4263 pSMB->MaxParameterCount = cpu_to_le16(2);
4264 pSMB->MaxDataCount = cpu_to_le16(1000);
4265 pSMB->MaxSetupCount = 0;
4269 pSMB->Reserved2 = 0;
4270 byte_count = params + 1 /* pad */ ;
4271 pSMB->TotalParameterCount = cpu_to_le16(params);
4272 pSMB->ParameterCount = pSMB->TotalParameterCount;
4273 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4274 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4275 pSMB->DataCount = 0;
4276 pSMB->DataOffset = 0;
4277 pSMB->SetupCount = 1;
4278 pSMB->Reserved3 = 0;
4279 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4280 pSMB->InformationLevel = cpu_to_le16(SMB_INFO_ALLOCATION);
4281 pSMB->hdr.smb_buf_length += byte_count;
4282 pSMB->ByteCount = cpu_to_le16(byte_count);
4284 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4285 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4287 cFYI(1, "Send error in QFSInfo = %d", rc);
4288 } else { /* decode response */
4289 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4291 if (rc || (pSMBr->ByteCount < 18))
4292 rc = -EIO; /* bad smb */
4294 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4295 cFYI(1, "qfsinf resp BCC: %d Offset %d",
4296 pSMBr->ByteCount, data_offset);
4298 response_data = (FILE_SYSTEM_ALLOC_INFO *)
4299 (((char *) &pSMBr->hdr.Protocol) + data_offset);
4301 le16_to_cpu(response_data->BytesPerSector) *
4302 le32_to_cpu(response_data->
4303 SectorsPerAllocationUnit);
4305 le32_to_cpu(response_data->TotalAllocationUnits);
4306 FSData->f_bfree = FSData->f_bavail =
4307 le32_to_cpu(response_data->FreeAllocationUnits);
4308 cFYI(1, "Blocks: %lld Free: %lld Block size %ld",
4309 (unsigned long long)FSData->f_blocks,
4310 (unsigned long long)FSData->f_bfree,
4314 cifs_buf_release(pSMB);
4317 goto oldQFSInfoRetry;
4323 CIFSSMBQFSInfo(const int xid, struct cifsTconInfo *tcon, struct kstatfs *FSData)
4325 /* level 0x103 SMB_QUERY_FILE_SYSTEM_INFO */
4326 TRANSACTION2_QFSI_REQ *pSMB = NULL;
4327 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4328 FILE_SYSTEM_INFO *response_data;
4330 int bytes_returned = 0;
4331 __u16 params, byte_count;
4333 cFYI(1, "In QFSInfo");
4335 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4340 params = 2; /* level */
4341 pSMB->TotalDataCount = 0;
4342 pSMB->MaxParameterCount = cpu_to_le16(2);
4343 pSMB->MaxDataCount = cpu_to_le16(1000);
4344 pSMB->MaxSetupCount = 0;
4348 pSMB->Reserved2 = 0;
4349 byte_count = params + 1 /* pad */ ;
4350 pSMB->TotalParameterCount = cpu_to_le16(params);
4351 pSMB->ParameterCount = pSMB->TotalParameterCount;
4352 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4353 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4354 pSMB->DataCount = 0;
4355 pSMB->DataOffset = 0;
4356 pSMB->SetupCount = 1;
4357 pSMB->Reserved3 = 0;
4358 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4359 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_SIZE_INFO);
4360 pSMB->hdr.smb_buf_length += byte_count;
4361 pSMB->ByteCount = cpu_to_le16(byte_count);
4363 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4364 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4366 cFYI(1, "Send error in QFSInfo = %d", rc);
4367 } else { /* decode response */
4368 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4370 if (rc || (pSMBr->ByteCount < 24))
4371 rc = -EIO; /* bad smb */
4373 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4377 *) (((char *) &pSMBr->hdr.Protocol) +
4380 le32_to_cpu(response_data->BytesPerSector) *
4381 le32_to_cpu(response_data->
4382 SectorsPerAllocationUnit);
4384 le64_to_cpu(response_data->TotalAllocationUnits);
4385 FSData->f_bfree = FSData->f_bavail =
4386 le64_to_cpu(response_data->FreeAllocationUnits);
4387 cFYI(1, "Blocks: %lld Free: %lld Block size %ld",
4388 (unsigned long long)FSData->f_blocks,
4389 (unsigned long long)FSData->f_bfree,
4393 cifs_buf_release(pSMB);
4402 CIFSSMBQFSAttributeInfo(const int xid, struct cifsTconInfo *tcon)
4404 /* level 0x105 SMB_QUERY_FILE_SYSTEM_INFO */
4405 TRANSACTION2_QFSI_REQ *pSMB = NULL;
4406 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4407 FILE_SYSTEM_ATTRIBUTE_INFO *response_data;
4409 int bytes_returned = 0;
4410 __u16 params, byte_count;
4412 cFYI(1, "In QFSAttributeInfo");
4414 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4419 params = 2; /* level */
4420 pSMB->TotalDataCount = 0;
4421 pSMB->MaxParameterCount = cpu_to_le16(2);
4422 /* BB find exact max SMB PDU from sess structure BB */
4423 pSMB->MaxDataCount = cpu_to_le16(1000);
4424 pSMB->MaxSetupCount = 0;
4428 pSMB->Reserved2 = 0;
4429 byte_count = params + 1 /* pad */ ;
4430 pSMB->TotalParameterCount = cpu_to_le16(params);
4431 pSMB->ParameterCount = pSMB->TotalParameterCount;
4432 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4433 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4434 pSMB->DataCount = 0;
4435 pSMB->DataOffset = 0;
4436 pSMB->SetupCount = 1;
4437 pSMB->Reserved3 = 0;
4438 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4439 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_ATTRIBUTE_INFO);
4440 pSMB->hdr.smb_buf_length += byte_count;
4441 pSMB->ByteCount = cpu_to_le16(byte_count);
4443 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4444 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4446 cERROR(1, "Send error in QFSAttributeInfo = %d", rc);
4447 } else { /* decode response */
4448 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4450 if (rc || (pSMBr->ByteCount < 13)) {
4451 /* BB also check if enough bytes returned */
4452 rc = -EIO; /* bad smb */
4454 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4456 (FILE_SYSTEM_ATTRIBUTE_INFO
4457 *) (((char *) &pSMBr->hdr.Protocol) +
4459 memcpy(&tcon->fsAttrInfo, response_data,
4460 sizeof(FILE_SYSTEM_ATTRIBUTE_INFO));
4463 cifs_buf_release(pSMB);
4466 goto QFSAttributeRetry;
4472 CIFSSMBQFSDeviceInfo(const int xid, struct cifsTconInfo *tcon)
4474 /* level 0x104 SMB_QUERY_FILE_SYSTEM_INFO */
4475 TRANSACTION2_QFSI_REQ *pSMB = NULL;
4476 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4477 FILE_SYSTEM_DEVICE_INFO *response_data;
4479 int bytes_returned = 0;
4480 __u16 params, byte_count;
4482 cFYI(1, "In QFSDeviceInfo");
4484 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4489 params = 2; /* level */
4490 pSMB->TotalDataCount = 0;
4491 pSMB->MaxParameterCount = cpu_to_le16(2);
4492 /* BB find exact max SMB PDU from sess structure BB */
4493 pSMB->MaxDataCount = cpu_to_le16(1000);
4494 pSMB->MaxSetupCount = 0;
4498 pSMB->Reserved2 = 0;
4499 byte_count = params + 1 /* pad */ ;
4500 pSMB->TotalParameterCount = cpu_to_le16(params);
4501 pSMB->ParameterCount = pSMB->TotalParameterCount;
4502 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4503 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4505 pSMB->DataCount = 0;
4506 pSMB->DataOffset = 0;
4507 pSMB->SetupCount = 1;
4508 pSMB->Reserved3 = 0;
4509 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4510 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_DEVICE_INFO);
4511 pSMB->hdr.smb_buf_length += byte_count;
4512 pSMB->ByteCount = cpu_to_le16(byte_count);
4514 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4515 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4517 cFYI(1, "Send error in QFSDeviceInfo = %d", rc);
4518 } else { /* decode response */
4519 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4521 if (rc || (pSMBr->ByteCount < sizeof(FILE_SYSTEM_DEVICE_INFO)))
4522 rc = -EIO; /* bad smb */
4524 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4526 (FILE_SYSTEM_DEVICE_INFO *)
4527 (((char *) &pSMBr->hdr.Protocol) +
4529 memcpy(&tcon->fsDevInfo, response_data,
4530 sizeof(FILE_SYSTEM_DEVICE_INFO));
4533 cifs_buf_release(pSMB);
4536 goto QFSDeviceRetry;
4542 CIFSSMBQFSUnixInfo(const int xid, struct cifsTconInfo *tcon)
4544 /* level 0x200 SMB_QUERY_CIFS_UNIX_INFO */
4545 TRANSACTION2_QFSI_REQ *pSMB = NULL;
4546 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4547 FILE_SYSTEM_UNIX_INFO *response_data;
4549 int bytes_returned = 0;
4550 __u16 params, byte_count;
4552 cFYI(1, "In QFSUnixInfo");
4554 rc = smb_init_no_reconnect(SMB_COM_TRANSACTION2, 15, tcon,
4555 (void **) &pSMB, (void **) &pSMBr);
4559 params = 2; /* level */
4560 pSMB->TotalDataCount = 0;
4561 pSMB->DataCount = 0;
4562 pSMB->DataOffset = 0;
4563 pSMB->MaxParameterCount = cpu_to_le16(2);
4564 /* BB find exact max SMB PDU from sess structure BB */
4565 pSMB->MaxDataCount = cpu_to_le16(100);
4566 pSMB->MaxSetupCount = 0;
4570 pSMB->Reserved2 = 0;
4571 byte_count = params + 1 /* pad */ ;
4572 pSMB->ParameterCount = cpu_to_le16(params);
4573 pSMB->TotalParameterCount = pSMB->ParameterCount;
4574 pSMB->ParameterOffset = cpu_to_le16(offsetof(struct
4575 smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4576 pSMB->SetupCount = 1;
4577 pSMB->Reserved3 = 0;
4578 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4579 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_CIFS_UNIX_INFO);
4580 pSMB->hdr.smb_buf_length += byte_count;
4581 pSMB->ByteCount = cpu_to_le16(byte_count);
4583 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4584 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4586 cERROR(1, "Send error in QFSUnixInfo = %d", rc);
4587 } else { /* decode response */
4588 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4590 if (rc || (pSMBr->ByteCount < 13)) {
4591 rc = -EIO; /* bad smb */
4593 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4595 (FILE_SYSTEM_UNIX_INFO
4596 *) (((char *) &pSMBr->hdr.Protocol) +
4598 memcpy(&tcon->fsUnixInfo, response_data,
4599 sizeof(FILE_SYSTEM_UNIX_INFO));
4602 cifs_buf_release(pSMB);
4612 CIFSSMBSetFSUnixInfo(const int xid, struct cifsTconInfo *tcon, __u64 cap)
4614 /* level 0x200 SMB_SET_CIFS_UNIX_INFO */
4615 TRANSACTION2_SETFSI_REQ *pSMB = NULL;
4616 TRANSACTION2_SETFSI_RSP *pSMBr = NULL;
4618 int bytes_returned = 0;
4619 __u16 params, param_offset, offset, byte_count;
4621 cFYI(1, "In SETFSUnixInfo");
4623 /* BB switch to small buf init to save memory */
4624 rc = smb_init_no_reconnect(SMB_COM_TRANSACTION2, 15, tcon,
4625 (void **) &pSMB, (void **) &pSMBr);
4629 params = 4; /* 2 bytes zero followed by info level. */
4630 pSMB->MaxSetupCount = 0;
4634 pSMB->Reserved2 = 0;
4635 param_offset = offsetof(struct smb_com_transaction2_setfsi_req, FileNum)
4637 offset = param_offset + params;
4639 pSMB->MaxParameterCount = cpu_to_le16(4);
4640 /* BB find exact max SMB PDU from sess structure BB */
4641 pSMB->MaxDataCount = cpu_to_le16(100);
4642 pSMB->SetupCount = 1;
4643 pSMB->Reserved3 = 0;
4644 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FS_INFORMATION);
4645 byte_count = 1 /* pad */ + params + 12;
4647 pSMB->DataCount = cpu_to_le16(12);
4648 pSMB->ParameterCount = cpu_to_le16(params);
4649 pSMB->TotalDataCount = pSMB->DataCount;
4650 pSMB->TotalParameterCount = pSMB->ParameterCount;
4651 pSMB->ParameterOffset = cpu_to_le16(param_offset);
4652 pSMB->DataOffset = cpu_to_le16(offset);
4656 pSMB->InformationLevel = cpu_to_le16(SMB_SET_CIFS_UNIX_INFO);
4659 pSMB->ClientUnixMajor = cpu_to_le16(CIFS_UNIX_MAJOR_VERSION);
4660 pSMB->ClientUnixMinor = cpu_to_le16(CIFS_UNIX_MINOR_VERSION);
4661 pSMB->ClientUnixCap = cpu_to_le64(cap);
4663 pSMB->hdr.smb_buf_length += byte_count;
4664 pSMB->ByteCount = cpu_to_le16(byte_count);
4666 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4667 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4669 cERROR(1, "Send error in SETFSUnixInfo = %d", rc);
4670 } else { /* decode response */
4671 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4673 rc = -EIO; /* bad smb */
4675 cifs_buf_release(pSMB);
4678 goto SETFSUnixRetry;
4686 CIFSSMBQFSPosixInfo(const int xid, struct cifsTconInfo *tcon,
4687 struct kstatfs *FSData)
4689 /* level 0x201 SMB_QUERY_CIFS_POSIX_INFO */
4690 TRANSACTION2_QFSI_REQ *pSMB = NULL;
4691 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4692 FILE_SYSTEM_POSIX_INFO *response_data;
4694 int bytes_returned = 0;
4695 __u16 params, byte_count;
4697 cFYI(1, "In QFSPosixInfo");
4699 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4704 params = 2; /* level */
4705 pSMB->TotalDataCount = 0;
4706 pSMB->DataCount = 0;
4707 pSMB->DataOffset = 0;
4708 pSMB->MaxParameterCount = cpu_to_le16(2);
4709 /* BB find exact max SMB PDU from sess structure BB */
4710 pSMB->MaxDataCount = cpu_to_le16(100);
4711 pSMB->MaxSetupCount = 0;
4715 pSMB->Reserved2 = 0;
4716 byte_count = params + 1 /* pad */ ;
4717 pSMB->ParameterCount = cpu_to_le16(params);
4718 pSMB->TotalParameterCount = pSMB->ParameterCount;
4719 pSMB->ParameterOffset = cpu_to_le16(offsetof(struct
4720 smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4721 pSMB->SetupCount = 1;
4722 pSMB->Reserved3 = 0;
4723 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4724 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_POSIX_FS_INFO);
4725 pSMB->hdr.smb_buf_length += byte_count;
4726 pSMB->ByteCount = cpu_to_le16(byte_count);
4728 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4729 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4731 cFYI(1, "Send error in QFSUnixInfo = %d", rc);
4732 } else { /* decode response */
4733 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4735 if (rc || (pSMBr->ByteCount < 13)) {
4736 rc = -EIO; /* bad smb */
4738 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4740 (FILE_SYSTEM_POSIX_INFO
4741 *) (((char *) &pSMBr->hdr.Protocol) +
4744 le32_to_cpu(response_data->BlockSize);
4746 le64_to_cpu(response_data->TotalBlocks);
4748 le64_to_cpu(response_data->BlocksAvail);
4749 if (response_data->UserBlocksAvail == cpu_to_le64(-1)) {
4750 FSData->f_bavail = FSData->f_bfree;
4753 le64_to_cpu(response_data->UserBlocksAvail);
4755 if (response_data->TotalFileNodes != cpu_to_le64(-1))
4757 le64_to_cpu(response_data->TotalFileNodes);
4758 if (response_data->FreeFileNodes != cpu_to_le64(-1))
4760 le64_to_cpu(response_data->FreeFileNodes);
4763 cifs_buf_release(pSMB);
4772 /* We can not use write of zero bytes trick to
4773 set file size due to need for large file support. Also note that
4774 this SetPathInfo is preferred to SetFileInfo based method in next
4775 routine which is only needed to work around a sharing violation bug
4776 in Samba which this routine can run into */
4779 CIFSSMBSetEOF(const int xid, struct cifsTconInfo *tcon, const char *fileName,
4780 __u64 size, bool SetAllocation,
4781 const struct nls_table *nls_codepage, int remap)
4783 struct smb_com_transaction2_spi_req *pSMB = NULL;
4784 struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
4785 struct file_end_of_file_info *parm_data;
4788 int bytes_returned = 0;
4789 __u16 params, byte_count, data_count, param_offset, offset;
4791 cFYI(1, "In SetEOF");
4793 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4798 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4800 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
4801 PATH_MAX, nls_codepage, remap);
4802 name_len++; /* trailing null */
4804 } else { /* BB improve the check for buffer overruns BB */
4805 name_len = strnlen(fileName, PATH_MAX);
4806 name_len++; /* trailing null */
4807 strncpy(pSMB->FileName, fileName, name_len);
4809 params = 6 + name_len;
4810 data_count = sizeof(struct file_end_of_file_info);
4811 pSMB->MaxParameterCount = cpu_to_le16(2);
4812 pSMB->MaxDataCount = cpu_to_le16(4100);
4813 pSMB->MaxSetupCount = 0;
4817 pSMB->Reserved2 = 0;
4818 param_offset = offsetof(struct smb_com_transaction2_spi_req,
4819 InformationLevel) - 4;
4820 offset = param_offset + params;
4821 if (SetAllocation) {
4822 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
4823 pSMB->InformationLevel =
4824 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2);
4826 pSMB->InformationLevel =
4827 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO);
4828 } else /* Set File Size */ {
4829 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
4830 pSMB->InformationLevel =
4831 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO2);
4833 pSMB->InformationLevel =
4834 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO);
4838 (struct file_end_of_file_info *) (((char *) &pSMB->hdr.Protocol) +
4840 pSMB->ParameterOffset = cpu_to_le16(param_offset);
4841 pSMB->DataOffset = cpu_to_le16(offset);
4842 pSMB->SetupCount = 1;
4843 pSMB->Reserved3 = 0;
4844 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
4845 byte_count = 3 /* pad */ + params + data_count;
4846 pSMB->DataCount = cpu_to_le16(data_count);
4847 pSMB->TotalDataCount = pSMB->DataCount;
4848 pSMB->ParameterCount = cpu_to_le16(params);
4849 pSMB->TotalParameterCount = pSMB->ParameterCount;
4850 pSMB->Reserved4 = 0;
4851 pSMB->hdr.smb_buf_length += byte_count;
4852 parm_data->FileSize = cpu_to_le64(size);
4853 pSMB->ByteCount = cpu_to_le16(byte_count);
4854 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4855 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4857 cFYI(1, "SetPathInfo (file size) returned %d", rc);
4859 cifs_buf_release(pSMB);
4868 CIFSSMBSetFileSize(const int xid, struct cifsTconInfo *tcon, __u64 size,
4869 __u16 fid, __u32 pid_of_opener, bool SetAllocation)
4871 struct smb_com_transaction2_sfi_req *pSMB = NULL;
4873 struct file_end_of_file_info *parm_data;
4875 __u16 params, param_offset, offset, byte_count, count;
4877 cFYI(1, "SetFileSize (via SetFileInfo) %lld",
4879 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
4884 pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
4885 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));
4888 pSMB->MaxSetupCount = 0;
4892 pSMB->Reserved2 = 0;
4893 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
4894 offset = param_offset + params;
4896 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
4898 count = sizeof(struct file_end_of_file_info);
4899 pSMB->MaxParameterCount = cpu_to_le16(2);
4900 /* BB find exact max SMB PDU from sess structure BB */
4901 pSMB->MaxDataCount = cpu_to_le16(1000);
4902 pSMB->SetupCount = 1;
4903 pSMB->Reserved3 = 0;
4904 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
4905 byte_count = 3 /* pad */ + params + count;
4906 pSMB->DataCount = cpu_to_le16(count);
4907 pSMB->ParameterCount = cpu_to_le16(params);
4908 pSMB->TotalDataCount = pSMB->DataCount;
4909 pSMB->TotalParameterCount = pSMB->ParameterCount;
4910 pSMB->ParameterOffset = cpu_to_le16(param_offset);
4912 (struct file_end_of_file_info *) (((char *) &pSMB->hdr.Protocol)
4914 pSMB->DataOffset = cpu_to_le16(offset);
4915 parm_data->FileSize = cpu_to_le64(size);
4917 if (SetAllocation) {
4918 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
4919 pSMB->InformationLevel =
4920 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2);
4922 pSMB->InformationLevel =
4923 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO);
4924 } else /* Set File Size */ {
4925 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
4926 pSMB->InformationLevel =
4927 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO2);
4929 pSMB->InformationLevel =
4930 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO);
4932 pSMB->Reserved4 = 0;
4933 pSMB->hdr.smb_buf_length += byte_count;
4934 pSMB->ByteCount = cpu_to_le16(byte_count);
4935 rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0);
4937 cFYI(1, "Send error in SetFileInfo (SetFileSize) = %d", rc);
4940 /* Note: On -EAGAIN error only caller can retry on handle based calls
4941 since file handle passed in no longer valid */
4946 /* Some legacy servers such as NT4 require that the file times be set on
4947 an open handle, rather than by pathname - this is awkward due to
4948 potential access conflicts on the open, but it is unavoidable for these
4949 old servers since the only other choice is to go from 100 nanosecond DCE
4950 time and resort to the original setpathinfo level which takes the ancient
4951 DOS time format with 2 second granularity */
4953 CIFSSMBSetFileInfo(const int xid, struct cifsTconInfo *tcon,
4954 const FILE_BASIC_INFO *data, __u16 fid, __u32 pid_of_opener)
4956 struct smb_com_transaction2_sfi_req *pSMB = NULL;
4959 __u16 params, param_offset, offset, byte_count, count;
4961 cFYI(1, "Set Times (via SetFileInfo)");
4962 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
4967 pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
4968 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));
4971 pSMB->MaxSetupCount = 0;
4975 pSMB->Reserved2 = 0;
4976 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
4977 offset = param_offset + params;
4979 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
4981 count = sizeof(FILE_BASIC_INFO);
4982 pSMB->MaxParameterCount = cpu_to_le16(2);
4983 /* BB find max SMB PDU from sess */
4984 pSMB->MaxDataCount = cpu_to_le16(1000);
4985 pSMB->SetupCount = 1;
4986 pSMB->Reserved3 = 0;
4987 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
4988 byte_count = 3 /* pad */ + params + count;
4989 pSMB->DataCount = cpu_to_le16(count);
4990 pSMB->ParameterCount = cpu_to_le16(params);
4991 pSMB->TotalDataCount = pSMB->DataCount;
4992 pSMB->TotalParameterCount = pSMB->ParameterCount;
4993 pSMB->ParameterOffset = cpu_to_le16(param_offset);
4994 pSMB->DataOffset = cpu_to_le16(offset);
4996 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
4997 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO2);
4999 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO);
5000 pSMB->Reserved4 = 0;
5001 pSMB->hdr.smb_buf_length += byte_count;
5002 pSMB->ByteCount = cpu_to_le16(byte_count);
5003 memcpy(data_offset, data, sizeof(FILE_BASIC_INFO));
5004 rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0);
5006 cFYI(1, "Send error in Set Time (SetFileInfo) = %d", rc);
5008 /* Note: On -EAGAIN error only caller can retry on handle based calls
5009 since file handle passed in no longer valid */
5015 CIFSSMBSetFileDisposition(const int xid, struct cifsTconInfo *tcon,
5016 bool delete_file, __u16 fid, __u32 pid_of_opener)
5018 struct smb_com_transaction2_sfi_req *pSMB = NULL;
5021 __u16 params, param_offset, offset, byte_count, count;
5023 cFYI(1, "Set File Disposition (via SetFileInfo)");
5024 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
5029 pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
5030 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));
5033 pSMB->MaxSetupCount = 0;
5037 pSMB->Reserved2 = 0;
5038 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
5039 offset = param_offset + params;
5041 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
5044 pSMB->MaxParameterCount = cpu_to_le16(2);
5045 /* BB find max SMB PDU from sess */
5046 pSMB->MaxDataCount = cpu_to_le16(1000);
5047 pSMB->SetupCount = 1;
5048 pSMB->Reserved3 = 0;
5049 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
5050 byte_count = 3 /* pad */ + params + count;
5051 pSMB->DataCount = cpu_to_le16(count);
5052 pSMB->ParameterCount = cpu_to_le16(params);
5053 pSMB->TotalDataCount = pSMB->DataCount;
5054 pSMB->TotalParameterCount = pSMB->ParameterCount;
5055 pSMB->ParameterOffset = cpu_to_le16(param_offset);
5056 pSMB->DataOffset = cpu_to_le16(offset);
5058 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_DISPOSITION_INFO);
5059 pSMB->Reserved4 = 0;
5060 pSMB->hdr.smb_buf_length += byte_count;
5061 pSMB->ByteCount = cpu_to_le16(byte_count);
5062 *data_offset = delete_file ? 1 : 0;
5063 rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0);
5065 cFYI(1, "Send error in SetFileDisposition = %d", rc);
5071 CIFSSMBSetPathInfo(const int xid, struct cifsTconInfo *tcon,
5072 const char *fileName, const FILE_BASIC_INFO *data,
5073 const struct nls_table *nls_codepage, int remap)
5075 TRANSACTION2_SPI_REQ *pSMB = NULL;
5076 TRANSACTION2_SPI_RSP *pSMBr = NULL;
5079 int bytes_returned = 0;
5081 __u16 params, param_offset, offset, byte_count, count;
5083 cFYI(1, "In SetTimes");
5086 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5091 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5093 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
5094 PATH_MAX, nls_codepage, remap);
5095 name_len++; /* trailing null */
5097 } else { /* BB improve the check for buffer overruns BB */
5098 name_len = strnlen(fileName, PATH_MAX);
5099 name_len++; /* trailing null */
5100 strncpy(pSMB->FileName, fileName, name_len);
5103 params = 6 + name_len;
5104 count = sizeof(FILE_BASIC_INFO);
5105 pSMB->MaxParameterCount = cpu_to_le16(2);
5106 /* BB find max SMB PDU from sess structure BB */
5107 pSMB->MaxDataCount = cpu_to_le16(1000);
5108 pSMB->MaxSetupCount = 0;
5112 pSMB->Reserved2 = 0;
5113 param_offset = offsetof(struct smb_com_transaction2_spi_req,
5114 InformationLevel) - 4;
5115 offset = param_offset + params;
5116 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
5117 pSMB->ParameterOffset = cpu_to_le16(param_offset);
5118 pSMB->DataOffset = cpu_to_le16(offset);
5119 pSMB->SetupCount = 1;
5120 pSMB->Reserved3 = 0;
5121 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
5122 byte_count = 3 /* pad */ + params + count;
5124 pSMB->DataCount = cpu_to_le16(count);
5125 pSMB->ParameterCount = cpu_to_le16(params);
5126 pSMB->TotalDataCount = pSMB->DataCount;
5127 pSMB->TotalParameterCount = pSMB->ParameterCount;
5128 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
5129 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO2);
5131 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO);
5132 pSMB->Reserved4 = 0;
5133 pSMB->hdr.smb_buf_length += byte_count;
5134 memcpy(data_offset, data, sizeof(FILE_BASIC_INFO));
5135 pSMB->ByteCount = cpu_to_le16(byte_count);
5136 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5137 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5139 cFYI(1, "SetPathInfo (times) returned %d", rc);
5141 cifs_buf_release(pSMB);
5149 /* Can not be used to set time stamps yet (due to old DOS time format) */
5150 /* Can be used to set attributes */
5151 #if 0 /* Possibly not needed - since it turns out that strangely NT4 has a bug
5152 handling it anyway and NT4 was what we thought it would be needed for
5153 Do not delete it until we prove whether needed for Win9x though */
5155 CIFSSMBSetAttrLegacy(int xid, struct cifsTconInfo *tcon, char *fileName,
5156 __u16 dos_attrs, const struct nls_table *nls_codepage)
5158 SETATTR_REQ *pSMB = NULL;
5159 SETATTR_RSP *pSMBr = NULL;
5164 cFYI(1, "In SetAttrLegacy");
5167 rc = smb_init(SMB_COM_SETATTR, 8, tcon, (void **) &pSMB,
5172 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5174 ConvertToUCS((__le16 *) pSMB->fileName, fileName,
5175 PATH_MAX, nls_codepage);
5176 name_len++; /* trailing null */
5178 } else { /* BB improve the check for buffer overruns BB */
5179 name_len = strnlen(fileName, PATH_MAX);
5180 name_len++; /* trailing null */
5181 strncpy(pSMB->fileName, fileName, name_len);
5183 pSMB->attr = cpu_to_le16(dos_attrs);
5184 pSMB->BufferFormat = 0x04;
5185 pSMB->hdr.smb_buf_length += name_len + 1;
5186 pSMB->ByteCount = cpu_to_le16(name_len + 1);
5187 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5188 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5190 cFYI(1, "Error in LegacySetAttr = %d", rc);
5192 cifs_buf_release(pSMB);
5195 goto SetAttrLgcyRetry;
5199 #endif /* temporarily unneeded SetAttr legacy function */
5202 cifs_fill_unix_set_info(FILE_UNIX_BASIC_INFO *data_offset,
5203 const struct cifs_unix_set_info_args *args)
5205 u64 mode = args->mode;
5208 * Samba server ignores set of file size to zero due to bugs in some
5209 * older clients, but we should be precise - we use SetFileSize to
5210 * set file size and do not want to truncate file size to zero
5211 * accidently as happened on one Samba server beta by putting
5212 * zero instead of -1 here
5214 data_offset->EndOfFile = cpu_to_le64(NO_CHANGE_64);
5215 data_offset->NumOfBytes = cpu_to_le64(NO_CHANGE_64);
5216 data_offset->LastStatusChange = cpu_to_le64(args->ctime);
5217 data_offset->LastAccessTime = cpu_to_le64(args->atime);
5218 data_offset->LastModificationTime = cpu_to_le64(args->mtime);
5219 data_offset->Uid = cpu_to_le64(args->uid);
5220 data_offset->Gid = cpu_to_le64(args->gid);
5221 /* better to leave device as zero when it is */
5222 data_offset->DevMajor = cpu_to_le64(MAJOR(args->device));
5223 data_offset->DevMinor = cpu_to_le64(MINOR(args->device));
5224 data_offset->Permissions = cpu_to_le64(mode);
5227 data_offset->Type = cpu_to_le32(UNIX_FILE);
5228 else if (S_ISDIR(mode))
5229 data_offset->Type = cpu_to_le32(UNIX_DIR);
5230 else if (S_ISLNK(mode))
5231 data_offset->Type = cpu_to_le32(UNIX_SYMLINK);
5232 else if (S_ISCHR(mode))
5233 data_offset->Type = cpu_to_le32(UNIX_CHARDEV);
5234 else if (S_ISBLK(mode))
5235 data_offset->Type = cpu_to_le32(UNIX_BLOCKDEV);
5236 else if (S_ISFIFO(mode))
5237 data_offset->Type = cpu_to_le32(UNIX_FIFO);
5238 else if (S_ISSOCK(mode))
5239 data_offset->Type = cpu_to_le32(UNIX_SOCKET);
5243 CIFSSMBUnixSetFileInfo(const int xid, struct cifsTconInfo *tcon,
5244 const struct cifs_unix_set_info_args *args,
5245 u16 fid, u32 pid_of_opener)
5247 struct smb_com_transaction2_sfi_req *pSMB = NULL;
5248 FILE_UNIX_BASIC_INFO *data_offset;
5250 u16 params, param_offset, offset, byte_count, count;
5252 cFYI(1, "Set Unix Info (via SetFileInfo)");
5253 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
5258 pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
5259 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));
5262 pSMB->MaxSetupCount = 0;
5266 pSMB->Reserved2 = 0;
5267 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
5268 offset = param_offset + params;
5270 data_offset = (FILE_UNIX_BASIC_INFO *)
5271 ((char *)(&pSMB->hdr.Protocol) + offset);
5272 count = sizeof(FILE_UNIX_BASIC_INFO);
5274 pSMB->MaxParameterCount = cpu_to_le16(2);
5275 /* BB find max SMB PDU from sess */
5276 pSMB->MaxDataCount = cpu_to_le16(1000);
5277 pSMB->SetupCount = 1;
5278 pSMB->Reserved3 = 0;
5279 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
5280 byte_count = 3 /* pad */ + params + count;
5281 pSMB->DataCount = cpu_to_le16(count);
5282 pSMB->ParameterCount = cpu_to_le16(params);
5283 pSMB->TotalDataCount = pSMB->DataCount;
5284 pSMB->TotalParameterCount = pSMB->ParameterCount;
5285 pSMB->ParameterOffset = cpu_to_le16(param_offset);
5286 pSMB->DataOffset = cpu_to_le16(offset);
5288 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_BASIC);
5289 pSMB->Reserved4 = 0;
5290 pSMB->hdr.smb_buf_length += byte_count;
5291 pSMB->ByteCount = cpu_to_le16(byte_count);
5293 cifs_fill_unix_set_info(data_offset, args);
5295 rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0);
5297 cFYI(1, "Send error in Set Time (SetFileInfo) = %d", rc);
5299 /* Note: On -EAGAIN error only caller can retry on handle based calls
5300 since file handle passed in no longer valid */
5306 CIFSSMBUnixSetPathInfo(const int xid, struct cifsTconInfo *tcon, char *fileName,
5307 const struct cifs_unix_set_info_args *args,
5308 const struct nls_table *nls_codepage, int remap)
5310 TRANSACTION2_SPI_REQ *pSMB = NULL;
5311 TRANSACTION2_SPI_RSP *pSMBr = NULL;
5314 int bytes_returned = 0;
5315 FILE_UNIX_BASIC_INFO *data_offset;
5316 __u16 params, param_offset, offset, count, byte_count;
5318 cFYI(1, "In SetUID/GID/Mode");
5320 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5325 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5327 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
5328 PATH_MAX, nls_codepage, remap);
5329 name_len++; /* trailing null */
5331 } else { /* BB improve the check for buffer overruns BB */
5332 name_len = strnlen(fileName, PATH_MAX);
5333 name_len++; /* trailing null */
5334 strncpy(pSMB->FileName, fileName, name_len);
5337 params = 6 + name_len;
5338 count = sizeof(FILE_UNIX_BASIC_INFO);
5339 pSMB->MaxParameterCount = cpu_to_le16(2);
5340 /* BB find max SMB PDU from sess structure BB */
5341 pSMB->MaxDataCount = cpu_to_le16(1000);
5342 pSMB->MaxSetupCount = 0;
5346 pSMB->Reserved2 = 0;
5347 param_offset = offsetof(struct smb_com_transaction2_spi_req,
5348 InformationLevel) - 4;
5349 offset = param_offset + params;
5351 (FILE_UNIX_BASIC_INFO *) ((char *) &pSMB->hdr.Protocol +
5353 memset(data_offset, 0, count);
5354 pSMB->DataOffset = cpu_to_le16(offset);
5355 pSMB->ParameterOffset = cpu_to_le16(param_offset);
5356 pSMB->SetupCount = 1;
5357 pSMB->Reserved3 = 0;
5358 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
5359 byte_count = 3 /* pad */ + params + count;
5360 pSMB->ParameterCount = cpu_to_le16(params);
5361 pSMB->DataCount = cpu_to_le16(count);
5362 pSMB->TotalParameterCount = pSMB->ParameterCount;
5363 pSMB->TotalDataCount = pSMB->DataCount;
5364 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_BASIC);
5365 pSMB->Reserved4 = 0;
5366 pSMB->hdr.smb_buf_length += byte_count;
5368 cifs_fill_unix_set_info(data_offset, args);
5370 pSMB->ByteCount = cpu_to_le16(byte_count);
5371 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5372 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5374 cFYI(1, "SetPathInfo (perms) returned %d", rc);
5376 cifs_buf_release(pSMB);
5382 int CIFSSMBNotify(const int xid, struct cifsTconInfo *tcon,
5383 const int notify_subdirs, const __u16 netfid,
5384 __u32 filter, struct file *pfile, int multishot,
5385 const struct nls_table *nls_codepage)
5388 struct smb_com_transaction_change_notify_req *pSMB = NULL;
5389 struct smb_com_ntransaction_change_notify_rsp *pSMBr = NULL;
5390 struct dir_notify_req *dnotify_req;
5393 cFYI(1, "In CIFSSMBNotify for file handle %d", (int)netfid);
5394 rc = smb_init(SMB_COM_NT_TRANSACT, 23, tcon, (void **) &pSMB,
5399 pSMB->TotalParameterCount = 0 ;
5400 pSMB->TotalDataCount = 0;
5401 pSMB->MaxParameterCount = cpu_to_le32(2);
5402 /* BB find exact data count max from sess structure BB */
5403 pSMB->MaxDataCount = 0; /* same in little endian or be */
5404 /* BB VERIFY verify which is correct for above BB */
5405 pSMB->MaxDataCount = cpu_to_le32((tcon->ses->server->maxBuf -
5406 MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
5408 pSMB->MaxSetupCount = 4;
5410 pSMB->ParameterOffset = 0;
5411 pSMB->DataCount = 0;
5412 pSMB->DataOffset = 0;
5413 pSMB->SetupCount = 4; /* single byte does not need le conversion */
5414 pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_NOTIFY_CHANGE);
5415 pSMB->ParameterCount = pSMB->TotalParameterCount;
5417 pSMB->WatchTree = 1; /* one byte - no le conversion needed */
5418 pSMB->Reserved2 = 0;
5419 pSMB->CompletionFilter = cpu_to_le32(filter);
5420 pSMB->Fid = netfid; /* file handle always le */
5421 pSMB->ByteCount = 0;
5423 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5424 (struct smb_hdr *)pSMBr, &bytes_returned,
5427 cFYI(1, "Error in Notify = %d", rc);
5429 /* Add file to outstanding requests */
5430 /* BB change to kmem cache alloc */
5431 dnotify_req = kmalloc(
5432 sizeof(struct dir_notify_req),
5435 dnotify_req->Pid = pSMB->hdr.Pid;
5436 dnotify_req->PidHigh = pSMB->hdr.PidHigh;
5437 dnotify_req->Mid = pSMB->hdr.Mid;
5438 dnotify_req->Tid = pSMB->hdr.Tid;
5439 dnotify_req->Uid = pSMB->hdr.Uid;
5440 dnotify_req->netfid = netfid;
5441 dnotify_req->pfile = pfile;
5442 dnotify_req->filter = filter;
5443 dnotify_req->multishot = multishot;
5444 spin_lock(&GlobalMid_Lock);
5445 list_add_tail(&dnotify_req->lhead,
5446 &GlobalDnotifyReqList);
5447 spin_unlock(&GlobalMid_Lock);
5451 cifs_buf_release(pSMB);
5455 #ifdef CONFIG_CIFS_XATTR
5457 * Do a path-based QUERY_ALL_EAS call and parse the result. This is a common
5458 * function used by listxattr and getxattr type calls. When ea_name is set,
5459 * it looks for that attribute name and stuffs that value into the EAData
5460 * buffer. When ea_name is NULL, it stuffs a list of attribute names into the
5461 * buffer. In both cases, the return value is either the length of the
5462 * resulting data or a negative error code. If EAData is a NULL pointer then
5463 * the data isn't copied to it, but the length is returned.
5466 CIFSSMBQAllEAs(const int xid, struct cifsTconInfo *tcon,
5467 const unsigned char *searchName, const unsigned char *ea_name,
5468 char *EAData, size_t buf_size,
5469 const struct nls_table *nls_codepage, int remap)
5471 /* BB assumes one setup word */
5472 TRANSACTION2_QPI_REQ *pSMB = NULL;
5473 TRANSACTION2_QPI_RSP *pSMBr = NULL;
5477 struct fealist *ea_response_data;
5478 struct fea *temp_fea;
5481 __u16 params, byte_count, data_offset;
5483 cFYI(1, "In Query All EAs path %s", searchName);
5485 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5490 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5492 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
5493 PATH_MAX, nls_codepage, remap);
5494 list_len++; /* trailing null */
5496 } else { /* BB improve the check for buffer overruns BB */
5497 list_len = strnlen(searchName, PATH_MAX);
5498 list_len++; /* trailing null */
5499 strncpy(pSMB->FileName, searchName, list_len);
5502 params = 2 /* level */ + 4 /* reserved */ + list_len /* includes NUL */;
5503 pSMB->TotalDataCount = 0;
5504 pSMB->MaxParameterCount = cpu_to_le16(2);
5505 /* BB find exact max SMB PDU from sess structure BB */
5506 pSMB->MaxDataCount = cpu_to_le16(CIFSMaxBufSize);
5507 pSMB->MaxSetupCount = 0;
5511 pSMB->Reserved2 = 0;
5512 pSMB->ParameterOffset = cpu_to_le16(offsetof(
5513 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
5514 pSMB->DataCount = 0;
5515 pSMB->DataOffset = 0;
5516 pSMB->SetupCount = 1;
5517 pSMB->Reserved3 = 0;
5518 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
5519 byte_count = params + 1 /* pad */ ;
5520 pSMB->TotalParameterCount = cpu_to_le16(params);
5521 pSMB->ParameterCount = pSMB->TotalParameterCount;
5522 pSMB->InformationLevel = cpu_to_le16(SMB_INFO_QUERY_ALL_EAS);
5523 pSMB->Reserved4 = 0;
5524 pSMB->hdr.smb_buf_length += byte_count;
5525 pSMB->ByteCount = cpu_to_le16(byte_count);
5527 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5528 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5530 cFYI(1, "Send error in QueryAllEAs = %d", rc);
5535 /* BB also check enough total bytes returned */
5536 /* BB we need to improve the validity checking
5537 of these trans2 responses */
5539 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
5540 if (rc || (pSMBr->ByteCount < 4)) {
5541 rc = -EIO; /* bad smb */
5545 /* check that length of list is not more than bcc */
5546 /* check that each entry does not go beyond length
5548 /* check that each element of each entry does not
5549 go beyond end of list */
5550 /* validate_trans2_offsets() */
5551 /* BB check if start of smb + data_offset > &bcc+ bcc */
5553 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
5554 ea_response_data = (struct fealist *)
5555 (((char *) &pSMBr->hdr.Protocol) + data_offset);
5557 list_len = le32_to_cpu(ea_response_data->list_len);
5558 cFYI(1, "ea length %d", list_len);
5559 if (list_len <= 8) {
5560 cFYI(1, "empty EA list returned from server");
5564 /* make sure list_len doesn't go past end of SMB */
5565 end_of_smb = (char *)pByteArea(&pSMBr->hdr) + BCC(&pSMBr->hdr);
5566 if ((char *)ea_response_data + list_len > end_of_smb) {
5567 cFYI(1, "EA list appears to go beyond SMB");
5572 /* account for ea list len */
5574 temp_fea = ea_response_data->list;
5575 temp_ptr = (char *)temp_fea;
5576 while (list_len > 0) {
5577 unsigned int name_len;
5582 /* make sure we can read name_len and value_len */
5584 cFYI(1, "EA entry goes beyond length of list");
5589 name_len = temp_fea->name_len;
5590 value_len = le16_to_cpu(temp_fea->value_len);
5591 list_len -= name_len + 1 + value_len;
5593 cFYI(1, "EA entry goes beyond length of list");
5599 if (strncmp(ea_name, temp_ptr, name_len) == 0) {
5600 temp_ptr += name_len + 1;
5604 if ((size_t)value_len > buf_size) {
5608 memcpy(EAData, temp_ptr, value_len);
5612 /* account for prefix user. and trailing null */
5613 rc += (5 + 1 + name_len);
5614 if (rc < (int) buf_size) {
5615 memcpy(EAData, "user.", 5);
5617 memcpy(EAData, temp_ptr, name_len);
5619 /* null terminate name */
5622 } else if (buf_size == 0) {
5623 /* skip copy - calc size only */
5625 /* stop before overrun buffer */
5630 temp_ptr += name_len + 1 + value_len;
5631 temp_fea = (struct fea *)temp_ptr;
5634 /* didn't find the named attribute */
5639 cifs_buf_release(pSMB);
5647 CIFSSMBSetEA(const int xid, struct cifsTconInfo *tcon, const char *fileName,
5648 const char *ea_name, const void *ea_value,
5649 const __u16 ea_value_len, const struct nls_table *nls_codepage,
5652 struct smb_com_transaction2_spi_req *pSMB = NULL;
5653 struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
5654 struct fealist *parm_data;
5657 int bytes_returned = 0;
5658 __u16 params, param_offset, byte_count, offset, count;
5660 cFYI(1, "In SetEA");
5662 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5667 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5669 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
5670 PATH_MAX, nls_codepage, remap);
5671 name_len++; /* trailing null */
5673 } else { /* BB improve the check for buffer overruns BB */
5674 name_len = strnlen(fileName, PATH_MAX);
5675 name_len++; /* trailing null */
5676 strncpy(pSMB->FileName, fileName, name_len);
5679 params = 6 + name_len;
5681 /* done calculating parms using name_len of file name,
5682 now use name_len to calculate length of ea name
5683 we are going to create in the inode xattrs */
5684 if (ea_name == NULL)
5687 name_len = strnlen(ea_name, 255);
5689 count = sizeof(*parm_data) + ea_value_len + name_len;
5690 pSMB->MaxParameterCount = cpu_to_le16(2);
5691 /* BB find max SMB PDU from sess */
5692 pSMB->MaxDataCount = cpu_to_le16(1000);
5693 pSMB->MaxSetupCount = 0;
5697 pSMB->Reserved2 = 0;
5698 param_offset = offsetof(struct smb_com_transaction2_spi_req,
5699 InformationLevel) - 4;
5700 offset = param_offset + params;
5701 pSMB->InformationLevel =
5702 cpu_to_le16(SMB_SET_FILE_EA);
5705 (struct fealist *) (((char *) &pSMB->hdr.Protocol) +
5707 pSMB->ParameterOffset = cpu_to_le16(param_offset);
5708 pSMB->DataOffset = cpu_to_le16(offset);
5709 pSMB->SetupCount = 1;
5710 pSMB->Reserved3 = 0;
5711 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
5712 byte_count = 3 /* pad */ + params + count;
5713 pSMB->DataCount = cpu_to_le16(count);
5714 parm_data->list_len = cpu_to_le32(count);
5715 parm_data->list[0].EA_flags = 0;
5716 /* we checked above that name len is less than 255 */
5717 parm_data->list[0].name_len = (__u8)name_len;
5718 /* EA names are always ASCII */
5720 strncpy(parm_data->list[0].name, ea_name, name_len);
5721 parm_data->list[0].name[name_len] = 0;
5722 parm_data->list[0].value_len = cpu_to_le16(ea_value_len);
5723 /* caller ensures that ea_value_len is less than 64K but
5724 we need to ensure that it fits within the smb */
5726 /*BB add length check to see if it would fit in
5727 negotiated SMB buffer size BB */
5728 /* if (ea_value_len > buffer_size - 512 (enough for header)) */
5730 memcpy(parm_data->list[0].name+name_len+1,
5731 ea_value, ea_value_len);
5733 pSMB->TotalDataCount = pSMB->DataCount;
5734 pSMB->ParameterCount = cpu_to_le16(params);
5735 pSMB->TotalParameterCount = pSMB->ParameterCount;
5736 pSMB->Reserved4 = 0;
5737 pSMB->hdr.smb_buf_length += byte_count;
5738 pSMB->ByteCount = cpu_to_le16(byte_count);
5739 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5740 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5742 cFYI(1, "SetPathInfo (EA) returned %d", rc);
5744 cifs_buf_release(pSMB);