4 * Copyright (C) International Business Machines Corp., 2002,2009
5 * Author(s): Steve French (sfrench@us.ibm.com)
7 * Contains the routines for constructing the SMB PDUs themselves
9 * This library is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU Lesser General Public License as published
11 * by the Free Software Foundation; either version 2.1 of the License, or
12 * (at your option) any later version.
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
17 * the GNU Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public License
20 * along with this library; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 /* SMB/CIFS PDU handling routines here - except for leftovers in connect.c */
25 /* These are mostly routines that operate on a pathname, or on a tree id */
26 /* (mounted volume), but there are eight handle based routines which must be */
27 /* treated slightly differently for reconnection purposes since we never */
28 /* want to reuse a stale file handle and only the caller knows the file info */
31 #include <linux/kernel.h>
32 #include <linux/vfs.h>
33 #include <linux/posix_acl_xattr.h>
34 #include <asm/uaccess.h>
38 #include "cifsproto.h"
39 #include "cifs_unicode.h"
40 #include "cifs_debug.h"
42 #ifdef CONFIG_CIFS_POSIX
47 #ifdef CONFIG_CIFS_WEAK_PW_HASH
48 {LANMAN_PROT
, "\2LM1.2X002"},
49 {LANMAN2_PROT
, "\2LANMAN2.1"},
50 #endif /* weak password hashing for legacy clients */
51 {CIFS_PROT
, "\2NT LM 0.12"},
52 {POSIX_PROT
, "\2POSIX 2"},
60 #ifdef CONFIG_CIFS_WEAK_PW_HASH
61 {LANMAN_PROT
, "\2LM1.2X002"},
62 {LANMAN2_PROT
, "\2LANMAN2.1"},
63 #endif /* weak password hashing for legacy clients */
64 {CIFS_PROT
, "\2NT LM 0.12"},
69 /* define the number of elements in the cifs dialect array */
70 #ifdef CONFIG_CIFS_POSIX
71 #ifdef CONFIG_CIFS_WEAK_PW_HASH
72 #define CIFS_NUM_PROT 4
74 #define CIFS_NUM_PROT 2
75 #endif /* CIFS_WEAK_PW_HASH */
77 #ifdef CONFIG_CIFS_WEAK_PW_HASH
78 #define CIFS_NUM_PROT 3
80 #define CIFS_NUM_PROT 1
81 #endif /* CONFIG_CIFS_WEAK_PW_HASH */
82 #endif /* CIFS_POSIX */
84 /* Mark as invalid, all open files on tree connections since they
85 were closed when session to server was lost */
86 static void mark_open_files_invalid(struct cifsTconInfo
*pTcon
)
88 struct cifsFileInfo
*open_file
= NULL
;
89 struct list_head
*tmp
;
90 struct list_head
*tmp1
;
92 /* list all files open on tree connection and mark them invalid */
93 write_lock(&GlobalSMBSeslock
);
94 list_for_each_safe(tmp
, tmp1
, &pTcon
->openFileList
) {
95 open_file
= list_entry(tmp
, struct cifsFileInfo
, tlist
);
96 open_file
->invalidHandle
= true;
97 open_file
->oplock_break_cancelled
= true;
99 write_unlock(&GlobalSMBSeslock
);
100 /* BB Add call to invalidate_inodes(sb) for all superblocks mounted
104 /* reconnect the socket, tcon, and smb session if needed */
106 cifs_reconnect_tcon(struct cifsTconInfo
*tcon
, int smb_command
)
109 struct cifsSesInfo
*ses
;
110 struct TCP_Server_Info
*server
;
111 struct nls_table
*nls_codepage
;
114 * SMBs NegProt, SessSetup, uLogoff do not have tcon yet so check for
115 * tcp and smb session status done differently for those three - in the
122 server
= ses
->server
;
125 * only tree disconnect, open, and write, (and ulogoff which does not
126 * have tcon) are allowed as we start force umount
128 if (tcon
->tidStatus
== CifsExiting
) {
129 if (smb_command
!= SMB_COM_WRITE_ANDX
&&
130 smb_command
!= SMB_COM_OPEN_ANDX
&&
131 smb_command
!= SMB_COM_TREE_DISCONNECT
) {
132 cFYI(1, ("can not send cmd %d while umounting",
138 if (ses
->status
== CifsExiting
)
142 * Give demultiplex thread up to 10 seconds to reconnect, should be
143 * greater than cifs socket timeout which is 7 seconds
145 while (server
->tcpStatus
== CifsNeedReconnect
) {
146 wait_event_interruptible_timeout(server
->response_q
,
147 (server
->tcpStatus
== CifsGood
), 10 * HZ
);
149 /* is TCP session is reestablished now ?*/
150 if (server
->tcpStatus
!= CifsNeedReconnect
)
154 * on "soft" mounts we wait once. Hard mounts keep
155 * retrying until process is killed or server comes
158 if (!tcon
->retry
|| ses
->status
== CifsExiting
) {
159 cFYI(1, ("gave up waiting on reconnect in smb_init"));
164 if (!ses
->need_reconnect
&& !tcon
->need_reconnect
)
167 nls_codepage
= load_nls_default();
170 * need to prevent multiple threads trying to simultaneously
171 * reconnect the same SMB session
173 mutex_lock(&ses
->session_mutex
);
174 if (ses
->need_reconnect
)
175 rc
= cifs_setup_session(0, ses
, nls_codepage
);
177 /* do we need to reconnect tcon? */
178 if (rc
|| !tcon
->need_reconnect
) {
179 mutex_unlock(&ses
->session_mutex
);
183 mark_open_files_invalid(tcon
);
184 rc
= CIFSTCon(0, ses
, tcon
->treeName
, tcon
, nls_codepage
);
185 mutex_unlock(&ses
->session_mutex
);
186 cFYI(1, ("reconnect tcon rc = %d", rc
));
192 * FIXME: check if wsize needs updated due to negotiated smb buffer
195 atomic_inc(&tconInfoReconnectCount
);
197 /* tell server Unix caps we support */
198 if (ses
->capabilities
& CAP_UNIX
)
199 reset_cifs_unix_caps(0, tcon
, NULL
, NULL
);
202 * Removed call to reopen open files here. It is safer (and faster) to
203 * reopen files one at a time as needed in read and write.
205 * FIXME: what about file locks? don't we need to reclaim them ASAP?
210 * Check if handle based operation so we know whether we can continue
211 * or not without returning to caller to reset file handle
213 switch (smb_command
) {
214 case SMB_COM_READ_ANDX
:
215 case SMB_COM_WRITE_ANDX
:
217 case SMB_COM_FIND_CLOSE2
:
218 case SMB_COM_LOCKING_ANDX
:
222 unload_nls(nls_codepage
);
226 /* Allocate and return pointer to an SMB request buffer, and set basic
227 SMB information in the SMB header. If the return code is zero, this
228 function must have filled in request_buf pointer */
230 small_smb_init(int smb_command
, int wct
, struct cifsTconInfo
*tcon
,
235 rc
= cifs_reconnect_tcon(tcon
, smb_command
);
239 *request_buf
= cifs_small_buf_get();
240 if (*request_buf
== NULL
) {
241 /* BB should we add a retry in here if not a writepage? */
245 header_assemble((struct smb_hdr
*) *request_buf
, smb_command
,
249 cifs_stats_inc(&tcon
->num_smbs_sent
);
255 small_smb_init_no_tc(const int smb_command
, const int wct
,
256 struct cifsSesInfo
*ses
, void **request_buf
)
259 struct smb_hdr
*buffer
;
261 rc
= small_smb_init(smb_command
, wct
, NULL
, request_buf
);
265 buffer
= (struct smb_hdr
*)*request_buf
;
266 buffer
->Mid
= GetNextMid(ses
->server
);
267 if (ses
->capabilities
& CAP_UNICODE
)
268 buffer
->Flags2
|= SMBFLG2_UNICODE
;
269 if (ses
->capabilities
& CAP_STATUS32
)
270 buffer
->Flags2
|= SMBFLG2_ERR_STATUS
;
272 /* uid, tid can stay at zero as set in header assemble */
274 /* BB add support for turning on the signing when
275 this function is used after 1st of session setup requests */
280 /* If the return code is zero, this function must fill in request_buf pointer */
282 smb_init(int smb_command
, int wct
, struct cifsTconInfo
*tcon
,
283 void **request_buf
/* returned */ ,
284 void **response_buf
/* returned */ )
288 rc
= cifs_reconnect_tcon(tcon
, smb_command
);
292 *request_buf
= cifs_buf_get();
293 if (*request_buf
== NULL
) {
294 /* BB should we add a retry in here if not a writepage? */
297 /* Although the original thought was we needed the response buf for */
298 /* potential retries of smb operations it turns out we can determine */
299 /* from the mid flags when the request buffer can be resent without */
300 /* having to use a second distinct buffer for the response */
302 *response_buf
= *request_buf
;
304 header_assemble((struct smb_hdr
*) *request_buf
, smb_command
, tcon
,
308 cifs_stats_inc(&tcon
->num_smbs_sent
);
313 static int validate_t2(struct smb_t2_rsp
*pSMB
)
319 /* check for plausible wct, bcc and t2 data and parm sizes */
320 /* check for parm and data offset going beyond end of smb */
321 if (pSMB
->hdr
.WordCount
>= 10) {
322 if ((le16_to_cpu(pSMB
->t2_rsp
.ParameterOffset
) <= 1024) &&
323 (le16_to_cpu(pSMB
->t2_rsp
.DataOffset
) <= 1024)) {
324 /* check that bcc is at least as big as parms + data */
325 /* check that bcc is less than negotiated smb buffer */
326 total_size
= le16_to_cpu(pSMB
->t2_rsp
.ParameterCount
);
327 if (total_size
< 512) {
329 le16_to_cpu(pSMB
->t2_rsp
.DataCount
);
330 /* BCC le converted in SendReceive */
331 pBCC
= (pSMB
->hdr
.WordCount
* 2) +
332 sizeof(struct smb_hdr
) +
334 if ((total_size
<= (*(u16
*)pBCC
)) &&
336 CIFSMaxBufSize
+MAX_CIFS_HDR_SIZE
)) {
342 cifs_dump_mem("Invalid transact2 SMB: ", (char *)pSMB
,
343 sizeof(struct smb_t2_rsp
) + 16);
347 CIFSSMBNegotiate(unsigned int xid
, struct cifsSesInfo
*ses
)
350 NEGOTIATE_RSP
*pSMBr
;
354 struct TCP_Server_Info
*server
;
356 unsigned int secFlags
;
360 server
= ses
->server
;
365 rc
= smb_init(SMB_COM_NEGOTIATE
, 0, NULL
/* no tcon yet */ ,
366 (void **) &pSMB
, (void **) &pSMBr
);
370 /* if any of auth flags (ie not sign or seal) are overriden use them */
371 if (ses
->overrideSecFlg
& (~(CIFSSEC_MUST_SIGN
| CIFSSEC_MUST_SEAL
)))
372 secFlags
= ses
->overrideSecFlg
; /* BB FIXME fix sign flags? */
373 else /* if override flags set only sign/seal OR them with global auth */
374 secFlags
= extended_security
| ses
->overrideSecFlg
;
376 cFYI(1, ("secFlags 0x%x", secFlags
));
378 pSMB
->hdr
.Mid
= GetNextMid(server
);
379 pSMB
->hdr
.Flags2
|= (SMBFLG2_UNICODE
| SMBFLG2_ERR_STATUS
);
381 if ((secFlags
& CIFSSEC_MUST_KRB5
) == CIFSSEC_MUST_KRB5
)
382 pSMB
->hdr
.Flags2
|= SMBFLG2_EXT_SEC
;
383 else if ((secFlags
& CIFSSEC_AUTH_MASK
) == CIFSSEC_MAY_KRB5
) {
384 cFYI(1, ("Kerberos only mechanism, enable extended security"));
385 pSMB
->hdr
.Flags2
|= SMBFLG2_EXT_SEC
;
387 #ifdef CONFIG_CIFS_EXPERIMENTAL
388 else if ((secFlags
& CIFSSEC_MUST_NTLMSSP
) == CIFSSEC_MUST_NTLMSSP
)
389 pSMB
->hdr
.Flags2
|= SMBFLG2_EXT_SEC
;
390 else if ((secFlags
& CIFSSEC_AUTH_MASK
) == CIFSSEC_MAY_NTLMSSP
) {
391 cFYI(1, ("NTLMSSP only mechanism, enable extended security"));
392 pSMB
->hdr
.Flags2
|= SMBFLG2_EXT_SEC
;
397 for (i
= 0; i
< CIFS_NUM_PROT
; i
++) {
398 strncpy(pSMB
->DialectsArray
+count
, protocols
[i
].name
, 16);
399 count
+= strlen(protocols
[i
].name
) + 1;
400 /* null at end of source and target buffers anyway */
402 pSMB
->hdr
.smb_buf_length
+= count
;
403 pSMB
->ByteCount
= cpu_to_le16(count
);
405 rc
= SendReceive(xid
, ses
, (struct smb_hdr
*) pSMB
,
406 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
410 dialect
= le16_to_cpu(pSMBr
->DialectIndex
);
411 cFYI(1, ("Dialect: %d", dialect
));
412 /* Check wct = 1 error case */
413 if ((pSMBr
->hdr
.WordCount
< 13) || (dialect
== BAD_PROT
)) {
414 /* core returns wct = 1, but we do not ask for core - otherwise
415 small wct just comes when dialect index is -1 indicating we
416 could not negotiate a common dialect */
419 #ifdef CONFIG_CIFS_WEAK_PW_HASH
420 } else if ((pSMBr
->hdr
.WordCount
== 13)
421 && ((dialect
== LANMAN_PROT
)
422 || (dialect
== LANMAN2_PROT
))) {
424 struct lanman_neg_rsp
*rsp
= (struct lanman_neg_rsp
*)pSMBr
;
426 if ((secFlags
& CIFSSEC_MAY_LANMAN
) ||
427 (secFlags
& CIFSSEC_MAY_PLNTXT
))
428 server
->secType
= LANMAN
;
430 cERROR(1, ("mount failed weak security disabled"
431 " in /proc/fs/cifs/SecurityFlags"));
435 server
->secMode
= (__u8
)le16_to_cpu(rsp
->SecurityMode
);
436 server
->maxReq
= le16_to_cpu(rsp
->MaxMpxCount
);
437 server
->maxBuf
= min((__u32
)le16_to_cpu(rsp
->MaxBufSize
),
438 (__u32
)CIFSMaxBufSize
+ MAX_CIFS_HDR_SIZE
);
439 server
->max_vcs
= le16_to_cpu(rsp
->MaxNumberVcs
);
440 GETU32(server
->sessid
) = le32_to_cpu(rsp
->SessionKey
);
441 /* even though we do not use raw we might as well set this
442 accurately, in case we ever find a need for it */
443 if ((le16_to_cpu(rsp
->RawMode
) & RAW_ENABLE
) == RAW_ENABLE
) {
444 server
->max_rw
= 0xFF00;
445 server
->capabilities
= CAP_MPX_MODE
| CAP_RAW_MODE
;
447 server
->max_rw
= 0;/* do not need to use raw anyway */
448 server
->capabilities
= CAP_MPX_MODE
;
450 tmp
= (__s16
)le16_to_cpu(rsp
->ServerTimeZone
);
452 /* OS/2 often does not set timezone therefore
453 * we must use server time to calc time zone.
454 * Could deviate slightly from the right zone.
455 * Smallest defined timezone difference is 15 minutes
456 * (i.e. Nepal). Rounding up/down is done to match
459 int val
, seconds
, remain
, result
;
460 struct timespec ts
, utc
;
462 ts
= cnvrtDosUnixTm(rsp
->SrvTime
.Date
,
463 rsp
->SrvTime
.Time
, 0);
464 cFYI(1, ("SrvTime %d sec since 1970 (utc: %d) diff: %d",
465 (int)ts
.tv_sec
, (int)utc
.tv_sec
,
466 (int)(utc
.tv_sec
- ts
.tv_sec
)));
467 val
= (int)(utc
.tv_sec
- ts
.tv_sec
);
469 result
= (seconds
/ MIN_TZ_ADJ
) * MIN_TZ_ADJ
;
470 remain
= seconds
% MIN_TZ_ADJ
;
471 if (remain
>= (MIN_TZ_ADJ
/ 2))
472 result
+= MIN_TZ_ADJ
;
475 server
->timeAdj
= result
;
477 server
->timeAdj
= (int)tmp
;
478 server
->timeAdj
*= 60; /* also in seconds */
480 cFYI(1, ("server->timeAdj: %d seconds", server
->timeAdj
));
483 /* BB get server time for time conversions and add
484 code to use it and timezone since this is not UTC */
486 if (rsp
->EncryptionKeyLength
==
487 cpu_to_le16(CIFS_CRYPTO_KEY_SIZE
)) {
488 memcpy(server
->cryptKey
, rsp
->EncryptionKey
,
489 CIFS_CRYPTO_KEY_SIZE
);
490 } else if (server
->secMode
& SECMODE_PW_ENCRYPT
) {
491 rc
= -EIO
; /* need cryptkey unless plain text */
495 cFYI(1, ("LANMAN negotiated"));
496 /* we will not end up setting signing flags - as no signing
497 was in LANMAN and server did not return the flags on */
499 #else /* weak security disabled */
500 } else if (pSMBr
->hdr
.WordCount
== 13) {
501 cERROR(1, ("mount failed, cifs module not built "
502 "with CIFS_WEAK_PW_HASH support"));
504 #endif /* WEAK_PW_HASH */
506 } else if (pSMBr
->hdr
.WordCount
!= 17) {
511 /* else wct == 17 NTLM */
512 server
->secMode
= pSMBr
->SecurityMode
;
513 if ((server
->secMode
& SECMODE_USER
) == 0)
514 cFYI(1, ("share mode security"));
516 if ((server
->secMode
& SECMODE_PW_ENCRYPT
) == 0)
517 #ifdef CONFIG_CIFS_WEAK_PW_HASH
518 if ((secFlags
& CIFSSEC_MAY_PLNTXT
) == 0)
519 #endif /* CIFS_WEAK_PW_HASH */
520 cERROR(1, ("Server requests plain text password"
521 " but client support disabled"));
523 if ((secFlags
& CIFSSEC_MUST_NTLMV2
) == CIFSSEC_MUST_NTLMV2
)
524 server
->secType
= NTLMv2
;
525 else if (secFlags
& CIFSSEC_MAY_NTLM
)
526 server
->secType
= NTLM
;
527 else if (secFlags
& CIFSSEC_MAY_NTLMV2
)
528 server
->secType
= NTLMv2
;
529 else if (secFlags
& CIFSSEC_MAY_KRB5
)
530 server
->secType
= Kerberos
;
531 else if (secFlags
& CIFSSEC_MAY_NTLMSSP
)
532 server
->secType
= RawNTLMSSP
;
533 else if (secFlags
& CIFSSEC_MAY_LANMAN
)
534 server
->secType
= LANMAN
;
535 /* #ifdef CONFIG_CIFS_EXPERIMENTAL
536 else if (secFlags & CIFSSEC_MAY_PLNTXT)
541 cERROR(1, ("Invalid security type"));
544 /* else ... any others ...? */
546 /* one byte, so no need to convert this or EncryptionKeyLen from
548 server
->maxReq
= le16_to_cpu(pSMBr
->MaxMpxCount
);
549 /* probably no need to store and check maxvcs */
550 server
->maxBuf
= min(le32_to_cpu(pSMBr
->MaxBufferSize
),
551 (__u32
) CIFSMaxBufSize
+ MAX_CIFS_HDR_SIZE
);
552 server
->max_rw
= le32_to_cpu(pSMBr
->MaxRawSize
);
553 cFYI(DBG2
, ("Max buf = %d", ses
->server
->maxBuf
));
554 GETU32(ses
->server
->sessid
) = le32_to_cpu(pSMBr
->SessionKey
);
555 server
->capabilities
= le32_to_cpu(pSMBr
->Capabilities
);
556 server
->timeAdj
= (int)(__s16
)le16_to_cpu(pSMBr
->ServerTimeZone
);
557 server
->timeAdj
*= 60;
558 if (pSMBr
->EncryptionKeyLength
== CIFS_CRYPTO_KEY_SIZE
) {
559 memcpy(server
->cryptKey
, pSMBr
->u
.EncryptionKey
,
560 CIFS_CRYPTO_KEY_SIZE
);
561 } else if ((pSMBr
->hdr
.Flags2
& SMBFLG2_EXT_SEC
)
562 && (pSMBr
->EncryptionKeyLength
== 0)) {
563 /* decode security blob */
564 } else if (server
->secMode
& SECMODE_PW_ENCRYPT
) {
565 rc
= -EIO
; /* no crypt key only if plain text pwd */
569 /* BB might be helpful to save off the domain of server here */
571 if ((pSMBr
->hdr
.Flags2
& SMBFLG2_EXT_SEC
) &&
572 (server
->capabilities
& CAP_EXTENDED_SECURITY
)) {
573 count
= pSMBr
->ByteCount
;
578 read_lock(&cifs_tcp_ses_lock
);
579 if (server
->srv_count
> 1) {
580 read_unlock(&cifs_tcp_ses_lock
);
581 if (memcmp(server
->server_GUID
,
582 pSMBr
->u
.extended_response
.
584 cFYI(1, ("server UID changed"));
585 memcpy(server
->server_GUID
,
586 pSMBr
->u
.extended_response
.GUID
,
590 read_unlock(&cifs_tcp_ses_lock
);
591 memcpy(server
->server_GUID
,
592 pSMBr
->u
.extended_response
.GUID
, 16);
596 server
->secType
= RawNTLMSSP
;
598 rc
= decode_negTokenInit(pSMBr
->u
.extended_response
.
608 server
->capabilities
&= ~CAP_EXTENDED_SECURITY
;
610 #ifdef CONFIG_CIFS_WEAK_PW_HASH
613 if ((secFlags
& CIFSSEC_MAY_SIGN
) == 0) {
614 /* MUST_SIGN already includes the MAY_SIGN FLAG
615 so if this is zero it means that signing is disabled */
616 cFYI(1, ("Signing disabled"));
617 if (server
->secMode
& SECMODE_SIGN_REQUIRED
) {
618 cERROR(1, ("Server requires "
619 "packet signing to be enabled in "
620 "/proc/fs/cifs/SecurityFlags."));
624 ~(SECMODE_SIGN_ENABLED
| SECMODE_SIGN_REQUIRED
);
625 } else if ((secFlags
& CIFSSEC_MUST_SIGN
) == CIFSSEC_MUST_SIGN
) {
626 /* signing required */
627 cFYI(1, ("Must sign - secFlags 0x%x", secFlags
));
628 if ((server
->secMode
&
629 (SECMODE_SIGN_ENABLED
| SECMODE_SIGN_REQUIRED
)) == 0) {
631 ("signing required but server lacks support"));
634 server
->secMode
|= SECMODE_SIGN_REQUIRED
;
636 /* signing optional ie CIFSSEC_MAY_SIGN */
637 if ((server
->secMode
& SECMODE_SIGN_REQUIRED
) == 0)
639 ~(SECMODE_SIGN_ENABLED
| SECMODE_SIGN_REQUIRED
);
643 cifs_buf_release(pSMB
);
645 cFYI(1, ("negprot rc %d", rc
));
650 CIFSSMBTDis(const int xid
, struct cifsTconInfo
*tcon
)
652 struct smb_hdr
*smb_buffer
;
655 cFYI(1, ("In tree disconnect"));
657 /* BB: do we need to check this? These should never be NULL. */
658 if ((tcon
->ses
== NULL
) || (tcon
->ses
->server
== NULL
))
662 * No need to return error on this operation if tid invalidated and
663 * closed on server already e.g. due to tcp session crashing. Also,
664 * the tcon is no longer on the list, so no need to take lock before
667 if ((tcon
->need_reconnect
) || (tcon
->ses
->need_reconnect
))
670 rc
= small_smb_init(SMB_COM_TREE_DISCONNECT
, 0, tcon
,
671 (void **)&smb_buffer
);
675 rc
= SendReceiveNoRsp(xid
, tcon
->ses
, smb_buffer
, 0);
677 cFYI(1, ("Tree disconnect failed %d", rc
));
679 /* No need to return error on this operation if tid invalidated and
680 closed on server already e.g. due to tcp session crashing */
688 CIFSSMBLogoff(const int xid
, struct cifsSesInfo
*ses
)
690 LOGOFF_ANDX_REQ
*pSMB
;
693 cFYI(1, ("In SMBLogoff for session disconnect"));
696 * BB: do we need to check validity of ses and server? They should
697 * always be valid since we have an active reference. If not, that
698 * should probably be a BUG()
700 if (!ses
|| !ses
->server
)
703 mutex_lock(&ses
->session_mutex
);
704 if (ses
->need_reconnect
)
705 goto session_already_dead
; /* no need to send SMBlogoff if uid
706 already closed due to reconnect */
707 rc
= small_smb_init(SMB_COM_LOGOFF_ANDX
, 2, NULL
, (void **)&pSMB
);
709 mutex_unlock(&ses
->session_mutex
);
713 pSMB
->hdr
.Mid
= GetNextMid(ses
->server
);
715 if (ses
->server
->secMode
&
716 (SECMODE_SIGN_REQUIRED
| SECMODE_SIGN_ENABLED
))
717 pSMB
->hdr
.Flags2
|= SMBFLG2_SECURITY_SIGNATURE
;
719 pSMB
->hdr
.Uid
= ses
->Suid
;
721 pSMB
->AndXCommand
= 0xFF;
722 rc
= SendReceiveNoRsp(xid
, ses
, (struct smb_hdr
*) pSMB
, 0);
723 session_already_dead
:
724 mutex_unlock(&ses
->session_mutex
);
726 /* if session dead then we do not need to do ulogoff,
727 since server closed smb session, no sense reporting
735 CIFSPOSIXDelFile(const int xid
, struct cifsTconInfo
*tcon
, const char *fileName
,
736 __u16 type
, const struct nls_table
*nls_codepage
, int remap
)
738 TRANSACTION2_SPI_REQ
*pSMB
= NULL
;
739 TRANSACTION2_SPI_RSP
*pSMBr
= NULL
;
740 struct unlink_psx_rq
*pRqD
;
743 int bytes_returned
= 0;
744 __u16 params
, param_offset
, offset
, byte_count
;
746 cFYI(1, ("In POSIX delete"));
748 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
753 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
755 cifsConvertToUCS((__le16
*) pSMB
->FileName
, fileName
,
756 PATH_MAX
, nls_codepage
, remap
);
757 name_len
++; /* trailing null */
759 } else { /* BB add path length overrun check */
760 name_len
= strnlen(fileName
, PATH_MAX
);
761 name_len
++; /* trailing null */
762 strncpy(pSMB
->FileName
, fileName
, name_len
);
765 params
= 6 + name_len
;
766 pSMB
->MaxParameterCount
= cpu_to_le16(2);
767 pSMB
->MaxDataCount
= 0; /* BB double check this with jra */
768 pSMB
->MaxSetupCount
= 0;
773 param_offset
= offsetof(struct smb_com_transaction2_spi_req
,
774 InformationLevel
) - 4;
775 offset
= param_offset
+ params
;
777 /* Setup pointer to Request Data (inode type) */
778 pRqD
= (struct unlink_psx_rq
*)(((char *)&pSMB
->hdr
.Protocol
) + offset
);
779 pRqD
->type
= cpu_to_le16(type
);
780 pSMB
->ParameterOffset
= cpu_to_le16(param_offset
);
781 pSMB
->DataOffset
= cpu_to_le16(offset
);
782 pSMB
->SetupCount
= 1;
784 pSMB
->SubCommand
= cpu_to_le16(TRANS2_SET_PATH_INFORMATION
);
785 byte_count
= 3 /* pad */ + params
+ sizeof(struct unlink_psx_rq
);
787 pSMB
->DataCount
= cpu_to_le16(sizeof(struct unlink_psx_rq
));
788 pSMB
->TotalDataCount
= cpu_to_le16(sizeof(struct unlink_psx_rq
));
789 pSMB
->ParameterCount
= cpu_to_le16(params
);
790 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
791 pSMB
->InformationLevel
= cpu_to_le16(SMB_POSIX_UNLINK
);
793 pSMB
->hdr
.smb_buf_length
+= byte_count
;
794 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
795 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
796 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
798 cFYI(1, ("Posix delete returned %d", rc
));
799 cifs_buf_release(pSMB
);
801 cifs_stats_inc(&tcon
->num_deletes
);
810 CIFSSMBDelFile(const int xid
, struct cifsTconInfo
*tcon
, const char *fileName
,
811 const struct nls_table
*nls_codepage
, int remap
)
813 DELETE_FILE_REQ
*pSMB
= NULL
;
814 DELETE_FILE_RSP
*pSMBr
= NULL
;
820 rc
= smb_init(SMB_COM_DELETE
, 1, tcon
, (void **) &pSMB
,
825 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
827 cifsConvertToUCS((__le16
*) pSMB
->fileName
, fileName
,
828 PATH_MAX
, nls_codepage
, remap
);
829 name_len
++; /* trailing null */
831 } else { /* BB improve check for buffer overruns BB */
832 name_len
= strnlen(fileName
, PATH_MAX
);
833 name_len
++; /* trailing null */
834 strncpy(pSMB
->fileName
, fileName
, name_len
);
836 pSMB
->SearchAttributes
=
837 cpu_to_le16(ATTR_READONLY
| ATTR_HIDDEN
| ATTR_SYSTEM
);
838 pSMB
->BufferFormat
= 0x04;
839 pSMB
->hdr
.smb_buf_length
+= name_len
+ 1;
840 pSMB
->ByteCount
= cpu_to_le16(name_len
+ 1);
841 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
842 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
843 cifs_stats_inc(&tcon
->num_deletes
);
845 cFYI(1, ("Error in RMFile = %d", rc
));
847 cifs_buf_release(pSMB
);
855 CIFSSMBRmDir(const int xid
, struct cifsTconInfo
*tcon
, const char *dirName
,
856 const struct nls_table
*nls_codepage
, int remap
)
858 DELETE_DIRECTORY_REQ
*pSMB
= NULL
;
859 DELETE_DIRECTORY_RSP
*pSMBr
= NULL
;
864 cFYI(1, ("In CIFSSMBRmDir"));
866 rc
= smb_init(SMB_COM_DELETE_DIRECTORY
, 0, tcon
, (void **) &pSMB
,
871 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
872 name_len
= cifsConvertToUCS((__le16
*) pSMB
->DirName
, dirName
,
873 PATH_MAX
, nls_codepage
, remap
);
874 name_len
++; /* trailing null */
876 } else { /* BB improve check for buffer overruns BB */
877 name_len
= strnlen(dirName
, PATH_MAX
);
878 name_len
++; /* trailing null */
879 strncpy(pSMB
->DirName
, dirName
, name_len
);
882 pSMB
->BufferFormat
= 0x04;
883 pSMB
->hdr
.smb_buf_length
+= name_len
+ 1;
884 pSMB
->ByteCount
= cpu_to_le16(name_len
+ 1);
885 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
886 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
887 cifs_stats_inc(&tcon
->num_rmdirs
);
889 cFYI(1, ("Error in RMDir = %d", rc
));
891 cifs_buf_release(pSMB
);
898 CIFSSMBMkDir(const int xid
, struct cifsTconInfo
*tcon
,
899 const char *name
, const struct nls_table
*nls_codepage
, int remap
)
902 CREATE_DIRECTORY_REQ
*pSMB
= NULL
;
903 CREATE_DIRECTORY_RSP
*pSMBr
= NULL
;
907 cFYI(1, ("In CIFSSMBMkDir"));
909 rc
= smb_init(SMB_COM_CREATE_DIRECTORY
, 0, tcon
, (void **) &pSMB
,
914 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
915 name_len
= cifsConvertToUCS((__le16
*) pSMB
->DirName
, name
,
916 PATH_MAX
, nls_codepage
, remap
);
917 name_len
++; /* trailing null */
919 } else { /* BB improve check for buffer overruns BB */
920 name_len
= strnlen(name
, PATH_MAX
);
921 name_len
++; /* trailing null */
922 strncpy(pSMB
->DirName
, name
, name_len
);
925 pSMB
->BufferFormat
= 0x04;
926 pSMB
->hdr
.smb_buf_length
+= name_len
+ 1;
927 pSMB
->ByteCount
= cpu_to_le16(name_len
+ 1);
928 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
929 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
930 cifs_stats_inc(&tcon
->num_mkdirs
);
932 cFYI(1, ("Error in Mkdir = %d", rc
));
934 cifs_buf_release(pSMB
);
941 CIFSPOSIXCreate(const int xid
, struct cifsTconInfo
*tcon
, __u32 posix_flags
,
942 __u64 mode
, __u16
*netfid
, FILE_UNIX_BASIC_INFO
*pRetData
,
943 __u32
*pOplock
, const char *name
,
944 const struct nls_table
*nls_codepage
, int remap
)
946 TRANSACTION2_SPI_REQ
*pSMB
= NULL
;
947 TRANSACTION2_SPI_RSP
*pSMBr
= NULL
;
950 int bytes_returned
= 0;
951 __u16 params
, param_offset
, offset
, byte_count
, count
;
953 OPEN_PSX_RSP
*psx_rsp
;
955 cFYI(1, ("In POSIX Create"));
957 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
962 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
964 cifsConvertToUCS((__le16
*) pSMB
->FileName
, name
,
965 PATH_MAX
, nls_codepage
, remap
);
966 name_len
++; /* trailing null */
968 } else { /* BB improve the check for buffer overruns BB */
969 name_len
= strnlen(name
, PATH_MAX
);
970 name_len
++; /* trailing null */
971 strncpy(pSMB
->FileName
, name
, name_len
);
974 params
= 6 + name_len
;
975 count
= sizeof(OPEN_PSX_REQ
);
976 pSMB
->MaxParameterCount
= cpu_to_le16(2);
977 pSMB
->MaxDataCount
= cpu_to_le16(1000); /* large enough */
978 pSMB
->MaxSetupCount
= 0;
983 param_offset
= offsetof(struct smb_com_transaction2_spi_req
,
984 InformationLevel
) - 4;
985 offset
= param_offset
+ params
;
986 pdata
= (OPEN_PSX_REQ
*)(((char *)&pSMB
->hdr
.Protocol
) + offset
);
987 pdata
->Level
= cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC
);
988 pdata
->Permissions
= cpu_to_le64(mode
);
989 pdata
->PosixOpenFlags
= cpu_to_le32(posix_flags
);
990 pdata
->OpenFlags
= cpu_to_le32(*pOplock
);
991 pSMB
->ParameterOffset
= cpu_to_le16(param_offset
);
992 pSMB
->DataOffset
= cpu_to_le16(offset
);
993 pSMB
->SetupCount
= 1;
995 pSMB
->SubCommand
= cpu_to_le16(TRANS2_SET_PATH_INFORMATION
);
996 byte_count
= 3 /* pad */ + params
+ count
;
998 pSMB
->DataCount
= cpu_to_le16(count
);
999 pSMB
->ParameterCount
= cpu_to_le16(params
);
1000 pSMB
->TotalDataCount
= pSMB
->DataCount
;
1001 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
1002 pSMB
->InformationLevel
= cpu_to_le16(SMB_POSIX_OPEN
);
1003 pSMB
->Reserved4
= 0;
1004 pSMB
->hdr
.smb_buf_length
+= byte_count
;
1005 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
1006 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
1007 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
1009 cFYI(1, ("Posix create returned %d", rc
));
1010 goto psx_create_err
;
1013 cFYI(1, ("copying inode info"));
1014 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
1016 if (rc
|| (pSMBr
->ByteCount
< sizeof(OPEN_PSX_RSP
))) {
1017 rc
= -EIO
; /* bad smb */
1018 goto psx_create_err
;
1021 /* copy return information to pRetData */
1022 psx_rsp
= (OPEN_PSX_RSP
*)((char *) &pSMBr
->hdr
.Protocol
1023 + le16_to_cpu(pSMBr
->t2
.DataOffset
));
1025 *pOplock
= le16_to_cpu(psx_rsp
->OplockFlags
);
1027 *netfid
= psx_rsp
->Fid
; /* cifs fid stays in le */
1028 /* Let caller know file was created so we can set the mode. */
1029 /* Do we care about the CreateAction in any other cases? */
1030 if (cpu_to_le32(FILE_CREATE
) == psx_rsp
->CreateAction
)
1031 *pOplock
|= CIFS_CREATE_ACTION
;
1032 /* check to make sure response data is there */
1033 if (psx_rsp
->ReturnedLevel
!= cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC
)) {
1034 pRetData
->Type
= cpu_to_le32(-1); /* unknown */
1035 cFYI(DBG2
, ("unknown type"));
1037 if (pSMBr
->ByteCount
< sizeof(OPEN_PSX_RSP
)
1038 + sizeof(FILE_UNIX_BASIC_INFO
)) {
1039 cERROR(1, ("Open response data too small"));
1040 pRetData
->Type
= cpu_to_le32(-1);
1041 goto psx_create_err
;
1043 memcpy((char *) pRetData
,
1044 (char *)psx_rsp
+ sizeof(OPEN_PSX_RSP
),
1045 sizeof(FILE_UNIX_BASIC_INFO
));
1049 cifs_buf_release(pSMB
);
1051 if (posix_flags
& SMB_O_DIRECTORY
)
1052 cifs_stats_inc(&tcon
->num_posixmkdirs
);
1054 cifs_stats_inc(&tcon
->num_posixopens
);
1062 static __u16
convert_disposition(int disposition
)
1066 switch (disposition
) {
1067 case FILE_SUPERSEDE
:
1068 ofun
= SMBOPEN_OCREATE
| SMBOPEN_OTRUNC
;
1071 ofun
= SMBOPEN_OAPPEND
;
1074 ofun
= SMBOPEN_OCREATE
;
1077 ofun
= SMBOPEN_OCREATE
| SMBOPEN_OAPPEND
;
1079 case FILE_OVERWRITE
:
1080 ofun
= SMBOPEN_OTRUNC
;
1082 case FILE_OVERWRITE_IF
:
1083 ofun
= SMBOPEN_OCREATE
| SMBOPEN_OTRUNC
;
1086 cFYI(1, ("unknown disposition %d", disposition
));
1087 ofun
= SMBOPEN_OAPPEND
; /* regular open */
1093 access_flags_to_smbopen_mode(const int access_flags
)
1095 int masked_flags
= access_flags
& (GENERIC_READ
| GENERIC_WRITE
);
1097 if (masked_flags
== GENERIC_READ
)
1098 return SMBOPEN_READ
;
1099 else if (masked_flags
== GENERIC_WRITE
)
1100 return SMBOPEN_WRITE
;
1102 /* just go for read/write */
1103 return SMBOPEN_READWRITE
;
1107 SMBLegacyOpen(const int xid
, struct cifsTconInfo
*tcon
,
1108 const char *fileName
, const int openDisposition
,
1109 const int access_flags
, const int create_options
, __u16
*netfid
,
1110 int *pOplock
, FILE_ALL_INFO
*pfile_info
,
1111 const struct nls_table
*nls_codepage
, int remap
)
1114 OPENX_REQ
*pSMB
= NULL
;
1115 OPENX_RSP
*pSMBr
= NULL
;
1121 rc
= smb_init(SMB_COM_OPEN_ANDX
, 15, tcon
, (void **) &pSMB
,
1126 pSMB
->AndXCommand
= 0xFF; /* none */
1128 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
1129 count
= 1; /* account for one byte pad to word boundary */
1131 cifsConvertToUCS((__le16
*) (pSMB
->fileName
+ 1),
1132 fileName
, PATH_MAX
, nls_codepage
, remap
);
1133 name_len
++; /* trailing null */
1135 } else { /* BB improve check for buffer overruns BB */
1136 count
= 0; /* no pad */
1137 name_len
= strnlen(fileName
, PATH_MAX
);
1138 name_len
++; /* trailing null */
1139 strncpy(pSMB
->fileName
, fileName
, name_len
);
1141 if (*pOplock
& REQ_OPLOCK
)
1142 pSMB
->OpenFlags
= cpu_to_le16(REQ_OPLOCK
);
1143 else if (*pOplock
& REQ_BATCHOPLOCK
)
1144 pSMB
->OpenFlags
= cpu_to_le16(REQ_BATCHOPLOCK
);
1146 pSMB
->OpenFlags
|= cpu_to_le16(REQ_MORE_INFO
);
1147 pSMB
->Mode
= cpu_to_le16(access_flags_to_smbopen_mode(access_flags
));
1148 pSMB
->Mode
|= cpu_to_le16(0x40); /* deny none */
1149 /* set file as system file if special file such
1150 as fifo and server expecting SFU style and
1151 no Unix extensions */
1153 if (create_options
& CREATE_OPTION_SPECIAL
)
1154 pSMB
->FileAttributes
= cpu_to_le16(ATTR_SYSTEM
);
1155 else /* BB FIXME BB */
1156 pSMB
->FileAttributes
= cpu_to_le16(0/*ATTR_NORMAL*/);
1158 if (create_options
& CREATE_OPTION_READONLY
)
1159 pSMB
->FileAttributes
|= cpu_to_le16(ATTR_READONLY
);
1162 /* pSMB->CreateOptions = cpu_to_le32(create_options &
1163 CREATE_OPTIONS_MASK); */
1164 /* BB FIXME END BB */
1166 pSMB
->Sattr
= cpu_to_le16(ATTR_HIDDEN
| ATTR_SYSTEM
| ATTR_DIRECTORY
);
1167 pSMB
->OpenFunction
= cpu_to_le16(convert_disposition(openDisposition
));
1169 pSMB
->hdr
.smb_buf_length
+= count
;
1171 pSMB
->ByteCount
= cpu_to_le16(count
);
1172 /* long_op set to 1 to allow for oplock break timeouts */
1173 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
1174 (struct smb_hdr
*)pSMBr
, &bytes_returned
, CIFS_LONG_OP
);
1175 cifs_stats_inc(&tcon
->num_opens
);
1177 cFYI(1, ("Error in Open = %d", rc
));
1179 /* BB verify if wct == 15 */
1181 /* *pOplock = pSMBr->OplockLevel; */ /* BB take from action field*/
1183 *netfid
= pSMBr
->Fid
; /* cifs fid stays in le */
1184 /* Let caller know file was created so we can set the mode. */
1185 /* Do we care about the CreateAction in any other cases? */
1187 /* if (cpu_to_le32(FILE_CREATE) == pSMBr->CreateAction)
1188 *pOplock |= CIFS_CREATE_ACTION; */
1192 pfile_info
->CreationTime
= 0; /* BB convert CreateTime*/
1193 pfile_info
->LastAccessTime
= 0; /* BB fixme */
1194 pfile_info
->LastWriteTime
= 0; /* BB fixme */
1195 pfile_info
->ChangeTime
= 0; /* BB fixme */
1196 pfile_info
->Attributes
=
1197 cpu_to_le32(le16_to_cpu(pSMBr
->FileAttributes
));
1198 /* the file_info buf is endian converted by caller */
1199 pfile_info
->AllocationSize
=
1200 cpu_to_le64(le32_to_cpu(pSMBr
->EndOfFile
));
1201 pfile_info
->EndOfFile
= pfile_info
->AllocationSize
;
1202 pfile_info
->NumberOfLinks
= cpu_to_le32(1);
1203 pfile_info
->DeletePending
= 0;
1207 cifs_buf_release(pSMB
);
1214 CIFSSMBOpen(const int xid
, struct cifsTconInfo
*tcon
,
1215 const char *fileName
, const int openDisposition
,
1216 const int access_flags
, const int create_options
, __u16
*netfid
,
1217 int *pOplock
, FILE_ALL_INFO
*pfile_info
,
1218 const struct nls_table
*nls_codepage
, int remap
)
1221 OPEN_REQ
*pSMB
= NULL
;
1222 OPEN_RSP
*pSMBr
= NULL
;
1228 rc
= smb_init(SMB_COM_NT_CREATE_ANDX
, 24, tcon
, (void **) &pSMB
,
1233 pSMB
->AndXCommand
= 0xFF; /* none */
1235 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
1236 count
= 1; /* account for one byte pad to word boundary */
1238 cifsConvertToUCS((__le16
*) (pSMB
->fileName
+ 1),
1239 fileName
, PATH_MAX
, nls_codepage
, remap
);
1240 name_len
++; /* trailing null */
1242 pSMB
->NameLength
= cpu_to_le16(name_len
);
1243 } else { /* BB improve check for buffer overruns BB */
1244 count
= 0; /* no pad */
1245 name_len
= strnlen(fileName
, PATH_MAX
);
1246 name_len
++; /* trailing null */
1247 pSMB
->NameLength
= cpu_to_le16(name_len
);
1248 strncpy(pSMB
->fileName
, fileName
, name_len
);
1250 if (*pOplock
& REQ_OPLOCK
)
1251 pSMB
->OpenFlags
= cpu_to_le32(REQ_OPLOCK
);
1252 else if (*pOplock
& REQ_BATCHOPLOCK
)
1253 pSMB
->OpenFlags
= cpu_to_le32(REQ_BATCHOPLOCK
);
1254 pSMB
->DesiredAccess
= cpu_to_le32(access_flags
);
1255 pSMB
->AllocationSize
= 0;
1256 /* set file as system file if special file such
1257 as fifo and server expecting SFU style and
1258 no Unix extensions */
1259 if (create_options
& CREATE_OPTION_SPECIAL
)
1260 pSMB
->FileAttributes
= cpu_to_le32(ATTR_SYSTEM
);
1262 pSMB
->FileAttributes
= cpu_to_le32(ATTR_NORMAL
);
1264 /* XP does not handle ATTR_POSIX_SEMANTICS */
1265 /* but it helps speed up case sensitive checks for other
1266 servers such as Samba */
1267 if (tcon
->ses
->capabilities
& CAP_UNIX
)
1268 pSMB
->FileAttributes
|= cpu_to_le32(ATTR_POSIX_SEMANTICS
);
1270 if (create_options
& CREATE_OPTION_READONLY
)
1271 pSMB
->FileAttributes
|= cpu_to_le32(ATTR_READONLY
);
1273 pSMB
->ShareAccess
= cpu_to_le32(FILE_SHARE_ALL
);
1274 pSMB
->CreateDisposition
= cpu_to_le32(openDisposition
);
1275 pSMB
->CreateOptions
= cpu_to_le32(create_options
& CREATE_OPTIONS_MASK
);
1276 /* BB Expirement with various impersonation levels and verify */
1277 pSMB
->ImpersonationLevel
= cpu_to_le32(SECURITY_IMPERSONATION
);
1278 pSMB
->SecurityFlags
=
1279 SECURITY_CONTEXT_TRACKING
| SECURITY_EFFECTIVE_ONLY
;
1282 pSMB
->hdr
.smb_buf_length
+= count
;
1284 pSMB
->ByteCount
= cpu_to_le16(count
);
1285 /* long_op set to 1 to allow for oplock break timeouts */
1286 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
1287 (struct smb_hdr
*)pSMBr
, &bytes_returned
, CIFS_LONG_OP
);
1288 cifs_stats_inc(&tcon
->num_opens
);
1290 cFYI(1, ("Error in Open = %d", rc
));
1292 *pOplock
= pSMBr
->OplockLevel
; /* 1 byte no need to le_to_cpu */
1293 *netfid
= pSMBr
->Fid
; /* cifs fid stays in le */
1294 /* Let caller know file was created so we can set the mode. */
1295 /* Do we care about the CreateAction in any other cases? */
1296 if (cpu_to_le32(FILE_CREATE
) == pSMBr
->CreateAction
)
1297 *pOplock
|= CIFS_CREATE_ACTION
;
1299 memcpy((char *)pfile_info
, (char *)&pSMBr
->CreationTime
,
1300 36 /* CreationTime to Attributes */);
1301 /* the file_info buf is endian converted by caller */
1302 pfile_info
->AllocationSize
= pSMBr
->AllocationSize
;
1303 pfile_info
->EndOfFile
= pSMBr
->EndOfFile
;
1304 pfile_info
->NumberOfLinks
= cpu_to_le32(1);
1305 pfile_info
->DeletePending
= 0;
1309 cifs_buf_release(pSMB
);
1316 CIFSSMBRead(const int xid
, struct cifsTconInfo
*tcon
, const int netfid
,
1317 const unsigned int count
, const __u64 lseek
, unsigned int *nbytes
,
1318 char **buf
, int *pbuf_type
)
1321 READ_REQ
*pSMB
= NULL
;
1322 READ_RSP
*pSMBr
= NULL
;
1323 char *pReadData
= NULL
;
1325 int resp_buf_type
= 0;
1328 cFYI(1, ("Reading %d bytes on fid %d", count
, netfid
));
1329 if (tcon
->ses
->capabilities
& CAP_LARGE_FILES
)
1332 wct
= 10; /* old style read */
1333 if ((lseek
>> 32) > 0) {
1334 /* can not handle this big offset for old */
1340 rc
= small_smb_init(SMB_COM_READ_ANDX
, wct
, tcon
, (void **) &pSMB
);
1344 /* tcon and ses pointer are checked in smb_init */
1345 if (tcon
->ses
->server
== NULL
)
1346 return -ECONNABORTED
;
1348 pSMB
->AndXCommand
= 0xFF; /* none */
1350 pSMB
->OffsetLow
= cpu_to_le32(lseek
& 0xFFFFFFFF);
1352 pSMB
->OffsetHigh
= cpu_to_le32(lseek
>> 32);
1354 pSMB
->Remaining
= 0;
1355 pSMB
->MaxCount
= cpu_to_le16(count
& 0xFFFF);
1356 pSMB
->MaxCountHigh
= cpu_to_le32(count
>> 16);
1358 pSMB
->ByteCount
= 0; /* no need to do le conversion since 0 */
1360 /* old style read */
1361 struct smb_com_readx_req
*pSMBW
=
1362 (struct smb_com_readx_req
*)pSMB
;
1363 pSMBW
->ByteCount
= 0;
1366 iov
[0].iov_base
= (char *)pSMB
;
1367 iov
[0].iov_len
= pSMB
->hdr
.smb_buf_length
+ 4;
1368 rc
= SendReceive2(xid
, tcon
->ses
, iov
, 1 /* num iovecs */,
1369 &resp_buf_type
, CIFS_STD_OP
| CIFS_LOG_ERROR
);
1370 cifs_stats_inc(&tcon
->num_reads
);
1371 pSMBr
= (READ_RSP
*)iov
[0].iov_base
;
1373 cERROR(1, ("Send error in read = %d", rc
));
1375 int data_length
= le16_to_cpu(pSMBr
->DataLengthHigh
);
1376 data_length
= data_length
<< 16;
1377 data_length
+= le16_to_cpu(pSMBr
->DataLength
);
1378 *nbytes
= data_length
;
1380 /*check that DataLength would not go beyond end of SMB */
1381 if ((data_length
> CIFSMaxBufSize
)
1382 || (data_length
> count
)) {
1383 cFYI(1, ("bad length %d for count %d",
1384 data_length
, count
));
1388 pReadData
= (char *) (&pSMBr
->hdr
.Protocol
) +
1389 le16_to_cpu(pSMBr
->DataOffset
);
1390 /* if (rc = copy_to_user(buf, pReadData, data_length)) {
1391 cERROR(1,("Faulting on read rc = %d",rc));
1393 }*/ /* can not use copy_to_user when using page cache*/
1395 memcpy(*buf
, pReadData
, data_length
);
1399 /* cifs_small_buf_release(pSMB); */ /* Freed earlier now in SendReceive2 */
1401 if (resp_buf_type
== CIFS_SMALL_BUFFER
)
1402 cifs_small_buf_release(iov
[0].iov_base
);
1403 else if (resp_buf_type
== CIFS_LARGE_BUFFER
)
1404 cifs_buf_release(iov
[0].iov_base
);
1405 } else if (resp_buf_type
!= CIFS_NO_BUFFER
) {
1406 /* return buffer to caller to free */
1407 *buf
= iov
[0].iov_base
;
1408 if (resp_buf_type
== CIFS_SMALL_BUFFER
)
1409 *pbuf_type
= CIFS_SMALL_BUFFER
;
1410 else if (resp_buf_type
== CIFS_LARGE_BUFFER
)
1411 *pbuf_type
= CIFS_LARGE_BUFFER
;
1412 } /* else no valid buffer on return - leave as null */
1414 /* Note: On -EAGAIN error only caller can retry on handle based calls
1415 since file handle passed in no longer valid */
1421 CIFSSMBWrite(const int xid
, struct cifsTconInfo
*tcon
,
1422 const int netfid
, const unsigned int count
,
1423 const __u64 offset
, unsigned int *nbytes
, const char *buf
,
1424 const char __user
*ubuf
, const int long_op
)
1427 WRITE_REQ
*pSMB
= NULL
;
1428 WRITE_RSP
*pSMBr
= NULL
;
1429 int bytes_returned
, wct
;
1433 /* cFYI(1, ("write at %lld %d bytes", offset, count));*/
1434 if (tcon
->ses
== NULL
)
1435 return -ECONNABORTED
;
1437 if (tcon
->ses
->capabilities
& CAP_LARGE_FILES
)
1441 if ((offset
>> 32) > 0) {
1442 /* can not handle big offset for old srv */
1447 rc
= smb_init(SMB_COM_WRITE_ANDX
, wct
, tcon
, (void **) &pSMB
,
1451 /* tcon and ses pointer are checked in smb_init */
1452 if (tcon
->ses
->server
== NULL
)
1453 return -ECONNABORTED
;
1455 pSMB
->AndXCommand
= 0xFF; /* none */
1457 pSMB
->OffsetLow
= cpu_to_le32(offset
& 0xFFFFFFFF);
1459 pSMB
->OffsetHigh
= cpu_to_le32(offset
>> 32);
1461 pSMB
->Reserved
= 0xFFFFFFFF;
1462 pSMB
->WriteMode
= 0;
1463 pSMB
->Remaining
= 0;
1465 /* Can increase buffer size if buffer is big enough in some cases ie we
1466 can send more if LARGE_WRITE_X capability returned by the server and if
1467 our buffer is big enough or if we convert to iovecs on socket writes
1468 and eliminate the copy to the CIFS buffer */
1469 if (tcon
->ses
->capabilities
& CAP_LARGE_WRITE_X
) {
1470 bytes_sent
= min_t(const unsigned int, CIFSMaxBufSize
, count
);
1472 bytes_sent
= (tcon
->ses
->server
->maxBuf
- MAX_CIFS_HDR_SIZE
)
1476 if (bytes_sent
> count
)
1479 cpu_to_le16(offsetof(struct smb_com_write_req
, Data
) - 4);
1481 memcpy(pSMB
->Data
, buf
, bytes_sent
);
1483 if (copy_from_user(pSMB
->Data
, ubuf
, bytes_sent
)) {
1484 cifs_buf_release(pSMB
);
1487 } else if (count
!= 0) {
1489 cifs_buf_release(pSMB
);
1491 } /* else setting file size with write of zero bytes */
1493 byte_count
= bytes_sent
+ 1; /* pad */
1494 else /* wct == 12 */
1495 byte_count
= bytes_sent
+ 5; /* bigger pad, smaller smb hdr */
1497 pSMB
->DataLengthLow
= cpu_to_le16(bytes_sent
& 0xFFFF);
1498 pSMB
->DataLengthHigh
= cpu_to_le16(bytes_sent
>> 16);
1499 pSMB
->hdr
.smb_buf_length
+= byte_count
;
1502 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
1503 else { /* old style write has byte count 4 bytes earlier
1505 struct smb_com_writex_req
*pSMBW
=
1506 (struct smb_com_writex_req
*)pSMB
;
1507 pSMBW
->ByteCount
= cpu_to_le16(byte_count
);
1510 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
1511 (struct smb_hdr
*) pSMBr
, &bytes_returned
, long_op
);
1512 cifs_stats_inc(&tcon
->num_writes
);
1514 cFYI(1, ("Send error in write = %d", rc
));
1517 *nbytes
= le16_to_cpu(pSMBr
->CountHigh
);
1518 *nbytes
= (*nbytes
) << 16;
1519 *nbytes
+= le16_to_cpu(pSMBr
->Count
);
1522 cifs_buf_release(pSMB
);
1524 /* Note: On -EAGAIN error only caller can retry on handle based calls
1525 since file handle passed in no longer valid */
1531 CIFSSMBWrite2(const int xid
, struct cifsTconInfo
*tcon
,
1532 const int netfid
, const unsigned int count
,
1533 const __u64 offset
, unsigned int *nbytes
, struct kvec
*iov
,
1534 int n_vec
, const int long_op
)
1537 WRITE_REQ
*pSMB
= NULL
;
1540 int resp_buf_type
= 0;
1544 cFYI(1, ("write2 at %lld %d bytes", (long long)offset
, count
));
1546 if (tcon
->ses
->capabilities
& CAP_LARGE_FILES
) {
1550 if ((offset
>> 32) > 0) {
1551 /* can not handle big offset for old srv */
1555 rc
= small_smb_init(SMB_COM_WRITE_ANDX
, wct
, tcon
, (void **) &pSMB
);
1558 /* tcon and ses pointer are checked in smb_init */
1559 if (tcon
->ses
->server
== NULL
)
1560 return -ECONNABORTED
;
1562 pSMB
->AndXCommand
= 0xFF; /* none */
1564 pSMB
->OffsetLow
= cpu_to_le32(offset
& 0xFFFFFFFF);
1566 pSMB
->OffsetHigh
= cpu_to_le32(offset
>> 32);
1567 pSMB
->Reserved
= 0xFFFFFFFF;
1568 pSMB
->WriteMode
= 0;
1569 pSMB
->Remaining
= 0;
1572 cpu_to_le16(offsetof(struct smb_com_write_req
, Data
) - 4);
1574 pSMB
->DataLengthLow
= cpu_to_le16(count
& 0xFFFF);
1575 pSMB
->DataLengthHigh
= cpu_to_le16(count
>> 16);
1576 smb_hdr_len
= pSMB
->hdr
.smb_buf_length
+ 1; /* hdr + 1 byte pad */
1578 pSMB
->hdr
.smb_buf_length
+= count
+1;
1579 else /* wct == 12 */
1580 pSMB
->hdr
.smb_buf_length
+= count
+5; /* smb data starts later */
1582 pSMB
->ByteCount
= cpu_to_le16(count
+ 1);
1583 else /* wct == 12 */ /* bigger pad, smaller smb hdr, keep offset ok */ {
1584 struct smb_com_writex_req
*pSMBW
=
1585 (struct smb_com_writex_req
*)pSMB
;
1586 pSMBW
->ByteCount
= cpu_to_le16(count
+ 5);
1588 iov
[0].iov_base
= pSMB
;
1590 iov
[0].iov_len
= smb_hdr_len
+ 4;
1591 else /* wct == 12 pad bigger by four bytes */
1592 iov
[0].iov_len
= smb_hdr_len
+ 8;
1595 rc
= SendReceive2(xid
, tcon
->ses
, iov
, n_vec
+ 1, &resp_buf_type
,
1597 cifs_stats_inc(&tcon
->num_writes
);
1599 cFYI(1, ("Send error Write2 = %d", rc
));
1600 } else if (resp_buf_type
== 0) {
1601 /* presumably this can not happen, but best to be safe */
1604 WRITE_RSP
*pSMBr
= (WRITE_RSP
*)iov
[0].iov_base
;
1605 *nbytes
= le16_to_cpu(pSMBr
->CountHigh
);
1606 *nbytes
= (*nbytes
) << 16;
1607 *nbytes
+= le16_to_cpu(pSMBr
->Count
);
1610 /* cifs_small_buf_release(pSMB); */ /* Freed earlier now in SendReceive2 */
1611 if (resp_buf_type
== CIFS_SMALL_BUFFER
)
1612 cifs_small_buf_release(iov
[0].iov_base
);
1613 else if (resp_buf_type
== CIFS_LARGE_BUFFER
)
1614 cifs_buf_release(iov
[0].iov_base
);
1616 /* Note: On -EAGAIN error only caller can retry on handle based calls
1617 since file handle passed in no longer valid */
1624 CIFSSMBLock(const int xid
, struct cifsTconInfo
*tcon
,
1625 const __u16 smb_file_id
, const __u64 len
,
1626 const __u64 offset
, const __u32 numUnlock
,
1627 const __u32 numLock
, const __u8 lockType
, const bool waitFlag
)
1630 LOCK_REQ
*pSMB
= NULL
;
1631 /* LOCK_RSP *pSMBr = NULL; */ /* No response data other than rc to parse */
1636 cFYI(1, ("CIFSSMBLock timeout %d numLock %d", (int)waitFlag
, numLock
));
1637 rc
= small_smb_init(SMB_COM_LOCKING_ANDX
, 8, tcon
, (void **) &pSMB
);
1642 if (lockType
== LOCKING_ANDX_OPLOCK_RELEASE
) {
1643 timeout
= CIFS_ASYNC_OP
; /* no response expected */
1645 } else if (waitFlag
) {
1646 timeout
= CIFS_BLOCKING_OP
; /* blocking operation, no timeout */
1647 pSMB
->Timeout
= cpu_to_le32(-1);/* blocking - do not time out */
1652 pSMB
->NumberOfLocks
= cpu_to_le16(numLock
);
1653 pSMB
->NumberOfUnlocks
= cpu_to_le16(numUnlock
);
1654 pSMB
->LockType
= lockType
;
1655 pSMB
->AndXCommand
= 0xFF; /* none */
1656 pSMB
->Fid
= smb_file_id
; /* netfid stays le */
1658 if ((numLock
!= 0) || (numUnlock
!= 0)) {
1659 pSMB
->Locks
[0].Pid
= cpu_to_le16(current
->tgid
);
1660 /* BB where to store pid high? */
1661 pSMB
->Locks
[0].LengthLow
= cpu_to_le32((u32
)len
);
1662 pSMB
->Locks
[0].LengthHigh
= cpu_to_le32((u32
)(len
>>32));
1663 pSMB
->Locks
[0].OffsetLow
= cpu_to_le32((u32
)offset
);
1664 pSMB
->Locks
[0].OffsetHigh
= cpu_to_le32((u32
)(offset
>>32));
1665 count
= sizeof(LOCKING_ANDX_RANGE
);
1670 pSMB
->hdr
.smb_buf_length
+= count
;
1671 pSMB
->ByteCount
= cpu_to_le16(count
);
1674 rc
= SendReceiveBlockingLock(xid
, tcon
, (struct smb_hdr
*) pSMB
,
1675 (struct smb_hdr
*) pSMB
, &bytes_returned
);
1676 cifs_small_buf_release(pSMB
);
1678 rc
= SendReceiveNoRsp(xid
, tcon
->ses
, (struct smb_hdr
*)pSMB
,
1680 /* SMB buffer freed by function above */
1682 cifs_stats_inc(&tcon
->num_locks
);
1684 cFYI(1, ("Send error in Lock = %d", rc
));
1686 /* Note: On -EAGAIN error only caller can retry on handle based calls
1687 since file handle passed in no longer valid */
1692 CIFSSMBPosixLock(const int xid
, struct cifsTconInfo
*tcon
,
1693 const __u16 smb_file_id
, const int get_flag
, const __u64 len
,
1694 struct file_lock
*pLockData
, const __u16 lock_type
,
1695 const bool waitFlag
)
1697 struct smb_com_transaction2_sfi_req
*pSMB
= NULL
;
1698 struct smb_com_transaction2_sfi_rsp
*pSMBr
= NULL
;
1699 struct cifs_posix_lock
*parm_data
;
1702 int bytes_returned
= 0;
1703 int resp_buf_type
= 0;
1704 __u16 params
, param_offset
, offset
, byte_count
, count
;
1707 cFYI(1, ("Posix Lock"));
1709 if (pLockData
== NULL
)
1712 rc
= small_smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
);
1717 pSMBr
= (struct smb_com_transaction2_sfi_rsp
*)pSMB
;
1720 pSMB
->MaxSetupCount
= 0;
1723 pSMB
->Reserved2
= 0;
1724 param_offset
= offsetof(struct smb_com_transaction2_sfi_req
, Fid
) - 4;
1725 offset
= param_offset
+ params
;
1727 count
= sizeof(struct cifs_posix_lock
);
1728 pSMB
->MaxParameterCount
= cpu_to_le16(2);
1729 pSMB
->MaxDataCount
= cpu_to_le16(1000); /* BB find max SMB from sess */
1730 pSMB
->SetupCount
= 1;
1731 pSMB
->Reserved3
= 0;
1733 pSMB
->SubCommand
= cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION
);
1735 pSMB
->SubCommand
= cpu_to_le16(TRANS2_SET_FILE_INFORMATION
);
1736 byte_count
= 3 /* pad */ + params
+ count
;
1737 pSMB
->DataCount
= cpu_to_le16(count
);
1738 pSMB
->ParameterCount
= cpu_to_le16(params
);
1739 pSMB
->TotalDataCount
= pSMB
->DataCount
;
1740 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
1741 pSMB
->ParameterOffset
= cpu_to_le16(param_offset
);
1742 parm_data
= (struct cifs_posix_lock
*)
1743 (((char *) &pSMB
->hdr
.Protocol
) + offset
);
1745 parm_data
->lock_type
= cpu_to_le16(lock_type
);
1747 timeout
= CIFS_BLOCKING_OP
; /* blocking operation, no timeout */
1748 parm_data
->lock_flags
= cpu_to_le16(1);
1749 pSMB
->Timeout
= cpu_to_le32(-1);
1753 parm_data
->pid
= cpu_to_le32(current
->tgid
);
1754 parm_data
->start
= cpu_to_le64(pLockData
->fl_start
);
1755 parm_data
->length
= cpu_to_le64(len
); /* normalize negative numbers */
1757 pSMB
->DataOffset
= cpu_to_le16(offset
);
1758 pSMB
->Fid
= smb_file_id
;
1759 pSMB
->InformationLevel
= cpu_to_le16(SMB_SET_POSIX_LOCK
);
1760 pSMB
->Reserved4
= 0;
1761 pSMB
->hdr
.smb_buf_length
+= byte_count
;
1762 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
1764 rc
= SendReceiveBlockingLock(xid
, tcon
, (struct smb_hdr
*) pSMB
,
1765 (struct smb_hdr
*) pSMBr
, &bytes_returned
);
1767 iov
[0].iov_base
= (char *)pSMB
;
1768 iov
[0].iov_len
= pSMB
->hdr
.smb_buf_length
+ 4;
1769 rc
= SendReceive2(xid
, tcon
->ses
, iov
, 1 /* num iovecs */,
1770 &resp_buf_type
, timeout
);
1771 pSMB
= NULL
; /* request buf already freed by SendReceive2. Do
1772 not try to free it twice below on exit */
1773 pSMBr
= (struct smb_com_transaction2_sfi_rsp
*)iov
[0].iov_base
;
1777 cFYI(1, ("Send error in Posix Lock = %d", rc
));
1778 } else if (get_flag
) {
1779 /* lock structure can be returned on get */
1782 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
1784 if (rc
|| (pSMBr
->ByteCount
< sizeof(struct cifs_posix_lock
))) {
1785 rc
= -EIO
; /* bad smb */
1788 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
1789 data_count
= le16_to_cpu(pSMBr
->t2
.DataCount
);
1790 if (data_count
< sizeof(struct cifs_posix_lock
)) {
1794 parm_data
= (struct cifs_posix_lock
*)
1795 ((char *)&pSMBr
->hdr
.Protocol
+ data_offset
);
1796 if (parm_data
->lock_type
== cpu_to_le16(CIFS_UNLCK
))
1797 pLockData
->fl_type
= F_UNLCK
;
1802 cifs_small_buf_release(pSMB
);
1804 if (resp_buf_type
== CIFS_SMALL_BUFFER
)
1805 cifs_small_buf_release(iov
[0].iov_base
);
1806 else if (resp_buf_type
== CIFS_LARGE_BUFFER
)
1807 cifs_buf_release(iov
[0].iov_base
);
1809 /* Note: On -EAGAIN error only caller can retry on handle based calls
1810 since file handle passed in no longer valid */
1817 CIFSSMBClose(const int xid
, struct cifsTconInfo
*tcon
, int smb_file_id
)
1820 CLOSE_REQ
*pSMB
= NULL
;
1821 cFYI(1, ("In CIFSSMBClose"));
1823 /* do not retry on dead session on close */
1824 rc
= small_smb_init(SMB_COM_CLOSE
, 3, tcon
, (void **) &pSMB
);
1830 pSMB
->FileID
= (__u16
) smb_file_id
;
1831 pSMB
->LastWriteTime
= 0xFFFFFFFF;
1832 pSMB
->ByteCount
= 0;
1833 rc
= SendReceiveNoRsp(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
, 0);
1834 cifs_stats_inc(&tcon
->num_closes
);
1837 /* EINTR is expected when user ctl-c to kill app */
1838 cERROR(1, ("Send error in Close = %d", rc
));
1842 /* Since session is dead, file will be closed on server already */
1850 CIFSSMBFlush(const int xid
, struct cifsTconInfo
*tcon
, int smb_file_id
)
1853 FLUSH_REQ
*pSMB
= NULL
;
1854 cFYI(1, ("In CIFSSMBFlush"));
1856 rc
= small_smb_init(SMB_COM_FLUSH
, 1, tcon
, (void **) &pSMB
);
1860 pSMB
->FileID
= (__u16
) smb_file_id
;
1861 pSMB
->ByteCount
= 0;
1862 rc
= SendReceiveNoRsp(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
, 0);
1863 cifs_stats_inc(&tcon
->num_flushes
);
1865 cERROR(1, ("Send error in Flush = %d", rc
));
1871 CIFSSMBRename(const int xid
, struct cifsTconInfo
*tcon
,
1872 const char *fromName
, const char *toName
,
1873 const struct nls_table
*nls_codepage
, int remap
)
1876 RENAME_REQ
*pSMB
= NULL
;
1877 RENAME_RSP
*pSMBr
= NULL
;
1879 int name_len
, name_len2
;
1882 cFYI(1, ("In CIFSSMBRename"));
1884 rc
= smb_init(SMB_COM_RENAME
, 1, tcon
, (void **) &pSMB
,
1889 pSMB
->BufferFormat
= 0x04;
1890 pSMB
->SearchAttributes
=
1891 cpu_to_le16(ATTR_READONLY
| ATTR_HIDDEN
| ATTR_SYSTEM
|
1894 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
1896 cifsConvertToUCS((__le16
*) pSMB
->OldFileName
, fromName
,
1897 PATH_MAX
, nls_codepage
, remap
);
1898 name_len
++; /* trailing null */
1900 pSMB
->OldFileName
[name_len
] = 0x04; /* pad */
1901 /* protocol requires ASCII signature byte on Unicode string */
1902 pSMB
->OldFileName
[name_len
+ 1] = 0x00;
1904 cifsConvertToUCS((__le16
*)&pSMB
->OldFileName
[name_len
+ 2],
1905 toName
, PATH_MAX
, nls_codepage
, remap
);
1906 name_len2
+= 1 /* trailing null */ + 1 /* Signature word */ ;
1907 name_len2
*= 2; /* convert to bytes */
1908 } else { /* BB improve the check for buffer overruns BB */
1909 name_len
= strnlen(fromName
, PATH_MAX
);
1910 name_len
++; /* trailing null */
1911 strncpy(pSMB
->OldFileName
, fromName
, name_len
);
1912 name_len2
= strnlen(toName
, PATH_MAX
);
1913 name_len2
++; /* trailing null */
1914 pSMB
->OldFileName
[name_len
] = 0x04; /* 2nd buffer format */
1915 strncpy(&pSMB
->OldFileName
[name_len
+ 1], toName
, name_len2
);
1916 name_len2
++; /* trailing null */
1917 name_len2
++; /* signature byte */
1920 count
= 1 /* 1st signature byte */ + name_len
+ name_len2
;
1921 pSMB
->hdr
.smb_buf_length
+= count
;
1922 pSMB
->ByteCount
= cpu_to_le16(count
);
1924 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
1925 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
1926 cifs_stats_inc(&tcon
->num_renames
);
1928 cFYI(1, ("Send error in rename = %d", rc
));
1930 cifs_buf_release(pSMB
);
1938 int CIFSSMBRenameOpenFile(const int xid
, struct cifsTconInfo
*pTcon
,
1939 int netfid
, const char *target_name
,
1940 const struct nls_table
*nls_codepage
, int remap
)
1942 struct smb_com_transaction2_sfi_req
*pSMB
= NULL
;
1943 struct smb_com_transaction2_sfi_rsp
*pSMBr
= NULL
;
1944 struct set_file_rename
*rename_info
;
1946 char dummy_string
[30];
1948 int bytes_returned
= 0;
1950 __u16 params
, param_offset
, offset
, count
, byte_count
;
1952 cFYI(1, ("Rename to File by handle"));
1953 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, pTcon
, (void **) &pSMB
,
1959 pSMB
->MaxSetupCount
= 0;
1963 pSMB
->Reserved2
= 0;
1964 param_offset
= offsetof(struct smb_com_transaction2_sfi_req
, Fid
) - 4;
1965 offset
= param_offset
+ params
;
1967 data_offset
= (char *) (&pSMB
->hdr
.Protocol
) + offset
;
1968 rename_info
= (struct set_file_rename
*) data_offset
;
1969 pSMB
->MaxParameterCount
= cpu_to_le16(2);
1970 pSMB
->MaxDataCount
= cpu_to_le16(1000); /* BB find max SMB from sess */
1971 pSMB
->SetupCount
= 1;
1972 pSMB
->Reserved3
= 0;
1973 pSMB
->SubCommand
= cpu_to_le16(TRANS2_SET_FILE_INFORMATION
);
1974 byte_count
= 3 /* pad */ + params
;
1975 pSMB
->ParameterCount
= cpu_to_le16(params
);
1976 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
1977 pSMB
->ParameterOffset
= cpu_to_le16(param_offset
);
1978 pSMB
->DataOffset
= cpu_to_le16(offset
);
1979 /* construct random name ".cifs_tmp<inodenum><mid>" */
1980 rename_info
->overwrite
= cpu_to_le32(1);
1981 rename_info
->root_fid
= 0;
1982 /* unicode only call */
1983 if (target_name
== NULL
) {
1984 sprintf(dummy_string
, "cifs%x", pSMB
->hdr
.Mid
);
1985 len_of_str
= cifsConvertToUCS((__le16
*)rename_info
->target_name
,
1986 dummy_string
, 24, nls_codepage
, remap
);
1988 len_of_str
= cifsConvertToUCS((__le16
*)rename_info
->target_name
,
1989 target_name
, PATH_MAX
, nls_codepage
,
1992 rename_info
->target_name_len
= cpu_to_le32(2 * len_of_str
);
1993 count
= 12 /* sizeof(struct set_file_rename) */ + (2 * len_of_str
);
1994 byte_count
+= count
;
1995 pSMB
->DataCount
= cpu_to_le16(count
);
1996 pSMB
->TotalDataCount
= pSMB
->DataCount
;
1998 pSMB
->InformationLevel
=
1999 cpu_to_le16(SMB_SET_FILE_RENAME_INFORMATION
);
2000 pSMB
->Reserved4
= 0;
2001 pSMB
->hdr
.smb_buf_length
+= byte_count
;
2002 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
2003 rc
= SendReceive(xid
, pTcon
->ses
, (struct smb_hdr
*) pSMB
,
2004 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
2005 cifs_stats_inc(&pTcon
->num_t2renames
);
2007 cFYI(1, ("Send error in Rename (by file handle) = %d", rc
));
2009 cifs_buf_release(pSMB
);
2011 /* Note: On -EAGAIN error only caller can retry on handle based calls
2012 since file handle passed in no longer valid */
2018 CIFSSMBCopy(const int xid
, struct cifsTconInfo
*tcon
, const char *fromName
,
2019 const __u16 target_tid
, const char *toName
, const int flags
,
2020 const struct nls_table
*nls_codepage
, int remap
)
2023 COPY_REQ
*pSMB
= NULL
;
2024 COPY_RSP
*pSMBr
= NULL
;
2026 int name_len
, name_len2
;
2029 cFYI(1, ("In CIFSSMBCopy"));
2031 rc
= smb_init(SMB_COM_COPY
, 1, tcon
, (void **) &pSMB
,
2036 pSMB
->BufferFormat
= 0x04;
2037 pSMB
->Tid2
= target_tid
;
2039 pSMB
->Flags
= cpu_to_le16(flags
& COPY_TREE
);
2041 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
2042 name_len
= cifsConvertToUCS((__le16
*) pSMB
->OldFileName
,
2043 fromName
, PATH_MAX
, nls_codepage
,
2045 name_len
++; /* trailing null */
2047 pSMB
->OldFileName
[name_len
] = 0x04; /* pad */
2048 /* protocol requires ASCII signature byte on Unicode string */
2049 pSMB
->OldFileName
[name_len
+ 1] = 0x00;
2051 cifsConvertToUCS((__le16
*)&pSMB
->OldFileName
[name_len
+ 2],
2052 toName
, PATH_MAX
, nls_codepage
, remap
);
2053 name_len2
+= 1 /* trailing null */ + 1 /* Signature word */ ;
2054 name_len2
*= 2; /* convert to bytes */
2055 } else { /* BB improve the check for buffer overruns BB */
2056 name_len
= strnlen(fromName
, PATH_MAX
);
2057 name_len
++; /* trailing null */
2058 strncpy(pSMB
->OldFileName
, fromName
, name_len
);
2059 name_len2
= strnlen(toName
, PATH_MAX
);
2060 name_len2
++; /* trailing null */
2061 pSMB
->OldFileName
[name_len
] = 0x04; /* 2nd buffer format */
2062 strncpy(&pSMB
->OldFileName
[name_len
+ 1], toName
, name_len2
);
2063 name_len2
++; /* trailing null */
2064 name_len2
++; /* signature byte */
2067 count
= 1 /* 1st signature byte */ + name_len
+ name_len2
;
2068 pSMB
->hdr
.smb_buf_length
+= count
;
2069 pSMB
->ByteCount
= cpu_to_le16(count
);
2071 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
2072 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
2074 cFYI(1, ("Send error in copy = %d with %d files copied",
2075 rc
, le16_to_cpu(pSMBr
->CopyCount
)));
2077 cifs_buf_release(pSMB
);
2086 CIFSUnixCreateSymLink(const int xid
, struct cifsTconInfo
*tcon
,
2087 const char *fromName
, const char *toName
,
2088 const struct nls_table
*nls_codepage
)
2090 TRANSACTION2_SPI_REQ
*pSMB
= NULL
;
2091 TRANSACTION2_SPI_RSP
*pSMBr
= NULL
;
2094 int name_len_target
;
2096 int bytes_returned
= 0;
2097 __u16 params
, param_offset
, offset
, byte_count
;
2099 cFYI(1, ("In Symlink Unix style"));
2101 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
2106 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
2108 cifs_strtoUCS((__le16
*) pSMB
->FileName
, fromName
, PATH_MAX
2109 /* find define for this maxpathcomponent */
2111 name_len
++; /* trailing null */
2114 } else { /* BB improve the check for buffer overruns BB */
2115 name_len
= strnlen(fromName
, PATH_MAX
);
2116 name_len
++; /* trailing null */
2117 strncpy(pSMB
->FileName
, fromName
, name_len
);
2119 params
= 6 + name_len
;
2120 pSMB
->MaxSetupCount
= 0;
2124 pSMB
->Reserved2
= 0;
2125 param_offset
= offsetof(struct smb_com_transaction2_spi_req
,
2126 InformationLevel
) - 4;
2127 offset
= param_offset
+ params
;
2129 data_offset
= (char *) (&pSMB
->hdr
.Protocol
) + offset
;
2130 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
2132 cifs_strtoUCS((__le16
*) data_offset
, toName
, PATH_MAX
2133 /* find define for this maxpathcomponent */
2135 name_len_target
++; /* trailing null */
2136 name_len_target
*= 2;
2137 } else { /* BB improve the check for buffer overruns BB */
2138 name_len_target
= strnlen(toName
, PATH_MAX
);
2139 name_len_target
++; /* trailing null */
2140 strncpy(data_offset
, toName
, name_len_target
);
2143 pSMB
->MaxParameterCount
= cpu_to_le16(2);
2144 /* BB find exact max on data count below from sess */
2145 pSMB
->MaxDataCount
= cpu_to_le16(1000);
2146 pSMB
->SetupCount
= 1;
2147 pSMB
->Reserved3
= 0;
2148 pSMB
->SubCommand
= cpu_to_le16(TRANS2_SET_PATH_INFORMATION
);
2149 byte_count
= 3 /* pad */ + params
+ name_len_target
;
2150 pSMB
->DataCount
= cpu_to_le16(name_len_target
);
2151 pSMB
->ParameterCount
= cpu_to_le16(params
);
2152 pSMB
->TotalDataCount
= pSMB
->DataCount
;
2153 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
2154 pSMB
->ParameterOffset
= cpu_to_le16(param_offset
);
2155 pSMB
->DataOffset
= cpu_to_le16(offset
);
2156 pSMB
->InformationLevel
= cpu_to_le16(SMB_SET_FILE_UNIX_LINK
);
2157 pSMB
->Reserved4
= 0;
2158 pSMB
->hdr
.smb_buf_length
+= byte_count
;
2159 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
2160 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
2161 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
2162 cifs_stats_inc(&tcon
->num_symlinks
);
2164 cFYI(1, ("Send error in SetPathInfo create symlink = %d", rc
));
2166 cifs_buf_release(pSMB
);
2169 goto createSymLinkRetry
;
2175 CIFSUnixCreateHardLink(const int xid
, struct cifsTconInfo
*tcon
,
2176 const char *fromName
, const char *toName
,
2177 const struct nls_table
*nls_codepage
, int remap
)
2179 TRANSACTION2_SPI_REQ
*pSMB
= NULL
;
2180 TRANSACTION2_SPI_RSP
*pSMBr
= NULL
;
2183 int name_len_target
;
2185 int bytes_returned
= 0;
2186 __u16 params
, param_offset
, offset
, byte_count
;
2188 cFYI(1, ("In Create Hard link Unix style"));
2189 createHardLinkRetry
:
2190 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
2195 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
2196 name_len
= cifsConvertToUCS((__le16
*) pSMB
->FileName
, toName
,
2197 PATH_MAX
, nls_codepage
, remap
);
2198 name_len
++; /* trailing null */
2201 } else { /* BB improve the check for buffer overruns BB */
2202 name_len
= strnlen(toName
, PATH_MAX
);
2203 name_len
++; /* trailing null */
2204 strncpy(pSMB
->FileName
, toName
, name_len
);
2206 params
= 6 + name_len
;
2207 pSMB
->MaxSetupCount
= 0;
2211 pSMB
->Reserved2
= 0;
2212 param_offset
= offsetof(struct smb_com_transaction2_spi_req
,
2213 InformationLevel
) - 4;
2214 offset
= param_offset
+ params
;
2216 data_offset
= (char *) (&pSMB
->hdr
.Protocol
) + offset
;
2217 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
2219 cifsConvertToUCS((__le16
*) data_offset
, fromName
, PATH_MAX
,
2220 nls_codepage
, remap
);
2221 name_len_target
++; /* trailing null */
2222 name_len_target
*= 2;
2223 } else { /* BB improve the check for buffer overruns BB */
2224 name_len_target
= strnlen(fromName
, PATH_MAX
);
2225 name_len_target
++; /* trailing null */
2226 strncpy(data_offset
, fromName
, name_len_target
);
2229 pSMB
->MaxParameterCount
= cpu_to_le16(2);
2230 /* BB find exact max on data count below from sess*/
2231 pSMB
->MaxDataCount
= cpu_to_le16(1000);
2232 pSMB
->SetupCount
= 1;
2233 pSMB
->Reserved3
= 0;
2234 pSMB
->SubCommand
= cpu_to_le16(TRANS2_SET_PATH_INFORMATION
);
2235 byte_count
= 3 /* pad */ + params
+ name_len_target
;
2236 pSMB
->ParameterCount
= cpu_to_le16(params
);
2237 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
2238 pSMB
->DataCount
= cpu_to_le16(name_len_target
);
2239 pSMB
->TotalDataCount
= pSMB
->DataCount
;
2240 pSMB
->ParameterOffset
= cpu_to_le16(param_offset
);
2241 pSMB
->DataOffset
= cpu_to_le16(offset
);
2242 pSMB
->InformationLevel
= cpu_to_le16(SMB_SET_FILE_UNIX_HLINK
);
2243 pSMB
->Reserved4
= 0;
2244 pSMB
->hdr
.smb_buf_length
+= byte_count
;
2245 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
2246 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
2247 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
2248 cifs_stats_inc(&tcon
->num_hardlinks
);
2250 cFYI(1, ("Send error in SetPathInfo (hard link) = %d", rc
));
2252 cifs_buf_release(pSMB
);
2254 goto createHardLinkRetry
;
2260 CIFSCreateHardLink(const int xid
, struct cifsTconInfo
*tcon
,
2261 const char *fromName
, const char *toName
,
2262 const struct nls_table
*nls_codepage
, int remap
)
2265 NT_RENAME_REQ
*pSMB
= NULL
;
2266 RENAME_RSP
*pSMBr
= NULL
;
2268 int name_len
, name_len2
;
2271 cFYI(1, ("In CIFSCreateHardLink"));
2272 winCreateHardLinkRetry
:
2274 rc
= smb_init(SMB_COM_NT_RENAME
, 4, tcon
, (void **) &pSMB
,
2279 pSMB
->SearchAttributes
=
2280 cpu_to_le16(ATTR_READONLY
| ATTR_HIDDEN
| ATTR_SYSTEM
|
2282 pSMB
->Flags
= cpu_to_le16(CREATE_HARD_LINK
);
2283 pSMB
->ClusterCount
= 0;
2285 pSMB
->BufferFormat
= 0x04;
2287 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
2289 cifsConvertToUCS((__le16
*) pSMB
->OldFileName
, fromName
,
2290 PATH_MAX
, nls_codepage
, remap
);
2291 name_len
++; /* trailing null */
2294 /* protocol specifies ASCII buffer format (0x04) for unicode */
2295 pSMB
->OldFileName
[name_len
] = 0x04;
2296 pSMB
->OldFileName
[name_len
+ 1] = 0x00; /* pad */
2298 cifsConvertToUCS((__le16
*)&pSMB
->OldFileName
[name_len
+ 2],
2299 toName
, PATH_MAX
, nls_codepage
, remap
);
2300 name_len2
+= 1 /* trailing null */ + 1 /* Signature word */ ;
2301 name_len2
*= 2; /* convert to bytes */
2302 } else { /* BB improve the check for buffer overruns BB */
2303 name_len
= strnlen(fromName
, PATH_MAX
);
2304 name_len
++; /* trailing null */
2305 strncpy(pSMB
->OldFileName
, fromName
, name_len
);
2306 name_len2
= strnlen(toName
, PATH_MAX
);
2307 name_len2
++; /* trailing null */
2308 pSMB
->OldFileName
[name_len
] = 0x04; /* 2nd buffer format */
2309 strncpy(&pSMB
->OldFileName
[name_len
+ 1], toName
, name_len2
);
2310 name_len2
++; /* trailing null */
2311 name_len2
++; /* signature byte */
2314 count
= 1 /* string type byte */ + name_len
+ name_len2
;
2315 pSMB
->hdr
.smb_buf_length
+= count
;
2316 pSMB
->ByteCount
= cpu_to_le16(count
);
2318 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
2319 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
2320 cifs_stats_inc(&tcon
->num_hardlinks
);
2322 cFYI(1, ("Send error in hard link (NT rename) = %d", rc
));
2324 cifs_buf_release(pSMB
);
2326 goto winCreateHardLinkRetry
;
2332 CIFSSMBUnixQuerySymLink(const int xid
, struct cifsTconInfo
*tcon
,
2333 const unsigned char *searchName
, char **symlinkinfo
,
2334 const struct nls_table
*nls_codepage
)
2336 /* SMB_QUERY_FILE_UNIX_LINK */
2337 TRANSACTION2_QPI_REQ
*pSMB
= NULL
;
2338 TRANSACTION2_QPI_RSP
*pSMBr
= NULL
;
2342 __u16 params
, byte_count
;
2345 cFYI(1, ("In QPathSymLinkInfo (Unix) for path %s", searchName
));
2348 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
2353 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
2355 cifs_strtoUCS((__le16
*) pSMB
->FileName
, searchName
,
2356 PATH_MAX
, nls_codepage
);
2357 name_len
++; /* trailing null */
2359 } else { /* BB improve the check for buffer overruns BB */
2360 name_len
= strnlen(searchName
, PATH_MAX
);
2361 name_len
++; /* trailing null */
2362 strncpy(pSMB
->FileName
, searchName
, name_len
);
2365 params
= 2 /* level */ + 4 /* rsrvd */ + name_len
/* incl null */ ;
2366 pSMB
->TotalDataCount
= 0;
2367 pSMB
->MaxParameterCount
= cpu_to_le16(2);
2368 pSMB
->MaxDataCount
= cpu_to_le16(CIFSMaxBufSize
);
2369 pSMB
->MaxSetupCount
= 0;
2373 pSMB
->Reserved2
= 0;
2374 pSMB
->ParameterOffset
= cpu_to_le16(offsetof(
2375 struct smb_com_transaction2_qpi_req
, InformationLevel
) - 4);
2376 pSMB
->DataCount
= 0;
2377 pSMB
->DataOffset
= 0;
2378 pSMB
->SetupCount
= 1;
2379 pSMB
->Reserved3
= 0;
2380 pSMB
->SubCommand
= cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION
);
2381 byte_count
= params
+ 1 /* pad */ ;
2382 pSMB
->TotalParameterCount
= cpu_to_le16(params
);
2383 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
2384 pSMB
->InformationLevel
= cpu_to_le16(SMB_QUERY_FILE_UNIX_LINK
);
2385 pSMB
->Reserved4
= 0;
2386 pSMB
->hdr
.smb_buf_length
+= byte_count
;
2387 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
2389 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
2390 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
2392 cFYI(1, ("Send error in QuerySymLinkInfo = %d", rc
));
2394 /* decode response */
2396 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
2397 /* BB also check enough total bytes returned */
2398 if (rc
|| (pSMBr
->ByteCount
< 2))
2402 u16 count
= le16_to_cpu(pSMBr
->t2
.DataCount
);
2404 data_start
= ((char *) &pSMBr
->hdr
.Protocol
) +
2405 le16_to_cpu(pSMBr
->t2
.DataOffset
);
2407 if (pSMBr
->hdr
.Flags2
& SMBFLG2_UNICODE
)
2412 /* BB FIXME investigate remapping reserved chars here */
2413 *symlinkinfo
= cifs_strndup_from_ucs(data_start
, count
,
2414 is_unicode
, nls_codepage
);
2419 cifs_buf_release(pSMB
);
2421 goto querySymLinkRetry
;
2425 #ifdef CONFIG_CIFS_EXPERIMENTAL
2426 /* Initialize NT TRANSACT SMB into small smb request buffer.
2427 This assumes that all NT TRANSACTS that we init here have
2428 total parm and data under about 400 bytes (to fit in small cifs
2429 buffer size), which is the case so far, it easily fits. NB:
2430 Setup words themselves and ByteCount
2431 MaxSetupCount (size of returned setup area) and
2432 MaxParameterCount (returned parms size) must be set by caller */
2434 smb_init_nttransact(const __u16 sub_command
, const int setup_count
,
2435 const int parm_len
, struct cifsTconInfo
*tcon
,
2440 struct smb_com_ntransact_req
*pSMB
;
2442 rc
= small_smb_init(SMB_COM_NT_TRANSACT
, 19 + setup_count
, tcon
,
2446 *ret_buf
= (void *)pSMB
;
2448 pSMB
->TotalParameterCount
= cpu_to_le32(parm_len
);
2449 pSMB
->TotalDataCount
= 0;
2450 pSMB
->MaxDataCount
= cpu_to_le32((tcon
->ses
->server
->maxBuf
-
2451 MAX_CIFS_HDR_SIZE
) & 0xFFFFFF00);
2452 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
2453 pSMB
->DataCount
= pSMB
->TotalDataCount
;
2454 temp_offset
= offsetof(struct smb_com_ntransact_req
, Parms
) +
2455 (setup_count
* 2) - 4 /* for rfc1001 length itself */;
2456 pSMB
->ParameterOffset
= cpu_to_le32(temp_offset
);
2457 pSMB
->DataOffset
= cpu_to_le32(temp_offset
+ parm_len
);
2458 pSMB
->SetupCount
= setup_count
; /* no need to le convert byte fields */
2459 pSMB
->SubCommand
= cpu_to_le16(sub_command
);
2464 validate_ntransact(char *buf
, char **ppparm
, char **ppdata
,
2465 __u32
*pparmlen
, __u32
*pdatalen
)
2468 __u32 data_count
, data_offset
, parm_count
, parm_offset
;
2469 struct smb_com_ntransact_rsp
*pSMBr
;
2477 pSMBr
= (struct smb_com_ntransact_rsp
*)buf
;
2479 /* ByteCount was converted from little endian in SendReceive */
2480 end_of_smb
= 2 /* sizeof byte count */ + pSMBr
->ByteCount
+
2481 (char *)&pSMBr
->ByteCount
;
2483 data_offset
= le32_to_cpu(pSMBr
->DataOffset
);
2484 data_count
= le32_to_cpu(pSMBr
->DataCount
);
2485 parm_offset
= le32_to_cpu(pSMBr
->ParameterOffset
);
2486 parm_count
= le32_to_cpu(pSMBr
->ParameterCount
);
2488 *ppparm
= (char *)&pSMBr
->hdr
.Protocol
+ parm_offset
;
2489 *ppdata
= (char *)&pSMBr
->hdr
.Protocol
+ data_offset
;
2491 /* should we also check that parm and data areas do not overlap? */
2492 if (*ppparm
> end_of_smb
) {
2493 cFYI(1, ("parms start after end of smb"));
2495 } else if (parm_count
+ *ppparm
> end_of_smb
) {
2496 cFYI(1, ("parm end after end of smb"));
2498 } else if (*ppdata
> end_of_smb
) {
2499 cFYI(1, ("data starts after end of smb"));
2501 } else if (data_count
+ *ppdata
> end_of_smb
) {
2502 cFYI(1, ("data %p + count %d (%p) ends after end of smb %p start %p",
2503 *ppdata
, data_count
, (data_count
+ *ppdata
),
2504 end_of_smb
, pSMBr
));
2506 } else if (parm_count
+ data_count
> pSMBr
->ByteCount
) {
2507 cFYI(1, ("parm count and data count larger than SMB"));
2510 *pdatalen
= data_count
;
2511 *pparmlen
= parm_count
;
2516 CIFSSMBQueryReparseLinkInfo(const int xid
, struct cifsTconInfo
*tcon
,
2517 const unsigned char *searchName
,
2518 char *symlinkinfo
, const int buflen
, __u16 fid
,
2519 const struct nls_table
*nls_codepage
)
2523 struct smb_com_transaction_ioctl_req
*pSMB
;
2524 struct smb_com_transaction_ioctl_rsp
*pSMBr
;
2526 cFYI(1, ("In Windows reparse style QueryLink for path %s", searchName
));
2527 rc
= smb_init(SMB_COM_NT_TRANSACT
, 23, tcon
, (void **) &pSMB
,
2532 pSMB
->TotalParameterCount
= 0 ;
2533 pSMB
->TotalDataCount
= 0;
2534 pSMB
->MaxParameterCount
= cpu_to_le32(2);
2535 /* BB find exact data count max from sess structure BB */
2536 pSMB
->MaxDataCount
= cpu_to_le32((tcon
->ses
->server
->maxBuf
-
2537 MAX_CIFS_HDR_SIZE
) & 0xFFFFFF00);
2538 pSMB
->MaxSetupCount
= 4;
2540 pSMB
->ParameterOffset
= 0;
2541 pSMB
->DataCount
= 0;
2542 pSMB
->DataOffset
= 0;
2543 pSMB
->SetupCount
= 4;
2544 pSMB
->SubCommand
= cpu_to_le16(NT_TRANSACT_IOCTL
);
2545 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
2546 pSMB
->FunctionCode
= cpu_to_le32(FSCTL_GET_REPARSE_POINT
);
2547 pSMB
->IsFsctl
= 1; /* FSCTL */
2548 pSMB
->IsRootFlag
= 0;
2549 pSMB
->Fid
= fid
; /* file handle always le */
2550 pSMB
->ByteCount
= 0;
2552 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
2553 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
2555 cFYI(1, ("Send error in QueryReparseLinkInfo = %d", rc
));
2556 } else { /* decode response */
2557 __u32 data_offset
= le32_to_cpu(pSMBr
->DataOffset
);
2558 __u32 data_count
= le32_to_cpu(pSMBr
->DataCount
);
2559 if ((pSMBr
->ByteCount
< 2) || (data_offset
> 512)) {
2560 /* BB also check enough total bytes returned */
2561 rc
= -EIO
; /* bad smb */
2564 if (data_count
&& (data_count
< 2048)) {
2565 char *end_of_smb
= 2 /* sizeof byte count */ +
2566 pSMBr
->ByteCount
+ (char *)&pSMBr
->ByteCount
;
2568 struct reparse_data
*reparse_buf
=
2569 (struct reparse_data
*)
2570 ((char *)&pSMBr
->hdr
.Protocol
2572 if ((char *)reparse_buf
>= end_of_smb
) {
2576 if ((reparse_buf
->LinkNamesBuf
+
2577 reparse_buf
->TargetNameOffset
+
2578 reparse_buf
->TargetNameLen
) > end_of_smb
) {
2579 cFYI(1, ("reparse buf beyond SMB"));
2584 if (pSMBr
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
2585 cifs_from_ucs2(symlinkinfo
, (__le16
*)
2586 (reparse_buf
->LinkNamesBuf
+
2587 reparse_buf
->TargetNameOffset
),
2589 reparse_buf
->TargetNameLen
,
2591 } else { /* ASCII names */
2592 strncpy(symlinkinfo
,
2593 reparse_buf
->LinkNamesBuf
+
2594 reparse_buf
->TargetNameOffset
,
2595 min_t(const int, buflen
,
2596 reparse_buf
->TargetNameLen
));
2600 cFYI(1, ("Invalid return data count on "
2601 "get reparse info ioctl"));
2603 symlinkinfo
[buflen
] = 0; /* just in case so the caller
2604 does not go off the end of the buffer */
2605 cFYI(1, ("readlink result - %s", symlinkinfo
));
2609 cifs_buf_release(pSMB
);
2611 /* Note: On -EAGAIN error only caller can retry on handle based calls
2612 since file handle passed in no longer valid */
2616 #endif /* CIFS_EXPERIMENTAL */
2618 #ifdef CONFIG_CIFS_POSIX
2620 /*Convert an Access Control Entry from wire format to local POSIX xattr format*/
2621 static void cifs_convert_ace(posix_acl_xattr_entry
*ace
,
2622 struct cifs_posix_ace
*cifs_ace
)
2624 /* u8 cifs fields do not need le conversion */
2625 ace
->e_perm
= cpu_to_le16(cifs_ace
->cifs_e_perm
);
2626 ace
->e_tag
= cpu_to_le16(cifs_ace
->cifs_e_tag
);
2627 ace
->e_id
= cpu_to_le32(le64_to_cpu(cifs_ace
->cifs_uid
));
2628 /* cFYI(1,("perm %d tag %d id %d",ace->e_perm,ace->e_tag,ace->e_id)); */
2633 /* Convert ACL from CIFS POSIX wire format to local Linux POSIX ACL xattr */
2634 static int cifs_copy_posix_acl(char *trgt
, char *src
, const int buflen
,
2635 const int acl_type
, const int size_of_data_area
)
2640 struct cifs_posix_ace
*pACE
;
2641 struct cifs_posix_acl
*cifs_acl
= (struct cifs_posix_acl
*)src
;
2642 posix_acl_xattr_header
*local_acl
= (posix_acl_xattr_header
*)trgt
;
2644 if (le16_to_cpu(cifs_acl
->version
) != CIFS_ACL_VERSION
)
2647 if (acl_type
& ACL_TYPE_ACCESS
) {
2648 count
= le16_to_cpu(cifs_acl
->access_entry_count
);
2649 pACE
= &cifs_acl
->ace_array
[0];
2650 size
= sizeof(struct cifs_posix_acl
);
2651 size
+= sizeof(struct cifs_posix_ace
) * count
;
2652 /* check if we would go beyond end of SMB */
2653 if (size_of_data_area
< size
) {
2654 cFYI(1, ("bad CIFS POSIX ACL size %d vs. %d",
2655 size_of_data_area
, size
));
2658 } else if (acl_type
& ACL_TYPE_DEFAULT
) {
2659 count
= le16_to_cpu(cifs_acl
->access_entry_count
);
2660 size
= sizeof(struct cifs_posix_acl
);
2661 size
+= sizeof(struct cifs_posix_ace
) * count
;
2662 /* skip past access ACEs to get to default ACEs */
2663 pACE
= &cifs_acl
->ace_array
[count
];
2664 count
= le16_to_cpu(cifs_acl
->default_entry_count
);
2665 size
+= sizeof(struct cifs_posix_ace
) * count
;
2666 /* check if we would go beyond end of SMB */
2667 if (size_of_data_area
< size
)
2674 size
= posix_acl_xattr_size(count
);
2675 if ((buflen
== 0) || (local_acl
== NULL
)) {
2676 /* used to query ACL EA size */
2677 } else if (size
> buflen
) {
2679 } else /* buffer big enough */ {
2680 local_acl
->a_version
= cpu_to_le32(POSIX_ACL_XATTR_VERSION
);
2681 for (i
= 0; i
< count
; i
++) {
2682 cifs_convert_ace(&local_acl
->a_entries
[i
], pACE
);
2689 static __u16
convert_ace_to_cifs_ace(struct cifs_posix_ace
*cifs_ace
,
2690 const posix_acl_xattr_entry
*local_ace
)
2692 __u16 rc
= 0; /* 0 = ACL converted ok */
2694 cifs_ace
->cifs_e_perm
= le16_to_cpu(local_ace
->e_perm
);
2695 cifs_ace
->cifs_e_tag
= le16_to_cpu(local_ace
->e_tag
);
2696 /* BB is there a better way to handle the large uid? */
2697 if (local_ace
->e_id
== cpu_to_le32(-1)) {
2698 /* Probably no need to le convert -1 on any arch but can not hurt */
2699 cifs_ace
->cifs_uid
= cpu_to_le64(-1);
2701 cifs_ace
->cifs_uid
= cpu_to_le64(le32_to_cpu(local_ace
->e_id
));
2702 /*cFYI(1,("perm %d tag %d id %d",ace->e_perm,ace->e_tag,ace->e_id));*/
2706 /* Convert ACL from local Linux POSIX xattr to CIFS POSIX ACL wire format */
2707 static __u16
ACL_to_cifs_posix(char *parm_data
, const char *pACL
,
2708 const int buflen
, const int acl_type
)
2711 struct cifs_posix_acl
*cifs_acl
= (struct cifs_posix_acl
*)parm_data
;
2712 posix_acl_xattr_header
*local_acl
= (posix_acl_xattr_header
*)pACL
;
2716 if ((buflen
== 0) || (pACL
== NULL
) || (cifs_acl
== NULL
))
2719 count
= posix_acl_xattr_count((size_t)buflen
);
2720 cFYI(1, ("setting acl with %d entries from buf of length %d and "
2722 count
, buflen
, le32_to_cpu(local_acl
->a_version
)));
2723 if (le32_to_cpu(local_acl
->a_version
) != 2) {
2724 cFYI(1, ("unknown POSIX ACL version %d",
2725 le32_to_cpu(local_acl
->a_version
)));
2728 cifs_acl
->version
= cpu_to_le16(1);
2729 if (acl_type
== ACL_TYPE_ACCESS
)
2730 cifs_acl
->access_entry_count
= cpu_to_le16(count
);
2731 else if (acl_type
== ACL_TYPE_DEFAULT
)
2732 cifs_acl
->default_entry_count
= cpu_to_le16(count
);
2734 cFYI(1, ("unknown ACL type %d", acl_type
));
2737 for (i
= 0; i
< count
; i
++) {
2738 rc
= convert_ace_to_cifs_ace(&cifs_acl
->ace_array
[i
],
2739 &local_acl
->a_entries
[i
]);
2741 /* ACE not converted */
2746 rc
= (__u16
)(count
* sizeof(struct cifs_posix_ace
));
2747 rc
+= sizeof(struct cifs_posix_acl
);
2748 /* BB add check to make sure ACL does not overflow SMB */
2754 CIFSSMBGetPosixACL(const int xid
, struct cifsTconInfo
*tcon
,
2755 const unsigned char *searchName
,
2756 char *acl_inf
, const int buflen
, const int acl_type
,
2757 const struct nls_table
*nls_codepage
, int remap
)
2759 /* SMB_QUERY_POSIX_ACL */
2760 TRANSACTION2_QPI_REQ
*pSMB
= NULL
;
2761 TRANSACTION2_QPI_RSP
*pSMBr
= NULL
;
2765 __u16 params
, byte_count
;
2767 cFYI(1, ("In GetPosixACL (Unix) for path %s", searchName
));
2770 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
2775 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
2777 cifsConvertToUCS((__le16
*) pSMB
->FileName
, searchName
,
2778 PATH_MAX
, nls_codepage
, remap
);
2779 name_len
++; /* trailing null */
2781 pSMB
->FileName
[name_len
] = 0;
2782 pSMB
->FileName
[name_len
+1] = 0;
2783 } else { /* BB improve the check for buffer overruns BB */
2784 name_len
= strnlen(searchName
, PATH_MAX
);
2785 name_len
++; /* trailing null */
2786 strncpy(pSMB
->FileName
, searchName
, name_len
);
2789 params
= 2 /* level */ + 4 /* rsrvd */ + name_len
/* incl null */ ;
2790 pSMB
->TotalDataCount
= 0;
2791 pSMB
->MaxParameterCount
= cpu_to_le16(2);
2792 /* BB find exact max data count below from sess structure BB */
2793 pSMB
->MaxDataCount
= cpu_to_le16(4000);
2794 pSMB
->MaxSetupCount
= 0;
2798 pSMB
->Reserved2
= 0;
2799 pSMB
->ParameterOffset
= cpu_to_le16(
2800 offsetof(struct smb_com_transaction2_qpi_req
,
2801 InformationLevel
) - 4);
2802 pSMB
->DataCount
= 0;
2803 pSMB
->DataOffset
= 0;
2804 pSMB
->SetupCount
= 1;
2805 pSMB
->Reserved3
= 0;
2806 pSMB
->SubCommand
= cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION
);
2807 byte_count
= params
+ 1 /* pad */ ;
2808 pSMB
->TotalParameterCount
= cpu_to_le16(params
);
2809 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
2810 pSMB
->InformationLevel
= cpu_to_le16(SMB_QUERY_POSIX_ACL
);
2811 pSMB
->Reserved4
= 0;
2812 pSMB
->hdr
.smb_buf_length
+= byte_count
;
2813 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
2815 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
2816 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
2817 cifs_stats_inc(&tcon
->num_acl_get
);
2819 cFYI(1, ("Send error in Query POSIX ACL = %d", rc
));
2821 /* decode response */
2823 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
2824 if (rc
|| (pSMBr
->ByteCount
< 2))
2825 /* BB also check enough total bytes returned */
2826 rc
= -EIO
; /* bad smb */
2828 __u16 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
2829 __u16 count
= le16_to_cpu(pSMBr
->t2
.DataCount
);
2830 rc
= cifs_copy_posix_acl(acl_inf
,
2831 (char *)&pSMBr
->hdr
.Protocol
+data_offset
,
2832 buflen
, acl_type
, count
);
2835 cifs_buf_release(pSMB
);
2842 CIFSSMBSetPosixACL(const int xid
, struct cifsTconInfo
*tcon
,
2843 const unsigned char *fileName
,
2844 const char *local_acl
, const int buflen
,
2846 const struct nls_table
*nls_codepage
, int remap
)
2848 struct smb_com_transaction2_spi_req
*pSMB
= NULL
;
2849 struct smb_com_transaction2_spi_rsp
*pSMBr
= NULL
;
2853 int bytes_returned
= 0;
2854 __u16 params
, byte_count
, data_count
, param_offset
, offset
;
2856 cFYI(1, ("In SetPosixACL (Unix) for path %s", fileName
));
2858 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
2862 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
2864 cifsConvertToUCS((__le16
*) pSMB
->FileName
, fileName
,
2865 PATH_MAX
, nls_codepage
, remap
);
2866 name_len
++; /* trailing null */
2868 } else { /* BB improve the check for buffer overruns BB */
2869 name_len
= strnlen(fileName
, PATH_MAX
);
2870 name_len
++; /* trailing null */
2871 strncpy(pSMB
->FileName
, fileName
, name_len
);
2873 params
= 6 + name_len
;
2874 pSMB
->MaxParameterCount
= cpu_to_le16(2);
2875 /* BB find max SMB size from sess */
2876 pSMB
->MaxDataCount
= cpu_to_le16(1000);
2877 pSMB
->MaxSetupCount
= 0;
2881 pSMB
->Reserved2
= 0;
2882 param_offset
= offsetof(struct smb_com_transaction2_spi_req
,
2883 InformationLevel
) - 4;
2884 offset
= param_offset
+ params
;
2885 parm_data
= ((char *) &pSMB
->hdr
.Protocol
) + offset
;
2886 pSMB
->ParameterOffset
= cpu_to_le16(param_offset
);
2888 /* convert to on the wire format for POSIX ACL */
2889 data_count
= ACL_to_cifs_posix(parm_data
, local_acl
, buflen
, acl_type
);
2891 if (data_count
== 0) {
2893 goto setACLerrorExit
;
2895 pSMB
->DataOffset
= cpu_to_le16(offset
);
2896 pSMB
->SetupCount
= 1;
2897 pSMB
->Reserved3
= 0;
2898 pSMB
->SubCommand
= cpu_to_le16(TRANS2_SET_PATH_INFORMATION
);
2899 pSMB
->InformationLevel
= cpu_to_le16(SMB_SET_POSIX_ACL
);
2900 byte_count
= 3 /* pad */ + params
+ data_count
;
2901 pSMB
->DataCount
= cpu_to_le16(data_count
);
2902 pSMB
->TotalDataCount
= pSMB
->DataCount
;
2903 pSMB
->ParameterCount
= cpu_to_le16(params
);
2904 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
2905 pSMB
->Reserved4
= 0;
2906 pSMB
->hdr
.smb_buf_length
+= byte_count
;
2907 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
2908 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
2909 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
2911 cFYI(1, ("Set POSIX ACL returned %d", rc
));
2914 cifs_buf_release(pSMB
);
2920 /* BB fix tabs in this function FIXME BB */
2922 CIFSGetExtAttr(const int xid
, struct cifsTconInfo
*tcon
,
2923 const int netfid
, __u64
*pExtAttrBits
, __u64
*pMask
)
2926 struct smb_t2_qfi_req
*pSMB
= NULL
;
2927 struct smb_t2_qfi_rsp
*pSMBr
= NULL
;
2929 __u16 params
, byte_count
;
2931 cFYI(1, ("In GetExtAttr"));
2936 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
2941 params
= 2 /* level */ + 2 /* fid */;
2942 pSMB
->t2
.TotalDataCount
= 0;
2943 pSMB
->t2
.MaxParameterCount
= cpu_to_le16(4);
2944 /* BB find exact max data count below from sess structure BB */
2945 pSMB
->t2
.MaxDataCount
= cpu_to_le16(4000);
2946 pSMB
->t2
.MaxSetupCount
= 0;
2947 pSMB
->t2
.Reserved
= 0;
2949 pSMB
->t2
.Timeout
= 0;
2950 pSMB
->t2
.Reserved2
= 0;
2951 pSMB
->t2
.ParameterOffset
= cpu_to_le16(offsetof(struct smb_t2_qfi_req
,
2953 pSMB
->t2
.DataCount
= 0;
2954 pSMB
->t2
.DataOffset
= 0;
2955 pSMB
->t2
.SetupCount
= 1;
2956 pSMB
->t2
.Reserved3
= 0;
2957 pSMB
->t2
.SubCommand
= cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION
);
2958 byte_count
= params
+ 1 /* pad */ ;
2959 pSMB
->t2
.TotalParameterCount
= cpu_to_le16(params
);
2960 pSMB
->t2
.ParameterCount
= pSMB
->t2
.TotalParameterCount
;
2961 pSMB
->InformationLevel
= cpu_to_le16(SMB_QUERY_ATTR_FLAGS
);
2964 pSMB
->hdr
.smb_buf_length
+= byte_count
;
2965 pSMB
->t2
.ByteCount
= cpu_to_le16(byte_count
);
2967 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
2968 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
2970 cFYI(1, ("error %d in GetExtAttr", rc
));
2972 /* decode response */
2973 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
2974 if (rc
|| (pSMBr
->ByteCount
< 2))
2975 /* BB also check enough total bytes returned */
2976 /* If rc should we check for EOPNOSUPP and
2977 disable the srvino flag? or in caller? */
2978 rc
= -EIO
; /* bad smb */
2980 __u16 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
2981 __u16 count
= le16_to_cpu(pSMBr
->t2
.DataCount
);
2982 struct file_chattr_info
*pfinfo
;
2983 /* BB Do we need a cast or hash here ? */
2985 cFYI(1, ("Illegal size ret in GetExtAttr"));
2989 pfinfo
= (struct file_chattr_info
*)
2990 (data_offset
+ (char *) &pSMBr
->hdr
.Protocol
);
2991 *pExtAttrBits
= le64_to_cpu(pfinfo
->mode
);
2992 *pMask
= le64_to_cpu(pfinfo
->mask
);
2996 cifs_buf_release(pSMB
);
2998 goto GetExtAttrRetry
;
3002 #endif /* CONFIG_POSIX */
3004 #ifdef CONFIG_CIFS_EXPERIMENTAL
3005 /* Get Security Descriptor (by handle) from remote server for a file or dir */
3007 CIFSSMBGetCIFSACL(const int xid
, struct cifsTconInfo
*tcon
, __u16 fid
,
3008 struct cifs_ntsd
**acl_inf
, __u32
*pbuflen
)
3012 QUERY_SEC_DESC_REQ
*pSMB
;
3015 cFYI(1, ("GetCifsACL"));
3020 rc
= smb_init_nttransact(NT_TRANSACT_QUERY_SECURITY_DESC
, 0,
3021 8 /* parm len */, tcon
, (void **) &pSMB
);
3025 pSMB
->MaxParameterCount
= cpu_to_le32(4);
3026 /* BB TEST with big acls that might need to be e.g. larger than 16K */
3027 pSMB
->MaxSetupCount
= 0;
3028 pSMB
->Fid
= fid
; /* file handle always le */
3029 pSMB
->AclFlags
= cpu_to_le32(CIFS_ACL_OWNER
| CIFS_ACL_GROUP
|
3031 pSMB
->ByteCount
= cpu_to_le16(11); /* 3 bytes pad + 8 bytes parm */
3032 pSMB
->hdr
.smb_buf_length
+= 11;
3033 iov
[0].iov_base
= (char *)pSMB
;
3034 iov
[0].iov_len
= pSMB
->hdr
.smb_buf_length
+ 4;
3036 rc
= SendReceive2(xid
, tcon
->ses
, iov
, 1 /* num iovec */, &buf_type
,
3038 cifs_stats_inc(&tcon
->num_acl_get
);
3040 cFYI(1, ("Send error in QuerySecDesc = %d", rc
));
3041 } else { /* decode response */
3045 struct smb_com_ntransact_rsp
*pSMBr
;
3048 /* validate_nttransact */
3049 rc
= validate_ntransact(iov
[0].iov_base
, (char **)&parm
,
3050 &pdata
, &parm_len
, pbuflen
);
3053 pSMBr
= (struct smb_com_ntransact_rsp
*)iov
[0].iov_base
;
3055 cFYI(1, ("smb %p parm %p data %p", pSMBr
, parm
, *acl_inf
));
3057 if (le32_to_cpu(pSMBr
->ParameterCount
) != 4) {
3058 rc
= -EIO
; /* bad smb */
3063 /* BB check that data area is minimum length and as big as acl_len */
3065 acl_len
= le32_to_cpu(*parm
);
3066 if (acl_len
!= *pbuflen
) {
3067 cERROR(1, ("acl length %d does not match %d",
3068 acl_len
, *pbuflen
));
3069 if (*pbuflen
> acl_len
)
3073 /* check if buffer is big enough for the acl
3074 header followed by the smallest SID */
3075 if ((*pbuflen
< sizeof(struct cifs_ntsd
) + 8) ||
3076 (*pbuflen
>= 64 * 1024)) {
3077 cERROR(1, ("bad acl length %d", *pbuflen
));
3081 *acl_inf
= kmalloc(*pbuflen
, GFP_KERNEL
);
3082 if (*acl_inf
== NULL
) {
3086 memcpy(*acl_inf
, pdata
, *pbuflen
);
3090 if (buf_type
== CIFS_SMALL_BUFFER
)
3091 cifs_small_buf_release(iov
[0].iov_base
);
3092 else if (buf_type
== CIFS_LARGE_BUFFER
)
3093 cifs_buf_release(iov
[0].iov_base
);
3094 /* cifs_small_buf_release(pSMB); */ /* Freed earlier now in SendReceive2 */
3099 CIFSSMBSetCIFSACL(const int xid
, struct cifsTconInfo
*tcon
, __u16 fid
,
3100 struct cifs_ntsd
*pntsd
, __u32 acllen
)
3102 __u16 byte_count
, param_count
, data_count
, param_offset
, data_offset
;
3104 int bytes_returned
= 0;
3105 SET_SEC_DESC_REQ
*pSMB
= NULL
;
3106 NTRANSACT_RSP
*pSMBr
= NULL
;
3109 rc
= smb_init(SMB_COM_NT_TRANSACT
, 19, tcon
, (void **) &pSMB
,
3114 pSMB
->MaxSetupCount
= 0;
3118 param_offset
= offsetof(struct smb_com_transaction_ssec_req
, Fid
) - 4;
3119 data_count
= acllen
;
3120 data_offset
= param_offset
+ param_count
;
3121 byte_count
= 3 /* pad */ + param_count
;
3123 pSMB
->DataCount
= cpu_to_le32(data_count
);
3124 pSMB
->TotalDataCount
= pSMB
->DataCount
;
3125 pSMB
->MaxParameterCount
= cpu_to_le32(4);
3126 pSMB
->MaxDataCount
= cpu_to_le32(16384);
3127 pSMB
->ParameterCount
= cpu_to_le32(param_count
);
3128 pSMB
->ParameterOffset
= cpu_to_le32(param_offset
);
3129 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
3130 pSMB
->DataOffset
= cpu_to_le32(data_offset
);
3131 pSMB
->SetupCount
= 0;
3132 pSMB
->SubCommand
= cpu_to_le16(NT_TRANSACT_SET_SECURITY_DESC
);
3133 pSMB
->ByteCount
= cpu_to_le16(byte_count
+data_count
);
3135 pSMB
->Fid
= fid
; /* file handle always le */
3136 pSMB
->Reserved2
= 0;
3137 pSMB
->AclFlags
= cpu_to_le32(CIFS_ACL_DACL
);
3139 if (pntsd
&& acllen
) {
3140 memcpy((char *) &pSMBr
->hdr
.Protocol
+ data_offset
,
3143 pSMB
->hdr
.smb_buf_length
+= (byte_count
+ data_count
);
3146 pSMB
->hdr
.smb_buf_length
+= byte_count
;
3148 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
3149 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
3151 cFYI(1, ("SetCIFSACL bytes_returned: %d, rc: %d", bytes_returned
, rc
));
3153 cFYI(1, ("Set CIFS ACL returned %d", rc
));
3154 cifs_buf_release(pSMB
);
3157 goto setCifsAclRetry
;
3162 #endif /* CONFIG_CIFS_EXPERIMENTAL */
3164 /* Legacy Query Path Information call for lookup to old servers such
3166 int SMBQueryInformation(const int xid
, struct cifsTconInfo
*tcon
,
3167 const unsigned char *searchName
,
3168 FILE_ALL_INFO
*pFinfo
,
3169 const struct nls_table
*nls_codepage
, int remap
)
3171 QUERY_INFORMATION_REQ
*pSMB
;
3172 QUERY_INFORMATION_RSP
*pSMBr
;
3177 cFYI(1, ("In SMBQPath path %s", searchName
));
3179 rc
= smb_init(SMB_COM_QUERY_INFORMATION
, 0, tcon
, (void **) &pSMB
,
3184 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
3186 cifsConvertToUCS((__le16
*) pSMB
->FileName
, searchName
,
3187 PATH_MAX
, nls_codepage
, remap
);
3188 name_len
++; /* trailing null */
3191 name_len
= strnlen(searchName
, PATH_MAX
);
3192 name_len
++; /* trailing null */
3193 strncpy(pSMB
->FileName
, searchName
, name_len
);
3195 pSMB
->BufferFormat
= 0x04;
3196 name_len
++; /* account for buffer type byte */
3197 pSMB
->hdr
.smb_buf_length
+= (__u16
) name_len
;
3198 pSMB
->ByteCount
= cpu_to_le16(name_len
);
3200 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
3201 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
3203 cFYI(1, ("Send error in QueryInfo = %d", rc
));
3204 } else if (pFinfo
) {
3206 __u32 time
= le32_to_cpu(pSMBr
->last_write_time
);
3208 /* decode response */
3209 /* BB FIXME - add time zone adjustment BB */
3210 memset(pFinfo
, 0, sizeof(FILE_ALL_INFO
));
3213 /* decode time fields */
3214 pFinfo
->ChangeTime
= cpu_to_le64(cifs_UnixTimeToNT(ts
));
3215 pFinfo
->LastWriteTime
= pFinfo
->ChangeTime
;
3216 pFinfo
->LastAccessTime
= 0;
3217 pFinfo
->AllocationSize
=
3218 cpu_to_le64(le32_to_cpu(pSMBr
->size
));
3219 pFinfo
->EndOfFile
= pFinfo
->AllocationSize
;
3220 pFinfo
->Attributes
=
3221 cpu_to_le32(le16_to_cpu(pSMBr
->attr
));
3223 rc
= -EIO
; /* bad buffer passed in */
3225 cifs_buf_release(pSMB
);
3234 CIFSSMBQFileInfo(const int xid
, struct cifsTconInfo
*tcon
,
3235 u16 netfid
, FILE_ALL_INFO
*pFindData
)
3237 struct smb_t2_qfi_req
*pSMB
= NULL
;
3238 struct smb_t2_qfi_rsp
*pSMBr
= NULL
;
3241 __u16 params
, byte_count
;
3244 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
3249 params
= 2 /* level */ + 2 /* fid */;
3250 pSMB
->t2
.TotalDataCount
= 0;
3251 pSMB
->t2
.MaxParameterCount
= cpu_to_le16(4);
3252 /* BB find exact max data count below from sess structure BB */
3253 pSMB
->t2
.MaxDataCount
= cpu_to_le16(CIFSMaxBufSize
);
3254 pSMB
->t2
.MaxSetupCount
= 0;
3255 pSMB
->t2
.Reserved
= 0;
3257 pSMB
->t2
.Timeout
= 0;
3258 pSMB
->t2
.Reserved2
= 0;
3259 pSMB
->t2
.ParameterOffset
= cpu_to_le16(offsetof(struct smb_t2_qfi_req
,
3261 pSMB
->t2
.DataCount
= 0;
3262 pSMB
->t2
.DataOffset
= 0;
3263 pSMB
->t2
.SetupCount
= 1;
3264 pSMB
->t2
.Reserved3
= 0;
3265 pSMB
->t2
.SubCommand
= cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION
);
3266 byte_count
= params
+ 1 /* pad */ ;
3267 pSMB
->t2
.TotalParameterCount
= cpu_to_le16(params
);
3268 pSMB
->t2
.ParameterCount
= pSMB
->t2
.TotalParameterCount
;
3269 pSMB
->InformationLevel
= cpu_to_le16(SMB_QUERY_FILE_ALL_INFO
);
3272 pSMB
->hdr
.smb_buf_length
+= 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 (pSMBr
->ByteCount
< 40)
3284 rc
= -EIO
; /* bad smb */
3285 else if (pFindData
) {
3286 __u16 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
3287 memcpy((char *) pFindData
,
3288 (char *) &pSMBr
->hdr
.Protocol
+
3289 data_offset
, sizeof(FILE_ALL_INFO
));
3293 cifs_buf_release(pSMB
);
3295 goto QFileInfoRetry
;
3301 CIFSSMBQPathInfo(const int xid
, struct cifsTconInfo
*tcon
,
3302 const unsigned char *searchName
,
3303 FILE_ALL_INFO
*pFindData
,
3304 int legacy
/* old style infolevel */,
3305 const struct nls_table
*nls_codepage
, int remap
)
3307 /* level 263 SMB_QUERY_FILE_ALL_INFO */
3308 TRANSACTION2_QPI_REQ
*pSMB
= NULL
;
3309 TRANSACTION2_QPI_RSP
*pSMBr
= NULL
;
3313 __u16 params
, byte_count
;
3315 /* cFYI(1, ("In QPathInfo path %s", searchName)); */
3317 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
3322 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
3324 cifsConvertToUCS((__le16
*) pSMB
->FileName
, searchName
,
3325 PATH_MAX
, nls_codepage
, remap
);
3326 name_len
++; /* trailing null */
3328 } else { /* BB improve the check for buffer overruns BB */
3329 name_len
= strnlen(searchName
, PATH_MAX
);
3330 name_len
++; /* trailing null */
3331 strncpy(pSMB
->FileName
, searchName
, name_len
);
3334 params
= 2 /* level */ + 4 /* reserved */ + name_len
/* includes NUL */;
3335 pSMB
->TotalDataCount
= 0;
3336 pSMB
->MaxParameterCount
= cpu_to_le16(2);
3337 /* BB find exact max SMB PDU from sess structure BB */
3338 pSMB
->MaxDataCount
= cpu_to_le16(4000);
3339 pSMB
->MaxSetupCount
= 0;
3343 pSMB
->Reserved2
= 0;
3344 pSMB
->ParameterOffset
= cpu_to_le16(offsetof(
3345 struct smb_com_transaction2_qpi_req
, InformationLevel
) - 4);
3346 pSMB
->DataCount
= 0;
3347 pSMB
->DataOffset
= 0;
3348 pSMB
->SetupCount
= 1;
3349 pSMB
->Reserved3
= 0;
3350 pSMB
->SubCommand
= cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION
);
3351 byte_count
= params
+ 1 /* pad */ ;
3352 pSMB
->TotalParameterCount
= cpu_to_le16(params
);
3353 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
3355 pSMB
->InformationLevel
= cpu_to_le16(SMB_INFO_STANDARD
);
3357 pSMB
->InformationLevel
= cpu_to_le16(SMB_QUERY_FILE_ALL_INFO
);
3358 pSMB
->Reserved4
= 0;
3359 pSMB
->hdr
.smb_buf_length
+= byte_count
;
3360 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
3362 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
3363 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
3365 cFYI(1, ("Send error in QPathInfo = %d", rc
));
3366 } else { /* decode response */
3367 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
3369 if (rc
) /* BB add auto retry on EOPNOTSUPP? */
3371 else if (!legacy
&& (pSMBr
->ByteCount
< 40))
3372 rc
= -EIO
; /* bad smb */
3373 else if (legacy
&& (pSMBr
->ByteCount
< 24))
3374 rc
= -EIO
; /* 24 or 26 expected but we do not read
3376 else if (pFindData
) {
3378 __u16 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
3380 /* On legacy responses we do not read the last field,
3381 EAsize, fortunately since it varies by subdialect and
3382 also note it differs on Set vs. Get, ie two bytes or 4
3383 bytes depending but we don't care here */
3385 size
= sizeof(FILE_INFO_STANDARD
);
3387 size
= sizeof(FILE_ALL_INFO
);
3388 memcpy((char *) pFindData
,
3389 (char *) &pSMBr
->hdr
.Protocol
+
3394 cifs_buf_release(pSMB
);
3396 goto QPathInfoRetry
;
3402 CIFSSMBUnixQFileInfo(const int xid
, struct cifsTconInfo
*tcon
,
3403 u16 netfid
, FILE_UNIX_BASIC_INFO
*pFindData
)
3405 struct smb_t2_qfi_req
*pSMB
= NULL
;
3406 struct smb_t2_qfi_rsp
*pSMBr
= NULL
;
3409 __u16 params
, byte_count
;
3412 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
3417 params
= 2 /* level */ + 2 /* fid */;
3418 pSMB
->t2
.TotalDataCount
= 0;
3419 pSMB
->t2
.MaxParameterCount
= cpu_to_le16(4);
3420 /* BB find exact max data count below from sess structure BB */
3421 pSMB
->t2
.MaxDataCount
= cpu_to_le16(CIFSMaxBufSize
);
3422 pSMB
->t2
.MaxSetupCount
= 0;
3423 pSMB
->t2
.Reserved
= 0;
3425 pSMB
->t2
.Timeout
= 0;
3426 pSMB
->t2
.Reserved2
= 0;
3427 pSMB
->t2
.ParameterOffset
= cpu_to_le16(offsetof(struct smb_t2_qfi_req
,
3429 pSMB
->t2
.DataCount
= 0;
3430 pSMB
->t2
.DataOffset
= 0;
3431 pSMB
->t2
.SetupCount
= 1;
3432 pSMB
->t2
.Reserved3
= 0;
3433 pSMB
->t2
.SubCommand
= cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION
);
3434 byte_count
= params
+ 1 /* pad */ ;
3435 pSMB
->t2
.TotalParameterCount
= cpu_to_le16(params
);
3436 pSMB
->t2
.ParameterCount
= pSMB
->t2
.TotalParameterCount
;
3437 pSMB
->InformationLevel
= cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC
);
3440 pSMB
->hdr
.smb_buf_length
+= byte_count
;
3442 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
3443 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
3445 cFYI(1, ("Send error in QPathInfo = %d", rc
));
3446 } else { /* decode response */
3447 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
3449 if (rc
|| (pSMBr
->ByteCount
< sizeof(FILE_UNIX_BASIC_INFO
))) {
3450 cERROR(1, ("Malformed FILE_UNIX_BASIC_INFO response.\n"
3451 "Unix Extensions can be disabled on mount "
3452 "by specifying the nosfu mount option."));
3453 rc
= -EIO
; /* bad smb */
3455 __u16 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
3456 memcpy((char *) pFindData
,
3457 (char *) &pSMBr
->hdr
.Protocol
+
3459 sizeof(FILE_UNIX_BASIC_INFO
));
3463 cifs_buf_release(pSMB
);
3465 goto UnixQFileInfoRetry
;
3471 CIFSSMBUnixQPathInfo(const int xid
, struct cifsTconInfo
*tcon
,
3472 const unsigned char *searchName
,
3473 FILE_UNIX_BASIC_INFO
*pFindData
,
3474 const struct nls_table
*nls_codepage
, int remap
)
3476 /* SMB_QUERY_FILE_UNIX_BASIC */
3477 TRANSACTION2_QPI_REQ
*pSMB
= NULL
;
3478 TRANSACTION2_QPI_RSP
*pSMBr
= NULL
;
3480 int bytes_returned
= 0;
3482 __u16 params
, byte_count
;
3484 cFYI(1, ("In QPathInfo (Unix) the path %s", searchName
));
3486 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
3491 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
3493 cifsConvertToUCS((__le16
*) pSMB
->FileName
, searchName
,
3494 PATH_MAX
, nls_codepage
, remap
);
3495 name_len
++; /* trailing null */
3497 } else { /* BB improve the check for buffer overruns BB */
3498 name_len
= strnlen(searchName
, PATH_MAX
);
3499 name_len
++; /* trailing null */
3500 strncpy(pSMB
->FileName
, searchName
, name_len
);
3503 params
= 2 /* level */ + 4 /* reserved */ + name_len
/* includes NUL */;
3504 pSMB
->TotalDataCount
= 0;
3505 pSMB
->MaxParameterCount
= cpu_to_le16(2);
3506 /* BB find exact max SMB PDU from sess structure BB */
3507 pSMB
->MaxDataCount
= cpu_to_le16(4000);
3508 pSMB
->MaxSetupCount
= 0;
3512 pSMB
->Reserved2
= 0;
3513 pSMB
->ParameterOffset
= cpu_to_le16(offsetof(
3514 struct smb_com_transaction2_qpi_req
, InformationLevel
) - 4);
3515 pSMB
->DataCount
= 0;
3516 pSMB
->DataOffset
= 0;
3517 pSMB
->SetupCount
= 1;
3518 pSMB
->Reserved3
= 0;
3519 pSMB
->SubCommand
= cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION
);
3520 byte_count
= params
+ 1 /* pad */ ;
3521 pSMB
->TotalParameterCount
= cpu_to_le16(params
);
3522 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
3523 pSMB
->InformationLevel
= cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC
);
3524 pSMB
->Reserved4
= 0;
3525 pSMB
->hdr
.smb_buf_length
+= byte_count
;
3526 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
3528 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
3529 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
3531 cFYI(1, ("Send error in QPathInfo = %d", rc
));
3532 } else { /* decode response */
3533 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
3535 if (rc
|| (pSMBr
->ByteCount
< sizeof(FILE_UNIX_BASIC_INFO
))) {
3536 cERROR(1, ("Malformed FILE_UNIX_BASIC_INFO response.\n"
3537 "Unix Extensions can be disabled on mount "
3538 "by specifying the nosfu mount option."));
3539 rc
= -EIO
; /* bad smb */
3541 __u16 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
3542 memcpy((char *) pFindData
,
3543 (char *) &pSMBr
->hdr
.Protocol
+
3545 sizeof(FILE_UNIX_BASIC_INFO
));
3548 cifs_buf_release(pSMB
);
3550 goto UnixQPathInfoRetry
;
3555 /* xid, tcon, searchName and codepage are input parms, rest are returned */
3557 CIFSFindFirst(const int xid
, struct cifsTconInfo
*tcon
,
3558 const char *searchName
,
3559 const struct nls_table
*nls_codepage
,
3561 struct cifs_search_info
*psrch_inf
, int remap
, const char dirsep
)
3563 /* level 257 SMB_ */
3564 TRANSACTION2_FFIRST_REQ
*pSMB
= NULL
;
3565 TRANSACTION2_FFIRST_RSP
*pSMBr
= NULL
;
3566 T2_FFIRST_RSP_PARMS
*parms
;
3568 int bytes_returned
= 0;
3570 __u16 params
, byte_count
;
3572 cFYI(1, ("In FindFirst for %s", searchName
));
3575 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
3580 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
3582 cifsConvertToUCS((__le16
*) pSMB
->FileName
, searchName
,
3583 PATH_MAX
, nls_codepage
, remap
);
3584 /* We can not add the asterik earlier in case
3585 it got remapped to 0xF03A as if it were part of the
3586 directory name instead of a wildcard */
3588 pSMB
->FileName
[name_len
] = dirsep
;
3589 pSMB
->FileName
[name_len
+1] = 0;
3590 pSMB
->FileName
[name_len
+2] = '*';
3591 pSMB
->FileName
[name_len
+3] = 0;
3592 name_len
+= 4; /* now the trailing null */
3593 pSMB
->FileName
[name_len
] = 0; /* null terminate just in case */
3594 pSMB
->FileName
[name_len
+1] = 0;
3596 } else { /* BB add check for overrun of SMB buf BB */
3597 name_len
= strnlen(searchName
, PATH_MAX
);
3598 /* BB fix here and in unicode clause above ie
3599 if (name_len > buffersize-header)
3600 free buffer exit; BB */
3601 strncpy(pSMB
->FileName
, searchName
, name_len
);
3602 pSMB
->FileName
[name_len
] = dirsep
;
3603 pSMB
->FileName
[name_len
+1] = '*';
3604 pSMB
->FileName
[name_len
+2] = 0;
3608 params
= 12 + name_len
/* includes null */ ;
3609 pSMB
->TotalDataCount
= 0; /* no EAs */
3610 pSMB
->MaxParameterCount
= cpu_to_le16(10);
3611 pSMB
->MaxDataCount
= cpu_to_le16((tcon
->ses
->server
->maxBuf
-
3612 MAX_CIFS_HDR_SIZE
) & 0xFFFFFF00);
3613 pSMB
->MaxSetupCount
= 0;
3617 pSMB
->Reserved2
= 0;
3618 byte_count
= params
+ 1 /* pad */ ;
3619 pSMB
->TotalParameterCount
= cpu_to_le16(params
);
3620 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
3621 pSMB
->ParameterOffset
= cpu_to_le16(
3622 offsetof(struct smb_com_transaction2_ffirst_req
, SearchAttributes
)
3624 pSMB
->DataCount
= 0;
3625 pSMB
->DataOffset
= 0;
3626 pSMB
->SetupCount
= 1; /* one byte, no need to make endian neutral */
3627 pSMB
->Reserved3
= 0;
3628 pSMB
->SubCommand
= cpu_to_le16(TRANS2_FIND_FIRST
);
3629 pSMB
->SearchAttributes
=
3630 cpu_to_le16(ATTR_READONLY
| ATTR_HIDDEN
| ATTR_SYSTEM
|
3632 pSMB
->SearchCount
= cpu_to_le16(CIFSMaxBufSize
/sizeof(FILE_UNIX_INFO
));
3633 pSMB
->SearchFlags
= cpu_to_le16(CIFS_SEARCH_CLOSE_AT_END
|
3634 CIFS_SEARCH_RETURN_RESUME
);
3635 pSMB
->InformationLevel
= cpu_to_le16(psrch_inf
->info_level
);
3637 /* BB what should we set StorageType to? Does it matter? BB */
3638 pSMB
->SearchStorageType
= 0;
3639 pSMB
->hdr
.smb_buf_length
+= byte_count
;
3640 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
3642 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
3643 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
3644 cifs_stats_inc(&tcon
->num_ffirst
);
3646 if (rc
) {/* BB add logic to retry regular search if Unix search
3647 rejected unexpectedly by server */
3648 /* BB Add code to handle unsupported level rc */
3649 cFYI(1, ("Error in FindFirst = %d", rc
));
3651 cifs_buf_release(pSMB
);
3653 /* BB eventually could optimize out free and realloc of buf */
3656 goto findFirstRetry
;
3657 } else { /* decode response */
3658 /* BB remember to free buffer if error BB */
3659 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
3663 if (pSMBr
->hdr
.Flags2
& SMBFLG2_UNICODE
)
3664 psrch_inf
->unicode
= true;
3666 psrch_inf
->unicode
= false;
3668 psrch_inf
->ntwrk_buf_start
= (char *)pSMBr
;
3669 psrch_inf
->smallBuf
= 0;
3670 psrch_inf
->srch_entries_start
=
3671 (char *) &pSMBr
->hdr
.Protocol
+
3672 le16_to_cpu(pSMBr
->t2
.DataOffset
);
3673 parms
= (T2_FFIRST_RSP_PARMS
*)((char *) &pSMBr
->hdr
.Protocol
+
3674 le16_to_cpu(pSMBr
->t2
.ParameterOffset
));
3676 if (parms
->EndofSearch
)
3677 psrch_inf
->endOfSearch
= true;
3679 psrch_inf
->endOfSearch
= false;
3681 psrch_inf
->entries_in_buffer
=
3682 le16_to_cpu(parms
->SearchCount
);
3683 psrch_inf
->index_of_last_entry
= 2 /* skip . and .. */ +
3684 psrch_inf
->entries_in_buffer
;
3685 lnoff
= le16_to_cpu(parms
->LastNameOffset
);
3686 if (tcon
->ses
->server
->maxBuf
- MAX_CIFS_HDR_SIZE
<
3688 cERROR(1, ("ignoring corrupt resume name"));
3689 psrch_inf
->last_entry
= NULL
;
3693 psrch_inf
->last_entry
= psrch_inf
->srch_entries_start
+
3696 *pnetfid
= parms
->SearchHandle
;
3698 cifs_buf_release(pSMB
);
3705 int CIFSFindNext(const int xid
, struct cifsTconInfo
*tcon
,
3706 __u16 searchHandle
, struct cifs_search_info
*psrch_inf
)
3708 TRANSACTION2_FNEXT_REQ
*pSMB
= NULL
;
3709 TRANSACTION2_FNEXT_RSP
*pSMBr
= NULL
;
3710 T2_FNEXT_RSP_PARMS
*parms
;
3711 char *response_data
;
3713 int bytes_returned
, name_len
;
3714 __u16 params
, byte_count
;
3716 cFYI(1, ("In FindNext"));
3718 if (psrch_inf
->endOfSearch
)
3721 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
3726 params
= 14; /* includes 2 bytes of null string, converted to LE below*/
3728 pSMB
->TotalDataCount
= 0; /* no EAs */
3729 pSMB
->MaxParameterCount
= cpu_to_le16(8);
3730 pSMB
->MaxDataCount
=
3731 cpu_to_le16((tcon
->ses
->server
->maxBuf
- MAX_CIFS_HDR_SIZE
) &
3733 pSMB
->MaxSetupCount
= 0;
3737 pSMB
->Reserved2
= 0;
3738 pSMB
->ParameterOffset
= cpu_to_le16(
3739 offsetof(struct smb_com_transaction2_fnext_req
,SearchHandle
) - 4);
3740 pSMB
->DataCount
= 0;
3741 pSMB
->DataOffset
= 0;
3742 pSMB
->SetupCount
= 1;
3743 pSMB
->Reserved3
= 0;
3744 pSMB
->SubCommand
= cpu_to_le16(TRANS2_FIND_NEXT
);
3745 pSMB
->SearchHandle
= searchHandle
; /* always kept as le */
3747 cpu_to_le16(CIFSMaxBufSize
/ sizeof(FILE_UNIX_INFO
));
3748 pSMB
->InformationLevel
= cpu_to_le16(psrch_inf
->info_level
);
3749 pSMB
->ResumeKey
= psrch_inf
->resume_key
;
3751 cpu_to_le16(CIFS_SEARCH_CLOSE_AT_END
| CIFS_SEARCH_RETURN_RESUME
);
3753 name_len
= psrch_inf
->resume_name_len
;
3755 if (name_len
< PATH_MAX
) {
3756 memcpy(pSMB
->ResumeFileName
, psrch_inf
->presume_name
, name_len
);
3757 byte_count
+= name_len
;
3758 /* 14 byte parm len above enough for 2 byte null terminator */
3759 pSMB
->ResumeFileName
[name_len
] = 0;
3760 pSMB
->ResumeFileName
[name_len
+1] = 0;
3763 goto FNext2_err_exit
;
3765 byte_count
= params
+ 1 /* pad */ ;
3766 pSMB
->TotalParameterCount
= cpu_to_le16(params
);
3767 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
3768 pSMB
->hdr
.smb_buf_length
+= byte_count
;
3769 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
3771 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
3772 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
3773 cifs_stats_inc(&tcon
->num_fnext
);
3776 psrch_inf
->endOfSearch
= true;
3777 cifs_buf_release(pSMB
);
3778 rc
= 0; /* search probably was closed at end of search*/
3780 cFYI(1, ("FindNext returned = %d", rc
));
3781 } else { /* decode response */
3782 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
3787 /* BB fixme add lock for file (srch_info) struct here */
3788 if (pSMBr
->hdr
.Flags2
& SMBFLG2_UNICODE
)
3789 psrch_inf
->unicode
= true;
3791 psrch_inf
->unicode
= false;
3792 response_data
= (char *) &pSMBr
->hdr
.Protocol
+
3793 le16_to_cpu(pSMBr
->t2
.ParameterOffset
);
3794 parms
= (T2_FNEXT_RSP_PARMS
*)response_data
;
3795 response_data
= (char *)&pSMBr
->hdr
.Protocol
+
3796 le16_to_cpu(pSMBr
->t2
.DataOffset
);
3797 if (psrch_inf
->smallBuf
)
3798 cifs_small_buf_release(
3799 psrch_inf
->ntwrk_buf_start
);
3801 cifs_buf_release(psrch_inf
->ntwrk_buf_start
);
3802 psrch_inf
->srch_entries_start
= response_data
;
3803 psrch_inf
->ntwrk_buf_start
= (char *)pSMB
;
3804 psrch_inf
->smallBuf
= 0;
3805 if (parms
->EndofSearch
)
3806 psrch_inf
->endOfSearch
= true;
3808 psrch_inf
->endOfSearch
= false;
3809 psrch_inf
->entries_in_buffer
=
3810 le16_to_cpu(parms
->SearchCount
);
3811 psrch_inf
->index_of_last_entry
+=
3812 psrch_inf
->entries_in_buffer
;
3813 lnoff
= le16_to_cpu(parms
->LastNameOffset
);
3814 if (tcon
->ses
->server
->maxBuf
- MAX_CIFS_HDR_SIZE
<
3816 cERROR(1, ("ignoring corrupt resume name"));
3817 psrch_inf
->last_entry
= NULL
;
3820 psrch_inf
->last_entry
=
3821 psrch_inf
->srch_entries_start
+ lnoff
;
3823 /* cFYI(1,("fnxt2 entries in buf %d index_of_last %d",
3824 psrch_inf->entries_in_buffer, psrch_inf->index_of_last_entry)); */
3826 /* BB fixme add unlock here */
3831 /* BB On error, should we leave previous search buf (and count and
3832 last entry fields) intact or free the previous one? */
3834 /* Note: On -EAGAIN error only caller can retry on handle based calls
3835 since file handle passed in no longer valid */
3838 cifs_buf_release(pSMB
);
3843 CIFSFindClose(const int xid
, struct cifsTconInfo
*tcon
,
3844 const __u16 searchHandle
)
3847 FINDCLOSE_REQ
*pSMB
= NULL
;
3849 cFYI(1, ("In CIFSSMBFindClose"));
3850 rc
= small_smb_init(SMB_COM_FIND_CLOSE2
, 1, tcon
, (void **)&pSMB
);
3852 /* no sense returning error if session restarted
3853 as file handle has been closed */
3859 pSMB
->FileID
= searchHandle
;
3860 pSMB
->ByteCount
= 0;
3861 rc
= SendReceiveNoRsp(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
, 0);
3863 cERROR(1, ("Send error in FindClose = %d", rc
));
3865 cifs_stats_inc(&tcon
->num_fclose
);
3867 /* Since session is dead, search handle closed on server already */
3875 CIFSGetSrvInodeNumber(const int xid
, struct cifsTconInfo
*tcon
,
3876 const unsigned char *searchName
,
3877 __u64
*inode_number
,
3878 const struct nls_table
*nls_codepage
, int remap
)
3881 TRANSACTION2_QPI_REQ
*pSMB
= NULL
;
3882 TRANSACTION2_QPI_RSP
*pSMBr
= NULL
;
3883 int name_len
, bytes_returned
;
3884 __u16 params
, byte_count
;
3886 cFYI(1, ("In GetSrvInodeNum for %s", searchName
));
3890 GetInodeNumberRetry
:
3891 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
3896 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
3898 cifsConvertToUCS((__le16
*) pSMB
->FileName
, searchName
,
3899 PATH_MAX
, nls_codepage
, remap
);
3900 name_len
++; /* trailing null */
3902 } else { /* BB improve the check for buffer overruns BB */
3903 name_len
= strnlen(searchName
, PATH_MAX
);
3904 name_len
++; /* trailing null */
3905 strncpy(pSMB
->FileName
, searchName
, name_len
);
3908 params
= 2 /* level */ + 4 /* rsrvd */ + name_len
/* incl null */ ;
3909 pSMB
->TotalDataCount
= 0;
3910 pSMB
->MaxParameterCount
= cpu_to_le16(2);
3911 /* BB find exact max data count below from sess structure BB */
3912 pSMB
->MaxDataCount
= cpu_to_le16(4000);
3913 pSMB
->MaxSetupCount
= 0;
3917 pSMB
->Reserved2
= 0;
3918 pSMB
->ParameterOffset
= cpu_to_le16(offsetof(
3919 struct smb_com_transaction2_qpi_req
, InformationLevel
) - 4);
3920 pSMB
->DataCount
= 0;
3921 pSMB
->DataOffset
= 0;
3922 pSMB
->SetupCount
= 1;
3923 pSMB
->Reserved3
= 0;
3924 pSMB
->SubCommand
= cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION
);
3925 byte_count
= params
+ 1 /* pad */ ;
3926 pSMB
->TotalParameterCount
= cpu_to_le16(params
);
3927 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
3928 pSMB
->InformationLevel
= cpu_to_le16(SMB_QUERY_FILE_INTERNAL_INFO
);
3929 pSMB
->Reserved4
= 0;
3930 pSMB
->hdr
.smb_buf_length
+= byte_count
;
3931 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
3933 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
3934 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
3936 cFYI(1, ("error %d in QueryInternalInfo", rc
));
3938 /* decode response */
3939 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
3940 if (rc
|| (pSMBr
->ByteCount
< 2))
3941 /* BB also check enough total bytes returned */
3942 /* If rc should we check for EOPNOSUPP and
3943 disable the srvino flag? or in caller? */
3944 rc
= -EIO
; /* bad smb */
3946 __u16 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
3947 __u16 count
= le16_to_cpu(pSMBr
->t2
.DataCount
);
3948 struct file_internal_info
*pfinfo
;
3949 /* BB Do we need a cast or hash here ? */
3951 cFYI(1, ("Illegal size ret in QryIntrnlInf"));
3953 goto GetInodeNumOut
;
3955 pfinfo
= (struct file_internal_info
*)
3956 (data_offset
+ (char *) &pSMBr
->hdr
.Protocol
);
3957 *inode_number
= le64_to_cpu(pfinfo
->UniqueId
);
3961 cifs_buf_release(pSMB
);
3963 goto GetInodeNumberRetry
;
3967 /* parses DFS refferal V3 structure
3968 * caller is responsible for freeing target_nodes
3971 * on failure - errno
3974 parse_DFS_referrals(TRANSACTION2_GET_DFS_REFER_RSP
*pSMBr
,
3975 unsigned int *num_of_nodes
,
3976 struct dfs_info3_param
**target_nodes
,
3977 const struct nls_table
*nls_codepage
, int remap
,
3978 const char *searchName
)
3983 struct dfs_referral_level_3
*ref
;
3985 if (pSMBr
->hdr
.Flags2
& SMBFLG2_UNICODE
)
3989 *num_of_nodes
= le16_to_cpu(pSMBr
->NumberOfReferrals
);
3991 if (*num_of_nodes
< 1) {
3992 cERROR(1, ("num_referrals: must be at least > 0,"
3993 "but we get num_referrals = %d\n", *num_of_nodes
));
3995 goto parse_DFS_referrals_exit
;
3998 ref
= (struct dfs_referral_level_3
*) &(pSMBr
->referrals
);
3999 if (ref
->VersionNumber
!= cpu_to_le16(3)) {
4000 cERROR(1, ("Referrals of V%d version are not supported,"
4001 "should be V3", le16_to_cpu(ref
->VersionNumber
)));
4003 goto parse_DFS_referrals_exit
;
4006 /* get the upper boundary of the resp buffer */
4007 data_end
= (char *)(&(pSMBr
->PathConsumed
)) +
4008 le16_to_cpu(pSMBr
->t2
.DataCount
);
4010 cFYI(1, ("num_referrals: %d dfs flags: 0x%x ... \n",
4012 le32_to_cpu(pSMBr
->DFSFlags
)));
4014 *target_nodes
= kzalloc(sizeof(struct dfs_info3_param
) *
4015 *num_of_nodes
, GFP_KERNEL
);
4016 if (*target_nodes
== NULL
) {
4017 cERROR(1, ("Failed to allocate buffer for target_nodes\n"));
4019 goto parse_DFS_referrals_exit
;
4022 /* collect necessary data from referrals */
4023 for (i
= 0; i
< *num_of_nodes
; i
++) {
4026 struct dfs_info3_param
*node
= (*target_nodes
)+i
;
4028 node
->flags
= le32_to_cpu(pSMBr
->DFSFlags
);
4030 __le16
*tmp
= kmalloc(strlen(searchName
)*2 + 2,
4034 goto parse_DFS_referrals_exit
;
4036 cifsConvertToUCS((__le16
*) tmp
, searchName
,
4037 PATH_MAX
, nls_codepage
, remap
);
4038 node
->path_consumed
= cifs_ucs2_bytes(tmp
,
4039 le16_to_cpu(pSMBr
->PathConsumed
),
4043 node
->path_consumed
= le16_to_cpu(pSMBr
->PathConsumed
);
4045 node
->server_type
= le16_to_cpu(ref
->ServerType
);
4046 node
->ref_flag
= le16_to_cpu(ref
->ReferralEntryFlags
);
4049 temp
= (char *)ref
+ le16_to_cpu(ref
->DfsPathOffset
);
4050 max_len
= data_end
- temp
;
4051 node
->path_name
= cifs_strndup_from_ucs(temp
, max_len
,
4052 is_unicode
, nls_codepage
);
4053 if (!node
->path_name
) {
4055 goto parse_DFS_referrals_exit
;
4058 /* copy link target UNC */
4059 temp
= (char *)ref
+ le16_to_cpu(ref
->NetworkAddressOffset
);
4060 max_len
= data_end
- temp
;
4061 node
->node_name
= cifs_strndup_from_ucs(temp
, max_len
,
4062 is_unicode
, nls_codepage
);
4063 if (!node
->node_name
)
4067 parse_DFS_referrals_exit
:
4069 free_dfs_info_array(*target_nodes
, *num_of_nodes
);
4070 *target_nodes
= NULL
;
4077 CIFSGetDFSRefer(const int xid
, struct cifsSesInfo
*ses
,
4078 const unsigned char *searchName
,
4079 struct dfs_info3_param
**target_nodes
,
4080 unsigned int *num_of_nodes
,
4081 const struct nls_table
*nls_codepage
, int remap
)
4083 /* TRANS2_GET_DFS_REFERRAL */
4084 TRANSACTION2_GET_DFS_REFER_REQ
*pSMB
= NULL
;
4085 TRANSACTION2_GET_DFS_REFER_RSP
*pSMBr
= NULL
;
4089 __u16 params
, byte_count
;
4091 *target_nodes
= NULL
;
4093 cFYI(1, ("In GetDFSRefer the path %s", searchName
));
4097 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, NULL
, (void **) &pSMB
,
4102 /* server pointer checked in called function,
4103 but should never be null here anyway */
4104 pSMB
->hdr
.Mid
= GetNextMid(ses
->server
);
4105 pSMB
->hdr
.Tid
= ses
->ipc_tid
;
4106 pSMB
->hdr
.Uid
= ses
->Suid
;
4107 if (ses
->capabilities
& CAP_STATUS32
)
4108 pSMB
->hdr
.Flags2
|= SMBFLG2_ERR_STATUS
;
4109 if (ses
->capabilities
& CAP_DFS
)
4110 pSMB
->hdr
.Flags2
|= SMBFLG2_DFS
;
4112 if (ses
->capabilities
& CAP_UNICODE
) {
4113 pSMB
->hdr
.Flags2
|= SMBFLG2_UNICODE
;
4115 cifsConvertToUCS((__le16
*) pSMB
->RequestFileName
,
4116 searchName
, PATH_MAX
, nls_codepage
, remap
);
4117 name_len
++; /* trailing null */
4119 } else { /* BB improve the check for buffer overruns BB */
4120 name_len
= strnlen(searchName
, PATH_MAX
);
4121 name_len
++; /* trailing null */
4122 strncpy(pSMB
->RequestFileName
, searchName
, name_len
);
4126 if (ses
->server
->secMode
&
4127 (SECMODE_SIGN_REQUIRED
| SECMODE_SIGN_ENABLED
))
4128 pSMB
->hdr
.Flags2
|= SMBFLG2_SECURITY_SIGNATURE
;
4131 pSMB
->hdr
.Uid
= ses
->Suid
;
4133 params
= 2 /* level */ + name_len
/*includes null */ ;
4134 pSMB
->TotalDataCount
= 0;
4135 pSMB
->DataCount
= 0;
4136 pSMB
->DataOffset
= 0;
4137 pSMB
->MaxParameterCount
= 0;
4138 /* BB find exact max SMB PDU from sess structure BB */
4139 pSMB
->MaxDataCount
= cpu_to_le16(4000);
4140 pSMB
->MaxSetupCount
= 0;
4144 pSMB
->Reserved2
= 0;
4145 pSMB
->ParameterOffset
= cpu_to_le16(offsetof(
4146 struct smb_com_transaction2_get_dfs_refer_req
, MaxReferralLevel
) - 4);
4147 pSMB
->SetupCount
= 1;
4148 pSMB
->Reserved3
= 0;
4149 pSMB
->SubCommand
= cpu_to_le16(TRANS2_GET_DFS_REFERRAL
);
4150 byte_count
= params
+ 3 /* pad */ ;
4151 pSMB
->ParameterCount
= cpu_to_le16(params
);
4152 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
4153 pSMB
->MaxReferralLevel
= cpu_to_le16(3);
4154 pSMB
->hdr
.smb_buf_length
+= byte_count
;
4155 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
4157 rc
= SendReceive(xid
, ses
, (struct smb_hdr
*) pSMB
,
4158 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
4160 cFYI(1, ("Send error in GetDFSRefer = %d", rc
));
4163 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
4165 /* BB Also check if enough total bytes returned? */
4166 if (rc
|| (pSMBr
->ByteCount
< 17)) {
4167 rc
= -EIO
; /* bad smb */
4171 cFYI(1, ("Decoding GetDFSRefer response BCC: %d Offset %d",
4173 le16_to_cpu(pSMBr
->t2
.DataOffset
)));
4175 /* parse returned result into more usable form */
4176 rc
= parse_DFS_referrals(pSMBr
, num_of_nodes
,
4177 target_nodes
, nls_codepage
, remap
,
4181 cifs_buf_release(pSMB
);
4189 /* Query File System Info such as free space to old servers such as Win 9x */
4191 SMBOldQFSInfo(const int xid
, struct cifsTconInfo
*tcon
, struct kstatfs
*FSData
)
4193 /* level 0x01 SMB_QUERY_FILE_SYSTEM_INFO */
4194 TRANSACTION2_QFSI_REQ
*pSMB
= NULL
;
4195 TRANSACTION2_QFSI_RSP
*pSMBr
= NULL
;
4196 FILE_SYSTEM_ALLOC_INFO
*response_data
;
4198 int bytes_returned
= 0;
4199 __u16 params
, byte_count
;
4201 cFYI(1, ("OldQFSInfo"));
4203 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
4208 params
= 2; /* level */
4209 pSMB
->TotalDataCount
= 0;
4210 pSMB
->MaxParameterCount
= cpu_to_le16(2);
4211 pSMB
->MaxDataCount
= cpu_to_le16(1000);
4212 pSMB
->MaxSetupCount
= 0;
4216 pSMB
->Reserved2
= 0;
4217 byte_count
= params
+ 1 /* pad */ ;
4218 pSMB
->TotalParameterCount
= cpu_to_le16(params
);
4219 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
4220 pSMB
->ParameterOffset
= cpu_to_le16(offsetof(
4221 struct smb_com_transaction2_qfsi_req
, InformationLevel
) - 4);
4222 pSMB
->DataCount
= 0;
4223 pSMB
->DataOffset
= 0;
4224 pSMB
->SetupCount
= 1;
4225 pSMB
->Reserved3
= 0;
4226 pSMB
->SubCommand
= cpu_to_le16(TRANS2_QUERY_FS_INFORMATION
);
4227 pSMB
->InformationLevel
= cpu_to_le16(SMB_INFO_ALLOCATION
);
4228 pSMB
->hdr
.smb_buf_length
+= byte_count
;
4229 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
4231 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
4232 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
4234 cFYI(1, ("Send error in QFSInfo = %d", rc
));
4235 } else { /* decode response */
4236 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
4238 if (rc
|| (pSMBr
->ByteCount
< 18))
4239 rc
= -EIO
; /* bad smb */
4241 __u16 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
4242 cFYI(1, ("qfsinf resp BCC: %d Offset %d",
4243 pSMBr
->ByteCount
, data_offset
));
4245 response_data
= (FILE_SYSTEM_ALLOC_INFO
*)
4246 (((char *) &pSMBr
->hdr
.Protocol
) + data_offset
);
4248 le16_to_cpu(response_data
->BytesPerSector
) *
4249 le32_to_cpu(response_data
->
4250 SectorsPerAllocationUnit
);
4252 le32_to_cpu(response_data
->TotalAllocationUnits
);
4253 FSData
->f_bfree
= FSData
->f_bavail
=
4254 le32_to_cpu(response_data
->FreeAllocationUnits
);
4256 ("Blocks: %lld Free: %lld Block size %ld",
4257 (unsigned long long)FSData
->f_blocks
,
4258 (unsigned long long)FSData
->f_bfree
,
4262 cifs_buf_release(pSMB
);
4265 goto oldQFSInfoRetry
;
4271 CIFSSMBQFSInfo(const int xid
, struct cifsTconInfo
*tcon
, struct kstatfs
*FSData
)
4273 /* level 0x103 SMB_QUERY_FILE_SYSTEM_INFO */
4274 TRANSACTION2_QFSI_REQ
*pSMB
= NULL
;
4275 TRANSACTION2_QFSI_RSP
*pSMBr
= NULL
;
4276 FILE_SYSTEM_INFO
*response_data
;
4278 int bytes_returned
= 0;
4279 __u16 params
, byte_count
;
4281 cFYI(1, ("In QFSInfo"));
4283 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
4288 params
= 2; /* level */
4289 pSMB
->TotalDataCount
= 0;
4290 pSMB
->MaxParameterCount
= cpu_to_le16(2);
4291 pSMB
->MaxDataCount
= cpu_to_le16(1000);
4292 pSMB
->MaxSetupCount
= 0;
4296 pSMB
->Reserved2
= 0;
4297 byte_count
= params
+ 1 /* pad */ ;
4298 pSMB
->TotalParameterCount
= cpu_to_le16(params
);
4299 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
4300 pSMB
->ParameterOffset
= cpu_to_le16(offsetof(
4301 struct smb_com_transaction2_qfsi_req
, InformationLevel
) - 4);
4302 pSMB
->DataCount
= 0;
4303 pSMB
->DataOffset
= 0;
4304 pSMB
->SetupCount
= 1;
4305 pSMB
->Reserved3
= 0;
4306 pSMB
->SubCommand
= cpu_to_le16(TRANS2_QUERY_FS_INFORMATION
);
4307 pSMB
->InformationLevel
= cpu_to_le16(SMB_QUERY_FS_SIZE_INFO
);
4308 pSMB
->hdr
.smb_buf_length
+= byte_count
;
4309 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
4311 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
4312 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
4314 cFYI(1, ("Send error in QFSInfo = %d", rc
));
4315 } else { /* decode response */
4316 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
4318 if (rc
|| (pSMBr
->ByteCount
< 24))
4319 rc
= -EIO
; /* bad smb */
4321 __u16 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
4325 *) (((char *) &pSMBr
->hdr
.Protocol
) +
4328 le32_to_cpu(response_data
->BytesPerSector
) *
4329 le32_to_cpu(response_data
->
4330 SectorsPerAllocationUnit
);
4332 le64_to_cpu(response_data
->TotalAllocationUnits
);
4333 FSData
->f_bfree
= FSData
->f_bavail
=
4334 le64_to_cpu(response_data
->FreeAllocationUnits
);
4336 ("Blocks: %lld Free: %lld Block size %ld",
4337 (unsigned long long)FSData
->f_blocks
,
4338 (unsigned long long)FSData
->f_bfree
,
4342 cifs_buf_release(pSMB
);
4351 CIFSSMBQFSAttributeInfo(const int xid
, struct cifsTconInfo
*tcon
)
4353 /* level 0x105 SMB_QUERY_FILE_SYSTEM_INFO */
4354 TRANSACTION2_QFSI_REQ
*pSMB
= NULL
;
4355 TRANSACTION2_QFSI_RSP
*pSMBr
= NULL
;
4356 FILE_SYSTEM_ATTRIBUTE_INFO
*response_data
;
4358 int bytes_returned
= 0;
4359 __u16 params
, byte_count
;
4361 cFYI(1, ("In QFSAttributeInfo"));
4363 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
4368 params
= 2; /* level */
4369 pSMB
->TotalDataCount
= 0;
4370 pSMB
->MaxParameterCount
= cpu_to_le16(2);
4371 /* BB find exact max SMB PDU from sess structure BB */
4372 pSMB
->MaxDataCount
= cpu_to_le16(1000);
4373 pSMB
->MaxSetupCount
= 0;
4377 pSMB
->Reserved2
= 0;
4378 byte_count
= params
+ 1 /* pad */ ;
4379 pSMB
->TotalParameterCount
= cpu_to_le16(params
);
4380 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
4381 pSMB
->ParameterOffset
= cpu_to_le16(offsetof(
4382 struct smb_com_transaction2_qfsi_req
, InformationLevel
) - 4);
4383 pSMB
->DataCount
= 0;
4384 pSMB
->DataOffset
= 0;
4385 pSMB
->SetupCount
= 1;
4386 pSMB
->Reserved3
= 0;
4387 pSMB
->SubCommand
= cpu_to_le16(TRANS2_QUERY_FS_INFORMATION
);
4388 pSMB
->InformationLevel
= cpu_to_le16(SMB_QUERY_FS_ATTRIBUTE_INFO
);
4389 pSMB
->hdr
.smb_buf_length
+= byte_count
;
4390 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
4392 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
4393 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
4395 cERROR(1, ("Send error in QFSAttributeInfo = %d", rc
));
4396 } else { /* decode response */
4397 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
4399 if (rc
|| (pSMBr
->ByteCount
< 13)) {
4400 /* BB also check if enough bytes returned */
4401 rc
= -EIO
; /* bad smb */
4403 __u16 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
4405 (FILE_SYSTEM_ATTRIBUTE_INFO
4406 *) (((char *) &pSMBr
->hdr
.Protocol
) +
4408 memcpy(&tcon
->fsAttrInfo
, response_data
,
4409 sizeof(FILE_SYSTEM_ATTRIBUTE_INFO
));
4412 cifs_buf_release(pSMB
);
4415 goto QFSAttributeRetry
;
4421 CIFSSMBQFSDeviceInfo(const int xid
, struct cifsTconInfo
*tcon
)
4423 /* level 0x104 SMB_QUERY_FILE_SYSTEM_INFO */
4424 TRANSACTION2_QFSI_REQ
*pSMB
= NULL
;
4425 TRANSACTION2_QFSI_RSP
*pSMBr
= NULL
;
4426 FILE_SYSTEM_DEVICE_INFO
*response_data
;
4428 int bytes_returned
= 0;
4429 __u16 params
, byte_count
;
4431 cFYI(1, ("In QFSDeviceInfo"));
4433 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
4438 params
= 2; /* level */
4439 pSMB
->TotalDataCount
= 0;
4440 pSMB
->MaxParameterCount
= cpu_to_le16(2);
4441 /* BB find exact max SMB PDU from sess structure BB */
4442 pSMB
->MaxDataCount
= cpu_to_le16(1000);
4443 pSMB
->MaxSetupCount
= 0;
4447 pSMB
->Reserved2
= 0;
4448 byte_count
= params
+ 1 /* pad */ ;
4449 pSMB
->TotalParameterCount
= cpu_to_le16(params
);
4450 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
4451 pSMB
->ParameterOffset
= cpu_to_le16(offsetof(
4452 struct smb_com_transaction2_qfsi_req
, InformationLevel
) - 4);
4454 pSMB
->DataCount
= 0;
4455 pSMB
->DataOffset
= 0;
4456 pSMB
->SetupCount
= 1;
4457 pSMB
->Reserved3
= 0;
4458 pSMB
->SubCommand
= cpu_to_le16(TRANS2_QUERY_FS_INFORMATION
);
4459 pSMB
->InformationLevel
= cpu_to_le16(SMB_QUERY_FS_DEVICE_INFO
);
4460 pSMB
->hdr
.smb_buf_length
+= byte_count
;
4461 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
4463 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
4464 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
4466 cFYI(1, ("Send error in QFSDeviceInfo = %d", rc
));
4467 } else { /* decode response */
4468 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
4470 if (rc
|| (pSMBr
->ByteCount
< sizeof(FILE_SYSTEM_DEVICE_INFO
)))
4471 rc
= -EIO
; /* bad smb */
4473 __u16 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
4475 (FILE_SYSTEM_DEVICE_INFO
*)
4476 (((char *) &pSMBr
->hdr
.Protocol
) +
4478 memcpy(&tcon
->fsDevInfo
, response_data
,
4479 sizeof(FILE_SYSTEM_DEVICE_INFO
));
4482 cifs_buf_release(pSMB
);
4485 goto QFSDeviceRetry
;
4491 CIFSSMBQFSUnixInfo(const int xid
, struct cifsTconInfo
*tcon
)
4493 /* level 0x200 SMB_QUERY_CIFS_UNIX_INFO */
4494 TRANSACTION2_QFSI_REQ
*pSMB
= NULL
;
4495 TRANSACTION2_QFSI_RSP
*pSMBr
= NULL
;
4496 FILE_SYSTEM_UNIX_INFO
*response_data
;
4498 int bytes_returned
= 0;
4499 __u16 params
, byte_count
;
4501 cFYI(1, ("In QFSUnixInfo"));
4503 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
4508 params
= 2; /* level */
4509 pSMB
->TotalDataCount
= 0;
4510 pSMB
->DataCount
= 0;
4511 pSMB
->DataOffset
= 0;
4512 pSMB
->MaxParameterCount
= cpu_to_le16(2);
4513 /* BB find exact max SMB PDU from sess structure BB */
4514 pSMB
->MaxDataCount
= cpu_to_le16(100);
4515 pSMB
->MaxSetupCount
= 0;
4519 pSMB
->Reserved2
= 0;
4520 byte_count
= params
+ 1 /* pad */ ;
4521 pSMB
->ParameterCount
= cpu_to_le16(params
);
4522 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
4523 pSMB
->ParameterOffset
= cpu_to_le16(offsetof(struct
4524 smb_com_transaction2_qfsi_req
, InformationLevel
) - 4);
4525 pSMB
->SetupCount
= 1;
4526 pSMB
->Reserved3
= 0;
4527 pSMB
->SubCommand
= cpu_to_le16(TRANS2_QUERY_FS_INFORMATION
);
4528 pSMB
->InformationLevel
= cpu_to_le16(SMB_QUERY_CIFS_UNIX_INFO
);
4529 pSMB
->hdr
.smb_buf_length
+= byte_count
;
4530 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
4532 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
4533 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
4535 cERROR(1, ("Send error in QFSUnixInfo = %d", rc
));
4536 } else { /* decode response */
4537 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
4539 if (rc
|| (pSMBr
->ByteCount
< 13)) {
4540 rc
= -EIO
; /* bad smb */
4542 __u16 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
4544 (FILE_SYSTEM_UNIX_INFO
4545 *) (((char *) &pSMBr
->hdr
.Protocol
) +
4547 memcpy(&tcon
->fsUnixInfo
, response_data
,
4548 sizeof(FILE_SYSTEM_UNIX_INFO
));
4551 cifs_buf_release(pSMB
);
4561 CIFSSMBSetFSUnixInfo(const int xid
, struct cifsTconInfo
*tcon
, __u64 cap
)
4563 /* level 0x200 SMB_SET_CIFS_UNIX_INFO */
4564 TRANSACTION2_SETFSI_REQ
*pSMB
= NULL
;
4565 TRANSACTION2_SETFSI_RSP
*pSMBr
= NULL
;
4567 int bytes_returned
= 0;
4568 __u16 params
, param_offset
, offset
, byte_count
;
4570 cFYI(1, ("In SETFSUnixInfo"));
4572 /* BB switch to small buf init to save memory */
4573 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
4578 params
= 4; /* 2 bytes zero followed by info level. */
4579 pSMB
->MaxSetupCount
= 0;
4583 pSMB
->Reserved2
= 0;
4584 param_offset
= offsetof(struct smb_com_transaction2_setfsi_req
, FileNum
)
4586 offset
= param_offset
+ params
;
4588 pSMB
->MaxParameterCount
= cpu_to_le16(4);
4589 /* BB find exact max SMB PDU from sess structure BB */
4590 pSMB
->MaxDataCount
= cpu_to_le16(100);
4591 pSMB
->SetupCount
= 1;
4592 pSMB
->Reserved3
= 0;
4593 pSMB
->SubCommand
= cpu_to_le16(TRANS2_SET_FS_INFORMATION
);
4594 byte_count
= 1 /* pad */ + params
+ 12;
4596 pSMB
->DataCount
= cpu_to_le16(12);
4597 pSMB
->ParameterCount
= cpu_to_le16(params
);
4598 pSMB
->TotalDataCount
= pSMB
->DataCount
;
4599 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
4600 pSMB
->ParameterOffset
= cpu_to_le16(param_offset
);
4601 pSMB
->DataOffset
= cpu_to_le16(offset
);
4605 pSMB
->InformationLevel
= cpu_to_le16(SMB_SET_CIFS_UNIX_INFO
);
4608 pSMB
->ClientUnixMajor
= cpu_to_le16(CIFS_UNIX_MAJOR_VERSION
);
4609 pSMB
->ClientUnixMinor
= cpu_to_le16(CIFS_UNIX_MINOR_VERSION
);
4610 pSMB
->ClientUnixCap
= cpu_to_le64(cap
);
4612 pSMB
->hdr
.smb_buf_length
+= byte_count
;
4613 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
4615 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
4616 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
4618 cERROR(1, ("Send error in SETFSUnixInfo = %d", rc
));
4619 } else { /* decode response */
4620 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
4622 rc
= -EIO
; /* bad smb */
4624 cifs_buf_release(pSMB
);
4627 goto SETFSUnixRetry
;
4635 CIFSSMBQFSPosixInfo(const int xid
, struct cifsTconInfo
*tcon
,
4636 struct kstatfs
*FSData
)
4638 /* level 0x201 SMB_QUERY_CIFS_POSIX_INFO */
4639 TRANSACTION2_QFSI_REQ
*pSMB
= NULL
;
4640 TRANSACTION2_QFSI_RSP
*pSMBr
= NULL
;
4641 FILE_SYSTEM_POSIX_INFO
*response_data
;
4643 int bytes_returned
= 0;
4644 __u16 params
, byte_count
;
4646 cFYI(1, ("In QFSPosixInfo"));
4648 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
4653 params
= 2; /* level */
4654 pSMB
->TotalDataCount
= 0;
4655 pSMB
->DataCount
= 0;
4656 pSMB
->DataOffset
= 0;
4657 pSMB
->MaxParameterCount
= cpu_to_le16(2);
4658 /* BB find exact max SMB PDU from sess structure BB */
4659 pSMB
->MaxDataCount
= cpu_to_le16(100);
4660 pSMB
->MaxSetupCount
= 0;
4664 pSMB
->Reserved2
= 0;
4665 byte_count
= params
+ 1 /* pad */ ;
4666 pSMB
->ParameterCount
= cpu_to_le16(params
);
4667 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
4668 pSMB
->ParameterOffset
= cpu_to_le16(offsetof(struct
4669 smb_com_transaction2_qfsi_req
, InformationLevel
) - 4);
4670 pSMB
->SetupCount
= 1;
4671 pSMB
->Reserved3
= 0;
4672 pSMB
->SubCommand
= cpu_to_le16(TRANS2_QUERY_FS_INFORMATION
);
4673 pSMB
->InformationLevel
= cpu_to_le16(SMB_QUERY_POSIX_FS_INFO
);
4674 pSMB
->hdr
.smb_buf_length
+= byte_count
;
4675 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
4677 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
4678 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
4680 cFYI(1, ("Send error in QFSUnixInfo = %d", rc
));
4681 } else { /* decode response */
4682 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
4684 if (rc
|| (pSMBr
->ByteCount
< 13)) {
4685 rc
= -EIO
; /* bad smb */
4687 __u16 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
4689 (FILE_SYSTEM_POSIX_INFO
4690 *) (((char *) &pSMBr
->hdr
.Protocol
) +
4693 le32_to_cpu(response_data
->BlockSize
);
4695 le64_to_cpu(response_data
->TotalBlocks
);
4697 le64_to_cpu(response_data
->BlocksAvail
);
4698 if (response_data
->UserBlocksAvail
== cpu_to_le64(-1)) {
4699 FSData
->f_bavail
= FSData
->f_bfree
;
4702 le64_to_cpu(response_data
->UserBlocksAvail
);
4704 if (response_data
->TotalFileNodes
!= cpu_to_le64(-1))
4706 le64_to_cpu(response_data
->TotalFileNodes
);
4707 if (response_data
->FreeFileNodes
!= cpu_to_le64(-1))
4709 le64_to_cpu(response_data
->FreeFileNodes
);
4712 cifs_buf_release(pSMB
);
4721 /* We can not use write of zero bytes trick to
4722 set file size due to need for large file support. Also note that
4723 this SetPathInfo is preferred to SetFileInfo based method in next
4724 routine which is only needed to work around a sharing violation bug
4725 in Samba which this routine can run into */
4728 CIFSSMBSetEOF(const int xid
, struct cifsTconInfo
*tcon
, const char *fileName
,
4729 __u64 size
, bool SetAllocation
,
4730 const struct nls_table
*nls_codepage
, int remap
)
4732 struct smb_com_transaction2_spi_req
*pSMB
= NULL
;
4733 struct smb_com_transaction2_spi_rsp
*pSMBr
= NULL
;
4734 struct file_end_of_file_info
*parm_data
;
4737 int bytes_returned
= 0;
4738 __u16 params
, byte_count
, data_count
, param_offset
, offset
;
4740 cFYI(1, ("In SetEOF"));
4742 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
4747 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
4749 cifsConvertToUCS((__le16
*) pSMB
->FileName
, fileName
,
4750 PATH_MAX
, nls_codepage
, remap
);
4751 name_len
++; /* trailing null */
4753 } else { /* BB improve the check for buffer overruns BB */
4754 name_len
= strnlen(fileName
, PATH_MAX
);
4755 name_len
++; /* trailing null */
4756 strncpy(pSMB
->FileName
, fileName
, name_len
);
4758 params
= 6 + name_len
;
4759 data_count
= sizeof(struct file_end_of_file_info
);
4760 pSMB
->MaxParameterCount
= cpu_to_le16(2);
4761 pSMB
->MaxDataCount
= cpu_to_le16(4100);
4762 pSMB
->MaxSetupCount
= 0;
4766 pSMB
->Reserved2
= 0;
4767 param_offset
= offsetof(struct smb_com_transaction2_spi_req
,
4768 InformationLevel
) - 4;
4769 offset
= param_offset
+ params
;
4770 if (SetAllocation
) {
4771 if (tcon
->ses
->capabilities
& CAP_INFOLEVEL_PASSTHRU
)
4772 pSMB
->InformationLevel
=
4773 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2
);
4775 pSMB
->InformationLevel
=
4776 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO
);
4777 } else /* Set File Size */ {
4778 if (tcon
->ses
->capabilities
& CAP_INFOLEVEL_PASSTHRU
)
4779 pSMB
->InformationLevel
=
4780 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO2
);
4782 pSMB
->InformationLevel
=
4783 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO
);
4787 (struct file_end_of_file_info
*) (((char *) &pSMB
->hdr
.Protocol
) +
4789 pSMB
->ParameterOffset
= cpu_to_le16(param_offset
);
4790 pSMB
->DataOffset
= cpu_to_le16(offset
);
4791 pSMB
->SetupCount
= 1;
4792 pSMB
->Reserved3
= 0;
4793 pSMB
->SubCommand
= cpu_to_le16(TRANS2_SET_PATH_INFORMATION
);
4794 byte_count
= 3 /* pad */ + params
+ data_count
;
4795 pSMB
->DataCount
= cpu_to_le16(data_count
);
4796 pSMB
->TotalDataCount
= pSMB
->DataCount
;
4797 pSMB
->ParameterCount
= cpu_to_le16(params
);
4798 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
4799 pSMB
->Reserved4
= 0;
4800 pSMB
->hdr
.smb_buf_length
+= byte_count
;
4801 parm_data
->FileSize
= cpu_to_le64(size
);
4802 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
4803 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
4804 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
4806 cFYI(1, ("SetPathInfo (file size) returned %d", rc
));
4808 cifs_buf_release(pSMB
);
4817 CIFSSMBSetFileSize(const int xid
, struct cifsTconInfo
*tcon
, __u64 size
,
4818 __u16 fid
, __u32 pid_of_opener
, bool SetAllocation
)
4820 struct smb_com_transaction2_sfi_req
*pSMB
= NULL
;
4822 struct file_end_of_file_info
*parm_data
;
4824 __u16 params
, param_offset
, offset
, byte_count
, count
;
4826 cFYI(1, ("SetFileSize (via SetFileInfo) %lld",
4828 rc
= small_smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
);
4833 pSMB
->hdr
.Pid
= cpu_to_le16((__u16
)pid_of_opener
);
4834 pSMB
->hdr
.PidHigh
= cpu_to_le16((__u16
)(pid_of_opener
>> 16));
4837 pSMB
->MaxSetupCount
= 0;
4841 pSMB
->Reserved2
= 0;
4842 param_offset
= offsetof(struct smb_com_transaction2_sfi_req
, Fid
) - 4;
4843 offset
= param_offset
+ params
;
4845 data_offset
= (char *) (&pSMB
->hdr
.Protocol
) + offset
;
4847 count
= sizeof(struct file_end_of_file_info
);
4848 pSMB
->MaxParameterCount
= cpu_to_le16(2);
4849 /* BB find exact max SMB PDU from sess structure BB */
4850 pSMB
->MaxDataCount
= cpu_to_le16(1000);
4851 pSMB
->SetupCount
= 1;
4852 pSMB
->Reserved3
= 0;
4853 pSMB
->SubCommand
= cpu_to_le16(TRANS2_SET_FILE_INFORMATION
);
4854 byte_count
= 3 /* pad */ + params
+ count
;
4855 pSMB
->DataCount
= cpu_to_le16(count
);
4856 pSMB
->ParameterCount
= cpu_to_le16(params
);
4857 pSMB
->TotalDataCount
= pSMB
->DataCount
;
4858 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
4859 pSMB
->ParameterOffset
= cpu_to_le16(param_offset
);
4861 (struct file_end_of_file_info
*) (((char *) &pSMB
->hdr
.Protocol
)
4863 pSMB
->DataOffset
= cpu_to_le16(offset
);
4864 parm_data
->FileSize
= cpu_to_le64(size
);
4866 if (SetAllocation
) {
4867 if (tcon
->ses
->capabilities
& CAP_INFOLEVEL_PASSTHRU
)
4868 pSMB
->InformationLevel
=
4869 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2
);
4871 pSMB
->InformationLevel
=
4872 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO
);
4873 } else /* Set File Size */ {
4874 if (tcon
->ses
->capabilities
& CAP_INFOLEVEL_PASSTHRU
)
4875 pSMB
->InformationLevel
=
4876 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO2
);
4878 pSMB
->InformationLevel
=
4879 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO
);
4881 pSMB
->Reserved4
= 0;
4882 pSMB
->hdr
.smb_buf_length
+= byte_count
;
4883 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
4884 rc
= SendReceiveNoRsp(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
, 0);
4887 ("Send error in SetFileInfo (SetFileSize) = %d",
4891 /* Note: On -EAGAIN error only caller can retry on handle based calls
4892 since file handle passed in no longer valid */
4897 /* Some legacy servers such as NT4 require that the file times be set on
4898 an open handle, rather than by pathname - this is awkward due to
4899 potential access conflicts on the open, but it is unavoidable for these
4900 old servers since the only other choice is to go from 100 nanosecond DCE
4901 time and resort to the original setpathinfo level which takes the ancient
4902 DOS time format with 2 second granularity */
4904 CIFSSMBSetFileInfo(const int xid
, struct cifsTconInfo
*tcon
,
4905 const FILE_BASIC_INFO
*data
, __u16 fid
, __u32 pid_of_opener
)
4907 struct smb_com_transaction2_sfi_req
*pSMB
= NULL
;
4910 __u16 params
, param_offset
, offset
, byte_count
, count
;
4912 cFYI(1, ("Set Times (via SetFileInfo)"));
4913 rc
= small_smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
);
4918 pSMB
->hdr
.Pid
= cpu_to_le16((__u16
)pid_of_opener
);
4919 pSMB
->hdr
.PidHigh
= cpu_to_le16((__u16
)(pid_of_opener
>> 16));
4922 pSMB
->MaxSetupCount
= 0;
4926 pSMB
->Reserved2
= 0;
4927 param_offset
= offsetof(struct smb_com_transaction2_sfi_req
, Fid
) - 4;
4928 offset
= param_offset
+ params
;
4930 data_offset
= (char *) (&pSMB
->hdr
.Protocol
) + offset
;
4932 count
= sizeof(FILE_BASIC_INFO
);
4933 pSMB
->MaxParameterCount
= cpu_to_le16(2);
4934 /* BB find max SMB PDU from sess */
4935 pSMB
->MaxDataCount
= cpu_to_le16(1000);
4936 pSMB
->SetupCount
= 1;
4937 pSMB
->Reserved3
= 0;
4938 pSMB
->SubCommand
= cpu_to_le16(TRANS2_SET_FILE_INFORMATION
);
4939 byte_count
= 3 /* pad */ + params
+ count
;
4940 pSMB
->DataCount
= cpu_to_le16(count
);
4941 pSMB
->ParameterCount
= cpu_to_le16(params
);
4942 pSMB
->TotalDataCount
= pSMB
->DataCount
;
4943 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
4944 pSMB
->ParameterOffset
= cpu_to_le16(param_offset
);
4945 pSMB
->DataOffset
= cpu_to_le16(offset
);
4947 if (tcon
->ses
->capabilities
& CAP_INFOLEVEL_PASSTHRU
)
4948 pSMB
->InformationLevel
= cpu_to_le16(SMB_SET_FILE_BASIC_INFO2
);
4950 pSMB
->InformationLevel
= cpu_to_le16(SMB_SET_FILE_BASIC_INFO
);
4951 pSMB
->Reserved4
= 0;
4952 pSMB
->hdr
.smb_buf_length
+= byte_count
;
4953 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
4954 memcpy(data_offset
, data
, sizeof(FILE_BASIC_INFO
));
4955 rc
= SendReceiveNoRsp(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
, 0);
4957 cFYI(1, ("Send error in Set Time (SetFileInfo) = %d", rc
));
4959 /* Note: On -EAGAIN error only caller can retry on handle based calls
4960 since file handle passed in no longer valid */
4966 CIFSSMBSetFileDisposition(const int xid
, struct cifsTconInfo
*tcon
,
4967 bool delete_file
, __u16 fid
, __u32 pid_of_opener
)
4969 struct smb_com_transaction2_sfi_req
*pSMB
= NULL
;
4972 __u16 params
, param_offset
, offset
, byte_count
, count
;
4974 cFYI(1, ("Set File Disposition (via SetFileInfo)"));
4975 rc
= small_smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
);
4980 pSMB
->hdr
.Pid
= cpu_to_le16((__u16
)pid_of_opener
);
4981 pSMB
->hdr
.PidHigh
= cpu_to_le16((__u16
)(pid_of_opener
>> 16));
4984 pSMB
->MaxSetupCount
= 0;
4988 pSMB
->Reserved2
= 0;
4989 param_offset
= offsetof(struct smb_com_transaction2_sfi_req
, Fid
) - 4;
4990 offset
= param_offset
+ params
;
4992 data_offset
= (char *) (&pSMB
->hdr
.Protocol
) + offset
;
4995 pSMB
->MaxParameterCount
= cpu_to_le16(2);
4996 /* BB find max SMB PDU from sess */
4997 pSMB
->MaxDataCount
= cpu_to_le16(1000);
4998 pSMB
->SetupCount
= 1;
4999 pSMB
->Reserved3
= 0;
5000 pSMB
->SubCommand
= cpu_to_le16(TRANS2_SET_FILE_INFORMATION
);
5001 byte_count
= 3 /* pad */ + params
+ count
;
5002 pSMB
->DataCount
= cpu_to_le16(count
);
5003 pSMB
->ParameterCount
= cpu_to_le16(params
);
5004 pSMB
->TotalDataCount
= pSMB
->DataCount
;
5005 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
5006 pSMB
->ParameterOffset
= cpu_to_le16(param_offset
);
5007 pSMB
->DataOffset
= cpu_to_le16(offset
);
5009 pSMB
->InformationLevel
= cpu_to_le16(SMB_SET_FILE_DISPOSITION_INFO
);
5010 pSMB
->Reserved4
= 0;
5011 pSMB
->hdr
.smb_buf_length
+= byte_count
;
5012 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
5013 *data_offset
= delete_file
? 1 : 0;
5014 rc
= SendReceiveNoRsp(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
, 0);
5016 cFYI(1, ("Send error in SetFileDisposition = %d", rc
));
5022 CIFSSMBSetPathInfo(const int xid
, struct cifsTconInfo
*tcon
,
5023 const char *fileName
, const FILE_BASIC_INFO
*data
,
5024 const struct nls_table
*nls_codepage
, int remap
)
5026 TRANSACTION2_SPI_REQ
*pSMB
= NULL
;
5027 TRANSACTION2_SPI_RSP
*pSMBr
= NULL
;
5030 int bytes_returned
= 0;
5032 __u16 params
, param_offset
, offset
, byte_count
, count
;
5034 cFYI(1, ("In SetTimes"));
5037 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
5042 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
5044 cifsConvertToUCS((__le16
*) pSMB
->FileName
, fileName
,
5045 PATH_MAX
, nls_codepage
, remap
);
5046 name_len
++; /* trailing null */
5048 } else { /* BB improve the check for buffer overruns BB */
5049 name_len
= strnlen(fileName
, PATH_MAX
);
5050 name_len
++; /* trailing null */
5051 strncpy(pSMB
->FileName
, fileName
, name_len
);
5054 params
= 6 + name_len
;
5055 count
= sizeof(FILE_BASIC_INFO
);
5056 pSMB
->MaxParameterCount
= cpu_to_le16(2);
5057 /* BB find max SMB PDU from sess structure BB */
5058 pSMB
->MaxDataCount
= cpu_to_le16(1000);
5059 pSMB
->MaxSetupCount
= 0;
5063 pSMB
->Reserved2
= 0;
5064 param_offset
= offsetof(struct smb_com_transaction2_spi_req
,
5065 InformationLevel
) - 4;
5066 offset
= param_offset
+ params
;
5067 data_offset
= (char *) (&pSMB
->hdr
.Protocol
) + offset
;
5068 pSMB
->ParameterOffset
= cpu_to_le16(param_offset
);
5069 pSMB
->DataOffset
= cpu_to_le16(offset
);
5070 pSMB
->SetupCount
= 1;
5071 pSMB
->Reserved3
= 0;
5072 pSMB
->SubCommand
= cpu_to_le16(TRANS2_SET_PATH_INFORMATION
);
5073 byte_count
= 3 /* pad */ + params
+ count
;
5075 pSMB
->DataCount
= cpu_to_le16(count
);
5076 pSMB
->ParameterCount
= cpu_to_le16(params
);
5077 pSMB
->TotalDataCount
= pSMB
->DataCount
;
5078 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
5079 if (tcon
->ses
->capabilities
& CAP_INFOLEVEL_PASSTHRU
)
5080 pSMB
->InformationLevel
= cpu_to_le16(SMB_SET_FILE_BASIC_INFO2
);
5082 pSMB
->InformationLevel
= cpu_to_le16(SMB_SET_FILE_BASIC_INFO
);
5083 pSMB
->Reserved4
= 0;
5084 pSMB
->hdr
.smb_buf_length
+= byte_count
;
5085 memcpy(data_offset
, data
, sizeof(FILE_BASIC_INFO
));
5086 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
5087 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
5088 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
5090 cFYI(1, ("SetPathInfo (times) returned %d", rc
));
5092 cifs_buf_release(pSMB
);
5100 /* Can not be used to set time stamps yet (due to old DOS time format) */
5101 /* Can be used to set attributes */
5102 #if 0 /* Possibly not needed - since it turns out that strangely NT4 has a bug
5103 handling it anyway and NT4 was what we thought it would be needed for
5104 Do not delete it until we prove whether needed for Win9x though */
5106 CIFSSMBSetAttrLegacy(int xid
, struct cifsTconInfo
*tcon
, char *fileName
,
5107 __u16 dos_attrs
, const struct nls_table
*nls_codepage
)
5109 SETATTR_REQ
*pSMB
= NULL
;
5110 SETATTR_RSP
*pSMBr
= NULL
;
5115 cFYI(1, ("In SetAttrLegacy"));
5118 rc
= smb_init(SMB_COM_SETATTR
, 8, tcon
, (void **) &pSMB
,
5123 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
5125 ConvertToUCS((__le16
*) pSMB
->fileName
, fileName
,
5126 PATH_MAX
, nls_codepage
);
5127 name_len
++; /* trailing null */
5129 } else { /* BB improve the check for buffer overruns BB */
5130 name_len
= strnlen(fileName
, PATH_MAX
);
5131 name_len
++; /* trailing null */
5132 strncpy(pSMB
->fileName
, fileName
, name_len
);
5134 pSMB
->attr
= cpu_to_le16(dos_attrs
);
5135 pSMB
->BufferFormat
= 0x04;
5136 pSMB
->hdr
.smb_buf_length
+= name_len
+ 1;
5137 pSMB
->ByteCount
= cpu_to_le16(name_len
+ 1);
5138 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
5139 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
5141 cFYI(1, ("Error in LegacySetAttr = %d", rc
));
5143 cifs_buf_release(pSMB
);
5146 goto SetAttrLgcyRetry
;
5150 #endif /* temporarily unneeded SetAttr legacy function */
5153 cifs_fill_unix_set_info(FILE_UNIX_BASIC_INFO
*data_offset
,
5154 const struct cifs_unix_set_info_args
*args
)
5156 u64 mode
= args
->mode
;
5159 * Samba server ignores set of file size to zero due to bugs in some
5160 * older clients, but we should be precise - we use SetFileSize to
5161 * set file size and do not want to truncate file size to zero
5162 * accidently as happened on one Samba server beta by putting
5163 * zero instead of -1 here
5165 data_offset
->EndOfFile
= cpu_to_le64(NO_CHANGE_64
);
5166 data_offset
->NumOfBytes
= cpu_to_le64(NO_CHANGE_64
);
5167 data_offset
->LastStatusChange
= cpu_to_le64(args
->ctime
);
5168 data_offset
->LastAccessTime
= cpu_to_le64(args
->atime
);
5169 data_offset
->LastModificationTime
= cpu_to_le64(args
->mtime
);
5170 data_offset
->Uid
= cpu_to_le64(args
->uid
);
5171 data_offset
->Gid
= cpu_to_le64(args
->gid
);
5172 /* better to leave device as zero when it is */
5173 data_offset
->DevMajor
= cpu_to_le64(MAJOR(args
->device
));
5174 data_offset
->DevMinor
= cpu_to_le64(MINOR(args
->device
));
5175 data_offset
->Permissions
= cpu_to_le64(mode
);
5178 data_offset
->Type
= cpu_to_le32(UNIX_FILE
);
5179 else if (S_ISDIR(mode
))
5180 data_offset
->Type
= cpu_to_le32(UNIX_DIR
);
5181 else if (S_ISLNK(mode
))
5182 data_offset
->Type
= cpu_to_le32(UNIX_SYMLINK
);
5183 else if (S_ISCHR(mode
))
5184 data_offset
->Type
= cpu_to_le32(UNIX_CHARDEV
);
5185 else if (S_ISBLK(mode
))
5186 data_offset
->Type
= cpu_to_le32(UNIX_BLOCKDEV
);
5187 else if (S_ISFIFO(mode
))
5188 data_offset
->Type
= cpu_to_le32(UNIX_FIFO
);
5189 else if (S_ISSOCK(mode
))
5190 data_offset
->Type
= cpu_to_le32(UNIX_SOCKET
);
5194 CIFSSMBUnixSetFileInfo(const int xid
, struct cifsTconInfo
*tcon
,
5195 const struct cifs_unix_set_info_args
*args
,
5196 u16 fid
, u32 pid_of_opener
)
5198 struct smb_com_transaction2_sfi_req
*pSMB
= NULL
;
5199 FILE_UNIX_BASIC_INFO
*data_offset
;
5201 u16 params
, param_offset
, offset
, byte_count
, count
;
5203 cFYI(1, ("Set Unix Info (via SetFileInfo)"));
5204 rc
= small_smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
);
5209 pSMB
->hdr
.Pid
= cpu_to_le16((__u16
)pid_of_opener
);
5210 pSMB
->hdr
.PidHigh
= cpu_to_le16((__u16
)(pid_of_opener
>> 16));
5213 pSMB
->MaxSetupCount
= 0;
5217 pSMB
->Reserved2
= 0;
5218 param_offset
= offsetof(struct smb_com_transaction2_sfi_req
, Fid
) - 4;
5219 offset
= param_offset
+ params
;
5221 data_offset
= (FILE_UNIX_BASIC_INFO
*)
5222 ((char *)(&pSMB
->hdr
.Protocol
) + offset
);
5223 count
= sizeof(FILE_UNIX_BASIC_INFO
);
5225 pSMB
->MaxParameterCount
= cpu_to_le16(2);
5226 /* BB find max SMB PDU from sess */
5227 pSMB
->MaxDataCount
= cpu_to_le16(1000);
5228 pSMB
->SetupCount
= 1;
5229 pSMB
->Reserved3
= 0;
5230 pSMB
->SubCommand
= cpu_to_le16(TRANS2_SET_FILE_INFORMATION
);
5231 byte_count
= 3 /* pad */ + params
+ count
;
5232 pSMB
->DataCount
= cpu_to_le16(count
);
5233 pSMB
->ParameterCount
= cpu_to_le16(params
);
5234 pSMB
->TotalDataCount
= pSMB
->DataCount
;
5235 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
5236 pSMB
->ParameterOffset
= cpu_to_le16(param_offset
);
5237 pSMB
->DataOffset
= cpu_to_le16(offset
);
5239 pSMB
->InformationLevel
= cpu_to_le16(SMB_SET_FILE_UNIX_BASIC
);
5240 pSMB
->Reserved4
= 0;
5241 pSMB
->hdr
.smb_buf_length
+= byte_count
;
5242 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
5244 cifs_fill_unix_set_info(data_offset
, args
);
5246 rc
= SendReceiveNoRsp(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
, 0);
5248 cFYI(1, ("Send error in Set Time (SetFileInfo) = %d", rc
));
5250 /* Note: On -EAGAIN error only caller can retry on handle based calls
5251 since file handle passed in no longer valid */
5257 CIFSSMBUnixSetPathInfo(const int xid
, struct cifsTconInfo
*tcon
, char *fileName
,
5258 const struct cifs_unix_set_info_args
*args
,
5259 const struct nls_table
*nls_codepage
, int remap
)
5261 TRANSACTION2_SPI_REQ
*pSMB
= NULL
;
5262 TRANSACTION2_SPI_RSP
*pSMBr
= NULL
;
5265 int bytes_returned
= 0;
5266 FILE_UNIX_BASIC_INFO
*data_offset
;
5267 __u16 params
, param_offset
, offset
, count
, byte_count
;
5269 cFYI(1, ("In SetUID/GID/Mode"));
5271 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
5276 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
5278 cifsConvertToUCS((__le16
*) pSMB
->FileName
, fileName
,
5279 PATH_MAX
, nls_codepage
, remap
);
5280 name_len
++; /* trailing null */
5282 } else { /* BB improve the check for buffer overruns BB */
5283 name_len
= strnlen(fileName
, PATH_MAX
);
5284 name_len
++; /* trailing null */
5285 strncpy(pSMB
->FileName
, fileName
, name_len
);
5288 params
= 6 + name_len
;
5289 count
= sizeof(FILE_UNIX_BASIC_INFO
);
5290 pSMB
->MaxParameterCount
= cpu_to_le16(2);
5291 /* BB find max SMB PDU from sess structure BB */
5292 pSMB
->MaxDataCount
= cpu_to_le16(1000);
5293 pSMB
->MaxSetupCount
= 0;
5297 pSMB
->Reserved2
= 0;
5298 param_offset
= offsetof(struct smb_com_transaction2_spi_req
,
5299 InformationLevel
) - 4;
5300 offset
= param_offset
+ params
;
5302 (FILE_UNIX_BASIC_INFO
*) ((char *) &pSMB
->hdr
.Protocol
+
5304 memset(data_offset
, 0, count
);
5305 pSMB
->DataOffset
= cpu_to_le16(offset
);
5306 pSMB
->ParameterOffset
= cpu_to_le16(param_offset
);
5307 pSMB
->SetupCount
= 1;
5308 pSMB
->Reserved3
= 0;
5309 pSMB
->SubCommand
= cpu_to_le16(TRANS2_SET_PATH_INFORMATION
);
5310 byte_count
= 3 /* pad */ + params
+ count
;
5311 pSMB
->ParameterCount
= cpu_to_le16(params
);
5312 pSMB
->DataCount
= cpu_to_le16(count
);
5313 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
5314 pSMB
->TotalDataCount
= pSMB
->DataCount
;
5315 pSMB
->InformationLevel
= cpu_to_le16(SMB_SET_FILE_UNIX_BASIC
);
5316 pSMB
->Reserved4
= 0;
5317 pSMB
->hdr
.smb_buf_length
+= byte_count
;
5319 cifs_fill_unix_set_info(data_offset
, args
);
5321 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
5322 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
5323 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
5325 cFYI(1, ("SetPathInfo (perms) returned %d", rc
));
5327 cifs_buf_release(pSMB
);
5333 int CIFSSMBNotify(const int xid
, struct cifsTconInfo
*tcon
,
5334 const int notify_subdirs
, const __u16 netfid
,
5335 __u32 filter
, struct file
*pfile
, int multishot
,
5336 const struct nls_table
*nls_codepage
)
5339 struct smb_com_transaction_change_notify_req
*pSMB
= NULL
;
5340 struct smb_com_ntransaction_change_notify_rsp
*pSMBr
= NULL
;
5341 struct dir_notify_req
*dnotify_req
;
5344 cFYI(1, ("In CIFSSMBNotify for file handle %d", (int)netfid
));
5345 rc
= smb_init(SMB_COM_NT_TRANSACT
, 23, tcon
, (void **) &pSMB
,
5350 pSMB
->TotalParameterCount
= 0 ;
5351 pSMB
->TotalDataCount
= 0;
5352 pSMB
->MaxParameterCount
= cpu_to_le32(2);
5353 /* BB find exact data count max from sess structure BB */
5354 pSMB
->MaxDataCount
= 0; /* same in little endian or be */
5355 /* BB VERIFY verify which is correct for above BB */
5356 pSMB
->MaxDataCount
= cpu_to_le32((tcon
->ses
->server
->maxBuf
-
5357 MAX_CIFS_HDR_SIZE
) & 0xFFFFFF00);
5359 pSMB
->MaxSetupCount
= 4;
5361 pSMB
->ParameterOffset
= 0;
5362 pSMB
->DataCount
= 0;
5363 pSMB
->DataOffset
= 0;
5364 pSMB
->SetupCount
= 4; /* single byte does not need le conversion */
5365 pSMB
->SubCommand
= cpu_to_le16(NT_TRANSACT_NOTIFY_CHANGE
);
5366 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
5368 pSMB
->WatchTree
= 1; /* one byte - no le conversion needed */
5369 pSMB
->Reserved2
= 0;
5370 pSMB
->CompletionFilter
= cpu_to_le32(filter
);
5371 pSMB
->Fid
= netfid
; /* file handle always le */
5372 pSMB
->ByteCount
= 0;
5374 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
5375 (struct smb_hdr
*)pSMBr
, &bytes_returned
,
5378 cFYI(1, ("Error in Notify = %d", rc
));
5380 /* Add file to outstanding requests */
5381 /* BB change to kmem cache alloc */
5382 dnotify_req
= kmalloc(
5383 sizeof(struct dir_notify_req
),
5386 dnotify_req
->Pid
= pSMB
->hdr
.Pid
;
5387 dnotify_req
->PidHigh
= pSMB
->hdr
.PidHigh
;
5388 dnotify_req
->Mid
= pSMB
->hdr
.Mid
;
5389 dnotify_req
->Tid
= pSMB
->hdr
.Tid
;
5390 dnotify_req
->Uid
= pSMB
->hdr
.Uid
;
5391 dnotify_req
->netfid
= netfid
;
5392 dnotify_req
->pfile
= pfile
;
5393 dnotify_req
->filter
= filter
;
5394 dnotify_req
->multishot
= multishot
;
5395 spin_lock(&GlobalMid_Lock
);
5396 list_add_tail(&dnotify_req
->lhead
,
5397 &GlobalDnotifyReqList
);
5398 spin_unlock(&GlobalMid_Lock
);
5402 cifs_buf_release(pSMB
);
5406 #ifdef CONFIG_CIFS_XATTR
5408 * Do a path-based QUERY_ALL_EAS call and parse the result. This is a common
5409 * function used by listxattr and getxattr type calls. When ea_name is set,
5410 * it looks for that attribute name and stuffs that value into the EAData
5411 * buffer. When ea_name is NULL, it stuffs a list of attribute names into the
5412 * buffer. In both cases, the return value is either the length of the
5413 * resulting data or a negative error code. If EAData is a NULL pointer then
5414 * the data isn't copied to it, but the length is returned.
5417 CIFSSMBQAllEAs(const int xid
, struct cifsTconInfo
*tcon
,
5418 const unsigned char *searchName
, const unsigned char *ea_name
,
5419 char *EAData
, size_t buf_size
,
5420 const struct nls_table
*nls_codepage
, int remap
)
5422 /* BB assumes one setup word */
5423 TRANSACTION2_QPI_REQ
*pSMB
= NULL
;
5424 TRANSACTION2_QPI_RSP
*pSMBr
= NULL
;
5428 struct fealist
*ea_response_data
;
5429 struct fea
*temp_fea
;
5432 __u16 params
, byte_count
, data_offset
;
5434 cFYI(1, ("In Query All EAs path %s", searchName
));
5436 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
5441 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
5443 cifsConvertToUCS((__le16
*) pSMB
->FileName
, searchName
,
5444 PATH_MAX
, nls_codepage
, remap
);
5445 list_len
++; /* trailing null */
5447 } else { /* BB improve the check for buffer overruns BB */
5448 list_len
= strnlen(searchName
, PATH_MAX
);
5449 list_len
++; /* trailing null */
5450 strncpy(pSMB
->FileName
, searchName
, list_len
);
5453 params
= 2 /* level */ + 4 /* reserved */ + list_len
/* includes NUL */;
5454 pSMB
->TotalDataCount
= 0;
5455 pSMB
->MaxParameterCount
= cpu_to_le16(2);
5456 /* BB find exact max SMB PDU from sess structure BB */
5457 pSMB
->MaxDataCount
= cpu_to_le16(CIFSMaxBufSize
);
5458 pSMB
->MaxSetupCount
= 0;
5462 pSMB
->Reserved2
= 0;
5463 pSMB
->ParameterOffset
= cpu_to_le16(offsetof(
5464 struct smb_com_transaction2_qpi_req
, InformationLevel
) - 4);
5465 pSMB
->DataCount
= 0;
5466 pSMB
->DataOffset
= 0;
5467 pSMB
->SetupCount
= 1;
5468 pSMB
->Reserved3
= 0;
5469 pSMB
->SubCommand
= cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION
);
5470 byte_count
= params
+ 1 /* pad */ ;
5471 pSMB
->TotalParameterCount
= cpu_to_le16(params
);
5472 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
5473 pSMB
->InformationLevel
= cpu_to_le16(SMB_INFO_QUERY_ALL_EAS
);
5474 pSMB
->Reserved4
= 0;
5475 pSMB
->hdr
.smb_buf_length
+= byte_count
;
5476 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
5478 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
5479 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
5481 cFYI(1, ("Send error in QueryAllEAs = %d", rc
));
5486 /* BB also check enough total bytes returned */
5487 /* BB we need to improve the validity checking
5488 of these trans2 responses */
5490 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
5491 if (rc
|| (pSMBr
->ByteCount
< 4)) {
5492 rc
= -EIO
; /* bad smb */
5496 /* check that length of list is not more than bcc */
5497 /* check that each entry does not go beyond length
5499 /* check that each element of each entry does not
5500 go beyond end of list */
5501 /* validate_trans2_offsets() */
5502 /* BB check if start of smb + data_offset > &bcc+ bcc */
5504 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
5505 ea_response_data
= (struct fealist
*)
5506 (((char *) &pSMBr
->hdr
.Protocol
) + data_offset
);
5508 list_len
= le32_to_cpu(ea_response_data
->list_len
);
5509 cFYI(1, ("ea length %d", list_len
));
5510 if (list_len
<= 8) {
5511 cFYI(1, ("empty EA list returned from server"));
5515 /* make sure list_len doesn't go past end of SMB */
5516 end_of_smb
= (char *)pByteArea(&pSMBr
->hdr
) + BCC(&pSMBr
->hdr
);
5517 if ((char *)ea_response_data
+ list_len
> end_of_smb
) {
5518 cFYI(1, ("EA list appears to go beyond SMB"));
5523 /* account for ea list len */
5525 temp_fea
= ea_response_data
->list
;
5526 temp_ptr
= (char *)temp_fea
;
5527 while (list_len
> 0) {
5528 unsigned int name_len
;
5533 /* make sure we can read name_len and value_len */
5535 cFYI(1, ("EA entry goes beyond length of list"));
5540 name_len
= temp_fea
->name_len
;
5541 value_len
= le16_to_cpu(temp_fea
->value_len
);
5542 list_len
-= name_len
+ 1 + value_len
;
5544 cFYI(1, ("EA entry goes beyond length of list"));
5550 if (strncmp(ea_name
, temp_ptr
, name_len
) == 0) {
5551 temp_ptr
+= name_len
+ 1;
5555 if ((size_t)value_len
> buf_size
) {
5559 memcpy(EAData
, temp_ptr
, value_len
);
5563 /* account for prefix user. and trailing null */
5564 rc
+= (5 + 1 + name_len
);
5565 if (rc
< (int) buf_size
) {
5566 memcpy(EAData
, "user.", 5);
5568 memcpy(EAData
, temp_ptr
, name_len
);
5570 /* null terminate name */
5573 } else if (buf_size
== 0) {
5574 /* skip copy - calc size only */
5576 /* stop before overrun buffer */
5581 temp_ptr
+= name_len
+ 1 + value_len
;
5582 temp_fea
= (struct fea
*)temp_ptr
;
5585 /* didn't find the named attribute */
5590 cifs_buf_release(pSMB
);
5598 CIFSSMBSetEA(const int xid
, struct cifsTconInfo
*tcon
, const char *fileName
,
5599 const char *ea_name
, const void *ea_value
,
5600 const __u16 ea_value_len
, const struct nls_table
*nls_codepage
,
5603 struct smb_com_transaction2_spi_req
*pSMB
= NULL
;
5604 struct smb_com_transaction2_spi_rsp
*pSMBr
= NULL
;
5605 struct fealist
*parm_data
;
5608 int bytes_returned
= 0;
5609 __u16 params
, param_offset
, byte_count
, offset
, count
;
5611 cFYI(1, ("In SetEA"));
5613 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
5618 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
5620 cifsConvertToUCS((__le16
*) pSMB
->FileName
, fileName
,
5621 PATH_MAX
, nls_codepage
, remap
);
5622 name_len
++; /* trailing null */
5624 } else { /* BB improve the check for buffer overruns BB */
5625 name_len
= strnlen(fileName
, PATH_MAX
);
5626 name_len
++; /* trailing null */
5627 strncpy(pSMB
->FileName
, fileName
, name_len
);
5630 params
= 6 + name_len
;
5632 /* done calculating parms using name_len of file name,
5633 now use name_len to calculate length of ea name
5634 we are going to create in the inode xattrs */
5635 if (ea_name
== NULL
)
5638 name_len
= strnlen(ea_name
, 255);
5640 count
= sizeof(*parm_data
) + ea_value_len
+ name_len
;
5641 pSMB
->MaxParameterCount
= cpu_to_le16(2);
5642 /* BB find max SMB PDU from sess */
5643 pSMB
->MaxDataCount
= cpu_to_le16(1000);
5644 pSMB
->MaxSetupCount
= 0;
5648 pSMB
->Reserved2
= 0;
5649 param_offset
= offsetof(struct smb_com_transaction2_spi_req
,
5650 InformationLevel
) - 4;
5651 offset
= param_offset
+ params
;
5652 pSMB
->InformationLevel
=
5653 cpu_to_le16(SMB_SET_FILE_EA
);
5656 (struct fealist
*) (((char *) &pSMB
->hdr
.Protocol
) +
5658 pSMB
->ParameterOffset
= cpu_to_le16(param_offset
);
5659 pSMB
->DataOffset
= cpu_to_le16(offset
);
5660 pSMB
->SetupCount
= 1;
5661 pSMB
->Reserved3
= 0;
5662 pSMB
->SubCommand
= cpu_to_le16(TRANS2_SET_PATH_INFORMATION
);
5663 byte_count
= 3 /* pad */ + params
+ count
;
5664 pSMB
->DataCount
= cpu_to_le16(count
);
5665 parm_data
->list_len
= cpu_to_le32(count
);
5666 parm_data
->list
[0].EA_flags
= 0;
5667 /* we checked above that name len is less than 255 */
5668 parm_data
->list
[0].name_len
= (__u8
)name_len
;
5669 /* EA names are always ASCII */
5671 strncpy(parm_data
->list
[0].name
, ea_name
, name_len
);
5672 parm_data
->list
[0].name
[name_len
] = 0;
5673 parm_data
->list
[0].value_len
= cpu_to_le16(ea_value_len
);
5674 /* caller ensures that ea_value_len is less than 64K but
5675 we need to ensure that it fits within the smb */
5677 /*BB add length check to see if it would fit in
5678 negotiated SMB buffer size BB */
5679 /* if (ea_value_len > buffer_size - 512 (enough for header)) */
5681 memcpy(parm_data
->list
[0].name
+name_len
+1,
5682 ea_value
, ea_value_len
);
5684 pSMB
->TotalDataCount
= pSMB
->DataCount
;
5685 pSMB
->ParameterCount
= cpu_to_le16(params
);
5686 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
5687 pSMB
->Reserved4
= 0;
5688 pSMB
->hdr
.smb_buf_length
+= byte_count
;
5689 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
5690 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
5691 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
5693 cFYI(1, ("SetPathInfo (EA) returned %d", rc
));
5695 cifs_buf_release(pSMB
);