4 * Copyright (C) International Business Machines Corp., 2002,2007
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 */
85 /* Mark as invalid, all open files on tree connections since they
86 were closed when session to server was lost */
87 static void mark_open_files_invalid(struct cifsTconInfo *pTcon)
89 struct cifsFileInfo *open_file = NULL;
90 struct list_head *tmp;
91 struct list_head *tmp1;
93 /* list all files open on tree connection and mark them invalid */
94 write_lock(&GlobalSMBSeslock);
95 list_for_each_safe(tmp, tmp1, &pTcon->openFileList) {
96 open_file = list_entry(tmp, struct cifsFileInfo, tlist);
98 open_file->invalidHandle = TRUE;
100 write_unlock(&GlobalSMBSeslock);
101 /* BB Add call to invalidate_inodes(sb) for all superblocks mounted
105 /* If the return code is zero, this function must fill in request_buf pointer */
107 small_smb_init(int smb_command, int wct, struct cifsTconInfo *tcon,
108 void **request_buf /* returned */)
112 /* SMBs NegProt, SessSetup, uLogoff do not have tcon yet so
113 check for tcp and smb session status done differently
114 for those three - in the calling routine */
116 if (tcon->tidStatus == CifsExiting) {
117 /* only tree disconnect, open, and write,
118 (and ulogoff which does not have tcon)
119 are allowed as we start force umount */
120 if ((smb_command != SMB_COM_WRITE_ANDX) &&
121 (smb_command != SMB_COM_OPEN_ANDX) &&
122 (smb_command != SMB_COM_TREE_DISCONNECT)) {
123 cFYI(1, ("can not send cmd %d while umounting",
128 if ((tcon->ses) && (tcon->ses->status != CifsExiting) &&
129 (tcon->ses->server)) {
130 struct nls_table *nls_codepage;
131 /* Give Demultiplex thread up to 10 seconds to
132 reconnect, should be greater than cifs socket
133 timeout which is 7 seconds */
134 while (tcon->ses->server->tcpStatus ==
136 wait_event_interruptible_timeout(tcon->ses->server->response_q,
137 (tcon->ses->server->tcpStatus ==
139 if (tcon->ses->server->tcpStatus ==
141 /* on "soft" mounts we wait once */
142 if ((tcon->retry == FALSE) ||
143 (tcon->ses->status == CifsExiting)) {
144 cFYI(1, ("gave up waiting on "
145 "reconnect in smb_init"));
147 } /* else "hard" mount - keep retrying
148 until process is killed or server
149 comes back on-line */
150 } else /* TCP session is reestablished now */
154 nls_codepage = load_nls_default();
155 /* need to prevent multiple threads trying to
156 simultaneously reconnect the same SMB session */
157 down(&tcon->ses->sesSem);
158 if (tcon->ses->status == CifsNeedReconnect)
159 rc = cifs_setup_session(0, tcon->ses,
161 if (!rc && (tcon->tidStatus == CifsNeedReconnect)) {
162 mark_open_files_invalid(tcon);
163 rc = CIFSTCon(0, tcon->ses, tcon->treeName,
165 up(&tcon->ses->sesSem);
166 /* tell server which Unix caps we support */
167 if (tcon->ses->capabilities & CAP_UNIX)
168 reset_cifs_unix_caps(0 /* no xid */,
170 NULL /* we do not know sb */,
171 NULL /* no vol info */);
172 /* BB FIXME add code to check if wsize needs
173 update due to negotiated smb buffer size
176 atomic_inc(&tconInfoReconnectCount);
178 cFYI(1, ("reconnect tcon rc = %d", rc));
179 /* Removed call to reopen open files here.
180 It is safer (and faster) to reopen files
181 one at a time as needed in read and write */
183 /* Check if handle based operation so we
184 know whether we can continue or not without
185 returning to caller to reset file handle */
186 switch (smb_command) {
187 case SMB_COM_READ_ANDX:
188 case SMB_COM_WRITE_ANDX:
190 case SMB_COM_FIND_CLOSE2:
191 case SMB_COM_LOCKING_ANDX: {
192 unload_nls(nls_codepage);
197 up(&tcon->ses->sesSem);
199 unload_nls(nls_codepage);
208 *request_buf = cifs_small_buf_get();
209 if (*request_buf == NULL) {
210 /* BB should we add a retry in here if not a writepage? */
214 header_assemble((struct smb_hdr *) *request_buf, smb_command,
218 cifs_stats_inc(&tcon->num_smbs_sent);
224 small_smb_init_no_tc(const int smb_command, const int wct,
225 struct cifsSesInfo *ses, void **request_buf)
228 struct smb_hdr *buffer;
230 rc = small_smb_init(smb_command, wct, NULL, request_buf);
234 buffer = (struct smb_hdr *)*request_buf;
235 buffer->Mid = GetNextMid(ses->server);
236 if (ses->capabilities & CAP_UNICODE)
237 buffer->Flags2 |= SMBFLG2_UNICODE;
238 if (ses->capabilities & CAP_STATUS32)
239 buffer->Flags2 |= SMBFLG2_ERR_STATUS;
241 /* uid, tid can stay at zero as set in header assemble */
243 /* BB add support for turning on the signing when
244 this function is used after 1st of session setup requests */
249 /* If the return code is zero, this function must fill in request_buf pointer */
251 smb_init(int smb_command, int wct, struct cifsTconInfo *tcon,
252 void **request_buf /* returned */ ,
253 void **response_buf /* returned */ )
257 /* SMBs NegProt, SessSetup, uLogoff do not have tcon yet so
258 check for tcp and smb session status done differently
259 for those three - in the calling routine */
261 if (tcon->tidStatus == CifsExiting) {
262 /* only tree disconnect, open, and write,
263 (and ulogoff which does not have tcon)
264 are allowed as we start force umount */
265 if ((smb_command != SMB_COM_WRITE_ANDX) &&
266 (smb_command != SMB_COM_OPEN_ANDX) &&
267 (smb_command != SMB_COM_TREE_DISCONNECT)) {
268 cFYI(1, ("can not send cmd %d while umounting",
274 if ((tcon->ses) && (tcon->ses->status != CifsExiting) &&
275 (tcon->ses->server)) {
276 struct nls_table *nls_codepage;
277 /* Give Demultiplex thread up to 10 seconds to
278 reconnect, should be greater than cifs socket
279 timeout which is 7 seconds */
280 while (tcon->ses->server->tcpStatus ==
282 wait_event_interruptible_timeout(tcon->ses->server->response_q,
283 (tcon->ses->server->tcpStatus ==
285 if (tcon->ses->server->tcpStatus ==
287 /* on "soft" mounts we wait once */
288 if ((tcon->retry == FALSE) ||
289 (tcon->ses->status == CifsExiting)) {
290 cFYI(1, ("gave up waiting on "
291 "reconnect in smb_init"));
293 } /* else "hard" mount - keep retrying
294 until process is killed or server
296 } else /* TCP session is reestablished now */
299 nls_codepage = load_nls_default();
300 /* need to prevent multiple threads trying to
301 simultaneously reconnect the same SMB session */
302 down(&tcon->ses->sesSem);
303 if (tcon->ses->status == CifsNeedReconnect)
304 rc = cifs_setup_session(0, tcon->ses,
306 if (!rc && (tcon->tidStatus == CifsNeedReconnect)) {
307 mark_open_files_invalid(tcon);
308 rc = CIFSTCon(0, tcon->ses, tcon->treeName,
310 up(&tcon->ses->sesSem);
311 /* tell server which Unix caps we support */
312 if (tcon->ses->capabilities & CAP_UNIX)
313 reset_cifs_unix_caps(0 /* no xid */,
315 NULL /* do not know sb */,
316 NULL /* no vol info */);
317 /* BB FIXME add code to check if wsize needs
318 update due to negotiated smb buffer size
321 atomic_inc(&tconInfoReconnectCount);
323 cFYI(1, ("reconnect tcon rc = %d", rc));
324 /* Removed call to reopen open files here.
325 It is safer (and faster) to reopen files
326 one at a time as needed in read and write */
328 /* Check if handle based operation so we
329 know whether we can continue or not without
330 returning to caller to reset file handle */
331 switch (smb_command) {
332 case SMB_COM_READ_ANDX:
333 case SMB_COM_WRITE_ANDX:
335 case SMB_COM_FIND_CLOSE2:
336 case SMB_COM_LOCKING_ANDX: {
337 unload_nls(nls_codepage);
342 up(&tcon->ses->sesSem);
344 unload_nls(nls_codepage);
353 *request_buf = cifs_buf_get();
354 if (*request_buf == NULL) {
355 /* BB should we add a retry in here if not a writepage? */
358 /* Although the original thought was we needed the response buf for */
359 /* potential retries of smb operations it turns out we can determine */
360 /* from the mid flags when the request buffer can be resent without */
361 /* having to use a second distinct buffer for the response */
363 *response_buf = *request_buf;
365 header_assemble((struct smb_hdr *) *request_buf, smb_command, tcon,
369 cifs_stats_inc(&tcon->num_smbs_sent);
374 static int validate_t2(struct smb_t2_rsp *pSMB)
380 /* check for plausible wct, bcc and t2 data and parm sizes */
381 /* check for parm and data offset going beyond end of smb */
382 if (pSMB->hdr.WordCount >= 10) {
383 if ((le16_to_cpu(pSMB->t2_rsp.ParameterOffset) <= 1024) &&
384 (le16_to_cpu(pSMB->t2_rsp.DataOffset) <= 1024)) {
385 /* check that bcc is at least as big as parms + data */
386 /* check that bcc is less than negotiated smb buffer */
387 total_size = le16_to_cpu(pSMB->t2_rsp.ParameterCount);
388 if (total_size < 512) {
390 le16_to_cpu(pSMB->t2_rsp.DataCount);
391 /* BCC le converted in SendReceive */
392 pBCC = (pSMB->hdr.WordCount * 2) +
393 sizeof(struct smb_hdr) +
395 if ((total_size <= (*(u16 *)pBCC)) &&
397 CIFSMaxBufSize+MAX_CIFS_HDR_SIZE)) {
403 cifs_dump_mem("Invalid transact2 SMB: ", (char *)pSMB,
404 sizeof(struct smb_t2_rsp) + 16);
408 CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses)
411 NEGOTIATE_RSP *pSMBr;
415 struct TCP_Server_Info *server;
417 unsigned int secFlags;
421 server = ses->server;
426 rc = smb_init(SMB_COM_NEGOTIATE, 0, NULL /* no tcon yet */ ,
427 (void **) &pSMB, (void **) &pSMBr);
431 /* if any of auth flags (ie not sign or seal) are overriden use them */
432 if (ses->overrideSecFlg & (~(CIFSSEC_MUST_SIGN | CIFSSEC_MUST_SEAL)))
433 secFlags = ses->overrideSecFlg; /* BB FIXME fix sign flags? */
434 else /* if override flags set only sign/seal OR them with global auth */
435 secFlags = extended_security | ses->overrideSecFlg;
437 cFYI(1, ("secFlags 0x%x", secFlags));
439 pSMB->hdr.Mid = GetNextMid(server);
440 pSMB->hdr.Flags2 |= (SMBFLG2_UNICODE | SMBFLG2_ERR_STATUS);
442 if ((secFlags & CIFSSEC_MUST_KRB5) == CIFSSEC_MUST_KRB5)
443 pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC;
444 else if ((secFlags & CIFSSEC_AUTH_MASK) == CIFSSEC_MAY_KRB5) {
445 cFYI(1, ("Kerberos only mechanism, enable extended security"));
446 pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC;
450 for (i = 0; i < CIFS_NUM_PROT; i++) {
451 strncpy(pSMB->DialectsArray+count, protocols[i].name, 16);
452 count += strlen(protocols[i].name) + 1;
453 /* null at end of source and target buffers anyway */
455 pSMB->hdr.smb_buf_length += count;
456 pSMB->ByteCount = cpu_to_le16(count);
458 rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB,
459 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
463 dialect = le16_to_cpu(pSMBr->DialectIndex);
464 cFYI(1, ("Dialect: %d", dialect));
465 /* Check wct = 1 error case */
466 if ((pSMBr->hdr.WordCount < 13) || (dialect == BAD_PROT)) {
467 /* core returns wct = 1, but we do not ask for core - otherwise
468 small wct just comes when dialect index is -1 indicating we
469 could not negotiate a common dialect */
472 #ifdef CONFIG_CIFS_WEAK_PW_HASH
473 } else if ((pSMBr->hdr.WordCount == 13)
474 && ((dialect == LANMAN_PROT)
475 || (dialect == LANMAN2_PROT))) {
477 struct lanman_neg_rsp *rsp = (struct lanman_neg_rsp *)pSMBr;
479 if ((secFlags & CIFSSEC_MAY_LANMAN) ||
480 (secFlags & CIFSSEC_MAY_PLNTXT))
481 server->secType = LANMAN;
483 cERROR(1, ("mount failed weak security disabled"
484 " in /proc/fs/cifs/SecurityFlags"));
488 server->secMode = (__u8)le16_to_cpu(rsp->SecurityMode);
489 server->maxReq = le16_to_cpu(rsp->MaxMpxCount);
490 server->maxBuf = min((__u32)le16_to_cpu(rsp->MaxBufSize),
491 (__u32)CIFSMaxBufSize + MAX_CIFS_HDR_SIZE);
492 GETU32(server->sessid) = le32_to_cpu(rsp->SessionKey);
493 /* even though we do not use raw we might as well set this
494 accurately, in case we ever find a need for it */
495 if ((le16_to_cpu(rsp->RawMode) & RAW_ENABLE) == RAW_ENABLE) {
496 server->maxRw = 0xFF00;
497 server->capabilities = CAP_MPX_MODE | CAP_RAW_MODE;
499 server->maxRw = 0;/* we do not need to use raw anyway */
500 server->capabilities = CAP_MPX_MODE;
502 tmp = (__s16)le16_to_cpu(rsp->ServerTimeZone);
504 /* OS/2 often does not set timezone therefore
505 * we must use server time to calc time zone.
506 * Could deviate slightly from the right zone.
507 * Smallest defined timezone difference is 15 minutes
508 * (i.e. Nepal). Rounding up/down is done to match
511 int val, seconds, remain, result;
512 struct timespec ts, utc;
514 ts = cnvrtDosUnixTm(le16_to_cpu(rsp->SrvTime.Date),
515 le16_to_cpu(rsp->SrvTime.Time));
516 cFYI(1, ("SrvTime %d sec since 1970 (utc: %d) diff: %d",
517 (int)ts.tv_sec, (int)utc.tv_sec,
518 (int)(utc.tv_sec - ts.tv_sec)));
519 val = (int)(utc.tv_sec - ts.tv_sec);
521 result = (seconds / MIN_TZ_ADJ) * MIN_TZ_ADJ;
522 remain = seconds % MIN_TZ_ADJ;
523 if (remain >= (MIN_TZ_ADJ / 2))
524 result += MIN_TZ_ADJ;
527 server->timeAdj = result;
529 server->timeAdj = (int)tmp;
530 server->timeAdj *= 60; /* also in seconds */
532 cFYI(1, ("server->timeAdj: %d seconds", server->timeAdj));
535 /* BB get server time for time conversions and add
536 code to use it and timezone since this is not UTC */
538 if (rsp->EncryptionKeyLength ==
539 cpu_to_le16(CIFS_CRYPTO_KEY_SIZE)) {
540 memcpy(server->cryptKey, rsp->EncryptionKey,
541 CIFS_CRYPTO_KEY_SIZE);
542 } else if (server->secMode & SECMODE_PW_ENCRYPT) {
543 rc = -EIO; /* need cryptkey unless plain text */
547 cFYI(1, ("LANMAN negotiated"));
548 /* we will not end up setting signing flags - as no signing
549 was in LANMAN and server did not return the flags on */
551 #else /* weak security disabled */
552 } else if (pSMBr->hdr.WordCount == 13) {
553 cERROR(1, ("mount failed, cifs module not built "
554 "with CIFS_WEAK_PW_HASH support"));
556 #endif /* WEAK_PW_HASH */
558 } else if (pSMBr->hdr.WordCount != 17) {
563 /* else wct == 17 NTLM */
564 server->secMode = pSMBr->SecurityMode;
565 if ((server->secMode & SECMODE_USER) == 0)
566 cFYI(1, ("share mode security"));
568 if ((server->secMode & SECMODE_PW_ENCRYPT) == 0)
569 #ifdef CONFIG_CIFS_WEAK_PW_HASH
570 if ((secFlags & CIFSSEC_MAY_PLNTXT) == 0)
571 #endif /* CIFS_WEAK_PW_HASH */
572 cERROR(1, ("Server requests plain text password"
573 " but client support disabled"));
575 if ((secFlags & CIFSSEC_MUST_NTLMV2) == CIFSSEC_MUST_NTLMV2)
576 server->secType = NTLMv2;
577 else if (secFlags & CIFSSEC_MAY_NTLM)
578 server->secType = NTLM;
579 else if (secFlags & CIFSSEC_MAY_NTLMV2)
580 server->secType = NTLMv2;
581 else if (secFlags & CIFSSEC_MAY_KRB5)
582 server->secType = Kerberos;
583 else if (secFlags & CIFSSEC_MAY_LANMAN)
584 server->secType = LANMAN;
585 /* #ifdef CONFIG_CIFS_EXPERIMENTAL
586 else if (secFlags & CIFSSEC_MAY_PLNTXT)
591 cERROR(1, ("Invalid security type"));
594 /* else ... any others ...? */
596 /* one byte, so no need to convert this or EncryptionKeyLen from
598 server->maxReq = le16_to_cpu(pSMBr->MaxMpxCount);
599 /* probably no need to store and check maxvcs */
600 server->maxBuf = min(le32_to_cpu(pSMBr->MaxBufferSize),
601 (__u32) CIFSMaxBufSize + MAX_CIFS_HDR_SIZE);
602 server->maxRw = le32_to_cpu(pSMBr->MaxRawSize);
603 cFYI(0, ("Max buf = %d", ses->server->maxBuf));
604 GETU32(ses->server->sessid) = le32_to_cpu(pSMBr->SessionKey);
605 server->capabilities = le32_to_cpu(pSMBr->Capabilities);
606 server->timeAdj = (int)(__s16)le16_to_cpu(pSMBr->ServerTimeZone);
607 server->timeAdj *= 60;
608 if (pSMBr->EncryptionKeyLength == CIFS_CRYPTO_KEY_SIZE) {
609 memcpy(server->cryptKey, pSMBr->u.EncryptionKey,
610 CIFS_CRYPTO_KEY_SIZE);
611 } else if ((pSMBr->hdr.Flags2 & SMBFLG2_EXT_SEC)
612 && (pSMBr->EncryptionKeyLength == 0)) {
613 /* decode security blob */
614 } else if (server->secMode & SECMODE_PW_ENCRYPT) {
615 rc = -EIO; /* no crypt key only if plain text pwd */
619 /* BB might be helpful to save off the domain of server here */
621 if ((pSMBr->hdr.Flags2 & SMBFLG2_EXT_SEC) &&
622 (server->capabilities & CAP_EXTENDED_SECURITY)) {
623 count = pSMBr->ByteCount;
629 if (server->socketUseCount.counter > 1) {
630 if (memcmp(server->server_GUID,
631 pSMBr->u.extended_response.
633 cFYI(1, ("server UID changed"));
634 memcpy(server->server_GUID,
635 pSMBr->u.extended_response.GUID,
639 memcpy(server->server_GUID,
640 pSMBr->u.extended_response.GUID, 16);
643 server->secType = RawNTLMSSP;
645 rc = decode_negTokenInit(pSMBr->u.extended_response.
656 server->capabilities &= ~CAP_EXTENDED_SECURITY;
658 #ifdef CONFIG_CIFS_WEAK_PW_HASH
661 if ((secFlags & CIFSSEC_MAY_SIGN) == 0) {
662 /* MUST_SIGN already includes the MAY_SIGN FLAG
663 so if this is zero it means that signing is disabled */
664 cFYI(1, ("Signing disabled"));
665 if (server->secMode & SECMODE_SIGN_REQUIRED) {
666 cERROR(1, ("Server requires "
667 "packet signing to be enabled in "
668 "/proc/fs/cifs/SecurityFlags."));
672 ~(SECMODE_SIGN_ENABLED | SECMODE_SIGN_REQUIRED);
673 } else if ((secFlags & CIFSSEC_MUST_SIGN) == CIFSSEC_MUST_SIGN) {
674 /* signing required */
675 cFYI(1, ("Must sign - secFlags 0x%x", secFlags));
676 if ((server->secMode &
677 (SECMODE_SIGN_ENABLED | SECMODE_SIGN_REQUIRED)) == 0) {
679 ("signing required but server lacks support"));
682 server->secMode |= SECMODE_SIGN_REQUIRED;
684 /* signing optional ie CIFSSEC_MAY_SIGN */
685 if ((server->secMode & SECMODE_SIGN_REQUIRED) == 0)
687 ~(SECMODE_SIGN_ENABLED | SECMODE_SIGN_REQUIRED);
691 cifs_buf_release(pSMB);
693 cFYI(1, ("negprot rc %d", rc));
698 CIFSSMBTDis(const int xid, struct cifsTconInfo *tcon)
700 struct smb_hdr *smb_buffer;
703 cFYI(1, ("In tree disconnect"));
705 * If last user of the connection and
706 * connection alive - disconnect it
707 * If this is the last connection on the server session disconnect it
708 * (and inside session disconnect we should check if tcp socket needs
709 * to be freed and kernel thread woken up).
712 down(&tcon->tconSem);
716 atomic_dec(&tcon->useCount);
717 if (atomic_read(&tcon->useCount) > 0) {
722 /* No need to return error on this operation if tid invalidated and
723 closed on server already e.g. due to tcp session crashing */
724 if (tcon->tidStatus == CifsNeedReconnect) {
729 if ((tcon->ses == NULL) || (tcon->ses->server == NULL)) {
733 rc = small_smb_init(SMB_COM_TREE_DISCONNECT, 0, tcon,
734 (void **)&smb_buffer);
740 rc = SendReceiveNoRsp(xid, tcon->ses, smb_buffer, 0);
742 cFYI(1, ("Tree disconnect failed %d", rc));
746 /* No need to return error on this operation if tid invalidated and
747 closed on server already e.g. due to tcp session crashing */
755 CIFSSMBLogoff(const int xid, struct cifsSesInfo *ses)
757 LOGOFF_ANDX_REQ *pSMB;
760 cFYI(1, ("In SMBLogoff for session disconnect"));
766 atomic_dec(&ses->inUse);
767 if (atomic_read(&ses->inUse) > 0) {
771 rc = small_smb_init(SMB_COM_LOGOFF_ANDX, 2, NULL, (void **)&pSMB);
778 pSMB->hdr.Mid = GetNextMid(ses->server);
780 if (ses->server->secMode &
781 (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
782 pSMB->hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
785 pSMB->hdr.Uid = ses->Suid;
787 pSMB->AndXCommand = 0xFF;
788 rc = SendReceiveNoRsp(xid, ses, (struct smb_hdr *) pSMB, 0);
790 atomic_dec(&ses->server->socketUseCount);
791 if (atomic_read(&ses->server->socketUseCount) == 0) {
792 spin_lock(&GlobalMid_Lock);
793 ses->server->tcpStatus = CifsExiting;
794 spin_unlock(&GlobalMid_Lock);
800 /* if session dead then we do not need to do ulogoff,
801 since server closed smb session, no sense reporting
809 CIFSPOSIXDelFile(const int xid, struct cifsTconInfo *tcon, const char *fileName,
810 __u16 type, const struct nls_table *nls_codepage, int remap)
812 TRANSACTION2_SPI_REQ *pSMB = NULL;
813 TRANSACTION2_SPI_RSP *pSMBr = NULL;
814 struct unlink_psx_rq *pRqD;
817 int bytes_returned = 0;
818 __u16 params, param_offset, offset, byte_count;
820 cFYI(1, ("In POSIX delete"));
822 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
827 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
829 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
830 PATH_MAX, nls_codepage, remap);
831 name_len++; /* trailing null */
833 } else { /* BB add path length overrun check */
834 name_len = strnlen(fileName, PATH_MAX);
835 name_len++; /* trailing null */
836 strncpy(pSMB->FileName, fileName, name_len);
839 params = 6 + name_len;
840 pSMB->MaxParameterCount = cpu_to_le16(2);
841 pSMB->MaxDataCount = 0; /* BB double check this with jra */
842 pSMB->MaxSetupCount = 0;
847 param_offset = offsetof(struct smb_com_transaction2_spi_req,
848 InformationLevel) - 4;
849 offset = param_offset + params;
851 /* Setup pointer to Request Data (inode type) */
852 pRqD = (struct unlink_psx_rq *)(((char *)&pSMB->hdr.Protocol) + offset);
853 pRqD->type = cpu_to_le16(type);
854 pSMB->ParameterOffset = cpu_to_le16(param_offset);
855 pSMB->DataOffset = cpu_to_le16(offset);
856 pSMB->SetupCount = 1;
858 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
859 byte_count = 3 /* pad */ + params + sizeof(struct unlink_psx_rq);
861 pSMB->DataCount = cpu_to_le16(sizeof(struct unlink_psx_rq));
862 pSMB->TotalDataCount = cpu_to_le16(sizeof(struct unlink_psx_rq));
863 pSMB->ParameterCount = cpu_to_le16(params);
864 pSMB->TotalParameterCount = pSMB->ParameterCount;
865 pSMB->InformationLevel = cpu_to_le16(SMB_POSIX_UNLINK);
867 pSMB->hdr.smb_buf_length += byte_count;
868 pSMB->ByteCount = cpu_to_le16(byte_count);
869 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
870 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
872 cFYI(1, ("Posix delete returned %d", rc));
874 cifs_buf_release(pSMB);
876 cifs_stats_inc(&tcon->num_deletes);
885 CIFSSMBDelFile(const int xid, struct cifsTconInfo *tcon, const char *fileName,
886 const struct nls_table *nls_codepage, int remap)
888 DELETE_FILE_REQ *pSMB = NULL;
889 DELETE_FILE_RSP *pSMBr = NULL;
895 rc = smb_init(SMB_COM_DELETE, 1, tcon, (void **) &pSMB,
900 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
902 cifsConvertToUCS((__le16 *) pSMB->fileName, fileName,
903 PATH_MAX, nls_codepage, remap);
904 name_len++; /* trailing null */
906 } else { /* BB improve check for buffer overruns BB */
907 name_len = strnlen(fileName, PATH_MAX);
908 name_len++; /* trailing null */
909 strncpy(pSMB->fileName, fileName, name_len);
911 pSMB->SearchAttributes =
912 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM);
913 pSMB->BufferFormat = 0x04;
914 pSMB->hdr.smb_buf_length += name_len + 1;
915 pSMB->ByteCount = cpu_to_le16(name_len + 1);
916 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
917 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
918 cifs_stats_inc(&tcon->num_deletes);
920 cFYI(1, ("Error in RMFile = %d", rc));
923 cifs_buf_release(pSMB);
931 CIFSSMBRmDir(const int xid, struct cifsTconInfo *tcon, const char *dirName,
932 const struct nls_table *nls_codepage, int remap)
934 DELETE_DIRECTORY_REQ *pSMB = NULL;
935 DELETE_DIRECTORY_RSP *pSMBr = NULL;
940 cFYI(1, ("In CIFSSMBRmDir"));
942 rc = smb_init(SMB_COM_DELETE_DIRECTORY, 0, tcon, (void **) &pSMB,
947 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
948 name_len = cifsConvertToUCS((__le16 *) pSMB->DirName, dirName,
949 PATH_MAX, nls_codepage, remap);
950 name_len++; /* trailing null */
952 } else { /* BB improve check for buffer overruns BB */
953 name_len = strnlen(dirName, PATH_MAX);
954 name_len++; /* trailing null */
955 strncpy(pSMB->DirName, dirName, name_len);
958 pSMB->BufferFormat = 0x04;
959 pSMB->hdr.smb_buf_length += name_len + 1;
960 pSMB->ByteCount = cpu_to_le16(name_len + 1);
961 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
962 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
963 cifs_stats_inc(&tcon->num_rmdirs);
965 cFYI(1, ("Error in RMDir = %d", rc));
968 cifs_buf_release(pSMB);
975 CIFSSMBMkDir(const int xid, struct cifsTconInfo *tcon,
976 const char *name, const struct nls_table *nls_codepage, int remap)
979 CREATE_DIRECTORY_REQ *pSMB = NULL;
980 CREATE_DIRECTORY_RSP *pSMBr = NULL;
984 cFYI(1, ("In CIFSSMBMkDir"));
986 rc = smb_init(SMB_COM_CREATE_DIRECTORY, 0, tcon, (void **) &pSMB,
991 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
992 name_len = cifsConvertToUCS((__le16 *) pSMB->DirName, name,
993 PATH_MAX, nls_codepage, remap);
994 name_len++; /* trailing null */
996 } else { /* BB improve check for buffer overruns BB */
997 name_len = strnlen(name, PATH_MAX);
998 name_len++; /* trailing null */
999 strncpy(pSMB->DirName, name, name_len);
1002 pSMB->BufferFormat = 0x04;
1003 pSMB->hdr.smb_buf_length += name_len + 1;
1004 pSMB->ByteCount = cpu_to_le16(name_len + 1);
1005 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1006 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1007 cifs_stats_inc(&tcon->num_mkdirs);
1009 cFYI(1, ("Error in Mkdir = %d", rc));
1012 cifs_buf_release(pSMB);
1019 CIFSPOSIXCreate(const int xid, struct cifsTconInfo *tcon, __u32 posix_flags,
1020 __u64 mode, __u16 * netfid, FILE_UNIX_BASIC_INFO *pRetData,
1021 __u32 *pOplock, const char *name,
1022 const struct nls_table *nls_codepage, int remap)
1024 TRANSACTION2_SPI_REQ *pSMB = NULL;
1025 TRANSACTION2_SPI_RSP *pSMBr = NULL;
1028 int bytes_returned = 0;
1029 __u16 params, param_offset, offset, byte_count, count;
1030 OPEN_PSX_REQ * pdata;
1031 OPEN_PSX_RSP * psx_rsp;
1033 cFYI(1, ("In POSIX Create"));
1035 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
1040 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1042 cifsConvertToUCS((__le16 *) pSMB->FileName, name,
1043 PATH_MAX, nls_codepage, remap);
1044 name_len++; /* trailing null */
1046 } else { /* BB improve the check for buffer overruns BB */
1047 name_len = strnlen(name, PATH_MAX);
1048 name_len++; /* trailing null */
1049 strncpy(pSMB->FileName, name, name_len);
1052 params = 6 + name_len;
1053 count = sizeof(OPEN_PSX_REQ);
1054 pSMB->MaxParameterCount = cpu_to_le16(2);
1055 pSMB->MaxDataCount = cpu_to_le16(1000); /* large enough */
1056 pSMB->MaxSetupCount = 0;
1060 pSMB->Reserved2 = 0;
1061 param_offset = offsetof(struct smb_com_transaction2_spi_req,
1062 InformationLevel) - 4;
1063 offset = param_offset + params;
1064 pdata = (OPEN_PSX_REQ *)(((char *)&pSMB->hdr.Protocol) + offset);
1065 pdata->Level = cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC);
1066 pdata->Permissions = cpu_to_le64(mode);
1067 pdata->PosixOpenFlags = cpu_to_le32(posix_flags);
1068 pdata->OpenFlags = cpu_to_le32(*pOplock);
1069 pSMB->ParameterOffset = cpu_to_le16(param_offset);
1070 pSMB->DataOffset = cpu_to_le16(offset);
1071 pSMB->SetupCount = 1;
1072 pSMB->Reserved3 = 0;
1073 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
1074 byte_count = 3 /* pad */ + params + count;
1076 pSMB->DataCount = cpu_to_le16(count);
1077 pSMB->ParameterCount = cpu_to_le16(params);
1078 pSMB->TotalDataCount = pSMB->DataCount;
1079 pSMB->TotalParameterCount = pSMB->ParameterCount;
1080 pSMB->InformationLevel = cpu_to_le16(SMB_POSIX_OPEN);
1081 pSMB->Reserved4 = 0;
1082 pSMB->hdr.smb_buf_length += byte_count;
1083 pSMB->ByteCount = cpu_to_le16(byte_count);
1084 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1085 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1087 cFYI(1, ("Posix create returned %d", rc));
1088 goto psx_create_err;
1091 cFYI(1, ("copying inode info"));
1092 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
1094 if (rc || (pSMBr->ByteCount < sizeof(OPEN_PSX_RSP))) {
1095 rc = -EIO; /* bad smb */
1096 goto psx_create_err;
1099 /* copy return information to pRetData */
1100 psx_rsp = (OPEN_PSX_RSP *)((char *) &pSMBr->hdr.Protocol
1101 + le16_to_cpu(pSMBr->t2.DataOffset));
1103 *pOplock = le16_to_cpu(psx_rsp->OplockFlags);
1105 *netfid = psx_rsp->Fid; /* cifs fid stays in le */
1106 /* Let caller know file was created so we can set the mode. */
1107 /* Do we care about the CreateAction in any other cases? */
1108 if (cpu_to_le32(FILE_CREATE) == psx_rsp->CreateAction)
1109 *pOplock |= CIFS_CREATE_ACTION;
1110 /* check to make sure response data is there */
1111 if (psx_rsp->ReturnedLevel != cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC)) {
1112 pRetData->Type = cpu_to_le32(-1); /* unknown */
1113 #ifdef CONFIG_CIFS_DEBUG2
1114 cFYI(1, ("unknown type"));
1117 if (pSMBr->ByteCount < sizeof(OPEN_PSX_RSP)
1118 + sizeof(FILE_UNIX_BASIC_INFO)) {
1119 cERROR(1, ("Open response data too small"));
1120 pRetData->Type = cpu_to_le32(-1);
1121 goto psx_create_err;
1123 memcpy((char *) pRetData,
1124 (char *)psx_rsp + sizeof(OPEN_PSX_RSP),
1125 sizeof(FILE_UNIX_BASIC_INFO));
1129 cifs_buf_release(pSMB);
1131 cifs_stats_inc(&tcon->num_mkdirs);
1139 static __u16 convert_disposition(int disposition)
1143 switch (disposition) {
1144 case FILE_SUPERSEDE:
1145 ofun = SMBOPEN_OCREATE | SMBOPEN_OTRUNC;
1148 ofun = SMBOPEN_OAPPEND;
1151 ofun = SMBOPEN_OCREATE;
1154 ofun = SMBOPEN_OCREATE | SMBOPEN_OAPPEND;
1156 case FILE_OVERWRITE:
1157 ofun = SMBOPEN_OTRUNC;
1159 case FILE_OVERWRITE_IF:
1160 ofun = SMBOPEN_OCREATE | SMBOPEN_OTRUNC;
1163 cFYI(1, ("unknown disposition %d", disposition));
1164 ofun = SMBOPEN_OAPPEND; /* regular open */
1170 SMBLegacyOpen(const int xid, struct cifsTconInfo *tcon,
1171 const char *fileName, const int openDisposition,
1172 const int access_flags, const int create_options, __u16 * netfid,
1173 int *pOplock, FILE_ALL_INFO * pfile_info,
1174 const struct nls_table *nls_codepage, int remap)
1177 OPENX_REQ *pSMB = NULL;
1178 OPENX_RSP *pSMBr = NULL;
1184 rc = smb_init(SMB_COM_OPEN_ANDX, 15, tcon, (void **) &pSMB,
1189 pSMB->AndXCommand = 0xFF; /* none */
1191 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1192 count = 1; /* account for one byte pad to word boundary */
1194 cifsConvertToUCS((__le16 *) (pSMB->fileName + 1),
1195 fileName, PATH_MAX, nls_codepage, remap);
1196 name_len++; /* trailing null */
1198 } else { /* BB improve check for buffer overruns BB */
1199 count = 0; /* no pad */
1200 name_len = strnlen(fileName, PATH_MAX);
1201 name_len++; /* trailing null */
1202 strncpy(pSMB->fileName, fileName, name_len);
1204 if (*pOplock & REQ_OPLOCK)
1205 pSMB->OpenFlags = cpu_to_le16(REQ_OPLOCK);
1206 else if (*pOplock & REQ_BATCHOPLOCK)
1207 pSMB->OpenFlags = cpu_to_le16(REQ_BATCHOPLOCK);
1209 pSMB->OpenFlags |= cpu_to_le16(REQ_MORE_INFO);
1210 /* BB fixme add conversion for access_flags to bits 0 - 2 of mode */
1216 pSMB->Mode = cpu_to_le16(2);
1217 pSMB->Mode |= cpu_to_le16(0x40); /* deny none */
1218 /* set file as system file if special file such
1219 as fifo and server expecting SFU style and
1220 no Unix extensions */
1222 if (create_options & CREATE_OPTION_SPECIAL)
1223 pSMB->FileAttributes = cpu_to_le16(ATTR_SYSTEM);
1225 pSMB->FileAttributes = cpu_to_le16(0/*ATTR_NORMAL*/); /* BB FIXME */
1227 /* if ((omode & S_IWUGO) == 0)
1228 pSMB->FileAttributes |= cpu_to_le32(ATTR_READONLY);*/
1229 /* Above line causes problems due to vfs splitting create into two
1230 pieces - need to set mode after file created not while it is
1234 /* pSMB->CreateOptions = cpu_to_le32(create_options &
1235 CREATE_OPTIONS_MASK); */
1236 /* BB FIXME END BB */
1238 pSMB->Sattr = cpu_to_le16(ATTR_HIDDEN | ATTR_SYSTEM | ATTR_DIRECTORY);
1239 pSMB->OpenFunction = cpu_to_le16(convert_disposition(openDisposition));
1241 pSMB->hdr.smb_buf_length += count;
1243 pSMB->ByteCount = cpu_to_le16(count);
1244 /* long_op set to 1 to allow for oplock break timeouts */
1245 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1246 (struct smb_hdr *)pSMBr, &bytes_returned, CIFS_LONG_OP);
1247 cifs_stats_inc(&tcon->num_opens);
1249 cFYI(1, ("Error in Open = %d", rc));
1251 /* BB verify if wct == 15 */
1253 /* *pOplock = pSMBr->OplockLevel; */ /* BB take from action field BB */
1255 *netfid = pSMBr->Fid; /* cifs fid stays in le */
1256 /* Let caller know file was created so we can set the mode. */
1257 /* Do we care about the CreateAction in any other cases? */
1259 /* if (cpu_to_le32(FILE_CREATE) == pSMBr->CreateAction)
1260 *pOplock |= CIFS_CREATE_ACTION; */
1264 pfile_info->CreationTime = 0; /* BB convert CreateTime*/
1265 pfile_info->LastAccessTime = 0; /* BB fixme */
1266 pfile_info->LastWriteTime = 0; /* BB fixme */
1267 pfile_info->ChangeTime = 0; /* BB fixme */
1268 pfile_info->Attributes =
1269 cpu_to_le32(le16_to_cpu(pSMBr->FileAttributes));
1270 /* the file_info buf is endian converted by caller */
1271 pfile_info->AllocationSize =
1272 cpu_to_le64(le32_to_cpu(pSMBr->EndOfFile));
1273 pfile_info->EndOfFile = pfile_info->AllocationSize;
1274 pfile_info->NumberOfLinks = cpu_to_le32(1);
1278 cifs_buf_release(pSMB);
1285 CIFSSMBOpen(const int xid, struct cifsTconInfo *tcon,
1286 const char *fileName, const int openDisposition,
1287 const int access_flags, const int create_options, __u16 * netfid,
1288 int *pOplock, FILE_ALL_INFO * pfile_info,
1289 const struct nls_table *nls_codepage, int remap)
1292 OPEN_REQ *pSMB = NULL;
1293 OPEN_RSP *pSMBr = NULL;
1299 rc = smb_init(SMB_COM_NT_CREATE_ANDX, 24, tcon, (void **) &pSMB,
1304 pSMB->AndXCommand = 0xFF; /* none */
1306 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1307 count = 1; /* account for one byte pad to word boundary */
1309 cifsConvertToUCS((__le16 *) (pSMB->fileName + 1),
1310 fileName, PATH_MAX, nls_codepage, remap);
1311 name_len++; /* trailing null */
1313 pSMB->NameLength = cpu_to_le16(name_len);
1314 } else { /* BB improve check for buffer overruns BB */
1315 count = 0; /* no pad */
1316 name_len = strnlen(fileName, PATH_MAX);
1317 name_len++; /* trailing null */
1318 pSMB->NameLength = cpu_to_le16(name_len);
1319 strncpy(pSMB->fileName, fileName, name_len);
1321 if (*pOplock & REQ_OPLOCK)
1322 pSMB->OpenFlags = cpu_to_le32(REQ_OPLOCK);
1323 else if (*pOplock & REQ_BATCHOPLOCK)
1324 pSMB->OpenFlags = cpu_to_le32(REQ_BATCHOPLOCK);
1325 pSMB->DesiredAccess = cpu_to_le32(access_flags);
1326 pSMB->AllocationSize = 0;
1327 /* set file as system file if special file such
1328 as fifo and server expecting SFU style and
1329 no Unix extensions */
1330 if (create_options & CREATE_OPTION_SPECIAL)
1331 pSMB->FileAttributes = cpu_to_le32(ATTR_SYSTEM);
1333 pSMB->FileAttributes = cpu_to_le32(ATTR_NORMAL);
1334 /* XP does not handle ATTR_POSIX_SEMANTICS */
1335 /* but it helps speed up case sensitive checks for other
1336 servers such as Samba */
1337 if (tcon->ses->capabilities & CAP_UNIX)
1338 pSMB->FileAttributes |= cpu_to_le32(ATTR_POSIX_SEMANTICS);
1340 /* if ((omode & S_IWUGO) == 0)
1341 pSMB->FileAttributes |= cpu_to_le32(ATTR_READONLY);*/
1342 /* Above line causes problems due to vfs splitting create into two
1343 pieces - need to set mode after file created not while it is
1345 pSMB->ShareAccess = cpu_to_le32(FILE_SHARE_ALL);
1346 pSMB->CreateDisposition = cpu_to_le32(openDisposition);
1347 pSMB->CreateOptions = cpu_to_le32(create_options & CREATE_OPTIONS_MASK);
1348 /* BB Expirement with various impersonation levels and verify */
1349 pSMB->ImpersonationLevel = cpu_to_le32(SECURITY_IMPERSONATION);
1350 pSMB->SecurityFlags =
1351 SECURITY_CONTEXT_TRACKING | SECURITY_EFFECTIVE_ONLY;
1354 pSMB->hdr.smb_buf_length += count;
1356 pSMB->ByteCount = cpu_to_le16(count);
1357 /* long_op set to 1 to allow for oplock break timeouts */
1358 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1359 (struct smb_hdr *)pSMBr, &bytes_returned, CIFS_LONG_OP);
1360 cifs_stats_inc(&tcon->num_opens);
1362 cFYI(1, ("Error in Open = %d", rc));
1364 *pOplock = pSMBr->OplockLevel; /* 1 byte no need to le_to_cpu */
1365 *netfid = pSMBr->Fid; /* cifs fid stays in le */
1366 /* Let caller know file was created so we can set the mode. */
1367 /* Do we care about the CreateAction in any other cases? */
1368 if (cpu_to_le32(FILE_CREATE) == pSMBr->CreateAction)
1369 *pOplock |= CIFS_CREATE_ACTION;
1371 memcpy((char *)pfile_info, (char *)&pSMBr->CreationTime,
1372 36 /* CreationTime to Attributes */);
1373 /* the file_info buf is endian converted by caller */
1374 pfile_info->AllocationSize = pSMBr->AllocationSize;
1375 pfile_info->EndOfFile = pSMBr->EndOfFile;
1376 pfile_info->NumberOfLinks = cpu_to_le32(1);
1380 cifs_buf_release(pSMB);
1387 CIFSSMBRead(const int xid, struct cifsTconInfo *tcon, const int netfid,
1388 const unsigned int count, const __u64 lseek, unsigned int *nbytes,
1389 char **buf, int *pbuf_type)
1392 READ_REQ *pSMB = NULL;
1393 READ_RSP *pSMBr = NULL;
1394 char *pReadData = NULL;
1396 int resp_buf_type = 0;
1399 cFYI(1, ("Reading %d bytes on fid %d", count, netfid));
1400 if (tcon->ses->capabilities & CAP_LARGE_FILES)
1403 wct = 10; /* old style read */
1406 rc = small_smb_init(SMB_COM_READ_ANDX, wct, tcon, (void **) &pSMB);
1410 /* tcon and ses pointer are checked in smb_init */
1411 if (tcon->ses->server == NULL)
1412 return -ECONNABORTED;
1414 pSMB->AndXCommand = 0xFF; /* none */
1416 pSMB->OffsetLow = cpu_to_le32(lseek & 0xFFFFFFFF);
1418 pSMB->OffsetHigh = cpu_to_le32(lseek >> 32);
1419 else if ((lseek >> 32) > 0) /* can not handle this big offset for old */
1422 pSMB->Remaining = 0;
1423 pSMB->MaxCount = cpu_to_le16(count & 0xFFFF);
1424 pSMB->MaxCountHigh = cpu_to_le32(count >> 16);
1426 pSMB->ByteCount = 0; /* no need to do le conversion since 0 */
1428 /* old style read */
1429 struct smb_com_readx_req *pSMBW =
1430 (struct smb_com_readx_req *)pSMB;
1431 pSMBW->ByteCount = 0;
1434 iov[0].iov_base = (char *)pSMB;
1435 iov[0].iov_len = pSMB->hdr.smb_buf_length + 4;
1436 rc = SendReceive2(xid, tcon->ses, iov, 1 /* num iovecs */,
1437 &resp_buf_type, CIFS_STD_OP | CIFS_LOG_ERROR);
1438 cifs_stats_inc(&tcon->num_reads);
1439 pSMBr = (READ_RSP *)iov[0].iov_base;
1441 cERROR(1, ("Send error in read = %d", rc));
1443 int data_length = le16_to_cpu(pSMBr->DataLengthHigh);
1444 data_length = data_length << 16;
1445 data_length += le16_to_cpu(pSMBr->DataLength);
1446 *nbytes = data_length;
1448 /*check that DataLength would not go beyond end of SMB */
1449 if ((data_length > CIFSMaxBufSize)
1450 || (data_length > count)) {
1451 cFYI(1, ("bad length %d for count %d",
1452 data_length, count));
1456 pReadData = (char *) (&pSMBr->hdr.Protocol) +
1457 le16_to_cpu(pSMBr->DataOffset);
1458 /* if (rc = copy_to_user(buf, pReadData, data_length)) {
1459 cERROR(1,("Faulting on read rc = %d",rc));
1461 }*/ /* can not use copy_to_user when using page cache*/
1463 memcpy(*buf, pReadData, data_length);
1467 /* cifs_small_buf_release(pSMB); */ /* Freed earlier now in SendReceive2 */
1469 if (resp_buf_type == CIFS_SMALL_BUFFER)
1470 cifs_small_buf_release(iov[0].iov_base);
1471 else if (resp_buf_type == CIFS_LARGE_BUFFER)
1472 cifs_buf_release(iov[0].iov_base);
1473 } else if (resp_buf_type != CIFS_NO_BUFFER) {
1474 /* return buffer to caller to free */
1475 *buf = iov[0].iov_base;
1476 if (resp_buf_type == CIFS_SMALL_BUFFER)
1477 *pbuf_type = CIFS_SMALL_BUFFER;
1478 else if (resp_buf_type == CIFS_LARGE_BUFFER)
1479 *pbuf_type = CIFS_LARGE_BUFFER;
1480 } /* else no valid buffer on return - leave as null */
1482 /* Note: On -EAGAIN error only caller can retry on handle based calls
1483 since file handle passed in no longer valid */
1489 CIFSSMBWrite(const int xid, struct cifsTconInfo *tcon,
1490 const int netfid, const unsigned int count,
1491 const __u64 offset, unsigned int *nbytes, const char *buf,
1492 const char __user *ubuf, const int long_op)
1495 WRITE_REQ *pSMB = NULL;
1496 WRITE_RSP *pSMBr = NULL;
1497 int bytes_returned, wct;
1501 /* cFYI(1,("write at %lld %d bytes",offset,count));*/
1502 if (tcon->ses == NULL)
1503 return -ECONNABORTED;
1505 if (tcon->ses->capabilities & CAP_LARGE_FILES)
1510 rc = smb_init(SMB_COM_WRITE_ANDX, wct, tcon, (void **) &pSMB,
1514 /* tcon and ses pointer are checked in smb_init */
1515 if (tcon->ses->server == NULL)
1516 return -ECONNABORTED;
1518 pSMB->AndXCommand = 0xFF; /* none */
1520 pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF);
1522 pSMB->OffsetHigh = cpu_to_le32(offset >> 32);
1523 else if ((offset >> 32) > 0) /* can not handle big offset for old srv */
1526 pSMB->Reserved = 0xFFFFFFFF;
1527 pSMB->WriteMode = 0;
1528 pSMB->Remaining = 0;
1530 /* Can increase buffer size if buffer is big enough in some cases ie we
1531 can send more if LARGE_WRITE_X capability returned by the server and if
1532 our buffer is big enough or if we convert to iovecs on socket writes
1533 and eliminate the copy to the CIFS buffer */
1534 if (tcon->ses->capabilities & CAP_LARGE_WRITE_X) {
1535 bytes_sent = min_t(const unsigned int, CIFSMaxBufSize, count);
1537 bytes_sent = (tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE)
1541 if (bytes_sent > count)
1544 cpu_to_le16(offsetof(struct smb_com_write_req, Data) - 4);
1546 memcpy(pSMB->Data, buf, bytes_sent);
1548 if (copy_from_user(pSMB->Data, ubuf, bytes_sent)) {
1549 cifs_buf_release(pSMB);
1552 } else if (count != 0) {
1554 cifs_buf_release(pSMB);
1556 } /* else setting file size with write of zero bytes */
1558 byte_count = bytes_sent + 1; /* pad */
1559 else /* wct == 12 */ {
1560 byte_count = bytes_sent + 5; /* bigger pad, smaller smb hdr */
1562 pSMB->DataLengthLow = cpu_to_le16(bytes_sent & 0xFFFF);
1563 pSMB->DataLengthHigh = cpu_to_le16(bytes_sent >> 16);
1564 pSMB->hdr.smb_buf_length += byte_count;
1567 pSMB->ByteCount = cpu_to_le16(byte_count);
1568 else { /* old style write has byte count 4 bytes earlier
1570 struct smb_com_writex_req *pSMBW =
1571 (struct smb_com_writex_req *)pSMB;
1572 pSMBW->ByteCount = cpu_to_le16(byte_count);
1575 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1576 (struct smb_hdr *) pSMBr, &bytes_returned, long_op);
1577 cifs_stats_inc(&tcon->num_writes);
1579 cFYI(1, ("Send error in write = %d", rc));
1582 *nbytes = le16_to_cpu(pSMBr->CountHigh);
1583 *nbytes = (*nbytes) << 16;
1584 *nbytes += le16_to_cpu(pSMBr->Count);
1587 cifs_buf_release(pSMB);
1589 /* Note: On -EAGAIN error only caller can retry on handle based calls
1590 since file handle passed in no longer valid */
1596 CIFSSMBWrite2(const int xid, struct cifsTconInfo *tcon,
1597 const int netfid, const unsigned int count,
1598 const __u64 offset, unsigned int *nbytes, struct kvec *iov,
1599 int n_vec, const int long_op)
1602 WRITE_REQ *pSMB = NULL;
1605 int resp_buf_type = 0;
1607 cFYI(1, ("write2 at %lld %d bytes", (long long)offset, count));
1609 if (tcon->ses->capabilities & CAP_LARGE_FILES)
1613 rc = small_smb_init(SMB_COM_WRITE_ANDX, wct, tcon, (void **) &pSMB);
1616 /* tcon and ses pointer are checked in smb_init */
1617 if (tcon->ses->server == NULL)
1618 return -ECONNABORTED;
1620 pSMB->AndXCommand = 0xFF; /* none */
1622 pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF);
1624 pSMB->OffsetHigh = cpu_to_le32(offset >> 32);
1625 else if ((offset >> 32) > 0) /* can not handle big offset for old srv */
1627 pSMB->Reserved = 0xFFFFFFFF;
1628 pSMB->WriteMode = 0;
1629 pSMB->Remaining = 0;
1632 cpu_to_le16(offsetof(struct smb_com_write_req, Data) - 4);
1634 pSMB->DataLengthLow = cpu_to_le16(count & 0xFFFF);
1635 pSMB->DataLengthHigh = cpu_to_le16(count >> 16);
1636 smb_hdr_len = pSMB->hdr.smb_buf_length + 1; /* hdr + 1 byte pad */
1638 pSMB->hdr.smb_buf_length += count+1;
1639 else /* wct == 12 */
1640 pSMB->hdr.smb_buf_length += count+5; /* smb data starts later */
1642 pSMB->ByteCount = cpu_to_le16(count + 1);
1643 else /* wct == 12 */ /* bigger pad, smaller smb hdr, keep offset ok */ {
1644 struct smb_com_writex_req *pSMBW =
1645 (struct smb_com_writex_req *)pSMB;
1646 pSMBW->ByteCount = cpu_to_le16(count + 5);
1648 iov[0].iov_base = pSMB;
1650 iov[0].iov_len = smb_hdr_len + 4;
1651 else /* wct == 12 pad bigger by four bytes */
1652 iov[0].iov_len = smb_hdr_len + 8;
1655 rc = SendReceive2(xid, tcon->ses, iov, n_vec + 1, &resp_buf_type,
1657 cifs_stats_inc(&tcon->num_writes);
1659 cFYI(1, ("Send error Write2 = %d", rc));
1661 } else if (resp_buf_type == 0) {
1662 /* presumably this can not happen, but best to be safe */
1666 WRITE_RSP * pSMBr = (WRITE_RSP *)iov[0].iov_base;
1667 *nbytes = le16_to_cpu(pSMBr->CountHigh);
1668 *nbytes = (*nbytes) << 16;
1669 *nbytes += le16_to_cpu(pSMBr->Count);
1672 /* cifs_small_buf_release(pSMB); */ /* Freed earlier now in SendReceive2 */
1673 if (resp_buf_type == CIFS_SMALL_BUFFER)
1674 cifs_small_buf_release(iov[0].iov_base);
1675 else if (resp_buf_type == CIFS_LARGE_BUFFER)
1676 cifs_buf_release(iov[0].iov_base);
1678 /* Note: On -EAGAIN error only caller can retry on handle based calls
1679 since file handle passed in no longer valid */
1686 CIFSSMBLock(const int xid, struct cifsTconInfo *tcon,
1687 const __u16 smb_file_id, const __u64 len,
1688 const __u64 offset, const __u32 numUnlock,
1689 const __u32 numLock, const __u8 lockType, const int waitFlag)
1692 LOCK_REQ *pSMB = NULL;
1693 LOCK_RSP *pSMBr = NULL;
1698 cFYI(1, ("CIFSSMBLock timeout %d numLock %d", waitFlag, numLock));
1699 rc = small_smb_init(SMB_COM_LOCKING_ANDX, 8, tcon, (void **) &pSMB);
1704 pSMBr = (LOCK_RSP *)pSMB; /* BB removeme BB */
1706 if (lockType == LOCKING_ANDX_OPLOCK_RELEASE) {
1707 timeout = CIFS_ASYNC_OP; /* no response expected */
1709 } else if (waitFlag == TRUE) {
1710 timeout = CIFS_BLOCKING_OP; /* blocking operation, no timeout */
1711 pSMB->Timeout = cpu_to_le32(-1);/* blocking - do not time out */
1716 pSMB->NumberOfLocks = cpu_to_le16(numLock);
1717 pSMB->NumberOfUnlocks = cpu_to_le16(numUnlock);
1718 pSMB->LockType = lockType;
1719 pSMB->AndXCommand = 0xFF; /* none */
1720 pSMB->Fid = smb_file_id; /* netfid stays le */
1722 if ((numLock != 0) || (numUnlock != 0)) {
1723 pSMB->Locks[0].Pid = cpu_to_le16(current->tgid);
1724 /* BB where to store pid high? */
1725 pSMB->Locks[0].LengthLow = cpu_to_le32((u32)len);
1726 pSMB->Locks[0].LengthHigh = cpu_to_le32((u32)(len>>32));
1727 pSMB->Locks[0].OffsetLow = cpu_to_le32((u32)offset);
1728 pSMB->Locks[0].OffsetHigh = cpu_to_le32((u32)(offset>>32));
1729 count = sizeof(LOCKING_ANDX_RANGE);
1734 pSMB->hdr.smb_buf_length += count;
1735 pSMB->ByteCount = cpu_to_le16(count);
1738 rc = SendReceiveBlockingLock(xid, tcon, (struct smb_hdr *) pSMB,
1739 (struct smb_hdr *) pSMBr, &bytes_returned);
1740 cifs_small_buf_release(pSMB);
1742 rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *)pSMB,
1744 /* SMB buffer freed by function above */
1746 cifs_stats_inc(&tcon->num_locks);
1748 cFYI(1, ("Send error in Lock = %d", rc));
1751 /* Note: On -EAGAIN error only caller can retry on handle based calls
1752 since file handle passed in no longer valid */
1757 CIFSSMBPosixLock(const int xid, struct cifsTconInfo *tcon,
1758 const __u16 smb_file_id, const int get_flag, const __u64 len,
1759 struct file_lock *pLockData, const __u16 lock_type,
1762 struct smb_com_transaction2_sfi_req *pSMB = NULL;
1763 struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
1764 struct cifs_posix_lock *parm_data;
1767 int bytes_returned = 0;
1768 int resp_buf_type = 0;
1769 __u16 params, param_offset, offset, byte_count, count;
1772 cFYI(1, ("Posix Lock"));
1774 if (pLockData == NULL)
1777 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
1782 pSMBr = (struct smb_com_transaction2_sfi_rsp *)pSMB;
1785 pSMB->MaxSetupCount = 0;
1788 pSMB->Reserved2 = 0;
1789 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
1790 offset = param_offset + params;
1792 count = sizeof(struct cifs_posix_lock);
1793 pSMB->MaxParameterCount = cpu_to_le16(2);
1794 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB PDU from sess */
1795 pSMB->SetupCount = 1;
1796 pSMB->Reserved3 = 0;
1798 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION);
1800 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
1801 byte_count = 3 /* pad */ + params + count;
1802 pSMB->DataCount = cpu_to_le16(count);
1803 pSMB->ParameterCount = cpu_to_le16(params);
1804 pSMB->TotalDataCount = pSMB->DataCount;
1805 pSMB->TotalParameterCount = pSMB->ParameterCount;
1806 pSMB->ParameterOffset = cpu_to_le16(param_offset);
1807 parm_data = (struct cifs_posix_lock *)
1808 (((char *) &pSMB->hdr.Protocol) + offset);
1810 parm_data->lock_type = cpu_to_le16(lock_type);
1812 timeout = CIFS_BLOCKING_OP; /* blocking operation, no timeout */
1813 parm_data->lock_flags = cpu_to_le16(1);
1814 pSMB->Timeout = cpu_to_le32(-1);
1818 parm_data->pid = cpu_to_le32(current->tgid);
1819 parm_data->start = cpu_to_le64(pLockData->fl_start);
1820 parm_data->length = cpu_to_le64(len); /* normalize negative numbers */
1822 pSMB->DataOffset = cpu_to_le16(offset);
1823 pSMB->Fid = smb_file_id;
1824 pSMB->InformationLevel = cpu_to_le16(SMB_SET_POSIX_LOCK);
1825 pSMB->Reserved4 = 0;
1826 pSMB->hdr.smb_buf_length += byte_count;
1827 pSMB->ByteCount = cpu_to_le16(byte_count);
1829 rc = SendReceiveBlockingLock(xid, tcon, (struct smb_hdr *) pSMB,
1830 (struct smb_hdr *) pSMBr, &bytes_returned);
1832 iov[0].iov_base = (char *)pSMB;
1833 iov[0].iov_len = pSMB->hdr.smb_buf_length + 4;
1834 rc = SendReceive2(xid, tcon->ses, iov, 1 /* num iovecs */,
1835 &resp_buf_type, timeout);
1836 pSMB = NULL; /* request buf already freed by SendReceive2. Do
1837 not try to free it twice below on exit */
1838 pSMBr = (struct smb_com_transaction2_sfi_rsp *)iov[0].iov_base;
1842 cFYI(1, ("Send error in Posix Lock = %d", rc));
1843 } else if (get_flag) {
1844 /* lock structure can be returned on get */
1847 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
1849 if (rc || (pSMBr->ByteCount < sizeof(struct cifs_posix_lock))) {
1850 rc = -EIO; /* bad smb */
1853 if (pLockData == NULL) {
1857 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
1858 data_count = le16_to_cpu(pSMBr->t2.DataCount);
1859 if (data_count < sizeof(struct cifs_posix_lock)) {
1863 parm_data = (struct cifs_posix_lock *)
1864 ((char *)&pSMBr->hdr.Protocol + data_offset);
1865 if (parm_data->lock_type == cpu_to_le16(CIFS_UNLCK))
1866 pLockData->fl_type = F_UNLCK;
1871 cifs_small_buf_release(pSMB);
1873 if (resp_buf_type == CIFS_SMALL_BUFFER)
1874 cifs_small_buf_release(iov[0].iov_base);
1875 else if (resp_buf_type == CIFS_LARGE_BUFFER)
1876 cifs_buf_release(iov[0].iov_base);
1878 /* Note: On -EAGAIN error only caller can retry on handle based calls
1879 since file handle passed in no longer valid */
1886 CIFSSMBClose(const int xid, struct cifsTconInfo *tcon, int smb_file_id)
1889 CLOSE_REQ *pSMB = NULL;
1890 cFYI(1, ("In CIFSSMBClose"));
1892 /* do not retry on dead session on close */
1893 rc = small_smb_init(SMB_COM_CLOSE, 3, tcon, (void **) &pSMB);
1899 pSMB->FileID = (__u16) smb_file_id;
1900 pSMB->LastWriteTime = 0xFFFFFFFF;
1901 pSMB->ByteCount = 0;
1902 rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0);
1903 cifs_stats_inc(&tcon->num_closes);
1906 /* EINTR is expected when user ctl-c to kill app */
1907 cERROR(1, ("Send error in Close = %d", rc));
1911 /* Since session is dead, file will be closed on server already */
1919 CIFSSMBRename(const int xid, struct cifsTconInfo *tcon,
1920 const char *fromName, const char *toName,
1921 const struct nls_table *nls_codepage, int remap)
1924 RENAME_REQ *pSMB = NULL;
1925 RENAME_RSP *pSMBr = NULL;
1927 int name_len, name_len2;
1930 cFYI(1, ("In CIFSSMBRename"));
1932 rc = smb_init(SMB_COM_RENAME, 1, tcon, (void **) &pSMB,
1937 pSMB->BufferFormat = 0x04;
1938 pSMB->SearchAttributes =
1939 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
1942 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1944 cifsConvertToUCS((__le16 *) pSMB->OldFileName, fromName,
1945 PATH_MAX, nls_codepage, remap);
1946 name_len++; /* trailing null */
1948 pSMB->OldFileName[name_len] = 0x04; /* pad */
1949 /* protocol requires ASCII signature byte on Unicode string */
1950 pSMB->OldFileName[name_len + 1] = 0x00;
1952 cifsConvertToUCS((__le16 *) &pSMB->OldFileName[name_len + 2],
1953 toName, PATH_MAX, nls_codepage, remap);
1954 name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
1955 name_len2 *= 2; /* convert to bytes */
1956 } else { /* BB improve the check for buffer overruns BB */
1957 name_len = strnlen(fromName, PATH_MAX);
1958 name_len++; /* trailing null */
1959 strncpy(pSMB->OldFileName, fromName, name_len);
1960 name_len2 = strnlen(toName, PATH_MAX);
1961 name_len2++; /* trailing null */
1962 pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */
1963 strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2);
1964 name_len2++; /* trailing null */
1965 name_len2++; /* signature byte */
1968 count = 1 /* 1st signature byte */ + name_len + name_len2;
1969 pSMB->hdr.smb_buf_length += count;
1970 pSMB->ByteCount = cpu_to_le16(count);
1972 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1973 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1974 cifs_stats_inc(&tcon->num_renames);
1976 cFYI(1, ("Send error in rename = %d", rc));
1979 cifs_buf_release(pSMB);
1987 int CIFSSMBRenameOpenFile(const int xid, struct cifsTconInfo *pTcon,
1988 int netfid, char *target_name,
1989 const struct nls_table *nls_codepage, int remap)
1991 struct smb_com_transaction2_sfi_req *pSMB = NULL;
1992 struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
1993 struct set_file_rename *rename_info;
1995 char dummy_string[30];
1997 int bytes_returned = 0;
1999 __u16 params, param_offset, offset, count, byte_count;
2001 cFYI(1, ("Rename to File by handle"));
2002 rc = smb_init(SMB_COM_TRANSACTION2, 15, pTcon, (void **) &pSMB,
2008 pSMB->MaxSetupCount = 0;
2012 pSMB->Reserved2 = 0;
2013 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
2014 offset = param_offset + params;
2016 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
2017 rename_info = (struct set_file_rename *) data_offset;
2018 pSMB->MaxParameterCount = cpu_to_le16(2);
2019 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB PDU from sess */
2020 pSMB->SetupCount = 1;
2021 pSMB->Reserved3 = 0;
2022 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
2023 byte_count = 3 /* pad */ + params;
2024 pSMB->ParameterCount = cpu_to_le16(params);
2025 pSMB->TotalParameterCount = pSMB->ParameterCount;
2026 pSMB->ParameterOffset = cpu_to_le16(param_offset);
2027 pSMB->DataOffset = cpu_to_le16(offset);
2028 /* construct random name ".cifs_tmp<inodenum><mid>" */
2029 rename_info->overwrite = cpu_to_le32(1);
2030 rename_info->root_fid = 0;
2031 /* unicode only call */
2032 if (target_name == NULL) {
2033 sprintf(dummy_string, "cifs%x", pSMB->hdr.Mid);
2034 len_of_str = cifsConvertToUCS((__le16 *)rename_info->target_name,
2035 dummy_string, 24, nls_codepage, remap);
2037 len_of_str = cifsConvertToUCS((__le16 *)rename_info->target_name,
2038 target_name, PATH_MAX, nls_codepage,
2041 rename_info->target_name_len = cpu_to_le32(2 * len_of_str);
2042 count = 12 /* sizeof(struct set_file_rename) */ + (2 * len_of_str) + 2;
2043 byte_count += count;
2044 pSMB->DataCount = cpu_to_le16(count);
2045 pSMB->TotalDataCount = pSMB->DataCount;
2047 pSMB->InformationLevel =
2048 cpu_to_le16(SMB_SET_FILE_RENAME_INFORMATION);
2049 pSMB->Reserved4 = 0;
2050 pSMB->hdr.smb_buf_length += byte_count;
2051 pSMB->ByteCount = cpu_to_le16(byte_count);
2052 rc = SendReceive(xid, pTcon->ses, (struct smb_hdr *) pSMB,
2053 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2054 cifs_stats_inc(&pTcon->num_t2renames);
2056 cFYI(1, ("Send error in Rename (by file handle) = %d", rc));
2059 cifs_buf_release(pSMB);
2061 /* Note: On -EAGAIN error only caller can retry on handle based calls
2062 since file handle passed in no longer valid */
2068 CIFSSMBCopy(const int xid, struct cifsTconInfo *tcon, const char *fromName,
2069 const __u16 target_tid, const char *toName, const int flags,
2070 const struct nls_table *nls_codepage, int remap)
2073 COPY_REQ *pSMB = NULL;
2074 COPY_RSP *pSMBr = NULL;
2076 int name_len, name_len2;
2079 cFYI(1, ("In CIFSSMBCopy"));
2081 rc = smb_init(SMB_COM_COPY, 1, tcon, (void **) &pSMB,
2086 pSMB->BufferFormat = 0x04;
2087 pSMB->Tid2 = target_tid;
2089 pSMB->Flags = cpu_to_le16(flags & COPY_TREE);
2091 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2092 name_len = cifsConvertToUCS((__le16 *) pSMB->OldFileName,
2093 fromName, PATH_MAX, nls_codepage,
2095 name_len++; /* trailing null */
2097 pSMB->OldFileName[name_len] = 0x04; /* pad */
2098 /* protocol requires ASCII signature byte on Unicode string */
2099 pSMB->OldFileName[name_len + 1] = 0x00;
2101 cifsConvertToUCS((__le16 *)&pSMB->OldFileName[name_len + 2],
2102 toName, PATH_MAX, nls_codepage, remap);
2103 name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
2104 name_len2 *= 2; /* convert to bytes */
2105 } else { /* BB improve the check for buffer overruns BB */
2106 name_len = strnlen(fromName, PATH_MAX);
2107 name_len++; /* trailing null */
2108 strncpy(pSMB->OldFileName, fromName, name_len);
2109 name_len2 = strnlen(toName, PATH_MAX);
2110 name_len2++; /* trailing null */
2111 pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */
2112 strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2);
2113 name_len2++; /* trailing null */
2114 name_len2++; /* signature byte */
2117 count = 1 /* 1st signature byte */ + name_len + name_len2;
2118 pSMB->hdr.smb_buf_length += count;
2119 pSMB->ByteCount = cpu_to_le16(count);
2121 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2122 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2124 cFYI(1, ("Send error in copy = %d with %d files copied",
2125 rc, le16_to_cpu(pSMBr->CopyCount)));
2128 cifs_buf_release(pSMB);
2137 CIFSUnixCreateSymLink(const int xid, struct cifsTconInfo *tcon,
2138 const char *fromName, const char *toName,
2139 const struct nls_table *nls_codepage)
2141 TRANSACTION2_SPI_REQ *pSMB = NULL;
2142 TRANSACTION2_SPI_RSP *pSMBr = NULL;
2145 int name_len_target;
2147 int bytes_returned = 0;
2148 __u16 params, param_offset, offset, byte_count;
2150 cFYI(1, ("In Symlink Unix style"));
2152 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2157 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2159 cifs_strtoUCS((__le16 *) pSMB->FileName, fromName, PATH_MAX
2160 /* find define for this maxpathcomponent */
2162 name_len++; /* trailing null */
2165 } else { /* BB improve the check for buffer overruns BB */
2166 name_len = strnlen(fromName, PATH_MAX);
2167 name_len++; /* trailing null */
2168 strncpy(pSMB->FileName, fromName, name_len);
2170 params = 6 + name_len;
2171 pSMB->MaxSetupCount = 0;
2175 pSMB->Reserved2 = 0;
2176 param_offset = offsetof(struct smb_com_transaction2_spi_req,
2177 InformationLevel) - 4;
2178 offset = param_offset + params;
2180 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
2181 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2183 cifs_strtoUCS((__le16 *) data_offset, toName, PATH_MAX
2184 /* find define for this maxpathcomponent */
2186 name_len_target++; /* trailing null */
2187 name_len_target *= 2;
2188 } else { /* BB improve the check for buffer overruns BB */
2189 name_len_target = strnlen(toName, PATH_MAX);
2190 name_len_target++; /* trailing null */
2191 strncpy(data_offset, toName, name_len_target);
2194 pSMB->MaxParameterCount = cpu_to_le16(2);
2195 /* BB find exact max on data count below from sess */
2196 pSMB->MaxDataCount = cpu_to_le16(1000);
2197 pSMB->SetupCount = 1;
2198 pSMB->Reserved3 = 0;
2199 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
2200 byte_count = 3 /* pad */ + params + name_len_target;
2201 pSMB->DataCount = cpu_to_le16(name_len_target);
2202 pSMB->ParameterCount = cpu_to_le16(params);
2203 pSMB->TotalDataCount = pSMB->DataCount;
2204 pSMB->TotalParameterCount = pSMB->ParameterCount;
2205 pSMB->ParameterOffset = cpu_to_le16(param_offset);
2206 pSMB->DataOffset = cpu_to_le16(offset);
2207 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_LINK);
2208 pSMB->Reserved4 = 0;
2209 pSMB->hdr.smb_buf_length += byte_count;
2210 pSMB->ByteCount = cpu_to_le16(byte_count);
2211 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2212 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2213 cifs_stats_inc(&tcon->num_symlinks);
2215 cFYI(1, ("Send error in SetPathInfo create symlink = %d", rc));
2219 cifs_buf_release(pSMB);
2222 goto createSymLinkRetry;
2228 CIFSUnixCreateHardLink(const int xid, struct cifsTconInfo *tcon,
2229 const char *fromName, const char *toName,
2230 const struct nls_table *nls_codepage, int remap)
2232 TRANSACTION2_SPI_REQ *pSMB = NULL;
2233 TRANSACTION2_SPI_RSP *pSMBr = NULL;
2236 int name_len_target;
2238 int bytes_returned = 0;
2239 __u16 params, param_offset, offset, byte_count;
2241 cFYI(1, ("In Create Hard link Unix style"));
2242 createHardLinkRetry:
2243 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2248 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2249 name_len = cifsConvertToUCS((__le16 *) pSMB->FileName, toName,
2250 PATH_MAX, nls_codepage, remap);
2251 name_len++; /* trailing null */
2254 } else { /* BB improve the check for buffer overruns BB */
2255 name_len = strnlen(toName, PATH_MAX);
2256 name_len++; /* trailing null */
2257 strncpy(pSMB->FileName, toName, name_len);
2259 params = 6 + name_len;
2260 pSMB->MaxSetupCount = 0;
2264 pSMB->Reserved2 = 0;
2265 param_offset = offsetof(struct smb_com_transaction2_spi_req,
2266 InformationLevel) - 4;
2267 offset = param_offset + params;
2269 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
2270 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2272 cifsConvertToUCS((__le16 *) data_offset, fromName, PATH_MAX,
2273 nls_codepage, remap);
2274 name_len_target++; /* trailing null */
2275 name_len_target *= 2;
2276 } else { /* BB improve the check for buffer overruns BB */
2277 name_len_target = strnlen(fromName, PATH_MAX);
2278 name_len_target++; /* trailing null */
2279 strncpy(data_offset, fromName, name_len_target);
2282 pSMB->MaxParameterCount = cpu_to_le16(2);
2283 /* BB find exact max on data count below from sess*/
2284 pSMB->MaxDataCount = cpu_to_le16(1000);
2285 pSMB->SetupCount = 1;
2286 pSMB->Reserved3 = 0;
2287 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
2288 byte_count = 3 /* pad */ + params + name_len_target;
2289 pSMB->ParameterCount = cpu_to_le16(params);
2290 pSMB->TotalParameterCount = pSMB->ParameterCount;
2291 pSMB->DataCount = cpu_to_le16(name_len_target);
2292 pSMB->TotalDataCount = pSMB->DataCount;
2293 pSMB->ParameterOffset = cpu_to_le16(param_offset);
2294 pSMB->DataOffset = cpu_to_le16(offset);
2295 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_HLINK);
2296 pSMB->Reserved4 = 0;
2297 pSMB->hdr.smb_buf_length += byte_count;
2298 pSMB->ByteCount = cpu_to_le16(byte_count);
2299 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2300 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2301 cifs_stats_inc(&tcon->num_hardlinks);
2303 cFYI(1, ("Send error in SetPathInfo (hard link) = %d", rc));
2306 cifs_buf_release(pSMB);
2308 goto createHardLinkRetry;
2314 CIFSCreateHardLink(const int xid, struct cifsTconInfo *tcon,
2315 const char *fromName, const char *toName,
2316 const struct nls_table *nls_codepage, int remap)
2319 NT_RENAME_REQ *pSMB = NULL;
2320 RENAME_RSP *pSMBr = NULL;
2322 int name_len, name_len2;
2325 cFYI(1, ("In CIFSCreateHardLink"));
2326 winCreateHardLinkRetry:
2328 rc = smb_init(SMB_COM_NT_RENAME, 4, tcon, (void **) &pSMB,
2333 pSMB->SearchAttributes =
2334 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
2336 pSMB->Flags = cpu_to_le16(CREATE_HARD_LINK);
2337 pSMB->ClusterCount = 0;
2339 pSMB->BufferFormat = 0x04;
2341 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2343 cifsConvertToUCS((__le16 *) pSMB->OldFileName, fromName,
2344 PATH_MAX, nls_codepage, remap);
2345 name_len++; /* trailing null */
2347 pSMB->OldFileName[name_len] = 0; /* pad */
2348 pSMB->OldFileName[name_len + 1] = 0x04;
2350 cifsConvertToUCS((__le16 *)&pSMB->OldFileName[name_len + 2],
2351 toName, PATH_MAX, nls_codepage, remap);
2352 name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
2353 name_len2 *= 2; /* convert to bytes */
2354 } else { /* BB improve the check for buffer overruns BB */
2355 name_len = strnlen(fromName, PATH_MAX);
2356 name_len++; /* trailing null */
2357 strncpy(pSMB->OldFileName, fromName, name_len);
2358 name_len2 = strnlen(toName, PATH_MAX);
2359 name_len2++; /* trailing null */
2360 pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */
2361 strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2);
2362 name_len2++; /* trailing null */
2363 name_len2++; /* signature byte */
2366 count = 1 /* string type byte */ + name_len + name_len2;
2367 pSMB->hdr.smb_buf_length += count;
2368 pSMB->ByteCount = cpu_to_le16(count);
2370 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2371 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2372 cifs_stats_inc(&tcon->num_hardlinks);
2374 cFYI(1, ("Send error in hard link (NT rename) = %d", rc));
2376 cifs_buf_release(pSMB);
2378 goto winCreateHardLinkRetry;
2384 CIFSSMBUnixQuerySymLink(const int xid, struct cifsTconInfo *tcon,
2385 const unsigned char *searchName,
2386 char *symlinkinfo, const int buflen,
2387 const struct nls_table *nls_codepage)
2389 /* SMB_QUERY_FILE_UNIX_LINK */
2390 TRANSACTION2_QPI_REQ *pSMB = NULL;
2391 TRANSACTION2_QPI_RSP *pSMBr = NULL;
2395 __u16 params, byte_count;
2397 cFYI(1, ("In QPathSymLinkInfo (Unix) for path %s", searchName));
2400 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2405 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2407 cifs_strtoUCS((__le16 *) pSMB->FileName, searchName,
2408 PATH_MAX, nls_codepage);
2409 name_len++; /* trailing null */
2411 } else { /* BB improve the check for buffer overruns BB */
2412 name_len = strnlen(searchName, PATH_MAX);
2413 name_len++; /* trailing null */
2414 strncpy(pSMB->FileName, searchName, name_len);
2417 params = 2 /* level */ + 4 /* rsrvd */ + name_len /* incl null */ ;
2418 pSMB->TotalDataCount = 0;
2419 pSMB->MaxParameterCount = cpu_to_le16(2);
2420 /* BB find exact max data count below from sess structure BB */
2421 pSMB->MaxDataCount = cpu_to_le16(4000);
2422 pSMB->MaxSetupCount = 0;
2426 pSMB->Reserved2 = 0;
2427 pSMB->ParameterOffset = cpu_to_le16(offsetof(
2428 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
2429 pSMB->DataCount = 0;
2430 pSMB->DataOffset = 0;
2431 pSMB->SetupCount = 1;
2432 pSMB->Reserved3 = 0;
2433 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
2434 byte_count = params + 1 /* pad */ ;
2435 pSMB->TotalParameterCount = cpu_to_le16(params);
2436 pSMB->ParameterCount = pSMB->TotalParameterCount;
2437 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_LINK);
2438 pSMB->Reserved4 = 0;
2439 pSMB->hdr.smb_buf_length += byte_count;
2440 pSMB->ByteCount = cpu_to_le16(byte_count);
2442 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2443 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2445 cFYI(1, ("Send error in QuerySymLinkInfo = %d", rc));
2447 /* decode response */
2449 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
2450 if (rc || (pSMBr->ByteCount < 2))
2451 /* BB also check enough total bytes returned */
2452 rc = -EIO; /* bad smb */
2454 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
2455 __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
2457 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
2458 name_len = UniStrnlen((wchar_t *) ((char *)
2459 &pSMBr->hdr.Protocol + data_offset),
2460 min_t(const int, buflen, count) / 2);
2461 /* BB FIXME investigate remapping reserved chars here */
2462 cifs_strfromUCS_le(symlinkinfo,
2463 (__le16 *) ((char *)&pSMBr->hdr.Protocol
2465 name_len, nls_codepage);
2467 strncpy(symlinkinfo,
2468 (char *) &pSMBr->hdr.Protocol +
2470 min_t(const int, buflen, count));
2472 symlinkinfo[buflen] = 0;
2473 /* just in case so calling code does not go off the end of buffer */
2476 cifs_buf_release(pSMB);
2478 goto querySymLinkRetry;
2482 #ifdef CONFIG_CIFS_EXPERIMENTAL
2483 /* Initialize NT TRANSACT SMB into small smb request buffer.
2484 This assumes that all NT TRANSACTS that we init here have
2485 total parm and data under about 400 bytes (to fit in small cifs
2486 buffer size), which is the case so far, it easily fits. NB:
2487 Setup words themselves and ByteCount
2488 MaxSetupCount (size of returned setup area) and
2489 MaxParameterCount (returned parms size) must be set by caller */
2491 smb_init_nttransact(const __u16 sub_command, const int setup_count,
2492 const int parm_len, struct cifsTconInfo *tcon,
2497 struct smb_com_ntransact_req *pSMB;
2499 rc = small_smb_init(SMB_COM_NT_TRANSACT, 19 + setup_count, tcon,
2503 *ret_buf = (void *)pSMB;
2505 pSMB->TotalParameterCount = cpu_to_le32(parm_len);
2506 pSMB->TotalDataCount = 0;
2507 pSMB->MaxDataCount = cpu_to_le32((tcon->ses->server->maxBuf -
2508 MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
2509 pSMB->ParameterCount = pSMB->TotalParameterCount;
2510 pSMB->DataCount = pSMB->TotalDataCount;
2511 temp_offset = offsetof(struct smb_com_ntransact_req, Parms) +
2512 (setup_count * 2) - 4 /* for rfc1001 length itself */;
2513 pSMB->ParameterOffset = cpu_to_le32(temp_offset);
2514 pSMB->DataOffset = cpu_to_le32(temp_offset + parm_len);
2515 pSMB->SetupCount = setup_count; /* no need to le convert byte fields */
2516 pSMB->SubCommand = cpu_to_le16(sub_command);
2521 validate_ntransact(char *buf, char **ppparm, char **ppdata,
2522 __u32 *pparmlen, __u32 *pdatalen)
2525 __u32 data_count, data_offset, parm_count, parm_offset;
2526 struct smb_com_ntransact_rsp *pSMBr;
2534 pSMBr = (struct smb_com_ntransact_rsp *)buf;
2536 /* ByteCount was converted from little endian in SendReceive */
2537 end_of_smb = 2 /* sizeof byte count */ + pSMBr->ByteCount +
2538 (char *)&pSMBr->ByteCount;
2540 data_offset = le32_to_cpu(pSMBr->DataOffset);
2541 data_count = le32_to_cpu(pSMBr->DataCount);
2542 parm_offset = le32_to_cpu(pSMBr->ParameterOffset);
2543 parm_count = le32_to_cpu(pSMBr->ParameterCount);
2545 *ppparm = (char *)&pSMBr->hdr.Protocol + parm_offset;
2546 *ppdata = (char *)&pSMBr->hdr.Protocol + data_offset;
2548 /* should we also check that parm and data areas do not overlap? */
2549 if (*ppparm > end_of_smb) {
2550 cFYI(1, ("parms start after end of smb"));
2552 } else if (parm_count + *ppparm > end_of_smb) {
2553 cFYI(1, ("parm end after end of smb"));
2555 } else if (*ppdata > end_of_smb) {
2556 cFYI(1, ("data starts after end of smb"));
2558 } else if (data_count + *ppdata > end_of_smb) {
2559 cFYI(1, ("data %p + count %d (%p) ends after end of smb %p start %p",
2560 *ppdata, data_count, (data_count + *ppdata),
2561 end_of_smb, pSMBr));
2563 } else if (parm_count + data_count > pSMBr->ByteCount) {
2564 cFYI(1, ("parm count and data count larger than SMB"));
2567 *pdatalen = data_count;
2568 *pparmlen = parm_count;
2571 #endif /* CIFS_EXPERIMENTAL */
2574 CIFSSMBQueryReparseLinkInfo(const int xid, struct cifsTconInfo *tcon,
2575 const unsigned char *searchName,
2576 char *symlinkinfo, const int buflen, __u16 fid,
2577 const struct nls_table *nls_codepage)
2582 struct smb_com_transaction_ioctl_req *pSMB;
2583 struct smb_com_transaction_ioctl_rsp *pSMBr;
2585 cFYI(1, ("In Windows reparse style QueryLink for path %s", searchName));
2586 rc = smb_init(SMB_COM_NT_TRANSACT, 23, tcon, (void **) &pSMB,
2591 pSMB->TotalParameterCount = 0 ;
2592 pSMB->TotalDataCount = 0;
2593 pSMB->MaxParameterCount = cpu_to_le32(2);
2594 /* BB find exact data count max from sess structure BB */
2595 pSMB->MaxDataCount = cpu_to_le32((tcon->ses->server->maxBuf -
2596 MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
2597 pSMB->MaxSetupCount = 4;
2599 pSMB->ParameterOffset = 0;
2600 pSMB->DataCount = 0;
2601 pSMB->DataOffset = 0;
2602 pSMB->SetupCount = 4;
2603 pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_IOCTL);
2604 pSMB->ParameterCount = pSMB->TotalParameterCount;
2605 pSMB->FunctionCode = cpu_to_le32(FSCTL_GET_REPARSE_POINT);
2606 pSMB->IsFsctl = 1; /* FSCTL */
2607 pSMB->IsRootFlag = 0;
2608 pSMB->Fid = fid; /* file handle always le */
2609 pSMB->ByteCount = 0;
2611 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2612 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2614 cFYI(1, ("Send error in QueryReparseLinkInfo = %d", rc));
2615 } else { /* decode response */
2616 __u32 data_offset = le32_to_cpu(pSMBr->DataOffset);
2617 __u32 data_count = le32_to_cpu(pSMBr->DataCount);
2618 if ((pSMBr->ByteCount < 2) || (data_offset > 512))
2619 /* BB also check enough total bytes returned */
2620 rc = -EIO; /* bad smb */
2622 if (data_count && (data_count < 2048)) {
2623 char *end_of_smb = 2 /* sizeof byte count */ +
2625 (char *)&pSMBr->ByteCount;
2627 struct reparse_data *reparse_buf =
2628 (struct reparse_data *)
2629 ((char *)&pSMBr->hdr.Protocol
2631 if ((char *)reparse_buf >= end_of_smb) {
2635 if ((reparse_buf->LinkNamesBuf +
2636 reparse_buf->TargetNameOffset +
2637 reparse_buf->TargetNameLen) >
2639 cFYI(1, ("reparse buf beyond SMB"));
2644 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
2645 name_len = UniStrnlen((wchar_t *)
2646 (reparse_buf->LinkNamesBuf +
2647 reparse_buf->TargetNameOffset),
2649 reparse_buf->TargetNameLen / 2));
2650 cifs_strfromUCS_le(symlinkinfo,
2651 (__le16 *) (reparse_buf->LinkNamesBuf +
2652 reparse_buf->TargetNameOffset),
2653 name_len, nls_codepage);
2654 } else { /* ASCII names */
2655 strncpy(symlinkinfo,
2656 reparse_buf->LinkNamesBuf +
2657 reparse_buf->TargetNameOffset,
2658 min_t(const int, buflen,
2659 reparse_buf->TargetNameLen));
2663 cFYI(1, ("Invalid return data count on "
2664 "get reparse info ioctl"));
2666 symlinkinfo[buflen] = 0; /* just in case so the caller
2667 does not go off the end of the buffer */
2668 cFYI(1, ("readlink result - %s", symlinkinfo));
2672 cifs_buf_release(pSMB);
2674 /* Note: On -EAGAIN error only caller can retry on handle based calls
2675 since file handle passed in no longer valid */
2680 #ifdef CONFIG_CIFS_POSIX
2682 /*Convert an Access Control Entry from wire format to local POSIX xattr format*/
2683 static void cifs_convert_ace(posix_acl_xattr_entry *ace,
2684 struct cifs_posix_ace *cifs_ace)
2686 /* u8 cifs fields do not need le conversion */
2687 ace->e_perm = cpu_to_le16(cifs_ace->cifs_e_perm);
2688 ace->e_tag = cpu_to_le16(cifs_ace->cifs_e_tag);
2689 ace->e_id = cpu_to_le32(le64_to_cpu(cifs_ace->cifs_uid));
2690 /* cFYI(1,("perm %d tag %d id %d",ace->e_perm,ace->e_tag,ace->e_id)); */
2695 /* Convert ACL from CIFS POSIX wire format to local Linux POSIX ACL xattr */
2696 static int cifs_copy_posix_acl(char *trgt, char *src, const int buflen,
2697 const int acl_type, const int size_of_data_area)
2702 struct cifs_posix_ace *pACE;
2703 struct cifs_posix_acl *cifs_acl = (struct cifs_posix_acl *)src;
2704 posix_acl_xattr_header *local_acl = (posix_acl_xattr_header *)trgt;
2706 if (le16_to_cpu(cifs_acl->version) != CIFS_ACL_VERSION)
2709 if (acl_type & ACL_TYPE_ACCESS) {
2710 count = le16_to_cpu(cifs_acl->access_entry_count);
2711 pACE = &cifs_acl->ace_array[0];
2712 size = sizeof(struct cifs_posix_acl);
2713 size += sizeof(struct cifs_posix_ace) * count;
2714 /* check if we would go beyond end of SMB */
2715 if (size_of_data_area < size) {
2716 cFYI(1, ("bad CIFS POSIX ACL size %d vs. %d",
2717 size_of_data_area, size));
2720 } else if (acl_type & ACL_TYPE_DEFAULT) {
2721 count = le16_to_cpu(cifs_acl->access_entry_count);
2722 size = sizeof(struct cifs_posix_acl);
2723 size += sizeof(struct cifs_posix_ace) * count;
2724 /* skip past access ACEs to get to default ACEs */
2725 pACE = &cifs_acl->ace_array[count];
2726 count = le16_to_cpu(cifs_acl->default_entry_count);
2727 size += sizeof(struct cifs_posix_ace) * count;
2728 /* check if we would go beyond end of SMB */
2729 if (size_of_data_area < size)
2736 size = posix_acl_xattr_size(count);
2737 if ((buflen == 0) || (local_acl == NULL)) {
2738 /* used to query ACL EA size */
2739 } else if (size > buflen) {
2741 } else /* buffer big enough */ {
2742 local_acl->a_version = cpu_to_le32(POSIX_ACL_XATTR_VERSION);
2743 for (i = 0; i < count ; i++) {
2744 cifs_convert_ace(&local_acl->a_entries[i], pACE);
2751 static __u16 convert_ace_to_cifs_ace(struct cifs_posix_ace *cifs_ace,
2752 const posix_acl_xattr_entry *local_ace)
2754 __u16 rc = 0; /* 0 = ACL converted ok */
2756 cifs_ace->cifs_e_perm = le16_to_cpu(local_ace->e_perm);
2757 cifs_ace->cifs_e_tag = le16_to_cpu(local_ace->e_tag);
2758 /* BB is there a better way to handle the large uid? */
2759 if (local_ace->e_id == cpu_to_le32(-1)) {
2760 /* Probably no need to le convert -1 on any arch but can not hurt */
2761 cifs_ace->cifs_uid = cpu_to_le64(-1);
2763 cifs_ace->cifs_uid = cpu_to_le64(le32_to_cpu(local_ace->e_id));
2764 /*cFYI(1,("perm %d tag %d id %d",ace->e_perm,ace->e_tag,ace->e_id));*/
2768 /* Convert ACL from local Linux POSIX xattr to CIFS POSIX ACL wire format */
2769 static __u16 ACL_to_cifs_posix(char *parm_data, const char *pACL,
2770 const int buflen, const int acl_type)
2773 struct cifs_posix_acl *cifs_acl = (struct cifs_posix_acl *)parm_data;
2774 posix_acl_xattr_header *local_acl = (posix_acl_xattr_header *)pACL;
2778 if ((buflen == 0) || (pACL == NULL) || (cifs_acl == NULL))
2781 count = posix_acl_xattr_count((size_t)buflen);
2782 cFYI(1, ("setting acl with %d entries from buf of length %d and "
2784 count, buflen, le32_to_cpu(local_acl->a_version)));
2785 if (le32_to_cpu(local_acl->a_version) != 2) {
2786 cFYI(1, ("unknown POSIX ACL version %d",
2787 le32_to_cpu(local_acl->a_version)));
2790 cifs_acl->version = cpu_to_le16(1);
2791 if (acl_type == ACL_TYPE_ACCESS)
2792 cifs_acl->access_entry_count = cpu_to_le16(count);
2793 else if (acl_type == ACL_TYPE_DEFAULT)
2794 cifs_acl->default_entry_count = cpu_to_le16(count);
2796 cFYI(1, ("unknown ACL type %d", acl_type));
2799 for (i = 0; i < count; i++) {
2800 rc = convert_ace_to_cifs_ace(&cifs_acl->ace_array[i],
2801 &local_acl->a_entries[i]);
2803 /* ACE not converted */
2808 rc = (__u16)(count * sizeof(struct cifs_posix_ace));
2809 rc += sizeof(struct cifs_posix_acl);
2810 /* BB add check to make sure ACL does not overflow SMB */
2816 CIFSSMBGetPosixACL(const int xid, struct cifsTconInfo *tcon,
2817 const unsigned char *searchName,
2818 char *acl_inf, const int buflen, const int acl_type,
2819 const struct nls_table *nls_codepage, int remap)
2821 /* SMB_QUERY_POSIX_ACL */
2822 TRANSACTION2_QPI_REQ *pSMB = NULL;
2823 TRANSACTION2_QPI_RSP *pSMBr = NULL;
2827 __u16 params, byte_count;
2829 cFYI(1, ("In GetPosixACL (Unix) for path %s", searchName));
2832 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2837 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2839 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
2840 PATH_MAX, nls_codepage, remap);
2841 name_len++; /* trailing null */
2843 pSMB->FileName[name_len] = 0;
2844 pSMB->FileName[name_len+1] = 0;
2845 } else { /* BB improve the check for buffer overruns BB */
2846 name_len = strnlen(searchName, PATH_MAX);
2847 name_len++; /* trailing null */
2848 strncpy(pSMB->FileName, searchName, name_len);
2851 params = 2 /* level */ + 4 /* rsrvd */ + name_len /* incl null */ ;
2852 pSMB->TotalDataCount = 0;
2853 pSMB->MaxParameterCount = cpu_to_le16(2);
2854 /* BB find exact max data count below from sess structure BB */
2855 pSMB->MaxDataCount = cpu_to_le16(4000);
2856 pSMB->MaxSetupCount = 0;
2860 pSMB->Reserved2 = 0;
2861 pSMB->ParameterOffset = cpu_to_le16(
2862 offsetof(struct smb_com_transaction2_qpi_req,
2863 InformationLevel) - 4);
2864 pSMB->DataCount = 0;
2865 pSMB->DataOffset = 0;
2866 pSMB->SetupCount = 1;
2867 pSMB->Reserved3 = 0;
2868 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
2869 byte_count = params + 1 /* pad */ ;
2870 pSMB->TotalParameterCount = cpu_to_le16(params);
2871 pSMB->ParameterCount = pSMB->TotalParameterCount;
2872 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_POSIX_ACL);
2873 pSMB->Reserved4 = 0;
2874 pSMB->hdr.smb_buf_length += byte_count;
2875 pSMB->ByteCount = cpu_to_le16(byte_count);
2877 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2878 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2879 cifs_stats_inc(&tcon->num_acl_get);
2881 cFYI(1, ("Send error in Query POSIX ACL = %d", rc));
2883 /* decode response */
2885 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
2886 if (rc || (pSMBr->ByteCount < 2))
2887 /* BB also check enough total bytes returned */
2888 rc = -EIO; /* bad smb */
2890 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
2891 __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
2892 rc = cifs_copy_posix_acl(acl_inf,
2893 (char *)&pSMBr->hdr.Protocol+data_offset,
2894 buflen, acl_type, count);
2897 cifs_buf_release(pSMB);
2904 CIFSSMBSetPosixACL(const int xid, struct cifsTconInfo *tcon,
2905 const unsigned char *fileName,
2906 const char *local_acl, const int buflen,
2908 const struct nls_table *nls_codepage, int remap)
2910 struct smb_com_transaction2_spi_req *pSMB = NULL;
2911 struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
2915 int bytes_returned = 0;
2916 __u16 params, byte_count, data_count, param_offset, offset;
2918 cFYI(1, ("In SetPosixACL (Unix) for path %s", fileName));
2920 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2924 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2926 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
2927 PATH_MAX, nls_codepage, remap);
2928 name_len++; /* trailing null */
2930 } else { /* BB improve the check for buffer overruns BB */
2931 name_len = strnlen(fileName, PATH_MAX);
2932 name_len++; /* trailing null */
2933 strncpy(pSMB->FileName, fileName, name_len);
2935 params = 6 + name_len;
2936 pSMB->MaxParameterCount = cpu_to_le16(2);
2937 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB size from sess */
2938 pSMB->MaxSetupCount = 0;
2942 pSMB->Reserved2 = 0;
2943 param_offset = offsetof(struct smb_com_transaction2_spi_req,
2944 InformationLevel) - 4;
2945 offset = param_offset + params;
2946 parm_data = ((char *) &pSMB->hdr.Protocol) + offset;
2947 pSMB->ParameterOffset = cpu_to_le16(param_offset);
2949 /* convert to on the wire format for POSIX ACL */
2950 data_count = ACL_to_cifs_posix(parm_data, local_acl, buflen, acl_type);
2952 if (data_count == 0) {
2954 goto setACLerrorExit;
2956 pSMB->DataOffset = cpu_to_le16(offset);
2957 pSMB->SetupCount = 1;
2958 pSMB->Reserved3 = 0;
2959 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
2960 pSMB->InformationLevel = cpu_to_le16(SMB_SET_POSIX_ACL);
2961 byte_count = 3 /* pad */ + params + data_count;
2962 pSMB->DataCount = cpu_to_le16(data_count);
2963 pSMB->TotalDataCount = pSMB->DataCount;
2964 pSMB->ParameterCount = cpu_to_le16(params);
2965 pSMB->TotalParameterCount = pSMB->ParameterCount;
2966 pSMB->Reserved4 = 0;
2967 pSMB->hdr.smb_buf_length += byte_count;
2968 pSMB->ByteCount = cpu_to_le16(byte_count);
2969 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2970 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2972 cFYI(1, ("Set POSIX ACL returned %d", rc));
2976 cifs_buf_release(pSMB);
2982 /* BB fix tabs in this function FIXME BB */
2984 CIFSGetExtAttr(const int xid, struct cifsTconInfo *tcon,
2985 const int netfid, __u64 * pExtAttrBits, __u64 *pMask)
2988 struct smb_t2_qfi_req *pSMB = NULL;
2989 struct smb_t2_qfi_rsp *pSMBr = NULL;
2991 __u16 params, byte_count;
2993 cFYI(1, ("In GetExtAttr"));
2998 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3003 params = 2 /* level */ +2 /* fid */;
3004 pSMB->t2.TotalDataCount = 0;
3005 pSMB->t2.MaxParameterCount = cpu_to_le16(4);
3006 /* BB find exact max data count below from sess structure BB */
3007 pSMB->t2.MaxDataCount = cpu_to_le16(4000);
3008 pSMB->t2.MaxSetupCount = 0;
3009 pSMB->t2.Reserved = 0;
3011 pSMB->t2.Timeout = 0;
3012 pSMB->t2.Reserved2 = 0;
3013 pSMB->t2.ParameterOffset = cpu_to_le16(offsetof(struct smb_t2_qfi_req,
3015 pSMB->t2.DataCount = 0;
3016 pSMB->t2.DataOffset = 0;
3017 pSMB->t2.SetupCount = 1;
3018 pSMB->t2.Reserved3 = 0;
3019 pSMB->t2.SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION);
3020 byte_count = params + 1 /* pad */ ;
3021 pSMB->t2.TotalParameterCount = cpu_to_le16(params);
3022 pSMB->t2.ParameterCount = pSMB->t2.TotalParameterCount;
3023 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_ATTR_FLAGS);
3026 pSMB->hdr.smb_buf_length += byte_count;
3027 pSMB->t2.ByteCount = cpu_to_le16(byte_count);
3029 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3030 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3032 cFYI(1, ("error %d in GetExtAttr", rc));
3034 /* decode response */
3035 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3036 if (rc || (pSMBr->ByteCount < 2))
3037 /* BB also check enough total bytes returned */
3038 /* If rc should we check for EOPNOSUPP and
3039 disable the srvino flag? or in caller? */
3040 rc = -EIO; /* bad smb */
3042 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3043 __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
3044 struct file_chattr_info *pfinfo;
3045 /* BB Do we need a cast or hash here ? */
3047 cFYI(1, ("Illegal size ret in GetExtAttr"));
3051 pfinfo = (struct file_chattr_info *)
3052 (data_offset + (char *) &pSMBr->hdr.Protocol);
3053 *pExtAttrBits = le64_to_cpu(pfinfo->mode);
3054 *pMask = le64_to_cpu(pfinfo->mask);
3058 cifs_buf_release(pSMB);
3060 goto GetExtAttrRetry;
3064 #endif /* CONFIG_POSIX */
3066 #ifdef CONFIG_CIFS_EXPERIMENTAL
3067 /* Get Security Descriptor (by handle) from remote server for a file or dir */
3069 CIFSSMBGetCIFSACL(const int xid, struct cifsTconInfo *tcon, __u16 fid,
3070 struct cifs_ntsd **acl_inf, __u32 *pbuflen)
3074 QUERY_SEC_DESC_REQ * pSMB;
3077 cFYI(1, ("GetCifsACL"));
3082 rc = smb_init_nttransact(NT_TRANSACT_QUERY_SECURITY_DESC, 0,
3083 8 /* parm len */, tcon, (void **) &pSMB);
3087 pSMB->MaxParameterCount = cpu_to_le32(4);
3088 /* BB TEST with big acls that might need to be e.g. larger than 16K */
3089 pSMB->MaxSetupCount = 0;
3090 pSMB->Fid = fid; /* file handle always le */
3091 pSMB->AclFlags = cpu_to_le32(CIFS_ACL_OWNER | CIFS_ACL_GROUP |
3093 pSMB->ByteCount = cpu_to_le16(11); /* 3 bytes pad + 8 bytes parm */
3094 pSMB->hdr.smb_buf_length += 11;
3095 iov[0].iov_base = (char *)pSMB;
3096 iov[0].iov_len = pSMB->hdr.smb_buf_length + 4;
3098 rc = SendReceive2(xid, tcon->ses, iov, 1 /* num iovec */, &buf_type,
3100 cifs_stats_inc(&tcon->num_acl_get);
3102 cFYI(1, ("Send error in QuerySecDesc = %d", rc));
3103 } else { /* decode response */
3107 struct smb_com_ntransact_rsp *pSMBr;
3110 /* validate_nttransact */
3111 rc = validate_ntransact(iov[0].iov_base, (char **)&parm,
3112 &pdata, &parm_len, pbuflen);
3115 pSMBr = (struct smb_com_ntransact_rsp *)iov[0].iov_base;
3117 cFYI(1, ("smb %p parm %p data %p", pSMBr, parm, *acl_inf));
3119 if (le32_to_cpu(pSMBr->ParameterCount) != 4) {
3120 rc = -EIO; /* bad smb */
3125 /* BB check that data area is minimum length and as big as acl_len */
3127 acl_len = le32_to_cpu(*parm);
3128 if (acl_len != *pbuflen) {
3129 cERROR(1, ("acl length %d does not match %d",
3130 acl_len, *pbuflen));
3131 if (*pbuflen > acl_len)
3135 /* check if buffer is big enough for the acl
3136 header followed by the smallest SID */
3137 if ((*pbuflen < sizeof(struct cifs_ntsd) + 8) ||
3138 (*pbuflen >= 64 * 1024)) {
3139 cERROR(1, ("bad acl length %d", *pbuflen));
3143 *acl_inf = kmalloc(*pbuflen, GFP_KERNEL);
3144 if (*acl_inf == NULL) {
3148 memcpy(*acl_inf, pdata, *pbuflen);
3152 if (buf_type == CIFS_SMALL_BUFFER)
3153 cifs_small_buf_release(iov[0].iov_base);
3154 else if (buf_type == CIFS_LARGE_BUFFER)
3155 cifs_buf_release(iov[0].iov_base);
3156 /* cifs_small_buf_release(pSMB); */ /* Freed earlier now in SendReceive2 */
3161 CIFSSMBSetCIFSACL(const int xid, struct cifsTconInfo *tcon, __u16 fid,
3162 struct cifs_ntsd *pntsd, __u32 acllen)
3164 __u16 byte_count, param_count, data_count, param_offset, data_offset;
3166 int bytes_returned = 0;
3167 SET_SEC_DESC_REQ *pSMB = NULL;
3168 NTRANSACT_RSP *pSMBr = NULL;
3171 rc = smb_init(SMB_COM_NT_TRANSACT, 19, tcon, (void **) &pSMB,
3176 pSMB->MaxSetupCount = 0;
3180 param_offset = offsetof(struct smb_com_transaction_ssec_req, Fid) - 4;
3181 data_count = acllen;
3182 data_offset = param_offset + param_count;
3183 byte_count = 3 /* pad */ + param_count;
3185 pSMB->DataCount = cpu_to_le32(data_count);
3186 pSMB->TotalDataCount = pSMB->DataCount;
3187 pSMB->MaxParameterCount = cpu_to_le32(4);
3188 pSMB->MaxDataCount = cpu_to_le32(16384);
3189 pSMB->ParameterCount = cpu_to_le32(param_count);
3190 pSMB->ParameterOffset = cpu_to_le32(param_offset);
3191 pSMB->TotalParameterCount = pSMB->ParameterCount;
3192 pSMB->DataOffset = cpu_to_le32(data_offset);
3193 pSMB->SetupCount = 0;
3194 pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_SET_SECURITY_DESC);
3195 pSMB->ByteCount = cpu_to_le16(byte_count+data_count);
3197 pSMB->Fid = fid; /* file handle always le */
3198 pSMB->Reserved2 = 0;
3199 pSMB->AclFlags = cpu_to_le32(CIFS_ACL_DACL);
3201 if (pntsd && acllen) {
3202 memcpy((char *) &pSMBr->hdr.Protocol + data_offset,
3205 pSMB->hdr.smb_buf_length += (byte_count + data_count);
3208 pSMB->hdr.smb_buf_length += byte_count;
3210 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3211 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3213 cFYI(1, ("SetCIFSACL bytes_returned: %d, rc: %d", bytes_returned, rc));
3215 cFYI(1, ("Set CIFS ACL returned %d", rc));
3216 cifs_buf_release(pSMB);
3219 goto setCifsAclRetry;
3224 #endif /* CONFIG_CIFS_EXPERIMENTAL */
3226 /* Legacy Query Path Information call for lookup to old servers such
3228 int SMBQueryInformation(const int xid, struct cifsTconInfo *tcon,
3229 const unsigned char *searchName,
3230 FILE_ALL_INFO *pFinfo,
3231 const struct nls_table *nls_codepage, int remap)
3233 QUERY_INFORMATION_REQ * pSMB;
3234 QUERY_INFORMATION_RSP * pSMBr;
3239 cFYI(1, ("In SMBQPath path %s", searchName));
3241 rc = smb_init(SMB_COM_QUERY_INFORMATION, 0, tcon, (void **) &pSMB,
3246 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3248 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
3249 PATH_MAX, nls_codepage, remap);
3250 name_len++; /* trailing null */
3253 name_len = strnlen(searchName, PATH_MAX);
3254 name_len++; /* trailing null */
3255 strncpy(pSMB->FileName, searchName, name_len);
3257 pSMB->BufferFormat = 0x04;
3258 name_len++; /* account for buffer type byte */
3259 pSMB->hdr.smb_buf_length += (__u16) name_len;
3260 pSMB->ByteCount = cpu_to_le16(name_len);
3262 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3263 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3265 cFYI(1, ("Send error in QueryInfo = %d", rc));
3266 } else if (pFinfo) { /* decode response */
3268 __u32 time = le32_to_cpu(pSMBr->last_write_time);
3269 /* BB FIXME - add time zone adjustment BB */
3270 memset(pFinfo, 0, sizeof(FILE_ALL_INFO));
3273 /* decode time fields */
3274 pFinfo->ChangeTime = cpu_to_le64(cifs_UnixTimeToNT(ts));
3275 pFinfo->LastWriteTime = pFinfo->ChangeTime;
3276 pFinfo->LastAccessTime = 0;
3277 pFinfo->AllocationSize =
3278 cpu_to_le64(le32_to_cpu(pSMBr->size));
3279 pFinfo->EndOfFile = pFinfo->AllocationSize;
3280 pFinfo->Attributes =
3281 cpu_to_le32(le16_to_cpu(pSMBr->attr));
3283 rc = -EIO; /* bad buffer passed in */
3285 cifs_buf_release(pSMB);
3297 CIFSSMBQPathInfo(const int xid, struct cifsTconInfo *tcon,
3298 const unsigned char *searchName,
3299 FILE_ALL_INFO * pFindData,
3300 int legacy /* old style infolevel */,
3301 const struct nls_table *nls_codepage, int remap)
3303 /* level 263 SMB_QUERY_FILE_ALL_INFO */
3304 TRANSACTION2_QPI_REQ *pSMB = NULL;
3305 TRANSACTION2_QPI_RSP *pSMBr = NULL;
3309 __u16 params, byte_count;
3311 /* cFYI(1, ("In QPathInfo path %s", searchName)); */
3313 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3318 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3320 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
3321 PATH_MAX, nls_codepage, remap);
3322 name_len++; /* trailing null */
3324 } else { /* BB improve the check for buffer overruns BB */
3325 name_len = strnlen(searchName, PATH_MAX);
3326 name_len++; /* trailing null */
3327 strncpy(pSMB->FileName, searchName, name_len);
3330 params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */;
3331 pSMB->TotalDataCount = 0;
3332 pSMB->MaxParameterCount = cpu_to_le16(2);
3333 pSMB->MaxDataCount = cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
3334 pSMB->MaxSetupCount = 0;
3338 pSMB->Reserved2 = 0;
3339 pSMB->ParameterOffset = cpu_to_le16(offsetof(
3340 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
3341 pSMB->DataCount = 0;
3342 pSMB->DataOffset = 0;
3343 pSMB->SetupCount = 1;
3344 pSMB->Reserved3 = 0;
3345 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
3346 byte_count = params + 1 /* pad */ ;
3347 pSMB->TotalParameterCount = cpu_to_le16(params);
3348 pSMB->ParameterCount = pSMB->TotalParameterCount;
3350 pSMB->InformationLevel = cpu_to_le16(SMB_INFO_STANDARD);
3352 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_ALL_INFO);
3353 pSMB->Reserved4 = 0;
3354 pSMB->hdr.smb_buf_length += byte_count;
3355 pSMB->ByteCount = cpu_to_le16(byte_count);
3357 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3358 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3360 cFYI(1, ("Send error in QPathInfo = %d", rc));
3361 } else { /* decode response */
3362 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3364 if (rc) /* BB add auto retry on EOPNOTSUPP? */
3366 else if (!legacy && (pSMBr->ByteCount < 40))
3367 rc = -EIO; /* bad smb */
3368 else if (legacy && (pSMBr->ByteCount < 24))
3369 rc = -EIO; /* 24 or 26 expected but we do not read
3371 else if (pFindData) {
3373 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3374 if (legacy) /* we do not read the last field, EAsize,
3375 fortunately since it varies by subdialect
3376 and on Set vs. Get, is two bytes or 4
3377 bytes depending but we don't care here */
3378 size = sizeof(FILE_INFO_STANDARD);
3380 size = sizeof(FILE_ALL_INFO);
3381 memcpy((char *) pFindData,
3382 (char *) &pSMBr->hdr.Protocol +
3387 cifs_buf_release(pSMB);
3389 goto QPathInfoRetry;
3395 CIFSSMBUnixQPathInfo(const int xid, struct cifsTconInfo *tcon,
3396 const unsigned char *searchName,
3397 FILE_UNIX_BASIC_INFO * pFindData,
3398 const struct nls_table *nls_codepage, int remap)
3400 /* SMB_QUERY_FILE_UNIX_BASIC */
3401 TRANSACTION2_QPI_REQ *pSMB = NULL;
3402 TRANSACTION2_QPI_RSP *pSMBr = NULL;
3404 int bytes_returned = 0;
3406 __u16 params, byte_count;
3408 cFYI(1, ("In QPathInfo (Unix) the path %s", searchName));
3410 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3415 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3417 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
3418 PATH_MAX, nls_codepage, remap);
3419 name_len++; /* trailing null */
3421 } else { /* BB improve the check for buffer overruns BB */
3422 name_len = strnlen(searchName, PATH_MAX);
3423 name_len++; /* trailing null */
3424 strncpy(pSMB->FileName, searchName, name_len);
3427 params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */;
3428 pSMB->TotalDataCount = 0;
3429 pSMB->MaxParameterCount = cpu_to_le16(2);
3430 /* BB find exact max SMB PDU from sess structure BB */
3431 pSMB->MaxDataCount = cpu_to_le16(4000);
3432 pSMB->MaxSetupCount = 0;
3436 pSMB->Reserved2 = 0;
3437 pSMB->ParameterOffset = cpu_to_le16(offsetof(
3438 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
3439 pSMB->DataCount = 0;
3440 pSMB->DataOffset = 0;
3441 pSMB->SetupCount = 1;
3442 pSMB->Reserved3 = 0;
3443 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
3444 byte_count = params + 1 /* pad */ ;
3445 pSMB->TotalParameterCount = cpu_to_le16(params);
3446 pSMB->ParameterCount = pSMB->TotalParameterCount;
3447 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC);
3448 pSMB->Reserved4 = 0;
3449 pSMB->hdr.smb_buf_length += byte_count;
3450 pSMB->ByteCount = cpu_to_le16(byte_count);
3452 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3453 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3455 cFYI(1, ("Send error in QPathInfo = %d", rc));
3456 } else { /* decode response */
3457 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3459 if (rc || (pSMBr->ByteCount < sizeof(FILE_UNIX_BASIC_INFO))) {
3460 cERROR(1, ("Malformed FILE_UNIX_BASIC_INFO response.\n"
3461 "Unix Extensions can be disabled on mount "
3462 "by specifying the nosfu mount option."));
3463 rc = -EIO; /* bad smb */
3465 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3466 memcpy((char *) pFindData,
3467 (char *) &pSMBr->hdr.Protocol +
3469 sizeof(FILE_UNIX_BASIC_INFO));
3472 cifs_buf_release(pSMB);
3474 goto UnixQPathInfoRetry;
3479 #if 0 /* function unused at present */
3480 int CIFSFindSingle(const int xid, struct cifsTconInfo *tcon,
3481 const char *searchName, FILE_ALL_INFO * findData,
3482 const struct nls_table *nls_codepage)
3484 /* level 257 SMB_ */
3485 TRANSACTION2_FFIRST_REQ *pSMB = NULL;
3486 TRANSACTION2_FFIRST_RSP *pSMBr = NULL;
3490 __u16 params, byte_count;
3492 cFYI(1, ("In FindUnique"));
3494 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3499 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3501 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
3502 PATH_MAX, nls_codepage);
3503 name_len++; /* trailing null */
3505 } else { /* BB improve the check for buffer overruns BB */
3506 name_len = strnlen(searchName, PATH_MAX);
3507 name_len++; /* trailing null */
3508 strncpy(pSMB->FileName, searchName, name_len);
3511 params = 12 + name_len /* includes null */ ;
3512 pSMB->TotalDataCount = 0; /* no EAs */
3513 pSMB->MaxParameterCount = cpu_to_le16(2);
3514 pSMB->MaxDataCount = cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
3515 pSMB->MaxSetupCount = 0;
3519 pSMB->Reserved2 = 0;
3520 pSMB->ParameterOffset = cpu_to_le16(
3521 offsetof(struct smb_com_transaction2_ffirst_req, InformationLevel)-4);
3522 pSMB->DataCount = 0;
3523 pSMB->DataOffset = 0;
3524 pSMB->SetupCount = 1; /* one byte, no need to le convert */
3525 pSMB->Reserved3 = 0;
3526 pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_FIRST);
3527 byte_count = params + 1 /* pad */ ;
3528 pSMB->TotalParameterCount = cpu_to_le16(params);
3529 pSMB->ParameterCount = pSMB->TotalParameterCount;
3530 pSMB->SearchAttributes =
3531 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
3533 pSMB->SearchCount = cpu_to_le16(16); /* BB increase */
3534 pSMB->SearchFlags = cpu_to_le16(1);
3535 pSMB->InformationLevel = cpu_to_le16(SMB_FIND_FILE_DIRECTORY_INFO);
3536 pSMB->SearchStorageType = 0; /* BB what should we set this to? BB */
3537 pSMB->hdr.smb_buf_length += byte_count;
3538 pSMB->ByteCount = cpu_to_le16(byte_count);
3540 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3541 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3544 cFYI(1, ("Send error in FindFileDirInfo = %d", rc));
3545 } else { /* decode response */
3546 cifs_stats_inc(&tcon->num_ffirst);
3550 cifs_buf_release(pSMB);
3552 goto findUniqueRetry;
3556 #endif /* end unused (temporarily) function */
3558 /* xid, tcon, searchName and codepage are input parms, rest are returned */
3560 CIFSFindFirst(const int xid, struct cifsTconInfo *tcon,
3561 const char *searchName,
3562 const struct nls_table *nls_codepage,
3564 struct cifs_search_info *psrch_inf, int remap, const char dirsep)
3566 /* level 257 SMB_ */
3567 TRANSACTION2_FFIRST_REQ *pSMB = NULL;
3568 TRANSACTION2_FFIRST_RSP *pSMBr = NULL;
3569 T2_FFIRST_RSP_PARMS * parms;
3571 int bytes_returned = 0;
3573 __u16 params, byte_count;
3575 cFYI(1, ("In FindFirst for %s", searchName));
3578 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3583 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3585 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
3586 PATH_MAX, nls_codepage, remap);
3587 /* We can not add the asterik earlier in case
3588 it got remapped to 0xF03A as if it were part of the
3589 directory name instead of a wildcard */
3591 pSMB->FileName[name_len] = dirsep;
3592 pSMB->FileName[name_len+1] = 0;
3593 pSMB->FileName[name_len+2] = '*';
3594 pSMB->FileName[name_len+3] = 0;
3595 name_len += 4; /* now the trailing null */
3596 pSMB->FileName[name_len] = 0; /* null terminate just in case */
3597 pSMB->FileName[name_len+1] = 0;
3599 } else { /* BB add check for overrun of SMB buf BB */
3600 name_len = strnlen(searchName, PATH_MAX);
3601 /* BB fix here and in unicode clause above ie
3602 if (name_len > buffersize-header)
3603 free buffer exit; BB */
3604 strncpy(pSMB->FileName, searchName, name_len);
3605 pSMB->FileName[name_len] = dirsep;
3606 pSMB->FileName[name_len+1] = '*';
3607 pSMB->FileName[name_len+2] = 0;
3611 params = 12 + name_len /* includes null */ ;
3612 pSMB->TotalDataCount = 0; /* no EAs */
3613 pSMB->MaxParameterCount = cpu_to_le16(10);
3614 pSMB->MaxDataCount = cpu_to_le16((tcon->ses->server->maxBuf -
3615 MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
3616 pSMB->MaxSetupCount = 0;
3620 pSMB->Reserved2 = 0;
3621 byte_count = params + 1 /* pad */ ;
3622 pSMB->TotalParameterCount = cpu_to_le16(params);
3623 pSMB->ParameterCount = pSMB->TotalParameterCount;
3624 pSMB->ParameterOffset = cpu_to_le16(
3625 offsetof(struct smb_com_transaction2_ffirst_req, SearchAttributes)
3627 pSMB->DataCount = 0;
3628 pSMB->DataOffset = 0;
3629 pSMB->SetupCount = 1; /* one byte, no need to make endian neutral */
3630 pSMB->Reserved3 = 0;
3631 pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_FIRST);
3632 pSMB->SearchAttributes =
3633 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
3635 pSMB->SearchCount = cpu_to_le16(CIFSMaxBufSize/sizeof(FILE_UNIX_INFO));
3636 pSMB->SearchFlags = cpu_to_le16(CIFS_SEARCH_CLOSE_AT_END |
3637 CIFS_SEARCH_RETURN_RESUME);
3638 pSMB->InformationLevel = cpu_to_le16(psrch_inf->info_level);
3640 /* BB what should we set StorageType to? Does it matter? BB */
3641 pSMB->SearchStorageType = 0;
3642 pSMB->hdr.smb_buf_length += byte_count;
3643 pSMB->ByteCount = cpu_to_le16(byte_count);
3645 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3646 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3647 cifs_stats_inc(&tcon->num_ffirst);
3649 if (rc) {/* BB add logic to retry regular search if Unix search
3650 rejected unexpectedly by server */
3651 /* BB Add code to handle unsupported level rc */
3652 cFYI(1, ("Error in FindFirst = %d", rc));
3654 cifs_buf_release(pSMB);
3656 /* BB eventually could optimize out free and realloc of buf */
3659 goto findFirstRetry;
3660 } else { /* decode response */
3661 /* BB remember to free buffer if error BB */
3662 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3664 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
3665 psrch_inf->unicode = TRUE;
3667 psrch_inf->unicode = FALSE;
3669 psrch_inf->ntwrk_buf_start = (char *)pSMBr;
3670 psrch_inf->smallBuf = 0;
3671 psrch_inf->srch_entries_start =
3672 (char *) &pSMBr->hdr.Protocol +
3673 le16_to_cpu(pSMBr->t2.DataOffset);
3674 parms = (T2_FFIRST_RSP_PARMS *)((char *) &pSMBr->hdr.Protocol +
3675 le16_to_cpu(pSMBr->t2.ParameterOffset));
3677 if (parms->EndofSearch)
3678 psrch_inf->endOfSearch = TRUE;
3680 psrch_inf->endOfSearch = FALSE;
3682 psrch_inf->entries_in_buffer =
3683 le16_to_cpu(parms->SearchCount);
3684 psrch_inf->index_of_last_entry = 2 /* skip . and .. */ +
3685 psrch_inf->entries_in_buffer;
3686 *pnetfid = parms->SearchHandle;
3688 cifs_buf_release(pSMB);
3695 int CIFSFindNext(const int xid, struct cifsTconInfo *tcon,
3696 __u16 searchHandle, struct cifs_search_info *psrch_inf)
3698 TRANSACTION2_FNEXT_REQ *pSMB = NULL;
3699 TRANSACTION2_FNEXT_RSP *pSMBr = NULL;
3700 T2_FNEXT_RSP_PARMS * parms;
3701 char *response_data;
3703 int bytes_returned, name_len;
3704 __u16 params, byte_count;
3706 cFYI(1, ("In FindNext"));
3708 if (psrch_inf->endOfSearch == TRUE)
3711 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3716 params = 14; /* includes 2 bytes of null string, converted to LE below*/
3718 pSMB->TotalDataCount = 0; /* no EAs */
3719 pSMB->MaxParameterCount = cpu_to_le16(8);
3720 pSMB->MaxDataCount =
3721 cpu_to_le16((tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE) &
3723 pSMB->MaxSetupCount = 0;
3727 pSMB->Reserved2 = 0;
3728 pSMB->ParameterOffset = cpu_to_le16(
3729 offsetof(struct smb_com_transaction2_fnext_req,SearchHandle) - 4);
3730 pSMB->DataCount = 0;
3731 pSMB->DataOffset = 0;
3732 pSMB->SetupCount = 1;
3733 pSMB->Reserved3 = 0;
3734 pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_NEXT);
3735 pSMB->SearchHandle = searchHandle; /* always kept as le */
3737 cpu_to_le16(CIFSMaxBufSize / sizeof(FILE_UNIX_INFO));
3738 pSMB->InformationLevel = cpu_to_le16(psrch_inf->info_level);
3739 pSMB->ResumeKey = psrch_inf->resume_key;
3741 cpu_to_le16(CIFS_SEARCH_CLOSE_AT_END | CIFS_SEARCH_RETURN_RESUME);
3743 name_len = psrch_inf->resume_name_len;
3745 if (name_len < PATH_MAX) {
3746 memcpy(pSMB->ResumeFileName, psrch_inf->presume_name, name_len);
3747 byte_count += name_len;
3748 /* 14 byte parm len above enough for 2 byte null terminator */
3749 pSMB->ResumeFileName[name_len] = 0;
3750 pSMB->ResumeFileName[name_len+1] = 0;
3753 goto FNext2_err_exit;
3755 byte_count = params + 1 /* pad */ ;
3756 pSMB->TotalParameterCount = cpu_to_le16(params);
3757 pSMB->ParameterCount = pSMB->TotalParameterCount;
3758 pSMB->hdr.smb_buf_length += byte_count;
3759 pSMB->ByteCount = cpu_to_le16(byte_count);
3761 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3762 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3763 cifs_stats_inc(&tcon->num_fnext);
3766 psrch_inf->endOfSearch = TRUE;
3767 rc = 0; /* search probably was closed at end of search*/
3769 cFYI(1, ("FindNext returned = %d", rc));
3770 } else { /* decode response */
3771 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3774 /* BB fixme add lock for file (srch_info) struct here */
3775 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
3776 psrch_inf->unicode = TRUE;
3778 psrch_inf->unicode = FALSE;
3779 response_data = (char *) &pSMBr->hdr.Protocol +
3780 le16_to_cpu(pSMBr->t2.ParameterOffset);
3781 parms = (T2_FNEXT_RSP_PARMS *)response_data;
3782 response_data = (char *)&pSMBr->hdr.Protocol +
3783 le16_to_cpu(pSMBr->t2.DataOffset);
3784 if (psrch_inf->smallBuf)
3785 cifs_small_buf_release(
3786 psrch_inf->ntwrk_buf_start);
3788 cifs_buf_release(psrch_inf->ntwrk_buf_start);
3789 psrch_inf->srch_entries_start = response_data;
3790 psrch_inf->ntwrk_buf_start = (char *)pSMB;
3791 psrch_inf->smallBuf = 0;
3792 if (parms->EndofSearch)
3793 psrch_inf->endOfSearch = TRUE;
3795 psrch_inf->endOfSearch = FALSE;
3796 psrch_inf->entries_in_buffer =
3797 le16_to_cpu(parms->SearchCount);
3798 psrch_inf->index_of_last_entry +=
3799 psrch_inf->entries_in_buffer;
3800 /* cFYI(1,("fnxt2 entries in buf %d index_of_last %d",
3801 psrch_inf->entries_in_buffer, psrch_inf->index_of_last_entry)); */
3803 /* BB fixme add unlock here */
3808 /* BB On error, should we leave previous search buf (and count and
3809 last entry fields) intact or free the previous one? */
3811 /* Note: On -EAGAIN error only caller can retry on handle based calls
3812 since file handle passed in no longer valid */
3815 cifs_buf_release(pSMB);
3820 CIFSFindClose(const int xid, struct cifsTconInfo *tcon,
3821 const __u16 searchHandle)
3824 FINDCLOSE_REQ *pSMB = NULL;
3826 cFYI(1, ("In CIFSSMBFindClose"));
3827 rc = small_smb_init(SMB_COM_FIND_CLOSE2, 1, tcon, (void **)&pSMB);
3829 /* no sense returning error if session restarted
3830 as file handle has been closed */
3836 pSMB->FileID = searchHandle;
3837 pSMB->ByteCount = 0;
3838 rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0);
3840 cERROR(1, ("Send error in FindClose = %d", rc));
3842 cifs_stats_inc(&tcon->num_fclose);
3844 /* Since session is dead, search handle closed on server already */
3852 CIFSGetSrvInodeNumber(const int xid, struct cifsTconInfo *tcon,
3853 const unsigned char *searchName,
3854 __u64 * inode_number,
3855 const struct nls_table *nls_codepage, int remap)
3858 TRANSACTION2_QPI_REQ *pSMB = NULL;
3859 TRANSACTION2_QPI_RSP *pSMBr = NULL;
3860 int name_len, bytes_returned;
3861 __u16 params, byte_count;
3863 cFYI(1, ("In GetSrvInodeNum for %s", searchName));
3867 GetInodeNumberRetry:
3868 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3873 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3875 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
3876 PATH_MAX, nls_codepage, remap);
3877 name_len++; /* trailing null */
3879 } else { /* BB improve the check for buffer overruns BB */
3880 name_len = strnlen(searchName, PATH_MAX);
3881 name_len++; /* trailing null */
3882 strncpy(pSMB->FileName, searchName, name_len);
3885 params = 2 /* level */ + 4 /* rsrvd */ + name_len /* incl null */ ;
3886 pSMB->TotalDataCount = 0;
3887 pSMB->MaxParameterCount = cpu_to_le16(2);
3888 /* BB find exact max data count below from sess structure BB */
3889 pSMB->MaxDataCount = cpu_to_le16(4000);
3890 pSMB->MaxSetupCount = 0;
3894 pSMB->Reserved2 = 0;
3895 pSMB->ParameterOffset = cpu_to_le16(offsetof(
3896 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
3897 pSMB->DataCount = 0;
3898 pSMB->DataOffset = 0;
3899 pSMB->SetupCount = 1;
3900 pSMB->Reserved3 = 0;
3901 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
3902 byte_count = params + 1 /* pad */ ;
3903 pSMB->TotalParameterCount = cpu_to_le16(params);
3904 pSMB->ParameterCount = pSMB->TotalParameterCount;
3905 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_INTERNAL_INFO);
3906 pSMB->Reserved4 = 0;
3907 pSMB->hdr.smb_buf_length += byte_count;
3908 pSMB->ByteCount = cpu_to_le16(byte_count);
3910 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3911 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3913 cFYI(1, ("error %d in QueryInternalInfo", rc));
3915 /* decode response */
3916 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3917 if (rc || (pSMBr->ByteCount < 2))
3918 /* BB also check enough total bytes returned */
3919 /* If rc should we check for EOPNOSUPP and
3920 disable the srvino flag? or in caller? */
3921 rc = -EIO; /* bad smb */
3923 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3924 __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
3925 struct file_internal_info *pfinfo;
3926 /* BB Do we need a cast or hash here ? */
3928 cFYI(1, ("Illegal size ret in QryIntrnlInf"));
3930 goto GetInodeNumOut;
3932 pfinfo = (struct file_internal_info *)
3933 (data_offset + (char *) &pSMBr->hdr.Protocol);
3934 *inode_number = pfinfo->UniqueId;
3938 cifs_buf_release(pSMB);
3940 goto GetInodeNumberRetry;
3945 CIFSGetDFSRefer(const int xid, struct cifsSesInfo *ses,
3946 const unsigned char *searchName,
3947 unsigned char **targetUNCs,
3948 unsigned int *number_of_UNC_in_array,
3949 const struct nls_table *nls_codepage, int remap)
3951 /* TRANS2_GET_DFS_REFERRAL */
3952 TRANSACTION2_GET_DFS_REFER_REQ *pSMB = NULL;
3953 TRANSACTION2_GET_DFS_REFER_RSP *pSMBr = NULL;
3954 struct dfs_referral_level_3 *referrals = NULL;
3960 __u16 params, byte_count;
3961 *number_of_UNC_in_array = 0;
3964 cFYI(1, ("In GetDFSRefer the path %s", searchName));
3968 rc = smb_init(SMB_COM_TRANSACTION2, 15, NULL, (void **) &pSMB,
3973 /* server pointer checked in called function,
3974 but should never be null here anyway */
3975 pSMB->hdr.Mid = GetNextMid(ses->server);
3976 pSMB->hdr.Tid = ses->ipc_tid;
3977 pSMB->hdr.Uid = ses->Suid;
3978 if (ses->capabilities & CAP_STATUS32)
3979 pSMB->hdr.Flags2 |= SMBFLG2_ERR_STATUS;
3980 if (ses->capabilities & CAP_DFS)
3981 pSMB->hdr.Flags2 |= SMBFLG2_DFS;
3983 if (ses->capabilities & CAP_UNICODE) {
3984 pSMB->hdr.Flags2 |= SMBFLG2_UNICODE;
3986 cifsConvertToUCS((__le16 *) pSMB->RequestFileName,
3987 searchName, PATH_MAX, nls_codepage, remap);
3988 name_len++; /* trailing null */
3990 } else { /* BB improve the check for buffer overruns BB */
3991 name_len = strnlen(searchName, PATH_MAX);
3992 name_len++; /* trailing null */
3993 strncpy(pSMB->RequestFileName, searchName, name_len);
3997 if (ses->server->secMode &
3998 (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
3999 pSMB->hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
4002 pSMB->hdr.Uid = ses->Suid;
4004 params = 2 /* level */ + name_len /*includes null */ ;
4005 pSMB->TotalDataCount = 0;
4006 pSMB->DataCount = 0;
4007 pSMB->DataOffset = 0;
4008 pSMB->MaxParameterCount = 0;
4009 pSMB->MaxDataCount = cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
4010 pSMB->MaxSetupCount = 0;
4014 pSMB->Reserved2 = 0;
4015 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4016 struct smb_com_transaction2_get_dfs_refer_req, MaxReferralLevel) - 4);
4017 pSMB->SetupCount = 1;
4018 pSMB->Reserved3 = 0;
4019 pSMB->SubCommand = cpu_to_le16(TRANS2_GET_DFS_REFERRAL);
4020 byte_count = params + 3 /* pad */ ;
4021 pSMB->ParameterCount = cpu_to_le16(params);
4022 pSMB->TotalParameterCount = pSMB->ParameterCount;
4023 pSMB->MaxReferralLevel = cpu_to_le16(3);
4024 pSMB->hdr.smb_buf_length += byte_count;
4025 pSMB->ByteCount = cpu_to_le16(byte_count);
4027 rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB,
4028 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4030 cFYI(1, ("Send error in GetDFSRefer = %d", rc));
4031 } else { /* decode response */
4032 /* BB Add logic to parse referrals here */
4033 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4035 /* BB Also check if enough total bytes returned? */
4036 if (rc || (pSMBr->ByteCount < 17))
4037 rc = -EIO; /* bad smb */
4039 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4040 __u16 data_count = le16_to_cpu(pSMBr->t2.DataCount);
4043 ("Decoding GetDFSRefer response BCC: %d Offset %d",
4044 pSMBr->ByteCount, data_offset));
4046 (struct dfs_referral_level_3 *)
4047 (8 /* sizeof start of data block */ +
4049 (char *) &pSMBr->hdr.Protocol);
4050 cFYI(1, ("num_referrals: %d dfs flags: 0x%x ... \n"
4051 "for referral one refer size: 0x%x srv "
4052 "type: 0x%x refer flags: 0x%x ttl: 0x%x",
4053 le16_to_cpu(pSMBr->NumberOfReferrals),
4054 le16_to_cpu(pSMBr->DFSFlags),
4055 le16_to_cpu(referrals->ReferralSize),
4056 le16_to_cpu(referrals->ServerType),
4057 le16_to_cpu(referrals->ReferralFlags),
4058 le16_to_cpu(referrals->TimeToLive)));
4059 /* BB This field is actually two bytes in from start of
4060 data block so we could do safety check that DataBlock
4061 begins at address of pSMBr->NumberOfReferrals */
4062 *number_of_UNC_in_array =
4063 le16_to_cpu(pSMBr->NumberOfReferrals);
4065 /* BB Fix below so can return more than one referral */
4066 if (*number_of_UNC_in_array > 1)
4067 *number_of_UNC_in_array = 1;
4069 /* get the length of the strings describing refs */
4071 for (i = 0; i < *number_of_UNC_in_array; i++) {
4072 /* make sure that DfsPathOffset not past end */
4074 le16_to_cpu(referrals->DfsPathOffset);
4075 if (offset > data_count) {
4076 /* if invalid referral, stop here and do
4077 not try to copy any more */
4078 *number_of_UNC_in_array = i;
4081 temp = ((char *)referrals) + offset;
4083 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
4084 name_len += UniStrnlen((wchar_t *)temp,
4087 name_len += strnlen(temp, data_count);
4090 /* BB add check that referral pointer does
4091 not fall off end PDU */
4093 /* BB add check for name_len bigger than bcc */
4095 kmalloc(name_len+1+(*number_of_UNC_in_array),
4097 if (*targetUNCs == NULL) {
4101 /* copy the ref strings */
4102 referrals = (struct dfs_referral_level_3 *)
4103 (8 /* sizeof data hdr */ + data_offset +
4104 (char *) &pSMBr->hdr.Protocol);
4106 for (i = 0; i < *number_of_UNC_in_array; i++) {
4107 temp = ((char *)referrals) +
4108 le16_to_cpu(referrals->DfsPathOffset);
4109 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
4110 cifs_strfromUCS_le(*targetUNCs,
4115 strncpy(*targetUNCs, temp, name_len);
4117 /* BB update target_uncs pointers */
4127 cifs_buf_release(pSMB);
4135 /* Query File System Info such as free space to old servers such as Win 9x */
4137 SMBOldQFSInfo(const int xid, struct cifsTconInfo *tcon, struct kstatfs *FSData)
4139 /* level 0x01 SMB_QUERY_FILE_SYSTEM_INFO */
4140 TRANSACTION2_QFSI_REQ *pSMB = NULL;
4141 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4142 FILE_SYSTEM_ALLOC_INFO *response_data;
4144 int bytes_returned = 0;
4145 __u16 params, byte_count;
4147 cFYI(1, ("OldQFSInfo"));
4149 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4154 params = 2; /* level */
4155 pSMB->TotalDataCount = 0;
4156 pSMB->MaxParameterCount = cpu_to_le16(2);
4157 pSMB->MaxDataCount = cpu_to_le16(1000);
4158 pSMB->MaxSetupCount = 0;
4162 pSMB->Reserved2 = 0;
4163 byte_count = params + 1 /* pad */ ;
4164 pSMB->TotalParameterCount = cpu_to_le16(params);
4165 pSMB->ParameterCount = pSMB->TotalParameterCount;
4166 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4167 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4168 pSMB->DataCount = 0;
4169 pSMB->DataOffset = 0;
4170 pSMB->SetupCount = 1;
4171 pSMB->Reserved3 = 0;
4172 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4173 pSMB->InformationLevel = cpu_to_le16(SMB_INFO_ALLOCATION);
4174 pSMB->hdr.smb_buf_length += byte_count;
4175 pSMB->ByteCount = cpu_to_le16(byte_count);
4177 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4178 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4180 cFYI(1, ("Send error in QFSInfo = %d", rc));
4181 } else { /* decode response */
4182 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4184 if (rc || (pSMBr->ByteCount < 18))
4185 rc = -EIO; /* bad smb */
4187 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4188 cFYI(1, ("qfsinf resp BCC: %d Offset %d",
4189 pSMBr->ByteCount, data_offset));
4191 response_data = (FILE_SYSTEM_ALLOC_INFO *)
4192 (((char *) &pSMBr->hdr.Protocol) + data_offset);
4194 le16_to_cpu(response_data->BytesPerSector) *
4195 le32_to_cpu(response_data->
4196 SectorsPerAllocationUnit);
4198 le32_to_cpu(response_data->TotalAllocationUnits);
4199 FSData->f_bfree = FSData->f_bavail =
4200 le32_to_cpu(response_data->FreeAllocationUnits);
4202 ("Blocks: %lld Free: %lld Block size %ld",
4203 (unsigned long long)FSData->f_blocks,
4204 (unsigned long long)FSData->f_bfree,
4208 cifs_buf_release(pSMB);
4211 goto oldQFSInfoRetry;
4217 CIFSSMBQFSInfo(const int xid, struct cifsTconInfo *tcon, struct kstatfs *FSData)
4219 /* level 0x103 SMB_QUERY_FILE_SYSTEM_INFO */
4220 TRANSACTION2_QFSI_REQ *pSMB = NULL;
4221 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4222 FILE_SYSTEM_INFO *response_data;
4224 int bytes_returned = 0;
4225 __u16 params, byte_count;
4227 cFYI(1, ("In QFSInfo"));
4229 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4234 params = 2; /* level */
4235 pSMB->TotalDataCount = 0;
4236 pSMB->MaxParameterCount = cpu_to_le16(2);
4237 pSMB->MaxDataCount = cpu_to_le16(1000);
4238 pSMB->MaxSetupCount = 0;
4242 pSMB->Reserved2 = 0;
4243 byte_count = params + 1 /* pad */ ;
4244 pSMB->TotalParameterCount = cpu_to_le16(params);
4245 pSMB->ParameterCount = pSMB->TotalParameterCount;
4246 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4247 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4248 pSMB->DataCount = 0;
4249 pSMB->DataOffset = 0;
4250 pSMB->SetupCount = 1;
4251 pSMB->Reserved3 = 0;
4252 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4253 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_SIZE_INFO);
4254 pSMB->hdr.smb_buf_length += byte_count;
4255 pSMB->ByteCount = cpu_to_le16(byte_count);
4257 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4258 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4260 cFYI(1, ("Send error in QFSInfo = %d", rc));
4261 } else { /* decode response */
4262 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4264 if (rc || (pSMBr->ByteCount < 24))
4265 rc = -EIO; /* bad smb */
4267 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4271 *) (((char *) &pSMBr->hdr.Protocol) +
4274 le32_to_cpu(response_data->BytesPerSector) *
4275 le32_to_cpu(response_data->
4276 SectorsPerAllocationUnit);
4278 le64_to_cpu(response_data->TotalAllocationUnits);
4279 FSData->f_bfree = FSData->f_bavail =
4280 le64_to_cpu(response_data->FreeAllocationUnits);
4282 ("Blocks: %lld Free: %lld Block size %ld",
4283 (unsigned long long)FSData->f_blocks,
4284 (unsigned long long)FSData->f_bfree,
4288 cifs_buf_release(pSMB);
4297 CIFSSMBQFSAttributeInfo(const int xid, struct cifsTconInfo *tcon)
4299 /* level 0x105 SMB_QUERY_FILE_SYSTEM_INFO */
4300 TRANSACTION2_QFSI_REQ *pSMB = NULL;
4301 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4302 FILE_SYSTEM_ATTRIBUTE_INFO *response_data;
4304 int bytes_returned = 0;
4305 __u16 params, byte_count;
4307 cFYI(1, ("In QFSAttributeInfo"));
4309 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4314 params = 2; /* level */
4315 pSMB->TotalDataCount = 0;
4316 pSMB->MaxParameterCount = cpu_to_le16(2);
4317 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
4318 pSMB->MaxSetupCount = 0;
4322 pSMB->Reserved2 = 0;
4323 byte_count = params + 1 /* pad */ ;
4324 pSMB->TotalParameterCount = cpu_to_le16(params);
4325 pSMB->ParameterCount = pSMB->TotalParameterCount;
4326 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4327 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4328 pSMB->DataCount = 0;
4329 pSMB->DataOffset = 0;
4330 pSMB->SetupCount = 1;
4331 pSMB->Reserved3 = 0;
4332 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4333 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_ATTRIBUTE_INFO);
4334 pSMB->hdr.smb_buf_length += byte_count;
4335 pSMB->ByteCount = cpu_to_le16(byte_count);
4337 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4338 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4340 cERROR(1, ("Send error in QFSAttributeInfo = %d", rc));
4341 } else { /* decode response */
4342 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4344 if (rc || (pSMBr->ByteCount < 13)) {
4345 /* BB also check if enough bytes returned */
4346 rc = -EIO; /* bad smb */
4348 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4350 (FILE_SYSTEM_ATTRIBUTE_INFO
4351 *) (((char *) &pSMBr->hdr.Protocol) +
4353 memcpy(&tcon->fsAttrInfo, response_data,
4354 sizeof(FILE_SYSTEM_ATTRIBUTE_INFO));
4357 cifs_buf_release(pSMB);
4360 goto QFSAttributeRetry;
4366 CIFSSMBQFSDeviceInfo(const int xid, struct cifsTconInfo *tcon)
4368 /* level 0x104 SMB_QUERY_FILE_SYSTEM_INFO */
4369 TRANSACTION2_QFSI_REQ *pSMB = NULL;
4370 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4371 FILE_SYSTEM_DEVICE_INFO *response_data;
4373 int bytes_returned = 0;
4374 __u16 params, byte_count;
4376 cFYI(1, ("In QFSDeviceInfo"));
4378 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4383 params = 2; /* level */
4384 pSMB->TotalDataCount = 0;
4385 pSMB->MaxParameterCount = cpu_to_le16(2);
4386 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
4387 pSMB->MaxSetupCount = 0;
4391 pSMB->Reserved2 = 0;
4392 byte_count = params + 1 /* pad */ ;
4393 pSMB->TotalParameterCount = cpu_to_le16(params);
4394 pSMB->ParameterCount = pSMB->TotalParameterCount;
4395 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4396 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4398 pSMB->DataCount = 0;
4399 pSMB->DataOffset = 0;
4400 pSMB->SetupCount = 1;
4401 pSMB->Reserved3 = 0;
4402 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4403 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_DEVICE_INFO);
4404 pSMB->hdr.smb_buf_length += byte_count;
4405 pSMB->ByteCount = cpu_to_le16(byte_count);
4407 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4408 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4410 cFYI(1, ("Send error in QFSDeviceInfo = %d", rc));
4411 } else { /* decode response */
4412 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4414 if (rc || (pSMBr->ByteCount < sizeof(FILE_SYSTEM_DEVICE_INFO)))
4415 rc = -EIO; /* bad smb */
4417 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4419 (FILE_SYSTEM_DEVICE_INFO *)
4420 (((char *) &pSMBr->hdr.Protocol) +
4422 memcpy(&tcon->fsDevInfo, response_data,
4423 sizeof(FILE_SYSTEM_DEVICE_INFO));
4426 cifs_buf_release(pSMB);
4429 goto QFSDeviceRetry;
4435 CIFSSMBQFSUnixInfo(const int xid, struct cifsTconInfo *tcon)
4437 /* level 0x200 SMB_QUERY_CIFS_UNIX_INFO */
4438 TRANSACTION2_QFSI_REQ *pSMB = NULL;
4439 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4440 FILE_SYSTEM_UNIX_INFO *response_data;
4442 int bytes_returned = 0;
4443 __u16 params, byte_count;
4445 cFYI(1, ("In QFSUnixInfo"));
4447 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4452 params = 2; /* level */
4453 pSMB->TotalDataCount = 0;
4454 pSMB->DataCount = 0;
4455 pSMB->DataOffset = 0;
4456 pSMB->MaxParameterCount = cpu_to_le16(2);
4457 pSMB->MaxDataCount = cpu_to_le16(100); /* BB find exact max SMB PDU from sess structure BB */
4458 pSMB->MaxSetupCount = 0;
4462 pSMB->Reserved2 = 0;
4463 byte_count = params + 1 /* pad */ ;
4464 pSMB->ParameterCount = cpu_to_le16(params);
4465 pSMB->TotalParameterCount = pSMB->ParameterCount;
4466 pSMB->ParameterOffset = cpu_to_le16(offsetof(struct
4467 smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4468 pSMB->SetupCount = 1;
4469 pSMB->Reserved3 = 0;
4470 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4471 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_CIFS_UNIX_INFO);
4472 pSMB->hdr.smb_buf_length += byte_count;
4473 pSMB->ByteCount = cpu_to_le16(byte_count);
4475 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4476 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4478 cERROR(1, ("Send error in QFSUnixInfo = %d", rc));
4479 } else { /* decode response */
4480 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4482 if (rc || (pSMBr->ByteCount < 13)) {
4483 rc = -EIO; /* bad smb */
4485 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4487 (FILE_SYSTEM_UNIX_INFO
4488 *) (((char *) &pSMBr->hdr.Protocol) +
4490 memcpy(&tcon->fsUnixInfo, response_data,
4491 sizeof(FILE_SYSTEM_UNIX_INFO));
4494 cifs_buf_release(pSMB);
4504 CIFSSMBSetFSUnixInfo(const int xid, struct cifsTconInfo *tcon, __u64 cap)
4506 /* level 0x200 SMB_SET_CIFS_UNIX_INFO */
4507 TRANSACTION2_SETFSI_REQ *pSMB = NULL;
4508 TRANSACTION2_SETFSI_RSP *pSMBr = NULL;
4510 int bytes_returned = 0;
4511 __u16 params, param_offset, offset, byte_count;
4513 cFYI(1, ("In SETFSUnixInfo"));
4515 /* BB switch to small buf init to save memory */
4516 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4521 params = 4; /* 2 bytes zero followed by info level. */
4522 pSMB->MaxSetupCount = 0;
4526 pSMB->Reserved2 = 0;
4527 param_offset = offsetof(struct smb_com_transaction2_setfsi_req, FileNum)
4529 offset = param_offset + params;
4531 pSMB->MaxParameterCount = cpu_to_le16(4);
4532 pSMB->MaxDataCount = cpu_to_le16(100); /* BB find exact max SMB PDU from sess structure BB */
4533 pSMB->SetupCount = 1;
4534 pSMB->Reserved3 = 0;
4535 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FS_INFORMATION);
4536 byte_count = 1 /* pad */ + params + 12;
4538 pSMB->DataCount = cpu_to_le16(12);
4539 pSMB->ParameterCount = cpu_to_le16(params);
4540 pSMB->TotalDataCount = pSMB->DataCount;
4541 pSMB->TotalParameterCount = pSMB->ParameterCount;
4542 pSMB->ParameterOffset = cpu_to_le16(param_offset);
4543 pSMB->DataOffset = cpu_to_le16(offset);
4547 pSMB->InformationLevel = cpu_to_le16(SMB_SET_CIFS_UNIX_INFO);
4550 pSMB->ClientUnixMajor = cpu_to_le16(CIFS_UNIX_MAJOR_VERSION);
4551 pSMB->ClientUnixMinor = cpu_to_le16(CIFS_UNIX_MINOR_VERSION);
4552 pSMB->ClientUnixCap = cpu_to_le64(cap);
4554 pSMB->hdr.smb_buf_length += byte_count;
4555 pSMB->ByteCount = cpu_to_le16(byte_count);
4557 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4558 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4560 cERROR(1, ("Send error in SETFSUnixInfo = %d", rc));
4561 } else { /* decode response */
4562 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4564 rc = -EIO; /* bad smb */
4567 cifs_buf_release(pSMB);
4570 goto SETFSUnixRetry;
4578 CIFSSMBQFSPosixInfo(const int xid, struct cifsTconInfo *tcon,
4579 struct kstatfs *FSData)
4581 /* level 0x201 SMB_QUERY_CIFS_POSIX_INFO */
4582 TRANSACTION2_QFSI_REQ *pSMB = NULL;
4583 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4584 FILE_SYSTEM_POSIX_INFO *response_data;
4586 int bytes_returned = 0;
4587 __u16 params, byte_count;
4589 cFYI(1, ("In QFSPosixInfo"));
4591 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4596 params = 2; /* level */
4597 pSMB->TotalDataCount = 0;
4598 pSMB->DataCount = 0;
4599 pSMB->DataOffset = 0;
4600 pSMB->MaxParameterCount = cpu_to_le16(2);
4601 pSMB->MaxDataCount = cpu_to_le16(100); /* BB find exact max SMB PDU from sess structure BB */
4602 pSMB->MaxSetupCount = 0;
4606 pSMB->Reserved2 = 0;
4607 byte_count = params + 1 /* pad */ ;
4608 pSMB->ParameterCount = cpu_to_le16(params);
4609 pSMB->TotalParameterCount = pSMB->ParameterCount;
4610 pSMB->ParameterOffset = cpu_to_le16(offsetof(struct
4611 smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4612 pSMB->SetupCount = 1;
4613 pSMB->Reserved3 = 0;
4614 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4615 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_POSIX_FS_INFO);
4616 pSMB->hdr.smb_buf_length += byte_count;
4617 pSMB->ByteCount = cpu_to_le16(byte_count);
4619 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4620 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4622 cFYI(1, ("Send error in QFSUnixInfo = %d", rc));
4623 } else { /* decode response */
4624 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4626 if (rc || (pSMBr->ByteCount < 13)) {
4627 rc = -EIO; /* bad smb */
4629 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4631 (FILE_SYSTEM_POSIX_INFO
4632 *) (((char *) &pSMBr->hdr.Protocol) +
4635 le32_to_cpu(response_data->BlockSize);
4637 le64_to_cpu(response_data->TotalBlocks);
4639 le64_to_cpu(response_data->BlocksAvail);
4640 if (response_data->UserBlocksAvail == cpu_to_le64(-1)) {
4641 FSData->f_bavail = FSData->f_bfree;
4644 le64_to_cpu(response_data->UserBlocksAvail);
4646 if (response_data->TotalFileNodes != cpu_to_le64(-1))
4648 le64_to_cpu(response_data->TotalFileNodes);
4649 if (response_data->FreeFileNodes != cpu_to_le64(-1))
4651 le64_to_cpu(response_data->FreeFileNodes);
4654 cifs_buf_release(pSMB);
4663 /* We can not use write of zero bytes trick to
4664 set file size due to need for large file support. Also note that
4665 this SetPathInfo is preferred to SetFileInfo based method in next
4666 routine which is only needed to work around a sharing violation bug
4667 in Samba which this routine can run into */
4670 CIFSSMBSetEOF(const int xid, struct cifsTconInfo *tcon, const char *fileName,
4671 __u64 size, int SetAllocation,
4672 const struct nls_table *nls_codepage, int remap)
4674 struct smb_com_transaction2_spi_req *pSMB = NULL;
4675 struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
4676 struct file_end_of_file_info *parm_data;
4679 int bytes_returned = 0;
4680 __u16 params, byte_count, data_count, param_offset, offset;
4682 cFYI(1, ("In SetEOF"));
4684 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4689 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4691 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
4692 PATH_MAX, nls_codepage, remap);
4693 name_len++; /* trailing null */
4695 } else { /* BB improve the check for buffer overruns BB */
4696 name_len = strnlen(fileName, PATH_MAX);
4697 name_len++; /* trailing null */
4698 strncpy(pSMB->FileName, fileName, name_len);
4700 params = 6 + name_len;
4701 data_count = sizeof(struct file_end_of_file_info);
4702 pSMB->MaxParameterCount = cpu_to_le16(2);
4703 pSMB->MaxDataCount = cpu_to_le16(4100);
4704 pSMB->MaxSetupCount = 0;
4708 pSMB->Reserved2 = 0;
4709 param_offset = offsetof(struct smb_com_transaction2_spi_req,
4710 InformationLevel) - 4;
4711 offset = param_offset + params;
4712 if (SetAllocation) {
4713 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
4714 pSMB->InformationLevel =
4715 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2);
4717 pSMB->InformationLevel =
4718 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO);
4719 } else /* Set File Size */ {
4720 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
4721 pSMB->InformationLevel =
4722 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO2);
4724 pSMB->InformationLevel =
4725 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO);
4729 (struct file_end_of_file_info *) (((char *) &pSMB->hdr.Protocol) +
4731 pSMB->ParameterOffset = cpu_to_le16(param_offset);
4732 pSMB->DataOffset = cpu_to_le16(offset);
4733 pSMB->SetupCount = 1;
4734 pSMB->Reserved3 = 0;
4735 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
4736 byte_count = 3 /* pad */ + params + data_count;
4737 pSMB->DataCount = cpu_to_le16(data_count);
4738 pSMB->TotalDataCount = pSMB->DataCount;
4739 pSMB->ParameterCount = cpu_to_le16(params);
4740 pSMB->TotalParameterCount = pSMB->ParameterCount;
4741 pSMB->Reserved4 = 0;
4742 pSMB->hdr.smb_buf_length += byte_count;
4743 parm_data->FileSize = cpu_to_le64(size);
4744 pSMB->ByteCount = cpu_to_le16(byte_count);
4745 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4746 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4748 cFYI(1, ("SetPathInfo (file size) returned %d", rc));
4751 cifs_buf_release(pSMB);
4760 CIFSSMBSetFileSize(const int xid, struct cifsTconInfo *tcon, __u64 size,
4761 __u16 fid, __u32 pid_of_opener, int SetAllocation)
4763 struct smb_com_transaction2_sfi_req *pSMB = NULL;
4765 struct file_end_of_file_info *parm_data;
4767 __u16 params, param_offset, offset, byte_count, count;
4769 cFYI(1, ("SetFileSize (via SetFileInfo) %lld",
4771 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
4776 pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
4777 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));
4780 pSMB->MaxSetupCount = 0;
4784 pSMB->Reserved2 = 0;
4785 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
4786 offset = param_offset + params;
4788 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
4790 count = sizeof(struct file_end_of_file_info);
4791 pSMB->MaxParameterCount = cpu_to_le16(2);
4792 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB PDU from sess */
4793 pSMB->SetupCount = 1;
4794 pSMB->Reserved3 = 0;
4795 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
4796 byte_count = 3 /* pad */ + params + count;
4797 pSMB->DataCount = cpu_to_le16(count);
4798 pSMB->ParameterCount = cpu_to_le16(params);
4799 pSMB->TotalDataCount = pSMB->DataCount;
4800 pSMB->TotalParameterCount = pSMB->ParameterCount;
4801 pSMB->ParameterOffset = cpu_to_le16(param_offset);
4803 (struct file_end_of_file_info *) (((char *) &pSMB->hdr.Protocol)
4805 pSMB->DataOffset = cpu_to_le16(offset);
4806 parm_data->FileSize = cpu_to_le64(size);
4808 if (SetAllocation) {
4809 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
4810 pSMB->InformationLevel =
4811 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2);
4813 pSMB->InformationLevel =
4814 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO);
4815 } else /* Set File Size */ {
4816 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
4817 pSMB->InformationLevel =
4818 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO2);
4820 pSMB->InformationLevel =
4821 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO);
4823 pSMB->Reserved4 = 0;
4824 pSMB->hdr.smb_buf_length += byte_count;
4825 pSMB->ByteCount = cpu_to_le16(byte_count);
4826 rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0);
4829 ("Send error in SetFileInfo (SetFileSize) = %d",
4833 /* Note: On -EAGAIN error only caller can retry on handle based calls
4834 since file handle passed in no longer valid */
4839 /* Some legacy servers such as NT4 require that the file times be set on
4840 an open handle, rather than by pathname - this is awkward due to
4841 potential access conflicts on the open, but it is unavoidable for these
4842 old servers since the only other choice is to go from 100 nanosecond DCE
4843 time and resort to the original setpathinfo level which takes the ancient
4844 DOS time format with 2 second granularity */
4846 CIFSSMBSetFileTimes(const int xid, struct cifsTconInfo *tcon,
4847 const FILE_BASIC_INFO *data, __u16 fid)
4849 struct smb_com_transaction2_sfi_req *pSMB = NULL;
4852 __u16 params, param_offset, offset, byte_count, count;
4854 cFYI(1, ("Set Times (via SetFileInfo)"));
4855 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
4860 /* At this point there is no need to override the current pid
4861 with the pid of the opener, but that could change if we someday
4862 use an existing handle (rather than opening one on the fly) */
4863 /* pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
4864 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));*/
4867 pSMB->MaxSetupCount = 0;
4871 pSMB->Reserved2 = 0;
4872 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
4873 offset = param_offset + params;
4875 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
4877 count = sizeof(FILE_BASIC_INFO);
4878 pSMB->MaxParameterCount = cpu_to_le16(2);
4879 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB PDU from sess */
4880 pSMB->SetupCount = 1;
4881 pSMB->Reserved3 = 0;
4882 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
4883 byte_count = 3 /* pad */ + params + count;
4884 pSMB->DataCount = cpu_to_le16(count);
4885 pSMB->ParameterCount = cpu_to_le16(params);
4886 pSMB->TotalDataCount = pSMB->DataCount;
4887 pSMB->TotalParameterCount = pSMB->ParameterCount;
4888 pSMB->ParameterOffset = cpu_to_le16(param_offset);
4889 pSMB->DataOffset = cpu_to_le16(offset);
4891 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
4892 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO2);
4894 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO);
4895 pSMB->Reserved4 = 0;
4896 pSMB->hdr.smb_buf_length += byte_count;
4897 pSMB->ByteCount = cpu_to_le16(byte_count);
4898 memcpy(data_offset, data, sizeof(FILE_BASIC_INFO));
4899 rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0);
4901 cFYI(1, ("Send error in Set Time (SetFileInfo) = %d", rc));
4904 /* Note: On -EAGAIN error only caller can retry on handle based calls
4905 since file handle passed in no longer valid */
4912 CIFSSMBSetTimes(const int xid, struct cifsTconInfo *tcon, const char *fileName,
4913 const FILE_BASIC_INFO *data,
4914 const struct nls_table *nls_codepage, int remap)
4916 TRANSACTION2_SPI_REQ *pSMB = NULL;
4917 TRANSACTION2_SPI_RSP *pSMBr = NULL;
4920 int bytes_returned = 0;
4922 __u16 params, param_offset, offset, byte_count, count;
4924 cFYI(1, ("In SetTimes"));
4927 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4932 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4934 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
4935 PATH_MAX, nls_codepage, remap);
4936 name_len++; /* trailing null */
4938 } else { /* BB improve the check for buffer overruns BB */
4939 name_len = strnlen(fileName, PATH_MAX);
4940 name_len++; /* trailing null */
4941 strncpy(pSMB->FileName, fileName, name_len);
4944 params = 6 + name_len;
4945 count = sizeof(FILE_BASIC_INFO);
4946 pSMB->MaxParameterCount = cpu_to_le16(2);
4947 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
4948 pSMB->MaxSetupCount = 0;
4952 pSMB->Reserved2 = 0;
4953 param_offset = offsetof(struct smb_com_transaction2_spi_req,
4954 InformationLevel) - 4;
4955 offset = param_offset + params;
4956 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
4957 pSMB->ParameterOffset = cpu_to_le16(param_offset);
4958 pSMB->DataOffset = cpu_to_le16(offset);
4959 pSMB->SetupCount = 1;
4960 pSMB->Reserved3 = 0;
4961 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
4962 byte_count = 3 /* pad */ + params + count;
4964 pSMB->DataCount = cpu_to_le16(count);
4965 pSMB->ParameterCount = cpu_to_le16(params);
4966 pSMB->TotalDataCount = pSMB->DataCount;
4967 pSMB->TotalParameterCount = pSMB->ParameterCount;
4968 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
4969 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO2);
4971 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO);
4972 pSMB->Reserved4 = 0;
4973 pSMB->hdr.smb_buf_length += byte_count;
4974 memcpy(data_offset, data, sizeof(FILE_BASIC_INFO));
4975 pSMB->ByteCount = cpu_to_le16(byte_count);
4976 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4977 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4979 cFYI(1, ("SetPathInfo (times) returned %d", rc));
4982 cifs_buf_release(pSMB);
4990 /* Can not be used to set time stamps yet (due to old DOS time format) */
4991 /* Can be used to set attributes */
4992 #if 0 /* Possibly not needed - since it turns out that strangely NT4 has a bug
4993 handling it anyway and NT4 was what we thought it would be needed for
4994 Do not delete it until we prove whether needed for Win9x though */
4996 CIFSSMBSetAttrLegacy(int xid, struct cifsTconInfo *tcon, char *fileName,
4997 __u16 dos_attrs, const struct nls_table *nls_codepage)
4999 SETATTR_REQ *pSMB = NULL;
5000 SETATTR_RSP *pSMBr = NULL;
5005 cFYI(1, ("In SetAttrLegacy"));
5008 rc = smb_init(SMB_COM_SETATTR, 8, tcon, (void **) &pSMB,
5013 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5015 ConvertToUCS((__le16 *) pSMB->fileName, fileName,
5016 PATH_MAX, nls_codepage);
5017 name_len++; /* trailing null */
5019 } else { /* BB improve the check for buffer overruns BB */
5020 name_len = strnlen(fileName, PATH_MAX);
5021 name_len++; /* trailing null */
5022 strncpy(pSMB->fileName, fileName, name_len);
5024 pSMB->attr = cpu_to_le16(dos_attrs);
5025 pSMB->BufferFormat = 0x04;
5026 pSMB->hdr.smb_buf_length += name_len + 1;
5027 pSMB->ByteCount = cpu_to_le16(name_len + 1);
5028 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5029 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5031 cFYI(1, ("Error in LegacySetAttr = %d", rc));
5034 cifs_buf_release(pSMB);
5037 goto SetAttrLgcyRetry;
5041 #endif /* temporarily unneeded SetAttr legacy function */
5044 CIFSSMBUnixSetPerms(const int xid, struct cifsTconInfo *tcon,
5045 char *fileName, __u64 mode, __u64 uid, __u64 gid,
5046 dev_t device, const struct nls_table *nls_codepage,
5049 TRANSACTION2_SPI_REQ *pSMB = NULL;
5050 TRANSACTION2_SPI_RSP *pSMBr = NULL;
5053 int bytes_returned = 0;
5054 FILE_UNIX_BASIC_INFO *data_offset;
5055 __u16 params, param_offset, offset, count, byte_count;
5057 cFYI(1, ("In SetUID/GID/Mode"));
5059 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5064 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5066 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
5067 PATH_MAX, nls_codepage, remap);
5068 name_len++; /* trailing null */
5070 } else { /* BB improve the check for buffer overruns BB */
5071 name_len = strnlen(fileName, PATH_MAX);
5072 name_len++; /* trailing null */
5073 strncpy(pSMB->FileName, fileName, name_len);
5076 params = 6 + name_len;
5077 count = sizeof(FILE_UNIX_BASIC_INFO);
5078 pSMB->MaxParameterCount = cpu_to_le16(2);
5079 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
5080 pSMB->MaxSetupCount = 0;
5084 pSMB->Reserved2 = 0;
5085 param_offset = offsetof(struct smb_com_transaction2_spi_req,
5086 InformationLevel) - 4;
5087 offset = param_offset + params;
5089 (FILE_UNIX_BASIC_INFO *) ((char *) &pSMB->hdr.Protocol +
5091 memset(data_offset, 0, count);
5092 pSMB->DataOffset = cpu_to_le16(offset);
5093 pSMB->ParameterOffset = cpu_to_le16(param_offset);
5094 pSMB->SetupCount = 1;
5095 pSMB->Reserved3 = 0;
5096 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
5097 byte_count = 3 /* pad */ + params + count;
5098 pSMB->ParameterCount = cpu_to_le16(params);
5099 pSMB->DataCount = cpu_to_le16(count);
5100 pSMB->TotalParameterCount = pSMB->ParameterCount;
5101 pSMB->TotalDataCount = pSMB->DataCount;
5102 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_BASIC);
5103 pSMB->Reserved4 = 0;
5104 pSMB->hdr.smb_buf_length += byte_count;
5105 /* Samba server ignores set of file size to zero due to bugs in some
5106 older clients, but we should be precise - we use SetFileSize to
5107 set file size and do not want to truncate file size to zero
5108 accidently as happened on one Samba server beta by putting
5109 zero instead of -1 here */
5110 data_offset->EndOfFile = NO_CHANGE_64;
5111 data_offset->NumOfBytes = NO_CHANGE_64;
5112 data_offset->LastStatusChange = NO_CHANGE_64;
5113 data_offset->LastAccessTime = NO_CHANGE_64;
5114 data_offset->LastModificationTime = NO_CHANGE_64;
5115 data_offset->Uid = cpu_to_le64(uid);
5116 data_offset->Gid = cpu_to_le64(gid);
5117 /* better to leave device as zero when it is */
5118 data_offset->DevMajor = cpu_to_le64(MAJOR(device));
5119 data_offset->DevMinor = cpu_to_le64(MINOR(device));
5120 data_offset->Permissions = cpu_to_le64(mode);
5123 data_offset->Type = cpu_to_le32(UNIX_FILE);
5124 else if (S_ISDIR(mode))
5125 data_offset->Type = cpu_to_le32(UNIX_DIR);
5126 else if (S_ISLNK(mode))
5127 data_offset->Type = cpu_to_le32(UNIX_SYMLINK);
5128 else if (S_ISCHR(mode))
5129 data_offset->Type = cpu_to_le32(UNIX_CHARDEV);
5130 else if (S_ISBLK(mode))
5131 data_offset->Type = cpu_to_le32(UNIX_BLOCKDEV);
5132 else if (S_ISFIFO(mode))
5133 data_offset->Type = cpu_to_le32(UNIX_FIFO);
5134 else if (S_ISSOCK(mode))
5135 data_offset->Type = cpu_to_le32(UNIX_SOCKET);
5138 pSMB->ByteCount = cpu_to_le16(byte_count);
5139 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5140 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5142 cFYI(1, ("SetPathInfo (perms) returned %d", rc));
5146 cifs_buf_release(pSMB);
5152 int CIFSSMBNotify(const int xid, struct cifsTconInfo *tcon,
5153 const int notify_subdirs, const __u16 netfid,
5154 __u32 filter, struct file *pfile, int multishot,
5155 const struct nls_table *nls_codepage)
5158 struct smb_com_transaction_change_notify_req *pSMB = NULL;
5159 struct smb_com_ntransaction_change_notify_rsp *pSMBr = NULL;
5160 struct dir_notify_req *dnotify_req;
5163 cFYI(1, ("In CIFSSMBNotify for file handle %d", (int)netfid));
5164 rc = smb_init(SMB_COM_NT_TRANSACT, 23, tcon, (void **) &pSMB,
5169 pSMB->TotalParameterCount = 0 ;
5170 pSMB->TotalDataCount = 0;
5171 pSMB->MaxParameterCount = cpu_to_le32(2);
5172 /* BB find exact data count max from sess structure BB */
5173 pSMB->MaxDataCount = 0; /* same in little endian or be */
5174 /* BB VERIFY verify which is correct for above BB */
5175 pSMB->MaxDataCount = cpu_to_le32((tcon->ses->server->maxBuf -
5176 MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
5178 pSMB->MaxSetupCount = 4;
5180 pSMB->ParameterOffset = 0;
5181 pSMB->DataCount = 0;
5182 pSMB->DataOffset = 0;
5183 pSMB->SetupCount = 4; /* single byte does not need le conversion */
5184 pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_NOTIFY_CHANGE);
5185 pSMB->ParameterCount = pSMB->TotalParameterCount;
5187 pSMB->WatchTree = 1; /* one byte - no le conversion needed */
5188 pSMB->Reserved2 = 0;
5189 pSMB->CompletionFilter = cpu_to_le32(filter);
5190 pSMB->Fid = netfid; /* file handle always le */
5191 pSMB->ByteCount = 0;
5193 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5194 (struct smb_hdr *)pSMBr, &bytes_returned,
5197 cFYI(1, ("Error in Notify = %d", rc));
5199 /* Add file to outstanding requests */
5200 /* BB change to kmem cache alloc */
5201 dnotify_req = kmalloc(
5202 sizeof(struct dir_notify_req),
5205 dnotify_req->Pid = pSMB->hdr.Pid;
5206 dnotify_req->PidHigh = pSMB->hdr.PidHigh;
5207 dnotify_req->Mid = pSMB->hdr.Mid;
5208 dnotify_req->Tid = pSMB->hdr.Tid;
5209 dnotify_req->Uid = pSMB->hdr.Uid;
5210 dnotify_req->netfid = netfid;
5211 dnotify_req->pfile = pfile;
5212 dnotify_req->filter = filter;
5213 dnotify_req->multishot = multishot;
5214 spin_lock(&GlobalMid_Lock);
5215 list_add_tail(&dnotify_req->lhead,
5216 &GlobalDnotifyReqList);
5217 spin_unlock(&GlobalMid_Lock);
5221 cifs_buf_release(pSMB);
5224 #ifdef CONFIG_CIFS_XATTR
5226 CIFSSMBQAllEAs(const int xid, struct cifsTconInfo *tcon,
5227 const unsigned char *searchName,
5228 char *EAData, size_t buf_size,
5229 const struct nls_table *nls_codepage, int remap)
5231 /* BB assumes one setup word */
5232 TRANSACTION2_QPI_REQ *pSMB = NULL;
5233 TRANSACTION2_QPI_RSP *pSMBr = NULL;
5237 struct fea *temp_fea;
5239 __u16 params, byte_count;
5241 cFYI(1, ("In Query All EAs path %s", searchName));
5243 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5248 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5250 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
5251 PATH_MAX, nls_codepage, remap);
5252 name_len++; /* trailing null */
5254 } else { /* BB improve the check for buffer overruns BB */
5255 name_len = strnlen(searchName, PATH_MAX);
5256 name_len++; /* trailing null */
5257 strncpy(pSMB->FileName, searchName, name_len);
5260 params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */;
5261 pSMB->TotalDataCount = 0;
5262 pSMB->MaxParameterCount = cpu_to_le16(2);
5263 pSMB->MaxDataCount = cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
5264 pSMB->MaxSetupCount = 0;
5268 pSMB->Reserved2 = 0;
5269 pSMB->ParameterOffset = cpu_to_le16(offsetof(
5270 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
5271 pSMB->DataCount = 0;
5272 pSMB->DataOffset = 0;
5273 pSMB->SetupCount = 1;
5274 pSMB->Reserved3 = 0;
5275 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
5276 byte_count = params + 1 /* pad */ ;
5277 pSMB->TotalParameterCount = cpu_to_le16(params);
5278 pSMB->ParameterCount = pSMB->TotalParameterCount;
5279 pSMB->InformationLevel = cpu_to_le16(SMB_INFO_QUERY_ALL_EAS);
5280 pSMB->Reserved4 = 0;
5281 pSMB->hdr.smb_buf_length += byte_count;
5282 pSMB->ByteCount = cpu_to_le16(byte_count);
5284 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5285 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5287 cFYI(1, ("Send error in QueryAllEAs = %d", rc));
5288 } else { /* decode response */
5289 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
5291 /* BB also check enough total bytes returned */
5292 /* BB we need to improve the validity checking
5293 of these trans2 responses */
5294 if (rc || (pSMBr->ByteCount < 4))
5295 rc = -EIO; /* bad smb */
5296 /* else if (pFindData){
5297 memcpy((char *) pFindData,
5298 (char *) &pSMBr->hdr.Protocol +
5301 /* check that length of list is not more than bcc */
5302 /* check that each entry does not go beyond length
5304 /* check that each element of each entry does not
5305 go beyond end of list */
5306 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
5307 struct fealist *ea_response_data;
5309 /* validate_trans2_offsets() */
5310 /* BB check if start of smb + data_offset > &bcc+ bcc */
5311 ea_response_data = (struct fealist *)
5312 (((char *) &pSMBr->hdr.Protocol) +
5314 name_len = le32_to_cpu(ea_response_data->list_len);
5315 cFYI(1, ("ea length %d", name_len));
5316 if (name_len <= 8) {
5317 /* returned EA size zeroed at top of function */
5318 cFYI(1, ("empty EA list returned from server"));
5320 /* account for ea list len */
5322 temp_fea = ea_response_data->list;
5323 temp_ptr = (char *)temp_fea;
5324 while (name_len > 0) {
5328 rc += temp_fea->name_len;
5329 /* account for prefix user. and trailing null */
5331 if (rc < (int)buf_size) {
5332 memcpy(EAData, "user.", 5);
5334 memcpy(EAData, temp_ptr,
5335 temp_fea->name_len);
5336 EAData += temp_fea->name_len;
5337 /* null terminate name */
5339 EAData = EAData + 1;
5340 } else if (buf_size == 0) {
5341 /* skip copy - calc size only */
5343 /* stop before overrun buffer */
5347 name_len -= temp_fea->name_len;
5348 temp_ptr += temp_fea->name_len;
5349 /* account for trailing null */
5353 le16_to_cpu(temp_fea->value_len);
5354 name_len -= value_len;
5355 temp_ptr += value_len;
5356 /* BB check that temp_ptr is still
5359 /* no trailing null to account for
5361 /* go on to next EA */
5362 temp_fea = (struct fea *)temp_ptr;
5368 cifs_buf_release(pSMB);
5375 ssize_t CIFSSMBQueryEA(const int xid, struct cifsTconInfo *tcon,
5376 const unsigned char *searchName, const unsigned char *ea_name,
5377 unsigned char *ea_value, size_t buf_size,
5378 const struct nls_table *nls_codepage, int remap)
5380 TRANSACTION2_QPI_REQ *pSMB = NULL;
5381 TRANSACTION2_QPI_RSP *pSMBr = NULL;
5385 struct fea *temp_fea;
5387 __u16 params, byte_count;
5389 cFYI(1, ("In Query EA path %s", searchName));
5391 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5396 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5398 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
5399 PATH_MAX, nls_codepage, remap);
5400 name_len++; /* trailing null */
5402 } else { /* BB improve the check for buffer overruns BB */
5403 name_len = strnlen(searchName, PATH_MAX);
5404 name_len++; /* trailing null */
5405 strncpy(pSMB->FileName, searchName, name_len);
5408 params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */;
5409 pSMB->TotalDataCount = 0;
5410 pSMB->MaxParameterCount = cpu_to_le16(2);
5411 pSMB->MaxDataCount = cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
5412 pSMB->MaxSetupCount = 0;
5416 pSMB->Reserved2 = 0;
5417 pSMB->ParameterOffset = cpu_to_le16(offsetof(
5418 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
5419 pSMB->DataCount = 0;
5420 pSMB->DataOffset = 0;
5421 pSMB->SetupCount = 1;
5422 pSMB->Reserved3 = 0;
5423 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
5424 byte_count = params + 1 /* pad */ ;
5425 pSMB->TotalParameterCount = cpu_to_le16(params);
5426 pSMB->ParameterCount = pSMB->TotalParameterCount;
5427 pSMB->InformationLevel = cpu_to_le16(SMB_INFO_QUERY_ALL_EAS);
5428 pSMB->Reserved4 = 0;
5429 pSMB->hdr.smb_buf_length += byte_count;
5430 pSMB->ByteCount = cpu_to_le16(byte_count);
5432 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5433 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5435 cFYI(1, ("Send error in Query EA = %d", rc));
5436 } else { /* decode response */
5437 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
5439 /* BB also check enough total bytes returned */
5440 /* BB we need to improve the validity checking
5441 of these trans2 responses */
5442 if (rc || (pSMBr->ByteCount < 4))
5443 rc = -EIO; /* bad smb */
5444 /* else if (pFindData){
5445 memcpy((char *) pFindData,
5446 (char *) &pSMBr->hdr.Protocol +
5449 /* check that length of list is not more than bcc */
5450 /* check that each entry does not go beyond length
5452 /* check that each element of each entry does not
5453 go beyond end of list */
5454 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
5455 struct fealist *ea_response_data;
5457 /* validate_trans2_offsets() */
5458 /* BB check if start of smb + data_offset > &bcc+ bcc*/
5459 ea_response_data = (struct fealist *)
5460 (((char *) &pSMBr->hdr.Protocol) +
5462 name_len = le32_to_cpu(ea_response_data->list_len);
5463 cFYI(1, ("ea length %d", name_len));
5464 if (name_len <= 8) {
5465 /* returned EA size zeroed at top of function */
5466 cFYI(1, ("empty EA list returned from server"));
5468 /* account for ea list len */
5470 temp_fea = ea_response_data->list;
5471 temp_ptr = (char *)temp_fea;
5472 /* loop through checking if we have a matching
5473 name and then return the associated value */
5474 while (name_len > 0) {
5479 le16_to_cpu(temp_fea->value_len);
5480 /* BB validate that value_len falls within SMB,
5481 even though maximum for name_len is 255 */
5482 if (memcmp(temp_fea->name, ea_name,
5483 temp_fea->name_len) == 0) {
5486 /* account for prefix user. and trailing null */
5487 if (rc <= (int)buf_size) {
5489 temp_fea->name+temp_fea->name_len+1,
5491 /* ea values, unlike ea
5494 } else if (buf_size == 0) {
5495 /* skip copy - calc size only */
5497 /* stop before overrun buffer */
5502 name_len -= temp_fea->name_len;
5503 temp_ptr += temp_fea->name_len;
5504 /* account for trailing null */
5507 name_len -= value_len;
5508 temp_ptr += value_len;
5509 /* No trailing null to account for in
5510 value_len. Go on to next EA */
5511 temp_fea = (struct fea *)temp_ptr;
5517 cifs_buf_release(pSMB);
5525 CIFSSMBSetEA(const int xid, struct cifsTconInfo *tcon, const char *fileName,
5526 const char *ea_name, const void *ea_value,
5527 const __u16 ea_value_len, const struct nls_table *nls_codepage,
5530 struct smb_com_transaction2_spi_req *pSMB = NULL;
5531 struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
5532 struct fealist *parm_data;
5535 int bytes_returned = 0;
5536 __u16 params, param_offset, byte_count, offset, count;
5538 cFYI(1, ("In SetEA"));
5540 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5545 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5547 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
5548 PATH_MAX, nls_codepage, remap);
5549 name_len++; /* trailing null */
5551 } else { /* BB improve the check for buffer overruns BB */
5552 name_len = strnlen(fileName, PATH_MAX);
5553 name_len++; /* trailing null */
5554 strncpy(pSMB->FileName, fileName, name_len);
5557 params = 6 + name_len;
5559 /* done calculating parms using name_len of file name,
5560 now use name_len to calculate length of ea name
5561 we are going to create in the inode xattrs */
5562 if (ea_name == NULL)
5565 name_len = strnlen(ea_name, 255);
5567 count = sizeof(*parm_data) + ea_value_len + name_len;
5568 pSMB->MaxParameterCount = cpu_to_le16(2);
5569 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB size from sess */
5570 pSMB->MaxSetupCount = 0;
5574 pSMB->Reserved2 = 0;
5575 param_offset = offsetof(struct smb_com_transaction2_spi_req,
5576 InformationLevel) - 4;
5577 offset = param_offset + params;
5578 pSMB->InformationLevel =
5579 cpu_to_le16(SMB_SET_FILE_EA);
5582 (struct fealist *) (((char *) &pSMB->hdr.Protocol) +
5584 pSMB->ParameterOffset = cpu_to_le16(param_offset);
5585 pSMB->DataOffset = cpu_to_le16(offset);
5586 pSMB->SetupCount = 1;
5587 pSMB->Reserved3 = 0;
5588 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
5589 byte_count = 3 /* pad */ + params + count;
5590 pSMB->DataCount = cpu_to_le16(count);
5591 parm_data->list_len = cpu_to_le32(count);
5592 parm_data->list[0].EA_flags = 0;
5593 /* we checked above that name len is less than 255 */
5594 parm_data->list[0].name_len = (__u8)name_len;
5595 /* EA names are always ASCII */
5597 strncpy(parm_data->list[0].name, ea_name, name_len);
5598 parm_data->list[0].name[name_len] = 0;
5599 parm_data->list[0].value_len = cpu_to_le16(ea_value_len);
5600 /* caller ensures that ea_value_len is less than 64K but
5601 we need to ensure that it fits within the smb */
5603 /*BB add length check to see if it would fit in
5604 negotiated SMB buffer size BB */
5605 /* if (ea_value_len > buffer_size - 512 (enough for header)) */
5607 memcpy(parm_data->list[0].name+name_len+1,
5608 ea_value, ea_value_len);
5610 pSMB->TotalDataCount = pSMB->DataCount;
5611 pSMB->ParameterCount = cpu_to_le16(params);
5612 pSMB->TotalParameterCount = pSMB->ParameterCount;
5613 pSMB->Reserved4 = 0;
5614 pSMB->hdr.smb_buf_length += byte_count;
5615 pSMB->ByteCount = cpu_to_le16(byte_count);
5616 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5617 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5619 cFYI(1, ("SetPathInfo (EA) returned %d", rc));
5622 cifs_buf_release(pSMB);