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 write_lock(&GlobalSMBSeslock);
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 write_unlock(&GlobalSMBSeslock);
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 /* returned */ ,
286 void **response_buf /* returned */ )
290 rc = cifs_reconnect_tcon(tcon, smb_command);
294 *request_buf = cifs_buf_get();
295 if (*request_buf == NULL) {
296 /* BB should we add a retry in here if not a writepage? */
299 /* Although the original thought was we needed the response buf for */
300 /* potential retries of smb operations it turns out we can determine */
301 /* from the mid flags when the request buffer can be resent without */
302 /* having to use a second distinct buffer for the response */
304 *response_buf = *request_buf;
306 header_assemble((struct smb_hdr *) *request_buf, smb_command, tcon,
310 cifs_stats_inc(&tcon->num_smbs_sent);
315 static int validate_t2(struct smb_t2_rsp *pSMB)
321 /* check for plausible wct, bcc and t2 data and parm sizes */
322 /* check for parm and data offset going beyond end of smb */
323 if (pSMB->hdr.WordCount >= 10) {
324 if ((le16_to_cpu(pSMB->t2_rsp.ParameterOffset) <= 1024) &&
325 (le16_to_cpu(pSMB->t2_rsp.DataOffset) <= 1024)) {
326 /* check that bcc is at least as big as parms + data */
327 /* check that bcc is less than negotiated smb buffer */
328 total_size = le16_to_cpu(pSMB->t2_rsp.ParameterCount);
329 if (total_size < 512) {
331 le16_to_cpu(pSMB->t2_rsp.DataCount);
332 /* BCC le converted in SendReceive */
333 pBCC = (pSMB->hdr.WordCount * 2) +
334 sizeof(struct smb_hdr) +
336 if ((total_size <= (*(u16 *)pBCC)) &&
338 CIFSMaxBufSize+MAX_CIFS_HDR_SIZE)) {
344 cifs_dump_mem("Invalid transact2 SMB: ", (char *)pSMB,
345 sizeof(struct smb_t2_rsp) + 16);
349 CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses)
352 NEGOTIATE_RSP *pSMBr;
356 struct TCP_Server_Info *server;
358 unsigned int secFlags;
361 server = ses->server;
366 rc = smb_init(SMB_COM_NEGOTIATE, 0, NULL /* no tcon yet */ ,
367 (void **) &pSMB, (void **) &pSMBr);
371 /* if any of auth flags (ie not sign or seal) are overriden use them */
372 if (ses->overrideSecFlg & (~(CIFSSEC_MUST_SIGN | CIFSSEC_MUST_SEAL)))
373 secFlags = ses->overrideSecFlg; /* BB FIXME fix sign flags? */
374 else /* if override flags set only sign/seal OR them with global auth */
375 secFlags = global_secflags | ses->overrideSecFlg;
377 cFYI(1, "secFlags 0x%x", secFlags);
379 pSMB->hdr.Mid = GetNextMid(server);
380 pSMB->hdr.Flags2 |= (SMBFLG2_UNICODE | SMBFLG2_ERR_STATUS);
382 if ((secFlags & CIFSSEC_MUST_KRB5) == CIFSSEC_MUST_KRB5)
383 pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC;
384 else if ((secFlags & CIFSSEC_AUTH_MASK) == CIFSSEC_MAY_KRB5) {
385 cFYI(1, "Kerberos only mechanism, enable extended security");
386 pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC;
388 #ifdef CONFIG_CIFS_EXPERIMENTAL
389 else if ((secFlags & CIFSSEC_MUST_NTLMSSP) == CIFSSEC_MUST_NTLMSSP)
390 pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC;
391 else if ((secFlags & CIFSSEC_AUTH_MASK) == CIFSSEC_MAY_NTLMSSP) {
392 cFYI(1, "NTLMSSP only mechanism, enable extended security");
393 pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC;
398 for (i = 0; i < CIFS_NUM_PROT; i++) {
399 strncpy(pSMB->DialectsArray+count, protocols[i].name, 16);
400 count += strlen(protocols[i].name) + 1;
401 /* null at end of source and target buffers anyway */
403 pSMB->hdr.smb_buf_length += count;
404 pSMB->ByteCount = cpu_to_le16(count);
406 rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB,
407 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
411 server->dialect = le16_to_cpu(pSMBr->DialectIndex);
412 cFYI(1, "Dialect: %d", server->dialect);
413 /* Check wct = 1 error case */
414 if ((pSMBr->hdr.WordCount < 13) || (server->dialect == BAD_PROT)) {
415 /* core returns wct = 1, but we do not ask for core - otherwise
416 small wct just comes when dialect index is -1 indicating we
417 could not negotiate a common dialect */
420 #ifdef CONFIG_CIFS_WEAK_PW_HASH
421 } else if ((pSMBr->hdr.WordCount == 13)
422 && ((server->dialect == LANMAN_PROT)
423 || (server->dialect == LANMAN2_PROT))) {
425 struct lanman_neg_rsp *rsp = (struct lanman_neg_rsp *)pSMBr;
427 if ((secFlags & CIFSSEC_MAY_LANMAN) ||
428 (secFlags & CIFSSEC_MAY_PLNTXT))
429 server->secType = LANMAN;
431 cERROR(1, "mount failed weak security disabled"
432 " in /proc/fs/cifs/SecurityFlags");
436 server->secMode = (__u8)le16_to_cpu(rsp->SecurityMode);
437 server->maxReq = le16_to_cpu(rsp->MaxMpxCount);
438 server->maxBuf = min((__u32)le16_to_cpu(rsp->MaxBufSize),
439 (__u32)CIFSMaxBufSize + MAX_CIFS_HDR_SIZE);
440 server->max_vcs = le16_to_cpu(rsp->MaxNumberVcs);
441 GETU32(server->sessid) = le32_to_cpu(rsp->SessionKey);
442 /* even though we do not use raw we might as well set this
443 accurately, in case we ever find a need for it */
444 if ((le16_to_cpu(rsp->RawMode) & RAW_ENABLE) == RAW_ENABLE) {
445 server->max_rw = 0xFF00;
446 server->capabilities = CAP_MPX_MODE | CAP_RAW_MODE;
448 server->max_rw = 0;/* do not need to use raw anyway */
449 server->capabilities = CAP_MPX_MODE;
451 tmp = (__s16)le16_to_cpu(rsp->ServerTimeZone);
453 /* OS/2 often does not set timezone therefore
454 * we must use server time to calc time zone.
455 * Could deviate slightly from the right zone.
456 * Smallest defined timezone difference is 15 minutes
457 * (i.e. Nepal). Rounding up/down is done to match
460 int val, seconds, remain, result;
461 struct timespec ts, utc;
463 ts = cnvrtDosUnixTm(rsp->SrvTime.Date,
464 rsp->SrvTime.Time, 0);
465 cFYI(1, "SrvTime %d sec since 1970 (utc: %d) diff: %d",
466 (int)ts.tv_sec, (int)utc.tv_sec,
467 (int)(utc.tv_sec - ts.tv_sec));
468 val = (int)(utc.tv_sec - ts.tv_sec);
470 result = (seconds / MIN_TZ_ADJ) * MIN_TZ_ADJ;
471 remain = seconds % MIN_TZ_ADJ;
472 if (remain >= (MIN_TZ_ADJ / 2))
473 result += MIN_TZ_ADJ;
476 server->timeAdj = result;
478 server->timeAdj = (int)tmp;
479 server->timeAdj *= 60; /* also in seconds */
481 cFYI(1, "server->timeAdj: %d seconds", server->timeAdj);
484 /* BB get server time for time conversions and add
485 code to use it and timezone since this is not UTC */
487 if (rsp->EncryptionKeyLength ==
488 cpu_to_le16(CIFS_CRYPTO_KEY_SIZE)) {
489 memcpy(server->cryptKey, rsp->EncryptionKey,
490 CIFS_CRYPTO_KEY_SIZE);
491 } else if (server->secMode & SECMODE_PW_ENCRYPT) {
492 rc = -EIO; /* need cryptkey unless plain text */
496 cFYI(1, "LANMAN negotiated");
497 /* we will not end up setting signing flags - as no signing
498 was in LANMAN and server did not return the flags on */
500 #else /* weak security disabled */
501 } else if (pSMBr->hdr.WordCount == 13) {
502 cERROR(1, "mount failed, cifs module not built "
503 "with CIFS_WEAK_PW_HASH support");
505 #endif /* WEAK_PW_HASH */
507 } else if (pSMBr->hdr.WordCount != 17) {
512 /* else wct == 17 NTLM */
513 server->secMode = pSMBr->SecurityMode;
514 if ((server->secMode & SECMODE_USER) == 0)
515 cFYI(1, "share mode security");
517 if ((server->secMode & SECMODE_PW_ENCRYPT) == 0)
518 #ifdef CONFIG_CIFS_WEAK_PW_HASH
519 if ((secFlags & CIFSSEC_MAY_PLNTXT) == 0)
520 #endif /* CIFS_WEAK_PW_HASH */
521 cERROR(1, "Server requests plain text password"
522 " but client support disabled");
524 if ((secFlags & CIFSSEC_MUST_NTLMV2) == CIFSSEC_MUST_NTLMV2)
525 server->secType = NTLMv2;
526 else if (secFlags & CIFSSEC_MAY_NTLM)
527 server->secType = NTLM;
528 else if (secFlags & CIFSSEC_MAY_NTLMV2)
529 server->secType = NTLMv2;
530 else if (secFlags & CIFSSEC_MAY_KRB5)
531 server->secType = Kerberos;
532 else if (secFlags & CIFSSEC_MAY_NTLMSSP)
533 server->secType = RawNTLMSSP;
534 else if (secFlags & CIFSSEC_MAY_LANMAN)
535 server->secType = LANMAN;
536 /* #ifdef CONFIG_CIFS_EXPERIMENTAL
537 else if (secFlags & CIFSSEC_MAY_PLNTXT)
542 cERROR(1, "Invalid security type");
545 /* else ... any others ...? */
547 /* one byte, so no need to convert this or EncryptionKeyLen from
549 server->maxReq = le16_to_cpu(pSMBr->MaxMpxCount);
550 /* probably no need to store and check maxvcs */
551 server->maxBuf = min(le32_to_cpu(pSMBr->MaxBufferSize),
552 (__u32) CIFSMaxBufSize + MAX_CIFS_HDR_SIZE);
553 server->max_rw = le32_to_cpu(pSMBr->MaxRawSize);
554 cFYI(DBG2, "Max buf = %d", ses->server->maxBuf);
555 GETU32(ses->server->sessid) = le32_to_cpu(pSMBr->SessionKey);
556 server->capabilities = le32_to_cpu(pSMBr->Capabilities);
557 server->timeAdj = (int)(__s16)le16_to_cpu(pSMBr->ServerTimeZone);
558 server->timeAdj *= 60;
559 if (pSMBr->EncryptionKeyLength == CIFS_CRYPTO_KEY_SIZE) {
560 memcpy(server->cryptKey, pSMBr->u.EncryptionKey,
561 CIFS_CRYPTO_KEY_SIZE);
562 } else if ((pSMBr->hdr.Flags2 & SMBFLG2_EXT_SEC)
563 && (pSMBr->EncryptionKeyLength == 0)) {
564 /* decode security blob */
565 } else if (server->secMode & SECMODE_PW_ENCRYPT) {
566 rc = -EIO; /* no crypt key only if plain text pwd */
570 /* BB might be helpful to save off the domain of server here */
572 if ((pSMBr->hdr.Flags2 & SMBFLG2_EXT_SEC) &&
573 (server->capabilities & CAP_EXTENDED_SECURITY)) {
574 count = pSMBr->ByteCount;
579 read_lock(&cifs_tcp_ses_lock);
580 if (server->srv_count > 1) {
581 read_unlock(&cifs_tcp_ses_lock);
582 if (memcmp(server->server_GUID,
583 pSMBr->u.extended_response.
585 cFYI(1, "server UID changed");
586 memcpy(server->server_GUID,
587 pSMBr->u.extended_response.GUID,
591 read_unlock(&cifs_tcp_ses_lock);
592 memcpy(server->server_GUID,
593 pSMBr->u.extended_response.GUID, 16);
597 server->secType = RawNTLMSSP;
599 rc = decode_negTokenInit(pSMBr->u.extended_response.
600 SecurityBlob, count - 16,
607 if (server->secType == Kerberos) {
608 if (!server->sec_kerberos &&
609 !server->sec_mskerberos)
611 } else if (server->secType == RawNTLMSSP) {
612 if (!server->sec_ntlmssp)
618 server->capabilities &= ~CAP_EXTENDED_SECURITY;
620 #ifdef CONFIG_CIFS_WEAK_PW_HASH
623 if ((secFlags & CIFSSEC_MAY_SIGN) == 0) {
624 /* MUST_SIGN already includes the MAY_SIGN FLAG
625 so if this is zero it means that signing is disabled */
626 cFYI(1, "Signing disabled");
627 if (server->secMode & SECMODE_SIGN_REQUIRED) {
628 cERROR(1, "Server requires "
629 "packet signing to be enabled in "
630 "/proc/fs/cifs/SecurityFlags.");
634 ~(SECMODE_SIGN_ENABLED | SECMODE_SIGN_REQUIRED);
635 } else if ((secFlags & CIFSSEC_MUST_SIGN) == CIFSSEC_MUST_SIGN) {
636 /* signing required */
637 cFYI(1, "Must sign - secFlags 0x%x", secFlags);
638 if ((server->secMode &
639 (SECMODE_SIGN_ENABLED | SECMODE_SIGN_REQUIRED)) == 0) {
640 cERROR(1, "signing required but server lacks support");
643 server->secMode |= SECMODE_SIGN_REQUIRED;
645 /* signing optional ie CIFSSEC_MAY_SIGN */
646 if ((server->secMode & SECMODE_SIGN_REQUIRED) == 0)
648 ~(SECMODE_SIGN_ENABLED | SECMODE_SIGN_REQUIRED);
652 cifs_buf_release(pSMB);
654 cFYI(1, "negprot rc %d", rc);
659 CIFSSMBTDis(const int xid, struct cifsTconInfo *tcon)
661 struct smb_hdr *smb_buffer;
664 cFYI(1, "In tree disconnect");
666 /* BB: do we need to check this? These should never be NULL. */
667 if ((tcon->ses == NULL) || (tcon->ses->server == NULL))
671 * No need to return error on this operation if tid invalidated and
672 * closed on server already e.g. due to tcp session crashing. Also,
673 * the tcon is no longer on the list, so no need to take lock before
676 if ((tcon->need_reconnect) || (tcon->ses->need_reconnect))
679 rc = small_smb_init(SMB_COM_TREE_DISCONNECT, 0, tcon,
680 (void **)&smb_buffer);
684 rc = SendReceiveNoRsp(xid, tcon->ses, smb_buffer, 0);
686 cFYI(1, "Tree disconnect failed %d", rc);
688 /* No need to return error on this operation if tid invalidated and
689 closed on server already e.g. due to tcp session crashing */
697 CIFSSMBLogoff(const int xid, struct cifsSesInfo *ses)
699 LOGOFF_ANDX_REQ *pSMB;
702 cFYI(1, "In SMBLogoff for session disconnect");
705 * BB: do we need to check validity of ses and server? They should
706 * always be valid since we have an active reference. If not, that
707 * should probably be a BUG()
709 if (!ses || !ses->server)
712 mutex_lock(&ses->session_mutex);
713 if (ses->need_reconnect)
714 goto session_already_dead; /* no need to send SMBlogoff if uid
715 already closed due to reconnect */
716 rc = small_smb_init(SMB_COM_LOGOFF_ANDX, 2, NULL, (void **)&pSMB);
718 mutex_unlock(&ses->session_mutex);
722 pSMB->hdr.Mid = GetNextMid(ses->server);
724 if (ses->server->secMode &
725 (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
726 pSMB->hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
728 pSMB->hdr.Uid = ses->Suid;
730 pSMB->AndXCommand = 0xFF;
731 rc = SendReceiveNoRsp(xid, ses, (struct smb_hdr *) pSMB, 0);
732 session_already_dead:
733 mutex_unlock(&ses->session_mutex);
735 /* if session dead then we do not need to do ulogoff,
736 since server closed smb session, no sense reporting
744 CIFSPOSIXDelFile(const int xid, struct cifsTconInfo *tcon, const char *fileName,
745 __u16 type, const struct nls_table *nls_codepage, int remap)
747 TRANSACTION2_SPI_REQ *pSMB = NULL;
748 TRANSACTION2_SPI_RSP *pSMBr = NULL;
749 struct unlink_psx_rq *pRqD;
752 int bytes_returned = 0;
753 __u16 params, param_offset, offset, byte_count;
755 cFYI(1, "In POSIX delete");
757 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
762 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
764 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
765 PATH_MAX, nls_codepage, remap);
766 name_len++; /* trailing null */
768 } else { /* BB add path length overrun check */
769 name_len = strnlen(fileName, PATH_MAX);
770 name_len++; /* trailing null */
771 strncpy(pSMB->FileName, fileName, name_len);
774 params = 6 + name_len;
775 pSMB->MaxParameterCount = cpu_to_le16(2);
776 pSMB->MaxDataCount = 0; /* BB double check this with jra */
777 pSMB->MaxSetupCount = 0;
782 param_offset = offsetof(struct smb_com_transaction2_spi_req,
783 InformationLevel) - 4;
784 offset = param_offset + params;
786 /* Setup pointer to Request Data (inode type) */
787 pRqD = (struct unlink_psx_rq *)(((char *)&pSMB->hdr.Protocol) + offset);
788 pRqD->type = cpu_to_le16(type);
789 pSMB->ParameterOffset = cpu_to_le16(param_offset);
790 pSMB->DataOffset = cpu_to_le16(offset);
791 pSMB->SetupCount = 1;
793 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
794 byte_count = 3 /* pad */ + params + sizeof(struct unlink_psx_rq);
796 pSMB->DataCount = cpu_to_le16(sizeof(struct unlink_psx_rq));
797 pSMB->TotalDataCount = cpu_to_le16(sizeof(struct unlink_psx_rq));
798 pSMB->ParameterCount = cpu_to_le16(params);
799 pSMB->TotalParameterCount = pSMB->ParameterCount;
800 pSMB->InformationLevel = cpu_to_le16(SMB_POSIX_UNLINK);
802 pSMB->hdr.smb_buf_length += byte_count;
803 pSMB->ByteCount = cpu_to_le16(byte_count);
804 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
805 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
807 cFYI(1, "Posix delete returned %d", rc);
808 cifs_buf_release(pSMB);
810 cifs_stats_inc(&tcon->num_deletes);
819 CIFSSMBDelFile(const int xid, struct cifsTconInfo *tcon, const char *fileName,
820 const struct nls_table *nls_codepage, int remap)
822 DELETE_FILE_REQ *pSMB = NULL;
823 DELETE_FILE_RSP *pSMBr = NULL;
829 rc = smb_init(SMB_COM_DELETE, 1, tcon, (void **) &pSMB,
834 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
836 cifsConvertToUCS((__le16 *) pSMB->fileName, fileName,
837 PATH_MAX, nls_codepage, remap);
838 name_len++; /* trailing null */
840 } else { /* BB improve check for buffer overruns BB */
841 name_len = strnlen(fileName, PATH_MAX);
842 name_len++; /* trailing null */
843 strncpy(pSMB->fileName, fileName, name_len);
845 pSMB->SearchAttributes =
846 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM);
847 pSMB->BufferFormat = 0x04;
848 pSMB->hdr.smb_buf_length += name_len + 1;
849 pSMB->ByteCount = cpu_to_le16(name_len + 1);
850 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
851 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
852 cifs_stats_inc(&tcon->num_deletes);
854 cFYI(1, "Error in RMFile = %d", rc);
856 cifs_buf_release(pSMB);
864 CIFSSMBRmDir(const int xid, struct cifsTconInfo *tcon, const char *dirName,
865 const struct nls_table *nls_codepage, int remap)
867 DELETE_DIRECTORY_REQ *pSMB = NULL;
868 DELETE_DIRECTORY_RSP *pSMBr = NULL;
873 cFYI(1, "In CIFSSMBRmDir");
875 rc = smb_init(SMB_COM_DELETE_DIRECTORY, 0, tcon, (void **) &pSMB,
880 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
881 name_len = cifsConvertToUCS((__le16 *) pSMB->DirName, dirName,
882 PATH_MAX, nls_codepage, remap);
883 name_len++; /* trailing null */
885 } else { /* BB improve check for buffer overruns BB */
886 name_len = strnlen(dirName, PATH_MAX);
887 name_len++; /* trailing null */
888 strncpy(pSMB->DirName, dirName, name_len);
891 pSMB->BufferFormat = 0x04;
892 pSMB->hdr.smb_buf_length += name_len + 1;
893 pSMB->ByteCount = cpu_to_le16(name_len + 1);
894 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
895 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
896 cifs_stats_inc(&tcon->num_rmdirs);
898 cFYI(1, "Error in RMDir = %d", rc);
900 cifs_buf_release(pSMB);
907 CIFSSMBMkDir(const int xid, struct cifsTconInfo *tcon,
908 const char *name, const struct nls_table *nls_codepage, int remap)
911 CREATE_DIRECTORY_REQ *pSMB = NULL;
912 CREATE_DIRECTORY_RSP *pSMBr = NULL;
916 cFYI(1, "In CIFSSMBMkDir");
918 rc = smb_init(SMB_COM_CREATE_DIRECTORY, 0, tcon, (void **) &pSMB,
923 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
924 name_len = cifsConvertToUCS((__le16 *) pSMB->DirName, name,
925 PATH_MAX, nls_codepage, remap);
926 name_len++; /* trailing null */
928 } else { /* BB improve check for buffer overruns BB */
929 name_len = strnlen(name, PATH_MAX);
930 name_len++; /* trailing null */
931 strncpy(pSMB->DirName, name, name_len);
934 pSMB->BufferFormat = 0x04;
935 pSMB->hdr.smb_buf_length += name_len + 1;
936 pSMB->ByteCount = cpu_to_le16(name_len + 1);
937 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
938 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
939 cifs_stats_inc(&tcon->num_mkdirs);
941 cFYI(1, "Error in Mkdir = %d", rc);
943 cifs_buf_release(pSMB);
950 CIFSPOSIXCreate(const int xid, struct cifsTconInfo *tcon, __u32 posix_flags,
951 __u64 mode, __u16 *netfid, FILE_UNIX_BASIC_INFO *pRetData,
952 __u32 *pOplock, const char *name,
953 const struct nls_table *nls_codepage, int remap)
955 TRANSACTION2_SPI_REQ *pSMB = NULL;
956 TRANSACTION2_SPI_RSP *pSMBr = NULL;
959 int bytes_returned = 0;
960 __u16 params, param_offset, offset, byte_count, count;
962 OPEN_PSX_RSP *psx_rsp;
964 cFYI(1, "In POSIX Create");
966 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
971 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
973 cifsConvertToUCS((__le16 *) pSMB->FileName, name,
974 PATH_MAX, nls_codepage, remap);
975 name_len++; /* trailing null */
977 } else { /* BB improve the check for buffer overruns BB */
978 name_len = strnlen(name, PATH_MAX);
979 name_len++; /* trailing null */
980 strncpy(pSMB->FileName, name, name_len);
983 params = 6 + name_len;
984 count = sizeof(OPEN_PSX_REQ);
985 pSMB->MaxParameterCount = cpu_to_le16(2);
986 pSMB->MaxDataCount = cpu_to_le16(1000); /* large enough */
987 pSMB->MaxSetupCount = 0;
992 param_offset = offsetof(struct smb_com_transaction2_spi_req,
993 InformationLevel) - 4;
994 offset = param_offset + params;
995 pdata = (OPEN_PSX_REQ *)(((char *)&pSMB->hdr.Protocol) + offset);
996 pdata->Level = cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC);
997 pdata->Permissions = cpu_to_le64(mode);
998 pdata->PosixOpenFlags = cpu_to_le32(posix_flags);
999 pdata->OpenFlags = cpu_to_le32(*pOplock);
1000 pSMB->ParameterOffset = cpu_to_le16(param_offset);
1001 pSMB->DataOffset = cpu_to_le16(offset);
1002 pSMB->SetupCount = 1;
1003 pSMB->Reserved3 = 0;
1004 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
1005 byte_count = 3 /* pad */ + params + count;
1007 pSMB->DataCount = cpu_to_le16(count);
1008 pSMB->ParameterCount = cpu_to_le16(params);
1009 pSMB->TotalDataCount = pSMB->DataCount;
1010 pSMB->TotalParameterCount = pSMB->ParameterCount;
1011 pSMB->InformationLevel = cpu_to_le16(SMB_POSIX_OPEN);
1012 pSMB->Reserved4 = 0;
1013 pSMB->hdr.smb_buf_length += byte_count;
1014 pSMB->ByteCount = cpu_to_le16(byte_count);
1015 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1016 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1018 cFYI(1, "Posix create returned %d", rc);
1019 goto psx_create_err;
1022 cFYI(1, "copying inode info");
1023 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
1025 if (rc || (pSMBr->ByteCount < sizeof(OPEN_PSX_RSP))) {
1026 rc = -EIO; /* bad smb */
1027 goto psx_create_err;
1030 /* copy return information to pRetData */
1031 psx_rsp = (OPEN_PSX_RSP *)((char *) &pSMBr->hdr.Protocol
1032 + le16_to_cpu(pSMBr->t2.DataOffset));
1034 *pOplock = le16_to_cpu(psx_rsp->OplockFlags);
1036 *netfid = psx_rsp->Fid; /* cifs fid stays in le */
1037 /* Let caller know file was created so we can set the mode. */
1038 /* Do we care about the CreateAction in any other cases? */
1039 if (cpu_to_le32(FILE_CREATE) == psx_rsp->CreateAction)
1040 *pOplock |= CIFS_CREATE_ACTION;
1041 /* check to make sure response data is there */
1042 if (psx_rsp->ReturnedLevel != cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC)) {
1043 pRetData->Type = cpu_to_le32(-1); /* unknown */
1044 cFYI(DBG2, "unknown type");
1046 if (pSMBr->ByteCount < sizeof(OPEN_PSX_RSP)
1047 + sizeof(FILE_UNIX_BASIC_INFO)) {
1048 cERROR(1, "Open response data too small");
1049 pRetData->Type = cpu_to_le32(-1);
1050 goto psx_create_err;
1052 memcpy((char *) pRetData,
1053 (char *)psx_rsp + sizeof(OPEN_PSX_RSP),
1054 sizeof(FILE_UNIX_BASIC_INFO));
1058 cifs_buf_release(pSMB);
1060 if (posix_flags & SMB_O_DIRECTORY)
1061 cifs_stats_inc(&tcon->num_posixmkdirs);
1063 cifs_stats_inc(&tcon->num_posixopens);
1071 static __u16 convert_disposition(int disposition)
1075 switch (disposition) {
1076 case FILE_SUPERSEDE:
1077 ofun = SMBOPEN_OCREATE | SMBOPEN_OTRUNC;
1080 ofun = SMBOPEN_OAPPEND;
1083 ofun = SMBOPEN_OCREATE;
1086 ofun = SMBOPEN_OCREATE | SMBOPEN_OAPPEND;
1088 case FILE_OVERWRITE:
1089 ofun = SMBOPEN_OTRUNC;
1091 case FILE_OVERWRITE_IF:
1092 ofun = SMBOPEN_OCREATE | SMBOPEN_OTRUNC;
1095 cFYI(1, "unknown disposition %d", disposition);
1096 ofun = SMBOPEN_OAPPEND; /* regular open */
1102 access_flags_to_smbopen_mode(const int access_flags)
1104 int masked_flags = access_flags & (GENERIC_READ | GENERIC_WRITE);
1106 if (masked_flags == GENERIC_READ)
1107 return SMBOPEN_READ;
1108 else if (masked_flags == GENERIC_WRITE)
1109 return SMBOPEN_WRITE;
1111 /* just go for read/write */
1112 return SMBOPEN_READWRITE;
1116 SMBLegacyOpen(const int xid, struct cifsTconInfo *tcon,
1117 const char *fileName, const int openDisposition,
1118 const int access_flags, const int create_options, __u16 *netfid,
1119 int *pOplock, FILE_ALL_INFO *pfile_info,
1120 const struct nls_table *nls_codepage, int remap)
1123 OPENX_REQ *pSMB = NULL;
1124 OPENX_RSP *pSMBr = NULL;
1130 rc = smb_init(SMB_COM_OPEN_ANDX, 15, tcon, (void **) &pSMB,
1135 pSMB->AndXCommand = 0xFF; /* none */
1137 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1138 count = 1; /* account for one byte pad to word boundary */
1140 cifsConvertToUCS((__le16 *) (pSMB->fileName + 1),
1141 fileName, PATH_MAX, nls_codepage, remap);
1142 name_len++; /* trailing null */
1144 } else { /* BB improve check for buffer overruns BB */
1145 count = 0; /* no pad */
1146 name_len = strnlen(fileName, PATH_MAX);
1147 name_len++; /* trailing null */
1148 strncpy(pSMB->fileName, fileName, name_len);
1150 if (*pOplock & REQ_OPLOCK)
1151 pSMB->OpenFlags = cpu_to_le16(REQ_OPLOCK);
1152 else if (*pOplock & REQ_BATCHOPLOCK)
1153 pSMB->OpenFlags = cpu_to_le16(REQ_BATCHOPLOCK);
1155 pSMB->OpenFlags |= cpu_to_le16(REQ_MORE_INFO);
1156 pSMB->Mode = cpu_to_le16(access_flags_to_smbopen_mode(access_flags));
1157 pSMB->Mode |= cpu_to_le16(0x40); /* deny none */
1158 /* set file as system file if special file such
1159 as fifo and server expecting SFU style and
1160 no Unix extensions */
1162 if (create_options & CREATE_OPTION_SPECIAL)
1163 pSMB->FileAttributes = cpu_to_le16(ATTR_SYSTEM);
1164 else /* BB FIXME BB */
1165 pSMB->FileAttributes = cpu_to_le16(0/*ATTR_NORMAL*/);
1167 if (create_options & CREATE_OPTION_READONLY)
1168 pSMB->FileAttributes |= cpu_to_le16(ATTR_READONLY);
1171 /* pSMB->CreateOptions = cpu_to_le32(create_options &
1172 CREATE_OPTIONS_MASK); */
1173 /* BB FIXME END BB */
1175 pSMB->Sattr = cpu_to_le16(ATTR_HIDDEN | ATTR_SYSTEM | ATTR_DIRECTORY);
1176 pSMB->OpenFunction = cpu_to_le16(convert_disposition(openDisposition));
1178 pSMB->hdr.smb_buf_length += count;
1180 pSMB->ByteCount = cpu_to_le16(count);
1181 /* long_op set to 1 to allow for oplock break timeouts */
1182 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1183 (struct smb_hdr *)pSMBr, &bytes_returned, CIFS_LONG_OP);
1184 cifs_stats_inc(&tcon->num_opens);
1186 cFYI(1, "Error in Open = %d", rc);
1188 /* BB verify if wct == 15 */
1190 /* *pOplock = pSMBr->OplockLevel; */ /* BB take from action field*/
1192 *netfid = pSMBr->Fid; /* cifs fid stays in le */
1193 /* Let caller know file was created so we can set the mode. */
1194 /* Do we care about the CreateAction in any other cases? */
1196 /* if (cpu_to_le32(FILE_CREATE) == pSMBr->CreateAction)
1197 *pOplock |= CIFS_CREATE_ACTION; */
1201 pfile_info->CreationTime = 0; /* BB convert CreateTime*/
1202 pfile_info->LastAccessTime = 0; /* BB fixme */
1203 pfile_info->LastWriteTime = 0; /* BB fixme */
1204 pfile_info->ChangeTime = 0; /* BB fixme */
1205 pfile_info->Attributes =
1206 cpu_to_le32(le16_to_cpu(pSMBr->FileAttributes));
1207 /* the file_info buf is endian converted by caller */
1208 pfile_info->AllocationSize =
1209 cpu_to_le64(le32_to_cpu(pSMBr->EndOfFile));
1210 pfile_info->EndOfFile = pfile_info->AllocationSize;
1211 pfile_info->NumberOfLinks = cpu_to_le32(1);
1212 pfile_info->DeletePending = 0;
1216 cifs_buf_release(pSMB);
1223 CIFSSMBOpen(const int xid, struct cifsTconInfo *tcon,
1224 const char *fileName, const int openDisposition,
1225 const int access_flags, const int create_options, __u16 *netfid,
1226 int *pOplock, FILE_ALL_INFO *pfile_info,
1227 const struct nls_table *nls_codepage, int remap)
1230 OPEN_REQ *pSMB = NULL;
1231 OPEN_RSP *pSMBr = NULL;
1237 rc = smb_init(SMB_COM_NT_CREATE_ANDX, 24, tcon, (void **) &pSMB,
1242 pSMB->AndXCommand = 0xFF; /* none */
1244 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1245 count = 1; /* account for one byte pad to word boundary */
1247 cifsConvertToUCS((__le16 *) (pSMB->fileName + 1),
1248 fileName, PATH_MAX, nls_codepage, remap);
1249 name_len++; /* trailing null */
1251 pSMB->NameLength = cpu_to_le16(name_len);
1252 } else { /* BB improve check for buffer overruns BB */
1253 count = 0; /* no pad */
1254 name_len = strnlen(fileName, PATH_MAX);
1255 name_len++; /* trailing null */
1256 pSMB->NameLength = cpu_to_le16(name_len);
1257 strncpy(pSMB->fileName, fileName, name_len);
1259 if (*pOplock & REQ_OPLOCK)
1260 pSMB->OpenFlags = cpu_to_le32(REQ_OPLOCK);
1261 else if (*pOplock & REQ_BATCHOPLOCK)
1262 pSMB->OpenFlags = cpu_to_le32(REQ_BATCHOPLOCK);
1263 pSMB->DesiredAccess = cpu_to_le32(access_flags);
1264 pSMB->AllocationSize = 0;
1265 /* set file as system file if special file such
1266 as fifo and server expecting SFU style and
1267 no Unix extensions */
1268 if (create_options & CREATE_OPTION_SPECIAL)
1269 pSMB->FileAttributes = cpu_to_le32(ATTR_SYSTEM);
1271 pSMB->FileAttributes = cpu_to_le32(ATTR_NORMAL);
1273 /* XP does not handle ATTR_POSIX_SEMANTICS */
1274 /* but it helps speed up case sensitive checks for other
1275 servers such as Samba */
1276 if (tcon->ses->capabilities & CAP_UNIX)
1277 pSMB->FileAttributes |= cpu_to_le32(ATTR_POSIX_SEMANTICS);
1279 if (create_options & CREATE_OPTION_READONLY)
1280 pSMB->FileAttributes |= cpu_to_le32(ATTR_READONLY);
1282 pSMB->ShareAccess = cpu_to_le32(FILE_SHARE_ALL);
1283 pSMB->CreateDisposition = cpu_to_le32(openDisposition);
1284 pSMB->CreateOptions = cpu_to_le32(create_options & CREATE_OPTIONS_MASK);
1285 /* BB Expirement with various impersonation levels and verify */
1286 pSMB->ImpersonationLevel = cpu_to_le32(SECURITY_IMPERSONATION);
1287 pSMB->SecurityFlags =
1288 SECURITY_CONTEXT_TRACKING | SECURITY_EFFECTIVE_ONLY;
1291 pSMB->hdr.smb_buf_length += count;
1293 pSMB->ByteCount = cpu_to_le16(count);
1294 /* long_op set to 1 to allow for oplock break timeouts */
1295 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1296 (struct smb_hdr *)pSMBr, &bytes_returned, CIFS_LONG_OP);
1297 cifs_stats_inc(&tcon->num_opens);
1299 cFYI(1, "Error in Open = %d", rc);
1301 *pOplock = pSMBr->OplockLevel; /* 1 byte no need to le_to_cpu */
1302 *netfid = pSMBr->Fid; /* cifs fid stays in le */
1303 /* Let caller know file was created so we can set the mode. */
1304 /* Do we care about the CreateAction in any other cases? */
1305 if (cpu_to_le32(FILE_CREATE) == pSMBr->CreateAction)
1306 *pOplock |= CIFS_CREATE_ACTION;
1308 memcpy((char *)pfile_info, (char *)&pSMBr->CreationTime,
1309 36 /* CreationTime to Attributes */);
1310 /* the file_info buf is endian converted by caller */
1311 pfile_info->AllocationSize = pSMBr->AllocationSize;
1312 pfile_info->EndOfFile = pSMBr->EndOfFile;
1313 pfile_info->NumberOfLinks = cpu_to_le32(1);
1314 pfile_info->DeletePending = 0;
1318 cifs_buf_release(pSMB);
1325 CIFSSMBRead(const int xid, struct cifsTconInfo *tcon, const int netfid,
1326 const unsigned int count, const __u64 lseek, unsigned int *nbytes,
1327 char **buf, int *pbuf_type)
1330 READ_REQ *pSMB = NULL;
1331 READ_RSP *pSMBr = NULL;
1332 char *pReadData = NULL;
1334 int resp_buf_type = 0;
1337 cFYI(1, "Reading %d bytes on fid %d", count, netfid);
1338 if (tcon->ses->capabilities & CAP_LARGE_FILES)
1341 wct = 10; /* old style read */
1342 if ((lseek >> 32) > 0) {
1343 /* can not handle this big offset for old */
1349 rc = small_smb_init(SMB_COM_READ_ANDX, wct, tcon, (void **) &pSMB);
1353 /* tcon and ses pointer are checked in smb_init */
1354 if (tcon->ses->server == NULL)
1355 return -ECONNABORTED;
1357 pSMB->AndXCommand = 0xFF; /* none */
1359 pSMB->OffsetLow = cpu_to_le32(lseek & 0xFFFFFFFF);
1361 pSMB->OffsetHigh = cpu_to_le32(lseek >> 32);
1363 pSMB->Remaining = 0;
1364 pSMB->MaxCount = cpu_to_le16(count & 0xFFFF);
1365 pSMB->MaxCountHigh = cpu_to_le32(count >> 16);
1367 pSMB->ByteCount = 0; /* no need to do le conversion since 0 */
1369 /* old style read */
1370 struct smb_com_readx_req *pSMBW =
1371 (struct smb_com_readx_req *)pSMB;
1372 pSMBW->ByteCount = 0;
1375 iov[0].iov_base = (char *)pSMB;
1376 iov[0].iov_len = pSMB->hdr.smb_buf_length + 4;
1377 rc = SendReceive2(xid, tcon->ses, iov, 1 /* num iovecs */,
1378 &resp_buf_type, CIFS_STD_OP | CIFS_LOG_ERROR);
1379 cifs_stats_inc(&tcon->num_reads);
1380 pSMBr = (READ_RSP *)iov[0].iov_base;
1382 cERROR(1, "Send error in read = %d", rc);
1384 int data_length = le16_to_cpu(pSMBr->DataLengthHigh);
1385 data_length = data_length << 16;
1386 data_length += le16_to_cpu(pSMBr->DataLength);
1387 *nbytes = data_length;
1389 /*check that DataLength would not go beyond end of SMB */
1390 if ((data_length > CIFSMaxBufSize)
1391 || (data_length > count)) {
1392 cFYI(1, "bad length %d for count %d",
1393 data_length, count);
1397 pReadData = (char *) (&pSMBr->hdr.Protocol) +
1398 le16_to_cpu(pSMBr->DataOffset);
1399 /* if (rc = copy_to_user(buf, pReadData, data_length)) {
1400 cERROR(1, "Faulting on read rc = %d",rc);
1402 }*/ /* can not use copy_to_user when using page cache*/
1404 memcpy(*buf, pReadData, data_length);
1408 /* cifs_small_buf_release(pSMB); */ /* Freed earlier now in SendReceive2 */
1410 if (resp_buf_type == CIFS_SMALL_BUFFER)
1411 cifs_small_buf_release(iov[0].iov_base);
1412 else if (resp_buf_type == CIFS_LARGE_BUFFER)
1413 cifs_buf_release(iov[0].iov_base);
1414 } else if (resp_buf_type != CIFS_NO_BUFFER) {
1415 /* return buffer to caller to free */
1416 *buf = iov[0].iov_base;
1417 if (resp_buf_type == CIFS_SMALL_BUFFER)
1418 *pbuf_type = CIFS_SMALL_BUFFER;
1419 else if (resp_buf_type == CIFS_LARGE_BUFFER)
1420 *pbuf_type = CIFS_LARGE_BUFFER;
1421 } /* else no valid buffer on return - leave as null */
1423 /* Note: On -EAGAIN error only caller can retry on handle based calls
1424 since file handle passed in no longer valid */
1430 CIFSSMBWrite(const int xid, struct cifsTconInfo *tcon,
1431 const int netfid, const unsigned int count,
1432 const __u64 offset, unsigned int *nbytes, const char *buf,
1433 const char __user *ubuf, const int long_op)
1436 WRITE_REQ *pSMB = NULL;
1437 WRITE_RSP *pSMBr = NULL;
1438 int bytes_returned, wct;
1444 /* cFYI(1, "write at %lld %d bytes", offset, count);*/
1445 if (tcon->ses == NULL)
1446 return -ECONNABORTED;
1448 if (tcon->ses->capabilities & CAP_LARGE_FILES)
1452 if ((offset >> 32) > 0) {
1453 /* can not handle big offset for old srv */
1458 rc = smb_init(SMB_COM_WRITE_ANDX, wct, tcon, (void **) &pSMB,
1462 /* tcon and ses pointer are checked in smb_init */
1463 if (tcon->ses->server == NULL)
1464 return -ECONNABORTED;
1466 pSMB->AndXCommand = 0xFF; /* none */
1468 pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF);
1470 pSMB->OffsetHigh = cpu_to_le32(offset >> 32);
1472 pSMB->Reserved = 0xFFFFFFFF;
1473 pSMB->WriteMode = 0;
1474 pSMB->Remaining = 0;
1476 /* Can increase buffer size if buffer is big enough in some cases ie we
1477 can send more if LARGE_WRITE_X capability returned by the server and if
1478 our buffer is big enough or if we convert to iovecs on socket writes
1479 and eliminate the copy to the CIFS buffer */
1480 if (tcon->ses->capabilities & CAP_LARGE_WRITE_X) {
1481 bytes_sent = min_t(const unsigned int, CIFSMaxBufSize, count);
1483 bytes_sent = (tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE)
1487 if (bytes_sent > count)
1490 cpu_to_le16(offsetof(struct smb_com_write_req, Data) - 4);
1492 memcpy(pSMB->Data, buf, bytes_sent);
1494 if (copy_from_user(pSMB->Data, ubuf, bytes_sent)) {
1495 cifs_buf_release(pSMB);
1498 } else if (count != 0) {
1500 cifs_buf_release(pSMB);
1502 } /* else setting file size with write of zero bytes */
1504 byte_count = bytes_sent + 1; /* pad */
1505 else /* wct == 12 */
1506 byte_count = bytes_sent + 5; /* bigger pad, smaller smb hdr */
1508 pSMB->DataLengthLow = cpu_to_le16(bytes_sent & 0xFFFF);
1509 pSMB->DataLengthHigh = cpu_to_le16(bytes_sent >> 16);
1510 pSMB->hdr.smb_buf_length += byte_count;
1513 pSMB->ByteCount = cpu_to_le16(byte_count);
1514 else { /* old style write has byte count 4 bytes earlier
1516 struct smb_com_writex_req *pSMBW =
1517 (struct smb_com_writex_req *)pSMB;
1518 pSMBW->ByteCount = cpu_to_le16(byte_count);
1521 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1522 (struct smb_hdr *) pSMBr, &bytes_returned, long_op);
1523 cifs_stats_inc(&tcon->num_writes);
1525 cFYI(1, "Send error in write = %d", rc);
1527 *nbytes = le16_to_cpu(pSMBr->CountHigh);
1528 *nbytes = (*nbytes) << 16;
1529 *nbytes += le16_to_cpu(pSMBr->Count);
1532 * Mask off high 16 bits when bytes written as returned by the
1533 * server is greater than bytes requested by the client. Some
1534 * OS/2 servers are known to set incorrect CountHigh values.
1536 if (*nbytes > count)
1540 cifs_buf_release(pSMB);
1542 /* Note: On -EAGAIN error only caller can retry on handle based calls
1543 since file handle passed in no longer valid */
1549 CIFSSMBWrite2(const int xid, struct cifsTconInfo *tcon,
1550 const int netfid, const unsigned int count,
1551 const __u64 offset, unsigned int *nbytes, struct kvec *iov,
1552 int n_vec, const int long_op)
1555 WRITE_REQ *pSMB = NULL;
1558 int resp_buf_type = 0;
1562 cFYI(1, "write2 at %lld %d bytes", (long long)offset, count);
1564 if (tcon->ses->capabilities & CAP_LARGE_FILES) {
1568 if ((offset >> 32) > 0) {
1569 /* can not handle big offset for old srv */
1573 rc = small_smb_init(SMB_COM_WRITE_ANDX, wct, tcon, (void **) &pSMB);
1576 /* tcon and ses pointer are checked in smb_init */
1577 if (tcon->ses->server == NULL)
1578 return -ECONNABORTED;
1580 pSMB->AndXCommand = 0xFF; /* none */
1582 pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF);
1584 pSMB->OffsetHigh = cpu_to_le32(offset >> 32);
1585 pSMB->Reserved = 0xFFFFFFFF;
1586 pSMB->WriteMode = 0;
1587 pSMB->Remaining = 0;
1590 cpu_to_le16(offsetof(struct smb_com_write_req, Data) - 4);
1592 pSMB->DataLengthLow = cpu_to_le16(count & 0xFFFF);
1593 pSMB->DataLengthHigh = cpu_to_le16(count >> 16);
1594 smb_hdr_len = pSMB->hdr.smb_buf_length + 1; /* hdr + 1 byte pad */
1596 pSMB->hdr.smb_buf_length += count+1;
1597 else /* wct == 12 */
1598 pSMB->hdr.smb_buf_length += count+5; /* smb data starts later */
1600 pSMB->ByteCount = cpu_to_le16(count + 1);
1601 else /* wct == 12 */ /* bigger pad, smaller smb hdr, keep offset ok */ {
1602 struct smb_com_writex_req *pSMBW =
1603 (struct smb_com_writex_req *)pSMB;
1604 pSMBW->ByteCount = cpu_to_le16(count + 5);
1606 iov[0].iov_base = pSMB;
1608 iov[0].iov_len = smb_hdr_len + 4;
1609 else /* wct == 12 pad bigger by four bytes */
1610 iov[0].iov_len = smb_hdr_len + 8;
1613 rc = SendReceive2(xid, tcon->ses, iov, n_vec + 1, &resp_buf_type,
1615 cifs_stats_inc(&tcon->num_writes);
1617 cFYI(1, "Send error Write2 = %d", rc);
1618 } else if (resp_buf_type == 0) {
1619 /* presumably this can not happen, but best to be safe */
1622 WRITE_RSP *pSMBr = (WRITE_RSP *)iov[0].iov_base;
1623 *nbytes = le16_to_cpu(pSMBr->CountHigh);
1624 *nbytes = (*nbytes) << 16;
1625 *nbytes += le16_to_cpu(pSMBr->Count);
1628 * Mask off high 16 bits when bytes written as returned by the
1629 * server is greater than bytes requested by the client. OS/2
1630 * servers are known to set incorrect CountHigh values.
1632 if (*nbytes > count)
1636 /* cifs_small_buf_release(pSMB); */ /* Freed earlier now in SendReceive2 */
1637 if (resp_buf_type == CIFS_SMALL_BUFFER)
1638 cifs_small_buf_release(iov[0].iov_base);
1639 else if (resp_buf_type == CIFS_LARGE_BUFFER)
1640 cifs_buf_release(iov[0].iov_base);
1642 /* Note: On -EAGAIN error only caller can retry on handle based calls
1643 since file handle passed in no longer valid */
1650 CIFSSMBLock(const int xid, struct cifsTconInfo *tcon,
1651 const __u16 smb_file_id, const __u64 len,
1652 const __u64 offset, const __u32 numUnlock,
1653 const __u32 numLock, const __u8 lockType, const bool waitFlag)
1656 LOCK_REQ *pSMB = NULL;
1657 /* LOCK_RSP *pSMBr = NULL; */ /* No response data other than rc to parse */
1662 cFYI(1, "CIFSSMBLock timeout %d numLock %d", (int)waitFlag, numLock);
1663 rc = small_smb_init(SMB_COM_LOCKING_ANDX, 8, tcon, (void **) &pSMB);
1668 if (lockType == LOCKING_ANDX_OPLOCK_RELEASE) {
1669 timeout = CIFS_ASYNC_OP; /* no response expected */
1671 } else if (waitFlag) {
1672 timeout = CIFS_BLOCKING_OP; /* blocking operation, no timeout */
1673 pSMB->Timeout = cpu_to_le32(-1);/* blocking - do not time out */
1678 pSMB->NumberOfLocks = cpu_to_le16(numLock);
1679 pSMB->NumberOfUnlocks = cpu_to_le16(numUnlock);
1680 pSMB->LockType = lockType;
1681 pSMB->AndXCommand = 0xFF; /* none */
1682 pSMB->Fid = smb_file_id; /* netfid stays le */
1684 if ((numLock != 0) || (numUnlock != 0)) {
1685 pSMB->Locks[0].Pid = cpu_to_le16(current->tgid);
1686 /* BB where to store pid high? */
1687 pSMB->Locks[0].LengthLow = cpu_to_le32((u32)len);
1688 pSMB->Locks[0].LengthHigh = cpu_to_le32((u32)(len>>32));
1689 pSMB->Locks[0].OffsetLow = cpu_to_le32((u32)offset);
1690 pSMB->Locks[0].OffsetHigh = cpu_to_le32((u32)(offset>>32));
1691 count = sizeof(LOCKING_ANDX_RANGE);
1696 pSMB->hdr.smb_buf_length += count;
1697 pSMB->ByteCount = cpu_to_le16(count);
1700 rc = SendReceiveBlockingLock(xid, tcon, (struct smb_hdr *) pSMB,
1701 (struct smb_hdr *) pSMB, &bytes_returned);
1702 cifs_small_buf_release(pSMB);
1704 rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *)pSMB,
1706 /* SMB buffer freed by function above */
1708 cifs_stats_inc(&tcon->num_locks);
1710 cFYI(1, "Send error in Lock = %d", rc);
1712 /* Note: On -EAGAIN error only caller can retry on handle based calls
1713 since file handle passed in no longer valid */
1718 CIFSSMBPosixLock(const int xid, struct cifsTconInfo *tcon,
1719 const __u16 smb_file_id, const int get_flag, const __u64 len,
1720 struct file_lock *pLockData, const __u16 lock_type,
1721 const bool waitFlag)
1723 struct smb_com_transaction2_sfi_req *pSMB = NULL;
1724 struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
1725 struct cifs_posix_lock *parm_data;
1728 int bytes_returned = 0;
1729 int resp_buf_type = 0;
1730 __u16 params, param_offset, offset, byte_count, count;
1733 cFYI(1, "Posix Lock");
1735 if (pLockData == NULL)
1738 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
1743 pSMBr = (struct smb_com_transaction2_sfi_rsp *)pSMB;
1746 pSMB->MaxSetupCount = 0;
1749 pSMB->Reserved2 = 0;
1750 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
1751 offset = param_offset + params;
1753 count = sizeof(struct cifs_posix_lock);
1754 pSMB->MaxParameterCount = cpu_to_le16(2);
1755 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB from sess */
1756 pSMB->SetupCount = 1;
1757 pSMB->Reserved3 = 0;
1759 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION);
1761 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
1762 byte_count = 3 /* pad */ + params + count;
1763 pSMB->DataCount = cpu_to_le16(count);
1764 pSMB->ParameterCount = cpu_to_le16(params);
1765 pSMB->TotalDataCount = pSMB->DataCount;
1766 pSMB->TotalParameterCount = pSMB->ParameterCount;
1767 pSMB->ParameterOffset = cpu_to_le16(param_offset);
1768 parm_data = (struct cifs_posix_lock *)
1769 (((char *) &pSMB->hdr.Protocol) + offset);
1771 parm_data->lock_type = cpu_to_le16(lock_type);
1773 timeout = CIFS_BLOCKING_OP; /* blocking operation, no timeout */
1774 parm_data->lock_flags = cpu_to_le16(1);
1775 pSMB->Timeout = cpu_to_le32(-1);
1779 parm_data->pid = cpu_to_le32(current->tgid);
1780 parm_data->start = cpu_to_le64(pLockData->fl_start);
1781 parm_data->length = cpu_to_le64(len); /* normalize negative numbers */
1783 pSMB->DataOffset = cpu_to_le16(offset);
1784 pSMB->Fid = smb_file_id;
1785 pSMB->InformationLevel = cpu_to_le16(SMB_SET_POSIX_LOCK);
1786 pSMB->Reserved4 = 0;
1787 pSMB->hdr.smb_buf_length += byte_count;
1788 pSMB->ByteCount = cpu_to_le16(byte_count);
1790 rc = SendReceiveBlockingLock(xid, tcon, (struct smb_hdr *) pSMB,
1791 (struct smb_hdr *) pSMBr, &bytes_returned);
1793 iov[0].iov_base = (char *)pSMB;
1794 iov[0].iov_len = pSMB->hdr.smb_buf_length + 4;
1795 rc = SendReceive2(xid, tcon->ses, iov, 1 /* num iovecs */,
1796 &resp_buf_type, timeout);
1797 pSMB = NULL; /* request buf already freed by SendReceive2. Do
1798 not try to free it twice below on exit */
1799 pSMBr = (struct smb_com_transaction2_sfi_rsp *)iov[0].iov_base;
1803 cFYI(1, "Send error in Posix Lock = %d", rc);
1804 } else if (get_flag) {
1805 /* lock structure can be returned on get */
1808 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
1810 if (rc || (pSMBr->ByteCount < sizeof(struct cifs_posix_lock))) {
1811 rc = -EIO; /* bad smb */
1814 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
1815 data_count = le16_to_cpu(pSMBr->t2.DataCount);
1816 if (data_count < sizeof(struct cifs_posix_lock)) {
1820 parm_data = (struct cifs_posix_lock *)
1821 ((char *)&pSMBr->hdr.Protocol + data_offset);
1822 if (parm_data->lock_type == __constant_cpu_to_le16(CIFS_UNLCK))
1823 pLockData->fl_type = F_UNLCK;
1825 if (parm_data->lock_type ==
1826 __constant_cpu_to_le16(CIFS_RDLCK))
1827 pLockData->fl_type = F_RDLCK;
1828 else if (parm_data->lock_type ==
1829 __constant_cpu_to_le16(CIFS_WRLCK))
1830 pLockData->fl_type = F_WRLCK;
1832 pLockData->fl_start = parm_data->start;
1833 pLockData->fl_end = parm_data->start +
1834 parm_data->length - 1;
1835 pLockData->fl_pid = parm_data->pid;
1841 cifs_small_buf_release(pSMB);
1843 if (resp_buf_type == CIFS_SMALL_BUFFER)
1844 cifs_small_buf_release(iov[0].iov_base);
1845 else if (resp_buf_type == CIFS_LARGE_BUFFER)
1846 cifs_buf_release(iov[0].iov_base);
1848 /* Note: On -EAGAIN error only caller can retry on handle based calls
1849 since file handle passed in no longer valid */
1856 CIFSSMBClose(const int xid, struct cifsTconInfo *tcon, int smb_file_id)
1859 CLOSE_REQ *pSMB = NULL;
1860 cFYI(1, "In CIFSSMBClose");
1862 /* do not retry on dead session on close */
1863 rc = small_smb_init(SMB_COM_CLOSE, 3, tcon, (void **) &pSMB);
1869 pSMB->FileID = (__u16) smb_file_id;
1870 pSMB->LastWriteTime = 0xFFFFFFFF;
1871 pSMB->ByteCount = 0;
1872 rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0);
1873 cifs_stats_inc(&tcon->num_closes);
1876 /* EINTR is expected when user ctl-c to kill app */
1877 cERROR(1, "Send error in Close = %d", rc);
1881 /* Since session is dead, file will be closed on server already */
1889 CIFSSMBFlush(const int xid, struct cifsTconInfo *tcon, int smb_file_id)
1892 FLUSH_REQ *pSMB = NULL;
1893 cFYI(1, "In CIFSSMBFlush");
1895 rc = small_smb_init(SMB_COM_FLUSH, 1, tcon, (void **) &pSMB);
1899 pSMB->FileID = (__u16) smb_file_id;
1900 pSMB->ByteCount = 0;
1901 rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0);
1902 cifs_stats_inc(&tcon->num_flushes);
1904 cERROR(1, "Send error in Flush = %d", rc);
1910 CIFSSMBRename(const int xid, struct cifsTconInfo *tcon,
1911 const char *fromName, const char *toName,
1912 const struct nls_table *nls_codepage, int remap)
1915 RENAME_REQ *pSMB = NULL;
1916 RENAME_RSP *pSMBr = NULL;
1918 int name_len, name_len2;
1921 cFYI(1, "In CIFSSMBRename");
1923 rc = smb_init(SMB_COM_RENAME, 1, tcon, (void **) &pSMB,
1928 pSMB->BufferFormat = 0x04;
1929 pSMB->SearchAttributes =
1930 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
1933 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1935 cifsConvertToUCS((__le16 *) pSMB->OldFileName, fromName,
1936 PATH_MAX, nls_codepage, remap);
1937 name_len++; /* trailing null */
1939 pSMB->OldFileName[name_len] = 0x04; /* pad */
1940 /* protocol requires ASCII signature byte on Unicode string */
1941 pSMB->OldFileName[name_len + 1] = 0x00;
1943 cifsConvertToUCS((__le16 *)&pSMB->OldFileName[name_len + 2],
1944 toName, PATH_MAX, nls_codepage, remap);
1945 name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
1946 name_len2 *= 2; /* convert to bytes */
1947 } else { /* BB improve the check for buffer overruns BB */
1948 name_len = strnlen(fromName, PATH_MAX);
1949 name_len++; /* trailing null */
1950 strncpy(pSMB->OldFileName, fromName, name_len);
1951 name_len2 = strnlen(toName, PATH_MAX);
1952 name_len2++; /* trailing null */
1953 pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */
1954 strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2);
1955 name_len2++; /* trailing null */
1956 name_len2++; /* signature byte */
1959 count = 1 /* 1st signature byte */ + name_len + name_len2;
1960 pSMB->hdr.smb_buf_length += count;
1961 pSMB->ByteCount = cpu_to_le16(count);
1963 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1964 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1965 cifs_stats_inc(&tcon->num_renames);
1967 cFYI(1, "Send error in rename = %d", rc);
1969 cifs_buf_release(pSMB);
1977 int CIFSSMBRenameOpenFile(const int xid, struct cifsTconInfo *pTcon,
1978 int netfid, const char *target_name,
1979 const struct nls_table *nls_codepage, int remap)
1981 struct smb_com_transaction2_sfi_req *pSMB = NULL;
1982 struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
1983 struct set_file_rename *rename_info;
1985 char dummy_string[30];
1987 int bytes_returned = 0;
1989 __u16 params, param_offset, offset, count, byte_count;
1991 cFYI(1, "Rename to File by handle");
1992 rc = smb_init(SMB_COM_TRANSACTION2, 15, pTcon, (void **) &pSMB,
1998 pSMB->MaxSetupCount = 0;
2002 pSMB->Reserved2 = 0;
2003 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
2004 offset = param_offset + params;
2006 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
2007 rename_info = (struct set_file_rename *) data_offset;
2008 pSMB->MaxParameterCount = cpu_to_le16(2);
2009 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB from sess */
2010 pSMB->SetupCount = 1;
2011 pSMB->Reserved3 = 0;
2012 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
2013 byte_count = 3 /* pad */ + params;
2014 pSMB->ParameterCount = cpu_to_le16(params);
2015 pSMB->TotalParameterCount = pSMB->ParameterCount;
2016 pSMB->ParameterOffset = cpu_to_le16(param_offset);
2017 pSMB->DataOffset = cpu_to_le16(offset);
2018 /* construct random name ".cifs_tmp<inodenum><mid>" */
2019 rename_info->overwrite = cpu_to_le32(1);
2020 rename_info->root_fid = 0;
2021 /* unicode only call */
2022 if (target_name == NULL) {
2023 sprintf(dummy_string, "cifs%x", pSMB->hdr.Mid);
2024 len_of_str = cifsConvertToUCS((__le16 *)rename_info->target_name,
2025 dummy_string, 24, nls_codepage, remap);
2027 len_of_str = cifsConvertToUCS((__le16 *)rename_info->target_name,
2028 target_name, PATH_MAX, nls_codepage,
2031 rename_info->target_name_len = cpu_to_le32(2 * len_of_str);
2032 count = 12 /* sizeof(struct set_file_rename) */ + (2 * len_of_str);
2033 byte_count += count;
2034 pSMB->DataCount = cpu_to_le16(count);
2035 pSMB->TotalDataCount = pSMB->DataCount;
2037 pSMB->InformationLevel =
2038 cpu_to_le16(SMB_SET_FILE_RENAME_INFORMATION);
2039 pSMB->Reserved4 = 0;
2040 pSMB->hdr.smb_buf_length += byte_count;
2041 pSMB->ByteCount = cpu_to_le16(byte_count);
2042 rc = SendReceive(xid, pTcon->ses, (struct smb_hdr *) pSMB,
2043 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2044 cifs_stats_inc(&pTcon->num_t2renames);
2046 cFYI(1, "Send error in Rename (by file handle) = %d", rc);
2048 cifs_buf_release(pSMB);
2050 /* Note: On -EAGAIN error only caller can retry on handle based calls
2051 since file handle passed in no longer valid */
2057 CIFSSMBCopy(const int xid, struct cifsTconInfo *tcon, const char *fromName,
2058 const __u16 target_tid, const char *toName, const int flags,
2059 const struct nls_table *nls_codepage, int remap)
2062 COPY_REQ *pSMB = NULL;
2063 COPY_RSP *pSMBr = NULL;
2065 int name_len, name_len2;
2068 cFYI(1, "In CIFSSMBCopy");
2070 rc = smb_init(SMB_COM_COPY, 1, tcon, (void **) &pSMB,
2075 pSMB->BufferFormat = 0x04;
2076 pSMB->Tid2 = target_tid;
2078 pSMB->Flags = cpu_to_le16(flags & COPY_TREE);
2080 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2081 name_len = cifsConvertToUCS((__le16 *) pSMB->OldFileName,
2082 fromName, PATH_MAX, nls_codepage,
2084 name_len++; /* trailing null */
2086 pSMB->OldFileName[name_len] = 0x04; /* pad */
2087 /* protocol requires ASCII signature byte on Unicode string */
2088 pSMB->OldFileName[name_len + 1] = 0x00;
2090 cifsConvertToUCS((__le16 *)&pSMB->OldFileName[name_len + 2],
2091 toName, PATH_MAX, nls_codepage, remap);
2092 name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
2093 name_len2 *= 2; /* convert to bytes */
2094 } else { /* BB improve the check for buffer overruns BB */
2095 name_len = strnlen(fromName, PATH_MAX);
2096 name_len++; /* trailing null */
2097 strncpy(pSMB->OldFileName, fromName, name_len);
2098 name_len2 = strnlen(toName, PATH_MAX);
2099 name_len2++; /* trailing null */
2100 pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */
2101 strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2);
2102 name_len2++; /* trailing null */
2103 name_len2++; /* signature byte */
2106 count = 1 /* 1st signature byte */ + name_len + name_len2;
2107 pSMB->hdr.smb_buf_length += count;
2108 pSMB->ByteCount = cpu_to_le16(count);
2110 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2111 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2113 cFYI(1, "Send error in copy = %d with %d files copied",
2114 rc, le16_to_cpu(pSMBr->CopyCount));
2116 cifs_buf_release(pSMB);
2125 CIFSUnixCreateSymLink(const int xid, struct cifsTconInfo *tcon,
2126 const char *fromName, const char *toName,
2127 const struct nls_table *nls_codepage)
2129 TRANSACTION2_SPI_REQ *pSMB = NULL;
2130 TRANSACTION2_SPI_RSP *pSMBr = NULL;
2133 int name_len_target;
2135 int bytes_returned = 0;
2136 __u16 params, param_offset, offset, byte_count;
2138 cFYI(1, "In Symlink Unix style");
2140 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2145 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2147 cifs_strtoUCS((__le16 *) pSMB->FileName, fromName, PATH_MAX
2148 /* find define for this maxpathcomponent */
2150 name_len++; /* trailing null */
2153 } else { /* BB improve the check for buffer overruns BB */
2154 name_len = strnlen(fromName, PATH_MAX);
2155 name_len++; /* trailing null */
2156 strncpy(pSMB->FileName, fromName, name_len);
2158 params = 6 + name_len;
2159 pSMB->MaxSetupCount = 0;
2163 pSMB->Reserved2 = 0;
2164 param_offset = offsetof(struct smb_com_transaction2_spi_req,
2165 InformationLevel) - 4;
2166 offset = param_offset + params;
2168 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
2169 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2171 cifs_strtoUCS((__le16 *) data_offset, toName, PATH_MAX
2172 /* find define for this maxpathcomponent */
2174 name_len_target++; /* trailing null */
2175 name_len_target *= 2;
2176 } else { /* BB improve the check for buffer overruns BB */
2177 name_len_target = strnlen(toName, PATH_MAX);
2178 name_len_target++; /* trailing null */
2179 strncpy(data_offset, toName, name_len_target);
2182 pSMB->MaxParameterCount = cpu_to_le16(2);
2183 /* BB find exact max on data count below from sess */
2184 pSMB->MaxDataCount = cpu_to_le16(1000);
2185 pSMB->SetupCount = 1;
2186 pSMB->Reserved3 = 0;
2187 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
2188 byte_count = 3 /* pad */ + params + name_len_target;
2189 pSMB->DataCount = cpu_to_le16(name_len_target);
2190 pSMB->ParameterCount = cpu_to_le16(params);
2191 pSMB->TotalDataCount = pSMB->DataCount;
2192 pSMB->TotalParameterCount = pSMB->ParameterCount;
2193 pSMB->ParameterOffset = cpu_to_le16(param_offset);
2194 pSMB->DataOffset = cpu_to_le16(offset);
2195 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_LINK);
2196 pSMB->Reserved4 = 0;
2197 pSMB->hdr.smb_buf_length += byte_count;
2198 pSMB->ByteCount = cpu_to_le16(byte_count);
2199 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2200 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2201 cifs_stats_inc(&tcon->num_symlinks);
2203 cFYI(1, "Send error in SetPathInfo create symlink = %d", rc);
2205 cifs_buf_release(pSMB);
2208 goto createSymLinkRetry;
2214 CIFSUnixCreateHardLink(const int xid, struct cifsTconInfo *tcon,
2215 const char *fromName, const char *toName,
2216 const struct nls_table *nls_codepage, int remap)
2218 TRANSACTION2_SPI_REQ *pSMB = NULL;
2219 TRANSACTION2_SPI_RSP *pSMBr = NULL;
2222 int name_len_target;
2224 int bytes_returned = 0;
2225 __u16 params, param_offset, offset, byte_count;
2227 cFYI(1, "In Create Hard link Unix style");
2228 createHardLinkRetry:
2229 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2234 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2235 name_len = cifsConvertToUCS((__le16 *) pSMB->FileName, toName,
2236 PATH_MAX, nls_codepage, remap);
2237 name_len++; /* trailing null */
2240 } else { /* BB improve the check for buffer overruns BB */
2241 name_len = strnlen(toName, PATH_MAX);
2242 name_len++; /* trailing null */
2243 strncpy(pSMB->FileName, toName, name_len);
2245 params = 6 + name_len;
2246 pSMB->MaxSetupCount = 0;
2250 pSMB->Reserved2 = 0;
2251 param_offset = offsetof(struct smb_com_transaction2_spi_req,
2252 InformationLevel) - 4;
2253 offset = param_offset + params;
2255 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
2256 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2258 cifsConvertToUCS((__le16 *) data_offset, fromName, PATH_MAX,
2259 nls_codepage, remap);
2260 name_len_target++; /* trailing null */
2261 name_len_target *= 2;
2262 } else { /* BB improve the check for buffer overruns BB */
2263 name_len_target = strnlen(fromName, PATH_MAX);
2264 name_len_target++; /* trailing null */
2265 strncpy(data_offset, fromName, name_len_target);
2268 pSMB->MaxParameterCount = cpu_to_le16(2);
2269 /* BB find exact max on data count below from sess*/
2270 pSMB->MaxDataCount = cpu_to_le16(1000);
2271 pSMB->SetupCount = 1;
2272 pSMB->Reserved3 = 0;
2273 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
2274 byte_count = 3 /* pad */ + params + name_len_target;
2275 pSMB->ParameterCount = cpu_to_le16(params);
2276 pSMB->TotalParameterCount = pSMB->ParameterCount;
2277 pSMB->DataCount = cpu_to_le16(name_len_target);
2278 pSMB->TotalDataCount = pSMB->DataCount;
2279 pSMB->ParameterOffset = cpu_to_le16(param_offset);
2280 pSMB->DataOffset = cpu_to_le16(offset);
2281 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_HLINK);
2282 pSMB->Reserved4 = 0;
2283 pSMB->hdr.smb_buf_length += byte_count;
2284 pSMB->ByteCount = cpu_to_le16(byte_count);
2285 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2286 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2287 cifs_stats_inc(&tcon->num_hardlinks);
2289 cFYI(1, "Send error in SetPathInfo (hard link) = %d", rc);
2291 cifs_buf_release(pSMB);
2293 goto createHardLinkRetry;
2299 CIFSCreateHardLink(const int xid, struct cifsTconInfo *tcon,
2300 const char *fromName, const char *toName,
2301 const struct nls_table *nls_codepage, int remap)
2304 NT_RENAME_REQ *pSMB = NULL;
2305 RENAME_RSP *pSMBr = NULL;
2307 int name_len, name_len2;
2310 cFYI(1, "In CIFSCreateHardLink");
2311 winCreateHardLinkRetry:
2313 rc = smb_init(SMB_COM_NT_RENAME, 4, tcon, (void **) &pSMB,
2318 pSMB->SearchAttributes =
2319 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
2321 pSMB->Flags = cpu_to_le16(CREATE_HARD_LINK);
2322 pSMB->ClusterCount = 0;
2324 pSMB->BufferFormat = 0x04;
2326 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2328 cifsConvertToUCS((__le16 *) pSMB->OldFileName, fromName,
2329 PATH_MAX, nls_codepage, remap);
2330 name_len++; /* trailing null */
2333 /* protocol specifies ASCII buffer format (0x04) for unicode */
2334 pSMB->OldFileName[name_len] = 0x04;
2335 pSMB->OldFileName[name_len + 1] = 0x00; /* pad */
2337 cifsConvertToUCS((__le16 *)&pSMB->OldFileName[name_len + 2],
2338 toName, PATH_MAX, nls_codepage, remap);
2339 name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
2340 name_len2 *= 2; /* convert to bytes */
2341 } else { /* BB improve the check for buffer overruns BB */
2342 name_len = strnlen(fromName, PATH_MAX);
2343 name_len++; /* trailing null */
2344 strncpy(pSMB->OldFileName, fromName, name_len);
2345 name_len2 = strnlen(toName, PATH_MAX);
2346 name_len2++; /* trailing null */
2347 pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */
2348 strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2);
2349 name_len2++; /* trailing null */
2350 name_len2++; /* signature byte */
2353 count = 1 /* string type byte */ + name_len + name_len2;
2354 pSMB->hdr.smb_buf_length += count;
2355 pSMB->ByteCount = cpu_to_le16(count);
2357 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2358 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2359 cifs_stats_inc(&tcon->num_hardlinks);
2361 cFYI(1, "Send error in hard link (NT rename) = %d", rc);
2363 cifs_buf_release(pSMB);
2365 goto winCreateHardLinkRetry;
2371 CIFSSMBUnixQuerySymLink(const int xid, struct cifsTconInfo *tcon,
2372 const unsigned char *searchName, char **symlinkinfo,
2373 const struct nls_table *nls_codepage)
2375 /* SMB_QUERY_FILE_UNIX_LINK */
2376 TRANSACTION2_QPI_REQ *pSMB = NULL;
2377 TRANSACTION2_QPI_RSP *pSMBr = NULL;
2381 __u16 params, byte_count;
2384 cFYI(1, "In QPathSymLinkInfo (Unix) for path %s", searchName);
2387 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2392 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2394 cifs_strtoUCS((__le16 *) pSMB->FileName, searchName,
2395 PATH_MAX, nls_codepage);
2396 name_len++; /* trailing null */
2398 } else { /* BB improve the check for buffer overruns BB */
2399 name_len = strnlen(searchName, PATH_MAX);
2400 name_len++; /* trailing null */
2401 strncpy(pSMB->FileName, searchName, name_len);
2404 params = 2 /* level */ + 4 /* rsrvd */ + name_len /* incl null */ ;
2405 pSMB->TotalDataCount = 0;
2406 pSMB->MaxParameterCount = cpu_to_le16(2);
2407 pSMB->MaxDataCount = cpu_to_le16(CIFSMaxBufSize);
2408 pSMB->MaxSetupCount = 0;
2412 pSMB->Reserved2 = 0;
2413 pSMB->ParameterOffset = cpu_to_le16(offsetof(
2414 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
2415 pSMB->DataCount = 0;
2416 pSMB->DataOffset = 0;
2417 pSMB->SetupCount = 1;
2418 pSMB->Reserved3 = 0;
2419 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
2420 byte_count = params + 1 /* pad */ ;
2421 pSMB->TotalParameterCount = cpu_to_le16(params);
2422 pSMB->ParameterCount = pSMB->TotalParameterCount;
2423 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_LINK);
2424 pSMB->Reserved4 = 0;
2425 pSMB->hdr.smb_buf_length += byte_count;
2426 pSMB->ByteCount = cpu_to_le16(byte_count);
2428 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2429 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2431 cFYI(1, "Send error in QuerySymLinkInfo = %d", rc);
2433 /* decode response */
2435 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
2436 /* BB also check enough total bytes returned */
2437 if (rc || (pSMBr->ByteCount < 2))
2441 u16 count = le16_to_cpu(pSMBr->t2.DataCount);
2443 data_start = ((char *) &pSMBr->hdr.Protocol) +
2444 le16_to_cpu(pSMBr->t2.DataOffset);
2446 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
2451 /* BB FIXME investigate remapping reserved chars here */
2452 *symlinkinfo = cifs_strndup_from_ucs(data_start, count,
2453 is_unicode, nls_codepage);
2458 cifs_buf_release(pSMB);
2460 goto querySymLinkRetry;
2464 #ifdef CONFIG_CIFS_EXPERIMENTAL
2465 /* Initialize NT TRANSACT SMB into small smb request buffer.
2466 This assumes that all NT TRANSACTS that we init here have
2467 total parm and data under about 400 bytes (to fit in small cifs
2468 buffer size), which is the case so far, it easily fits. NB:
2469 Setup words themselves and ByteCount
2470 MaxSetupCount (size of returned setup area) and
2471 MaxParameterCount (returned parms size) must be set by caller */
2473 smb_init_nttransact(const __u16 sub_command, const int setup_count,
2474 const int parm_len, struct cifsTconInfo *tcon,
2479 struct smb_com_ntransact_req *pSMB;
2481 rc = small_smb_init(SMB_COM_NT_TRANSACT, 19 + setup_count, tcon,
2485 *ret_buf = (void *)pSMB;
2487 pSMB->TotalParameterCount = cpu_to_le32(parm_len);
2488 pSMB->TotalDataCount = 0;
2489 pSMB->MaxDataCount = cpu_to_le32((tcon->ses->server->maxBuf -
2490 MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
2491 pSMB->ParameterCount = pSMB->TotalParameterCount;
2492 pSMB->DataCount = pSMB->TotalDataCount;
2493 temp_offset = offsetof(struct smb_com_ntransact_req, Parms) +
2494 (setup_count * 2) - 4 /* for rfc1001 length itself */;
2495 pSMB->ParameterOffset = cpu_to_le32(temp_offset);
2496 pSMB->DataOffset = cpu_to_le32(temp_offset + parm_len);
2497 pSMB->SetupCount = setup_count; /* no need to le convert byte fields */
2498 pSMB->SubCommand = cpu_to_le16(sub_command);
2503 validate_ntransact(char *buf, char **ppparm, char **ppdata,
2504 __u32 *pparmlen, __u32 *pdatalen)
2507 __u32 data_count, data_offset, parm_count, parm_offset;
2508 struct smb_com_ntransact_rsp *pSMBr;
2516 pSMBr = (struct smb_com_ntransact_rsp *)buf;
2518 /* ByteCount was converted from little endian in SendReceive */
2519 end_of_smb = 2 /* sizeof byte count */ + pSMBr->ByteCount +
2520 (char *)&pSMBr->ByteCount;
2522 data_offset = le32_to_cpu(pSMBr->DataOffset);
2523 data_count = le32_to_cpu(pSMBr->DataCount);
2524 parm_offset = le32_to_cpu(pSMBr->ParameterOffset);
2525 parm_count = le32_to_cpu(pSMBr->ParameterCount);
2527 *ppparm = (char *)&pSMBr->hdr.Protocol + parm_offset;
2528 *ppdata = (char *)&pSMBr->hdr.Protocol + data_offset;
2530 /* should we also check that parm and data areas do not overlap? */
2531 if (*ppparm > end_of_smb) {
2532 cFYI(1, "parms start after end of smb");
2534 } else if (parm_count + *ppparm > end_of_smb) {
2535 cFYI(1, "parm end after end of smb");
2537 } else if (*ppdata > end_of_smb) {
2538 cFYI(1, "data starts after end of smb");
2540 } else if (data_count + *ppdata > end_of_smb) {
2541 cFYI(1, "data %p + count %d (%p) past smb end %p start %p",
2542 *ppdata, data_count, (data_count + *ppdata),
2545 } else if (parm_count + data_count > pSMBr->ByteCount) {
2546 cFYI(1, "parm count and data count larger than SMB");
2549 *pdatalen = data_count;
2550 *pparmlen = parm_count;
2555 CIFSSMBQueryReparseLinkInfo(const int xid, struct cifsTconInfo *tcon,
2556 const unsigned char *searchName,
2557 char *symlinkinfo, const int buflen, __u16 fid,
2558 const struct nls_table *nls_codepage)
2562 struct smb_com_transaction_ioctl_req *pSMB;
2563 struct smb_com_transaction_ioctl_rsp *pSMBr;
2565 cFYI(1, "In Windows reparse style QueryLink for path %s", searchName);
2566 rc = smb_init(SMB_COM_NT_TRANSACT, 23, tcon, (void **) &pSMB,
2571 pSMB->TotalParameterCount = 0 ;
2572 pSMB->TotalDataCount = 0;
2573 pSMB->MaxParameterCount = cpu_to_le32(2);
2574 /* BB find exact data count max from sess structure BB */
2575 pSMB->MaxDataCount = cpu_to_le32((tcon->ses->server->maxBuf -
2576 MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
2577 pSMB->MaxSetupCount = 4;
2579 pSMB->ParameterOffset = 0;
2580 pSMB->DataCount = 0;
2581 pSMB->DataOffset = 0;
2582 pSMB->SetupCount = 4;
2583 pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_IOCTL);
2584 pSMB->ParameterCount = pSMB->TotalParameterCount;
2585 pSMB->FunctionCode = cpu_to_le32(FSCTL_GET_REPARSE_POINT);
2586 pSMB->IsFsctl = 1; /* FSCTL */
2587 pSMB->IsRootFlag = 0;
2588 pSMB->Fid = fid; /* file handle always le */
2589 pSMB->ByteCount = 0;
2591 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2592 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2594 cFYI(1, "Send error in QueryReparseLinkInfo = %d", rc);
2595 } else { /* decode response */
2596 __u32 data_offset = le32_to_cpu(pSMBr->DataOffset);
2597 __u32 data_count = le32_to_cpu(pSMBr->DataCount);
2598 if ((pSMBr->ByteCount < 2) || (data_offset > 512)) {
2599 /* BB also check enough total bytes returned */
2600 rc = -EIO; /* bad smb */
2603 if (data_count && (data_count < 2048)) {
2604 char *end_of_smb = 2 /* sizeof byte count */ +
2605 pSMBr->ByteCount + (char *)&pSMBr->ByteCount;
2607 struct reparse_data *reparse_buf =
2608 (struct reparse_data *)
2609 ((char *)&pSMBr->hdr.Protocol
2611 if ((char *)reparse_buf >= end_of_smb) {
2615 if ((reparse_buf->LinkNamesBuf +
2616 reparse_buf->TargetNameOffset +
2617 reparse_buf->TargetNameLen) > end_of_smb) {
2618 cFYI(1, "reparse buf beyond SMB");
2623 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
2624 cifs_from_ucs2(symlinkinfo, (__le16 *)
2625 (reparse_buf->LinkNamesBuf +
2626 reparse_buf->TargetNameOffset),
2628 reparse_buf->TargetNameLen,
2630 } else { /* ASCII names */
2631 strncpy(symlinkinfo,
2632 reparse_buf->LinkNamesBuf +
2633 reparse_buf->TargetNameOffset,
2634 min_t(const int, buflen,
2635 reparse_buf->TargetNameLen));
2639 cFYI(1, "Invalid return data count on "
2640 "get reparse info ioctl");
2642 symlinkinfo[buflen] = 0; /* just in case so the caller
2643 does not go off the end of the buffer */
2644 cFYI(1, "readlink result - %s", symlinkinfo);
2648 cifs_buf_release(pSMB);
2650 /* Note: On -EAGAIN error only caller can retry on handle based calls
2651 since file handle passed in no longer valid */
2655 #endif /* CIFS_EXPERIMENTAL */
2657 #ifdef CONFIG_CIFS_POSIX
2659 /*Convert an Access Control Entry from wire format to local POSIX xattr format*/
2660 static void cifs_convert_ace(posix_acl_xattr_entry *ace,
2661 struct cifs_posix_ace *cifs_ace)
2663 /* u8 cifs fields do not need le conversion */
2664 ace->e_perm = cpu_to_le16(cifs_ace->cifs_e_perm);
2665 ace->e_tag = cpu_to_le16(cifs_ace->cifs_e_tag);
2666 ace->e_id = cpu_to_le32(le64_to_cpu(cifs_ace->cifs_uid));
2667 /* cFYI(1, "perm %d tag %d id %d",ace->e_perm,ace->e_tag,ace->e_id); */
2672 /* Convert ACL from CIFS POSIX wire format to local Linux POSIX ACL xattr */
2673 static int cifs_copy_posix_acl(char *trgt, char *src, const int buflen,
2674 const int acl_type, const int size_of_data_area)
2679 struct cifs_posix_ace *pACE;
2680 struct cifs_posix_acl *cifs_acl = (struct cifs_posix_acl *)src;
2681 posix_acl_xattr_header *local_acl = (posix_acl_xattr_header *)trgt;
2683 if (le16_to_cpu(cifs_acl->version) != CIFS_ACL_VERSION)
2686 if (acl_type & ACL_TYPE_ACCESS) {
2687 count = le16_to_cpu(cifs_acl->access_entry_count);
2688 pACE = &cifs_acl->ace_array[0];
2689 size = sizeof(struct cifs_posix_acl);
2690 size += sizeof(struct cifs_posix_ace) * count;
2691 /* check if we would go beyond end of SMB */
2692 if (size_of_data_area < size) {
2693 cFYI(1, "bad CIFS POSIX ACL size %d vs. %d",
2694 size_of_data_area, size);
2697 } else if (acl_type & ACL_TYPE_DEFAULT) {
2698 count = le16_to_cpu(cifs_acl->access_entry_count);
2699 size = sizeof(struct cifs_posix_acl);
2700 size += sizeof(struct cifs_posix_ace) * count;
2701 /* skip past access ACEs to get to default ACEs */
2702 pACE = &cifs_acl->ace_array[count];
2703 count = le16_to_cpu(cifs_acl->default_entry_count);
2704 size += sizeof(struct cifs_posix_ace) * count;
2705 /* check if we would go beyond end of SMB */
2706 if (size_of_data_area < size)
2713 size = posix_acl_xattr_size(count);
2714 if ((buflen == 0) || (local_acl == NULL)) {
2715 /* used to query ACL EA size */
2716 } else if (size > buflen) {
2718 } else /* buffer big enough */ {
2719 local_acl->a_version = cpu_to_le32(POSIX_ACL_XATTR_VERSION);
2720 for (i = 0; i < count ; i++) {
2721 cifs_convert_ace(&local_acl->a_entries[i], pACE);
2728 static __u16 convert_ace_to_cifs_ace(struct cifs_posix_ace *cifs_ace,
2729 const posix_acl_xattr_entry *local_ace)
2731 __u16 rc = 0; /* 0 = ACL converted ok */
2733 cifs_ace->cifs_e_perm = le16_to_cpu(local_ace->e_perm);
2734 cifs_ace->cifs_e_tag = le16_to_cpu(local_ace->e_tag);
2735 /* BB is there a better way to handle the large uid? */
2736 if (local_ace->e_id == cpu_to_le32(-1)) {
2737 /* Probably no need to le convert -1 on any arch but can not hurt */
2738 cifs_ace->cifs_uid = cpu_to_le64(-1);
2740 cifs_ace->cifs_uid = cpu_to_le64(le32_to_cpu(local_ace->e_id));
2741 /*cFYI(1, "perm %d tag %d id %d",ace->e_perm,ace->e_tag,ace->e_id);*/
2745 /* Convert ACL from local Linux POSIX xattr to CIFS POSIX ACL wire format */
2746 static __u16 ACL_to_cifs_posix(char *parm_data, const char *pACL,
2747 const int buflen, const int acl_type)
2750 struct cifs_posix_acl *cifs_acl = (struct cifs_posix_acl *)parm_data;
2751 posix_acl_xattr_header *local_acl = (posix_acl_xattr_header *)pACL;
2755 if ((buflen == 0) || (pACL == NULL) || (cifs_acl == NULL))
2758 count = posix_acl_xattr_count((size_t)buflen);
2759 cFYI(1, "setting acl with %d entries from buf of length %d and "
2761 count, buflen, le32_to_cpu(local_acl->a_version));
2762 if (le32_to_cpu(local_acl->a_version) != 2) {
2763 cFYI(1, "unknown POSIX ACL version %d",
2764 le32_to_cpu(local_acl->a_version));
2767 cifs_acl->version = cpu_to_le16(1);
2768 if (acl_type == ACL_TYPE_ACCESS)
2769 cifs_acl->access_entry_count = cpu_to_le16(count);
2770 else if (acl_type == ACL_TYPE_DEFAULT)
2771 cifs_acl->default_entry_count = cpu_to_le16(count);
2773 cFYI(1, "unknown ACL type %d", acl_type);
2776 for (i = 0; i < count; i++) {
2777 rc = convert_ace_to_cifs_ace(&cifs_acl->ace_array[i],
2778 &local_acl->a_entries[i]);
2780 /* ACE not converted */
2785 rc = (__u16)(count * sizeof(struct cifs_posix_ace));
2786 rc += sizeof(struct cifs_posix_acl);
2787 /* BB add check to make sure ACL does not overflow SMB */
2793 CIFSSMBGetPosixACL(const int xid, struct cifsTconInfo *tcon,
2794 const unsigned char *searchName,
2795 char *acl_inf, const int buflen, const int acl_type,
2796 const struct nls_table *nls_codepage, int remap)
2798 /* SMB_QUERY_POSIX_ACL */
2799 TRANSACTION2_QPI_REQ *pSMB = NULL;
2800 TRANSACTION2_QPI_RSP *pSMBr = NULL;
2804 __u16 params, byte_count;
2806 cFYI(1, "In GetPosixACL (Unix) for path %s", searchName);
2809 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2814 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2816 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
2817 PATH_MAX, nls_codepage, remap);
2818 name_len++; /* trailing null */
2820 pSMB->FileName[name_len] = 0;
2821 pSMB->FileName[name_len+1] = 0;
2822 } else { /* BB improve the check for buffer overruns BB */
2823 name_len = strnlen(searchName, PATH_MAX);
2824 name_len++; /* trailing null */
2825 strncpy(pSMB->FileName, searchName, name_len);
2828 params = 2 /* level */ + 4 /* rsrvd */ + name_len /* incl null */ ;
2829 pSMB->TotalDataCount = 0;
2830 pSMB->MaxParameterCount = cpu_to_le16(2);
2831 /* BB find exact max data count below from sess structure BB */
2832 pSMB->MaxDataCount = cpu_to_le16(4000);
2833 pSMB->MaxSetupCount = 0;
2837 pSMB->Reserved2 = 0;
2838 pSMB->ParameterOffset = cpu_to_le16(
2839 offsetof(struct smb_com_transaction2_qpi_req,
2840 InformationLevel) - 4);
2841 pSMB->DataCount = 0;
2842 pSMB->DataOffset = 0;
2843 pSMB->SetupCount = 1;
2844 pSMB->Reserved3 = 0;
2845 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
2846 byte_count = params + 1 /* pad */ ;
2847 pSMB->TotalParameterCount = cpu_to_le16(params);
2848 pSMB->ParameterCount = pSMB->TotalParameterCount;
2849 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_POSIX_ACL);
2850 pSMB->Reserved4 = 0;
2851 pSMB->hdr.smb_buf_length += byte_count;
2852 pSMB->ByteCount = cpu_to_le16(byte_count);
2854 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2855 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2856 cifs_stats_inc(&tcon->num_acl_get);
2858 cFYI(1, "Send error in Query POSIX ACL = %d", rc);
2860 /* decode response */
2862 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
2863 if (rc || (pSMBr->ByteCount < 2))
2864 /* BB also check enough total bytes returned */
2865 rc = -EIO; /* bad smb */
2867 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
2868 __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
2869 rc = cifs_copy_posix_acl(acl_inf,
2870 (char *)&pSMBr->hdr.Protocol+data_offset,
2871 buflen, acl_type, count);
2874 cifs_buf_release(pSMB);
2881 CIFSSMBSetPosixACL(const int xid, struct cifsTconInfo *tcon,
2882 const unsigned char *fileName,
2883 const char *local_acl, const int buflen,
2885 const struct nls_table *nls_codepage, int remap)
2887 struct smb_com_transaction2_spi_req *pSMB = NULL;
2888 struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
2892 int bytes_returned = 0;
2893 __u16 params, byte_count, data_count, param_offset, offset;
2895 cFYI(1, "In SetPosixACL (Unix) for path %s", fileName);
2897 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2901 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2903 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
2904 PATH_MAX, nls_codepage, remap);
2905 name_len++; /* trailing null */
2907 } else { /* BB improve the check for buffer overruns BB */
2908 name_len = strnlen(fileName, PATH_MAX);
2909 name_len++; /* trailing null */
2910 strncpy(pSMB->FileName, fileName, name_len);
2912 params = 6 + name_len;
2913 pSMB->MaxParameterCount = cpu_to_le16(2);
2914 /* BB find max SMB size from sess */
2915 pSMB->MaxDataCount = cpu_to_le16(1000);
2916 pSMB->MaxSetupCount = 0;
2920 pSMB->Reserved2 = 0;
2921 param_offset = offsetof(struct smb_com_transaction2_spi_req,
2922 InformationLevel) - 4;
2923 offset = param_offset + params;
2924 parm_data = ((char *) &pSMB->hdr.Protocol) + offset;
2925 pSMB->ParameterOffset = cpu_to_le16(param_offset);
2927 /* convert to on the wire format for POSIX ACL */
2928 data_count = ACL_to_cifs_posix(parm_data, local_acl, buflen, acl_type);
2930 if (data_count == 0) {
2932 goto setACLerrorExit;
2934 pSMB->DataOffset = cpu_to_le16(offset);
2935 pSMB->SetupCount = 1;
2936 pSMB->Reserved3 = 0;
2937 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
2938 pSMB->InformationLevel = cpu_to_le16(SMB_SET_POSIX_ACL);
2939 byte_count = 3 /* pad */ + params + data_count;
2940 pSMB->DataCount = cpu_to_le16(data_count);
2941 pSMB->TotalDataCount = pSMB->DataCount;
2942 pSMB->ParameterCount = cpu_to_le16(params);
2943 pSMB->TotalParameterCount = pSMB->ParameterCount;
2944 pSMB->Reserved4 = 0;
2945 pSMB->hdr.smb_buf_length += byte_count;
2946 pSMB->ByteCount = cpu_to_le16(byte_count);
2947 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2948 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2950 cFYI(1, "Set POSIX ACL returned %d", rc);
2953 cifs_buf_release(pSMB);
2959 /* BB fix tabs in this function FIXME BB */
2961 CIFSGetExtAttr(const int xid, struct cifsTconInfo *tcon,
2962 const int netfid, __u64 *pExtAttrBits, __u64 *pMask)
2965 struct smb_t2_qfi_req *pSMB = NULL;
2966 struct smb_t2_qfi_rsp *pSMBr = NULL;
2968 __u16 params, byte_count;
2970 cFYI(1, "In GetExtAttr");
2975 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2980 params = 2 /* level */ + 2 /* fid */;
2981 pSMB->t2.TotalDataCount = 0;
2982 pSMB->t2.MaxParameterCount = cpu_to_le16(4);
2983 /* BB find exact max data count below from sess structure BB */
2984 pSMB->t2.MaxDataCount = cpu_to_le16(4000);
2985 pSMB->t2.MaxSetupCount = 0;
2986 pSMB->t2.Reserved = 0;
2988 pSMB->t2.Timeout = 0;
2989 pSMB->t2.Reserved2 = 0;
2990 pSMB->t2.ParameterOffset = cpu_to_le16(offsetof(struct smb_t2_qfi_req,
2992 pSMB->t2.DataCount = 0;
2993 pSMB->t2.DataOffset = 0;
2994 pSMB->t2.SetupCount = 1;
2995 pSMB->t2.Reserved3 = 0;
2996 pSMB->t2.SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION);
2997 byte_count = params + 1 /* pad */ ;
2998 pSMB->t2.TotalParameterCount = cpu_to_le16(params);
2999 pSMB->t2.ParameterCount = pSMB->t2.TotalParameterCount;
3000 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_ATTR_FLAGS);
3003 pSMB->hdr.smb_buf_length += byte_count;
3004 pSMB->t2.ByteCount = cpu_to_le16(byte_count);
3006 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3007 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3009 cFYI(1, "error %d in GetExtAttr", rc);
3011 /* decode response */
3012 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3013 if (rc || (pSMBr->ByteCount < 2))
3014 /* BB also check enough total bytes returned */
3015 /* If rc should we check for EOPNOSUPP and
3016 disable the srvino flag? or in caller? */
3017 rc = -EIO; /* bad smb */
3019 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3020 __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
3021 struct file_chattr_info *pfinfo;
3022 /* BB Do we need a cast or hash here ? */
3024 cFYI(1, "Illegal size ret in GetExtAttr");
3028 pfinfo = (struct file_chattr_info *)
3029 (data_offset + (char *) &pSMBr->hdr.Protocol);
3030 *pExtAttrBits = le64_to_cpu(pfinfo->mode);
3031 *pMask = le64_to_cpu(pfinfo->mask);
3035 cifs_buf_release(pSMB);
3037 goto GetExtAttrRetry;
3041 #endif /* CONFIG_POSIX */
3043 #ifdef CONFIG_CIFS_EXPERIMENTAL
3044 /* Get Security Descriptor (by handle) from remote server for a file or dir */
3046 CIFSSMBGetCIFSACL(const int xid, struct cifsTconInfo *tcon, __u16 fid,
3047 struct cifs_ntsd **acl_inf, __u32 *pbuflen)
3051 QUERY_SEC_DESC_REQ *pSMB;
3054 cFYI(1, "GetCifsACL");
3059 rc = smb_init_nttransact(NT_TRANSACT_QUERY_SECURITY_DESC, 0,
3060 8 /* parm len */, tcon, (void **) &pSMB);
3064 pSMB->MaxParameterCount = cpu_to_le32(4);
3065 /* BB TEST with big acls that might need to be e.g. larger than 16K */
3066 pSMB->MaxSetupCount = 0;
3067 pSMB->Fid = fid; /* file handle always le */
3068 pSMB->AclFlags = cpu_to_le32(CIFS_ACL_OWNER | CIFS_ACL_GROUP |
3070 pSMB->ByteCount = cpu_to_le16(11); /* 3 bytes pad + 8 bytes parm */
3071 pSMB->hdr.smb_buf_length += 11;
3072 iov[0].iov_base = (char *)pSMB;
3073 iov[0].iov_len = pSMB->hdr.smb_buf_length + 4;
3075 rc = SendReceive2(xid, tcon->ses, iov, 1 /* num iovec */, &buf_type,
3077 cifs_stats_inc(&tcon->num_acl_get);
3079 cFYI(1, "Send error in QuerySecDesc = %d", rc);
3080 } else { /* decode response */
3084 struct smb_com_ntransact_rsp *pSMBr;
3087 /* validate_nttransact */
3088 rc = validate_ntransact(iov[0].iov_base, (char **)&parm,
3089 &pdata, &parm_len, pbuflen);
3092 pSMBr = (struct smb_com_ntransact_rsp *)iov[0].iov_base;
3094 cFYI(1, "smb %p parm %p data %p", pSMBr, parm, *acl_inf);
3096 if (le32_to_cpu(pSMBr->ParameterCount) != 4) {
3097 rc = -EIO; /* bad smb */
3102 /* BB check that data area is minimum length and as big as acl_len */
3104 acl_len = le32_to_cpu(*parm);
3105 if (acl_len != *pbuflen) {
3106 cERROR(1, "acl length %d does not match %d",
3108 if (*pbuflen > acl_len)
3112 /* check if buffer is big enough for the acl
3113 header followed by the smallest SID */
3114 if ((*pbuflen < sizeof(struct cifs_ntsd) + 8) ||
3115 (*pbuflen >= 64 * 1024)) {
3116 cERROR(1, "bad acl length %d", *pbuflen);
3120 *acl_inf = kmalloc(*pbuflen, GFP_KERNEL);
3121 if (*acl_inf == NULL) {
3125 memcpy(*acl_inf, pdata, *pbuflen);
3129 if (buf_type == CIFS_SMALL_BUFFER)
3130 cifs_small_buf_release(iov[0].iov_base);
3131 else if (buf_type == CIFS_LARGE_BUFFER)
3132 cifs_buf_release(iov[0].iov_base);
3133 /* cifs_small_buf_release(pSMB); */ /* Freed earlier now in SendReceive2 */
3138 CIFSSMBSetCIFSACL(const int xid, struct cifsTconInfo *tcon, __u16 fid,
3139 struct cifs_ntsd *pntsd, __u32 acllen)
3141 __u16 byte_count, param_count, data_count, param_offset, data_offset;
3143 int bytes_returned = 0;
3144 SET_SEC_DESC_REQ *pSMB = NULL;
3145 NTRANSACT_RSP *pSMBr = NULL;
3148 rc = smb_init(SMB_COM_NT_TRANSACT, 19, tcon, (void **) &pSMB,
3153 pSMB->MaxSetupCount = 0;
3157 param_offset = offsetof(struct smb_com_transaction_ssec_req, Fid) - 4;
3158 data_count = acllen;
3159 data_offset = param_offset + param_count;
3160 byte_count = 3 /* pad */ + param_count;
3162 pSMB->DataCount = cpu_to_le32(data_count);
3163 pSMB->TotalDataCount = pSMB->DataCount;
3164 pSMB->MaxParameterCount = cpu_to_le32(4);
3165 pSMB->MaxDataCount = cpu_to_le32(16384);
3166 pSMB->ParameterCount = cpu_to_le32(param_count);
3167 pSMB->ParameterOffset = cpu_to_le32(param_offset);
3168 pSMB->TotalParameterCount = pSMB->ParameterCount;
3169 pSMB->DataOffset = cpu_to_le32(data_offset);
3170 pSMB->SetupCount = 0;
3171 pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_SET_SECURITY_DESC);
3172 pSMB->ByteCount = cpu_to_le16(byte_count+data_count);
3174 pSMB->Fid = fid; /* file handle always le */
3175 pSMB->Reserved2 = 0;
3176 pSMB->AclFlags = cpu_to_le32(CIFS_ACL_DACL);
3178 if (pntsd && acllen) {
3179 memcpy((char *) &pSMBr->hdr.Protocol + data_offset,
3182 pSMB->hdr.smb_buf_length += (byte_count + data_count);
3185 pSMB->hdr.smb_buf_length += byte_count;
3187 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3188 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3190 cFYI(1, "SetCIFSACL bytes_returned: %d, rc: %d", bytes_returned, rc);
3192 cFYI(1, "Set CIFS ACL returned %d", rc);
3193 cifs_buf_release(pSMB);
3196 goto setCifsAclRetry;
3201 #endif /* CONFIG_CIFS_EXPERIMENTAL */
3203 /* Legacy Query Path Information call for lookup to old servers such
3205 int SMBQueryInformation(const int xid, struct cifsTconInfo *tcon,
3206 const unsigned char *searchName,
3207 FILE_ALL_INFO *pFinfo,
3208 const struct nls_table *nls_codepage, int remap)
3210 QUERY_INFORMATION_REQ *pSMB;
3211 QUERY_INFORMATION_RSP *pSMBr;
3216 cFYI(1, "In SMBQPath path %s", searchName);
3218 rc = smb_init(SMB_COM_QUERY_INFORMATION, 0, tcon, (void **) &pSMB,
3223 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3225 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
3226 PATH_MAX, nls_codepage, remap);
3227 name_len++; /* trailing null */
3230 name_len = strnlen(searchName, PATH_MAX);
3231 name_len++; /* trailing null */
3232 strncpy(pSMB->FileName, searchName, name_len);
3234 pSMB->BufferFormat = 0x04;
3235 name_len++; /* account for buffer type byte */
3236 pSMB->hdr.smb_buf_length += (__u16) name_len;
3237 pSMB->ByteCount = cpu_to_le16(name_len);
3239 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3240 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3242 cFYI(1, "Send error in QueryInfo = %d", rc);
3243 } else if (pFinfo) {
3245 __u32 time = le32_to_cpu(pSMBr->last_write_time);
3247 /* decode response */
3248 /* BB FIXME - add time zone adjustment BB */
3249 memset(pFinfo, 0, sizeof(FILE_ALL_INFO));
3252 /* decode time fields */
3253 pFinfo->ChangeTime = cpu_to_le64(cifs_UnixTimeToNT(ts));
3254 pFinfo->LastWriteTime = pFinfo->ChangeTime;
3255 pFinfo->LastAccessTime = 0;
3256 pFinfo->AllocationSize =
3257 cpu_to_le64(le32_to_cpu(pSMBr->size));
3258 pFinfo->EndOfFile = pFinfo->AllocationSize;
3259 pFinfo->Attributes =
3260 cpu_to_le32(le16_to_cpu(pSMBr->attr));
3262 rc = -EIO; /* bad buffer passed in */
3264 cifs_buf_release(pSMB);
3273 CIFSSMBQFileInfo(const int xid, struct cifsTconInfo *tcon,
3274 u16 netfid, FILE_ALL_INFO *pFindData)
3276 struct smb_t2_qfi_req *pSMB = NULL;
3277 struct smb_t2_qfi_rsp *pSMBr = NULL;
3280 __u16 params, byte_count;
3283 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3288 params = 2 /* level */ + 2 /* fid */;
3289 pSMB->t2.TotalDataCount = 0;
3290 pSMB->t2.MaxParameterCount = cpu_to_le16(4);
3291 /* BB find exact max data count below from sess structure BB */
3292 pSMB->t2.MaxDataCount = cpu_to_le16(CIFSMaxBufSize);
3293 pSMB->t2.MaxSetupCount = 0;
3294 pSMB->t2.Reserved = 0;
3296 pSMB->t2.Timeout = 0;
3297 pSMB->t2.Reserved2 = 0;
3298 pSMB->t2.ParameterOffset = cpu_to_le16(offsetof(struct smb_t2_qfi_req,
3300 pSMB->t2.DataCount = 0;
3301 pSMB->t2.DataOffset = 0;
3302 pSMB->t2.SetupCount = 1;
3303 pSMB->t2.Reserved3 = 0;
3304 pSMB->t2.SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION);
3305 byte_count = params + 1 /* pad */ ;
3306 pSMB->t2.TotalParameterCount = cpu_to_le16(params);
3307 pSMB->t2.ParameterCount = pSMB->t2.TotalParameterCount;
3308 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_ALL_INFO);
3311 pSMB->hdr.smb_buf_length += byte_count;
3313 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3314 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3316 cFYI(1, "Send error in QPathInfo = %d", rc);
3317 } else { /* decode response */
3318 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3320 if (rc) /* BB add auto retry on EOPNOTSUPP? */
3322 else if (pSMBr->ByteCount < 40)
3323 rc = -EIO; /* bad smb */
3324 else if (pFindData) {
3325 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3326 memcpy((char *) pFindData,
3327 (char *) &pSMBr->hdr.Protocol +
3328 data_offset, sizeof(FILE_ALL_INFO));
3332 cifs_buf_release(pSMB);
3334 goto QFileInfoRetry;
3340 CIFSSMBQPathInfo(const int xid, struct cifsTconInfo *tcon,
3341 const unsigned char *searchName,
3342 FILE_ALL_INFO *pFindData,
3343 int legacy /* old style infolevel */,
3344 const struct nls_table *nls_codepage, int remap)
3346 /* level 263 SMB_QUERY_FILE_ALL_INFO */
3347 TRANSACTION2_QPI_REQ *pSMB = NULL;
3348 TRANSACTION2_QPI_RSP *pSMBr = NULL;
3352 __u16 params, byte_count;
3354 /* cFYI(1, "In QPathInfo path %s", searchName); */
3356 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3361 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3363 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
3364 PATH_MAX, nls_codepage, remap);
3365 name_len++; /* trailing null */
3367 } else { /* BB improve the check for buffer overruns BB */
3368 name_len = strnlen(searchName, PATH_MAX);
3369 name_len++; /* trailing null */
3370 strncpy(pSMB->FileName, searchName, name_len);
3373 params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */;
3374 pSMB->TotalDataCount = 0;
3375 pSMB->MaxParameterCount = cpu_to_le16(2);
3376 /* BB find exact max SMB PDU from sess structure BB */
3377 pSMB->MaxDataCount = cpu_to_le16(4000);
3378 pSMB->MaxSetupCount = 0;
3382 pSMB->Reserved2 = 0;
3383 pSMB->ParameterOffset = cpu_to_le16(offsetof(
3384 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
3385 pSMB->DataCount = 0;
3386 pSMB->DataOffset = 0;
3387 pSMB->SetupCount = 1;
3388 pSMB->Reserved3 = 0;
3389 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
3390 byte_count = params + 1 /* pad */ ;
3391 pSMB->TotalParameterCount = cpu_to_le16(params);
3392 pSMB->ParameterCount = pSMB->TotalParameterCount;
3394 pSMB->InformationLevel = cpu_to_le16(SMB_INFO_STANDARD);
3396 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_ALL_INFO);
3397 pSMB->Reserved4 = 0;
3398 pSMB->hdr.smb_buf_length += byte_count;
3399 pSMB->ByteCount = cpu_to_le16(byte_count);
3401 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3402 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3404 cFYI(1, "Send error in QPathInfo = %d", rc);
3405 } else { /* decode response */
3406 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3408 if (rc) /* BB add auto retry on EOPNOTSUPP? */
3410 else if (!legacy && (pSMBr->ByteCount < 40))
3411 rc = -EIO; /* bad smb */
3412 else if (legacy && (pSMBr->ByteCount < 24))
3413 rc = -EIO; /* 24 or 26 expected but we do not read
3415 else if (pFindData) {
3417 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3419 /* On legacy responses we do not read the last field,
3420 EAsize, fortunately since it varies by subdialect and
3421 also note it differs on Set vs. Get, ie two bytes or 4
3422 bytes depending but we don't care here */
3424 size = sizeof(FILE_INFO_STANDARD);
3426 size = sizeof(FILE_ALL_INFO);
3427 memcpy((char *) pFindData,
3428 (char *) &pSMBr->hdr.Protocol +
3433 cifs_buf_release(pSMB);
3435 goto QPathInfoRetry;
3441 CIFSSMBUnixQFileInfo(const int xid, struct cifsTconInfo *tcon,
3442 u16 netfid, FILE_UNIX_BASIC_INFO *pFindData)
3444 struct smb_t2_qfi_req *pSMB = NULL;
3445 struct smb_t2_qfi_rsp *pSMBr = NULL;
3448 __u16 params, byte_count;
3451 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3456 params = 2 /* level */ + 2 /* fid */;
3457 pSMB->t2.TotalDataCount = 0;
3458 pSMB->t2.MaxParameterCount = cpu_to_le16(4);
3459 /* BB find exact max data count below from sess structure BB */
3460 pSMB->t2.MaxDataCount = cpu_to_le16(CIFSMaxBufSize);
3461 pSMB->t2.MaxSetupCount = 0;
3462 pSMB->t2.Reserved = 0;
3464 pSMB->t2.Timeout = 0;
3465 pSMB->t2.Reserved2 = 0;
3466 pSMB->t2.ParameterOffset = cpu_to_le16(offsetof(struct smb_t2_qfi_req,
3468 pSMB->t2.DataCount = 0;
3469 pSMB->t2.DataOffset = 0;
3470 pSMB->t2.SetupCount = 1;
3471 pSMB->t2.Reserved3 = 0;
3472 pSMB->t2.SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION);
3473 byte_count = params + 1 /* pad */ ;
3474 pSMB->t2.TotalParameterCount = cpu_to_le16(params);
3475 pSMB->t2.ParameterCount = pSMB->t2.TotalParameterCount;
3476 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC);
3479 pSMB->hdr.smb_buf_length += byte_count;
3481 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3482 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3484 cFYI(1, "Send error in QPathInfo = %d", rc);
3485 } else { /* decode response */
3486 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3488 if (rc || (pSMBr->ByteCount < sizeof(FILE_UNIX_BASIC_INFO))) {
3489 cERROR(1, "Malformed FILE_UNIX_BASIC_INFO response.\n"
3490 "Unix Extensions can be disabled on mount "
3491 "by specifying the nosfu mount option.");
3492 rc = -EIO; /* bad smb */
3494 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3495 memcpy((char *) pFindData,
3496 (char *) &pSMBr->hdr.Protocol +
3498 sizeof(FILE_UNIX_BASIC_INFO));
3502 cifs_buf_release(pSMB);
3504 goto UnixQFileInfoRetry;
3510 CIFSSMBUnixQPathInfo(const int xid, struct cifsTconInfo *tcon,
3511 const unsigned char *searchName,
3512 FILE_UNIX_BASIC_INFO *pFindData,
3513 const struct nls_table *nls_codepage, int remap)
3515 /* SMB_QUERY_FILE_UNIX_BASIC */
3516 TRANSACTION2_QPI_REQ *pSMB = NULL;
3517 TRANSACTION2_QPI_RSP *pSMBr = NULL;
3519 int bytes_returned = 0;
3521 __u16 params, byte_count;
3523 cFYI(1, "In QPathInfo (Unix) the path %s", searchName);
3525 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3530 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3532 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
3533 PATH_MAX, nls_codepage, remap);
3534 name_len++; /* trailing null */
3536 } else { /* BB improve the check for buffer overruns BB */
3537 name_len = strnlen(searchName, PATH_MAX);
3538 name_len++; /* trailing null */
3539 strncpy(pSMB->FileName, searchName, name_len);
3542 params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */;
3543 pSMB->TotalDataCount = 0;
3544 pSMB->MaxParameterCount = cpu_to_le16(2);
3545 /* BB find exact max SMB PDU from sess structure BB */
3546 pSMB->MaxDataCount = cpu_to_le16(4000);
3547 pSMB->MaxSetupCount = 0;
3551 pSMB->Reserved2 = 0;
3552 pSMB->ParameterOffset = cpu_to_le16(offsetof(
3553 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
3554 pSMB->DataCount = 0;
3555 pSMB->DataOffset = 0;
3556 pSMB->SetupCount = 1;
3557 pSMB->Reserved3 = 0;
3558 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
3559 byte_count = params + 1 /* pad */ ;
3560 pSMB->TotalParameterCount = cpu_to_le16(params);
3561 pSMB->ParameterCount = pSMB->TotalParameterCount;
3562 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC);
3563 pSMB->Reserved4 = 0;
3564 pSMB->hdr.smb_buf_length += byte_count;
3565 pSMB->ByteCount = cpu_to_le16(byte_count);
3567 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3568 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3570 cFYI(1, "Send error in QPathInfo = %d", rc);
3571 } else { /* decode response */
3572 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3574 if (rc || (pSMBr->ByteCount < sizeof(FILE_UNIX_BASIC_INFO))) {
3575 cERROR(1, "Malformed FILE_UNIX_BASIC_INFO response.\n"
3576 "Unix Extensions can be disabled on mount "
3577 "by specifying the nosfu mount option.");
3578 rc = -EIO; /* bad smb */
3580 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3581 memcpy((char *) pFindData,
3582 (char *) &pSMBr->hdr.Protocol +
3584 sizeof(FILE_UNIX_BASIC_INFO));
3587 cifs_buf_release(pSMB);
3589 goto UnixQPathInfoRetry;
3594 /* xid, tcon, searchName and codepage are input parms, rest are returned */
3596 CIFSFindFirst(const int xid, struct cifsTconInfo *tcon,
3597 const char *searchName,
3598 const struct nls_table *nls_codepage,
3600 struct cifs_search_info *psrch_inf, int remap, const char dirsep)
3602 /* level 257 SMB_ */
3603 TRANSACTION2_FFIRST_REQ *pSMB = NULL;
3604 TRANSACTION2_FFIRST_RSP *pSMBr = NULL;
3605 T2_FFIRST_RSP_PARMS *parms;
3607 int bytes_returned = 0;
3609 __u16 params, byte_count;
3611 cFYI(1, "In FindFirst for %s", searchName);
3614 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3619 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3621 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
3622 PATH_MAX, nls_codepage, remap);
3623 /* We can not add the asterik earlier in case
3624 it got remapped to 0xF03A as if it were part of the
3625 directory name instead of a wildcard */
3627 pSMB->FileName[name_len] = dirsep;
3628 pSMB->FileName[name_len+1] = 0;
3629 pSMB->FileName[name_len+2] = '*';
3630 pSMB->FileName[name_len+3] = 0;
3631 name_len += 4; /* now the trailing null */
3632 pSMB->FileName[name_len] = 0; /* null terminate just in case */
3633 pSMB->FileName[name_len+1] = 0;
3635 } else { /* BB add check for overrun of SMB buf BB */
3636 name_len = strnlen(searchName, PATH_MAX);
3637 /* BB fix here and in unicode clause above ie
3638 if (name_len > buffersize-header)
3639 free buffer exit; BB */
3640 strncpy(pSMB->FileName, searchName, name_len);
3641 pSMB->FileName[name_len] = dirsep;
3642 pSMB->FileName[name_len+1] = '*';
3643 pSMB->FileName[name_len+2] = 0;
3647 params = 12 + name_len /* includes null */ ;
3648 pSMB->TotalDataCount = 0; /* no EAs */
3649 pSMB->MaxParameterCount = cpu_to_le16(10);
3650 pSMB->MaxDataCount = cpu_to_le16((tcon->ses->server->maxBuf -
3651 MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
3652 pSMB->MaxSetupCount = 0;
3656 pSMB->Reserved2 = 0;
3657 byte_count = params + 1 /* pad */ ;
3658 pSMB->TotalParameterCount = cpu_to_le16(params);
3659 pSMB->ParameterCount = pSMB->TotalParameterCount;
3660 pSMB->ParameterOffset = cpu_to_le16(
3661 offsetof(struct smb_com_transaction2_ffirst_req, SearchAttributes)
3663 pSMB->DataCount = 0;
3664 pSMB->DataOffset = 0;
3665 pSMB->SetupCount = 1; /* one byte, no need to make endian neutral */
3666 pSMB->Reserved3 = 0;
3667 pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_FIRST);
3668 pSMB->SearchAttributes =
3669 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
3671 pSMB->SearchCount = cpu_to_le16(CIFSMaxBufSize/sizeof(FILE_UNIX_INFO));
3672 pSMB->SearchFlags = cpu_to_le16(CIFS_SEARCH_CLOSE_AT_END |
3673 CIFS_SEARCH_RETURN_RESUME);
3674 pSMB->InformationLevel = cpu_to_le16(psrch_inf->info_level);
3676 /* BB what should we set StorageType to? Does it matter? BB */
3677 pSMB->SearchStorageType = 0;
3678 pSMB->hdr.smb_buf_length += byte_count;
3679 pSMB->ByteCount = cpu_to_le16(byte_count);
3681 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3682 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3683 cifs_stats_inc(&tcon->num_ffirst);
3685 if (rc) {/* BB add logic to retry regular search if Unix search
3686 rejected unexpectedly by server */
3687 /* BB Add code to handle unsupported level rc */
3688 cFYI(1, "Error in FindFirst = %d", rc);
3690 cifs_buf_release(pSMB);
3692 /* BB eventually could optimize out free and realloc of buf */
3695 goto findFirstRetry;
3696 } else { /* decode response */
3697 /* BB remember to free buffer if error BB */
3698 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3702 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
3703 psrch_inf->unicode = true;
3705 psrch_inf->unicode = false;
3707 psrch_inf->ntwrk_buf_start = (char *)pSMBr;
3708 psrch_inf->smallBuf = 0;
3709 psrch_inf->srch_entries_start =
3710 (char *) &pSMBr->hdr.Protocol +
3711 le16_to_cpu(pSMBr->t2.DataOffset);
3712 parms = (T2_FFIRST_RSP_PARMS *)((char *) &pSMBr->hdr.Protocol +
3713 le16_to_cpu(pSMBr->t2.ParameterOffset));
3715 if (parms->EndofSearch)
3716 psrch_inf->endOfSearch = true;
3718 psrch_inf->endOfSearch = false;
3720 psrch_inf->entries_in_buffer =
3721 le16_to_cpu(parms->SearchCount);
3722 psrch_inf->index_of_last_entry = 2 /* skip . and .. */ +
3723 psrch_inf->entries_in_buffer;
3724 lnoff = le16_to_cpu(parms->LastNameOffset);
3725 if (tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE <
3727 cERROR(1, "ignoring corrupt resume name");
3728 psrch_inf->last_entry = NULL;
3732 psrch_inf->last_entry = psrch_inf->srch_entries_start +
3735 *pnetfid = parms->SearchHandle;
3737 cifs_buf_release(pSMB);
3744 int CIFSFindNext(const int xid, struct cifsTconInfo *tcon,
3745 __u16 searchHandle, struct cifs_search_info *psrch_inf)
3747 TRANSACTION2_FNEXT_REQ *pSMB = NULL;
3748 TRANSACTION2_FNEXT_RSP *pSMBr = NULL;
3749 T2_FNEXT_RSP_PARMS *parms;
3750 char *response_data;
3752 int bytes_returned, name_len;
3753 __u16 params, byte_count;
3755 cFYI(1, "In FindNext");
3757 if (psrch_inf->endOfSearch)
3760 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3765 params = 14; /* includes 2 bytes of null string, converted to LE below*/
3767 pSMB->TotalDataCount = 0; /* no EAs */
3768 pSMB->MaxParameterCount = cpu_to_le16(8);
3769 pSMB->MaxDataCount =
3770 cpu_to_le16((tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE) &
3772 pSMB->MaxSetupCount = 0;
3776 pSMB->Reserved2 = 0;
3777 pSMB->ParameterOffset = cpu_to_le16(
3778 offsetof(struct smb_com_transaction2_fnext_req,SearchHandle) - 4);
3779 pSMB->DataCount = 0;
3780 pSMB->DataOffset = 0;
3781 pSMB->SetupCount = 1;
3782 pSMB->Reserved3 = 0;
3783 pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_NEXT);
3784 pSMB->SearchHandle = searchHandle; /* always kept as le */
3786 cpu_to_le16(CIFSMaxBufSize / sizeof(FILE_UNIX_INFO));
3787 pSMB->InformationLevel = cpu_to_le16(psrch_inf->info_level);
3788 pSMB->ResumeKey = psrch_inf->resume_key;
3790 cpu_to_le16(CIFS_SEARCH_CLOSE_AT_END | CIFS_SEARCH_RETURN_RESUME);
3792 name_len = psrch_inf->resume_name_len;
3794 if (name_len < PATH_MAX) {
3795 memcpy(pSMB->ResumeFileName, psrch_inf->presume_name, name_len);
3796 byte_count += name_len;
3797 /* 14 byte parm len above enough for 2 byte null terminator */
3798 pSMB->ResumeFileName[name_len] = 0;
3799 pSMB->ResumeFileName[name_len+1] = 0;
3802 goto FNext2_err_exit;
3804 byte_count = params + 1 /* pad */ ;
3805 pSMB->TotalParameterCount = cpu_to_le16(params);
3806 pSMB->ParameterCount = pSMB->TotalParameterCount;
3807 pSMB->hdr.smb_buf_length += byte_count;
3808 pSMB->ByteCount = cpu_to_le16(byte_count);
3810 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3811 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3812 cifs_stats_inc(&tcon->num_fnext);
3815 psrch_inf->endOfSearch = true;
3816 cifs_buf_release(pSMB);
3817 rc = 0; /* search probably was closed at end of search*/
3819 cFYI(1, "FindNext returned = %d", rc);
3820 } else { /* decode response */
3821 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3826 /* BB fixme add lock for file (srch_info) struct here */
3827 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
3828 psrch_inf->unicode = true;
3830 psrch_inf->unicode = false;
3831 response_data = (char *) &pSMBr->hdr.Protocol +
3832 le16_to_cpu(pSMBr->t2.ParameterOffset);
3833 parms = (T2_FNEXT_RSP_PARMS *)response_data;
3834 response_data = (char *)&pSMBr->hdr.Protocol +
3835 le16_to_cpu(pSMBr->t2.DataOffset);
3836 if (psrch_inf->smallBuf)
3837 cifs_small_buf_release(
3838 psrch_inf->ntwrk_buf_start);
3840 cifs_buf_release(psrch_inf->ntwrk_buf_start);
3841 psrch_inf->srch_entries_start = response_data;
3842 psrch_inf->ntwrk_buf_start = (char *)pSMB;
3843 psrch_inf->smallBuf = 0;
3844 if (parms->EndofSearch)
3845 psrch_inf->endOfSearch = true;
3847 psrch_inf->endOfSearch = false;
3848 psrch_inf->entries_in_buffer =
3849 le16_to_cpu(parms->SearchCount);
3850 psrch_inf->index_of_last_entry +=
3851 psrch_inf->entries_in_buffer;
3852 lnoff = le16_to_cpu(parms->LastNameOffset);
3853 if (tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE <
3855 cERROR(1, "ignoring corrupt resume name");
3856 psrch_inf->last_entry = NULL;
3859 psrch_inf->last_entry =
3860 psrch_inf->srch_entries_start + lnoff;
3862 /* cFYI(1, "fnxt2 entries in buf %d index_of_last %d",
3863 psrch_inf->entries_in_buffer, psrch_inf->index_of_last_entry); */
3865 /* BB fixme add unlock here */
3870 /* BB On error, should we leave previous search buf (and count and
3871 last entry fields) intact or free the previous one? */
3873 /* Note: On -EAGAIN error only caller can retry on handle based calls
3874 since file handle passed in no longer valid */
3877 cifs_buf_release(pSMB);
3882 CIFSFindClose(const int xid, struct cifsTconInfo *tcon,
3883 const __u16 searchHandle)
3886 FINDCLOSE_REQ *pSMB = NULL;
3888 cFYI(1, "In CIFSSMBFindClose");
3889 rc = small_smb_init(SMB_COM_FIND_CLOSE2, 1, tcon, (void **)&pSMB);
3891 /* no sense returning error if session restarted
3892 as file handle has been closed */
3898 pSMB->FileID = searchHandle;
3899 pSMB->ByteCount = 0;
3900 rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0);
3902 cERROR(1, "Send error in FindClose = %d", rc);
3904 cifs_stats_inc(&tcon->num_fclose);
3906 /* Since session is dead, search handle closed on server already */
3914 CIFSGetSrvInodeNumber(const int xid, struct cifsTconInfo *tcon,
3915 const unsigned char *searchName,
3916 __u64 *inode_number,
3917 const struct nls_table *nls_codepage, int remap)
3920 TRANSACTION2_QPI_REQ *pSMB = NULL;
3921 TRANSACTION2_QPI_RSP *pSMBr = NULL;
3922 int name_len, bytes_returned;
3923 __u16 params, byte_count;
3925 cFYI(1, "In GetSrvInodeNum for %s", searchName);
3929 GetInodeNumberRetry:
3930 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3935 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3937 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
3938 PATH_MAX, nls_codepage, remap);
3939 name_len++; /* trailing null */
3941 } else { /* BB improve the check for buffer overruns BB */
3942 name_len = strnlen(searchName, PATH_MAX);
3943 name_len++; /* trailing null */
3944 strncpy(pSMB->FileName, searchName, name_len);
3947 params = 2 /* level */ + 4 /* rsrvd */ + name_len /* incl null */ ;
3948 pSMB->TotalDataCount = 0;
3949 pSMB->MaxParameterCount = cpu_to_le16(2);
3950 /* BB find exact max data count below from sess structure BB */
3951 pSMB->MaxDataCount = cpu_to_le16(4000);
3952 pSMB->MaxSetupCount = 0;
3956 pSMB->Reserved2 = 0;
3957 pSMB->ParameterOffset = cpu_to_le16(offsetof(
3958 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
3959 pSMB->DataCount = 0;
3960 pSMB->DataOffset = 0;
3961 pSMB->SetupCount = 1;
3962 pSMB->Reserved3 = 0;
3963 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
3964 byte_count = params + 1 /* pad */ ;
3965 pSMB->TotalParameterCount = cpu_to_le16(params);
3966 pSMB->ParameterCount = pSMB->TotalParameterCount;
3967 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_INTERNAL_INFO);
3968 pSMB->Reserved4 = 0;
3969 pSMB->hdr.smb_buf_length += byte_count;
3970 pSMB->ByteCount = cpu_to_le16(byte_count);
3972 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3973 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3975 cFYI(1, "error %d in QueryInternalInfo", rc);
3977 /* decode response */
3978 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3979 if (rc || (pSMBr->ByteCount < 2))
3980 /* BB also check enough total bytes returned */
3981 /* If rc should we check for EOPNOSUPP and
3982 disable the srvino flag? or in caller? */
3983 rc = -EIO; /* bad smb */
3985 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3986 __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
3987 struct file_internal_info *pfinfo;
3988 /* BB Do we need a cast or hash here ? */
3990 cFYI(1, "Illegal size ret in QryIntrnlInf");
3992 goto GetInodeNumOut;
3994 pfinfo = (struct file_internal_info *)
3995 (data_offset + (char *) &pSMBr->hdr.Protocol);
3996 *inode_number = le64_to_cpu(pfinfo->UniqueId);
4000 cifs_buf_release(pSMB);
4002 goto GetInodeNumberRetry;
4006 /* parses DFS refferal V3 structure
4007 * caller is responsible for freeing target_nodes
4010 * on failure - errno
4013 parse_DFS_referrals(TRANSACTION2_GET_DFS_REFER_RSP *pSMBr,
4014 unsigned int *num_of_nodes,
4015 struct dfs_info3_param **target_nodes,
4016 const struct nls_table *nls_codepage, int remap,
4017 const char *searchName)
4022 struct dfs_referral_level_3 *ref;
4024 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
4028 *num_of_nodes = le16_to_cpu(pSMBr->NumberOfReferrals);
4030 if (*num_of_nodes < 1) {
4031 cERROR(1, "num_referrals: must be at least > 0,"
4032 "but we get num_referrals = %d\n", *num_of_nodes);
4034 goto parse_DFS_referrals_exit;
4037 ref = (struct dfs_referral_level_3 *) &(pSMBr->referrals);
4038 if (ref->VersionNumber != cpu_to_le16(3)) {
4039 cERROR(1, "Referrals of V%d version are not supported,"
4040 "should be V3", le16_to_cpu(ref->VersionNumber));
4042 goto parse_DFS_referrals_exit;
4045 /* get the upper boundary of the resp buffer */
4046 data_end = (char *)(&(pSMBr->PathConsumed)) +
4047 le16_to_cpu(pSMBr->t2.DataCount);
4049 cFYI(1, "num_referrals: %d dfs flags: 0x%x ...\n",
4051 le32_to_cpu(pSMBr->DFSFlags));
4053 *target_nodes = kzalloc(sizeof(struct dfs_info3_param) *
4054 *num_of_nodes, GFP_KERNEL);
4055 if (*target_nodes == NULL) {
4056 cERROR(1, "Failed to allocate buffer for target_nodes\n");
4058 goto parse_DFS_referrals_exit;
4061 /* collect necessary data from referrals */
4062 for (i = 0; i < *num_of_nodes; i++) {
4065 struct dfs_info3_param *node = (*target_nodes)+i;
4067 node->flags = le32_to_cpu(pSMBr->DFSFlags);
4069 __le16 *tmp = kmalloc(strlen(searchName)*2 + 2,
4073 goto parse_DFS_referrals_exit;
4075 cifsConvertToUCS((__le16 *) tmp, searchName,
4076 PATH_MAX, nls_codepage, remap);
4077 node->path_consumed = cifs_ucs2_bytes(tmp,
4078 le16_to_cpu(pSMBr->PathConsumed),
4082 node->path_consumed = le16_to_cpu(pSMBr->PathConsumed);
4084 node->server_type = le16_to_cpu(ref->ServerType);
4085 node->ref_flag = le16_to_cpu(ref->ReferralEntryFlags);
4088 temp = (char *)ref + le16_to_cpu(ref->DfsPathOffset);
4089 max_len = data_end - temp;
4090 node->path_name = cifs_strndup_from_ucs(temp, max_len,
4091 is_unicode, nls_codepage);
4092 if (!node->path_name) {
4094 goto parse_DFS_referrals_exit;
4097 /* copy link target UNC */
4098 temp = (char *)ref + le16_to_cpu(ref->NetworkAddressOffset);
4099 max_len = data_end - temp;
4100 node->node_name = cifs_strndup_from_ucs(temp, max_len,
4101 is_unicode, nls_codepage);
4102 if (!node->node_name)
4106 parse_DFS_referrals_exit:
4108 free_dfs_info_array(*target_nodes, *num_of_nodes);
4109 *target_nodes = NULL;
4116 CIFSGetDFSRefer(const int xid, struct cifsSesInfo *ses,
4117 const unsigned char *searchName,
4118 struct dfs_info3_param **target_nodes,
4119 unsigned int *num_of_nodes,
4120 const struct nls_table *nls_codepage, int remap)
4122 /* TRANS2_GET_DFS_REFERRAL */
4123 TRANSACTION2_GET_DFS_REFER_REQ *pSMB = NULL;
4124 TRANSACTION2_GET_DFS_REFER_RSP *pSMBr = NULL;
4128 __u16 params, byte_count;
4130 *target_nodes = NULL;
4132 cFYI(1, "In GetDFSRefer the path %s", searchName);
4136 rc = smb_init(SMB_COM_TRANSACTION2, 15, NULL, (void **) &pSMB,
4141 /* server pointer checked in called function,
4142 but should never be null here anyway */
4143 pSMB->hdr.Mid = GetNextMid(ses->server);
4144 pSMB->hdr.Tid = ses->ipc_tid;
4145 pSMB->hdr.Uid = ses->Suid;
4146 if (ses->capabilities & CAP_STATUS32)
4147 pSMB->hdr.Flags2 |= SMBFLG2_ERR_STATUS;
4148 if (ses->capabilities & CAP_DFS)
4149 pSMB->hdr.Flags2 |= SMBFLG2_DFS;
4151 if (ses->capabilities & CAP_UNICODE) {
4152 pSMB->hdr.Flags2 |= SMBFLG2_UNICODE;
4154 cifsConvertToUCS((__le16 *) pSMB->RequestFileName,
4155 searchName, PATH_MAX, nls_codepage, remap);
4156 name_len++; /* trailing null */
4158 } else { /* BB improve the check for buffer overruns BB */
4159 name_len = strnlen(searchName, PATH_MAX);
4160 name_len++; /* trailing null */
4161 strncpy(pSMB->RequestFileName, searchName, name_len);
4165 if (ses->server->secMode &
4166 (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
4167 pSMB->hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
4170 pSMB->hdr.Uid = ses->Suid;
4172 params = 2 /* level */ + name_len /*includes null */ ;
4173 pSMB->TotalDataCount = 0;
4174 pSMB->DataCount = 0;
4175 pSMB->DataOffset = 0;
4176 pSMB->MaxParameterCount = 0;
4177 /* BB find exact max SMB PDU from sess structure BB */
4178 pSMB->MaxDataCount = cpu_to_le16(4000);
4179 pSMB->MaxSetupCount = 0;
4183 pSMB->Reserved2 = 0;
4184 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4185 struct smb_com_transaction2_get_dfs_refer_req, MaxReferralLevel) - 4);
4186 pSMB->SetupCount = 1;
4187 pSMB->Reserved3 = 0;
4188 pSMB->SubCommand = cpu_to_le16(TRANS2_GET_DFS_REFERRAL);
4189 byte_count = params + 3 /* pad */ ;
4190 pSMB->ParameterCount = cpu_to_le16(params);
4191 pSMB->TotalParameterCount = pSMB->ParameterCount;
4192 pSMB->MaxReferralLevel = cpu_to_le16(3);
4193 pSMB->hdr.smb_buf_length += byte_count;
4194 pSMB->ByteCount = cpu_to_le16(byte_count);
4196 rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB,
4197 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4199 cFYI(1, "Send error in GetDFSRefer = %d", rc);
4202 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4204 /* BB Also check if enough total bytes returned? */
4205 if (rc || (pSMBr->ByteCount < 17)) {
4206 rc = -EIO; /* bad smb */
4210 cFYI(1, "Decoding GetDFSRefer response BCC: %d Offset %d",
4212 le16_to_cpu(pSMBr->t2.DataOffset));
4214 /* parse returned result into more usable form */
4215 rc = parse_DFS_referrals(pSMBr, num_of_nodes,
4216 target_nodes, nls_codepage, remap,
4220 cifs_buf_release(pSMB);
4228 /* Query File System Info such as free space to old servers such as Win 9x */
4230 SMBOldQFSInfo(const int xid, struct cifsTconInfo *tcon, struct kstatfs *FSData)
4232 /* level 0x01 SMB_QUERY_FILE_SYSTEM_INFO */
4233 TRANSACTION2_QFSI_REQ *pSMB = NULL;
4234 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4235 FILE_SYSTEM_ALLOC_INFO *response_data;
4237 int bytes_returned = 0;
4238 __u16 params, byte_count;
4240 cFYI(1, "OldQFSInfo");
4242 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4247 params = 2; /* level */
4248 pSMB->TotalDataCount = 0;
4249 pSMB->MaxParameterCount = cpu_to_le16(2);
4250 pSMB->MaxDataCount = cpu_to_le16(1000);
4251 pSMB->MaxSetupCount = 0;
4255 pSMB->Reserved2 = 0;
4256 byte_count = params + 1 /* pad */ ;
4257 pSMB->TotalParameterCount = cpu_to_le16(params);
4258 pSMB->ParameterCount = pSMB->TotalParameterCount;
4259 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4260 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4261 pSMB->DataCount = 0;
4262 pSMB->DataOffset = 0;
4263 pSMB->SetupCount = 1;
4264 pSMB->Reserved3 = 0;
4265 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4266 pSMB->InformationLevel = cpu_to_le16(SMB_INFO_ALLOCATION);
4267 pSMB->hdr.smb_buf_length += byte_count;
4268 pSMB->ByteCount = cpu_to_le16(byte_count);
4270 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4271 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4273 cFYI(1, "Send error in QFSInfo = %d", rc);
4274 } else { /* decode response */
4275 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4277 if (rc || (pSMBr->ByteCount < 18))
4278 rc = -EIO; /* bad smb */
4280 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4281 cFYI(1, "qfsinf resp BCC: %d Offset %d",
4282 pSMBr->ByteCount, data_offset);
4284 response_data = (FILE_SYSTEM_ALLOC_INFO *)
4285 (((char *) &pSMBr->hdr.Protocol) + data_offset);
4287 le16_to_cpu(response_data->BytesPerSector) *
4288 le32_to_cpu(response_data->
4289 SectorsPerAllocationUnit);
4291 le32_to_cpu(response_data->TotalAllocationUnits);
4292 FSData->f_bfree = FSData->f_bavail =
4293 le32_to_cpu(response_data->FreeAllocationUnits);
4294 cFYI(1, "Blocks: %lld Free: %lld Block size %ld",
4295 (unsigned long long)FSData->f_blocks,
4296 (unsigned long long)FSData->f_bfree,
4300 cifs_buf_release(pSMB);
4303 goto oldQFSInfoRetry;
4309 CIFSSMBQFSInfo(const int xid, struct cifsTconInfo *tcon, struct kstatfs *FSData)
4311 /* level 0x103 SMB_QUERY_FILE_SYSTEM_INFO */
4312 TRANSACTION2_QFSI_REQ *pSMB = NULL;
4313 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4314 FILE_SYSTEM_INFO *response_data;
4316 int bytes_returned = 0;
4317 __u16 params, byte_count;
4319 cFYI(1, "In QFSInfo");
4321 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4326 params = 2; /* level */
4327 pSMB->TotalDataCount = 0;
4328 pSMB->MaxParameterCount = cpu_to_le16(2);
4329 pSMB->MaxDataCount = cpu_to_le16(1000);
4330 pSMB->MaxSetupCount = 0;
4334 pSMB->Reserved2 = 0;
4335 byte_count = params + 1 /* pad */ ;
4336 pSMB->TotalParameterCount = cpu_to_le16(params);
4337 pSMB->ParameterCount = pSMB->TotalParameterCount;
4338 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4339 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4340 pSMB->DataCount = 0;
4341 pSMB->DataOffset = 0;
4342 pSMB->SetupCount = 1;
4343 pSMB->Reserved3 = 0;
4344 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4345 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_SIZE_INFO);
4346 pSMB->hdr.smb_buf_length += byte_count;
4347 pSMB->ByteCount = cpu_to_le16(byte_count);
4349 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4350 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4352 cFYI(1, "Send error in QFSInfo = %d", rc);
4353 } else { /* decode response */
4354 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4356 if (rc || (pSMBr->ByteCount < 24))
4357 rc = -EIO; /* bad smb */
4359 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4363 *) (((char *) &pSMBr->hdr.Protocol) +
4366 le32_to_cpu(response_data->BytesPerSector) *
4367 le32_to_cpu(response_data->
4368 SectorsPerAllocationUnit);
4370 le64_to_cpu(response_data->TotalAllocationUnits);
4371 FSData->f_bfree = FSData->f_bavail =
4372 le64_to_cpu(response_data->FreeAllocationUnits);
4373 cFYI(1, "Blocks: %lld Free: %lld Block size %ld",
4374 (unsigned long long)FSData->f_blocks,
4375 (unsigned long long)FSData->f_bfree,
4379 cifs_buf_release(pSMB);
4388 CIFSSMBQFSAttributeInfo(const int xid, struct cifsTconInfo *tcon)
4390 /* level 0x105 SMB_QUERY_FILE_SYSTEM_INFO */
4391 TRANSACTION2_QFSI_REQ *pSMB = NULL;
4392 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4393 FILE_SYSTEM_ATTRIBUTE_INFO *response_data;
4395 int bytes_returned = 0;
4396 __u16 params, byte_count;
4398 cFYI(1, "In QFSAttributeInfo");
4400 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4405 params = 2; /* level */
4406 pSMB->TotalDataCount = 0;
4407 pSMB->MaxParameterCount = cpu_to_le16(2);
4408 /* BB find exact max SMB PDU from sess structure BB */
4409 pSMB->MaxDataCount = cpu_to_le16(1000);
4410 pSMB->MaxSetupCount = 0;
4414 pSMB->Reserved2 = 0;
4415 byte_count = params + 1 /* pad */ ;
4416 pSMB->TotalParameterCount = cpu_to_le16(params);
4417 pSMB->ParameterCount = pSMB->TotalParameterCount;
4418 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4419 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4420 pSMB->DataCount = 0;
4421 pSMB->DataOffset = 0;
4422 pSMB->SetupCount = 1;
4423 pSMB->Reserved3 = 0;
4424 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4425 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_ATTRIBUTE_INFO);
4426 pSMB->hdr.smb_buf_length += byte_count;
4427 pSMB->ByteCount = cpu_to_le16(byte_count);
4429 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4430 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4432 cERROR(1, "Send error in QFSAttributeInfo = %d", rc);
4433 } else { /* decode response */
4434 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4436 if (rc || (pSMBr->ByteCount < 13)) {
4437 /* BB also check if enough bytes returned */
4438 rc = -EIO; /* bad smb */
4440 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4442 (FILE_SYSTEM_ATTRIBUTE_INFO
4443 *) (((char *) &pSMBr->hdr.Protocol) +
4445 memcpy(&tcon->fsAttrInfo, response_data,
4446 sizeof(FILE_SYSTEM_ATTRIBUTE_INFO));
4449 cifs_buf_release(pSMB);
4452 goto QFSAttributeRetry;
4458 CIFSSMBQFSDeviceInfo(const int xid, struct cifsTconInfo *tcon)
4460 /* level 0x104 SMB_QUERY_FILE_SYSTEM_INFO */
4461 TRANSACTION2_QFSI_REQ *pSMB = NULL;
4462 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4463 FILE_SYSTEM_DEVICE_INFO *response_data;
4465 int bytes_returned = 0;
4466 __u16 params, byte_count;
4468 cFYI(1, "In QFSDeviceInfo");
4470 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4475 params = 2; /* level */
4476 pSMB->TotalDataCount = 0;
4477 pSMB->MaxParameterCount = cpu_to_le16(2);
4478 /* BB find exact max SMB PDU from sess structure BB */
4479 pSMB->MaxDataCount = cpu_to_le16(1000);
4480 pSMB->MaxSetupCount = 0;
4484 pSMB->Reserved2 = 0;
4485 byte_count = params + 1 /* pad */ ;
4486 pSMB->TotalParameterCount = cpu_to_le16(params);
4487 pSMB->ParameterCount = pSMB->TotalParameterCount;
4488 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4489 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4491 pSMB->DataCount = 0;
4492 pSMB->DataOffset = 0;
4493 pSMB->SetupCount = 1;
4494 pSMB->Reserved3 = 0;
4495 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4496 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_DEVICE_INFO);
4497 pSMB->hdr.smb_buf_length += byte_count;
4498 pSMB->ByteCount = cpu_to_le16(byte_count);
4500 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4501 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4503 cFYI(1, "Send error in QFSDeviceInfo = %d", rc);
4504 } else { /* decode response */
4505 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4507 if (rc || (pSMBr->ByteCount < sizeof(FILE_SYSTEM_DEVICE_INFO)))
4508 rc = -EIO; /* bad smb */
4510 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4512 (FILE_SYSTEM_DEVICE_INFO *)
4513 (((char *) &pSMBr->hdr.Protocol) +
4515 memcpy(&tcon->fsDevInfo, response_data,
4516 sizeof(FILE_SYSTEM_DEVICE_INFO));
4519 cifs_buf_release(pSMB);
4522 goto QFSDeviceRetry;
4528 CIFSSMBQFSUnixInfo(const int xid, struct cifsTconInfo *tcon)
4530 /* level 0x200 SMB_QUERY_CIFS_UNIX_INFO */
4531 TRANSACTION2_QFSI_REQ *pSMB = NULL;
4532 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4533 FILE_SYSTEM_UNIX_INFO *response_data;
4535 int bytes_returned = 0;
4536 __u16 params, byte_count;
4538 cFYI(1, "In QFSUnixInfo");
4540 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4545 params = 2; /* level */
4546 pSMB->TotalDataCount = 0;
4547 pSMB->DataCount = 0;
4548 pSMB->DataOffset = 0;
4549 pSMB->MaxParameterCount = cpu_to_le16(2);
4550 /* BB find exact max SMB PDU from sess structure BB */
4551 pSMB->MaxDataCount = cpu_to_le16(100);
4552 pSMB->MaxSetupCount = 0;
4556 pSMB->Reserved2 = 0;
4557 byte_count = params + 1 /* pad */ ;
4558 pSMB->ParameterCount = cpu_to_le16(params);
4559 pSMB->TotalParameterCount = pSMB->ParameterCount;
4560 pSMB->ParameterOffset = cpu_to_le16(offsetof(struct
4561 smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4562 pSMB->SetupCount = 1;
4563 pSMB->Reserved3 = 0;
4564 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4565 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_CIFS_UNIX_INFO);
4566 pSMB->hdr.smb_buf_length += byte_count;
4567 pSMB->ByteCount = cpu_to_le16(byte_count);
4569 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4570 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4572 cERROR(1, "Send error in QFSUnixInfo = %d", rc);
4573 } else { /* decode response */
4574 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4576 if (rc || (pSMBr->ByteCount < 13)) {
4577 rc = -EIO; /* bad smb */
4579 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4581 (FILE_SYSTEM_UNIX_INFO
4582 *) (((char *) &pSMBr->hdr.Protocol) +
4584 memcpy(&tcon->fsUnixInfo, response_data,
4585 sizeof(FILE_SYSTEM_UNIX_INFO));
4588 cifs_buf_release(pSMB);
4598 CIFSSMBSetFSUnixInfo(const int xid, struct cifsTconInfo *tcon, __u64 cap)
4600 /* level 0x200 SMB_SET_CIFS_UNIX_INFO */
4601 TRANSACTION2_SETFSI_REQ *pSMB = NULL;
4602 TRANSACTION2_SETFSI_RSP *pSMBr = NULL;
4604 int bytes_returned = 0;
4605 __u16 params, param_offset, offset, byte_count;
4607 cFYI(1, "In SETFSUnixInfo");
4609 /* BB switch to small buf init to save memory */
4610 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4615 params = 4; /* 2 bytes zero followed by info level. */
4616 pSMB->MaxSetupCount = 0;
4620 pSMB->Reserved2 = 0;
4621 param_offset = offsetof(struct smb_com_transaction2_setfsi_req, FileNum)
4623 offset = param_offset + params;
4625 pSMB->MaxParameterCount = cpu_to_le16(4);
4626 /* BB find exact max SMB PDU from sess structure BB */
4627 pSMB->MaxDataCount = cpu_to_le16(100);
4628 pSMB->SetupCount = 1;
4629 pSMB->Reserved3 = 0;
4630 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FS_INFORMATION);
4631 byte_count = 1 /* pad */ + params + 12;
4633 pSMB->DataCount = cpu_to_le16(12);
4634 pSMB->ParameterCount = cpu_to_le16(params);
4635 pSMB->TotalDataCount = pSMB->DataCount;
4636 pSMB->TotalParameterCount = pSMB->ParameterCount;
4637 pSMB->ParameterOffset = cpu_to_le16(param_offset);
4638 pSMB->DataOffset = cpu_to_le16(offset);
4642 pSMB->InformationLevel = cpu_to_le16(SMB_SET_CIFS_UNIX_INFO);
4645 pSMB->ClientUnixMajor = cpu_to_le16(CIFS_UNIX_MAJOR_VERSION);
4646 pSMB->ClientUnixMinor = cpu_to_le16(CIFS_UNIX_MINOR_VERSION);
4647 pSMB->ClientUnixCap = cpu_to_le64(cap);
4649 pSMB->hdr.smb_buf_length += byte_count;
4650 pSMB->ByteCount = cpu_to_le16(byte_count);
4652 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4653 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4655 cERROR(1, "Send error in SETFSUnixInfo = %d", rc);
4656 } else { /* decode response */
4657 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4659 rc = -EIO; /* bad smb */
4661 cifs_buf_release(pSMB);
4664 goto SETFSUnixRetry;
4672 CIFSSMBQFSPosixInfo(const int xid, struct cifsTconInfo *tcon,
4673 struct kstatfs *FSData)
4675 /* level 0x201 SMB_QUERY_CIFS_POSIX_INFO */
4676 TRANSACTION2_QFSI_REQ *pSMB = NULL;
4677 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4678 FILE_SYSTEM_POSIX_INFO *response_data;
4680 int bytes_returned = 0;
4681 __u16 params, byte_count;
4683 cFYI(1, "In QFSPosixInfo");
4685 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4690 params = 2; /* level */
4691 pSMB->TotalDataCount = 0;
4692 pSMB->DataCount = 0;
4693 pSMB->DataOffset = 0;
4694 pSMB->MaxParameterCount = cpu_to_le16(2);
4695 /* BB find exact max SMB PDU from sess structure BB */
4696 pSMB->MaxDataCount = cpu_to_le16(100);
4697 pSMB->MaxSetupCount = 0;
4701 pSMB->Reserved2 = 0;
4702 byte_count = params + 1 /* pad */ ;
4703 pSMB->ParameterCount = cpu_to_le16(params);
4704 pSMB->TotalParameterCount = pSMB->ParameterCount;
4705 pSMB->ParameterOffset = cpu_to_le16(offsetof(struct
4706 smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4707 pSMB->SetupCount = 1;
4708 pSMB->Reserved3 = 0;
4709 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4710 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_POSIX_FS_INFO);
4711 pSMB->hdr.smb_buf_length += byte_count;
4712 pSMB->ByteCount = cpu_to_le16(byte_count);
4714 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4715 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4717 cFYI(1, "Send error in QFSUnixInfo = %d", rc);
4718 } else { /* decode response */
4719 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4721 if (rc || (pSMBr->ByteCount < 13)) {
4722 rc = -EIO; /* bad smb */
4724 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4726 (FILE_SYSTEM_POSIX_INFO
4727 *) (((char *) &pSMBr->hdr.Protocol) +
4730 le32_to_cpu(response_data->BlockSize);
4732 le64_to_cpu(response_data->TotalBlocks);
4734 le64_to_cpu(response_data->BlocksAvail);
4735 if (response_data->UserBlocksAvail == cpu_to_le64(-1)) {
4736 FSData->f_bavail = FSData->f_bfree;
4739 le64_to_cpu(response_data->UserBlocksAvail);
4741 if (response_data->TotalFileNodes != cpu_to_le64(-1))
4743 le64_to_cpu(response_data->TotalFileNodes);
4744 if (response_data->FreeFileNodes != cpu_to_le64(-1))
4746 le64_to_cpu(response_data->FreeFileNodes);
4749 cifs_buf_release(pSMB);
4758 /* We can not use write of zero bytes trick to
4759 set file size due to need for large file support. Also note that
4760 this SetPathInfo is preferred to SetFileInfo based method in next
4761 routine which is only needed to work around a sharing violation bug
4762 in Samba which this routine can run into */
4765 CIFSSMBSetEOF(const int xid, struct cifsTconInfo *tcon, const char *fileName,
4766 __u64 size, bool SetAllocation,
4767 const struct nls_table *nls_codepage, int remap)
4769 struct smb_com_transaction2_spi_req *pSMB = NULL;
4770 struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
4771 struct file_end_of_file_info *parm_data;
4774 int bytes_returned = 0;
4775 __u16 params, byte_count, data_count, param_offset, offset;
4777 cFYI(1, "In SetEOF");
4779 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4784 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4786 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
4787 PATH_MAX, nls_codepage, remap);
4788 name_len++; /* trailing null */
4790 } else { /* BB improve the check for buffer overruns BB */
4791 name_len = strnlen(fileName, PATH_MAX);
4792 name_len++; /* trailing null */
4793 strncpy(pSMB->FileName, fileName, name_len);
4795 params = 6 + name_len;
4796 data_count = sizeof(struct file_end_of_file_info);
4797 pSMB->MaxParameterCount = cpu_to_le16(2);
4798 pSMB->MaxDataCount = cpu_to_le16(4100);
4799 pSMB->MaxSetupCount = 0;
4803 pSMB->Reserved2 = 0;
4804 param_offset = offsetof(struct smb_com_transaction2_spi_req,
4805 InformationLevel) - 4;
4806 offset = param_offset + params;
4807 if (SetAllocation) {
4808 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
4809 pSMB->InformationLevel =
4810 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2);
4812 pSMB->InformationLevel =
4813 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO);
4814 } else /* Set File Size */ {
4815 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
4816 pSMB->InformationLevel =
4817 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO2);
4819 pSMB->InformationLevel =
4820 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO);
4824 (struct file_end_of_file_info *) (((char *) &pSMB->hdr.Protocol) +
4826 pSMB->ParameterOffset = cpu_to_le16(param_offset);
4827 pSMB->DataOffset = cpu_to_le16(offset);
4828 pSMB->SetupCount = 1;
4829 pSMB->Reserved3 = 0;
4830 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
4831 byte_count = 3 /* pad */ + params + data_count;
4832 pSMB->DataCount = cpu_to_le16(data_count);
4833 pSMB->TotalDataCount = pSMB->DataCount;
4834 pSMB->ParameterCount = cpu_to_le16(params);
4835 pSMB->TotalParameterCount = pSMB->ParameterCount;
4836 pSMB->Reserved4 = 0;
4837 pSMB->hdr.smb_buf_length += byte_count;
4838 parm_data->FileSize = cpu_to_le64(size);
4839 pSMB->ByteCount = cpu_to_le16(byte_count);
4840 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4841 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4843 cFYI(1, "SetPathInfo (file size) returned %d", rc);
4845 cifs_buf_release(pSMB);
4854 CIFSSMBSetFileSize(const int xid, struct cifsTconInfo *tcon, __u64 size,
4855 __u16 fid, __u32 pid_of_opener, bool SetAllocation)
4857 struct smb_com_transaction2_sfi_req *pSMB = NULL;
4859 struct file_end_of_file_info *parm_data;
4861 __u16 params, param_offset, offset, byte_count, count;
4863 cFYI(1, "SetFileSize (via SetFileInfo) %lld",
4865 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
4870 pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
4871 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));
4874 pSMB->MaxSetupCount = 0;
4878 pSMB->Reserved2 = 0;
4879 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
4880 offset = param_offset + params;
4882 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
4884 count = sizeof(struct file_end_of_file_info);
4885 pSMB->MaxParameterCount = cpu_to_le16(2);
4886 /* BB find exact max SMB PDU from sess structure BB */
4887 pSMB->MaxDataCount = cpu_to_le16(1000);
4888 pSMB->SetupCount = 1;
4889 pSMB->Reserved3 = 0;
4890 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
4891 byte_count = 3 /* pad */ + params + count;
4892 pSMB->DataCount = cpu_to_le16(count);
4893 pSMB->ParameterCount = cpu_to_le16(params);
4894 pSMB->TotalDataCount = pSMB->DataCount;
4895 pSMB->TotalParameterCount = pSMB->ParameterCount;
4896 pSMB->ParameterOffset = cpu_to_le16(param_offset);
4898 (struct file_end_of_file_info *) (((char *) &pSMB->hdr.Protocol)
4900 pSMB->DataOffset = cpu_to_le16(offset);
4901 parm_data->FileSize = cpu_to_le64(size);
4903 if (SetAllocation) {
4904 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
4905 pSMB->InformationLevel =
4906 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2);
4908 pSMB->InformationLevel =
4909 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO);
4910 } else /* Set File Size */ {
4911 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
4912 pSMB->InformationLevel =
4913 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO2);
4915 pSMB->InformationLevel =
4916 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO);
4918 pSMB->Reserved4 = 0;
4919 pSMB->hdr.smb_buf_length += byte_count;
4920 pSMB->ByteCount = cpu_to_le16(byte_count);
4921 rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0);
4923 cFYI(1, "Send error in SetFileInfo (SetFileSize) = %d", rc);
4926 /* Note: On -EAGAIN error only caller can retry on handle based calls
4927 since file handle passed in no longer valid */
4932 /* Some legacy servers such as NT4 require that the file times be set on
4933 an open handle, rather than by pathname - this is awkward due to
4934 potential access conflicts on the open, but it is unavoidable for these
4935 old servers since the only other choice is to go from 100 nanosecond DCE
4936 time and resort to the original setpathinfo level which takes the ancient
4937 DOS time format with 2 second granularity */
4939 CIFSSMBSetFileInfo(const int xid, struct cifsTconInfo *tcon,
4940 const FILE_BASIC_INFO *data, __u16 fid, __u32 pid_of_opener)
4942 struct smb_com_transaction2_sfi_req *pSMB = NULL;
4945 __u16 params, param_offset, offset, byte_count, count;
4947 cFYI(1, "Set Times (via SetFileInfo)");
4948 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
4953 pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
4954 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));
4957 pSMB->MaxSetupCount = 0;
4961 pSMB->Reserved2 = 0;
4962 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
4963 offset = param_offset + params;
4965 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
4967 count = sizeof(FILE_BASIC_INFO);
4968 pSMB->MaxParameterCount = cpu_to_le16(2);
4969 /* BB find max SMB PDU from sess */
4970 pSMB->MaxDataCount = cpu_to_le16(1000);
4971 pSMB->SetupCount = 1;
4972 pSMB->Reserved3 = 0;
4973 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
4974 byte_count = 3 /* pad */ + params + count;
4975 pSMB->DataCount = cpu_to_le16(count);
4976 pSMB->ParameterCount = cpu_to_le16(params);
4977 pSMB->TotalDataCount = pSMB->DataCount;
4978 pSMB->TotalParameterCount = pSMB->ParameterCount;
4979 pSMB->ParameterOffset = cpu_to_le16(param_offset);
4980 pSMB->DataOffset = cpu_to_le16(offset);
4982 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
4983 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO2);
4985 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO);
4986 pSMB->Reserved4 = 0;
4987 pSMB->hdr.smb_buf_length += byte_count;
4988 pSMB->ByteCount = cpu_to_le16(byte_count);
4989 memcpy(data_offset, data, sizeof(FILE_BASIC_INFO));
4990 rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0);
4992 cFYI(1, "Send error in Set Time (SetFileInfo) = %d", rc);
4994 /* Note: On -EAGAIN error only caller can retry on handle based calls
4995 since file handle passed in no longer valid */
5001 CIFSSMBSetFileDisposition(const int xid, struct cifsTconInfo *tcon,
5002 bool delete_file, __u16 fid, __u32 pid_of_opener)
5004 struct smb_com_transaction2_sfi_req *pSMB = NULL;
5007 __u16 params, param_offset, offset, byte_count, count;
5009 cFYI(1, "Set File Disposition (via SetFileInfo)");
5010 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
5015 pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
5016 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));
5019 pSMB->MaxSetupCount = 0;
5023 pSMB->Reserved2 = 0;
5024 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
5025 offset = param_offset + params;
5027 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
5030 pSMB->MaxParameterCount = cpu_to_le16(2);
5031 /* BB find max SMB PDU from sess */
5032 pSMB->MaxDataCount = cpu_to_le16(1000);
5033 pSMB->SetupCount = 1;
5034 pSMB->Reserved3 = 0;
5035 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
5036 byte_count = 3 /* pad */ + params + count;
5037 pSMB->DataCount = cpu_to_le16(count);
5038 pSMB->ParameterCount = cpu_to_le16(params);
5039 pSMB->TotalDataCount = pSMB->DataCount;
5040 pSMB->TotalParameterCount = pSMB->ParameterCount;
5041 pSMB->ParameterOffset = cpu_to_le16(param_offset);
5042 pSMB->DataOffset = cpu_to_le16(offset);
5044 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_DISPOSITION_INFO);
5045 pSMB->Reserved4 = 0;
5046 pSMB->hdr.smb_buf_length += byte_count;
5047 pSMB->ByteCount = cpu_to_le16(byte_count);
5048 *data_offset = delete_file ? 1 : 0;
5049 rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0);
5051 cFYI(1, "Send error in SetFileDisposition = %d", rc);
5057 CIFSSMBSetPathInfo(const int xid, struct cifsTconInfo *tcon,
5058 const char *fileName, const FILE_BASIC_INFO *data,
5059 const struct nls_table *nls_codepage, int remap)
5061 TRANSACTION2_SPI_REQ *pSMB = NULL;
5062 TRANSACTION2_SPI_RSP *pSMBr = NULL;
5065 int bytes_returned = 0;
5067 __u16 params, param_offset, offset, byte_count, count;
5069 cFYI(1, "In SetTimes");
5072 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5077 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5079 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
5080 PATH_MAX, nls_codepage, remap);
5081 name_len++; /* trailing null */
5083 } else { /* BB improve the check for buffer overruns BB */
5084 name_len = strnlen(fileName, PATH_MAX);
5085 name_len++; /* trailing null */
5086 strncpy(pSMB->FileName, fileName, name_len);
5089 params = 6 + name_len;
5090 count = sizeof(FILE_BASIC_INFO);
5091 pSMB->MaxParameterCount = cpu_to_le16(2);
5092 /* BB find max SMB PDU from sess structure BB */
5093 pSMB->MaxDataCount = cpu_to_le16(1000);
5094 pSMB->MaxSetupCount = 0;
5098 pSMB->Reserved2 = 0;
5099 param_offset = offsetof(struct smb_com_transaction2_spi_req,
5100 InformationLevel) - 4;
5101 offset = param_offset + params;
5102 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
5103 pSMB->ParameterOffset = cpu_to_le16(param_offset);
5104 pSMB->DataOffset = cpu_to_le16(offset);
5105 pSMB->SetupCount = 1;
5106 pSMB->Reserved3 = 0;
5107 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
5108 byte_count = 3 /* pad */ + params + count;
5110 pSMB->DataCount = cpu_to_le16(count);
5111 pSMB->ParameterCount = cpu_to_le16(params);
5112 pSMB->TotalDataCount = pSMB->DataCount;
5113 pSMB->TotalParameterCount = pSMB->ParameterCount;
5114 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
5115 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO2);
5117 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO);
5118 pSMB->Reserved4 = 0;
5119 pSMB->hdr.smb_buf_length += byte_count;
5120 memcpy(data_offset, data, sizeof(FILE_BASIC_INFO));
5121 pSMB->ByteCount = cpu_to_le16(byte_count);
5122 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5123 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5125 cFYI(1, "SetPathInfo (times) returned %d", rc);
5127 cifs_buf_release(pSMB);
5135 /* Can not be used to set time stamps yet (due to old DOS time format) */
5136 /* Can be used to set attributes */
5137 #if 0 /* Possibly not needed - since it turns out that strangely NT4 has a bug
5138 handling it anyway and NT4 was what we thought it would be needed for
5139 Do not delete it until we prove whether needed for Win9x though */
5141 CIFSSMBSetAttrLegacy(int xid, struct cifsTconInfo *tcon, char *fileName,
5142 __u16 dos_attrs, const struct nls_table *nls_codepage)
5144 SETATTR_REQ *pSMB = NULL;
5145 SETATTR_RSP *pSMBr = NULL;
5150 cFYI(1, "In SetAttrLegacy");
5153 rc = smb_init(SMB_COM_SETATTR, 8, tcon, (void **) &pSMB,
5158 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5160 ConvertToUCS((__le16 *) pSMB->fileName, fileName,
5161 PATH_MAX, nls_codepage);
5162 name_len++; /* trailing null */
5164 } else { /* BB improve the check for buffer overruns BB */
5165 name_len = strnlen(fileName, PATH_MAX);
5166 name_len++; /* trailing null */
5167 strncpy(pSMB->fileName, fileName, name_len);
5169 pSMB->attr = cpu_to_le16(dos_attrs);
5170 pSMB->BufferFormat = 0x04;
5171 pSMB->hdr.smb_buf_length += name_len + 1;
5172 pSMB->ByteCount = cpu_to_le16(name_len + 1);
5173 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5174 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5176 cFYI(1, "Error in LegacySetAttr = %d", rc);
5178 cifs_buf_release(pSMB);
5181 goto SetAttrLgcyRetry;
5185 #endif /* temporarily unneeded SetAttr legacy function */
5188 cifs_fill_unix_set_info(FILE_UNIX_BASIC_INFO *data_offset,
5189 const struct cifs_unix_set_info_args *args)
5191 u64 mode = args->mode;
5194 * Samba server ignores set of file size to zero due to bugs in some
5195 * older clients, but we should be precise - we use SetFileSize to
5196 * set file size and do not want to truncate file size to zero
5197 * accidently as happened on one Samba server beta by putting
5198 * zero instead of -1 here
5200 data_offset->EndOfFile = cpu_to_le64(NO_CHANGE_64);
5201 data_offset->NumOfBytes = cpu_to_le64(NO_CHANGE_64);
5202 data_offset->LastStatusChange = cpu_to_le64(args->ctime);
5203 data_offset->LastAccessTime = cpu_to_le64(args->atime);
5204 data_offset->LastModificationTime = cpu_to_le64(args->mtime);
5205 data_offset->Uid = cpu_to_le64(args->uid);
5206 data_offset->Gid = cpu_to_le64(args->gid);
5207 /* better to leave device as zero when it is */
5208 data_offset->DevMajor = cpu_to_le64(MAJOR(args->device));
5209 data_offset->DevMinor = cpu_to_le64(MINOR(args->device));
5210 data_offset->Permissions = cpu_to_le64(mode);
5213 data_offset->Type = cpu_to_le32(UNIX_FILE);
5214 else if (S_ISDIR(mode))
5215 data_offset->Type = cpu_to_le32(UNIX_DIR);
5216 else if (S_ISLNK(mode))
5217 data_offset->Type = cpu_to_le32(UNIX_SYMLINK);
5218 else if (S_ISCHR(mode))
5219 data_offset->Type = cpu_to_le32(UNIX_CHARDEV);
5220 else if (S_ISBLK(mode))
5221 data_offset->Type = cpu_to_le32(UNIX_BLOCKDEV);
5222 else if (S_ISFIFO(mode))
5223 data_offset->Type = cpu_to_le32(UNIX_FIFO);
5224 else if (S_ISSOCK(mode))
5225 data_offset->Type = cpu_to_le32(UNIX_SOCKET);
5229 CIFSSMBUnixSetFileInfo(const int xid, struct cifsTconInfo *tcon,
5230 const struct cifs_unix_set_info_args *args,
5231 u16 fid, u32 pid_of_opener)
5233 struct smb_com_transaction2_sfi_req *pSMB = NULL;
5234 FILE_UNIX_BASIC_INFO *data_offset;
5236 u16 params, param_offset, offset, byte_count, count;
5238 cFYI(1, "Set Unix Info (via SetFileInfo)");
5239 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
5244 pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
5245 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));
5248 pSMB->MaxSetupCount = 0;
5252 pSMB->Reserved2 = 0;
5253 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
5254 offset = param_offset + params;
5256 data_offset = (FILE_UNIX_BASIC_INFO *)
5257 ((char *)(&pSMB->hdr.Protocol) + offset);
5258 count = sizeof(FILE_UNIX_BASIC_INFO);
5260 pSMB->MaxParameterCount = cpu_to_le16(2);
5261 /* BB find max SMB PDU from sess */
5262 pSMB->MaxDataCount = cpu_to_le16(1000);
5263 pSMB->SetupCount = 1;
5264 pSMB->Reserved3 = 0;
5265 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
5266 byte_count = 3 /* pad */ + params + count;
5267 pSMB->DataCount = cpu_to_le16(count);
5268 pSMB->ParameterCount = cpu_to_le16(params);
5269 pSMB->TotalDataCount = pSMB->DataCount;
5270 pSMB->TotalParameterCount = pSMB->ParameterCount;
5271 pSMB->ParameterOffset = cpu_to_le16(param_offset);
5272 pSMB->DataOffset = cpu_to_le16(offset);
5274 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_BASIC);
5275 pSMB->Reserved4 = 0;
5276 pSMB->hdr.smb_buf_length += byte_count;
5277 pSMB->ByteCount = cpu_to_le16(byte_count);
5279 cifs_fill_unix_set_info(data_offset, args);
5281 rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0);
5283 cFYI(1, "Send error in Set Time (SetFileInfo) = %d", rc);
5285 /* Note: On -EAGAIN error only caller can retry on handle based calls
5286 since file handle passed in no longer valid */
5292 CIFSSMBUnixSetPathInfo(const int xid, struct cifsTconInfo *tcon, char *fileName,
5293 const struct cifs_unix_set_info_args *args,
5294 const struct nls_table *nls_codepage, int remap)
5296 TRANSACTION2_SPI_REQ *pSMB = NULL;
5297 TRANSACTION2_SPI_RSP *pSMBr = NULL;
5300 int bytes_returned = 0;
5301 FILE_UNIX_BASIC_INFO *data_offset;
5302 __u16 params, param_offset, offset, count, byte_count;
5304 cFYI(1, "In SetUID/GID/Mode");
5306 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5311 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5313 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
5314 PATH_MAX, nls_codepage, remap);
5315 name_len++; /* trailing null */
5317 } else { /* BB improve the check for buffer overruns BB */
5318 name_len = strnlen(fileName, PATH_MAX);
5319 name_len++; /* trailing null */
5320 strncpy(pSMB->FileName, fileName, name_len);
5323 params = 6 + name_len;
5324 count = sizeof(FILE_UNIX_BASIC_INFO);
5325 pSMB->MaxParameterCount = cpu_to_le16(2);
5326 /* BB find max SMB PDU from sess structure BB */
5327 pSMB->MaxDataCount = cpu_to_le16(1000);
5328 pSMB->MaxSetupCount = 0;
5332 pSMB->Reserved2 = 0;
5333 param_offset = offsetof(struct smb_com_transaction2_spi_req,
5334 InformationLevel) - 4;
5335 offset = param_offset + params;
5337 (FILE_UNIX_BASIC_INFO *) ((char *) &pSMB->hdr.Protocol +
5339 memset(data_offset, 0, count);
5340 pSMB->DataOffset = cpu_to_le16(offset);
5341 pSMB->ParameterOffset = cpu_to_le16(param_offset);
5342 pSMB->SetupCount = 1;
5343 pSMB->Reserved3 = 0;
5344 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
5345 byte_count = 3 /* pad */ + params + count;
5346 pSMB->ParameterCount = cpu_to_le16(params);
5347 pSMB->DataCount = cpu_to_le16(count);
5348 pSMB->TotalParameterCount = pSMB->ParameterCount;
5349 pSMB->TotalDataCount = pSMB->DataCount;
5350 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_BASIC);
5351 pSMB->Reserved4 = 0;
5352 pSMB->hdr.smb_buf_length += byte_count;
5354 cifs_fill_unix_set_info(data_offset, args);
5356 pSMB->ByteCount = cpu_to_le16(byte_count);
5357 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5358 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5360 cFYI(1, "SetPathInfo (perms) returned %d", rc);
5362 cifs_buf_release(pSMB);
5368 int CIFSSMBNotify(const int xid, struct cifsTconInfo *tcon,
5369 const int notify_subdirs, const __u16 netfid,
5370 __u32 filter, struct file *pfile, int multishot,
5371 const struct nls_table *nls_codepage)
5374 struct smb_com_transaction_change_notify_req *pSMB = NULL;
5375 struct smb_com_ntransaction_change_notify_rsp *pSMBr = NULL;
5376 struct dir_notify_req *dnotify_req;
5379 cFYI(1, "In CIFSSMBNotify for file handle %d", (int)netfid);
5380 rc = smb_init(SMB_COM_NT_TRANSACT, 23, tcon, (void **) &pSMB,
5385 pSMB->TotalParameterCount = 0 ;
5386 pSMB->TotalDataCount = 0;
5387 pSMB->MaxParameterCount = cpu_to_le32(2);
5388 /* BB find exact data count max from sess structure BB */
5389 pSMB->MaxDataCount = 0; /* same in little endian or be */
5390 /* BB VERIFY verify which is correct for above BB */
5391 pSMB->MaxDataCount = cpu_to_le32((tcon->ses->server->maxBuf -
5392 MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
5394 pSMB->MaxSetupCount = 4;
5396 pSMB->ParameterOffset = 0;
5397 pSMB->DataCount = 0;
5398 pSMB->DataOffset = 0;
5399 pSMB->SetupCount = 4; /* single byte does not need le conversion */
5400 pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_NOTIFY_CHANGE);
5401 pSMB->ParameterCount = pSMB->TotalParameterCount;
5403 pSMB->WatchTree = 1; /* one byte - no le conversion needed */
5404 pSMB->Reserved2 = 0;
5405 pSMB->CompletionFilter = cpu_to_le32(filter);
5406 pSMB->Fid = netfid; /* file handle always le */
5407 pSMB->ByteCount = 0;
5409 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5410 (struct smb_hdr *)pSMBr, &bytes_returned,
5413 cFYI(1, "Error in Notify = %d", rc);
5415 /* Add file to outstanding requests */
5416 /* BB change to kmem cache alloc */
5417 dnotify_req = kmalloc(
5418 sizeof(struct dir_notify_req),
5421 dnotify_req->Pid = pSMB->hdr.Pid;
5422 dnotify_req->PidHigh = pSMB->hdr.PidHigh;
5423 dnotify_req->Mid = pSMB->hdr.Mid;
5424 dnotify_req->Tid = pSMB->hdr.Tid;
5425 dnotify_req->Uid = pSMB->hdr.Uid;
5426 dnotify_req->netfid = netfid;
5427 dnotify_req->pfile = pfile;
5428 dnotify_req->filter = filter;
5429 dnotify_req->multishot = multishot;
5430 spin_lock(&GlobalMid_Lock);
5431 list_add_tail(&dnotify_req->lhead,
5432 &GlobalDnotifyReqList);
5433 spin_unlock(&GlobalMid_Lock);
5437 cifs_buf_release(pSMB);
5441 #ifdef CONFIG_CIFS_XATTR
5443 * Do a path-based QUERY_ALL_EAS call and parse the result. This is a common
5444 * function used by listxattr and getxattr type calls. When ea_name is set,
5445 * it looks for that attribute name and stuffs that value into the EAData
5446 * buffer. When ea_name is NULL, it stuffs a list of attribute names into the
5447 * buffer. In both cases, the return value is either the length of the
5448 * resulting data or a negative error code. If EAData is a NULL pointer then
5449 * the data isn't copied to it, but the length is returned.
5452 CIFSSMBQAllEAs(const int xid, struct cifsTconInfo *tcon,
5453 const unsigned char *searchName, const unsigned char *ea_name,
5454 char *EAData, size_t buf_size,
5455 const struct nls_table *nls_codepage, int remap)
5457 /* BB assumes one setup word */
5458 TRANSACTION2_QPI_REQ *pSMB = NULL;
5459 TRANSACTION2_QPI_RSP *pSMBr = NULL;
5463 struct fealist *ea_response_data;
5464 struct fea *temp_fea;
5467 __u16 params, byte_count, data_offset;
5469 cFYI(1, "In Query All EAs path %s", searchName);
5471 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5476 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5478 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
5479 PATH_MAX, nls_codepage, remap);
5480 list_len++; /* trailing null */
5482 } else { /* BB improve the check for buffer overruns BB */
5483 list_len = strnlen(searchName, PATH_MAX);
5484 list_len++; /* trailing null */
5485 strncpy(pSMB->FileName, searchName, list_len);
5488 params = 2 /* level */ + 4 /* reserved */ + list_len /* includes NUL */;
5489 pSMB->TotalDataCount = 0;
5490 pSMB->MaxParameterCount = cpu_to_le16(2);
5491 /* BB find exact max SMB PDU from sess structure BB */
5492 pSMB->MaxDataCount = cpu_to_le16(CIFSMaxBufSize);
5493 pSMB->MaxSetupCount = 0;
5497 pSMB->Reserved2 = 0;
5498 pSMB->ParameterOffset = cpu_to_le16(offsetof(
5499 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
5500 pSMB->DataCount = 0;
5501 pSMB->DataOffset = 0;
5502 pSMB->SetupCount = 1;
5503 pSMB->Reserved3 = 0;
5504 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
5505 byte_count = params + 1 /* pad */ ;
5506 pSMB->TotalParameterCount = cpu_to_le16(params);
5507 pSMB->ParameterCount = pSMB->TotalParameterCount;
5508 pSMB->InformationLevel = cpu_to_le16(SMB_INFO_QUERY_ALL_EAS);
5509 pSMB->Reserved4 = 0;
5510 pSMB->hdr.smb_buf_length += byte_count;
5511 pSMB->ByteCount = cpu_to_le16(byte_count);
5513 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5514 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5516 cFYI(1, "Send error in QueryAllEAs = %d", rc);
5521 /* BB also check enough total bytes returned */
5522 /* BB we need to improve the validity checking
5523 of these trans2 responses */
5525 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
5526 if (rc || (pSMBr->ByteCount < 4)) {
5527 rc = -EIO; /* bad smb */
5531 /* check that length of list is not more than bcc */
5532 /* check that each entry does not go beyond length
5534 /* check that each element of each entry does not
5535 go beyond end of list */
5536 /* validate_trans2_offsets() */
5537 /* BB check if start of smb + data_offset > &bcc+ bcc */
5539 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
5540 ea_response_data = (struct fealist *)
5541 (((char *) &pSMBr->hdr.Protocol) + data_offset);
5543 list_len = le32_to_cpu(ea_response_data->list_len);
5544 cFYI(1, "ea length %d", list_len);
5545 if (list_len <= 8) {
5546 cFYI(1, "empty EA list returned from server");
5550 /* make sure list_len doesn't go past end of SMB */
5551 end_of_smb = (char *)pByteArea(&pSMBr->hdr) + BCC(&pSMBr->hdr);
5552 if ((char *)ea_response_data + list_len > end_of_smb) {
5553 cFYI(1, "EA list appears to go beyond SMB");
5558 /* account for ea list len */
5560 temp_fea = ea_response_data->list;
5561 temp_ptr = (char *)temp_fea;
5562 while (list_len > 0) {
5563 unsigned int name_len;
5568 /* make sure we can read name_len and value_len */
5570 cFYI(1, "EA entry goes beyond length of list");
5575 name_len = temp_fea->name_len;
5576 value_len = le16_to_cpu(temp_fea->value_len);
5577 list_len -= name_len + 1 + value_len;
5579 cFYI(1, "EA entry goes beyond length of list");
5585 if (strncmp(ea_name, temp_ptr, name_len) == 0) {
5586 temp_ptr += name_len + 1;
5590 if ((size_t)value_len > buf_size) {
5594 memcpy(EAData, temp_ptr, value_len);
5598 /* account for prefix user. and trailing null */
5599 rc += (5 + 1 + name_len);
5600 if (rc < (int) buf_size) {
5601 memcpy(EAData, "user.", 5);
5603 memcpy(EAData, temp_ptr, name_len);
5605 /* null terminate name */
5608 } else if (buf_size == 0) {
5609 /* skip copy - calc size only */
5611 /* stop before overrun buffer */
5616 temp_ptr += name_len + 1 + value_len;
5617 temp_fea = (struct fea *)temp_ptr;
5620 /* didn't find the named attribute */
5625 cifs_buf_release(pSMB);
5633 CIFSSMBSetEA(const int xid, struct cifsTconInfo *tcon, const char *fileName,
5634 const char *ea_name, const void *ea_value,
5635 const __u16 ea_value_len, const struct nls_table *nls_codepage,
5638 struct smb_com_transaction2_spi_req *pSMB = NULL;
5639 struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
5640 struct fealist *parm_data;
5643 int bytes_returned = 0;
5644 __u16 params, param_offset, byte_count, offset, count;
5646 cFYI(1, "In SetEA");
5648 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5653 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5655 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
5656 PATH_MAX, nls_codepage, remap);
5657 name_len++; /* trailing null */
5659 } else { /* BB improve the check for buffer overruns BB */
5660 name_len = strnlen(fileName, PATH_MAX);
5661 name_len++; /* trailing null */
5662 strncpy(pSMB->FileName, fileName, name_len);
5665 params = 6 + name_len;
5667 /* done calculating parms using name_len of file name,
5668 now use name_len to calculate length of ea name
5669 we are going to create in the inode xattrs */
5670 if (ea_name == NULL)
5673 name_len = strnlen(ea_name, 255);
5675 count = sizeof(*parm_data) + ea_value_len + name_len;
5676 pSMB->MaxParameterCount = cpu_to_le16(2);
5677 /* BB find max SMB PDU from sess */
5678 pSMB->MaxDataCount = cpu_to_le16(1000);
5679 pSMB->MaxSetupCount = 0;
5683 pSMB->Reserved2 = 0;
5684 param_offset = offsetof(struct smb_com_transaction2_spi_req,
5685 InformationLevel) - 4;
5686 offset = param_offset + params;
5687 pSMB->InformationLevel =
5688 cpu_to_le16(SMB_SET_FILE_EA);
5691 (struct fealist *) (((char *) &pSMB->hdr.Protocol) +
5693 pSMB->ParameterOffset = cpu_to_le16(param_offset);
5694 pSMB->DataOffset = cpu_to_le16(offset);
5695 pSMB->SetupCount = 1;
5696 pSMB->Reserved3 = 0;
5697 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
5698 byte_count = 3 /* pad */ + params + count;
5699 pSMB->DataCount = cpu_to_le16(count);
5700 parm_data->list_len = cpu_to_le32(count);
5701 parm_data->list[0].EA_flags = 0;
5702 /* we checked above that name len is less than 255 */
5703 parm_data->list[0].name_len = (__u8)name_len;
5704 /* EA names are always ASCII */
5706 strncpy(parm_data->list[0].name, ea_name, name_len);
5707 parm_data->list[0].name[name_len] = 0;
5708 parm_data->list[0].value_len = cpu_to_le16(ea_value_len);
5709 /* caller ensures that ea_value_len is less than 64K but
5710 we need to ensure that it fits within the smb */
5712 /*BB add length check to see if it would fit in
5713 negotiated SMB buffer size BB */
5714 /* if (ea_value_len > buffer_size - 512 (enough for header)) */
5716 memcpy(parm_data->list[0].name+name_len+1,
5717 ea_value, ea_value_len);
5719 pSMB->TotalDataCount = pSMB->DataCount;
5720 pSMB->ParameterCount = cpu_to_le16(params);
5721 pSMB->TotalParameterCount = pSMB->ParameterCount;
5722 pSMB->Reserved4 = 0;
5723 pSMB->hdr.smb_buf_length += byte_count;
5724 pSMB->ByteCount = cpu_to_le16(byte_count);
5725 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5726 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5728 cFYI(1, "SetPathInfo (EA) returned %d", rc);
5730 cifs_buf_release(pSMB);