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,
606 if (server->secType == Kerberos) {
607 if (!server->sec_kerberos &&
608 !server->sec_mskerberos)
610 } else if (server->secType == RawNTLMSSP) {
611 if (!server->sec_ntlmssp)
617 server->capabilities &= ~CAP_EXTENDED_SECURITY;
619 #ifdef CONFIG_CIFS_WEAK_PW_HASH
622 if ((secFlags & CIFSSEC_MAY_SIGN) == 0) {
623 /* MUST_SIGN already includes the MAY_SIGN FLAG
624 so if this is zero it means that signing is disabled */
625 cFYI(1, "Signing disabled");
626 if (server->secMode & SECMODE_SIGN_REQUIRED) {
627 cERROR(1, "Server requires "
628 "packet signing to be enabled in "
629 "/proc/fs/cifs/SecurityFlags.");
633 ~(SECMODE_SIGN_ENABLED | SECMODE_SIGN_REQUIRED);
634 } else if ((secFlags & CIFSSEC_MUST_SIGN) == CIFSSEC_MUST_SIGN) {
635 /* signing required */
636 cFYI(1, "Must sign - secFlags 0x%x", secFlags);
637 if ((server->secMode &
638 (SECMODE_SIGN_ENABLED | SECMODE_SIGN_REQUIRED)) == 0) {
639 cERROR(1, "signing required but server lacks support");
642 server->secMode |= SECMODE_SIGN_REQUIRED;
644 /* signing optional ie CIFSSEC_MAY_SIGN */
645 if ((server->secMode & SECMODE_SIGN_REQUIRED) == 0)
647 ~(SECMODE_SIGN_ENABLED | SECMODE_SIGN_REQUIRED);
651 cifs_buf_release(pSMB);
653 cFYI(1, "negprot rc %d", rc);
658 CIFSSMBTDis(const int xid, struct cifsTconInfo *tcon)
660 struct smb_hdr *smb_buffer;
663 cFYI(1, "In tree disconnect");
665 /* BB: do we need to check this? These should never be NULL. */
666 if ((tcon->ses == NULL) || (tcon->ses->server == NULL))
670 * No need to return error on this operation if tid invalidated and
671 * closed on server already e.g. due to tcp session crashing. Also,
672 * the tcon is no longer on the list, so no need to take lock before
675 if ((tcon->need_reconnect) || (tcon->ses->need_reconnect))
678 rc = small_smb_init(SMB_COM_TREE_DISCONNECT, 0, tcon,
679 (void **)&smb_buffer);
683 rc = SendReceiveNoRsp(xid, tcon->ses, smb_buffer, 0);
685 cFYI(1, "Tree disconnect failed %d", rc);
687 /* No need to return error on this operation if tid invalidated and
688 closed on server already e.g. due to tcp session crashing */
696 CIFSSMBLogoff(const int xid, struct cifsSesInfo *ses)
698 LOGOFF_ANDX_REQ *pSMB;
701 cFYI(1, "In SMBLogoff for session disconnect");
704 * BB: do we need to check validity of ses and server? They should
705 * always be valid since we have an active reference. If not, that
706 * should probably be a BUG()
708 if (!ses || !ses->server)
711 mutex_lock(&ses->session_mutex);
712 if (ses->need_reconnect)
713 goto session_already_dead; /* no need to send SMBlogoff if uid
714 already closed due to reconnect */
715 rc = small_smb_init(SMB_COM_LOGOFF_ANDX, 2, NULL, (void **)&pSMB);
717 mutex_unlock(&ses->session_mutex);
721 pSMB->hdr.Mid = GetNextMid(ses->server);
723 if (ses->server->secMode &
724 (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
725 pSMB->hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
727 pSMB->hdr.Uid = ses->Suid;
729 pSMB->AndXCommand = 0xFF;
730 rc = SendReceiveNoRsp(xid, ses, (struct smb_hdr *) pSMB, 0);
731 session_already_dead:
732 mutex_unlock(&ses->session_mutex);
734 /* if session dead then we do not need to do ulogoff,
735 since server closed smb session, no sense reporting
743 CIFSPOSIXDelFile(const int xid, struct cifsTconInfo *tcon, const char *fileName,
744 __u16 type, const struct nls_table *nls_codepage, int remap)
746 TRANSACTION2_SPI_REQ *pSMB = NULL;
747 TRANSACTION2_SPI_RSP *pSMBr = NULL;
748 struct unlink_psx_rq *pRqD;
751 int bytes_returned = 0;
752 __u16 params, param_offset, offset, byte_count;
754 cFYI(1, "In POSIX delete");
756 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
761 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
763 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
764 PATH_MAX, nls_codepage, remap);
765 name_len++; /* trailing null */
767 } else { /* BB add path length overrun check */
768 name_len = strnlen(fileName, PATH_MAX);
769 name_len++; /* trailing null */
770 strncpy(pSMB->FileName, fileName, name_len);
773 params = 6 + name_len;
774 pSMB->MaxParameterCount = cpu_to_le16(2);
775 pSMB->MaxDataCount = 0; /* BB double check this with jra */
776 pSMB->MaxSetupCount = 0;
781 param_offset = offsetof(struct smb_com_transaction2_spi_req,
782 InformationLevel) - 4;
783 offset = param_offset + params;
785 /* Setup pointer to Request Data (inode type) */
786 pRqD = (struct unlink_psx_rq *)(((char *)&pSMB->hdr.Protocol) + offset);
787 pRqD->type = cpu_to_le16(type);
788 pSMB->ParameterOffset = cpu_to_le16(param_offset);
789 pSMB->DataOffset = cpu_to_le16(offset);
790 pSMB->SetupCount = 1;
792 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
793 byte_count = 3 /* pad */ + params + sizeof(struct unlink_psx_rq);
795 pSMB->DataCount = cpu_to_le16(sizeof(struct unlink_psx_rq));
796 pSMB->TotalDataCount = cpu_to_le16(sizeof(struct unlink_psx_rq));
797 pSMB->ParameterCount = cpu_to_le16(params);
798 pSMB->TotalParameterCount = pSMB->ParameterCount;
799 pSMB->InformationLevel = cpu_to_le16(SMB_POSIX_UNLINK);
801 pSMB->hdr.smb_buf_length += byte_count;
802 pSMB->ByteCount = cpu_to_le16(byte_count);
803 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
804 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
806 cFYI(1, "Posix delete returned %d", rc);
807 cifs_buf_release(pSMB);
809 cifs_stats_inc(&tcon->num_deletes);
818 CIFSSMBDelFile(const int xid, struct cifsTconInfo *tcon, const char *fileName,
819 const struct nls_table *nls_codepage, int remap)
821 DELETE_FILE_REQ *pSMB = NULL;
822 DELETE_FILE_RSP *pSMBr = NULL;
828 rc = smb_init(SMB_COM_DELETE, 1, tcon, (void **) &pSMB,
833 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
835 cifsConvertToUCS((__le16 *) pSMB->fileName, fileName,
836 PATH_MAX, nls_codepage, remap);
837 name_len++; /* trailing null */
839 } else { /* BB improve check for buffer overruns BB */
840 name_len = strnlen(fileName, PATH_MAX);
841 name_len++; /* trailing null */
842 strncpy(pSMB->fileName, fileName, name_len);
844 pSMB->SearchAttributes =
845 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM);
846 pSMB->BufferFormat = 0x04;
847 pSMB->hdr.smb_buf_length += name_len + 1;
848 pSMB->ByteCount = cpu_to_le16(name_len + 1);
849 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
850 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
851 cifs_stats_inc(&tcon->num_deletes);
853 cFYI(1, "Error in RMFile = %d", rc);
855 cifs_buf_release(pSMB);
863 CIFSSMBRmDir(const int xid, struct cifsTconInfo *tcon, const char *dirName,
864 const struct nls_table *nls_codepage, int remap)
866 DELETE_DIRECTORY_REQ *pSMB = NULL;
867 DELETE_DIRECTORY_RSP *pSMBr = NULL;
872 cFYI(1, "In CIFSSMBRmDir");
874 rc = smb_init(SMB_COM_DELETE_DIRECTORY, 0, tcon, (void **) &pSMB,
879 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
880 name_len = cifsConvertToUCS((__le16 *) pSMB->DirName, dirName,
881 PATH_MAX, nls_codepage, remap);
882 name_len++; /* trailing null */
884 } else { /* BB improve check for buffer overruns BB */
885 name_len = strnlen(dirName, PATH_MAX);
886 name_len++; /* trailing null */
887 strncpy(pSMB->DirName, dirName, name_len);
890 pSMB->BufferFormat = 0x04;
891 pSMB->hdr.smb_buf_length += name_len + 1;
892 pSMB->ByteCount = cpu_to_le16(name_len + 1);
893 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
894 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
895 cifs_stats_inc(&tcon->num_rmdirs);
897 cFYI(1, "Error in RMDir = %d", rc);
899 cifs_buf_release(pSMB);
906 CIFSSMBMkDir(const int xid, struct cifsTconInfo *tcon,
907 const char *name, const struct nls_table *nls_codepage, int remap)
910 CREATE_DIRECTORY_REQ *pSMB = NULL;
911 CREATE_DIRECTORY_RSP *pSMBr = NULL;
915 cFYI(1, "In CIFSSMBMkDir");
917 rc = smb_init(SMB_COM_CREATE_DIRECTORY, 0, tcon, (void **) &pSMB,
922 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
923 name_len = cifsConvertToUCS((__le16 *) pSMB->DirName, name,
924 PATH_MAX, nls_codepage, remap);
925 name_len++; /* trailing null */
927 } else { /* BB improve check for buffer overruns BB */
928 name_len = strnlen(name, PATH_MAX);
929 name_len++; /* trailing null */
930 strncpy(pSMB->DirName, name, name_len);
933 pSMB->BufferFormat = 0x04;
934 pSMB->hdr.smb_buf_length += name_len + 1;
935 pSMB->ByteCount = cpu_to_le16(name_len + 1);
936 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
937 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
938 cifs_stats_inc(&tcon->num_mkdirs);
940 cFYI(1, "Error in Mkdir = %d", rc);
942 cifs_buf_release(pSMB);
949 CIFSPOSIXCreate(const int xid, struct cifsTconInfo *tcon, __u32 posix_flags,
950 __u64 mode, __u16 *netfid, FILE_UNIX_BASIC_INFO *pRetData,
951 __u32 *pOplock, const char *name,
952 const struct nls_table *nls_codepage, int remap)
954 TRANSACTION2_SPI_REQ *pSMB = NULL;
955 TRANSACTION2_SPI_RSP *pSMBr = NULL;
958 int bytes_returned = 0;
959 __u16 params, param_offset, offset, byte_count, count;
961 OPEN_PSX_RSP *psx_rsp;
963 cFYI(1, "In POSIX Create");
965 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
970 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
972 cifsConvertToUCS((__le16 *) pSMB->FileName, name,
973 PATH_MAX, nls_codepage, remap);
974 name_len++; /* trailing null */
976 } else { /* BB improve the check for buffer overruns BB */
977 name_len = strnlen(name, PATH_MAX);
978 name_len++; /* trailing null */
979 strncpy(pSMB->FileName, name, name_len);
982 params = 6 + name_len;
983 count = sizeof(OPEN_PSX_REQ);
984 pSMB->MaxParameterCount = cpu_to_le16(2);
985 pSMB->MaxDataCount = cpu_to_le16(1000); /* large enough */
986 pSMB->MaxSetupCount = 0;
991 param_offset = offsetof(struct smb_com_transaction2_spi_req,
992 InformationLevel) - 4;
993 offset = param_offset + params;
994 pdata = (OPEN_PSX_REQ *)(((char *)&pSMB->hdr.Protocol) + offset);
995 pdata->Level = cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC);
996 pdata->Permissions = cpu_to_le64(mode);
997 pdata->PosixOpenFlags = cpu_to_le32(posix_flags);
998 pdata->OpenFlags = cpu_to_le32(*pOplock);
999 pSMB->ParameterOffset = cpu_to_le16(param_offset);
1000 pSMB->DataOffset = cpu_to_le16(offset);
1001 pSMB->SetupCount = 1;
1002 pSMB->Reserved3 = 0;
1003 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
1004 byte_count = 3 /* pad */ + params + count;
1006 pSMB->DataCount = cpu_to_le16(count);
1007 pSMB->ParameterCount = cpu_to_le16(params);
1008 pSMB->TotalDataCount = pSMB->DataCount;
1009 pSMB->TotalParameterCount = pSMB->ParameterCount;
1010 pSMB->InformationLevel = cpu_to_le16(SMB_POSIX_OPEN);
1011 pSMB->Reserved4 = 0;
1012 pSMB->hdr.smb_buf_length += byte_count;
1013 pSMB->ByteCount = cpu_to_le16(byte_count);
1014 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1015 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1017 cFYI(1, "Posix create returned %d", rc);
1018 goto psx_create_err;
1021 cFYI(1, "copying inode info");
1022 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
1024 if (rc || (pSMBr->ByteCount < sizeof(OPEN_PSX_RSP))) {
1025 rc = -EIO; /* bad smb */
1026 goto psx_create_err;
1029 /* copy return information to pRetData */
1030 psx_rsp = (OPEN_PSX_RSP *)((char *) &pSMBr->hdr.Protocol
1031 + le16_to_cpu(pSMBr->t2.DataOffset));
1033 *pOplock = le16_to_cpu(psx_rsp->OplockFlags);
1035 *netfid = psx_rsp->Fid; /* cifs fid stays in le */
1036 /* Let caller know file was created so we can set the mode. */
1037 /* Do we care about the CreateAction in any other cases? */
1038 if (cpu_to_le32(FILE_CREATE) == psx_rsp->CreateAction)
1039 *pOplock |= CIFS_CREATE_ACTION;
1040 /* check to make sure response data is there */
1041 if (psx_rsp->ReturnedLevel != cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC)) {
1042 pRetData->Type = cpu_to_le32(-1); /* unknown */
1043 cFYI(DBG2, "unknown type");
1045 if (pSMBr->ByteCount < sizeof(OPEN_PSX_RSP)
1046 + sizeof(FILE_UNIX_BASIC_INFO)) {
1047 cERROR(1, "Open response data too small");
1048 pRetData->Type = cpu_to_le32(-1);
1049 goto psx_create_err;
1051 memcpy((char *) pRetData,
1052 (char *)psx_rsp + sizeof(OPEN_PSX_RSP),
1053 sizeof(FILE_UNIX_BASIC_INFO));
1057 cifs_buf_release(pSMB);
1059 if (posix_flags & SMB_O_DIRECTORY)
1060 cifs_stats_inc(&tcon->num_posixmkdirs);
1062 cifs_stats_inc(&tcon->num_posixopens);
1070 static __u16 convert_disposition(int disposition)
1074 switch (disposition) {
1075 case FILE_SUPERSEDE:
1076 ofun = SMBOPEN_OCREATE | SMBOPEN_OTRUNC;
1079 ofun = SMBOPEN_OAPPEND;
1082 ofun = SMBOPEN_OCREATE;
1085 ofun = SMBOPEN_OCREATE | SMBOPEN_OAPPEND;
1087 case FILE_OVERWRITE:
1088 ofun = SMBOPEN_OTRUNC;
1090 case FILE_OVERWRITE_IF:
1091 ofun = SMBOPEN_OCREATE | SMBOPEN_OTRUNC;
1094 cFYI(1, "unknown disposition %d", disposition);
1095 ofun = SMBOPEN_OAPPEND; /* regular open */
1101 access_flags_to_smbopen_mode(const int access_flags)
1103 int masked_flags = access_flags & (GENERIC_READ | GENERIC_WRITE);
1105 if (masked_flags == GENERIC_READ)
1106 return SMBOPEN_READ;
1107 else if (masked_flags == GENERIC_WRITE)
1108 return SMBOPEN_WRITE;
1110 /* just go for read/write */
1111 return SMBOPEN_READWRITE;
1115 SMBLegacyOpen(const int xid, struct cifsTconInfo *tcon,
1116 const char *fileName, const int openDisposition,
1117 const int access_flags, const int create_options, __u16 *netfid,
1118 int *pOplock, FILE_ALL_INFO *pfile_info,
1119 const struct nls_table *nls_codepage, int remap)
1122 OPENX_REQ *pSMB = NULL;
1123 OPENX_RSP *pSMBr = NULL;
1129 rc = smb_init(SMB_COM_OPEN_ANDX, 15, tcon, (void **) &pSMB,
1134 pSMB->AndXCommand = 0xFF; /* none */
1136 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1137 count = 1; /* account for one byte pad to word boundary */
1139 cifsConvertToUCS((__le16 *) (pSMB->fileName + 1),
1140 fileName, PATH_MAX, nls_codepage, remap);
1141 name_len++; /* trailing null */
1143 } else { /* BB improve check for buffer overruns BB */
1144 count = 0; /* no pad */
1145 name_len = strnlen(fileName, PATH_MAX);
1146 name_len++; /* trailing null */
1147 strncpy(pSMB->fileName, fileName, name_len);
1149 if (*pOplock & REQ_OPLOCK)
1150 pSMB->OpenFlags = cpu_to_le16(REQ_OPLOCK);
1151 else if (*pOplock & REQ_BATCHOPLOCK)
1152 pSMB->OpenFlags = cpu_to_le16(REQ_BATCHOPLOCK);
1154 pSMB->OpenFlags |= cpu_to_le16(REQ_MORE_INFO);
1155 pSMB->Mode = cpu_to_le16(access_flags_to_smbopen_mode(access_flags));
1156 pSMB->Mode |= cpu_to_le16(0x40); /* deny none */
1157 /* set file as system file if special file such
1158 as fifo and server expecting SFU style and
1159 no Unix extensions */
1161 if (create_options & CREATE_OPTION_SPECIAL)
1162 pSMB->FileAttributes = cpu_to_le16(ATTR_SYSTEM);
1163 else /* BB FIXME BB */
1164 pSMB->FileAttributes = cpu_to_le16(0/*ATTR_NORMAL*/);
1166 if (create_options & CREATE_OPTION_READONLY)
1167 pSMB->FileAttributes |= cpu_to_le16(ATTR_READONLY);
1170 /* pSMB->CreateOptions = cpu_to_le32(create_options &
1171 CREATE_OPTIONS_MASK); */
1172 /* BB FIXME END BB */
1174 pSMB->Sattr = cpu_to_le16(ATTR_HIDDEN | ATTR_SYSTEM | ATTR_DIRECTORY);
1175 pSMB->OpenFunction = cpu_to_le16(convert_disposition(openDisposition));
1177 pSMB->hdr.smb_buf_length += count;
1179 pSMB->ByteCount = cpu_to_le16(count);
1180 /* long_op set to 1 to allow for oplock break timeouts */
1181 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1182 (struct smb_hdr *)pSMBr, &bytes_returned, CIFS_LONG_OP);
1183 cifs_stats_inc(&tcon->num_opens);
1185 cFYI(1, "Error in Open = %d", rc);
1187 /* BB verify if wct == 15 */
1189 /* *pOplock = pSMBr->OplockLevel; */ /* BB take from action field*/
1191 *netfid = pSMBr->Fid; /* cifs fid stays in le */
1192 /* Let caller know file was created so we can set the mode. */
1193 /* Do we care about the CreateAction in any other cases? */
1195 /* if (cpu_to_le32(FILE_CREATE) == pSMBr->CreateAction)
1196 *pOplock |= CIFS_CREATE_ACTION; */
1200 pfile_info->CreationTime = 0; /* BB convert CreateTime*/
1201 pfile_info->LastAccessTime = 0; /* BB fixme */
1202 pfile_info->LastWriteTime = 0; /* BB fixme */
1203 pfile_info->ChangeTime = 0; /* BB fixme */
1204 pfile_info->Attributes =
1205 cpu_to_le32(le16_to_cpu(pSMBr->FileAttributes));
1206 /* the file_info buf is endian converted by caller */
1207 pfile_info->AllocationSize =
1208 cpu_to_le64(le32_to_cpu(pSMBr->EndOfFile));
1209 pfile_info->EndOfFile = pfile_info->AllocationSize;
1210 pfile_info->NumberOfLinks = cpu_to_le32(1);
1211 pfile_info->DeletePending = 0;
1215 cifs_buf_release(pSMB);
1222 CIFSSMBOpen(const int xid, struct cifsTconInfo *tcon,
1223 const char *fileName, const int openDisposition,
1224 const int access_flags, const int create_options, __u16 *netfid,
1225 int *pOplock, FILE_ALL_INFO *pfile_info,
1226 const struct nls_table *nls_codepage, int remap)
1229 OPEN_REQ *pSMB = NULL;
1230 OPEN_RSP *pSMBr = NULL;
1236 rc = smb_init(SMB_COM_NT_CREATE_ANDX, 24, tcon, (void **) &pSMB,
1241 pSMB->AndXCommand = 0xFF; /* none */
1243 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1244 count = 1; /* account for one byte pad to word boundary */
1246 cifsConvertToUCS((__le16 *) (pSMB->fileName + 1),
1247 fileName, PATH_MAX, nls_codepage, remap);
1248 name_len++; /* trailing null */
1250 pSMB->NameLength = cpu_to_le16(name_len);
1251 } else { /* BB improve check for buffer overruns BB */
1252 count = 0; /* no pad */
1253 name_len = strnlen(fileName, PATH_MAX);
1254 name_len++; /* trailing null */
1255 pSMB->NameLength = cpu_to_le16(name_len);
1256 strncpy(pSMB->fileName, fileName, name_len);
1258 if (*pOplock & REQ_OPLOCK)
1259 pSMB->OpenFlags = cpu_to_le32(REQ_OPLOCK);
1260 else if (*pOplock & REQ_BATCHOPLOCK)
1261 pSMB->OpenFlags = cpu_to_le32(REQ_BATCHOPLOCK);
1262 pSMB->DesiredAccess = cpu_to_le32(access_flags);
1263 pSMB->AllocationSize = 0;
1264 /* set file as system file if special file such
1265 as fifo and server expecting SFU style and
1266 no Unix extensions */
1267 if (create_options & CREATE_OPTION_SPECIAL)
1268 pSMB->FileAttributes = cpu_to_le32(ATTR_SYSTEM);
1270 pSMB->FileAttributes = cpu_to_le32(ATTR_NORMAL);
1272 /* XP does not handle ATTR_POSIX_SEMANTICS */
1273 /* but it helps speed up case sensitive checks for other
1274 servers such as Samba */
1275 if (tcon->ses->capabilities & CAP_UNIX)
1276 pSMB->FileAttributes |= cpu_to_le32(ATTR_POSIX_SEMANTICS);
1278 if (create_options & CREATE_OPTION_READONLY)
1279 pSMB->FileAttributes |= cpu_to_le32(ATTR_READONLY);
1281 pSMB->ShareAccess = cpu_to_le32(FILE_SHARE_ALL);
1282 pSMB->CreateDisposition = cpu_to_le32(openDisposition);
1283 pSMB->CreateOptions = cpu_to_le32(create_options & CREATE_OPTIONS_MASK);
1284 /* BB Expirement with various impersonation levels and verify */
1285 pSMB->ImpersonationLevel = cpu_to_le32(SECURITY_IMPERSONATION);
1286 pSMB->SecurityFlags =
1287 SECURITY_CONTEXT_TRACKING | SECURITY_EFFECTIVE_ONLY;
1290 pSMB->hdr.smb_buf_length += count;
1292 pSMB->ByteCount = cpu_to_le16(count);
1293 /* long_op set to 1 to allow for oplock break timeouts */
1294 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1295 (struct smb_hdr *)pSMBr, &bytes_returned, CIFS_LONG_OP);
1296 cifs_stats_inc(&tcon->num_opens);
1298 cFYI(1, "Error in Open = %d", rc);
1300 *pOplock = pSMBr->OplockLevel; /* 1 byte no need to le_to_cpu */
1301 *netfid = pSMBr->Fid; /* cifs fid stays in le */
1302 /* Let caller know file was created so we can set the mode. */
1303 /* Do we care about the CreateAction in any other cases? */
1304 if (cpu_to_le32(FILE_CREATE) == pSMBr->CreateAction)
1305 *pOplock |= CIFS_CREATE_ACTION;
1307 memcpy((char *)pfile_info, (char *)&pSMBr->CreationTime,
1308 36 /* CreationTime to Attributes */);
1309 /* the file_info buf is endian converted by caller */
1310 pfile_info->AllocationSize = pSMBr->AllocationSize;
1311 pfile_info->EndOfFile = pSMBr->EndOfFile;
1312 pfile_info->NumberOfLinks = cpu_to_le32(1);
1313 pfile_info->DeletePending = 0;
1317 cifs_buf_release(pSMB);
1324 CIFSSMBRead(const int xid, struct cifsTconInfo *tcon, const int netfid,
1325 const unsigned int count, const __u64 lseek, unsigned int *nbytes,
1326 char **buf, int *pbuf_type)
1329 READ_REQ *pSMB = NULL;
1330 READ_RSP *pSMBr = NULL;
1331 char *pReadData = NULL;
1333 int resp_buf_type = 0;
1336 cFYI(1, "Reading %d bytes on fid %d", count, netfid);
1337 if (tcon->ses->capabilities & CAP_LARGE_FILES)
1340 wct = 10; /* old style read */
1341 if ((lseek >> 32) > 0) {
1342 /* can not handle this big offset for old */
1348 rc = small_smb_init(SMB_COM_READ_ANDX, wct, tcon, (void **) &pSMB);
1352 /* tcon and ses pointer are checked in smb_init */
1353 if (tcon->ses->server == NULL)
1354 return -ECONNABORTED;
1356 pSMB->AndXCommand = 0xFF; /* none */
1358 pSMB->OffsetLow = cpu_to_le32(lseek & 0xFFFFFFFF);
1360 pSMB->OffsetHigh = cpu_to_le32(lseek >> 32);
1362 pSMB->Remaining = 0;
1363 pSMB->MaxCount = cpu_to_le16(count & 0xFFFF);
1364 pSMB->MaxCountHigh = cpu_to_le32(count >> 16);
1366 pSMB->ByteCount = 0; /* no need to do le conversion since 0 */
1368 /* old style read */
1369 struct smb_com_readx_req *pSMBW =
1370 (struct smb_com_readx_req *)pSMB;
1371 pSMBW->ByteCount = 0;
1374 iov[0].iov_base = (char *)pSMB;
1375 iov[0].iov_len = pSMB->hdr.smb_buf_length + 4;
1376 rc = SendReceive2(xid, tcon->ses, iov, 1 /* num iovecs */,
1377 &resp_buf_type, CIFS_STD_OP | CIFS_LOG_ERROR);
1378 cifs_stats_inc(&tcon->num_reads);
1379 pSMBr = (READ_RSP *)iov[0].iov_base;
1381 cERROR(1, "Send error in read = %d", rc);
1383 int data_length = le16_to_cpu(pSMBr->DataLengthHigh);
1384 data_length = data_length << 16;
1385 data_length += le16_to_cpu(pSMBr->DataLength);
1386 *nbytes = data_length;
1388 /*check that DataLength would not go beyond end of SMB */
1389 if ((data_length > CIFSMaxBufSize)
1390 || (data_length > count)) {
1391 cFYI(1, "bad length %d for count %d",
1392 data_length, count);
1396 pReadData = (char *) (&pSMBr->hdr.Protocol) +
1397 le16_to_cpu(pSMBr->DataOffset);
1398 /* if (rc = copy_to_user(buf, pReadData, data_length)) {
1399 cERROR(1, "Faulting on read rc = %d",rc);
1401 }*/ /* can not use copy_to_user when using page cache*/
1403 memcpy(*buf, pReadData, data_length);
1407 /* cifs_small_buf_release(pSMB); */ /* Freed earlier now in SendReceive2 */
1409 if (resp_buf_type == CIFS_SMALL_BUFFER)
1410 cifs_small_buf_release(iov[0].iov_base);
1411 else if (resp_buf_type == CIFS_LARGE_BUFFER)
1412 cifs_buf_release(iov[0].iov_base);
1413 } else if (resp_buf_type != CIFS_NO_BUFFER) {
1414 /* return buffer to caller to free */
1415 *buf = iov[0].iov_base;
1416 if (resp_buf_type == CIFS_SMALL_BUFFER)
1417 *pbuf_type = CIFS_SMALL_BUFFER;
1418 else if (resp_buf_type == CIFS_LARGE_BUFFER)
1419 *pbuf_type = CIFS_LARGE_BUFFER;
1420 } /* else no valid buffer on return - leave as null */
1422 /* Note: On -EAGAIN error only caller can retry on handle based calls
1423 since file handle passed in no longer valid */
1429 CIFSSMBWrite(const int xid, struct cifsTconInfo *tcon,
1430 const int netfid, const unsigned int count,
1431 const __u64 offset, unsigned int *nbytes, const char *buf,
1432 const char __user *ubuf, const int long_op)
1435 WRITE_REQ *pSMB = NULL;
1436 WRITE_RSP *pSMBr = NULL;
1437 int bytes_returned, wct;
1443 /* cFYI(1, "write at %lld %d bytes", offset, count);*/
1444 if (tcon->ses == NULL)
1445 return -ECONNABORTED;
1447 if (tcon->ses->capabilities & CAP_LARGE_FILES)
1451 if ((offset >> 32) > 0) {
1452 /* can not handle big offset for old srv */
1457 rc = smb_init(SMB_COM_WRITE_ANDX, wct, tcon, (void **) &pSMB,
1461 /* tcon and ses pointer are checked in smb_init */
1462 if (tcon->ses->server == NULL)
1463 return -ECONNABORTED;
1465 pSMB->AndXCommand = 0xFF; /* none */
1467 pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF);
1469 pSMB->OffsetHigh = cpu_to_le32(offset >> 32);
1471 pSMB->Reserved = 0xFFFFFFFF;
1472 pSMB->WriteMode = 0;
1473 pSMB->Remaining = 0;
1475 /* Can increase buffer size if buffer is big enough in some cases ie we
1476 can send more if LARGE_WRITE_X capability returned by the server and if
1477 our buffer is big enough or if we convert to iovecs on socket writes
1478 and eliminate the copy to the CIFS buffer */
1479 if (tcon->ses->capabilities & CAP_LARGE_WRITE_X) {
1480 bytes_sent = min_t(const unsigned int, CIFSMaxBufSize, count);
1482 bytes_sent = (tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE)
1486 if (bytes_sent > count)
1489 cpu_to_le16(offsetof(struct smb_com_write_req, Data) - 4);
1491 memcpy(pSMB->Data, buf, bytes_sent);
1493 if (copy_from_user(pSMB->Data, ubuf, bytes_sent)) {
1494 cifs_buf_release(pSMB);
1497 } else if (count != 0) {
1499 cifs_buf_release(pSMB);
1501 } /* else setting file size with write of zero bytes */
1503 byte_count = bytes_sent + 1; /* pad */
1504 else /* wct == 12 */
1505 byte_count = bytes_sent + 5; /* bigger pad, smaller smb hdr */
1507 pSMB->DataLengthLow = cpu_to_le16(bytes_sent & 0xFFFF);
1508 pSMB->DataLengthHigh = cpu_to_le16(bytes_sent >> 16);
1509 pSMB->hdr.smb_buf_length += byte_count;
1512 pSMB->ByteCount = cpu_to_le16(byte_count);
1513 else { /* old style write has byte count 4 bytes earlier
1515 struct smb_com_writex_req *pSMBW =
1516 (struct smb_com_writex_req *)pSMB;
1517 pSMBW->ByteCount = cpu_to_le16(byte_count);
1520 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1521 (struct smb_hdr *) pSMBr, &bytes_returned, long_op);
1522 cifs_stats_inc(&tcon->num_writes);
1524 cFYI(1, "Send error in write = %d", rc);
1526 *nbytes = le16_to_cpu(pSMBr->CountHigh);
1527 *nbytes = (*nbytes) << 16;
1528 *nbytes += le16_to_cpu(pSMBr->Count);
1531 * Mask off high 16 bits when bytes written as returned by the
1532 * server is greater than bytes requested by the client. Some
1533 * OS/2 servers are known to set incorrect CountHigh values.
1535 if (*nbytes > count)
1539 cifs_buf_release(pSMB);
1541 /* Note: On -EAGAIN error only caller can retry on handle based calls
1542 since file handle passed in no longer valid */
1548 CIFSSMBWrite2(const int xid, struct cifsTconInfo *tcon,
1549 const int netfid, const unsigned int count,
1550 const __u64 offset, unsigned int *nbytes, struct kvec *iov,
1551 int n_vec, const int long_op)
1554 WRITE_REQ *pSMB = NULL;
1557 int resp_buf_type = 0;
1561 cFYI(1, "write2 at %lld %d bytes", (long long)offset, count);
1563 if (tcon->ses->capabilities & CAP_LARGE_FILES) {
1567 if ((offset >> 32) > 0) {
1568 /* can not handle big offset for old srv */
1572 rc = small_smb_init(SMB_COM_WRITE_ANDX, wct, tcon, (void **) &pSMB);
1575 /* tcon and ses pointer are checked in smb_init */
1576 if (tcon->ses->server == NULL)
1577 return -ECONNABORTED;
1579 pSMB->AndXCommand = 0xFF; /* none */
1581 pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF);
1583 pSMB->OffsetHigh = cpu_to_le32(offset >> 32);
1584 pSMB->Reserved = 0xFFFFFFFF;
1585 pSMB->WriteMode = 0;
1586 pSMB->Remaining = 0;
1589 cpu_to_le16(offsetof(struct smb_com_write_req, Data) - 4);
1591 pSMB->DataLengthLow = cpu_to_le16(count & 0xFFFF);
1592 pSMB->DataLengthHigh = cpu_to_le16(count >> 16);
1593 smb_hdr_len = pSMB->hdr.smb_buf_length + 1; /* hdr + 1 byte pad */
1595 pSMB->hdr.smb_buf_length += count+1;
1596 else /* wct == 12 */
1597 pSMB->hdr.smb_buf_length += count+5; /* smb data starts later */
1599 pSMB->ByteCount = cpu_to_le16(count + 1);
1600 else /* wct == 12 */ /* bigger pad, smaller smb hdr, keep offset ok */ {
1601 struct smb_com_writex_req *pSMBW =
1602 (struct smb_com_writex_req *)pSMB;
1603 pSMBW->ByteCount = cpu_to_le16(count + 5);
1605 iov[0].iov_base = pSMB;
1607 iov[0].iov_len = smb_hdr_len + 4;
1608 else /* wct == 12 pad bigger by four bytes */
1609 iov[0].iov_len = smb_hdr_len + 8;
1612 rc = SendReceive2(xid, tcon->ses, iov, n_vec + 1, &resp_buf_type,
1614 cifs_stats_inc(&tcon->num_writes);
1616 cFYI(1, "Send error Write2 = %d", rc);
1617 } else if (resp_buf_type == 0) {
1618 /* presumably this can not happen, but best to be safe */
1621 WRITE_RSP *pSMBr = (WRITE_RSP *)iov[0].iov_base;
1622 *nbytes = le16_to_cpu(pSMBr->CountHigh);
1623 *nbytes = (*nbytes) << 16;
1624 *nbytes += le16_to_cpu(pSMBr->Count);
1627 * Mask off high 16 bits when bytes written as returned by the
1628 * server is greater than bytes requested by the client. OS/2
1629 * servers are known to set incorrect CountHigh values.
1631 if (*nbytes > count)
1635 /* cifs_small_buf_release(pSMB); */ /* Freed earlier now in SendReceive2 */
1636 if (resp_buf_type == CIFS_SMALL_BUFFER)
1637 cifs_small_buf_release(iov[0].iov_base);
1638 else if (resp_buf_type == CIFS_LARGE_BUFFER)
1639 cifs_buf_release(iov[0].iov_base);
1641 /* Note: On -EAGAIN error only caller can retry on handle based calls
1642 since file handle passed in no longer valid */
1649 CIFSSMBLock(const int xid, struct cifsTconInfo *tcon,
1650 const __u16 smb_file_id, const __u64 len,
1651 const __u64 offset, const __u32 numUnlock,
1652 const __u32 numLock, const __u8 lockType, const bool waitFlag)
1655 LOCK_REQ *pSMB = NULL;
1656 /* LOCK_RSP *pSMBr = NULL; */ /* No response data other than rc to parse */
1661 cFYI(1, "CIFSSMBLock timeout %d numLock %d", (int)waitFlag, numLock);
1662 rc = small_smb_init(SMB_COM_LOCKING_ANDX, 8, tcon, (void **) &pSMB);
1667 if (lockType == LOCKING_ANDX_OPLOCK_RELEASE) {
1668 timeout = CIFS_ASYNC_OP; /* no response expected */
1670 } else if (waitFlag) {
1671 timeout = CIFS_BLOCKING_OP; /* blocking operation, no timeout */
1672 pSMB->Timeout = cpu_to_le32(-1);/* blocking - do not time out */
1677 pSMB->NumberOfLocks = cpu_to_le16(numLock);
1678 pSMB->NumberOfUnlocks = cpu_to_le16(numUnlock);
1679 pSMB->LockType = lockType;
1680 pSMB->AndXCommand = 0xFF; /* none */
1681 pSMB->Fid = smb_file_id; /* netfid stays le */
1683 if ((numLock != 0) || (numUnlock != 0)) {
1684 pSMB->Locks[0].Pid = cpu_to_le16(current->tgid);
1685 /* BB where to store pid high? */
1686 pSMB->Locks[0].LengthLow = cpu_to_le32((u32)len);
1687 pSMB->Locks[0].LengthHigh = cpu_to_le32((u32)(len>>32));
1688 pSMB->Locks[0].OffsetLow = cpu_to_le32((u32)offset);
1689 pSMB->Locks[0].OffsetHigh = cpu_to_le32((u32)(offset>>32));
1690 count = sizeof(LOCKING_ANDX_RANGE);
1695 pSMB->hdr.smb_buf_length += count;
1696 pSMB->ByteCount = cpu_to_le16(count);
1699 rc = SendReceiveBlockingLock(xid, tcon, (struct smb_hdr *) pSMB,
1700 (struct smb_hdr *) pSMB, &bytes_returned);
1701 cifs_small_buf_release(pSMB);
1703 rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *)pSMB,
1705 /* SMB buffer freed by function above */
1707 cifs_stats_inc(&tcon->num_locks);
1709 cFYI(1, "Send error in Lock = %d", rc);
1711 /* Note: On -EAGAIN error only caller can retry on handle based calls
1712 since file handle passed in no longer valid */
1717 CIFSSMBPosixLock(const int xid, struct cifsTconInfo *tcon,
1718 const __u16 smb_file_id, const int get_flag, const __u64 len,
1719 struct file_lock *pLockData, const __u16 lock_type,
1720 const bool waitFlag)
1722 struct smb_com_transaction2_sfi_req *pSMB = NULL;
1723 struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
1724 struct cifs_posix_lock *parm_data;
1727 int bytes_returned = 0;
1728 int resp_buf_type = 0;
1729 __u16 params, param_offset, offset, byte_count, count;
1732 cFYI(1, "Posix Lock");
1734 if (pLockData == NULL)
1737 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
1742 pSMBr = (struct smb_com_transaction2_sfi_rsp *)pSMB;
1745 pSMB->MaxSetupCount = 0;
1748 pSMB->Reserved2 = 0;
1749 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
1750 offset = param_offset + params;
1752 count = sizeof(struct cifs_posix_lock);
1753 pSMB->MaxParameterCount = cpu_to_le16(2);
1754 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB from sess */
1755 pSMB->SetupCount = 1;
1756 pSMB->Reserved3 = 0;
1758 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION);
1760 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
1761 byte_count = 3 /* pad */ + params + count;
1762 pSMB->DataCount = cpu_to_le16(count);
1763 pSMB->ParameterCount = cpu_to_le16(params);
1764 pSMB->TotalDataCount = pSMB->DataCount;
1765 pSMB->TotalParameterCount = pSMB->ParameterCount;
1766 pSMB->ParameterOffset = cpu_to_le16(param_offset);
1767 parm_data = (struct cifs_posix_lock *)
1768 (((char *) &pSMB->hdr.Protocol) + offset);
1770 parm_data->lock_type = cpu_to_le16(lock_type);
1772 timeout = CIFS_BLOCKING_OP; /* blocking operation, no timeout */
1773 parm_data->lock_flags = cpu_to_le16(1);
1774 pSMB->Timeout = cpu_to_le32(-1);
1778 parm_data->pid = cpu_to_le32(current->tgid);
1779 parm_data->start = cpu_to_le64(pLockData->fl_start);
1780 parm_data->length = cpu_to_le64(len); /* normalize negative numbers */
1782 pSMB->DataOffset = cpu_to_le16(offset);
1783 pSMB->Fid = smb_file_id;
1784 pSMB->InformationLevel = cpu_to_le16(SMB_SET_POSIX_LOCK);
1785 pSMB->Reserved4 = 0;
1786 pSMB->hdr.smb_buf_length += byte_count;
1787 pSMB->ByteCount = cpu_to_le16(byte_count);
1789 rc = SendReceiveBlockingLock(xid, tcon, (struct smb_hdr *) pSMB,
1790 (struct smb_hdr *) pSMBr, &bytes_returned);
1792 iov[0].iov_base = (char *)pSMB;
1793 iov[0].iov_len = pSMB->hdr.smb_buf_length + 4;
1794 rc = SendReceive2(xid, tcon->ses, iov, 1 /* num iovecs */,
1795 &resp_buf_type, timeout);
1796 pSMB = NULL; /* request buf already freed by SendReceive2. Do
1797 not try to free it twice below on exit */
1798 pSMBr = (struct smb_com_transaction2_sfi_rsp *)iov[0].iov_base;
1802 cFYI(1, "Send error in Posix Lock = %d", rc);
1803 } else if (get_flag) {
1804 /* lock structure can be returned on get */
1807 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
1809 if (rc || (pSMBr->ByteCount < sizeof(struct cifs_posix_lock))) {
1810 rc = -EIO; /* bad smb */
1813 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
1814 data_count = le16_to_cpu(pSMBr->t2.DataCount);
1815 if (data_count < sizeof(struct cifs_posix_lock)) {
1819 parm_data = (struct cifs_posix_lock *)
1820 ((char *)&pSMBr->hdr.Protocol + data_offset);
1821 if (parm_data->lock_type == __constant_cpu_to_le16(CIFS_UNLCK))
1822 pLockData->fl_type = F_UNLCK;
1824 if (parm_data->lock_type ==
1825 __constant_cpu_to_le16(CIFS_RDLCK))
1826 pLockData->fl_type = F_RDLCK;
1827 else if (parm_data->lock_type ==
1828 __constant_cpu_to_le16(CIFS_WRLCK))
1829 pLockData->fl_type = F_WRLCK;
1831 pLockData->fl_start = parm_data->start;
1832 pLockData->fl_end = parm_data->start +
1833 parm_data->length - 1;
1834 pLockData->fl_pid = parm_data->pid;
1840 cifs_small_buf_release(pSMB);
1842 if (resp_buf_type == CIFS_SMALL_BUFFER)
1843 cifs_small_buf_release(iov[0].iov_base);
1844 else if (resp_buf_type == CIFS_LARGE_BUFFER)
1845 cifs_buf_release(iov[0].iov_base);
1847 /* Note: On -EAGAIN error only caller can retry on handle based calls
1848 since file handle passed in no longer valid */
1855 CIFSSMBClose(const int xid, struct cifsTconInfo *tcon, int smb_file_id)
1858 CLOSE_REQ *pSMB = NULL;
1859 cFYI(1, "In CIFSSMBClose");
1861 /* do not retry on dead session on close */
1862 rc = small_smb_init(SMB_COM_CLOSE, 3, tcon, (void **) &pSMB);
1868 pSMB->FileID = (__u16) smb_file_id;
1869 pSMB->LastWriteTime = 0xFFFFFFFF;
1870 pSMB->ByteCount = 0;
1871 rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0);
1872 cifs_stats_inc(&tcon->num_closes);
1875 /* EINTR is expected when user ctl-c to kill app */
1876 cERROR(1, "Send error in Close = %d", rc);
1880 /* Since session is dead, file will be closed on server already */
1888 CIFSSMBFlush(const int xid, struct cifsTconInfo *tcon, int smb_file_id)
1891 FLUSH_REQ *pSMB = NULL;
1892 cFYI(1, "In CIFSSMBFlush");
1894 rc = small_smb_init(SMB_COM_FLUSH, 1, tcon, (void **) &pSMB);
1898 pSMB->FileID = (__u16) smb_file_id;
1899 pSMB->ByteCount = 0;
1900 rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0);
1901 cifs_stats_inc(&tcon->num_flushes);
1903 cERROR(1, "Send error in Flush = %d", rc);
1909 CIFSSMBRename(const int xid, struct cifsTconInfo *tcon,
1910 const char *fromName, const char *toName,
1911 const struct nls_table *nls_codepage, int remap)
1914 RENAME_REQ *pSMB = NULL;
1915 RENAME_RSP *pSMBr = NULL;
1917 int name_len, name_len2;
1920 cFYI(1, "In CIFSSMBRename");
1922 rc = smb_init(SMB_COM_RENAME, 1, tcon, (void **) &pSMB,
1927 pSMB->BufferFormat = 0x04;
1928 pSMB->SearchAttributes =
1929 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
1932 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1934 cifsConvertToUCS((__le16 *) pSMB->OldFileName, fromName,
1935 PATH_MAX, nls_codepage, remap);
1936 name_len++; /* trailing null */
1938 pSMB->OldFileName[name_len] = 0x04; /* pad */
1939 /* protocol requires ASCII signature byte on Unicode string */
1940 pSMB->OldFileName[name_len + 1] = 0x00;
1942 cifsConvertToUCS((__le16 *)&pSMB->OldFileName[name_len + 2],
1943 toName, PATH_MAX, nls_codepage, remap);
1944 name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
1945 name_len2 *= 2; /* convert to bytes */
1946 } else { /* BB improve the check for buffer overruns BB */
1947 name_len = strnlen(fromName, PATH_MAX);
1948 name_len++; /* trailing null */
1949 strncpy(pSMB->OldFileName, fromName, name_len);
1950 name_len2 = strnlen(toName, PATH_MAX);
1951 name_len2++; /* trailing null */
1952 pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */
1953 strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2);
1954 name_len2++; /* trailing null */
1955 name_len2++; /* signature byte */
1958 count = 1 /* 1st signature byte */ + name_len + name_len2;
1959 pSMB->hdr.smb_buf_length += count;
1960 pSMB->ByteCount = cpu_to_le16(count);
1962 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1963 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1964 cifs_stats_inc(&tcon->num_renames);
1966 cFYI(1, "Send error in rename = %d", rc);
1968 cifs_buf_release(pSMB);
1976 int CIFSSMBRenameOpenFile(const int xid, struct cifsTconInfo *pTcon,
1977 int netfid, const char *target_name,
1978 const struct nls_table *nls_codepage, int remap)
1980 struct smb_com_transaction2_sfi_req *pSMB = NULL;
1981 struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
1982 struct set_file_rename *rename_info;
1984 char dummy_string[30];
1986 int bytes_returned = 0;
1988 __u16 params, param_offset, offset, count, byte_count;
1990 cFYI(1, "Rename to File by handle");
1991 rc = smb_init(SMB_COM_TRANSACTION2, 15, pTcon, (void **) &pSMB,
1997 pSMB->MaxSetupCount = 0;
2001 pSMB->Reserved2 = 0;
2002 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
2003 offset = param_offset + params;
2005 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
2006 rename_info = (struct set_file_rename *) data_offset;
2007 pSMB->MaxParameterCount = cpu_to_le16(2);
2008 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB from sess */
2009 pSMB->SetupCount = 1;
2010 pSMB->Reserved3 = 0;
2011 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
2012 byte_count = 3 /* pad */ + params;
2013 pSMB->ParameterCount = cpu_to_le16(params);
2014 pSMB->TotalParameterCount = pSMB->ParameterCount;
2015 pSMB->ParameterOffset = cpu_to_le16(param_offset);
2016 pSMB->DataOffset = cpu_to_le16(offset);
2017 /* construct random name ".cifs_tmp<inodenum><mid>" */
2018 rename_info->overwrite = cpu_to_le32(1);
2019 rename_info->root_fid = 0;
2020 /* unicode only call */
2021 if (target_name == NULL) {
2022 sprintf(dummy_string, "cifs%x", pSMB->hdr.Mid);
2023 len_of_str = cifsConvertToUCS((__le16 *)rename_info->target_name,
2024 dummy_string, 24, nls_codepage, remap);
2026 len_of_str = cifsConvertToUCS((__le16 *)rename_info->target_name,
2027 target_name, PATH_MAX, nls_codepage,
2030 rename_info->target_name_len = cpu_to_le32(2 * len_of_str);
2031 count = 12 /* sizeof(struct set_file_rename) */ + (2 * len_of_str);
2032 byte_count += count;
2033 pSMB->DataCount = cpu_to_le16(count);
2034 pSMB->TotalDataCount = pSMB->DataCount;
2036 pSMB->InformationLevel =
2037 cpu_to_le16(SMB_SET_FILE_RENAME_INFORMATION);
2038 pSMB->Reserved4 = 0;
2039 pSMB->hdr.smb_buf_length += byte_count;
2040 pSMB->ByteCount = cpu_to_le16(byte_count);
2041 rc = SendReceive(xid, pTcon->ses, (struct smb_hdr *) pSMB,
2042 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2043 cifs_stats_inc(&pTcon->num_t2renames);
2045 cFYI(1, "Send error in Rename (by file handle) = %d", rc);
2047 cifs_buf_release(pSMB);
2049 /* Note: On -EAGAIN error only caller can retry on handle based calls
2050 since file handle passed in no longer valid */
2056 CIFSSMBCopy(const int xid, struct cifsTconInfo *tcon, const char *fromName,
2057 const __u16 target_tid, const char *toName, const int flags,
2058 const struct nls_table *nls_codepage, int remap)
2061 COPY_REQ *pSMB = NULL;
2062 COPY_RSP *pSMBr = NULL;
2064 int name_len, name_len2;
2067 cFYI(1, "In CIFSSMBCopy");
2069 rc = smb_init(SMB_COM_COPY, 1, tcon, (void **) &pSMB,
2074 pSMB->BufferFormat = 0x04;
2075 pSMB->Tid2 = target_tid;
2077 pSMB->Flags = cpu_to_le16(flags & COPY_TREE);
2079 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2080 name_len = cifsConvertToUCS((__le16 *) pSMB->OldFileName,
2081 fromName, PATH_MAX, nls_codepage,
2083 name_len++; /* trailing null */
2085 pSMB->OldFileName[name_len] = 0x04; /* pad */
2086 /* protocol requires ASCII signature byte on Unicode string */
2087 pSMB->OldFileName[name_len + 1] = 0x00;
2089 cifsConvertToUCS((__le16 *)&pSMB->OldFileName[name_len + 2],
2090 toName, PATH_MAX, nls_codepage, remap);
2091 name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
2092 name_len2 *= 2; /* convert to bytes */
2093 } else { /* BB improve the check for buffer overruns BB */
2094 name_len = strnlen(fromName, PATH_MAX);
2095 name_len++; /* trailing null */
2096 strncpy(pSMB->OldFileName, fromName, name_len);
2097 name_len2 = strnlen(toName, PATH_MAX);
2098 name_len2++; /* trailing null */
2099 pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */
2100 strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2);
2101 name_len2++; /* trailing null */
2102 name_len2++; /* signature byte */
2105 count = 1 /* 1st signature byte */ + name_len + name_len2;
2106 pSMB->hdr.smb_buf_length += count;
2107 pSMB->ByteCount = cpu_to_le16(count);
2109 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2110 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2112 cFYI(1, "Send error in copy = %d with %d files copied",
2113 rc, le16_to_cpu(pSMBr->CopyCount));
2115 cifs_buf_release(pSMB);
2124 CIFSUnixCreateSymLink(const int xid, struct cifsTconInfo *tcon,
2125 const char *fromName, const char *toName,
2126 const struct nls_table *nls_codepage)
2128 TRANSACTION2_SPI_REQ *pSMB = NULL;
2129 TRANSACTION2_SPI_RSP *pSMBr = NULL;
2132 int name_len_target;
2134 int bytes_returned = 0;
2135 __u16 params, param_offset, offset, byte_count;
2137 cFYI(1, "In Symlink Unix style");
2139 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2144 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2146 cifs_strtoUCS((__le16 *) pSMB->FileName, fromName, PATH_MAX
2147 /* find define for this maxpathcomponent */
2149 name_len++; /* trailing null */
2152 } else { /* BB improve the check for buffer overruns BB */
2153 name_len = strnlen(fromName, PATH_MAX);
2154 name_len++; /* trailing null */
2155 strncpy(pSMB->FileName, fromName, name_len);
2157 params = 6 + name_len;
2158 pSMB->MaxSetupCount = 0;
2162 pSMB->Reserved2 = 0;
2163 param_offset = offsetof(struct smb_com_transaction2_spi_req,
2164 InformationLevel) - 4;
2165 offset = param_offset + params;
2167 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
2168 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2170 cifs_strtoUCS((__le16 *) data_offset, toName, PATH_MAX
2171 /* find define for this maxpathcomponent */
2173 name_len_target++; /* trailing null */
2174 name_len_target *= 2;
2175 } else { /* BB improve the check for buffer overruns BB */
2176 name_len_target = strnlen(toName, PATH_MAX);
2177 name_len_target++; /* trailing null */
2178 strncpy(data_offset, toName, name_len_target);
2181 pSMB->MaxParameterCount = cpu_to_le16(2);
2182 /* BB find exact max on data count below from sess */
2183 pSMB->MaxDataCount = cpu_to_le16(1000);
2184 pSMB->SetupCount = 1;
2185 pSMB->Reserved3 = 0;
2186 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
2187 byte_count = 3 /* pad */ + params + name_len_target;
2188 pSMB->DataCount = cpu_to_le16(name_len_target);
2189 pSMB->ParameterCount = cpu_to_le16(params);
2190 pSMB->TotalDataCount = pSMB->DataCount;
2191 pSMB->TotalParameterCount = pSMB->ParameterCount;
2192 pSMB->ParameterOffset = cpu_to_le16(param_offset);
2193 pSMB->DataOffset = cpu_to_le16(offset);
2194 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_LINK);
2195 pSMB->Reserved4 = 0;
2196 pSMB->hdr.smb_buf_length += byte_count;
2197 pSMB->ByteCount = cpu_to_le16(byte_count);
2198 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2199 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2200 cifs_stats_inc(&tcon->num_symlinks);
2202 cFYI(1, "Send error in SetPathInfo create symlink = %d", rc);
2204 cifs_buf_release(pSMB);
2207 goto createSymLinkRetry;
2213 CIFSUnixCreateHardLink(const int xid, struct cifsTconInfo *tcon,
2214 const char *fromName, const char *toName,
2215 const struct nls_table *nls_codepage, int remap)
2217 TRANSACTION2_SPI_REQ *pSMB = NULL;
2218 TRANSACTION2_SPI_RSP *pSMBr = NULL;
2221 int name_len_target;
2223 int bytes_returned = 0;
2224 __u16 params, param_offset, offset, byte_count;
2226 cFYI(1, "In Create Hard link Unix style");
2227 createHardLinkRetry:
2228 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2233 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2234 name_len = cifsConvertToUCS((__le16 *) pSMB->FileName, toName,
2235 PATH_MAX, nls_codepage, remap);
2236 name_len++; /* trailing null */
2239 } else { /* BB improve the check for buffer overruns BB */
2240 name_len = strnlen(toName, PATH_MAX);
2241 name_len++; /* trailing null */
2242 strncpy(pSMB->FileName, toName, name_len);
2244 params = 6 + name_len;
2245 pSMB->MaxSetupCount = 0;
2249 pSMB->Reserved2 = 0;
2250 param_offset = offsetof(struct smb_com_transaction2_spi_req,
2251 InformationLevel) - 4;
2252 offset = param_offset + params;
2254 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
2255 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2257 cifsConvertToUCS((__le16 *) data_offset, fromName, PATH_MAX,
2258 nls_codepage, remap);
2259 name_len_target++; /* trailing null */
2260 name_len_target *= 2;
2261 } else { /* BB improve the check for buffer overruns BB */
2262 name_len_target = strnlen(fromName, PATH_MAX);
2263 name_len_target++; /* trailing null */
2264 strncpy(data_offset, fromName, name_len_target);
2267 pSMB->MaxParameterCount = cpu_to_le16(2);
2268 /* BB find exact max on data count below from sess*/
2269 pSMB->MaxDataCount = cpu_to_le16(1000);
2270 pSMB->SetupCount = 1;
2271 pSMB->Reserved3 = 0;
2272 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
2273 byte_count = 3 /* pad */ + params + name_len_target;
2274 pSMB->ParameterCount = cpu_to_le16(params);
2275 pSMB->TotalParameterCount = pSMB->ParameterCount;
2276 pSMB->DataCount = cpu_to_le16(name_len_target);
2277 pSMB->TotalDataCount = pSMB->DataCount;
2278 pSMB->ParameterOffset = cpu_to_le16(param_offset);
2279 pSMB->DataOffset = cpu_to_le16(offset);
2280 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_HLINK);
2281 pSMB->Reserved4 = 0;
2282 pSMB->hdr.smb_buf_length += byte_count;
2283 pSMB->ByteCount = cpu_to_le16(byte_count);
2284 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2285 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2286 cifs_stats_inc(&tcon->num_hardlinks);
2288 cFYI(1, "Send error in SetPathInfo (hard link) = %d", rc);
2290 cifs_buf_release(pSMB);
2292 goto createHardLinkRetry;
2298 CIFSCreateHardLink(const int xid, struct cifsTconInfo *tcon,
2299 const char *fromName, const char *toName,
2300 const struct nls_table *nls_codepage, int remap)
2303 NT_RENAME_REQ *pSMB = NULL;
2304 RENAME_RSP *pSMBr = NULL;
2306 int name_len, name_len2;
2309 cFYI(1, "In CIFSCreateHardLink");
2310 winCreateHardLinkRetry:
2312 rc = smb_init(SMB_COM_NT_RENAME, 4, tcon, (void **) &pSMB,
2317 pSMB->SearchAttributes =
2318 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
2320 pSMB->Flags = cpu_to_le16(CREATE_HARD_LINK);
2321 pSMB->ClusterCount = 0;
2323 pSMB->BufferFormat = 0x04;
2325 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2327 cifsConvertToUCS((__le16 *) pSMB->OldFileName, fromName,
2328 PATH_MAX, nls_codepage, remap);
2329 name_len++; /* trailing null */
2332 /* protocol specifies ASCII buffer format (0x04) for unicode */
2333 pSMB->OldFileName[name_len] = 0x04;
2334 pSMB->OldFileName[name_len + 1] = 0x00; /* pad */
2336 cifsConvertToUCS((__le16 *)&pSMB->OldFileName[name_len + 2],
2337 toName, PATH_MAX, nls_codepage, remap);
2338 name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
2339 name_len2 *= 2; /* convert to bytes */
2340 } else { /* BB improve the check for buffer overruns BB */
2341 name_len = strnlen(fromName, PATH_MAX);
2342 name_len++; /* trailing null */
2343 strncpy(pSMB->OldFileName, fromName, name_len);
2344 name_len2 = strnlen(toName, PATH_MAX);
2345 name_len2++; /* trailing null */
2346 pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */
2347 strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2);
2348 name_len2++; /* trailing null */
2349 name_len2++; /* signature byte */
2352 count = 1 /* string type byte */ + name_len + name_len2;
2353 pSMB->hdr.smb_buf_length += count;
2354 pSMB->ByteCount = cpu_to_le16(count);
2356 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2357 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2358 cifs_stats_inc(&tcon->num_hardlinks);
2360 cFYI(1, "Send error in hard link (NT rename) = %d", rc);
2362 cifs_buf_release(pSMB);
2364 goto winCreateHardLinkRetry;
2370 CIFSSMBUnixQuerySymLink(const int xid, struct cifsTconInfo *tcon,
2371 const unsigned char *searchName, char **symlinkinfo,
2372 const struct nls_table *nls_codepage)
2374 /* SMB_QUERY_FILE_UNIX_LINK */
2375 TRANSACTION2_QPI_REQ *pSMB = NULL;
2376 TRANSACTION2_QPI_RSP *pSMBr = NULL;
2380 __u16 params, byte_count;
2383 cFYI(1, "In QPathSymLinkInfo (Unix) for path %s", searchName);
2386 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2391 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2393 cifs_strtoUCS((__le16 *) pSMB->FileName, searchName,
2394 PATH_MAX, nls_codepage);
2395 name_len++; /* trailing null */
2397 } else { /* BB improve the check for buffer overruns BB */
2398 name_len = strnlen(searchName, PATH_MAX);
2399 name_len++; /* trailing null */
2400 strncpy(pSMB->FileName, searchName, name_len);
2403 params = 2 /* level */ + 4 /* rsrvd */ + name_len /* incl null */ ;
2404 pSMB->TotalDataCount = 0;
2405 pSMB->MaxParameterCount = cpu_to_le16(2);
2406 pSMB->MaxDataCount = cpu_to_le16(CIFSMaxBufSize);
2407 pSMB->MaxSetupCount = 0;
2411 pSMB->Reserved2 = 0;
2412 pSMB->ParameterOffset = cpu_to_le16(offsetof(
2413 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
2414 pSMB->DataCount = 0;
2415 pSMB->DataOffset = 0;
2416 pSMB->SetupCount = 1;
2417 pSMB->Reserved3 = 0;
2418 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
2419 byte_count = params + 1 /* pad */ ;
2420 pSMB->TotalParameterCount = cpu_to_le16(params);
2421 pSMB->ParameterCount = pSMB->TotalParameterCount;
2422 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_LINK);
2423 pSMB->Reserved4 = 0;
2424 pSMB->hdr.smb_buf_length += byte_count;
2425 pSMB->ByteCount = cpu_to_le16(byte_count);
2427 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2428 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2430 cFYI(1, "Send error in QuerySymLinkInfo = %d", rc);
2432 /* decode response */
2434 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
2435 /* BB also check enough total bytes returned */
2436 if (rc || (pSMBr->ByteCount < 2))
2440 u16 count = le16_to_cpu(pSMBr->t2.DataCount);
2442 data_start = ((char *) &pSMBr->hdr.Protocol) +
2443 le16_to_cpu(pSMBr->t2.DataOffset);
2445 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
2450 /* BB FIXME investigate remapping reserved chars here */
2451 *symlinkinfo = cifs_strndup_from_ucs(data_start, count,
2452 is_unicode, nls_codepage);
2457 cifs_buf_release(pSMB);
2459 goto querySymLinkRetry;
2463 #ifdef CONFIG_CIFS_EXPERIMENTAL
2464 /* Initialize NT TRANSACT SMB into small smb request buffer.
2465 This assumes that all NT TRANSACTS that we init here have
2466 total parm and data under about 400 bytes (to fit in small cifs
2467 buffer size), which is the case so far, it easily fits. NB:
2468 Setup words themselves and ByteCount
2469 MaxSetupCount (size of returned setup area) and
2470 MaxParameterCount (returned parms size) must be set by caller */
2472 smb_init_nttransact(const __u16 sub_command, const int setup_count,
2473 const int parm_len, struct cifsTconInfo *tcon,
2478 struct smb_com_ntransact_req *pSMB;
2480 rc = small_smb_init(SMB_COM_NT_TRANSACT, 19 + setup_count, tcon,
2484 *ret_buf = (void *)pSMB;
2486 pSMB->TotalParameterCount = cpu_to_le32(parm_len);
2487 pSMB->TotalDataCount = 0;
2488 pSMB->MaxDataCount = cpu_to_le32((tcon->ses->server->maxBuf -
2489 MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
2490 pSMB->ParameterCount = pSMB->TotalParameterCount;
2491 pSMB->DataCount = pSMB->TotalDataCount;
2492 temp_offset = offsetof(struct smb_com_ntransact_req, Parms) +
2493 (setup_count * 2) - 4 /* for rfc1001 length itself */;
2494 pSMB->ParameterOffset = cpu_to_le32(temp_offset);
2495 pSMB->DataOffset = cpu_to_le32(temp_offset + parm_len);
2496 pSMB->SetupCount = setup_count; /* no need to le convert byte fields */
2497 pSMB->SubCommand = cpu_to_le16(sub_command);
2502 validate_ntransact(char *buf, char **ppparm, char **ppdata,
2503 __u32 *pparmlen, __u32 *pdatalen)
2506 __u32 data_count, data_offset, parm_count, parm_offset;
2507 struct smb_com_ntransact_rsp *pSMBr;
2515 pSMBr = (struct smb_com_ntransact_rsp *)buf;
2517 /* ByteCount was converted from little endian in SendReceive */
2518 end_of_smb = 2 /* sizeof byte count */ + pSMBr->ByteCount +
2519 (char *)&pSMBr->ByteCount;
2521 data_offset = le32_to_cpu(pSMBr->DataOffset);
2522 data_count = le32_to_cpu(pSMBr->DataCount);
2523 parm_offset = le32_to_cpu(pSMBr->ParameterOffset);
2524 parm_count = le32_to_cpu(pSMBr->ParameterCount);
2526 *ppparm = (char *)&pSMBr->hdr.Protocol + parm_offset;
2527 *ppdata = (char *)&pSMBr->hdr.Protocol + data_offset;
2529 /* should we also check that parm and data areas do not overlap? */
2530 if (*ppparm > end_of_smb) {
2531 cFYI(1, "parms start after end of smb");
2533 } else if (parm_count + *ppparm > end_of_smb) {
2534 cFYI(1, "parm end after end of smb");
2536 } else if (*ppdata > end_of_smb) {
2537 cFYI(1, "data starts after end of smb");
2539 } else if (data_count + *ppdata > end_of_smb) {
2540 cFYI(1, "data %p + count %d (%p) past smb end %p start %p",
2541 *ppdata, data_count, (data_count + *ppdata),
2544 } else if (parm_count + data_count > pSMBr->ByteCount) {
2545 cFYI(1, "parm count and data count larger than SMB");
2548 *pdatalen = data_count;
2549 *pparmlen = parm_count;
2554 CIFSSMBQueryReparseLinkInfo(const int xid, struct cifsTconInfo *tcon,
2555 const unsigned char *searchName,
2556 char *symlinkinfo, const int buflen, __u16 fid,
2557 const struct nls_table *nls_codepage)
2561 struct smb_com_transaction_ioctl_req *pSMB;
2562 struct smb_com_transaction_ioctl_rsp *pSMBr;
2564 cFYI(1, "In Windows reparse style QueryLink for path %s", searchName);
2565 rc = smb_init(SMB_COM_NT_TRANSACT, 23, tcon, (void **) &pSMB,
2570 pSMB->TotalParameterCount = 0 ;
2571 pSMB->TotalDataCount = 0;
2572 pSMB->MaxParameterCount = cpu_to_le32(2);
2573 /* BB find exact data count max from sess structure BB */
2574 pSMB->MaxDataCount = cpu_to_le32((tcon->ses->server->maxBuf -
2575 MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
2576 pSMB->MaxSetupCount = 4;
2578 pSMB->ParameterOffset = 0;
2579 pSMB->DataCount = 0;
2580 pSMB->DataOffset = 0;
2581 pSMB->SetupCount = 4;
2582 pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_IOCTL);
2583 pSMB->ParameterCount = pSMB->TotalParameterCount;
2584 pSMB->FunctionCode = cpu_to_le32(FSCTL_GET_REPARSE_POINT);
2585 pSMB->IsFsctl = 1; /* FSCTL */
2586 pSMB->IsRootFlag = 0;
2587 pSMB->Fid = fid; /* file handle always le */
2588 pSMB->ByteCount = 0;
2590 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2591 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2593 cFYI(1, "Send error in QueryReparseLinkInfo = %d", rc);
2594 } else { /* decode response */
2595 __u32 data_offset = le32_to_cpu(pSMBr->DataOffset);
2596 __u32 data_count = le32_to_cpu(pSMBr->DataCount);
2597 if ((pSMBr->ByteCount < 2) || (data_offset > 512)) {
2598 /* BB also check enough total bytes returned */
2599 rc = -EIO; /* bad smb */
2602 if (data_count && (data_count < 2048)) {
2603 char *end_of_smb = 2 /* sizeof byte count */ +
2604 pSMBr->ByteCount + (char *)&pSMBr->ByteCount;
2606 struct reparse_data *reparse_buf =
2607 (struct reparse_data *)
2608 ((char *)&pSMBr->hdr.Protocol
2610 if ((char *)reparse_buf >= end_of_smb) {
2614 if ((reparse_buf->LinkNamesBuf +
2615 reparse_buf->TargetNameOffset +
2616 reparse_buf->TargetNameLen) > end_of_smb) {
2617 cFYI(1, "reparse buf beyond SMB");
2622 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
2623 cifs_from_ucs2(symlinkinfo, (__le16 *)
2624 (reparse_buf->LinkNamesBuf +
2625 reparse_buf->TargetNameOffset),
2627 reparse_buf->TargetNameLen,
2629 } else { /* ASCII names */
2630 strncpy(symlinkinfo,
2631 reparse_buf->LinkNamesBuf +
2632 reparse_buf->TargetNameOffset,
2633 min_t(const int, buflen,
2634 reparse_buf->TargetNameLen));
2638 cFYI(1, "Invalid return data count on "
2639 "get reparse info ioctl");
2641 symlinkinfo[buflen] = 0; /* just in case so the caller
2642 does not go off the end of the buffer */
2643 cFYI(1, "readlink result - %s", symlinkinfo);
2647 cifs_buf_release(pSMB);
2649 /* Note: On -EAGAIN error only caller can retry on handle based calls
2650 since file handle passed in no longer valid */
2654 #endif /* CIFS_EXPERIMENTAL */
2656 #ifdef CONFIG_CIFS_POSIX
2658 /*Convert an Access Control Entry from wire format to local POSIX xattr format*/
2659 static void cifs_convert_ace(posix_acl_xattr_entry *ace,
2660 struct cifs_posix_ace *cifs_ace)
2662 /* u8 cifs fields do not need le conversion */
2663 ace->e_perm = cpu_to_le16(cifs_ace->cifs_e_perm);
2664 ace->e_tag = cpu_to_le16(cifs_ace->cifs_e_tag);
2665 ace->e_id = cpu_to_le32(le64_to_cpu(cifs_ace->cifs_uid));
2666 /* cFYI(1, "perm %d tag %d id %d",ace->e_perm,ace->e_tag,ace->e_id); */
2671 /* Convert ACL from CIFS POSIX wire format to local Linux POSIX ACL xattr */
2672 static int cifs_copy_posix_acl(char *trgt, char *src, const int buflen,
2673 const int acl_type, const int size_of_data_area)
2678 struct cifs_posix_ace *pACE;
2679 struct cifs_posix_acl *cifs_acl = (struct cifs_posix_acl *)src;
2680 posix_acl_xattr_header *local_acl = (posix_acl_xattr_header *)trgt;
2682 if (le16_to_cpu(cifs_acl->version) != CIFS_ACL_VERSION)
2685 if (acl_type & ACL_TYPE_ACCESS) {
2686 count = le16_to_cpu(cifs_acl->access_entry_count);
2687 pACE = &cifs_acl->ace_array[0];
2688 size = sizeof(struct cifs_posix_acl);
2689 size += sizeof(struct cifs_posix_ace) * count;
2690 /* check if we would go beyond end of SMB */
2691 if (size_of_data_area < size) {
2692 cFYI(1, "bad CIFS POSIX ACL size %d vs. %d",
2693 size_of_data_area, size);
2696 } else if (acl_type & ACL_TYPE_DEFAULT) {
2697 count = le16_to_cpu(cifs_acl->access_entry_count);
2698 size = sizeof(struct cifs_posix_acl);
2699 size += sizeof(struct cifs_posix_ace) * count;
2700 /* skip past access ACEs to get to default ACEs */
2701 pACE = &cifs_acl->ace_array[count];
2702 count = le16_to_cpu(cifs_acl->default_entry_count);
2703 size += sizeof(struct cifs_posix_ace) * count;
2704 /* check if we would go beyond end of SMB */
2705 if (size_of_data_area < size)
2712 size = posix_acl_xattr_size(count);
2713 if ((buflen == 0) || (local_acl == NULL)) {
2714 /* used to query ACL EA size */
2715 } else if (size > buflen) {
2717 } else /* buffer big enough */ {
2718 local_acl->a_version = cpu_to_le32(POSIX_ACL_XATTR_VERSION);
2719 for (i = 0; i < count ; i++) {
2720 cifs_convert_ace(&local_acl->a_entries[i], pACE);
2727 static __u16 convert_ace_to_cifs_ace(struct cifs_posix_ace *cifs_ace,
2728 const posix_acl_xattr_entry *local_ace)
2730 __u16 rc = 0; /* 0 = ACL converted ok */
2732 cifs_ace->cifs_e_perm = le16_to_cpu(local_ace->e_perm);
2733 cifs_ace->cifs_e_tag = le16_to_cpu(local_ace->e_tag);
2734 /* BB is there a better way to handle the large uid? */
2735 if (local_ace->e_id == cpu_to_le32(-1)) {
2736 /* Probably no need to le convert -1 on any arch but can not hurt */
2737 cifs_ace->cifs_uid = cpu_to_le64(-1);
2739 cifs_ace->cifs_uid = cpu_to_le64(le32_to_cpu(local_ace->e_id));
2740 /*cFYI(1, "perm %d tag %d id %d",ace->e_perm,ace->e_tag,ace->e_id);*/
2744 /* Convert ACL from local Linux POSIX xattr to CIFS POSIX ACL wire format */
2745 static __u16 ACL_to_cifs_posix(char *parm_data, const char *pACL,
2746 const int buflen, const int acl_type)
2749 struct cifs_posix_acl *cifs_acl = (struct cifs_posix_acl *)parm_data;
2750 posix_acl_xattr_header *local_acl = (posix_acl_xattr_header *)pACL;
2754 if ((buflen == 0) || (pACL == NULL) || (cifs_acl == NULL))
2757 count = posix_acl_xattr_count((size_t)buflen);
2758 cFYI(1, "setting acl with %d entries from buf of length %d and "
2760 count, buflen, le32_to_cpu(local_acl->a_version));
2761 if (le32_to_cpu(local_acl->a_version) != 2) {
2762 cFYI(1, "unknown POSIX ACL version %d",
2763 le32_to_cpu(local_acl->a_version));
2766 cifs_acl->version = cpu_to_le16(1);
2767 if (acl_type == ACL_TYPE_ACCESS)
2768 cifs_acl->access_entry_count = cpu_to_le16(count);
2769 else if (acl_type == ACL_TYPE_DEFAULT)
2770 cifs_acl->default_entry_count = cpu_to_le16(count);
2772 cFYI(1, "unknown ACL type %d", acl_type);
2775 for (i = 0; i < count; i++) {
2776 rc = convert_ace_to_cifs_ace(&cifs_acl->ace_array[i],
2777 &local_acl->a_entries[i]);
2779 /* ACE not converted */
2784 rc = (__u16)(count * sizeof(struct cifs_posix_ace));
2785 rc += sizeof(struct cifs_posix_acl);
2786 /* BB add check to make sure ACL does not overflow SMB */
2792 CIFSSMBGetPosixACL(const int xid, struct cifsTconInfo *tcon,
2793 const unsigned char *searchName,
2794 char *acl_inf, const int buflen, const int acl_type,
2795 const struct nls_table *nls_codepage, int remap)
2797 /* SMB_QUERY_POSIX_ACL */
2798 TRANSACTION2_QPI_REQ *pSMB = NULL;
2799 TRANSACTION2_QPI_RSP *pSMBr = NULL;
2803 __u16 params, byte_count;
2805 cFYI(1, "In GetPosixACL (Unix) for path %s", searchName);
2808 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2813 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2815 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
2816 PATH_MAX, nls_codepage, remap);
2817 name_len++; /* trailing null */
2819 pSMB->FileName[name_len] = 0;
2820 pSMB->FileName[name_len+1] = 0;
2821 } else { /* BB improve the check for buffer overruns BB */
2822 name_len = strnlen(searchName, PATH_MAX);
2823 name_len++; /* trailing null */
2824 strncpy(pSMB->FileName, searchName, name_len);
2827 params = 2 /* level */ + 4 /* rsrvd */ + name_len /* incl null */ ;
2828 pSMB->TotalDataCount = 0;
2829 pSMB->MaxParameterCount = cpu_to_le16(2);
2830 /* BB find exact max data count below from sess structure BB */
2831 pSMB->MaxDataCount = cpu_to_le16(4000);
2832 pSMB->MaxSetupCount = 0;
2836 pSMB->Reserved2 = 0;
2837 pSMB->ParameterOffset = cpu_to_le16(
2838 offsetof(struct smb_com_transaction2_qpi_req,
2839 InformationLevel) - 4);
2840 pSMB->DataCount = 0;
2841 pSMB->DataOffset = 0;
2842 pSMB->SetupCount = 1;
2843 pSMB->Reserved3 = 0;
2844 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
2845 byte_count = params + 1 /* pad */ ;
2846 pSMB->TotalParameterCount = cpu_to_le16(params);
2847 pSMB->ParameterCount = pSMB->TotalParameterCount;
2848 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_POSIX_ACL);
2849 pSMB->Reserved4 = 0;
2850 pSMB->hdr.smb_buf_length += byte_count;
2851 pSMB->ByteCount = cpu_to_le16(byte_count);
2853 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2854 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2855 cifs_stats_inc(&tcon->num_acl_get);
2857 cFYI(1, "Send error in Query POSIX ACL = %d", rc);
2859 /* decode response */
2861 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
2862 if (rc || (pSMBr->ByteCount < 2))
2863 /* BB also check enough total bytes returned */
2864 rc = -EIO; /* bad smb */
2866 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
2867 __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
2868 rc = cifs_copy_posix_acl(acl_inf,
2869 (char *)&pSMBr->hdr.Protocol+data_offset,
2870 buflen, acl_type, count);
2873 cifs_buf_release(pSMB);
2880 CIFSSMBSetPosixACL(const int xid, struct cifsTconInfo *tcon,
2881 const unsigned char *fileName,
2882 const char *local_acl, const int buflen,
2884 const struct nls_table *nls_codepage, int remap)
2886 struct smb_com_transaction2_spi_req *pSMB = NULL;
2887 struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
2891 int bytes_returned = 0;
2892 __u16 params, byte_count, data_count, param_offset, offset;
2894 cFYI(1, "In SetPosixACL (Unix) for path %s", fileName);
2896 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2900 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2902 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
2903 PATH_MAX, nls_codepage, remap);
2904 name_len++; /* trailing null */
2906 } else { /* BB improve the check for buffer overruns BB */
2907 name_len = strnlen(fileName, PATH_MAX);
2908 name_len++; /* trailing null */
2909 strncpy(pSMB->FileName, fileName, name_len);
2911 params = 6 + name_len;
2912 pSMB->MaxParameterCount = cpu_to_le16(2);
2913 /* BB find max SMB size from sess */
2914 pSMB->MaxDataCount = cpu_to_le16(1000);
2915 pSMB->MaxSetupCount = 0;
2919 pSMB->Reserved2 = 0;
2920 param_offset = offsetof(struct smb_com_transaction2_spi_req,
2921 InformationLevel) - 4;
2922 offset = param_offset + params;
2923 parm_data = ((char *) &pSMB->hdr.Protocol) + offset;
2924 pSMB->ParameterOffset = cpu_to_le16(param_offset);
2926 /* convert to on the wire format for POSIX ACL */
2927 data_count = ACL_to_cifs_posix(parm_data, local_acl, buflen, acl_type);
2929 if (data_count == 0) {
2931 goto setACLerrorExit;
2933 pSMB->DataOffset = cpu_to_le16(offset);
2934 pSMB->SetupCount = 1;
2935 pSMB->Reserved3 = 0;
2936 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
2937 pSMB->InformationLevel = cpu_to_le16(SMB_SET_POSIX_ACL);
2938 byte_count = 3 /* pad */ + params + data_count;
2939 pSMB->DataCount = cpu_to_le16(data_count);
2940 pSMB->TotalDataCount = pSMB->DataCount;
2941 pSMB->ParameterCount = cpu_to_le16(params);
2942 pSMB->TotalParameterCount = pSMB->ParameterCount;
2943 pSMB->Reserved4 = 0;
2944 pSMB->hdr.smb_buf_length += byte_count;
2945 pSMB->ByteCount = cpu_to_le16(byte_count);
2946 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2947 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2949 cFYI(1, "Set POSIX ACL returned %d", rc);
2952 cifs_buf_release(pSMB);
2958 /* BB fix tabs in this function FIXME BB */
2960 CIFSGetExtAttr(const int xid, struct cifsTconInfo *tcon,
2961 const int netfid, __u64 *pExtAttrBits, __u64 *pMask)
2964 struct smb_t2_qfi_req *pSMB = NULL;
2965 struct smb_t2_qfi_rsp *pSMBr = NULL;
2967 __u16 params, byte_count;
2969 cFYI(1, "In GetExtAttr");
2974 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2979 params = 2 /* level */ + 2 /* fid */;
2980 pSMB->t2.TotalDataCount = 0;
2981 pSMB->t2.MaxParameterCount = cpu_to_le16(4);
2982 /* BB find exact max data count below from sess structure BB */
2983 pSMB->t2.MaxDataCount = cpu_to_le16(4000);
2984 pSMB->t2.MaxSetupCount = 0;
2985 pSMB->t2.Reserved = 0;
2987 pSMB->t2.Timeout = 0;
2988 pSMB->t2.Reserved2 = 0;
2989 pSMB->t2.ParameterOffset = cpu_to_le16(offsetof(struct smb_t2_qfi_req,
2991 pSMB->t2.DataCount = 0;
2992 pSMB->t2.DataOffset = 0;
2993 pSMB->t2.SetupCount = 1;
2994 pSMB->t2.Reserved3 = 0;
2995 pSMB->t2.SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION);
2996 byte_count = params + 1 /* pad */ ;
2997 pSMB->t2.TotalParameterCount = cpu_to_le16(params);
2998 pSMB->t2.ParameterCount = pSMB->t2.TotalParameterCount;
2999 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_ATTR_FLAGS);
3002 pSMB->hdr.smb_buf_length += byte_count;
3003 pSMB->t2.ByteCount = cpu_to_le16(byte_count);
3005 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3006 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3008 cFYI(1, "error %d in GetExtAttr", rc);
3010 /* decode response */
3011 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3012 if (rc || (pSMBr->ByteCount < 2))
3013 /* BB also check enough total bytes returned */
3014 /* If rc should we check for EOPNOSUPP and
3015 disable the srvino flag? or in caller? */
3016 rc = -EIO; /* bad smb */
3018 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3019 __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
3020 struct file_chattr_info *pfinfo;
3021 /* BB Do we need a cast or hash here ? */
3023 cFYI(1, "Illegal size ret in GetExtAttr");
3027 pfinfo = (struct file_chattr_info *)
3028 (data_offset + (char *) &pSMBr->hdr.Protocol);
3029 *pExtAttrBits = le64_to_cpu(pfinfo->mode);
3030 *pMask = le64_to_cpu(pfinfo->mask);
3034 cifs_buf_release(pSMB);
3036 goto GetExtAttrRetry;
3040 #endif /* CONFIG_POSIX */
3042 #ifdef CONFIG_CIFS_EXPERIMENTAL
3043 /* Get Security Descriptor (by handle) from remote server for a file or dir */
3045 CIFSSMBGetCIFSACL(const int xid, struct cifsTconInfo *tcon, __u16 fid,
3046 struct cifs_ntsd **acl_inf, __u32 *pbuflen)
3050 QUERY_SEC_DESC_REQ *pSMB;
3053 cFYI(1, "GetCifsACL");
3058 rc = smb_init_nttransact(NT_TRANSACT_QUERY_SECURITY_DESC, 0,
3059 8 /* parm len */, tcon, (void **) &pSMB);
3063 pSMB->MaxParameterCount = cpu_to_le32(4);
3064 /* BB TEST with big acls that might need to be e.g. larger than 16K */
3065 pSMB->MaxSetupCount = 0;
3066 pSMB->Fid = fid; /* file handle always le */
3067 pSMB->AclFlags = cpu_to_le32(CIFS_ACL_OWNER | CIFS_ACL_GROUP |
3069 pSMB->ByteCount = cpu_to_le16(11); /* 3 bytes pad + 8 bytes parm */
3070 pSMB->hdr.smb_buf_length += 11;
3071 iov[0].iov_base = (char *)pSMB;
3072 iov[0].iov_len = pSMB->hdr.smb_buf_length + 4;
3074 rc = SendReceive2(xid, tcon->ses, iov, 1 /* num iovec */, &buf_type,
3076 cifs_stats_inc(&tcon->num_acl_get);
3078 cFYI(1, "Send error in QuerySecDesc = %d", rc);
3079 } else { /* decode response */
3083 struct smb_com_ntransact_rsp *pSMBr;
3086 /* validate_nttransact */
3087 rc = validate_ntransact(iov[0].iov_base, (char **)&parm,
3088 &pdata, &parm_len, pbuflen);
3091 pSMBr = (struct smb_com_ntransact_rsp *)iov[0].iov_base;
3093 cFYI(1, "smb %p parm %p data %p", pSMBr, parm, *acl_inf);
3095 if (le32_to_cpu(pSMBr->ParameterCount) != 4) {
3096 rc = -EIO; /* bad smb */
3101 /* BB check that data area is minimum length and as big as acl_len */
3103 acl_len = le32_to_cpu(*parm);
3104 if (acl_len != *pbuflen) {
3105 cERROR(1, "acl length %d does not match %d",
3107 if (*pbuflen > acl_len)
3111 /* check if buffer is big enough for the acl
3112 header followed by the smallest SID */
3113 if ((*pbuflen < sizeof(struct cifs_ntsd) + 8) ||
3114 (*pbuflen >= 64 * 1024)) {
3115 cERROR(1, "bad acl length %d", *pbuflen);
3119 *acl_inf = kmalloc(*pbuflen, GFP_KERNEL);
3120 if (*acl_inf == NULL) {
3124 memcpy(*acl_inf, pdata, *pbuflen);
3128 if (buf_type == CIFS_SMALL_BUFFER)
3129 cifs_small_buf_release(iov[0].iov_base);
3130 else if (buf_type == CIFS_LARGE_BUFFER)
3131 cifs_buf_release(iov[0].iov_base);
3132 /* cifs_small_buf_release(pSMB); */ /* Freed earlier now in SendReceive2 */
3137 CIFSSMBSetCIFSACL(const int xid, struct cifsTconInfo *tcon, __u16 fid,
3138 struct cifs_ntsd *pntsd, __u32 acllen)
3140 __u16 byte_count, param_count, data_count, param_offset, data_offset;
3142 int bytes_returned = 0;
3143 SET_SEC_DESC_REQ *pSMB = NULL;
3144 NTRANSACT_RSP *pSMBr = NULL;
3147 rc = smb_init(SMB_COM_NT_TRANSACT, 19, tcon, (void **) &pSMB,
3152 pSMB->MaxSetupCount = 0;
3156 param_offset = offsetof(struct smb_com_transaction_ssec_req, Fid) - 4;
3157 data_count = acllen;
3158 data_offset = param_offset + param_count;
3159 byte_count = 3 /* pad */ + param_count;
3161 pSMB->DataCount = cpu_to_le32(data_count);
3162 pSMB->TotalDataCount = pSMB->DataCount;
3163 pSMB->MaxParameterCount = cpu_to_le32(4);
3164 pSMB->MaxDataCount = cpu_to_le32(16384);
3165 pSMB->ParameterCount = cpu_to_le32(param_count);
3166 pSMB->ParameterOffset = cpu_to_le32(param_offset);
3167 pSMB->TotalParameterCount = pSMB->ParameterCount;
3168 pSMB->DataOffset = cpu_to_le32(data_offset);
3169 pSMB->SetupCount = 0;
3170 pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_SET_SECURITY_DESC);
3171 pSMB->ByteCount = cpu_to_le16(byte_count+data_count);
3173 pSMB->Fid = fid; /* file handle always le */
3174 pSMB->Reserved2 = 0;
3175 pSMB->AclFlags = cpu_to_le32(CIFS_ACL_DACL);
3177 if (pntsd && acllen) {
3178 memcpy((char *) &pSMBr->hdr.Protocol + data_offset,
3181 pSMB->hdr.smb_buf_length += (byte_count + data_count);
3184 pSMB->hdr.smb_buf_length += byte_count;
3186 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3187 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3189 cFYI(1, "SetCIFSACL bytes_returned: %d, rc: %d", bytes_returned, rc);
3191 cFYI(1, "Set CIFS ACL returned %d", rc);
3192 cifs_buf_release(pSMB);
3195 goto setCifsAclRetry;
3200 #endif /* CONFIG_CIFS_EXPERIMENTAL */
3202 /* Legacy Query Path Information call for lookup to old servers such
3204 int SMBQueryInformation(const int xid, struct cifsTconInfo *tcon,
3205 const unsigned char *searchName,
3206 FILE_ALL_INFO *pFinfo,
3207 const struct nls_table *nls_codepage, int remap)
3209 QUERY_INFORMATION_REQ *pSMB;
3210 QUERY_INFORMATION_RSP *pSMBr;
3215 cFYI(1, "In SMBQPath path %s", searchName);
3217 rc = smb_init(SMB_COM_QUERY_INFORMATION, 0, tcon, (void **) &pSMB,
3222 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3224 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
3225 PATH_MAX, nls_codepage, remap);
3226 name_len++; /* trailing null */
3229 name_len = strnlen(searchName, PATH_MAX);
3230 name_len++; /* trailing null */
3231 strncpy(pSMB->FileName, searchName, name_len);
3233 pSMB->BufferFormat = 0x04;
3234 name_len++; /* account for buffer type byte */
3235 pSMB->hdr.smb_buf_length += (__u16) name_len;
3236 pSMB->ByteCount = cpu_to_le16(name_len);
3238 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3239 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3241 cFYI(1, "Send error in QueryInfo = %d", rc);
3242 } else if (pFinfo) {
3244 __u32 time = le32_to_cpu(pSMBr->last_write_time);
3246 /* decode response */
3247 /* BB FIXME - add time zone adjustment BB */
3248 memset(pFinfo, 0, sizeof(FILE_ALL_INFO));
3251 /* decode time fields */
3252 pFinfo->ChangeTime = cpu_to_le64(cifs_UnixTimeToNT(ts));
3253 pFinfo->LastWriteTime = pFinfo->ChangeTime;
3254 pFinfo->LastAccessTime = 0;
3255 pFinfo->AllocationSize =
3256 cpu_to_le64(le32_to_cpu(pSMBr->size));
3257 pFinfo->EndOfFile = pFinfo->AllocationSize;
3258 pFinfo->Attributes =
3259 cpu_to_le32(le16_to_cpu(pSMBr->attr));
3261 rc = -EIO; /* bad buffer passed in */
3263 cifs_buf_release(pSMB);
3272 CIFSSMBQFileInfo(const int xid, struct cifsTconInfo *tcon,
3273 u16 netfid, FILE_ALL_INFO *pFindData)
3275 struct smb_t2_qfi_req *pSMB = NULL;
3276 struct smb_t2_qfi_rsp *pSMBr = NULL;
3279 __u16 params, byte_count;
3282 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3287 params = 2 /* level */ + 2 /* fid */;
3288 pSMB->t2.TotalDataCount = 0;
3289 pSMB->t2.MaxParameterCount = cpu_to_le16(4);
3290 /* BB find exact max data count below from sess structure BB */
3291 pSMB->t2.MaxDataCount = cpu_to_le16(CIFSMaxBufSize);
3292 pSMB->t2.MaxSetupCount = 0;
3293 pSMB->t2.Reserved = 0;
3295 pSMB->t2.Timeout = 0;
3296 pSMB->t2.Reserved2 = 0;
3297 pSMB->t2.ParameterOffset = cpu_to_le16(offsetof(struct smb_t2_qfi_req,
3299 pSMB->t2.DataCount = 0;
3300 pSMB->t2.DataOffset = 0;
3301 pSMB->t2.SetupCount = 1;
3302 pSMB->t2.Reserved3 = 0;
3303 pSMB->t2.SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION);
3304 byte_count = params + 1 /* pad */ ;
3305 pSMB->t2.TotalParameterCount = cpu_to_le16(params);
3306 pSMB->t2.ParameterCount = pSMB->t2.TotalParameterCount;
3307 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_ALL_INFO);
3310 pSMB->hdr.smb_buf_length += byte_count;
3312 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3313 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3315 cFYI(1, "Send error in QPathInfo = %d", rc);
3316 } else { /* decode response */
3317 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3319 if (rc) /* BB add auto retry on EOPNOTSUPP? */
3321 else if (pSMBr->ByteCount < 40)
3322 rc = -EIO; /* bad smb */
3323 else if (pFindData) {
3324 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3325 memcpy((char *) pFindData,
3326 (char *) &pSMBr->hdr.Protocol +
3327 data_offset, sizeof(FILE_ALL_INFO));
3331 cifs_buf_release(pSMB);
3333 goto QFileInfoRetry;
3339 CIFSSMBQPathInfo(const int xid, struct cifsTconInfo *tcon,
3340 const unsigned char *searchName,
3341 FILE_ALL_INFO *pFindData,
3342 int legacy /* old style infolevel */,
3343 const struct nls_table *nls_codepage, int remap)
3345 /* level 263 SMB_QUERY_FILE_ALL_INFO */
3346 TRANSACTION2_QPI_REQ *pSMB = NULL;
3347 TRANSACTION2_QPI_RSP *pSMBr = NULL;
3351 __u16 params, byte_count;
3353 /* cFYI(1, "In QPathInfo path %s", searchName); */
3355 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3360 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3362 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
3363 PATH_MAX, nls_codepage, remap);
3364 name_len++; /* trailing null */
3366 } else { /* BB improve the check for buffer overruns BB */
3367 name_len = strnlen(searchName, PATH_MAX);
3368 name_len++; /* trailing null */
3369 strncpy(pSMB->FileName, searchName, name_len);
3372 params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */;
3373 pSMB->TotalDataCount = 0;
3374 pSMB->MaxParameterCount = cpu_to_le16(2);
3375 /* BB find exact max SMB PDU from sess structure BB */
3376 pSMB->MaxDataCount = cpu_to_le16(4000);
3377 pSMB->MaxSetupCount = 0;
3381 pSMB->Reserved2 = 0;
3382 pSMB->ParameterOffset = cpu_to_le16(offsetof(
3383 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
3384 pSMB->DataCount = 0;
3385 pSMB->DataOffset = 0;
3386 pSMB->SetupCount = 1;
3387 pSMB->Reserved3 = 0;
3388 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
3389 byte_count = params + 1 /* pad */ ;
3390 pSMB->TotalParameterCount = cpu_to_le16(params);
3391 pSMB->ParameterCount = pSMB->TotalParameterCount;
3393 pSMB->InformationLevel = cpu_to_le16(SMB_INFO_STANDARD);
3395 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_ALL_INFO);
3396 pSMB->Reserved4 = 0;
3397 pSMB->hdr.smb_buf_length += byte_count;
3398 pSMB->ByteCount = cpu_to_le16(byte_count);
3400 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3401 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3403 cFYI(1, "Send error in QPathInfo = %d", rc);
3404 } else { /* decode response */
3405 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3407 if (rc) /* BB add auto retry on EOPNOTSUPP? */
3409 else if (!legacy && (pSMBr->ByteCount < 40))
3410 rc = -EIO; /* bad smb */
3411 else if (legacy && (pSMBr->ByteCount < 24))
3412 rc = -EIO; /* 24 or 26 expected but we do not read
3414 else if (pFindData) {
3416 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3418 /* On legacy responses we do not read the last field,
3419 EAsize, fortunately since it varies by subdialect and
3420 also note it differs on Set vs. Get, ie two bytes or 4
3421 bytes depending but we don't care here */
3423 size = sizeof(FILE_INFO_STANDARD);
3425 size = sizeof(FILE_ALL_INFO);
3426 memcpy((char *) pFindData,
3427 (char *) &pSMBr->hdr.Protocol +
3432 cifs_buf_release(pSMB);
3434 goto QPathInfoRetry;
3440 CIFSSMBUnixQFileInfo(const int xid, struct cifsTconInfo *tcon,
3441 u16 netfid, FILE_UNIX_BASIC_INFO *pFindData)
3443 struct smb_t2_qfi_req *pSMB = NULL;
3444 struct smb_t2_qfi_rsp *pSMBr = NULL;
3447 __u16 params, byte_count;
3450 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3455 params = 2 /* level */ + 2 /* fid */;
3456 pSMB->t2.TotalDataCount = 0;
3457 pSMB->t2.MaxParameterCount = cpu_to_le16(4);
3458 /* BB find exact max data count below from sess structure BB */
3459 pSMB->t2.MaxDataCount = cpu_to_le16(CIFSMaxBufSize);
3460 pSMB->t2.MaxSetupCount = 0;
3461 pSMB->t2.Reserved = 0;
3463 pSMB->t2.Timeout = 0;
3464 pSMB->t2.Reserved2 = 0;
3465 pSMB->t2.ParameterOffset = cpu_to_le16(offsetof(struct smb_t2_qfi_req,
3467 pSMB->t2.DataCount = 0;
3468 pSMB->t2.DataOffset = 0;
3469 pSMB->t2.SetupCount = 1;
3470 pSMB->t2.Reserved3 = 0;
3471 pSMB->t2.SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION);
3472 byte_count = params + 1 /* pad */ ;
3473 pSMB->t2.TotalParameterCount = cpu_to_le16(params);
3474 pSMB->t2.ParameterCount = pSMB->t2.TotalParameterCount;
3475 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC);
3478 pSMB->hdr.smb_buf_length += byte_count;
3480 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3481 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3483 cFYI(1, "Send error in QPathInfo = %d", rc);
3484 } else { /* decode response */
3485 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3487 if (rc || (pSMBr->ByteCount < sizeof(FILE_UNIX_BASIC_INFO))) {
3488 cERROR(1, "Malformed FILE_UNIX_BASIC_INFO response.\n"
3489 "Unix Extensions can be disabled on mount "
3490 "by specifying the nosfu mount option.");
3491 rc = -EIO; /* bad smb */
3493 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3494 memcpy((char *) pFindData,
3495 (char *) &pSMBr->hdr.Protocol +
3497 sizeof(FILE_UNIX_BASIC_INFO));
3501 cifs_buf_release(pSMB);
3503 goto UnixQFileInfoRetry;
3509 CIFSSMBUnixQPathInfo(const int xid, struct cifsTconInfo *tcon,
3510 const unsigned char *searchName,
3511 FILE_UNIX_BASIC_INFO *pFindData,
3512 const struct nls_table *nls_codepage, int remap)
3514 /* SMB_QUERY_FILE_UNIX_BASIC */
3515 TRANSACTION2_QPI_REQ *pSMB = NULL;
3516 TRANSACTION2_QPI_RSP *pSMBr = NULL;
3518 int bytes_returned = 0;
3520 __u16 params, byte_count;
3522 cFYI(1, "In QPathInfo (Unix) the path %s", searchName);
3524 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3529 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3531 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
3532 PATH_MAX, nls_codepage, remap);
3533 name_len++; /* trailing null */
3535 } else { /* BB improve the check for buffer overruns BB */
3536 name_len = strnlen(searchName, PATH_MAX);
3537 name_len++; /* trailing null */
3538 strncpy(pSMB->FileName, searchName, name_len);
3541 params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */;
3542 pSMB->TotalDataCount = 0;
3543 pSMB->MaxParameterCount = cpu_to_le16(2);
3544 /* BB find exact max SMB PDU from sess structure BB */
3545 pSMB->MaxDataCount = cpu_to_le16(4000);
3546 pSMB->MaxSetupCount = 0;
3550 pSMB->Reserved2 = 0;
3551 pSMB->ParameterOffset = cpu_to_le16(offsetof(
3552 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
3553 pSMB->DataCount = 0;
3554 pSMB->DataOffset = 0;
3555 pSMB->SetupCount = 1;
3556 pSMB->Reserved3 = 0;
3557 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
3558 byte_count = params + 1 /* pad */ ;
3559 pSMB->TotalParameterCount = cpu_to_le16(params);
3560 pSMB->ParameterCount = pSMB->TotalParameterCount;
3561 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC);
3562 pSMB->Reserved4 = 0;
3563 pSMB->hdr.smb_buf_length += byte_count;
3564 pSMB->ByteCount = cpu_to_le16(byte_count);
3566 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3567 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3569 cFYI(1, "Send error in QPathInfo = %d", rc);
3570 } else { /* decode response */
3571 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3573 if (rc || (pSMBr->ByteCount < sizeof(FILE_UNIX_BASIC_INFO))) {
3574 cERROR(1, "Malformed FILE_UNIX_BASIC_INFO response.\n"
3575 "Unix Extensions can be disabled on mount "
3576 "by specifying the nosfu mount option.");
3577 rc = -EIO; /* bad smb */
3579 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3580 memcpy((char *) pFindData,
3581 (char *) &pSMBr->hdr.Protocol +
3583 sizeof(FILE_UNIX_BASIC_INFO));
3586 cifs_buf_release(pSMB);
3588 goto UnixQPathInfoRetry;
3593 /* xid, tcon, searchName and codepage are input parms, rest are returned */
3595 CIFSFindFirst(const int xid, struct cifsTconInfo *tcon,
3596 const char *searchName,
3597 const struct nls_table *nls_codepage,
3599 struct cifs_search_info *psrch_inf, int remap, const char dirsep)
3601 /* level 257 SMB_ */
3602 TRANSACTION2_FFIRST_REQ *pSMB = NULL;
3603 TRANSACTION2_FFIRST_RSP *pSMBr = NULL;
3604 T2_FFIRST_RSP_PARMS *parms;
3606 int bytes_returned = 0;
3608 __u16 params, byte_count;
3610 cFYI(1, "In FindFirst for %s", searchName);
3613 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3618 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3620 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
3621 PATH_MAX, nls_codepage, remap);
3622 /* We can not add the asterik earlier in case
3623 it got remapped to 0xF03A as if it were part of the
3624 directory name instead of a wildcard */
3626 pSMB->FileName[name_len] = dirsep;
3627 pSMB->FileName[name_len+1] = 0;
3628 pSMB->FileName[name_len+2] = '*';
3629 pSMB->FileName[name_len+3] = 0;
3630 name_len += 4; /* now the trailing null */
3631 pSMB->FileName[name_len] = 0; /* null terminate just in case */
3632 pSMB->FileName[name_len+1] = 0;
3634 } else { /* BB add check for overrun of SMB buf BB */
3635 name_len = strnlen(searchName, PATH_MAX);
3636 /* BB fix here and in unicode clause above ie
3637 if (name_len > buffersize-header)
3638 free buffer exit; BB */
3639 strncpy(pSMB->FileName, searchName, name_len);
3640 pSMB->FileName[name_len] = dirsep;
3641 pSMB->FileName[name_len+1] = '*';
3642 pSMB->FileName[name_len+2] = 0;
3646 params = 12 + name_len /* includes null */ ;
3647 pSMB->TotalDataCount = 0; /* no EAs */
3648 pSMB->MaxParameterCount = cpu_to_le16(10);
3649 pSMB->MaxDataCount = cpu_to_le16((tcon->ses->server->maxBuf -
3650 MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
3651 pSMB->MaxSetupCount = 0;
3655 pSMB->Reserved2 = 0;
3656 byte_count = params + 1 /* pad */ ;
3657 pSMB->TotalParameterCount = cpu_to_le16(params);
3658 pSMB->ParameterCount = pSMB->TotalParameterCount;
3659 pSMB->ParameterOffset = cpu_to_le16(
3660 offsetof(struct smb_com_transaction2_ffirst_req, SearchAttributes)
3662 pSMB->DataCount = 0;
3663 pSMB->DataOffset = 0;
3664 pSMB->SetupCount = 1; /* one byte, no need to make endian neutral */
3665 pSMB->Reserved3 = 0;
3666 pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_FIRST);
3667 pSMB->SearchAttributes =
3668 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
3670 pSMB->SearchCount = cpu_to_le16(CIFSMaxBufSize/sizeof(FILE_UNIX_INFO));
3671 pSMB->SearchFlags = cpu_to_le16(CIFS_SEARCH_CLOSE_AT_END |
3672 CIFS_SEARCH_RETURN_RESUME);
3673 pSMB->InformationLevel = cpu_to_le16(psrch_inf->info_level);
3675 /* BB what should we set StorageType to? Does it matter? BB */
3676 pSMB->SearchStorageType = 0;
3677 pSMB->hdr.smb_buf_length += byte_count;
3678 pSMB->ByteCount = cpu_to_le16(byte_count);
3680 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3681 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3682 cifs_stats_inc(&tcon->num_ffirst);
3684 if (rc) {/* BB add logic to retry regular search if Unix search
3685 rejected unexpectedly by server */
3686 /* BB Add code to handle unsupported level rc */
3687 cFYI(1, "Error in FindFirst = %d", rc);
3689 cifs_buf_release(pSMB);
3691 /* BB eventually could optimize out free and realloc of buf */
3694 goto findFirstRetry;
3695 } else { /* decode response */
3696 /* BB remember to free buffer if error BB */
3697 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3701 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
3702 psrch_inf->unicode = true;
3704 psrch_inf->unicode = false;
3706 psrch_inf->ntwrk_buf_start = (char *)pSMBr;
3707 psrch_inf->smallBuf = 0;
3708 psrch_inf->srch_entries_start =
3709 (char *) &pSMBr->hdr.Protocol +
3710 le16_to_cpu(pSMBr->t2.DataOffset);
3711 parms = (T2_FFIRST_RSP_PARMS *)((char *) &pSMBr->hdr.Protocol +
3712 le16_to_cpu(pSMBr->t2.ParameterOffset));
3714 if (parms->EndofSearch)
3715 psrch_inf->endOfSearch = true;
3717 psrch_inf->endOfSearch = false;
3719 psrch_inf->entries_in_buffer =
3720 le16_to_cpu(parms->SearchCount);
3721 psrch_inf->index_of_last_entry = 2 /* skip . and .. */ +
3722 psrch_inf->entries_in_buffer;
3723 lnoff = le16_to_cpu(parms->LastNameOffset);
3724 if (tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE <
3726 cERROR(1, "ignoring corrupt resume name");
3727 psrch_inf->last_entry = NULL;
3731 psrch_inf->last_entry = psrch_inf->srch_entries_start +
3734 *pnetfid = parms->SearchHandle;
3736 cifs_buf_release(pSMB);
3743 int CIFSFindNext(const int xid, struct cifsTconInfo *tcon,
3744 __u16 searchHandle, struct cifs_search_info *psrch_inf)
3746 TRANSACTION2_FNEXT_REQ *pSMB = NULL;
3747 TRANSACTION2_FNEXT_RSP *pSMBr = NULL;
3748 T2_FNEXT_RSP_PARMS *parms;
3749 char *response_data;
3751 int bytes_returned, name_len;
3752 __u16 params, byte_count;
3754 cFYI(1, "In FindNext");
3756 if (psrch_inf->endOfSearch)
3759 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3764 params = 14; /* includes 2 bytes of null string, converted to LE below*/
3766 pSMB->TotalDataCount = 0; /* no EAs */
3767 pSMB->MaxParameterCount = cpu_to_le16(8);
3768 pSMB->MaxDataCount =
3769 cpu_to_le16((tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE) &
3771 pSMB->MaxSetupCount = 0;
3775 pSMB->Reserved2 = 0;
3776 pSMB->ParameterOffset = cpu_to_le16(
3777 offsetof(struct smb_com_transaction2_fnext_req,SearchHandle) - 4);
3778 pSMB->DataCount = 0;
3779 pSMB->DataOffset = 0;
3780 pSMB->SetupCount = 1;
3781 pSMB->Reserved3 = 0;
3782 pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_NEXT);
3783 pSMB->SearchHandle = searchHandle; /* always kept as le */
3785 cpu_to_le16(CIFSMaxBufSize / sizeof(FILE_UNIX_INFO));
3786 pSMB->InformationLevel = cpu_to_le16(psrch_inf->info_level);
3787 pSMB->ResumeKey = psrch_inf->resume_key;
3789 cpu_to_le16(CIFS_SEARCH_CLOSE_AT_END | CIFS_SEARCH_RETURN_RESUME);
3791 name_len = psrch_inf->resume_name_len;
3793 if (name_len < PATH_MAX) {
3794 memcpy(pSMB->ResumeFileName, psrch_inf->presume_name, name_len);
3795 byte_count += name_len;
3796 /* 14 byte parm len above enough for 2 byte null terminator */
3797 pSMB->ResumeFileName[name_len] = 0;
3798 pSMB->ResumeFileName[name_len+1] = 0;
3801 goto FNext2_err_exit;
3803 byte_count = params + 1 /* pad */ ;
3804 pSMB->TotalParameterCount = cpu_to_le16(params);
3805 pSMB->ParameterCount = pSMB->TotalParameterCount;
3806 pSMB->hdr.smb_buf_length += byte_count;
3807 pSMB->ByteCount = cpu_to_le16(byte_count);
3809 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3810 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3811 cifs_stats_inc(&tcon->num_fnext);
3814 psrch_inf->endOfSearch = true;
3815 cifs_buf_release(pSMB);
3816 rc = 0; /* search probably was closed at end of search*/
3818 cFYI(1, "FindNext returned = %d", rc);
3819 } else { /* decode response */
3820 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3825 /* BB fixme add lock for file (srch_info) struct here */
3826 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
3827 psrch_inf->unicode = true;
3829 psrch_inf->unicode = false;
3830 response_data = (char *) &pSMBr->hdr.Protocol +
3831 le16_to_cpu(pSMBr->t2.ParameterOffset);
3832 parms = (T2_FNEXT_RSP_PARMS *)response_data;
3833 response_data = (char *)&pSMBr->hdr.Protocol +
3834 le16_to_cpu(pSMBr->t2.DataOffset);
3835 if (psrch_inf->smallBuf)
3836 cifs_small_buf_release(
3837 psrch_inf->ntwrk_buf_start);
3839 cifs_buf_release(psrch_inf->ntwrk_buf_start);
3840 psrch_inf->srch_entries_start = response_data;
3841 psrch_inf->ntwrk_buf_start = (char *)pSMB;
3842 psrch_inf->smallBuf = 0;
3843 if (parms->EndofSearch)
3844 psrch_inf->endOfSearch = true;
3846 psrch_inf->endOfSearch = false;
3847 psrch_inf->entries_in_buffer =
3848 le16_to_cpu(parms->SearchCount);
3849 psrch_inf->index_of_last_entry +=
3850 psrch_inf->entries_in_buffer;
3851 lnoff = le16_to_cpu(parms->LastNameOffset);
3852 if (tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE <
3854 cERROR(1, "ignoring corrupt resume name");
3855 psrch_inf->last_entry = NULL;
3858 psrch_inf->last_entry =
3859 psrch_inf->srch_entries_start + lnoff;
3861 /* cFYI(1, "fnxt2 entries in buf %d index_of_last %d",
3862 psrch_inf->entries_in_buffer, psrch_inf->index_of_last_entry); */
3864 /* BB fixme add unlock here */
3869 /* BB On error, should we leave previous search buf (and count and
3870 last entry fields) intact or free the previous one? */
3872 /* Note: On -EAGAIN error only caller can retry on handle based calls
3873 since file handle passed in no longer valid */
3876 cifs_buf_release(pSMB);
3881 CIFSFindClose(const int xid, struct cifsTconInfo *tcon,
3882 const __u16 searchHandle)
3885 FINDCLOSE_REQ *pSMB = NULL;
3887 cFYI(1, "In CIFSSMBFindClose");
3888 rc = small_smb_init(SMB_COM_FIND_CLOSE2, 1, tcon, (void **)&pSMB);
3890 /* no sense returning error if session restarted
3891 as file handle has been closed */
3897 pSMB->FileID = searchHandle;
3898 pSMB->ByteCount = 0;
3899 rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0);
3901 cERROR(1, "Send error in FindClose = %d", rc);
3903 cifs_stats_inc(&tcon->num_fclose);
3905 /* Since session is dead, search handle closed on server already */
3913 CIFSGetSrvInodeNumber(const int xid, struct cifsTconInfo *tcon,
3914 const unsigned char *searchName,
3915 __u64 *inode_number,
3916 const struct nls_table *nls_codepage, int remap)
3919 TRANSACTION2_QPI_REQ *pSMB = NULL;
3920 TRANSACTION2_QPI_RSP *pSMBr = NULL;
3921 int name_len, bytes_returned;
3922 __u16 params, byte_count;
3924 cFYI(1, "In GetSrvInodeNum for %s", searchName);
3928 GetInodeNumberRetry:
3929 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3934 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3936 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
3937 PATH_MAX, nls_codepage, remap);
3938 name_len++; /* trailing null */
3940 } else { /* BB improve the check for buffer overruns BB */
3941 name_len = strnlen(searchName, PATH_MAX);
3942 name_len++; /* trailing null */
3943 strncpy(pSMB->FileName, searchName, name_len);
3946 params = 2 /* level */ + 4 /* rsrvd */ + name_len /* incl null */ ;
3947 pSMB->TotalDataCount = 0;
3948 pSMB->MaxParameterCount = cpu_to_le16(2);
3949 /* BB find exact max data count below from sess structure BB */
3950 pSMB->MaxDataCount = cpu_to_le16(4000);
3951 pSMB->MaxSetupCount = 0;
3955 pSMB->Reserved2 = 0;
3956 pSMB->ParameterOffset = cpu_to_le16(offsetof(
3957 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
3958 pSMB->DataCount = 0;
3959 pSMB->DataOffset = 0;
3960 pSMB->SetupCount = 1;
3961 pSMB->Reserved3 = 0;
3962 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
3963 byte_count = params + 1 /* pad */ ;
3964 pSMB->TotalParameterCount = cpu_to_le16(params);
3965 pSMB->ParameterCount = pSMB->TotalParameterCount;
3966 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_INTERNAL_INFO);
3967 pSMB->Reserved4 = 0;
3968 pSMB->hdr.smb_buf_length += byte_count;
3969 pSMB->ByteCount = cpu_to_le16(byte_count);
3971 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3972 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3974 cFYI(1, "error %d in QueryInternalInfo", rc);
3976 /* decode response */
3977 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3978 if (rc || (pSMBr->ByteCount < 2))
3979 /* BB also check enough total bytes returned */
3980 /* If rc should we check for EOPNOSUPP and
3981 disable the srvino flag? or in caller? */
3982 rc = -EIO; /* bad smb */
3984 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3985 __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
3986 struct file_internal_info *pfinfo;
3987 /* BB Do we need a cast or hash here ? */
3989 cFYI(1, "Illegal size ret in QryIntrnlInf");
3991 goto GetInodeNumOut;
3993 pfinfo = (struct file_internal_info *)
3994 (data_offset + (char *) &pSMBr->hdr.Protocol);
3995 *inode_number = le64_to_cpu(pfinfo->UniqueId);
3999 cifs_buf_release(pSMB);
4001 goto GetInodeNumberRetry;
4005 /* parses DFS refferal V3 structure
4006 * caller is responsible for freeing target_nodes
4009 * on failure - errno
4012 parse_DFS_referrals(TRANSACTION2_GET_DFS_REFER_RSP *pSMBr,
4013 unsigned int *num_of_nodes,
4014 struct dfs_info3_param **target_nodes,
4015 const struct nls_table *nls_codepage, int remap,
4016 const char *searchName)
4021 struct dfs_referral_level_3 *ref;
4023 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
4027 *num_of_nodes = le16_to_cpu(pSMBr->NumberOfReferrals);
4029 if (*num_of_nodes < 1) {
4030 cERROR(1, "num_referrals: must be at least > 0,"
4031 "but we get num_referrals = %d\n", *num_of_nodes);
4033 goto parse_DFS_referrals_exit;
4036 ref = (struct dfs_referral_level_3 *) &(pSMBr->referrals);
4037 if (ref->VersionNumber != cpu_to_le16(3)) {
4038 cERROR(1, "Referrals of V%d version are not supported,"
4039 "should be V3", le16_to_cpu(ref->VersionNumber));
4041 goto parse_DFS_referrals_exit;
4044 /* get the upper boundary of the resp buffer */
4045 data_end = (char *)(&(pSMBr->PathConsumed)) +
4046 le16_to_cpu(pSMBr->t2.DataCount);
4048 cFYI(1, "num_referrals: %d dfs flags: 0x%x ...\n",
4050 le32_to_cpu(pSMBr->DFSFlags));
4052 *target_nodes = kzalloc(sizeof(struct dfs_info3_param) *
4053 *num_of_nodes, GFP_KERNEL);
4054 if (*target_nodes == NULL) {
4055 cERROR(1, "Failed to allocate buffer for target_nodes\n");
4057 goto parse_DFS_referrals_exit;
4060 /* collect necessary data from referrals */
4061 for (i = 0; i < *num_of_nodes; i++) {
4064 struct dfs_info3_param *node = (*target_nodes)+i;
4066 node->flags = le32_to_cpu(pSMBr->DFSFlags);
4068 __le16 *tmp = kmalloc(strlen(searchName)*2 + 2,
4072 goto parse_DFS_referrals_exit;
4074 cifsConvertToUCS((__le16 *) tmp, searchName,
4075 PATH_MAX, nls_codepage, remap);
4076 node->path_consumed = cifs_ucs2_bytes(tmp,
4077 le16_to_cpu(pSMBr->PathConsumed),
4081 node->path_consumed = le16_to_cpu(pSMBr->PathConsumed);
4083 node->server_type = le16_to_cpu(ref->ServerType);
4084 node->ref_flag = le16_to_cpu(ref->ReferralEntryFlags);
4087 temp = (char *)ref + le16_to_cpu(ref->DfsPathOffset);
4088 max_len = data_end - temp;
4089 node->path_name = cifs_strndup_from_ucs(temp, max_len,
4090 is_unicode, nls_codepage);
4091 if (!node->path_name) {
4093 goto parse_DFS_referrals_exit;
4096 /* copy link target UNC */
4097 temp = (char *)ref + le16_to_cpu(ref->NetworkAddressOffset);
4098 max_len = data_end - temp;
4099 node->node_name = cifs_strndup_from_ucs(temp, max_len,
4100 is_unicode, nls_codepage);
4101 if (!node->node_name)
4105 parse_DFS_referrals_exit:
4107 free_dfs_info_array(*target_nodes, *num_of_nodes);
4108 *target_nodes = NULL;
4115 CIFSGetDFSRefer(const int xid, struct cifsSesInfo *ses,
4116 const unsigned char *searchName,
4117 struct dfs_info3_param **target_nodes,
4118 unsigned int *num_of_nodes,
4119 const struct nls_table *nls_codepage, int remap)
4121 /* TRANS2_GET_DFS_REFERRAL */
4122 TRANSACTION2_GET_DFS_REFER_REQ *pSMB = NULL;
4123 TRANSACTION2_GET_DFS_REFER_RSP *pSMBr = NULL;
4127 __u16 params, byte_count;
4129 *target_nodes = NULL;
4131 cFYI(1, "In GetDFSRefer the path %s", searchName);
4135 rc = smb_init(SMB_COM_TRANSACTION2, 15, NULL, (void **) &pSMB,
4140 /* server pointer checked in called function,
4141 but should never be null here anyway */
4142 pSMB->hdr.Mid = GetNextMid(ses->server);
4143 pSMB->hdr.Tid = ses->ipc_tid;
4144 pSMB->hdr.Uid = ses->Suid;
4145 if (ses->capabilities & CAP_STATUS32)
4146 pSMB->hdr.Flags2 |= SMBFLG2_ERR_STATUS;
4147 if (ses->capabilities & CAP_DFS)
4148 pSMB->hdr.Flags2 |= SMBFLG2_DFS;
4150 if (ses->capabilities & CAP_UNICODE) {
4151 pSMB->hdr.Flags2 |= SMBFLG2_UNICODE;
4153 cifsConvertToUCS((__le16 *) pSMB->RequestFileName,
4154 searchName, PATH_MAX, nls_codepage, remap);
4155 name_len++; /* trailing null */
4157 } else { /* BB improve the check for buffer overruns BB */
4158 name_len = strnlen(searchName, PATH_MAX);
4159 name_len++; /* trailing null */
4160 strncpy(pSMB->RequestFileName, searchName, name_len);
4164 if (ses->server->secMode &
4165 (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
4166 pSMB->hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
4169 pSMB->hdr.Uid = ses->Suid;
4171 params = 2 /* level */ + name_len /*includes null */ ;
4172 pSMB->TotalDataCount = 0;
4173 pSMB->DataCount = 0;
4174 pSMB->DataOffset = 0;
4175 pSMB->MaxParameterCount = 0;
4176 /* BB find exact max SMB PDU from sess structure BB */
4177 pSMB->MaxDataCount = cpu_to_le16(4000);
4178 pSMB->MaxSetupCount = 0;
4182 pSMB->Reserved2 = 0;
4183 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4184 struct smb_com_transaction2_get_dfs_refer_req, MaxReferralLevel) - 4);
4185 pSMB->SetupCount = 1;
4186 pSMB->Reserved3 = 0;
4187 pSMB->SubCommand = cpu_to_le16(TRANS2_GET_DFS_REFERRAL);
4188 byte_count = params + 3 /* pad */ ;
4189 pSMB->ParameterCount = cpu_to_le16(params);
4190 pSMB->TotalParameterCount = pSMB->ParameterCount;
4191 pSMB->MaxReferralLevel = cpu_to_le16(3);
4192 pSMB->hdr.smb_buf_length += byte_count;
4193 pSMB->ByteCount = cpu_to_le16(byte_count);
4195 rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB,
4196 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4198 cFYI(1, "Send error in GetDFSRefer = %d", rc);
4201 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4203 /* BB Also check if enough total bytes returned? */
4204 if (rc || (pSMBr->ByteCount < 17)) {
4205 rc = -EIO; /* bad smb */
4209 cFYI(1, "Decoding GetDFSRefer response BCC: %d Offset %d",
4211 le16_to_cpu(pSMBr->t2.DataOffset));
4213 /* parse returned result into more usable form */
4214 rc = parse_DFS_referrals(pSMBr, num_of_nodes,
4215 target_nodes, nls_codepage, remap,
4219 cifs_buf_release(pSMB);
4227 /* Query File System Info such as free space to old servers such as Win 9x */
4229 SMBOldQFSInfo(const int xid, struct cifsTconInfo *tcon, struct kstatfs *FSData)
4231 /* level 0x01 SMB_QUERY_FILE_SYSTEM_INFO */
4232 TRANSACTION2_QFSI_REQ *pSMB = NULL;
4233 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4234 FILE_SYSTEM_ALLOC_INFO *response_data;
4236 int bytes_returned = 0;
4237 __u16 params, byte_count;
4239 cFYI(1, "OldQFSInfo");
4241 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4246 params = 2; /* level */
4247 pSMB->TotalDataCount = 0;
4248 pSMB->MaxParameterCount = cpu_to_le16(2);
4249 pSMB->MaxDataCount = cpu_to_le16(1000);
4250 pSMB->MaxSetupCount = 0;
4254 pSMB->Reserved2 = 0;
4255 byte_count = params + 1 /* pad */ ;
4256 pSMB->TotalParameterCount = cpu_to_le16(params);
4257 pSMB->ParameterCount = pSMB->TotalParameterCount;
4258 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4259 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4260 pSMB->DataCount = 0;
4261 pSMB->DataOffset = 0;
4262 pSMB->SetupCount = 1;
4263 pSMB->Reserved3 = 0;
4264 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4265 pSMB->InformationLevel = cpu_to_le16(SMB_INFO_ALLOCATION);
4266 pSMB->hdr.smb_buf_length += byte_count;
4267 pSMB->ByteCount = cpu_to_le16(byte_count);
4269 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4270 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4272 cFYI(1, "Send error in QFSInfo = %d", rc);
4273 } else { /* decode response */
4274 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4276 if (rc || (pSMBr->ByteCount < 18))
4277 rc = -EIO; /* bad smb */
4279 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4280 cFYI(1, "qfsinf resp BCC: %d Offset %d",
4281 pSMBr->ByteCount, data_offset);
4283 response_data = (FILE_SYSTEM_ALLOC_INFO *)
4284 (((char *) &pSMBr->hdr.Protocol) + data_offset);
4286 le16_to_cpu(response_data->BytesPerSector) *
4287 le32_to_cpu(response_data->
4288 SectorsPerAllocationUnit);
4290 le32_to_cpu(response_data->TotalAllocationUnits);
4291 FSData->f_bfree = FSData->f_bavail =
4292 le32_to_cpu(response_data->FreeAllocationUnits);
4293 cFYI(1, "Blocks: %lld Free: %lld Block size %ld",
4294 (unsigned long long)FSData->f_blocks,
4295 (unsigned long long)FSData->f_bfree,
4299 cifs_buf_release(pSMB);
4302 goto oldQFSInfoRetry;
4308 CIFSSMBQFSInfo(const int xid, struct cifsTconInfo *tcon, struct kstatfs *FSData)
4310 /* level 0x103 SMB_QUERY_FILE_SYSTEM_INFO */
4311 TRANSACTION2_QFSI_REQ *pSMB = NULL;
4312 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4313 FILE_SYSTEM_INFO *response_data;
4315 int bytes_returned = 0;
4316 __u16 params, byte_count;
4318 cFYI(1, "In QFSInfo");
4320 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4325 params = 2; /* level */
4326 pSMB->TotalDataCount = 0;
4327 pSMB->MaxParameterCount = cpu_to_le16(2);
4328 pSMB->MaxDataCount = cpu_to_le16(1000);
4329 pSMB->MaxSetupCount = 0;
4333 pSMB->Reserved2 = 0;
4334 byte_count = params + 1 /* pad */ ;
4335 pSMB->TotalParameterCount = cpu_to_le16(params);
4336 pSMB->ParameterCount = pSMB->TotalParameterCount;
4337 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4338 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4339 pSMB->DataCount = 0;
4340 pSMB->DataOffset = 0;
4341 pSMB->SetupCount = 1;
4342 pSMB->Reserved3 = 0;
4343 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4344 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_SIZE_INFO);
4345 pSMB->hdr.smb_buf_length += byte_count;
4346 pSMB->ByteCount = cpu_to_le16(byte_count);
4348 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4349 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4351 cFYI(1, "Send error in QFSInfo = %d", rc);
4352 } else { /* decode response */
4353 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4355 if (rc || (pSMBr->ByteCount < 24))
4356 rc = -EIO; /* bad smb */
4358 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4362 *) (((char *) &pSMBr->hdr.Protocol) +
4365 le32_to_cpu(response_data->BytesPerSector) *
4366 le32_to_cpu(response_data->
4367 SectorsPerAllocationUnit);
4369 le64_to_cpu(response_data->TotalAllocationUnits);
4370 FSData->f_bfree = FSData->f_bavail =
4371 le64_to_cpu(response_data->FreeAllocationUnits);
4372 cFYI(1, "Blocks: %lld Free: %lld Block size %ld",
4373 (unsigned long long)FSData->f_blocks,
4374 (unsigned long long)FSData->f_bfree,
4378 cifs_buf_release(pSMB);
4387 CIFSSMBQFSAttributeInfo(const int xid, struct cifsTconInfo *tcon)
4389 /* level 0x105 SMB_QUERY_FILE_SYSTEM_INFO */
4390 TRANSACTION2_QFSI_REQ *pSMB = NULL;
4391 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4392 FILE_SYSTEM_ATTRIBUTE_INFO *response_data;
4394 int bytes_returned = 0;
4395 __u16 params, byte_count;
4397 cFYI(1, "In QFSAttributeInfo");
4399 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4404 params = 2; /* level */
4405 pSMB->TotalDataCount = 0;
4406 pSMB->MaxParameterCount = cpu_to_le16(2);
4407 /* BB find exact max SMB PDU from sess structure BB */
4408 pSMB->MaxDataCount = cpu_to_le16(1000);
4409 pSMB->MaxSetupCount = 0;
4413 pSMB->Reserved2 = 0;
4414 byte_count = params + 1 /* pad */ ;
4415 pSMB->TotalParameterCount = cpu_to_le16(params);
4416 pSMB->ParameterCount = pSMB->TotalParameterCount;
4417 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4418 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4419 pSMB->DataCount = 0;
4420 pSMB->DataOffset = 0;
4421 pSMB->SetupCount = 1;
4422 pSMB->Reserved3 = 0;
4423 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4424 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_ATTRIBUTE_INFO);
4425 pSMB->hdr.smb_buf_length += byte_count;
4426 pSMB->ByteCount = cpu_to_le16(byte_count);
4428 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4429 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4431 cERROR(1, "Send error in QFSAttributeInfo = %d", rc);
4432 } else { /* decode response */
4433 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4435 if (rc || (pSMBr->ByteCount < 13)) {
4436 /* BB also check if enough bytes returned */
4437 rc = -EIO; /* bad smb */
4439 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4441 (FILE_SYSTEM_ATTRIBUTE_INFO
4442 *) (((char *) &pSMBr->hdr.Protocol) +
4444 memcpy(&tcon->fsAttrInfo, response_data,
4445 sizeof(FILE_SYSTEM_ATTRIBUTE_INFO));
4448 cifs_buf_release(pSMB);
4451 goto QFSAttributeRetry;
4457 CIFSSMBQFSDeviceInfo(const int xid, struct cifsTconInfo *tcon)
4459 /* level 0x104 SMB_QUERY_FILE_SYSTEM_INFO */
4460 TRANSACTION2_QFSI_REQ *pSMB = NULL;
4461 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4462 FILE_SYSTEM_DEVICE_INFO *response_data;
4464 int bytes_returned = 0;
4465 __u16 params, byte_count;
4467 cFYI(1, "In QFSDeviceInfo");
4469 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4474 params = 2; /* level */
4475 pSMB->TotalDataCount = 0;
4476 pSMB->MaxParameterCount = cpu_to_le16(2);
4477 /* BB find exact max SMB PDU from sess structure BB */
4478 pSMB->MaxDataCount = cpu_to_le16(1000);
4479 pSMB->MaxSetupCount = 0;
4483 pSMB->Reserved2 = 0;
4484 byte_count = params + 1 /* pad */ ;
4485 pSMB->TotalParameterCount = cpu_to_le16(params);
4486 pSMB->ParameterCount = pSMB->TotalParameterCount;
4487 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4488 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4490 pSMB->DataCount = 0;
4491 pSMB->DataOffset = 0;
4492 pSMB->SetupCount = 1;
4493 pSMB->Reserved3 = 0;
4494 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4495 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_DEVICE_INFO);
4496 pSMB->hdr.smb_buf_length += byte_count;
4497 pSMB->ByteCount = cpu_to_le16(byte_count);
4499 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4500 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4502 cFYI(1, "Send error in QFSDeviceInfo = %d", rc);
4503 } else { /* decode response */
4504 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4506 if (rc || (pSMBr->ByteCount < sizeof(FILE_SYSTEM_DEVICE_INFO)))
4507 rc = -EIO; /* bad smb */
4509 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4511 (FILE_SYSTEM_DEVICE_INFO *)
4512 (((char *) &pSMBr->hdr.Protocol) +
4514 memcpy(&tcon->fsDevInfo, response_data,
4515 sizeof(FILE_SYSTEM_DEVICE_INFO));
4518 cifs_buf_release(pSMB);
4521 goto QFSDeviceRetry;
4527 CIFSSMBQFSUnixInfo(const int xid, struct cifsTconInfo *tcon)
4529 /* level 0x200 SMB_QUERY_CIFS_UNIX_INFO */
4530 TRANSACTION2_QFSI_REQ *pSMB = NULL;
4531 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4532 FILE_SYSTEM_UNIX_INFO *response_data;
4534 int bytes_returned = 0;
4535 __u16 params, byte_count;
4537 cFYI(1, "In QFSUnixInfo");
4539 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4544 params = 2; /* level */
4545 pSMB->TotalDataCount = 0;
4546 pSMB->DataCount = 0;
4547 pSMB->DataOffset = 0;
4548 pSMB->MaxParameterCount = cpu_to_le16(2);
4549 /* BB find exact max SMB PDU from sess structure BB */
4550 pSMB->MaxDataCount = cpu_to_le16(100);
4551 pSMB->MaxSetupCount = 0;
4555 pSMB->Reserved2 = 0;
4556 byte_count = params + 1 /* pad */ ;
4557 pSMB->ParameterCount = cpu_to_le16(params);
4558 pSMB->TotalParameterCount = pSMB->ParameterCount;
4559 pSMB->ParameterOffset = cpu_to_le16(offsetof(struct
4560 smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4561 pSMB->SetupCount = 1;
4562 pSMB->Reserved3 = 0;
4563 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4564 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_CIFS_UNIX_INFO);
4565 pSMB->hdr.smb_buf_length += byte_count;
4566 pSMB->ByteCount = cpu_to_le16(byte_count);
4568 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4569 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4571 cERROR(1, "Send error in QFSUnixInfo = %d", rc);
4572 } else { /* decode response */
4573 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4575 if (rc || (pSMBr->ByteCount < 13)) {
4576 rc = -EIO; /* bad smb */
4578 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4580 (FILE_SYSTEM_UNIX_INFO
4581 *) (((char *) &pSMBr->hdr.Protocol) +
4583 memcpy(&tcon->fsUnixInfo, response_data,
4584 sizeof(FILE_SYSTEM_UNIX_INFO));
4587 cifs_buf_release(pSMB);
4597 CIFSSMBSetFSUnixInfo(const int xid, struct cifsTconInfo *tcon, __u64 cap)
4599 /* level 0x200 SMB_SET_CIFS_UNIX_INFO */
4600 TRANSACTION2_SETFSI_REQ *pSMB = NULL;
4601 TRANSACTION2_SETFSI_RSP *pSMBr = NULL;
4603 int bytes_returned = 0;
4604 __u16 params, param_offset, offset, byte_count;
4606 cFYI(1, "In SETFSUnixInfo");
4608 /* BB switch to small buf init to save memory */
4609 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4614 params = 4; /* 2 bytes zero followed by info level. */
4615 pSMB->MaxSetupCount = 0;
4619 pSMB->Reserved2 = 0;
4620 param_offset = offsetof(struct smb_com_transaction2_setfsi_req, FileNum)
4622 offset = param_offset + params;
4624 pSMB->MaxParameterCount = cpu_to_le16(4);
4625 /* BB find exact max SMB PDU from sess structure BB */
4626 pSMB->MaxDataCount = cpu_to_le16(100);
4627 pSMB->SetupCount = 1;
4628 pSMB->Reserved3 = 0;
4629 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FS_INFORMATION);
4630 byte_count = 1 /* pad */ + params + 12;
4632 pSMB->DataCount = cpu_to_le16(12);
4633 pSMB->ParameterCount = cpu_to_le16(params);
4634 pSMB->TotalDataCount = pSMB->DataCount;
4635 pSMB->TotalParameterCount = pSMB->ParameterCount;
4636 pSMB->ParameterOffset = cpu_to_le16(param_offset);
4637 pSMB->DataOffset = cpu_to_le16(offset);
4641 pSMB->InformationLevel = cpu_to_le16(SMB_SET_CIFS_UNIX_INFO);
4644 pSMB->ClientUnixMajor = cpu_to_le16(CIFS_UNIX_MAJOR_VERSION);
4645 pSMB->ClientUnixMinor = cpu_to_le16(CIFS_UNIX_MINOR_VERSION);
4646 pSMB->ClientUnixCap = cpu_to_le64(cap);
4648 pSMB->hdr.smb_buf_length += byte_count;
4649 pSMB->ByteCount = cpu_to_le16(byte_count);
4651 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4652 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4654 cERROR(1, "Send error in SETFSUnixInfo = %d", rc);
4655 } else { /* decode response */
4656 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4658 rc = -EIO; /* bad smb */
4660 cifs_buf_release(pSMB);
4663 goto SETFSUnixRetry;
4671 CIFSSMBQFSPosixInfo(const int xid, struct cifsTconInfo *tcon,
4672 struct kstatfs *FSData)
4674 /* level 0x201 SMB_QUERY_CIFS_POSIX_INFO */
4675 TRANSACTION2_QFSI_REQ *pSMB = NULL;
4676 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4677 FILE_SYSTEM_POSIX_INFO *response_data;
4679 int bytes_returned = 0;
4680 __u16 params, byte_count;
4682 cFYI(1, "In QFSPosixInfo");
4684 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4689 params = 2; /* level */
4690 pSMB->TotalDataCount = 0;
4691 pSMB->DataCount = 0;
4692 pSMB->DataOffset = 0;
4693 pSMB->MaxParameterCount = cpu_to_le16(2);
4694 /* BB find exact max SMB PDU from sess structure BB */
4695 pSMB->MaxDataCount = cpu_to_le16(100);
4696 pSMB->MaxSetupCount = 0;
4700 pSMB->Reserved2 = 0;
4701 byte_count = params + 1 /* pad */ ;
4702 pSMB->ParameterCount = cpu_to_le16(params);
4703 pSMB->TotalParameterCount = pSMB->ParameterCount;
4704 pSMB->ParameterOffset = cpu_to_le16(offsetof(struct
4705 smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4706 pSMB->SetupCount = 1;
4707 pSMB->Reserved3 = 0;
4708 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4709 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_POSIX_FS_INFO);
4710 pSMB->hdr.smb_buf_length += byte_count;
4711 pSMB->ByteCount = cpu_to_le16(byte_count);
4713 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4714 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4716 cFYI(1, "Send error in QFSUnixInfo = %d", rc);
4717 } else { /* decode response */
4718 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4720 if (rc || (pSMBr->ByteCount < 13)) {
4721 rc = -EIO; /* bad smb */
4723 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4725 (FILE_SYSTEM_POSIX_INFO
4726 *) (((char *) &pSMBr->hdr.Protocol) +
4729 le32_to_cpu(response_data->BlockSize);
4731 le64_to_cpu(response_data->TotalBlocks);
4733 le64_to_cpu(response_data->BlocksAvail);
4734 if (response_data->UserBlocksAvail == cpu_to_le64(-1)) {
4735 FSData->f_bavail = FSData->f_bfree;
4738 le64_to_cpu(response_data->UserBlocksAvail);
4740 if (response_data->TotalFileNodes != cpu_to_le64(-1))
4742 le64_to_cpu(response_data->TotalFileNodes);
4743 if (response_data->FreeFileNodes != cpu_to_le64(-1))
4745 le64_to_cpu(response_data->FreeFileNodes);
4748 cifs_buf_release(pSMB);
4757 /* We can not use write of zero bytes trick to
4758 set file size due to need for large file support. Also note that
4759 this SetPathInfo is preferred to SetFileInfo based method in next
4760 routine which is only needed to work around a sharing violation bug
4761 in Samba which this routine can run into */
4764 CIFSSMBSetEOF(const int xid, struct cifsTconInfo *tcon, const char *fileName,
4765 __u64 size, bool SetAllocation,
4766 const struct nls_table *nls_codepage, int remap)
4768 struct smb_com_transaction2_spi_req *pSMB = NULL;
4769 struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
4770 struct file_end_of_file_info *parm_data;
4773 int bytes_returned = 0;
4774 __u16 params, byte_count, data_count, param_offset, offset;
4776 cFYI(1, "In SetEOF");
4778 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4783 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4785 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
4786 PATH_MAX, nls_codepage, remap);
4787 name_len++; /* trailing null */
4789 } else { /* BB improve the check for buffer overruns BB */
4790 name_len = strnlen(fileName, PATH_MAX);
4791 name_len++; /* trailing null */
4792 strncpy(pSMB->FileName, fileName, name_len);
4794 params = 6 + name_len;
4795 data_count = sizeof(struct file_end_of_file_info);
4796 pSMB->MaxParameterCount = cpu_to_le16(2);
4797 pSMB->MaxDataCount = cpu_to_le16(4100);
4798 pSMB->MaxSetupCount = 0;
4802 pSMB->Reserved2 = 0;
4803 param_offset = offsetof(struct smb_com_transaction2_spi_req,
4804 InformationLevel) - 4;
4805 offset = param_offset + params;
4806 if (SetAllocation) {
4807 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
4808 pSMB->InformationLevel =
4809 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2);
4811 pSMB->InformationLevel =
4812 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO);
4813 } else /* Set File Size */ {
4814 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
4815 pSMB->InformationLevel =
4816 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO2);
4818 pSMB->InformationLevel =
4819 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO);
4823 (struct file_end_of_file_info *) (((char *) &pSMB->hdr.Protocol) +
4825 pSMB->ParameterOffset = cpu_to_le16(param_offset);
4826 pSMB->DataOffset = cpu_to_le16(offset);
4827 pSMB->SetupCount = 1;
4828 pSMB->Reserved3 = 0;
4829 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
4830 byte_count = 3 /* pad */ + params + data_count;
4831 pSMB->DataCount = cpu_to_le16(data_count);
4832 pSMB->TotalDataCount = pSMB->DataCount;
4833 pSMB->ParameterCount = cpu_to_le16(params);
4834 pSMB->TotalParameterCount = pSMB->ParameterCount;
4835 pSMB->Reserved4 = 0;
4836 pSMB->hdr.smb_buf_length += byte_count;
4837 parm_data->FileSize = cpu_to_le64(size);
4838 pSMB->ByteCount = cpu_to_le16(byte_count);
4839 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4840 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4842 cFYI(1, "SetPathInfo (file size) returned %d", rc);
4844 cifs_buf_release(pSMB);
4853 CIFSSMBSetFileSize(const int xid, struct cifsTconInfo *tcon, __u64 size,
4854 __u16 fid, __u32 pid_of_opener, bool SetAllocation)
4856 struct smb_com_transaction2_sfi_req *pSMB = NULL;
4858 struct file_end_of_file_info *parm_data;
4860 __u16 params, param_offset, offset, byte_count, count;
4862 cFYI(1, "SetFileSize (via SetFileInfo) %lld",
4864 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
4869 pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
4870 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));
4873 pSMB->MaxSetupCount = 0;
4877 pSMB->Reserved2 = 0;
4878 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
4879 offset = param_offset + params;
4881 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
4883 count = sizeof(struct file_end_of_file_info);
4884 pSMB->MaxParameterCount = cpu_to_le16(2);
4885 /* BB find exact max SMB PDU from sess structure BB */
4886 pSMB->MaxDataCount = cpu_to_le16(1000);
4887 pSMB->SetupCount = 1;
4888 pSMB->Reserved3 = 0;
4889 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
4890 byte_count = 3 /* pad */ + params + count;
4891 pSMB->DataCount = cpu_to_le16(count);
4892 pSMB->ParameterCount = cpu_to_le16(params);
4893 pSMB->TotalDataCount = pSMB->DataCount;
4894 pSMB->TotalParameterCount = pSMB->ParameterCount;
4895 pSMB->ParameterOffset = cpu_to_le16(param_offset);
4897 (struct file_end_of_file_info *) (((char *) &pSMB->hdr.Protocol)
4899 pSMB->DataOffset = cpu_to_le16(offset);
4900 parm_data->FileSize = cpu_to_le64(size);
4902 if (SetAllocation) {
4903 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
4904 pSMB->InformationLevel =
4905 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2);
4907 pSMB->InformationLevel =
4908 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO);
4909 } else /* Set File Size */ {
4910 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
4911 pSMB->InformationLevel =
4912 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO2);
4914 pSMB->InformationLevel =
4915 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO);
4917 pSMB->Reserved4 = 0;
4918 pSMB->hdr.smb_buf_length += byte_count;
4919 pSMB->ByteCount = cpu_to_le16(byte_count);
4920 rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0);
4922 cFYI(1, "Send error in SetFileInfo (SetFileSize) = %d", rc);
4925 /* Note: On -EAGAIN error only caller can retry on handle based calls
4926 since file handle passed in no longer valid */
4931 /* Some legacy servers such as NT4 require that the file times be set on
4932 an open handle, rather than by pathname - this is awkward due to
4933 potential access conflicts on the open, but it is unavoidable for these
4934 old servers since the only other choice is to go from 100 nanosecond DCE
4935 time and resort to the original setpathinfo level which takes the ancient
4936 DOS time format with 2 second granularity */
4938 CIFSSMBSetFileInfo(const int xid, struct cifsTconInfo *tcon,
4939 const FILE_BASIC_INFO *data, __u16 fid, __u32 pid_of_opener)
4941 struct smb_com_transaction2_sfi_req *pSMB = NULL;
4944 __u16 params, param_offset, offset, byte_count, count;
4946 cFYI(1, "Set Times (via SetFileInfo)");
4947 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
4952 pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
4953 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));
4956 pSMB->MaxSetupCount = 0;
4960 pSMB->Reserved2 = 0;
4961 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
4962 offset = param_offset + params;
4964 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
4966 count = sizeof(FILE_BASIC_INFO);
4967 pSMB->MaxParameterCount = cpu_to_le16(2);
4968 /* BB find max SMB PDU from sess */
4969 pSMB->MaxDataCount = cpu_to_le16(1000);
4970 pSMB->SetupCount = 1;
4971 pSMB->Reserved3 = 0;
4972 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
4973 byte_count = 3 /* pad */ + params + count;
4974 pSMB->DataCount = cpu_to_le16(count);
4975 pSMB->ParameterCount = cpu_to_le16(params);
4976 pSMB->TotalDataCount = pSMB->DataCount;
4977 pSMB->TotalParameterCount = pSMB->ParameterCount;
4978 pSMB->ParameterOffset = cpu_to_le16(param_offset);
4979 pSMB->DataOffset = cpu_to_le16(offset);
4981 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
4982 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO2);
4984 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO);
4985 pSMB->Reserved4 = 0;
4986 pSMB->hdr.smb_buf_length += byte_count;
4987 pSMB->ByteCount = cpu_to_le16(byte_count);
4988 memcpy(data_offset, data, sizeof(FILE_BASIC_INFO));
4989 rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0);
4991 cFYI(1, "Send error in Set Time (SetFileInfo) = %d", rc);
4993 /* Note: On -EAGAIN error only caller can retry on handle based calls
4994 since file handle passed in no longer valid */
5000 CIFSSMBSetFileDisposition(const int xid, struct cifsTconInfo *tcon,
5001 bool delete_file, __u16 fid, __u32 pid_of_opener)
5003 struct smb_com_transaction2_sfi_req *pSMB = NULL;
5006 __u16 params, param_offset, offset, byte_count, count;
5008 cFYI(1, "Set File Disposition (via SetFileInfo)");
5009 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
5014 pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
5015 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));
5018 pSMB->MaxSetupCount = 0;
5022 pSMB->Reserved2 = 0;
5023 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
5024 offset = param_offset + params;
5026 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
5029 pSMB->MaxParameterCount = cpu_to_le16(2);
5030 /* BB find max SMB PDU from sess */
5031 pSMB->MaxDataCount = cpu_to_le16(1000);
5032 pSMB->SetupCount = 1;
5033 pSMB->Reserved3 = 0;
5034 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
5035 byte_count = 3 /* pad */ + params + count;
5036 pSMB->DataCount = cpu_to_le16(count);
5037 pSMB->ParameterCount = cpu_to_le16(params);
5038 pSMB->TotalDataCount = pSMB->DataCount;
5039 pSMB->TotalParameterCount = pSMB->ParameterCount;
5040 pSMB->ParameterOffset = cpu_to_le16(param_offset);
5041 pSMB->DataOffset = cpu_to_le16(offset);
5043 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_DISPOSITION_INFO);
5044 pSMB->Reserved4 = 0;
5045 pSMB->hdr.smb_buf_length += byte_count;
5046 pSMB->ByteCount = cpu_to_le16(byte_count);
5047 *data_offset = delete_file ? 1 : 0;
5048 rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0);
5050 cFYI(1, "Send error in SetFileDisposition = %d", rc);
5056 CIFSSMBSetPathInfo(const int xid, struct cifsTconInfo *tcon,
5057 const char *fileName, const FILE_BASIC_INFO *data,
5058 const struct nls_table *nls_codepage, int remap)
5060 TRANSACTION2_SPI_REQ *pSMB = NULL;
5061 TRANSACTION2_SPI_RSP *pSMBr = NULL;
5064 int bytes_returned = 0;
5066 __u16 params, param_offset, offset, byte_count, count;
5068 cFYI(1, "In SetTimes");
5071 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5076 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5078 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
5079 PATH_MAX, nls_codepage, remap);
5080 name_len++; /* trailing null */
5082 } else { /* BB improve the check for buffer overruns BB */
5083 name_len = strnlen(fileName, PATH_MAX);
5084 name_len++; /* trailing null */
5085 strncpy(pSMB->FileName, fileName, name_len);
5088 params = 6 + name_len;
5089 count = sizeof(FILE_BASIC_INFO);
5090 pSMB->MaxParameterCount = cpu_to_le16(2);
5091 /* BB find max SMB PDU from sess structure BB */
5092 pSMB->MaxDataCount = cpu_to_le16(1000);
5093 pSMB->MaxSetupCount = 0;
5097 pSMB->Reserved2 = 0;
5098 param_offset = offsetof(struct smb_com_transaction2_spi_req,
5099 InformationLevel) - 4;
5100 offset = param_offset + params;
5101 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
5102 pSMB->ParameterOffset = cpu_to_le16(param_offset);
5103 pSMB->DataOffset = cpu_to_le16(offset);
5104 pSMB->SetupCount = 1;
5105 pSMB->Reserved3 = 0;
5106 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
5107 byte_count = 3 /* pad */ + params + count;
5109 pSMB->DataCount = cpu_to_le16(count);
5110 pSMB->ParameterCount = cpu_to_le16(params);
5111 pSMB->TotalDataCount = pSMB->DataCount;
5112 pSMB->TotalParameterCount = pSMB->ParameterCount;
5113 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
5114 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO2);
5116 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO);
5117 pSMB->Reserved4 = 0;
5118 pSMB->hdr.smb_buf_length += byte_count;
5119 memcpy(data_offset, data, sizeof(FILE_BASIC_INFO));
5120 pSMB->ByteCount = cpu_to_le16(byte_count);
5121 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5122 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5124 cFYI(1, "SetPathInfo (times) returned %d", rc);
5126 cifs_buf_release(pSMB);
5134 /* Can not be used to set time stamps yet (due to old DOS time format) */
5135 /* Can be used to set attributes */
5136 #if 0 /* Possibly not needed - since it turns out that strangely NT4 has a bug
5137 handling it anyway and NT4 was what we thought it would be needed for
5138 Do not delete it until we prove whether needed for Win9x though */
5140 CIFSSMBSetAttrLegacy(int xid, struct cifsTconInfo *tcon, char *fileName,
5141 __u16 dos_attrs, const struct nls_table *nls_codepage)
5143 SETATTR_REQ *pSMB = NULL;
5144 SETATTR_RSP *pSMBr = NULL;
5149 cFYI(1, "In SetAttrLegacy");
5152 rc = smb_init(SMB_COM_SETATTR, 8, tcon, (void **) &pSMB,
5157 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5159 ConvertToUCS((__le16 *) pSMB->fileName, fileName,
5160 PATH_MAX, nls_codepage);
5161 name_len++; /* trailing null */
5163 } else { /* BB improve the check for buffer overruns BB */
5164 name_len = strnlen(fileName, PATH_MAX);
5165 name_len++; /* trailing null */
5166 strncpy(pSMB->fileName, fileName, name_len);
5168 pSMB->attr = cpu_to_le16(dos_attrs);
5169 pSMB->BufferFormat = 0x04;
5170 pSMB->hdr.smb_buf_length += name_len + 1;
5171 pSMB->ByteCount = cpu_to_le16(name_len + 1);
5172 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5173 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5175 cFYI(1, "Error in LegacySetAttr = %d", rc);
5177 cifs_buf_release(pSMB);
5180 goto SetAttrLgcyRetry;
5184 #endif /* temporarily unneeded SetAttr legacy function */
5187 cifs_fill_unix_set_info(FILE_UNIX_BASIC_INFO *data_offset,
5188 const struct cifs_unix_set_info_args *args)
5190 u64 mode = args->mode;
5193 * Samba server ignores set of file size to zero due to bugs in some
5194 * older clients, but we should be precise - we use SetFileSize to
5195 * set file size and do not want to truncate file size to zero
5196 * accidently as happened on one Samba server beta by putting
5197 * zero instead of -1 here
5199 data_offset->EndOfFile = cpu_to_le64(NO_CHANGE_64);
5200 data_offset->NumOfBytes = cpu_to_le64(NO_CHANGE_64);
5201 data_offset->LastStatusChange = cpu_to_le64(args->ctime);
5202 data_offset->LastAccessTime = cpu_to_le64(args->atime);
5203 data_offset->LastModificationTime = cpu_to_le64(args->mtime);
5204 data_offset->Uid = cpu_to_le64(args->uid);
5205 data_offset->Gid = cpu_to_le64(args->gid);
5206 /* better to leave device as zero when it is */
5207 data_offset->DevMajor = cpu_to_le64(MAJOR(args->device));
5208 data_offset->DevMinor = cpu_to_le64(MINOR(args->device));
5209 data_offset->Permissions = cpu_to_le64(mode);
5212 data_offset->Type = cpu_to_le32(UNIX_FILE);
5213 else if (S_ISDIR(mode))
5214 data_offset->Type = cpu_to_le32(UNIX_DIR);
5215 else if (S_ISLNK(mode))
5216 data_offset->Type = cpu_to_le32(UNIX_SYMLINK);
5217 else if (S_ISCHR(mode))
5218 data_offset->Type = cpu_to_le32(UNIX_CHARDEV);
5219 else if (S_ISBLK(mode))
5220 data_offset->Type = cpu_to_le32(UNIX_BLOCKDEV);
5221 else if (S_ISFIFO(mode))
5222 data_offset->Type = cpu_to_le32(UNIX_FIFO);
5223 else if (S_ISSOCK(mode))
5224 data_offset->Type = cpu_to_le32(UNIX_SOCKET);
5228 CIFSSMBUnixSetFileInfo(const int xid, struct cifsTconInfo *tcon,
5229 const struct cifs_unix_set_info_args *args,
5230 u16 fid, u32 pid_of_opener)
5232 struct smb_com_transaction2_sfi_req *pSMB = NULL;
5233 FILE_UNIX_BASIC_INFO *data_offset;
5235 u16 params, param_offset, offset, byte_count, count;
5237 cFYI(1, "Set Unix Info (via SetFileInfo)");
5238 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
5243 pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
5244 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));
5247 pSMB->MaxSetupCount = 0;
5251 pSMB->Reserved2 = 0;
5252 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
5253 offset = param_offset + params;
5255 data_offset = (FILE_UNIX_BASIC_INFO *)
5256 ((char *)(&pSMB->hdr.Protocol) + offset);
5257 count = sizeof(FILE_UNIX_BASIC_INFO);
5259 pSMB->MaxParameterCount = cpu_to_le16(2);
5260 /* BB find max SMB PDU from sess */
5261 pSMB->MaxDataCount = cpu_to_le16(1000);
5262 pSMB->SetupCount = 1;
5263 pSMB->Reserved3 = 0;
5264 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
5265 byte_count = 3 /* pad */ + params + count;
5266 pSMB->DataCount = cpu_to_le16(count);
5267 pSMB->ParameterCount = cpu_to_le16(params);
5268 pSMB->TotalDataCount = pSMB->DataCount;
5269 pSMB->TotalParameterCount = pSMB->ParameterCount;
5270 pSMB->ParameterOffset = cpu_to_le16(param_offset);
5271 pSMB->DataOffset = cpu_to_le16(offset);
5273 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_BASIC);
5274 pSMB->Reserved4 = 0;
5275 pSMB->hdr.smb_buf_length += byte_count;
5276 pSMB->ByteCount = cpu_to_le16(byte_count);
5278 cifs_fill_unix_set_info(data_offset, args);
5280 rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0);
5282 cFYI(1, "Send error in Set Time (SetFileInfo) = %d", rc);
5284 /* Note: On -EAGAIN error only caller can retry on handle based calls
5285 since file handle passed in no longer valid */
5291 CIFSSMBUnixSetPathInfo(const int xid, struct cifsTconInfo *tcon, char *fileName,
5292 const struct cifs_unix_set_info_args *args,
5293 const struct nls_table *nls_codepage, int remap)
5295 TRANSACTION2_SPI_REQ *pSMB = NULL;
5296 TRANSACTION2_SPI_RSP *pSMBr = NULL;
5299 int bytes_returned = 0;
5300 FILE_UNIX_BASIC_INFO *data_offset;
5301 __u16 params, param_offset, offset, count, byte_count;
5303 cFYI(1, "In SetUID/GID/Mode");
5305 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5310 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5312 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
5313 PATH_MAX, nls_codepage, remap);
5314 name_len++; /* trailing null */
5316 } else { /* BB improve the check for buffer overruns BB */
5317 name_len = strnlen(fileName, PATH_MAX);
5318 name_len++; /* trailing null */
5319 strncpy(pSMB->FileName, fileName, name_len);
5322 params = 6 + name_len;
5323 count = sizeof(FILE_UNIX_BASIC_INFO);
5324 pSMB->MaxParameterCount = cpu_to_le16(2);
5325 /* BB find max SMB PDU from sess structure BB */
5326 pSMB->MaxDataCount = cpu_to_le16(1000);
5327 pSMB->MaxSetupCount = 0;
5331 pSMB->Reserved2 = 0;
5332 param_offset = offsetof(struct smb_com_transaction2_spi_req,
5333 InformationLevel) - 4;
5334 offset = param_offset + params;
5336 (FILE_UNIX_BASIC_INFO *) ((char *) &pSMB->hdr.Protocol +
5338 memset(data_offset, 0, count);
5339 pSMB->DataOffset = cpu_to_le16(offset);
5340 pSMB->ParameterOffset = cpu_to_le16(param_offset);
5341 pSMB->SetupCount = 1;
5342 pSMB->Reserved3 = 0;
5343 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
5344 byte_count = 3 /* pad */ + params + count;
5345 pSMB->ParameterCount = cpu_to_le16(params);
5346 pSMB->DataCount = cpu_to_le16(count);
5347 pSMB->TotalParameterCount = pSMB->ParameterCount;
5348 pSMB->TotalDataCount = pSMB->DataCount;
5349 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_BASIC);
5350 pSMB->Reserved4 = 0;
5351 pSMB->hdr.smb_buf_length += byte_count;
5353 cifs_fill_unix_set_info(data_offset, args);
5355 pSMB->ByteCount = cpu_to_le16(byte_count);
5356 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5357 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5359 cFYI(1, "SetPathInfo (perms) returned %d", rc);
5361 cifs_buf_release(pSMB);
5367 int CIFSSMBNotify(const int xid, struct cifsTconInfo *tcon,
5368 const int notify_subdirs, const __u16 netfid,
5369 __u32 filter, struct file *pfile, int multishot,
5370 const struct nls_table *nls_codepage)
5373 struct smb_com_transaction_change_notify_req *pSMB = NULL;
5374 struct smb_com_ntransaction_change_notify_rsp *pSMBr = NULL;
5375 struct dir_notify_req *dnotify_req;
5378 cFYI(1, "In CIFSSMBNotify for file handle %d", (int)netfid);
5379 rc = smb_init(SMB_COM_NT_TRANSACT, 23, tcon, (void **) &pSMB,
5384 pSMB->TotalParameterCount = 0 ;
5385 pSMB->TotalDataCount = 0;
5386 pSMB->MaxParameterCount = cpu_to_le32(2);
5387 /* BB find exact data count max from sess structure BB */
5388 pSMB->MaxDataCount = 0; /* same in little endian or be */
5389 /* BB VERIFY verify which is correct for above BB */
5390 pSMB->MaxDataCount = cpu_to_le32((tcon->ses->server->maxBuf -
5391 MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
5393 pSMB->MaxSetupCount = 4;
5395 pSMB->ParameterOffset = 0;
5396 pSMB->DataCount = 0;
5397 pSMB->DataOffset = 0;
5398 pSMB->SetupCount = 4; /* single byte does not need le conversion */
5399 pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_NOTIFY_CHANGE);
5400 pSMB->ParameterCount = pSMB->TotalParameterCount;
5402 pSMB->WatchTree = 1; /* one byte - no le conversion needed */
5403 pSMB->Reserved2 = 0;
5404 pSMB->CompletionFilter = cpu_to_le32(filter);
5405 pSMB->Fid = netfid; /* file handle always le */
5406 pSMB->ByteCount = 0;
5408 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5409 (struct smb_hdr *)pSMBr, &bytes_returned,
5412 cFYI(1, "Error in Notify = %d", rc);
5414 /* Add file to outstanding requests */
5415 /* BB change to kmem cache alloc */
5416 dnotify_req = kmalloc(
5417 sizeof(struct dir_notify_req),
5420 dnotify_req->Pid = pSMB->hdr.Pid;
5421 dnotify_req->PidHigh = pSMB->hdr.PidHigh;
5422 dnotify_req->Mid = pSMB->hdr.Mid;
5423 dnotify_req->Tid = pSMB->hdr.Tid;
5424 dnotify_req->Uid = pSMB->hdr.Uid;
5425 dnotify_req->netfid = netfid;
5426 dnotify_req->pfile = pfile;
5427 dnotify_req->filter = filter;
5428 dnotify_req->multishot = multishot;
5429 spin_lock(&GlobalMid_Lock);
5430 list_add_tail(&dnotify_req->lhead,
5431 &GlobalDnotifyReqList);
5432 spin_unlock(&GlobalMid_Lock);
5436 cifs_buf_release(pSMB);
5440 #ifdef CONFIG_CIFS_XATTR
5442 * Do a path-based QUERY_ALL_EAS call and parse the result. This is a common
5443 * function used by listxattr and getxattr type calls. When ea_name is set,
5444 * it looks for that attribute name and stuffs that value into the EAData
5445 * buffer. When ea_name is NULL, it stuffs a list of attribute names into the
5446 * buffer. In both cases, the return value is either the length of the
5447 * resulting data or a negative error code. If EAData is a NULL pointer then
5448 * the data isn't copied to it, but the length is returned.
5451 CIFSSMBQAllEAs(const int xid, struct cifsTconInfo *tcon,
5452 const unsigned char *searchName, const unsigned char *ea_name,
5453 char *EAData, size_t buf_size,
5454 const struct nls_table *nls_codepage, int remap)
5456 /* BB assumes one setup word */
5457 TRANSACTION2_QPI_REQ *pSMB = NULL;
5458 TRANSACTION2_QPI_RSP *pSMBr = NULL;
5462 struct fealist *ea_response_data;
5463 struct fea *temp_fea;
5466 __u16 params, byte_count, data_offset;
5468 cFYI(1, "In Query All EAs path %s", searchName);
5470 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5475 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5477 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
5478 PATH_MAX, nls_codepage, remap);
5479 list_len++; /* trailing null */
5481 } else { /* BB improve the check for buffer overruns BB */
5482 list_len = strnlen(searchName, PATH_MAX);
5483 list_len++; /* trailing null */
5484 strncpy(pSMB->FileName, searchName, list_len);
5487 params = 2 /* level */ + 4 /* reserved */ + list_len /* includes NUL */;
5488 pSMB->TotalDataCount = 0;
5489 pSMB->MaxParameterCount = cpu_to_le16(2);
5490 /* BB find exact max SMB PDU from sess structure BB */
5491 pSMB->MaxDataCount = cpu_to_le16(CIFSMaxBufSize);
5492 pSMB->MaxSetupCount = 0;
5496 pSMB->Reserved2 = 0;
5497 pSMB->ParameterOffset = cpu_to_le16(offsetof(
5498 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
5499 pSMB->DataCount = 0;
5500 pSMB->DataOffset = 0;
5501 pSMB->SetupCount = 1;
5502 pSMB->Reserved3 = 0;
5503 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
5504 byte_count = params + 1 /* pad */ ;
5505 pSMB->TotalParameterCount = cpu_to_le16(params);
5506 pSMB->ParameterCount = pSMB->TotalParameterCount;
5507 pSMB->InformationLevel = cpu_to_le16(SMB_INFO_QUERY_ALL_EAS);
5508 pSMB->Reserved4 = 0;
5509 pSMB->hdr.smb_buf_length += byte_count;
5510 pSMB->ByteCount = cpu_to_le16(byte_count);
5512 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5513 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5515 cFYI(1, "Send error in QueryAllEAs = %d", rc);
5520 /* BB also check enough total bytes returned */
5521 /* BB we need to improve the validity checking
5522 of these trans2 responses */
5524 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
5525 if (rc || (pSMBr->ByteCount < 4)) {
5526 rc = -EIO; /* bad smb */
5530 /* check that length of list is not more than bcc */
5531 /* check that each entry does not go beyond length
5533 /* check that each element of each entry does not
5534 go beyond end of list */
5535 /* validate_trans2_offsets() */
5536 /* BB check if start of smb + data_offset > &bcc+ bcc */
5538 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
5539 ea_response_data = (struct fealist *)
5540 (((char *) &pSMBr->hdr.Protocol) + data_offset);
5542 list_len = le32_to_cpu(ea_response_data->list_len);
5543 cFYI(1, "ea length %d", list_len);
5544 if (list_len <= 8) {
5545 cFYI(1, "empty EA list returned from server");
5549 /* make sure list_len doesn't go past end of SMB */
5550 end_of_smb = (char *)pByteArea(&pSMBr->hdr) + BCC(&pSMBr->hdr);
5551 if ((char *)ea_response_data + list_len > end_of_smb) {
5552 cFYI(1, "EA list appears to go beyond SMB");
5557 /* account for ea list len */
5559 temp_fea = ea_response_data->list;
5560 temp_ptr = (char *)temp_fea;
5561 while (list_len > 0) {
5562 unsigned int name_len;
5567 /* make sure we can read name_len and value_len */
5569 cFYI(1, "EA entry goes beyond length of list");
5574 name_len = temp_fea->name_len;
5575 value_len = le16_to_cpu(temp_fea->value_len);
5576 list_len -= name_len + 1 + value_len;
5578 cFYI(1, "EA entry goes beyond length of list");
5584 if (strncmp(ea_name, temp_ptr, name_len) == 0) {
5585 temp_ptr += name_len + 1;
5589 if ((size_t)value_len > buf_size) {
5593 memcpy(EAData, temp_ptr, value_len);
5597 /* account for prefix user. and trailing null */
5598 rc += (5 + 1 + name_len);
5599 if (rc < (int) buf_size) {
5600 memcpy(EAData, "user.", 5);
5602 memcpy(EAData, temp_ptr, name_len);
5604 /* null terminate name */
5607 } else if (buf_size == 0) {
5608 /* skip copy - calc size only */
5610 /* stop before overrun buffer */
5615 temp_ptr += name_len + 1 + value_len;
5616 temp_fea = (struct fea *)temp_ptr;
5619 /* didn't find the named attribute */
5624 cifs_buf_release(pSMB);
5632 CIFSSMBSetEA(const int xid, struct cifsTconInfo *tcon, const char *fileName,
5633 const char *ea_name, const void *ea_value,
5634 const __u16 ea_value_len, const struct nls_table *nls_codepage,
5637 struct smb_com_transaction2_spi_req *pSMB = NULL;
5638 struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
5639 struct fealist *parm_data;
5642 int bytes_returned = 0;
5643 __u16 params, param_offset, byte_count, offset, count;
5645 cFYI(1, "In SetEA");
5647 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5652 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5654 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
5655 PATH_MAX, nls_codepage, remap);
5656 name_len++; /* trailing null */
5658 } else { /* BB improve the check for buffer overruns BB */
5659 name_len = strnlen(fileName, PATH_MAX);
5660 name_len++; /* trailing null */
5661 strncpy(pSMB->FileName, fileName, name_len);
5664 params = 6 + name_len;
5666 /* done calculating parms using name_len of file name,
5667 now use name_len to calculate length of ea name
5668 we are going to create in the inode xattrs */
5669 if (ea_name == NULL)
5672 name_len = strnlen(ea_name, 255);
5674 count = sizeof(*parm_data) + ea_value_len + name_len;
5675 pSMB->MaxParameterCount = cpu_to_le16(2);
5676 /* BB find max SMB PDU from sess */
5677 pSMB->MaxDataCount = cpu_to_le16(1000);
5678 pSMB->MaxSetupCount = 0;
5682 pSMB->Reserved2 = 0;
5683 param_offset = offsetof(struct smb_com_transaction2_spi_req,
5684 InformationLevel) - 4;
5685 offset = param_offset + params;
5686 pSMB->InformationLevel =
5687 cpu_to_le16(SMB_SET_FILE_EA);
5690 (struct fealist *) (((char *) &pSMB->hdr.Protocol) +
5692 pSMB->ParameterOffset = cpu_to_le16(param_offset);
5693 pSMB->DataOffset = cpu_to_le16(offset);
5694 pSMB->SetupCount = 1;
5695 pSMB->Reserved3 = 0;
5696 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
5697 byte_count = 3 /* pad */ + params + count;
5698 pSMB->DataCount = cpu_to_le16(count);
5699 parm_data->list_len = cpu_to_le32(count);
5700 parm_data->list[0].EA_flags = 0;
5701 /* we checked above that name len is less than 255 */
5702 parm_data->list[0].name_len = (__u8)name_len;
5703 /* EA names are always ASCII */
5705 strncpy(parm_data->list[0].name, ea_name, name_len);
5706 parm_data->list[0].name[name_len] = 0;
5707 parm_data->list[0].value_len = cpu_to_le16(ea_value_len);
5708 /* caller ensures that ea_value_len is less than 64K but
5709 we need to ensure that it fits within the smb */
5711 /*BB add length check to see if it would fit in
5712 negotiated SMB buffer size BB */
5713 /* if (ea_value_len > buffer_size - 512 (enough for header)) */
5715 memcpy(parm_data->list[0].name+name_len+1,
5716 ea_value, ea_value_len);
5718 pSMB->TotalDataCount = pSMB->DataCount;
5719 pSMB->ParameterCount = cpu_to_le16(params);
5720 pSMB->TotalParameterCount = pSMB->ParameterCount;
5721 pSMB->Reserved4 = 0;
5722 pSMB->hdr.smb_buf_length += byte_count;
5723 pSMB->ByteCount = cpu_to_le16(byte_count);
5724 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5725 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5727 cFYI(1, "SetPathInfo (EA) returned %d", rc);
5729 cifs_buf_release(pSMB);