4 * Copyright (C) International Business Machines Corp., 2002,2008
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 /* Allocates buffer into dst and copies smb string from src to it.
85 * caller is responsible for freeing dst if function returned 0.
91 cifs_strncpy_to_host(char **dst, const char *src, const int maxlen,
92 const bool is_unicode, const struct nls_table *nls_codepage)
97 plen = UniStrnlen((wchar_t *)src, maxlen);
98 *dst = kmalloc(plen + 2, GFP_KERNEL);
100 goto cifs_strncpy_to_host_ErrExit;
101 cifs_strfromUCS_le(*dst, (__le16 *)src, plen, nls_codepage);
103 plen = strnlen(src, maxlen);
104 *dst = kmalloc(plen + 2, GFP_KERNEL);
106 goto cifs_strncpy_to_host_ErrExit;
107 strncpy(*dst, src, plen);
110 (*dst)[plen+1] = 0; /* harmless for ASCII case, needed for Unicode */
113 cifs_strncpy_to_host_ErrExit:
114 cERROR(1, ("Failed to allocate buffer for string\n"));
119 /* Mark as invalid, all open files on tree connections since they
120 were closed when session to server was lost */
121 static void mark_open_files_invalid(struct cifsTconInfo *pTcon)
123 struct cifsFileInfo *open_file = NULL;
124 struct list_head *tmp;
125 struct list_head *tmp1;
127 /* list all files open on tree connection and mark them invalid */
128 write_lock(&GlobalSMBSeslock);
129 list_for_each_safe(tmp, tmp1, &pTcon->openFileList) {
130 open_file = list_entry(tmp, struct cifsFileInfo, tlist);
131 open_file->invalidHandle = true;
133 write_unlock(&GlobalSMBSeslock);
134 /* BB Add call to invalidate_inodes(sb) for all superblocks mounted
138 /* Allocate and return pointer to an SMB request buffer, and set basic
139 SMB information in the SMB header. If the return code is zero, this
140 function must have filled in request_buf pointer */
142 small_smb_init(int smb_command, int wct, struct cifsTconInfo *tcon,
147 /* SMBs NegProt, SessSetup, uLogoff do not have tcon yet so
148 check for tcp and smb session status done differently
149 for those three - in the calling routine */
151 if (tcon->tidStatus == CifsExiting) {
152 /* only tree disconnect, open, and write,
153 (and ulogoff which does not have tcon)
154 are allowed as we start force umount */
155 if ((smb_command != SMB_COM_WRITE_ANDX) &&
156 (smb_command != SMB_COM_OPEN_ANDX) &&
157 (smb_command != SMB_COM_TREE_DISCONNECT)) {
158 cFYI(1, ("can not send cmd %d while umounting",
163 if ((tcon->ses) && (tcon->ses->status != CifsExiting) &&
164 (tcon->ses->server)) {
165 struct nls_table *nls_codepage;
166 /* Give Demultiplex thread up to 10 seconds to
167 reconnect, should be greater than cifs socket
168 timeout which is 7 seconds */
169 while (tcon->ses->server->tcpStatus ==
171 wait_event_interruptible_timeout(tcon->ses->server->response_q,
172 (tcon->ses->server->tcpStatus ==
174 if (tcon->ses->server->tcpStatus ==
176 /* on "soft" mounts we wait once */
178 (tcon->ses->status == CifsExiting)) {
179 cFYI(1, ("gave up waiting on "
180 "reconnect in smb_init"));
182 } /* else "hard" mount - keep retrying
183 until process is killed or server
184 comes back on-line */
185 } else /* TCP session is reestablished now */
189 nls_codepage = load_nls_default();
190 /* need to prevent multiple threads trying to
191 simultaneously reconnect the same SMB session */
192 down(&tcon->ses->sesSem);
193 if (tcon->ses->need_reconnect)
194 rc = cifs_setup_session(0, tcon->ses,
196 if (!rc && (tcon->need_reconnect)) {
197 mark_open_files_invalid(tcon);
198 rc = CIFSTCon(0, tcon->ses, tcon->treeName,
200 up(&tcon->ses->sesSem);
201 /* BB FIXME add code to check if wsize needs
202 update due to negotiated smb buffer size
205 atomic_inc(&tconInfoReconnectCount);
206 /* tell server Unix caps we support */
207 if (tcon->ses->capabilities & CAP_UNIX)
208 reset_cifs_unix_caps(
211 NULL /* we do not know sb */,
212 NULL /* no vol info */);
215 cFYI(1, ("reconnect tcon rc = %d", rc));
216 /* Removed call to reopen open files here.
217 It is safer (and faster) to reopen files
218 one at a time as needed in read and write */
220 /* Check if handle based operation so we
221 know whether we can continue or not without
222 returning to caller to reset file handle */
223 switch (smb_command) {
224 case SMB_COM_READ_ANDX:
225 case SMB_COM_WRITE_ANDX:
227 case SMB_COM_FIND_CLOSE2:
228 case SMB_COM_LOCKING_ANDX: {
229 unload_nls(nls_codepage);
234 up(&tcon->ses->sesSem);
236 unload_nls(nls_codepage);
245 *request_buf = cifs_small_buf_get();
246 if (*request_buf == NULL) {
247 /* BB should we add a retry in here if not a writepage? */
251 header_assemble((struct smb_hdr *) *request_buf, smb_command,
255 cifs_stats_inc(&tcon->num_smbs_sent);
261 small_smb_init_no_tc(const int smb_command, const int wct,
262 struct cifsSesInfo *ses, void **request_buf)
265 struct smb_hdr *buffer;
267 rc = small_smb_init(smb_command, wct, NULL, request_buf);
271 buffer = (struct smb_hdr *)*request_buf;
272 buffer->Mid = GetNextMid(ses->server);
273 if (ses->capabilities & CAP_UNICODE)
274 buffer->Flags2 |= SMBFLG2_UNICODE;
275 if (ses->capabilities & CAP_STATUS32)
276 buffer->Flags2 |= SMBFLG2_ERR_STATUS;
278 /* uid, tid can stay at zero as set in header assemble */
280 /* BB add support for turning on the signing when
281 this function is used after 1st of session setup requests */
286 /* If the return code is zero, this function must fill in request_buf pointer */
288 smb_init(int smb_command, int wct, struct cifsTconInfo *tcon,
289 void **request_buf /* returned */ ,
290 void **response_buf /* returned */ )
294 /* SMBs NegProt, SessSetup, uLogoff do not have tcon yet so
295 check for tcp and smb session status done differently
296 for those three - in the calling routine */
298 if (tcon->tidStatus == CifsExiting) {
299 /* only tree disconnect, open, and write,
300 (and ulogoff which does not have tcon)
301 are allowed as we start force umount */
302 if ((smb_command != SMB_COM_WRITE_ANDX) &&
303 (smb_command != SMB_COM_OPEN_ANDX) &&
304 (smb_command != SMB_COM_TREE_DISCONNECT)) {
305 cFYI(1, ("can not send cmd %d while umounting",
311 if ((tcon->ses) && (tcon->ses->status != CifsExiting) &&
312 (tcon->ses->server)) {
313 struct nls_table *nls_codepage;
314 /* Give Demultiplex thread up to 10 seconds to
315 reconnect, should be greater than cifs socket
316 timeout which is 7 seconds */
317 while (tcon->ses->server->tcpStatus ==
319 wait_event_interruptible_timeout(tcon->ses->server->response_q,
320 (tcon->ses->server->tcpStatus ==
322 if (tcon->ses->server->tcpStatus ==
324 /* on "soft" mounts we wait once */
326 (tcon->ses->status == CifsExiting)) {
327 cFYI(1, ("gave up waiting on "
328 "reconnect in smb_init"));
330 } /* else "hard" mount - keep retrying
331 until process is killed or server
333 } else /* TCP session is reestablished now */
336 nls_codepage = load_nls_default();
337 /* need to prevent multiple threads trying to
338 simultaneously reconnect the same SMB session */
339 down(&tcon->ses->sesSem);
340 if (tcon->ses->need_reconnect)
341 rc = cifs_setup_session(0, tcon->ses,
343 if (!rc && (tcon->need_reconnect)) {
344 mark_open_files_invalid(tcon);
345 rc = CIFSTCon(0, tcon->ses, tcon->treeName,
347 up(&tcon->ses->sesSem);
348 /* BB FIXME add code to check if wsize needs
349 update due to negotiated smb buffer size
352 atomic_inc(&tconInfoReconnectCount);
353 /* tell server Unix caps we support */
354 if (tcon->ses->capabilities & CAP_UNIX)
355 reset_cifs_unix_caps(
358 NULL /* do not know sb */,
359 NULL /* no vol info */);
362 cFYI(1, ("reconnect tcon rc = %d", rc));
363 /* Removed call to reopen open files here.
364 It is safer (and faster) to reopen files
365 one at a time as needed in read and write */
367 /* Check if handle based operation so we
368 know whether we can continue or not without
369 returning to caller to reset file handle */
370 switch (smb_command) {
371 case SMB_COM_READ_ANDX:
372 case SMB_COM_WRITE_ANDX:
374 case SMB_COM_FIND_CLOSE2:
375 case SMB_COM_LOCKING_ANDX: {
376 unload_nls(nls_codepage);
381 up(&tcon->ses->sesSem);
383 unload_nls(nls_codepage);
392 *request_buf = cifs_buf_get();
393 if (*request_buf == NULL) {
394 /* BB should we add a retry in here if not a writepage? */
397 /* Although the original thought was we needed the response buf for */
398 /* potential retries of smb operations it turns out we can determine */
399 /* from the mid flags when the request buffer can be resent without */
400 /* having to use a second distinct buffer for the response */
402 *response_buf = *request_buf;
404 header_assemble((struct smb_hdr *) *request_buf, smb_command, tcon,
408 cifs_stats_inc(&tcon->num_smbs_sent);
413 static int validate_t2(struct smb_t2_rsp *pSMB)
419 /* check for plausible wct, bcc and t2 data and parm sizes */
420 /* check for parm and data offset going beyond end of smb */
421 if (pSMB->hdr.WordCount >= 10) {
422 if ((le16_to_cpu(pSMB->t2_rsp.ParameterOffset) <= 1024) &&
423 (le16_to_cpu(pSMB->t2_rsp.DataOffset) <= 1024)) {
424 /* check that bcc is at least as big as parms + data */
425 /* check that bcc is less than negotiated smb buffer */
426 total_size = le16_to_cpu(pSMB->t2_rsp.ParameterCount);
427 if (total_size < 512) {
429 le16_to_cpu(pSMB->t2_rsp.DataCount);
430 /* BCC le converted in SendReceive */
431 pBCC = (pSMB->hdr.WordCount * 2) +
432 sizeof(struct smb_hdr) +
434 if ((total_size <= (*(u16 *)pBCC)) &&
436 CIFSMaxBufSize+MAX_CIFS_HDR_SIZE)) {
442 cifs_dump_mem("Invalid transact2 SMB: ", (char *)pSMB,
443 sizeof(struct smb_t2_rsp) + 16);
447 CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses)
450 NEGOTIATE_RSP *pSMBr;
454 struct TCP_Server_Info *server;
456 unsigned int secFlags;
460 server = ses->server;
465 rc = smb_init(SMB_COM_NEGOTIATE, 0, NULL /* no tcon yet */ ,
466 (void **) &pSMB, (void **) &pSMBr);
470 /* if any of auth flags (ie not sign or seal) are overriden use them */
471 if (ses->overrideSecFlg & (~(CIFSSEC_MUST_SIGN | CIFSSEC_MUST_SEAL)))
472 secFlags = ses->overrideSecFlg; /* BB FIXME fix sign flags? */
473 else /* if override flags set only sign/seal OR them with global auth */
474 secFlags = extended_security | ses->overrideSecFlg;
476 cFYI(1, ("secFlags 0x%x", secFlags));
478 pSMB->hdr.Mid = GetNextMid(server);
479 pSMB->hdr.Flags2 |= (SMBFLG2_UNICODE | SMBFLG2_ERR_STATUS);
481 if ((secFlags & CIFSSEC_MUST_KRB5) == CIFSSEC_MUST_KRB5)
482 pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC;
483 else if ((secFlags & CIFSSEC_AUTH_MASK) == CIFSSEC_MAY_KRB5) {
484 cFYI(1, ("Kerberos only mechanism, enable extended security"));
485 pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC;
489 for (i = 0; i < CIFS_NUM_PROT; i++) {
490 strncpy(pSMB->DialectsArray+count, protocols[i].name, 16);
491 count += strlen(protocols[i].name) + 1;
492 /* null at end of source and target buffers anyway */
494 pSMB->hdr.smb_buf_length += count;
495 pSMB->ByteCount = cpu_to_le16(count);
497 rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB,
498 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
502 dialect = le16_to_cpu(pSMBr->DialectIndex);
503 cFYI(1, ("Dialect: %d", dialect));
504 /* Check wct = 1 error case */
505 if ((pSMBr->hdr.WordCount < 13) || (dialect == BAD_PROT)) {
506 /* core returns wct = 1, but we do not ask for core - otherwise
507 small wct just comes when dialect index is -1 indicating we
508 could not negotiate a common dialect */
511 #ifdef CONFIG_CIFS_WEAK_PW_HASH
512 } else if ((pSMBr->hdr.WordCount == 13)
513 && ((dialect == LANMAN_PROT)
514 || (dialect == LANMAN2_PROT))) {
516 struct lanman_neg_rsp *rsp = (struct lanman_neg_rsp *)pSMBr;
518 if ((secFlags & CIFSSEC_MAY_LANMAN) ||
519 (secFlags & CIFSSEC_MAY_PLNTXT))
520 server->secType = LANMAN;
522 cERROR(1, ("mount failed weak security disabled"
523 " in /proc/fs/cifs/SecurityFlags"));
527 server->secMode = (__u8)le16_to_cpu(rsp->SecurityMode);
528 server->maxReq = le16_to_cpu(rsp->MaxMpxCount);
529 server->maxBuf = min((__u32)le16_to_cpu(rsp->MaxBufSize),
530 (__u32)CIFSMaxBufSize + MAX_CIFS_HDR_SIZE);
531 server->max_vcs = le16_to_cpu(rsp->MaxNumberVcs);
532 GETU32(server->sessid) = le32_to_cpu(rsp->SessionKey);
533 /* even though we do not use raw we might as well set this
534 accurately, in case we ever find a need for it */
535 if ((le16_to_cpu(rsp->RawMode) & RAW_ENABLE) == RAW_ENABLE) {
536 server->max_rw = 0xFF00;
537 server->capabilities = CAP_MPX_MODE | CAP_RAW_MODE;
539 server->max_rw = 0;/* do not need to use raw anyway */
540 server->capabilities = CAP_MPX_MODE;
542 tmp = (__s16)le16_to_cpu(rsp->ServerTimeZone);
544 /* OS/2 often does not set timezone therefore
545 * we must use server time to calc time zone.
546 * Could deviate slightly from the right zone.
547 * Smallest defined timezone difference is 15 minutes
548 * (i.e. Nepal). Rounding up/down is done to match
551 int val, seconds, remain, result;
552 struct timespec ts, utc;
554 ts = cnvrtDosUnixTm(le16_to_cpu(rsp->SrvTime.Date),
555 le16_to_cpu(rsp->SrvTime.Time));
556 cFYI(1, ("SrvTime %d sec since 1970 (utc: %d) diff: %d",
557 (int)ts.tv_sec, (int)utc.tv_sec,
558 (int)(utc.tv_sec - ts.tv_sec)));
559 val = (int)(utc.tv_sec - ts.tv_sec);
561 result = (seconds / MIN_TZ_ADJ) * MIN_TZ_ADJ;
562 remain = seconds % MIN_TZ_ADJ;
563 if (remain >= (MIN_TZ_ADJ / 2))
564 result += MIN_TZ_ADJ;
567 server->timeAdj = result;
569 server->timeAdj = (int)tmp;
570 server->timeAdj *= 60; /* also in seconds */
572 cFYI(1, ("server->timeAdj: %d seconds", server->timeAdj));
575 /* BB get server time for time conversions and add
576 code to use it and timezone since this is not UTC */
578 if (rsp->EncryptionKeyLength ==
579 cpu_to_le16(CIFS_CRYPTO_KEY_SIZE)) {
580 memcpy(server->cryptKey, rsp->EncryptionKey,
581 CIFS_CRYPTO_KEY_SIZE);
582 } else if (server->secMode & SECMODE_PW_ENCRYPT) {
583 rc = -EIO; /* need cryptkey unless plain text */
587 cFYI(1, ("LANMAN negotiated"));
588 /* we will not end up setting signing flags - as no signing
589 was in LANMAN and server did not return the flags on */
591 #else /* weak security disabled */
592 } else if (pSMBr->hdr.WordCount == 13) {
593 cERROR(1, ("mount failed, cifs module not built "
594 "with CIFS_WEAK_PW_HASH support"));
596 #endif /* WEAK_PW_HASH */
598 } else if (pSMBr->hdr.WordCount != 17) {
603 /* else wct == 17 NTLM */
604 server->secMode = pSMBr->SecurityMode;
605 if ((server->secMode & SECMODE_USER) == 0)
606 cFYI(1, ("share mode security"));
608 if ((server->secMode & SECMODE_PW_ENCRYPT) == 0)
609 #ifdef CONFIG_CIFS_WEAK_PW_HASH
610 if ((secFlags & CIFSSEC_MAY_PLNTXT) == 0)
611 #endif /* CIFS_WEAK_PW_HASH */
612 cERROR(1, ("Server requests plain text password"
613 " but client support disabled"));
615 if ((secFlags & CIFSSEC_MUST_NTLMV2) == CIFSSEC_MUST_NTLMV2)
616 server->secType = NTLMv2;
617 else if (secFlags & CIFSSEC_MAY_NTLM)
618 server->secType = NTLM;
619 else if (secFlags & CIFSSEC_MAY_NTLMV2)
620 server->secType = NTLMv2;
621 else if (secFlags & CIFSSEC_MAY_KRB5)
622 server->secType = Kerberos;
623 else if (secFlags & CIFSSEC_MAY_LANMAN)
624 server->secType = LANMAN;
625 /* #ifdef CONFIG_CIFS_EXPERIMENTAL
626 else if (secFlags & CIFSSEC_MAY_PLNTXT)
631 cERROR(1, ("Invalid security type"));
634 /* else ... any others ...? */
636 /* one byte, so no need to convert this or EncryptionKeyLen from
638 server->maxReq = le16_to_cpu(pSMBr->MaxMpxCount);
639 /* probably no need to store and check maxvcs */
640 server->maxBuf = min(le32_to_cpu(pSMBr->MaxBufferSize),
641 (__u32) CIFSMaxBufSize + MAX_CIFS_HDR_SIZE);
642 server->max_rw = le32_to_cpu(pSMBr->MaxRawSize);
643 cFYI(DBG2, ("Max buf = %d", ses->server->maxBuf));
644 GETU32(ses->server->sessid) = le32_to_cpu(pSMBr->SessionKey);
645 server->capabilities = le32_to_cpu(pSMBr->Capabilities);
646 server->timeAdj = (int)(__s16)le16_to_cpu(pSMBr->ServerTimeZone);
647 server->timeAdj *= 60;
648 if (pSMBr->EncryptionKeyLength == CIFS_CRYPTO_KEY_SIZE) {
649 memcpy(server->cryptKey, pSMBr->u.EncryptionKey,
650 CIFS_CRYPTO_KEY_SIZE);
651 } else if ((pSMBr->hdr.Flags2 & SMBFLG2_EXT_SEC)
652 && (pSMBr->EncryptionKeyLength == 0)) {
653 /* decode security blob */
654 } else if (server->secMode & SECMODE_PW_ENCRYPT) {
655 rc = -EIO; /* no crypt key only if plain text pwd */
659 /* BB might be helpful to save off the domain of server here */
661 if ((pSMBr->hdr.Flags2 & SMBFLG2_EXT_SEC) &&
662 (server->capabilities & CAP_EXTENDED_SECURITY)) {
663 count = pSMBr->ByteCount;
668 read_lock(&cifs_tcp_ses_lock);
669 if (server->srv_count > 1) {
670 read_unlock(&cifs_tcp_ses_lock);
671 if (memcmp(server->server_GUID,
672 pSMBr->u.extended_response.
674 cFYI(1, ("server UID changed"));
675 memcpy(server->server_GUID,
676 pSMBr->u.extended_response.GUID,
680 read_unlock(&cifs_tcp_ses_lock);
681 memcpy(server->server_GUID,
682 pSMBr->u.extended_response.GUID, 16);
686 server->secType = RawNTLMSSP;
688 rc = decode_negTokenInit(pSMBr->u.extended_response.
698 server->capabilities &= ~CAP_EXTENDED_SECURITY;
700 #ifdef CONFIG_CIFS_WEAK_PW_HASH
703 if ((secFlags & CIFSSEC_MAY_SIGN) == 0) {
704 /* MUST_SIGN already includes the MAY_SIGN FLAG
705 so if this is zero it means that signing is disabled */
706 cFYI(1, ("Signing disabled"));
707 if (server->secMode & SECMODE_SIGN_REQUIRED) {
708 cERROR(1, ("Server requires "
709 "packet signing to be enabled in "
710 "/proc/fs/cifs/SecurityFlags."));
714 ~(SECMODE_SIGN_ENABLED | SECMODE_SIGN_REQUIRED);
715 } else if ((secFlags & CIFSSEC_MUST_SIGN) == CIFSSEC_MUST_SIGN) {
716 /* signing required */
717 cFYI(1, ("Must sign - secFlags 0x%x", secFlags));
718 if ((server->secMode &
719 (SECMODE_SIGN_ENABLED | SECMODE_SIGN_REQUIRED)) == 0) {
721 ("signing required but server lacks support"));
724 server->secMode |= SECMODE_SIGN_REQUIRED;
726 /* signing optional ie CIFSSEC_MAY_SIGN */
727 if ((server->secMode & SECMODE_SIGN_REQUIRED) == 0)
729 ~(SECMODE_SIGN_ENABLED | SECMODE_SIGN_REQUIRED);
733 cifs_buf_release(pSMB);
735 cFYI(1, ("negprot rc %d", rc));
740 CIFSSMBTDis(const int xid, struct cifsTconInfo *tcon)
742 struct smb_hdr *smb_buffer;
745 cFYI(1, ("In tree disconnect"));
747 /* BB: do we need to check this? These should never be NULL. */
748 if ((tcon->ses == NULL) || (tcon->ses->server == NULL))
752 * No need to return error on this operation if tid invalidated and
753 * closed on server already e.g. due to tcp session crashing. Also,
754 * the tcon is no longer on the list, so no need to take lock before
757 if (tcon->need_reconnect)
760 rc = small_smb_init(SMB_COM_TREE_DISCONNECT, 0, tcon,
761 (void **)&smb_buffer);
765 rc = SendReceiveNoRsp(xid, tcon->ses, smb_buffer, 0);
767 cFYI(1, ("Tree disconnect failed %d", rc));
769 /* No need to return error on this operation if tid invalidated and
770 closed on server already e.g. due to tcp session crashing */
778 CIFSSMBLogoff(const int xid, struct cifsSesInfo *ses)
780 LOGOFF_ANDX_REQ *pSMB;
783 cFYI(1, ("In SMBLogoff for session disconnect"));
786 * BB: do we need to check validity of ses and server? They should
787 * always be valid since we have an active reference. If not, that
788 * should probably be a BUG()
790 if (!ses || !ses->server)
794 if (ses->need_reconnect)
795 goto session_already_dead; /* no need to send SMBlogoff if uid
796 already closed due to reconnect */
797 rc = small_smb_init(SMB_COM_LOGOFF_ANDX, 2, NULL, (void **)&pSMB);
803 pSMB->hdr.Mid = GetNextMid(ses->server);
805 if (ses->server->secMode &
806 (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
807 pSMB->hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
809 pSMB->hdr.Uid = ses->Suid;
811 pSMB->AndXCommand = 0xFF;
812 rc = SendReceiveNoRsp(xid, ses, (struct smb_hdr *) pSMB, 0);
813 session_already_dead:
816 /* if session dead then we do not need to do ulogoff,
817 since server closed smb session, no sense reporting
825 CIFSPOSIXDelFile(const int xid, struct cifsTconInfo *tcon, const char *fileName,
826 __u16 type, const struct nls_table *nls_codepage, int remap)
828 TRANSACTION2_SPI_REQ *pSMB = NULL;
829 TRANSACTION2_SPI_RSP *pSMBr = NULL;
830 struct unlink_psx_rq *pRqD;
833 int bytes_returned = 0;
834 __u16 params, param_offset, offset, byte_count;
836 cFYI(1, ("In POSIX delete"));
838 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
843 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
845 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
846 PATH_MAX, nls_codepage, remap);
847 name_len++; /* trailing null */
849 } else { /* BB add path length overrun check */
850 name_len = strnlen(fileName, PATH_MAX);
851 name_len++; /* trailing null */
852 strncpy(pSMB->FileName, fileName, name_len);
855 params = 6 + name_len;
856 pSMB->MaxParameterCount = cpu_to_le16(2);
857 pSMB->MaxDataCount = 0; /* BB double check this with jra */
858 pSMB->MaxSetupCount = 0;
863 param_offset = offsetof(struct smb_com_transaction2_spi_req,
864 InformationLevel) - 4;
865 offset = param_offset + params;
867 /* Setup pointer to Request Data (inode type) */
868 pRqD = (struct unlink_psx_rq *)(((char *)&pSMB->hdr.Protocol) + offset);
869 pRqD->type = cpu_to_le16(type);
870 pSMB->ParameterOffset = cpu_to_le16(param_offset);
871 pSMB->DataOffset = cpu_to_le16(offset);
872 pSMB->SetupCount = 1;
874 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
875 byte_count = 3 /* pad */ + params + sizeof(struct unlink_psx_rq);
877 pSMB->DataCount = cpu_to_le16(sizeof(struct unlink_psx_rq));
878 pSMB->TotalDataCount = cpu_to_le16(sizeof(struct unlink_psx_rq));
879 pSMB->ParameterCount = cpu_to_le16(params);
880 pSMB->TotalParameterCount = pSMB->ParameterCount;
881 pSMB->InformationLevel = cpu_to_le16(SMB_POSIX_UNLINK);
883 pSMB->hdr.smb_buf_length += byte_count;
884 pSMB->ByteCount = cpu_to_le16(byte_count);
885 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
886 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
888 cFYI(1, ("Posix delete returned %d", rc));
889 cifs_buf_release(pSMB);
891 cifs_stats_inc(&tcon->num_deletes);
900 CIFSSMBDelFile(const int xid, struct cifsTconInfo *tcon, const char *fileName,
901 const struct nls_table *nls_codepage, int remap)
903 DELETE_FILE_REQ *pSMB = NULL;
904 DELETE_FILE_RSP *pSMBr = NULL;
910 rc = smb_init(SMB_COM_DELETE, 1, tcon, (void **) &pSMB,
915 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
917 cifsConvertToUCS((__le16 *) pSMB->fileName, fileName,
918 PATH_MAX, nls_codepage, remap);
919 name_len++; /* trailing null */
921 } else { /* BB improve check for buffer overruns BB */
922 name_len = strnlen(fileName, PATH_MAX);
923 name_len++; /* trailing null */
924 strncpy(pSMB->fileName, fileName, name_len);
926 pSMB->SearchAttributes =
927 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM);
928 pSMB->BufferFormat = 0x04;
929 pSMB->hdr.smb_buf_length += name_len + 1;
930 pSMB->ByteCount = cpu_to_le16(name_len + 1);
931 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
932 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
933 cifs_stats_inc(&tcon->num_deletes);
935 cFYI(1, ("Error in RMFile = %d", rc));
937 cifs_buf_release(pSMB);
945 CIFSSMBRmDir(const int xid, struct cifsTconInfo *tcon, const char *dirName,
946 const struct nls_table *nls_codepage, int remap)
948 DELETE_DIRECTORY_REQ *pSMB = NULL;
949 DELETE_DIRECTORY_RSP *pSMBr = NULL;
954 cFYI(1, ("In CIFSSMBRmDir"));
956 rc = smb_init(SMB_COM_DELETE_DIRECTORY, 0, tcon, (void **) &pSMB,
961 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
962 name_len = cifsConvertToUCS((__le16 *) pSMB->DirName, dirName,
963 PATH_MAX, nls_codepage, remap);
964 name_len++; /* trailing null */
966 } else { /* BB improve check for buffer overruns BB */
967 name_len = strnlen(dirName, PATH_MAX);
968 name_len++; /* trailing null */
969 strncpy(pSMB->DirName, dirName, name_len);
972 pSMB->BufferFormat = 0x04;
973 pSMB->hdr.smb_buf_length += name_len + 1;
974 pSMB->ByteCount = cpu_to_le16(name_len + 1);
975 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
976 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
977 cifs_stats_inc(&tcon->num_rmdirs);
979 cFYI(1, ("Error in RMDir = %d", rc));
981 cifs_buf_release(pSMB);
988 CIFSSMBMkDir(const int xid, struct cifsTconInfo *tcon,
989 const char *name, const struct nls_table *nls_codepage, int remap)
992 CREATE_DIRECTORY_REQ *pSMB = NULL;
993 CREATE_DIRECTORY_RSP *pSMBr = NULL;
997 cFYI(1, ("In CIFSSMBMkDir"));
999 rc = smb_init(SMB_COM_CREATE_DIRECTORY, 0, tcon, (void **) &pSMB,
1004 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1005 name_len = cifsConvertToUCS((__le16 *) pSMB->DirName, name,
1006 PATH_MAX, nls_codepage, remap);
1007 name_len++; /* trailing null */
1009 } else { /* BB improve check for buffer overruns BB */
1010 name_len = strnlen(name, PATH_MAX);
1011 name_len++; /* trailing null */
1012 strncpy(pSMB->DirName, name, name_len);
1015 pSMB->BufferFormat = 0x04;
1016 pSMB->hdr.smb_buf_length += name_len + 1;
1017 pSMB->ByteCount = cpu_to_le16(name_len + 1);
1018 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1019 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1020 cifs_stats_inc(&tcon->num_mkdirs);
1022 cFYI(1, ("Error in Mkdir = %d", rc));
1024 cifs_buf_release(pSMB);
1031 CIFSPOSIXCreate(const int xid, struct cifsTconInfo *tcon, __u32 posix_flags,
1032 __u64 mode, __u16 *netfid, FILE_UNIX_BASIC_INFO *pRetData,
1033 __u32 *pOplock, const char *name,
1034 const struct nls_table *nls_codepage, int remap)
1036 TRANSACTION2_SPI_REQ *pSMB = NULL;
1037 TRANSACTION2_SPI_RSP *pSMBr = NULL;
1040 int bytes_returned = 0;
1041 __u16 params, param_offset, offset, byte_count, count;
1042 OPEN_PSX_REQ *pdata;
1043 OPEN_PSX_RSP *psx_rsp;
1045 cFYI(1, ("In POSIX Create"));
1047 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
1052 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1054 cifsConvertToUCS((__le16 *) pSMB->FileName, name,
1055 PATH_MAX, nls_codepage, remap);
1056 name_len++; /* trailing null */
1058 } else { /* BB improve the check for buffer overruns BB */
1059 name_len = strnlen(name, PATH_MAX);
1060 name_len++; /* trailing null */
1061 strncpy(pSMB->FileName, name, name_len);
1064 params = 6 + name_len;
1065 count = sizeof(OPEN_PSX_REQ);
1066 pSMB->MaxParameterCount = cpu_to_le16(2);
1067 pSMB->MaxDataCount = cpu_to_le16(1000); /* large enough */
1068 pSMB->MaxSetupCount = 0;
1072 pSMB->Reserved2 = 0;
1073 param_offset = offsetof(struct smb_com_transaction2_spi_req,
1074 InformationLevel) - 4;
1075 offset = param_offset + params;
1076 pdata = (OPEN_PSX_REQ *)(((char *)&pSMB->hdr.Protocol) + offset);
1077 pdata->Level = cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC);
1078 pdata->Permissions = cpu_to_le64(mode);
1079 pdata->PosixOpenFlags = cpu_to_le32(posix_flags);
1080 pdata->OpenFlags = cpu_to_le32(*pOplock);
1081 pSMB->ParameterOffset = cpu_to_le16(param_offset);
1082 pSMB->DataOffset = cpu_to_le16(offset);
1083 pSMB->SetupCount = 1;
1084 pSMB->Reserved3 = 0;
1085 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
1086 byte_count = 3 /* pad */ + params + count;
1088 pSMB->DataCount = cpu_to_le16(count);
1089 pSMB->ParameterCount = cpu_to_le16(params);
1090 pSMB->TotalDataCount = pSMB->DataCount;
1091 pSMB->TotalParameterCount = pSMB->ParameterCount;
1092 pSMB->InformationLevel = cpu_to_le16(SMB_POSIX_OPEN);
1093 pSMB->Reserved4 = 0;
1094 pSMB->hdr.smb_buf_length += byte_count;
1095 pSMB->ByteCount = cpu_to_le16(byte_count);
1096 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1097 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1099 cFYI(1, ("Posix create returned %d", rc));
1100 goto psx_create_err;
1103 cFYI(1, ("copying inode info"));
1104 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
1106 if (rc || (pSMBr->ByteCount < sizeof(OPEN_PSX_RSP))) {
1107 rc = -EIO; /* bad smb */
1108 goto psx_create_err;
1111 /* copy return information to pRetData */
1112 psx_rsp = (OPEN_PSX_RSP *)((char *) &pSMBr->hdr.Protocol
1113 + le16_to_cpu(pSMBr->t2.DataOffset));
1115 *pOplock = le16_to_cpu(psx_rsp->OplockFlags);
1117 *netfid = psx_rsp->Fid; /* cifs fid stays in le */
1118 /* Let caller know file was created so we can set the mode. */
1119 /* Do we care about the CreateAction in any other cases? */
1120 if (cpu_to_le32(FILE_CREATE) == psx_rsp->CreateAction)
1121 *pOplock |= CIFS_CREATE_ACTION;
1122 /* check to make sure response data is there */
1123 if (psx_rsp->ReturnedLevel != cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC)) {
1124 pRetData->Type = cpu_to_le32(-1); /* unknown */
1125 cFYI(DBG2, ("unknown type"));
1127 if (pSMBr->ByteCount < sizeof(OPEN_PSX_RSP)
1128 + sizeof(FILE_UNIX_BASIC_INFO)) {
1129 cERROR(1, ("Open response data too small"));
1130 pRetData->Type = cpu_to_le32(-1);
1131 goto psx_create_err;
1133 memcpy((char *) pRetData,
1134 (char *)psx_rsp + sizeof(OPEN_PSX_RSP),
1135 sizeof(FILE_UNIX_BASIC_INFO));
1139 cifs_buf_release(pSMB);
1141 cifs_stats_inc(&tcon->num_mkdirs);
1149 static __u16 convert_disposition(int disposition)
1153 switch (disposition) {
1154 case FILE_SUPERSEDE:
1155 ofun = SMBOPEN_OCREATE | SMBOPEN_OTRUNC;
1158 ofun = SMBOPEN_OAPPEND;
1161 ofun = SMBOPEN_OCREATE;
1164 ofun = SMBOPEN_OCREATE | SMBOPEN_OAPPEND;
1166 case FILE_OVERWRITE:
1167 ofun = SMBOPEN_OTRUNC;
1169 case FILE_OVERWRITE_IF:
1170 ofun = SMBOPEN_OCREATE | SMBOPEN_OTRUNC;
1173 cFYI(1, ("unknown disposition %d", disposition));
1174 ofun = SMBOPEN_OAPPEND; /* regular open */
1180 access_flags_to_smbopen_mode(const int access_flags)
1182 int masked_flags = access_flags & (GENERIC_READ | GENERIC_WRITE);
1184 if (masked_flags == GENERIC_READ)
1185 return SMBOPEN_READ;
1186 else if (masked_flags == GENERIC_WRITE)
1187 return SMBOPEN_WRITE;
1189 /* just go for read/write */
1190 return SMBOPEN_READWRITE;
1194 SMBLegacyOpen(const int xid, struct cifsTconInfo *tcon,
1195 const char *fileName, const int openDisposition,
1196 const int access_flags, const int create_options, __u16 *netfid,
1197 int *pOplock, FILE_ALL_INFO *pfile_info,
1198 const struct nls_table *nls_codepage, int remap)
1201 OPENX_REQ *pSMB = NULL;
1202 OPENX_RSP *pSMBr = NULL;
1208 rc = smb_init(SMB_COM_OPEN_ANDX, 15, tcon, (void **) &pSMB,
1213 pSMB->AndXCommand = 0xFF; /* none */
1215 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1216 count = 1; /* account for one byte pad to word boundary */
1218 cifsConvertToUCS((__le16 *) (pSMB->fileName + 1),
1219 fileName, PATH_MAX, nls_codepage, remap);
1220 name_len++; /* trailing null */
1222 } else { /* BB improve check for buffer overruns BB */
1223 count = 0; /* no pad */
1224 name_len = strnlen(fileName, PATH_MAX);
1225 name_len++; /* trailing null */
1226 strncpy(pSMB->fileName, fileName, name_len);
1228 if (*pOplock & REQ_OPLOCK)
1229 pSMB->OpenFlags = cpu_to_le16(REQ_OPLOCK);
1230 else if (*pOplock & REQ_BATCHOPLOCK)
1231 pSMB->OpenFlags = cpu_to_le16(REQ_BATCHOPLOCK);
1233 pSMB->OpenFlags |= cpu_to_le16(REQ_MORE_INFO);
1234 pSMB->Mode = cpu_to_le16(access_flags_to_smbopen_mode(access_flags));
1235 pSMB->Mode |= cpu_to_le16(0x40); /* deny none */
1236 /* set file as system file if special file such
1237 as fifo and server expecting SFU style and
1238 no Unix extensions */
1240 if (create_options & CREATE_OPTION_SPECIAL)
1241 pSMB->FileAttributes = cpu_to_le16(ATTR_SYSTEM);
1242 else /* BB FIXME BB */
1243 pSMB->FileAttributes = cpu_to_le16(0/*ATTR_NORMAL*/);
1245 if (create_options & CREATE_OPTION_READONLY)
1246 pSMB->FileAttributes |= cpu_to_le16(ATTR_READONLY);
1249 /* pSMB->CreateOptions = cpu_to_le32(create_options &
1250 CREATE_OPTIONS_MASK); */
1251 /* BB FIXME END BB */
1253 pSMB->Sattr = cpu_to_le16(ATTR_HIDDEN | ATTR_SYSTEM | ATTR_DIRECTORY);
1254 pSMB->OpenFunction = cpu_to_le16(convert_disposition(openDisposition));
1256 pSMB->hdr.smb_buf_length += count;
1258 pSMB->ByteCount = cpu_to_le16(count);
1259 /* long_op set to 1 to allow for oplock break timeouts */
1260 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1261 (struct smb_hdr *)pSMBr, &bytes_returned, CIFS_LONG_OP);
1262 cifs_stats_inc(&tcon->num_opens);
1264 cFYI(1, ("Error in Open = %d", rc));
1266 /* BB verify if wct == 15 */
1268 /* *pOplock = pSMBr->OplockLevel; */ /* BB take from action field*/
1270 *netfid = pSMBr->Fid; /* cifs fid stays in le */
1271 /* Let caller know file was created so we can set the mode. */
1272 /* Do we care about the CreateAction in any other cases? */
1274 /* if (cpu_to_le32(FILE_CREATE) == pSMBr->CreateAction)
1275 *pOplock |= CIFS_CREATE_ACTION; */
1279 pfile_info->CreationTime = 0; /* BB convert CreateTime*/
1280 pfile_info->LastAccessTime = 0; /* BB fixme */
1281 pfile_info->LastWriteTime = 0; /* BB fixme */
1282 pfile_info->ChangeTime = 0; /* BB fixme */
1283 pfile_info->Attributes =
1284 cpu_to_le32(le16_to_cpu(pSMBr->FileAttributes));
1285 /* the file_info buf is endian converted by caller */
1286 pfile_info->AllocationSize =
1287 cpu_to_le64(le32_to_cpu(pSMBr->EndOfFile));
1288 pfile_info->EndOfFile = pfile_info->AllocationSize;
1289 pfile_info->NumberOfLinks = cpu_to_le32(1);
1290 pfile_info->DeletePending = 0;
1294 cifs_buf_release(pSMB);
1301 CIFSSMBOpen(const int xid, struct cifsTconInfo *tcon,
1302 const char *fileName, const int openDisposition,
1303 const int access_flags, const int create_options, __u16 *netfid,
1304 int *pOplock, FILE_ALL_INFO *pfile_info,
1305 const struct nls_table *nls_codepage, int remap)
1308 OPEN_REQ *pSMB = NULL;
1309 OPEN_RSP *pSMBr = NULL;
1315 rc = smb_init(SMB_COM_NT_CREATE_ANDX, 24, tcon, (void **) &pSMB,
1320 pSMB->AndXCommand = 0xFF; /* none */
1322 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1323 count = 1; /* account for one byte pad to word boundary */
1325 cifsConvertToUCS((__le16 *) (pSMB->fileName + 1),
1326 fileName, PATH_MAX, nls_codepage, remap);
1327 name_len++; /* trailing null */
1329 pSMB->NameLength = cpu_to_le16(name_len);
1330 } else { /* BB improve check for buffer overruns BB */
1331 count = 0; /* no pad */
1332 name_len = strnlen(fileName, PATH_MAX);
1333 name_len++; /* trailing null */
1334 pSMB->NameLength = cpu_to_le16(name_len);
1335 strncpy(pSMB->fileName, fileName, name_len);
1337 if (*pOplock & REQ_OPLOCK)
1338 pSMB->OpenFlags = cpu_to_le32(REQ_OPLOCK);
1339 else if (*pOplock & REQ_BATCHOPLOCK)
1340 pSMB->OpenFlags = cpu_to_le32(REQ_BATCHOPLOCK);
1341 pSMB->DesiredAccess = cpu_to_le32(access_flags);
1342 pSMB->AllocationSize = 0;
1343 /* set file as system file if special file such
1344 as fifo and server expecting SFU style and
1345 no Unix extensions */
1346 if (create_options & CREATE_OPTION_SPECIAL)
1347 pSMB->FileAttributes = cpu_to_le32(ATTR_SYSTEM);
1349 pSMB->FileAttributes = cpu_to_le32(ATTR_NORMAL);
1351 /* XP does not handle ATTR_POSIX_SEMANTICS */
1352 /* but it helps speed up case sensitive checks for other
1353 servers such as Samba */
1354 if (tcon->ses->capabilities & CAP_UNIX)
1355 pSMB->FileAttributes |= cpu_to_le32(ATTR_POSIX_SEMANTICS);
1357 if (create_options & CREATE_OPTION_READONLY)
1358 pSMB->FileAttributes |= cpu_to_le32(ATTR_READONLY);
1360 pSMB->ShareAccess = cpu_to_le32(FILE_SHARE_ALL);
1361 pSMB->CreateDisposition = cpu_to_le32(openDisposition);
1362 pSMB->CreateOptions = cpu_to_le32(create_options & CREATE_OPTIONS_MASK);
1363 /* BB Expirement with various impersonation levels and verify */
1364 pSMB->ImpersonationLevel = cpu_to_le32(SECURITY_IMPERSONATION);
1365 pSMB->SecurityFlags =
1366 SECURITY_CONTEXT_TRACKING | SECURITY_EFFECTIVE_ONLY;
1369 pSMB->hdr.smb_buf_length += count;
1371 pSMB->ByteCount = cpu_to_le16(count);
1372 /* long_op set to 1 to allow for oplock break timeouts */
1373 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1374 (struct smb_hdr *)pSMBr, &bytes_returned, CIFS_LONG_OP);
1375 cifs_stats_inc(&tcon->num_opens);
1377 cFYI(1, ("Error in Open = %d", rc));
1379 *pOplock = pSMBr->OplockLevel; /* 1 byte no need to le_to_cpu */
1380 *netfid = pSMBr->Fid; /* cifs fid stays in le */
1381 /* Let caller know file was created so we can set the mode. */
1382 /* Do we care about the CreateAction in any other cases? */
1383 if (cpu_to_le32(FILE_CREATE) == pSMBr->CreateAction)
1384 *pOplock |= CIFS_CREATE_ACTION;
1386 memcpy((char *)pfile_info, (char *)&pSMBr->CreationTime,
1387 36 /* CreationTime to Attributes */);
1388 /* the file_info buf is endian converted by caller */
1389 pfile_info->AllocationSize = pSMBr->AllocationSize;
1390 pfile_info->EndOfFile = pSMBr->EndOfFile;
1391 pfile_info->NumberOfLinks = cpu_to_le32(1);
1392 pfile_info->DeletePending = 0;
1396 cifs_buf_release(pSMB);
1403 CIFSSMBRead(const int xid, struct cifsTconInfo *tcon, const int netfid,
1404 const unsigned int count, const __u64 lseek, unsigned int *nbytes,
1405 char **buf, int *pbuf_type)
1408 READ_REQ *pSMB = NULL;
1409 READ_RSP *pSMBr = NULL;
1410 char *pReadData = NULL;
1412 int resp_buf_type = 0;
1415 cFYI(1, ("Reading %d bytes on fid %d", count, netfid));
1416 if (tcon->ses->capabilities & CAP_LARGE_FILES)
1419 wct = 10; /* old style read */
1420 if ((lseek >> 32) > 0) {
1421 /* can not handle this big offset for old */
1427 rc = small_smb_init(SMB_COM_READ_ANDX, wct, tcon, (void **) &pSMB);
1431 /* tcon and ses pointer are checked in smb_init */
1432 if (tcon->ses->server == NULL)
1433 return -ECONNABORTED;
1435 pSMB->AndXCommand = 0xFF; /* none */
1437 pSMB->OffsetLow = cpu_to_le32(lseek & 0xFFFFFFFF);
1439 pSMB->OffsetHigh = cpu_to_le32(lseek >> 32);
1441 pSMB->Remaining = 0;
1442 pSMB->MaxCount = cpu_to_le16(count & 0xFFFF);
1443 pSMB->MaxCountHigh = cpu_to_le32(count >> 16);
1445 pSMB->ByteCount = 0; /* no need to do le conversion since 0 */
1447 /* old style read */
1448 struct smb_com_readx_req *pSMBW =
1449 (struct smb_com_readx_req *)pSMB;
1450 pSMBW->ByteCount = 0;
1453 iov[0].iov_base = (char *)pSMB;
1454 iov[0].iov_len = pSMB->hdr.smb_buf_length + 4;
1455 rc = SendReceive2(xid, tcon->ses, iov, 1 /* num iovecs */,
1456 &resp_buf_type, CIFS_STD_OP | CIFS_LOG_ERROR);
1457 cifs_stats_inc(&tcon->num_reads);
1458 pSMBr = (READ_RSP *)iov[0].iov_base;
1460 cERROR(1, ("Send error in read = %d", rc));
1462 int data_length = le16_to_cpu(pSMBr->DataLengthHigh);
1463 data_length = data_length << 16;
1464 data_length += le16_to_cpu(pSMBr->DataLength);
1465 *nbytes = data_length;
1467 /*check that DataLength would not go beyond end of SMB */
1468 if ((data_length > CIFSMaxBufSize)
1469 || (data_length > count)) {
1470 cFYI(1, ("bad length %d for count %d",
1471 data_length, count));
1475 pReadData = (char *) (&pSMBr->hdr.Protocol) +
1476 le16_to_cpu(pSMBr->DataOffset);
1477 /* if (rc = copy_to_user(buf, pReadData, data_length)) {
1478 cERROR(1,("Faulting on read rc = %d",rc));
1480 }*/ /* can not use copy_to_user when using page cache*/
1482 memcpy(*buf, pReadData, data_length);
1486 /* cifs_small_buf_release(pSMB); */ /* Freed earlier now in SendReceive2 */
1488 if (resp_buf_type == CIFS_SMALL_BUFFER)
1489 cifs_small_buf_release(iov[0].iov_base);
1490 else if (resp_buf_type == CIFS_LARGE_BUFFER)
1491 cifs_buf_release(iov[0].iov_base);
1492 } else if (resp_buf_type != CIFS_NO_BUFFER) {
1493 /* return buffer to caller to free */
1494 *buf = iov[0].iov_base;
1495 if (resp_buf_type == CIFS_SMALL_BUFFER)
1496 *pbuf_type = CIFS_SMALL_BUFFER;
1497 else if (resp_buf_type == CIFS_LARGE_BUFFER)
1498 *pbuf_type = CIFS_LARGE_BUFFER;
1499 } /* else no valid buffer on return - leave as null */
1501 /* Note: On -EAGAIN error only caller can retry on handle based calls
1502 since file handle passed in no longer valid */
1508 CIFSSMBWrite(const int xid, struct cifsTconInfo *tcon,
1509 const int netfid, const unsigned int count,
1510 const __u64 offset, unsigned int *nbytes, const char *buf,
1511 const char __user *ubuf, const int long_op)
1514 WRITE_REQ *pSMB = NULL;
1515 WRITE_RSP *pSMBr = NULL;
1516 int bytes_returned, wct;
1520 /* cFYI(1, ("write at %lld %d bytes", offset, count));*/
1521 if (tcon->ses == NULL)
1522 return -ECONNABORTED;
1524 if (tcon->ses->capabilities & CAP_LARGE_FILES)
1528 if ((offset >> 32) > 0) {
1529 /* can not handle big offset for old srv */
1534 rc = smb_init(SMB_COM_WRITE_ANDX, wct, tcon, (void **) &pSMB,
1538 /* tcon and ses pointer are checked in smb_init */
1539 if (tcon->ses->server == NULL)
1540 return -ECONNABORTED;
1542 pSMB->AndXCommand = 0xFF; /* none */
1544 pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF);
1546 pSMB->OffsetHigh = cpu_to_le32(offset >> 32);
1548 pSMB->Reserved = 0xFFFFFFFF;
1549 pSMB->WriteMode = 0;
1550 pSMB->Remaining = 0;
1552 /* Can increase buffer size if buffer is big enough in some cases ie we
1553 can send more if LARGE_WRITE_X capability returned by the server and if
1554 our buffer is big enough or if we convert to iovecs on socket writes
1555 and eliminate the copy to the CIFS buffer */
1556 if (tcon->ses->capabilities & CAP_LARGE_WRITE_X) {
1557 bytes_sent = min_t(const unsigned int, CIFSMaxBufSize, count);
1559 bytes_sent = (tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE)
1563 if (bytes_sent > count)
1566 cpu_to_le16(offsetof(struct smb_com_write_req, Data) - 4);
1568 memcpy(pSMB->Data, buf, bytes_sent);
1570 if (copy_from_user(pSMB->Data, ubuf, bytes_sent)) {
1571 cifs_buf_release(pSMB);
1574 } else if (count != 0) {
1576 cifs_buf_release(pSMB);
1578 } /* else setting file size with write of zero bytes */
1580 byte_count = bytes_sent + 1; /* pad */
1581 else /* wct == 12 */
1582 byte_count = bytes_sent + 5; /* bigger pad, smaller smb hdr */
1584 pSMB->DataLengthLow = cpu_to_le16(bytes_sent & 0xFFFF);
1585 pSMB->DataLengthHigh = cpu_to_le16(bytes_sent >> 16);
1586 pSMB->hdr.smb_buf_length += byte_count;
1589 pSMB->ByteCount = cpu_to_le16(byte_count);
1590 else { /* old style write has byte count 4 bytes earlier
1592 struct smb_com_writex_req *pSMBW =
1593 (struct smb_com_writex_req *)pSMB;
1594 pSMBW->ByteCount = cpu_to_le16(byte_count);
1597 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1598 (struct smb_hdr *) pSMBr, &bytes_returned, long_op);
1599 cifs_stats_inc(&tcon->num_writes);
1601 cFYI(1, ("Send error in write = %d", rc));
1604 *nbytes = le16_to_cpu(pSMBr->CountHigh);
1605 *nbytes = (*nbytes) << 16;
1606 *nbytes += le16_to_cpu(pSMBr->Count);
1609 cifs_buf_release(pSMB);
1611 /* Note: On -EAGAIN error only caller can retry on handle based calls
1612 since file handle passed in no longer valid */
1618 CIFSSMBWrite2(const int xid, struct cifsTconInfo *tcon,
1619 const int netfid, const unsigned int count,
1620 const __u64 offset, unsigned int *nbytes, struct kvec *iov,
1621 int n_vec, const int long_op)
1624 WRITE_REQ *pSMB = NULL;
1627 int resp_buf_type = 0;
1629 cFYI(1, ("write2 at %lld %d bytes", (long long)offset, count));
1631 if (tcon->ses->capabilities & CAP_LARGE_FILES) {
1635 if ((offset >> 32) > 0) {
1636 /* can not handle big offset for old srv */
1640 rc = small_smb_init(SMB_COM_WRITE_ANDX, wct, tcon, (void **) &pSMB);
1643 /* tcon and ses pointer are checked in smb_init */
1644 if (tcon->ses->server == NULL)
1645 return -ECONNABORTED;
1647 pSMB->AndXCommand = 0xFF; /* none */
1649 pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF);
1651 pSMB->OffsetHigh = cpu_to_le32(offset >> 32);
1652 pSMB->Reserved = 0xFFFFFFFF;
1653 pSMB->WriteMode = 0;
1654 pSMB->Remaining = 0;
1657 cpu_to_le16(offsetof(struct smb_com_write_req, Data) - 4);
1659 pSMB->DataLengthLow = cpu_to_le16(count & 0xFFFF);
1660 pSMB->DataLengthHigh = cpu_to_le16(count >> 16);
1661 smb_hdr_len = pSMB->hdr.smb_buf_length + 1; /* hdr + 1 byte pad */
1663 pSMB->hdr.smb_buf_length += count+1;
1664 else /* wct == 12 */
1665 pSMB->hdr.smb_buf_length += count+5; /* smb data starts later */
1667 pSMB->ByteCount = cpu_to_le16(count + 1);
1668 else /* wct == 12 */ /* bigger pad, smaller smb hdr, keep offset ok */ {
1669 struct smb_com_writex_req *pSMBW =
1670 (struct smb_com_writex_req *)pSMB;
1671 pSMBW->ByteCount = cpu_to_le16(count + 5);
1673 iov[0].iov_base = pSMB;
1675 iov[0].iov_len = smb_hdr_len + 4;
1676 else /* wct == 12 pad bigger by four bytes */
1677 iov[0].iov_len = smb_hdr_len + 8;
1680 rc = SendReceive2(xid, tcon->ses, iov, n_vec + 1, &resp_buf_type,
1682 cifs_stats_inc(&tcon->num_writes);
1684 cFYI(1, ("Send error Write2 = %d", rc));
1686 } else if (resp_buf_type == 0) {
1687 /* presumably this can not happen, but best to be safe */
1691 WRITE_RSP *pSMBr = (WRITE_RSP *)iov[0].iov_base;
1692 *nbytes = le16_to_cpu(pSMBr->CountHigh);
1693 *nbytes = (*nbytes) << 16;
1694 *nbytes += le16_to_cpu(pSMBr->Count);
1697 /* cifs_small_buf_release(pSMB); */ /* Freed earlier now in SendReceive2 */
1698 if (resp_buf_type == CIFS_SMALL_BUFFER)
1699 cifs_small_buf_release(iov[0].iov_base);
1700 else if (resp_buf_type == CIFS_LARGE_BUFFER)
1701 cifs_buf_release(iov[0].iov_base);
1703 /* Note: On -EAGAIN error only caller can retry on handle based calls
1704 since file handle passed in no longer valid */
1711 CIFSSMBLock(const int xid, struct cifsTconInfo *tcon,
1712 const __u16 smb_file_id, const __u64 len,
1713 const __u64 offset, const __u32 numUnlock,
1714 const __u32 numLock, const __u8 lockType, const bool waitFlag)
1717 LOCK_REQ *pSMB = NULL;
1718 /* LOCK_RSP *pSMBr = NULL; */ /* No response data other than rc to parse */
1723 cFYI(1, ("CIFSSMBLock timeout %d numLock %d", (int)waitFlag, numLock));
1724 rc = small_smb_init(SMB_COM_LOCKING_ANDX, 8, tcon, (void **) &pSMB);
1729 if (lockType == LOCKING_ANDX_OPLOCK_RELEASE) {
1730 timeout = CIFS_ASYNC_OP; /* no response expected */
1732 } else if (waitFlag) {
1733 timeout = CIFS_BLOCKING_OP; /* blocking operation, no timeout */
1734 pSMB->Timeout = cpu_to_le32(-1);/* blocking - do not time out */
1739 pSMB->NumberOfLocks = cpu_to_le16(numLock);
1740 pSMB->NumberOfUnlocks = cpu_to_le16(numUnlock);
1741 pSMB->LockType = lockType;
1742 pSMB->AndXCommand = 0xFF; /* none */
1743 pSMB->Fid = smb_file_id; /* netfid stays le */
1745 if ((numLock != 0) || (numUnlock != 0)) {
1746 pSMB->Locks[0].Pid = cpu_to_le16(current->tgid);
1747 /* BB where to store pid high? */
1748 pSMB->Locks[0].LengthLow = cpu_to_le32((u32)len);
1749 pSMB->Locks[0].LengthHigh = cpu_to_le32((u32)(len>>32));
1750 pSMB->Locks[0].OffsetLow = cpu_to_le32((u32)offset);
1751 pSMB->Locks[0].OffsetHigh = cpu_to_le32((u32)(offset>>32));
1752 count = sizeof(LOCKING_ANDX_RANGE);
1757 pSMB->hdr.smb_buf_length += count;
1758 pSMB->ByteCount = cpu_to_le16(count);
1761 rc = SendReceiveBlockingLock(xid, tcon, (struct smb_hdr *) pSMB,
1762 (struct smb_hdr *) pSMB, &bytes_returned);
1763 cifs_small_buf_release(pSMB);
1765 rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *)pSMB,
1767 /* SMB buffer freed by function above */
1769 cifs_stats_inc(&tcon->num_locks);
1771 cFYI(1, ("Send error in Lock = %d", rc));
1773 /* Note: On -EAGAIN error only caller can retry on handle based calls
1774 since file handle passed in no longer valid */
1779 CIFSSMBPosixLock(const int xid, struct cifsTconInfo *tcon,
1780 const __u16 smb_file_id, const int get_flag, const __u64 len,
1781 struct file_lock *pLockData, const __u16 lock_type,
1782 const bool waitFlag)
1784 struct smb_com_transaction2_sfi_req *pSMB = NULL;
1785 struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
1786 struct cifs_posix_lock *parm_data;
1789 int bytes_returned = 0;
1790 int resp_buf_type = 0;
1791 __u16 params, param_offset, offset, byte_count, count;
1794 cFYI(1, ("Posix Lock"));
1796 if (pLockData == NULL)
1799 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
1804 pSMBr = (struct smb_com_transaction2_sfi_rsp *)pSMB;
1807 pSMB->MaxSetupCount = 0;
1810 pSMB->Reserved2 = 0;
1811 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
1812 offset = param_offset + params;
1814 count = sizeof(struct cifs_posix_lock);
1815 pSMB->MaxParameterCount = cpu_to_le16(2);
1816 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB from sess */
1817 pSMB->SetupCount = 1;
1818 pSMB->Reserved3 = 0;
1820 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION);
1822 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
1823 byte_count = 3 /* pad */ + params + count;
1824 pSMB->DataCount = cpu_to_le16(count);
1825 pSMB->ParameterCount = cpu_to_le16(params);
1826 pSMB->TotalDataCount = pSMB->DataCount;
1827 pSMB->TotalParameterCount = pSMB->ParameterCount;
1828 pSMB->ParameterOffset = cpu_to_le16(param_offset);
1829 parm_data = (struct cifs_posix_lock *)
1830 (((char *) &pSMB->hdr.Protocol) + offset);
1832 parm_data->lock_type = cpu_to_le16(lock_type);
1834 timeout = CIFS_BLOCKING_OP; /* blocking operation, no timeout */
1835 parm_data->lock_flags = cpu_to_le16(1);
1836 pSMB->Timeout = cpu_to_le32(-1);
1840 parm_data->pid = cpu_to_le32(current->tgid);
1841 parm_data->start = cpu_to_le64(pLockData->fl_start);
1842 parm_data->length = cpu_to_le64(len); /* normalize negative numbers */
1844 pSMB->DataOffset = cpu_to_le16(offset);
1845 pSMB->Fid = smb_file_id;
1846 pSMB->InformationLevel = cpu_to_le16(SMB_SET_POSIX_LOCK);
1847 pSMB->Reserved4 = 0;
1848 pSMB->hdr.smb_buf_length += byte_count;
1849 pSMB->ByteCount = cpu_to_le16(byte_count);
1851 rc = SendReceiveBlockingLock(xid, tcon, (struct smb_hdr *) pSMB,
1852 (struct smb_hdr *) pSMBr, &bytes_returned);
1854 iov[0].iov_base = (char *)pSMB;
1855 iov[0].iov_len = pSMB->hdr.smb_buf_length + 4;
1856 rc = SendReceive2(xid, tcon->ses, iov, 1 /* num iovecs */,
1857 &resp_buf_type, timeout);
1858 pSMB = NULL; /* request buf already freed by SendReceive2. Do
1859 not try to free it twice below on exit */
1860 pSMBr = (struct smb_com_transaction2_sfi_rsp *)iov[0].iov_base;
1864 cFYI(1, ("Send error in Posix Lock = %d", rc));
1865 } else if (get_flag) {
1866 /* lock structure can be returned on get */
1869 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
1871 if (rc || (pSMBr->ByteCount < sizeof(struct cifs_posix_lock))) {
1872 rc = -EIO; /* bad smb */
1875 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
1876 data_count = le16_to_cpu(pSMBr->t2.DataCount);
1877 if (data_count < sizeof(struct cifs_posix_lock)) {
1881 parm_data = (struct cifs_posix_lock *)
1882 ((char *)&pSMBr->hdr.Protocol + data_offset);
1883 if (parm_data->lock_type == cpu_to_le16(CIFS_UNLCK))
1884 pLockData->fl_type = F_UNLCK;
1889 cifs_small_buf_release(pSMB);
1891 if (resp_buf_type == CIFS_SMALL_BUFFER)
1892 cifs_small_buf_release(iov[0].iov_base);
1893 else if (resp_buf_type == CIFS_LARGE_BUFFER)
1894 cifs_buf_release(iov[0].iov_base);
1896 /* Note: On -EAGAIN error only caller can retry on handle based calls
1897 since file handle passed in no longer valid */
1904 CIFSSMBClose(const int xid, struct cifsTconInfo *tcon, int smb_file_id)
1907 CLOSE_REQ *pSMB = NULL;
1908 cFYI(1, ("In CIFSSMBClose"));
1910 /* do not retry on dead session on close */
1911 rc = small_smb_init(SMB_COM_CLOSE, 3, tcon, (void **) &pSMB);
1917 pSMB->FileID = (__u16) smb_file_id;
1918 pSMB->LastWriteTime = 0xFFFFFFFF;
1919 pSMB->ByteCount = 0;
1920 rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0);
1921 cifs_stats_inc(&tcon->num_closes);
1924 /* EINTR is expected when user ctl-c to kill app */
1925 cERROR(1, ("Send error in Close = %d", rc));
1929 /* Since session is dead, file will be closed on server already */
1937 CIFSSMBFlush(const int xid, struct cifsTconInfo *tcon, int smb_file_id)
1940 FLUSH_REQ *pSMB = NULL;
1941 cFYI(1, ("In CIFSSMBFlush"));
1943 rc = small_smb_init(SMB_COM_FLUSH, 1, tcon, (void **) &pSMB);
1947 pSMB->FileID = (__u16) smb_file_id;
1948 pSMB->ByteCount = 0;
1949 rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0);
1950 cifs_stats_inc(&tcon->num_flushes);
1952 cERROR(1, ("Send error in Flush = %d", rc));
1958 CIFSSMBRename(const int xid, struct cifsTconInfo *tcon,
1959 const char *fromName, const char *toName,
1960 const struct nls_table *nls_codepage, int remap)
1963 RENAME_REQ *pSMB = NULL;
1964 RENAME_RSP *pSMBr = NULL;
1966 int name_len, name_len2;
1969 cFYI(1, ("In CIFSSMBRename"));
1971 rc = smb_init(SMB_COM_RENAME, 1, tcon, (void **) &pSMB,
1976 pSMB->BufferFormat = 0x04;
1977 pSMB->SearchAttributes =
1978 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
1981 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1983 cifsConvertToUCS((__le16 *) pSMB->OldFileName, fromName,
1984 PATH_MAX, nls_codepage, remap);
1985 name_len++; /* trailing null */
1987 pSMB->OldFileName[name_len] = 0x04; /* pad */
1988 /* protocol requires ASCII signature byte on Unicode string */
1989 pSMB->OldFileName[name_len + 1] = 0x00;
1991 cifsConvertToUCS((__le16 *)&pSMB->OldFileName[name_len + 2],
1992 toName, PATH_MAX, nls_codepage, remap);
1993 name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
1994 name_len2 *= 2; /* convert to bytes */
1995 } else { /* BB improve the check for buffer overruns BB */
1996 name_len = strnlen(fromName, PATH_MAX);
1997 name_len++; /* trailing null */
1998 strncpy(pSMB->OldFileName, fromName, name_len);
1999 name_len2 = strnlen(toName, PATH_MAX);
2000 name_len2++; /* trailing null */
2001 pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */
2002 strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2);
2003 name_len2++; /* trailing null */
2004 name_len2++; /* signature byte */
2007 count = 1 /* 1st signature byte */ + name_len + name_len2;
2008 pSMB->hdr.smb_buf_length += count;
2009 pSMB->ByteCount = cpu_to_le16(count);
2011 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2012 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2013 cifs_stats_inc(&tcon->num_renames);
2015 cFYI(1, ("Send error in rename = %d", rc));
2017 cifs_buf_release(pSMB);
2025 int CIFSSMBRenameOpenFile(const int xid, struct cifsTconInfo *pTcon,
2026 int netfid, const char *target_name,
2027 const struct nls_table *nls_codepage, int remap)
2029 struct smb_com_transaction2_sfi_req *pSMB = NULL;
2030 struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
2031 struct set_file_rename *rename_info;
2033 char dummy_string[30];
2035 int bytes_returned = 0;
2037 __u16 params, param_offset, offset, count, byte_count;
2039 cFYI(1, ("Rename to File by handle"));
2040 rc = smb_init(SMB_COM_TRANSACTION2, 15, pTcon, (void **) &pSMB,
2046 pSMB->MaxSetupCount = 0;
2050 pSMB->Reserved2 = 0;
2051 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
2052 offset = param_offset + params;
2054 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
2055 rename_info = (struct set_file_rename *) data_offset;
2056 pSMB->MaxParameterCount = cpu_to_le16(2);
2057 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB from sess */
2058 pSMB->SetupCount = 1;
2059 pSMB->Reserved3 = 0;
2060 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
2061 byte_count = 3 /* pad */ + params;
2062 pSMB->ParameterCount = cpu_to_le16(params);
2063 pSMB->TotalParameterCount = pSMB->ParameterCount;
2064 pSMB->ParameterOffset = cpu_to_le16(param_offset);
2065 pSMB->DataOffset = cpu_to_le16(offset);
2066 /* construct random name ".cifs_tmp<inodenum><mid>" */
2067 rename_info->overwrite = cpu_to_le32(1);
2068 rename_info->root_fid = 0;
2069 /* unicode only call */
2070 if (target_name == NULL) {
2071 sprintf(dummy_string, "cifs%x", pSMB->hdr.Mid);
2072 len_of_str = cifsConvertToUCS((__le16 *)rename_info->target_name,
2073 dummy_string, 24, nls_codepage, remap);
2075 len_of_str = cifsConvertToUCS((__le16 *)rename_info->target_name,
2076 target_name, PATH_MAX, nls_codepage,
2079 rename_info->target_name_len = cpu_to_le32(2 * len_of_str);
2080 count = 12 /* sizeof(struct set_file_rename) */ + (2 * len_of_str);
2081 byte_count += count;
2082 pSMB->DataCount = cpu_to_le16(count);
2083 pSMB->TotalDataCount = pSMB->DataCount;
2085 pSMB->InformationLevel =
2086 cpu_to_le16(SMB_SET_FILE_RENAME_INFORMATION);
2087 pSMB->Reserved4 = 0;
2088 pSMB->hdr.smb_buf_length += byte_count;
2089 pSMB->ByteCount = cpu_to_le16(byte_count);
2090 rc = SendReceive(xid, pTcon->ses, (struct smb_hdr *) pSMB,
2091 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2092 cifs_stats_inc(&pTcon->num_t2renames);
2094 cFYI(1, ("Send error in Rename (by file handle) = %d", rc));
2096 cifs_buf_release(pSMB);
2098 /* Note: On -EAGAIN error only caller can retry on handle based calls
2099 since file handle passed in no longer valid */
2105 CIFSSMBCopy(const int xid, struct cifsTconInfo *tcon, const char *fromName,
2106 const __u16 target_tid, const char *toName, const int flags,
2107 const struct nls_table *nls_codepage, int remap)
2110 COPY_REQ *pSMB = NULL;
2111 COPY_RSP *pSMBr = NULL;
2113 int name_len, name_len2;
2116 cFYI(1, ("In CIFSSMBCopy"));
2118 rc = smb_init(SMB_COM_COPY, 1, tcon, (void **) &pSMB,
2123 pSMB->BufferFormat = 0x04;
2124 pSMB->Tid2 = target_tid;
2126 pSMB->Flags = cpu_to_le16(flags & COPY_TREE);
2128 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2129 name_len = cifsConvertToUCS((__le16 *) pSMB->OldFileName,
2130 fromName, PATH_MAX, nls_codepage,
2132 name_len++; /* trailing null */
2134 pSMB->OldFileName[name_len] = 0x04; /* pad */
2135 /* protocol requires ASCII signature byte on Unicode string */
2136 pSMB->OldFileName[name_len + 1] = 0x00;
2138 cifsConvertToUCS((__le16 *)&pSMB->OldFileName[name_len + 2],
2139 toName, PATH_MAX, nls_codepage, remap);
2140 name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
2141 name_len2 *= 2; /* convert to bytes */
2142 } else { /* BB improve the check for buffer overruns BB */
2143 name_len = strnlen(fromName, PATH_MAX);
2144 name_len++; /* trailing null */
2145 strncpy(pSMB->OldFileName, fromName, name_len);
2146 name_len2 = strnlen(toName, PATH_MAX);
2147 name_len2++; /* trailing null */
2148 pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */
2149 strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2);
2150 name_len2++; /* trailing null */
2151 name_len2++; /* signature byte */
2154 count = 1 /* 1st signature byte */ + name_len + name_len2;
2155 pSMB->hdr.smb_buf_length += count;
2156 pSMB->ByteCount = cpu_to_le16(count);
2158 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2159 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2161 cFYI(1, ("Send error in copy = %d with %d files copied",
2162 rc, le16_to_cpu(pSMBr->CopyCount)));
2164 cifs_buf_release(pSMB);
2173 CIFSUnixCreateSymLink(const int xid, struct cifsTconInfo *tcon,
2174 const char *fromName, const char *toName,
2175 const struct nls_table *nls_codepage)
2177 TRANSACTION2_SPI_REQ *pSMB = NULL;
2178 TRANSACTION2_SPI_RSP *pSMBr = NULL;
2181 int name_len_target;
2183 int bytes_returned = 0;
2184 __u16 params, param_offset, offset, byte_count;
2186 cFYI(1, ("In Symlink Unix style"));
2188 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2193 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2195 cifs_strtoUCS((__le16 *) pSMB->FileName, fromName, PATH_MAX
2196 /* find define for this maxpathcomponent */
2198 name_len++; /* trailing null */
2201 } else { /* BB improve the check for buffer overruns BB */
2202 name_len = strnlen(fromName, PATH_MAX);
2203 name_len++; /* trailing null */
2204 strncpy(pSMB->FileName, fromName, name_len);
2206 params = 6 + name_len;
2207 pSMB->MaxSetupCount = 0;
2211 pSMB->Reserved2 = 0;
2212 param_offset = offsetof(struct smb_com_transaction2_spi_req,
2213 InformationLevel) - 4;
2214 offset = param_offset + params;
2216 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
2217 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2219 cifs_strtoUCS((__le16 *) data_offset, toName, PATH_MAX
2220 /* find define for this maxpathcomponent */
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(toName, PATH_MAX);
2226 name_len_target++; /* trailing null */
2227 strncpy(data_offset, toName, 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->DataCount = cpu_to_le16(name_len_target);
2238 pSMB->ParameterCount = cpu_to_le16(params);
2239 pSMB->TotalDataCount = pSMB->DataCount;
2240 pSMB->TotalParameterCount = pSMB->ParameterCount;
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_LINK);
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_symlinks);
2251 cFYI(1, ("Send error in SetPathInfo create symlink = %d", rc));
2253 cifs_buf_release(pSMB);
2256 goto createSymLinkRetry;
2262 CIFSUnixCreateHardLink(const int xid, struct cifsTconInfo *tcon,
2263 const char *fromName, const char *toName,
2264 const struct nls_table *nls_codepage, int remap)
2266 TRANSACTION2_SPI_REQ *pSMB = NULL;
2267 TRANSACTION2_SPI_RSP *pSMBr = NULL;
2270 int name_len_target;
2272 int bytes_returned = 0;
2273 __u16 params, param_offset, offset, byte_count;
2275 cFYI(1, ("In Create Hard link Unix style"));
2276 createHardLinkRetry:
2277 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2282 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2283 name_len = cifsConvertToUCS((__le16 *) pSMB->FileName, toName,
2284 PATH_MAX, nls_codepage, remap);
2285 name_len++; /* trailing null */
2288 } else { /* BB improve the check for buffer overruns BB */
2289 name_len = strnlen(toName, PATH_MAX);
2290 name_len++; /* trailing null */
2291 strncpy(pSMB->FileName, toName, name_len);
2293 params = 6 + name_len;
2294 pSMB->MaxSetupCount = 0;
2298 pSMB->Reserved2 = 0;
2299 param_offset = offsetof(struct smb_com_transaction2_spi_req,
2300 InformationLevel) - 4;
2301 offset = param_offset + params;
2303 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
2304 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2306 cifsConvertToUCS((__le16 *) data_offset, fromName, PATH_MAX,
2307 nls_codepage, remap);
2308 name_len_target++; /* trailing null */
2309 name_len_target *= 2;
2310 } else { /* BB improve the check for buffer overruns BB */
2311 name_len_target = strnlen(fromName, PATH_MAX);
2312 name_len_target++; /* trailing null */
2313 strncpy(data_offset, fromName, name_len_target);
2316 pSMB->MaxParameterCount = cpu_to_le16(2);
2317 /* BB find exact max on data count below from sess*/
2318 pSMB->MaxDataCount = cpu_to_le16(1000);
2319 pSMB->SetupCount = 1;
2320 pSMB->Reserved3 = 0;
2321 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
2322 byte_count = 3 /* pad */ + params + name_len_target;
2323 pSMB->ParameterCount = cpu_to_le16(params);
2324 pSMB->TotalParameterCount = pSMB->ParameterCount;
2325 pSMB->DataCount = cpu_to_le16(name_len_target);
2326 pSMB->TotalDataCount = pSMB->DataCount;
2327 pSMB->ParameterOffset = cpu_to_le16(param_offset);
2328 pSMB->DataOffset = cpu_to_le16(offset);
2329 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_HLINK);
2330 pSMB->Reserved4 = 0;
2331 pSMB->hdr.smb_buf_length += byte_count;
2332 pSMB->ByteCount = cpu_to_le16(byte_count);
2333 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2334 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2335 cifs_stats_inc(&tcon->num_hardlinks);
2337 cFYI(1, ("Send error in SetPathInfo (hard link) = %d", rc));
2339 cifs_buf_release(pSMB);
2341 goto createHardLinkRetry;
2347 CIFSCreateHardLink(const int xid, struct cifsTconInfo *tcon,
2348 const char *fromName, const char *toName,
2349 const struct nls_table *nls_codepage, int remap)
2352 NT_RENAME_REQ *pSMB = NULL;
2353 RENAME_RSP *pSMBr = NULL;
2355 int name_len, name_len2;
2358 cFYI(1, ("In CIFSCreateHardLink"));
2359 winCreateHardLinkRetry:
2361 rc = smb_init(SMB_COM_NT_RENAME, 4, tcon, (void **) &pSMB,
2366 pSMB->SearchAttributes =
2367 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
2369 pSMB->Flags = cpu_to_le16(CREATE_HARD_LINK);
2370 pSMB->ClusterCount = 0;
2372 pSMB->BufferFormat = 0x04;
2374 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2376 cifsConvertToUCS((__le16 *) pSMB->OldFileName, fromName,
2377 PATH_MAX, nls_codepage, remap);
2378 name_len++; /* trailing null */
2381 /* protocol specifies ASCII buffer format (0x04) for unicode */
2382 pSMB->OldFileName[name_len] = 0x04;
2383 pSMB->OldFileName[name_len + 1] = 0x00; /* pad */
2385 cifsConvertToUCS((__le16 *)&pSMB->OldFileName[name_len + 2],
2386 toName, PATH_MAX, nls_codepage, remap);
2387 name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
2388 name_len2 *= 2; /* convert to bytes */
2389 } else { /* BB improve the check for buffer overruns BB */
2390 name_len = strnlen(fromName, PATH_MAX);
2391 name_len++; /* trailing null */
2392 strncpy(pSMB->OldFileName, fromName, name_len);
2393 name_len2 = strnlen(toName, PATH_MAX);
2394 name_len2++; /* trailing null */
2395 pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */
2396 strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2);
2397 name_len2++; /* trailing null */
2398 name_len2++; /* signature byte */
2401 count = 1 /* string type byte */ + name_len + name_len2;
2402 pSMB->hdr.smb_buf_length += count;
2403 pSMB->ByteCount = cpu_to_le16(count);
2405 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2406 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2407 cifs_stats_inc(&tcon->num_hardlinks);
2409 cFYI(1, ("Send error in hard link (NT rename) = %d", rc));
2411 cifs_buf_release(pSMB);
2413 goto winCreateHardLinkRetry;
2419 CIFSSMBUnixQuerySymLink(const int xid, struct cifsTconInfo *tcon,
2420 const unsigned char *searchName,
2421 char *symlinkinfo, const int buflen,
2422 const struct nls_table *nls_codepage)
2424 /* SMB_QUERY_FILE_UNIX_LINK */
2425 TRANSACTION2_QPI_REQ *pSMB = NULL;
2426 TRANSACTION2_QPI_RSP *pSMBr = NULL;
2430 __u16 params, byte_count;
2432 cFYI(1, ("In QPathSymLinkInfo (Unix) for path %s", searchName));
2435 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2440 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2442 cifs_strtoUCS((__le16 *) pSMB->FileName, searchName,
2443 PATH_MAX, nls_codepage);
2444 name_len++; /* trailing null */
2446 } else { /* BB improve the check for buffer overruns BB */
2447 name_len = strnlen(searchName, PATH_MAX);
2448 name_len++; /* trailing null */
2449 strncpy(pSMB->FileName, searchName, name_len);
2452 params = 2 /* level */ + 4 /* rsrvd */ + name_len /* incl null */ ;
2453 pSMB->TotalDataCount = 0;
2454 pSMB->MaxParameterCount = cpu_to_le16(2);
2455 /* BB find exact max data count below from sess structure BB */
2456 pSMB->MaxDataCount = cpu_to_le16(4000);
2457 pSMB->MaxSetupCount = 0;
2461 pSMB->Reserved2 = 0;
2462 pSMB->ParameterOffset = cpu_to_le16(offsetof(
2463 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
2464 pSMB->DataCount = 0;
2465 pSMB->DataOffset = 0;
2466 pSMB->SetupCount = 1;
2467 pSMB->Reserved3 = 0;
2468 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
2469 byte_count = params + 1 /* pad */ ;
2470 pSMB->TotalParameterCount = cpu_to_le16(params);
2471 pSMB->ParameterCount = pSMB->TotalParameterCount;
2472 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_LINK);
2473 pSMB->Reserved4 = 0;
2474 pSMB->hdr.smb_buf_length += byte_count;
2475 pSMB->ByteCount = cpu_to_le16(byte_count);
2477 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2478 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2480 cFYI(1, ("Send error in QuerySymLinkInfo = %d", rc));
2482 /* decode response */
2484 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
2485 if (rc || (pSMBr->ByteCount < 2))
2486 /* BB also check enough total bytes returned */
2487 rc = -EIO; /* bad smb */
2489 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
2490 __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
2492 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
2493 name_len = UniStrnlen((wchar_t *) ((char *)
2494 &pSMBr->hdr.Protocol + data_offset),
2495 min_t(const int, buflen, count) / 2);
2496 /* BB FIXME investigate remapping reserved chars here */
2497 cifs_strfromUCS_le(symlinkinfo,
2498 (__le16 *) ((char *)&pSMBr->hdr.Protocol
2500 name_len, nls_codepage);
2502 strncpy(symlinkinfo,
2503 (char *) &pSMBr->hdr.Protocol +
2505 min_t(const int, buflen, count));
2507 symlinkinfo[buflen] = 0;
2508 /* just in case so calling code does not go off the end of buffer */
2511 cifs_buf_release(pSMB);
2513 goto querySymLinkRetry;
2517 #ifdef CONFIG_CIFS_EXPERIMENTAL
2518 /* Initialize NT TRANSACT SMB into small smb request buffer.
2519 This assumes that all NT TRANSACTS that we init here have
2520 total parm and data under about 400 bytes (to fit in small cifs
2521 buffer size), which is the case so far, it easily fits. NB:
2522 Setup words themselves and ByteCount
2523 MaxSetupCount (size of returned setup area) and
2524 MaxParameterCount (returned parms size) must be set by caller */
2526 smb_init_nttransact(const __u16 sub_command, const int setup_count,
2527 const int parm_len, struct cifsTconInfo *tcon,
2532 struct smb_com_ntransact_req *pSMB;
2534 rc = small_smb_init(SMB_COM_NT_TRANSACT, 19 + setup_count, tcon,
2538 *ret_buf = (void *)pSMB;
2540 pSMB->TotalParameterCount = cpu_to_le32(parm_len);
2541 pSMB->TotalDataCount = 0;
2542 pSMB->MaxDataCount = cpu_to_le32((tcon->ses->server->maxBuf -
2543 MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
2544 pSMB->ParameterCount = pSMB->TotalParameterCount;
2545 pSMB->DataCount = pSMB->TotalDataCount;
2546 temp_offset = offsetof(struct smb_com_ntransact_req, Parms) +
2547 (setup_count * 2) - 4 /* for rfc1001 length itself */;
2548 pSMB->ParameterOffset = cpu_to_le32(temp_offset);
2549 pSMB->DataOffset = cpu_to_le32(temp_offset + parm_len);
2550 pSMB->SetupCount = setup_count; /* no need to le convert byte fields */
2551 pSMB->SubCommand = cpu_to_le16(sub_command);
2556 validate_ntransact(char *buf, char **ppparm, char **ppdata,
2557 __u32 *pparmlen, __u32 *pdatalen)
2560 __u32 data_count, data_offset, parm_count, parm_offset;
2561 struct smb_com_ntransact_rsp *pSMBr;
2569 pSMBr = (struct smb_com_ntransact_rsp *)buf;
2571 /* ByteCount was converted from little endian in SendReceive */
2572 end_of_smb = 2 /* sizeof byte count */ + pSMBr->ByteCount +
2573 (char *)&pSMBr->ByteCount;
2575 data_offset = le32_to_cpu(pSMBr->DataOffset);
2576 data_count = le32_to_cpu(pSMBr->DataCount);
2577 parm_offset = le32_to_cpu(pSMBr->ParameterOffset);
2578 parm_count = le32_to_cpu(pSMBr->ParameterCount);
2580 *ppparm = (char *)&pSMBr->hdr.Protocol + parm_offset;
2581 *ppdata = (char *)&pSMBr->hdr.Protocol + data_offset;
2583 /* should we also check that parm and data areas do not overlap? */
2584 if (*ppparm > end_of_smb) {
2585 cFYI(1, ("parms start after end of smb"));
2587 } else if (parm_count + *ppparm > end_of_smb) {
2588 cFYI(1, ("parm end after end of smb"));
2590 } else if (*ppdata > end_of_smb) {
2591 cFYI(1, ("data starts after end of smb"));
2593 } else if (data_count + *ppdata > end_of_smb) {
2594 cFYI(1, ("data %p + count %d (%p) ends after end of smb %p start %p",
2595 *ppdata, data_count, (data_count + *ppdata),
2596 end_of_smb, pSMBr));
2598 } else if (parm_count + data_count > pSMBr->ByteCount) {
2599 cFYI(1, ("parm count and data count larger than SMB"));
2602 *pdatalen = data_count;
2603 *pparmlen = parm_count;
2606 #endif /* CIFS_EXPERIMENTAL */
2609 CIFSSMBQueryReparseLinkInfo(const int xid, struct cifsTconInfo *tcon,
2610 const unsigned char *searchName,
2611 char *symlinkinfo, const int buflen, __u16 fid,
2612 const struct nls_table *nls_codepage)
2617 struct smb_com_transaction_ioctl_req *pSMB;
2618 struct smb_com_transaction_ioctl_rsp *pSMBr;
2620 cFYI(1, ("In Windows reparse style QueryLink for path %s", searchName));
2621 rc = smb_init(SMB_COM_NT_TRANSACT, 23, tcon, (void **) &pSMB,
2626 pSMB->TotalParameterCount = 0 ;
2627 pSMB->TotalDataCount = 0;
2628 pSMB->MaxParameterCount = cpu_to_le32(2);
2629 /* BB find exact data count max from sess structure BB */
2630 pSMB->MaxDataCount = cpu_to_le32((tcon->ses->server->maxBuf -
2631 MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
2632 pSMB->MaxSetupCount = 4;
2634 pSMB->ParameterOffset = 0;
2635 pSMB->DataCount = 0;
2636 pSMB->DataOffset = 0;
2637 pSMB->SetupCount = 4;
2638 pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_IOCTL);
2639 pSMB->ParameterCount = pSMB->TotalParameterCount;
2640 pSMB->FunctionCode = cpu_to_le32(FSCTL_GET_REPARSE_POINT);
2641 pSMB->IsFsctl = 1; /* FSCTL */
2642 pSMB->IsRootFlag = 0;
2643 pSMB->Fid = fid; /* file handle always le */
2644 pSMB->ByteCount = 0;
2646 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2647 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2649 cFYI(1, ("Send error in QueryReparseLinkInfo = %d", rc));
2650 } else { /* decode response */
2651 __u32 data_offset = le32_to_cpu(pSMBr->DataOffset);
2652 __u32 data_count = le32_to_cpu(pSMBr->DataCount);
2653 if ((pSMBr->ByteCount < 2) || (data_offset > 512))
2654 /* BB also check enough total bytes returned */
2655 rc = -EIO; /* bad smb */
2657 if (data_count && (data_count < 2048)) {
2658 char *end_of_smb = 2 /* sizeof byte count */ +
2660 (char *)&pSMBr->ByteCount;
2662 struct reparse_data *reparse_buf =
2663 (struct reparse_data *)
2664 ((char *)&pSMBr->hdr.Protocol
2666 if ((char *)reparse_buf >= end_of_smb) {
2670 if ((reparse_buf->LinkNamesBuf +
2671 reparse_buf->TargetNameOffset +
2672 reparse_buf->TargetNameLen) >
2674 cFYI(1, ("reparse buf beyond SMB"));
2679 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
2680 name_len = UniStrnlen((wchar_t *)
2681 (reparse_buf->LinkNamesBuf +
2682 reparse_buf->TargetNameOffset),
2684 reparse_buf->TargetNameLen / 2));
2685 cifs_strfromUCS_le(symlinkinfo,
2686 (__le16 *) (reparse_buf->LinkNamesBuf +
2687 reparse_buf->TargetNameOffset),
2688 name_len, nls_codepage);
2689 } else { /* ASCII names */
2690 strncpy(symlinkinfo,
2691 reparse_buf->LinkNamesBuf +
2692 reparse_buf->TargetNameOffset,
2693 min_t(const int, buflen,
2694 reparse_buf->TargetNameLen));
2698 cFYI(1, ("Invalid return data count on "
2699 "get reparse info ioctl"));
2701 symlinkinfo[buflen] = 0; /* just in case so the caller
2702 does not go off the end of the buffer */
2703 cFYI(1, ("readlink result - %s", symlinkinfo));
2707 cifs_buf_release(pSMB);
2709 /* Note: On -EAGAIN error only caller can retry on handle based calls
2710 since file handle passed in no longer valid */
2715 #ifdef CONFIG_CIFS_POSIX
2717 /*Convert an Access Control Entry from wire format to local POSIX xattr format*/
2718 static void cifs_convert_ace(posix_acl_xattr_entry *ace,
2719 struct cifs_posix_ace *cifs_ace)
2721 /* u8 cifs fields do not need le conversion */
2722 ace->e_perm = cpu_to_le16(cifs_ace->cifs_e_perm);
2723 ace->e_tag = cpu_to_le16(cifs_ace->cifs_e_tag);
2724 ace->e_id = cpu_to_le32(le64_to_cpu(cifs_ace->cifs_uid));
2725 /* cFYI(1,("perm %d tag %d id %d",ace->e_perm,ace->e_tag,ace->e_id)); */
2730 /* Convert ACL from CIFS POSIX wire format to local Linux POSIX ACL xattr */
2731 static int cifs_copy_posix_acl(char *trgt, char *src, const int buflen,
2732 const int acl_type, const int size_of_data_area)
2737 struct cifs_posix_ace *pACE;
2738 struct cifs_posix_acl *cifs_acl = (struct cifs_posix_acl *)src;
2739 posix_acl_xattr_header *local_acl = (posix_acl_xattr_header *)trgt;
2741 if (le16_to_cpu(cifs_acl->version) != CIFS_ACL_VERSION)
2744 if (acl_type & ACL_TYPE_ACCESS) {
2745 count = le16_to_cpu(cifs_acl->access_entry_count);
2746 pACE = &cifs_acl->ace_array[0];
2747 size = sizeof(struct cifs_posix_acl);
2748 size += sizeof(struct cifs_posix_ace) * count;
2749 /* check if we would go beyond end of SMB */
2750 if (size_of_data_area < size) {
2751 cFYI(1, ("bad CIFS POSIX ACL size %d vs. %d",
2752 size_of_data_area, size));
2755 } else if (acl_type & ACL_TYPE_DEFAULT) {
2756 count = le16_to_cpu(cifs_acl->access_entry_count);
2757 size = sizeof(struct cifs_posix_acl);
2758 size += sizeof(struct cifs_posix_ace) * count;
2759 /* skip past access ACEs to get to default ACEs */
2760 pACE = &cifs_acl->ace_array[count];
2761 count = le16_to_cpu(cifs_acl->default_entry_count);
2762 size += sizeof(struct cifs_posix_ace) * count;
2763 /* check if we would go beyond end of SMB */
2764 if (size_of_data_area < size)
2771 size = posix_acl_xattr_size(count);
2772 if ((buflen == 0) || (local_acl == NULL)) {
2773 /* used to query ACL EA size */
2774 } else if (size > buflen) {
2776 } else /* buffer big enough */ {
2777 local_acl->a_version = cpu_to_le32(POSIX_ACL_XATTR_VERSION);
2778 for (i = 0; i < count ; i++) {
2779 cifs_convert_ace(&local_acl->a_entries[i], pACE);
2786 static __u16 convert_ace_to_cifs_ace(struct cifs_posix_ace *cifs_ace,
2787 const posix_acl_xattr_entry *local_ace)
2789 __u16 rc = 0; /* 0 = ACL converted ok */
2791 cifs_ace->cifs_e_perm = le16_to_cpu(local_ace->e_perm);
2792 cifs_ace->cifs_e_tag = le16_to_cpu(local_ace->e_tag);
2793 /* BB is there a better way to handle the large uid? */
2794 if (local_ace->e_id == cpu_to_le32(-1)) {
2795 /* Probably no need to le convert -1 on any arch but can not hurt */
2796 cifs_ace->cifs_uid = cpu_to_le64(-1);
2798 cifs_ace->cifs_uid = cpu_to_le64(le32_to_cpu(local_ace->e_id));
2799 /*cFYI(1,("perm %d tag %d id %d",ace->e_perm,ace->e_tag,ace->e_id));*/
2803 /* Convert ACL from local Linux POSIX xattr to CIFS POSIX ACL wire format */
2804 static __u16 ACL_to_cifs_posix(char *parm_data, const char *pACL,
2805 const int buflen, const int acl_type)
2808 struct cifs_posix_acl *cifs_acl = (struct cifs_posix_acl *)parm_data;
2809 posix_acl_xattr_header *local_acl = (posix_acl_xattr_header *)pACL;
2813 if ((buflen == 0) || (pACL == NULL) || (cifs_acl == NULL))
2816 count = posix_acl_xattr_count((size_t)buflen);
2817 cFYI(1, ("setting acl with %d entries from buf of length %d and "
2819 count, buflen, le32_to_cpu(local_acl->a_version)));
2820 if (le32_to_cpu(local_acl->a_version) != 2) {
2821 cFYI(1, ("unknown POSIX ACL version %d",
2822 le32_to_cpu(local_acl->a_version)));
2825 cifs_acl->version = cpu_to_le16(1);
2826 if (acl_type == ACL_TYPE_ACCESS)
2827 cifs_acl->access_entry_count = cpu_to_le16(count);
2828 else if (acl_type == ACL_TYPE_DEFAULT)
2829 cifs_acl->default_entry_count = cpu_to_le16(count);
2831 cFYI(1, ("unknown ACL type %d", acl_type));
2834 for (i = 0; i < count; i++) {
2835 rc = convert_ace_to_cifs_ace(&cifs_acl->ace_array[i],
2836 &local_acl->a_entries[i]);
2838 /* ACE not converted */
2843 rc = (__u16)(count * sizeof(struct cifs_posix_ace));
2844 rc += sizeof(struct cifs_posix_acl);
2845 /* BB add check to make sure ACL does not overflow SMB */
2851 CIFSSMBGetPosixACL(const int xid, struct cifsTconInfo *tcon,
2852 const unsigned char *searchName,
2853 char *acl_inf, const int buflen, const int acl_type,
2854 const struct nls_table *nls_codepage, int remap)
2856 /* SMB_QUERY_POSIX_ACL */
2857 TRANSACTION2_QPI_REQ *pSMB = NULL;
2858 TRANSACTION2_QPI_RSP *pSMBr = NULL;
2862 __u16 params, byte_count;
2864 cFYI(1, ("In GetPosixACL (Unix) for path %s", searchName));
2867 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2872 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2874 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
2875 PATH_MAX, nls_codepage, remap);
2876 name_len++; /* trailing null */
2878 pSMB->FileName[name_len] = 0;
2879 pSMB->FileName[name_len+1] = 0;
2880 } else { /* BB improve the check for buffer overruns BB */
2881 name_len = strnlen(searchName, PATH_MAX);
2882 name_len++; /* trailing null */
2883 strncpy(pSMB->FileName, searchName, name_len);
2886 params = 2 /* level */ + 4 /* rsrvd */ + name_len /* incl null */ ;
2887 pSMB->TotalDataCount = 0;
2888 pSMB->MaxParameterCount = cpu_to_le16(2);
2889 /* BB find exact max data count below from sess structure BB */
2890 pSMB->MaxDataCount = cpu_to_le16(4000);
2891 pSMB->MaxSetupCount = 0;
2895 pSMB->Reserved2 = 0;
2896 pSMB->ParameterOffset = cpu_to_le16(
2897 offsetof(struct smb_com_transaction2_qpi_req,
2898 InformationLevel) - 4);
2899 pSMB->DataCount = 0;
2900 pSMB->DataOffset = 0;
2901 pSMB->SetupCount = 1;
2902 pSMB->Reserved3 = 0;
2903 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
2904 byte_count = params + 1 /* pad */ ;
2905 pSMB->TotalParameterCount = cpu_to_le16(params);
2906 pSMB->ParameterCount = pSMB->TotalParameterCount;
2907 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_POSIX_ACL);
2908 pSMB->Reserved4 = 0;
2909 pSMB->hdr.smb_buf_length += byte_count;
2910 pSMB->ByteCount = cpu_to_le16(byte_count);
2912 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2913 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2914 cifs_stats_inc(&tcon->num_acl_get);
2916 cFYI(1, ("Send error in Query POSIX ACL = %d", rc));
2918 /* decode response */
2920 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
2921 if (rc || (pSMBr->ByteCount < 2))
2922 /* BB also check enough total bytes returned */
2923 rc = -EIO; /* bad smb */
2925 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
2926 __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
2927 rc = cifs_copy_posix_acl(acl_inf,
2928 (char *)&pSMBr->hdr.Protocol+data_offset,
2929 buflen, acl_type, count);
2932 cifs_buf_release(pSMB);
2939 CIFSSMBSetPosixACL(const int xid, struct cifsTconInfo *tcon,
2940 const unsigned char *fileName,
2941 const char *local_acl, const int buflen,
2943 const struct nls_table *nls_codepage, int remap)
2945 struct smb_com_transaction2_spi_req *pSMB = NULL;
2946 struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
2950 int bytes_returned = 0;
2951 __u16 params, byte_count, data_count, param_offset, offset;
2953 cFYI(1, ("In SetPosixACL (Unix) for path %s", fileName));
2955 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2959 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2961 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
2962 PATH_MAX, nls_codepage, remap);
2963 name_len++; /* trailing null */
2965 } else { /* BB improve the check for buffer overruns BB */
2966 name_len = strnlen(fileName, PATH_MAX);
2967 name_len++; /* trailing null */
2968 strncpy(pSMB->FileName, fileName, name_len);
2970 params = 6 + name_len;
2971 pSMB->MaxParameterCount = cpu_to_le16(2);
2972 /* BB find max SMB size from sess */
2973 pSMB->MaxDataCount = cpu_to_le16(1000);
2974 pSMB->MaxSetupCount = 0;
2978 pSMB->Reserved2 = 0;
2979 param_offset = offsetof(struct smb_com_transaction2_spi_req,
2980 InformationLevel) - 4;
2981 offset = param_offset + params;
2982 parm_data = ((char *) &pSMB->hdr.Protocol) + offset;
2983 pSMB->ParameterOffset = cpu_to_le16(param_offset);
2985 /* convert to on the wire format for POSIX ACL */
2986 data_count = ACL_to_cifs_posix(parm_data, local_acl, buflen, acl_type);
2988 if (data_count == 0) {
2990 goto setACLerrorExit;
2992 pSMB->DataOffset = cpu_to_le16(offset);
2993 pSMB->SetupCount = 1;
2994 pSMB->Reserved3 = 0;
2995 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
2996 pSMB->InformationLevel = cpu_to_le16(SMB_SET_POSIX_ACL);
2997 byte_count = 3 /* pad */ + params + data_count;
2998 pSMB->DataCount = cpu_to_le16(data_count);
2999 pSMB->TotalDataCount = pSMB->DataCount;
3000 pSMB->ParameterCount = cpu_to_le16(params);
3001 pSMB->TotalParameterCount = pSMB->ParameterCount;
3002 pSMB->Reserved4 = 0;
3003 pSMB->hdr.smb_buf_length += byte_count;
3004 pSMB->ByteCount = cpu_to_le16(byte_count);
3005 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3006 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3008 cFYI(1, ("Set POSIX ACL returned %d", rc));
3011 cifs_buf_release(pSMB);
3017 /* BB fix tabs in this function FIXME BB */
3019 CIFSGetExtAttr(const int xid, struct cifsTconInfo *tcon,
3020 const int netfid, __u64 *pExtAttrBits, __u64 *pMask)
3023 struct smb_t2_qfi_req *pSMB = NULL;
3024 struct smb_t2_qfi_rsp *pSMBr = NULL;
3026 __u16 params, byte_count;
3028 cFYI(1, ("In GetExtAttr"));
3033 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3038 params = 2 /* level */ + 2 /* fid */;
3039 pSMB->t2.TotalDataCount = 0;
3040 pSMB->t2.MaxParameterCount = cpu_to_le16(4);
3041 /* BB find exact max data count below from sess structure BB */
3042 pSMB->t2.MaxDataCount = cpu_to_le16(4000);
3043 pSMB->t2.MaxSetupCount = 0;
3044 pSMB->t2.Reserved = 0;
3046 pSMB->t2.Timeout = 0;
3047 pSMB->t2.Reserved2 = 0;
3048 pSMB->t2.ParameterOffset = cpu_to_le16(offsetof(struct smb_t2_qfi_req,
3050 pSMB->t2.DataCount = 0;
3051 pSMB->t2.DataOffset = 0;
3052 pSMB->t2.SetupCount = 1;
3053 pSMB->t2.Reserved3 = 0;
3054 pSMB->t2.SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION);
3055 byte_count = params + 1 /* pad */ ;
3056 pSMB->t2.TotalParameterCount = cpu_to_le16(params);
3057 pSMB->t2.ParameterCount = pSMB->t2.TotalParameterCount;
3058 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_ATTR_FLAGS);
3061 pSMB->hdr.smb_buf_length += byte_count;
3062 pSMB->t2.ByteCount = cpu_to_le16(byte_count);
3064 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3065 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3067 cFYI(1, ("error %d in GetExtAttr", rc));
3069 /* decode response */
3070 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3071 if (rc || (pSMBr->ByteCount < 2))
3072 /* BB also check enough total bytes returned */
3073 /* If rc should we check for EOPNOSUPP and
3074 disable the srvino flag? or in caller? */
3075 rc = -EIO; /* bad smb */
3077 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3078 __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
3079 struct file_chattr_info *pfinfo;
3080 /* BB Do we need a cast or hash here ? */
3082 cFYI(1, ("Illegal size ret in GetExtAttr"));
3086 pfinfo = (struct file_chattr_info *)
3087 (data_offset + (char *) &pSMBr->hdr.Protocol);
3088 *pExtAttrBits = le64_to_cpu(pfinfo->mode);
3089 *pMask = le64_to_cpu(pfinfo->mask);
3093 cifs_buf_release(pSMB);
3095 goto GetExtAttrRetry;
3099 #endif /* CONFIG_POSIX */
3101 #ifdef CONFIG_CIFS_EXPERIMENTAL
3102 /* Get Security Descriptor (by handle) from remote server for a file or dir */
3104 CIFSSMBGetCIFSACL(const int xid, struct cifsTconInfo *tcon, __u16 fid,
3105 struct cifs_ntsd **acl_inf, __u32 *pbuflen)
3109 QUERY_SEC_DESC_REQ *pSMB;
3112 cFYI(1, ("GetCifsACL"));
3117 rc = smb_init_nttransact(NT_TRANSACT_QUERY_SECURITY_DESC, 0,
3118 8 /* parm len */, tcon, (void **) &pSMB);
3122 pSMB->MaxParameterCount = cpu_to_le32(4);
3123 /* BB TEST with big acls that might need to be e.g. larger than 16K */
3124 pSMB->MaxSetupCount = 0;
3125 pSMB->Fid = fid; /* file handle always le */
3126 pSMB->AclFlags = cpu_to_le32(CIFS_ACL_OWNER | CIFS_ACL_GROUP |
3128 pSMB->ByteCount = cpu_to_le16(11); /* 3 bytes pad + 8 bytes parm */
3129 pSMB->hdr.smb_buf_length += 11;
3130 iov[0].iov_base = (char *)pSMB;
3131 iov[0].iov_len = pSMB->hdr.smb_buf_length + 4;
3133 rc = SendReceive2(xid, tcon->ses, iov, 1 /* num iovec */, &buf_type,
3135 cifs_stats_inc(&tcon->num_acl_get);
3137 cFYI(1, ("Send error in QuerySecDesc = %d", rc));
3138 } else { /* decode response */
3142 struct smb_com_ntransact_rsp *pSMBr;
3145 /* validate_nttransact */
3146 rc = validate_ntransact(iov[0].iov_base, (char **)&parm,
3147 &pdata, &parm_len, pbuflen);
3150 pSMBr = (struct smb_com_ntransact_rsp *)iov[0].iov_base;
3152 cFYI(1, ("smb %p parm %p data %p", pSMBr, parm, *acl_inf));
3154 if (le32_to_cpu(pSMBr->ParameterCount) != 4) {
3155 rc = -EIO; /* bad smb */
3160 /* BB check that data area is minimum length and as big as acl_len */
3162 acl_len = le32_to_cpu(*parm);
3163 if (acl_len != *pbuflen) {
3164 cERROR(1, ("acl length %d does not match %d",
3165 acl_len, *pbuflen));
3166 if (*pbuflen > acl_len)
3170 /* check if buffer is big enough for the acl
3171 header followed by the smallest SID */
3172 if ((*pbuflen < sizeof(struct cifs_ntsd) + 8) ||
3173 (*pbuflen >= 64 * 1024)) {
3174 cERROR(1, ("bad acl length %d", *pbuflen));
3178 *acl_inf = kmalloc(*pbuflen, GFP_KERNEL);
3179 if (*acl_inf == NULL) {
3183 memcpy(*acl_inf, pdata, *pbuflen);
3187 if (buf_type == CIFS_SMALL_BUFFER)
3188 cifs_small_buf_release(iov[0].iov_base);
3189 else if (buf_type == CIFS_LARGE_BUFFER)
3190 cifs_buf_release(iov[0].iov_base);
3191 /* cifs_small_buf_release(pSMB); */ /* Freed earlier now in SendReceive2 */
3196 CIFSSMBSetCIFSACL(const int xid, struct cifsTconInfo *tcon, __u16 fid,
3197 struct cifs_ntsd *pntsd, __u32 acllen)
3199 __u16 byte_count, param_count, data_count, param_offset, data_offset;
3201 int bytes_returned = 0;
3202 SET_SEC_DESC_REQ *pSMB = NULL;
3203 NTRANSACT_RSP *pSMBr = NULL;
3206 rc = smb_init(SMB_COM_NT_TRANSACT, 19, tcon, (void **) &pSMB,
3211 pSMB->MaxSetupCount = 0;
3215 param_offset = offsetof(struct smb_com_transaction_ssec_req, Fid) - 4;
3216 data_count = acllen;
3217 data_offset = param_offset + param_count;
3218 byte_count = 3 /* pad */ + param_count;
3220 pSMB->DataCount = cpu_to_le32(data_count);
3221 pSMB->TotalDataCount = pSMB->DataCount;
3222 pSMB->MaxParameterCount = cpu_to_le32(4);
3223 pSMB->MaxDataCount = cpu_to_le32(16384);
3224 pSMB->ParameterCount = cpu_to_le32(param_count);
3225 pSMB->ParameterOffset = cpu_to_le32(param_offset);
3226 pSMB->TotalParameterCount = pSMB->ParameterCount;
3227 pSMB->DataOffset = cpu_to_le32(data_offset);
3228 pSMB->SetupCount = 0;
3229 pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_SET_SECURITY_DESC);
3230 pSMB->ByteCount = cpu_to_le16(byte_count+data_count);
3232 pSMB->Fid = fid; /* file handle always le */
3233 pSMB->Reserved2 = 0;
3234 pSMB->AclFlags = cpu_to_le32(CIFS_ACL_DACL);
3236 if (pntsd && acllen) {
3237 memcpy((char *) &pSMBr->hdr.Protocol + data_offset,
3240 pSMB->hdr.smb_buf_length += (byte_count + data_count);
3243 pSMB->hdr.smb_buf_length += byte_count;
3245 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3246 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3248 cFYI(1, ("SetCIFSACL bytes_returned: %d, rc: %d", bytes_returned, rc));
3250 cFYI(1, ("Set CIFS ACL returned %d", rc));
3251 cifs_buf_release(pSMB);
3254 goto setCifsAclRetry;
3259 #endif /* CONFIG_CIFS_EXPERIMENTAL */
3261 /* Legacy Query Path Information call for lookup to old servers such
3263 int SMBQueryInformation(const int xid, struct cifsTconInfo *tcon,
3264 const unsigned char *searchName,
3265 FILE_ALL_INFO *pFinfo,
3266 const struct nls_table *nls_codepage, int remap)
3268 QUERY_INFORMATION_REQ *pSMB;
3269 QUERY_INFORMATION_RSP *pSMBr;
3274 cFYI(1, ("In SMBQPath path %s", searchName));
3276 rc = smb_init(SMB_COM_QUERY_INFORMATION, 0, tcon, (void **) &pSMB,
3281 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3283 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
3284 PATH_MAX, nls_codepage, remap);
3285 name_len++; /* trailing null */
3288 name_len = strnlen(searchName, PATH_MAX);
3289 name_len++; /* trailing null */
3290 strncpy(pSMB->FileName, searchName, name_len);
3292 pSMB->BufferFormat = 0x04;
3293 name_len++; /* account for buffer type byte */
3294 pSMB->hdr.smb_buf_length += (__u16) name_len;
3295 pSMB->ByteCount = cpu_to_le16(name_len);
3297 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3298 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3300 cFYI(1, ("Send error in QueryInfo = %d", rc));
3301 } else if (pFinfo) {
3303 __u32 time = le32_to_cpu(pSMBr->last_write_time);
3305 /* decode response */
3306 /* BB FIXME - add time zone adjustment BB */
3307 memset(pFinfo, 0, sizeof(FILE_ALL_INFO));
3310 /* decode time fields */
3311 pFinfo->ChangeTime = cpu_to_le64(cifs_UnixTimeToNT(ts));
3312 pFinfo->LastWriteTime = pFinfo->ChangeTime;
3313 pFinfo->LastAccessTime = 0;
3314 pFinfo->AllocationSize =
3315 cpu_to_le64(le32_to_cpu(pSMBr->size));
3316 pFinfo->EndOfFile = pFinfo->AllocationSize;
3317 pFinfo->Attributes =
3318 cpu_to_le32(le16_to_cpu(pSMBr->attr));
3320 rc = -EIO; /* bad buffer passed in */
3322 cifs_buf_release(pSMB);
3334 CIFSSMBQPathInfo(const int xid, struct cifsTconInfo *tcon,
3335 const unsigned char *searchName,
3336 FILE_ALL_INFO *pFindData,
3337 int legacy /* old style infolevel */,
3338 const struct nls_table *nls_codepage, int remap)
3340 /* level 263 SMB_QUERY_FILE_ALL_INFO */
3341 TRANSACTION2_QPI_REQ *pSMB = NULL;
3342 TRANSACTION2_QPI_RSP *pSMBr = NULL;
3346 __u16 params, byte_count;
3348 /* cFYI(1, ("In QPathInfo path %s", searchName)); */
3350 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3355 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3357 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
3358 PATH_MAX, nls_codepage, remap);
3359 name_len++; /* trailing null */
3361 } else { /* BB improve the check for buffer overruns BB */
3362 name_len = strnlen(searchName, PATH_MAX);
3363 name_len++; /* trailing null */
3364 strncpy(pSMB->FileName, searchName, name_len);
3367 params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */;
3368 pSMB->TotalDataCount = 0;
3369 pSMB->MaxParameterCount = cpu_to_le16(2);
3370 /* BB find exact max SMB PDU from sess structure BB */
3371 pSMB->MaxDataCount = cpu_to_le16(4000);
3372 pSMB->MaxSetupCount = 0;
3376 pSMB->Reserved2 = 0;
3377 pSMB->ParameterOffset = cpu_to_le16(offsetof(
3378 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
3379 pSMB->DataCount = 0;
3380 pSMB->DataOffset = 0;
3381 pSMB->SetupCount = 1;
3382 pSMB->Reserved3 = 0;
3383 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
3384 byte_count = params + 1 /* pad */ ;
3385 pSMB->TotalParameterCount = cpu_to_le16(params);
3386 pSMB->ParameterCount = pSMB->TotalParameterCount;
3388 pSMB->InformationLevel = cpu_to_le16(SMB_INFO_STANDARD);
3390 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_ALL_INFO);
3391 pSMB->Reserved4 = 0;
3392 pSMB->hdr.smb_buf_length += byte_count;
3393 pSMB->ByteCount = cpu_to_le16(byte_count);
3395 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3396 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3398 cFYI(1, ("Send error in QPathInfo = %d", rc));
3399 } else { /* decode response */
3400 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3402 if (rc) /* BB add auto retry on EOPNOTSUPP? */
3404 else if (!legacy && (pSMBr->ByteCount < 40))
3405 rc = -EIO; /* bad smb */
3406 else if (legacy && (pSMBr->ByteCount < 24))
3407 rc = -EIO; /* 24 or 26 expected but we do not read
3409 else if (pFindData) {
3411 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3413 /* On legacy responses we do not read the last field,
3414 EAsize, fortunately since it varies by subdialect and
3415 also note it differs on Set vs. Get, ie two bytes or 4
3416 bytes depending but we don't care here */
3418 size = sizeof(FILE_INFO_STANDARD);
3420 size = sizeof(FILE_ALL_INFO);
3421 memcpy((char *) pFindData,
3422 (char *) &pSMBr->hdr.Protocol +
3427 cifs_buf_release(pSMB);
3429 goto QPathInfoRetry;
3435 CIFSSMBUnixQPathInfo(const int xid, struct cifsTconInfo *tcon,
3436 const unsigned char *searchName,
3437 FILE_UNIX_BASIC_INFO *pFindData,
3438 const struct nls_table *nls_codepage, int remap)
3440 /* SMB_QUERY_FILE_UNIX_BASIC */
3441 TRANSACTION2_QPI_REQ *pSMB = NULL;
3442 TRANSACTION2_QPI_RSP *pSMBr = NULL;
3444 int bytes_returned = 0;
3446 __u16 params, byte_count;
3448 cFYI(1, ("In QPathInfo (Unix) the path %s", searchName));
3450 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3455 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3457 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
3458 PATH_MAX, nls_codepage, remap);
3459 name_len++; /* trailing null */
3461 } else { /* BB improve the check for buffer overruns BB */
3462 name_len = strnlen(searchName, PATH_MAX);
3463 name_len++; /* trailing null */
3464 strncpy(pSMB->FileName, searchName, name_len);
3467 params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */;
3468 pSMB->TotalDataCount = 0;
3469 pSMB->MaxParameterCount = cpu_to_le16(2);
3470 /* BB find exact max SMB PDU from sess structure BB */
3471 pSMB->MaxDataCount = cpu_to_le16(4000);
3472 pSMB->MaxSetupCount = 0;
3476 pSMB->Reserved2 = 0;
3477 pSMB->ParameterOffset = cpu_to_le16(offsetof(
3478 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
3479 pSMB->DataCount = 0;
3480 pSMB->DataOffset = 0;
3481 pSMB->SetupCount = 1;
3482 pSMB->Reserved3 = 0;
3483 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
3484 byte_count = params + 1 /* pad */ ;
3485 pSMB->TotalParameterCount = cpu_to_le16(params);
3486 pSMB->ParameterCount = pSMB->TotalParameterCount;
3487 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC);
3488 pSMB->Reserved4 = 0;
3489 pSMB->hdr.smb_buf_length += byte_count;
3490 pSMB->ByteCount = cpu_to_le16(byte_count);
3492 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3493 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3495 cFYI(1, ("Send error in QPathInfo = %d", rc));
3496 } else { /* decode response */
3497 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3499 if (rc || (pSMBr->ByteCount < sizeof(FILE_UNIX_BASIC_INFO))) {
3500 cERROR(1, ("Malformed FILE_UNIX_BASIC_INFO response.\n"
3501 "Unix Extensions can be disabled on mount "
3502 "by specifying the nosfu mount option."));
3503 rc = -EIO; /* bad smb */
3505 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3506 memcpy((char *) pFindData,
3507 (char *) &pSMBr->hdr.Protocol +
3509 sizeof(FILE_UNIX_BASIC_INFO));
3512 cifs_buf_release(pSMB);
3514 goto UnixQPathInfoRetry;
3519 /* xid, tcon, searchName and codepage are input parms, rest are returned */
3521 CIFSFindFirst(const int xid, struct cifsTconInfo *tcon,
3522 const char *searchName,
3523 const struct nls_table *nls_codepage,
3525 struct cifs_search_info *psrch_inf, int remap, const char dirsep)
3527 /* level 257 SMB_ */
3528 TRANSACTION2_FFIRST_REQ *pSMB = NULL;
3529 TRANSACTION2_FFIRST_RSP *pSMBr = NULL;
3530 T2_FFIRST_RSP_PARMS *parms;
3532 int bytes_returned = 0;
3534 __u16 params, byte_count;
3536 cFYI(1, ("In FindFirst for %s", searchName));
3539 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3544 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3546 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
3547 PATH_MAX, nls_codepage, remap);
3548 /* We can not add the asterik earlier in case
3549 it got remapped to 0xF03A as if it were part of the
3550 directory name instead of a wildcard */
3552 pSMB->FileName[name_len] = dirsep;
3553 pSMB->FileName[name_len+1] = 0;
3554 pSMB->FileName[name_len+2] = '*';
3555 pSMB->FileName[name_len+3] = 0;
3556 name_len += 4; /* now the trailing null */
3557 pSMB->FileName[name_len] = 0; /* null terminate just in case */
3558 pSMB->FileName[name_len+1] = 0;
3560 } else { /* BB add check for overrun of SMB buf BB */
3561 name_len = strnlen(searchName, PATH_MAX);
3562 /* BB fix here and in unicode clause above ie
3563 if (name_len > buffersize-header)
3564 free buffer exit; BB */
3565 strncpy(pSMB->FileName, searchName, name_len);
3566 pSMB->FileName[name_len] = dirsep;
3567 pSMB->FileName[name_len+1] = '*';
3568 pSMB->FileName[name_len+2] = 0;
3572 params = 12 + name_len /* includes null */ ;
3573 pSMB->TotalDataCount = 0; /* no EAs */
3574 pSMB->MaxParameterCount = cpu_to_le16(10);
3575 pSMB->MaxDataCount = cpu_to_le16((tcon->ses->server->maxBuf -
3576 MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
3577 pSMB->MaxSetupCount = 0;
3581 pSMB->Reserved2 = 0;
3582 byte_count = params + 1 /* pad */ ;
3583 pSMB->TotalParameterCount = cpu_to_le16(params);
3584 pSMB->ParameterCount = pSMB->TotalParameterCount;
3585 pSMB->ParameterOffset = cpu_to_le16(
3586 offsetof(struct smb_com_transaction2_ffirst_req, SearchAttributes)
3588 pSMB->DataCount = 0;
3589 pSMB->DataOffset = 0;
3590 pSMB->SetupCount = 1; /* one byte, no need to make endian neutral */
3591 pSMB->Reserved3 = 0;
3592 pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_FIRST);
3593 pSMB->SearchAttributes =
3594 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
3596 pSMB->SearchCount = cpu_to_le16(CIFSMaxBufSize/sizeof(FILE_UNIX_INFO));
3597 pSMB->SearchFlags = cpu_to_le16(CIFS_SEARCH_CLOSE_AT_END |
3598 CIFS_SEARCH_RETURN_RESUME);
3599 pSMB->InformationLevel = cpu_to_le16(psrch_inf->info_level);
3601 /* BB what should we set StorageType to? Does it matter? BB */
3602 pSMB->SearchStorageType = 0;
3603 pSMB->hdr.smb_buf_length += byte_count;
3604 pSMB->ByteCount = cpu_to_le16(byte_count);
3606 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3607 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3608 cifs_stats_inc(&tcon->num_ffirst);
3610 if (rc) {/* BB add logic to retry regular search if Unix search
3611 rejected unexpectedly by server */
3612 /* BB Add code to handle unsupported level rc */
3613 cFYI(1, ("Error in FindFirst = %d", rc));
3615 cifs_buf_release(pSMB);
3617 /* BB eventually could optimize out free and realloc of buf */
3620 goto findFirstRetry;
3621 } else { /* decode response */
3622 /* BB remember to free buffer if error BB */
3623 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3627 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
3628 psrch_inf->unicode = true;
3630 psrch_inf->unicode = false;
3632 psrch_inf->ntwrk_buf_start = (char *)pSMBr;
3633 psrch_inf->smallBuf = 0;
3634 psrch_inf->srch_entries_start =
3635 (char *) &pSMBr->hdr.Protocol +
3636 le16_to_cpu(pSMBr->t2.DataOffset);
3637 parms = (T2_FFIRST_RSP_PARMS *)((char *) &pSMBr->hdr.Protocol +
3638 le16_to_cpu(pSMBr->t2.ParameterOffset));
3640 if (parms->EndofSearch)
3641 psrch_inf->endOfSearch = true;
3643 psrch_inf->endOfSearch = false;
3645 psrch_inf->entries_in_buffer =
3646 le16_to_cpu(parms->SearchCount);
3647 psrch_inf->index_of_last_entry = 2 /* skip . and .. */ +
3648 psrch_inf->entries_in_buffer;
3649 lnoff = le16_to_cpu(parms->LastNameOffset);
3650 if (tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE <
3652 cERROR(1, ("ignoring corrupt resume name"));
3653 psrch_inf->last_entry = NULL;
3657 psrch_inf->last_entry = psrch_inf->srch_entries_start +
3660 *pnetfid = parms->SearchHandle;
3662 cifs_buf_release(pSMB);
3669 int CIFSFindNext(const int xid, struct cifsTconInfo *tcon,
3670 __u16 searchHandle, struct cifs_search_info *psrch_inf)
3672 TRANSACTION2_FNEXT_REQ *pSMB = NULL;
3673 TRANSACTION2_FNEXT_RSP *pSMBr = NULL;
3674 T2_FNEXT_RSP_PARMS *parms;
3675 char *response_data;
3677 int bytes_returned, name_len;
3678 __u16 params, byte_count;
3680 cFYI(1, ("In FindNext"));
3682 if (psrch_inf->endOfSearch)
3685 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3690 params = 14; /* includes 2 bytes of null string, converted to LE below*/
3692 pSMB->TotalDataCount = 0; /* no EAs */
3693 pSMB->MaxParameterCount = cpu_to_le16(8);
3694 pSMB->MaxDataCount =
3695 cpu_to_le16((tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE) &
3697 pSMB->MaxSetupCount = 0;
3701 pSMB->Reserved2 = 0;
3702 pSMB->ParameterOffset = cpu_to_le16(
3703 offsetof(struct smb_com_transaction2_fnext_req,SearchHandle) - 4);
3704 pSMB->DataCount = 0;
3705 pSMB->DataOffset = 0;
3706 pSMB->SetupCount = 1;
3707 pSMB->Reserved3 = 0;
3708 pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_NEXT);
3709 pSMB->SearchHandle = searchHandle; /* always kept as le */
3711 cpu_to_le16(CIFSMaxBufSize / sizeof(FILE_UNIX_INFO));
3712 pSMB->InformationLevel = cpu_to_le16(psrch_inf->info_level);
3713 pSMB->ResumeKey = psrch_inf->resume_key;
3715 cpu_to_le16(CIFS_SEARCH_CLOSE_AT_END | CIFS_SEARCH_RETURN_RESUME);
3717 name_len = psrch_inf->resume_name_len;
3719 if (name_len < PATH_MAX) {
3720 memcpy(pSMB->ResumeFileName, psrch_inf->presume_name, name_len);
3721 byte_count += name_len;
3722 /* 14 byte parm len above enough for 2 byte null terminator */
3723 pSMB->ResumeFileName[name_len] = 0;
3724 pSMB->ResumeFileName[name_len+1] = 0;
3727 goto FNext2_err_exit;
3729 byte_count = params + 1 /* pad */ ;
3730 pSMB->TotalParameterCount = cpu_to_le16(params);
3731 pSMB->ParameterCount = pSMB->TotalParameterCount;
3732 pSMB->hdr.smb_buf_length += byte_count;
3733 pSMB->ByteCount = cpu_to_le16(byte_count);
3735 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3736 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3737 cifs_stats_inc(&tcon->num_fnext);
3740 psrch_inf->endOfSearch = true;
3741 cifs_buf_release(pSMB);
3742 rc = 0; /* search probably was closed at end of search*/
3744 cFYI(1, ("FindNext returned = %d", rc));
3745 } else { /* decode response */
3746 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3751 /* BB fixme add lock for file (srch_info) struct here */
3752 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
3753 psrch_inf->unicode = true;
3755 psrch_inf->unicode = false;
3756 response_data = (char *) &pSMBr->hdr.Protocol +
3757 le16_to_cpu(pSMBr->t2.ParameterOffset);
3758 parms = (T2_FNEXT_RSP_PARMS *)response_data;
3759 response_data = (char *)&pSMBr->hdr.Protocol +
3760 le16_to_cpu(pSMBr->t2.DataOffset);
3761 if (psrch_inf->smallBuf)
3762 cifs_small_buf_release(
3763 psrch_inf->ntwrk_buf_start);
3765 cifs_buf_release(psrch_inf->ntwrk_buf_start);
3766 psrch_inf->srch_entries_start = response_data;
3767 psrch_inf->ntwrk_buf_start = (char *)pSMB;
3768 psrch_inf->smallBuf = 0;
3769 if (parms->EndofSearch)
3770 psrch_inf->endOfSearch = true;
3772 psrch_inf->endOfSearch = false;
3773 psrch_inf->entries_in_buffer =
3774 le16_to_cpu(parms->SearchCount);
3775 psrch_inf->index_of_last_entry +=
3776 psrch_inf->entries_in_buffer;
3777 lnoff = le16_to_cpu(parms->LastNameOffset);
3778 if (tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE <
3780 cERROR(1, ("ignoring corrupt resume name"));
3781 psrch_inf->last_entry = NULL;
3784 psrch_inf->last_entry =
3785 psrch_inf->srch_entries_start + lnoff;
3787 /* cFYI(1,("fnxt2 entries in buf %d index_of_last %d",
3788 psrch_inf->entries_in_buffer, psrch_inf->index_of_last_entry)); */
3790 /* BB fixme add unlock here */
3795 /* BB On error, should we leave previous search buf (and count and
3796 last entry fields) intact or free the previous one? */
3798 /* Note: On -EAGAIN error only caller can retry on handle based calls
3799 since file handle passed in no longer valid */
3802 cifs_buf_release(pSMB);
3807 CIFSFindClose(const int xid, struct cifsTconInfo *tcon,
3808 const __u16 searchHandle)
3811 FINDCLOSE_REQ *pSMB = NULL;
3813 cFYI(1, ("In CIFSSMBFindClose"));
3814 rc = small_smb_init(SMB_COM_FIND_CLOSE2, 1, tcon, (void **)&pSMB);
3816 /* no sense returning error if session restarted
3817 as file handle has been closed */
3823 pSMB->FileID = searchHandle;
3824 pSMB->ByteCount = 0;
3825 rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0);
3827 cERROR(1, ("Send error in FindClose = %d", rc));
3829 cifs_stats_inc(&tcon->num_fclose);
3831 /* Since session is dead, search handle closed on server already */
3839 CIFSGetSrvInodeNumber(const int xid, struct cifsTconInfo *tcon,
3840 const unsigned char *searchName,
3841 __u64 *inode_number,
3842 const struct nls_table *nls_codepage, int remap)
3845 TRANSACTION2_QPI_REQ *pSMB = NULL;
3846 TRANSACTION2_QPI_RSP *pSMBr = NULL;
3847 int name_len, bytes_returned;
3848 __u16 params, byte_count;
3850 cFYI(1, ("In GetSrvInodeNum for %s", searchName));
3854 GetInodeNumberRetry:
3855 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3860 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3862 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
3863 PATH_MAX, nls_codepage, remap);
3864 name_len++; /* trailing null */
3866 } else { /* BB improve the check for buffer overruns BB */
3867 name_len = strnlen(searchName, PATH_MAX);
3868 name_len++; /* trailing null */
3869 strncpy(pSMB->FileName, searchName, name_len);
3872 params = 2 /* level */ + 4 /* rsrvd */ + name_len /* incl null */ ;
3873 pSMB->TotalDataCount = 0;
3874 pSMB->MaxParameterCount = cpu_to_le16(2);
3875 /* BB find exact max data count below from sess structure BB */
3876 pSMB->MaxDataCount = cpu_to_le16(4000);
3877 pSMB->MaxSetupCount = 0;
3881 pSMB->Reserved2 = 0;
3882 pSMB->ParameterOffset = cpu_to_le16(offsetof(
3883 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
3884 pSMB->DataCount = 0;
3885 pSMB->DataOffset = 0;
3886 pSMB->SetupCount = 1;
3887 pSMB->Reserved3 = 0;
3888 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
3889 byte_count = params + 1 /* pad */ ;
3890 pSMB->TotalParameterCount = cpu_to_le16(params);
3891 pSMB->ParameterCount = pSMB->TotalParameterCount;
3892 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_INTERNAL_INFO);
3893 pSMB->Reserved4 = 0;
3894 pSMB->hdr.smb_buf_length += byte_count;
3895 pSMB->ByteCount = cpu_to_le16(byte_count);
3897 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3898 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3900 cFYI(1, ("error %d in QueryInternalInfo", rc));
3902 /* decode response */
3903 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3904 if (rc || (pSMBr->ByteCount < 2))
3905 /* BB also check enough total bytes returned */
3906 /* If rc should we check for EOPNOSUPP and
3907 disable the srvino flag? or in caller? */
3908 rc = -EIO; /* bad smb */
3910 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3911 __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
3912 struct file_internal_info *pfinfo;
3913 /* BB Do we need a cast or hash here ? */
3915 cFYI(1, ("Illegal size ret in QryIntrnlInf"));
3917 goto GetInodeNumOut;
3919 pfinfo = (struct file_internal_info *)
3920 (data_offset + (char *) &pSMBr->hdr.Protocol);
3921 *inode_number = pfinfo->UniqueId;
3925 cifs_buf_release(pSMB);
3927 goto GetInodeNumberRetry;
3931 /* computes length of UCS string converted to host codepage
3933 * @maxlen: length of the input string in UCS characters
3936 * return: size of input string in host codepage
3938 static int hostlen_fromUCS(const __le16 *src, const int maxlen,
3939 const struct nls_table *nls_codepage) {
3944 for (i = 0; (i < maxlen) && src[i]; ++i) {
3945 charlen = nls_codepage->uni2char(le16_to_cpu(src[i]),
3946 to, NLS_MAX_CHARSET_SIZE);
3947 hostlen += charlen > 0 ? charlen : 1;
3952 /* parses DFS refferal V3 structure
3953 * caller is responsible for freeing target_nodes
3956 * on failure - errno
3959 parse_DFS_referrals(TRANSACTION2_GET_DFS_REFER_RSP *pSMBr,
3960 unsigned int *num_of_nodes,
3961 struct dfs_info3_param **target_nodes,
3962 const struct nls_table *nls_codepage, int remap,
3963 const char *searchName)
3968 struct dfs_referral_level_3 *ref;
3970 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
3974 *num_of_nodes = le16_to_cpu(pSMBr->NumberOfReferrals);
3976 if (*num_of_nodes < 1) {
3977 cERROR(1, ("num_referrals: must be at least > 0,"
3978 "but we get num_referrals = %d\n", *num_of_nodes));
3980 goto parse_DFS_referrals_exit;
3983 ref = (struct dfs_referral_level_3 *) &(pSMBr->referrals);
3984 if (ref->VersionNumber != cpu_to_le16(3)) {
3985 cERROR(1, ("Referrals of V%d version are not supported,"
3986 "should be V3", le16_to_cpu(ref->VersionNumber)));
3988 goto parse_DFS_referrals_exit;
3991 /* get the upper boundary of the resp buffer */
3992 data_end = (char *)(&(pSMBr->PathConsumed)) +
3993 le16_to_cpu(pSMBr->t2.DataCount);
3995 cFYI(1, ("num_referrals: %d dfs flags: 0x%x ... \n",
3997 le16_to_cpu(pSMBr->DFSFlags)));
3999 *target_nodes = kzalloc(sizeof(struct dfs_info3_param) *
4000 *num_of_nodes, GFP_KERNEL);
4001 if (*target_nodes == NULL) {
4002 cERROR(1, ("Failed to allocate buffer for target_nodes\n"));
4004 goto parse_DFS_referrals_exit;
4007 /* collect neccessary data from referrals */
4008 for (i = 0; i < *num_of_nodes; i++) {
4011 struct dfs_info3_param *node = (*target_nodes)+i;
4013 node->flags = le16_to_cpu(pSMBr->DFSFlags);
4015 __le16 *tmp = kmalloc(strlen(searchName)*2 + 2,
4017 cifsConvertToUCS((__le16 *) tmp, searchName,
4018 PATH_MAX, nls_codepage, remap);
4019 node->path_consumed = hostlen_fromUCS(tmp,
4020 le16_to_cpu(pSMBr->PathConsumed)/2,
4024 node->path_consumed = le16_to_cpu(pSMBr->PathConsumed);
4026 node->server_type = le16_to_cpu(ref->ServerType);
4027 node->ref_flag = le16_to_cpu(ref->ReferralEntryFlags);
4030 temp = (char *)ref + le16_to_cpu(ref->DfsPathOffset);
4031 max_len = data_end - temp;
4032 rc = cifs_strncpy_to_host(&(node->path_name), temp,
4033 max_len, is_unicode, nls_codepage);
4035 goto parse_DFS_referrals_exit;
4037 /* copy link target UNC */
4038 temp = (char *)ref + le16_to_cpu(ref->NetworkAddressOffset);
4039 max_len = data_end - temp;
4040 rc = cifs_strncpy_to_host(&(node->node_name), temp,
4041 max_len, is_unicode, nls_codepage);
4043 goto parse_DFS_referrals_exit;
4045 ref += le16_to_cpu(ref->Size);
4048 parse_DFS_referrals_exit:
4050 free_dfs_info_array(*target_nodes, *num_of_nodes);
4051 *target_nodes = NULL;
4058 CIFSGetDFSRefer(const int xid, struct cifsSesInfo *ses,
4059 const unsigned char *searchName,
4060 struct dfs_info3_param **target_nodes,
4061 unsigned int *num_of_nodes,
4062 const struct nls_table *nls_codepage, int remap)
4064 /* TRANS2_GET_DFS_REFERRAL */
4065 TRANSACTION2_GET_DFS_REFER_REQ *pSMB = NULL;
4066 TRANSACTION2_GET_DFS_REFER_RSP *pSMBr = NULL;
4070 __u16 params, byte_count;
4072 *target_nodes = NULL;
4074 cFYI(1, ("In GetDFSRefer the path %s", searchName));
4078 rc = smb_init(SMB_COM_TRANSACTION2, 15, NULL, (void **) &pSMB,
4083 /* server pointer checked in called function,
4084 but should never be null here anyway */
4085 pSMB->hdr.Mid = GetNextMid(ses->server);
4086 pSMB->hdr.Tid = ses->ipc_tid;
4087 pSMB->hdr.Uid = ses->Suid;
4088 if (ses->capabilities & CAP_STATUS32)
4089 pSMB->hdr.Flags2 |= SMBFLG2_ERR_STATUS;
4090 if (ses->capabilities & CAP_DFS)
4091 pSMB->hdr.Flags2 |= SMBFLG2_DFS;
4093 if (ses->capabilities & CAP_UNICODE) {
4094 pSMB->hdr.Flags2 |= SMBFLG2_UNICODE;
4096 cifsConvertToUCS((__le16 *) pSMB->RequestFileName,
4097 searchName, PATH_MAX, nls_codepage, remap);
4098 name_len++; /* trailing null */
4100 } else { /* BB improve the check for buffer overruns BB */
4101 name_len = strnlen(searchName, PATH_MAX);
4102 name_len++; /* trailing null */
4103 strncpy(pSMB->RequestFileName, searchName, name_len);
4107 if (ses->server->secMode &
4108 (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
4109 pSMB->hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
4112 pSMB->hdr.Uid = ses->Suid;
4114 params = 2 /* level */ + name_len /*includes null */ ;
4115 pSMB->TotalDataCount = 0;
4116 pSMB->DataCount = 0;
4117 pSMB->DataOffset = 0;
4118 pSMB->MaxParameterCount = 0;
4119 /* BB find exact max SMB PDU from sess structure BB */
4120 pSMB->MaxDataCount = cpu_to_le16(4000);
4121 pSMB->MaxSetupCount = 0;
4125 pSMB->Reserved2 = 0;
4126 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4127 struct smb_com_transaction2_get_dfs_refer_req, MaxReferralLevel) - 4);
4128 pSMB->SetupCount = 1;
4129 pSMB->Reserved3 = 0;
4130 pSMB->SubCommand = cpu_to_le16(TRANS2_GET_DFS_REFERRAL);
4131 byte_count = params + 3 /* pad */ ;
4132 pSMB->ParameterCount = cpu_to_le16(params);
4133 pSMB->TotalParameterCount = pSMB->ParameterCount;
4134 pSMB->MaxReferralLevel = cpu_to_le16(3);
4135 pSMB->hdr.smb_buf_length += byte_count;
4136 pSMB->ByteCount = cpu_to_le16(byte_count);
4138 rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB,
4139 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4141 cFYI(1, ("Send error in GetDFSRefer = %d", rc));
4144 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4146 /* BB Also check if enough total bytes returned? */
4147 if (rc || (pSMBr->ByteCount < 17)) {
4148 rc = -EIO; /* bad smb */
4152 cFYI(1, ("Decoding GetDFSRefer response BCC: %d Offset %d",
4154 le16_to_cpu(pSMBr->t2.DataOffset)));
4156 /* parse returned result into more usable form */
4157 rc = parse_DFS_referrals(pSMBr, num_of_nodes,
4158 target_nodes, nls_codepage, remap,
4162 cifs_buf_release(pSMB);
4170 /* Query File System Info such as free space to old servers such as Win 9x */
4172 SMBOldQFSInfo(const int xid, struct cifsTconInfo *tcon, struct kstatfs *FSData)
4174 /* level 0x01 SMB_QUERY_FILE_SYSTEM_INFO */
4175 TRANSACTION2_QFSI_REQ *pSMB = NULL;
4176 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4177 FILE_SYSTEM_ALLOC_INFO *response_data;
4179 int bytes_returned = 0;
4180 __u16 params, byte_count;
4182 cFYI(1, ("OldQFSInfo"));
4184 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4189 params = 2; /* level */
4190 pSMB->TotalDataCount = 0;
4191 pSMB->MaxParameterCount = cpu_to_le16(2);
4192 pSMB->MaxDataCount = cpu_to_le16(1000);
4193 pSMB->MaxSetupCount = 0;
4197 pSMB->Reserved2 = 0;
4198 byte_count = params + 1 /* pad */ ;
4199 pSMB->TotalParameterCount = cpu_to_le16(params);
4200 pSMB->ParameterCount = pSMB->TotalParameterCount;
4201 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4202 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4203 pSMB->DataCount = 0;
4204 pSMB->DataOffset = 0;
4205 pSMB->SetupCount = 1;
4206 pSMB->Reserved3 = 0;
4207 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4208 pSMB->InformationLevel = cpu_to_le16(SMB_INFO_ALLOCATION);
4209 pSMB->hdr.smb_buf_length += byte_count;
4210 pSMB->ByteCount = cpu_to_le16(byte_count);
4212 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4213 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4215 cFYI(1, ("Send error in QFSInfo = %d", rc));
4216 } else { /* decode response */
4217 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4219 if (rc || (pSMBr->ByteCount < 18))
4220 rc = -EIO; /* bad smb */
4222 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4223 cFYI(1, ("qfsinf resp BCC: %d Offset %d",
4224 pSMBr->ByteCount, data_offset));
4226 response_data = (FILE_SYSTEM_ALLOC_INFO *)
4227 (((char *) &pSMBr->hdr.Protocol) + data_offset);
4229 le16_to_cpu(response_data->BytesPerSector) *
4230 le32_to_cpu(response_data->
4231 SectorsPerAllocationUnit);
4233 le32_to_cpu(response_data->TotalAllocationUnits);
4234 FSData->f_bfree = FSData->f_bavail =
4235 le32_to_cpu(response_data->FreeAllocationUnits);
4237 ("Blocks: %lld Free: %lld Block size %ld",
4238 (unsigned long long)FSData->f_blocks,
4239 (unsigned long long)FSData->f_bfree,
4243 cifs_buf_release(pSMB);
4246 goto oldQFSInfoRetry;
4252 CIFSSMBQFSInfo(const int xid, struct cifsTconInfo *tcon, struct kstatfs *FSData)
4254 /* level 0x103 SMB_QUERY_FILE_SYSTEM_INFO */
4255 TRANSACTION2_QFSI_REQ *pSMB = NULL;
4256 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4257 FILE_SYSTEM_INFO *response_data;
4259 int bytes_returned = 0;
4260 __u16 params, byte_count;
4262 cFYI(1, ("In QFSInfo"));
4264 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4269 params = 2; /* level */
4270 pSMB->TotalDataCount = 0;
4271 pSMB->MaxParameterCount = cpu_to_le16(2);
4272 pSMB->MaxDataCount = cpu_to_le16(1000);
4273 pSMB->MaxSetupCount = 0;
4277 pSMB->Reserved2 = 0;
4278 byte_count = params + 1 /* pad */ ;
4279 pSMB->TotalParameterCount = cpu_to_le16(params);
4280 pSMB->ParameterCount = pSMB->TotalParameterCount;
4281 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4282 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4283 pSMB->DataCount = 0;
4284 pSMB->DataOffset = 0;
4285 pSMB->SetupCount = 1;
4286 pSMB->Reserved3 = 0;
4287 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4288 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_SIZE_INFO);
4289 pSMB->hdr.smb_buf_length += byte_count;
4290 pSMB->ByteCount = cpu_to_le16(byte_count);
4292 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4293 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4295 cFYI(1, ("Send error in QFSInfo = %d", rc));
4296 } else { /* decode response */
4297 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4299 if (rc || (pSMBr->ByteCount < 24))
4300 rc = -EIO; /* bad smb */
4302 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4306 *) (((char *) &pSMBr->hdr.Protocol) +
4309 le32_to_cpu(response_data->BytesPerSector) *
4310 le32_to_cpu(response_data->
4311 SectorsPerAllocationUnit);
4313 le64_to_cpu(response_data->TotalAllocationUnits);
4314 FSData->f_bfree = FSData->f_bavail =
4315 le64_to_cpu(response_data->FreeAllocationUnits);
4317 ("Blocks: %lld Free: %lld Block size %ld",
4318 (unsigned long long)FSData->f_blocks,
4319 (unsigned long long)FSData->f_bfree,
4323 cifs_buf_release(pSMB);
4332 CIFSSMBQFSAttributeInfo(const int xid, struct cifsTconInfo *tcon)
4334 /* level 0x105 SMB_QUERY_FILE_SYSTEM_INFO */
4335 TRANSACTION2_QFSI_REQ *pSMB = NULL;
4336 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4337 FILE_SYSTEM_ATTRIBUTE_INFO *response_data;
4339 int bytes_returned = 0;
4340 __u16 params, byte_count;
4342 cFYI(1, ("In QFSAttributeInfo"));
4344 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4349 params = 2; /* level */
4350 pSMB->TotalDataCount = 0;
4351 pSMB->MaxParameterCount = cpu_to_le16(2);
4352 /* BB find exact max SMB PDU from sess structure BB */
4353 pSMB->MaxDataCount = cpu_to_le16(1000);
4354 pSMB->MaxSetupCount = 0;
4358 pSMB->Reserved2 = 0;
4359 byte_count = params + 1 /* pad */ ;
4360 pSMB->TotalParameterCount = cpu_to_le16(params);
4361 pSMB->ParameterCount = pSMB->TotalParameterCount;
4362 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4363 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4364 pSMB->DataCount = 0;
4365 pSMB->DataOffset = 0;
4366 pSMB->SetupCount = 1;
4367 pSMB->Reserved3 = 0;
4368 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4369 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_ATTRIBUTE_INFO);
4370 pSMB->hdr.smb_buf_length += byte_count;
4371 pSMB->ByteCount = cpu_to_le16(byte_count);
4373 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4374 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4376 cERROR(1, ("Send error in QFSAttributeInfo = %d", rc));
4377 } else { /* decode response */
4378 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4380 if (rc || (pSMBr->ByteCount < 13)) {
4381 /* BB also check if enough bytes returned */
4382 rc = -EIO; /* bad smb */
4384 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4386 (FILE_SYSTEM_ATTRIBUTE_INFO
4387 *) (((char *) &pSMBr->hdr.Protocol) +
4389 memcpy(&tcon->fsAttrInfo, response_data,
4390 sizeof(FILE_SYSTEM_ATTRIBUTE_INFO));
4393 cifs_buf_release(pSMB);
4396 goto QFSAttributeRetry;
4402 CIFSSMBQFSDeviceInfo(const int xid, struct cifsTconInfo *tcon)
4404 /* level 0x104 SMB_QUERY_FILE_SYSTEM_INFO */
4405 TRANSACTION2_QFSI_REQ *pSMB = NULL;
4406 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4407 FILE_SYSTEM_DEVICE_INFO *response_data;
4409 int bytes_returned = 0;
4410 __u16 params, byte_count;
4412 cFYI(1, ("In QFSDeviceInfo"));
4414 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4419 params = 2; /* level */
4420 pSMB->TotalDataCount = 0;
4421 pSMB->MaxParameterCount = cpu_to_le16(2);
4422 /* BB find exact max SMB PDU from sess structure BB */
4423 pSMB->MaxDataCount = cpu_to_le16(1000);
4424 pSMB->MaxSetupCount = 0;
4428 pSMB->Reserved2 = 0;
4429 byte_count = params + 1 /* pad */ ;
4430 pSMB->TotalParameterCount = cpu_to_le16(params);
4431 pSMB->ParameterCount = pSMB->TotalParameterCount;
4432 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4433 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4435 pSMB->DataCount = 0;
4436 pSMB->DataOffset = 0;
4437 pSMB->SetupCount = 1;
4438 pSMB->Reserved3 = 0;
4439 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4440 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_DEVICE_INFO);
4441 pSMB->hdr.smb_buf_length += byte_count;
4442 pSMB->ByteCount = cpu_to_le16(byte_count);
4444 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4445 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4447 cFYI(1, ("Send error in QFSDeviceInfo = %d", rc));
4448 } else { /* decode response */
4449 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4451 if (rc || (pSMBr->ByteCount < sizeof(FILE_SYSTEM_DEVICE_INFO)))
4452 rc = -EIO; /* bad smb */
4454 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4456 (FILE_SYSTEM_DEVICE_INFO *)
4457 (((char *) &pSMBr->hdr.Protocol) +
4459 memcpy(&tcon->fsDevInfo, response_data,
4460 sizeof(FILE_SYSTEM_DEVICE_INFO));
4463 cifs_buf_release(pSMB);
4466 goto QFSDeviceRetry;
4472 CIFSSMBQFSUnixInfo(const int xid, struct cifsTconInfo *tcon)
4474 /* level 0x200 SMB_QUERY_CIFS_UNIX_INFO */
4475 TRANSACTION2_QFSI_REQ *pSMB = NULL;
4476 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4477 FILE_SYSTEM_UNIX_INFO *response_data;
4479 int bytes_returned = 0;
4480 __u16 params, byte_count;
4482 cFYI(1, ("In QFSUnixInfo"));
4484 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4489 params = 2; /* level */
4490 pSMB->TotalDataCount = 0;
4491 pSMB->DataCount = 0;
4492 pSMB->DataOffset = 0;
4493 pSMB->MaxParameterCount = cpu_to_le16(2);
4494 /* BB find exact max SMB PDU from sess structure BB */
4495 pSMB->MaxDataCount = cpu_to_le16(100);
4496 pSMB->MaxSetupCount = 0;
4500 pSMB->Reserved2 = 0;
4501 byte_count = params + 1 /* pad */ ;
4502 pSMB->ParameterCount = cpu_to_le16(params);
4503 pSMB->TotalParameterCount = pSMB->ParameterCount;
4504 pSMB->ParameterOffset = cpu_to_le16(offsetof(struct
4505 smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4506 pSMB->SetupCount = 1;
4507 pSMB->Reserved3 = 0;
4508 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4509 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_CIFS_UNIX_INFO);
4510 pSMB->hdr.smb_buf_length += byte_count;
4511 pSMB->ByteCount = cpu_to_le16(byte_count);
4513 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4514 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4516 cERROR(1, ("Send error in QFSUnixInfo = %d", rc));
4517 } else { /* decode response */
4518 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4520 if (rc || (pSMBr->ByteCount < 13)) {
4521 rc = -EIO; /* bad smb */
4523 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4525 (FILE_SYSTEM_UNIX_INFO
4526 *) (((char *) &pSMBr->hdr.Protocol) +
4528 memcpy(&tcon->fsUnixInfo, response_data,
4529 sizeof(FILE_SYSTEM_UNIX_INFO));
4532 cifs_buf_release(pSMB);
4542 CIFSSMBSetFSUnixInfo(const int xid, struct cifsTconInfo *tcon, __u64 cap)
4544 /* level 0x200 SMB_SET_CIFS_UNIX_INFO */
4545 TRANSACTION2_SETFSI_REQ *pSMB = NULL;
4546 TRANSACTION2_SETFSI_RSP *pSMBr = NULL;
4548 int bytes_returned = 0;
4549 __u16 params, param_offset, offset, byte_count;
4551 cFYI(1, ("In SETFSUnixInfo"));
4553 /* BB switch to small buf init to save memory */
4554 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4559 params = 4; /* 2 bytes zero followed by info level. */
4560 pSMB->MaxSetupCount = 0;
4564 pSMB->Reserved2 = 0;
4565 param_offset = offsetof(struct smb_com_transaction2_setfsi_req, FileNum)
4567 offset = param_offset + params;
4569 pSMB->MaxParameterCount = cpu_to_le16(4);
4570 /* BB find exact max SMB PDU from sess structure BB */
4571 pSMB->MaxDataCount = cpu_to_le16(100);
4572 pSMB->SetupCount = 1;
4573 pSMB->Reserved3 = 0;
4574 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FS_INFORMATION);
4575 byte_count = 1 /* pad */ + params + 12;
4577 pSMB->DataCount = cpu_to_le16(12);
4578 pSMB->ParameterCount = cpu_to_le16(params);
4579 pSMB->TotalDataCount = pSMB->DataCount;
4580 pSMB->TotalParameterCount = pSMB->ParameterCount;
4581 pSMB->ParameterOffset = cpu_to_le16(param_offset);
4582 pSMB->DataOffset = cpu_to_le16(offset);
4586 pSMB->InformationLevel = cpu_to_le16(SMB_SET_CIFS_UNIX_INFO);
4589 pSMB->ClientUnixMajor = cpu_to_le16(CIFS_UNIX_MAJOR_VERSION);
4590 pSMB->ClientUnixMinor = cpu_to_le16(CIFS_UNIX_MINOR_VERSION);
4591 pSMB->ClientUnixCap = cpu_to_le64(cap);
4593 pSMB->hdr.smb_buf_length += byte_count;
4594 pSMB->ByteCount = cpu_to_le16(byte_count);
4596 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4597 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4599 cERROR(1, ("Send error in SETFSUnixInfo = %d", rc));
4600 } else { /* decode response */
4601 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4603 rc = -EIO; /* bad smb */
4605 cifs_buf_release(pSMB);
4608 goto SETFSUnixRetry;
4616 CIFSSMBQFSPosixInfo(const int xid, struct cifsTconInfo *tcon,
4617 struct kstatfs *FSData)
4619 /* level 0x201 SMB_QUERY_CIFS_POSIX_INFO */
4620 TRANSACTION2_QFSI_REQ *pSMB = NULL;
4621 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4622 FILE_SYSTEM_POSIX_INFO *response_data;
4624 int bytes_returned = 0;
4625 __u16 params, byte_count;
4627 cFYI(1, ("In QFSPosixInfo"));
4629 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4634 params = 2; /* level */
4635 pSMB->TotalDataCount = 0;
4636 pSMB->DataCount = 0;
4637 pSMB->DataOffset = 0;
4638 pSMB->MaxParameterCount = cpu_to_le16(2);
4639 /* BB find exact max SMB PDU from sess structure BB */
4640 pSMB->MaxDataCount = cpu_to_le16(100);
4641 pSMB->MaxSetupCount = 0;
4645 pSMB->Reserved2 = 0;
4646 byte_count = params + 1 /* pad */ ;
4647 pSMB->ParameterCount = cpu_to_le16(params);
4648 pSMB->TotalParameterCount = pSMB->ParameterCount;
4649 pSMB->ParameterOffset = cpu_to_le16(offsetof(struct
4650 smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4651 pSMB->SetupCount = 1;
4652 pSMB->Reserved3 = 0;
4653 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4654 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_POSIX_FS_INFO);
4655 pSMB->hdr.smb_buf_length += byte_count;
4656 pSMB->ByteCount = cpu_to_le16(byte_count);
4658 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4659 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4661 cFYI(1, ("Send error in QFSUnixInfo = %d", rc));
4662 } else { /* decode response */
4663 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4665 if (rc || (pSMBr->ByteCount < 13)) {
4666 rc = -EIO; /* bad smb */
4668 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4670 (FILE_SYSTEM_POSIX_INFO
4671 *) (((char *) &pSMBr->hdr.Protocol) +
4674 le32_to_cpu(response_data->BlockSize);
4676 le64_to_cpu(response_data->TotalBlocks);
4678 le64_to_cpu(response_data->BlocksAvail);
4679 if (response_data->UserBlocksAvail == cpu_to_le64(-1)) {
4680 FSData->f_bavail = FSData->f_bfree;
4683 le64_to_cpu(response_data->UserBlocksAvail);
4685 if (response_data->TotalFileNodes != cpu_to_le64(-1))
4687 le64_to_cpu(response_data->TotalFileNodes);
4688 if (response_data->FreeFileNodes != cpu_to_le64(-1))
4690 le64_to_cpu(response_data->FreeFileNodes);
4693 cifs_buf_release(pSMB);
4702 /* We can not use write of zero bytes trick to
4703 set file size due to need for large file support. Also note that
4704 this SetPathInfo is preferred to SetFileInfo based method in next
4705 routine which is only needed to work around a sharing violation bug
4706 in Samba which this routine can run into */
4709 CIFSSMBSetEOF(const int xid, struct cifsTconInfo *tcon, const char *fileName,
4710 __u64 size, bool SetAllocation,
4711 const struct nls_table *nls_codepage, int remap)
4713 struct smb_com_transaction2_spi_req *pSMB = NULL;
4714 struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
4715 struct file_end_of_file_info *parm_data;
4718 int bytes_returned = 0;
4719 __u16 params, byte_count, data_count, param_offset, offset;
4721 cFYI(1, ("In SetEOF"));
4723 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4728 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4730 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
4731 PATH_MAX, nls_codepage, remap);
4732 name_len++; /* trailing null */
4734 } else { /* BB improve the check for buffer overruns BB */
4735 name_len = strnlen(fileName, PATH_MAX);
4736 name_len++; /* trailing null */
4737 strncpy(pSMB->FileName, fileName, name_len);
4739 params = 6 + name_len;
4740 data_count = sizeof(struct file_end_of_file_info);
4741 pSMB->MaxParameterCount = cpu_to_le16(2);
4742 pSMB->MaxDataCount = cpu_to_le16(4100);
4743 pSMB->MaxSetupCount = 0;
4747 pSMB->Reserved2 = 0;
4748 param_offset = offsetof(struct smb_com_transaction2_spi_req,
4749 InformationLevel) - 4;
4750 offset = param_offset + params;
4751 if (SetAllocation) {
4752 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
4753 pSMB->InformationLevel =
4754 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2);
4756 pSMB->InformationLevel =
4757 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO);
4758 } else /* Set File Size */ {
4759 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
4760 pSMB->InformationLevel =
4761 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO2);
4763 pSMB->InformationLevel =
4764 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO);
4768 (struct file_end_of_file_info *) (((char *) &pSMB->hdr.Protocol) +
4770 pSMB->ParameterOffset = cpu_to_le16(param_offset);
4771 pSMB->DataOffset = cpu_to_le16(offset);
4772 pSMB->SetupCount = 1;
4773 pSMB->Reserved3 = 0;
4774 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
4775 byte_count = 3 /* pad */ + params + data_count;
4776 pSMB->DataCount = cpu_to_le16(data_count);
4777 pSMB->TotalDataCount = pSMB->DataCount;
4778 pSMB->ParameterCount = cpu_to_le16(params);
4779 pSMB->TotalParameterCount = pSMB->ParameterCount;
4780 pSMB->Reserved4 = 0;
4781 pSMB->hdr.smb_buf_length += byte_count;
4782 parm_data->FileSize = cpu_to_le64(size);
4783 pSMB->ByteCount = cpu_to_le16(byte_count);
4784 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4785 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4787 cFYI(1, ("SetPathInfo (file size) returned %d", rc));
4789 cifs_buf_release(pSMB);
4798 CIFSSMBSetFileSize(const int xid, struct cifsTconInfo *tcon, __u64 size,
4799 __u16 fid, __u32 pid_of_opener, bool SetAllocation)
4801 struct smb_com_transaction2_sfi_req *pSMB = NULL;
4803 struct file_end_of_file_info *parm_data;
4805 __u16 params, param_offset, offset, byte_count, count;
4807 cFYI(1, ("SetFileSize (via SetFileInfo) %lld",
4809 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
4814 pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
4815 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));
4818 pSMB->MaxSetupCount = 0;
4822 pSMB->Reserved2 = 0;
4823 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
4824 offset = param_offset + params;
4826 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
4828 count = sizeof(struct file_end_of_file_info);
4829 pSMB->MaxParameterCount = cpu_to_le16(2);
4830 /* BB find exact max SMB PDU from sess structure BB */
4831 pSMB->MaxDataCount = cpu_to_le16(1000);
4832 pSMB->SetupCount = 1;
4833 pSMB->Reserved3 = 0;
4834 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
4835 byte_count = 3 /* pad */ + params + count;
4836 pSMB->DataCount = cpu_to_le16(count);
4837 pSMB->ParameterCount = cpu_to_le16(params);
4838 pSMB->TotalDataCount = pSMB->DataCount;
4839 pSMB->TotalParameterCount = pSMB->ParameterCount;
4840 pSMB->ParameterOffset = cpu_to_le16(param_offset);
4842 (struct file_end_of_file_info *) (((char *) &pSMB->hdr.Protocol)
4844 pSMB->DataOffset = cpu_to_le16(offset);
4845 parm_data->FileSize = cpu_to_le64(size);
4847 if (SetAllocation) {
4848 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
4849 pSMB->InformationLevel =
4850 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2);
4852 pSMB->InformationLevel =
4853 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO);
4854 } else /* Set File Size */ {
4855 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
4856 pSMB->InformationLevel =
4857 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO2);
4859 pSMB->InformationLevel =
4860 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO);
4862 pSMB->Reserved4 = 0;
4863 pSMB->hdr.smb_buf_length += byte_count;
4864 pSMB->ByteCount = cpu_to_le16(byte_count);
4865 rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0);
4868 ("Send error in SetFileInfo (SetFileSize) = %d",
4872 /* Note: On -EAGAIN error only caller can retry on handle based calls
4873 since file handle passed in no longer valid */
4878 /* Some legacy servers such as NT4 require that the file times be set on
4879 an open handle, rather than by pathname - this is awkward due to
4880 potential access conflicts on the open, but it is unavoidable for these
4881 old servers since the only other choice is to go from 100 nanosecond DCE
4882 time and resort to the original setpathinfo level which takes the ancient
4883 DOS time format with 2 second granularity */
4885 CIFSSMBSetFileInfo(const int xid, struct cifsTconInfo *tcon,
4886 const FILE_BASIC_INFO *data, __u16 fid, __u32 pid_of_opener)
4888 struct smb_com_transaction2_sfi_req *pSMB = NULL;
4891 __u16 params, param_offset, offset, byte_count, count;
4893 cFYI(1, ("Set Times (via SetFileInfo)"));
4894 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
4899 pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
4900 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));
4903 pSMB->MaxSetupCount = 0;
4907 pSMB->Reserved2 = 0;
4908 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
4909 offset = param_offset + params;
4911 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
4913 count = sizeof(FILE_BASIC_INFO);
4914 pSMB->MaxParameterCount = cpu_to_le16(2);
4915 /* BB find max SMB PDU from sess */
4916 pSMB->MaxDataCount = cpu_to_le16(1000);
4917 pSMB->SetupCount = 1;
4918 pSMB->Reserved3 = 0;
4919 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
4920 byte_count = 3 /* pad */ + params + count;
4921 pSMB->DataCount = cpu_to_le16(count);
4922 pSMB->ParameterCount = cpu_to_le16(params);
4923 pSMB->TotalDataCount = pSMB->DataCount;
4924 pSMB->TotalParameterCount = pSMB->ParameterCount;
4925 pSMB->ParameterOffset = cpu_to_le16(param_offset);
4926 pSMB->DataOffset = cpu_to_le16(offset);
4928 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
4929 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO2);
4931 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO);
4932 pSMB->Reserved4 = 0;
4933 pSMB->hdr.smb_buf_length += byte_count;
4934 pSMB->ByteCount = cpu_to_le16(byte_count);
4935 memcpy(data_offset, data, sizeof(FILE_BASIC_INFO));
4936 rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0);
4938 cFYI(1, ("Send error in Set Time (SetFileInfo) = %d", rc));
4940 /* Note: On -EAGAIN error only caller can retry on handle based calls
4941 since file handle passed in no longer valid */
4947 CIFSSMBSetFileDisposition(const int xid, struct cifsTconInfo *tcon,
4948 bool delete_file, __u16 fid, __u32 pid_of_opener)
4950 struct smb_com_transaction2_sfi_req *pSMB = NULL;
4953 __u16 params, param_offset, offset, byte_count, count;
4955 cFYI(1, ("Set File Disposition (via SetFileInfo)"));
4956 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
4961 pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
4962 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));
4965 pSMB->MaxSetupCount = 0;
4969 pSMB->Reserved2 = 0;
4970 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
4971 offset = param_offset + params;
4973 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
4976 pSMB->MaxParameterCount = cpu_to_le16(2);
4977 /* BB find max SMB PDU from sess */
4978 pSMB->MaxDataCount = cpu_to_le16(1000);
4979 pSMB->SetupCount = 1;
4980 pSMB->Reserved3 = 0;
4981 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
4982 byte_count = 3 /* pad */ + params + count;
4983 pSMB->DataCount = cpu_to_le16(count);
4984 pSMB->ParameterCount = cpu_to_le16(params);
4985 pSMB->TotalDataCount = pSMB->DataCount;
4986 pSMB->TotalParameterCount = pSMB->ParameterCount;
4987 pSMB->ParameterOffset = cpu_to_le16(param_offset);
4988 pSMB->DataOffset = cpu_to_le16(offset);
4990 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_DISPOSITION_INFO);
4991 pSMB->Reserved4 = 0;
4992 pSMB->hdr.smb_buf_length += byte_count;
4993 pSMB->ByteCount = cpu_to_le16(byte_count);
4994 *data_offset = delete_file ? 1 : 0;
4995 rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0);
4997 cFYI(1, ("Send error in SetFileDisposition = %d", rc));
5003 CIFSSMBSetPathInfo(const int xid, struct cifsTconInfo *tcon,
5004 const char *fileName, const FILE_BASIC_INFO *data,
5005 const struct nls_table *nls_codepage, int remap)
5007 TRANSACTION2_SPI_REQ *pSMB = NULL;
5008 TRANSACTION2_SPI_RSP *pSMBr = NULL;
5011 int bytes_returned = 0;
5013 __u16 params, param_offset, offset, byte_count, count;
5015 cFYI(1, ("In SetTimes"));
5018 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5023 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5025 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
5026 PATH_MAX, nls_codepage, remap);
5027 name_len++; /* trailing null */
5029 } else { /* BB improve the check for buffer overruns BB */
5030 name_len = strnlen(fileName, PATH_MAX);
5031 name_len++; /* trailing null */
5032 strncpy(pSMB->FileName, fileName, name_len);
5035 params = 6 + name_len;
5036 count = sizeof(FILE_BASIC_INFO);
5037 pSMB->MaxParameterCount = cpu_to_le16(2);
5038 /* BB find max SMB PDU from sess structure BB */
5039 pSMB->MaxDataCount = cpu_to_le16(1000);
5040 pSMB->MaxSetupCount = 0;
5044 pSMB->Reserved2 = 0;
5045 param_offset = offsetof(struct smb_com_transaction2_spi_req,
5046 InformationLevel) - 4;
5047 offset = param_offset + params;
5048 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
5049 pSMB->ParameterOffset = cpu_to_le16(param_offset);
5050 pSMB->DataOffset = cpu_to_le16(offset);
5051 pSMB->SetupCount = 1;
5052 pSMB->Reserved3 = 0;
5053 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
5054 byte_count = 3 /* pad */ + params + count;
5056 pSMB->DataCount = cpu_to_le16(count);
5057 pSMB->ParameterCount = cpu_to_le16(params);
5058 pSMB->TotalDataCount = pSMB->DataCount;
5059 pSMB->TotalParameterCount = pSMB->ParameterCount;
5060 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
5061 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO2);
5063 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO);
5064 pSMB->Reserved4 = 0;
5065 pSMB->hdr.smb_buf_length += byte_count;
5066 memcpy(data_offset, data, sizeof(FILE_BASIC_INFO));
5067 pSMB->ByteCount = cpu_to_le16(byte_count);
5068 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5069 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5071 cFYI(1, ("SetPathInfo (times) returned %d", rc));
5073 cifs_buf_release(pSMB);
5081 /* Can not be used to set time stamps yet (due to old DOS time format) */
5082 /* Can be used to set attributes */
5083 #if 0 /* Possibly not needed - since it turns out that strangely NT4 has a bug
5084 handling it anyway and NT4 was what we thought it would be needed for
5085 Do not delete it until we prove whether needed for Win9x though */
5087 CIFSSMBSetAttrLegacy(int xid, struct cifsTconInfo *tcon, char *fileName,
5088 __u16 dos_attrs, const struct nls_table *nls_codepage)
5090 SETATTR_REQ *pSMB = NULL;
5091 SETATTR_RSP *pSMBr = NULL;
5096 cFYI(1, ("In SetAttrLegacy"));
5099 rc = smb_init(SMB_COM_SETATTR, 8, tcon, (void **) &pSMB,
5104 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5106 ConvertToUCS((__le16 *) pSMB->fileName, fileName,
5107 PATH_MAX, nls_codepage);
5108 name_len++; /* trailing null */
5110 } else { /* BB improve the check for buffer overruns BB */
5111 name_len = strnlen(fileName, PATH_MAX);
5112 name_len++; /* trailing null */
5113 strncpy(pSMB->fileName, fileName, name_len);
5115 pSMB->attr = cpu_to_le16(dos_attrs);
5116 pSMB->BufferFormat = 0x04;
5117 pSMB->hdr.smb_buf_length += name_len + 1;
5118 pSMB->ByteCount = cpu_to_le16(name_len + 1);
5119 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5120 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5122 cFYI(1, ("Error in LegacySetAttr = %d", rc));
5124 cifs_buf_release(pSMB);
5127 goto SetAttrLgcyRetry;
5131 #endif /* temporarily unneeded SetAttr legacy function */
5134 CIFSSMBUnixSetInfo(const int xid, struct cifsTconInfo *tcon, char *fileName,
5135 const struct cifs_unix_set_info_args *args,
5136 const struct nls_table *nls_codepage, int remap)
5138 TRANSACTION2_SPI_REQ *pSMB = NULL;
5139 TRANSACTION2_SPI_RSP *pSMBr = NULL;
5142 int bytes_returned = 0;
5143 FILE_UNIX_BASIC_INFO *data_offset;
5144 __u16 params, param_offset, offset, count, byte_count;
5145 __u64 mode = args->mode;
5147 cFYI(1, ("In SetUID/GID/Mode"));
5149 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5154 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5156 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
5157 PATH_MAX, nls_codepage, remap);
5158 name_len++; /* trailing null */
5160 } else { /* BB improve the check for buffer overruns BB */
5161 name_len = strnlen(fileName, PATH_MAX);
5162 name_len++; /* trailing null */
5163 strncpy(pSMB->FileName, fileName, name_len);
5166 params = 6 + name_len;
5167 count = sizeof(FILE_UNIX_BASIC_INFO);
5168 pSMB->MaxParameterCount = cpu_to_le16(2);
5169 /* BB find max SMB PDU from sess structure BB */
5170 pSMB->MaxDataCount = cpu_to_le16(1000);
5171 pSMB->MaxSetupCount = 0;
5175 pSMB->Reserved2 = 0;
5176 param_offset = offsetof(struct smb_com_transaction2_spi_req,
5177 InformationLevel) - 4;
5178 offset = param_offset + params;
5180 (FILE_UNIX_BASIC_INFO *) ((char *) &pSMB->hdr.Protocol +
5182 memset(data_offset, 0, count);
5183 pSMB->DataOffset = cpu_to_le16(offset);
5184 pSMB->ParameterOffset = cpu_to_le16(param_offset);
5185 pSMB->SetupCount = 1;
5186 pSMB->Reserved3 = 0;
5187 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
5188 byte_count = 3 /* pad */ + params + count;
5189 pSMB->ParameterCount = cpu_to_le16(params);
5190 pSMB->DataCount = cpu_to_le16(count);
5191 pSMB->TotalParameterCount = pSMB->ParameterCount;
5192 pSMB->TotalDataCount = pSMB->DataCount;
5193 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_BASIC);
5194 pSMB->Reserved4 = 0;
5195 pSMB->hdr.smb_buf_length += byte_count;
5196 /* Samba server ignores set of file size to zero due to bugs in some
5197 older clients, but we should be precise - we use SetFileSize to
5198 set file size and do not want to truncate file size to zero
5199 accidently as happened on one Samba server beta by putting
5200 zero instead of -1 here */
5201 data_offset->EndOfFile = cpu_to_le64(NO_CHANGE_64);
5202 data_offset->NumOfBytes = cpu_to_le64(NO_CHANGE_64);
5203 data_offset->LastStatusChange = cpu_to_le64(args->ctime);
5204 data_offset->LastAccessTime = cpu_to_le64(args->atime);
5205 data_offset->LastModificationTime = cpu_to_le64(args->mtime);
5206 data_offset->Uid = cpu_to_le64(args->uid);
5207 data_offset->Gid = cpu_to_le64(args->gid);
5208 /* better to leave device as zero when it is */
5209 data_offset->DevMajor = cpu_to_le64(MAJOR(args->device));
5210 data_offset->DevMinor = cpu_to_le64(MINOR(args->device));
5211 data_offset->Permissions = cpu_to_le64(mode);
5214 data_offset->Type = cpu_to_le32(UNIX_FILE);
5215 else if (S_ISDIR(mode))
5216 data_offset->Type = cpu_to_le32(UNIX_DIR);
5217 else if (S_ISLNK(mode))
5218 data_offset->Type = cpu_to_le32(UNIX_SYMLINK);
5219 else if (S_ISCHR(mode))
5220 data_offset->Type = cpu_to_le32(UNIX_CHARDEV);
5221 else if (S_ISBLK(mode))
5222 data_offset->Type = cpu_to_le32(UNIX_BLOCKDEV);
5223 else if (S_ISFIFO(mode))
5224 data_offset->Type = cpu_to_le32(UNIX_FIFO);
5225 else if (S_ISSOCK(mode))
5226 data_offset->Type = cpu_to_le32(UNIX_SOCKET);
5229 pSMB->ByteCount = cpu_to_le16(byte_count);
5230 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5231 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5233 cFYI(1, ("SetPathInfo (perms) returned %d", rc));
5235 cifs_buf_release(pSMB);
5241 int CIFSSMBNotify(const int xid, struct cifsTconInfo *tcon,
5242 const int notify_subdirs, const __u16 netfid,
5243 __u32 filter, struct file *pfile, int multishot,
5244 const struct nls_table *nls_codepage)
5247 struct smb_com_transaction_change_notify_req *pSMB = NULL;
5248 struct smb_com_ntransaction_change_notify_rsp *pSMBr = NULL;
5249 struct dir_notify_req *dnotify_req;
5252 cFYI(1, ("In CIFSSMBNotify for file handle %d", (int)netfid));
5253 rc = smb_init(SMB_COM_NT_TRANSACT, 23, tcon, (void **) &pSMB,
5258 pSMB->TotalParameterCount = 0 ;
5259 pSMB->TotalDataCount = 0;
5260 pSMB->MaxParameterCount = cpu_to_le32(2);
5261 /* BB find exact data count max from sess structure BB */
5262 pSMB->MaxDataCount = 0; /* same in little endian or be */
5263 /* BB VERIFY verify which is correct for above BB */
5264 pSMB->MaxDataCount = cpu_to_le32((tcon->ses->server->maxBuf -
5265 MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
5267 pSMB->MaxSetupCount = 4;
5269 pSMB->ParameterOffset = 0;
5270 pSMB->DataCount = 0;
5271 pSMB->DataOffset = 0;
5272 pSMB->SetupCount = 4; /* single byte does not need le conversion */
5273 pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_NOTIFY_CHANGE);
5274 pSMB->ParameterCount = pSMB->TotalParameterCount;
5276 pSMB->WatchTree = 1; /* one byte - no le conversion needed */
5277 pSMB->Reserved2 = 0;
5278 pSMB->CompletionFilter = cpu_to_le32(filter);
5279 pSMB->Fid = netfid; /* file handle always le */
5280 pSMB->ByteCount = 0;
5282 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5283 (struct smb_hdr *)pSMBr, &bytes_returned,
5286 cFYI(1, ("Error in Notify = %d", rc));
5288 /* Add file to outstanding requests */
5289 /* BB change to kmem cache alloc */
5290 dnotify_req = kmalloc(
5291 sizeof(struct dir_notify_req),
5294 dnotify_req->Pid = pSMB->hdr.Pid;
5295 dnotify_req->PidHigh = pSMB->hdr.PidHigh;
5296 dnotify_req->Mid = pSMB->hdr.Mid;
5297 dnotify_req->Tid = pSMB->hdr.Tid;
5298 dnotify_req->Uid = pSMB->hdr.Uid;
5299 dnotify_req->netfid = netfid;
5300 dnotify_req->pfile = pfile;
5301 dnotify_req->filter = filter;
5302 dnotify_req->multishot = multishot;
5303 spin_lock(&GlobalMid_Lock);
5304 list_add_tail(&dnotify_req->lhead,
5305 &GlobalDnotifyReqList);
5306 spin_unlock(&GlobalMid_Lock);
5310 cifs_buf_release(pSMB);
5313 #ifdef CONFIG_CIFS_XATTR
5315 CIFSSMBQAllEAs(const int xid, struct cifsTconInfo *tcon,
5316 const unsigned char *searchName,
5317 char *EAData, size_t buf_size,
5318 const struct nls_table *nls_codepage, int remap)
5320 /* BB assumes one setup word */
5321 TRANSACTION2_QPI_REQ *pSMB = NULL;
5322 TRANSACTION2_QPI_RSP *pSMBr = NULL;
5326 struct fea *temp_fea;
5328 __u16 params, byte_count;
5330 cFYI(1, ("In Query All EAs path %s", searchName));
5332 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5337 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5339 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
5340 PATH_MAX, nls_codepage, remap);
5341 name_len++; /* trailing null */
5343 } else { /* BB improve the check for buffer overruns BB */
5344 name_len = strnlen(searchName, PATH_MAX);
5345 name_len++; /* trailing null */
5346 strncpy(pSMB->FileName, searchName, name_len);
5349 params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */;
5350 pSMB->TotalDataCount = 0;
5351 pSMB->MaxParameterCount = cpu_to_le16(2);
5352 /* BB find exact max SMB PDU from sess structure BB */
5353 pSMB->MaxDataCount = cpu_to_le16(4000);
5354 pSMB->MaxSetupCount = 0;
5358 pSMB->Reserved2 = 0;
5359 pSMB->ParameterOffset = cpu_to_le16(offsetof(
5360 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
5361 pSMB->DataCount = 0;
5362 pSMB->DataOffset = 0;
5363 pSMB->SetupCount = 1;
5364 pSMB->Reserved3 = 0;
5365 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
5366 byte_count = params + 1 /* pad */ ;
5367 pSMB->TotalParameterCount = cpu_to_le16(params);
5368 pSMB->ParameterCount = pSMB->TotalParameterCount;
5369 pSMB->InformationLevel = cpu_to_le16(SMB_INFO_QUERY_ALL_EAS);
5370 pSMB->Reserved4 = 0;
5371 pSMB->hdr.smb_buf_length += byte_count;
5372 pSMB->ByteCount = cpu_to_le16(byte_count);
5374 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5375 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5377 cFYI(1, ("Send error in QueryAllEAs = %d", rc));
5378 } else { /* decode response */
5379 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
5381 /* BB also check enough total bytes returned */
5382 /* BB we need to improve the validity checking
5383 of these trans2 responses */
5384 if (rc || (pSMBr->ByteCount < 4))
5385 rc = -EIO; /* bad smb */
5386 /* else if (pFindData){
5387 memcpy((char *) pFindData,
5388 (char *) &pSMBr->hdr.Protocol +
5391 /* check that length of list is not more than bcc */
5392 /* check that each entry does not go beyond length
5394 /* check that each element of each entry does not
5395 go beyond end of list */
5396 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
5397 struct fealist *ea_response_data;
5399 /* validate_trans2_offsets() */
5400 /* BB check if start of smb + data_offset > &bcc+ bcc */
5401 ea_response_data = (struct fealist *)
5402 (((char *) &pSMBr->hdr.Protocol) +
5404 name_len = le32_to_cpu(ea_response_data->list_len);
5405 cFYI(1, ("ea length %d", name_len));
5406 if (name_len <= 8) {
5407 /* returned EA size zeroed at top of function */
5408 cFYI(1, ("empty EA list returned from server"));
5410 /* account for ea list len */
5412 temp_fea = ea_response_data->list;
5413 temp_ptr = (char *)temp_fea;
5414 while (name_len > 0) {
5418 rc += temp_fea->name_len;
5419 /* account for prefix user. and trailing null */
5421 if (rc < (int)buf_size) {
5422 memcpy(EAData, "user.", 5);
5424 memcpy(EAData, temp_ptr,
5425 temp_fea->name_len);
5426 EAData += temp_fea->name_len;
5427 /* null terminate name */
5429 EAData = EAData + 1;
5430 } else if (buf_size == 0) {
5431 /* skip copy - calc size only */
5433 /* stop before overrun buffer */
5437 name_len -= temp_fea->name_len;
5438 temp_ptr += temp_fea->name_len;
5439 /* account for trailing null */
5443 le16_to_cpu(temp_fea->value_len);
5444 name_len -= value_len;
5445 temp_ptr += value_len;
5446 /* BB check that temp_ptr is still
5449 /* no trailing null to account for
5451 /* go on to next EA */
5452 temp_fea = (struct fea *)temp_ptr;
5457 cifs_buf_release(pSMB);
5464 ssize_t CIFSSMBQueryEA(const int xid, struct cifsTconInfo *tcon,
5465 const unsigned char *searchName, const unsigned char *ea_name,
5466 unsigned char *ea_value, size_t buf_size,
5467 const struct nls_table *nls_codepage, int remap)
5469 TRANSACTION2_QPI_REQ *pSMB = NULL;
5470 TRANSACTION2_QPI_RSP *pSMBr = NULL;
5474 struct fea *temp_fea;
5476 __u16 params, byte_count;
5478 cFYI(1, ("In Query EA path %s", searchName));
5480 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5485 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5487 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
5488 PATH_MAX, nls_codepage, remap);
5489 name_len++; /* trailing null */
5491 } else { /* BB improve the check for buffer overruns BB */
5492 name_len = strnlen(searchName, PATH_MAX);
5493 name_len++; /* trailing null */
5494 strncpy(pSMB->FileName, searchName, name_len);
5497 params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */;
5498 pSMB->TotalDataCount = 0;
5499 pSMB->MaxParameterCount = cpu_to_le16(2);
5500 /* BB find exact max SMB PDU from sess structure BB */
5501 pSMB->MaxDataCount = cpu_to_le16(4000);
5502 pSMB->MaxSetupCount = 0;
5506 pSMB->Reserved2 = 0;
5507 pSMB->ParameterOffset = cpu_to_le16(offsetof(
5508 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
5509 pSMB->DataCount = 0;
5510 pSMB->DataOffset = 0;
5511 pSMB->SetupCount = 1;
5512 pSMB->Reserved3 = 0;
5513 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
5514 byte_count = params + 1 /* pad */ ;
5515 pSMB->TotalParameterCount = cpu_to_le16(params);
5516 pSMB->ParameterCount = pSMB->TotalParameterCount;
5517 pSMB->InformationLevel = cpu_to_le16(SMB_INFO_QUERY_ALL_EAS);
5518 pSMB->Reserved4 = 0;
5519 pSMB->hdr.smb_buf_length += byte_count;
5520 pSMB->ByteCount = cpu_to_le16(byte_count);
5522 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5523 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5525 cFYI(1, ("Send error in Query EA = %d", rc));
5526 } else { /* decode response */
5527 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
5529 /* BB also check enough total bytes returned */
5530 /* BB we need to improve the validity checking
5531 of these trans2 responses */
5532 if (rc || (pSMBr->ByteCount < 4))
5533 rc = -EIO; /* bad smb */
5534 /* else if (pFindData){
5535 memcpy((char *) pFindData,
5536 (char *) &pSMBr->hdr.Protocol +
5539 /* check that length of list is not more than bcc */
5540 /* check that each entry does not go beyond length
5542 /* check that each element of each entry does not
5543 go beyond end of list */
5544 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
5545 struct fealist *ea_response_data;
5547 /* validate_trans2_offsets() */
5548 /* BB check if start of smb + data_offset > &bcc+ bcc*/
5549 ea_response_data = (struct fealist *)
5550 (((char *) &pSMBr->hdr.Protocol) +
5552 name_len = le32_to_cpu(ea_response_data->list_len);
5553 cFYI(1, ("ea length %d", name_len));
5554 if (name_len <= 8) {
5555 /* returned EA size zeroed at top of function */
5556 cFYI(1, ("empty EA list returned from server"));
5558 /* account for ea list len */
5560 temp_fea = ea_response_data->list;
5561 temp_ptr = (char *)temp_fea;
5562 /* loop through checking if we have a matching
5563 name and then return the associated value */
5564 while (name_len > 0) {
5569 le16_to_cpu(temp_fea->value_len);
5570 /* BB validate that value_len falls within SMB,
5571 even though maximum for name_len is 255 */
5572 if (memcmp(temp_fea->name, ea_name,
5573 temp_fea->name_len) == 0) {
5576 /* account for prefix user. and trailing null */
5577 if (rc <= (int)buf_size) {
5579 temp_fea->name+temp_fea->name_len+1,
5581 /* ea values, unlike ea
5584 } else if (buf_size == 0) {
5585 /* skip copy - calc size only */
5587 /* stop before overrun buffer */
5592 name_len -= temp_fea->name_len;
5593 temp_ptr += temp_fea->name_len;
5594 /* account for trailing null */
5597 name_len -= value_len;
5598 temp_ptr += value_len;
5599 /* No trailing null to account for in
5600 value_len. Go on to next EA */
5601 temp_fea = (struct fea *)temp_ptr;
5606 cifs_buf_release(pSMB);
5614 CIFSSMBSetEA(const int xid, struct cifsTconInfo *tcon, const char *fileName,
5615 const char *ea_name, const void *ea_value,
5616 const __u16 ea_value_len, const struct nls_table *nls_codepage,
5619 struct smb_com_transaction2_spi_req *pSMB = NULL;
5620 struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
5621 struct fealist *parm_data;
5624 int bytes_returned = 0;
5625 __u16 params, param_offset, byte_count, offset, count;
5627 cFYI(1, ("In SetEA"));
5629 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5634 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5636 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
5637 PATH_MAX, nls_codepage, remap);
5638 name_len++; /* trailing null */
5640 } else { /* BB improve the check for buffer overruns BB */
5641 name_len = strnlen(fileName, PATH_MAX);
5642 name_len++; /* trailing null */
5643 strncpy(pSMB->FileName, fileName, name_len);
5646 params = 6 + name_len;
5648 /* done calculating parms using name_len of file name,
5649 now use name_len to calculate length of ea name
5650 we are going to create in the inode xattrs */
5651 if (ea_name == NULL)
5654 name_len = strnlen(ea_name, 255);
5656 count = sizeof(*parm_data) + ea_value_len + name_len;
5657 pSMB->MaxParameterCount = cpu_to_le16(2);
5658 /* BB find max SMB PDU from sess */
5659 pSMB->MaxDataCount = cpu_to_le16(1000);
5660 pSMB->MaxSetupCount = 0;
5664 pSMB->Reserved2 = 0;
5665 param_offset = offsetof(struct smb_com_transaction2_spi_req,
5666 InformationLevel) - 4;
5667 offset = param_offset + params;
5668 pSMB->InformationLevel =
5669 cpu_to_le16(SMB_SET_FILE_EA);
5672 (struct fealist *) (((char *) &pSMB->hdr.Protocol) +
5674 pSMB->ParameterOffset = cpu_to_le16(param_offset);
5675 pSMB->DataOffset = cpu_to_le16(offset);
5676 pSMB->SetupCount = 1;
5677 pSMB->Reserved3 = 0;
5678 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
5679 byte_count = 3 /* pad */ + params + count;
5680 pSMB->DataCount = cpu_to_le16(count);
5681 parm_data->list_len = cpu_to_le32(count);
5682 parm_data->list[0].EA_flags = 0;
5683 /* we checked above that name len is less than 255 */
5684 parm_data->list[0].name_len = (__u8)name_len;
5685 /* EA names are always ASCII */
5687 strncpy(parm_data->list[0].name, ea_name, name_len);
5688 parm_data->list[0].name[name_len] = 0;
5689 parm_data->list[0].value_len = cpu_to_le16(ea_value_len);
5690 /* caller ensures that ea_value_len is less than 64K but
5691 we need to ensure that it fits within the smb */
5693 /*BB add length check to see if it would fit in
5694 negotiated SMB buffer size BB */
5695 /* if (ea_value_len > buffer_size - 512 (enough for header)) */
5697 memcpy(parm_data->list[0].name+name_len+1,
5698 ea_value, ea_value_len);
5700 pSMB->TotalDataCount = pSMB->DataCount;
5701 pSMB->ParameterCount = cpu_to_le16(params);
5702 pSMB->TotalParameterCount = pSMB->ParameterCount;
5703 pSMB->Reserved4 = 0;
5704 pSMB->hdr.smb_buf_length += byte_count;
5705 pSMB->ByteCount = cpu_to_le16(byte_count);
5706 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5707 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5709 cFYI(1, ("SetPathInfo (EA) returned %d", rc));
5711 cifs_buf_release(pSMB);