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/posix_acl_xattr.h>
34 #include <asm/uaccess.h>
38 #include "cifsproto.h"
39 #include "cifs_unicode.h"
40 #include "cifs_debug.h"
42 #ifdef CONFIG_CIFS_POSIX
47 #ifdef CONFIG_CIFS_WEAK_PW_HASH
48 {LANMAN_PROT, "\2LM1.2X002"},
49 {LANMAN2_PROT, "\2LANMAN2.1"},
50 #endif /* weak password hashing for legacy clients */
51 {CIFS_PROT, "\2NT LM 0.12"},
52 {POSIX_PROT, "\2POSIX 2"},
60 #ifdef CONFIG_CIFS_WEAK_PW_HASH
61 {LANMAN_PROT, "\2LM1.2X002"},
62 {LANMAN2_PROT, "\2LANMAN2.1"},
63 #endif /* weak password hashing for legacy clients */
64 {CIFS_PROT, "\2NT LM 0.12"},
69 /* define the number of elements in the cifs dialect array */
70 #ifdef CONFIG_CIFS_POSIX
71 #ifdef CONFIG_CIFS_WEAK_PW_HASH
72 #define CIFS_NUM_PROT 4
74 #define CIFS_NUM_PROT 2
75 #endif /* CIFS_WEAK_PW_HASH */
77 #ifdef CONFIG_CIFS_WEAK_PW_HASH
78 #define CIFS_NUM_PROT 3
80 #define CIFS_NUM_PROT 1
81 #endif /* CONFIG_CIFS_WEAK_PW_HASH */
82 #endif /* CIFS_POSIX */
84 /* Mark as invalid, all open files on tree connections since they
85 were closed when session to server was lost */
86 static void mark_open_files_invalid(struct cifsTconInfo *pTcon)
88 struct cifsFileInfo *open_file = NULL;
89 struct list_head *tmp;
90 struct list_head *tmp1;
92 /* list all files open on tree connection and mark them invalid */
93 write_lock(&GlobalSMBSeslock);
94 list_for_each_safe(tmp, tmp1, &pTcon->openFileList) {
95 open_file = list_entry(tmp, struct cifsFileInfo, tlist);
96 open_file->invalidHandle = true;
97 open_file->oplock_break_cancelled = true;
99 write_unlock(&GlobalSMBSeslock);
100 /* BB Add call to invalidate_inodes(sb) for all superblocks mounted
104 /* reconnect the socket, tcon, and smb session if needed */
106 cifs_reconnect_tcon(struct cifsTconInfo *tcon, int smb_command)
109 struct cifsSesInfo *ses;
110 struct TCP_Server_Info *server;
111 struct nls_table *nls_codepage;
114 * SMBs NegProt, SessSetup, uLogoff do not have tcon yet so check for
115 * tcp and smb session status done differently for those three - in the
122 server = ses->server;
125 * only tree disconnect, open, and write, (and ulogoff which does not
126 * have tcon) are allowed as we start force umount
128 if (tcon->tidStatus == CifsExiting) {
129 if (smb_command != SMB_COM_WRITE_ANDX &&
130 smb_command != SMB_COM_OPEN_ANDX &&
131 smb_command != SMB_COM_TREE_DISCONNECT) {
132 cFYI(1, ("can not send cmd %d while umounting",
138 if (ses->status == CifsExiting)
142 * Give demultiplex thread up to 10 seconds to reconnect, should be
143 * greater than cifs socket timeout which is 7 seconds
145 while (server->tcpStatus == CifsNeedReconnect) {
146 wait_event_interruptible_timeout(server->response_q,
147 (server->tcpStatus == CifsGood), 10 * HZ);
149 /* is TCP session is reestablished now ?*/
150 if (server->tcpStatus != CifsNeedReconnect)
154 * on "soft" mounts we wait once. Hard mounts keep
155 * retrying until process is killed or server comes
158 if (!tcon->retry || ses->status == CifsExiting) {
159 cFYI(1, ("gave up waiting on reconnect in smb_init"));
164 if (!ses->need_reconnect && !tcon->need_reconnect)
167 nls_codepage = load_nls_default();
170 * need to prevent multiple threads trying to simultaneously
171 * reconnect the same SMB session
173 mutex_lock(&ses->session_mutex);
174 if (ses->need_reconnect)
175 rc = cifs_setup_session(0, ses, nls_codepage);
177 /* do we need to reconnect tcon? */
178 if (rc || !tcon->need_reconnect) {
179 mutex_unlock(&ses->session_mutex);
183 mark_open_files_invalid(tcon);
184 rc = CIFSTCon(0, ses, tcon->treeName, tcon, nls_codepage);
185 mutex_unlock(&ses->session_mutex);
186 cFYI(1, ("reconnect tcon rc = %d", rc));
192 * FIXME: check if wsize needs updated due to negotiated smb buffer
195 atomic_inc(&tconInfoReconnectCount);
197 /* tell server Unix caps we support */
198 if (ses->capabilities & CAP_UNIX)
199 reset_cifs_unix_caps(0, tcon, NULL, NULL);
202 * Removed call to reopen open files here. It is safer (and faster) to
203 * reopen files one at a time as needed in read and write.
205 * FIXME: what about file locks? don't we need to reclaim them ASAP?
210 * Check if handle based operation so we know whether we can continue
211 * or not without returning to caller to reset file handle
213 switch (smb_command) {
214 case SMB_COM_READ_ANDX:
215 case SMB_COM_WRITE_ANDX:
217 case SMB_COM_FIND_CLOSE2:
218 case SMB_COM_LOCKING_ANDX:
222 unload_nls(nls_codepage);
226 /* Allocate and return pointer to an SMB request buffer, and set basic
227 SMB information in the SMB header. If the return code is zero, this
228 function must have filled in request_buf pointer */
230 small_smb_init(int smb_command, int wct, struct cifsTconInfo *tcon,
235 rc = cifs_reconnect_tcon(tcon, smb_command);
239 *request_buf = cifs_small_buf_get();
240 if (*request_buf == NULL) {
241 /* BB should we add a retry in here if not a writepage? */
245 header_assemble((struct smb_hdr *) *request_buf, smb_command,
249 cifs_stats_inc(&tcon->num_smbs_sent);
255 small_smb_init_no_tc(const int smb_command, const int wct,
256 struct cifsSesInfo *ses, void **request_buf)
259 struct smb_hdr *buffer;
261 rc = small_smb_init(smb_command, wct, NULL, request_buf);
265 buffer = (struct smb_hdr *)*request_buf;
266 buffer->Mid = GetNextMid(ses->server);
267 if (ses->capabilities & CAP_UNICODE)
268 buffer->Flags2 |= SMBFLG2_UNICODE;
269 if (ses->capabilities & CAP_STATUS32)
270 buffer->Flags2 |= SMBFLG2_ERR_STATUS;
272 /* uid, tid can stay at zero as set in header assemble */
274 /* BB add support for turning on the signing when
275 this function is used after 1st of session setup requests */
280 /* If the return code is zero, this function must fill in request_buf pointer */
282 smb_init(int smb_command, int wct, struct cifsTconInfo *tcon,
283 void **request_buf /* returned */ ,
284 void **response_buf /* returned */ )
288 rc = cifs_reconnect_tcon(tcon, smb_command);
292 *request_buf = cifs_buf_get();
293 if (*request_buf == NULL) {
294 /* BB should we add a retry in here if not a writepage? */
297 /* Although the original thought was we needed the response buf for */
298 /* potential retries of smb operations it turns out we can determine */
299 /* from the mid flags when the request buffer can be resent without */
300 /* having to use a second distinct buffer for the response */
302 *response_buf = *request_buf;
304 header_assemble((struct smb_hdr *) *request_buf, smb_command, tcon,
308 cifs_stats_inc(&tcon->num_smbs_sent);
313 static int validate_t2(struct smb_t2_rsp *pSMB)
319 /* check for plausible wct, bcc and t2 data and parm sizes */
320 /* check for parm and data offset going beyond end of smb */
321 if (pSMB->hdr.WordCount >= 10) {
322 if ((le16_to_cpu(pSMB->t2_rsp.ParameterOffset) <= 1024) &&
323 (le16_to_cpu(pSMB->t2_rsp.DataOffset) <= 1024)) {
324 /* check that bcc is at least as big as parms + data */
325 /* check that bcc is less than negotiated smb buffer */
326 total_size = le16_to_cpu(pSMB->t2_rsp.ParameterCount);
327 if (total_size < 512) {
329 le16_to_cpu(pSMB->t2_rsp.DataCount);
330 /* BCC le converted in SendReceive */
331 pBCC = (pSMB->hdr.WordCount * 2) +
332 sizeof(struct smb_hdr) +
334 if ((total_size <= (*(u16 *)pBCC)) &&
336 CIFSMaxBufSize+MAX_CIFS_HDR_SIZE)) {
342 cifs_dump_mem("Invalid transact2 SMB: ", (char *)pSMB,
343 sizeof(struct smb_t2_rsp) + 16);
347 CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses)
350 NEGOTIATE_RSP *pSMBr;
354 struct TCP_Server_Info *server;
356 unsigned int secFlags;
360 server = ses->server;
365 rc = smb_init(SMB_COM_NEGOTIATE, 0, NULL /* no tcon yet */ ,
366 (void **) &pSMB, (void **) &pSMBr);
370 /* if any of auth flags (ie not sign or seal) are overriden use them */
371 if (ses->overrideSecFlg & (~(CIFSSEC_MUST_SIGN | CIFSSEC_MUST_SEAL)))
372 secFlags = ses->overrideSecFlg; /* BB FIXME fix sign flags? */
373 else /* if override flags set only sign/seal OR them with global auth */
374 secFlags = extended_security | ses->overrideSecFlg;
376 cFYI(1, ("secFlags 0x%x", secFlags));
378 pSMB->hdr.Mid = GetNextMid(server);
379 pSMB->hdr.Flags2 |= (SMBFLG2_UNICODE | SMBFLG2_ERR_STATUS);
381 if ((secFlags & CIFSSEC_MUST_KRB5) == CIFSSEC_MUST_KRB5)
382 pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC;
383 else if ((secFlags & CIFSSEC_AUTH_MASK) == CIFSSEC_MAY_KRB5) {
384 cFYI(1, ("Kerberos only mechanism, enable extended security"));
385 pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC;
387 #ifdef CONFIG_CIFS_EXPERIMENTAL
388 else if ((secFlags & CIFSSEC_MUST_NTLMSSP) == CIFSSEC_MUST_NTLMSSP)
389 pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC;
390 else if ((secFlags & CIFSSEC_AUTH_MASK) == CIFSSEC_MAY_NTLMSSP) {
391 cFYI(1, ("NTLMSSP only mechanism, enable extended security"));
392 pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC;
397 for (i = 0; i < CIFS_NUM_PROT; i++) {
398 strncpy(pSMB->DialectsArray+count, protocols[i].name, 16);
399 count += strlen(protocols[i].name) + 1;
400 /* null at end of source and target buffers anyway */
402 pSMB->hdr.smb_buf_length += count;
403 pSMB->ByteCount = cpu_to_le16(count);
405 rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB,
406 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
410 dialect = le16_to_cpu(pSMBr->DialectIndex);
411 cFYI(1, ("Dialect: %d", dialect));
412 /* Check wct = 1 error case */
413 if ((pSMBr->hdr.WordCount < 13) || (dialect == BAD_PROT)) {
414 /* core returns wct = 1, but we do not ask for core - otherwise
415 small wct just comes when dialect index is -1 indicating we
416 could not negotiate a common dialect */
419 #ifdef CONFIG_CIFS_WEAK_PW_HASH
420 } else if ((pSMBr->hdr.WordCount == 13)
421 && ((dialect == LANMAN_PROT)
422 || (dialect == LANMAN2_PROT))) {
424 struct lanman_neg_rsp *rsp = (struct lanman_neg_rsp *)pSMBr;
426 if ((secFlags & CIFSSEC_MAY_LANMAN) ||
427 (secFlags & CIFSSEC_MAY_PLNTXT))
428 server->secType = LANMAN;
430 cERROR(1, ("mount failed weak security disabled"
431 " in /proc/fs/cifs/SecurityFlags"));
435 server->secMode = (__u8)le16_to_cpu(rsp->SecurityMode);
436 server->maxReq = le16_to_cpu(rsp->MaxMpxCount);
437 server->maxBuf = min((__u32)le16_to_cpu(rsp->MaxBufSize),
438 (__u32)CIFSMaxBufSize + MAX_CIFS_HDR_SIZE);
439 server->max_vcs = le16_to_cpu(rsp->MaxNumberVcs);
440 GETU32(server->sessid) = le32_to_cpu(rsp->SessionKey);
441 /* even though we do not use raw we might as well set this
442 accurately, in case we ever find a need for it */
443 if ((le16_to_cpu(rsp->RawMode) & RAW_ENABLE) == RAW_ENABLE) {
444 server->max_rw = 0xFF00;
445 server->capabilities = CAP_MPX_MODE | CAP_RAW_MODE;
447 server->max_rw = 0;/* do not need to use raw anyway */
448 server->capabilities = CAP_MPX_MODE;
450 tmp = (__s16)le16_to_cpu(rsp->ServerTimeZone);
452 /* OS/2 often does not set timezone therefore
453 * we must use server time to calc time zone.
454 * Could deviate slightly from the right zone.
455 * Smallest defined timezone difference is 15 minutes
456 * (i.e. Nepal). Rounding up/down is done to match
459 int val, seconds, remain, result;
460 struct timespec ts, utc;
462 ts = cnvrtDosUnixTm(rsp->SrvTime.Date,
463 rsp->SrvTime.Time, 0);
464 cFYI(1, ("SrvTime %d sec since 1970 (utc: %d) diff: %d",
465 (int)ts.tv_sec, (int)utc.tv_sec,
466 (int)(utc.tv_sec - ts.tv_sec)));
467 val = (int)(utc.tv_sec - ts.tv_sec);
469 result = (seconds / MIN_TZ_ADJ) * MIN_TZ_ADJ;
470 remain = seconds % MIN_TZ_ADJ;
471 if (remain >= (MIN_TZ_ADJ / 2))
472 result += MIN_TZ_ADJ;
475 server->timeAdj = result;
477 server->timeAdj = (int)tmp;
478 server->timeAdj *= 60; /* also in seconds */
480 cFYI(1, ("server->timeAdj: %d seconds", server->timeAdj));
483 /* BB get server time for time conversions and add
484 code to use it and timezone since this is not UTC */
486 if (rsp->EncryptionKeyLength ==
487 cpu_to_le16(CIFS_CRYPTO_KEY_SIZE)) {
488 memcpy(server->cryptKey, rsp->EncryptionKey,
489 CIFS_CRYPTO_KEY_SIZE);
490 } else if (server->secMode & SECMODE_PW_ENCRYPT) {
491 rc = -EIO; /* need cryptkey unless plain text */
495 cFYI(1, ("LANMAN negotiated"));
496 /* we will not end up setting signing flags - as no signing
497 was in LANMAN and server did not return the flags on */
499 #else /* weak security disabled */
500 } else if (pSMBr->hdr.WordCount == 13) {
501 cERROR(1, ("mount failed, cifs module not built "
502 "with CIFS_WEAK_PW_HASH support"));
504 #endif /* WEAK_PW_HASH */
506 } else if (pSMBr->hdr.WordCount != 17) {
511 /* else wct == 17 NTLM */
512 server->secMode = pSMBr->SecurityMode;
513 if ((server->secMode & SECMODE_USER) == 0)
514 cFYI(1, ("share mode security"));
516 if ((server->secMode & SECMODE_PW_ENCRYPT) == 0)
517 #ifdef CONFIG_CIFS_WEAK_PW_HASH
518 if ((secFlags & CIFSSEC_MAY_PLNTXT) == 0)
519 #endif /* CIFS_WEAK_PW_HASH */
520 cERROR(1, ("Server requests plain text password"
521 " but client support disabled"));
523 if ((secFlags & CIFSSEC_MUST_NTLMV2) == CIFSSEC_MUST_NTLMV2)
524 server->secType = NTLMv2;
525 else if (secFlags & CIFSSEC_MAY_NTLM)
526 server->secType = NTLM;
527 else if (secFlags & CIFSSEC_MAY_NTLMV2)
528 server->secType = NTLMv2;
529 else if (secFlags & CIFSSEC_MAY_KRB5)
530 server->secType = Kerberos;
531 else if (secFlags & CIFSSEC_MAY_NTLMSSP)
532 server->secType = RawNTLMSSP;
533 else if (secFlags & CIFSSEC_MAY_LANMAN)
534 server->secType = LANMAN;
535 /* #ifdef CONFIG_CIFS_EXPERIMENTAL
536 else if (secFlags & CIFSSEC_MAY_PLNTXT)
541 cERROR(1, ("Invalid security type"));
544 /* else ... any others ...? */
546 /* one byte, so no need to convert this or EncryptionKeyLen from
548 server->maxReq = le16_to_cpu(pSMBr->MaxMpxCount);
549 /* probably no need to store and check maxvcs */
550 server->maxBuf = min(le32_to_cpu(pSMBr->MaxBufferSize),
551 (__u32) CIFSMaxBufSize + MAX_CIFS_HDR_SIZE);
552 server->max_rw = le32_to_cpu(pSMBr->MaxRawSize);
553 cFYI(DBG2, ("Max buf = %d", ses->server->maxBuf));
554 GETU32(ses->server->sessid) = le32_to_cpu(pSMBr->SessionKey);
555 server->capabilities = le32_to_cpu(pSMBr->Capabilities);
556 server->timeAdj = (int)(__s16)le16_to_cpu(pSMBr->ServerTimeZone);
557 server->timeAdj *= 60;
558 if (pSMBr->EncryptionKeyLength == CIFS_CRYPTO_KEY_SIZE) {
559 memcpy(server->cryptKey, pSMBr->u.EncryptionKey,
560 CIFS_CRYPTO_KEY_SIZE);
561 } else if ((pSMBr->hdr.Flags2 & SMBFLG2_EXT_SEC)
562 && (pSMBr->EncryptionKeyLength == 0)) {
563 /* decode security blob */
564 } else if (server->secMode & SECMODE_PW_ENCRYPT) {
565 rc = -EIO; /* no crypt key only if plain text pwd */
569 /* BB might be helpful to save off the domain of server here */
571 if ((pSMBr->hdr.Flags2 & SMBFLG2_EXT_SEC) &&
572 (server->capabilities & CAP_EXTENDED_SECURITY)) {
573 count = pSMBr->ByteCount;
578 read_lock(&cifs_tcp_ses_lock);
579 if (server->srv_count > 1) {
580 read_unlock(&cifs_tcp_ses_lock);
581 if (memcmp(server->server_GUID,
582 pSMBr->u.extended_response.
584 cFYI(1, ("server UID changed"));
585 memcpy(server->server_GUID,
586 pSMBr->u.extended_response.GUID,
590 read_unlock(&cifs_tcp_ses_lock);
591 memcpy(server->server_GUID,
592 pSMBr->u.extended_response.GUID, 16);
596 server->secType = RawNTLMSSP;
598 rc = decode_negTokenInit(pSMBr->u.extended_response.
608 server->capabilities &= ~CAP_EXTENDED_SECURITY;
610 #ifdef CONFIG_CIFS_WEAK_PW_HASH
613 if ((secFlags & CIFSSEC_MAY_SIGN) == 0) {
614 /* MUST_SIGN already includes the MAY_SIGN FLAG
615 so if this is zero it means that signing is disabled */
616 cFYI(1, ("Signing disabled"));
617 if (server->secMode & SECMODE_SIGN_REQUIRED) {
618 cERROR(1, ("Server requires "
619 "packet signing to be enabled in "
620 "/proc/fs/cifs/SecurityFlags."));
624 ~(SECMODE_SIGN_ENABLED | SECMODE_SIGN_REQUIRED);
625 } else if ((secFlags & CIFSSEC_MUST_SIGN) == CIFSSEC_MUST_SIGN) {
626 /* signing required */
627 cFYI(1, ("Must sign - secFlags 0x%x", secFlags));
628 if ((server->secMode &
629 (SECMODE_SIGN_ENABLED | SECMODE_SIGN_REQUIRED)) == 0) {
631 ("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 == cpu_to_le16(CIFS_UNLCK))
1814 pLockData->fl_type = F_UNLCK;
1819 cifs_small_buf_release(pSMB);
1821 if (resp_buf_type == CIFS_SMALL_BUFFER)
1822 cifs_small_buf_release(iov[0].iov_base);
1823 else if (resp_buf_type == CIFS_LARGE_BUFFER)
1824 cifs_buf_release(iov[0].iov_base);
1826 /* Note: On -EAGAIN error only caller can retry on handle based calls
1827 since file handle passed in no longer valid */
1834 CIFSSMBClose(const int xid, struct cifsTconInfo *tcon, int smb_file_id)
1837 CLOSE_REQ *pSMB = NULL;
1838 cFYI(1, ("In CIFSSMBClose"));
1840 /* do not retry on dead session on close */
1841 rc = small_smb_init(SMB_COM_CLOSE, 3, tcon, (void **) &pSMB);
1847 pSMB->FileID = (__u16) smb_file_id;
1848 pSMB->LastWriteTime = 0xFFFFFFFF;
1849 pSMB->ByteCount = 0;
1850 rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0);
1851 cifs_stats_inc(&tcon->num_closes);
1854 /* EINTR is expected when user ctl-c to kill app */
1855 cERROR(1, ("Send error in Close = %d", rc));
1859 /* Since session is dead, file will be closed on server already */
1867 CIFSSMBFlush(const int xid, struct cifsTconInfo *tcon, int smb_file_id)
1870 FLUSH_REQ *pSMB = NULL;
1871 cFYI(1, ("In CIFSSMBFlush"));
1873 rc = small_smb_init(SMB_COM_FLUSH, 1, tcon, (void **) &pSMB);
1877 pSMB->FileID = (__u16) smb_file_id;
1878 pSMB->ByteCount = 0;
1879 rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0);
1880 cifs_stats_inc(&tcon->num_flushes);
1882 cERROR(1, ("Send error in Flush = %d", rc));
1888 CIFSSMBRename(const int xid, struct cifsTconInfo *tcon,
1889 const char *fromName, const char *toName,
1890 const struct nls_table *nls_codepage, int remap)
1893 RENAME_REQ *pSMB = NULL;
1894 RENAME_RSP *pSMBr = NULL;
1896 int name_len, name_len2;
1899 cFYI(1, ("In CIFSSMBRename"));
1901 rc = smb_init(SMB_COM_RENAME, 1, tcon, (void **) &pSMB,
1906 pSMB->BufferFormat = 0x04;
1907 pSMB->SearchAttributes =
1908 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
1911 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1913 cifsConvertToUCS((__le16 *) pSMB->OldFileName, fromName,
1914 PATH_MAX, nls_codepage, remap);
1915 name_len++; /* trailing null */
1917 pSMB->OldFileName[name_len] = 0x04; /* pad */
1918 /* protocol requires ASCII signature byte on Unicode string */
1919 pSMB->OldFileName[name_len + 1] = 0x00;
1921 cifsConvertToUCS((__le16 *)&pSMB->OldFileName[name_len + 2],
1922 toName, PATH_MAX, nls_codepage, remap);
1923 name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
1924 name_len2 *= 2; /* convert to bytes */
1925 } else { /* BB improve the check for buffer overruns BB */
1926 name_len = strnlen(fromName, PATH_MAX);
1927 name_len++; /* trailing null */
1928 strncpy(pSMB->OldFileName, fromName, name_len);
1929 name_len2 = strnlen(toName, PATH_MAX);
1930 name_len2++; /* trailing null */
1931 pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */
1932 strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2);
1933 name_len2++; /* trailing null */
1934 name_len2++; /* signature byte */
1937 count = 1 /* 1st signature byte */ + name_len + name_len2;
1938 pSMB->hdr.smb_buf_length += count;
1939 pSMB->ByteCount = cpu_to_le16(count);
1941 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1942 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1943 cifs_stats_inc(&tcon->num_renames);
1945 cFYI(1, ("Send error in rename = %d", rc));
1947 cifs_buf_release(pSMB);
1955 int CIFSSMBRenameOpenFile(const int xid, struct cifsTconInfo *pTcon,
1956 int netfid, const char *target_name,
1957 const struct nls_table *nls_codepage, int remap)
1959 struct smb_com_transaction2_sfi_req *pSMB = NULL;
1960 struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
1961 struct set_file_rename *rename_info;
1963 char dummy_string[30];
1965 int bytes_returned = 0;
1967 __u16 params, param_offset, offset, count, byte_count;
1969 cFYI(1, ("Rename to File by handle"));
1970 rc = smb_init(SMB_COM_TRANSACTION2, 15, pTcon, (void **) &pSMB,
1976 pSMB->MaxSetupCount = 0;
1980 pSMB->Reserved2 = 0;
1981 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
1982 offset = param_offset + params;
1984 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
1985 rename_info = (struct set_file_rename *) data_offset;
1986 pSMB->MaxParameterCount = cpu_to_le16(2);
1987 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB from sess */
1988 pSMB->SetupCount = 1;
1989 pSMB->Reserved3 = 0;
1990 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
1991 byte_count = 3 /* pad */ + params;
1992 pSMB->ParameterCount = cpu_to_le16(params);
1993 pSMB->TotalParameterCount = pSMB->ParameterCount;
1994 pSMB->ParameterOffset = cpu_to_le16(param_offset);
1995 pSMB->DataOffset = cpu_to_le16(offset);
1996 /* construct random name ".cifs_tmp<inodenum><mid>" */
1997 rename_info->overwrite = cpu_to_le32(1);
1998 rename_info->root_fid = 0;
1999 /* unicode only call */
2000 if (target_name == NULL) {
2001 sprintf(dummy_string, "cifs%x", pSMB->hdr.Mid);
2002 len_of_str = cifsConvertToUCS((__le16 *)rename_info->target_name,
2003 dummy_string, 24, nls_codepage, remap);
2005 len_of_str = cifsConvertToUCS((__le16 *)rename_info->target_name,
2006 target_name, PATH_MAX, nls_codepage,
2009 rename_info->target_name_len = cpu_to_le32(2 * len_of_str);
2010 count = 12 /* sizeof(struct set_file_rename) */ + (2 * len_of_str);
2011 byte_count += count;
2012 pSMB->DataCount = cpu_to_le16(count);
2013 pSMB->TotalDataCount = pSMB->DataCount;
2015 pSMB->InformationLevel =
2016 cpu_to_le16(SMB_SET_FILE_RENAME_INFORMATION);
2017 pSMB->Reserved4 = 0;
2018 pSMB->hdr.smb_buf_length += byte_count;
2019 pSMB->ByteCount = cpu_to_le16(byte_count);
2020 rc = SendReceive(xid, pTcon->ses, (struct smb_hdr *) pSMB,
2021 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2022 cifs_stats_inc(&pTcon->num_t2renames);
2024 cFYI(1, ("Send error in Rename (by file handle) = %d", rc));
2026 cifs_buf_release(pSMB);
2028 /* Note: On -EAGAIN error only caller can retry on handle based calls
2029 since file handle passed in no longer valid */
2035 CIFSSMBCopy(const int xid, struct cifsTconInfo *tcon, const char *fromName,
2036 const __u16 target_tid, const char *toName, const int flags,
2037 const struct nls_table *nls_codepage, int remap)
2040 COPY_REQ *pSMB = NULL;
2041 COPY_RSP *pSMBr = NULL;
2043 int name_len, name_len2;
2046 cFYI(1, ("In CIFSSMBCopy"));
2048 rc = smb_init(SMB_COM_COPY, 1, tcon, (void **) &pSMB,
2053 pSMB->BufferFormat = 0x04;
2054 pSMB->Tid2 = target_tid;
2056 pSMB->Flags = cpu_to_le16(flags & COPY_TREE);
2058 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2059 name_len = cifsConvertToUCS((__le16 *) pSMB->OldFileName,
2060 fromName, PATH_MAX, nls_codepage,
2062 name_len++; /* trailing null */
2064 pSMB->OldFileName[name_len] = 0x04; /* pad */
2065 /* protocol requires ASCII signature byte on Unicode string */
2066 pSMB->OldFileName[name_len + 1] = 0x00;
2068 cifsConvertToUCS((__le16 *)&pSMB->OldFileName[name_len + 2],
2069 toName, PATH_MAX, nls_codepage, remap);
2070 name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
2071 name_len2 *= 2; /* convert to bytes */
2072 } else { /* BB improve the check for buffer overruns BB */
2073 name_len = strnlen(fromName, PATH_MAX);
2074 name_len++; /* trailing null */
2075 strncpy(pSMB->OldFileName, fromName, name_len);
2076 name_len2 = strnlen(toName, PATH_MAX);
2077 name_len2++; /* trailing null */
2078 pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */
2079 strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2);
2080 name_len2++; /* trailing null */
2081 name_len2++; /* signature byte */
2084 count = 1 /* 1st signature byte */ + name_len + name_len2;
2085 pSMB->hdr.smb_buf_length += count;
2086 pSMB->ByteCount = cpu_to_le16(count);
2088 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2089 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2091 cFYI(1, ("Send error in copy = %d with %d files copied",
2092 rc, le16_to_cpu(pSMBr->CopyCount)));
2094 cifs_buf_release(pSMB);
2103 CIFSUnixCreateSymLink(const int xid, struct cifsTconInfo *tcon,
2104 const char *fromName, const char *toName,
2105 const struct nls_table *nls_codepage)
2107 TRANSACTION2_SPI_REQ *pSMB = NULL;
2108 TRANSACTION2_SPI_RSP *pSMBr = NULL;
2111 int name_len_target;
2113 int bytes_returned = 0;
2114 __u16 params, param_offset, offset, byte_count;
2116 cFYI(1, ("In Symlink Unix style"));
2118 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2123 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2125 cifs_strtoUCS((__le16 *) pSMB->FileName, fromName, PATH_MAX
2126 /* find define for this maxpathcomponent */
2128 name_len++; /* trailing null */
2131 } else { /* BB improve the check for buffer overruns BB */
2132 name_len = strnlen(fromName, PATH_MAX);
2133 name_len++; /* trailing null */
2134 strncpy(pSMB->FileName, fromName, name_len);
2136 params = 6 + name_len;
2137 pSMB->MaxSetupCount = 0;
2141 pSMB->Reserved2 = 0;
2142 param_offset = offsetof(struct smb_com_transaction2_spi_req,
2143 InformationLevel) - 4;
2144 offset = param_offset + params;
2146 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
2147 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2149 cifs_strtoUCS((__le16 *) data_offset, toName, PATH_MAX
2150 /* find define for this maxpathcomponent */
2152 name_len_target++; /* trailing null */
2153 name_len_target *= 2;
2154 } else { /* BB improve the check for buffer overruns BB */
2155 name_len_target = strnlen(toName, PATH_MAX);
2156 name_len_target++; /* trailing null */
2157 strncpy(data_offset, toName, name_len_target);
2160 pSMB->MaxParameterCount = cpu_to_le16(2);
2161 /* BB find exact max on data count below from sess */
2162 pSMB->MaxDataCount = cpu_to_le16(1000);
2163 pSMB->SetupCount = 1;
2164 pSMB->Reserved3 = 0;
2165 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
2166 byte_count = 3 /* pad */ + params + name_len_target;
2167 pSMB->DataCount = cpu_to_le16(name_len_target);
2168 pSMB->ParameterCount = cpu_to_le16(params);
2169 pSMB->TotalDataCount = pSMB->DataCount;
2170 pSMB->TotalParameterCount = pSMB->ParameterCount;
2171 pSMB->ParameterOffset = cpu_to_le16(param_offset);
2172 pSMB->DataOffset = cpu_to_le16(offset);
2173 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_LINK);
2174 pSMB->Reserved4 = 0;
2175 pSMB->hdr.smb_buf_length += byte_count;
2176 pSMB->ByteCount = cpu_to_le16(byte_count);
2177 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2178 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2179 cifs_stats_inc(&tcon->num_symlinks);
2181 cFYI(1, ("Send error in SetPathInfo create symlink = %d", rc));
2183 cifs_buf_release(pSMB);
2186 goto createSymLinkRetry;
2192 CIFSUnixCreateHardLink(const int xid, struct cifsTconInfo *tcon,
2193 const char *fromName, const char *toName,
2194 const struct nls_table *nls_codepage, int remap)
2196 TRANSACTION2_SPI_REQ *pSMB = NULL;
2197 TRANSACTION2_SPI_RSP *pSMBr = NULL;
2200 int name_len_target;
2202 int bytes_returned = 0;
2203 __u16 params, param_offset, offset, byte_count;
2205 cFYI(1, ("In Create Hard link Unix style"));
2206 createHardLinkRetry:
2207 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2212 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2213 name_len = cifsConvertToUCS((__le16 *) pSMB->FileName, toName,
2214 PATH_MAX, nls_codepage, remap);
2215 name_len++; /* trailing null */
2218 } else { /* BB improve the check for buffer overruns BB */
2219 name_len = strnlen(toName, PATH_MAX);
2220 name_len++; /* trailing null */
2221 strncpy(pSMB->FileName, toName, name_len);
2223 params = 6 + name_len;
2224 pSMB->MaxSetupCount = 0;
2228 pSMB->Reserved2 = 0;
2229 param_offset = offsetof(struct smb_com_transaction2_spi_req,
2230 InformationLevel) - 4;
2231 offset = param_offset + params;
2233 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
2234 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2236 cifsConvertToUCS((__le16 *) data_offset, fromName, PATH_MAX,
2237 nls_codepage, remap);
2238 name_len_target++; /* trailing null */
2239 name_len_target *= 2;
2240 } else { /* BB improve the check for buffer overruns BB */
2241 name_len_target = strnlen(fromName, PATH_MAX);
2242 name_len_target++; /* trailing null */
2243 strncpy(data_offset, fromName, name_len_target);
2246 pSMB->MaxParameterCount = cpu_to_le16(2);
2247 /* BB find exact max on data count below from sess*/
2248 pSMB->MaxDataCount = cpu_to_le16(1000);
2249 pSMB->SetupCount = 1;
2250 pSMB->Reserved3 = 0;
2251 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
2252 byte_count = 3 /* pad */ + params + name_len_target;
2253 pSMB->ParameterCount = cpu_to_le16(params);
2254 pSMB->TotalParameterCount = pSMB->ParameterCount;
2255 pSMB->DataCount = cpu_to_le16(name_len_target);
2256 pSMB->TotalDataCount = pSMB->DataCount;
2257 pSMB->ParameterOffset = cpu_to_le16(param_offset);
2258 pSMB->DataOffset = cpu_to_le16(offset);
2259 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_HLINK);
2260 pSMB->Reserved4 = 0;
2261 pSMB->hdr.smb_buf_length += byte_count;
2262 pSMB->ByteCount = cpu_to_le16(byte_count);
2263 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2264 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2265 cifs_stats_inc(&tcon->num_hardlinks);
2267 cFYI(1, ("Send error in SetPathInfo (hard link) = %d", rc));
2269 cifs_buf_release(pSMB);
2271 goto createHardLinkRetry;
2277 CIFSCreateHardLink(const int xid, struct cifsTconInfo *tcon,
2278 const char *fromName, const char *toName,
2279 const struct nls_table *nls_codepage, int remap)
2282 NT_RENAME_REQ *pSMB = NULL;
2283 RENAME_RSP *pSMBr = NULL;
2285 int name_len, name_len2;
2288 cFYI(1, ("In CIFSCreateHardLink"));
2289 winCreateHardLinkRetry:
2291 rc = smb_init(SMB_COM_NT_RENAME, 4, tcon, (void **) &pSMB,
2296 pSMB->SearchAttributes =
2297 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
2299 pSMB->Flags = cpu_to_le16(CREATE_HARD_LINK);
2300 pSMB->ClusterCount = 0;
2302 pSMB->BufferFormat = 0x04;
2304 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2306 cifsConvertToUCS((__le16 *) pSMB->OldFileName, fromName,
2307 PATH_MAX, nls_codepage, remap);
2308 name_len++; /* trailing null */
2311 /* protocol specifies ASCII buffer format (0x04) for unicode */
2312 pSMB->OldFileName[name_len] = 0x04;
2313 pSMB->OldFileName[name_len + 1] = 0x00; /* pad */
2315 cifsConvertToUCS((__le16 *)&pSMB->OldFileName[name_len + 2],
2316 toName, PATH_MAX, nls_codepage, remap);
2317 name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
2318 name_len2 *= 2; /* convert to bytes */
2319 } else { /* BB improve the check for buffer overruns BB */
2320 name_len = strnlen(fromName, PATH_MAX);
2321 name_len++; /* trailing null */
2322 strncpy(pSMB->OldFileName, fromName, name_len);
2323 name_len2 = strnlen(toName, PATH_MAX);
2324 name_len2++; /* trailing null */
2325 pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */
2326 strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2);
2327 name_len2++; /* trailing null */
2328 name_len2++; /* signature byte */
2331 count = 1 /* string type byte */ + name_len + name_len2;
2332 pSMB->hdr.smb_buf_length += count;
2333 pSMB->ByteCount = cpu_to_le16(count);
2335 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2336 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2337 cifs_stats_inc(&tcon->num_hardlinks);
2339 cFYI(1, ("Send error in hard link (NT rename) = %d", rc));
2341 cifs_buf_release(pSMB);
2343 goto winCreateHardLinkRetry;
2349 CIFSSMBUnixQuerySymLink(const int xid, struct cifsTconInfo *tcon,
2350 const unsigned char *searchName, char **symlinkinfo,
2351 const struct nls_table *nls_codepage)
2353 /* SMB_QUERY_FILE_UNIX_LINK */
2354 TRANSACTION2_QPI_REQ *pSMB = NULL;
2355 TRANSACTION2_QPI_RSP *pSMBr = NULL;
2359 __u16 params, byte_count;
2362 cFYI(1, ("In QPathSymLinkInfo (Unix) for path %s", searchName));
2365 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2370 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2372 cifs_strtoUCS((__le16 *) pSMB->FileName, searchName,
2373 PATH_MAX, nls_codepage);
2374 name_len++; /* trailing null */
2376 } else { /* BB improve the check for buffer overruns BB */
2377 name_len = strnlen(searchName, PATH_MAX);
2378 name_len++; /* trailing null */
2379 strncpy(pSMB->FileName, searchName, name_len);
2382 params = 2 /* level */ + 4 /* rsrvd */ + name_len /* incl null */ ;
2383 pSMB->TotalDataCount = 0;
2384 pSMB->MaxParameterCount = cpu_to_le16(2);
2385 pSMB->MaxDataCount = cpu_to_le16(CIFSMaxBufSize);
2386 pSMB->MaxSetupCount = 0;
2390 pSMB->Reserved2 = 0;
2391 pSMB->ParameterOffset = cpu_to_le16(offsetof(
2392 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
2393 pSMB->DataCount = 0;
2394 pSMB->DataOffset = 0;
2395 pSMB->SetupCount = 1;
2396 pSMB->Reserved3 = 0;
2397 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
2398 byte_count = params + 1 /* pad */ ;
2399 pSMB->TotalParameterCount = cpu_to_le16(params);
2400 pSMB->ParameterCount = pSMB->TotalParameterCount;
2401 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_LINK);
2402 pSMB->Reserved4 = 0;
2403 pSMB->hdr.smb_buf_length += byte_count;
2404 pSMB->ByteCount = cpu_to_le16(byte_count);
2406 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2407 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2409 cFYI(1, ("Send error in QuerySymLinkInfo = %d", rc));
2411 /* decode response */
2413 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
2414 /* BB also check enough total bytes returned */
2415 if (rc || (pSMBr->ByteCount < 2))
2419 u16 count = le16_to_cpu(pSMBr->t2.DataCount);
2421 data_start = ((char *) &pSMBr->hdr.Protocol) +
2422 le16_to_cpu(pSMBr->t2.DataOffset);
2424 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
2429 /* BB FIXME investigate remapping reserved chars here */
2430 *symlinkinfo = cifs_strndup_from_ucs(data_start, count,
2431 is_unicode, nls_codepage);
2436 cifs_buf_release(pSMB);
2438 goto querySymLinkRetry;
2442 #ifdef CONFIG_CIFS_EXPERIMENTAL
2443 /* Initialize NT TRANSACT SMB into small smb request buffer.
2444 This assumes that all NT TRANSACTS that we init here have
2445 total parm and data under about 400 bytes (to fit in small cifs
2446 buffer size), which is the case so far, it easily fits. NB:
2447 Setup words themselves and ByteCount
2448 MaxSetupCount (size of returned setup area) and
2449 MaxParameterCount (returned parms size) must be set by caller */
2451 smb_init_nttransact(const __u16 sub_command, const int setup_count,
2452 const int parm_len, struct cifsTconInfo *tcon,
2457 struct smb_com_ntransact_req *pSMB;
2459 rc = small_smb_init(SMB_COM_NT_TRANSACT, 19 + setup_count, tcon,
2463 *ret_buf = (void *)pSMB;
2465 pSMB->TotalParameterCount = cpu_to_le32(parm_len);
2466 pSMB->TotalDataCount = 0;
2467 pSMB->MaxDataCount = cpu_to_le32((tcon->ses->server->maxBuf -
2468 MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
2469 pSMB->ParameterCount = pSMB->TotalParameterCount;
2470 pSMB->DataCount = pSMB->TotalDataCount;
2471 temp_offset = offsetof(struct smb_com_ntransact_req, Parms) +
2472 (setup_count * 2) - 4 /* for rfc1001 length itself */;
2473 pSMB->ParameterOffset = cpu_to_le32(temp_offset);
2474 pSMB->DataOffset = cpu_to_le32(temp_offset + parm_len);
2475 pSMB->SetupCount = setup_count; /* no need to le convert byte fields */
2476 pSMB->SubCommand = cpu_to_le16(sub_command);
2481 validate_ntransact(char *buf, char **ppparm, char **ppdata,
2482 __u32 *pparmlen, __u32 *pdatalen)
2485 __u32 data_count, data_offset, parm_count, parm_offset;
2486 struct smb_com_ntransact_rsp *pSMBr;
2494 pSMBr = (struct smb_com_ntransact_rsp *)buf;
2496 /* ByteCount was converted from little endian in SendReceive */
2497 end_of_smb = 2 /* sizeof byte count */ + pSMBr->ByteCount +
2498 (char *)&pSMBr->ByteCount;
2500 data_offset = le32_to_cpu(pSMBr->DataOffset);
2501 data_count = le32_to_cpu(pSMBr->DataCount);
2502 parm_offset = le32_to_cpu(pSMBr->ParameterOffset);
2503 parm_count = le32_to_cpu(pSMBr->ParameterCount);
2505 *ppparm = (char *)&pSMBr->hdr.Protocol + parm_offset;
2506 *ppdata = (char *)&pSMBr->hdr.Protocol + data_offset;
2508 /* should we also check that parm and data areas do not overlap? */
2509 if (*ppparm > end_of_smb) {
2510 cFYI(1, ("parms start after end of smb"));
2512 } else if (parm_count + *ppparm > end_of_smb) {
2513 cFYI(1, ("parm end after end of smb"));
2515 } else if (*ppdata > end_of_smb) {
2516 cFYI(1, ("data starts after end of smb"));
2518 } else if (data_count + *ppdata > end_of_smb) {
2519 cFYI(1, ("data %p + count %d (%p) ends after end of smb %p start %p",
2520 *ppdata, data_count, (data_count + *ppdata),
2521 end_of_smb, pSMBr));
2523 } else if (parm_count + data_count > pSMBr->ByteCount) {
2524 cFYI(1, ("parm count and data count larger than SMB"));
2527 *pdatalen = data_count;
2528 *pparmlen = parm_count;
2533 CIFSSMBQueryReparseLinkInfo(const int xid, struct cifsTconInfo *tcon,
2534 const unsigned char *searchName,
2535 char *symlinkinfo, const int buflen, __u16 fid,
2536 const struct nls_table *nls_codepage)
2540 struct smb_com_transaction_ioctl_req *pSMB;
2541 struct smb_com_transaction_ioctl_rsp *pSMBr;
2543 cFYI(1, ("In Windows reparse style QueryLink for path %s", searchName));
2544 rc = smb_init(SMB_COM_NT_TRANSACT, 23, tcon, (void **) &pSMB,
2549 pSMB->TotalParameterCount = 0 ;
2550 pSMB->TotalDataCount = 0;
2551 pSMB->MaxParameterCount = cpu_to_le32(2);
2552 /* BB find exact data count max from sess structure BB */
2553 pSMB->MaxDataCount = cpu_to_le32((tcon->ses->server->maxBuf -
2554 MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
2555 pSMB->MaxSetupCount = 4;
2557 pSMB->ParameterOffset = 0;
2558 pSMB->DataCount = 0;
2559 pSMB->DataOffset = 0;
2560 pSMB->SetupCount = 4;
2561 pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_IOCTL);
2562 pSMB->ParameterCount = pSMB->TotalParameterCount;
2563 pSMB->FunctionCode = cpu_to_le32(FSCTL_GET_REPARSE_POINT);
2564 pSMB->IsFsctl = 1; /* FSCTL */
2565 pSMB->IsRootFlag = 0;
2566 pSMB->Fid = fid; /* file handle always le */
2567 pSMB->ByteCount = 0;
2569 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2570 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2572 cFYI(1, ("Send error in QueryReparseLinkInfo = %d", rc));
2573 } else { /* decode response */
2574 __u32 data_offset = le32_to_cpu(pSMBr->DataOffset);
2575 __u32 data_count = le32_to_cpu(pSMBr->DataCount);
2576 if ((pSMBr->ByteCount < 2) || (data_offset > 512)) {
2577 /* BB also check enough total bytes returned */
2578 rc = -EIO; /* bad smb */
2581 if (data_count && (data_count < 2048)) {
2582 char *end_of_smb = 2 /* sizeof byte count */ +
2583 pSMBr->ByteCount + (char *)&pSMBr->ByteCount;
2585 struct reparse_data *reparse_buf =
2586 (struct reparse_data *)
2587 ((char *)&pSMBr->hdr.Protocol
2589 if ((char *)reparse_buf >= end_of_smb) {
2593 if ((reparse_buf->LinkNamesBuf +
2594 reparse_buf->TargetNameOffset +
2595 reparse_buf->TargetNameLen) > end_of_smb) {
2596 cFYI(1, ("reparse buf beyond SMB"));
2601 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
2602 cifs_from_ucs2(symlinkinfo, (__le16 *)
2603 (reparse_buf->LinkNamesBuf +
2604 reparse_buf->TargetNameOffset),
2606 reparse_buf->TargetNameLen,
2608 } else { /* ASCII names */
2609 strncpy(symlinkinfo,
2610 reparse_buf->LinkNamesBuf +
2611 reparse_buf->TargetNameOffset,
2612 min_t(const int, buflen,
2613 reparse_buf->TargetNameLen));
2617 cFYI(1, ("Invalid return data count on "
2618 "get reparse info ioctl"));
2620 symlinkinfo[buflen] = 0; /* just in case so the caller
2621 does not go off the end of the buffer */
2622 cFYI(1, ("readlink result - %s", symlinkinfo));
2626 cifs_buf_release(pSMB);
2628 /* Note: On -EAGAIN error only caller can retry on handle based calls
2629 since file handle passed in no longer valid */
2633 #endif /* CIFS_EXPERIMENTAL */
2635 #ifdef CONFIG_CIFS_POSIX
2637 /*Convert an Access Control Entry from wire format to local POSIX xattr format*/
2638 static void cifs_convert_ace(posix_acl_xattr_entry *ace,
2639 struct cifs_posix_ace *cifs_ace)
2641 /* u8 cifs fields do not need le conversion */
2642 ace->e_perm = cpu_to_le16(cifs_ace->cifs_e_perm);
2643 ace->e_tag = cpu_to_le16(cifs_ace->cifs_e_tag);
2644 ace->e_id = cpu_to_le32(le64_to_cpu(cifs_ace->cifs_uid));
2645 /* cFYI(1,("perm %d tag %d id %d",ace->e_perm,ace->e_tag,ace->e_id)); */
2650 /* Convert ACL from CIFS POSIX wire format to local Linux POSIX ACL xattr */
2651 static int cifs_copy_posix_acl(char *trgt, char *src, const int buflen,
2652 const int acl_type, const int size_of_data_area)
2657 struct cifs_posix_ace *pACE;
2658 struct cifs_posix_acl *cifs_acl = (struct cifs_posix_acl *)src;
2659 posix_acl_xattr_header *local_acl = (posix_acl_xattr_header *)trgt;
2661 if (le16_to_cpu(cifs_acl->version) != CIFS_ACL_VERSION)
2664 if (acl_type & ACL_TYPE_ACCESS) {
2665 count = le16_to_cpu(cifs_acl->access_entry_count);
2666 pACE = &cifs_acl->ace_array[0];
2667 size = sizeof(struct cifs_posix_acl);
2668 size += sizeof(struct cifs_posix_ace) * count;
2669 /* check if we would go beyond end of SMB */
2670 if (size_of_data_area < size) {
2671 cFYI(1, ("bad CIFS POSIX ACL size %d vs. %d",
2672 size_of_data_area, size));
2675 } else if (acl_type & ACL_TYPE_DEFAULT) {
2676 count = le16_to_cpu(cifs_acl->access_entry_count);
2677 size = sizeof(struct cifs_posix_acl);
2678 size += sizeof(struct cifs_posix_ace) * count;
2679 /* skip past access ACEs to get to default ACEs */
2680 pACE = &cifs_acl->ace_array[count];
2681 count = le16_to_cpu(cifs_acl->default_entry_count);
2682 size += sizeof(struct cifs_posix_ace) * count;
2683 /* check if we would go beyond end of SMB */
2684 if (size_of_data_area < size)
2691 size = posix_acl_xattr_size(count);
2692 if ((buflen == 0) || (local_acl == NULL)) {
2693 /* used to query ACL EA size */
2694 } else if (size > buflen) {
2696 } else /* buffer big enough */ {
2697 local_acl->a_version = cpu_to_le32(POSIX_ACL_XATTR_VERSION);
2698 for (i = 0; i < count ; i++) {
2699 cifs_convert_ace(&local_acl->a_entries[i], pACE);
2706 static __u16 convert_ace_to_cifs_ace(struct cifs_posix_ace *cifs_ace,
2707 const posix_acl_xattr_entry *local_ace)
2709 __u16 rc = 0; /* 0 = ACL converted ok */
2711 cifs_ace->cifs_e_perm = le16_to_cpu(local_ace->e_perm);
2712 cifs_ace->cifs_e_tag = le16_to_cpu(local_ace->e_tag);
2713 /* BB is there a better way to handle the large uid? */
2714 if (local_ace->e_id == cpu_to_le32(-1)) {
2715 /* Probably no need to le convert -1 on any arch but can not hurt */
2716 cifs_ace->cifs_uid = cpu_to_le64(-1);
2718 cifs_ace->cifs_uid = cpu_to_le64(le32_to_cpu(local_ace->e_id));
2719 /*cFYI(1,("perm %d tag %d id %d",ace->e_perm,ace->e_tag,ace->e_id));*/
2723 /* Convert ACL from local Linux POSIX xattr to CIFS POSIX ACL wire format */
2724 static __u16 ACL_to_cifs_posix(char *parm_data, const char *pACL,
2725 const int buflen, const int acl_type)
2728 struct cifs_posix_acl *cifs_acl = (struct cifs_posix_acl *)parm_data;
2729 posix_acl_xattr_header *local_acl = (posix_acl_xattr_header *)pACL;
2733 if ((buflen == 0) || (pACL == NULL) || (cifs_acl == NULL))
2736 count = posix_acl_xattr_count((size_t)buflen);
2737 cFYI(1, ("setting acl with %d entries from buf of length %d and "
2739 count, buflen, le32_to_cpu(local_acl->a_version)));
2740 if (le32_to_cpu(local_acl->a_version) != 2) {
2741 cFYI(1, ("unknown POSIX ACL version %d",
2742 le32_to_cpu(local_acl->a_version)));
2745 cifs_acl->version = cpu_to_le16(1);
2746 if (acl_type == ACL_TYPE_ACCESS)
2747 cifs_acl->access_entry_count = cpu_to_le16(count);
2748 else if (acl_type == ACL_TYPE_DEFAULT)
2749 cifs_acl->default_entry_count = cpu_to_le16(count);
2751 cFYI(1, ("unknown ACL type %d", acl_type));
2754 for (i = 0; i < count; i++) {
2755 rc = convert_ace_to_cifs_ace(&cifs_acl->ace_array[i],
2756 &local_acl->a_entries[i]);
2758 /* ACE not converted */
2763 rc = (__u16)(count * sizeof(struct cifs_posix_ace));
2764 rc += sizeof(struct cifs_posix_acl);
2765 /* BB add check to make sure ACL does not overflow SMB */
2771 CIFSSMBGetPosixACL(const int xid, struct cifsTconInfo *tcon,
2772 const unsigned char *searchName,
2773 char *acl_inf, const int buflen, const int acl_type,
2774 const struct nls_table *nls_codepage, int remap)
2776 /* SMB_QUERY_POSIX_ACL */
2777 TRANSACTION2_QPI_REQ *pSMB = NULL;
2778 TRANSACTION2_QPI_RSP *pSMBr = NULL;
2782 __u16 params, byte_count;
2784 cFYI(1, ("In GetPosixACL (Unix) for path %s", searchName));
2787 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2792 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2794 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
2795 PATH_MAX, nls_codepage, remap);
2796 name_len++; /* trailing null */
2798 pSMB->FileName[name_len] = 0;
2799 pSMB->FileName[name_len+1] = 0;
2800 } else { /* BB improve the check for buffer overruns BB */
2801 name_len = strnlen(searchName, PATH_MAX);
2802 name_len++; /* trailing null */
2803 strncpy(pSMB->FileName, searchName, name_len);
2806 params = 2 /* level */ + 4 /* rsrvd */ + name_len /* incl null */ ;
2807 pSMB->TotalDataCount = 0;
2808 pSMB->MaxParameterCount = cpu_to_le16(2);
2809 /* BB find exact max data count below from sess structure BB */
2810 pSMB->MaxDataCount = cpu_to_le16(4000);
2811 pSMB->MaxSetupCount = 0;
2815 pSMB->Reserved2 = 0;
2816 pSMB->ParameterOffset = cpu_to_le16(
2817 offsetof(struct smb_com_transaction2_qpi_req,
2818 InformationLevel) - 4);
2819 pSMB->DataCount = 0;
2820 pSMB->DataOffset = 0;
2821 pSMB->SetupCount = 1;
2822 pSMB->Reserved3 = 0;
2823 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
2824 byte_count = params + 1 /* pad */ ;
2825 pSMB->TotalParameterCount = cpu_to_le16(params);
2826 pSMB->ParameterCount = pSMB->TotalParameterCount;
2827 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_POSIX_ACL);
2828 pSMB->Reserved4 = 0;
2829 pSMB->hdr.smb_buf_length += byte_count;
2830 pSMB->ByteCount = cpu_to_le16(byte_count);
2832 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2833 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2834 cifs_stats_inc(&tcon->num_acl_get);
2836 cFYI(1, ("Send error in Query POSIX ACL = %d", rc));
2838 /* decode response */
2840 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
2841 if (rc || (pSMBr->ByteCount < 2))
2842 /* BB also check enough total bytes returned */
2843 rc = -EIO; /* bad smb */
2845 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
2846 __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
2847 rc = cifs_copy_posix_acl(acl_inf,
2848 (char *)&pSMBr->hdr.Protocol+data_offset,
2849 buflen, acl_type, count);
2852 cifs_buf_release(pSMB);
2859 CIFSSMBSetPosixACL(const int xid, struct cifsTconInfo *tcon,
2860 const unsigned char *fileName,
2861 const char *local_acl, const int buflen,
2863 const struct nls_table *nls_codepage, int remap)
2865 struct smb_com_transaction2_spi_req *pSMB = NULL;
2866 struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
2870 int bytes_returned = 0;
2871 __u16 params, byte_count, data_count, param_offset, offset;
2873 cFYI(1, ("In SetPosixACL (Unix) for path %s", fileName));
2875 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2879 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2881 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
2882 PATH_MAX, nls_codepage, remap);
2883 name_len++; /* trailing null */
2885 } else { /* BB improve the check for buffer overruns BB */
2886 name_len = strnlen(fileName, PATH_MAX);
2887 name_len++; /* trailing null */
2888 strncpy(pSMB->FileName, fileName, name_len);
2890 params = 6 + name_len;
2891 pSMB->MaxParameterCount = cpu_to_le16(2);
2892 /* BB find max SMB size from sess */
2893 pSMB->MaxDataCount = cpu_to_le16(1000);
2894 pSMB->MaxSetupCount = 0;
2898 pSMB->Reserved2 = 0;
2899 param_offset = offsetof(struct smb_com_transaction2_spi_req,
2900 InformationLevel) - 4;
2901 offset = param_offset + params;
2902 parm_data = ((char *) &pSMB->hdr.Protocol) + offset;
2903 pSMB->ParameterOffset = cpu_to_le16(param_offset);
2905 /* convert to on the wire format for POSIX ACL */
2906 data_count = ACL_to_cifs_posix(parm_data, local_acl, buflen, acl_type);
2908 if (data_count == 0) {
2910 goto setACLerrorExit;
2912 pSMB->DataOffset = cpu_to_le16(offset);
2913 pSMB->SetupCount = 1;
2914 pSMB->Reserved3 = 0;
2915 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
2916 pSMB->InformationLevel = cpu_to_le16(SMB_SET_POSIX_ACL);
2917 byte_count = 3 /* pad */ + params + data_count;
2918 pSMB->DataCount = cpu_to_le16(data_count);
2919 pSMB->TotalDataCount = pSMB->DataCount;
2920 pSMB->ParameterCount = cpu_to_le16(params);
2921 pSMB->TotalParameterCount = pSMB->ParameterCount;
2922 pSMB->Reserved4 = 0;
2923 pSMB->hdr.smb_buf_length += byte_count;
2924 pSMB->ByteCount = cpu_to_le16(byte_count);
2925 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2926 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2928 cFYI(1, ("Set POSIX ACL returned %d", rc));
2931 cifs_buf_release(pSMB);
2937 /* BB fix tabs in this function FIXME BB */
2939 CIFSGetExtAttr(const int xid, struct cifsTconInfo *tcon,
2940 const int netfid, __u64 *pExtAttrBits, __u64 *pMask)
2943 struct smb_t2_qfi_req *pSMB = NULL;
2944 struct smb_t2_qfi_rsp *pSMBr = NULL;
2946 __u16 params, byte_count;
2948 cFYI(1, ("In GetExtAttr"));
2953 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2958 params = 2 /* level */ + 2 /* fid */;
2959 pSMB->t2.TotalDataCount = 0;
2960 pSMB->t2.MaxParameterCount = cpu_to_le16(4);
2961 /* BB find exact max data count below from sess structure BB */
2962 pSMB->t2.MaxDataCount = cpu_to_le16(4000);
2963 pSMB->t2.MaxSetupCount = 0;
2964 pSMB->t2.Reserved = 0;
2966 pSMB->t2.Timeout = 0;
2967 pSMB->t2.Reserved2 = 0;
2968 pSMB->t2.ParameterOffset = cpu_to_le16(offsetof(struct smb_t2_qfi_req,
2970 pSMB->t2.DataCount = 0;
2971 pSMB->t2.DataOffset = 0;
2972 pSMB->t2.SetupCount = 1;
2973 pSMB->t2.Reserved3 = 0;
2974 pSMB->t2.SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION);
2975 byte_count = params + 1 /* pad */ ;
2976 pSMB->t2.TotalParameterCount = cpu_to_le16(params);
2977 pSMB->t2.ParameterCount = pSMB->t2.TotalParameterCount;
2978 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_ATTR_FLAGS);
2981 pSMB->hdr.smb_buf_length += byte_count;
2982 pSMB->t2.ByteCount = cpu_to_le16(byte_count);
2984 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2985 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2987 cFYI(1, ("error %d in GetExtAttr", rc));
2989 /* decode response */
2990 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
2991 if (rc || (pSMBr->ByteCount < 2))
2992 /* BB also check enough total bytes returned */
2993 /* If rc should we check for EOPNOSUPP and
2994 disable the srvino flag? or in caller? */
2995 rc = -EIO; /* bad smb */
2997 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
2998 __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
2999 struct file_chattr_info *pfinfo;
3000 /* BB Do we need a cast or hash here ? */
3002 cFYI(1, ("Illegal size ret in GetExtAttr"));
3006 pfinfo = (struct file_chattr_info *)
3007 (data_offset + (char *) &pSMBr->hdr.Protocol);
3008 *pExtAttrBits = le64_to_cpu(pfinfo->mode);
3009 *pMask = le64_to_cpu(pfinfo->mask);
3013 cifs_buf_release(pSMB);
3015 goto GetExtAttrRetry;
3019 #endif /* CONFIG_POSIX */
3021 #ifdef CONFIG_CIFS_EXPERIMENTAL
3022 /* Get Security Descriptor (by handle) from remote server for a file or dir */
3024 CIFSSMBGetCIFSACL(const int xid, struct cifsTconInfo *tcon, __u16 fid,
3025 struct cifs_ntsd **acl_inf, __u32 *pbuflen)
3029 QUERY_SEC_DESC_REQ *pSMB;
3032 cFYI(1, ("GetCifsACL"));
3037 rc = smb_init_nttransact(NT_TRANSACT_QUERY_SECURITY_DESC, 0,
3038 8 /* parm len */, tcon, (void **) &pSMB);
3042 pSMB->MaxParameterCount = cpu_to_le32(4);
3043 /* BB TEST with big acls that might need to be e.g. larger than 16K */
3044 pSMB->MaxSetupCount = 0;
3045 pSMB->Fid = fid; /* file handle always le */
3046 pSMB->AclFlags = cpu_to_le32(CIFS_ACL_OWNER | CIFS_ACL_GROUP |
3048 pSMB->ByteCount = cpu_to_le16(11); /* 3 bytes pad + 8 bytes parm */
3049 pSMB->hdr.smb_buf_length += 11;
3050 iov[0].iov_base = (char *)pSMB;
3051 iov[0].iov_len = pSMB->hdr.smb_buf_length + 4;
3053 rc = SendReceive2(xid, tcon->ses, iov, 1 /* num iovec */, &buf_type,
3055 cifs_stats_inc(&tcon->num_acl_get);
3057 cFYI(1, ("Send error in QuerySecDesc = %d", rc));
3058 } else { /* decode response */
3062 struct smb_com_ntransact_rsp *pSMBr;
3065 /* validate_nttransact */
3066 rc = validate_ntransact(iov[0].iov_base, (char **)&parm,
3067 &pdata, &parm_len, pbuflen);
3070 pSMBr = (struct smb_com_ntransact_rsp *)iov[0].iov_base;
3072 cFYI(1, ("smb %p parm %p data %p", pSMBr, parm, *acl_inf));
3074 if (le32_to_cpu(pSMBr->ParameterCount) != 4) {
3075 rc = -EIO; /* bad smb */
3080 /* BB check that data area is minimum length and as big as acl_len */
3082 acl_len = le32_to_cpu(*parm);
3083 if (acl_len != *pbuflen) {
3084 cERROR(1, ("acl length %d does not match %d",
3085 acl_len, *pbuflen));
3086 if (*pbuflen > acl_len)
3090 /* check if buffer is big enough for the acl
3091 header followed by the smallest SID */
3092 if ((*pbuflen < sizeof(struct cifs_ntsd) + 8) ||
3093 (*pbuflen >= 64 * 1024)) {
3094 cERROR(1, ("bad acl length %d", *pbuflen));
3098 *acl_inf = kmalloc(*pbuflen, GFP_KERNEL);
3099 if (*acl_inf == NULL) {
3103 memcpy(*acl_inf, pdata, *pbuflen);
3107 if (buf_type == CIFS_SMALL_BUFFER)
3108 cifs_small_buf_release(iov[0].iov_base);
3109 else if (buf_type == CIFS_LARGE_BUFFER)
3110 cifs_buf_release(iov[0].iov_base);
3111 /* cifs_small_buf_release(pSMB); */ /* Freed earlier now in SendReceive2 */
3116 CIFSSMBSetCIFSACL(const int xid, struct cifsTconInfo *tcon, __u16 fid,
3117 struct cifs_ntsd *pntsd, __u32 acllen)
3119 __u16 byte_count, param_count, data_count, param_offset, data_offset;
3121 int bytes_returned = 0;
3122 SET_SEC_DESC_REQ *pSMB = NULL;
3123 NTRANSACT_RSP *pSMBr = NULL;
3126 rc = smb_init(SMB_COM_NT_TRANSACT, 19, tcon, (void **) &pSMB,
3131 pSMB->MaxSetupCount = 0;
3135 param_offset = offsetof(struct smb_com_transaction_ssec_req, Fid) - 4;
3136 data_count = acllen;
3137 data_offset = param_offset + param_count;
3138 byte_count = 3 /* pad */ + param_count;
3140 pSMB->DataCount = cpu_to_le32(data_count);
3141 pSMB->TotalDataCount = pSMB->DataCount;
3142 pSMB->MaxParameterCount = cpu_to_le32(4);
3143 pSMB->MaxDataCount = cpu_to_le32(16384);
3144 pSMB->ParameterCount = cpu_to_le32(param_count);
3145 pSMB->ParameterOffset = cpu_to_le32(param_offset);
3146 pSMB->TotalParameterCount = pSMB->ParameterCount;
3147 pSMB->DataOffset = cpu_to_le32(data_offset);
3148 pSMB->SetupCount = 0;
3149 pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_SET_SECURITY_DESC);
3150 pSMB->ByteCount = cpu_to_le16(byte_count+data_count);
3152 pSMB->Fid = fid; /* file handle always le */
3153 pSMB->Reserved2 = 0;
3154 pSMB->AclFlags = cpu_to_le32(CIFS_ACL_DACL);
3156 if (pntsd && acllen) {
3157 memcpy((char *) &pSMBr->hdr.Protocol + data_offset,
3160 pSMB->hdr.smb_buf_length += (byte_count + data_count);
3163 pSMB->hdr.smb_buf_length += byte_count;
3165 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3166 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3168 cFYI(1, ("SetCIFSACL bytes_returned: %d, rc: %d", bytes_returned, rc));
3170 cFYI(1, ("Set CIFS ACL returned %d", rc));
3171 cifs_buf_release(pSMB);
3174 goto setCifsAclRetry;
3179 #endif /* CONFIG_CIFS_EXPERIMENTAL */
3181 /* Legacy Query Path Information call for lookup to old servers such
3183 int SMBQueryInformation(const int xid, struct cifsTconInfo *tcon,
3184 const unsigned char *searchName,
3185 FILE_ALL_INFO *pFinfo,
3186 const struct nls_table *nls_codepage, int remap)
3188 QUERY_INFORMATION_REQ *pSMB;
3189 QUERY_INFORMATION_RSP *pSMBr;
3194 cFYI(1, ("In SMBQPath path %s", searchName));
3196 rc = smb_init(SMB_COM_QUERY_INFORMATION, 0, tcon, (void **) &pSMB,
3201 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3203 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
3204 PATH_MAX, nls_codepage, remap);
3205 name_len++; /* trailing null */
3208 name_len = strnlen(searchName, PATH_MAX);
3209 name_len++; /* trailing null */
3210 strncpy(pSMB->FileName, searchName, name_len);
3212 pSMB->BufferFormat = 0x04;
3213 name_len++; /* account for buffer type byte */
3214 pSMB->hdr.smb_buf_length += (__u16) name_len;
3215 pSMB->ByteCount = cpu_to_le16(name_len);
3217 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3218 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3220 cFYI(1, ("Send error in QueryInfo = %d", rc));
3221 } else if (pFinfo) {
3223 __u32 time = le32_to_cpu(pSMBr->last_write_time);
3225 /* decode response */
3226 /* BB FIXME - add time zone adjustment BB */
3227 memset(pFinfo, 0, sizeof(FILE_ALL_INFO));
3230 /* decode time fields */
3231 pFinfo->ChangeTime = cpu_to_le64(cifs_UnixTimeToNT(ts));
3232 pFinfo->LastWriteTime = pFinfo->ChangeTime;
3233 pFinfo->LastAccessTime = 0;
3234 pFinfo->AllocationSize =
3235 cpu_to_le64(le32_to_cpu(pSMBr->size));
3236 pFinfo->EndOfFile = pFinfo->AllocationSize;
3237 pFinfo->Attributes =
3238 cpu_to_le32(le16_to_cpu(pSMBr->attr));
3240 rc = -EIO; /* bad buffer passed in */
3242 cifs_buf_release(pSMB);
3251 CIFSSMBQFileInfo(const int xid, struct cifsTconInfo *tcon,
3252 u16 netfid, FILE_ALL_INFO *pFindData)
3254 struct smb_t2_qfi_req *pSMB = NULL;
3255 struct smb_t2_qfi_rsp *pSMBr = NULL;
3258 __u16 params, byte_count;
3261 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3266 params = 2 /* level */ + 2 /* fid */;
3267 pSMB->t2.TotalDataCount = 0;
3268 pSMB->t2.MaxParameterCount = cpu_to_le16(4);
3269 /* BB find exact max data count below from sess structure BB */
3270 pSMB->t2.MaxDataCount = cpu_to_le16(CIFSMaxBufSize);
3271 pSMB->t2.MaxSetupCount = 0;
3272 pSMB->t2.Reserved = 0;
3274 pSMB->t2.Timeout = 0;
3275 pSMB->t2.Reserved2 = 0;
3276 pSMB->t2.ParameterOffset = cpu_to_le16(offsetof(struct smb_t2_qfi_req,
3278 pSMB->t2.DataCount = 0;
3279 pSMB->t2.DataOffset = 0;
3280 pSMB->t2.SetupCount = 1;
3281 pSMB->t2.Reserved3 = 0;
3282 pSMB->t2.SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION);
3283 byte_count = params + 1 /* pad */ ;
3284 pSMB->t2.TotalParameterCount = cpu_to_le16(params);
3285 pSMB->t2.ParameterCount = pSMB->t2.TotalParameterCount;
3286 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_ALL_INFO);
3289 pSMB->hdr.smb_buf_length += byte_count;
3291 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3292 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3294 cFYI(1, ("Send error in QPathInfo = %d", rc));
3295 } else { /* decode response */
3296 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3298 if (rc) /* BB add auto retry on EOPNOTSUPP? */
3300 else if (pSMBr->ByteCount < 40)
3301 rc = -EIO; /* bad smb */
3302 else if (pFindData) {
3303 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3304 memcpy((char *) pFindData,
3305 (char *) &pSMBr->hdr.Protocol +
3306 data_offset, sizeof(FILE_ALL_INFO));
3310 cifs_buf_release(pSMB);
3312 goto QFileInfoRetry;
3318 CIFSSMBQPathInfo(const int xid, struct cifsTconInfo *tcon,
3319 const unsigned char *searchName,
3320 FILE_ALL_INFO *pFindData,
3321 int legacy /* old style infolevel */,
3322 const struct nls_table *nls_codepage, int remap)
3324 /* level 263 SMB_QUERY_FILE_ALL_INFO */
3325 TRANSACTION2_QPI_REQ *pSMB = NULL;
3326 TRANSACTION2_QPI_RSP *pSMBr = NULL;
3330 __u16 params, byte_count;
3332 /* cFYI(1, ("In QPathInfo path %s", searchName)); */
3334 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3339 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3341 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
3342 PATH_MAX, nls_codepage, remap);
3343 name_len++; /* trailing null */
3345 } else { /* BB improve the check for buffer overruns BB */
3346 name_len = strnlen(searchName, PATH_MAX);
3347 name_len++; /* trailing null */
3348 strncpy(pSMB->FileName, searchName, name_len);
3351 params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */;
3352 pSMB->TotalDataCount = 0;
3353 pSMB->MaxParameterCount = cpu_to_le16(2);
3354 /* BB find exact max SMB PDU from sess structure BB */
3355 pSMB->MaxDataCount = cpu_to_le16(4000);
3356 pSMB->MaxSetupCount = 0;
3360 pSMB->Reserved2 = 0;
3361 pSMB->ParameterOffset = cpu_to_le16(offsetof(
3362 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
3363 pSMB->DataCount = 0;
3364 pSMB->DataOffset = 0;
3365 pSMB->SetupCount = 1;
3366 pSMB->Reserved3 = 0;
3367 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
3368 byte_count = params + 1 /* pad */ ;
3369 pSMB->TotalParameterCount = cpu_to_le16(params);
3370 pSMB->ParameterCount = pSMB->TotalParameterCount;
3372 pSMB->InformationLevel = cpu_to_le16(SMB_INFO_STANDARD);
3374 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_ALL_INFO);
3375 pSMB->Reserved4 = 0;
3376 pSMB->hdr.smb_buf_length += byte_count;
3377 pSMB->ByteCount = cpu_to_le16(byte_count);
3379 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3380 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3382 cFYI(1, ("Send error in QPathInfo = %d", rc));
3383 } else { /* decode response */
3384 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3386 if (rc) /* BB add auto retry on EOPNOTSUPP? */
3388 else if (!legacy && (pSMBr->ByteCount < 40))
3389 rc = -EIO; /* bad smb */
3390 else if (legacy && (pSMBr->ByteCount < 24))
3391 rc = -EIO; /* 24 or 26 expected but we do not read
3393 else if (pFindData) {
3395 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3397 /* On legacy responses we do not read the last field,
3398 EAsize, fortunately since it varies by subdialect and
3399 also note it differs on Set vs. Get, ie two bytes or 4
3400 bytes depending but we don't care here */
3402 size = sizeof(FILE_INFO_STANDARD);
3404 size = sizeof(FILE_ALL_INFO);
3405 memcpy((char *) pFindData,
3406 (char *) &pSMBr->hdr.Protocol +
3411 cifs_buf_release(pSMB);
3413 goto QPathInfoRetry;
3419 CIFSSMBUnixQFileInfo(const int xid, struct cifsTconInfo *tcon,
3420 u16 netfid, FILE_UNIX_BASIC_INFO *pFindData)
3422 struct smb_t2_qfi_req *pSMB = NULL;
3423 struct smb_t2_qfi_rsp *pSMBr = NULL;
3426 __u16 params, byte_count;
3429 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3434 params = 2 /* level */ + 2 /* fid */;
3435 pSMB->t2.TotalDataCount = 0;
3436 pSMB->t2.MaxParameterCount = cpu_to_le16(4);
3437 /* BB find exact max data count below from sess structure BB */
3438 pSMB->t2.MaxDataCount = cpu_to_le16(CIFSMaxBufSize);
3439 pSMB->t2.MaxSetupCount = 0;
3440 pSMB->t2.Reserved = 0;
3442 pSMB->t2.Timeout = 0;
3443 pSMB->t2.Reserved2 = 0;
3444 pSMB->t2.ParameterOffset = cpu_to_le16(offsetof(struct smb_t2_qfi_req,
3446 pSMB->t2.DataCount = 0;
3447 pSMB->t2.DataOffset = 0;
3448 pSMB->t2.SetupCount = 1;
3449 pSMB->t2.Reserved3 = 0;
3450 pSMB->t2.SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION);
3451 byte_count = params + 1 /* pad */ ;
3452 pSMB->t2.TotalParameterCount = cpu_to_le16(params);
3453 pSMB->t2.ParameterCount = pSMB->t2.TotalParameterCount;
3454 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC);
3457 pSMB->hdr.smb_buf_length += byte_count;
3459 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3460 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3462 cFYI(1, ("Send error in QPathInfo = %d", rc));
3463 } else { /* decode response */
3464 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3466 if (rc || (pSMBr->ByteCount < sizeof(FILE_UNIX_BASIC_INFO))) {
3467 cERROR(1, ("Malformed FILE_UNIX_BASIC_INFO response.\n"
3468 "Unix Extensions can be disabled on mount "
3469 "by specifying the nosfu mount option."));
3470 rc = -EIO; /* bad smb */
3472 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3473 memcpy((char *) pFindData,
3474 (char *) &pSMBr->hdr.Protocol +
3476 sizeof(FILE_UNIX_BASIC_INFO));
3480 cifs_buf_release(pSMB);
3482 goto UnixQFileInfoRetry;
3488 CIFSSMBUnixQPathInfo(const int xid, struct cifsTconInfo *tcon,
3489 const unsigned char *searchName,
3490 FILE_UNIX_BASIC_INFO *pFindData,
3491 const struct nls_table *nls_codepage, int remap)
3493 /* SMB_QUERY_FILE_UNIX_BASIC */
3494 TRANSACTION2_QPI_REQ *pSMB = NULL;
3495 TRANSACTION2_QPI_RSP *pSMBr = NULL;
3497 int bytes_returned = 0;
3499 __u16 params, byte_count;
3501 cFYI(1, ("In QPathInfo (Unix) the path %s", searchName));
3503 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3508 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3510 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
3511 PATH_MAX, nls_codepage, remap);
3512 name_len++; /* trailing null */
3514 } else { /* BB improve the check for buffer overruns BB */
3515 name_len = strnlen(searchName, PATH_MAX);
3516 name_len++; /* trailing null */
3517 strncpy(pSMB->FileName, searchName, name_len);
3520 params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */;
3521 pSMB->TotalDataCount = 0;
3522 pSMB->MaxParameterCount = cpu_to_le16(2);
3523 /* BB find exact max SMB PDU from sess structure BB */
3524 pSMB->MaxDataCount = cpu_to_le16(4000);
3525 pSMB->MaxSetupCount = 0;
3529 pSMB->Reserved2 = 0;
3530 pSMB->ParameterOffset = cpu_to_le16(offsetof(
3531 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
3532 pSMB->DataCount = 0;
3533 pSMB->DataOffset = 0;
3534 pSMB->SetupCount = 1;
3535 pSMB->Reserved3 = 0;
3536 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
3537 byte_count = params + 1 /* pad */ ;
3538 pSMB->TotalParameterCount = cpu_to_le16(params);
3539 pSMB->ParameterCount = pSMB->TotalParameterCount;
3540 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC);
3541 pSMB->Reserved4 = 0;
3542 pSMB->hdr.smb_buf_length += byte_count;
3543 pSMB->ByteCount = cpu_to_le16(byte_count);
3545 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3546 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3548 cFYI(1, ("Send error in QPathInfo = %d", rc));
3549 } else { /* decode response */
3550 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3552 if (rc || (pSMBr->ByteCount < sizeof(FILE_UNIX_BASIC_INFO))) {
3553 cERROR(1, ("Malformed FILE_UNIX_BASIC_INFO response.\n"
3554 "Unix Extensions can be disabled on mount "
3555 "by specifying the nosfu mount option."));
3556 rc = -EIO; /* bad smb */
3558 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3559 memcpy((char *) pFindData,
3560 (char *) &pSMBr->hdr.Protocol +
3562 sizeof(FILE_UNIX_BASIC_INFO));
3565 cifs_buf_release(pSMB);
3567 goto UnixQPathInfoRetry;
3572 /* xid, tcon, searchName and codepage are input parms, rest are returned */
3574 CIFSFindFirst(const int xid, struct cifsTconInfo *tcon,
3575 const char *searchName,
3576 const struct nls_table *nls_codepage,
3578 struct cifs_search_info *psrch_inf, int remap, const char dirsep)
3580 /* level 257 SMB_ */
3581 TRANSACTION2_FFIRST_REQ *pSMB = NULL;
3582 TRANSACTION2_FFIRST_RSP *pSMBr = NULL;
3583 T2_FFIRST_RSP_PARMS *parms;
3585 int bytes_returned = 0;
3587 __u16 params, byte_count;
3589 cFYI(1, ("In FindFirst for %s", searchName));
3592 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3597 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3599 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
3600 PATH_MAX, nls_codepage, remap);
3601 /* We can not add the asterik earlier in case
3602 it got remapped to 0xF03A as if it were part of the
3603 directory name instead of a wildcard */
3605 pSMB->FileName[name_len] = dirsep;
3606 pSMB->FileName[name_len+1] = 0;
3607 pSMB->FileName[name_len+2] = '*';
3608 pSMB->FileName[name_len+3] = 0;
3609 name_len += 4; /* now the trailing null */
3610 pSMB->FileName[name_len] = 0; /* null terminate just in case */
3611 pSMB->FileName[name_len+1] = 0;
3613 } else { /* BB add check for overrun of SMB buf BB */
3614 name_len = strnlen(searchName, PATH_MAX);
3615 /* BB fix here and in unicode clause above ie
3616 if (name_len > buffersize-header)
3617 free buffer exit; BB */
3618 strncpy(pSMB->FileName, searchName, name_len);
3619 pSMB->FileName[name_len] = dirsep;
3620 pSMB->FileName[name_len+1] = '*';
3621 pSMB->FileName[name_len+2] = 0;
3625 params = 12 + name_len /* includes null */ ;
3626 pSMB->TotalDataCount = 0; /* no EAs */
3627 pSMB->MaxParameterCount = cpu_to_le16(10);
3628 pSMB->MaxDataCount = cpu_to_le16((tcon->ses->server->maxBuf -
3629 MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
3630 pSMB->MaxSetupCount = 0;
3634 pSMB->Reserved2 = 0;
3635 byte_count = params + 1 /* pad */ ;
3636 pSMB->TotalParameterCount = cpu_to_le16(params);
3637 pSMB->ParameterCount = pSMB->TotalParameterCount;
3638 pSMB->ParameterOffset = cpu_to_le16(
3639 offsetof(struct smb_com_transaction2_ffirst_req, SearchAttributes)
3641 pSMB->DataCount = 0;
3642 pSMB->DataOffset = 0;
3643 pSMB->SetupCount = 1; /* one byte, no need to make endian neutral */
3644 pSMB->Reserved3 = 0;
3645 pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_FIRST);
3646 pSMB->SearchAttributes =
3647 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
3649 pSMB->SearchCount = cpu_to_le16(CIFSMaxBufSize/sizeof(FILE_UNIX_INFO));
3650 pSMB->SearchFlags = cpu_to_le16(CIFS_SEARCH_CLOSE_AT_END |
3651 CIFS_SEARCH_RETURN_RESUME);
3652 pSMB->InformationLevel = cpu_to_le16(psrch_inf->info_level);
3654 /* BB what should we set StorageType to? Does it matter? BB */
3655 pSMB->SearchStorageType = 0;
3656 pSMB->hdr.smb_buf_length += byte_count;
3657 pSMB->ByteCount = cpu_to_le16(byte_count);
3659 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3660 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3661 cifs_stats_inc(&tcon->num_ffirst);
3663 if (rc) {/* BB add logic to retry regular search if Unix search
3664 rejected unexpectedly by server */
3665 /* BB Add code to handle unsupported level rc */
3666 cFYI(1, ("Error in FindFirst = %d", rc));
3668 cifs_buf_release(pSMB);
3670 /* BB eventually could optimize out free and realloc of buf */
3673 goto findFirstRetry;
3674 } else { /* decode response */
3675 /* BB remember to free buffer if error BB */
3676 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3680 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
3681 psrch_inf->unicode = true;
3683 psrch_inf->unicode = false;
3685 psrch_inf->ntwrk_buf_start = (char *)pSMBr;
3686 psrch_inf->smallBuf = 0;
3687 psrch_inf->srch_entries_start =
3688 (char *) &pSMBr->hdr.Protocol +
3689 le16_to_cpu(pSMBr->t2.DataOffset);
3690 parms = (T2_FFIRST_RSP_PARMS *)((char *) &pSMBr->hdr.Protocol +
3691 le16_to_cpu(pSMBr->t2.ParameterOffset));
3693 if (parms->EndofSearch)
3694 psrch_inf->endOfSearch = true;
3696 psrch_inf->endOfSearch = false;
3698 psrch_inf->entries_in_buffer =
3699 le16_to_cpu(parms->SearchCount);
3700 psrch_inf->index_of_last_entry = 2 /* skip . and .. */ +
3701 psrch_inf->entries_in_buffer;
3702 lnoff = le16_to_cpu(parms->LastNameOffset);
3703 if (tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE <
3705 cERROR(1, ("ignoring corrupt resume name"));
3706 psrch_inf->last_entry = NULL;
3710 psrch_inf->last_entry = psrch_inf->srch_entries_start +
3713 *pnetfid = parms->SearchHandle;
3715 cifs_buf_release(pSMB);
3722 int CIFSFindNext(const int xid, struct cifsTconInfo *tcon,
3723 __u16 searchHandle, struct cifs_search_info *psrch_inf)
3725 TRANSACTION2_FNEXT_REQ *pSMB = NULL;
3726 TRANSACTION2_FNEXT_RSP *pSMBr = NULL;
3727 T2_FNEXT_RSP_PARMS *parms;
3728 char *response_data;
3730 int bytes_returned, name_len;
3731 __u16 params, byte_count;
3733 cFYI(1, ("In FindNext"));
3735 if (psrch_inf->endOfSearch)
3738 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3743 params = 14; /* includes 2 bytes of null string, converted to LE below*/
3745 pSMB->TotalDataCount = 0; /* no EAs */
3746 pSMB->MaxParameterCount = cpu_to_le16(8);
3747 pSMB->MaxDataCount =
3748 cpu_to_le16((tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE) &
3750 pSMB->MaxSetupCount = 0;
3754 pSMB->Reserved2 = 0;
3755 pSMB->ParameterOffset = cpu_to_le16(
3756 offsetof(struct smb_com_transaction2_fnext_req,SearchHandle) - 4);
3757 pSMB->DataCount = 0;
3758 pSMB->DataOffset = 0;
3759 pSMB->SetupCount = 1;
3760 pSMB->Reserved3 = 0;
3761 pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_NEXT);
3762 pSMB->SearchHandle = searchHandle; /* always kept as le */
3764 cpu_to_le16(CIFSMaxBufSize / sizeof(FILE_UNIX_INFO));
3765 pSMB->InformationLevel = cpu_to_le16(psrch_inf->info_level);
3766 pSMB->ResumeKey = psrch_inf->resume_key;
3768 cpu_to_le16(CIFS_SEARCH_CLOSE_AT_END | CIFS_SEARCH_RETURN_RESUME);
3770 name_len = psrch_inf->resume_name_len;
3772 if (name_len < PATH_MAX) {
3773 memcpy(pSMB->ResumeFileName, psrch_inf->presume_name, name_len);
3774 byte_count += name_len;
3775 /* 14 byte parm len above enough for 2 byte null terminator */
3776 pSMB->ResumeFileName[name_len] = 0;
3777 pSMB->ResumeFileName[name_len+1] = 0;
3780 goto FNext2_err_exit;
3782 byte_count = params + 1 /* pad */ ;
3783 pSMB->TotalParameterCount = cpu_to_le16(params);
3784 pSMB->ParameterCount = pSMB->TotalParameterCount;
3785 pSMB->hdr.smb_buf_length += byte_count;
3786 pSMB->ByteCount = cpu_to_le16(byte_count);
3788 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3789 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3790 cifs_stats_inc(&tcon->num_fnext);
3793 psrch_inf->endOfSearch = true;
3794 cifs_buf_release(pSMB);
3795 rc = 0; /* search probably was closed at end of search*/
3797 cFYI(1, ("FindNext returned = %d", rc));
3798 } else { /* decode response */
3799 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3804 /* BB fixme add lock for file (srch_info) struct here */
3805 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
3806 psrch_inf->unicode = true;
3808 psrch_inf->unicode = false;
3809 response_data = (char *) &pSMBr->hdr.Protocol +
3810 le16_to_cpu(pSMBr->t2.ParameterOffset);
3811 parms = (T2_FNEXT_RSP_PARMS *)response_data;
3812 response_data = (char *)&pSMBr->hdr.Protocol +
3813 le16_to_cpu(pSMBr->t2.DataOffset);
3814 if (psrch_inf->smallBuf)
3815 cifs_small_buf_release(
3816 psrch_inf->ntwrk_buf_start);
3818 cifs_buf_release(psrch_inf->ntwrk_buf_start);
3819 psrch_inf->srch_entries_start = response_data;
3820 psrch_inf->ntwrk_buf_start = (char *)pSMB;
3821 psrch_inf->smallBuf = 0;
3822 if (parms->EndofSearch)
3823 psrch_inf->endOfSearch = true;
3825 psrch_inf->endOfSearch = false;
3826 psrch_inf->entries_in_buffer =
3827 le16_to_cpu(parms->SearchCount);
3828 psrch_inf->index_of_last_entry +=
3829 psrch_inf->entries_in_buffer;
3830 lnoff = le16_to_cpu(parms->LastNameOffset);
3831 if (tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE <
3833 cERROR(1, ("ignoring corrupt resume name"));
3834 psrch_inf->last_entry = NULL;
3837 psrch_inf->last_entry =
3838 psrch_inf->srch_entries_start + lnoff;
3840 /* cFYI(1,("fnxt2 entries in buf %d index_of_last %d",
3841 psrch_inf->entries_in_buffer, psrch_inf->index_of_last_entry)); */
3843 /* BB fixme add unlock here */
3848 /* BB On error, should we leave previous search buf (and count and
3849 last entry fields) intact or free the previous one? */
3851 /* Note: On -EAGAIN error only caller can retry on handle based calls
3852 since file handle passed in no longer valid */
3855 cifs_buf_release(pSMB);
3860 CIFSFindClose(const int xid, struct cifsTconInfo *tcon,
3861 const __u16 searchHandle)
3864 FINDCLOSE_REQ *pSMB = NULL;
3866 cFYI(1, ("In CIFSSMBFindClose"));
3867 rc = small_smb_init(SMB_COM_FIND_CLOSE2, 1, tcon, (void **)&pSMB);
3869 /* no sense returning error if session restarted
3870 as file handle has been closed */
3876 pSMB->FileID = searchHandle;
3877 pSMB->ByteCount = 0;
3878 rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0);
3880 cERROR(1, ("Send error in FindClose = %d", rc));
3882 cifs_stats_inc(&tcon->num_fclose);
3884 /* Since session is dead, search handle closed on server already */
3892 CIFSGetSrvInodeNumber(const int xid, struct cifsTconInfo *tcon,
3893 const unsigned char *searchName,
3894 __u64 *inode_number,
3895 const struct nls_table *nls_codepage, int remap)
3898 TRANSACTION2_QPI_REQ *pSMB = NULL;
3899 TRANSACTION2_QPI_RSP *pSMBr = NULL;
3900 int name_len, bytes_returned;
3901 __u16 params, byte_count;
3903 cFYI(1, ("In GetSrvInodeNum for %s", searchName));
3907 GetInodeNumberRetry:
3908 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3913 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3915 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
3916 PATH_MAX, nls_codepage, remap);
3917 name_len++; /* trailing null */
3919 } else { /* BB improve the check for buffer overruns BB */
3920 name_len = strnlen(searchName, PATH_MAX);
3921 name_len++; /* trailing null */
3922 strncpy(pSMB->FileName, searchName, name_len);
3925 params = 2 /* level */ + 4 /* rsrvd */ + name_len /* incl null */ ;
3926 pSMB->TotalDataCount = 0;
3927 pSMB->MaxParameterCount = cpu_to_le16(2);
3928 /* BB find exact max data count below from sess structure BB */
3929 pSMB->MaxDataCount = cpu_to_le16(4000);
3930 pSMB->MaxSetupCount = 0;
3934 pSMB->Reserved2 = 0;
3935 pSMB->ParameterOffset = cpu_to_le16(offsetof(
3936 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
3937 pSMB->DataCount = 0;
3938 pSMB->DataOffset = 0;
3939 pSMB->SetupCount = 1;
3940 pSMB->Reserved3 = 0;
3941 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
3942 byte_count = params + 1 /* pad */ ;
3943 pSMB->TotalParameterCount = cpu_to_le16(params);
3944 pSMB->ParameterCount = pSMB->TotalParameterCount;
3945 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_INTERNAL_INFO);
3946 pSMB->Reserved4 = 0;
3947 pSMB->hdr.smb_buf_length += byte_count;
3948 pSMB->ByteCount = cpu_to_le16(byte_count);
3950 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3951 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3953 cFYI(1, ("error %d in QueryInternalInfo", rc));
3955 /* decode response */
3956 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3957 if (rc || (pSMBr->ByteCount < 2))
3958 /* BB also check enough total bytes returned */
3959 /* If rc should we check for EOPNOSUPP and
3960 disable the srvino flag? or in caller? */
3961 rc = -EIO; /* bad smb */
3963 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3964 __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
3965 struct file_internal_info *pfinfo;
3966 /* BB Do we need a cast or hash here ? */
3968 cFYI(1, ("Illegal size ret in QryIntrnlInf"));
3970 goto GetInodeNumOut;
3972 pfinfo = (struct file_internal_info *)
3973 (data_offset + (char *) &pSMBr->hdr.Protocol);
3974 *inode_number = le64_to_cpu(pfinfo->UniqueId);
3978 cifs_buf_release(pSMB);
3980 goto GetInodeNumberRetry;
3984 /* parses DFS refferal V3 structure
3985 * caller is responsible for freeing target_nodes
3988 * on failure - errno
3991 parse_DFS_referrals(TRANSACTION2_GET_DFS_REFER_RSP *pSMBr,
3992 unsigned int *num_of_nodes,
3993 struct dfs_info3_param **target_nodes,
3994 const struct nls_table *nls_codepage, int remap,
3995 const char *searchName)
4000 struct dfs_referral_level_3 *ref;
4002 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
4006 *num_of_nodes = le16_to_cpu(pSMBr->NumberOfReferrals);
4008 if (*num_of_nodes < 1) {
4009 cERROR(1, ("num_referrals: must be at least > 0,"
4010 "but we get num_referrals = %d\n", *num_of_nodes));
4012 goto parse_DFS_referrals_exit;
4015 ref = (struct dfs_referral_level_3 *) &(pSMBr->referrals);
4016 if (ref->VersionNumber != cpu_to_le16(3)) {
4017 cERROR(1, ("Referrals of V%d version are not supported,"
4018 "should be V3", le16_to_cpu(ref->VersionNumber)));
4020 goto parse_DFS_referrals_exit;
4023 /* get the upper boundary of the resp buffer */
4024 data_end = (char *)(&(pSMBr->PathConsumed)) +
4025 le16_to_cpu(pSMBr->t2.DataCount);
4027 cFYI(1, ("num_referrals: %d dfs flags: 0x%x ... \n",
4029 le32_to_cpu(pSMBr->DFSFlags)));
4031 *target_nodes = kzalloc(sizeof(struct dfs_info3_param) *
4032 *num_of_nodes, GFP_KERNEL);
4033 if (*target_nodes == NULL) {
4034 cERROR(1, ("Failed to allocate buffer for target_nodes\n"));
4036 goto parse_DFS_referrals_exit;
4039 /* collect necessary data from referrals */
4040 for (i = 0; i < *num_of_nodes; i++) {
4043 struct dfs_info3_param *node = (*target_nodes)+i;
4045 node->flags = le32_to_cpu(pSMBr->DFSFlags);
4047 __le16 *tmp = kmalloc(strlen(searchName)*2 + 2,
4051 goto parse_DFS_referrals_exit;
4053 cifsConvertToUCS((__le16 *) tmp, searchName,
4054 PATH_MAX, nls_codepage, remap);
4055 node->path_consumed = cifs_ucs2_bytes(tmp,
4056 le16_to_cpu(pSMBr->PathConsumed),
4060 node->path_consumed = le16_to_cpu(pSMBr->PathConsumed);
4062 node->server_type = le16_to_cpu(ref->ServerType);
4063 node->ref_flag = le16_to_cpu(ref->ReferralEntryFlags);
4066 temp = (char *)ref + le16_to_cpu(ref->DfsPathOffset);
4067 max_len = data_end - temp;
4068 node->path_name = cifs_strndup_from_ucs(temp, max_len,
4069 is_unicode, nls_codepage);
4070 if (!node->path_name) {
4072 goto parse_DFS_referrals_exit;
4075 /* copy link target UNC */
4076 temp = (char *)ref + le16_to_cpu(ref->NetworkAddressOffset);
4077 max_len = data_end - temp;
4078 node->node_name = cifs_strndup_from_ucs(temp, max_len,
4079 is_unicode, nls_codepage);
4080 if (!node->node_name)
4084 parse_DFS_referrals_exit:
4086 free_dfs_info_array(*target_nodes, *num_of_nodes);
4087 *target_nodes = NULL;
4094 CIFSGetDFSRefer(const int xid, struct cifsSesInfo *ses,
4095 const unsigned char *searchName,
4096 struct dfs_info3_param **target_nodes,
4097 unsigned int *num_of_nodes,
4098 const struct nls_table *nls_codepage, int remap)
4100 /* TRANS2_GET_DFS_REFERRAL */
4101 TRANSACTION2_GET_DFS_REFER_REQ *pSMB = NULL;
4102 TRANSACTION2_GET_DFS_REFER_RSP *pSMBr = NULL;
4106 __u16 params, byte_count;
4108 *target_nodes = NULL;
4110 cFYI(1, ("In GetDFSRefer the path %s", searchName));
4114 rc = smb_init(SMB_COM_TRANSACTION2, 15, NULL, (void **) &pSMB,
4119 /* server pointer checked in called function,
4120 but should never be null here anyway */
4121 pSMB->hdr.Mid = GetNextMid(ses->server);
4122 pSMB->hdr.Tid = ses->ipc_tid;
4123 pSMB->hdr.Uid = ses->Suid;
4124 if (ses->capabilities & CAP_STATUS32)
4125 pSMB->hdr.Flags2 |= SMBFLG2_ERR_STATUS;
4126 if (ses->capabilities & CAP_DFS)
4127 pSMB->hdr.Flags2 |= SMBFLG2_DFS;
4129 if (ses->capabilities & CAP_UNICODE) {
4130 pSMB->hdr.Flags2 |= SMBFLG2_UNICODE;
4132 cifsConvertToUCS((__le16 *) pSMB->RequestFileName,
4133 searchName, PATH_MAX, nls_codepage, remap);
4134 name_len++; /* trailing null */
4136 } else { /* BB improve the check for buffer overruns BB */
4137 name_len = strnlen(searchName, PATH_MAX);
4138 name_len++; /* trailing null */
4139 strncpy(pSMB->RequestFileName, searchName, name_len);
4143 if (ses->server->secMode &
4144 (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
4145 pSMB->hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
4148 pSMB->hdr.Uid = ses->Suid;
4150 params = 2 /* level */ + name_len /*includes null */ ;
4151 pSMB->TotalDataCount = 0;
4152 pSMB->DataCount = 0;
4153 pSMB->DataOffset = 0;
4154 pSMB->MaxParameterCount = 0;
4155 /* BB find exact max SMB PDU from sess structure BB */
4156 pSMB->MaxDataCount = cpu_to_le16(4000);
4157 pSMB->MaxSetupCount = 0;
4161 pSMB->Reserved2 = 0;
4162 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4163 struct smb_com_transaction2_get_dfs_refer_req, MaxReferralLevel) - 4);
4164 pSMB->SetupCount = 1;
4165 pSMB->Reserved3 = 0;
4166 pSMB->SubCommand = cpu_to_le16(TRANS2_GET_DFS_REFERRAL);
4167 byte_count = params + 3 /* pad */ ;
4168 pSMB->ParameterCount = cpu_to_le16(params);
4169 pSMB->TotalParameterCount = pSMB->ParameterCount;
4170 pSMB->MaxReferralLevel = cpu_to_le16(3);
4171 pSMB->hdr.smb_buf_length += byte_count;
4172 pSMB->ByteCount = cpu_to_le16(byte_count);
4174 rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB,
4175 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4177 cFYI(1, ("Send error in GetDFSRefer = %d", rc));
4180 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4182 /* BB Also check if enough total bytes returned? */
4183 if (rc || (pSMBr->ByteCount < 17)) {
4184 rc = -EIO; /* bad smb */
4188 cFYI(1, ("Decoding GetDFSRefer response BCC: %d Offset %d",
4190 le16_to_cpu(pSMBr->t2.DataOffset)));
4192 /* parse returned result into more usable form */
4193 rc = parse_DFS_referrals(pSMBr, num_of_nodes,
4194 target_nodes, nls_codepage, remap,
4198 cifs_buf_release(pSMB);
4206 /* Query File System Info such as free space to old servers such as Win 9x */
4208 SMBOldQFSInfo(const int xid, struct cifsTconInfo *tcon, struct kstatfs *FSData)
4210 /* level 0x01 SMB_QUERY_FILE_SYSTEM_INFO */
4211 TRANSACTION2_QFSI_REQ *pSMB = NULL;
4212 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4213 FILE_SYSTEM_ALLOC_INFO *response_data;
4215 int bytes_returned = 0;
4216 __u16 params, byte_count;
4218 cFYI(1, ("OldQFSInfo"));
4220 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4225 params = 2; /* level */
4226 pSMB->TotalDataCount = 0;
4227 pSMB->MaxParameterCount = cpu_to_le16(2);
4228 pSMB->MaxDataCount = cpu_to_le16(1000);
4229 pSMB->MaxSetupCount = 0;
4233 pSMB->Reserved2 = 0;
4234 byte_count = params + 1 /* pad */ ;
4235 pSMB->TotalParameterCount = cpu_to_le16(params);
4236 pSMB->ParameterCount = pSMB->TotalParameterCount;
4237 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4238 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4239 pSMB->DataCount = 0;
4240 pSMB->DataOffset = 0;
4241 pSMB->SetupCount = 1;
4242 pSMB->Reserved3 = 0;
4243 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4244 pSMB->InformationLevel = cpu_to_le16(SMB_INFO_ALLOCATION);
4245 pSMB->hdr.smb_buf_length += byte_count;
4246 pSMB->ByteCount = cpu_to_le16(byte_count);
4248 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4249 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4251 cFYI(1, ("Send error in QFSInfo = %d", rc));
4252 } else { /* decode response */
4253 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4255 if (rc || (pSMBr->ByteCount < 18))
4256 rc = -EIO; /* bad smb */
4258 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4259 cFYI(1, ("qfsinf resp BCC: %d Offset %d",
4260 pSMBr->ByteCount, data_offset));
4262 response_data = (FILE_SYSTEM_ALLOC_INFO *)
4263 (((char *) &pSMBr->hdr.Protocol) + data_offset);
4265 le16_to_cpu(response_data->BytesPerSector) *
4266 le32_to_cpu(response_data->
4267 SectorsPerAllocationUnit);
4269 le32_to_cpu(response_data->TotalAllocationUnits);
4270 FSData->f_bfree = FSData->f_bavail =
4271 le32_to_cpu(response_data->FreeAllocationUnits);
4273 ("Blocks: %lld Free: %lld Block size %ld",
4274 (unsigned long long)FSData->f_blocks,
4275 (unsigned long long)FSData->f_bfree,
4279 cifs_buf_release(pSMB);
4282 goto oldQFSInfoRetry;
4288 CIFSSMBQFSInfo(const int xid, struct cifsTconInfo *tcon, struct kstatfs *FSData)
4290 /* level 0x103 SMB_QUERY_FILE_SYSTEM_INFO */
4291 TRANSACTION2_QFSI_REQ *pSMB = NULL;
4292 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4293 FILE_SYSTEM_INFO *response_data;
4295 int bytes_returned = 0;
4296 __u16 params, byte_count;
4298 cFYI(1, ("In QFSInfo"));
4300 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4305 params = 2; /* level */
4306 pSMB->TotalDataCount = 0;
4307 pSMB->MaxParameterCount = cpu_to_le16(2);
4308 pSMB->MaxDataCount = cpu_to_le16(1000);
4309 pSMB->MaxSetupCount = 0;
4313 pSMB->Reserved2 = 0;
4314 byte_count = params + 1 /* pad */ ;
4315 pSMB->TotalParameterCount = cpu_to_le16(params);
4316 pSMB->ParameterCount = pSMB->TotalParameterCount;
4317 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4318 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4319 pSMB->DataCount = 0;
4320 pSMB->DataOffset = 0;
4321 pSMB->SetupCount = 1;
4322 pSMB->Reserved3 = 0;
4323 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4324 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_SIZE_INFO);
4325 pSMB->hdr.smb_buf_length += byte_count;
4326 pSMB->ByteCount = cpu_to_le16(byte_count);
4328 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4329 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4331 cFYI(1, ("Send error in QFSInfo = %d", rc));
4332 } else { /* decode response */
4333 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4335 if (rc || (pSMBr->ByteCount < 24))
4336 rc = -EIO; /* bad smb */
4338 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4342 *) (((char *) &pSMBr->hdr.Protocol) +
4345 le32_to_cpu(response_data->BytesPerSector) *
4346 le32_to_cpu(response_data->
4347 SectorsPerAllocationUnit);
4349 le64_to_cpu(response_data->TotalAllocationUnits);
4350 FSData->f_bfree = FSData->f_bavail =
4351 le64_to_cpu(response_data->FreeAllocationUnits);
4353 ("Blocks: %lld Free: %lld Block size %ld",
4354 (unsigned long long)FSData->f_blocks,
4355 (unsigned long long)FSData->f_bfree,
4359 cifs_buf_release(pSMB);
4368 CIFSSMBQFSAttributeInfo(const int xid, struct cifsTconInfo *tcon)
4370 /* level 0x105 SMB_QUERY_FILE_SYSTEM_INFO */
4371 TRANSACTION2_QFSI_REQ *pSMB = NULL;
4372 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4373 FILE_SYSTEM_ATTRIBUTE_INFO *response_data;
4375 int bytes_returned = 0;
4376 __u16 params, byte_count;
4378 cFYI(1, ("In QFSAttributeInfo"));
4380 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4385 params = 2; /* level */
4386 pSMB->TotalDataCount = 0;
4387 pSMB->MaxParameterCount = cpu_to_le16(2);
4388 /* BB find exact max SMB PDU from sess structure BB */
4389 pSMB->MaxDataCount = cpu_to_le16(1000);
4390 pSMB->MaxSetupCount = 0;
4394 pSMB->Reserved2 = 0;
4395 byte_count = params + 1 /* pad */ ;
4396 pSMB->TotalParameterCount = cpu_to_le16(params);
4397 pSMB->ParameterCount = pSMB->TotalParameterCount;
4398 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4399 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4400 pSMB->DataCount = 0;
4401 pSMB->DataOffset = 0;
4402 pSMB->SetupCount = 1;
4403 pSMB->Reserved3 = 0;
4404 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4405 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_ATTRIBUTE_INFO);
4406 pSMB->hdr.smb_buf_length += byte_count;
4407 pSMB->ByteCount = cpu_to_le16(byte_count);
4409 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4410 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4412 cERROR(1, ("Send error in QFSAttributeInfo = %d", rc));
4413 } else { /* decode response */
4414 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4416 if (rc || (pSMBr->ByteCount < 13)) {
4417 /* BB also check if enough bytes returned */
4418 rc = -EIO; /* bad smb */
4420 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4422 (FILE_SYSTEM_ATTRIBUTE_INFO
4423 *) (((char *) &pSMBr->hdr.Protocol) +
4425 memcpy(&tcon->fsAttrInfo, response_data,
4426 sizeof(FILE_SYSTEM_ATTRIBUTE_INFO));
4429 cifs_buf_release(pSMB);
4432 goto QFSAttributeRetry;
4438 CIFSSMBQFSDeviceInfo(const int xid, struct cifsTconInfo *tcon)
4440 /* level 0x104 SMB_QUERY_FILE_SYSTEM_INFO */
4441 TRANSACTION2_QFSI_REQ *pSMB = NULL;
4442 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4443 FILE_SYSTEM_DEVICE_INFO *response_data;
4445 int bytes_returned = 0;
4446 __u16 params, byte_count;
4448 cFYI(1, ("In QFSDeviceInfo"));
4450 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4455 params = 2; /* level */
4456 pSMB->TotalDataCount = 0;
4457 pSMB->MaxParameterCount = cpu_to_le16(2);
4458 /* BB find exact max SMB PDU from sess structure BB */
4459 pSMB->MaxDataCount = cpu_to_le16(1000);
4460 pSMB->MaxSetupCount = 0;
4464 pSMB->Reserved2 = 0;
4465 byte_count = params + 1 /* pad */ ;
4466 pSMB->TotalParameterCount = cpu_to_le16(params);
4467 pSMB->ParameterCount = pSMB->TotalParameterCount;
4468 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4469 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4471 pSMB->DataCount = 0;
4472 pSMB->DataOffset = 0;
4473 pSMB->SetupCount = 1;
4474 pSMB->Reserved3 = 0;
4475 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4476 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_DEVICE_INFO);
4477 pSMB->hdr.smb_buf_length += byte_count;
4478 pSMB->ByteCount = cpu_to_le16(byte_count);
4480 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4481 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4483 cFYI(1, ("Send error in QFSDeviceInfo = %d", rc));
4484 } else { /* decode response */
4485 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4487 if (rc || (pSMBr->ByteCount < sizeof(FILE_SYSTEM_DEVICE_INFO)))
4488 rc = -EIO; /* bad smb */
4490 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4492 (FILE_SYSTEM_DEVICE_INFO *)
4493 (((char *) &pSMBr->hdr.Protocol) +
4495 memcpy(&tcon->fsDevInfo, response_data,
4496 sizeof(FILE_SYSTEM_DEVICE_INFO));
4499 cifs_buf_release(pSMB);
4502 goto QFSDeviceRetry;
4508 CIFSSMBQFSUnixInfo(const int xid, struct cifsTconInfo *tcon)
4510 /* level 0x200 SMB_QUERY_CIFS_UNIX_INFO */
4511 TRANSACTION2_QFSI_REQ *pSMB = NULL;
4512 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4513 FILE_SYSTEM_UNIX_INFO *response_data;
4515 int bytes_returned = 0;
4516 __u16 params, byte_count;
4518 cFYI(1, ("In QFSUnixInfo"));
4520 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4525 params = 2; /* level */
4526 pSMB->TotalDataCount = 0;
4527 pSMB->DataCount = 0;
4528 pSMB->DataOffset = 0;
4529 pSMB->MaxParameterCount = cpu_to_le16(2);
4530 /* BB find exact max SMB PDU from sess structure BB */
4531 pSMB->MaxDataCount = cpu_to_le16(100);
4532 pSMB->MaxSetupCount = 0;
4536 pSMB->Reserved2 = 0;
4537 byte_count = params + 1 /* pad */ ;
4538 pSMB->ParameterCount = cpu_to_le16(params);
4539 pSMB->TotalParameterCount = pSMB->ParameterCount;
4540 pSMB->ParameterOffset = cpu_to_le16(offsetof(struct
4541 smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4542 pSMB->SetupCount = 1;
4543 pSMB->Reserved3 = 0;
4544 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4545 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_CIFS_UNIX_INFO);
4546 pSMB->hdr.smb_buf_length += byte_count;
4547 pSMB->ByteCount = cpu_to_le16(byte_count);
4549 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4550 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4552 cERROR(1, ("Send error in QFSUnixInfo = %d", rc));
4553 } else { /* decode response */
4554 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4556 if (rc || (pSMBr->ByteCount < 13)) {
4557 rc = -EIO; /* bad smb */
4559 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4561 (FILE_SYSTEM_UNIX_INFO
4562 *) (((char *) &pSMBr->hdr.Protocol) +
4564 memcpy(&tcon->fsUnixInfo, response_data,
4565 sizeof(FILE_SYSTEM_UNIX_INFO));
4568 cifs_buf_release(pSMB);
4578 CIFSSMBSetFSUnixInfo(const int xid, struct cifsTconInfo *tcon, __u64 cap)
4580 /* level 0x200 SMB_SET_CIFS_UNIX_INFO */
4581 TRANSACTION2_SETFSI_REQ *pSMB = NULL;
4582 TRANSACTION2_SETFSI_RSP *pSMBr = NULL;
4584 int bytes_returned = 0;
4585 __u16 params, param_offset, offset, byte_count;
4587 cFYI(1, ("In SETFSUnixInfo"));
4589 /* BB switch to small buf init to save memory */
4590 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4595 params = 4; /* 2 bytes zero followed by info level. */
4596 pSMB->MaxSetupCount = 0;
4600 pSMB->Reserved2 = 0;
4601 param_offset = offsetof(struct smb_com_transaction2_setfsi_req, FileNum)
4603 offset = param_offset + params;
4605 pSMB->MaxParameterCount = cpu_to_le16(4);
4606 /* BB find exact max SMB PDU from sess structure BB */
4607 pSMB->MaxDataCount = cpu_to_le16(100);
4608 pSMB->SetupCount = 1;
4609 pSMB->Reserved3 = 0;
4610 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FS_INFORMATION);
4611 byte_count = 1 /* pad */ + params + 12;
4613 pSMB->DataCount = cpu_to_le16(12);
4614 pSMB->ParameterCount = cpu_to_le16(params);
4615 pSMB->TotalDataCount = pSMB->DataCount;
4616 pSMB->TotalParameterCount = pSMB->ParameterCount;
4617 pSMB->ParameterOffset = cpu_to_le16(param_offset);
4618 pSMB->DataOffset = cpu_to_le16(offset);
4622 pSMB->InformationLevel = cpu_to_le16(SMB_SET_CIFS_UNIX_INFO);
4625 pSMB->ClientUnixMajor = cpu_to_le16(CIFS_UNIX_MAJOR_VERSION);
4626 pSMB->ClientUnixMinor = cpu_to_le16(CIFS_UNIX_MINOR_VERSION);
4627 pSMB->ClientUnixCap = cpu_to_le64(cap);
4629 pSMB->hdr.smb_buf_length += byte_count;
4630 pSMB->ByteCount = cpu_to_le16(byte_count);
4632 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4633 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4635 cERROR(1, ("Send error in SETFSUnixInfo = %d", rc));
4636 } else { /* decode response */
4637 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4639 rc = -EIO; /* bad smb */
4641 cifs_buf_release(pSMB);
4644 goto SETFSUnixRetry;
4652 CIFSSMBQFSPosixInfo(const int xid, struct cifsTconInfo *tcon,
4653 struct kstatfs *FSData)
4655 /* level 0x201 SMB_QUERY_CIFS_POSIX_INFO */
4656 TRANSACTION2_QFSI_REQ *pSMB = NULL;
4657 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4658 FILE_SYSTEM_POSIX_INFO *response_data;
4660 int bytes_returned = 0;
4661 __u16 params, byte_count;
4663 cFYI(1, ("In QFSPosixInfo"));
4665 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4670 params = 2; /* level */
4671 pSMB->TotalDataCount = 0;
4672 pSMB->DataCount = 0;
4673 pSMB->DataOffset = 0;
4674 pSMB->MaxParameterCount = cpu_to_le16(2);
4675 /* BB find exact max SMB PDU from sess structure BB */
4676 pSMB->MaxDataCount = cpu_to_le16(100);
4677 pSMB->MaxSetupCount = 0;
4681 pSMB->Reserved2 = 0;
4682 byte_count = params + 1 /* pad */ ;
4683 pSMB->ParameterCount = cpu_to_le16(params);
4684 pSMB->TotalParameterCount = pSMB->ParameterCount;
4685 pSMB->ParameterOffset = cpu_to_le16(offsetof(struct
4686 smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4687 pSMB->SetupCount = 1;
4688 pSMB->Reserved3 = 0;
4689 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4690 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_POSIX_FS_INFO);
4691 pSMB->hdr.smb_buf_length += byte_count;
4692 pSMB->ByteCount = cpu_to_le16(byte_count);
4694 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4695 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4697 cFYI(1, ("Send error in QFSUnixInfo = %d", rc));
4698 } else { /* decode response */
4699 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4701 if (rc || (pSMBr->ByteCount < 13)) {
4702 rc = -EIO; /* bad smb */
4704 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4706 (FILE_SYSTEM_POSIX_INFO
4707 *) (((char *) &pSMBr->hdr.Protocol) +
4710 le32_to_cpu(response_data->BlockSize);
4712 le64_to_cpu(response_data->TotalBlocks);
4714 le64_to_cpu(response_data->BlocksAvail);
4715 if (response_data->UserBlocksAvail == cpu_to_le64(-1)) {
4716 FSData->f_bavail = FSData->f_bfree;
4719 le64_to_cpu(response_data->UserBlocksAvail);
4721 if (response_data->TotalFileNodes != cpu_to_le64(-1))
4723 le64_to_cpu(response_data->TotalFileNodes);
4724 if (response_data->FreeFileNodes != cpu_to_le64(-1))
4726 le64_to_cpu(response_data->FreeFileNodes);
4729 cifs_buf_release(pSMB);
4738 /* We can not use write of zero bytes trick to
4739 set file size due to need for large file support. Also note that
4740 this SetPathInfo is preferred to SetFileInfo based method in next
4741 routine which is only needed to work around a sharing violation bug
4742 in Samba which this routine can run into */
4745 CIFSSMBSetEOF(const int xid, struct cifsTconInfo *tcon, const char *fileName,
4746 __u64 size, bool SetAllocation,
4747 const struct nls_table *nls_codepage, int remap)
4749 struct smb_com_transaction2_spi_req *pSMB = NULL;
4750 struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
4751 struct file_end_of_file_info *parm_data;
4754 int bytes_returned = 0;
4755 __u16 params, byte_count, data_count, param_offset, offset;
4757 cFYI(1, ("In SetEOF"));
4759 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4764 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4766 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
4767 PATH_MAX, nls_codepage, remap);
4768 name_len++; /* trailing null */
4770 } else { /* BB improve the check for buffer overruns BB */
4771 name_len = strnlen(fileName, PATH_MAX);
4772 name_len++; /* trailing null */
4773 strncpy(pSMB->FileName, fileName, name_len);
4775 params = 6 + name_len;
4776 data_count = sizeof(struct file_end_of_file_info);
4777 pSMB->MaxParameterCount = cpu_to_le16(2);
4778 pSMB->MaxDataCount = cpu_to_le16(4100);
4779 pSMB->MaxSetupCount = 0;
4783 pSMB->Reserved2 = 0;
4784 param_offset = offsetof(struct smb_com_transaction2_spi_req,
4785 InformationLevel) - 4;
4786 offset = param_offset + params;
4787 if (SetAllocation) {
4788 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
4789 pSMB->InformationLevel =
4790 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2);
4792 pSMB->InformationLevel =
4793 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO);
4794 } else /* Set File Size */ {
4795 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
4796 pSMB->InformationLevel =
4797 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO2);
4799 pSMB->InformationLevel =
4800 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO);
4804 (struct file_end_of_file_info *) (((char *) &pSMB->hdr.Protocol) +
4806 pSMB->ParameterOffset = cpu_to_le16(param_offset);
4807 pSMB->DataOffset = cpu_to_le16(offset);
4808 pSMB->SetupCount = 1;
4809 pSMB->Reserved3 = 0;
4810 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
4811 byte_count = 3 /* pad */ + params + data_count;
4812 pSMB->DataCount = cpu_to_le16(data_count);
4813 pSMB->TotalDataCount = pSMB->DataCount;
4814 pSMB->ParameterCount = cpu_to_le16(params);
4815 pSMB->TotalParameterCount = pSMB->ParameterCount;
4816 pSMB->Reserved4 = 0;
4817 pSMB->hdr.smb_buf_length += byte_count;
4818 parm_data->FileSize = cpu_to_le64(size);
4819 pSMB->ByteCount = cpu_to_le16(byte_count);
4820 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4821 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4823 cFYI(1, ("SetPathInfo (file size) returned %d", rc));
4825 cifs_buf_release(pSMB);
4834 CIFSSMBSetFileSize(const int xid, struct cifsTconInfo *tcon, __u64 size,
4835 __u16 fid, __u32 pid_of_opener, bool SetAllocation)
4837 struct smb_com_transaction2_sfi_req *pSMB = NULL;
4839 struct file_end_of_file_info *parm_data;
4841 __u16 params, param_offset, offset, byte_count, count;
4843 cFYI(1, ("SetFileSize (via SetFileInfo) %lld",
4845 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
4850 pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
4851 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));
4854 pSMB->MaxSetupCount = 0;
4858 pSMB->Reserved2 = 0;
4859 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
4860 offset = param_offset + params;
4862 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
4864 count = sizeof(struct file_end_of_file_info);
4865 pSMB->MaxParameterCount = cpu_to_le16(2);
4866 /* BB find exact max SMB PDU from sess structure BB */
4867 pSMB->MaxDataCount = cpu_to_le16(1000);
4868 pSMB->SetupCount = 1;
4869 pSMB->Reserved3 = 0;
4870 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
4871 byte_count = 3 /* pad */ + params + count;
4872 pSMB->DataCount = cpu_to_le16(count);
4873 pSMB->ParameterCount = cpu_to_le16(params);
4874 pSMB->TotalDataCount = pSMB->DataCount;
4875 pSMB->TotalParameterCount = pSMB->ParameterCount;
4876 pSMB->ParameterOffset = cpu_to_le16(param_offset);
4878 (struct file_end_of_file_info *) (((char *) &pSMB->hdr.Protocol)
4880 pSMB->DataOffset = cpu_to_le16(offset);
4881 parm_data->FileSize = cpu_to_le64(size);
4883 if (SetAllocation) {
4884 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
4885 pSMB->InformationLevel =
4886 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2);
4888 pSMB->InformationLevel =
4889 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO);
4890 } else /* Set File Size */ {
4891 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
4892 pSMB->InformationLevel =
4893 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO2);
4895 pSMB->InformationLevel =
4896 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO);
4898 pSMB->Reserved4 = 0;
4899 pSMB->hdr.smb_buf_length += byte_count;
4900 pSMB->ByteCount = cpu_to_le16(byte_count);
4901 rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0);
4904 ("Send error in SetFileInfo (SetFileSize) = %d",
4908 /* Note: On -EAGAIN error only caller can retry on handle based calls
4909 since file handle passed in no longer valid */
4914 /* Some legacy servers such as NT4 require that the file times be set on
4915 an open handle, rather than by pathname - this is awkward due to
4916 potential access conflicts on the open, but it is unavoidable for these
4917 old servers since the only other choice is to go from 100 nanosecond DCE
4918 time and resort to the original setpathinfo level which takes the ancient
4919 DOS time format with 2 second granularity */
4921 CIFSSMBSetFileInfo(const int xid, struct cifsTconInfo *tcon,
4922 const FILE_BASIC_INFO *data, __u16 fid, __u32 pid_of_opener)
4924 struct smb_com_transaction2_sfi_req *pSMB = NULL;
4927 __u16 params, param_offset, offset, byte_count, count;
4929 cFYI(1, ("Set Times (via SetFileInfo)"));
4930 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
4935 pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
4936 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));
4939 pSMB->MaxSetupCount = 0;
4943 pSMB->Reserved2 = 0;
4944 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
4945 offset = param_offset + params;
4947 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
4949 count = sizeof(FILE_BASIC_INFO);
4950 pSMB->MaxParameterCount = cpu_to_le16(2);
4951 /* BB find max SMB PDU from sess */
4952 pSMB->MaxDataCount = cpu_to_le16(1000);
4953 pSMB->SetupCount = 1;
4954 pSMB->Reserved3 = 0;
4955 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
4956 byte_count = 3 /* pad */ + params + count;
4957 pSMB->DataCount = cpu_to_le16(count);
4958 pSMB->ParameterCount = cpu_to_le16(params);
4959 pSMB->TotalDataCount = pSMB->DataCount;
4960 pSMB->TotalParameterCount = pSMB->ParameterCount;
4961 pSMB->ParameterOffset = cpu_to_le16(param_offset);
4962 pSMB->DataOffset = cpu_to_le16(offset);
4964 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
4965 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO2);
4967 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO);
4968 pSMB->Reserved4 = 0;
4969 pSMB->hdr.smb_buf_length += byte_count;
4970 pSMB->ByteCount = cpu_to_le16(byte_count);
4971 memcpy(data_offset, data, sizeof(FILE_BASIC_INFO));
4972 rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0);
4974 cFYI(1, ("Send error in Set Time (SetFileInfo) = %d", rc));
4976 /* Note: On -EAGAIN error only caller can retry on handle based calls
4977 since file handle passed in no longer valid */
4983 CIFSSMBSetFileDisposition(const int xid, struct cifsTconInfo *tcon,
4984 bool delete_file, __u16 fid, __u32 pid_of_opener)
4986 struct smb_com_transaction2_sfi_req *pSMB = NULL;
4989 __u16 params, param_offset, offset, byte_count, count;
4991 cFYI(1, ("Set File Disposition (via SetFileInfo)"));
4992 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
4997 pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
4998 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));
5001 pSMB->MaxSetupCount = 0;
5005 pSMB->Reserved2 = 0;
5006 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
5007 offset = param_offset + params;
5009 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
5012 pSMB->MaxParameterCount = cpu_to_le16(2);
5013 /* BB find max SMB PDU from sess */
5014 pSMB->MaxDataCount = cpu_to_le16(1000);
5015 pSMB->SetupCount = 1;
5016 pSMB->Reserved3 = 0;
5017 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
5018 byte_count = 3 /* pad */ + params + count;
5019 pSMB->DataCount = cpu_to_le16(count);
5020 pSMB->ParameterCount = cpu_to_le16(params);
5021 pSMB->TotalDataCount = pSMB->DataCount;
5022 pSMB->TotalParameterCount = pSMB->ParameterCount;
5023 pSMB->ParameterOffset = cpu_to_le16(param_offset);
5024 pSMB->DataOffset = cpu_to_le16(offset);
5026 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_DISPOSITION_INFO);
5027 pSMB->Reserved4 = 0;
5028 pSMB->hdr.smb_buf_length += byte_count;
5029 pSMB->ByteCount = cpu_to_le16(byte_count);
5030 *data_offset = delete_file ? 1 : 0;
5031 rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0);
5033 cFYI(1, ("Send error in SetFileDisposition = %d", rc));
5039 CIFSSMBSetPathInfo(const int xid, struct cifsTconInfo *tcon,
5040 const char *fileName, const FILE_BASIC_INFO *data,
5041 const struct nls_table *nls_codepage, int remap)
5043 TRANSACTION2_SPI_REQ *pSMB = NULL;
5044 TRANSACTION2_SPI_RSP *pSMBr = NULL;
5047 int bytes_returned = 0;
5049 __u16 params, param_offset, offset, byte_count, count;
5051 cFYI(1, ("In SetTimes"));
5054 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5059 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5061 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
5062 PATH_MAX, nls_codepage, remap);
5063 name_len++; /* trailing null */
5065 } else { /* BB improve the check for buffer overruns BB */
5066 name_len = strnlen(fileName, PATH_MAX);
5067 name_len++; /* trailing null */
5068 strncpy(pSMB->FileName, fileName, name_len);
5071 params = 6 + name_len;
5072 count = sizeof(FILE_BASIC_INFO);
5073 pSMB->MaxParameterCount = cpu_to_le16(2);
5074 /* BB find max SMB PDU from sess structure BB */
5075 pSMB->MaxDataCount = cpu_to_le16(1000);
5076 pSMB->MaxSetupCount = 0;
5080 pSMB->Reserved2 = 0;
5081 param_offset = offsetof(struct smb_com_transaction2_spi_req,
5082 InformationLevel) - 4;
5083 offset = param_offset + params;
5084 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
5085 pSMB->ParameterOffset = cpu_to_le16(param_offset);
5086 pSMB->DataOffset = cpu_to_le16(offset);
5087 pSMB->SetupCount = 1;
5088 pSMB->Reserved3 = 0;
5089 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
5090 byte_count = 3 /* pad */ + params + count;
5092 pSMB->DataCount = cpu_to_le16(count);
5093 pSMB->ParameterCount = cpu_to_le16(params);
5094 pSMB->TotalDataCount = pSMB->DataCount;
5095 pSMB->TotalParameterCount = pSMB->ParameterCount;
5096 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
5097 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO2);
5099 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO);
5100 pSMB->Reserved4 = 0;
5101 pSMB->hdr.smb_buf_length += byte_count;
5102 memcpy(data_offset, data, sizeof(FILE_BASIC_INFO));
5103 pSMB->ByteCount = cpu_to_le16(byte_count);
5104 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5105 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5107 cFYI(1, ("SetPathInfo (times) returned %d", rc));
5109 cifs_buf_release(pSMB);
5117 /* Can not be used to set time stamps yet (due to old DOS time format) */
5118 /* Can be used to set attributes */
5119 #if 0 /* Possibly not needed - since it turns out that strangely NT4 has a bug
5120 handling it anyway and NT4 was what we thought it would be needed for
5121 Do not delete it until we prove whether needed for Win9x though */
5123 CIFSSMBSetAttrLegacy(int xid, struct cifsTconInfo *tcon, char *fileName,
5124 __u16 dos_attrs, const struct nls_table *nls_codepage)
5126 SETATTR_REQ *pSMB = NULL;
5127 SETATTR_RSP *pSMBr = NULL;
5132 cFYI(1, ("In SetAttrLegacy"));
5135 rc = smb_init(SMB_COM_SETATTR, 8, tcon, (void **) &pSMB,
5140 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5142 ConvertToUCS((__le16 *) pSMB->fileName, fileName,
5143 PATH_MAX, nls_codepage);
5144 name_len++; /* trailing null */
5146 } else { /* BB improve the check for buffer overruns BB */
5147 name_len = strnlen(fileName, PATH_MAX);
5148 name_len++; /* trailing null */
5149 strncpy(pSMB->fileName, fileName, name_len);
5151 pSMB->attr = cpu_to_le16(dos_attrs);
5152 pSMB->BufferFormat = 0x04;
5153 pSMB->hdr.smb_buf_length += name_len + 1;
5154 pSMB->ByteCount = cpu_to_le16(name_len + 1);
5155 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5156 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5158 cFYI(1, ("Error in LegacySetAttr = %d", rc));
5160 cifs_buf_release(pSMB);
5163 goto SetAttrLgcyRetry;
5167 #endif /* temporarily unneeded SetAttr legacy function */
5170 cifs_fill_unix_set_info(FILE_UNIX_BASIC_INFO *data_offset,
5171 const struct cifs_unix_set_info_args *args)
5173 u64 mode = args->mode;
5176 * Samba server ignores set of file size to zero due to bugs in some
5177 * older clients, but we should be precise - we use SetFileSize to
5178 * set file size and do not want to truncate file size to zero
5179 * accidently as happened on one Samba server beta by putting
5180 * zero instead of -1 here
5182 data_offset->EndOfFile = cpu_to_le64(NO_CHANGE_64);
5183 data_offset->NumOfBytes = cpu_to_le64(NO_CHANGE_64);
5184 data_offset->LastStatusChange = cpu_to_le64(args->ctime);
5185 data_offset->LastAccessTime = cpu_to_le64(args->atime);
5186 data_offset->LastModificationTime = cpu_to_le64(args->mtime);
5187 data_offset->Uid = cpu_to_le64(args->uid);
5188 data_offset->Gid = cpu_to_le64(args->gid);
5189 /* better to leave device as zero when it is */
5190 data_offset->DevMajor = cpu_to_le64(MAJOR(args->device));
5191 data_offset->DevMinor = cpu_to_le64(MINOR(args->device));
5192 data_offset->Permissions = cpu_to_le64(mode);
5195 data_offset->Type = cpu_to_le32(UNIX_FILE);
5196 else if (S_ISDIR(mode))
5197 data_offset->Type = cpu_to_le32(UNIX_DIR);
5198 else if (S_ISLNK(mode))
5199 data_offset->Type = cpu_to_le32(UNIX_SYMLINK);
5200 else if (S_ISCHR(mode))
5201 data_offset->Type = cpu_to_le32(UNIX_CHARDEV);
5202 else if (S_ISBLK(mode))
5203 data_offset->Type = cpu_to_le32(UNIX_BLOCKDEV);
5204 else if (S_ISFIFO(mode))
5205 data_offset->Type = cpu_to_le32(UNIX_FIFO);
5206 else if (S_ISSOCK(mode))
5207 data_offset->Type = cpu_to_le32(UNIX_SOCKET);
5211 CIFSSMBUnixSetFileInfo(const int xid, struct cifsTconInfo *tcon,
5212 const struct cifs_unix_set_info_args *args,
5213 u16 fid, u32 pid_of_opener)
5215 struct smb_com_transaction2_sfi_req *pSMB = NULL;
5216 FILE_UNIX_BASIC_INFO *data_offset;
5218 u16 params, param_offset, offset, byte_count, count;
5220 cFYI(1, ("Set Unix Info (via SetFileInfo)"));
5221 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
5226 pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
5227 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));
5230 pSMB->MaxSetupCount = 0;
5234 pSMB->Reserved2 = 0;
5235 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
5236 offset = param_offset + params;
5238 data_offset = (FILE_UNIX_BASIC_INFO *)
5239 ((char *)(&pSMB->hdr.Protocol) + offset);
5240 count = sizeof(FILE_UNIX_BASIC_INFO);
5242 pSMB->MaxParameterCount = cpu_to_le16(2);
5243 /* BB find max SMB PDU from sess */
5244 pSMB->MaxDataCount = cpu_to_le16(1000);
5245 pSMB->SetupCount = 1;
5246 pSMB->Reserved3 = 0;
5247 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
5248 byte_count = 3 /* pad */ + params + count;
5249 pSMB->DataCount = cpu_to_le16(count);
5250 pSMB->ParameterCount = cpu_to_le16(params);
5251 pSMB->TotalDataCount = pSMB->DataCount;
5252 pSMB->TotalParameterCount = pSMB->ParameterCount;
5253 pSMB->ParameterOffset = cpu_to_le16(param_offset);
5254 pSMB->DataOffset = cpu_to_le16(offset);
5256 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_BASIC);
5257 pSMB->Reserved4 = 0;
5258 pSMB->hdr.smb_buf_length += byte_count;
5259 pSMB->ByteCount = cpu_to_le16(byte_count);
5261 cifs_fill_unix_set_info(data_offset, args);
5263 rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0);
5265 cFYI(1, ("Send error in Set Time (SetFileInfo) = %d", rc));
5267 /* Note: On -EAGAIN error only caller can retry on handle based calls
5268 since file handle passed in no longer valid */
5274 CIFSSMBUnixSetPathInfo(const int xid, struct cifsTconInfo *tcon, char *fileName,
5275 const struct cifs_unix_set_info_args *args,
5276 const struct nls_table *nls_codepage, int remap)
5278 TRANSACTION2_SPI_REQ *pSMB = NULL;
5279 TRANSACTION2_SPI_RSP *pSMBr = NULL;
5282 int bytes_returned = 0;
5283 FILE_UNIX_BASIC_INFO *data_offset;
5284 __u16 params, param_offset, offset, count, byte_count;
5286 cFYI(1, ("In SetUID/GID/Mode"));
5288 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5293 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5295 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
5296 PATH_MAX, nls_codepage, remap);
5297 name_len++; /* trailing null */
5299 } else { /* BB improve the check for buffer overruns BB */
5300 name_len = strnlen(fileName, PATH_MAX);
5301 name_len++; /* trailing null */
5302 strncpy(pSMB->FileName, fileName, name_len);
5305 params = 6 + name_len;
5306 count = sizeof(FILE_UNIX_BASIC_INFO);
5307 pSMB->MaxParameterCount = cpu_to_le16(2);
5308 /* BB find max SMB PDU from sess structure BB */
5309 pSMB->MaxDataCount = cpu_to_le16(1000);
5310 pSMB->MaxSetupCount = 0;
5314 pSMB->Reserved2 = 0;
5315 param_offset = offsetof(struct smb_com_transaction2_spi_req,
5316 InformationLevel) - 4;
5317 offset = param_offset + params;
5319 (FILE_UNIX_BASIC_INFO *) ((char *) &pSMB->hdr.Protocol +
5321 memset(data_offset, 0, count);
5322 pSMB->DataOffset = cpu_to_le16(offset);
5323 pSMB->ParameterOffset = cpu_to_le16(param_offset);
5324 pSMB->SetupCount = 1;
5325 pSMB->Reserved3 = 0;
5326 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
5327 byte_count = 3 /* pad */ + params + count;
5328 pSMB->ParameterCount = cpu_to_le16(params);
5329 pSMB->DataCount = cpu_to_le16(count);
5330 pSMB->TotalParameterCount = pSMB->ParameterCount;
5331 pSMB->TotalDataCount = pSMB->DataCount;
5332 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_BASIC);
5333 pSMB->Reserved4 = 0;
5334 pSMB->hdr.smb_buf_length += byte_count;
5336 cifs_fill_unix_set_info(data_offset, args);
5338 pSMB->ByteCount = cpu_to_le16(byte_count);
5339 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5340 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5342 cFYI(1, ("SetPathInfo (perms) returned %d", rc));
5344 cifs_buf_release(pSMB);
5350 int CIFSSMBNotify(const int xid, struct cifsTconInfo *tcon,
5351 const int notify_subdirs, const __u16 netfid,
5352 __u32 filter, struct file *pfile, int multishot,
5353 const struct nls_table *nls_codepage)
5356 struct smb_com_transaction_change_notify_req *pSMB = NULL;
5357 struct smb_com_ntransaction_change_notify_rsp *pSMBr = NULL;
5358 struct dir_notify_req *dnotify_req;
5361 cFYI(1, ("In CIFSSMBNotify for file handle %d", (int)netfid));
5362 rc = smb_init(SMB_COM_NT_TRANSACT, 23, tcon, (void **) &pSMB,
5367 pSMB->TotalParameterCount = 0 ;
5368 pSMB->TotalDataCount = 0;
5369 pSMB->MaxParameterCount = cpu_to_le32(2);
5370 /* BB find exact data count max from sess structure BB */
5371 pSMB->MaxDataCount = 0; /* same in little endian or be */
5372 /* BB VERIFY verify which is correct for above BB */
5373 pSMB->MaxDataCount = cpu_to_le32((tcon->ses->server->maxBuf -
5374 MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
5376 pSMB->MaxSetupCount = 4;
5378 pSMB->ParameterOffset = 0;
5379 pSMB->DataCount = 0;
5380 pSMB->DataOffset = 0;
5381 pSMB->SetupCount = 4; /* single byte does not need le conversion */
5382 pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_NOTIFY_CHANGE);
5383 pSMB->ParameterCount = pSMB->TotalParameterCount;
5385 pSMB->WatchTree = 1; /* one byte - no le conversion needed */
5386 pSMB->Reserved2 = 0;
5387 pSMB->CompletionFilter = cpu_to_le32(filter);
5388 pSMB->Fid = netfid; /* file handle always le */
5389 pSMB->ByteCount = 0;
5391 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5392 (struct smb_hdr *)pSMBr, &bytes_returned,
5395 cFYI(1, ("Error in Notify = %d", rc));
5397 /* Add file to outstanding requests */
5398 /* BB change to kmem cache alloc */
5399 dnotify_req = kmalloc(
5400 sizeof(struct dir_notify_req),
5403 dnotify_req->Pid = pSMB->hdr.Pid;
5404 dnotify_req->PidHigh = pSMB->hdr.PidHigh;
5405 dnotify_req->Mid = pSMB->hdr.Mid;
5406 dnotify_req->Tid = pSMB->hdr.Tid;
5407 dnotify_req->Uid = pSMB->hdr.Uid;
5408 dnotify_req->netfid = netfid;
5409 dnotify_req->pfile = pfile;
5410 dnotify_req->filter = filter;
5411 dnotify_req->multishot = multishot;
5412 spin_lock(&GlobalMid_Lock);
5413 list_add_tail(&dnotify_req->lhead,
5414 &GlobalDnotifyReqList);
5415 spin_unlock(&GlobalMid_Lock);
5419 cifs_buf_release(pSMB);
5423 #ifdef CONFIG_CIFS_XATTR
5425 * Do a path-based QUERY_ALL_EAS call and parse the result. This is a common
5426 * function used by listxattr and getxattr type calls. When ea_name is set,
5427 * it looks for that attribute name and stuffs that value into the EAData
5428 * buffer. When ea_name is NULL, it stuffs a list of attribute names into the
5429 * buffer. In both cases, the return value is either the length of the
5430 * resulting data or a negative error code. If EAData is a NULL pointer then
5431 * the data isn't copied to it, but the length is returned.
5434 CIFSSMBQAllEAs(const int xid, struct cifsTconInfo *tcon,
5435 const unsigned char *searchName, const unsigned char *ea_name,
5436 char *EAData, size_t buf_size,
5437 const struct nls_table *nls_codepage, int remap)
5439 /* BB assumes one setup word */
5440 TRANSACTION2_QPI_REQ *pSMB = NULL;
5441 TRANSACTION2_QPI_RSP *pSMBr = NULL;
5445 struct fealist *ea_response_data;
5446 struct fea *temp_fea;
5449 __u16 params, byte_count, data_offset;
5451 cFYI(1, ("In Query All EAs path %s", searchName));
5453 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5458 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5460 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
5461 PATH_MAX, nls_codepage, remap);
5462 list_len++; /* trailing null */
5464 } else { /* BB improve the check for buffer overruns BB */
5465 list_len = strnlen(searchName, PATH_MAX);
5466 list_len++; /* trailing null */
5467 strncpy(pSMB->FileName, searchName, list_len);
5470 params = 2 /* level */ + 4 /* reserved */ + list_len /* includes NUL */;
5471 pSMB->TotalDataCount = 0;
5472 pSMB->MaxParameterCount = cpu_to_le16(2);
5473 /* BB find exact max SMB PDU from sess structure BB */
5474 pSMB->MaxDataCount = cpu_to_le16(CIFSMaxBufSize);
5475 pSMB->MaxSetupCount = 0;
5479 pSMB->Reserved2 = 0;
5480 pSMB->ParameterOffset = cpu_to_le16(offsetof(
5481 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
5482 pSMB->DataCount = 0;
5483 pSMB->DataOffset = 0;
5484 pSMB->SetupCount = 1;
5485 pSMB->Reserved3 = 0;
5486 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
5487 byte_count = params + 1 /* pad */ ;
5488 pSMB->TotalParameterCount = cpu_to_le16(params);
5489 pSMB->ParameterCount = pSMB->TotalParameterCount;
5490 pSMB->InformationLevel = cpu_to_le16(SMB_INFO_QUERY_ALL_EAS);
5491 pSMB->Reserved4 = 0;
5492 pSMB->hdr.smb_buf_length += byte_count;
5493 pSMB->ByteCount = cpu_to_le16(byte_count);
5495 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5496 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5498 cFYI(1, ("Send error in QueryAllEAs = %d", rc));
5503 /* BB also check enough total bytes returned */
5504 /* BB we need to improve the validity checking
5505 of these trans2 responses */
5507 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
5508 if (rc || (pSMBr->ByteCount < 4)) {
5509 rc = -EIO; /* bad smb */
5513 /* check that length of list is not more than bcc */
5514 /* check that each entry does not go beyond length
5516 /* check that each element of each entry does not
5517 go beyond end of list */
5518 /* validate_trans2_offsets() */
5519 /* BB check if start of smb + data_offset > &bcc+ bcc */
5521 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
5522 ea_response_data = (struct fealist *)
5523 (((char *) &pSMBr->hdr.Protocol) + data_offset);
5525 list_len = le32_to_cpu(ea_response_data->list_len);
5526 cFYI(1, ("ea length %d", list_len));
5527 if (list_len <= 8) {
5528 cFYI(1, ("empty EA list returned from server"));
5532 /* make sure list_len doesn't go past end of SMB */
5533 end_of_smb = (char *)pByteArea(&pSMBr->hdr) + BCC(&pSMBr->hdr);
5534 if ((char *)ea_response_data + list_len > end_of_smb) {
5535 cFYI(1, ("EA list appears to go beyond SMB"));
5540 /* account for ea list len */
5542 temp_fea = ea_response_data->list;
5543 temp_ptr = (char *)temp_fea;
5544 while (list_len > 0) {
5545 unsigned int name_len;
5550 /* make sure we can read name_len and value_len */
5552 cFYI(1, ("EA entry goes beyond length of list"));
5557 name_len = temp_fea->name_len;
5558 value_len = le16_to_cpu(temp_fea->value_len);
5559 list_len -= name_len + 1 + value_len;
5561 cFYI(1, ("EA entry goes beyond length of list"));
5567 if (strncmp(ea_name, temp_ptr, name_len) == 0) {
5568 temp_ptr += name_len + 1;
5572 if ((size_t)value_len > buf_size) {
5576 memcpy(EAData, temp_ptr, value_len);
5580 /* account for prefix user. and trailing null */
5581 rc += (5 + 1 + name_len);
5582 if (rc < (int) buf_size) {
5583 memcpy(EAData, "user.", 5);
5585 memcpy(EAData, temp_ptr, name_len);
5587 /* null terminate name */
5590 } else if (buf_size == 0) {
5591 /* skip copy - calc size only */
5593 /* stop before overrun buffer */
5598 temp_ptr += name_len + 1 + value_len;
5599 temp_fea = (struct fea *)temp_ptr;
5602 /* didn't find the named attribute */
5607 cifs_buf_release(pSMB);
5615 CIFSSMBSetEA(const int xid, struct cifsTconInfo *tcon, const char *fileName,
5616 const char *ea_name, const void *ea_value,
5617 const __u16 ea_value_len, const struct nls_table *nls_codepage,
5620 struct smb_com_transaction2_spi_req *pSMB = NULL;
5621 struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
5622 struct fealist *parm_data;
5625 int bytes_returned = 0;
5626 __u16 params, param_offset, byte_count, offset, count;
5628 cFYI(1, ("In SetEA"));
5630 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5635 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5637 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
5638 PATH_MAX, nls_codepage, remap);
5639 name_len++; /* trailing null */
5641 } else { /* BB improve the check for buffer overruns BB */
5642 name_len = strnlen(fileName, PATH_MAX);
5643 name_len++; /* trailing null */
5644 strncpy(pSMB->FileName, fileName, name_len);
5647 params = 6 + name_len;
5649 /* done calculating parms using name_len of file name,
5650 now use name_len to calculate length of ea name
5651 we are going to create in the inode xattrs */
5652 if (ea_name == NULL)
5655 name_len = strnlen(ea_name, 255);
5657 count = sizeof(*parm_data) + ea_value_len + name_len;
5658 pSMB->MaxParameterCount = cpu_to_le16(2);
5659 /* BB find max SMB PDU from sess */
5660 pSMB->MaxDataCount = cpu_to_le16(1000);
5661 pSMB->MaxSetupCount = 0;
5665 pSMB->Reserved2 = 0;
5666 param_offset = offsetof(struct smb_com_transaction2_spi_req,
5667 InformationLevel) - 4;
5668 offset = param_offset + params;
5669 pSMB->InformationLevel =
5670 cpu_to_le16(SMB_SET_FILE_EA);
5673 (struct fealist *) (((char *) &pSMB->hdr.Protocol) +
5675 pSMB->ParameterOffset = cpu_to_le16(param_offset);
5676 pSMB->DataOffset = cpu_to_le16(offset);
5677 pSMB->SetupCount = 1;
5678 pSMB->Reserved3 = 0;
5679 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
5680 byte_count = 3 /* pad */ + params + count;
5681 pSMB->DataCount = cpu_to_le16(count);
5682 parm_data->list_len = cpu_to_le32(count);
5683 parm_data->list[0].EA_flags = 0;
5684 /* we checked above that name len is less than 255 */
5685 parm_data->list[0].name_len = (__u8)name_len;
5686 /* EA names are always ASCII */
5688 strncpy(parm_data->list[0].name, ea_name, name_len);
5689 parm_data->list[0].name[name_len] = 0;
5690 parm_data->list[0].value_len = cpu_to_le16(ea_value_len);
5691 /* caller ensures that ea_value_len is less than 64K but
5692 we need to ensure that it fits within the smb */
5694 /*BB add length check to see if it would fit in
5695 negotiated SMB buffer size BB */
5696 /* if (ea_value_len > buffer_size - 512 (enough for header)) */
5698 memcpy(parm_data->list[0].name+name_len+1,
5699 ea_value, ea_value_len);
5701 pSMB->TotalDataCount = pSMB->DataCount;
5702 pSMB->ParameterCount = cpu_to_le16(params);
5703 pSMB->TotalParameterCount = pSMB->ParameterCount;
5704 pSMB->Reserved4 = 0;
5705 pSMB->hdr.smb_buf_length += byte_count;
5706 pSMB->ByteCount = cpu_to_le16(byte_count);
5707 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5708 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5710 cFYI(1, ("SetPathInfo (EA) returned %d", rc));
5712 cifs_buf_release(pSMB);