4 * Copyright (C) International Business Machines Corp., 2002,2010
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
;
360 server
= ses
->server
;
365 rc
= smb_init(SMB_COM_NEGOTIATE
, 0, NULL
/* no tcon yet */ ,
366 (void **) &pSMB
, (void **) &pSMBr
);
370 /* if any of auth flags (ie not sign or seal) are overriden use them */
371 if (ses
->overrideSecFlg
& (~(CIFSSEC_MUST_SIGN
| CIFSSEC_MUST_SEAL
)))
372 secFlags
= ses
->overrideSecFlg
; /* BB FIXME fix sign flags? */
373 else /* if override flags set only sign/seal OR them with global auth */
374 secFlags
= global_secflags
| ses
->overrideSecFlg
;
376 cFYI(1, "secFlags 0x%x", secFlags
);
378 pSMB
->hdr
.Mid
= GetNextMid(server
);
379 pSMB
->hdr
.Flags2
|= (SMBFLG2_UNICODE
| SMBFLG2_ERR_STATUS
);
381 if ((secFlags
& CIFSSEC_MUST_KRB5
) == CIFSSEC_MUST_KRB5
)
382 pSMB
->hdr
.Flags2
|= SMBFLG2_EXT_SEC
;
383 else if ((secFlags
& CIFSSEC_AUTH_MASK
) == CIFSSEC_MAY_KRB5
) {
384 cFYI(1, "Kerberos only mechanism, enable extended security");
385 pSMB
->hdr
.Flags2
|= SMBFLG2_EXT_SEC
;
387 #ifdef CONFIG_CIFS_EXPERIMENTAL
388 else if ((secFlags
& CIFSSEC_MUST_NTLMSSP
) == CIFSSEC_MUST_NTLMSSP
)
389 pSMB
->hdr
.Flags2
|= SMBFLG2_EXT_SEC
;
390 else if ((secFlags
& CIFSSEC_AUTH_MASK
) == CIFSSEC_MAY_NTLMSSP
) {
391 cFYI(1, "NTLMSSP only mechanism, enable extended security");
392 pSMB
->hdr
.Flags2
|= SMBFLG2_EXT_SEC
;
397 for (i
= 0; i
< CIFS_NUM_PROT
; i
++) {
398 strncpy(pSMB
->DialectsArray
+count
, protocols
[i
].name
, 16);
399 count
+= strlen(protocols
[i
].name
) + 1;
400 /* null at end of source and target buffers anyway */
402 pSMB
->hdr
.smb_buf_length
+= count
;
403 pSMB
->ByteCount
= cpu_to_le16(count
);
405 rc
= SendReceive(xid
, ses
, (struct smb_hdr
*) pSMB
,
406 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
410 server
->dialect
= le16_to_cpu(pSMBr
->DialectIndex
);
411 cFYI(1, "Dialect: %d", server
->dialect
);
412 /* Check wct = 1 error case */
413 if ((pSMBr
->hdr
.WordCount
< 13) || (server
->dialect
== BAD_PROT
)) {
414 /* core returns wct = 1, but we do not ask for core - otherwise
415 small wct just comes when dialect index is -1 indicating we
416 could not negotiate a common dialect */
419 #ifdef CONFIG_CIFS_WEAK_PW_HASH
420 } else if ((pSMBr
->hdr
.WordCount
== 13)
421 && ((server
->dialect
== LANMAN_PROT
)
422 || (server
->dialect
== LANMAN2_PROT
))) {
424 struct lanman_neg_rsp
*rsp
= (struct lanman_neg_rsp
*)pSMBr
;
426 if ((secFlags
& CIFSSEC_MAY_LANMAN
) ||
427 (secFlags
& CIFSSEC_MAY_PLNTXT
))
428 server
->secType
= LANMAN
;
430 cERROR(1, "mount failed weak security disabled"
431 " in /proc/fs/cifs/SecurityFlags");
435 server
->secMode
= (__u8
)le16_to_cpu(rsp
->SecurityMode
);
436 server
->maxReq
= le16_to_cpu(rsp
->MaxMpxCount
);
437 server
->maxBuf
= min((__u32
)le16_to_cpu(rsp
->MaxBufSize
),
438 (__u32
)CIFSMaxBufSize
+ MAX_CIFS_HDR_SIZE
);
439 server
->max_vcs
= le16_to_cpu(rsp
->MaxNumberVcs
);
440 GETU32(server
->sessid
) = le32_to_cpu(rsp
->SessionKey
);
441 /* even though we do not use raw we might as well set this
442 accurately, in case we ever find a need for it */
443 if ((le16_to_cpu(rsp
->RawMode
) & RAW_ENABLE
) == RAW_ENABLE
) {
444 server
->max_rw
= 0xFF00;
445 server
->capabilities
= CAP_MPX_MODE
| CAP_RAW_MODE
;
447 server
->max_rw
= 0;/* do not need to use raw anyway */
448 server
->capabilities
= CAP_MPX_MODE
;
450 tmp
= (__s16
)le16_to_cpu(rsp
->ServerTimeZone
);
452 /* OS/2 often does not set timezone therefore
453 * we must use server time to calc time zone.
454 * Could deviate slightly from the right zone.
455 * Smallest defined timezone difference is 15 minutes
456 * (i.e. Nepal). Rounding up/down is done to match
459 int val
, seconds
, remain
, result
;
460 struct timespec ts
, utc
;
462 ts
= cnvrtDosUnixTm(rsp
->SrvTime
.Date
,
463 rsp
->SrvTime
.Time
, 0);
464 cFYI(1, "SrvTime %d sec since 1970 (utc: %d) diff: %d",
465 (int)ts
.tv_sec
, (int)utc
.tv_sec
,
466 (int)(utc
.tv_sec
- ts
.tv_sec
));
467 val
= (int)(utc
.tv_sec
- ts
.tv_sec
);
469 result
= (seconds
/ MIN_TZ_ADJ
) * MIN_TZ_ADJ
;
470 remain
= seconds
% MIN_TZ_ADJ
;
471 if (remain
>= (MIN_TZ_ADJ
/ 2))
472 result
+= MIN_TZ_ADJ
;
475 server
->timeAdj
= result
;
477 server
->timeAdj
= (int)tmp
;
478 server
->timeAdj
*= 60; /* also in seconds */
480 cFYI(1, "server->timeAdj: %d seconds", server
->timeAdj
);
483 /* BB get server time for time conversions and add
484 code to use it and timezone since this is not UTC */
486 if (rsp
->EncryptionKeyLength
==
487 cpu_to_le16(CIFS_CRYPTO_KEY_SIZE
)) {
488 memcpy(server
->cryptKey
, rsp
->EncryptionKey
,
489 CIFS_CRYPTO_KEY_SIZE
);
490 } else if (server
->secMode
& SECMODE_PW_ENCRYPT
) {
491 rc
= -EIO
; /* need cryptkey unless plain text */
495 cFYI(1, "LANMAN negotiated");
496 /* we will not end up setting signing flags - as no signing
497 was in LANMAN and server did not return the flags on */
499 #else /* weak security disabled */
500 } else if (pSMBr
->hdr
.WordCount
== 13) {
501 cERROR(1, "mount failed, cifs module not built "
502 "with CIFS_WEAK_PW_HASH support");
504 #endif /* WEAK_PW_HASH */
506 } else if (pSMBr
->hdr
.WordCount
!= 17) {
511 /* else wct == 17 NTLM */
512 server
->secMode
= pSMBr
->SecurityMode
;
513 if ((server
->secMode
& SECMODE_USER
) == 0)
514 cFYI(1, "share mode security");
516 if ((server
->secMode
& SECMODE_PW_ENCRYPT
) == 0)
517 #ifdef CONFIG_CIFS_WEAK_PW_HASH
518 if ((secFlags
& CIFSSEC_MAY_PLNTXT
) == 0)
519 #endif /* CIFS_WEAK_PW_HASH */
520 cERROR(1, "Server requests plain text password"
521 " but client support disabled");
523 if ((secFlags
& CIFSSEC_MUST_NTLMV2
) == CIFSSEC_MUST_NTLMV2
)
524 server
->secType
= NTLMv2
;
525 else if (secFlags
& CIFSSEC_MAY_NTLM
)
526 server
->secType
= NTLM
;
527 else if (secFlags
& CIFSSEC_MAY_NTLMV2
)
528 server
->secType
= NTLMv2
;
529 else if (secFlags
& CIFSSEC_MAY_KRB5
)
530 server
->secType
= Kerberos
;
531 else if (secFlags
& CIFSSEC_MAY_NTLMSSP
)
532 server
->secType
= RawNTLMSSP
;
533 else if (secFlags
& CIFSSEC_MAY_LANMAN
)
534 server
->secType
= LANMAN
;
535 /* #ifdef CONFIG_CIFS_EXPERIMENTAL
536 else if (secFlags & CIFSSEC_MAY_PLNTXT)
541 cERROR(1, "Invalid security type");
544 /* else ... any others ...? */
546 /* one byte, so no need to convert this or EncryptionKeyLen from
548 server
->maxReq
= le16_to_cpu(pSMBr
->MaxMpxCount
);
549 /* probably no need to store and check maxvcs */
550 server
->maxBuf
= min(le32_to_cpu(pSMBr
->MaxBufferSize
),
551 (__u32
) CIFSMaxBufSize
+ MAX_CIFS_HDR_SIZE
);
552 server
->max_rw
= le32_to_cpu(pSMBr
->MaxRawSize
);
553 cFYI(DBG2
, "Max buf = %d", ses
->server
->maxBuf
);
554 GETU32(ses
->server
->sessid
) = le32_to_cpu(pSMBr
->SessionKey
);
555 server
->capabilities
= le32_to_cpu(pSMBr
->Capabilities
);
556 server
->timeAdj
= (int)(__s16
)le16_to_cpu(pSMBr
->ServerTimeZone
);
557 server
->timeAdj
*= 60;
558 if (pSMBr
->EncryptionKeyLength
== CIFS_CRYPTO_KEY_SIZE
) {
559 memcpy(server
->cryptKey
, pSMBr
->u
.EncryptionKey
,
560 CIFS_CRYPTO_KEY_SIZE
);
561 } else if ((pSMBr
->hdr
.Flags2
& SMBFLG2_EXT_SEC
)
562 && (pSMBr
->EncryptionKeyLength
== 0)) {
563 /* decode security blob */
564 } else if (server
->secMode
& SECMODE_PW_ENCRYPT
) {
565 rc
= -EIO
; /* no crypt key only if plain text pwd */
569 /* BB might be helpful to save off the domain of server here */
571 if ((pSMBr
->hdr
.Flags2
& SMBFLG2_EXT_SEC
) &&
572 (server
->capabilities
& CAP_EXTENDED_SECURITY
)) {
573 count
= pSMBr
->ByteCount
;
578 read_lock(&cifs_tcp_ses_lock
);
579 if (server
->srv_count
> 1) {
580 read_unlock(&cifs_tcp_ses_lock
);
581 if (memcmp(server
->server_GUID
,
582 pSMBr
->u
.extended_response
.
584 cFYI(1, "server UID changed");
585 memcpy(server
->server_GUID
,
586 pSMBr
->u
.extended_response
.GUID
,
590 read_unlock(&cifs_tcp_ses_lock
);
591 memcpy(server
->server_GUID
,
592 pSMBr
->u
.extended_response
.GUID
, 16);
596 server
->secType
= RawNTLMSSP
;
598 rc
= decode_negTokenInit(pSMBr
->u
.extended_response
.
608 server
->capabilities
&= ~CAP_EXTENDED_SECURITY
;
610 #ifdef CONFIG_CIFS_WEAK_PW_HASH
613 if ((secFlags
& CIFSSEC_MAY_SIGN
) == 0) {
614 /* MUST_SIGN already includes the MAY_SIGN FLAG
615 so if this is zero it means that signing is disabled */
616 cFYI(1, "Signing disabled");
617 if (server
->secMode
& SECMODE_SIGN_REQUIRED
) {
618 cERROR(1, "Server requires "
619 "packet signing to be enabled in "
620 "/proc/fs/cifs/SecurityFlags.");
624 ~(SECMODE_SIGN_ENABLED
| SECMODE_SIGN_REQUIRED
);
625 } else if ((secFlags
& CIFSSEC_MUST_SIGN
) == CIFSSEC_MUST_SIGN
) {
626 /* signing required */
627 cFYI(1, "Must sign - secFlags 0x%x", secFlags
);
628 if ((server
->secMode
&
629 (SECMODE_SIGN_ENABLED
| SECMODE_SIGN_REQUIRED
)) == 0) {
630 cERROR(1, "signing required but server lacks support");
633 server
->secMode
|= SECMODE_SIGN_REQUIRED
;
635 /* signing optional ie CIFSSEC_MAY_SIGN */
636 if ((server
->secMode
& SECMODE_SIGN_REQUIRED
) == 0)
638 ~(SECMODE_SIGN_ENABLED
| SECMODE_SIGN_REQUIRED
);
642 cifs_buf_release(pSMB
);
644 cFYI(1, "negprot rc %d", rc
);
649 CIFSSMBTDis(const int xid
, struct cifsTconInfo
*tcon
)
651 struct smb_hdr
*smb_buffer
;
654 cFYI(1, "In tree disconnect");
656 /* BB: do we need to check this? These should never be NULL. */
657 if ((tcon
->ses
== NULL
) || (tcon
->ses
->server
== NULL
))
661 * No need to return error on this operation if tid invalidated and
662 * closed on server already e.g. due to tcp session crashing. Also,
663 * the tcon is no longer on the list, so no need to take lock before
666 if ((tcon
->need_reconnect
) || (tcon
->ses
->need_reconnect
))
669 rc
= small_smb_init(SMB_COM_TREE_DISCONNECT
, 0, tcon
,
670 (void **)&smb_buffer
);
674 rc
= SendReceiveNoRsp(xid
, tcon
->ses
, smb_buffer
, 0);
676 cFYI(1, "Tree disconnect failed %d", rc
);
678 /* No need to return error on this operation if tid invalidated and
679 closed on server already e.g. due to tcp session crashing */
687 CIFSSMBLogoff(const int xid
, struct cifsSesInfo
*ses
)
689 LOGOFF_ANDX_REQ
*pSMB
;
692 cFYI(1, "In SMBLogoff for session disconnect");
695 * BB: do we need to check validity of ses and server? They should
696 * always be valid since we have an active reference. If not, that
697 * should probably be a BUG()
699 if (!ses
|| !ses
->server
)
702 mutex_lock(&ses
->session_mutex
);
703 if (ses
->need_reconnect
)
704 goto session_already_dead
; /* no need to send SMBlogoff if uid
705 already closed due to reconnect */
706 rc
= small_smb_init(SMB_COM_LOGOFF_ANDX
, 2, NULL
, (void **)&pSMB
);
708 mutex_unlock(&ses
->session_mutex
);
712 pSMB
->hdr
.Mid
= GetNextMid(ses
->server
);
714 if (ses
->server
->secMode
&
715 (SECMODE_SIGN_REQUIRED
| SECMODE_SIGN_ENABLED
))
716 pSMB
->hdr
.Flags2
|= SMBFLG2_SECURITY_SIGNATURE
;
718 pSMB
->hdr
.Uid
= ses
->Suid
;
720 pSMB
->AndXCommand
= 0xFF;
721 rc
= SendReceiveNoRsp(xid
, ses
, (struct smb_hdr
*) pSMB
, 0);
722 session_already_dead
:
723 mutex_unlock(&ses
->session_mutex
);
725 /* if session dead then we do not need to do ulogoff,
726 since server closed smb session, no sense reporting
734 CIFSPOSIXDelFile(const int xid
, struct cifsTconInfo
*tcon
, const char *fileName
,
735 __u16 type
, const struct nls_table
*nls_codepage
, int remap
)
737 TRANSACTION2_SPI_REQ
*pSMB
= NULL
;
738 TRANSACTION2_SPI_RSP
*pSMBr
= NULL
;
739 struct unlink_psx_rq
*pRqD
;
742 int bytes_returned
= 0;
743 __u16 params
, param_offset
, offset
, byte_count
;
745 cFYI(1, "In POSIX delete");
747 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
752 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
754 cifsConvertToUCS((__le16
*) pSMB
->FileName
, fileName
,
755 PATH_MAX
, nls_codepage
, remap
);
756 name_len
++; /* trailing null */
758 } else { /* BB add path length overrun check */
759 name_len
= strnlen(fileName
, PATH_MAX
);
760 name_len
++; /* trailing null */
761 strncpy(pSMB
->FileName
, fileName
, name_len
);
764 params
= 6 + name_len
;
765 pSMB
->MaxParameterCount
= cpu_to_le16(2);
766 pSMB
->MaxDataCount
= 0; /* BB double check this with jra */
767 pSMB
->MaxSetupCount
= 0;
772 param_offset
= offsetof(struct smb_com_transaction2_spi_req
,
773 InformationLevel
) - 4;
774 offset
= param_offset
+ params
;
776 /* Setup pointer to Request Data (inode type) */
777 pRqD
= (struct unlink_psx_rq
*)(((char *)&pSMB
->hdr
.Protocol
) + offset
);
778 pRqD
->type
= cpu_to_le16(type
);
779 pSMB
->ParameterOffset
= cpu_to_le16(param_offset
);
780 pSMB
->DataOffset
= cpu_to_le16(offset
);
781 pSMB
->SetupCount
= 1;
783 pSMB
->SubCommand
= cpu_to_le16(TRANS2_SET_PATH_INFORMATION
);
784 byte_count
= 3 /* pad */ + params
+ sizeof(struct unlink_psx_rq
);
786 pSMB
->DataCount
= cpu_to_le16(sizeof(struct unlink_psx_rq
));
787 pSMB
->TotalDataCount
= cpu_to_le16(sizeof(struct unlink_psx_rq
));
788 pSMB
->ParameterCount
= cpu_to_le16(params
);
789 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
790 pSMB
->InformationLevel
= cpu_to_le16(SMB_POSIX_UNLINK
);
792 pSMB
->hdr
.smb_buf_length
+= byte_count
;
793 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
794 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
795 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
797 cFYI(1, "Posix delete returned %d", rc
);
798 cifs_buf_release(pSMB
);
800 cifs_stats_inc(&tcon
->num_deletes
);
809 CIFSSMBDelFile(const int xid
, struct cifsTconInfo
*tcon
, const char *fileName
,
810 const struct nls_table
*nls_codepage
, int remap
)
812 DELETE_FILE_REQ
*pSMB
= NULL
;
813 DELETE_FILE_RSP
*pSMBr
= NULL
;
819 rc
= smb_init(SMB_COM_DELETE
, 1, tcon
, (void **) &pSMB
,
824 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
826 cifsConvertToUCS((__le16
*) pSMB
->fileName
, fileName
,
827 PATH_MAX
, nls_codepage
, remap
);
828 name_len
++; /* trailing null */
830 } else { /* BB improve check for buffer overruns BB */
831 name_len
= strnlen(fileName
, PATH_MAX
);
832 name_len
++; /* trailing null */
833 strncpy(pSMB
->fileName
, fileName
, name_len
);
835 pSMB
->SearchAttributes
=
836 cpu_to_le16(ATTR_READONLY
| ATTR_HIDDEN
| ATTR_SYSTEM
);
837 pSMB
->BufferFormat
= 0x04;
838 pSMB
->hdr
.smb_buf_length
+= name_len
+ 1;
839 pSMB
->ByteCount
= cpu_to_le16(name_len
+ 1);
840 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
841 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
842 cifs_stats_inc(&tcon
->num_deletes
);
844 cFYI(1, "Error in RMFile = %d", rc
);
846 cifs_buf_release(pSMB
);
854 CIFSSMBRmDir(const int xid
, struct cifsTconInfo
*tcon
, const char *dirName
,
855 const struct nls_table
*nls_codepage
, int remap
)
857 DELETE_DIRECTORY_REQ
*pSMB
= NULL
;
858 DELETE_DIRECTORY_RSP
*pSMBr
= NULL
;
863 cFYI(1, "In CIFSSMBRmDir");
865 rc
= smb_init(SMB_COM_DELETE_DIRECTORY
, 0, tcon
, (void **) &pSMB
,
870 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
871 name_len
= cifsConvertToUCS((__le16
*) pSMB
->DirName
, dirName
,
872 PATH_MAX
, nls_codepage
, remap
);
873 name_len
++; /* trailing null */
875 } else { /* BB improve check for buffer overruns BB */
876 name_len
= strnlen(dirName
, PATH_MAX
);
877 name_len
++; /* trailing null */
878 strncpy(pSMB
->DirName
, dirName
, name_len
);
881 pSMB
->BufferFormat
= 0x04;
882 pSMB
->hdr
.smb_buf_length
+= name_len
+ 1;
883 pSMB
->ByteCount
= cpu_to_le16(name_len
+ 1);
884 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
885 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
886 cifs_stats_inc(&tcon
->num_rmdirs
);
888 cFYI(1, "Error in RMDir = %d", rc
);
890 cifs_buf_release(pSMB
);
897 CIFSSMBMkDir(const int xid
, struct cifsTconInfo
*tcon
,
898 const char *name
, const struct nls_table
*nls_codepage
, int remap
)
901 CREATE_DIRECTORY_REQ
*pSMB
= NULL
;
902 CREATE_DIRECTORY_RSP
*pSMBr
= NULL
;
906 cFYI(1, "In CIFSSMBMkDir");
908 rc
= smb_init(SMB_COM_CREATE_DIRECTORY
, 0, tcon
, (void **) &pSMB
,
913 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
914 name_len
= cifsConvertToUCS((__le16
*) pSMB
->DirName
, name
,
915 PATH_MAX
, nls_codepage
, remap
);
916 name_len
++; /* trailing null */
918 } else { /* BB improve check for buffer overruns BB */
919 name_len
= strnlen(name
, PATH_MAX
);
920 name_len
++; /* trailing null */
921 strncpy(pSMB
->DirName
, name
, name_len
);
924 pSMB
->BufferFormat
= 0x04;
925 pSMB
->hdr
.smb_buf_length
+= name_len
+ 1;
926 pSMB
->ByteCount
= cpu_to_le16(name_len
+ 1);
927 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
928 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
929 cifs_stats_inc(&tcon
->num_mkdirs
);
931 cFYI(1, "Error in Mkdir = %d", rc
);
933 cifs_buf_release(pSMB
);
940 CIFSPOSIXCreate(const int xid
, struct cifsTconInfo
*tcon
, __u32 posix_flags
,
941 __u64 mode
, __u16
*netfid
, FILE_UNIX_BASIC_INFO
*pRetData
,
942 __u32
*pOplock
, const char *name
,
943 const struct nls_table
*nls_codepage
, int remap
)
945 TRANSACTION2_SPI_REQ
*pSMB
= NULL
;
946 TRANSACTION2_SPI_RSP
*pSMBr
= NULL
;
949 int bytes_returned
= 0;
950 __u16 params
, param_offset
, offset
, byte_count
, count
;
952 OPEN_PSX_RSP
*psx_rsp
;
954 cFYI(1, "In POSIX Create");
956 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
961 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
963 cifsConvertToUCS((__le16
*) pSMB
->FileName
, name
,
964 PATH_MAX
, nls_codepage
, remap
);
965 name_len
++; /* trailing null */
967 } else { /* BB improve the check for buffer overruns BB */
968 name_len
= strnlen(name
, PATH_MAX
);
969 name_len
++; /* trailing null */
970 strncpy(pSMB
->FileName
, name
, name_len
);
973 params
= 6 + name_len
;
974 count
= sizeof(OPEN_PSX_REQ
);
975 pSMB
->MaxParameterCount
= cpu_to_le16(2);
976 pSMB
->MaxDataCount
= cpu_to_le16(1000); /* large enough */
977 pSMB
->MaxSetupCount
= 0;
982 param_offset
= offsetof(struct smb_com_transaction2_spi_req
,
983 InformationLevel
) - 4;
984 offset
= param_offset
+ params
;
985 pdata
= (OPEN_PSX_REQ
*)(((char *)&pSMB
->hdr
.Protocol
) + offset
);
986 pdata
->Level
= cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC
);
987 pdata
->Permissions
= cpu_to_le64(mode
);
988 pdata
->PosixOpenFlags
= cpu_to_le32(posix_flags
);
989 pdata
->OpenFlags
= cpu_to_le32(*pOplock
);
990 pSMB
->ParameterOffset
= cpu_to_le16(param_offset
);
991 pSMB
->DataOffset
= cpu_to_le16(offset
);
992 pSMB
->SetupCount
= 1;
994 pSMB
->SubCommand
= cpu_to_le16(TRANS2_SET_PATH_INFORMATION
);
995 byte_count
= 3 /* pad */ + params
+ count
;
997 pSMB
->DataCount
= cpu_to_le16(count
);
998 pSMB
->ParameterCount
= cpu_to_le16(params
);
999 pSMB
->TotalDataCount
= pSMB
->DataCount
;
1000 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
1001 pSMB
->InformationLevel
= cpu_to_le16(SMB_POSIX_OPEN
);
1002 pSMB
->Reserved4
= 0;
1003 pSMB
->hdr
.smb_buf_length
+= byte_count
;
1004 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
1005 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
1006 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
1008 cFYI(1, "Posix create returned %d", rc
);
1009 goto psx_create_err
;
1012 cFYI(1, "copying inode info");
1013 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
1015 if (rc
|| (pSMBr
->ByteCount
< sizeof(OPEN_PSX_RSP
))) {
1016 rc
= -EIO
; /* bad smb */
1017 goto psx_create_err
;
1020 /* copy return information to pRetData */
1021 psx_rsp
= (OPEN_PSX_RSP
*)((char *) &pSMBr
->hdr
.Protocol
1022 + le16_to_cpu(pSMBr
->t2
.DataOffset
));
1024 *pOplock
= le16_to_cpu(psx_rsp
->OplockFlags
);
1026 *netfid
= psx_rsp
->Fid
; /* cifs fid stays in le */
1027 /* Let caller know file was created so we can set the mode. */
1028 /* Do we care about the CreateAction in any other cases? */
1029 if (cpu_to_le32(FILE_CREATE
) == psx_rsp
->CreateAction
)
1030 *pOplock
|= CIFS_CREATE_ACTION
;
1031 /* check to make sure response data is there */
1032 if (psx_rsp
->ReturnedLevel
!= cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC
)) {
1033 pRetData
->Type
= cpu_to_le32(-1); /* unknown */
1034 cFYI(DBG2
, "unknown type");
1036 if (pSMBr
->ByteCount
< sizeof(OPEN_PSX_RSP
)
1037 + sizeof(FILE_UNIX_BASIC_INFO
)) {
1038 cERROR(1, "Open response data too small");
1039 pRetData
->Type
= cpu_to_le32(-1);
1040 goto psx_create_err
;
1042 memcpy((char *) pRetData
,
1043 (char *)psx_rsp
+ sizeof(OPEN_PSX_RSP
),
1044 sizeof(FILE_UNIX_BASIC_INFO
));
1048 cifs_buf_release(pSMB
);
1050 if (posix_flags
& SMB_O_DIRECTORY
)
1051 cifs_stats_inc(&tcon
->num_posixmkdirs
);
1053 cifs_stats_inc(&tcon
->num_posixopens
);
1061 static __u16
convert_disposition(int disposition
)
1065 switch (disposition
) {
1066 case FILE_SUPERSEDE
:
1067 ofun
= SMBOPEN_OCREATE
| SMBOPEN_OTRUNC
;
1070 ofun
= SMBOPEN_OAPPEND
;
1073 ofun
= SMBOPEN_OCREATE
;
1076 ofun
= SMBOPEN_OCREATE
| SMBOPEN_OAPPEND
;
1078 case FILE_OVERWRITE
:
1079 ofun
= SMBOPEN_OTRUNC
;
1081 case FILE_OVERWRITE_IF
:
1082 ofun
= SMBOPEN_OCREATE
| SMBOPEN_OTRUNC
;
1085 cFYI(1, "unknown disposition %d", disposition
);
1086 ofun
= SMBOPEN_OAPPEND
; /* regular open */
1092 access_flags_to_smbopen_mode(const int access_flags
)
1094 int masked_flags
= access_flags
& (GENERIC_READ
| GENERIC_WRITE
);
1096 if (masked_flags
== GENERIC_READ
)
1097 return SMBOPEN_READ
;
1098 else if (masked_flags
== GENERIC_WRITE
)
1099 return SMBOPEN_WRITE
;
1101 /* just go for read/write */
1102 return SMBOPEN_READWRITE
;
1106 SMBLegacyOpen(const int xid
, struct cifsTconInfo
*tcon
,
1107 const char *fileName
, const int openDisposition
,
1108 const int access_flags
, const int create_options
, __u16
*netfid
,
1109 int *pOplock
, FILE_ALL_INFO
*pfile_info
,
1110 const struct nls_table
*nls_codepage
, int remap
)
1113 OPENX_REQ
*pSMB
= NULL
;
1114 OPENX_RSP
*pSMBr
= NULL
;
1120 rc
= smb_init(SMB_COM_OPEN_ANDX
, 15, tcon
, (void **) &pSMB
,
1125 pSMB
->AndXCommand
= 0xFF; /* none */
1127 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
1128 count
= 1; /* account for one byte pad to word boundary */
1130 cifsConvertToUCS((__le16
*) (pSMB
->fileName
+ 1),
1131 fileName
, PATH_MAX
, nls_codepage
, remap
);
1132 name_len
++; /* trailing null */
1134 } else { /* BB improve check for buffer overruns BB */
1135 count
= 0; /* no pad */
1136 name_len
= strnlen(fileName
, PATH_MAX
);
1137 name_len
++; /* trailing null */
1138 strncpy(pSMB
->fileName
, fileName
, name_len
);
1140 if (*pOplock
& REQ_OPLOCK
)
1141 pSMB
->OpenFlags
= cpu_to_le16(REQ_OPLOCK
);
1142 else if (*pOplock
& REQ_BATCHOPLOCK
)
1143 pSMB
->OpenFlags
= cpu_to_le16(REQ_BATCHOPLOCK
);
1145 pSMB
->OpenFlags
|= cpu_to_le16(REQ_MORE_INFO
);
1146 pSMB
->Mode
= cpu_to_le16(access_flags_to_smbopen_mode(access_flags
));
1147 pSMB
->Mode
|= cpu_to_le16(0x40); /* deny none */
1148 /* set file as system file if special file such
1149 as fifo and server expecting SFU style and
1150 no Unix extensions */
1152 if (create_options
& CREATE_OPTION_SPECIAL
)
1153 pSMB
->FileAttributes
= cpu_to_le16(ATTR_SYSTEM
);
1154 else /* BB FIXME BB */
1155 pSMB
->FileAttributes
= cpu_to_le16(0/*ATTR_NORMAL*/);
1157 if (create_options
& CREATE_OPTION_READONLY
)
1158 pSMB
->FileAttributes
|= cpu_to_le16(ATTR_READONLY
);
1161 /* pSMB->CreateOptions = cpu_to_le32(create_options &
1162 CREATE_OPTIONS_MASK); */
1163 /* BB FIXME END BB */
1165 pSMB
->Sattr
= cpu_to_le16(ATTR_HIDDEN
| ATTR_SYSTEM
| ATTR_DIRECTORY
);
1166 pSMB
->OpenFunction
= cpu_to_le16(convert_disposition(openDisposition
));
1168 pSMB
->hdr
.smb_buf_length
+= count
;
1170 pSMB
->ByteCount
= cpu_to_le16(count
);
1171 /* long_op set to 1 to allow for oplock break timeouts */
1172 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
1173 (struct smb_hdr
*)pSMBr
, &bytes_returned
, CIFS_LONG_OP
);
1174 cifs_stats_inc(&tcon
->num_opens
);
1176 cFYI(1, "Error in Open = %d", rc
);
1178 /* BB verify if wct == 15 */
1180 /* *pOplock = pSMBr->OplockLevel; */ /* BB take from action field*/
1182 *netfid
= pSMBr
->Fid
; /* cifs fid stays in le */
1183 /* Let caller know file was created so we can set the mode. */
1184 /* Do we care about the CreateAction in any other cases? */
1186 /* if (cpu_to_le32(FILE_CREATE) == pSMBr->CreateAction)
1187 *pOplock |= CIFS_CREATE_ACTION; */
1191 pfile_info
->CreationTime
= 0; /* BB convert CreateTime*/
1192 pfile_info
->LastAccessTime
= 0; /* BB fixme */
1193 pfile_info
->LastWriteTime
= 0; /* BB fixme */
1194 pfile_info
->ChangeTime
= 0; /* BB fixme */
1195 pfile_info
->Attributes
=
1196 cpu_to_le32(le16_to_cpu(pSMBr
->FileAttributes
));
1197 /* the file_info buf is endian converted by caller */
1198 pfile_info
->AllocationSize
=
1199 cpu_to_le64(le32_to_cpu(pSMBr
->EndOfFile
));
1200 pfile_info
->EndOfFile
= pfile_info
->AllocationSize
;
1201 pfile_info
->NumberOfLinks
= cpu_to_le32(1);
1202 pfile_info
->DeletePending
= 0;
1206 cifs_buf_release(pSMB
);
1213 CIFSSMBOpen(const int xid
, struct cifsTconInfo
*tcon
,
1214 const char *fileName
, const int openDisposition
,
1215 const int access_flags
, const int create_options
, __u16
*netfid
,
1216 int *pOplock
, FILE_ALL_INFO
*pfile_info
,
1217 const struct nls_table
*nls_codepage
, int remap
)
1220 OPEN_REQ
*pSMB
= NULL
;
1221 OPEN_RSP
*pSMBr
= NULL
;
1227 rc
= smb_init(SMB_COM_NT_CREATE_ANDX
, 24, tcon
, (void **) &pSMB
,
1232 pSMB
->AndXCommand
= 0xFF; /* none */
1234 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
1235 count
= 1; /* account for one byte pad to word boundary */
1237 cifsConvertToUCS((__le16
*) (pSMB
->fileName
+ 1),
1238 fileName
, PATH_MAX
, nls_codepage
, remap
);
1239 name_len
++; /* trailing null */
1241 pSMB
->NameLength
= cpu_to_le16(name_len
);
1242 } else { /* BB improve check for buffer overruns BB */
1243 count
= 0; /* no pad */
1244 name_len
= strnlen(fileName
, PATH_MAX
);
1245 name_len
++; /* trailing null */
1246 pSMB
->NameLength
= cpu_to_le16(name_len
);
1247 strncpy(pSMB
->fileName
, fileName
, name_len
);
1249 if (*pOplock
& REQ_OPLOCK
)
1250 pSMB
->OpenFlags
= cpu_to_le32(REQ_OPLOCK
);
1251 else if (*pOplock
& REQ_BATCHOPLOCK
)
1252 pSMB
->OpenFlags
= cpu_to_le32(REQ_BATCHOPLOCK
);
1253 pSMB
->DesiredAccess
= cpu_to_le32(access_flags
);
1254 pSMB
->AllocationSize
= 0;
1255 /* set file as system file if special file such
1256 as fifo and server expecting SFU style and
1257 no Unix extensions */
1258 if (create_options
& CREATE_OPTION_SPECIAL
)
1259 pSMB
->FileAttributes
= cpu_to_le32(ATTR_SYSTEM
);
1261 pSMB
->FileAttributes
= cpu_to_le32(ATTR_NORMAL
);
1263 /* XP does not handle ATTR_POSIX_SEMANTICS */
1264 /* but it helps speed up case sensitive checks for other
1265 servers such as Samba */
1266 if (tcon
->ses
->capabilities
& CAP_UNIX
)
1267 pSMB
->FileAttributes
|= cpu_to_le32(ATTR_POSIX_SEMANTICS
);
1269 if (create_options
& CREATE_OPTION_READONLY
)
1270 pSMB
->FileAttributes
|= cpu_to_le32(ATTR_READONLY
);
1272 pSMB
->ShareAccess
= cpu_to_le32(FILE_SHARE_ALL
);
1273 pSMB
->CreateDisposition
= cpu_to_le32(openDisposition
);
1274 pSMB
->CreateOptions
= cpu_to_le32(create_options
& CREATE_OPTIONS_MASK
);
1275 /* BB Expirement with various impersonation levels and verify */
1276 pSMB
->ImpersonationLevel
= cpu_to_le32(SECURITY_IMPERSONATION
);
1277 pSMB
->SecurityFlags
=
1278 SECURITY_CONTEXT_TRACKING
| SECURITY_EFFECTIVE_ONLY
;
1281 pSMB
->hdr
.smb_buf_length
+= count
;
1283 pSMB
->ByteCount
= cpu_to_le16(count
);
1284 /* long_op set to 1 to allow for oplock break timeouts */
1285 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
1286 (struct smb_hdr
*)pSMBr
, &bytes_returned
, CIFS_LONG_OP
);
1287 cifs_stats_inc(&tcon
->num_opens
);
1289 cFYI(1, "Error in Open = %d", rc
);
1291 *pOplock
= pSMBr
->OplockLevel
; /* 1 byte no need to le_to_cpu */
1292 *netfid
= pSMBr
->Fid
; /* cifs fid stays in le */
1293 /* Let caller know file was created so we can set the mode. */
1294 /* Do we care about the CreateAction in any other cases? */
1295 if (cpu_to_le32(FILE_CREATE
) == pSMBr
->CreateAction
)
1296 *pOplock
|= CIFS_CREATE_ACTION
;
1298 memcpy((char *)pfile_info
, (char *)&pSMBr
->CreationTime
,
1299 36 /* CreationTime to Attributes */);
1300 /* the file_info buf is endian converted by caller */
1301 pfile_info
->AllocationSize
= pSMBr
->AllocationSize
;
1302 pfile_info
->EndOfFile
= pSMBr
->EndOfFile
;
1303 pfile_info
->NumberOfLinks
= cpu_to_le32(1);
1304 pfile_info
->DeletePending
= 0;
1308 cifs_buf_release(pSMB
);
1315 CIFSSMBRead(const int xid
, struct cifsTconInfo
*tcon
, const int netfid
,
1316 const unsigned int count
, const __u64 lseek
, unsigned int *nbytes
,
1317 char **buf
, int *pbuf_type
)
1320 READ_REQ
*pSMB
= NULL
;
1321 READ_RSP
*pSMBr
= NULL
;
1322 char *pReadData
= NULL
;
1324 int resp_buf_type
= 0;
1327 cFYI(1, "Reading %d bytes on fid %d", count
, netfid
);
1328 if (tcon
->ses
->capabilities
& CAP_LARGE_FILES
)
1331 wct
= 10; /* old style read */
1332 if ((lseek
>> 32) > 0) {
1333 /* can not handle this big offset for old */
1339 rc
= small_smb_init(SMB_COM_READ_ANDX
, wct
, tcon
, (void **) &pSMB
);
1343 /* tcon and ses pointer are checked in smb_init */
1344 if (tcon
->ses
->server
== NULL
)
1345 return -ECONNABORTED
;
1347 pSMB
->AndXCommand
= 0xFF; /* none */
1349 pSMB
->OffsetLow
= cpu_to_le32(lseek
& 0xFFFFFFFF);
1351 pSMB
->OffsetHigh
= cpu_to_le32(lseek
>> 32);
1353 pSMB
->Remaining
= 0;
1354 pSMB
->MaxCount
= cpu_to_le16(count
& 0xFFFF);
1355 pSMB
->MaxCountHigh
= cpu_to_le32(count
>> 16);
1357 pSMB
->ByteCount
= 0; /* no need to do le conversion since 0 */
1359 /* old style read */
1360 struct smb_com_readx_req
*pSMBW
=
1361 (struct smb_com_readx_req
*)pSMB
;
1362 pSMBW
->ByteCount
= 0;
1365 iov
[0].iov_base
= (char *)pSMB
;
1366 iov
[0].iov_len
= pSMB
->hdr
.smb_buf_length
+ 4;
1367 rc
= SendReceive2(xid
, tcon
->ses
, iov
, 1 /* num iovecs */,
1368 &resp_buf_type
, CIFS_STD_OP
| CIFS_LOG_ERROR
);
1369 cifs_stats_inc(&tcon
->num_reads
);
1370 pSMBr
= (READ_RSP
*)iov
[0].iov_base
;
1372 cERROR(1, "Send error in read = %d", rc
);
1374 int data_length
= le16_to_cpu(pSMBr
->DataLengthHigh
);
1375 data_length
= data_length
<< 16;
1376 data_length
+= le16_to_cpu(pSMBr
->DataLength
);
1377 *nbytes
= data_length
;
1379 /*check that DataLength would not go beyond end of SMB */
1380 if ((data_length
> CIFSMaxBufSize
)
1381 || (data_length
> count
)) {
1382 cFYI(1, "bad length %d for count %d",
1383 data_length
, count
);
1387 pReadData
= (char *) (&pSMBr
->hdr
.Protocol
) +
1388 le16_to_cpu(pSMBr
->DataOffset
);
1389 /* if (rc = copy_to_user(buf, pReadData, data_length)) {
1390 cERROR(1, "Faulting on read rc = %d",rc);
1392 }*/ /* can not use copy_to_user when using page cache*/
1394 memcpy(*buf
, pReadData
, data_length
);
1398 /* cifs_small_buf_release(pSMB); */ /* Freed earlier now in SendReceive2 */
1400 if (resp_buf_type
== CIFS_SMALL_BUFFER
)
1401 cifs_small_buf_release(iov
[0].iov_base
);
1402 else if (resp_buf_type
== CIFS_LARGE_BUFFER
)
1403 cifs_buf_release(iov
[0].iov_base
);
1404 } else if (resp_buf_type
!= CIFS_NO_BUFFER
) {
1405 /* return buffer to caller to free */
1406 *buf
= iov
[0].iov_base
;
1407 if (resp_buf_type
== CIFS_SMALL_BUFFER
)
1408 *pbuf_type
= CIFS_SMALL_BUFFER
;
1409 else if (resp_buf_type
== CIFS_LARGE_BUFFER
)
1410 *pbuf_type
= CIFS_LARGE_BUFFER
;
1411 } /* else no valid buffer on return - leave as null */
1413 /* Note: On -EAGAIN error only caller can retry on handle based calls
1414 since file handle passed in no longer valid */
1420 CIFSSMBWrite(const int xid
, struct cifsTconInfo
*tcon
,
1421 const int netfid
, const unsigned int count
,
1422 const __u64 offset
, unsigned int *nbytes
, const char *buf
,
1423 const char __user
*ubuf
, const int long_op
)
1426 WRITE_REQ
*pSMB
= NULL
;
1427 WRITE_RSP
*pSMBr
= NULL
;
1428 int bytes_returned
, wct
;
1434 /* cFYI(1, "write at %lld %d bytes", offset, count);*/
1435 if (tcon
->ses
== NULL
)
1436 return -ECONNABORTED
;
1438 if (tcon
->ses
->capabilities
& CAP_LARGE_FILES
)
1442 if ((offset
>> 32) > 0) {
1443 /* can not handle big offset for old srv */
1448 rc
= smb_init(SMB_COM_WRITE_ANDX
, wct
, tcon
, (void **) &pSMB
,
1452 /* tcon and ses pointer are checked in smb_init */
1453 if (tcon
->ses
->server
== NULL
)
1454 return -ECONNABORTED
;
1456 pSMB
->AndXCommand
= 0xFF; /* none */
1458 pSMB
->OffsetLow
= cpu_to_le32(offset
& 0xFFFFFFFF);
1460 pSMB
->OffsetHigh
= cpu_to_le32(offset
>> 32);
1462 pSMB
->Reserved
= 0xFFFFFFFF;
1463 pSMB
->WriteMode
= 0;
1464 pSMB
->Remaining
= 0;
1466 /* Can increase buffer size if buffer is big enough in some cases ie we
1467 can send more if LARGE_WRITE_X capability returned by the server and if
1468 our buffer is big enough or if we convert to iovecs on socket writes
1469 and eliminate the copy to the CIFS buffer */
1470 if (tcon
->ses
->capabilities
& CAP_LARGE_WRITE_X
) {
1471 bytes_sent
= min_t(const unsigned int, CIFSMaxBufSize
, count
);
1473 bytes_sent
= (tcon
->ses
->server
->maxBuf
- MAX_CIFS_HDR_SIZE
)
1477 if (bytes_sent
> count
)
1480 cpu_to_le16(offsetof(struct smb_com_write_req
, Data
) - 4);
1482 memcpy(pSMB
->Data
, buf
, bytes_sent
);
1484 if (copy_from_user(pSMB
->Data
, ubuf
, bytes_sent
)) {
1485 cifs_buf_release(pSMB
);
1488 } else if (count
!= 0) {
1490 cifs_buf_release(pSMB
);
1492 } /* else setting file size with write of zero bytes */
1494 byte_count
= bytes_sent
+ 1; /* pad */
1495 else /* wct == 12 */
1496 byte_count
= bytes_sent
+ 5; /* bigger pad, smaller smb hdr */
1498 pSMB
->DataLengthLow
= cpu_to_le16(bytes_sent
& 0xFFFF);
1499 pSMB
->DataLengthHigh
= cpu_to_le16(bytes_sent
>> 16);
1500 pSMB
->hdr
.smb_buf_length
+= byte_count
;
1503 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
1504 else { /* old style write has byte count 4 bytes earlier
1506 struct smb_com_writex_req
*pSMBW
=
1507 (struct smb_com_writex_req
*)pSMB
;
1508 pSMBW
->ByteCount
= cpu_to_le16(byte_count
);
1511 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
1512 (struct smb_hdr
*) pSMBr
, &bytes_returned
, long_op
);
1513 cifs_stats_inc(&tcon
->num_writes
);
1515 cFYI(1, "Send error in write = %d", rc
);
1517 *nbytes
= le16_to_cpu(pSMBr
->CountHigh
);
1518 *nbytes
= (*nbytes
) << 16;
1519 *nbytes
+= le16_to_cpu(pSMBr
->Count
);
1522 * Mask off high 16 bits when bytes written as returned by the
1523 * server is greater than bytes requested by the client. Some
1524 * OS/2 servers are known to set incorrect CountHigh values.
1526 if (*nbytes
> count
)
1530 cifs_buf_release(pSMB
);
1532 /* Note: On -EAGAIN error only caller can retry on handle based calls
1533 since file handle passed in no longer valid */
1539 CIFSSMBWrite2(const int xid
, struct cifsTconInfo
*tcon
,
1540 const int netfid
, const unsigned int count
,
1541 const __u64 offset
, unsigned int *nbytes
, struct kvec
*iov
,
1542 int n_vec
, const int long_op
)
1545 WRITE_REQ
*pSMB
= NULL
;
1548 int resp_buf_type
= 0;
1552 cFYI(1, "write2 at %lld %d bytes", (long long)offset
, count
);
1554 if (tcon
->ses
->capabilities
& CAP_LARGE_FILES
) {
1558 if ((offset
>> 32) > 0) {
1559 /* can not handle big offset for old srv */
1563 rc
= small_smb_init(SMB_COM_WRITE_ANDX
, wct
, tcon
, (void **) &pSMB
);
1566 /* tcon and ses pointer are checked in smb_init */
1567 if (tcon
->ses
->server
== NULL
)
1568 return -ECONNABORTED
;
1570 pSMB
->AndXCommand
= 0xFF; /* none */
1572 pSMB
->OffsetLow
= cpu_to_le32(offset
& 0xFFFFFFFF);
1574 pSMB
->OffsetHigh
= cpu_to_le32(offset
>> 32);
1575 pSMB
->Reserved
= 0xFFFFFFFF;
1576 pSMB
->WriteMode
= 0;
1577 pSMB
->Remaining
= 0;
1580 cpu_to_le16(offsetof(struct smb_com_write_req
, Data
) - 4);
1582 pSMB
->DataLengthLow
= cpu_to_le16(count
& 0xFFFF);
1583 pSMB
->DataLengthHigh
= cpu_to_le16(count
>> 16);
1584 smb_hdr_len
= pSMB
->hdr
.smb_buf_length
+ 1; /* hdr + 1 byte pad */
1586 pSMB
->hdr
.smb_buf_length
+= count
+1;
1587 else /* wct == 12 */
1588 pSMB
->hdr
.smb_buf_length
+= count
+5; /* smb data starts later */
1590 pSMB
->ByteCount
= cpu_to_le16(count
+ 1);
1591 else /* wct == 12 */ /* bigger pad, smaller smb hdr, keep offset ok */ {
1592 struct smb_com_writex_req
*pSMBW
=
1593 (struct smb_com_writex_req
*)pSMB
;
1594 pSMBW
->ByteCount
= cpu_to_le16(count
+ 5);
1596 iov
[0].iov_base
= pSMB
;
1598 iov
[0].iov_len
= smb_hdr_len
+ 4;
1599 else /* wct == 12 pad bigger by four bytes */
1600 iov
[0].iov_len
= smb_hdr_len
+ 8;
1603 rc
= SendReceive2(xid
, tcon
->ses
, iov
, n_vec
+ 1, &resp_buf_type
,
1605 cifs_stats_inc(&tcon
->num_writes
);
1607 cFYI(1, "Send error Write2 = %d", rc
);
1608 } else if (resp_buf_type
== 0) {
1609 /* presumably this can not happen, but best to be safe */
1612 WRITE_RSP
*pSMBr
= (WRITE_RSP
*)iov
[0].iov_base
;
1613 *nbytes
= le16_to_cpu(pSMBr
->CountHigh
);
1614 *nbytes
= (*nbytes
) << 16;
1615 *nbytes
+= le16_to_cpu(pSMBr
->Count
);
1618 * Mask off high 16 bits when bytes written as returned by the
1619 * server is greater than bytes requested by the client. OS/2
1620 * servers are known to set incorrect CountHigh values.
1622 if (*nbytes
> count
)
1626 /* cifs_small_buf_release(pSMB); */ /* Freed earlier now in SendReceive2 */
1627 if (resp_buf_type
== CIFS_SMALL_BUFFER
)
1628 cifs_small_buf_release(iov
[0].iov_base
);
1629 else if (resp_buf_type
== CIFS_LARGE_BUFFER
)
1630 cifs_buf_release(iov
[0].iov_base
);
1632 /* Note: On -EAGAIN error only caller can retry on handle based calls
1633 since file handle passed in no longer valid */
1640 CIFSSMBLock(const int xid
, struct cifsTconInfo
*tcon
,
1641 const __u16 smb_file_id
, const __u64 len
,
1642 const __u64 offset
, const __u32 numUnlock
,
1643 const __u32 numLock
, const __u8 lockType
, const bool waitFlag
)
1646 LOCK_REQ
*pSMB
= NULL
;
1647 /* LOCK_RSP *pSMBr = NULL; */ /* No response data other than rc to parse */
1652 cFYI(1, "CIFSSMBLock timeout %d numLock %d", (int)waitFlag
, numLock
);
1653 rc
= small_smb_init(SMB_COM_LOCKING_ANDX
, 8, tcon
, (void **) &pSMB
);
1658 if (lockType
== LOCKING_ANDX_OPLOCK_RELEASE
) {
1659 timeout
= CIFS_ASYNC_OP
; /* no response expected */
1661 } else if (waitFlag
) {
1662 timeout
= CIFS_BLOCKING_OP
; /* blocking operation, no timeout */
1663 pSMB
->Timeout
= cpu_to_le32(-1);/* blocking - do not time out */
1668 pSMB
->NumberOfLocks
= cpu_to_le16(numLock
);
1669 pSMB
->NumberOfUnlocks
= cpu_to_le16(numUnlock
);
1670 pSMB
->LockType
= lockType
;
1671 pSMB
->AndXCommand
= 0xFF; /* none */
1672 pSMB
->Fid
= smb_file_id
; /* netfid stays le */
1674 if ((numLock
!= 0) || (numUnlock
!= 0)) {
1675 pSMB
->Locks
[0].Pid
= cpu_to_le16(current
->tgid
);
1676 /* BB where to store pid high? */
1677 pSMB
->Locks
[0].LengthLow
= cpu_to_le32((u32
)len
);
1678 pSMB
->Locks
[0].LengthHigh
= cpu_to_le32((u32
)(len
>>32));
1679 pSMB
->Locks
[0].OffsetLow
= cpu_to_le32((u32
)offset
);
1680 pSMB
->Locks
[0].OffsetHigh
= cpu_to_le32((u32
)(offset
>>32));
1681 count
= sizeof(LOCKING_ANDX_RANGE
);
1686 pSMB
->hdr
.smb_buf_length
+= count
;
1687 pSMB
->ByteCount
= cpu_to_le16(count
);
1690 rc
= SendReceiveBlockingLock(xid
, tcon
, (struct smb_hdr
*) pSMB
,
1691 (struct smb_hdr
*) pSMB
, &bytes_returned
);
1692 cifs_small_buf_release(pSMB
);
1694 rc
= SendReceiveNoRsp(xid
, tcon
->ses
, (struct smb_hdr
*)pSMB
,
1696 /* SMB buffer freed by function above */
1698 cifs_stats_inc(&tcon
->num_locks
);
1700 cFYI(1, "Send error in Lock = %d", rc
);
1702 /* Note: On -EAGAIN error only caller can retry on handle based calls
1703 since file handle passed in no longer valid */
1708 CIFSSMBPosixLock(const int xid
, struct cifsTconInfo
*tcon
,
1709 const __u16 smb_file_id
, const int get_flag
, const __u64 len
,
1710 struct file_lock
*pLockData
, const __u16 lock_type
,
1711 const bool waitFlag
)
1713 struct smb_com_transaction2_sfi_req
*pSMB
= NULL
;
1714 struct smb_com_transaction2_sfi_rsp
*pSMBr
= NULL
;
1715 struct cifs_posix_lock
*parm_data
;
1718 int bytes_returned
= 0;
1719 int resp_buf_type
= 0;
1720 __u16 params
, param_offset
, offset
, byte_count
, count
;
1723 cFYI(1, "Posix Lock");
1725 if (pLockData
== NULL
)
1728 rc
= small_smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
);
1733 pSMBr
= (struct smb_com_transaction2_sfi_rsp
*)pSMB
;
1736 pSMB
->MaxSetupCount
= 0;
1739 pSMB
->Reserved2
= 0;
1740 param_offset
= offsetof(struct smb_com_transaction2_sfi_req
, Fid
) - 4;
1741 offset
= param_offset
+ params
;
1743 count
= sizeof(struct cifs_posix_lock
);
1744 pSMB
->MaxParameterCount
= cpu_to_le16(2);
1745 pSMB
->MaxDataCount
= cpu_to_le16(1000); /* BB find max SMB from sess */
1746 pSMB
->SetupCount
= 1;
1747 pSMB
->Reserved3
= 0;
1749 pSMB
->SubCommand
= cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION
);
1751 pSMB
->SubCommand
= cpu_to_le16(TRANS2_SET_FILE_INFORMATION
);
1752 byte_count
= 3 /* pad */ + params
+ count
;
1753 pSMB
->DataCount
= cpu_to_le16(count
);
1754 pSMB
->ParameterCount
= cpu_to_le16(params
);
1755 pSMB
->TotalDataCount
= pSMB
->DataCount
;
1756 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
1757 pSMB
->ParameterOffset
= cpu_to_le16(param_offset
);
1758 parm_data
= (struct cifs_posix_lock
*)
1759 (((char *) &pSMB
->hdr
.Protocol
) + offset
);
1761 parm_data
->lock_type
= cpu_to_le16(lock_type
);
1763 timeout
= CIFS_BLOCKING_OP
; /* blocking operation, no timeout */
1764 parm_data
->lock_flags
= cpu_to_le16(1);
1765 pSMB
->Timeout
= cpu_to_le32(-1);
1769 parm_data
->pid
= cpu_to_le32(current
->tgid
);
1770 parm_data
->start
= cpu_to_le64(pLockData
->fl_start
);
1771 parm_data
->length
= cpu_to_le64(len
); /* normalize negative numbers */
1773 pSMB
->DataOffset
= cpu_to_le16(offset
);
1774 pSMB
->Fid
= smb_file_id
;
1775 pSMB
->InformationLevel
= cpu_to_le16(SMB_SET_POSIX_LOCK
);
1776 pSMB
->Reserved4
= 0;
1777 pSMB
->hdr
.smb_buf_length
+= byte_count
;
1778 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
1780 rc
= SendReceiveBlockingLock(xid
, tcon
, (struct smb_hdr
*) pSMB
,
1781 (struct smb_hdr
*) pSMBr
, &bytes_returned
);
1783 iov
[0].iov_base
= (char *)pSMB
;
1784 iov
[0].iov_len
= pSMB
->hdr
.smb_buf_length
+ 4;
1785 rc
= SendReceive2(xid
, tcon
->ses
, iov
, 1 /* num iovecs */,
1786 &resp_buf_type
, timeout
);
1787 pSMB
= NULL
; /* request buf already freed by SendReceive2. Do
1788 not try to free it twice below on exit */
1789 pSMBr
= (struct smb_com_transaction2_sfi_rsp
*)iov
[0].iov_base
;
1793 cFYI(1, "Send error in Posix Lock = %d", rc
);
1794 } else if (get_flag
) {
1795 /* lock structure can be returned on get */
1798 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
1800 if (rc
|| (pSMBr
->ByteCount
< sizeof(struct cifs_posix_lock
))) {
1801 rc
= -EIO
; /* bad smb */
1804 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
1805 data_count
= le16_to_cpu(pSMBr
->t2
.DataCount
);
1806 if (data_count
< sizeof(struct cifs_posix_lock
)) {
1810 parm_data
= (struct cifs_posix_lock
*)
1811 ((char *)&pSMBr
->hdr
.Protocol
+ data_offset
);
1812 if (parm_data
->lock_type
== __constant_cpu_to_le16(CIFS_UNLCK
))
1813 pLockData
->fl_type
= F_UNLCK
;
1815 if (parm_data
->lock_type
==
1816 __constant_cpu_to_le16(CIFS_RDLCK
))
1817 pLockData
->fl_type
= F_RDLCK
;
1818 else if (parm_data
->lock_type
==
1819 __constant_cpu_to_le16(CIFS_WRLCK
))
1820 pLockData
->fl_type
= F_WRLCK
;
1822 pLockData
->fl_start
= parm_data
->start
;
1823 pLockData
->fl_end
= parm_data
->start
+
1824 parm_data
->length
- 1;
1825 pLockData
->fl_pid
= parm_data
->pid
;
1831 cifs_small_buf_release(pSMB
);
1833 if (resp_buf_type
== CIFS_SMALL_BUFFER
)
1834 cifs_small_buf_release(iov
[0].iov_base
);
1835 else if (resp_buf_type
== CIFS_LARGE_BUFFER
)
1836 cifs_buf_release(iov
[0].iov_base
);
1838 /* Note: On -EAGAIN error only caller can retry on handle based calls
1839 since file handle passed in no longer valid */
1846 CIFSSMBClose(const int xid
, struct cifsTconInfo
*tcon
, int smb_file_id
)
1849 CLOSE_REQ
*pSMB
= NULL
;
1850 cFYI(1, "In CIFSSMBClose");
1852 /* do not retry on dead session on close */
1853 rc
= small_smb_init(SMB_COM_CLOSE
, 3, tcon
, (void **) &pSMB
);
1859 pSMB
->FileID
= (__u16
) smb_file_id
;
1860 pSMB
->LastWriteTime
= 0xFFFFFFFF;
1861 pSMB
->ByteCount
= 0;
1862 rc
= SendReceiveNoRsp(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
, 0);
1863 cifs_stats_inc(&tcon
->num_closes
);
1866 /* EINTR is expected when user ctl-c to kill app */
1867 cERROR(1, "Send error in Close = %d", rc
);
1871 /* Since session is dead, file will be closed on server already */
1879 CIFSSMBFlush(const int xid
, struct cifsTconInfo
*tcon
, int smb_file_id
)
1882 FLUSH_REQ
*pSMB
= NULL
;
1883 cFYI(1, "In CIFSSMBFlush");
1885 rc
= small_smb_init(SMB_COM_FLUSH
, 1, tcon
, (void **) &pSMB
);
1889 pSMB
->FileID
= (__u16
) smb_file_id
;
1890 pSMB
->ByteCount
= 0;
1891 rc
= SendReceiveNoRsp(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
, 0);
1892 cifs_stats_inc(&tcon
->num_flushes
);
1894 cERROR(1, "Send error in Flush = %d", rc
);
1900 CIFSSMBRename(const int xid
, struct cifsTconInfo
*tcon
,
1901 const char *fromName
, const char *toName
,
1902 const struct nls_table
*nls_codepage
, int remap
)
1905 RENAME_REQ
*pSMB
= NULL
;
1906 RENAME_RSP
*pSMBr
= NULL
;
1908 int name_len
, name_len2
;
1911 cFYI(1, "In CIFSSMBRename");
1913 rc
= smb_init(SMB_COM_RENAME
, 1, tcon
, (void **) &pSMB
,
1918 pSMB
->BufferFormat
= 0x04;
1919 pSMB
->SearchAttributes
=
1920 cpu_to_le16(ATTR_READONLY
| ATTR_HIDDEN
| ATTR_SYSTEM
|
1923 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
1925 cifsConvertToUCS((__le16
*) pSMB
->OldFileName
, fromName
,
1926 PATH_MAX
, nls_codepage
, remap
);
1927 name_len
++; /* trailing null */
1929 pSMB
->OldFileName
[name_len
] = 0x04; /* pad */
1930 /* protocol requires ASCII signature byte on Unicode string */
1931 pSMB
->OldFileName
[name_len
+ 1] = 0x00;
1933 cifsConvertToUCS((__le16
*)&pSMB
->OldFileName
[name_len
+ 2],
1934 toName
, PATH_MAX
, nls_codepage
, remap
);
1935 name_len2
+= 1 /* trailing null */ + 1 /* Signature word */ ;
1936 name_len2
*= 2; /* convert to bytes */
1937 } else { /* BB improve the check for buffer overruns BB */
1938 name_len
= strnlen(fromName
, PATH_MAX
);
1939 name_len
++; /* trailing null */
1940 strncpy(pSMB
->OldFileName
, fromName
, name_len
);
1941 name_len2
= strnlen(toName
, PATH_MAX
);
1942 name_len2
++; /* trailing null */
1943 pSMB
->OldFileName
[name_len
] = 0x04; /* 2nd buffer format */
1944 strncpy(&pSMB
->OldFileName
[name_len
+ 1], toName
, name_len2
);
1945 name_len2
++; /* trailing null */
1946 name_len2
++; /* signature byte */
1949 count
= 1 /* 1st signature byte */ + name_len
+ name_len2
;
1950 pSMB
->hdr
.smb_buf_length
+= count
;
1951 pSMB
->ByteCount
= cpu_to_le16(count
);
1953 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
1954 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
1955 cifs_stats_inc(&tcon
->num_renames
);
1957 cFYI(1, "Send error in rename = %d", rc
);
1959 cifs_buf_release(pSMB
);
1967 int CIFSSMBRenameOpenFile(const int xid
, struct cifsTconInfo
*pTcon
,
1968 int netfid
, const char *target_name
,
1969 const struct nls_table
*nls_codepage
, int remap
)
1971 struct smb_com_transaction2_sfi_req
*pSMB
= NULL
;
1972 struct smb_com_transaction2_sfi_rsp
*pSMBr
= NULL
;
1973 struct set_file_rename
*rename_info
;
1975 char dummy_string
[30];
1977 int bytes_returned
= 0;
1979 __u16 params
, param_offset
, offset
, count
, byte_count
;
1981 cFYI(1, "Rename to File by handle");
1982 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, pTcon
, (void **) &pSMB
,
1988 pSMB
->MaxSetupCount
= 0;
1992 pSMB
->Reserved2
= 0;
1993 param_offset
= offsetof(struct smb_com_transaction2_sfi_req
, Fid
) - 4;
1994 offset
= param_offset
+ params
;
1996 data_offset
= (char *) (&pSMB
->hdr
.Protocol
) + offset
;
1997 rename_info
= (struct set_file_rename
*) data_offset
;
1998 pSMB
->MaxParameterCount
= cpu_to_le16(2);
1999 pSMB
->MaxDataCount
= cpu_to_le16(1000); /* BB find max SMB from sess */
2000 pSMB
->SetupCount
= 1;
2001 pSMB
->Reserved3
= 0;
2002 pSMB
->SubCommand
= cpu_to_le16(TRANS2_SET_FILE_INFORMATION
);
2003 byte_count
= 3 /* pad */ + params
;
2004 pSMB
->ParameterCount
= cpu_to_le16(params
);
2005 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
2006 pSMB
->ParameterOffset
= cpu_to_le16(param_offset
);
2007 pSMB
->DataOffset
= cpu_to_le16(offset
);
2008 /* construct random name ".cifs_tmp<inodenum><mid>" */
2009 rename_info
->overwrite
= cpu_to_le32(1);
2010 rename_info
->root_fid
= 0;
2011 /* unicode only call */
2012 if (target_name
== NULL
) {
2013 sprintf(dummy_string
, "cifs%x", pSMB
->hdr
.Mid
);
2014 len_of_str
= cifsConvertToUCS((__le16
*)rename_info
->target_name
,
2015 dummy_string
, 24, nls_codepage
, remap
);
2017 len_of_str
= cifsConvertToUCS((__le16
*)rename_info
->target_name
,
2018 target_name
, PATH_MAX
, nls_codepage
,
2021 rename_info
->target_name_len
= cpu_to_le32(2 * len_of_str
);
2022 count
= 12 /* sizeof(struct set_file_rename) */ + (2 * len_of_str
);
2023 byte_count
+= count
;
2024 pSMB
->DataCount
= cpu_to_le16(count
);
2025 pSMB
->TotalDataCount
= pSMB
->DataCount
;
2027 pSMB
->InformationLevel
=
2028 cpu_to_le16(SMB_SET_FILE_RENAME_INFORMATION
);
2029 pSMB
->Reserved4
= 0;
2030 pSMB
->hdr
.smb_buf_length
+= byte_count
;
2031 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
2032 rc
= SendReceive(xid
, pTcon
->ses
, (struct smb_hdr
*) pSMB
,
2033 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
2034 cifs_stats_inc(&pTcon
->num_t2renames
);
2036 cFYI(1, "Send error in Rename (by file handle) = %d", rc
);
2038 cifs_buf_release(pSMB
);
2040 /* Note: On -EAGAIN error only caller can retry on handle based calls
2041 since file handle passed in no longer valid */
2047 CIFSSMBCopy(const int xid
, struct cifsTconInfo
*tcon
, const char *fromName
,
2048 const __u16 target_tid
, const char *toName
, const int flags
,
2049 const struct nls_table
*nls_codepage
, int remap
)
2052 COPY_REQ
*pSMB
= NULL
;
2053 COPY_RSP
*pSMBr
= NULL
;
2055 int name_len
, name_len2
;
2058 cFYI(1, "In CIFSSMBCopy");
2060 rc
= smb_init(SMB_COM_COPY
, 1, tcon
, (void **) &pSMB
,
2065 pSMB
->BufferFormat
= 0x04;
2066 pSMB
->Tid2
= target_tid
;
2068 pSMB
->Flags
= cpu_to_le16(flags
& COPY_TREE
);
2070 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
2071 name_len
= cifsConvertToUCS((__le16
*) pSMB
->OldFileName
,
2072 fromName
, PATH_MAX
, nls_codepage
,
2074 name_len
++; /* trailing null */
2076 pSMB
->OldFileName
[name_len
] = 0x04; /* pad */
2077 /* protocol requires ASCII signature byte on Unicode string */
2078 pSMB
->OldFileName
[name_len
+ 1] = 0x00;
2080 cifsConvertToUCS((__le16
*)&pSMB
->OldFileName
[name_len
+ 2],
2081 toName
, PATH_MAX
, nls_codepage
, remap
);
2082 name_len2
+= 1 /* trailing null */ + 1 /* Signature word */ ;
2083 name_len2
*= 2; /* convert to bytes */
2084 } else { /* BB improve the check for buffer overruns BB */
2085 name_len
= strnlen(fromName
, PATH_MAX
);
2086 name_len
++; /* trailing null */
2087 strncpy(pSMB
->OldFileName
, fromName
, name_len
);
2088 name_len2
= strnlen(toName
, PATH_MAX
);
2089 name_len2
++; /* trailing null */
2090 pSMB
->OldFileName
[name_len
] = 0x04; /* 2nd buffer format */
2091 strncpy(&pSMB
->OldFileName
[name_len
+ 1], toName
, name_len2
);
2092 name_len2
++; /* trailing null */
2093 name_len2
++; /* signature byte */
2096 count
= 1 /* 1st signature byte */ + name_len
+ name_len2
;
2097 pSMB
->hdr
.smb_buf_length
+= count
;
2098 pSMB
->ByteCount
= cpu_to_le16(count
);
2100 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
2101 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
2103 cFYI(1, "Send error in copy = %d with %d files copied",
2104 rc
, le16_to_cpu(pSMBr
->CopyCount
));
2106 cifs_buf_release(pSMB
);
2115 CIFSUnixCreateSymLink(const int xid
, struct cifsTconInfo
*tcon
,
2116 const char *fromName
, const char *toName
,
2117 const struct nls_table
*nls_codepage
)
2119 TRANSACTION2_SPI_REQ
*pSMB
= NULL
;
2120 TRANSACTION2_SPI_RSP
*pSMBr
= NULL
;
2123 int name_len_target
;
2125 int bytes_returned
= 0;
2126 __u16 params
, param_offset
, offset
, byte_count
;
2128 cFYI(1, "In Symlink Unix style");
2130 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
2135 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
2137 cifs_strtoUCS((__le16
*) pSMB
->FileName
, fromName
, PATH_MAX
2138 /* find define for this maxpathcomponent */
2140 name_len
++; /* trailing null */
2143 } else { /* BB improve the check for buffer overruns BB */
2144 name_len
= strnlen(fromName
, PATH_MAX
);
2145 name_len
++; /* trailing null */
2146 strncpy(pSMB
->FileName
, fromName
, name_len
);
2148 params
= 6 + name_len
;
2149 pSMB
->MaxSetupCount
= 0;
2153 pSMB
->Reserved2
= 0;
2154 param_offset
= offsetof(struct smb_com_transaction2_spi_req
,
2155 InformationLevel
) - 4;
2156 offset
= param_offset
+ params
;
2158 data_offset
= (char *) (&pSMB
->hdr
.Protocol
) + offset
;
2159 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
2161 cifs_strtoUCS((__le16
*) data_offset
, toName
, PATH_MAX
2162 /* find define for this maxpathcomponent */
2164 name_len_target
++; /* trailing null */
2165 name_len_target
*= 2;
2166 } else { /* BB improve the check for buffer overruns BB */
2167 name_len_target
= strnlen(toName
, PATH_MAX
);
2168 name_len_target
++; /* trailing null */
2169 strncpy(data_offset
, toName
, name_len_target
);
2172 pSMB
->MaxParameterCount
= cpu_to_le16(2);
2173 /* BB find exact max on data count below from sess */
2174 pSMB
->MaxDataCount
= cpu_to_le16(1000);
2175 pSMB
->SetupCount
= 1;
2176 pSMB
->Reserved3
= 0;
2177 pSMB
->SubCommand
= cpu_to_le16(TRANS2_SET_PATH_INFORMATION
);
2178 byte_count
= 3 /* pad */ + params
+ name_len_target
;
2179 pSMB
->DataCount
= cpu_to_le16(name_len_target
);
2180 pSMB
->ParameterCount
= cpu_to_le16(params
);
2181 pSMB
->TotalDataCount
= pSMB
->DataCount
;
2182 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
2183 pSMB
->ParameterOffset
= cpu_to_le16(param_offset
);
2184 pSMB
->DataOffset
= cpu_to_le16(offset
);
2185 pSMB
->InformationLevel
= cpu_to_le16(SMB_SET_FILE_UNIX_LINK
);
2186 pSMB
->Reserved4
= 0;
2187 pSMB
->hdr
.smb_buf_length
+= byte_count
;
2188 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
2189 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
2190 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
2191 cifs_stats_inc(&tcon
->num_symlinks
);
2193 cFYI(1, "Send error in SetPathInfo create symlink = %d", rc
);
2195 cifs_buf_release(pSMB
);
2198 goto createSymLinkRetry
;
2204 CIFSUnixCreateHardLink(const int xid
, struct cifsTconInfo
*tcon
,
2205 const char *fromName
, const char *toName
,
2206 const struct nls_table
*nls_codepage
, int remap
)
2208 TRANSACTION2_SPI_REQ
*pSMB
= NULL
;
2209 TRANSACTION2_SPI_RSP
*pSMBr
= NULL
;
2212 int name_len_target
;
2214 int bytes_returned
= 0;
2215 __u16 params
, param_offset
, offset
, byte_count
;
2217 cFYI(1, "In Create Hard link Unix style");
2218 createHardLinkRetry
:
2219 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
2224 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
2225 name_len
= cifsConvertToUCS((__le16
*) pSMB
->FileName
, toName
,
2226 PATH_MAX
, nls_codepage
, remap
);
2227 name_len
++; /* trailing null */
2230 } else { /* BB improve the check for buffer overruns BB */
2231 name_len
= strnlen(toName
, PATH_MAX
);
2232 name_len
++; /* trailing null */
2233 strncpy(pSMB
->FileName
, toName
, name_len
);
2235 params
= 6 + name_len
;
2236 pSMB
->MaxSetupCount
= 0;
2240 pSMB
->Reserved2
= 0;
2241 param_offset
= offsetof(struct smb_com_transaction2_spi_req
,
2242 InformationLevel
) - 4;
2243 offset
= param_offset
+ params
;
2245 data_offset
= (char *) (&pSMB
->hdr
.Protocol
) + offset
;
2246 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
2248 cifsConvertToUCS((__le16
*) data_offset
, fromName
, PATH_MAX
,
2249 nls_codepage
, remap
);
2250 name_len_target
++; /* trailing null */
2251 name_len_target
*= 2;
2252 } else { /* BB improve the check for buffer overruns BB */
2253 name_len_target
= strnlen(fromName
, PATH_MAX
);
2254 name_len_target
++; /* trailing null */
2255 strncpy(data_offset
, fromName
, name_len_target
);
2258 pSMB
->MaxParameterCount
= cpu_to_le16(2);
2259 /* BB find exact max on data count below from sess*/
2260 pSMB
->MaxDataCount
= cpu_to_le16(1000);
2261 pSMB
->SetupCount
= 1;
2262 pSMB
->Reserved3
= 0;
2263 pSMB
->SubCommand
= cpu_to_le16(TRANS2_SET_PATH_INFORMATION
);
2264 byte_count
= 3 /* pad */ + params
+ name_len_target
;
2265 pSMB
->ParameterCount
= cpu_to_le16(params
);
2266 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
2267 pSMB
->DataCount
= cpu_to_le16(name_len_target
);
2268 pSMB
->TotalDataCount
= pSMB
->DataCount
;
2269 pSMB
->ParameterOffset
= cpu_to_le16(param_offset
);
2270 pSMB
->DataOffset
= cpu_to_le16(offset
);
2271 pSMB
->InformationLevel
= cpu_to_le16(SMB_SET_FILE_UNIX_HLINK
);
2272 pSMB
->Reserved4
= 0;
2273 pSMB
->hdr
.smb_buf_length
+= byte_count
;
2274 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
2275 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
2276 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
2277 cifs_stats_inc(&tcon
->num_hardlinks
);
2279 cFYI(1, "Send error in SetPathInfo (hard link) = %d", rc
);
2281 cifs_buf_release(pSMB
);
2283 goto createHardLinkRetry
;
2289 CIFSCreateHardLink(const int xid
, struct cifsTconInfo
*tcon
,
2290 const char *fromName
, const char *toName
,
2291 const struct nls_table
*nls_codepage
, int remap
)
2294 NT_RENAME_REQ
*pSMB
= NULL
;
2295 RENAME_RSP
*pSMBr
= NULL
;
2297 int name_len
, name_len2
;
2300 cFYI(1, "In CIFSCreateHardLink");
2301 winCreateHardLinkRetry
:
2303 rc
= smb_init(SMB_COM_NT_RENAME
, 4, tcon
, (void **) &pSMB
,
2308 pSMB
->SearchAttributes
=
2309 cpu_to_le16(ATTR_READONLY
| ATTR_HIDDEN
| ATTR_SYSTEM
|
2311 pSMB
->Flags
= cpu_to_le16(CREATE_HARD_LINK
);
2312 pSMB
->ClusterCount
= 0;
2314 pSMB
->BufferFormat
= 0x04;
2316 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
2318 cifsConvertToUCS((__le16
*) pSMB
->OldFileName
, fromName
,
2319 PATH_MAX
, nls_codepage
, remap
);
2320 name_len
++; /* trailing null */
2323 /* protocol specifies ASCII buffer format (0x04) for unicode */
2324 pSMB
->OldFileName
[name_len
] = 0x04;
2325 pSMB
->OldFileName
[name_len
+ 1] = 0x00; /* pad */
2327 cifsConvertToUCS((__le16
*)&pSMB
->OldFileName
[name_len
+ 2],
2328 toName
, PATH_MAX
, nls_codepage
, remap
);
2329 name_len2
+= 1 /* trailing null */ + 1 /* Signature word */ ;
2330 name_len2
*= 2; /* convert to bytes */
2331 } else { /* BB improve the check for buffer overruns BB */
2332 name_len
= strnlen(fromName
, PATH_MAX
);
2333 name_len
++; /* trailing null */
2334 strncpy(pSMB
->OldFileName
, fromName
, name_len
);
2335 name_len2
= strnlen(toName
, PATH_MAX
);
2336 name_len2
++; /* trailing null */
2337 pSMB
->OldFileName
[name_len
] = 0x04; /* 2nd buffer format */
2338 strncpy(&pSMB
->OldFileName
[name_len
+ 1], toName
, name_len2
);
2339 name_len2
++; /* trailing null */
2340 name_len2
++; /* signature byte */
2343 count
= 1 /* string type byte */ + name_len
+ name_len2
;
2344 pSMB
->hdr
.smb_buf_length
+= count
;
2345 pSMB
->ByteCount
= cpu_to_le16(count
);
2347 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
2348 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
2349 cifs_stats_inc(&tcon
->num_hardlinks
);
2351 cFYI(1, "Send error in hard link (NT rename) = %d", rc
);
2353 cifs_buf_release(pSMB
);
2355 goto winCreateHardLinkRetry
;
2361 CIFSSMBUnixQuerySymLink(const int xid
, struct cifsTconInfo
*tcon
,
2362 const unsigned char *searchName
, char **symlinkinfo
,
2363 const struct nls_table
*nls_codepage
)
2365 /* SMB_QUERY_FILE_UNIX_LINK */
2366 TRANSACTION2_QPI_REQ
*pSMB
= NULL
;
2367 TRANSACTION2_QPI_RSP
*pSMBr
= NULL
;
2371 __u16 params
, byte_count
;
2374 cFYI(1, "In QPathSymLinkInfo (Unix) for path %s", searchName
);
2377 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
2382 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
2384 cifs_strtoUCS((__le16
*) pSMB
->FileName
, searchName
,
2385 PATH_MAX
, nls_codepage
);
2386 name_len
++; /* trailing null */
2388 } else { /* BB improve the check for buffer overruns BB */
2389 name_len
= strnlen(searchName
, PATH_MAX
);
2390 name_len
++; /* trailing null */
2391 strncpy(pSMB
->FileName
, searchName
, name_len
);
2394 params
= 2 /* level */ + 4 /* rsrvd */ + name_len
/* incl null */ ;
2395 pSMB
->TotalDataCount
= 0;
2396 pSMB
->MaxParameterCount
= cpu_to_le16(2);
2397 pSMB
->MaxDataCount
= cpu_to_le16(CIFSMaxBufSize
);
2398 pSMB
->MaxSetupCount
= 0;
2402 pSMB
->Reserved2
= 0;
2403 pSMB
->ParameterOffset
= cpu_to_le16(offsetof(
2404 struct smb_com_transaction2_qpi_req
, InformationLevel
) - 4);
2405 pSMB
->DataCount
= 0;
2406 pSMB
->DataOffset
= 0;
2407 pSMB
->SetupCount
= 1;
2408 pSMB
->Reserved3
= 0;
2409 pSMB
->SubCommand
= cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION
);
2410 byte_count
= params
+ 1 /* pad */ ;
2411 pSMB
->TotalParameterCount
= cpu_to_le16(params
);
2412 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
2413 pSMB
->InformationLevel
= cpu_to_le16(SMB_QUERY_FILE_UNIX_LINK
);
2414 pSMB
->Reserved4
= 0;
2415 pSMB
->hdr
.smb_buf_length
+= byte_count
;
2416 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
2418 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
2419 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
2421 cFYI(1, "Send error in QuerySymLinkInfo = %d", rc
);
2423 /* decode response */
2425 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
2426 /* BB also check enough total bytes returned */
2427 if (rc
|| (pSMBr
->ByteCount
< 2))
2431 u16 count
= le16_to_cpu(pSMBr
->t2
.DataCount
);
2433 data_start
= ((char *) &pSMBr
->hdr
.Protocol
) +
2434 le16_to_cpu(pSMBr
->t2
.DataOffset
);
2436 if (pSMBr
->hdr
.Flags2
& SMBFLG2_UNICODE
)
2441 /* BB FIXME investigate remapping reserved chars here */
2442 *symlinkinfo
= cifs_strndup_from_ucs(data_start
, count
,
2443 is_unicode
, nls_codepage
);
2448 cifs_buf_release(pSMB
);
2450 goto querySymLinkRetry
;
2454 #ifdef CONFIG_CIFS_EXPERIMENTAL
2455 /* Initialize NT TRANSACT SMB into small smb request buffer.
2456 This assumes that all NT TRANSACTS that we init here have
2457 total parm and data under about 400 bytes (to fit in small cifs
2458 buffer size), which is the case so far, it easily fits. NB:
2459 Setup words themselves and ByteCount
2460 MaxSetupCount (size of returned setup area) and
2461 MaxParameterCount (returned parms size) must be set by caller */
2463 smb_init_nttransact(const __u16 sub_command
, const int setup_count
,
2464 const int parm_len
, struct cifsTconInfo
*tcon
,
2469 struct smb_com_ntransact_req
*pSMB
;
2471 rc
= small_smb_init(SMB_COM_NT_TRANSACT
, 19 + setup_count
, tcon
,
2475 *ret_buf
= (void *)pSMB
;
2477 pSMB
->TotalParameterCount
= cpu_to_le32(parm_len
);
2478 pSMB
->TotalDataCount
= 0;
2479 pSMB
->MaxDataCount
= cpu_to_le32((tcon
->ses
->server
->maxBuf
-
2480 MAX_CIFS_HDR_SIZE
) & 0xFFFFFF00);
2481 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
2482 pSMB
->DataCount
= pSMB
->TotalDataCount
;
2483 temp_offset
= offsetof(struct smb_com_ntransact_req
, Parms
) +
2484 (setup_count
* 2) - 4 /* for rfc1001 length itself */;
2485 pSMB
->ParameterOffset
= cpu_to_le32(temp_offset
);
2486 pSMB
->DataOffset
= cpu_to_le32(temp_offset
+ parm_len
);
2487 pSMB
->SetupCount
= setup_count
; /* no need to le convert byte fields */
2488 pSMB
->SubCommand
= cpu_to_le16(sub_command
);
2493 validate_ntransact(char *buf
, char **ppparm
, char **ppdata
,
2494 __u32
*pparmlen
, __u32
*pdatalen
)
2497 __u32 data_count
, data_offset
, parm_count
, parm_offset
;
2498 struct smb_com_ntransact_rsp
*pSMBr
;
2506 pSMBr
= (struct smb_com_ntransact_rsp
*)buf
;
2508 /* ByteCount was converted from little endian in SendReceive */
2509 end_of_smb
= 2 /* sizeof byte count */ + pSMBr
->ByteCount
+
2510 (char *)&pSMBr
->ByteCount
;
2512 data_offset
= le32_to_cpu(pSMBr
->DataOffset
);
2513 data_count
= le32_to_cpu(pSMBr
->DataCount
);
2514 parm_offset
= le32_to_cpu(pSMBr
->ParameterOffset
);
2515 parm_count
= le32_to_cpu(pSMBr
->ParameterCount
);
2517 *ppparm
= (char *)&pSMBr
->hdr
.Protocol
+ parm_offset
;
2518 *ppdata
= (char *)&pSMBr
->hdr
.Protocol
+ data_offset
;
2520 /* should we also check that parm and data areas do not overlap? */
2521 if (*ppparm
> end_of_smb
) {
2522 cFYI(1, "parms start after end of smb");
2524 } else if (parm_count
+ *ppparm
> end_of_smb
) {
2525 cFYI(1, "parm end after end of smb");
2527 } else if (*ppdata
> end_of_smb
) {
2528 cFYI(1, "data starts after end of smb");
2530 } else if (data_count
+ *ppdata
> end_of_smb
) {
2531 cFYI(1, "data %p + count %d (%p) past smb end %p start %p",
2532 *ppdata
, data_count
, (data_count
+ *ppdata
),
2535 } else if (parm_count
+ data_count
> pSMBr
->ByteCount
) {
2536 cFYI(1, "parm count and data count larger than SMB");
2539 *pdatalen
= data_count
;
2540 *pparmlen
= parm_count
;
2545 CIFSSMBQueryReparseLinkInfo(const int xid
, struct cifsTconInfo
*tcon
,
2546 const unsigned char *searchName
,
2547 char *symlinkinfo
, const int buflen
, __u16 fid
,
2548 const struct nls_table
*nls_codepage
)
2552 struct smb_com_transaction_ioctl_req
*pSMB
;
2553 struct smb_com_transaction_ioctl_rsp
*pSMBr
;
2555 cFYI(1, "In Windows reparse style QueryLink for path %s", searchName
);
2556 rc
= smb_init(SMB_COM_NT_TRANSACT
, 23, tcon
, (void **) &pSMB
,
2561 pSMB
->TotalParameterCount
= 0 ;
2562 pSMB
->TotalDataCount
= 0;
2563 pSMB
->MaxParameterCount
= cpu_to_le32(2);
2564 /* BB find exact data count max from sess structure BB */
2565 pSMB
->MaxDataCount
= cpu_to_le32((tcon
->ses
->server
->maxBuf
-
2566 MAX_CIFS_HDR_SIZE
) & 0xFFFFFF00);
2567 pSMB
->MaxSetupCount
= 4;
2569 pSMB
->ParameterOffset
= 0;
2570 pSMB
->DataCount
= 0;
2571 pSMB
->DataOffset
= 0;
2572 pSMB
->SetupCount
= 4;
2573 pSMB
->SubCommand
= cpu_to_le16(NT_TRANSACT_IOCTL
);
2574 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
2575 pSMB
->FunctionCode
= cpu_to_le32(FSCTL_GET_REPARSE_POINT
);
2576 pSMB
->IsFsctl
= 1; /* FSCTL */
2577 pSMB
->IsRootFlag
= 0;
2578 pSMB
->Fid
= fid
; /* file handle always le */
2579 pSMB
->ByteCount
= 0;
2581 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
2582 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
2584 cFYI(1, "Send error in QueryReparseLinkInfo = %d", rc
);
2585 } else { /* decode response */
2586 __u32 data_offset
= le32_to_cpu(pSMBr
->DataOffset
);
2587 __u32 data_count
= le32_to_cpu(pSMBr
->DataCount
);
2588 if ((pSMBr
->ByteCount
< 2) || (data_offset
> 512)) {
2589 /* BB also check enough total bytes returned */
2590 rc
= -EIO
; /* bad smb */
2593 if (data_count
&& (data_count
< 2048)) {
2594 char *end_of_smb
= 2 /* sizeof byte count */ +
2595 pSMBr
->ByteCount
+ (char *)&pSMBr
->ByteCount
;
2597 struct reparse_data
*reparse_buf
=
2598 (struct reparse_data
*)
2599 ((char *)&pSMBr
->hdr
.Protocol
2601 if ((char *)reparse_buf
>= end_of_smb
) {
2605 if ((reparse_buf
->LinkNamesBuf
+
2606 reparse_buf
->TargetNameOffset
+
2607 reparse_buf
->TargetNameLen
) > end_of_smb
) {
2608 cFYI(1, "reparse buf beyond SMB");
2613 if (pSMBr
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
2614 cifs_from_ucs2(symlinkinfo
, (__le16
*)
2615 (reparse_buf
->LinkNamesBuf
+
2616 reparse_buf
->TargetNameOffset
),
2618 reparse_buf
->TargetNameLen
,
2620 } else { /* ASCII names */
2621 strncpy(symlinkinfo
,
2622 reparse_buf
->LinkNamesBuf
+
2623 reparse_buf
->TargetNameOffset
,
2624 min_t(const int, buflen
,
2625 reparse_buf
->TargetNameLen
));
2629 cFYI(1, "Invalid return data count on "
2630 "get reparse info ioctl");
2632 symlinkinfo
[buflen
] = 0; /* just in case so the caller
2633 does not go off the end of the buffer */
2634 cFYI(1, "readlink result - %s", symlinkinfo
);
2638 cifs_buf_release(pSMB
);
2640 /* Note: On -EAGAIN error only caller can retry on handle based calls
2641 since file handle passed in no longer valid */
2645 #endif /* CIFS_EXPERIMENTAL */
2647 #ifdef CONFIG_CIFS_POSIX
2649 /*Convert an Access Control Entry from wire format to local POSIX xattr format*/
2650 static void cifs_convert_ace(posix_acl_xattr_entry
*ace
,
2651 struct cifs_posix_ace
*cifs_ace
)
2653 /* u8 cifs fields do not need le conversion */
2654 ace
->e_perm
= cpu_to_le16(cifs_ace
->cifs_e_perm
);
2655 ace
->e_tag
= cpu_to_le16(cifs_ace
->cifs_e_tag
);
2656 ace
->e_id
= cpu_to_le32(le64_to_cpu(cifs_ace
->cifs_uid
));
2657 /* cFYI(1, "perm %d tag %d id %d",ace->e_perm,ace->e_tag,ace->e_id); */
2662 /* Convert ACL from CIFS POSIX wire format to local Linux POSIX ACL xattr */
2663 static int cifs_copy_posix_acl(char *trgt
, char *src
, const int buflen
,
2664 const int acl_type
, const int size_of_data_area
)
2669 struct cifs_posix_ace
*pACE
;
2670 struct cifs_posix_acl
*cifs_acl
= (struct cifs_posix_acl
*)src
;
2671 posix_acl_xattr_header
*local_acl
= (posix_acl_xattr_header
*)trgt
;
2673 if (le16_to_cpu(cifs_acl
->version
) != CIFS_ACL_VERSION
)
2676 if (acl_type
& ACL_TYPE_ACCESS
) {
2677 count
= le16_to_cpu(cifs_acl
->access_entry_count
);
2678 pACE
= &cifs_acl
->ace_array
[0];
2679 size
= sizeof(struct cifs_posix_acl
);
2680 size
+= sizeof(struct cifs_posix_ace
) * count
;
2681 /* check if we would go beyond end of SMB */
2682 if (size_of_data_area
< size
) {
2683 cFYI(1, "bad CIFS POSIX ACL size %d vs. %d",
2684 size_of_data_area
, size
);
2687 } else if (acl_type
& ACL_TYPE_DEFAULT
) {
2688 count
= le16_to_cpu(cifs_acl
->access_entry_count
);
2689 size
= sizeof(struct cifs_posix_acl
);
2690 size
+= sizeof(struct cifs_posix_ace
) * count
;
2691 /* skip past access ACEs to get to default ACEs */
2692 pACE
= &cifs_acl
->ace_array
[count
];
2693 count
= le16_to_cpu(cifs_acl
->default_entry_count
);
2694 size
+= sizeof(struct cifs_posix_ace
) * count
;
2695 /* check if we would go beyond end of SMB */
2696 if (size_of_data_area
< size
)
2703 size
= posix_acl_xattr_size(count
);
2704 if ((buflen
== 0) || (local_acl
== NULL
)) {
2705 /* used to query ACL EA size */
2706 } else if (size
> buflen
) {
2708 } else /* buffer big enough */ {
2709 local_acl
->a_version
= cpu_to_le32(POSIX_ACL_XATTR_VERSION
);
2710 for (i
= 0; i
< count
; i
++) {
2711 cifs_convert_ace(&local_acl
->a_entries
[i
], pACE
);
2718 static __u16
convert_ace_to_cifs_ace(struct cifs_posix_ace
*cifs_ace
,
2719 const posix_acl_xattr_entry
*local_ace
)
2721 __u16 rc
= 0; /* 0 = ACL converted ok */
2723 cifs_ace
->cifs_e_perm
= le16_to_cpu(local_ace
->e_perm
);
2724 cifs_ace
->cifs_e_tag
= le16_to_cpu(local_ace
->e_tag
);
2725 /* BB is there a better way to handle the large uid? */
2726 if (local_ace
->e_id
== cpu_to_le32(-1)) {
2727 /* Probably no need to le convert -1 on any arch but can not hurt */
2728 cifs_ace
->cifs_uid
= cpu_to_le64(-1);
2730 cifs_ace
->cifs_uid
= cpu_to_le64(le32_to_cpu(local_ace
->e_id
));
2731 /*cFYI(1, "perm %d tag %d id %d",ace->e_perm,ace->e_tag,ace->e_id);*/
2735 /* Convert ACL from local Linux POSIX xattr to CIFS POSIX ACL wire format */
2736 static __u16
ACL_to_cifs_posix(char *parm_data
, const char *pACL
,
2737 const int buflen
, const int acl_type
)
2740 struct cifs_posix_acl
*cifs_acl
= (struct cifs_posix_acl
*)parm_data
;
2741 posix_acl_xattr_header
*local_acl
= (posix_acl_xattr_header
*)pACL
;
2745 if ((buflen
== 0) || (pACL
== NULL
) || (cifs_acl
== NULL
))
2748 count
= posix_acl_xattr_count((size_t)buflen
);
2749 cFYI(1, "setting acl with %d entries from buf of length %d and "
2751 count
, buflen
, le32_to_cpu(local_acl
->a_version
));
2752 if (le32_to_cpu(local_acl
->a_version
) != 2) {
2753 cFYI(1, "unknown POSIX ACL version %d",
2754 le32_to_cpu(local_acl
->a_version
));
2757 cifs_acl
->version
= cpu_to_le16(1);
2758 if (acl_type
== ACL_TYPE_ACCESS
)
2759 cifs_acl
->access_entry_count
= cpu_to_le16(count
);
2760 else if (acl_type
== ACL_TYPE_DEFAULT
)
2761 cifs_acl
->default_entry_count
= cpu_to_le16(count
);
2763 cFYI(1, "unknown ACL type %d", acl_type
);
2766 for (i
= 0; i
< count
; i
++) {
2767 rc
= convert_ace_to_cifs_ace(&cifs_acl
->ace_array
[i
],
2768 &local_acl
->a_entries
[i
]);
2770 /* ACE not converted */
2775 rc
= (__u16
)(count
* sizeof(struct cifs_posix_ace
));
2776 rc
+= sizeof(struct cifs_posix_acl
);
2777 /* BB add check to make sure ACL does not overflow SMB */
2783 CIFSSMBGetPosixACL(const int xid
, struct cifsTconInfo
*tcon
,
2784 const unsigned char *searchName
,
2785 char *acl_inf
, const int buflen
, const int acl_type
,
2786 const struct nls_table
*nls_codepage
, int remap
)
2788 /* SMB_QUERY_POSIX_ACL */
2789 TRANSACTION2_QPI_REQ
*pSMB
= NULL
;
2790 TRANSACTION2_QPI_RSP
*pSMBr
= NULL
;
2794 __u16 params
, byte_count
;
2796 cFYI(1, "In GetPosixACL (Unix) for path %s", searchName
);
2799 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
2804 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
2806 cifsConvertToUCS((__le16
*) pSMB
->FileName
, searchName
,
2807 PATH_MAX
, nls_codepage
, remap
);
2808 name_len
++; /* trailing null */
2810 pSMB
->FileName
[name_len
] = 0;
2811 pSMB
->FileName
[name_len
+1] = 0;
2812 } else { /* BB improve the check for buffer overruns BB */
2813 name_len
= strnlen(searchName
, PATH_MAX
);
2814 name_len
++; /* trailing null */
2815 strncpy(pSMB
->FileName
, searchName
, name_len
);
2818 params
= 2 /* level */ + 4 /* rsrvd */ + name_len
/* incl null */ ;
2819 pSMB
->TotalDataCount
= 0;
2820 pSMB
->MaxParameterCount
= cpu_to_le16(2);
2821 /* BB find exact max data count below from sess structure BB */
2822 pSMB
->MaxDataCount
= cpu_to_le16(4000);
2823 pSMB
->MaxSetupCount
= 0;
2827 pSMB
->Reserved2
= 0;
2828 pSMB
->ParameterOffset
= cpu_to_le16(
2829 offsetof(struct smb_com_transaction2_qpi_req
,
2830 InformationLevel
) - 4);
2831 pSMB
->DataCount
= 0;
2832 pSMB
->DataOffset
= 0;
2833 pSMB
->SetupCount
= 1;
2834 pSMB
->Reserved3
= 0;
2835 pSMB
->SubCommand
= cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION
);
2836 byte_count
= params
+ 1 /* pad */ ;
2837 pSMB
->TotalParameterCount
= cpu_to_le16(params
);
2838 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
2839 pSMB
->InformationLevel
= cpu_to_le16(SMB_QUERY_POSIX_ACL
);
2840 pSMB
->Reserved4
= 0;
2841 pSMB
->hdr
.smb_buf_length
+= byte_count
;
2842 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
2844 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
2845 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
2846 cifs_stats_inc(&tcon
->num_acl_get
);
2848 cFYI(1, "Send error in Query POSIX ACL = %d", rc
);
2850 /* decode response */
2852 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
2853 if (rc
|| (pSMBr
->ByteCount
< 2))
2854 /* BB also check enough total bytes returned */
2855 rc
= -EIO
; /* bad smb */
2857 __u16 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
2858 __u16 count
= le16_to_cpu(pSMBr
->t2
.DataCount
);
2859 rc
= cifs_copy_posix_acl(acl_inf
,
2860 (char *)&pSMBr
->hdr
.Protocol
+data_offset
,
2861 buflen
, acl_type
, count
);
2864 cifs_buf_release(pSMB
);
2871 CIFSSMBSetPosixACL(const int xid
, struct cifsTconInfo
*tcon
,
2872 const unsigned char *fileName
,
2873 const char *local_acl
, const int buflen
,
2875 const struct nls_table
*nls_codepage
, int remap
)
2877 struct smb_com_transaction2_spi_req
*pSMB
= NULL
;
2878 struct smb_com_transaction2_spi_rsp
*pSMBr
= NULL
;
2882 int bytes_returned
= 0;
2883 __u16 params
, byte_count
, data_count
, param_offset
, offset
;
2885 cFYI(1, "In SetPosixACL (Unix) for path %s", fileName
);
2887 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
2891 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
2893 cifsConvertToUCS((__le16
*) pSMB
->FileName
, fileName
,
2894 PATH_MAX
, nls_codepage
, remap
);
2895 name_len
++; /* trailing null */
2897 } else { /* BB improve the check for buffer overruns BB */
2898 name_len
= strnlen(fileName
, PATH_MAX
);
2899 name_len
++; /* trailing null */
2900 strncpy(pSMB
->FileName
, fileName
, name_len
);
2902 params
= 6 + name_len
;
2903 pSMB
->MaxParameterCount
= cpu_to_le16(2);
2904 /* BB find max SMB size from sess */
2905 pSMB
->MaxDataCount
= cpu_to_le16(1000);
2906 pSMB
->MaxSetupCount
= 0;
2910 pSMB
->Reserved2
= 0;
2911 param_offset
= offsetof(struct smb_com_transaction2_spi_req
,
2912 InformationLevel
) - 4;
2913 offset
= param_offset
+ params
;
2914 parm_data
= ((char *) &pSMB
->hdr
.Protocol
) + offset
;
2915 pSMB
->ParameterOffset
= cpu_to_le16(param_offset
);
2917 /* convert to on the wire format for POSIX ACL */
2918 data_count
= ACL_to_cifs_posix(parm_data
, local_acl
, buflen
, acl_type
);
2920 if (data_count
== 0) {
2922 goto setACLerrorExit
;
2924 pSMB
->DataOffset
= cpu_to_le16(offset
);
2925 pSMB
->SetupCount
= 1;
2926 pSMB
->Reserved3
= 0;
2927 pSMB
->SubCommand
= cpu_to_le16(TRANS2_SET_PATH_INFORMATION
);
2928 pSMB
->InformationLevel
= cpu_to_le16(SMB_SET_POSIX_ACL
);
2929 byte_count
= 3 /* pad */ + params
+ data_count
;
2930 pSMB
->DataCount
= cpu_to_le16(data_count
);
2931 pSMB
->TotalDataCount
= pSMB
->DataCount
;
2932 pSMB
->ParameterCount
= cpu_to_le16(params
);
2933 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
2934 pSMB
->Reserved4
= 0;
2935 pSMB
->hdr
.smb_buf_length
+= byte_count
;
2936 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
2937 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
2938 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
2940 cFYI(1, "Set POSIX ACL returned %d", rc
);
2943 cifs_buf_release(pSMB
);
2949 /* BB fix tabs in this function FIXME BB */
2951 CIFSGetExtAttr(const int xid
, struct cifsTconInfo
*tcon
,
2952 const int netfid
, __u64
*pExtAttrBits
, __u64
*pMask
)
2955 struct smb_t2_qfi_req
*pSMB
= NULL
;
2956 struct smb_t2_qfi_rsp
*pSMBr
= NULL
;
2958 __u16 params
, byte_count
;
2960 cFYI(1, "In GetExtAttr");
2965 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
2970 params
= 2 /* level */ + 2 /* fid */;
2971 pSMB
->t2
.TotalDataCount
= 0;
2972 pSMB
->t2
.MaxParameterCount
= cpu_to_le16(4);
2973 /* BB find exact max data count below from sess structure BB */
2974 pSMB
->t2
.MaxDataCount
= cpu_to_le16(4000);
2975 pSMB
->t2
.MaxSetupCount
= 0;
2976 pSMB
->t2
.Reserved
= 0;
2978 pSMB
->t2
.Timeout
= 0;
2979 pSMB
->t2
.Reserved2
= 0;
2980 pSMB
->t2
.ParameterOffset
= cpu_to_le16(offsetof(struct smb_t2_qfi_req
,
2982 pSMB
->t2
.DataCount
= 0;
2983 pSMB
->t2
.DataOffset
= 0;
2984 pSMB
->t2
.SetupCount
= 1;
2985 pSMB
->t2
.Reserved3
= 0;
2986 pSMB
->t2
.SubCommand
= cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION
);
2987 byte_count
= params
+ 1 /* pad */ ;
2988 pSMB
->t2
.TotalParameterCount
= cpu_to_le16(params
);
2989 pSMB
->t2
.ParameterCount
= pSMB
->t2
.TotalParameterCount
;
2990 pSMB
->InformationLevel
= cpu_to_le16(SMB_QUERY_ATTR_FLAGS
);
2993 pSMB
->hdr
.smb_buf_length
+= byte_count
;
2994 pSMB
->t2
.ByteCount
= cpu_to_le16(byte_count
);
2996 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
2997 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
2999 cFYI(1, "error %d in GetExtAttr", rc
);
3001 /* decode response */
3002 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
3003 if (rc
|| (pSMBr
->ByteCount
< 2))
3004 /* BB also check enough total bytes returned */
3005 /* If rc should we check for EOPNOSUPP and
3006 disable the srvino flag? or in caller? */
3007 rc
= -EIO
; /* bad smb */
3009 __u16 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
3010 __u16 count
= le16_to_cpu(pSMBr
->t2
.DataCount
);
3011 struct file_chattr_info
*pfinfo
;
3012 /* BB Do we need a cast or hash here ? */
3014 cFYI(1, "Illegal size ret in GetExtAttr");
3018 pfinfo
= (struct file_chattr_info
*)
3019 (data_offset
+ (char *) &pSMBr
->hdr
.Protocol
);
3020 *pExtAttrBits
= le64_to_cpu(pfinfo
->mode
);
3021 *pMask
= le64_to_cpu(pfinfo
->mask
);
3025 cifs_buf_release(pSMB
);
3027 goto GetExtAttrRetry
;
3031 #endif /* CONFIG_POSIX */
3033 #ifdef CONFIG_CIFS_EXPERIMENTAL
3034 /* Get Security Descriptor (by handle) from remote server for a file or dir */
3036 CIFSSMBGetCIFSACL(const int xid
, struct cifsTconInfo
*tcon
, __u16 fid
,
3037 struct cifs_ntsd
**acl_inf
, __u32
*pbuflen
)
3041 QUERY_SEC_DESC_REQ
*pSMB
;
3044 cFYI(1, "GetCifsACL");
3049 rc
= smb_init_nttransact(NT_TRANSACT_QUERY_SECURITY_DESC
, 0,
3050 8 /* parm len */, tcon
, (void **) &pSMB
);
3054 pSMB
->MaxParameterCount
= cpu_to_le32(4);
3055 /* BB TEST with big acls that might need to be e.g. larger than 16K */
3056 pSMB
->MaxSetupCount
= 0;
3057 pSMB
->Fid
= fid
; /* file handle always le */
3058 pSMB
->AclFlags
= cpu_to_le32(CIFS_ACL_OWNER
| CIFS_ACL_GROUP
|
3060 pSMB
->ByteCount
= cpu_to_le16(11); /* 3 bytes pad + 8 bytes parm */
3061 pSMB
->hdr
.smb_buf_length
+= 11;
3062 iov
[0].iov_base
= (char *)pSMB
;
3063 iov
[0].iov_len
= pSMB
->hdr
.smb_buf_length
+ 4;
3065 rc
= SendReceive2(xid
, tcon
->ses
, iov
, 1 /* num iovec */, &buf_type
,
3067 cifs_stats_inc(&tcon
->num_acl_get
);
3069 cFYI(1, "Send error in QuerySecDesc = %d", rc
);
3070 } else { /* decode response */
3074 struct smb_com_ntransact_rsp
*pSMBr
;
3077 /* validate_nttransact */
3078 rc
= validate_ntransact(iov
[0].iov_base
, (char **)&parm
,
3079 &pdata
, &parm_len
, pbuflen
);
3082 pSMBr
= (struct smb_com_ntransact_rsp
*)iov
[0].iov_base
;
3084 cFYI(1, "smb %p parm %p data %p", pSMBr
, parm
, *acl_inf
);
3086 if (le32_to_cpu(pSMBr
->ParameterCount
) != 4) {
3087 rc
= -EIO
; /* bad smb */
3092 /* BB check that data area is minimum length and as big as acl_len */
3094 acl_len
= le32_to_cpu(*parm
);
3095 if (acl_len
!= *pbuflen
) {
3096 cERROR(1, "acl length %d does not match %d",
3098 if (*pbuflen
> acl_len
)
3102 /* check if buffer is big enough for the acl
3103 header followed by the smallest SID */
3104 if ((*pbuflen
< sizeof(struct cifs_ntsd
) + 8) ||
3105 (*pbuflen
>= 64 * 1024)) {
3106 cERROR(1, "bad acl length %d", *pbuflen
);
3110 *acl_inf
= kmalloc(*pbuflen
, GFP_KERNEL
);
3111 if (*acl_inf
== NULL
) {
3115 memcpy(*acl_inf
, pdata
, *pbuflen
);
3119 if (buf_type
== CIFS_SMALL_BUFFER
)
3120 cifs_small_buf_release(iov
[0].iov_base
);
3121 else if (buf_type
== CIFS_LARGE_BUFFER
)
3122 cifs_buf_release(iov
[0].iov_base
);
3123 /* cifs_small_buf_release(pSMB); */ /* Freed earlier now in SendReceive2 */
3128 CIFSSMBSetCIFSACL(const int xid
, struct cifsTconInfo
*tcon
, __u16 fid
,
3129 struct cifs_ntsd
*pntsd
, __u32 acllen
)
3131 __u16 byte_count
, param_count
, data_count
, param_offset
, data_offset
;
3133 int bytes_returned
= 0;
3134 SET_SEC_DESC_REQ
*pSMB
= NULL
;
3135 NTRANSACT_RSP
*pSMBr
= NULL
;
3138 rc
= smb_init(SMB_COM_NT_TRANSACT
, 19, tcon
, (void **) &pSMB
,
3143 pSMB
->MaxSetupCount
= 0;
3147 param_offset
= offsetof(struct smb_com_transaction_ssec_req
, Fid
) - 4;
3148 data_count
= acllen
;
3149 data_offset
= param_offset
+ param_count
;
3150 byte_count
= 3 /* pad */ + param_count
;
3152 pSMB
->DataCount
= cpu_to_le32(data_count
);
3153 pSMB
->TotalDataCount
= pSMB
->DataCount
;
3154 pSMB
->MaxParameterCount
= cpu_to_le32(4);
3155 pSMB
->MaxDataCount
= cpu_to_le32(16384);
3156 pSMB
->ParameterCount
= cpu_to_le32(param_count
);
3157 pSMB
->ParameterOffset
= cpu_to_le32(param_offset
);
3158 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
3159 pSMB
->DataOffset
= cpu_to_le32(data_offset
);
3160 pSMB
->SetupCount
= 0;
3161 pSMB
->SubCommand
= cpu_to_le16(NT_TRANSACT_SET_SECURITY_DESC
);
3162 pSMB
->ByteCount
= cpu_to_le16(byte_count
+data_count
);
3164 pSMB
->Fid
= fid
; /* file handle always le */
3165 pSMB
->Reserved2
= 0;
3166 pSMB
->AclFlags
= cpu_to_le32(CIFS_ACL_DACL
);
3168 if (pntsd
&& acllen
) {
3169 memcpy((char *) &pSMBr
->hdr
.Protocol
+ data_offset
,
3172 pSMB
->hdr
.smb_buf_length
+= (byte_count
+ data_count
);
3175 pSMB
->hdr
.smb_buf_length
+= byte_count
;
3177 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
3178 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
3180 cFYI(1, "SetCIFSACL bytes_returned: %d, rc: %d", bytes_returned
, rc
);
3182 cFYI(1, "Set CIFS ACL returned %d", rc
);
3183 cifs_buf_release(pSMB
);
3186 goto setCifsAclRetry
;
3191 #endif /* CONFIG_CIFS_EXPERIMENTAL */
3193 /* Legacy Query Path Information call for lookup to old servers such
3195 int SMBQueryInformation(const int xid
, struct cifsTconInfo
*tcon
,
3196 const unsigned char *searchName
,
3197 FILE_ALL_INFO
*pFinfo
,
3198 const struct nls_table
*nls_codepage
, int remap
)
3200 QUERY_INFORMATION_REQ
*pSMB
;
3201 QUERY_INFORMATION_RSP
*pSMBr
;
3206 cFYI(1, "In SMBQPath path %s", searchName
);
3208 rc
= smb_init(SMB_COM_QUERY_INFORMATION
, 0, tcon
, (void **) &pSMB
,
3213 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
3215 cifsConvertToUCS((__le16
*) pSMB
->FileName
, searchName
,
3216 PATH_MAX
, nls_codepage
, remap
);
3217 name_len
++; /* trailing null */
3220 name_len
= strnlen(searchName
, PATH_MAX
);
3221 name_len
++; /* trailing null */
3222 strncpy(pSMB
->FileName
, searchName
, name_len
);
3224 pSMB
->BufferFormat
= 0x04;
3225 name_len
++; /* account for buffer type byte */
3226 pSMB
->hdr
.smb_buf_length
+= (__u16
) name_len
;
3227 pSMB
->ByteCount
= cpu_to_le16(name_len
);
3229 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
3230 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
3232 cFYI(1, "Send error in QueryInfo = %d", rc
);
3233 } else if (pFinfo
) {
3235 __u32 time
= le32_to_cpu(pSMBr
->last_write_time
);
3237 /* decode response */
3238 /* BB FIXME - add time zone adjustment BB */
3239 memset(pFinfo
, 0, sizeof(FILE_ALL_INFO
));
3242 /* decode time fields */
3243 pFinfo
->ChangeTime
= cpu_to_le64(cifs_UnixTimeToNT(ts
));
3244 pFinfo
->LastWriteTime
= pFinfo
->ChangeTime
;
3245 pFinfo
->LastAccessTime
= 0;
3246 pFinfo
->AllocationSize
=
3247 cpu_to_le64(le32_to_cpu(pSMBr
->size
));
3248 pFinfo
->EndOfFile
= pFinfo
->AllocationSize
;
3249 pFinfo
->Attributes
=
3250 cpu_to_le32(le16_to_cpu(pSMBr
->attr
));
3252 rc
= -EIO
; /* bad buffer passed in */
3254 cifs_buf_release(pSMB
);
3263 CIFSSMBQFileInfo(const int xid
, struct cifsTconInfo
*tcon
,
3264 u16 netfid
, FILE_ALL_INFO
*pFindData
)
3266 struct smb_t2_qfi_req
*pSMB
= NULL
;
3267 struct smb_t2_qfi_rsp
*pSMBr
= NULL
;
3270 __u16 params
, byte_count
;
3273 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
3278 params
= 2 /* level */ + 2 /* fid */;
3279 pSMB
->t2
.TotalDataCount
= 0;
3280 pSMB
->t2
.MaxParameterCount
= cpu_to_le16(4);
3281 /* BB find exact max data count below from sess structure BB */
3282 pSMB
->t2
.MaxDataCount
= cpu_to_le16(CIFSMaxBufSize
);
3283 pSMB
->t2
.MaxSetupCount
= 0;
3284 pSMB
->t2
.Reserved
= 0;
3286 pSMB
->t2
.Timeout
= 0;
3287 pSMB
->t2
.Reserved2
= 0;
3288 pSMB
->t2
.ParameterOffset
= cpu_to_le16(offsetof(struct smb_t2_qfi_req
,
3290 pSMB
->t2
.DataCount
= 0;
3291 pSMB
->t2
.DataOffset
= 0;
3292 pSMB
->t2
.SetupCount
= 1;
3293 pSMB
->t2
.Reserved3
= 0;
3294 pSMB
->t2
.SubCommand
= cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION
);
3295 byte_count
= params
+ 1 /* pad */ ;
3296 pSMB
->t2
.TotalParameterCount
= cpu_to_le16(params
);
3297 pSMB
->t2
.ParameterCount
= pSMB
->t2
.TotalParameterCount
;
3298 pSMB
->InformationLevel
= cpu_to_le16(SMB_QUERY_FILE_ALL_INFO
);
3301 pSMB
->hdr
.smb_buf_length
+= byte_count
;
3303 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
3304 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
3306 cFYI(1, "Send error in QPathInfo = %d", rc
);
3307 } else { /* decode response */
3308 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
3310 if (rc
) /* BB add auto retry on EOPNOTSUPP? */
3312 else if (pSMBr
->ByteCount
< 40)
3313 rc
= -EIO
; /* bad smb */
3314 else if (pFindData
) {
3315 __u16 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
3316 memcpy((char *) pFindData
,
3317 (char *) &pSMBr
->hdr
.Protocol
+
3318 data_offset
, sizeof(FILE_ALL_INFO
));
3322 cifs_buf_release(pSMB
);
3324 goto QFileInfoRetry
;
3330 CIFSSMBQPathInfo(const int xid
, struct cifsTconInfo
*tcon
,
3331 const unsigned char *searchName
,
3332 FILE_ALL_INFO
*pFindData
,
3333 int legacy
/* old style infolevel */,
3334 const struct nls_table
*nls_codepage
, int remap
)
3336 /* level 263 SMB_QUERY_FILE_ALL_INFO */
3337 TRANSACTION2_QPI_REQ
*pSMB
= NULL
;
3338 TRANSACTION2_QPI_RSP
*pSMBr
= NULL
;
3342 __u16 params
, byte_count
;
3344 /* cFYI(1, "In QPathInfo path %s", searchName); */
3346 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
3351 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
3353 cifsConvertToUCS((__le16
*) pSMB
->FileName
, searchName
,
3354 PATH_MAX
, nls_codepage
, remap
);
3355 name_len
++; /* trailing null */
3357 } else { /* BB improve the check for buffer overruns BB */
3358 name_len
= strnlen(searchName
, PATH_MAX
);
3359 name_len
++; /* trailing null */
3360 strncpy(pSMB
->FileName
, searchName
, name_len
);
3363 params
= 2 /* level */ + 4 /* reserved */ + name_len
/* includes NUL */;
3364 pSMB
->TotalDataCount
= 0;
3365 pSMB
->MaxParameterCount
= cpu_to_le16(2);
3366 /* BB find exact max SMB PDU from sess structure BB */
3367 pSMB
->MaxDataCount
= cpu_to_le16(4000);
3368 pSMB
->MaxSetupCount
= 0;
3372 pSMB
->Reserved2
= 0;
3373 pSMB
->ParameterOffset
= cpu_to_le16(offsetof(
3374 struct smb_com_transaction2_qpi_req
, InformationLevel
) - 4);
3375 pSMB
->DataCount
= 0;
3376 pSMB
->DataOffset
= 0;
3377 pSMB
->SetupCount
= 1;
3378 pSMB
->Reserved3
= 0;
3379 pSMB
->SubCommand
= cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION
);
3380 byte_count
= params
+ 1 /* pad */ ;
3381 pSMB
->TotalParameterCount
= cpu_to_le16(params
);
3382 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
3384 pSMB
->InformationLevel
= cpu_to_le16(SMB_INFO_STANDARD
);
3386 pSMB
->InformationLevel
= cpu_to_le16(SMB_QUERY_FILE_ALL_INFO
);
3387 pSMB
->Reserved4
= 0;
3388 pSMB
->hdr
.smb_buf_length
+= byte_count
;
3389 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
3391 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
3392 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
3394 cFYI(1, "Send error in QPathInfo = %d", rc
);
3395 } else { /* decode response */
3396 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
3398 if (rc
) /* BB add auto retry on EOPNOTSUPP? */
3400 else if (!legacy
&& (pSMBr
->ByteCount
< 40))
3401 rc
= -EIO
; /* bad smb */
3402 else if (legacy
&& (pSMBr
->ByteCount
< 24))
3403 rc
= -EIO
; /* 24 or 26 expected but we do not read
3405 else if (pFindData
) {
3407 __u16 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
3409 /* On legacy responses we do not read the last field,
3410 EAsize, fortunately since it varies by subdialect and
3411 also note it differs on Set vs. Get, ie two bytes or 4
3412 bytes depending but we don't care here */
3414 size
= sizeof(FILE_INFO_STANDARD
);
3416 size
= sizeof(FILE_ALL_INFO
);
3417 memcpy((char *) pFindData
,
3418 (char *) &pSMBr
->hdr
.Protocol
+
3423 cifs_buf_release(pSMB
);
3425 goto QPathInfoRetry
;
3431 CIFSSMBUnixQFileInfo(const int xid
, struct cifsTconInfo
*tcon
,
3432 u16 netfid
, FILE_UNIX_BASIC_INFO
*pFindData
)
3434 struct smb_t2_qfi_req
*pSMB
= NULL
;
3435 struct smb_t2_qfi_rsp
*pSMBr
= NULL
;
3438 __u16 params
, byte_count
;
3441 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
3446 params
= 2 /* level */ + 2 /* fid */;
3447 pSMB
->t2
.TotalDataCount
= 0;
3448 pSMB
->t2
.MaxParameterCount
= cpu_to_le16(4);
3449 /* BB find exact max data count below from sess structure BB */
3450 pSMB
->t2
.MaxDataCount
= cpu_to_le16(CIFSMaxBufSize
);
3451 pSMB
->t2
.MaxSetupCount
= 0;
3452 pSMB
->t2
.Reserved
= 0;
3454 pSMB
->t2
.Timeout
= 0;
3455 pSMB
->t2
.Reserved2
= 0;
3456 pSMB
->t2
.ParameterOffset
= cpu_to_le16(offsetof(struct smb_t2_qfi_req
,
3458 pSMB
->t2
.DataCount
= 0;
3459 pSMB
->t2
.DataOffset
= 0;
3460 pSMB
->t2
.SetupCount
= 1;
3461 pSMB
->t2
.Reserved3
= 0;
3462 pSMB
->t2
.SubCommand
= cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION
);
3463 byte_count
= params
+ 1 /* pad */ ;
3464 pSMB
->t2
.TotalParameterCount
= cpu_to_le16(params
);
3465 pSMB
->t2
.ParameterCount
= pSMB
->t2
.TotalParameterCount
;
3466 pSMB
->InformationLevel
= cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC
);
3469 pSMB
->hdr
.smb_buf_length
+= byte_count
;
3471 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
3472 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
3474 cFYI(1, "Send error in QPathInfo = %d", rc
);
3475 } else { /* decode response */
3476 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
3478 if (rc
|| (pSMBr
->ByteCount
< sizeof(FILE_UNIX_BASIC_INFO
))) {
3479 cERROR(1, "Malformed FILE_UNIX_BASIC_INFO response.\n"
3480 "Unix Extensions can be disabled on mount "
3481 "by specifying the nosfu mount option.");
3482 rc
= -EIO
; /* bad smb */
3484 __u16 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
3485 memcpy((char *) pFindData
,
3486 (char *) &pSMBr
->hdr
.Protocol
+
3488 sizeof(FILE_UNIX_BASIC_INFO
));
3492 cifs_buf_release(pSMB
);
3494 goto UnixQFileInfoRetry
;
3500 CIFSSMBUnixQPathInfo(const int xid
, struct cifsTconInfo
*tcon
,
3501 const unsigned char *searchName
,
3502 FILE_UNIX_BASIC_INFO
*pFindData
,
3503 const struct nls_table
*nls_codepage
, int remap
)
3505 /* SMB_QUERY_FILE_UNIX_BASIC */
3506 TRANSACTION2_QPI_REQ
*pSMB
= NULL
;
3507 TRANSACTION2_QPI_RSP
*pSMBr
= NULL
;
3509 int bytes_returned
= 0;
3511 __u16 params
, byte_count
;
3513 cFYI(1, "In QPathInfo (Unix) the path %s", searchName
);
3515 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
3520 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
3522 cifsConvertToUCS((__le16
*) pSMB
->FileName
, searchName
,
3523 PATH_MAX
, nls_codepage
, remap
);
3524 name_len
++; /* trailing null */
3526 } else { /* BB improve the check for buffer overruns BB */
3527 name_len
= strnlen(searchName
, PATH_MAX
);
3528 name_len
++; /* trailing null */
3529 strncpy(pSMB
->FileName
, searchName
, name_len
);
3532 params
= 2 /* level */ + 4 /* reserved */ + name_len
/* includes NUL */;
3533 pSMB
->TotalDataCount
= 0;
3534 pSMB
->MaxParameterCount
= cpu_to_le16(2);
3535 /* BB find exact max SMB PDU from sess structure BB */
3536 pSMB
->MaxDataCount
= cpu_to_le16(4000);
3537 pSMB
->MaxSetupCount
= 0;
3541 pSMB
->Reserved2
= 0;
3542 pSMB
->ParameterOffset
= cpu_to_le16(offsetof(
3543 struct smb_com_transaction2_qpi_req
, InformationLevel
) - 4);
3544 pSMB
->DataCount
= 0;
3545 pSMB
->DataOffset
= 0;
3546 pSMB
->SetupCount
= 1;
3547 pSMB
->Reserved3
= 0;
3548 pSMB
->SubCommand
= cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION
);
3549 byte_count
= params
+ 1 /* pad */ ;
3550 pSMB
->TotalParameterCount
= cpu_to_le16(params
);
3551 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
3552 pSMB
->InformationLevel
= cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC
);
3553 pSMB
->Reserved4
= 0;
3554 pSMB
->hdr
.smb_buf_length
+= byte_count
;
3555 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
3557 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
3558 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
3560 cFYI(1, "Send error in QPathInfo = %d", rc
);
3561 } else { /* decode response */
3562 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
3564 if (rc
|| (pSMBr
->ByteCount
< sizeof(FILE_UNIX_BASIC_INFO
))) {
3565 cERROR(1, "Malformed FILE_UNIX_BASIC_INFO response.\n"
3566 "Unix Extensions can be disabled on mount "
3567 "by specifying the nosfu mount option.");
3568 rc
= -EIO
; /* bad smb */
3570 __u16 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
3571 memcpy((char *) pFindData
,
3572 (char *) &pSMBr
->hdr
.Protocol
+
3574 sizeof(FILE_UNIX_BASIC_INFO
));
3577 cifs_buf_release(pSMB
);
3579 goto UnixQPathInfoRetry
;
3584 /* xid, tcon, searchName and codepage are input parms, rest are returned */
3586 CIFSFindFirst(const int xid
, struct cifsTconInfo
*tcon
,
3587 const char *searchName
,
3588 const struct nls_table
*nls_codepage
,
3590 struct cifs_search_info
*psrch_inf
, int remap
, const char dirsep
)
3592 /* level 257 SMB_ */
3593 TRANSACTION2_FFIRST_REQ
*pSMB
= NULL
;
3594 TRANSACTION2_FFIRST_RSP
*pSMBr
= NULL
;
3595 T2_FFIRST_RSP_PARMS
*parms
;
3597 int bytes_returned
= 0;
3599 __u16 params
, byte_count
;
3601 cFYI(1, "In FindFirst for %s", searchName
);
3604 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
3609 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
3611 cifsConvertToUCS((__le16
*) pSMB
->FileName
, searchName
,
3612 PATH_MAX
, nls_codepage
, remap
);
3613 /* We can not add the asterik earlier in case
3614 it got remapped to 0xF03A as if it were part of the
3615 directory name instead of a wildcard */
3617 pSMB
->FileName
[name_len
] = dirsep
;
3618 pSMB
->FileName
[name_len
+1] = 0;
3619 pSMB
->FileName
[name_len
+2] = '*';
3620 pSMB
->FileName
[name_len
+3] = 0;
3621 name_len
+= 4; /* now the trailing null */
3622 pSMB
->FileName
[name_len
] = 0; /* null terminate just in case */
3623 pSMB
->FileName
[name_len
+1] = 0;
3625 } else { /* BB add check for overrun of SMB buf BB */
3626 name_len
= strnlen(searchName
, PATH_MAX
);
3627 /* BB fix here and in unicode clause above ie
3628 if (name_len > buffersize-header)
3629 free buffer exit; BB */
3630 strncpy(pSMB
->FileName
, searchName
, name_len
);
3631 pSMB
->FileName
[name_len
] = dirsep
;
3632 pSMB
->FileName
[name_len
+1] = '*';
3633 pSMB
->FileName
[name_len
+2] = 0;
3637 params
= 12 + name_len
/* includes null */ ;
3638 pSMB
->TotalDataCount
= 0; /* no EAs */
3639 pSMB
->MaxParameterCount
= cpu_to_le16(10);
3640 pSMB
->MaxDataCount
= cpu_to_le16((tcon
->ses
->server
->maxBuf
-
3641 MAX_CIFS_HDR_SIZE
) & 0xFFFFFF00);
3642 pSMB
->MaxSetupCount
= 0;
3646 pSMB
->Reserved2
= 0;
3647 byte_count
= params
+ 1 /* pad */ ;
3648 pSMB
->TotalParameterCount
= cpu_to_le16(params
);
3649 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
3650 pSMB
->ParameterOffset
= cpu_to_le16(
3651 offsetof(struct smb_com_transaction2_ffirst_req
, SearchAttributes
)
3653 pSMB
->DataCount
= 0;
3654 pSMB
->DataOffset
= 0;
3655 pSMB
->SetupCount
= 1; /* one byte, no need to make endian neutral */
3656 pSMB
->Reserved3
= 0;
3657 pSMB
->SubCommand
= cpu_to_le16(TRANS2_FIND_FIRST
);
3658 pSMB
->SearchAttributes
=
3659 cpu_to_le16(ATTR_READONLY
| ATTR_HIDDEN
| ATTR_SYSTEM
|
3661 pSMB
->SearchCount
= cpu_to_le16(CIFSMaxBufSize
/sizeof(FILE_UNIX_INFO
));
3662 pSMB
->SearchFlags
= cpu_to_le16(CIFS_SEARCH_CLOSE_AT_END
|
3663 CIFS_SEARCH_RETURN_RESUME
);
3664 pSMB
->InformationLevel
= cpu_to_le16(psrch_inf
->info_level
);
3666 /* BB what should we set StorageType to? Does it matter? BB */
3667 pSMB
->SearchStorageType
= 0;
3668 pSMB
->hdr
.smb_buf_length
+= byte_count
;
3669 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
3671 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
3672 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
3673 cifs_stats_inc(&tcon
->num_ffirst
);
3675 if (rc
) {/* BB add logic to retry regular search if Unix search
3676 rejected unexpectedly by server */
3677 /* BB Add code to handle unsupported level rc */
3678 cFYI(1, "Error in FindFirst = %d", rc
);
3680 cifs_buf_release(pSMB
);
3682 /* BB eventually could optimize out free and realloc of buf */
3685 goto findFirstRetry
;
3686 } else { /* decode response */
3687 /* BB remember to free buffer if error BB */
3688 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
3692 if (pSMBr
->hdr
.Flags2
& SMBFLG2_UNICODE
)
3693 psrch_inf
->unicode
= true;
3695 psrch_inf
->unicode
= false;
3697 psrch_inf
->ntwrk_buf_start
= (char *)pSMBr
;
3698 psrch_inf
->smallBuf
= 0;
3699 psrch_inf
->srch_entries_start
=
3700 (char *) &pSMBr
->hdr
.Protocol
+
3701 le16_to_cpu(pSMBr
->t2
.DataOffset
);
3702 parms
= (T2_FFIRST_RSP_PARMS
*)((char *) &pSMBr
->hdr
.Protocol
+
3703 le16_to_cpu(pSMBr
->t2
.ParameterOffset
));
3705 if (parms
->EndofSearch
)
3706 psrch_inf
->endOfSearch
= true;
3708 psrch_inf
->endOfSearch
= false;
3710 psrch_inf
->entries_in_buffer
=
3711 le16_to_cpu(parms
->SearchCount
);
3712 psrch_inf
->index_of_last_entry
= 2 /* skip . and .. */ +
3713 psrch_inf
->entries_in_buffer
;
3714 lnoff
= le16_to_cpu(parms
->LastNameOffset
);
3715 if (tcon
->ses
->server
->maxBuf
- MAX_CIFS_HDR_SIZE
<
3717 cERROR(1, "ignoring corrupt resume name");
3718 psrch_inf
->last_entry
= NULL
;
3722 psrch_inf
->last_entry
= psrch_inf
->srch_entries_start
+
3725 *pnetfid
= parms
->SearchHandle
;
3727 cifs_buf_release(pSMB
);
3734 int CIFSFindNext(const int xid
, struct cifsTconInfo
*tcon
,
3735 __u16 searchHandle
, struct cifs_search_info
*psrch_inf
)
3737 TRANSACTION2_FNEXT_REQ
*pSMB
= NULL
;
3738 TRANSACTION2_FNEXT_RSP
*pSMBr
= NULL
;
3739 T2_FNEXT_RSP_PARMS
*parms
;
3740 char *response_data
;
3742 int bytes_returned
, name_len
;
3743 __u16 params
, byte_count
;
3745 cFYI(1, "In FindNext");
3747 if (psrch_inf
->endOfSearch
)
3750 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
3755 params
= 14; /* includes 2 bytes of null string, converted to LE below*/
3757 pSMB
->TotalDataCount
= 0; /* no EAs */
3758 pSMB
->MaxParameterCount
= cpu_to_le16(8);
3759 pSMB
->MaxDataCount
=
3760 cpu_to_le16((tcon
->ses
->server
->maxBuf
- MAX_CIFS_HDR_SIZE
) &
3762 pSMB
->MaxSetupCount
= 0;
3766 pSMB
->Reserved2
= 0;
3767 pSMB
->ParameterOffset
= cpu_to_le16(
3768 offsetof(struct smb_com_transaction2_fnext_req
,SearchHandle
) - 4);
3769 pSMB
->DataCount
= 0;
3770 pSMB
->DataOffset
= 0;
3771 pSMB
->SetupCount
= 1;
3772 pSMB
->Reserved3
= 0;
3773 pSMB
->SubCommand
= cpu_to_le16(TRANS2_FIND_NEXT
);
3774 pSMB
->SearchHandle
= searchHandle
; /* always kept as le */
3776 cpu_to_le16(CIFSMaxBufSize
/ sizeof(FILE_UNIX_INFO
));
3777 pSMB
->InformationLevel
= cpu_to_le16(psrch_inf
->info_level
);
3778 pSMB
->ResumeKey
= psrch_inf
->resume_key
;
3780 cpu_to_le16(CIFS_SEARCH_CLOSE_AT_END
| CIFS_SEARCH_RETURN_RESUME
);
3782 name_len
= psrch_inf
->resume_name_len
;
3784 if (name_len
< PATH_MAX
) {
3785 memcpy(pSMB
->ResumeFileName
, psrch_inf
->presume_name
, name_len
);
3786 byte_count
+= name_len
;
3787 /* 14 byte parm len above enough for 2 byte null terminator */
3788 pSMB
->ResumeFileName
[name_len
] = 0;
3789 pSMB
->ResumeFileName
[name_len
+1] = 0;
3792 goto FNext2_err_exit
;
3794 byte_count
= params
+ 1 /* pad */ ;
3795 pSMB
->TotalParameterCount
= cpu_to_le16(params
);
3796 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
3797 pSMB
->hdr
.smb_buf_length
+= byte_count
;
3798 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
3800 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
3801 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
3802 cifs_stats_inc(&tcon
->num_fnext
);
3805 psrch_inf
->endOfSearch
= true;
3806 cifs_buf_release(pSMB
);
3807 rc
= 0; /* search probably was closed at end of search*/
3809 cFYI(1, "FindNext returned = %d", rc
);
3810 } else { /* decode response */
3811 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
3816 /* BB fixme add lock for file (srch_info) struct here */
3817 if (pSMBr
->hdr
.Flags2
& SMBFLG2_UNICODE
)
3818 psrch_inf
->unicode
= true;
3820 psrch_inf
->unicode
= false;
3821 response_data
= (char *) &pSMBr
->hdr
.Protocol
+
3822 le16_to_cpu(pSMBr
->t2
.ParameterOffset
);
3823 parms
= (T2_FNEXT_RSP_PARMS
*)response_data
;
3824 response_data
= (char *)&pSMBr
->hdr
.Protocol
+
3825 le16_to_cpu(pSMBr
->t2
.DataOffset
);
3826 if (psrch_inf
->smallBuf
)
3827 cifs_small_buf_release(
3828 psrch_inf
->ntwrk_buf_start
);
3830 cifs_buf_release(psrch_inf
->ntwrk_buf_start
);
3831 psrch_inf
->srch_entries_start
= response_data
;
3832 psrch_inf
->ntwrk_buf_start
= (char *)pSMB
;
3833 psrch_inf
->smallBuf
= 0;
3834 if (parms
->EndofSearch
)
3835 psrch_inf
->endOfSearch
= true;
3837 psrch_inf
->endOfSearch
= false;
3838 psrch_inf
->entries_in_buffer
=
3839 le16_to_cpu(parms
->SearchCount
);
3840 psrch_inf
->index_of_last_entry
+=
3841 psrch_inf
->entries_in_buffer
;
3842 lnoff
= le16_to_cpu(parms
->LastNameOffset
);
3843 if (tcon
->ses
->server
->maxBuf
- MAX_CIFS_HDR_SIZE
<
3845 cERROR(1, "ignoring corrupt resume name");
3846 psrch_inf
->last_entry
= NULL
;
3849 psrch_inf
->last_entry
=
3850 psrch_inf
->srch_entries_start
+ lnoff
;
3852 /* cFYI(1, "fnxt2 entries in buf %d index_of_last %d",
3853 psrch_inf->entries_in_buffer, psrch_inf->index_of_last_entry); */
3855 /* BB fixme add unlock here */
3860 /* BB On error, should we leave previous search buf (and count and
3861 last entry fields) intact or free the previous one? */
3863 /* Note: On -EAGAIN error only caller can retry on handle based calls
3864 since file handle passed in no longer valid */
3867 cifs_buf_release(pSMB
);
3872 CIFSFindClose(const int xid
, struct cifsTconInfo
*tcon
,
3873 const __u16 searchHandle
)
3876 FINDCLOSE_REQ
*pSMB
= NULL
;
3878 cFYI(1, "In CIFSSMBFindClose");
3879 rc
= small_smb_init(SMB_COM_FIND_CLOSE2
, 1, tcon
, (void **)&pSMB
);
3881 /* no sense returning error if session restarted
3882 as file handle has been closed */
3888 pSMB
->FileID
= searchHandle
;
3889 pSMB
->ByteCount
= 0;
3890 rc
= SendReceiveNoRsp(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
, 0);
3892 cERROR(1, "Send error in FindClose = %d", rc
);
3894 cifs_stats_inc(&tcon
->num_fclose
);
3896 /* Since session is dead, search handle closed on server already */
3904 CIFSGetSrvInodeNumber(const int xid
, struct cifsTconInfo
*tcon
,
3905 const unsigned char *searchName
,
3906 __u64
*inode_number
,
3907 const struct nls_table
*nls_codepage
, int remap
)
3910 TRANSACTION2_QPI_REQ
*pSMB
= NULL
;
3911 TRANSACTION2_QPI_RSP
*pSMBr
= NULL
;
3912 int name_len
, bytes_returned
;
3913 __u16 params
, byte_count
;
3915 cFYI(1, "In GetSrvInodeNum for %s", searchName
);
3919 GetInodeNumberRetry
:
3920 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
3925 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
3927 cifsConvertToUCS((__le16
*) pSMB
->FileName
, searchName
,
3928 PATH_MAX
, nls_codepage
, remap
);
3929 name_len
++; /* trailing null */
3931 } else { /* BB improve the check for buffer overruns BB */
3932 name_len
= strnlen(searchName
, PATH_MAX
);
3933 name_len
++; /* trailing null */
3934 strncpy(pSMB
->FileName
, searchName
, name_len
);
3937 params
= 2 /* level */ + 4 /* rsrvd */ + name_len
/* incl null */ ;
3938 pSMB
->TotalDataCount
= 0;
3939 pSMB
->MaxParameterCount
= cpu_to_le16(2);
3940 /* BB find exact max data count below from sess structure BB */
3941 pSMB
->MaxDataCount
= cpu_to_le16(4000);
3942 pSMB
->MaxSetupCount
= 0;
3946 pSMB
->Reserved2
= 0;
3947 pSMB
->ParameterOffset
= cpu_to_le16(offsetof(
3948 struct smb_com_transaction2_qpi_req
, InformationLevel
) - 4);
3949 pSMB
->DataCount
= 0;
3950 pSMB
->DataOffset
= 0;
3951 pSMB
->SetupCount
= 1;
3952 pSMB
->Reserved3
= 0;
3953 pSMB
->SubCommand
= cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION
);
3954 byte_count
= params
+ 1 /* pad */ ;
3955 pSMB
->TotalParameterCount
= cpu_to_le16(params
);
3956 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
3957 pSMB
->InformationLevel
= cpu_to_le16(SMB_QUERY_FILE_INTERNAL_INFO
);
3958 pSMB
->Reserved4
= 0;
3959 pSMB
->hdr
.smb_buf_length
+= byte_count
;
3960 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
3962 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
3963 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
3965 cFYI(1, "error %d in QueryInternalInfo", rc
);
3967 /* decode response */
3968 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
3969 if (rc
|| (pSMBr
->ByteCount
< 2))
3970 /* BB also check enough total bytes returned */
3971 /* If rc should we check for EOPNOSUPP and
3972 disable the srvino flag? or in caller? */
3973 rc
= -EIO
; /* bad smb */
3975 __u16 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
3976 __u16 count
= le16_to_cpu(pSMBr
->t2
.DataCount
);
3977 struct file_internal_info
*pfinfo
;
3978 /* BB Do we need a cast or hash here ? */
3980 cFYI(1, "Illegal size ret in QryIntrnlInf");
3982 goto GetInodeNumOut
;
3984 pfinfo
= (struct file_internal_info
*)
3985 (data_offset
+ (char *) &pSMBr
->hdr
.Protocol
);
3986 *inode_number
= le64_to_cpu(pfinfo
->UniqueId
);
3990 cifs_buf_release(pSMB
);
3992 goto GetInodeNumberRetry
;
3996 /* parses DFS refferal V3 structure
3997 * caller is responsible for freeing target_nodes
4000 * on failure - errno
4003 parse_DFS_referrals(TRANSACTION2_GET_DFS_REFER_RSP
*pSMBr
,
4004 unsigned int *num_of_nodes
,
4005 struct dfs_info3_param
**target_nodes
,
4006 const struct nls_table
*nls_codepage
, int remap
,
4007 const char *searchName
)
4012 struct dfs_referral_level_3
*ref
;
4014 if (pSMBr
->hdr
.Flags2
& SMBFLG2_UNICODE
)
4018 *num_of_nodes
= le16_to_cpu(pSMBr
->NumberOfReferrals
);
4020 if (*num_of_nodes
< 1) {
4021 cERROR(1, "num_referrals: must be at least > 0,"
4022 "but we get num_referrals = %d\n", *num_of_nodes
);
4024 goto parse_DFS_referrals_exit
;
4027 ref
= (struct dfs_referral_level_3
*) &(pSMBr
->referrals
);
4028 if (ref
->VersionNumber
!= cpu_to_le16(3)) {
4029 cERROR(1, "Referrals of V%d version are not supported,"
4030 "should be V3", le16_to_cpu(ref
->VersionNumber
));
4032 goto parse_DFS_referrals_exit
;
4035 /* get the upper boundary of the resp buffer */
4036 data_end
= (char *)(&(pSMBr
->PathConsumed
)) +
4037 le16_to_cpu(pSMBr
->t2
.DataCount
);
4039 cFYI(1, "num_referrals: %d dfs flags: 0x%x ...\n",
4041 le32_to_cpu(pSMBr
->DFSFlags
));
4043 *target_nodes
= kzalloc(sizeof(struct dfs_info3_param
) *
4044 *num_of_nodes
, GFP_KERNEL
);
4045 if (*target_nodes
== NULL
) {
4046 cERROR(1, "Failed to allocate buffer for target_nodes\n");
4048 goto parse_DFS_referrals_exit
;
4051 /* collect necessary data from referrals */
4052 for (i
= 0; i
< *num_of_nodes
; i
++) {
4055 struct dfs_info3_param
*node
= (*target_nodes
)+i
;
4057 node
->flags
= le32_to_cpu(pSMBr
->DFSFlags
);
4059 __le16
*tmp
= kmalloc(strlen(searchName
)*2 + 2,
4063 goto parse_DFS_referrals_exit
;
4065 cifsConvertToUCS((__le16
*) tmp
, searchName
,
4066 PATH_MAX
, nls_codepage
, remap
);
4067 node
->path_consumed
= cifs_ucs2_bytes(tmp
,
4068 le16_to_cpu(pSMBr
->PathConsumed
),
4072 node
->path_consumed
= le16_to_cpu(pSMBr
->PathConsumed
);
4074 node
->server_type
= le16_to_cpu(ref
->ServerType
);
4075 node
->ref_flag
= le16_to_cpu(ref
->ReferralEntryFlags
);
4078 temp
= (char *)ref
+ le16_to_cpu(ref
->DfsPathOffset
);
4079 max_len
= data_end
- temp
;
4080 node
->path_name
= cifs_strndup_from_ucs(temp
, max_len
,
4081 is_unicode
, nls_codepage
);
4082 if (!node
->path_name
) {
4084 goto parse_DFS_referrals_exit
;
4087 /* copy link target UNC */
4088 temp
= (char *)ref
+ le16_to_cpu(ref
->NetworkAddressOffset
);
4089 max_len
= data_end
- temp
;
4090 node
->node_name
= cifs_strndup_from_ucs(temp
, max_len
,
4091 is_unicode
, nls_codepage
);
4092 if (!node
->node_name
)
4096 parse_DFS_referrals_exit
:
4098 free_dfs_info_array(*target_nodes
, *num_of_nodes
);
4099 *target_nodes
= NULL
;
4106 CIFSGetDFSRefer(const int xid
, struct cifsSesInfo
*ses
,
4107 const unsigned char *searchName
,
4108 struct dfs_info3_param
**target_nodes
,
4109 unsigned int *num_of_nodes
,
4110 const struct nls_table
*nls_codepage
, int remap
)
4112 /* TRANS2_GET_DFS_REFERRAL */
4113 TRANSACTION2_GET_DFS_REFER_REQ
*pSMB
= NULL
;
4114 TRANSACTION2_GET_DFS_REFER_RSP
*pSMBr
= NULL
;
4118 __u16 params
, byte_count
;
4120 *target_nodes
= NULL
;
4122 cFYI(1, "In GetDFSRefer the path %s", searchName
);
4126 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, NULL
, (void **) &pSMB
,
4131 /* server pointer checked in called function,
4132 but should never be null here anyway */
4133 pSMB
->hdr
.Mid
= GetNextMid(ses
->server
);
4134 pSMB
->hdr
.Tid
= ses
->ipc_tid
;
4135 pSMB
->hdr
.Uid
= ses
->Suid
;
4136 if (ses
->capabilities
& CAP_STATUS32
)
4137 pSMB
->hdr
.Flags2
|= SMBFLG2_ERR_STATUS
;
4138 if (ses
->capabilities
& CAP_DFS
)
4139 pSMB
->hdr
.Flags2
|= SMBFLG2_DFS
;
4141 if (ses
->capabilities
& CAP_UNICODE
) {
4142 pSMB
->hdr
.Flags2
|= SMBFLG2_UNICODE
;
4144 cifsConvertToUCS((__le16
*) pSMB
->RequestFileName
,
4145 searchName
, PATH_MAX
, nls_codepage
, remap
);
4146 name_len
++; /* trailing null */
4148 } else { /* BB improve the check for buffer overruns BB */
4149 name_len
= strnlen(searchName
, PATH_MAX
);
4150 name_len
++; /* trailing null */
4151 strncpy(pSMB
->RequestFileName
, searchName
, name_len
);
4155 if (ses
->server
->secMode
&
4156 (SECMODE_SIGN_REQUIRED
| SECMODE_SIGN_ENABLED
))
4157 pSMB
->hdr
.Flags2
|= SMBFLG2_SECURITY_SIGNATURE
;
4160 pSMB
->hdr
.Uid
= ses
->Suid
;
4162 params
= 2 /* level */ + name_len
/*includes null */ ;
4163 pSMB
->TotalDataCount
= 0;
4164 pSMB
->DataCount
= 0;
4165 pSMB
->DataOffset
= 0;
4166 pSMB
->MaxParameterCount
= 0;
4167 /* BB find exact max SMB PDU from sess structure BB */
4168 pSMB
->MaxDataCount
= cpu_to_le16(4000);
4169 pSMB
->MaxSetupCount
= 0;
4173 pSMB
->Reserved2
= 0;
4174 pSMB
->ParameterOffset
= cpu_to_le16(offsetof(
4175 struct smb_com_transaction2_get_dfs_refer_req
, MaxReferralLevel
) - 4);
4176 pSMB
->SetupCount
= 1;
4177 pSMB
->Reserved3
= 0;
4178 pSMB
->SubCommand
= cpu_to_le16(TRANS2_GET_DFS_REFERRAL
);
4179 byte_count
= params
+ 3 /* pad */ ;
4180 pSMB
->ParameterCount
= cpu_to_le16(params
);
4181 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
4182 pSMB
->MaxReferralLevel
= cpu_to_le16(3);
4183 pSMB
->hdr
.smb_buf_length
+= byte_count
;
4184 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
4186 rc
= SendReceive(xid
, ses
, (struct smb_hdr
*) pSMB
,
4187 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
4189 cFYI(1, "Send error in GetDFSRefer = %d", rc
);
4192 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
4194 /* BB Also check if enough total bytes returned? */
4195 if (rc
|| (pSMBr
->ByteCount
< 17)) {
4196 rc
= -EIO
; /* bad smb */
4200 cFYI(1, "Decoding GetDFSRefer response BCC: %d Offset %d",
4202 le16_to_cpu(pSMBr
->t2
.DataOffset
));
4204 /* parse returned result into more usable form */
4205 rc
= parse_DFS_referrals(pSMBr
, num_of_nodes
,
4206 target_nodes
, nls_codepage
, remap
,
4210 cifs_buf_release(pSMB
);
4218 /* Query File System Info such as free space to old servers such as Win 9x */
4220 SMBOldQFSInfo(const int xid
, struct cifsTconInfo
*tcon
, struct kstatfs
*FSData
)
4222 /* level 0x01 SMB_QUERY_FILE_SYSTEM_INFO */
4223 TRANSACTION2_QFSI_REQ
*pSMB
= NULL
;
4224 TRANSACTION2_QFSI_RSP
*pSMBr
= NULL
;
4225 FILE_SYSTEM_ALLOC_INFO
*response_data
;
4227 int bytes_returned
= 0;
4228 __u16 params
, byte_count
;
4230 cFYI(1, "OldQFSInfo");
4232 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
4237 params
= 2; /* level */
4238 pSMB
->TotalDataCount
= 0;
4239 pSMB
->MaxParameterCount
= cpu_to_le16(2);
4240 pSMB
->MaxDataCount
= cpu_to_le16(1000);
4241 pSMB
->MaxSetupCount
= 0;
4245 pSMB
->Reserved2
= 0;
4246 byte_count
= params
+ 1 /* pad */ ;
4247 pSMB
->TotalParameterCount
= cpu_to_le16(params
);
4248 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
4249 pSMB
->ParameterOffset
= cpu_to_le16(offsetof(
4250 struct smb_com_transaction2_qfsi_req
, InformationLevel
) - 4);
4251 pSMB
->DataCount
= 0;
4252 pSMB
->DataOffset
= 0;
4253 pSMB
->SetupCount
= 1;
4254 pSMB
->Reserved3
= 0;
4255 pSMB
->SubCommand
= cpu_to_le16(TRANS2_QUERY_FS_INFORMATION
);
4256 pSMB
->InformationLevel
= cpu_to_le16(SMB_INFO_ALLOCATION
);
4257 pSMB
->hdr
.smb_buf_length
+= byte_count
;
4258 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
4260 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
4261 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
4263 cFYI(1, "Send error in QFSInfo = %d", rc
);
4264 } else { /* decode response */
4265 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
4267 if (rc
|| (pSMBr
->ByteCount
< 18))
4268 rc
= -EIO
; /* bad smb */
4270 __u16 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
4271 cFYI(1, "qfsinf resp BCC: %d Offset %d",
4272 pSMBr
->ByteCount
, data_offset
);
4274 response_data
= (FILE_SYSTEM_ALLOC_INFO
*)
4275 (((char *) &pSMBr
->hdr
.Protocol
) + data_offset
);
4277 le16_to_cpu(response_data
->BytesPerSector
) *
4278 le32_to_cpu(response_data
->
4279 SectorsPerAllocationUnit
);
4281 le32_to_cpu(response_data
->TotalAllocationUnits
);
4282 FSData
->f_bfree
= FSData
->f_bavail
=
4283 le32_to_cpu(response_data
->FreeAllocationUnits
);
4284 cFYI(1, "Blocks: %lld Free: %lld Block size %ld",
4285 (unsigned long long)FSData
->f_blocks
,
4286 (unsigned long long)FSData
->f_bfree
,
4290 cifs_buf_release(pSMB
);
4293 goto oldQFSInfoRetry
;
4299 CIFSSMBQFSInfo(const int xid
, struct cifsTconInfo
*tcon
, struct kstatfs
*FSData
)
4301 /* level 0x103 SMB_QUERY_FILE_SYSTEM_INFO */
4302 TRANSACTION2_QFSI_REQ
*pSMB
= NULL
;
4303 TRANSACTION2_QFSI_RSP
*pSMBr
= NULL
;
4304 FILE_SYSTEM_INFO
*response_data
;
4306 int bytes_returned
= 0;
4307 __u16 params
, byte_count
;
4309 cFYI(1, "In QFSInfo");
4311 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
4316 params
= 2; /* level */
4317 pSMB
->TotalDataCount
= 0;
4318 pSMB
->MaxParameterCount
= cpu_to_le16(2);
4319 pSMB
->MaxDataCount
= cpu_to_le16(1000);
4320 pSMB
->MaxSetupCount
= 0;
4324 pSMB
->Reserved2
= 0;
4325 byte_count
= params
+ 1 /* pad */ ;
4326 pSMB
->TotalParameterCount
= cpu_to_le16(params
);
4327 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
4328 pSMB
->ParameterOffset
= cpu_to_le16(offsetof(
4329 struct smb_com_transaction2_qfsi_req
, InformationLevel
) - 4);
4330 pSMB
->DataCount
= 0;
4331 pSMB
->DataOffset
= 0;
4332 pSMB
->SetupCount
= 1;
4333 pSMB
->Reserved3
= 0;
4334 pSMB
->SubCommand
= cpu_to_le16(TRANS2_QUERY_FS_INFORMATION
);
4335 pSMB
->InformationLevel
= cpu_to_le16(SMB_QUERY_FS_SIZE_INFO
);
4336 pSMB
->hdr
.smb_buf_length
+= byte_count
;
4337 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
4339 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
4340 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
4342 cFYI(1, "Send error in QFSInfo = %d", rc
);
4343 } else { /* decode response */
4344 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
4346 if (rc
|| (pSMBr
->ByteCount
< 24))
4347 rc
= -EIO
; /* bad smb */
4349 __u16 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
4353 *) (((char *) &pSMBr
->hdr
.Protocol
) +
4356 le32_to_cpu(response_data
->BytesPerSector
) *
4357 le32_to_cpu(response_data
->
4358 SectorsPerAllocationUnit
);
4360 le64_to_cpu(response_data
->TotalAllocationUnits
);
4361 FSData
->f_bfree
= FSData
->f_bavail
=
4362 le64_to_cpu(response_data
->FreeAllocationUnits
);
4363 cFYI(1, "Blocks: %lld Free: %lld Block size %ld",
4364 (unsigned long long)FSData
->f_blocks
,
4365 (unsigned long long)FSData
->f_bfree
,
4369 cifs_buf_release(pSMB
);
4378 CIFSSMBQFSAttributeInfo(const int xid
, struct cifsTconInfo
*tcon
)
4380 /* level 0x105 SMB_QUERY_FILE_SYSTEM_INFO */
4381 TRANSACTION2_QFSI_REQ
*pSMB
= NULL
;
4382 TRANSACTION2_QFSI_RSP
*pSMBr
= NULL
;
4383 FILE_SYSTEM_ATTRIBUTE_INFO
*response_data
;
4385 int bytes_returned
= 0;
4386 __u16 params
, byte_count
;
4388 cFYI(1, "In QFSAttributeInfo");
4390 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
4395 params
= 2; /* level */
4396 pSMB
->TotalDataCount
= 0;
4397 pSMB
->MaxParameterCount
= cpu_to_le16(2);
4398 /* BB find exact max SMB PDU from sess structure BB */
4399 pSMB
->MaxDataCount
= cpu_to_le16(1000);
4400 pSMB
->MaxSetupCount
= 0;
4404 pSMB
->Reserved2
= 0;
4405 byte_count
= params
+ 1 /* pad */ ;
4406 pSMB
->TotalParameterCount
= cpu_to_le16(params
);
4407 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
4408 pSMB
->ParameterOffset
= cpu_to_le16(offsetof(
4409 struct smb_com_transaction2_qfsi_req
, InformationLevel
) - 4);
4410 pSMB
->DataCount
= 0;
4411 pSMB
->DataOffset
= 0;
4412 pSMB
->SetupCount
= 1;
4413 pSMB
->Reserved3
= 0;
4414 pSMB
->SubCommand
= cpu_to_le16(TRANS2_QUERY_FS_INFORMATION
);
4415 pSMB
->InformationLevel
= cpu_to_le16(SMB_QUERY_FS_ATTRIBUTE_INFO
);
4416 pSMB
->hdr
.smb_buf_length
+= byte_count
;
4417 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
4419 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
4420 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
4422 cERROR(1, "Send error in QFSAttributeInfo = %d", rc
);
4423 } else { /* decode response */
4424 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
4426 if (rc
|| (pSMBr
->ByteCount
< 13)) {
4427 /* BB also check if enough bytes returned */
4428 rc
= -EIO
; /* bad smb */
4430 __u16 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
4432 (FILE_SYSTEM_ATTRIBUTE_INFO
4433 *) (((char *) &pSMBr
->hdr
.Protocol
) +
4435 memcpy(&tcon
->fsAttrInfo
, response_data
,
4436 sizeof(FILE_SYSTEM_ATTRIBUTE_INFO
));
4439 cifs_buf_release(pSMB
);
4442 goto QFSAttributeRetry
;
4448 CIFSSMBQFSDeviceInfo(const int xid
, struct cifsTconInfo
*tcon
)
4450 /* level 0x104 SMB_QUERY_FILE_SYSTEM_INFO */
4451 TRANSACTION2_QFSI_REQ
*pSMB
= NULL
;
4452 TRANSACTION2_QFSI_RSP
*pSMBr
= NULL
;
4453 FILE_SYSTEM_DEVICE_INFO
*response_data
;
4455 int bytes_returned
= 0;
4456 __u16 params
, byte_count
;
4458 cFYI(1, "In QFSDeviceInfo");
4460 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
4465 params
= 2; /* level */
4466 pSMB
->TotalDataCount
= 0;
4467 pSMB
->MaxParameterCount
= cpu_to_le16(2);
4468 /* BB find exact max SMB PDU from sess structure BB */
4469 pSMB
->MaxDataCount
= cpu_to_le16(1000);
4470 pSMB
->MaxSetupCount
= 0;
4474 pSMB
->Reserved2
= 0;
4475 byte_count
= params
+ 1 /* pad */ ;
4476 pSMB
->TotalParameterCount
= cpu_to_le16(params
);
4477 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
4478 pSMB
->ParameterOffset
= cpu_to_le16(offsetof(
4479 struct smb_com_transaction2_qfsi_req
, InformationLevel
) - 4);
4481 pSMB
->DataCount
= 0;
4482 pSMB
->DataOffset
= 0;
4483 pSMB
->SetupCount
= 1;
4484 pSMB
->Reserved3
= 0;
4485 pSMB
->SubCommand
= cpu_to_le16(TRANS2_QUERY_FS_INFORMATION
);
4486 pSMB
->InformationLevel
= cpu_to_le16(SMB_QUERY_FS_DEVICE_INFO
);
4487 pSMB
->hdr
.smb_buf_length
+= byte_count
;
4488 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
4490 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
4491 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
4493 cFYI(1, "Send error in QFSDeviceInfo = %d", rc
);
4494 } else { /* decode response */
4495 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
4497 if (rc
|| (pSMBr
->ByteCount
< sizeof(FILE_SYSTEM_DEVICE_INFO
)))
4498 rc
= -EIO
; /* bad smb */
4500 __u16 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
4502 (FILE_SYSTEM_DEVICE_INFO
*)
4503 (((char *) &pSMBr
->hdr
.Protocol
) +
4505 memcpy(&tcon
->fsDevInfo
, response_data
,
4506 sizeof(FILE_SYSTEM_DEVICE_INFO
));
4509 cifs_buf_release(pSMB
);
4512 goto QFSDeviceRetry
;
4518 CIFSSMBQFSUnixInfo(const int xid
, struct cifsTconInfo
*tcon
)
4520 /* level 0x200 SMB_QUERY_CIFS_UNIX_INFO */
4521 TRANSACTION2_QFSI_REQ
*pSMB
= NULL
;
4522 TRANSACTION2_QFSI_RSP
*pSMBr
= NULL
;
4523 FILE_SYSTEM_UNIX_INFO
*response_data
;
4525 int bytes_returned
= 0;
4526 __u16 params
, byte_count
;
4528 cFYI(1, "In QFSUnixInfo");
4530 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
4535 params
= 2; /* level */
4536 pSMB
->TotalDataCount
= 0;
4537 pSMB
->DataCount
= 0;
4538 pSMB
->DataOffset
= 0;
4539 pSMB
->MaxParameterCount
= cpu_to_le16(2);
4540 /* BB find exact max SMB PDU from sess structure BB */
4541 pSMB
->MaxDataCount
= cpu_to_le16(100);
4542 pSMB
->MaxSetupCount
= 0;
4546 pSMB
->Reserved2
= 0;
4547 byte_count
= params
+ 1 /* pad */ ;
4548 pSMB
->ParameterCount
= cpu_to_le16(params
);
4549 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
4550 pSMB
->ParameterOffset
= cpu_to_le16(offsetof(struct
4551 smb_com_transaction2_qfsi_req
, InformationLevel
) - 4);
4552 pSMB
->SetupCount
= 1;
4553 pSMB
->Reserved3
= 0;
4554 pSMB
->SubCommand
= cpu_to_le16(TRANS2_QUERY_FS_INFORMATION
);
4555 pSMB
->InformationLevel
= cpu_to_le16(SMB_QUERY_CIFS_UNIX_INFO
);
4556 pSMB
->hdr
.smb_buf_length
+= byte_count
;
4557 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
4559 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
4560 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
4562 cERROR(1, "Send error in QFSUnixInfo = %d", rc
);
4563 } else { /* decode response */
4564 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
4566 if (rc
|| (pSMBr
->ByteCount
< 13)) {
4567 rc
= -EIO
; /* bad smb */
4569 __u16 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
4571 (FILE_SYSTEM_UNIX_INFO
4572 *) (((char *) &pSMBr
->hdr
.Protocol
) +
4574 memcpy(&tcon
->fsUnixInfo
, response_data
,
4575 sizeof(FILE_SYSTEM_UNIX_INFO
));
4578 cifs_buf_release(pSMB
);
4588 CIFSSMBSetFSUnixInfo(const int xid
, struct cifsTconInfo
*tcon
, __u64 cap
)
4590 /* level 0x200 SMB_SET_CIFS_UNIX_INFO */
4591 TRANSACTION2_SETFSI_REQ
*pSMB
= NULL
;
4592 TRANSACTION2_SETFSI_RSP
*pSMBr
= NULL
;
4594 int bytes_returned
= 0;
4595 __u16 params
, param_offset
, offset
, byte_count
;
4597 cFYI(1, "In SETFSUnixInfo");
4599 /* BB switch to small buf init to save memory */
4600 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
4605 params
= 4; /* 2 bytes zero followed by info level. */
4606 pSMB
->MaxSetupCount
= 0;
4610 pSMB
->Reserved2
= 0;
4611 param_offset
= offsetof(struct smb_com_transaction2_setfsi_req
, FileNum
)
4613 offset
= param_offset
+ params
;
4615 pSMB
->MaxParameterCount
= cpu_to_le16(4);
4616 /* BB find exact max SMB PDU from sess structure BB */
4617 pSMB
->MaxDataCount
= cpu_to_le16(100);
4618 pSMB
->SetupCount
= 1;
4619 pSMB
->Reserved3
= 0;
4620 pSMB
->SubCommand
= cpu_to_le16(TRANS2_SET_FS_INFORMATION
);
4621 byte_count
= 1 /* pad */ + params
+ 12;
4623 pSMB
->DataCount
= cpu_to_le16(12);
4624 pSMB
->ParameterCount
= cpu_to_le16(params
);
4625 pSMB
->TotalDataCount
= pSMB
->DataCount
;
4626 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
4627 pSMB
->ParameterOffset
= cpu_to_le16(param_offset
);
4628 pSMB
->DataOffset
= cpu_to_le16(offset
);
4632 pSMB
->InformationLevel
= cpu_to_le16(SMB_SET_CIFS_UNIX_INFO
);
4635 pSMB
->ClientUnixMajor
= cpu_to_le16(CIFS_UNIX_MAJOR_VERSION
);
4636 pSMB
->ClientUnixMinor
= cpu_to_le16(CIFS_UNIX_MINOR_VERSION
);
4637 pSMB
->ClientUnixCap
= cpu_to_le64(cap
);
4639 pSMB
->hdr
.smb_buf_length
+= byte_count
;
4640 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
4642 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
4643 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
4645 cERROR(1, "Send error in SETFSUnixInfo = %d", rc
);
4646 } else { /* decode response */
4647 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
4649 rc
= -EIO
; /* bad smb */
4651 cifs_buf_release(pSMB
);
4654 goto SETFSUnixRetry
;
4662 CIFSSMBQFSPosixInfo(const int xid
, struct cifsTconInfo
*tcon
,
4663 struct kstatfs
*FSData
)
4665 /* level 0x201 SMB_QUERY_CIFS_POSIX_INFO */
4666 TRANSACTION2_QFSI_REQ
*pSMB
= NULL
;
4667 TRANSACTION2_QFSI_RSP
*pSMBr
= NULL
;
4668 FILE_SYSTEM_POSIX_INFO
*response_data
;
4670 int bytes_returned
= 0;
4671 __u16 params
, byte_count
;
4673 cFYI(1, "In QFSPosixInfo");
4675 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
4680 params
= 2; /* level */
4681 pSMB
->TotalDataCount
= 0;
4682 pSMB
->DataCount
= 0;
4683 pSMB
->DataOffset
= 0;
4684 pSMB
->MaxParameterCount
= cpu_to_le16(2);
4685 /* BB find exact max SMB PDU from sess structure BB */
4686 pSMB
->MaxDataCount
= cpu_to_le16(100);
4687 pSMB
->MaxSetupCount
= 0;
4691 pSMB
->Reserved2
= 0;
4692 byte_count
= params
+ 1 /* pad */ ;
4693 pSMB
->ParameterCount
= cpu_to_le16(params
);
4694 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
4695 pSMB
->ParameterOffset
= cpu_to_le16(offsetof(struct
4696 smb_com_transaction2_qfsi_req
, InformationLevel
) - 4);
4697 pSMB
->SetupCount
= 1;
4698 pSMB
->Reserved3
= 0;
4699 pSMB
->SubCommand
= cpu_to_le16(TRANS2_QUERY_FS_INFORMATION
);
4700 pSMB
->InformationLevel
= cpu_to_le16(SMB_QUERY_POSIX_FS_INFO
);
4701 pSMB
->hdr
.smb_buf_length
+= byte_count
;
4702 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
4704 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
4705 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
4707 cFYI(1, "Send error in QFSUnixInfo = %d", rc
);
4708 } else { /* decode response */
4709 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
4711 if (rc
|| (pSMBr
->ByteCount
< 13)) {
4712 rc
= -EIO
; /* bad smb */
4714 __u16 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
4716 (FILE_SYSTEM_POSIX_INFO
4717 *) (((char *) &pSMBr
->hdr
.Protocol
) +
4720 le32_to_cpu(response_data
->BlockSize
);
4722 le64_to_cpu(response_data
->TotalBlocks
);
4724 le64_to_cpu(response_data
->BlocksAvail
);
4725 if (response_data
->UserBlocksAvail
== cpu_to_le64(-1)) {
4726 FSData
->f_bavail
= FSData
->f_bfree
;
4729 le64_to_cpu(response_data
->UserBlocksAvail
);
4731 if (response_data
->TotalFileNodes
!= cpu_to_le64(-1))
4733 le64_to_cpu(response_data
->TotalFileNodes
);
4734 if (response_data
->FreeFileNodes
!= cpu_to_le64(-1))
4736 le64_to_cpu(response_data
->FreeFileNodes
);
4739 cifs_buf_release(pSMB
);
4748 /* We can not use write of zero bytes trick to
4749 set file size due to need for large file support. Also note that
4750 this SetPathInfo is preferred to SetFileInfo based method in next
4751 routine which is only needed to work around a sharing violation bug
4752 in Samba which this routine can run into */
4755 CIFSSMBSetEOF(const int xid
, struct cifsTconInfo
*tcon
, const char *fileName
,
4756 __u64 size
, bool SetAllocation
,
4757 const struct nls_table
*nls_codepage
, int remap
)
4759 struct smb_com_transaction2_spi_req
*pSMB
= NULL
;
4760 struct smb_com_transaction2_spi_rsp
*pSMBr
= NULL
;
4761 struct file_end_of_file_info
*parm_data
;
4764 int bytes_returned
= 0;
4765 __u16 params
, byte_count
, data_count
, param_offset
, offset
;
4767 cFYI(1, "In SetEOF");
4769 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
4774 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
4776 cifsConvertToUCS((__le16
*) pSMB
->FileName
, fileName
,
4777 PATH_MAX
, nls_codepage
, remap
);
4778 name_len
++; /* trailing null */
4780 } else { /* BB improve the check for buffer overruns BB */
4781 name_len
= strnlen(fileName
, PATH_MAX
);
4782 name_len
++; /* trailing null */
4783 strncpy(pSMB
->FileName
, fileName
, name_len
);
4785 params
= 6 + name_len
;
4786 data_count
= sizeof(struct file_end_of_file_info
);
4787 pSMB
->MaxParameterCount
= cpu_to_le16(2);
4788 pSMB
->MaxDataCount
= cpu_to_le16(4100);
4789 pSMB
->MaxSetupCount
= 0;
4793 pSMB
->Reserved2
= 0;
4794 param_offset
= offsetof(struct smb_com_transaction2_spi_req
,
4795 InformationLevel
) - 4;
4796 offset
= param_offset
+ params
;
4797 if (SetAllocation
) {
4798 if (tcon
->ses
->capabilities
& CAP_INFOLEVEL_PASSTHRU
)
4799 pSMB
->InformationLevel
=
4800 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2
);
4802 pSMB
->InformationLevel
=
4803 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO
);
4804 } else /* Set File Size */ {
4805 if (tcon
->ses
->capabilities
& CAP_INFOLEVEL_PASSTHRU
)
4806 pSMB
->InformationLevel
=
4807 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO2
);
4809 pSMB
->InformationLevel
=
4810 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO
);
4814 (struct file_end_of_file_info
*) (((char *) &pSMB
->hdr
.Protocol
) +
4816 pSMB
->ParameterOffset
= cpu_to_le16(param_offset
);
4817 pSMB
->DataOffset
= cpu_to_le16(offset
);
4818 pSMB
->SetupCount
= 1;
4819 pSMB
->Reserved3
= 0;
4820 pSMB
->SubCommand
= cpu_to_le16(TRANS2_SET_PATH_INFORMATION
);
4821 byte_count
= 3 /* pad */ + params
+ data_count
;
4822 pSMB
->DataCount
= cpu_to_le16(data_count
);
4823 pSMB
->TotalDataCount
= pSMB
->DataCount
;
4824 pSMB
->ParameterCount
= cpu_to_le16(params
);
4825 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
4826 pSMB
->Reserved4
= 0;
4827 pSMB
->hdr
.smb_buf_length
+= byte_count
;
4828 parm_data
->FileSize
= cpu_to_le64(size
);
4829 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
4830 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
4831 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
4833 cFYI(1, "SetPathInfo (file size) returned %d", rc
);
4835 cifs_buf_release(pSMB
);
4844 CIFSSMBSetFileSize(const int xid
, struct cifsTconInfo
*tcon
, __u64 size
,
4845 __u16 fid
, __u32 pid_of_opener
, bool SetAllocation
)
4847 struct smb_com_transaction2_sfi_req
*pSMB
= NULL
;
4849 struct file_end_of_file_info
*parm_data
;
4851 __u16 params
, param_offset
, offset
, byte_count
, count
;
4853 cFYI(1, "SetFileSize (via SetFileInfo) %lld",
4855 rc
= small_smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
);
4860 pSMB
->hdr
.Pid
= cpu_to_le16((__u16
)pid_of_opener
);
4861 pSMB
->hdr
.PidHigh
= cpu_to_le16((__u16
)(pid_of_opener
>> 16));
4864 pSMB
->MaxSetupCount
= 0;
4868 pSMB
->Reserved2
= 0;
4869 param_offset
= offsetof(struct smb_com_transaction2_sfi_req
, Fid
) - 4;
4870 offset
= param_offset
+ params
;
4872 data_offset
= (char *) (&pSMB
->hdr
.Protocol
) + offset
;
4874 count
= sizeof(struct file_end_of_file_info
);
4875 pSMB
->MaxParameterCount
= cpu_to_le16(2);
4876 /* BB find exact max SMB PDU from sess structure BB */
4877 pSMB
->MaxDataCount
= cpu_to_le16(1000);
4878 pSMB
->SetupCount
= 1;
4879 pSMB
->Reserved3
= 0;
4880 pSMB
->SubCommand
= cpu_to_le16(TRANS2_SET_FILE_INFORMATION
);
4881 byte_count
= 3 /* pad */ + params
+ count
;
4882 pSMB
->DataCount
= cpu_to_le16(count
);
4883 pSMB
->ParameterCount
= cpu_to_le16(params
);
4884 pSMB
->TotalDataCount
= pSMB
->DataCount
;
4885 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
4886 pSMB
->ParameterOffset
= cpu_to_le16(param_offset
);
4888 (struct file_end_of_file_info
*) (((char *) &pSMB
->hdr
.Protocol
)
4890 pSMB
->DataOffset
= cpu_to_le16(offset
);
4891 parm_data
->FileSize
= cpu_to_le64(size
);
4893 if (SetAllocation
) {
4894 if (tcon
->ses
->capabilities
& CAP_INFOLEVEL_PASSTHRU
)
4895 pSMB
->InformationLevel
=
4896 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2
);
4898 pSMB
->InformationLevel
=
4899 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO
);
4900 } else /* Set File Size */ {
4901 if (tcon
->ses
->capabilities
& CAP_INFOLEVEL_PASSTHRU
)
4902 pSMB
->InformationLevel
=
4903 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO2
);
4905 pSMB
->InformationLevel
=
4906 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO
);
4908 pSMB
->Reserved4
= 0;
4909 pSMB
->hdr
.smb_buf_length
+= byte_count
;
4910 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
4911 rc
= SendReceiveNoRsp(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
, 0);
4913 cFYI(1, "Send error in SetFileInfo (SetFileSize) = %d", rc
);
4916 /* Note: On -EAGAIN error only caller can retry on handle based calls
4917 since file handle passed in no longer valid */
4922 /* Some legacy servers such as NT4 require that the file times be set on
4923 an open handle, rather than by pathname - this is awkward due to
4924 potential access conflicts on the open, but it is unavoidable for these
4925 old servers since the only other choice is to go from 100 nanosecond DCE
4926 time and resort to the original setpathinfo level which takes the ancient
4927 DOS time format with 2 second granularity */
4929 CIFSSMBSetFileInfo(const int xid
, struct cifsTconInfo
*tcon
,
4930 const FILE_BASIC_INFO
*data
, __u16 fid
, __u32 pid_of_opener
)
4932 struct smb_com_transaction2_sfi_req
*pSMB
= NULL
;
4935 __u16 params
, param_offset
, offset
, byte_count
, count
;
4937 cFYI(1, "Set Times (via SetFileInfo)");
4938 rc
= small_smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
);
4943 pSMB
->hdr
.Pid
= cpu_to_le16((__u16
)pid_of_opener
);
4944 pSMB
->hdr
.PidHigh
= cpu_to_le16((__u16
)(pid_of_opener
>> 16));
4947 pSMB
->MaxSetupCount
= 0;
4951 pSMB
->Reserved2
= 0;
4952 param_offset
= offsetof(struct smb_com_transaction2_sfi_req
, Fid
) - 4;
4953 offset
= param_offset
+ params
;
4955 data_offset
= (char *) (&pSMB
->hdr
.Protocol
) + offset
;
4957 count
= sizeof(FILE_BASIC_INFO
);
4958 pSMB
->MaxParameterCount
= cpu_to_le16(2);
4959 /* BB find max SMB PDU from sess */
4960 pSMB
->MaxDataCount
= cpu_to_le16(1000);
4961 pSMB
->SetupCount
= 1;
4962 pSMB
->Reserved3
= 0;
4963 pSMB
->SubCommand
= cpu_to_le16(TRANS2_SET_FILE_INFORMATION
);
4964 byte_count
= 3 /* pad */ + params
+ count
;
4965 pSMB
->DataCount
= cpu_to_le16(count
);
4966 pSMB
->ParameterCount
= cpu_to_le16(params
);
4967 pSMB
->TotalDataCount
= pSMB
->DataCount
;
4968 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
4969 pSMB
->ParameterOffset
= cpu_to_le16(param_offset
);
4970 pSMB
->DataOffset
= cpu_to_le16(offset
);
4972 if (tcon
->ses
->capabilities
& CAP_INFOLEVEL_PASSTHRU
)
4973 pSMB
->InformationLevel
= cpu_to_le16(SMB_SET_FILE_BASIC_INFO2
);
4975 pSMB
->InformationLevel
= cpu_to_le16(SMB_SET_FILE_BASIC_INFO
);
4976 pSMB
->Reserved4
= 0;
4977 pSMB
->hdr
.smb_buf_length
+= byte_count
;
4978 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
4979 memcpy(data_offset
, data
, sizeof(FILE_BASIC_INFO
));
4980 rc
= SendReceiveNoRsp(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
, 0);
4982 cFYI(1, "Send error in Set Time (SetFileInfo) = %d", rc
);
4984 /* Note: On -EAGAIN error only caller can retry on handle based calls
4985 since file handle passed in no longer valid */
4991 CIFSSMBSetFileDisposition(const int xid
, struct cifsTconInfo
*tcon
,
4992 bool delete_file
, __u16 fid
, __u32 pid_of_opener
)
4994 struct smb_com_transaction2_sfi_req
*pSMB
= NULL
;
4997 __u16 params
, param_offset
, offset
, byte_count
, count
;
4999 cFYI(1, "Set File Disposition (via SetFileInfo)");
5000 rc
= small_smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
);
5005 pSMB
->hdr
.Pid
= cpu_to_le16((__u16
)pid_of_opener
);
5006 pSMB
->hdr
.PidHigh
= cpu_to_le16((__u16
)(pid_of_opener
>> 16));
5009 pSMB
->MaxSetupCount
= 0;
5013 pSMB
->Reserved2
= 0;
5014 param_offset
= offsetof(struct smb_com_transaction2_sfi_req
, Fid
) - 4;
5015 offset
= param_offset
+ params
;
5017 data_offset
= (char *) (&pSMB
->hdr
.Protocol
) + offset
;
5020 pSMB
->MaxParameterCount
= cpu_to_le16(2);
5021 /* BB find max SMB PDU from sess */
5022 pSMB
->MaxDataCount
= cpu_to_le16(1000);
5023 pSMB
->SetupCount
= 1;
5024 pSMB
->Reserved3
= 0;
5025 pSMB
->SubCommand
= cpu_to_le16(TRANS2_SET_FILE_INFORMATION
);
5026 byte_count
= 3 /* pad */ + params
+ count
;
5027 pSMB
->DataCount
= cpu_to_le16(count
);
5028 pSMB
->ParameterCount
= cpu_to_le16(params
);
5029 pSMB
->TotalDataCount
= pSMB
->DataCount
;
5030 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
5031 pSMB
->ParameterOffset
= cpu_to_le16(param_offset
);
5032 pSMB
->DataOffset
= cpu_to_le16(offset
);
5034 pSMB
->InformationLevel
= cpu_to_le16(SMB_SET_FILE_DISPOSITION_INFO
);
5035 pSMB
->Reserved4
= 0;
5036 pSMB
->hdr
.smb_buf_length
+= byte_count
;
5037 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
5038 *data_offset
= delete_file
? 1 : 0;
5039 rc
= SendReceiveNoRsp(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
, 0);
5041 cFYI(1, "Send error in SetFileDisposition = %d", rc
);
5047 CIFSSMBSetPathInfo(const int xid
, struct cifsTconInfo
*tcon
,
5048 const char *fileName
, const FILE_BASIC_INFO
*data
,
5049 const struct nls_table
*nls_codepage
, int remap
)
5051 TRANSACTION2_SPI_REQ
*pSMB
= NULL
;
5052 TRANSACTION2_SPI_RSP
*pSMBr
= NULL
;
5055 int bytes_returned
= 0;
5057 __u16 params
, param_offset
, offset
, byte_count
, count
;
5059 cFYI(1, "In SetTimes");
5062 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
5067 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
5069 cifsConvertToUCS((__le16
*) pSMB
->FileName
, fileName
,
5070 PATH_MAX
, nls_codepage
, remap
);
5071 name_len
++; /* trailing null */
5073 } else { /* BB improve the check for buffer overruns BB */
5074 name_len
= strnlen(fileName
, PATH_MAX
);
5075 name_len
++; /* trailing null */
5076 strncpy(pSMB
->FileName
, fileName
, name_len
);
5079 params
= 6 + name_len
;
5080 count
= sizeof(FILE_BASIC_INFO
);
5081 pSMB
->MaxParameterCount
= cpu_to_le16(2);
5082 /* BB find max SMB PDU from sess structure BB */
5083 pSMB
->MaxDataCount
= cpu_to_le16(1000);
5084 pSMB
->MaxSetupCount
= 0;
5088 pSMB
->Reserved2
= 0;
5089 param_offset
= offsetof(struct smb_com_transaction2_spi_req
,
5090 InformationLevel
) - 4;
5091 offset
= param_offset
+ params
;
5092 data_offset
= (char *) (&pSMB
->hdr
.Protocol
) + offset
;
5093 pSMB
->ParameterOffset
= cpu_to_le16(param_offset
);
5094 pSMB
->DataOffset
= cpu_to_le16(offset
);
5095 pSMB
->SetupCount
= 1;
5096 pSMB
->Reserved3
= 0;
5097 pSMB
->SubCommand
= cpu_to_le16(TRANS2_SET_PATH_INFORMATION
);
5098 byte_count
= 3 /* pad */ + params
+ count
;
5100 pSMB
->DataCount
= cpu_to_le16(count
);
5101 pSMB
->ParameterCount
= cpu_to_le16(params
);
5102 pSMB
->TotalDataCount
= pSMB
->DataCount
;
5103 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
5104 if (tcon
->ses
->capabilities
& CAP_INFOLEVEL_PASSTHRU
)
5105 pSMB
->InformationLevel
= cpu_to_le16(SMB_SET_FILE_BASIC_INFO2
);
5107 pSMB
->InformationLevel
= cpu_to_le16(SMB_SET_FILE_BASIC_INFO
);
5108 pSMB
->Reserved4
= 0;
5109 pSMB
->hdr
.smb_buf_length
+= byte_count
;
5110 memcpy(data_offset
, data
, sizeof(FILE_BASIC_INFO
));
5111 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
5112 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
5113 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
5115 cFYI(1, "SetPathInfo (times) returned %d", rc
);
5117 cifs_buf_release(pSMB
);
5125 /* Can not be used to set time stamps yet (due to old DOS time format) */
5126 /* Can be used to set attributes */
5127 #if 0 /* Possibly not needed - since it turns out that strangely NT4 has a bug
5128 handling it anyway and NT4 was what we thought it would be needed for
5129 Do not delete it until we prove whether needed for Win9x though */
5131 CIFSSMBSetAttrLegacy(int xid
, struct cifsTconInfo
*tcon
, char *fileName
,
5132 __u16 dos_attrs
, const struct nls_table
*nls_codepage
)
5134 SETATTR_REQ
*pSMB
= NULL
;
5135 SETATTR_RSP
*pSMBr
= NULL
;
5140 cFYI(1, "In SetAttrLegacy");
5143 rc
= smb_init(SMB_COM_SETATTR
, 8, tcon
, (void **) &pSMB
,
5148 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
5150 ConvertToUCS((__le16
*) pSMB
->fileName
, fileName
,
5151 PATH_MAX
, nls_codepage
);
5152 name_len
++; /* trailing null */
5154 } else { /* BB improve the check for buffer overruns BB */
5155 name_len
= strnlen(fileName
, PATH_MAX
);
5156 name_len
++; /* trailing null */
5157 strncpy(pSMB
->fileName
, fileName
, name_len
);
5159 pSMB
->attr
= cpu_to_le16(dos_attrs
);
5160 pSMB
->BufferFormat
= 0x04;
5161 pSMB
->hdr
.smb_buf_length
+= name_len
+ 1;
5162 pSMB
->ByteCount
= cpu_to_le16(name_len
+ 1);
5163 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
5164 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
5166 cFYI(1, "Error in LegacySetAttr = %d", rc
);
5168 cifs_buf_release(pSMB
);
5171 goto SetAttrLgcyRetry
;
5175 #endif /* temporarily unneeded SetAttr legacy function */
5178 cifs_fill_unix_set_info(FILE_UNIX_BASIC_INFO
*data_offset
,
5179 const struct cifs_unix_set_info_args
*args
)
5181 u64 mode
= args
->mode
;
5184 * Samba server ignores set of file size to zero due to bugs in some
5185 * older clients, but we should be precise - we use SetFileSize to
5186 * set file size and do not want to truncate file size to zero
5187 * accidently as happened on one Samba server beta by putting
5188 * zero instead of -1 here
5190 data_offset
->EndOfFile
= cpu_to_le64(NO_CHANGE_64
);
5191 data_offset
->NumOfBytes
= cpu_to_le64(NO_CHANGE_64
);
5192 data_offset
->LastStatusChange
= cpu_to_le64(args
->ctime
);
5193 data_offset
->LastAccessTime
= cpu_to_le64(args
->atime
);
5194 data_offset
->LastModificationTime
= cpu_to_le64(args
->mtime
);
5195 data_offset
->Uid
= cpu_to_le64(args
->uid
);
5196 data_offset
->Gid
= cpu_to_le64(args
->gid
);
5197 /* better to leave device as zero when it is */
5198 data_offset
->DevMajor
= cpu_to_le64(MAJOR(args
->device
));
5199 data_offset
->DevMinor
= cpu_to_le64(MINOR(args
->device
));
5200 data_offset
->Permissions
= cpu_to_le64(mode
);
5203 data_offset
->Type
= cpu_to_le32(UNIX_FILE
);
5204 else if (S_ISDIR(mode
))
5205 data_offset
->Type
= cpu_to_le32(UNIX_DIR
);
5206 else if (S_ISLNK(mode
))
5207 data_offset
->Type
= cpu_to_le32(UNIX_SYMLINK
);
5208 else if (S_ISCHR(mode
))
5209 data_offset
->Type
= cpu_to_le32(UNIX_CHARDEV
);
5210 else if (S_ISBLK(mode
))
5211 data_offset
->Type
= cpu_to_le32(UNIX_BLOCKDEV
);
5212 else if (S_ISFIFO(mode
))
5213 data_offset
->Type
= cpu_to_le32(UNIX_FIFO
);
5214 else if (S_ISSOCK(mode
))
5215 data_offset
->Type
= cpu_to_le32(UNIX_SOCKET
);
5219 CIFSSMBUnixSetFileInfo(const int xid
, struct cifsTconInfo
*tcon
,
5220 const struct cifs_unix_set_info_args
*args
,
5221 u16 fid
, u32 pid_of_opener
)
5223 struct smb_com_transaction2_sfi_req
*pSMB
= NULL
;
5224 FILE_UNIX_BASIC_INFO
*data_offset
;
5226 u16 params
, param_offset
, offset
, byte_count
, count
;
5228 cFYI(1, "Set Unix Info (via SetFileInfo)");
5229 rc
= small_smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
);
5234 pSMB
->hdr
.Pid
= cpu_to_le16((__u16
)pid_of_opener
);
5235 pSMB
->hdr
.PidHigh
= cpu_to_le16((__u16
)(pid_of_opener
>> 16));
5238 pSMB
->MaxSetupCount
= 0;
5242 pSMB
->Reserved2
= 0;
5243 param_offset
= offsetof(struct smb_com_transaction2_sfi_req
, Fid
) - 4;
5244 offset
= param_offset
+ params
;
5246 data_offset
= (FILE_UNIX_BASIC_INFO
*)
5247 ((char *)(&pSMB
->hdr
.Protocol
) + offset
);
5248 count
= sizeof(FILE_UNIX_BASIC_INFO
);
5250 pSMB
->MaxParameterCount
= cpu_to_le16(2);
5251 /* BB find max SMB PDU from sess */
5252 pSMB
->MaxDataCount
= cpu_to_le16(1000);
5253 pSMB
->SetupCount
= 1;
5254 pSMB
->Reserved3
= 0;
5255 pSMB
->SubCommand
= cpu_to_le16(TRANS2_SET_FILE_INFORMATION
);
5256 byte_count
= 3 /* pad */ + params
+ count
;
5257 pSMB
->DataCount
= cpu_to_le16(count
);
5258 pSMB
->ParameterCount
= cpu_to_le16(params
);
5259 pSMB
->TotalDataCount
= pSMB
->DataCount
;
5260 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
5261 pSMB
->ParameterOffset
= cpu_to_le16(param_offset
);
5262 pSMB
->DataOffset
= cpu_to_le16(offset
);
5264 pSMB
->InformationLevel
= cpu_to_le16(SMB_SET_FILE_UNIX_BASIC
);
5265 pSMB
->Reserved4
= 0;
5266 pSMB
->hdr
.smb_buf_length
+= byte_count
;
5267 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
5269 cifs_fill_unix_set_info(data_offset
, args
);
5271 rc
= SendReceiveNoRsp(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
, 0);
5273 cFYI(1, "Send error in Set Time (SetFileInfo) = %d", rc
);
5275 /* Note: On -EAGAIN error only caller can retry on handle based calls
5276 since file handle passed in no longer valid */
5282 CIFSSMBUnixSetPathInfo(const int xid
, struct cifsTconInfo
*tcon
, char *fileName
,
5283 const struct cifs_unix_set_info_args
*args
,
5284 const struct nls_table
*nls_codepage
, int remap
)
5286 TRANSACTION2_SPI_REQ
*pSMB
= NULL
;
5287 TRANSACTION2_SPI_RSP
*pSMBr
= NULL
;
5290 int bytes_returned
= 0;
5291 FILE_UNIX_BASIC_INFO
*data_offset
;
5292 __u16 params
, param_offset
, offset
, count
, byte_count
;
5294 cFYI(1, "In SetUID/GID/Mode");
5296 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
5301 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
5303 cifsConvertToUCS((__le16
*) pSMB
->FileName
, fileName
,
5304 PATH_MAX
, nls_codepage
, remap
);
5305 name_len
++; /* trailing null */
5307 } else { /* BB improve the check for buffer overruns BB */
5308 name_len
= strnlen(fileName
, PATH_MAX
);
5309 name_len
++; /* trailing null */
5310 strncpy(pSMB
->FileName
, fileName
, name_len
);
5313 params
= 6 + name_len
;
5314 count
= sizeof(FILE_UNIX_BASIC_INFO
);
5315 pSMB
->MaxParameterCount
= cpu_to_le16(2);
5316 /* BB find max SMB PDU from sess structure BB */
5317 pSMB
->MaxDataCount
= cpu_to_le16(1000);
5318 pSMB
->MaxSetupCount
= 0;
5322 pSMB
->Reserved2
= 0;
5323 param_offset
= offsetof(struct smb_com_transaction2_spi_req
,
5324 InformationLevel
) - 4;
5325 offset
= param_offset
+ params
;
5327 (FILE_UNIX_BASIC_INFO
*) ((char *) &pSMB
->hdr
.Protocol
+
5329 memset(data_offset
, 0, count
);
5330 pSMB
->DataOffset
= cpu_to_le16(offset
);
5331 pSMB
->ParameterOffset
= cpu_to_le16(param_offset
);
5332 pSMB
->SetupCount
= 1;
5333 pSMB
->Reserved3
= 0;
5334 pSMB
->SubCommand
= cpu_to_le16(TRANS2_SET_PATH_INFORMATION
);
5335 byte_count
= 3 /* pad */ + params
+ count
;
5336 pSMB
->ParameterCount
= cpu_to_le16(params
);
5337 pSMB
->DataCount
= cpu_to_le16(count
);
5338 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
5339 pSMB
->TotalDataCount
= pSMB
->DataCount
;
5340 pSMB
->InformationLevel
= cpu_to_le16(SMB_SET_FILE_UNIX_BASIC
);
5341 pSMB
->Reserved4
= 0;
5342 pSMB
->hdr
.smb_buf_length
+= byte_count
;
5344 cifs_fill_unix_set_info(data_offset
, args
);
5346 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
5347 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
5348 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
5350 cFYI(1, "SetPathInfo (perms) returned %d", rc
);
5352 cifs_buf_release(pSMB
);
5358 int CIFSSMBNotify(const int xid
, struct cifsTconInfo
*tcon
,
5359 const int notify_subdirs
, const __u16 netfid
,
5360 __u32 filter
, struct file
*pfile
, int multishot
,
5361 const struct nls_table
*nls_codepage
)
5364 struct smb_com_transaction_change_notify_req
*pSMB
= NULL
;
5365 struct smb_com_ntransaction_change_notify_rsp
*pSMBr
= NULL
;
5366 struct dir_notify_req
*dnotify_req
;
5369 cFYI(1, "In CIFSSMBNotify for file handle %d", (int)netfid
);
5370 rc
= smb_init(SMB_COM_NT_TRANSACT
, 23, tcon
, (void **) &pSMB
,
5375 pSMB
->TotalParameterCount
= 0 ;
5376 pSMB
->TotalDataCount
= 0;
5377 pSMB
->MaxParameterCount
= cpu_to_le32(2);
5378 /* BB find exact data count max from sess structure BB */
5379 pSMB
->MaxDataCount
= 0; /* same in little endian or be */
5380 /* BB VERIFY verify which is correct for above BB */
5381 pSMB
->MaxDataCount
= cpu_to_le32((tcon
->ses
->server
->maxBuf
-
5382 MAX_CIFS_HDR_SIZE
) & 0xFFFFFF00);
5384 pSMB
->MaxSetupCount
= 4;
5386 pSMB
->ParameterOffset
= 0;
5387 pSMB
->DataCount
= 0;
5388 pSMB
->DataOffset
= 0;
5389 pSMB
->SetupCount
= 4; /* single byte does not need le conversion */
5390 pSMB
->SubCommand
= cpu_to_le16(NT_TRANSACT_NOTIFY_CHANGE
);
5391 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
5393 pSMB
->WatchTree
= 1; /* one byte - no le conversion needed */
5394 pSMB
->Reserved2
= 0;
5395 pSMB
->CompletionFilter
= cpu_to_le32(filter
);
5396 pSMB
->Fid
= netfid
; /* file handle always le */
5397 pSMB
->ByteCount
= 0;
5399 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
5400 (struct smb_hdr
*)pSMBr
, &bytes_returned
,
5403 cFYI(1, "Error in Notify = %d", rc
);
5405 /* Add file to outstanding requests */
5406 /* BB change to kmem cache alloc */
5407 dnotify_req
= kmalloc(
5408 sizeof(struct dir_notify_req
),
5411 dnotify_req
->Pid
= pSMB
->hdr
.Pid
;
5412 dnotify_req
->PidHigh
= pSMB
->hdr
.PidHigh
;
5413 dnotify_req
->Mid
= pSMB
->hdr
.Mid
;
5414 dnotify_req
->Tid
= pSMB
->hdr
.Tid
;
5415 dnotify_req
->Uid
= pSMB
->hdr
.Uid
;
5416 dnotify_req
->netfid
= netfid
;
5417 dnotify_req
->pfile
= pfile
;
5418 dnotify_req
->filter
= filter
;
5419 dnotify_req
->multishot
= multishot
;
5420 spin_lock(&GlobalMid_Lock
);
5421 list_add_tail(&dnotify_req
->lhead
,
5422 &GlobalDnotifyReqList
);
5423 spin_unlock(&GlobalMid_Lock
);
5427 cifs_buf_release(pSMB
);
5431 #ifdef CONFIG_CIFS_XATTR
5433 * Do a path-based QUERY_ALL_EAS call and parse the result. This is a common
5434 * function used by listxattr and getxattr type calls. When ea_name is set,
5435 * it looks for that attribute name and stuffs that value into the EAData
5436 * buffer. When ea_name is NULL, it stuffs a list of attribute names into the
5437 * buffer. In both cases, the return value is either the length of the
5438 * resulting data or a negative error code. If EAData is a NULL pointer then
5439 * the data isn't copied to it, but the length is returned.
5442 CIFSSMBQAllEAs(const int xid
, struct cifsTconInfo
*tcon
,
5443 const unsigned char *searchName
, const unsigned char *ea_name
,
5444 char *EAData
, size_t buf_size
,
5445 const struct nls_table
*nls_codepage
, int remap
)
5447 /* BB assumes one setup word */
5448 TRANSACTION2_QPI_REQ
*pSMB
= NULL
;
5449 TRANSACTION2_QPI_RSP
*pSMBr
= NULL
;
5453 struct fealist
*ea_response_data
;
5454 struct fea
*temp_fea
;
5457 __u16 params
, byte_count
, data_offset
;
5459 cFYI(1, "In Query All EAs path %s", searchName
);
5461 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
5466 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
5468 cifsConvertToUCS((__le16
*) pSMB
->FileName
, searchName
,
5469 PATH_MAX
, nls_codepage
, remap
);
5470 list_len
++; /* trailing null */
5472 } else { /* BB improve the check for buffer overruns BB */
5473 list_len
= strnlen(searchName
, PATH_MAX
);
5474 list_len
++; /* trailing null */
5475 strncpy(pSMB
->FileName
, searchName
, list_len
);
5478 params
= 2 /* level */ + 4 /* reserved */ + list_len
/* includes NUL */;
5479 pSMB
->TotalDataCount
= 0;
5480 pSMB
->MaxParameterCount
= cpu_to_le16(2);
5481 /* BB find exact max SMB PDU from sess structure BB */
5482 pSMB
->MaxDataCount
= cpu_to_le16(CIFSMaxBufSize
);
5483 pSMB
->MaxSetupCount
= 0;
5487 pSMB
->Reserved2
= 0;
5488 pSMB
->ParameterOffset
= cpu_to_le16(offsetof(
5489 struct smb_com_transaction2_qpi_req
, InformationLevel
) - 4);
5490 pSMB
->DataCount
= 0;
5491 pSMB
->DataOffset
= 0;
5492 pSMB
->SetupCount
= 1;
5493 pSMB
->Reserved3
= 0;
5494 pSMB
->SubCommand
= cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION
);
5495 byte_count
= params
+ 1 /* pad */ ;
5496 pSMB
->TotalParameterCount
= cpu_to_le16(params
);
5497 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
5498 pSMB
->InformationLevel
= cpu_to_le16(SMB_INFO_QUERY_ALL_EAS
);
5499 pSMB
->Reserved4
= 0;
5500 pSMB
->hdr
.smb_buf_length
+= byte_count
;
5501 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
5503 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
5504 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
5506 cFYI(1, "Send error in QueryAllEAs = %d", rc
);
5511 /* BB also check enough total bytes returned */
5512 /* BB we need to improve the validity checking
5513 of these trans2 responses */
5515 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
5516 if (rc
|| (pSMBr
->ByteCount
< 4)) {
5517 rc
= -EIO
; /* bad smb */
5521 /* check that length of list is not more than bcc */
5522 /* check that each entry does not go beyond length
5524 /* check that each element of each entry does not
5525 go beyond end of list */
5526 /* validate_trans2_offsets() */
5527 /* BB check if start of smb + data_offset > &bcc+ bcc */
5529 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
5530 ea_response_data
= (struct fealist
*)
5531 (((char *) &pSMBr
->hdr
.Protocol
) + data_offset
);
5533 list_len
= le32_to_cpu(ea_response_data
->list_len
);
5534 cFYI(1, "ea length %d", list_len
);
5535 if (list_len
<= 8) {
5536 cFYI(1, "empty EA list returned from server");
5540 /* make sure list_len doesn't go past end of SMB */
5541 end_of_smb
= (char *)pByteArea(&pSMBr
->hdr
) + BCC(&pSMBr
->hdr
);
5542 if ((char *)ea_response_data
+ list_len
> end_of_smb
) {
5543 cFYI(1, "EA list appears to go beyond SMB");
5548 /* account for ea list len */
5550 temp_fea
= ea_response_data
->list
;
5551 temp_ptr
= (char *)temp_fea
;
5552 while (list_len
> 0) {
5553 unsigned int name_len
;
5558 /* make sure we can read name_len and value_len */
5560 cFYI(1, "EA entry goes beyond length of list");
5565 name_len
= temp_fea
->name_len
;
5566 value_len
= le16_to_cpu(temp_fea
->value_len
);
5567 list_len
-= name_len
+ 1 + value_len
;
5569 cFYI(1, "EA entry goes beyond length of list");
5575 if (strncmp(ea_name
, temp_ptr
, name_len
) == 0) {
5576 temp_ptr
+= name_len
+ 1;
5580 if ((size_t)value_len
> buf_size
) {
5584 memcpy(EAData
, temp_ptr
, value_len
);
5588 /* account for prefix user. and trailing null */
5589 rc
+= (5 + 1 + name_len
);
5590 if (rc
< (int) buf_size
) {
5591 memcpy(EAData
, "user.", 5);
5593 memcpy(EAData
, temp_ptr
, name_len
);
5595 /* null terminate name */
5598 } else if (buf_size
== 0) {
5599 /* skip copy - calc size only */
5601 /* stop before overrun buffer */
5606 temp_ptr
+= name_len
+ 1 + value_len
;
5607 temp_fea
= (struct fea
*)temp_ptr
;
5610 /* didn't find the named attribute */
5615 cifs_buf_release(pSMB
);
5623 CIFSSMBSetEA(const int xid
, struct cifsTconInfo
*tcon
, const char *fileName
,
5624 const char *ea_name
, const void *ea_value
,
5625 const __u16 ea_value_len
, const struct nls_table
*nls_codepage
,
5628 struct smb_com_transaction2_spi_req
*pSMB
= NULL
;
5629 struct smb_com_transaction2_spi_rsp
*pSMBr
= NULL
;
5630 struct fealist
*parm_data
;
5633 int bytes_returned
= 0;
5634 __u16 params
, param_offset
, byte_count
, offset
, count
;
5636 cFYI(1, "In SetEA");
5638 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
5643 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
5645 cifsConvertToUCS((__le16
*) pSMB
->FileName
, fileName
,
5646 PATH_MAX
, nls_codepage
, remap
);
5647 name_len
++; /* trailing null */
5649 } else { /* BB improve the check for buffer overruns BB */
5650 name_len
= strnlen(fileName
, PATH_MAX
);
5651 name_len
++; /* trailing null */
5652 strncpy(pSMB
->FileName
, fileName
, name_len
);
5655 params
= 6 + name_len
;
5657 /* done calculating parms using name_len of file name,
5658 now use name_len to calculate length of ea name
5659 we are going to create in the inode xattrs */
5660 if (ea_name
== NULL
)
5663 name_len
= strnlen(ea_name
, 255);
5665 count
= sizeof(*parm_data
) + ea_value_len
+ name_len
;
5666 pSMB
->MaxParameterCount
= cpu_to_le16(2);
5667 /* BB find max SMB PDU from sess */
5668 pSMB
->MaxDataCount
= cpu_to_le16(1000);
5669 pSMB
->MaxSetupCount
= 0;
5673 pSMB
->Reserved2
= 0;
5674 param_offset
= offsetof(struct smb_com_transaction2_spi_req
,
5675 InformationLevel
) - 4;
5676 offset
= param_offset
+ params
;
5677 pSMB
->InformationLevel
=
5678 cpu_to_le16(SMB_SET_FILE_EA
);
5681 (struct fealist
*) (((char *) &pSMB
->hdr
.Protocol
) +
5683 pSMB
->ParameterOffset
= cpu_to_le16(param_offset
);
5684 pSMB
->DataOffset
= cpu_to_le16(offset
);
5685 pSMB
->SetupCount
= 1;
5686 pSMB
->Reserved3
= 0;
5687 pSMB
->SubCommand
= cpu_to_le16(TRANS2_SET_PATH_INFORMATION
);
5688 byte_count
= 3 /* pad */ + params
+ count
;
5689 pSMB
->DataCount
= cpu_to_le16(count
);
5690 parm_data
->list_len
= cpu_to_le32(count
);
5691 parm_data
->list
[0].EA_flags
= 0;
5692 /* we checked above that name len is less than 255 */
5693 parm_data
->list
[0].name_len
= (__u8
)name_len
;
5694 /* EA names are always ASCII */
5696 strncpy(parm_data
->list
[0].name
, ea_name
, name_len
);
5697 parm_data
->list
[0].name
[name_len
] = 0;
5698 parm_data
->list
[0].value_len
= cpu_to_le16(ea_value_len
);
5699 /* caller ensures that ea_value_len is less than 64K but
5700 we need to ensure that it fits within the smb */
5702 /*BB add length check to see if it would fit in
5703 negotiated SMB buffer size BB */
5704 /* if (ea_value_len > buffer_size - 512 (enough for header)) */
5706 memcpy(parm_data
->list
[0].name
+name_len
+1,
5707 ea_value
, ea_value_len
);
5709 pSMB
->TotalDataCount
= pSMB
->DataCount
;
5710 pSMB
->ParameterCount
= cpu_to_le16(params
);
5711 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
5712 pSMB
->Reserved4
= 0;
5713 pSMB
->hdr
.smb_buf_length
+= byte_count
;
5714 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
5715 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
5716 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
5718 cFYI(1, "SetPathInfo (EA) returned %d", rc
);
5720 cifs_buf_release(pSMB
);