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/slab.h>
34 #include <linux/posix_acl_xattr.h>
35 #include <asm/uaccess.h>
39 #include "cifsproto.h"
40 #include "cifs_unicode.h"
41 #include "cifs_debug.h"
43 #ifdef CONFIG_CIFS_POSIX
48 #ifdef CONFIG_CIFS_WEAK_PW_HASH
49 {LANMAN_PROT
, "\2LM1.2X002"},
50 {LANMAN2_PROT
, "\2LANMAN2.1"},
51 #endif /* weak password hashing for legacy clients */
52 {CIFS_PROT
, "\2NT LM 0.12"},
53 {POSIX_PROT
, "\2POSIX 2"},
61 #ifdef CONFIG_CIFS_WEAK_PW_HASH
62 {LANMAN_PROT
, "\2LM1.2X002"},
63 {LANMAN2_PROT
, "\2LANMAN2.1"},
64 #endif /* weak password hashing for legacy clients */
65 {CIFS_PROT
, "\2NT LM 0.12"},
70 /* define the number of elements in the cifs dialect array */
71 #ifdef CONFIG_CIFS_POSIX
72 #ifdef CONFIG_CIFS_WEAK_PW_HASH
73 #define CIFS_NUM_PROT 4
75 #define CIFS_NUM_PROT 2
76 #endif /* CIFS_WEAK_PW_HASH */
78 #ifdef CONFIG_CIFS_WEAK_PW_HASH
79 #define CIFS_NUM_PROT 3
81 #define CIFS_NUM_PROT 1
82 #endif /* CONFIG_CIFS_WEAK_PW_HASH */
83 #endif /* CIFS_POSIX */
85 /* Mark as invalid, all open files on tree connections since they
86 were closed when session to server was lost */
87 static void mark_open_files_invalid(struct cifsTconInfo
*pTcon
)
89 struct cifsFileInfo
*open_file
= NULL
;
90 struct list_head
*tmp
;
91 struct list_head
*tmp1
;
93 /* list all files open on tree connection and mark them invalid */
94 write_lock(&GlobalSMBSeslock
);
95 list_for_each_safe(tmp
, tmp1
, &pTcon
->openFileList
) {
96 open_file
= list_entry(tmp
, struct cifsFileInfo
, tlist
);
97 open_file
->invalidHandle
= true;
98 open_file
->oplock_break_cancelled
= true;
100 write_unlock(&GlobalSMBSeslock
);
101 /* BB Add call to invalidate_inodes(sb) for all superblocks mounted
105 /* reconnect the socket, tcon, and smb session if needed */
107 cifs_reconnect_tcon(struct cifsTconInfo
*tcon
, int smb_command
)
110 struct cifsSesInfo
*ses
;
111 struct TCP_Server_Info
*server
;
112 struct nls_table
*nls_codepage
;
115 * SMBs NegProt, SessSetup, uLogoff do not have tcon yet so check for
116 * tcp and smb session status done differently for those three - in the
123 server
= ses
->server
;
126 * only tree disconnect, open, and write, (and ulogoff which does not
127 * have tcon) are allowed as we start force umount
129 if (tcon
->tidStatus
== CifsExiting
) {
130 if (smb_command
!= SMB_COM_WRITE_ANDX
&&
131 smb_command
!= SMB_COM_OPEN_ANDX
&&
132 smb_command
!= SMB_COM_TREE_DISCONNECT
) {
133 cFYI(1, ("can not send cmd %d while umounting",
139 if (ses
->status
== CifsExiting
)
143 * Give demultiplex thread up to 10 seconds to reconnect, should be
144 * greater than cifs socket timeout which is 7 seconds
146 while (server
->tcpStatus
== CifsNeedReconnect
) {
147 wait_event_interruptible_timeout(server
->response_q
,
148 (server
->tcpStatus
== CifsGood
), 10 * HZ
);
150 /* is TCP session is reestablished now ?*/
151 if (server
->tcpStatus
!= CifsNeedReconnect
)
155 * on "soft" mounts we wait once. Hard mounts keep
156 * retrying until process is killed or server comes
159 if (!tcon
->retry
|| ses
->status
== CifsExiting
) {
160 cFYI(1, ("gave up waiting on reconnect in smb_init"));
165 if (!ses
->need_reconnect
&& !tcon
->need_reconnect
)
168 nls_codepage
= load_nls_default();
171 * need to prevent multiple threads trying to simultaneously
172 * reconnect the same SMB session
174 mutex_lock(&ses
->session_mutex
);
175 if (ses
->need_reconnect
)
176 rc
= cifs_setup_session(0, ses
, nls_codepage
);
178 /* do we need to reconnect tcon? */
179 if (rc
|| !tcon
->need_reconnect
) {
180 mutex_unlock(&ses
->session_mutex
);
184 mark_open_files_invalid(tcon
);
185 rc
= CIFSTCon(0, ses
, tcon
->treeName
, tcon
, nls_codepage
);
186 mutex_unlock(&ses
->session_mutex
);
187 cFYI(1, ("reconnect tcon rc = %d", rc
));
193 * FIXME: check if wsize needs updated due to negotiated smb buffer
196 atomic_inc(&tconInfoReconnectCount
);
198 /* tell server Unix caps we support */
199 if (ses
->capabilities
& CAP_UNIX
)
200 reset_cifs_unix_caps(0, tcon
, NULL
, NULL
);
203 * Removed call to reopen open files here. It is safer (and faster) to
204 * reopen files one at a time as needed in read and write.
206 * FIXME: what about file locks? don't we need to reclaim them ASAP?
211 * Check if handle based operation so we know whether we can continue
212 * or not without returning to caller to reset file handle
214 switch (smb_command
) {
215 case SMB_COM_READ_ANDX
:
216 case SMB_COM_WRITE_ANDX
:
218 case SMB_COM_FIND_CLOSE2
:
219 case SMB_COM_LOCKING_ANDX
:
223 unload_nls(nls_codepage
);
227 /* Allocate and return pointer to an SMB request buffer, and set basic
228 SMB information in the SMB header. If the return code is zero, this
229 function must have filled in request_buf pointer */
231 small_smb_init(int smb_command
, int wct
, struct cifsTconInfo
*tcon
,
236 rc
= cifs_reconnect_tcon(tcon
, smb_command
);
240 *request_buf
= cifs_small_buf_get();
241 if (*request_buf
== NULL
) {
242 /* BB should we add a retry in here if not a writepage? */
246 header_assemble((struct smb_hdr
*) *request_buf
, smb_command
,
250 cifs_stats_inc(&tcon
->num_smbs_sent
);
256 small_smb_init_no_tc(const int smb_command
, const int wct
,
257 struct cifsSesInfo
*ses
, void **request_buf
)
260 struct smb_hdr
*buffer
;
262 rc
= small_smb_init(smb_command
, wct
, NULL
, request_buf
);
266 buffer
= (struct smb_hdr
*)*request_buf
;
267 buffer
->Mid
= GetNextMid(ses
->server
);
268 if (ses
->capabilities
& CAP_UNICODE
)
269 buffer
->Flags2
|= SMBFLG2_UNICODE
;
270 if (ses
->capabilities
& CAP_STATUS32
)
271 buffer
->Flags2
|= SMBFLG2_ERR_STATUS
;
273 /* uid, tid can stay at zero as set in header assemble */
275 /* BB add support for turning on the signing when
276 this function is used after 1st of session setup requests */
281 /* If the return code is zero, this function must fill in request_buf pointer */
283 smb_init(int smb_command
, int wct
, struct cifsTconInfo
*tcon
,
284 void **request_buf
/* returned */ ,
285 void **response_buf
/* returned */ )
289 rc
= cifs_reconnect_tcon(tcon
, smb_command
);
293 *request_buf
= cifs_buf_get();
294 if (*request_buf
== NULL
) {
295 /* BB should we add a retry in here if not a writepage? */
298 /* Although the original thought was we needed the response buf for */
299 /* potential retries of smb operations it turns out we can determine */
300 /* from the mid flags when the request buffer can be resent without */
301 /* having to use a second distinct buffer for the response */
303 *response_buf
= *request_buf
;
305 header_assemble((struct smb_hdr
*) *request_buf
, smb_command
, tcon
,
309 cifs_stats_inc(&tcon
->num_smbs_sent
);
314 static int validate_t2(struct smb_t2_rsp
*pSMB
)
320 /* check for plausible wct, bcc and t2 data and parm sizes */
321 /* check for parm and data offset going beyond end of smb */
322 if (pSMB
->hdr
.WordCount
>= 10) {
323 if ((le16_to_cpu(pSMB
->t2_rsp
.ParameterOffset
) <= 1024) &&
324 (le16_to_cpu(pSMB
->t2_rsp
.DataOffset
) <= 1024)) {
325 /* check that bcc is at least as big as parms + data */
326 /* check that bcc is less than negotiated smb buffer */
327 total_size
= le16_to_cpu(pSMB
->t2_rsp
.ParameterCount
);
328 if (total_size
< 512) {
330 le16_to_cpu(pSMB
->t2_rsp
.DataCount
);
331 /* BCC le converted in SendReceive */
332 pBCC
= (pSMB
->hdr
.WordCount
* 2) +
333 sizeof(struct smb_hdr
) +
335 if ((total_size
<= (*(u16
*)pBCC
)) &&
337 CIFSMaxBufSize
+MAX_CIFS_HDR_SIZE
)) {
343 cifs_dump_mem("Invalid transact2 SMB: ", (char *)pSMB
,
344 sizeof(struct smb_t2_rsp
) + 16);
348 CIFSSMBNegotiate(unsigned int xid
, struct cifsSesInfo
*ses
)
351 NEGOTIATE_RSP
*pSMBr
;
355 struct TCP_Server_Info
*server
;
357 unsigned int secFlags
;
361 server
= ses
->server
;
366 rc
= smb_init(SMB_COM_NEGOTIATE
, 0, NULL
/* no tcon yet */ ,
367 (void **) &pSMB
, (void **) &pSMBr
);
371 /* if any of auth flags (ie not sign or seal) are overriden use them */
372 if (ses
->overrideSecFlg
& (~(CIFSSEC_MUST_SIGN
| CIFSSEC_MUST_SEAL
)))
373 secFlags
= ses
->overrideSecFlg
; /* BB FIXME fix sign flags? */
374 else /* if override flags set only sign/seal OR them with global auth */
375 secFlags
= extended_security
| ses
->overrideSecFlg
;
377 cFYI(1, ("secFlags 0x%x", secFlags
));
379 pSMB
->hdr
.Mid
= GetNextMid(server
);
380 pSMB
->hdr
.Flags2
|= (SMBFLG2_UNICODE
| SMBFLG2_ERR_STATUS
);
382 if ((secFlags
& CIFSSEC_MUST_KRB5
) == CIFSSEC_MUST_KRB5
)
383 pSMB
->hdr
.Flags2
|= SMBFLG2_EXT_SEC
;
384 else if ((secFlags
& CIFSSEC_AUTH_MASK
) == CIFSSEC_MAY_KRB5
) {
385 cFYI(1, ("Kerberos only mechanism, enable extended security"));
386 pSMB
->hdr
.Flags2
|= SMBFLG2_EXT_SEC
;
388 #ifdef CONFIG_CIFS_EXPERIMENTAL
389 else if ((secFlags
& CIFSSEC_MUST_NTLMSSP
) == CIFSSEC_MUST_NTLMSSP
)
390 pSMB
->hdr
.Flags2
|= SMBFLG2_EXT_SEC
;
391 else if ((secFlags
& CIFSSEC_AUTH_MASK
) == CIFSSEC_MAY_NTLMSSP
) {
392 cFYI(1, ("NTLMSSP only mechanism, enable extended security"));
393 pSMB
->hdr
.Flags2
|= SMBFLG2_EXT_SEC
;
398 for (i
= 0; i
< CIFS_NUM_PROT
; i
++) {
399 strncpy(pSMB
->DialectsArray
+count
, protocols
[i
].name
, 16);
400 count
+= strlen(protocols
[i
].name
) + 1;
401 /* null at end of source and target buffers anyway */
403 pSMB
->hdr
.smb_buf_length
+= count
;
404 pSMB
->ByteCount
= cpu_to_le16(count
);
406 rc
= SendReceive(xid
, ses
, (struct smb_hdr
*) pSMB
,
407 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
411 dialect
= le16_to_cpu(pSMBr
->DialectIndex
);
412 cFYI(1, ("Dialect: %d", dialect
));
413 /* Check wct = 1 error case */
414 if ((pSMBr
->hdr
.WordCount
< 13) || (dialect
== BAD_PROT
)) {
415 /* core returns wct = 1, but we do not ask for core - otherwise
416 small wct just comes when dialect index is -1 indicating we
417 could not negotiate a common dialect */
420 #ifdef CONFIG_CIFS_WEAK_PW_HASH
421 } else if ((pSMBr
->hdr
.WordCount
== 13)
422 && ((dialect
== LANMAN_PROT
)
423 || (dialect
== LANMAN2_PROT
))) {
425 struct lanman_neg_rsp
*rsp
= (struct lanman_neg_rsp
*)pSMBr
;
427 if ((secFlags
& CIFSSEC_MAY_LANMAN
) ||
428 (secFlags
& CIFSSEC_MAY_PLNTXT
))
429 server
->secType
= LANMAN
;
431 cERROR(1, ("mount failed weak security disabled"
432 " in /proc/fs/cifs/SecurityFlags"));
436 server
->secMode
= (__u8
)le16_to_cpu(rsp
->SecurityMode
);
437 server
->maxReq
= le16_to_cpu(rsp
->MaxMpxCount
);
438 server
->maxBuf
= min((__u32
)le16_to_cpu(rsp
->MaxBufSize
),
439 (__u32
)CIFSMaxBufSize
+ MAX_CIFS_HDR_SIZE
);
440 server
->max_vcs
= le16_to_cpu(rsp
->MaxNumberVcs
);
441 GETU32(server
->sessid
) = le32_to_cpu(rsp
->SessionKey
);
442 /* even though we do not use raw we might as well set this
443 accurately, in case we ever find a need for it */
444 if ((le16_to_cpu(rsp
->RawMode
) & RAW_ENABLE
) == RAW_ENABLE
) {
445 server
->max_rw
= 0xFF00;
446 server
->capabilities
= CAP_MPX_MODE
| CAP_RAW_MODE
;
448 server
->max_rw
= 0;/* do not need to use raw anyway */
449 server
->capabilities
= CAP_MPX_MODE
;
451 tmp
= (__s16
)le16_to_cpu(rsp
->ServerTimeZone
);
453 /* OS/2 often does not set timezone therefore
454 * we must use server time to calc time zone.
455 * Could deviate slightly from the right zone.
456 * Smallest defined timezone difference is 15 minutes
457 * (i.e. Nepal). Rounding up/down is done to match
460 int val
, seconds
, remain
, result
;
461 struct timespec ts
, utc
;
463 ts
= cnvrtDosUnixTm(rsp
->SrvTime
.Date
,
464 rsp
->SrvTime
.Time
, 0);
465 cFYI(1, ("SrvTime %d sec since 1970 (utc: %d) diff: %d",
466 (int)ts
.tv_sec
, (int)utc
.tv_sec
,
467 (int)(utc
.tv_sec
- ts
.tv_sec
)));
468 val
= (int)(utc
.tv_sec
- ts
.tv_sec
);
470 result
= (seconds
/ MIN_TZ_ADJ
) * MIN_TZ_ADJ
;
471 remain
= seconds
% MIN_TZ_ADJ
;
472 if (remain
>= (MIN_TZ_ADJ
/ 2))
473 result
+= MIN_TZ_ADJ
;
476 server
->timeAdj
= result
;
478 server
->timeAdj
= (int)tmp
;
479 server
->timeAdj
*= 60; /* also in seconds */
481 cFYI(1, ("server->timeAdj: %d seconds", server
->timeAdj
));
484 /* BB get server time for time conversions and add
485 code to use it and timezone since this is not UTC */
487 if (rsp
->EncryptionKeyLength
==
488 cpu_to_le16(CIFS_CRYPTO_KEY_SIZE
)) {
489 memcpy(server
->cryptKey
, rsp
->EncryptionKey
,
490 CIFS_CRYPTO_KEY_SIZE
);
491 } else if (server
->secMode
& SECMODE_PW_ENCRYPT
) {
492 rc
= -EIO
; /* need cryptkey unless plain text */
496 cFYI(1, ("LANMAN negotiated"));
497 /* we will not end up setting signing flags - as no signing
498 was in LANMAN and server did not return the flags on */
500 #else /* weak security disabled */
501 } else if (pSMBr
->hdr
.WordCount
== 13) {
502 cERROR(1, ("mount failed, cifs module not built "
503 "with CIFS_WEAK_PW_HASH support"));
505 #endif /* WEAK_PW_HASH */
507 } else if (pSMBr
->hdr
.WordCount
!= 17) {
512 /* else wct == 17 NTLM */
513 server
->secMode
= pSMBr
->SecurityMode
;
514 if ((server
->secMode
& SECMODE_USER
) == 0)
515 cFYI(1, ("share mode security"));
517 if ((server
->secMode
& SECMODE_PW_ENCRYPT
) == 0)
518 #ifdef CONFIG_CIFS_WEAK_PW_HASH
519 if ((secFlags
& CIFSSEC_MAY_PLNTXT
) == 0)
520 #endif /* CIFS_WEAK_PW_HASH */
521 cERROR(1, ("Server requests plain text password"
522 " but client support disabled"));
524 if ((secFlags
& CIFSSEC_MUST_NTLMV2
) == CIFSSEC_MUST_NTLMV2
)
525 server
->secType
= NTLMv2
;
526 else if (secFlags
& CIFSSEC_MAY_NTLM
)
527 server
->secType
= NTLM
;
528 else if (secFlags
& CIFSSEC_MAY_NTLMV2
)
529 server
->secType
= NTLMv2
;
530 else if (secFlags
& CIFSSEC_MAY_KRB5
)
531 server
->secType
= Kerberos
;
532 else if (secFlags
& CIFSSEC_MAY_NTLMSSP
)
533 server
->secType
= RawNTLMSSP
;
534 else if (secFlags
& CIFSSEC_MAY_LANMAN
)
535 server
->secType
= LANMAN
;
536 /* #ifdef CONFIG_CIFS_EXPERIMENTAL
537 else if (secFlags & CIFSSEC_MAY_PLNTXT)
542 cERROR(1, ("Invalid security type"));
545 /* else ... any others ...? */
547 /* one byte, so no need to convert this or EncryptionKeyLen from
549 server
->maxReq
= le16_to_cpu(pSMBr
->MaxMpxCount
);
550 /* probably no need to store and check maxvcs */
551 server
->maxBuf
= min(le32_to_cpu(pSMBr
->MaxBufferSize
),
552 (__u32
) CIFSMaxBufSize
+ MAX_CIFS_HDR_SIZE
);
553 server
->max_rw
= le32_to_cpu(pSMBr
->MaxRawSize
);
554 cFYI(DBG2
, ("Max buf = %d", ses
->server
->maxBuf
));
555 GETU32(ses
->server
->sessid
) = le32_to_cpu(pSMBr
->SessionKey
);
556 server
->capabilities
= le32_to_cpu(pSMBr
->Capabilities
);
557 server
->timeAdj
= (int)(__s16
)le16_to_cpu(pSMBr
->ServerTimeZone
);
558 server
->timeAdj
*= 60;
559 if (pSMBr
->EncryptionKeyLength
== CIFS_CRYPTO_KEY_SIZE
) {
560 memcpy(server
->cryptKey
, pSMBr
->u
.EncryptionKey
,
561 CIFS_CRYPTO_KEY_SIZE
);
562 } else if ((pSMBr
->hdr
.Flags2
& SMBFLG2_EXT_SEC
)
563 && (pSMBr
->EncryptionKeyLength
== 0)) {
564 /* decode security blob */
565 } else if (server
->secMode
& SECMODE_PW_ENCRYPT
) {
566 rc
= -EIO
; /* no crypt key only if plain text pwd */
570 /* BB might be helpful to save off the domain of server here */
572 if ((pSMBr
->hdr
.Flags2
& SMBFLG2_EXT_SEC
) &&
573 (server
->capabilities
& CAP_EXTENDED_SECURITY
)) {
574 count
= pSMBr
->ByteCount
;
579 read_lock(&cifs_tcp_ses_lock
);
580 if (server
->srv_count
> 1) {
581 read_unlock(&cifs_tcp_ses_lock
);
582 if (memcmp(server
->server_GUID
,
583 pSMBr
->u
.extended_response
.
585 cFYI(1, ("server UID changed"));
586 memcpy(server
->server_GUID
,
587 pSMBr
->u
.extended_response
.GUID
,
591 read_unlock(&cifs_tcp_ses_lock
);
592 memcpy(server
->server_GUID
,
593 pSMBr
->u
.extended_response
.GUID
, 16);
597 server
->secType
= RawNTLMSSP
;
599 rc
= decode_negTokenInit(pSMBr
->u
.extended_response
.
609 server
->capabilities
&= ~CAP_EXTENDED_SECURITY
;
611 #ifdef CONFIG_CIFS_WEAK_PW_HASH
614 if ((secFlags
& CIFSSEC_MAY_SIGN
) == 0) {
615 /* MUST_SIGN already includes the MAY_SIGN FLAG
616 so if this is zero it means that signing is disabled */
617 cFYI(1, ("Signing disabled"));
618 if (server
->secMode
& SECMODE_SIGN_REQUIRED
) {
619 cERROR(1, ("Server requires "
620 "packet signing to be enabled in "
621 "/proc/fs/cifs/SecurityFlags."));
625 ~(SECMODE_SIGN_ENABLED
| SECMODE_SIGN_REQUIRED
);
626 } else if ((secFlags
& CIFSSEC_MUST_SIGN
) == CIFSSEC_MUST_SIGN
) {
627 /* signing required */
628 cFYI(1, ("Must sign - secFlags 0x%x", secFlags
));
629 if ((server
->secMode
&
630 (SECMODE_SIGN_ENABLED
| SECMODE_SIGN_REQUIRED
)) == 0) {
632 ("signing required but server lacks support"));
635 server
->secMode
|= SECMODE_SIGN_REQUIRED
;
637 /* signing optional ie CIFSSEC_MAY_SIGN */
638 if ((server
->secMode
& SECMODE_SIGN_REQUIRED
) == 0)
640 ~(SECMODE_SIGN_ENABLED
| SECMODE_SIGN_REQUIRED
);
644 cifs_buf_release(pSMB
);
646 cFYI(1, ("negprot rc %d", rc
));
651 CIFSSMBTDis(const int xid
, struct cifsTconInfo
*tcon
)
653 struct smb_hdr
*smb_buffer
;
656 cFYI(1, ("In tree disconnect"));
658 /* BB: do we need to check this? These should never be NULL. */
659 if ((tcon
->ses
== NULL
) || (tcon
->ses
->server
== NULL
))
663 * No need to return error on this operation if tid invalidated and
664 * closed on server already e.g. due to tcp session crashing. Also,
665 * the tcon is no longer on the list, so no need to take lock before
668 if ((tcon
->need_reconnect
) || (tcon
->ses
->need_reconnect
))
671 rc
= small_smb_init(SMB_COM_TREE_DISCONNECT
, 0, tcon
,
672 (void **)&smb_buffer
);
676 rc
= SendReceiveNoRsp(xid
, tcon
->ses
, smb_buffer
, 0);
678 cFYI(1, ("Tree disconnect failed %d", rc
));
680 /* No need to return error on this operation if tid invalidated and
681 closed on server already e.g. due to tcp session crashing */
689 CIFSSMBLogoff(const int xid
, struct cifsSesInfo
*ses
)
691 LOGOFF_ANDX_REQ
*pSMB
;
694 cFYI(1, ("In SMBLogoff for session disconnect"));
697 * BB: do we need to check validity of ses and server? They should
698 * always be valid since we have an active reference. If not, that
699 * should probably be a BUG()
701 if (!ses
|| !ses
->server
)
704 mutex_lock(&ses
->session_mutex
);
705 if (ses
->need_reconnect
)
706 goto session_already_dead
; /* no need to send SMBlogoff if uid
707 already closed due to reconnect */
708 rc
= small_smb_init(SMB_COM_LOGOFF_ANDX
, 2, NULL
, (void **)&pSMB
);
710 mutex_unlock(&ses
->session_mutex
);
714 pSMB
->hdr
.Mid
= GetNextMid(ses
->server
);
716 if (ses
->server
->secMode
&
717 (SECMODE_SIGN_REQUIRED
| SECMODE_SIGN_ENABLED
))
718 pSMB
->hdr
.Flags2
|= SMBFLG2_SECURITY_SIGNATURE
;
720 pSMB
->hdr
.Uid
= ses
->Suid
;
722 pSMB
->AndXCommand
= 0xFF;
723 rc
= SendReceiveNoRsp(xid
, ses
, (struct smb_hdr
*) pSMB
, 0);
724 session_already_dead
:
725 mutex_unlock(&ses
->session_mutex
);
727 /* if session dead then we do not need to do ulogoff,
728 since server closed smb session, no sense reporting
736 CIFSPOSIXDelFile(const int xid
, struct cifsTconInfo
*tcon
, const char *fileName
,
737 __u16 type
, const struct nls_table
*nls_codepage
, int remap
)
739 TRANSACTION2_SPI_REQ
*pSMB
= NULL
;
740 TRANSACTION2_SPI_RSP
*pSMBr
= NULL
;
741 struct unlink_psx_rq
*pRqD
;
744 int bytes_returned
= 0;
745 __u16 params
, param_offset
, offset
, byte_count
;
747 cFYI(1, ("In POSIX delete"));
749 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
754 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
756 cifsConvertToUCS((__le16
*) pSMB
->FileName
, fileName
,
757 PATH_MAX
, nls_codepage
, remap
);
758 name_len
++; /* trailing null */
760 } else { /* BB add path length overrun check */
761 name_len
= strnlen(fileName
, PATH_MAX
);
762 name_len
++; /* trailing null */
763 strncpy(pSMB
->FileName
, fileName
, name_len
);
766 params
= 6 + name_len
;
767 pSMB
->MaxParameterCount
= cpu_to_le16(2);
768 pSMB
->MaxDataCount
= 0; /* BB double check this with jra */
769 pSMB
->MaxSetupCount
= 0;
774 param_offset
= offsetof(struct smb_com_transaction2_spi_req
,
775 InformationLevel
) - 4;
776 offset
= param_offset
+ params
;
778 /* Setup pointer to Request Data (inode type) */
779 pRqD
= (struct unlink_psx_rq
*)(((char *)&pSMB
->hdr
.Protocol
) + offset
);
780 pRqD
->type
= cpu_to_le16(type
);
781 pSMB
->ParameterOffset
= cpu_to_le16(param_offset
);
782 pSMB
->DataOffset
= cpu_to_le16(offset
);
783 pSMB
->SetupCount
= 1;
785 pSMB
->SubCommand
= cpu_to_le16(TRANS2_SET_PATH_INFORMATION
);
786 byte_count
= 3 /* pad */ + params
+ sizeof(struct unlink_psx_rq
);
788 pSMB
->DataCount
= cpu_to_le16(sizeof(struct unlink_psx_rq
));
789 pSMB
->TotalDataCount
= cpu_to_le16(sizeof(struct unlink_psx_rq
));
790 pSMB
->ParameterCount
= cpu_to_le16(params
);
791 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
792 pSMB
->InformationLevel
= cpu_to_le16(SMB_POSIX_UNLINK
);
794 pSMB
->hdr
.smb_buf_length
+= byte_count
;
795 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
796 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
797 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
799 cFYI(1, ("Posix delete returned %d", rc
));
800 cifs_buf_release(pSMB
);
802 cifs_stats_inc(&tcon
->num_deletes
);
811 CIFSSMBDelFile(const int xid
, struct cifsTconInfo
*tcon
, const char *fileName
,
812 const struct nls_table
*nls_codepage
, int remap
)
814 DELETE_FILE_REQ
*pSMB
= NULL
;
815 DELETE_FILE_RSP
*pSMBr
= NULL
;
821 rc
= smb_init(SMB_COM_DELETE
, 1, tcon
, (void **) &pSMB
,
826 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
828 cifsConvertToUCS((__le16
*) pSMB
->fileName
, fileName
,
829 PATH_MAX
, nls_codepage
, remap
);
830 name_len
++; /* trailing null */
832 } else { /* BB improve check for buffer overruns BB */
833 name_len
= strnlen(fileName
, PATH_MAX
);
834 name_len
++; /* trailing null */
835 strncpy(pSMB
->fileName
, fileName
, name_len
);
837 pSMB
->SearchAttributes
=
838 cpu_to_le16(ATTR_READONLY
| ATTR_HIDDEN
| ATTR_SYSTEM
);
839 pSMB
->BufferFormat
= 0x04;
840 pSMB
->hdr
.smb_buf_length
+= name_len
+ 1;
841 pSMB
->ByteCount
= cpu_to_le16(name_len
+ 1);
842 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
843 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
844 cifs_stats_inc(&tcon
->num_deletes
);
846 cFYI(1, ("Error in RMFile = %d", rc
));
848 cifs_buf_release(pSMB
);
856 CIFSSMBRmDir(const int xid
, struct cifsTconInfo
*tcon
, const char *dirName
,
857 const struct nls_table
*nls_codepage
, int remap
)
859 DELETE_DIRECTORY_REQ
*pSMB
= NULL
;
860 DELETE_DIRECTORY_RSP
*pSMBr
= NULL
;
865 cFYI(1, ("In CIFSSMBRmDir"));
867 rc
= smb_init(SMB_COM_DELETE_DIRECTORY
, 0, tcon
, (void **) &pSMB
,
872 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
873 name_len
= cifsConvertToUCS((__le16
*) pSMB
->DirName
, dirName
,
874 PATH_MAX
, nls_codepage
, remap
);
875 name_len
++; /* trailing null */
877 } else { /* BB improve check for buffer overruns BB */
878 name_len
= strnlen(dirName
, PATH_MAX
);
879 name_len
++; /* trailing null */
880 strncpy(pSMB
->DirName
, dirName
, name_len
);
883 pSMB
->BufferFormat
= 0x04;
884 pSMB
->hdr
.smb_buf_length
+= name_len
+ 1;
885 pSMB
->ByteCount
= cpu_to_le16(name_len
+ 1);
886 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
887 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
888 cifs_stats_inc(&tcon
->num_rmdirs
);
890 cFYI(1, ("Error in RMDir = %d", rc
));
892 cifs_buf_release(pSMB
);
899 CIFSSMBMkDir(const int xid
, struct cifsTconInfo
*tcon
,
900 const char *name
, const struct nls_table
*nls_codepage
, int remap
)
903 CREATE_DIRECTORY_REQ
*pSMB
= NULL
;
904 CREATE_DIRECTORY_RSP
*pSMBr
= NULL
;
908 cFYI(1, ("In CIFSSMBMkDir"));
910 rc
= smb_init(SMB_COM_CREATE_DIRECTORY
, 0, tcon
, (void **) &pSMB
,
915 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
916 name_len
= cifsConvertToUCS((__le16
*) pSMB
->DirName
, name
,
917 PATH_MAX
, nls_codepage
, remap
);
918 name_len
++; /* trailing null */
920 } else { /* BB improve check for buffer overruns BB */
921 name_len
= strnlen(name
, PATH_MAX
);
922 name_len
++; /* trailing null */
923 strncpy(pSMB
->DirName
, name
, name_len
);
926 pSMB
->BufferFormat
= 0x04;
927 pSMB
->hdr
.smb_buf_length
+= name_len
+ 1;
928 pSMB
->ByteCount
= cpu_to_le16(name_len
+ 1);
929 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
930 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
931 cifs_stats_inc(&tcon
->num_mkdirs
);
933 cFYI(1, ("Error in Mkdir = %d", rc
));
935 cifs_buf_release(pSMB
);
942 CIFSPOSIXCreate(const int xid
, struct cifsTconInfo
*tcon
, __u32 posix_flags
,
943 __u64 mode
, __u16
*netfid
, FILE_UNIX_BASIC_INFO
*pRetData
,
944 __u32
*pOplock
, const char *name
,
945 const struct nls_table
*nls_codepage
, int remap
)
947 TRANSACTION2_SPI_REQ
*pSMB
= NULL
;
948 TRANSACTION2_SPI_RSP
*pSMBr
= NULL
;
951 int bytes_returned
= 0;
952 __u16 params
, param_offset
, offset
, byte_count
, count
;
954 OPEN_PSX_RSP
*psx_rsp
;
956 cFYI(1, ("In POSIX Create"));
958 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
963 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
965 cifsConvertToUCS((__le16
*) pSMB
->FileName
, name
,
966 PATH_MAX
, nls_codepage
, remap
);
967 name_len
++; /* trailing null */
969 } else { /* BB improve the check for buffer overruns BB */
970 name_len
= strnlen(name
, PATH_MAX
);
971 name_len
++; /* trailing null */
972 strncpy(pSMB
->FileName
, name
, name_len
);
975 params
= 6 + name_len
;
976 count
= sizeof(OPEN_PSX_REQ
);
977 pSMB
->MaxParameterCount
= cpu_to_le16(2);
978 pSMB
->MaxDataCount
= cpu_to_le16(1000); /* large enough */
979 pSMB
->MaxSetupCount
= 0;
984 param_offset
= offsetof(struct smb_com_transaction2_spi_req
,
985 InformationLevel
) - 4;
986 offset
= param_offset
+ params
;
987 pdata
= (OPEN_PSX_REQ
*)(((char *)&pSMB
->hdr
.Protocol
) + offset
);
988 pdata
->Level
= cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC
);
989 pdata
->Permissions
= cpu_to_le64(mode
);
990 pdata
->PosixOpenFlags
= cpu_to_le32(posix_flags
);
991 pdata
->OpenFlags
= cpu_to_le32(*pOplock
);
992 pSMB
->ParameterOffset
= cpu_to_le16(param_offset
);
993 pSMB
->DataOffset
= cpu_to_le16(offset
);
994 pSMB
->SetupCount
= 1;
996 pSMB
->SubCommand
= cpu_to_le16(TRANS2_SET_PATH_INFORMATION
);
997 byte_count
= 3 /* pad */ + params
+ count
;
999 pSMB
->DataCount
= cpu_to_le16(count
);
1000 pSMB
->ParameterCount
= cpu_to_le16(params
);
1001 pSMB
->TotalDataCount
= pSMB
->DataCount
;
1002 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
1003 pSMB
->InformationLevel
= cpu_to_le16(SMB_POSIX_OPEN
);
1004 pSMB
->Reserved4
= 0;
1005 pSMB
->hdr
.smb_buf_length
+= byte_count
;
1006 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
1007 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
1008 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
1010 cFYI(1, ("Posix create returned %d", rc
));
1011 goto psx_create_err
;
1014 cFYI(1, ("copying inode info"));
1015 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
1017 if (rc
|| (pSMBr
->ByteCount
< sizeof(OPEN_PSX_RSP
))) {
1018 rc
= -EIO
; /* bad smb */
1019 goto psx_create_err
;
1022 /* copy return information to pRetData */
1023 psx_rsp
= (OPEN_PSX_RSP
*)((char *) &pSMBr
->hdr
.Protocol
1024 + le16_to_cpu(pSMBr
->t2
.DataOffset
));
1026 *pOplock
= le16_to_cpu(psx_rsp
->OplockFlags
);
1028 *netfid
= psx_rsp
->Fid
; /* cifs fid stays in le */
1029 /* Let caller know file was created so we can set the mode. */
1030 /* Do we care about the CreateAction in any other cases? */
1031 if (cpu_to_le32(FILE_CREATE
) == psx_rsp
->CreateAction
)
1032 *pOplock
|= CIFS_CREATE_ACTION
;
1033 /* check to make sure response data is there */
1034 if (psx_rsp
->ReturnedLevel
!= cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC
)) {
1035 pRetData
->Type
= cpu_to_le32(-1); /* unknown */
1036 cFYI(DBG2
, ("unknown type"));
1038 if (pSMBr
->ByteCount
< sizeof(OPEN_PSX_RSP
)
1039 + sizeof(FILE_UNIX_BASIC_INFO
)) {
1040 cERROR(1, ("Open response data too small"));
1041 pRetData
->Type
= cpu_to_le32(-1);
1042 goto psx_create_err
;
1044 memcpy((char *) pRetData
,
1045 (char *)psx_rsp
+ sizeof(OPEN_PSX_RSP
),
1046 sizeof(FILE_UNIX_BASIC_INFO
));
1050 cifs_buf_release(pSMB
);
1052 if (posix_flags
& SMB_O_DIRECTORY
)
1053 cifs_stats_inc(&tcon
->num_posixmkdirs
);
1055 cifs_stats_inc(&tcon
->num_posixopens
);
1063 static __u16
convert_disposition(int disposition
)
1067 switch (disposition
) {
1068 case FILE_SUPERSEDE
:
1069 ofun
= SMBOPEN_OCREATE
| SMBOPEN_OTRUNC
;
1072 ofun
= SMBOPEN_OAPPEND
;
1075 ofun
= SMBOPEN_OCREATE
;
1078 ofun
= SMBOPEN_OCREATE
| SMBOPEN_OAPPEND
;
1080 case FILE_OVERWRITE
:
1081 ofun
= SMBOPEN_OTRUNC
;
1083 case FILE_OVERWRITE_IF
:
1084 ofun
= SMBOPEN_OCREATE
| SMBOPEN_OTRUNC
;
1087 cFYI(1, ("unknown disposition %d", disposition
));
1088 ofun
= SMBOPEN_OAPPEND
; /* regular open */
1094 access_flags_to_smbopen_mode(const int access_flags
)
1096 int masked_flags
= access_flags
& (GENERIC_READ
| GENERIC_WRITE
);
1098 if (masked_flags
== GENERIC_READ
)
1099 return SMBOPEN_READ
;
1100 else if (masked_flags
== GENERIC_WRITE
)
1101 return SMBOPEN_WRITE
;
1103 /* just go for read/write */
1104 return SMBOPEN_READWRITE
;
1108 SMBLegacyOpen(const int xid
, struct cifsTconInfo
*tcon
,
1109 const char *fileName
, const int openDisposition
,
1110 const int access_flags
, const int create_options
, __u16
*netfid
,
1111 int *pOplock
, FILE_ALL_INFO
*pfile_info
,
1112 const struct nls_table
*nls_codepage
, int remap
)
1115 OPENX_REQ
*pSMB
= NULL
;
1116 OPENX_RSP
*pSMBr
= NULL
;
1122 rc
= smb_init(SMB_COM_OPEN_ANDX
, 15, tcon
, (void **) &pSMB
,
1127 pSMB
->AndXCommand
= 0xFF; /* none */
1129 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
1130 count
= 1; /* account for one byte pad to word boundary */
1132 cifsConvertToUCS((__le16
*) (pSMB
->fileName
+ 1),
1133 fileName
, PATH_MAX
, nls_codepage
, remap
);
1134 name_len
++; /* trailing null */
1136 } else { /* BB improve check for buffer overruns BB */
1137 count
= 0; /* no pad */
1138 name_len
= strnlen(fileName
, PATH_MAX
);
1139 name_len
++; /* trailing null */
1140 strncpy(pSMB
->fileName
, fileName
, name_len
);
1142 if (*pOplock
& REQ_OPLOCK
)
1143 pSMB
->OpenFlags
= cpu_to_le16(REQ_OPLOCK
);
1144 else if (*pOplock
& REQ_BATCHOPLOCK
)
1145 pSMB
->OpenFlags
= cpu_to_le16(REQ_BATCHOPLOCK
);
1147 pSMB
->OpenFlags
|= cpu_to_le16(REQ_MORE_INFO
);
1148 pSMB
->Mode
= cpu_to_le16(access_flags_to_smbopen_mode(access_flags
));
1149 pSMB
->Mode
|= cpu_to_le16(0x40); /* deny none */
1150 /* set file as system file if special file such
1151 as fifo and server expecting SFU style and
1152 no Unix extensions */
1154 if (create_options
& CREATE_OPTION_SPECIAL
)
1155 pSMB
->FileAttributes
= cpu_to_le16(ATTR_SYSTEM
);
1156 else /* BB FIXME BB */
1157 pSMB
->FileAttributes
= cpu_to_le16(0/*ATTR_NORMAL*/);
1159 if (create_options
& CREATE_OPTION_READONLY
)
1160 pSMB
->FileAttributes
|= cpu_to_le16(ATTR_READONLY
);
1163 /* pSMB->CreateOptions = cpu_to_le32(create_options &
1164 CREATE_OPTIONS_MASK); */
1165 /* BB FIXME END BB */
1167 pSMB
->Sattr
= cpu_to_le16(ATTR_HIDDEN
| ATTR_SYSTEM
| ATTR_DIRECTORY
);
1168 pSMB
->OpenFunction
= cpu_to_le16(convert_disposition(openDisposition
));
1170 pSMB
->hdr
.smb_buf_length
+= count
;
1172 pSMB
->ByteCount
= cpu_to_le16(count
);
1173 /* long_op set to 1 to allow for oplock break timeouts */
1174 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
1175 (struct smb_hdr
*)pSMBr
, &bytes_returned
, CIFS_LONG_OP
);
1176 cifs_stats_inc(&tcon
->num_opens
);
1178 cFYI(1, ("Error in Open = %d", rc
));
1180 /* BB verify if wct == 15 */
1182 /* *pOplock = pSMBr->OplockLevel; */ /* BB take from action field*/
1184 *netfid
= pSMBr
->Fid
; /* cifs fid stays in le */
1185 /* Let caller know file was created so we can set the mode. */
1186 /* Do we care about the CreateAction in any other cases? */
1188 /* if (cpu_to_le32(FILE_CREATE) == pSMBr->CreateAction)
1189 *pOplock |= CIFS_CREATE_ACTION; */
1193 pfile_info
->CreationTime
= 0; /* BB convert CreateTime*/
1194 pfile_info
->LastAccessTime
= 0; /* BB fixme */
1195 pfile_info
->LastWriteTime
= 0; /* BB fixme */
1196 pfile_info
->ChangeTime
= 0; /* BB fixme */
1197 pfile_info
->Attributes
=
1198 cpu_to_le32(le16_to_cpu(pSMBr
->FileAttributes
));
1199 /* the file_info buf is endian converted by caller */
1200 pfile_info
->AllocationSize
=
1201 cpu_to_le64(le32_to_cpu(pSMBr
->EndOfFile
));
1202 pfile_info
->EndOfFile
= pfile_info
->AllocationSize
;
1203 pfile_info
->NumberOfLinks
= cpu_to_le32(1);
1204 pfile_info
->DeletePending
= 0;
1208 cifs_buf_release(pSMB
);
1215 CIFSSMBOpen(const int xid
, struct cifsTconInfo
*tcon
,
1216 const char *fileName
, const int openDisposition
,
1217 const int access_flags
, const int create_options
, __u16
*netfid
,
1218 int *pOplock
, FILE_ALL_INFO
*pfile_info
,
1219 const struct nls_table
*nls_codepage
, int remap
)
1222 OPEN_REQ
*pSMB
= NULL
;
1223 OPEN_RSP
*pSMBr
= NULL
;
1229 rc
= smb_init(SMB_COM_NT_CREATE_ANDX
, 24, tcon
, (void **) &pSMB
,
1234 pSMB
->AndXCommand
= 0xFF; /* none */
1236 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
1237 count
= 1; /* account for one byte pad to word boundary */
1239 cifsConvertToUCS((__le16
*) (pSMB
->fileName
+ 1),
1240 fileName
, PATH_MAX
, nls_codepage
, remap
);
1241 name_len
++; /* trailing null */
1243 pSMB
->NameLength
= cpu_to_le16(name_len
);
1244 } else { /* BB improve check for buffer overruns BB */
1245 count
= 0; /* no pad */
1246 name_len
= strnlen(fileName
, PATH_MAX
);
1247 name_len
++; /* trailing null */
1248 pSMB
->NameLength
= cpu_to_le16(name_len
);
1249 strncpy(pSMB
->fileName
, fileName
, name_len
);
1251 if (*pOplock
& REQ_OPLOCK
)
1252 pSMB
->OpenFlags
= cpu_to_le32(REQ_OPLOCK
);
1253 else if (*pOplock
& REQ_BATCHOPLOCK
)
1254 pSMB
->OpenFlags
= cpu_to_le32(REQ_BATCHOPLOCK
);
1255 pSMB
->DesiredAccess
= cpu_to_le32(access_flags
);
1256 pSMB
->AllocationSize
= 0;
1257 /* set file as system file if special file such
1258 as fifo and server expecting SFU style and
1259 no Unix extensions */
1260 if (create_options
& CREATE_OPTION_SPECIAL
)
1261 pSMB
->FileAttributes
= cpu_to_le32(ATTR_SYSTEM
);
1263 pSMB
->FileAttributes
= cpu_to_le32(ATTR_NORMAL
);
1265 /* XP does not handle ATTR_POSIX_SEMANTICS */
1266 /* but it helps speed up case sensitive checks for other
1267 servers such as Samba */
1268 if (tcon
->ses
->capabilities
& CAP_UNIX
)
1269 pSMB
->FileAttributes
|= cpu_to_le32(ATTR_POSIX_SEMANTICS
);
1271 if (create_options
& CREATE_OPTION_READONLY
)
1272 pSMB
->FileAttributes
|= cpu_to_le32(ATTR_READONLY
);
1274 pSMB
->ShareAccess
= cpu_to_le32(FILE_SHARE_ALL
);
1275 pSMB
->CreateDisposition
= cpu_to_le32(openDisposition
);
1276 pSMB
->CreateOptions
= cpu_to_le32(create_options
& CREATE_OPTIONS_MASK
);
1277 /* BB Expirement with various impersonation levels and verify */
1278 pSMB
->ImpersonationLevel
= cpu_to_le32(SECURITY_IMPERSONATION
);
1279 pSMB
->SecurityFlags
=
1280 SECURITY_CONTEXT_TRACKING
| SECURITY_EFFECTIVE_ONLY
;
1283 pSMB
->hdr
.smb_buf_length
+= count
;
1285 pSMB
->ByteCount
= cpu_to_le16(count
);
1286 /* long_op set to 1 to allow for oplock break timeouts */
1287 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
1288 (struct smb_hdr
*)pSMBr
, &bytes_returned
, CIFS_LONG_OP
);
1289 cifs_stats_inc(&tcon
->num_opens
);
1291 cFYI(1, ("Error in Open = %d", rc
));
1293 *pOplock
= pSMBr
->OplockLevel
; /* 1 byte no need to le_to_cpu */
1294 *netfid
= pSMBr
->Fid
; /* cifs fid stays in le */
1295 /* Let caller know file was created so we can set the mode. */
1296 /* Do we care about the CreateAction in any other cases? */
1297 if (cpu_to_le32(FILE_CREATE
) == pSMBr
->CreateAction
)
1298 *pOplock
|= CIFS_CREATE_ACTION
;
1300 memcpy((char *)pfile_info
, (char *)&pSMBr
->CreationTime
,
1301 36 /* CreationTime to Attributes */);
1302 /* the file_info buf is endian converted by caller */
1303 pfile_info
->AllocationSize
= pSMBr
->AllocationSize
;
1304 pfile_info
->EndOfFile
= pSMBr
->EndOfFile
;
1305 pfile_info
->NumberOfLinks
= cpu_to_le32(1);
1306 pfile_info
->DeletePending
= 0;
1310 cifs_buf_release(pSMB
);
1317 CIFSSMBRead(const int xid
, struct cifsTconInfo
*tcon
, const int netfid
,
1318 const unsigned int count
, const __u64 lseek
, unsigned int *nbytes
,
1319 char **buf
, int *pbuf_type
)
1322 READ_REQ
*pSMB
= NULL
;
1323 READ_RSP
*pSMBr
= NULL
;
1324 char *pReadData
= NULL
;
1326 int resp_buf_type
= 0;
1329 cFYI(1, ("Reading %d bytes on fid %d", count
, netfid
));
1330 if (tcon
->ses
->capabilities
& CAP_LARGE_FILES
)
1333 wct
= 10; /* old style read */
1334 if ((lseek
>> 32) > 0) {
1335 /* can not handle this big offset for old */
1341 rc
= small_smb_init(SMB_COM_READ_ANDX
, wct
, tcon
, (void **) &pSMB
);
1345 /* tcon and ses pointer are checked in smb_init */
1346 if (tcon
->ses
->server
== NULL
)
1347 return -ECONNABORTED
;
1349 pSMB
->AndXCommand
= 0xFF; /* none */
1351 pSMB
->OffsetLow
= cpu_to_le32(lseek
& 0xFFFFFFFF);
1353 pSMB
->OffsetHigh
= cpu_to_le32(lseek
>> 32);
1355 pSMB
->Remaining
= 0;
1356 pSMB
->MaxCount
= cpu_to_le16(count
& 0xFFFF);
1357 pSMB
->MaxCountHigh
= cpu_to_le32(count
>> 16);
1359 pSMB
->ByteCount
= 0; /* no need to do le conversion since 0 */
1361 /* old style read */
1362 struct smb_com_readx_req
*pSMBW
=
1363 (struct smb_com_readx_req
*)pSMB
;
1364 pSMBW
->ByteCount
= 0;
1367 iov
[0].iov_base
= (char *)pSMB
;
1368 iov
[0].iov_len
= pSMB
->hdr
.smb_buf_length
+ 4;
1369 rc
= SendReceive2(xid
, tcon
->ses
, iov
, 1 /* num iovecs */,
1370 &resp_buf_type
, CIFS_STD_OP
| CIFS_LOG_ERROR
);
1371 cifs_stats_inc(&tcon
->num_reads
);
1372 pSMBr
= (READ_RSP
*)iov
[0].iov_base
;
1374 cERROR(1, ("Send error in read = %d", rc
));
1376 int data_length
= le16_to_cpu(pSMBr
->DataLengthHigh
);
1377 data_length
= data_length
<< 16;
1378 data_length
+= le16_to_cpu(pSMBr
->DataLength
);
1379 *nbytes
= data_length
;
1381 /*check that DataLength would not go beyond end of SMB */
1382 if ((data_length
> CIFSMaxBufSize
)
1383 || (data_length
> count
)) {
1384 cFYI(1, ("bad length %d for count %d",
1385 data_length
, count
));
1389 pReadData
= (char *) (&pSMBr
->hdr
.Protocol
) +
1390 le16_to_cpu(pSMBr
->DataOffset
);
1391 /* if (rc = copy_to_user(buf, pReadData, data_length)) {
1392 cERROR(1,("Faulting on read rc = %d",rc));
1394 }*/ /* can not use copy_to_user when using page cache*/
1396 memcpy(*buf
, pReadData
, data_length
);
1400 /* cifs_small_buf_release(pSMB); */ /* Freed earlier now in SendReceive2 */
1402 if (resp_buf_type
== CIFS_SMALL_BUFFER
)
1403 cifs_small_buf_release(iov
[0].iov_base
);
1404 else if (resp_buf_type
== CIFS_LARGE_BUFFER
)
1405 cifs_buf_release(iov
[0].iov_base
);
1406 } else if (resp_buf_type
!= CIFS_NO_BUFFER
) {
1407 /* return buffer to caller to free */
1408 *buf
= iov
[0].iov_base
;
1409 if (resp_buf_type
== CIFS_SMALL_BUFFER
)
1410 *pbuf_type
= CIFS_SMALL_BUFFER
;
1411 else if (resp_buf_type
== CIFS_LARGE_BUFFER
)
1412 *pbuf_type
= CIFS_LARGE_BUFFER
;
1413 } /* else no valid buffer on return - leave as null */
1415 /* Note: On -EAGAIN error only caller can retry on handle based calls
1416 since file handle passed in no longer valid */
1422 CIFSSMBWrite(const int xid
, struct cifsTconInfo
*tcon
,
1423 const int netfid
, const unsigned int count
,
1424 const __u64 offset
, unsigned int *nbytes
, const char *buf
,
1425 const char __user
*ubuf
, const int long_op
)
1428 WRITE_REQ
*pSMB
= NULL
;
1429 WRITE_RSP
*pSMBr
= NULL
;
1430 int bytes_returned
, wct
;
1436 /* cFYI(1, ("write at %lld %d bytes", offset, count));*/
1437 if (tcon
->ses
== NULL
)
1438 return -ECONNABORTED
;
1440 if (tcon
->ses
->capabilities
& CAP_LARGE_FILES
)
1444 if ((offset
>> 32) > 0) {
1445 /* can not handle big offset for old srv */
1450 rc
= smb_init(SMB_COM_WRITE_ANDX
, wct
, tcon
, (void **) &pSMB
,
1454 /* tcon and ses pointer are checked in smb_init */
1455 if (tcon
->ses
->server
== NULL
)
1456 return -ECONNABORTED
;
1458 pSMB
->AndXCommand
= 0xFF; /* none */
1460 pSMB
->OffsetLow
= cpu_to_le32(offset
& 0xFFFFFFFF);
1462 pSMB
->OffsetHigh
= cpu_to_le32(offset
>> 32);
1464 pSMB
->Reserved
= 0xFFFFFFFF;
1465 pSMB
->WriteMode
= 0;
1466 pSMB
->Remaining
= 0;
1468 /* Can increase buffer size if buffer is big enough in some cases ie we
1469 can send more if LARGE_WRITE_X capability returned by the server and if
1470 our buffer is big enough or if we convert to iovecs on socket writes
1471 and eliminate the copy to the CIFS buffer */
1472 if (tcon
->ses
->capabilities
& CAP_LARGE_WRITE_X
) {
1473 bytes_sent
= min_t(const unsigned int, CIFSMaxBufSize
, count
);
1475 bytes_sent
= (tcon
->ses
->server
->maxBuf
- MAX_CIFS_HDR_SIZE
)
1479 if (bytes_sent
> count
)
1482 cpu_to_le16(offsetof(struct smb_com_write_req
, Data
) - 4);
1484 memcpy(pSMB
->Data
, buf
, bytes_sent
);
1486 if (copy_from_user(pSMB
->Data
, ubuf
, bytes_sent
)) {
1487 cifs_buf_release(pSMB
);
1490 } else if (count
!= 0) {
1492 cifs_buf_release(pSMB
);
1494 } /* else setting file size with write of zero bytes */
1496 byte_count
= bytes_sent
+ 1; /* pad */
1497 else /* wct == 12 */
1498 byte_count
= bytes_sent
+ 5; /* bigger pad, smaller smb hdr */
1500 pSMB
->DataLengthLow
= cpu_to_le16(bytes_sent
& 0xFFFF);
1501 pSMB
->DataLengthHigh
= cpu_to_le16(bytes_sent
>> 16);
1502 pSMB
->hdr
.smb_buf_length
+= byte_count
;
1505 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
1506 else { /* old style write has byte count 4 bytes earlier
1508 struct smb_com_writex_req
*pSMBW
=
1509 (struct smb_com_writex_req
*)pSMB
;
1510 pSMBW
->ByteCount
= cpu_to_le16(byte_count
);
1513 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
1514 (struct smb_hdr
*) pSMBr
, &bytes_returned
, long_op
);
1515 cifs_stats_inc(&tcon
->num_writes
);
1517 cFYI(1, ("Send error in write = %d", rc
));
1519 *nbytes
= le16_to_cpu(pSMBr
->CountHigh
);
1520 *nbytes
= (*nbytes
) << 16;
1521 *nbytes
+= le16_to_cpu(pSMBr
->Count
);
1524 * Mask off high 16 bits when bytes written as returned by the
1525 * server is greater than bytes requested by the client. Some
1526 * OS/2 servers are known to set incorrect CountHigh values.
1528 if (*nbytes
> count
)
1532 cifs_buf_release(pSMB
);
1534 /* Note: On -EAGAIN error only caller can retry on handle based calls
1535 since file handle passed in no longer valid */
1541 CIFSSMBWrite2(const int xid
, struct cifsTconInfo
*tcon
,
1542 const int netfid
, const unsigned int count
,
1543 const __u64 offset
, unsigned int *nbytes
, struct kvec
*iov
,
1544 int n_vec
, const int long_op
)
1547 WRITE_REQ
*pSMB
= NULL
;
1550 int resp_buf_type
= 0;
1554 cFYI(1, ("write2 at %lld %d bytes", (long long)offset
, count
));
1556 if (tcon
->ses
->capabilities
& CAP_LARGE_FILES
) {
1560 if ((offset
>> 32) > 0) {
1561 /* can not handle big offset for old srv */
1565 rc
= small_smb_init(SMB_COM_WRITE_ANDX
, wct
, tcon
, (void **) &pSMB
);
1568 /* tcon and ses pointer are checked in smb_init */
1569 if (tcon
->ses
->server
== NULL
)
1570 return -ECONNABORTED
;
1572 pSMB
->AndXCommand
= 0xFF; /* none */
1574 pSMB
->OffsetLow
= cpu_to_le32(offset
& 0xFFFFFFFF);
1576 pSMB
->OffsetHigh
= cpu_to_le32(offset
>> 32);
1577 pSMB
->Reserved
= 0xFFFFFFFF;
1578 pSMB
->WriteMode
= 0;
1579 pSMB
->Remaining
= 0;
1582 cpu_to_le16(offsetof(struct smb_com_write_req
, Data
) - 4);
1584 pSMB
->DataLengthLow
= cpu_to_le16(count
& 0xFFFF);
1585 pSMB
->DataLengthHigh
= cpu_to_le16(count
>> 16);
1586 smb_hdr_len
= pSMB
->hdr
.smb_buf_length
+ 1; /* hdr + 1 byte pad */
1588 pSMB
->hdr
.smb_buf_length
+= count
+1;
1589 else /* wct == 12 */
1590 pSMB
->hdr
.smb_buf_length
+= count
+5; /* smb data starts later */
1592 pSMB
->ByteCount
= cpu_to_le16(count
+ 1);
1593 else /* wct == 12 */ /* bigger pad, smaller smb hdr, keep offset ok */ {
1594 struct smb_com_writex_req
*pSMBW
=
1595 (struct smb_com_writex_req
*)pSMB
;
1596 pSMBW
->ByteCount
= cpu_to_le16(count
+ 5);
1598 iov
[0].iov_base
= pSMB
;
1600 iov
[0].iov_len
= smb_hdr_len
+ 4;
1601 else /* wct == 12 pad bigger by four bytes */
1602 iov
[0].iov_len
= smb_hdr_len
+ 8;
1605 rc
= SendReceive2(xid
, tcon
->ses
, iov
, n_vec
+ 1, &resp_buf_type
,
1607 cifs_stats_inc(&tcon
->num_writes
);
1609 cFYI(1, ("Send error Write2 = %d", rc
));
1610 } else if (resp_buf_type
== 0) {
1611 /* presumably this can not happen, but best to be safe */
1614 WRITE_RSP
*pSMBr
= (WRITE_RSP
*)iov
[0].iov_base
;
1615 *nbytes
= le16_to_cpu(pSMBr
->CountHigh
);
1616 *nbytes
= (*nbytes
) << 16;
1617 *nbytes
+= le16_to_cpu(pSMBr
->Count
);
1620 * Mask off high 16 bits when bytes written as returned by the
1621 * server is greater than bytes requested by the client. OS/2
1622 * servers are known to set incorrect CountHigh values.
1624 if (*nbytes
> count
)
1628 /* cifs_small_buf_release(pSMB); */ /* Freed earlier now in SendReceive2 */
1629 if (resp_buf_type
== CIFS_SMALL_BUFFER
)
1630 cifs_small_buf_release(iov
[0].iov_base
);
1631 else if (resp_buf_type
== CIFS_LARGE_BUFFER
)
1632 cifs_buf_release(iov
[0].iov_base
);
1634 /* Note: On -EAGAIN error only caller can retry on handle based calls
1635 since file handle passed in no longer valid */
1642 CIFSSMBLock(const int xid
, struct cifsTconInfo
*tcon
,
1643 const __u16 smb_file_id
, const __u64 len
,
1644 const __u64 offset
, const __u32 numUnlock
,
1645 const __u32 numLock
, const __u8 lockType
, const bool waitFlag
)
1648 LOCK_REQ
*pSMB
= NULL
;
1649 /* LOCK_RSP *pSMBr = NULL; */ /* No response data other than rc to parse */
1654 cFYI(1, ("CIFSSMBLock timeout %d numLock %d", (int)waitFlag
, numLock
));
1655 rc
= small_smb_init(SMB_COM_LOCKING_ANDX
, 8, tcon
, (void **) &pSMB
);
1660 if (lockType
== LOCKING_ANDX_OPLOCK_RELEASE
) {
1661 timeout
= CIFS_ASYNC_OP
; /* no response expected */
1663 } else if (waitFlag
) {
1664 timeout
= CIFS_BLOCKING_OP
; /* blocking operation, no timeout */
1665 pSMB
->Timeout
= cpu_to_le32(-1);/* blocking - do not time out */
1670 pSMB
->NumberOfLocks
= cpu_to_le16(numLock
);
1671 pSMB
->NumberOfUnlocks
= cpu_to_le16(numUnlock
);
1672 pSMB
->LockType
= lockType
;
1673 pSMB
->AndXCommand
= 0xFF; /* none */
1674 pSMB
->Fid
= smb_file_id
; /* netfid stays le */
1676 if ((numLock
!= 0) || (numUnlock
!= 0)) {
1677 pSMB
->Locks
[0].Pid
= cpu_to_le16(current
->tgid
);
1678 /* BB where to store pid high? */
1679 pSMB
->Locks
[0].LengthLow
= cpu_to_le32((u32
)len
);
1680 pSMB
->Locks
[0].LengthHigh
= cpu_to_le32((u32
)(len
>>32));
1681 pSMB
->Locks
[0].OffsetLow
= cpu_to_le32((u32
)offset
);
1682 pSMB
->Locks
[0].OffsetHigh
= cpu_to_le32((u32
)(offset
>>32));
1683 count
= sizeof(LOCKING_ANDX_RANGE
);
1688 pSMB
->hdr
.smb_buf_length
+= count
;
1689 pSMB
->ByteCount
= cpu_to_le16(count
);
1692 rc
= SendReceiveBlockingLock(xid
, tcon
, (struct smb_hdr
*) pSMB
,
1693 (struct smb_hdr
*) pSMB
, &bytes_returned
);
1694 cifs_small_buf_release(pSMB
);
1696 rc
= SendReceiveNoRsp(xid
, tcon
->ses
, (struct smb_hdr
*)pSMB
,
1698 /* SMB buffer freed by function above */
1700 cifs_stats_inc(&tcon
->num_locks
);
1702 cFYI(1, ("Send error in Lock = %d", rc
));
1704 /* Note: On -EAGAIN error only caller can retry on handle based calls
1705 since file handle passed in no longer valid */
1710 CIFSSMBPosixLock(const int xid
, struct cifsTconInfo
*tcon
,
1711 const __u16 smb_file_id
, const int get_flag
, const __u64 len
,
1712 struct file_lock
*pLockData
, const __u16 lock_type
,
1713 const bool waitFlag
)
1715 struct smb_com_transaction2_sfi_req
*pSMB
= NULL
;
1716 struct smb_com_transaction2_sfi_rsp
*pSMBr
= NULL
;
1717 struct cifs_posix_lock
*parm_data
;
1720 int bytes_returned
= 0;
1721 int resp_buf_type
= 0;
1722 __u16 params
, param_offset
, offset
, byte_count
, count
;
1725 cFYI(1, ("Posix Lock"));
1727 if (pLockData
== NULL
)
1730 rc
= small_smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
);
1735 pSMBr
= (struct smb_com_transaction2_sfi_rsp
*)pSMB
;
1738 pSMB
->MaxSetupCount
= 0;
1741 pSMB
->Reserved2
= 0;
1742 param_offset
= offsetof(struct smb_com_transaction2_sfi_req
, Fid
) - 4;
1743 offset
= param_offset
+ params
;
1745 count
= sizeof(struct cifs_posix_lock
);
1746 pSMB
->MaxParameterCount
= cpu_to_le16(2);
1747 pSMB
->MaxDataCount
= cpu_to_le16(1000); /* BB find max SMB from sess */
1748 pSMB
->SetupCount
= 1;
1749 pSMB
->Reserved3
= 0;
1751 pSMB
->SubCommand
= cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION
);
1753 pSMB
->SubCommand
= cpu_to_le16(TRANS2_SET_FILE_INFORMATION
);
1754 byte_count
= 3 /* pad */ + params
+ count
;
1755 pSMB
->DataCount
= cpu_to_le16(count
);
1756 pSMB
->ParameterCount
= cpu_to_le16(params
);
1757 pSMB
->TotalDataCount
= pSMB
->DataCount
;
1758 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
1759 pSMB
->ParameterOffset
= cpu_to_le16(param_offset
);
1760 parm_data
= (struct cifs_posix_lock
*)
1761 (((char *) &pSMB
->hdr
.Protocol
) + offset
);
1763 parm_data
->lock_type
= cpu_to_le16(lock_type
);
1765 timeout
= CIFS_BLOCKING_OP
; /* blocking operation, no timeout */
1766 parm_data
->lock_flags
= cpu_to_le16(1);
1767 pSMB
->Timeout
= cpu_to_le32(-1);
1771 parm_data
->pid
= cpu_to_le32(current
->tgid
);
1772 parm_data
->start
= cpu_to_le64(pLockData
->fl_start
);
1773 parm_data
->length
= cpu_to_le64(len
); /* normalize negative numbers */
1775 pSMB
->DataOffset
= cpu_to_le16(offset
);
1776 pSMB
->Fid
= smb_file_id
;
1777 pSMB
->InformationLevel
= cpu_to_le16(SMB_SET_POSIX_LOCK
);
1778 pSMB
->Reserved4
= 0;
1779 pSMB
->hdr
.smb_buf_length
+= byte_count
;
1780 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
1782 rc
= SendReceiveBlockingLock(xid
, tcon
, (struct smb_hdr
*) pSMB
,
1783 (struct smb_hdr
*) pSMBr
, &bytes_returned
);
1785 iov
[0].iov_base
= (char *)pSMB
;
1786 iov
[0].iov_len
= pSMB
->hdr
.smb_buf_length
+ 4;
1787 rc
= SendReceive2(xid
, tcon
->ses
, iov
, 1 /* num iovecs */,
1788 &resp_buf_type
, timeout
);
1789 pSMB
= NULL
; /* request buf already freed by SendReceive2. Do
1790 not try to free it twice below on exit */
1791 pSMBr
= (struct smb_com_transaction2_sfi_rsp
*)iov
[0].iov_base
;
1795 cFYI(1, ("Send error in Posix Lock = %d", rc
));
1796 } else if (get_flag
) {
1797 /* lock structure can be returned on get */
1800 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
1802 if (rc
|| (pSMBr
->ByteCount
< sizeof(struct cifs_posix_lock
))) {
1803 rc
= -EIO
; /* bad smb */
1806 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
1807 data_count
= le16_to_cpu(pSMBr
->t2
.DataCount
);
1808 if (data_count
< sizeof(struct cifs_posix_lock
)) {
1812 parm_data
= (struct cifs_posix_lock
*)
1813 ((char *)&pSMBr
->hdr
.Protocol
+ data_offset
);
1814 if (parm_data
->lock_type
== __constant_cpu_to_le16(CIFS_UNLCK
))
1815 pLockData
->fl_type
= F_UNLCK
;
1817 if (parm_data
->lock_type
==
1818 __constant_cpu_to_le16(CIFS_RDLCK
))
1819 pLockData
->fl_type
= F_RDLCK
;
1820 else if (parm_data
->lock_type
==
1821 __constant_cpu_to_le16(CIFS_WRLCK
))
1822 pLockData
->fl_type
= F_WRLCK
;
1824 pLockData
->fl_start
= parm_data
->start
;
1825 pLockData
->fl_end
= parm_data
->start
+
1826 parm_data
->length
- 1;
1827 pLockData
->fl_pid
= parm_data
->pid
;
1833 cifs_small_buf_release(pSMB
);
1835 if (resp_buf_type
== CIFS_SMALL_BUFFER
)
1836 cifs_small_buf_release(iov
[0].iov_base
);
1837 else if (resp_buf_type
== CIFS_LARGE_BUFFER
)
1838 cifs_buf_release(iov
[0].iov_base
);
1840 /* Note: On -EAGAIN error only caller can retry on handle based calls
1841 since file handle passed in no longer valid */
1848 CIFSSMBClose(const int xid
, struct cifsTconInfo
*tcon
, int smb_file_id
)
1851 CLOSE_REQ
*pSMB
= NULL
;
1852 cFYI(1, ("In CIFSSMBClose"));
1854 /* do not retry on dead session on close */
1855 rc
= small_smb_init(SMB_COM_CLOSE
, 3, tcon
, (void **) &pSMB
);
1861 pSMB
->FileID
= (__u16
) smb_file_id
;
1862 pSMB
->LastWriteTime
= 0xFFFFFFFF;
1863 pSMB
->ByteCount
= 0;
1864 rc
= SendReceiveNoRsp(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
, 0);
1865 cifs_stats_inc(&tcon
->num_closes
);
1868 /* EINTR is expected when user ctl-c to kill app */
1869 cERROR(1, ("Send error in Close = %d", rc
));
1873 /* Since session is dead, file will be closed on server already */
1881 CIFSSMBFlush(const int xid
, struct cifsTconInfo
*tcon
, int smb_file_id
)
1884 FLUSH_REQ
*pSMB
= NULL
;
1885 cFYI(1, ("In CIFSSMBFlush"));
1887 rc
= small_smb_init(SMB_COM_FLUSH
, 1, tcon
, (void **) &pSMB
);
1891 pSMB
->FileID
= (__u16
) smb_file_id
;
1892 pSMB
->ByteCount
= 0;
1893 rc
= SendReceiveNoRsp(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
, 0);
1894 cifs_stats_inc(&tcon
->num_flushes
);
1896 cERROR(1, ("Send error in Flush = %d", rc
));
1902 CIFSSMBRename(const int xid
, struct cifsTconInfo
*tcon
,
1903 const char *fromName
, const char *toName
,
1904 const struct nls_table
*nls_codepage
, int remap
)
1907 RENAME_REQ
*pSMB
= NULL
;
1908 RENAME_RSP
*pSMBr
= NULL
;
1910 int name_len
, name_len2
;
1913 cFYI(1, ("In CIFSSMBRename"));
1915 rc
= smb_init(SMB_COM_RENAME
, 1, tcon
, (void **) &pSMB
,
1920 pSMB
->BufferFormat
= 0x04;
1921 pSMB
->SearchAttributes
=
1922 cpu_to_le16(ATTR_READONLY
| ATTR_HIDDEN
| ATTR_SYSTEM
|
1925 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
1927 cifsConvertToUCS((__le16
*) pSMB
->OldFileName
, fromName
,
1928 PATH_MAX
, nls_codepage
, remap
);
1929 name_len
++; /* trailing null */
1931 pSMB
->OldFileName
[name_len
] = 0x04; /* pad */
1932 /* protocol requires ASCII signature byte on Unicode string */
1933 pSMB
->OldFileName
[name_len
+ 1] = 0x00;
1935 cifsConvertToUCS((__le16
*)&pSMB
->OldFileName
[name_len
+ 2],
1936 toName
, PATH_MAX
, nls_codepage
, remap
);
1937 name_len2
+= 1 /* trailing null */ + 1 /* Signature word */ ;
1938 name_len2
*= 2; /* convert to bytes */
1939 } else { /* BB improve the check for buffer overruns BB */
1940 name_len
= strnlen(fromName
, PATH_MAX
);
1941 name_len
++; /* trailing null */
1942 strncpy(pSMB
->OldFileName
, fromName
, name_len
);
1943 name_len2
= strnlen(toName
, PATH_MAX
);
1944 name_len2
++; /* trailing null */
1945 pSMB
->OldFileName
[name_len
] = 0x04; /* 2nd buffer format */
1946 strncpy(&pSMB
->OldFileName
[name_len
+ 1], toName
, name_len2
);
1947 name_len2
++; /* trailing null */
1948 name_len2
++; /* signature byte */
1951 count
= 1 /* 1st signature byte */ + name_len
+ name_len2
;
1952 pSMB
->hdr
.smb_buf_length
+= count
;
1953 pSMB
->ByteCount
= cpu_to_le16(count
);
1955 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
1956 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
1957 cifs_stats_inc(&tcon
->num_renames
);
1959 cFYI(1, ("Send error in rename = %d", rc
));
1961 cifs_buf_release(pSMB
);
1969 int CIFSSMBRenameOpenFile(const int xid
, struct cifsTconInfo
*pTcon
,
1970 int netfid
, const char *target_name
,
1971 const struct nls_table
*nls_codepage
, int remap
)
1973 struct smb_com_transaction2_sfi_req
*pSMB
= NULL
;
1974 struct smb_com_transaction2_sfi_rsp
*pSMBr
= NULL
;
1975 struct set_file_rename
*rename_info
;
1977 char dummy_string
[30];
1979 int bytes_returned
= 0;
1981 __u16 params
, param_offset
, offset
, count
, byte_count
;
1983 cFYI(1, ("Rename to File by handle"));
1984 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, pTcon
, (void **) &pSMB
,
1990 pSMB
->MaxSetupCount
= 0;
1994 pSMB
->Reserved2
= 0;
1995 param_offset
= offsetof(struct smb_com_transaction2_sfi_req
, Fid
) - 4;
1996 offset
= param_offset
+ params
;
1998 data_offset
= (char *) (&pSMB
->hdr
.Protocol
) + offset
;
1999 rename_info
= (struct set_file_rename
*) data_offset
;
2000 pSMB
->MaxParameterCount
= cpu_to_le16(2);
2001 pSMB
->MaxDataCount
= cpu_to_le16(1000); /* BB find max SMB from sess */
2002 pSMB
->SetupCount
= 1;
2003 pSMB
->Reserved3
= 0;
2004 pSMB
->SubCommand
= cpu_to_le16(TRANS2_SET_FILE_INFORMATION
);
2005 byte_count
= 3 /* pad */ + params
;
2006 pSMB
->ParameterCount
= cpu_to_le16(params
);
2007 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
2008 pSMB
->ParameterOffset
= cpu_to_le16(param_offset
);
2009 pSMB
->DataOffset
= cpu_to_le16(offset
);
2010 /* construct random name ".cifs_tmp<inodenum><mid>" */
2011 rename_info
->overwrite
= cpu_to_le32(1);
2012 rename_info
->root_fid
= 0;
2013 /* unicode only call */
2014 if (target_name
== NULL
) {
2015 sprintf(dummy_string
, "cifs%x", pSMB
->hdr
.Mid
);
2016 len_of_str
= cifsConvertToUCS((__le16
*)rename_info
->target_name
,
2017 dummy_string
, 24, nls_codepage
, remap
);
2019 len_of_str
= cifsConvertToUCS((__le16
*)rename_info
->target_name
,
2020 target_name
, PATH_MAX
, nls_codepage
,
2023 rename_info
->target_name_len
= cpu_to_le32(2 * len_of_str
);
2024 count
= 12 /* sizeof(struct set_file_rename) */ + (2 * len_of_str
);
2025 byte_count
+= count
;
2026 pSMB
->DataCount
= cpu_to_le16(count
);
2027 pSMB
->TotalDataCount
= pSMB
->DataCount
;
2029 pSMB
->InformationLevel
=
2030 cpu_to_le16(SMB_SET_FILE_RENAME_INFORMATION
);
2031 pSMB
->Reserved4
= 0;
2032 pSMB
->hdr
.smb_buf_length
+= byte_count
;
2033 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
2034 rc
= SendReceive(xid
, pTcon
->ses
, (struct smb_hdr
*) pSMB
,
2035 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
2036 cifs_stats_inc(&pTcon
->num_t2renames
);
2038 cFYI(1, ("Send error in Rename (by file handle) = %d", rc
));
2040 cifs_buf_release(pSMB
);
2042 /* Note: On -EAGAIN error only caller can retry on handle based calls
2043 since file handle passed in no longer valid */
2049 CIFSSMBCopy(const int xid
, struct cifsTconInfo
*tcon
, const char *fromName
,
2050 const __u16 target_tid
, const char *toName
, const int flags
,
2051 const struct nls_table
*nls_codepage
, int remap
)
2054 COPY_REQ
*pSMB
= NULL
;
2055 COPY_RSP
*pSMBr
= NULL
;
2057 int name_len
, name_len2
;
2060 cFYI(1, ("In CIFSSMBCopy"));
2062 rc
= smb_init(SMB_COM_COPY
, 1, tcon
, (void **) &pSMB
,
2067 pSMB
->BufferFormat
= 0x04;
2068 pSMB
->Tid2
= target_tid
;
2070 pSMB
->Flags
= cpu_to_le16(flags
& COPY_TREE
);
2072 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
2073 name_len
= cifsConvertToUCS((__le16
*) pSMB
->OldFileName
,
2074 fromName
, PATH_MAX
, nls_codepage
,
2076 name_len
++; /* trailing null */
2078 pSMB
->OldFileName
[name_len
] = 0x04; /* pad */
2079 /* protocol requires ASCII signature byte on Unicode string */
2080 pSMB
->OldFileName
[name_len
+ 1] = 0x00;
2082 cifsConvertToUCS((__le16
*)&pSMB
->OldFileName
[name_len
+ 2],
2083 toName
, PATH_MAX
, nls_codepage
, remap
);
2084 name_len2
+= 1 /* trailing null */ + 1 /* Signature word */ ;
2085 name_len2
*= 2; /* convert to bytes */
2086 } else { /* BB improve the check for buffer overruns BB */
2087 name_len
= strnlen(fromName
, PATH_MAX
);
2088 name_len
++; /* trailing null */
2089 strncpy(pSMB
->OldFileName
, fromName
, name_len
);
2090 name_len2
= strnlen(toName
, PATH_MAX
);
2091 name_len2
++; /* trailing null */
2092 pSMB
->OldFileName
[name_len
] = 0x04; /* 2nd buffer format */
2093 strncpy(&pSMB
->OldFileName
[name_len
+ 1], toName
, name_len2
);
2094 name_len2
++; /* trailing null */
2095 name_len2
++; /* signature byte */
2098 count
= 1 /* 1st signature byte */ + name_len
+ name_len2
;
2099 pSMB
->hdr
.smb_buf_length
+= count
;
2100 pSMB
->ByteCount
= cpu_to_le16(count
);
2102 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
2103 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
2105 cFYI(1, ("Send error in copy = %d with %d files copied",
2106 rc
, le16_to_cpu(pSMBr
->CopyCount
)));
2108 cifs_buf_release(pSMB
);
2117 CIFSUnixCreateSymLink(const int xid
, struct cifsTconInfo
*tcon
,
2118 const char *fromName
, const char *toName
,
2119 const struct nls_table
*nls_codepage
)
2121 TRANSACTION2_SPI_REQ
*pSMB
= NULL
;
2122 TRANSACTION2_SPI_RSP
*pSMBr
= NULL
;
2125 int name_len_target
;
2127 int bytes_returned
= 0;
2128 __u16 params
, param_offset
, offset
, byte_count
;
2130 cFYI(1, ("In Symlink Unix style"));
2132 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
2137 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
2139 cifs_strtoUCS((__le16
*) pSMB
->FileName
, fromName
, PATH_MAX
2140 /* find define for this maxpathcomponent */
2142 name_len
++; /* trailing null */
2145 } else { /* BB improve the check for buffer overruns BB */
2146 name_len
= strnlen(fromName
, PATH_MAX
);
2147 name_len
++; /* trailing null */
2148 strncpy(pSMB
->FileName
, fromName
, name_len
);
2150 params
= 6 + name_len
;
2151 pSMB
->MaxSetupCount
= 0;
2155 pSMB
->Reserved2
= 0;
2156 param_offset
= offsetof(struct smb_com_transaction2_spi_req
,
2157 InformationLevel
) - 4;
2158 offset
= param_offset
+ params
;
2160 data_offset
= (char *) (&pSMB
->hdr
.Protocol
) + offset
;
2161 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
2163 cifs_strtoUCS((__le16
*) data_offset
, toName
, PATH_MAX
2164 /* find define for this maxpathcomponent */
2166 name_len_target
++; /* trailing null */
2167 name_len_target
*= 2;
2168 } else { /* BB improve the check for buffer overruns BB */
2169 name_len_target
= strnlen(toName
, PATH_MAX
);
2170 name_len_target
++; /* trailing null */
2171 strncpy(data_offset
, toName
, name_len_target
);
2174 pSMB
->MaxParameterCount
= cpu_to_le16(2);
2175 /* BB find exact max on data count below from sess */
2176 pSMB
->MaxDataCount
= cpu_to_le16(1000);
2177 pSMB
->SetupCount
= 1;
2178 pSMB
->Reserved3
= 0;
2179 pSMB
->SubCommand
= cpu_to_le16(TRANS2_SET_PATH_INFORMATION
);
2180 byte_count
= 3 /* pad */ + params
+ name_len_target
;
2181 pSMB
->DataCount
= cpu_to_le16(name_len_target
);
2182 pSMB
->ParameterCount
= cpu_to_le16(params
);
2183 pSMB
->TotalDataCount
= pSMB
->DataCount
;
2184 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
2185 pSMB
->ParameterOffset
= cpu_to_le16(param_offset
);
2186 pSMB
->DataOffset
= cpu_to_le16(offset
);
2187 pSMB
->InformationLevel
= cpu_to_le16(SMB_SET_FILE_UNIX_LINK
);
2188 pSMB
->Reserved4
= 0;
2189 pSMB
->hdr
.smb_buf_length
+= byte_count
;
2190 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
2191 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
2192 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
2193 cifs_stats_inc(&tcon
->num_symlinks
);
2195 cFYI(1, ("Send error in SetPathInfo create symlink = %d", rc
));
2197 cifs_buf_release(pSMB
);
2200 goto createSymLinkRetry
;
2206 CIFSUnixCreateHardLink(const int xid
, struct cifsTconInfo
*tcon
,
2207 const char *fromName
, const char *toName
,
2208 const struct nls_table
*nls_codepage
, int remap
)
2210 TRANSACTION2_SPI_REQ
*pSMB
= NULL
;
2211 TRANSACTION2_SPI_RSP
*pSMBr
= NULL
;
2214 int name_len_target
;
2216 int bytes_returned
= 0;
2217 __u16 params
, param_offset
, offset
, byte_count
;
2219 cFYI(1, ("In Create Hard link Unix style"));
2220 createHardLinkRetry
:
2221 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
2226 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
2227 name_len
= cifsConvertToUCS((__le16
*) pSMB
->FileName
, toName
,
2228 PATH_MAX
, nls_codepage
, remap
);
2229 name_len
++; /* trailing null */
2232 } else { /* BB improve the check for buffer overruns BB */
2233 name_len
= strnlen(toName
, PATH_MAX
);
2234 name_len
++; /* trailing null */
2235 strncpy(pSMB
->FileName
, toName
, name_len
);
2237 params
= 6 + name_len
;
2238 pSMB
->MaxSetupCount
= 0;
2242 pSMB
->Reserved2
= 0;
2243 param_offset
= offsetof(struct smb_com_transaction2_spi_req
,
2244 InformationLevel
) - 4;
2245 offset
= param_offset
+ params
;
2247 data_offset
= (char *) (&pSMB
->hdr
.Protocol
) + offset
;
2248 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
2250 cifsConvertToUCS((__le16
*) data_offset
, fromName
, PATH_MAX
,
2251 nls_codepage
, remap
);
2252 name_len_target
++; /* trailing null */
2253 name_len_target
*= 2;
2254 } else { /* BB improve the check for buffer overruns BB */
2255 name_len_target
= strnlen(fromName
, PATH_MAX
);
2256 name_len_target
++; /* trailing null */
2257 strncpy(data_offset
, fromName
, name_len_target
);
2260 pSMB
->MaxParameterCount
= cpu_to_le16(2);
2261 /* BB find exact max on data count below from sess*/
2262 pSMB
->MaxDataCount
= cpu_to_le16(1000);
2263 pSMB
->SetupCount
= 1;
2264 pSMB
->Reserved3
= 0;
2265 pSMB
->SubCommand
= cpu_to_le16(TRANS2_SET_PATH_INFORMATION
);
2266 byte_count
= 3 /* pad */ + params
+ name_len_target
;
2267 pSMB
->ParameterCount
= cpu_to_le16(params
);
2268 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
2269 pSMB
->DataCount
= cpu_to_le16(name_len_target
);
2270 pSMB
->TotalDataCount
= pSMB
->DataCount
;
2271 pSMB
->ParameterOffset
= cpu_to_le16(param_offset
);
2272 pSMB
->DataOffset
= cpu_to_le16(offset
);
2273 pSMB
->InformationLevel
= cpu_to_le16(SMB_SET_FILE_UNIX_HLINK
);
2274 pSMB
->Reserved4
= 0;
2275 pSMB
->hdr
.smb_buf_length
+= byte_count
;
2276 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
2277 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
2278 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
2279 cifs_stats_inc(&tcon
->num_hardlinks
);
2281 cFYI(1, ("Send error in SetPathInfo (hard link) = %d", rc
));
2283 cifs_buf_release(pSMB
);
2285 goto createHardLinkRetry
;
2291 CIFSCreateHardLink(const int xid
, struct cifsTconInfo
*tcon
,
2292 const char *fromName
, const char *toName
,
2293 const struct nls_table
*nls_codepage
, int remap
)
2296 NT_RENAME_REQ
*pSMB
= NULL
;
2297 RENAME_RSP
*pSMBr
= NULL
;
2299 int name_len
, name_len2
;
2302 cFYI(1, ("In CIFSCreateHardLink"));
2303 winCreateHardLinkRetry
:
2305 rc
= smb_init(SMB_COM_NT_RENAME
, 4, tcon
, (void **) &pSMB
,
2310 pSMB
->SearchAttributes
=
2311 cpu_to_le16(ATTR_READONLY
| ATTR_HIDDEN
| ATTR_SYSTEM
|
2313 pSMB
->Flags
= cpu_to_le16(CREATE_HARD_LINK
);
2314 pSMB
->ClusterCount
= 0;
2316 pSMB
->BufferFormat
= 0x04;
2318 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
2320 cifsConvertToUCS((__le16
*) pSMB
->OldFileName
, fromName
,
2321 PATH_MAX
, nls_codepage
, remap
);
2322 name_len
++; /* trailing null */
2325 /* protocol specifies ASCII buffer format (0x04) for unicode */
2326 pSMB
->OldFileName
[name_len
] = 0x04;
2327 pSMB
->OldFileName
[name_len
+ 1] = 0x00; /* pad */
2329 cifsConvertToUCS((__le16
*)&pSMB
->OldFileName
[name_len
+ 2],
2330 toName
, PATH_MAX
, nls_codepage
, remap
);
2331 name_len2
+= 1 /* trailing null */ + 1 /* Signature word */ ;
2332 name_len2
*= 2; /* convert to bytes */
2333 } else { /* BB improve the check for buffer overruns BB */
2334 name_len
= strnlen(fromName
, PATH_MAX
);
2335 name_len
++; /* trailing null */
2336 strncpy(pSMB
->OldFileName
, fromName
, name_len
);
2337 name_len2
= strnlen(toName
, PATH_MAX
);
2338 name_len2
++; /* trailing null */
2339 pSMB
->OldFileName
[name_len
] = 0x04; /* 2nd buffer format */
2340 strncpy(&pSMB
->OldFileName
[name_len
+ 1], toName
, name_len2
);
2341 name_len2
++; /* trailing null */
2342 name_len2
++; /* signature byte */
2345 count
= 1 /* string type byte */ + name_len
+ name_len2
;
2346 pSMB
->hdr
.smb_buf_length
+= count
;
2347 pSMB
->ByteCount
= cpu_to_le16(count
);
2349 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
2350 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
2351 cifs_stats_inc(&tcon
->num_hardlinks
);
2353 cFYI(1, ("Send error in hard link (NT rename) = %d", rc
));
2355 cifs_buf_release(pSMB
);
2357 goto winCreateHardLinkRetry
;
2363 CIFSSMBUnixQuerySymLink(const int xid
, struct cifsTconInfo
*tcon
,
2364 const unsigned char *searchName
, char **symlinkinfo
,
2365 const struct nls_table
*nls_codepage
)
2367 /* SMB_QUERY_FILE_UNIX_LINK */
2368 TRANSACTION2_QPI_REQ
*pSMB
= NULL
;
2369 TRANSACTION2_QPI_RSP
*pSMBr
= NULL
;
2373 __u16 params
, byte_count
;
2376 cFYI(1, ("In QPathSymLinkInfo (Unix) for path %s", searchName
));
2379 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
2384 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
2386 cifs_strtoUCS((__le16
*) pSMB
->FileName
, searchName
,
2387 PATH_MAX
, nls_codepage
);
2388 name_len
++; /* trailing null */
2390 } else { /* BB improve the check for buffer overruns BB */
2391 name_len
= strnlen(searchName
, PATH_MAX
);
2392 name_len
++; /* trailing null */
2393 strncpy(pSMB
->FileName
, searchName
, name_len
);
2396 params
= 2 /* level */ + 4 /* rsrvd */ + name_len
/* incl null */ ;
2397 pSMB
->TotalDataCount
= 0;
2398 pSMB
->MaxParameterCount
= cpu_to_le16(2);
2399 pSMB
->MaxDataCount
= cpu_to_le16(CIFSMaxBufSize
);
2400 pSMB
->MaxSetupCount
= 0;
2404 pSMB
->Reserved2
= 0;
2405 pSMB
->ParameterOffset
= cpu_to_le16(offsetof(
2406 struct smb_com_transaction2_qpi_req
, InformationLevel
) - 4);
2407 pSMB
->DataCount
= 0;
2408 pSMB
->DataOffset
= 0;
2409 pSMB
->SetupCount
= 1;
2410 pSMB
->Reserved3
= 0;
2411 pSMB
->SubCommand
= cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION
);
2412 byte_count
= params
+ 1 /* pad */ ;
2413 pSMB
->TotalParameterCount
= cpu_to_le16(params
);
2414 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
2415 pSMB
->InformationLevel
= cpu_to_le16(SMB_QUERY_FILE_UNIX_LINK
);
2416 pSMB
->Reserved4
= 0;
2417 pSMB
->hdr
.smb_buf_length
+= byte_count
;
2418 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
2420 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
2421 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
2423 cFYI(1, ("Send error in QuerySymLinkInfo = %d", rc
));
2425 /* decode response */
2427 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
2428 /* BB also check enough total bytes returned */
2429 if (rc
|| (pSMBr
->ByteCount
< 2))
2433 u16 count
= le16_to_cpu(pSMBr
->t2
.DataCount
);
2435 data_start
= ((char *) &pSMBr
->hdr
.Protocol
) +
2436 le16_to_cpu(pSMBr
->t2
.DataOffset
);
2438 if (pSMBr
->hdr
.Flags2
& SMBFLG2_UNICODE
)
2443 /* BB FIXME investigate remapping reserved chars here */
2444 *symlinkinfo
= cifs_strndup_from_ucs(data_start
, count
,
2445 is_unicode
, nls_codepage
);
2450 cifs_buf_release(pSMB
);
2452 goto querySymLinkRetry
;
2456 #ifdef CONFIG_CIFS_EXPERIMENTAL
2457 /* Initialize NT TRANSACT SMB into small smb request buffer.
2458 This assumes that all NT TRANSACTS that we init here have
2459 total parm and data under about 400 bytes (to fit in small cifs
2460 buffer size), which is the case so far, it easily fits. NB:
2461 Setup words themselves and ByteCount
2462 MaxSetupCount (size of returned setup area) and
2463 MaxParameterCount (returned parms size) must be set by caller */
2465 smb_init_nttransact(const __u16 sub_command
, const int setup_count
,
2466 const int parm_len
, struct cifsTconInfo
*tcon
,
2471 struct smb_com_ntransact_req
*pSMB
;
2473 rc
= small_smb_init(SMB_COM_NT_TRANSACT
, 19 + setup_count
, tcon
,
2477 *ret_buf
= (void *)pSMB
;
2479 pSMB
->TotalParameterCount
= cpu_to_le32(parm_len
);
2480 pSMB
->TotalDataCount
= 0;
2481 pSMB
->MaxDataCount
= cpu_to_le32((tcon
->ses
->server
->maxBuf
-
2482 MAX_CIFS_HDR_SIZE
) & 0xFFFFFF00);
2483 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
2484 pSMB
->DataCount
= pSMB
->TotalDataCount
;
2485 temp_offset
= offsetof(struct smb_com_ntransact_req
, Parms
) +
2486 (setup_count
* 2) - 4 /* for rfc1001 length itself */;
2487 pSMB
->ParameterOffset
= cpu_to_le32(temp_offset
);
2488 pSMB
->DataOffset
= cpu_to_le32(temp_offset
+ parm_len
);
2489 pSMB
->SetupCount
= setup_count
; /* no need to le convert byte fields */
2490 pSMB
->SubCommand
= cpu_to_le16(sub_command
);
2495 validate_ntransact(char *buf
, char **ppparm
, char **ppdata
,
2496 __u32
*pparmlen
, __u32
*pdatalen
)
2499 __u32 data_count
, data_offset
, parm_count
, parm_offset
;
2500 struct smb_com_ntransact_rsp
*pSMBr
;
2508 pSMBr
= (struct smb_com_ntransact_rsp
*)buf
;
2510 /* ByteCount was converted from little endian in SendReceive */
2511 end_of_smb
= 2 /* sizeof byte count */ + pSMBr
->ByteCount
+
2512 (char *)&pSMBr
->ByteCount
;
2514 data_offset
= le32_to_cpu(pSMBr
->DataOffset
);
2515 data_count
= le32_to_cpu(pSMBr
->DataCount
);
2516 parm_offset
= le32_to_cpu(pSMBr
->ParameterOffset
);
2517 parm_count
= le32_to_cpu(pSMBr
->ParameterCount
);
2519 *ppparm
= (char *)&pSMBr
->hdr
.Protocol
+ parm_offset
;
2520 *ppdata
= (char *)&pSMBr
->hdr
.Protocol
+ data_offset
;
2522 /* should we also check that parm and data areas do not overlap? */
2523 if (*ppparm
> end_of_smb
) {
2524 cFYI(1, ("parms start after end of smb"));
2526 } else if (parm_count
+ *ppparm
> end_of_smb
) {
2527 cFYI(1, ("parm end after end of smb"));
2529 } else if (*ppdata
> end_of_smb
) {
2530 cFYI(1, ("data starts after end of smb"));
2532 } else if (data_count
+ *ppdata
> end_of_smb
) {
2533 cFYI(1, ("data %p + count %d (%p) ends after end of smb %p start %p",
2534 *ppdata
, data_count
, (data_count
+ *ppdata
),
2535 end_of_smb
, pSMBr
));
2537 } else if (parm_count
+ data_count
> pSMBr
->ByteCount
) {
2538 cFYI(1, ("parm count and data count larger than SMB"));
2541 *pdatalen
= data_count
;
2542 *pparmlen
= parm_count
;
2547 CIFSSMBQueryReparseLinkInfo(const int xid
, struct cifsTconInfo
*tcon
,
2548 const unsigned char *searchName
,
2549 char *symlinkinfo
, const int buflen
, __u16 fid
,
2550 const struct nls_table
*nls_codepage
)
2554 struct smb_com_transaction_ioctl_req
*pSMB
;
2555 struct smb_com_transaction_ioctl_rsp
*pSMBr
;
2557 cFYI(1, ("In Windows reparse style QueryLink for path %s", searchName
));
2558 rc
= smb_init(SMB_COM_NT_TRANSACT
, 23, tcon
, (void **) &pSMB
,
2563 pSMB
->TotalParameterCount
= 0 ;
2564 pSMB
->TotalDataCount
= 0;
2565 pSMB
->MaxParameterCount
= cpu_to_le32(2);
2566 /* BB find exact data count max from sess structure BB */
2567 pSMB
->MaxDataCount
= cpu_to_le32((tcon
->ses
->server
->maxBuf
-
2568 MAX_CIFS_HDR_SIZE
) & 0xFFFFFF00);
2569 pSMB
->MaxSetupCount
= 4;
2571 pSMB
->ParameterOffset
= 0;
2572 pSMB
->DataCount
= 0;
2573 pSMB
->DataOffset
= 0;
2574 pSMB
->SetupCount
= 4;
2575 pSMB
->SubCommand
= cpu_to_le16(NT_TRANSACT_IOCTL
);
2576 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
2577 pSMB
->FunctionCode
= cpu_to_le32(FSCTL_GET_REPARSE_POINT
);
2578 pSMB
->IsFsctl
= 1; /* FSCTL */
2579 pSMB
->IsRootFlag
= 0;
2580 pSMB
->Fid
= fid
; /* file handle always le */
2581 pSMB
->ByteCount
= 0;
2583 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
2584 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
2586 cFYI(1, ("Send error in QueryReparseLinkInfo = %d", rc
));
2587 } else { /* decode response */
2588 __u32 data_offset
= le32_to_cpu(pSMBr
->DataOffset
);
2589 __u32 data_count
= le32_to_cpu(pSMBr
->DataCount
);
2590 if ((pSMBr
->ByteCount
< 2) || (data_offset
> 512)) {
2591 /* BB also check enough total bytes returned */
2592 rc
= -EIO
; /* bad smb */
2595 if (data_count
&& (data_count
< 2048)) {
2596 char *end_of_smb
= 2 /* sizeof byte count */ +
2597 pSMBr
->ByteCount
+ (char *)&pSMBr
->ByteCount
;
2599 struct reparse_data
*reparse_buf
=
2600 (struct reparse_data
*)
2601 ((char *)&pSMBr
->hdr
.Protocol
2603 if ((char *)reparse_buf
>= end_of_smb
) {
2607 if ((reparse_buf
->LinkNamesBuf
+
2608 reparse_buf
->TargetNameOffset
+
2609 reparse_buf
->TargetNameLen
) > end_of_smb
) {
2610 cFYI(1, ("reparse buf beyond SMB"));
2615 if (pSMBr
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
2616 cifs_from_ucs2(symlinkinfo
, (__le16
*)
2617 (reparse_buf
->LinkNamesBuf
+
2618 reparse_buf
->TargetNameOffset
),
2620 reparse_buf
->TargetNameLen
,
2622 } else { /* ASCII names */
2623 strncpy(symlinkinfo
,
2624 reparse_buf
->LinkNamesBuf
+
2625 reparse_buf
->TargetNameOffset
,
2626 min_t(const int, buflen
,
2627 reparse_buf
->TargetNameLen
));
2631 cFYI(1, ("Invalid return data count on "
2632 "get reparse info ioctl"));
2634 symlinkinfo
[buflen
] = 0; /* just in case so the caller
2635 does not go off the end of the buffer */
2636 cFYI(1, ("readlink result - %s", symlinkinfo
));
2640 cifs_buf_release(pSMB
);
2642 /* Note: On -EAGAIN error only caller can retry on handle based calls
2643 since file handle passed in no longer valid */
2647 #endif /* CIFS_EXPERIMENTAL */
2649 #ifdef CONFIG_CIFS_POSIX
2651 /*Convert an Access Control Entry from wire format to local POSIX xattr format*/
2652 static void cifs_convert_ace(posix_acl_xattr_entry
*ace
,
2653 struct cifs_posix_ace
*cifs_ace
)
2655 /* u8 cifs fields do not need le conversion */
2656 ace
->e_perm
= cpu_to_le16(cifs_ace
->cifs_e_perm
);
2657 ace
->e_tag
= cpu_to_le16(cifs_ace
->cifs_e_tag
);
2658 ace
->e_id
= cpu_to_le32(le64_to_cpu(cifs_ace
->cifs_uid
));
2659 /* cFYI(1,("perm %d tag %d id %d",ace->e_perm,ace->e_tag,ace->e_id)); */
2664 /* Convert ACL from CIFS POSIX wire format to local Linux POSIX ACL xattr */
2665 static int cifs_copy_posix_acl(char *trgt
, char *src
, const int buflen
,
2666 const int acl_type
, const int size_of_data_area
)
2671 struct cifs_posix_ace
*pACE
;
2672 struct cifs_posix_acl
*cifs_acl
= (struct cifs_posix_acl
*)src
;
2673 posix_acl_xattr_header
*local_acl
= (posix_acl_xattr_header
*)trgt
;
2675 if (le16_to_cpu(cifs_acl
->version
) != CIFS_ACL_VERSION
)
2678 if (acl_type
& ACL_TYPE_ACCESS
) {
2679 count
= le16_to_cpu(cifs_acl
->access_entry_count
);
2680 pACE
= &cifs_acl
->ace_array
[0];
2681 size
= sizeof(struct cifs_posix_acl
);
2682 size
+= sizeof(struct cifs_posix_ace
) * count
;
2683 /* check if we would go beyond end of SMB */
2684 if (size_of_data_area
< size
) {
2685 cFYI(1, ("bad CIFS POSIX ACL size %d vs. %d",
2686 size_of_data_area
, size
));
2689 } else if (acl_type
& ACL_TYPE_DEFAULT
) {
2690 count
= le16_to_cpu(cifs_acl
->access_entry_count
);
2691 size
= sizeof(struct cifs_posix_acl
);
2692 size
+= sizeof(struct cifs_posix_ace
) * count
;
2693 /* skip past access ACEs to get to default ACEs */
2694 pACE
= &cifs_acl
->ace_array
[count
];
2695 count
= le16_to_cpu(cifs_acl
->default_entry_count
);
2696 size
+= sizeof(struct cifs_posix_ace
) * count
;
2697 /* check if we would go beyond end of SMB */
2698 if (size_of_data_area
< size
)
2705 size
= posix_acl_xattr_size(count
);
2706 if ((buflen
== 0) || (local_acl
== NULL
)) {
2707 /* used to query ACL EA size */
2708 } else if (size
> buflen
) {
2710 } else /* buffer big enough */ {
2711 local_acl
->a_version
= cpu_to_le32(POSIX_ACL_XATTR_VERSION
);
2712 for (i
= 0; i
< count
; i
++) {
2713 cifs_convert_ace(&local_acl
->a_entries
[i
], pACE
);
2720 static __u16
convert_ace_to_cifs_ace(struct cifs_posix_ace
*cifs_ace
,
2721 const posix_acl_xattr_entry
*local_ace
)
2723 __u16 rc
= 0; /* 0 = ACL converted ok */
2725 cifs_ace
->cifs_e_perm
= le16_to_cpu(local_ace
->e_perm
);
2726 cifs_ace
->cifs_e_tag
= le16_to_cpu(local_ace
->e_tag
);
2727 /* BB is there a better way to handle the large uid? */
2728 if (local_ace
->e_id
== cpu_to_le32(-1)) {
2729 /* Probably no need to le convert -1 on any arch but can not hurt */
2730 cifs_ace
->cifs_uid
= cpu_to_le64(-1);
2732 cifs_ace
->cifs_uid
= cpu_to_le64(le32_to_cpu(local_ace
->e_id
));
2733 /*cFYI(1,("perm %d tag %d id %d",ace->e_perm,ace->e_tag,ace->e_id));*/
2737 /* Convert ACL from local Linux POSIX xattr to CIFS POSIX ACL wire format */
2738 static __u16
ACL_to_cifs_posix(char *parm_data
, const char *pACL
,
2739 const int buflen
, const int acl_type
)
2742 struct cifs_posix_acl
*cifs_acl
= (struct cifs_posix_acl
*)parm_data
;
2743 posix_acl_xattr_header
*local_acl
= (posix_acl_xattr_header
*)pACL
;
2747 if ((buflen
== 0) || (pACL
== NULL
) || (cifs_acl
== NULL
))
2750 count
= posix_acl_xattr_count((size_t)buflen
);
2751 cFYI(1, ("setting acl with %d entries from buf of length %d and "
2753 count
, buflen
, le32_to_cpu(local_acl
->a_version
)));
2754 if (le32_to_cpu(local_acl
->a_version
) != 2) {
2755 cFYI(1, ("unknown POSIX ACL version %d",
2756 le32_to_cpu(local_acl
->a_version
)));
2759 cifs_acl
->version
= cpu_to_le16(1);
2760 if (acl_type
== ACL_TYPE_ACCESS
)
2761 cifs_acl
->access_entry_count
= cpu_to_le16(count
);
2762 else if (acl_type
== ACL_TYPE_DEFAULT
)
2763 cifs_acl
->default_entry_count
= cpu_to_le16(count
);
2765 cFYI(1, ("unknown ACL type %d", acl_type
));
2768 for (i
= 0; i
< count
; i
++) {
2769 rc
= convert_ace_to_cifs_ace(&cifs_acl
->ace_array
[i
],
2770 &local_acl
->a_entries
[i
]);
2772 /* ACE not converted */
2777 rc
= (__u16
)(count
* sizeof(struct cifs_posix_ace
));
2778 rc
+= sizeof(struct cifs_posix_acl
);
2779 /* BB add check to make sure ACL does not overflow SMB */
2785 CIFSSMBGetPosixACL(const int xid
, struct cifsTconInfo
*tcon
,
2786 const unsigned char *searchName
,
2787 char *acl_inf
, const int buflen
, const int acl_type
,
2788 const struct nls_table
*nls_codepage
, int remap
)
2790 /* SMB_QUERY_POSIX_ACL */
2791 TRANSACTION2_QPI_REQ
*pSMB
= NULL
;
2792 TRANSACTION2_QPI_RSP
*pSMBr
= NULL
;
2796 __u16 params
, byte_count
;
2798 cFYI(1, ("In GetPosixACL (Unix) for path %s", searchName
));
2801 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
2806 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
2808 cifsConvertToUCS((__le16
*) pSMB
->FileName
, searchName
,
2809 PATH_MAX
, nls_codepage
, remap
);
2810 name_len
++; /* trailing null */
2812 pSMB
->FileName
[name_len
] = 0;
2813 pSMB
->FileName
[name_len
+1] = 0;
2814 } else { /* BB improve the check for buffer overruns BB */
2815 name_len
= strnlen(searchName
, PATH_MAX
);
2816 name_len
++; /* trailing null */
2817 strncpy(pSMB
->FileName
, searchName
, name_len
);
2820 params
= 2 /* level */ + 4 /* rsrvd */ + name_len
/* incl null */ ;
2821 pSMB
->TotalDataCount
= 0;
2822 pSMB
->MaxParameterCount
= cpu_to_le16(2);
2823 /* BB find exact max data count below from sess structure BB */
2824 pSMB
->MaxDataCount
= cpu_to_le16(4000);
2825 pSMB
->MaxSetupCount
= 0;
2829 pSMB
->Reserved2
= 0;
2830 pSMB
->ParameterOffset
= cpu_to_le16(
2831 offsetof(struct smb_com_transaction2_qpi_req
,
2832 InformationLevel
) - 4);
2833 pSMB
->DataCount
= 0;
2834 pSMB
->DataOffset
= 0;
2835 pSMB
->SetupCount
= 1;
2836 pSMB
->Reserved3
= 0;
2837 pSMB
->SubCommand
= cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION
);
2838 byte_count
= params
+ 1 /* pad */ ;
2839 pSMB
->TotalParameterCount
= cpu_to_le16(params
);
2840 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
2841 pSMB
->InformationLevel
= cpu_to_le16(SMB_QUERY_POSIX_ACL
);
2842 pSMB
->Reserved4
= 0;
2843 pSMB
->hdr
.smb_buf_length
+= byte_count
;
2844 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
2846 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
2847 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
2848 cifs_stats_inc(&tcon
->num_acl_get
);
2850 cFYI(1, ("Send error in Query POSIX ACL = %d", rc
));
2852 /* decode response */
2854 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
2855 if (rc
|| (pSMBr
->ByteCount
< 2))
2856 /* BB also check enough total bytes returned */
2857 rc
= -EIO
; /* bad smb */
2859 __u16 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
2860 __u16 count
= le16_to_cpu(pSMBr
->t2
.DataCount
);
2861 rc
= cifs_copy_posix_acl(acl_inf
,
2862 (char *)&pSMBr
->hdr
.Protocol
+data_offset
,
2863 buflen
, acl_type
, count
);
2866 cifs_buf_release(pSMB
);
2873 CIFSSMBSetPosixACL(const int xid
, struct cifsTconInfo
*tcon
,
2874 const unsigned char *fileName
,
2875 const char *local_acl
, const int buflen
,
2877 const struct nls_table
*nls_codepage
, int remap
)
2879 struct smb_com_transaction2_spi_req
*pSMB
= NULL
;
2880 struct smb_com_transaction2_spi_rsp
*pSMBr
= NULL
;
2884 int bytes_returned
= 0;
2885 __u16 params
, byte_count
, data_count
, param_offset
, offset
;
2887 cFYI(1, ("In SetPosixACL (Unix) for path %s", fileName
));
2889 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
2893 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
2895 cifsConvertToUCS((__le16
*) pSMB
->FileName
, fileName
,
2896 PATH_MAX
, nls_codepage
, remap
);
2897 name_len
++; /* trailing null */
2899 } else { /* BB improve the check for buffer overruns BB */
2900 name_len
= strnlen(fileName
, PATH_MAX
);
2901 name_len
++; /* trailing null */
2902 strncpy(pSMB
->FileName
, fileName
, name_len
);
2904 params
= 6 + name_len
;
2905 pSMB
->MaxParameterCount
= cpu_to_le16(2);
2906 /* BB find max SMB size from sess */
2907 pSMB
->MaxDataCount
= cpu_to_le16(1000);
2908 pSMB
->MaxSetupCount
= 0;
2912 pSMB
->Reserved2
= 0;
2913 param_offset
= offsetof(struct smb_com_transaction2_spi_req
,
2914 InformationLevel
) - 4;
2915 offset
= param_offset
+ params
;
2916 parm_data
= ((char *) &pSMB
->hdr
.Protocol
) + offset
;
2917 pSMB
->ParameterOffset
= cpu_to_le16(param_offset
);
2919 /* convert to on the wire format for POSIX ACL */
2920 data_count
= ACL_to_cifs_posix(parm_data
, local_acl
, buflen
, acl_type
);
2922 if (data_count
== 0) {
2924 goto setACLerrorExit
;
2926 pSMB
->DataOffset
= cpu_to_le16(offset
);
2927 pSMB
->SetupCount
= 1;
2928 pSMB
->Reserved3
= 0;
2929 pSMB
->SubCommand
= cpu_to_le16(TRANS2_SET_PATH_INFORMATION
);
2930 pSMB
->InformationLevel
= cpu_to_le16(SMB_SET_POSIX_ACL
);
2931 byte_count
= 3 /* pad */ + params
+ data_count
;
2932 pSMB
->DataCount
= cpu_to_le16(data_count
);
2933 pSMB
->TotalDataCount
= pSMB
->DataCount
;
2934 pSMB
->ParameterCount
= cpu_to_le16(params
);
2935 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
2936 pSMB
->Reserved4
= 0;
2937 pSMB
->hdr
.smb_buf_length
+= byte_count
;
2938 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
2939 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
2940 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
2942 cFYI(1, ("Set POSIX ACL returned %d", rc
));
2945 cifs_buf_release(pSMB
);
2951 /* BB fix tabs in this function FIXME BB */
2953 CIFSGetExtAttr(const int xid
, struct cifsTconInfo
*tcon
,
2954 const int netfid
, __u64
*pExtAttrBits
, __u64
*pMask
)
2957 struct smb_t2_qfi_req
*pSMB
= NULL
;
2958 struct smb_t2_qfi_rsp
*pSMBr
= NULL
;
2960 __u16 params
, byte_count
;
2962 cFYI(1, ("In GetExtAttr"));
2967 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
2972 params
= 2 /* level */ + 2 /* fid */;
2973 pSMB
->t2
.TotalDataCount
= 0;
2974 pSMB
->t2
.MaxParameterCount
= cpu_to_le16(4);
2975 /* BB find exact max data count below from sess structure BB */
2976 pSMB
->t2
.MaxDataCount
= cpu_to_le16(4000);
2977 pSMB
->t2
.MaxSetupCount
= 0;
2978 pSMB
->t2
.Reserved
= 0;
2980 pSMB
->t2
.Timeout
= 0;
2981 pSMB
->t2
.Reserved2
= 0;
2982 pSMB
->t2
.ParameterOffset
= cpu_to_le16(offsetof(struct smb_t2_qfi_req
,
2984 pSMB
->t2
.DataCount
= 0;
2985 pSMB
->t2
.DataOffset
= 0;
2986 pSMB
->t2
.SetupCount
= 1;
2987 pSMB
->t2
.Reserved3
= 0;
2988 pSMB
->t2
.SubCommand
= cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION
);
2989 byte_count
= params
+ 1 /* pad */ ;
2990 pSMB
->t2
.TotalParameterCount
= cpu_to_le16(params
);
2991 pSMB
->t2
.ParameterCount
= pSMB
->t2
.TotalParameterCount
;
2992 pSMB
->InformationLevel
= cpu_to_le16(SMB_QUERY_ATTR_FLAGS
);
2995 pSMB
->hdr
.smb_buf_length
+= byte_count
;
2996 pSMB
->t2
.ByteCount
= cpu_to_le16(byte_count
);
2998 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
2999 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
3001 cFYI(1, ("error %d in GetExtAttr", rc
));
3003 /* decode response */
3004 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
3005 if (rc
|| (pSMBr
->ByteCount
< 2))
3006 /* BB also check enough total bytes returned */
3007 /* If rc should we check for EOPNOSUPP and
3008 disable the srvino flag? or in caller? */
3009 rc
= -EIO
; /* bad smb */
3011 __u16 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
3012 __u16 count
= le16_to_cpu(pSMBr
->t2
.DataCount
);
3013 struct file_chattr_info
*pfinfo
;
3014 /* BB Do we need a cast or hash here ? */
3016 cFYI(1, ("Illegal size ret in GetExtAttr"));
3020 pfinfo
= (struct file_chattr_info
*)
3021 (data_offset
+ (char *) &pSMBr
->hdr
.Protocol
);
3022 *pExtAttrBits
= le64_to_cpu(pfinfo
->mode
);
3023 *pMask
= le64_to_cpu(pfinfo
->mask
);
3027 cifs_buf_release(pSMB
);
3029 goto GetExtAttrRetry
;
3033 #endif /* CONFIG_POSIX */
3035 #ifdef CONFIG_CIFS_EXPERIMENTAL
3036 /* Get Security Descriptor (by handle) from remote server for a file or dir */
3038 CIFSSMBGetCIFSACL(const int xid
, struct cifsTconInfo
*tcon
, __u16 fid
,
3039 struct cifs_ntsd
**acl_inf
, __u32
*pbuflen
)
3043 QUERY_SEC_DESC_REQ
*pSMB
;
3046 cFYI(1, ("GetCifsACL"));
3051 rc
= smb_init_nttransact(NT_TRANSACT_QUERY_SECURITY_DESC
, 0,
3052 8 /* parm len */, tcon
, (void **) &pSMB
);
3056 pSMB
->MaxParameterCount
= cpu_to_le32(4);
3057 /* BB TEST with big acls that might need to be e.g. larger than 16K */
3058 pSMB
->MaxSetupCount
= 0;
3059 pSMB
->Fid
= fid
; /* file handle always le */
3060 pSMB
->AclFlags
= cpu_to_le32(CIFS_ACL_OWNER
| CIFS_ACL_GROUP
|
3062 pSMB
->ByteCount
= cpu_to_le16(11); /* 3 bytes pad + 8 bytes parm */
3063 pSMB
->hdr
.smb_buf_length
+= 11;
3064 iov
[0].iov_base
= (char *)pSMB
;
3065 iov
[0].iov_len
= pSMB
->hdr
.smb_buf_length
+ 4;
3067 rc
= SendReceive2(xid
, tcon
->ses
, iov
, 1 /* num iovec */, &buf_type
,
3069 cifs_stats_inc(&tcon
->num_acl_get
);
3071 cFYI(1, ("Send error in QuerySecDesc = %d", rc
));
3072 } else { /* decode response */
3076 struct smb_com_ntransact_rsp
*pSMBr
;
3079 /* validate_nttransact */
3080 rc
= validate_ntransact(iov
[0].iov_base
, (char **)&parm
,
3081 &pdata
, &parm_len
, pbuflen
);
3084 pSMBr
= (struct smb_com_ntransact_rsp
*)iov
[0].iov_base
;
3086 cFYI(1, ("smb %p parm %p data %p", pSMBr
, parm
, *acl_inf
));
3088 if (le32_to_cpu(pSMBr
->ParameterCount
) != 4) {
3089 rc
= -EIO
; /* bad smb */
3094 /* BB check that data area is minimum length and as big as acl_len */
3096 acl_len
= le32_to_cpu(*parm
);
3097 if (acl_len
!= *pbuflen
) {
3098 cERROR(1, ("acl length %d does not match %d",
3099 acl_len
, *pbuflen
));
3100 if (*pbuflen
> acl_len
)
3104 /* check if buffer is big enough for the acl
3105 header followed by the smallest SID */
3106 if ((*pbuflen
< sizeof(struct cifs_ntsd
) + 8) ||
3107 (*pbuflen
>= 64 * 1024)) {
3108 cERROR(1, ("bad acl length %d", *pbuflen
));
3112 *acl_inf
= kmalloc(*pbuflen
, GFP_KERNEL
);
3113 if (*acl_inf
== NULL
) {
3117 memcpy(*acl_inf
, pdata
, *pbuflen
);
3121 if (buf_type
== CIFS_SMALL_BUFFER
)
3122 cifs_small_buf_release(iov
[0].iov_base
);
3123 else if (buf_type
== CIFS_LARGE_BUFFER
)
3124 cifs_buf_release(iov
[0].iov_base
);
3125 /* cifs_small_buf_release(pSMB); */ /* Freed earlier now in SendReceive2 */
3130 CIFSSMBSetCIFSACL(const int xid
, struct cifsTconInfo
*tcon
, __u16 fid
,
3131 struct cifs_ntsd
*pntsd
, __u32 acllen
)
3133 __u16 byte_count
, param_count
, data_count
, param_offset
, data_offset
;
3135 int bytes_returned
= 0;
3136 SET_SEC_DESC_REQ
*pSMB
= NULL
;
3137 NTRANSACT_RSP
*pSMBr
= NULL
;
3140 rc
= smb_init(SMB_COM_NT_TRANSACT
, 19, tcon
, (void **) &pSMB
,
3145 pSMB
->MaxSetupCount
= 0;
3149 param_offset
= offsetof(struct smb_com_transaction_ssec_req
, Fid
) - 4;
3150 data_count
= acllen
;
3151 data_offset
= param_offset
+ param_count
;
3152 byte_count
= 3 /* pad */ + param_count
;
3154 pSMB
->DataCount
= cpu_to_le32(data_count
);
3155 pSMB
->TotalDataCount
= pSMB
->DataCount
;
3156 pSMB
->MaxParameterCount
= cpu_to_le32(4);
3157 pSMB
->MaxDataCount
= cpu_to_le32(16384);
3158 pSMB
->ParameterCount
= cpu_to_le32(param_count
);
3159 pSMB
->ParameterOffset
= cpu_to_le32(param_offset
);
3160 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
3161 pSMB
->DataOffset
= cpu_to_le32(data_offset
);
3162 pSMB
->SetupCount
= 0;
3163 pSMB
->SubCommand
= cpu_to_le16(NT_TRANSACT_SET_SECURITY_DESC
);
3164 pSMB
->ByteCount
= cpu_to_le16(byte_count
+data_count
);
3166 pSMB
->Fid
= fid
; /* file handle always le */
3167 pSMB
->Reserved2
= 0;
3168 pSMB
->AclFlags
= cpu_to_le32(CIFS_ACL_DACL
);
3170 if (pntsd
&& acllen
) {
3171 memcpy((char *) &pSMBr
->hdr
.Protocol
+ data_offset
,
3174 pSMB
->hdr
.smb_buf_length
+= (byte_count
+ data_count
);
3177 pSMB
->hdr
.smb_buf_length
+= byte_count
;
3179 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
3180 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
3182 cFYI(1, ("SetCIFSACL bytes_returned: %d, rc: %d", bytes_returned
, rc
));
3184 cFYI(1, ("Set CIFS ACL returned %d", rc
));
3185 cifs_buf_release(pSMB
);
3188 goto setCifsAclRetry
;
3193 #endif /* CONFIG_CIFS_EXPERIMENTAL */
3195 /* Legacy Query Path Information call for lookup to old servers such
3197 int SMBQueryInformation(const int xid
, struct cifsTconInfo
*tcon
,
3198 const unsigned char *searchName
,
3199 FILE_ALL_INFO
*pFinfo
,
3200 const struct nls_table
*nls_codepage
, int remap
)
3202 QUERY_INFORMATION_REQ
*pSMB
;
3203 QUERY_INFORMATION_RSP
*pSMBr
;
3208 cFYI(1, ("In SMBQPath path %s", searchName
));
3210 rc
= smb_init(SMB_COM_QUERY_INFORMATION
, 0, tcon
, (void **) &pSMB
,
3215 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
3217 cifsConvertToUCS((__le16
*) pSMB
->FileName
, searchName
,
3218 PATH_MAX
, nls_codepage
, remap
);
3219 name_len
++; /* trailing null */
3222 name_len
= strnlen(searchName
, PATH_MAX
);
3223 name_len
++; /* trailing null */
3224 strncpy(pSMB
->FileName
, searchName
, name_len
);
3226 pSMB
->BufferFormat
= 0x04;
3227 name_len
++; /* account for buffer type byte */
3228 pSMB
->hdr
.smb_buf_length
+= (__u16
) name_len
;
3229 pSMB
->ByteCount
= cpu_to_le16(name_len
);
3231 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
3232 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
3234 cFYI(1, ("Send error in QueryInfo = %d", rc
));
3235 } else if (pFinfo
) {
3237 __u32 time
= le32_to_cpu(pSMBr
->last_write_time
);
3239 /* decode response */
3240 /* BB FIXME - add time zone adjustment BB */
3241 memset(pFinfo
, 0, sizeof(FILE_ALL_INFO
));
3244 /* decode time fields */
3245 pFinfo
->ChangeTime
= cpu_to_le64(cifs_UnixTimeToNT(ts
));
3246 pFinfo
->LastWriteTime
= pFinfo
->ChangeTime
;
3247 pFinfo
->LastAccessTime
= 0;
3248 pFinfo
->AllocationSize
=
3249 cpu_to_le64(le32_to_cpu(pSMBr
->size
));
3250 pFinfo
->EndOfFile
= pFinfo
->AllocationSize
;
3251 pFinfo
->Attributes
=
3252 cpu_to_le32(le16_to_cpu(pSMBr
->attr
));
3254 rc
= -EIO
; /* bad buffer passed in */
3256 cifs_buf_release(pSMB
);
3265 CIFSSMBQFileInfo(const int xid
, struct cifsTconInfo
*tcon
,
3266 u16 netfid
, FILE_ALL_INFO
*pFindData
)
3268 struct smb_t2_qfi_req
*pSMB
= NULL
;
3269 struct smb_t2_qfi_rsp
*pSMBr
= NULL
;
3272 __u16 params
, byte_count
;
3275 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
3280 params
= 2 /* level */ + 2 /* fid */;
3281 pSMB
->t2
.TotalDataCount
= 0;
3282 pSMB
->t2
.MaxParameterCount
= cpu_to_le16(4);
3283 /* BB find exact max data count below from sess structure BB */
3284 pSMB
->t2
.MaxDataCount
= cpu_to_le16(CIFSMaxBufSize
);
3285 pSMB
->t2
.MaxSetupCount
= 0;
3286 pSMB
->t2
.Reserved
= 0;
3288 pSMB
->t2
.Timeout
= 0;
3289 pSMB
->t2
.Reserved2
= 0;
3290 pSMB
->t2
.ParameterOffset
= cpu_to_le16(offsetof(struct smb_t2_qfi_req
,
3292 pSMB
->t2
.DataCount
= 0;
3293 pSMB
->t2
.DataOffset
= 0;
3294 pSMB
->t2
.SetupCount
= 1;
3295 pSMB
->t2
.Reserved3
= 0;
3296 pSMB
->t2
.SubCommand
= cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION
);
3297 byte_count
= params
+ 1 /* pad */ ;
3298 pSMB
->t2
.TotalParameterCount
= cpu_to_le16(params
);
3299 pSMB
->t2
.ParameterCount
= pSMB
->t2
.TotalParameterCount
;
3300 pSMB
->InformationLevel
= cpu_to_le16(SMB_QUERY_FILE_ALL_INFO
);
3303 pSMB
->hdr
.smb_buf_length
+= byte_count
;
3305 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
3306 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
3308 cFYI(1, ("Send error in QPathInfo = %d", rc
));
3309 } else { /* decode response */
3310 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
3312 if (rc
) /* BB add auto retry on EOPNOTSUPP? */
3314 else if (pSMBr
->ByteCount
< 40)
3315 rc
= -EIO
; /* bad smb */
3316 else if (pFindData
) {
3317 __u16 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
3318 memcpy((char *) pFindData
,
3319 (char *) &pSMBr
->hdr
.Protocol
+
3320 data_offset
, sizeof(FILE_ALL_INFO
));
3324 cifs_buf_release(pSMB
);
3326 goto QFileInfoRetry
;
3332 CIFSSMBQPathInfo(const int xid
, struct cifsTconInfo
*tcon
,
3333 const unsigned char *searchName
,
3334 FILE_ALL_INFO
*pFindData
,
3335 int legacy
/* old style infolevel */,
3336 const struct nls_table
*nls_codepage
, int remap
)
3338 /* level 263 SMB_QUERY_FILE_ALL_INFO */
3339 TRANSACTION2_QPI_REQ
*pSMB
= NULL
;
3340 TRANSACTION2_QPI_RSP
*pSMBr
= NULL
;
3344 __u16 params
, byte_count
;
3346 /* cFYI(1, ("In QPathInfo path %s", searchName)); */
3348 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
3353 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
3355 cifsConvertToUCS((__le16
*) pSMB
->FileName
, searchName
,
3356 PATH_MAX
, nls_codepage
, remap
);
3357 name_len
++; /* trailing null */
3359 } else { /* BB improve the check for buffer overruns BB */
3360 name_len
= strnlen(searchName
, PATH_MAX
);
3361 name_len
++; /* trailing null */
3362 strncpy(pSMB
->FileName
, searchName
, name_len
);
3365 params
= 2 /* level */ + 4 /* reserved */ + name_len
/* includes NUL */;
3366 pSMB
->TotalDataCount
= 0;
3367 pSMB
->MaxParameterCount
= cpu_to_le16(2);
3368 /* BB find exact max SMB PDU from sess structure BB */
3369 pSMB
->MaxDataCount
= cpu_to_le16(4000);
3370 pSMB
->MaxSetupCount
= 0;
3374 pSMB
->Reserved2
= 0;
3375 pSMB
->ParameterOffset
= cpu_to_le16(offsetof(
3376 struct smb_com_transaction2_qpi_req
, InformationLevel
) - 4);
3377 pSMB
->DataCount
= 0;
3378 pSMB
->DataOffset
= 0;
3379 pSMB
->SetupCount
= 1;
3380 pSMB
->Reserved3
= 0;
3381 pSMB
->SubCommand
= cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION
);
3382 byte_count
= params
+ 1 /* pad */ ;
3383 pSMB
->TotalParameterCount
= cpu_to_le16(params
);
3384 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
3386 pSMB
->InformationLevel
= cpu_to_le16(SMB_INFO_STANDARD
);
3388 pSMB
->InformationLevel
= cpu_to_le16(SMB_QUERY_FILE_ALL_INFO
);
3389 pSMB
->Reserved4
= 0;
3390 pSMB
->hdr
.smb_buf_length
+= byte_count
;
3391 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
3393 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
3394 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
3396 cFYI(1, ("Send error in QPathInfo = %d", rc
));
3397 } else { /* decode response */
3398 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
3400 if (rc
) /* BB add auto retry on EOPNOTSUPP? */
3402 else if (!legacy
&& (pSMBr
->ByteCount
< 40))
3403 rc
= -EIO
; /* bad smb */
3404 else if (legacy
&& (pSMBr
->ByteCount
< 24))
3405 rc
= -EIO
; /* 24 or 26 expected but we do not read
3407 else if (pFindData
) {
3409 __u16 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
3411 /* On legacy responses we do not read the last field,
3412 EAsize, fortunately since it varies by subdialect and
3413 also note it differs on Set vs. Get, ie two bytes or 4
3414 bytes depending but we don't care here */
3416 size
= sizeof(FILE_INFO_STANDARD
);
3418 size
= sizeof(FILE_ALL_INFO
);
3419 memcpy((char *) pFindData
,
3420 (char *) &pSMBr
->hdr
.Protocol
+
3425 cifs_buf_release(pSMB
);
3427 goto QPathInfoRetry
;
3433 CIFSSMBUnixQFileInfo(const int xid
, struct cifsTconInfo
*tcon
,
3434 u16 netfid
, FILE_UNIX_BASIC_INFO
*pFindData
)
3436 struct smb_t2_qfi_req
*pSMB
= NULL
;
3437 struct smb_t2_qfi_rsp
*pSMBr
= NULL
;
3440 __u16 params
, byte_count
;
3443 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
3448 params
= 2 /* level */ + 2 /* fid */;
3449 pSMB
->t2
.TotalDataCount
= 0;
3450 pSMB
->t2
.MaxParameterCount
= cpu_to_le16(4);
3451 /* BB find exact max data count below from sess structure BB */
3452 pSMB
->t2
.MaxDataCount
= cpu_to_le16(CIFSMaxBufSize
);
3453 pSMB
->t2
.MaxSetupCount
= 0;
3454 pSMB
->t2
.Reserved
= 0;
3456 pSMB
->t2
.Timeout
= 0;
3457 pSMB
->t2
.Reserved2
= 0;
3458 pSMB
->t2
.ParameterOffset
= cpu_to_le16(offsetof(struct smb_t2_qfi_req
,
3460 pSMB
->t2
.DataCount
= 0;
3461 pSMB
->t2
.DataOffset
= 0;
3462 pSMB
->t2
.SetupCount
= 1;
3463 pSMB
->t2
.Reserved3
= 0;
3464 pSMB
->t2
.SubCommand
= cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION
);
3465 byte_count
= params
+ 1 /* pad */ ;
3466 pSMB
->t2
.TotalParameterCount
= cpu_to_le16(params
);
3467 pSMB
->t2
.ParameterCount
= pSMB
->t2
.TotalParameterCount
;
3468 pSMB
->InformationLevel
= cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC
);
3471 pSMB
->hdr
.smb_buf_length
+= byte_count
;
3473 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
3474 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
3476 cFYI(1, ("Send error in QPathInfo = %d", rc
));
3477 } else { /* decode response */
3478 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
3480 if (rc
|| (pSMBr
->ByteCount
< sizeof(FILE_UNIX_BASIC_INFO
))) {
3481 cERROR(1, ("Malformed FILE_UNIX_BASIC_INFO response.\n"
3482 "Unix Extensions can be disabled on mount "
3483 "by specifying the nosfu mount option."));
3484 rc
= -EIO
; /* bad smb */
3486 __u16 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
3487 memcpy((char *) pFindData
,
3488 (char *) &pSMBr
->hdr
.Protocol
+
3490 sizeof(FILE_UNIX_BASIC_INFO
));
3494 cifs_buf_release(pSMB
);
3496 goto UnixQFileInfoRetry
;
3502 CIFSSMBUnixQPathInfo(const int xid
, struct cifsTconInfo
*tcon
,
3503 const unsigned char *searchName
,
3504 FILE_UNIX_BASIC_INFO
*pFindData
,
3505 const struct nls_table
*nls_codepage
, int remap
)
3507 /* SMB_QUERY_FILE_UNIX_BASIC */
3508 TRANSACTION2_QPI_REQ
*pSMB
= NULL
;
3509 TRANSACTION2_QPI_RSP
*pSMBr
= NULL
;
3511 int bytes_returned
= 0;
3513 __u16 params
, byte_count
;
3515 cFYI(1, ("In QPathInfo (Unix) the path %s", searchName
));
3517 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
3522 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
3524 cifsConvertToUCS((__le16
*) pSMB
->FileName
, searchName
,
3525 PATH_MAX
, nls_codepage
, remap
);
3526 name_len
++; /* trailing null */
3528 } else { /* BB improve the check for buffer overruns BB */
3529 name_len
= strnlen(searchName
, PATH_MAX
);
3530 name_len
++; /* trailing null */
3531 strncpy(pSMB
->FileName
, searchName
, name_len
);
3534 params
= 2 /* level */ + 4 /* reserved */ + name_len
/* includes NUL */;
3535 pSMB
->TotalDataCount
= 0;
3536 pSMB
->MaxParameterCount
= cpu_to_le16(2);
3537 /* BB find exact max SMB PDU from sess structure BB */
3538 pSMB
->MaxDataCount
= cpu_to_le16(4000);
3539 pSMB
->MaxSetupCount
= 0;
3543 pSMB
->Reserved2
= 0;
3544 pSMB
->ParameterOffset
= cpu_to_le16(offsetof(
3545 struct smb_com_transaction2_qpi_req
, InformationLevel
) - 4);
3546 pSMB
->DataCount
= 0;
3547 pSMB
->DataOffset
= 0;
3548 pSMB
->SetupCount
= 1;
3549 pSMB
->Reserved3
= 0;
3550 pSMB
->SubCommand
= cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION
);
3551 byte_count
= params
+ 1 /* pad */ ;
3552 pSMB
->TotalParameterCount
= cpu_to_le16(params
);
3553 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
3554 pSMB
->InformationLevel
= cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC
);
3555 pSMB
->Reserved4
= 0;
3556 pSMB
->hdr
.smb_buf_length
+= byte_count
;
3557 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
3559 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
3560 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
3562 cFYI(1, ("Send error in QPathInfo = %d", rc
));
3563 } else { /* decode response */
3564 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
3566 if (rc
|| (pSMBr
->ByteCount
< sizeof(FILE_UNIX_BASIC_INFO
))) {
3567 cERROR(1, ("Malformed FILE_UNIX_BASIC_INFO response.\n"
3568 "Unix Extensions can be disabled on mount "
3569 "by specifying the nosfu mount option."));
3570 rc
= -EIO
; /* bad smb */
3572 __u16 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
3573 memcpy((char *) pFindData
,
3574 (char *) &pSMBr
->hdr
.Protocol
+
3576 sizeof(FILE_UNIX_BASIC_INFO
));
3579 cifs_buf_release(pSMB
);
3581 goto UnixQPathInfoRetry
;
3586 /* xid, tcon, searchName and codepage are input parms, rest are returned */
3588 CIFSFindFirst(const int xid
, struct cifsTconInfo
*tcon
,
3589 const char *searchName
,
3590 const struct nls_table
*nls_codepage
,
3592 struct cifs_search_info
*psrch_inf
, int remap
, const char dirsep
)
3594 /* level 257 SMB_ */
3595 TRANSACTION2_FFIRST_REQ
*pSMB
= NULL
;
3596 TRANSACTION2_FFIRST_RSP
*pSMBr
= NULL
;
3597 T2_FFIRST_RSP_PARMS
*parms
;
3599 int bytes_returned
= 0;
3601 __u16 params
, byte_count
;
3603 cFYI(1, ("In FindFirst for %s", searchName
));
3606 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
3611 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
3613 cifsConvertToUCS((__le16
*) pSMB
->FileName
, searchName
,
3614 PATH_MAX
, nls_codepage
, remap
);
3615 /* We can not add the asterik earlier in case
3616 it got remapped to 0xF03A as if it were part of the
3617 directory name instead of a wildcard */
3619 pSMB
->FileName
[name_len
] = dirsep
;
3620 pSMB
->FileName
[name_len
+1] = 0;
3621 pSMB
->FileName
[name_len
+2] = '*';
3622 pSMB
->FileName
[name_len
+3] = 0;
3623 name_len
+= 4; /* now the trailing null */
3624 pSMB
->FileName
[name_len
] = 0; /* null terminate just in case */
3625 pSMB
->FileName
[name_len
+1] = 0;
3627 } else { /* BB add check for overrun of SMB buf BB */
3628 name_len
= strnlen(searchName
, PATH_MAX
);
3629 /* BB fix here and in unicode clause above ie
3630 if (name_len > buffersize-header)
3631 free buffer exit; BB */
3632 strncpy(pSMB
->FileName
, searchName
, name_len
);
3633 pSMB
->FileName
[name_len
] = dirsep
;
3634 pSMB
->FileName
[name_len
+1] = '*';
3635 pSMB
->FileName
[name_len
+2] = 0;
3639 params
= 12 + name_len
/* includes null */ ;
3640 pSMB
->TotalDataCount
= 0; /* no EAs */
3641 pSMB
->MaxParameterCount
= cpu_to_le16(10);
3642 pSMB
->MaxDataCount
= cpu_to_le16((tcon
->ses
->server
->maxBuf
-
3643 MAX_CIFS_HDR_SIZE
) & 0xFFFFFF00);
3644 pSMB
->MaxSetupCount
= 0;
3648 pSMB
->Reserved2
= 0;
3649 byte_count
= params
+ 1 /* pad */ ;
3650 pSMB
->TotalParameterCount
= cpu_to_le16(params
);
3651 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
3652 pSMB
->ParameterOffset
= cpu_to_le16(
3653 offsetof(struct smb_com_transaction2_ffirst_req
, SearchAttributes
)
3655 pSMB
->DataCount
= 0;
3656 pSMB
->DataOffset
= 0;
3657 pSMB
->SetupCount
= 1; /* one byte, no need to make endian neutral */
3658 pSMB
->Reserved3
= 0;
3659 pSMB
->SubCommand
= cpu_to_le16(TRANS2_FIND_FIRST
);
3660 pSMB
->SearchAttributes
=
3661 cpu_to_le16(ATTR_READONLY
| ATTR_HIDDEN
| ATTR_SYSTEM
|
3663 pSMB
->SearchCount
= cpu_to_le16(CIFSMaxBufSize
/sizeof(FILE_UNIX_INFO
));
3664 pSMB
->SearchFlags
= cpu_to_le16(CIFS_SEARCH_CLOSE_AT_END
|
3665 CIFS_SEARCH_RETURN_RESUME
);
3666 pSMB
->InformationLevel
= cpu_to_le16(psrch_inf
->info_level
);
3668 /* BB what should we set StorageType to? Does it matter? BB */
3669 pSMB
->SearchStorageType
= 0;
3670 pSMB
->hdr
.smb_buf_length
+= byte_count
;
3671 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
3673 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
3674 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
3675 cifs_stats_inc(&tcon
->num_ffirst
);
3677 if (rc
) {/* BB add logic to retry regular search if Unix search
3678 rejected unexpectedly by server */
3679 /* BB Add code to handle unsupported level rc */
3680 cFYI(1, ("Error in FindFirst = %d", rc
));
3682 cifs_buf_release(pSMB
);
3684 /* BB eventually could optimize out free and realloc of buf */
3687 goto findFirstRetry
;
3688 } else { /* decode response */
3689 /* BB remember to free buffer if error BB */
3690 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
3694 if (pSMBr
->hdr
.Flags2
& SMBFLG2_UNICODE
)
3695 psrch_inf
->unicode
= true;
3697 psrch_inf
->unicode
= false;
3699 psrch_inf
->ntwrk_buf_start
= (char *)pSMBr
;
3700 psrch_inf
->smallBuf
= 0;
3701 psrch_inf
->srch_entries_start
=
3702 (char *) &pSMBr
->hdr
.Protocol
+
3703 le16_to_cpu(pSMBr
->t2
.DataOffset
);
3704 parms
= (T2_FFIRST_RSP_PARMS
*)((char *) &pSMBr
->hdr
.Protocol
+
3705 le16_to_cpu(pSMBr
->t2
.ParameterOffset
));
3707 if (parms
->EndofSearch
)
3708 psrch_inf
->endOfSearch
= true;
3710 psrch_inf
->endOfSearch
= false;
3712 psrch_inf
->entries_in_buffer
=
3713 le16_to_cpu(parms
->SearchCount
);
3714 psrch_inf
->index_of_last_entry
= 2 /* skip . and .. */ +
3715 psrch_inf
->entries_in_buffer
;
3716 lnoff
= le16_to_cpu(parms
->LastNameOffset
);
3717 if (tcon
->ses
->server
->maxBuf
- MAX_CIFS_HDR_SIZE
<
3719 cERROR(1, ("ignoring corrupt resume name"));
3720 psrch_inf
->last_entry
= NULL
;
3724 psrch_inf
->last_entry
= psrch_inf
->srch_entries_start
+
3727 *pnetfid
= parms
->SearchHandle
;
3729 cifs_buf_release(pSMB
);
3736 int CIFSFindNext(const int xid
, struct cifsTconInfo
*tcon
,
3737 __u16 searchHandle
, struct cifs_search_info
*psrch_inf
)
3739 TRANSACTION2_FNEXT_REQ
*pSMB
= NULL
;
3740 TRANSACTION2_FNEXT_RSP
*pSMBr
= NULL
;
3741 T2_FNEXT_RSP_PARMS
*parms
;
3742 char *response_data
;
3744 int bytes_returned
, name_len
;
3745 __u16 params
, byte_count
;
3747 cFYI(1, ("In FindNext"));
3749 if (psrch_inf
->endOfSearch
)
3752 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
3757 params
= 14; /* includes 2 bytes of null string, converted to LE below*/
3759 pSMB
->TotalDataCount
= 0; /* no EAs */
3760 pSMB
->MaxParameterCount
= cpu_to_le16(8);
3761 pSMB
->MaxDataCount
=
3762 cpu_to_le16((tcon
->ses
->server
->maxBuf
- MAX_CIFS_HDR_SIZE
) &
3764 pSMB
->MaxSetupCount
= 0;
3768 pSMB
->Reserved2
= 0;
3769 pSMB
->ParameterOffset
= cpu_to_le16(
3770 offsetof(struct smb_com_transaction2_fnext_req
,SearchHandle
) - 4);
3771 pSMB
->DataCount
= 0;
3772 pSMB
->DataOffset
= 0;
3773 pSMB
->SetupCount
= 1;
3774 pSMB
->Reserved3
= 0;
3775 pSMB
->SubCommand
= cpu_to_le16(TRANS2_FIND_NEXT
);
3776 pSMB
->SearchHandle
= searchHandle
; /* always kept as le */
3778 cpu_to_le16(CIFSMaxBufSize
/ sizeof(FILE_UNIX_INFO
));
3779 pSMB
->InformationLevel
= cpu_to_le16(psrch_inf
->info_level
);
3780 pSMB
->ResumeKey
= psrch_inf
->resume_key
;
3782 cpu_to_le16(CIFS_SEARCH_CLOSE_AT_END
| CIFS_SEARCH_RETURN_RESUME
);
3784 name_len
= psrch_inf
->resume_name_len
;
3786 if (name_len
< PATH_MAX
) {
3787 memcpy(pSMB
->ResumeFileName
, psrch_inf
->presume_name
, name_len
);
3788 byte_count
+= name_len
;
3789 /* 14 byte parm len above enough for 2 byte null terminator */
3790 pSMB
->ResumeFileName
[name_len
] = 0;
3791 pSMB
->ResumeFileName
[name_len
+1] = 0;
3794 goto FNext2_err_exit
;
3796 byte_count
= params
+ 1 /* pad */ ;
3797 pSMB
->TotalParameterCount
= cpu_to_le16(params
);
3798 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
3799 pSMB
->hdr
.smb_buf_length
+= byte_count
;
3800 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
3802 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
3803 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
3804 cifs_stats_inc(&tcon
->num_fnext
);
3807 psrch_inf
->endOfSearch
= true;
3808 cifs_buf_release(pSMB
);
3809 rc
= 0; /* search probably was closed at end of search*/
3811 cFYI(1, ("FindNext returned = %d", rc
));
3812 } else { /* decode response */
3813 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
3818 /* BB fixme add lock for file (srch_info) struct here */
3819 if (pSMBr
->hdr
.Flags2
& SMBFLG2_UNICODE
)
3820 psrch_inf
->unicode
= true;
3822 psrch_inf
->unicode
= false;
3823 response_data
= (char *) &pSMBr
->hdr
.Protocol
+
3824 le16_to_cpu(pSMBr
->t2
.ParameterOffset
);
3825 parms
= (T2_FNEXT_RSP_PARMS
*)response_data
;
3826 response_data
= (char *)&pSMBr
->hdr
.Protocol
+
3827 le16_to_cpu(pSMBr
->t2
.DataOffset
);
3828 if (psrch_inf
->smallBuf
)
3829 cifs_small_buf_release(
3830 psrch_inf
->ntwrk_buf_start
);
3832 cifs_buf_release(psrch_inf
->ntwrk_buf_start
);
3833 psrch_inf
->srch_entries_start
= response_data
;
3834 psrch_inf
->ntwrk_buf_start
= (char *)pSMB
;
3835 psrch_inf
->smallBuf
= 0;
3836 if (parms
->EndofSearch
)
3837 psrch_inf
->endOfSearch
= true;
3839 psrch_inf
->endOfSearch
= false;
3840 psrch_inf
->entries_in_buffer
=
3841 le16_to_cpu(parms
->SearchCount
);
3842 psrch_inf
->index_of_last_entry
+=
3843 psrch_inf
->entries_in_buffer
;
3844 lnoff
= le16_to_cpu(parms
->LastNameOffset
);
3845 if (tcon
->ses
->server
->maxBuf
- MAX_CIFS_HDR_SIZE
<
3847 cERROR(1, ("ignoring corrupt resume name"));
3848 psrch_inf
->last_entry
= NULL
;
3851 psrch_inf
->last_entry
=
3852 psrch_inf
->srch_entries_start
+ lnoff
;
3854 /* cFYI(1,("fnxt2 entries in buf %d index_of_last %d",
3855 psrch_inf->entries_in_buffer, psrch_inf->index_of_last_entry)); */
3857 /* BB fixme add unlock here */
3862 /* BB On error, should we leave previous search buf (and count and
3863 last entry fields) intact or free the previous one? */
3865 /* Note: On -EAGAIN error only caller can retry on handle based calls
3866 since file handle passed in no longer valid */
3869 cifs_buf_release(pSMB
);
3874 CIFSFindClose(const int xid
, struct cifsTconInfo
*tcon
,
3875 const __u16 searchHandle
)
3878 FINDCLOSE_REQ
*pSMB
= NULL
;
3880 cFYI(1, ("In CIFSSMBFindClose"));
3881 rc
= small_smb_init(SMB_COM_FIND_CLOSE2
, 1, tcon
, (void **)&pSMB
);
3883 /* no sense returning error if session restarted
3884 as file handle has been closed */
3890 pSMB
->FileID
= searchHandle
;
3891 pSMB
->ByteCount
= 0;
3892 rc
= SendReceiveNoRsp(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
, 0);
3894 cERROR(1, ("Send error in FindClose = %d", rc
));
3896 cifs_stats_inc(&tcon
->num_fclose
);
3898 /* Since session is dead, search handle closed on server already */
3906 CIFSGetSrvInodeNumber(const int xid
, struct cifsTconInfo
*tcon
,
3907 const unsigned char *searchName
,
3908 __u64
*inode_number
,
3909 const struct nls_table
*nls_codepage
, int remap
)
3912 TRANSACTION2_QPI_REQ
*pSMB
= NULL
;
3913 TRANSACTION2_QPI_RSP
*pSMBr
= NULL
;
3914 int name_len
, bytes_returned
;
3915 __u16 params
, byte_count
;
3917 cFYI(1, ("In GetSrvInodeNum for %s", searchName
));
3921 GetInodeNumberRetry
:
3922 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
3927 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
3929 cifsConvertToUCS((__le16
*) pSMB
->FileName
, searchName
,
3930 PATH_MAX
, nls_codepage
, remap
);
3931 name_len
++; /* trailing null */
3933 } else { /* BB improve the check for buffer overruns BB */
3934 name_len
= strnlen(searchName
, PATH_MAX
);
3935 name_len
++; /* trailing null */
3936 strncpy(pSMB
->FileName
, searchName
, name_len
);
3939 params
= 2 /* level */ + 4 /* rsrvd */ + name_len
/* incl null */ ;
3940 pSMB
->TotalDataCount
= 0;
3941 pSMB
->MaxParameterCount
= cpu_to_le16(2);
3942 /* BB find exact max data count below from sess structure BB */
3943 pSMB
->MaxDataCount
= cpu_to_le16(4000);
3944 pSMB
->MaxSetupCount
= 0;
3948 pSMB
->Reserved2
= 0;
3949 pSMB
->ParameterOffset
= cpu_to_le16(offsetof(
3950 struct smb_com_transaction2_qpi_req
, InformationLevel
) - 4);
3951 pSMB
->DataCount
= 0;
3952 pSMB
->DataOffset
= 0;
3953 pSMB
->SetupCount
= 1;
3954 pSMB
->Reserved3
= 0;
3955 pSMB
->SubCommand
= cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION
);
3956 byte_count
= params
+ 1 /* pad */ ;
3957 pSMB
->TotalParameterCount
= cpu_to_le16(params
);
3958 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
3959 pSMB
->InformationLevel
= cpu_to_le16(SMB_QUERY_FILE_INTERNAL_INFO
);
3960 pSMB
->Reserved4
= 0;
3961 pSMB
->hdr
.smb_buf_length
+= byte_count
;
3962 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
3964 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
3965 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
3967 cFYI(1, ("error %d in QueryInternalInfo", rc
));
3969 /* decode response */
3970 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
3971 if (rc
|| (pSMBr
->ByteCount
< 2))
3972 /* BB also check enough total bytes returned */
3973 /* If rc should we check for EOPNOSUPP and
3974 disable the srvino flag? or in caller? */
3975 rc
= -EIO
; /* bad smb */
3977 __u16 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
3978 __u16 count
= le16_to_cpu(pSMBr
->t2
.DataCount
);
3979 struct file_internal_info
*pfinfo
;
3980 /* BB Do we need a cast or hash here ? */
3982 cFYI(1, ("Illegal size ret in QryIntrnlInf"));
3984 goto GetInodeNumOut
;
3986 pfinfo
= (struct file_internal_info
*)
3987 (data_offset
+ (char *) &pSMBr
->hdr
.Protocol
);
3988 *inode_number
= le64_to_cpu(pfinfo
->UniqueId
);
3992 cifs_buf_release(pSMB
);
3994 goto GetInodeNumberRetry
;
3998 /* parses DFS refferal V3 structure
3999 * caller is responsible for freeing target_nodes
4002 * on failure - errno
4005 parse_DFS_referrals(TRANSACTION2_GET_DFS_REFER_RSP
*pSMBr
,
4006 unsigned int *num_of_nodes
,
4007 struct dfs_info3_param
**target_nodes
,
4008 const struct nls_table
*nls_codepage
, int remap
,
4009 const char *searchName
)
4014 struct dfs_referral_level_3
*ref
;
4016 if (pSMBr
->hdr
.Flags2
& SMBFLG2_UNICODE
)
4020 *num_of_nodes
= le16_to_cpu(pSMBr
->NumberOfReferrals
);
4022 if (*num_of_nodes
< 1) {
4023 cERROR(1, ("num_referrals: must be at least > 0,"
4024 "but we get num_referrals = %d\n", *num_of_nodes
));
4026 goto parse_DFS_referrals_exit
;
4029 ref
= (struct dfs_referral_level_3
*) &(pSMBr
->referrals
);
4030 if (ref
->VersionNumber
!= cpu_to_le16(3)) {
4031 cERROR(1, ("Referrals of V%d version are not supported,"
4032 "should be V3", le16_to_cpu(ref
->VersionNumber
)));
4034 goto parse_DFS_referrals_exit
;
4037 /* get the upper boundary of the resp buffer */
4038 data_end
= (char *)(&(pSMBr
->PathConsumed
)) +
4039 le16_to_cpu(pSMBr
->t2
.DataCount
);
4041 cFYI(1, ("num_referrals: %d dfs flags: 0x%x ... \n",
4043 le32_to_cpu(pSMBr
->DFSFlags
)));
4045 *target_nodes
= kzalloc(sizeof(struct dfs_info3_param
) *
4046 *num_of_nodes
, GFP_KERNEL
);
4047 if (*target_nodes
== NULL
) {
4048 cERROR(1, ("Failed to allocate buffer for target_nodes\n"));
4050 goto parse_DFS_referrals_exit
;
4053 /* collect necessary data from referrals */
4054 for (i
= 0; i
< *num_of_nodes
; i
++) {
4057 struct dfs_info3_param
*node
= (*target_nodes
)+i
;
4059 node
->flags
= le32_to_cpu(pSMBr
->DFSFlags
);
4061 __le16
*tmp
= kmalloc(strlen(searchName
)*2 + 2,
4065 goto parse_DFS_referrals_exit
;
4067 cifsConvertToUCS((__le16
*) tmp
, searchName
,
4068 PATH_MAX
, nls_codepage
, remap
);
4069 node
->path_consumed
= cifs_ucs2_bytes(tmp
,
4070 le16_to_cpu(pSMBr
->PathConsumed
),
4074 node
->path_consumed
= le16_to_cpu(pSMBr
->PathConsumed
);
4076 node
->server_type
= le16_to_cpu(ref
->ServerType
);
4077 node
->ref_flag
= le16_to_cpu(ref
->ReferralEntryFlags
);
4080 temp
= (char *)ref
+ le16_to_cpu(ref
->DfsPathOffset
);
4081 max_len
= data_end
- temp
;
4082 node
->path_name
= cifs_strndup_from_ucs(temp
, max_len
,
4083 is_unicode
, nls_codepage
);
4084 if (!node
->path_name
) {
4086 goto parse_DFS_referrals_exit
;
4089 /* copy link target UNC */
4090 temp
= (char *)ref
+ le16_to_cpu(ref
->NetworkAddressOffset
);
4091 max_len
= data_end
- temp
;
4092 node
->node_name
= cifs_strndup_from_ucs(temp
, max_len
,
4093 is_unicode
, nls_codepage
);
4094 if (!node
->node_name
)
4098 parse_DFS_referrals_exit
:
4100 free_dfs_info_array(*target_nodes
, *num_of_nodes
);
4101 *target_nodes
= NULL
;
4108 CIFSGetDFSRefer(const int xid
, struct cifsSesInfo
*ses
,
4109 const unsigned char *searchName
,
4110 struct dfs_info3_param
**target_nodes
,
4111 unsigned int *num_of_nodes
,
4112 const struct nls_table
*nls_codepage
, int remap
)
4114 /* TRANS2_GET_DFS_REFERRAL */
4115 TRANSACTION2_GET_DFS_REFER_REQ
*pSMB
= NULL
;
4116 TRANSACTION2_GET_DFS_REFER_RSP
*pSMBr
= NULL
;
4120 __u16 params
, byte_count
;
4122 *target_nodes
= NULL
;
4124 cFYI(1, ("In GetDFSRefer the path %s", searchName
));
4128 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, NULL
, (void **) &pSMB
,
4133 /* server pointer checked in called function,
4134 but should never be null here anyway */
4135 pSMB
->hdr
.Mid
= GetNextMid(ses
->server
);
4136 pSMB
->hdr
.Tid
= ses
->ipc_tid
;
4137 pSMB
->hdr
.Uid
= ses
->Suid
;
4138 if (ses
->capabilities
& CAP_STATUS32
)
4139 pSMB
->hdr
.Flags2
|= SMBFLG2_ERR_STATUS
;
4140 if (ses
->capabilities
& CAP_DFS
)
4141 pSMB
->hdr
.Flags2
|= SMBFLG2_DFS
;
4143 if (ses
->capabilities
& CAP_UNICODE
) {
4144 pSMB
->hdr
.Flags2
|= SMBFLG2_UNICODE
;
4146 cifsConvertToUCS((__le16
*) pSMB
->RequestFileName
,
4147 searchName
, PATH_MAX
, nls_codepage
, remap
);
4148 name_len
++; /* trailing null */
4150 } else { /* BB improve the check for buffer overruns BB */
4151 name_len
= strnlen(searchName
, PATH_MAX
);
4152 name_len
++; /* trailing null */
4153 strncpy(pSMB
->RequestFileName
, searchName
, name_len
);
4157 if (ses
->server
->secMode
&
4158 (SECMODE_SIGN_REQUIRED
| SECMODE_SIGN_ENABLED
))
4159 pSMB
->hdr
.Flags2
|= SMBFLG2_SECURITY_SIGNATURE
;
4162 pSMB
->hdr
.Uid
= ses
->Suid
;
4164 params
= 2 /* level */ + name_len
/*includes null */ ;
4165 pSMB
->TotalDataCount
= 0;
4166 pSMB
->DataCount
= 0;
4167 pSMB
->DataOffset
= 0;
4168 pSMB
->MaxParameterCount
= 0;
4169 /* BB find exact max SMB PDU from sess structure BB */
4170 pSMB
->MaxDataCount
= cpu_to_le16(4000);
4171 pSMB
->MaxSetupCount
= 0;
4175 pSMB
->Reserved2
= 0;
4176 pSMB
->ParameterOffset
= cpu_to_le16(offsetof(
4177 struct smb_com_transaction2_get_dfs_refer_req
, MaxReferralLevel
) - 4);
4178 pSMB
->SetupCount
= 1;
4179 pSMB
->Reserved3
= 0;
4180 pSMB
->SubCommand
= cpu_to_le16(TRANS2_GET_DFS_REFERRAL
);
4181 byte_count
= params
+ 3 /* pad */ ;
4182 pSMB
->ParameterCount
= cpu_to_le16(params
);
4183 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
4184 pSMB
->MaxReferralLevel
= cpu_to_le16(3);
4185 pSMB
->hdr
.smb_buf_length
+= byte_count
;
4186 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
4188 rc
= SendReceive(xid
, ses
, (struct smb_hdr
*) pSMB
,
4189 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
4191 cFYI(1, ("Send error in GetDFSRefer = %d", rc
));
4194 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
4196 /* BB Also check if enough total bytes returned? */
4197 if (rc
|| (pSMBr
->ByteCount
< 17)) {
4198 rc
= -EIO
; /* bad smb */
4202 cFYI(1, ("Decoding GetDFSRefer response BCC: %d Offset %d",
4204 le16_to_cpu(pSMBr
->t2
.DataOffset
)));
4206 /* parse returned result into more usable form */
4207 rc
= parse_DFS_referrals(pSMBr
, num_of_nodes
,
4208 target_nodes
, nls_codepage
, remap
,
4212 cifs_buf_release(pSMB
);
4220 /* Query File System Info such as free space to old servers such as Win 9x */
4222 SMBOldQFSInfo(const int xid
, struct cifsTconInfo
*tcon
, struct kstatfs
*FSData
)
4224 /* level 0x01 SMB_QUERY_FILE_SYSTEM_INFO */
4225 TRANSACTION2_QFSI_REQ
*pSMB
= NULL
;
4226 TRANSACTION2_QFSI_RSP
*pSMBr
= NULL
;
4227 FILE_SYSTEM_ALLOC_INFO
*response_data
;
4229 int bytes_returned
= 0;
4230 __u16 params
, byte_count
;
4232 cFYI(1, ("OldQFSInfo"));
4234 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
4239 params
= 2; /* level */
4240 pSMB
->TotalDataCount
= 0;
4241 pSMB
->MaxParameterCount
= cpu_to_le16(2);
4242 pSMB
->MaxDataCount
= cpu_to_le16(1000);
4243 pSMB
->MaxSetupCount
= 0;
4247 pSMB
->Reserved2
= 0;
4248 byte_count
= params
+ 1 /* pad */ ;
4249 pSMB
->TotalParameterCount
= cpu_to_le16(params
);
4250 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
4251 pSMB
->ParameterOffset
= cpu_to_le16(offsetof(
4252 struct smb_com_transaction2_qfsi_req
, InformationLevel
) - 4);
4253 pSMB
->DataCount
= 0;
4254 pSMB
->DataOffset
= 0;
4255 pSMB
->SetupCount
= 1;
4256 pSMB
->Reserved3
= 0;
4257 pSMB
->SubCommand
= cpu_to_le16(TRANS2_QUERY_FS_INFORMATION
);
4258 pSMB
->InformationLevel
= cpu_to_le16(SMB_INFO_ALLOCATION
);
4259 pSMB
->hdr
.smb_buf_length
+= byte_count
;
4260 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
4262 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
4263 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
4265 cFYI(1, ("Send error in QFSInfo = %d", rc
));
4266 } else { /* decode response */
4267 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
4269 if (rc
|| (pSMBr
->ByteCount
< 18))
4270 rc
= -EIO
; /* bad smb */
4272 __u16 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
4273 cFYI(1, ("qfsinf resp BCC: %d Offset %d",
4274 pSMBr
->ByteCount
, data_offset
));
4276 response_data
= (FILE_SYSTEM_ALLOC_INFO
*)
4277 (((char *) &pSMBr
->hdr
.Protocol
) + data_offset
);
4279 le16_to_cpu(response_data
->BytesPerSector
) *
4280 le32_to_cpu(response_data
->
4281 SectorsPerAllocationUnit
);
4283 le32_to_cpu(response_data
->TotalAllocationUnits
);
4284 FSData
->f_bfree
= FSData
->f_bavail
=
4285 le32_to_cpu(response_data
->FreeAllocationUnits
);
4287 ("Blocks: %lld Free: %lld Block size %ld",
4288 (unsigned long long)FSData
->f_blocks
,
4289 (unsigned long long)FSData
->f_bfree
,
4293 cifs_buf_release(pSMB
);
4296 goto oldQFSInfoRetry
;
4302 CIFSSMBQFSInfo(const int xid
, struct cifsTconInfo
*tcon
, struct kstatfs
*FSData
)
4304 /* level 0x103 SMB_QUERY_FILE_SYSTEM_INFO */
4305 TRANSACTION2_QFSI_REQ
*pSMB
= NULL
;
4306 TRANSACTION2_QFSI_RSP
*pSMBr
= NULL
;
4307 FILE_SYSTEM_INFO
*response_data
;
4309 int bytes_returned
= 0;
4310 __u16 params
, byte_count
;
4312 cFYI(1, ("In QFSInfo"));
4314 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
4319 params
= 2; /* level */
4320 pSMB
->TotalDataCount
= 0;
4321 pSMB
->MaxParameterCount
= cpu_to_le16(2);
4322 pSMB
->MaxDataCount
= cpu_to_le16(1000);
4323 pSMB
->MaxSetupCount
= 0;
4327 pSMB
->Reserved2
= 0;
4328 byte_count
= params
+ 1 /* pad */ ;
4329 pSMB
->TotalParameterCount
= cpu_to_le16(params
);
4330 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
4331 pSMB
->ParameterOffset
= cpu_to_le16(offsetof(
4332 struct smb_com_transaction2_qfsi_req
, InformationLevel
) - 4);
4333 pSMB
->DataCount
= 0;
4334 pSMB
->DataOffset
= 0;
4335 pSMB
->SetupCount
= 1;
4336 pSMB
->Reserved3
= 0;
4337 pSMB
->SubCommand
= cpu_to_le16(TRANS2_QUERY_FS_INFORMATION
);
4338 pSMB
->InformationLevel
= cpu_to_le16(SMB_QUERY_FS_SIZE_INFO
);
4339 pSMB
->hdr
.smb_buf_length
+= byte_count
;
4340 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
4342 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
4343 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
4345 cFYI(1, ("Send error in QFSInfo = %d", rc
));
4346 } else { /* decode response */
4347 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
4349 if (rc
|| (pSMBr
->ByteCount
< 24))
4350 rc
= -EIO
; /* bad smb */
4352 __u16 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
4356 *) (((char *) &pSMBr
->hdr
.Protocol
) +
4359 le32_to_cpu(response_data
->BytesPerSector
) *
4360 le32_to_cpu(response_data
->
4361 SectorsPerAllocationUnit
);
4363 le64_to_cpu(response_data
->TotalAllocationUnits
);
4364 FSData
->f_bfree
= FSData
->f_bavail
=
4365 le64_to_cpu(response_data
->FreeAllocationUnits
);
4367 ("Blocks: %lld Free: %lld Block size %ld",
4368 (unsigned long long)FSData
->f_blocks
,
4369 (unsigned long long)FSData
->f_bfree
,
4373 cifs_buf_release(pSMB
);
4382 CIFSSMBQFSAttributeInfo(const int xid
, struct cifsTconInfo
*tcon
)
4384 /* level 0x105 SMB_QUERY_FILE_SYSTEM_INFO */
4385 TRANSACTION2_QFSI_REQ
*pSMB
= NULL
;
4386 TRANSACTION2_QFSI_RSP
*pSMBr
= NULL
;
4387 FILE_SYSTEM_ATTRIBUTE_INFO
*response_data
;
4389 int bytes_returned
= 0;
4390 __u16 params
, byte_count
;
4392 cFYI(1, ("In QFSAttributeInfo"));
4394 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
4399 params
= 2; /* level */
4400 pSMB
->TotalDataCount
= 0;
4401 pSMB
->MaxParameterCount
= cpu_to_le16(2);
4402 /* BB find exact max SMB PDU from sess structure BB */
4403 pSMB
->MaxDataCount
= cpu_to_le16(1000);
4404 pSMB
->MaxSetupCount
= 0;
4408 pSMB
->Reserved2
= 0;
4409 byte_count
= params
+ 1 /* pad */ ;
4410 pSMB
->TotalParameterCount
= cpu_to_le16(params
);
4411 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
4412 pSMB
->ParameterOffset
= cpu_to_le16(offsetof(
4413 struct smb_com_transaction2_qfsi_req
, InformationLevel
) - 4);
4414 pSMB
->DataCount
= 0;
4415 pSMB
->DataOffset
= 0;
4416 pSMB
->SetupCount
= 1;
4417 pSMB
->Reserved3
= 0;
4418 pSMB
->SubCommand
= cpu_to_le16(TRANS2_QUERY_FS_INFORMATION
);
4419 pSMB
->InformationLevel
= cpu_to_le16(SMB_QUERY_FS_ATTRIBUTE_INFO
);
4420 pSMB
->hdr
.smb_buf_length
+= byte_count
;
4421 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
4423 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
4424 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
4426 cERROR(1, ("Send error in QFSAttributeInfo = %d", rc
));
4427 } else { /* decode response */
4428 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
4430 if (rc
|| (pSMBr
->ByteCount
< 13)) {
4431 /* BB also check if enough bytes returned */
4432 rc
= -EIO
; /* bad smb */
4434 __u16 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
4436 (FILE_SYSTEM_ATTRIBUTE_INFO
4437 *) (((char *) &pSMBr
->hdr
.Protocol
) +
4439 memcpy(&tcon
->fsAttrInfo
, response_data
,
4440 sizeof(FILE_SYSTEM_ATTRIBUTE_INFO
));
4443 cifs_buf_release(pSMB
);
4446 goto QFSAttributeRetry
;
4452 CIFSSMBQFSDeviceInfo(const int xid
, struct cifsTconInfo
*tcon
)
4454 /* level 0x104 SMB_QUERY_FILE_SYSTEM_INFO */
4455 TRANSACTION2_QFSI_REQ
*pSMB
= NULL
;
4456 TRANSACTION2_QFSI_RSP
*pSMBr
= NULL
;
4457 FILE_SYSTEM_DEVICE_INFO
*response_data
;
4459 int bytes_returned
= 0;
4460 __u16 params
, byte_count
;
4462 cFYI(1, ("In QFSDeviceInfo"));
4464 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
4469 params
= 2; /* level */
4470 pSMB
->TotalDataCount
= 0;
4471 pSMB
->MaxParameterCount
= cpu_to_le16(2);
4472 /* BB find exact max SMB PDU from sess structure BB */
4473 pSMB
->MaxDataCount
= cpu_to_le16(1000);
4474 pSMB
->MaxSetupCount
= 0;
4478 pSMB
->Reserved2
= 0;
4479 byte_count
= params
+ 1 /* pad */ ;
4480 pSMB
->TotalParameterCount
= cpu_to_le16(params
);
4481 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
4482 pSMB
->ParameterOffset
= cpu_to_le16(offsetof(
4483 struct smb_com_transaction2_qfsi_req
, InformationLevel
) - 4);
4485 pSMB
->DataCount
= 0;
4486 pSMB
->DataOffset
= 0;
4487 pSMB
->SetupCount
= 1;
4488 pSMB
->Reserved3
= 0;
4489 pSMB
->SubCommand
= cpu_to_le16(TRANS2_QUERY_FS_INFORMATION
);
4490 pSMB
->InformationLevel
= cpu_to_le16(SMB_QUERY_FS_DEVICE_INFO
);
4491 pSMB
->hdr
.smb_buf_length
+= byte_count
;
4492 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
4494 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
4495 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
4497 cFYI(1, ("Send error in QFSDeviceInfo = %d", rc
));
4498 } else { /* decode response */
4499 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
4501 if (rc
|| (pSMBr
->ByteCount
< sizeof(FILE_SYSTEM_DEVICE_INFO
)))
4502 rc
= -EIO
; /* bad smb */
4504 __u16 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
4506 (FILE_SYSTEM_DEVICE_INFO
*)
4507 (((char *) &pSMBr
->hdr
.Protocol
) +
4509 memcpy(&tcon
->fsDevInfo
, response_data
,
4510 sizeof(FILE_SYSTEM_DEVICE_INFO
));
4513 cifs_buf_release(pSMB
);
4516 goto QFSDeviceRetry
;
4522 CIFSSMBQFSUnixInfo(const int xid
, struct cifsTconInfo
*tcon
)
4524 /* level 0x200 SMB_QUERY_CIFS_UNIX_INFO */
4525 TRANSACTION2_QFSI_REQ
*pSMB
= NULL
;
4526 TRANSACTION2_QFSI_RSP
*pSMBr
= NULL
;
4527 FILE_SYSTEM_UNIX_INFO
*response_data
;
4529 int bytes_returned
= 0;
4530 __u16 params
, byte_count
;
4532 cFYI(1, ("In QFSUnixInfo"));
4534 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
4539 params
= 2; /* level */
4540 pSMB
->TotalDataCount
= 0;
4541 pSMB
->DataCount
= 0;
4542 pSMB
->DataOffset
= 0;
4543 pSMB
->MaxParameterCount
= cpu_to_le16(2);
4544 /* BB find exact max SMB PDU from sess structure BB */
4545 pSMB
->MaxDataCount
= cpu_to_le16(100);
4546 pSMB
->MaxSetupCount
= 0;
4550 pSMB
->Reserved2
= 0;
4551 byte_count
= params
+ 1 /* pad */ ;
4552 pSMB
->ParameterCount
= cpu_to_le16(params
);
4553 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
4554 pSMB
->ParameterOffset
= cpu_to_le16(offsetof(struct
4555 smb_com_transaction2_qfsi_req
, InformationLevel
) - 4);
4556 pSMB
->SetupCount
= 1;
4557 pSMB
->Reserved3
= 0;
4558 pSMB
->SubCommand
= cpu_to_le16(TRANS2_QUERY_FS_INFORMATION
);
4559 pSMB
->InformationLevel
= cpu_to_le16(SMB_QUERY_CIFS_UNIX_INFO
);
4560 pSMB
->hdr
.smb_buf_length
+= byte_count
;
4561 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
4563 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
4564 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
4566 cERROR(1, ("Send error in QFSUnixInfo = %d", rc
));
4567 } else { /* decode response */
4568 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
4570 if (rc
|| (pSMBr
->ByteCount
< 13)) {
4571 rc
= -EIO
; /* bad smb */
4573 __u16 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
4575 (FILE_SYSTEM_UNIX_INFO
4576 *) (((char *) &pSMBr
->hdr
.Protocol
) +
4578 memcpy(&tcon
->fsUnixInfo
, response_data
,
4579 sizeof(FILE_SYSTEM_UNIX_INFO
));
4582 cifs_buf_release(pSMB
);
4592 CIFSSMBSetFSUnixInfo(const int xid
, struct cifsTconInfo
*tcon
, __u64 cap
)
4594 /* level 0x200 SMB_SET_CIFS_UNIX_INFO */
4595 TRANSACTION2_SETFSI_REQ
*pSMB
= NULL
;
4596 TRANSACTION2_SETFSI_RSP
*pSMBr
= NULL
;
4598 int bytes_returned
= 0;
4599 __u16 params
, param_offset
, offset
, byte_count
;
4601 cFYI(1, ("In SETFSUnixInfo"));
4603 /* BB switch to small buf init to save memory */
4604 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
4609 params
= 4; /* 2 bytes zero followed by info level. */
4610 pSMB
->MaxSetupCount
= 0;
4614 pSMB
->Reserved2
= 0;
4615 param_offset
= offsetof(struct smb_com_transaction2_setfsi_req
, FileNum
)
4617 offset
= param_offset
+ params
;
4619 pSMB
->MaxParameterCount
= cpu_to_le16(4);
4620 /* BB find exact max SMB PDU from sess structure BB */
4621 pSMB
->MaxDataCount
= cpu_to_le16(100);
4622 pSMB
->SetupCount
= 1;
4623 pSMB
->Reserved3
= 0;
4624 pSMB
->SubCommand
= cpu_to_le16(TRANS2_SET_FS_INFORMATION
);
4625 byte_count
= 1 /* pad */ + params
+ 12;
4627 pSMB
->DataCount
= cpu_to_le16(12);
4628 pSMB
->ParameterCount
= cpu_to_le16(params
);
4629 pSMB
->TotalDataCount
= pSMB
->DataCount
;
4630 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
4631 pSMB
->ParameterOffset
= cpu_to_le16(param_offset
);
4632 pSMB
->DataOffset
= cpu_to_le16(offset
);
4636 pSMB
->InformationLevel
= cpu_to_le16(SMB_SET_CIFS_UNIX_INFO
);
4639 pSMB
->ClientUnixMajor
= cpu_to_le16(CIFS_UNIX_MAJOR_VERSION
);
4640 pSMB
->ClientUnixMinor
= cpu_to_le16(CIFS_UNIX_MINOR_VERSION
);
4641 pSMB
->ClientUnixCap
= cpu_to_le64(cap
);
4643 pSMB
->hdr
.smb_buf_length
+= byte_count
;
4644 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
4646 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
4647 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
4649 cERROR(1, ("Send error in SETFSUnixInfo = %d", rc
));
4650 } else { /* decode response */
4651 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
4653 rc
= -EIO
; /* bad smb */
4655 cifs_buf_release(pSMB
);
4658 goto SETFSUnixRetry
;
4666 CIFSSMBQFSPosixInfo(const int xid
, struct cifsTconInfo
*tcon
,
4667 struct kstatfs
*FSData
)
4669 /* level 0x201 SMB_QUERY_CIFS_POSIX_INFO */
4670 TRANSACTION2_QFSI_REQ
*pSMB
= NULL
;
4671 TRANSACTION2_QFSI_RSP
*pSMBr
= NULL
;
4672 FILE_SYSTEM_POSIX_INFO
*response_data
;
4674 int bytes_returned
= 0;
4675 __u16 params
, byte_count
;
4677 cFYI(1, ("In QFSPosixInfo"));
4679 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
4684 params
= 2; /* level */
4685 pSMB
->TotalDataCount
= 0;
4686 pSMB
->DataCount
= 0;
4687 pSMB
->DataOffset
= 0;
4688 pSMB
->MaxParameterCount
= cpu_to_le16(2);
4689 /* BB find exact max SMB PDU from sess structure BB */
4690 pSMB
->MaxDataCount
= cpu_to_le16(100);
4691 pSMB
->MaxSetupCount
= 0;
4695 pSMB
->Reserved2
= 0;
4696 byte_count
= params
+ 1 /* pad */ ;
4697 pSMB
->ParameterCount
= cpu_to_le16(params
);
4698 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
4699 pSMB
->ParameterOffset
= cpu_to_le16(offsetof(struct
4700 smb_com_transaction2_qfsi_req
, InformationLevel
) - 4);
4701 pSMB
->SetupCount
= 1;
4702 pSMB
->Reserved3
= 0;
4703 pSMB
->SubCommand
= cpu_to_le16(TRANS2_QUERY_FS_INFORMATION
);
4704 pSMB
->InformationLevel
= cpu_to_le16(SMB_QUERY_POSIX_FS_INFO
);
4705 pSMB
->hdr
.smb_buf_length
+= byte_count
;
4706 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
4708 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
4709 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
4711 cFYI(1, ("Send error in QFSUnixInfo = %d", rc
));
4712 } else { /* decode response */
4713 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
4715 if (rc
|| (pSMBr
->ByteCount
< 13)) {
4716 rc
= -EIO
; /* bad smb */
4718 __u16 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
4720 (FILE_SYSTEM_POSIX_INFO
4721 *) (((char *) &pSMBr
->hdr
.Protocol
) +
4724 le32_to_cpu(response_data
->BlockSize
);
4726 le64_to_cpu(response_data
->TotalBlocks
);
4728 le64_to_cpu(response_data
->BlocksAvail
);
4729 if (response_data
->UserBlocksAvail
== cpu_to_le64(-1)) {
4730 FSData
->f_bavail
= FSData
->f_bfree
;
4733 le64_to_cpu(response_data
->UserBlocksAvail
);
4735 if (response_data
->TotalFileNodes
!= cpu_to_le64(-1))
4737 le64_to_cpu(response_data
->TotalFileNodes
);
4738 if (response_data
->FreeFileNodes
!= cpu_to_le64(-1))
4740 le64_to_cpu(response_data
->FreeFileNodes
);
4743 cifs_buf_release(pSMB
);
4752 /* We can not use write of zero bytes trick to
4753 set file size due to need for large file support. Also note that
4754 this SetPathInfo is preferred to SetFileInfo based method in next
4755 routine which is only needed to work around a sharing violation bug
4756 in Samba which this routine can run into */
4759 CIFSSMBSetEOF(const int xid
, struct cifsTconInfo
*tcon
, const char *fileName
,
4760 __u64 size
, bool SetAllocation
,
4761 const struct nls_table
*nls_codepage
, int remap
)
4763 struct smb_com_transaction2_spi_req
*pSMB
= NULL
;
4764 struct smb_com_transaction2_spi_rsp
*pSMBr
= NULL
;
4765 struct file_end_of_file_info
*parm_data
;
4768 int bytes_returned
= 0;
4769 __u16 params
, byte_count
, data_count
, param_offset
, offset
;
4771 cFYI(1, ("In SetEOF"));
4773 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
4778 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
4780 cifsConvertToUCS((__le16
*) pSMB
->FileName
, fileName
,
4781 PATH_MAX
, nls_codepage
, remap
);
4782 name_len
++; /* trailing null */
4784 } else { /* BB improve the check for buffer overruns BB */
4785 name_len
= strnlen(fileName
, PATH_MAX
);
4786 name_len
++; /* trailing null */
4787 strncpy(pSMB
->FileName
, fileName
, name_len
);
4789 params
= 6 + name_len
;
4790 data_count
= sizeof(struct file_end_of_file_info
);
4791 pSMB
->MaxParameterCount
= cpu_to_le16(2);
4792 pSMB
->MaxDataCount
= cpu_to_le16(4100);
4793 pSMB
->MaxSetupCount
= 0;
4797 pSMB
->Reserved2
= 0;
4798 param_offset
= offsetof(struct smb_com_transaction2_spi_req
,
4799 InformationLevel
) - 4;
4800 offset
= param_offset
+ params
;
4801 if (SetAllocation
) {
4802 if (tcon
->ses
->capabilities
& CAP_INFOLEVEL_PASSTHRU
)
4803 pSMB
->InformationLevel
=
4804 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2
);
4806 pSMB
->InformationLevel
=
4807 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO
);
4808 } else /* Set File Size */ {
4809 if (tcon
->ses
->capabilities
& CAP_INFOLEVEL_PASSTHRU
)
4810 pSMB
->InformationLevel
=
4811 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO2
);
4813 pSMB
->InformationLevel
=
4814 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO
);
4818 (struct file_end_of_file_info
*) (((char *) &pSMB
->hdr
.Protocol
) +
4820 pSMB
->ParameterOffset
= cpu_to_le16(param_offset
);
4821 pSMB
->DataOffset
= cpu_to_le16(offset
);
4822 pSMB
->SetupCount
= 1;
4823 pSMB
->Reserved3
= 0;
4824 pSMB
->SubCommand
= cpu_to_le16(TRANS2_SET_PATH_INFORMATION
);
4825 byte_count
= 3 /* pad */ + params
+ data_count
;
4826 pSMB
->DataCount
= cpu_to_le16(data_count
);
4827 pSMB
->TotalDataCount
= pSMB
->DataCount
;
4828 pSMB
->ParameterCount
= cpu_to_le16(params
);
4829 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
4830 pSMB
->Reserved4
= 0;
4831 pSMB
->hdr
.smb_buf_length
+= byte_count
;
4832 parm_data
->FileSize
= cpu_to_le64(size
);
4833 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
4834 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
4835 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
4837 cFYI(1, ("SetPathInfo (file size) returned %d", rc
));
4839 cifs_buf_release(pSMB
);
4848 CIFSSMBSetFileSize(const int xid
, struct cifsTconInfo
*tcon
, __u64 size
,
4849 __u16 fid
, __u32 pid_of_opener
, bool SetAllocation
)
4851 struct smb_com_transaction2_sfi_req
*pSMB
= NULL
;
4853 struct file_end_of_file_info
*parm_data
;
4855 __u16 params
, param_offset
, offset
, byte_count
, count
;
4857 cFYI(1, ("SetFileSize (via SetFileInfo) %lld",
4859 rc
= small_smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
);
4864 pSMB
->hdr
.Pid
= cpu_to_le16((__u16
)pid_of_opener
);
4865 pSMB
->hdr
.PidHigh
= cpu_to_le16((__u16
)(pid_of_opener
>> 16));
4868 pSMB
->MaxSetupCount
= 0;
4872 pSMB
->Reserved2
= 0;
4873 param_offset
= offsetof(struct smb_com_transaction2_sfi_req
, Fid
) - 4;
4874 offset
= param_offset
+ params
;
4876 data_offset
= (char *) (&pSMB
->hdr
.Protocol
) + offset
;
4878 count
= sizeof(struct file_end_of_file_info
);
4879 pSMB
->MaxParameterCount
= cpu_to_le16(2);
4880 /* BB find exact max SMB PDU from sess structure BB */
4881 pSMB
->MaxDataCount
= cpu_to_le16(1000);
4882 pSMB
->SetupCount
= 1;
4883 pSMB
->Reserved3
= 0;
4884 pSMB
->SubCommand
= cpu_to_le16(TRANS2_SET_FILE_INFORMATION
);
4885 byte_count
= 3 /* pad */ + params
+ count
;
4886 pSMB
->DataCount
= cpu_to_le16(count
);
4887 pSMB
->ParameterCount
= cpu_to_le16(params
);
4888 pSMB
->TotalDataCount
= pSMB
->DataCount
;
4889 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
4890 pSMB
->ParameterOffset
= cpu_to_le16(param_offset
);
4892 (struct file_end_of_file_info
*) (((char *) &pSMB
->hdr
.Protocol
)
4894 pSMB
->DataOffset
= cpu_to_le16(offset
);
4895 parm_data
->FileSize
= cpu_to_le64(size
);
4897 if (SetAllocation
) {
4898 if (tcon
->ses
->capabilities
& CAP_INFOLEVEL_PASSTHRU
)
4899 pSMB
->InformationLevel
=
4900 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2
);
4902 pSMB
->InformationLevel
=
4903 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO
);
4904 } else /* Set File Size */ {
4905 if (tcon
->ses
->capabilities
& CAP_INFOLEVEL_PASSTHRU
)
4906 pSMB
->InformationLevel
=
4907 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO2
);
4909 pSMB
->InformationLevel
=
4910 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO
);
4912 pSMB
->Reserved4
= 0;
4913 pSMB
->hdr
.smb_buf_length
+= byte_count
;
4914 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
4915 rc
= SendReceiveNoRsp(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
, 0);
4918 ("Send error in SetFileInfo (SetFileSize) = %d",
4922 /* Note: On -EAGAIN error only caller can retry on handle based calls
4923 since file handle passed in no longer valid */
4928 /* Some legacy servers such as NT4 require that the file times be set on
4929 an open handle, rather than by pathname - this is awkward due to
4930 potential access conflicts on the open, but it is unavoidable for these
4931 old servers since the only other choice is to go from 100 nanosecond DCE
4932 time and resort to the original setpathinfo level which takes the ancient
4933 DOS time format with 2 second granularity */
4935 CIFSSMBSetFileInfo(const int xid
, struct cifsTconInfo
*tcon
,
4936 const FILE_BASIC_INFO
*data
, __u16 fid
, __u32 pid_of_opener
)
4938 struct smb_com_transaction2_sfi_req
*pSMB
= NULL
;
4941 __u16 params
, param_offset
, offset
, byte_count
, count
;
4943 cFYI(1, ("Set Times (via SetFileInfo)"));
4944 rc
= small_smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
);
4949 pSMB
->hdr
.Pid
= cpu_to_le16((__u16
)pid_of_opener
);
4950 pSMB
->hdr
.PidHigh
= cpu_to_le16((__u16
)(pid_of_opener
>> 16));
4953 pSMB
->MaxSetupCount
= 0;
4957 pSMB
->Reserved2
= 0;
4958 param_offset
= offsetof(struct smb_com_transaction2_sfi_req
, Fid
) - 4;
4959 offset
= param_offset
+ params
;
4961 data_offset
= (char *) (&pSMB
->hdr
.Protocol
) + offset
;
4963 count
= sizeof(FILE_BASIC_INFO
);
4964 pSMB
->MaxParameterCount
= cpu_to_le16(2);
4965 /* BB find max SMB PDU from sess */
4966 pSMB
->MaxDataCount
= cpu_to_le16(1000);
4967 pSMB
->SetupCount
= 1;
4968 pSMB
->Reserved3
= 0;
4969 pSMB
->SubCommand
= cpu_to_le16(TRANS2_SET_FILE_INFORMATION
);
4970 byte_count
= 3 /* pad */ + params
+ count
;
4971 pSMB
->DataCount
= cpu_to_le16(count
);
4972 pSMB
->ParameterCount
= cpu_to_le16(params
);
4973 pSMB
->TotalDataCount
= pSMB
->DataCount
;
4974 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
4975 pSMB
->ParameterOffset
= cpu_to_le16(param_offset
);
4976 pSMB
->DataOffset
= cpu_to_le16(offset
);
4978 if (tcon
->ses
->capabilities
& CAP_INFOLEVEL_PASSTHRU
)
4979 pSMB
->InformationLevel
= cpu_to_le16(SMB_SET_FILE_BASIC_INFO2
);
4981 pSMB
->InformationLevel
= cpu_to_le16(SMB_SET_FILE_BASIC_INFO
);
4982 pSMB
->Reserved4
= 0;
4983 pSMB
->hdr
.smb_buf_length
+= byte_count
;
4984 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
4985 memcpy(data_offset
, data
, sizeof(FILE_BASIC_INFO
));
4986 rc
= SendReceiveNoRsp(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
, 0);
4988 cFYI(1, ("Send error in Set Time (SetFileInfo) = %d", rc
));
4990 /* Note: On -EAGAIN error only caller can retry on handle based calls
4991 since file handle passed in no longer valid */
4997 CIFSSMBSetFileDisposition(const int xid
, struct cifsTconInfo
*tcon
,
4998 bool delete_file
, __u16 fid
, __u32 pid_of_opener
)
5000 struct smb_com_transaction2_sfi_req
*pSMB
= NULL
;
5003 __u16 params
, param_offset
, offset
, byte_count
, count
;
5005 cFYI(1, ("Set File Disposition (via SetFileInfo)"));
5006 rc
= small_smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
);
5011 pSMB
->hdr
.Pid
= cpu_to_le16((__u16
)pid_of_opener
);
5012 pSMB
->hdr
.PidHigh
= cpu_to_le16((__u16
)(pid_of_opener
>> 16));
5015 pSMB
->MaxSetupCount
= 0;
5019 pSMB
->Reserved2
= 0;
5020 param_offset
= offsetof(struct smb_com_transaction2_sfi_req
, Fid
) - 4;
5021 offset
= param_offset
+ params
;
5023 data_offset
= (char *) (&pSMB
->hdr
.Protocol
) + offset
;
5026 pSMB
->MaxParameterCount
= cpu_to_le16(2);
5027 /* BB find max SMB PDU from sess */
5028 pSMB
->MaxDataCount
= cpu_to_le16(1000);
5029 pSMB
->SetupCount
= 1;
5030 pSMB
->Reserved3
= 0;
5031 pSMB
->SubCommand
= cpu_to_le16(TRANS2_SET_FILE_INFORMATION
);
5032 byte_count
= 3 /* pad */ + params
+ count
;
5033 pSMB
->DataCount
= cpu_to_le16(count
);
5034 pSMB
->ParameterCount
= cpu_to_le16(params
);
5035 pSMB
->TotalDataCount
= pSMB
->DataCount
;
5036 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
5037 pSMB
->ParameterOffset
= cpu_to_le16(param_offset
);
5038 pSMB
->DataOffset
= cpu_to_le16(offset
);
5040 pSMB
->InformationLevel
= cpu_to_le16(SMB_SET_FILE_DISPOSITION_INFO
);
5041 pSMB
->Reserved4
= 0;
5042 pSMB
->hdr
.smb_buf_length
+= byte_count
;
5043 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
5044 *data_offset
= delete_file
? 1 : 0;
5045 rc
= SendReceiveNoRsp(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
, 0);
5047 cFYI(1, ("Send error in SetFileDisposition = %d", rc
));
5053 CIFSSMBSetPathInfo(const int xid
, struct cifsTconInfo
*tcon
,
5054 const char *fileName
, const FILE_BASIC_INFO
*data
,
5055 const struct nls_table
*nls_codepage
, int remap
)
5057 TRANSACTION2_SPI_REQ
*pSMB
= NULL
;
5058 TRANSACTION2_SPI_RSP
*pSMBr
= NULL
;
5061 int bytes_returned
= 0;
5063 __u16 params
, param_offset
, offset
, byte_count
, count
;
5065 cFYI(1, ("In SetTimes"));
5068 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
5073 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
5075 cifsConvertToUCS((__le16
*) pSMB
->FileName
, fileName
,
5076 PATH_MAX
, nls_codepage
, remap
);
5077 name_len
++; /* trailing null */
5079 } else { /* BB improve the check for buffer overruns BB */
5080 name_len
= strnlen(fileName
, PATH_MAX
);
5081 name_len
++; /* trailing null */
5082 strncpy(pSMB
->FileName
, fileName
, name_len
);
5085 params
= 6 + name_len
;
5086 count
= sizeof(FILE_BASIC_INFO
);
5087 pSMB
->MaxParameterCount
= cpu_to_le16(2);
5088 /* BB find max SMB PDU from sess structure BB */
5089 pSMB
->MaxDataCount
= cpu_to_le16(1000);
5090 pSMB
->MaxSetupCount
= 0;
5094 pSMB
->Reserved2
= 0;
5095 param_offset
= offsetof(struct smb_com_transaction2_spi_req
,
5096 InformationLevel
) - 4;
5097 offset
= param_offset
+ params
;
5098 data_offset
= (char *) (&pSMB
->hdr
.Protocol
) + offset
;
5099 pSMB
->ParameterOffset
= cpu_to_le16(param_offset
);
5100 pSMB
->DataOffset
= cpu_to_le16(offset
);
5101 pSMB
->SetupCount
= 1;
5102 pSMB
->Reserved3
= 0;
5103 pSMB
->SubCommand
= cpu_to_le16(TRANS2_SET_PATH_INFORMATION
);
5104 byte_count
= 3 /* pad */ + params
+ count
;
5106 pSMB
->DataCount
= cpu_to_le16(count
);
5107 pSMB
->ParameterCount
= cpu_to_le16(params
);
5108 pSMB
->TotalDataCount
= pSMB
->DataCount
;
5109 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
5110 if (tcon
->ses
->capabilities
& CAP_INFOLEVEL_PASSTHRU
)
5111 pSMB
->InformationLevel
= cpu_to_le16(SMB_SET_FILE_BASIC_INFO2
);
5113 pSMB
->InformationLevel
= cpu_to_le16(SMB_SET_FILE_BASIC_INFO
);
5114 pSMB
->Reserved4
= 0;
5115 pSMB
->hdr
.smb_buf_length
+= byte_count
;
5116 memcpy(data_offset
, data
, sizeof(FILE_BASIC_INFO
));
5117 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
5118 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
5119 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
5121 cFYI(1, ("SetPathInfo (times) returned %d", rc
));
5123 cifs_buf_release(pSMB
);
5131 /* Can not be used to set time stamps yet (due to old DOS time format) */
5132 /* Can be used to set attributes */
5133 #if 0 /* Possibly not needed - since it turns out that strangely NT4 has a bug
5134 handling it anyway and NT4 was what we thought it would be needed for
5135 Do not delete it until we prove whether needed for Win9x though */
5137 CIFSSMBSetAttrLegacy(int xid
, struct cifsTconInfo
*tcon
, char *fileName
,
5138 __u16 dos_attrs
, const struct nls_table
*nls_codepage
)
5140 SETATTR_REQ
*pSMB
= NULL
;
5141 SETATTR_RSP
*pSMBr
= NULL
;
5146 cFYI(1, ("In SetAttrLegacy"));
5149 rc
= smb_init(SMB_COM_SETATTR
, 8, tcon
, (void **) &pSMB
,
5154 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
5156 ConvertToUCS((__le16
*) pSMB
->fileName
, fileName
,
5157 PATH_MAX
, nls_codepage
);
5158 name_len
++; /* trailing null */
5160 } else { /* BB improve the check for buffer overruns BB */
5161 name_len
= strnlen(fileName
, PATH_MAX
);
5162 name_len
++; /* trailing null */
5163 strncpy(pSMB
->fileName
, fileName
, name_len
);
5165 pSMB
->attr
= cpu_to_le16(dos_attrs
);
5166 pSMB
->BufferFormat
= 0x04;
5167 pSMB
->hdr
.smb_buf_length
+= name_len
+ 1;
5168 pSMB
->ByteCount
= cpu_to_le16(name_len
+ 1);
5169 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
5170 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
5172 cFYI(1, ("Error in LegacySetAttr = %d", rc
));
5174 cifs_buf_release(pSMB
);
5177 goto SetAttrLgcyRetry
;
5181 #endif /* temporarily unneeded SetAttr legacy function */
5184 cifs_fill_unix_set_info(FILE_UNIX_BASIC_INFO
*data_offset
,
5185 const struct cifs_unix_set_info_args
*args
)
5187 u64 mode
= args
->mode
;
5190 * Samba server ignores set of file size to zero due to bugs in some
5191 * older clients, but we should be precise - we use SetFileSize to
5192 * set file size and do not want to truncate file size to zero
5193 * accidently as happened on one Samba server beta by putting
5194 * zero instead of -1 here
5196 data_offset
->EndOfFile
= cpu_to_le64(NO_CHANGE_64
);
5197 data_offset
->NumOfBytes
= cpu_to_le64(NO_CHANGE_64
);
5198 data_offset
->LastStatusChange
= cpu_to_le64(args
->ctime
);
5199 data_offset
->LastAccessTime
= cpu_to_le64(args
->atime
);
5200 data_offset
->LastModificationTime
= cpu_to_le64(args
->mtime
);
5201 data_offset
->Uid
= cpu_to_le64(args
->uid
);
5202 data_offset
->Gid
= cpu_to_le64(args
->gid
);
5203 /* better to leave device as zero when it is */
5204 data_offset
->DevMajor
= cpu_to_le64(MAJOR(args
->device
));
5205 data_offset
->DevMinor
= cpu_to_le64(MINOR(args
->device
));
5206 data_offset
->Permissions
= cpu_to_le64(mode
);
5209 data_offset
->Type
= cpu_to_le32(UNIX_FILE
);
5210 else if (S_ISDIR(mode
))
5211 data_offset
->Type
= cpu_to_le32(UNIX_DIR
);
5212 else if (S_ISLNK(mode
))
5213 data_offset
->Type
= cpu_to_le32(UNIX_SYMLINK
);
5214 else if (S_ISCHR(mode
))
5215 data_offset
->Type
= cpu_to_le32(UNIX_CHARDEV
);
5216 else if (S_ISBLK(mode
))
5217 data_offset
->Type
= cpu_to_le32(UNIX_BLOCKDEV
);
5218 else if (S_ISFIFO(mode
))
5219 data_offset
->Type
= cpu_to_le32(UNIX_FIFO
);
5220 else if (S_ISSOCK(mode
))
5221 data_offset
->Type
= cpu_to_le32(UNIX_SOCKET
);
5225 CIFSSMBUnixSetFileInfo(const int xid
, struct cifsTconInfo
*tcon
,
5226 const struct cifs_unix_set_info_args
*args
,
5227 u16 fid
, u32 pid_of_opener
)
5229 struct smb_com_transaction2_sfi_req
*pSMB
= NULL
;
5230 FILE_UNIX_BASIC_INFO
*data_offset
;
5232 u16 params
, param_offset
, offset
, byte_count
, count
;
5234 cFYI(1, ("Set Unix Info (via SetFileInfo)"));
5235 rc
= small_smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
);
5240 pSMB
->hdr
.Pid
= cpu_to_le16((__u16
)pid_of_opener
);
5241 pSMB
->hdr
.PidHigh
= cpu_to_le16((__u16
)(pid_of_opener
>> 16));
5244 pSMB
->MaxSetupCount
= 0;
5248 pSMB
->Reserved2
= 0;
5249 param_offset
= offsetof(struct smb_com_transaction2_sfi_req
, Fid
) - 4;
5250 offset
= param_offset
+ params
;
5252 data_offset
= (FILE_UNIX_BASIC_INFO
*)
5253 ((char *)(&pSMB
->hdr
.Protocol
) + offset
);
5254 count
= sizeof(FILE_UNIX_BASIC_INFO
);
5256 pSMB
->MaxParameterCount
= cpu_to_le16(2);
5257 /* BB find max SMB PDU from sess */
5258 pSMB
->MaxDataCount
= cpu_to_le16(1000);
5259 pSMB
->SetupCount
= 1;
5260 pSMB
->Reserved3
= 0;
5261 pSMB
->SubCommand
= cpu_to_le16(TRANS2_SET_FILE_INFORMATION
);
5262 byte_count
= 3 /* pad */ + params
+ count
;
5263 pSMB
->DataCount
= cpu_to_le16(count
);
5264 pSMB
->ParameterCount
= cpu_to_le16(params
);
5265 pSMB
->TotalDataCount
= pSMB
->DataCount
;
5266 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
5267 pSMB
->ParameterOffset
= cpu_to_le16(param_offset
);
5268 pSMB
->DataOffset
= cpu_to_le16(offset
);
5270 pSMB
->InformationLevel
= cpu_to_le16(SMB_SET_FILE_UNIX_BASIC
);
5271 pSMB
->Reserved4
= 0;
5272 pSMB
->hdr
.smb_buf_length
+= byte_count
;
5273 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
5275 cifs_fill_unix_set_info(data_offset
, args
);
5277 rc
= SendReceiveNoRsp(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
, 0);
5279 cFYI(1, ("Send error in Set Time (SetFileInfo) = %d", rc
));
5281 /* Note: On -EAGAIN error only caller can retry on handle based calls
5282 since file handle passed in no longer valid */
5288 CIFSSMBUnixSetPathInfo(const int xid
, struct cifsTconInfo
*tcon
, char *fileName
,
5289 const struct cifs_unix_set_info_args
*args
,
5290 const struct nls_table
*nls_codepage
, int remap
)
5292 TRANSACTION2_SPI_REQ
*pSMB
= NULL
;
5293 TRANSACTION2_SPI_RSP
*pSMBr
= NULL
;
5296 int bytes_returned
= 0;
5297 FILE_UNIX_BASIC_INFO
*data_offset
;
5298 __u16 params
, param_offset
, offset
, count
, byte_count
;
5300 cFYI(1, ("In SetUID/GID/Mode"));
5302 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
5307 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
5309 cifsConvertToUCS((__le16
*) pSMB
->FileName
, fileName
,
5310 PATH_MAX
, nls_codepage
, remap
);
5311 name_len
++; /* trailing null */
5313 } else { /* BB improve the check for buffer overruns BB */
5314 name_len
= strnlen(fileName
, PATH_MAX
);
5315 name_len
++; /* trailing null */
5316 strncpy(pSMB
->FileName
, fileName
, name_len
);
5319 params
= 6 + name_len
;
5320 count
= sizeof(FILE_UNIX_BASIC_INFO
);
5321 pSMB
->MaxParameterCount
= cpu_to_le16(2);
5322 /* BB find max SMB PDU from sess structure BB */
5323 pSMB
->MaxDataCount
= cpu_to_le16(1000);
5324 pSMB
->MaxSetupCount
= 0;
5328 pSMB
->Reserved2
= 0;
5329 param_offset
= offsetof(struct smb_com_transaction2_spi_req
,
5330 InformationLevel
) - 4;
5331 offset
= param_offset
+ params
;
5333 (FILE_UNIX_BASIC_INFO
*) ((char *) &pSMB
->hdr
.Protocol
+
5335 memset(data_offset
, 0, count
);
5336 pSMB
->DataOffset
= cpu_to_le16(offset
);
5337 pSMB
->ParameterOffset
= cpu_to_le16(param_offset
);
5338 pSMB
->SetupCount
= 1;
5339 pSMB
->Reserved3
= 0;
5340 pSMB
->SubCommand
= cpu_to_le16(TRANS2_SET_PATH_INFORMATION
);
5341 byte_count
= 3 /* pad */ + params
+ count
;
5342 pSMB
->ParameterCount
= cpu_to_le16(params
);
5343 pSMB
->DataCount
= cpu_to_le16(count
);
5344 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
5345 pSMB
->TotalDataCount
= pSMB
->DataCount
;
5346 pSMB
->InformationLevel
= cpu_to_le16(SMB_SET_FILE_UNIX_BASIC
);
5347 pSMB
->Reserved4
= 0;
5348 pSMB
->hdr
.smb_buf_length
+= byte_count
;
5350 cifs_fill_unix_set_info(data_offset
, args
);
5352 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
5353 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
5354 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
5356 cFYI(1, ("SetPathInfo (perms) returned %d", rc
));
5358 cifs_buf_release(pSMB
);
5364 int CIFSSMBNotify(const int xid
, struct cifsTconInfo
*tcon
,
5365 const int notify_subdirs
, const __u16 netfid
,
5366 __u32 filter
, struct file
*pfile
, int multishot
,
5367 const struct nls_table
*nls_codepage
)
5370 struct smb_com_transaction_change_notify_req
*pSMB
= NULL
;
5371 struct smb_com_ntransaction_change_notify_rsp
*pSMBr
= NULL
;
5372 struct dir_notify_req
*dnotify_req
;
5375 cFYI(1, ("In CIFSSMBNotify for file handle %d", (int)netfid
));
5376 rc
= smb_init(SMB_COM_NT_TRANSACT
, 23, tcon
, (void **) &pSMB
,
5381 pSMB
->TotalParameterCount
= 0 ;
5382 pSMB
->TotalDataCount
= 0;
5383 pSMB
->MaxParameterCount
= cpu_to_le32(2);
5384 /* BB find exact data count max from sess structure BB */
5385 pSMB
->MaxDataCount
= 0; /* same in little endian or be */
5386 /* BB VERIFY verify which is correct for above BB */
5387 pSMB
->MaxDataCount
= cpu_to_le32((tcon
->ses
->server
->maxBuf
-
5388 MAX_CIFS_HDR_SIZE
) & 0xFFFFFF00);
5390 pSMB
->MaxSetupCount
= 4;
5392 pSMB
->ParameterOffset
= 0;
5393 pSMB
->DataCount
= 0;
5394 pSMB
->DataOffset
= 0;
5395 pSMB
->SetupCount
= 4; /* single byte does not need le conversion */
5396 pSMB
->SubCommand
= cpu_to_le16(NT_TRANSACT_NOTIFY_CHANGE
);
5397 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
5399 pSMB
->WatchTree
= 1; /* one byte - no le conversion needed */
5400 pSMB
->Reserved2
= 0;
5401 pSMB
->CompletionFilter
= cpu_to_le32(filter
);
5402 pSMB
->Fid
= netfid
; /* file handle always le */
5403 pSMB
->ByteCount
= 0;
5405 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
5406 (struct smb_hdr
*)pSMBr
, &bytes_returned
,
5409 cFYI(1, ("Error in Notify = %d", rc
));
5411 /* Add file to outstanding requests */
5412 /* BB change to kmem cache alloc */
5413 dnotify_req
= kmalloc(
5414 sizeof(struct dir_notify_req
),
5417 dnotify_req
->Pid
= pSMB
->hdr
.Pid
;
5418 dnotify_req
->PidHigh
= pSMB
->hdr
.PidHigh
;
5419 dnotify_req
->Mid
= pSMB
->hdr
.Mid
;
5420 dnotify_req
->Tid
= pSMB
->hdr
.Tid
;
5421 dnotify_req
->Uid
= pSMB
->hdr
.Uid
;
5422 dnotify_req
->netfid
= netfid
;
5423 dnotify_req
->pfile
= pfile
;
5424 dnotify_req
->filter
= filter
;
5425 dnotify_req
->multishot
= multishot
;
5426 spin_lock(&GlobalMid_Lock
);
5427 list_add_tail(&dnotify_req
->lhead
,
5428 &GlobalDnotifyReqList
);
5429 spin_unlock(&GlobalMid_Lock
);
5433 cifs_buf_release(pSMB
);
5437 #ifdef CONFIG_CIFS_XATTR
5439 * Do a path-based QUERY_ALL_EAS call and parse the result. This is a common
5440 * function used by listxattr and getxattr type calls. When ea_name is set,
5441 * it looks for that attribute name and stuffs that value into the EAData
5442 * buffer. When ea_name is NULL, it stuffs a list of attribute names into the
5443 * buffer. In both cases, the return value is either the length of the
5444 * resulting data or a negative error code. If EAData is a NULL pointer then
5445 * the data isn't copied to it, but the length is returned.
5448 CIFSSMBQAllEAs(const int xid
, struct cifsTconInfo
*tcon
,
5449 const unsigned char *searchName
, const unsigned char *ea_name
,
5450 char *EAData
, size_t buf_size
,
5451 const struct nls_table
*nls_codepage
, int remap
)
5453 /* BB assumes one setup word */
5454 TRANSACTION2_QPI_REQ
*pSMB
= NULL
;
5455 TRANSACTION2_QPI_RSP
*pSMBr
= NULL
;
5459 struct fealist
*ea_response_data
;
5460 struct fea
*temp_fea
;
5463 __u16 params
, byte_count
, data_offset
;
5465 cFYI(1, ("In Query All EAs path %s", searchName
));
5467 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
5472 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
5474 cifsConvertToUCS((__le16
*) pSMB
->FileName
, searchName
,
5475 PATH_MAX
, nls_codepage
, remap
);
5476 list_len
++; /* trailing null */
5478 } else { /* BB improve the check for buffer overruns BB */
5479 list_len
= strnlen(searchName
, PATH_MAX
);
5480 list_len
++; /* trailing null */
5481 strncpy(pSMB
->FileName
, searchName
, list_len
);
5484 params
= 2 /* level */ + 4 /* reserved */ + list_len
/* includes NUL */;
5485 pSMB
->TotalDataCount
= 0;
5486 pSMB
->MaxParameterCount
= cpu_to_le16(2);
5487 /* BB find exact max SMB PDU from sess structure BB */
5488 pSMB
->MaxDataCount
= cpu_to_le16(CIFSMaxBufSize
);
5489 pSMB
->MaxSetupCount
= 0;
5493 pSMB
->Reserved2
= 0;
5494 pSMB
->ParameterOffset
= cpu_to_le16(offsetof(
5495 struct smb_com_transaction2_qpi_req
, InformationLevel
) - 4);
5496 pSMB
->DataCount
= 0;
5497 pSMB
->DataOffset
= 0;
5498 pSMB
->SetupCount
= 1;
5499 pSMB
->Reserved3
= 0;
5500 pSMB
->SubCommand
= cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION
);
5501 byte_count
= params
+ 1 /* pad */ ;
5502 pSMB
->TotalParameterCount
= cpu_to_le16(params
);
5503 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
5504 pSMB
->InformationLevel
= cpu_to_le16(SMB_INFO_QUERY_ALL_EAS
);
5505 pSMB
->Reserved4
= 0;
5506 pSMB
->hdr
.smb_buf_length
+= byte_count
;
5507 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
5509 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
5510 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
5512 cFYI(1, ("Send error in QueryAllEAs = %d", rc
));
5517 /* BB also check enough total bytes returned */
5518 /* BB we need to improve the validity checking
5519 of these trans2 responses */
5521 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
5522 if (rc
|| (pSMBr
->ByteCount
< 4)) {
5523 rc
= -EIO
; /* bad smb */
5527 /* check that length of list is not more than bcc */
5528 /* check that each entry does not go beyond length
5530 /* check that each element of each entry does not
5531 go beyond end of list */
5532 /* validate_trans2_offsets() */
5533 /* BB check if start of smb + data_offset > &bcc+ bcc */
5535 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
5536 ea_response_data
= (struct fealist
*)
5537 (((char *) &pSMBr
->hdr
.Protocol
) + data_offset
);
5539 list_len
= le32_to_cpu(ea_response_data
->list_len
);
5540 cFYI(1, ("ea length %d", list_len
));
5541 if (list_len
<= 8) {
5542 cFYI(1, ("empty EA list returned from server"));
5546 /* make sure list_len doesn't go past end of SMB */
5547 end_of_smb
= (char *)pByteArea(&pSMBr
->hdr
) + BCC(&pSMBr
->hdr
);
5548 if ((char *)ea_response_data
+ list_len
> end_of_smb
) {
5549 cFYI(1, ("EA list appears to go beyond SMB"));
5554 /* account for ea list len */
5556 temp_fea
= ea_response_data
->list
;
5557 temp_ptr
= (char *)temp_fea
;
5558 while (list_len
> 0) {
5559 unsigned int name_len
;
5564 /* make sure we can read name_len and value_len */
5566 cFYI(1, ("EA entry goes beyond length of list"));
5571 name_len
= temp_fea
->name_len
;
5572 value_len
= le16_to_cpu(temp_fea
->value_len
);
5573 list_len
-= name_len
+ 1 + value_len
;
5575 cFYI(1, ("EA entry goes beyond length of list"));
5581 if (strncmp(ea_name
, temp_ptr
, name_len
) == 0) {
5582 temp_ptr
+= name_len
+ 1;
5586 if ((size_t)value_len
> buf_size
) {
5590 memcpy(EAData
, temp_ptr
, value_len
);
5594 /* account for prefix user. and trailing null */
5595 rc
+= (5 + 1 + name_len
);
5596 if (rc
< (int) buf_size
) {
5597 memcpy(EAData
, "user.", 5);
5599 memcpy(EAData
, temp_ptr
, name_len
);
5601 /* null terminate name */
5604 } else if (buf_size
== 0) {
5605 /* skip copy - calc size only */
5607 /* stop before overrun buffer */
5612 temp_ptr
+= name_len
+ 1 + value_len
;
5613 temp_fea
= (struct fea
*)temp_ptr
;
5616 /* didn't find the named attribute */
5621 cifs_buf_release(pSMB
);
5629 CIFSSMBSetEA(const int xid
, struct cifsTconInfo
*tcon
, const char *fileName
,
5630 const char *ea_name
, const void *ea_value
,
5631 const __u16 ea_value_len
, const struct nls_table
*nls_codepage
,
5634 struct smb_com_transaction2_spi_req
*pSMB
= NULL
;
5635 struct smb_com_transaction2_spi_rsp
*pSMBr
= NULL
;
5636 struct fealist
*parm_data
;
5639 int bytes_returned
= 0;
5640 __u16 params
, param_offset
, byte_count
, offset
, count
;
5642 cFYI(1, ("In SetEA"));
5644 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
5649 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
5651 cifsConvertToUCS((__le16
*) pSMB
->FileName
, fileName
,
5652 PATH_MAX
, nls_codepage
, remap
);
5653 name_len
++; /* trailing null */
5655 } else { /* BB improve the check for buffer overruns BB */
5656 name_len
= strnlen(fileName
, PATH_MAX
);
5657 name_len
++; /* trailing null */
5658 strncpy(pSMB
->FileName
, fileName
, name_len
);
5661 params
= 6 + name_len
;
5663 /* done calculating parms using name_len of file name,
5664 now use name_len to calculate length of ea name
5665 we are going to create in the inode xattrs */
5666 if (ea_name
== NULL
)
5669 name_len
= strnlen(ea_name
, 255);
5671 count
= sizeof(*parm_data
) + ea_value_len
+ name_len
;
5672 pSMB
->MaxParameterCount
= cpu_to_le16(2);
5673 /* BB find max SMB PDU from sess */
5674 pSMB
->MaxDataCount
= cpu_to_le16(1000);
5675 pSMB
->MaxSetupCount
= 0;
5679 pSMB
->Reserved2
= 0;
5680 param_offset
= offsetof(struct smb_com_transaction2_spi_req
,
5681 InformationLevel
) - 4;
5682 offset
= param_offset
+ params
;
5683 pSMB
->InformationLevel
=
5684 cpu_to_le16(SMB_SET_FILE_EA
);
5687 (struct fealist
*) (((char *) &pSMB
->hdr
.Protocol
) +
5689 pSMB
->ParameterOffset
= cpu_to_le16(param_offset
);
5690 pSMB
->DataOffset
= cpu_to_le16(offset
);
5691 pSMB
->SetupCount
= 1;
5692 pSMB
->Reserved3
= 0;
5693 pSMB
->SubCommand
= cpu_to_le16(TRANS2_SET_PATH_INFORMATION
);
5694 byte_count
= 3 /* pad */ + params
+ count
;
5695 pSMB
->DataCount
= cpu_to_le16(count
);
5696 parm_data
->list_len
= cpu_to_le32(count
);
5697 parm_data
->list
[0].EA_flags
= 0;
5698 /* we checked above that name len is less than 255 */
5699 parm_data
->list
[0].name_len
= (__u8
)name_len
;
5700 /* EA names are always ASCII */
5702 strncpy(parm_data
->list
[0].name
, ea_name
, name_len
);
5703 parm_data
->list
[0].name
[name_len
] = 0;
5704 parm_data
->list
[0].value_len
= cpu_to_le16(ea_value_len
);
5705 /* caller ensures that ea_value_len is less than 64K but
5706 we need to ensure that it fits within the smb */
5708 /*BB add length check to see if it would fit in
5709 negotiated SMB buffer size BB */
5710 /* if (ea_value_len > buffer_size - 512 (enough for header)) */
5712 memcpy(parm_data
->list
[0].name
+name_len
+1,
5713 ea_value
, ea_value_len
);
5715 pSMB
->TotalDataCount
= pSMB
->DataCount
;
5716 pSMB
->ParameterCount
= cpu_to_le16(params
);
5717 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
5718 pSMB
->Reserved4
= 0;
5719 pSMB
->hdr
.smb_buf_length
+= byte_count
;
5720 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
5721 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
5722 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
5724 cFYI(1, ("SetPathInfo (EA) returned %d", rc
));
5726 cifs_buf_release(pSMB
);