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 spin_lock(&cifs_file_list_lock
);
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 spin_unlock(&cifs_file_list_lock
);
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",
140 * Give demultiplex thread up to 10 seconds to reconnect, should be
141 * greater than cifs socket timeout which is 7 seconds
143 while (server
->tcpStatus
== CifsNeedReconnect
) {
144 wait_event_interruptible_timeout(server
->response_q
,
145 (server
->tcpStatus
!= CifsNeedReconnect
), 10 * HZ
);
147 /* are we still trying to reconnect? */
148 if (server
->tcpStatus
!= CifsNeedReconnect
)
152 * on "soft" mounts we wait once. Hard mounts keep
153 * retrying until process is killed or server comes
157 cFYI(1, "gave up waiting on reconnect in smb_init");
162 if (!ses
->need_reconnect
&& !tcon
->need_reconnect
)
165 nls_codepage
= load_nls_default();
168 * need to prevent multiple threads trying to simultaneously
169 * reconnect the same SMB session
171 mutex_lock(&ses
->session_mutex
);
172 rc
= cifs_negotiate_protocol(0, ses
);
173 if (rc
== 0 && ses
->need_reconnect
)
174 rc
= cifs_setup_session(0, ses
, nls_codepage
);
176 /* do we need to reconnect tcon? */
177 if (rc
|| !tcon
->need_reconnect
) {
178 mutex_unlock(&ses
->session_mutex
);
182 mark_open_files_invalid(tcon
);
183 rc
= CIFSTCon(0, ses
, tcon
->treeName
, tcon
, nls_codepage
);
184 mutex_unlock(&ses
->session_mutex
);
185 cFYI(1, "reconnect tcon rc = %d", rc
);
191 * FIXME: check if wsize needs updated due to negotiated smb buffer
194 atomic_inc(&tconInfoReconnectCount
);
196 /* tell server Unix caps we support */
197 if (ses
->capabilities
& CAP_UNIX
)
198 reset_cifs_unix_caps(0, tcon
, NULL
, NULL
);
201 * Removed call to reopen open files here. It is safer (and faster) to
202 * reopen files one at a time as needed in read and write.
204 * FIXME: what about file locks? don't we need to reclaim them ASAP?
209 * Check if handle based operation so we know whether we can continue
210 * or not without returning to caller to reset file handle
212 switch (smb_command
) {
213 case SMB_COM_READ_ANDX
:
214 case SMB_COM_WRITE_ANDX
:
216 case SMB_COM_FIND_CLOSE2
:
217 case SMB_COM_LOCKING_ANDX
:
221 unload_nls(nls_codepage
);
225 /* Allocate and return pointer to an SMB request buffer, and set basic
226 SMB information in the SMB header. If the return code is zero, this
227 function must have filled in request_buf pointer */
229 small_smb_init(int smb_command
, int wct
, struct cifsTconInfo
*tcon
,
234 rc
= cifs_reconnect_tcon(tcon
, smb_command
);
238 *request_buf
= cifs_small_buf_get();
239 if (*request_buf
== NULL
) {
240 /* BB should we add a retry in here if not a writepage? */
244 header_assemble((struct smb_hdr
*) *request_buf
, smb_command
,
248 cifs_stats_inc(&tcon
->num_smbs_sent
);
254 small_smb_init_no_tc(const int smb_command
, const int wct
,
255 struct cifsSesInfo
*ses
, void **request_buf
)
258 struct smb_hdr
*buffer
;
260 rc
= small_smb_init(smb_command
, wct
, NULL
, request_buf
);
264 buffer
= (struct smb_hdr
*)*request_buf
;
265 buffer
->Mid
= GetNextMid(ses
->server
);
266 if (ses
->capabilities
& CAP_UNICODE
)
267 buffer
->Flags2
|= SMBFLG2_UNICODE
;
268 if (ses
->capabilities
& CAP_STATUS32
)
269 buffer
->Flags2
|= SMBFLG2_ERR_STATUS
;
271 /* uid, tid can stay at zero as set in header assemble */
273 /* BB add support for turning on the signing when
274 this function is used after 1st of session setup requests */
279 /* If the return code is zero, this function must fill in request_buf pointer */
281 __smb_init(int smb_command
, int wct
, struct cifsTconInfo
*tcon
,
282 void **request_buf
, void **response_buf
)
284 *request_buf
= cifs_buf_get();
285 if (*request_buf
== NULL
) {
286 /* BB should we add a retry in here if not a writepage? */
289 /* Although the original thought was we needed the response buf for */
290 /* potential retries of smb operations it turns out we can determine */
291 /* from the mid flags when the request buffer can be resent without */
292 /* having to use a second distinct buffer for the response */
294 *response_buf
= *request_buf
;
296 header_assemble((struct smb_hdr
*) *request_buf
, smb_command
, tcon
,
300 cifs_stats_inc(&tcon
->num_smbs_sent
);
305 /* If the return code is zero, this function must fill in request_buf pointer */
307 smb_init(int smb_command
, int wct
, struct cifsTconInfo
*tcon
,
308 void **request_buf
, void **response_buf
)
312 rc
= cifs_reconnect_tcon(tcon
, smb_command
);
316 return __smb_init(smb_command
, wct
, tcon
, request_buf
, response_buf
);
320 smb_init_no_reconnect(int smb_command
, int wct
, struct cifsTconInfo
*tcon
,
321 void **request_buf
, void **response_buf
)
323 if (tcon
->ses
->need_reconnect
|| tcon
->need_reconnect
)
326 return __smb_init(smb_command
, wct
, tcon
, request_buf
, response_buf
);
329 static int validate_t2(struct smb_t2_rsp
*pSMB
)
331 unsigned int total_size
;
333 /* check for plausible wct */
334 if (pSMB
->hdr
.WordCount
< 10)
337 /* check for parm and data offset going beyond end of smb */
338 if (get_unaligned_le16(&pSMB
->t2_rsp
.ParameterOffset
) > 1024 ||
339 get_unaligned_le16(&pSMB
->t2_rsp
.DataOffset
) > 1024)
342 total_size
= get_unaligned_le16(&pSMB
->t2_rsp
.ParameterCount
);
343 if (total_size
>= 512)
346 /* check that bcc is at least as big as parms + data, and that it is
347 * less than negotiated smb buffer
349 total_size
+= get_unaligned_le16(&pSMB
->t2_rsp
.DataCount
);
350 if (total_size
> get_bcc(&pSMB
->hdr
) ||
351 total_size
>= CIFSMaxBufSize
+ MAX_CIFS_HDR_SIZE
)
356 cifs_dump_mem("Invalid transact2 SMB: ", (char *)pSMB
,
357 sizeof(struct smb_t2_rsp
) + 16);
362 CIFSSMBNegotiate(unsigned int xid
, struct cifsSesInfo
*ses
)
365 NEGOTIATE_RSP
*pSMBr
;
369 struct TCP_Server_Info
*server
;
371 unsigned int secFlags
;
374 server
= ses
->server
;
379 rc
= smb_init(SMB_COM_NEGOTIATE
, 0, NULL
/* no tcon yet */ ,
380 (void **) &pSMB
, (void **) &pSMBr
);
384 /* if any of auth flags (ie not sign or seal) are overriden use them */
385 if (ses
->overrideSecFlg
& (~(CIFSSEC_MUST_SIGN
| CIFSSEC_MUST_SEAL
)))
386 secFlags
= ses
->overrideSecFlg
; /* BB FIXME fix sign flags? */
387 else /* if override flags set only sign/seal OR them with global auth */
388 secFlags
= global_secflags
| ses
->overrideSecFlg
;
390 cFYI(1, "secFlags 0x%x", secFlags
);
392 pSMB
->hdr
.Mid
= GetNextMid(server
);
393 pSMB
->hdr
.Flags2
|= (SMBFLG2_UNICODE
| SMBFLG2_ERR_STATUS
);
395 if ((secFlags
& CIFSSEC_MUST_KRB5
) == CIFSSEC_MUST_KRB5
)
396 pSMB
->hdr
.Flags2
|= SMBFLG2_EXT_SEC
;
397 else if ((secFlags
& CIFSSEC_AUTH_MASK
) == CIFSSEC_MAY_KRB5
) {
398 cFYI(1, "Kerberos only mechanism, enable extended security");
399 pSMB
->hdr
.Flags2
|= SMBFLG2_EXT_SEC
;
400 } else if ((secFlags
& CIFSSEC_MUST_NTLMSSP
) == CIFSSEC_MUST_NTLMSSP
)
401 pSMB
->hdr
.Flags2
|= SMBFLG2_EXT_SEC
;
402 else if ((secFlags
& CIFSSEC_AUTH_MASK
) == CIFSSEC_MAY_NTLMSSP
) {
403 cFYI(1, "NTLMSSP only mechanism, enable extended security");
404 pSMB
->hdr
.Flags2
|= SMBFLG2_EXT_SEC
;
408 for (i
= 0; i
< CIFS_NUM_PROT
; i
++) {
409 strncpy(pSMB
->DialectsArray
+count
, protocols
[i
].name
, 16);
410 count
+= strlen(protocols
[i
].name
) + 1;
411 /* null at end of source and target buffers anyway */
413 pSMB
->hdr
.smb_buf_length
+= count
;
414 pSMB
->ByteCount
= cpu_to_le16(count
);
416 rc
= SendReceive(xid
, ses
, (struct smb_hdr
*) pSMB
,
417 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
421 server
->dialect
= le16_to_cpu(pSMBr
->DialectIndex
);
422 cFYI(1, "Dialect: %d", server
->dialect
);
423 /* Check wct = 1 error case */
424 if ((pSMBr
->hdr
.WordCount
< 13) || (server
->dialect
== BAD_PROT
)) {
425 /* core returns wct = 1, but we do not ask for core - otherwise
426 small wct just comes when dialect index is -1 indicating we
427 could not negotiate a common dialect */
430 #ifdef CONFIG_CIFS_WEAK_PW_HASH
431 } else if ((pSMBr
->hdr
.WordCount
== 13)
432 && ((server
->dialect
== LANMAN_PROT
)
433 || (server
->dialect
== LANMAN2_PROT
))) {
435 struct lanman_neg_rsp
*rsp
= (struct lanman_neg_rsp
*)pSMBr
;
437 if ((secFlags
& CIFSSEC_MAY_LANMAN
) ||
438 (secFlags
& CIFSSEC_MAY_PLNTXT
))
439 server
->secType
= LANMAN
;
441 cERROR(1, "mount failed weak security disabled"
442 " in /proc/fs/cifs/SecurityFlags");
446 server
->secMode
= (__u8
)le16_to_cpu(rsp
->SecurityMode
);
447 server
->maxReq
= le16_to_cpu(rsp
->MaxMpxCount
);
448 server
->maxBuf
= min((__u32
)le16_to_cpu(rsp
->MaxBufSize
),
449 (__u32
)CIFSMaxBufSize
+ MAX_CIFS_HDR_SIZE
);
450 server
->max_vcs
= le16_to_cpu(rsp
->MaxNumberVcs
);
451 /* even though we do not use raw we might as well set this
452 accurately, in case we ever find a need for it */
453 if ((le16_to_cpu(rsp
->RawMode
) & RAW_ENABLE
) == RAW_ENABLE
) {
454 server
->max_rw
= 0xFF00;
455 server
->capabilities
= CAP_MPX_MODE
| CAP_RAW_MODE
;
457 server
->max_rw
= 0;/* do not need to use raw anyway */
458 server
->capabilities
= CAP_MPX_MODE
;
460 tmp
= (__s16
)le16_to_cpu(rsp
->ServerTimeZone
);
462 /* OS/2 often does not set timezone therefore
463 * we must use server time to calc time zone.
464 * Could deviate slightly from the right zone.
465 * Smallest defined timezone difference is 15 minutes
466 * (i.e. Nepal). Rounding up/down is done to match
469 int val
, seconds
, remain
, result
;
470 struct timespec ts
, utc
;
472 ts
= cnvrtDosUnixTm(rsp
->SrvTime
.Date
,
473 rsp
->SrvTime
.Time
, 0);
474 cFYI(1, "SrvTime %d sec since 1970 (utc: %d) diff: %d",
475 (int)ts
.tv_sec
, (int)utc
.tv_sec
,
476 (int)(utc
.tv_sec
- ts
.tv_sec
));
477 val
= (int)(utc
.tv_sec
- ts
.tv_sec
);
479 result
= (seconds
/ MIN_TZ_ADJ
) * MIN_TZ_ADJ
;
480 remain
= seconds
% MIN_TZ_ADJ
;
481 if (remain
>= (MIN_TZ_ADJ
/ 2))
482 result
+= MIN_TZ_ADJ
;
485 server
->timeAdj
= result
;
487 server
->timeAdj
= (int)tmp
;
488 server
->timeAdj
*= 60; /* also in seconds */
490 cFYI(1, "server->timeAdj: %d seconds", server
->timeAdj
);
493 /* BB get server time for time conversions and add
494 code to use it and timezone since this is not UTC */
496 if (rsp
->EncryptionKeyLength
==
497 cpu_to_le16(CIFS_CRYPTO_KEY_SIZE
)) {
498 memcpy(ses
->server
->cryptkey
, rsp
->EncryptionKey
,
499 CIFS_CRYPTO_KEY_SIZE
);
500 } else if (server
->secMode
& SECMODE_PW_ENCRYPT
) {
501 rc
= -EIO
; /* need cryptkey unless plain text */
505 cFYI(1, "LANMAN negotiated");
506 /* we will not end up setting signing flags - as no signing
507 was in LANMAN and server did not return the flags on */
509 #else /* weak security disabled */
510 } else if (pSMBr
->hdr
.WordCount
== 13) {
511 cERROR(1, "mount failed, cifs module not built "
512 "with CIFS_WEAK_PW_HASH support");
514 #endif /* WEAK_PW_HASH */
516 } else if (pSMBr
->hdr
.WordCount
!= 17) {
521 /* else wct == 17 NTLM */
522 server
->secMode
= pSMBr
->SecurityMode
;
523 if ((server
->secMode
& SECMODE_USER
) == 0)
524 cFYI(1, "share mode security");
526 if ((server
->secMode
& SECMODE_PW_ENCRYPT
) == 0)
527 #ifdef CONFIG_CIFS_WEAK_PW_HASH
528 if ((secFlags
& CIFSSEC_MAY_PLNTXT
) == 0)
529 #endif /* CIFS_WEAK_PW_HASH */
530 cERROR(1, "Server requests plain text password"
531 " but client support disabled");
533 if ((secFlags
& CIFSSEC_MUST_NTLMV2
) == CIFSSEC_MUST_NTLMV2
)
534 server
->secType
= NTLMv2
;
535 else if (secFlags
& CIFSSEC_MAY_NTLM
)
536 server
->secType
= NTLM
;
537 else if (secFlags
& CIFSSEC_MAY_NTLMV2
)
538 server
->secType
= NTLMv2
;
539 else if (secFlags
& CIFSSEC_MAY_KRB5
)
540 server
->secType
= Kerberos
;
541 else if (secFlags
& CIFSSEC_MAY_NTLMSSP
)
542 server
->secType
= RawNTLMSSP
;
543 else if (secFlags
& CIFSSEC_MAY_LANMAN
)
544 server
->secType
= LANMAN
;
547 cERROR(1, "Invalid security type");
550 /* else ... any others ...? */
552 /* one byte, so no need to convert this or EncryptionKeyLen from
554 server
->maxReq
= le16_to_cpu(pSMBr
->MaxMpxCount
);
555 /* probably no need to store and check maxvcs */
556 server
->maxBuf
= min(le32_to_cpu(pSMBr
->MaxBufferSize
),
557 (__u32
) CIFSMaxBufSize
+ MAX_CIFS_HDR_SIZE
);
558 server
->max_rw
= le32_to_cpu(pSMBr
->MaxRawSize
);
559 cFYI(DBG2
, "Max buf = %d", ses
->server
->maxBuf
);
560 server
->capabilities
= le32_to_cpu(pSMBr
->Capabilities
);
561 server
->timeAdj
= (int)(__s16
)le16_to_cpu(pSMBr
->ServerTimeZone
);
562 server
->timeAdj
*= 60;
563 if (pSMBr
->EncryptionKeyLength
== CIFS_CRYPTO_KEY_SIZE
) {
564 memcpy(ses
->server
->cryptkey
, pSMBr
->u
.EncryptionKey
,
565 CIFS_CRYPTO_KEY_SIZE
);
566 } else if ((pSMBr
->hdr
.Flags2
& SMBFLG2_EXT_SEC
)
567 && (pSMBr
->EncryptionKeyLength
== 0)) {
568 /* decode security blob */
569 } else if (server
->secMode
& SECMODE_PW_ENCRYPT
) {
570 rc
= -EIO
; /* no crypt key only if plain text pwd */
574 /* BB might be helpful to save off the domain of server here */
576 if ((pSMBr
->hdr
.Flags2
& SMBFLG2_EXT_SEC
) &&
577 (server
->capabilities
& CAP_EXTENDED_SECURITY
)) {
578 count
= pSMBr
->ByteCount
;
583 spin_lock(&cifs_tcp_ses_lock
);
584 if (server
->srv_count
> 1) {
585 spin_unlock(&cifs_tcp_ses_lock
);
586 if (memcmp(server
->server_GUID
,
587 pSMBr
->u
.extended_response
.
589 cFYI(1, "server UID changed");
590 memcpy(server
->server_GUID
,
591 pSMBr
->u
.extended_response
.GUID
,
595 spin_unlock(&cifs_tcp_ses_lock
);
596 memcpy(server
->server_GUID
,
597 pSMBr
->u
.extended_response
.GUID
, 16);
601 server
->secType
= RawNTLMSSP
;
603 rc
= decode_negTokenInit(pSMBr
->u
.extended_response
.
604 SecurityBlob
, count
- 16,
610 if (server
->secType
== Kerberos
) {
611 if (!server
->sec_kerberos
&&
612 !server
->sec_mskerberos
)
614 } else if (server
->secType
== RawNTLMSSP
) {
615 if (!server
->sec_ntlmssp
)
621 server
->capabilities
&= ~CAP_EXTENDED_SECURITY
;
623 #ifdef CONFIG_CIFS_WEAK_PW_HASH
626 if ((secFlags
& CIFSSEC_MAY_SIGN
) == 0) {
627 /* MUST_SIGN already includes the MAY_SIGN FLAG
628 so if this is zero it means that signing is disabled */
629 cFYI(1, "Signing disabled");
630 if (server
->secMode
& SECMODE_SIGN_REQUIRED
) {
631 cERROR(1, "Server requires "
632 "packet signing to be enabled in "
633 "/proc/fs/cifs/SecurityFlags.");
637 ~(SECMODE_SIGN_ENABLED
| SECMODE_SIGN_REQUIRED
);
638 } else if ((secFlags
& CIFSSEC_MUST_SIGN
) == CIFSSEC_MUST_SIGN
) {
639 /* signing required */
640 cFYI(1, "Must sign - secFlags 0x%x", secFlags
);
641 if ((server
->secMode
&
642 (SECMODE_SIGN_ENABLED
| SECMODE_SIGN_REQUIRED
)) == 0) {
643 cERROR(1, "signing required but server lacks support");
646 server
->secMode
|= SECMODE_SIGN_REQUIRED
;
648 /* signing optional ie CIFSSEC_MAY_SIGN */
649 if ((server
->secMode
& SECMODE_SIGN_REQUIRED
) == 0)
651 ~(SECMODE_SIGN_ENABLED
| SECMODE_SIGN_REQUIRED
);
655 cifs_buf_release(pSMB
);
657 cFYI(1, "negprot rc %d", rc
);
662 CIFSSMBTDis(const int xid
, struct cifsTconInfo
*tcon
)
664 struct smb_hdr
*smb_buffer
;
667 cFYI(1, "In tree disconnect");
669 /* BB: do we need to check this? These should never be NULL. */
670 if ((tcon
->ses
== NULL
) || (tcon
->ses
->server
== NULL
))
674 * No need to return error on this operation if tid invalidated and
675 * closed on server already e.g. due to tcp session crashing. Also,
676 * the tcon is no longer on the list, so no need to take lock before
679 if ((tcon
->need_reconnect
) || (tcon
->ses
->need_reconnect
))
682 rc
= small_smb_init(SMB_COM_TREE_DISCONNECT
, 0, tcon
,
683 (void **)&smb_buffer
);
687 rc
= SendReceiveNoRsp(xid
, tcon
->ses
, smb_buffer
, 0);
689 cFYI(1, "Tree disconnect failed %d", rc
);
691 /* No need to return error on this operation if tid invalidated and
692 closed on server already e.g. due to tcp session crashing */
700 * This is a no-op for now. We're not really interested in the reply, but
701 * rather in the fact that the server sent one and that server->lstrp
704 * FIXME: maybe we should consider checking that the reply matches request?
707 cifs_echo_callback(struct mid_q_entry
*mid
)
709 struct TCP_Server_Info
*server
= mid
->callback_data
;
711 DeleteMidQEntry(mid
);
712 atomic_dec(&server
->inFlight
);
713 wake_up(&server
->request_q
);
717 CIFSSMBEcho(struct TCP_Server_Info
*server
)
722 cFYI(1, "In echo request");
724 rc
= small_smb_init(SMB_COM_ECHO
, 0, NULL
, (void **)&smb
);
728 /* set up echo request */
729 smb
->hdr
.Tid
= 0xffff;
730 smb
->hdr
.WordCount
= 1;
731 put_unaligned_le16(1, &smb
->EchoCount
);
732 put_bcc_le(1, &smb
->hdr
);
734 smb
->hdr
.smb_buf_length
+= 3;
736 rc
= cifs_call_async(server
, (struct smb_hdr
*)smb
,
737 cifs_echo_callback
, server
);
739 cFYI(1, "Echo request failed: %d", rc
);
741 cifs_small_buf_release(smb
);
747 CIFSSMBLogoff(const int xid
, struct cifsSesInfo
*ses
)
749 LOGOFF_ANDX_REQ
*pSMB
;
752 cFYI(1, "In SMBLogoff for session disconnect");
755 * BB: do we need to check validity of ses and server? They should
756 * always be valid since we have an active reference. If not, that
757 * should probably be a BUG()
759 if (!ses
|| !ses
->server
)
762 mutex_lock(&ses
->session_mutex
);
763 if (ses
->need_reconnect
)
764 goto session_already_dead
; /* no need to send SMBlogoff if uid
765 already closed due to reconnect */
766 rc
= small_smb_init(SMB_COM_LOGOFF_ANDX
, 2, NULL
, (void **)&pSMB
);
768 mutex_unlock(&ses
->session_mutex
);
772 pSMB
->hdr
.Mid
= GetNextMid(ses
->server
);
774 if (ses
->server
->secMode
&
775 (SECMODE_SIGN_REQUIRED
| SECMODE_SIGN_ENABLED
))
776 pSMB
->hdr
.Flags2
|= SMBFLG2_SECURITY_SIGNATURE
;
778 pSMB
->hdr
.Uid
= ses
->Suid
;
780 pSMB
->AndXCommand
= 0xFF;
781 rc
= SendReceiveNoRsp(xid
, ses
, (struct smb_hdr
*) pSMB
, 0);
782 session_already_dead
:
783 mutex_unlock(&ses
->session_mutex
);
785 /* if session dead then we do not need to do ulogoff,
786 since server closed smb session, no sense reporting
794 CIFSPOSIXDelFile(const int xid
, struct cifsTconInfo
*tcon
, const char *fileName
,
795 __u16 type
, const struct nls_table
*nls_codepage
, int remap
)
797 TRANSACTION2_SPI_REQ
*pSMB
= NULL
;
798 TRANSACTION2_SPI_RSP
*pSMBr
= NULL
;
799 struct unlink_psx_rq
*pRqD
;
802 int bytes_returned
= 0;
803 __u16 params
, param_offset
, offset
, byte_count
;
805 cFYI(1, "In POSIX delete");
807 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
812 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
814 cifsConvertToUCS((__le16
*) pSMB
->FileName
, fileName
,
815 PATH_MAX
, nls_codepage
, remap
);
816 name_len
++; /* trailing null */
818 } else { /* BB add path length overrun check */
819 name_len
= strnlen(fileName
, PATH_MAX
);
820 name_len
++; /* trailing null */
821 strncpy(pSMB
->FileName
, fileName
, name_len
);
824 params
= 6 + name_len
;
825 pSMB
->MaxParameterCount
= cpu_to_le16(2);
826 pSMB
->MaxDataCount
= 0; /* BB double check this with jra */
827 pSMB
->MaxSetupCount
= 0;
832 param_offset
= offsetof(struct smb_com_transaction2_spi_req
,
833 InformationLevel
) - 4;
834 offset
= param_offset
+ params
;
836 /* Setup pointer to Request Data (inode type) */
837 pRqD
= (struct unlink_psx_rq
*)(((char *)&pSMB
->hdr
.Protocol
) + offset
);
838 pRqD
->type
= cpu_to_le16(type
);
839 pSMB
->ParameterOffset
= cpu_to_le16(param_offset
);
840 pSMB
->DataOffset
= cpu_to_le16(offset
);
841 pSMB
->SetupCount
= 1;
843 pSMB
->SubCommand
= cpu_to_le16(TRANS2_SET_PATH_INFORMATION
);
844 byte_count
= 3 /* pad */ + params
+ sizeof(struct unlink_psx_rq
);
846 pSMB
->DataCount
= cpu_to_le16(sizeof(struct unlink_psx_rq
));
847 pSMB
->TotalDataCount
= cpu_to_le16(sizeof(struct unlink_psx_rq
));
848 pSMB
->ParameterCount
= cpu_to_le16(params
);
849 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
850 pSMB
->InformationLevel
= cpu_to_le16(SMB_POSIX_UNLINK
);
852 pSMB
->hdr
.smb_buf_length
+= byte_count
;
853 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
854 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
855 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
857 cFYI(1, "Posix delete returned %d", rc
);
858 cifs_buf_release(pSMB
);
860 cifs_stats_inc(&tcon
->num_deletes
);
869 CIFSSMBDelFile(const int xid
, struct cifsTconInfo
*tcon
, const char *fileName
,
870 const struct nls_table
*nls_codepage
, int remap
)
872 DELETE_FILE_REQ
*pSMB
= NULL
;
873 DELETE_FILE_RSP
*pSMBr
= NULL
;
879 rc
= smb_init(SMB_COM_DELETE
, 1, tcon
, (void **) &pSMB
,
884 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
886 cifsConvertToUCS((__le16
*) pSMB
->fileName
, fileName
,
887 PATH_MAX
, nls_codepage
, remap
);
888 name_len
++; /* trailing null */
890 } else { /* BB improve check for buffer overruns BB */
891 name_len
= strnlen(fileName
, PATH_MAX
);
892 name_len
++; /* trailing null */
893 strncpy(pSMB
->fileName
, fileName
, name_len
);
895 pSMB
->SearchAttributes
=
896 cpu_to_le16(ATTR_READONLY
| ATTR_HIDDEN
| ATTR_SYSTEM
);
897 pSMB
->BufferFormat
= 0x04;
898 pSMB
->hdr
.smb_buf_length
+= name_len
+ 1;
899 pSMB
->ByteCount
= cpu_to_le16(name_len
+ 1);
900 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
901 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
902 cifs_stats_inc(&tcon
->num_deletes
);
904 cFYI(1, "Error in RMFile = %d", rc
);
906 cifs_buf_release(pSMB
);
914 CIFSSMBRmDir(const int xid
, struct cifsTconInfo
*tcon
, const char *dirName
,
915 const struct nls_table
*nls_codepage
, int remap
)
917 DELETE_DIRECTORY_REQ
*pSMB
= NULL
;
918 DELETE_DIRECTORY_RSP
*pSMBr
= NULL
;
923 cFYI(1, "In CIFSSMBRmDir");
925 rc
= smb_init(SMB_COM_DELETE_DIRECTORY
, 0, tcon
, (void **) &pSMB
,
930 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
931 name_len
= cifsConvertToUCS((__le16
*) pSMB
->DirName
, dirName
,
932 PATH_MAX
, nls_codepage
, remap
);
933 name_len
++; /* trailing null */
935 } else { /* BB improve check for buffer overruns BB */
936 name_len
= strnlen(dirName
, PATH_MAX
);
937 name_len
++; /* trailing null */
938 strncpy(pSMB
->DirName
, dirName
, name_len
);
941 pSMB
->BufferFormat
= 0x04;
942 pSMB
->hdr
.smb_buf_length
+= name_len
+ 1;
943 pSMB
->ByteCount
= cpu_to_le16(name_len
+ 1);
944 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
945 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
946 cifs_stats_inc(&tcon
->num_rmdirs
);
948 cFYI(1, "Error in RMDir = %d", rc
);
950 cifs_buf_release(pSMB
);
957 CIFSSMBMkDir(const int xid
, struct cifsTconInfo
*tcon
,
958 const char *name
, const struct nls_table
*nls_codepage
, int remap
)
961 CREATE_DIRECTORY_REQ
*pSMB
= NULL
;
962 CREATE_DIRECTORY_RSP
*pSMBr
= NULL
;
966 cFYI(1, "In CIFSSMBMkDir");
968 rc
= smb_init(SMB_COM_CREATE_DIRECTORY
, 0, tcon
, (void **) &pSMB
,
973 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
974 name_len
= cifsConvertToUCS((__le16
*) pSMB
->DirName
, name
,
975 PATH_MAX
, nls_codepage
, remap
);
976 name_len
++; /* trailing null */
978 } else { /* BB improve check for buffer overruns BB */
979 name_len
= strnlen(name
, PATH_MAX
);
980 name_len
++; /* trailing null */
981 strncpy(pSMB
->DirName
, name
, name_len
);
984 pSMB
->BufferFormat
= 0x04;
985 pSMB
->hdr
.smb_buf_length
+= name_len
+ 1;
986 pSMB
->ByteCount
= cpu_to_le16(name_len
+ 1);
987 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
988 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
989 cifs_stats_inc(&tcon
->num_mkdirs
);
991 cFYI(1, "Error in Mkdir = %d", rc
);
993 cifs_buf_release(pSMB
);
1000 CIFSPOSIXCreate(const int xid
, struct cifsTconInfo
*tcon
, __u32 posix_flags
,
1001 __u64 mode
, __u16
*netfid
, FILE_UNIX_BASIC_INFO
*pRetData
,
1002 __u32
*pOplock
, const char *name
,
1003 const struct nls_table
*nls_codepage
, int remap
)
1005 TRANSACTION2_SPI_REQ
*pSMB
= NULL
;
1006 TRANSACTION2_SPI_RSP
*pSMBr
= NULL
;
1009 int bytes_returned
= 0;
1010 __u16 params
, param_offset
, offset
, byte_count
, count
;
1011 OPEN_PSX_REQ
*pdata
;
1012 OPEN_PSX_RSP
*psx_rsp
;
1014 cFYI(1, "In POSIX Create");
1016 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
1021 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
1023 cifsConvertToUCS((__le16
*) pSMB
->FileName
, name
,
1024 PATH_MAX
, nls_codepage
, remap
);
1025 name_len
++; /* trailing null */
1027 } else { /* BB improve the check for buffer overruns BB */
1028 name_len
= strnlen(name
, PATH_MAX
);
1029 name_len
++; /* trailing null */
1030 strncpy(pSMB
->FileName
, name
, name_len
);
1033 params
= 6 + name_len
;
1034 count
= sizeof(OPEN_PSX_REQ
);
1035 pSMB
->MaxParameterCount
= cpu_to_le16(2);
1036 pSMB
->MaxDataCount
= cpu_to_le16(1000); /* large enough */
1037 pSMB
->MaxSetupCount
= 0;
1041 pSMB
->Reserved2
= 0;
1042 param_offset
= offsetof(struct smb_com_transaction2_spi_req
,
1043 InformationLevel
) - 4;
1044 offset
= param_offset
+ params
;
1045 pdata
= (OPEN_PSX_REQ
*)(((char *)&pSMB
->hdr
.Protocol
) + offset
);
1046 pdata
->Level
= cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC
);
1047 pdata
->Permissions
= cpu_to_le64(mode
);
1048 pdata
->PosixOpenFlags
= cpu_to_le32(posix_flags
);
1049 pdata
->OpenFlags
= cpu_to_le32(*pOplock
);
1050 pSMB
->ParameterOffset
= cpu_to_le16(param_offset
);
1051 pSMB
->DataOffset
= cpu_to_le16(offset
);
1052 pSMB
->SetupCount
= 1;
1053 pSMB
->Reserved3
= 0;
1054 pSMB
->SubCommand
= cpu_to_le16(TRANS2_SET_PATH_INFORMATION
);
1055 byte_count
= 3 /* pad */ + params
+ count
;
1057 pSMB
->DataCount
= cpu_to_le16(count
);
1058 pSMB
->ParameterCount
= cpu_to_le16(params
);
1059 pSMB
->TotalDataCount
= pSMB
->DataCount
;
1060 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
1061 pSMB
->InformationLevel
= cpu_to_le16(SMB_POSIX_OPEN
);
1062 pSMB
->Reserved4
= 0;
1063 pSMB
->hdr
.smb_buf_length
+= byte_count
;
1064 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
1065 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
1066 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
1068 cFYI(1, "Posix create returned %d", rc
);
1069 goto psx_create_err
;
1072 cFYI(1, "copying inode info");
1073 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
1075 if (rc
|| (pSMBr
->ByteCount
< sizeof(OPEN_PSX_RSP
))) {
1076 rc
= -EIO
; /* bad smb */
1077 goto psx_create_err
;
1080 /* copy return information to pRetData */
1081 psx_rsp
= (OPEN_PSX_RSP
*)((char *) &pSMBr
->hdr
.Protocol
1082 + le16_to_cpu(pSMBr
->t2
.DataOffset
));
1084 *pOplock
= le16_to_cpu(psx_rsp
->OplockFlags
);
1086 *netfid
= psx_rsp
->Fid
; /* cifs fid stays in le */
1087 /* Let caller know file was created so we can set the mode. */
1088 /* Do we care about the CreateAction in any other cases? */
1089 if (cpu_to_le32(FILE_CREATE
) == psx_rsp
->CreateAction
)
1090 *pOplock
|= CIFS_CREATE_ACTION
;
1091 /* check to make sure response data is there */
1092 if (psx_rsp
->ReturnedLevel
!= cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC
)) {
1093 pRetData
->Type
= cpu_to_le32(-1); /* unknown */
1094 cFYI(DBG2
, "unknown type");
1096 if (pSMBr
->ByteCount
< sizeof(OPEN_PSX_RSP
)
1097 + sizeof(FILE_UNIX_BASIC_INFO
)) {
1098 cERROR(1, "Open response data too small");
1099 pRetData
->Type
= cpu_to_le32(-1);
1100 goto psx_create_err
;
1102 memcpy((char *) pRetData
,
1103 (char *)psx_rsp
+ sizeof(OPEN_PSX_RSP
),
1104 sizeof(FILE_UNIX_BASIC_INFO
));
1108 cifs_buf_release(pSMB
);
1110 if (posix_flags
& SMB_O_DIRECTORY
)
1111 cifs_stats_inc(&tcon
->num_posixmkdirs
);
1113 cifs_stats_inc(&tcon
->num_posixopens
);
1121 static __u16
convert_disposition(int disposition
)
1125 switch (disposition
) {
1126 case FILE_SUPERSEDE
:
1127 ofun
= SMBOPEN_OCREATE
| SMBOPEN_OTRUNC
;
1130 ofun
= SMBOPEN_OAPPEND
;
1133 ofun
= SMBOPEN_OCREATE
;
1136 ofun
= SMBOPEN_OCREATE
| SMBOPEN_OAPPEND
;
1138 case FILE_OVERWRITE
:
1139 ofun
= SMBOPEN_OTRUNC
;
1141 case FILE_OVERWRITE_IF
:
1142 ofun
= SMBOPEN_OCREATE
| SMBOPEN_OTRUNC
;
1145 cFYI(1, "unknown disposition %d", disposition
);
1146 ofun
= SMBOPEN_OAPPEND
; /* regular open */
1152 access_flags_to_smbopen_mode(const int access_flags
)
1154 int masked_flags
= access_flags
& (GENERIC_READ
| GENERIC_WRITE
);
1156 if (masked_flags
== GENERIC_READ
)
1157 return SMBOPEN_READ
;
1158 else if (masked_flags
== GENERIC_WRITE
)
1159 return SMBOPEN_WRITE
;
1161 /* just go for read/write */
1162 return SMBOPEN_READWRITE
;
1166 SMBLegacyOpen(const int xid
, struct cifsTconInfo
*tcon
,
1167 const char *fileName
, const int openDisposition
,
1168 const int access_flags
, const int create_options
, __u16
*netfid
,
1169 int *pOplock
, FILE_ALL_INFO
*pfile_info
,
1170 const struct nls_table
*nls_codepage
, int remap
)
1173 OPENX_REQ
*pSMB
= NULL
;
1174 OPENX_RSP
*pSMBr
= NULL
;
1180 rc
= smb_init(SMB_COM_OPEN_ANDX
, 15, tcon
, (void **) &pSMB
,
1185 pSMB
->AndXCommand
= 0xFF; /* none */
1187 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
1188 count
= 1; /* account for one byte pad to word boundary */
1190 cifsConvertToUCS((__le16
*) (pSMB
->fileName
+ 1),
1191 fileName
, PATH_MAX
, nls_codepage
, remap
);
1192 name_len
++; /* trailing null */
1194 } else { /* BB improve check for buffer overruns BB */
1195 count
= 0; /* no pad */
1196 name_len
= strnlen(fileName
, PATH_MAX
);
1197 name_len
++; /* trailing null */
1198 strncpy(pSMB
->fileName
, fileName
, name_len
);
1200 if (*pOplock
& REQ_OPLOCK
)
1201 pSMB
->OpenFlags
= cpu_to_le16(REQ_OPLOCK
);
1202 else if (*pOplock
& REQ_BATCHOPLOCK
)
1203 pSMB
->OpenFlags
= cpu_to_le16(REQ_BATCHOPLOCK
);
1205 pSMB
->OpenFlags
|= cpu_to_le16(REQ_MORE_INFO
);
1206 pSMB
->Mode
= cpu_to_le16(access_flags_to_smbopen_mode(access_flags
));
1207 pSMB
->Mode
|= cpu_to_le16(0x40); /* deny none */
1208 /* set file as system file if special file such
1209 as fifo and server expecting SFU style and
1210 no Unix extensions */
1212 if (create_options
& CREATE_OPTION_SPECIAL
)
1213 pSMB
->FileAttributes
= cpu_to_le16(ATTR_SYSTEM
);
1214 else /* BB FIXME BB */
1215 pSMB
->FileAttributes
= cpu_to_le16(0/*ATTR_NORMAL*/);
1217 if (create_options
& CREATE_OPTION_READONLY
)
1218 pSMB
->FileAttributes
|= cpu_to_le16(ATTR_READONLY
);
1221 /* pSMB->CreateOptions = cpu_to_le32(create_options &
1222 CREATE_OPTIONS_MASK); */
1223 /* BB FIXME END BB */
1225 pSMB
->Sattr
= cpu_to_le16(ATTR_HIDDEN
| ATTR_SYSTEM
| ATTR_DIRECTORY
);
1226 pSMB
->OpenFunction
= cpu_to_le16(convert_disposition(openDisposition
));
1228 pSMB
->hdr
.smb_buf_length
+= count
;
1230 pSMB
->ByteCount
= cpu_to_le16(count
);
1231 /* long_op set to 1 to allow for oplock break timeouts */
1232 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
1233 (struct smb_hdr
*)pSMBr
, &bytes_returned
, 0);
1234 cifs_stats_inc(&tcon
->num_opens
);
1236 cFYI(1, "Error in Open = %d", rc
);
1238 /* BB verify if wct == 15 */
1240 /* *pOplock = pSMBr->OplockLevel; */ /* BB take from action field*/
1242 *netfid
= pSMBr
->Fid
; /* cifs fid stays in le */
1243 /* Let caller know file was created so we can set the mode. */
1244 /* Do we care about the CreateAction in any other cases? */
1246 /* if (cpu_to_le32(FILE_CREATE) == pSMBr->CreateAction)
1247 *pOplock |= CIFS_CREATE_ACTION; */
1251 pfile_info
->CreationTime
= 0; /* BB convert CreateTime*/
1252 pfile_info
->LastAccessTime
= 0; /* BB fixme */
1253 pfile_info
->LastWriteTime
= 0; /* BB fixme */
1254 pfile_info
->ChangeTime
= 0; /* BB fixme */
1255 pfile_info
->Attributes
=
1256 cpu_to_le32(le16_to_cpu(pSMBr
->FileAttributes
));
1257 /* the file_info buf is endian converted by caller */
1258 pfile_info
->AllocationSize
=
1259 cpu_to_le64(le32_to_cpu(pSMBr
->EndOfFile
));
1260 pfile_info
->EndOfFile
= pfile_info
->AllocationSize
;
1261 pfile_info
->NumberOfLinks
= cpu_to_le32(1);
1262 pfile_info
->DeletePending
= 0;
1266 cifs_buf_release(pSMB
);
1273 CIFSSMBOpen(const int xid
, struct cifsTconInfo
*tcon
,
1274 const char *fileName
, const int openDisposition
,
1275 const int access_flags
, const int create_options
, __u16
*netfid
,
1276 int *pOplock
, FILE_ALL_INFO
*pfile_info
,
1277 const struct nls_table
*nls_codepage
, int remap
)
1280 OPEN_REQ
*pSMB
= NULL
;
1281 OPEN_RSP
*pSMBr
= NULL
;
1287 rc
= smb_init(SMB_COM_NT_CREATE_ANDX
, 24, tcon
, (void **) &pSMB
,
1292 pSMB
->AndXCommand
= 0xFF; /* none */
1294 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
1295 count
= 1; /* account for one byte pad to word boundary */
1297 cifsConvertToUCS((__le16
*) (pSMB
->fileName
+ 1),
1298 fileName
, PATH_MAX
, nls_codepage
, remap
);
1299 name_len
++; /* trailing null */
1301 pSMB
->NameLength
= cpu_to_le16(name_len
);
1302 } else { /* BB improve check for buffer overruns BB */
1303 count
= 0; /* no pad */
1304 name_len
= strnlen(fileName
, PATH_MAX
);
1305 name_len
++; /* trailing null */
1306 pSMB
->NameLength
= cpu_to_le16(name_len
);
1307 strncpy(pSMB
->fileName
, fileName
, name_len
);
1309 if (*pOplock
& REQ_OPLOCK
)
1310 pSMB
->OpenFlags
= cpu_to_le32(REQ_OPLOCK
);
1311 else if (*pOplock
& REQ_BATCHOPLOCK
)
1312 pSMB
->OpenFlags
= cpu_to_le32(REQ_BATCHOPLOCK
);
1313 pSMB
->DesiredAccess
= cpu_to_le32(access_flags
);
1314 pSMB
->AllocationSize
= 0;
1315 /* set file as system file if special file such
1316 as fifo and server expecting SFU style and
1317 no Unix extensions */
1318 if (create_options
& CREATE_OPTION_SPECIAL
)
1319 pSMB
->FileAttributes
= cpu_to_le32(ATTR_SYSTEM
);
1321 pSMB
->FileAttributes
= cpu_to_le32(ATTR_NORMAL
);
1323 /* XP does not handle ATTR_POSIX_SEMANTICS */
1324 /* but it helps speed up case sensitive checks for other
1325 servers such as Samba */
1326 if (tcon
->ses
->capabilities
& CAP_UNIX
)
1327 pSMB
->FileAttributes
|= cpu_to_le32(ATTR_POSIX_SEMANTICS
);
1329 if (create_options
& CREATE_OPTION_READONLY
)
1330 pSMB
->FileAttributes
|= cpu_to_le32(ATTR_READONLY
);
1332 pSMB
->ShareAccess
= cpu_to_le32(FILE_SHARE_ALL
);
1333 pSMB
->CreateDisposition
= cpu_to_le32(openDisposition
);
1334 pSMB
->CreateOptions
= cpu_to_le32(create_options
& CREATE_OPTIONS_MASK
);
1335 /* BB Expirement with various impersonation levels and verify */
1336 pSMB
->ImpersonationLevel
= cpu_to_le32(SECURITY_IMPERSONATION
);
1337 pSMB
->SecurityFlags
=
1338 SECURITY_CONTEXT_TRACKING
| SECURITY_EFFECTIVE_ONLY
;
1341 pSMB
->hdr
.smb_buf_length
+= count
;
1343 pSMB
->ByteCount
= cpu_to_le16(count
);
1344 /* long_op set to 1 to allow for oplock break timeouts */
1345 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
1346 (struct smb_hdr
*)pSMBr
, &bytes_returned
, 0);
1347 cifs_stats_inc(&tcon
->num_opens
);
1349 cFYI(1, "Error in Open = %d", rc
);
1351 *pOplock
= pSMBr
->OplockLevel
; /* 1 byte no need to le_to_cpu */
1352 *netfid
= pSMBr
->Fid
; /* cifs fid stays in le */
1353 /* Let caller know file was created so we can set the mode. */
1354 /* Do we care about the CreateAction in any other cases? */
1355 if (cpu_to_le32(FILE_CREATE
) == pSMBr
->CreateAction
)
1356 *pOplock
|= CIFS_CREATE_ACTION
;
1358 memcpy((char *)pfile_info
, (char *)&pSMBr
->CreationTime
,
1359 36 /* CreationTime to Attributes */);
1360 /* the file_info buf is endian converted by caller */
1361 pfile_info
->AllocationSize
= pSMBr
->AllocationSize
;
1362 pfile_info
->EndOfFile
= pSMBr
->EndOfFile
;
1363 pfile_info
->NumberOfLinks
= cpu_to_le32(1);
1364 pfile_info
->DeletePending
= 0;
1368 cifs_buf_release(pSMB
);
1375 CIFSSMBRead(const int xid
, struct cifsTconInfo
*tcon
, const int netfid
,
1376 const unsigned int count
, const __u64 lseek
, unsigned int *nbytes
,
1377 char **buf
, int *pbuf_type
)
1380 READ_REQ
*pSMB
= NULL
;
1381 READ_RSP
*pSMBr
= NULL
;
1382 char *pReadData
= NULL
;
1384 int resp_buf_type
= 0;
1387 cFYI(1, "Reading %d bytes on fid %d", count
, netfid
);
1388 if (tcon
->ses
->capabilities
& CAP_LARGE_FILES
)
1391 wct
= 10; /* old style read */
1392 if ((lseek
>> 32) > 0) {
1393 /* can not handle this big offset for old */
1399 rc
= small_smb_init(SMB_COM_READ_ANDX
, wct
, tcon
, (void **) &pSMB
);
1403 /* tcon and ses pointer are checked in smb_init */
1404 if (tcon
->ses
->server
== NULL
)
1405 return -ECONNABORTED
;
1407 pSMB
->AndXCommand
= 0xFF; /* none */
1409 pSMB
->OffsetLow
= cpu_to_le32(lseek
& 0xFFFFFFFF);
1411 pSMB
->OffsetHigh
= cpu_to_le32(lseek
>> 32);
1413 pSMB
->Remaining
= 0;
1414 pSMB
->MaxCount
= cpu_to_le16(count
& 0xFFFF);
1415 pSMB
->MaxCountHigh
= cpu_to_le32(count
>> 16);
1417 pSMB
->ByteCount
= 0; /* no need to do le conversion since 0 */
1419 /* old style read */
1420 struct smb_com_readx_req
*pSMBW
=
1421 (struct smb_com_readx_req
*)pSMB
;
1422 pSMBW
->ByteCount
= 0;
1425 iov
[0].iov_base
= (char *)pSMB
;
1426 iov
[0].iov_len
= pSMB
->hdr
.smb_buf_length
+ 4;
1427 rc
= SendReceive2(xid
, tcon
->ses
, iov
, 1 /* num iovecs */,
1428 &resp_buf_type
, CIFS_LOG_ERROR
);
1429 cifs_stats_inc(&tcon
->num_reads
);
1430 pSMBr
= (READ_RSP
*)iov
[0].iov_base
;
1432 cERROR(1, "Send error in read = %d", rc
);
1434 int data_length
= le16_to_cpu(pSMBr
->DataLengthHigh
);
1435 data_length
= data_length
<< 16;
1436 data_length
+= le16_to_cpu(pSMBr
->DataLength
);
1437 *nbytes
= data_length
;
1439 /*check that DataLength would not go beyond end of SMB */
1440 if ((data_length
> CIFSMaxBufSize
)
1441 || (data_length
> count
)) {
1442 cFYI(1, "bad length %d for count %d",
1443 data_length
, count
);
1447 pReadData
= (char *) (&pSMBr
->hdr
.Protocol
) +
1448 le16_to_cpu(pSMBr
->DataOffset
);
1449 /* if (rc = copy_to_user(buf, pReadData, data_length)) {
1450 cERROR(1, "Faulting on read rc = %d",rc);
1452 }*/ /* can not use copy_to_user when using page cache*/
1454 memcpy(*buf
, pReadData
, data_length
);
1458 /* cifs_small_buf_release(pSMB); */ /* Freed earlier now in SendReceive2 */
1460 if (resp_buf_type
== CIFS_SMALL_BUFFER
)
1461 cifs_small_buf_release(iov
[0].iov_base
);
1462 else if (resp_buf_type
== CIFS_LARGE_BUFFER
)
1463 cifs_buf_release(iov
[0].iov_base
);
1464 } else if (resp_buf_type
!= CIFS_NO_BUFFER
) {
1465 /* return buffer to caller to free */
1466 *buf
= iov
[0].iov_base
;
1467 if (resp_buf_type
== CIFS_SMALL_BUFFER
)
1468 *pbuf_type
= CIFS_SMALL_BUFFER
;
1469 else if (resp_buf_type
== CIFS_LARGE_BUFFER
)
1470 *pbuf_type
= CIFS_LARGE_BUFFER
;
1471 } /* else no valid buffer on return - leave as null */
1473 /* Note: On -EAGAIN error only caller can retry on handle based calls
1474 since file handle passed in no longer valid */
1480 CIFSSMBWrite(const int xid
, struct cifsTconInfo
*tcon
,
1481 const int netfid
, const unsigned int count
,
1482 const __u64 offset
, unsigned int *nbytes
, const char *buf
,
1483 const char __user
*ubuf
, const int long_op
)
1486 WRITE_REQ
*pSMB
= NULL
;
1487 WRITE_RSP
*pSMBr
= NULL
;
1488 int bytes_returned
, wct
;
1494 /* cFYI(1, "write at %lld %d bytes", offset, count);*/
1495 if (tcon
->ses
== NULL
)
1496 return -ECONNABORTED
;
1498 if (tcon
->ses
->capabilities
& CAP_LARGE_FILES
)
1502 if ((offset
>> 32) > 0) {
1503 /* can not handle big offset for old srv */
1508 rc
= smb_init(SMB_COM_WRITE_ANDX
, wct
, tcon
, (void **) &pSMB
,
1512 /* tcon and ses pointer are checked in smb_init */
1513 if (tcon
->ses
->server
== NULL
)
1514 return -ECONNABORTED
;
1516 pSMB
->AndXCommand
= 0xFF; /* none */
1518 pSMB
->OffsetLow
= cpu_to_le32(offset
& 0xFFFFFFFF);
1520 pSMB
->OffsetHigh
= cpu_to_le32(offset
>> 32);
1522 pSMB
->Reserved
= 0xFFFFFFFF;
1523 pSMB
->WriteMode
= 0;
1524 pSMB
->Remaining
= 0;
1526 /* Can increase buffer size if buffer is big enough in some cases ie we
1527 can send more if LARGE_WRITE_X capability returned by the server and if
1528 our buffer is big enough or if we convert to iovecs on socket writes
1529 and eliminate the copy to the CIFS buffer */
1530 if (tcon
->ses
->capabilities
& CAP_LARGE_WRITE_X
) {
1531 bytes_sent
= min_t(const unsigned int, CIFSMaxBufSize
, count
);
1533 bytes_sent
= (tcon
->ses
->server
->maxBuf
- MAX_CIFS_HDR_SIZE
)
1537 if (bytes_sent
> count
)
1540 cpu_to_le16(offsetof(struct smb_com_write_req
, Data
) - 4);
1542 memcpy(pSMB
->Data
, buf
, bytes_sent
);
1544 if (copy_from_user(pSMB
->Data
, ubuf
, bytes_sent
)) {
1545 cifs_buf_release(pSMB
);
1548 } else if (count
!= 0) {
1550 cifs_buf_release(pSMB
);
1552 } /* else setting file size with write of zero bytes */
1554 byte_count
= bytes_sent
+ 1; /* pad */
1555 else /* wct == 12 */
1556 byte_count
= bytes_sent
+ 5; /* bigger pad, smaller smb hdr */
1558 pSMB
->DataLengthLow
= cpu_to_le16(bytes_sent
& 0xFFFF);
1559 pSMB
->DataLengthHigh
= cpu_to_le16(bytes_sent
>> 16);
1560 pSMB
->hdr
.smb_buf_length
+= byte_count
;
1563 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
1564 else { /* old style write has byte count 4 bytes earlier
1566 struct smb_com_writex_req
*pSMBW
=
1567 (struct smb_com_writex_req
*)pSMB
;
1568 pSMBW
->ByteCount
= cpu_to_le16(byte_count
);
1571 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
1572 (struct smb_hdr
*) pSMBr
, &bytes_returned
, long_op
);
1573 cifs_stats_inc(&tcon
->num_writes
);
1575 cFYI(1, "Send error in write = %d", rc
);
1577 *nbytes
= le16_to_cpu(pSMBr
->CountHigh
);
1578 *nbytes
= (*nbytes
) << 16;
1579 *nbytes
+= le16_to_cpu(pSMBr
->Count
);
1582 * Mask off high 16 bits when bytes written as returned by the
1583 * server is greater than bytes requested by the client. Some
1584 * OS/2 servers are known to set incorrect CountHigh values.
1586 if (*nbytes
> count
)
1590 cifs_buf_release(pSMB
);
1592 /* Note: On -EAGAIN error only caller can retry on handle based calls
1593 since file handle passed in no longer valid */
1599 CIFSSMBWrite2(const int xid
, struct cifsTconInfo
*tcon
,
1600 const int netfid
, const unsigned int count
,
1601 const __u64 offset
, unsigned int *nbytes
, struct kvec
*iov
,
1602 int n_vec
, const int long_op
)
1605 WRITE_REQ
*pSMB
= NULL
;
1608 int resp_buf_type
= 0;
1612 cFYI(1, "write2 at %lld %d bytes", (long long)offset
, count
);
1614 if (tcon
->ses
->capabilities
& CAP_LARGE_FILES
) {
1618 if ((offset
>> 32) > 0) {
1619 /* can not handle big offset for old srv */
1623 rc
= small_smb_init(SMB_COM_WRITE_ANDX
, wct
, tcon
, (void **) &pSMB
);
1626 /* tcon and ses pointer are checked in smb_init */
1627 if (tcon
->ses
->server
== NULL
)
1628 return -ECONNABORTED
;
1630 pSMB
->AndXCommand
= 0xFF; /* none */
1632 pSMB
->OffsetLow
= cpu_to_le32(offset
& 0xFFFFFFFF);
1634 pSMB
->OffsetHigh
= cpu_to_le32(offset
>> 32);
1635 pSMB
->Reserved
= 0xFFFFFFFF;
1636 pSMB
->WriteMode
= 0;
1637 pSMB
->Remaining
= 0;
1640 cpu_to_le16(offsetof(struct smb_com_write_req
, Data
) - 4);
1642 pSMB
->DataLengthLow
= cpu_to_le16(count
& 0xFFFF);
1643 pSMB
->DataLengthHigh
= cpu_to_le16(count
>> 16);
1644 smb_hdr_len
= pSMB
->hdr
.smb_buf_length
+ 1; /* hdr + 1 byte pad */
1646 pSMB
->hdr
.smb_buf_length
+= count
+1;
1647 else /* wct == 12 */
1648 pSMB
->hdr
.smb_buf_length
+= count
+5; /* smb data starts later */
1650 pSMB
->ByteCount
= cpu_to_le16(count
+ 1);
1651 else /* wct == 12 */ /* bigger pad, smaller smb hdr, keep offset ok */ {
1652 struct smb_com_writex_req
*pSMBW
=
1653 (struct smb_com_writex_req
*)pSMB
;
1654 pSMBW
->ByteCount
= cpu_to_le16(count
+ 5);
1656 iov
[0].iov_base
= pSMB
;
1658 iov
[0].iov_len
= smb_hdr_len
+ 4;
1659 else /* wct == 12 pad bigger by four bytes */
1660 iov
[0].iov_len
= smb_hdr_len
+ 8;
1663 rc
= SendReceive2(xid
, tcon
->ses
, iov
, n_vec
+ 1, &resp_buf_type
,
1665 cifs_stats_inc(&tcon
->num_writes
);
1667 cFYI(1, "Send error Write2 = %d", rc
);
1668 } else if (resp_buf_type
== 0) {
1669 /* presumably this can not happen, but best to be safe */
1672 WRITE_RSP
*pSMBr
= (WRITE_RSP
*)iov
[0].iov_base
;
1673 *nbytes
= le16_to_cpu(pSMBr
->CountHigh
);
1674 *nbytes
= (*nbytes
) << 16;
1675 *nbytes
+= le16_to_cpu(pSMBr
->Count
);
1678 * Mask off high 16 bits when bytes written as returned by the
1679 * server is greater than bytes requested by the client. OS/2
1680 * servers are known to set incorrect CountHigh values.
1682 if (*nbytes
> count
)
1686 /* cifs_small_buf_release(pSMB); */ /* Freed earlier now in SendReceive2 */
1687 if (resp_buf_type
== CIFS_SMALL_BUFFER
)
1688 cifs_small_buf_release(iov
[0].iov_base
);
1689 else if (resp_buf_type
== CIFS_LARGE_BUFFER
)
1690 cifs_buf_release(iov
[0].iov_base
);
1692 /* Note: On -EAGAIN error only caller can retry on handle based calls
1693 since file handle passed in no longer valid */
1700 CIFSSMBLock(const int xid
, struct cifsTconInfo
*tcon
,
1701 const __u16 smb_file_id
, const __u64 len
,
1702 const __u64 offset
, const __u32 numUnlock
,
1703 const __u32 numLock
, const __u8 lockType
,
1704 const bool waitFlag
, const __u8 oplock_level
)
1707 LOCK_REQ
*pSMB
= NULL
;
1708 /* LOCK_RSP *pSMBr = NULL; */ /* No response data other than rc to parse */
1713 cFYI(1, "CIFSSMBLock timeout %d numLock %d", (int)waitFlag
, numLock
);
1714 rc
= small_smb_init(SMB_COM_LOCKING_ANDX
, 8, tcon
, (void **) &pSMB
);
1719 if (lockType
== LOCKING_ANDX_OPLOCK_RELEASE
) {
1720 timeout
= CIFS_ASYNC_OP
; /* no response expected */
1722 } else if (waitFlag
) {
1723 timeout
= CIFS_BLOCKING_OP
; /* blocking operation, no timeout */
1724 pSMB
->Timeout
= cpu_to_le32(-1);/* blocking - do not time out */
1729 pSMB
->NumberOfLocks
= cpu_to_le16(numLock
);
1730 pSMB
->NumberOfUnlocks
= cpu_to_le16(numUnlock
);
1731 pSMB
->LockType
= lockType
;
1732 pSMB
->OplockLevel
= oplock_level
;
1733 pSMB
->AndXCommand
= 0xFF; /* none */
1734 pSMB
->Fid
= smb_file_id
; /* netfid stays le */
1736 if ((numLock
!= 0) || (numUnlock
!= 0)) {
1737 pSMB
->Locks
[0].Pid
= cpu_to_le16(current
->tgid
);
1738 /* BB where to store pid high? */
1739 pSMB
->Locks
[0].LengthLow
= cpu_to_le32((u32
)len
);
1740 pSMB
->Locks
[0].LengthHigh
= cpu_to_le32((u32
)(len
>>32));
1741 pSMB
->Locks
[0].OffsetLow
= cpu_to_le32((u32
)offset
);
1742 pSMB
->Locks
[0].OffsetHigh
= cpu_to_le32((u32
)(offset
>>32));
1743 count
= sizeof(LOCKING_ANDX_RANGE
);
1748 pSMB
->hdr
.smb_buf_length
+= count
;
1749 pSMB
->ByteCount
= cpu_to_le16(count
);
1752 rc
= SendReceiveBlockingLock(xid
, tcon
, (struct smb_hdr
*) pSMB
,
1753 (struct smb_hdr
*) pSMB
, &bytes_returned
);
1754 cifs_small_buf_release(pSMB
);
1756 rc
= SendReceiveNoRsp(xid
, tcon
->ses
, (struct smb_hdr
*)pSMB
,
1758 /* SMB buffer freed by function above */
1760 cifs_stats_inc(&tcon
->num_locks
);
1762 cFYI(1, "Send error in Lock = %d", rc
);
1764 /* Note: On -EAGAIN error only caller can retry on handle based calls
1765 since file handle passed in no longer valid */
1770 CIFSSMBPosixLock(const int xid
, struct cifsTconInfo
*tcon
,
1771 const __u16 smb_file_id
, const int get_flag
, const __u64 len
,
1772 struct file_lock
*pLockData
, const __u16 lock_type
,
1773 const bool waitFlag
)
1775 struct smb_com_transaction2_sfi_req
*pSMB
= NULL
;
1776 struct smb_com_transaction2_sfi_rsp
*pSMBr
= NULL
;
1777 struct cifs_posix_lock
*parm_data
;
1780 int bytes_returned
= 0;
1781 int resp_buf_type
= 0;
1782 __u16 params
, param_offset
, offset
, byte_count
, count
;
1785 cFYI(1, "Posix Lock");
1787 if (pLockData
== NULL
)
1790 rc
= small_smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
);
1795 pSMBr
= (struct smb_com_transaction2_sfi_rsp
*)pSMB
;
1798 pSMB
->MaxSetupCount
= 0;
1801 pSMB
->Reserved2
= 0;
1802 param_offset
= offsetof(struct smb_com_transaction2_sfi_req
, Fid
) - 4;
1803 offset
= param_offset
+ params
;
1805 count
= sizeof(struct cifs_posix_lock
);
1806 pSMB
->MaxParameterCount
= cpu_to_le16(2);
1807 pSMB
->MaxDataCount
= cpu_to_le16(1000); /* BB find max SMB from sess */
1808 pSMB
->SetupCount
= 1;
1809 pSMB
->Reserved3
= 0;
1811 pSMB
->SubCommand
= cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION
);
1813 pSMB
->SubCommand
= cpu_to_le16(TRANS2_SET_FILE_INFORMATION
);
1814 byte_count
= 3 /* pad */ + params
+ count
;
1815 pSMB
->DataCount
= cpu_to_le16(count
);
1816 pSMB
->ParameterCount
= cpu_to_le16(params
);
1817 pSMB
->TotalDataCount
= pSMB
->DataCount
;
1818 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
1819 pSMB
->ParameterOffset
= cpu_to_le16(param_offset
);
1820 parm_data
= (struct cifs_posix_lock
*)
1821 (((char *) &pSMB
->hdr
.Protocol
) + offset
);
1823 parm_data
->lock_type
= cpu_to_le16(lock_type
);
1825 timeout
= CIFS_BLOCKING_OP
; /* blocking operation, no timeout */
1826 parm_data
->lock_flags
= cpu_to_le16(1);
1827 pSMB
->Timeout
= cpu_to_le32(-1);
1831 parm_data
->pid
= cpu_to_le32(current
->tgid
);
1832 parm_data
->start
= cpu_to_le64(pLockData
->fl_start
);
1833 parm_data
->length
= cpu_to_le64(len
); /* normalize negative numbers */
1835 pSMB
->DataOffset
= cpu_to_le16(offset
);
1836 pSMB
->Fid
= smb_file_id
;
1837 pSMB
->InformationLevel
= cpu_to_le16(SMB_SET_POSIX_LOCK
);
1838 pSMB
->Reserved4
= 0;
1839 pSMB
->hdr
.smb_buf_length
+= byte_count
;
1840 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
1842 rc
= SendReceiveBlockingLock(xid
, tcon
, (struct smb_hdr
*) pSMB
,
1843 (struct smb_hdr
*) pSMBr
, &bytes_returned
);
1845 iov
[0].iov_base
= (char *)pSMB
;
1846 iov
[0].iov_len
= pSMB
->hdr
.smb_buf_length
+ 4;
1847 rc
= SendReceive2(xid
, tcon
->ses
, iov
, 1 /* num iovecs */,
1848 &resp_buf_type
, timeout
);
1849 pSMB
= NULL
; /* request buf already freed by SendReceive2. Do
1850 not try to free it twice below on exit */
1851 pSMBr
= (struct smb_com_transaction2_sfi_rsp
*)iov
[0].iov_base
;
1855 cFYI(1, "Send error in Posix Lock = %d", rc
);
1856 } else if (get_flag
) {
1857 /* lock structure can be returned on get */
1860 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
1862 if (rc
|| (pSMBr
->ByteCount
< sizeof(struct cifs_posix_lock
))) {
1863 rc
= -EIO
; /* bad smb */
1866 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
1867 data_count
= le16_to_cpu(pSMBr
->t2
.DataCount
);
1868 if (data_count
< sizeof(struct cifs_posix_lock
)) {
1872 parm_data
= (struct cifs_posix_lock
*)
1873 ((char *)&pSMBr
->hdr
.Protocol
+ data_offset
);
1874 if (parm_data
->lock_type
== __constant_cpu_to_le16(CIFS_UNLCK
))
1875 pLockData
->fl_type
= F_UNLCK
;
1877 if (parm_data
->lock_type
==
1878 __constant_cpu_to_le16(CIFS_RDLCK
))
1879 pLockData
->fl_type
= F_RDLCK
;
1880 else if (parm_data
->lock_type
==
1881 __constant_cpu_to_le16(CIFS_WRLCK
))
1882 pLockData
->fl_type
= F_WRLCK
;
1884 pLockData
->fl_start
= le64_to_cpu(parm_data
->start
);
1885 pLockData
->fl_end
= pLockData
->fl_start
+
1886 le64_to_cpu(parm_data
->length
) - 1;
1887 pLockData
->fl_pid
= le32_to_cpu(parm_data
->pid
);
1893 cifs_small_buf_release(pSMB
);
1895 if (resp_buf_type
== CIFS_SMALL_BUFFER
)
1896 cifs_small_buf_release(iov
[0].iov_base
);
1897 else if (resp_buf_type
== CIFS_LARGE_BUFFER
)
1898 cifs_buf_release(iov
[0].iov_base
);
1900 /* Note: On -EAGAIN error only caller can retry on handle based calls
1901 since file handle passed in no longer valid */
1908 CIFSSMBClose(const int xid
, struct cifsTconInfo
*tcon
, int smb_file_id
)
1911 CLOSE_REQ
*pSMB
= NULL
;
1912 cFYI(1, "In CIFSSMBClose");
1914 /* do not retry on dead session on close */
1915 rc
= small_smb_init(SMB_COM_CLOSE
, 3, tcon
, (void **) &pSMB
);
1921 pSMB
->FileID
= (__u16
) smb_file_id
;
1922 pSMB
->LastWriteTime
= 0xFFFFFFFF;
1923 pSMB
->ByteCount
= 0;
1924 rc
= SendReceiveNoRsp(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
, 0);
1925 cifs_stats_inc(&tcon
->num_closes
);
1928 /* EINTR is expected when user ctl-c to kill app */
1929 cERROR(1, "Send error in Close = %d", rc
);
1933 /* Since session is dead, file will be closed on server already */
1941 CIFSSMBFlush(const int xid
, struct cifsTconInfo
*tcon
, int smb_file_id
)
1944 FLUSH_REQ
*pSMB
= NULL
;
1945 cFYI(1, "In CIFSSMBFlush");
1947 rc
= small_smb_init(SMB_COM_FLUSH
, 1, tcon
, (void **) &pSMB
);
1951 pSMB
->FileID
= (__u16
) smb_file_id
;
1952 pSMB
->ByteCount
= 0;
1953 rc
= SendReceiveNoRsp(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
, 0);
1954 cifs_stats_inc(&tcon
->num_flushes
);
1956 cERROR(1, "Send error in Flush = %d", rc
);
1962 CIFSSMBRename(const int xid
, struct cifsTconInfo
*tcon
,
1963 const char *fromName
, const char *toName
,
1964 const struct nls_table
*nls_codepage
, int remap
)
1967 RENAME_REQ
*pSMB
= NULL
;
1968 RENAME_RSP
*pSMBr
= NULL
;
1970 int name_len
, name_len2
;
1973 cFYI(1, "In CIFSSMBRename");
1975 rc
= smb_init(SMB_COM_RENAME
, 1, tcon
, (void **) &pSMB
,
1980 pSMB
->BufferFormat
= 0x04;
1981 pSMB
->SearchAttributes
=
1982 cpu_to_le16(ATTR_READONLY
| ATTR_HIDDEN
| ATTR_SYSTEM
|
1985 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
1987 cifsConvertToUCS((__le16
*) pSMB
->OldFileName
, fromName
,
1988 PATH_MAX
, nls_codepage
, remap
);
1989 name_len
++; /* trailing null */
1991 pSMB
->OldFileName
[name_len
] = 0x04; /* pad */
1992 /* protocol requires ASCII signature byte on Unicode string */
1993 pSMB
->OldFileName
[name_len
+ 1] = 0x00;
1995 cifsConvertToUCS((__le16
*)&pSMB
->OldFileName
[name_len
+ 2],
1996 toName
, PATH_MAX
, nls_codepage
, remap
);
1997 name_len2
+= 1 /* trailing null */ + 1 /* Signature word */ ;
1998 name_len2
*= 2; /* convert to bytes */
1999 } else { /* BB improve the check for buffer overruns BB */
2000 name_len
= strnlen(fromName
, PATH_MAX
);
2001 name_len
++; /* trailing null */
2002 strncpy(pSMB
->OldFileName
, fromName
, name_len
);
2003 name_len2
= strnlen(toName
, PATH_MAX
);
2004 name_len2
++; /* trailing null */
2005 pSMB
->OldFileName
[name_len
] = 0x04; /* 2nd buffer format */
2006 strncpy(&pSMB
->OldFileName
[name_len
+ 1], toName
, name_len2
);
2007 name_len2
++; /* trailing null */
2008 name_len2
++; /* signature byte */
2011 count
= 1 /* 1st signature byte */ + name_len
+ name_len2
;
2012 pSMB
->hdr
.smb_buf_length
+= count
;
2013 pSMB
->ByteCount
= cpu_to_le16(count
);
2015 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
2016 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
2017 cifs_stats_inc(&tcon
->num_renames
);
2019 cFYI(1, "Send error in rename = %d", rc
);
2021 cifs_buf_release(pSMB
);
2029 int CIFSSMBRenameOpenFile(const int xid
, struct cifsTconInfo
*pTcon
,
2030 int netfid
, const char *target_name
,
2031 const struct nls_table
*nls_codepage
, int remap
)
2033 struct smb_com_transaction2_sfi_req
*pSMB
= NULL
;
2034 struct smb_com_transaction2_sfi_rsp
*pSMBr
= NULL
;
2035 struct set_file_rename
*rename_info
;
2037 char dummy_string
[30];
2039 int bytes_returned
= 0;
2041 __u16 params
, param_offset
, offset
, count
, byte_count
;
2043 cFYI(1, "Rename to File by handle");
2044 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, pTcon
, (void **) &pSMB
,
2050 pSMB
->MaxSetupCount
= 0;
2054 pSMB
->Reserved2
= 0;
2055 param_offset
= offsetof(struct smb_com_transaction2_sfi_req
, Fid
) - 4;
2056 offset
= param_offset
+ params
;
2058 data_offset
= (char *) (&pSMB
->hdr
.Protocol
) + offset
;
2059 rename_info
= (struct set_file_rename
*) data_offset
;
2060 pSMB
->MaxParameterCount
= cpu_to_le16(2);
2061 pSMB
->MaxDataCount
= cpu_to_le16(1000); /* BB find max SMB from sess */
2062 pSMB
->SetupCount
= 1;
2063 pSMB
->Reserved3
= 0;
2064 pSMB
->SubCommand
= cpu_to_le16(TRANS2_SET_FILE_INFORMATION
);
2065 byte_count
= 3 /* pad */ + params
;
2066 pSMB
->ParameterCount
= cpu_to_le16(params
);
2067 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
2068 pSMB
->ParameterOffset
= cpu_to_le16(param_offset
);
2069 pSMB
->DataOffset
= cpu_to_le16(offset
);
2070 /* construct random name ".cifs_tmp<inodenum><mid>" */
2071 rename_info
->overwrite
= cpu_to_le32(1);
2072 rename_info
->root_fid
= 0;
2073 /* unicode only call */
2074 if (target_name
== NULL
) {
2075 sprintf(dummy_string
, "cifs%x", pSMB
->hdr
.Mid
);
2076 len_of_str
= cifsConvertToUCS((__le16
*)rename_info
->target_name
,
2077 dummy_string
, 24, nls_codepage
, remap
);
2079 len_of_str
= cifsConvertToUCS((__le16
*)rename_info
->target_name
,
2080 target_name
, PATH_MAX
, nls_codepage
,
2083 rename_info
->target_name_len
= cpu_to_le32(2 * len_of_str
);
2084 count
= 12 /* sizeof(struct set_file_rename) */ + (2 * len_of_str
);
2085 byte_count
+= count
;
2086 pSMB
->DataCount
= cpu_to_le16(count
);
2087 pSMB
->TotalDataCount
= pSMB
->DataCount
;
2089 pSMB
->InformationLevel
=
2090 cpu_to_le16(SMB_SET_FILE_RENAME_INFORMATION
);
2091 pSMB
->Reserved4
= 0;
2092 pSMB
->hdr
.smb_buf_length
+= byte_count
;
2093 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
2094 rc
= SendReceive(xid
, pTcon
->ses
, (struct smb_hdr
*) pSMB
,
2095 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
2096 cifs_stats_inc(&pTcon
->num_t2renames
);
2098 cFYI(1, "Send error in Rename (by file handle) = %d", rc
);
2100 cifs_buf_release(pSMB
);
2102 /* Note: On -EAGAIN error only caller can retry on handle based calls
2103 since file handle passed in no longer valid */
2109 CIFSSMBCopy(const int xid
, struct cifsTconInfo
*tcon
, const char *fromName
,
2110 const __u16 target_tid
, const char *toName
, const int flags
,
2111 const struct nls_table
*nls_codepage
, int remap
)
2114 COPY_REQ
*pSMB
= NULL
;
2115 COPY_RSP
*pSMBr
= NULL
;
2117 int name_len
, name_len2
;
2120 cFYI(1, "In CIFSSMBCopy");
2122 rc
= smb_init(SMB_COM_COPY
, 1, tcon
, (void **) &pSMB
,
2127 pSMB
->BufferFormat
= 0x04;
2128 pSMB
->Tid2
= target_tid
;
2130 pSMB
->Flags
= cpu_to_le16(flags
& COPY_TREE
);
2132 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
2133 name_len
= cifsConvertToUCS((__le16
*) pSMB
->OldFileName
,
2134 fromName
, PATH_MAX
, nls_codepage
,
2136 name_len
++; /* trailing null */
2138 pSMB
->OldFileName
[name_len
] = 0x04; /* pad */
2139 /* protocol requires ASCII signature byte on Unicode string */
2140 pSMB
->OldFileName
[name_len
+ 1] = 0x00;
2142 cifsConvertToUCS((__le16
*)&pSMB
->OldFileName
[name_len
+ 2],
2143 toName
, PATH_MAX
, nls_codepage
, remap
);
2144 name_len2
+= 1 /* trailing null */ + 1 /* Signature word */ ;
2145 name_len2
*= 2; /* convert to bytes */
2146 } else { /* BB improve the check for buffer overruns BB */
2147 name_len
= strnlen(fromName
, PATH_MAX
);
2148 name_len
++; /* trailing null */
2149 strncpy(pSMB
->OldFileName
, fromName
, name_len
);
2150 name_len2
= strnlen(toName
, PATH_MAX
);
2151 name_len2
++; /* trailing null */
2152 pSMB
->OldFileName
[name_len
] = 0x04; /* 2nd buffer format */
2153 strncpy(&pSMB
->OldFileName
[name_len
+ 1], toName
, name_len2
);
2154 name_len2
++; /* trailing null */
2155 name_len2
++; /* signature byte */
2158 count
= 1 /* 1st signature byte */ + name_len
+ name_len2
;
2159 pSMB
->hdr
.smb_buf_length
+= count
;
2160 pSMB
->ByteCount
= cpu_to_le16(count
);
2162 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
2163 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
2165 cFYI(1, "Send error in copy = %d with %d files copied",
2166 rc
, le16_to_cpu(pSMBr
->CopyCount
));
2168 cifs_buf_release(pSMB
);
2177 CIFSUnixCreateSymLink(const int xid
, struct cifsTconInfo
*tcon
,
2178 const char *fromName
, const char *toName
,
2179 const struct nls_table
*nls_codepage
)
2181 TRANSACTION2_SPI_REQ
*pSMB
= NULL
;
2182 TRANSACTION2_SPI_RSP
*pSMBr
= NULL
;
2185 int name_len_target
;
2187 int bytes_returned
= 0;
2188 __u16 params
, param_offset
, offset
, byte_count
;
2190 cFYI(1, "In Symlink Unix style");
2192 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
2197 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
2199 cifs_strtoUCS((__le16
*) pSMB
->FileName
, fromName
, PATH_MAX
2200 /* find define for this maxpathcomponent */
2202 name_len
++; /* trailing null */
2205 } else { /* BB improve the check for buffer overruns BB */
2206 name_len
= strnlen(fromName
, PATH_MAX
);
2207 name_len
++; /* trailing null */
2208 strncpy(pSMB
->FileName
, fromName
, name_len
);
2210 params
= 6 + name_len
;
2211 pSMB
->MaxSetupCount
= 0;
2215 pSMB
->Reserved2
= 0;
2216 param_offset
= offsetof(struct smb_com_transaction2_spi_req
,
2217 InformationLevel
) - 4;
2218 offset
= param_offset
+ params
;
2220 data_offset
= (char *) (&pSMB
->hdr
.Protocol
) + offset
;
2221 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
2223 cifs_strtoUCS((__le16
*) data_offset
, toName
, PATH_MAX
2224 /* find define for this maxpathcomponent */
2226 name_len_target
++; /* trailing null */
2227 name_len_target
*= 2;
2228 } else { /* BB improve the check for buffer overruns BB */
2229 name_len_target
= strnlen(toName
, PATH_MAX
);
2230 name_len_target
++; /* trailing null */
2231 strncpy(data_offset
, toName
, name_len_target
);
2234 pSMB
->MaxParameterCount
= cpu_to_le16(2);
2235 /* BB find exact max on data count below from sess */
2236 pSMB
->MaxDataCount
= cpu_to_le16(1000);
2237 pSMB
->SetupCount
= 1;
2238 pSMB
->Reserved3
= 0;
2239 pSMB
->SubCommand
= cpu_to_le16(TRANS2_SET_PATH_INFORMATION
);
2240 byte_count
= 3 /* pad */ + params
+ name_len_target
;
2241 pSMB
->DataCount
= cpu_to_le16(name_len_target
);
2242 pSMB
->ParameterCount
= cpu_to_le16(params
);
2243 pSMB
->TotalDataCount
= pSMB
->DataCount
;
2244 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
2245 pSMB
->ParameterOffset
= cpu_to_le16(param_offset
);
2246 pSMB
->DataOffset
= cpu_to_le16(offset
);
2247 pSMB
->InformationLevel
= cpu_to_le16(SMB_SET_FILE_UNIX_LINK
);
2248 pSMB
->Reserved4
= 0;
2249 pSMB
->hdr
.smb_buf_length
+= byte_count
;
2250 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
2251 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
2252 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
2253 cifs_stats_inc(&tcon
->num_symlinks
);
2255 cFYI(1, "Send error in SetPathInfo create symlink = %d", rc
);
2257 cifs_buf_release(pSMB
);
2260 goto createSymLinkRetry
;
2266 CIFSUnixCreateHardLink(const int xid
, struct cifsTconInfo
*tcon
,
2267 const char *fromName
, const char *toName
,
2268 const struct nls_table
*nls_codepage
, int remap
)
2270 TRANSACTION2_SPI_REQ
*pSMB
= NULL
;
2271 TRANSACTION2_SPI_RSP
*pSMBr
= NULL
;
2274 int name_len_target
;
2276 int bytes_returned
= 0;
2277 __u16 params
, param_offset
, offset
, byte_count
;
2279 cFYI(1, "In Create Hard link Unix style");
2280 createHardLinkRetry
:
2281 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
2286 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
2287 name_len
= cifsConvertToUCS((__le16
*) pSMB
->FileName
, toName
,
2288 PATH_MAX
, nls_codepage
, remap
);
2289 name_len
++; /* trailing null */
2292 } else { /* BB improve the check for buffer overruns BB */
2293 name_len
= strnlen(toName
, PATH_MAX
);
2294 name_len
++; /* trailing null */
2295 strncpy(pSMB
->FileName
, toName
, name_len
);
2297 params
= 6 + name_len
;
2298 pSMB
->MaxSetupCount
= 0;
2302 pSMB
->Reserved2
= 0;
2303 param_offset
= offsetof(struct smb_com_transaction2_spi_req
,
2304 InformationLevel
) - 4;
2305 offset
= param_offset
+ params
;
2307 data_offset
= (char *) (&pSMB
->hdr
.Protocol
) + offset
;
2308 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
2310 cifsConvertToUCS((__le16
*) data_offset
, fromName
, PATH_MAX
,
2311 nls_codepage
, remap
);
2312 name_len_target
++; /* trailing null */
2313 name_len_target
*= 2;
2314 } else { /* BB improve the check for buffer overruns BB */
2315 name_len_target
= strnlen(fromName
, PATH_MAX
);
2316 name_len_target
++; /* trailing null */
2317 strncpy(data_offset
, fromName
, name_len_target
);
2320 pSMB
->MaxParameterCount
= cpu_to_le16(2);
2321 /* BB find exact max on data count below from sess*/
2322 pSMB
->MaxDataCount
= cpu_to_le16(1000);
2323 pSMB
->SetupCount
= 1;
2324 pSMB
->Reserved3
= 0;
2325 pSMB
->SubCommand
= cpu_to_le16(TRANS2_SET_PATH_INFORMATION
);
2326 byte_count
= 3 /* pad */ + params
+ name_len_target
;
2327 pSMB
->ParameterCount
= cpu_to_le16(params
);
2328 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
2329 pSMB
->DataCount
= cpu_to_le16(name_len_target
);
2330 pSMB
->TotalDataCount
= pSMB
->DataCount
;
2331 pSMB
->ParameterOffset
= cpu_to_le16(param_offset
);
2332 pSMB
->DataOffset
= cpu_to_le16(offset
);
2333 pSMB
->InformationLevel
= cpu_to_le16(SMB_SET_FILE_UNIX_HLINK
);
2334 pSMB
->Reserved4
= 0;
2335 pSMB
->hdr
.smb_buf_length
+= byte_count
;
2336 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
2337 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
2338 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
2339 cifs_stats_inc(&tcon
->num_hardlinks
);
2341 cFYI(1, "Send error in SetPathInfo (hard link) = %d", rc
);
2343 cifs_buf_release(pSMB
);
2345 goto createHardLinkRetry
;
2351 CIFSCreateHardLink(const int xid
, struct cifsTconInfo
*tcon
,
2352 const char *fromName
, const char *toName
,
2353 const struct nls_table
*nls_codepage
, int remap
)
2356 NT_RENAME_REQ
*pSMB
= NULL
;
2357 RENAME_RSP
*pSMBr
= NULL
;
2359 int name_len
, name_len2
;
2362 cFYI(1, "In CIFSCreateHardLink");
2363 winCreateHardLinkRetry
:
2365 rc
= smb_init(SMB_COM_NT_RENAME
, 4, tcon
, (void **) &pSMB
,
2370 pSMB
->SearchAttributes
=
2371 cpu_to_le16(ATTR_READONLY
| ATTR_HIDDEN
| ATTR_SYSTEM
|
2373 pSMB
->Flags
= cpu_to_le16(CREATE_HARD_LINK
);
2374 pSMB
->ClusterCount
= 0;
2376 pSMB
->BufferFormat
= 0x04;
2378 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
2380 cifsConvertToUCS((__le16
*) pSMB
->OldFileName
, fromName
,
2381 PATH_MAX
, nls_codepage
, remap
);
2382 name_len
++; /* trailing null */
2385 /* protocol specifies ASCII buffer format (0x04) for unicode */
2386 pSMB
->OldFileName
[name_len
] = 0x04;
2387 pSMB
->OldFileName
[name_len
+ 1] = 0x00; /* pad */
2389 cifsConvertToUCS((__le16
*)&pSMB
->OldFileName
[name_len
+ 2],
2390 toName
, PATH_MAX
, nls_codepage
, remap
);
2391 name_len2
+= 1 /* trailing null */ + 1 /* Signature word */ ;
2392 name_len2
*= 2; /* convert to bytes */
2393 } else { /* BB improve the check for buffer overruns BB */
2394 name_len
= strnlen(fromName
, PATH_MAX
);
2395 name_len
++; /* trailing null */
2396 strncpy(pSMB
->OldFileName
, fromName
, name_len
);
2397 name_len2
= strnlen(toName
, PATH_MAX
);
2398 name_len2
++; /* trailing null */
2399 pSMB
->OldFileName
[name_len
] = 0x04; /* 2nd buffer format */
2400 strncpy(&pSMB
->OldFileName
[name_len
+ 1], toName
, name_len2
);
2401 name_len2
++; /* trailing null */
2402 name_len2
++; /* signature byte */
2405 count
= 1 /* string type byte */ + name_len
+ name_len2
;
2406 pSMB
->hdr
.smb_buf_length
+= count
;
2407 pSMB
->ByteCount
= cpu_to_le16(count
);
2409 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
2410 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
2411 cifs_stats_inc(&tcon
->num_hardlinks
);
2413 cFYI(1, "Send error in hard link (NT rename) = %d", rc
);
2415 cifs_buf_release(pSMB
);
2417 goto winCreateHardLinkRetry
;
2423 CIFSSMBUnixQuerySymLink(const int xid
, struct cifsTconInfo
*tcon
,
2424 const unsigned char *searchName
, char **symlinkinfo
,
2425 const struct nls_table
*nls_codepage
)
2427 /* SMB_QUERY_FILE_UNIX_LINK */
2428 TRANSACTION2_QPI_REQ
*pSMB
= NULL
;
2429 TRANSACTION2_QPI_RSP
*pSMBr
= NULL
;
2433 __u16 params
, byte_count
;
2436 cFYI(1, "In QPathSymLinkInfo (Unix) for path %s", searchName
);
2439 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
2444 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
2446 cifs_strtoUCS((__le16
*) pSMB
->FileName
, searchName
,
2447 PATH_MAX
, nls_codepage
);
2448 name_len
++; /* trailing null */
2450 } else { /* BB improve the check for buffer overruns BB */
2451 name_len
= strnlen(searchName
, PATH_MAX
);
2452 name_len
++; /* trailing null */
2453 strncpy(pSMB
->FileName
, searchName
, name_len
);
2456 params
= 2 /* level */ + 4 /* rsrvd */ + name_len
/* incl null */ ;
2457 pSMB
->TotalDataCount
= 0;
2458 pSMB
->MaxParameterCount
= cpu_to_le16(2);
2459 pSMB
->MaxDataCount
= cpu_to_le16(CIFSMaxBufSize
);
2460 pSMB
->MaxSetupCount
= 0;
2464 pSMB
->Reserved2
= 0;
2465 pSMB
->ParameterOffset
= cpu_to_le16(offsetof(
2466 struct smb_com_transaction2_qpi_req
, InformationLevel
) - 4);
2467 pSMB
->DataCount
= 0;
2468 pSMB
->DataOffset
= 0;
2469 pSMB
->SetupCount
= 1;
2470 pSMB
->Reserved3
= 0;
2471 pSMB
->SubCommand
= cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION
);
2472 byte_count
= params
+ 1 /* pad */ ;
2473 pSMB
->TotalParameterCount
= cpu_to_le16(params
);
2474 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
2475 pSMB
->InformationLevel
= cpu_to_le16(SMB_QUERY_FILE_UNIX_LINK
);
2476 pSMB
->Reserved4
= 0;
2477 pSMB
->hdr
.smb_buf_length
+= byte_count
;
2478 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
2480 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
2481 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
2483 cFYI(1, "Send error in QuerySymLinkInfo = %d", rc
);
2485 /* decode response */
2487 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
2488 /* BB also check enough total bytes returned */
2489 if (rc
|| (pSMBr
->ByteCount
< 2))
2493 u16 count
= le16_to_cpu(pSMBr
->t2
.DataCount
);
2495 data_start
= ((char *) &pSMBr
->hdr
.Protocol
) +
2496 le16_to_cpu(pSMBr
->t2
.DataOffset
);
2498 if (pSMBr
->hdr
.Flags2
& SMBFLG2_UNICODE
)
2503 /* BB FIXME investigate remapping reserved chars here */
2504 *symlinkinfo
= cifs_strndup_from_ucs(data_start
, count
,
2505 is_unicode
, nls_codepage
);
2510 cifs_buf_release(pSMB
);
2512 goto querySymLinkRetry
;
2516 #ifdef CONFIG_CIFS_SYMLINK_EXPERIMENTAL
2518 * Recent Windows versions now create symlinks more frequently
2519 * and they use the "reparse point" mechanism below. We can of course
2520 * do symlinks nicely to Samba and other servers which support the
2521 * CIFS Unix Extensions and we can also do SFU symlinks and "client only"
2522 * "MF" symlinks optionally, but for recent Windows we really need to
2523 * reenable the code below and fix the cifs_symlink callers to handle this.
2524 * In the interim this code has been moved to its own config option so
2525 * it is not compiled in by default until callers fixed up and more tested.
2528 CIFSSMBQueryReparseLinkInfo(const int xid
, struct cifsTconInfo
*tcon
,
2529 const unsigned char *searchName
,
2530 char *symlinkinfo
, const int buflen
, __u16 fid
,
2531 const struct nls_table
*nls_codepage
)
2535 struct smb_com_transaction_ioctl_req
*pSMB
;
2536 struct smb_com_transaction_ioctl_rsp
*pSMBr
;
2538 cFYI(1, "In Windows reparse style QueryLink for path %s", searchName
);
2539 rc
= smb_init(SMB_COM_NT_TRANSACT
, 23, tcon
, (void **) &pSMB
,
2544 pSMB
->TotalParameterCount
= 0 ;
2545 pSMB
->TotalDataCount
= 0;
2546 pSMB
->MaxParameterCount
= cpu_to_le32(2);
2547 /* BB find exact data count max from sess structure BB */
2548 pSMB
->MaxDataCount
= cpu_to_le32((tcon
->ses
->server
->maxBuf
-
2549 MAX_CIFS_HDR_SIZE
) & 0xFFFFFF00);
2550 pSMB
->MaxSetupCount
= 4;
2552 pSMB
->ParameterOffset
= 0;
2553 pSMB
->DataCount
= 0;
2554 pSMB
->DataOffset
= 0;
2555 pSMB
->SetupCount
= 4;
2556 pSMB
->SubCommand
= cpu_to_le16(NT_TRANSACT_IOCTL
);
2557 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
2558 pSMB
->FunctionCode
= cpu_to_le32(FSCTL_GET_REPARSE_POINT
);
2559 pSMB
->IsFsctl
= 1; /* FSCTL */
2560 pSMB
->IsRootFlag
= 0;
2561 pSMB
->Fid
= fid
; /* file handle always le */
2562 pSMB
->ByteCount
= 0;
2564 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
2565 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
2567 cFYI(1, "Send error in QueryReparseLinkInfo = %d", rc
);
2568 } else { /* decode response */
2569 __u32 data_offset
= le32_to_cpu(pSMBr
->DataOffset
);
2570 __u32 data_count
= le32_to_cpu(pSMBr
->DataCount
);
2571 if ((pSMBr
->ByteCount
< 2) || (data_offset
> 512)) {
2572 /* BB also check enough total bytes returned */
2573 rc
= -EIO
; /* bad smb */
2576 if (data_count
&& (data_count
< 2048)) {
2577 char *end_of_smb
= 2 /* sizeof byte count */ +
2578 pSMBr
->ByteCount
+ (char *)&pSMBr
->ByteCount
;
2580 struct reparse_data
*reparse_buf
=
2581 (struct reparse_data
*)
2582 ((char *)&pSMBr
->hdr
.Protocol
2584 if ((char *)reparse_buf
>= end_of_smb
) {
2588 if ((reparse_buf
->LinkNamesBuf
+
2589 reparse_buf
->TargetNameOffset
+
2590 reparse_buf
->TargetNameLen
) > end_of_smb
) {
2591 cFYI(1, "reparse buf beyond SMB");
2596 if (pSMBr
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
2597 cifs_from_ucs2(symlinkinfo
, (__le16
*)
2598 (reparse_buf
->LinkNamesBuf
+
2599 reparse_buf
->TargetNameOffset
),
2601 reparse_buf
->TargetNameLen
,
2603 } else { /* ASCII names */
2604 strncpy(symlinkinfo
,
2605 reparse_buf
->LinkNamesBuf
+
2606 reparse_buf
->TargetNameOffset
,
2607 min_t(const int, buflen
,
2608 reparse_buf
->TargetNameLen
));
2612 cFYI(1, "Invalid return data count on "
2613 "get reparse info ioctl");
2615 symlinkinfo
[buflen
] = 0; /* just in case so the caller
2616 does not go off the end of the buffer */
2617 cFYI(1, "readlink result - %s", symlinkinfo
);
2621 cifs_buf_release(pSMB
);
2623 /* Note: On -EAGAIN error only caller can retry on handle based calls
2624 since file handle passed in no longer valid */
2628 #endif /* CIFS_SYMLINK_EXPERIMENTAL */ /* BB temporarily unused */
2630 #ifdef CONFIG_CIFS_POSIX
2632 /*Convert an Access Control Entry from wire format to local POSIX xattr format*/
2633 static void cifs_convert_ace(posix_acl_xattr_entry
*ace
,
2634 struct cifs_posix_ace
*cifs_ace
)
2636 /* u8 cifs fields do not need le conversion */
2637 ace
->e_perm
= cpu_to_le16(cifs_ace
->cifs_e_perm
);
2638 ace
->e_tag
= cpu_to_le16(cifs_ace
->cifs_e_tag
);
2639 ace
->e_id
= cpu_to_le32(le64_to_cpu(cifs_ace
->cifs_uid
));
2640 /* cFYI(1, "perm %d tag %d id %d",ace->e_perm,ace->e_tag,ace->e_id); */
2645 /* Convert ACL from CIFS POSIX wire format to local Linux POSIX ACL xattr */
2646 static int cifs_copy_posix_acl(char *trgt
, char *src
, const int buflen
,
2647 const int acl_type
, const int size_of_data_area
)
2652 struct cifs_posix_ace
*pACE
;
2653 struct cifs_posix_acl
*cifs_acl
= (struct cifs_posix_acl
*)src
;
2654 posix_acl_xattr_header
*local_acl
= (posix_acl_xattr_header
*)trgt
;
2656 if (le16_to_cpu(cifs_acl
->version
) != CIFS_ACL_VERSION
)
2659 if (acl_type
& ACL_TYPE_ACCESS
) {
2660 count
= le16_to_cpu(cifs_acl
->access_entry_count
);
2661 pACE
= &cifs_acl
->ace_array
[0];
2662 size
= sizeof(struct cifs_posix_acl
);
2663 size
+= sizeof(struct cifs_posix_ace
) * count
;
2664 /* check if we would go beyond end of SMB */
2665 if (size_of_data_area
< size
) {
2666 cFYI(1, "bad CIFS POSIX ACL size %d vs. %d",
2667 size_of_data_area
, size
);
2670 } else if (acl_type
& ACL_TYPE_DEFAULT
) {
2671 count
= le16_to_cpu(cifs_acl
->access_entry_count
);
2672 size
= sizeof(struct cifs_posix_acl
);
2673 size
+= sizeof(struct cifs_posix_ace
) * count
;
2674 /* skip past access ACEs to get to default ACEs */
2675 pACE
= &cifs_acl
->ace_array
[count
];
2676 count
= le16_to_cpu(cifs_acl
->default_entry_count
);
2677 size
+= sizeof(struct cifs_posix_ace
) * count
;
2678 /* check if we would go beyond end of SMB */
2679 if (size_of_data_area
< size
)
2686 size
= posix_acl_xattr_size(count
);
2687 if ((buflen
== 0) || (local_acl
== NULL
)) {
2688 /* used to query ACL EA size */
2689 } else if (size
> buflen
) {
2691 } else /* buffer big enough */ {
2692 local_acl
->a_version
= cpu_to_le32(POSIX_ACL_XATTR_VERSION
);
2693 for (i
= 0; i
< count
; i
++) {
2694 cifs_convert_ace(&local_acl
->a_entries
[i
], pACE
);
2701 static __u16
convert_ace_to_cifs_ace(struct cifs_posix_ace
*cifs_ace
,
2702 const posix_acl_xattr_entry
*local_ace
)
2704 __u16 rc
= 0; /* 0 = ACL converted ok */
2706 cifs_ace
->cifs_e_perm
= le16_to_cpu(local_ace
->e_perm
);
2707 cifs_ace
->cifs_e_tag
= le16_to_cpu(local_ace
->e_tag
);
2708 /* BB is there a better way to handle the large uid? */
2709 if (local_ace
->e_id
== cpu_to_le32(-1)) {
2710 /* Probably no need to le convert -1 on any arch but can not hurt */
2711 cifs_ace
->cifs_uid
= cpu_to_le64(-1);
2713 cifs_ace
->cifs_uid
= cpu_to_le64(le32_to_cpu(local_ace
->e_id
));
2714 /*cFYI(1, "perm %d tag %d id %d",ace->e_perm,ace->e_tag,ace->e_id);*/
2718 /* Convert ACL from local Linux POSIX xattr to CIFS POSIX ACL wire format */
2719 static __u16
ACL_to_cifs_posix(char *parm_data
, const char *pACL
,
2720 const int buflen
, const int acl_type
)
2723 struct cifs_posix_acl
*cifs_acl
= (struct cifs_posix_acl
*)parm_data
;
2724 posix_acl_xattr_header
*local_acl
= (posix_acl_xattr_header
*)pACL
;
2728 if ((buflen
== 0) || (pACL
== NULL
) || (cifs_acl
== NULL
))
2731 count
= posix_acl_xattr_count((size_t)buflen
);
2732 cFYI(1, "setting acl with %d entries from buf of length %d and "
2734 count
, buflen
, le32_to_cpu(local_acl
->a_version
));
2735 if (le32_to_cpu(local_acl
->a_version
) != 2) {
2736 cFYI(1, "unknown POSIX ACL version %d",
2737 le32_to_cpu(local_acl
->a_version
));
2740 cifs_acl
->version
= cpu_to_le16(1);
2741 if (acl_type
== ACL_TYPE_ACCESS
)
2742 cifs_acl
->access_entry_count
= cpu_to_le16(count
);
2743 else if (acl_type
== ACL_TYPE_DEFAULT
)
2744 cifs_acl
->default_entry_count
= cpu_to_le16(count
);
2746 cFYI(1, "unknown ACL type %d", acl_type
);
2749 for (i
= 0; i
< count
; i
++) {
2750 rc
= convert_ace_to_cifs_ace(&cifs_acl
->ace_array
[i
],
2751 &local_acl
->a_entries
[i
]);
2753 /* ACE not converted */
2758 rc
= (__u16
)(count
* sizeof(struct cifs_posix_ace
));
2759 rc
+= sizeof(struct cifs_posix_acl
);
2760 /* BB add check to make sure ACL does not overflow SMB */
2766 CIFSSMBGetPosixACL(const int xid
, struct cifsTconInfo
*tcon
,
2767 const unsigned char *searchName
,
2768 char *acl_inf
, const int buflen
, const int acl_type
,
2769 const struct nls_table
*nls_codepage
, int remap
)
2771 /* SMB_QUERY_POSIX_ACL */
2772 TRANSACTION2_QPI_REQ
*pSMB
= NULL
;
2773 TRANSACTION2_QPI_RSP
*pSMBr
= NULL
;
2777 __u16 params
, byte_count
;
2779 cFYI(1, "In GetPosixACL (Unix) for path %s", searchName
);
2782 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
2787 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
2789 cifsConvertToUCS((__le16
*) pSMB
->FileName
, searchName
,
2790 PATH_MAX
, nls_codepage
, remap
);
2791 name_len
++; /* trailing null */
2793 pSMB
->FileName
[name_len
] = 0;
2794 pSMB
->FileName
[name_len
+1] = 0;
2795 } else { /* BB improve the check for buffer overruns BB */
2796 name_len
= strnlen(searchName
, PATH_MAX
);
2797 name_len
++; /* trailing null */
2798 strncpy(pSMB
->FileName
, searchName
, name_len
);
2801 params
= 2 /* level */ + 4 /* rsrvd */ + name_len
/* incl null */ ;
2802 pSMB
->TotalDataCount
= 0;
2803 pSMB
->MaxParameterCount
= cpu_to_le16(2);
2804 /* BB find exact max data count below from sess structure BB */
2805 pSMB
->MaxDataCount
= cpu_to_le16(4000);
2806 pSMB
->MaxSetupCount
= 0;
2810 pSMB
->Reserved2
= 0;
2811 pSMB
->ParameterOffset
= cpu_to_le16(
2812 offsetof(struct smb_com_transaction2_qpi_req
,
2813 InformationLevel
) - 4);
2814 pSMB
->DataCount
= 0;
2815 pSMB
->DataOffset
= 0;
2816 pSMB
->SetupCount
= 1;
2817 pSMB
->Reserved3
= 0;
2818 pSMB
->SubCommand
= cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION
);
2819 byte_count
= params
+ 1 /* pad */ ;
2820 pSMB
->TotalParameterCount
= cpu_to_le16(params
);
2821 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
2822 pSMB
->InformationLevel
= cpu_to_le16(SMB_QUERY_POSIX_ACL
);
2823 pSMB
->Reserved4
= 0;
2824 pSMB
->hdr
.smb_buf_length
+= byte_count
;
2825 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
2827 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
2828 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
2829 cifs_stats_inc(&tcon
->num_acl_get
);
2831 cFYI(1, "Send error in Query POSIX ACL = %d", rc
);
2833 /* decode response */
2835 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
2836 if (rc
|| (pSMBr
->ByteCount
< 2))
2837 /* BB also check enough total bytes returned */
2838 rc
= -EIO
; /* bad smb */
2840 __u16 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
2841 __u16 count
= le16_to_cpu(pSMBr
->t2
.DataCount
);
2842 rc
= cifs_copy_posix_acl(acl_inf
,
2843 (char *)&pSMBr
->hdr
.Protocol
+data_offset
,
2844 buflen
, acl_type
, count
);
2847 cifs_buf_release(pSMB
);
2854 CIFSSMBSetPosixACL(const int xid
, struct cifsTconInfo
*tcon
,
2855 const unsigned char *fileName
,
2856 const char *local_acl
, const int buflen
,
2858 const struct nls_table
*nls_codepage
, int remap
)
2860 struct smb_com_transaction2_spi_req
*pSMB
= NULL
;
2861 struct smb_com_transaction2_spi_rsp
*pSMBr
= NULL
;
2865 int bytes_returned
= 0;
2866 __u16 params
, byte_count
, data_count
, param_offset
, offset
;
2868 cFYI(1, "In SetPosixACL (Unix) for path %s", fileName
);
2870 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
2874 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
2876 cifsConvertToUCS((__le16
*) pSMB
->FileName
, fileName
,
2877 PATH_MAX
, nls_codepage
, remap
);
2878 name_len
++; /* trailing null */
2880 } else { /* BB improve the check for buffer overruns BB */
2881 name_len
= strnlen(fileName
, PATH_MAX
);
2882 name_len
++; /* trailing null */
2883 strncpy(pSMB
->FileName
, fileName
, name_len
);
2885 params
= 6 + name_len
;
2886 pSMB
->MaxParameterCount
= cpu_to_le16(2);
2887 /* BB find max SMB size from sess */
2888 pSMB
->MaxDataCount
= cpu_to_le16(1000);
2889 pSMB
->MaxSetupCount
= 0;
2893 pSMB
->Reserved2
= 0;
2894 param_offset
= offsetof(struct smb_com_transaction2_spi_req
,
2895 InformationLevel
) - 4;
2896 offset
= param_offset
+ params
;
2897 parm_data
= ((char *) &pSMB
->hdr
.Protocol
) + offset
;
2898 pSMB
->ParameterOffset
= cpu_to_le16(param_offset
);
2900 /* convert to on the wire format for POSIX ACL */
2901 data_count
= ACL_to_cifs_posix(parm_data
, local_acl
, buflen
, acl_type
);
2903 if (data_count
== 0) {
2905 goto setACLerrorExit
;
2907 pSMB
->DataOffset
= cpu_to_le16(offset
);
2908 pSMB
->SetupCount
= 1;
2909 pSMB
->Reserved3
= 0;
2910 pSMB
->SubCommand
= cpu_to_le16(TRANS2_SET_PATH_INFORMATION
);
2911 pSMB
->InformationLevel
= cpu_to_le16(SMB_SET_POSIX_ACL
);
2912 byte_count
= 3 /* pad */ + params
+ data_count
;
2913 pSMB
->DataCount
= cpu_to_le16(data_count
);
2914 pSMB
->TotalDataCount
= pSMB
->DataCount
;
2915 pSMB
->ParameterCount
= cpu_to_le16(params
);
2916 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
2917 pSMB
->Reserved4
= 0;
2918 pSMB
->hdr
.smb_buf_length
+= byte_count
;
2919 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
2920 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
2921 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
2923 cFYI(1, "Set POSIX ACL returned %d", rc
);
2926 cifs_buf_release(pSMB
);
2932 /* BB fix tabs in this function FIXME BB */
2934 CIFSGetExtAttr(const int xid
, struct cifsTconInfo
*tcon
,
2935 const int netfid
, __u64
*pExtAttrBits
, __u64
*pMask
)
2938 struct smb_t2_qfi_req
*pSMB
= NULL
;
2939 struct smb_t2_qfi_rsp
*pSMBr
= NULL
;
2941 __u16 params
, byte_count
;
2943 cFYI(1, "In GetExtAttr");
2948 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
2953 params
= 2 /* level */ + 2 /* fid */;
2954 pSMB
->t2
.TotalDataCount
= 0;
2955 pSMB
->t2
.MaxParameterCount
= cpu_to_le16(4);
2956 /* BB find exact max data count below from sess structure BB */
2957 pSMB
->t2
.MaxDataCount
= cpu_to_le16(4000);
2958 pSMB
->t2
.MaxSetupCount
= 0;
2959 pSMB
->t2
.Reserved
= 0;
2961 pSMB
->t2
.Timeout
= 0;
2962 pSMB
->t2
.Reserved2
= 0;
2963 pSMB
->t2
.ParameterOffset
= cpu_to_le16(offsetof(struct smb_t2_qfi_req
,
2965 pSMB
->t2
.DataCount
= 0;
2966 pSMB
->t2
.DataOffset
= 0;
2967 pSMB
->t2
.SetupCount
= 1;
2968 pSMB
->t2
.Reserved3
= 0;
2969 pSMB
->t2
.SubCommand
= cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION
);
2970 byte_count
= params
+ 1 /* pad */ ;
2971 pSMB
->t2
.TotalParameterCount
= cpu_to_le16(params
);
2972 pSMB
->t2
.ParameterCount
= pSMB
->t2
.TotalParameterCount
;
2973 pSMB
->InformationLevel
= cpu_to_le16(SMB_QUERY_ATTR_FLAGS
);
2976 pSMB
->hdr
.smb_buf_length
+= byte_count
;
2977 pSMB
->t2
.ByteCount
= cpu_to_le16(byte_count
);
2979 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
2980 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
2982 cFYI(1, "error %d in GetExtAttr", rc
);
2984 /* decode response */
2985 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
2986 if (rc
|| (pSMBr
->ByteCount
< 2))
2987 /* BB also check enough total bytes returned */
2988 /* If rc should we check for EOPNOSUPP and
2989 disable the srvino flag? or in caller? */
2990 rc
= -EIO
; /* bad smb */
2992 __u16 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
2993 __u16 count
= le16_to_cpu(pSMBr
->t2
.DataCount
);
2994 struct file_chattr_info
*pfinfo
;
2995 /* BB Do we need a cast or hash here ? */
2997 cFYI(1, "Illegal size ret in GetExtAttr");
3001 pfinfo
= (struct file_chattr_info
*)
3002 (data_offset
+ (char *) &pSMBr
->hdr
.Protocol
);
3003 *pExtAttrBits
= le64_to_cpu(pfinfo
->mode
);
3004 *pMask
= le64_to_cpu(pfinfo
->mask
);
3008 cifs_buf_release(pSMB
);
3010 goto GetExtAttrRetry
;
3014 #endif /* CONFIG_POSIX */
3016 #ifdef CONFIG_CIFS_ACL
3018 * Initialize NT TRANSACT SMB into small smb request buffer. This assumes that
3019 * all NT TRANSACTS that we init here have total parm and data under about 400
3020 * bytes (to fit in small cifs buffer size), which is the case so far, it
3021 * easily fits. NB: Setup words themselves and ByteCount MaxSetupCount (size of
3022 * returned setup area) and MaxParameterCount (returned parms size) must be set
3026 smb_init_nttransact(const __u16 sub_command
, const int setup_count
,
3027 const int parm_len
, struct cifsTconInfo
*tcon
,
3032 struct smb_com_ntransact_req
*pSMB
;
3034 rc
= small_smb_init(SMB_COM_NT_TRANSACT
, 19 + setup_count
, tcon
,
3038 *ret_buf
= (void *)pSMB
;
3040 pSMB
->TotalParameterCount
= cpu_to_le32(parm_len
);
3041 pSMB
->TotalDataCount
= 0;
3042 pSMB
->MaxDataCount
= cpu_to_le32((tcon
->ses
->server
->maxBuf
-
3043 MAX_CIFS_HDR_SIZE
) & 0xFFFFFF00);
3044 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
3045 pSMB
->DataCount
= pSMB
->TotalDataCount
;
3046 temp_offset
= offsetof(struct smb_com_ntransact_req
, Parms
) +
3047 (setup_count
* 2) - 4 /* for rfc1001 length itself */;
3048 pSMB
->ParameterOffset
= cpu_to_le32(temp_offset
);
3049 pSMB
->DataOffset
= cpu_to_le32(temp_offset
+ parm_len
);
3050 pSMB
->SetupCount
= setup_count
; /* no need to le convert byte fields */
3051 pSMB
->SubCommand
= cpu_to_le16(sub_command
);
3056 validate_ntransact(char *buf
, char **ppparm
, char **ppdata
,
3057 __u32
*pparmlen
, __u32
*pdatalen
)
3060 __u32 data_count
, data_offset
, parm_count
, parm_offset
;
3061 struct smb_com_ntransact_rsp
*pSMBr
;
3069 pSMBr
= (struct smb_com_ntransact_rsp
*)buf
;
3071 /* ByteCount was converted from little endian in SendReceive */
3072 end_of_smb
= 2 /* sizeof byte count */ + pSMBr
->ByteCount
+
3073 (char *)&pSMBr
->ByteCount
;
3075 data_offset
= le32_to_cpu(pSMBr
->DataOffset
);
3076 data_count
= le32_to_cpu(pSMBr
->DataCount
);
3077 parm_offset
= le32_to_cpu(pSMBr
->ParameterOffset
);
3078 parm_count
= le32_to_cpu(pSMBr
->ParameterCount
);
3080 *ppparm
= (char *)&pSMBr
->hdr
.Protocol
+ parm_offset
;
3081 *ppdata
= (char *)&pSMBr
->hdr
.Protocol
+ data_offset
;
3083 /* should we also check that parm and data areas do not overlap? */
3084 if (*ppparm
> end_of_smb
) {
3085 cFYI(1, "parms start after end of smb");
3087 } else if (parm_count
+ *ppparm
> end_of_smb
) {
3088 cFYI(1, "parm end after end of smb");
3090 } else if (*ppdata
> end_of_smb
) {
3091 cFYI(1, "data starts after end of smb");
3093 } else if (data_count
+ *ppdata
> end_of_smb
) {
3094 cFYI(1, "data %p + count %d (%p) past smb end %p start %p",
3095 *ppdata
, data_count
, (data_count
+ *ppdata
),
3098 } else if (parm_count
+ data_count
> pSMBr
->ByteCount
) {
3099 cFYI(1, "parm count and data count larger than SMB");
3102 *pdatalen
= data_count
;
3103 *pparmlen
= parm_count
;
3107 /* Get Security Descriptor (by handle) from remote server for a file or dir */
3109 CIFSSMBGetCIFSACL(const int xid
, struct cifsTconInfo
*tcon
, __u16 fid
,
3110 struct cifs_ntsd
**acl_inf
, __u32
*pbuflen
)
3114 QUERY_SEC_DESC_REQ
*pSMB
;
3117 cFYI(1, "GetCifsACL");
3122 rc
= smb_init_nttransact(NT_TRANSACT_QUERY_SECURITY_DESC
, 0,
3123 8 /* parm len */, tcon
, (void **) &pSMB
);
3127 pSMB
->MaxParameterCount
= cpu_to_le32(4);
3128 /* BB TEST with big acls that might need to be e.g. larger than 16K */
3129 pSMB
->MaxSetupCount
= 0;
3130 pSMB
->Fid
= fid
; /* file handle always le */
3131 pSMB
->AclFlags
= cpu_to_le32(CIFS_ACL_OWNER
| CIFS_ACL_GROUP
|
3133 pSMB
->ByteCount
= cpu_to_le16(11); /* 3 bytes pad + 8 bytes parm */
3134 pSMB
->hdr
.smb_buf_length
+= 11;
3135 iov
[0].iov_base
= (char *)pSMB
;
3136 iov
[0].iov_len
= pSMB
->hdr
.smb_buf_length
+ 4;
3138 rc
= SendReceive2(xid
, tcon
->ses
, iov
, 1 /* num iovec */, &buf_type
,
3140 cifs_stats_inc(&tcon
->num_acl_get
);
3142 cFYI(1, "Send error in QuerySecDesc = %d", rc
);
3143 } else { /* decode response */
3147 struct smb_com_ntransact_rsp
*pSMBr
;
3150 /* validate_nttransact */
3151 rc
= validate_ntransact(iov
[0].iov_base
, (char **)&parm
,
3152 &pdata
, &parm_len
, pbuflen
);
3155 pSMBr
= (struct smb_com_ntransact_rsp
*)iov
[0].iov_base
;
3157 cFYI(1, "smb %p parm %p data %p", pSMBr
, parm
, *acl_inf
);
3159 if (le32_to_cpu(pSMBr
->ParameterCount
) != 4) {
3160 rc
= -EIO
; /* bad smb */
3165 /* BB check that data area is minimum length and as big as acl_len */
3167 acl_len
= le32_to_cpu(*parm
);
3168 if (acl_len
!= *pbuflen
) {
3169 cERROR(1, "acl length %d does not match %d",
3171 if (*pbuflen
> acl_len
)
3175 /* check if buffer is big enough for the acl
3176 header followed by the smallest SID */
3177 if ((*pbuflen
< sizeof(struct cifs_ntsd
) + 8) ||
3178 (*pbuflen
>= 64 * 1024)) {
3179 cERROR(1, "bad acl length %d", *pbuflen
);
3183 *acl_inf
= kmalloc(*pbuflen
, GFP_KERNEL
);
3184 if (*acl_inf
== NULL
) {
3188 memcpy(*acl_inf
, pdata
, *pbuflen
);
3192 if (buf_type
== CIFS_SMALL_BUFFER
)
3193 cifs_small_buf_release(iov
[0].iov_base
);
3194 else if (buf_type
== CIFS_LARGE_BUFFER
)
3195 cifs_buf_release(iov
[0].iov_base
);
3196 /* cifs_small_buf_release(pSMB); */ /* Freed earlier now in SendReceive2 */
3201 CIFSSMBSetCIFSACL(const int xid
, struct cifsTconInfo
*tcon
, __u16 fid
,
3202 struct cifs_ntsd
*pntsd
, __u32 acllen
)
3204 __u16 byte_count
, param_count
, data_count
, param_offset
, data_offset
;
3206 int bytes_returned
= 0;
3207 SET_SEC_DESC_REQ
*pSMB
= NULL
;
3208 NTRANSACT_RSP
*pSMBr
= NULL
;
3211 rc
= smb_init(SMB_COM_NT_TRANSACT
, 19, tcon
, (void **) &pSMB
,
3216 pSMB
->MaxSetupCount
= 0;
3220 param_offset
= offsetof(struct smb_com_transaction_ssec_req
, Fid
) - 4;
3221 data_count
= acllen
;
3222 data_offset
= param_offset
+ param_count
;
3223 byte_count
= 3 /* pad */ + param_count
;
3225 pSMB
->DataCount
= cpu_to_le32(data_count
);
3226 pSMB
->TotalDataCount
= pSMB
->DataCount
;
3227 pSMB
->MaxParameterCount
= cpu_to_le32(4);
3228 pSMB
->MaxDataCount
= cpu_to_le32(16384);
3229 pSMB
->ParameterCount
= cpu_to_le32(param_count
);
3230 pSMB
->ParameterOffset
= cpu_to_le32(param_offset
);
3231 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
3232 pSMB
->DataOffset
= cpu_to_le32(data_offset
);
3233 pSMB
->SetupCount
= 0;
3234 pSMB
->SubCommand
= cpu_to_le16(NT_TRANSACT_SET_SECURITY_DESC
);
3235 pSMB
->ByteCount
= cpu_to_le16(byte_count
+data_count
);
3237 pSMB
->Fid
= fid
; /* file handle always le */
3238 pSMB
->Reserved2
= 0;
3239 pSMB
->AclFlags
= cpu_to_le32(CIFS_ACL_DACL
);
3241 if (pntsd
&& acllen
) {
3242 memcpy((char *) &pSMBr
->hdr
.Protocol
+ data_offset
,
3245 pSMB
->hdr
.smb_buf_length
+= (byte_count
+ data_count
);
3248 pSMB
->hdr
.smb_buf_length
+= byte_count
;
3250 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
3251 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
3253 cFYI(1, "SetCIFSACL bytes_returned: %d, rc: %d", bytes_returned
, rc
);
3255 cFYI(1, "Set CIFS ACL returned %d", rc
);
3256 cifs_buf_release(pSMB
);
3259 goto setCifsAclRetry
;
3264 #endif /* CONFIG_CIFS_ACL */
3266 /* Legacy Query Path Information call for lookup to old servers such
3268 int SMBQueryInformation(const int xid
, struct cifsTconInfo
*tcon
,
3269 const unsigned char *searchName
,
3270 FILE_ALL_INFO
*pFinfo
,
3271 const struct nls_table
*nls_codepage
, int remap
)
3273 QUERY_INFORMATION_REQ
*pSMB
;
3274 QUERY_INFORMATION_RSP
*pSMBr
;
3279 cFYI(1, "In SMBQPath path %s", searchName
);
3281 rc
= smb_init(SMB_COM_QUERY_INFORMATION
, 0, tcon
, (void **) &pSMB
,
3286 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
3288 cifsConvertToUCS((__le16
*) pSMB
->FileName
, searchName
,
3289 PATH_MAX
, nls_codepage
, remap
);
3290 name_len
++; /* trailing null */
3293 name_len
= strnlen(searchName
, PATH_MAX
);
3294 name_len
++; /* trailing null */
3295 strncpy(pSMB
->FileName
, searchName
, name_len
);
3297 pSMB
->BufferFormat
= 0x04;
3298 name_len
++; /* account for buffer type byte */
3299 pSMB
->hdr
.smb_buf_length
+= (__u16
) name_len
;
3300 pSMB
->ByteCount
= cpu_to_le16(name_len
);
3302 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
3303 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
3305 cFYI(1, "Send error in QueryInfo = %d", rc
);
3306 } else if (pFinfo
) {
3308 __u32 time
= le32_to_cpu(pSMBr
->last_write_time
);
3310 /* decode response */
3311 /* BB FIXME - add time zone adjustment BB */
3312 memset(pFinfo
, 0, sizeof(FILE_ALL_INFO
));
3315 /* decode time fields */
3316 pFinfo
->ChangeTime
= cpu_to_le64(cifs_UnixTimeToNT(ts
));
3317 pFinfo
->LastWriteTime
= pFinfo
->ChangeTime
;
3318 pFinfo
->LastAccessTime
= 0;
3319 pFinfo
->AllocationSize
=
3320 cpu_to_le64(le32_to_cpu(pSMBr
->size
));
3321 pFinfo
->EndOfFile
= pFinfo
->AllocationSize
;
3322 pFinfo
->Attributes
=
3323 cpu_to_le32(le16_to_cpu(pSMBr
->attr
));
3325 rc
= -EIO
; /* bad buffer passed in */
3327 cifs_buf_release(pSMB
);
3336 CIFSSMBQFileInfo(const int xid
, struct cifsTconInfo
*tcon
,
3337 u16 netfid
, FILE_ALL_INFO
*pFindData
)
3339 struct smb_t2_qfi_req
*pSMB
= NULL
;
3340 struct smb_t2_qfi_rsp
*pSMBr
= NULL
;
3343 __u16 params
, byte_count
;
3346 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
3351 params
= 2 /* level */ + 2 /* fid */;
3352 pSMB
->t2
.TotalDataCount
= 0;
3353 pSMB
->t2
.MaxParameterCount
= cpu_to_le16(4);
3354 /* BB find exact max data count below from sess structure BB */
3355 pSMB
->t2
.MaxDataCount
= cpu_to_le16(CIFSMaxBufSize
);
3356 pSMB
->t2
.MaxSetupCount
= 0;
3357 pSMB
->t2
.Reserved
= 0;
3359 pSMB
->t2
.Timeout
= 0;
3360 pSMB
->t2
.Reserved2
= 0;
3361 pSMB
->t2
.ParameterOffset
= cpu_to_le16(offsetof(struct smb_t2_qfi_req
,
3363 pSMB
->t2
.DataCount
= 0;
3364 pSMB
->t2
.DataOffset
= 0;
3365 pSMB
->t2
.SetupCount
= 1;
3366 pSMB
->t2
.Reserved3
= 0;
3367 pSMB
->t2
.SubCommand
= cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION
);
3368 byte_count
= params
+ 1 /* pad */ ;
3369 pSMB
->t2
.TotalParameterCount
= cpu_to_le16(params
);
3370 pSMB
->t2
.ParameterCount
= pSMB
->t2
.TotalParameterCount
;
3371 pSMB
->InformationLevel
= cpu_to_le16(SMB_QUERY_FILE_ALL_INFO
);
3374 pSMB
->hdr
.smb_buf_length
+= byte_count
;
3376 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
3377 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
3379 cFYI(1, "Send error in QPathInfo = %d", rc
);
3380 } else { /* decode response */
3381 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
3383 if (rc
) /* BB add auto retry on EOPNOTSUPP? */
3385 else if (pSMBr
->ByteCount
< 40)
3386 rc
= -EIO
; /* bad smb */
3387 else if (pFindData
) {
3388 __u16 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
3389 memcpy((char *) pFindData
,
3390 (char *) &pSMBr
->hdr
.Protocol
+
3391 data_offset
, sizeof(FILE_ALL_INFO
));
3395 cifs_buf_release(pSMB
);
3397 goto QFileInfoRetry
;
3403 CIFSSMBQPathInfo(const int xid
, struct cifsTconInfo
*tcon
,
3404 const unsigned char *searchName
,
3405 FILE_ALL_INFO
*pFindData
,
3406 int legacy
/* old style infolevel */,
3407 const struct nls_table
*nls_codepage
, int remap
)
3409 /* level 263 SMB_QUERY_FILE_ALL_INFO */
3410 TRANSACTION2_QPI_REQ
*pSMB
= NULL
;
3411 TRANSACTION2_QPI_RSP
*pSMBr
= NULL
;
3415 __u16 params
, byte_count
;
3417 /* cFYI(1, "In QPathInfo path %s", searchName); */
3419 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
3424 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
3426 cifsConvertToUCS((__le16
*) pSMB
->FileName
, searchName
,
3427 PATH_MAX
, nls_codepage
, remap
);
3428 name_len
++; /* trailing null */
3430 } else { /* BB improve the check for buffer overruns BB */
3431 name_len
= strnlen(searchName
, PATH_MAX
);
3432 name_len
++; /* trailing null */
3433 strncpy(pSMB
->FileName
, searchName
, name_len
);
3436 params
= 2 /* level */ + 4 /* reserved */ + name_len
/* includes NUL */;
3437 pSMB
->TotalDataCount
= 0;
3438 pSMB
->MaxParameterCount
= cpu_to_le16(2);
3439 /* BB find exact max SMB PDU from sess structure BB */
3440 pSMB
->MaxDataCount
= cpu_to_le16(4000);
3441 pSMB
->MaxSetupCount
= 0;
3445 pSMB
->Reserved2
= 0;
3446 pSMB
->ParameterOffset
= cpu_to_le16(offsetof(
3447 struct smb_com_transaction2_qpi_req
, InformationLevel
) - 4);
3448 pSMB
->DataCount
= 0;
3449 pSMB
->DataOffset
= 0;
3450 pSMB
->SetupCount
= 1;
3451 pSMB
->Reserved3
= 0;
3452 pSMB
->SubCommand
= cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION
);
3453 byte_count
= params
+ 1 /* pad */ ;
3454 pSMB
->TotalParameterCount
= cpu_to_le16(params
);
3455 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
3457 pSMB
->InformationLevel
= cpu_to_le16(SMB_INFO_STANDARD
);
3459 pSMB
->InformationLevel
= cpu_to_le16(SMB_QUERY_FILE_ALL_INFO
);
3460 pSMB
->Reserved4
= 0;
3461 pSMB
->hdr
.smb_buf_length
+= byte_count
;
3462 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
3464 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
3465 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
3467 cFYI(1, "Send error in QPathInfo = %d", rc
);
3468 } else { /* decode response */
3469 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
3471 if (rc
) /* BB add auto retry on EOPNOTSUPP? */
3473 else if (!legacy
&& (pSMBr
->ByteCount
< 40))
3474 rc
= -EIO
; /* bad smb */
3475 else if (legacy
&& (pSMBr
->ByteCount
< 24))
3476 rc
= -EIO
; /* 24 or 26 expected but we do not read
3478 else if (pFindData
) {
3480 __u16 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
3482 /* On legacy responses we do not read the last field,
3483 EAsize, fortunately since it varies by subdialect and
3484 also note it differs on Set vs. Get, ie two bytes or 4
3485 bytes depending but we don't care here */
3487 size
= sizeof(FILE_INFO_STANDARD
);
3489 size
= sizeof(FILE_ALL_INFO
);
3490 memcpy((char *) pFindData
,
3491 (char *) &pSMBr
->hdr
.Protocol
+
3496 cifs_buf_release(pSMB
);
3498 goto QPathInfoRetry
;
3504 CIFSSMBUnixQFileInfo(const int xid
, struct cifsTconInfo
*tcon
,
3505 u16 netfid
, FILE_UNIX_BASIC_INFO
*pFindData
)
3507 struct smb_t2_qfi_req
*pSMB
= NULL
;
3508 struct smb_t2_qfi_rsp
*pSMBr
= NULL
;
3511 __u16 params
, byte_count
;
3514 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
3519 params
= 2 /* level */ + 2 /* fid */;
3520 pSMB
->t2
.TotalDataCount
= 0;
3521 pSMB
->t2
.MaxParameterCount
= cpu_to_le16(4);
3522 /* BB find exact max data count below from sess structure BB */
3523 pSMB
->t2
.MaxDataCount
= cpu_to_le16(CIFSMaxBufSize
);
3524 pSMB
->t2
.MaxSetupCount
= 0;
3525 pSMB
->t2
.Reserved
= 0;
3527 pSMB
->t2
.Timeout
= 0;
3528 pSMB
->t2
.Reserved2
= 0;
3529 pSMB
->t2
.ParameterOffset
= cpu_to_le16(offsetof(struct smb_t2_qfi_req
,
3531 pSMB
->t2
.DataCount
= 0;
3532 pSMB
->t2
.DataOffset
= 0;
3533 pSMB
->t2
.SetupCount
= 1;
3534 pSMB
->t2
.Reserved3
= 0;
3535 pSMB
->t2
.SubCommand
= cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION
);
3536 byte_count
= params
+ 1 /* pad */ ;
3537 pSMB
->t2
.TotalParameterCount
= cpu_to_le16(params
);
3538 pSMB
->t2
.ParameterCount
= pSMB
->t2
.TotalParameterCount
;
3539 pSMB
->InformationLevel
= cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC
);
3542 pSMB
->hdr
.smb_buf_length
+= byte_count
;
3544 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
3545 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
3547 cFYI(1, "Send error in QPathInfo = %d", rc
);
3548 } else { /* decode response */
3549 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
3551 if (rc
|| (pSMBr
->ByteCount
< sizeof(FILE_UNIX_BASIC_INFO
))) {
3552 cERROR(1, "Malformed FILE_UNIX_BASIC_INFO response.\n"
3553 "Unix Extensions can be disabled on mount "
3554 "by specifying the nosfu mount option.");
3555 rc
= -EIO
; /* bad smb */
3557 __u16 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
3558 memcpy((char *) pFindData
,
3559 (char *) &pSMBr
->hdr
.Protocol
+
3561 sizeof(FILE_UNIX_BASIC_INFO
));
3565 cifs_buf_release(pSMB
);
3567 goto UnixQFileInfoRetry
;
3573 CIFSSMBUnixQPathInfo(const int xid
, struct cifsTconInfo
*tcon
,
3574 const unsigned char *searchName
,
3575 FILE_UNIX_BASIC_INFO
*pFindData
,
3576 const struct nls_table
*nls_codepage
, int remap
)
3578 /* SMB_QUERY_FILE_UNIX_BASIC */
3579 TRANSACTION2_QPI_REQ
*pSMB
= NULL
;
3580 TRANSACTION2_QPI_RSP
*pSMBr
= NULL
;
3582 int bytes_returned
= 0;
3584 __u16 params
, byte_count
;
3586 cFYI(1, "In QPathInfo (Unix) the path %s", searchName
);
3588 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
3593 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
3595 cifsConvertToUCS((__le16
*) pSMB
->FileName
, searchName
,
3596 PATH_MAX
, nls_codepage
, remap
);
3597 name_len
++; /* trailing null */
3599 } else { /* BB improve the check for buffer overruns BB */
3600 name_len
= strnlen(searchName
, PATH_MAX
);
3601 name_len
++; /* trailing null */
3602 strncpy(pSMB
->FileName
, searchName
, name_len
);
3605 params
= 2 /* level */ + 4 /* reserved */ + name_len
/* includes NUL */;
3606 pSMB
->TotalDataCount
= 0;
3607 pSMB
->MaxParameterCount
= cpu_to_le16(2);
3608 /* BB find exact max SMB PDU from sess structure BB */
3609 pSMB
->MaxDataCount
= cpu_to_le16(4000);
3610 pSMB
->MaxSetupCount
= 0;
3614 pSMB
->Reserved2
= 0;
3615 pSMB
->ParameterOffset
= cpu_to_le16(offsetof(
3616 struct smb_com_transaction2_qpi_req
, InformationLevel
) - 4);
3617 pSMB
->DataCount
= 0;
3618 pSMB
->DataOffset
= 0;
3619 pSMB
->SetupCount
= 1;
3620 pSMB
->Reserved3
= 0;
3621 pSMB
->SubCommand
= cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION
);
3622 byte_count
= params
+ 1 /* pad */ ;
3623 pSMB
->TotalParameterCount
= cpu_to_le16(params
);
3624 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
3625 pSMB
->InformationLevel
= cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC
);
3626 pSMB
->Reserved4
= 0;
3627 pSMB
->hdr
.smb_buf_length
+= byte_count
;
3628 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
3630 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
3631 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
3633 cFYI(1, "Send error in QPathInfo = %d", rc
);
3634 } else { /* decode response */
3635 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
3637 if (rc
|| (pSMBr
->ByteCount
< sizeof(FILE_UNIX_BASIC_INFO
))) {
3638 cERROR(1, "Malformed FILE_UNIX_BASIC_INFO response.\n"
3639 "Unix Extensions can be disabled on mount "
3640 "by specifying the nosfu mount option.");
3641 rc
= -EIO
; /* bad smb */
3643 __u16 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
3644 memcpy((char *) pFindData
,
3645 (char *) &pSMBr
->hdr
.Protocol
+
3647 sizeof(FILE_UNIX_BASIC_INFO
));
3650 cifs_buf_release(pSMB
);
3652 goto UnixQPathInfoRetry
;
3657 /* xid, tcon, searchName and codepage are input parms, rest are returned */
3659 CIFSFindFirst(const int xid
, struct cifsTconInfo
*tcon
,
3660 const char *searchName
,
3661 const struct nls_table
*nls_codepage
,
3663 struct cifs_search_info
*psrch_inf
, int remap
, const char dirsep
)
3665 /* level 257 SMB_ */
3666 TRANSACTION2_FFIRST_REQ
*pSMB
= NULL
;
3667 TRANSACTION2_FFIRST_RSP
*pSMBr
= NULL
;
3668 T2_FFIRST_RSP_PARMS
*parms
;
3670 int bytes_returned
= 0;
3672 __u16 params
, byte_count
;
3674 cFYI(1, "In FindFirst for %s", searchName
);
3677 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
3682 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
3684 cifsConvertToUCS((__le16
*) pSMB
->FileName
, searchName
,
3685 PATH_MAX
, nls_codepage
, remap
);
3686 /* We can not add the asterik earlier in case
3687 it got remapped to 0xF03A as if it were part of the
3688 directory name instead of a wildcard */
3690 pSMB
->FileName
[name_len
] = dirsep
;
3691 pSMB
->FileName
[name_len
+1] = 0;
3692 pSMB
->FileName
[name_len
+2] = '*';
3693 pSMB
->FileName
[name_len
+3] = 0;
3694 name_len
+= 4; /* now the trailing null */
3695 pSMB
->FileName
[name_len
] = 0; /* null terminate just in case */
3696 pSMB
->FileName
[name_len
+1] = 0;
3698 } else { /* BB add check for overrun of SMB buf BB */
3699 name_len
= strnlen(searchName
, PATH_MAX
);
3700 /* BB fix here and in unicode clause above ie
3701 if (name_len > buffersize-header)
3702 free buffer exit; BB */
3703 strncpy(pSMB
->FileName
, searchName
, name_len
);
3704 pSMB
->FileName
[name_len
] = dirsep
;
3705 pSMB
->FileName
[name_len
+1] = '*';
3706 pSMB
->FileName
[name_len
+2] = 0;
3710 params
= 12 + name_len
/* includes null */ ;
3711 pSMB
->TotalDataCount
= 0; /* no EAs */
3712 pSMB
->MaxParameterCount
= cpu_to_le16(10);
3713 pSMB
->MaxDataCount
= cpu_to_le16((tcon
->ses
->server
->maxBuf
-
3714 MAX_CIFS_HDR_SIZE
) & 0xFFFFFF00);
3715 pSMB
->MaxSetupCount
= 0;
3719 pSMB
->Reserved2
= 0;
3720 byte_count
= params
+ 1 /* pad */ ;
3721 pSMB
->TotalParameterCount
= cpu_to_le16(params
);
3722 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
3723 pSMB
->ParameterOffset
= cpu_to_le16(
3724 offsetof(struct smb_com_transaction2_ffirst_req
, SearchAttributes
)
3726 pSMB
->DataCount
= 0;
3727 pSMB
->DataOffset
= 0;
3728 pSMB
->SetupCount
= 1; /* one byte, no need to make endian neutral */
3729 pSMB
->Reserved3
= 0;
3730 pSMB
->SubCommand
= cpu_to_le16(TRANS2_FIND_FIRST
);
3731 pSMB
->SearchAttributes
=
3732 cpu_to_le16(ATTR_READONLY
| ATTR_HIDDEN
| ATTR_SYSTEM
|
3734 pSMB
->SearchCount
= cpu_to_le16(CIFSMaxBufSize
/sizeof(FILE_UNIX_INFO
));
3735 pSMB
->SearchFlags
= cpu_to_le16(CIFS_SEARCH_CLOSE_AT_END
|
3736 CIFS_SEARCH_RETURN_RESUME
);
3737 pSMB
->InformationLevel
= cpu_to_le16(psrch_inf
->info_level
);
3739 /* BB what should we set StorageType to? Does it matter? BB */
3740 pSMB
->SearchStorageType
= 0;
3741 pSMB
->hdr
.smb_buf_length
+= byte_count
;
3742 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
3744 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
3745 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
3746 cifs_stats_inc(&tcon
->num_ffirst
);
3748 if (rc
) {/* BB add logic to retry regular search if Unix search
3749 rejected unexpectedly by server */
3750 /* BB Add code to handle unsupported level rc */
3751 cFYI(1, "Error in FindFirst = %d", rc
);
3753 cifs_buf_release(pSMB
);
3755 /* BB eventually could optimize out free and realloc of buf */
3758 goto findFirstRetry
;
3759 } else { /* decode response */
3760 /* BB remember to free buffer if error BB */
3761 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
3765 if (pSMBr
->hdr
.Flags2
& SMBFLG2_UNICODE
)
3766 psrch_inf
->unicode
= true;
3768 psrch_inf
->unicode
= false;
3770 psrch_inf
->ntwrk_buf_start
= (char *)pSMBr
;
3771 psrch_inf
->smallBuf
= 0;
3772 psrch_inf
->srch_entries_start
=
3773 (char *) &pSMBr
->hdr
.Protocol
+
3774 le16_to_cpu(pSMBr
->t2
.DataOffset
);
3775 parms
= (T2_FFIRST_RSP_PARMS
*)((char *) &pSMBr
->hdr
.Protocol
+
3776 le16_to_cpu(pSMBr
->t2
.ParameterOffset
));
3778 if (parms
->EndofSearch
)
3779 psrch_inf
->endOfSearch
= true;
3781 psrch_inf
->endOfSearch
= false;
3783 psrch_inf
->entries_in_buffer
=
3784 le16_to_cpu(parms
->SearchCount
);
3785 psrch_inf
->index_of_last_entry
= 2 /* skip . and .. */ +
3786 psrch_inf
->entries_in_buffer
;
3787 lnoff
= le16_to_cpu(parms
->LastNameOffset
);
3788 if (tcon
->ses
->server
->maxBuf
- MAX_CIFS_HDR_SIZE
<
3790 cERROR(1, "ignoring corrupt resume name");
3791 psrch_inf
->last_entry
= NULL
;
3795 psrch_inf
->last_entry
= psrch_inf
->srch_entries_start
+
3798 *pnetfid
= parms
->SearchHandle
;
3800 cifs_buf_release(pSMB
);
3807 int CIFSFindNext(const int xid
, struct cifsTconInfo
*tcon
,
3808 __u16 searchHandle
, struct cifs_search_info
*psrch_inf
)
3810 TRANSACTION2_FNEXT_REQ
*pSMB
= NULL
;
3811 TRANSACTION2_FNEXT_RSP
*pSMBr
= NULL
;
3812 T2_FNEXT_RSP_PARMS
*parms
;
3813 char *response_data
;
3815 int bytes_returned
, name_len
;
3816 __u16 params
, byte_count
;
3818 cFYI(1, "In FindNext");
3820 if (psrch_inf
->endOfSearch
)
3823 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
3828 params
= 14; /* includes 2 bytes of null string, converted to LE below*/
3830 pSMB
->TotalDataCount
= 0; /* no EAs */
3831 pSMB
->MaxParameterCount
= cpu_to_le16(8);
3832 pSMB
->MaxDataCount
=
3833 cpu_to_le16((tcon
->ses
->server
->maxBuf
- MAX_CIFS_HDR_SIZE
) &
3835 pSMB
->MaxSetupCount
= 0;
3839 pSMB
->Reserved2
= 0;
3840 pSMB
->ParameterOffset
= cpu_to_le16(
3841 offsetof(struct smb_com_transaction2_fnext_req
,SearchHandle
) - 4);
3842 pSMB
->DataCount
= 0;
3843 pSMB
->DataOffset
= 0;
3844 pSMB
->SetupCount
= 1;
3845 pSMB
->Reserved3
= 0;
3846 pSMB
->SubCommand
= cpu_to_le16(TRANS2_FIND_NEXT
);
3847 pSMB
->SearchHandle
= searchHandle
; /* always kept as le */
3849 cpu_to_le16(CIFSMaxBufSize
/ sizeof(FILE_UNIX_INFO
));
3850 pSMB
->InformationLevel
= cpu_to_le16(psrch_inf
->info_level
);
3851 pSMB
->ResumeKey
= psrch_inf
->resume_key
;
3853 cpu_to_le16(CIFS_SEARCH_CLOSE_AT_END
| CIFS_SEARCH_RETURN_RESUME
);
3855 name_len
= psrch_inf
->resume_name_len
;
3857 if (name_len
< PATH_MAX
) {
3858 memcpy(pSMB
->ResumeFileName
, psrch_inf
->presume_name
, name_len
);
3859 byte_count
+= name_len
;
3860 /* 14 byte parm len above enough for 2 byte null terminator */
3861 pSMB
->ResumeFileName
[name_len
] = 0;
3862 pSMB
->ResumeFileName
[name_len
+1] = 0;
3865 goto FNext2_err_exit
;
3867 byte_count
= params
+ 1 /* pad */ ;
3868 pSMB
->TotalParameterCount
= cpu_to_le16(params
);
3869 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
3870 pSMB
->hdr
.smb_buf_length
+= byte_count
;
3871 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
3873 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
3874 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
3875 cifs_stats_inc(&tcon
->num_fnext
);
3878 psrch_inf
->endOfSearch
= true;
3879 cifs_buf_release(pSMB
);
3880 rc
= 0; /* search probably was closed at end of search*/
3882 cFYI(1, "FindNext returned = %d", rc
);
3883 } else { /* decode response */
3884 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
3889 /* BB fixme add lock for file (srch_info) struct here */
3890 if (pSMBr
->hdr
.Flags2
& SMBFLG2_UNICODE
)
3891 psrch_inf
->unicode
= true;
3893 psrch_inf
->unicode
= false;
3894 response_data
= (char *) &pSMBr
->hdr
.Protocol
+
3895 le16_to_cpu(pSMBr
->t2
.ParameterOffset
);
3896 parms
= (T2_FNEXT_RSP_PARMS
*)response_data
;
3897 response_data
= (char *)&pSMBr
->hdr
.Protocol
+
3898 le16_to_cpu(pSMBr
->t2
.DataOffset
);
3899 if (psrch_inf
->smallBuf
)
3900 cifs_small_buf_release(
3901 psrch_inf
->ntwrk_buf_start
);
3903 cifs_buf_release(psrch_inf
->ntwrk_buf_start
);
3904 psrch_inf
->srch_entries_start
= response_data
;
3905 psrch_inf
->ntwrk_buf_start
= (char *)pSMB
;
3906 psrch_inf
->smallBuf
= 0;
3907 if (parms
->EndofSearch
)
3908 psrch_inf
->endOfSearch
= true;
3910 psrch_inf
->endOfSearch
= false;
3911 psrch_inf
->entries_in_buffer
=
3912 le16_to_cpu(parms
->SearchCount
);
3913 psrch_inf
->index_of_last_entry
+=
3914 psrch_inf
->entries_in_buffer
;
3915 lnoff
= le16_to_cpu(parms
->LastNameOffset
);
3916 if (tcon
->ses
->server
->maxBuf
- MAX_CIFS_HDR_SIZE
<
3918 cERROR(1, "ignoring corrupt resume name");
3919 psrch_inf
->last_entry
= NULL
;
3922 psrch_inf
->last_entry
=
3923 psrch_inf
->srch_entries_start
+ lnoff
;
3925 /* cFYI(1, "fnxt2 entries in buf %d index_of_last %d",
3926 psrch_inf->entries_in_buffer, psrch_inf->index_of_last_entry); */
3928 /* BB fixme add unlock here */
3933 /* BB On error, should we leave previous search buf (and count and
3934 last entry fields) intact or free the previous one? */
3936 /* Note: On -EAGAIN error only caller can retry on handle based calls
3937 since file handle passed in no longer valid */
3940 cifs_buf_release(pSMB
);
3945 CIFSFindClose(const int xid
, struct cifsTconInfo
*tcon
,
3946 const __u16 searchHandle
)
3949 FINDCLOSE_REQ
*pSMB
= NULL
;
3951 cFYI(1, "In CIFSSMBFindClose");
3952 rc
= small_smb_init(SMB_COM_FIND_CLOSE2
, 1, tcon
, (void **)&pSMB
);
3954 /* no sense returning error if session restarted
3955 as file handle has been closed */
3961 pSMB
->FileID
= searchHandle
;
3962 pSMB
->ByteCount
= 0;
3963 rc
= SendReceiveNoRsp(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
, 0);
3965 cERROR(1, "Send error in FindClose = %d", rc
);
3967 cifs_stats_inc(&tcon
->num_fclose
);
3969 /* Since session is dead, search handle closed on server already */
3977 CIFSGetSrvInodeNumber(const int xid
, struct cifsTconInfo
*tcon
,
3978 const unsigned char *searchName
,
3979 __u64
*inode_number
,
3980 const struct nls_table
*nls_codepage
, int remap
)
3983 TRANSACTION2_QPI_REQ
*pSMB
= NULL
;
3984 TRANSACTION2_QPI_RSP
*pSMBr
= NULL
;
3985 int name_len
, bytes_returned
;
3986 __u16 params
, byte_count
;
3988 cFYI(1, "In GetSrvInodeNum for %s", searchName
);
3992 GetInodeNumberRetry
:
3993 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
3998 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
4000 cifsConvertToUCS((__le16
*) pSMB
->FileName
, searchName
,
4001 PATH_MAX
, nls_codepage
, remap
);
4002 name_len
++; /* trailing null */
4004 } else { /* BB improve the check for buffer overruns BB */
4005 name_len
= strnlen(searchName
, PATH_MAX
);
4006 name_len
++; /* trailing null */
4007 strncpy(pSMB
->FileName
, searchName
, name_len
);
4010 params
= 2 /* level */ + 4 /* rsrvd */ + name_len
/* incl null */ ;
4011 pSMB
->TotalDataCount
= 0;
4012 pSMB
->MaxParameterCount
= cpu_to_le16(2);
4013 /* BB find exact max data count below from sess structure BB */
4014 pSMB
->MaxDataCount
= cpu_to_le16(4000);
4015 pSMB
->MaxSetupCount
= 0;
4019 pSMB
->Reserved2
= 0;
4020 pSMB
->ParameterOffset
= cpu_to_le16(offsetof(
4021 struct smb_com_transaction2_qpi_req
, InformationLevel
) - 4);
4022 pSMB
->DataCount
= 0;
4023 pSMB
->DataOffset
= 0;
4024 pSMB
->SetupCount
= 1;
4025 pSMB
->Reserved3
= 0;
4026 pSMB
->SubCommand
= cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION
);
4027 byte_count
= params
+ 1 /* pad */ ;
4028 pSMB
->TotalParameterCount
= cpu_to_le16(params
);
4029 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
4030 pSMB
->InformationLevel
= cpu_to_le16(SMB_QUERY_FILE_INTERNAL_INFO
);
4031 pSMB
->Reserved4
= 0;
4032 pSMB
->hdr
.smb_buf_length
+= byte_count
;
4033 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
4035 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
4036 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
4038 cFYI(1, "error %d in QueryInternalInfo", rc
);
4040 /* decode response */
4041 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
4042 if (rc
|| (pSMBr
->ByteCount
< 2))
4043 /* BB also check enough total bytes returned */
4044 /* If rc should we check for EOPNOSUPP and
4045 disable the srvino flag? or in caller? */
4046 rc
= -EIO
; /* bad smb */
4048 __u16 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
4049 __u16 count
= le16_to_cpu(pSMBr
->t2
.DataCount
);
4050 struct file_internal_info
*pfinfo
;
4051 /* BB Do we need a cast or hash here ? */
4053 cFYI(1, "Illegal size ret in QryIntrnlInf");
4055 goto GetInodeNumOut
;
4057 pfinfo
= (struct file_internal_info
*)
4058 (data_offset
+ (char *) &pSMBr
->hdr
.Protocol
);
4059 *inode_number
= le64_to_cpu(pfinfo
->UniqueId
);
4063 cifs_buf_release(pSMB
);
4065 goto GetInodeNumberRetry
;
4069 /* parses DFS refferal V3 structure
4070 * caller is responsible for freeing target_nodes
4073 * on failure - errno
4076 parse_DFS_referrals(TRANSACTION2_GET_DFS_REFER_RSP
*pSMBr
,
4077 unsigned int *num_of_nodes
,
4078 struct dfs_info3_param
**target_nodes
,
4079 const struct nls_table
*nls_codepage
, int remap
,
4080 const char *searchName
)
4085 struct dfs_referral_level_3
*ref
;
4087 if (pSMBr
->hdr
.Flags2
& SMBFLG2_UNICODE
)
4091 *num_of_nodes
= le16_to_cpu(pSMBr
->NumberOfReferrals
);
4093 if (*num_of_nodes
< 1) {
4094 cERROR(1, "num_referrals: must be at least > 0,"
4095 "but we get num_referrals = %d\n", *num_of_nodes
);
4097 goto parse_DFS_referrals_exit
;
4100 ref
= (struct dfs_referral_level_3
*) &(pSMBr
->referrals
);
4101 if (ref
->VersionNumber
!= cpu_to_le16(3)) {
4102 cERROR(1, "Referrals of V%d version are not supported,"
4103 "should be V3", le16_to_cpu(ref
->VersionNumber
));
4105 goto parse_DFS_referrals_exit
;
4108 /* get the upper boundary of the resp buffer */
4109 data_end
= (char *)(&(pSMBr
->PathConsumed
)) +
4110 le16_to_cpu(pSMBr
->t2
.DataCount
);
4112 cFYI(1, "num_referrals: %d dfs flags: 0x%x ...\n",
4114 le32_to_cpu(pSMBr
->DFSFlags
));
4116 *target_nodes
= kzalloc(sizeof(struct dfs_info3_param
) *
4117 *num_of_nodes
, GFP_KERNEL
);
4118 if (*target_nodes
== NULL
) {
4119 cERROR(1, "Failed to allocate buffer for target_nodes\n");
4121 goto parse_DFS_referrals_exit
;
4124 /* collect necessary data from referrals */
4125 for (i
= 0; i
< *num_of_nodes
; i
++) {
4128 struct dfs_info3_param
*node
= (*target_nodes
)+i
;
4130 node
->flags
= le32_to_cpu(pSMBr
->DFSFlags
);
4132 __le16
*tmp
= kmalloc(strlen(searchName
)*2 + 2,
4136 goto parse_DFS_referrals_exit
;
4138 cifsConvertToUCS((__le16
*) tmp
, searchName
,
4139 PATH_MAX
, nls_codepage
, remap
);
4140 node
->path_consumed
= cifs_ucs2_bytes(tmp
,
4141 le16_to_cpu(pSMBr
->PathConsumed
),
4145 node
->path_consumed
= le16_to_cpu(pSMBr
->PathConsumed
);
4147 node
->server_type
= le16_to_cpu(ref
->ServerType
);
4148 node
->ref_flag
= le16_to_cpu(ref
->ReferralEntryFlags
);
4151 temp
= (char *)ref
+ le16_to_cpu(ref
->DfsPathOffset
);
4152 max_len
= data_end
- temp
;
4153 node
->path_name
= cifs_strndup_from_ucs(temp
, max_len
,
4154 is_unicode
, nls_codepage
);
4155 if (!node
->path_name
) {
4157 goto parse_DFS_referrals_exit
;
4160 /* copy link target UNC */
4161 temp
= (char *)ref
+ le16_to_cpu(ref
->NetworkAddressOffset
);
4162 max_len
= data_end
- temp
;
4163 node
->node_name
= cifs_strndup_from_ucs(temp
, max_len
,
4164 is_unicode
, nls_codepage
);
4165 if (!node
->node_name
)
4169 parse_DFS_referrals_exit
:
4171 free_dfs_info_array(*target_nodes
, *num_of_nodes
);
4172 *target_nodes
= NULL
;
4179 CIFSGetDFSRefer(const int xid
, struct cifsSesInfo
*ses
,
4180 const unsigned char *searchName
,
4181 struct dfs_info3_param
**target_nodes
,
4182 unsigned int *num_of_nodes
,
4183 const struct nls_table
*nls_codepage
, int remap
)
4185 /* TRANS2_GET_DFS_REFERRAL */
4186 TRANSACTION2_GET_DFS_REFER_REQ
*pSMB
= NULL
;
4187 TRANSACTION2_GET_DFS_REFER_RSP
*pSMBr
= NULL
;
4191 __u16 params
, byte_count
;
4193 *target_nodes
= NULL
;
4195 cFYI(1, "In GetDFSRefer the path %s", searchName
);
4199 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, NULL
, (void **) &pSMB
,
4204 /* server pointer checked in called function,
4205 but should never be null here anyway */
4206 pSMB
->hdr
.Mid
= GetNextMid(ses
->server
);
4207 pSMB
->hdr
.Tid
= ses
->ipc_tid
;
4208 pSMB
->hdr
.Uid
= ses
->Suid
;
4209 if (ses
->capabilities
& CAP_STATUS32
)
4210 pSMB
->hdr
.Flags2
|= SMBFLG2_ERR_STATUS
;
4211 if (ses
->capabilities
& CAP_DFS
)
4212 pSMB
->hdr
.Flags2
|= SMBFLG2_DFS
;
4214 if (ses
->capabilities
& CAP_UNICODE
) {
4215 pSMB
->hdr
.Flags2
|= SMBFLG2_UNICODE
;
4217 cifsConvertToUCS((__le16
*) pSMB
->RequestFileName
,
4218 searchName
, PATH_MAX
, nls_codepage
, remap
);
4219 name_len
++; /* trailing null */
4221 } else { /* BB improve the check for buffer overruns BB */
4222 name_len
= strnlen(searchName
, PATH_MAX
);
4223 name_len
++; /* trailing null */
4224 strncpy(pSMB
->RequestFileName
, searchName
, name_len
);
4228 if (ses
->server
->secMode
&
4229 (SECMODE_SIGN_REQUIRED
| SECMODE_SIGN_ENABLED
))
4230 pSMB
->hdr
.Flags2
|= SMBFLG2_SECURITY_SIGNATURE
;
4233 pSMB
->hdr
.Uid
= ses
->Suid
;
4235 params
= 2 /* level */ + name_len
/*includes null */ ;
4236 pSMB
->TotalDataCount
= 0;
4237 pSMB
->DataCount
= 0;
4238 pSMB
->DataOffset
= 0;
4239 pSMB
->MaxParameterCount
= 0;
4240 /* BB find exact max SMB PDU from sess structure BB */
4241 pSMB
->MaxDataCount
= cpu_to_le16(4000);
4242 pSMB
->MaxSetupCount
= 0;
4246 pSMB
->Reserved2
= 0;
4247 pSMB
->ParameterOffset
= cpu_to_le16(offsetof(
4248 struct smb_com_transaction2_get_dfs_refer_req
, MaxReferralLevel
) - 4);
4249 pSMB
->SetupCount
= 1;
4250 pSMB
->Reserved3
= 0;
4251 pSMB
->SubCommand
= cpu_to_le16(TRANS2_GET_DFS_REFERRAL
);
4252 byte_count
= params
+ 3 /* pad */ ;
4253 pSMB
->ParameterCount
= cpu_to_le16(params
);
4254 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
4255 pSMB
->MaxReferralLevel
= cpu_to_le16(3);
4256 pSMB
->hdr
.smb_buf_length
+= byte_count
;
4257 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
4259 rc
= SendReceive(xid
, ses
, (struct smb_hdr
*) pSMB
,
4260 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
4262 cFYI(1, "Send error in GetDFSRefer = %d", rc
);
4265 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
4267 /* BB Also check if enough total bytes returned? */
4268 if (rc
|| (pSMBr
->ByteCount
< 17)) {
4269 rc
= -EIO
; /* bad smb */
4273 cFYI(1, "Decoding GetDFSRefer response BCC: %d Offset %d",
4275 le16_to_cpu(pSMBr
->t2
.DataOffset
));
4277 /* parse returned result into more usable form */
4278 rc
= parse_DFS_referrals(pSMBr
, num_of_nodes
,
4279 target_nodes
, nls_codepage
, remap
,
4283 cifs_buf_release(pSMB
);
4291 /* Query File System Info such as free space to old servers such as Win 9x */
4293 SMBOldQFSInfo(const int xid
, struct cifsTconInfo
*tcon
, struct kstatfs
*FSData
)
4295 /* level 0x01 SMB_QUERY_FILE_SYSTEM_INFO */
4296 TRANSACTION2_QFSI_REQ
*pSMB
= NULL
;
4297 TRANSACTION2_QFSI_RSP
*pSMBr
= NULL
;
4298 FILE_SYSTEM_ALLOC_INFO
*response_data
;
4300 int bytes_returned
= 0;
4301 __u16 params
, byte_count
;
4303 cFYI(1, "OldQFSInfo");
4305 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
4310 params
= 2; /* level */
4311 pSMB
->TotalDataCount
= 0;
4312 pSMB
->MaxParameterCount
= cpu_to_le16(2);
4313 pSMB
->MaxDataCount
= cpu_to_le16(1000);
4314 pSMB
->MaxSetupCount
= 0;
4318 pSMB
->Reserved2
= 0;
4319 byte_count
= params
+ 1 /* pad */ ;
4320 pSMB
->TotalParameterCount
= cpu_to_le16(params
);
4321 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
4322 pSMB
->ParameterOffset
= cpu_to_le16(offsetof(
4323 struct smb_com_transaction2_qfsi_req
, InformationLevel
) - 4);
4324 pSMB
->DataCount
= 0;
4325 pSMB
->DataOffset
= 0;
4326 pSMB
->SetupCount
= 1;
4327 pSMB
->Reserved3
= 0;
4328 pSMB
->SubCommand
= cpu_to_le16(TRANS2_QUERY_FS_INFORMATION
);
4329 pSMB
->InformationLevel
= cpu_to_le16(SMB_INFO_ALLOCATION
);
4330 pSMB
->hdr
.smb_buf_length
+= byte_count
;
4331 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
4333 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
4334 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
4336 cFYI(1, "Send error in QFSInfo = %d", rc
);
4337 } else { /* decode response */
4338 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
4340 if (rc
|| (pSMBr
->ByteCount
< 18))
4341 rc
= -EIO
; /* bad smb */
4343 __u16 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
4344 cFYI(1, "qfsinf resp BCC: %d Offset %d",
4345 pSMBr
->ByteCount
, data_offset
);
4347 response_data
= (FILE_SYSTEM_ALLOC_INFO
*)
4348 (((char *) &pSMBr
->hdr
.Protocol
) + data_offset
);
4350 le16_to_cpu(response_data
->BytesPerSector
) *
4351 le32_to_cpu(response_data
->
4352 SectorsPerAllocationUnit
);
4354 le32_to_cpu(response_data
->TotalAllocationUnits
);
4355 FSData
->f_bfree
= FSData
->f_bavail
=
4356 le32_to_cpu(response_data
->FreeAllocationUnits
);
4357 cFYI(1, "Blocks: %lld Free: %lld Block size %ld",
4358 (unsigned long long)FSData
->f_blocks
,
4359 (unsigned long long)FSData
->f_bfree
,
4363 cifs_buf_release(pSMB
);
4366 goto oldQFSInfoRetry
;
4372 CIFSSMBQFSInfo(const int xid
, struct cifsTconInfo
*tcon
, struct kstatfs
*FSData
)
4374 /* level 0x103 SMB_QUERY_FILE_SYSTEM_INFO */
4375 TRANSACTION2_QFSI_REQ
*pSMB
= NULL
;
4376 TRANSACTION2_QFSI_RSP
*pSMBr
= NULL
;
4377 FILE_SYSTEM_INFO
*response_data
;
4379 int bytes_returned
= 0;
4380 __u16 params
, byte_count
;
4382 cFYI(1, "In QFSInfo");
4384 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
4389 params
= 2; /* level */
4390 pSMB
->TotalDataCount
= 0;
4391 pSMB
->MaxParameterCount
= cpu_to_le16(2);
4392 pSMB
->MaxDataCount
= cpu_to_le16(1000);
4393 pSMB
->MaxSetupCount
= 0;
4397 pSMB
->Reserved2
= 0;
4398 byte_count
= params
+ 1 /* pad */ ;
4399 pSMB
->TotalParameterCount
= cpu_to_le16(params
);
4400 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
4401 pSMB
->ParameterOffset
= cpu_to_le16(offsetof(
4402 struct smb_com_transaction2_qfsi_req
, InformationLevel
) - 4);
4403 pSMB
->DataCount
= 0;
4404 pSMB
->DataOffset
= 0;
4405 pSMB
->SetupCount
= 1;
4406 pSMB
->Reserved3
= 0;
4407 pSMB
->SubCommand
= cpu_to_le16(TRANS2_QUERY_FS_INFORMATION
);
4408 pSMB
->InformationLevel
= cpu_to_le16(SMB_QUERY_FS_SIZE_INFO
);
4409 pSMB
->hdr
.smb_buf_length
+= byte_count
;
4410 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
4412 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
4413 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
4415 cFYI(1, "Send error in QFSInfo = %d", rc
);
4416 } else { /* decode response */
4417 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
4419 if (rc
|| (pSMBr
->ByteCount
< 24))
4420 rc
= -EIO
; /* bad smb */
4422 __u16 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
4426 *) (((char *) &pSMBr
->hdr
.Protocol
) +
4429 le32_to_cpu(response_data
->BytesPerSector
) *
4430 le32_to_cpu(response_data
->
4431 SectorsPerAllocationUnit
);
4433 le64_to_cpu(response_data
->TotalAllocationUnits
);
4434 FSData
->f_bfree
= FSData
->f_bavail
=
4435 le64_to_cpu(response_data
->FreeAllocationUnits
);
4436 cFYI(1, "Blocks: %lld Free: %lld Block size %ld",
4437 (unsigned long long)FSData
->f_blocks
,
4438 (unsigned long long)FSData
->f_bfree
,
4442 cifs_buf_release(pSMB
);
4451 CIFSSMBQFSAttributeInfo(const int xid
, struct cifsTconInfo
*tcon
)
4453 /* level 0x105 SMB_QUERY_FILE_SYSTEM_INFO */
4454 TRANSACTION2_QFSI_REQ
*pSMB
= NULL
;
4455 TRANSACTION2_QFSI_RSP
*pSMBr
= NULL
;
4456 FILE_SYSTEM_ATTRIBUTE_INFO
*response_data
;
4458 int bytes_returned
= 0;
4459 __u16 params
, byte_count
;
4461 cFYI(1, "In QFSAttributeInfo");
4463 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
4468 params
= 2; /* level */
4469 pSMB
->TotalDataCount
= 0;
4470 pSMB
->MaxParameterCount
= cpu_to_le16(2);
4471 /* BB find exact max SMB PDU from sess structure BB */
4472 pSMB
->MaxDataCount
= cpu_to_le16(1000);
4473 pSMB
->MaxSetupCount
= 0;
4477 pSMB
->Reserved2
= 0;
4478 byte_count
= params
+ 1 /* pad */ ;
4479 pSMB
->TotalParameterCount
= cpu_to_le16(params
);
4480 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
4481 pSMB
->ParameterOffset
= cpu_to_le16(offsetof(
4482 struct smb_com_transaction2_qfsi_req
, InformationLevel
) - 4);
4483 pSMB
->DataCount
= 0;
4484 pSMB
->DataOffset
= 0;
4485 pSMB
->SetupCount
= 1;
4486 pSMB
->Reserved3
= 0;
4487 pSMB
->SubCommand
= cpu_to_le16(TRANS2_QUERY_FS_INFORMATION
);
4488 pSMB
->InformationLevel
= cpu_to_le16(SMB_QUERY_FS_ATTRIBUTE_INFO
);
4489 pSMB
->hdr
.smb_buf_length
+= byte_count
;
4490 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
4492 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
4493 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
4495 cERROR(1, "Send error in QFSAttributeInfo = %d", rc
);
4496 } else { /* decode response */
4497 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
4499 if (rc
|| (pSMBr
->ByteCount
< 13)) {
4500 /* BB also check if enough bytes returned */
4501 rc
= -EIO
; /* bad smb */
4503 __u16 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
4505 (FILE_SYSTEM_ATTRIBUTE_INFO
4506 *) (((char *) &pSMBr
->hdr
.Protocol
) +
4508 memcpy(&tcon
->fsAttrInfo
, response_data
,
4509 sizeof(FILE_SYSTEM_ATTRIBUTE_INFO
));
4512 cifs_buf_release(pSMB
);
4515 goto QFSAttributeRetry
;
4521 CIFSSMBQFSDeviceInfo(const int xid
, struct cifsTconInfo
*tcon
)
4523 /* level 0x104 SMB_QUERY_FILE_SYSTEM_INFO */
4524 TRANSACTION2_QFSI_REQ
*pSMB
= NULL
;
4525 TRANSACTION2_QFSI_RSP
*pSMBr
= NULL
;
4526 FILE_SYSTEM_DEVICE_INFO
*response_data
;
4528 int bytes_returned
= 0;
4529 __u16 params
, byte_count
;
4531 cFYI(1, "In QFSDeviceInfo");
4533 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
4538 params
= 2; /* level */
4539 pSMB
->TotalDataCount
= 0;
4540 pSMB
->MaxParameterCount
= cpu_to_le16(2);
4541 /* BB find exact max SMB PDU from sess structure BB */
4542 pSMB
->MaxDataCount
= cpu_to_le16(1000);
4543 pSMB
->MaxSetupCount
= 0;
4547 pSMB
->Reserved2
= 0;
4548 byte_count
= params
+ 1 /* pad */ ;
4549 pSMB
->TotalParameterCount
= cpu_to_le16(params
);
4550 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
4551 pSMB
->ParameterOffset
= cpu_to_le16(offsetof(
4552 struct smb_com_transaction2_qfsi_req
, InformationLevel
) - 4);
4554 pSMB
->DataCount
= 0;
4555 pSMB
->DataOffset
= 0;
4556 pSMB
->SetupCount
= 1;
4557 pSMB
->Reserved3
= 0;
4558 pSMB
->SubCommand
= cpu_to_le16(TRANS2_QUERY_FS_INFORMATION
);
4559 pSMB
->InformationLevel
= cpu_to_le16(SMB_QUERY_FS_DEVICE_INFO
);
4560 pSMB
->hdr
.smb_buf_length
+= byte_count
;
4561 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
4563 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
4564 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
4566 cFYI(1, "Send error in QFSDeviceInfo = %d", rc
);
4567 } else { /* decode response */
4568 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
4570 if (rc
|| (pSMBr
->ByteCount
< sizeof(FILE_SYSTEM_DEVICE_INFO
)))
4571 rc
= -EIO
; /* bad smb */
4573 __u16 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
4575 (FILE_SYSTEM_DEVICE_INFO
*)
4576 (((char *) &pSMBr
->hdr
.Protocol
) +
4578 memcpy(&tcon
->fsDevInfo
, response_data
,
4579 sizeof(FILE_SYSTEM_DEVICE_INFO
));
4582 cifs_buf_release(pSMB
);
4585 goto QFSDeviceRetry
;
4591 CIFSSMBQFSUnixInfo(const int xid
, struct cifsTconInfo
*tcon
)
4593 /* level 0x200 SMB_QUERY_CIFS_UNIX_INFO */
4594 TRANSACTION2_QFSI_REQ
*pSMB
= NULL
;
4595 TRANSACTION2_QFSI_RSP
*pSMBr
= NULL
;
4596 FILE_SYSTEM_UNIX_INFO
*response_data
;
4598 int bytes_returned
= 0;
4599 __u16 params
, byte_count
;
4601 cFYI(1, "In QFSUnixInfo");
4603 rc
= smb_init_no_reconnect(SMB_COM_TRANSACTION2
, 15, tcon
,
4604 (void **) &pSMB
, (void **) &pSMBr
);
4608 params
= 2; /* level */
4609 pSMB
->TotalDataCount
= 0;
4610 pSMB
->DataCount
= 0;
4611 pSMB
->DataOffset
= 0;
4612 pSMB
->MaxParameterCount
= cpu_to_le16(2);
4613 /* BB find exact max SMB PDU from sess structure BB */
4614 pSMB
->MaxDataCount
= cpu_to_le16(100);
4615 pSMB
->MaxSetupCount
= 0;
4619 pSMB
->Reserved2
= 0;
4620 byte_count
= params
+ 1 /* pad */ ;
4621 pSMB
->ParameterCount
= cpu_to_le16(params
);
4622 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
4623 pSMB
->ParameterOffset
= cpu_to_le16(offsetof(struct
4624 smb_com_transaction2_qfsi_req
, InformationLevel
) - 4);
4625 pSMB
->SetupCount
= 1;
4626 pSMB
->Reserved3
= 0;
4627 pSMB
->SubCommand
= cpu_to_le16(TRANS2_QUERY_FS_INFORMATION
);
4628 pSMB
->InformationLevel
= cpu_to_le16(SMB_QUERY_CIFS_UNIX_INFO
);
4629 pSMB
->hdr
.smb_buf_length
+= byte_count
;
4630 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
4632 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
4633 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
4635 cERROR(1, "Send error in QFSUnixInfo = %d", rc
);
4636 } else { /* decode response */
4637 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
4639 if (rc
|| (pSMBr
->ByteCount
< 13)) {
4640 rc
= -EIO
; /* bad smb */
4642 __u16 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
4644 (FILE_SYSTEM_UNIX_INFO
4645 *) (((char *) &pSMBr
->hdr
.Protocol
) +
4647 memcpy(&tcon
->fsUnixInfo
, response_data
,
4648 sizeof(FILE_SYSTEM_UNIX_INFO
));
4651 cifs_buf_release(pSMB
);
4661 CIFSSMBSetFSUnixInfo(const int xid
, struct cifsTconInfo
*tcon
, __u64 cap
)
4663 /* level 0x200 SMB_SET_CIFS_UNIX_INFO */
4664 TRANSACTION2_SETFSI_REQ
*pSMB
= NULL
;
4665 TRANSACTION2_SETFSI_RSP
*pSMBr
= NULL
;
4667 int bytes_returned
= 0;
4668 __u16 params
, param_offset
, offset
, byte_count
;
4670 cFYI(1, "In SETFSUnixInfo");
4672 /* BB switch to small buf init to save memory */
4673 rc
= smb_init_no_reconnect(SMB_COM_TRANSACTION2
, 15, tcon
,
4674 (void **) &pSMB
, (void **) &pSMBr
);
4678 params
= 4; /* 2 bytes zero followed by info level. */
4679 pSMB
->MaxSetupCount
= 0;
4683 pSMB
->Reserved2
= 0;
4684 param_offset
= offsetof(struct smb_com_transaction2_setfsi_req
, FileNum
)
4686 offset
= param_offset
+ params
;
4688 pSMB
->MaxParameterCount
= cpu_to_le16(4);
4689 /* BB find exact max SMB PDU from sess structure BB */
4690 pSMB
->MaxDataCount
= cpu_to_le16(100);
4691 pSMB
->SetupCount
= 1;
4692 pSMB
->Reserved3
= 0;
4693 pSMB
->SubCommand
= cpu_to_le16(TRANS2_SET_FS_INFORMATION
);
4694 byte_count
= 1 /* pad */ + params
+ 12;
4696 pSMB
->DataCount
= cpu_to_le16(12);
4697 pSMB
->ParameterCount
= cpu_to_le16(params
);
4698 pSMB
->TotalDataCount
= pSMB
->DataCount
;
4699 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
4700 pSMB
->ParameterOffset
= cpu_to_le16(param_offset
);
4701 pSMB
->DataOffset
= cpu_to_le16(offset
);
4705 pSMB
->InformationLevel
= cpu_to_le16(SMB_SET_CIFS_UNIX_INFO
);
4708 pSMB
->ClientUnixMajor
= cpu_to_le16(CIFS_UNIX_MAJOR_VERSION
);
4709 pSMB
->ClientUnixMinor
= cpu_to_le16(CIFS_UNIX_MINOR_VERSION
);
4710 pSMB
->ClientUnixCap
= cpu_to_le64(cap
);
4712 pSMB
->hdr
.smb_buf_length
+= byte_count
;
4713 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
4715 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
4716 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
4718 cERROR(1, "Send error in SETFSUnixInfo = %d", rc
);
4719 } else { /* decode response */
4720 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
4722 rc
= -EIO
; /* bad smb */
4724 cifs_buf_release(pSMB
);
4727 goto SETFSUnixRetry
;
4735 CIFSSMBQFSPosixInfo(const int xid
, struct cifsTconInfo
*tcon
,
4736 struct kstatfs
*FSData
)
4738 /* level 0x201 SMB_QUERY_CIFS_POSIX_INFO */
4739 TRANSACTION2_QFSI_REQ
*pSMB
= NULL
;
4740 TRANSACTION2_QFSI_RSP
*pSMBr
= NULL
;
4741 FILE_SYSTEM_POSIX_INFO
*response_data
;
4743 int bytes_returned
= 0;
4744 __u16 params
, byte_count
;
4746 cFYI(1, "In QFSPosixInfo");
4748 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
4753 params
= 2; /* level */
4754 pSMB
->TotalDataCount
= 0;
4755 pSMB
->DataCount
= 0;
4756 pSMB
->DataOffset
= 0;
4757 pSMB
->MaxParameterCount
= cpu_to_le16(2);
4758 /* BB find exact max SMB PDU from sess structure BB */
4759 pSMB
->MaxDataCount
= cpu_to_le16(100);
4760 pSMB
->MaxSetupCount
= 0;
4764 pSMB
->Reserved2
= 0;
4765 byte_count
= params
+ 1 /* pad */ ;
4766 pSMB
->ParameterCount
= cpu_to_le16(params
);
4767 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
4768 pSMB
->ParameterOffset
= cpu_to_le16(offsetof(struct
4769 smb_com_transaction2_qfsi_req
, InformationLevel
) - 4);
4770 pSMB
->SetupCount
= 1;
4771 pSMB
->Reserved3
= 0;
4772 pSMB
->SubCommand
= cpu_to_le16(TRANS2_QUERY_FS_INFORMATION
);
4773 pSMB
->InformationLevel
= cpu_to_le16(SMB_QUERY_POSIX_FS_INFO
);
4774 pSMB
->hdr
.smb_buf_length
+= byte_count
;
4775 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
4777 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
4778 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
4780 cFYI(1, "Send error in QFSUnixInfo = %d", rc
);
4781 } else { /* decode response */
4782 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
4784 if (rc
|| (pSMBr
->ByteCount
< 13)) {
4785 rc
= -EIO
; /* bad smb */
4787 __u16 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
4789 (FILE_SYSTEM_POSIX_INFO
4790 *) (((char *) &pSMBr
->hdr
.Protocol
) +
4793 le32_to_cpu(response_data
->BlockSize
);
4795 le64_to_cpu(response_data
->TotalBlocks
);
4797 le64_to_cpu(response_data
->BlocksAvail
);
4798 if (response_data
->UserBlocksAvail
== cpu_to_le64(-1)) {
4799 FSData
->f_bavail
= FSData
->f_bfree
;
4802 le64_to_cpu(response_data
->UserBlocksAvail
);
4804 if (response_data
->TotalFileNodes
!= cpu_to_le64(-1))
4806 le64_to_cpu(response_data
->TotalFileNodes
);
4807 if (response_data
->FreeFileNodes
!= cpu_to_le64(-1))
4809 le64_to_cpu(response_data
->FreeFileNodes
);
4812 cifs_buf_release(pSMB
);
4821 /* We can not use write of zero bytes trick to
4822 set file size due to need for large file support. Also note that
4823 this SetPathInfo is preferred to SetFileInfo based method in next
4824 routine which is only needed to work around a sharing violation bug
4825 in Samba which this routine can run into */
4828 CIFSSMBSetEOF(const int xid
, struct cifsTconInfo
*tcon
, const char *fileName
,
4829 __u64 size
, bool SetAllocation
,
4830 const struct nls_table
*nls_codepage
, int remap
)
4832 struct smb_com_transaction2_spi_req
*pSMB
= NULL
;
4833 struct smb_com_transaction2_spi_rsp
*pSMBr
= NULL
;
4834 struct file_end_of_file_info
*parm_data
;
4837 int bytes_returned
= 0;
4838 __u16 params
, byte_count
, data_count
, param_offset
, offset
;
4840 cFYI(1, "In SetEOF");
4842 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
4847 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
4849 cifsConvertToUCS((__le16
*) pSMB
->FileName
, fileName
,
4850 PATH_MAX
, nls_codepage
, remap
);
4851 name_len
++; /* trailing null */
4853 } else { /* BB improve the check for buffer overruns BB */
4854 name_len
= strnlen(fileName
, PATH_MAX
);
4855 name_len
++; /* trailing null */
4856 strncpy(pSMB
->FileName
, fileName
, name_len
);
4858 params
= 6 + name_len
;
4859 data_count
= sizeof(struct file_end_of_file_info
);
4860 pSMB
->MaxParameterCount
= cpu_to_le16(2);
4861 pSMB
->MaxDataCount
= cpu_to_le16(4100);
4862 pSMB
->MaxSetupCount
= 0;
4866 pSMB
->Reserved2
= 0;
4867 param_offset
= offsetof(struct smb_com_transaction2_spi_req
,
4868 InformationLevel
) - 4;
4869 offset
= param_offset
+ params
;
4870 if (SetAllocation
) {
4871 if (tcon
->ses
->capabilities
& CAP_INFOLEVEL_PASSTHRU
)
4872 pSMB
->InformationLevel
=
4873 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2
);
4875 pSMB
->InformationLevel
=
4876 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO
);
4877 } else /* Set File Size */ {
4878 if (tcon
->ses
->capabilities
& CAP_INFOLEVEL_PASSTHRU
)
4879 pSMB
->InformationLevel
=
4880 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO2
);
4882 pSMB
->InformationLevel
=
4883 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO
);
4887 (struct file_end_of_file_info
*) (((char *) &pSMB
->hdr
.Protocol
) +
4889 pSMB
->ParameterOffset
= cpu_to_le16(param_offset
);
4890 pSMB
->DataOffset
= cpu_to_le16(offset
);
4891 pSMB
->SetupCount
= 1;
4892 pSMB
->Reserved3
= 0;
4893 pSMB
->SubCommand
= cpu_to_le16(TRANS2_SET_PATH_INFORMATION
);
4894 byte_count
= 3 /* pad */ + params
+ data_count
;
4895 pSMB
->DataCount
= cpu_to_le16(data_count
);
4896 pSMB
->TotalDataCount
= pSMB
->DataCount
;
4897 pSMB
->ParameterCount
= cpu_to_le16(params
);
4898 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
4899 pSMB
->Reserved4
= 0;
4900 pSMB
->hdr
.smb_buf_length
+= byte_count
;
4901 parm_data
->FileSize
= cpu_to_le64(size
);
4902 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
4903 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
4904 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
4906 cFYI(1, "SetPathInfo (file size) returned %d", rc
);
4908 cifs_buf_release(pSMB
);
4917 CIFSSMBSetFileSize(const int xid
, struct cifsTconInfo
*tcon
, __u64 size
,
4918 __u16 fid
, __u32 pid_of_opener
, bool SetAllocation
)
4920 struct smb_com_transaction2_sfi_req
*pSMB
= NULL
;
4921 struct file_end_of_file_info
*parm_data
;
4923 __u16 params
, param_offset
, offset
, byte_count
, count
;
4925 cFYI(1, "SetFileSize (via SetFileInfo) %lld",
4927 rc
= small_smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
);
4932 pSMB
->hdr
.Pid
= cpu_to_le16((__u16
)pid_of_opener
);
4933 pSMB
->hdr
.PidHigh
= cpu_to_le16((__u16
)(pid_of_opener
>> 16));
4936 pSMB
->MaxSetupCount
= 0;
4940 pSMB
->Reserved2
= 0;
4941 param_offset
= offsetof(struct smb_com_transaction2_sfi_req
, Fid
) - 4;
4942 offset
= param_offset
+ params
;
4944 count
= sizeof(struct file_end_of_file_info
);
4945 pSMB
->MaxParameterCount
= cpu_to_le16(2);
4946 /* BB find exact max SMB PDU from sess structure BB */
4947 pSMB
->MaxDataCount
= cpu_to_le16(1000);
4948 pSMB
->SetupCount
= 1;
4949 pSMB
->Reserved3
= 0;
4950 pSMB
->SubCommand
= cpu_to_le16(TRANS2_SET_FILE_INFORMATION
);
4951 byte_count
= 3 /* pad */ + params
+ count
;
4952 pSMB
->DataCount
= cpu_to_le16(count
);
4953 pSMB
->ParameterCount
= cpu_to_le16(params
);
4954 pSMB
->TotalDataCount
= pSMB
->DataCount
;
4955 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
4956 pSMB
->ParameterOffset
= cpu_to_le16(param_offset
);
4958 (struct file_end_of_file_info
*) (((char *) &pSMB
->hdr
.Protocol
)
4960 pSMB
->DataOffset
= cpu_to_le16(offset
);
4961 parm_data
->FileSize
= cpu_to_le64(size
);
4963 if (SetAllocation
) {
4964 if (tcon
->ses
->capabilities
& CAP_INFOLEVEL_PASSTHRU
)
4965 pSMB
->InformationLevel
=
4966 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2
);
4968 pSMB
->InformationLevel
=
4969 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO
);
4970 } else /* Set File Size */ {
4971 if (tcon
->ses
->capabilities
& CAP_INFOLEVEL_PASSTHRU
)
4972 pSMB
->InformationLevel
=
4973 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO2
);
4975 pSMB
->InformationLevel
=
4976 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO
);
4978 pSMB
->Reserved4
= 0;
4979 pSMB
->hdr
.smb_buf_length
+= byte_count
;
4980 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
4981 rc
= SendReceiveNoRsp(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
, 0);
4983 cFYI(1, "Send error in SetFileInfo (SetFileSize) = %d", rc
);
4986 /* Note: On -EAGAIN error only caller can retry on handle based calls
4987 since file handle passed in no longer valid */
4992 /* Some legacy servers such as NT4 require that the file times be set on
4993 an open handle, rather than by pathname - this is awkward due to
4994 potential access conflicts on the open, but it is unavoidable for these
4995 old servers since the only other choice is to go from 100 nanosecond DCE
4996 time and resort to the original setpathinfo level which takes the ancient
4997 DOS time format with 2 second granularity */
4999 CIFSSMBSetFileInfo(const int xid
, struct cifsTconInfo
*tcon
,
5000 const FILE_BASIC_INFO
*data
, __u16 fid
, __u32 pid_of_opener
)
5002 struct smb_com_transaction2_sfi_req
*pSMB
= NULL
;
5005 __u16 params
, param_offset
, offset
, byte_count
, count
;
5007 cFYI(1, "Set Times (via SetFileInfo)");
5008 rc
= small_smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
);
5013 pSMB
->hdr
.Pid
= cpu_to_le16((__u16
)pid_of_opener
);
5014 pSMB
->hdr
.PidHigh
= cpu_to_le16((__u16
)(pid_of_opener
>> 16));
5017 pSMB
->MaxSetupCount
= 0;
5021 pSMB
->Reserved2
= 0;
5022 param_offset
= offsetof(struct smb_com_transaction2_sfi_req
, Fid
) - 4;
5023 offset
= param_offset
+ params
;
5025 data_offset
= (char *) (&pSMB
->hdr
.Protocol
) + offset
;
5027 count
= sizeof(FILE_BASIC_INFO
);
5028 pSMB
->MaxParameterCount
= cpu_to_le16(2);
5029 /* BB find max SMB PDU from sess */
5030 pSMB
->MaxDataCount
= cpu_to_le16(1000);
5031 pSMB
->SetupCount
= 1;
5032 pSMB
->Reserved3
= 0;
5033 pSMB
->SubCommand
= cpu_to_le16(TRANS2_SET_FILE_INFORMATION
);
5034 byte_count
= 3 /* pad */ + params
+ count
;
5035 pSMB
->DataCount
= cpu_to_le16(count
);
5036 pSMB
->ParameterCount
= cpu_to_le16(params
);
5037 pSMB
->TotalDataCount
= pSMB
->DataCount
;
5038 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
5039 pSMB
->ParameterOffset
= cpu_to_le16(param_offset
);
5040 pSMB
->DataOffset
= cpu_to_le16(offset
);
5042 if (tcon
->ses
->capabilities
& CAP_INFOLEVEL_PASSTHRU
)
5043 pSMB
->InformationLevel
= cpu_to_le16(SMB_SET_FILE_BASIC_INFO2
);
5045 pSMB
->InformationLevel
= cpu_to_le16(SMB_SET_FILE_BASIC_INFO
);
5046 pSMB
->Reserved4
= 0;
5047 pSMB
->hdr
.smb_buf_length
+= byte_count
;
5048 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
5049 memcpy(data_offset
, data
, sizeof(FILE_BASIC_INFO
));
5050 rc
= SendReceiveNoRsp(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
, 0);
5052 cFYI(1, "Send error in Set Time (SetFileInfo) = %d", rc
);
5054 /* Note: On -EAGAIN error only caller can retry on handle based calls
5055 since file handle passed in no longer valid */
5061 CIFSSMBSetFileDisposition(const int xid
, struct cifsTconInfo
*tcon
,
5062 bool delete_file
, __u16 fid
, __u32 pid_of_opener
)
5064 struct smb_com_transaction2_sfi_req
*pSMB
= NULL
;
5067 __u16 params
, param_offset
, offset
, byte_count
, count
;
5069 cFYI(1, "Set File Disposition (via SetFileInfo)");
5070 rc
= small_smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
);
5075 pSMB
->hdr
.Pid
= cpu_to_le16((__u16
)pid_of_opener
);
5076 pSMB
->hdr
.PidHigh
= cpu_to_le16((__u16
)(pid_of_opener
>> 16));
5079 pSMB
->MaxSetupCount
= 0;
5083 pSMB
->Reserved2
= 0;
5084 param_offset
= offsetof(struct smb_com_transaction2_sfi_req
, Fid
) - 4;
5085 offset
= param_offset
+ params
;
5087 data_offset
= (char *) (&pSMB
->hdr
.Protocol
) + offset
;
5090 pSMB
->MaxParameterCount
= cpu_to_le16(2);
5091 /* BB find max SMB PDU from sess */
5092 pSMB
->MaxDataCount
= cpu_to_le16(1000);
5093 pSMB
->SetupCount
= 1;
5094 pSMB
->Reserved3
= 0;
5095 pSMB
->SubCommand
= cpu_to_le16(TRANS2_SET_FILE_INFORMATION
);
5096 byte_count
= 3 /* pad */ + params
+ count
;
5097 pSMB
->DataCount
= cpu_to_le16(count
);
5098 pSMB
->ParameterCount
= cpu_to_le16(params
);
5099 pSMB
->TotalDataCount
= pSMB
->DataCount
;
5100 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
5101 pSMB
->ParameterOffset
= cpu_to_le16(param_offset
);
5102 pSMB
->DataOffset
= cpu_to_le16(offset
);
5104 pSMB
->InformationLevel
= cpu_to_le16(SMB_SET_FILE_DISPOSITION_INFO
);
5105 pSMB
->Reserved4
= 0;
5106 pSMB
->hdr
.smb_buf_length
+= byte_count
;
5107 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
5108 *data_offset
= delete_file
? 1 : 0;
5109 rc
= SendReceiveNoRsp(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
, 0);
5111 cFYI(1, "Send error in SetFileDisposition = %d", rc
);
5117 CIFSSMBSetPathInfo(const int xid
, struct cifsTconInfo
*tcon
,
5118 const char *fileName
, const FILE_BASIC_INFO
*data
,
5119 const struct nls_table
*nls_codepage
, int remap
)
5121 TRANSACTION2_SPI_REQ
*pSMB
= NULL
;
5122 TRANSACTION2_SPI_RSP
*pSMBr
= NULL
;
5125 int bytes_returned
= 0;
5127 __u16 params
, param_offset
, offset
, byte_count
, count
;
5129 cFYI(1, "In SetTimes");
5132 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
5137 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
5139 cifsConvertToUCS((__le16
*) pSMB
->FileName
, fileName
,
5140 PATH_MAX
, nls_codepage
, remap
);
5141 name_len
++; /* trailing null */
5143 } else { /* BB improve the check for buffer overruns BB */
5144 name_len
= strnlen(fileName
, PATH_MAX
);
5145 name_len
++; /* trailing null */
5146 strncpy(pSMB
->FileName
, fileName
, name_len
);
5149 params
= 6 + name_len
;
5150 count
= sizeof(FILE_BASIC_INFO
);
5151 pSMB
->MaxParameterCount
= cpu_to_le16(2);
5152 /* BB find max SMB PDU from sess structure BB */
5153 pSMB
->MaxDataCount
= cpu_to_le16(1000);
5154 pSMB
->MaxSetupCount
= 0;
5158 pSMB
->Reserved2
= 0;
5159 param_offset
= offsetof(struct smb_com_transaction2_spi_req
,
5160 InformationLevel
) - 4;
5161 offset
= param_offset
+ params
;
5162 data_offset
= (char *) (&pSMB
->hdr
.Protocol
) + offset
;
5163 pSMB
->ParameterOffset
= cpu_to_le16(param_offset
);
5164 pSMB
->DataOffset
= cpu_to_le16(offset
);
5165 pSMB
->SetupCount
= 1;
5166 pSMB
->Reserved3
= 0;
5167 pSMB
->SubCommand
= cpu_to_le16(TRANS2_SET_PATH_INFORMATION
);
5168 byte_count
= 3 /* pad */ + params
+ count
;
5170 pSMB
->DataCount
= cpu_to_le16(count
);
5171 pSMB
->ParameterCount
= cpu_to_le16(params
);
5172 pSMB
->TotalDataCount
= pSMB
->DataCount
;
5173 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
5174 if (tcon
->ses
->capabilities
& CAP_INFOLEVEL_PASSTHRU
)
5175 pSMB
->InformationLevel
= cpu_to_le16(SMB_SET_FILE_BASIC_INFO2
);
5177 pSMB
->InformationLevel
= cpu_to_le16(SMB_SET_FILE_BASIC_INFO
);
5178 pSMB
->Reserved4
= 0;
5179 pSMB
->hdr
.smb_buf_length
+= byte_count
;
5180 memcpy(data_offset
, data
, sizeof(FILE_BASIC_INFO
));
5181 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
5182 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
5183 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
5185 cFYI(1, "SetPathInfo (times) returned %d", rc
);
5187 cifs_buf_release(pSMB
);
5195 /* Can not be used to set time stamps yet (due to old DOS time format) */
5196 /* Can be used to set attributes */
5197 #if 0 /* Possibly not needed - since it turns out that strangely NT4 has a bug
5198 handling it anyway and NT4 was what we thought it would be needed for
5199 Do not delete it until we prove whether needed for Win9x though */
5201 CIFSSMBSetAttrLegacy(int xid
, struct cifsTconInfo
*tcon
, char *fileName
,
5202 __u16 dos_attrs
, const struct nls_table
*nls_codepage
)
5204 SETATTR_REQ
*pSMB
= NULL
;
5205 SETATTR_RSP
*pSMBr
= NULL
;
5210 cFYI(1, "In SetAttrLegacy");
5213 rc
= smb_init(SMB_COM_SETATTR
, 8, tcon
, (void **) &pSMB
,
5218 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
5220 ConvertToUCS((__le16
*) pSMB
->fileName
, fileName
,
5221 PATH_MAX
, nls_codepage
);
5222 name_len
++; /* trailing null */
5224 } else { /* BB improve the check for buffer overruns BB */
5225 name_len
= strnlen(fileName
, PATH_MAX
);
5226 name_len
++; /* trailing null */
5227 strncpy(pSMB
->fileName
, fileName
, name_len
);
5229 pSMB
->attr
= cpu_to_le16(dos_attrs
);
5230 pSMB
->BufferFormat
= 0x04;
5231 pSMB
->hdr
.smb_buf_length
+= name_len
+ 1;
5232 pSMB
->ByteCount
= cpu_to_le16(name_len
+ 1);
5233 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
5234 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
5236 cFYI(1, "Error in LegacySetAttr = %d", rc
);
5238 cifs_buf_release(pSMB
);
5241 goto SetAttrLgcyRetry
;
5245 #endif /* temporarily unneeded SetAttr legacy function */
5248 cifs_fill_unix_set_info(FILE_UNIX_BASIC_INFO
*data_offset
,
5249 const struct cifs_unix_set_info_args
*args
)
5251 u64 mode
= args
->mode
;
5254 * Samba server ignores set of file size to zero due to bugs in some
5255 * older clients, but we should be precise - we use SetFileSize to
5256 * set file size and do not want to truncate file size to zero
5257 * accidentally as happened on one Samba server beta by putting
5258 * zero instead of -1 here
5260 data_offset
->EndOfFile
= cpu_to_le64(NO_CHANGE_64
);
5261 data_offset
->NumOfBytes
= cpu_to_le64(NO_CHANGE_64
);
5262 data_offset
->LastStatusChange
= cpu_to_le64(args
->ctime
);
5263 data_offset
->LastAccessTime
= cpu_to_le64(args
->atime
);
5264 data_offset
->LastModificationTime
= cpu_to_le64(args
->mtime
);
5265 data_offset
->Uid
= cpu_to_le64(args
->uid
);
5266 data_offset
->Gid
= cpu_to_le64(args
->gid
);
5267 /* better to leave device as zero when it is */
5268 data_offset
->DevMajor
= cpu_to_le64(MAJOR(args
->device
));
5269 data_offset
->DevMinor
= cpu_to_le64(MINOR(args
->device
));
5270 data_offset
->Permissions
= cpu_to_le64(mode
);
5273 data_offset
->Type
= cpu_to_le32(UNIX_FILE
);
5274 else if (S_ISDIR(mode
))
5275 data_offset
->Type
= cpu_to_le32(UNIX_DIR
);
5276 else if (S_ISLNK(mode
))
5277 data_offset
->Type
= cpu_to_le32(UNIX_SYMLINK
);
5278 else if (S_ISCHR(mode
))
5279 data_offset
->Type
= cpu_to_le32(UNIX_CHARDEV
);
5280 else if (S_ISBLK(mode
))
5281 data_offset
->Type
= cpu_to_le32(UNIX_BLOCKDEV
);
5282 else if (S_ISFIFO(mode
))
5283 data_offset
->Type
= cpu_to_le32(UNIX_FIFO
);
5284 else if (S_ISSOCK(mode
))
5285 data_offset
->Type
= cpu_to_le32(UNIX_SOCKET
);
5289 CIFSSMBUnixSetFileInfo(const int xid
, struct cifsTconInfo
*tcon
,
5290 const struct cifs_unix_set_info_args
*args
,
5291 u16 fid
, u32 pid_of_opener
)
5293 struct smb_com_transaction2_sfi_req
*pSMB
= NULL
;
5294 FILE_UNIX_BASIC_INFO
*data_offset
;
5296 u16 params
, param_offset
, offset
, byte_count
, count
;
5298 cFYI(1, "Set Unix Info (via SetFileInfo)");
5299 rc
= small_smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
);
5304 pSMB
->hdr
.Pid
= cpu_to_le16((__u16
)pid_of_opener
);
5305 pSMB
->hdr
.PidHigh
= cpu_to_le16((__u16
)(pid_of_opener
>> 16));
5308 pSMB
->MaxSetupCount
= 0;
5312 pSMB
->Reserved2
= 0;
5313 param_offset
= offsetof(struct smb_com_transaction2_sfi_req
, Fid
) - 4;
5314 offset
= param_offset
+ params
;
5316 data_offset
= (FILE_UNIX_BASIC_INFO
*)
5317 ((char *)(&pSMB
->hdr
.Protocol
) + offset
);
5318 count
= sizeof(FILE_UNIX_BASIC_INFO
);
5320 pSMB
->MaxParameterCount
= cpu_to_le16(2);
5321 /* BB find max SMB PDU from sess */
5322 pSMB
->MaxDataCount
= cpu_to_le16(1000);
5323 pSMB
->SetupCount
= 1;
5324 pSMB
->Reserved3
= 0;
5325 pSMB
->SubCommand
= cpu_to_le16(TRANS2_SET_FILE_INFORMATION
);
5326 byte_count
= 3 /* pad */ + params
+ count
;
5327 pSMB
->DataCount
= cpu_to_le16(count
);
5328 pSMB
->ParameterCount
= cpu_to_le16(params
);
5329 pSMB
->TotalDataCount
= pSMB
->DataCount
;
5330 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
5331 pSMB
->ParameterOffset
= cpu_to_le16(param_offset
);
5332 pSMB
->DataOffset
= cpu_to_le16(offset
);
5334 pSMB
->InformationLevel
= cpu_to_le16(SMB_SET_FILE_UNIX_BASIC
);
5335 pSMB
->Reserved4
= 0;
5336 pSMB
->hdr
.smb_buf_length
+= byte_count
;
5337 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
5339 cifs_fill_unix_set_info(data_offset
, args
);
5341 rc
= SendReceiveNoRsp(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
, 0);
5343 cFYI(1, "Send error in Set Time (SetFileInfo) = %d", rc
);
5345 /* Note: On -EAGAIN error only caller can retry on handle based calls
5346 since file handle passed in no longer valid */
5352 CIFSSMBUnixSetPathInfo(const int xid
, struct cifsTconInfo
*tcon
, char *fileName
,
5353 const struct cifs_unix_set_info_args
*args
,
5354 const struct nls_table
*nls_codepage
, int remap
)
5356 TRANSACTION2_SPI_REQ
*pSMB
= NULL
;
5357 TRANSACTION2_SPI_RSP
*pSMBr
= NULL
;
5360 int bytes_returned
= 0;
5361 FILE_UNIX_BASIC_INFO
*data_offset
;
5362 __u16 params
, param_offset
, offset
, count
, byte_count
;
5364 cFYI(1, "In SetUID/GID/Mode");
5366 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
5371 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
5373 cifsConvertToUCS((__le16
*) pSMB
->FileName
, fileName
,
5374 PATH_MAX
, nls_codepage
, remap
);
5375 name_len
++; /* trailing null */
5377 } else { /* BB improve the check for buffer overruns BB */
5378 name_len
= strnlen(fileName
, PATH_MAX
);
5379 name_len
++; /* trailing null */
5380 strncpy(pSMB
->FileName
, fileName
, name_len
);
5383 params
= 6 + name_len
;
5384 count
= sizeof(FILE_UNIX_BASIC_INFO
);
5385 pSMB
->MaxParameterCount
= cpu_to_le16(2);
5386 /* BB find max SMB PDU from sess structure BB */
5387 pSMB
->MaxDataCount
= cpu_to_le16(1000);
5388 pSMB
->MaxSetupCount
= 0;
5392 pSMB
->Reserved2
= 0;
5393 param_offset
= offsetof(struct smb_com_transaction2_spi_req
,
5394 InformationLevel
) - 4;
5395 offset
= param_offset
+ params
;
5397 (FILE_UNIX_BASIC_INFO
*) ((char *) &pSMB
->hdr
.Protocol
+
5399 memset(data_offset
, 0, count
);
5400 pSMB
->DataOffset
= cpu_to_le16(offset
);
5401 pSMB
->ParameterOffset
= cpu_to_le16(param_offset
);
5402 pSMB
->SetupCount
= 1;
5403 pSMB
->Reserved3
= 0;
5404 pSMB
->SubCommand
= cpu_to_le16(TRANS2_SET_PATH_INFORMATION
);
5405 byte_count
= 3 /* pad */ + params
+ count
;
5406 pSMB
->ParameterCount
= cpu_to_le16(params
);
5407 pSMB
->DataCount
= cpu_to_le16(count
);
5408 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
5409 pSMB
->TotalDataCount
= pSMB
->DataCount
;
5410 pSMB
->InformationLevel
= cpu_to_le16(SMB_SET_FILE_UNIX_BASIC
);
5411 pSMB
->Reserved4
= 0;
5412 pSMB
->hdr
.smb_buf_length
+= byte_count
;
5414 cifs_fill_unix_set_info(data_offset
, args
);
5416 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
5417 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
5418 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
5420 cFYI(1, "SetPathInfo (perms) returned %d", rc
);
5422 cifs_buf_release(pSMB
);
5428 #ifdef CONFIG_CIFS_XATTR
5430 * Do a path-based QUERY_ALL_EAS call and parse the result. This is a common
5431 * function used by listxattr and getxattr type calls. When ea_name is set,
5432 * it looks for that attribute name and stuffs that value into the EAData
5433 * buffer. When ea_name is NULL, it stuffs a list of attribute names into the
5434 * buffer. In both cases, the return value is either the length of the
5435 * resulting data or a negative error code. If EAData is a NULL pointer then
5436 * the data isn't copied to it, but the length is returned.
5439 CIFSSMBQAllEAs(const int xid
, struct cifsTconInfo
*tcon
,
5440 const unsigned char *searchName
, const unsigned char *ea_name
,
5441 char *EAData
, size_t buf_size
,
5442 const struct nls_table
*nls_codepage
, int remap
)
5444 /* BB assumes one setup word */
5445 TRANSACTION2_QPI_REQ
*pSMB
= NULL
;
5446 TRANSACTION2_QPI_RSP
*pSMBr
= NULL
;
5450 struct fealist
*ea_response_data
;
5451 struct fea
*temp_fea
;
5454 __u16 params
, byte_count
, data_offset
;
5456 cFYI(1, "In Query All EAs path %s", searchName
);
5458 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
5463 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
5465 cifsConvertToUCS((__le16
*) pSMB
->FileName
, searchName
,
5466 PATH_MAX
, nls_codepage
, remap
);
5467 list_len
++; /* trailing null */
5469 } else { /* BB improve the check for buffer overruns BB */
5470 list_len
= strnlen(searchName
, PATH_MAX
);
5471 list_len
++; /* trailing null */
5472 strncpy(pSMB
->FileName
, searchName
, list_len
);
5475 params
= 2 /* level */ + 4 /* reserved */ + list_len
/* includes NUL */;
5476 pSMB
->TotalDataCount
= 0;
5477 pSMB
->MaxParameterCount
= cpu_to_le16(2);
5478 /* BB find exact max SMB PDU from sess structure BB */
5479 pSMB
->MaxDataCount
= cpu_to_le16(CIFSMaxBufSize
);
5480 pSMB
->MaxSetupCount
= 0;
5484 pSMB
->Reserved2
= 0;
5485 pSMB
->ParameterOffset
= cpu_to_le16(offsetof(
5486 struct smb_com_transaction2_qpi_req
, InformationLevel
) - 4);
5487 pSMB
->DataCount
= 0;
5488 pSMB
->DataOffset
= 0;
5489 pSMB
->SetupCount
= 1;
5490 pSMB
->Reserved3
= 0;
5491 pSMB
->SubCommand
= cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION
);
5492 byte_count
= params
+ 1 /* pad */ ;
5493 pSMB
->TotalParameterCount
= cpu_to_le16(params
);
5494 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
5495 pSMB
->InformationLevel
= cpu_to_le16(SMB_INFO_QUERY_ALL_EAS
);
5496 pSMB
->Reserved4
= 0;
5497 pSMB
->hdr
.smb_buf_length
+= byte_count
;
5498 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
5500 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
5501 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
5503 cFYI(1, "Send error in QueryAllEAs = %d", rc
);
5508 /* BB also check enough total bytes returned */
5509 /* BB we need to improve the validity checking
5510 of these trans2 responses */
5512 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
5513 if (rc
|| (pSMBr
->ByteCount
< 4)) {
5514 rc
= -EIO
; /* bad smb */
5518 /* check that length of list is not more than bcc */
5519 /* check that each entry does not go beyond length
5521 /* check that each element of each entry does not
5522 go beyond end of list */
5523 /* validate_trans2_offsets() */
5524 /* BB check if start of smb + data_offset > &bcc+ bcc */
5526 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
5527 ea_response_data
= (struct fealist
*)
5528 (((char *) &pSMBr
->hdr
.Protocol
) + data_offset
);
5530 list_len
= le32_to_cpu(ea_response_data
->list_len
);
5531 cFYI(1, "ea length %d", list_len
);
5532 if (list_len
<= 8) {
5533 cFYI(1, "empty EA list returned from server");
5537 /* make sure list_len doesn't go past end of SMB */
5538 end_of_smb
= (char *)pByteArea(&pSMBr
->hdr
) + get_bcc(&pSMBr
->hdr
);
5539 if ((char *)ea_response_data
+ list_len
> end_of_smb
) {
5540 cFYI(1, "EA list appears to go beyond SMB");
5545 /* account for ea list len */
5547 temp_fea
= ea_response_data
->list
;
5548 temp_ptr
= (char *)temp_fea
;
5549 while (list_len
> 0) {
5550 unsigned int name_len
;
5555 /* make sure we can read name_len and value_len */
5557 cFYI(1, "EA entry goes beyond length of list");
5562 name_len
= temp_fea
->name_len
;
5563 value_len
= le16_to_cpu(temp_fea
->value_len
);
5564 list_len
-= name_len
+ 1 + value_len
;
5566 cFYI(1, "EA entry goes beyond length of list");
5572 if (strncmp(ea_name
, temp_ptr
, name_len
) == 0) {
5573 temp_ptr
+= name_len
+ 1;
5577 if ((size_t)value_len
> buf_size
) {
5581 memcpy(EAData
, temp_ptr
, value_len
);
5585 /* account for prefix user. and trailing null */
5586 rc
+= (5 + 1 + name_len
);
5587 if (rc
< (int) buf_size
) {
5588 memcpy(EAData
, "user.", 5);
5590 memcpy(EAData
, temp_ptr
, name_len
);
5592 /* null terminate name */
5595 } else if (buf_size
== 0) {
5596 /* skip copy - calc size only */
5598 /* stop before overrun buffer */
5603 temp_ptr
+= name_len
+ 1 + value_len
;
5604 temp_fea
= (struct fea
*)temp_ptr
;
5607 /* didn't find the named attribute */
5612 cifs_buf_release(pSMB
);
5620 CIFSSMBSetEA(const int xid
, struct cifsTconInfo
*tcon
, const char *fileName
,
5621 const char *ea_name
, const void *ea_value
,
5622 const __u16 ea_value_len
, const struct nls_table
*nls_codepage
,
5625 struct smb_com_transaction2_spi_req
*pSMB
= NULL
;
5626 struct smb_com_transaction2_spi_rsp
*pSMBr
= NULL
;
5627 struct fealist
*parm_data
;
5630 int bytes_returned
= 0;
5631 __u16 params
, param_offset
, byte_count
, offset
, count
;
5633 cFYI(1, "In SetEA");
5635 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
5640 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
5642 cifsConvertToUCS((__le16
*) pSMB
->FileName
, fileName
,
5643 PATH_MAX
, nls_codepage
, remap
);
5644 name_len
++; /* trailing null */
5646 } else { /* BB improve the check for buffer overruns BB */
5647 name_len
= strnlen(fileName
, PATH_MAX
);
5648 name_len
++; /* trailing null */
5649 strncpy(pSMB
->FileName
, fileName
, name_len
);
5652 params
= 6 + name_len
;
5654 /* done calculating parms using name_len of file name,
5655 now use name_len to calculate length of ea name
5656 we are going to create in the inode xattrs */
5657 if (ea_name
== NULL
)
5660 name_len
= strnlen(ea_name
, 255);
5662 count
= sizeof(*parm_data
) + ea_value_len
+ name_len
;
5663 pSMB
->MaxParameterCount
= cpu_to_le16(2);
5664 /* BB find max SMB PDU from sess */
5665 pSMB
->MaxDataCount
= cpu_to_le16(1000);
5666 pSMB
->MaxSetupCount
= 0;
5670 pSMB
->Reserved2
= 0;
5671 param_offset
= offsetof(struct smb_com_transaction2_spi_req
,
5672 InformationLevel
) - 4;
5673 offset
= param_offset
+ params
;
5674 pSMB
->InformationLevel
=
5675 cpu_to_le16(SMB_SET_FILE_EA
);
5678 (struct fealist
*) (((char *) &pSMB
->hdr
.Protocol
) +
5680 pSMB
->ParameterOffset
= cpu_to_le16(param_offset
);
5681 pSMB
->DataOffset
= cpu_to_le16(offset
);
5682 pSMB
->SetupCount
= 1;
5683 pSMB
->Reserved3
= 0;
5684 pSMB
->SubCommand
= cpu_to_le16(TRANS2_SET_PATH_INFORMATION
);
5685 byte_count
= 3 /* pad */ + params
+ count
;
5686 pSMB
->DataCount
= cpu_to_le16(count
);
5687 parm_data
->list_len
= cpu_to_le32(count
);
5688 parm_data
->list
[0].EA_flags
= 0;
5689 /* we checked above that name len is less than 255 */
5690 parm_data
->list
[0].name_len
= (__u8
)name_len
;
5691 /* EA names are always ASCII */
5693 strncpy(parm_data
->list
[0].name
, ea_name
, name_len
);
5694 parm_data
->list
[0].name
[name_len
] = 0;
5695 parm_data
->list
[0].value_len
= cpu_to_le16(ea_value_len
);
5696 /* caller ensures that ea_value_len is less than 64K but
5697 we need to ensure that it fits within the smb */
5699 /*BB add length check to see if it would fit in
5700 negotiated SMB buffer size BB */
5701 /* if (ea_value_len > buffer_size - 512 (enough for header)) */
5703 memcpy(parm_data
->list
[0].name
+name_len
+1,
5704 ea_value
, ea_value_len
);
5706 pSMB
->TotalDataCount
= pSMB
->DataCount
;
5707 pSMB
->ParameterCount
= cpu_to_le16(params
);
5708 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
5709 pSMB
->Reserved4
= 0;
5710 pSMB
->hdr
.smb_buf_length
+= byte_count
;
5711 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
5712 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
5713 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
5715 cFYI(1, "SetPathInfo (EA) returned %d", rc
);
5717 cifs_buf_release(pSMB
);
5726 #ifdef CONFIG_CIFS_DNOTIFY_EXPERIMENTAL /* BB unused temporarily */
5728 * Years ago the kernel added a "dnotify" function for Samba server,
5729 * to allow network clients (such as Windows) to display updated
5730 * lists of files in directory listings automatically when
5731 * files are added by one user when another user has the
5732 * same directory open on their desktop. The Linux cifs kernel
5733 * client hooked into the kernel side of this interface for
5734 * the same reason, but ironically when the VFS moved from
5735 * "dnotify" to "inotify" it became harder to plug in Linux
5736 * network file system clients (the most obvious use case
5737 * for notify interfaces is when multiple users can update
5738 * the contents of the same directory - exactly what network
5739 * file systems can do) although the server (Samba) could
5740 * still use it. For the short term we leave the worker
5741 * function ifdeffed out (below) until inotify is fixed
5742 * in the VFS to make it easier to plug in network file
5743 * system clients. If inotify turns out to be permanently
5744 * incompatible for network fs clients, we could instead simply
5745 * expose this config flag by adding a future cifs (and smb2) notify ioctl.
5747 int CIFSSMBNotify(const int xid
, struct cifsTconInfo
*tcon
,
5748 const int notify_subdirs
, const __u16 netfid
,
5749 __u32 filter
, struct file
*pfile
, int multishot
,
5750 const struct nls_table
*nls_codepage
)
5753 struct smb_com_transaction_change_notify_req
*pSMB
= NULL
;
5754 struct smb_com_ntransaction_change_notify_rsp
*pSMBr
= NULL
;
5755 struct dir_notify_req
*dnotify_req
;
5758 cFYI(1, "In CIFSSMBNotify for file handle %d", (int)netfid
);
5759 rc
= smb_init(SMB_COM_NT_TRANSACT
, 23, tcon
, (void **) &pSMB
,
5764 pSMB
->TotalParameterCount
= 0 ;
5765 pSMB
->TotalDataCount
= 0;
5766 pSMB
->MaxParameterCount
= cpu_to_le32(2);
5767 /* BB find exact data count max from sess structure BB */
5768 pSMB
->MaxDataCount
= 0; /* same in little endian or be */
5769 /* BB VERIFY verify which is correct for above BB */
5770 pSMB
->MaxDataCount
= cpu_to_le32((tcon
->ses
->server
->maxBuf
-
5771 MAX_CIFS_HDR_SIZE
) & 0xFFFFFF00);
5773 pSMB
->MaxSetupCount
= 4;
5775 pSMB
->ParameterOffset
= 0;
5776 pSMB
->DataCount
= 0;
5777 pSMB
->DataOffset
= 0;
5778 pSMB
->SetupCount
= 4; /* single byte does not need le conversion */
5779 pSMB
->SubCommand
= cpu_to_le16(NT_TRANSACT_NOTIFY_CHANGE
);
5780 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
5782 pSMB
->WatchTree
= 1; /* one byte - no le conversion needed */
5783 pSMB
->Reserved2
= 0;
5784 pSMB
->CompletionFilter
= cpu_to_le32(filter
);
5785 pSMB
->Fid
= netfid
; /* file handle always le */
5786 pSMB
->ByteCount
= 0;
5788 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
5789 (struct smb_hdr
*)pSMBr
, &bytes_returned
,
5792 cFYI(1, "Error in Notify = %d", rc
);
5794 /* Add file to outstanding requests */
5795 /* BB change to kmem cache alloc */
5796 dnotify_req
= kmalloc(
5797 sizeof(struct dir_notify_req
),
5800 dnotify_req
->Pid
= pSMB
->hdr
.Pid
;
5801 dnotify_req
->PidHigh
= pSMB
->hdr
.PidHigh
;
5802 dnotify_req
->Mid
= pSMB
->hdr
.Mid
;
5803 dnotify_req
->Tid
= pSMB
->hdr
.Tid
;
5804 dnotify_req
->Uid
= pSMB
->hdr
.Uid
;
5805 dnotify_req
->netfid
= netfid
;
5806 dnotify_req
->pfile
= pfile
;
5807 dnotify_req
->filter
= filter
;
5808 dnotify_req
->multishot
= multishot
;
5809 spin_lock(&GlobalMid_Lock
);
5810 list_add_tail(&dnotify_req
->lhead
,
5811 &GlobalDnotifyReqList
);
5812 spin_unlock(&GlobalMid_Lock
);
5816 cifs_buf_release(pSMB
);
5819 #endif /* was needed for dnotify, and will be needed for inotify when VFS fix */