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.
650 /* BB Need to fill struct for sessetup here */
657 server->capabilities &= ~CAP_EXTENDED_SECURITY;
659 #ifdef CONFIG_CIFS_WEAK_PW_HASH
662 if ((secFlags & CIFSSEC_MAY_SIGN) == 0) {
663 /* MUST_SIGN already includes the MAY_SIGN FLAG
664 so if this is zero it means that signing is disabled */
665 cFYI(1, ("Signing disabled"));
666 if (server->secMode & SECMODE_SIGN_REQUIRED) {
667 cERROR(1, ("Server requires "
668 "packet signing to be enabled in "
669 "/proc/fs/cifs/SecurityFlags."));
673 ~(SECMODE_SIGN_ENABLED | SECMODE_SIGN_REQUIRED);
674 } else if ((secFlags & CIFSSEC_MUST_SIGN) == CIFSSEC_MUST_SIGN) {
675 /* signing required */
676 cFYI(1, ("Must sign - secFlags 0x%x", secFlags));
677 if ((server->secMode &
678 (SECMODE_SIGN_ENABLED | SECMODE_SIGN_REQUIRED)) == 0) {
680 ("signing required but server lacks support"));
683 server->secMode |= SECMODE_SIGN_REQUIRED;
685 /* signing optional ie CIFSSEC_MAY_SIGN */
686 if ((server->secMode & SECMODE_SIGN_REQUIRED) == 0)
688 ~(SECMODE_SIGN_ENABLED | SECMODE_SIGN_REQUIRED);
692 cifs_buf_release(pSMB);
694 cFYI(1, ("negprot rc %d", rc));
699 CIFSSMBTDis(const int xid, struct cifsTconInfo *tcon)
701 struct smb_hdr *smb_buffer;
702 struct smb_hdr *smb_buffer_response; /* BB removeme BB */
706 cFYI(1, ("In tree disconnect"));
708 * If last user of the connection and
709 * connection alive - disconnect it
710 * If this is the last connection on the server session disconnect it
711 * (and inside session disconnect we should check if tcp socket needs
712 * to be freed and kernel thread woken up).
715 down(&tcon->tconSem);
719 atomic_dec(&tcon->useCount);
720 if (atomic_read(&tcon->useCount) > 0) {
725 /* No need to return error on this operation if tid invalidated and
726 closed on server already e.g. due to tcp session crashing */
727 if (tcon->tidStatus == CifsNeedReconnect) {
732 if ((tcon->ses == NULL) || (tcon->ses->server == NULL)) {
736 rc = small_smb_init(SMB_COM_TREE_DISCONNECT, 0, tcon,
737 (void **)&smb_buffer);
742 smb_buffer_response = smb_buffer; /* BB removeme BB */
744 rc = SendReceive(xid, tcon->ses, smb_buffer, smb_buffer_response,
747 cFYI(1, ("Tree disconnect failed %d", rc));
750 cifs_small_buf_release(smb_buffer);
753 /* No need to return error on this operation if tid invalidated and
754 closed on server already e.g. due to tcp session crashing */
762 CIFSSMBLogoff(const int xid, struct cifsSesInfo *ses)
764 struct smb_hdr *smb_buffer_response;
765 LOGOFF_ANDX_REQ *pSMB;
769 cFYI(1, ("In SMBLogoff for session disconnect"));
775 atomic_dec(&ses->inUse);
776 if (atomic_read(&ses->inUse) > 0) {
780 rc = small_smb_init(SMB_COM_LOGOFF_ANDX, 2, NULL, (void **)&pSMB);
786 smb_buffer_response = (struct smb_hdr *)pSMB; /* BB removeme BB */
789 pSMB->hdr.Mid = GetNextMid(ses->server);
791 if (ses->server->secMode &
792 (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
793 pSMB->hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
796 pSMB->hdr.Uid = ses->Suid;
798 pSMB->AndXCommand = 0xFF;
799 rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB,
800 smb_buffer_response, &length, 0);
802 atomic_dec(&ses->server->socketUseCount);
803 if (atomic_read(&ses->server->socketUseCount) == 0) {
804 spin_lock(&GlobalMid_Lock);
805 ses->server->tcpStatus = CifsExiting;
806 spin_unlock(&GlobalMid_Lock);
811 cifs_small_buf_release(pSMB);
813 /* if session dead then we do not need to do ulogoff,
814 since server closed smb session, no sense reporting
822 CIFSPOSIXDelFile(const int xid, struct cifsTconInfo *tcon, const char *fileName,
823 __u16 type, const struct nls_table *nls_codepage, int remap)
825 TRANSACTION2_SPI_REQ *pSMB = NULL;
826 TRANSACTION2_SPI_RSP *pSMBr = NULL;
827 struct unlink_psx_rq *pRqD;
830 int bytes_returned = 0;
831 __u16 params, param_offset, offset, byte_count;
833 cFYI(1, ("In POSIX delete"));
835 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
840 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
842 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
843 PATH_MAX, nls_codepage, remap);
844 name_len++; /* trailing null */
846 } else { /* BB add path length overrun check */
847 name_len = strnlen(fileName, PATH_MAX);
848 name_len++; /* trailing null */
849 strncpy(pSMB->FileName, fileName, name_len);
852 params = 6 + name_len;
853 pSMB->MaxParameterCount = cpu_to_le16(2);
854 pSMB->MaxDataCount = 0; /* BB double check this with jra */
855 pSMB->MaxSetupCount = 0;
860 param_offset = offsetof(struct smb_com_transaction2_spi_req,
861 InformationLevel) - 4;
862 offset = param_offset + params;
864 /* Setup pointer to Request Data (inode type) */
865 pRqD = (struct unlink_psx_rq *)(((char *)&pSMB->hdr.Protocol) + offset);
866 pRqD->type = cpu_to_le16(type);
867 pSMB->ParameterOffset = cpu_to_le16(param_offset);
868 pSMB->DataOffset = cpu_to_le16(offset);
869 pSMB->SetupCount = 1;
871 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
872 byte_count = 3 /* pad */ + params + sizeof(struct unlink_psx_rq);
874 pSMB->DataCount = cpu_to_le16(sizeof(struct unlink_psx_rq));
875 pSMB->TotalDataCount = cpu_to_le16(sizeof(struct unlink_psx_rq));
876 pSMB->ParameterCount = cpu_to_le16(params);
877 pSMB->TotalParameterCount = pSMB->ParameterCount;
878 pSMB->InformationLevel = cpu_to_le16(SMB_POSIX_UNLINK);
880 pSMB->hdr.smb_buf_length += byte_count;
881 pSMB->ByteCount = cpu_to_le16(byte_count);
882 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
883 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
885 cFYI(1, ("Posix delete returned %d", rc));
887 cifs_buf_release(pSMB);
889 cifs_stats_inc(&tcon->num_deletes);
898 CIFSSMBDelFile(const int xid, struct cifsTconInfo *tcon, const char *fileName,
899 const struct nls_table *nls_codepage, int remap)
901 DELETE_FILE_REQ *pSMB = NULL;
902 DELETE_FILE_RSP *pSMBr = NULL;
908 rc = smb_init(SMB_COM_DELETE, 1, tcon, (void **) &pSMB,
913 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
915 cifsConvertToUCS((__le16 *) pSMB->fileName, fileName,
916 PATH_MAX, nls_codepage, remap);
917 name_len++; /* trailing null */
919 } else { /* BB improve check for buffer overruns BB */
920 name_len = strnlen(fileName, PATH_MAX);
921 name_len++; /* trailing null */
922 strncpy(pSMB->fileName, fileName, name_len);
924 pSMB->SearchAttributes =
925 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM);
926 pSMB->BufferFormat = 0x04;
927 pSMB->hdr.smb_buf_length += name_len + 1;
928 pSMB->ByteCount = cpu_to_le16(name_len + 1);
929 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
930 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
931 cifs_stats_inc(&tcon->num_deletes);
933 cFYI(1, ("Error in RMFile = %d", rc));
936 cifs_buf_release(pSMB);
944 CIFSSMBRmDir(const int xid, struct cifsTconInfo *tcon, const char *dirName,
945 const struct nls_table *nls_codepage, int remap)
947 DELETE_DIRECTORY_REQ *pSMB = NULL;
948 DELETE_DIRECTORY_RSP *pSMBr = NULL;
953 cFYI(1, ("In CIFSSMBRmDir"));
955 rc = smb_init(SMB_COM_DELETE_DIRECTORY, 0, tcon, (void **) &pSMB,
960 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
961 name_len = cifsConvertToUCS((__le16 *) pSMB->DirName, dirName,
962 PATH_MAX, nls_codepage, remap);
963 name_len++; /* trailing null */
965 } else { /* BB improve check for buffer overruns BB */
966 name_len = strnlen(dirName, PATH_MAX);
967 name_len++; /* trailing null */
968 strncpy(pSMB->DirName, dirName, name_len);
971 pSMB->BufferFormat = 0x04;
972 pSMB->hdr.smb_buf_length += name_len + 1;
973 pSMB->ByteCount = cpu_to_le16(name_len + 1);
974 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
975 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
976 cifs_stats_inc(&tcon->num_rmdirs);
978 cFYI(1, ("Error in RMDir = %d", rc));
981 cifs_buf_release(pSMB);
988 CIFSSMBMkDir(const int xid, struct cifsTconInfo *tcon,
989 const char *name, const struct nls_table *nls_codepage, int remap)
992 CREATE_DIRECTORY_REQ *pSMB = NULL;
993 CREATE_DIRECTORY_RSP *pSMBr = NULL;
997 cFYI(1, ("In CIFSSMBMkDir"));
999 rc = smb_init(SMB_COM_CREATE_DIRECTORY, 0, tcon, (void **) &pSMB,
1004 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1005 name_len = cifsConvertToUCS((__le16 *) pSMB->DirName, name,
1006 PATH_MAX, nls_codepage, remap);
1007 name_len++; /* trailing null */
1009 } else { /* BB improve check for buffer overruns BB */
1010 name_len = strnlen(name, PATH_MAX);
1011 name_len++; /* trailing null */
1012 strncpy(pSMB->DirName, name, name_len);
1015 pSMB->BufferFormat = 0x04;
1016 pSMB->hdr.smb_buf_length += name_len + 1;
1017 pSMB->ByteCount = cpu_to_le16(name_len + 1);
1018 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1019 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1020 cifs_stats_inc(&tcon->num_mkdirs);
1022 cFYI(1, ("Error in Mkdir = %d", rc));
1025 cifs_buf_release(pSMB);
1032 CIFSPOSIXCreate(const int xid, struct cifsTconInfo *tcon, __u32 posix_flags,
1033 __u64 mode, __u16 * netfid, FILE_UNIX_BASIC_INFO *pRetData,
1034 __u32 *pOplock, const char *name,
1035 const struct nls_table *nls_codepage, int remap)
1037 TRANSACTION2_SPI_REQ *pSMB = NULL;
1038 TRANSACTION2_SPI_RSP *pSMBr = NULL;
1041 int bytes_returned = 0;
1042 __u16 params, param_offset, offset, byte_count, count;
1043 OPEN_PSX_REQ * pdata;
1044 OPEN_PSX_RSP * psx_rsp;
1046 cFYI(1, ("In POSIX Create"));
1048 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
1053 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1055 cifsConvertToUCS((__le16 *) pSMB->FileName, name,
1056 PATH_MAX, nls_codepage, remap);
1057 name_len++; /* trailing null */
1059 } else { /* BB improve the check for buffer overruns BB */
1060 name_len = strnlen(name, PATH_MAX);
1061 name_len++; /* trailing null */
1062 strncpy(pSMB->FileName, name, name_len);
1065 params = 6 + name_len;
1066 count = sizeof(OPEN_PSX_REQ);
1067 pSMB->MaxParameterCount = cpu_to_le16(2);
1068 pSMB->MaxDataCount = cpu_to_le16(1000); /* large enough */
1069 pSMB->MaxSetupCount = 0;
1073 pSMB->Reserved2 = 0;
1074 param_offset = offsetof(struct smb_com_transaction2_spi_req,
1075 InformationLevel) - 4;
1076 offset = param_offset + params;
1077 pdata = (OPEN_PSX_REQ *)(((char *)&pSMB->hdr.Protocol) + offset);
1078 pdata->Level = cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC);
1079 pdata->Permissions = cpu_to_le64(mode);
1080 pdata->PosixOpenFlags = cpu_to_le32(posix_flags);
1081 pdata->OpenFlags = cpu_to_le32(*pOplock);
1082 pSMB->ParameterOffset = cpu_to_le16(param_offset);
1083 pSMB->DataOffset = cpu_to_le16(offset);
1084 pSMB->SetupCount = 1;
1085 pSMB->Reserved3 = 0;
1086 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
1087 byte_count = 3 /* pad */ + params + count;
1089 pSMB->DataCount = cpu_to_le16(count);
1090 pSMB->ParameterCount = cpu_to_le16(params);
1091 pSMB->TotalDataCount = pSMB->DataCount;
1092 pSMB->TotalParameterCount = pSMB->ParameterCount;
1093 pSMB->InformationLevel = cpu_to_le16(SMB_POSIX_OPEN);
1094 pSMB->Reserved4 = 0;
1095 pSMB->hdr.smb_buf_length += byte_count;
1096 pSMB->ByteCount = cpu_to_le16(byte_count);
1097 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1098 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1100 cFYI(1, ("Posix create returned %d", rc));
1101 goto psx_create_err;
1104 cFYI(1, ("copying inode info"));
1105 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
1107 if (rc || (pSMBr->ByteCount < sizeof(OPEN_PSX_RSP))) {
1108 rc = -EIO; /* bad smb */
1109 goto psx_create_err;
1112 /* copy return information to pRetData */
1113 psx_rsp = (OPEN_PSX_RSP *)((char *) &pSMBr->hdr.Protocol
1114 + le16_to_cpu(pSMBr->t2.DataOffset));
1116 *pOplock = le16_to_cpu(psx_rsp->OplockFlags);
1118 *netfid = psx_rsp->Fid; /* cifs fid stays in le */
1119 /* Let caller know file was created so we can set the mode. */
1120 /* Do we care about the CreateAction in any other cases? */
1121 if (cpu_to_le32(FILE_CREATE) == psx_rsp->CreateAction)
1122 *pOplock |= CIFS_CREATE_ACTION;
1123 /* check to make sure response data is there */
1124 if (psx_rsp->ReturnedLevel != cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC)) {
1125 pRetData->Type = cpu_to_le32(-1); /* unknown */
1126 #ifdef CONFIG_CIFS_DEBUG2
1127 cFYI(1, ("unknown type"));
1130 if (pSMBr->ByteCount < sizeof(OPEN_PSX_RSP)
1131 + sizeof(FILE_UNIX_BASIC_INFO)) {
1132 cERROR(1, ("Open response data too small"));
1133 pRetData->Type = cpu_to_le32(-1);
1134 goto psx_create_err;
1136 memcpy((char *) pRetData,
1137 (char *)psx_rsp + sizeof(OPEN_PSX_RSP),
1138 sizeof(FILE_UNIX_BASIC_INFO));
1142 cifs_buf_release(pSMB);
1144 cifs_stats_inc(&tcon->num_mkdirs);
1152 static __u16 convert_disposition(int disposition)
1156 switch (disposition) {
1157 case FILE_SUPERSEDE:
1158 ofun = SMBOPEN_OCREATE | SMBOPEN_OTRUNC;
1161 ofun = SMBOPEN_OAPPEND;
1164 ofun = SMBOPEN_OCREATE;
1167 ofun = SMBOPEN_OCREATE | SMBOPEN_OAPPEND;
1169 case FILE_OVERWRITE:
1170 ofun = SMBOPEN_OTRUNC;
1172 case FILE_OVERWRITE_IF:
1173 ofun = SMBOPEN_OCREATE | SMBOPEN_OTRUNC;
1176 cFYI(1, ("unknown disposition %d", disposition));
1177 ofun = SMBOPEN_OAPPEND; /* regular open */
1183 SMBLegacyOpen(const int xid, struct cifsTconInfo *tcon,
1184 const char *fileName, const int openDisposition,
1185 const int access_flags, const int create_options, __u16 * netfid,
1186 int *pOplock, FILE_ALL_INFO * pfile_info,
1187 const struct nls_table *nls_codepage, int remap)
1190 OPENX_REQ *pSMB = NULL;
1191 OPENX_RSP *pSMBr = NULL;
1197 rc = smb_init(SMB_COM_OPEN_ANDX, 15, tcon, (void **) &pSMB,
1202 pSMB->AndXCommand = 0xFF; /* none */
1204 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1205 count = 1; /* account for one byte pad to word boundary */
1207 cifsConvertToUCS((__le16 *) (pSMB->fileName + 1),
1208 fileName, PATH_MAX, nls_codepage, remap);
1209 name_len++; /* trailing null */
1211 } else { /* BB improve check for buffer overruns BB */
1212 count = 0; /* no pad */
1213 name_len = strnlen(fileName, PATH_MAX);
1214 name_len++; /* trailing null */
1215 strncpy(pSMB->fileName, fileName, name_len);
1217 if (*pOplock & REQ_OPLOCK)
1218 pSMB->OpenFlags = cpu_to_le16(REQ_OPLOCK);
1219 else if (*pOplock & REQ_BATCHOPLOCK)
1220 pSMB->OpenFlags = cpu_to_le16(REQ_BATCHOPLOCK);
1222 pSMB->OpenFlags |= cpu_to_le16(REQ_MORE_INFO);
1223 /* BB fixme add conversion for access_flags to bits 0 - 2 of mode */
1229 pSMB->Mode = cpu_to_le16(2);
1230 pSMB->Mode |= cpu_to_le16(0x40); /* deny none */
1231 /* set file as system file if special file such
1232 as fifo and server expecting SFU style and
1233 no Unix extensions */
1235 if (create_options & CREATE_OPTION_SPECIAL)
1236 pSMB->FileAttributes = cpu_to_le16(ATTR_SYSTEM);
1238 pSMB->FileAttributes = cpu_to_le16(0/*ATTR_NORMAL*/); /* BB FIXME */
1240 /* if ((omode & S_IWUGO) == 0)
1241 pSMB->FileAttributes |= cpu_to_le32(ATTR_READONLY);*/
1242 /* Above line causes problems due to vfs splitting create into two
1243 pieces - need to set mode after file created not while it is
1247 /* pSMB->CreateOptions = cpu_to_le32(create_options &
1248 CREATE_OPTIONS_MASK); */
1249 /* BB FIXME END BB */
1251 pSMB->Sattr = cpu_to_le16(ATTR_HIDDEN | ATTR_SYSTEM | ATTR_DIRECTORY);
1252 pSMB->OpenFunction = cpu_to_le16(convert_disposition(openDisposition));
1254 pSMB->hdr.smb_buf_length += count;
1256 pSMB->ByteCount = cpu_to_le16(count);
1257 /* long_op set to 1 to allow for oplock break timeouts */
1258 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1259 (struct smb_hdr *) pSMBr, &bytes_returned, 1);
1260 cifs_stats_inc(&tcon->num_opens);
1262 cFYI(1, ("Error in Open = %d", rc));
1264 /* BB verify if wct == 15 */
1266 /* *pOplock = pSMBr->OplockLevel; */ /* BB take from action field BB */
1268 *netfid = pSMBr->Fid; /* cifs fid stays in le */
1269 /* Let caller know file was created so we can set the mode. */
1270 /* Do we care about the CreateAction in any other cases? */
1272 /* if (cpu_to_le32(FILE_CREATE) == pSMBr->CreateAction)
1273 *pOplock |= CIFS_CREATE_ACTION; */
1277 pfile_info->CreationTime = 0; /* BB convert CreateTime*/
1278 pfile_info->LastAccessTime = 0; /* BB fixme */
1279 pfile_info->LastWriteTime = 0; /* BB fixme */
1280 pfile_info->ChangeTime = 0; /* BB fixme */
1281 pfile_info->Attributes =
1282 cpu_to_le32(le16_to_cpu(pSMBr->FileAttributes));
1283 /* the file_info buf is endian converted by caller */
1284 pfile_info->AllocationSize =
1285 cpu_to_le64(le32_to_cpu(pSMBr->EndOfFile));
1286 pfile_info->EndOfFile = pfile_info->AllocationSize;
1287 pfile_info->NumberOfLinks = cpu_to_le32(1);
1291 cifs_buf_release(pSMB);
1298 CIFSSMBOpen(const int xid, struct cifsTconInfo *tcon,
1299 const char *fileName, const int openDisposition,
1300 const int access_flags, const int create_options, __u16 * netfid,
1301 int *pOplock, FILE_ALL_INFO * pfile_info,
1302 const struct nls_table *nls_codepage, int remap)
1305 OPEN_REQ *pSMB = NULL;
1306 OPEN_RSP *pSMBr = NULL;
1312 rc = smb_init(SMB_COM_NT_CREATE_ANDX, 24, tcon, (void **) &pSMB,
1317 pSMB->AndXCommand = 0xFF; /* none */
1319 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1320 count = 1; /* account for one byte pad to word boundary */
1322 cifsConvertToUCS((__le16 *) (pSMB->fileName + 1),
1323 fileName, PATH_MAX, nls_codepage, remap);
1324 name_len++; /* trailing null */
1326 pSMB->NameLength = cpu_to_le16(name_len);
1327 } else { /* BB improve check for buffer overruns BB */
1328 count = 0; /* no pad */
1329 name_len = strnlen(fileName, PATH_MAX);
1330 name_len++; /* trailing null */
1331 pSMB->NameLength = cpu_to_le16(name_len);
1332 strncpy(pSMB->fileName, fileName, name_len);
1334 if (*pOplock & REQ_OPLOCK)
1335 pSMB->OpenFlags = cpu_to_le32(REQ_OPLOCK);
1336 else if (*pOplock & REQ_BATCHOPLOCK)
1337 pSMB->OpenFlags = cpu_to_le32(REQ_BATCHOPLOCK);
1338 pSMB->DesiredAccess = cpu_to_le32(access_flags);
1339 pSMB->AllocationSize = 0;
1340 /* set file as system file if special file such
1341 as fifo and server expecting SFU style and
1342 no Unix extensions */
1343 if (create_options & CREATE_OPTION_SPECIAL)
1344 pSMB->FileAttributes = cpu_to_le32(ATTR_SYSTEM);
1346 pSMB->FileAttributes = cpu_to_le32(ATTR_NORMAL);
1347 /* XP does not handle ATTR_POSIX_SEMANTICS */
1348 /* but it helps speed up case sensitive checks for other
1349 servers such as Samba */
1350 if (tcon->ses->capabilities & CAP_UNIX)
1351 pSMB->FileAttributes |= cpu_to_le32(ATTR_POSIX_SEMANTICS);
1353 /* if ((omode & S_IWUGO) == 0)
1354 pSMB->FileAttributes |= cpu_to_le32(ATTR_READONLY);*/
1355 /* Above line causes problems due to vfs splitting create into two
1356 pieces - need to set mode after file created not while it is
1358 pSMB->ShareAccess = cpu_to_le32(FILE_SHARE_ALL);
1359 pSMB->CreateDisposition = cpu_to_le32(openDisposition);
1360 pSMB->CreateOptions = cpu_to_le32(create_options & CREATE_OPTIONS_MASK);
1361 /* BB Expirement with various impersonation levels and verify */
1362 pSMB->ImpersonationLevel = cpu_to_le32(SECURITY_IMPERSONATION);
1363 pSMB->SecurityFlags =
1364 SECURITY_CONTEXT_TRACKING | SECURITY_EFFECTIVE_ONLY;
1367 pSMB->hdr.smb_buf_length += count;
1369 pSMB->ByteCount = cpu_to_le16(count);
1370 /* long_op set to 1 to allow for oplock break timeouts */
1371 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1372 (struct smb_hdr *) pSMBr, &bytes_returned, 1);
1373 cifs_stats_inc(&tcon->num_opens);
1375 cFYI(1, ("Error in Open = %d", rc));
1377 *pOplock = pSMBr->OplockLevel; /* 1 byte no need to le_to_cpu */
1378 *netfid = pSMBr->Fid; /* cifs fid stays in le */
1379 /* Let caller know file was created so we can set the mode. */
1380 /* Do we care about the CreateAction in any other cases? */
1381 if (cpu_to_le32(FILE_CREATE) == pSMBr->CreateAction)
1382 *pOplock |= CIFS_CREATE_ACTION;
1384 memcpy((char *)pfile_info, (char *)&pSMBr->CreationTime,
1385 36 /* CreationTime to Attributes */);
1386 /* the file_info buf is endian converted by caller */
1387 pfile_info->AllocationSize = pSMBr->AllocationSize;
1388 pfile_info->EndOfFile = pSMBr->EndOfFile;
1389 pfile_info->NumberOfLinks = cpu_to_le32(1);
1393 cifs_buf_release(pSMB);
1400 CIFSSMBRead(const int xid, struct cifsTconInfo *tcon, const int netfid,
1401 const unsigned int count, const __u64 lseek, unsigned int *nbytes,
1402 char **buf, int *pbuf_type)
1405 READ_REQ *pSMB = NULL;
1406 READ_RSP *pSMBr = NULL;
1407 char *pReadData = NULL;
1409 int resp_buf_type = 0;
1412 cFYI(1, ("Reading %d bytes on fid %d", count, netfid));
1413 if (tcon->ses->capabilities & CAP_LARGE_FILES)
1416 wct = 10; /* old style read */
1419 rc = small_smb_init(SMB_COM_READ_ANDX, wct, tcon, (void **) &pSMB);
1423 /* tcon and ses pointer are checked in smb_init */
1424 if (tcon->ses->server == NULL)
1425 return -ECONNABORTED;
1427 pSMB->AndXCommand = 0xFF; /* none */
1429 pSMB->OffsetLow = cpu_to_le32(lseek & 0xFFFFFFFF);
1431 pSMB->OffsetHigh = cpu_to_le32(lseek >> 32);
1432 else if ((lseek >> 32) > 0) /* can not handle this big offset for old */
1435 pSMB->Remaining = 0;
1436 pSMB->MaxCount = cpu_to_le16(count & 0xFFFF);
1437 pSMB->MaxCountHigh = cpu_to_le32(count >> 16);
1439 pSMB->ByteCount = 0; /* no need to do le conversion since 0 */
1441 /* old style read */
1442 struct smb_com_readx_req *pSMBW =
1443 (struct smb_com_readx_req *)pSMB;
1444 pSMBW->ByteCount = 0;
1447 iov[0].iov_base = (char *)pSMB;
1448 iov[0].iov_len = pSMB->hdr.smb_buf_length + 4;
1449 rc = SendReceive2(xid, tcon->ses, iov, 1 /* num iovecs */,
1450 &resp_buf_type, 0 /* not long op */, 1 /* log err */ );
1451 cifs_stats_inc(&tcon->num_reads);
1452 pSMBr = (READ_RSP *)iov[0].iov_base;
1454 cERROR(1, ("Send error in read = %d", rc));
1456 int data_length = le16_to_cpu(pSMBr->DataLengthHigh);
1457 data_length = data_length << 16;
1458 data_length += le16_to_cpu(pSMBr->DataLength);
1459 *nbytes = data_length;
1461 /*check that DataLength would not go beyond end of SMB */
1462 if ((data_length > CIFSMaxBufSize)
1463 || (data_length > count)) {
1464 cFYI(1, ("bad length %d for count %d",
1465 data_length, count));
1469 pReadData = (char *) (&pSMBr->hdr.Protocol) +
1470 le16_to_cpu(pSMBr->DataOffset);
1471 /* if (rc = copy_to_user(buf, pReadData, data_length)) {
1472 cERROR(1,("Faulting on read rc = %d",rc));
1474 }*/ /* can not use copy_to_user when using page cache*/
1476 memcpy(*buf, pReadData, data_length);
1480 /* cifs_small_buf_release(pSMB); */ /* Freed earlier now in SendReceive2 */
1482 if (resp_buf_type == CIFS_SMALL_BUFFER)
1483 cifs_small_buf_release(iov[0].iov_base);
1484 else if (resp_buf_type == CIFS_LARGE_BUFFER)
1485 cifs_buf_release(iov[0].iov_base);
1486 } else if (resp_buf_type != CIFS_NO_BUFFER) {
1487 /* return buffer to caller to free */
1488 *buf = iov[0].iov_base;
1489 if (resp_buf_type == CIFS_SMALL_BUFFER)
1490 *pbuf_type = CIFS_SMALL_BUFFER;
1491 else if (resp_buf_type == CIFS_LARGE_BUFFER)
1492 *pbuf_type = CIFS_LARGE_BUFFER;
1493 } /* else no valid buffer on return - leave as null */
1495 /* Note: On -EAGAIN error only caller can retry on handle based calls
1496 since file handle passed in no longer valid */
1502 CIFSSMBWrite(const int xid, struct cifsTconInfo *tcon,
1503 const int netfid, const unsigned int count,
1504 const __u64 offset, unsigned int *nbytes, const char *buf,
1505 const char __user *ubuf, const int long_op)
1508 WRITE_REQ *pSMB = NULL;
1509 WRITE_RSP *pSMBr = NULL;
1510 int bytes_returned, wct;
1514 /* cFYI(1,("write at %lld %d bytes",offset,count));*/
1515 if (tcon->ses == NULL)
1516 return -ECONNABORTED;
1518 if (tcon->ses->capabilities & CAP_LARGE_FILES)
1523 rc = smb_init(SMB_COM_WRITE_ANDX, wct, tcon, (void **) &pSMB,
1527 /* tcon and ses pointer are checked in smb_init */
1528 if (tcon->ses->server == NULL)
1529 return -ECONNABORTED;
1531 pSMB->AndXCommand = 0xFF; /* none */
1533 pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF);
1535 pSMB->OffsetHigh = cpu_to_le32(offset >> 32);
1536 else if ((offset >> 32) > 0) /* can not handle big offset for old srv */
1539 pSMB->Reserved = 0xFFFFFFFF;
1540 pSMB->WriteMode = 0;
1541 pSMB->Remaining = 0;
1543 /* Can increase buffer size if buffer is big enough in some cases ie we
1544 can send more if LARGE_WRITE_X capability returned by the server and if
1545 our buffer is big enough or if we convert to iovecs on socket writes
1546 and eliminate the copy to the CIFS buffer */
1547 if (tcon->ses->capabilities & CAP_LARGE_WRITE_X) {
1548 bytes_sent = min_t(const unsigned int, CIFSMaxBufSize, count);
1550 bytes_sent = (tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE)
1554 if (bytes_sent > count)
1557 cpu_to_le16(offsetof(struct smb_com_write_req, Data) - 4);
1559 memcpy(pSMB->Data, buf, bytes_sent);
1561 if (copy_from_user(pSMB->Data, ubuf, bytes_sent)) {
1562 cifs_buf_release(pSMB);
1565 } else if (count != 0) {
1567 cifs_buf_release(pSMB);
1569 } /* else setting file size with write of zero bytes */
1571 byte_count = bytes_sent + 1; /* pad */
1572 else /* wct == 12 */ {
1573 byte_count = bytes_sent + 5; /* bigger pad, smaller smb hdr */
1575 pSMB->DataLengthLow = cpu_to_le16(bytes_sent & 0xFFFF);
1576 pSMB->DataLengthHigh = cpu_to_le16(bytes_sent >> 16);
1577 pSMB->hdr.smb_buf_length += byte_count;
1580 pSMB->ByteCount = cpu_to_le16(byte_count);
1581 else { /* old style write has byte count 4 bytes earlier
1583 struct smb_com_writex_req *pSMBW =
1584 (struct smb_com_writex_req *)pSMB;
1585 pSMBW->ByteCount = cpu_to_le16(byte_count);
1588 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1589 (struct smb_hdr *) pSMBr, &bytes_returned, long_op);
1590 cifs_stats_inc(&tcon->num_writes);
1592 cFYI(1, ("Send error in write = %d", rc));
1595 *nbytes = le16_to_cpu(pSMBr->CountHigh);
1596 *nbytes = (*nbytes) << 16;
1597 *nbytes += le16_to_cpu(pSMBr->Count);
1600 cifs_buf_release(pSMB);
1602 /* Note: On -EAGAIN error only caller can retry on handle based calls
1603 since file handle passed in no longer valid */
1609 CIFSSMBWrite2(const int xid, struct cifsTconInfo *tcon,
1610 const int netfid, const unsigned int count,
1611 const __u64 offset, unsigned int *nbytes, struct kvec *iov,
1612 int n_vec, const int long_op)
1615 WRITE_REQ *pSMB = NULL;
1618 int resp_buf_type = 0;
1620 cFYI(1, ("write2 at %lld %d bytes", (long long)offset, count));
1622 if (tcon->ses->capabilities & CAP_LARGE_FILES)
1626 rc = small_smb_init(SMB_COM_WRITE_ANDX, wct, tcon, (void **) &pSMB);
1629 /* tcon and ses pointer are checked in smb_init */
1630 if (tcon->ses->server == NULL)
1631 return -ECONNABORTED;
1633 pSMB->AndXCommand = 0xFF; /* none */
1635 pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF);
1637 pSMB->OffsetHigh = cpu_to_le32(offset >> 32);
1638 else if ((offset >> 32) > 0) /* can not handle big offset for old srv */
1640 pSMB->Reserved = 0xFFFFFFFF;
1641 pSMB->WriteMode = 0;
1642 pSMB->Remaining = 0;
1645 cpu_to_le16(offsetof(struct smb_com_write_req, Data) - 4);
1647 pSMB->DataLengthLow = cpu_to_le16(count & 0xFFFF);
1648 pSMB->DataLengthHigh = cpu_to_le16(count >> 16);
1649 smb_hdr_len = pSMB->hdr.smb_buf_length + 1; /* hdr + 1 byte pad */
1651 pSMB->hdr.smb_buf_length += count+1;
1652 else /* wct == 12 */
1653 pSMB->hdr.smb_buf_length += count+5; /* smb data starts later */
1655 pSMB->ByteCount = cpu_to_le16(count + 1);
1656 else /* wct == 12 */ /* bigger pad, smaller smb hdr, keep offset ok */ {
1657 struct smb_com_writex_req *pSMBW =
1658 (struct smb_com_writex_req *)pSMB;
1659 pSMBW->ByteCount = cpu_to_le16(count + 5);
1661 iov[0].iov_base = pSMB;
1663 iov[0].iov_len = smb_hdr_len + 4;
1664 else /* wct == 12 pad bigger by four bytes */
1665 iov[0].iov_len = smb_hdr_len + 8;
1668 rc = SendReceive2(xid, tcon->ses, iov, n_vec + 1, &resp_buf_type,
1669 long_op, 0 /* do not log STATUS code */ );
1670 cifs_stats_inc(&tcon->num_writes);
1672 cFYI(1, ("Send error Write2 = %d", rc));
1674 } else if (resp_buf_type == 0) {
1675 /* presumably this can not happen, but best to be safe */
1679 WRITE_RSP * pSMBr = (WRITE_RSP *)iov[0].iov_base;
1680 *nbytes = le16_to_cpu(pSMBr->CountHigh);
1681 *nbytes = (*nbytes) << 16;
1682 *nbytes += le16_to_cpu(pSMBr->Count);
1685 /* cifs_small_buf_release(pSMB); */ /* Freed earlier now in SendReceive2 */
1686 if (resp_buf_type == CIFS_SMALL_BUFFER)
1687 cifs_small_buf_release(iov[0].iov_base);
1688 else if (resp_buf_type == CIFS_LARGE_BUFFER)
1689 cifs_buf_release(iov[0].iov_base);
1691 /* Note: On -EAGAIN error only caller can retry on handle based calls
1692 since file handle passed in no longer valid */
1699 CIFSSMBLock(const int xid, struct cifsTconInfo *tcon,
1700 const __u16 smb_file_id, const __u64 len,
1701 const __u64 offset, const __u32 numUnlock,
1702 const __u32 numLock, const __u8 lockType, const int waitFlag)
1705 LOCK_REQ *pSMB = NULL;
1706 LOCK_RSP *pSMBr = NULL;
1711 cFYI(1, ("In CIFSSMBLock - timeout %d numLock %d", waitFlag, numLock));
1712 rc = small_smb_init(SMB_COM_LOCKING_ANDX, 8, tcon, (void **) &pSMB);
1717 pSMBr = (LOCK_RSP *)pSMB; /* BB removeme BB */
1719 if (lockType == LOCKING_ANDX_OPLOCK_RELEASE) {
1720 timeout = -1; /* no response expected */
1722 } else if (waitFlag == TRUE) {
1723 timeout = 3; /* blocking operation, no timeout */
1724 pSMB->Timeout = cpu_to_le32(-1);/* blocking - do not time out */
1729 pSMB->NumberOfLocks = cpu_to_le16(numLock);
1730 pSMB->NumberOfUnlocks = cpu_to_le16(numUnlock);
1731 pSMB->LockType = lockType;
1732 pSMB->AndXCommand = 0xFF; /* none */
1733 pSMB->Fid = smb_file_id; /* netfid stays le */
1735 if ((numLock != 0) || (numUnlock != 0)) {
1736 pSMB->Locks[0].Pid = cpu_to_le16(current->tgid);
1737 /* BB where to store pid high? */
1738 pSMB->Locks[0].LengthLow = cpu_to_le32((u32)len);
1739 pSMB->Locks[0].LengthHigh = cpu_to_le32((u32)(len>>32));
1740 pSMB->Locks[0].OffsetLow = cpu_to_le32((u32)offset);
1741 pSMB->Locks[0].OffsetHigh = cpu_to_le32((u32)(offset>>32));
1742 count = sizeof(LOCKING_ANDX_RANGE);
1747 pSMB->hdr.smb_buf_length += count;
1748 pSMB->ByteCount = cpu_to_le16(count);
1751 rc = SendReceiveBlockingLock(xid, tcon, (struct smb_hdr *) pSMB,
1752 (struct smb_hdr *) pSMBr, &bytes_returned);
1754 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1755 (struct smb_hdr *) pSMBr, &bytes_returned, timeout);
1757 cifs_stats_inc(&tcon->num_locks);
1759 cFYI(1, ("Send error in Lock = %d", rc));
1761 cifs_small_buf_release(pSMB);
1763 /* Note: On -EAGAIN error only caller can retry on handle based calls
1764 since file handle passed in no longer valid */
1769 CIFSSMBPosixLock(const int xid, struct cifsTconInfo *tcon,
1770 const __u16 smb_file_id, const int get_flag, const __u64 len,
1771 struct file_lock *pLockData, const __u16 lock_type,
1774 struct smb_com_transaction2_sfi_req *pSMB = NULL;
1775 struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
1776 struct cifs_posix_lock *parm_data;
1779 int bytes_returned = 0;
1780 __u16 params, param_offset, offset, byte_count, count;
1782 cFYI(1, ("Posix Lock"));
1784 if (pLockData == NULL)
1787 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
1792 pSMBr = (struct smb_com_transaction2_sfi_rsp *)pSMB;
1795 pSMB->MaxSetupCount = 0;
1798 pSMB->Reserved2 = 0;
1799 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
1800 offset = param_offset + params;
1802 count = sizeof(struct cifs_posix_lock);
1803 pSMB->MaxParameterCount = cpu_to_le16(2);
1804 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB PDU from sess */
1805 pSMB->SetupCount = 1;
1806 pSMB->Reserved3 = 0;
1808 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION);
1810 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
1811 byte_count = 3 /* pad */ + params + count;
1812 pSMB->DataCount = cpu_to_le16(count);
1813 pSMB->ParameterCount = cpu_to_le16(params);
1814 pSMB->TotalDataCount = pSMB->DataCount;
1815 pSMB->TotalParameterCount = pSMB->ParameterCount;
1816 pSMB->ParameterOffset = cpu_to_le16(param_offset);
1817 parm_data = (struct cifs_posix_lock *)
1818 (((char *) &pSMB->hdr.Protocol) + offset);
1820 parm_data->lock_type = cpu_to_le16(lock_type);
1822 timeout = 3; /* blocking operation, no timeout */
1823 parm_data->lock_flags = cpu_to_le16(1);
1824 pSMB->Timeout = cpu_to_le32(-1);
1828 parm_data->pid = cpu_to_le32(current->tgid);
1829 parm_data->start = cpu_to_le64(pLockData->fl_start);
1830 parm_data->length = cpu_to_le64(len); /* normalize negative numbers */
1832 pSMB->DataOffset = cpu_to_le16(offset);
1833 pSMB->Fid = smb_file_id;
1834 pSMB->InformationLevel = cpu_to_le16(SMB_SET_POSIX_LOCK);
1835 pSMB->Reserved4 = 0;
1836 pSMB->hdr.smb_buf_length += byte_count;
1837 pSMB->ByteCount = cpu_to_le16(byte_count);
1839 rc = SendReceiveBlockingLock(xid, tcon, (struct smb_hdr *) pSMB,
1840 (struct smb_hdr *) pSMBr, &bytes_returned);
1842 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1843 (struct smb_hdr *) pSMBr, &bytes_returned, timeout);
1847 cFYI(1, ("Send error in Posix Lock = %d", rc));
1848 } else if (get_flag) {
1849 /* lock structure can be returned on get */
1852 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
1854 if (rc || (pSMBr->ByteCount < sizeof(struct cifs_posix_lock))) {
1855 rc = -EIO; /* bad smb */
1858 if (pLockData == NULL) {
1862 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
1863 data_count = le16_to_cpu(pSMBr->t2.DataCount);
1864 if (data_count < sizeof(struct cifs_posix_lock)) {
1868 parm_data = (struct cifs_posix_lock *)
1869 ((char *)&pSMBr->hdr.Protocol + data_offset);
1870 if (parm_data->lock_type == cpu_to_le16(CIFS_UNLCK))
1871 pLockData->fl_type = F_UNLCK;
1876 cifs_small_buf_release(pSMB);
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 CLOSE_RSP *pSMBr = NULL;
1892 cFYI(1, ("In CIFSSMBClose"));
1894 /* do not retry on dead session on close */
1895 rc = small_smb_init(SMB_COM_CLOSE, 3, tcon, (void **) &pSMB);
1901 pSMBr = (CLOSE_RSP *)pSMB; /* BB removeme BB */
1903 pSMB->FileID = (__u16) smb_file_id;
1904 pSMB->LastWriteTime = 0xFFFFFFFF;
1905 pSMB->ByteCount = 0;
1906 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1907 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1908 cifs_stats_inc(&tcon->num_closes);
1911 /* EINTR is expected when user ctl-c to kill app */
1912 cERROR(1, ("Send error in Close = %d", rc));
1916 cifs_small_buf_release(pSMB);
1918 /* Since session is dead, file will be closed on server already */
1926 CIFSSMBRename(const int xid, struct cifsTconInfo *tcon,
1927 const char *fromName, const char *toName,
1928 const struct nls_table *nls_codepage, int remap)
1931 RENAME_REQ *pSMB = NULL;
1932 RENAME_RSP *pSMBr = NULL;
1934 int name_len, name_len2;
1937 cFYI(1, ("In CIFSSMBRename"));
1939 rc = smb_init(SMB_COM_RENAME, 1, tcon, (void **) &pSMB,
1944 pSMB->BufferFormat = 0x04;
1945 pSMB->SearchAttributes =
1946 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
1949 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1951 cifsConvertToUCS((__le16 *) pSMB->OldFileName, fromName,
1952 PATH_MAX, nls_codepage, remap);
1953 name_len++; /* trailing null */
1955 pSMB->OldFileName[name_len] = 0x04; /* pad */
1956 /* protocol requires ASCII signature byte on Unicode string */
1957 pSMB->OldFileName[name_len + 1] = 0x00;
1959 cifsConvertToUCS((__le16 *) &pSMB->OldFileName[name_len + 2],
1960 toName, PATH_MAX, nls_codepage, remap);
1961 name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
1962 name_len2 *= 2; /* convert to bytes */
1963 } else { /* BB improve the check for buffer overruns BB */
1964 name_len = strnlen(fromName, PATH_MAX);
1965 name_len++; /* trailing null */
1966 strncpy(pSMB->OldFileName, fromName, name_len);
1967 name_len2 = strnlen(toName, PATH_MAX);
1968 name_len2++; /* trailing null */
1969 pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */
1970 strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2);
1971 name_len2++; /* trailing null */
1972 name_len2++; /* signature byte */
1975 count = 1 /* 1st signature byte */ + name_len + name_len2;
1976 pSMB->hdr.smb_buf_length += count;
1977 pSMB->ByteCount = cpu_to_le16(count);
1979 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1980 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1981 cifs_stats_inc(&tcon->num_renames);
1983 cFYI(1, ("Send error in rename = %d", rc));
1986 cifs_buf_release(pSMB);
1994 int CIFSSMBRenameOpenFile(const int xid, struct cifsTconInfo *pTcon,
1995 int netfid, char *target_name,
1996 const struct nls_table *nls_codepage, int remap)
1998 struct smb_com_transaction2_sfi_req *pSMB = NULL;
1999 struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
2000 struct set_file_rename *rename_info;
2002 char dummy_string[30];
2004 int bytes_returned = 0;
2006 __u16 params, param_offset, offset, count, byte_count;
2008 cFYI(1, ("Rename to File by handle"));
2009 rc = smb_init(SMB_COM_TRANSACTION2, 15, pTcon, (void **) &pSMB,
2015 pSMB->MaxSetupCount = 0;
2019 pSMB->Reserved2 = 0;
2020 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
2021 offset = param_offset + params;
2023 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
2024 rename_info = (struct set_file_rename *) data_offset;
2025 pSMB->MaxParameterCount = cpu_to_le16(2);
2026 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB PDU from sess */
2027 pSMB->SetupCount = 1;
2028 pSMB->Reserved3 = 0;
2029 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
2030 byte_count = 3 /* pad */ + params;
2031 pSMB->ParameterCount = cpu_to_le16(params);
2032 pSMB->TotalParameterCount = pSMB->ParameterCount;
2033 pSMB->ParameterOffset = cpu_to_le16(param_offset);
2034 pSMB->DataOffset = cpu_to_le16(offset);
2035 /* construct random name ".cifs_tmp<inodenum><mid>" */
2036 rename_info->overwrite = cpu_to_le32(1);
2037 rename_info->root_fid = 0;
2038 /* unicode only call */
2039 if (target_name == NULL) {
2040 sprintf(dummy_string, "cifs%x", pSMB->hdr.Mid);
2041 len_of_str = cifsConvertToUCS((__le16 *)rename_info->target_name,
2042 dummy_string, 24, nls_codepage, remap);
2044 len_of_str = cifsConvertToUCS((__le16 *)rename_info->target_name,
2045 target_name, PATH_MAX, nls_codepage,
2048 rename_info->target_name_len = cpu_to_le32(2 * len_of_str);
2049 count = 12 /* sizeof(struct set_file_rename) */ + (2 * len_of_str) + 2;
2050 byte_count += count;
2051 pSMB->DataCount = cpu_to_le16(count);
2052 pSMB->TotalDataCount = pSMB->DataCount;
2054 pSMB->InformationLevel =
2055 cpu_to_le16(SMB_SET_FILE_RENAME_INFORMATION);
2056 pSMB->Reserved4 = 0;
2057 pSMB->hdr.smb_buf_length += byte_count;
2058 pSMB->ByteCount = cpu_to_le16(byte_count);
2059 rc = SendReceive(xid, pTcon->ses, (struct smb_hdr *) pSMB,
2060 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2061 cifs_stats_inc(&pTcon->num_t2renames);
2063 cFYI(1, ("Send error in Rename (by file handle) = %d", rc));
2066 cifs_buf_release(pSMB);
2068 /* Note: On -EAGAIN error only caller can retry on handle based calls
2069 since file handle passed in no longer valid */
2075 CIFSSMBCopy(const int xid, struct cifsTconInfo *tcon, const char *fromName,
2076 const __u16 target_tid, const char *toName, const int flags,
2077 const struct nls_table *nls_codepage, int remap)
2080 COPY_REQ *pSMB = NULL;
2081 COPY_RSP *pSMBr = NULL;
2083 int name_len, name_len2;
2086 cFYI(1, ("In CIFSSMBCopy"));
2088 rc = smb_init(SMB_COM_COPY, 1, tcon, (void **) &pSMB,
2093 pSMB->BufferFormat = 0x04;
2094 pSMB->Tid2 = target_tid;
2096 pSMB->Flags = cpu_to_le16(flags & COPY_TREE);
2098 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2099 name_len = cifsConvertToUCS((__le16 *) pSMB->OldFileName,
2100 fromName, PATH_MAX, nls_codepage,
2102 name_len++; /* trailing null */
2104 pSMB->OldFileName[name_len] = 0x04; /* pad */
2105 /* protocol requires ASCII signature byte on Unicode string */
2106 pSMB->OldFileName[name_len + 1] = 0x00;
2108 cifsConvertToUCS((__le16 *)&pSMB->OldFileName[name_len + 2],
2109 toName, PATH_MAX, nls_codepage, remap);
2110 name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
2111 name_len2 *= 2; /* convert to bytes */
2112 } else { /* BB improve the check for buffer overruns BB */
2113 name_len = strnlen(fromName, PATH_MAX);
2114 name_len++; /* trailing null */
2115 strncpy(pSMB->OldFileName, fromName, name_len);
2116 name_len2 = strnlen(toName, PATH_MAX);
2117 name_len2++; /* trailing null */
2118 pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */
2119 strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2);
2120 name_len2++; /* trailing null */
2121 name_len2++; /* signature byte */
2124 count = 1 /* 1st signature byte */ + name_len + name_len2;
2125 pSMB->hdr.smb_buf_length += count;
2126 pSMB->ByteCount = cpu_to_le16(count);
2128 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2129 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2131 cFYI(1, ("Send error in copy = %d with %d files copied",
2132 rc, le16_to_cpu(pSMBr->CopyCount)));
2135 cifs_buf_release(pSMB);
2144 CIFSUnixCreateSymLink(const int xid, struct cifsTconInfo *tcon,
2145 const char *fromName, const char *toName,
2146 const struct nls_table *nls_codepage)
2148 TRANSACTION2_SPI_REQ *pSMB = NULL;
2149 TRANSACTION2_SPI_RSP *pSMBr = NULL;
2152 int name_len_target;
2154 int bytes_returned = 0;
2155 __u16 params, param_offset, offset, byte_count;
2157 cFYI(1, ("In Symlink Unix style"));
2159 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2164 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2166 cifs_strtoUCS((__le16 *) pSMB->FileName, fromName, PATH_MAX
2167 /* find define for this maxpathcomponent */
2169 name_len++; /* trailing null */
2172 } else { /* BB improve the check for buffer overruns BB */
2173 name_len = strnlen(fromName, PATH_MAX);
2174 name_len++; /* trailing null */
2175 strncpy(pSMB->FileName, fromName, name_len);
2177 params = 6 + name_len;
2178 pSMB->MaxSetupCount = 0;
2182 pSMB->Reserved2 = 0;
2183 param_offset = offsetof(struct smb_com_transaction2_spi_req,
2184 InformationLevel) - 4;
2185 offset = param_offset + params;
2187 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
2188 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2190 cifs_strtoUCS((__le16 *) data_offset, toName, PATH_MAX
2191 /* find define for this maxpathcomponent */
2193 name_len_target++; /* trailing null */
2194 name_len_target *= 2;
2195 } else { /* BB improve the check for buffer overruns BB */
2196 name_len_target = strnlen(toName, PATH_MAX);
2197 name_len_target++; /* trailing null */
2198 strncpy(data_offset, toName, name_len_target);
2201 pSMB->MaxParameterCount = cpu_to_le16(2);
2202 /* BB find exact max on data count below from sess */
2203 pSMB->MaxDataCount = cpu_to_le16(1000);
2204 pSMB->SetupCount = 1;
2205 pSMB->Reserved3 = 0;
2206 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
2207 byte_count = 3 /* pad */ + params + name_len_target;
2208 pSMB->DataCount = cpu_to_le16(name_len_target);
2209 pSMB->ParameterCount = cpu_to_le16(params);
2210 pSMB->TotalDataCount = pSMB->DataCount;
2211 pSMB->TotalParameterCount = pSMB->ParameterCount;
2212 pSMB->ParameterOffset = cpu_to_le16(param_offset);
2213 pSMB->DataOffset = cpu_to_le16(offset);
2214 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_LINK);
2215 pSMB->Reserved4 = 0;
2216 pSMB->hdr.smb_buf_length += byte_count;
2217 pSMB->ByteCount = cpu_to_le16(byte_count);
2218 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2219 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2220 cifs_stats_inc(&tcon->num_symlinks);
2222 cFYI(1, ("Send error in SetPathInfo create symlink = %d", rc));
2226 cifs_buf_release(pSMB);
2229 goto createSymLinkRetry;
2235 CIFSUnixCreateHardLink(const int xid, struct cifsTconInfo *tcon,
2236 const char *fromName, const char *toName,
2237 const struct nls_table *nls_codepage, int remap)
2239 TRANSACTION2_SPI_REQ *pSMB = NULL;
2240 TRANSACTION2_SPI_RSP *pSMBr = NULL;
2243 int name_len_target;
2245 int bytes_returned = 0;
2246 __u16 params, param_offset, offset, byte_count;
2248 cFYI(1, ("In Create Hard link Unix style"));
2249 createHardLinkRetry:
2250 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2255 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2256 name_len = cifsConvertToUCS((__le16 *) pSMB->FileName, toName,
2257 PATH_MAX, nls_codepage, remap);
2258 name_len++; /* trailing null */
2261 } else { /* BB improve the check for buffer overruns BB */
2262 name_len = strnlen(toName, PATH_MAX);
2263 name_len++; /* trailing null */
2264 strncpy(pSMB->FileName, toName, name_len);
2266 params = 6 + name_len;
2267 pSMB->MaxSetupCount = 0;
2271 pSMB->Reserved2 = 0;
2272 param_offset = offsetof(struct smb_com_transaction2_spi_req,
2273 InformationLevel) - 4;
2274 offset = param_offset + params;
2276 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
2277 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2279 cifsConvertToUCS((__le16 *) data_offset, fromName, PATH_MAX,
2280 nls_codepage, remap);
2281 name_len_target++; /* trailing null */
2282 name_len_target *= 2;
2283 } else { /* BB improve the check for buffer overruns BB */
2284 name_len_target = strnlen(fromName, PATH_MAX);
2285 name_len_target++; /* trailing null */
2286 strncpy(data_offset, fromName, name_len_target);
2289 pSMB->MaxParameterCount = cpu_to_le16(2);
2290 /* BB find exact max on data count below from sess*/
2291 pSMB->MaxDataCount = cpu_to_le16(1000);
2292 pSMB->SetupCount = 1;
2293 pSMB->Reserved3 = 0;
2294 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
2295 byte_count = 3 /* pad */ + params + name_len_target;
2296 pSMB->ParameterCount = cpu_to_le16(params);
2297 pSMB->TotalParameterCount = pSMB->ParameterCount;
2298 pSMB->DataCount = cpu_to_le16(name_len_target);
2299 pSMB->TotalDataCount = pSMB->DataCount;
2300 pSMB->ParameterOffset = cpu_to_le16(param_offset);
2301 pSMB->DataOffset = cpu_to_le16(offset);
2302 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_HLINK);
2303 pSMB->Reserved4 = 0;
2304 pSMB->hdr.smb_buf_length += byte_count;
2305 pSMB->ByteCount = cpu_to_le16(byte_count);
2306 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2307 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2308 cifs_stats_inc(&tcon->num_hardlinks);
2310 cFYI(1, ("Send error in SetPathInfo (hard link) = %d", rc));
2313 cifs_buf_release(pSMB);
2315 goto createHardLinkRetry;
2321 CIFSCreateHardLink(const int xid, struct cifsTconInfo *tcon,
2322 const char *fromName, const char *toName,
2323 const struct nls_table *nls_codepage, int remap)
2326 NT_RENAME_REQ *pSMB = NULL;
2327 RENAME_RSP *pSMBr = NULL;
2329 int name_len, name_len2;
2332 cFYI(1, ("In CIFSCreateHardLink"));
2333 winCreateHardLinkRetry:
2335 rc = smb_init(SMB_COM_NT_RENAME, 4, tcon, (void **) &pSMB,
2340 pSMB->SearchAttributes =
2341 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
2343 pSMB->Flags = cpu_to_le16(CREATE_HARD_LINK);
2344 pSMB->ClusterCount = 0;
2346 pSMB->BufferFormat = 0x04;
2348 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2350 cifsConvertToUCS((__le16 *) pSMB->OldFileName, fromName,
2351 PATH_MAX, nls_codepage, remap);
2352 name_len++; /* trailing null */
2354 pSMB->OldFileName[name_len] = 0; /* pad */
2355 pSMB->OldFileName[name_len + 1] = 0x04;
2357 cifsConvertToUCS((__le16 *)&pSMB->OldFileName[name_len + 2],
2358 toName, PATH_MAX, nls_codepage, remap);
2359 name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
2360 name_len2 *= 2; /* convert to bytes */
2361 } else { /* BB improve the check for buffer overruns BB */
2362 name_len = strnlen(fromName, PATH_MAX);
2363 name_len++; /* trailing null */
2364 strncpy(pSMB->OldFileName, fromName, name_len);
2365 name_len2 = strnlen(toName, PATH_MAX);
2366 name_len2++; /* trailing null */
2367 pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */
2368 strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2);
2369 name_len2++; /* trailing null */
2370 name_len2++; /* signature byte */
2373 count = 1 /* string type byte */ + name_len + name_len2;
2374 pSMB->hdr.smb_buf_length += count;
2375 pSMB->ByteCount = cpu_to_le16(count);
2377 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2378 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2379 cifs_stats_inc(&tcon->num_hardlinks);
2381 cFYI(1, ("Send error in hard link (NT rename) = %d", rc));
2383 cifs_buf_release(pSMB);
2385 goto winCreateHardLinkRetry;
2391 CIFSSMBUnixQuerySymLink(const int xid, struct cifsTconInfo *tcon,
2392 const unsigned char *searchName,
2393 char *symlinkinfo, const int buflen,
2394 const struct nls_table *nls_codepage)
2396 /* SMB_QUERY_FILE_UNIX_LINK */
2397 TRANSACTION2_QPI_REQ *pSMB = NULL;
2398 TRANSACTION2_QPI_RSP *pSMBr = NULL;
2402 __u16 params, byte_count;
2404 cFYI(1, ("In QPathSymLinkInfo (Unix) for path %s", searchName));
2407 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2412 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2414 cifs_strtoUCS((__le16 *) pSMB->FileName, searchName,
2415 PATH_MAX, nls_codepage);
2416 name_len++; /* trailing null */
2418 } else { /* BB improve the check for buffer overruns BB */
2419 name_len = strnlen(searchName, PATH_MAX);
2420 name_len++; /* trailing null */
2421 strncpy(pSMB->FileName, searchName, name_len);
2424 params = 2 /* level */ + 4 /* rsrvd */ + name_len /* incl null */ ;
2425 pSMB->TotalDataCount = 0;
2426 pSMB->MaxParameterCount = cpu_to_le16(2);
2427 /* BB find exact max data count below from sess structure BB */
2428 pSMB->MaxDataCount = cpu_to_le16(4000);
2429 pSMB->MaxSetupCount = 0;
2433 pSMB->Reserved2 = 0;
2434 pSMB->ParameterOffset = cpu_to_le16(offsetof(
2435 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
2436 pSMB->DataCount = 0;
2437 pSMB->DataOffset = 0;
2438 pSMB->SetupCount = 1;
2439 pSMB->Reserved3 = 0;
2440 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
2441 byte_count = params + 1 /* pad */ ;
2442 pSMB->TotalParameterCount = cpu_to_le16(params);
2443 pSMB->ParameterCount = pSMB->TotalParameterCount;
2444 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_LINK);
2445 pSMB->Reserved4 = 0;
2446 pSMB->hdr.smb_buf_length += byte_count;
2447 pSMB->ByteCount = cpu_to_le16(byte_count);
2449 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2450 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2452 cFYI(1, ("Send error in QuerySymLinkInfo = %d", rc));
2454 /* decode response */
2456 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
2457 if (rc || (pSMBr->ByteCount < 2))
2458 /* BB also check enough total bytes returned */
2459 rc = -EIO; /* bad smb */
2461 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
2462 __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
2464 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
2465 name_len = UniStrnlen((wchar_t *) ((char *)
2466 &pSMBr->hdr.Protocol + data_offset),
2467 min_t(const int, buflen, count) / 2);
2468 /* BB FIXME investigate remapping reserved chars here */
2469 cifs_strfromUCS_le(symlinkinfo,
2470 (__le16 *) ((char *)&pSMBr->hdr.Protocol
2472 name_len, nls_codepage);
2474 strncpy(symlinkinfo,
2475 (char *) &pSMBr->hdr.Protocol +
2477 min_t(const int, buflen, count));
2479 symlinkinfo[buflen] = 0;
2480 /* just in case so calling code does not go off the end of buffer */
2483 cifs_buf_release(pSMB);
2485 goto querySymLinkRetry;
2489 #ifdef CONFIG_CIFS_EXPERIMENTAL
2490 /* Initialize NT TRANSACT SMB into small smb request buffer.
2491 This assumes that all NT TRANSACTS that we init here have
2492 total parm and data under about 400 bytes (to fit in small cifs
2493 buffer size), which is the case so far, it easily fits. NB:
2494 Setup words themselves and ByteCount
2495 MaxSetupCount (size of returned setup area) and
2496 MaxParameterCount (returned parms size) must be set by caller */
2498 smb_init_ntransact(const __u16 sub_command, const int setup_count,
2499 const int parm_len, struct cifsTconInfo *tcon,
2504 struct smb_com_ntransact_req *pSMB;
2506 rc = small_smb_init(SMB_COM_NT_TRANSACT, 19 + setup_count, tcon,
2510 *ret_buf = (void *)pSMB;
2512 pSMB->TotalParameterCount = cpu_to_le32(parm_len);
2513 pSMB->TotalDataCount = 0;
2514 pSMB->MaxDataCount = cpu_to_le32((tcon->ses->server->maxBuf -
2515 MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
2516 pSMB->ParameterCount = pSMB->TotalParameterCount;
2517 pSMB->DataCount = pSMB->TotalDataCount;
2518 temp_offset = offsetof(struct smb_com_ntransact_req, Parms) +
2519 (setup_count * 2) - 4 /* for rfc1001 length itself */;
2520 pSMB->ParameterOffset = cpu_to_le32(temp_offset);
2521 pSMB->DataOffset = cpu_to_le32(temp_offset + parm_len);
2522 pSMB->SetupCount = setup_count; /* no need to le convert byte fields */
2523 pSMB->SubCommand = cpu_to_le16(sub_command);
2528 validate_ntransact(char *buf, char **ppparm, char **ppdata,
2529 int *pdatalen, int *pparmlen)
2532 __u32 data_count, data_offset, parm_count, parm_offset;
2533 struct smb_com_ntransact_rsp *pSMBr;
2538 pSMBr = (struct smb_com_ntransact_rsp *)buf;
2540 /* ByteCount was converted from little endian in SendReceive */
2541 end_of_smb = 2 /* sizeof byte count */ + pSMBr->ByteCount +
2542 (char *)&pSMBr->ByteCount;
2544 data_offset = le32_to_cpu(pSMBr->DataOffset);
2545 data_count = le32_to_cpu(pSMBr->DataCount);
2546 parm_offset = le32_to_cpu(pSMBr->ParameterOffset);
2547 parm_count = le32_to_cpu(pSMBr->ParameterCount);
2549 *ppparm = (char *)&pSMBr->hdr.Protocol + parm_offset;
2550 *ppdata = (char *)&pSMBr->hdr.Protocol + data_offset;
2552 /* should we also check that parm and data areas do not overlap? */
2553 if (*ppparm > end_of_smb) {
2554 cFYI(1, ("parms start after end of smb"));
2556 } else if (parm_count + *ppparm > end_of_smb) {
2557 cFYI(1, ("parm end after end of smb"));
2559 } else if (*ppdata > end_of_smb) {
2560 cFYI(1, ("data starts after end of smb"));
2562 } else if (data_count + *ppdata > end_of_smb) {
2563 cFYI(1, ("data %p + count %d (%p) ends after end of smb %p start %p",
2564 *ppdata, data_count, (data_count + *ppdata),
2565 end_of_smb, pSMBr));
2567 } else if (parm_count + data_count > pSMBr->ByteCount) {
2568 cFYI(1, ("parm count and data count larger than SMB"));
2573 #endif /* CIFS_EXPERIMENTAL */
2576 CIFSSMBQueryReparseLinkInfo(const int xid, struct cifsTconInfo *tcon,
2577 const unsigned char *searchName,
2578 char *symlinkinfo, const int buflen, __u16 fid,
2579 const struct nls_table *nls_codepage)
2584 struct smb_com_transaction_ioctl_req *pSMB;
2585 struct smb_com_transaction_ioctl_rsp *pSMBr;
2587 cFYI(1, ("In Windows reparse style QueryLink for path %s", searchName));
2588 rc = smb_init(SMB_COM_NT_TRANSACT, 23, tcon, (void **) &pSMB,
2593 pSMB->TotalParameterCount = 0 ;
2594 pSMB->TotalDataCount = 0;
2595 pSMB->MaxParameterCount = cpu_to_le32(2);
2596 /* BB find exact data count max from sess structure BB */
2597 pSMB->MaxDataCount = cpu_to_le32((tcon->ses->server->maxBuf -
2598 MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
2599 pSMB->MaxSetupCount = 4;
2601 pSMB->ParameterOffset = 0;
2602 pSMB->DataCount = 0;
2603 pSMB->DataOffset = 0;
2604 pSMB->SetupCount = 4;
2605 pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_IOCTL);
2606 pSMB->ParameterCount = pSMB->TotalParameterCount;
2607 pSMB->FunctionCode = cpu_to_le32(FSCTL_GET_REPARSE_POINT);
2608 pSMB->IsFsctl = 1; /* FSCTL */
2609 pSMB->IsRootFlag = 0;
2610 pSMB->Fid = fid; /* file handle always le */
2611 pSMB->ByteCount = 0;
2613 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2614 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2616 cFYI(1, ("Send error in QueryReparseLinkInfo = %d", rc));
2617 } else { /* decode response */
2618 __u32 data_offset = le32_to_cpu(pSMBr->DataOffset);
2619 __u32 data_count = le32_to_cpu(pSMBr->DataCount);
2620 if ((pSMBr->ByteCount < 2) || (data_offset > 512))
2621 /* BB also check enough total bytes returned */
2622 rc = -EIO; /* bad smb */
2624 if (data_count && (data_count < 2048)) {
2625 char *end_of_smb = 2 /* sizeof byte count */ +
2627 (char *)&pSMBr->ByteCount;
2629 struct reparse_data *reparse_buf =
2630 (struct reparse_data *)
2631 ((char *)&pSMBr->hdr.Protocol
2633 if ((char *)reparse_buf >= end_of_smb) {
2637 if ((reparse_buf->LinkNamesBuf +
2638 reparse_buf->TargetNameOffset +
2639 reparse_buf->TargetNameLen) >
2641 cFYI(1, ("reparse buf beyond SMB"));
2646 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
2647 name_len = UniStrnlen((wchar_t *)
2648 (reparse_buf->LinkNamesBuf +
2649 reparse_buf->TargetNameOffset),
2651 reparse_buf->TargetNameLen / 2));
2652 cifs_strfromUCS_le(symlinkinfo,
2653 (__le16 *) (reparse_buf->LinkNamesBuf +
2654 reparse_buf->TargetNameOffset),
2655 name_len, nls_codepage);
2656 } else { /* ASCII names */
2657 strncpy(symlinkinfo,
2658 reparse_buf->LinkNamesBuf +
2659 reparse_buf->TargetNameOffset,
2660 min_t(const int, buflen,
2661 reparse_buf->TargetNameLen));
2665 cFYI(1, ("Invalid return data count on "
2666 "get reparse info ioctl"));
2668 symlinkinfo[buflen] = 0; /* just in case so the caller
2669 does not go off the end of the buffer */
2670 cFYI(1, ("readlink result - %s", symlinkinfo));
2674 cifs_buf_release(pSMB);
2676 /* Note: On -EAGAIN error only caller can retry on handle based calls
2677 since file handle passed in no longer valid */
2682 #ifdef CONFIG_CIFS_POSIX
2684 /*Convert an Access Control Entry from wire format to local POSIX xattr format*/
2685 static void cifs_convert_ace(posix_acl_xattr_entry *ace,
2686 struct cifs_posix_ace *cifs_ace)
2688 /* u8 cifs fields do not need le conversion */
2689 ace->e_perm = cpu_to_le16(cifs_ace->cifs_e_perm);
2690 ace->e_tag = cpu_to_le16(cifs_ace->cifs_e_tag);
2691 ace->e_id = cpu_to_le32(le64_to_cpu(cifs_ace->cifs_uid));
2692 /* cFYI(1,("perm %d tag %d id %d",ace->e_perm,ace->e_tag,ace->e_id)); */
2697 /* Convert ACL from CIFS POSIX wire format to local Linux POSIX ACL xattr */
2698 static int cifs_copy_posix_acl(char *trgt, char *src, const int buflen,
2699 const int acl_type, const int size_of_data_area)
2704 struct cifs_posix_ace *pACE;
2705 struct cifs_posix_acl *cifs_acl = (struct cifs_posix_acl *)src;
2706 posix_acl_xattr_header *local_acl = (posix_acl_xattr_header *)trgt;
2708 if (le16_to_cpu(cifs_acl->version) != CIFS_ACL_VERSION)
2711 if (acl_type & ACL_TYPE_ACCESS) {
2712 count = le16_to_cpu(cifs_acl->access_entry_count);
2713 pACE = &cifs_acl->ace_array[0];
2714 size = sizeof(struct cifs_posix_acl);
2715 size += sizeof(struct cifs_posix_ace) * count;
2716 /* check if we would go beyond end of SMB */
2717 if (size_of_data_area < size) {
2718 cFYI(1, ("bad CIFS POSIX ACL size %d vs. %d",
2719 size_of_data_area, size));
2722 } else if (acl_type & ACL_TYPE_DEFAULT) {
2723 count = le16_to_cpu(cifs_acl->access_entry_count);
2724 size = sizeof(struct cifs_posix_acl);
2725 size += sizeof(struct cifs_posix_ace) * count;
2726 /* skip past access ACEs to get to default ACEs */
2727 pACE = &cifs_acl->ace_array[count];
2728 count = le16_to_cpu(cifs_acl->default_entry_count);
2729 size += sizeof(struct cifs_posix_ace) * count;
2730 /* check if we would go beyond end of SMB */
2731 if (size_of_data_area < size)
2738 size = posix_acl_xattr_size(count);
2739 if ((buflen == 0) || (local_acl == NULL)) {
2740 /* used to query ACL EA size */
2741 } else if (size > buflen) {
2743 } else /* buffer big enough */ {
2744 local_acl->a_version = cpu_to_le32(POSIX_ACL_XATTR_VERSION);
2745 for (i = 0; i < count ; i++) {
2746 cifs_convert_ace(&local_acl->a_entries[i], pACE);
2753 static __u16 convert_ace_to_cifs_ace(struct cifs_posix_ace *cifs_ace,
2754 const posix_acl_xattr_entry *local_ace)
2756 __u16 rc = 0; /* 0 = ACL converted ok */
2758 cifs_ace->cifs_e_perm = le16_to_cpu(local_ace->e_perm);
2759 cifs_ace->cifs_e_tag = le16_to_cpu(local_ace->e_tag);
2760 /* BB is there a better way to handle the large uid? */
2761 if (local_ace->e_id == cpu_to_le32(-1)) {
2762 /* Probably no need to le convert -1 on any arch but can not hurt */
2763 cifs_ace->cifs_uid = cpu_to_le64(-1);
2765 cifs_ace->cifs_uid = cpu_to_le64(le32_to_cpu(local_ace->e_id));
2766 /*cFYI(1,("perm %d tag %d id %d",ace->e_perm,ace->e_tag,ace->e_id));*/
2770 /* Convert ACL from local Linux POSIX xattr to CIFS POSIX ACL wire format */
2771 static __u16 ACL_to_cifs_posix(char *parm_data, const char *pACL,
2772 const int buflen, const int acl_type)
2775 struct cifs_posix_acl *cifs_acl = (struct cifs_posix_acl *)parm_data;
2776 posix_acl_xattr_header *local_acl = (posix_acl_xattr_header *)pACL;
2780 if ((buflen == 0) || (pACL == NULL) || (cifs_acl == NULL))
2783 count = posix_acl_xattr_count((size_t)buflen);
2784 cFYI(1, ("setting acl with %d entries from buf of length %d and "
2786 count, buflen, le32_to_cpu(local_acl->a_version)));
2787 if (le32_to_cpu(local_acl->a_version) != 2) {
2788 cFYI(1, ("unknown POSIX ACL version %d",
2789 le32_to_cpu(local_acl->a_version)));
2792 cifs_acl->version = cpu_to_le16(1);
2793 if (acl_type == ACL_TYPE_ACCESS)
2794 cifs_acl->access_entry_count = cpu_to_le16(count);
2795 else if (acl_type == ACL_TYPE_DEFAULT)
2796 cifs_acl->default_entry_count = cpu_to_le16(count);
2798 cFYI(1, ("unknown ACL type %d", acl_type));
2801 for (i = 0; i < count; i++) {
2802 rc = convert_ace_to_cifs_ace(&cifs_acl->ace_array[i],
2803 &local_acl->a_entries[i]);
2805 /* ACE not converted */
2810 rc = (__u16)(count * sizeof(struct cifs_posix_ace));
2811 rc += sizeof(struct cifs_posix_acl);
2812 /* BB add check to make sure ACL does not overflow SMB */
2818 CIFSSMBGetPosixACL(const int xid, struct cifsTconInfo *tcon,
2819 const unsigned char *searchName,
2820 char *acl_inf, const int buflen, const int acl_type,
2821 const struct nls_table *nls_codepage, int remap)
2823 /* SMB_QUERY_POSIX_ACL */
2824 TRANSACTION2_QPI_REQ *pSMB = NULL;
2825 TRANSACTION2_QPI_RSP *pSMBr = NULL;
2829 __u16 params, byte_count;
2831 cFYI(1, ("In GetPosixACL (Unix) for path %s", searchName));
2834 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2839 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2841 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
2842 PATH_MAX, nls_codepage, remap);
2843 name_len++; /* trailing null */
2845 pSMB->FileName[name_len] = 0;
2846 pSMB->FileName[name_len+1] = 0;
2847 } else { /* BB improve the check for buffer overruns BB */
2848 name_len = strnlen(searchName, PATH_MAX);
2849 name_len++; /* trailing null */
2850 strncpy(pSMB->FileName, searchName, name_len);
2853 params = 2 /* level */ + 4 /* rsrvd */ + name_len /* incl null */ ;
2854 pSMB->TotalDataCount = 0;
2855 pSMB->MaxParameterCount = cpu_to_le16(2);
2856 /* BB find exact max data count below from sess structure BB */
2857 pSMB->MaxDataCount = cpu_to_le16(4000);
2858 pSMB->MaxSetupCount = 0;
2862 pSMB->Reserved2 = 0;
2863 pSMB->ParameterOffset = cpu_to_le16(
2864 offsetof(struct smb_com_transaction2_qpi_req,
2865 InformationLevel) - 4);
2866 pSMB->DataCount = 0;
2867 pSMB->DataOffset = 0;
2868 pSMB->SetupCount = 1;
2869 pSMB->Reserved3 = 0;
2870 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
2871 byte_count = params + 1 /* pad */ ;
2872 pSMB->TotalParameterCount = cpu_to_le16(params);
2873 pSMB->ParameterCount = pSMB->TotalParameterCount;
2874 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_POSIX_ACL);
2875 pSMB->Reserved4 = 0;
2876 pSMB->hdr.smb_buf_length += byte_count;
2877 pSMB->ByteCount = cpu_to_le16(byte_count);
2879 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2880 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2881 cifs_stats_inc(&tcon->num_acl_get);
2883 cFYI(1, ("Send error in Query POSIX ACL = %d", rc));
2885 /* decode response */
2887 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
2888 if (rc || (pSMBr->ByteCount < 2))
2889 /* BB also check enough total bytes returned */
2890 rc = -EIO; /* bad smb */
2892 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
2893 __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
2894 rc = cifs_copy_posix_acl(acl_inf,
2895 (char *)&pSMBr->hdr.Protocol+data_offset,
2896 buflen, acl_type, count);
2899 cifs_buf_release(pSMB);
2906 CIFSSMBSetPosixACL(const int xid, struct cifsTconInfo *tcon,
2907 const unsigned char *fileName,
2908 const char *local_acl, const int buflen,
2910 const struct nls_table *nls_codepage, int remap)
2912 struct smb_com_transaction2_spi_req *pSMB = NULL;
2913 struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
2917 int bytes_returned = 0;
2918 __u16 params, byte_count, data_count, param_offset, offset;
2920 cFYI(1, ("In SetPosixACL (Unix) for path %s", fileName));
2922 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2926 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2928 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
2929 PATH_MAX, nls_codepage, remap);
2930 name_len++; /* trailing null */
2932 } else { /* BB improve the check for buffer overruns BB */
2933 name_len = strnlen(fileName, PATH_MAX);
2934 name_len++; /* trailing null */
2935 strncpy(pSMB->FileName, fileName, name_len);
2937 params = 6 + name_len;
2938 pSMB->MaxParameterCount = cpu_to_le16(2);
2939 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB size from sess */
2940 pSMB->MaxSetupCount = 0;
2944 pSMB->Reserved2 = 0;
2945 param_offset = offsetof(struct smb_com_transaction2_spi_req,
2946 InformationLevel) - 4;
2947 offset = param_offset + params;
2948 parm_data = ((char *) &pSMB->hdr.Protocol) + offset;
2949 pSMB->ParameterOffset = cpu_to_le16(param_offset);
2951 /* convert to on the wire format for POSIX ACL */
2952 data_count = ACL_to_cifs_posix(parm_data, local_acl, buflen, acl_type);
2954 if (data_count == 0) {
2956 goto setACLerrorExit;
2958 pSMB->DataOffset = cpu_to_le16(offset);
2959 pSMB->SetupCount = 1;
2960 pSMB->Reserved3 = 0;
2961 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
2962 pSMB->InformationLevel = cpu_to_le16(SMB_SET_POSIX_ACL);
2963 byte_count = 3 /* pad */ + params + data_count;
2964 pSMB->DataCount = cpu_to_le16(data_count);
2965 pSMB->TotalDataCount = pSMB->DataCount;
2966 pSMB->ParameterCount = cpu_to_le16(params);
2967 pSMB->TotalParameterCount = pSMB->ParameterCount;
2968 pSMB->Reserved4 = 0;
2969 pSMB->hdr.smb_buf_length += byte_count;
2970 pSMB->ByteCount = cpu_to_le16(byte_count);
2971 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2972 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2974 cFYI(1, ("Set POSIX ACL returned %d", rc));
2978 cifs_buf_release(pSMB);
2984 /* BB fix tabs in this function FIXME BB */
2986 CIFSGetExtAttr(const int xid, struct cifsTconInfo *tcon,
2987 const int netfid, __u64 * pExtAttrBits, __u64 *pMask)
2990 struct smb_t2_qfi_req *pSMB = NULL;
2991 struct smb_t2_qfi_rsp *pSMBr = NULL;
2993 __u16 params, byte_count;
2995 cFYI(1, ("In GetExtAttr"));
3000 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3005 params = 2 /* level */ +2 /* fid */;
3006 pSMB->t2.TotalDataCount = 0;
3007 pSMB->t2.MaxParameterCount = cpu_to_le16(4);
3008 /* BB find exact max data count below from sess structure BB */
3009 pSMB->t2.MaxDataCount = cpu_to_le16(4000);
3010 pSMB->t2.MaxSetupCount = 0;
3011 pSMB->t2.Reserved = 0;
3013 pSMB->t2.Timeout = 0;
3014 pSMB->t2.Reserved2 = 0;
3015 pSMB->t2.ParameterOffset = cpu_to_le16(offsetof(struct smb_t2_qfi_req,
3017 pSMB->t2.DataCount = 0;
3018 pSMB->t2.DataOffset = 0;
3019 pSMB->t2.SetupCount = 1;
3020 pSMB->t2.Reserved3 = 0;
3021 pSMB->t2.SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION);
3022 byte_count = params + 1 /* pad */ ;
3023 pSMB->t2.TotalParameterCount = cpu_to_le16(params);
3024 pSMB->t2.ParameterCount = pSMB->t2.TotalParameterCount;
3025 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_ATTR_FLAGS);
3028 pSMB->hdr.smb_buf_length += byte_count;
3029 pSMB->t2.ByteCount = cpu_to_le16(byte_count);
3031 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3032 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3034 cFYI(1, ("error %d in GetExtAttr", rc));
3036 /* decode response */
3037 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3038 if (rc || (pSMBr->ByteCount < 2))
3039 /* BB also check enough total bytes returned */
3040 /* If rc should we check for EOPNOSUPP and
3041 disable the srvino flag? or in caller? */
3042 rc = -EIO; /* bad smb */
3044 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3045 __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
3046 struct file_chattr_info *pfinfo;
3047 /* BB Do we need a cast or hash here ? */
3049 cFYI(1, ("Illegal size ret in GetExtAttr"));
3053 pfinfo = (struct file_chattr_info *)
3054 (data_offset + (char *) &pSMBr->hdr.Protocol);
3055 *pExtAttrBits = le64_to_cpu(pfinfo->mode);
3056 *pMask = le64_to_cpu(pfinfo->mask);
3060 cifs_buf_release(pSMB);
3062 goto GetExtAttrRetry;
3066 #endif /* CONFIG_POSIX */
3068 #ifdef CONFIG_CIFS_EXPERIMENTAL
3069 /* Get Security Descriptor (by handle) from remote server for a file or dir */
3071 CIFSSMBGetCIFSACL(const int xid, struct cifsTconInfo *tcon, __u16 fid,
3072 /* BB fix up return info */ char *acl_inf, const int buflen,
3077 QUERY_SEC_DESC_REQ * pSMB;
3080 cFYI(1, ("GetCifsACL"));
3082 rc = smb_init_ntransact(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,
3099 0 /* not long op */, 0 /* do not log STATUS codes */ );
3100 cifs_stats_inc(&tcon->num_acl_get);
3102 cFYI(1, ("Send error in QuerySecDesc = %d", rc));
3103 } else { /* decode response */
3104 struct cifs_ntsd *psec_desc;
3109 struct smb_com_ntransact_rsp *pSMBr;
3111 /* validate_nttransact */
3112 rc = validate_ntransact(iov[0].iov_base, (char **)&parm,
3113 (char **)&psec_desc,
3114 &parm_len, &data_len);
3117 pSMBr = (struct smb_com_ntransact_rsp *)iov[0].iov_base;
3119 cFYI(1, ("smb %p parm %p data %p", pSMBr, parm, psec_desc));
3121 if (le32_to_cpu(pSMBr->ParameterCount) != 4) {
3122 rc = -EIO; /* bad smb */
3126 /* BB check that data area is minimum length and as big as acl_len */
3128 acl_len = le32_to_cpu(*parm);
3129 /* BB check if (acl_len > bufsize) */
3131 parse_sec_desc(psec_desc, acl_len);
3134 if (buf_type == CIFS_SMALL_BUFFER)
3135 cifs_small_buf_release(iov[0].iov_base);
3136 else if (buf_type == CIFS_LARGE_BUFFER)
3137 cifs_buf_release(iov[0].iov_base);
3138 /* cifs_small_buf_release(pSMB); */ /* Freed earlier now in SendReceive2 */
3141 #endif /* CONFIG_CIFS_EXPERIMENTAL */
3143 /* Legacy Query Path Information call for lookup to old servers such
3145 int SMBQueryInformation(const int xid, struct cifsTconInfo *tcon,
3146 const unsigned char *searchName,
3147 FILE_ALL_INFO *pFinfo,
3148 const struct nls_table *nls_codepage, int remap)
3150 QUERY_INFORMATION_REQ * pSMB;
3151 QUERY_INFORMATION_RSP * pSMBr;
3156 cFYI(1, ("In SMBQPath path %s", searchName));
3158 rc = smb_init(SMB_COM_QUERY_INFORMATION, 0, tcon, (void **) &pSMB,
3163 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3165 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
3166 PATH_MAX, nls_codepage, remap);
3167 name_len++; /* trailing null */
3170 name_len = strnlen(searchName, PATH_MAX);
3171 name_len++; /* trailing null */
3172 strncpy(pSMB->FileName, searchName, name_len);
3174 pSMB->BufferFormat = 0x04;
3175 name_len++; /* account for buffer type byte */
3176 pSMB->hdr.smb_buf_length += (__u16) name_len;
3177 pSMB->ByteCount = cpu_to_le16(name_len);
3179 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3180 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3182 cFYI(1, ("Send error in QueryInfo = %d", rc));
3183 } else if (pFinfo) { /* decode response */
3185 __u32 time = le32_to_cpu(pSMBr->last_write_time);
3186 /* BB FIXME - add time zone adjustment BB */
3187 memset(pFinfo, 0, sizeof(FILE_ALL_INFO));
3190 /* decode time fields */
3191 pFinfo->ChangeTime = cpu_to_le64(cifs_UnixTimeToNT(ts));
3192 pFinfo->LastWriteTime = pFinfo->ChangeTime;
3193 pFinfo->LastAccessTime = 0;
3194 pFinfo->AllocationSize =
3195 cpu_to_le64(le32_to_cpu(pSMBr->size));
3196 pFinfo->EndOfFile = pFinfo->AllocationSize;
3197 pFinfo->Attributes =
3198 cpu_to_le32(le16_to_cpu(pSMBr->attr));
3200 rc = -EIO; /* bad buffer passed in */
3202 cifs_buf_release(pSMB);
3214 CIFSSMBQPathInfo(const int xid, struct cifsTconInfo *tcon,
3215 const unsigned char *searchName,
3216 FILE_ALL_INFO * pFindData,
3217 int legacy /* old style infolevel */,
3218 const struct nls_table *nls_codepage, int remap)
3220 /* level 263 SMB_QUERY_FILE_ALL_INFO */
3221 TRANSACTION2_QPI_REQ *pSMB = NULL;
3222 TRANSACTION2_QPI_RSP *pSMBr = NULL;
3226 __u16 params, byte_count;
3228 /* cFYI(1, ("In QPathInfo path %s", searchName)); */
3230 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3235 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3237 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
3238 PATH_MAX, nls_codepage, remap);
3239 name_len++; /* trailing null */
3241 } else { /* BB improve the check for buffer overruns BB */
3242 name_len = strnlen(searchName, PATH_MAX);
3243 name_len++; /* trailing null */
3244 strncpy(pSMB->FileName, searchName, name_len);
3247 params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */;
3248 pSMB->TotalDataCount = 0;
3249 pSMB->MaxParameterCount = cpu_to_le16(2);
3250 pSMB->MaxDataCount = cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
3251 pSMB->MaxSetupCount = 0;
3255 pSMB->Reserved2 = 0;
3256 pSMB->ParameterOffset = cpu_to_le16(offsetof(
3257 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
3258 pSMB->DataCount = 0;
3259 pSMB->DataOffset = 0;
3260 pSMB->SetupCount = 1;
3261 pSMB->Reserved3 = 0;
3262 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
3263 byte_count = params + 1 /* pad */ ;
3264 pSMB->TotalParameterCount = cpu_to_le16(params);
3265 pSMB->ParameterCount = pSMB->TotalParameterCount;
3267 pSMB->InformationLevel = cpu_to_le16(SMB_INFO_STANDARD);
3269 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_ALL_INFO);
3270 pSMB->Reserved4 = 0;
3271 pSMB->hdr.smb_buf_length += byte_count;
3272 pSMB->ByteCount = cpu_to_le16(byte_count);
3274 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3275 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3277 cFYI(1, ("Send error in QPathInfo = %d", rc));
3278 } else { /* decode response */
3279 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3281 if (rc) /* BB add auto retry on EOPNOTSUPP? */
3283 else if (!legacy && (pSMBr->ByteCount < 40))
3284 rc = -EIO; /* bad smb */
3285 else if (legacy && (pSMBr->ByteCount < 24))
3286 rc = -EIO; /* 24 or 26 expected but we do not read
3288 else if (pFindData) {
3290 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3291 if (legacy) /* we do not read the last field, EAsize,
3292 fortunately since it varies by subdialect
3293 and on Set vs. Get, is two bytes or 4
3294 bytes depending but we don't care here */
3295 size = sizeof(FILE_INFO_STANDARD);
3297 size = sizeof(FILE_ALL_INFO);
3298 memcpy((char *) pFindData,
3299 (char *) &pSMBr->hdr.Protocol +
3304 cifs_buf_release(pSMB);
3306 goto QPathInfoRetry;
3312 CIFSSMBUnixQPathInfo(const int xid, struct cifsTconInfo *tcon,
3313 const unsigned char *searchName,
3314 FILE_UNIX_BASIC_INFO * pFindData,
3315 const struct nls_table *nls_codepage, int remap)
3317 /* SMB_QUERY_FILE_UNIX_BASIC */
3318 TRANSACTION2_QPI_REQ *pSMB = NULL;
3319 TRANSACTION2_QPI_RSP *pSMBr = NULL;
3321 int bytes_returned = 0;
3323 __u16 params, byte_count;
3325 cFYI(1, ("In QPathInfo (Unix) the path %s", searchName));
3327 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3332 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3334 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
3335 PATH_MAX, nls_codepage, remap);
3336 name_len++; /* trailing null */
3338 } else { /* BB improve the check for buffer overruns BB */
3339 name_len = strnlen(searchName, PATH_MAX);
3340 name_len++; /* trailing null */
3341 strncpy(pSMB->FileName, searchName, name_len);
3344 params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */;
3345 pSMB->TotalDataCount = 0;
3346 pSMB->MaxParameterCount = cpu_to_le16(2);
3347 /* BB find exact max SMB PDU from sess structure BB */
3348 pSMB->MaxDataCount = cpu_to_le16(4000);
3349 pSMB->MaxSetupCount = 0;
3353 pSMB->Reserved2 = 0;
3354 pSMB->ParameterOffset = cpu_to_le16(offsetof(
3355 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
3356 pSMB->DataCount = 0;
3357 pSMB->DataOffset = 0;
3358 pSMB->SetupCount = 1;
3359 pSMB->Reserved3 = 0;
3360 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
3361 byte_count = params + 1 /* pad */ ;
3362 pSMB->TotalParameterCount = cpu_to_le16(params);
3363 pSMB->ParameterCount = pSMB->TotalParameterCount;
3364 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC);
3365 pSMB->Reserved4 = 0;
3366 pSMB->hdr.smb_buf_length += byte_count;
3367 pSMB->ByteCount = cpu_to_le16(byte_count);
3369 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3370 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3372 cFYI(1, ("Send error in QPathInfo = %d", rc));
3373 } else { /* decode response */
3374 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3376 if (rc || (pSMBr->ByteCount < sizeof(FILE_UNIX_BASIC_INFO))) {
3377 cERROR(1, ("Malformed FILE_UNIX_BASIC_INFO response.\n"
3378 "Unix Extensions can be disabled on mount "
3379 "by specifying the nosfu mount option."));
3380 rc = -EIO; /* bad smb */
3382 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3383 memcpy((char *) pFindData,
3384 (char *) &pSMBr->hdr.Protocol +
3386 sizeof (FILE_UNIX_BASIC_INFO));
3389 cifs_buf_release(pSMB);
3391 goto UnixQPathInfoRetry;
3396 #if 0 /* function unused at present */
3397 int CIFSFindSingle(const int xid, struct cifsTconInfo *tcon,
3398 const char *searchName, FILE_ALL_INFO * findData,
3399 const struct nls_table *nls_codepage)
3401 /* level 257 SMB_ */
3402 TRANSACTION2_FFIRST_REQ *pSMB = NULL;
3403 TRANSACTION2_FFIRST_RSP *pSMBr = NULL;
3407 __u16 params, byte_count;
3409 cFYI(1, ("In FindUnique"));
3411 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3416 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3418 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
3419 PATH_MAX, nls_codepage);
3420 name_len++; /* trailing null */
3422 } else { /* BB improve the check for buffer overruns BB */
3423 name_len = strnlen(searchName, PATH_MAX);
3424 name_len++; /* trailing null */
3425 strncpy(pSMB->FileName, searchName, name_len);
3428 params = 12 + name_len /* includes null */ ;
3429 pSMB->TotalDataCount = 0; /* no EAs */
3430 pSMB->MaxParameterCount = cpu_to_le16(2);
3431 pSMB->MaxDataCount = cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
3432 pSMB->MaxSetupCount = 0;
3436 pSMB->Reserved2 = 0;
3437 pSMB->ParameterOffset = cpu_to_le16(
3438 offsetof(struct smb_com_transaction2_ffirst_req, InformationLevel)-4);
3439 pSMB->DataCount = 0;
3440 pSMB->DataOffset = 0;
3441 pSMB->SetupCount = 1; /* one byte, no need to le convert */
3442 pSMB->Reserved3 = 0;
3443 pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_FIRST);
3444 byte_count = params + 1 /* pad */ ;
3445 pSMB->TotalParameterCount = cpu_to_le16(params);
3446 pSMB->ParameterCount = pSMB->TotalParameterCount;
3447 pSMB->SearchAttributes =
3448 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
3450 pSMB->SearchCount = cpu_to_le16(16); /* BB increase */
3451 pSMB->SearchFlags = cpu_to_le16(1);
3452 pSMB->InformationLevel = cpu_to_le16(SMB_FIND_FILE_DIRECTORY_INFO);
3453 pSMB->SearchStorageType = 0; /* BB what should we set this to? BB */
3454 pSMB->hdr.smb_buf_length += byte_count;
3455 pSMB->ByteCount = cpu_to_le16(byte_count);
3457 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3458 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3461 cFYI(1, ("Send error in FindFileDirInfo = %d", rc));
3462 } else { /* decode response */
3463 cifs_stats_inc(&tcon->num_ffirst);
3467 cifs_buf_release(pSMB);
3469 goto findUniqueRetry;
3473 #endif /* end unused (temporarily) function */
3475 /* xid, tcon, searchName and codepage are input parms, rest are returned */
3477 CIFSFindFirst(const int xid, struct cifsTconInfo *tcon,
3478 const char *searchName,
3479 const struct nls_table *nls_codepage,
3481 struct cifs_search_info *psrch_inf, int remap, const char dirsep)
3483 /* level 257 SMB_ */
3484 TRANSACTION2_FFIRST_REQ *pSMB = NULL;
3485 TRANSACTION2_FFIRST_RSP *pSMBr = NULL;
3486 T2_FFIRST_RSP_PARMS * parms;
3488 int bytes_returned = 0;
3490 __u16 params, byte_count;
3492 cFYI(1, ("In FindFirst for %s", searchName));
3495 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3500 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3502 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
3503 PATH_MAX, nls_codepage, remap);
3504 /* We can not add the asterik earlier in case
3505 it got remapped to 0xF03A as if it were part of the
3506 directory name instead of a wildcard */
3508 pSMB->FileName[name_len] = dirsep;
3509 pSMB->FileName[name_len+1] = 0;
3510 pSMB->FileName[name_len+2] = '*';
3511 pSMB->FileName[name_len+3] = 0;
3512 name_len += 4; /* now the trailing null */
3513 pSMB->FileName[name_len] = 0; /* null terminate just in case */
3514 pSMB->FileName[name_len+1] = 0;
3516 } else { /* BB add check for overrun of SMB buf BB */
3517 name_len = strnlen(searchName, PATH_MAX);
3518 /* BB fix here and in unicode clause above ie
3519 if (name_len > buffersize-header)
3520 free buffer exit; BB */
3521 strncpy(pSMB->FileName, searchName, name_len);
3522 pSMB->FileName[name_len] = dirsep;
3523 pSMB->FileName[name_len+1] = '*';
3524 pSMB->FileName[name_len+2] = 0;
3528 params = 12 + name_len /* includes null */ ;
3529 pSMB->TotalDataCount = 0; /* no EAs */
3530 pSMB->MaxParameterCount = cpu_to_le16(10);
3531 pSMB->MaxDataCount = cpu_to_le16((tcon->ses->server->maxBuf -
3532 MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
3533 pSMB->MaxSetupCount = 0;
3537 pSMB->Reserved2 = 0;
3538 byte_count = params + 1 /* pad */ ;
3539 pSMB->TotalParameterCount = cpu_to_le16(params);
3540 pSMB->ParameterCount = pSMB->TotalParameterCount;
3541 pSMB->ParameterOffset = cpu_to_le16(
3542 offsetof(struct smb_com_transaction2_ffirst_req, SearchAttributes)
3544 pSMB->DataCount = 0;
3545 pSMB->DataOffset = 0;
3546 pSMB->SetupCount = 1; /* one byte, no need to make endian neutral */
3547 pSMB->Reserved3 = 0;
3548 pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_FIRST);
3549 pSMB->SearchAttributes =
3550 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
3552 pSMB->SearchCount = cpu_to_le16(CIFSMaxBufSize/sizeof(FILE_UNIX_INFO));
3553 pSMB->SearchFlags = cpu_to_le16(CIFS_SEARCH_CLOSE_AT_END |
3554 CIFS_SEARCH_RETURN_RESUME);
3555 pSMB->InformationLevel = cpu_to_le16(psrch_inf->info_level);
3557 /* BB what should we set StorageType to? Does it matter? BB */
3558 pSMB->SearchStorageType = 0;
3559 pSMB->hdr.smb_buf_length += byte_count;
3560 pSMB->ByteCount = cpu_to_le16(byte_count);
3562 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3563 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3564 cifs_stats_inc(&tcon->num_ffirst);
3566 if (rc) {/* BB add logic to retry regular search if Unix search
3567 rejected unexpectedly by server */
3568 /* BB Add code to handle unsupported level rc */
3569 cFYI(1, ("Error in FindFirst = %d", rc));
3571 cifs_buf_release(pSMB);
3573 /* BB eventually could optimize out free and realloc of buf */
3576 goto findFirstRetry;
3577 } else { /* decode response */
3578 /* BB remember to free buffer if error BB */
3579 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3581 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
3582 psrch_inf->unicode = TRUE;
3584 psrch_inf->unicode = FALSE;
3586 psrch_inf->ntwrk_buf_start = (char *)pSMBr;
3587 psrch_inf->smallBuf = 0;
3588 psrch_inf->srch_entries_start =
3589 (char *) &pSMBr->hdr.Protocol +
3590 le16_to_cpu(pSMBr->t2.DataOffset);
3591 parms = (T2_FFIRST_RSP_PARMS *)((char *) &pSMBr->hdr.Protocol +
3592 le16_to_cpu(pSMBr->t2.ParameterOffset));
3594 if (parms->EndofSearch)
3595 psrch_inf->endOfSearch = TRUE;
3597 psrch_inf->endOfSearch = FALSE;
3599 psrch_inf->entries_in_buffer =
3600 le16_to_cpu(parms->SearchCount);
3601 psrch_inf->index_of_last_entry = 2 /* skip . and .. */ +
3602 psrch_inf->entries_in_buffer;
3603 *pnetfid = parms->SearchHandle;
3605 cifs_buf_release(pSMB);
3612 int CIFSFindNext(const int xid, struct cifsTconInfo *tcon,
3613 __u16 searchHandle, struct cifs_search_info *psrch_inf)
3615 TRANSACTION2_FNEXT_REQ *pSMB = NULL;
3616 TRANSACTION2_FNEXT_RSP *pSMBr = NULL;
3617 T2_FNEXT_RSP_PARMS * parms;
3618 char *response_data;
3620 int bytes_returned, name_len;
3621 __u16 params, byte_count;
3623 cFYI(1, ("In FindNext"));
3625 if (psrch_inf->endOfSearch == TRUE)
3628 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3633 params = 14; /* includes 2 bytes of null string, converted to LE below*/
3635 pSMB->TotalDataCount = 0; /* no EAs */
3636 pSMB->MaxParameterCount = cpu_to_le16(8);
3637 pSMB->MaxDataCount =
3638 cpu_to_le16((tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE) &
3640 pSMB->MaxSetupCount = 0;
3644 pSMB->Reserved2 = 0;
3645 pSMB->ParameterOffset = cpu_to_le16(
3646 offsetof(struct smb_com_transaction2_fnext_req,SearchHandle) - 4);
3647 pSMB->DataCount = 0;
3648 pSMB->DataOffset = 0;
3649 pSMB->SetupCount = 1;
3650 pSMB->Reserved3 = 0;
3651 pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_NEXT);
3652 pSMB->SearchHandle = searchHandle; /* always kept as le */
3654 cpu_to_le16(CIFSMaxBufSize / sizeof (FILE_UNIX_INFO));
3655 pSMB->InformationLevel = cpu_to_le16(psrch_inf->info_level);
3656 pSMB->ResumeKey = psrch_inf->resume_key;
3658 cpu_to_le16(CIFS_SEARCH_CLOSE_AT_END | CIFS_SEARCH_RETURN_RESUME);
3660 name_len = psrch_inf->resume_name_len;
3662 if (name_len < PATH_MAX) {
3663 memcpy(pSMB->ResumeFileName, psrch_inf->presume_name, name_len);
3664 byte_count += name_len;
3665 /* 14 byte parm len above enough for 2 byte null terminator */
3666 pSMB->ResumeFileName[name_len] = 0;
3667 pSMB->ResumeFileName[name_len+1] = 0;
3670 goto FNext2_err_exit;
3672 byte_count = params + 1 /* pad */ ;
3673 pSMB->TotalParameterCount = cpu_to_le16(params);
3674 pSMB->ParameterCount = pSMB->TotalParameterCount;
3675 pSMB->hdr.smb_buf_length += byte_count;
3676 pSMB->ByteCount = cpu_to_le16(byte_count);
3678 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3679 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3680 cifs_stats_inc(&tcon->num_fnext);
3683 psrch_inf->endOfSearch = TRUE;
3684 rc = 0; /* search probably was closed at end of search*/
3686 cFYI(1, ("FindNext returned = %d", rc));
3687 } else { /* decode response */
3688 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3691 /* BB fixme add lock for file (srch_info) struct here */
3692 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
3693 psrch_inf->unicode = TRUE;
3695 psrch_inf->unicode = FALSE;
3696 response_data = (char *) &pSMBr->hdr.Protocol +
3697 le16_to_cpu(pSMBr->t2.ParameterOffset);
3698 parms = (T2_FNEXT_RSP_PARMS *)response_data;
3699 response_data = (char *)&pSMBr->hdr.Protocol +
3700 le16_to_cpu(pSMBr->t2.DataOffset);
3701 if (psrch_inf->smallBuf)
3702 cifs_small_buf_release(
3703 psrch_inf->ntwrk_buf_start);
3705 cifs_buf_release(psrch_inf->ntwrk_buf_start);
3706 psrch_inf->srch_entries_start = response_data;
3707 psrch_inf->ntwrk_buf_start = (char *)pSMB;
3708 psrch_inf->smallBuf = 0;
3709 if (parms->EndofSearch)
3710 psrch_inf->endOfSearch = TRUE;
3712 psrch_inf->endOfSearch = FALSE;
3713 psrch_inf->entries_in_buffer =
3714 le16_to_cpu(parms->SearchCount);
3715 psrch_inf->index_of_last_entry +=
3716 psrch_inf->entries_in_buffer;
3717 /* cFYI(1,("fnxt2 entries in buf %d index_of_last %d",
3718 psrch_inf->entries_in_buffer, psrch_inf->index_of_last_entry)); */
3720 /* BB fixme add unlock here */
3725 /* BB On error, should we leave previous search buf (and count and
3726 last entry fields) intact or free the previous one? */
3728 /* Note: On -EAGAIN error only caller can retry on handle based calls
3729 since file handle passed in no longer valid */
3732 cifs_buf_release(pSMB);
3737 CIFSFindClose(const int xid, struct cifsTconInfo *tcon,
3738 const __u16 searchHandle)
3741 FINDCLOSE_REQ *pSMB = NULL;
3742 CLOSE_RSP *pSMBr = NULL; /* BB removeme BB */
3745 cFYI(1, ("In CIFSSMBFindClose"));
3746 rc = small_smb_init(SMB_COM_FIND_CLOSE2, 1, tcon, (void **)&pSMB);
3748 /* no sense returning error if session restarted
3749 as file handle has been closed */
3755 pSMBr = (CLOSE_RSP *)pSMB; /* BB removeme BB */
3756 pSMB->FileID = searchHandle;
3757 pSMB->ByteCount = 0;
3758 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3759 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3761 cERROR(1, ("Send error in FindClose = %d", rc));
3763 cifs_stats_inc(&tcon->num_fclose);
3764 cifs_small_buf_release(pSMB);
3766 /* Since session is dead, search handle closed on server already */
3774 CIFSGetSrvInodeNumber(const int xid, struct cifsTconInfo *tcon,
3775 const unsigned char *searchName,
3776 __u64 * inode_number,
3777 const struct nls_table *nls_codepage, int remap)
3780 TRANSACTION2_QPI_REQ *pSMB = NULL;
3781 TRANSACTION2_QPI_RSP *pSMBr = NULL;
3782 int name_len, bytes_returned;
3783 __u16 params, byte_count;
3785 cFYI(1, ("In GetSrvInodeNum for %s", searchName));
3789 GetInodeNumberRetry:
3790 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3795 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3797 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
3798 PATH_MAX, nls_codepage, remap);
3799 name_len++; /* trailing null */
3801 } else { /* BB improve the check for buffer overruns BB */
3802 name_len = strnlen(searchName, PATH_MAX);
3803 name_len++; /* trailing null */
3804 strncpy(pSMB->FileName, searchName, name_len);
3807 params = 2 /* level */ + 4 /* rsrvd */ + name_len /* incl null */ ;
3808 pSMB->TotalDataCount = 0;
3809 pSMB->MaxParameterCount = cpu_to_le16(2);
3810 /* BB find exact max data count below from sess structure BB */
3811 pSMB->MaxDataCount = cpu_to_le16(4000);
3812 pSMB->MaxSetupCount = 0;
3816 pSMB->Reserved2 = 0;
3817 pSMB->ParameterOffset = cpu_to_le16(offsetof(
3818 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
3819 pSMB->DataCount = 0;
3820 pSMB->DataOffset = 0;
3821 pSMB->SetupCount = 1;
3822 pSMB->Reserved3 = 0;
3823 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
3824 byte_count = params + 1 /* pad */ ;
3825 pSMB->TotalParameterCount = cpu_to_le16(params);
3826 pSMB->ParameterCount = pSMB->TotalParameterCount;
3827 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_INTERNAL_INFO);
3828 pSMB->Reserved4 = 0;
3829 pSMB->hdr.smb_buf_length += byte_count;
3830 pSMB->ByteCount = cpu_to_le16(byte_count);
3832 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3833 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3835 cFYI(1, ("error %d in QueryInternalInfo", rc));
3837 /* decode response */
3838 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3839 if (rc || (pSMBr->ByteCount < 2))
3840 /* BB also check enough total bytes returned */
3841 /* If rc should we check for EOPNOSUPP and
3842 disable the srvino flag? or in caller? */
3843 rc = -EIO; /* bad smb */
3845 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3846 __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
3847 struct file_internal_info *pfinfo;
3848 /* BB Do we need a cast or hash here ? */
3850 cFYI(1, ("Illegal size ret in QryIntrnlInf"));
3852 goto GetInodeNumOut;
3854 pfinfo = (struct file_internal_info *)
3855 (data_offset + (char *) &pSMBr->hdr.Protocol);
3856 *inode_number = pfinfo->UniqueId;
3860 cifs_buf_release(pSMB);
3862 goto GetInodeNumberRetry;
3867 CIFSGetDFSRefer(const int xid, struct cifsSesInfo *ses,
3868 const unsigned char *searchName,
3869 unsigned char **targetUNCs,
3870 unsigned int *number_of_UNC_in_array,
3871 const struct nls_table *nls_codepage, int remap)
3873 /* TRANS2_GET_DFS_REFERRAL */
3874 TRANSACTION2_GET_DFS_REFER_REQ *pSMB = NULL;
3875 TRANSACTION2_GET_DFS_REFER_RSP *pSMBr = NULL;
3876 struct dfs_referral_level_3 *referrals = NULL;
3882 __u16 params, byte_count;
3883 *number_of_UNC_in_array = 0;
3886 cFYI(1, ("In GetDFSRefer the path %s", searchName));
3890 rc = smb_init(SMB_COM_TRANSACTION2, 15, NULL, (void **) &pSMB,
3895 /* server pointer checked in called function,
3896 but should never be null here anyway */
3897 pSMB->hdr.Mid = GetNextMid(ses->server);
3898 pSMB->hdr.Tid = ses->ipc_tid;
3899 pSMB->hdr.Uid = ses->Suid;
3900 if (ses->capabilities & CAP_STATUS32)
3901 pSMB->hdr.Flags2 |= SMBFLG2_ERR_STATUS;
3902 if (ses->capabilities & CAP_DFS)
3903 pSMB->hdr.Flags2 |= SMBFLG2_DFS;
3905 if (ses->capabilities & CAP_UNICODE) {
3906 pSMB->hdr.Flags2 |= SMBFLG2_UNICODE;
3908 cifsConvertToUCS((__le16 *) pSMB->RequestFileName,
3909 searchName, PATH_MAX, nls_codepage, remap);
3910 name_len++; /* trailing null */
3912 } else { /* BB improve the check for buffer overruns BB */
3913 name_len = strnlen(searchName, PATH_MAX);
3914 name_len++; /* trailing null */
3915 strncpy(pSMB->RequestFileName, searchName, name_len);
3919 if (ses->server->secMode &
3920 (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
3921 pSMB->hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
3924 pSMB->hdr.Uid = ses->Suid;
3926 params = 2 /* level */ + name_len /*includes null */ ;
3927 pSMB->TotalDataCount = 0;
3928 pSMB->DataCount = 0;
3929 pSMB->DataOffset = 0;
3930 pSMB->MaxParameterCount = 0;
3931 pSMB->MaxDataCount = cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
3932 pSMB->MaxSetupCount = 0;
3936 pSMB->Reserved2 = 0;
3937 pSMB->ParameterOffset = cpu_to_le16(offsetof(
3938 struct smb_com_transaction2_get_dfs_refer_req, MaxReferralLevel) - 4);
3939 pSMB->SetupCount = 1;
3940 pSMB->Reserved3 = 0;
3941 pSMB->SubCommand = cpu_to_le16(TRANS2_GET_DFS_REFERRAL);
3942 byte_count = params + 3 /* pad */ ;
3943 pSMB->ParameterCount = cpu_to_le16(params);
3944 pSMB->TotalParameterCount = pSMB->ParameterCount;
3945 pSMB->MaxReferralLevel = cpu_to_le16(3);
3946 pSMB->hdr.smb_buf_length += byte_count;
3947 pSMB->ByteCount = cpu_to_le16(byte_count);
3949 rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB,
3950 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3952 cFYI(1, ("Send error in GetDFSRefer = %d", rc));
3953 } else { /* decode response */
3954 /* BB Add logic to parse referrals here */
3955 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3957 /* BB Also check if enough total bytes returned? */
3958 if (rc || (pSMBr->ByteCount < 17))
3959 rc = -EIO; /* bad smb */
3961 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3962 __u16 data_count = le16_to_cpu(pSMBr->t2.DataCount);
3965 ("Decoding GetDFSRefer response BCC: %d Offset %d",
3966 pSMBr->ByteCount, data_offset));
3968 (struct dfs_referral_level_3 *)
3969 (8 /* sizeof start of data block */ +
3971 (char *) &pSMBr->hdr.Protocol);
3972 cFYI(1, ("num_referrals: %d dfs flags: 0x%x ... \n"
3973 "for referral one refer size: 0x%x srv "
3974 "type: 0x%x refer flags: 0x%x ttl: 0x%x",
3975 le16_to_cpu(pSMBr->NumberOfReferrals),
3976 le16_to_cpu(pSMBr->DFSFlags),
3977 le16_to_cpu(referrals->ReferralSize),
3978 le16_to_cpu(referrals->ServerType),
3979 le16_to_cpu(referrals->ReferralFlags),
3980 le16_to_cpu(referrals->TimeToLive)));
3981 /* BB This field is actually two bytes in from start of
3982 data block so we could do safety check that DataBlock
3983 begins at address of pSMBr->NumberOfReferrals */
3984 *number_of_UNC_in_array =
3985 le16_to_cpu(pSMBr->NumberOfReferrals);
3987 /* BB Fix below so can return more than one referral */
3988 if (*number_of_UNC_in_array > 1)
3989 *number_of_UNC_in_array = 1;
3991 /* get the length of the strings describing refs */
3993 for (i = 0; i < *number_of_UNC_in_array; i++) {
3994 /* make sure that DfsPathOffset not past end */
3996 le16_to_cpu(referrals->DfsPathOffset);
3997 if (offset > data_count) {
3998 /* if invalid referral, stop here and do
3999 not try to copy any more */
4000 *number_of_UNC_in_array = i;
4003 temp = ((char *)referrals) + offset;
4005 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
4006 name_len += UniStrnlen((wchar_t *)temp,
4009 name_len += strnlen(temp, data_count);
4012 /* BB add check that referral pointer does
4013 not fall off end PDU */
4015 /* BB add check for name_len bigger than bcc */
4017 kmalloc(name_len+1+(*number_of_UNC_in_array),
4019 if (*targetUNCs == NULL) {
4023 /* copy the ref strings */
4024 referrals = (struct dfs_referral_level_3 *)
4025 (8 /* sizeof data hdr */ + data_offset +
4026 (char *) &pSMBr->hdr.Protocol);
4028 for (i = 0; i < *number_of_UNC_in_array; i++) {
4029 temp = ((char *)referrals) +
4030 le16_to_cpu(referrals->DfsPathOffset);
4031 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
4032 cifs_strfromUCS_le(*targetUNCs,
4037 strncpy(*targetUNCs, temp, name_len);
4039 /* BB update target_uncs pointers */
4049 cifs_buf_release(pSMB);
4057 /* Query File System Info such as free space to old servers such as Win 9x */
4059 SMBOldQFSInfo(const int xid, struct cifsTconInfo *tcon, struct kstatfs *FSData)
4061 /* level 0x01 SMB_QUERY_FILE_SYSTEM_INFO */
4062 TRANSACTION2_QFSI_REQ *pSMB = NULL;
4063 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4064 FILE_SYSTEM_ALLOC_INFO *response_data;
4066 int bytes_returned = 0;
4067 __u16 params, byte_count;
4069 cFYI(1, ("OldQFSInfo"));
4071 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4076 params = 2; /* level */
4077 pSMB->TotalDataCount = 0;
4078 pSMB->MaxParameterCount = cpu_to_le16(2);
4079 pSMB->MaxDataCount = cpu_to_le16(1000);
4080 pSMB->MaxSetupCount = 0;
4084 pSMB->Reserved2 = 0;
4085 byte_count = params + 1 /* pad */ ;
4086 pSMB->TotalParameterCount = cpu_to_le16(params);
4087 pSMB->ParameterCount = pSMB->TotalParameterCount;
4088 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4089 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4090 pSMB->DataCount = 0;
4091 pSMB->DataOffset = 0;
4092 pSMB->SetupCount = 1;
4093 pSMB->Reserved3 = 0;
4094 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4095 pSMB->InformationLevel = cpu_to_le16(SMB_INFO_ALLOCATION);
4096 pSMB->hdr.smb_buf_length += byte_count;
4097 pSMB->ByteCount = cpu_to_le16(byte_count);
4099 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4100 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4102 cFYI(1, ("Send error in QFSInfo = %d", rc));
4103 } else { /* decode response */
4104 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4106 if (rc || (pSMBr->ByteCount < 18))
4107 rc = -EIO; /* bad smb */
4109 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4110 cFYI(1, ("qfsinf resp BCC: %d Offset %d",
4111 pSMBr->ByteCount, data_offset));
4113 response_data = (FILE_SYSTEM_ALLOC_INFO *)
4114 (((char *) &pSMBr->hdr.Protocol) + data_offset);
4116 le16_to_cpu(response_data->BytesPerSector) *
4117 le32_to_cpu(response_data->
4118 SectorsPerAllocationUnit);
4120 le32_to_cpu(response_data->TotalAllocationUnits);
4121 FSData->f_bfree = FSData->f_bavail =
4122 le32_to_cpu(response_data->FreeAllocationUnits);
4124 ("Blocks: %lld Free: %lld Block size %ld",
4125 (unsigned long long)FSData->f_blocks,
4126 (unsigned long long)FSData->f_bfree,
4130 cifs_buf_release(pSMB);
4133 goto oldQFSInfoRetry;
4139 CIFSSMBQFSInfo(const int xid, struct cifsTconInfo *tcon, struct kstatfs *FSData)
4141 /* level 0x103 SMB_QUERY_FILE_SYSTEM_INFO */
4142 TRANSACTION2_QFSI_REQ *pSMB = NULL;
4143 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4144 FILE_SYSTEM_INFO *response_data;
4146 int bytes_returned = 0;
4147 __u16 params, byte_count;
4149 cFYI(1, ("In QFSInfo"));
4151 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4156 params = 2; /* level */
4157 pSMB->TotalDataCount = 0;
4158 pSMB->MaxParameterCount = cpu_to_le16(2);
4159 pSMB->MaxDataCount = cpu_to_le16(1000);
4160 pSMB->MaxSetupCount = 0;
4164 pSMB->Reserved2 = 0;
4165 byte_count = params + 1 /* pad */ ;
4166 pSMB->TotalParameterCount = cpu_to_le16(params);
4167 pSMB->ParameterCount = pSMB->TotalParameterCount;
4168 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4169 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4170 pSMB->DataCount = 0;
4171 pSMB->DataOffset = 0;
4172 pSMB->SetupCount = 1;
4173 pSMB->Reserved3 = 0;
4174 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4175 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_SIZE_INFO);
4176 pSMB->hdr.smb_buf_length += byte_count;
4177 pSMB->ByteCount = cpu_to_le16(byte_count);
4179 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4180 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4182 cFYI(1, ("Send error in QFSInfo = %d", rc));
4183 } else { /* decode response */
4184 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4186 if (rc || (pSMBr->ByteCount < 24))
4187 rc = -EIO; /* bad smb */
4189 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4193 *) (((char *) &pSMBr->hdr.Protocol) +
4196 le32_to_cpu(response_data->BytesPerSector) *
4197 le32_to_cpu(response_data->
4198 SectorsPerAllocationUnit);
4200 le64_to_cpu(response_data->TotalAllocationUnits);
4201 FSData->f_bfree = FSData->f_bavail =
4202 le64_to_cpu(response_data->FreeAllocationUnits);
4204 ("Blocks: %lld Free: %lld Block size %ld",
4205 (unsigned long long)FSData->f_blocks,
4206 (unsigned long long)FSData->f_bfree,
4210 cifs_buf_release(pSMB);
4219 CIFSSMBQFSAttributeInfo(const int xid, struct cifsTconInfo *tcon)
4221 /* level 0x105 SMB_QUERY_FILE_SYSTEM_INFO */
4222 TRANSACTION2_QFSI_REQ *pSMB = NULL;
4223 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4224 FILE_SYSTEM_ATTRIBUTE_INFO *response_data;
4226 int bytes_returned = 0;
4227 __u16 params, byte_count;
4229 cFYI(1, ("In QFSAttributeInfo"));
4231 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4236 params = 2; /* level */
4237 pSMB->TotalDataCount = 0;
4238 pSMB->MaxParameterCount = cpu_to_le16(2);
4239 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
4240 pSMB->MaxSetupCount = 0;
4244 pSMB->Reserved2 = 0;
4245 byte_count = params + 1 /* pad */ ;
4246 pSMB->TotalParameterCount = cpu_to_le16(params);
4247 pSMB->ParameterCount = pSMB->TotalParameterCount;
4248 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4249 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4250 pSMB->DataCount = 0;
4251 pSMB->DataOffset = 0;
4252 pSMB->SetupCount = 1;
4253 pSMB->Reserved3 = 0;
4254 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4255 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_ATTRIBUTE_INFO);
4256 pSMB->hdr.smb_buf_length += byte_count;
4257 pSMB->ByteCount = cpu_to_le16(byte_count);
4259 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4260 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4262 cERROR(1, ("Send error in QFSAttributeInfo = %d", rc));
4263 } else { /* decode response */
4264 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4266 if (rc || (pSMBr->ByteCount < 13)) {
4267 /* BB also check if enough bytes returned */
4268 rc = -EIO; /* bad smb */
4270 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4272 (FILE_SYSTEM_ATTRIBUTE_INFO
4273 *) (((char *) &pSMBr->hdr.Protocol) +
4275 memcpy(&tcon->fsAttrInfo, response_data,
4276 sizeof(FILE_SYSTEM_ATTRIBUTE_INFO));
4279 cifs_buf_release(pSMB);
4282 goto QFSAttributeRetry;
4288 CIFSSMBQFSDeviceInfo(const int xid, struct cifsTconInfo *tcon)
4290 /* level 0x104 SMB_QUERY_FILE_SYSTEM_INFO */
4291 TRANSACTION2_QFSI_REQ *pSMB = NULL;
4292 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4293 FILE_SYSTEM_DEVICE_INFO *response_data;
4295 int bytes_returned = 0;
4296 __u16 params, byte_count;
4298 cFYI(1, ("In QFSDeviceInfo"));
4300 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4305 params = 2; /* level */
4306 pSMB->TotalDataCount = 0;
4307 pSMB->MaxParameterCount = cpu_to_le16(2);
4308 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
4309 pSMB->MaxSetupCount = 0;
4313 pSMB->Reserved2 = 0;
4314 byte_count = params + 1 /* pad */ ;
4315 pSMB->TotalParameterCount = cpu_to_le16(params);
4316 pSMB->ParameterCount = pSMB->TotalParameterCount;
4317 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4318 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4320 pSMB->DataCount = 0;
4321 pSMB->DataOffset = 0;
4322 pSMB->SetupCount = 1;
4323 pSMB->Reserved3 = 0;
4324 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4325 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_DEVICE_INFO);
4326 pSMB->hdr.smb_buf_length += byte_count;
4327 pSMB->ByteCount = cpu_to_le16(byte_count);
4329 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4330 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4332 cFYI(1, ("Send error in QFSDeviceInfo = %d", rc));
4333 } else { /* decode response */
4334 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4336 if (rc || (pSMBr->ByteCount < sizeof (FILE_SYSTEM_DEVICE_INFO)))
4337 rc = -EIO; /* bad smb */
4339 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4341 (FILE_SYSTEM_DEVICE_INFO *)
4342 (((char *) &pSMBr->hdr.Protocol) +
4344 memcpy(&tcon->fsDevInfo, response_data,
4345 sizeof(FILE_SYSTEM_DEVICE_INFO));
4348 cifs_buf_release(pSMB);
4351 goto QFSDeviceRetry;
4357 CIFSSMBQFSUnixInfo(const int xid, struct cifsTconInfo *tcon)
4359 /* level 0x200 SMB_QUERY_CIFS_UNIX_INFO */
4360 TRANSACTION2_QFSI_REQ *pSMB = NULL;
4361 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4362 FILE_SYSTEM_UNIX_INFO *response_data;
4364 int bytes_returned = 0;
4365 __u16 params, byte_count;
4367 cFYI(1, ("In QFSUnixInfo"));
4369 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4374 params = 2; /* level */
4375 pSMB->TotalDataCount = 0;
4376 pSMB->DataCount = 0;
4377 pSMB->DataOffset = 0;
4378 pSMB->MaxParameterCount = cpu_to_le16(2);
4379 pSMB->MaxDataCount = cpu_to_le16(100); /* BB find exact max SMB PDU from sess structure BB */
4380 pSMB->MaxSetupCount = 0;
4384 pSMB->Reserved2 = 0;
4385 byte_count = params + 1 /* pad */ ;
4386 pSMB->ParameterCount = cpu_to_le16(params);
4387 pSMB->TotalParameterCount = pSMB->ParameterCount;
4388 pSMB->ParameterOffset = cpu_to_le16(offsetof(struct
4389 smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4390 pSMB->SetupCount = 1;
4391 pSMB->Reserved3 = 0;
4392 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4393 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_CIFS_UNIX_INFO);
4394 pSMB->hdr.smb_buf_length += byte_count;
4395 pSMB->ByteCount = cpu_to_le16(byte_count);
4397 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4398 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4400 cERROR(1, ("Send error in QFSUnixInfo = %d", rc));
4401 } else { /* decode response */
4402 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4404 if (rc || (pSMBr->ByteCount < 13)) {
4405 rc = -EIO; /* bad smb */
4407 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4409 (FILE_SYSTEM_UNIX_INFO
4410 *) (((char *) &pSMBr->hdr.Protocol) +
4412 memcpy(&tcon->fsUnixInfo, response_data,
4413 sizeof(FILE_SYSTEM_UNIX_INFO));
4416 cifs_buf_release(pSMB);
4426 CIFSSMBSetFSUnixInfo(const int xid, struct cifsTconInfo *tcon, __u64 cap)
4428 /* level 0x200 SMB_SET_CIFS_UNIX_INFO */
4429 TRANSACTION2_SETFSI_REQ *pSMB = NULL;
4430 TRANSACTION2_SETFSI_RSP *pSMBr = NULL;
4432 int bytes_returned = 0;
4433 __u16 params, param_offset, offset, byte_count;
4435 cFYI(1, ("In SETFSUnixInfo"));
4437 /* BB switch to small buf init to save memory */
4438 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4443 params = 4; /* 2 bytes zero followed by info level. */
4444 pSMB->MaxSetupCount = 0;
4448 pSMB->Reserved2 = 0;
4449 param_offset = offsetof(struct smb_com_transaction2_setfsi_req, FileNum)
4451 offset = param_offset + params;
4453 pSMB->MaxParameterCount = cpu_to_le16(4);
4454 pSMB->MaxDataCount = cpu_to_le16(100); /* BB find exact max SMB PDU from sess structure BB */
4455 pSMB->SetupCount = 1;
4456 pSMB->Reserved3 = 0;
4457 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FS_INFORMATION);
4458 byte_count = 1 /* pad */ + params + 12;
4460 pSMB->DataCount = cpu_to_le16(12);
4461 pSMB->ParameterCount = cpu_to_le16(params);
4462 pSMB->TotalDataCount = pSMB->DataCount;
4463 pSMB->TotalParameterCount = pSMB->ParameterCount;
4464 pSMB->ParameterOffset = cpu_to_le16(param_offset);
4465 pSMB->DataOffset = cpu_to_le16(offset);
4469 pSMB->InformationLevel = cpu_to_le16(SMB_SET_CIFS_UNIX_INFO);
4472 pSMB->ClientUnixMajor = cpu_to_le16(CIFS_UNIX_MAJOR_VERSION);
4473 pSMB->ClientUnixMinor = cpu_to_le16(CIFS_UNIX_MINOR_VERSION);
4474 pSMB->ClientUnixCap = cpu_to_le64(cap);
4476 pSMB->hdr.smb_buf_length += byte_count;
4477 pSMB->ByteCount = cpu_to_le16(byte_count);
4479 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4480 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4482 cERROR(1, ("Send error in SETFSUnixInfo = %d", rc));
4483 } else { /* decode response */
4484 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4486 rc = -EIO; /* bad smb */
4489 cifs_buf_release(pSMB);
4492 goto SETFSUnixRetry;
4500 CIFSSMBQFSPosixInfo(const int xid, struct cifsTconInfo *tcon,
4501 struct kstatfs *FSData)
4503 /* level 0x201 SMB_QUERY_CIFS_POSIX_INFO */
4504 TRANSACTION2_QFSI_REQ *pSMB = NULL;
4505 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4506 FILE_SYSTEM_POSIX_INFO *response_data;
4508 int bytes_returned = 0;
4509 __u16 params, byte_count;
4511 cFYI(1, ("In QFSPosixInfo"));
4513 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4518 params = 2; /* level */
4519 pSMB->TotalDataCount = 0;
4520 pSMB->DataCount = 0;
4521 pSMB->DataOffset = 0;
4522 pSMB->MaxParameterCount = cpu_to_le16(2);
4523 pSMB->MaxDataCount = cpu_to_le16(100); /* BB find exact max SMB PDU from sess structure BB */
4524 pSMB->MaxSetupCount = 0;
4528 pSMB->Reserved2 = 0;
4529 byte_count = params + 1 /* pad */ ;
4530 pSMB->ParameterCount = cpu_to_le16(params);
4531 pSMB->TotalParameterCount = pSMB->ParameterCount;
4532 pSMB->ParameterOffset = cpu_to_le16(offsetof(struct
4533 smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4534 pSMB->SetupCount = 1;
4535 pSMB->Reserved3 = 0;
4536 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4537 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_POSIX_FS_INFO);
4538 pSMB->hdr.smb_buf_length += byte_count;
4539 pSMB->ByteCount = cpu_to_le16(byte_count);
4541 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4542 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4544 cFYI(1, ("Send error in QFSUnixInfo = %d", rc));
4545 } else { /* decode response */
4546 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4548 if (rc || (pSMBr->ByteCount < 13)) {
4549 rc = -EIO; /* bad smb */
4551 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4553 (FILE_SYSTEM_POSIX_INFO
4554 *) (((char *) &pSMBr->hdr.Protocol) +
4557 le32_to_cpu(response_data->BlockSize);
4559 le64_to_cpu(response_data->TotalBlocks);
4561 le64_to_cpu(response_data->BlocksAvail);
4562 if (response_data->UserBlocksAvail == cpu_to_le64(-1)) {
4563 FSData->f_bavail = FSData->f_bfree;
4566 le64_to_cpu(response_data->UserBlocksAvail);
4568 if (response_data->TotalFileNodes != cpu_to_le64(-1))
4570 le64_to_cpu(response_data->TotalFileNodes);
4571 if (response_data->FreeFileNodes != cpu_to_le64(-1))
4573 le64_to_cpu(response_data->FreeFileNodes);
4576 cifs_buf_release(pSMB);
4585 /* We can not use write of zero bytes trick to
4586 set file size due to need for large file support. Also note that
4587 this SetPathInfo is preferred to SetFileInfo based method in next
4588 routine which is only needed to work around a sharing violation bug
4589 in Samba which this routine can run into */
4592 CIFSSMBSetEOF(const int xid, struct cifsTconInfo *tcon, const char *fileName,
4593 __u64 size, int SetAllocation,
4594 const struct nls_table *nls_codepage, int remap)
4596 struct smb_com_transaction2_spi_req *pSMB = NULL;
4597 struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
4598 struct file_end_of_file_info *parm_data;
4601 int bytes_returned = 0;
4602 __u16 params, byte_count, data_count, param_offset, offset;
4604 cFYI(1, ("In SetEOF"));
4606 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4611 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4613 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
4614 PATH_MAX, nls_codepage, remap);
4615 name_len++; /* trailing null */
4617 } else { /* BB improve the check for buffer overruns BB */
4618 name_len = strnlen(fileName, PATH_MAX);
4619 name_len++; /* trailing null */
4620 strncpy(pSMB->FileName, fileName, name_len);
4622 params = 6 + name_len;
4623 data_count = sizeof(struct file_end_of_file_info);
4624 pSMB->MaxParameterCount = cpu_to_le16(2);
4625 pSMB->MaxDataCount = cpu_to_le16(4100);
4626 pSMB->MaxSetupCount = 0;
4630 pSMB->Reserved2 = 0;
4631 param_offset = offsetof(struct smb_com_transaction2_spi_req,
4632 InformationLevel) - 4;
4633 offset = param_offset + params;
4634 if (SetAllocation) {
4635 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
4636 pSMB->InformationLevel =
4637 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2);
4639 pSMB->InformationLevel =
4640 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO);
4641 } else /* Set File Size */ {
4642 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
4643 pSMB->InformationLevel =
4644 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO2);
4646 pSMB->InformationLevel =
4647 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO);
4651 (struct file_end_of_file_info *) (((char *) &pSMB->hdr.Protocol) +
4653 pSMB->ParameterOffset = cpu_to_le16(param_offset);
4654 pSMB->DataOffset = cpu_to_le16(offset);
4655 pSMB->SetupCount = 1;
4656 pSMB->Reserved3 = 0;
4657 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
4658 byte_count = 3 /* pad */ + params + data_count;
4659 pSMB->DataCount = cpu_to_le16(data_count);
4660 pSMB->TotalDataCount = pSMB->DataCount;
4661 pSMB->ParameterCount = cpu_to_le16(params);
4662 pSMB->TotalParameterCount = pSMB->ParameterCount;
4663 pSMB->Reserved4 = 0;
4664 pSMB->hdr.smb_buf_length += byte_count;
4665 parm_data->FileSize = cpu_to_le64(size);
4666 pSMB->ByteCount = cpu_to_le16(byte_count);
4667 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4668 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4670 cFYI(1, ("SetPathInfo (file size) returned %d", rc));
4673 cifs_buf_release(pSMB);
4682 CIFSSMBSetFileSize(const int xid, struct cifsTconInfo *tcon, __u64 size,
4683 __u16 fid, __u32 pid_of_opener, int SetAllocation)
4685 struct smb_com_transaction2_sfi_req *pSMB = NULL;
4686 struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
4688 struct file_end_of_file_info *parm_data;
4690 int bytes_returned = 0;
4691 __u16 params, param_offset, offset, byte_count, count;
4693 cFYI(1, ("SetFileSize (via SetFileInfo) %lld",
4695 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
4700 pSMBr = (struct smb_com_transaction2_sfi_rsp *)pSMB;
4702 pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
4703 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));
4706 pSMB->MaxSetupCount = 0;
4710 pSMB->Reserved2 = 0;
4711 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
4712 offset = param_offset + params;
4714 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
4716 count = sizeof(struct file_end_of_file_info);
4717 pSMB->MaxParameterCount = cpu_to_le16(2);
4718 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB PDU from sess */
4719 pSMB->SetupCount = 1;
4720 pSMB->Reserved3 = 0;
4721 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
4722 byte_count = 3 /* pad */ + params + count;
4723 pSMB->DataCount = cpu_to_le16(count);
4724 pSMB->ParameterCount = cpu_to_le16(params);
4725 pSMB->TotalDataCount = pSMB->DataCount;
4726 pSMB->TotalParameterCount = pSMB->ParameterCount;
4727 pSMB->ParameterOffset = cpu_to_le16(param_offset);
4729 (struct file_end_of_file_info *) (((char *) &pSMB->hdr.Protocol)
4731 pSMB->DataOffset = cpu_to_le16(offset);
4732 parm_data->FileSize = cpu_to_le64(size);
4734 if (SetAllocation) {
4735 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
4736 pSMB->InformationLevel =
4737 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2);
4739 pSMB->InformationLevel =
4740 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO);
4741 } else /* Set File Size */ {
4742 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
4743 pSMB->InformationLevel =
4744 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO2);
4746 pSMB->InformationLevel =
4747 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO);
4749 pSMB->Reserved4 = 0;
4750 pSMB->hdr.smb_buf_length += byte_count;
4751 pSMB->ByteCount = cpu_to_le16(byte_count);
4752 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4753 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4756 ("Send error in SetFileInfo (SetFileSize) = %d",
4761 cifs_small_buf_release(pSMB);
4763 /* Note: On -EAGAIN error only caller can retry on handle based calls
4764 since file handle passed in no longer valid */
4769 /* Some legacy servers such as NT4 require that the file times be set on
4770 an open handle, rather than by pathname - this is awkward due to
4771 potential access conflicts on the open, but it is unavoidable for these
4772 old servers since the only other choice is to go from 100 nanosecond DCE
4773 time and resort to the original setpathinfo level which takes the ancient
4774 DOS time format with 2 second granularity */
4776 CIFSSMBSetFileTimes(const int xid, struct cifsTconInfo *tcon,
4777 const FILE_BASIC_INFO *data, __u16 fid)
4779 struct smb_com_transaction2_sfi_req *pSMB = NULL;
4780 struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
4783 int bytes_returned = 0;
4784 __u16 params, param_offset, offset, byte_count, count;
4786 cFYI(1, ("Set Times (via SetFileInfo)"));
4787 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
4792 pSMBr = (struct smb_com_transaction2_sfi_rsp *)pSMB;
4794 /* At this point there is no need to override the current pid
4795 with the pid of the opener, but that could change if we someday
4796 use an existing handle (rather than opening one on the fly) */
4797 /* pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
4798 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));*/
4801 pSMB->MaxSetupCount = 0;
4805 pSMB->Reserved2 = 0;
4806 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
4807 offset = param_offset + params;
4809 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
4811 count = sizeof(FILE_BASIC_INFO);
4812 pSMB->MaxParameterCount = cpu_to_le16(2);
4813 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB PDU from sess */
4814 pSMB->SetupCount = 1;
4815 pSMB->Reserved3 = 0;
4816 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
4817 byte_count = 3 /* pad */ + params + count;
4818 pSMB->DataCount = cpu_to_le16(count);
4819 pSMB->ParameterCount = cpu_to_le16(params);
4820 pSMB->TotalDataCount = pSMB->DataCount;
4821 pSMB->TotalParameterCount = pSMB->ParameterCount;
4822 pSMB->ParameterOffset = cpu_to_le16(param_offset);
4823 pSMB->DataOffset = cpu_to_le16(offset);
4825 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
4826 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO2);
4828 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO);
4829 pSMB->Reserved4 = 0;
4830 pSMB->hdr.smb_buf_length += byte_count;
4831 pSMB->ByteCount = cpu_to_le16(byte_count);
4832 memcpy(data_offset, data, sizeof(FILE_BASIC_INFO));
4833 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4834 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4836 cFYI(1, ("Send error in Set Time (SetFileInfo) = %d", rc));
4839 cifs_small_buf_release(pSMB);
4841 /* Note: On -EAGAIN error only caller can retry on handle based calls
4842 since file handle passed in no longer valid */
4849 CIFSSMBSetTimes(const int xid, struct cifsTconInfo *tcon, const char *fileName,
4850 const FILE_BASIC_INFO *data,
4851 const struct nls_table *nls_codepage, int remap)
4853 TRANSACTION2_SPI_REQ *pSMB = NULL;
4854 TRANSACTION2_SPI_RSP *pSMBr = NULL;
4857 int bytes_returned = 0;
4859 __u16 params, param_offset, offset, byte_count, count;
4861 cFYI(1, ("In SetTimes"));
4864 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4869 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4871 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
4872 PATH_MAX, nls_codepage, remap);
4873 name_len++; /* trailing null */
4875 } else { /* BB improve the check for buffer overruns BB */
4876 name_len = strnlen(fileName, PATH_MAX);
4877 name_len++; /* trailing null */
4878 strncpy(pSMB->FileName, fileName, name_len);
4881 params = 6 + name_len;
4882 count = sizeof(FILE_BASIC_INFO);
4883 pSMB->MaxParameterCount = cpu_to_le16(2);
4884 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
4885 pSMB->MaxSetupCount = 0;
4889 pSMB->Reserved2 = 0;
4890 param_offset = offsetof(struct smb_com_transaction2_spi_req,
4891 InformationLevel) - 4;
4892 offset = param_offset + params;
4893 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
4894 pSMB->ParameterOffset = cpu_to_le16(param_offset);
4895 pSMB->DataOffset = cpu_to_le16(offset);
4896 pSMB->SetupCount = 1;
4897 pSMB->Reserved3 = 0;
4898 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
4899 byte_count = 3 /* pad */ + params + count;
4901 pSMB->DataCount = cpu_to_le16(count);
4902 pSMB->ParameterCount = cpu_to_le16(params);
4903 pSMB->TotalDataCount = pSMB->DataCount;
4904 pSMB->TotalParameterCount = pSMB->ParameterCount;
4905 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
4906 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO2);
4908 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO);
4909 pSMB->Reserved4 = 0;
4910 pSMB->hdr.smb_buf_length += byte_count;
4911 memcpy(data_offset, data, sizeof(FILE_BASIC_INFO));
4912 pSMB->ByteCount = cpu_to_le16(byte_count);
4913 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4914 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4916 cFYI(1, ("SetPathInfo (times) returned %d", rc));
4919 cifs_buf_release(pSMB);
4927 /* Can not be used to set time stamps yet (due to old DOS time format) */
4928 /* Can be used to set attributes */
4929 #if 0 /* Possibly not needed - since it turns out that strangely NT4 has a bug
4930 handling it anyway and NT4 was what we thought it would be needed for
4931 Do not delete it until we prove whether needed for Win9x though */
4933 CIFSSMBSetAttrLegacy(int xid, struct cifsTconInfo *tcon, char *fileName,
4934 __u16 dos_attrs, const struct nls_table *nls_codepage)
4936 SETATTR_REQ *pSMB = NULL;
4937 SETATTR_RSP *pSMBr = NULL;
4942 cFYI(1, ("In SetAttrLegacy"));
4945 rc = smb_init(SMB_COM_SETATTR, 8, tcon, (void **) &pSMB,
4950 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4952 ConvertToUCS((__le16 *) pSMB->fileName, fileName,
4953 PATH_MAX, nls_codepage);
4954 name_len++; /* trailing null */
4956 } else { /* BB improve the check for buffer overruns BB */
4957 name_len = strnlen(fileName, PATH_MAX);
4958 name_len++; /* trailing null */
4959 strncpy(pSMB->fileName, fileName, name_len);
4961 pSMB->attr = cpu_to_le16(dos_attrs);
4962 pSMB->BufferFormat = 0x04;
4963 pSMB->hdr.smb_buf_length += name_len + 1;
4964 pSMB->ByteCount = cpu_to_le16(name_len + 1);
4965 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4966 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4968 cFYI(1, ("Error in LegacySetAttr = %d", rc));
4971 cifs_buf_release(pSMB);
4974 goto SetAttrLgcyRetry;
4978 #endif /* temporarily unneeded SetAttr legacy function */
4981 CIFSSMBUnixSetPerms(const int xid, struct cifsTconInfo *tcon,
4982 char *fileName, __u64 mode, __u64 uid, __u64 gid,
4983 dev_t device, const struct nls_table *nls_codepage,
4986 TRANSACTION2_SPI_REQ *pSMB = NULL;
4987 TRANSACTION2_SPI_RSP *pSMBr = NULL;
4990 int bytes_returned = 0;
4991 FILE_UNIX_BASIC_INFO *data_offset;
4992 __u16 params, param_offset, offset, count, byte_count;
4994 cFYI(1, ("In SetUID/GID/Mode"));
4996 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5001 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5003 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
5004 PATH_MAX, nls_codepage, remap);
5005 name_len++; /* trailing null */
5007 } else { /* BB improve the check for buffer overruns BB */
5008 name_len = strnlen(fileName, PATH_MAX);
5009 name_len++; /* trailing null */
5010 strncpy(pSMB->FileName, fileName, name_len);
5013 params = 6 + name_len;
5014 count = sizeof(FILE_UNIX_BASIC_INFO);
5015 pSMB->MaxParameterCount = cpu_to_le16(2);
5016 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
5017 pSMB->MaxSetupCount = 0;
5021 pSMB->Reserved2 = 0;
5022 param_offset = offsetof(struct smb_com_transaction2_spi_req,
5023 InformationLevel) - 4;
5024 offset = param_offset + params;
5026 (FILE_UNIX_BASIC_INFO *) ((char *) &pSMB->hdr.Protocol +
5028 memset(data_offset, 0, count);
5029 pSMB->DataOffset = cpu_to_le16(offset);
5030 pSMB->ParameterOffset = cpu_to_le16(param_offset);
5031 pSMB->SetupCount = 1;
5032 pSMB->Reserved3 = 0;
5033 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
5034 byte_count = 3 /* pad */ + params + count;
5035 pSMB->ParameterCount = cpu_to_le16(params);
5036 pSMB->DataCount = cpu_to_le16(count);
5037 pSMB->TotalParameterCount = pSMB->ParameterCount;
5038 pSMB->TotalDataCount = pSMB->DataCount;
5039 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_BASIC);
5040 pSMB->Reserved4 = 0;
5041 pSMB->hdr.smb_buf_length += byte_count;
5042 /* Samba server ignores set of file size to zero due to bugs in some
5043 older clients, but we should be precise - we use SetFileSize to
5044 set file size and do not want to truncate file size to zero
5045 accidently as happened on one Samba server beta by putting
5046 zero instead of -1 here */
5047 data_offset->EndOfFile = NO_CHANGE_64;
5048 data_offset->NumOfBytes = NO_CHANGE_64;
5049 data_offset->LastStatusChange = NO_CHANGE_64;
5050 data_offset->LastAccessTime = NO_CHANGE_64;
5051 data_offset->LastModificationTime = NO_CHANGE_64;
5052 data_offset->Uid = cpu_to_le64(uid);
5053 data_offset->Gid = cpu_to_le64(gid);
5054 /* better to leave device as zero when it is */
5055 data_offset->DevMajor = cpu_to_le64(MAJOR(device));
5056 data_offset->DevMinor = cpu_to_le64(MINOR(device));
5057 data_offset->Permissions = cpu_to_le64(mode);
5060 data_offset->Type = cpu_to_le32(UNIX_FILE);
5061 else if (S_ISDIR(mode))
5062 data_offset->Type = cpu_to_le32(UNIX_DIR);
5063 else if (S_ISLNK(mode))
5064 data_offset->Type = cpu_to_le32(UNIX_SYMLINK);
5065 else if (S_ISCHR(mode))
5066 data_offset->Type = cpu_to_le32(UNIX_CHARDEV);
5067 else if (S_ISBLK(mode))
5068 data_offset->Type = cpu_to_le32(UNIX_BLOCKDEV);
5069 else if (S_ISFIFO(mode))
5070 data_offset->Type = cpu_to_le32(UNIX_FIFO);
5071 else if (S_ISSOCK(mode))
5072 data_offset->Type = cpu_to_le32(UNIX_SOCKET);
5075 pSMB->ByteCount = cpu_to_le16(byte_count);
5076 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5077 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5079 cFYI(1, ("SetPathInfo (perms) returned %d", rc));
5083 cifs_buf_release(pSMB);
5089 int CIFSSMBNotify(const int xid, struct cifsTconInfo *tcon,
5090 const int notify_subdirs, const __u16 netfid,
5091 __u32 filter, struct file *pfile, int multishot,
5092 const struct nls_table *nls_codepage)
5095 struct smb_com_transaction_change_notify_req *pSMB = NULL;
5096 struct smb_com_ntransaction_change_notify_rsp *pSMBr = NULL;
5097 struct dir_notify_req *dnotify_req;
5100 cFYI(1, ("In CIFSSMBNotify for file handle %d", (int)netfid));
5101 rc = smb_init(SMB_COM_NT_TRANSACT, 23, tcon, (void **) &pSMB,
5106 pSMB->TotalParameterCount = 0 ;
5107 pSMB->TotalDataCount = 0;
5108 pSMB->MaxParameterCount = cpu_to_le32(2);
5109 /* BB find exact data count max from sess structure BB */
5110 pSMB->MaxDataCount = 0; /* same in little endian or be */
5111 /* BB VERIFY verify which is correct for above BB */
5112 pSMB->MaxDataCount = cpu_to_le32((tcon->ses->server->maxBuf -
5113 MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
5115 pSMB->MaxSetupCount = 4;
5117 pSMB->ParameterOffset = 0;
5118 pSMB->DataCount = 0;
5119 pSMB->DataOffset = 0;
5120 pSMB->SetupCount = 4; /* single byte does not need le conversion */
5121 pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_NOTIFY_CHANGE);
5122 pSMB->ParameterCount = pSMB->TotalParameterCount;
5124 pSMB->WatchTree = 1; /* one byte - no le conversion needed */
5125 pSMB->Reserved2 = 0;
5126 pSMB->CompletionFilter = cpu_to_le32(filter);
5127 pSMB->Fid = netfid; /* file handle always le */
5128 pSMB->ByteCount = 0;
5130 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5131 (struct smb_hdr *) pSMBr, &bytes_returned, -1);
5133 cFYI(1, ("Error in Notify = %d", rc));
5135 /* Add file to outstanding requests */
5136 /* BB change to kmem cache alloc */
5137 dnotify_req = kmalloc(
5138 sizeof(struct dir_notify_req),
5141 dnotify_req->Pid = pSMB->hdr.Pid;
5142 dnotify_req->PidHigh = pSMB->hdr.PidHigh;
5143 dnotify_req->Mid = pSMB->hdr.Mid;
5144 dnotify_req->Tid = pSMB->hdr.Tid;
5145 dnotify_req->Uid = pSMB->hdr.Uid;
5146 dnotify_req->netfid = netfid;
5147 dnotify_req->pfile = pfile;
5148 dnotify_req->filter = filter;
5149 dnotify_req->multishot = multishot;
5150 spin_lock(&GlobalMid_Lock);
5151 list_add_tail(&dnotify_req->lhead,
5152 &GlobalDnotifyReqList);
5153 spin_unlock(&GlobalMid_Lock);
5157 cifs_buf_release(pSMB);
5160 #ifdef CONFIG_CIFS_XATTR
5162 CIFSSMBQAllEAs(const int xid, struct cifsTconInfo *tcon,
5163 const unsigned char *searchName,
5164 char *EAData, size_t buf_size,
5165 const struct nls_table *nls_codepage, int remap)
5167 /* BB assumes one setup word */
5168 TRANSACTION2_QPI_REQ *pSMB = NULL;
5169 TRANSACTION2_QPI_RSP *pSMBr = NULL;
5173 struct fea *temp_fea;
5175 __u16 params, byte_count;
5177 cFYI(1, ("In Query All EAs path %s", searchName));
5179 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5184 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5186 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
5187 PATH_MAX, nls_codepage, remap);
5188 name_len++; /* trailing null */
5190 } else { /* BB improve the check for buffer overruns BB */
5191 name_len = strnlen(searchName, PATH_MAX);
5192 name_len++; /* trailing null */
5193 strncpy(pSMB->FileName, searchName, name_len);
5196 params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */;
5197 pSMB->TotalDataCount = 0;
5198 pSMB->MaxParameterCount = cpu_to_le16(2);
5199 pSMB->MaxDataCount = cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
5200 pSMB->MaxSetupCount = 0;
5204 pSMB->Reserved2 = 0;
5205 pSMB->ParameterOffset = cpu_to_le16(offsetof(
5206 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
5207 pSMB->DataCount = 0;
5208 pSMB->DataOffset = 0;
5209 pSMB->SetupCount = 1;
5210 pSMB->Reserved3 = 0;
5211 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
5212 byte_count = params + 1 /* pad */ ;
5213 pSMB->TotalParameterCount = cpu_to_le16(params);
5214 pSMB->ParameterCount = pSMB->TotalParameterCount;
5215 pSMB->InformationLevel = cpu_to_le16(SMB_INFO_QUERY_ALL_EAS);
5216 pSMB->Reserved4 = 0;
5217 pSMB->hdr.smb_buf_length += byte_count;
5218 pSMB->ByteCount = cpu_to_le16(byte_count);
5220 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5221 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5223 cFYI(1, ("Send error in QueryAllEAs = %d", rc));
5224 } else { /* decode response */
5225 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
5227 /* BB also check enough total bytes returned */
5228 /* BB we need to improve the validity checking
5229 of these trans2 responses */
5230 if (rc || (pSMBr->ByteCount < 4))
5231 rc = -EIO; /* bad smb */
5232 /* else if (pFindData){
5233 memcpy((char *) pFindData,
5234 (char *) &pSMBr->hdr.Protocol +
5237 /* check that length of list is not more than bcc */
5238 /* check that each entry does not go beyond length
5240 /* check that each element of each entry does not
5241 go beyond end of list */
5242 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
5243 struct fealist *ea_response_data;
5245 /* validate_trans2_offsets() */
5246 /* BB check if start of smb + data_offset > &bcc+ bcc */
5247 ea_response_data = (struct fealist *)
5248 (((char *) &pSMBr->hdr.Protocol) +
5250 name_len = le32_to_cpu(ea_response_data->list_len);
5251 cFYI(1, ("ea length %d", name_len));
5252 if (name_len <= 8) {
5253 /* returned EA size zeroed at top of function */
5254 cFYI(1, ("empty EA list returned from server"));
5256 /* account for ea list len */
5258 temp_fea = ea_response_data->list;
5259 temp_ptr = (char *)temp_fea;
5260 while (name_len > 0) {
5264 rc += temp_fea->name_len;
5265 /* account for prefix user. and trailing null */
5267 if (rc < (int)buf_size) {
5268 memcpy(EAData, "user.", 5);
5270 memcpy(EAData, temp_ptr,
5271 temp_fea->name_len);
5272 EAData += temp_fea->name_len;
5273 /* null terminate name */
5275 EAData = EAData + 1;
5276 } else if (buf_size == 0) {
5277 /* skip copy - calc size only */
5279 /* stop before overrun buffer */
5283 name_len -= temp_fea->name_len;
5284 temp_ptr += temp_fea->name_len;
5285 /* account for trailing null */
5289 le16_to_cpu(temp_fea->value_len);
5290 name_len -= value_len;
5291 temp_ptr += value_len;
5292 /* BB check that temp_ptr is still
5295 /* no trailing null to account for
5297 /* go on to next EA */
5298 temp_fea = (struct fea *)temp_ptr;
5304 cifs_buf_release(pSMB);
5311 ssize_t CIFSSMBQueryEA(const int xid, struct cifsTconInfo *tcon,
5312 const unsigned char *searchName, const unsigned char *ea_name,
5313 unsigned char *ea_value, size_t buf_size,
5314 const struct nls_table *nls_codepage, int remap)
5316 TRANSACTION2_QPI_REQ *pSMB = NULL;
5317 TRANSACTION2_QPI_RSP *pSMBr = NULL;
5321 struct fea *temp_fea;
5323 __u16 params, byte_count;
5325 cFYI(1, ("In Query EA path %s", searchName));
5327 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5332 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5334 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
5335 PATH_MAX, nls_codepage, remap);
5336 name_len++; /* trailing null */
5338 } else { /* BB improve the check for buffer overruns BB */
5339 name_len = strnlen(searchName, PATH_MAX);
5340 name_len++; /* trailing null */
5341 strncpy(pSMB->FileName, searchName, name_len);
5344 params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */;
5345 pSMB->TotalDataCount = 0;
5346 pSMB->MaxParameterCount = cpu_to_le16(2);
5347 pSMB->MaxDataCount = cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
5348 pSMB->MaxSetupCount = 0;
5352 pSMB->Reserved2 = 0;
5353 pSMB->ParameterOffset = cpu_to_le16(offsetof(
5354 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
5355 pSMB->DataCount = 0;
5356 pSMB->DataOffset = 0;
5357 pSMB->SetupCount = 1;
5358 pSMB->Reserved3 = 0;
5359 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
5360 byte_count = params + 1 /* pad */ ;
5361 pSMB->TotalParameterCount = cpu_to_le16(params);
5362 pSMB->ParameterCount = pSMB->TotalParameterCount;
5363 pSMB->InformationLevel = cpu_to_le16(SMB_INFO_QUERY_ALL_EAS);
5364 pSMB->Reserved4 = 0;
5365 pSMB->hdr.smb_buf_length += byte_count;
5366 pSMB->ByteCount = cpu_to_le16(byte_count);
5368 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5369 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5371 cFYI(1, ("Send error in Query EA = %d", rc));
5372 } else { /* decode response */
5373 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
5375 /* BB also check enough total bytes returned */
5376 /* BB we need to improve the validity checking
5377 of these trans2 responses */
5378 if (rc || (pSMBr->ByteCount < 4))
5379 rc = -EIO; /* bad smb */
5380 /* else if (pFindData){
5381 memcpy((char *) pFindData,
5382 (char *) &pSMBr->hdr.Protocol +
5385 /* check that length of list is not more than bcc */
5386 /* check that each entry does not go beyond length
5388 /* check that each element of each entry does not
5389 go beyond end of list */
5390 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
5391 struct fealist *ea_response_data;
5393 /* validate_trans2_offsets() */
5394 /* BB check if start of smb + data_offset > &bcc+ bcc*/
5395 ea_response_data = (struct fealist *)
5396 (((char *) &pSMBr->hdr.Protocol) +
5398 name_len = le32_to_cpu(ea_response_data->list_len);
5399 cFYI(1, ("ea length %d", name_len));
5400 if (name_len <= 8) {
5401 /* returned EA size zeroed at top of function */
5402 cFYI(1, ("empty EA list returned from server"));
5404 /* account for ea list len */
5406 temp_fea = ea_response_data->list;
5407 temp_ptr = (char *)temp_fea;
5408 /* loop through checking if we have a matching
5409 name and then return the associated value */
5410 while (name_len > 0) {
5415 le16_to_cpu(temp_fea->value_len);
5416 /* BB validate that value_len falls within SMB,
5417 even though maximum for name_len is 255 */
5418 if (memcmp(temp_fea->name, ea_name,
5419 temp_fea->name_len) == 0) {
5422 /* account for prefix user. and trailing null */
5423 if (rc <= (int)buf_size) {
5425 temp_fea->name+temp_fea->name_len+1,
5427 /* ea values, unlike ea
5430 } else if (buf_size == 0) {
5431 /* skip copy - calc size only */
5433 /* stop before overrun buffer */
5438 name_len -= temp_fea->name_len;
5439 temp_ptr += temp_fea->name_len;
5440 /* account for trailing null */
5443 name_len -= value_len;
5444 temp_ptr += value_len;
5445 /* No trailing null to account for in
5446 value_len. Go on to next EA */
5447 temp_fea = (struct fea *)temp_ptr;
5453 cifs_buf_release(pSMB);
5461 CIFSSMBSetEA(const int xid, struct cifsTconInfo *tcon, const char *fileName,
5462 const char *ea_name, const void *ea_value,
5463 const __u16 ea_value_len, const struct nls_table *nls_codepage,
5466 struct smb_com_transaction2_spi_req *pSMB = NULL;
5467 struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
5468 struct fealist *parm_data;
5471 int bytes_returned = 0;
5472 __u16 params, param_offset, byte_count, offset, count;
5474 cFYI(1, ("In SetEA"));
5476 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5481 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5483 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
5484 PATH_MAX, nls_codepage, remap);
5485 name_len++; /* trailing null */
5487 } else { /* BB improve the check for buffer overruns BB */
5488 name_len = strnlen(fileName, PATH_MAX);
5489 name_len++; /* trailing null */
5490 strncpy(pSMB->FileName, fileName, name_len);
5493 params = 6 + name_len;
5495 /* done calculating parms using name_len of file name,
5496 now use name_len to calculate length of ea name
5497 we are going to create in the inode xattrs */
5498 if (ea_name == NULL)
5501 name_len = strnlen(ea_name, 255);
5503 count = sizeof(*parm_data) + ea_value_len + name_len + 1;
5504 pSMB->MaxParameterCount = cpu_to_le16(2);
5505 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB size from sess */
5506 pSMB->MaxSetupCount = 0;
5510 pSMB->Reserved2 = 0;
5511 param_offset = offsetof(struct smb_com_transaction2_spi_req,
5512 InformationLevel) - 4;
5513 offset = param_offset + params;
5514 pSMB->InformationLevel =
5515 cpu_to_le16(SMB_SET_FILE_EA);
5518 (struct fealist *) (((char *) &pSMB->hdr.Protocol) +
5520 pSMB->ParameterOffset = cpu_to_le16(param_offset);
5521 pSMB->DataOffset = cpu_to_le16(offset);
5522 pSMB->SetupCount = 1;
5523 pSMB->Reserved3 = 0;
5524 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
5525 byte_count = 3 /* pad */ + params + count;
5526 pSMB->DataCount = cpu_to_le16(count);
5527 parm_data->list_len = cpu_to_le32(count);
5528 parm_data->list[0].EA_flags = 0;
5529 /* we checked above that name len is less than 255 */
5530 parm_data->list[0].name_len = (__u8)name_len;
5531 /* EA names are always ASCII */
5533 strncpy(parm_data->list[0].name, ea_name, name_len);
5534 parm_data->list[0].name[name_len] = 0;
5535 parm_data->list[0].value_len = cpu_to_le16(ea_value_len);
5536 /* caller ensures that ea_value_len is less than 64K but
5537 we need to ensure that it fits within the smb */
5539 /*BB add length check to see if it would fit in
5540 negotiated SMB buffer size BB */
5541 /* if (ea_value_len > buffer_size - 512 (enough for header)) */
5543 memcpy(parm_data->list[0].name+name_len+1,
5544 ea_value, ea_value_len);
5546 pSMB->TotalDataCount = pSMB->DataCount;
5547 pSMB->ParameterCount = cpu_to_le16(params);
5548 pSMB->TotalParameterCount = pSMB->ParameterCount;
5549 pSMB->Reserved4 = 0;
5550 pSMB->hdr.smb_buf_length += byte_count;
5551 pSMB->ByteCount = cpu_to_le16(byte_count);
5552 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5553 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5555 cFYI(1, ("SetPathInfo (EA) returned %d", rc));
5558 cifs_buf_release(pSMB);