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 cifs_buf_release(pSMB);
1525 /* Note: On -EAGAIN error only caller can retry on handle based calls
1526 since file handle passed in no longer valid */
1532 CIFSSMBWrite2(const int xid, struct cifsTconInfo *tcon,
1533 const int netfid, const unsigned int count,
1534 const __u64 offset, unsigned int *nbytes, struct kvec *iov,
1535 int n_vec, const int long_op)
1538 WRITE_REQ *pSMB = NULL;
1541 int resp_buf_type = 0;
1545 cFYI(1, ("write2 at %lld %d bytes", (long long)offset, count));
1547 if (tcon->ses->capabilities & CAP_LARGE_FILES) {
1551 if ((offset >> 32) > 0) {
1552 /* can not handle big offset for old srv */
1556 rc = small_smb_init(SMB_COM_WRITE_ANDX, wct, tcon, (void **) &pSMB);
1559 /* tcon and ses pointer are checked in smb_init */
1560 if (tcon->ses->server == NULL)
1561 return -ECONNABORTED;
1563 pSMB->AndXCommand = 0xFF; /* none */
1565 pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF);
1567 pSMB->OffsetHigh = cpu_to_le32(offset >> 32);
1568 pSMB->Reserved = 0xFFFFFFFF;
1569 pSMB->WriteMode = 0;
1570 pSMB->Remaining = 0;
1573 cpu_to_le16(offsetof(struct smb_com_write_req, Data) - 4);
1575 pSMB->DataLengthLow = cpu_to_le16(count & 0xFFFF);
1576 pSMB->DataLengthHigh = cpu_to_le16(count >> 16);
1577 smb_hdr_len = pSMB->hdr.smb_buf_length + 1; /* hdr + 1 byte pad */
1579 pSMB->hdr.smb_buf_length += count+1;
1580 else /* wct == 12 */
1581 pSMB->hdr.smb_buf_length += count+5; /* smb data starts later */
1583 pSMB->ByteCount = cpu_to_le16(count + 1);
1584 else /* wct == 12 */ /* bigger pad, smaller smb hdr, keep offset ok */ {
1585 struct smb_com_writex_req *pSMBW =
1586 (struct smb_com_writex_req *)pSMB;
1587 pSMBW->ByteCount = cpu_to_le16(count + 5);
1589 iov[0].iov_base = pSMB;
1591 iov[0].iov_len = smb_hdr_len + 4;
1592 else /* wct == 12 pad bigger by four bytes */
1593 iov[0].iov_len = smb_hdr_len + 8;
1596 rc = SendReceive2(xid, tcon->ses, iov, n_vec + 1, &resp_buf_type,
1598 cifs_stats_inc(&tcon->num_writes);
1600 cFYI(1, ("Send error Write2 = %d", rc));
1601 } else if (resp_buf_type == 0) {
1602 /* presumably this can not happen, but best to be safe */
1605 WRITE_RSP *pSMBr = (WRITE_RSP *)iov[0].iov_base;
1606 *nbytes = le16_to_cpu(pSMBr->CountHigh);
1607 *nbytes = (*nbytes) << 16;
1608 *nbytes += le16_to_cpu(pSMBr->Count);
1611 /* cifs_small_buf_release(pSMB); */ /* Freed earlier now in SendReceive2 */
1612 if (resp_buf_type == CIFS_SMALL_BUFFER)
1613 cifs_small_buf_release(iov[0].iov_base);
1614 else if (resp_buf_type == CIFS_LARGE_BUFFER)
1615 cifs_buf_release(iov[0].iov_base);
1617 /* Note: On -EAGAIN error only caller can retry on handle based calls
1618 since file handle passed in no longer valid */
1625 CIFSSMBLock(const int xid, struct cifsTconInfo *tcon,
1626 const __u16 smb_file_id, const __u64 len,
1627 const __u64 offset, const __u32 numUnlock,
1628 const __u32 numLock, const __u8 lockType, const bool waitFlag)
1631 LOCK_REQ *pSMB = NULL;
1632 /* LOCK_RSP *pSMBr = NULL; */ /* No response data other than rc to parse */
1637 cFYI(1, ("CIFSSMBLock timeout %d numLock %d", (int)waitFlag, numLock));
1638 rc = small_smb_init(SMB_COM_LOCKING_ANDX, 8, tcon, (void **) &pSMB);
1643 if (lockType == LOCKING_ANDX_OPLOCK_RELEASE) {
1644 timeout = CIFS_ASYNC_OP; /* no response expected */
1646 } else if (waitFlag) {
1647 timeout = CIFS_BLOCKING_OP; /* blocking operation, no timeout */
1648 pSMB->Timeout = cpu_to_le32(-1);/* blocking - do not time out */
1653 pSMB->NumberOfLocks = cpu_to_le16(numLock);
1654 pSMB->NumberOfUnlocks = cpu_to_le16(numUnlock);
1655 pSMB->LockType = lockType;
1656 pSMB->AndXCommand = 0xFF; /* none */
1657 pSMB->Fid = smb_file_id; /* netfid stays le */
1659 if ((numLock != 0) || (numUnlock != 0)) {
1660 pSMB->Locks[0].Pid = cpu_to_le16(current->tgid);
1661 /* BB where to store pid high? */
1662 pSMB->Locks[0].LengthLow = cpu_to_le32((u32)len);
1663 pSMB->Locks[0].LengthHigh = cpu_to_le32((u32)(len>>32));
1664 pSMB->Locks[0].OffsetLow = cpu_to_le32((u32)offset);
1665 pSMB->Locks[0].OffsetHigh = cpu_to_le32((u32)(offset>>32));
1666 count = sizeof(LOCKING_ANDX_RANGE);
1671 pSMB->hdr.smb_buf_length += count;
1672 pSMB->ByteCount = cpu_to_le16(count);
1675 rc = SendReceiveBlockingLock(xid, tcon, (struct smb_hdr *) pSMB,
1676 (struct smb_hdr *) pSMB, &bytes_returned);
1677 cifs_small_buf_release(pSMB);
1679 rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *)pSMB,
1681 /* SMB buffer freed by function above */
1683 cifs_stats_inc(&tcon->num_locks);
1685 cFYI(1, ("Send error in Lock = %d", rc));
1687 /* Note: On -EAGAIN error only caller can retry on handle based calls
1688 since file handle passed in no longer valid */
1693 CIFSSMBPosixLock(const int xid, struct cifsTconInfo *tcon,
1694 const __u16 smb_file_id, const int get_flag, const __u64 len,
1695 struct file_lock *pLockData, const __u16 lock_type,
1696 const bool waitFlag)
1698 struct smb_com_transaction2_sfi_req *pSMB = NULL;
1699 struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
1700 struct cifs_posix_lock *parm_data;
1703 int bytes_returned = 0;
1704 int resp_buf_type = 0;
1705 __u16 params, param_offset, offset, byte_count, count;
1708 cFYI(1, ("Posix Lock"));
1710 if (pLockData == NULL)
1713 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
1718 pSMBr = (struct smb_com_transaction2_sfi_rsp *)pSMB;
1721 pSMB->MaxSetupCount = 0;
1724 pSMB->Reserved2 = 0;
1725 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
1726 offset = param_offset + params;
1728 count = sizeof(struct cifs_posix_lock);
1729 pSMB->MaxParameterCount = cpu_to_le16(2);
1730 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB from sess */
1731 pSMB->SetupCount = 1;
1732 pSMB->Reserved3 = 0;
1734 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION);
1736 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
1737 byte_count = 3 /* pad */ + params + count;
1738 pSMB->DataCount = cpu_to_le16(count);
1739 pSMB->ParameterCount = cpu_to_le16(params);
1740 pSMB->TotalDataCount = pSMB->DataCount;
1741 pSMB->TotalParameterCount = pSMB->ParameterCount;
1742 pSMB->ParameterOffset = cpu_to_le16(param_offset);
1743 parm_data = (struct cifs_posix_lock *)
1744 (((char *) &pSMB->hdr.Protocol) + offset);
1746 parm_data->lock_type = cpu_to_le16(lock_type);
1748 timeout = CIFS_BLOCKING_OP; /* blocking operation, no timeout */
1749 parm_data->lock_flags = cpu_to_le16(1);
1750 pSMB->Timeout = cpu_to_le32(-1);
1754 parm_data->pid = cpu_to_le32(current->tgid);
1755 parm_data->start = cpu_to_le64(pLockData->fl_start);
1756 parm_data->length = cpu_to_le64(len); /* normalize negative numbers */
1758 pSMB->DataOffset = cpu_to_le16(offset);
1759 pSMB->Fid = smb_file_id;
1760 pSMB->InformationLevel = cpu_to_le16(SMB_SET_POSIX_LOCK);
1761 pSMB->Reserved4 = 0;
1762 pSMB->hdr.smb_buf_length += byte_count;
1763 pSMB->ByteCount = cpu_to_le16(byte_count);
1765 rc = SendReceiveBlockingLock(xid, tcon, (struct smb_hdr *) pSMB,
1766 (struct smb_hdr *) pSMBr, &bytes_returned);
1768 iov[0].iov_base = (char *)pSMB;
1769 iov[0].iov_len = pSMB->hdr.smb_buf_length + 4;
1770 rc = SendReceive2(xid, tcon->ses, iov, 1 /* num iovecs */,
1771 &resp_buf_type, timeout);
1772 pSMB = NULL; /* request buf already freed by SendReceive2. Do
1773 not try to free it twice below on exit */
1774 pSMBr = (struct smb_com_transaction2_sfi_rsp *)iov[0].iov_base;
1778 cFYI(1, ("Send error in Posix Lock = %d", rc));
1779 } else if (get_flag) {
1780 /* lock structure can be returned on get */
1783 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
1785 if (rc || (pSMBr->ByteCount < sizeof(struct cifs_posix_lock))) {
1786 rc = -EIO; /* bad smb */
1789 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
1790 data_count = le16_to_cpu(pSMBr->t2.DataCount);
1791 if (data_count < sizeof(struct cifs_posix_lock)) {
1795 parm_data = (struct cifs_posix_lock *)
1796 ((char *)&pSMBr->hdr.Protocol + data_offset);
1797 if (parm_data->lock_type == cpu_to_le16(CIFS_UNLCK))
1798 pLockData->fl_type = F_UNLCK;
1803 cifs_small_buf_release(pSMB);
1805 if (resp_buf_type == CIFS_SMALL_BUFFER)
1806 cifs_small_buf_release(iov[0].iov_base);
1807 else if (resp_buf_type == CIFS_LARGE_BUFFER)
1808 cifs_buf_release(iov[0].iov_base);
1810 /* Note: On -EAGAIN error only caller can retry on handle based calls
1811 since file handle passed in no longer valid */
1818 CIFSSMBClose(const int xid, struct cifsTconInfo *tcon, int smb_file_id)
1821 CLOSE_REQ *pSMB = NULL;
1822 cFYI(1, ("In CIFSSMBClose"));
1824 /* do not retry on dead session on close */
1825 rc = small_smb_init(SMB_COM_CLOSE, 3, tcon, (void **) &pSMB);
1831 pSMB->FileID = (__u16) smb_file_id;
1832 pSMB->LastWriteTime = 0xFFFFFFFF;
1833 pSMB->ByteCount = 0;
1834 rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0);
1835 cifs_stats_inc(&tcon->num_closes);
1838 /* EINTR is expected when user ctl-c to kill app */
1839 cERROR(1, ("Send error in Close = %d", rc));
1843 /* Since session is dead, file will be closed on server already */
1851 CIFSSMBFlush(const int xid, struct cifsTconInfo *tcon, int smb_file_id)
1854 FLUSH_REQ *pSMB = NULL;
1855 cFYI(1, ("In CIFSSMBFlush"));
1857 rc = small_smb_init(SMB_COM_FLUSH, 1, tcon, (void **) &pSMB);
1861 pSMB->FileID = (__u16) smb_file_id;
1862 pSMB->ByteCount = 0;
1863 rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0);
1864 cifs_stats_inc(&tcon->num_flushes);
1866 cERROR(1, ("Send error in Flush = %d", rc));
1872 CIFSSMBRename(const int xid, struct cifsTconInfo *tcon,
1873 const char *fromName, const char *toName,
1874 const struct nls_table *nls_codepage, int remap)
1877 RENAME_REQ *pSMB = NULL;
1878 RENAME_RSP *pSMBr = NULL;
1880 int name_len, name_len2;
1883 cFYI(1, ("In CIFSSMBRename"));
1885 rc = smb_init(SMB_COM_RENAME, 1, tcon, (void **) &pSMB,
1890 pSMB->BufferFormat = 0x04;
1891 pSMB->SearchAttributes =
1892 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
1895 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1897 cifsConvertToUCS((__le16 *) pSMB->OldFileName, fromName,
1898 PATH_MAX, nls_codepage, remap);
1899 name_len++; /* trailing null */
1901 pSMB->OldFileName[name_len] = 0x04; /* pad */
1902 /* protocol requires ASCII signature byte on Unicode string */
1903 pSMB->OldFileName[name_len + 1] = 0x00;
1905 cifsConvertToUCS((__le16 *)&pSMB->OldFileName[name_len + 2],
1906 toName, PATH_MAX, nls_codepage, remap);
1907 name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
1908 name_len2 *= 2; /* convert to bytes */
1909 } else { /* BB improve the check for buffer overruns BB */
1910 name_len = strnlen(fromName, PATH_MAX);
1911 name_len++; /* trailing null */
1912 strncpy(pSMB->OldFileName, fromName, name_len);
1913 name_len2 = strnlen(toName, PATH_MAX);
1914 name_len2++; /* trailing null */
1915 pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */
1916 strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2);
1917 name_len2++; /* trailing null */
1918 name_len2++; /* signature byte */
1921 count = 1 /* 1st signature byte */ + name_len + name_len2;
1922 pSMB->hdr.smb_buf_length += count;
1923 pSMB->ByteCount = cpu_to_le16(count);
1925 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1926 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1927 cifs_stats_inc(&tcon->num_renames);
1929 cFYI(1, ("Send error in rename = %d", rc));
1931 cifs_buf_release(pSMB);
1939 int CIFSSMBRenameOpenFile(const int xid, struct cifsTconInfo *pTcon,
1940 int netfid, const char *target_name,
1941 const struct nls_table *nls_codepage, int remap)
1943 struct smb_com_transaction2_sfi_req *pSMB = NULL;
1944 struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
1945 struct set_file_rename *rename_info;
1947 char dummy_string[30];
1949 int bytes_returned = 0;
1951 __u16 params, param_offset, offset, count, byte_count;
1953 cFYI(1, ("Rename to File by handle"));
1954 rc = smb_init(SMB_COM_TRANSACTION2, 15, pTcon, (void **) &pSMB,
1960 pSMB->MaxSetupCount = 0;
1964 pSMB->Reserved2 = 0;
1965 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
1966 offset = param_offset + params;
1968 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
1969 rename_info = (struct set_file_rename *) data_offset;
1970 pSMB->MaxParameterCount = cpu_to_le16(2);
1971 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB from sess */
1972 pSMB->SetupCount = 1;
1973 pSMB->Reserved3 = 0;
1974 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
1975 byte_count = 3 /* pad */ + params;
1976 pSMB->ParameterCount = cpu_to_le16(params);
1977 pSMB->TotalParameterCount = pSMB->ParameterCount;
1978 pSMB->ParameterOffset = cpu_to_le16(param_offset);
1979 pSMB->DataOffset = cpu_to_le16(offset);
1980 /* construct random name ".cifs_tmp<inodenum><mid>" */
1981 rename_info->overwrite = cpu_to_le32(1);
1982 rename_info->root_fid = 0;
1983 /* unicode only call */
1984 if (target_name == NULL) {
1985 sprintf(dummy_string, "cifs%x", pSMB->hdr.Mid);
1986 len_of_str = cifsConvertToUCS((__le16 *)rename_info->target_name,
1987 dummy_string, 24, nls_codepage, remap);
1989 len_of_str = cifsConvertToUCS((__le16 *)rename_info->target_name,
1990 target_name, PATH_MAX, nls_codepage,
1993 rename_info->target_name_len = cpu_to_le32(2 * len_of_str);
1994 count = 12 /* sizeof(struct set_file_rename) */ + (2 * len_of_str);
1995 byte_count += count;
1996 pSMB->DataCount = cpu_to_le16(count);
1997 pSMB->TotalDataCount = pSMB->DataCount;
1999 pSMB->InformationLevel =
2000 cpu_to_le16(SMB_SET_FILE_RENAME_INFORMATION);
2001 pSMB->Reserved4 = 0;
2002 pSMB->hdr.smb_buf_length += byte_count;
2003 pSMB->ByteCount = cpu_to_le16(byte_count);
2004 rc = SendReceive(xid, pTcon->ses, (struct smb_hdr *) pSMB,
2005 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2006 cifs_stats_inc(&pTcon->num_t2renames);
2008 cFYI(1, ("Send error in Rename (by file handle) = %d", rc));
2010 cifs_buf_release(pSMB);
2012 /* Note: On -EAGAIN error only caller can retry on handle based calls
2013 since file handle passed in no longer valid */
2019 CIFSSMBCopy(const int xid, struct cifsTconInfo *tcon, const char *fromName,
2020 const __u16 target_tid, const char *toName, const int flags,
2021 const struct nls_table *nls_codepage, int remap)
2024 COPY_REQ *pSMB = NULL;
2025 COPY_RSP *pSMBr = NULL;
2027 int name_len, name_len2;
2030 cFYI(1, ("In CIFSSMBCopy"));
2032 rc = smb_init(SMB_COM_COPY, 1, tcon, (void **) &pSMB,
2037 pSMB->BufferFormat = 0x04;
2038 pSMB->Tid2 = target_tid;
2040 pSMB->Flags = cpu_to_le16(flags & COPY_TREE);
2042 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2043 name_len = cifsConvertToUCS((__le16 *) pSMB->OldFileName,
2044 fromName, PATH_MAX, nls_codepage,
2046 name_len++; /* trailing null */
2048 pSMB->OldFileName[name_len] = 0x04; /* pad */
2049 /* protocol requires ASCII signature byte on Unicode string */
2050 pSMB->OldFileName[name_len + 1] = 0x00;
2052 cifsConvertToUCS((__le16 *)&pSMB->OldFileName[name_len + 2],
2053 toName, PATH_MAX, nls_codepage, remap);
2054 name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
2055 name_len2 *= 2; /* convert to bytes */
2056 } else { /* BB improve the check for buffer overruns BB */
2057 name_len = strnlen(fromName, PATH_MAX);
2058 name_len++; /* trailing null */
2059 strncpy(pSMB->OldFileName, fromName, name_len);
2060 name_len2 = strnlen(toName, PATH_MAX);
2061 name_len2++; /* trailing null */
2062 pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */
2063 strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2);
2064 name_len2++; /* trailing null */
2065 name_len2++; /* signature byte */
2068 count = 1 /* 1st signature byte */ + name_len + name_len2;
2069 pSMB->hdr.smb_buf_length += count;
2070 pSMB->ByteCount = cpu_to_le16(count);
2072 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2073 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2075 cFYI(1, ("Send error in copy = %d with %d files copied",
2076 rc, le16_to_cpu(pSMBr->CopyCount)));
2078 cifs_buf_release(pSMB);
2087 CIFSUnixCreateSymLink(const int xid, struct cifsTconInfo *tcon,
2088 const char *fromName, const char *toName,
2089 const struct nls_table *nls_codepage)
2091 TRANSACTION2_SPI_REQ *pSMB = NULL;
2092 TRANSACTION2_SPI_RSP *pSMBr = NULL;
2095 int name_len_target;
2097 int bytes_returned = 0;
2098 __u16 params, param_offset, offset, byte_count;
2100 cFYI(1, ("In Symlink Unix style"));
2102 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2107 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2109 cifs_strtoUCS((__le16 *) pSMB->FileName, fromName, PATH_MAX
2110 /* find define for this maxpathcomponent */
2112 name_len++; /* trailing null */
2115 } else { /* BB improve the check for buffer overruns BB */
2116 name_len = strnlen(fromName, PATH_MAX);
2117 name_len++; /* trailing null */
2118 strncpy(pSMB->FileName, fromName, name_len);
2120 params = 6 + name_len;
2121 pSMB->MaxSetupCount = 0;
2125 pSMB->Reserved2 = 0;
2126 param_offset = offsetof(struct smb_com_transaction2_spi_req,
2127 InformationLevel) - 4;
2128 offset = param_offset + params;
2130 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
2131 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2133 cifs_strtoUCS((__le16 *) data_offset, toName, PATH_MAX
2134 /* find define for this maxpathcomponent */
2136 name_len_target++; /* trailing null */
2137 name_len_target *= 2;
2138 } else { /* BB improve the check for buffer overruns BB */
2139 name_len_target = strnlen(toName, PATH_MAX);
2140 name_len_target++; /* trailing null */
2141 strncpy(data_offset, toName, name_len_target);
2144 pSMB->MaxParameterCount = cpu_to_le16(2);
2145 /* BB find exact max on data count below from sess */
2146 pSMB->MaxDataCount = cpu_to_le16(1000);
2147 pSMB->SetupCount = 1;
2148 pSMB->Reserved3 = 0;
2149 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
2150 byte_count = 3 /* pad */ + params + name_len_target;
2151 pSMB->DataCount = cpu_to_le16(name_len_target);
2152 pSMB->ParameterCount = cpu_to_le16(params);
2153 pSMB->TotalDataCount = pSMB->DataCount;
2154 pSMB->TotalParameterCount = pSMB->ParameterCount;
2155 pSMB->ParameterOffset = cpu_to_le16(param_offset);
2156 pSMB->DataOffset = cpu_to_le16(offset);
2157 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_LINK);
2158 pSMB->Reserved4 = 0;
2159 pSMB->hdr.smb_buf_length += byte_count;
2160 pSMB->ByteCount = cpu_to_le16(byte_count);
2161 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2162 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2163 cifs_stats_inc(&tcon->num_symlinks);
2165 cFYI(1, ("Send error in SetPathInfo create symlink = %d", rc));
2167 cifs_buf_release(pSMB);
2170 goto createSymLinkRetry;
2176 CIFSUnixCreateHardLink(const int xid, struct cifsTconInfo *tcon,
2177 const char *fromName, const char *toName,
2178 const struct nls_table *nls_codepage, int remap)
2180 TRANSACTION2_SPI_REQ *pSMB = NULL;
2181 TRANSACTION2_SPI_RSP *pSMBr = NULL;
2184 int name_len_target;
2186 int bytes_returned = 0;
2187 __u16 params, param_offset, offset, byte_count;
2189 cFYI(1, ("In Create Hard link Unix style"));
2190 createHardLinkRetry:
2191 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2196 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2197 name_len = cifsConvertToUCS((__le16 *) pSMB->FileName, toName,
2198 PATH_MAX, nls_codepage, remap);
2199 name_len++; /* trailing null */
2202 } else { /* BB improve the check for buffer overruns BB */
2203 name_len = strnlen(toName, PATH_MAX);
2204 name_len++; /* trailing null */
2205 strncpy(pSMB->FileName, toName, name_len);
2207 params = 6 + name_len;
2208 pSMB->MaxSetupCount = 0;
2212 pSMB->Reserved2 = 0;
2213 param_offset = offsetof(struct smb_com_transaction2_spi_req,
2214 InformationLevel) - 4;
2215 offset = param_offset + params;
2217 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
2218 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2220 cifsConvertToUCS((__le16 *) data_offset, fromName, PATH_MAX,
2221 nls_codepage, remap);
2222 name_len_target++; /* trailing null */
2223 name_len_target *= 2;
2224 } else { /* BB improve the check for buffer overruns BB */
2225 name_len_target = strnlen(fromName, PATH_MAX);
2226 name_len_target++; /* trailing null */
2227 strncpy(data_offset, fromName, name_len_target);
2230 pSMB->MaxParameterCount = cpu_to_le16(2);
2231 /* BB find exact max on data count below from sess*/
2232 pSMB->MaxDataCount = cpu_to_le16(1000);
2233 pSMB->SetupCount = 1;
2234 pSMB->Reserved3 = 0;
2235 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
2236 byte_count = 3 /* pad */ + params + name_len_target;
2237 pSMB->ParameterCount = cpu_to_le16(params);
2238 pSMB->TotalParameterCount = pSMB->ParameterCount;
2239 pSMB->DataCount = cpu_to_le16(name_len_target);
2240 pSMB->TotalDataCount = pSMB->DataCount;
2241 pSMB->ParameterOffset = cpu_to_le16(param_offset);
2242 pSMB->DataOffset = cpu_to_le16(offset);
2243 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_HLINK);
2244 pSMB->Reserved4 = 0;
2245 pSMB->hdr.smb_buf_length += byte_count;
2246 pSMB->ByteCount = cpu_to_le16(byte_count);
2247 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2248 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2249 cifs_stats_inc(&tcon->num_hardlinks);
2251 cFYI(1, ("Send error in SetPathInfo (hard link) = %d", rc));
2253 cifs_buf_release(pSMB);
2255 goto createHardLinkRetry;
2261 CIFSCreateHardLink(const int xid, struct cifsTconInfo *tcon,
2262 const char *fromName, const char *toName,
2263 const struct nls_table *nls_codepage, int remap)
2266 NT_RENAME_REQ *pSMB = NULL;
2267 RENAME_RSP *pSMBr = NULL;
2269 int name_len, name_len2;
2272 cFYI(1, ("In CIFSCreateHardLink"));
2273 winCreateHardLinkRetry:
2275 rc = smb_init(SMB_COM_NT_RENAME, 4, tcon, (void **) &pSMB,
2280 pSMB->SearchAttributes =
2281 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
2283 pSMB->Flags = cpu_to_le16(CREATE_HARD_LINK);
2284 pSMB->ClusterCount = 0;
2286 pSMB->BufferFormat = 0x04;
2288 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2290 cifsConvertToUCS((__le16 *) pSMB->OldFileName, fromName,
2291 PATH_MAX, nls_codepage, remap);
2292 name_len++; /* trailing null */
2295 /* protocol specifies ASCII buffer format (0x04) for unicode */
2296 pSMB->OldFileName[name_len] = 0x04;
2297 pSMB->OldFileName[name_len + 1] = 0x00; /* pad */
2299 cifsConvertToUCS((__le16 *)&pSMB->OldFileName[name_len + 2],
2300 toName, PATH_MAX, nls_codepage, remap);
2301 name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
2302 name_len2 *= 2; /* convert to bytes */
2303 } else { /* BB improve the check for buffer overruns BB */
2304 name_len = strnlen(fromName, PATH_MAX);
2305 name_len++; /* trailing null */
2306 strncpy(pSMB->OldFileName, fromName, name_len);
2307 name_len2 = strnlen(toName, PATH_MAX);
2308 name_len2++; /* trailing null */
2309 pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */
2310 strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2);
2311 name_len2++; /* trailing null */
2312 name_len2++; /* signature byte */
2315 count = 1 /* string type byte */ + name_len + name_len2;
2316 pSMB->hdr.smb_buf_length += count;
2317 pSMB->ByteCount = cpu_to_le16(count);
2319 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2320 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2321 cifs_stats_inc(&tcon->num_hardlinks);
2323 cFYI(1, ("Send error in hard link (NT rename) = %d", rc));
2325 cifs_buf_release(pSMB);
2327 goto winCreateHardLinkRetry;
2333 CIFSSMBUnixQuerySymLink(const int xid, struct cifsTconInfo *tcon,
2334 const unsigned char *searchName, char **symlinkinfo,
2335 const struct nls_table *nls_codepage)
2337 /* SMB_QUERY_FILE_UNIX_LINK */
2338 TRANSACTION2_QPI_REQ *pSMB = NULL;
2339 TRANSACTION2_QPI_RSP *pSMBr = NULL;
2343 __u16 params, byte_count;
2346 cFYI(1, ("In QPathSymLinkInfo (Unix) for path %s", searchName));
2349 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2354 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2356 cifs_strtoUCS((__le16 *) pSMB->FileName, searchName,
2357 PATH_MAX, nls_codepage);
2358 name_len++; /* trailing null */
2360 } else { /* BB improve the check for buffer overruns BB */
2361 name_len = strnlen(searchName, PATH_MAX);
2362 name_len++; /* trailing null */
2363 strncpy(pSMB->FileName, searchName, name_len);
2366 params = 2 /* level */ + 4 /* rsrvd */ + name_len /* incl null */ ;
2367 pSMB->TotalDataCount = 0;
2368 pSMB->MaxParameterCount = cpu_to_le16(2);
2369 pSMB->MaxDataCount = cpu_to_le16(CIFSMaxBufSize);
2370 pSMB->MaxSetupCount = 0;
2374 pSMB->Reserved2 = 0;
2375 pSMB->ParameterOffset = cpu_to_le16(offsetof(
2376 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
2377 pSMB->DataCount = 0;
2378 pSMB->DataOffset = 0;
2379 pSMB->SetupCount = 1;
2380 pSMB->Reserved3 = 0;
2381 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
2382 byte_count = params + 1 /* pad */ ;
2383 pSMB->TotalParameterCount = cpu_to_le16(params);
2384 pSMB->ParameterCount = pSMB->TotalParameterCount;
2385 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_LINK);
2386 pSMB->Reserved4 = 0;
2387 pSMB->hdr.smb_buf_length += byte_count;
2388 pSMB->ByteCount = cpu_to_le16(byte_count);
2390 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2391 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2393 cFYI(1, ("Send error in QuerySymLinkInfo = %d", rc));
2395 /* decode response */
2397 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
2398 /* BB also check enough total bytes returned */
2399 if (rc || (pSMBr->ByteCount < 2))
2403 u16 count = le16_to_cpu(pSMBr->t2.DataCount);
2405 data_start = ((char *) &pSMBr->hdr.Protocol) +
2406 le16_to_cpu(pSMBr->t2.DataOffset);
2408 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
2413 /* BB FIXME investigate remapping reserved chars here */
2414 *symlinkinfo = cifs_strndup_from_ucs(data_start, count,
2415 is_unicode, nls_codepage);
2420 cifs_buf_release(pSMB);
2422 goto querySymLinkRetry;
2426 #ifdef CONFIG_CIFS_EXPERIMENTAL
2427 /* Initialize NT TRANSACT SMB into small smb request buffer.
2428 This assumes that all NT TRANSACTS that we init here have
2429 total parm and data under about 400 bytes (to fit in small cifs
2430 buffer size), which is the case so far, it easily fits. NB:
2431 Setup words themselves and ByteCount
2432 MaxSetupCount (size of returned setup area) and
2433 MaxParameterCount (returned parms size) must be set by caller */
2435 smb_init_nttransact(const __u16 sub_command, const int setup_count,
2436 const int parm_len, struct cifsTconInfo *tcon,
2441 struct smb_com_ntransact_req *pSMB;
2443 rc = small_smb_init(SMB_COM_NT_TRANSACT, 19 + setup_count, tcon,
2447 *ret_buf = (void *)pSMB;
2449 pSMB->TotalParameterCount = cpu_to_le32(parm_len);
2450 pSMB->TotalDataCount = 0;
2451 pSMB->MaxDataCount = cpu_to_le32((tcon->ses->server->maxBuf -
2452 MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
2453 pSMB->ParameterCount = pSMB->TotalParameterCount;
2454 pSMB->DataCount = pSMB->TotalDataCount;
2455 temp_offset = offsetof(struct smb_com_ntransact_req, Parms) +
2456 (setup_count * 2) - 4 /* for rfc1001 length itself */;
2457 pSMB->ParameterOffset = cpu_to_le32(temp_offset);
2458 pSMB->DataOffset = cpu_to_le32(temp_offset + parm_len);
2459 pSMB->SetupCount = setup_count; /* no need to le convert byte fields */
2460 pSMB->SubCommand = cpu_to_le16(sub_command);
2465 validate_ntransact(char *buf, char **ppparm, char **ppdata,
2466 __u32 *pparmlen, __u32 *pdatalen)
2469 __u32 data_count, data_offset, parm_count, parm_offset;
2470 struct smb_com_ntransact_rsp *pSMBr;
2478 pSMBr = (struct smb_com_ntransact_rsp *)buf;
2480 /* ByteCount was converted from little endian in SendReceive */
2481 end_of_smb = 2 /* sizeof byte count */ + pSMBr->ByteCount +
2482 (char *)&pSMBr->ByteCount;
2484 data_offset = le32_to_cpu(pSMBr->DataOffset);
2485 data_count = le32_to_cpu(pSMBr->DataCount);
2486 parm_offset = le32_to_cpu(pSMBr->ParameterOffset);
2487 parm_count = le32_to_cpu(pSMBr->ParameterCount);
2489 *ppparm = (char *)&pSMBr->hdr.Protocol + parm_offset;
2490 *ppdata = (char *)&pSMBr->hdr.Protocol + data_offset;
2492 /* should we also check that parm and data areas do not overlap? */
2493 if (*ppparm > end_of_smb) {
2494 cFYI(1, ("parms start after end of smb"));
2496 } else if (parm_count + *ppparm > end_of_smb) {
2497 cFYI(1, ("parm end after end of smb"));
2499 } else if (*ppdata > end_of_smb) {
2500 cFYI(1, ("data starts after end of smb"));
2502 } else if (data_count + *ppdata > end_of_smb) {
2503 cFYI(1, ("data %p + count %d (%p) ends after end of smb %p start %p",
2504 *ppdata, data_count, (data_count + *ppdata),
2505 end_of_smb, pSMBr));
2507 } else if (parm_count + data_count > pSMBr->ByteCount) {
2508 cFYI(1, ("parm count and data count larger than SMB"));
2511 *pdatalen = data_count;
2512 *pparmlen = parm_count;
2517 CIFSSMBQueryReparseLinkInfo(const int xid, struct cifsTconInfo *tcon,
2518 const unsigned char *searchName,
2519 char *symlinkinfo, const int buflen, __u16 fid,
2520 const struct nls_table *nls_codepage)
2524 struct smb_com_transaction_ioctl_req *pSMB;
2525 struct smb_com_transaction_ioctl_rsp *pSMBr;
2527 cFYI(1, ("In Windows reparse style QueryLink for path %s", searchName));
2528 rc = smb_init(SMB_COM_NT_TRANSACT, 23, tcon, (void **) &pSMB,
2533 pSMB->TotalParameterCount = 0 ;
2534 pSMB->TotalDataCount = 0;
2535 pSMB->MaxParameterCount = cpu_to_le32(2);
2536 /* BB find exact data count max from sess structure BB */
2537 pSMB->MaxDataCount = cpu_to_le32((tcon->ses->server->maxBuf -
2538 MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
2539 pSMB->MaxSetupCount = 4;
2541 pSMB->ParameterOffset = 0;
2542 pSMB->DataCount = 0;
2543 pSMB->DataOffset = 0;
2544 pSMB->SetupCount = 4;
2545 pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_IOCTL);
2546 pSMB->ParameterCount = pSMB->TotalParameterCount;
2547 pSMB->FunctionCode = cpu_to_le32(FSCTL_GET_REPARSE_POINT);
2548 pSMB->IsFsctl = 1; /* FSCTL */
2549 pSMB->IsRootFlag = 0;
2550 pSMB->Fid = fid; /* file handle always le */
2551 pSMB->ByteCount = 0;
2553 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2554 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2556 cFYI(1, ("Send error in QueryReparseLinkInfo = %d", rc));
2557 } else { /* decode response */
2558 __u32 data_offset = le32_to_cpu(pSMBr->DataOffset);
2559 __u32 data_count = le32_to_cpu(pSMBr->DataCount);
2560 if ((pSMBr->ByteCount < 2) || (data_offset > 512)) {
2561 /* BB also check enough total bytes returned */
2562 rc = -EIO; /* bad smb */
2565 if (data_count && (data_count < 2048)) {
2566 char *end_of_smb = 2 /* sizeof byte count */ +
2567 pSMBr->ByteCount + (char *)&pSMBr->ByteCount;
2569 struct reparse_data *reparse_buf =
2570 (struct reparse_data *)
2571 ((char *)&pSMBr->hdr.Protocol
2573 if ((char *)reparse_buf >= end_of_smb) {
2577 if ((reparse_buf->LinkNamesBuf +
2578 reparse_buf->TargetNameOffset +
2579 reparse_buf->TargetNameLen) > end_of_smb) {
2580 cFYI(1, ("reparse buf beyond SMB"));
2585 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
2586 cifs_from_ucs2(symlinkinfo, (__le16 *)
2587 (reparse_buf->LinkNamesBuf +
2588 reparse_buf->TargetNameOffset),
2590 reparse_buf->TargetNameLen,
2592 } else { /* ASCII names */
2593 strncpy(symlinkinfo,
2594 reparse_buf->LinkNamesBuf +
2595 reparse_buf->TargetNameOffset,
2596 min_t(const int, buflen,
2597 reparse_buf->TargetNameLen));
2601 cFYI(1, ("Invalid return data count on "
2602 "get reparse info ioctl"));
2604 symlinkinfo[buflen] = 0; /* just in case so the caller
2605 does not go off the end of the buffer */
2606 cFYI(1, ("readlink result - %s", symlinkinfo));
2610 cifs_buf_release(pSMB);
2612 /* Note: On -EAGAIN error only caller can retry on handle based calls
2613 since file handle passed in no longer valid */
2617 #endif /* CIFS_EXPERIMENTAL */
2619 #ifdef CONFIG_CIFS_POSIX
2621 /*Convert an Access Control Entry from wire format to local POSIX xattr format*/
2622 static void cifs_convert_ace(posix_acl_xattr_entry *ace,
2623 struct cifs_posix_ace *cifs_ace)
2625 /* u8 cifs fields do not need le conversion */
2626 ace->e_perm = cpu_to_le16(cifs_ace->cifs_e_perm);
2627 ace->e_tag = cpu_to_le16(cifs_ace->cifs_e_tag);
2628 ace->e_id = cpu_to_le32(le64_to_cpu(cifs_ace->cifs_uid));
2629 /* cFYI(1,("perm %d tag %d id %d",ace->e_perm,ace->e_tag,ace->e_id)); */
2634 /* Convert ACL from CIFS POSIX wire format to local Linux POSIX ACL xattr */
2635 static int cifs_copy_posix_acl(char *trgt, char *src, const int buflen,
2636 const int acl_type, const int size_of_data_area)
2641 struct cifs_posix_ace *pACE;
2642 struct cifs_posix_acl *cifs_acl = (struct cifs_posix_acl *)src;
2643 posix_acl_xattr_header *local_acl = (posix_acl_xattr_header *)trgt;
2645 if (le16_to_cpu(cifs_acl->version) != CIFS_ACL_VERSION)
2648 if (acl_type & ACL_TYPE_ACCESS) {
2649 count = le16_to_cpu(cifs_acl->access_entry_count);
2650 pACE = &cifs_acl->ace_array[0];
2651 size = sizeof(struct cifs_posix_acl);
2652 size += sizeof(struct cifs_posix_ace) * count;
2653 /* check if we would go beyond end of SMB */
2654 if (size_of_data_area < size) {
2655 cFYI(1, ("bad CIFS POSIX ACL size %d vs. %d",
2656 size_of_data_area, size));
2659 } else if (acl_type & ACL_TYPE_DEFAULT) {
2660 count = le16_to_cpu(cifs_acl->access_entry_count);
2661 size = sizeof(struct cifs_posix_acl);
2662 size += sizeof(struct cifs_posix_ace) * count;
2663 /* skip past access ACEs to get to default ACEs */
2664 pACE = &cifs_acl->ace_array[count];
2665 count = le16_to_cpu(cifs_acl->default_entry_count);
2666 size += sizeof(struct cifs_posix_ace) * count;
2667 /* check if we would go beyond end of SMB */
2668 if (size_of_data_area < size)
2675 size = posix_acl_xattr_size(count);
2676 if ((buflen == 0) || (local_acl == NULL)) {
2677 /* used to query ACL EA size */
2678 } else if (size > buflen) {
2680 } else /* buffer big enough */ {
2681 local_acl->a_version = cpu_to_le32(POSIX_ACL_XATTR_VERSION);
2682 for (i = 0; i < count ; i++) {
2683 cifs_convert_ace(&local_acl->a_entries[i], pACE);
2690 static __u16 convert_ace_to_cifs_ace(struct cifs_posix_ace *cifs_ace,
2691 const posix_acl_xattr_entry *local_ace)
2693 __u16 rc = 0; /* 0 = ACL converted ok */
2695 cifs_ace->cifs_e_perm = le16_to_cpu(local_ace->e_perm);
2696 cifs_ace->cifs_e_tag = le16_to_cpu(local_ace->e_tag);
2697 /* BB is there a better way to handle the large uid? */
2698 if (local_ace->e_id == cpu_to_le32(-1)) {
2699 /* Probably no need to le convert -1 on any arch but can not hurt */
2700 cifs_ace->cifs_uid = cpu_to_le64(-1);
2702 cifs_ace->cifs_uid = cpu_to_le64(le32_to_cpu(local_ace->e_id));
2703 /*cFYI(1,("perm %d tag %d id %d",ace->e_perm,ace->e_tag,ace->e_id));*/
2707 /* Convert ACL from local Linux POSIX xattr to CIFS POSIX ACL wire format */
2708 static __u16 ACL_to_cifs_posix(char *parm_data, const char *pACL,
2709 const int buflen, const int acl_type)
2712 struct cifs_posix_acl *cifs_acl = (struct cifs_posix_acl *)parm_data;
2713 posix_acl_xattr_header *local_acl = (posix_acl_xattr_header *)pACL;
2717 if ((buflen == 0) || (pACL == NULL) || (cifs_acl == NULL))
2720 count = posix_acl_xattr_count((size_t)buflen);
2721 cFYI(1, ("setting acl with %d entries from buf of length %d and "
2723 count, buflen, le32_to_cpu(local_acl->a_version)));
2724 if (le32_to_cpu(local_acl->a_version) != 2) {
2725 cFYI(1, ("unknown POSIX ACL version %d",
2726 le32_to_cpu(local_acl->a_version)));
2729 cifs_acl->version = cpu_to_le16(1);
2730 if (acl_type == ACL_TYPE_ACCESS)
2731 cifs_acl->access_entry_count = cpu_to_le16(count);
2732 else if (acl_type == ACL_TYPE_DEFAULT)
2733 cifs_acl->default_entry_count = cpu_to_le16(count);
2735 cFYI(1, ("unknown ACL type %d", acl_type));
2738 for (i = 0; i < count; i++) {
2739 rc = convert_ace_to_cifs_ace(&cifs_acl->ace_array[i],
2740 &local_acl->a_entries[i]);
2742 /* ACE not converted */
2747 rc = (__u16)(count * sizeof(struct cifs_posix_ace));
2748 rc += sizeof(struct cifs_posix_acl);
2749 /* BB add check to make sure ACL does not overflow SMB */
2755 CIFSSMBGetPosixACL(const int xid, struct cifsTconInfo *tcon,
2756 const unsigned char *searchName,
2757 char *acl_inf, const int buflen, const int acl_type,
2758 const struct nls_table *nls_codepage, int remap)
2760 /* SMB_QUERY_POSIX_ACL */
2761 TRANSACTION2_QPI_REQ *pSMB = NULL;
2762 TRANSACTION2_QPI_RSP *pSMBr = NULL;
2766 __u16 params, byte_count;
2768 cFYI(1, ("In GetPosixACL (Unix) for path %s", searchName));
2771 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2776 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2778 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
2779 PATH_MAX, nls_codepage, remap);
2780 name_len++; /* trailing null */
2782 pSMB->FileName[name_len] = 0;
2783 pSMB->FileName[name_len+1] = 0;
2784 } else { /* BB improve the check for buffer overruns BB */
2785 name_len = strnlen(searchName, PATH_MAX);
2786 name_len++; /* trailing null */
2787 strncpy(pSMB->FileName, searchName, name_len);
2790 params = 2 /* level */ + 4 /* rsrvd */ + name_len /* incl null */ ;
2791 pSMB->TotalDataCount = 0;
2792 pSMB->MaxParameterCount = cpu_to_le16(2);
2793 /* BB find exact max data count below from sess structure BB */
2794 pSMB->MaxDataCount = cpu_to_le16(4000);
2795 pSMB->MaxSetupCount = 0;
2799 pSMB->Reserved2 = 0;
2800 pSMB->ParameterOffset = cpu_to_le16(
2801 offsetof(struct smb_com_transaction2_qpi_req,
2802 InformationLevel) - 4);
2803 pSMB->DataCount = 0;
2804 pSMB->DataOffset = 0;
2805 pSMB->SetupCount = 1;
2806 pSMB->Reserved3 = 0;
2807 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
2808 byte_count = params + 1 /* pad */ ;
2809 pSMB->TotalParameterCount = cpu_to_le16(params);
2810 pSMB->ParameterCount = pSMB->TotalParameterCount;
2811 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_POSIX_ACL);
2812 pSMB->Reserved4 = 0;
2813 pSMB->hdr.smb_buf_length += byte_count;
2814 pSMB->ByteCount = cpu_to_le16(byte_count);
2816 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2817 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2818 cifs_stats_inc(&tcon->num_acl_get);
2820 cFYI(1, ("Send error in Query POSIX ACL = %d", rc));
2822 /* decode response */
2824 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
2825 if (rc || (pSMBr->ByteCount < 2))
2826 /* BB also check enough total bytes returned */
2827 rc = -EIO; /* bad smb */
2829 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
2830 __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
2831 rc = cifs_copy_posix_acl(acl_inf,
2832 (char *)&pSMBr->hdr.Protocol+data_offset,
2833 buflen, acl_type, count);
2836 cifs_buf_release(pSMB);
2843 CIFSSMBSetPosixACL(const int xid, struct cifsTconInfo *tcon,
2844 const unsigned char *fileName,
2845 const char *local_acl, const int buflen,
2847 const struct nls_table *nls_codepage, int remap)
2849 struct smb_com_transaction2_spi_req *pSMB = NULL;
2850 struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
2854 int bytes_returned = 0;
2855 __u16 params, byte_count, data_count, param_offset, offset;
2857 cFYI(1, ("In SetPosixACL (Unix) for path %s", fileName));
2859 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2863 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2865 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
2866 PATH_MAX, nls_codepage, remap);
2867 name_len++; /* trailing null */
2869 } else { /* BB improve the check for buffer overruns BB */
2870 name_len = strnlen(fileName, PATH_MAX);
2871 name_len++; /* trailing null */
2872 strncpy(pSMB->FileName, fileName, name_len);
2874 params = 6 + name_len;
2875 pSMB->MaxParameterCount = cpu_to_le16(2);
2876 /* BB find max SMB size from sess */
2877 pSMB->MaxDataCount = cpu_to_le16(1000);
2878 pSMB->MaxSetupCount = 0;
2882 pSMB->Reserved2 = 0;
2883 param_offset = offsetof(struct smb_com_transaction2_spi_req,
2884 InformationLevel) - 4;
2885 offset = param_offset + params;
2886 parm_data = ((char *) &pSMB->hdr.Protocol) + offset;
2887 pSMB->ParameterOffset = cpu_to_le16(param_offset);
2889 /* convert to on the wire format for POSIX ACL */
2890 data_count = ACL_to_cifs_posix(parm_data, local_acl, buflen, acl_type);
2892 if (data_count == 0) {
2894 goto setACLerrorExit;
2896 pSMB->DataOffset = cpu_to_le16(offset);
2897 pSMB->SetupCount = 1;
2898 pSMB->Reserved3 = 0;
2899 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
2900 pSMB->InformationLevel = cpu_to_le16(SMB_SET_POSIX_ACL);
2901 byte_count = 3 /* pad */ + params + data_count;
2902 pSMB->DataCount = cpu_to_le16(data_count);
2903 pSMB->TotalDataCount = pSMB->DataCount;
2904 pSMB->ParameterCount = cpu_to_le16(params);
2905 pSMB->TotalParameterCount = pSMB->ParameterCount;
2906 pSMB->Reserved4 = 0;
2907 pSMB->hdr.smb_buf_length += byte_count;
2908 pSMB->ByteCount = cpu_to_le16(byte_count);
2909 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2910 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2912 cFYI(1, ("Set POSIX ACL returned %d", rc));
2915 cifs_buf_release(pSMB);
2921 /* BB fix tabs in this function FIXME BB */
2923 CIFSGetExtAttr(const int xid, struct cifsTconInfo *tcon,
2924 const int netfid, __u64 *pExtAttrBits, __u64 *pMask)
2927 struct smb_t2_qfi_req *pSMB = NULL;
2928 struct smb_t2_qfi_rsp *pSMBr = NULL;
2930 __u16 params, byte_count;
2932 cFYI(1, ("In GetExtAttr"));
2937 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2942 params = 2 /* level */ + 2 /* fid */;
2943 pSMB->t2.TotalDataCount = 0;
2944 pSMB->t2.MaxParameterCount = cpu_to_le16(4);
2945 /* BB find exact max data count below from sess structure BB */
2946 pSMB->t2.MaxDataCount = cpu_to_le16(4000);
2947 pSMB->t2.MaxSetupCount = 0;
2948 pSMB->t2.Reserved = 0;
2950 pSMB->t2.Timeout = 0;
2951 pSMB->t2.Reserved2 = 0;
2952 pSMB->t2.ParameterOffset = cpu_to_le16(offsetof(struct smb_t2_qfi_req,
2954 pSMB->t2.DataCount = 0;
2955 pSMB->t2.DataOffset = 0;
2956 pSMB->t2.SetupCount = 1;
2957 pSMB->t2.Reserved3 = 0;
2958 pSMB->t2.SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION);
2959 byte_count = params + 1 /* pad */ ;
2960 pSMB->t2.TotalParameterCount = cpu_to_le16(params);
2961 pSMB->t2.ParameterCount = pSMB->t2.TotalParameterCount;
2962 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_ATTR_FLAGS);
2965 pSMB->hdr.smb_buf_length += byte_count;
2966 pSMB->t2.ByteCount = cpu_to_le16(byte_count);
2968 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2969 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2971 cFYI(1, ("error %d in GetExtAttr", rc));
2973 /* decode response */
2974 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
2975 if (rc || (pSMBr->ByteCount < 2))
2976 /* BB also check enough total bytes returned */
2977 /* If rc should we check for EOPNOSUPP and
2978 disable the srvino flag? or in caller? */
2979 rc = -EIO; /* bad smb */
2981 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
2982 __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
2983 struct file_chattr_info *pfinfo;
2984 /* BB Do we need a cast or hash here ? */
2986 cFYI(1, ("Illegal size ret in GetExtAttr"));
2990 pfinfo = (struct file_chattr_info *)
2991 (data_offset + (char *) &pSMBr->hdr.Protocol);
2992 *pExtAttrBits = le64_to_cpu(pfinfo->mode);
2993 *pMask = le64_to_cpu(pfinfo->mask);
2997 cifs_buf_release(pSMB);
2999 goto GetExtAttrRetry;
3003 #endif /* CONFIG_POSIX */
3005 #ifdef CONFIG_CIFS_EXPERIMENTAL
3006 /* Get Security Descriptor (by handle) from remote server for a file or dir */
3008 CIFSSMBGetCIFSACL(const int xid, struct cifsTconInfo *tcon, __u16 fid,
3009 struct cifs_ntsd **acl_inf, __u32 *pbuflen)
3013 QUERY_SEC_DESC_REQ *pSMB;
3016 cFYI(1, ("GetCifsACL"));
3021 rc = smb_init_nttransact(NT_TRANSACT_QUERY_SECURITY_DESC, 0,
3022 8 /* parm len */, tcon, (void **) &pSMB);
3026 pSMB->MaxParameterCount = cpu_to_le32(4);
3027 /* BB TEST with big acls that might need to be e.g. larger than 16K */
3028 pSMB->MaxSetupCount = 0;
3029 pSMB->Fid = fid; /* file handle always le */
3030 pSMB->AclFlags = cpu_to_le32(CIFS_ACL_OWNER | CIFS_ACL_GROUP |
3032 pSMB->ByteCount = cpu_to_le16(11); /* 3 bytes pad + 8 bytes parm */
3033 pSMB->hdr.smb_buf_length += 11;
3034 iov[0].iov_base = (char *)pSMB;
3035 iov[0].iov_len = pSMB->hdr.smb_buf_length + 4;
3037 rc = SendReceive2(xid, tcon->ses, iov, 1 /* num iovec */, &buf_type,
3039 cifs_stats_inc(&tcon->num_acl_get);
3041 cFYI(1, ("Send error in QuerySecDesc = %d", rc));
3042 } else { /* decode response */
3046 struct smb_com_ntransact_rsp *pSMBr;
3049 /* validate_nttransact */
3050 rc = validate_ntransact(iov[0].iov_base, (char **)&parm,
3051 &pdata, &parm_len, pbuflen);
3054 pSMBr = (struct smb_com_ntransact_rsp *)iov[0].iov_base;
3056 cFYI(1, ("smb %p parm %p data %p", pSMBr, parm, *acl_inf));
3058 if (le32_to_cpu(pSMBr->ParameterCount) != 4) {
3059 rc = -EIO; /* bad smb */
3064 /* BB check that data area is minimum length and as big as acl_len */
3066 acl_len = le32_to_cpu(*parm);
3067 if (acl_len != *pbuflen) {
3068 cERROR(1, ("acl length %d does not match %d",
3069 acl_len, *pbuflen));
3070 if (*pbuflen > acl_len)
3074 /* check if buffer is big enough for the acl
3075 header followed by the smallest SID */
3076 if ((*pbuflen < sizeof(struct cifs_ntsd) + 8) ||
3077 (*pbuflen >= 64 * 1024)) {
3078 cERROR(1, ("bad acl length %d", *pbuflen));
3082 *acl_inf = kmalloc(*pbuflen, GFP_KERNEL);
3083 if (*acl_inf == NULL) {
3087 memcpy(*acl_inf, pdata, *pbuflen);
3091 if (buf_type == CIFS_SMALL_BUFFER)
3092 cifs_small_buf_release(iov[0].iov_base);
3093 else if (buf_type == CIFS_LARGE_BUFFER)
3094 cifs_buf_release(iov[0].iov_base);
3095 /* cifs_small_buf_release(pSMB); */ /* Freed earlier now in SendReceive2 */
3100 CIFSSMBSetCIFSACL(const int xid, struct cifsTconInfo *tcon, __u16 fid,
3101 struct cifs_ntsd *pntsd, __u32 acllen)
3103 __u16 byte_count, param_count, data_count, param_offset, data_offset;
3105 int bytes_returned = 0;
3106 SET_SEC_DESC_REQ *pSMB = NULL;
3107 NTRANSACT_RSP *pSMBr = NULL;
3110 rc = smb_init(SMB_COM_NT_TRANSACT, 19, tcon, (void **) &pSMB,
3115 pSMB->MaxSetupCount = 0;
3119 param_offset = offsetof(struct smb_com_transaction_ssec_req, Fid) - 4;
3120 data_count = acllen;
3121 data_offset = param_offset + param_count;
3122 byte_count = 3 /* pad */ + param_count;
3124 pSMB->DataCount = cpu_to_le32(data_count);
3125 pSMB->TotalDataCount = pSMB->DataCount;
3126 pSMB->MaxParameterCount = cpu_to_le32(4);
3127 pSMB->MaxDataCount = cpu_to_le32(16384);
3128 pSMB->ParameterCount = cpu_to_le32(param_count);
3129 pSMB->ParameterOffset = cpu_to_le32(param_offset);
3130 pSMB->TotalParameterCount = pSMB->ParameterCount;
3131 pSMB->DataOffset = cpu_to_le32(data_offset);
3132 pSMB->SetupCount = 0;
3133 pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_SET_SECURITY_DESC);
3134 pSMB->ByteCount = cpu_to_le16(byte_count+data_count);
3136 pSMB->Fid = fid; /* file handle always le */
3137 pSMB->Reserved2 = 0;
3138 pSMB->AclFlags = cpu_to_le32(CIFS_ACL_DACL);
3140 if (pntsd && acllen) {
3141 memcpy((char *) &pSMBr->hdr.Protocol + data_offset,
3144 pSMB->hdr.smb_buf_length += (byte_count + data_count);
3147 pSMB->hdr.smb_buf_length += byte_count;
3149 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3150 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3152 cFYI(1, ("SetCIFSACL bytes_returned: %d, rc: %d", bytes_returned, rc));
3154 cFYI(1, ("Set CIFS ACL returned %d", rc));
3155 cifs_buf_release(pSMB);
3158 goto setCifsAclRetry;
3163 #endif /* CONFIG_CIFS_EXPERIMENTAL */
3165 /* Legacy Query Path Information call for lookup to old servers such
3167 int SMBQueryInformation(const int xid, struct cifsTconInfo *tcon,
3168 const unsigned char *searchName,
3169 FILE_ALL_INFO *pFinfo,
3170 const struct nls_table *nls_codepage, int remap)
3172 QUERY_INFORMATION_REQ *pSMB;
3173 QUERY_INFORMATION_RSP *pSMBr;
3178 cFYI(1, ("In SMBQPath path %s", searchName));
3180 rc = smb_init(SMB_COM_QUERY_INFORMATION, 0, tcon, (void **) &pSMB,
3185 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3187 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
3188 PATH_MAX, nls_codepage, remap);
3189 name_len++; /* trailing null */
3192 name_len = strnlen(searchName, PATH_MAX);
3193 name_len++; /* trailing null */
3194 strncpy(pSMB->FileName, searchName, name_len);
3196 pSMB->BufferFormat = 0x04;
3197 name_len++; /* account for buffer type byte */
3198 pSMB->hdr.smb_buf_length += (__u16) name_len;
3199 pSMB->ByteCount = cpu_to_le16(name_len);
3201 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3202 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3204 cFYI(1, ("Send error in QueryInfo = %d", rc));
3205 } else if (pFinfo) {
3207 __u32 time = le32_to_cpu(pSMBr->last_write_time);
3209 /* decode response */
3210 /* BB FIXME - add time zone adjustment BB */
3211 memset(pFinfo, 0, sizeof(FILE_ALL_INFO));
3214 /* decode time fields */
3215 pFinfo->ChangeTime = cpu_to_le64(cifs_UnixTimeToNT(ts));
3216 pFinfo->LastWriteTime = pFinfo->ChangeTime;
3217 pFinfo->LastAccessTime = 0;
3218 pFinfo->AllocationSize =
3219 cpu_to_le64(le32_to_cpu(pSMBr->size));
3220 pFinfo->EndOfFile = pFinfo->AllocationSize;
3221 pFinfo->Attributes =
3222 cpu_to_le32(le16_to_cpu(pSMBr->attr));
3224 rc = -EIO; /* bad buffer passed in */
3226 cifs_buf_release(pSMB);
3235 CIFSSMBQFileInfo(const int xid, struct cifsTconInfo *tcon,
3236 u16 netfid, FILE_ALL_INFO *pFindData)
3238 struct smb_t2_qfi_req *pSMB = NULL;
3239 struct smb_t2_qfi_rsp *pSMBr = NULL;
3242 __u16 params, byte_count;
3245 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3250 params = 2 /* level */ + 2 /* fid */;
3251 pSMB->t2.TotalDataCount = 0;
3252 pSMB->t2.MaxParameterCount = cpu_to_le16(4);
3253 /* BB find exact max data count below from sess structure BB */
3254 pSMB->t2.MaxDataCount = cpu_to_le16(CIFSMaxBufSize);
3255 pSMB->t2.MaxSetupCount = 0;
3256 pSMB->t2.Reserved = 0;
3258 pSMB->t2.Timeout = 0;
3259 pSMB->t2.Reserved2 = 0;
3260 pSMB->t2.ParameterOffset = cpu_to_le16(offsetof(struct smb_t2_qfi_req,
3262 pSMB->t2.DataCount = 0;
3263 pSMB->t2.DataOffset = 0;
3264 pSMB->t2.SetupCount = 1;
3265 pSMB->t2.Reserved3 = 0;
3266 pSMB->t2.SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION);
3267 byte_count = params + 1 /* pad */ ;
3268 pSMB->t2.TotalParameterCount = cpu_to_le16(params);
3269 pSMB->t2.ParameterCount = pSMB->t2.TotalParameterCount;
3270 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_ALL_INFO);
3273 pSMB->hdr.smb_buf_length += byte_count;
3275 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3276 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3278 cFYI(1, ("Send error in QPathInfo = %d", rc));
3279 } else { /* decode response */
3280 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3282 if (rc) /* BB add auto retry on EOPNOTSUPP? */
3284 else if (pSMBr->ByteCount < 40)
3285 rc = -EIO; /* bad smb */
3286 else if (pFindData) {
3287 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3288 memcpy((char *) pFindData,
3289 (char *) &pSMBr->hdr.Protocol +
3290 data_offset, sizeof(FILE_ALL_INFO));
3294 cifs_buf_release(pSMB);
3296 goto QFileInfoRetry;
3302 CIFSSMBQPathInfo(const int xid, struct cifsTconInfo *tcon,
3303 const unsigned char *searchName,
3304 FILE_ALL_INFO *pFindData,
3305 int legacy /* old style infolevel */,
3306 const struct nls_table *nls_codepage, int remap)
3308 /* level 263 SMB_QUERY_FILE_ALL_INFO */
3309 TRANSACTION2_QPI_REQ *pSMB = NULL;
3310 TRANSACTION2_QPI_RSP *pSMBr = NULL;
3314 __u16 params, byte_count;
3316 /* cFYI(1, ("In QPathInfo path %s", searchName)); */
3318 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3323 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3325 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
3326 PATH_MAX, nls_codepage, remap);
3327 name_len++; /* trailing null */
3329 } else { /* BB improve the check for buffer overruns BB */
3330 name_len = strnlen(searchName, PATH_MAX);
3331 name_len++; /* trailing null */
3332 strncpy(pSMB->FileName, searchName, name_len);
3335 params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */;
3336 pSMB->TotalDataCount = 0;
3337 pSMB->MaxParameterCount = cpu_to_le16(2);
3338 /* BB find exact max SMB PDU from sess structure BB */
3339 pSMB->MaxDataCount = cpu_to_le16(4000);
3340 pSMB->MaxSetupCount = 0;
3344 pSMB->Reserved2 = 0;
3345 pSMB->ParameterOffset = cpu_to_le16(offsetof(
3346 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
3347 pSMB->DataCount = 0;
3348 pSMB->DataOffset = 0;
3349 pSMB->SetupCount = 1;
3350 pSMB->Reserved3 = 0;
3351 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
3352 byte_count = params + 1 /* pad */ ;
3353 pSMB->TotalParameterCount = cpu_to_le16(params);
3354 pSMB->ParameterCount = pSMB->TotalParameterCount;
3356 pSMB->InformationLevel = cpu_to_le16(SMB_INFO_STANDARD);
3358 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_ALL_INFO);
3359 pSMB->Reserved4 = 0;
3360 pSMB->hdr.smb_buf_length += byte_count;
3361 pSMB->ByteCount = cpu_to_le16(byte_count);
3363 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3364 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3366 cFYI(1, ("Send error in QPathInfo = %d", rc));
3367 } else { /* decode response */
3368 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3370 if (rc) /* BB add auto retry on EOPNOTSUPP? */
3372 else if (!legacy && (pSMBr->ByteCount < 40))
3373 rc = -EIO; /* bad smb */
3374 else if (legacy && (pSMBr->ByteCount < 24))
3375 rc = -EIO; /* 24 or 26 expected but we do not read
3377 else if (pFindData) {
3379 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3381 /* On legacy responses we do not read the last field,
3382 EAsize, fortunately since it varies by subdialect and
3383 also note it differs on Set vs. Get, ie two bytes or 4
3384 bytes depending but we don't care here */
3386 size = sizeof(FILE_INFO_STANDARD);
3388 size = sizeof(FILE_ALL_INFO);
3389 memcpy((char *) pFindData,
3390 (char *) &pSMBr->hdr.Protocol +
3395 cifs_buf_release(pSMB);
3397 goto QPathInfoRetry;
3403 CIFSSMBUnixQFileInfo(const int xid, struct cifsTconInfo *tcon,
3404 u16 netfid, FILE_UNIX_BASIC_INFO *pFindData)
3406 struct smb_t2_qfi_req *pSMB = NULL;
3407 struct smb_t2_qfi_rsp *pSMBr = NULL;
3410 __u16 params, byte_count;
3413 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3418 params = 2 /* level */ + 2 /* fid */;
3419 pSMB->t2.TotalDataCount = 0;
3420 pSMB->t2.MaxParameterCount = cpu_to_le16(4);
3421 /* BB find exact max data count below from sess structure BB */
3422 pSMB->t2.MaxDataCount = cpu_to_le16(CIFSMaxBufSize);
3423 pSMB->t2.MaxSetupCount = 0;
3424 pSMB->t2.Reserved = 0;
3426 pSMB->t2.Timeout = 0;
3427 pSMB->t2.Reserved2 = 0;
3428 pSMB->t2.ParameterOffset = cpu_to_le16(offsetof(struct smb_t2_qfi_req,
3430 pSMB->t2.DataCount = 0;
3431 pSMB->t2.DataOffset = 0;
3432 pSMB->t2.SetupCount = 1;
3433 pSMB->t2.Reserved3 = 0;
3434 pSMB->t2.SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION);
3435 byte_count = params + 1 /* pad */ ;
3436 pSMB->t2.TotalParameterCount = cpu_to_le16(params);
3437 pSMB->t2.ParameterCount = pSMB->t2.TotalParameterCount;
3438 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC);
3441 pSMB->hdr.smb_buf_length += byte_count;
3443 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3444 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3446 cFYI(1, ("Send error in QPathInfo = %d", rc));
3447 } else { /* decode response */
3448 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3450 if (rc || (pSMBr->ByteCount < sizeof(FILE_UNIX_BASIC_INFO))) {
3451 cERROR(1, ("Malformed FILE_UNIX_BASIC_INFO response.\n"
3452 "Unix Extensions can be disabled on mount "
3453 "by specifying the nosfu mount option."));
3454 rc = -EIO; /* bad smb */
3456 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3457 memcpy((char *) pFindData,
3458 (char *) &pSMBr->hdr.Protocol +
3460 sizeof(FILE_UNIX_BASIC_INFO));
3464 cifs_buf_release(pSMB);
3466 goto UnixQFileInfoRetry;
3472 CIFSSMBUnixQPathInfo(const int xid, struct cifsTconInfo *tcon,
3473 const unsigned char *searchName,
3474 FILE_UNIX_BASIC_INFO *pFindData,
3475 const struct nls_table *nls_codepage, int remap)
3477 /* SMB_QUERY_FILE_UNIX_BASIC */
3478 TRANSACTION2_QPI_REQ *pSMB = NULL;
3479 TRANSACTION2_QPI_RSP *pSMBr = NULL;
3481 int bytes_returned = 0;
3483 __u16 params, byte_count;
3485 cFYI(1, ("In QPathInfo (Unix) the path %s", searchName));
3487 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3492 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3494 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
3495 PATH_MAX, nls_codepage, remap);
3496 name_len++; /* trailing null */
3498 } else { /* BB improve the check for buffer overruns BB */
3499 name_len = strnlen(searchName, PATH_MAX);
3500 name_len++; /* trailing null */
3501 strncpy(pSMB->FileName, searchName, name_len);
3504 params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */;
3505 pSMB->TotalDataCount = 0;
3506 pSMB->MaxParameterCount = cpu_to_le16(2);
3507 /* BB find exact max SMB PDU from sess structure BB */
3508 pSMB->MaxDataCount = cpu_to_le16(4000);
3509 pSMB->MaxSetupCount = 0;
3513 pSMB->Reserved2 = 0;
3514 pSMB->ParameterOffset = cpu_to_le16(offsetof(
3515 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
3516 pSMB->DataCount = 0;
3517 pSMB->DataOffset = 0;
3518 pSMB->SetupCount = 1;
3519 pSMB->Reserved3 = 0;
3520 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
3521 byte_count = params + 1 /* pad */ ;
3522 pSMB->TotalParameterCount = cpu_to_le16(params);
3523 pSMB->ParameterCount = pSMB->TotalParameterCount;
3524 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC);
3525 pSMB->Reserved4 = 0;
3526 pSMB->hdr.smb_buf_length += byte_count;
3527 pSMB->ByteCount = cpu_to_le16(byte_count);
3529 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3530 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3532 cFYI(1, ("Send error in QPathInfo = %d", rc));
3533 } else { /* decode response */
3534 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3536 if (rc || (pSMBr->ByteCount < sizeof(FILE_UNIX_BASIC_INFO))) {
3537 cERROR(1, ("Malformed FILE_UNIX_BASIC_INFO response.\n"
3538 "Unix Extensions can be disabled on mount "
3539 "by specifying the nosfu mount option."));
3540 rc = -EIO; /* bad smb */
3542 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3543 memcpy((char *) pFindData,
3544 (char *) &pSMBr->hdr.Protocol +
3546 sizeof(FILE_UNIX_BASIC_INFO));
3549 cifs_buf_release(pSMB);
3551 goto UnixQPathInfoRetry;
3556 /* xid, tcon, searchName and codepage are input parms, rest are returned */
3558 CIFSFindFirst(const int xid, struct cifsTconInfo *tcon,
3559 const char *searchName,
3560 const struct nls_table *nls_codepage,
3562 struct cifs_search_info *psrch_inf, int remap, const char dirsep)
3564 /* level 257 SMB_ */
3565 TRANSACTION2_FFIRST_REQ *pSMB = NULL;
3566 TRANSACTION2_FFIRST_RSP *pSMBr = NULL;
3567 T2_FFIRST_RSP_PARMS *parms;
3569 int bytes_returned = 0;
3571 __u16 params, byte_count;
3573 cFYI(1, ("In FindFirst for %s", searchName));
3576 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3581 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3583 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
3584 PATH_MAX, nls_codepage, remap);
3585 /* We can not add the asterik earlier in case
3586 it got remapped to 0xF03A as if it were part of the
3587 directory name instead of a wildcard */
3589 pSMB->FileName[name_len] = dirsep;
3590 pSMB->FileName[name_len+1] = 0;
3591 pSMB->FileName[name_len+2] = '*';
3592 pSMB->FileName[name_len+3] = 0;
3593 name_len += 4; /* now the trailing null */
3594 pSMB->FileName[name_len] = 0; /* null terminate just in case */
3595 pSMB->FileName[name_len+1] = 0;
3597 } else { /* BB add check for overrun of SMB buf BB */
3598 name_len = strnlen(searchName, PATH_MAX);
3599 /* BB fix here and in unicode clause above ie
3600 if (name_len > buffersize-header)
3601 free buffer exit; BB */
3602 strncpy(pSMB->FileName, searchName, name_len);
3603 pSMB->FileName[name_len] = dirsep;
3604 pSMB->FileName[name_len+1] = '*';
3605 pSMB->FileName[name_len+2] = 0;
3609 params = 12 + name_len /* includes null */ ;
3610 pSMB->TotalDataCount = 0; /* no EAs */
3611 pSMB->MaxParameterCount = cpu_to_le16(10);
3612 pSMB->MaxDataCount = cpu_to_le16((tcon->ses->server->maxBuf -
3613 MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
3614 pSMB->MaxSetupCount = 0;
3618 pSMB->Reserved2 = 0;
3619 byte_count = params + 1 /* pad */ ;
3620 pSMB->TotalParameterCount = cpu_to_le16(params);
3621 pSMB->ParameterCount = pSMB->TotalParameterCount;
3622 pSMB->ParameterOffset = cpu_to_le16(
3623 offsetof(struct smb_com_transaction2_ffirst_req, SearchAttributes)
3625 pSMB->DataCount = 0;
3626 pSMB->DataOffset = 0;
3627 pSMB->SetupCount = 1; /* one byte, no need to make endian neutral */
3628 pSMB->Reserved3 = 0;
3629 pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_FIRST);
3630 pSMB->SearchAttributes =
3631 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
3633 pSMB->SearchCount = cpu_to_le16(CIFSMaxBufSize/sizeof(FILE_UNIX_INFO));
3634 pSMB->SearchFlags = cpu_to_le16(CIFS_SEARCH_CLOSE_AT_END |
3635 CIFS_SEARCH_RETURN_RESUME);
3636 pSMB->InformationLevel = cpu_to_le16(psrch_inf->info_level);
3638 /* BB what should we set StorageType to? Does it matter? BB */
3639 pSMB->SearchStorageType = 0;
3640 pSMB->hdr.smb_buf_length += byte_count;
3641 pSMB->ByteCount = cpu_to_le16(byte_count);
3643 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3644 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3645 cifs_stats_inc(&tcon->num_ffirst);
3647 if (rc) {/* BB add logic to retry regular search if Unix search
3648 rejected unexpectedly by server */
3649 /* BB Add code to handle unsupported level rc */
3650 cFYI(1, ("Error in FindFirst = %d", rc));
3652 cifs_buf_release(pSMB);
3654 /* BB eventually could optimize out free and realloc of buf */
3657 goto findFirstRetry;
3658 } else { /* decode response */
3659 /* BB remember to free buffer if error BB */
3660 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3664 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
3665 psrch_inf->unicode = true;
3667 psrch_inf->unicode = false;
3669 psrch_inf->ntwrk_buf_start = (char *)pSMBr;
3670 psrch_inf->smallBuf = 0;
3671 psrch_inf->srch_entries_start =
3672 (char *) &pSMBr->hdr.Protocol +
3673 le16_to_cpu(pSMBr->t2.DataOffset);
3674 parms = (T2_FFIRST_RSP_PARMS *)((char *) &pSMBr->hdr.Protocol +
3675 le16_to_cpu(pSMBr->t2.ParameterOffset));
3677 if (parms->EndofSearch)
3678 psrch_inf->endOfSearch = true;
3680 psrch_inf->endOfSearch = false;
3682 psrch_inf->entries_in_buffer =
3683 le16_to_cpu(parms->SearchCount);
3684 psrch_inf->index_of_last_entry = 2 /* skip . and .. */ +
3685 psrch_inf->entries_in_buffer;
3686 lnoff = le16_to_cpu(parms->LastNameOffset);
3687 if (tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE <
3689 cERROR(1, ("ignoring corrupt resume name"));
3690 psrch_inf->last_entry = NULL;
3694 psrch_inf->last_entry = psrch_inf->srch_entries_start +
3697 *pnetfid = parms->SearchHandle;
3699 cifs_buf_release(pSMB);
3706 int CIFSFindNext(const int xid, struct cifsTconInfo *tcon,
3707 __u16 searchHandle, struct cifs_search_info *psrch_inf)
3709 TRANSACTION2_FNEXT_REQ *pSMB = NULL;
3710 TRANSACTION2_FNEXT_RSP *pSMBr = NULL;
3711 T2_FNEXT_RSP_PARMS *parms;
3712 char *response_data;
3714 int bytes_returned, name_len;
3715 __u16 params, byte_count;
3717 cFYI(1, ("In FindNext"));
3719 if (psrch_inf->endOfSearch)
3722 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3727 params = 14; /* includes 2 bytes of null string, converted to LE below*/
3729 pSMB->TotalDataCount = 0; /* no EAs */
3730 pSMB->MaxParameterCount = cpu_to_le16(8);
3731 pSMB->MaxDataCount =
3732 cpu_to_le16((tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE) &
3734 pSMB->MaxSetupCount = 0;
3738 pSMB->Reserved2 = 0;
3739 pSMB->ParameterOffset = cpu_to_le16(
3740 offsetof(struct smb_com_transaction2_fnext_req,SearchHandle) - 4);
3741 pSMB->DataCount = 0;
3742 pSMB->DataOffset = 0;
3743 pSMB->SetupCount = 1;
3744 pSMB->Reserved3 = 0;
3745 pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_NEXT);
3746 pSMB->SearchHandle = searchHandle; /* always kept as le */
3748 cpu_to_le16(CIFSMaxBufSize / sizeof(FILE_UNIX_INFO));
3749 pSMB->InformationLevel = cpu_to_le16(psrch_inf->info_level);
3750 pSMB->ResumeKey = psrch_inf->resume_key;
3752 cpu_to_le16(CIFS_SEARCH_CLOSE_AT_END | CIFS_SEARCH_RETURN_RESUME);
3754 name_len = psrch_inf->resume_name_len;
3756 if (name_len < PATH_MAX) {
3757 memcpy(pSMB->ResumeFileName, psrch_inf->presume_name, name_len);
3758 byte_count += name_len;
3759 /* 14 byte parm len above enough for 2 byte null terminator */
3760 pSMB->ResumeFileName[name_len] = 0;
3761 pSMB->ResumeFileName[name_len+1] = 0;
3764 goto FNext2_err_exit;
3766 byte_count = params + 1 /* pad */ ;
3767 pSMB->TotalParameterCount = cpu_to_le16(params);
3768 pSMB->ParameterCount = pSMB->TotalParameterCount;
3769 pSMB->hdr.smb_buf_length += byte_count;
3770 pSMB->ByteCount = cpu_to_le16(byte_count);
3772 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3773 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3774 cifs_stats_inc(&tcon->num_fnext);
3777 psrch_inf->endOfSearch = true;
3778 cifs_buf_release(pSMB);
3779 rc = 0; /* search probably was closed at end of search*/
3781 cFYI(1, ("FindNext returned = %d", rc));
3782 } else { /* decode response */
3783 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3788 /* BB fixme add lock for file (srch_info) struct here */
3789 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
3790 psrch_inf->unicode = true;
3792 psrch_inf->unicode = false;
3793 response_data = (char *) &pSMBr->hdr.Protocol +
3794 le16_to_cpu(pSMBr->t2.ParameterOffset);
3795 parms = (T2_FNEXT_RSP_PARMS *)response_data;
3796 response_data = (char *)&pSMBr->hdr.Protocol +
3797 le16_to_cpu(pSMBr->t2.DataOffset);
3798 if (psrch_inf->smallBuf)
3799 cifs_small_buf_release(
3800 psrch_inf->ntwrk_buf_start);
3802 cifs_buf_release(psrch_inf->ntwrk_buf_start);
3803 psrch_inf->srch_entries_start = response_data;
3804 psrch_inf->ntwrk_buf_start = (char *)pSMB;
3805 psrch_inf->smallBuf = 0;
3806 if (parms->EndofSearch)
3807 psrch_inf->endOfSearch = true;
3809 psrch_inf->endOfSearch = false;
3810 psrch_inf->entries_in_buffer =
3811 le16_to_cpu(parms->SearchCount);
3812 psrch_inf->index_of_last_entry +=
3813 psrch_inf->entries_in_buffer;
3814 lnoff = le16_to_cpu(parms->LastNameOffset);
3815 if (tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE <
3817 cERROR(1, ("ignoring corrupt resume name"));
3818 psrch_inf->last_entry = NULL;
3821 psrch_inf->last_entry =
3822 psrch_inf->srch_entries_start + lnoff;
3824 /* cFYI(1,("fnxt2 entries in buf %d index_of_last %d",
3825 psrch_inf->entries_in_buffer, psrch_inf->index_of_last_entry)); */
3827 /* BB fixme add unlock here */
3832 /* BB On error, should we leave previous search buf (and count and
3833 last entry fields) intact or free the previous one? */
3835 /* Note: On -EAGAIN error only caller can retry on handle based calls
3836 since file handle passed in no longer valid */
3839 cifs_buf_release(pSMB);
3844 CIFSFindClose(const int xid, struct cifsTconInfo *tcon,
3845 const __u16 searchHandle)
3848 FINDCLOSE_REQ *pSMB = NULL;
3850 cFYI(1, ("In CIFSSMBFindClose"));
3851 rc = small_smb_init(SMB_COM_FIND_CLOSE2, 1, tcon, (void **)&pSMB);
3853 /* no sense returning error if session restarted
3854 as file handle has been closed */
3860 pSMB->FileID = searchHandle;
3861 pSMB->ByteCount = 0;
3862 rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0);
3864 cERROR(1, ("Send error in FindClose = %d", rc));
3866 cifs_stats_inc(&tcon->num_fclose);
3868 /* Since session is dead, search handle closed on server already */
3876 CIFSGetSrvInodeNumber(const int xid, struct cifsTconInfo *tcon,
3877 const unsigned char *searchName,
3878 __u64 *inode_number,
3879 const struct nls_table *nls_codepage, int remap)
3882 TRANSACTION2_QPI_REQ *pSMB = NULL;
3883 TRANSACTION2_QPI_RSP *pSMBr = NULL;
3884 int name_len, bytes_returned;
3885 __u16 params, byte_count;
3887 cFYI(1, ("In GetSrvInodeNum for %s", searchName));
3891 GetInodeNumberRetry:
3892 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3897 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3899 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
3900 PATH_MAX, nls_codepage, remap);
3901 name_len++; /* trailing null */
3903 } else { /* BB improve the check for buffer overruns BB */
3904 name_len = strnlen(searchName, PATH_MAX);
3905 name_len++; /* trailing null */
3906 strncpy(pSMB->FileName, searchName, name_len);
3909 params = 2 /* level */ + 4 /* rsrvd */ + name_len /* incl null */ ;
3910 pSMB->TotalDataCount = 0;
3911 pSMB->MaxParameterCount = cpu_to_le16(2);
3912 /* BB find exact max data count below from sess structure BB */
3913 pSMB->MaxDataCount = cpu_to_le16(4000);
3914 pSMB->MaxSetupCount = 0;
3918 pSMB->Reserved2 = 0;
3919 pSMB->ParameterOffset = cpu_to_le16(offsetof(
3920 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
3921 pSMB->DataCount = 0;
3922 pSMB->DataOffset = 0;
3923 pSMB->SetupCount = 1;
3924 pSMB->Reserved3 = 0;
3925 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
3926 byte_count = params + 1 /* pad */ ;
3927 pSMB->TotalParameterCount = cpu_to_le16(params);
3928 pSMB->ParameterCount = pSMB->TotalParameterCount;
3929 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_INTERNAL_INFO);
3930 pSMB->Reserved4 = 0;
3931 pSMB->hdr.smb_buf_length += byte_count;
3932 pSMB->ByteCount = cpu_to_le16(byte_count);
3934 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3935 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3937 cFYI(1, ("error %d in QueryInternalInfo", rc));
3939 /* decode response */
3940 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3941 if (rc || (pSMBr->ByteCount < 2))
3942 /* BB also check enough total bytes returned */
3943 /* If rc should we check for EOPNOSUPP and
3944 disable the srvino flag? or in caller? */
3945 rc = -EIO; /* bad smb */
3947 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3948 __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
3949 struct file_internal_info *pfinfo;
3950 /* BB Do we need a cast or hash here ? */
3952 cFYI(1, ("Illegal size ret in QryIntrnlInf"));
3954 goto GetInodeNumOut;
3956 pfinfo = (struct file_internal_info *)
3957 (data_offset + (char *) &pSMBr->hdr.Protocol);
3958 *inode_number = le64_to_cpu(pfinfo->UniqueId);
3962 cifs_buf_release(pSMB);
3964 goto GetInodeNumberRetry;
3968 /* parses DFS refferal V3 structure
3969 * caller is responsible for freeing target_nodes
3972 * on failure - errno
3975 parse_DFS_referrals(TRANSACTION2_GET_DFS_REFER_RSP *pSMBr,
3976 unsigned int *num_of_nodes,
3977 struct dfs_info3_param **target_nodes,
3978 const struct nls_table *nls_codepage, int remap,
3979 const char *searchName)
3984 struct dfs_referral_level_3 *ref;
3986 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
3990 *num_of_nodes = le16_to_cpu(pSMBr->NumberOfReferrals);
3992 if (*num_of_nodes < 1) {
3993 cERROR(1, ("num_referrals: must be at least > 0,"
3994 "but we get num_referrals = %d\n", *num_of_nodes));
3996 goto parse_DFS_referrals_exit;
3999 ref = (struct dfs_referral_level_3 *) &(pSMBr->referrals);
4000 if (ref->VersionNumber != cpu_to_le16(3)) {
4001 cERROR(1, ("Referrals of V%d version are not supported,"
4002 "should be V3", le16_to_cpu(ref->VersionNumber)));
4004 goto parse_DFS_referrals_exit;
4007 /* get the upper boundary of the resp buffer */
4008 data_end = (char *)(&(pSMBr->PathConsumed)) +
4009 le16_to_cpu(pSMBr->t2.DataCount);
4011 cFYI(1, ("num_referrals: %d dfs flags: 0x%x ... \n",
4013 le32_to_cpu(pSMBr->DFSFlags)));
4015 *target_nodes = kzalloc(sizeof(struct dfs_info3_param) *
4016 *num_of_nodes, GFP_KERNEL);
4017 if (*target_nodes == NULL) {
4018 cERROR(1, ("Failed to allocate buffer for target_nodes\n"));
4020 goto parse_DFS_referrals_exit;
4023 /* collect necessary data from referrals */
4024 for (i = 0; i < *num_of_nodes; i++) {
4027 struct dfs_info3_param *node = (*target_nodes)+i;
4029 node->flags = le32_to_cpu(pSMBr->DFSFlags);
4031 __le16 *tmp = kmalloc(strlen(searchName)*2 + 2,
4035 goto parse_DFS_referrals_exit;
4037 cifsConvertToUCS((__le16 *) tmp, searchName,
4038 PATH_MAX, nls_codepage, remap);
4039 node->path_consumed = cifs_ucs2_bytes(tmp,
4040 le16_to_cpu(pSMBr->PathConsumed),
4044 node->path_consumed = le16_to_cpu(pSMBr->PathConsumed);
4046 node->server_type = le16_to_cpu(ref->ServerType);
4047 node->ref_flag = le16_to_cpu(ref->ReferralEntryFlags);
4050 temp = (char *)ref + le16_to_cpu(ref->DfsPathOffset);
4051 max_len = data_end - temp;
4052 node->path_name = cifs_strndup_from_ucs(temp, max_len,
4053 is_unicode, nls_codepage);
4054 if (!node->path_name) {
4056 goto parse_DFS_referrals_exit;
4059 /* copy link target UNC */
4060 temp = (char *)ref + le16_to_cpu(ref->NetworkAddressOffset);
4061 max_len = data_end - temp;
4062 node->node_name = cifs_strndup_from_ucs(temp, max_len,
4063 is_unicode, nls_codepage);
4064 if (!node->node_name)
4068 parse_DFS_referrals_exit:
4070 free_dfs_info_array(*target_nodes, *num_of_nodes);
4071 *target_nodes = NULL;
4078 CIFSGetDFSRefer(const int xid, struct cifsSesInfo *ses,
4079 const unsigned char *searchName,
4080 struct dfs_info3_param **target_nodes,
4081 unsigned int *num_of_nodes,
4082 const struct nls_table *nls_codepage, int remap)
4084 /* TRANS2_GET_DFS_REFERRAL */
4085 TRANSACTION2_GET_DFS_REFER_REQ *pSMB = NULL;
4086 TRANSACTION2_GET_DFS_REFER_RSP *pSMBr = NULL;
4090 __u16 params, byte_count;
4092 *target_nodes = NULL;
4094 cFYI(1, ("In GetDFSRefer the path %s", searchName));
4098 rc = smb_init(SMB_COM_TRANSACTION2, 15, NULL, (void **) &pSMB,
4103 /* server pointer checked in called function,
4104 but should never be null here anyway */
4105 pSMB->hdr.Mid = GetNextMid(ses->server);
4106 pSMB->hdr.Tid = ses->ipc_tid;
4107 pSMB->hdr.Uid = ses->Suid;
4108 if (ses->capabilities & CAP_STATUS32)
4109 pSMB->hdr.Flags2 |= SMBFLG2_ERR_STATUS;
4110 if (ses->capabilities & CAP_DFS)
4111 pSMB->hdr.Flags2 |= SMBFLG2_DFS;
4113 if (ses->capabilities & CAP_UNICODE) {
4114 pSMB->hdr.Flags2 |= SMBFLG2_UNICODE;
4116 cifsConvertToUCS((__le16 *) pSMB->RequestFileName,
4117 searchName, PATH_MAX, nls_codepage, remap);
4118 name_len++; /* trailing null */
4120 } else { /* BB improve the check for buffer overruns BB */
4121 name_len = strnlen(searchName, PATH_MAX);
4122 name_len++; /* trailing null */
4123 strncpy(pSMB->RequestFileName, searchName, name_len);
4127 if (ses->server->secMode &
4128 (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
4129 pSMB->hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
4132 pSMB->hdr.Uid = ses->Suid;
4134 params = 2 /* level */ + name_len /*includes null */ ;
4135 pSMB->TotalDataCount = 0;
4136 pSMB->DataCount = 0;
4137 pSMB->DataOffset = 0;
4138 pSMB->MaxParameterCount = 0;
4139 /* BB find exact max SMB PDU from sess structure BB */
4140 pSMB->MaxDataCount = cpu_to_le16(4000);
4141 pSMB->MaxSetupCount = 0;
4145 pSMB->Reserved2 = 0;
4146 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4147 struct smb_com_transaction2_get_dfs_refer_req, MaxReferralLevel) - 4);
4148 pSMB->SetupCount = 1;
4149 pSMB->Reserved3 = 0;
4150 pSMB->SubCommand = cpu_to_le16(TRANS2_GET_DFS_REFERRAL);
4151 byte_count = params + 3 /* pad */ ;
4152 pSMB->ParameterCount = cpu_to_le16(params);
4153 pSMB->TotalParameterCount = pSMB->ParameterCount;
4154 pSMB->MaxReferralLevel = cpu_to_le16(3);
4155 pSMB->hdr.smb_buf_length += byte_count;
4156 pSMB->ByteCount = cpu_to_le16(byte_count);
4158 rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB,
4159 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4161 cFYI(1, ("Send error in GetDFSRefer = %d", rc));
4164 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4166 /* BB Also check if enough total bytes returned? */
4167 if (rc || (pSMBr->ByteCount < 17)) {
4168 rc = -EIO; /* bad smb */
4172 cFYI(1, ("Decoding GetDFSRefer response BCC: %d Offset %d",
4174 le16_to_cpu(pSMBr->t2.DataOffset)));
4176 /* parse returned result into more usable form */
4177 rc = parse_DFS_referrals(pSMBr, num_of_nodes,
4178 target_nodes, nls_codepage, remap,
4182 cifs_buf_release(pSMB);
4190 /* Query File System Info such as free space to old servers such as Win 9x */
4192 SMBOldQFSInfo(const int xid, struct cifsTconInfo *tcon, struct kstatfs *FSData)
4194 /* level 0x01 SMB_QUERY_FILE_SYSTEM_INFO */
4195 TRANSACTION2_QFSI_REQ *pSMB = NULL;
4196 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4197 FILE_SYSTEM_ALLOC_INFO *response_data;
4199 int bytes_returned = 0;
4200 __u16 params, byte_count;
4202 cFYI(1, ("OldQFSInfo"));
4204 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4209 params = 2; /* level */
4210 pSMB->TotalDataCount = 0;
4211 pSMB->MaxParameterCount = cpu_to_le16(2);
4212 pSMB->MaxDataCount = cpu_to_le16(1000);
4213 pSMB->MaxSetupCount = 0;
4217 pSMB->Reserved2 = 0;
4218 byte_count = params + 1 /* pad */ ;
4219 pSMB->TotalParameterCount = cpu_to_le16(params);
4220 pSMB->ParameterCount = pSMB->TotalParameterCount;
4221 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4222 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4223 pSMB->DataCount = 0;
4224 pSMB->DataOffset = 0;
4225 pSMB->SetupCount = 1;
4226 pSMB->Reserved3 = 0;
4227 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4228 pSMB->InformationLevel = cpu_to_le16(SMB_INFO_ALLOCATION);
4229 pSMB->hdr.smb_buf_length += byte_count;
4230 pSMB->ByteCount = cpu_to_le16(byte_count);
4232 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4233 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4235 cFYI(1, ("Send error in QFSInfo = %d", rc));
4236 } else { /* decode response */
4237 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4239 if (rc || (pSMBr->ByteCount < 18))
4240 rc = -EIO; /* bad smb */
4242 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4243 cFYI(1, ("qfsinf resp BCC: %d Offset %d",
4244 pSMBr->ByteCount, data_offset));
4246 response_data = (FILE_SYSTEM_ALLOC_INFO *)
4247 (((char *) &pSMBr->hdr.Protocol) + data_offset);
4249 le16_to_cpu(response_data->BytesPerSector) *
4250 le32_to_cpu(response_data->
4251 SectorsPerAllocationUnit);
4253 le32_to_cpu(response_data->TotalAllocationUnits);
4254 FSData->f_bfree = FSData->f_bavail =
4255 le32_to_cpu(response_data->FreeAllocationUnits);
4257 ("Blocks: %lld Free: %lld Block size %ld",
4258 (unsigned long long)FSData->f_blocks,
4259 (unsigned long long)FSData->f_bfree,
4263 cifs_buf_release(pSMB);
4266 goto oldQFSInfoRetry;
4272 CIFSSMBQFSInfo(const int xid, struct cifsTconInfo *tcon, struct kstatfs *FSData)
4274 /* level 0x103 SMB_QUERY_FILE_SYSTEM_INFO */
4275 TRANSACTION2_QFSI_REQ *pSMB = NULL;
4276 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4277 FILE_SYSTEM_INFO *response_data;
4279 int bytes_returned = 0;
4280 __u16 params, byte_count;
4282 cFYI(1, ("In QFSInfo"));
4284 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4289 params = 2; /* level */
4290 pSMB->TotalDataCount = 0;
4291 pSMB->MaxParameterCount = cpu_to_le16(2);
4292 pSMB->MaxDataCount = cpu_to_le16(1000);
4293 pSMB->MaxSetupCount = 0;
4297 pSMB->Reserved2 = 0;
4298 byte_count = params + 1 /* pad */ ;
4299 pSMB->TotalParameterCount = cpu_to_le16(params);
4300 pSMB->ParameterCount = pSMB->TotalParameterCount;
4301 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4302 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4303 pSMB->DataCount = 0;
4304 pSMB->DataOffset = 0;
4305 pSMB->SetupCount = 1;
4306 pSMB->Reserved3 = 0;
4307 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4308 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_SIZE_INFO);
4309 pSMB->hdr.smb_buf_length += byte_count;
4310 pSMB->ByteCount = cpu_to_le16(byte_count);
4312 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4313 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4315 cFYI(1, ("Send error in QFSInfo = %d", rc));
4316 } else { /* decode response */
4317 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4319 if (rc || (pSMBr->ByteCount < 24))
4320 rc = -EIO; /* bad smb */
4322 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4326 *) (((char *) &pSMBr->hdr.Protocol) +
4329 le32_to_cpu(response_data->BytesPerSector) *
4330 le32_to_cpu(response_data->
4331 SectorsPerAllocationUnit);
4333 le64_to_cpu(response_data->TotalAllocationUnits);
4334 FSData->f_bfree = FSData->f_bavail =
4335 le64_to_cpu(response_data->FreeAllocationUnits);
4337 ("Blocks: %lld Free: %lld Block size %ld",
4338 (unsigned long long)FSData->f_blocks,
4339 (unsigned long long)FSData->f_bfree,
4343 cifs_buf_release(pSMB);
4352 CIFSSMBQFSAttributeInfo(const int xid, struct cifsTconInfo *tcon)
4354 /* level 0x105 SMB_QUERY_FILE_SYSTEM_INFO */
4355 TRANSACTION2_QFSI_REQ *pSMB = NULL;
4356 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4357 FILE_SYSTEM_ATTRIBUTE_INFO *response_data;
4359 int bytes_returned = 0;
4360 __u16 params, byte_count;
4362 cFYI(1, ("In QFSAttributeInfo"));
4364 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4369 params = 2; /* level */
4370 pSMB->TotalDataCount = 0;
4371 pSMB->MaxParameterCount = cpu_to_le16(2);
4372 /* BB find exact max SMB PDU from sess structure BB */
4373 pSMB->MaxDataCount = cpu_to_le16(1000);
4374 pSMB->MaxSetupCount = 0;
4378 pSMB->Reserved2 = 0;
4379 byte_count = params + 1 /* pad */ ;
4380 pSMB->TotalParameterCount = cpu_to_le16(params);
4381 pSMB->ParameterCount = pSMB->TotalParameterCount;
4382 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4383 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4384 pSMB->DataCount = 0;
4385 pSMB->DataOffset = 0;
4386 pSMB->SetupCount = 1;
4387 pSMB->Reserved3 = 0;
4388 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4389 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_ATTRIBUTE_INFO);
4390 pSMB->hdr.smb_buf_length += byte_count;
4391 pSMB->ByteCount = cpu_to_le16(byte_count);
4393 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4394 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4396 cERROR(1, ("Send error in QFSAttributeInfo = %d", rc));
4397 } else { /* decode response */
4398 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4400 if (rc || (pSMBr->ByteCount < 13)) {
4401 /* BB also check if enough bytes returned */
4402 rc = -EIO; /* bad smb */
4404 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4406 (FILE_SYSTEM_ATTRIBUTE_INFO
4407 *) (((char *) &pSMBr->hdr.Protocol) +
4409 memcpy(&tcon->fsAttrInfo, response_data,
4410 sizeof(FILE_SYSTEM_ATTRIBUTE_INFO));
4413 cifs_buf_release(pSMB);
4416 goto QFSAttributeRetry;
4422 CIFSSMBQFSDeviceInfo(const int xid, struct cifsTconInfo *tcon)
4424 /* level 0x104 SMB_QUERY_FILE_SYSTEM_INFO */
4425 TRANSACTION2_QFSI_REQ *pSMB = NULL;
4426 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4427 FILE_SYSTEM_DEVICE_INFO *response_data;
4429 int bytes_returned = 0;
4430 __u16 params, byte_count;
4432 cFYI(1, ("In QFSDeviceInfo"));
4434 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4439 params = 2; /* level */
4440 pSMB->TotalDataCount = 0;
4441 pSMB->MaxParameterCount = cpu_to_le16(2);
4442 /* BB find exact max SMB PDU from sess structure BB */
4443 pSMB->MaxDataCount = cpu_to_le16(1000);
4444 pSMB->MaxSetupCount = 0;
4448 pSMB->Reserved2 = 0;
4449 byte_count = params + 1 /* pad */ ;
4450 pSMB->TotalParameterCount = cpu_to_le16(params);
4451 pSMB->ParameterCount = pSMB->TotalParameterCount;
4452 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4453 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4455 pSMB->DataCount = 0;
4456 pSMB->DataOffset = 0;
4457 pSMB->SetupCount = 1;
4458 pSMB->Reserved3 = 0;
4459 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4460 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_DEVICE_INFO);
4461 pSMB->hdr.smb_buf_length += byte_count;
4462 pSMB->ByteCount = cpu_to_le16(byte_count);
4464 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4465 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4467 cFYI(1, ("Send error in QFSDeviceInfo = %d", rc));
4468 } else { /* decode response */
4469 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4471 if (rc || (pSMBr->ByteCount < sizeof(FILE_SYSTEM_DEVICE_INFO)))
4472 rc = -EIO; /* bad smb */
4474 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4476 (FILE_SYSTEM_DEVICE_INFO *)
4477 (((char *) &pSMBr->hdr.Protocol) +
4479 memcpy(&tcon->fsDevInfo, response_data,
4480 sizeof(FILE_SYSTEM_DEVICE_INFO));
4483 cifs_buf_release(pSMB);
4486 goto QFSDeviceRetry;
4492 CIFSSMBQFSUnixInfo(const int xid, struct cifsTconInfo *tcon)
4494 /* level 0x200 SMB_QUERY_CIFS_UNIX_INFO */
4495 TRANSACTION2_QFSI_REQ *pSMB = NULL;
4496 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4497 FILE_SYSTEM_UNIX_INFO *response_data;
4499 int bytes_returned = 0;
4500 __u16 params, byte_count;
4502 cFYI(1, ("In QFSUnixInfo"));
4504 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4509 params = 2; /* level */
4510 pSMB->TotalDataCount = 0;
4511 pSMB->DataCount = 0;
4512 pSMB->DataOffset = 0;
4513 pSMB->MaxParameterCount = cpu_to_le16(2);
4514 /* BB find exact max SMB PDU from sess structure BB */
4515 pSMB->MaxDataCount = cpu_to_le16(100);
4516 pSMB->MaxSetupCount = 0;
4520 pSMB->Reserved2 = 0;
4521 byte_count = params + 1 /* pad */ ;
4522 pSMB->ParameterCount = cpu_to_le16(params);
4523 pSMB->TotalParameterCount = pSMB->ParameterCount;
4524 pSMB->ParameterOffset = cpu_to_le16(offsetof(struct
4525 smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4526 pSMB->SetupCount = 1;
4527 pSMB->Reserved3 = 0;
4528 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4529 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_CIFS_UNIX_INFO);
4530 pSMB->hdr.smb_buf_length += byte_count;
4531 pSMB->ByteCount = cpu_to_le16(byte_count);
4533 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4534 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4536 cERROR(1, ("Send error in QFSUnixInfo = %d", rc));
4537 } else { /* decode response */
4538 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4540 if (rc || (pSMBr->ByteCount < 13)) {
4541 rc = -EIO; /* bad smb */
4543 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4545 (FILE_SYSTEM_UNIX_INFO
4546 *) (((char *) &pSMBr->hdr.Protocol) +
4548 memcpy(&tcon->fsUnixInfo, response_data,
4549 sizeof(FILE_SYSTEM_UNIX_INFO));
4552 cifs_buf_release(pSMB);
4562 CIFSSMBSetFSUnixInfo(const int xid, struct cifsTconInfo *tcon, __u64 cap)
4564 /* level 0x200 SMB_SET_CIFS_UNIX_INFO */
4565 TRANSACTION2_SETFSI_REQ *pSMB = NULL;
4566 TRANSACTION2_SETFSI_RSP *pSMBr = NULL;
4568 int bytes_returned = 0;
4569 __u16 params, param_offset, offset, byte_count;
4571 cFYI(1, ("In SETFSUnixInfo"));
4573 /* BB switch to small buf init to save memory */
4574 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4579 params = 4; /* 2 bytes zero followed by info level. */
4580 pSMB->MaxSetupCount = 0;
4584 pSMB->Reserved2 = 0;
4585 param_offset = offsetof(struct smb_com_transaction2_setfsi_req, FileNum)
4587 offset = param_offset + params;
4589 pSMB->MaxParameterCount = cpu_to_le16(4);
4590 /* BB find exact max SMB PDU from sess structure BB */
4591 pSMB->MaxDataCount = cpu_to_le16(100);
4592 pSMB->SetupCount = 1;
4593 pSMB->Reserved3 = 0;
4594 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FS_INFORMATION);
4595 byte_count = 1 /* pad */ + params + 12;
4597 pSMB->DataCount = cpu_to_le16(12);
4598 pSMB->ParameterCount = cpu_to_le16(params);
4599 pSMB->TotalDataCount = pSMB->DataCount;
4600 pSMB->TotalParameterCount = pSMB->ParameterCount;
4601 pSMB->ParameterOffset = cpu_to_le16(param_offset);
4602 pSMB->DataOffset = cpu_to_le16(offset);
4606 pSMB->InformationLevel = cpu_to_le16(SMB_SET_CIFS_UNIX_INFO);
4609 pSMB->ClientUnixMajor = cpu_to_le16(CIFS_UNIX_MAJOR_VERSION);
4610 pSMB->ClientUnixMinor = cpu_to_le16(CIFS_UNIX_MINOR_VERSION);
4611 pSMB->ClientUnixCap = cpu_to_le64(cap);
4613 pSMB->hdr.smb_buf_length += byte_count;
4614 pSMB->ByteCount = cpu_to_le16(byte_count);
4616 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4617 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4619 cERROR(1, ("Send error in SETFSUnixInfo = %d", rc));
4620 } else { /* decode response */
4621 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4623 rc = -EIO; /* bad smb */
4625 cifs_buf_release(pSMB);
4628 goto SETFSUnixRetry;
4636 CIFSSMBQFSPosixInfo(const int xid, struct cifsTconInfo *tcon,
4637 struct kstatfs *FSData)
4639 /* level 0x201 SMB_QUERY_CIFS_POSIX_INFO */
4640 TRANSACTION2_QFSI_REQ *pSMB = NULL;
4641 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4642 FILE_SYSTEM_POSIX_INFO *response_data;
4644 int bytes_returned = 0;
4645 __u16 params, byte_count;
4647 cFYI(1, ("In QFSPosixInfo"));
4649 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4654 params = 2; /* level */
4655 pSMB->TotalDataCount = 0;
4656 pSMB->DataCount = 0;
4657 pSMB->DataOffset = 0;
4658 pSMB->MaxParameterCount = cpu_to_le16(2);
4659 /* BB find exact max SMB PDU from sess structure BB */
4660 pSMB->MaxDataCount = cpu_to_le16(100);
4661 pSMB->MaxSetupCount = 0;
4665 pSMB->Reserved2 = 0;
4666 byte_count = params + 1 /* pad */ ;
4667 pSMB->ParameterCount = cpu_to_le16(params);
4668 pSMB->TotalParameterCount = pSMB->ParameterCount;
4669 pSMB->ParameterOffset = cpu_to_le16(offsetof(struct
4670 smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4671 pSMB->SetupCount = 1;
4672 pSMB->Reserved3 = 0;
4673 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4674 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_POSIX_FS_INFO);
4675 pSMB->hdr.smb_buf_length += byte_count;
4676 pSMB->ByteCount = cpu_to_le16(byte_count);
4678 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4679 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4681 cFYI(1, ("Send error in QFSUnixInfo = %d", rc));
4682 } else { /* decode response */
4683 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4685 if (rc || (pSMBr->ByteCount < 13)) {
4686 rc = -EIO; /* bad smb */
4688 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4690 (FILE_SYSTEM_POSIX_INFO
4691 *) (((char *) &pSMBr->hdr.Protocol) +
4694 le32_to_cpu(response_data->BlockSize);
4696 le64_to_cpu(response_data->TotalBlocks);
4698 le64_to_cpu(response_data->BlocksAvail);
4699 if (response_data->UserBlocksAvail == cpu_to_le64(-1)) {
4700 FSData->f_bavail = FSData->f_bfree;
4703 le64_to_cpu(response_data->UserBlocksAvail);
4705 if (response_data->TotalFileNodes != cpu_to_le64(-1))
4707 le64_to_cpu(response_data->TotalFileNodes);
4708 if (response_data->FreeFileNodes != cpu_to_le64(-1))
4710 le64_to_cpu(response_data->FreeFileNodes);
4713 cifs_buf_release(pSMB);
4722 /* We can not use write of zero bytes trick to
4723 set file size due to need for large file support. Also note that
4724 this SetPathInfo is preferred to SetFileInfo based method in next
4725 routine which is only needed to work around a sharing violation bug
4726 in Samba which this routine can run into */
4729 CIFSSMBSetEOF(const int xid, struct cifsTconInfo *tcon, const char *fileName,
4730 __u64 size, bool SetAllocation,
4731 const struct nls_table *nls_codepage, int remap)
4733 struct smb_com_transaction2_spi_req *pSMB = NULL;
4734 struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
4735 struct file_end_of_file_info *parm_data;
4738 int bytes_returned = 0;
4739 __u16 params, byte_count, data_count, param_offset, offset;
4741 cFYI(1, ("In SetEOF"));
4743 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4748 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4750 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
4751 PATH_MAX, nls_codepage, remap);
4752 name_len++; /* trailing null */
4754 } else { /* BB improve the check for buffer overruns BB */
4755 name_len = strnlen(fileName, PATH_MAX);
4756 name_len++; /* trailing null */
4757 strncpy(pSMB->FileName, fileName, name_len);
4759 params = 6 + name_len;
4760 data_count = sizeof(struct file_end_of_file_info);
4761 pSMB->MaxParameterCount = cpu_to_le16(2);
4762 pSMB->MaxDataCount = cpu_to_le16(4100);
4763 pSMB->MaxSetupCount = 0;
4767 pSMB->Reserved2 = 0;
4768 param_offset = offsetof(struct smb_com_transaction2_spi_req,
4769 InformationLevel) - 4;
4770 offset = param_offset + params;
4771 if (SetAllocation) {
4772 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
4773 pSMB->InformationLevel =
4774 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2);
4776 pSMB->InformationLevel =
4777 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO);
4778 } else /* Set File Size */ {
4779 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
4780 pSMB->InformationLevel =
4781 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO2);
4783 pSMB->InformationLevel =
4784 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO);
4788 (struct file_end_of_file_info *) (((char *) &pSMB->hdr.Protocol) +
4790 pSMB->ParameterOffset = cpu_to_le16(param_offset);
4791 pSMB->DataOffset = cpu_to_le16(offset);
4792 pSMB->SetupCount = 1;
4793 pSMB->Reserved3 = 0;
4794 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
4795 byte_count = 3 /* pad */ + params + data_count;
4796 pSMB->DataCount = cpu_to_le16(data_count);
4797 pSMB->TotalDataCount = pSMB->DataCount;
4798 pSMB->ParameterCount = cpu_to_le16(params);
4799 pSMB->TotalParameterCount = pSMB->ParameterCount;
4800 pSMB->Reserved4 = 0;
4801 pSMB->hdr.smb_buf_length += byte_count;
4802 parm_data->FileSize = cpu_to_le64(size);
4803 pSMB->ByteCount = cpu_to_le16(byte_count);
4804 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4805 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4807 cFYI(1, ("SetPathInfo (file size) returned %d", rc));
4809 cifs_buf_release(pSMB);
4818 CIFSSMBSetFileSize(const int xid, struct cifsTconInfo *tcon, __u64 size,
4819 __u16 fid, __u32 pid_of_opener, bool SetAllocation)
4821 struct smb_com_transaction2_sfi_req *pSMB = NULL;
4823 struct file_end_of_file_info *parm_data;
4825 __u16 params, param_offset, offset, byte_count, count;
4827 cFYI(1, ("SetFileSize (via SetFileInfo) %lld",
4829 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
4834 pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
4835 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));
4838 pSMB->MaxSetupCount = 0;
4842 pSMB->Reserved2 = 0;
4843 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
4844 offset = param_offset + params;
4846 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
4848 count = sizeof(struct file_end_of_file_info);
4849 pSMB->MaxParameterCount = cpu_to_le16(2);
4850 /* BB find exact max SMB PDU from sess structure BB */
4851 pSMB->MaxDataCount = cpu_to_le16(1000);
4852 pSMB->SetupCount = 1;
4853 pSMB->Reserved3 = 0;
4854 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
4855 byte_count = 3 /* pad */ + params + count;
4856 pSMB->DataCount = cpu_to_le16(count);
4857 pSMB->ParameterCount = cpu_to_le16(params);
4858 pSMB->TotalDataCount = pSMB->DataCount;
4859 pSMB->TotalParameterCount = pSMB->ParameterCount;
4860 pSMB->ParameterOffset = cpu_to_le16(param_offset);
4862 (struct file_end_of_file_info *) (((char *) &pSMB->hdr.Protocol)
4864 pSMB->DataOffset = cpu_to_le16(offset);
4865 parm_data->FileSize = cpu_to_le64(size);
4867 if (SetAllocation) {
4868 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
4869 pSMB->InformationLevel =
4870 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2);
4872 pSMB->InformationLevel =
4873 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO);
4874 } else /* Set File Size */ {
4875 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
4876 pSMB->InformationLevel =
4877 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO2);
4879 pSMB->InformationLevel =
4880 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO);
4882 pSMB->Reserved4 = 0;
4883 pSMB->hdr.smb_buf_length += byte_count;
4884 pSMB->ByteCount = cpu_to_le16(byte_count);
4885 rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0);
4888 ("Send error in SetFileInfo (SetFileSize) = %d",
4892 /* Note: On -EAGAIN error only caller can retry on handle based calls
4893 since file handle passed in no longer valid */
4898 /* Some legacy servers such as NT4 require that the file times be set on
4899 an open handle, rather than by pathname - this is awkward due to
4900 potential access conflicts on the open, but it is unavoidable for these
4901 old servers since the only other choice is to go from 100 nanosecond DCE
4902 time and resort to the original setpathinfo level which takes the ancient
4903 DOS time format with 2 second granularity */
4905 CIFSSMBSetFileInfo(const int xid, struct cifsTconInfo *tcon,
4906 const FILE_BASIC_INFO *data, __u16 fid, __u32 pid_of_opener)
4908 struct smb_com_transaction2_sfi_req *pSMB = NULL;
4911 __u16 params, param_offset, offset, byte_count, count;
4913 cFYI(1, ("Set Times (via SetFileInfo)"));
4914 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
4919 pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
4920 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));
4923 pSMB->MaxSetupCount = 0;
4927 pSMB->Reserved2 = 0;
4928 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
4929 offset = param_offset + params;
4931 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
4933 count = sizeof(FILE_BASIC_INFO);
4934 pSMB->MaxParameterCount = cpu_to_le16(2);
4935 /* BB find max SMB PDU from sess */
4936 pSMB->MaxDataCount = cpu_to_le16(1000);
4937 pSMB->SetupCount = 1;
4938 pSMB->Reserved3 = 0;
4939 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
4940 byte_count = 3 /* pad */ + params + count;
4941 pSMB->DataCount = cpu_to_le16(count);
4942 pSMB->ParameterCount = cpu_to_le16(params);
4943 pSMB->TotalDataCount = pSMB->DataCount;
4944 pSMB->TotalParameterCount = pSMB->ParameterCount;
4945 pSMB->ParameterOffset = cpu_to_le16(param_offset);
4946 pSMB->DataOffset = cpu_to_le16(offset);
4948 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
4949 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO2);
4951 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO);
4952 pSMB->Reserved4 = 0;
4953 pSMB->hdr.smb_buf_length += byte_count;
4954 pSMB->ByteCount = cpu_to_le16(byte_count);
4955 memcpy(data_offset, data, sizeof(FILE_BASIC_INFO));
4956 rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0);
4958 cFYI(1, ("Send error in Set Time (SetFileInfo) = %d", rc));
4960 /* Note: On -EAGAIN error only caller can retry on handle based calls
4961 since file handle passed in no longer valid */
4967 CIFSSMBSetFileDisposition(const int xid, struct cifsTconInfo *tcon,
4968 bool delete_file, __u16 fid, __u32 pid_of_opener)
4970 struct smb_com_transaction2_sfi_req *pSMB = NULL;
4973 __u16 params, param_offset, offset, byte_count, count;
4975 cFYI(1, ("Set File Disposition (via SetFileInfo)"));
4976 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
4981 pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
4982 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));
4985 pSMB->MaxSetupCount = 0;
4989 pSMB->Reserved2 = 0;
4990 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
4991 offset = param_offset + params;
4993 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
4996 pSMB->MaxParameterCount = cpu_to_le16(2);
4997 /* BB find max SMB PDU from sess */
4998 pSMB->MaxDataCount = cpu_to_le16(1000);
4999 pSMB->SetupCount = 1;
5000 pSMB->Reserved3 = 0;
5001 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
5002 byte_count = 3 /* pad */ + params + count;
5003 pSMB->DataCount = cpu_to_le16(count);
5004 pSMB->ParameterCount = cpu_to_le16(params);
5005 pSMB->TotalDataCount = pSMB->DataCount;
5006 pSMB->TotalParameterCount = pSMB->ParameterCount;
5007 pSMB->ParameterOffset = cpu_to_le16(param_offset);
5008 pSMB->DataOffset = cpu_to_le16(offset);
5010 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_DISPOSITION_INFO);
5011 pSMB->Reserved4 = 0;
5012 pSMB->hdr.smb_buf_length += byte_count;
5013 pSMB->ByteCount = cpu_to_le16(byte_count);
5014 *data_offset = delete_file ? 1 : 0;
5015 rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0);
5017 cFYI(1, ("Send error in SetFileDisposition = %d", rc));
5023 CIFSSMBSetPathInfo(const int xid, struct cifsTconInfo *tcon,
5024 const char *fileName, const FILE_BASIC_INFO *data,
5025 const struct nls_table *nls_codepage, int remap)
5027 TRANSACTION2_SPI_REQ *pSMB = NULL;
5028 TRANSACTION2_SPI_RSP *pSMBr = NULL;
5031 int bytes_returned = 0;
5033 __u16 params, param_offset, offset, byte_count, count;
5035 cFYI(1, ("In SetTimes"));
5038 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5043 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5045 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
5046 PATH_MAX, nls_codepage, remap);
5047 name_len++; /* trailing null */
5049 } else { /* BB improve the check for buffer overruns BB */
5050 name_len = strnlen(fileName, PATH_MAX);
5051 name_len++; /* trailing null */
5052 strncpy(pSMB->FileName, fileName, name_len);
5055 params = 6 + name_len;
5056 count = sizeof(FILE_BASIC_INFO);
5057 pSMB->MaxParameterCount = cpu_to_le16(2);
5058 /* BB find max SMB PDU from sess structure BB */
5059 pSMB->MaxDataCount = cpu_to_le16(1000);
5060 pSMB->MaxSetupCount = 0;
5064 pSMB->Reserved2 = 0;
5065 param_offset = offsetof(struct smb_com_transaction2_spi_req,
5066 InformationLevel) - 4;
5067 offset = param_offset + params;
5068 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
5069 pSMB->ParameterOffset = cpu_to_le16(param_offset);
5070 pSMB->DataOffset = cpu_to_le16(offset);
5071 pSMB->SetupCount = 1;
5072 pSMB->Reserved3 = 0;
5073 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
5074 byte_count = 3 /* pad */ + params + count;
5076 pSMB->DataCount = cpu_to_le16(count);
5077 pSMB->ParameterCount = cpu_to_le16(params);
5078 pSMB->TotalDataCount = pSMB->DataCount;
5079 pSMB->TotalParameterCount = pSMB->ParameterCount;
5080 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
5081 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO2);
5083 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO);
5084 pSMB->Reserved4 = 0;
5085 pSMB->hdr.smb_buf_length += byte_count;
5086 memcpy(data_offset, data, sizeof(FILE_BASIC_INFO));
5087 pSMB->ByteCount = cpu_to_le16(byte_count);
5088 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5089 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5091 cFYI(1, ("SetPathInfo (times) returned %d", rc));
5093 cifs_buf_release(pSMB);
5101 /* Can not be used to set time stamps yet (due to old DOS time format) */
5102 /* Can be used to set attributes */
5103 #if 0 /* Possibly not needed - since it turns out that strangely NT4 has a bug
5104 handling it anyway and NT4 was what we thought it would be needed for
5105 Do not delete it until we prove whether needed for Win9x though */
5107 CIFSSMBSetAttrLegacy(int xid, struct cifsTconInfo *tcon, char *fileName,
5108 __u16 dos_attrs, const struct nls_table *nls_codepage)
5110 SETATTR_REQ *pSMB = NULL;
5111 SETATTR_RSP *pSMBr = NULL;
5116 cFYI(1, ("In SetAttrLegacy"));
5119 rc = smb_init(SMB_COM_SETATTR, 8, tcon, (void **) &pSMB,
5124 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5126 ConvertToUCS((__le16 *) pSMB->fileName, fileName,
5127 PATH_MAX, nls_codepage);
5128 name_len++; /* trailing null */
5130 } else { /* BB improve the check for buffer overruns BB */
5131 name_len = strnlen(fileName, PATH_MAX);
5132 name_len++; /* trailing null */
5133 strncpy(pSMB->fileName, fileName, name_len);
5135 pSMB->attr = cpu_to_le16(dos_attrs);
5136 pSMB->BufferFormat = 0x04;
5137 pSMB->hdr.smb_buf_length += name_len + 1;
5138 pSMB->ByteCount = cpu_to_le16(name_len + 1);
5139 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5140 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5142 cFYI(1, ("Error in LegacySetAttr = %d", rc));
5144 cifs_buf_release(pSMB);
5147 goto SetAttrLgcyRetry;
5151 #endif /* temporarily unneeded SetAttr legacy function */
5154 cifs_fill_unix_set_info(FILE_UNIX_BASIC_INFO *data_offset,
5155 const struct cifs_unix_set_info_args *args)
5157 u64 mode = args->mode;
5160 * Samba server ignores set of file size to zero due to bugs in some
5161 * older clients, but we should be precise - we use SetFileSize to
5162 * set file size and do not want to truncate file size to zero
5163 * accidently as happened on one Samba server beta by putting
5164 * zero instead of -1 here
5166 data_offset->EndOfFile = cpu_to_le64(NO_CHANGE_64);
5167 data_offset->NumOfBytes = cpu_to_le64(NO_CHANGE_64);
5168 data_offset->LastStatusChange = cpu_to_le64(args->ctime);
5169 data_offset->LastAccessTime = cpu_to_le64(args->atime);
5170 data_offset->LastModificationTime = cpu_to_le64(args->mtime);
5171 data_offset->Uid = cpu_to_le64(args->uid);
5172 data_offset->Gid = cpu_to_le64(args->gid);
5173 /* better to leave device as zero when it is */
5174 data_offset->DevMajor = cpu_to_le64(MAJOR(args->device));
5175 data_offset->DevMinor = cpu_to_le64(MINOR(args->device));
5176 data_offset->Permissions = cpu_to_le64(mode);
5179 data_offset->Type = cpu_to_le32(UNIX_FILE);
5180 else if (S_ISDIR(mode))
5181 data_offset->Type = cpu_to_le32(UNIX_DIR);
5182 else if (S_ISLNK(mode))
5183 data_offset->Type = cpu_to_le32(UNIX_SYMLINK);
5184 else if (S_ISCHR(mode))
5185 data_offset->Type = cpu_to_le32(UNIX_CHARDEV);
5186 else if (S_ISBLK(mode))
5187 data_offset->Type = cpu_to_le32(UNIX_BLOCKDEV);
5188 else if (S_ISFIFO(mode))
5189 data_offset->Type = cpu_to_le32(UNIX_FIFO);
5190 else if (S_ISSOCK(mode))
5191 data_offset->Type = cpu_to_le32(UNIX_SOCKET);
5195 CIFSSMBUnixSetFileInfo(const int xid, struct cifsTconInfo *tcon,
5196 const struct cifs_unix_set_info_args *args,
5197 u16 fid, u32 pid_of_opener)
5199 struct smb_com_transaction2_sfi_req *pSMB = NULL;
5200 FILE_UNIX_BASIC_INFO *data_offset;
5202 u16 params, param_offset, offset, byte_count, count;
5204 cFYI(1, ("Set Unix Info (via SetFileInfo)"));
5205 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
5210 pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
5211 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));
5214 pSMB->MaxSetupCount = 0;
5218 pSMB->Reserved2 = 0;
5219 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
5220 offset = param_offset + params;
5222 data_offset = (FILE_UNIX_BASIC_INFO *)
5223 ((char *)(&pSMB->hdr.Protocol) + offset);
5224 count = sizeof(FILE_UNIX_BASIC_INFO);
5226 pSMB->MaxParameterCount = cpu_to_le16(2);
5227 /* BB find max SMB PDU from sess */
5228 pSMB->MaxDataCount = cpu_to_le16(1000);
5229 pSMB->SetupCount = 1;
5230 pSMB->Reserved3 = 0;
5231 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
5232 byte_count = 3 /* pad */ + params + count;
5233 pSMB->DataCount = cpu_to_le16(count);
5234 pSMB->ParameterCount = cpu_to_le16(params);
5235 pSMB->TotalDataCount = pSMB->DataCount;
5236 pSMB->TotalParameterCount = pSMB->ParameterCount;
5237 pSMB->ParameterOffset = cpu_to_le16(param_offset);
5238 pSMB->DataOffset = cpu_to_le16(offset);
5240 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_BASIC);
5241 pSMB->Reserved4 = 0;
5242 pSMB->hdr.smb_buf_length += byte_count;
5243 pSMB->ByteCount = cpu_to_le16(byte_count);
5245 cifs_fill_unix_set_info(data_offset, args);
5247 rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0);
5249 cFYI(1, ("Send error in Set Time (SetFileInfo) = %d", rc));
5251 /* Note: On -EAGAIN error only caller can retry on handle based calls
5252 since file handle passed in no longer valid */
5258 CIFSSMBUnixSetPathInfo(const int xid, struct cifsTconInfo *tcon, char *fileName,
5259 const struct cifs_unix_set_info_args *args,
5260 const struct nls_table *nls_codepage, int remap)
5262 TRANSACTION2_SPI_REQ *pSMB = NULL;
5263 TRANSACTION2_SPI_RSP *pSMBr = NULL;
5266 int bytes_returned = 0;
5267 FILE_UNIX_BASIC_INFO *data_offset;
5268 __u16 params, param_offset, offset, count, byte_count;
5270 cFYI(1, ("In SetUID/GID/Mode"));
5272 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5277 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5279 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
5280 PATH_MAX, nls_codepage, remap);
5281 name_len++; /* trailing null */
5283 } else { /* BB improve the check for buffer overruns BB */
5284 name_len = strnlen(fileName, PATH_MAX);
5285 name_len++; /* trailing null */
5286 strncpy(pSMB->FileName, fileName, name_len);
5289 params = 6 + name_len;
5290 count = sizeof(FILE_UNIX_BASIC_INFO);
5291 pSMB->MaxParameterCount = cpu_to_le16(2);
5292 /* BB find max SMB PDU from sess structure BB */
5293 pSMB->MaxDataCount = cpu_to_le16(1000);
5294 pSMB->MaxSetupCount = 0;
5298 pSMB->Reserved2 = 0;
5299 param_offset = offsetof(struct smb_com_transaction2_spi_req,
5300 InformationLevel) - 4;
5301 offset = param_offset + params;
5303 (FILE_UNIX_BASIC_INFO *) ((char *) &pSMB->hdr.Protocol +
5305 memset(data_offset, 0, count);
5306 pSMB->DataOffset = cpu_to_le16(offset);
5307 pSMB->ParameterOffset = cpu_to_le16(param_offset);
5308 pSMB->SetupCount = 1;
5309 pSMB->Reserved3 = 0;
5310 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
5311 byte_count = 3 /* pad */ + params + count;
5312 pSMB->ParameterCount = cpu_to_le16(params);
5313 pSMB->DataCount = cpu_to_le16(count);
5314 pSMB->TotalParameterCount = pSMB->ParameterCount;
5315 pSMB->TotalDataCount = pSMB->DataCount;
5316 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_BASIC);
5317 pSMB->Reserved4 = 0;
5318 pSMB->hdr.smb_buf_length += byte_count;
5320 cifs_fill_unix_set_info(data_offset, args);
5322 pSMB->ByteCount = cpu_to_le16(byte_count);
5323 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5324 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5326 cFYI(1, ("SetPathInfo (perms) returned %d", rc));
5328 cifs_buf_release(pSMB);
5334 int CIFSSMBNotify(const int xid, struct cifsTconInfo *tcon,
5335 const int notify_subdirs, const __u16 netfid,
5336 __u32 filter, struct file *pfile, int multishot,
5337 const struct nls_table *nls_codepage)
5340 struct smb_com_transaction_change_notify_req *pSMB = NULL;
5341 struct smb_com_ntransaction_change_notify_rsp *pSMBr = NULL;
5342 struct dir_notify_req *dnotify_req;
5345 cFYI(1, ("In CIFSSMBNotify for file handle %d", (int)netfid));
5346 rc = smb_init(SMB_COM_NT_TRANSACT, 23, tcon, (void **) &pSMB,
5351 pSMB->TotalParameterCount = 0 ;
5352 pSMB->TotalDataCount = 0;
5353 pSMB->MaxParameterCount = cpu_to_le32(2);
5354 /* BB find exact data count max from sess structure BB */
5355 pSMB->MaxDataCount = 0; /* same in little endian or be */
5356 /* BB VERIFY verify which is correct for above BB */
5357 pSMB->MaxDataCount = cpu_to_le32((tcon->ses->server->maxBuf -
5358 MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
5360 pSMB->MaxSetupCount = 4;
5362 pSMB->ParameterOffset = 0;
5363 pSMB->DataCount = 0;
5364 pSMB->DataOffset = 0;
5365 pSMB->SetupCount = 4; /* single byte does not need le conversion */
5366 pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_NOTIFY_CHANGE);
5367 pSMB->ParameterCount = pSMB->TotalParameterCount;
5369 pSMB->WatchTree = 1; /* one byte - no le conversion needed */
5370 pSMB->Reserved2 = 0;
5371 pSMB->CompletionFilter = cpu_to_le32(filter);
5372 pSMB->Fid = netfid; /* file handle always le */
5373 pSMB->ByteCount = 0;
5375 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5376 (struct smb_hdr *)pSMBr, &bytes_returned,
5379 cFYI(1, ("Error in Notify = %d", rc));
5381 /* Add file to outstanding requests */
5382 /* BB change to kmem cache alloc */
5383 dnotify_req = kmalloc(
5384 sizeof(struct dir_notify_req),
5387 dnotify_req->Pid = pSMB->hdr.Pid;
5388 dnotify_req->PidHigh = pSMB->hdr.PidHigh;
5389 dnotify_req->Mid = pSMB->hdr.Mid;
5390 dnotify_req->Tid = pSMB->hdr.Tid;
5391 dnotify_req->Uid = pSMB->hdr.Uid;
5392 dnotify_req->netfid = netfid;
5393 dnotify_req->pfile = pfile;
5394 dnotify_req->filter = filter;
5395 dnotify_req->multishot = multishot;
5396 spin_lock(&GlobalMid_Lock);
5397 list_add_tail(&dnotify_req->lhead,
5398 &GlobalDnotifyReqList);
5399 spin_unlock(&GlobalMid_Lock);
5403 cifs_buf_release(pSMB);
5407 #ifdef CONFIG_CIFS_XATTR
5409 * Do a path-based QUERY_ALL_EAS call and parse the result. This is a common
5410 * function used by listxattr and getxattr type calls. When ea_name is set,
5411 * it looks for that attribute name and stuffs that value into the EAData
5412 * buffer. When ea_name is NULL, it stuffs a list of attribute names into the
5413 * buffer. In both cases, the return value is either the length of the
5414 * resulting data or a negative error code. If EAData is a NULL pointer then
5415 * the data isn't copied to it, but the length is returned.
5418 CIFSSMBQAllEAs(const int xid, struct cifsTconInfo *tcon,
5419 const unsigned char *searchName, const unsigned char *ea_name,
5420 char *EAData, size_t buf_size,
5421 const struct nls_table *nls_codepage, int remap)
5423 /* BB assumes one setup word */
5424 TRANSACTION2_QPI_REQ *pSMB = NULL;
5425 TRANSACTION2_QPI_RSP *pSMBr = NULL;
5429 struct fealist *ea_response_data;
5430 struct fea *temp_fea;
5433 __u16 params, byte_count, data_offset;
5435 cFYI(1, ("In Query All EAs path %s", searchName));
5437 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5442 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5444 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
5445 PATH_MAX, nls_codepage, remap);
5446 list_len++; /* trailing null */
5448 } else { /* BB improve the check for buffer overruns BB */
5449 list_len = strnlen(searchName, PATH_MAX);
5450 list_len++; /* trailing null */
5451 strncpy(pSMB->FileName, searchName, list_len);
5454 params = 2 /* level */ + 4 /* reserved */ + list_len /* includes NUL */;
5455 pSMB->TotalDataCount = 0;
5456 pSMB->MaxParameterCount = cpu_to_le16(2);
5457 /* BB find exact max SMB PDU from sess structure BB */
5458 pSMB->MaxDataCount = cpu_to_le16(CIFSMaxBufSize);
5459 pSMB->MaxSetupCount = 0;
5463 pSMB->Reserved2 = 0;
5464 pSMB->ParameterOffset = cpu_to_le16(offsetof(
5465 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
5466 pSMB->DataCount = 0;
5467 pSMB->DataOffset = 0;
5468 pSMB->SetupCount = 1;
5469 pSMB->Reserved3 = 0;
5470 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
5471 byte_count = params + 1 /* pad */ ;
5472 pSMB->TotalParameterCount = cpu_to_le16(params);
5473 pSMB->ParameterCount = pSMB->TotalParameterCount;
5474 pSMB->InformationLevel = cpu_to_le16(SMB_INFO_QUERY_ALL_EAS);
5475 pSMB->Reserved4 = 0;
5476 pSMB->hdr.smb_buf_length += byte_count;
5477 pSMB->ByteCount = cpu_to_le16(byte_count);
5479 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5480 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5482 cFYI(1, ("Send error in QueryAllEAs = %d", rc));
5487 /* BB also check enough total bytes returned */
5488 /* BB we need to improve the validity checking
5489 of these trans2 responses */
5491 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
5492 if (rc || (pSMBr->ByteCount < 4)) {
5493 rc = -EIO; /* bad smb */
5497 /* check that length of list is not more than bcc */
5498 /* check that each entry does not go beyond length
5500 /* check that each element of each entry does not
5501 go beyond end of list */
5502 /* validate_trans2_offsets() */
5503 /* BB check if start of smb + data_offset > &bcc+ bcc */
5505 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
5506 ea_response_data = (struct fealist *)
5507 (((char *) &pSMBr->hdr.Protocol) + data_offset);
5509 list_len = le32_to_cpu(ea_response_data->list_len);
5510 cFYI(1, ("ea length %d", list_len));
5511 if (list_len <= 8) {
5512 cFYI(1, ("empty EA list returned from server"));
5516 /* make sure list_len doesn't go past end of SMB */
5517 end_of_smb = (char *)pByteArea(&pSMBr->hdr) + BCC(&pSMBr->hdr);
5518 if ((char *)ea_response_data + list_len > end_of_smb) {
5519 cFYI(1, ("EA list appears to go beyond SMB"));
5524 /* account for ea list len */
5526 temp_fea = ea_response_data->list;
5527 temp_ptr = (char *)temp_fea;
5528 while (list_len > 0) {
5529 unsigned int name_len;
5534 /* make sure we can read name_len and value_len */
5536 cFYI(1, ("EA entry goes beyond length of list"));
5541 name_len = temp_fea->name_len;
5542 value_len = le16_to_cpu(temp_fea->value_len);
5543 list_len -= name_len + 1 + value_len;
5545 cFYI(1, ("EA entry goes beyond length of list"));
5551 if (strncmp(ea_name, temp_ptr, name_len) == 0) {
5552 temp_ptr += name_len + 1;
5556 if ((size_t)value_len > buf_size) {
5560 memcpy(EAData, temp_ptr, value_len);
5564 /* account for prefix user. and trailing null */
5565 rc += (5 + 1 + name_len);
5566 if (rc < (int) buf_size) {
5567 memcpy(EAData, "user.", 5);
5569 memcpy(EAData, temp_ptr, name_len);
5571 /* null terminate name */
5574 } else if (buf_size == 0) {
5575 /* skip copy - calc size only */
5577 /* stop before overrun buffer */
5582 temp_ptr += name_len + 1 + value_len;
5583 temp_fea = (struct fea *)temp_ptr;
5586 /* didn't find the named attribute */
5591 cifs_buf_release(pSMB);
5599 CIFSSMBSetEA(const int xid, struct cifsTconInfo *tcon, const char *fileName,
5600 const char *ea_name, const void *ea_value,
5601 const __u16 ea_value_len, const struct nls_table *nls_codepage,
5604 struct smb_com_transaction2_spi_req *pSMB = NULL;
5605 struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
5606 struct fealist *parm_data;
5609 int bytes_returned = 0;
5610 __u16 params, param_offset, byte_count, offset, count;
5612 cFYI(1, ("In SetEA"));
5614 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5619 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5621 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
5622 PATH_MAX, nls_codepage, remap);
5623 name_len++; /* trailing null */
5625 } else { /* BB improve the check for buffer overruns BB */
5626 name_len = strnlen(fileName, PATH_MAX);
5627 name_len++; /* trailing null */
5628 strncpy(pSMB->FileName, fileName, name_len);
5631 params = 6 + name_len;
5633 /* done calculating parms using name_len of file name,
5634 now use name_len to calculate length of ea name
5635 we are going to create in the inode xattrs */
5636 if (ea_name == NULL)
5639 name_len = strnlen(ea_name, 255);
5641 count = sizeof(*parm_data) + ea_value_len + name_len;
5642 pSMB->MaxParameterCount = cpu_to_le16(2);
5643 /* BB find max SMB PDU from sess */
5644 pSMB->MaxDataCount = cpu_to_le16(1000);
5645 pSMB->MaxSetupCount = 0;
5649 pSMB->Reserved2 = 0;
5650 param_offset = offsetof(struct smb_com_transaction2_spi_req,
5651 InformationLevel) - 4;
5652 offset = param_offset + params;
5653 pSMB->InformationLevel =
5654 cpu_to_le16(SMB_SET_FILE_EA);
5657 (struct fealist *) (((char *) &pSMB->hdr.Protocol) +
5659 pSMB->ParameterOffset = cpu_to_le16(param_offset);
5660 pSMB->DataOffset = cpu_to_le16(offset);
5661 pSMB->SetupCount = 1;
5662 pSMB->Reserved3 = 0;
5663 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
5664 byte_count = 3 /* pad */ + params + count;
5665 pSMB->DataCount = cpu_to_le16(count);
5666 parm_data->list_len = cpu_to_le32(count);
5667 parm_data->list[0].EA_flags = 0;
5668 /* we checked above that name len is less than 255 */
5669 parm_data->list[0].name_len = (__u8)name_len;
5670 /* EA names are always ASCII */
5672 strncpy(parm_data->list[0].name, ea_name, name_len);
5673 parm_data->list[0].name[name_len] = 0;
5674 parm_data->list[0].value_len = cpu_to_le16(ea_value_len);
5675 /* caller ensures that ea_value_len is less than 64K but
5676 we need to ensure that it fits within the smb */
5678 /*BB add length check to see if it would fit in
5679 negotiated SMB buffer size BB */
5680 /* if (ea_value_len > buffer_size - 512 (enough for header)) */
5682 memcpy(parm_data->list[0].name+name_len+1,
5683 ea_value, ea_value_len);
5685 pSMB->TotalDataCount = pSMB->DataCount;
5686 pSMB->ParameterCount = cpu_to_le16(params);
5687 pSMB->TotalParameterCount = pSMB->ParameterCount;
5688 pSMB->Reserved4 = 0;
5689 pSMB->hdr.smb_buf_length += byte_count;
5690 pSMB->ByteCount = cpu_to_le16(byte_count);
5691 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5692 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5694 cFYI(1, ("SetPathInfo (EA) returned %d", rc));
5696 cifs_buf_release(pSMB);