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 GETU32(server->sessid) = le32_to_cpu(rsp->SessionKey);
532 /* even though we do not use raw we might as well set this
533 accurately, in case we ever find a need for it */
534 if ((le16_to_cpu(rsp->RawMode) & RAW_ENABLE) == RAW_ENABLE) {
535 server->maxRw = 0xFF00;
536 server->capabilities = CAP_MPX_MODE | CAP_RAW_MODE;
538 server->maxRw = 0;/* we do not need to use raw anyway */
539 server->capabilities = CAP_MPX_MODE;
541 tmp = (__s16)le16_to_cpu(rsp->ServerTimeZone);
543 /* OS/2 often does not set timezone therefore
544 * we must use server time to calc time zone.
545 * Could deviate slightly from the right zone.
546 * Smallest defined timezone difference is 15 minutes
547 * (i.e. Nepal). Rounding up/down is done to match
550 int val, seconds, remain, result;
551 struct timespec ts, utc;
553 ts = cnvrtDosUnixTm(le16_to_cpu(rsp->SrvTime.Date),
554 le16_to_cpu(rsp->SrvTime.Time));
555 cFYI(1, ("SrvTime %d sec since 1970 (utc: %d) diff: %d",
556 (int)ts.tv_sec, (int)utc.tv_sec,
557 (int)(utc.tv_sec - ts.tv_sec)));
558 val = (int)(utc.tv_sec - ts.tv_sec);
560 result = (seconds / MIN_TZ_ADJ) * MIN_TZ_ADJ;
561 remain = seconds % MIN_TZ_ADJ;
562 if (remain >= (MIN_TZ_ADJ / 2))
563 result += MIN_TZ_ADJ;
566 server->timeAdj = result;
568 server->timeAdj = (int)tmp;
569 server->timeAdj *= 60; /* also in seconds */
571 cFYI(1, ("server->timeAdj: %d seconds", server->timeAdj));
574 /* BB get server time for time conversions and add
575 code to use it and timezone since this is not UTC */
577 if (rsp->EncryptionKeyLength ==
578 cpu_to_le16(CIFS_CRYPTO_KEY_SIZE)) {
579 memcpy(server->cryptKey, rsp->EncryptionKey,
580 CIFS_CRYPTO_KEY_SIZE);
581 } else if (server->secMode & SECMODE_PW_ENCRYPT) {
582 rc = -EIO; /* need cryptkey unless plain text */
586 cFYI(1, ("LANMAN negotiated"));
587 /* we will not end up setting signing flags - as no signing
588 was in LANMAN and server did not return the flags on */
590 #else /* weak security disabled */
591 } else if (pSMBr->hdr.WordCount == 13) {
592 cERROR(1, ("mount failed, cifs module not built "
593 "with CIFS_WEAK_PW_HASH support"));
595 #endif /* WEAK_PW_HASH */
597 } else if (pSMBr->hdr.WordCount != 17) {
602 /* else wct == 17 NTLM */
603 server->secMode = pSMBr->SecurityMode;
604 if ((server->secMode & SECMODE_USER) == 0)
605 cFYI(1, ("share mode security"));
607 if ((server->secMode & SECMODE_PW_ENCRYPT) == 0)
608 #ifdef CONFIG_CIFS_WEAK_PW_HASH
609 if ((secFlags & CIFSSEC_MAY_PLNTXT) == 0)
610 #endif /* CIFS_WEAK_PW_HASH */
611 cERROR(1, ("Server requests plain text password"
612 " but client support disabled"));
614 if ((secFlags & CIFSSEC_MUST_NTLMV2) == CIFSSEC_MUST_NTLMV2)
615 server->secType = NTLMv2;
616 else if (secFlags & CIFSSEC_MAY_NTLM)
617 server->secType = NTLM;
618 else if (secFlags & CIFSSEC_MAY_NTLMV2)
619 server->secType = NTLMv2;
620 else if (secFlags & CIFSSEC_MAY_KRB5)
621 server->secType = Kerberos;
622 else if (secFlags & CIFSSEC_MAY_LANMAN)
623 server->secType = LANMAN;
624 /* #ifdef CONFIG_CIFS_EXPERIMENTAL
625 else if (secFlags & CIFSSEC_MAY_PLNTXT)
630 cERROR(1, ("Invalid security type"));
633 /* else ... any others ...? */
635 /* one byte, so no need to convert this or EncryptionKeyLen from
637 server->maxReq = le16_to_cpu(pSMBr->MaxMpxCount);
638 /* probably no need to store and check maxvcs */
639 server->maxBuf = min(le32_to_cpu(pSMBr->MaxBufferSize),
640 (__u32) CIFSMaxBufSize + MAX_CIFS_HDR_SIZE);
641 server->maxRw = le32_to_cpu(pSMBr->MaxRawSize);
642 cFYI(DBG2, ("Max buf = %d", ses->server->maxBuf));
643 GETU32(ses->server->sessid) = le32_to_cpu(pSMBr->SessionKey);
644 server->capabilities = le32_to_cpu(pSMBr->Capabilities);
645 server->timeAdj = (int)(__s16)le16_to_cpu(pSMBr->ServerTimeZone);
646 server->timeAdj *= 60;
647 if (pSMBr->EncryptionKeyLength == CIFS_CRYPTO_KEY_SIZE) {
648 memcpy(server->cryptKey, pSMBr->u.EncryptionKey,
649 CIFS_CRYPTO_KEY_SIZE);
650 } else if ((pSMBr->hdr.Flags2 & SMBFLG2_EXT_SEC)
651 && (pSMBr->EncryptionKeyLength == 0)) {
652 /* decode security blob */
653 } else if (server->secMode & SECMODE_PW_ENCRYPT) {
654 rc = -EIO; /* no crypt key only if plain text pwd */
658 /* BB might be helpful to save off the domain of server here */
660 if ((pSMBr->hdr.Flags2 & SMBFLG2_EXT_SEC) &&
661 (server->capabilities & CAP_EXTENDED_SECURITY)) {
662 count = pSMBr->ByteCount;
667 read_lock(&cifs_tcp_ses_lock);
668 if (server->srv_count > 1) {
669 read_unlock(&cifs_tcp_ses_lock);
670 if (memcmp(server->server_GUID,
671 pSMBr->u.extended_response.
673 cFYI(1, ("server UID changed"));
674 memcpy(server->server_GUID,
675 pSMBr->u.extended_response.GUID,
679 read_unlock(&cifs_tcp_ses_lock);
680 memcpy(server->server_GUID,
681 pSMBr->u.extended_response.GUID, 16);
685 server->secType = RawNTLMSSP;
687 rc = decode_negTokenInit(pSMBr->u.extended_response.
697 server->capabilities &= ~CAP_EXTENDED_SECURITY;
699 #ifdef CONFIG_CIFS_WEAK_PW_HASH
702 if ((secFlags & CIFSSEC_MAY_SIGN) == 0) {
703 /* MUST_SIGN already includes the MAY_SIGN FLAG
704 so if this is zero it means that signing is disabled */
705 cFYI(1, ("Signing disabled"));
706 if (server->secMode & SECMODE_SIGN_REQUIRED) {
707 cERROR(1, ("Server requires "
708 "packet signing to be enabled in "
709 "/proc/fs/cifs/SecurityFlags."));
713 ~(SECMODE_SIGN_ENABLED | SECMODE_SIGN_REQUIRED);
714 } else if ((secFlags & CIFSSEC_MUST_SIGN) == CIFSSEC_MUST_SIGN) {
715 /* signing required */
716 cFYI(1, ("Must sign - secFlags 0x%x", secFlags));
717 if ((server->secMode &
718 (SECMODE_SIGN_ENABLED | SECMODE_SIGN_REQUIRED)) == 0) {
720 ("signing required but server lacks support"));
723 server->secMode |= SECMODE_SIGN_REQUIRED;
725 /* signing optional ie CIFSSEC_MAY_SIGN */
726 if ((server->secMode & SECMODE_SIGN_REQUIRED) == 0)
728 ~(SECMODE_SIGN_ENABLED | SECMODE_SIGN_REQUIRED);
732 cifs_buf_release(pSMB);
734 cFYI(1, ("negprot rc %d", rc));
739 CIFSSMBTDis(const int xid, struct cifsTconInfo *tcon)
741 struct smb_hdr *smb_buffer;
744 cFYI(1, ("In tree disconnect"));
746 /* BB: do we need to check this? These should never be NULL. */
747 if ((tcon->ses == NULL) || (tcon->ses->server == NULL))
751 * No need to return error on this operation if tid invalidated and
752 * closed on server already e.g. due to tcp session crashing. Also,
753 * the tcon is no longer on the list, so no need to take lock before
756 if (tcon->need_reconnect)
759 rc = small_smb_init(SMB_COM_TREE_DISCONNECT, 0, tcon,
760 (void **)&smb_buffer);
764 rc = SendReceiveNoRsp(xid, tcon->ses, smb_buffer, 0);
766 cFYI(1, ("Tree disconnect failed %d", rc));
768 /* No need to return error on this operation if tid invalidated and
769 closed on server already e.g. due to tcp session crashing */
777 CIFSSMBLogoff(const int xid, struct cifsSesInfo *ses)
779 LOGOFF_ANDX_REQ *pSMB;
782 cFYI(1, ("In SMBLogoff for session disconnect"));
785 * BB: do we need to check validity of ses and server? They should
786 * always be valid since we have an active reference. If not, that
787 * should probably be a BUG()
789 if (!ses || !ses->server)
793 if (ses->need_reconnect)
794 goto session_already_dead; /* no need to send SMBlogoff if uid
795 already closed due to reconnect */
796 rc = small_smb_init(SMB_COM_LOGOFF_ANDX, 2, NULL, (void **)&pSMB);
802 pSMB->hdr.Mid = GetNextMid(ses->server);
804 if (ses->server->secMode &
805 (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
806 pSMB->hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
808 pSMB->hdr.Uid = ses->Suid;
810 pSMB->AndXCommand = 0xFF;
811 rc = SendReceiveNoRsp(xid, ses, (struct smb_hdr *) pSMB, 0);
812 session_already_dead:
815 /* if session dead then we do not need to do ulogoff,
816 since server closed smb session, no sense reporting
824 CIFSPOSIXDelFile(const int xid, struct cifsTconInfo *tcon, const char *fileName,
825 __u16 type, const struct nls_table *nls_codepage, int remap)
827 TRANSACTION2_SPI_REQ *pSMB = NULL;
828 TRANSACTION2_SPI_RSP *pSMBr = NULL;
829 struct unlink_psx_rq *pRqD;
832 int bytes_returned = 0;
833 __u16 params, param_offset, offset, byte_count;
835 cFYI(1, ("In POSIX delete"));
837 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
842 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
844 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
845 PATH_MAX, nls_codepage, remap);
846 name_len++; /* trailing null */
848 } else { /* BB add path length overrun check */
849 name_len = strnlen(fileName, PATH_MAX);
850 name_len++; /* trailing null */
851 strncpy(pSMB->FileName, fileName, name_len);
854 params = 6 + name_len;
855 pSMB->MaxParameterCount = cpu_to_le16(2);
856 pSMB->MaxDataCount = 0; /* BB double check this with jra */
857 pSMB->MaxSetupCount = 0;
862 param_offset = offsetof(struct smb_com_transaction2_spi_req,
863 InformationLevel) - 4;
864 offset = param_offset + params;
866 /* Setup pointer to Request Data (inode type) */
867 pRqD = (struct unlink_psx_rq *)(((char *)&pSMB->hdr.Protocol) + offset);
868 pRqD->type = cpu_to_le16(type);
869 pSMB->ParameterOffset = cpu_to_le16(param_offset);
870 pSMB->DataOffset = cpu_to_le16(offset);
871 pSMB->SetupCount = 1;
873 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
874 byte_count = 3 /* pad */ + params + sizeof(struct unlink_psx_rq);
876 pSMB->DataCount = cpu_to_le16(sizeof(struct unlink_psx_rq));
877 pSMB->TotalDataCount = cpu_to_le16(sizeof(struct unlink_psx_rq));
878 pSMB->ParameterCount = cpu_to_le16(params);
879 pSMB->TotalParameterCount = pSMB->ParameterCount;
880 pSMB->InformationLevel = cpu_to_le16(SMB_POSIX_UNLINK);
882 pSMB->hdr.smb_buf_length += byte_count;
883 pSMB->ByteCount = cpu_to_le16(byte_count);
884 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
885 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
887 cFYI(1, ("Posix delete returned %d", rc));
888 cifs_buf_release(pSMB);
890 cifs_stats_inc(&tcon->num_deletes);
899 CIFSSMBDelFile(const int xid, struct cifsTconInfo *tcon, const char *fileName,
900 const struct nls_table *nls_codepage, int remap)
902 DELETE_FILE_REQ *pSMB = NULL;
903 DELETE_FILE_RSP *pSMBr = NULL;
909 rc = smb_init(SMB_COM_DELETE, 1, tcon, (void **) &pSMB,
914 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
916 cifsConvertToUCS((__le16 *) pSMB->fileName, fileName,
917 PATH_MAX, nls_codepage, remap);
918 name_len++; /* trailing null */
920 } else { /* BB improve check for buffer overruns BB */
921 name_len = strnlen(fileName, PATH_MAX);
922 name_len++; /* trailing null */
923 strncpy(pSMB->fileName, fileName, name_len);
925 pSMB->SearchAttributes =
926 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM);
927 pSMB->BufferFormat = 0x04;
928 pSMB->hdr.smb_buf_length += name_len + 1;
929 pSMB->ByteCount = cpu_to_le16(name_len + 1);
930 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
931 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
932 cifs_stats_inc(&tcon->num_deletes);
934 cFYI(1, ("Error in RMFile = %d", rc));
936 cifs_buf_release(pSMB);
944 CIFSSMBRmDir(const int xid, struct cifsTconInfo *tcon, const char *dirName,
945 const struct nls_table *nls_codepage, int remap)
947 DELETE_DIRECTORY_REQ *pSMB = NULL;
948 DELETE_DIRECTORY_RSP *pSMBr = NULL;
953 cFYI(1, ("In CIFSSMBRmDir"));
955 rc = smb_init(SMB_COM_DELETE_DIRECTORY, 0, tcon, (void **) &pSMB,
960 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
961 name_len = cifsConvertToUCS((__le16 *) pSMB->DirName, dirName,
962 PATH_MAX, nls_codepage, remap);
963 name_len++; /* trailing null */
965 } else { /* BB improve check for buffer overruns BB */
966 name_len = strnlen(dirName, PATH_MAX);
967 name_len++; /* trailing null */
968 strncpy(pSMB->DirName, dirName, name_len);
971 pSMB->BufferFormat = 0x04;
972 pSMB->hdr.smb_buf_length += name_len + 1;
973 pSMB->ByteCount = cpu_to_le16(name_len + 1);
974 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
975 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
976 cifs_stats_inc(&tcon->num_rmdirs);
978 cFYI(1, ("Error in RMDir = %d", rc));
980 cifs_buf_release(pSMB);
987 CIFSSMBMkDir(const int xid, struct cifsTconInfo *tcon,
988 const char *name, const struct nls_table *nls_codepage, int remap)
991 CREATE_DIRECTORY_REQ *pSMB = NULL;
992 CREATE_DIRECTORY_RSP *pSMBr = NULL;
996 cFYI(1, ("In CIFSSMBMkDir"));
998 rc = smb_init(SMB_COM_CREATE_DIRECTORY, 0, tcon, (void **) &pSMB,
1003 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1004 name_len = cifsConvertToUCS((__le16 *) pSMB->DirName, name,
1005 PATH_MAX, nls_codepage, remap);
1006 name_len++; /* trailing null */
1008 } else { /* BB improve check for buffer overruns BB */
1009 name_len = strnlen(name, PATH_MAX);
1010 name_len++; /* trailing null */
1011 strncpy(pSMB->DirName, name, name_len);
1014 pSMB->BufferFormat = 0x04;
1015 pSMB->hdr.smb_buf_length += name_len + 1;
1016 pSMB->ByteCount = cpu_to_le16(name_len + 1);
1017 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1018 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1019 cifs_stats_inc(&tcon->num_mkdirs);
1021 cFYI(1, ("Error in Mkdir = %d", rc));
1023 cifs_buf_release(pSMB);
1030 CIFSPOSIXCreate(const int xid, struct cifsTconInfo *tcon, __u32 posix_flags,
1031 __u64 mode, __u16 *netfid, FILE_UNIX_BASIC_INFO *pRetData,
1032 __u32 *pOplock, const char *name,
1033 const struct nls_table *nls_codepage, int remap)
1035 TRANSACTION2_SPI_REQ *pSMB = NULL;
1036 TRANSACTION2_SPI_RSP *pSMBr = NULL;
1039 int bytes_returned = 0;
1040 __u16 params, param_offset, offset, byte_count, count;
1041 OPEN_PSX_REQ *pdata;
1042 OPEN_PSX_RSP *psx_rsp;
1044 cFYI(1, ("In POSIX Create"));
1046 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
1051 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1053 cifsConvertToUCS((__le16 *) pSMB->FileName, name,
1054 PATH_MAX, nls_codepage, remap);
1055 name_len++; /* trailing null */
1057 } else { /* BB improve the check for buffer overruns BB */
1058 name_len = strnlen(name, PATH_MAX);
1059 name_len++; /* trailing null */
1060 strncpy(pSMB->FileName, name, name_len);
1063 params = 6 + name_len;
1064 count = sizeof(OPEN_PSX_REQ);
1065 pSMB->MaxParameterCount = cpu_to_le16(2);
1066 pSMB->MaxDataCount = cpu_to_le16(1000); /* large enough */
1067 pSMB->MaxSetupCount = 0;
1071 pSMB->Reserved2 = 0;
1072 param_offset = offsetof(struct smb_com_transaction2_spi_req,
1073 InformationLevel) - 4;
1074 offset = param_offset + params;
1075 pdata = (OPEN_PSX_REQ *)(((char *)&pSMB->hdr.Protocol) + offset);
1076 pdata->Level = cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC);
1077 pdata->Permissions = cpu_to_le64(mode);
1078 pdata->PosixOpenFlags = cpu_to_le32(posix_flags);
1079 pdata->OpenFlags = cpu_to_le32(*pOplock);
1080 pSMB->ParameterOffset = cpu_to_le16(param_offset);
1081 pSMB->DataOffset = cpu_to_le16(offset);
1082 pSMB->SetupCount = 1;
1083 pSMB->Reserved3 = 0;
1084 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
1085 byte_count = 3 /* pad */ + params + count;
1087 pSMB->DataCount = cpu_to_le16(count);
1088 pSMB->ParameterCount = cpu_to_le16(params);
1089 pSMB->TotalDataCount = pSMB->DataCount;
1090 pSMB->TotalParameterCount = pSMB->ParameterCount;
1091 pSMB->InformationLevel = cpu_to_le16(SMB_POSIX_OPEN);
1092 pSMB->Reserved4 = 0;
1093 pSMB->hdr.smb_buf_length += byte_count;
1094 pSMB->ByteCount = cpu_to_le16(byte_count);
1095 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1096 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1098 cFYI(1, ("Posix create returned %d", rc));
1099 goto psx_create_err;
1102 cFYI(1, ("copying inode info"));
1103 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
1105 if (rc || (pSMBr->ByteCount < sizeof(OPEN_PSX_RSP))) {
1106 rc = -EIO; /* bad smb */
1107 goto psx_create_err;
1110 /* copy return information to pRetData */
1111 psx_rsp = (OPEN_PSX_RSP *)((char *) &pSMBr->hdr.Protocol
1112 + le16_to_cpu(pSMBr->t2.DataOffset));
1114 *pOplock = le16_to_cpu(psx_rsp->OplockFlags);
1116 *netfid = psx_rsp->Fid; /* cifs fid stays in le */
1117 /* Let caller know file was created so we can set the mode. */
1118 /* Do we care about the CreateAction in any other cases? */
1119 if (cpu_to_le32(FILE_CREATE) == psx_rsp->CreateAction)
1120 *pOplock |= CIFS_CREATE_ACTION;
1121 /* check to make sure response data is there */
1122 if (psx_rsp->ReturnedLevel != cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC)) {
1123 pRetData->Type = cpu_to_le32(-1); /* unknown */
1124 cFYI(DBG2, ("unknown type"));
1126 if (pSMBr->ByteCount < sizeof(OPEN_PSX_RSP)
1127 + sizeof(FILE_UNIX_BASIC_INFO)) {
1128 cERROR(1, ("Open response data too small"));
1129 pRetData->Type = cpu_to_le32(-1);
1130 goto psx_create_err;
1132 memcpy((char *) pRetData,
1133 (char *)psx_rsp + sizeof(OPEN_PSX_RSP),
1134 sizeof(FILE_UNIX_BASIC_INFO));
1138 cifs_buf_release(pSMB);
1140 cifs_stats_inc(&tcon->num_mkdirs);
1148 static __u16 convert_disposition(int disposition)
1152 switch (disposition) {
1153 case FILE_SUPERSEDE:
1154 ofun = SMBOPEN_OCREATE | SMBOPEN_OTRUNC;
1157 ofun = SMBOPEN_OAPPEND;
1160 ofun = SMBOPEN_OCREATE;
1163 ofun = SMBOPEN_OCREATE | SMBOPEN_OAPPEND;
1165 case FILE_OVERWRITE:
1166 ofun = SMBOPEN_OTRUNC;
1168 case FILE_OVERWRITE_IF:
1169 ofun = SMBOPEN_OCREATE | SMBOPEN_OTRUNC;
1172 cFYI(1, ("unknown disposition %d", disposition));
1173 ofun = SMBOPEN_OAPPEND; /* regular open */
1179 access_flags_to_smbopen_mode(const int access_flags)
1181 int masked_flags = access_flags & (GENERIC_READ | GENERIC_WRITE);
1183 if (masked_flags == GENERIC_READ)
1184 return SMBOPEN_READ;
1185 else if (masked_flags == GENERIC_WRITE)
1186 return SMBOPEN_WRITE;
1188 /* just go for read/write */
1189 return SMBOPEN_READWRITE;
1193 SMBLegacyOpen(const int xid, struct cifsTconInfo *tcon,
1194 const char *fileName, const int openDisposition,
1195 const int access_flags, const int create_options, __u16 *netfid,
1196 int *pOplock, FILE_ALL_INFO *pfile_info,
1197 const struct nls_table *nls_codepage, int remap)
1200 OPENX_REQ *pSMB = NULL;
1201 OPENX_RSP *pSMBr = NULL;
1207 rc = smb_init(SMB_COM_OPEN_ANDX, 15, tcon, (void **) &pSMB,
1212 pSMB->AndXCommand = 0xFF; /* none */
1214 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1215 count = 1; /* account for one byte pad to word boundary */
1217 cifsConvertToUCS((__le16 *) (pSMB->fileName + 1),
1218 fileName, PATH_MAX, nls_codepage, remap);
1219 name_len++; /* trailing null */
1221 } else { /* BB improve check for buffer overruns BB */
1222 count = 0; /* no pad */
1223 name_len = strnlen(fileName, PATH_MAX);
1224 name_len++; /* trailing null */
1225 strncpy(pSMB->fileName, fileName, name_len);
1227 if (*pOplock & REQ_OPLOCK)
1228 pSMB->OpenFlags = cpu_to_le16(REQ_OPLOCK);
1229 else if (*pOplock & REQ_BATCHOPLOCK)
1230 pSMB->OpenFlags = cpu_to_le16(REQ_BATCHOPLOCK);
1232 pSMB->OpenFlags |= cpu_to_le16(REQ_MORE_INFO);
1233 pSMB->Mode = cpu_to_le16(access_flags_to_smbopen_mode(access_flags));
1234 pSMB->Mode |= cpu_to_le16(0x40); /* deny none */
1235 /* set file as system file if special file such
1236 as fifo and server expecting SFU style and
1237 no Unix extensions */
1239 if (create_options & CREATE_OPTION_SPECIAL)
1240 pSMB->FileAttributes = cpu_to_le16(ATTR_SYSTEM);
1241 else /* BB FIXME BB */
1242 pSMB->FileAttributes = cpu_to_le16(0/*ATTR_NORMAL*/);
1244 if (create_options & CREATE_OPTION_READONLY)
1245 pSMB->FileAttributes |= cpu_to_le16(ATTR_READONLY);
1248 /* pSMB->CreateOptions = cpu_to_le32(create_options &
1249 CREATE_OPTIONS_MASK); */
1250 /* BB FIXME END BB */
1252 pSMB->Sattr = cpu_to_le16(ATTR_HIDDEN | ATTR_SYSTEM | ATTR_DIRECTORY);
1253 pSMB->OpenFunction = cpu_to_le16(convert_disposition(openDisposition));
1255 pSMB->hdr.smb_buf_length += count;
1257 pSMB->ByteCount = cpu_to_le16(count);
1258 /* long_op set to 1 to allow for oplock break timeouts */
1259 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1260 (struct smb_hdr *)pSMBr, &bytes_returned, CIFS_LONG_OP);
1261 cifs_stats_inc(&tcon->num_opens);
1263 cFYI(1, ("Error in Open = %d", rc));
1265 /* BB verify if wct == 15 */
1267 /* *pOplock = pSMBr->OplockLevel; */ /* BB take from action field*/
1269 *netfid = pSMBr->Fid; /* cifs fid stays in le */
1270 /* Let caller know file was created so we can set the mode. */
1271 /* Do we care about the CreateAction in any other cases? */
1273 /* if (cpu_to_le32(FILE_CREATE) == pSMBr->CreateAction)
1274 *pOplock |= CIFS_CREATE_ACTION; */
1278 pfile_info->CreationTime = 0; /* BB convert CreateTime*/
1279 pfile_info->LastAccessTime = 0; /* BB fixme */
1280 pfile_info->LastWriteTime = 0; /* BB fixme */
1281 pfile_info->ChangeTime = 0; /* BB fixme */
1282 pfile_info->Attributes =
1283 cpu_to_le32(le16_to_cpu(pSMBr->FileAttributes));
1284 /* the file_info buf is endian converted by caller */
1285 pfile_info->AllocationSize =
1286 cpu_to_le64(le32_to_cpu(pSMBr->EndOfFile));
1287 pfile_info->EndOfFile = pfile_info->AllocationSize;
1288 pfile_info->NumberOfLinks = cpu_to_le32(1);
1289 pfile_info->DeletePending = 0;
1293 cifs_buf_release(pSMB);
1300 CIFSSMBOpen(const int xid, struct cifsTconInfo *tcon,
1301 const char *fileName, const int openDisposition,
1302 const int access_flags, const int create_options, __u16 *netfid,
1303 int *pOplock, FILE_ALL_INFO *pfile_info,
1304 const struct nls_table *nls_codepage, int remap)
1307 OPEN_REQ *pSMB = NULL;
1308 OPEN_RSP *pSMBr = NULL;
1314 rc = smb_init(SMB_COM_NT_CREATE_ANDX, 24, tcon, (void **) &pSMB,
1319 pSMB->AndXCommand = 0xFF; /* none */
1321 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1322 count = 1; /* account for one byte pad to word boundary */
1324 cifsConvertToUCS((__le16 *) (pSMB->fileName + 1),
1325 fileName, PATH_MAX, nls_codepage, remap);
1326 name_len++; /* trailing null */
1328 pSMB->NameLength = cpu_to_le16(name_len);
1329 } else { /* BB improve check for buffer overruns BB */
1330 count = 0; /* no pad */
1331 name_len = strnlen(fileName, PATH_MAX);
1332 name_len++; /* trailing null */
1333 pSMB->NameLength = cpu_to_le16(name_len);
1334 strncpy(pSMB->fileName, fileName, name_len);
1336 if (*pOplock & REQ_OPLOCK)
1337 pSMB->OpenFlags = cpu_to_le32(REQ_OPLOCK);
1338 else if (*pOplock & REQ_BATCHOPLOCK)
1339 pSMB->OpenFlags = cpu_to_le32(REQ_BATCHOPLOCK);
1340 pSMB->DesiredAccess = cpu_to_le32(access_flags);
1341 pSMB->AllocationSize = 0;
1342 /* set file as system file if special file such
1343 as fifo and server expecting SFU style and
1344 no Unix extensions */
1345 if (create_options & CREATE_OPTION_SPECIAL)
1346 pSMB->FileAttributes = cpu_to_le32(ATTR_SYSTEM);
1348 pSMB->FileAttributes = cpu_to_le32(ATTR_NORMAL);
1350 /* XP does not handle ATTR_POSIX_SEMANTICS */
1351 /* but it helps speed up case sensitive checks for other
1352 servers such as Samba */
1353 if (tcon->ses->capabilities & CAP_UNIX)
1354 pSMB->FileAttributes |= cpu_to_le32(ATTR_POSIX_SEMANTICS);
1356 if (create_options & CREATE_OPTION_READONLY)
1357 pSMB->FileAttributes |= cpu_to_le32(ATTR_READONLY);
1359 pSMB->ShareAccess = cpu_to_le32(FILE_SHARE_ALL);
1360 pSMB->CreateDisposition = cpu_to_le32(openDisposition);
1361 pSMB->CreateOptions = cpu_to_le32(create_options & CREATE_OPTIONS_MASK);
1362 /* BB Expirement with various impersonation levels and verify */
1363 pSMB->ImpersonationLevel = cpu_to_le32(SECURITY_IMPERSONATION);
1364 pSMB->SecurityFlags =
1365 SECURITY_CONTEXT_TRACKING | SECURITY_EFFECTIVE_ONLY;
1368 pSMB->hdr.smb_buf_length += count;
1370 pSMB->ByteCount = cpu_to_le16(count);
1371 /* long_op set to 1 to allow for oplock break timeouts */
1372 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1373 (struct smb_hdr *)pSMBr, &bytes_returned, CIFS_LONG_OP);
1374 cifs_stats_inc(&tcon->num_opens);
1376 cFYI(1, ("Error in Open = %d", rc));
1378 *pOplock = pSMBr->OplockLevel; /* 1 byte no need to le_to_cpu */
1379 *netfid = pSMBr->Fid; /* cifs fid stays in le */
1380 /* Let caller know file was created so we can set the mode. */
1381 /* Do we care about the CreateAction in any other cases? */
1382 if (cpu_to_le32(FILE_CREATE) == pSMBr->CreateAction)
1383 *pOplock |= CIFS_CREATE_ACTION;
1385 memcpy((char *)pfile_info, (char *)&pSMBr->CreationTime,
1386 36 /* CreationTime to Attributes */);
1387 /* the file_info buf is endian converted by caller */
1388 pfile_info->AllocationSize = pSMBr->AllocationSize;
1389 pfile_info->EndOfFile = pSMBr->EndOfFile;
1390 pfile_info->NumberOfLinks = cpu_to_le32(1);
1391 pfile_info->DeletePending = 0;
1395 cifs_buf_release(pSMB);
1402 CIFSSMBRead(const int xid, struct cifsTconInfo *tcon, const int netfid,
1403 const unsigned int count, const __u64 lseek, unsigned int *nbytes,
1404 char **buf, int *pbuf_type)
1407 READ_REQ *pSMB = NULL;
1408 READ_RSP *pSMBr = NULL;
1409 char *pReadData = NULL;
1411 int resp_buf_type = 0;
1414 cFYI(1, ("Reading %d bytes on fid %d", count, netfid));
1415 if (tcon->ses->capabilities & CAP_LARGE_FILES)
1418 wct = 10; /* old style read */
1419 if ((lseek >> 32) > 0) {
1420 /* can not handle this big offset for old */
1426 rc = small_smb_init(SMB_COM_READ_ANDX, wct, tcon, (void **) &pSMB);
1430 /* tcon and ses pointer are checked in smb_init */
1431 if (tcon->ses->server == NULL)
1432 return -ECONNABORTED;
1434 pSMB->AndXCommand = 0xFF; /* none */
1436 pSMB->OffsetLow = cpu_to_le32(lseek & 0xFFFFFFFF);
1438 pSMB->OffsetHigh = cpu_to_le32(lseek >> 32);
1440 pSMB->Remaining = 0;
1441 pSMB->MaxCount = cpu_to_le16(count & 0xFFFF);
1442 pSMB->MaxCountHigh = cpu_to_le32(count >> 16);
1444 pSMB->ByteCount = 0; /* no need to do le conversion since 0 */
1446 /* old style read */
1447 struct smb_com_readx_req *pSMBW =
1448 (struct smb_com_readx_req *)pSMB;
1449 pSMBW->ByteCount = 0;
1452 iov[0].iov_base = (char *)pSMB;
1453 iov[0].iov_len = pSMB->hdr.smb_buf_length + 4;
1454 rc = SendReceive2(xid, tcon->ses, iov, 1 /* num iovecs */,
1455 &resp_buf_type, CIFS_STD_OP | CIFS_LOG_ERROR);
1456 cifs_stats_inc(&tcon->num_reads);
1457 pSMBr = (READ_RSP *)iov[0].iov_base;
1459 cERROR(1, ("Send error in read = %d", rc));
1461 int data_length = le16_to_cpu(pSMBr->DataLengthHigh);
1462 data_length = data_length << 16;
1463 data_length += le16_to_cpu(pSMBr->DataLength);
1464 *nbytes = data_length;
1466 /*check that DataLength would not go beyond end of SMB */
1467 if ((data_length > CIFSMaxBufSize)
1468 || (data_length > count)) {
1469 cFYI(1, ("bad length %d for count %d",
1470 data_length, count));
1474 pReadData = (char *) (&pSMBr->hdr.Protocol) +
1475 le16_to_cpu(pSMBr->DataOffset);
1476 /* if (rc = copy_to_user(buf, pReadData, data_length)) {
1477 cERROR(1,("Faulting on read rc = %d",rc));
1479 }*/ /* can not use copy_to_user when using page cache*/
1481 memcpy(*buf, pReadData, data_length);
1485 /* cifs_small_buf_release(pSMB); */ /* Freed earlier now in SendReceive2 */
1487 if (resp_buf_type == CIFS_SMALL_BUFFER)
1488 cifs_small_buf_release(iov[0].iov_base);
1489 else if (resp_buf_type == CIFS_LARGE_BUFFER)
1490 cifs_buf_release(iov[0].iov_base);
1491 } else if (resp_buf_type != CIFS_NO_BUFFER) {
1492 /* return buffer to caller to free */
1493 *buf = iov[0].iov_base;
1494 if (resp_buf_type == CIFS_SMALL_BUFFER)
1495 *pbuf_type = CIFS_SMALL_BUFFER;
1496 else if (resp_buf_type == CIFS_LARGE_BUFFER)
1497 *pbuf_type = CIFS_LARGE_BUFFER;
1498 } /* else no valid buffer on return - leave as null */
1500 /* Note: On -EAGAIN error only caller can retry on handle based calls
1501 since file handle passed in no longer valid */
1507 CIFSSMBWrite(const int xid, struct cifsTconInfo *tcon,
1508 const int netfid, const unsigned int count,
1509 const __u64 offset, unsigned int *nbytes, const char *buf,
1510 const char __user *ubuf, const int long_op)
1513 WRITE_REQ *pSMB = NULL;
1514 WRITE_RSP *pSMBr = NULL;
1515 int bytes_returned, wct;
1519 /* cFYI(1, ("write at %lld %d bytes", offset, count));*/
1520 if (tcon->ses == NULL)
1521 return -ECONNABORTED;
1523 if (tcon->ses->capabilities & CAP_LARGE_FILES)
1527 if ((offset >> 32) > 0) {
1528 /* can not handle big offset for old srv */
1533 rc = smb_init(SMB_COM_WRITE_ANDX, wct, tcon, (void **) &pSMB,
1537 /* tcon and ses pointer are checked in smb_init */
1538 if (tcon->ses->server == NULL)
1539 return -ECONNABORTED;
1541 pSMB->AndXCommand = 0xFF; /* none */
1543 pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF);
1545 pSMB->OffsetHigh = cpu_to_le32(offset >> 32);
1547 pSMB->Reserved = 0xFFFFFFFF;
1548 pSMB->WriteMode = 0;
1549 pSMB->Remaining = 0;
1551 /* Can increase buffer size if buffer is big enough in some cases ie we
1552 can send more if LARGE_WRITE_X capability returned by the server and if
1553 our buffer is big enough or if we convert to iovecs on socket writes
1554 and eliminate the copy to the CIFS buffer */
1555 if (tcon->ses->capabilities & CAP_LARGE_WRITE_X) {
1556 bytes_sent = min_t(const unsigned int, CIFSMaxBufSize, count);
1558 bytes_sent = (tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE)
1562 if (bytes_sent > count)
1565 cpu_to_le16(offsetof(struct smb_com_write_req, Data) - 4);
1567 memcpy(pSMB->Data, buf, bytes_sent);
1569 if (copy_from_user(pSMB->Data, ubuf, bytes_sent)) {
1570 cifs_buf_release(pSMB);
1573 } else if (count != 0) {
1575 cifs_buf_release(pSMB);
1577 } /* else setting file size with write of zero bytes */
1579 byte_count = bytes_sent + 1; /* pad */
1580 else /* wct == 12 */
1581 byte_count = bytes_sent + 5; /* bigger pad, smaller smb hdr */
1583 pSMB->DataLengthLow = cpu_to_le16(bytes_sent & 0xFFFF);
1584 pSMB->DataLengthHigh = cpu_to_le16(bytes_sent >> 16);
1585 pSMB->hdr.smb_buf_length += byte_count;
1588 pSMB->ByteCount = cpu_to_le16(byte_count);
1589 else { /* old style write has byte count 4 bytes earlier
1591 struct smb_com_writex_req *pSMBW =
1592 (struct smb_com_writex_req *)pSMB;
1593 pSMBW->ByteCount = cpu_to_le16(byte_count);
1596 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1597 (struct smb_hdr *) pSMBr, &bytes_returned, long_op);
1598 cifs_stats_inc(&tcon->num_writes);
1600 cFYI(1, ("Send error in write = %d", rc));
1603 *nbytes = le16_to_cpu(pSMBr->CountHigh);
1604 *nbytes = (*nbytes) << 16;
1605 *nbytes += le16_to_cpu(pSMBr->Count);
1608 cifs_buf_release(pSMB);
1610 /* Note: On -EAGAIN error only caller can retry on handle based calls
1611 since file handle passed in no longer valid */
1617 CIFSSMBWrite2(const int xid, struct cifsTconInfo *tcon,
1618 const int netfid, const unsigned int count,
1619 const __u64 offset, unsigned int *nbytes, struct kvec *iov,
1620 int n_vec, const int long_op)
1623 WRITE_REQ *pSMB = NULL;
1626 int resp_buf_type = 0;
1628 cFYI(1, ("write2 at %lld %d bytes", (long long)offset, count));
1630 if (tcon->ses->capabilities & CAP_LARGE_FILES) {
1634 if ((offset >> 32) > 0) {
1635 /* can not handle big offset for old srv */
1639 rc = small_smb_init(SMB_COM_WRITE_ANDX, wct, tcon, (void **) &pSMB);
1642 /* tcon and ses pointer are checked in smb_init */
1643 if (tcon->ses->server == NULL)
1644 return -ECONNABORTED;
1646 pSMB->AndXCommand = 0xFF; /* none */
1648 pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF);
1650 pSMB->OffsetHigh = cpu_to_le32(offset >> 32);
1651 pSMB->Reserved = 0xFFFFFFFF;
1652 pSMB->WriteMode = 0;
1653 pSMB->Remaining = 0;
1656 cpu_to_le16(offsetof(struct smb_com_write_req, Data) - 4);
1658 pSMB->DataLengthLow = cpu_to_le16(count & 0xFFFF);
1659 pSMB->DataLengthHigh = cpu_to_le16(count >> 16);
1660 smb_hdr_len = pSMB->hdr.smb_buf_length + 1; /* hdr + 1 byte pad */
1662 pSMB->hdr.smb_buf_length += count+1;
1663 else /* wct == 12 */
1664 pSMB->hdr.smb_buf_length += count+5; /* smb data starts later */
1666 pSMB->ByteCount = cpu_to_le16(count + 1);
1667 else /* wct == 12 */ /* bigger pad, smaller smb hdr, keep offset ok */ {
1668 struct smb_com_writex_req *pSMBW =
1669 (struct smb_com_writex_req *)pSMB;
1670 pSMBW->ByteCount = cpu_to_le16(count + 5);
1672 iov[0].iov_base = pSMB;
1674 iov[0].iov_len = smb_hdr_len + 4;
1675 else /* wct == 12 pad bigger by four bytes */
1676 iov[0].iov_len = smb_hdr_len + 8;
1679 rc = SendReceive2(xid, tcon->ses, iov, n_vec + 1, &resp_buf_type,
1681 cifs_stats_inc(&tcon->num_writes);
1683 cFYI(1, ("Send error Write2 = %d", rc));
1685 } else if (resp_buf_type == 0) {
1686 /* presumably this can not happen, but best to be safe */
1690 WRITE_RSP *pSMBr = (WRITE_RSP *)iov[0].iov_base;
1691 *nbytes = le16_to_cpu(pSMBr->CountHigh);
1692 *nbytes = (*nbytes) << 16;
1693 *nbytes += le16_to_cpu(pSMBr->Count);
1696 /* cifs_small_buf_release(pSMB); */ /* Freed earlier now in SendReceive2 */
1697 if (resp_buf_type == CIFS_SMALL_BUFFER)
1698 cifs_small_buf_release(iov[0].iov_base);
1699 else if (resp_buf_type == CIFS_LARGE_BUFFER)
1700 cifs_buf_release(iov[0].iov_base);
1702 /* Note: On -EAGAIN error only caller can retry on handle based calls
1703 since file handle passed in no longer valid */
1710 CIFSSMBLock(const int xid, struct cifsTconInfo *tcon,
1711 const __u16 smb_file_id, const __u64 len,
1712 const __u64 offset, const __u32 numUnlock,
1713 const __u32 numLock, const __u8 lockType, const bool waitFlag)
1716 LOCK_REQ *pSMB = NULL;
1717 /* LOCK_RSP *pSMBr = NULL; */ /* No response data other than rc to parse */
1722 cFYI(1, ("CIFSSMBLock timeout %d numLock %d", (int)waitFlag, numLock));
1723 rc = small_smb_init(SMB_COM_LOCKING_ANDX, 8, tcon, (void **) &pSMB);
1728 if (lockType == LOCKING_ANDX_OPLOCK_RELEASE) {
1729 timeout = CIFS_ASYNC_OP; /* no response expected */
1731 } else if (waitFlag) {
1732 timeout = CIFS_BLOCKING_OP; /* blocking operation, no timeout */
1733 pSMB->Timeout = cpu_to_le32(-1);/* blocking - do not time out */
1738 pSMB->NumberOfLocks = cpu_to_le16(numLock);
1739 pSMB->NumberOfUnlocks = cpu_to_le16(numUnlock);
1740 pSMB->LockType = lockType;
1741 pSMB->AndXCommand = 0xFF; /* none */
1742 pSMB->Fid = smb_file_id; /* netfid stays le */
1744 if ((numLock != 0) || (numUnlock != 0)) {
1745 pSMB->Locks[0].Pid = cpu_to_le16(current->tgid);
1746 /* BB where to store pid high? */
1747 pSMB->Locks[0].LengthLow = cpu_to_le32((u32)len);
1748 pSMB->Locks[0].LengthHigh = cpu_to_le32((u32)(len>>32));
1749 pSMB->Locks[0].OffsetLow = cpu_to_le32((u32)offset);
1750 pSMB->Locks[0].OffsetHigh = cpu_to_le32((u32)(offset>>32));
1751 count = sizeof(LOCKING_ANDX_RANGE);
1756 pSMB->hdr.smb_buf_length += count;
1757 pSMB->ByteCount = cpu_to_le16(count);
1760 rc = SendReceiveBlockingLock(xid, tcon, (struct smb_hdr *) pSMB,
1761 (struct smb_hdr *) pSMB, &bytes_returned);
1762 cifs_small_buf_release(pSMB);
1764 rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *)pSMB,
1766 /* SMB buffer freed by function above */
1768 cifs_stats_inc(&tcon->num_locks);
1770 cFYI(1, ("Send error in Lock = %d", rc));
1772 /* Note: On -EAGAIN error only caller can retry on handle based calls
1773 since file handle passed in no longer valid */
1778 CIFSSMBPosixLock(const int xid, struct cifsTconInfo *tcon,
1779 const __u16 smb_file_id, const int get_flag, const __u64 len,
1780 struct file_lock *pLockData, const __u16 lock_type,
1781 const bool waitFlag)
1783 struct smb_com_transaction2_sfi_req *pSMB = NULL;
1784 struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
1785 struct cifs_posix_lock *parm_data;
1788 int bytes_returned = 0;
1789 int resp_buf_type = 0;
1790 __u16 params, param_offset, offset, byte_count, count;
1793 cFYI(1, ("Posix Lock"));
1795 if (pLockData == NULL)
1798 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
1803 pSMBr = (struct smb_com_transaction2_sfi_rsp *)pSMB;
1806 pSMB->MaxSetupCount = 0;
1809 pSMB->Reserved2 = 0;
1810 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
1811 offset = param_offset + params;
1813 count = sizeof(struct cifs_posix_lock);
1814 pSMB->MaxParameterCount = cpu_to_le16(2);
1815 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB from sess */
1816 pSMB->SetupCount = 1;
1817 pSMB->Reserved3 = 0;
1819 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION);
1821 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
1822 byte_count = 3 /* pad */ + params + count;
1823 pSMB->DataCount = cpu_to_le16(count);
1824 pSMB->ParameterCount = cpu_to_le16(params);
1825 pSMB->TotalDataCount = pSMB->DataCount;
1826 pSMB->TotalParameterCount = pSMB->ParameterCount;
1827 pSMB->ParameterOffset = cpu_to_le16(param_offset);
1828 parm_data = (struct cifs_posix_lock *)
1829 (((char *) &pSMB->hdr.Protocol) + offset);
1831 parm_data->lock_type = cpu_to_le16(lock_type);
1833 timeout = CIFS_BLOCKING_OP; /* blocking operation, no timeout */
1834 parm_data->lock_flags = cpu_to_le16(1);
1835 pSMB->Timeout = cpu_to_le32(-1);
1839 parm_data->pid = cpu_to_le32(current->tgid);
1840 parm_data->start = cpu_to_le64(pLockData->fl_start);
1841 parm_data->length = cpu_to_le64(len); /* normalize negative numbers */
1843 pSMB->DataOffset = cpu_to_le16(offset);
1844 pSMB->Fid = smb_file_id;
1845 pSMB->InformationLevel = cpu_to_le16(SMB_SET_POSIX_LOCK);
1846 pSMB->Reserved4 = 0;
1847 pSMB->hdr.smb_buf_length += byte_count;
1848 pSMB->ByteCount = cpu_to_le16(byte_count);
1850 rc = SendReceiveBlockingLock(xid, tcon, (struct smb_hdr *) pSMB,
1851 (struct smb_hdr *) pSMBr, &bytes_returned);
1853 iov[0].iov_base = (char *)pSMB;
1854 iov[0].iov_len = pSMB->hdr.smb_buf_length + 4;
1855 rc = SendReceive2(xid, tcon->ses, iov, 1 /* num iovecs */,
1856 &resp_buf_type, timeout);
1857 pSMB = NULL; /* request buf already freed by SendReceive2. Do
1858 not try to free it twice below on exit */
1859 pSMBr = (struct smb_com_transaction2_sfi_rsp *)iov[0].iov_base;
1863 cFYI(1, ("Send error in Posix Lock = %d", rc));
1864 } else if (get_flag) {
1865 /* lock structure can be returned on get */
1868 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
1870 if (rc || (pSMBr->ByteCount < sizeof(struct cifs_posix_lock))) {
1871 rc = -EIO; /* bad smb */
1874 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
1875 data_count = le16_to_cpu(pSMBr->t2.DataCount);
1876 if (data_count < sizeof(struct cifs_posix_lock)) {
1880 parm_data = (struct cifs_posix_lock *)
1881 ((char *)&pSMBr->hdr.Protocol + data_offset);
1882 if (parm_data->lock_type == cpu_to_le16(CIFS_UNLCK))
1883 pLockData->fl_type = F_UNLCK;
1888 cifs_small_buf_release(pSMB);
1890 if (resp_buf_type == CIFS_SMALL_BUFFER)
1891 cifs_small_buf_release(iov[0].iov_base);
1892 else if (resp_buf_type == CIFS_LARGE_BUFFER)
1893 cifs_buf_release(iov[0].iov_base);
1895 /* Note: On -EAGAIN error only caller can retry on handle based calls
1896 since file handle passed in no longer valid */
1903 CIFSSMBClose(const int xid, struct cifsTconInfo *tcon, int smb_file_id)
1906 CLOSE_REQ *pSMB = NULL;
1907 cFYI(1, ("In CIFSSMBClose"));
1909 /* do not retry on dead session on close */
1910 rc = small_smb_init(SMB_COM_CLOSE, 3, tcon, (void **) &pSMB);
1916 pSMB->FileID = (__u16) smb_file_id;
1917 pSMB->LastWriteTime = 0xFFFFFFFF;
1918 pSMB->ByteCount = 0;
1919 rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0);
1920 cifs_stats_inc(&tcon->num_closes);
1923 /* EINTR is expected when user ctl-c to kill app */
1924 cERROR(1, ("Send error in Close = %d", rc));
1928 /* Since session is dead, file will be closed on server already */
1936 CIFSSMBRename(const int xid, struct cifsTconInfo *tcon,
1937 const char *fromName, const char *toName,
1938 const struct nls_table *nls_codepage, int remap)
1941 RENAME_REQ *pSMB = NULL;
1942 RENAME_RSP *pSMBr = NULL;
1944 int name_len, name_len2;
1947 cFYI(1, ("In CIFSSMBRename"));
1949 rc = smb_init(SMB_COM_RENAME, 1, tcon, (void **) &pSMB,
1954 pSMB->BufferFormat = 0x04;
1955 pSMB->SearchAttributes =
1956 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
1959 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1961 cifsConvertToUCS((__le16 *) pSMB->OldFileName, fromName,
1962 PATH_MAX, nls_codepage, remap);
1963 name_len++; /* trailing null */
1965 pSMB->OldFileName[name_len] = 0x04; /* pad */
1966 /* protocol requires ASCII signature byte on Unicode string */
1967 pSMB->OldFileName[name_len + 1] = 0x00;
1969 cifsConvertToUCS((__le16 *)&pSMB->OldFileName[name_len + 2],
1970 toName, PATH_MAX, nls_codepage, remap);
1971 name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
1972 name_len2 *= 2; /* convert to bytes */
1973 } else { /* BB improve the check for buffer overruns BB */
1974 name_len = strnlen(fromName, PATH_MAX);
1975 name_len++; /* trailing null */
1976 strncpy(pSMB->OldFileName, fromName, name_len);
1977 name_len2 = strnlen(toName, PATH_MAX);
1978 name_len2++; /* trailing null */
1979 pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */
1980 strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2);
1981 name_len2++; /* trailing null */
1982 name_len2++; /* signature byte */
1985 count = 1 /* 1st signature byte */ + name_len + name_len2;
1986 pSMB->hdr.smb_buf_length += count;
1987 pSMB->ByteCount = cpu_to_le16(count);
1989 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1990 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1991 cifs_stats_inc(&tcon->num_renames);
1993 cFYI(1, ("Send error in rename = %d", rc));
1995 cifs_buf_release(pSMB);
2003 int CIFSSMBRenameOpenFile(const int xid, struct cifsTconInfo *pTcon,
2004 int netfid, const char *target_name,
2005 const struct nls_table *nls_codepage, int remap)
2007 struct smb_com_transaction2_sfi_req *pSMB = NULL;
2008 struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
2009 struct set_file_rename *rename_info;
2011 char dummy_string[30];
2013 int bytes_returned = 0;
2015 __u16 params, param_offset, offset, count, byte_count;
2017 cFYI(1, ("Rename to File by handle"));
2018 rc = smb_init(SMB_COM_TRANSACTION2, 15, pTcon, (void **) &pSMB,
2024 pSMB->MaxSetupCount = 0;
2028 pSMB->Reserved2 = 0;
2029 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
2030 offset = param_offset + params;
2032 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
2033 rename_info = (struct set_file_rename *) data_offset;
2034 pSMB->MaxParameterCount = cpu_to_le16(2);
2035 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB from sess */
2036 pSMB->SetupCount = 1;
2037 pSMB->Reserved3 = 0;
2038 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
2039 byte_count = 3 /* pad */ + params;
2040 pSMB->ParameterCount = cpu_to_le16(params);
2041 pSMB->TotalParameterCount = pSMB->ParameterCount;
2042 pSMB->ParameterOffset = cpu_to_le16(param_offset);
2043 pSMB->DataOffset = cpu_to_le16(offset);
2044 /* construct random name ".cifs_tmp<inodenum><mid>" */
2045 rename_info->overwrite = cpu_to_le32(1);
2046 rename_info->root_fid = 0;
2047 /* unicode only call */
2048 if (target_name == NULL) {
2049 sprintf(dummy_string, "cifs%x", pSMB->hdr.Mid);
2050 len_of_str = cifsConvertToUCS((__le16 *)rename_info->target_name,
2051 dummy_string, 24, nls_codepage, remap);
2053 len_of_str = cifsConvertToUCS((__le16 *)rename_info->target_name,
2054 target_name, PATH_MAX, nls_codepage,
2057 rename_info->target_name_len = cpu_to_le32(2 * len_of_str);
2058 count = 12 /* sizeof(struct set_file_rename) */ + (2 * len_of_str);
2059 byte_count += count;
2060 pSMB->DataCount = cpu_to_le16(count);
2061 pSMB->TotalDataCount = pSMB->DataCount;
2063 pSMB->InformationLevel =
2064 cpu_to_le16(SMB_SET_FILE_RENAME_INFORMATION);
2065 pSMB->Reserved4 = 0;
2066 pSMB->hdr.smb_buf_length += byte_count;
2067 pSMB->ByteCount = cpu_to_le16(byte_count);
2068 rc = SendReceive(xid, pTcon->ses, (struct smb_hdr *) pSMB,
2069 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2070 cifs_stats_inc(&pTcon->num_t2renames);
2072 cFYI(1, ("Send error in Rename (by file handle) = %d", rc));
2074 cifs_buf_release(pSMB);
2076 /* Note: On -EAGAIN error only caller can retry on handle based calls
2077 since file handle passed in no longer valid */
2083 CIFSSMBCopy(const int xid, struct cifsTconInfo *tcon, const char *fromName,
2084 const __u16 target_tid, const char *toName, const int flags,
2085 const struct nls_table *nls_codepage, int remap)
2088 COPY_REQ *pSMB = NULL;
2089 COPY_RSP *pSMBr = NULL;
2091 int name_len, name_len2;
2094 cFYI(1, ("In CIFSSMBCopy"));
2096 rc = smb_init(SMB_COM_COPY, 1, tcon, (void **) &pSMB,
2101 pSMB->BufferFormat = 0x04;
2102 pSMB->Tid2 = target_tid;
2104 pSMB->Flags = cpu_to_le16(flags & COPY_TREE);
2106 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2107 name_len = cifsConvertToUCS((__le16 *) pSMB->OldFileName,
2108 fromName, PATH_MAX, nls_codepage,
2110 name_len++; /* trailing null */
2112 pSMB->OldFileName[name_len] = 0x04; /* pad */
2113 /* protocol requires ASCII signature byte on Unicode string */
2114 pSMB->OldFileName[name_len + 1] = 0x00;
2116 cifsConvertToUCS((__le16 *)&pSMB->OldFileName[name_len + 2],
2117 toName, PATH_MAX, nls_codepage, remap);
2118 name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
2119 name_len2 *= 2; /* convert to bytes */
2120 } else { /* BB improve the check for buffer overruns BB */
2121 name_len = strnlen(fromName, PATH_MAX);
2122 name_len++; /* trailing null */
2123 strncpy(pSMB->OldFileName, fromName, name_len);
2124 name_len2 = strnlen(toName, PATH_MAX);
2125 name_len2++; /* trailing null */
2126 pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */
2127 strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2);
2128 name_len2++; /* trailing null */
2129 name_len2++; /* signature byte */
2132 count = 1 /* 1st signature byte */ + name_len + name_len2;
2133 pSMB->hdr.smb_buf_length += count;
2134 pSMB->ByteCount = cpu_to_le16(count);
2136 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2137 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2139 cFYI(1, ("Send error in copy = %d with %d files copied",
2140 rc, le16_to_cpu(pSMBr->CopyCount)));
2142 cifs_buf_release(pSMB);
2151 CIFSUnixCreateSymLink(const int xid, struct cifsTconInfo *tcon,
2152 const char *fromName, const char *toName,
2153 const struct nls_table *nls_codepage)
2155 TRANSACTION2_SPI_REQ *pSMB = NULL;
2156 TRANSACTION2_SPI_RSP *pSMBr = NULL;
2159 int name_len_target;
2161 int bytes_returned = 0;
2162 __u16 params, param_offset, offset, byte_count;
2164 cFYI(1, ("In Symlink Unix style"));
2166 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2171 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2173 cifs_strtoUCS((__le16 *) pSMB->FileName, fromName, PATH_MAX
2174 /* find define for this maxpathcomponent */
2176 name_len++; /* trailing null */
2179 } else { /* BB improve the check for buffer overruns BB */
2180 name_len = strnlen(fromName, PATH_MAX);
2181 name_len++; /* trailing null */
2182 strncpy(pSMB->FileName, fromName, name_len);
2184 params = 6 + name_len;
2185 pSMB->MaxSetupCount = 0;
2189 pSMB->Reserved2 = 0;
2190 param_offset = offsetof(struct smb_com_transaction2_spi_req,
2191 InformationLevel) - 4;
2192 offset = param_offset + params;
2194 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
2195 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2197 cifs_strtoUCS((__le16 *) data_offset, toName, PATH_MAX
2198 /* find define for this maxpathcomponent */
2200 name_len_target++; /* trailing null */
2201 name_len_target *= 2;
2202 } else { /* BB improve the check for buffer overruns BB */
2203 name_len_target = strnlen(toName, PATH_MAX);
2204 name_len_target++; /* trailing null */
2205 strncpy(data_offset, toName, name_len_target);
2208 pSMB->MaxParameterCount = cpu_to_le16(2);
2209 /* BB find exact max on data count below from sess */
2210 pSMB->MaxDataCount = cpu_to_le16(1000);
2211 pSMB->SetupCount = 1;
2212 pSMB->Reserved3 = 0;
2213 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
2214 byte_count = 3 /* pad */ + params + name_len_target;
2215 pSMB->DataCount = cpu_to_le16(name_len_target);
2216 pSMB->ParameterCount = cpu_to_le16(params);
2217 pSMB->TotalDataCount = pSMB->DataCount;
2218 pSMB->TotalParameterCount = pSMB->ParameterCount;
2219 pSMB->ParameterOffset = cpu_to_le16(param_offset);
2220 pSMB->DataOffset = cpu_to_le16(offset);
2221 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_LINK);
2222 pSMB->Reserved4 = 0;
2223 pSMB->hdr.smb_buf_length += byte_count;
2224 pSMB->ByteCount = cpu_to_le16(byte_count);
2225 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2226 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2227 cifs_stats_inc(&tcon->num_symlinks);
2229 cFYI(1, ("Send error in SetPathInfo create symlink = %d", rc));
2231 cifs_buf_release(pSMB);
2234 goto createSymLinkRetry;
2240 CIFSUnixCreateHardLink(const int xid, struct cifsTconInfo *tcon,
2241 const char *fromName, const char *toName,
2242 const struct nls_table *nls_codepage, int remap)
2244 TRANSACTION2_SPI_REQ *pSMB = NULL;
2245 TRANSACTION2_SPI_RSP *pSMBr = NULL;
2248 int name_len_target;
2250 int bytes_returned = 0;
2251 __u16 params, param_offset, offset, byte_count;
2253 cFYI(1, ("In Create Hard link Unix style"));
2254 createHardLinkRetry:
2255 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2260 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2261 name_len = cifsConvertToUCS((__le16 *) pSMB->FileName, toName,
2262 PATH_MAX, nls_codepage, remap);
2263 name_len++; /* trailing null */
2266 } else { /* BB improve the check for buffer overruns BB */
2267 name_len = strnlen(toName, PATH_MAX);
2268 name_len++; /* trailing null */
2269 strncpy(pSMB->FileName, toName, name_len);
2271 params = 6 + name_len;
2272 pSMB->MaxSetupCount = 0;
2276 pSMB->Reserved2 = 0;
2277 param_offset = offsetof(struct smb_com_transaction2_spi_req,
2278 InformationLevel) - 4;
2279 offset = param_offset + params;
2281 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
2282 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2284 cifsConvertToUCS((__le16 *) data_offset, fromName, PATH_MAX,
2285 nls_codepage, remap);
2286 name_len_target++; /* trailing null */
2287 name_len_target *= 2;
2288 } else { /* BB improve the check for buffer overruns BB */
2289 name_len_target = strnlen(fromName, PATH_MAX);
2290 name_len_target++; /* trailing null */
2291 strncpy(data_offset, fromName, name_len_target);
2294 pSMB->MaxParameterCount = cpu_to_le16(2);
2295 /* BB find exact max on data count below from sess*/
2296 pSMB->MaxDataCount = cpu_to_le16(1000);
2297 pSMB->SetupCount = 1;
2298 pSMB->Reserved3 = 0;
2299 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
2300 byte_count = 3 /* pad */ + params + name_len_target;
2301 pSMB->ParameterCount = cpu_to_le16(params);
2302 pSMB->TotalParameterCount = pSMB->ParameterCount;
2303 pSMB->DataCount = cpu_to_le16(name_len_target);
2304 pSMB->TotalDataCount = pSMB->DataCount;
2305 pSMB->ParameterOffset = cpu_to_le16(param_offset);
2306 pSMB->DataOffset = cpu_to_le16(offset);
2307 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_HLINK);
2308 pSMB->Reserved4 = 0;
2309 pSMB->hdr.smb_buf_length += byte_count;
2310 pSMB->ByteCount = cpu_to_le16(byte_count);
2311 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2312 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2313 cifs_stats_inc(&tcon->num_hardlinks);
2315 cFYI(1, ("Send error in SetPathInfo (hard link) = %d", rc));
2317 cifs_buf_release(pSMB);
2319 goto createHardLinkRetry;
2325 CIFSCreateHardLink(const int xid, struct cifsTconInfo *tcon,
2326 const char *fromName, const char *toName,
2327 const struct nls_table *nls_codepage, int remap)
2330 NT_RENAME_REQ *pSMB = NULL;
2331 RENAME_RSP *pSMBr = NULL;
2333 int name_len, name_len2;
2336 cFYI(1, ("In CIFSCreateHardLink"));
2337 winCreateHardLinkRetry:
2339 rc = smb_init(SMB_COM_NT_RENAME, 4, tcon, (void **) &pSMB,
2344 pSMB->SearchAttributes =
2345 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
2347 pSMB->Flags = cpu_to_le16(CREATE_HARD_LINK);
2348 pSMB->ClusterCount = 0;
2350 pSMB->BufferFormat = 0x04;
2352 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2354 cifsConvertToUCS((__le16 *) pSMB->OldFileName, fromName,
2355 PATH_MAX, nls_codepage, remap);
2356 name_len++; /* trailing null */
2358 pSMB->OldFileName[name_len] = 0; /* pad */
2359 pSMB->OldFileName[name_len + 1] = 0x04;
2361 cifsConvertToUCS((__le16 *)&pSMB->OldFileName[name_len + 2],
2362 toName, PATH_MAX, nls_codepage, remap);
2363 name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
2364 name_len2 *= 2; /* convert to bytes */
2365 } else { /* BB improve the check for buffer overruns BB */
2366 name_len = strnlen(fromName, PATH_MAX);
2367 name_len++; /* trailing null */
2368 strncpy(pSMB->OldFileName, fromName, name_len);
2369 name_len2 = strnlen(toName, PATH_MAX);
2370 name_len2++; /* trailing null */
2371 pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */
2372 strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2);
2373 name_len2++; /* trailing null */
2374 name_len2++; /* signature byte */
2377 count = 1 /* string type byte */ + name_len + name_len2;
2378 pSMB->hdr.smb_buf_length += count;
2379 pSMB->ByteCount = cpu_to_le16(count);
2381 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2382 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2383 cifs_stats_inc(&tcon->num_hardlinks);
2385 cFYI(1, ("Send error in hard link (NT rename) = %d", rc));
2387 cifs_buf_release(pSMB);
2389 goto winCreateHardLinkRetry;
2395 CIFSSMBUnixQuerySymLink(const int xid, struct cifsTconInfo *tcon,
2396 const unsigned char *searchName,
2397 char *symlinkinfo, const int buflen,
2398 const struct nls_table *nls_codepage)
2400 /* SMB_QUERY_FILE_UNIX_LINK */
2401 TRANSACTION2_QPI_REQ *pSMB = NULL;
2402 TRANSACTION2_QPI_RSP *pSMBr = NULL;
2406 __u16 params, byte_count;
2408 cFYI(1, ("In QPathSymLinkInfo (Unix) for path %s", searchName));
2411 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2416 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2418 cifs_strtoUCS((__le16 *) pSMB->FileName, searchName,
2419 PATH_MAX, nls_codepage);
2420 name_len++; /* trailing null */
2422 } else { /* BB improve the check for buffer overruns BB */
2423 name_len = strnlen(searchName, PATH_MAX);
2424 name_len++; /* trailing null */
2425 strncpy(pSMB->FileName, searchName, name_len);
2428 params = 2 /* level */ + 4 /* rsrvd */ + name_len /* incl null */ ;
2429 pSMB->TotalDataCount = 0;
2430 pSMB->MaxParameterCount = cpu_to_le16(2);
2431 /* BB find exact max data count below from sess structure BB */
2432 pSMB->MaxDataCount = cpu_to_le16(4000);
2433 pSMB->MaxSetupCount = 0;
2437 pSMB->Reserved2 = 0;
2438 pSMB->ParameterOffset = cpu_to_le16(offsetof(
2439 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
2440 pSMB->DataCount = 0;
2441 pSMB->DataOffset = 0;
2442 pSMB->SetupCount = 1;
2443 pSMB->Reserved3 = 0;
2444 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
2445 byte_count = params + 1 /* pad */ ;
2446 pSMB->TotalParameterCount = cpu_to_le16(params);
2447 pSMB->ParameterCount = pSMB->TotalParameterCount;
2448 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_LINK);
2449 pSMB->Reserved4 = 0;
2450 pSMB->hdr.smb_buf_length += byte_count;
2451 pSMB->ByteCount = cpu_to_le16(byte_count);
2453 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2454 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2456 cFYI(1, ("Send error in QuerySymLinkInfo = %d", rc));
2458 /* decode response */
2460 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
2461 if (rc || (pSMBr->ByteCount < 2))
2462 /* BB also check enough total bytes returned */
2463 rc = -EIO; /* bad smb */
2465 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
2466 __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
2468 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
2469 name_len = UniStrnlen((wchar_t *) ((char *)
2470 &pSMBr->hdr.Protocol + data_offset),
2471 min_t(const int, buflen, count) / 2);
2472 /* BB FIXME investigate remapping reserved chars here */
2473 cifs_strfromUCS_le(symlinkinfo,
2474 (__le16 *) ((char *)&pSMBr->hdr.Protocol
2476 name_len, nls_codepage);
2478 strncpy(symlinkinfo,
2479 (char *) &pSMBr->hdr.Protocol +
2481 min_t(const int, buflen, count));
2483 symlinkinfo[buflen] = 0;
2484 /* just in case so calling code does not go off the end of buffer */
2487 cifs_buf_release(pSMB);
2489 goto querySymLinkRetry;
2493 #ifdef CONFIG_CIFS_EXPERIMENTAL
2494 /* Initialize NT TRANSACT SMB into small smb request buffer.
2495 This assumes that all NT TRANSACTS that we init here have
2496 total parm and data under about 400 bytes (to fit in small cifs
2497 buffer size), which is the case so far, it easily fits. NB:
2498 Setup words themselves and ByteCount
2499 MaxSetupCount (size of returned setup area) and
2500 MaxParameterCount (returned parms size) must be set by caller */
2502 smb_init_nttransact(const __u16 sub_command, const int setup_count,
2503 const int parm_len, struct cifsTconInfo *tcon,
2508 struct smb_com_ntransact_req *pSMB;
2510 rc = small_smb_init(SMB_COM_NT_TRANSACT, 19 + setup_count, tcon,
2514 *ret_buf = (void *)pSMB;
2516 pSMB->TotalParameterCount = cpu_to_le32(parm_len);
2517 pSMB->TotalDataCount = 0;
2518 pSMB->MaxDataCount = cpu_to_le32((tcon->ses->server->maxBuf -
2519 MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
2520 pSMB->ParameterCount = pSMB->TotalParameterCount;
2521 pSMB->DataCount = pSMB->TotalDataCount;
2522 temp_offset = offsetof(struct smb_com_ntransact_req, Parms) +
2523 (setup_count * 2) - 4 /* for rfc1001 length itself */;
2524 pSMB->ParameterOffset = cpu_to_le32(temp_offset);
2525 pSMB->DataOffset = cpu_to_le32(temp_offset + parm_len);
2526 pSMB->SetupCount = setup_count; /* no need to le convert byte fields */
2527 pSMB->SubCommand = cpu_to_le16(sub_command);
2532 validate_ntransact(char *buf, char **ppparm, char **ppdata,
2533 __u32 *pparmlen, __u32 *pdatalen)
2536 __u32 data_count, data_offset, parm_count, parm_offset;
2537 struct smb_com_ntransact_rsp *pSMBr;
2545 pSMBr = (struct smb_com_ntransact_rsp *)buf;
2547 /* ByteCount was converted from little endian in SendReceive */
2548 end_of_smb = 2 /* sizeof byte count */ + pSMBr->ByteCount +
2549 (char *)&pSMBr->ByteCount;
2551 data_offset = le32_to_cpu(pSMBr->DataOffset);
2552 data_count = le32_to_cpu(pSMBr->DataCount);
2553 parm_offset = le32_to_cpu(pSMBr->ParameterOffset);
2554 parm_count = le32_to_cpu(pSMBr->ParameterCount);
2556 *ppparm = (char *)&pSMBr->hdr.Protocol + parm_offset;
2557 *ppdata = (char *)&pSMBr->hdr.Protocol + data_offset;
2559 /* should we also check that parm and data areas do not overlap? */
2560 if (*ppparm > end_of_smb) {
2561 cFYI(1, ("parms start after end of smb"));
2563 } else if (parm_count + *ppparm > end_of_smb) {
2564 cFYI(1, ("parm end after end of smb"));
2566 } else if (*ppdata > end_of_smb) {
2567 cFYI(1, ("data starts after end of smb"));
2569 } else if (data_count + *ppdata > end_of_smb) {
2570 cFYI(1, ("data %p + count %d (%p) ends after end of smb %p start %p",
2571 *ppdata, data_count, (data_count + *ppdata),
2572 end_of_smb, pSMBr));
2574 } else if (parm_count + data_count > pSMBr->ByteCount) {
2575 cFYI(1, ("parm count and data count larger than SMB"));
2578 *pdatalen = data_count;
2579 *pparmlen = parm_count;
2582 #endif /* CIFS_EXPERIMENTAL */
2585 CIFSSMBQueryReparseLinkInfo(const int xid, struct cifsTconInfo *tcon,
2586 const unsigned char *searchName,
2587 char *symlinkinfo, const int buflen, __u16 fid,
2588 const struct nls_table *nls_codepage)
2593 struct smb_com_transaction_ioctl_req *pSMB;
2594 struct smb_com_transaction_ioctl_rsp *pSMBr;
2596 cFYI(1, ("In Windows reparse style QueryLink for path %s", searchName));
2597 rc = smb_init(SMB_COM_NT_TRANSACT, 23, tcon, (void **) &pSMB,
2602 pSMB->TotalParameterCount = 0 ;
2603 pSMB->TotalDataCount = 0;
2604 pSMB->MaxParameterCount = cpu_to_le32(2);
2605 /* BB find exact data count max from sess structure BB */
2606 pSMB->MaxDataCount = cpu_to_le32((tcon->ses->server->maxBuf -
2607 MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
2608 pSMB->MaxSetupCount = 4;
2610 pSMB->ParameterOffset = 0;
2611 pSMB->DataCount = 0;
2612 pSMB->DataOffset = 0;
2613 pSMB->SetupCount = 4;
2614 pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_IOCTL);
2615 pSMB->ParameterCount = pSMB->TotalParameterCount;
2616 pSMB->FunctionCode = cpu_to_le32(FSCTL_GET_REPARSE_POINT);
2617 pSMB->IsFsctl = 1; /* FSCTL */
2618 pSMB->IsRootFlag = 0;
2619 pSMB->Fid = fid; /* file handle always le */
2620 pSMB->ByteCount = 0;
2622 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2623 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2625 cFYI(1, ("Send error in QueryReparseLinkInfo = %d", rc));
2626 } else { /* decode response */
2627 __u32 data_offset = le32_to_cpu(pSMBr->DataOffset);
2628 __u32 data_count = le32_to_cpu(pSMBr->DataCount);
2629 if ((pSMBr->ByteCount < 2) || (data_offset > 512))
2630 /* BB also check enough total bytes returned */
2631 rc = -EIO; /* bad smb */
2633 if (data_count && (data_count < 2048)) {
2634 char *end_of_smb = 2 /* sizeof byte count */ +
2636 (char *)&pSMBr->ByteCount;
2638 struct reparse_data *reparse_buf =
2639 (struct reparse_data *)
2640 ((char *)&pSMBr->hdr.Protocol
2642 if ((char *)reparse_buf >= end_of_smb) {
2646 if ((reparse_buf->LinkNamesBuf +
2647 reparse_buf->TargetNameOffset +
2648 reparse_buf->TargetNameLen) >
2650 cFYI(1, ("reparse buf beyond SMB"));
2655 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
2656 name_len = UniStrnlen((wchar_t *)
2657 (reparse_buf->LinkNamesBuf +
2658 reparse_buf->TargetNameOffset),
2660 reparse_buf->TargetNameLen / 2));
2661 cifs_strfromUCS_le(symlinkinfo,
2662 (__le16 *) (reparse_buf->LinkNamesBuf +
2663 reparse_buf->TargetNameOffset),
2664 name_len, nls_codepage);
2665 } else { /* ASCII names */
2666 strncpy(symlinkinfo,
2667 reparse_buf->LinkNamesBuf +
2668 reparse_buf->TargetNameOffset,
2669 min_t(const int, buflen,
2670 reparse_buf->TargetNameLen));
2674 cFYI(1, ("Invalid return data count on "
2675 "get reparse info ioctl"));
2677 symlinkinfo[buflen] = 0; /* just in case so the caller
2678 does not go off the end of the buffer */
2679 cFYI(1, ("readlink result - %s", symlinkinfo));
2683 cifs_buf_release(pSMB);
2685 /* Note: On -EAGAIN error only caller can retry on handle based calls
2686 since file handle passed in no longer valid */
2691 #ifdef CONFIG_CIFS_POSIX
2693 /*Convert an Access Control Entry from wire format to local POSIX xattr format*/
2694 static void cifs_convert_ace(posix_acl_xattr_entry *ace,
2695 struct cifs_posix_ace *cifs_ace)
2697 /* u8 cifs fields do not need le conversion */
2698 ace->e_perm = cpu_to_le16(cifs_ace->cifs_e_perm);
2699 ace->e_tag = cpu_to_le16(cifs_ace->cifs_e_tag);
2700 ace->e_id = cpu_to_le32(le64_to_cpu(cifs_ace->cifs_uid));
2701 /* cFYI(1,("perm %d tag %d id %d",ace->e_perm,ace->e_tag,ace->e_id)); */
2706 /* Convert ACL from CIFS POSIX wire format to local Linux POSIX ACL xattr */
2707 static int cifs_copy_posix_acl(char *trgt, char *src, const int buflen,
2708 const int acl_type, const int size_of_data_area)
2713 struct cifs_posix_ace *pACE;
2714 struct cifs_posix_acl *cifs_acl = (struct cifs_posix_acl *)src;
2715 posix_acl_xattr_header *local_acl = (posix_acl_xattr_header *)trgt;
2717 if (le16_to_cpu(cifs_acl->version) != CIFS_ACL_VERSION)
2720 if (acl_type & ACL_TYPE_ACCESS) {
2721 count = le16_to_cpu(cifs_acl->access_entry_count);
2722 pACE = &cifs_acl->ace_array[0];
2723 size = sizeof(struct cifs_posix_acl);
2724 size += sizeof(struct cifs_posix_ace) * count;
2725 /* check if we would go beyond end of SMB */
2726 if (size_of_data_area < size) {
2727 cFYI(1, ("bad CIFS POSIX ACL size %d vs. %d",
2728 size_of_data_area, size));
2731 } else if (acl_type & ACL_TYPE_DEFAULT) {
2732 count = le16_to_cpu(cifs_acl->access_entry_count);
2733 size = sizeof(struct cifs_posix_acl);
2734 size += sizeof(struct cifs_posix_ace) * count;
2735 /* skip past access ACEs to get to default ACEs */
2736 pACE = &cifs_acl->ace_array[count];
2737 count = le16_to_cpu(cifs_acl->default_entry_count);
2738 size += sizeof(struct cifs_posix_ace) * count;
2739 /* check if we would go beyond end of SMB */
2740 if (size_of_data_area < size)
2747 size = posix_acl_xattr_size(count);
2748 if ((buflen == 0) || (local_acl == NULL)) {
2749 /* used to query ACL EA size */
2750 } else if (size > buflen) {
2752 } else /* buffer big enough */ {
2753 local_acl->a_version = cpu_to_le32(POSIX_ACL_XATTR_VERSION);
2754 for (i = 0; i < count ; i++) {
2755 cifs_convert_ace(&local_acl->a_entries[i], pACE);
2762 static __u16 convert_ace_to_cifs_ace(struct cifs_posix_ace *cifs_ace,
2763 const posix_acl_xattr_entry *local_ace)
2765 __u16 rc = 0; /* 0 = ACL converted ok */
2767 cifs_ace->cifs_e_perm = le16_to_cpu(local_ace->e_perm);
2768 cifs_ace->cifs_e_tag = le16_to_cpu(local_ace->e_tag);
2769 /* BB is there a better way to handle the large uid? */
2770 if (local_ace->e_id == cpu_to_le32(-1)) {
2771 /* Probably no need to le convert -1 on any arch but can not hurt */
2772 cifs_ace->cifs_uid = cpu_to_le64(-1);
2774 cifs_ace->cifs_uid = cpu_to_le64(le32_to_cpu(local_ace->e_id));
2775 /*cFYI(1,("perm %d tag %d id %d",ace->e_perm,ace->e_tag,ace->e_id));*/
2779 /* Convert ACL from local Linux POSIX xattr to CIFS POSIX ACL wire format */
2780 static __u16 ACL_to_cifs_posix(char *parm_data, const char *pACL,
2781 const int buflen, const int acl_type)
2784 struct cifs_posix_acl *cifs_acl = (struct cifs_posix_acl *)parm_data;
2785 posix_acl_xattr_header *local_acl = (posix_acl_xattr_header *)pACL;
2789 if ((buflen == 0) || (pACL == NULL) || (cifs_acl == NULL))
2792 count = posix_acl_xattr_count((size_t)buflen);
2793 cFYI(1, ("setting acl with %d entries from buf of length %d and "
2795 count, buflen, le32_to_cpu(local_acl->a_version)));
2796 if (le32_to_cpu(local_acl->a_version) != 2) {
2797 cFYI(1, ("unknown POSIX ACL version %d",
2798 le32_to_cpu(local_acl->a_version)));
2801 cifs_acl->version = cpu_to_le16(1);
2802 if (acl_type == ACL_TYPE_ACCESS)
2803 cifs_acl->access_entry_count = cpu_to_le16(count);
2804 else if (acl_type == ACL_TYPE_DEFAULT)
2805 cifs_acl->default_entry_count = cpu_to_le16(count);
2807 cFYI(1, ("unknown ACL type %d", acl_type));
2810 for (i = 0; i < count; i++) {
2811 rc = convert_ace_to_cifs_ace(&cifs_acl->ace_array[i],
2812 &local_acl->a_entries[i]);
2814 /* ACE not converted */
2819 rc = (__u16)(count * sizeof(struct cifs_posix_ace));
2820 rc += sizeof(struct cifs_posix_acl);
2821 /* BB add check to make sure ACL does not overflow SMB */
2827 CIFSSMBGetPosixACL(const int xid, struct cifsTconInfo *tcon,
2828 const unsigned char *searchName,
2829 char *acl_inf, const int buflen, const int acl_type,
2830 const struct nls_table *nls_codepage, int remap)
2832 /* SMB_QUERY_POSIX_ACL */
2833 TRANSACTION2_QPI_REQ *pSMB = NULL;
2834 TRANSACTION2_QPI_RSP *pSMBr = NULL;
2838 __u16 params, byte_count;
2840 cFYI(1, ("In GetPosixACL (Unix) for path %s", searchName));
2843 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2848 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2850 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
2851 PATH_MAX, nls_codepage, remap);
2852 name_len++; /* trailing null */
2854 pSMB->FileName[name_len] = 0;
2855 pSMB->FileName[name_len+1] = 0;
2856 } else { /* BB improve the check for buffer overruns BB */
2857 name_len = strnlen(searchName, PATH_MAX);
2858 name_len++; /* trailing null */
2859 strncpy(pSMB->FileName, searchName, name_len);
2862 params = 2 /* level */ + 4 /* rsrvd */ + name_len /* incl null */ ;
2863 pSMB->TotalDataCount = 0;
2864 pSMB->MaxParameterCount = cpu_to_le16(2);
2865 /* BB find exact max data count below from sess structure BB */
2866 pSMB->MaxDataCount = cpu_to_le16(4000);
2867 pSMB->MaxSetupCount = 0;
2871 pSMB->Reserved2 = 0;
2872 pSMB->ParameterOffset = cpu_to_le16(
2873 offsetof(struct smb_com_transaction2_qpi_req,
2874 InformationLevel) - 4);
2875 pSMB->DataCount = 0;
2876 pSMB->DataOffset = 0;
2877 pSMB->SetupCount = 1;
2878 pSMB->Reserved3 = 0;
2879 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
2880 byte_count = params + 1 /* pad */ ;
2881 pSMB->TotalParameterCount = cpu_to_le16(params);
2882 pSMB->ParameterCount = pSMB->TotalParameterCount;
2883 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_POSIX_ACL);
2884 pSMB->Reserved4 = 0;
2885 pSMB->hdr.smb_buf_length += byte_count;
2886 pSMB->ByteCount = cpu_to_le16(byte_count);
2888 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2889 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2890 cifs_stats_inc(&tcon->num_acl_get);
2892 cFYI(1, ("Send error in Query POSIX ACL = %d", rc));
2894 /* decode response */
2896 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
2897 if (rc || (pSMBr->ByteCount < 2))
2898 /* BB also check enough total bytes returned */
2899 rc = -EIO; /* bad smb */
2901 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
2902 __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
2903 rc = cifs_copy_posix_acl(acl_inf,
2904 (char *)&pSMBr->hdr.Protocol+data_offset,
2905 buflen, acl_type, count);
2908 cifs_buf_release(pSMB);
2915 CIFSSMBSetPosixACL(const int xid, struct cifsTconInfo *tcon,
2916 const unsigned char *fileName,
2917 const char *local_acl, const int buflen,
2919 const struct nls_table *nls_codepage, int remap)
2921 struct smb_com_transaction2_spi_req *pSMB = NULL;
2922 struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
2926 int bytes_returned = 0;
2927 __u16 params, byte_count, data_count, param_offset, offset;
2929 cFYI(1, ("In SetPosixACL (Unix) for path %s", fileName));
2931 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2935 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2937 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
2938 PATH_MAX, nls_codepage, remap);
2939 name_len++; /* trailing null */
2941 } else { /* BB improve the check for buffer overruns BB */
2942 name_len = strnlen(fileName, PATH_MAX);
2943 name_len++; /* trailing null */
2944 strncpy(pSMB->FileName, fileName, name_len);
2946 params = 6 + name_len;
2947 pSMB->MaxParameterCount = cpu_to_le16(2);
2948 /* BB find max SMB size from sess */
2949 pSMB->MaxDataCount = cpu_to_le16(1000);
2950 pSMB->MaxSetupCount = 0;
2954 pSMB->Reserved2 = 0;
2955 param_offset = offsetof(struct smb_com_transaction2_spi_req,
2956 InformationLevel) - 4;
2957 offset = param_offset + params;
2958 parm_data = ((char *) &pSMB->hdr.Protocol) + offset;
2959 pSMB->ParameterOffset = cpu_to_le16(param_offset);
2961 /* convert to on the wire format for POSIX ACL */
2962 data_count = ACL_to_cifs_posix(parm_data, local_acl, buflen, acl_type);
2964 if (data_count == 0) {
2966 goto setACLerrorExit;
2968 pSMB->DataOffset = cpu_to_le16(offset);
2969 pSMB->SetupCount = 1;
2970 pSMB->Reserved3 = 0;
2971 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
2972 pSMB->InformationLevel = cpu_to_le16(SMB_SET_POSIX_ACL);
2973 byte_count = 3 /* pad */ + params + data_count;
2974 pSMB->DataCount = cpu_to_le16(data_count);
2975 pSMB->TotalDataCount = pSMB->DataCount;
2976 pSMB->ParameterCount = cpu_to_le16(params);
2977 pSMB->TotalParameterCount = pSMB->ParameterCount;
2978 pSMB->Reserved4 = 0;
2979 pSMB->hdr.smb_buf_length += byte_count;
2980 pSMB->ByteCount = cpu_to_le16(byte_count);
2981 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2982 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2984 cFYI(1, ("Set POSIX ACL returned %d", rc));
2987 cifs_buf_release(pSMB);
2993 /* BB fix tabs in this function FIXME BB */
2995 CIFSGetExtAttr(const int xid, struct cifsTconInfo *tcon,
2996 const int netfid, __u64 *pExtAttrBits, __u64 *pMask)
2999 struct smb_t2_qfi_req *pSMB = NULL;
3000 struct smb_t2_qfi_rsp *pSMBr = NULL;
3002 __u16 params, byte_count;
3004 cFYI(1, ("In GetExtAttr"));
3009 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3014 params = 2 /* level */ + 2 /* fid */;
3015 pSMB->t2.TotalDataCount = 0;
3016 pSMB->t2.MaxParameterCount = cpu_to_le16(4);
3017 /* BB find exact max data count below from sess structure BB */
3018 pSMB->t2.MaxDataCount = cpu_to_le16(4000);
3019 pSMB->t2.MaxSetupCount = 0;
3020 pSMB->t2.Reserved = 0;
3022 pSMB->t2.Timeout = 0;
3023 pSMB->t2.Reserved2 = 0;
3024 pSMB->t2.ParameterOffset = cpu_to_le16(offsetof(struct smb_t2_qfi_req,
3026 pSMB->t2.DataCount = 0;
3027 pSMB->t2.DataOffset = 0;
3028 pSMB->t2.SetupCount = 1;
3029 pSMB->t2.Reserved3 = 0;
3030 pSMB->t2.SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION);
3031 byte_count = params + 1 /* pad */ ;
3032 pSMB->t2.TotalParameterCount = cpu_to_le16(params);
3033 pSMB->t2.ParameterCount = pSMB->t2.TotalParameterCount;
3034 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_ATTR_FLAGS);
3037 pSMB->hdr.smb_buf_length += byte_count;
3038 pSMB->t2.ByteCount = cpu_to_le16(byte_count);
3040 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3041 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3043 cFYI(1, ("error %d in GetExtAttr", rc));
3045 /* decode response */
3046 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3047 if (rc || (pSMBr->ByteCount < 2))
3048 /* BB also check enough total bytes returned */
3049 /* If rc should we check for EOPNOSUPP and
3050 disable the srvino flag? or in caller? */
3051 rc = -EIO; /* bad smb */
3053 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3054 __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
3055 struct file_chattr_info *pfinfo;
3056 /* BB Do we need a cast or hash here ? */
3058 cFYI(1, ("Illegal size ret in GetExtAttr"));
3062 pfinfo = (struct file_chattr_info *)
3063 (data_offset + (char *) &pSMBr->hdr.Protocol);
3064 *pExtAttrBits = le64_to_cpu(pfinfo->mode);
3065 *pMask = le64_to_cpu(pfinfo->mask);
3069 cifs_buf_release(pSMB);
3071 goto GetExtAttrRetry;
3075 #endif /* CONFIG_POSIX */
3077 #ifdef CONFIG_CIFS_EXPERIMENTAL
3078 /* Get Security Descriptor (by handle) from remote server for a file or dir */
3080 CIFSSMBGetCIFSACL(const int xid, struct cifsTconInfo *tcon, __u16 fid,
3081 struct cifs_ntsd **acl_inf, __u32 *pbuflen)
3085 QUERY_SEC_DESC_REQ *pSMB;
3088 cFYI(1, ("GetCifsACL"));
3093 rc = smb_init_nttransact(NT_TRANSACT_QUERY_SECURITY_DESC, 0,
3094 8 /* parm len */, tcon, (void **) &pSMB);
3098 pSMB->MaxParameterCount = cpu_to_le32(4);
3099 /* BB TEST with big acls that might need to be e.g. larger than 16K */
3100 pSMB->MaxSetupCount = 0;
3101 pSMB->Fid = fid; /* file handle always le */
3102 pSMB->AclFlags = cpu_to_le32(CIFS_ACL_OWNER | CIFS_ACL_GROUP |
3104 pSMB->ByteCount = cpu_to_le16(11); /* 3 bytes pad + 8 bytes parm */
3105 pSMB->hdr.smb_buf_length += 11;
3106 iov[0].iov_base = (char *)pSMB;
3107 iov[0].iov_len = pSMB->hdr.smb_buf_length + 4;
3109 rc = SendReceive2(xid, tcon->ses, iov, 1 /* num iovec */, &buf_type,
3111 cifs_stats_inc(&tcon->num_acl_get);
3113 cFYI(1, ("Send error in QuerySecDesc = %d", rc));
3114 } else { /* decode response */
3118 struct smb_com_ntransact_rsp *pSMBr;
3121 /* validate_nttransact */
3122 rc = validate_ntransact(iov[0].iov_base, (char **)&parm,
3123 &pdata, &parm_len, pbuflen);
3126 pSMBr = (struct smb_com_ntransact_rsp *)iov[0].iov_base;
3128 cFYI(1, ("smb %p parm %p data %p", pSMBr, parm, *acl_inf));
3130 if (le32_to_cpu(pSMBr->ParameterCount) != 4) {
3131 rc = -EIO; /* bad smb */
3136 /* BB check that data area is minimum length and as big as acl_len */
3138 acl_len = le32_to_cpu(*parm);
3139 if (acl_len != *pbuflen) {
3140 cERROR(1, ("acl length %d does not match %d",
3141 acl_len, *pbuflen));
3142 if (*pbuflen > acl_len)
3146 /* check if buffer is big enough for the acl
3147 header followed by the smallest SID */
3148 if ((*pbuflen < sizeof(struct cifs_ntsd) + 8) ||
3149 (*pbuflen >= 64 * 1024)) {
3150 cERROR(1, ("bad acl length %d", *pbuflen));
3154 *acl_inf = kmalloc(*pbuflen, GFP_KERNEL);
3155 if (*acl_inf == NULL) {
3159 memcpy(*acl_inf, pdata, *pbuflen);
3163 if (buf_type == CIFS_SMALL_BUFFER)
3164 cifs_small_buf_release(iov[0].iov_base);
3165 else if (buf_type == CIFS_LARGE_BUFFER)
3166 cifs_buf_release(iov[0].iov_base);
3167 /* cifs_small_buf_release(pSMB); */ /* Freed earlier now in SendReceive2 */
3172 CIFSSMBSetCIFSACL(const int xid, struct cifsTconInfo *tcon, __u16 fid,
3173 struct cifs_ntsd *pntsd, __u32 acllen)
3175 __u16 byte_count, param_count, data_count, param_offset, data_offset;
3177 int bytes_returned = 0;
3178 SET_SEC_DESC_REQ *pSMB = NULL;
3179 NTRANSACT_RSP *pSMBr = NULL;
3182 rc = smb_init(SMB_COM_NT_TRANSACT, 19, tcon, (void **) &pSMB,
3187 pSMB->MaxSetupCount = 0;
3191 param_offset = offsetof(struct smb_com_transaction_ssec_req, Fid) - 4;
3192 data_count = acllen;
3193 data_offset = param_offset + param_count;
3194 byte_count = 3 /* pad */ + param_count;
3196 pSMB->DataCount = cpu_to_le32(data_count);
3197 pSMB->TotalDataCount = pSMB->DataCount;
3198 pSMB->MaxParameterCount = cpu_to_le32(4);
3199 pSMB->MaxDataCount = cpu_to_le32(16384);
3200 pSMB->ParameterCount = cpu_to_le32(param_count);
3201 pSMB->ParameterOffset = cpu_to_le32(param_offset);
3202 pSMB->TotalParameterCount = pSMB->ParameterCount;
3203 pSMB->DataOffset = cpu_to_le32(data_offset);
3204 pSMB->SetupCount = 0;
3205 pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_SET_SECURITY_DESC);
3206 pSMB->ByteCount = cpu_to_le16(byte_count+data_count);
3208 pSMB->Fid = fid; /* file handle always le */
3209 pSMB->Reserved2 = 0;
3210 pSMB->AclFlags = cpu_to_le32(CIFS_ACL_DACL);
3212 if (pntsd && acllen) {
3213 memcpy((char *) &pSMBr->hdr.Protocol + data_offset,
3216 pSMB->hdr.smb_buf_length += (byte_count + data_count);
3219 pSMB->hdr.smb_buf_length += byte_count;
3221 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3222 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3224 cFYI(1, ("SetCIFSACL bytes_returned: %d, rc: %d", bytes_returned, rc));
3226 cFYI(1, ("Set CIFS ACL returned %d", rc));
3227 cifs_buf_release(pSMB);
3230 goto setCifsAclRetry;
3235 #endif /* CONFIG_CIFS_EXPERIMENTAL */
3237 /* Legacy Query Path Information call for lookup to old servers such
3239 int SMBQueryInformation(const int xid, struct cifsTconInfo *tcon,
3240 const unsigned char *searchName,
3241 FILE_ALL_INFO *pFinfo,
3242 const struct nls_table *nls_codepage, int remap)
3244 QUERY_INFORMATION_REQ *pSMB;
3245 QUERY_INFORMATION_RSP *pSMBr;
3250 cFYI(1, ("In SMBQPath path %s", searchName));
3252 rc = smb_init(SMB_COM_QUERY_INFORMATION, 0, tcon, (void **) &pSMB,
3257 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3259 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
3260 PATH_MAX, nls_codepage, remap);
3261 name_len++; /* trailing null */
3264 name_len = strnlen(searchName, PATH_MAX);
3265 name_len++; /* trailing null */
3266 strncpy(pSMB->FileName, searchName, name_len);
3268 pSMB->BufferFormat = 0x04;
3269 name_len++; /* account for buffer type byte */
3270 pSMB->hdr.smb_buf_length += (__u16) name_len;
3271 pSMB->ByteCount = cpu_to_le16(name_len);
3273 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3274 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3276 cFYI(1, ("Send error in QueryInfo = %d", rc));
3277 } else if (pFinfo) {
3279 __u32 time = le32_to_cpu(pSMBr->last_write_time);
3281 /* decode response */
3282 /* BB FIXME - add time zone adjustment BB */
3283 memset(pFinfo, 0, sizeof(FILE_ALL_INFO));
3286 /* decode time fields */
3287 pFinfo->ChangeTime = cpu_to_le64(cifs_UnixTimeToNT(ts));
3288 pFinfo->LastWriteTime = pFinfo->ChangeTime;
3289 pFinfo->LastAccessTime = 0;
3290 pFinfo->AllocationSize =
3291 cpu_to_le64(le32_to_cpu(pSMBr->size));
3292 pFinfo->EndOfFile = pFinfo->AllocationSize;
3293 pFinfo->Attributes =
3294 cpu_to_le32(le16_to_cpu(pSMBr->attr));
3296 rc = -EIO; /* bad buffer passed in */
3298 cifs_buf_release(pSMB);
3310 CIFSSMBQPathInfo(const int xid, struct cifsTconInfo *tcon,
3311 const unsigned char *searchName,
3312 FILE_ALL_INFO *pFindData,
3313 int legacy /* old style infolevel */,
3314 const struct nls_table *nls_codepage, int remap)
3316 /* level 263 SMB_QUERY_FILE_ALL_INFO */
3317 TRANSACTION2_QPI_REQ *pSMB = NULL;
3318 TRANSACTION2_QPI_RSP *pSMBr = NULL;
3322 __u16 params, byte_count;
3324 /* cFYI(1, ("In QPathInfo path %s", searchName)); */
3326 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3331 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3333 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
3334 PATH_MAX, nls_codepage, remap);
3335 name_len++; /* trailing null */
3337 } else { /* BB improve the check for buffer overruns BB */
3338 name_len = strnlen(searchName, PATH_MAX);
3339 name_len++; /* trailing null */
3340 strncpy(pSMB->FileName, searchName, name_len);
3343 params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */;
3344 pSMB->TotalDataCount = 0;
3345 pSMB->MaxParameterCount = cpu_to_le16(2);
3346 /* BB find exact max SMB PDU from sess structure BB */
3347 pSMB->MaxDataCount = cpu_to_le16(4000);
3348 pSMB->MaxSetupCount = 0;
3352 pSMB->Reserved2 = 0;
3353 pSMB->ParameterOffset = cpu_to_le16(offsetof(
3354 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
3355 pSMB->DataCount = 0;
3356 pSMB->DataOffset = 0;
3357 pSMB->SetupCount = 1;
3358 pSMB->Reserved3 = 0;
3359 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
3360 byte_count = params + 1 /* pad */ ;
3361 pSMB->TotalParameterCount = cpu_to_le16(params);
3362 pSMB->ParameterCount = pSMB->TotalParameterCount;
3364 pSMB->InformationLevel = cpu_to_le16(SMB_INFO_STANDARD);
3366 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_ALL_INFO);
3367 pSMB->Reserved4 = 0;
3368 pSMB->hdr.smb_buf_length += byte_count;
3369 pSMB->ByteCount = cpu_to_le16(byte_count);
3371 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3372 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3374 cFYI(1, ("Send error in QPathInfo = %d", rc));
3375 } else { /* decode response */
3376 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3378 if (rc) /* BB add auto retry on EOPNOTSUPP? */
3380 else if (!legacy && (pSMBr->ByteCount < 40))
3381 rc = -EIO; /* bad smb */
3382 else if (legacy && (pSMBr->ByteCount < 24))
3383 rc = -EIO; /* 24 or 26 expected but we do not read
3385 else if (pFindData) {
3387 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3389 /* On legacy responses we do not read the last field,
3390 EAsize, fortunately since it varies by subdialect and
3391 also note it differs on Set vs. Get, ie two bytes or 4
3392 bytes depending but we don't care here */
3394 size = sizeof(FILE_INFO_STANDARD);
3396 size = sizeof(FILE_ALL_INFO);
3397 memcpy((char *) pFindData,
3398 (char *) &pSMBr->hdr.Protocol +
3403 cifs_buf_release(pSMB);
3405 goto QPathInfoRetry;
3411 CIFSSMBUnixQPathInfo(const int xid, struct cifsTconInfo *tcon,
3412 const unsigned char *searchName,
3413 FILE_UNIX_BASIC_INFO *pFindData,
3414 const struct nls_table *nls_codepage, int remap)
3416 /* SMB_QUERY_FILE_UNIX_BASIC */
3417 TRANSACTION2_QPI_REQ *pSMB = NULL;
3418 TRANSACTION2_QPI_RSP *pSMBr = NULL;
3420 int bytes_returned = 0;
3422 __u16 params, byte_count;
3424 cFYI(1, ("In QPathInfo (Unix) the path %s", searchName));
3426 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3431 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3433 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
3434 PATH_MAX, nls_codepage, remap);
3435 name_len++; /* trailing null */
3437 } else { /* BB improve the check for buffer overruns BB */
3438 name_len = strnlen(searchName, PATH_MAX);
3439 name_len++; /* trailing null */
3440 strncpy(pSMB->FileName, searchName, name_len);
3443 params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */;
3444 pSMB->TotalDataCount = 0;
3445 pSMB->MaxParameterCount = cpu_to_le16(2);
3446 /* BB find exact max SMB PDU from sess structure BB */
3447 pSMB->MaxDataCount = cpu_to_le16(4000);
3448 pSMB->MaxSetupCount = 0;
3452 pSMB->Reserved2 = 0;
3453 pSMB->ParameterOffset = cpu_to_le16(offsetof(
3454 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
3455 pSMB->DataCount = 0;
3456 pSMB->DataOffset = 0;
3457 pSMB->SetupCount = 1;
3458 pSMB->Reserved3 = 0;
3459 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
3460 byte_count = params + 1 /* pad */ ;
3461 pSMB->TotalParameterCount = cpu_to_le16(params);
3462 pSMB->ParameterCount = pSMB->TotalParameterCount;
3463 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC);
3464 pSMB->Reserved4 = 0;
3465 pSMB->hdr.smb_buf_length += byte_count;
3466 pSMB->ByteCount = cpu_to_le16(byte_count);
3468 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3469 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3471 cFYI(1, ("Send error in QPathInfo = %d", rc));
3472 } else { /* decode response */
3473 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3475 if (rc || (pSMBr->ByteCount < sizeof(FILE_UNIX_BASIC_INFO))) {
3476 cERROR(1, ("Malformed FILE_UNIX_BASIC_INFO response.\n"
3477 "Unix Extensions can be disabled on mount "
3478 "by specifying the nosfu mount option."));
3479 rc = -EIO; /* bad smb */
3481 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3482 memcpy((char *) pFindData,
3483 (char *) &pSMBr->hdr.Protocol +
3485 sizeof(FILE_UNIX_BASIC_INFO));
3488 cifs_buf_release(pSMB);
3490 goto UnixQPathInfoRetry;
3495 /* xid, tcon, searchName and codepage are input parms, rest are returned */
3497 CIFSFindFirst(const int xid, struct cifsTconInfo *tcon,
3498 const char *searchName,
3499 const struct nls_table *nls_codepage,
3501 struct cifs_search_info *psrch_inf, int remap, const char dirsep)
3503 /* level 257 SMB_ */
3504 TRANSACTION2_FFIRST_REQ *pSMB = NULL;
3505 TRANSACTION2_FFIRST_RSP *pSMBr = NULL;
3506 T2_FFIRST_RSP_PARMS *parms;
3508 int bytes_returned = 0;
3510 __u16 params, byte_count;
3512 cFYI(1, ("In FindFirst for %s", searchName));
3515 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3520 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3522 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
3523 PATH_MAX, nls_codepage, remap);
3524 /* We can not add the asterik earlier in case
3525 it got remapped to 0xF03A as if it were part of the
3526 directory name instead of a wildcard */
3528 pSMB->FileName[name_len] = dirsep;
3529 pSMB->FileName[name_len+1] = 0;
3530 pSMB->FileName[name_len+2] = '*';
3531 pSMB->FileName[name_len+3] = 0;
3532 name_len += 4; /* now the trailing null */
3533 pSMB->FileName[name_len] = 0; /* null terminate just in case */
3534 pSMB->FileName[name_len+1] = 0;
3536 } else { /* BB add check for overrun of SMB buf BB */
3537 name_len = strnlen(searchName, PATH_MAX);
3538 /* BB fix here and in unicode clause above ie
3539 if (name_len > buffersize-header)
3540 free buffer exit; BB */
3541 strncpy(pSMB->FileName, searchName, name_len);
3542 pSMB->FileName[name_len] = dirsep;
3543 pSMB->FileName[name_len+1] = '*';
3544 pSMB->FileName[name_len+2] = 0;
3548 params = 12 + name_len /* includes null */ ;
3549 pSMB->TotalDataCount = 0; /* no EAs */
3550 pSMB->MaxParameterCount = cpu_to_le16(10);
3551 pSMB->MaxDataCount = cpu_to_le16((tcon->ses->server->maxBuf -
3552 MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
3553 pSMB->MaxSetupCount = 0;
3557 pSMB->Reserved2 = 0;
3558 byte_count = params + 1 /* pad */ ;
3559 pSMB->TotalParameterCount = cpu_to_le16(params);
3560 pSMB->ParameterCount = pSMB->TotalParameterCount;
3561 pSMB->ParameterOffset = cpu_to_le16(
3562 offsetof(struct smb_com_transaction2_ffirst_req, SearchAttributes)
3564 pSMB->DataCount = 0;
3565 pSMB->DataOffset = 0;
3566 pSMB->SetupCount = 1; /* one byte, no need to make endian neutral */
3567 pSMB->Reserved3 = 0;
3568 pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_FIRST);
3569 pSMB->SearchAttributes =
3570 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
3572 pSMB->SearchCount = cpu_to_le16(CIFSMaxBufSize/sizeof(FILE_UNIX_INFO));
3573 pSMB->SearchFlags = cpu_to_le16(CIFS_SEARCH_CLOSE_AT_END |
3574 CIFS_SEARCH_RETURN_RESUME);
3575 pSMB->InformationLevel = cpu_to_le16(psrch_inf->info_level);
3577 /* BB what should we set StorageType to? Does it matter? BB */
3578 pSMB->SearchStorageType = 0;
3579 pSMB->hdr.smb_buf_length += byte_count;
3580 pSMB->ByteCount = cpu_to_le16(byte_count);
3582 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3583 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3584 cifs_stats_inc(&tcon->num_ffirst);
3586 if (rc) {/* BB add logic to retry regular search if Unix search
3587 rejected unexpectedly by server */
3588 /* BB Add code to handle unsupported level rc */
3589 cFYI(1, ("Error in FindFirst = %d", rc));
3591 cifs_buf_release(pSMB);
3593 /* BB eventually could optimize out free and realloc of buf */
3596 goto findFirstRetry;
3597 } else { /* decode response */
3598 /* BB remember to free buffer if error BB */
3599 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3603 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
3604 psrch_inf->unicode = true;
3606 psrch_inf->unicode = false;
3608 psrch_inf->ntwrk_buf_start = (char *)pSMBr;
3609 psrch_inf->smallBuf = 0;
3610 psrch_inf->srch_entries_start =
3611 (char *) &pSMBr->hdr.Protocol +
3612 le16_to_cpu(pSMBr->t2.DataOffset);
3613 parms = (T2_FFIRST_RSP_PARMS *)((char *) &pSMBr->hdr.Protocol +
3614 le16_to_cpu(pSMBr->t2.ParameterOffset));
3616 if (parms->EndofSearch)
3617 psrch_inf->endOfSearch = true;
3619 psrch_inf->endOfSearch = false;
3621 psrch_inf->entries_in_buffer =
3622 le16_to_cpu(parms->SearchCount);
3623 psrch_inf->index_of_last_entry = 2 /* skip . and .. */ +
3624 psrch_inf->entries_in_buffer;
3625 lnoff = le16_to_cpu(parms->LastNameOffset);
3626 if (tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE <
3628 cERROR(1, ("ignoring corrupt resume name"));
3629 psrch_inf->last_entry = NULL;
3633 psrch_inf->last_entry = psrch_inf->srch_entries_start +
3636 *pnetfid = parms->SearchHandle;
3638 cifs_buf_release(pSMB);
3645 int CIFSFindNext(const int xid, struct cifsTconInfo *tcon,
3646 __u16 searchHandle, struct cifs_search_info *psrch_inf)
3648 TRANSACTION2_FNEXT_REQ *pSMB = NULL;
3649 TRANSACTION2_FNEXT_RSP *pSMBr = NULL;
3650 T2_FNEXT_RSP_PARMS *parms;
3651 char *response_data;
3653 int bytes_returned, name_len;
3654 __u16 params, byte_count;
3656 cFYI(1, ("In FindNext"));
3658 if (psrch_inf->endOfSearch)
3661 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3666 params = 14; /* includes 2 bytes of null string, converted to LE below*/
3668 pSMB->TotalDataCount = 0; /* no EAs */
3669 pSMB->MaxParameterCount = cpu_to_le16(8);
3670 pSMB->MaxDataCount =
3671 cpu_to_le16((tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE) &
3673 pSMB->MaxSetupCount = 0;
3677 pSMB->Reserved2 = 0;
3678 pSMB->ParameterOffset = cpu_to_le16(
3679 offsetof(struct smb_com_transaction2_fnext_req,SearchHandle) - 4);
3680 pSMB->DataCount = 0;
3681 pSMB->DataOffset = 0;
3682 pSMB->SetupCount = 1;
3683 pSMB->Reserved3 = 0;
3684 pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_NEXT);
3685 pSMB->SearchHandle = searchHandle; /* always kept as le */
3687 cpu_to_le16(CIFSMaxBufSize / sizeof(FILE_UNIX_INFO));
3688 pSMB->InformationLevel = cpu_to_le16(psrch_inf->info_level);
3689 pSMB->ResumeKey = psrch_inf->resume_key;
3691 cpu_to_le16(CIFS_SEARCH_CLOSE_AT_END | CIFS_SEARCH_RETURN_RESUME);
3693 name_len = psrch_inf->resume_name_len;
3695 if (name_len < PATH_MAX) {
3696 memcpy(pSMB->ResumeFileName, psrch_inf->presume_name, name_len);
3697 byte_count += name_len;
3698 /* 14 byte parm len above enough for 2 byte null terminator */
3699 pSMB->ResumeFileName[name_len] = 0;
3700 pSMB->ResumeFileName[name_len+1] = 0;
3703 goto FNext2_err_exit;
3705 byte_count = params + 1 /* pad */ ;
3706 pSMB->TotalParameterCount = cpu_to_le16(params);
3707 pSMB->ParameterCount = pSMB->TotalParameterCount;
3708 pSMB->hdr.smb_buf_length += byte_count;
3709 pSMB->ByteCount = cpu_to_le16(byte_count);
3711 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3712 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3713 cifs_stats_inc(&tcon->num_fnext);
3716 psrch_inf->endOfSearch = true;
3717 cifs_buf_release(pSMB);
3718 rc = 0; /* search probably was closed at end of search*/
3720 cFYI(1, ("FindNext returned = %d", rc));
3721 } else { /* decode response */
3722 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3727 /* BB fixme add lock for file (srch_info) struct here */
3728 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
3729 psrch_inf->unicode = true;
3731 psrch_inf->unicode = false;
3732 response_data = (char *) &pSMBr->hdr.Protocol +
3733 le16_to_cpu(pSMBr->t2.ParameterOffset);
3734 parms = (T2_FNEXT_RSP_PARMS *)response_data;
3735 response_data = (char *)&pSMBr->hdr.Protocol +
3736 le16_to_cpu(pSMBr->t2.DataOffset);
3737 if (psrch_inf->smallBuf)
3738 cifs_small_buf_release(
3739 psrch_inf->ntwrk_buf_start);
3741 cifs_buf_release(psrch_inf->ntwrk_buf_start);
3742 psrch_inf->srch_entries_start = response_data;
3743 psrch_inf->ntwrk_buf_start = (char *)pSMB;
3744 psrch_inf->smallBuf = 0;
3745 if (parms->EndofSearch)
3746 psrch_inf->endOfSearch = true;
3748 psrch_inf->endOfSearch = false;
3749 psrch_inf->entries_in_buffer =
3750 le16_to_cpu(parms->SearchCount);
3751 psrch_inf->index_of_last_entry +=
3752 psrch_inf->entries_in_buffer;
3753 lnoff = le16_to_cpu(parms->LastNameOffset);
3754 if (tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE <
3756 cERROR(1, ("ignoring corrupt resume name"));
3757 psrch_inf->last_entry = NULL;
3760 psrch_inf->last_entry =
3761 psrch_inf->srch_entries_start + lnoff;
3763 /* cFYI(1,("fnxt2 entries in buf %d index_of_last %d",
3764 psrch_inf->entries_in_buffer, psrch_inf->index_of_last_entry)); */
3766 /* BB fixme add unlock here */
3771 /* BB On error, should we leave previous search buf (and count and
3772 last entry fields) intact or free the previous one? */
3774 /* Note: On -EAGAIN error only caller can retry on handle based calls
3775 since file handle passed in no longer valid */
3778 cifs_buf_release(pSMB);
3783 CIFSFindClose(const int xid, struct cifsTconInfo *tcon,
3784 const __u16 searchHandle)
3787 FINDCLOSE_REQ *pSMB = NULL;
3789 cFYI(1, ("In CIFSSMBFindClose"));
3790 rc = small_smb_init(SMB_COM_FIND_CLOSE2, 1, tcon, (void **)&pSMB);
3792 /* no sense returning error if session restarted
3793 as file handle has been closed */
3799 pSMB->FileID = searchHandle;
3800 pSMB->ByteCount = 0;
3801 rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0);
3803 cERROR(1, ("Send error in FindClose = %d", rc));
3805 cifs_stats_inc(&tcon->num_fclose);
3807 /* Since session is dead, search handle closed on server already */
3815 CIFSGetSrvInodeNumber(const int xid, struct cifsTconInfo *tcon,
3816 const unsigned char *searchName,
3817 __u64 *inode_number,
3818 const struct nls_table *nls_codepage, int remap)
3821 TRANSACTION2_QPI_REQ *pSMB = NULL;
3822 TRANSACTION2_QPI_RSP *pSMBr = NULL;
3823 int name_len, bytes_returned;
3824 __u16 params, byte_count;
3826 cFYI(1, ("In GetSrvInodeNum for %s", searchName));
3830 GetInodeNumberRetry:
3831 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3836 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3838 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
3839 PATH_MAX, nls_codepage, remap);
3840 name_len++; /* trailing null */
3842 } else { /* BB improve the check for buffer overruns BB */
3843 name_len = strnlen(searchName, PATH_MAX);
3844 name_len++; /* trailing null */
3845 strncpy(pSMB->FileName, searchName, name_len);
3848 params = 2 /* level */ + 4 /* rsrvd */ + name_len /* incl null */ ;
3849 pSMB->TotalDataCount = 0;
3850 pSMB->MaxParameterCount = cpu_to_le16(2);
3851 /* BB find exact max data count below from sess structure BB */
3852 pSMB->MaxDataCount = cpu_to_le16(4000);
3853 pSMB->MaxSetupCount = 0;
3857 pSMB->Reserved2 = 0;
3858 pSMB->ParameterOffset = cpu_to_le16(offsetof(
3859 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
3860 pSMB->DataCount = 0;
3861 pSMB->DataOffset = 0;
3862 pSMB->SetupCount = 1;
3863 pSMB->Reserved3 = 0;
3864 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
3865 byte_count = params + 1 /* pad */ ;
3866 pSMB->TotalParameterCount = cpu_to_le16(params);
3867 pSMB->ParameterCount = pSMB->TotalParameterCount;
3868 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_INTERNAL_INFO);
3869 pSMB->Reserved4 = 0;
3870 pSMB->hdr.smb_buf_length += byte_count;
3871 pSMB->ByteCount = cpu_to_le16(byte_count);
3873 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3874 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3876 cFYI(1, ("error %d in QueryInternalInfo", rc));
3878 /* decode response */
3879 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3880 if (rc || (pSMBr->ByteCount < 2))
3881 /* BB also check enough total bytes returned */
3882 /* If rc should we check for EOPNOSUPP and
3883 disable the srvino flag? or in caller? */
3884 rc = -EIO; /* bad smb */
3886 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3887 __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
3888 struct file_internal_info *pfinfo;
3889 /* BB Do we need a cast or hash here ? */
3891 cFYI(1, ("Illegal size ret in QryIntrnlInf"));
3893 goto GetInodeNumOut;
3895 pfinfo = (struct file_internal_info *)
3896 (data_offset + (char *) &pSMBr->hdr.Protocol);
3897 *inode_number = pfinfo->UniqueId;
3901 cifs_buf_release(pSMB);
3903 goto GetInodeNumberRetry;
3907 /* computes length of UCS string converted to host codepage
3909 * @maxlen: length of the input string in UCS characters
3912 * return: size of input string in host codepage
3914 static int hostlen_fromUCS(const __le16 *src, const int maxlen,
3915 const struct nls_table *nls_codepage) {
3920 for (i = 0; (i < maxlen) && src[i]; ++i) {
3921 charlen = nls_codepage->uni2char(le16_to_cpu(src[i]),
3922 to, NLS_MAX_CHARSET_SIZE);
3923 hostlen += charlen > 0 ? charlen : 1;
3928 /* parses DFS refferal V3 structure
3929 * caller is responsible for freeing target_nodes
3932 * on failure - errno
3935 parse_DFS_referrals(TRANSACTION2_GET_DFS_REFER_RSP *pSMBr,
3936 unsigned int *num_of_nodes,
3937 struct dfs_info3_param **target_nodes,
3938 const struct nls_table *nls_codepage, int remap,
3939 const char *searchName)
3944 struct dfs_referral_level_3 *ref;
3946 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
3950 *num_of_nodes = le16_to_cpu(pSMBr->NumberOfReferrals);
3952 if (*num_of_nodes < 1) {
3953 cERROR(1, ("num_referrals: must be at least > 0,"
3954 "but we get num_referrals = %d\n", *num_of_nodes));
3956 goto parse_DFS_referrals_exit;
3959 ref = (struct dfs_referral_level_3 *) &(pSMBr->referrals);
3960 if (ref->VersionNumber != cpu_to_le16(3)) {
3961 cERROR(1, ("Referrals of V%d version are not supported,"
3962 "should be V3", le16_to_cpu(ref->VersionNumber)));
3964 goto parse_DFS_referrals_exit;
3967 /* get the upper boundary of the resp buffer */
3968 data_end = (char *)(&(pSMBr->PathConsumed)) +
3969 le16_to_cpu(pSMBr->t2.DataCount);
3971 cFYI(1, ("num_referrals: %d dfs flags: 0x%x ... \n",
3973 le16_to_cpu(pSMBr->DFSFlags)));
3975 *target_nodes = kzalloc(sizeof(struct dfs_info3_param) *
3976 *num_of_nodes, GFP_KERNEL);
3977 if (*target_nodes == NULL) {
3978 cERROR(1, ("Failed to allocate buffer for target_nodes\n"));
3980 goto parse_DFS_referrals_exit;
3983 /* collect neccessary data from referrals */
3984 for (i = 0; i < *num_of_nodes; i++) {
3987 struct dfs_info3_param *node = (*target_nodes)+i;
3989 node->flags = le16_to_cpu(pSMBr->DFSFlags);
3991 __le16 *tmp = kmalloc(strlen(searchName)*2 + 2,
3993 cifsConvertToUCS((__le16 *) tmp, searchName,
3994 PATH_MAX, nls_codepage, remap);
3995 node->path_consumed = hostlen_fromUCS(tmp,
3996 le16_to_cpu(pSMBr->PathConsumed)/2,
4000 node->path_consumed = le16_to_cpu(pSMBr->PathConsumed);
4002 node->server_type = le16_to_cpu(ref->ServerType);
4003 node->ref_flag = le16_to_cpu(ref->ReferralEntryFlags);
4006 temp = (char *)ref + le16_to_cpu(ref->DfsPathOffset);
4007 max_len = data_end - temp;
4008 rc = cifs_strncpy_to_host(&(node->path_name), temp,
4009 max_len, is_unicode, nls_codepage);
4011 goto parse_DFS_referrals_exit;
4013 /* copy link target UNC */
4014 temp = (char *)ref + le16_to_cpu(ref->NetworkAddressOffset);
4015 max_len = data_end - temp;
4016 rc = cifs_strncpy_to_host(&(node->node_name), temp,
4017 max_len, is_unicode, nls_codepage);
4019 goto parse_DFS_referrals_exit;
4021 ref += le16_to_cpu(ref->Size);
4024 parse_DFS_referrals_exit:
4026 free_dfs_info_array(*target_nodes, *num_of_nodes);
4027 *target_nodes = NULL;
4034 CIFSGetDFSRefer(const int xid, struct cifsSesInfo *ses,
4035 const unsigned char *searchName,
4036 struct dfs_info3_param **target_nodes,
4037 unsigned int *num_of_nodes,
4038 const struct nls_table *nls_codepage, int remap)
4040 /* TRANS2_GET_DFS_REFERRAL */
4041 TRANSACTION2_GET_DFS_REFER_REQ *pSMB = NULL;
4042 TRANSACTION2_GET_DFS_REFER_RSP *pSMBr = NULL;
4046 __u16 params, byte_count;
4048 *target_nodes = NULL;
4050 cFYI(1, ("In GetDFSRefer the path %s", searchName));
4054 rc = smb_init(SMB_COM_TRANSACTION2, 15, NULL, (void **) &pSMB,
4059 /* server pointer checked in called function,
4060 but should never be null here anyway */
4061 pSMB->hdr.Mid = GetNextMid(ses->server);
4062 pSMB->hdr.Tid = ses->ipc_tid;
4063 pSMB->hdr.Uid = ses->Suid;
4064 if (ses->capabilities & CAP_STATUS32)
4065 pSMB->hdr.Flags2 |= SMBFLG2_ERR_STATUS;
4066 if (ses->capabilities & CAP_DFS)
4067 pSMB->hdr.Flags2 |= SMBFLG2_DFS;
4069 if (ses->capabilities & CAP_UNICODE) {
4070 pSMB->hdr.Flags2 |= SMBFLG2_UNICODE;
4072 cifsConvertToUCS((__le16 *) pSMB->RequestFileName,
4073 searchName, PATH_MAX, nls_codepage, remap);
4074 name_len++; /* trailing null */
4076 } else { /* BB improve the check for buffer overruns BB */
4077 name_len = strnlen(searchName, PATH_MAX);
4078 name_len++; /* trailing null */
4079 strncpy(pSMB->RequestFileName, searchName, name_len);
4083 if (ses->server->secMode &
4084 (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
4085 pSMB->hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
4088 pSMB->hdr.Uid = ses->Suid;
4090 params = 2 /* level */ + name_len /*includes null */ ;
4091 pSMB->TotalDataCount = 0;
4092 pSMB->DataCount = 0;
4093 pSMB->DataOffset = 0;
4094 pSMB->MaxParameterCount = 0;
4095 /* BB find exact max SMB PDU from sess structure BB */
4096 pSMB->MaxDataCount = cpu_to_le16(4000);
4097 pSMB->MaxSetupCount = 0;
4101 pSMB->Reserved2 = 0;
4102 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4103 struct smb_com_transaction2_get_dfs_refer_req, MaxReferralLevel) - 4);
4104 pSMB->SetupCount = 1;
4105 pSMB->Reserved3 = 0;
4106 pSMB->SubCommand = cpu_to_le16(TRANS2_GET_DFS_REFERRAL);
4107 byte_count = params + 3 /* pad */ ;
4108 pSMB->ParameterCount = cpu_to_le16(params);
4109 pSMB->TotalParameterCount = pSMB->ParameterCount;
4110 pSMB->MaxReferralLevel = cpu_to_le16(3);
4111 pSMB->hdr.smb_buf_length += byte_count;
4112 pSMB->ByteCount = cpu_to_le16(byte_count);
4114 rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB,
4115 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4117 cFYI(1, ("Send error in GetDFSRefer = %d", rc));
4120 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4122 /* BB Also check if enough total bytes returned? */
4123 if (rc || (pSMBr->ByteCount < 17)) {
4124 rc = -EIO; /* bad smb */
4128 cFYI(1, ("Decoding GetDFSRefer response BCC: %d Offset %d",
4130 le16_to_cpu(pSMBr->t2.DataOffset)));
4132 /* parse returned result into more usable form */
4133 rc = parse_DFS_referrals(pSMBr, num_of_nodes,
4134 target_nodes, nls_codepage, remap,
4138 cifs_buf_release(pSMB);
4146 /* Query File System Info such as free space to old servers such as Win 9x */
4148 SMBOldQFSInfo(const int xid, struct cifsTconInfo *tcon, struct kstatfs *FSData)
4150 /* level 0x01 SMB_QUERY_FILE_SYSTEM_INFO */
4151 TRANSACTION2_QFSI_REQ *pSMB = NULL;
4152 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4153 FILE_SYSTEM_ALLOC_INFO *response_data;
4155 int bytes_returned = 0;
4156 __u16 params, byte_count;
4158 cFYI(1, ("OldQFSInfo"));
4160 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4165 params = 2; /* level */
4166 pSMB->TotalDataCount = 0;
4167 pSMB->MaxParameterCount = cpu_to_le16(2);
4168 pSMB->MaxDataCount = cpu_to_le16(1000);
4169 pSMB->MaxSetupCount = 0;
4173 pSMB->Reserved2 = 0;
4174 byte_count = params + 1 /* pad */ ;
4175 pSMB->TotalParameterCount = cpu_to_le16(params);
4176 pSMB->ParameterCount = pSMB->TotalParameterCount;
4177 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4178 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4179 pSMB->DataCount = 0;
4180 pSMB->DataOffset = 0;
4181 pSMB->SetupCount = 1;
4182 pSMB->Reserved3 = 0;
4183 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4184 pSMB->InformationLevel = cpu_to_le16(SMB_INFO_ALLOCATION);
4185 pSMB->hdr.smb_buf_length += byte_count;
4186 pSMB->ByteCount = cpu_to_le16(byte_count);
4188 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4189 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4191 cFYI(1, ("Send error in QFSInfo = %d", rc));
4192 } else { /* decode response */
4193 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4195 if (rc || (pSMBr->ByteCount < 18))
4196 rc = -EIO; /* bad smb */
4198 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4199 cFYI(1, ("qfsinf resp BCC: %d Offset %d",
4200 pSMBr->ByteCount, data_offset));
4202 response_data = (FILE_SYSTEM_ALLOC_INFO *)
4203 (((char *) &pSMBr->hdr.Protocol) + data_offset);
4205 le16_to_cpu(response_data->BytesPerSector) *
4206 le32_to_cpu(response_data->
4207 SectorsPerAllocationUnit);
4209 le32_to_cpu(response_data->TotalAllocationUnits);
4210 FSData->f_bfree = FSData->f_bavail =
4211 le32_to_cpu(response_data->FreeAllocationUnits);
4213 ("Blocks: %lld Free: %lld Block size %ld",
4214 (unsigned long long)FSData->f_blocks,
4215 (unsigned long long)FSData->f_bfree,
4219 cifs_buf_release(pSMB);
4222 goto oldQFSInfoRetry;
4228 CIFSSMBQFSInfo(const int xid, struct cifsTconInfo *tcon, struct kstatfs *FSData)
4230 /* level 0x103 SMB_QUERY_FILE_SYSTEM_INFO */
4231 TRANSACTION2_QFSI_REQ *pSMB = NULL;
4232 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4233 FILE_SYSTEM_INFO *response_data;
4235 int bytes_returned = 0;
4236 __u16 params, byte_count;
4238 cFYI(1, ("In QFSInfo"));
4240 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4245 params = 2; /* level */
4246 pSMB->TotalDataCount = 0;
4247 pSMB->MaxParameterCount = cpu_to_le16(2);
4248 pSMB->MaxDataCount = cpu_to_le16(1000);
4249 pSMB->MaxSetupCount = 0;
4253 pSMB->Reserved2 = 0;
4254 byte_count = params + 1 /* pad */ ;
4255 pSMB->TotalParameterCount = cpu_to_le16(params);
4256 pSMB->ParameterCount = pSMB->TotalParameterCount;
4257 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4258 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4259 pSMB->DataCount = 0;
4260 pSMB->DataOffset = 0;
4261 pSMB->SetupCount = 1;
4262 pSMB->Reserved3 = 0;
4263 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4264 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_SIZE_INFO);
4265 pSMB->hdr.smb_buf_length += byte_count;
4266 pSMB->ByteCount = cpu_to_le16(byte_count);
4268 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4269 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4271 cFYI(1, ("Send error in QFSInfo = %d", rc));
4272 } else { /* decode response */
4273 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4275 if (rc || (pSMBr->ByteCount < 24))
4276 rc = -EIO; /* bad smb */
4278 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4282 *) (((char *) &pSMBr->hdr.Protocol) +
4285 le32_to_cpu(response_data->BytesPerSector) *
4286 le32_to_cpu(response_data->
4287 SectorsPerAllocationUnit);
4289 le64_to_cpu(response_data->TotalAllocationUnits);
4290 FSData->f_bfree = FSData->f_bavail =
4291 le64_to_cpu(response_data->FreeAllocationUnits);
4293 ("Blocks: %lld Free: %lld Block size %ld",
4294 (unsigned long long)FSData->f_blocks,
4295 (unsigned long long)FSData->f_bfree,
4299 cifs_buf_release(pSMB);
4308 CIFSSMBQFSAttributeInfo(const int xid, struct cifsTconInfo *tcon)
4310 /* level 0x105 SMB_QUERY_FILE_SYSTEM_INFO */
4311 TRANSACTION2_QFSI_REQ *pSMB = NULL;
4312 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4313 FILE_SYSTEM_ATTRIBUTE_INFO *response_data;
4315 int bytes_returned = 0;
4316 __u16 params, byte_count;
4318 cFYI(1, ("In QFSAttributeInfo"));
4320 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4325 params = 2; /* level */
4326 pSMB->TotalDataCount = 0;
4327 pSMB->MaxParameterCount = cpu_to_le16(2);
4328 /* BB find exact max SMB PDU from sess structure BB */
4329 pSMB->MaxDataCount = cpu_to_le16(1000);
4330 pSMB->MaxSetupCount = 0;
4334 pSMB->Reserved2 = 0;
4335 byte_count = params + 1 /* pad */ ;
4336 pSMB->TotalParameterCount = cpu_to_le16(params);
4337 pSMB->ParameterCount = pSMB->TotalParameterCount;
4338 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4339 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4340 pSMB->DataCount = 0;
4341 pSMB->DataOffset = 0;
4342 pSMB->SetupCount = 1;
4343 pSMB->Reserved3 = 0;
4344 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4345 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_ATTRIBUTE_INFO);
4346 pSMB->hdr.smb_buf_length += byte_count;
4347 pSMB->ByteCount = cpu_to_le16(byte_count);
4349 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4350 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4352 cERROR(1, ("Send error in QFSAttributeInfo = %d", rc));
4353 } else { /* decode response */
4354 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4356 if (rc || (pSMBr->ByteCount < 13)) {
4357 /* BB also check if enough bytes returned */
4358 rc = -EIO; /* bad smb */
4360 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4362 (FILE_SYSTEM_ATTRIBUTE_INFO
4363 *) (((char *) &pSMBr->hdr.Protocol) +
4365 memcpy(&tcon->fsAttrInfo, response_data,
4366 sizeof(FILE_SYSTEM_ATTRIBUTE_INFO));
4369 cifs_buf_release(pSMB);
4372 goto QFSAttributeRetry;
4378 CIFSSMBQFSDeviceInfo(const int xid, struct cifsTconInfo *tcon)
4380 /* level 0x104 SMB_QUERY_FILE_SYSTEM_INFO */
4381 TRANSACTION2_QFSI_REQ *pSMB = NULL;
4382 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4383 FILE_SYSTEM_DEVICE_INFO *response_data;
4385 int bytes_returned = 0;
4386 __u16 params, byte_count;
4388 cFYI(1, ("In QFSDeviceInfo"));
4390 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4395 params = 2; /* level */
4396 pSMB->TotalDataCount = 0;
4397 pSMB->MaxParameterCount = cpu_to_le16(2);
4398 /* BB find exact max SMB PDU from sess structure BB */
4399 pSMB->MaxDataCount = cpu_to_le16(1000);
4400 pSMB->MaxSetupCount = 0;
4404 pSMB->Reserved2 = 0;
4405 byte_count = params + 1 /* pad */ ;
4406 pSMB->TotalParameterCount = cpu_to_le16(params);
4407 pSMB->ParameterCount = pSMB->TotalParameterCount;
4408 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4409 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4411 pSMB->DataCount = 0;
4412 pSMB->DataOffset = 0;
4413 pSMB->SetupCount = 1;
4414 pSMB->Reserved3 = 0;
4415 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4416 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_DEVICE_INFO);
4417 pSMB->hdr.smb_buf_length += byte_count;
4418 pSMB->ByteCount = cpu_to_le16(byte_count);
4420 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4421 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4423 cFYI(1, ("Send error in QFSDeviceInfo = %d", rc));
4424 } else { /* decode response */
4425 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4427 if (rc || (pSMBr->ByteCount < sizeof(FILE_SYSTEM_DEVICE_INFO)))
4428 rc = -EIO; /* bad smb */
4430 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4432 (FILE_SYSTEM_DEVICE_INFO *)
4433 (((char *) &pSMBr->hdr.Protocol) +
4435 memcpy(&tcon->fsDevInfo, response_data,
4436 sizeof(FILE_SYSTEM_DEVICE_INFO));
4439 cifs_buf_release(pSMB);
4442 goto QFSDeviceRetry;
4448 CIFSSMBQFSUnixInfo(const int xid, struct cifsTconInfo *tcon)
4450 /* level 0x200 SMB_QUERY_CIFS_UNIX_INFO */
4451 TRANSACTION2_QFSI_REQ *pSMB = NULL;
4452 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4453 FILE_SYSTEM_UNIX_INFO *response_data;
4455 int bytes_returned = 0;
4456 __u16 params, byte_count;
4458 cFYI(1, ("In QFSUnixInfo"));
4460 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4465 params = 2; /* level */
4466 pSMB->TotalDataCount = 0;
4467 pSMB->DataCount = 0;
4468 pSMB->DataOffset = 0;
4469 pSMB->MaxParameterCount = cpu_to_le16(2);
4470 /* BB find exact max SMB PDU from sess structure BB */
4471 pSMB->MaxDataCount = cpu_to_le16(100);
4472 pSMB->MaxSetupCount = 0;
4476 pSMB->Reserved2 = 0;
4477 byte_count = params + 1 /* pad */ ;
4478 pSMB->ParameterCount = cpu_to_le16(params);
4479 pSMB->TotalParameterCount = pSMB->ParameterCount;
4480 pSMB->ParameterOffset = cpu_to_le16(offsetof(struct
4481 smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4482 pSMB->SetupCount = 1;
4483 pSMB->Reserved3 = 0;
4484 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4485 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_CIFS_UNIX_INFO);
4486 pSMB->hdr.smb_buf_length += byte_count;
4487 pSMB->ByteCount = cpu_to_le16(byte_count);
4489 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4490 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4492 cERROR(1, ("Send error in QFSUnixInfo = %d", rc));
4493 } else { /* decode response */
4494 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4496 if (rc || (pSMBr->ByteCount < 13)) {
4497 rc = -EIO; /* bad smb */
4499 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4501 (FILE_SYSTEM_UNIX_INFO
4502 *) (((char *) &pSMBr->hdr.Protocol) +
4504 memcpy(&tcon->fsUnixInfo, response_data,
4505 sizeof(FILE_SYSTEM_UNIX_INFO));
4508 cifs_buf_release(pSMB);
4518 CIFSSMBSetFSUnixInfo(const int xid, struct cifsTconInfo *tcon, __u64 cap)
4520 /* level 0x200 SMB_SET_CIFS_UNIX_INFO */
4521 TRANSACTION2_SETFSI_REQ *pSMB = NULL;
4522 TRANSACTION2_SETFSI_RSP *pSMBr = NULL;
4524 int bytes_returned = 0;
4525 __u16 params, param_offset, offset, byte_count;
4527 cFYI(1, ("In SETFSUnixInfo"));
4529 /* BB switch to small buf init to save memory */
4530 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4535 params = 4; /* 2 bytes zero followed by info level. */
4536 pSMB->MaxSetupCount = 0;
4540 pSMB->Reserved2 = 0;
4541 param_offset = offsetof(struct smb_com_transaction2_setfsi_req, FileNum)
4543 offset = param_offset + params;
4545 pSMB->MaxParameterCount = cpu_to_le16(4);
4546 /* BB find exact max SMB PDU from sess structure BB */
4547 pSMB->MaxDataCount = cpu_to_le16(100);
4548 pSMB->SetupCount = 1;
4549 pSMB->Reserved3 = 0;
4550 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FS_INFORMATION);
4551 byte_count = 1 /* pad */ + params + 12;
4553 pSMB->DataCount = cpu_to_le16(12);
4554 pSMB->ParameterCount = cpu_to_le16(params);
4555 pSMB->TotalDataCount = pSMB->DataCount;
4556 pSMB->TotalParameterCount = pSMB->ParameterCount;
4557 pSMB->ParameterOffset = cpu_to_le16(param_offset);
4558 pSMB->DataOffset = cpu_to_le16(offset);
4562 pSMB->InformationLevel = cpu_to_le16(SMB_SET_CIFS_UNIX_INFO);
4565 pSMB->ClientUnixMajor = cpu_to_le16(CIFS_UNIX_MAJOR_VERSION);
4566 pSMB->ClientUnixMinor = cpu_to_le16(CIFS_UNIX_MINOR_VERSION);
4567 pSMB->ClientUnixCap = cpu_to_le64(cap);
4569 pSMB->hdr.smb_buf_length += byte_count;
4570 pSMB->ByteCount = cpu_to_le16(byte_count);
4572 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4573 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4575 cERROR(1, ("Send error in SETFSUnixInfo = %d", rc));
4576 } else { /* decode response */
4577 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4579 rc = -EIO; /* bad smb */
4581 cifs_buf_release(pSMB);
4584 goto SETFSUnixRetry;
4592 CIFSSMBQFSPosixInfo(const int xid, struct cifsTconInfo *tcon,
4593 struct kstatfs *FSData)
4595 /* level 0x201 SMB_QUERY_CIFS_POSIX_INFO */
4596 TRANSACTION2_QFSI_REQ *pSMB = NULL;
4597 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4598 FILE_SYSTEM_POSIX_INFO *response_data;
4600 int bytes_returned = 0;
4601 __u16 params, byte_count;
4603 cFYI(1, ("In QFSPosixInfo"));
4605 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4610 params = 2; /* level */
4611 pSMB->TotalDataCount = 0;
4612 pSMB->DataCount = 0;
4613 pSMB->DataOffset = 0;
4614 pSMB->MaxParameterCount = cpu_to_le16(2);
4615 /* BB find exact max SMB PDU from sess structure BB */
4616 pSMB->MaxDataCount = cpu_to_le16(100);
4617 pSMB->MaxSetupCount = 0;
4621 pSMB->Reserved2 = 0;
4622 byte_count = params + 1 /* pad */ ;
4623 pSMB->ParameterCount = cpu_to_le16(params);
4624 pSMB->TotalParameterCount = pSMB->ParameterCount;
4625 pSMB->ParameterOffset = cpu_to_le16(offsetof(struct
4626 smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4627 pSMB->SetupCount = 1;
4628 pSMB->Reserved3 = 0;
4629 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4630 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_POSIX_FS_INFO);
4631 pSMB->hdr.smb_buf_length += byte_count;
4632 pSMB->ByteCount = cpu_to_le16(byte_count);
4634 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4635 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4637 cFYI(1, ("Send error in QFSUnixInfo = %d", rc));
4638 } else { /* decode response */
4639 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4641 if (rc || (pSMBr->ByteCount < 13)) {
4642 rc = -EIO; /* bad smb */
4644 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4646 (FILE_SYSTEM_POSIX_INFO
4647 *) (((char *) &pSMBr->hdr.Protocol) +
4650 le32_to_cpu(response_data->BlockSize);
4652 le64_to_cpu(response_data->TotalBlocks);
4654 le64_to_cpu(response_data->BlocksAvail);
4655 if (response_data->UserBlocksAvail == cpu_to_le64(-1)) {
4656 FSData->f_bavail = FSData->f_bfree;
4659 le64_to_cpu(response_data->UserBlocksAvail);
4661 if (response_data->TotalFileNodes != cpu_to_le64(-1))
4663 le64_to_cpu(response_data->TotalFileNodes);
4664 if (response_data->FreeFileNodes != cpu_to_le64(-1))
4666 le64_to_cpu(response_data->FreeFileNodes);
4669 cifs_buf_release(pSMB);
4678 /* We can not use write of zero bytes trick to
4679 set file size due to need for large file support. Also note that
4680 this SetPathInfo is preferred to SetFileInfo based method in next
4681 routine which is only needed to work around a sharing violation bug
4682 in Samba which this routine can run into */
4685 CIFSSMBSetEOF(const int xid, struct cifsTconInfo *tcon, const char *fileName,
4686 __u64 size, bool SetAllocation,
4687 const struct nls_table *nls_codepage, int remap)
4689 struct smb_com_transaction2_spi_req *pSMB = NULL;
4690 struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
4691 struct file_end_of_file_info *parm_data;
4694 int bytes_returned = 0;
4695 __u16 params, byte_count, data_count, param_offset, offset;
4697 cFYI(1, ("In SetEOF"));
4699 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4704 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4706 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
4707 PATH_MAX, nls_codepage, remap);
4708 name_len++; /* trailing null */
4710 } else { /* BB improve the check for buffer overruns BB */
4711 name_len = strnlen(fileName, PATH_MAX);
4712 name_len++; /* trailing null */
4713 strncpy(pSMB->FileName, fileName, name_len);
4715 params = 6 + name_len;
4716 data_count = sizeof(struct file_end_of_file_info);
4717 pSMB->MaxParameterCount = cpu_to_le16(2);
4718 pSMB->MaxDataCount = cpu_to_le16(4100);
4719 pSMB->MaxSetupCount = 0;
4723 pSMB->Reserved2 = 0;
4724 param_offset = offsetof(struct smb_com_transaction2_spi_req,
4725 InformationLevel) - 4;
4726 offset = param_offset + params;
4727 if (SetAllocation) {
4728 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
4729 pSMB->InformationLevel =
4730 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2);
4732 pSMB->InformationLevel =
4733 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO);
4734 } else /* Set File Size */ {
4735 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
4736 pSMB->InformationLevel =
4737 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO2);
4739 pSMB->InformationLevel =
4740 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO);
4744 (struct file_end_of_file_info *) (((char *) &pSMB->hdr.Protocol) +
4746 pSMB->ParameterOffset = cpu_to_le16(param_offset);
4747 pSMB->DataOffset = cpu_to_le16(offset);
4748 pSMB->SetupCount = 1;
4749 pSMB->Reserved3 = 0;
4750 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
4751 byte_count = 3 /* pad */ + params + data_count;
4752 pSMB->DataCount = cpu_to_le16(data_count);
4753 pSMB->TotalDataCount = pSMB->DataCount;
4754 pSMB->ParameterCount = cpu_to_le16(params);
4755 pSMB->TotalParameterCount = pSMB->ParameterCount;
4756 pSMB->Reserved4 = 0;
4757 pSMB->hdr.smb_buf_length += byte_count;
4758 parm_data->FileSize = cpu_to_le64(size);
4759 pSMB->ByteCount = cpu_to_le16(byte_count);
4760 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4761 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4763 cFYI(1, ("SetPathInfo (file size) returned %d", rc));
4765 cifs_buf_release(pSMB);
4774 CIFSSMBSetFileSize(const int xid, struct cifsTconInfo *tcon, __u64 size,
4775 __u16 fid, __u32 pid_of_opener, bool SetAllocation)
4777 struct smb_com_transaction2_sfi_req *pSMB = NULL;
4779 struct file_end_of_file_info *parm_data;
4781 __u16 params, param_offset, offset, byte_count, count;
4783 cFYI(1, ("SetFileSize (via SetFileInfo) %lld",
4785 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
4790 pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
4791 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));
4794 pSMB->MaxSetupCount = 0;
4798 pSMB->Reserved2 = 0;
4799 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
4800 offset = param_offset + params;
4802 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
4804 count = sizeof(struct file_end_of_file_info);
4805 pSMB->MaxParameterCount = cpu_to_le16(2);
4806 /* BB find exact max SMB PDU from sess structure BB */
4807 pSMB->MaxDataCount = cpu_to_le16(1000);
4808 pSMB->SetupCount = 1;
4809 pSMB->Reserved3 = 0;
4810 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
4811 byte_count = 3 /* pad */ + params + count;
4812 pSMB->DataCount = cpu_to_le16(count);
4813 pSMB->ParameterCount = cpu_to_le16(params);
4814 pSMB->TotalDataCount = pSMB->DataCount;
4815 pSMB->TotalParameterCount = pSMB->ParameterCount;
4816 pSMB->ParameterOffset = cpu_to_le16(param_offset);
4818 (struct file_end_of_file_info *) (((char *) &pSMB->hdr.Protocol)
4820 pSMB->DataOffset = cpu_to_le16(offset);
4821 parm_data->FileSize = cpu_to_le64(size);
4823 if (SetAllocation) {
4824 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
4825 pSMB->InformationLevel =
4826 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2);
4828 pSMB->InformationLevel =
4829 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO);
4830 } else /* Set File Size */ {
4831 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
4832 pSMB->InformationLevel =
4833 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO2);
4835 pSMB->InformationLevel =
4836 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO);
4838 pSMB->Reserved4 = 0;
4839 pSMB->hdr.smb_buf_length += byte_count;
4840 pSMB->ByteCount = cpu_to_le16(byte_count);
4841 rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0);
4844 ("Send error in SetFileInfo (SetFileSize) = %d",
4848 /* Note: On -EAGAIN error only caller can retry on handle based calls
4849 since file handle passed in no longer valid */
4854 /* Some legacy servers such as NT4 require that the file times be set on
4855 an open handle, rather than by pathname - this is awkward due to
4856 potential access conflicts on the open, but it is unavoidable for these
4857 old servers since the only other choice is to go from 100 nanosecond DCE
4858 time and resort to the original setpathinfo level which takes the ancient
4859 DOS time format with 2 second granularity */
4861 CIFSSMBSetFileInfo(const int xid, struct cifsTconInfo *tcon,
4862 const FILE_BASIC_INFO *data, __u16 fid, __u32 pid_of_opener)
4864 struct smb_com_transaction2_sfi_req *pSMB = NULL;
4867 __u16 params, param_offset, offset, byte_count, count;
4869 cFYI(1, ("Set Times (via SetFileInfo)"));
4870 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
4875 pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
4876 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));
4879 pSMB->MaxSetupCount = 0;
4883 pSMB->Reserved2 = 0;
4884 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
4885 offset = param_offset + params;
4887 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
4889 count = sizeof(FILE_BASIC_INFO);
4890 pSMB->MaxParameterCount = cpu_to_le16(2);
4891 /* BB find max SMB PDU from sess */
4892 pSMB->MaxDataCount = cpu_to_le16(1000);
4893 pSMB->SetupCount = 1;
4894 pSMB->Reserved3 = 0;
4895 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
4896 byte_count = 3 /* pad */ + params + count;
4897 pSMB->DataCount = cpu_to_le16(count);
4898 pSMB->ParameterCount = cpu_to_le16(params);
4899 pSMB->TotalDataCount = pSMB->DataCount;
4900 pSMB->TotalParameterCount = pSMB->ParameterCount;
4901 pSMB->ParameterOffset = cpu_to_le16(param_offset);
4902 pSMB->DataOffset = cpu_to_le16(offset);
4904 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
4905 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO2);
4907 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO);
4908 pSMB->Reserved4 = 0;
4909 pSMB->hdr.smb_buf_length += byte_count;
4910 pSMB->ByteCount = cpu_to_le16(byte_count);
4911 memcpy(data_offset, data, sizeof(FILE_BASIC_INFO));
4912 rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0);
4914 cFYI(1, ("Send error in Set Time (SetFileInfo) = %d", rc));
4916 /* Note: On -EAGAIN error only caller can retry on handle based calls
4917 since file handle passed in no longer valid */
4923 CIFSSMBSetFileDisposition(const int xid, struct cifsTconInfo *tcon,
4924 bool delete_file, __u16 fid, __u32 pid_of_opener)
4926 struct smb_com_transaction2_sfi_req *pSMB = NULL;
4929 __u16 params, param_offset, offset, byte_count, count;
4931 cFYI(1, ("Set File Disposition (via SetFileInfo)"));
4932 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
4937 pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
4938 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));
4941 pSMB->MaxSetupCount = 0;
4945 pSMB->Reserved2 = 0;
4946 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
4947 offset = param_offset + params;
4949 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
4952 pSMB->MaxParameterCount = cpu_to_le16(2);
4953 /* BB find max SMB PDU from sess */
4954 pSMB->MaxDataCount = cpu_to_le16(1000);
4955 pSMB->SetupCount = 1;
4956 pSMB->Reserved3 = 0;
4957 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
4958 byte_count = 3 /* pad */ + params + count;
4959 pSMB->DataCount = cpu_to_le16(count);
4960 pSMB->ParameterCount = cpu_to_le16(params);
4961 pSMB->TotalDataCount = pSMB->DataCount;
4962 pSMB->TotalParameterCount = pSMB->ParameterCount;
4963 pSMB->ParameterOffset = cpu_to_le16(param_offset);
4964 pSMB->DataOffset = cpu_to_le16(offset);
4966 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_DISPOSITION_INFO);
4967 pSMB->Reserved4 = 0;
4968 pSMB->hdr.smb_buf_length += byte_count;
4969 pSMB->ByteCount = cpu_to_le16(byte_count);
4970 *data_offset = delete_file ? 1 : 0;
4971 rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0);
4973 cFYI(1, ("Send error in SetFileDisposition = %d", rc));
4979 CIFSSMBSetPathInfo(const int xid, struct cifsTconInfo *tcon,
4980 const char *fileName, const FILE_BASIC_INFO *data,
4981 const struct nls_table *nls_codepage, int remap)
4983 TRANSACTION2_SPI_REQ *pSMB = NULL;
4984 TRANSACTION2_SPI_RSP *pSMBr = NULL;
4987 int bytes_returned = 0;
4989 __u16 params, param_offset, offset, byte_count, count;
4991 cFYI(1, ("In SetTimes"));
4994 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4999 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5001 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
5002 PATH_MAX, nls_codepage, remap);
5003 name_len++; /* trailing null */
5005 } else { /* BB improve the check for buffer overruns BB */
5006 name_len = strnlen(fileName, PATH_MAX);
5007 name_len++; /* trailing null */
5008 strncpy(pSMB->FileName, fileName, name_len);
5011 params = 6 + name_len;
5012 count = sizeof(FILE_BASIC_INFO);
5013 pSMB->MaxParameterCount = cpu_to_le16(2);
5014 /* BB find max SMB PDU from sess structure BB */
5015 pSMB->MaxDataCount = cpu_to_le16(1000);
5016 pSMB->MaxSetupCount = 0;
5020 pSMB->Reserved2 = 0;
5021 param_offset = offsetof(struct smb_com_transaction2_spi_req,
5022 InformationLevel) - 4;
5023 offset = param_offset + params;
5024 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
5025 pSMB->ParameterOffset = cpu_to_le16(param_offset);
5026 pSMB->DataOffset = cpu_to_le16(offset);
5027 pSMB->SetupCount = 1;
5028 pSMB->Reserved3 = 0;
5029 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
5030 byte_count = 3 /* pad */ + params + count;
5032 pSMB->DataCount = cpu_to_le16(count);
5033 pSMB->ParameterCount = cpu_to_le16(params);
5034 pSMB->TotalDataCount = pSMB->DataCount;
5035 pSMB->TotalParameterCount = pSMB->ParameterCount;
5036 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
5037 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO2);
5039 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO);
5040 pSMB->Reserved4 = 0;
5041 pSMB->hdr.smb_buf_length += byte_count;
5042 memcpy(data_offset, data, sizeof(FILE_BASIC_INFO));
5043 pSMB->ByteCount = cpu_to_le16(byte_count);
5044 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5045 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5047 cFYI(1, ("SetPathInfo (times) returned %d", rc));
5049 cifs_buf_release(pSMB);
5057 /* Can not be used to set time stamps yet (due to old DOS time format) */
5058 /* Can be used to set attributes */
5059 #if 0 /* Possibly not needed - since it turns out that strangely NT4 has a bug
5060 handling it anyway and NT4 was what we thought it would be needed for
5061 Do not delete it until we prove whether needed for Win9x though */
5063 CIFSSMBSetAttrLegacy(int xid, struct cifsTconInfo *tcon, char *fileName,
5064 __u16 dos_attrs, const struct nls_table *nls_codepage)
5066 SETATTR_REQ *pSMB = NULL;
5067 SETATTR_RSP *pSMBr = NULL;
5072 cFYI(1, ("In SetAttrLegacy"));
5075 rc = smb_init(SMB_COM_SETATTR, 8, tcon, (void **) &pSMB,
5080 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5082 ConvertToUCS((__le16 *) pSMB->fileName, fileName,
5083 PATH_MAX, nls_codepage);
5084 name_len++; /* trailing null */
5086 } else { /* BB improve the check for buffer overruns BB */
5087 name_len = strnlen(fileName, PATH_MAX);
5088 name_len++; /* trailing null */
5089 strncpy(pSMB->fileName, fileName, name_len);
5091 pSMB->attr = cpu_to_le16(dos_attrs);
5092 pSMB->BufferFormat = 0x04;
5093 pSMB->hdr.smb_buf_length += name_len + 1;
5094 pSMB->ByteCount = cpu_to_le16(name_len + 1);
5095 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5096 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5098 cFYI(1, ("Error in LegacySetAttr = %d", rc));
5100 cifs_buf_release(pSMB);
5103 goto SetAttrLgcyRetry;
5107 #endif /* temporarily unneeded SetAttr legacy function */
5110 CIFSSMBUnixSetInfo(const int xid, struct cifsTconInfo *tcon, char *fileName,
5111 const struct cifs_unix_set_info_args *args,
5112 const struct nls_table *nls_codepage, int remap)
5114 TRANSACTION2_SPI_REQ *pSMB = NULL;
5115 TRANSACTION2_SPI_RSP *pSMBr = NULL;
5118 int bytes_returned = 0;
5119 FILE_UNIX_BASIC_INFO *data_offset;
5120 __u16 params, param_offset, offset, count, byte_count;
5121 __u64 mode = args->mode;
5123 cFYI(1, ("In SetUID/GID/Mode"));
5125 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5130 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5132 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
5133 PATH_MAX, nls_codepage, remap);
5134 name_len++; /* trailing null */
5136 } else { /* BB improve the check for buffer overruns BB */
5137 name_len = strnlen(fileName, PATH_MAX);
5138 name_len++; /* trailing null */
5139 strncpy(pSMB->FileName, fileName, name_len);
5142 params = 6 + name_len;
5143 count = sizeof(FILE_UNIX_BASIC_INFO);
5144 pSMB->MaxParameterCount = cpu_to_le16(2);
5145 /* BB find max SMB PDU from sess structure BB */
5146 pSMB->MaxDataCount = cpu_to_le16(1000);
5147 pSMB->MaxSetupCount = 0;
5151 pSMB->Reserved2 = 0;
5152 param_offset = offsetof(struct smb_com_transaction2_spi_req,
5153 InformationLevel) - 4;
5154 offset = param_offset + params;
5156 (FILE_UNIX_BASIC_INFO *) ((char *) &pSMB->hdr.Protocol +
5158 memset(data_offset, 0, count);
5159 pSMB->DataOffset = cpu_to_le16(offset);
5160 pSMB->ParameterOffset = cpu_to_le16(param_offset);
5161 pSMB->SetupCount = 1;
5162 pSMB->Reserved3 = 0;
5163 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
5164 byte_count = 3 /* pad */ + params + count;
5165 pSMB->ParameterCount = cpu_to_le16(params);
5166 pSMB->DataCount = cpu_to_le16(count);
5167 pSMB->TotalParameterCount = pSMB->ParameterCount;
5168 pSMB->TotalDataCount = pSMB->DataCount;
5169 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_BASIC);
5170 pSMB->Reserved4 = 0;
5171 pSMB->hdr.smb_buf_length += byte_count;
5172 /* Samba server ignores set of file size to zero due to bugs in some
5173 older clients, but we should be precise - we use SetFileSize to
5174 set file size and do not want to truncate file size to zero
5175 accidently as happened on one Samba server beta by putting
5176 zero instead of -1 here */
5177 data_offset->EndOfFile = cpu_to_le64(NO_CHANGE_64);
5178 data_offset->NumOfBytes = cpu_to_le64(NO_CHANGE_64);
5179 data_offset->LastStatusChange = cpu_to_le64(args->ctime);
5180 data_offset->LastAccessTime = cpu_to_le64(args->atime);
5181 data_offset->LastModificationTime = cpu_to_le64(args->mtime);
5182 data_offset->Uid = cpu_to_le64(args->uid);
5183 data_offset->Gid = cpu_to_le64(args->gid);
5184 /* better to leave device as zero when it is */
5185 data_offset->DevMajor = cpu_to_le64(MAJOR(args->device));
5186 data_offset->DevMinor = cpu_to_le64(MINOR(args->device));
5187 data_offset->Permissions = cpu_to_le64(mode);
5190 data_offset->Type = cpu_to_le32(UNIX_FILE);
5191 else if (S_ISDIR(mode))
5192 data_offset->Type = cpu_to_le32(UNIX_DIR);
5193 else if (S_ISLNK(mode))
5194 data_offset->Type = cpu_to_le32(UNIX_SYMLINK);
5195 else if (S_ISCHR(mode))
5196 data_offset->Type = cpu_to_le32(UNIX_CHARDEV);
5197 else if (S_ISBLK(mode))
5198 data_offset->Type = cpu_to_le32(UNIX_BLOCKDEV);
5199 else if (S_ISFIFO(mode))
5200 data_offset->Type = cpu_to_le32(UNIX_FIFO);
5201 else if (S_ISSOCK(mode))
5202 data_offset->Type = cpu_to_le32(UNIX_SOCKET);
5205 pSMB->ByteCount = cpu_to_le16(byte_count);
5206 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5207 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5209 cFYI(1, ("SetPathInfo (perms) returned %d", rc));
5211 cifs_buf_release(pSMB);
5217 int CIFSSMBNotify(const int xid, struct cifsTconInfo *tcon,
5218 const int notify_subdirs, const __u16 netfid,
5219 __u32 filter, struct file *pfile, int multishot,
5220 const struct nls_table *nls_codepage)
5223 struct smb_com_transaction_change_notify_req *pSMB = NULL;
5224 struct smb_com_ntransaction_change_notify_rsp *pSMBr = NULL;
5225 struct dir_notify_req *dnotify_req;
5228 cFYI(1, ("In CIFSSMBNotify for file handle %d", (int)netfid));
5229 rc = smb_init(SMB_COM_NT_TRANSACT, 23, tcon, (void **) &pSMB,
5234 pSMB->TotalParameterCount = 0 ;
5235 pSMB->TotalDataCount = 0;
5236 pSMB->MaxParameterCount = cpu_to_le32(2);
5237 /* BB find exact data count max from sess structure BB */
5238 pSMB->MaxDataCount = 0; /* same in little endian or be */
5239 /* BB VERIFY verify which is correct for above BB */
5240 pSMB->MaxDataCount = cpu_to_le32((tcon->ses->server->maxBuf -
5241 MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
5243 pSMB->MaxSetupCount = 4;
5245 pSMB->ParameterOffset = 0;
5246 pSMB->DataCount = 0;
5247 pSMB->DataOffset = 0;
5248 pSMB->SetupCount = 4; /* single byte does not need le conversion */
5249 pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_NOTIFY_CHANGE);
5250 pSMB->ParameterCount = pSMB->TotalParameterCount;
5252 pSMB->WatchTree = 1; /* one byte - no le conversion needed */
5253 pSMB->Reserved2 = 0;
5254 pSMB->CompletionFilter = cpu_to_le32(filter);
5255 pSMB->Fid = netfid; /* file handle always le */
5256 pSMB->ByteCount = 0;
5258 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5259 (struct smb_hdr *)pSMBr, &bytes_returned,
5262 cFYI(1, ("Error in Notify = %d", rc));
5264 /* Add file to outstanding requests */
5265 /* BB change to kmem cache alloc */
5266 dnotify_req = kmalloc(
5267 sizeof(struct dir_notify_req),
5270 dnotify_req->Pid = pSMB->hdr.Pid;
5271 dnotify_req->PidHigh = pSMB->hdr.PidHigh;
5272 dnotify_req->Mid = pSMB->hdr.Mid;
5273 dnotify_req->Tid = pSMB->hdr.Tid;
5274 dnotify_req->Uid = pSMB->hdr.Uid;
5275 dnotify_req->netfid = netfid;
5276 dnotify_req->pfile = pfile;
5277 dnotify_req->filter = filter;
5278 dnotify_req->multishot = multishot;
5279 spin_lock(&GlobalMid_Lock);
5280 list_add_tail(&dnotify_req->lhead,
5281 &GlobalDnotifyReqList);
5282 spin_unlock(&GlobalMid_Lock);
5286 cifs_buf_release(pSMB);
5289 #ifdef CONFIG_CIFS_XATTR
5291 CIFSSMBQAllEAs(const int xid, struct cifsTconInfo *tcon,
5292 const unsigned char *searchName,
5293 char *EAData, size_t buf_size,
5294 const struct nls_table *nls_codepage, int remap)
5296 /* BB assumes one setup word */
5297 TRANSACTION2_QPI_REQ *pSMB = NULL;
5298 TRANSACTION2_QPI_RSP *pSMBr = NULL;
5302 struct fea *temp_fea;
5304 __u16 params, byte_count;
5306 cFYI(1, ("In Query All EAs path %s", searchName));
5308 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5313 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5315 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
5316 PATH_MAX, nls_codepage, remap);
5317 name_len++; /* trailing null */
5319 } else { /* BB improve the check for buffer overruns BB */
5320 name_len = strnlen(searchName, PATH_MAX);
5321 name_len++; /* trailing null */
5322 strncpy(pSMB->FileName, searchName, name_len);
5325 params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */;
5326 pSMB->TotalDataCount = 0;
5327 pSMB->MaxParameterCount = cpu_to_le16(2);
5328 /* BB find exact max SMB PDU from sess structure BB */
5329 pSMB->MaxDataCount = cpu_to_le16(4000);
5330 pSMB->MaxSetupCount = 0;
5334 pSMB->Reserved2 = 0;
5335 pSMB->ParameterOffset = cpu_to_le16(offsetof(
5336 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
5337 pSMB->DataCount = 0;
5338 pSMB->DataOffset = 0;
5339 pSMB->SetupCount = 1;
5340 pSMB->Reserved3 = 0;
5341 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
5342 byte_count = params + 1 /* pad */ ;
5343 pSMB->TotalParameterCount = cpu_to_le16(params);
5344 pSMB->ParameterCount = pSMB->TotalParameterCount;
5345 pSMB->InformationLevel = cpu_to_le16(SMB_INFO_QUERY_ALL_EAS);
5346 pSMB->Reserved4 = 0;
5347 pSMB->hdr.smb_buf_length += byte_count;
5348 pSMB->ByteCount = cpu_to_le16(byte_count);
5350 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5351 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5353 cFYI(1, ("Send error in QueryAllEAs = %d", rc));
5354 } else { /* decode response */
5355 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
5357 /* BB also check enough total bytes returned */
5358 /* BB we need to improve the validity checking
5359 of these trans2 responses */
5360 if (rc || (pSMBr->ByteCount < 4))
5361 rc = -EIO; /* bad smb */
5362 /* else if (pFindData){
5363 memcpy((char *) pFindData,
5364 (char *) &pSMBr->hdr.Protocol +
5367 /* check that length of list is not more than bcc */
5368 /* check that each entry does not go beyond length
5370 /* check that each element of each entry does not
5371 go beyond end of list */
5372 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
5373 struct fealist *ea_response_data;
5375 /* validate_trans2_offsets() */
5376 /* BB check if start of smb + data_offset > &bcc+ bcc */
5377 ea_response_data = (struct fealist *)
5378 (((char *) &pSMBr->hdr.Protocol) +
5380 name_len = le32_to_cpu(ea_response_data->list_len);
5381 cFYI(1, ("ea length %d", name_len));
5382 if (name_len <= 8) {
5383 /* returned EA size zeroed at top of function */
5384 cFYI(1, ("empty EA list returned from server"));
5386 /* account for ea list len */
5388 temp_fea = ea_response_data->list;
5389 temp_ptr = (char *)temp_fea;
5390 while (name_len > 0) {
5394 rc += temp_fea->name_len;
5395 /* account for prefix user. and trailing null */
5397 if (rc < (int)buf_size) {
5398 memcpy(EAData, "user.", 5);
5400 memcpy(EAData, temp_ptr,
5401 temp_fea->name_len);
5402 EAData += temp_fea->name_len;
5403 /* null terminate name */
5405 EAData = EAData + 1;
5406 } else if (buf_size == 0) {
5407 /* skip copy - calc size only */
5409 /* stop before overrun buffer */
5413 name_len -= temp_fea->name_len;
5414 temp_ptr += temp_fea->name_len;
5415 /* account for trailing null */
5419 le16_to_cpu(temp_fea->value_len);
5420 name_len -= value_len;
5421 temp_ptr += value_len;
5422 /* BB check that temp_ptr is still
5425 /* no trailing null to account for
5427 /* go on to next EA */
5428 temp_fea = (struct fea *)temp_ptr;
5433 cifs_buf_release(pSMB);
5440 ssize_t CIFSSMBQueryEA(const int xid, struct cifsTconInfo *tcon,
5441 const unsigned char *searchName, const unsigned char *ea_name,
5442 unsigned char *ea_value, size_t buf_size,
5443 const struct nls_table *nls_codepage, int remap)
5445 TRANSACTION2_QPI_REQ *pSMB = NULL;
5446 TRANSACTION2_QPI_RSP *pSMBr = NULL;
5450 struct fea *temp_fea;
5452 __u16 params, byte_count;
5454 cFYI(1, ("In Query EA path %s", searchName));
5456 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5461 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5463 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
5464 PATH_MAX, nls_codepage, remap);
5465 name_len++; /* trailing null */
5467 } else { /* BB improve the check for buffer overruns BB */
5468 name_len = strnlen(searchName, PATH_MAX);
5469 name_len++; /* trailing null */
5470 strncpy(pSMB->FileName, searchName, name_len);
5473 params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */;
5474 pSMB->TotalDataCount = 0;
5475 pSMB->MaxParameterCount = cpu_to_le16(2);
5476 /* BB find exact max SMB PDU from sess structure BB */
5477 pSMB->MaxDataCount = cpu_to_le16(4000);
5478 pSMB->MaxSetupCount = 0;
5482 pSMB->Reserved2 = 0;
5483 pSMB->ParameterOffset = cpu_to_le16(offsetof(
5484 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
5485 pSMB->DataCount = 0;
5486 pSMB->DataOffset = 0;
5487 pSMB->SetupCount = 1;
5488 pSMB->Reserved3 = 0;
5489 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
5490 byte_count = params + 1 /* pad */ ;
5491 pSMB->TotalParameterCount = cpu_to_le16(params);
5492 pSMB->ParameterCount = pSMB->TotalParameterCount;
5493 pSMB->InformationLevel = cpu_to_le16(SMB_INFO_QUERY_ALL_EAS);
5494 pSMB->Reserved4 = 0;
5495 pSMB->hdr.smb_buf_length += byte_count;
5496 pSMB->ByteCount = cpu_to_le16(byte_count);
5498 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5499 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5501 cFYI(1, ("Send error in Query EA = %d", rc));
5502 } else { /* decode response */
5503 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
5505 /* BB also check enough total bytes returned */
5506 /* BB we need to improve the validity checking
5507 of these trans2 responses */
5508 if (rc || (pSMBr->ByteCount < 4))
5509 rc = -EIO; /* bad smb */
5510 /* else if (pFindData){
5511 memcpy((char *) pFindData,
5512 (char *) &pSMBr->hdr.Protocol +
5515 /* check that length of list is not more than bcc */
5516 /* check that each entry does not go beyond length
5518 /* check that each element of each entry does not
5519 go beyond end of list */
5520 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
5521 struct fealist *ea_response_data;
5523 /* validate_trans2_offsets() */
5524 /* BB check if start of smb + data_offset > &bcc+ bcc*/
5525 ea_response_data = (struct fealist *)
5526 (((char *) &pSMBr->hdr.Protocol) +
5528 name_len = le32_to_cpu(ea_response_data->list_len);
5529 cFYI(1, ("ea length %d", name_len));
5530 if (name_len <= 8) {
5531 /* returned EA size zeroed at top of function */
5532 cFYI(1, ("empty EA list returned from server"));
5534 /* account for ea list len */
5536 temp_fea = ea_response_data->list;
5537 temp_ptr = (char *)temp_fea;
5538 /* loop through checking if we have a matching
5539 name and then return the associated value */
5540 while (name_len > 0) {
5545 le16_to_cpu(temp_fea->value_len);
5546 /* BB validate that value_len falls within SMB,
5547 even though maximum for name_len is 255 */
5548 if (memcmp(temp_fea->name, ea_name,
5549 temp_fea->name_len) == 0) {
5552 /* account for prefix user. and trailing null */
5553 if (rc <= (int)buf_size) {
5555 temp_fea->name+temp_fea->name_len+1,
5557 /* ea values, unlike ea
5560 } else if (buf_size == 0) {
5561 /* skip copy - calc size only */
5563 /* stop before overrun buffer */
5568 name_len -= temp_fea->name_len;
5569 temp_ptr += temp_fea->name_len;
5570 /* account for trailing null */
5573 name_len -= value_len;
5574 temp_ptr += value_len;
5575 /* No trailing null to account for in
5576 value_len. Go on to next EA */
5577 temp_fea = (struct fea *)temp_ptr;
5582 cifs_buf_release(pSMB);
5590 CIFSSMBSetEA(const int xid, struct cifsTconInfo *tcon, const char *fileName,
5591 const char *ea_name, const void *ea_value,
5592 const __u16 ea_value_len, const struct nls_table *nls_codepage,
5595 struct smb_com_transaction2_spi_req *pSMB = NULL;
5596 struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
5597 struct fealist *parm_data;
5600 int bytes_returned = 0;
5601 __u16 params, param_offset, byte_count, offset, count;
5603 cFYI(1, ("In SetEA"));
5605 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5610 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5612 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
5613 PATH_MAX, nls_codepage, remap);
5614 name_len++; /* trailing null */
5616 } else { /* BB improve the check for buffer overruns BB */
5617 name_len = strnlen(fileName, PATH_MAX);
5618 name_len++; /* trailing null */
5619 strncpy(pSMB->FileName, fileName, name_len);
5622 params = 6 + name_len;
5624 /* done calculating parms using name_len of file name,
5625 now use name_len to calculate length of ea name
5626 we are going to create in the inode xattrs */
5627 if (ea_name == NULL)
5630 name_len = strnlen(ea_name, 255);
5632 count = sizeof(*parm_data) + ea_value_len + name_len;
5633 pSMB->MaxParameterCount = cpu_to_le16(2);
5634 /* BB find max SMB PDU from sess */
5635 pSMB->MaxDataCount = cpu_to_le16(1000);
5636 pSMB->MaxSetupCount = 0;
5640 pSMB->Reserved2 = 0;
5641 param_offset = offsetof(struct smb_com_transaction2_spi_req,
5642 InformationLevel) - 4;
5643 offset = param_offset + params;
5644 pSMB->InformationLevel =
5645 cpu_to_le16(SMB_SET_FILE_EA);
5648 (struct fealist *) (((char *) &pSMB->hdr.Protocol) +
5650 pSMB->ParameterOffset = cpu_to_le16(param_offset);
5651 pSMB->DataOffset = cpu_to_le16(offset);
5652 pSMB->SetupCount = 1;
5653 pSMB->Reserved3 = 0;
5654 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
5655 byte_count = 3 /* pad */ + params + count;
5656 pSMB->DataCount = cpu_to_le16(count);
5657 parm_data->list_len = cpu_to_le32(count);
5658 parm_data->list[0].EA_flags = 0;
5659 /* we checked above that name len is less than 255 */
5660 parm_data->list[0].name_len = (__u8)name_len;
5661 /* EA names are always ASCII */
5663 strncpy(parm_data->list[0].name, ea_name, name_len);
5664 parm_data->list[0].name[name_len] = 0;
5665 parm_data->list[0].value_len = cpu_to_le16(ea_value_len);
5666 /* caller ensures that ea_value_len is less than 64K but
5667 we need to ensure that it fits within the smb */
5669 /*BB add length check to see if it would fit in
5670 negotiated SMB buffer size BB */
5671 /* if (ea_value_len > buffer_size - 512 (enough for header)) */
5673 memcpy(parm_data->list[0].name+name_len+1,
5674 ea_value, ea_value_len);
5676 pSMB->TotalDataCount = pSMB->DataCount;
5677 pSMB->ParameterCount = cpu_to_le16(params);
5678 pSMB->TotalParameterCount = pSMB->ParameterCount;
5679 pSMB->Reserved4 = 0;
5680 pSMB->hdr.smb_buf_length += byte_count;
5681 pSMB->ByteCount = cpu_to_le16(byte_count);
5682 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5683 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5685 cFYI(1, ("SetPathInfo (EA) returned %d", rc));
5687 cifs_buf_release(pSMB);