4 * Copyright (C) International Business Machines Corp., 2002,2009
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 if (ses->need_reconnect)
176 rc = cifs_setup_session(0, ses, nls_codepage);
178 /* do we need to reconnect tcon? */
179 if (rc || !tcon->need_reconnect) {
180 mutex_unlock(&ses->session_mutex);
184 mark_open_files_invalid(tcon);
185 rc = CIFSTCon(0, ses, tcon->treeName, tcon, nls_codepage);
186 mutex_unlock(&ses->session_mutex);
187 cFYI(1, "reconnect tcon rc = %d", rc);
193 * FIXME: check if wsize needs updated due to negotiated smb buffer
196 atomic_inc(&tconInfoReconnectCount);
198 /* tell server Unix caps we support */
199 if (ses->capabilities & CAP_UNIX)
200 reset_cifs_unix_caps(0, tcon, NULL, NULL);
203 * Removed call to reopen open files here. It is safer (and faster) to
204 * reopen files one at a time as needed in read and write.
206 * FIXME: what about file locks? don't we need to reclaim them ASAP?
211 * Check if handle based operation so we know whether we can continue
212 * or not without returning to caller to reset file handle
214 switch (smb_command) {
215 case SMB_COM_READ_ANDX:
216 case SMB_COM_WRITE_ANDX:
218 case SMB_COM_FIND_CLOSE2:
219 case SMB_COM_LOCKING_ANDX:
223 unload_nls(nls_codepage);
227 /* Allocate and return pointer to an SMB request buffer, and set basic
228 SMB information in the SMB header. If the return code is zero, this
229 function must have filled in request_buf pointer */
231 small_smb_init(int smb_command, int wct, struct cifsTconInfo *tcon,
236 rc = cifs_reconnect_tcon(tcon, smb_command);
240 *request_buf = cifs_small_buf_get();
241 if (*request_buf == NULL) {
242 /* BB should we add a retry in here if not a writepage? */
246 header_assemble((struct smb_hdr *) *request_buf, smb_command,
250 cifs_stats_inc(&tcon->num_smbs_sent);
256 small_smb_init_no_tc(const int smb_command, const int wct,
257 struct cifsSesInfo *ses, void **request_buf)
260 struct smb_hdr *buffer;
262 rc = small_smb_init(smb_command, wct, NULL, request_buf);
266 buffer = (struct smb_hdr *)*request_buf;
267 buffer->Mid = GetNextMid(ses->server);
268 if (ses->capabilities & CAP_UNICODE)
269 buffer->Flags2 |= SMBFLG2_UNICODE;
270 if (ses->capabilities & CAP_STATUS32)
271 buffer->Flags2 |= SMBFLG2_ERR_STATUS;
273 /* uid, tid can stay at zero as set in header assemble */
275 /* BB add support for turning on the signing when
276 this function is used after 1st of session setup requests */
281 /* If the return code is zero, this function must fill in request_buf pointer */
283 smb_init(int smb_command, int wct, struct cifsTconInfo *tcon,
284 void **request_buf /* returned */ ,
285 void **response_buf /* returned */ )
289 rc = cifs_reconnect_tcon(tcon, smb_command);
293 *request_buf = cifs_buf_get();
294 if (*request_buf == NULL) {
295 /* BB should we add a retry in here if not a writepage? */
298 /* Although the original thought was we needed the response buf for */
299 /* potential retries of smb operations it turns out we can determine */
300 /* from the mid flags when the request buffer can be resent without */
301 /* having to use a second distinct buffer for the response */
303 *response_buf = *request_buf;
305 header_assemble((struct smb_hdr *) *request_buf, smb_command, tcon,
309 cifs_stats_inc(&tcon->num_smbs_sent);
314 static int validate_t2(struct smb_t2_rsp *pSMB)
320 /* check for plausible wct, bcc and t2 data and parm sizes */
321 /* check for parm and data offset going beyond end of smb */
322 if (pSMB->hdr.WordCount >= 10) {
323 if ((le16_to_cpu(pSMB->t2_rsp.ParameterOffset) <= 1024) &&
324 (le16_to_cpu(pSMB->t2_rsp.DataOffset) <= 1024)) {
325 /* check that bcc is at least as big as parms + data */
326 /* check that bcc is less than negotiated smb buffer */
327 total_size = le16_to_cpu(pSMB->t2_rsp.ParameterCount);
328 if (total_size < 512) {
330 le16_to_cpu(pSMB->t2_rsp.DataCount);
331 /* BCC le converted in SendReceive */
332 pBCC = (pSMB->hdr.WordCount * 2) +
333 sizeof(struct smb_hdr) +
335 if ((total_size <= (*(u16 *)pBCC)) &&
337 CIFSMaxBufSize+MAX_CIFS_HDR_SIZE)) {
343 cifs_dump_mem("Invalid transact2 SMB: ", (char *)pSMB,
344 sizeof(struct smb_t2_rsp) + 16);
348 CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses)
351 NEGOTIATE_RSP *pSMBr;
355 struct TCP_Server_Info *server;
357 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 = extended_security | 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 dialect = le16_to_cpu(pSMBr->DialectIndex);
412 cFYI(1, "Dialect: %d", dialect);
413 /* Check wct = 1 error case */
414 if ((pSMBr->hdr.WordCount < 13) || (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 && ((dialect == LANMAN_PROT)
423 || (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.
609 server->capabilities &= ~CAP_EXTENDED_SECURITY;
611 #ifdef CONFIG_CIFS_WEAK_PW_HASH
614 if ((secFlags & CIFSSEC_MAY_SIGN) == 0) {
615 /* MUST_SIGN already includes the MAY_SIGN FLAG
616 so if this is zero it means that signing is disabled */
617 cFYI(1, "Signing disabled");
618 if (server->secMode & SECMODE_SIGN_REQUIRED) {
619 cERROR(1, "Server requires "
620 "packet signing to be enabled in "
621 "/proc/fs/cifs/SecurityFlags.");
625 ~(SECMODE_SIGN_ENABLED | SECMODE_SIGN_REQUIRED);
626 } else if ((secFlags & CIFSSEC_MUST_SIGN) == CIFSSEC_MUST_SIGN) {
627 /* signing required */
628 cFYI(1, "Must sign - secFlags 0x%x", secFlags);
629 if ((server->secMode &
630 (SECMODE_SIGN_ENABLED | SECMODE_SIGN_REQUIRED)) == 0) {
631 cERROR(1, "signing required but server lacks support");
634 server->secMode |= SECMODE_SIGN_REQUIRED;
636 /* signing optional ie CIFSSEC_MAY_SIGN */
637 if ((server->secMode & SECMODE_SIGN_REQUIRED) == 0)
639 ~(SECMODE_SIGN_ENABLED | SECMODE_SIGN_REQUIRED);
643 cifs_buf_release(pSMB);
645 cFYI(1, "negprot rc %d", rc);
650 CIFSSMBTDis(const int xid, struct cifsTconInfo *tcon)
652 struct smb_hdr *smb_buffer;
655 cFYI(1, "In tree disconnect");
657 /* BB: do we need to check this? These should never be NULL. */
658 if ((tcon->ses == NULL) || (tcon->ses->server == NULL))
662 * No need to return error on this operation if tid invalidated and
663 * closed on server already e.g. due to tcp session crashing. Also,
664 * the tcon is no longer on the list, so no need to take lock before
667 if ((tcon->need_reconnect) || (tcon->ses->need_reconnect))
670 rc = small_smb_init(SMB_COM_TREE_DISCONNECT, 0, tcon,
671 (void **)&smb_buffer);
675 rc = SendReceiveNoRsp(xid, tcon->ses, smb_buffer, 0);
677 cFYI(1, "Tree disconnect failed %d", rc);
679 /* No need to return error on this operation if tid invalidated and
680 closed on server already e.g. due to tcp session crashing */
688 CIFSSMBLogoff(const int xid, struct cifsSesInfo *ses)
690 LOGOFF_ANDX_REQ *pSMB;
693 cFYI(1, "In SMBLogoff for session disconnect");
696 * BB: do we need to check validity of ses and server? They should
697 * always be valid since we have an active reference. If not, that
698 * should probably be a BUG()
700 if (!ses || !ses->server)
703 mutex_lock(&ses->session_mutex);
704 if (ses->need_reconnect)
705 goto session_already_dead; /* no need to send SMBlogoff if uid
706 already closed due to reconnect */
707 rc = small_smb_init(SMB_COM_LOGOFF_ANDX, 2, NULL, (void **)&pSMB);
709 mutex_unlock(&ses->session_mutex);
713 pSMB->hdr.Mid = GetNextMid(ses->server);
715 if (ses->server->secMode &
716 (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
717 pSMB->hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
719 pSMB->hdr.Uid = ses->Suid;
721 pSMB->AndXCommand = 0xFF;
722 rc = SendReceiveNoRsp(xid, ses, (struct smb_hdr *) pSMB, 0);
723 session_already_dead:
724 mutex_unlock(&ses->session_mutex);
726 /* if session dead then we do not need to do ulogoff,
727 since server closed smb session, no sense reporting
735 CIFSPOSIXDelFile(const int xid, struct cifsTconInfo *tcon, const char *fileName,
736 __u16 type, const struct nls_table *nls_codepage, int remap)
738 TRANSACTION2_SPI_REQ *pSMB = NULL;
739 TRANSACTION2_SPI_RSP *pSMBr = NULL;
740 struct unlink_psx_rq *pRqD;
743 int bytes_returned = 0;
744 __u16 params, param_offset, offset, byte_count;
746 cFYI(1, "In POSIX delete");
748 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
753 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
755 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
756 PATH_MAX, nls_codepage, remap);
757 name_len++; /* trailing null */
759 } else { /* BB add path length overrun check */
760 name_len = strnlen(fileName, PATH_MAX);
761 name_len++; /* trailing null */
762 strncpy(pSMB->FileName, fileName, name_len);
765 params = 6 + name_len;
766 pSMB->MaxParameterCount = cpu_to_le16(2);
767 pSMB->MaxDataCount = 0; /* BB double check this with jra */
768 pSMB->MaxSetupCount = 0;
773 param_offset = offsetof(struct smb_com_transaction2_spi_req,
774 InformationLevel) - 4;
775 offset = param_offset + params;
777 /* Setup pointer to Request Data (inode type) */
778 pRqD = (struct unlink_psx_rq *)(((char *)&pSMB->hdr.Protocol) + offset);
779 pRqD->type = cpu_to_le16(type);
780 pSMB->ParameterOffset = cpu_to_le16(param_offset);
781 pSMB->DataOffset = cpu_to_le16(offset);
782 pSMB->SetupCount = 1;
784 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
785 byte_count = 3 /* pad */ + params + sizeof(struct unlink_psx_rq);
787 pSMB->DataCount = cpu_to_le16(sizeof(struct unlink_psx_rq));
788 pSMB->TotalDataCount = cpu_to_le16(sizeof(struct unlink_psx_rq));
789 pSMB->ParameterCount = cpu_to_le16(params);
790 pSMB->TotalParameterCount = pSMB->ParameterCount;
791 pSMB->InformationLevel = cpu_to_le16(SMB_POSIX_UNLINK);
793 pSMB->hdr.smb_buf_length += byte_count;
794 pSMB->ByteCount = cpu_to_le16(byte_count);
795 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
796 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
798 cFYI(1, "Posix delete returned %d", rc);
799 cifs_buf_release(pSMB);
801 cifs_stats_inc(&tcon->num_deletes);
810 CIFSSMBDelFile(const int xid, struct cifsTconInfo *tcon, const char *fileName,
811 const struct nls_table *nls_codepage, int remap)
813 DELETE_FILE_REQ *pSMB = NULL;
814 DELETE_FILE_RSP *pSMBr = NULL;
820 rc = smb_init(SMB_COM_DELETE, 1, tcon, (void **) &pSMB,
825 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
827 cifsConvertToUCS((__le16 *) pSMB->fileName, fileName,
828 PATH_MAX, nls_codepage, remap);
829 name_len++; /* trailing null */
831 } else { /* BB improve check for buffer overruns BB */
832 name_len = strnlen(fileName, PATH_MAX);
833 name_len++; /* trailing null */
834 strncpy(pSMB->fileName, fileName, name_len);
836 pSMB->SearchAttributes =
837 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM);
838 pSMB->BufferFormat = 0x04;
839 pSMB->hdr.smb_buf_length += name_len + 1;
840 pSMB->ByteCount = cpu_to_le16(name_len + 1);
841 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
842 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
843 cifs_stats_inc(&tcon->num_deletes);
845 cFYI(1, "Error in RMFile = %d", rc);
847 cifs_buf_release(pSMB);
855 CIFSSMBRmDir(const int xid, struct cifsTconInfo *tcon, const char *dirName,
856 const struct nls_table *nls_codepage, int remap)
858 DELETE_DIRECTORY_REQ *pSMB = NULL;
859 DELETE_DIRECTORY_RSP *pSMBr = NULL;
864 cFYI(1, "In CIFSSMBRmDir");
866 rc = smb_init(SMB_COM_DELETE_DIRECTORY, 0, tcon, (void **) &pSMB,
871 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
872 name_len = cifsConvertToUCS((__le16 *) pSMB->DirName, dirName,
873 PATH_MAX, nls_codepage, remap);
874 name_len++; /* trailing null */
876 } else { /* BB improve check for buffer overruns BB */
877 name_len = strnlen(dirName, PATH_MAX);
878 name_len++; /* trailing null */
879 strncpy(pSMB->DirName, dirName, name_len);
882 pSMB->BufferFormat = 0x04;
883 pSMB->hdr.smb_buf_length += name_len + 1;
884 pSMB->ByteCount = cpu_to_le16(name_len + 1);
885 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
886 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
887 cifs_stats_inc(&tcon->num_rmdirs);
889 cFYI(1, "Error in RMDir = %d", rc);
891 cifs_buf_release(pSMB);
898 CIFSSMBMkDir(const int xid, struct cifsTconInfo *tcon,
899 const char *name, const struct nls_table *nls_codepage, int remap)
902 CREATE_DIRECTORY_REQ *pSMB = NULL;
903 CREATE_DIRECTORY_RSP *pSMBr = NULL;
907 cFYI(1, "In CIFSSMBMkDir");
909 rc = smb_init(SMB_COM_CREATE_DIRECTORY, 0, tcon, (void **) &pSMB,
914 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
915 name_len = cifsConvertToUCS((__le16 *) pSMB->DirName, name,
916 PATH_MAX, nls_codepage, remap);
917 name_len++; /* trailing null */
919 } else { /* BB improve check for buffer overruns BB */
920 name_len = strnlen(name, PATH_MAX);
921 name_len++; /* trailing null */
922 strncpy(pSMB->DirName, name, name_len);
925 pSMB->BufferFormat = 0x04;
926 pSMB->hdr.smb_buf_length += name_len + 1;
927 pSMB->ByteCount = cpu_to_le16(name_len + 1);
928 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
929 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
930 cifs_stats_inc(&tcon->num_mkdirs);
932 cFYI(1, "Error in Mkdir = %d", rc);
934 cifs_buf_release(pSMB);
941 CIFSPOSIXCreate(const int xid, struct cifsTconInfo *tcon, __u32 posix_flags,
942 __u64 mode, __u16 *netfid, FILE_UNIX_BASIC_INFO *pRetData,
943 __u32 *pOplock, const char *name,
944 const struct nls_table *nls_codepage, int remap)
946 TRANSACTION2_SPI_REQ *pSMB = NULL;
947 TRANSACTION2_SPI_RSP *pSMBr = NULL;
950 int bytes_returned = 0;
951 __u16 params, param_offset, offset, byte_count, count;
953 OPEN_PSX_RSP *psx_rsp;
955 cFYI(1, "In POSIX Create");
957 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
962 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
964 cifsConvertToUCS((__le16 *) pSMB->FileName, name,
965 PATH_MAX, nls_codepage, remap);
966 name_len++; /* trailing null */
968 } else { /* BB improve the check for buffer overruns BB */
969 name_len = strnlen(name, PATH_MAX);
970 name_len++; /* trailing null */
971 strncpy(pSMB->FileName, name, name_len);
974 params = 6 + name_len;
975 count = sizeof(OPEN_PSX_REQ);
976 pSMB->MaxParameterCount = cpu_to_le16(2);
977 pSMB->MaxDataCount = cpu_to_le16(1000); /* large enough */
978 pSMB->MaxSetupCount = 0;
983 param_offset = offsetof(struct smb_com_transaction2_spi_req,
984 InformationLevel) - 4;
985 offset = param_offset + params;
986 pdata = (OPEN_PSX_REQ *)(((char *)&pSMB->hdr.Protocol) + offset);
987 pdata->Level = cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC);
988 pdata->Permissions = cpu_to_le64(mode);
989 pdata->PosixOpenFlags = cpu_to_le32(posix_flags);
990 pdata->OpenFlags = cpu_to_le32(*pOplock);
991 pSMB->ParameterOffset = cpu_to_le16(param_offset);
992 pSMB->DataOffset = cpu_to_le16(offset);
993 pSMB->SetupCount = 1;
995 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
996 byte_count = 3 /* pad */ + params + count;
998 pSMB->DataCount = cpu_to_le16(count);
999 pSMB->ParameterCount = cpu_to_le16(params);
1000 pSMB->TotalDataCount = pSMB->DataCount;
1001 pSMB->TotalParameterCount = pSMB->ParameterCount;
1002 pSMB->InformationLevel = cpu_to_le16(SMB_POSIX_OPEN);
1003 pSMB->Reserved4 = 0;
1004 pSMB->hdr.smb_buf_length += byte_count;
1005 pSMB->ByteCount = cpu_to_le16(byte_count);
1006 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1007 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1009 cFYI(1, "Posix create returned %d", rc);
1010 goto psx_create_err;
1013 cFYI(1, "copying inode info");
1014 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
1016 if (rc || (pSMBr->ByteCount < sizeof(OPEN_PSX_RSP))) {
1017 rc = -EIO; /* bad smb */
1018 goto psx_create_err;
1021 /* copy return information to pRetData */
1022 psx_rsp = (OPEN_PSX_RSP *)((char *) &pSMBr->hdr.Protocol
1023 + le16_to_cpu(pSMBr->t2.DataOffset));
1025 *pOplock = le16_to_cpu(psx_rsp->OplockFlags);
1027 *netfid = psx_rsp->Fid; /* cifs fid stays in le */
1028 /* Let caller know file was created so we can set the mode. */
1029 /* Do we care about the CreateAction in any other cases? */
1030 if (cpu_to_le32(FILE_CREATE) == psx_rsp->CreateAction)
1031 *pOplock |= CIFS_CREATE_ACTION;
1032 /* check to make sure response data is there */
1033 if (psx_rsp->ReturnedLevel != cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC)) {
1034 pRetData->Type = cpu_to_le32(-1); /* unknown */
1035 cFYI(DBG2, "unknown type");
1037 if (pSMBr->ByteCount < sizeof(OPEN_PSX_RSP)
1038 + sizeof(FILE_UNIX_BASIC_INFO)) {
1039 cERROR(1, "Open response data too small");
1040 pRetData->Type = cpu_to_le32(-1);
1041 goto psx_create_err;
1043 memcpy((char *) pRetData,
1044 (char *)psx_rsp + sizeof(OPEN_PSX_RSP),
1045 sizeof(FILE_UNIX_BASIC_INFO));
1049 cifs_buf_release(pSMB);
1051 if (posix_flags & SMB_O_DIRECTORY)
1052 cifs_stats_inc(&tcon->num_posixmkdirs);
1054 cifs_stats_inc(&tcon->num_posixopens);
1062 static __u16 convert_disposition(int disposition)
1066 switch (disposition) {
1067 case FILE_SUPERSEDE:
1068 ofun = SMBOPEN_OCREATE | SMBOPEN_OTRUNC;
1071 ofun = SMBOPEN_OAPPEND;
1074 ofun = SMBOPEN_OCREATE;
1077 ofun = SMBOPEN_OCREATE | SMBOPEN_OAPPEND;
1079 case FILE_OVERWRITE:
1080 ofun = SMBOPEN_OTRUNC;
1082 case FILE_OVERWRITE_IF:
1083 ofun = SMBOPEN_OCREATE | SMBOPEN_OTRUNC;
1086 cFYI(1, "unknown disposition %d", disposition);
1087 ofun = SMBOPEN_OAPPEND; /* regular open */
1093 access_flags_to_smbopen_mode(const int access_flags)
1095 int masked_flags = access_flags & (GENERIC_READ | GENERIC_WRITE);
1097 if (masked_flags == GENERIC_READ)
1098 return SMBOPEN_READ;
1099 else if (masked_flags == GENERIC_WRITE)
1100 return SMBOPEN_WRITE;
1102 /* just go for read/write */
1103 return SMBOPEN_READWRITE;
1107 SMBLegacyOpen(const int xid, struct cifsTconInfo *tcon,
1108 const char *fileName, const int openDisposition,
1109 const int access_flags, const int create_options, __u16 *netfid,
1110 int *pOplock, FILE_ALL_INFO *pfile_info,
1111 const struct nls_table *nls_codepage, int remap)
1114 OPENX_REQ *pSMB = NULL;
1115 OPENX_RSP *pSMBr = NULL;
1121 rc = smb_init(SMB_COM_OPEN_ANDX, 15, tcon, (void **) &pSMB,
1126 pSMB->AndXCommand = 0xFF; /* none */
1128 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1129 count = 1; /* account for one byte pad to word boundary */
1131 cifsConvertToUCS((__le16 *) (pSMB->fileName + 1),
1132 fileName, PATH_MAX, nls_codepage, remap);
1133 name_len++; /* trailing null */
1135 } else { /* BB improve check for buffer overruns BB */
1136 count = 0; /* no pad */
1137 name_len = strnlen(fileName, PATH_MAX);
1138 name_len++; /* trailing null */
1139 strncpy(pSMB->fileName, fileName, name_len);
1141 if (*pOplock & REQ_OPLOCK)
1142 pSMB->OpenFlags = cpu_to_le16(REQ_OPLOCK);
1143 else if (*pOplock & REQ_BATCHOPLOCK)
1144 pSMB->OpenFlags = cpu_to_le16(REQ_BATCHOPLOCK);
1146 pSMB->OpenFlags |= cpu_to_le16(REQ_MORE_INFO);
1147 pSMB->Mode = cpu_to_le16(access_flags_to_smbopen_mode(access_flags));
1148 pSMB->Mode |= cpu_to_le16(0x40); /* deny none */
1149 /* set file as system file if special file such
1150 as fifo and server expecting SFU style and
1151 no Unix extensions */
1153 if (create_options & CREATE_OPTION_SPECIAL)
1154 pSMB->FileAttributes = cpu_to_le16(ATTR_SYSTEM);
1155 else /* BB FIXME BB */
1156 pSMB->FileAttributes = cpu_to_le16(0/*ATTR_NORMAL*/);
1158 if (create_options & CREATE_OPTION_READONLY)
1159 pSMB->FileAttributes |= cpu_to_le16(ATTR_READONLY);
1162 /* pSMB->CreateOptions = cpu_to_le32(create_options &
1163 CREATE_OPTIONS_MASK); */
1164 /* BB FIXME END BB */
1166 pSMB->Sattr = cpu_to_le16(ATTR_HIDDEN | ATTR_SYSTEM | ATTR_DIRECTORY);
1167 pSMB->OpenFunction = cpu_to_le16(convert_disposition(openDisposition));
1169 pSMB->hdr.smb_buf_length += count;
1171 pSMB->ByteCount = cpu_to_le16(count);
1172 /* long_op set to 1 to allow for oplock break timeouts */
1173 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1174 (struct smb_hdr *)pSMBr, &bytes_returned, CIFS_LONG_OP);
1175 cifs_stats_inc(&tcon->num_opens);
1177 cFYI(1, "Error in Open = %d", rc);
1179 /* BB verify if wct == 15 */
1181 /* *pOplock = pSMBr->OplockLevel; */ /* BB take from action field*/
1183 *netfid = pSMBr->Fid; /* cifs fid stays in le */
1184 /* Let caller know file was created so we can set the mode. */
1185 /* Do we care about the CreateAction in any other cases? */
1187 /* if (cpu_to_le32(FILE_CREATE) == pSMBr->CreateAction)
1188 *pOplock |= CIFS_CREATE_ACTION; */
1192 pfile_info->CreationTime = 0; /* BB convert CreateTime*/
1193 pfile_info->LastAccessTime = 0; /* BB fixme */
1194 pfile_info->LastWriteTime = 0; /* BB fixme */
1195 pfile_info->ChangeTime = 0; /* BB fixme */
1196 pfile_info->Attributes =
1197 cpu_to_le32(le16_to_cpu(pSMBr->FileAttributes));
1198 /* the file_info buf is endian converted by caller */
1199 pfile_info->AllocationSize =
1200 cpu_to_le64(le32_to_cpu(pSMBr->EndOfFile));
1201 pfile_info->EndOfFile = pfile_info->AllocationSize;
1202 pfile_info->NumberOfLinks = cpu_to_le32(1);
1203 pfile_info->DeletePending = 0;
1207 cifs_buf_release(pSMB);
1214 CIFSSMBOpen(const int xid, struct cifsTconInfo *tcon,
1215 const char *fileName, const int openDisposition,
1216 const int access_flags, const int create_options, __u16 *netfid,
1217 int *pOplock, FILE_ALL_INFO *pfile_info,
1218 const struct nls_table *nls_codepage, int remap)
1221 OPEN_REQ *pSMB = NULL;
1222 OPEN_RSP *pSMBr = NULL;
1228 rc = smb_init(SMB_COM_NT_CREATE_ANDX, 24, tcon, (void **) &pSMB,
1233 pSMB->AndXCommand = 0xFF; /* none */
1235 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1236 count = 1; /* account for one byte pad to word boundary */
1238 cifsConvertToUCS((__le16 *) (pSMB->fileName + 1),
1239 fileName, PATH_MAX, nls_codepage, remap);
1240 name_len++; /* trailing null */
1242 pSMB->NameLength = cpu_to_le16(name_len);
1243 } else { /* BB improve check for buffer overruns BB */
1244 count = 0; /* no pad */
1245 name_len = strnlen(fileName, PATH_MAX);
1246 name_len++; /* trailing null */
1247 pSMB->NameLength = cpu_to_le16(name_len);
1248 strncpy(pSMB->fileName, fileName, name_len);
1250 if (*pOplock & REQ_OPLOCK)
1251 pSMB->OpenFlags = cpu_to_le32(REQ_OPLOCK);
1252 else if (*pOplock & REQ_BATCHOPLOCK)
1253 pSMB->OpenFlags = cpu_to_le32(REQ_BATCHOPLOCK);
1254 pSMB->DesiredAccess = cpu_to_le32(access_flags);
1255 pSMB->AllocationSize = 0;
1256 /* set file as system file if special file such
1257 as fifo and server expecting SFU style and
1258 no Unix extensions */
1259 if (create_options & CREATE_OPTION_SPECIAL)
1260 pSMB->FileAttributes = cpu_to_le32(ATTR_SYSTEM);
1262 pSMB->FileAttributes = cpu_to_le32(ATTR_NORMAL);
1264 /* XP does not handle ATTR_POSIX_SEMANTICS */
1265 /* but it helps speed up case sensitive checks for other
1266 servers such as Samba */
1267 if (tcon->ses->capabilities & CAP_UNIX)
1268 pSMB->FileAttributes |= cpu_to_le32(ATTR_POSIX_SEMANTICS);
1270 if (create_options & CREATE_OPTION_READONLY)
1271 pSMB->FileAttributes |= cpu_to_le32(ATTR_READONLY);
1273 pSMB->ShareAccess = cpu_to_le32(FILE_SHARE_ALL);
1274 pSMB->CreateDisposition = cpu_to_le32(openDisposition);
1275 pSMB->CreateOptions = cpu_to_le32(create_options & CREATE_OPTIONS_MASK);
1276 /* BB Expirement with various impersonation levels and verify */
1277 pSMB->ImpersonationLevel = cpu_to_le32(SECURITY_IMPERSONATION);
1278 pSMB->SecurityFlags =
1279 SECURITY_CONTEXT_TRACKING | SECURITY_EFFECTIVE_ONLY;
1282 pSMB->hdr.smb_buf_length += count;
1284 pSMB->ByteCount = cpu_to_le16(count);
1285 /* long_op set to 1 to allow for oplock break timeouts */
1286 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1287 (struct smb_hdr *)pSMBr, &bytes_returned, CIFS_LONG_OP);
1288 cifs_stats_inc(&tcon->num_opens);
1290 cFYI(1, "Error in Open = %d", rc);
1292 *pOplock = pSMBr->OplockLevel; /* 1 byte no need to le_to_cpu */
1293 *netfid = pSMBr->Fid; /* cifs fid stays in le */
1294 /* Let caller know file was created so we can set the mode. */
1295 /* Do we care about the CreateAction in any other cases? */
1296 if (cpu_to_le32(FILE_CREATE) == pSMBr->CreateAction)
1297 *pOplock |= CIFS_CREATE_ACTION;
1299 memcpy((char *)pfile_info, (char *)&pSMBr->CreationTime,
1300 36 /* CreationTime to Attributes */);
1301 /* the file_info buf is endian converted by caller */
1302 pfile_info->AllocationSize = pSMBr->AllocationSize;
1303 pfile_info->EndOfFile = pSMBr->EndOfFile;
1304 pfile_info->NumberOfLinks = cpu_to_le32(1);
1305 pfile_info->DeletePending = 0;
1309 cifs_buf_release(pSMB);
1316 CIFSSMBRead(const int xid, struct cifsTconInfo *tcon, const int netfid,
1317 const unsigned int count, const __u64 lseek, unsigned int *nbytes,
1318 char **buf, int *pbuf_type)
1321 READ_REQ *pSMB = NULL;
1322 READ_RSP *pSMBr = NULL;
1323 char *pReadData = NULL;
1325 int resp_buf_type = 0;
1328 cFYI(1, "Reading %d bytes on fid %d", count, netfid);
1329 if (tcon->ses->capabilities & CAP_LARGE_FILES)
1332 wct = 10; /* old style read */
1333 if ((lseek >> 32) > 0) {
1334 /* can not handle this big offset for old */
1340 rc = small_smb_init(SMB_COM_READ_ANDX, wct, tcon, (void **) &pSMB);
1344 /* tcon and ses pointer are checked in smb_init */
1345 if (tcon->ses->server == NULL)
1346 return -ECONNABORTED;
1348 pSMB->AndXCommand = 0xFF; /* none */
1350 pSMB->OffsetLow = cpu_to_le32(lseek & 0xFFFFFFFF);
1352 pSMB->OffsetHigh = cpu_to_le32(lseek >> 32);
1354 pSMB->Remaining = 0;
1355 pSMB->MaxCount = cpu_to_le16(count & 0xFFFF);
1356 pSMB->MaxCountHigh = cpu_to_le32(count >> 16);
1358 pSMB->ByteCount = 0; /* no need to do le conversion since 0 */
1360 /* old style read */
1361 struct smb_com_readx_req *pSMBW =
1362 (struct smb_com_readx_req *)pSMB;
1363 pSMBW->ByteCount = 0;
1366 iov[0].iov_base = (char *)pSMB;
1367 iov[0].iov_len = pSMB->hdr.smb_buf_length + 4;
1368 rc = SendReceive2(xid, tcon->ses, iov, 1 /* num iovecs */,
1369 &resp_buf_type, CIFS_STD_OP | CIFS_LOG_ERROR);
1370 cifs_stats_inc(&tcon->num_reads);
1371 pSMBr = (READ_RSP *)iov[0].iov_base;
1373 cERROR(1, "Send error in read = %d", rc);
1375 int data_length = le16_to_cpu(pSMBr->DataLengthHigh);
1376 data_length = data_length << 16;
1377 data_length += le16_to_cpu(pSMBr->DataLength);
1378 *nbytes = data_length;
1380 /*check that DataLength would not go beyond end of SMB */
1381 if ((data_length > CIFSMaxBufSize)
1382 || (data_length > count)) {
1383 cFYI(1, "bad length %d for count %d",
1384 data_length, count);
1388 pReadData = (char *) (&pSMBr->hdr.Protocol) +
1389 le16_to_cpu(pSMBr->DataOffset);
1390 /* if (rc = copy_to_user(buf, pReadData, data_length)) {
1391 cERROR(1, "Faulting on read rc = %d",rc);
1393 }*/ /* can not use copy_to_user when using page cache*/
1395 memcpy(*buf, pReadData, data_length);
1399 /* cifs_small_buf_release(pSMB); */ /* Freed earlier now in SendReceive2 */
1401 if (resp_buf_type == CIFS_SMALL_BUFFER)
1402 cifs_small_buf_release(iov[0].iov_base);
1403 else if (resp_buf_type == CIFS_LARGE_BUFFER)
1404 cifs_buf_release(iov[0].iov_base);
1405 } else if (resp_buf_type != CIFS_NO_BUFFER) {
1406 /* return buffer to caller to free */
1407 *buf = iov[0].iov_base;
1408 if (resp_buf_type == CIFS_SMALL_BUFFER)
1409 *pbuf_type = CIFS_SMALL_BUFFER;
1410 else if (resp_buf_type == CIFS_LARGE_BUFFER)
1411 *pbuf_type = CIFS_LARGE_BUFFER;
1412 } /* else no valid buffer on return - leave as null */
1414 /* Note: On -EAGAIN error only caller can retry on handle based calls
1415 since file handle passed in no longer valid */
1421 CIFSSMBWrite(const int xid, struct cifsTconInfo *tcon,
1422 const int netfid, const unsigned int count,
1423 const __u64 offset, unsigned int *nbytes, const char *buf,
1424 const char __user *ubuf, const int long_op)
1427 WRITE_REQ *pSMB = NULL;
1428 WRITE_RSP *pSMBr = NULL;
1429 int bytes_returned, wct;
1435 /* cFYI(1, "write at %lld %d bytes", offset, count);*/
1436 if (tcon->ses == NULL)
1437 return -ECONNABORTED;
1439 if (tcon->ses->capabilities & CAP_LARGE_FILES)
1443 if ((offset >> 32) > 0) {
1444 /* can not handle big offset for old srv */
1449 rc = smb_init(SMB_COM_WRITE_ANDX, wct, tcon, (void **) &pSMB,
1453 /* tcon and ses pointer are checked in smb_init */
1454 if (tcon->ses->server == NULL)
1455 return -ECONNABORTED;
1457 pSMB->AndXCommand = 0xFF; /* none */
1459 pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF);
1461 pSMB->OffsetHigh = cpu_to_le32(offset >> 32);
1463 pSMB->Reserved = 0xFFFFFFFF;
1464 pSMB->WriteMode = 0;
1465 pSMB->Remaining = 0;
1467 /* Can increase buffer size if buffer is big enough in some cases ie we
1468 can send more if LARGE_WRITE_X capability returned by the server and if
1469 our buffer is big enough or if we convert to iovecs on socket writes
1470 and eliminate the copy to the CIFS buffer */
1471 if (tcon->ses->capabilities & CAP_LARGE_WRITE_X) {
1472 bytes_sent = min_t(const unsigned int, CIFSMaxBufSize, count);
1474 bytes_sent = (tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE)
1478 if (bytes_sent > count)
1481 cpu_to_le16(offsetof(struct smb_com_write_req, Data) - 4);
1483 memcpy(pSMB->Data, buf, bytes_sent);
1485 if (copy_from_user(pSMB->Data, ubuf, bytes_sent)) {
1486 cifs_buf_release(pSMB);
1489 } else if (count != 0) {
1491 cifs_buf_release(pSMB);
1493 } /* else setting file size with write of zero bytes */
1495 byte_count = bytes_sent + 1; /* pad */
1496 else /* wct == 12 */
1497 byte_count = bytes_sent + 5; /* bigger pad, smaller smb hdr */
1499 pSMB->DataLengthLow = cpu_to_le16(bytes_sent & 0xFFFF);
1500 pSMB->DataLengthHigh = cpu_to_le16(bytes_sent >> 16);
1501 pSMB->hdr.smb_buf_length += byte_count;
1504 pSMB->ByteCount = cpu_to_le16(byte_count);
1505 else { /* old style write has byte count 4 bytes earlier
1507 struct smb_com_writex_req *pSMBW =
1508 (struct smb_com_writex_req *)pSMB;
1509 pSMBW->ByteCount = cpu_to_le16(byte_count);
1512 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1513 (struct smb_hdr *) pSMBr, &bytes_returned, long_op);
1514 cifs_stats_inc(&tcon->num_writes);
1516 cFYI(1, ("Send error in write = %d", rc));
1518 *nbytes = le16_to_cpu(pSMBr->CountHigh);
1519 *nbytes = (*nbytes) << 16;
1520 *nbytes += le16_to_cpu(pSMBr->Count);
1523 * Mask off high 16 bits when bytes written as returned by the
1524 * server is greater than bytes requested by the client. Some
1525 * OS/2 servers are known to set incorrect CountHigh values.
1527 if (*nbytes > count)
1531 cifs_buf_release(pSMB);
1533 /* Note: On -EAGAIN error only caller can retry on handle based calls
1534 since file handle passed in no longer valid */
1540 CIFSSMBWrite2(const int xid, struct cifsTconInfo *tcon,
1541 const int netfid, const unsigned int count,
1542 const __u64 offset, unsigned int *nbytes, struct kvec *iov,
1543 int n_vec, const int long_op)
1546 WRITE_REQ *pSMB = NULL;
1549 int resp_buf_type = 0;
1553 cFYI(1, "write2 at %lld %d bytes", (long long)offset, count);
1555 if (tcon->ses->capabilities & CAP_LARGE_FILES) {
1559 if ((offset >> 32) > 0) {
1560 /* can not handle big offset for old srv */
1564 rc = small_smb_init(SMB_COM_WRITE_ANDX, wct, tcon, (void **) &pSMB);
1567 /* tcon and ses pointer are checked in smb_init */
1568 if (tcon->ses->server == NULL)
1569 return -ECONNABORTED;
1571 pSMB->AndXCommand = 0xFF; /* none */
1573 pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF);
1575 pSMB->OffsetHigh = cpu_to_le32(offset >> 32);
1576 pSMB->Reserved = 0xFFFFFFFF;
1577 pSMB->WriteMode = 0;
1578 pSMB->Remaining = 0;
1581 cpu_to_le16(offsetof(struct smb_com_write_req, Data) - 4);
1583 pSMB->DataLengthLow = cpu_to_le16(count & 0xFFFF);
1584 pSMB->DataLengthHigh = cpu_to_le16(count >> 16);
1585 smb_hdr_len = pSMB->hdr.smb_buf_length + 1; /* hdr + 1 byte pad */
1587 pSMB->hdr.smb_buf_length += count+1;
1588 else /* wct == 12 */
1589 pSMB->hdr.smb_buf_length += count+5; /* smb data starts later */
1591 pSMB->ByteCount = cpu_to_le16(count + 1);
1592 else /* wct == 12 */ /* bigger pad, smaller smb hdr, keep offset ok */ {
1593 struct smb_com_writex_req *pSMBW =
1594 (struct smb_com_writex_req *)pSMB;
1595 pSMBW->ByteCount = cpu_to_le16(count + 5);
1597 iov[0].iov_base = pSMB;
1599 iov[0].iov_len = smb_hdr_len + 4;
1600 else /* wct == 12 pad bigger by four bytes */
1601 iov[0].iov_len = smb_hdr_len + 8;
1604 rc = SendReceive2(xid, tcon->ses, iov, n_vec + 1, &resp_buf_type,
1606 cifs_stats_inc(&tcon->num_writes);
1608 cFYI(1, "Send error Write2 = %d", rc);
1609 } else if (resp_buf_type == 0) {
1610 /* presumably this can not happen, but best to be safe */
1613 WRITE_RSP *pSMBr = (WRITE_RSP *)iov[0].iov_base;
1614 *nbytes = le16_to_cpu(pSMBr->CountHigh);
1615 *nbytes = (*nbytes) << 16;
1616 *nbytes += le16_to_cpu(pSMBr->Count);
1619 * Mask off high 16 bits when bytes written as returned by the
1620 * server is greater than bytes requested by the client. OS/2
1621 * servers are known to set incorrect CountHigh values.
1623 if (*nbytes > count)
1627 /* cifs_small_buf_release(pSMB); */ /* Freed earlier now in SendReceive2 */
1628 if (resp_buf_type == CIFS_SMALL_BUFFER)
1629 cifs_small_buf_release(iov[0].iov_base);
1630 else if (resp_buf_type == CIFS_LARGE_BUFFER)
1631 cifs_buf_release(iov[0].iov_base);
1633 /* Note: On -EAGAIN error only caller can retry on handle based calls
1634 since file handle passed in no longer valid */
1641 CIFSSMBLock(const int xid, struct cifsTconInfo *tcon,
1642 const __u16 smb_file_id, const __u64 len,
1643 const __u64 offset, const __u32 numUnlock,
1644 const __u32 numLock, const __u8 lockType, const bool waitFlag)
1647 LOCK_REQ *pSMB = NULL;
1648 /* LOCK_RSP *pSMBr = NULL; */ /* No response data other than rc to parse */
1653 cFYI(1, "CIFSSMBLock timeout %d numLock %d", (int)waitFlag, numLock);
1654 rc = small_smb_init(SMB_COM_LOCKING_ANDX, 8, tcon, (void **) &pSMB);
1659 if (lockType == LOCKING_ANDX_OPLOCK_RELEASE) {
1660 timeout = CIFS_ASYNC_OP; /* no response expected */
1662 } else if (waitFlag) {
1663 timeout = CIFS_BLOCKING_OP; /* blocking operation, no timeout */
1664 pSMB->Timeout = cpu_to_le32(-1);/* blocking - do not time out */
1669 pSMB->NumberOfLocks = cpu_to_le16(numLock);
1670 pSMB->NumberOfUnlocks = cpu_to_le16(numUnlock);
1671 pSMB->LockType = lockType;
1672 pSMB->AndXCommand = 0xFF; /* none */
1673 pSMB->Fid = smb_file_id; /* netfid stays le */
1675 if ((numLock != 0) || (numUnlock != 0)) {
1676 pSMB->Locks[0].Pid = cpu_to_le16(current->tgid);
1677 /* BB where to store pid high? */
1678 pSMB->Locks[0].LengthLow = cpu_to_le32((u32)len);
1679 pSMB->Locks[0].LengthHigh = cpu_to_le32((u32)(len>>32));
1680 pSMB->Locks[0].OffsetLow = cpu_to_le32((u32)offset);
1681 pSMB->Locks[0].OffsetHigh = cpu_to_le32((u32)(offset>>32));
1682 count = sizeof(LOCKING_ANDX_RANGE);
1687 pSMB->hdr.smb_buf_length += count;
1688 pSMB->ByteCount = cpu_to_le16(count);
1691 rc = SendReceiveBlockingLock(xid, tcon, (struct smb_hdr *) pSMB,
1692 (struct smb_hdr *) pSMB, &bytes_returned);
1693 cifs_small_buf_release(pSMB);
1695 rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *)pSMB,
1697 /* SMB buffer freed by function above */
1699 cifs_stats_inc(&tcon->num_locks);
1701 cFYI(1, "Send error in Lock = %d", rc);
1703 /* Note: On -EAGAIN error only caller can retry on handle based calls
1704 since file handle passed in no longer valid */
1709 CIFSSMBPosixLock(const int xid, struct cifsTconInfo *tcon,
1710 const __u16 smb_file_id, const int get_flag, const __u64 len,
1711 struct file_lock *pLockData, const __u16 lock_type,
1712 const bool waitFlag)
1714 struct smb_com_transaction2_sfi_req *pSMB = NULL;
1715 struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
1716 struct cifs_posix_lock *parm_data;
1719 int bytes_returned = 0;
1720 int resp_buf_type = 0;
1721 __u16 params, param_offset, offset, byte_count, count;
1724 cFYI(1, "Posix Lock");
1726 if (pLockData == NULL)
1729 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
1734 pSMBr = (struct smb_com_transaction2_sfi_rsp *)pSMB;
1737 pSMB->MaxSetupCount = 0;
1740 pSMB->Reserved2 = 0;
1741 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
1742 offset = param_offset + params;
1744 count = sizeof(struct cifs_posix_lock);
1745 pSMB->MaxParameterCount = cpu_to_le16(2);
1746 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB from sess */
1747 pSMB->SetupCount = 1;
1748 pSMB->Reserved3 = 0;
1750 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION);
1752 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
1753 byte_count = 3 /* pad */ + params + count;
1754 pSMB->DataCount = cpu_to_le16(count);
1755 pSMB->ParameterCount = cpu_to_le16(params);
1756 pSMB->TotalDataCount = pSMB->DataCount;
1757 pSMB->TotalParameterCount = pSMB->ParameterCount;
1758 pSMB->ParameterOffset = cpu_to_le16(param_offset);
1759 parm_data = (struct cifs_posix_lock *)
1760 (((char *) &pSMB->hdr.Protocol) + offset);
1762 parm_data->lock_type = cpu_to_le16(lock_type);
1764 timeout = CIFS_BLOCKING_OP; /* blocking operation, no timeout */
1765 parm_data->lock_flags = cpu_to_le16(1);
1766 pSMB->Timeout = cpu_to_le32(-1);
1770 parm_data->pid = cpu_to_le32(current->tgid);
1771 parm_data->start = cpu_to_le64(pLockData->fl_start);
1772 parm_data->length = cpu_to_le64(len); /* normalize negative numbers */
1774 pSMB->DataOffset = cpu_to_le16(offset);
1775 pSMB->Fid = smb_file_id;
1776 pSMB->InformationLevel = cpu_to_le16(SMB_SET_POSIX_LOCK);
1777 pSMB->Reserved4 = 0;
1778 pSMB->hdr.smb_buf_length += byte_count;
1779 pSMB->ByteCount = cpu_to_le16(byte_count);
1781 rc = SendReceiveBlockingLock(xid, tcon, (struct smb_hdr *) pSMB,
1782 (struct smb_hdr *) pSMBr, &bytes_returned);
1784 iov[0].iov_base = (char *)pSMB;
1785 iov[0].iov_len = pSMB->hdr.smb_buf_length + 4;
1786 rc = SendReceive2(xid, tcon->ses, iov, 1 /* num iovecs */,
1787 &resp_buf_type, timeout);
1788 pSMB = NULL; /* request buf already freed by SendReceive2. Do
1789 not try to free it twice below on exit */
1790 pSMBr = (struct smb_com_transaction2_sfi_rsp *)iov[0].iov_base;
1794 cFYI(1, "Send error in Posix Lock = %d", rc);
1795 } else if (get_flag) {
1796 /* lock structure can be returned on get */
1799 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
1801 if (rc || (pSMBr->ByteCount < sizeof(struct cifs_posix_lock))) {
1802 rc = -EIO; /* bad smb */
1805 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
1806 data_count = le16_to_cpu(pSMBr->t2.DataCount);
1807 if (data_count < sizeof(struct cifs_posix_lock)) {
1811 parm_data = (struct cifs_posix_lock *)
1812 ((char *)&pSMBr->hdr.Protocol + data_offset);
1813 if (parm_data->lock_type == __constant_cpu_to_le16(CIFS_UNLCK))
1814 pLockData->fl_type = F_UNLCK;
1816 if (parm_data->lock_type ==
1817 __constant_cpu_to_le16(CIFS_RDLCK))
1818 pLockData->fl_type = F_RDLCK;
1819 else if (parm_data->lock_type ==
1820 __constant_cpu_to_le16(CIFS_WRLCK))
1821 pLockData->fl_type = F_WRLCK;
1823 pLockData->fl_start = parm_data->start;
1824 pLockData->fl_end = parm_data->start +
1825 parm_data->length - 1;
1826 pLockData->fl_pid = parm_data->pid;
1832 cifs_small_buf_release(pSMB);
1834 if (resp_buf_type == CIFS_SMALL_BUFFER)
1835 cifs_small_buf_release(iov[0].iov_base);
1836 else if (resp_buf_type == CIFS_LARGE_BUFFER)
1837 cifs_buf_release(iov[0].iov_base);
1839 /* Note: On -EAGAIN error only caller can retry on handle based calls
1840 since file handle passed in no longer valid */
1847 CIFSSMBClose(const int xid, struct cifsTconInfo *tcon, int smb_file_id)
1850 CLOSE_REQ *pSMB = NULL;
1851 cFYI(1, "In CIFSSMBClose");
1853 /* do not retry on dead session on close */
1854 rc = small_smb_init(SMB_COM_CLOSE, 3, tcon, (void **) &pSMB);
1860 pSMB->FileID = (__u16) smb_file_id;
1861 pSMB->LastWriteTime = 0xFFFFFFFF;
1862 pSMB->ByteCount = 0;
1863 rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0);
1864 cifs_stats_inc(&tcon->num_closes);
1867 /* EINTR is expected when user ctl-c to kill app */
1868 cERROR(1, "Send error in Close = %d", rc);
1872 /* Since session is dead, file will be closed on server already */
1880 CIFSSMBFlush(const int xid, struct cifsTconInfo *tcon, int smb_file_id)
1883 FLUSH_REQ *pSMB = NULL;
1884 cFYI(1, "In CIFSSMBFlush");
1886 rc = small_smb_init(SMB_COM_FLUSH, 1, tcon, (void **) &pSMB);
1890 pSMB->FileID = (__u16) smb_file_id;
1891 pSMB->ByteCount = 0;
1892 rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0);
1893 cifs_stats_inc(&tcon->num_flushes);
1895 cERROR(1, "Send error in Flush = %d", rc);
1901 CIFSSMBRename(const int xid, struct cifsTconInfo *tcon,
1902 const char *fromName, const char *toName,
1903 const struct nls_table *nls_codepage, int remap)
1906 RENAME_REQ *pSMB = NULL;
1907 RENAME_RSP *pSMBr = NULL;
1909 int name_len, name_len2;
1912 cFYI(1, "In CIFSSMBRename");
1914 rc = smb_init(SMB_COM_RENAME, 1, tcon, (void **) &pSMB,
1919 pSMB->BufferFormat = 0x04;
1920 pSMB->SearchAttributes =
1921 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
1924 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1926 cifsConvertToUCS((__le16 *) pSMB->OldFileName, fromName,
1927 PATH_MAX, nls_codepage, remap);
1928 name_len++; /* trailing null */
1930 pSMB->OldFileName[name_len] = 0x04; /* pad */
1931 /* protocol requires ASCII signature byte on Unicode string */
1932 pSMB->OldFileName[name_len + 1] = 0x00;
1934 cifsConvertToUCS((__le16 *)&pSMB->OldFileName[name_len + 2],
1935 toName, PATH_MAX, nls_codepage, remap);
1936 name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
1937 name_len2 *= 2; /* convert to bytes */
1938 } else { /* BB improve the check for buffer overruns BB */
1939 name_len = strnlen(fromName, PATH_MAX);
1940 name_len++; /* trailing null */
1941 strncpy(pSMB->OldFileName, fromName, name_len);
1942 name_len2 = strnlen(toName, PATH_MAX);
1943 name_len2++; /* trailing null */
1944 pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */
1945 strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2);
1946 name_len2++; /* trailing null */
1947 name_len2++; /* signature byte */
1950 count = 1 /* 1st signature byte */ + name_len + name_len2;
1951 pSMB->hdr.smb_buf_length += count;
1952 pSMB->ByteCount = cpu_to_le16(count);
1954 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1955 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1956 cifs_stats_inc(&tcon->num_renames);
1958 cFYI(1, "Send error in rename = %d", rc);
1960 cifs_buf_release(pSMB);
1968 int CIFSSMBRenameOpenFile(const int xid, struct cifsTconInfo *pTcon,
1969 int netfid, const char *target_name,
1970 const struct nls_table *nls_codepage, int remap)
1972 struct smb_com_transaction2_sfi_req *pSMB = NULL;
1973 struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
1974 struct set_file_rename *rename_info;
1976 char dummy_string[30];
1978 int bytes_returned = 0;
1980 __u16 params, param_offset, offset, count, byte_count;
1982 cFYI(1, "Rename to File by handle");
1983 rc = smb_init(SMB_COM_TRANSACTION2, 15, pTcon, (void **) &pSMB,
1989 pSMB->MaxSetupCount = 0;
1993 pSMB->Reserved2 = 0;
1994 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
1995 offset = param_offset + params;
1997 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
1998 rename_info = (struct set_file_rename *) data_offset;
1999 pSMB->MaxParameterCount = cpu_to_le16(2);
2000 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB from sess */
2001 pSMB->SetupCount = 1;
2002 pSMB->Reserved3 = 0;
2003 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
2004 byte_count = 3 /* pad */ + params;
2005 pSMB->ParameterCount = cpu_to_le16(params);
2006 pSMB->TotalParameterCount = pSMB->ParameterCount;
2007 pSMB->ParameterOffset = cpu_to_le16(param_offset);
2008 pSMB->DataOffset = cpu_to_le16(offset);
2009 /* construct random name ".cifs_tmp<inodenum><mid>" */
2010 rename_info->overwrite = cpu_to_le32(1);
2011 rename_info->root_fid = 0;
2012 /* unicode only call */
2013 if (target_name == NULL) {
2014 sprintf(dummy_string, "cifs%x", pSMB->hdr.Mid);
2015 len_of_str = cifsConvertToUCS((__le16 *)rename_info->target_name,
2016 dummy_string, 24, nls_codepage, remap);
2018 len_of_str = cifsConvertToUCS((__le16 *)rename_info->target_name,
2019 target_name, PATH_MAX, nls_codepage,
2022 rename_info->target_name_len = cpu_to_le32(2 * len_of_str);
2023 count = 12 /* sizeof(struct set_file_rename) */ + (2 * len_of_str);
2024 byte_count += count;
2025 pSMB->DataCount = cpu_to_le16(count);
2026 pSMB->TotalDataCount = pSMB->DataCount;
2028 pSMB->InformationLevel =
2029 cpu_to_le16(SMB_SET_FILE_RENAME_INFORMATION);
2030 pSMB->Reserved4 = 0;
2031 pSMB->hdr.smb_buf_length += byte_count;
2032 pSMB->ByteCount = cpu_to_le16(byte_count);
2033 rc = SendReceive(xid, pTcon->ses, (struct smb_hdr *) pSMB,
2034 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2035 cifs_stats_inc(&pTcon->num_t2renames);
2037 cFYI(1, "Send error in Rename (by file handle) = %d", rc);
2039 cifs_buf_release(pSMB);
2041 /* Note: On -EAGAIN error only caller can retry on handle based calls
2042 since file handle passed in no longer valid */
2048 CIFSSMBCopy(const int xid, struct cifsTconInfo *tcon, const char *fromName,
2049 const __u16 target_tid, const char *toName, const int flags,
2050 const struct nls_table *nls_codepage, int remap)
2053 COPY_REQ *pSMB = NULL;
2054 COPY_RSP *pSMBr = NULL;
2056 int name_len, name_len2;
2059 cFYI(1, "In CIFSSMBCopy");
2061 rc = smb_init(SMB_COM_COPY, 1, tcon, (void **) &pSMB,
2066 pSMB->BufferFormat = 0x04;
2067 pSMB->Tid2 = target_tid;
2069 pSMB->Flags = cpu_to_le16(flags & COPY_TREE);
2071 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2072 name_len = cifsConvertToUCS((__le16 *) pSMB->OldFileName,
2073 fromName, PATH_MAX, nls_codepage,
2075 name_len++; /* trailing null */
2077 pSMB->OldFileName[name_len] = 0x04; /* pad */
2078 /* protocol requires ASCII signature byte on Unicode string */
2079 pSMB->OldFileName[name_len + 1] = 0x00;
2081 cifsConvertToUCS((__le16 *)&pSMB->OldFileName[name_len + 2],
2082 toName, PATH_MAX, nls_codepage, remap);
2083 name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
2084 name_len2 *= 2; /* convert to bytes */
2085 } else { /* BB improve the check for buffer overruns BB */
2086 name_len = strnlen(fromName, PATH_MAX);
2087 name_len++; /* trailing null */
2088 strncpy(pSMB->OldFileName, fromName, name_len);
2089 name_len2 = strnlen(toName, PATH_MAX);
2090 name_len2++; /* trailing null */
2091 pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */
2092 strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2);
2093 name_len2++; /* trailing null */
2094 name_len2++; /* signature byte */
2097 count = 1 /* 1st signature byte */ + name_len + name_len2;
2098 pSMB->hdr.smb_buf_length += count;
2099 pSMB->ByteCount = cpu_to_le16(count);
2101 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2102 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2104 cFYI(1, "Send error in copy = %d with %d files copied",
2105 rc, le16_to_cpu(pSMBr->CopyCount));
2107 cifs_buf_release(pSMB);
2116 CIFSUnixCreateSymLink(const int xid, struct cifsTconInfo *tcon,
2117 const char *fromName, const char *toName,
2118 const struct nls_table *nls_codepage)
2120 TRANSACTION2_SPI_REQ *pSMB = NULL;
2121 TRANSACTION2_SPI_RSP *pSMBr = NULL;
2124 int name_len_target;
2126 int bytes_returned = 0;
2127 __u16 params, param_offset, offset, byte_count;
2129 cFYI(1, "In Symlink Unix style");
2131 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2136 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2138 cifs_strtoUCS((__le16 *) pSMB->FileName, fromName, PATH_MAX
2139 /* find define for this maxpathcomponent */
2141 name_len++; /* trailing null */
2144 } else { /* BB improve the check for buffer overruns BB */
2145 name_len = strnlen(fromName, PATH_MAX);
2146 name_len++; /* trailing null */
2147 strncpy(pSMB->FileName, fromName, name_len);
2149 params = 6 + name_len;
2150 pSMB->MaxSetupCount = 0;
2154 pSMB->Reserved2 = 0;
2155 param_offset = offsetof(struct smb_com_transaction2_spi_req,
2156 InformationLevel) - 4;
2157 offset = param_offset + params;
2159 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
2160 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2162 cifs_strtoUCS((__le16 *) data_offset, toName, PATH_MAX
2163 /* find define for this maxpathcomponent */
2165 name_len_target++; /* trailing null */
2166 name_len_target *= 2;
2167 } else { /* BB improve the check for buffer overruns BB */
2168 name_len_target = strnlen(toName, PATH_MAX);
2169 name_len_target++; /* trailing null */
2170 strncpy(data_offset, toName, name_len_target);
2173 pSMB->MaxParameterCount = cpu_to_le16(2);
2174 /* BB find exact max on data count below from sess */
2175 pSMB->MaxDataCount = cpu_to_le16(1000);
2176 pSMB->SetupCount = 1;
2177 pSMB->Reserved3 = 0;
2178 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
2179 byte_count = 3 /* pad */ + params + name_len_target;
2180 pSMB->DataCount = cpu_to_le16(name_len_target);
2181 pSMB->ParameterCount = cpu_to_le16(params);
2182 pSMB->TotalDataCount = pSMB->DataCount;
2183 pSMB->TotalParameterCount = pSMB->ParameterCount;
2184 pSMB->ParameterOffset = cpu_to_le16(param_offset);
2185 pSMB->DataOffset = cpu_to_le16(offset);
2186 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_LINK);
2187 pSMB->Reserved4 = 0;
2188 pSMB->hdr.smb_buf_length += byte_count;
2189 pSMB->ByteCount = cpu_to_le16(byte_count);
2190 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2191 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2192 cifs_stats_inc(&tcon->num_symlinks);
2194 cFYI(1, "Send error in SetPathInfo create symlink = %d", rc);
2196 cifs_buf_release(pSMB);
2199 goto createSymLinkRetry;
2205 CIFSUnixCreateHardLink(const int xid, struct cifsTconInfo *tcon,
2206 const char *fromName, const char *toName,
2207 const struct nls_table *nls_codepage, int remap)
2209 TRANSACTION2_SPI_REQ *pSMB = NULL;
2210 TRANSACTION2_SPI_RSP *pSMBr = NULL;
2213 int name_len_target;
2215 int bytes_returned = 0;
2216 __u16 params, param_offset, offset, byte_count;
2218 cFYI(1, "In Create Hard link Unix style");
2219 createHardLinkRetry:
2220 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2225 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2226 name_len = cifsConvertToUCS((__le16 *) pSMB->FileName, toName,
2227 PATH_MAX, nls_codepage, remap);
2228 name_len++; /* trailing null */
2231 } else { /* BB improve the check for buffer overruns BB */
2232 name_len = strnlen(toName, PATH_MAX);
2233 name_len++; /* trailing null */
2234 strncpy(pSMB->FileName, toName, name_len);
2236 params = 6 + name_len;
2237 pSMB->MaxSetupCount = 0;
2241 pSMB->Reserved2 = 0;
2242 param_offset = offsetof(struct smb_com_transaction2_spi_req,
2243 InformationLevel) - 4;
2244 offset = param_offset + params;
2246 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
2247 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2249 cifsConvertToUCS((__le16 *) data_offset, fromName, PATH_MAX,
2250 nls_codepage, remap);
2251 name_len_target++; /* trailing null */
2252 name_len_target *= 2;
2253 } else { /* BB improve the check for buffer overruns BB */
2254 name_len_target = strnlen(fromName, PATH_MAX);
2255 name_len_target++; /* trailing null */
2256 strncpy(data_offset, fromName, name_len_target);
2259 pSMB->MaxParameterCount = cpu_to_le16(2);
2260 /* BB find exact max on data count below from sess*/
2261 pSMB->MaxDataCount = cpu_to_le16(1000);
2262 pSMB->SetupCount = 1;
2263 pSMB->Reserved3 = 0;
2264 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
2265 byte_count = 3 /* pad */ + params + name_len_target;
2266 pSMB->ParameterCount = cpu_to_le16(params);
2267 pSMB->TotalParameterCount = pSMB->ParameterCount;
2268 pSMB->DataCount = cpu_to_le16(name_len_target);
2269 pSMB->TotalDataCount = pSMB->DataCount;
2270 pSMB->ParameterOffset = cpu_to_le16(param_offset);
2271 pSMB->DataOffset = cpu_to_le16(offset);
2272 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_HLINK);
2273 pSMB->Reserved4 = 0;
2274 pSMB->hdr.smb_buf_length += byte_count;
2275 pSMB->ByteCount = cpu_to_le16(byte_count);
2276 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2277 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2278 cifs_stats_inc(&tcon->num_hardlinks);
2280 cFYI(1, "Send error in SetPathInfo (hard link) = %d", rc);
2282 cifs_buf_release(pSMB);
2284 goto createHardLinkRetry;
2290 CIFSCreateHardLink(const int xid, struct cifsTconInfo *tcon,
2291 const char *fromName, const char *toName,
2292 const struct nls_table *nls_codepage, int remap)
2295 NT_RENAME_REQ *pSMB = NULL;
2296 RENAME_RSP *pSMBr = NULL;
2298 int name_len, name_len2;
2301 cFYI(1, "In CIFSCreateHardLink");
2302 winCreateHardLinkRetry:
2304 rc = smb_init(SMB_COM_NT_RENAME, 4, tcon, (void **) &pSMB,
2309 pSMB->SearchAttributes =
2310 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
2312 pSMB->Flags = cpu_to_le16(CREATE_HARD_LINK);
2313 pSMB->ClusterCount = 0;
2315 pSMB->BufferFormat = 0x04;
2317 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2319 cifsConvertToUCS((__le16 *) pSMB->OldFileName, fromName,
2320 PATH_MAX, nls_codepage, remap);
2321 name_len++; /* trailing null */
2324 /* protocol specifies ASCII buffer format (0x04) for unicode */
2325 pSMB->OldFileName[name_len] = 0x04;
2326 pSMB->OldFileName[name_len + 1] = 0x00; /* pad */
2328 cifsConvertToUCS((__le16 *)&pSMB->OldFileName[name_len + 2],
2329 toName, PATH_MAX, nls_codepage, remap);
2330 name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
2331 name_len2 *= 2; /* convert to bytes */
2332 } else { /* BB improve the check for buffer overruns BB */
2333 name_len = strnlen(fromName, PATH_MAX);
2334 name_len++; /* trailing null */
2335 strncpy(pSMB->OldFileName, fromName, name_len);
2336 name_len2 = strnlen(toName, PATH_MAX);
2337 name_len2++; /* trailing null */
2338 pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */
2339 strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2);
2340 name_len2++; /* trailing null */
2341 name_len2++; /* signature byte */
2344 count = 1 /* string type byte */ + name_len + name_len2;
2345 pSMB->hdr.smb_buf_length += count;
2346 pSMB->ByteCount = cpu_to_le16(count);
2348 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2349 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2350 cifs_stats_inc(&tcon->num_hardlinks);
2352 cFYI(1, "Send error in hard link (NT rename) = %d", rc);
2354 cifs_buf_release(pSMB);
2356 goto winCreateHardLinkRetry;
2362 CIFSSMBUnixQuerySymLink(const int xid, struct cifsTconInfo *tcon,
2363 const unsigned char *searchName, char **symlinkinfo,
2364 const struct nls_table *nls_codepage)
2366 /* SMB_QUERY_FILE_UNIX_LINK */
2367 TRANSACTION2_QPI_REQ *pSMB = NULL;
2368 TRANSACTION2_QPI_RSP *pSMBr = NULL;
2372 __u16 params, byte_count;
2375 cFYI(1, "In QPathSymLinkInfo (Unix) for path %s", searchName);
2378 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2383 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2385 cifs_strtoUCS((__le16 *) pSMB->FileName, searchName,
2386 PATH_MAX, nls_codepage);
2387 name_len++; /* trailing null */
2389 } else { /* BB improve the check for buffer overruns BB */
2390 name_len = strnlen(searchName, PATH_MAX);
2391 name_len++; /* trailing null */
2392 strncpy(pSMB->FileName, searchName, name_len);
2395 params = 2 /* level */ + 4 /* rsrvd */ + name_len /* incl null */ ;
2396 pSMB->TotalDataCount = 0;
2397 pSMB->MaxParameterCount = cpu_to_le16(2);
2398 pSMB->MaxDataCount = cpu_to_le16(CIFSMaxBufSize);
2399 pSMB->MaxSetupCount = 0;
2403 pSMB->Reserved2 = 0;
2404 pSMB->ParameterOffset = cpu_to_le16(offsetof(
2405 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
2406 pSMB->DataCount = 0;
2407 pSMB->DataOffset = 0;
2408 pSMB->SetupCount = 1;
2409 pSMB->Reserved3 = 0;
2410 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
2411 byte_count = params + 1 /* pad */ ;
2412 pSMB->TotalParameterCount = cpu_to_le16(params);
2413 pSMB->ParameterCount = pSMB->TotalParameterCount;
2414 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_LINK);
2415 pSMB->Reserved4 = 0;
2416 pSMB->hdr.smb_buf_length += byte_count;
2417 pSMB->ByteCount = cpu_to_le16(byte_count);
2419 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2420 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2422 cFYI(1, "Send error in QuerySymLinkInfo = %d", rc);
2424 /* decode response */
2426 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
2427 /* BB also check enough total bytes returned */
2428 if (rc || (pSMBr->ByteCount < 2))
2432 u16 count = le16_to_cpu(pSMBr->t2.DataCount);
2434 data_start = ((char *) &pSMBr->hdr.Protocol) +
2435 le16_to_cpu(pSMBr->t2.DataOffset);
2437 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
2442 /* BB FIXME investigate remapping reserved chars here */
2443 *symlinkinfo = cifs_strndup_from_ucs(data_start, count,
2444 is_unicode, nls_codepage);
2449 cifs_buf_release(pSMB);
2451 goto querySymLinkRetry;
2455 #ifdef CONFIG_CIFS_EXPERIMENTAL
2456 /* Initialize NT TRANSACT SMB into small smb request buffer.
2457 This assumes that all NT TRANSACTS that we init here have
2458 total parm and data under about 400 bytes (to fit in small cifs
2459 buffer size), which is the case so far, it easily fits. NB:
2460 Setup words themselves and ByteCount
2461 MaxSetupCount (size of returned setup area) and
2462 MaxParameterCount (returned parms size) must be set by caller */
2464 smb_init_nttransact(const __u16 sub_command, const int setup_count,
2465 const int parm_len, struct cifsTconInfo *tcon,
2470 struct smb_com_ntransact_req *pSMB;
2472 rc = small_smb_init(SMB_COM_NT_TRANSACT, 19 + setup_count, tcon,
2476 *ret_buf = (void *)pSMB;
2478 pSMB->TotalParameterCount = cpu_to_le32(parm_len);
2479 pSMB->TotalDataCount = 0;
2480 pSMB->MaxDataCount = cpu_to_le32((tcon->ses->server->maxBuf -
2481 MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
2482 pSMB->ParameterCount = pSMB->TotalParameterCount;
2483 pSMB->DataCount = pSMB->TotalDataCount;
2484 temp_offset = offsetof(struct smb_com_ntransact_req, Parms) +
2485 (setup_count * 2) - 4 /* for rfc1001 length itself */;
2486 pSMB->ParameterOffset = cpu_to_le32(temp_offset);
2487 pSMB->DataOffset = cpu_to_le32(temp_offset + parm_len);
2488 pSMB->SetupCount = setup_count; /* no need to le convert byte fields */
2489 pSMB->SubCommand = cpu_to_le16(sub_command);
2494 validate_ntransact(char *buf, char **ppparm, char **ppdata,
2495 __u32 *pparmlen, __u32 *pdatalen)
2498 __u32 data_count, data_offset, parm_count, parm_offset;
2499 struct smb_com_ntransact_rsp *pSMBr;
2507 pSMBr = (struct smb_com_ntransact_rsp *)buf;
2509 /* ByteCount was converted from little endian in SendReceive */
2510 end_of_smb = 2 /* sizeof byte count */ + pSMBr->ByteCount +
2511 (char *)&pSMBr->ByteCount;
2513 data_offset = le32_to_cpu(pSMBr->DataOffset);
2514 data_count = le32_to_cpu(pSMBr->DataCount);
2515 parm_offset = le32_to_cpu(pSMBr->ParameterOffset);
2516 parm_count = le32_to_cpu(pSMBr->ParameterCount);
2518 *ppparm = (char *)&pSMBr->hdr.Protocol + parm_offset;
2519 *ppdata = (char *)&pSMBr->hdr.Protocol + data_offset;
2521 /* should we also check that parm and data areas do not overlap? */
2522 if (*ppparm > end_of_smb) {
2523 cFYI(1, "parms start after end of smb");
2525 } else if (parm_count + *ppparm > end_of_smb) {
2526 cFYI(1, "parm end after end of smb");
2528 } else if (*ppdata > end_of_smb) {
2529 cFYI(1, "data starts after end of smb");
2531 } else if (data_count + *ppdata > end_of_smb) {
2532 cFYI(1, "data %p + count %d (%p) ends after end of smb %p start %p",
2533 *ppdata, data_count, (data_count + *ppdata),
2536 } else if (parm_count + data_count > pSMBr->ByteCount) {
2537 cFYI(1, "parm count and data count larger than SMB");
2540 *pdatalen = data_count;
2541 *pparmlen = parm_count;
2546 CIFSSMBQueryReparseLinkInfo(const int xid, struct cifsTconInfo *tcon,
2547 const unsigned char *searchName,
2548 char *symlinkinfo, const int buflen, __u16 fid,
2549 const struct nls_table *nls_codepage)
2553 struct smb_com_transaction_ioctl_req *pSMB;
2554 struct smb_com_transaction_ioctl_rsp *pSMBr;
2556 cFYI(1, "In Windows reparse style QueryLink for path %s", searchName);
2557 rc = smb_init(SMB_COM_NT_TRANSACT, 23, tcon, (void **) &pSMB,
2562 pSMB->TotalParameterCount = 0 ;
2563 pSMB->TotalDataCount = 0;
2564 pSMB->MaxParameterCount = cpu_to_le32(2);
2565 /* BB find exact data count max from sess structure BB */
2566 pSMB->MaxDataCount = cpu_to_le32((tcon->ses->server->maxBuf -
2567 MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
2568 pSMB->MaxSetupCount = 4;
2570 pSMB->ParameterOffset = 0;
2571 pSMB->DataCount = 0;
2572 pSMB->DataOffset = 0;
2573 pSMB->SetupCount = 4;
2574 pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_IOCTL);
2575 pSMB->ParameterCount = pSMB->TotalParameterCount;
2576 pSMB->FunctionCode = cpu_to_le32(FSCTL_GET_REPARSE_POINT);
2577 pSMB->IsFsctl = 1; /* FSCTL */
2578 pSMB->IsRootFlag = 0;
2579 pSMB->Fid = fid; /* file handle always le */
2580 pSMB->ByteCount = 0;
2582 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2583 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2585 cFYI(1, "Send error in QueryReparseLinkInfo = %d", rc);
2586 } else { /* decode response */
2587 __u32 data_offset = le32_to_cpu(pSMBr->DataOffset);
2588 __u32 data_count = le32_to_cpu(pSMBr->DataCount);
2589 if ((pSMBr->ByteCount < 2) || (data_offset > 512)) {
2590 /* BB also check enough total bytes returned */
2591 rc = -EIO; /* bad smb */
2594 if (data_count && (data_count < 2048)) {
2595 char *end_of_smb = 2 /* sizeof byte count */ +
2596 pSMBr->ByteCount + (char *)&pSMBr->ByteCount;
2598 struct reparse_data *reparse_buf =
2599 (struct reparse_data *)
2600 ((char *)&pSMBr->hdr.Protocol
2602 if ((char *)reparse_buf >= end_of_smb) {
2606 if ((reparse_buf->LinkNamesBuf +
2607 reparse_buf->TargetNameOffset +
2608 reparse_buf->TargetNameLen) > end_of_smb) {
2609 cFYI(1, "reparse buf beyond SMB");
2614 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
2615 cifs_from_ucs2(symlinkinfo, (__le16 *)
2616 (reparse_buf->LinkNamesBuf +
2617 reparse_buf->TargetNameOffset),
2619 reparse_buf->TargetNameLen,
2621 } else { /* ASCII names */
2622 strncpy(symlinkinfo,
2623 reparse_buf->LinkNamesBuf +
2624 reparse_buf->TargetNameOffset,
2625 min_t(const int, buflen,
2626 reparse_buf->TargetNameLen));
2630 cFYI(1, "Invalid return data count on "
2631 "get reparse info ioctl");
2633 symlinkinfo[buflen] = 0; /* just in case so the caller
2634 does not go off the end of the buffer */
2635 cFYI(1, "readlink result - %s", symlinkinfo);
2639 cifs_buf_release(pSMB);
2641 /* Note: On -EAGAIN error only caller can retry on handle based calls
2642 since file handle passed in no longer valid */
2646 #endif /* CIFS_EXPERIMENTAL */
2648 #ifdef CONFIG_CIFS_POSIX
2650 /*Convert an Access Control Entry from wire format to local POSIX xattr format*/
2651 static void cifs_convert_ace(posix_acl_xattr_entry *ace,
2652 struct cifs_posix_ace *cifs_ace)
2654 /* u8 cifs fields do not need le conversion */
2655 ace->e_perm = cpu_to_le16(cifs_ace->cifs_e_perm);
2656 ace->e_tag = cpu_to_le16(cifs_ace->cifs_e_tag);
2657 ace->e_id = cpu_to_le32(le64_to_cpu(cifs_ace->cifs_uid));
2658 /* cFYI(1, "perm %d tag %d id %d",ace->e_perm,ace->e_tag,ace->e_id); */
2663 /* Convert ACL from CIFS POSIX wire format to local Linux POSIX ACL xattr */
2664 static int cifs_copy_posix_acl(char *trgt, char *src, const int buflen,
2665 const int acl_type, const int size_of_data_area)
2670 struct cifs_posix_ace *pACE;
2671 struct cifs_posix_acl *cifs_acl = (struct cifs_posix_acl *)src;
2672 posix_acl_xattr_header *local_acl = (posix_acl_xattr_header *)trgt;
2674 if (le16_to_cpu(cifs_acl->version) != CIFS_ACL_VERSION)
2677 if (acl_type & ACL_TYPE_ACCESS) {
2678 count = le16_to_cpu(cifs_acl->access_entry_count);
2679 pACE = &cifs_acl->ace_array[0];
2680 size = sizeof(struct cifs_posix_acl);
2681 size += sizeof(struct cifs_posix_ace) * count;
2682 /* check if we would go beyond end of SMB */
2683 if (size_of_data_area < size) {
2684 cFYI(1, "bad CIFS POSIX ACL size %d vs. %d",
2685 size_of_data_area, size);
2688 } else if (acl_type & ACL_TYPE_DEFAULT) {
2689 count = le16_to_cpu(cifs_acl->access_entry_count);
2690 size = sizeof(struct cifs_posix_acl);
2691 size += sizeof(struct cifs_posix_ace) * count;
2692 /* skip past access ACEs to get to default ACEs */
2693 pACE = &cifs_acl->ace_array[count];
2694 count = le16_to_cpu(cifs_acl->default_entry_count);
2695 size += sizeof(struct cifs_posix_ace) * count;
2696 /* check if we would go beyond end of SMB */
2697 if (size_of_data_area < size)
2704 size = posix_acl_xattr_size(count);
2705 if ((buflen == 0) || (local_acl == NULL)) {
2706 /* used to query ACL EA size */
2707 } else if (size > buflen) {
2709 } else /* buffer big enough */ {
2710 local_acl->a_version = cpu_to_le32(POSIX_ACL_XATTR_VERSION);
2711 for (i = 0; i < count ; i++) {
2712 cifs_convert_ace(&local_acl->a_entries[i], pACE);
2719 static __u16 convert_ace_to_cifs_ace(struct cifs_posix_ace *cifs_ace,
2720 const posix_acl_xattr_entry *local_ace)
2722 __u16 rc = 0; /* 0 = ACL converted ok */
2724 cifs_ace->cifs_e_perm = le16_to_cpu(local_ace->e_perm);
2725 cifs_ace->cifs_e_tag = le16_to_cpu(local_ace->e_tag);
2726 /* BB is there a better way to handle the large uid? */
2727 if (local_ace->e_id == cpu_to_le32(-1)) {
2728 /* Probably no need to le convert -1 on any arch but can not hurt */
2729 cifs_ace->cifs_uid = cpu_to_le64(-1);
2731 cifs_ace->cifs_uid = cpu_to_le64(le32_to_cpu(local_ace->e_id));
2732 /*cFYI(1, "perm %d tag %d id %d",ace->e_perm,ace->e_tag,ace->e_id);*/
2736 /* Convert ACL from local Linux POSIX xattr to CIFS POSIX ACL wire format */
2737 static __u16 ACL_to_cifs_posix(char *parm_data, const char *pACL,
2738 const int buflen, const int acl_type)
2741 struct cifs_posix_acl *cifs_acl = (struct cifs_posix_acl *)parm_data;
2742 posix_acl_xattr_header *local_acl = (posix_acl_xattr_header *)pACL;
2746 if ((buflen == 0) || (pACL == NULL) || (cifs_acl == NULL))
2749 count = posix_acl_xattr_count((size_t)buflen);
2750 cFYI(1, "setting acl with %d entries from buf of length %d and "
2752 count, buflen, le32_to_cpu(local_acl->a_version));
2753 if (le32_to_cpu(local_acl->a_version) != 2) {
2754 cFYI(1, "unknown POSIX ACL version %d",
2755 le32_to_cpu(local_acl->a_version));
2758 cifs_acl->version = cpu_to_le16(1);
2759 if (acl_type == ACL_TYPE_ACCESS)
2760 cifs_acl->access_entry_count = cpu_to_le16(count);
2761 else if (acl_type == ACL_TYPE_DEFAULT)
2762 cifs_acl->default_entry_count = cpu_to_le16(count);
2764 cFYI(1, "unknown ACL type %d", acl_type);
2767 for (i = 0; i < count; i++) {
2768 rc = convert_ace_to_cifs_ace(&cifs_acl->ace_array[i],
2769 &local_acl->a_entries[i]);
2771 /* ACE not converted */
2776 rc = (__u16)(count * sizeof(struct cifs_posix_ace));
2777 rc += sizeof(struct cifs_posix_acl);
2778 /* BB add check to make sure ACL does not overflow SMB */
2784 CIFSSMBGetPosixACL(const int xid, struct cifsTconInfo *tcon,
2785 const unsigned char *searchName,
2786 char *acl_inf, const int buflen, const int acl_type,
2787 const struct nls_table *nls_codepage, int remap)
2789 /* SMB_QUERY_POSIX_ACL */
2790 TRANSACTION2_QPI_REQ *pSMB = NULL;
2791 TRANSACTION2_QPI_RSP *pSMBr = NULL;
2795 __u16 params, byte_count;
2797 cFYI(1, "In GetPosixACL (Unix) for path %s", searchName);
2800 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2805 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2807 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
2808 PATH_MAX, nls_codepage, remap);
2809 name_len++; /* trailing null */
2811 pSMB->FileName[name_len] = 0;
2812 pSMB->FileName[name_len+1] = 0;
2813 } else { /* BB improve the check for buffer overruns BB */
2814 name_len = strnlen(searchName, PATH_MAX);
2815 name_len++; /* trailing null */
2816 strncpy(pSMB->FileName, searchName, name_len);
2819 params = 2 /* level */ + 4 /* rsrvd */ + name_len /* incl null */ ;
2820 pSMB->TotalDataCount = 0;
2821 pSMB->MaxParameterCount = cpu_to_le16(2);
2822 /* BB find exact max data count below from sess structure BB */
2823 pSMB->MaxDataCount = cpu_to_le16(4000);
2824 pSMB->MaxSetupCount = 0;
2828 pSMB->Reserved2 = 0;
2829 pSMB->ParameterOffset = cpu_to_le16(
2830 offsetof(struct smb_com_transaction2_qpi_req,
2831 InformationLevel) - 4);
2832 pSMB->DataCount = 0;
2833 pSMB->DataOffset = 0;
2834 pSMB->SetupCount = 1;
2835 pSMB->Reserved3 = 0;
2836 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
2837 byte_count = params + 1 /* pad */ ;
2838 pSMB->TotalParameterCount = cpu_to_le16(params);
2839 pSMB->ParameterCount = pSMB->TotalParameterCount;
2840 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_POSIX_ACL);
2841 pSMB->Reserved4 = 0;
2842 pSMB->hdr.smb_buf_length += byte_count;
2843 pSMB->ByteCount = cpu_to_le16(byte_count);
2845 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2846 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2847 cifs_stats_inc(&tcon->num_acl_get);
2849 cFYI(1, "Send error in Query POSIX ACL = %d", rc);
2851 /* decode response */
2853 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
2854 if (rc || (pSMBr->ByteCount < 2))
2855 /* BB also check enough total bytes returned */
2856 rc = -EIO; /* bad smb */
2858 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
2859 __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
2860 rc = cifs_copy_posix_acl(acl_inf,
2861 (char *)&pSMBr->hdr.Protocol+data_offset,
2862 buflen, acl_type, count);
2865 cifs_buf_release(pSMB);
2872 CIFSSMBSetPosixACL(const int xid, struct cifsTconInfo *tcon,
2873 const unsigned char *fileName,
2874 const char *local_acl, const int buflen,
2876 const struct nls_table *nls_codepage, int remap)
2878 struct smb_com_transaction2_spi_req *pSMB = NULL;
2879 struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
2883 int bytes_returned = 0;
2884 __u16 params, byte_count, data_count, param_offset, offset;
2886 cFYI(1, "In SetPosixACL (Unix) for path %s", fileName);
2888 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2892 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2894 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
2895 PATH_MAX, nls_codepage, remap);
2896 name_len++; /* trailing null */
2898 } else { /* BB improve the check for buffer overruns BB */
2899 name_len = strnlen(fileName, PATH_MAX);
2900 name_len++; /* trailing null */
2901 strncpy(pSMB->FileName, fileName, name_len);
2903 params = 6 + name_len;
2904 pSMB->MaxParameterCount = cpu_to_le16(2);
2905 /* BB find max SMB size from sess */
2906 pSMB->MaxDataCount = cpu_to_le16(1000);
2907 pSMB->MaxSetupCount = 0;
2911 pSMB->Reserved2 = 0;
2912 param_offset = offsetof(struct smb_com_transaction2_spi_req,
2913 InformationLevel) - 4;
2914 offset = param_offset + params;
2915 parm_data = ((char *) &pSMB->hdr.Protocol) + offset;
2916 pSMB->ParameterOffset = cpu_to_le16(param_offset);
2918 /* convert to on the wire format for POSIX ACL */
2919 data_count = ACL_to_cifs_posix(parm_data, local_acl, buflen, acl_type);
2921 if (data_count == 0) {
2923 goto setACLerrorExit;
2925 pSMB->DataOffset = cpu_to_le16(offset);
2926 pSMB->SetupCount = 1;
2927 pSMB->Reserved3 = 0;
2928 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
2929 pSMB->InformationLevel = cpu_to_le16(SMB_SET_POSIX_ACL);
2930 byte_count = 3 /* pad */ + params + data_count;
2931 pSMB->DataCount = cpu_to_le16(data_count);
2932 pSMB->TotalDataCount = pSMB->DataCount;
2933 pSMB->ParameterCount = cpu_to_le16(params);
2934 pSMB->TotalParameterCount = pSMB->ParameterCount;
2935 pSMB->Reserved4 = 0;
2936 pSMB->hdr.smb_buf_length += byte_count;
2937 pSMB->ByteCount = cpu_to_le16(byte_count);
2938 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2939 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2941 cFYI(1, "Set POSIX ACL returned %d", rc);
2944 cifs_buf_release(pSMB);
2950 /* BB fix tabs in this function FIXME BB */
2952 CIFSGetExtAttr(const int xid, struct cifsTconInfo *tcon,
2953 const int netfid, __u64 *pExtAttrBits, __u64 *pMask)
2956 struct smb_t2_qfi_req *pSMB = NULL;
2957 struct smb_t2_qfi_rsp *pSMBr = NULL;
2959 __u16 params, byte_count;
2961 cFYI(1, "In GetExtAttr");
2966 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2971 params = 2 /* level */ + 2 /* fid */;
2972 pSMB->t2.TotalDataCount = 0;
2973 pSMB->t2.MaxParameterCount = cpu_to_le16(4);
2974 /* BB find exact max data count below from sess structure BB */
2975 pSMB->t2.MaxDataCount = cpu_to_le16(4000);
2976 pSMB->t2.MaxSetupCount = 0;
2977 pSMB->t2.Reserved = 0;
2979 pSMB->t2.Timeout = 0;
2980 pSMB->t2.Reserved2 = 0;
2981 pSMB->t2.ParameterOffset = cpu_to_le16(offsetof(struct smb_t2_qfi_req,
2983 pSMB->t2.DataCount = 0;
2984 pSMB->t2.DataOffset = 0;
2985 pSMB->t2.SetupCount = 1;
2986 pSMB->t2.Reserved3 = 0;
2987 pSMB->t2.SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION);
2988 byte_count = params + 1 /* pad */ ;
2989 pSMB->t2.TotalParameterCount = cpu_to_le16(params);
2990 pSMB->t2.ParameterCount = pSMB->t2.TotalParameterCount;
2991 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_ATTR_FLAGS);
2994 pSMB->hdr.smb_buf_length += byte_count;
2995 pSMB->t2.ByteCount = cpu_to_le16(byte_count);
2997 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2998 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3000 cFYI(1, "error %d in GetExtAttr", rc);
3002 /* decode response */
3003 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3004 if (rc || (pSMBr->ByteCount < 2))
3005 /* BB also check enough total bytes returned */
3006 /* If rc should we check for EOPNOSUPP and
3007 disable the srvino flag? or in caller? */
3008 rc = -EIO; /* bad smb */
3010 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3011 __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
3012 struct file_chattr_info *pfinfo;
3013 /* BB Do we need a cast or hash here ? */
3015 cFYI(1, "Illegal size ret in GetExtAttr");
3019 pfinfo = (struct file_chattr_info *)
3020 (data_offset + (char *) &pSMBr->hdr.Protocol);
3021 *pExtAttrBits = le64_to_cpu(pfinfo->mode);
3022 *pMask = le64_to_cpu(pfinfo->mask);
3026 cifs_buf_release(pSMB);
3028 goto GetExtAttrRetry;
3032 #endif /* CONFIG_POSIX */
3034 #ifdef CONFIG_CIFS_EXPERIMENTAL
3035 /* Get Security Descriptor (by handle) from remote server for a file or dir */
3037 CIFSSMBGetCIFSACL(const int xid, struct cifsTconInfo *tcon, __u16 fid,
3038 struct cifs_ntsd **acl_inf, __u32 *pbuflen)
3042 QUERY_SEC_DESC_REQ *pSMB;
3045 cFYI(1, "GetCifsACL");
3050 rc = smb_init_nttransact(NT_TRANSACT_QUERY_SECURITY_DESC, 0,
3051 8 /* parm len */, tcon, (void **) &pSMB);
3055 pSMB->MaxParameterCount = cpu_to_le32(4);
3056 /* BB TEST with big acls that might need to be e.g. larger than 16K */
3057 pSMB->MaxSetupCount = 0;
3058 pSMB->Fid = fid; /* file handle always le */
3059 pSMB->AclFlags = cpu_to_le32(CIFS_ACL_OWNER | CIFS_ACL_GROUP |
3061 pSMB->ByteCount = cpu_to_le16(11); /* 3 bytes pad + 8 bytes parm */
3062 pSMB->hdr.smb_buf_length += 11;
3063 iov[0].iov_base = (char *)pSMB;
3064 iov[0].iov_len = pSMB->hdr.smb_buf_length + 4;
3066 rc = SendReceive2(xid, tcon->ses, iov, 1 /* num iovec */, &buf_type,
3068 cifs_stats_inc(&tcon->num_acl_get);
3070 cFYI(1, "Send error in QuerySecDesc = %d", rc);
3071 } else { /* decode response */
3075 struct smb_com_ntransact_rsp *pSMBr;
3078 /* validate_nttransact */
3079 rc = validate_ntransact(iov[0].iov_base, (char **)&parm,
3080 &pdata, &parm_len, pbuflen);
3083 pSMBr = (struct smb_com_ntransact_rsp *)iov[0].iov_base;
3085 cFYI(1, "smb %p parm %p data %p", pSMBr, parm, *acl_inf);
3087 if (le32_to_cpu(pSMBr->ParameterCount) != 4) {
3088 rc = -EIO; /* bad smb */
3093 /* BB check that data area is minimum length and as big as acl_len */
3095 acl_len = le32_to_cpu(*parm);
3096 if (acl_len != *pbuflen) {
3097 cERROR(1, "acl length %d does not match %d",
3099 if (*pbuflen > acl_len)
3103 /* check if buffer is big enough for the acl
3104 header followed by the smallest SID */
3105 if ((*pbuflen < sizeof(struct cifs_ntsd) + 8) ||
3106 (*pbuflen >= 64 * 1024)) {
3107 cERROR(1, "bad acl length %d", *pbuflen);
3111 *acl_inf = kmalloc(*pbuflen, GFP_KERNEL);
3112 if (*acl_inf == NULL) {
3116 memcpy(*acl_inf, pdata, *pbuflen);
3120 if (buf_type == CIFS_SMALL_BUFFER)
3121 cifs_small_buf_release(iov[0].iov_base);
3122 else if (buf_type == CIFS_LARGE_BUFFER)
3123 cifs_buf_release(iov[0].iov_base);
3124 /* cifs_small_buf_release(pSMB); */ /* Freed earlier now in SendReceive2 */
3129 CIFSSMBSetCIFSACL(const int xid, struct cifsTconInfo *tcon, __u16 fid,
3130 struct cifs_ntsd *pntsd, __u32 acllen)
3132 __u16 byte_count, param_count, data_count, param_offset, data_offset;
3134 int bytes_returned = 0;
3135 SET_SEC_DESC_REQ *pSMB = NULL;
3136 NTRANSACT_RSP *pSMBr = NULL;
3139 rc = smb_init(SMB_COM_NT_TRANSACT, 19, tcon, (void **) &pSMB,
3144 pSMB->MaxSetupCount = 0;
3148 param_offset = offsetof(struct smb_com_transaction_ssec_req, Fid) - 4;
3149 data_count = acllen;
3150 data_offset = param_offset + param_count;
3151 byte_count = 3 /* pad */ + param_count;
3153 pSMB->DataCount = cpu_to_le32(data_count);
3154 pSMB->TotalDataCount = pSMB->DataCount;
3155 pSMB->MaxParameterCount = cpu_to_le32(4);
3156 pSMB->MaxDataCount = cpu_to_le32(16384);
3157 pSMB->ParameterCount = cpu_to_le32(param_count);
3158 pSMB->ParameterOffset = cpu_to_le32(param_offset);
3159 pSMB->TotalParameterCount = pSMB->ParameterCount;
3160 pSMB->DataOffset = cpu_to_le32(data_offset);
3161 pSMB->SetupCount = 0;
3162 pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_SET_SECURITY_DESC);
3163 pSMB->ByteCount = cpu_to_le16(byte_count+data_count);
3165 pSMB->Fid = fid; /* file handle always le */
3166 pSMB->Reserved2 = 0;
3167 pSMB->AclFlags = cpu_to_le32(CIFS_ACL_DACL);
3169 if (pntsd && acllen) {
3170 memcpy((char *) &pSMBr->hdr.Protocol + data_offset,
3173 pSMB->hdr.smb_buf_length += (byte_count + data_count);
3176 pSMB->hdr.smb_buf_length += byte_count;
3178 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3179 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3181 cFYI(1, "SetCIFSACL bytes_returned: %d, rc: %d", bytes_returned, rc);
3183 cFYI(1, "Set CIFS ACL returned %d", rc);
3184 cifs_buf_release(pSMB);
3187 goto setCifsAclRetry;
3192 #endif /* CONFIG_CIFS_EXPERIMENTAL */
3194 /* Legacy Query Path Information call for lookup to old servers such
3196 int SMBQueryInformation(const int xid, struct cifsTconInfo *tcon,
3197 const unsigned char *searchName,
3198 FILE_ALL_INFO *pFinfo,
3199 const struct nls_table *nls_codepage, int remap)
3201 QUERY_INFORMATION_REQ *pSMB;
3202 QUERY_INFORMATION_RSP *pSMBr;
3207 cFYI(1, "In SMBQPath path %s", searchName);
3209 rc = smb_init(SMB_COM_QUERY_INFORMATION, 0, tcon, (void **) &pSMB,
3214 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3216 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
3217 PATH_MAX, nls_codepage, remap);
3218 name_len++; /* trailing null */
3221 name_len = strnlen(searchName, PATH_MAX);
3222 name_len++; /* trailing null */
3223 strncpy(pSMB->FileName, searchName, name_len);
3225 pSMB->BufferFormat = 0x04;
3226 name_len++; /* account for buffer type byte */
3227 pSMB->hdr.smb_buf_length += (__u16) name_len;
3228 pSMB->ByteCount = cpu_to_le16(name_len);
3230 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3231 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3233 cFYI(1, "Send error in QueryInfo = %d", rc);
3234 } else if (pFinfo) {
3236 __u32 time = le32_to_cpu(pSMBr->last_write_time);
3238 /* decode response */
3239 /* BB FIXME - add time zone adjustment BB */
3240 memset(pFinfo, 0, sizeof(FILE_ALL_INFO));
3243 /* decode time fields */
3244 pFinfo->ChangeTime = cpu_to_le64(cifs_UnixTimeToNT(ts));
3245 pFinfo->LastWriteTime = pFinfo->ChangeTime;
3246 pFinfo->LastAccessTime = 0;
3247 pFinfo->AllocationSize =
3248 cpu_to_le64(le32_to_cpu(pSMBr->size));
3249 pFinfo->EndOfFile = pFinfo->AllocationSize;
3250 pFinfo->Attributes =
3251 cpu_to_le32(le16_to_cpu(pSMBr->attr));
3253 rc = -EIO; /* bad buffer passed in */
3255 cifs_buf_release(pSMB);
3264 CIFSSMBQFileInfo(const int xid, struct cifsTconInfo *tcon,
3265 u16 netfid, FILE_ALL_INFO *pFindData)
3267 struct smb_t2_qfi_req *pSMB = NULL;
3268 struct smb_t2_qfi_rsp *pSMBr = NULL;
3271 __u16 params, byte_count;
3274 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3279 params = 2 /* level */ + 2 /* fid */;
3280 pSMB->t2.TotalDataCount = 0;
3281 pSMB->t2.MaxParameterCount = cpu_to_le16(4);
3282 /* BB find exact max data count below from sess structure BB */
3283 pSMB->t2.MaxDataCount = cpu_to_le16(CIFSMaxBufSize);
3284 pSMB->t2.MaxSetupCount = 0;
3285 pSMB->t2.Reserved = 0;
3287 pSMB->t2.Timeout = 0;
3288 pSMB->t2.Reserved2 = 0;
3289 pSMB->t2.ParameterOffset = cpu_to_le16(offsetof(struct smb_t2_qfi_req,
3291 pSMB->t2.DataCount = 0;
3292 pSMB->t2.DataOffset = 0;
3293 pSMB->t2.SetupCount = 1;
3294 pSMB->t2.Reserved3 = 0;
3295 pSMB->t2.SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION);
3296 byte_count = params + 1 /* pad */ ;
3297 pSMB->t2.TotalParameterCount = cpu_to_le16(params);
3298 pSMB->t2.ParameterCount = pSMB->t2.TotalParameterCount;
3299 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_ALL_INFO);
3302 pSMB->hdr.smb_buf_length += byte_count;
3304 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3305 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3307 cFYI(1, ("Send error in QPathInfo = %d", rc));
3308 } else { /* decode response */
3309 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3311 if (rc) /* BB add auto retry on EOPNOTSUPP? */
3313 else if (pSMBr->ByteCount < 40)
3314 rc = -EIO; /* bad smb */
3315 else if (pFindData) {
3316 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3317 memcpy((char *) pFindData,
3318 (char *) &pSMBr->hdr.Protocol +
3319 data_offset, sizeof(FILE_ALL_INFO));
3323 cifs_buf_release(pSMB);
3325 goto QFileInfoRetry;
3331 CIFSSMBQPathInfo(const int xid, struct cifsTconInfo *tcon,
3332 const unsigned char *searchName,
3333 FILE_ALL_INFO *pFindData,
3334 int legacy /* old style infolevel */,
3335 const struct nls_table *nls_codepage, int remap)
3337 /* level 263 SMB_QUERY_FILE_ALL_INFO */
3338 TRANSACTION2_QPI_REQ *pSMB = NULL;
3339 TRANSACTION2_QPI_RSP *pSMBr = NULL;
3343 __u16 params, byte_count;
3345 /* cFYI(1, "In QPathInfo path %s", searchName); */
3347 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3352 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3354 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
3355 PATH_MAX, nls_codepage, remap);
3356 name_len++; /* trailing null */
3358 } else { /* BB improve the check for buffer overruns BB */
3359 name_len = strnlen(searchName, PATH_MAX);
3360 name_len++; /* trailing null */
3361 strncpy(pSMB->FileName, searchName, name_len);
3364 params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */;
3365 pSMB->TotalDataCount = 0;
3366 pSMB->MaxParameterCount = cpu_to_le16(2);
3367 /* BB find exact max SMB PDU from sess structure BB */
3368 pSMB->MaxDataCount = cpu_to_le16(4000);
3369 pSMB->MaxSetupCount = 0;
3373 pSMB->Reserved2 = 0;
3374 pSMB->ParameterOffset = cpu_to_le16(offsetof(
3375 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
3376 pSMB->DataCount = 0;
3377 pSMB->DataOffset = 0;
3378 pSMB->SetupCount = 1;
3379 pSMB->Reserved3 = 0;
3380 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
3381 byte_count = params + 1 /* pad */ ;
3382 pSMB->TotalParameterCount = cpu_to_le16(params);
3383 pSMB->ParameterCount = pSMB->TotalParameterCount;
3385 pSMB->InformationLevel = cpu_to_le16(SMB_INFO_STANDARD);
3387 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_ALL_INFO);
3388 pSMB->Reserved4 = 0;
3389 pSMB->hdr.smb_buf_length += byte_count;
3390 pSMB->ByteCount = cpu_to_le16(byte_count);
3392 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3393 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3395 cFYI(1, "Send error in QPathInfo = %d", rc);
3396 } else { /* decode response */
3397 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3399 if (rc) /* BB add auto retry on EOPNOTSUPP? */
3401 else if (!legacy && (pSMBr->ByteCount < 40))
3402 rc = -EIO; /* bad smb */
3403 else if (legacy && (pSMBr->ByteCount < 24))
3404 rc = -EIO; /* 24 or 26 expected but we do not read
3406 else if (pFindData) {
3408 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3410 /* On legacy responses we do not read the last field,
3411 EAsize, fortunately since it varies by subdialect and
3412 also note it differs on Set vs. Get, ie two bytes or 4
3413 bytes depending but we don't care here */
3415 size = sizeof(FILE_INFO_STANDARD);
3417 size = sizeof(FILE_ALL_INFO);
3418 memcpy((char *) pFindData,
3419 (char *) &pSMBr->hdr.Protocol +
3424 cifs_buf_release(pSMB);
3426 goto QPathInfoRetry;
3432 CIFSSMBUnixQFileInfo(const int xid, struct cifsTconInfo *tcon,
3433 u16 netfid, FILE_UNIX_BASIC_INFO *pFindData)
3435 struct smb_t2_qfi_req *pSMB = NULL;
3436 struct smb_t2_qfi_rsp *pSMBr = NULL;
3439 __u16 params, byte_count;
3442 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3447 params = 2 /* level */ + 2 /* fid */;
3448 pSMB->t2.TotalDataCount = 0;
3449 pSMB->t2.MaxParameterCount = cpu_to_le16(4);
3450 /* BB find exact max data count below from sess structure BB */
3451 pSMB->t2.MaxDataCount = cpu_to_le16(CIFSMaxBufSize);
3452 pSMB->t2.MaxSetupCount = 0;
3453 pSMB->t2.Reserved = 0;
3455 pSMB->t2.Timeout = 0;
3456 pSMB->t2.Reserved2 = 0;
3457 pSMB->t2.ParameterOffset = cpu_to_le16(offsetof(struct smb_t2_qfi_req,
3459 pSMB->t2.DataCount = 0;
3460 pSMB->t2.DataOffset = 0;
3461 pSMB->t2.SetupCount = 1;
3462 pSMB->t2.Reserved3 = 0;
3463 pSMB->t2.SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION);
3464 byte_count = params + 1 /* pad */ ;
3465 pSMB->t2.TotalParameterCount = cpu_to_le16(params);
3466 pSMB->t2.ParameterCount = pSMB->t2.TotalParameterCount;
3467 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC);
3470 pSMB->hdr.smb_buf_length += byte_count;
3472 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3473 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3475 cFYI(1, ("Send error in QPathInfo = %d", rc));
3476 } else { /* decode response */
3477 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3479 if (rc || (pSMBr->ByteCount < sizeof(FILE_UNIX_BASIC_INFO))) {
3480 cERROR(1, ("Malformed FILE_UNIX_BASIC_INFO response.\n"
3481 "Unix Extensions can be disabled on mount "
3482 "by specifying the nosfu mount option."));
3483 rc = -EIO; /* bad smb */
3485 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3486 memcpy((char *) pFindData,
3487 (char *) &pSMBr->hdr.Protocol +
3489 sizeof(FILE_UNIX_BASIC_INFO));
3493 cifs_buf_release(pSMB);
3495 goto UnixQFileInfoRetry;
3501 CIFSSMBUnixQPathInfo(const int xid, struct cifsTconInfo *tcon,
3502 const unsigned char *searchName,
3503 FILE_UNIX_BASIC_INFO *pFindData,
3504 const struct nls_table *nls_codepage, int remap)
3506 /* SMB_QUERY_FILE_UNIX_BASIC */
3507 TRANSACTION2_QPI_REQ *pSMB = NULL;
3508 TRANSACTION2_QPI_RSP *pSMBr = NULL;
3510 int bytes_returned = 0;
3512 __u16 params, byte_count;
3514 cFYI(1, "In QPathInfo (Unix) the path %s", searchName);
3516 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3521 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3523 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
3524 PATH_MAX, nls_codepage, remap);
3525 name_len++; /* trailing null */
3527 } else { /* BB improve the check for buffer overruns BB */
3528 name_len = strnlen(searchName, PATH_MAX);
3529 name_len++; /* trailing null */
3530 strncpy(pSMB->FileName, searchName, name_len);
3533 params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */;
3534 pSMB->TotalDataCount = 0;
3535 pSMB->MaxParameterCount = cpu_to_le16(2);
3536 /* BB find exact max SMB PDU from sess structure BB */
3537 pSMB->MaxDataCount = cpu_to_le16(4000);
3538 pSMB->MaxSetupCount = 0;
3542 pSMB->Reserved2 = 0;
3543 pSMB->ParameterOffset = cpu_to_le16(offsetof(
3544 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
3545 pSMB->DataCount = 0;
3546 pSMB->DataOffset = 0;
3547 pSMB->SetupCount = 1;
3548 pSMB->Reserved3 = 0;
3549 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
3550 byte_count = params + 1 /* pad */ ;
3551 pSMB->TotalParameterCount = cpu_to_le16(params);
3552 pSMB->ParameterCount = pSMB->TotalParameterCount;
3553 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC);
3554 pSMB->Reserved4 = 0;
3555 pSMB->hdr.smb_buf_length += byte_count;
3556 pSMB->ByteCount = cpu_to_le16(byte_count);
3558 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3559 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3561 cFYI(1, "Send error in QPathInfo = %d", rc);
3562 } else { /* decode response */
3563 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3565 if (rc || (pSMBr->ByteCount < sizeof(FILE_UNIX_BASIC_INFO))) {
3566 cERROR(1, "Malformed FILE_UNIX_BASIC_INFO response.\n"
3567 "Unix Extensions can be disabled on mount "
3568 "by specifying the nosfu mount option.");
3569 rc = -EIO; /* bad smb */
3571 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3572 memcpy((char *) pFindData,
3573 (char *) &pSMBr->hdr.Protocol +
3575 sizeof(FILE_UNIX_BASIC_INFO));
3578 cifs_buf_release(pSMB);
3580 goto UnixQPathInfoRetry;
3585 /* xid, tcon, searchName and codepage are input parms, rest are returned */
3587 CIFSFindFirst(const int xid, struct cifsTconInfo *tcon,
3588 const char *searchName,
3589 const struct nls_table *nls_codepage,
3591 struct cifs_search_info *psrch_inf, int remap, const char dirsep)
3593 /* level 257 SMB_ */
3594 TRANSACTION2_FFIRST_REQ *pSMB = NULL;
3595 TRANSACTION2_FFIRST_RSP *pSMBr = NULL;
3596 T2_FFIRST_RSP_PARMS *parms;
3598 int bytes_returned = 0;
3600 __u16 params, byte_count;
3602 cFYI(1, "In FindFirst for %s", searchName);
3605 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3610 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3612 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
3613 PATH_MAX, nls_codepage, remap);
3614 /* We can not add the asterik earlier in case
3615 it got remapped to 0xF03A as if it were part of the
3616 directory name instead of a wildcard */
3618 pSMB->FileName[name_len] = dirsep;
3619 pSMB->FileName[name_len+1] = 0;
3620 pSMB->FileName[name_len+2] = '*';
3621 pSMB->FileName[name_len+3] = 0;
3622 name_len += 4; /* now the trailing null */
3623 pSMB->FileName[name_len] = 0; /* null terminate just in case */
3624 pSMB->FileName[name_len+1] = 0;
3626 } else { /* BB add check for overrun of SMB buf BB */
3627 name_len = strnlen(searchName, PATH_MAX);
3628 /* BB fix here and in unicode clause above ie
3629 if (name_len > buffersize-header)
3630 free buffer exit; BB */
3631 strncpy(pSMB->FileName, searchName, name_len);
3632 pSMB->FileName[name_len] = dirsep;
3633 pSMB->FileName[name_len+1] = '*';
3634 pSMB->FileName[name_len+2] = 0;
3638 params = 12 + name_len /* includes null */ ;
3639 pSMB->TotalDataCount = 0; /* no EAs */
3640 pSMB->MaxParameterCount = cpu_to_le16(10);
3641 pSMB->MaxDataCount = cpu_to_le16((tcon->ses->server->maxBuf -
3642 MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
3643 pSMB->MaxSetupCount = 0;
3647 pSMB->Reserved2 = 0;
3648 byte_count = params + 1 /* pad */ ;
3649 pSMB->TotalParameterCount = cpu_to_le16(params);
3650 pSMB->ParameterCount = pSMB->TotalParameterCount;
3651 pSMB->ParameterOffset = cpu_to_le16(
3652 offsetof(struct smb_com_transaction2_ffirst_req, SearchAttributes)
3654 pSMB->DataCount = 0;
3655 pSMB->DataOffset = 0;
3656 pSMB->SetupCount = 1; /* one byte, no need to make endian neutral */
3657 pSMB->Reserved3 = 0;
3658 pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_FIRST);
3659 pSMB->SearchAttributes =
3660 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
3662 pSMB->SearchCount = cpu_to_le16(CIFSMaxBufSize/sizeof(FILE_UNIX_INFO));
3663 pSMB->SearchFlags = cpu_to_le16(CIFS_SEARCH_CLOSE_AT_END |
3664 CIFS_SEARCH_RETURN_RESUME);
3665 pSMB->InformationLevel = cpu_to_le16(psrch_inf->info_level);
3667 /* BB what should we set StorageType to? Does it matter? BB */
3668 pSMB->SearchStorageType = 0;
3669 pSMB->hdr.smb_buf_length += byte_count;
3670 pSMB->ByteCount = cpu_to_le16(byte_count);
3672 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3673 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3674 cifs_stats_inc(&tcon->num_ffirst);
3676 if (rc) {/* BB add logic to retry regular search if Unix search
3677 rejected unexpectedly by server */
3678 /* BB Add code to handle unsupported level rc */
3679 cFYI(1, "Error in FindFirst = %d", rc);
3681 cifs_buf_release(pSMB);
3683 /* BB eventually could optimize out free and realloc of buf */
3686 goto findFirstRetry;
3687 } else { /* decode response */
3688 /* BB remember to free buffer if error BB */
3689 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3693 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
3694 psrch_inf->unicode = true;
3696 psrch_inf->unicode = false;
3698 psrch_inf->ntwrk_buf_start = (char *)pSMBr;
3699 psrch_inf->smallBuf = 0;
3700 psrch_inf->srch_entries_start =
3701 (char *) &pSMBr->hdr.Protocol +
3702 le16_to_cpu(pSMBr->t2.DataOffset);
3703 parms = (T2_FFIRST_RSP_PARMS *)((char *) &pSMBr->hdr.Protocol +
3704 le16_to_cpu(pSMBr->t2.ParameterOffset));
3706 if (parms->EndofSearch)
3707 psrch_inf->endOfSearch = true;
3709 psrch_inf->endOfSearch = false;
3711 psrch_inf->entries_in_buffer =
3712 le16_to_cpu(parms->SearchCount);
3713 psrch_inf->index_of_last_entry = 2 /* skip . and .. */ +
3714 psrch_inf->entries_in_buffer;
3715 lnoff = le16_to_cpu(parms->LastNameOffset);
3716 if (tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE <
3718 cERROR(1, "ignoring corrupt resume name");
3719 psrch_inf->last_entry = NULL;
3723 psrch_inf->last_entry = psrch_inf->srch_entries_start +
3726 *pnetfid = parms->SearchHandle;
3728 cifs_buf_release(pSMB);
3735 int CIFSFindNext(const int xid, struct cifsTconInfo *tcon,
3736 __u16 searchHandle, struct cifs_search_info *psrch_inf)
3738 TRANSACTION2_FNEXT_REQ *pSMB = NULL;
3739 TRANSACTION2_FNEXT_RSP *pSMBr = NULL;
3740 T2_FNEXT_RSP_PARMS *parms;
3741 char *response_data;
3743 int bytes_returned, name_len;
3744 __u16 params, byte_count;
3746 cFYI(1, "In FindNext");
3748 if (psrch_inf->endOfSearch)
3751 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3756 params = 14; /* includes 2 bytes of null string, converted to LE below*/
3758 pSMB->TotalDataCount = 0; /* no EAs */
3759 pSMB->MaxParameterCount = cpu_to_le16(8);
3760 pSMB->MaxDataCount =
3761 cpu_to_le16((tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE) &
3763 pSMB->MaxSetupCount = 0;
3767 pSMB->Reserved2 = 0;
3768 pSMB->ParameterOffset = cpu_to_le16(
3769 offsetof(struct smb_com_transaction2_fnext_req,SearchHandle) - 4);
3770 pSMB->DataCount = 0;
3771 pSMB->DataOffset = 0;
3772 pSMB->SetupCount = 1;
3773 pSMB->Reserved3 = 0;
3774 pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_NEXT);
3775 pSMB->SearchHandle = searchHandle; /* always kept as le */
3777 cpu_to_le16(CIFSMaxBufSize / sizeof(FILE_UNIX_INFO));
3778 pSMB->InformationLevel = cpu_to_le16(psrch_inf->info_level);
3779 pSMB->ResumeKey = psrch_inf->resume_key;
3781 cpu_to_le16(CIFS_SEARCH_CLOSE_AT_END | CIFS_SEARCH_RETURN_RESUME);
3783 name_len = psrch_inf->resume_name_len;
3785 if (name_len < PATH_MAX) {
3786 memcpy(pSMB->ResumeFileName, psrch_inf->presume_name, name_len);
3787 byte_count += name_len;
3788 /* 14 byte parm len above enough for 2 byte null terminator */
3789 pSMB->ResumeFileName[name_len] = 0;
3790 pSMB->ResumeFileName[name_len+1] = 0;
3793 goto FNext2_err_exit;
3795 byte_count = params + 1 /* pad */ ;
3796 pSMB->TotalParameterCount = cpu_to_le16(params);
3797 pSMB->ParameterCount = pSMB->TotalParameterCount;
3798 pSMB->hdr.smb_buf_length += byte_count;
3799 pSMB->ByteCount = cpu_to_le16(byte_count);
3801 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3802 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3803 cifs_stats_inc(&tcon->num_fnext);
3806 psrch_inf->endOfSearch = true;
3807 cifs_buf_release(pSMB);
3808 rc = 0; /* search probably was closed at end of search*/
3810 cFYI(1, "FindNext returned = %d", rc);
3811 } else { /* decode response */
3812 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3817 /* BB fixme add lock for file (srch_info) struct here */
3818 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
3819 psrch_inf->unicode = true;
3821 psrch_inf->unicode = false;
3822 response_data = (char *) &pSMBr->hdr.Protocol +
3823 le16_to_cpu(pSMBr->t2.ParameterOffset);
3824 parms = (T2_FNEXT_RSP_PARMS *)response_data;
3825 response_data = (char *)&pSMBr->hdr.Protocol +
3826 le16_to_cpu(pSMBr->t2.DataOffset);
3827 if (psrch_inf->smallBuf)
3828 cifs_small_buf_release(
3829 psrch_inf->ntwrk_buf_start);
3831 cifs_buf_release(psrch_inf->ntwrk_buf_start);
3832 psrch_inf->srch_entries_start = response_data;
3833 psrch_inf->ntwrk_buf_start = (char *)pSMB;
3834 psrch_inf->smallBuf = 0;
3835 if (parms->EndofSearch)
3836 psrch_inf->endOfSearch = true;
3838 psrch_inf->endOfSearch = false;
3839 psrch_inf->entries_in_buffer =
3840 le16_to_cpu(parms->SearchCount);
3841 psrch_inf->index_of_last_entry +=
3842 psrch_inf->entries_in_buffer;
3843 lnoff = le16_to_cpu(parms->LastNameOffset);
3844 if (tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE <
3846 cERROR(1, "ignoring corrupt resume name");
3847 psrch_inf->last_entry = NULL;
3850 psrch_inf->last_entry =
3851 psrch_inf->srch_entries_start + lnoff;
3853 /* cFYI(1, "fnxt2 entries in buf %d index_of_last %d",
3854 psrch_inf->entries_in_buffer, psrch_inf->index_of_last_entry); */
3856 /* BB fixme add unlock here */
3861 /* BB On error, should we leave previous search buf (and count and
3862 last entry fields) intact or free the previous one? */
3864 /* Note: On -EAGAIN error only caller can retry on handle based calls
3865 since file handle passed in no longer valid */
3868 cifs_buf_release(pSMB);
3873 CIFSFindClose(const int xid, struct cifsTconInfo *tcon,
3874 const __u16 searchHandle)
3877 FINDCLOSE_REQ *pSMB = NULL;
3879 cFYI(1, "In CIFSSMBFindClose");
3880 rc = small_smb_init(SMB_COM_FIND_CLOSE2, 1, tcon, (void **)&pSMB);
3882 /* no sense returning error if session restarted
3883 as file handle has been closed */
3889 pSMB->FileID = searchHandle;
3890 pSMB->ByteCount = 0;
3891 rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0);
3893 cERROR(1, "Send error in FindClose = %d", rc);
3895 cifs_stats_inc(&tcon->num_fclose);
3897 /* Since session is dead, search handle closed on server already */
3905 CIFSGetSrvInodeNumber(const int xid, struct cifsTconInfo *tcon,
3906 const unsigned char *searchName,
3907 __u64 *inode_number,
3908 const struct nls_table *nls_codepage, int remap)
3911 TRANSACTION2_QPI_REQ *pSMB = NULL;
3912 TRANSACTION2_QPI_RSP *pSMBr = NULL;
3913 int name_len, bytes_returned;
3914 __u16 params, byte_count;
3916 cFYI(1, "In GetSrvInodeNum for %s", searchName);
3920 GetInodeNumberRetry:
3921 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3926 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3928 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
3929 PATH_MAX, nls_codepage, remap);
3930 name_len++; /* trailing null */
3932 } else { /* BB improve the check for buffer overruns BB */
3933 name_len = strnlen(searchName, PATH_MAX);
3934 name_len++; /* trailing null */
3935 strncpy(pSMB->FileName, searchName, name_len);
3938 params = 2 /* level */ + 4 /* rsrvd */ + name_len /* incl null */ ;
3939 pSMB->TotalDataCount = 0;
3940 pSMB->MaxParameterCount = cpu_to_le16(2);
3941 /* BB find exact max data count below from sess structure BB */
3942 pSMB->MaxDataCount = cpu_to_le16(4000);
3943 pSMB->MaxSetupCount = 0;
3947 pSMB->Reserved2 = 0;
3948 pSMB->ParameterOffset = cpu_to_le16(offsetof(
3949 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
3950 pSMB->DataCount = 0;
3951 pSMB->DataOffset = 0;
3952 pSMB->SetupCount = 1;
3953 pSMB->Reserved3 = 0;
3954 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
3955 byte_count = params + 1 /* pad */ ;
3956 pSMB->TotalParameterCount = cpu_to_le16(params);
3957 pSMB->ParameterCount = pSMB->TotalParameterCount;
3958 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_INTERNAL_INFO);
3959 pSMB->Reserved4 = 0;
3960 pSMB->hdr.smb_buf_length += byte_count;
3961 pSMB->ByteCount = cpu_to_le16(byte_count);
3963 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3964 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3966 cFYI(1, "error %d in QueryInternalInfo", rc);
3968 /* decode response */
3969 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3970 if (rc || (pSMBr->ByteCount < 2))
3971 /* BB also check enough total bytes returned */
3972 /* If rc should we check for EOPNOSUPP and
3973 disable the srvino flag? or in caller? */
3974 rc = -EIO; /* bad smb */
3976 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3977 __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
3978 struct file_internal_info *pfinfo;
3979 /* BB Do we need a cast or hash here ? */
3981 cFYI(1, "Illegal size ret in QryIntrnlInf");
3983 goto GetInodeNumOut;
3985 pfinfo = (struct file_internal_info *)
3986 (data_offset + (char *) &pSMBr->hdr.Protocol);
3987 *inode_number = le64_to_cpu(pfinfo->UniqueId);
3991 cifs_buf_release(pSMB);
3993 goto GetInodeNumberRetry;
3997 /* parses DFS refferal V3 structure
3998 * caller is responsible for freeing target_nodes
4001 * on failure - errno
4004 parse_DFS_referrals(TRANSACTION2_GET_DFS_REFER_RSP *pSMBr,
4005 unsigned int *num_of_nodes,
4006 struct dfs_info3_param **target_nodes,
4007 const struct nls_table *nls_codepage, int remap,
4008 const char *searchName)
4013 struct dfs_referral_level_3 *ref;
4015 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
4019 *num_of_nodes = le16_to_cpu(pSMBr->NumberOfReferrals);
4021 if (*num_of_nodes < 1) {
4022 cERROR(1, "num_referrals: must be at least > 0,"
4023 "but we get num_referrals = %d\n", *num_of_nodes);
4025 goto parse_DFS_referrals_exit;
4028 ref = (struct dfs_referral_level_3 *) &(pSMBr->referrals);
4029 if (ref->VersionNumber != cpu_to_le16(3)) {
4030 cERROR(1, "Referrals of V%d version are not supported,"
4031 "should be V3", le16_to_cpu(ref->VersionNumber));
4033 goto parse_DFS_referrals_exit;
4036 /* get the upper boundary of the resp buffer */
4037 data_end = (char *)(&(pSMBr->PathConsumed)) +
4038 le16_to_cpu(pSMBr->t2.DataCount);
4040 cFYI(1, "num_referrals: %d dfs flags: 0x%x ... \n",
4042 le32_to_cpu(pSMBr->DFSFlags));
4044 *target_nodes = kzalloc(sizeof(struct dfs_info3_param) *
4045 *num_of_nodes, GFP_KERNEL);
4046 if (*target_nodes == NULL) {
4047 cERROR(1, "Failed to allocate buffer for target_nodes\n");
4049 goto parse_DFS_referrals_exit;
4052 /* collect necessary data from referrals */
4053 for (i = 0; i < *num_of_nodes; i++) {
4056 struct dfs_info3_param *node = (*target_nodes)+i;
4058 node->flags = le32_to_cpu(pSMBr->DFSFlags);
4060 __le16 *tmp = kmalloc(strlen(searchName)*2 + 2,
4064 goto parse_DFS_referrals_exit;
4066 cifsConvertToUCS((__le16 *) tmp, searchName,
4067 PATH_MAX, nls_codepage, remap);
4068 node->path_consumed = cifs_ucs2_bytes(tmp,
4069 le16_to_cpu(pSMBr->PathConsumed),
4073 node->path_consumed = le16_to_cpu(pSMBr->PathConsumed);
4075 node->server_type = le16_to_cpu(ref->ServerType);
4076 node->ref_flag = le16_to_cpu(ref->ReferralEntryFlags);
4079 temp = (char *)ref + le16_to_cpu(ref->DfsPathOffset);
4080 max_len = data_end - temp;
4081 node->path_name = cifs_strndup_from_ucs(temp, max_len,
4082 is_unicode, nls_codepage);
4083 if (!node->path_name) {
4085 goto parse_DFS_referrals_exit;
4088 /* copy link target UNC */
4089 temp = (char *)ref + le16_to_cpu(ref->NetworkAddressOffset);
4090 max_len = data_end - temp;
4091 node->node_name = cifs_strndup_from_ucs(temp, max_len,
4092 is_unicode, nls_codepage);
4093 if (!node->node_name)
4097 parse_DFS_referrals_exit:
4099 free_dfs_info_array(*target_nodes, *num_of_nodes);
4100 *target_nodes = NULL;
4107 CIFSGetDFSRefer(const int xid, struct cifsSesInfo *ses,
4108 const unsigned char *searchName,
4109 struct dfs_info3_param **target_nodes,
4110 unsigned int *num_of_nodes,
4111 const struct nls_table *nls_codepage, int remap)
4113 /* TRANS2_GET_DFS_REFERRAL */
4114 TRANSACTION2_GET_DFS_REFER_REQ *pSMB = NULL;
4115 TRANSACTION2_GET_DFS_REFER_RSP *pSMBr = NULL;
4119 __u16 params, byte_count;
4121 *target_nodes = NULL;
4123 cFYI(1, "In GetDFSRefer the path %s", searchName);
4127 rc = smb_init(SMB_COM_TRANSACTION2, 15, NULL, (void **) &pSMB,
4132 /* server pointer checked in called function,
4133 but should never be null here anyway */
4134 pSMB->hdr.Mid = GetNextMid(ses->server);
4135 pSMB->hdr.Tid = ses->ipc_tid;
4136 pSMB->hdr.Uid = ses->Suid;
4137 if (ses->capabilities & CAP_STATUS32)
4138 pSMB->hdr.Flags2 |= SMBFLG2_ERR_STATUS;
4139 if (ses->capabilities & CAP_DFS)
4140 pSMB->hdr.Flags2 |= SMBFLG2_DFS;
4142 if (ses->capabilities & CAP_UNICODE) {
4143 pSMB->hdr.Flags2 |= SMBFLG2_UNICODE;
4145 cifsConvertToUCS((__le16 *) pSMB->RequestFileName,
4146 searchName, PATH_MAX, nls_codepage, remap);
4147 name_len++; /* trailing null */
4149 } else { /* BB improve the check for buffer overruns BB */
4150 name_len = strnlen(searchName, PATH_MAX);
4151 name_len++; /* trailing null */
4152 strncpy(pSMB->RequestFileName, searchName, name_len);
4156 if (ses->server->secMode &
4157 (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
4158 pSMB->hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
4161 pSMB->hdr.Uid = ses->Suid;
4163 params = 2 /* level */ + name_len /*includes null */ ;
4164 pSMB->TotalDataCount = 0;
4165 pSMB->DataCount = 0;
4166 pSMB->DataOffset = 0;
4167 pSMB->MaxParameterCount = 0;
4168 /* BB find exact max SMB PDU from sess structure BB */
4169 pSMB->MaxDataCount = cpu_to_le16(4000);
4170 pSMB->MaxSetupCount = 0;
4174 pSMB->Reserved2 = 0;
4175 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4176 struct smb_com_transaction2_get_dfs_refer_req, MaxReferralLevel) - 4);
4177 pSMB->SetupCount = 1;
4178 pSMB->Reserved3 = 0;
4179 pSMB->SubCommand = cpu_to_le16(TRANS2_GET_DFS_REFERRAL);
4180 byte_count = params + 3 /* pad */ ;
4181 pSMB->ParameterCount = cpu_to_le16(params);
4182 pSMB->TotalParameterCount = pSMB->ParameterCount;
4183 pSMB->MaxReferralLevel = cpu_to_le16(3);
4184 pSMB->hdr.smb_buf_length += byte_count;
4185 pSMB->ByteCount = cpu_to_le16(byte_count);
4187 rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB,
4188 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4190 cFYI(1, "Send error in GetDFSRefer = %d", rc);
4193 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4195 /* BB Also check if enough total bytes returned? */
4196 if (rc || (pSMBr->ByteCount < 17)) {
4197 rc = -EIO; /* bad smb */
4201 cFYI(1, "Decoding GetDFSRefer response BCC: %d Offset %d",
4203 le16_to_cpu(pSMBr->t2.DataOffset));
4205 /* parse returned result into more usable form */
4206 rc = parse_DFS_referrals(pSMBr, num_of_nodes,
4207 target_nodes, nls_codepage, remap,
4211 cifs_buf_release(pSMB);
4219 /* Query File System Info such as free space to old servers such as Win 9x */
4221 SMBOldQFSInfo(const int xid, struct cifsTconInfo *tcon, struct kstatfs *FSData)
4223 /* level 0x01 SMB_QUERY_FILE_SYSTEM_INFO */
4224 TRANSACTION2_QFSI_REQ *pSMB = NULL;
4225 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4226 FILE_SYSTEM_ALLOC_INFO *response_data;
4228 int bytes_returned = 0;
4229 __u16 params, byte_count;
4231 cFYI(1, "OldQFSInfo");
4233 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4238 params = 2; /* level */
4239 pSMB->TotalDataCount = 0;
4240 pSMB->MaxParameterCount = cpu_to_le16(2);
4241 pSMB->MaxDataCount = cpu_to_le16(1000);
4242 pSMB->MaxSetupCount = 0;
4246 pSMB->Reserved2 = 0;
4247 byte_count = params + 1 /* pad */ ;
4248 pSMB->TotalParameterCount = cpu_to_le16(params);
4249 pSMB->ParameterCount = pSMB->TotalParameterCount;
4250 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4251 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4252 pSMB->DataCount = 0;
4253 pSMB->DataOffset = 0;
4254 pSMB->SetupCount = 1;
4255 pSMB->Reserved3 = 0;
4256 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4257 pSMB->InformationLevel = cpu_to_le16(SMB_INFO_ALLOCATION);
4258 pSMB->hdr.smb_buf_length += byte_count;
4259 pSMB->ByteCount = cpu_to_le16(byte_count);
4261 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4262 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4264 cFYI(1, "Send error in QFSInfo = %d", rc);
4265 } else { /* decode response */
4266 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4268 if (rc || (pSMBr->ByteCount < 18))
4269 rc = -EIO; /* bad smb */
4271 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4272 cFYI(1, "qfsinf resp BCC: %d Offset %d",
4273 pSMBr->ByteCount, data_offset);
4275 response_data = (FILE_SYSTEM_ALLOC_INFO *)
4276 (((char *) &pSMBr->hdr.Protocol) + data_offset);
4278 le16_to_cpu(response_data->BytesPerSector) *
4279 le32_to_cpu(response_data->
4280 SectorsPerAllocationUnit);
4282 le32_to_cpu(response_data->TotalAllocationUnits);
4283 FSData->f_bfree = FSData->f_bavail =
4284 le32_to_cpu(response_data->FreeAllocationUnits);
4285 cFYI(1, "Blocks: %lld Free: %lld Block size %ld",
4286 (unsigned long long)FSData->f_blocks,
4287 (unsigned long long)FSData->f_bfree,
4291 cifs_buf_release(pSMB);
4294 goto oldQFSInfoRetry;
4300 CIFSSMBQFSInfo(const int xid, struct cifsTconInfo *tcon, struct kstatfs *FSData)
4302 /* level 0x103 SMB_QUERY_FILE_SYSTEM_INFO */
4303 TRANSACTION2_QFSI_REQ *pSMB = NULL;
4304 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4305 FILE_SYSTEM_INFO *response_data;
4307 int bytes_returned = 0;
4308 __u16 params, byte_count;
4310 cFYI(1, "In QFSInfo");
4312 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4317 params = 2; /* level */
4318 pSMB->TotalDataCount = 0;
4319 pSMB->MaxParameterCount = cpu_to_le16(2);
4320 pSMB->MaxDataCount = cpu_to_le16(1000);
4321 pSMB->MaxSetupCount = 0;
4325 pSMB->Reserved2 = 0;
4326 byte_count = params + 1 /* pad */ ;
4327 pSMB->TotalParameterCount = cpu_to_le16(params);
4328 pSMB->ParameterCount = pSMB->TotalParameterCount;
4329 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4330 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4331 pSMB->DataCount = 0;
4332 pSMB->DataOffset = 0;
4333 pSMB->SetupCount = 1;
4334 pSMB->Reserved3 = 0;
4335 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4336 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_SIZE_INFO);
4337 pSMB->hdr.smb_buf_length += byte_count;
4338 pSMB->ByteCount = cpu_to_le16(byte_count);
4340 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4341 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4343 cFYI(1, "Send error in QFSInfo = %d", rc);
4344 } else { /* decode response */
4345 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4347 if (rc || (pSMBr->ByteCount < 24))
4348 rc = -EIO; /* bad smb */
4350 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4354 *) (((char *) &pSMBr->hdr.Protocol) +
4357 le32_to_cpu(response_data->BytesPerSector) *
4358 le32_to_cpu(response_data->
4359 SectorsPerAllocationUnit);
4361 le64_to_cpu(response_data->TotalAllocationUnits);
4362 FSData->f_bfree = FSData->f_bavail =
4363 le64_to_cpu(response_data->FreeAllocationUnits);
4364 cFYI(1, "Blocks: %lld Free: %lld Block size %ld",
4365 (unsigned long long)FSData->f_blocks,
4366 (unsigned long long)FSData->f_bfree,
4370 cifs_buf_release(pSMB);
4379 CIFSSMBQFSAttributeInfo(const int xid, struct cifsTconInfo *tcon)
4381 /* level 0x105 SMB_QUERY_FILE_SYSTEM_INFO */
4382 TRANSACTION2_QFSI_REQ *pSMB = NULL;
4383 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4384 FILE_SYSTEM_ATTRIBUTE_INFO *response_data;
4386 int bytes_returned = 0;
4387 __u16 params, byte_count;
4389 cFYI(1, "In QFSAttributeInfo");
4391 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4396 params = 2; /* level */
4397 pSMB->TotalDataCount = 0;
4398 pSMB->MaxParameterCount = cpu_to_le16(2);
4399 /* BB find exact max SMB PDU from sess structure BB */
4400 pSMB->MaxDataCount = cpu_to_le16(1000);
4401 pSMB->MaxSetupCount = 0;
4405 pSMB->Reserved2 = 0;
4406 byte_count = params + 1 /* pad */ ;
4407 pSMB->TotalParameterCount = cpu_to_le16(params);
4408 pSMB->ParameterCount = pSMB->TotalParameterCount;
4409 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4410 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4411 pSMB->DataCount = 0;
4412 pSMB->DataOffset = 0;
4413 pSMB->SetupCount = 1;
4414 pSMB->Reserved3 = 0;
4415 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4416 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_ATTRIBUTE_INFO);
4417 pSMB->hdr.smb_buf_length += byte_count;
4418 pSMB->ByteCount = cpu_to_le16(byte_count);
4420 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4421 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4423 cERROR(1, "Send error in QFSAttributeInfo = %d", rc);
4424 } else { /* decode response */
4425 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4427 if (rc || (pSMBr->ByteCount < 13)) {
4428 /* BB also check if enough bytes returned */
4429 rc = -EIO; /* bad smb */
4431 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4433 (FILE_SYSTEM_ATTRIBUTE_INFO
4434 *) (((char *) &pSMBr->hdr.Protocol) +
4436 memcpy(&tcon->fsAttrInfo, response_data,
4437 sizeof(FILE_SYSTEM_ATTRIBUTE_INFO));
4440 cifs_buf_release(pSMB);
4443 goto QFSAttributeRetry;
4449 CIFSSMBQFSDeviceInfo(const int xid, struct cifsTconInfo *tcon)
4451 /* level 0x104 SMB_QUERY_FILE_SYSTEM_INFO */
4452 TRANSACTION2_QFSI_REQ *pSMB = NULL;
4453 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4454 FILE_SYSTEM_DEVICE_INFO *response_data;
4456 int bytes_returned = 0;
4457 __u16 params, byte_count;
4459 cFYI(1, "In QFSDeviceInfo");
4461 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4466 params = 2; /* level */
4467 pSMB->TotalDataCount = 0;
4468 pSMB->MaxParameterCount = cpu_to_le16(2);
4469 /* BB find exact max SMB PDU from sess structure BB */
4470 pSMB->MaxDataCount = cpu_to_le16(1000);
4471 pSMB->MaxSetupCount = 0;
4475 pSMB->Reserved2 = 0;
4476 byte_count = params + 1 /* pad */ ;
4477 pSMB->TotalParameterCount = cpu_to_le16(params);
4478 pSMB->ParameterCount = pSMB->TotalParameterCount;
4479 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4480 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4482 pSMB->DataCount = 0;
4483 pSMB->DataOffset = 0;
4484 pSMB->SetupCount = 1;
4485 pSMB->Reserved3 = 0;
4486 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4487 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_DEVICE_INFO);
4488 pSMB->hdr.smb_buf_length += byte_count;
4489 pSMB->ByteCount = cpu_to_le16(byte_count);
4491 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4492 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4494 cFYI(1, "Send error in QFSDeviceInfo = %d", rc);
4495 } else { /* decode response */
4496 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4498 if (rc || (pSMBr->ByteCount < sizeof(FILE_SYSTEM_DEVICE_INFO)))
4499 rc = -EIO; /* bad smb */
4501 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4503 (FILE_SYSTEM_DEVICE_INFO *)
4504 (((char *) &pSMBr->hdr.Protocol) +
4506 memcpy(&tcon->fsDevInfo, response_data,
4507 sizeof(FILE_SYSTEM_DEVICE_INFO));
4510 cifs_buf_release(pSMB);
4513 goto QFSDeviceRetry;
4519 CIFSSMBQFSUnixInfo(const int xid, struct cifsTconInfo *tcon)
4521 /* level 0x200 SMB_QUERY_CIFS_UNIX_INFO */
4522 TRANSACTION2_QFSI_REQ *pSMB = NULL;
4523 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4524 FILE_SYSTEM_UNIX_INFO *response_data;
4526 int bytes_returned = 0;
4527 __u16 params, byte_count;
4529 cFYI(1, "In QFSUnixInfo");
4531 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4536 params = 2; /* level */
4537 pSMB->TotalDataCount = 0;
4538 pSMB->DataCount = 0;
4539 pSMB->DataOffset = 0;
4540 pSMB->MaxParameterCount = cpu_to_le16(2);
4541 /* BB find exact max SMB PDU from sess structure BB */
4542 pSMB->MaxDataCount = cpu_to_le16(100);
4543 pSMB->MaxSetupCount = 0;
4547 pSMB->Reserved2 = 0;
4548 byte_count = params + 1 /* pad */ ;
4549 pSMB->ParameterCount = cpu_to_le16(params);
4550 pSMB->TotalParameterCount = pSMB->ParameterCount;
4551 pSMB->ParameterOffset = cpu_to_le16(offsetof(struct
4552 smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4553 pSMB->SetupCount = 1;
4554 pSMB->Reserved3 = 0;
4555 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4556 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_CIFS_UNIX_INFO);
4557 pSMB->hdr.smb_buf_length += byte_count;
4558 pSMB->ByteCount = cpu_to_le16(byte_count);
4560 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4561 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4563 cERROR(1, "Send error in QFSUnixInfo = %d", rc);
4564 } else { /* decode response */
4565 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4567 if (rc || (pSMBr->ByteCount < 13)) {
4568 rc = -EIO; /* bad smb */
4570 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4572 (FILE_SYSTEM_UNIX_INFO
4573 *) (((char *) &pSMBr->hdr.Protocol) +
4575 memcpy(&tcon->fsUnixInfo, response_data,
4576 sizeof(FILE_SYSTEM_UNIX_INFO));
4579 cifs_buf_release(pSMB);
4589 CIFSSMBSetFSUnixInfo(const int xid, struct cifsTconInfo *tcon, __u64 cap)
4591 /* level 0x200 SMB_SET_CIFS_UNIX_INFO */
4592 TRANSACTION2_SETFSI_REQ *pSMB = NULL;
4593 TRANSACTION2_SETFSI_RSP *pSMBr = NULL;
4595 int bytes_returned = 0;
4596 __u16 params, param_offset, offset, byte_count;
4598 cFYI(1, "In SETFSUnixInfo");
4600 /* BB switch to small buf init to save memory */
4601 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4606 params = 4; /* 2 bytes zero followed by info level. */
4607 pSMB->MaxSetupCount = 0;
4611 pSMB->Reserved2 = 0;
4612 param_offset = offsetof(struct smb_com_transaction2_setfsi_req, FileNum)
4614 offset = param_offset + params;
4616 pSMB->MaxParameterCount = cpu_to_le16(4);
4617 /* BB find exact max SMB PDU from sess structure BB */
4618 pSMB->MaxDataCount = cpu_to_le16(100);
4619 pSMB->SetupCount = 1;
4620 pSMB->Reserved3 = 0;
4621 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FS_INFORMATION);
4622 byte_count = 1 /* pad */ + params + 12;
4624 pSMB->DataCount = cpu_to_le16(12);
4625 pSMB->ParameterCount = cpu_to_le16(params);
4626 pSMB->TotalDataCount = pSMB->DataCount;
4627 pSMB->TotalParameterCount = pSMB->ParameterCount;
4628 pSMB->ParameterOffset = cpu_to_le16(param_offset);
4629 pSMB->DataOffset = cpu_to_le16(offset);
4633 pSMB->InformationLevel = cpu_to_le16(SMB_SET_CIFS_UNIX_INFO);
4636 pSMB->ClientUnixMajor = cpu_to_le16(CIFS_UNIX_MAJOR_VERSION);
4637 pSMB->ClientUnixMinor = cpu_to_le16(CIFS_UNIX_MINOR_VERSION);
4638 pSMB->ClientUnixCap = cpu_to_le64(cap);
4640 pSMB->hdr.smb_buf_length += byte_count;
4641 pSMB->ByteCount = cpu_to_le16(byte_count);
4643 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4644 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4646 cERROR(1, "Send error in SETFSUnixInfo = %d", rc);
4647 } else { /* decode response */
4648 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4650 rc = -EIO; /* bad smb */
4652 cifs_buf_release(pSMB);
4655 goto SETFSUnixRetry;
4663 CIFSSMBQFSPosixInfo(const int xid, struct cifsTconInfo *tcon,
4664 struct kstatfs *FSData)
4666 /* level 0x201 SMB_QUERY_CIFS_POSIX_INFO */
4667 TRANSACTION2_QFSI_REQ *pSMB = NULL;
4668 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4669 FILE_SYSTEM_POSIX_INFO *response_data;
4671 int bytes_returned = 0;
4672 __u16 params, byte_count;
4674 cFYI(1, "In QFSPosixInfo");
4676 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4681 params = 2; /* level */
4682 pSMB->TotalDataCount = 0;
4683 pSMB->DataCount = 0;
4684 pSMB->DataOffset = 0;
4685 pSMB->MaxParameterCount = cpu_to_le16(2);
4686 /* BB find exact max SMB PDU from sess structure BB */
4687 pSMB->MaxDataCount = cpu_to_le16(100);
4688 pSMB->MaxSetupCount = 0;
4692 pSMB->Reserved2 = 0;
4693 byte_count = params + 1 /* pad */ ;
4694 pSMB->ParameterCount = cpu_to_le16(params);
4695 pSMB->TotalParameterCount = pSMB->ParameterCount;
4696 pSMB->ParameterOffset = cpu_to_le16(offsetof(struct
4697 smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4698 pSMB->SetupCount = 1;
4699 pSMB->Reserved3 = 0;
4700 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4701 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_POSIX_FS_INFO);
4702 pSMB->hdr.smb_buf_length += byte_count;
4703 pSMB->ByteCount = cpu_to_le16(byte_count);
4705 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4706 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4708 cFYI(1, "Send error in QFSUnixInfo = %d", rc);
4709 } else { /* decode response */
4710 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4712 if (rc || (pSMBr->ByteCount < 13)) {
4713 rc = -EIO; /* bad smb */
4715 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4717 (FILE_SYSTEM_POSIX_INFO
4718 *) (((char *) &pSMBr->hdr.Protocol) +
4721 le32_to_cpu(response_data->BlockSize);
4723 le64_to_cpu(response_data->TotalBlocks);
4725 le64_to_cpu(response_data->BlocksAvail);
4726 if (response_data->UserBlocksAvail == cpu_to_le64(-1)) {
4727 FSData->f_bavail = FSData->f_bfree;
4730 le64_to_cpu(response_data->UserBlocksAvail);
4732 if (response_data->TotalFileNodes != cpu_to_le64(-1))
4734 le64_to_cpu(response_data->TotalFileNodes);
4735 if (response_data->FreeFileNodes != cpu_to_le64(-1))
4737 le64_to_cpu(response_data->FreeFileNodes);
4740 cifs_buf_release(pSMB);
4749 /* We can not use write of zero bytes trick to
4750 set file size due to need for large file support. Also note that
4751 this SetPathInfo is preferred to SetFileInfo based method in next
4752 routine which is only needed to work around a sharing violation bug
4753 in Samba which this routine can run into */
4756 CIFSSMBSetEOF(const int xid, struct cifsTconInfo *tcon, const char *fileName,
4757 __u64 size, bool SetAllocation,
4758 const struct nls_table *nls_codepage, int remap)
4760 struct smb_com_transaction2_spi_req *pSMB = NULL;
4761 struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
4762 struct file_end_of_file_info *parm_data;
4765 int bytes_returned = 0;
4766 __u16 params, byte_count, data_count, param_offset, offset;
4768 cFYI(1, "In SetEOF");
4770 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4775 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4777 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
4778 PATH_MAX, nls_codepage, remap);
4779 name_len++; /* trailing null */
4781 } else { /* BB improve the check for buffer overruns BB */
4782 name_len = strnlen(fileName, PATH_MAX);
4783 name_len++; /* trailing null */
4784 strncpy(pSMB->FileName, fileName, name_len);
4786 params = 6 + name_len;
4787 data_count = sizeof(struct file_end_of_file_info);
4788 pSMB->MaxParameterCount = cpu_to_le16(2);
4789 pSMB->MaxDataCount = cpu_to_le16(4100);
4790 pSMB->MaxSetupCount = 0;
4794 pSMB->Reserved2 = 0;
4795 param_offset = offsetof(struct smb_com_transaction2_spi_req,
4796 InformationLevel) - 4;
4797 offset = param_offset + params;
4798 if (SetAllocation) {
4799 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
4800 pSMB->InformationLevel =
4801 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2);
4803 pSMB->InformationLevel =
4804 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO);
4805 } else /* Set File Size */ {
4806 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
4807 pSMB->InformationLevel =
4808 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO2);
4810 pSMB->InformationLevel =
4811 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO);
4815 (struct file_end_of_file_info *) (((char *) &pSMB->hdr.Protocol) +
4817 pSMB->ParameterOffset = cpu_to_le16(param_offset);
4818 pSMB->DataOffset = cpu_to_le16(offset);
4819 pSMB->SetupCount = 1;
4820 pSMB->Reserved3 = 0;
4821 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
4822 byte_count = 3 /* pad */ + params + data_count;
4823 pSMB->DataCount = cpu_to_le16(data_count);
4824 pSMB->TotalDataCount = pSMB->DataCount;
4825 pSMB->ParameterCount = cpu_to_le16(params);
4826 pSMB->TotalParameterCount = pSMB->ParameterCount;
4827 pSMB->Reserved4 = 0;
4828 pSMB->hdr.smb_buf_length += byte_count;
4829 parm_data->FileSize = cpu_to_le64(size);
4830 pSMB->ByteCount = cpu_to_le16(byte_count);
4831 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4832 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4834 cFYI(1, "SetPathInfo (file size) returned %d", rc);
4836 cifs_buf_release(pSMB);
4845 CIFSSMBSetFileSize(const int xid, struct cifsTconInfo *tcon, __u64 size,
4846 __u16 fid, __u32 pid_of_opener, bool SetAllocation)
4848 struct smb_com_transaction2_sfi_req *pSMB = NULL;
4850 struct file_end_of_file_info *parm_data;
4852 __u16 params, param_offset, offset, byte_count, count;
4854 cFYI(1, "SetFileSize (via SetFileInfo) %lld",
4856 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
4861 pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
4862 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));
4865 pSMB->MaxSetupCount = 0;
4869 pSMB->Reserved2 = 0;
4870 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
4871 offset = param_offset + params;
4873 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
4875 count = sizeof(struct file_end_of_file_info);
4876 pSMB->MaxParameterCount = cpu_to_le16(2);
4877 /* BB find exact max SMB PDU from sess structure BB */
4878 pSMB->MaxDataCount = cpu_to_le16(1000);
4879 pSMB->SetupCount = 1;
4880 pSMB->Reserved3 = 0;
4881 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
4882 byte_count = 3 /* pad */ + params + count;
4883 pSMB->DataCount = cpu_to_le16(count);
4884 pSMB->ParameterCount = cpu_to_le16(params);
4885 pSMB->TotalDataCount = pSMB->DataCount;
4886 pSMB->TotalParameterCount = pSMB->ParameterCount;
4887 pSMB->ParameterOffset = cpu_to_le16(param_offset);
4889 (struct file_end_of_file_info *) (((char *) &pSMB->hdr.Protocol)
4891 pSMB->DataOffset = cpu_to_le16(offset);
4892 parm_data->FileSize = cpu_to_le64(size);
4894 if (SetAllocation) {
4895 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
4896 pSMB->InformationLevel =
4897 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2);
4899 pSMB->InformationLevel =
4900 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO);
4901 } else /* Set File Size */ {
4902 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
4903 pSMB->InformationLevel =
4904 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO2);
4906 pSMB->InformationLevel =
4907 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO);
4909 pSMB->Reserved4 = 0;
4910 pSMB->hdr.smb_buf_length += byte_count;
4911 pSMB->ByteCount = cpu_to_le16(byte_count);
4912 rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0);
4914 cFYI(1, "Send error in SetFileInfo (SetFileSize) = %d", rc);
4917 /* Note: On -EAGAIN error only caller can retry on handle based calls
4918 since file handle passed in no longer valid */
4923 /* Some legacy servers such as NT4 require that the file times be set on
4924 an open handle, rather than by pathname - this is awkward due to
4925 potential access conflicts on the open, but it is unavoidable for these
4926 old servers since the only other choice is to go from 100 nanosecond DCE
4927 time and resort to the original setpathinfo level which takes the ancient
4928 DOS time format with 2 second granularity */
4930 CIFSSMBSetFileInfo(const int xid, struct cifsTconInfo *tcon,
4931 const FILE_BASIC_INFO *data, __u16 fid, __u32 pid_of_opener)
4933 struct smb_com_transaction2_sfi_req *pSMB = NULL;
4936 __u16 params, param_offset, offset, byte_count, count;
4938 cFYI(1, "Set Times (via SetFileInfo)");
4939 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
4944 pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
4945 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));
4948 pSMB->MaxSetupCount = 0;
4952 pSMB->Reserved2 = 0;
4953 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
4954 offset = param_offset + params;
4956 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
4958 count = sizeof(FILE_BASIC_INFO);
4959 pSMB->MaxParameterCount = cpu_to_le16(2);
4960 /* BB find max SMB PDU from sess */
4961 pSMB->MaxDataCount = cpu_to_le16(1000);
4962 pSMB->SetupCount = 1;
4963 pSMB->Reserved3 = 0;
4964 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
4965 byte_count = 3 /* pad */ + params + count;
4966 pSMB->DataCount = cpu_to_le16(count);
4967 pSMB->ParameterCount = cpu_to_le16(params);
4968 pSMB->TotalDataCount = pSMB->DataCount;
4969 pSMB->TotalParameterCount = pSMB->ParameterCount;
4970 pSMB->ParameterOffset = cpu_to_le16(param_offset);
4971 pSMB->DataOffset = cpu_to_le16(offset);
4973 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
4974 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO2);
4976 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO);
4977 pSMB->Reserved4 = 0;
4978 pSMB->hdr.smb_buf_length += byte_count;
4979 pSMB->ByteCount = cpu_to_le16(byte_count);
4980 memcpy(data_offset, data, sizeof(FILE_BASIC_INFO));
4981 rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0);
4983 cFYI(1, "Send error in Set Time (SetFileInfo) = %d", rc);
4985 /* Note: On -EAGAIN error only caller can retry on handle based calls
4986 since file handle passed in no longer valid */
4992 CIFSSMBSetFileDisposition(const int xid, struct cifsTconInfo *tcon,
4993 bool delete_file, __u16 fid, __u32 pid_of_opener)
4995 struct smb_com_transaction2_sfi_req *pSMB = NULL;
4998 __u16 params, param_offset, offset, byte_count, count;
5000 cFYI(1, "Set File Disposition (via SetFileInfo)");
5001 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
5006 pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
5007 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));
5010 pSMB->MaxSetupCount = 0;
5014 pSMB->Reserved2 = 0;
5015 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
5016 offset = param_offset + params;
5018 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
5021 pSMB->MaxParameterCount = cpu_to_le16(2);
5022 /* BB find max SMB PDU from sess */
5023 pSMB->MaxDataCount = cpu_to_le16(1000);
5024 pSMB->SetupCount = 1;
5025 pSMB->Reserved3 = 0;
5026 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
5027 byte_count = 3 /* pad */ + params + count;
5028 pSMB->DataCount = cpu_to_le16(count);
5029 pSMB->ParameterCount = cpu_to_le16(params);
5030 pSMB->TotalDataCount = pSMB->DataCount;
5031 pSMB->TotalParameterCount = pSMB->ParameterCount;
5032 pSMB->ParameterOffset = cpu_to_le16(param_offset);
5033 pSMB->DataOffset = cpu_to_le16(offset);
5035 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_DISPOSITION_INFO);
5036 pSMB->Reserved4 = 0;
5037 pSMB->hdr.smb_buf_length += byte_count;
5038 pSMB->ByteCount = cpu_to_le16(byte_count);
5039 *data_offset = delete_file ? 1 : 0;
5040 rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0);
5042 cFYI(1, "Send error in SetFileDisposition = %d", rc);
5048 CIFSSMBSetPathInfo(const int xid, struct cifsTconInfo *tcon,
5049 const char *fileName, const FILE_BASIC_INFO *data,
5050 const struct nls_table *nls_codepage, int remap)
5052 TRANSACTION2_SPI_REQ *pSMB = NULL;
5053 TRANSACTION2_SPI_RSP *pSMBr = NULL;
5056 int bytes_returned = 0;
5058 __u16 params, param_offset, offset, byte_count, count;
5060 cFYI(1, "In SetTimes");
5063 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5068 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5070 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
5071 PATH_MAX, nls_codepage, remap);
5072 name_len++; /* trailing null */
5074 } else { /* BB improve the check for buffer overruns BB */
5075 name_len = strnlen(fileName, PATH_MAX);
5076 name_len++; /* trailing null */
5077 strncpy(pSMB->FileName, fileName, name_len);
5080 params = 6 + name_len;
5081 count = sizeof(FILE_BASIC_INFO);
5082 pSMB->MaxParameterCount = cpu_to_le16(2);
5083 /* BB find max SMB PDU from sess structure BB */
5084 pSMB->MaxDataCount = cpu_to_le16(1000);
5085 pSMB->MaxSetupCount = 0;
5089 pSMB->Reserved2 = 0;
5090 param_offset = offsetof(struct smb_com_transaction2_spi_req,
5091 InformationLevel) - 4;
5092 offset = param_offset + params;
5093 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
5094 pSMB->ParameterOffset = cpu_to_le16(param_offset);
5095 pSMB->DataOffset = cpu_to_le16(offset);
5096 pSMB->SetupCount = 1;
5097 pSMB->Reserved3 = 0;
5098 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
5099 byte_count = 3 /* pad */ + params + count;
5101 pSMB->DataCount = cpu_to_le16(count);
5102 pSMB->ParameterCount = cpu_to_le16(params);
5103 pSMB->TotalDataCount = pSMB->DataCount;
5104 pSMB->TotalParameterCount = pSMB->ParameterCount;
5105 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
5106 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO2);
5108 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO);
5109 pSMB->Reserved4 = 0;
5110 pSMB->hdr.smb_buf_length += byte_count;
5111 memcpy(data_offset, data, sizeof(FILE_BASIC_INFO));
5112 pSMB->ByteCount = cpu_to_le16(byte_count);
5113 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5114 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5116 cFYI(1, "SetPathInfo (times) returned %d", rc);
5118 cifs_buf_release(pSMB);
5126 /* Can not be used to set time stamps yet (due to old DOS time format) */
5127 /* Can be used to set attributes */
5128 #if 0 /* Possibly not needed - since it turns out that strangely NT4 has a bug
5129 handling it anyway and NT4 was what we thought it would be needed for
5130 Do not delete it until we prove whether needed for Win9x though */
5132 CIFSSMBSetAttrLegacy(int xid, struct cifsTconInfo *tcon, char *fileName,
5133 __u16 dos_attrs, const struct nls_table *nls_codepage)
5135 SETATTR_REQ *pSMB = NULL;
5136 SETATTR_RSP *pSMBr = NULL;
5141 cFYI(1, "In SetAttrLegacy");
5144 rc = smb_init(SMB_COM_SETATTR, 8, tcon, (void **) &pSMB,
5149 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5151 ConvertToUCS((__le16 *) pSMB->fileName, fileName,
5152 PATH_MAX, nls_codepage);
5153 name_len++; /* trailing null */
5155 } else { /* BB improve the check for buffer overruns BB */
5156 name_len = strnlen(fileName, PATH_MAX);
5157 name_len++; /* trailing null */
5158 strncpy(pSMB->fileName, fileName, name_len);
5160 pSMB->attr = cpu_to_le16(dos_attrs);
5161 pSMB->BufferFormat = 0x04;
5162 pSMB->hdr.smb_buf_length += name_len + 1;
5163 pSMB->ByteCount = cpu_to_le16(name_len + 1);
5164 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5165 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5167 cFYI(1, "Error in LegacySetAttr = %d", rc);
5169 cifs_buf_release(pSMB);
5172 goto SetAttrLgcyRetry;
5176 #endif /* temporarily unneeded SetAttr legacy function */
5179 cifs_fill_unix_set_info(FILE_UNIX_BASIC_INFO *data_offset,
5180 const struct cifs_unix_set_info_args *args)
5182 u64 mode = args->mode;
5185 * Samba server ignores set of file size to zero due to bugs in some
5186 * older clients, but we should be precise - we use SetFileSize to
5187 * set file size and do not want to truncate file size to zero
5188 * accidently as happened on one Samba server beta by putting
5189 * zero instead of -1 here
5191 data_offset->EndOfFile = cpu_to_le64(NO_CHANGE_64);
5192 data_offset->NumOfBytes = cpu_to_le64(NO_CHANGE_64);
5193 data_offset->LastStatusChange = cpu_to_le64(args->ctime);
5194 data_offset->LastAccessTime = cpu_to_le64(args->atime);
5195 data_offset->LastModificationTime = cpu_to_le64(args->mtime);
5196 data_offset->Uid = cpu_to_le64(args->uid);
5197 data_offset->Gid = cpu_to_le64(args->gid);
5198 /* better to leave device as zero when it is */
5199 data_offset->DevMajor = cpu_to_le64(MAJOR(args->device));
5200 data_offset->DevMinor = cpu_to_le64(MINOR(args->device));
5201 data_offset->Permissions = cpu_to_le64(mode);
5204 data_offset->Type = cpu_to_le32(UNIX_FILE);
5205 else if (S_ISDIR(mode))
5206 data_offset->Type = cpu_to_le32(UNIX_DIR);
5207 else if (S_ISLNK(mode))
5208 data_offset->Type = cpu_to_le32(UNIX_SYMLINK);
5209 else if (S_ISCHR(mode))
5210 data_offset->Type = cpu_to_le32(UNIX_CHARDEV);
5211 else if (S_ISBLK(mode))
5212 data_offset->Type = cpu_to_le32(UNIX_BLOCKDEV);
5213 else if (S_ISFIFO(mode))
5214 data_offset->Type = cpu_to_le32(UNIX_FIFO);
5215 else if (S_ISSOCK(mode))
5216 data_offset->Type = cpu_to_le32(UNIX_SOCKET);
5220 CIFSSMBUnixSetFileInfo(const int xid, struct cifsTconInfo *tcon,
5221 const struct cifs_unix_set_info_args *args,
5222 u16 fid, u32 pid_of_opener)
5224 struct smb_com_transaction2_sfi_req *pSMB = NULL;
5225 FILE_UNIX_BASIC_INFO *data_offset;
5227 u16 params, param_offset, offset, byte_count, count;
5229 cFYI(1, "Set Unix Info (via SetFileInfo)");
5230 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
5235 pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
5236 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));
5239 pSMB->MaxSetupCount = 0;
5243 pSMB->Reserved2 = 0;
5244 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
5245 offset = param_offset + params;
5247 data_offset = (FILE_UNIX_BASIC_INFO *)
5248 ((char *)(&pSMB->hdr.Protocol) + offset);
5249 count = sizeof(FILE_UNIX_BASIC_INFO);
5251 pSMB->MaxParameterCount = cpu_to_le16(2);
5252 /* BB find max SMB PDU from sess */
5253 pSMB->MaxDataCount = cpu_to_le16(1000);
5254 pSMB->SetupCount = 1;
5255 pSMB->Reserved3 = 0;
5256 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
5257 byte_count = 3 /* pad */ + params + count;
5258 pSMB->DataCount = cpu_to_le16(count);
5259 pSMB->ParameterCount = cpu_to_le16(params);
5260 pSMB->TotalDataCount = pSMB->DataCount;
5261 pSMB->TotalParameterCount = pSMB->ParameterCount;
5262 pSMB->ParameterOffset = cpu_to_le16(param_offset);
5263 pSMB->DataOffset = cpu_to_le16(offset);
5265 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_BASIC);
5266 pSMB->Reserved4 = 0;
5267 pSMB->hdr.smb_buf_length += byte_count;
5268 pSMB->ByteCount = cpu_to_le16(byte_count);
5270 cifs_fill_unix_set_info(data_offset, args);
5272 rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0);
5274 cFYI(1, "Send error in Set Time (SetFileInfo) = %d", rc);
5276 /* Note: On -EAGAIN error only caller can retry on handle based calls
5277 since file handle passed in no longer valid */
5283 CIFSSMBUnixSetPathInfo(const int xid, struct cifsTconInfo *tcon, char *fileName,
5284 const struct cifs_unix_set_info_args *args,
5285 const struct nls_table *nls_codepage, int remap)
5287 TRANSACTION2_SPI_REQ *pSMB = NULL;
5288 TRANSACTION2_SPI_RSP *pSMBr = NULL;
5291 int bytes_returned = 0;
5292 FILE_UNIX_BASIC_INFO *data_offset;
5293 __u16 params, param_offset, offset, count, byte_count;
5295 cFYI(1, "In SetUID/GID/Mode");
5297 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5302 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5304 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
5305 PATH_MAX, nls_codepage, remap);
5306 name_len++; /* trailing null */
5308 } else { /* BB improve the check for buffer overruns BB */
5309 name_len = strnlen(fileName, PATH_MAX);
5310 name_len++; /* trailing null */
5311 strncpy(pSMB->FileName, fileName, name_len);
5314 params = 6 + name_len;
5315 count = sizeof(FILE_UNIX_BASIC_INFO);
5316 pSMB->MaxParameterCount = cpu_to_le16(2);
5317 /* BB find max SMB PDU from sess structure BB */
5318 pSMB->MaxDataCount = cpu_to_le16(1000);
5319 pSMB->MaxSetupCount = 0;
5323 pSMB->Reserved2 = 0;
5324 param_offset = offsetof(struct smb_com_transaction2_spi_req,
5325 InformationLevel) - 4;
5326 offset = param_offset + params;
5328 (FILE_UNIX_BASIC_INFO *) ((char *) &pSMB->hdr.Protocol +
5330 memset(data_offset, 0, count);
5331 pSMB->DataOffset = cpu_to_le16(offset);
5332 pSMB->ParameterOffset = cpu_to_le16(param_offset);
5333 pSMB->SetupCount = 1;
5334 pSMB->Reserved3 = 0;
5335 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
5336 byte_count = 3 /* pad */ + params + count;
5337 pSMB->ParameterCount = cpu_to_le16(params);
5338 pSMB->DataCount = cpu_to_le16(count);
5339 pSMB->TotalParameterCount = pSMB->ParameterCount;
5340 pSMB->TotalDataCount = pSMB->DataCount;
5341 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_BASIC);
5342 pSMB->Reserved4 = 0;
5343 pSMB->hdr.smb_buf_length += byte_count;
5345 cifs_fill_unix_set_info(data_offset, args);
5347 pSMB->ByteCount = cpu_to_le16(byte_count);
5348 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5349 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5351 cFYI(1, "SetPathInfo (perms) returned %d", rc);
5353 cifs_buf_release(pSMB);
5359 int CIFSSMBNotify(const int xid, struct cifsTconInfo *tcon,
5360 const int notify_subdirs, const __u16 netfid,
5361 __u32 filter, struct file *pfile, int multishot,
5362 const struct nls_table *nls_codepage)
5365 struct smb_com_transaction_change_notify_req *pSMB = NULL;
5366 struct smb_com_ntransaction_change_notify_rsp *pSMBr = NULL;
5367 struct dir_notify_req *dnotify_req;
5370 cFYI(1, "In CIFSSMBNotify for file handle %d", (int)netfid);
5371 rc = smb_init(SMB_COM_NT_TRANSACT, 23, tcon, (void **) &pSMB,
5376 pSMB->TotalParameterCount = 0 ;
5377 pSMB->TotalDataCount = 0;
5378 pSMB->MaxParameterCount = cpu_to_le32(2);
5379 /* BB find exact data count max from sess structure BB */
5380 pSMB->MaxDataCount = 0; /* same in little endian or be */
5381 /* BB VERIFY verify which is correct for above BB */
5382 pSMB->MaxDataCount = cpu_to_le32((tcon->ses->server->maxBuf -
5383 MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
5385 pSMB->MaxSetupCount = 4;
5387 pSMB->ParameterOffset = 0;
5388 pSMB->DataCount = 0;
5389 pSMB->DataOffset = 0;
5390 pSMB->SetupCount = 4; /* single byte does not need le conversion */
5391 pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_NOTIFY_CHANGE);
5392 pSMB->ParameterCount = pSMB->TotalParameterCount;
5394 pSMB->WatchTree = 1; /* one byte - no le conversion needed */
5395 pSMB->Reserved2 = 0;
5396 pSMB->CompletionFilter = cpu_to_le32(filter);
5397 pSMB->Fid = netfid; /* file handle always le */
5398 pSMB->ByteCount = 0;
5400 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5401 (struct smb_hdr *)pSMBr, &bytes_returned,
5404 cFYI(1, "Error in Notify = %d", rc);
5406 /* Add file to outstanding requests */
5407 /* BB change to kmem cache alloc */
5408 dnotify_req = kmalloc(
5409 sizeof(struct dir_notify_req),
5412 dnotify_req->Pid = pSMB->hdr.Pid;
5413 dnotify_req->PidHigh = pSMB->hdr.PidHigh;
5414 dnotify_req->Mid = pSMB->hdr.Mid;
5415 dnotify_req->Tid = pSMB->hdr.Tid;
5416 dnotify_req->Uid = pSMB->hdr.Uid;
5417 dnotify_req->netfid = netfid;
5418 dnotify_req->pfile = pfile;
5419 dnotify_req->filter = filter;
5420 dnotify_req->multishot = multishot;
5421 spin_lock(&GlobalMid_Lock);
5422 list_add_tail(&dnotify_req->lhead,
5423 &GlobalDnotifyReqList);
5424 spin_unlock(&GlobalMid_Lock);
5428 cifs_buf_release(pSMB);
5432 #ifdef CONFIG_CIFS_XATTR
5434 * Do a path-based QUERY_ALL_EAS call and parse the result. This is a common
5435 * function used by listxattr and getxattr type calls. When ea_name is set,
5436 * it looks for that attribute name and stuffs that value into the EAData
5437 * buffer. When ea_name is NULL, it stuffs a list of attribute names into the
5438 * buffer. In both cases, the return value is either the length of the
5439 * resulting data or a negative error code. If EAData is a NULL pointer then
5440 * the data isn't copied to it, but the length is returned.
5443 CIFSSMBQAllEAs(const int xid, struct cifsTconInfo *tcon,
5444 const unsigned char *searchName, const unsigned char *ea_name,
5445 char *EAData, size_t buf_size,
5446 const struct nls_table *nls_codepage, int remap)
5448 /* BB assumes one setup word */
5449 TRANSACTION2_QPI_REQ *pSMB = NULL;
5450 TRANSACTION2_QPI_RSP *pSMBr = NULL;
5454 struct fealist *ea_response_data;
5455 struct fea *temp_fea;
5458 __u16 params, byte_count, data_offset;
5460 cFYI(1, "In Query All EAs path %s", searchName);
5462 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5467 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5469 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
5470 PATH_MAX, nls_codepage, remap);
5471 list_len++; /* trailing null */
5473 } else { /* BB improve the check for buffer overruns BB */
5474 list_len = strnlen(searchName, PATH_MAX);
5475 list_len++; /* trailing null */
5476 strncpy(pSMB->FileName, searchName, list_len);
5479 params = 2 /* level */ + 4 /* reserved */ + list_len /* includes NUL */;
5480 pSMB->TotalDataCount = 0;
5481 pSMB->MaxParameterCount = cpu_to_le16(2);
5482 /* BB find exact max SMB PDU from sess structure BB */
5483 pSMB->MaxDataCount = cpu_to_le16(CIFSMaxBufSize);
5484 pSMB->MaxSetupCount = 0;
5488 pSMB->Reserved2 = 0;
5489 pSMB->ParameterOffset = cpu_to_le16(offsetof(
5490 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
5491 pSMB->DataCount = 0;
5492 pSMB->DataOffset = 0;
5493 pSMB->SetupCount = 1;
5494 pSMB->Reserved3 = 0;
5495 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
5496 byte_count = params + 1 /* pad */ ;
5497 pSMB->TotalParameterCount = cpu_to_le16(params);
5498 pSMB->ParameterCount = pSMB->TotalParameterCount;
5499 pSMB->InformationLevel = cpu_to_le16(SMB_INFO_QUERY_ALL_EAS);
5500 pSMB->Reserved4 = 0;
5501 pSMB->hdr.smb_buf_length += byte_count;
5502 pSMB->ByteCount = cpu_to_le16(byte_count);
5504 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5505 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5507 cFYI(1, "Send error in QueryAllEAs = %d", rc);
5512 /* BB also check enough total bytes returned */
5513 /* BB we need to improve the validity checking
5514 of these trans2 responses */
5516 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
5517 if (rc || (pSMBr->ByteCount < 4)) {
5518 rc = -EIO; /* bad smb */
5522 /* check that length of list is not more than bcc */
5523 /* check that each entry does not go beyond length
5525 /* check that each element of each entry does not
5526 go beyond end of list */
5527 /* validate_trans2_offsets() */
5528 /* BB check if start of smb + data_offset > &bcc+ bcc */
5530 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
5531 ea_response_data = (struct fealist *)
5532 (((char *) &pSMBr->hdr.Protocol) + data_offset);
5534 list_len = le32_to_cpu(ea_response_data->list_len);
5535 cFYI(1, "ea length %d", list_len);
5536 if (list_len <= 8) {
5537 cFYI(1, "empty EA list returned from server");
5541 /* make sure list_len doesn't go past end of SMB */
5542 end_of_smb = (char *)pByteArea(&pSMBr->hdr) + BCC(&pSMBr->hdr);
5543 if ((char *)ea_response_data + list_len > end_of_smb) {
5544 cFYI(1, "EA list appears to go beyond SMB");
5549 /* account for ea list len */
5551 temp_fea = ea_response_data->list;
5552 temp_ptr = (char *)temp_fea;
5553 while (list_len > 0) {
5554 unsigned int name_len;
5559 /* make sure we can read name_len and value_len */
5561 cFYI(1, "EA entry goes beyond length of list");
5566 name_len = temp_fea->name_len;
5567 value_len = le16_to_cpu(temp_fea->value_len);
5568 list_len -= name_len + 1 + value_len;
5570 cFYI(1, "EA entry goes beyond length of list");
5576 if (strncmp(ea_name, temp_ptr, name_len) == 0) {
5577 temp_ptr += name_len + 1;
5581 if ((size_t)value_len > buf_size) {
5585 memcpy(EAData, temp_ptr, value_len);
5589 /* account for prefix user. and trailing null */
5590 rc += (5 + 1 + name_len);
5591 if (rc < (int) buf_size) {
5592 memcpy(EAData, "user.", 5);
5594 memcpy(EAData, temp_ptr, name_len);
5596 /* null terminate name */
5599 } else if (buf_size == 0) {
5600 /* skip copy - calc size only */
5602 /* stop before overrun buffer */
5607 temp_ptr += name_len + 1 + value_len;
5608 temp_fea = (struct fea *)temp_ptr;
5611 /* didn't find the named attribute */
5616 cifs_buf_release(pSMB);
5624 CIFSSMBSetEA(const int xid, struct cifsTconInfo *tcon, const char *fileName,
5625 const char *ea_name, const void *ea_value,
5626 const __u16 ea_value_len, const struct nls_table *nls_codepage,
5629 struct smb_com_transaction2_spi_req *pSMB = NULL;
5630 struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
5631 struct fealist *parm_data;
5634 int bytes_returned = 0;
5635 __u16 params, param_offset, byte_count, offset, count;
5637 cFYI(1, "In SetEA");
5639 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5644 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5646 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
5647 PATH_MAX, nls_codepage, remap);
5648 name_len++; /* trailing null */
5650 } else { /* BB improve the check for buffer overruns BB */
5651 name_len = strnlen(fileName, PATH_MAX);
5652 name_len++; /* trailing null */
5653 strncpy(pSMB->FileName, fileName, name_len);
5656 params = 6 + name_len;
5658 /* done calculating parms using name_len of file name,
5659 now use name_len to calculate length of ea name
5660 we are going to create in the inode xattrs */
5661 if (ea_name == NULL)
5664 name_len = strnlen(ea_name, 255);
5666 count = sizeof(*parm_data) + ea_value_len + name_len;
5667 pSMB->MaxParameterCount = cpu_to_le16(2);
5668 /* BB find max SMB PDU from sess */
5669 pSMB->MaxDataCount = cpu_to_le16(1000);
5670 pSMB->MaxSetupCount = 0;
5674 pSMB->Reserved2 = 0;
5675 param_offset = offsetof(struct smb_com_transaction2_spi_req,
5676 InformationLevel) - 4;
5677 offset = param_offset + params;
5678 pSMB->InformationLevel =
5679 cpu_to_le16(SMB_SET_FILE_EA);
5682 (struct fealist *) (((char *) &pSMB->hdr.Protocol) +
5684 pSMB->ParameterOffset = cpu_to_le16(param_offset);
5685 pSMB->DataOffset = cpu_to_le16(offset);
5686 pSMB->SetupCount = 1;
5687 pSMB->Reserved3 = 0;
5688 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
5689 byte_count = 3 /* pad */ + params + count;
5690 pSMB->DataCount = cpu_to_le16(count);
5691 parm_data->list_len = cpu_to_le32(count);
5692 parm_data->list[0].EA_flags = 0;
5693 /* we checked above that name len is less than 255 */
5694 parm_data->list[0].name_len = (__u8)name_len;
5695 /* EA names are always ASCII */
5697 strncpy(parm_data->list[0].name, ea_name, name_len);
5698 parm_data->list[0].name[name_len] = 0;
5699 parm_data->list[0].value_len = cpu_to_le16(ea_value_len);
5700 /* caller ensures that ea_value_len is less than 64K but
5701 we need to ensure that it fits within the smb */
5703 /*BB add length check to see if it would fit in
5704 negotiated SMB buffer size BB */
5705 /* if (ea_value_len > buffer_size - 512 (enough for header)) */
5707 memcpy(parm_data->list[0].name+name_len+1,
5708 ea_value, ea_value_len);
5710 pSMB->TotalDataCount = pSMB->DataCount;
5711 pSMB->ParameterCount = cpu_to_le16(params);
5712 pSMB->TotalParameterCount = pSMB->ParameterCount;
5713 pSMB->Reserved4 = 0;
5714 pSMB->hdr.smb_buf_length += byte_count;
5715 pSMB->ByteCount = cpu_to_le16(byte_count);
5716 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5717 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5719 cFYI(1, "SetPathInfo (EA) returned %d", rc);
5721 cifs_buf_release(pSMB);