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 <linux/pagemap.h>
36 #include <linux/swap.h>
37 #include <linux/task_io_accounting_ops.h>
38 #include <asm/uaccess.h>
42 #include "cifsproto.h"
43 #include "cifs_unicode.h"
44 #include "cifs_debug.h"
47 #ifdef CONFIG_CIFS_POSIX
52 #ifdef CONFIG_CIFS_WEAK_PW_HASH
53 {LANMAN_PROT
, "\2LM1.2X002"},
54 {LANMAN2_PROT
, "\2LANMAN2.1"},
55 #endif /* weak password hashing for legacy clients */
56 {CIFS_PROT
, "\2NT LM 0.12"},
57 {POSIX_PROT
, "\2POSIX 2"},
65 #ifdef CONFIG_CIFS_WEAK_PW_HASH
66 {LANMAN_PROT
, "\2LM1.2X002"},
67 {LANMAN2_PROT
, "\2LANMAN2.1"},
68 #endif /* weak password hashing for legacy clients */
69 {CIFS_PROT
, "\2NT LM 0.12"},
74 /* define the number of elements in the cifs dialect array */
75 #ifdef CONFIG_CIFS_POSIX
76 #ifdef CONFIG_CIFS_WEAK_PW_HASH
77 #define CIFS_NUM_PROT 4
79 #define CIFS_NUM_PROT 2
80 #endif /* CIFS_WEAK_PW_HASH */
82 #ifdef CONFIG_CIFS_WEAK_PW_HASH
83 #define CIFS_NUM_PROT 3
85 #define CIFS_NUM_PROT 1
86 #endif /* CONFIG_CIFS_WEAK_PW_HASH */
87 #endif /* CIFS_POSIX */
91 * On arches that have high memory, kmap address space is limited. By
92 * serializing the kmap operations on those arches, we ensure that we don't
93 * end up with a bunch of threads in writeback with partially mapped page
94 * arrays, stuck waiting for kmap to come back. That situation prevents
95 * progress and can deadlock.
97 static DEFINE_MUTEX(cifs_kmap_mutex
);
102 mutex_lock(&cifs_kmap_mutex
);
106 cifs_kmap_unlock(void)
108 mutex_unlock(&cifs_kmap_mutex
);
110 #else /* !CONFIG_HIGHMEM */
111 #define cifs_kmap_lock() do { ; } while(0)
112 #define cifs_kmap_unlock() do { ; } while(0)
113 #endif /* CONFIG_HIGHMEM */
115 /* Mark as invalid, all open files on tree connections since they
116 were closed when session to server was lost */
117 static void mark_open_files_invalid(struct cifs_tcon
*pTcon
)
119 struct cifsFileInfo
*open_file
= NULL
;
120 struct list_head
*tmp
;
121 struct list_head
*tmp1
;
123 /* list all files open on tree connection and mark them invalid */
124 spin_lock(&cifs_file_list_lock
);
125 list_for_each_safe(tmp
, tmp1
, &pTcon
->openFileList
) {
126 open_file
= list_entry(tmp
, struct cifsFileInfo
, tlist
);
127 open_file
->invalidHandle
= true;
128 open_file
->oplock_break_cancelled
= true;
130 spin_unlock(&cifs_file_list_lock
);
131 /* BB Add call to invalidate_inodes(sb) for all superblocks mounted
135 /* reconnect the socket, tcon, and smb session if needed */
137 cifs_reconnect_tcon(struct cifs_tcon
*tcon
, int smb_command
)
140 struct cifs_ses
*ses
;
141 struct TCP_Server_Info
*server
;
142 struct nls_table
*nls_codepage
;
145 * SMBs NegProt, SessSetup, uLogoff do not have tcon yet so check for
146 * tcp and smb session status done differently for those three - in the
153 server
= ses
->server
;
156 * only tree disconnect, open, and write, (and ulogoff which does not
157 * have tcon) are allowed as we start force umount
159 if (tcon
->tidStatus
== CifsExiting
) {
160 if (smb_command
!= SMB_COM_WRITE_ANDX
&&
161 smb_command
!= SMB_COM_OPEN_ANDX
&&
162 smb_command
!= SMB_COM_TREE_DISCONNECT
) {
163 cFYI(1, "can not send cmd %d while umounting",
170 * Give demultiplex thread up to 10 seconds to reconnect, should be
171 * greater than cifs socket timeout which is 7 seconds
173 while (server
->tcpStatus
== CifsNeedReconnect
) {
174 wait_event_interruptible_timeout(server
->response_q
,
175 (server
->tcpStatus
!= CifsNeedReconnect
), 10 * HZ
);
177 /* are we still trying to reconnect? */
178 if (server
->tcpStatus
!= CifsNeedReconnect
)
182 * on "soft" mounts we wait once. Hard mounts keep
183 * retrying until process is killed or server comes
187 cFYI(1, "gave up waiting on reconnect in smb_init");
192 if (!ses
->need_reconnect
&& !tcon
->need_reconnect
)
195 nls_codepage
= load_nls_default();
198 * need to prevent multiple threads trying to simultaneously
199 * reconnect the same SMB session
201 mutex_lock(&ses
->session_mutex
);
202 rc
= cifs_negotiate_protocol(0, ses
);
203 if (rc
== 0 && ses
->need_reconnect
)
204 rc
= cifs_setup_session(0, ses
, nls_codepage
);
206 /* do we need to reconnect tcon? */
207 if (rc
|| !tcon
->need_reconnect
) {
208 mutex_unlock(&ses
->session_mutex
);
212 mark_open_files_invalid(tcon
);
213 rc
= CIFSTCon(0, ses
, tcon
->treeName
, tcon
, nls_codepage
);
214 mutex_unlock(&ses
->session_mutex
);
215 cFYI(1, "reconnect tcon rc = %d", rc
);
221 * FIXME: check if wsize needs updated due to negotiated smb buffer
224 atomic_inc(&tconInfoReconnectCount
);
226 /* tell server Unix caps we support */
227 if (ses
->capabilities
& CAP_UNIX
)
228 reset_cifs_unix_caps(0, tcon
, NULL
, NULL
);
231 * Removed call to reopen open files here. It is safer (and faster) to
232 * reopen files one at a time as needed in read and write.
234 * FIXME: what about file locks? don't we need to reclaim them ASAP?
239 * Check if handle based operation so we know whether we can continue
240 * or not without returning to caller to reset file handle
242 switch (smb_command
) {
243 case SMB_COM_READ_ANDX
:
244 case SMB_COM_WRITE_ANDX
:
246 case SMB_COM_FIND_CLOSE2
:
247 case SMB_COM_LOCKING_ANDX
:
251 unload_nls(nls_codepage
);
255 /* Allocate and return pointer to an SMB request buffer, and set basic
256 SMB information in the SMB header. If the return code is zero, this
257 function must have filled in request_buf pointer */
259 small_smb_init(int smb_command
, int wct
, struct cifs_tcon
*tcon
,
264 rc
= cifs_reconnect_tcon(tcon
, smb_command
);
268 *request_buf
= cifs_small_buf_get();
269 if (*request_buf
== NULL
) {
270 /* BB should we add a retry in here if not a writepage? */
274 header_assemble((struct smb_hdr
*) *request_buf
, smb_command
,
278 cifs_stats_inc(&tcon
->num_smbs_sent
);
284 small_smb_init_no_tc(const int smb_command
, const int wct
,
285 struct cifs_ses
*ses
, void **request_buf
)
288 struct smb_hdr
*buffer
;
290 rc
= small_smb_init(smb_command
, wct
, NULL
, request_buf
);
294 buffer
= (struct smb_hdr
*)*request_buf
;
295 buffer
->Mid
= get_next_mid(ses
->server
);
296 if (ses
->capabilities
& CAP_UNICODE
)
297 buffer
->Flags2
|= SMBFLG2_UNICODE
;
298 if (ses
->capabilities
& CAP_STATUS32
)
299 buffer
->Flags2
|= SMBFLG2_ERR_STATUS
;
301 /* uid, tid can stay at zero as set in header assemble */
303 /* BB add support for turning on the signing when
304 this function is used after 1st of session setup requests */
309 /* If the return code is zero, this function must fill in request_buf pointer */
311 __smb_init(int smb_command
, int wct
, struct cifs_tcon
*tcon
,
312 void **request_buf
, void **response_buf
)
314 *request_buf
= cifs_buf_get();
315 if (*request_buf
== NULL
) {
316 /* BB should we add a retry in here if not a writepage? */
319 /* Although the original thought was we needed the response buf for */
320 /* potential retries of smb operations it turns out we can determine */
321 /* from the mid flags when the request buffer can be resent without */
322 /* having to use a second distinct buffer for the response */
324 *response_buf
= *request_buf
;
326 header_assemble((struct smb_hdr
*) *request_buf
, smb_command
, tcon
,
330 cifs_stats_inc(&tcon
->num_smbs_sent
);
335 /* If the return code is zero, this function must fill in request_buf pointer */
337 smb_init(int smb_command
, int wct
, struct cifs_tcon
*tcon
,
338 void **request_buf
, void **response_buf
)
342 rc
= cifs_reconnect_tcon(tcon
, smb_command
);
346 return __smb_init(smb_command
, wct
, tcon
, request_buf
, response_buf
);
350 smb_init_no_reconnect(int smb_command
, int wct
, struct cifs_tcon
*tcon
,
351 void **request_buf
, void **response_buf
)
353 if (tcon
->ses
->need_reconnect
|| tcon
->need_reconnect
)
356 return __smb_init(smb_command
, wct
, tcon
, request_buf
, response_buf
);
359 static int validate_t2(struct smb_t2_rsp
*pSMB
)
361 unsigned int total_size
;
363 /* check for plausible wct */
364 if (pSMB
->hdr
.WordCount
< 10)
367 /* check for parm and data offset going beyond end of smb */
368 if (get_unaligned_le16(&pSMB
->t2_rsp
.ParameterOffset
) > 1024 ||
369 get_unaligned_le16(&pSMB
->t2_rsp
.DataOffset
) > 1024)
372 total_size
= get_unaligned_le16(&pSMB
->t2_rsp
.ParameterCount
);
373 if (total_size
>= 512)
376 /* check that bcc is at least as big as parms + data, and that it is
377 * less than negotiated smb buffer
379 total_size
+= get_unaligned_le16(&pSMB
->t2_rsp
.DataCount
);
380 if (total_size
> get_bcc(&pSMB
->hdr
) ||
381 total_size
>= CIFSMaxBufSize
+ MAX_CIFS_HDR_SIZE
)
386 cifs_dump_mem("Invalid transact2 SMB: ", (char *)pSMB
,
387 sizeof(struct smb_t2_rsp
) + 16);
392 CIFSSMBNegotiate(const unsigned int xid
, struct cifs_ses
*ses
)
395 NEGOTIATE_RSP
*pSMBr
;
399 struct TCP_Server_Info
*server
;
401 unsigned int secFlags
;
404 server
= ses
->server
;
409 rc
= smb_init(SMB_COM_NEGOTIATE
, 0, NULL
/* no tcon yet */ ,
410 (void **) &pSMB
, (void **) &pSMBr
);
414 /* if any of auth flags (ie not sign or seal) are overriden use them */
415 if (ses
->overrideSecFlg
& (~(CIFSSEC_MUST_SIGN
| CIFSSEC_MUST_SEAL
)))
416 secFlags
= ses
->overrideSecFlg
; /* BB FIXME fix sign flags? */
417 else /* if override flags set only sign/seal OR them with global auth */
418 secFlags
= global_secflags
| ses
->overrideSecFlg
;
420 cFYI(1, "secFlags 0x%x", secFlags
);
422 pSMB
->hdr
.Mid
= get_next_mid(server
);
423 pSMB
->hdr
.Flags2
|= (SMBFLG2_UNICODE
| SMBFLG2_ERR_STATUS
);
425 if ((secFlags
& CIFSSEC_MUST_KRB5
) == CIFSSEC_MUST_KRB5
)
426 pSMB
->hdr
.Flags2
|= SMBFLG2_EXT_SEC
;
427 else if ((secFlags
& CIFSSEC_AUTH_MASK
) == CIFSSEC_MAY_KRB5
) {
428 cFYI(1, "Kerberos only mechanism, enable extended security");
429 pSMB
->hdr
.Flags2
|= SMBFLG2_EXT_SEC
;
430 } else if ((secFlags
& CIFSSEC_MUST_NTLMSSP
) == CIFSSEC_MUST_NTLMSSP
)
431 pSMB
->hdr
.Flags2
|= SMBFLG2_EXT_SEC
;
432 else if ((secFlags
& CIFSSEC_AUTH_MASK
) == CIFSSEC_MAY_NTLMSSP
) {
433 cFYI(1, "NTLMSSP only mechanism, enable extended security");
434 pSMB
->hdr
.Flags2
|= SMBFLG2_EXT_SEC
;
438 for (i
= 0; i
< CIFS_NUM_PROT
; i
++) {
439 strncpy(pSMB
->DialectsArray
+count
, protocols
[i
].name
, 16);
440 count
+= strlen(protocols
[i
].name
) + 1;
441 /* null at end of source and target buffers anyway */
443 inc_rfc1001_len(pSMB
, count
);
444 pSMB
->ByteCount
= cpu_to_le16(count
);
446 rc
= SendReceive(xid
, ses
, (struct smb_hdr
*) pSMB
,
447 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
451 server
->dialect
= le16_to_cpu(pSMBr
->DialectIndex
);
452 cFYI(1, "Dialect: %d", server
->dialect
);
453 /* Check wct = 1 error case */
454 if ((pSMBr
->hdr
.WordCount
< 13) || (server
->dialect
== BAD_PROT
)) {
455 /* core returns wct = 1, but we do not ask for core - otherwise
456 small wct just comes when dialect index is -1 indicating we
457 could not negotiate a common dialect */
460 #ifdef CONFIG_CIFS_WEAK_PW_HASH
461 } else if ((pSMBr
->hdr
.WordCount
== 13)
462 && ((server
->dialect
== LANMAN_PROT
)
463 || (server
->dialect
== LANMAN2_PROT
))) {
465 struct lanman_neg_rsp
*rsp
= (struct lanman_neg_rsp
*)pSMBr
;
467 if ((secFlags
& CIFSSEC_MAY_LANMAN
) ||
468 (secFlags
& CIFSSEC_MAY_PLNTXT
))
469 server
->secType
= LANMAN
;
471 cERROR(1, "mount failed weak security disabled"
472 " in /proc/fs/cifs/SecurityFlags");
476 server
->sec_mode
= le16_to_cpu(rsp
->SecurityMode
);
477 server
->maxReq
= min_t(unsigned int,
478 le16_to_cpu(rsp
->MaxMpxCount
),
480 set_credits(server
, server
->maxReq
);
481 server
->maxBuf
= le16_to_cpu(rsp
->MaxBufSize
);
482 server
->max_vcs
= le16_to_cpu(rsp
->MaxNumberVcs
);
483 /* even though we do not use raw we might as well set this
484 accurately, in case we ever find a need for it */
485 if ((le16_to_cpu(rsp
->RawMode
) & RAW_ENABLE
) == RAW_ENABLE
) {
486 server
->max_rw
= 0xFF00;
487 server
->capabilities
= CAP_MPX_MODE
| CAP_RAW_MODE
;
489 server
->max_rw
= 0;/* do not need to use raw anyway */
490 server
->capabilities
= CAP_MPX_MODE
;
492 tmp
= (__s16
)le16_to_cpu(rsp
->ServerTimeZone
);
494 /* OS/2 often does not set timezone therefore
495 * we must use server time to calc time zone.
496 * Could deviate slightly from the right zone.
497 * Smallest defined timezone difference is 15 minutes
498 * (i.e. Nepal). Rounding up/down is done to match
501 int val
, seconds
, remain
, result
;
502 struct timespec ts
, utc
;
504 ts
= cnvrtDosUnixTm(rsp
->SrvTime
.Date
,
505 rsp
->SrvTime
.Time
, 0);
506 cFYI(1, "SrvTime %d sec since 1970 (utc: %d) diff: %d",
507 (int)ts
.tv_sec
, (int)utc
.tv_sec
,
508 (int)(utc
.tv_sec
- ts
.tv_sec
));
509 val
= (int)(utc
.tv_sec
- ts
.tv_sec
);
511 result
= (seconds
/ MIN_TZ_ADJ
) * MIN_TZ_ADJ
;
512 remain
= seconds
% MIN_TZ_ADJ
;
513 if (remain
>= (MIN_TZ_ADJ
/ 2))
514 result
+= MIN_TZ_ADJ
;
517 server
->timeAdj
= result
;
519 server
->timeAdj
= (int)tmp
;
520 server
->timeAdj
*= 60; /* also in seconds */
522 cFYI(1, "server->timeAdj: %d seconds", server
->timeAdj
);
525 /* BB get server time for time conversions and add
526 code to use it and timezone since this is not UTC */
528 if (rsp
->EncryptionKeyLength
==
529 cpu_to_le16(CIFS_CRYPTO_KEY_SIZE
)) {
530 memcpy(ses
->server
->cryptkey
, rsp
->EncryptionKey
,
531 CIFS_CRYPTO_KEY_SIZE
);
532 } else if (server
->sec_mode
& SECMODE_PW_ENCRYPT
) {
533 rc
= -EIO
; /* need cryptkey unless plain text */
537 cFYI(1, "LANMAN negotiated");
538 /* we will not end up setting signing flags - as no signing
539 was in LANMAN and server did not return the flags on */
541 #else /* weak security disabled */
542 } else if (pSMBr
->hdr
.WordCount
== 13) {
543 cERROR(1, "mount failed, cifs module not built "
544 "with CIFS_WEAK_PW_HASH support");
546 #endif /* WEAK_PW_HASH */
548 } else if (pSMBr
->hdr
.WordCount
!= 17) {
553 /* else wct == 17 NTLM */
554 server
->sec_mode
= pSMBr
->SecurityMode
;
555 if ((server
->sec_mode
& SECMODE_USER
) == 0)
556 cFYI(1, "share mode security");
558 if ((server
->sec_mode
& SECMODE_PW_ENCRYPT
) == 0)
559 #ifdef CONFIG_CIFS_WEAK_PW_HASH
560 if ((secFlags
& CIFSSEC_MAY_PLNTXT
) == 0)
561 #endif /* CIFS_WEAK_PW_HASH */
562 cERROR(1, "Server requests plain text password"
563 " but client support disabled");
565 if ((secFlags
& CIFSSEC_MUST_NTLMV2
) == CIFSSEC_MUST_NTLMV2
)
566 server
->secType
= NTLMv2
;
567 else if (secFlags
& CIFSSEC_MAY_NTLM
)
568 server
->secType
= NTLM
;
569 else if (secFlags
& CIFSSEC_MAY_NTLMV2
)
570 server
->secType
= NTLMv2
;
571 else if (secFlags
& CIFSSEC_MAY_KRB5
)
572 server
->secType
= Kerberos
;
573 else if (secFlags
& CIFSSEC_MAY_NTLMSSP
)
574 server
->secType
= RawNTLMSSP
;
575 else if (secFlags
& CIFSSEC_MAY_LANMAN
)
576 server
->secType
= LANMAN
;
579 cERROR(1, "Invalid security type");
582 /* else ... any others ...? */
584 /* one byte, so no need to convert this or EncryptionKeyLen from
586 server
->maxReq
= min_t(unsigned int, le16_to_cpu(pSMBr
->MaxMpxCount
),
588 set_credits(server
, server
->maxReq
);
589 /* probably no need to store and check maxvcs */
590 server
->maxBuf
= le32_to_cpu(pSMBr
->MaxBufferSize
);
591 server
->max_rw
= le32_to_cpu(pSMBr
->MaxRawSize
);
592 cFYI(DBG2
, "Max buf = %d", ses
->server
->maxBuf
);
593 server
->capabilities
= le32_to_cpu(pSMBr
->Capabilities
);
594 server
->timeAdj
= (int)(__s16
)le16_to_cpu(pSMBr
->ServerTimeZone
);
595 server
->timeAdj
*= 60;
596 if (pSMBr
->EncryptionKeyLength
== CIFS_CRYPTO_KEY_SIZE
) {
597 memcpy(ses
->server
->cryptkey
, pSMBr
->u
.EncryptionKey
,
598 CIFS_CRYPTO_KEY_SIZE
);
599 } else if ((pSMBr
->hdr
.Flags2
& SMBFLG2_EXT_SEC
||
600 server
->capabilities
& CAP_EXTENDED_SECURITY
) &&
601 (pSMBr
->EncryptionKeyLength
== 0)) {
602 /* decode security blob */
603 count
= get_bcc(&pSMBr
->hdr
);
608 spin_lock(&cifs_tcp_ses_lock
);
609 if (server
->srv_count
> 1) {
610 spin_unlock(&cifs_tcp_ses_lock
);
611 if (memcmp(server
->server_GUID
,
612 pSMBr
->u
.extended_response
.
614 cFYI(1, "server UID changed");
615 memcpy(server
->server_GUID
,
616 pSMBr
->u
.extended_response
.GUID
,
620 spin_unlock(&cifs_tcp_ses_lock
);
621 memcpy(server
->server_GUID
,
622 pSMBr
->u
.extended_response
.GUID
, 16);
626 server
->secType
= RawNTLMSSP
;
628 rc
= decode_negTokenInit(pSMBr
->u
.extended_response
.
629 SecurityBlob
, count
- 16,
635 if (server
->secType
== Kerberos
) {
636 if (!server
->sec_kerberos
&&
637 !server
->sec_mskerberos
)
639 } else if (server
->secType
== RawNTLMSSP
) {
640 if (!server
->sec_ntlmssp
)
645 } else if (server
->sec_mode
& SECMODE_PW_ENCRYPT
) {
646 rc
= -EIO
; /* no crypt key only if plain text pwd */
649 server
->capabilities
&= ~CAP_EXTENDED_SECURITY
;
651 #ifdef CONFIG_CIFS_WEAK_PW_HASH
654 if ((secFlags
& CIFSSEC_MAY_SIGN
) == 0) {
655 /* MUST_SIGN already includes the MAY_SIGN FLAG
656 so if this is zero it means that signing is disabled */
657 cFYI(1, "Signing disabled");
658 if (server
->sec_mode
& SECMODE_SIGN_REQUIRED
) {
659 cERROR(1, "Server requires "
660 "packet signing to be enabled in "
661 "/proc/fs/cifs/SecurityFlags.");
665 ~(SECMODE_SIGN_ENABLED
| SECMODE_SIGN_REQUIRED
);
666 } else if ((secFlags
& CIFSSEC_MUST_SIGN
) == CIFSSEC_MUST_SIGN
) {
667 /* signing required */
668 cFYI(1, "Must sign - secFlags 0x%x", secFlags
);
669 if ((server
->sec_mode
&
670 (SECMODE_SIGN_ENABLED
| SECMODE_SIGN_REQUIRED
)) == 0) {
671 cERROR(1, "signing required but server lacks support");
674 server
->sec_mode
|= SECMODE_SIGN_REQUIRED
;
676 /* signing optional ie CIFSSEC_MAY_SIGN */
677 if ((server
->sec_mode
& SECMODE_SIGN_REQUIRED
) == 0)
679 ~(SECMODE_SIGN_ENABLED
| SECMODE_SIGN_REQUIRED
);
683 cifs_buf_release(pSMB
);
685 cFYI(1, "negprot rc %d", rc
);
690 CIFSSMBTDis(const unsigned int xid
, struct cifs_tcon
*tcon
)
692 struct smb_hdr
*smb_buffer
;
695 cFYI(1, "In tree disconnect");
697 /* BB: do we need to check this? These should never be NULL. */
698 if ((tcon
->ses
== NULL
) || (tcon
->ses
->server
== NULL
))
702 * No need to return error on this operation if tid invalidated and
703 * closed on server already e.g. due to tcp session crashing. Also,
704 * the tcon is no longer on the list, so no need to take lock before
707 if ((tcon
->need_reconnect
) || (tcon
->ses
->need_reconnect
))
710 rc
= small_smb_init(SMB_COM_TREE_DISCONNECT
, 0, tcon
,
711 (void **)&smb_buffer
);
715 rc
= SendReceiveNoRsp(xid
, tcon
->ses
, (char *)smb_buffer
, 0);
717 cFYI(1, "Tree disconnect failed %d", rc
);
719 /* No need to return error on this operation if tid invalidated and
720 closed on server already e.g. due to tcp session crashing */
728 * This is a no-op for now. We're not really interested in the reply, but
729 * rather in the fact that the server sent one and that server->lstrp
732 * FIXME: maybe we should consider checking that the reply matches request?
735 cifs_echo_callback(struct mid_q_entry
*mid
)
737 struct TCP_Server_Info
*server
= mid
->callback_data
;
739 DeleteMidQEntry(mid
);
740 add_credits(server
, 1, CIFS_ECHO_OP
);
744 CIFSSMBEcho(struct TCP_Server_Info
*server
)
750 cFYI(1, "In echo request");
752 rc
= small_smb_init(SMB_COM_ECHO
, 0, NULL
, (void **)&smb
);
756 /* set up echo request */
757 smb
->hdr
.Tid
= 0xffff;
758 smb
->hdr
.WordCount
= 1;
759 put_unaligned_le16(1, &smb
->EchoCount
);
760 put_bcc(1, &smb
->hdr
);
762 inc_rfc1001_len(smb
, 3);
764 iov
.iov_len
= be32_to_cpu(smb
->hdr
.smb_buf_length
) + 4;
766 rc
= cifs_call_async(server
, &iov
, 1, NULL
, cifs_echo_callback
,
767 server
, CIFS_ASYNC_OP
| CIFS_ECHO_OP
);
769 cFYI(1, "Echo request failed: %d", rc
);
771 cifs_small_buf_release(smb
);
777 CIFSSMBLogoff(const unsigned int xid
, struct cifs_ses
*ses
)
779 LOGOFF_ANDX_REQ
*pSMB
;
782 cFYI(1, "In SMBLogoff for session disconnect");
785 * BB: do we need to check validity of ses and server? They should
786 * always be valid since we have an active reference. If not, that
787 * should probably be a BUG()
789 if (!ses
|| !ses
->server
)
792 mutex_lock(&ses
->session_mutex
);
793 if (ses
->need_reconnect
)
794 goto session_already_dead
; /* no need to send SMBlogoff if uid
795 already closed due to reconnect */
796 rc
= small_smb_init(SMB_COM_LOGOFF_ANDX
, 2, NULL
, (void **)&pSMB
);
798 mutex_unlock(&ses
->session_mutex
);
802 pSMB
->hdr
.Mid
= get_next_mid(ses
->server
);
804 if (ses
->server
->sec_mode
&
805 (SECMODE_SIGN_REQUIRED
| SECMODE_SIGN_ENABLED
))
806 pSMB
->hdr
.Flags2
|= SMBFLG2_SECURITY_SIGNATURE
;
808 pSMB
->hdr
.Uid
= ses
->Suid
;
810 pSMB
->AndXCommand
= 0xFF;
811 rc
= SendReceiveNoRsp(xid
, ses
, (char *) pSMB
, 0);
812 session_already_dead
:
813 mutex_unlock(&ses
->session_mutex
);
815 /* if session dead then we do not need to do ulogoff,
816 since server closed smb session, no sense reporting
824 CIFSPOSIXDelFile(const unsigned int xid
, struct cifs_tcon
*tcon
,
825 const char *fileName
, __u16 type
,
826 const struct nls_table
*nls_codepage
, int remap
)
828 TRANSACTION2_SPI_REQ
*pSMB
= NULL
;
829 TRANSACTION2_SPI_RSP
*pSMBr
= NULL
;
830 struct unlink_psx_rq
*pRqD
;
833 int bytes_returned
= 0;
834 __u16 params
, param_offset
, offset
, byte_count
;
836 cFYI(1, "In POSIX delete");
838 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
843 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
845 cifsConvertToUTF16((__le16
*) pSMB
->FileName
, fileName
,
846 PATH_MAX
, nls_codepage
, remap
);
847 name_len
++; /* trailing null */
849 } else { /* BB add path length overrun check */
850 name_len
= strnlen(fileName
, PATH_MAX
);
851 name_len
++; /* trailing null */
852 strncpy(pSMB
->FileName
, fileName
, name_len
);
855 params
= 6 + name_len
;
856 pSMB
->MaxParameterCount
= cpu_to_le16(2);
857 pSMB
->MaxDataCount
= 0; /* BB double check this with jra */
858 pSMB
->MaxSetupCount
= 0;
863 param_offset
= offsetof(struct smb_com_transaction2_spi_req
,
864 InformationLevel
) - 4;
865 offset
= param_offset
+ params
;
867 /* Setup pointer to Request Data (inode type) */
868 pRqD
= (struct unlink_psx_rq
*)(((char *)&pSMB
->hdr
.Protocol
) + offset
);
869 pRqD
->type
= cpu_to_le16(type
);
870 pSMB
->ParameterOffset
= cpu_to_le16(param_offset
);
871 pSMB
->DataOffset
= cpu_to_le16(offset
);
872 pSMB
->SetupCount
= 1;
874 pSMB
->SubCommand
= cpu_to_le16(TRANS2_SET_PATH_INFORMATION
);
875 byte_count
= 3 /* pad */ + params
+ sizeof(struct unlink_psx_rq
);
877 pSMB
->DataCount
= cpu_to_le16(sizeof(struct unlink_psx_rq
));
878 pSMB
->TotalDataCount
= cpu_to_le16(sizeof(struct unlink_psx_rq
));
879 pSMB
->ParameterCount
= cpu_to_le16(params
);
880 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
881 pSMB
->InformationLevel
= cpu_to_le16(SMB_POSIX_UNLINK
);
883 inc_rfc1001_len(pSMB
, byte_count
);
884 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
885 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
886 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
888 cFYI(1, "Posix delete returned %d", rc
);
889 cifs_buf_release(pSMB
);
891 cifs_stats_inc(&tcon
->num_deletes
);
900 CIFSSMBDelFile(const unsigned int xid
, struct cifs_tcon
*tcon
,
901 const char *fileName
, const struct nls_table
*nls_codepage
,
904 DELETE_FILE_REQ
*pSMB
= NULL
;
905 DELETE_FILE_RSP
*pSMBr
= NULL
;
911 rc
= smb_init(SMB_COM_DELETE
, 1, tcon
, (void **) &pSMB
,
916 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
918 cifsConvertToUTF16((__le16
*) pSMB
->fileName
, fileName
,
919 PATH_MAX
, nls_codepage
, remap
);
920 name_len
++; /* trailing null */
922 } else { /* BB improve check for buffer overruns BB */
923 name_len
= strnlen(fileName
, PATH_MAX
);
924 name_len
++; /* trailing null */
925 strncpy(pSMB
->fileName
, fileName
, name_len
);
927 pSMB
->SearchAttributes
=
928 cpu_to_le16(ATTR_READONLY
| ATTR_HIDDEN
| ATTR_SYSTEM
);
929 pSMB
->BufferFormat
= 0x04;
930 inc_rfc1001_len(pSMB
, name_len
+ 1);
931 pSMB
->ByteCount
= cpu_to_le16(name_len
+ 1);
932 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
933 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
934 cifs_stats_inc(&tcon
->num_deletes
);
936 cFYI(1, "Error in RMFile = %d", rc
);
938 cifs_buf_release(pSMB
);
946 CIFSSMBRmDir(const unsigned int xid
, struct cifs_tcon
*tcon
,
947 const char *dirName
, const struct nls_table
*nls_codepage
,
950 DELETE_DIRECTORY_REQ
*pSMB
= NULL
;
951 DELETE_DIRECTORY_RSP
*pSMBr
= NULL
;
956 cFYI(1, "In CIFSSMBRmDir");
958 rc
= smb_init(SMB_COM_DELETE_DIRECTORY
, 0, tcon
, (void **) &pSMB
,
963 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
964 name_len
= cifsConvertToUTF16((__le16
*) pSMB
->DirName
, dirName
,
965 PATH_MAX
, nls_codepage
, remap
);
966 name_len
++; /* trailing null */
968 } else { /* BB improve check for buffer overruns BB */
969 name_len
= strnlen(dirName
, PATH_MAX
);
970 name_len
++; /* trailing null */
971 strncpy(pSMB
->DirName
, dirName
, name_len
);
974 pSMB
->BufferFormat
= 0x04;
975 inc_rfc1001_len(pSMB
, name_len
+ 1);
976 pSMB
->ByteCount
= cpu_to_le16(name_len
+ 1);
977 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
978 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
979 cifs_stats_inc(&tcon
->num_rmdirs
);
981 cFYI(1, "Error in RMDir = %d", rc
);
983 cifs_buf_release(pSMB
);
990 CIFSSMBMkDir(const unsigned int xid
, struct cifs_tcon
*tcon
,
991 const char *name
, const struct nls_table
*nls_codepage
, int remap
)
994 CREATE_DIRECTORY_REQ
*pSMB
= NULL
;
995 CREATE_DIRECTORY_RSP
*pSMBr
= NULL
;
999 cFYI(1, "In CIFSSMBMkDir");
1001 rc
= smb_init(SMB_COM_CREATE_DIRECTORY
, 0, tcon
, (void **) &pSMB
,
1006 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
1007 name_len
= cifsConvertToUTF16((__le16
*) pSMB
->DirName
, name
,
1008 PATH_MAX
, nls_codepage
, remap
);
1009 name_len
++; /* trailing null */
1011 } else { /* BB improve check for buffer overruns BB */
1012 name_len
= strnlen(name
, PATH_MAX
);
1013 name_len
++; /* trailing null */
1014 strncpy(pSMB
->DirName
, name
, name_len
);
1017 pSMB
->BufferFormat
= 0x04;
1018 inc_rfc1001_len(pSMB
, name_len
+ 1);
1019 pSMB
->ByteCount
= cpu_to_le16(name_len
+ 1);
1020 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
1021 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
1022 cifs_stats_inc(&tcon
->num_mkdirs
);
1024 cFYI(1, "Error in Mkdir = %d", rc
);
1026 cifs_buf_release(pSMB
);
1033 CIFSPOSIXCreate(const unsigned int xid
, struct cifs_tcon
*tcon
,
1034 __u32 posix_flags
, __u64 mode
, __u16
*netfid
,
1035 FILE_UNIX_BASIC_INFO
*pRetData
, __u32
*pOplock
,
1036 const char *name
, const struct nls_table
*nls_codepage
,
1039 TRANSACTION2_SPI_REQ
*pSMB
= NULL
;
1040 TRANSACTION2_SPI_RSP
*pSMBr
= NULL
;
1043 int bytes_returned
= 0;
1044 __u16 params
, param_offset
, offset
, byte_count
, count
;
1045 OPEN_PSX_REQ
*pdata
;
1046 OPEN_PSX_RSP
*psx_rsp
;
1048 cFYI(1, "In POSIX Create");
1050 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
1055 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
1057 cifsConvertToUTF16((__le16
*) pSMB
->FileName
, name
,
1058 PATH_MAX
, nls_codepage
, remap
);
1059 name_len
++; /* trailing null */
1061 } else { /* BB improve the check for buffer overruns BB */
1062 name_len
= strnlen(name
, PATH_MAX
);
1063 name_len
++; /* trailing null */
1064 strncpy(pSMB
->FileName
, name
, name_len
);
1067 params
= 6 + name_len
;
1068 count
= sizeof(OPEN_PSX_REQ
);
1069 pSMB
->MaxParameterCount
= cpu_to_le16(2);
1070 pSMB
->MaxDataCount
= cpu_to_le16(1000); /* large enough */
1071 pSMB
->MaxSetupCount
= 0;
1075 pSMB
->Reserved2
= 0;
1076 param_offset
= offsetof(struct smb_com_transaction2_spi_req
,
1077 InformationLevel
) - 4;
1078 offset
= param_offset
+ params
;
1079 pdata
= (OPEN_PSX_REQ
*)(((char *)&pSMB
->hdr
.Protocol
) + offset
);
1080 pdata
->Level
= cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC
);
1081 pdata
->Permissions
= cpu_to_le64(mode
);
1082 pdata
->PosixOpenFlags
= cpu_to_le32(posix_flags
);
1083 pdata
->OpenFlags
= cpu_to_le32(*pOplock
);
1084 pSMB
->ParameterOffset
= cpu_to_le16(param_offset
);
1085 pSMB
->DataOffset
= cpu_to_le16(offset
);
1086 pSMB
->SetupCount
= 1;
1087 pSMB
->Reserved3
= 0;
1088 pSMB
->SubCommand
= cpu_to_le16(TRANS2_SET_PATH_INFORMATION
);
1089 byte_count
= 3 /* pad */ + params
+ count
;
1091 pSMB
->DataCount
= cpu_to_le16(count
);
1092 pSMB
->ParameterCount
= cpu_to_le16(params
);
1093 pSMB
->TotalDataCount
= pSMB
->DataCount
;
1094 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
1095 pSMB
->InformationLevel
= cpu_to_le16(SMB_POSIX_OPEN
);
1096 pSMB
->Reserved4
= 0;
1097 inc_rfc1001_len(pSMB
, byte_count
);
1098 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
1099 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
1100 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
1102 cFYI(1, "Posix create returned %d", rc
);
1103 goto psx_create_err
;
1106 cFYI(1, "copying inode info");
1107 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
1109 if (rc
|| get_bcc(&pSMBr
->hdr
) < sizeof(OPEN_PSX_RSP
)) {
1110 rc
= -EIO
; /* bad smb */
1111 goto psx_create_err
;
1114 /* copy return information to pRetData */
1115 psx_rsp
= (OPEN_PSX_RSP
*)((char *) &pSMBr
->hdr
.Protocol
1116 + le16_to_cpu(pSMBr
->t2
.DataOffset
));
1118 *pOplock
= le16_to_cpu(psx_rsp
->OplockFlags
);
1120 *netfid
= psx_rsp
->Fid
; /* cifs fid stays in le */
1121 /* Let caller know file was created so we can set the mode. */
1122 /* Do we care about the CreateAction in any other cases? */
1123 if (cpu_to_le32(FILE_CREATE
) == psx_rsp
->CreateAction
)
1124 *pOplock
|= CIFS_CREATE_ACTION
;
1125 /* check to make sure response data is there */
1126 if (psx_rsp
->ReturnedLevel
!= cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC
)) {
1127 pRetData
->Type
= cpu_to_le32(-1); /* unknown */
1128 cFYI(DBG2
, "unknown type");
1130 if (get_bcc(&pSMBr
->hdr
) < sizeof(OPEN_PSX_RSP
)
1131 + sizeof(FILE_UNIX_BASIC_INFO
)) {
1132 cERROR(1, "Open response data too small");
1133 pRetData
->Type
= cpu_to_le32(-1);
1134 goto psx_create_err
;
1136 memcpy((char *) pRetData
,
1137 (char *)psx_rsp
+ sizeof(OPEN_PSX_RSP
),
1138 sizeof(FILE_UNIX_BASIC_INFO
));
1142 cifs_buf_release(pSMB
);
1144 if (posix_flags
& SMB_O_DIRECTORY
)
1145 cifs_stats_inc(&tcon
->num_posixmkdirs
);
1147 cifs_stats_inc(&tcon
->num_posixopens
);
1155 static __u16
convert_disposition(int disposition
)
1159 switch (disposition
) {
1160 case FILE_SUPERSEDE
:
1161 ofun
= SMBOPEN_OCREATE
| SMBOPEN_OTRUNC
;
1164 ofun
= SMBOPEN_OAPPEND
;
1167 ofun
= SMBOPEN_OCREATE
;
1170 ofun
= SMBOPEN_OCREATE
| SMBOPEN_OAPPEND
;
1172 case FILE_OVERWRITE
:
1173 ofun
= SMBOPEN_OTRUNC
;
1175 case FILE_OVERWRITE_IF
:
1176 ofun
= SMBOPEN_OCREATE
| SMBOPEN_OTRUNC
;
1179 cFYI(1, "unknown disposition %d", disposition
);
1180 ofun
= SMBOPEN_OAPPEND
; /* regular open */
1186 access_flags_to_smbopen_mode(const int access_flags
)
1188 int masked_flags
= access_flags
& (GENERIC_READ
| GENERIC_WRITE
);
1190 if (masked_flags
== GENERIC_READ
)
1191 return SMBOPEN_READ
;
1192 else if (masked_flags
== GENERIC_WRITE
)
1193 return SMBOPEN_WRITE
;
1195 /* just go for read/write */
1196 return SMBOPEN_READWRITE
;
1200 SMBLegacyOpen(const unsigned int xid
, struct cifs_tcon
*tcon
,
1201 const char *fileName
, const int openDisposition
,
1202 const int access_flags
, const int create_options
, __u16
*netfid
,
1203 int *pOplock
, FILE_ALL_INFO
*pfile_info
,
1204 const struct nls_table
*nls_codepage
, int remap
)
1207 OPENX_REQ
*pSMB
= NULL
;
1208 OPENX_RSP
*pSMBr
= NULL
;
1214 rc
= smb_init(SMB_COM_OPEN_ANDX
, 15, tcon
, (void **) &pSMB
,
1219 pSMB
->AndXCommand
= 0xFF; /* none */
1221 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
1222 count
= 1; /* account for one byte pad to word boundary */
1224 cifsConvertToUTF16((__le16
*) (pSMB
->fileName
+ 1),
1225 fileName
, PATH_MAX
, nls_codepage
, remap
);
1226 name_len
++; /* trailing null */
1228 } else { /* BB improve check for buffer overruns BB */
1229 count
= 0; /* no pad */
1230 name_len
= strnlen(fileName
, PATH_MAX
);
1231 name_len
++; /* trailing null */
1232 strncpy(pSMB
->fileName
, fileName
, name_len
);
1234 if (*pOplock
& REQ_OPLOCK
)
1235 pSMB
->OpenFlags
= cpu_to_le16(REQ_OPLOCK
);
1236 else if (*pOplock
& REQ_BATCHOPLOCK
)
1237 pSMB
->OpenFlags
= cpu_to_le16(REQ_BATCHOPLOCK
);
1239 pSMB
->OpenFlags
|= cpu_to_le16(REQ_MORE_INFO
);
1240 pSMB
->Mode
= cpu_to_le16(access_flags_to_smbopen_mode(access_flags
));
1241 pSMB
->Mode
|= cpu_to_le16(0x40); /* deny none */
1242 /* set file as system file if special file such
1243 as fifo and server expecting SFU style and
1244 no Unix extensions */
1246 if (create_options
& CREATE_OPTION_SPECIAL
)
1247 pSMB
->FileAttributes
= cpu_to_le16(ATTR_SYSTEM
);
1248 else /* BB FIXME BB */
1249 pSMB
->FileAttributes
= cpu_to_le16(0/*ATTR_NORMAL*/);
1251 if (create_options
& CREATE_OPTION_READONLY
)
1252 pSMB
->FileAttributes
|= cpu_to_le16(ATTR_READONLY
);
1255 /* pSMB->CreateOptions = cpu_to_le32(create_options &
1256 CREATE_OPTIONS_MASK); */
1257 /* BB FIXME END BB */
1259 pSMB
->Sattr
= cpu_to_le16(ATTR_HIDDEN
| ATTR_SYSTEM
| ATTR_DIRECTORY
);
1260 pSMB
->OpenFunction
= cpu_to_le16(convert_disposition(openDisposition
));
1262 inc_rfc1001_len(pSMB
, count
);
1264 pSMB
->ByteCount
= cpu_to_le16(count
);
1265 /* long_op set to 1 to allow for oplock break timeouts */
1266 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
1267 (struct smb_hdr
*)pSMBr
, &bytes_returned
, 0);
1268 cifs_stats_inc(&tcon
->num_opens
);
1270 cFYI(1, "Error in Open = %d", rc
);
1272 /* BB verify if wct == 15 */
1274 /* *pOplock = pSMBr->OplockLevel; */ /* BB take from action field*/
1276 *netfid
= pSMBr
->Fid
; /* cifs fid stays in le */
1277 /* Let caller know file was created so we can set the mode. */
1278 /* Do we care about the CreateAction in any other cases? */
1280 /* if (cpu_to_le32(FILE_CREATE) == pSMBr->CreateAction)
1281 *pOplock |= CIFS_CREATE_ACTION; */
1285 pfile_info
->CreationTime
= 0; /* BB convert CreateTime*/
1286 pfile_info
->LastAccessTime
= 0; /* BB fixme */
1287 pfile_info
->LastWriteTime
= 0; /* BB fixme */
1288 pfile_info
->ChangeTime
= 0; /* BB fixme */
1289 pfile_info
->Attributes
=
1290 cpu_to_le32(le16_to_cpu(pSMBr
->FileAttributes
));
1291 /* the file_info buf is endian converted by caller */
1292 pfile_info
->AllocationSize
=
1293 cpu_to_le64(le32_to_cpu(pSMBr
->EndOfFile
));
1294 pfile_info
->EndOfFile
= pfile_info
->AllocationSize
;
1295 pfile_info
->NumberOfLinks
= cpu_to_le32(1);
1296 pfile_info
->DeletePending
= 0;
1300 cifs_buf_release(pSMB
);
1307 CIFSSMBOpen(const unsigned int xid
, struct cifs_tcon
*tcon
,
1308 const char *fileName
, const int openDisposition
,
1309 const int access_flags
, const int create_options
, __u16
*netfid
,
1310 int *pOplock
, FILE_ALL_INFO
*pfile_info
,
1311 const struct nls_table
*nls_codepage
, int remap
)
1314 OPEN_REQ
*pSMB
= NULL
;
1315 OPEN_RSP
*pSMBr
= NULL
;
1321 rc
= smb_init(SMB_COM_NT_CREATE_ANDX
, 24, tcon
, (void **) &pSMB
,
1326 pSMB
->AndXCommand
= 0xFF; /* none */
1328 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
1329 count
= 1; /* account for one byte pad to word boundary */
1331 cifsConvertToUTF16((__le16
*) (pSMB
->fileName
+ 1),
1332 fileName
, PATH_MAX
, nls_codepage
, remap
);
1333 name_len
++; /* trailing null */
1335 pSMB
->NameLength
= cpu_to_le16(name_len
);
1336 } else { /* BB improve check for buffer overruns BB */
1337 count
= 0; /* no pad */
1338 name_len
= strnlen(fileName
, PATH_MAX
);
1339 name_len
++; /* trailing null */
1340 pSMB
->NameLength
= cpu_to_le16(name_len
);
1341 strncpy(pSMB
->fileName
, fileName
, name_len
);
1343 if (*pOplock
& REQ_OPLOCK
)
1344 pSMB
->OpenFlags
= cpu_to_le32(REQ_OPLOCK
);
1345 else if (*pOplock
& REQ_BATCHOPLOCK
)
1346 pSMB
->OpenFlags
= cpu_to_le32(REQ_BATCHOPLOCK
);
1347 pSMB
->DesiredAccess
= cpu_to_le32(access_flags
);
1348 pSMB
->AllocationSize
= 0;
1349 /* set file as system file if special file such
1350 as fifo and server expecting SFU style and
1351 no Unix extensions */
1352 if (create_options
& CREATE_OPTION_SPECIAL
)
1353 pSMB
->FileAttributes
= cpu_to_le32(ATTR_SYSTEM
);
1355 pSMB
->FileAttributes
= cpu_to_le32(ATTR_NORMAL
);
1357 /* XP does not handle ATTR_POSIX_SEMANTICS */
1358 /* but it helps speed up case sensitive checks for other
1359 servers such as Samba */
1360 if (tcon
->ses
->capabilities
& CAP_UNIX
)
1361 pSMB
->FileAttributes
|= cpu_to_le32(ATTR_POSIX_SEMANTICS
);
1363 if (create_options
& CREATE_OPTION_READONLY
)
1364 pSMB
->FileAttributes
|= cpu_to_le32(ATTR_READONLY
);
1366 pSMB
->ShareAccess
= cpu_to_le32(FILE_SHARE_ALL
);
1367 pSMB
->CreateDisposition
= cpu_to_le32(openDisposition
);
1368 pSMB
->CreateOptions
= cpu_to_le32(create_options
& CREATE_OPTIONS_MASK
);
1369 /* BB Expirement with various impersonation levels and verify */
1370 pSMB
->ImpersonationLevel
= cpu_to_le32(SECURITY_IMPERSONATION
);
1371 pSMB
->SecurityFlags
=
1372 SECURITY_CONTEXT_TRACKING
| SECURITY_EFFECTIVE_ONLY
;
1375 inc_rfc1001_len(pSMB
, count
);
1377 pSMB
->ByteCount
= cpu_to_le16(count
);
1378 /* long_op set to 1 to allow for oplock break timeouts */
1379 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
1380 (struct smb_hdr
*)pSMBr
, &bytes_returned
, 0);
1381 cifs_stats_inc(&tcon
->num_opens
);
1383 cFYI(1, "Error in Open = %d", rc
);
1385 *pOplock
= pSMBr
->OplockLevel
; /* 1 byte no need to le_to_cpu */
1386 *netfid
= pSMBr
->Fid
; /* cifs fid stays in le */
1387 /* Let caller know file was created so we can set the mode. */
1388 /* Do we care about the CreateAction in any other cases? */
1389 if (cpu_to_le32(FILE_CREATE
) == pSMBr
->CreateAction
)
1390 *pOplock
|= CIFS_CREATE_ACTION
;
1392 memcpy((char *)pfile_info
, (char *)&pSMBr
->CreationTime
,
1393 36 /* CreationTime to Attributes */);
1394 /* the file_info buf is endian converted by caller */
1395 pfile_info
->AllocationSize
= pSMBr
->AllocationSize
;
1396 pfile_info
->EndOfFile
= pSMBr
->EndOfFile
;
1397 pfile_info
->NumberOfLinks
= cpu_to_le32(1);
1398 pfile_info
->DeletePending
= 0;
1402 cifs_buf_release(pSMB
);
1409 * Discard any remaining data in the current SMB. To do this, we borrow the
1413 cifs_readv_discard(struct TCP_Server_Info
*server
, struct mid_q_entry
*mid
)
1415 unsigned int rfclen
= get_rfc1002_length(server
->smallbuf
);
1416 int remaining
= rfclen
+ 4 - server
->total_read
;
1417 struct cifs_readdata
*rdata
= mid
->callback_data
;
1419 while (remaining
> 0) {
1422 length
= cifs_read_from_socket(server
, server
->bigbuf
,
1423 min_t(unsigned int, remaining
,
1424 CIFSMaxBufSize
+ MAX_HEADER_SIZE(server
)));
1427 server
->total_read
+= length
;
1428 remaining
-= length
;
1431 dequeue_mid(mid
, rdata
->result
);
1436 cifs_readv_receive(struct TCP_Server_Info
*server
, struct mid_q_entry
*mid
)
1439 unsigned int data_offset
, data_len
;
1440 struct cifs_readdata
*rdata
= mid
->callback_data
;
1441 char *buf
= server
->smallbuf
;
1442 unsigned int buflen
= get_rfc1002_length(buf
) + 4;
1444 cFYI(1, "%s: mid=%llu offset=%llu bytes=%u", __func__
,
1445 mid
->mid
, rdata
->offset
, rdata
->bytes
);
1448 * read the rest of READ_RSP header (sans Data array), or whatever we
1449 * can if there's not enough data. At this point, we've read down to
1452 len
= min_t(unsigned int, buflen
, server
->vals
->read_rsp_size
) -
1453 HEADER_SIZE(server
) + 1;
1455 rdata
->iov
[0].iov_base
= buf
+ HEADER_SIZE(server
) - 1;
1456 rdata
->iov
[0].iov_len
= len
;
1458 length
= cifs_readv_from_socket(server
, rdata
->iov
, 1, len
);
1461 server
->total_read
+= length
;
1463 /* Was the SMB read successful? */
1464 rdata
->result
= server
->ops
->map_error(buf
, false);
1465 if (rdata
->result
!= 0) {
1466 cFYI(1, "%s: server returned error %d", __func__
,
1468 return cifs_readv_discard(server
, mid
);
1471 /* Is there enough to get to the rest of the READ_RSP header? */
1472 if (server
->total_read
< server
->vals
->read_rsp_size
) {
1473 cFYI(1, "%s: server returned short header. got=%u expected=%zu",
1474 __func__
, server
->total_read
,
1475 server
->vals
->read_rsp_size
);
1476 rdata
->result
= -EIO
;
1477 return cifs_readv_discard(server
, mid
);
1480 data_offset
= server
->ops
->read_data_offset(buf
) + 4;
1481 if (data_offset
< server
->total_read
) {
1483 * win2k8 sometimes sends an offset of 0 when the read
1484 * is beyond the EOF. Treat it as if the data starts just after
1487 cFYI(1, "%s: data offset (%u) inside read response header",
1488 __func__
, data_offset
);
1489 data_offset
= server
->total_read
;
1490 } else if (data_offset
> MAX_CIFS_SMALL_BUFFER_SIZE
) {
1491 /* data_offset is beyond the end of smallbuf */
1492 cFYI(1, "%s: data offset (%u) beyond end of smallbuf",
1493 __func__
, data_offset
);
1494 rdata
->result
= -EIO
;
1495 return cifs_readv_discard(server
, mid
);
1498 cFYI(1, "%s: total_read=%u data_offset=%u", __func__
,
1499 server
->total_read
, data_offset
);
1501 len
= data_offset
- server
->total_read
;
1503 /* read any junk before data into the rest of smallbuf */
1504 rdata
->iov
[0].iov_base
= buf
+ server
->total_read
;
1505 rdata
->iov
[0].iov_len
= len
;
1506 length
= cifs_readv_from_socket(server
, rdata
->iov
, 1, len
);
1509 server
->total_read
+= length
;
1512 /* set up first iov for signature check */
1513 rdata
->iov
[0].iov_base
= buf
;
1514 rdata
->iov
[0].iov_len
= server
->total_read
;
1515 cFYI(1, "0: iov_base=%p iov_len=%zu",
1516 rdata
->iov
[0].iov_base
, rdata
->iov
[0].iov_len
);
1518 /* how much data is in the response? */
1519 data_len
= server
->ops
->read_data_length(buf
);
1520 if (data_offset
+ data_len
> buflen
) {
1521 /* data_len is corrupt -- discard frame */
1522 rdata
->result
= -EIO
;
1523 return cifs_readv_discard(server
, mid
);
1526 /* marshal up the page array */
1528 len
= rdata
->marshal_iov(rdata
, data_len
);
1532 /* issue the read if we have any iovecs left to fill */
1533 if (rdata
->nr_iov
> 1) {
1534 length
= cifs_readv_from_socket(server
, &rdata
->iov
[1],
1535 rdata
->nr_iov
- 1, len
);
1538 server
->total_read
+= length
;
1543 rdata
->bytes
= length
;
1545 cFYI(1, "total_read=%u buflen=%u remaining=%u", server
->total_read
,
1548 /* discard anything left over */
1549 if (server
->total_read
< buflen
)
1550 return cifs_readv_discard(server
, mid
);
1552 dequeue_mid(mid
, false);
1557 cifs_readv_callback(struct mid_q_entry
*mid
)
1559 struct cifs_readdata
*rdata
= mid
->callback_data
;
1560 struct cifs_tcon
*tcon
= tlink_tcon(rdata
->cfile
->tlink
);
1561 struct TCP_Server_Info
*server
= tcon
->ses
->server
;
1563 cFYI(1, "%s: mid=%llu state=%d result=%d bytes=%u", __func__
,
1564 mid
->mid
, mid
->mid_state
, rdata
->result
, rdata
->bytes
);
1566 switch (mid
->mid_state
) {
1567 case MID_RESPONSE_RECEIVED
:
1568 /* result already set, check signature */
1569 if (server
->sec_mode
&
1570 (SECMODE_SIGN_REQUIRED
| SECMODE_SIGN_ENABLED
)) {
1571 if (cifs_verify_signature(rdata
->iov
, rdata
->nr_iov
,
1572 server
, mid
->sequence_number
+ 1))
1573 cERROR(1, "Unexpected SMB signature");
1575 /* FIXME: should this be counted toward the initiating task? */
1576 task_io_account_read(rdata
->bytes
);
1577 cifs_stats_bytes_read(tcon
, rdata
->bytes
);
1579 case MID_REQUEST_SUBMITTED
:
1580 case MID_RETRY_NEEDED
:
1581 rdata
->result
= -EAGAIN
;
1584 rdata
->result
= -EIO
;
1587 queue_work(cifsiod_wq
, &rdata
->work
);
1588 DeleteMidQEntry(mid
);
1589 add_credits(server
, 1, 0);
1592 /* cifs_async_readv - send an async write, and set up mid to handle result */
1594 cifs_async_readv(struct cifs_readdata
*rdata
)
1597 READ_REQ
*smb
= NULL
;
1599 struct cifs_tcon
*tcon
= tlink_tcon(rdata
->cfile
->tlink
);
1601 cFYI(1, "%s: offset=%llu bytes=%u", __func__
,
1602 rdata
->offset
, rdata
->bytes
);
1604 if (tcon
->ses
->capabilities
& CAP_LARGE_FILES
)
1607 wct
= 10; /* old style read */
1608 if ((rdata
->offset
>> 32) > 0) {
1609 /* can not handle this big offset for old */
1614 rc
= small_smb_init(SMB_COM_READ_ANDX
, wct
, tcon
, (void **)&smb
);
1618 smb
->hdr
.Pid
= cpu_to_le16((__u16
)rdata
->pid
);
1619 smb
->hdr
.PidHigh
= cpu_to_le16((__u16
)(rdata
->pid
>> 16));
1621 smb
->AndXCommand
= 0xFF; /* none */
1622 smb
->Fid
= rdata
->cfile
->netfid
;
1623 smb
->OffsetLow
= cpu_to_le32(rdata
->offset
& 0xFFFFFFFF);
1625 smb
->OffsetHigh
= cpu_to_le32(rdata
->offset
>> 32);
1627 smb
->MaxCount
= cpu_to_le16(rdata
->bytes
& 0xFFFF);
1628 smb
->MaxCountHigh
= cpu_to_le32(rdata
->bytes
>> 16);
1632 /* old style read */
1633 struct smb_com_readx_req
*smbr
=
1634 (struct smb_com_readx_req
*)smb
;
1635 smbr
->ByteCount
= 0;
1638 /* 4 for RFC1001 length + 1 for BCC */
1639 rdata
->iov
[0].iov_base
= smb
;
1640 rdata
->iov
[0].iov_len
= be32_to_cpu(smb
->hdr
.smb_buf_length
) + 4;
1642 kref_get(&rdata
->refcount
);
1643 rc
= cifs_call_async(tcon
->ses
->server
, rdata
->iov
, 1,
1644 cifs_readv_receive
, cifs_readv_callback
,
1648 cifs_stats_inc(&tcon
->num_reads
);
1650 kref_put(&rdata
->refcount
, cifs_readdata_release
);
1652 cifs_small_buf_release(smb
);
1657 CIFSSMBRead(const unsigned int xid
, struct cifs_io_parms
*io_parms
,
1658 unsigned int *nbytes
, char **buf
, int *pbuf_type
)
1661 READ_REQ
*pSMB
= NULL
;
1662 READ_RSP
*pSMBr
= NULL
;
1663 char *pReadData
= NULL
;
1665 int resp_buf_type
= 0;
1667 __u32 pid
= io_parms
->pid
;
1668 __u16 netfid
= io_parms
->netfid
;
1669 __u64 offset
= io_parms
->offset
;
1670 struct cifs_tcon
*tcon
= io_parms
->tcon
;
1671 unsigned int count
= io_parms
->length
;
1673 cFYI(1, "Reading %d bytes on fid %d", count
, netfid
);
1674 if (tcon
->ses
->capabilities
& CAP_LARGE_FILES
)
1677 wct
= 10; /* old style read */
1678 if ((offset
>> 32) > 0) {
1679 /* can not handle this big offset for old */
1685 rc
= small_smb_init(SMB_COM_READ_ANDX
, wct
, tcon
, (void **) &pSMB
);
1689 pSMB
->hdr
.Pid
= cpu_to_le16((__u16
)pid
);
1690 pSMB
->hdr
.PidHigh
= cpu_to_le16((__u16
)(pid
>> 16));
1692 /* tcon and ses pointer are checked in smb_init */
1693 if (tcon
->ses
->server
== NULL
)
1694 return -ECONNABORTED
;
1696 pSMB
->AndXCommand
= 0xFF; /* none */
1698 pSMB
->OffsetLow
= cpu_to_le32(offset
& 0xFFFFFFFF);
1700 pSMB
->OffsetHigh
= cpu_to_le32(offset
>> 32);
1702 pSMB
->Remaining
= 0;
1703 pSMB
->MaxCount
= cpu_to_le16(count
& 0xFFFF);
1704 pSMB
->MaxCountHigh
= cpu_to_le32(count
>> 16);
1706 pSMB
->ByteCount
= 0; /* no need to do le conversion since 0 */
1708 /* old style read */
1709 struct smb_com_readx_req
*pSMBW
=
1710 (struct smb_com_readx_req
*)pSMB
;
1711 pSMBW
->ByteCount
= 0;
1714 iov
[0].iov_base
= (char *)pSMB
;
1715 iov
[0].iov_len
= be32_to_cpu(pSMB
->hdr
.smb_buf_length
) + 4;
1716 rc
= SendReceive2(xid
, tcon
->ses
, iov
, 1 /* num iovecs */,
1717 &resp_buf_type
, CIFS_LOG_ERROR
);
1718 cifs_stats_inc(&tcon
->num_reads
);
1719 pSMBr
= (READ_RSP
*)iov
[0].iov_base
;
1721 cERROR(1, "Send error in read = %d", rc
);
1723 int data_length
= le16_to_cpu(pSMBr
->DataLengthHigh
);
1724 data_length
= data_length
<< 16;
1725 data_length
+= le16_to_cpu(pSMBr
->DataLength
);
1726 *nbytes
= data_length
;
1728 /*check that DataLength would not go beyond end of SMB */
1729 if ((data_length
> CIFSMaxBufSize
)
1730 || (data_length
> count
)) {
1731 cFYI(1, "bad length %d for count %d",
1732 data_length
, count
);
1736 pReadData
= (char *) (&pSMBr
->hdr
.Protocol
) +
1737 le16_to_cpu(pSMBr
->DataOffset
);
1738 /* if (rc = copy_to_user(buf, pReadData, data_length)) {
1739 cERROR(1, "Faulting on read rc = %d",rc);
1741 }*/ /* can not use copy_to_user when using page cache*/
1743 memcpy(*buf
, pReadData
, data_length
);
1747 /* cifs_small_buf_release(pSMB); */ /* Freed earlier now in SendReceive2 */
1749 if (resp_buf_type
== CIFS_SMALL_BUFFER
)
1750 cifs_small_buf_release(iov
[0].iov_base
);
1751 else if (resp_buf_type
== CIFS_LARGE_BUFFER
)
1752 cifs_buf_release(iov
[0].iov_base
);
1753 } else if (resp_buf_type
!= CIFS_NO_BUFFER
) {
1754 /* return buffer to caller to free */
1755 *buf
= iov
[0].iov_base
;
1756 if (resp_buf_type
== CIFS_SMALL_BUFFER
)
1757 *pbuf_type
= CIFS_SMALL_BUFFER
;
1758 else if (resp_buf_type
== CIFS_LARGE_BUFFER
)
1759 *pbuf_type
= CIFS_LARGE_BUFFER
;
1760 } /* else no valid buffer on return - leave as null */
1762 /* Note: On -EAGAIN error only caller can retry on handle based calls
1763 since file handle passed in no longer valid */
1769 CIFSSMBWrite(const unsigned int xid
, struct cifs_io_parms
*io_parms
,
1770 unsigned int *nbytes
, const char *buf
,
1771 const char __user
*ubuf
, const int long_op
)
1774 WRITE_REQ
*pSMB
= NULL
;
1775 WRITE_RSP
*pSMBr
= NULL
;
1776 int bytes_returned
, wct
;
1779 __u32 pid
= io_parms
->pid
;
1780 __u16 netfid
= io_parms
->netfid
;
1781 __u64 offset
= io_parms
->offset
;
1782 struct cifs_tcon
*tcon
= io_parms
->tcon
;
1783 unsigned int count
= io_parms
->length
;
1787 /* cFYI(1, "write at %lld %d bytes", offset, count);*/
1788 if (tcon
->ses
== NULL
)
1789 return -ECONNABORTED
;
1791 if (tcon
->ses
->capabilities
& CAP_LARGE_FILES
)
1795 if ((offset
>> 32) > 0) {
1796 /* can not handle big offset for old srv */
1801 rc
= smb_init(SMB_COM_WRITE_ANDX
, wct
, tcon
, (void **) &pSMB
,
1806 pSMB
->hdr
.Pid
= cpu_to_le16((__u16
)pid
);
1807 pSMB
->hdr
.PidHigh
= cpu_to_le16((__u16
)(pid
>> 16));
1809 /* tcon and ses pointer are checked in smb_init */
1810 if (tcon
->ses
->server
== NULL
)
1811 return -ECONNABORTED
;
1813 pSMB
->AndXCommand
= 0xFF; /* none */
1815 pSMB
->OffsetLow
= cpu_to_le32(offset
& 0xFFFFFFFF);
1817 pSMB
->OffsetHigh
= cpu_to_le32(offset
>> 32);
1819 pSMB
->Reserved
= 0xFFFFFFFF;
1820 pSMB
->WriteMode
= 0;
1821 pSMB
->Remaining
= 0;
1823 /* Can increase buffer size if buffer is big enough in some cases ie we
1824 can send more if LARGE_WRITE_X capability returned by the server and if
1825 our buffer is big enough or if we convert to iovecs on socket writes
1826 and eliminate the copy to the CIFS buffer */
1827 if (tcon
->ses
->capabilities
& CAP_LARGE_WRITE_X
) {
1828 bytes_sent
= min_t(const unsigned int, CIFSMaxBufSize
, count
);
1830 bytes_sent
= (tcon
->ses
->server
->maxBuf
- MAX_CIFS_HDR_SIZE
)
1834 if (bytes_sent
> count
)
1837 cpu_to_le16(offsetof(struct smb_com_write_req
, Data
) - 4);
1839 memcpy(pSMB
->Data
, buf
, bytes_sent
);
1841 if (copy_from_user(pSMB
->Data
, ubuf
, bytes_sent
)) {
1842 cifs_buf_release(pSMB
);
1845 } else if (count
!= 0) {
1847 cifs_buf_release(pSMB
);
1849 } /* else setting file size with write of zero bytes */
1851 byte_count
= bytes_sent
+ 1; /* pad */
1852 else /* wct == 12 */
1853 byte_count
= bytes_sent
+ 5; /* bigger pad, smaller smb hdr */
1855 pSMB
->DataLengthLow
= cpu_to_le16(bytes_sent
& 0xFFFF);
1856 pSMB
->DataLengthHigh
= cpu_to_le16(bytes_sent
>> 16);
1857 inc_rfc1001_len(pSMB
, byte_count
);
1860 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
1861 else { /* old style write has byte count 4 bytes earlier
1863 struct smb_com_writex_req
*pSMBW
=
1864 (struct smb_com_writex_req
*)pSMB
;
1865 pSMBW
->ByteCount
= cpu_to_le16(byte_count
);
1868 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
1869 (struct smb_hdr
*) pSMBr
, &bytes_returned
, long_op
);
1870 cifs_stats_inc(&tcon
->num_writes
);
1872 cFYI(1, "Send error in write = %d", rc
);
1874 *nbytes
= le16_to_cpu(pSMBr
->CountHigh
);
1875 *nbytes
= (*nbytes
) << 16;
1876 *nbytes
+= le16_to_cpu(pSMBr
->Count
);
1879 * Mask off high 16 bits when bytes written as returned by the
1880 * server is greater than bytes requested by the client. Some
1881 * OS/2 servers are known to set incorrect CountHigh values.
1883 if (*nbytes
> count
)
1887 cifs_buf_release(pSMB
);
1889 /* Note: On -EAGAIN error only caller can retry on handle based calls
1890 since file handle passed in no longer valid */
1896 cifs_writedata_release(struct kref
*refcount
)
1898 struct cifs_writedata
*wdata
= container_of(refcount
,
1899 struct cifs_writedata
, refcount
);
1902 cifsFileInfo_put(wdata
->cfile
);
1908 * Write failed with a retryable error. Resend the write request. It's also
1909 * possible that the page was redirtied so re-clean the page.
1912 cifs_writev_requeue(struct cifs_writedata
*wdata
)
1915 struct inode
*inode
= wdata
->cfile
->dentry
->d_inode
;
1917 for (i
= 0; i
< wdata
->nr_pages
; i
++) {
1918 lock_page(wdata
->pages
[i
]);
1919 clear_page_dirty_for_io(wdata
->pages
[i
]);
1923 rc
= cifs_async_writev(wdata
);
1924 } while (rc
== -EAGAIN
);
1926 for (i
= 0; i
< wdata
->nr_pages
; i
++) {
1928 SetPageError(wdata
->pages
[i
]);
1929 unlock_page(wdata
->pages
[i
]);
1932 mapping_set_error(inode
->i_mapping
, rc
);
1933 kref_put(&wdata
->refcount
, cifs_writedata_release
);
1937 cifs_writev_complete(struct work_struct
*work
)
1939 struct cifs_writedata
*wdata
= container_of(work
,
1940 struct cifs_writedata
, work
);
1941 struct inode
*inode
= wdata
->cfile
->dentry
->d_inode
;
1944 if (wdata
->result
== 0) {
1945 spin_lock(&inode
->i_lock
);
1946 cifs_update_eof(CIFS_I(inode
), wdata
->offset
, wdata
->bytes
);
1947 spin_unlock(&inode
->i_lock
);
1948 cifs_stats_bytes_written(tlink_tcon(wdata
->cfile
->tlink
),
1950 } else if (wdata
->sync_mode
== WB_SYNC_ALL
&& wdata
->result
== -EAGAIN
)
1951 return cifs_writev_requeue(wdata
);
1953 for (i
= 0; i
< wdata
->nr_pages
; i
++) {
1954 struct page
*page
= wdata
->pages
[i
];
1955 if (wdata
->result
== -EAGAIN
)
1956 __set_page_dirty_nobuffers(page
);
1957 else if (wdata
->result
< 0)
1959 end_page_writeback(page
);
1960 page_cache_release(page
);
1962 if (wdata
->result
!= -EAGAIN
)
1963 mapping_set_error(inode
->i_mapping
, wdata
->result
);
1964 kref_put(&wdata
->refcount
, cifs_writedata_release
);
1967 struct cifs_writedata
*
1968 cifs_writedata_alloc(unsigned int nr_pages
, work_func_t complete
)
1970 struct cifs_writedata
*wdata
;
1972 /* this would overflow */
1973 if (nr_pages
== 0) {
1974 cERROR(1, "%s: called with nr_pages == 0!", __func__
);
1978 /* writedata + number of page pointers */
1979 wdata
= kzalloc(sizeof(*wdata
) +
1980 sizeof(struct page
*) * (nr_pages
- 1), GFP_NOFS
);
1981 if (wdata
!= NULL
) {
1982 kref_init(&wdata
->refcount
);
1983 INIT_LIST_HEAD(&wdata
->list
);
1984 init_completion(&wdata
->done
);
1985 INIT_WORK(&wdata
->work
, complete
);
1991 * Check the mid_state and signature on received buffer (if any), and queue the
1992 * workqueue completion task.
1995 cifs_writev_callback(struct mid_q_entry
*mid
)
1997 struct cifs_writedata
*wdata
= mid
->callback_data
;
1998 struct cifs_tcon
*tcon
= tlink_tcon(wdata
->cfile
->tlink
);
1999 unsigned int written
;
2000 WRITE_RSP
*smb
= (WRITE_RSP
*)mid
->resp_buf
;
2002 switch (mid
->mid_state
) {
2003 case MID_RESPONSE_RECEIVED
:
2004 wdata
->result
= cifs_check_receive(mid
, tcon
->ses
->server
, 0);
2005 if (wdata
->result
!= 0)
2008 written
= le16_to_cpu(smb
->CountHigh
);
2010 written
+= le16_to_cpu(smb
->Count
);
2012 * Mask off high 16 bits when bytes written as returned
2013 * by the server is greater than bytes requested by the
2014 * client. OS/2 servers are known to set incorrect
2017 if (written
> wdata
->bytes
)
2020 if (written
< wdata
->bytes
)
2021 wdata
->result
= -ENOSPC
;
2023 wdata
->bytes
= written
;
2025 case MID_REQUEST_SUBMITTED
:
2026 case MID_RETRY_NEEDED
:
2027 wdata
->result
= -EAGAIN
;
2030 wdata
->result
= -EIO
;
2034 queue_work(cifsiod_wq
, &wdata
->work
);
2035 DeleteMidQEntry(mid
);
2036 add_credits(tcon
->ses
->server
, 1, 0);
2039 /* cifs_async_writev - send an async write, and set up mid to handle result */
2041 cifs_async_writev(struct cifs_writedata
*wdata
)
2043 int i
, rc
= -EACCES
;
2044 WRITE_REQ
*smb
= NULL
;
2046 struct cifs_tcon
*tcon
= tlink_tcon(wdata
->cfile
->tlink
);
2047 struct kvec
*iov
= NULL
;
2049 if (tcon
->ses
->capabilities
& CAP_LARGE_FILES
) {
2053 if (wdata
->offset
>> 32 > 0) {
2054 /* can not handle big offset for old srv */
2059 rc
= small_smb_init(SMB_COM_WRITE_ANDX
, wct
, tcon
, (void **)&smb
);
2061 goto async_writev_out
;
2063 /* 1 iov per page + 1 for header */
2064 iov
= kzalloc((wdata
->nr_pages
+ 1) * sizeof(*iov
), GFP_NOFS
);
2067 goto async_writev_out
;
2070 smb
->hdr
.Pid
= cpu_to_le16((__u16
)wdata
->pid
);
2071 smb
->hdr
.PidHigh
= cpu_to_le16((__u16
)(wdata
->pid
>> 16));
2073 smb
->AndXCommand
= 0xFF; /* none */
2074 smb
->Fid
= wdata
->cfile
->netfid
;
2075 smb
->OffsetLow
= cpu_to_le32(wdata
->offset
& 0xFFFFFFFF);
2077 smb
->OffsetHigh
= cpu_to_le32(wdata
->offset
>> 32);
2078 smb
->Reserved
= 0xFFFFFFFF;
2083 cpu_to_le16(offsetof(struct smb_com_write_req
, Data
) - 4);
2085 /* 4 for RFC1001 length + 1 for BCC */
2086 iov
[0].iov_len
= be32_to_cpu(smb
->hdr
.smb_buf_length
) + 4 + 1;
2087 iov
[0].iov_base
= smb
;
2090 * This function should marshal up the page array into the kvec
2091 * array, reserving [0] for the header. It should kmap the pages
2092 * and set the iov_len properly for each one. It may also set
2096 wdata
->marshal_iov(iov
, wdata
);
2099 cFYI(1, "async write at %llu %u bytes", wdata
->offset
, wdata
->bytes
);
2101 smb
->DataLengthLow
= cpu_to_le16(wdata
->bytes
& 0xFFFF);
2102 smb
->DataLengthHigh
= cpu_to_le16(wdata
->bytes
>> 16);
2105 inc_rfc1001_len(&smb
->hdr
, wdata
->bytes
+ 1);
2106 put_bcc(wdata
->bytes
+ 1, &smb
->hdr
);
2109 struct smb_com_writex_req
*smbw
=
2110 (struct smb_com_writex_req
*)smb
;
2111 inc_rfc1001_len(&smbw
->hdr
, wdata
->bytes
+ 5);
2112 put_bcc(wdata
->bytes
+ 5, &smbw
->hdr
);
2113 iov
[0].iov_len
+= 4; /* pad bigger by four bytes */
2116 kref_get(&wdata
->refcount
);
2117 rc
= cifs_call_async(tcon
->ses
->server
, iov
, wdata
->nr_pages
+ 1,
2118 NULL
, cifs_writev_callback
, wdata
, 0);
2121 cifs_stats_inc(&tcon
->num_writes
);
2123 kref_put(&wdata
->refcount
, cifs_writedata_release
);
2125 /* send is done, unmap pages */
2126 for (i
= 0; i
< wdata
->nr_pages
; i
++)
2127 kunmap(wdata
->pages
[i
]);
2130 cifs_small_buf_release(smb
);
2136 CIFSSMBWrite2(const unsigned int xid
, struct cifs_io_parms
*io_parms
,
2137 unsigned int *nbytes
, struct kvec
*iov
, int n_vec
,
2141 WRITE_REQ
*pSMB
= NULL
;
2144 int resp_buf_type
= 0;
2145 __u32 pid
= io_parms
->pid
;
2146 __u16 netfid
= io_parms
->netfid
;
2147 __u64 offset
= io_parms
->offset
;
2148 struct cifs_tcon
*tcon
= io_parms
->tcon
;
2149 unsigned int count
= io_parms
->length
;
2153 cFYI(1, "write2 at %lld %d bytes", (long long)offset
, count
);
2155 if (tcon
->ses
->capabilities
& CAP_LARGE_FILES
) {
2159 if ((offset
>> 32) > 0) {
2160 /* can not handle big offset for old srv */
2164 rc
= small_smb_init(SMB_COM_WRITE_ANDX
, wct
, tcon
, (void **) &pSMB
);
2168 pSMB
->hdr
.Pid
= cpu_to_le16((__u16
)pid
);
2169 pSMB
->hdr
.PidHigh
= cpu_to_le16((__u16
)(pid
>> 16));
2171 /* tcon and ses pointer are checked in smb_init */
2172 if (tcon
->ses
->server
== NULL
)
2173 return -ECONNABORTED
;
2175 pSMB
->AndXCommand
= 0xFF; /* none */
2177 pSMB
->OffsetLow
= cpu_to_le32(offset
& 0xFFFFFFFF);
2179 pSMB
->OffsetHigh
= cpu_to_le32(offset
>> 32);
2180 pSMB
->Reserved
= 0xFFFFFFFF;
2181 pSMB
->WriteMode
= 0;
2182 pSMB
->Remaining
= 0;
2185 cpu_to_le16(offsetof(struct smb_com_write_req
, Data
) - 4);
2187 pSMB
->DataLengthLow
= cpu_to_le16(count
& 0xFFFF);
2188 pSMB
->DataLengthHigh
= cpu_to_le16(count
>> 16);
2189 /* header + 1 byte pad */
2190 smb_hdr_len
= be32_to_cpu(pSMB
->hdr
.smb_buf_length
) + 1;
2192 inc_rfc1001_len(pSMB
, count
+ 1);
2193 else /* wct == 12 */
2194 inc_rfc1001_len(pSMB
, count
+ 5); /* smb data starts later */
2196 pSMB
->ByteCount
= cpu_to_le16(count
+ 1);
2197 else /* wct == 12 */ /* bigger pad, smaller smb hdr, keep offset ok */ {
2198 struct smb_com_writex_req
*pSMBW
=
2199 (struct smb_com_writex_req
*)pSMB
;
2200 pSMBW
->ByteCount
= cpu_to_le16(count
+ 5);
2202 iov
[0].iov_base
= pSMB
;
2204 iov
[0].iov_len
= smb_hdr_len
+ 4;
2205 else /* wct == 12 pad bigger by four bytes */
2206 iov
[0].iov_len
= smb_hdr_len
+ 8;
2209 rc
= SendReceive2(xid
, tcon
->ses
, iov
, n_vec
+ 1, &resp_buf_type
,
2211 cifs_stats_inc(&tcon
->num_writes
);
2213 cFYI(1, "Send error Write2 = %d", rc
);
2214 } else if (resp_buf_type
== 0) {
2215 /* presumably this can not happen, but best to be safe */
2218 WRITE_RSP
*pSMBr
= (WRITE_RSP
*)iov
[0].iov_base
;
2219 *nbytes
= le16_to_cpu(pSMBr
->CountHigh
);
2220 *nbytes
= (*nbytes
) << 16;
2221 *nbytes
+= le16_to_cpu(pSMBr
->Count
);
2224 * Mask off high 16 bits when bytes written as returned by the
2225 * server is greater than bytes requested by the client. OS/2
2226 * servers are known to set incorrect CountHigh values.
2228 if (*nbytes
> count
)
2232 /* cifs_small_buf_release(pSMB); */ /* Freed earlier now in SendReceive2 */
2233 if (resp_buf_type
== CIFS_SMALL_BUFFER
)
2234 cifs_small_buf_release(iov
[0].iov_base
);
2235 else if (resp_buf_type
== CIFS_LARGE_BUFFER
)
2236 cifs_buf_release(iov
[0].iov_base
);
2238 /* Note: On -EAGAIN error only caller can retry on handle based calls
2239 since file handle passed in no longer valid */
2244 int cifs_lockv(const unsigned int xid
, struct cifs_tcon
*tcon
,
2245 const __u16 netfid
, const __u8 lock_type
, const __u32 num_unlock
,
2246 const __u32 num_lock
, LOCKING_ANDX_RANGE
*buf
)
2249 LOCK_REQ
*pSMB
= NULL
;
2254 cFYI(1, "cifs_lockv num lock %d num unlock %d", num_lock
, num_unlock
);
2256 rc
= small_smb_init(SMB_COM_LOCKING_ANDX
, 8, tcon
, (void **) &pSMB
);
2261 pSMB
->NumberOfLocks
= cpu_to_le16(num_lock
);
2262 pSMB
->NumberOfUnlocks
= cpu_to_le16(num_unlock
);
2263 pSMB
->LockType
= lock_type
;
2264 pSMB
->AndXCommand
= 0xFF; /* none */
2265 pSMB
->Fid
= netfid
; /* netfid stays le */
2267 count
= (num_unlock
+ num_lock
) * sizeof(LOCKING_ANDX_RANGE
);
2268 inc_rfc1001_len(pSMB
, count
);
2269 pSMB
->ByteCount
= cpu_to_le16(count
);
2271 iov
[0].iov_base
= (char *)pSMB
;
2272 iov
[0].iov_len
= be32_to_cpu(pSMB
->hdr
.smb_buf_length
) + 4 -
2273 (num_unlock
+ num_lock
) * sizeof(LOCKING_ANDX_RANGE
);
2274 iov
[1].iov_base
= (char *)buf
;
2275 iov
[1].iov_len
= (num_unlock
+ num_lock
) * sizeof(LOCKING_ANDX_RANGE
);
2277 cifs_stats_inc(&tcon
->num_locks
);
2278 rc
= SendReceive2(xid
, tcon
->ses
, iov
, 2, &resp_buf_type
, CIFS_NO_RESP
);
2280 cFYI(1, "Send error in cifs_lockv = %d", rc
);
2286 CIFSSMBLock(const unsigned int xid
, struct cifs_tcon
*tcon
,
2287 const __u16 smb_file_id
, const __u32 netpid
, const __u64 len
,
2288 const __u64 offset
, const __u32 numUnlock
,
2289 const __u32 numLock
, const __u8 lockType
,
2290 const bool waitFlag
, const __u8 oplock_level
)
2293 LOCK_REQ
*pSMB
= NULL
;
2294 /* LOCK_RSP *pSMBr = NULL; */ /* No response data other than rc to parse */
2299 cFYI(1, "CIFSSMBLock timeout %d numLock %d", (int)waitFlag
, numLock
);
2300 rc
= small_smb_init(SMB_COM_LOCKING_ANDX
, 8, tcon
, (void **) &pSMB
);
2305 if (lockType
== LOCKING_ANDX_OPLOCK_RELEASE
) {
2306 /* no response expected */
2307 flags
= CIFS_ASYNC_OP
| CIFS_OBREAK_OP
;
2309 } else if (waitFlag
) {
2310 flags
= CIFS_BLOCKING_OP
; /* blocking operation, no timeout */
2311 pSMB
->Timeout
= cpu_to_le32(-1);/* blocking - do not time out */
2316 pSMB
->NumberOfLocks
= cpu_to_le16(numLock
);
2317 pSMB
->NumberOfUnlocks
= cpu_to_le16(numUnlock
);
2318 pSMB
->LockType
= lockType
;
2319 pSMB
->OplockLevel
= oplock_level
;
2320 pSMB
->AndXCommand
= 0xFF; /* none */
2321 pSMB
->Fid
= smb_file_id
; /* netfid stays le */
2323 if ((numLock
!= 0) || (numUnlock
!= 0)) {
2324 pSMB
->Locks
[0].Pid
= cpu_to_le16(netpid
);
2325 /* BB where to store pid high? */
2326 pSMB
->Locks
[0].LengthLow
= cpu_to_le32((u32
)len
);
2327 pSMB
->Locks
[0].LengthHigh
= cpu_to_le32((u32
)(len
>>32));
2328 pSMB
->Locks
[0].OffsetLow
= cpu_to_le32((u32
)offset
);
2329 pSMB
->Locks
[0].OffsetHigh
= cpu_to_le32((u32
)(offset
>>32));
2330 count
= sizeof(LOCKING_ANDX_RANGE
);
2335 inc_rfc1001_len(pSMB
, count
);
2336 pSMB
->ByteCount
= cpu_to_le16(count
);
2339 rc
= SendReceiveBlockingLock(xid
, tcon
, (struct smb_hdr
*) pSMB
,
2340 (struct smb_hdr
*) pSMB
, &bytes_returned
);
2341 cifs_small_buf_release(pSMB
);
2343 rc
= SendReceiveNoRsp(xid
, tcon
->ses
, (char *)pSMB
, flags
);
2344 /* SMB buffer freed by function above */
2346 cifs_stats_inc(&tcon
->num_locks
);
2348 cFYI(1, "Send error in Lock = %d", rc
);
2350 /* Note: On -EAGAIN error only caller can retry on handle based calls
2351 since file handle passed in no longer valid */
2356 CIFSSMBPosixLock(const unsigned int xid
, struct cifs_tcon
*tcon
,
2357 const __u16 smb_file_id
, const __u32 netpid
,
2358 const loff_t start_offset
, const __u64 len
,
2359 struct file_lock
*pLockData
, const __u16 lock_type
,
2360 const bool waitFlag
)
2362 struct smb_com_transaction2_sfi_req
*pSMB
= NULL
;
2363 struct smb_com_transaction2_sfi_rsp
*pSMBr
= NULL
;
2364 struct cifs_posix_lock
*parm_data
;
2367 int bytes_returned
= 0;
2368 int resp_buf_type
= 0;
2369 __u16 params
, param_offset
, offset
, byte_count
, count
;
2372 cFYI(1, "Posix Lock");
2374 rc
= small_smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
);
2379 pSMBr
= (struct smb_com_transaction2_sfi_rsp
*)pSMB
;
2382 pSMB
->MaxSetupCount
= 0;
2385 pSMB
->Reserved2
= 0;
2386 param_offset
= offsetof(struct smb_com_transaction2_sfi_req
, Fid
) - 4;
2387 offset
= param_offset
+ params
;
2389 count
= sizeof(struct cifs_posix_lock
);
2390 pSMB
->MaxParameterCount
= cpu_to_le16(2);
2391 pSMB
->MaxDataCount
= cpu_to_le16(1000); /* BB find max SMB from sess */
2392 pSMB
->SetupCount
= 1;
2393 pSMB
->Reserved3
= 0;
2395 pSMB
->SubCommand
= cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION
);
2397 pSMB
->SubCommand
= cpu_to_le16(TRANS2_SET_FILE_INFORMATION
);
2398 byte_count
= 3 /* pad */ + params
+ count
;
2399 pSMB
->DataCount
= cpu_to_le16(count
);
2400 pSMB
->ParameterCount
= cpu_to_le16(params
);
2401 pSMB
->TotalDataCount
= pSMB
->DataCount
;
2402 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
2403 pSMB
->ParameterOffset
= cpu_to_le16(param_offset
);
2404 parm_data
= (struct cifs_posix_lock
*)
2405 (((char *) &pSMB
->hdr
.Protocol
) + offset
);
2407 parm_data
->lock_type
= cpu_to_le16(lock_type
);
2409 timeout
= CIFS_BLOCKING_OP
; /* blocking operation, no timeout */
2410 parm_data
->lock_flags
= cpu_to_le16(1);
2411 pSMB
->Timeout
= cpu_to_le32(-1);
2415 parm_data
->pid
= cpu_to_le32(netpid
);
2416 parm_data
->start
= cpu_to_le64(start_offset
);
2417 parm_data
->length
= cpu_to_le64(len
); /* normalize negative numbers */
2419 pSMB
->DataOffset
= cpu_to_le16(offset
);
2420 pSMB
->Fid
= smb_file_id
;
2421 pSMB
->InformationLevel
= cpu_to_le16(SMB_SET_POSIX_LOCK
);
2422 pSMB
->Reserved4
= 0;
2423 inc_rfc1001_len(pSMB
, byte_count
);
2424 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
2426 rc
= SendReceiveBlockingLock(xid
, tcon
, (struct smb_hdr
*) pSMB
,
2427 (struct smb_hdr
*) pSMBr
, &bytes_returned
);
2429 iov
[0].iov_base
= (char *)pSMB
;
2430 iov
[0].iov_len
= be32_to_cpu(pSMB
->hdr
.smb_buf_length
) + 4;
2431 rc
= SendReceive2(xid
, tcon
->ses
, iov
, 1 /* num iovecs */,
2432 &resp_buf_type
, timeout
);
2433 pSMB
= NULL
; /* request buf already freed by SendReceive2. Do
2434 not try to free it twice below on exit */
2435 pSMBr
= (struct smb_com_transaction2_sfi_rsp
*)iov
[0].iov_base
;
2439 cFYI(1, "Send error in Posix Lock = %d", rc
);
2440 } else if (pLockData
) {
2441 /* lock structure can be returned on get */
2444 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
2446 if (rc
|| get_bcc(&pSMBr
->hdr
) < sizeof(*parm_data
)) {
2447 rc
= -EIO
; /* bad smb */
2450 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
2451 data_count
= le16_to_cpu(pSMBr
->t2
.DataCount
);
2452 if (data_count
< sizeof(struct cifs_posix_lock
)) {
2456 parm_data
= (struct cifs_posix_lock
*)
2457 ((char *)&pSMBr
->hdr
.Protocol
+ data_offset
);
2458 if (parm_data
->lock_type
== __constant_cpu_to_le16(CIFS_UNLCK
))
2459 pLockData
->fl_type
= F_UNLCK
;
2461 if (parm_data
->lock_type
==
2462 __constant_cpu_to_le16(CIFS_RDLCK
))
2463 pLockData
->fl_type
= F_RDLCK
;
2464 else if (parm_data
->lock_type
==
2465 __constant_cpu_to_le16(CIFS_WRLCK
))
2466 pLockData
->fl_type
= F_WRLCK
;
2468 pLockData
->fl_start
= le64_to_cpu(parm_data
->start
);
2469 pLockData
->fl_end
= pLockData
->fl_start
+
2470 le64_to_cpu(parm_data
->length
) - 1;
2471 pLockData
->fl_pid
= le32_to_cpu(parm_data
->pid
);
2477 cifs_small_buf_release(pSMB
);
2479 if (resp_buf_type
== CIFS_SMALL_BUFFER
)
2480 cifs_small_buf_release(iov
[0].iov_base
);
2481 else if (resp_buf_type
== CIFS_LARGE_BUFFER
)
2482 cifs_buf_release(iov
[0].iov_base
);
2484 /* Note: On -EAGAIN error only caller can retry on handle based calls
2485 since file handle passed in no longer valid */
2492 CIFSSMBClose(const unsigned int xid
, struct cifs_tcon
*tcon
, int smb_file_id
)
2495 CLOSE_REQ
*pSMB
= NULL
;
2496 cFYI(1, "In CIFSSMBClose");
2498 /* do not retry on dead session on close */
2499 rc
= small_smb_init(SMB_COM_CLOSE
, 3, tcon
, (void **) &pSMB
);
2505 pSMB
->FileID
= (__u16
) smb_file_id
;
2506 pSMB
->LastWriteTime
= 0xFFFFFFFF;
2507 pSMB
->ByteCount
= 0;
2508 rc
= SendReceiveNoRsp(xid
, tcon
->ses
, (char *) pSMB
, 0);
2509 cifs_stats_inc(&tcon
->num_closes
);
2512 /* EINTR is expected when user ctl-c to kill app */
2513 cERROR(1, "Send error in Close = %d", rc
);
2517 /* Since session is dead, file will be closed on server already */
2525 CIFSSMBFlush(const unsigned int xid
, struct cifs_tcon
*tcon
, int smb_file_id
)
2528 FLUSH_REQ
*pSMB
= NULL
;
2529 cFYI(1, "In CIFSSMBFlush");
2531 rc
= small_smb_init(SMB_COM_FLUSH
, 1, tcon
, (void **) &pSMB
);
2535 pSMB
->FileID
= (__u16
) smb_file_id
;
2536 pSMB
->ByteCount
= 0;
2537 rc
= SendReceiveNoRsp(xid
, tcon
->ses
, (char *) pSMB
, 0);
2538 cifs_stats_inc(&tcon
->num_flushes
);
2540 cERROR(1, "Send error in Flush = %d", rc
);
2546 CIFSSMBRename(const unsigned int xid
, struct cifs_tcon
*tcon
,
2547 const char *fromName
, const char *toName
,
2548 const struct nls_table
*nls_codepage
, int remap
)
2551 RENAME_REQ
*pSMB
= NULL
;
2552 RENAME_RSP
*pSMBr
= NULL
;
2554 int name_len
, name_len2
;
2557 cFYI(1, "In CIFSSMBRename");
2559 rc
= smb_init(SMB_COM_RENAME
, 1, tcon
, (void **) &pSMB
,
2564 pSMB
->BufferFormat
= 0x04;
2565 pSMB
->SearchAttributes
=
2566 cpu_to_le16(ATTR_READONLY
| ATTR_HIDDEN
| ATTR_SYSTEM
|
2569 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
2571 cifsConvertToUTF16((__le16
*) pSMB
->OldFileName
, fromName
,
2572 PATH_MAX
, nls_codepage
, remap
);
2573 name_len
++; /* trailing null */
2575 pSMB
->OldFileName
[name_len
] = 0x04; /* pad */
2576 /* protocol requires ASCII signature byte on Unicode string */
2577 pSMB
->OldFileName
[name_len
+ 1] = 0x00;
2579 cifsConvertToUTF16((__le16
*)&pSMB
->OldFileName
[name_len
+2],
2580 toName
, PATH_MAX
, nls_codepage
, remap
);
2581 name_len2
+= 1 /* trailing null */ + 1 /* Signature word */ ;
2582 name_len2
*= 2; /* convert to bytes */
2583 } else { /* BB improve the check for buffer overruns BB */
2584 name_len
= strnlen(fromName
, PATH_MAX
);
2585 name_len
++; /* trailing null */
2586 strncpy(pSMB
->OldFileName
, fromName
, name_len
);
2587 name_len2
= strnlen(toName
, PATH_MAX
);
2588 name_len2
++; /* trailing null */
2589 pSMB
->OldFileName
[name_len
] = 0x04; /* 2nd buffer format */
2590 strncpy(&pSMB
->OldFileName
[name_len
+ 1], toName
, name_len2
);
2591 name_len2
++; /* trailing null */
2592 name_len2
++; /* signature byte */
2595 count
= 1 /* 1st signature byte */ + name_len
+ name_len2
;
2596 inc_rfc1001_len(pSMB
, count
);
2597 pSMB
->ByteCount
= cpu_to_le16(count
);
2599 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
2600 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
2601 cifs_stats_inc(&tcon
->num_renames
);
2603 cFYI(1, "Send error in rename = %d", rc
);
2605 cifs_buf_release(pSMB
);
2613 int CIFSSMBRenameOpenFile(const unsigned int xid
, struct cifs_tcon
*pTcon
,
2614 int netfid
, const char *target_name
,
2615 const struct nls_table
*nls_codepage
, int remap
)
2617 struct smb_com_transaction2_sfi_req
*pSMB
= NULL
;
2618 struct smb_com_transaction2_sfi_rsp
*pSMBr
= NULL
;
2619 struct set_file_rename
*rename_info
;
2621 char dummy_string
[30];
2623 int bytes_returned
= 0;
2625 __u16 params
, param_offset
, offset
, count
, byte_count
;
2627 cFYI(1, "Rename to File by handle");
2628 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, pTcon
, (void **) &pSMB
,
2634 pSMB
->MaxSetupCount
= 0;
2638 pSMB
->Reserved2
= 0;
2639 param_offset
= offsetof(struct smb_com_transaction2_sfi_req
, Fid
) - 4;
2640 offset
= param_offset
+ params
;
2642 data_offset
= (char *) (&pSMB
->hdr
.Protocol
) + offset
;
2643 rename_info
= (struct set_file_rename
*) data_offset
;
2644 pSMB
->MaxParameterCount
= cpu_to_le16(2);
2645 pSMB
->MaxDataCount
= cpu_to_le16(1000); /* BB find max SMB from sess */
2646 pSMB
->SetupCount
= 1;
2647 pSMB
->Reserved3
= 0;
2648 pSMB
->SubCommand
= cpu_to_le16(TRANS2_SET_FILE_INFORMATION
);
2649 byte_count
= 3 /* pad */ + params
;
2650 pSMB
->ParameterCount
= cpu_to_le16(params
);
2651 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
2652 pSMB
->ParameterOffset
= cpu_to_le16(param_offset
);
2653 pSMB
->DataOffset
= cpu_to_le16(offset
);
2654 /* construct random name ".cifs_tmp<inodenum><mid>" */
2655 rename_info
->overwrite
= cpu_to_le32(1);
2656 rename_info
->root_fid
= 0;
2657 /* unicode only call */
2658 if (target_name
== NULL
) {
2659 sprintf(dummy_string
, "cifs%x", pSMB
->hdr
.Mid
);
2661 cifsConvertToUTF16((__le16
*)rename_info
->target_name
,
2662 dummy_string
, 24, nls_codepage
, remap
);
2665 cifsConvertToUTF16((__le16
*)rename_info
->target_name
,
2666 target_name
, PATH_MAX
, nls_codepage
,
2669 rename_info
->target_name_len
= cpu_to_le32(2 * len_of_str
);
2670 count
= 12 /* sizeof(struct set_file_rename) */ + (2 * len_of_str
);
2671 byte_count
+= count
;
2672 pSMB
->DataCount
= cpu_to_le16(count
);
2673 pSMB
->TotalDataCount
= pSMB
->DataCount
;
2675 pSMB
->InformationLevel
=
2676 cpu_to_le16(SMB_SET_FILE_RENAME_INFORMATION
);
2677 pSMB
->Reserved4
= 0;
2678 inc_rfc1001_len(pSMB
, byte_count
);
2679 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
2680 rc
= SendReceive(xid
, pTcon
->ses
, (struct smb_hdr
*) pSMB
,
2681 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
2682 cifs_stats_inc(&pTcon
->num_t2renames
);
2684 cFYI(1, "Send error in Rename (by file handle) = %d", rc
);
2686 cifs_buf_release(pSMB
);
2688 /* Note: On -EAGAIN error only caller can retry on handle based calls
2689 since file handle passed in no longer valid */
2695 CIFSSMBCopy(const unsigned int xid
, struct cifs_tcon
*tcon
,
2696 const char *fromName
, const __u16 target_tid
, const char *toName
,
2697 const int flags
, const struct nls_table
*nls_codepage
, int remap
)
2700 COPY_REQ
*pSMB
= NULL
;
2701 COPY_RSP
*pSMBr
= NULL
;
2703 int name_len
, name_len2
;
2706 cFYI(1, "In CIFSSMBCopy");
2708 rc
= smb_init(SMB_COM_COPY
, 1, tcon
, (void **) &pSMB
,
2713 pSMB
->BufferFormat
= 0x04;
2714 pSMB
->Tid2
= target_tid
;
2716 pSMB
->Flags
= cpu_to_le16(flags
& COPY_TREE
);
2718 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
2719 name_len
= cifsConvertToUTF16((__le16
*) pSMB
->OldFileName
,
2720 fromName
, PATH_MAX
, nls_codepage
,
2722 name_len
++; /* trailing null */
2724 pSMB
->OldFileName
[name_len
] = 0x04; /* pad */
2725 /* protocol requires ASCII signature byte on Unicode string */
2726 pSMB
->OldFileName
[name_len
+ 1] = 0x00;
2728 cifsConvertToUTF16((__le16
*)&pSMB
->OldFileName
[name_len
+2],
2729 toName
, PATH_MAX
, nls_codepage
, remap
);
2730 name_len2
+= 1 /* trailing null */ + 1 /* Signature word */ ;
2731 name_len2
*= 2; /* convert to bytes */
2732 } else { /* BB improve the check for buffer overruns BB */
2733 name_len
= strnlen(fromName
, PATH_MAX
);
2734 name_len
++; /* trailing null */
2735 strncpy(pSMB
->OldFileName
, fromName
, name_len
);
2736 name_len2
= strnlen(toName
, PATH_MAX
);
2737 name_len2
++; /* trailing null */
2738 pSMB
->OldFileName
[name_len
] = 0x04; /* 2nd buffer format */
2739 strncpy(&pSMB
->OldFileName
[name_len
+ 1], toName
, name_len2
);
2740 name_len2
++; /* trailing null */
2741 name_len2
++; /* signature byte */
2744 count
= 1 /* 1st signature byte */ + name_len
+ name_len2
;
2745 inc_rfc1001_len(pSMB
, count
);
2746 pSMB
->ByteCount
= cpu_to_le16(count
);
2748 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
2749 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
2751 cFYI(1, "Send error in copy = %d with %d files copied",
2752 rc
, le16_to_cpu(pSMBr
->CopyCount
));
2754 cifs_buf_release(pSMB
);
2763 CIFSUnixCreateSymLink(const unsigned int xid
, struct cifs_tcon
*tcon
,
2764 const char *fromName
, const char *toName
,
2765 const struct nls_table
*nls_codepage
)
2767 TRANSACTION2_SPI_REQ
*pSMB
= NULL
;
2768 TRANSACTION2_SPI_RSP
*pSMBr
= NULL
;
2771 int name_len_target
;
2773 int bytes_returned
= 0;
2774 __u16 params
, param_offset
, offset
, byte_count
;
2776 cFYI(1, "In Symlink Unix style");
2778 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
2783 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
2785 cifs_strtoUTF16((__le16
*) pSMB
->FileName
, fromName
,
2786 /* find define for this maxpathcomponent */
2787 PATH_MAX
, nls_codepage
);
2788 name_len
++; /* trailing null */
2791 } else { /* BB improve the check for buffer overruns BB */
2792 name_len
= strnlen(fromName
, PATH_MAX
);
2793 name_len
++; /* trailing null */
2794 strncpy(pSMB
->FileName
, fromName
, name_len
);
2796 params
= 6 + name_len
;
2797 pSMB
->MaxSetupCount
= 0;
2801 pSMB
->Reserved2
= 0;
2802 param_offset
= offsetof(struct smb_com_transaction2_spi_req
,
2803 InformationLevel
) - 4;
2804 offset
= param_offset
+ params
;
2806 data_offset
= (char *) (&pSMB
->hdr
.Protocol
) + offset
;
2807 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
2809 cifs_strtoUTF16((__le16
*) data_offset
, toName
, PATH_MAX
2810 /* find define for this maxpathcomponent */
2812 name_len_target
++; /* trailing null */
2813 name_len_target
*= 2;
2814 } else { /* BB improve the check for buffer overruns BB */
2815 name_len_target
= strnlen(toName
, PATH_MAX
);
2816 name_len_target
++; /* trailing null */
2817 strncpy(data_offset
, toName
, name_len_target
);
2820 pSMB
->MaxParameterCount
= cpu_to_le16(2);
2821 /* BB find exact max on data count below from sess */
2822 pSMB
->MaxDataCount
= cpu_to_le16(1000);
2823 pSMB
->SetupCount
= 1;
2824 pSMB
->Reserved3
= 0;
2825 pSMB
->SubCommand
= cpu_to_le16(TRANS2_SET_PATH_INFORMATION
);
2826 byte_count
= 3 /* pad */ + params
+ name_len_target
;
2827 pSMB
->DataCount
= cpu_to_le16(name_len_target
);
2828 pSMB
->ParameterCount
= cpu_to_le16(params
);
2829 pSMB
->TotalDataCount
= pSMB
->DataCount
;
2830 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
2831 pSMB
->ParameterOffset
= cpu_to_le16(param_offset
);
2832 pSMB
->DataOffset
= cpu_to_le16(offset
);
2833 pSMB
->InformationLevel
= cpu_to_le16(SMB_SET_FILE_UNIX_LINK
);
2834 pSMB
->Reserved4
= 0;
2835 inc_rfc1001_len(pSMB
, byte_count
);
2836 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
2837 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
2838 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
2839 cifs_stats_inc(&tcon
->num_symlinks
);
2841 cFYI(1, "Send error in SetPathInfo create symlink = %d", rc
);
2843 cifs_buf_release(pSMB
);
2846 goto createSymLinkRetry
;
2852 CIFSUnixCreateHardLink(const unsigned int xid
, struct cifs_tcon
*tcon
,
2853 const char *fromName
, const char *toName
,
2854 const struct nls_table
*nls_codepage
, int remap
)
2856 TRANSACTION2_SPI_REQ
*pSMB
= NULL
;
2857 TRANSACTION2_SPI_RSP
*pSMBr
= NULL
;
2860 int name_len_target
;
2862 int bytes_returned
= 0;
2863 __u16 params
, param_offset
, offset
, byte_count
;
2865 cFYI(1, "In Create Hard link Unix style");
2866 createHardLinkRetry
:
2867 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
2872 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
2873 name_len
= cifsConvertToUTF16((__le16
*) pSMB
->FileName
, toName
,
2874 PATH_MAX
, nls_codepage
, remap
);
2875 name_len
++; /* trailing null */
2878 } else { /* BB improve the check for buffer overruns BB */
2879 name_len
= strnlen(toName
, PATH_MAX
);
2880 name_len
++; /* trailing null */
2881 strncpy(pSMB
->FileName
, toName
, name_len
);
2883 params
= 6 + name_len
;
2884 pSMB
->MaxSetupCount
= 0;
2888 pSMB
->Reserved2
= 0;
2889 param_offset
= offsetof(struct smb_com_transaction2_spi_req
,
2890 InformationLevel
) - 4;
2891 offset
= param_offset
+ params
;
2893 data_offset
= (char *) (&pSMB
->hdr
.Protocol
) + offset
;
2894 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
2896 cifsConvertToUTF16((__le16
*) data_offset
, fromName
,
2897 PATH_MAX
, nls_codepage
, remap
);
2898 name_len_target
++; /* trailing null */
2899 name_len_target
*= 2;
2900 } else { /* BB improve the check for buffer overruns BB */
2901 name_len_target
= strnlen(fromName
, PATH_MAX
);
2902 name_len_target
++; /* trailing null */
2903 strncpy(data_offset
, fromName
, name_len_target
);
2906 pSMB
->MaxParameterCount
= cpu_to_le16(2);
2907 /* BB find exact max on data count below from sess*/
2908 pSMB
->MaxDataCount
= cpu_to_le16(1000);
2909 pSMB
->SetupCount
= 1;
2910 pSMB
->Reserved3
= 0;
2911 pSMB
->SubCommand
= cpu_to_le16(TRANS2_SET_PATH_INFORMATION
);
2912 byte_count
= 3 /* pad */ + params
+ name_len_target
;
2913 pSMB
->ParameterCount
= cpu_to_le16(params
);
2914 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
2915 pSMB
->DataCount
= cpu_to_le16(name_len_target
);
2916 pSMB
->TotalDataCount
= pSMB
->DataCount
;
2917 pSMB
->ParameterOffset
= cpu_to_le16(param_offset
);
2918 pSMB
->DataOffset
= cpu_to_le16(offset
);
2919 pSMB
->InformationLevel
= cpu_to_le16(SMB_SET_FILE_UNIX_HLINK
);
2920 pSMB
->Reserved4
= 0;
2921 inc_rfc1001_len(pSMB
, byte_count
);
2922 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
2923 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
2924 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
2925 cifs_stats_inc(&tcon
->num_hardlinks
);
2927 cFYI(1, "Send error in SetPathInfo (hard link) = %d", rc
);
2929 cifs_buf_release(pSMB
);
2931 goto createHardLinkRetry
;
2937 CIFSCreateHardLink(const unsigned int xid
, struct cifs_tcon
*tcon
,
2938 const char *fromName
, const char *toName
,
2939 const struct nls_table
*nls_codepage
, int remap
)
2942 NT_RENAME_REQ
*pSMB
= NULL
;
2943 RENAME_RSP
*pSMBr
= NULL
;
2945 int name_len
, name_len2
;
2948 cFYI(1, "In CIFSCreateHardLink");
2949 winCreateHardLinkRetry
:
2951 rc
= smb_init(SMB_COM_NT_RENAME
, 4, tcon
, (void **) &pSMB
,
2956 pSMB
->SearchAttributes
=
2957 cpu_to_le16(ATTR_READONLY
| ATTR_HIDDEN
| ATTR_SYSTEM
|
2959 pSMB
->Flags
= cpu_to_le16(CREATE_HARD_LINK
);
2960 pSMB
->ClusterCount
= 0;
2962 pSMB
->BufferFormat
= 0x04;
2964 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
2966 cifsConvertToUTF16((__le16
*) pSMB
->OldFileName
, fromName
,
2967 PATH_MAX
, nls_codepage
, remap
);
2968 name_len
++; /* trailing null */
2971 /* protocol specifies ASCII buffer format (0x04) for unicode */
2972 pSMB
->OldFileName
[name_len
] = 0x04;
2973 pSMB
->OldFileName
[name_len
+ 1] = 0x00; /* pad */
2975 cifsConvertToUTF16((__le16
*)&pSMB
->OldFileName
[name_len
+2],
2976 toName
, PATH_MAX
, nls_codepage
, remap
);
2977 name_len2
+= 1 /* trailing null */ + 1 /* Signature word */ ;
2978 name_len2
*= 2; /* convert to bytes */
2979 } else { /* BB improve the check for buffer overruns BB */
2980 name_len
= strnlen(fromName
, PATH_MAX
);
2981 name_len
++; /* trailing null */
2982 strncpy(pSMB
->OldFileName
, fromName
, name_len
);
2983 name_len2
= strnlen(toName
, PATH_MAX
);
2984 name_len2
++; /* trailing null */
2985 pSMB
->OldFileName
[name_len
] = 0x04; /* 2nd buffer format */
2986 strncpy(&pSMB
->OldFileName
[name_len
+ 1], toName
, name_len2
);
2987 name_len2
++; /* trailing null */
2988 name_len2
++; /* signature byte */
2991 count
= 1 /* string type byte */ + name_len
+ name_len2
;
2992 inc_rfc1001_len(pSMB
, count
);
2993 pSMB
->ByteCount
= cpu_to_le16(count
);
2995 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
2996 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
2997 cifs_stats_inc(&tcon
->num_hardlinks
);
2999 cFYI(1, "Send error in hard link (NT rename) = %d", rc
);
3001 cifs_buf_release(pSMB
);
3003 goto winCreateHardLinkRetry
;
3009 CIFSSMBUnixQuerySymLink(const unsigned int xid
, struct cifs_tcon
*tcon
,
3010 const unsigned char *searchName
, char **symlinkinfo
,
3011 const struct nls_table
*nls_codepage
)
3013 /* SMB_QUERY_FILE_UNIX_LINK */
3014 TRANSACTION2_QPI_REQ
*pSMB
= NULL
;
3015 TRANSACTION2_QPI_RSP
*pSMBr
= NULL
;
3019 __u16 params
, byte_count
;
3022 cFYI(1, "In QPathSymLinkInfo (Unix) for path %s", searchName
);
3025 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
3030 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
3032 cifs_strtoUTF16((__le16
*) pSMB
->FileName
, searchName
,
3033 PATH_MAX
, nls_codepage
);
3034 name_len
++; /* trailing null */
3036 } else { /* BB improve the check for buffer overruns BB */
3037 name_len
= strnlen(searchName
, PATH_MAX
);
3038 name_len
++; /* trailing null */
3039 strncpy(pSMB
->FileName
, searchName
, name_len
);
3042 params
= 2 /* level */ + 4 /* rsrvd */ + name_len
/* incl null */ ;
3043 pSMB
->TotalDataCount
= 0;
3044 pSMB
->MaxParameterCount
= cpu_to_le16(2);
3045 pSMB
->MaxDataCount
= cpu_to_le16(CIFSMaxBufSize
);
3046 pSMB
->MaxSetupCount
= 0;
3050 pSMB
->Reserved2
= 0;
3051 pSMB
->ParameterOffset
= cpu_to_le16(offsetof(
3052 struct smb_com_transaction2_qpi_req
, InformationLevel
) - 4);
3053 pSMB
->DataCount
= 0;
3054 pSMB
->DataOffset
= 0;
3055 pSMB
->SetupCount
= 1;
3056 pSMB
->Reserved3
= 0;
3057 pSMB
->SubCommand
= cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION
);
3058 byte_count
= params
+ 1 /* pad */ ;
3059 pSMB
->TotalParameterCount
= cpu_to_le16(params
);
3060 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
3061 pSMB
->InformationLevel
= cpu_to_le16(SMB_QUERY_FILE_UNIX_LINK
);
3062 pSMB
->Reserved4
= 0;
3063 inc_rfc1001_len(pSMB
, byte_count
);
3064 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
3066 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
3067 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
3069 cFYI(1, "Send error in QuerySymLinkInfo = %d", rc
);
3071 /* decode response */
3073 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
3074 /* BB also check enough total bytes returned */
3075 if (rc
|| get_bcc(&pSMBr
->hdr
) < 2)
3079 u16 count
= le16_to_cpu(pSMBr
->t2
.DataCount
);
3081 data_start
= ((char *) &pSMBr
->hdr
.Protocol
) +
3082 le16_to_cpu(pSMBr
->t2
.DataOffset
);
3084 if (pSMBr
->hdr
.Flags2
& SMBFLG2_UNICODE
)
3089 /* BB FIXME investigate remapping reserved chars here */
3090 *symlinkinfo
= cifs_strndup_from_utf16(data_start
,
3091 count
, is_unicode
, nls_codepage
);
3096 cifs_buf_release(pSMB
);
3098 goto querySymLinkRetry
;
3102 #ifdef CONFIG_CIFS_SYMLINK_EXPERIMENTAL
3104 * Recent Windows versions now create symlinks more frequently
3105 * and they use the "reparse point" mechanism below. We can of course
3106 * do symlinks nicely to Samba and other servers which support the
3107 * CIFS Unix Extensions and we can also do SFU symlinks and "client only"
3108 * "MF" symlinks optionally, but for recent Windows we really need to
3109 * reenable the code below and fix the cifs_symlink callers to handle this.
3110 * In the interim this code has been moved to its own config option so
3111 * it is not compiled in by default until callers fixed up and more tested.
3114 CIFSSMBQueryReparseLinkInfo(const unsigned int xid
, struct cifs_tcon
*tcon
,
3115 const unsigned char *searchName
,
3116 char *symlinkinfo
, const int buflen
, __u16 fid
,
3117 const struct nls_table
*nls_codepage
)
3121 struct smb_com_transaction_ioctl_req
*pSMB
;
3122 struct smb_com_transaction_ioctl_rsp
*pSMBr
;
3124 cFYI(1, "In Windows reparse style QueryLink for path %s", searchName
);
3125 rc
= smb_init(SMB_COM_NT_TRANSACT
, 23, tcon
, (void **) &pSMB
,
3130 pSMB
->TotalParameterCount
= 0 ;
3131 pSMB
->TotalDataCount
= 0;
3132 pSMB
->MaxParameterCount
= cpu_to_le32(2);
3133 /* BB find exact data count max from sess structure BB */
3134 pSMB
->MaxDataCount
= cpu_to_le32(CIFSMaxBufSize
& 0xFFFFFF00);
3135 pSMB
->MaxSetupCount
= 4;
3137 pSMB
->ParameterOffset
= 0;
3138 pSMB
->DataCount
= 0;
3139 pSMB
->DataOffset
= 0;
3140 pSMB
->SetupCount
= 4;
3141 pSMB
->SubCommand
= cpu_to_le16(NT_TRANSACT_IOCTL
);
3142 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
3143 pSMB
->FunctionCode
= cpu_to_le32(FSCTL_GET_REPARSE_POINT
);
3144 pSMB
->IsFsctl
= 1; /* FSCTL */
3145 pSMB
->IsRootFlag
= 0;
3146 pSMB
->Fid
= fid
; /* file handle always le */
3147 pSMB
->ByteCount
= 0;
3149 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
3150 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
3152 cFYI(1, "Send error in QueryReparseLinkInfo = %d", rc
);
3153 } else { /* decode response */
3154 __u32 data_offset
= le32_to_cpu(pSMBr
->DataOffset
);
3155 __u32 data_count
= le32_to_cpu(pSMBr
->DataCount
);
3156 if (get_bcc(&pSMBr
->hdr
) < 2 || data_offset
> 512) {
3157 /* BB also check enough total bytes returned */
3158 rc
= -EIO
; /* bad smb */
3161 if (data_count
&& (data_count
< 2048)) {
3162 char *end_of_smb
= 2 /* sizeof byte count */ +
3163 get_bcc(&pSMBr
->hdr
) + (char *)&pSMBr
->ByteCount
;
3165 struct reparse_data
*reparse_buf
=
3166 (struct reparse_data
*)
3167 ((char *)&pSMBr
->hdr
.Protocol
3169 if ((char *)reparse_buf
>= end_of_smb
) {
3173 if ((reparse_buf
->LinkNamesBuf
+
3174 reparse_buf
->TargetNameOffset
+
3175 reparse_buf
->TargetNameLen
) > end_of_smb
) {
3176 cFYI(1, "reparse buf beyond SMB");
3181 if (pSMBr
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
3182 cifs_from_ucs2(symlinkinfo
, (__le16
*)
3183 (reparse_buf
->LinkNamesBuf
+
3184 reparse_buf
->TargetNameOffset
),
3186 reparse_buf
->TargetNameLen
,
3188 } else { /* ASCII names */
3189 strncpy(symlinkinfo
,
3190 reparse_buf
->LinkNamesBuf
+
3191 reparse_buf
->TargetNameOffset
,
3192 min_t(const int, buflen
,
3193 reparse_buf
->TargetNameLen
));
3197 cFYI(1, "Invalid return data count on "
3198 "get reparse info ioctl");
3200 symlinkinfo
[buflen
] = 0; /* just in case so the caller
3201 does not go off the end of the buffer */
3202 cFYI(1, "readlink result - %s", symlinkinfo
);
3206 cifs_buf_release(pSMB
);
3208 /* Note: On -EAGAIN error only caller can retry on handle based calls
3209 since file handle passed in no longer valid */
3213 #endif /* CIFS_SYMLINK_EXPERIMENTAL */ /* BB temporarily unused */
3215 #ifdef CONFIG_CIFS_POSIX
3217 /*Convert an Access Control Entry from wire format to local POSIX xattr format*/
3218 static void cifs_convert_ace(posix_acl_xattr_entry
*ace
,
3219 struct cifs_posix_ace
*cifs_ace
)
3221 /* u8 cifs fields do not need le conversion */
3222 ace
->e_perm
= cpu_to_le16(cifs_ace
->cifs_e_perm
);
3223 ace
->e_tag
= cpu_to_le16(cifs_ace
->cifs_e_tag
);
3224 ace
->e_id
= cpu_to_le32(le64_to_cpu(cifs_ace
->cifs_uid
));
3225 /* cFYI(1, "perm %d tag %d id %d",ace->e_perm,ace->e_tag,ace->e_id); */
3230 /* Convert ACL from CIFS POSIX wire format to local Linux POSIX ACL xattr */
3231 static int cifs_copy_posix_acl(char *trgt
, char *src
, const int buflen
,
3232 const int acl_type
, const int size_of_data_area
)
3237 struct cifs_posix_ace
*pACE
;
3238 struct cifs_posix_acl
*cifs_acl
= (struct cifs_posix_acl
*)src
;
3239 posix_acl_xattr_header
*local_acl
= (posix_acl_xattr_header
*)trgt
;
3241 if (le16_to_cpu(cifs_acl
->version
) != CIFS_ACL_VERSION
)
3244 if (acl_type
& ACL_TYPE_ACCESS
) {
3245 count
= le16_to_cpu(cifs_acl
->access_entry_count
);
3246 pACE
= &cifs_acl
->ace_array
[0];
3247 size
= sizeof(struct cifs_posix_acl
);
3248 size
+= sizeof(struct cifs_posix_ace
) * count
;
3249 /* check if we would go beyond end of SMB */
3250 if (size_of_data_area
< size
) {
3251 cFYI(1, "bad CIFS POSIX ACL size %d vs. %d",
3252 size_of_data_area
, size
);
3255 } else if (acl_type
& ACL_TYPE_DEFAULT
) {
3256 count
= le16_to_cpu(cifs_acl
->access_entry_count
);
3257 size
= sizeof(struct cifs_posix_acl
);
3258 size
+= sizeof(struct cifs_posix_ace
) * count
;
3259 /* skip past access ACEs to get to default ACEs */
3260 pACE
= &cifs_acl
->ace_array
[count
];
3261 count
= le16_to_cpu(cifs_acl
->default_entry_count
);
3262 size
+= sizeof(struct cifs_posix_ace
) * count
;
3263 /* check if we would go beyond end of SMB */
3264 if (size_of_data_area
< size
)
3271 size
= posix_acl_xattr_size(count
);
3272 if ((buflen
== 0) || (local_acl
== NULL
)) {
3273 /* used to query ACL EA size */
3274 } else if (size
> buflen
) {
3276 } else /* buffer big enough */ {
3277 local_acl
->a_version
= cpu_to_le32(POSIX_ACL_XATTR_VERSION
);
3278 for (i
= 0; i
< count
; i
++) {
3279 cifs_convert_ace(&local_acl
->a_entries
[i
], pACE
);
3286 static __u16
convert_ace_to_cifs_ace(struct cifs_posix_ace
*cifs_ace
,
3287 const posix_acl_xattr_entry
*local_ace
)
3289 __u16 rc
= 0; /* 0 = ACL converted ok */
3291 cifs_ace
->cifs_e_perm
= le16_to_cpu(local_ace
->e_perm
);
3292 cifs_ace
->cifs_e_tag
= le16_to_cpu(local_ace
->e_tag
);
3293 /* BB is there a better way to handle the large uid? */
3294 if (local_ace
->e_id
== cpu_to_le32(-1)) {
3295 /* Probably no need to le convert -1 on any arch but can not hurt */
3296 cifs_ace
->cifs_uid
= cpu_to_le64(-1);
3298 cifs_ace
->cifs_uid
= cpu_to_le64(le32_to_cpu(local_ace
->e_id
));
3299 /*cFYI(1, "perm %d tag %d id %d",ace->e_perm,ace->e_tag,ace->e_id);*/
3303 /* Convert ACL from local Linux POSIX xattr to CIFS POSIX ACL wire format */
3304 static __u16
ACL_to_cifs_posix(char *parm_data
, const char *pACL
,
3305 const int buflen
, const int acl_type
)
3308 struct cifs_posix_acl
*cifs_acl
= (struct cifs_posix_acl
*)parm_data
;
3309 posix_acl_xattr_header
*local_acl
= (posix_acl_xattr_header
*)pACL
;
3313 if ((buflen
== 0) || (pACL
== NULL
) || (cifs_acl
== NULL
))
3316 count
= posix_acl_xattr_count((size_t)buflen
);
3317 cFYI(1, "setting acl with %d entries from buf of length %d and "
3319 count
, buflen
, le32_to_cpu(local_acl
->a_version
));
3320 if (le32_to_cpu(local_acl
->a_version
) != 2) {
3321 cFYI(1, "unknown POSIX ACL version %d",
3322 le32_to_cpu(local_acl
->a_version
));
3325 cifs_acl
->version
= cpu_to_le16(1);
3326 if (acl_type
== ACL_TYPE_ACCESS
)
3327 cifs_acl
->access_entry_count
= cpu_to_le16(count
);
3328 else if (acl_type
== ACL_TYPE_DEFAULT
)
3329 cifs_acl
->default_entry_count
= cpu_to_le16(count
);
3331 cFYI(1, "unknown ACL type %d", acl_type
);
3334 for (i
= 0; i
< count
; i
++) {
3335 rc
= convert_ace_to_cifs_ace(&cifs_acl
->ace_array
[i
],
3336 &local_acl
->a_entries
[i
]);
3338 /* ACE not converted */
3343 rc
= (__u16
)(count
* sizeof(struct cifs_posix_ace
));
3344 rc
+= sizeof(struct cifs_posix_acl
);
3345 /* BB add check to make sure ACL does not overflow SMB */
3351 CIFSSMBGetPosixACL(const unsigned int xid
, struct cifs_tcon
*tcon
,
3352 const unsigned char *searchName
,
3353 char *acl_inf
, const int buflen
, const int acl_type
,
3354 const struct nls_table
*nls_codepage
, int remap
)
3356 /* SMB_QUERY_POSIX_ACL */
3357 TRANSACTION2_QPI_REQ
*pSMB
= NULL
;
3358 TRANSACTION2_QPI_RSP
*pSMBr
= NULL
;
3362 __u16 params
, byte_count
;
3364 cFYI(1, "In GetPosixACL (Unix) for path %s", searchName
);
3367 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
3372 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
3374 cifsConvertToUTF16((__le16
*) pSMB
->FileName
,
3375 searchName
, PATH_MAX
, nls_codepage
,
3377 name_len
++; /* trailing null */
3379 pSMB
->FileName
[name_len
] = 0;
3380 pSMB
->FileName
[name_len
+1] = 0;
3381 } else { /* BB improve the check for buffer overruns BB */
3382 name_len
= strnlen(searchName
, PATH_MAX
);
3383 name_len
++; /* trailing null */
3384 strncpy(pSMB
->FileName
, searchName
, name_len
);
3387 params
= 2 /* level */ + 4 /* rsrvd */ + name_len
/* incl null */ ;
3388 pSMB
->TotalDataCount
= 0;
3389 pSMB
->MaxParameterCount
= cpu_to_le16(2);
3390 /* BB find exact max data count below from sess structure BB */
3391 pSMB
->MaxDataCount
= cpu_to_le16(4000);
3392 pSMB
->MaxSetupCount
= 0;
3396 pSMB
->Reserved2
= 0;
3397 pSMB
->ParameterOffset
= cpu_to_le16(
3398 offsetof(struct smb_com_transaction2_qpi_req
,
3399 InformationLevel
) - 4);
3400 pSMB
->DataCount
= 0;
3401 pSMB
->DataOffset
= 0;
3402 pSMB
->SetupCount
= 1;
3403 pSMB
->Reserved3
= 0;
3404 pSMB
->SubCommand
= cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION
);
3405 byte_count
= params
+ 1 /* pad */ ;
3406 pSMB
->TotalParameterCount
= cpu_to_le16(params
);
3407 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
3408 pSMB
->InformationLevel
= cpu_to_le16(SMB_QUERY_POSIX_ACL
);
3409 pSMB
->Reserved4
= 0;
3410 inc_rfc1001_len(pSMB
, byte_count
);
3411 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
3413 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
3414 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
3415 cifs_stats_inc(&tcon
->num_acl_get
);
3417 cFYI(1, "Send error in Query POSIX ACL = %d", rc
);
3419 /* decode response */
3421 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
3422 /* BB also check enough total bytes returned */
3423 if (rc
|| get_bcc(&pSMBr
->hdr
) < 2)
3424 rc
= -EIO
; /* bad smb */
3426 __u16 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
3427 __u16 count
= le16_to_cpu(pSMBr
->t2
.DataCount
);
3428 rc
= cifs_copy_posix_acl(acl_inf
,
3429 (char *)&pSMBr
->hdr
.Protocol
+data_offset
,
3430 buflen
, acl_type
, count
);
3433 cifs_buf_release(pSMB
);
3440 CIFSSMBSetPosixACL(const unsigned int xid
, struct cifs_tcon
*tcon
,
3441 const unsigned char *fileName
,
3442 const char *local_acl
, const int buflen
,
3444 const struct nls_table
*nls_codepage
, int remap
)
3446 struct smb_com_transaction2_spi_req
*pSMB
= NULL
;
3447 struct smb_com_transaction2_spi_rsp
*pSMBr
= NULL
;
3451 int bytes_returned
= 0;
3452 __u16 params
, byte_count
, data_count
, param_offset
, offset
;
3454 cFYI(1, "In SetPosixACL (Unix) for path %s", fileName
);
3456 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
3460 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
3462 cifsConvertToUTF16((__le16
*) pSMB
->FileName
, fileName
,
3463 PATH_MAX
, nls_codepage
, remap
);
3464 name_len
++; /* trailing null */
3466 } else { /* BB improve the check for buffer overruns BB */
3467 name_len
= strnlen(fileName
, PATH_MAX
);
3468 name_len
++; /* trailing null */
3469 strncpy(pSMB
->FileName
, fileName
, name_len
);
3471 params
= 6 + name_len
;
3472 pSMB
->MaxParameterCount
= cpu_to_le16(2);
3473 /* BB find max SMB size from sess */
3474 pSMB
->MaxDataCount
= cpu_to_le16(1000);
3475 pSMB
->MaxSetupCount
= 0;
3479 pSMB
->Reserved2
= 0;
3480 param_offset
= offsetof(struct smb_com_transaction2_spi_req
,
3481 InformationLevel
) - 4;
3482 offset
= param_offset
+ params
;
3483 parm_data
= ((char *) &pSMB
->hdr
.Protocol
) + offset
;
3484 pSMB
->ParameterOffset
= cpu_to_le16(param_offset
);
3486 /* convert to on the wire format for POSIX ACL */
3487 data_count
= ACL_to_cifs_posix(parm_data
, local_acl
, buflen
, acl_type
);
3489 if (data_count
== 0) {
3491 goto setACLerrorExit
;
3493 pSMB
->DataOffset
= cpu_to_le16(offset
);
3494 pSMB
->SetupCount
= 1;
3495 pSMB
->Reserved3
= 0;
3496 pSMB
->SubCommand
= cpu_to_le16(TRANS2_SET_PATH_INFORMATION
);
3497 pSMB
->InformationLevel
= cpu_to_le16(SMB_SET_POSIX_ACL
);
3498 byte_count
= 3 /* pad */ + params
+ data_count
;
3499 pSMB
->DataCount
= cpu_to_le16(data_count
);
3500 pSMB
->TotalDataCount
= pSMB
->DataCount
;
3501 pSMB
->ParameterCount
= cpu_to_le16(params
);
3502 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
3503 pSMB
->Reserved4
= 0;
3504 inc_rfc1001_len(pSMB
, byte_count
);
3505 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
3506 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
3507 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
3509 cFYI(1, "Set POSIX ACL returned %d", rc
);
3512 cifs_buf_release(pSMB
);
3518 /* BB fix tabs in this function FIXME BB */
3520 CIFSGetExtAttr(const unsigned int xid
, struct cifs_tcon
*tcon
,
3521 const int netfid
, __u64
*pExtAttrBits
, __u64
*pMask
)
3524 struct smb_t2_qfi_req
*pSMB
= NULL
;
3525 struct smb_t2_qfi_rsp
*pSMBr
= NULL
;
3527 __u16 params
, byte_count
;
3529 cFYI(1, "In GetExtAttr");
3534 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
3539 params
= 2 /* level */ + 2 /* fid */;
3540 pSMB
->t2
.TotalDataCount
= 0;
3541 pSMB
->t2
.MaxParameterCount
= cpu_to_le16(4);
3542 /* BB find exact max data count below from sess structure BB */
3543 pSMB
->t2
.MaxDataCount
= cpu_to_le16(4000);
3544 pSMB
->t2
.MaxSetupCount
= 0;
3545 pSMB
->t2
.Reserved
= 0;
3547 pSMB
->t2
.Timeout
= 0;
3548 pSMB
->t2
.Reserved2
= 0;
3549 pSMB
->t2
.ParameterOffset
= cpu_to_le16(offsetof(struct smb_t2_qfi_req
,
3551 pSMB
->t2
.DataCount
= 0;
3552 pSMB
->t2
.DataOffset
= 0;
3553 pSMB
->t2
.SetupCount
= 1;
3554 pSMB
->t2
.Reserved3
= 0;
3555 pSMB
->t2
.SubCommand
= cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION
);
3556 byte_count
= params
+ 1 /* pad */ ;
3557 pSMB
->t2
.TotalParameterCount
= cpu_to_le16(params
);
3558 pSMB
->t2
.ParameterCount
= pSMB
->t2
.TotalParameterCount
;
3559 pSMB
->InformationLevel
= cpu_to_le16(SMB_QUERY_ATTR_FLAGS
);
3562 inc_rfc1001_len(pSMB
, byte_count
);
3563 pSMB
->t2
.ByteCount
= cpu_to_le16(byte_count
);
3565 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
3566 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
3568 cFYI(1, "error %d in GetExtAttr", rc
);
3570 /* decode response */
3571 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
3572 /* BB also check enough total bytes returned */
3573 if (rc
|| get_bcc(&pSMBr
->hdr
) < 2)
3574 /* If rc should we check for EOPNOSUPP and
3575 disable the srvino flag? or in caller? */
3576 rc
= -EIO
; /* bad smb */
3578 __u16 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
3579 __u16 count
= le16_to_cpu(pSMBr
->t2
.DataCount
);
3580 struct file_chattr_info
*pfinfo
;
3581 /* BB Do we need a cast or hash here ? */
3583 cFYI(1, "Illegal size ret in GetExtAttr");
3587 pfinfo
= (struct file_chattr_info
*)
3588 (data_offset
+ (char *) &pSMBr
->hdr
.Protocol
);
3589 *pExtAttrBits
= le64_to_cpu(pfinfo
->mode
);
3590 *pMask
= le64_to_cpu(pfinfo
->mask
);
3594 cifs_buf_release(pSMB
);
3596 goto GetExtAttrRetry
;
3600 #endif /* CONFIG_POSIX */
3602 #ifdef CONFIG_CIFS_ACL
3604 * Initialize NT TRANSACT SMB into small smb request buffer. This assumes that
3605 * all NT TRANSACTS that we init here have total parm and data under about 400
3606 * bytes (to fit in small cifs buffer size), which is the case so far, it
3607 * easily fits. NB: Setup words themselves and ByteCount MaxSetupCount (size of
3608 * returned setup area) and MaxParameterCount (returned parms size) must be set
3612 smb_init_nttransact(const __u16 sub_command
, const int setup_count
,
3613 const int parm_len
, struct cifs_tcon
*tcon
,
3618 struct smb_com_ntransact_req
*pSMB
;
3620 rc
= small_smb_init(SMB_COM_NT_TRANSACT
, 19 + setup_count
, tcon
,
3624 *ret_buf
= (void *)pSMB
;
3626 pSMB
->TotalParameterCount
= cpu_to_le32(parm_len
);
3627 pSMB
->TotalDataCount
= 0;
3628 pSMB
->MaxDataCount
= cpu_to_le32(CIFSMaxBufSize
& 0xFFFFFF00);
3629 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
3630 pSMB
->DataCount
= pSMB
->TotalDataCount
;
3631 temp_offset
= offsetof(struct smb_com_ntransact_req
, Parms
) +
3632 (setup_count
* 2) - 4 /* for rfc1001 length itself */;
3633 pSMB
->ParameterOffset
= cpu_to_le32(temp_offset
);
3634 pSMB
->DataOffset
= cpu_to_le32(temp_offset
+ parm_len
);
3635 pSMB
->SetupCount
= setup_count
; /* no need to le convert byte fields */
3636 pSMB
->SubCommand
= cpu_to_le16(sub_command
);
3641 validate_ntransact(char *buf
, char **ppparm
, char **ppdata
,
3642 __u32
*pparmlen
, __u32
*pdatalen
)
3645 __u32 data_count
, data_offset
, parm_count
, parm_offset
;
3646 struct smb_com_ntransact_rsp
*pSMBr
;
3655 pSMBr
= (struct smb_com_ntransact_rsp
*)buf
;
3657 bcc
= get_bcc(&pSMBr
->hdr
);
3658 end_of_smb
= 2 /* sizeof byte count */ + bcc
+
3659 (char *)&pSMBr
->ByteCount
;
3661 data_offset
= le32_to_cpu(pSMBr
->DataOffset
);
3662 data_count
= le32_to_cpu(pSMBr
->DataCount
);
3663 parm_offset
= le32_to_cpu(pSMBr
->ParameterOffset
);
3664 parm_count
= le32_to_cpu(pSMBr
->ParameterCount
);
3666 *ppparm
= (char *)&pSMBr
->hdr
.Protocol
+ parm_offset
;
3667 *ppdata
= (char *)&pSMBr
->hdr
.Protocol
+ data_offset
;
3669 /* should we also check that parm and data areas do not overlap? */
3670 if (*ppparm
> end_of_smb
) {
3671 cFYI(1, "parms start after end of smb");
3673 } else if (parm_count
+ *ppparm
> end_of_smb
) {
3674 cFYI(1, "parm end after end of smb");
3676 } else if (*ppdata
> end_of_smb
) {
3677 cFYI(1, "data starts after end of smb");
3679 } else if (data_count
+ *ppdata
> end_of_smb
) {
3680 cFYI(1, "data %p + count %d (%p) past smb end %p start %p",
3681 *ppdata
, data_count
, (data_count
+ *ppdata
),
3684 } else if (parm_count
+ data_count
> bcc
) {
3685 cFYI(1, "parm count and data count larger than SMB");
3688 *pdatalen
= data_count
;
3689 *pparmlen
= parm_count
;
3693 /* Get Security Descriptor (by handle) from remote server for a file or dir */
3695 CIFSSMBGetCIFSACL(const unsigned int xid
, struct cifs_tcon
*tcon
, __u16 fid
,
3696 struct cifs_ntsd
**acl_inf
, __u32
*pbuflen
)
3700 QUERY_SEC_DESC_REQ
*pSMB
;
3703 cFYI(1, "GetCifsACL");
3708 rc
= smb_init_nttransact(NT_TRANSACT_QUERY_SECURITY_DESC
, 0,
3709 8 /* parm len */, tcon
, (void **) &pSMB
);
3713 pSMB
->MaxParameterCount
= cpu_to_le32(4);
3714 /* BB TEST with big acls that might need to be e.g. larger than 16K */
3715 pSMB
->MaxSetupCount
= 0;
3716 pSMB
->Fid
= fid
; /* file handle always le */
3717 pSMB
->AclFlags
= cpu_to_le32(CIFS_ACL_OWNER
| CIFS_ACL_GROUP
|
3719 pSMB
->ByteCount
= cpu_to_le16(11); /* 3 bytes pad + 8 bytes parm */
3720 inc_rfc1001_len(pSMB
, 11);
3721 iov
[0].iov_base
= (char *)pSMB
;
3722 iov
[0].iov_len
= be32_to_cpu(pSMB
->hdr
.smb_buf_length
) + 4;
3724 rc
= SendReceive2(xid
, tcon
->ses
, iov
, 1 /* num iovec */, &buf_type
,
3726 cifs_stats_inc(&tcon
->num_acl_get
);
3728 cFYI(1, "Send error in QuerySecDesc = %d", rc
);
3729 } else { /* decode response */
3733 struct smb_com_ntransact_rsp
*pSMBr
;
3736 /* validate_nttransact */
3737 rc
= validate_ntransact(iov
[0].iov_base
, (char **)&parm
,
3738 &pdata
, &parm_len
, pbuflen
);
3741 pSMBr
= (struct smb_com_ntransact_rsp
*)iov
[0].iov_base
;
3743 cFYI(1, "smb %p parm %p data %p", pSMBr
, parm
, *acl_inf
);
3745 if (le32_to_cpu(pSMBr
->ParameterCount
) != 4) {
3746 rc
= -EIO
; /* bad smb */
3751 /* BB check that data area is minimum length and as big as acl_len */
3753 acl_len
= le32_to_cpu(*parm
);
3754 if (acl_len
!= *pbuflen
) {
3755 cERROR(1, "acl length %d does not match %d",
3757 if (*pbuflen
> acl_len
)
3761 /* check if buffer is big enough for the acl
3762 header followed by the smallest SID */
3763 if ((*pbuflen
< sizeof(struct cifs_ntsd
) + 8) ||
3764 (*pbuflen
>= 64 * 1024)) {
3765 cERROR(1, "bad acl length %d", *pbuflen
);
3769 *acl_inf
= kmalloc(*pbuflen
, GFP_KERNEL
);
3770 if (*acl_inf
== NULL
) {
3774 memcpy(*acl_inf
, pdata
, *pbuflen
);
3778 if (buf_type
== CIFS_SMALL_BUFFER
)
3779 cifs_small_buf_release(iov
[0].iov_base
);
3780 else if (buf_type
== CIFS_LARGE_BUFFER
)
3781 cifs_buf_release(iov
[0].iov_base
);
3782 /* cifs_small_buf_release(pSMB); */ /* Freed earlier now in SendReceive2 */
3787 CIFSSMBSetCIFSACL(const unsigned int xid
, struct cifs_tcon
*tcon
, __u16 fid
,
3788 struct cifs_ntsd
*pntsd
, __u32 acllen
, int aclflag
)
3790 __u16 byte_count
, param_count
, data_count
, param_offset
, data_offset
;
3792 int bytes_returned
= 0;
3793 SET_SEC_DESC_REQ
*pSMB
= NULL
;
3797 rc
= smb_init(SMB_COM_NT_TRANSACT
, 19, tcon
, (void **) &pSMB
, &pSMBr
);
3801 pSMB
->MaxSetupCount
= 0;
3805 param_offset
= offsetof(struct smb_com_transaction_ssec_req
, Fid
) - 4;
3806 data_count
= acllen
;
3807 data_offset
= param_offset
+ param_count
;
3808 byte_count
= 3 /* pad */ + param_count
;
3810 pSMB
->DataCount
= cpu_to_le32(data_count
);
3811 pSMB
->TotalDataCount
= pSMB
->DataCount
;
3812 pSMB
->MaxParameterCount
= cpu_to_le32(4);
3813 pSMB
->MaxDataCount
= cpu_to_le32(16384);
3814 pSMB
->ParameterCount
= cpu_to_le32(param_count
);
3815 pSMB
->ParameterOffset
= cpu_to_le32(param_offset
);
3816 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
3817 pSMB
->DataOffset
= cpu_to_le32(data_offset
);
3818 pSMB
->SetupCount
= 0;
3819 pSMB
->SubCommand
= cpu_to_le16(NT_TRANSACT_SET_SECURITY_DESC
);
3820 pSMB
->ByteCount
= cpu_to_le16(byte_count
+data_count
);
3822 pSMB
->Fid
= fid
; /* file handle always le */
3823 pSMB
->Reserved2
= 0;
3824 pSMB
->AclFlags
= cpu_to_le32(aclflag
);
3826 if (pntsd
&& acllen
) {
3827 memcpy((char *)pSMBr
+ offsetof(struct smb_hdr
, Protocol
) +
3828 data_offset
, pntsd
, acllen
);
3829 inc_rfc1001_len(pSMB
, byte_count
+ data_count
);
3831 inc_rfc1001_len(pSMB
, byte_count
);
3833 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
3834 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
3836 cFYI(1, "SetCIFSACL bytes_returned: %d, rc: %d", bytes_returned
, rc
);
3838 cFYI(1, "Set CIFS ACL returned %d", rc
);
3839 cifs_buf_release(pSMB
);
3842 goto setCifsAclRetry
;
3847 #endif /* CONFIG_CIFS_ACL */
3849 /* Legacy Query Path Information call for lookup to old servers such
3851 int SMBQueryInformation(const unsigned int xid
, struct cifs_tcon
*tcon
,
3852 const unsigned char *searchName
,
3853 FILE_ALL_INFO
*pFinfo
,
3854 const struct nls_table
*nls_codepage
, int remap
)
3856 QUERY_INFORMATION_REQ
*pSMB
;
3857 QUERY_INFORMATION_RSP
*pSMBr
;
3862 cFYI(1, "In SMBQPath path %s", searchName
);
3864 rc
= smb_init(SMB_COM_QUERY_INFORMATION
, 0, tcon
, (void **) &pSMB
,
3869 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
3871 cifsConvertToUTF16((__le16
*) pSMB
->FileName
,
3872 searchName
, PATH_MAX
, nls_codepage
,
3874 name_len
++; /* trailing null */
3877 name_len
= strnlen(searchName
, PATH_MAX
);
3878 name_len
++; /* trailing null */
3879 strncpy(pSMB
->FileName
, searchName
, name_len
);
3881 pSMB
->BufferFormat
= 0x04;
3882 name_len
++; /* account for buffer type byte */
3883 inc_rfc1001_len(pSMB
, (__u16
)name_len
);
3884 pSMB
->ByteCount
= cpu_to_le16(name_len
);
3886 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
3887 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
3889 cFYI(1, "Send error in QueryInfo = %d", rc
);
3890 } else if (pFinfo
) {
3892 __u32 time
= le32_to_cpu(pSMBr
->last_write_time
);
3894 /* decode response */
3895 /* BB FIXME - add time zone adjustment BB */
3896 memset(pFinfo
, 0, sizeof(FILE_ALL_INFO
));
3899 /* decode time fields */
3900 pFinfo
->ChangeTime
= cpu_to_le64(cifs_UnixTimeToNT(ts
));
3901 pFinfo
->LastWriteTime
= pFinfo
->ChangeTime
;
3902 pFinfo
->LastAccessTime
= 0;
3903 pFinfo
->AllocationSize
=
3904 cpu_to_le64(le32_to_cpu(pSMBr
->size
));
3905 pFinfo
->EndOfFile
= pFinfo
->AllocationSize
;
3906 pFinfo
->Attributes
=
3907 cpu_to_le32(le16_to_cpu(pSMBr
->attr
));
3909 rc
= -EIO
; /* bad buffer passed in */
3911 cifs_buf_release(pSMB
);
3920 CIFSSMBQFileInfo(const unsigned int xid
, struct cifs_tcon
*tcon
,
3921 u16 netfid
, FILE_ALL_INFO
*pFindData
)
3923 struct smb_t2_qfi_req
*pSMB
= NULL
;
3924 struct smb_t2_qfi_rsp
*pSMBr
= NULL
;
3927 __u16 params
, byte_count
;
3930 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
3935 params
= 2 /* level */ + 2 /* fid */;
3936 pSMB
->t2
.TotalDataCount
= 0;
3937 pSMB
->t2
.MaxParameterCount
= cpu_to_le16(4);
3938 /* BB find exact max data count below from sess structure BB */
3939 pSMB
->t2
.MaxDataCount
= cpu_to_le16(CIFSMaxBufSize
);
3940 pSMB
->t2
.MaxSetupCount
= 0;
3941 pSMB
->t2
.Reserved
= 0;
3943 pSMB
->t2
.Timeout
= 0;
3944 pSMB
->t2
.Reserved2
= 0;
3945 pSMB
->t2
.ParameterOffset
= cpu_to_le16(offsetof(struct smb_t2_qfi_req
,
3947 pSMB
->t2
.DataCount
= 0;
3948 pSMB
->t2
.DataOffset
= 0;
3949 pSMB
->t2
.SetupCount
= 1;
3950 pSMB
->t2
.Reserved3
= 0;
3951 pSMB
->t2
.SubCommand
= cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION
);
3952 byte_count
= params
+ 1 /* pad */ ;
3953 pSMB
->t2
.TotalParameterCount
= cpu_to_le16(params
);
3954 pSMB
->t2
.ParameterCount
= pSMB
->t2
.TotalParameterCount
;
3955 pSMB
->InformationLevel
= cpu_to_le16(SMB_QUERY_FILE_ALL_INFO
);
3958 inc_rfc1001_len(pSMB
, byte_count
);
3960 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
3961 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
3963 cFYI(1, "Send error in QPathInfo = %d", rc
);
3964 } else { /* decode response */
3965 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
3967 if (rc
) /* BB add auto retry on EOPNOTSUPP? */
3969 else if (get_bcc(&pSMBr
->hdr
) < 40)
3970 rc
= -EIO
; /* bad smb */
3971 else if (pFindData
) {
3972 __u16 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
3973 memcpy((char *) pFindData
,
3974 (char *) &pSMBr
->hdr
.Protocol
+
3975 data_offset
, sizeof(FILE_ALL_INFO
));
3979 cifs_buf_release(pSMB
);
3981 goto QFileInfoRetry
;
3987 CIFSSMBQPathInfo(const unsigned int xid
, struct cifs_tcon
*tcon
,
3988 const unsigned char *searchName
,
3989 FILE_ALL_INFO
*pFindData
,
3990 int legacy
/* old style infolevel */,
3991 const struct nls_table
*nls_codepage
, int remap
)
3993 /* level 263 SMB_QUERY_FILE_ALL_INFO */
3994 TRANSACTION2_QPI_REQ
*pSMB
= NULL
;
3995 TRANSACTION2_QPI_RSP
*pSMBr
= NULL
;
3999 __u16 params
, byte_count
;
4001 /* cFYI(1, "In QPathInfo path %s", searchName); */
4003 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
4008 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
4010 cifsConvertToUTF16((__le16
*) pSMB
->FileName
, searchName
,
4011 PATH_MAX
, nls_codepage
, remap
);
4012 name_len
++; /* trailing null */
4014 } else { /* BB improve the check for buffer overruns BB */
4015 name_len
= strnlen(searchName
, PATH_MAX
);
4016 name_len
++; /* trailing null */
4017 strncpy(pSMB
->FileName
, searchName
, name_len
);
4020 params
= 2 /* level */ + 4 /* reserved */ + name_len
/* includes NUL */;
4021 pSMB
->TotalDataCount
= 0;
4022 pSMB
->MaxParameterCount
= cpu_to_le16(2);
4023 /* BB find exact max SMB PDU from sess structure BB */
4024 pSMB
->MaxDataCount
= cpu_to_le16(4000);
4025 pSMB
->MaxSetupCount
= 0;
4029 pSMB
->Reserved2
= 0;
4030 pSMB
->ParameterOffset
= cpu_to_le16(offsetof(
4031 struct smb_com_transaction2_qpi_req
, InformationLevel
) - 4);
4032 pSMB
->DataCount
= 0;
4033 pSMB
->DataOffset
= 0;
4034 pSMB
->SetupCount
= 1;
4035 pSMB
->Reserved3
= 0;
4036 pSMB
->SubCommand
= cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION
);
4037 byte_count
= params
+ 1 /* pad */ ;
4038 pSMB
->TotalParameterCount
= cpu_to_le16(params
);
4039 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
4041 pSMB
->InformationLevel
= cpu_to_le16(SMB_INFO_STANDARD
);
4043 pSMB
->InformationLevel
= cpu_to_le16(SMB_QUERY_FILE_ALL_INFO
);
4044 pSMB
->Reserved4
= 0;
4045 inc_rfc1001_len(pSMB
, byte_count
);
4046 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
4048 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
4049 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
4051 cFYI(1, "Send error in QPathInfo = %d", rc
);
4052 } else { /* decode response */
4053 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
4055 if (rc
) /* BB add auto retry on EOPNOTSUPP? */
4057 else if (!legacy
&& get_bcc(&pSMBr
->hdr
) < 40)
4058 rc
= -EIO
; /* bad smb */
4059 else if (legacy
&& get_bcc(&pSMBr
->hdr
) < 24)
4060 rc
= -EIO
; /* 24 or 26 expected but we do not read
4062 else if (pFindData
) {
4064 __u16 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
4066 /* On legacy responses we do not read the last field,
4067 EAsize, fortunately since it varies by subdialect and
4068 also note it differs on Set vs. Get, ie two bytes or 4
4069 bytes depending but we don't care here */
4071 size
= sizeof(FILE_INFO_STANDARD
);
4073 size
= sizeof(FILE_ALL_INFO
);
4074 memcpy((char *) pFindData
,
4075 (char *) &pSMBr
->hdr
.Protocol
+
4080 cifs_buf_release(pSMB
);
4082 goto QPathInfoRetry
;
4088 CIFSSMBUnixQFileInfo(const unsigned int xid
, struct cifs_tcon
*tcon
,
4089 u16 netfid
, FILE_UNIX_BASIC_INFO
*pFindData
)
4091 struct smb_t2_qfi_req
*pSMB
= NULL
;
4092 struct smb_t2_qfi_rsp
*pSMBr
= NULL
;
4095 __u16 params
, byte_count
;
4098 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
4103 params
= 2 /* level */ + 2 /* fid */;
4104 pSMB
->t2
.TotalDataCount
= 0;
4105 pSMB
->t2
.MaxParameterCount
= cpu_to_le16(4);
4106 /* BB find exact max data count below from sess structure BB */
4107 pSMB
->t2
.MaxDataCount
= cpu_to_le16(CIFSMaxBufSize
);
4108 pSMB
->t2
.MaxSetupCount
= 0;
4109 pSMB
->t2
.Reserved
= 0;
4111 pSMB
->t2
.Timeout
= 0;
4112 pSMB
->t2
.Reserved2
= 0;
4113 pSMB
->t2
.ParameterOffset
= cpu_to_le16(offsetof(struct smb_t2_qfi_req
,
4115 pSMB
->t2
.DataCount
= 0;
4116 pSMB
->t2
.DataOffset
= 0;
4117 pSMB
->t2
.SetupCount
= 1;
4118 pSMB
->t2
.Reserved3
= 0;
4119 pSMB
->t2
.SubCommand
= cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION
);
4120 byte_count
= params
+ 1 /* pad */ ;
4121 pSMB
->t2
.TotalParameterCount
= cpu_to_le16(params
);
4122 pSMB
->t2
.ParameterCount
= pSMB
->t2
.TotalParameterCount
;
4123 pSMB
->InformationLevel
= cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC
);
4126 inc_rfc1001_len(pSMB
, byte_count
);
4128 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
4129 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
4131 cFYI(1, "Send error in QPathInfo = %d", rc
);
4132 } else { /* decode response */
4133 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
4135 if (rc
|| get_bcc(&pSMBr
->hdr
) < sizeof(FILE_UNIX_BASIC_INFO
)) {
4136 cERROR(1, "Malformed FILE_UNIX_BASIC_INFO response. "
4137 "Unix Extensions can be disabled on mount "
4138 "by specifying the nosfu mount option.");
4139 rc
= -EIO
; /* bad smb */
4141 __u16 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
4142 memcpy((char *) pFindData
,
4143 (char *) &pSMBr
->hdr
.Protocol
+
4145 sizeof(FILE_UNIX_BASIC_INFO
));
4149 cifs_buf_release(pSMB
);
4151 goto UnixQFileInfoRetry
;
4157 CIFSSMBUnixQPathInfo(const unsigned int xid
, struct cifs_tcon
*tcon
,
4158 const unsigned char *searchName
,
4159 FILE_UNIX_BASIC_INFO
*pFindData
,
4160 const struct nls_table
*nls_codepage
, int remap
)
4162 /* SMB_QUERY_FILE_UNIX_BASIC */
4163 TRANSACTION2_QPI_REQ
*pSMB
= NULL
;
4164 TRANSACTION2_QPI_RSP
*pSMBr
= NULL
;
4166 int bytes_returned
= 0;
4168 __u16 params
, byte_count
;
4170 cFYI(1, "In QPathInfo (Unix) the path %s", searchName
);
4172 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
4177 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
4179 cifsConvertToUTF16((__le16
*) pSMB
->FileName
, searchName
,
4180 PATH_MAX
, nls_codepage
, remap
);
4181 name_len
++; /* trailing null */
4183 } else { /* BB improve the check for buffer overruns BB */
4184 name_len
= strnlen(searchName
, PATH_MAX
);
4185 name_len
++; /* trailing null */
4186 strncpy(pSMB
->FileName
, searchName
, name_len
);
4189 params
= 2 /* level */ + 4 /* reserved */ + name_len
/* includes NUL */;
4190 pSMB
->TotalDataCount
= 0;
4191 pSMB
->MaxParameterCount
= cpu_to_le16(2);
4192 /* BB find exact max SMB PDU from sess structure BB */
4193 pSMB
->MaxDataCount
= cpu_to_le16(4000);
4194 pSMB
->MaxSetupCount
= 0;
4198 pSMB
->Reserved2
= 0;
4199 pSMB
->ParameterOffset
= cpu_to_le16(offsetof(
4200 struct smb_com_transaction2_qpi_req
, InformationLevel
) - 4);
4201 pSMB
->DataCount
= 0;
4202 pSMB
->DataOffset
= 0;
4203 pSMB
->SetupCount
= 1;
4204 pSMB
->Reserved3
= 0;
4205 pSMB
->SubCommand
= cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION
);
4206 byte_count
= params
+ 1 /* pad */ ;
4207 pSMB
->TotalParameterCount
= cpu_to_le16(params
);
4208 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
4209 pSMB
->InformationLevel
= cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC
);
4210 pSMB
->Reserved4
= 0;
4211 inc_rfc1001_len(pSMB
, byte_count
);
4212 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
4214 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
4215 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
4217 cFYI(1, "Send error in QPathInfo = %d", rc
);
4218 } else { /* decode response */
4219 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
4221 if (rc
|| get_bcc(&pSMBr
->hdr
) < sizeof(FILE_UNIX_BASIC_INFO
)) {
4222 cERROR(1, "Malformed FILE_UNIX_BASIC_INFO response. "
4223 "Unix Extensions can be disabled on mount "
4224 "by specifying the nosfu mount option.");
4225 rc
= -EIO
; /* bad smb */
4227 __u16 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
4228 memcpy((char *) pFindData
,
4229 (char *) &pSMBr
->hdr
.Protocol
+
4231 sizeof(FILE_UNIX_BASIC_INFO
));
4234 cifs_buf_release(pSMB
);
4236 goto UnixQPathInfoRetry
;
4241 /* xid, tcon, searchName and codepage are input parms, rest are returned */
4243 CIFSFindFirst(const unsigned int xid
, struct cifs_tcon
*tcon
,
4244 const char *searchName
,
4245 const struct nls_table
*nls_codepage
,
4246 __u16
*pnetfid
, __u16 search_flags
,
4247 struct cifs_search_info
*psrch_inf
, int remap
, const char dirsep
)
4249 /* level 257 SMB_ */
4250 TRANSACTION2_FFIRST_REQ
*pSMB
= NULL
;
4251 TRANSACTION2_FFIRST_RSP
*pSMBr
= NULL
;
4252 T2_FFIRST_RSP_PARMS
*parms
;
4254 int bytes_returned
= 0;
4256 __u16 params
, byte_count
;
4258 cFYI(1, "In FindFirst for %s", searchName
);
4261 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
4266 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
4268 cifsConvertToUTF16((__le16
*) pSMB
->FileName
, searchName
,
4269 PATH_MAX
, nls_codepage
, remap
);
4270 /* We can not add the asterik earlier in case
4271 it got remapped to 0xF03A as if it were part of the
4272 directory name instead of a wildcard */
4274 pSMB
->FileName
[name_len
] = dirsep
;
4275 pSMB
->FileName
[name_len
+1] = 0;
4276 pSMB
->FileName
[name_len
+2] = '*';
4277 pSMB
->FileName
[name_len
+3] = 0;
4278 name_len
+= 4; /* now the trailing null */
4279 pSMB
->FileName
[name_len
] = 0; /* null terminate just in case */
4280 pSMB
->FileName
[name_len
+1] = 0;
4282 } else { /* BB add check for overrun of SMB buf BB */
4283 name_len
= strnlen(searchName
, PATH_MAX
);
4284 /* BB fix here and in unicode clause above ie
4285 if (name_len > buffersize-header)
4286 free buffer exit; BB */
4287 strncpy(pSMB
->FileName
, searchName
, name_len
);
4288 pSMB
->FileName
[name_len
] = dirsep
;
4289 pSMB
->FileName
[name_len
+1] = '*';
4290 pSMB
->FileName
[name_len
+2] = 0;
4294 params
= 12 + name_len
/* includes null */ ;
4295 pSMB
->TotalDataCount
= 0; /* no EAs */
4296 pSMB
->MaxParameterCount
= cpu_to_le16(10);
4297 pSMB
->MaxDataCount
= cpu_to_le16(CIFSMaxBufSize
& 0xFFFFFF00);
4298 pSMB
->MaxSetupCount
= 0;
4302 pSMB
->Reserved2
= 0;
4303 byte_count
= params
+ 1 /* pad */ ;
4304 pSMB
->TotalParameterCount
= cpu_to_le16(params
);
4305 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
4306 pSMB
->ParameterOffset
= cpu_to_le16(
4307 offsetof(struct smb_com_transaction2_ffirst_req
, SearchAttributes
)
4309 pSMB
->DataCount
= 0;
4310 pSMB
->DataOffset
= 0;
4311 pSMB
->SetupCount
= 1; /* one byte, no need to make endian neutral */
4312 pSMB
->Reserved3
= 0;
4313 pSMB
->SubCommand
= cpu_to_le16(TRANS2_FIND_FIRST
);
4314 pSMB
->SearchAttributes
=
4315 cpu_to_le16(ATTR_READONLY
| ATTR_HIDDEN
| ATTR_SYSTEM
|
4317 pSMB
->SearchCount
= cpu_to_le16(CIFSMaxBufSize
/sizeof(FILE_UNIX_INFO
));
4318 pSMB
->SearchFlags
= cpu_to_le16(search_flags
);
4319 pSMB
->InformationLevel
= cpu_to_le16(psrch_inf
->info_level
);
4321 /* BB what should we set StorageType to? Does it matter? BB */
4322 pSMB
->SearchStorageType
= 0;
4323 inc_rfc1001_len(pSMB
, byte_count
);
4324 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
4326 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
4327 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
4328 cifs_stats_inc(&tcon
->num_ffirst
);
4330 if (rc
) {/* BB add logic to retry regular search if Unix search
4331 rejected unexpectedly by server */
4332 /* BB Add code to handle unsupported level rc */
4333 cFYI(1, "Error in FindFirst = %d", rc
);
4335 cifs_buf_release(pSMB
);
4337 /* BB eventually could optimize out free and realloc of buf */
4340 goto findFirstRetry
;
4341 } else { /* decode response */
4342 /* BB remember to free buffer if error BB */
4343 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
4347 if (pSMBr
->hdr
.Flags2
& SMBFLG2_UNICODE
)
4348 psrch_inf
->unicode
= true;
4350 psrch_inf
->unicode
= false;
4352 psrch_inf
->ntwrk_buf_start
= (char *)pSMBr
;
4353 psrch_inf
->smallBuf
= 0;
4354 psrch_inf
->srch_entries_start
=
4355 (char *) &pSMBr
->hdr
.Protocol
+
4356 le16_to_cpu(pSMBr
->t2
.DataOffset
);
4357 parms
= (T2_FFIRST_RSP_PARMS
*)((char *) &pSMBr
->hdr
.Protocol
+
4358 le16_to_cpu(pSMBr
->t2
.ParameterOffset
));
4360 if (parms
->EndofSearch
)
4361 psrch_inf
->endOfSearch
= true;
4363 psrch_inf
->endOfSearch
= false;
4365 psrch_inf
->entries_in_buffer
=
4366 le16_to_cpu(parms
->SearchCount
);
4367 psrch_inf
->index_of_last_entry
= 2 /* skip . and .. */ +
4368 psrch_inf
->entries_in_buffer
;
4369 lnoff
= le16_to_cpu(parms
->LastNameOffset
);
4370 if (CIFSMaxBufSize
< lnoff
) {
4371 cERROR(1, "ignoring corrupt resume name");
4372 psrch_inf
->last_entry
= NULL
;
4376 psrch_inf
->last_entry
= psrch_inf
->srch_entries_start
+
4379 *pnetfid
= parms
->SearchHandle
;
4381 cifs_buf_release(pSMB
);
4388 int CIFSFindNext(const unsigned int xid
, struct cifs_tcon
*tcon
,
4389 __u16 searchHandle
, __u16 search_flags
,
4390 struct cifs_search_info
*psrch_inf
)
4392 TRANSACTION2_FNEXT_REQ
*pSMB
= NULL
;
4393 TRANSACTION2_FNEXT_RSP
*pSMBr
= NULL
;
4394 T2_FNEXT_RSP_PARMS
*parms
;
4395 char *response_data
;
4398 unsigned int name_len
;
4399 __u16 params
, byte_count
;
4401 cFYI(1, "In FindNext");
4403 if (psrch_inf
->endOfSearch
)
4406 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
4411 params
= 14; /* includes 2 bytes of null string, converted to LE below*/
4413 pSMB
->TotalDataCount
= 0; /* no EAs */
4414 pSMB
->MaxParameterCount
= cpu_to_le16(8);
4415 pSMB
->MaxDataCount
= cpu_to_le16(CIFSMaxBufSize
& 0xFFFFFF00);
4416 pSMB
->MaxSetupCount
= 0;
4420 pSMB
->Reserved2
= 0;
4421 pSMB
->ParameterOffset
= cpu_to_le16(
4422 offsetof(struct smb_com_transaction2_fnext_req
,SearchHandle
) - 4);
4423 pSMB
->DataCount
= 0;
4424 pSMB
->DataOffset
= 0;
4425 pSMB
->SetupCount
= 1;
4426 pSMB
->Reserved3
= 0;
4427 pSMB
->SubCommand
= cpu_to_le16(TRANS2_FIND_NEXT
);
4428 pSMB
->SearchHandle
= searchHandle
; /* always kept as le */
4430 cpu_to_le16(CIFSMaxBufSize
/ sizeof(FILE_UNIX_INFO
));
4431 pSMB
->InformationLevel
= cpu_to_le16(psrch_inf
->info_level
);
4432 pSMB
->ResumeKey
= psrch_inf
->resume_key
;
4433 pSMB
->SearchFlags
= cpu_to_le16(search_flags
);
4435 name_len
= psrch_inf
->resume_name_len
;
4437 if (name_len
< PATH_MAX
) {
4438 memcpy(pSMB
->ResumeFileName
, psrch_inf
->presume_name
, name_len
);
4439 byte_count
+= name_len
;
4440 /* 14 byte parm len above enough for 2 byte null terminator */
4441 pSMB
->ResumeFileName
[name_len
] = 0;
4442 pSMB
->ResumeFileName
[name_len
+1] = 0;
4445 goto FNext2_err_exit
;
4447 byte_count
= params
+ 1 /* pad */ ;
4448 pSMB
->TotalParameterCount
= cpu_to_le16(params
);
4449 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
4450 inc_rfc1001_len(pSMB
, byte_count
);
4451 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
4453 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
4454 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
4455 cifs_stats_inc(&tcon
->num_fnext
);
4458 psrch_inf
->endOfSearch
= true;
4459 cifs_buf_release(pSMB
);
4460 rc
= 0; /* search probably was closed at end of search*/
4462 cFYI(1, "FindNext returned = %d", rc
);
4463 } else { /* decode response */
4464 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
4469 /* BB fixme add lock for file (srch_info) struct here */
4470 if (pSMBr
->hdr
.Flags2
& SMBFLG2_UNICODE
)
4471 psrch_inf
->unicode
= true;
4473 psrch_inf
->unicode
= false;
4474 response_data
= (char *) &pSMBr
->hdr
.Protocol
+
4475 le16_to_cpu(pSMBr
->t2
.ParameterOffset
);
4476 parms
= (T2_FNEXT_RSP_PARMS
*)response_data
;
4477 response_data
= (char *)&pSMBr
->hdr
.Protocol
+
4478 le16_to_cpu(pSMBr
->t2
.DataOffset
);
4479 if (psrch_inf
->smallBuf
)
4480 cifs_small_buf_release(
4481 psrch_inf
->ntwrk_buf_start
);
4483 cifs_buf_release(psrch_inf
->ntwrk_buf_start
);
4484 psrch_inf
->srch_entries_start
= response_data
;
4485 psrch_inf
->ntwrk_buf_start
= (char *)pSMB
;
4486 psrch_inf
->smallBuf
= 0;
4487 if (parms
->EndofSearch
)
4488 psrch_inf
->endOfSearch
= true;
4490 psrch_inf
->endOfSearch
= false;
4491 psrch_inf
->entries_in_buffer
=
4492 le16_to_cpu(parms
->SearchCount
);
4493 psrch_inf
->index_of_last_entry
+=
4494 psrch_inf
->entries_in_buffer
;
4495 lnoff
= le16_to_cpu(parms
->LastNameOffset
);
4496 if (CIFSMaxBufSize
< lnoff
) {
4497 cERROR(1, "ignoring corrupt resume name");
4498 psrch_inf
->last_entry
= NULL
;
4501 psrch_inf
->last_entry
=
4502 psrch_inf
->srch_entries_start
+ lnoff
;
4504 /* cFYI(1, "fnxt2 entries in buf %d index_of_last %d",
4505 psrch_inf->entries_in_buffer, psrch_inf->index_of_last_entry); */
4507 /* BB fixme add unlock here */
4512 /* BB On error, should we leave previous search buf (and count and
4513 last entry fields) intact or free the previous one? */
4515 /* Note: On -EAGAIN error only caller can retry on handle based calls
4516 since file handle passed in no longer valid */
4519 cifs_buf_release(pSMB
);
4524 CIFSFindClose(const unsigned int xid
, struct cifs_tcon
*tcon
,
4525 const __u16 searchHandle
)
4528 FINDCLOSE_REQ
*pSMB
= NULL
;
4530 cFYI(1, "In CIFSSMBFindClose");
4531 rc
= small_smb_init(SMB_COM_FIND_CLOSE2
, 1, tcon
, (void **)&pSMB
);
4533 /* no sense returning error if session restarted
4534 as file handle has been closed */
4540 pSMB
->FileID
= searchHandle
;
4541 pSMB
->ByteCount
= 0;
4542 rc
= SendReceiveNoRsp(xid
, tcon
->ses
, (char *) pSMB
, 0);
4544 cERROR(1, "Send error in FindClose = %d", rc
);
4546 cifs_stats_inc(&tcon
->num_fclose
);
4548 /* Since session is dead, search handle closed on server already */
4556 CIFSGetSrvInodeNumber(const unsigned int xid
, struct cifs_tcon
*tcon
,
4557 const unsigned char *searchName
,
4558 __u64
*inode_number
,
4559 const struct nls_table
*nls_codepage
, int remap
)
4562 TRANSACTION2_QPI_REQ
*pSMB
= NULL
;
4563 TRANSACTION2_QPI_RSP
*pSMBr
= NULL
;
4564 int name_len
, bytes_returned
;
4565 __u16 params
, byte_count
;
4567 cFYI(1, "In GetSrvInodeNum for %s", searchName
);
4571 GetInodeNumberRetry
:
4572 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
4577 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
4579 cifsConvertToUTF16((__le16
*) pSMB
->FileName
,
4580 searchName
, PATH_MAX
, nls_codepage
,
4582 name_len
++; /* trailing null */
4584 } else { /* BB improve the check for buffer overruns BB */
4585 name_len
= strnlen(searchName
, PATH_MAX
);
4586 name_len
++; /* trailing null */
4587 strncpy(pSMB
->FileName
, searchName
, name_len
);
4590 params
= 2 /* level */ + 4 /* rsrvd */ + name_len
/* incl null */ ;
4591 pSMB
->TotalDataCount
= 0;
4592 pSMB
->MaxParameterCount
= cpu_to_le16(2);
4593 /* BB find exact max data count below from sess structure BB */
4594 pSMB
->MaxDataCount
= cpu_to_le16(4000);
4595 pSMB
->MaxSetupCount
= 0;
4599 pSMB
->Reserved2
= 0;
4600 pSMB
->ParameterOffset
= cpu_to_le16(offsetof(
4601 struct smb_com_transaction2_qpi_req
, InformationLevel
) - 4);
4602 pSMB
->DataCount
= 0;
4603 pSMB
->DataOffset
= 0;
4604 pSMB
->SetupCount
= 1;
4605 pSMB
->Reserved3
= 0;
4606 pSMB
->SubCommand
= cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION
);
4607 byte_count
= params
+ 1 /* pad */ ;
4608 pSMB
->TotalParameterCount
= cpu_to_le16(params
);
4609 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
4610 pSMB
->InformationLevel
= cpu_to_le16(SMB_QUERY_FILE_INTERNAL_INFO
);
4611 pSMB
->Reserved4
= 0;
4612 inc_rfc1001_len(pSMB
, byte_count
);
4613 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
4615 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
4616 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
4618 cFYI(1, "error %d in QueryInternalInfo", rc
);
4620 /* decode response */
4621 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
4622 /* BB also check enough total bytes returned */
4623 if (rc
|| get_bcc(&pSMBr
->hdr
) < 2)
4624 /* If rc should we check for EOPNOSUPP and
4625 disable the srvino flag? or in caller? */
4626 rc
= -EIO
; /* bad smb */
4628 __u16 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
4629 __u16 count
= le16_to_cpu(pSMBr
->t2
.DataCount
);
4630 struct file_internal_info
*pfinfo
;
4631 /* BB Do we need a cast or hash here ? */
4633 cFYI(1, "Illegal size ret in QryIntrnlInf");
4635 goto GetInodeNumOut
;
4637 pfinfo
= (struct file_internal_info
*)
4638 (data_offset
+ (char *) &pSMBr
->hdr
.Protocol
);
4639 *inode_number
= le64_to_cpu(pfinfo
->UniqueId
);
4643 cifs_buf_release(pSMB
);
4645 goto GetInodeNumberRetry
;
4649 /* parses DFS refferal V3 structure
4650 * caller is responsible for freeing target_nodes
4653 * on failure - errno
4656 parse_DFS_referrals(TRANSACTION2_GET_DFS_REFER_RSP
*pSMBr
,
4657 unsigned int *num_of_nodes
,
4658 struct dfs_info3_param
**target_nodes
,
4659 const struct nls_table
*nls_codepage
, int remap
,
4660 const char *searchName
)
4665 struct dfs_referral_level_3
*ref
;
4667 if (pSMBr
->hdr
.Flags2
& SMBFLG2_UNICODE
)
4671 *num_of_nodes
= le16_to_cpu(pSMBr
->NumberOfReferrals
);
4673 if (*num_of_nodes
< 1) {
4674 cERROR(1, "num_referrals: must be at least > 0,"
4675 "but we get num_referrals = %d", *num_of_nodes
);
4677 goto parse_DFS_referrals_exit
;
4680 ref
= (struct dfs_referral_level_3
*) &(pSMBr
->referrals
);
4681 if (ref
->VersionNumber
!= cpu_to_le16(3)) {
4682 cERROR(1, "Referrals of V%d version are not supported,"
4683 "should be V3", le16_to_cpu(ref
->VersionNumber
));
4685 goto parse_DFS_referrals_exit
;
4688 /* get the upper boundary of the resp buffer */
4689 data_end
= (char *)(&(pSMBr
->PathConsumed
)) +
4690 le16_to_cpu(pSMBr
->t2
.DataCount
);
4692 cFYI(1, "num_referrals: %d dfs flags: 0x%x ...",
4694 le32_to_cpu(pSMBr
->DFSFlags
));
4696 *target_nodes
= kzalloc(sizeof(struct dfs_info3_param
) *
4697 *num_of_nodes
, GFP_KERNEL
);
4698 if (*target_nodes
== NULL
) {
4699 cERROR(1, "Failed to allocate buffer for target_nodes");
4701 goto parse_DFS_referrals_exit
;
4704 /* collect necessary data from referrals */
4705 for (i
= 0; i
< *num_of_nodes
; i
++) {
4708 struct dfs_info3_param
*node
= (*target_nodes
)+i
;
4710 node
->flags
= le32_to_cpu(pSMBr
->DFSFlags
);
4712 __le16
*tmp
= kmalloc(strlen(searchName
)*2 + 2,
4716 goto parse_DFS_referrals_exit
;
4718 cifsConvertToUTF16((__le16
*) tmp
, searchName
,
4719 PATH_MAX
, nls_codepage
, remap
);
4720 node
->path_consumed
= cifs_utf16_bytes(tmp
,
4721 le16_to_cpu(pSMBr
->PathConsumed
),
4725 node
->path_consumed
= le16_to_cpu(pSMBr
->PathConsumed
);
4727 node
->server_type
= le16_to_cpu(ref
->ServerType
);
4728 node
->ref_flag
= le16_to_cpu(ref
->ReferralEntryFlags
);
4731 temp
= (char *)ref
+ le16_to_cpu(ref
->DfsPathOffset
);
4732 max_len
= data_end
- temp
;
4733 node
->path_name
= cifs_strndup_from_utf16(temp
, max_len
,
4734 is_unicode
, nls_codepage
);
4735 if (!node
->path_name
) {
4737 goto parse_DFS_referrals_exit
;
4740 /* copy link target UNC */
4741 temp
= (char *)ref
+ le16_to_cpu(ref
->NetworkAddressOffset
);
4742 max_len
= data_end
- temp
;
4743 node
->node_name
= cifs_strndup_from_utf16(temp
, max_len
,
4744 is_unicode
, nls_codepage
);
4745 if (!node
->node_name
) {
4747 goto parse_DFS_referrals_exit
;
4753 parse_DFS_referrals_exit
:
4755 free_dfs_info_array(*target_nodes
, *num_of_nodes
);
4756 *target_nodes
= NULL
;
4763 CIFSGetDFSRefer(const unsigned int xid
, struct cifs_ses
*ses
,
4764 const unsigned char *searchName
,
4765 struct dfs_info3_param
**target_nodes
,
4766 unsigned int *num_of_nodes
,
4767 const struct nls_table
*nls_codepage
, int remap
)
4769 /* TRANS2_GET_DFS_REFERRAL */
4770 TRANSACTION2_GET_DFS_REFER_REQ
*pSMB
= NULL
;
4771 TRANSACTION2_GET_DFS_REFER_RSP
*pSMBr
= NULL
;
4775 __u16 params
, byte_count
;
4777 *target_nodes
= NULL
;
4779 cFYI(1, "In GetDFSRefer the path %s", searchName
);
4783 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, NULL
, (void **) &pSMB
,
4788 /* server pointer checked in called function,
4789 but should never be null here anyway */
4790 pSMB
->hdr
.Mid
= get_next_mid(ses
->server
);
4791 pSMB
->hdr
.Tid
= ses
->ipc_tid
;
4792 pSMB
->hdr
.Uid
= ses
->Suid
;
4793 if (ses
->capabilities
& CAP_STATUS32
)
4794 pSMB
->hdr
.Flags2
|= SMBFLG2_ERR_STATUS
;
4795 if (ses
->capabilities
& CAP_DFS
)
4796 pSMB
->hdr
.Flags2
|= SMBFLG2_DFS
;
4798 if (ses
->capabilities
& CAP_UNICODE
) {
4799 pSMB
->hdr
.Flags2
|= SMBFLG2_UNICODE
;
4801 cifsConvertToUTF16((__le16
*) pSMB
->RequestFileName
,
4802 searchName
, PATH_MAX
, nls_codepage
,
4804 name_len
++; /* trailing null */
4806 } else { /* BB improve the check for buffer overruns BB */
4807 name_len
= strnlen(searchName
, PATH_MAX
);
4808 name_len
++; /* trailing null */
4809 strncpy(pSMB
->RequestFileName
, searchName
, name_len
);
4813 if (ses
->server
->sec_mode
&
4814 (SECMODE_SIGN_REQUIRED
| SECMODE_SIGN_ENABLED
))
4815 pSMB
->hdr
.Flags2
|= SMBFLG2_SECURITY_SIGNATURE
;
4818 pSMB
->hdr
.Uid
= ses
->Suid
;
4820 params
= 2 /* level */ + name_len
/*includes null */ ;
4821 pSMB
->TotalDataCount
= 0;
4822 pSMB
->DataCount
= 0;
4823 pSMB
->DataOffset
= 0;
4824 pSMB
->MaxParameterCount
= 0;
4825 /* BB find exact max SMB PDU from sess structure BB */
4826 pSMB
->MaxDataCount
= cpu_to_le16(4000);
4827 pSMB
->MaxSetupCount
= 0;
4831 pSMB
->Reserved2
= 0;
4832 pSMB
->ParameterOffset
= cpu_to_le16(offsetof(
4833 struct smb_com_transaction2_get_dfs_refer_req
, MaxReferralLevel
) - 4);
4834 pSMB
->SetupCount
= 1;
4835 pSMB
->Reserved3
= 0;
4836 pSMB
->SubCommand
= cpu_to_le16(TRANS2_GET_DFS_REFERRAL
);
4837 byte_count
= params
+ 3 /* pad */ ;
4838 pSMB
->ParameterCount
= cpu_to_le16(params
);
4839 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
4840 pSMB
->MaxReferralLevel
= cpu_to_le16(3);
4841 inc_rfc1001_len(pSMB
, byte_count
);
4842 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
4844 rc
= SendReceive(xid
, ses
, (struct smb_hdr
*) pSMB
,
4845 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
4847 cFYI(1, "Send error in GetDFSRefer = %d", rc
);
4850 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
4852 /* BB Also check if enough total bytes returned? */
4853 if (rc
|| get_bcc(&pSMBr
->hdr
) < 17) {
4854 rc
= -EIO
; /* bad smb */
4858 cFYI(1, "Decoding GetDFSRefer response BCC: %d Offset %d",
4859 get_bcc(&pSMBr
->hdr
),
4860 le16_to_cpu(pSMBr
->t2
.DataOffset
));
4862 /* parse returned result into more usable form */
4863 rc
= parse_DFS_referrals(pSMBr
, num_of_nodes
,
4864 target_nodes
, nls_codepage
, remap
,
4868 cifs_buf_release(pSMB
);
4876 /* Query File System Info such as free space to old servers such as Win 9x */
4878 SMBOldQFSInfo(const unsigned int xid
, struct cifs_tcon
*tcon
,
4879 struct kstatfs
*FSData
)
4881 /* level 0x01 SMB_QUERY_FILE_SYSTEM_INFO */
4882 TRANSACTION2_QFSI_REQ
*pSMB
= NULL
;
4883 TRANSACTION2_QFSI_RSP
*pSMBr
= NULL
;
4884 FILE_SYSTEM_ALLOC_INFO
*response_data
;
4886 int bytes_returned
= 0;
4887 __u16 params
, byte_count
;
4889 cFYI(1, "OldQFSInfo");
4891 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
4896 params
= 2; /* level */
4897 pSMB
->TotalDataCount
= 0;
4898 pSMB
->MaxParameterCount
= cpu_to_le16(2);
4899 pSMB
->MaxDataCount
= cpu_to_le16(1000);
4900 pSMB
->MaxSetupCount
= 0;
4904 pSMB
->Reserved2
= 0;
4905 byte_count
= params
+ 1 /* pad */ ;
4906 pSMB
->TotalParameterCount
= cpu_to_le16(params
);
4907 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
4908 pSMB
->ParameterOffset
= cpu_to_le16(offsetof(
4909 struct smb_com_transaction2_qfsi_req
, InformationLevel
) - 4);
4910 pSMB
->DataCount
= 0;
4911 pSMB
->DataOffset
= 0;
4912 pSMB
->SetupCount
= 1;
4913 pSMB
->Reserved3
= 0;
4914 pSMB
->SubCommand
= cpu_to_le16(TRANS2_QUERY_FS_INFORMATION
);
4915 pSMB
->InformationLevel
= cpu_to_le16(SMB_INFO_ALLOCATION
);
4916 inc_rfc1001_len(pSMB
, byte_count
);
4917 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
4919 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
4920 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
4922 cFYI(1, "Send error in QFSInfo = %d", rc
);
4923 } else { /* decode response */
4924 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
4926 if (rc
|| get_bcc(&pSMBr
->hdr
) < 18)
4927 rc
= -EIO
; /* bad smb */
4929 __u16 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
4930 cFYI(1, "qfsinf resp BCC: %d Offset %d",
4931 get_bcc(&pSMBr
->hdr
), data_offset
);
4933 response_data
= (FILE_SYSTEM_ALLOC_INFO
*)
4934 (((char *) &pSMBr
->hdr
.Protocol
) + data_offset
);
4936 le16_to_cpu(response_data
->BytesPerSector
) *
4937 le32_to_cpu(response_data
->
4938 SectorsPerAllocationUnit
);
4940 le32_to_cpu(response_data
->TotalAllocationUnits
);
4941 FSData
->f_bfree
= FSData
->f_bavail
=
4942 le32_to_cpu(response_data
->FreeAllocationUnits
);
4943 cFYI(1, "Blocks: %lld Free: %lld Block size %ld",
4944 (unsigned long long)FSData
->f_blocks
,
4945 (unsigned long long)FSData
->f_bfree
,
4949 cifs_buf_release(pSMB
);
4952 goto oldQFSInfoRetry
;
4958 CIFSSMBQFSInfo(const unsigned int xid
, struct cifs_tcon
*tcon
,
4959 struct kstatfs
*FSData
)
4961 /* level 0x103 SMB_QUERY_FILE_SYSTEM_INFO */
4962 TRANSACTION2_QFSI_REQ
*pSMB
= NULL
;
4963 TRANSACTION2_QFSI_RSP
*pSMBr
= NULL
;
4964 FILE_SYSTEM_INFO
*response_data
;
4966 int bytes_returned
= 0;
4967 __u16 params
, byte_count
;
4969 cFYI(1, "In QFSInfo");
4971 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
4976 params
= 2; /* level */
4977 pSMB
->TotalDataCount
= 0;
4978 pSMB
->MaxParameterCount
= cpu_to_le16(2);
4979 pSMB
->MaxDataCount
= cpu_to_le16(1000);
4980 pSMB
->MaxSetupCount
= 0;
4984 pSMB
->Reserved2
= 0;
4985 byte_count
= params
+ 1 /* pad */ ;
4986 pSMB
->TotalParameterCount
= cpu_to_le16(params
);
4987 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
4988 pSMB
->ParameterOffset
= cpu_to_le16(offsetof(
4989 struct smb_com_transaction2_qfsi_req
, InformationLevel
) - 4);
4990 pSMB
->DataCount
= 0;
4991 pSMB
->DataOffset
= 0;
4992 pSMB
->SetupCount
= 1;
4993 pSMB
->Reserved3
= 0;
4994 pSMB
->SubCommand
= cpu_to_le16(TRANS2_QUERY_FS_INFORMATION
);
4995 pSMB
->InformationLevel
= cpu_to_le16(SMB_QUERY_FS_SIZE_INFO
);
4996 inc_rfc1001_len(pSMB
, byte_count
);
4997 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
4999 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
5000 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
5002 cFYI(1, "Send error in QFSInfo = %d", rc
);
5003 } else { /* decode response */
5004 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
5006 if (rc
|| get_bcc(&pSMBr
->hdr
) < 24)
5007 rc
= -EIO
; /* bad smb */
5009 __u16 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
5013 *) (((char *) &pSMBr
->hdr
.Protocol
) +
5016 le32_to_cpu(response_data
->BytesPerSector
) *
5017 le32_to_cpu(response_data
->
5018 SectorsPerAllocationUnit
);
5020 le64_to_cpu(response_data
->TotalAllocationUnits
);
5021 FSData
->f_bfree
= FSData
->f_bavail
=
5022 le64_to_cpu(response_data
->FreeAllocationUnits
);
5023 cFYI(1, "Blocks: %lld Free: %lld Block size %ld",
5024 (unsigned long long)FSData
->f_blocks
,
5025 (unsigned long long)FSData
->f_bfree
,
5029 cifs_buf_release(pSMB
);
5038 CIFSSMBQFSAttributeInfo(const unsigned int xid
, struct cifs_tcon
*tcon
)
5040 /* level 0x105 SMB_QUERY_FILE_SYSTEM_INFO */
5041 TRANSACTION2_QFSI_REQ
*pSMB
= NULL
;
5042 TRANSACTION2_QFSI_RSP
*pSMBr
= NULL
;
5043 FILE_SYSTEM_ATTRIBUTE_INFO
*response_data
;
5045 int bytes_returned
= 0;
5046 __u16 params
, byte_count
;
5048 cFYI(1, "In QFSAttributeInfo");
5050 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
5055 params
= 2; /* level */
5056 pSMB
->TotalDataCount
= 0;
5057 pSMB
->MaxParameterCount
= cpu_to_le16(2);
5058 /* BB find exact max SMB PDU from sess structure BB */
5059 pSMB
->MaxDataCount
= cpu_to_le16(1000);
5060 pSMB
->MaxSetupCount
= 0;
5064 pSMB
->Reserved2
= 0;
5065 byte_count
= params
+ 1 /* pad */ ;
5066 pSMB
->TotalParameterCount
= cpu_to_le16(params
);
5067 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
5068 pSMB
->ParameterOffset
= cpu_to_le16(offsetof(
5069 struct smb_com_transaction2_qfsi_req
, InformationLevel
) - 4);
5070 pSMB
->DataCount
= 0;
5071 pSMB
->DataOffset
= 0;
5072 pSMB
->SetupCount
= 1;
5073 pSMB
->Reserved3
= 0;
5074 pSMB
->SubCommand
= cpu_to_le16(TRANS2_QUERY_FS_INFORMATION
);
5075 pSMB
->InformationLevel
= cpu_to_le16(SMB_QUERY_FS_ATTRIBUTE_INFO
);
5076 inc_rfc1001_len(pSMB
, byte_count
);
5077 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
5079 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
5080 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
5082 cERROR(1, "Send error in QFSAttributeInfo = %d", rc
);
5083 } else { /* decode response */
5084 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
5086 if (rc
|| get_bcc(&pSMBr
->hdr
) < 13) {
5087 /* BB also check if enough bytes returned */
5088 rc
= -EIO
; /* bad smb */
5090 __u16 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
5092 (FILE_SYSTEM_ATTRIBUTE_INFO
5093 *) (((char *) &pSMBr
->hdr
.Protocol
) +
5095 memcpy(&tcon
->fsAttrInfo
, response_data
,
5096 sizeof(FILE_SYSTEM_ATTRIBUTE_INFO
));
5099 cifs_buf_release(pSMB
);
5102 goto QFSAttributeRetry
;
5108 CIFSSMBQFSDeviceInfo(const unsigned int xid
, struct cifs_tcon
*tcon
)
5110 /* level 0x104 SMB_QUERY_FILE_SYSTEM_INFO */
5111 TRANSACTION2_QFSI_REQ
*pSMB
= NULL
;
5112 TRANSACTION2_QFSI_RSP
*pSMBr
= NULL
;
5113 FILE_SYSTEM_DEVICE_INFO
*response_data
;
5115 int bytes_returned
= 0;
5116 __u16 params
, byte_count
;
5118 cFYI(1, "In QFSDeviceInfo");
5120 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
5125 params
= 2; /* level */
5126 pSMB
->TotalDataCount
= 0;
5127 pSMB
->MaxParameterCount
= cpu_to_le16(2);
5128 /* BB find exact max SMB PDU from sess structure BB */
5129 pSMB
->MaxDataCount
= cpu_to_le16(1000);
5130 pSMB
->MaxSetupCount
= 0;
5134 pSMB
->Reserved2
= 0;
5135 byte_count
= params
+ 1 /* pad */ ;
5136 pSMB
->TotalParameterCount
= cpu_to_le16(params
);
5137 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
5138 pSMB
->ParameterOffset
= cpu_to_le16(offsetof(
5139 struct smb_com_transaction2_qfsi_req
, InformationLevel
) - 4);
5141 pSMB
->DataCount
= 0;
5142 pSMB
->DataOffset
= 0;
5143 pSMB
->SetupCount
= 1;
5144 pSMB
->Reserved3
= 0;
5145 pSMB
->SubCommand
= cpu_to_le16(TRANS2_QUERY_FS_INFORMATION
);
5146 pSMB
->InformationLevel
= cpu_to_le16(SMB_QUERY_FS_DEVICE_INFO
);
5147 inc_rfc1001_len(pSMB
, byte_count
);
5148 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
5150 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
5151 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
5153 cFYI(1, "Send error in QFSDeviceInfo = %d", rc
);
5154 } else { /* decode response */
5155 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
5157 if (rc
|| get_bcc(&pSMBr
->hdr
) <
5158 sizeof(FILE_SYSTEM_DEVICE_INFO
))
5159 rc
= -EIO
; /* bad smb */
5161 __u16 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
5163 (FILE_SYSTEM_DEVICE_INFO
*)
5164 (((char *) &pSMBr
->hdr
.Protocol
) +
5166 memcpy(&tcon
->fsDevInfo
, response_data
,
5167 sizeof(FILE_SYSTEM_DEVICE_INFO
));
5170 cifs_buf_release(pSMB
);
5173 goto QFSDeviceRetry
;
5179 CIFSSMBQFSUnixInfo(const unsigned int xid
, struct cifs_tcon
*tcon
)
5181 /* level 0x200 SMB_QUERY_CIFS_UNIX_INFO */
5182 TRANSACTION2_QFSI_REQ
*pSMB
= NULL
;
5183 TRANSACTION2_QFSI_RSP
*pSMBr
= NULL
;
5184 FILE_SYSTEM_UNIX_INFO
*response_data
;
5186 int bytes_returned
= 0;
5187 __u16 params
, byte_count
;
5189 cFYI(1, "In QFSUnixInfo");
5191 rc
= smb_init_no_reconnect(SMB_COM_TRANSACTION2
, 15, tcon
,
5192 (void **) &pSMB
, (void **) &pSMBr
);
5196 params
= 2; /* level */
5197 pSMB
->TotalDataCount
= 0;
5198 pSMB
->DataCount
= 0;
5199 pSMB
->DataOffset
= 0;
5200 pSMB
->MaxParameterCount
= cpu_to_le16(2);
5201 /* BB find exact max SMB PDU from sess structure BB */
5202 pSMB
->MaxDataCount
= cpu_to_le16(100);
5203 pSMB
->MaxSetupCount
= 0;
5207 pSMB
->Reserved2
= 0;
5208 byte_count
= params
+ 1 /* pad */ ;
5209 pSMB
->ParameterCount
= cpu_to_le16(params
);
5210 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
5211 pSMB
->ParameterOffset
= cpu_to_le16(offsetof(struct
5212 smb_com_transaction2_qfsi_req
, InformationLevel
) - 4);
5213 pSMB
->SetupCount
= 1;
5214 pSMB
->Reserved3
= 0;
5215 pSMB
->SubCommand
= cpu_to_le16(TRANS2_QUERY_FS_INFORMATION
);
5216 pSMB
->InformationLevel
= cpu_to_le16(SMB_QUERY_CIFS_UNIX_INFO
);
5217 inc_rfc1001_len(pSMB
, byte_count
);
5218 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
5220 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
5221 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
5223 cERROR(1, "Send error in QFSUnixInfo = %d", rc
);
5224 } else { /* decode response */
5225 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
5227 if (rc
|| get_bcc(&pSMBr
->hdr
) < 13) {
5228 rc
= -EIO
; /* bad smb */
5230 __u16 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
5232 (FILE_SYSTEM_UNIX_INFO
5233 *) (((char *) &pSMBr
->hdr
.Protocol
) +
5235 memcpy(&tcon
->fsUnixInfo
, response_data
,
5236 sizeof(FILE_SYSTEM_UNIX_INFO
));
5239 cifs_buf_release(pSMB
);
5249 CIFSSMBSetFSUnixInfo(const unsigned int xid
, struct cifs_tcon
*tcon
, __u64 cap
)
5251 /* level 0x200 SMB_SET_CIFS_UNIX_INFO */
5252 TRANSACTION2_SETFSI_REQ
*pSMB
= NULL
;
5253 TRANSACTION2_SETFSI_RSP
*pSMBr
= NULL
;
5255 int bytes_returned
= 0;
5256 __u16 params
, param_offset
, offset
, byte_count
;
5258 cFYI(1, "In SETFSUnixInfo");
5260 /* BB switch to small buf init to save memory */
5261 rc
= smb_init_no_reconnect(SMB_COM_TRANSACTION2
, 15, tcon
,
5262 (void **) &pSMB
, (void **) &pSMBr
);
5266 params
= 4; /* 2 bytes zero followed by info level. */
5267 pSMB
->MaxSetupCount
= 0;
5271 pSMB
->Reserved2
= 0;
5272 param_offset
= offsetof(struct smb_com_transaction2_setfsi_req
, FileNum
)
5274 offset
= param_offset
+ params
;
5276 pSMB
->MaxParameterCount
= cpu_to_le16(4);
5277 /* BB find exact max SMB PDU from sess structure BB */
5278 pSMB
->MaxDataCount
= cpu_to_le16(100);
5279 pSMB
->SetupCount
= 1;
5280 pSMB
->Reserved3
= 0;
5281 pSMB
->SubCommand
= cpu_to_le16(TRANS2_SET_FS_INFORMATION
);
5282 byte_count
= 1 /* pad */ + params
+ 12;
5284 pSMB
->DataCount
= cpu_to_le16(12);
5285 pSMB
->ParameterCount
= cpu_to_le16(params
);
5286 pSMB
->TotalDataCount
= pSMB
->DataCount
;
5287 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
5288 pSMB
->ParameterOffset
= cpu_to_le16(param_offset
);
5289 pSMB
->DataOffset
= cpu_to_le16(offset
);
5293 pSMB
->InformationLevel
= cpu_to_le16(SMB_SET_CIFS_UNIX_INFO
);
5296 pSMB
->ClientUnixMajor
= cpu_to_le16(CIFS_UNIX_MAJOR_VERSION
);
5297 pSMB
->ClientUnixMinor
= cpu_to_le16(CIFS_UNIX_MINOR_VERSION
);
5298 pSMB
->ClientUnixCap
= cpu_to_le64(cap
);
5300 inc_rfc1001_len(pSMB
, byte_count
);
5301 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
5303 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
5304 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
5306 cERROR(1, "Send error in SETFSUnixInfo = %d", rc
);
5307 } else { /* decode response */
5308 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
5310 rc
= -EIO
; /* bad smb */
5312 cifs_buf_release(pSMB
);
5315 goto SETFSUnixRetry
;
5323 CIFSSMBQFSPosixInfo(const unsigned int xid
, struct cifs_tcon
*tcon
,
5324 struct kstatfs
*FSData
)
5326 /* level 0x201 SMB_QUERY_CIFS_POSIX_INFO */
5327 TRANSACTION2_QFSI_REQ
*pSMB
= NULL
;
5328 TRANSACTION2_QFSI_RSP
*pSMBr
= NULL
;
5329 FILE_SYSTEM_POSIX_INFO
*response_data
;
5331 int bytes_returned
= 0;
5332 __u16 params
, byte_count
;
5334 cFYI(1, "In QFSPosixInfo");
5336 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
5341 params
= 2; /* level */
5342 pSMB
->TotalDataCount
= 0;
5343 pSMB
->DataCount
= 0;
5344 pSMB
->DataOffset
= 0;
5345 pSMB
->MaxParameterCount
= cpu_to_le16(2);
5346 /* BB find exact max SMB PDU from sess structure BB */
5347 pSMB
->MaxDataCount
= cpu_to_le16(100);
5348 pSMB
->MaxSetupCount
= 0;
5352 pSMB
->Reserved2
= 0;
5353 byte_count
= params
+ 1 /* pad */ ;
5354 pSMB
->ParameterCount
= cpu_to_le16(params
);
5355 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
5356 pSMB
->ParameterOffset
= cpu_to_le16(offsetof(struct
5357 smb_com_transaction2_qfsi_req
, InformationLevel
) - 4);
5358 pSMB
->SetupCount
= 1;
5359 pSMB
->Reserved3
= 0;
5360 pSMB
->SubCommand
= cpu_to_le16(TRANS2_QUERY_FS_INFORMATION
);
5361 pSMB
->InformationLevel
= cpu_to_le16(SMB_QUERY_POSIX_FS_INFO
);
5362 inc_rfc1001_len(pSMB
, byte_count
);
5363 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
5365 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
5366 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
5368 cFYI(1, "Send error in QFSUnixInfo = %d", rc
);
5369 } else { /* decode response */
5370 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
5372 if (rc
|| get_bcc(&pSMBr
->hdr
) < 13) {
5373 rc
= -EIO
; /* bad smb */
5375 __u16 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
5377 (FILE_SYSTEM_POSIX_INFO
5378 *) (((char *) &pSMBr
->hdr
.Protocol
) +
5381 le32_to_cpu(response_data
->BlockSize
);
5383 le64_to_cpu(response_data
->TotalBlocks
);
5385 le64_to_cpu(response_data
->BlocksAvail
);
5386 if (response_data
->UserBlocksAvail
== cpu_to_le64(-1)) {
5387 FSData
->f_bavail
= FSData
->f_bfree
;
5390 le64_to_cpu(response_data
->UserBlocksAvail
);
5392 if (response_data
->TotalFileNodes
!= cpu_to_le64(-1))
5394 le64_to_cpu(response_data
->TotalFileNodes
);
5395 if (response_data
->FreeFileNodes
!= cpu_to_le64(-1))
5397 le64_to_cpu(response_data
->FreeFileNodes
);
5400 cifs_buf_release(pSMB
);
5409 /* We can not use write of zero bytes trick to
5410 set file size due to need for large file support. Also note that
5411 this SetPathInfo is preferred to SetFileInfo based method in next
5412 routine which is only needed to work around a sharing violation bug
5413 in Samba which this routine can run into */
5416 CIFSSMBSetEOF(const unsigned int xid
, struct cifs_tcon
*tcon
,
5417 const char *fileName
, __u64 size
, bool SetAllocation
,
5418 const struct nls_table
*nls_codepage
, int remap
)
5420 struct smb_com_transaction2_spi_req
*pSMB
= NULL
;
5421 struct smb_com_transaction2_spi_rsp
*pSMBr
= NULL
;
5422 struct file_end_of_file_info
*parm_data
;
5425 int bytes_returned
= 0;
5426 __u16 params
, byte_count
, data_count
, param_offset
, offset
;
5428 cFYI(1, "In SetEOF");
5430 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
5435 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
5437 cifsConvertToUTF16((__le16
*) pSMB
->FileName
, fileName
,
5438 PATH_MAX
, nls_codepage
, remap
);
5439 name_len
++; /* trailing null */
5441 } else { /* BB improve the check for buffer overruns BB */
5442 name_len
= strnlen(fileName
, PATH_MAX
);
5443 name_len
++; /* trailing null */
5444 strncpy(pSMB
->FileName
, fileName
, name_len
);
5446 params
= 6 + name_len
;
5447 data_count
= sizeof(struct file_end_of_file_info
);
5448 pSMB
->MaxParameterCount
= cpu_to_le16(2);
5449 pSMB
->MaxDataCount
= cpu_to_le16(4100);
5450 pSMB
->MaxSetupCount
= 0;
5454 pSMB
->Reserved2
= 0;
5455 param_offset
= offsetof(struct smb_com_transaction2_spi_req
,
5456 InformationLevel
) - 4;
5457 offset
= param_offset
+ params
;
5458 if (SetAllocation
) {
5459 if (tcon
->ses
->capabilities
& CAP_INFOLEVEL_PASSTHRU
)
5460 pSMB
->InformationLevel
=
5461 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2
);
5463 pSMB
->InformationLevel
=
5464 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO
);
5465 } else /* Set File Size */ {
5466 if (tcon
->ses
->capabilities
& CAP_INFOLEVEL_PASSTHRU
)
5467 pSMB
->InformationLevel
=
5468 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO2
);
5470 pSMB
->InformationLevel
=
5471 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO
);
5475 (struct file_end_of_file_info
*) (((char *) &pSMB
->hdr
.Protocol
) +
5477 pSMB
->ParameterOffset
= cpu_to_le16(param_offset
);
5478 pSMB
->DataOffset
= cpu_to_le16(offset
);
5479 pSMB
->SetupCount
= 1;
5480 pSMB
->Reserved3
= 0;
5481 pSMB
->SubCommand
= cpu_to_le16(TRANS2_SET_PATH_INFORMATION
);
5482 byte_count
= 3 /* pad */ + params
+ data_count
;
5483 pSMB
->DataCount
= cpu_to_le16(data_count
);
5484 pSMB
->TotalDataCount
= pSMB
->DataCount
;
5485 pSMB
->ParameterCount
= cpu_to_le16(params
);
5486 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
5487 pSMB
->Reserved4
= 0;
5488 inc_rfc1001_len(pSMB
, byte_count
);
5489 parm_data
->FileSize
= cpu_to_le64(size
);
5490 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
5491 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
5492 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
5494 cFYI(1, "SetPathInfo (file size) returned %d", rc
);
5496 cifs_buf_release(pSMB
);
5505 CIFSSMBSetFileSize(const unsigned int xid
, struct cifs_tcon
*tcon
, __u64 size
,
5506 __u16 fid
, __u32 pid_of_opener
, bool SetAllocation
)
5508 struct smb_com_transaction2_sfi_req
*pSMB
= NULL
;
5509 struct file_end_of_file_info
*parm_data
;
5511 __u16 params
, param_offset
, offset
, byte_count
, count
;
5513 cFYI(1, "SetFileSize (via SetFileInfo) %lld",
5515 rc
= small_smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
);
5520 pSMB
->hdr
.Pid
= cpu_to_le16((__u16
)pid_of_opener
);
5521 pSMB
->hdr
.PidHigh
= cpu_to_le16((__u16
)(pid_of_opener
>> 16));
5524 pSMB
->MaxSetupCount
= 0;
5528 pSMB
->Reserved2
= 0;
5529 param_offset
= offsetof(struct smb_com_transaction2_sfi_req
, Fid
) - 4;
5530 offset
= param_offset
+ params
;
5532 count
= sizeof(struct file_end_of_file_info
);
5533 pSMB
->MaxParameterCount
= cpu_to_le16(2);
5534 /* BB find exact max SMB PDU from sess structure BB */
5535 pSMB
->MaxDataCount
= cpu_to_le16(1000);
5536 pSMB
->SetupCount
= 1;
5537 pSMB
->Reserved3
= 0;
5538 pSMB
->SubCommand
= cpu_to_le16(TRANS2_SET_FILE_INFORMATION
);
5539 byte_count
= 3 /* pad */ + params
+ count
;
5540 pSMB
->DataCount
= cpu_to_le16(count
);
5541 pSMB
->ParameterCount
= cpu_to_le16(params
);
5542 pSMB
->TotalDataCount
= pSMB
->DataCount
;
5543 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
5544 pSMB
->ParameterOffset
= cpu_to_le16(param_offset
);
5546 (struct file_end_of_file_info
*) (((char *) &pSMB
->hdr
.Protocol
)
5548 pSMB
->DataOffset
= cpu_to_le16(offset
);
5549 parm_data
->FileSize
= cpu_to_le64(size
);
5551 if (SetAllocation
) {
5552 if (tcon
->ses
->capabilities
& CAP_INFOLEVEL_PASSTHRU
)
5553 pSMB
->InformationLevel
=
5554 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2
);
5556 pSMB
->InformationLevel
=
5557 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO
);
5558 } else /* Set File Size */ {
5559 if (tcon
->ses
->capabilities
& CAP_INFOLEVEL_PASSTHRU
)
5560 pSMB
->InformationLevel
=
5561 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO2
);
5563 pSMB
->InformationLevel
=
5564 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO
);
5566 pSMB
->Reserved4
= 0;
5567 inc_rfc1001_len(pSMB
, byte_count
);
5568 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
5569 rc
= SendReceiveNoRsp(xid
, tcon
->ses
, (char *) pSMB
, 0);
5571 cFYI(1, "Send error in SetFileInfo (SetFileSize) = %d", rc
);
5574 /* Note: On -EAGAIN error only caller can retry on handle based calls
5575 since file handle passed in no longer valid */
5580 /* Some legacy servers such as NT4 require that the file times be set on
5581 an open handle, rather than by pathname - this is awkward due to
5582 potential access conflicts on the open, but it is unavoidable for these
5583 old servers since the only other choice is to go from 100 nanosecond DCE
5584 time and resort to the original setpathinfo level which takes the ancient
5585 DOS time format with 2 second granularity */
5587 CIFSSMBSetFileInfo(const unsigned int xid
, struct cifs_tcon
*tcon
,
5588 const FILE_BASIC_INFO
*data
, __u16 fid
, __u32 pid_of_opener
)
5590 struct smb_com_transaction2_sfi_req
*pSMB
= NULL
;
5593 __u16 params
, param_offset
, offset
, byte_count
, count
;
5595 cFYI(1, "Set Times (via SetFileInfo)");
5596 rc
= small_smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
);
5601 pSMB
->hdr
.Pid
= cpu_to_le16((__u16
)pid_of_opener
);
5602 pSMB
->hdr
.PidHigh
= cpu_to_le16((__u16
)(pid_of_opener
>> 16));
5605 pSMB
->MaxSetupCount
= 0;
5609 pSMB
->Reserved2
= 0;
5610 param_offset
= offsetof(struct smb_com_transaction2_sfi_req
, Fid
) - 4;
5611 offset
= param_offset
+ params
;
5613 data_offset
= (char *)pSMB
+
5614 offsetof(struct smb_hdr
, Protocol
) + offset
;
5616 count
= sizeof(FILE_BASIC_INFO
);
5617 pSMB
->MaxParameterCount
= cpu_to_le16(2);
5618 /* BB find max SMB PDU from sess */
5619 pSMB
->MaxDataCount
= cpu_to_le16(1000);
5620 pSMB
->SetupCount
= 1;
5621 pSMB
->Reserved3
= 0;
5622 pSMB
->SubCommand
= cpu_to_le16(TRANS2_SET_FILE_INFORMATION
);
5623 byte_count
= 3 /* pad */ + params
+ count
;
5624 pSMB
->DataCount
= cpu_to_le16(count
);
5625 pSMB
->ParameterCount
= cpu_to_le16(params
);
5626 pSMB
->TotalDataCount
= pSMB
->DataCount
;
5627 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
5628 pSMB
->ParameterOffset
= cpu_to_le16(param_offset
);
5629 pSMB
->DataOffset
= cpu_to_le16(offset
);
5631 if (tcon
->ses
->capabilities
& CAP_INFOLEVEL_PASSTHRU
)
5632 pSMB
->InformationLevel
= cpu_to_le16(SMB_SET_FILE_BASIC_INFO2
);
5634 pSMB
->InformationLevel
= cpu_to_le16(SMB_SET_FILE_BASIC_INFO
);
5635 pSMB
->Reserved4
= 0;
5636 inc_rfc1001_len(pSMB
, byte_count
);
5637 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
5638 memcpy(data_offset
, data
, sizeof(FILE_BASIC_INFO
));
5639 rc
= SendReceiveNoRsp(xid
, tcon
->ses
, (char *) pSMB
, 0);
5641 cFYI(1, "Send error in Set Time (SetFileInfo) = %d", rc
);
5643 /* Note: On -EAGAIN error only caller can retry on handle based calls
5644 since file handle passed in no longer valid */
5650 CIFSSMBSetFileDisposition(const unsigned int xid
, struct cifs_tcon
*tcon
,
5651 bool delete_file
, __u16 fid
, __u32 pid_of_opener
)
5653 struct smb_com_transaction2_sfi_req
*pSMB
= NULL
;
5656 __u16 params
, param_offset
, offset
, byte_count
, count
;
5658 cFYI(1, "Set File Disposition (via SetFileInfo)");
5659 rc
= small_smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
);
5664 pSMB
->hdr
.Pid
= cpu_to_le16((__u16
)pid_of_opener
);
5665 pSMB
->hdr
.PidHigh
= cpu_to_le16((__u16
)(pid_of_opener
>> 16));
5668 pSMB
->MaxSetupCount
= 0;
5672 pSMB
->Reserved2
= 0;
5673 param_offset
= offsetof(struct smb_com_transaction2_sfi_req
, Fid
) - 4;
5674 offset
= param_offset
+ params
;
5676 data_offset
= (char *) (&pSMB
->hdr
.Protocol
) + offset
;
5679 pSMB
->MaxParameterCount
= cpu_to_le16(2);
5680 /* BB find max SMB PDU from sess */
5681 pSMB
->MaxDataCount
= cpu_to_le16(1000);
5682 pSMB
->SetupCount
= 1;
5683 pSMB
->Reserved3
= 0;
5684 pSMB
->SubCommand
= cpu_to_le16(TRANS2_SET_FILE_INFORMATION
);
5685 byte_count
= 3 /* pad */ + params
+ count
;
5686 pSMB
->DataCount
= cpu_to_le16(count
);
5687 pSMB
->ParameterCount
= cpu_to_le16(params
);
5688 pSMB
->TotalDataCount
= pSMB
->DataCount
;
5689 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
5690 pSMB
->ParameterOffset
= cpu_to_le16(param_offset
);
5691 pSMB
->DataOffset
= cpu_to_le16(offset
);
5693 pSMB
->InformationLevel
= cpu_to_le16(SMB_SET_FILE_DISPOSITION_INFO
);
5694 pSMB
->Reserved4
= 0;
5695 inc_rfc1001_len(pSMB
, byte_count
);
5696 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
5697 *data_offset
= delete_file
? 1 : 0;
5698 rc
= SendReceiveNoRsp(xid
, tcon
->ses
, (char *) pSMB
, 0);
5700 cFYI(1, "Send error in SetFileDisposition = %d", rc
);
5706 CIFSSMBSetPathInfo(const unsigned int xid
, struct cifs_tcon
*tcon
,
5707 const char *fileName
, const FILE_BASIC_INFO
*data
,
5708 const struct nls_table
*nls_codepage
, int remap
)
5710 TRANSACTION2_SPI_REQ
*pSMB
= NULL
;
5711 TRANSACTION2_SPI_RSP
*pSMBr
= NULL
;
5714 int bytes_returned
= 0;
5716 __u16 params
, param_offset
, offset
, byte_count
, count
;
5718 cFYI(1, "In SetTimes");
5721 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
5726 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
5728 cifsConvertToUTF16((__le16
*) pSMB
->FileName
, fileName
,
5729 PATH_MAX
, nls_codepage
, remap
);
5730 name_len
++; /* trailing null */
5732 } else { /* BB improve the check for buffer overruns BB */
5733 name_len
= strnlen(fileName
, PATH_MAX
);
5734 name_len
++; /* trailing null */
5735 strncpy(pSMB
->FileName
, fileName
, name_len
);
5738 params
= 6 + name_len
;
5739 count
= sizeof(FILE_BASIC_INFO
);
5740 pSMB
->MaxParameterCount
= cpu_to_le16(2);
5741 /* BB find max SMB PDU from sess structure BB */
5742 pSMB
->MaxDataCount
= cpu_to_le16(1000);
5743 pSMB
->MaxSetupCount
= 0;
5747 pSMB
->Reserved2
= 0;
5748 param_offset
= offsetof(struct smb_com_transaction2_spi_req
,
5749 InformationLevel
) - 4;
5750 offset
= param_offset
+ params
;
5751 data_offset
= (char *) (&pSMB
->hdr
.Protocol
) + offset
;
5752 pSMB
->ParameterOffset
= cpu_to_le16(param_offset
);
5753 pSMB
->DataOffset
= cpu_to_le16(offset
);
5754 pSMB
->SetupCount
= 1;
5755 pSMB
->Reserved3
= 0;
5756 pSMB
->SubCommand
= cpu_to_le16(TRANS2_SET_PATH_INFORMATION
);
5757 byte_count
= 3 /* pad */ + params
+ count
;
5759 pSMB
->DataCount
= cpu_to_le16(count
);
5760 pSMB
->ParameterCount
= cpu_to_le16(params
);
5761 pSMB
->TotalDataCount
= pSMB
->DataCount
;
5762 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
5763 if (tcon
->ses
->capabilities
& CAP_INFOLEVEL_PASSTHRU
)
5764 pSMB
->InformationLevel
= cpu_to_le16(SMB_SET_FILE_BASIC_INFO2
);
5766 pSMB
->InformationLevel
= cpu_to_le16(SMB_SET_FILE_BASIC_INFO
);
5767 pSMB
->Reserved4
= 0;
5768 inc_rfc1001_len(pSMB
, byte_count
);
5769 memcpy(data_offset
, data
, sizeof(FILE_BASIC_INFO
));
5770 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
5771 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
5772 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
5774 cFYI(1, "SetPathInfo (times) returned %d", rc
);
5776 cifs_buf_release(pSMB
);
5784 /* Can not be used to set time stamps yet (due to old DOS time format) */
5785 /* Can be used to set attributes */
5786 #if 0 /* Possibly not needed - since it turns out that strangely NT4 has a bug
5787 handling it anyway and NT4 was what we thought it would be needed for
5788 Do not delete it until we prove whether needed for Win9x though */
5790 CIFSSMBSetAttrLegacy(unsigned int xid
, struct cifs_tcon
*tcon
, char *fileName
,
5791 __u16 dos_attrs
, const struct nls_table
*nls_codepage
)
5793 SETATTR_REQ
*pSMB
= NULL
;
5794 SETATTR_RSP
*pSMBr
= NULL
;
5799 cFYI(1, "In SetAttrLegacy");
5802 rc
= smb_init(SMB_COM_SETATTR
, 8, tcon
, (void **) &pSMB
,
5807 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
5809 ConvertToUTF16((__le16
*) pSMB
->fileName
, fileName
,
5810 PATH_MAX
, nls_codepage
);
5811 name_len
++; /* trailing null */
5813 } else { /* BB improve the check for buffer overruns BB */
5814 name_len
= strnlen(fileName
, PATH_MAX
);
5815 name_len
++; /* trailing null */
5816 strncpy(pSMB
->fileName
, fileName
, name_len
);
5818 pSMB
->attr
= cpu_to_le16(dos_attrs
);
5819 pSMB
->BufferFormat
= 0x04;
5820 inc_rfc1001_len(pSMB
, name_len
+ 1);
5821 pSMB
->ByteCount
= cpu_to_le16(name_len
+ 1);
5822 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
5823 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
5825 cFYI(1, "Error in LegacySetAttr = %d", rc
);
5827 cifs_buf_release(pSMB
);
5830 goto SetAttrLgcyRetry
;
5834 #endif /* temporarily unneeded SetAttr legacy function */
5837 cifs_fill_unix_set_info(FILE_UNIX_BASIC_INFO
*data_offset
,
5838 const struct cifs_unix_set_info_args
*args
)
5840 u64 mode
= args
->mode
;
5843 * Samba server ignores set of file size to zero due to bugs in some
5844 * older clients, but we should be precise - we use SetFileSize to
5845 * set file size and do not want to truncate file size to zero
5846 * accidentally as happened on one Samba server beta by putting
5847 * zero instead of -1 here
5849 data_offset
->EndOfFile
= cpu_to_le64(NO_CHANGE_64
);
5850 data_offset
->NumOfBytes
= cpu_to_le64(NO_CHANGE_64
);
5851 data_offset
->LastStatusChange
= cpu_to_le64(args
->ctime
);
5852 data_offset
->LastAccessTime
= cpu_to_le64(args
->atime
);
5853 data_offset
->LastModificationTime
= cpu_to_le64(args
->mtime
);
5854 data_offset
->Uid
= cpu_to_le64(args
->uid
);
5855 data_offset
->Gid
= cpu_to_le64(args
->gid
);
5856 /* better to leave device as zero when it is */
5857 data_offset
->DevMajor
= cpu_to_le64(MAJOR(args
->device
));
5858 data_offset
->DevMinor
= cpu_to_le64(MINOR(args
->device
));
5859 data_offset
->Permissions
= cpu_to_le64(mode
);
5862 data_offset
->Type
= cpu_to_le32(UNIX_FILE
);
5863 else if (S_ISDIR(mode
))
5864 data_offset
->Type
= cpu_to_le32(UNIX_DIR
);
5865 else if (S_ISLNK(mode
))
5866 data_offset
->Type
= cpu_to_le32(UNIX_SYMLINK
);
5867 else if (S_ISCHR(mode
))
5868 data_offset
->Type
= cpu_to_le32(UNIX_CHARDEV
);
5869 else if (S_ISBLK(mode
))
5870 data_offset
->Type
= cpu_to_le32(UNIX_BLOCKDEV
);
5871 else if (S_ISFIFO(mode
))
5872 data_offset
->Type
= cpu_to_le32(UNIX_FIFO
);
5873 else if (S_ISSOCK(mode
))
5874 data_offset
->Type
= cpu_to_le32(UNIX_SOCKET
);
5878 CIFSSMBUnixSetFileInfo(const unsigned int xid
, struct cifs_tcon
*tcon
,
5879 const struct cifs_unix_set_info_args
*args
,
5880 u16 fid
, u32 pid_of_opener
)
5882 struct smb_com_transaction2_sfi_req
*pSMB
= NULL
;
5885 u16 params
, param_offset
, offset
, byte_count
, count
;
5887 cFYI(1, "Set Unix Info (via SetFileInfo)");
5888 rc
= small_smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
);
5893 pSMB
->hdr
.Pid
= cpu_to_le16((__u16
)pid_of_opener
);
5894 pSMB
->hdr
.PidHigh
= cpu_to_le16((__u16
)(pid_of_opener
>> 16));
5897 pSMB
->MaxSetupCount
= 0;
5901 pSMB
->Reserved2
= 0;
5902 param_offset
= offsetof(struct smb_com_transaction2_sfi_req
, Fid
) - 4;
5903 offset
= param_offset
+ params
;
5905 data_offset
= (char *)pSMB
+
5906 offsetof(struct smb_hdr
, Protocol
) + offset
;
5908 count
= sizeof(FILE_UNIX_BASIC_INFO
);
5910 pSMB
->MaxParameterCount
= cpu_to_le16(2);
5911 /* BB find max SMB PDU from sess */
5912 pSMB
->MaxDataCount
= cpu_to_le16(1000);
5913 pSMB
->SetupCount
= 1;
5914 pSMB
->Reserved3
= 0;
5915 pSMB
->SubCommand
= cpu_to_le16(TRANS2_SET_FILE_INFORMATION
);
5916 byte_count
= 3 /* pad */ + params
+ count
;
5917 pSMB
->DataCount
= cpu_to_le16(count
);
5918 pSMB
->ParameterCount
= cpu_to_le16(params
);
5919 pSMB
->TotalDataCount
= pSMB
->DataCount
;
5920 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
5921 pSMB
->ParameterOffset
= cpu_to_le16(param_offset
);
5922 pSMB
->DataOffset
= cpu_to_le16(offset
);
5924 pSMB
->InformationLevel
= cpu_to_le16(SMB_SET_FILE_UNIX_BASIC
);
5925 pSMB
->Reserved4
= 0;
5926 inc_rfc1001_len(pSMB
, byte_count
);
5927 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
5929 cifs_fill_unix_set_info((FILE_UNIX_BASIC_INFO
*)data_offset
, args
);
5931 rc
= SendReceiveNoRsp(xid
, tcon
->ses
, (char *) pSMB
, 0);
5933 cFYI(1, "Send error in Set Time (SetFileInfo) = %d", rc
);
5935 /* Note: On -EAGAIN error only caller can retry on handle based calls
5936 since file handle passed in no longer valid */
5942 CIFSSMBUnixSetPathInfo(const unsigned int xid
, struct cifs_tcon
*tcon
,
5944 const struct cifs_unix_set_info_args
*args
,
5945 const struct nls_table
*nls_codepage
, int remap
)
5947 TRANSACTION2_SPI_REQ
*pSMB
= NULL
;
5948 TRANSACTION2_SPI_RSP
*pSMBr
= NULL
;
5951 int bytes_returned
= 0;
5952 FILE_UNIX_BASIC_INFO
*data_offset
;
5953 __u16 params
, param_offset
, offset
, count
, byte_count
;
5955 cFYI(1, "In SetUID/GID/Mode");
5957 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
5962 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
5964 cifsConvertToUTF16((__le16
*) pSMB
->FileName
, fileName
,
5965 PATH_MAX
, nls_codepage
, remap
);
5966 name_len
++; /* trailing null */
5968 } else { /* BB improve the check for buffer overruns BB */
5969 name_len
= strnlen(fileName
, PATH_MAX
);
5970 name_len
++; /* trailing null */
5971 strncpy(pSMB
->FileName
, fileName
, name_len
);
5974 params
= 6 + name_len
;
5975 count
= sizeof(FILE_UNIX_BASIC_INFO
);
5976 pSMB
->MaxParameterCount
= cpu_to_le16(2);
5977 /* BB find max SMB PDU from sess structure BB */
5978 pSMB
->MaxDataCount
= cpu_to_le16(1000);
5979 pSMB
->MaxSetupCount
= 0;
5983 pSMB
->Reserved2
= 0;
5984 param_offset
= offsetof(struct smb_com_transaction2_spi_req
,
5985 InformationLevel
) - 4;
5986 offset
= param_offset
+ params
;
5988 (FILE_UNIX_BASIC_INFO
*) ((char *) &pSMB
->hdr
.Protocol
+
5990 memset(data_offset
, 0, count
);
5991 pSMB
->DataOffset
= cpu_to_le16(offset
);
5992 pSMB
->ParameterOffset
= cpu_to_le16(param_offset
);
5993 pSMB
->SetupCount
= 1;
5994 pSMB
->Reserved3
= 0;
5995 pSMB
->SubCommand
= cpu_to_le16(TRANS2_SET_PATH_INFORMATION
);
5996 byte_count
= 3 /* pad */ + params
+ count
;
5997 pSMB
->ParameterCount
= cpu_to_le16(params
);
5998 pSMB
->DataCount
= cpu_to_le16(count
);
5999 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
6000 pSMB
->TotalDataCount
= pSMB
->DataCount
;
6001 pSMB
->InformationLevel
= cpu_to_le16(SMB_SET_FILE_UNIX_BASIC
);
6002 pSMB
->Reserved4
= 0;
6003 inc_rfc1001_len(pSMB
, byte_count
);
6005 cifs_fill_unix_set_info(data_offset
, args
);
6007 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
6008 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
6009 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
6011 cFYI(1, "SetPathInfo (perms) returned %d", rc
);
6013 cifs_buf_release(pSMB
);
6019 #ifdef CONFIG_CIFS_XATTR
6021 * Do a path-based QUERY_ALL_EAS call and parse the result. This is a common
6022 * function used by listxattr and getxattr type calls. When ea_name is set,
6023 * it looks for that attribute name and stuffs that value into the EAData
6024 * buffer. When ea_name is NULL, it stuffs a list of attribute names into the
6025 * buffer. In both cases, the return value is either the length of the
6026 * resulting data or a negative error code. If EAData is a NULL pointer then
6027 * the data isn't copied to it, but the length is returned.
6030 CIFSSMBQAllEAs(const unsigned int xid
, struct cifs_tcon
*tcon
,
6031 const unsigned char *searchName
, const unsigned char *ea_name
,
6032 char *EAData
, size_t buf_size
,
6033 const struct nls_table
*nls_codepage
, int remap
)
6035 /* BB assumes one setup word */
6036 TRANSACTION2_QPI_REQ
*pSMB
= NULL
;
6037 TRANSACTION2_QPI_RSP
*pSMBr
= NULL
;
6041 struct fealist
*ea_response_data
;
6042 struct fea
*temp_fea
;
6045 __u16 params
, byte_count
, data_offset
;
6046 unsigned int ea_name_len
= ea_name
? strlen(ea_name
) : 0;
6048 cFYI(1, "In Query All EAs path %s", searchName
);
6050 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
6055 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
6057 cifsConvertToUTF16((__le16
*) pSMB
->FileName
, searchName
,
6058 PATH_MAX
, nls_codepage
, remap
);
6059 list_len
++; /* trailing null */
6061 } else { /* BB improve the check for buffer overruns BB */
6062 list_len
= strnlen(searchName
, PATH_MAX
);
6063 list_len
++; /* trailing null */
6064 strncpy(pSMB
->FileName
, searchName
, list_len
);
6067 params
= 2 /* level */ + 4 /* reserved */ + list_len
/* includes NUL */;
6068 pSMB
->TotalDataCount
= 0;
6069 pSMB
->MaxParameterCount
= cpu_to_le16(2);
6070 /* BB find exact max SMB PDU from sess structure BB */
6071 pSMB
->MaxDataCount
= cpu_to_le16(CIFSMaxBufSize
);
6072 pSMB
->MaxSetupCount
= 0;
6076 pSMB
->Reserved2
= 0;
6077 pSMB
->ParameterOffset
= cpu_to_le16(offsetof(
6078 struct smb_com_transaction2_qpi_req
, InformationLevel
) - 4);
6079 pSMB
->DataCount
= 0;
6080 pSMB
->DataOffset
= 0;
6081 pSMB
->SetupCount
= 1;
6082 pSMB
->Reserved3
= 0;
6083 pSMB
->SubCommand
= cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION
);
6084 byte_count
= params
+ 1 /* pad */ ;
6085 pSMB
->TotalParameterCount
= cpu_to_le16(params
);
6086 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
6087 pSMB
->InformationLevel
= cpu_to_le16(SMB_INFO_QUERY_ALL_EAS
);
6088 pSMB
->Reserved4
= 0;
6089 inc_rfc1001_len(pSMB
, byte_count
);
6090 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
6092 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
6093 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
6095 cFYI(1, "Send error in QueryAllEAs = %d", rc
);
6100 /* BB also check enough total bytes returned */
6101 /* BB we need to improve the validity checking
6102 of these trans2 responses */
6104 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
6105 if (rc
|| get_bcc(&pSMBr
->hdr
) < 4) {
6106 rc
= -EIO
; /* bad smb */
6110 /* check that length of list is not more than bcc */
6111 /* check that each entry does not go beyond length
6113 /* check that each element of each entry does not
6114 go beyond end of list */
6115 /* validate_trans2_offsets() */
6116 /* BB check if start of smb + data_offset > &bcc+ bcc */
6118 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
6119 ea_response_data
= (struct fealist
*)
6120 (((char *) &pSMBr
->hdr
.Protocol
) + data_offset
);
6122 list_len
= le32_to_cpu(ea_response_data
->list_len
);
6123 cFYI(1, "ea length %d", list_len
);
6124 if (list_len
<= 8) {
6125 cFYI(1, "empty EA list returned from server");
6129 /* make sure list_len doesn't go past end of SMB */
6130 end_of_smb
= (char *)pByteArea(&pSMBr
->hdr
) + get_bcc(&pSMBr
->hdr
);
6131 if ((char *)ea_response_data
+ list_len
> end_of_smb
) {
6132 cFYI(1, "EA list appears to go beyond SMB");
6137 /* account for ea list len */
6139 temp_fea
= ea_response_data
->list
;
6140 temp_ptr
= (char *)temp_fea
;
6141 while (list_len
> 0) {
6142 unsigned int name_len
;
6147 /* make sure we can read name_len and value_len */
6149 cFYI(1, "EA entry goes beyond length of list");
6154 name_len
= temp_fea
->name_len
;
6155 value_len
= le16_to_cpu(temp_fea
->value_len
);
6156 list_len
-= name_len
+ 1 + value_len
;
6158 cFYI(1, "EA entry goes beyond length of list");
6164 if (ea_name_len
== name_len
&&
6165 memcmp(ea_name
, temp_ptr
, name_len
) == 0) {
6166 temp_ptr
+= name_len
+ 1;
6170 if ((size_t)value_len
> buf_size
) {
6174 memcpy(EAData
, temp_ptr
, value_len
);
6178 /* account for prefix user. and trailing null */
6179 rc
+= (5 + 1 + name_len
);
6180 if (rc
< (int) buf_size
) {
6181 memcpy(EAData
, "user.", 5);
6183 memcpy(EAData
, temp_ptr
, name_len
);
6185 /* null terminate name */
6188 } else if (buf_size
== 0) {
6189 /* skip copy - calc size only */
6191 /* stop before overrun buffer */
6196 temp_ptr
+= name_len
+ 1 + value_len
;
6197 temp_fea
= (struct fea
*)temp_ptr
;
6200 /* didn't find the named attribute */
6205 cifs_buf_release(pSMB
);
6213 CIFSSMBSetEA(const unsigned int xid
, struct cifs_tcon
*tcon
,
6214 const char *fileName
, const char *ea_name
, const void *ea_value
,
6215 const __u16 ea_value_len
, const struct nls_table
*nls_codepage
,
6218 struct smb_com_transaction2_spi_req
*pSMB
= NULL
;
6219 struct smb_com_transaction2_spi_rsp
*pSMBr
= NULL
;
6220 struct fealist
*parm_data
;
6223 int bytes_returned
= 0;
6224 __u16 params
, param_offset
, byte_count
, offset
, count
;
6226 cFYI(1, "In SetEA");
6228 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
6233 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
6235 cifsConvertToUTF16((__le16
*) pSMB
->FileName
, fileName
,
6236 PATH_MAX
, nls_codepage
, remap
);
6237 name_len
++; /* trailing null */
6239 } else { /* BB improve the check for buffer overruns BB */
6240 name_len
= strnlen(fileName
, PATH_MAX
);
6241 name_len
++; /* trailing null */
6242 strncpy(pSMB
->FileName
, fileName
, name_len
);
6245 params
= 6 + name_len
;
6247 /* done calculating parms using name_len of file name,
6248 now use name_len to calculate length of ea name
6249 we are going to create in the inode xattrs */
6250 if (ea_name
== NULL
)
6253 name_len
= strnlen(ea_name
, 255);
6255 count
= sizeof(*parm_data
) + ea_value_len
+ name_len
;
6256 pSMB
->MaxParameterCount
= cpu_to_le16(2);
6257 /* BB find max SMB PDU from sess */
6258 pSMB
->MaxDataCount
= cpu_to_le16(1000);
6259 pSMB
->MaxSetupCount
= 0;
6263 pSMB
->Reserved2
= 0;
6264 param_offset
= offsetof(struct smb_com_transaction2_spi_req
,
6265 InformationLevel
) - 4;
6266 offset
= param_offset
+ params
;
6267 pSMB
->InformationLevel
=
6268 cpu_to_le16(SMB_SET_FILE_EA
);
6271 (struct fealist
*) (((char *) &pSMB
->hdr
.Protocol
) +
6273 pSMB
->ParameterOffset
= cpu_to_le16(param_offset
);
6274 pSMB
->DataOffset
= cpu_to_le16(offset
);
6275 pSMB
->SetupCount
= 1;
6276 pSMB
->Reserved3
= 0;
6277 pSMB
->SubCommand
= cpu_to_le16(TRANS2_SET_PATH_INFORMATION
);
6278 byte_count
= 3 /* pad */ + params
+ count
;
6279 pSMB
->DataCount
= cpu_to_le16(count
);
6280 parm_data
->list_len
= cpu_to_le32(count
);
6281 parm_data
->list
[0].EA_flags
= 0;
6282 /* we checked above that name len is less than 255 */
6283 parm_data
->list
[0].name_len
= (__u8
)name_len
;
6284 /* EA names are always ASCII */
6286 strncpy(parm_data
->list
[0].name
, ea_name
, name_len
);
6287 parm_data
->list
[0].name
[name_len
] = 0;
6288 parm_data
->list
[0].value_len
= cpu_to_le16(ea_value_len
);
6289 /* caller ensures that ea_value_len is less than 64K but
6290 we need to ensure that it fits within the smb */
6292 /*BB add length check to see if it would fit in
6293 negotiated SMB buffer size BB */
6294 /* if (ea_value_len > buffer_size - 512 (enough for header)) */
6296 memcpy(parm_data
->list
[0].name
+name_len
+1,
6297 ea_value
, ea_value_len
);
6299 pSMB
->TotalDataCount
= pSMB
->DataCount
;
6300 pSMB
->ParameterCount
= cpu_to_le16(params
);
6301 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
6302 pSMB
->Reserved4
= 0;
6303 inc_rfc1001_len(pSMB
, byte_count
);
6304 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
6305 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
6306 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
6308 cFYI(1, "SetPathInfo (EA) returned %d", rc
);
6310 cifs_buf_release(pSMB
);
6319 #ifdef CONFIG_CIFS_DNOTIFY_EXPERIMENTAL /* BB unused temporarily */
6321 * Years ago the kernel added a "dnotify" function for Samba server,
6322 * to allow network clients (such as Windows) to display updated
6323 * lists of files in directory listings automatically when
6324 * files are added by one user when another user has the
6325 * same directory open on their desktop. The Linux cifs kernel
6326 * client hooked into the kernel side of this interface for
6327 * the same reason, but ironically when the VFS moved from
6328 * "dnotify" to "inotify" it became harder to plug in Linux
6329 * network file system clients (the most obvious use case
6330 * for notify interfaces is when multiple users can update
6331 * the contents of the same directory - exactly what network
6332 * file systems can do) although the server (Samba) could
6333 * still use it. For the short term we leave the worker
6334 * function ifdeffed out (below) until inotify is fixed
6335 * in the VFS to make it easier to plug in network file
6336 * system clients. If inotify turns out to be permanently
6337 * incompatible for network fs clients, we could instead simply
6338 * expose this config flag by adding a future cifs (and smb2) notify ioctl.
6340 int CIFSSMBNotify(const unsigned int xid
, struct cifs_tcon
*tcon
,
6341 const int notify_subdirs
, const __u16 netfid
,
6342 __u32 filter
, struct file
*pfile
, int multishot
,
6343 const struct nls_table
*nls_codepage
)
6346 struct smb_com_transaction_change_notify_req
*pSMB
= NULL
;
6347 struct smb_com_ntransaction_change_notify_rsp
*pSMBr
= NULL
;
6348 struct dir_notify_req
*dnotify_req
;
6351 cFYI(1, "In CIFSSMBNotify for file handle %d", (int)netfid
);
6352 rc
= smb_init(SMB_COM_NT_TRANSACT
, 23, tcon
, (void **) &pSMB
,
6357 pSMB
->TotalParameterCount
= 0 ;
6358 pSMB
->TotalDataCount
= 0;
6359 pSMB
->MaxParameterCount
= cpu_to_le32(2);
6360 pSMB
->MaxDataCount
= cpu_to_le32(CIFSMaxBufSize
& 0xFFFFFF00);
6361 pSMB
->MaxSetupCount
= 4;
6363 pSMB
->ParameterOffset
= 0;
6364 pSMB
->DataCount
= 0;
6365 pSMB
->DataOffset
= 0;
6366 pSMB
->SetupCount
= 4; /* single byte does not need le conversion */
6367 pSMB
->SubCommand
= cpu_to_le16(NT_TRANSACT_NOTIFY_CHANGE
);
6368 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
6370 pSMB
->WatchTree
= 1; /* one byte - no le conversion needed */
6371 pSMB
->Reserved2
= 0;
6372 pSMB
->CompletionFilter
= cpu_to_le32(filter
);
6373 pSMB
->Fid
= netfid
; /* file handle always le */
6374 pSMB
->ByteCount
= 0;
6376 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
6377 (struct smb_hdr
*)pSMBr
, &bytes_returned
,
6380 cFYI(1, "Error in Notify = %d", rc
);
6382 /* Add file to outstanding requests */
6383 /* BB change to kmem cache alloc */
6384 dnotify_req
= kmalloc(
6385 sizeof(struct dir_notify_req
),
6388 dnotify_req
->Pid
= pSMB
->hdr
.Pid
;
6389 dnotify_req
->PidHigh
= pSMB
->hdr
.PidHigh
;
6390 dnotify_req
->Mid
= pSMB
->hdr
.Mid
;
6391 dnotify_req
->Tid
= pSMB
->hdr
.Tid
;
6392 dnotify_req
->Uid
= pSMB
->hdr
.Uid
;
6393 dnotify_req
->netfid
= netfid
;
6394 dnotify_req
->pfile
= pfile
;
6395 dnotify_req
->filter
= filter
;
6396 dnotify_req
->multishot
= multishot
;
6397 spin_lock(&GlobalMid_Lock
);
6398 list_add_tail(&dnotify_req
->lhead
,
6399 &GlobalDnotifyReqList
);
6400 spin_unlock(&GlobalMid_Lock
);
6404 cifs_buf_release(pSMB
);
6407 #endif /* was needed for dnotify, and will be needed for inotify when VFS fix */