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 <asm/uaccess.h>
40 #include "cifsproto.h"
41 #include "cifs_unicode.h"
42 #include "cifs_debug.h"
44 #ifdef CONFIG_CIFS_POSIX
49 #ifdef CONFIG_CIFS_WEAK_PW_HASH
50 {LANMAN_PROT
, "\2LM1.2X002"},
51 {LANMAN2_PROT
, "\2LANMAN2.1"},
52 #endif /* weak password hashing for legacy clients */
53 {CIFS_PROT
, "\2NT LM 0.12"},
54 {POSIX_PROT
, "\2POSIX 2"},
62 #ifdef CONFIG_CIFS_WEAK_PW_HASH
63 {LANMAN_PROT
, "\2LM1.2X002"},
64 {LANMAN2_PROT
, "\2LANMAN2.1"},
65 #endif /* weak password hashing for legacy clients */
66 {CIFS_PROT
, "\2NT LM 0.12"},
71 /* define the number of elements in the cifs dialect array */
72 #ifdef CONFIG_CIFS_POSIX
73 #ifdef CONFIG_CIFS_WEAK_PW_HASH
74 #define CIFS_NUM_PROT 4
76 #define CIFS_NUM_PROT 2
77 #endif /* CIFS_WEAK_PW_HASH */
79 #ifdef CONFIG_CIFS_WEAK_PW_HASH
80 #define CIFS_NUM_PROT 3
82 #define CIFS_NUM_PROT 1
83 #endif /* CONFIG_CIFS_WEAK_PW_HASH */
84 #endif /* CIFS_POSIX */
86 /* Mark as invalid, all open files on tree connections since they
87 were closed when session to server was lost */
88 static void mark_open_files_invalid(struct cifs_tcon
*pTcon
)
90 struct cifsFileInfo
*open_file
= NULL
;
91 struct list_head
*tmp
;
92 struct list_head
*tmp1
;
94 /* list all files open on tree connection and mark them invalid */
95 spin_lock(&cifs_file_list_lock
);
96 list_for_each_safe(tmp
, tmp1
, &pTcon
->openFileList
) {
97 open_file
= list_entry(tmp
, struct cifsFileInfo
, tlist
);
98 open_file
->invalidHandle
= true;
99 open_file
->oplock_break_cancelled
= true;
101 spin_unlock(&cifs_file_list_lock
);
102 /* BB Add call to invalidate_inodes(sb) for all superblocks mounted
106 /* reconnect the socket, tcon, and smb session if needed */
108 cifs_reconnect_tcon(struct cifs_tcon
*tcon
, int smb_command
)
111 struct cifs_ses
*ses
;
112 struct TCP_Server_Info
*server
;
113 struct nls_table
*nls_codepage
;
116 * SMBs NegProt, SessSetup, uLogoff do not have tcon yet so check for
117 * tcp and smb session status done differently for those three - in the
124 server
= ses
->server
;
127 * only tree disconnect, open, and write, (and ulogoff which does not
128 * have tcon) are allowed as we start force umount
130 if (tcon
->tidStatus
== CifsExiting
) {
131 if (smb_command
!= SMB_COM_WRITE_ANDX
&&
132 smb_command
!= SMB_COM_OPEN_ANDX
&&
133 smb_command
!= SMB_COM_TREE_DISCONNECT
) {
134 cFYI(1, "can not send cmd %d while umounting",
141 * Give demultiplex thread up to 10 seconds to reconnect, should be
142 * greater than cifs socket timeout which is 7 seconds
144 while (server
->tcpStatus
== CifsNeedReconnect
) {
145 wait_event_interruptible_timeout(server
->response_q
,
146 (server
->tcpStatus
!= CifsNeedReconnect
), 10 * HZ
);
148 /* are we still trying to reconnect? */
149 if (server
->tcpStatus
!= CifsNeedReconnect
)
153 * on "soft" mounts we wait once. Hard mounts keep
154 * retrying until process is killed or server comes
158 cFYI(1, "gave up waiting on reconnect in smb_init");
163 if (!ses
->need_reconnect
&& !tcon
->need_reconnect
)
166 nls_codepage
= load_nls_default();
169 * need to prevent multiple threads trying to simultaneously
170 * reconnect the same SMB session
172 mutex_lock(&ses
->session_mutex
);
173 rc
= cifs_negotiate_protocol(0, ses
);
174 if (rc
== 0 && ses
->need_reconnect
)
175 rc
= cifs_setup_session(0, ses
, nls_codepage
);
177 /* do we need to reconnect tcon? */
178 if (rc
|| !tcon
->need_reconnect
) {
179 mutex_unlock(&ses
->session_mutex
);
183 mark_open_files_invalid(tcon
);
184 rc
= CIFSTCon(0, ses
, tcon
->treeName
, tcon
, nls_codepage
);
185 mutex_unlock(&ses
->session_mutex
);
186 cFYI(1, "reconnect tcon rc = %d", rc
);
192 * FIXME: check if wsize needs updated due to negotiated smb buffer
195 atomic_inc(&tconInfoReconnectCount
);
197 /* tell server Unix caps we support */
198 if (ses
->capabilities
& CAP_UNIX
)
199 reset_cifs_unix_caps(0, tcon
, NULL
, NULL
);
202 * Removed call to reopen open files here. It is safer (and faster) to
203 * reopen files one at a time as needed in read and write.
205 * FIXME: what about file locks? don't we need to reclaim them ASAP?
210 * Check if handle based operation so we know whether we can continue
211 * or not without returning to caller to reset file handle
213 switch (smb_command
) {
214 case SMB_COM_READ_ANDX
:
215 case SMB_COM_WRITE_ANDX
:
217 case SMB_COM_FIND_CLOSE2
:
218 case SMB_COM_LOCKING_ANDX
:
222 unload_nls(nls_codepage
);
226 /* Allocate and return pointer to an SMB request buffer, and set basic
227 SMB information in the SMB header. If the return code is zero, this
228 function must have filled in request_buf pointer */
230 small_smb_init(int smb_command
, int wct
, struct cifs_tcon
*tcon
,
235 rc
= cifs_reconnect_tcon(tcon
, smb_command
);
239 *request_buf
= cifs_small_buf_get();
240 if (*request_buf
== NULL
) {
241 /* BB should we add a retry in here if not a writepage? */
245 header_assemble((struct smb_hdr
*) *request_buf
, smb_command
,
249 cifs_stats_inc(&tcon
->num_smbs_sent
);
255 small_smb_init_no_tc(const int smb_command
, const int wct
,
256 struct cifs_ses
*ses
, void **request_buf
)
259 struct smb_hdr
*buffer
;
261 rc
= small_smb_init(smb_command
, wct
, NULL
, request_buf
);
265 buffer
= (struct smb_hdr
*)*request_buf
;
266 buffer
->Mid
= GetNextMid(ses
->server
);
267 if (ses
->capabilities
& CAP_UNICODE
)
268 buffer
->Flags2
|= SMBFLG2_UNICODE
;
269 if (ses
->capabilities
& CAP_STATUS32
)
270 buffer
->Flags2
|= SMBFLG2_ERR_STATUS
;
272 /* uid, tid can stay at zero as set in header assemble */
274 /* BB add support for turning on the signing when
275 this function is used after 1st of session setup requests */
280 /* If the return code is zero, this function must fill in request_buf pointer */
282 __smb_init(int smb_command
, int wct
, struct cifs_tcon
*tcon
,
283 void **request_buf
, void **response_buf
)
285 *request_buf
= cifs_buf_get();
286 if (*request_buf
== NULL
) {
287 /* BB should we add a retry in here if not a writepage? */
290 /* Although the original thought was we needed the response buf for */
291 /* potential retries of smb operations it turns out we can determine */
292 /* from the mid flags when the request buffer can be resent without */
293 /* having to use a second distinct buffer for the response */
295 *response_buf
= *request_buf
;
297 header_assemble((struct smb_hdr
*) *request_buf
, smb_command
, tcon
,
301 cifs_stats_inc(&tcon
->num_smbs_sent
);
306 /* If the return code is zero, this function must fill in request_buf pointer */
308 smb_init(int smb_command
, int wct
, struct cifs_tcon
*tcon
,
309 void **request_buf
, void **response_buf
)
313 rc
= cifs_reconnect_tcon(tcon
, smb_command
);
317 return __smb_init(smb_command
, wct
, tcon
, request_buf
, response_buf
);
321 smb_init_no_reconnect(int smb_command
, int wct
, struct cifs_tcon
*tcon
,
322 void **request_buf
, void **response_buf
)
324 if (tcon
->ses
->need_reconnect
|| tcon
->need_reconnect
)
327 return __smb_init(smb_command
, wct
, tcon
, request_buf
, response_buf
);
330 static int validate_t2(struct smb_t2_rsp
*pSMB
)
332 unsigned int total_size
;
334 /* check for plausible wct */
335 if (pSMB
->hdr
.WordCount
< 10)
338 /* check for parm and data offset going beyond end of smb */
339 if (get_unaligned_le16(&pSMB
->t2_rsp
.ParameterOffset
) > 1024 ||
340 get_unaligned_le16(&pSMB
->t2_rsp
.DataOffset
) > 1024)
343 total_size
= get_unaligned_le16(&pSMB
->t2_rsp
.ParameterCount
);
344 if (total_size
>= 512)
347 /* check that bcc is at least as big as parms + data, and that it is
348 * less than negotiated smb buffer
350 total_size
+= get_unaligned_le16(&pSMB
->t2_rsp
.DataCount
);
351 if (total_size
> get_bcc(&pSMB
->hdr
) ||
352 total_size
>= CIFSMaxBufSize
+ MAX_CIFS_HDR_SIZE
)
357 cifs_dump_mem("Invalid transact2 SMB: ", (char *)pSMB
,
358 sizeof(struct smb_t2_rsp
) + 16);
362 static inline void inc_rfc1001_len(void *pSMB
, int count
)
364 struct smb_hdr
*hdr
= (struct smb_hdr
*)pSMB
;
366 be32_add_cpu(&hdr
->smb_buf_length
, count
);
370 CIFSSMBNegotiate(unsigned int xid
, struct cifs_ses
*ses
)
373 NEGOTIATE_RSP
*pSMBr
;
377 struct TCP_Server_Info
*server
;
379 unsigned int secFlags
;
382 server
= ses
->server
;
387 rc
= smb_init(SMB_COM_NEGOTIATE
, 0, NULL
/* no tcon yet */ ,
388 (void **) &pSMB
, (void **) &pSMBr
);
392 /* if any of auth flags (ie not sign or seal) are overriden use them */
393 if (ses
->overrideSecFlg
& (~(CIFSSEC_MUST_SIGN
| CIFSSEC_MUST_SEAL
)))
394 secFlags
= ses
->overrideSecFlg
; /* BB FIXME fix sign flags? */
395 else /* if override flags set only sign/seal OR them with global auth */
396 secFlags
= global_secflags
| ses
->overrideSecFlg
;
398 cFYI(1, "secFlags 0x%x", secFlags
);
400 pSMB
->hdr
.Mid
= GetNextMid(server
);
401 pSMB
->hdr
.Flags2
|= (SMBFLG2_UNICODE
| SMBFLG2_ERR_STATUS
);
403 if ((secFlags
& CIFSSEC_MUST_KRB5
) == CIFSSEC_MUST_KRB5
)
404 pSMB
->hdr
.Flags2
|= SMBFLG2_EXT_SEC
;
405 else if ((secFlags
& CIFSSEC_AUTH_MASK
) == CIFSSEC_MAY_KRB5
) {
406 cFYI(1, "Kerberos only mechanism, enable extended security");
407 pSMB
->hdr
.Flags2
|= SMBFLG2_EXT_SEC
;
408 } else if ((secFlags
& CIFSSEC_MUST_NTLMSSP
) == CIFSSEC_MUST_NTLMSSP
)
409 pSMB
->hdr
.Flags2
|= SMBFLG2_EXT_SEC
;
410 else if ((secFlags
& CIFSSEC_AUTH_MASK
) == CIFSSEC_MAY_NTLMSSP
) {
411 cFYI(1, "NTLMSSP only mechanism, enable extended security");
412 pSMB
->hdr
.Flags2
|= SMBFLG2_EXT_SEC
;
416 for (i
= 0; i
< CIFS_NUM_PROT
; i
++) {
417 strncpy(pSMB
->DialectsArray
+count
, protocols
[i
].name
, 16);
418 count
+= strlen(protocols
[i
].name
) + 1;
419 /* null at end of source and target buffers anyway */
421 inc_rfc1001_len(pSMB
, count
);
422 pSMB
->ByteCount
= cpu_to_le16(count
);
424 rc
= SendReceive(xid
, ses
, (struct smb_hdr
*) pSMB
,
425 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
429 server
->dialect
= le16_to_cpu(pSMBr
->DialectIndex
);
430 cFYI(1, "Dialect: %d", server
->dialect
);
431 /* Check wct = 1 error case */
432 if ((pSMBr
->hdr
.WordCount
< 13) || (server
->dialect
== BAD_PROT
)) {
433 /* core returns wct = 1, but we do not ask for core - otherwise
434 small wct just comes when dialect index is -1 indicating we
435 could not negotiate a common dialect */
438 #ifdef CONFIG_CIFS_WEAK_PW_HASH
439 } else if ((pSMBr
->hdr
.WordCount
== 13)
440 && ((server
->dialect
== LANMAN_PROT
)
441 || (server
->dialect
== LANMAN2_PROT
))) {
443 struct lanman_neg_rsp
*rsp
= (struct lanman_neg_rsp
*)pSMBr
;
445 if ((secFlags
& CIFSSEC_MAY_LANMAN
) ||
446 (secFlags
& CIFSSEC_MAY_PLNTXT
))
447 server
->secType
= LANMAN
;
449 cERROR(1, "mount failed weak security disabled"
450 " in /proc/fs/cifs/SecurityFlags");
454 server
->sec_mode
= (__u8
)le16_to_cpu(rsp
->SecurityMode
);
455 server
->maxReq
= le16_to_cpu(rsp
->MaxMpxCount
);
456 server
->maxBuf
= min((__u32
)le16_to_cpu(rsp
->MaxBufSize
),
457 (__u32
)CIFSMaxBufSize
+ MAX_CIFS_HDR_SIZE
);
458 server
->max_vcs
= le16_to_cpu(rsp
->MaxNumberVcs
);
459 /* even though we do not use raw we might as well set this
460 accurately, in case we ever find a need for it */
461 if ((le16_to_cpu(rsp
->RawMode
) & RAW_ENABLE
) == RAW_ENABLE
) {
462 server
->max_rw
= 0xFF00;
463 server
->capabilities
= CAP_MPX_MODE
| CAP_RAW_MODE
;
465 server
->max_rw
= 0;/* do not need to use raw anyway */
466 server
->capabilities
= CAP_MPX_MODE
;
468 tmp
= (__s16
)le16_to_cpu(rsp
->ServerTimeZone
);
470 /* OS/2 often does not set timezone therefore
471 * we must use server time to calc time zone.
472 * Could deviate slightly from the right zone.
473 * Smallest defined timezone difference is 15 minutes
474 * (i.e. Nepal). Rounding up/down is done to match
477 int val
, seconds
, remain
, result
;
478 struct timespec ts
, utc
;
480 ts
= cnvrtDosUnixTm(rsp
->SrvTime
.Date
,
481 rsp
->SrvTime
.Time
, 0);
482 cFYI(1, "SrvTime %d sec since 1970 (utc: %d) diff: %d",
483 (int)ts
.tv_sec
, (int)utc
.tv_sec
,
484 (int)(utc
.tv_sec
- ts
.tv_sec
));
485 val
= (int)(utc
.tv_sec
- ts
.tv_sec
);
487 result
= (seconds
/ MIN_TZ_ADJ
) * MIN_TZ_ADJ
;
488 remain
= seconds
% MIN_TZ_ADJ
;
489 if (remain
>= (MIN_TZ_ADJ
/ 2))
490 result
+= MIN_TZ_ADJ
;
493 server
->timeAdj
= result
;
495 server
->timeAdj
= (int)tmp
;
496 server
->timeAdj
*= 60; /* also in seconds */
498 cFYI(1, "server->timeAdj: %d seconds", server
->timeAdj
);
501 /* BB get server time for time conversions and add
502 code to use it and timezone since this is not UTC */
504 if (rsp
->EncryptionKeyLength
==
505 cpu_to_le16(CIFS_CRYPTO_KEY_SIZE
)) {
506 memcpy(ses
->server
->cryptkey
, rsp
->EncryptionKey
,
507 CIFS_CRYPTO_KEY_SIZE
);
508 } else if (server
->sec_mode
& SECMODE_PW_ENCRYPT
) {
509 rc
= -EIO
; /* need cryptkey unless plain text */
513 cFYI(1, "LANMAN negotiated");
514 /* we will not end up setting signing flags - as no signing
515 was in LANMAN and server did not return the flags on */
517 #else /* weak security disabled */
518 } else if (pSMBr
->hdr
.WordCount
== 13) {
519 cERROR(1, "mount failed, cifs module not built "
520 "with CIFS_WEAK_PW_HASH support");
522 #endif /* WEAK_PW_HASH */
524 } else if (pSMBr
->hdr
.WordCount
!= 17) {
529 /* else wct == 17 NTLM */
530 server
->sec_mode
= pSMBr
->SecurityMode
;
531 if ((server
->sec_mode
& SECMODE_USER
) == 0)
532 cFYI(1, "share mode security");
534 if ((server
->sec_mode
& SECMODE_PW_ENCRYPT
) == 0)
535 #ifdef CONFIG_CIFS_WEAK_PW_HASH
536 if ((secFlags
& CIFSSEC_MAY_PLNTXT
) == 0)
537 #endif /* CIFS_WEAK_PW_HASH */
538 cERROR(1, "Server requests plain text password"
539 " but client support disabled");
541 if ((secFlags
& CIFSSEC_MUST_NTLMV2
) == CIFSSEC_MUST_NTLMV2
)
542 server
->secType
= NTLMv2
;
543 else if (secFlags
& CIFSSEC_MAY_NTLM
)
544 server
->secType
= NTLM
;
545 else if (secFlags
& CIFSSEC_MAY_NTLMV2
)
546 server
->secType
= NTLMv2
;
547 else if (secFlags
& CIFSSEC_MAY_KRB5
)
548 server
->secType
= Kerberos
;
549 else if (secFlags
& CIFSSEC_MAY_NTLMSSP
)
550 server
->secType
= RawNTLMSSP
;
551 else if (secFlags
& CIFSSEC_MAY_LANMAN
)
552 server
->secType
= LANMAN
;
555 cERROR(1, "Invalid security type");
558 /* else ... any others ...? */
560 /* one byte, so no need to convert this or EncryptionKeyLen from
562 server
->maxReq
= le16_to_cpu(pSMBr
->MaxMpxCount
);
563 /* probably no need to store and check maxvcs */
564 server
->maxBuf
= min(le32_to_cpu(pSMBr
->MaxBufferSize
),
565 (__u32
) CIFSMaxBufSize
+ MAX_CIFS_HDR_SIZE
);
566 server
->max_rw
= le32_to_cpu(pSMBr
->MaxRawSize
);
567 cFYI(DBG2
, "Max buf = %d", ses
->server
->maxBuf
);
568 server
->capabilities
= le32_to_cpu(pSMBr
->Capabilities
);
569 server
->timeAdj
= (int)(__s16
)le16_to_cpu(pSMBr
->ServerTimeZone
);
570 server
->timeAdj
*= 60;
571 if (pSMBr
->EncryptionKeyLength
== CIFS_CRYPTO_KEY_SIZE
) {
572 memcpy(ses
->server
->cryptkey
, pSMBr
->u
.EncryptionKey
,
573 CIFS_CRYPTO_KEY_SIZE
);
574 } else if ((pSMBr
->hdr
.Flags2
& SMBFLG2_EXT_SEC
||
575 server
->capabilities
& CAP_EXTENDED_SECURITY
) &&
576 (pSMBr
->EncryptionKeyLength
== 0)) {
577 /* decode security blob */
578 count
= get_bcc(&pSMBr
->hdr
);
583 spin_lock(&cifs_tcp_ses_lock
);
584 if (server
->srv_count
> 1) {
585 spin_unlock(&cifs_tcp_ses_lock
);
586 if (memcmp(server
->server_GUID
,
587 pSMBr
->u
.extended_response
.
589 cFYI(1, "server UID changed");
590 memcpy(server
->server_GUID
,
591 pSMBr
->u
.extended_response
.GUID
,
595 spin_unlock(&cifs_tcp_ses_lock
);
596 memcpy(server
->server_GUID
,
597 pSMBr
->u
.extended_response
.GUID
, 16);
601 server
->secType
= RawNTLMSSP
;
603 rc
= decode_negTokenInit(pSMBr
->u
.extended_response
.
604 SecurityBlob
, count
- 16,
610 if (server
->secType
== Kerberos
) {
611 if (!server
->sec_kerberos
&&
612 !server
->sec_mskerberos
)
614 } else if (server
->secType
== RawNTLMSSP
) {
615 if (!server
->sec_ntlmssp
)
620 } else if (server
->sec_mode
& SECMODE_PW_ENCRYPT
) {
621 rc
= -EIO
; /* no crypt key only if plain text pwd */
624 server
->capabilities
&= ~CAP_EXTENDED_SECURITY
;
626 #ifdef CONFIG_CIFS_WEAK_PW_HASH
629 if ((secFlags
& CIFSSEC_MAY_SIGN
) == 0) {
630 /* MUST_SIGN already includes the MAY_SIGN FLAG
631 so if this is zero it means that signing is disabled */
632 cFYI(1, "Signing disabled");
633 if (server
->sec_mode
& SECMODE_SIGN_REQUIRED
) {
634 cERROR(1, "Server requires "
635 "packet signing to be enabled in "
636 "/proc/fs/cifs/SecurityFlags.");
640 ~(SECMODE_SIGN_ENABLED
| SECMODE_SIGN_REQUIRED
);
641 } else if ((secFlags
& CIFSSEC_MUST_SIGN
) == CIFSSEC_MUST_SIGN
) {
642 /* signing required */
643 cFYI(1, "Must sign - secFlags 0x%x", secFlags
);
644 if ((server
->sec_mode
&
645 (SECMODE_SIGN_ENABLED
| SECMODE_SIGN_REQUIRED
)) == 0) {
646 cERROR(1, "signing required but server lacks support");
649 server
->sec_mode
|= SECMODE_SIGN_REQUIRED
;
651 /* signing optional ie CIFSSEC_MAY_SIGN */
652 if ((server
->sec_mode
& SECMODE_SIGN_REQUIRED
) == 0)
654 ~(SECMODE_SIGN_ENABLED
| SECMODE_SIGN_REQUIRED
);
658 cifs_buf_release(pSMB
);
660 cFYI(1, "negprot rc %d", rc
);
665 CIFSSMBTDis(const int xid
, struct cifs_tcon
*tcon
)
667 struct smb_hdr
*smb_buffer
;
670 cFYI(1, "In tree disconnect");
672 /* BB: do we need to check this? These should never be NULL. */
673 if ((tcon
->ses
== NULL
) || (tcon
->ses
->server
== NULL
))
677 * No need to return error on this operation if tid invalidated and
678 * closed on server already e.g. due to tcp session crashing. Also,
679 * the tcon is no longer on the list, so no need to take lock before
682 if ((tcon
->need_reconnect
) || (tcon
->ses
->need_reconnect
))
685 rc
= small_smb_init(SMB_COM_TREE_DISCONNECT
, 0, tcon
,
686 (void **)&smb_buffer
);
690 rc
= SendReceiveNoRsp(xid
, tcon
->ses
, smb_buffer
, 0);
692 cFYI(1, "Tree disconnect failed %d", rc
);
694 /* No need to return error on this operation if tid invalidated and
695 closed on server already e.g. due to tcp session crashing */
703 * This is a no-op for now. We're not really interested in the reply, but
704 * rather in the fact that the server sent one and that server->lstrp
707 * FIXME: maybe we should consider checking that the reply matches request?
710 cifs_echo_callback(struct mid_q_entry
*mid
)
712 struct TCP_Server_Info
*server
= mid
->callback_data
;
714 DeleteMidQEntry(mid
);
715 atomic_dec(&server
->inFlight
);
716 wake_up(&server
->request_q
);
720 CIFSSMBEcho(struct TCP_Server_Info
*server
)
726 cFYI(1, "In echo request");
728 rc
= small_smb_init(SMB_COM_ECHO
, 0, NULL
, (void **)&smb
);
732 /* set up echo request */
733 smb
->hdr
.Tid
= 0xffff;
734 smb
->hdr
.WordCount
= 1;
735 put_unaligned_le16(1, &smb
->EchoCount
);
736 put_bcc(1, &smb
->hdr
);
738 inc_rfc1001_len(smb
, 3);
740 iov
.iov_len
= be32_to_cpu(smb
->hdr
.smb_buf_length
) + 4;
742 rc
= cifs_call_async(server
, &iov
, 1, cifs_echo_callback
, server
, true);
744 cFYI(1, "Echo request failed: %d", rc
);
746 cifs_small_buf_release(smb
);
752 CIFSSMBLogoff(const int xid
, struct cifs_ses
*ses
)
754 LOGOFF_ANDX_REQ
*pSMB
;
757 cFYI(1, "In SMBLogoff for session disconnect");
760 * BB: do we need to check validity of ses and server? They should
761 * always be valid since we have an active reference. If not, that
762 * should probably be a BUG()
764 if (!ses
|| !ses
->server
)
767 mutex_lock(&ses
->session_mutex
);
768 if (ses
->need_reconnect
)
769 goto session_already_dead
; /* no need to send SMBlogoff if uid
770 already closed due to reconnect */
771 rc
= small_smb_init(SMB_COM_LOGOFF_ANDX
, 2, NULL
, (void **)&pSMB
);
773 mutex_unlock(&ses
->session_mutex
);
777 pSMB
->hdr
.Mid
= GetNextMid(ses
->server
);
779 if (ses
->server
->sec_mode
&
780 (SECMODE_SIGN_REQUIRED
| SECMODE_SIGN_ENABLED
))
781 pSMB
->hdr
.Flags2
|= SMBFLG2_SECURITY_SIGNATURE
;
783 pSMB
->hdr
.Uid
= ses
->Suid
;
785 pSMB
->AndXCommand
= 0xFF;
786 rc
= SendReceiveNoRsp(xid
, ses
, (struct smb_hdr
*) pSMB
, 0);
787 session_already_dead
:
788 mutex_unlock(&ses
->session_mutex
);
790 /* if session dead then we do not need to do ulogoff,
791 since server closed smb session, no sense reporting
799 CIFSPOSIXDelFile(const int xid
, struct cifs_tcon
*tcon
, const char *fileName
,
800 __u16 type
, const struct nls_table
*nls_codepage
, int remap
)
802 TRANSACTION2_SPI_REQ
*pSMB
= NULL
;
803 TRANSACTION2_SPI_RSP
*pSMBr
= NULL
;
804 struct unlink_psx_rq
*pRqD
;
807 int bytes_returned
= 0;
808 __u16 params
, param_offset
, offset
, byte_count
;
810 cFYI(1, "In POSIX delete");
812 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
817 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
819 cifsConvertToUCS((__le16
*) pSMB
->FileName
, fileName
,
820 PATH_MAX
, nls_codepage
, remap
);
821 name_len
++; /* trailing null */
823 } else { /* BB add path length overrun check */
824 name_len
= strnlen(fileName
, PATH_MAX
);
825 name_len
++; /* trailing null */
826 strncpy(pSMB
->FileName
, fileName
, name_len
);
829 params
= 6 + name_len
;
830 pSMB
->MaxParameterCount
= cpu_to_le16(2);
831 pSMB
->MaxDataCount
= 0; /* BB double check this with jra */
832 pSMB
->MaxSetupCount
= 0;
837 param_offset
= offsetof(struct smb_com_transaction2_spi_req
,
838 InformationLevel
) - 4;
839 offset
= param_offset
+ params
;
841 /* Setup pointer to Request Data (inode type) */
842 pRqD
= (struct unlink_psx_rq
*)(((char *)&pSMB
->hdr
.Protocol
) + offset
);
843 pRqD
->type
= cpu_to_le16(type
);
844 pSMB
->ParameterOffset
= cpu_to_le16(param_offset
);
845 pSMB
->DataOffset
= cpu_to_le16(offset
);
846 pSMB
->SetupCount
= 1;
848 pSMB
->SubCommand
= cpu_to_le16(TRANS2_SET_PATH_INFORMATION
);
849 byte_count
= 3 /* pad */ + params
+ sizeof(struct unlink_psx_rq
);
851 pSMB
->DataCount
= cpu_to_le16(sizeof(struct unlink_psx_rq
));
852 pSMB
->TotalDataCount
= cpu_to_le16(sizeof(struct unlink_psx_rq
));
853 pSMB
->ParameterCount
= cpu_to_le16(params
);
854 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
855 pSMB
->InformationLevel
= cpu_to_le16(SMB_POSIX_UNLINK
);
857 inc_rfc1001_len(pSMB
, byte_count
);
858 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
859 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
860 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
862 cFYI(1, "Posix delete returned %d", rc
);
863 cifs_buf_release(pSMB
);
865 cifs_stats_inc(&tcon
->num_deletes
);
874 CIFSSMBDelFile(const int xid
, struct cifs_tcon
*tcon
, const char *fileName
,
875 const struct nls_table
*nls_codepage
, int remap
)
877 DELETE_FILE_REQ
*pSMB
= NULL
;
878 DELETE_FILE_RSP
*pSMBr
= NULL
;
884 rc
= smb_init(SMB_COM_DELETE
, 1, tcon
, (void **) &pSMB
,
889 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
891 cifsConvertToUCS((__le16
*) pSMB
->fileName
, fileName
,
892 PATH_MAX
, nls_codepage
, remap
);
893 name_len
++; /* trailing null */
895 } else { /* BB improve check for buffer overruns BB */
896 name_len
= strnlen(fileName
, PATH_MAX
);
897 name_len
++; /* trailing null */
898 strncpy(pSMB
->fileName
, fileName
, name_len
);
900 pSMB
->SearchAttributes
=
901 cpu_to_le16(ATTR_READONLY
| ATTR_HIDDEN
| ATTR_SYSTEM
);
902 pSMB
->BufferFormat
= 0x04;
903 inc_rfc1001_len(pSMB
, name_len
+ 1);
904 pSMB
->ByteCount
= cpu_to_le16(name_len
+ 1);
905 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
906 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
907 cifs_stats_inc(&tcon
->num_deletes
);
909 cFYI(1, "Error in RMFile = %d", rc
);
911 cifs_buf_release(pSMB
);
919 CIFSSMBRmDir(const int xid
, struct cifs_tcon
*tcon
, const char *dirName
,
920 const struct nls_table
*nls_codepage
, int remap
)
922 DELETE_DIRECTORY_REQ
*pSMB
= NULL
;
923 DELETE_DIRECTORY_RSP
*pSMBr
= NULL
;
928 cFYI(1, "In CIFSSMBRmDir");
930 rc
= smb_init(SMB_COM_DELETE_DIRECTORY
, 0, tcon
, (void **) &pSMB
,
935 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
936 name_len
= cifsConvertToUCS((__le16
*) pSMB
->DirName
, dirName
,
937 PATH_MAX
, nls_codepage
, remap
);
938 name_len
++; /* trailing null */
940 } else { /* BB improve check for buffer overruns BB */
941 name_len
= strnlen(dirName
, PATH_MAX
);
942 name_len
++; /* trailing null */
943 strncpy(pSMB
->DirName
, dirName
, name_len
);
946 pSMB
->BufferFormat
= 0x04;
947 inc_rfc1001_len(pSMB
, name_len
+ 1);
948 pSMB
->ByteCount
= cpu_to_le16(name_len
+ 1);
949 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
950 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
951 cifs_stats_inc(&tcon
->num_rmdirs
);
953 cFYI(1, "Error in RMDir = %d", rc
);
955 cifs_buf_release(pSMB
);
962 CIFSSMBMkDir(const int xid
, struct cifs_tcon
*tcon
,
963 const char *name
, const struct nls_table
*nls_codepage
, int remap
)
966 CREATE_DIRECTORY_REQ
*pSMB
= NULL
;
967 CREATE_DIRECTORY_RSP
*pSMBr
= NULL
;
971 cFYI(1, "In CIFSSMBMkDir");
973 rc
= smb_init(SMB_COM_CREATE_DIRECTORY
, 0, tcon
, (void **) &pSMB
,
978 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
979 name_len
= cifsConvertToUCS((__le16
*) pSMB
->DirName
, name
,
980 PATH_MAX
, nls_codepage
, remap
);
981 name_len
++; /* trailing null */
983 } else { /* BB improve check for buffer overruns BB */
984 name_len
= strnlen(name
, PATH_MAX
);
985 name_len
++; /* trailing null */
986 strncpy(pSMB
->DirName
, name
, name_len
);
989 pSMB
->BufferFormat
= 0x04;
990 inc_rfc1001_len(pSMB
, name_len
+ 1);
991 pSMB
->ByteCount
= cpu_to_le16(name_len
+ 1);
992 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
993 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
994 cifs_stats_inc(&tcon
->num_mkdirs
);
996 cFYI(1, "Error in Mkdir = %d", rc
);
998 cifs_buf_release(pSMB
);
1005 CIFSPOSIXCreate(const int xid
, struct cifs_tcon
*tcon
, __u32 posix_flags
,
1006 __u64 mode
, __u16
*netfid
, FILE_UNIX_BASIC_INFO
*pRetData
,
1007 __u32
*pOplock
, const char *name
,
1008 const struct nls_table
*nls_codepage
, int remap
)
1010 TRANSACTION2_SPI_REQ
*pSMB
= NULL
;
1011 TRANSACTION2_SPI_RSP
*pSMBr
= NULL
;
1014 int bytes_returned
= 0;
1015 __u16 params
, param_offset
, offset
, byte_count
, count
;
1016 OPEN_PSX_REQ
*pdata
;
1017 OPEN_PSX_RSP
*psx_rsp
;
1019 cFYI(1, "In POSIX Create");
1021 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
1026 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
1028 cifsConvertToUCS((__le16
*) pSMB
->FileName
, name
,
1029 PATH_MAX
, nls_codepage
, remap
);
1030 name_len
++; /* trailing null */
1032 } else { /* BB improve the check for buffer overruns BB */
1033 name_len
= strnlen(name
, PATH_MAX
);
1034 name_len
++; /* trailing null */
1035 strncpy(pSMB
->FileName
, name
, name_len
);
1038 params
= 6 + name_len
;
1039 count
= sizeof(OPEN_PSX_REQ
);
1040 pSMB
->MaxParameterCount
= cpu_to_le16(2);
1041 pSMB
->MaxDataCount
= cpu_to_le16(1000); /* large enough */
1042 pSMB
->MaxSetupCount
= 0;
1046 pSMB
->Reserved2
= 0;
1047 param_offset
= offsetof(struct smb_com_transaction2_spi_req
,
1048 InformationLevel
) - 4;
1049 offset
= param_offset
+ params
;
1050 pdata
= (OPEN_PSX_REQ
*)(((char *)&pSMB
->hdr
.Protocol
) + offset
);
1051 pdata
->Level
= cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC
);
1052 pdata
->Permissions
= cpu_to_le64(mode
);
1053 pdata
->PosixOpenFlags
= cpu_to_le32(posix_flags
);
1054 pdata
->OpenFlags
= cpu_to_le32(*pOplock
);
1055 pSMB
->ParameterOffset
= cpu_to_le16(param_offset
);
1056 pSMB
->DataOffset
= cpu_to_le16(offset
);
1057 pSMB
->SetupCount
= 1;
1058 pSMB
->Reserved3
= 0;
1059 pSMB
->SubCommand
= cpu_to_le16(TRANS2_SET_PATH_INFORMATION
);
1060 byte_count
= 3 /* pad */ + params
+ count
;
1062 pSMB
->DataCount
= cpu_to_le16(count
);
1063 pSMB
->ParameterCount
= cpu_to_le16(params
);
1064 pSMB
->TotalDataCount
= pSMB
->DataCount
;
1065 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
1066 pSMB
->InformationLevel
= cpu_to_le16(SMB_POSIX_OPEN
);
1067 pSMB
->Reserved4
= 0;
1068 inc_rfc1001_len(pSMB
, byte_count
);
1069 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
1070 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
1071 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
1073 cFYI(1, "Posix create returned %d", rc
);
1074 goto psx_create_err
;
1077 cFYI(1, "copying inode info");
1078 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
1080 if (rc
|| get_bcc(&pSMBr
->hdr
) < sizeof(OPEN_PSX_RSP
)) {
1081 rc
= -EIO
; /* bad smb */
1082 goto psx_create_err
;
1085 /* copy return information to pRetData */
1086 psx_rsp
= (OPEN_PSX_RSP
*)((char *) &pSMBr
->hdr
.Protocol
1087 + le16_to_cpu(pSMBr
->t2
.DataOffset
));
1089 *pOplock
= le16_to_cpu(psx_rsp
->OplockFlags
);
1091 *netfid
= psx_rsp
->Fid
; /* cifs fid stays in le */
1092 /* Let caller know file was created so we can set the mode. */
1093 /* Do we care about the CreateAction in any other cases? */
1094 if (cpu_to_le32(FILE_CREATE
) == psx_rsp
->CreateAction
)
1095 *pOplock
|= CIFS_CREATE_ACTION
;
1096 /* check to make sure response data is there */
1097 if (psx_rsp
->ReturnedLevel
!= cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC
)) {
1098 pRetData
->Type
= cpu_to_le32(-1); /* unknown */
1099 cFYI(DBG2
, "unknown type");
1101 if (get_bcc(&pSMBr
->hdr
) < sizeof(OPEN_PSX_RSP
)
1102 + sizeof(FILE_UNIX_BASIC_INFO
)) {
1103 cERROR(1, "Open response data too small");
1104 pRetData
->Type
= cpu_to_le32(-1);
1105 goto psx_create_err
;
1107 memcpy((char *) pRetData
,
1108 (char *)psx_rsp
+ sizeof(OPEN_PSX_RSP
),
1109 sizeof(FILE_UNIX_BASIC_INFO
));
1113 cifs_buf_release(pSMB
);
1115 if (posix_flags
& SMB_O_DIRECTORY
)
1116 cifs_stats_inc(&tcon
->num_posixmkdirs
);
1118 cifs_stats_inc(&tcon
->num_posixopens
);
1126 static __u16
convert_disposition(int disposition
)
1130 switch (disposition
) {
1131 case FILE_SUPERSEDE
:
1132 ofun
= SMBOPEN_OCREATE
| SMBOPEN_OTRUNC
;
1135 ofun
= SMBOPEN_OAPPEND
;
1138 ofun
= SMBOPEN_OCREATE
;
1141 ofun
= SMBOPEN_OCREATE
| SMBOPEN_OAPPEND
;
1143 case FILE_OVERWRITE
:
1144 ofun
= SMBOPEN_OTRUNC
;
1146 case FILE_OVERWRITE_IF
:
1147 ofun
= SMBOPEN_OCREATE
| SMBOPEN_OTRUNC
;
1150 cFYI(1, "unknown disposition %d", disposition
);
1151 ofun
= SMBOPEN_OAPPEND
; /* regular open */
1157 access_flags_to_smbopen_mode(const int access_flags
)
1159 int masked_flags
= access_flags
& (GENERIC_READ
| GENERIC_WRITE
);
1161 if (masked_flags
== GENERIC_READ
)
1162 return SMBOPEN_READ
;
1163 else if (masked_flags
== GENERIC_WRITE
)
1164 return SMBOPEN_WRITE
;
1166 /* just go for read/write */
1167 return SMBOPEN_READWRITE
;
1171 SMBLegacyOpen(const int xid
, struct cifs_tcon
*tcon
,
1172 const char *fileName
, const int openDisposition
,
1173 const int access_flags
, const int create_options
, __u16
*netfid
,
1174 int *pOplock
, FILE_ALL_INFO
*pfile_info
,
1175 const struct nls_table
*nls_codepage
, int remap
)
1178 OPENX_REQ
*pSMB
= NULL
;
1179 OPENX_RSP
*pSMBr
= NULL
;
1185 rc
= smb_init(SMB_COM_OPEN_ANDX
, 15, tcon
, (void **) &pSMB
,
1190 pSMB
->AndXCommand
= 0xFF; /* none */
1192 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
1193 count
= 1; /* account for one byte pad to word boundary */
1195 cifsConvertToUCS((__le16
*) (pSMB
->fileName
+ 1),
1196 fileName
, PATH_MAX
, nls_codepage
, remap
);
1197 name_len
++; /* trailing null */
1199 } else { /* BB improve check for buffer overruns BB */
1200 count
= 0; /* no pad */
1201 name_len
= strnlen(fileName
, PATH_MAX
);
1202 name_len
++; /* trailing null */
1203 strncpy(pSMB
->fileName
, fileName
, name_len
);
1205 if (*pOplock
& REQ_OPLOCK
)
1206 pSMB
->OpenFlags
= cpu_to_le16(REQ_OPLOCK
);
1207 else if (*pOplock
& REQ_BATCHOPLOCK
)
1208 pSMB
->OpenFlags
= cpu_to_le16(REQ_BATCHOPLOCK
);
1210 pSMB
->OpenFlags
|= cpu_to_le16(REQ_MORE_INFO
);
1211 pSMB
->Mode
= cpu_to_le16(access_flags_to_smbopen_mode(access_flags
));
1212 pSMB
->Mode
|= cpu_to_le16(0x40); /* deny none */
1213 /* set file as system file if special file such
1214 as fifo and server expecting SFU style and
1215 no Unix extensions */
1217 if (create_options
& CREATE_OPTION_SPECIAL
)
1218 pSMB
->FileAttributes
= cpu_to_le16(ATTR_SYSTEM
);
1219 else /* BB FIXME BB */
1220 pSMB
->FileAttributes
= cpu_to_le16(0/*ATTR_NORMAL*/);
1222 if (create_options
& CREATE_OPTION_READONLY
)
1223 pSMB
->FileAttributes
|= cpu_to_le16(ATTR_READONLY
);
1226 /* pSMB->CreateOptions = cpu_to_le32(create_options &
1227 CREATE_OPTIONS_MASK); */
1228 /* BB FIXME END BB */
1230 pSMB
->Sattr
= cpu_to_le16(ATTR_HIDDEN
| ATTR_SYSTEM
| ATTR_DIRECTORY
);
1231 pSMB
->OpenFunction
= cpu_to_le16(convert_disposition(openDisposition
));
1233 inc_rfc1001_len(pSMB
, count
);
1235 pSMB
->ByteCount
= cpu_to_le16(count
);
1236 /* long_op set to 1 to allow for oplock break timeouts */
1237 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
1238 (struct smb_hdr
*)pSMBr
, &bytes_returned
, 0);
1239 cifs_stats_inc(&tcon
->num_opens
);
1241 cFYI(1, "Error in Open = %d", rc
);
1243 /* BB verify if wct == 15 */
1245 /* *pOplock = pSMBr->OplockLevel; */ /* BB take from action field*/
1247 *netfid
= pSMBr
->Fid
; /* cifs fid stays in le */
1248 /* Let caller know file was created so we can set the mode. */
1249 /* Do we care about the CreateAction in any other cases? */
1251 /* if (cpu_to_le32(FILE_CREATE) == pSMBr->CreateAction)
1252 *pOplock |= CIFS_CREATE_ACTION; */
1256 pfile_info
->CreationTime
= 0; /* BB convert CreateTime*/
1257 pfile_info
->LastAccessTime
= 0; /* BB fixme */
1258 pfile_info
->LastWriteTime
= 0; /* BB fixme */
1259 pfile_info
->ChangeTime
= 0; /* BB fixme */
1260 pfile_info
->Attributes
=
1261 cpu_to_le32(le16_to_cpu(pSMBr
->FileAttributes
));
1262 /* the file_info buf is endian converted by caller */
1263 pfile_info
->AllocationSize
=
1264 cpu_to_le64(le32_to_cpu(pSMBr
->EndOfFile
));
1265 pfile_info
->EndOfFile
= pfile_info
->AllocationSize
;
1266 pfile_info
->NumberOfLinks
= cpu_to_le32(1);
1267 pfile_info
->DeletePending
= 0;
1271 cifs_buf_release(pSMB
);
1278 CIFSSMBOpen(const int xid
, struct cifs_tcon
*tcon
,
1279 const char *fileName
, const int openDisposition
,
1280 const int access_flags
, const int create_options
, __u16
*netfid
,
1281 int *pOplock
, FILE_ALL_INFO
*pfile_info
,
1282 const struct nls_table
*nls_codepage
, int remap
)
1285 OPEN_REQ
*pSMB
= NULL
;
1286 OPEN_RSP
*pSMBr
= NULL
;
1292 rc
= smb_init(SMB_COM_NT_CREATE_ANDX
, 24, tcon
, (void **) &pSMB
,
1297 pSMB
->AndXCommand
= 0xFF; /* none */
1299 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
1300 count
= 1; /* account for one byte pad to word boundary */
1302 cifsConvertToUCS((__le16
*) (pSMB
->fileName
+ 1),
1303 fileName
, PATH_MAX
, nls_codepage
, remap
);
1304 name_len
++; /* trailing null */
1306 pSMB
->NameLength
= cpu_to_le16(name_len
);
1307 } else { /* BB improve check for buffer overruns BB */
1308 count
= 0; /* no pad */
1309 name_len
= strnlen(fileName
, PATH_MAX
);
1310 name_len
++; /* trailing null */
1311 pSMB
->NameLength
= cpu_to_le16(name_len
);
1312 strncpy(pSMB
->fileName
, fileName
, name_len
);
1314 if (*pOplock
& REQ_OPLOCK
)
1315 pSMB
->OpenFlags
= cpu_to_le32(REQ_OPLOCK
);
1316 else if (*pOplock
& REQ_BATCHOPLOCK
)
1317 pSMB
->OpenFlags
= cpu_to_le32(REQ_BATCHOPLOCK
);
1318 pSMB
->DesiredAccess
= cpu_to_le32(access_flags
);
1319 pSMB
->AllocationSize
= 0;
1320 /* set file as system file if special file such
1321 as fifo and server expecting SFU style and
1322 no Unix extensions */
1323 if (create_options
& CREATE_OPTION_SPECIAL
)
1324 pSMB
->FileAttributes
= cpu_to_le32(ATTR_SYSTEM
);
1326 pSMB
->FileAttributes
= cpu_to_le32(ATTR_NORMAL
);
1328 /* XP does not handle ATTR_POSIX_SEMANTICS */
1329 /* but it helps speed up case sensitive checks for other
1330 servers such as Samba */
1331 if (tcon
->ses
->capabilities
& CAP_UNIX
)
1332 pSMB
->FileAttributes
|= cpu_to_le32(ATTR_POSIX_SEMANTICS
);
1334 if (create_options
& CREATE_OPTION_READONLY
)
1335 pSMB
->FileAttributes
|= cpu_to_le32(ATTR_READONLY
);
1337 pSMB
->ShareAccess
= cpu_to_le32(FILE_SHARE_ALL
);
1338 pSMB
->CreateDisposition
= cpu_to_le32(openDisposition
);
1339 pSMB
->CreateOptions
= cpu_to_le32(create_options
& CREATE_OPTIONS_MASK
);
1340 /* BB Expirement with various impersonation levels and verify */
1341 pSMB
->ImpersonationLevel
= cpu_to_le32(SECURITY_IMPERSONATION
);
1342 pSMB
->SecurityFlags
=
1343 SECURITY_CONTEXT_TRACKING
| SECURITY_EFFECTIVE_ONLY
;
1346 inc_rfc1001_len(pSMB
, count
);
1348 pSMB
->ByteCount
= cpu_to_le16(count
);
1349 /* long_op set to 1 to allow for oplock break timeouts */
1350 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
1351 (struct smb_hdr
*)pSMBr
, &bytes_returned
, 0);
1352 cifs_stats_inc(&tcon
->num_opens
);
1354 cFYI(1, "Error in Open = %d", rc
);
1356 *pOplock
= pSMBr
->OplockLevel
; /* 1 byte no need to le_to_cpu */
1357 *netfid
= pSMBr
->Fid
; /* cifs fid stays in le */
1358 /* Let caller know file was created so we can set the mode. */
1359 /* Do we care about the CreateAction in any other cases? */
1360 if (cpu_to_le32(FILE_CREATE
) == pSMBr
->CreateAction
)
1361 *pOplock
|= CIFS_CREATE_ACTION
;
1363 memcpy((char *)pfile_info
, (char *)&pSMBr
->CreationTime
,
1364 36 /* CreationTime to Attributes */);
1365 /* the file_info buf is endian converted by caller */
1366 pfile_info
->AllocationSize
= pSMBr
->AllocationSize
;
1367 pfile_info
->EndOfFile
= pSMBr
->EndOfFile
;
1368 pfile_info
->NumberOfLinks
= cpu_to_le32(1);
1369 pfile_info
->DeletePending
= 0;
1373 cifs_buf_release(pSMB
);
1380 CIFSSMBRead(const int xid
, struct cifs_io_parms
*io_parms
, unsigned int *nbytes
,
1381 char **buf
, int *pbuf_type
)
1384 READ_REQ
*pSMB
= NULL
;
1385 READ_RSP
*pSMBr
= NULL
;
1386 char *pReadData
= NULL
;
1388 int resp_buf_type
= 0;
1390 __u32 pid
= io_parms
->pid
;
1391 __u16 netfid
= io_parms
->netfid
;
1392 __u64 offset
= io_parms
->offset
;
1393 struct cifs_tcon
*tcon
= io_parms
->tcon
;
1394 unsigned int count
= io_parms
->length
;
1396 cFYI(1, "Reading %d bytes on fid %d", count
, netfid
);
1397 if (tcon
->ses
->capabilities
& CAP_LARGE_FILES
)
1400 wct
= 10; /* old style read */
1401 if ((offset
>> 32) > 0) {
1402 /* can not handle this big offset for old */
1408 rc
= small_smb_init(SMB_COM_READ_ANDX
, wct
, tcon
, (void **) &pSMB
);
1412 pSMB
->hdr
.Pid
= cpu_to_le16((__u16
)pid
);
1413 pSMB
->hdr
.PidHigh
= cpu_to_le16((__u16
)(pid
>> 16));
1415 /* tcon and ses pointer are checked in smb_init */
1416 if (tcon
->ses
->server
== NULL
)
1417 return -ECONNABORTED
;
1419 pSMB
->AndXCommand
= 0xFF; /* none */
1421 pSMB
->OffsetLow
= cpu_to_le32(offset
& 0xFFFFFFFF);
1423 pSMB
->OffsetHigh
= cpu_to_le32(offset
>> 32);
1425 pSMB
->Remaining
= 0;
1426 pSMB
->MaxCount
= cpu_to_le16(count
& 0xFFFF);
1427 pSMB
->MaxCountHigh
= cpu_to_le32(count
>> 16);
1429 pSMB
->ByteCount
= 0; /* no need to do le conversion since 0 */
1431 /* old style read */
1432 struct smb_com_readx_req
*pSMBW
=
1433 (struct smb_com_readx_req
*)pSMB
;
1434 pSMBW
->ByteCount
= 0;
1437 iov
[0].iov_base
= (char *)pSMB
;
1438 iov
[0].iov_len
= be32_to_cpu(pSMB
->hdr
.smb_buf_length
) + 4;
1439 rc
= SendReceive2(xid
, tcon
->ses
, iov
, 1 /* num iovecs */,
1440 &resp_buf_type
, CIFS_LOG_ERROR
);
1441 cifs_stats_inc(&tcon
->num_reads
);
1442 pSMBr
= (READ_RSP
*)iov
[0].iov_base
;
1444 cERROR(1, "Send error in read = %d", rc
);
1446 int data_length
= le16_to_cpu(pSMBr
->DataLengthHigh
);
1447 data_length
= data_length
<< 16;
1448 data_length
+= le16_to_cpu(pSMBr
->DataLength
);
1449 *nbytes
= data_length
;
1451 /*check that DataLength would not go beyond end of SMB */
1452 if ((data_length
> CIFSMaxBufSize
)
1453 || (data_length
> count
)) {
1454 cFYI(1, "bad length %d for count %d",
1455 data_length
, count
);
1459 pReadData
= (char *) (&pSMBr
->hdr
.Protocol
) +
1460 le16_to_cpu(pSMBr
->DataOffset
);
1461 /* if (rc = copy_to_user(buf, pReadData, data_length)) {
1462 cERROR(1, "Faulting on read rc = %d",rc);
1464 }*/ /* can not use copy_to_user when using page cache*/
1466 memcpy(*buf
, pReadData
, data_length
);
1470 /* cifs_small_buf_release(pSMB); */ /* Freed earlier now in SendReceive2 */
1472 if (resp_buf_type
== CIFS_SMALL_BUFFER
)
1473 cifs_small_buf_release(iov
[0].iov_base
);
1474 else if (resp_buf_type
== CIFS_LARGE_BUFFER
)
1475 cifs_buf_release(iov
[0].iov_base
);
1476 } else if (resp_buf_type
!= CIFS_NO_BUFFER
) {
1477 /* return buffer to caller to free */
1478 *buf
= iov
[0].iov_base
;
1479 if (resp_buf_type
== CIFS_SMALL_BUFFER
)
1480 *pbuf_type
= CIFS_SMALL_BUFFER
;
1481 else if (resp_buf_type
== CIFS_LARGE_BUFFER
)
1482 *pbuf_type
= CIFS_LARGE_BUFFER
;
1483 } /* else no valid buffer on return - leave as null */
1485 /* Note: On -EAGAIN error only caller can retry on handle based calls
1486 since file handle passed in no longer valid */
1492 CIFSSMBWrite(const int xid
, struct cifs_io_parms
*io_parms
,
1493 unsigned int *nbytes
, const char *buf
,
1494 const char __user
*ubuf
, const int long_op
)
1497 WRITE_REQ
*pSMB
= NULL
;
1498 WRITE_RSP
*pSMBr
= NULL
;
1499 int bytes_returned
, wct
;
1502 __u32 pid
= io_parms
->pid
;
1503 __u16 netfid
= io_parms
->netfid
;
1504 __u64 offset
= io_parms
->offset
;
1505 struct cifs_tcon
*tcon
= io_parms
->tcon
;
1506 unsigned int count
= io_parms
->length
;
1510 /* cFYI(1, "write at %lld %d bytes", offset, count);*/
1511 if (tcon
->ses
== NULL
)
1512 return -ECONNABORTED
;
1514 if (tcon
->ses
->capabilities
& CAP_LARGE_FILES
)
1518 if ((offset
>> 32) > 0) {
1519 /* can not handle big offset for old srv */
1524 rc
= smb_init(SMB_COM_WRITE_ANDX
, wct
, tcon
, (void **) &pSMB
,
1529 pSMB
->hdr
.Pid
= cpu_to_le16((__u16
)pid
);
1530 pSMB
->hdr
.PidHigh
= cpu_to_le16((__u16
)(pid
>> 16));
1532 /* tcon and ses pointer are checked in smb_init */
1533 if (tcon
->ses
->server
== NULL
)
1534 return -ECONNABORTED
;
1536 pSMB
->AndXCommand
= 0xFF; /* none */
1538 pSMB
->OffsetLow
= cpu_to_le32(offset
& 0xFFFFFFFF);
1540 pSMB
->OffsetHigh
= cpu_to_le32(offset
>> 32);
1542 pSMB
->Reserved
= 0xFFFFFFFF;
1543 pSMB
->WriteMode
= 0;
1544 pSMB
->Remaining
= 0;
1546 /* Can increase buffer size if buffer is big enough in some cases ie we
1547 can send more if LARGE_WRITE_X capability returned by the server and if
1548 our buffer is big enough or if we convert to iovecs on socket writes
1549 and eliminate the copy to the CIFS buffer */
1550 if (tcon
->ses
->capabilities
& CAP_LARGE_WRITE_X
) {
1551 bytes_sent
= min_t(const unsigned int, CIFSMaxBufSize
, count
);
1553 bytes_sent
= (tcon
->ses
->server
->maxBuf
- MAX_CIFS_HDR_SIZE
)
1557 if (bytes_sent
> count
)
1560 cpu_to_le16(offsetof(struct smb_com_write_req
, Data
) - 4);
1562 memcpy(pSMB
->Data
, buf
, bytes_sent
);
1564 if (copy_from_user(pSMB
->Data
, ubuf
, bytes_sent
)) {
1565 cifs_buf_release(pSMB
);
1568 } else if (count
!= 0) {
1570 cifs_buf_release(pSMB
);
1572 } /* else setting file size with write of zero bytes */
1574 byte_count
= bytes_sent
+ 1; /* pad */
1575 else /* wct == 12 */
1576 byte_count
= bytes_sent
+ 5; /* bigger pad, smaller smb hdr */
1578 pSMB
->DataLengthLow
= cpu_to_le16(bytes_sent
& 0xFFFF);
1579 pSMB
->DataLengthHigh
= cpu_to_le16(bytes_sent
>> 16);
1580 inc_rfc1001_len(pSMB
, byte_count
);
1583 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
1584 else { /* old style write has byte count 4 bytes earlier
1586 struct smb_com_writex_req
*pSMBW
=
1587 (struct smb_com_writex_req
*)pSMB
;
1588 pSMBW
->ByteCount
= cpu_to_le16(byte_count
);
1591 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
1592 (struct smb_hdr
*) pSMBr
, &bytes_returned
, long_op
);
1593 cifs_stats_inc(&tcon
->num_writes
);
1595 cFYI(1, "Send error in write = %d", rc
);
1597 *nbytes
= le16_to_cpu(pSMBr
->CountHigh
);
1598 *nbytes
= (*nbytes
) << 16;
1599 *nbytes
+= le16_to_cpu(pSMBr
->Count
);
1602 * Mask off high 16 bits when bytes written as returned by the
1603 * server is greater than bytes requested by the client. Some
1604 * OS/2 servers are known to set incorrect CountHigh values.
1606 if (*nbytes
> count
)
1610 cifs_buf_release(pSMB
);
1612 /* Note: On -EAGAIN error only caller can retry on handle based calls
1613 since file handle passed in no longer valid */
1619 cifs_writedata_release(struct kref
*refcount
)
1621 struct cifs_writedata
*wdata
= container_of(refcount
,
1622 struct cifs_writedata
, refcount
);
1625 cifsFileInfo_put(wdata
->cfile
);
1631 * Write failed with a retryable error. Resend the write request. It's also
1632 * possible that the page was redirtied so re-clean the page.
1635 cifs_writev_requeue(struct cifs_writedata
*wdata
)
1638 struct inode
*inode
= wdata
->cfile
->dentry
->d_inode
;
1640 for (i
= 0; i
< wdata
->nr_pages
; i
++) {
1641 lock_page(wdata
->pages
[i
]);
1642 clear_page_dirty_for_io(wdata
->pages
[i
]);
1646 rc
= cifs_async_writev(wdata
);
1647 } while (rc
== -EAGAIN
);
1649 for (i
= 0; i
< wdata
->nr_pages
; i
++) {
1651 SetPageError(wdata
->pages
[i
]);
1652 unlock_page(wdata
->pages
[i
]);
1655 mapping_set_error(inode
->i_mapping
, rc
);
1656 kref_put(&wdata
->refcount
, cifs_writedata_release
);
1660 cifs_writev_complete(struct work_struct
*work
)
1662 struct cifs_writedata
*wdata
= container_of(work
,
1663 struct cifs_writedata
, work
);
1664 struct inode
*inode
= wdata
->cfile
->dentry
->d_inode
;
1667 if (wdata
->result
== 0) {
1668 cifs_update_eof(CIFS_I(inode
), wdata
->offset
, wdata
->bytes
);
1669 cifs_stats_bytes_written(tlink_tcon(wdata
->cfile
->tlink
),
1671 } else if (wdata
->sync_mode
== WB_SYNC_ALL
&& wdata
->result
== -EAGAIN
)
1672 return cifs_writev_requeue(wdata
);
1674 for (i
= 0; i
< wdata
->nr_pages
; i
++) {
1675 struct page
*page
= wdata
->pages
[i
];
1676 if (wdata
->result
== -EAGAIN
)
1677 __set_page_dirty_nobuffers(page
);
1678 else if (wdata
->result
< 0)
1680 end_page_writeback(page
);
1681 page_cache_release(page
);
1683 if (wdata
->result
!= -EAGAIN
)
1684 mapping_set_error(inode
->i_mapping
, wdata
->result
);
1685 kref_put(&wdata
->refcount
, cifs_writedata_release
);
1688 struct cifs_writedata
*
1689 cifs_writedata_alloc(unsigned int nr_pages
)
1691 struct cifs_writedata
*wdata
;
1693 /* this would overflow */
1694 if (nr_pages
== 0) {
1695 cERROR(1, "%s: called with nr_pages == 0!", __func__
);
1699 /* writedata + number of page pointers */
1700 wdata
= kzalloc(sizeof(*wdata
) +
1701 sizeof(struct page
*) * (nr_pages
- 1), GFP_NOFS
);
1702 if (wdata
!= NULL
) {
1703 INIT_WORK(&wdata
->work
, cifs_writev_complete
);
1704 kref_init(&wdata
->refcount
);
1710 * Check the midState and signature on received buffer (if any), and queue the
1711 * workqueue completion task.
1714 cifs_writev_callback(struct mid_q_entry
*mid
)
1716 struct cifs_writedata
*wdata
= mid
->callback_data
;
1717 struct cifs_tcon
*tcon
= tlink_tcon(wdata
->cfile
->tlink
);
1718 unsigned int written
;
1719 WRITE_RSP
*smb
= (WRITE_RSP
*)mid
->resp_buf
;
1721 switch (mid
->midState
) {
1722 case MID_RESPONSE_RECEIVED
:
1723 wdata
->result
= cifs_check_receive(mid
, tcon
->ses
->server
, 0);
1724 if (wdata
->result
!= 0)
1727 written
= le16_to_cpu(smb
->CountHigh
);
1729 written
+= le16_to_cpu(smb
->Count
);
1731 * Mask off high 16 bits when bytes written as returned
1732 * by the server is greater than bytes requested by the
1733 * client. OS/2 servers are known to set incorrect
1736 if (written
> wdata
->bytes
)
1739 if (written
< wdata
->bytes
)
1740 wdata
->result
= -ENOSPC
;
1742 wdata
->bytes
= written
;
1744 case MID_REQUEST_SUBMITTED
:
1745 case MID_RETRY_NEEDED
:
1746 wdata
->result
= -EAGAIN
;
1749 wdata
->result
= -EIO
;
1753 queue_work(system_nrt_wq
, &wdata
->work
);
1754 DeleteMidQEntry(mid
);
1755 atomic_dec(&tcon
->ses
->server
->inFlight
);
1756 wake_up(&tcon
->ses
->server
->request_q
);
1759 /* cifs_async_writev - send an async write, and set up mid to handle result */
1761 cifs_async_writev(struct cifs_writedata
*wdata
)
1763 int i
, rc
= -EACCES
;
1764 WRITE_REQ
*smb
= NULL
;
1766 struct cifs_tcon
*tcon
= tlink_tcon(wdata
->cfile
->tlink
);
1767 struct inode
*inode
= wdata
->cfile
->dentry
->d_inode
;
1768 struct kvec
*iov
= NULL
;
1770 if (tcon
->ses
->capabilities
& CAP_LARGE_FILES
) {
1774 if (wdata
->offset
>> 32 > 0) {
1775 /* can not handle big offset for old srv */
1780 rc
= small_smb_init(SMB_COM_WRITE_ANDX
, wct
, tcon
, (void **)&smb
);
1782 goto async_writev_out
;
1784 /* 1 iov per page + 1 for header */
1785 iov
= kzalloc((wdata
->nr_pages
+ 1) * sizeof(*iov
), GFP_NOFS
);
1788 goto async_writev_out
;
1791 smb
->hdr
.Pid
= cpu_to_le16((__u16
)wdata
->cfile
->pid
);
1792 smb
->hdr
.PidHigh
= cpu_to_le16((__u16
)(wdata
->cfile
->pid
>> 16));
1794 smb
->AndXCommand
= 0xFF; /* none */
1795 smb
->Fid
= wdata
->cfile
->netfid
;
1796 smb
->OffsetLow
= cpu_to_le32(wdata
->offset
& 0xFFFFFFFF);
1798 smb
->OffsetHigh
= cpu_to_le32(wdata
->offset
>> 32);
1799 smb
->Reserved
= 0xFFFFFFFF;
1804 cpu_to_le16(offsetof(struct smb_com_write_req
, Data
) - 4);
1806 /* 4 for RFC1001 length + 1 for BCC */
1807 iov
[0].iov_len
= be32_to_cpu(smb
->hdr
.smb_buf_length
) + 4 + 1;
1808 iov
[0].iov_base
= smb
;
1810 /* marshal up the pages into iov array */
1812 for (i
= 0; i
< wdata
->nr_pages
; i
++) {
1813 iov
[i
+ 1].iov_len
= min(inode
->i_size
-
1814 page_offset(wdata
->pages
[i
]),
1815 (loff_t
)PAGE_CACHE_SIZE
);
1816 iov
[i
+ 1].iov_base
= kmap(wdata
->pages
[i
]);
1817 wdata
->bytes
+= iov
[i
+ 1].iov_len
;
1820 cFYI(1, "async write at %llu %u bytes", wdata
->offset
, wdata
->bytes
);
1822 smb
->DataLengthLow
= cpu_to_le16(wdata
->bytes
& 0xFFFF);
1823 smb
->DataLengthHigh
= cpu_to_le16(wdata
->bytes
>> 16);
1826 inc_rfc1001_len(&smb
->hdr
, wdata
->bytes
+ 1);
1827 put_bcc(wdata
->bytes
+ 1, &smb
->hdr
);
1830 struct smb_com_writex_req
*smbw
=
1831 (struct smb_com_writex_req
*)smb
;
1832 inc_rfc1001_len(&smbw
->hdr
, wdata
->bytes
+ 5);
1833 put_bcc(wdata
->bytes
+ 5, &smbw
->hdr
);
1834 iov
[0].iov_len
+= 4; /* pad bigger by four bytes */
1837 kref_get(&wdata
->refcount
);
1838 rc
= cifs_call_async(tcon
->ses
->server
, iov
, wdata
->nr_pages
+ 1,
1839 cifs_writev_callback
, wdata
, false);
1842 cifs_stats_inc(&tcon
->num_writes
);
1844 kref_put(&wdata
->refcount
, cifs_writedata_release
);
1846 /* send is done, unmap pages */
1847 for (i
= 0; i
< wdata
->nr_pages
; i
++)
1848 kunmap(wdata
->pages
[i
]);
1851 cifs_small_buf_release(smb
);
1857 CIFSSMBWrite2(const int xid
, struct cifs_io_parms
*io_parms
,
1858 unsigned int *nbytes
, struct kvec
*iov
, int n_vec
,
1862 WRITE_REQ
*pSMB
= NULL
;
1865 int resp_buf_type
= 0;
1866 __u32 pid
= io_parms
->pid
;
1867 __u16 netfid
= io_parms
->netfid
;
1868 __u64 offset
= io_parms
->offset
;
1869 struct cifs_tcon
*tcon
= io_parms
->tcon
;
1870 unsigned int count
= io_parms
->length
;
1874 cFYI(1, "write2 at %lld %d bytes", (long long)offset
, count
);
1876 if (tcon
->ses
->capabilities
& CAP_LARGE_FILES
) {
1880 if ((offset
>> 32) > 0) {
1881 /* can not handle big offset for old srv */
1885 rc
= small_smb_init(SMB_COM_WRITE_ANDX
, wct
, tcon
, (void **) &pSMB
);
1889 pSMB
->hdr
.Pid
= cpu_to_le16((__u16
)pid
);
1890 pSMB
->hdr
.PidHigh
= cpu_to_le16((__u16
)(pid
>> 16));
1892 /* tcon and ses pointer are checked in smb_init */
1893 if (tcon
->ses
->server
== NULL
)
1894 return -ECONNABORTED
;
1896 pSMB
->AndXCommand
= 0xFF; /* none */
1898 pSMB
->OffsetLow
= cpu_to_le32(offset
& 0xFFFFFFFF);
1900 pSMB
->OffsetHigh
= cpu_to_le32(offset
>> 32);
1901 pSMB
->Reserved
= 0xFFFFFFFF;
1902 pSMB
->WriteMode
= 0;
1903 pSMB
->Remaining
= 0;
1906 cpu_to_le16(offsetof(struct smb_com_write_req
, Data
) - 4);
1908 pSMB
->DataLengthLow
= cpu_to_le16(count
& 0xFFFF);
1909 pSMB
->DataLengthHigh
= cpu_to_le16(count
>> 16);
1910 /* header + 1 byte pad */
1911 smb_hdr_len
= be32_to_cpu(pSMB
->hdr
.smb_buf_length
) + 1;
1913 inc_rfc1001_len(pSMB
, count
+ 1);
1914 else /* wct == 12 */
1915 inc_rfc1001_len(pSMB
, count
+ 5); /* smb data starts later */
1917 pSMB
->ByteCount
= cpu_to_le16(count
+ 1);
1918 else /* wct == 12 */ /* bigger pad, smaller smb hdr, keep offset ok */ {
1919 struct smb_com_writex_req
*pSMBW
=
1920 (struct smb_com_writex_req
*)pSMB
;
1921 pSMBW
->ByteCount
= cpu_to_le16(count
+ 5);
1923 iov
[0].iov_base
= pSMB
;
1925 iov
[0].iov_len
= smb_hdr_len
+ 4;
1926 else /* wct == 12 pad bigger by four bytes */
1927 iov
[0].iov_len
= smb_hdr_len
+ 8;
1930 rc
= SendReceive2(xid
, tcon
->ses
, iov
, n_vec
+ 1, &resp_buf_type
,
1932 cifs_stats_inc(&tcon
->num_writes
);
1934 cFYI(1, "Send error Write2 = %d", rc
);
1935 } else if (resp_buf_type
== 0) {
1936 /* presumably this can not happen, but best to be safe */
1939 WRITE_RSP
*pSMBr
= (WRITE_RSP
*)iov
[0].iov_base
;
1940 *nbytes
= le16_to_cpu(pSMBr
->CountHigh
);
1941 *nbytes
= (*nbytes
) << 16;
1942 *nbytes
+= le16_to_cpu(pSMBr
->Count
);
1945 * Mask off high 16 bits when bytes written as returned by the
1946 * server is greater than bytes requested by the client. OS/2
1947 * servers are known to set incorrect CountHigh values.
1949 if (*nbytes
> count
)
1953 /* cifs_small_buf_release(pSMB); */ /* Freed earlier now in SendReceive2 */
1954 if (resp_buf_type
== CIFS_SMALL_BUFFER
)
1955 cifs_small_buf_release(iov
[0].iov_base
);
1956 else if (resp_buf_type
== CIFS_LARGE_BUFFER
)
1957 cifs_buf_release(iov
[0].iov_base
);
1959 /* Note: On -EAGAIN error only caller can retry on handle based calls
1960 since file handle passed in no longer valid */
1967 CIFSSMBLock(const int xid
, struct cifs_tcon
*tcon
,
1968 const __u16 smb_file_id
, const __u64 len
,
1969 const __u64 offset
, const __u32 numUnlock
,
1970 const __u32 numLock
, const __u8 lockType
,
1971 const bool waitFlag
, const __u8 oplock_level
)
1974 LOCK_REQ
*pSMB
= NULL
;
1975 /* LOCK_RSP *pSMBr = NULL; */ /* No response data other than rc to parse */
1980 cFYI(1, "CIFSSMBLock timeout %d numLock %d", (int)waitFlag
, numLock
);
1981 rc
= small_smb_init(SMB_COM_LOCKING_ANDX
, 8, tcon
, (void **) &pSMB
);
1986 if (lockType
== LOCKING_ANDX_OPLOCK_RELEASE
) {
1987 timeout
= CIFS_ASYNC_OP
; /* no response expected */
1989 } else if (waitFlag
) {
1990 timeout
= CIFS_BLOCKING_OP
; /* blocking operation, no timeout */
1991 pSMB
->Timeout
= cpu_to_le32(-1);/* blocking - do not time out */
1996 pSMB
->NumberOfLocks
= cpu_to_le16(numLock
);
1997 pSMB
->NumberOfUnlocks
= cpu_to_le16(numUnlock
);
1998 pSMB
->LockType
= lockType
;
1999 pSMB
->OplockLevel
= oplock_level
;
2000 pSMB
->AndXCommand
= 0xFF; /* none */
2001 pSMB
->Fid
= smb_file_id
; /* netfid stays le */
2003 if ((numLock
!= 0) || (numUnlock
!= 0)) {
2004 pSMB
->Locks
[0].Pid
= cpu_to_le16(current
->tgid
);
2005 /* BB where to store pid high? */
2006 pSMB
->Locks
[0].LengthLow
= cpu_to_le32((u32
)len
);
2007 pSMB
->Locks
[0].LengthHigh
= cpu_to_le32((u32
)(len
>>32));
2008 pSMB
->Locks
[0].OffsetLow
= cpu_to_le32((u32
)offset
);
2009 pSMB
->Locks
[0].OffsetHigh
= cpu_to_le32((u32
)(offset
>>32));
2010 count
= sizeof(LOCKING_ANDX_RANGE
);
2015 inc_rfc1001_len(pSMB
, count
);
2016 pSMB
->ByteCount
= cpu_to_le16(count
);
2019 rc
= SendReceiveBlockingLock(xid
, tcon
, (struct smb_hdr
*) pSMB
,
2020 (struct smb_hdr
*) pSMB
, &bytes_returned
);
2021 cifs_small_buf_release(pSMB
);
2023 rc
= SendReceiveNoRsp(xid
, tcon
->ses
, (struct smb_hdr
*)pSMB
,
2025 /* SMB buffer freed by function above */
2027 cifs_stats_inc(&tcon
->num_locks
);
2029 cFYI(1, "Send error in Lock = %d", rc
);
2031 /* Note: On -EAGAIN error only caller can retry on handle based calls
2032 since file handle passed in no longer valid */
2037 CIFSSMBPosixLock(const int xid
, struct cifs_tcon
*tcon
,
2038 const __u16 smb_file_id
, const int get_flag
, const __u64 len
,
2039 struct file_lock
*pLockData
, const __u16 lock_type
,
2040 const bool waitFlag
)
2042 struct smb_com_transaction2_sfi_req
*pSMB
= NULL
;
2043 struct smb_com_transaction2_sfi_rsp
*pSMBr
= NULL
;
2044 struct cifs_posix_lock
*parm_data
;
2047 int bytes_returned
= 0;
2048 int resp_buf_type
= 0;
2049 __u16 params
, param_offset
, offset
, byte_count
, count
;
2052 cFYI(1, "Posix Lock");
2054 if (pLockData
== NULL
)
2057 rc
= small_smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
);
2062 pSMBr
= (struct smb_com_transaction2_sfi_rsp
*)pSMB
;
2065 pSMB
->MaxSetupCount
= 0;
2068 pSMB
->Reserved2
= 0;
2069 param_offset
= offsetof(struct smb_com_transaction2_sfi_req
, Fid
) - 4;
2070 offset
= param_offset
+ params
;
2072 count
= sizeof(struct cifs_posix_lock
);
2073 pSMB
->MaxParameterCount
= cpu_to_le16(2);
2074 pSMB
->MaxDataCount
= cpu_to_le16(1000); /* BB find max SMB from sess */
2075 pSMB
->SetupCount
= 1;
2076 pSMB
->Reserved3
= 0;
2078 pSMB
->SubCommand
= cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION
);
2080 pSMB
->SubCommand
= cpu_to_le16(TRANS2_SET_FILE_INFORMATION
);
2081 byte_count
= 3 /* pad */ + params
+ count
;
2082 pSMB
->DataCount
= cpu_to_le16(count
);
2083 pSMB
->ParameterCount
= cpu_to_le16(params
);
2084 pSMB
->TotalDataCount
= pSMB
->DataCount
;
2085 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
2086 pSMB
->ParameterOffset
= cpu_to_le16(param_offset
);
2087 parm_data
= (struct cifs_posix_lock
*)
2088 (((char *) &pSMB
->hdr
.Protocol
) + offset
);
2090 parm_data
->lock_type
= cpu_to_le16(lock_type
);
2092 timeout
= CIFS_BLOCKING_OP
; /* blocking operation, no timeout */
2093 parm_data
->lock_flags
= cpu_to_le16(1);
2094 pSMB
->Timeout
= cpu_to_le32(-1);
2098 parm_data
->pid
= cpu_to_le32(current
->tgid
);
2099 parm_data
->start
= cpu_to_le64(pLockData
->fl_start
);
2100 parm_data
->length
= cpu_to_le64(len
); /* normalize negative numbers */
2102 pSMB
->DataOffset
= cpu_to_le16(offset
);
2103 pSMB
->Fid
= smb_file_id
;
2104 pSMB
->InformationLevel
= cpu_to_le16(SMB_SET_POSIX_LOCK
);
2105 pSMB
->Reserved4
= 0;
2106 inc_rfc1001_len(pSMB
, byte_count
);
2107 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
2109 rc
= SendReceiveBlockingLock(xid
, tcon
, (struct smb_hdr
*) pSMB
,
2110 (struct smb_hdr
*) pSMBr
, &bytes_returned
);
2112 iov
[0].iov_base
= (char *)pSMB
;
2113 iov
[0].iov_len
= be32_to_cpu(pSMB
->hdr
.smb_buf_length
) + 4;
2114 rc
= SendReceive2(xid
, tcon
->ses
, iov
, 1 /* num iovecs */,
2115 &resp_buf_type
, timeout
);
2116 pSMB
= NULL
; /* request buf already freed by SendReceive2. Do
2117 not try to free it twice below on exit */
2118 pSMBr
= (struct smb_com_transaction2_sfi_rsp
*)iov
[0].iov_base
;
2122 cFYI(1, "Send error in Posix Lock = %d", rc
);
2123 } else if (get_flag
) {
2124 /* lock structure can be returned on get */
2127 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
2129 if (rc
|| get_bcc(&pSMBr
->hdr
) < sizeof(*parm_data
)) {
2130 rc
= -EIO
; /* bad smb */
2133 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
2134 data_count
= le16_to_cpu(pSMBr
->t2
.DataCount
);
2135 if (data_count
< sizeof(struct cifs_posix_lock
)) {
2139 parm_data
= (struct cifs_posix_lock
*)
2140 ((char *)&pSMBr
->hdr
.Protocol
+ data_offset
);
2141 if (parm_data
->lock_type
== __constant_cpu_to_le16(CIFS_UNLCK
))
2142 pLockData
->fl_type
= F_UNLCK
;
2144 if (parm_data
->lock_type
==
2145 __constant_cpu_to_le16(CIFS_RDLCK
))
2146 pLockData
->fl_type
= F_RDLCK
;
2147 else if (parm_data
->lock_type
==
2148 __constant_cpu_to_le16(CIFS_WRLCK
))
2149 pLockData
->fl_type
= F_WRLCK
;
2151 pLockData
->fl_start
= le64_to_cpu(parm_data
->start
);
2152 pLockData
->fl_end
= pLockData
->fl_start
+
2153 le64_to_cpu(parm_data
->length
) - 1;
2154 pLockData
->fl_pid
= le32_to_cpu(parm_data
->pid
);
2160 cifs_small_buf_release(pSMB
);
2162 if (resp_buf_type
== CIFS_SMALL_BUFFER
)
2163 cifs_small_buf_release(iov
[0].iov_base
);
2164 else if (resp_buf_type
== CIFS_LARGE_BUFFER
)
2165 cifs_buf_release(iov
[0].iov_base
);
2167 /* Note: On -EAGAIN error only caller can retry on handle based calls
2168 since file handle passed in no longer valid */
2175 CIFSSMBClose(const int xid
, struct cifs_tcon
*tcon
, int smb_file_id
)
2178 CLOSE_REQ
*pSMB
= NULL
;
2179 cFYI(1, "In CIFSSMBClose");
2181 /* do not retry on dead session on close */
2182 rc
= small_smb_init(SMB_COM_CLOSE
, 3, tcon
, (void **) &pSMB
);
2188 pSMB
->FileID
= (__u16
) smb_file_id
;
2189 pSMB
->LastWriteTime
= 0xFFFFFFFF;
2190 pSMB
->ByteCount
= 0;
2191 rc
= SendReceiveNoRsp(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
, 0);
2192 cifs_stats_inc(&tcon
->num_closes
);
2195 /* EINTR is expected when user ctl-c to kill app */
2196 cERROR(1, "Send error in Close = %d", rc
);
2200 /* Since session is dead, file will be closed on server already */
2208 CIFSSMBFlush(const int xid
, struct cifs_tcon
*tcon
, int smb_file_id
)
2211 FLUSH_REQ
*pSMB
= NULL
;
2212 cFYI(1, "In CIFSSMBFlush");
2214 rc
= small_smb_init(SMB_COM_FLUSH
, 1, tcon
, (void **) &pSMB
);
2218 pSMB
->FileID
= (__u16
) smb_file_id
;
2219 pSMB
->ByteCount
= 0;
2220 rc
= SendReceiveNoRsp(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
, 0);
2221 cifs_stats_inc(&tcon
->num_flushes
);
2223 cERROR(1, "Send error in Flush = %d", rc
);
2229 CIFSSMBRename(const int xid
, struct cifs_tcon
*tcon
,
2230 const char *fromName
, const char *toName
,
2231 const struct nls_table
*nls_codepage
, int remap
)
2234 RENAME_REQ
*pSMB
= NULL
;
2235 RENAME_RSP
*pSMBr
= NULL
;
2237 int name_len
, name_len2
;
2240 cFYI(1, "In CIFSSMBRename");
2242 rc
= smb_init(SMB_COM_RENAME
, 1, tcon
, (void **) &pSMB
,
2247 pSMB
->BufferFormat
= 0x04;
2248 pSMB
->SearchAttributes
=
2249 cpu_to_le16(ATTR_READONLY
| ATTR_HIDDEN
| ATTR_SYSTEM
|
2252 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
2254 cifsConvertToUCS((__le16
*) pSMB
->OldFileName
, fromName
,
2255 PATH_MAX
, nls_codepage
, remap
);
2256 name_len
++; /* trailing null */
2258 pSMB
->OldFileName
[name_len
] = 0x04; /* pad */
2259 /* protocol requires ASCII signature byte on Unicode string */
2260 pSMB
->OldFileName
[name_len
+ 1] = 0x00;
2262 cifsConvertToUCS((__le16
*)&pSMB
->OldFileName
[name_len
+ 2],
2263 toName
, PATH_MAX
, nls_codepage
, remap
);
2264 name_len2
+= 1 /* trailing null */ + 1 /* Signature word */ ;
2265 name_len2
*= 2; /* convert to bytes */
2266 } else { /* BB improve the check for buffer overruns BB */
2267 name_len
= strnlen(fromName
, PATH_MAX
);
2268 name_len
++; /* trailing null */
2269 strncpy(pSMB
->OldFileName
, fromName
, name_len
);
2270 name_len2
= strnlen(toName
, PATH_MAX
);
2271 name_len2
++; /* trailing null */
2272 pSMB
->OldFileName
[name_len
] = 0x04; /* 2nd buffer format */
2273 strncpy(&pSMB
->OldFileName
[name_len
+ 1], toName
, name_len2
);
2274 name_len2
++; /* trailing null */
2275 name_len2
++; /* signature byte */
2278 count
= 1 /* 1st signature byte */ + name_len
+ name_len2
;
2279 inc_rfc1001_len(pSMB
, count
);
2280 pSMB
->ByteCount
= cpu_to_le16(count
);
2282 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
2283 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
2284 cifs_stats_inc(&tcon
->num_renames
);
2286 cFYI(1, "Send error in rename = %d", rc
);
2288 cifs_buf_release(pSMB
);
2296 int CIFSSMBRenameOpenFile(const int xid
, struct cifs_tcon
*pTcon
,
2297 int netfid
, const char *target_name
,
2298 const struct nls_table
*nls_codepage
, int remap
)
2300 struct smb_com_transaction2_sfi_req
*pSMB
= NULL
;
2301 struct smb_com_transaction2_sfi_rsp
*pSMBr
= NULL
;
2302 struct set_file_rename
*rename_info
;
2304 char dummy_string
[30];
2306 int bytes_returned
= 0;
2308 __u16 params
, param_offset
, offset
, count
, byte_count
;
2310 cFYI(1, "Rename to File by handle");
2311 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, pTcon
, (void **) &pSMB
,
2317 pSMB
->MaxSetupCount
= 0;
2321 pSMB
->Reserved2
= 0;
2322 param_offset
= offsetof(struct smb_com_transaction2_sfi_req
, Fid
) - 4;
2323 offset
= param_offset
+ params
;
2325 data_offset
= (char *) (&pSMB
->hdr
.Protocol
) + offset
;
2326 rename_info
= (struct set_file_rename
*) data_offset
;
2327 pSMB
->MaxParameterCount
= cpu_to_le16(2);
2328 pSMB
->MaxDataCount
= cpu_to_le16(1000); /* BB find max SMB from sess */
2329 pSMB
->SetupCount
= 1;
2330 pSMB
->Reserved3
= 0;
2331 pSMB
->SubCommand
= cpu_to_le16(TRANS2_SET_FILE_INFORMATION
);
2332 byte_count
= 3 /* pad */ + params
;
2333 pSMB
->ParameterCount
= cpu_to_le16(params
);
2334 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
2335 pSMB
->ParameterOffset
= cpu_to_le16(param_offset
);
2336 pSMB
->DataOffset
= cpu_to_le16(offset
);
2337 /* construct random name ".cifs_tmp<inodenum><mid>" */
2338 rename_info
->overwrite
= cpu_to_le32(1);
2339 rename_info
->root_fid
= 0;
2340 /* unicode only call */
2341 if (target_name
== NULL
) {
2342 sprintf(dummy_string
, "cifs%x", pSMB
->hdr
.Mid
);
2343 len_of_str
= cifsConvertToUCS((__le16
*)rename_info
->target_name
,
2344 dummy_string
, 24, nls_codepage
, remap
);
2346 len_of_str
= cifsConvertToUCS((__le16
*)rename_info
->target_name
,
2347 target_name
, PATH_MAX
, nls_codepage
,
2350 rename_info
->target_name_len
= cpu_to_le32(2 * len_of_str
);
2351 count
= 12 /* sizeof(struct set_file_rename) */ + (2 * len_of_str
);
2352 byte_count
+= count
;
2353 pSMB
->DataCount
= cpu_to_le16(count
);
2354 pSMB
->TotalDataCount
= pSMB
->DataCount
;
2356 pSMB
->InformationLevel
=
2357 cpu_to_le16(SMB_SET_FILE_RENAME_INFORMATION
);
2358 pSMB
->Reserved4
= 0;
2359 inc_rfc1001_len(pSMB
, byte_count
);
2360 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
2361 rc
= SendReceive(xid
, pTcon
->ses
, (struct smb_hdr
*) pSMB
,
2362 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
2363 cifs_stats_inc(&pTcon
->num_t2renames
);
2365 cFYI(1, "Send error in Rename (by file handle) = %d", rc
);
2367 cifs_buf_release(pSMB
);
2369 /* Note: On -EAGAIN error only caller can retry on handle based calls
2370 since file handle passed in no longer valid */
2376 CIFSSMBCopy(const int xid
, struct cifs_tcon
*tcon
, const char *fromName
,
2377 const __u16 target_tid
, const char *toName
, const int flags
,
2378 const struct nls_table
*nls_codepage
, int remap
)
2381 COPY_REQ
*pSMB
= NULL
;
2382 COPY_RSP
*pSMBr
= NULL
;
2384 int name_len
, name_len2
;
2387 cFYI(1, "In CIFSSMBCopy");
2389 rc
= smb_init(SMB_COM_COPY
, 1, tcon
, (void **) &pSMB
,
2394 pSMB
->BufferFormat
= 0x04;
2395 pSMB
->Tid2
= target_tid
;
2397 pSMB
->Flags
= cpu_to_le16(flags
& COPY_TREE
);
2399 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
2400 name_len
= cifsConvertToUCS((__le16
*) pSMB
->OldFileName
,
2401 fromName
, PATH_MAX
, nls_codepage
,
2403 name_len
++; /* trailing null */
2405 pSMB
->OldFileName
[name_len
] = 0x04; /* pad */
2406 /* protocol requires ASCII signature byte on Unicode string */
2407 pSMB
->OldFileName
[name_len
+ 1] = 0x00;
2409 cifsConvertToUCS((__le16
*)&pSMB
->OldFileName
[name_len
+ 2],
2410 toName
, PATH_MAX
, nls_codepage
, remap
);
2411 name_len2
+= 1 /* trailing null */ + 1 /* Signature word */ ;
2412 name_len2
*= 2; /* convert to bytes */
2413 } else { /* BB improve the check for buffer overruns BB */
2414 name_len
= strnlen(fromName
, PATH_MAX
);
2415 name_len
++; /* trailing null */
2416 strncpy(pSMB
->OldFileName
, fromName
, name_len
);
2417 name_len2
= strnlen(toName
, PATH_MAX
);
2418 name_len2
++; /* trailing null */
2419 pSMB
->OldFileName
[name_len
] = 0x04; /* 2nd buffer format */
2420 strncpy(&pSMB
->OldFileName
[name_len
+ 1], toName
, name_len2
);
2421 name_len2
++; /* trailing null */
2422 name_len2
++; /* signature byte */
2425 count
= 1 /* 1st signature byte */ + name_len
+ name_len2
;
2426 inc_rfc1001_len(pSMB
, count
);
2427 pSMB
->ByteCount
= cpu_to_le16(count
);
2429 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
2430 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
2432 cFYI(1, "Send error in copy = %d with %d files copied",
2433 rc
, le16_to_cpu(pSMBr
->CopyCount
));
2435 cifs_buf_release(pSMB
);
2444 CIFSUnixCreateSymLink(const int xid
, struct cifs_tcon
*tcon
,
2445 const char *fromName
, const char *toName
,
2446 const struct nls_table
*nls_codepage
)
2448 TRANSACTION2_SPI_REQ
*pSMB
= NULL
;
2449 TRANSACTION2_SPI_RSP
*pSMBr
= NULL
;
2452 int name_len_target
;
2454 int bytes_returned
= 0;
2455 __u16 params
, param_offset
, offset
, byte_count
;
2457 cFYI(1, "In Symlink Unix style");
2459 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
2464 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
2466 cifs_strtoUCS((__le16
*) pSMB
->FileName
, fromName
, PATH_MAX
2467 /* find define for this maxpathcomponent */
2469 name_len
++; /* trailing null */
2472 } else { /* BB improve the check for buffer overruns BB */
2473 name_len
= strnlen(fromName
, PATH_MAX
);
2474 name_len
++; /* trailing null */
2475 strncpy(pSMB
->FileName
, fromName
, name_len
);
2477 params
= 6 + name_len
;
2478 pSMB
->MaxSetupCount
= 0;
2482 pSMB
->Reserved2
= 0;
2483 param_offset
= offsetof(struct smb_com_transaction2_spi_req
,
2484 InformationLevel
) - 4;
2485 offset
= param_offset
+ params
;
2487 data_offset
= (char *) (&pSMB
->hdr
.Protocol
) + offset
;
2488 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
2490 cifs_strtoUCS((__le16
*) data_offset
, toName
, PATH_MAX
2491 /* find define for this maxpathcomponent */
2493 name_len_target
++; /* trailing null */
2494 name_len_target
*= 2;
2495 } else { /* BB improve the check for buffer overruns BB */
2496 name_len_target
= strnlen(toName
, PATH_MAX
);
2497 name_len_target
++; /* trailing null */
2498 strncpy(data_offset
, toName
, name_len_target
);
2501 pSMB
->MaxParameterCount
= cpu_to_le16(2);
2502 /* BB find exact max on data count below from sess */
2503 pSMB
->MaxDataCount
= cpu_to_le16(1000);
2504 pSMB
->SetupCount
= 1;
2505 pSMB
->Reserved3
= 0;
2506 pSMB
->SubCommand
= cpu_to_le16(TRANS2_SET_PATH_INFORMATION
);
2507 byte_count
= 3 /* pad */ + params
+ name_len_target
;
2508 pSMB
->DataCount
= cpu_to_le16(name_len_target
);
2509 pSMB
->ParameterCount
= cpu_to_le16(params
);
2510 pSMB
->TotalDataCount
= pSMB
->DataCount
;
2511 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
2512 pSMB
->ParameterOffset
= cpu_to_le16(param_offset
);
2513 pSMB
->DataOffset
= cpu_to_le16(offset
);
2514 pSMB
->InformationLevel
= cpu_to_le16(SMB_SET_FILE_UNIX_LINK
);
2515 pSMB
->Reserved4
= 0;
2516 inc_rfc1001_len(pSMB
, byte_count
);
2517 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
2518 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
2519 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
2520 cifs_stats_inc(&tcon
->num_symlinks
);
2522 cFYI(1, "Send error in SetPathInfo create symlink = %d", rc
);
2524 cifs_buf_release(pSMB
);
2527 goto createSymLinkRetry
;
2533 CIFSUnixCreateHardLink(const int xid
, struct cifs_tcon
*tcon
,
2534 const char *fromName
, const char *toName
,
2535 const struct nls_table
*nls_codepage
, int remap
)
2537 TRANSACTION2_SPI_REQ
*pSMB
= NULL
;
2538 TRANSACTION2_SPI_RSP
*pSMBr
= NULL
;
2541 int name_len_target
;
2543 int bytes_returned
= 0;
2544 __u16 params
, param_offset
, offset
, byte_count
;
2546 cFYI(1, "In Create Hard link Unix style");
2547 createHardLinkRetry
:
2548 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
2553 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
2554 name_len
= cifsConvertToUCS((__le16
*) pSMB
->FileName
, toName
,
2555 PATH_MAX
, nls_codepage
, remap
);
2556 name_len
++; /* trailing null */
2559 } else { /* BB improve the check for buffer overruns BB */
2560 name_len
= strnlen(toName
, PATH_MAX
);
2561 name_len
++; /* trailing null */
2562 strncpy(pSMB
->FileName
, toName
, name_len
);
2564 params
= 6 + name_len
;
2565 pSMB
->MaxSetupCount
= 0;
2569 pSMB
->Reserved2
= 0;
2570 param_offset
= offsetof(struct smb_com_transaction2_spi_req
,
2571 InformationLevel
) - 4;
2572 offset
= param_offset
+ params
;
2574 data_offset
= (char *) (&pSMB
->hdr
.Protocol
) + offset
;
2575 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
2577 cifsConvertToUCS((__le16
*) data_offset
, fromName
, PATH_MAX
,
2578 nls_codepage
, remap
);
2579 name_len_target
++; /* trailing null */
2580 name_len_target
*= 2;
2581 } else { /* BB improve the check for buffer overruns BB */
2582 name_len_target
= strnlen(fromName
, PATH_MAX
);
2583 name_len_target
++; /* trailing null */
2584 strncpy(data_offset
, fromName
, name_len_target
);
2587 pSMB
->MaxParameterCount
= cpu_to_le16(2);
2588 /* BB find exact max on data count below from sess*/
2589 pSMB
->MaxDataCount
= cpu_to_le16(1000);
2590 pSMB
->SetupCount
= 1;
2591 pSMB
->Reserved3
= 0;
2592 pSMB
->SubCommand
= cpu_to_le16(TRANS2_SET_PATH_INFORMATION
);
2593 byte_count
= 3 /* pad */ + params
+ name_len_target
;
2594 pSMB
->ParameterCount
= cpu_to_le16(params
);
2595 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
2596 pSMB
->DataCount
= cpu_to_le16(name_len_target
);
2597 pSMB
->TotalDataCount
= pSMB
->DataCount
;
2598 pSMB
->ParameterOffset
= cpu_to_le16(param_offset
);
2599 pSMB
->DataOffset
= cpu_to_le16(offset
);
2600 pSMB
->InformationLevel
= cpu_to_le16(SMB_SET_FILE_UNIX_HLINK
);
2601 pSMB
->Reserved4
= 0;
2602 inc_rfc1001_len(pSMB
, byte_count
);
2603 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
2604 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
2605 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
2606 cifs_stats_inc(&tcon
->num_hardlinks
);
2608 cFYI(1, "Send error in SetPathInfo (hard link) = %d", rc
);
2610 cifs_buf_release(pSMB
);
2612 goto createHardLinkRetry
;
2618 CIFSCreateHardLink(const int xid
, struct cifs_tcon
*tcon
,
2619 const char *fromName
, const char *toName
,
2620 const struct nls_table
*nls_codepage
, int remap
)
2623 NT_RENAME_REQ
*pSMB
= NULL
;
2624 RENAME_RSP
*pSMBr
= NULL
;
2626 int name_len
, name_len2
;
2629 cFYI(1, "In CIFSCreateHardLink");
2630 winCreateHardLinkRetry
:
2632 rc
= smb_init(SMB_COM_NT_RENAME
, 4, tcon
, (void **) &pSMB
,
2637 pSMB
->SearchAttributes
=
2638 cpu_to_le16(ATTR_READONLY
| ATTR_HIDDEN
| ATTR_SYSTEM
|
2640 pSMB
->Flags
= cpu_to_le16(CREATE_HARD_LINK
);
2641 pSMB
->ClusterCount
= 0;
2643 pSMB
->BufferFormat
= 0x04;
2645 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
2647 cifsConvertToUCS((__le16
*) pSMB
->OldFileName
, fromName
,
2648 PATH_MAX
, nls_codepage
, remap
);
2649 name_len
++; /* trailing null */
2652 /* protocol specifies ASCII buffer format (0x04) for unicode */
2653 pSMB
->OldFileName
[name_len
] = 0x04;
2654 pSMB
->OldFileName
[name_len
+ 1] = 0x00; /* pad */
2656 cifsConvertToUCS((__le16
*)&pSMB
->OldFileName
[name_len
+ 2],
2657 toName
, PATH_MAX
, nls_codepage
, remap
);
2658 name_len2
+= 1 /* trailing null */ + 1 /* Signature word */ ;
2659 name_len2
*= 2; /* convert to bytes */
2660 } else { /* BB improve the check for buffer overruns BB */
2661 name_len
= strnlen(fromName
, PATH_MAX
);
2662 name_len
++; /* trailing null */
2663 strncpy(pSMB
->OldFileName
, fromName
, name_len
);
2664 name_len2
= strnlen(toName
, PATH_MAX
);
2665 name_len2
++; /* trailing null */
2666 pSMB
->OldFileName
[name_len
] = 0x04; /* 2nd buffer format */
2667 strncpy(&pSMB
->OldFileName
[name_len
+ 1], toName
, name_len2
);
2668 name_len2
++; /* trailing null */
2669 name_len2
++; /* signature byte */
2672 count
= 1 /* string type byte */ + name_len
+ name_len2
;
2673 inc_rfc1001_len(pSMB
, count
);
2674 pSMB
->ByteCount
= cpu_to_le16(count
);
2676 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
2677 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
2678 cifs_stats_inc(&tcon
->num_hardlinks
);
2680 cFYI(1, "Send error in hard link (NT rename) = %d", rc
);
2682 cifs_buf_release(pSMB
);
2684 goto winCreateHardLinkRetry
;
2690 CIFSSMBUnixQuerySymLink(const int xid
, struct cifs_tcon
*tcon
,
2691 const unsigned char *searchName
, char **symlinkinfo
,
2692 const struct nls_table
*nls_codepage
)
2694 /* SMB_QUERY_FILE_UNIX_LINK */
2695 TRANSACTION2_QPI_REQ
*pSMB
= NULL
;
2696 TRANSACTION2_QPI_RSP
*pSMBr
= NULL
;
2700 __u16 params
, byte_count
;
2703 cFYI(1, "In QPathSymLinkInfo (Unix) for path %s", searchName
);
2706 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
2711 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
2713 cifs_strtoUCS((__le16
*) pSMB
->FileName
, searchName
,
2714 PATH_MAX
, nls_codepage
);
2715 name_len
++; /* trailing null */
2717 } else { /* BB improve the check for buffer overruns BB */
2718 name_len
= strnlen(searchName
, PATH_MAX
);
2719 name_len
++; /* trailing null */
2720 strncpy(pSMB
->FileName
, searchName
, name_len
);
2723 params
= 2 /* level */ + 4 /* rsrvd */ + name_len
/* incl null */ ;
2724 pSMB
->TotalDataCount
= 0;
2725 pSMB
->MaxParameterCount
= cpu_to_le16(2);
2726 pSMB
->MaxDataCount
= cpu_to_le16(CIFSMaxBufSize
);
2727 pSMB
->MaxSetupCount
= 0;
2731 pSMB
->Reserved2
= 0;
2732 pSMB
->ParameterOffset
= cpu_to_le16(offsetof(
2733 struct smb_com_transaction2_qpi_req
, InformationLevel
) - 4);
2734 pSMB
->DataCount
= 0;
2735 pSMB
->DataOffset
= 0;
2736 pSMB
->SetupCount
= 1;
2737 pSMB
->Reserved3
= 0;
2738 pSMB
->SubCommand
= cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION
);
2739 byte_count
= params
+ 1 /* pad */ ;
2740 pSMB
->TotalParameterCount
= cpu_to_le16(params
);
2741 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
2742 pSMB
->InformationLevel
= cpu_to_le16(SMB_QUERY_FILE_UNIX_LINK
);
2743 pSMB
->Reserved4
= 0;
2744 inc_rfc1001_len(pSMB
, byte_count
);
2745 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
2747 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
2748 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
2750 cFYI(1, "Send error in QuerySymLinkInfo = %d", rc
);
2752 /* decode response */
2754 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
2755 /* BB also check enough total bytes returned */
2756 if (rc
|| get_bcc(&pSMBr
->hdr
) < 2)
2760 u16 count
= le16_to_cpu(pSMBr
->t2
.DataCount
);
2762 data_start
= ((char *) &pSMBr
->hdr
.Protocol
) +
2763 le16_to_cpu(pSMBr
->t2
.DataOffset
);
2765 if (pSMBr
->hdr
.Flags2
& SMBFLG2_UNICODE
)
2770 /* BB FIXME investigate remapping reserved chars here */
2771 *symlinkinfo
= cifs_strndup_from_ucs(data_start
, count
,
2772 is_unicode
, nls_codepage
);
2777 cifs_buf_release(pSMB
);
2779 goto querySymLinkRetry
;
2783 #ifdef CONFIG_CIFS_SYMLINK_EXPERIMENTAL
2785 * Recent Windows versions now create symlinks more frequently
2786 * and they use the "reparse point" mechanism below. We can of course
2787 * do symlinks nicely to Samba and other servers which support the
2788 * CIFS Unix Extensions and we can also do SFU symlinks and "client only"
2789 * "MF" symlinks optionally, but for recent Windows we really need to
2790 * reenable the code below and fix the cifs_symlink callers to handle this.
2791 * In the interim this code has been moved to its own config option so
2792 * it is not compiled in by default until callers fixed up and more tested.
2795 CIFSSMBQueryReparseLinkInfo(const int xid
, struct cifs_tcon
*tcon
,
2796 const unsigned char *searchName
,
2797 char *symlinkinfo
, const int buflen
, __u16 fid
,
2798 const struct nls_table
*nls_codepage
)
2802 struct smb_com_transaction_ioctl_req
*pSMB
;
2803 struct smb_com_transaction_ioctl_rsp
*pSMBr
;
2805 cFYI(1, "In Windows reparse style QueryLink for path %s", searchName
);
2806 rc
= smb_init(SMB_COM_NT_TRANSACT
, 23, tcon
, (void **) &pSMB
,
2811 pSMB
->TotalParameterCount
= 0 ;
2812 pSMB
->TotalDataCount
= 0;
2813 pSMB
->MaxParameterCount
= cpu_to_le32(2);
2814 /* BB find exact data count max from sess structure BB */
2815 pSMB
->MaxDataCount
= cpu_to_le32((tcon
->ses
->server
->maxBuf
-
2816 MAX_CIFS_HDR_SIZE
) & 0xFFFFFF00);
2817 pSMB
->MaxSetupCount
= 4;
2819 pSMB
->ParameterOffset
= 0;
2820 pSMB
->DataCount
= 0;
2821 pSMB
->DataOffset
= 0;
2822 pSMB
->SetupCount
= 4;
2823 pSMB
->SubCommand
= cpu_to_le16(NT_TRANSACT_IOCTL
);
2824 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
2825 pSMB
->FunctionCode
= cpu_to_le32(FSCTL_GET_REPARSE_POINT
);
2826 pSMB
->IsFsctl
= 1; /* FSCTL */
2827 pSMB
->IsRootFlag
= 0;
2828 pSMB
->Fid
= fid
; /* file handle always le */
2829 pSMB
->ByteCount
= 0;
2831 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
2832 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
2834 cFYI(1, "Send error in QueryReparseLinkInfo = %d", rc
);
2835 } else { /* decode response */
2836 __u32 data_offset
= le32_to_cpu(pSMBr
->DataOffset
);
2837 __u32 data_count
= le32_to_cpu(pSMBr
->DataCount
);
2838 if (get_bcc(&pSMBr
->hdr
) < 2 || data_offset
> 512) {
2839 /* BB also check enough total bytes returned */
2840 rc
= -EIO
; /* bad smb */
2843 if (data_count
&& (data_count
< 2048)) {
2844 char *end_of_smb
= 2 /* sizeof byte count */ +
2845 get_bcc(&pSMBr
->hdr
) + (char *)&pSMBr
->ByteCount
;
2847 struct reparse_data
*reparse_buf
=
2848 (struct reparse_data
*)
2849 ((char *)&pSMBr
->hdr
.Protocol
2851 if ((char *)reparse_buf
>= end_of_smb
) {
2855 if ((reparse_buf
->LinkNamesBuf
+
2856 reparse_buf
->TargetNameOffset
+
2857 reparse_buf
->TargetNameLen
) > end_of_smb
) {
2858 cFYI(1, "reparse buf beyond SMB");
2863 if (pSMBr
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
2864 cifs_from_ucs2(symlinkinfo
, (__le16
*)
2865 (reparse_buf
->LinkNamesBuf
+
2866 reparse_buf
->TargetNameOffset
),
2868 reparse_buf
->TargetNameLen
,
2870 } else { /* ASCII names */
2871 strncpy(symlinkinfo
,
2872 reparse_buf
->LinkNamesBuf
+
2873 reparse_buf
->TargetNameOffset
,
2874 min_t(const int, buflen
,
2875 reparse_buf
->TargetNameLen
));
2879 cFYI(1, "Invalid return data count on "
2880 "get reparse info ioctl");
2882 symlinkinfo
[buflen
] = 0; /* just in case so the caller
2883 does not go off the end of the buffer */
2884 cFYI(1, "readlink result - %s", symlinkinfo
);
2888 cifs_buf_release(pSMB
);
2890 /* Note: On -EAGAIN error only caller can retry on handle based calls
2891 since file handle passed in no longer valid */
2895 #endif /* CIFS_SYMLINK_EXPERIMENTAL */ /* BB temporarily unused */
2897 #ifdef CONFIG_CIFS_POSIX
2899 /*Convert an Access Control Entry from wire format to local POSIX xattr format*/
2900 static void cifs_convert_ace(posix_acl_xattr_entry
*ace
,
2901 struct cifs_posix_ace
*cifs_ace
)
2903 /* u8 cifs fields do not need le conversion */
2904 ace
->e_perm
= cpu_to_le16(cifs_ace
->cifs_e_perm
);
2905 ace
->e_tag
= cpu_to_le16(cifs_ace
->cifs_e_tag
);
2906 ace
->e_id
= cpu_to_le32(le64_to_cpu(cifs_ace
->cifs_uid
));
2907 /* cFYI(1, "perm %d tag %d id %d",ace->e_perm,ace->e_tag,ace->e_id); */
2912 /* Convert ACL from CIFS POSIX wire format to local Linux POSIX ACL xattr */
2913 static int cifs_copy_posix_acl(char *trgt
, char *src
, const int buflen
,
2914 const int acl_type
, const int size_of_data_area
)
2919 struct cifs_posix_ace
*pACE
;
2920 struct cifs_posix_acl
*cifs_acl
= (struct cifs_posix_acl
*)src
;
2921 posix_acl_xattr_header
*local_acl
= (posix_acl_xattr_header
*)trgt
;
2923 if (le16_to_cpu(cifs_acl
->version
) != CIFS_ACL_VERSION
)
2926 if (acl_type
& ACL_TYPE_ACCESS
) {
2927 count
= le16_to_cpu(cifs_acl
->access_entry_count
);
2928 pACE
= &cifs_acl
->ace_array
[0];
2929 size
= sizeof(struct cifs_posix_acl
);
2930 size
+= sizeof(struct cifs_posix_ace
) * count
;
2931 /* check if we would go beyond end of SMB */
2932 if (size_of_data_area
< size
) {
2933 cFYI(1, "bad CIFS POSIX ACL size %d vs. %d",
2934 size_of_data_area
, size
);
2937 } else if (acl_type
& ACL_TYPE_DEFAULT
) {
2938 count
= le16_to_cpu(cifs_acl
->access_entry_count
);
2939 size
= sizeof(struct cifs_posix_acl
);
2940 size
+= sizeof(struct cifs_posix_ace
) * count
;
2941 /* skip past access ACEs to get to default ACEs */
2942 pACE
= &cifs_acl
->ace_array
[count
];
2943 count
= le16_to_cpu(cifs_acl
->default_entry_count
);
2944 size
+= sizeof(struct cifs_posix_ace
) * count
;
2945 /* check if we would go beyond end of SMB */
2946 if (size_of_data_area
< size
)
2953 size
= posix_acl_xattr_size(count
);
2954 if ((buflen
== 0) || (local_acl
== NULL
)) {
2955 /* used to query ACL EA size */
2956 } else if (size
> buflen
) {
2958 } else /* buffer big enough */ {
2959 local_acl
->a_version
= cpu_to_le32(POSIX_ACL_XATTR_VERSION
);
2960 for (i
= 0; i
< count
; i
++) {
2961 cifs_convert_ace(&local_acl
->a_entries
[i
], pACE
);
2968 static __u16
convert_ace_to_cifs_ace(struct cifs_posix_ace
*cifs_ace
,
2969 const posix_acl_xattr_entry
*local_ace
)
2971 __u16 rc
= 0; /* 0 = ACL converted ok */
2973 cifs_ace
->cifs_e_perm
= le16_to_cpu(local_ace
->e_perm
);
2974 cifs_ace
->cifs_e_tag
= le16_to_cpu(local_ace
->e_tag
);
2975 /* BB is there a better way to handle the large uid? */
2976 if (local_ace
->e_id
== cpu_to_le32(-1)) {
2977 /* Probably no need to le convert -1 on any arch but can not hurt */
2978 cifs_ace
->cifs_uid
= cpu_to_le64(-1);
2980 cifs_ace
->cifs_uid
= cpu_to_le64(le32_to_cpu(local_ace
->e_id
));
2981 /*cFYI(1, "perm %d tag %d id %d",ace->e_perm,ace->e_tag,ace->e_id);*/
2985 /* Convert ACL from local Linux POSIX xattr to CIFS POSIX ACL wire format */
2986 static __u16
ACL_to_cifs_posix(char *parm_data
, const char *pACL
,
2987 const int buflen
, const int acl_type
)
2990 struct cifs_posix_acl
*cifs_acl
= (struct cifs_posix_acl
*)parm_data
;
2991 posix_acl_xattr_header
*local_acl
= (posix_acl_xattr_header
*)pACL
;
2995 if ((buflen
== 0) || (pACL
== NULL
) || (cifs_acl
== NULL
))
2998 count
= posix_acl_xattr_count((size_t)buflen
);
2999 cFYI(1, "setting acl with %d entries from buf of length %d and "
3001 count
, buflen
, le32_to_cpu(local_acl
->a_version
));
3002 if (le32_to_cpu(local_acl
->a_version
) != 2) {
3003 cFYI(1, "unknown POSIX ACL version %d",
3004 le32_to_cpu(local_acl
->a_version
));
3007 cifs_acl
->version
= cpu_to_le16(1);
3008 if (acl_type
== ACL_TYPE_ACCESS
)
3009 cifs_acl
->access_entry_count
= cpu_to_le16(count
);
3010 else if (acl_type
== ACL_TYPE_DEFAULT
)
3011 cifs_acl
->default_entry_count
= cpu_to_le16(count
);
3013 cFYI(1, "unknown ACL type %d", acl_type
);
3016 for (i
= 0; i
< count
; i
++) {
3017 rc
= convert_ace_to_cifs_ace(&cifs_acl
->ace_array
[i
],
3018 &local_acl
->a_entries
[i
]);
3020 /* ACE not converted */
3025 rc
= (__u16
)(count
* sizeof(struct cifs_posix_ace
));
3026 rc
+= sizeof(struct cifs_posix_acl
);
3027 /* BB add check to make sure ACL does not overflow SMB */
3033 CIFSSMBGetPosixACL(const int xid
, struct cifs_tcon
*tcon
,
3034 const unsigned char *searchName
,
3035 char *acl_inf
, const int buflen
, const int acl_type
,
3036 const struct nls_table
*nls_codepage
, int remap
)
3038 /* SMB_QUERY_POSIX_ACL */
3039 TRANSACTION2_QPI_REQ
*pSMB
= NULL
;
3040 TRANSACTION2_QPI_RSP
*pSMBr
= NULL
;
3044 __u16 params
, byte_count
;
3046 cFYI(1, "In GetPosixACL (Unix) for path %s", searchName
);
3049 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
3054 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
3056 cifsConvertToUCS((__le16
*) pSMB
->FileName
, searchName
,
3057 PATH_MAX
, nls_codepage
, remap
);
3058 name_len
++; /* trailing null */
3060 pSMB
->FileName
[name_len
] = 0;
3061 pSMB
->FileName
[name_len
+1] = 0;
3062 } else { /* BB improve the check for buffer overruns BB */
3063 name_len
= strnlen(searchName
, PATH_MAX
);
3064 name_len
++; /* trailing null */
3065 strncpy(pSMB
->FileName
, searchName
, name_len
);
3068 params
= 2 /* level */ + 4 /* rsrvd */ + name_len
/* incl null */ ;
3069 pSMB
->TotalDataCount
= 0;
3070 pSMB
->MaxParameterCount
= cpu_to_le16(2);
3071 /* BB find exact max data count below from sess structure BB */
3072 pSMB
->MaxDataCount
= cpu_to_le16(4000);
3073 pSMB
->MaxSetupCount
= 0;
3077 pSMB
->Reserved2
= 0;
3078 pSMB
->ParameterOffset
= cpu_to_le16(
3079 offsetof(struct smb_com_transaction2_qpi_req
,
3080 InformationLevel
) - 4);
3081 pSMB
->DataCount
= 0;
3082 pSMB
->DataOffset
= 0;
3083 pSMB
->SetupCount
= 1;
3084 pSMB
->Reserved3
= 0;
3085 pSMB
->SubCommand
= cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION
);
3086 byte_count
= params
+ 1 /* pad */ ;
3087 pSMB
->TotalParameterCount
= cpu_to_le16(params
);
3088 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
3089 pSMB
->InformationLevel
= cpu_to_le16(SMB_QUERY_POSIX_ACL
);
3090 pSMB
->Reserved4
= 0;
3091 inc_rfc1001_len(pSMB
, byte_count
);
3092 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
3094 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
3095 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
3096 cifs_stats_inc(&tcon
->num_acl_get
);
3098 cFYI(1, "Send error in Query POSIX ACL = %d", rc
);
3100 /* decode response */
3102 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
3103 /* BB also check enough total bytes returned */
3104 if (rc
|| get_bcc(&pSMBr
->hdr
) < 2)
3105 rc
= -EIO
; /* bad smb */
3107 __u16 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
3108 __u16 count
= le16_to_cpu(pSMBr
->t2
.DataCount
);
3109 rc
= cifs_copy_posix_acl(acl_inf
,
3110 (char *)&pSMBr
->hdr
.Protocol
+data_offset
,
3111 buflen
, acl_type
, count
);
3114 cifs_buf_release(pSMB
);
3121 CIFSSMBSetPosixACL(const int xid
, struct cifs_tcon
*tcon
,
3122 const unsigned char *fileName
,
3123 const char *local_acl
, const int buflen
,
3125 const struct nls_table
*nls_codepage
, int remap
)
3127 struct smb_com_transaction2_spi_req
*pSMB
= NULL
;
3128 struct smb_com_transaction2_spi_rsp
*pSMBr
= NULL
;
3132 int bytes_returned
= 0;
3133 __u16 params
, byte_count
, data_count
, param_offset
, offset
;
3135 cFYI(1, "In SetPosixACL (Unix) for path %s", fileName
);
3137 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
3141 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
3143 cifsConvertToUCS((__le16
*) pSMB
->FileName
, fileName
,
3144 PATH_MAX
, nls_codepage
, remap
);
3145 name_len
++; /* trailing null */
3147 } else { /* BB improve the check for buffer overruns BB */
3148 name_len
= strnlen(fileName
, PATH_MAX
);
3149 name_len
++; /* trailing null */
3150 strncpy(pSMB
->FileName
, fileName
, name_len
);
3152 params
= 6 + name_len
;
3153 pSMB
->MaxParameterCount
= cpu_to_le16(2);
3154 /* BB find max SMB size from sess */
3155 pSMB
->MaxDataCount
= cpu_to_le16(1000);
3156 pSMB
->MaxSetupCount
= 0;
3160 pSMB
->Reserved2
= 0;
3161 param_offset
= offsetof(struct smb_com_transaction2_spi_req
,
3162 InformationLevel
) - 4;
3163 offset
= param_offset
+ params
;
3164 parm_data
= ((char *) &pSMB
->hdr
.Protocol
) + offset
;
3165 pSMB
->ParameterOffset
= cpu_to_le16(param_offset
);
3167 /* convert to on the wire format for POSIX ACL */
3168 data_count
= ACL_to_cifs_posix(parm_data
, local_acl
, buflen
, acl_type
);
3170 if (data_count
== 0) {
3172 goto setACLerrorExit
;
3174 pSMB
->DataOffset
= cpu_to_le16(offset
);
3175 pSMB
->SetupCount
= 1;
3176 pSMB
->Reserved3
= 0;
3177 pSMB
->SubCommand
= cpu_to_le16(TRANS2_SET_PATH_INFORMATION
);
3178 pSMB
->InformationLevel
= cpu_to_le16(SMB_SET_POSIX_ACL
);
3179 byte_count
= 3 /* pad */ + params
+ data_count
;
3180 pSMB
->DataCount
= cpu_to_le16(data_count
);
3181 pSMB
->TotalDataCount
= pSMB
->DataCount
;
3182 pSMB
->ParameterCount
= cpu_to_le16(params
);
3183 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
3184 pSMB
->Reserved4
= 0;
3185 inc_rfc1001_len(pSMB
, byte_count
);
3186 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
3187 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
3188 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
3190 cFYI(1, "Set POSIX ACL returned %d", rc
);
3193 cifs_buf_release(pSMB
);
3199 /* BB fix tabs in this function FIXME BB */
3201 CIFSGetExtAttr(const int xid
, struct cifs_tcon
*tcon
,
3202 const int netfid
, __u64
*pExtAttrBits
, __u64
*pMask
)
3205 struct smb_t2_qfi_req
*pSMB
= NULL
;
3206 struct smb_t2_qfi_rsp
*pSMBr
= NULL
;
3208 __u16 params
, byte_count
;
3210 cFYI(1, "In GetExtAttr");
3215 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
3220 params
= 2 /* level */ + 2 /* fid */;
3221 pSMB
->t2
.TotalDataCount
= 0;
3222 pSMB
->t2
.MaxParameterCount
= cpu_to_le16(4);
3223 /* BB find exact max data count below from sess structure BB */
3224 pSMB
->t2
.MaxDataCount
= cpu_to_le16(4000);
3225 pSMB
->t2
.MaxSetupCount
= 0;
3226 pSMB
->t2
.Reserved
= 0;
3228 pSMB
->t2
.Timeout
= 0;
3229 pSMB
->t2
.Reserved2
= 0;
3230 pSMB
->t2
.ParameterOffset
= cpu_to_le16(offsetof(struct smb_t2_qfi_req
,
3232 pSMB
->t2
.DataCount
= 0;
3233 pSMB
->t2
.DataOffset
= 0;
3234 pSMB
->t2
.SetupCount
= 1;
3235 pSMB
->t2
.Reserved3
= 0;
3236 pSMB
->t2
.SubCommand
= cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION
);
3237 byte_count
= params
+ 1 /* pad */ ;
3238 pSMB
->t2
.TotalParameterCount
= cpu_to_le16(params
);
3239 pSMB
->t2
.ParameterCount
= pSMB
->t2
.TotalParameterCount
;
3240 pSMB
->InformationLevel
= cpu_to_le16(SMB_QUERY_ATTR_FLAGS
);
3243 inc_rfc1001_len(pSMB
, byte_count
);
3244 pSMB
->t2
.ByteCount
= cpu_to_le16(byte_count
);
3246 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
3247 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
3249 cFYI(1, "error %d in GetExtAttr", rc
);
3251 /* decode response */
3252 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
3253 /* BB also check enough total bytes returned */
3254 if (rc
|| get_bcc(&pSMBr
->hdr
) < 2)
3255 /* If rc should we check for EOPNOSUPP and
3256 disable the srvino flag? or in caller? */
3257 rc
= -EIO
; /* bad smb */
3259 __u16 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
3260 __u16 count
= le16_to_cpu(pSMBr
->t2
.DataCount
);
3261 struct file_chattr_info
*pfinfo
;
3262 /* BB Do we need a cast or hash here ? */
3264 cFYI(1, "Illegal size ret in GetExtAttr");
3268 pfinfo
= (struct file_chattr_info
*)
3269 (data_offset
+ (char *) &pSMBr
->hdr
.Protocol
);
3270 *pExtAttrBits
= le64_to_cpu(pfinfo
->mode
);
3271 *pMask
= le64_to_cpu(pfinfo
->mask
);
3275 cifs_buf_release(pSMB
);
3277 goto GetExtAttrRetry
;
3281 #endif /* CONFIG_POSIX */
3283 #ifdef CONFIG_CIFS_ACL
3285 * Initialize NT TRANSACT SMB into small smb request buffer. This assumes that
3286 * all NT TRANSACTS that we init here have total parm and data under about 400
3287 * bytes (to fit in small cifs buffer size), which is the case so far, it
3288 * easily fits. NB: Setup words themselves and ByteCount MaxSetupCount (size of
3289 * returned setup area) and MaxParameterCount (returned parms size) must be set
3293 smb_init_nttransact(const __u16 sub_command
, const int setup_count
,
3294 const int parm_len
, struct cifs_tcon
*tcon
,
3299 struct smb_com_ntransact_req
*pSMB
;
3301 rc
= small_smb_init(SMB_COM_NT_TRANSACT
, 19 + setup_count
, tcon
,
3305 *ret_buf
= (void *)pSMB
;
3307 pSMB
->TotalParameterCount
= cpu_to_le32(parm_len
);
3308 pSMB
->TotalDataCount
= 0;
3309 pSMB
->MaxDataCount
= cpu_to_le32((tcon
->ses
->server
->maxBuf
-
3310 MAX_CIFS_HDR_SIZE
) & 0xFFFFFF00);
3311 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
3312 pSMB
->DataCount
= pSMB
->TotalDataCount
;
3313 temp_offset
= offsetof(struct smb_com_ntransact_req
, Parms
) +
3314 (setup_count
* 2) - 4 /* for rfc1001 length itself */;
3315 pSMB
->ParameterOffset
= cpu_to_le32(temp_offset
);
3316 pSMB
->DataOffset
= cpu_to_le32(temp_offset
+ parm_len
);
3317 pSMB
->SetupCount
= setup_count
; /* no need to le convert byte fields */
3318 pSMB
->SubCommand
= cpu_to_le16(sub_command
);
3323 validate_ntransact(char *buf
, char **ppparm
, char **ppdata
,
3324 __u32
*pparmlen
, __u32
*pdatalen
)
3327 __u32 data_count
, data_offset
, parm_count
, parm_offset
;
3328 struct smb_com_ntransact_rsp
*pSMBr
;
3337 pSMBr
= (struct smb_com_ntransact_rsp
*)buf
;
3339 bcc
= get_bcc(&pSMBr
->hdr
);
3340 end_of_smb
= 2 /* sizeof byte count */ + bcc
+
3341 (char *)&pSMBr
->ByteCount
;
3343 data_offset
= le32_to_cpu(pSMBr
->DataOffset
);
3344 data_count
= le32_to_cpu(pSMBr
->DataCount
);
3345 parm_offset
= le32_to_cpu(pSMBr
->ParameterOffset
);
3346 parm_count
= le32_to_cpu(pSMBr
->ParameterCount
);
3348 *ppparm
= (char *)&pSMBr
->hdr
.Protocol
+ parm_offset
;
3349 *ppdata
= (char *)&pSMBr
->hdr
.Protocol
+ data_offset
;
3351 /* should we also check that parm and data areas do not overlap? */
3352 if (*ppparm
> end_of_smb
) {
3353 cFYI(1, "parms start after end of smb");
3355 } else if (parm_count
+ *ppparm
> end_of_smb
) {
3356 cFYI(1, "parm end after end of smb");
3358 } else if (*ppdata
> end_of_smb
) {
3359 cFYI(1, "data starts after end of smb");
3361 } else if (data_count
+ *ppdata
> end_of_smb
) {
3362 cFYI(1, "data %p + count %d (%p) past smb end %p start %p",
3363 *ppdata
, data_count
, (data_count
+ *ppdata
),
3366 } else if (parm_count
+ data_count
> bcc
) {
3367 cFYI(1, "parm count and data count larger than SMB");
3370 *pdatalen
= data_count
;
3371 *pparmlen
= parm_count
;
3375 /* Get Security Descriptor (by handle) from remote server for a file or dir */
3377 CIFSSMBGetCIFSACL(const int xid
, struct cifs_tcon
*tcon
, __u16 fid
,
3378 struct cifs_ntsd
**acl_inf
, __u32
*pbuflen
)
3382 QUERY_SEC_DESC_REQ
*pSMB
;
3385 cFYI(1, "GetCifsACL");
3390 rc
= smb_init_nttransact(NT_TRANSACT_QUERY_SECURITY_DESC
, 0,
3391 8 /* parm len */, tcon
, (void **) &pSMB
);
3395 pSMB
->MaxParameterCount
= cpu_to_le32(4);
3396 /* BB TEST with big acls that might need to be e.g. larger than 16K */
3397 pSMB
->MaxSetupCount
= 0;
3398 pSMB
->Fid
= fid
; /* file handle always le */
3399 pSMB
->AclFlags
= cpu_to_le32(CIFS_ACL_OWNER
| CIFS_ACL_GROUP
|
3401 pSMB
->ByteCount
= cpu_to_le16(11); /* 3 bytes pad + 8 bytes parm */
3402 inc_rfc1001_len(pSMB
, 11);
3403 iov
[0].iov_base
= (char *)pSMB
;
3404 iov
[0].iov_len
= be32_to_cpu(pSMB
->hdr
.smb_buf_length
) + 4;
3406 rc
= SendReceive2(xid
, tcon
->ses
, iov
, 1 /* num iovec */, &buf_type
,
3408 cifs_stats_inc(&tcon
->num_acl_get
);
3410 cFYI(1, "Send error in QuerySecDesc = %d", rc
);
3411 } else { /* decode response */
3415 struct smb_com_ntransact_rsp
*pSMBr
;
3418 /* validate_nttransact */
3419 rc
= validate_ntransact(iov
[0].iov_base
, (char **)&parm
,
3420 &pdata
, &parm_len
, pbuflen
);
3423 pSMBr
= (struct smb_com_ntransact_rsp
*)iov
[0].iov_base
;
3425 cFYI(1, "smb %p parm %p data %p", pSMBr
, parm
, *acl_inf
);
3427 if (le32_to_cpu(pSMBr
->ParameterCount
) != 4) {
3428 rc
= -EIO
; /* bad smb */
3433 /* BB check that data area is minimum length and as big as acl_len */
3435 acl_len
= le32_to_cpu(*parm
);
3436 if (acl_len
!= *pbuflen
) {
3437 cERROR(1, "acl length %d does not match %d",
3439 if (*pbuflen
> acl_len
)
3443 /* check if buffer is big enough for the acl
3444 header followed by the smallest SID */
3445 if ((*pbuflen
< sizeof(struct cifs_ntsd
) + 8) ||
3446 (*pbuflen
>= 64 * 1024)) {
3447 cERROR(1, "bad acl length %d", *pbuflen
);
3451 *acl_inf
= kmalloc(*pbuflen
, GFP_KERNEL
);
3452 if (*acl_inf
== NULL
) {
3456 memcpy(*acl_inf
, pdata
, *pbuflen
);
3460 if (buf_type
== CIFS_SMALL_BUFFER
)
3461 cifs_small_buf_release(iov
[0].iov_base
);
3462 else if (buf_type
== CIFS_LARGE_BUFFER
)
3463 cifs_buf_release(iov
[0].iov_base
);
3464 /* cifs_small_buf_release(pSMB); */ /* Freed earlier now in SendReceive2 */
3469 CIFSSMBSetCIFSACL(const int xid
, struct cifs_tcon
*tcon
, __u16 fid
,
3470 struct cifs_ntsd
*pntsd
, __u32 acllen
)
3472 __u16 byte_count
, param_count
, data_count
, param_offset
, data_offset
;
3474 int bytes_returned
= 0;
3475 SET_SEC_DESC_REQ
*pSMB
= NULL
;
3476 NTRANSACT_RSP
*pSMBr
= NULL
;
3479 rc
= smb_init(SMB_COM_NT_TRANSACT
, 19, tcon
, (void **) &pSMB
,
3484 pSMB
->MaxSetupCount
= 0;
3488 param_offset
= offsetof(struct smb_com_transaction_ssec_req
, Fid
) - 4;
3489 data_count
= acllen
;
3490 data_offset
= param_offset
+ param_count
;
3491 byte_count
= 3 /* pad */ + param_count
;
3493 pSMB
->DataCount
= cpu_to_le32(data_count
);
3494 pSMB
->TotalDataCount
= pSMB
->DataCount
;
3495 pSMB
->MaxParameterCount
= cpu_to_le32(4);
3496 pSMB
->MaxDataCount
= cpu_to_le32(16384);
3497 pSMB
->ParameterCount
= cpu_to_le32(param_count
);
3498 pSMB
->ParameterOffset
= cpu_to_le32(param_offset
);
3499 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
3500 pSMB
->DataOffset
= cpu_to_le32(data_offset
);
3501 pSMB
->SetupCount
= 0;
3502 pSMB
->SubCommand
= cpu_to_le16(NT_TRANSACT_SET_SECURITY_DESC
);
3503 pSMB
->ByteCount
= cpu_to_le16(byte_count
+data_count
);
3505 pSMB
->Fid
= fid
; /* file handle always le */
3506 pSMB
->Reserved2
= 0;
3507 pSMB
->AclFlags
= cpu_to_le32(CIFS_ACL_DACL
);
3509 if (pntsd
&& acllen
) {
3510 memcpy((char *) &pSMBr
->hdr
.Protocol
+ data_offset
,
3513 inc_rfc1001_len(pSMB
, byte_count
+ data_count
);
3515 inc_rfc1001_len(pSMB
, byte_count
);
3517 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
3518 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
3520 cFYI(1, "SetCIFSACL bytes_returned: %d, rc: %d", bytes_returned
, rc
);
3522 cFYI(1, "Set CIFS ACL returned %d", rc
);
3523 cifs_buf_release(pSMB
);
3526 goto setCifsAclRetry
;
3531 #endif /* CONFIG_CIFS_ACL */
3533 /* Legacy Query Path Information call for lookup to old servers such
3535 int SMBQueryInformation(const int xid
, struct cifs_tcon
*tcon
,
3536 const unsigned char *searchName
,
3537 FILE_ALL_INFO
*pFinfo
,
3538 const struct nls_table
*nls_codepage
, int remap
)
3540 QUERY_INFORMATION_REQ
*pSMB
;
3541 QUERY_INFORMATION_RSP
*pSMBr
;
3546 cFYI(1, "In SMBQPath path %s", searchName
);
3548 rc
= smb_init(SMB_COM_QUERY_INFORMATION
, 0, tcon
, (void **) &pSMB
,
3553 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
3555 cifsConvertToUCS((__le16
*) pSMB
->FileName
, searchName
,
3556 PATH_MAX
, nls_codepage
, remap
);
3557 name_len
++; /* trailing null */
3560 name_len
= strnlen(searchName
, PATH_MAX
);
3561 name_len
++; /* trailing null */
3562 strncpy(pSMB
->FileName
, searchName
, name_len
);
3564 pSMB
->BufferFormat
= 0x04;
3565 name_len
++; /* account for buffer type byte */
3566 inc_rfc1001_len(pSMB
, (__u16
)name_len
);
3567 pSMB
->ByteCount
= cpu_to_le16(name_len
);
3569 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
3570 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
3572 cFYI(1, "Send error in QueryInfo = %d", rc
);
3573 } else if (pFinfo
) {
3575 __u32 time
= le32_to_cpu(pSMBr
->last_write_time
);
3577 /* decode response */
3578 /* BB FIXME - add time zone adjustment BB */
3579 memset(pFinfo
, 0, sizeof(FILE_ALL_INFO
));
3582 /* decode time fields */
3583 pFinfo
->ChangeTime
= cpu_to_le64(cifs_UnixTimeToNT(ts
));
3584 pFinfo
->LastWriteTime
= pFinfo
->ChangeTime
;
3585 pFinfo
->LastAccessTime
= 0;
3586 pFinfo
->AllocationSize
=
3587 cpu_to_le64(le32_to_cpu(pSMBr
->size
));
3588 pFinfo
->EndOfFile
= pFinfo
->AllocationSize
;
3589 pFinfo
->Attributes
=
3590 cpu_to_le32(le16_to_cpu(pSMBr
->attr
));
3592 rc
= -EIO
; /* bad buffer passed in */
3594 cifs_buf_release(pSMB
);
3603 CIFSSMBQFileInfo(const int xid
, struct cifs_tcon
*tcon
,
3604 u16 netfid
, FILE_ALL_INFO
*pFindData
)
3606 struct smb_t2_qfi_req
*pSMB
= NULL
;
3607 struct smb_t2_qfi_rsp
*pSMBr
= NULL
;
3610 __u16 params
, byte_count
;
3613 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
3618 params
= 2 /* level */ + 2 /* fid */;
3619 pSMB
->t2
.TotalDataCount
= 0;
3620 pSMB
->t2
.MaxParameterCount
= cpu_to_le16(4);
3621 /* BB find exact max data count below from sess structure BB */
3622 pSMB
->t2
.MaxDataCount
= cpu_to_le16(CIFSMaxBufSize
);
3623 pSMB
->t2
.MaxSetupCount
= 0;
3624 pSMB
->t2
.Reserved
= 0;
3626 pSMB
->t2
.Timeout
= 0;
3627 pSMB
->t2
.Reserved2
= 0;
3628 pSMB
->t2
.ParameterOffset
= cpu_to_le16(offsetof(struct smb_t2_qfi_req
,
3630 pSMB
->t2
.DataCount
= 0;
3631 pSMB
->t2
.DataOffset
= 0;
3632 pSMB
->t2
.SetupCount
= 1;
3633 pSMB
->t2
.Reserved3
= 0;
3634 pSMB
->t2
.SubCommand
= cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION
);
3635 byte_count
= params
+ 1 /* pad */ ;
3636 pSMB
->t2
.TotalParameterCount
= cpu_to_le16(params
);
3637 pSMB
->t2
.ParameterCount
= pSMB
->t2
.TotalParameterCount
;
3638 pSMB
->InformationLevel
= cpu_to_le16(SMB_QUERY_FILE_ALL_INFO
);
3641 inc_rfc1001_len(pSMB
, byte_count
);
3643 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
3644 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
3646 cFYI(1, "Send error in QPathInfo = %d", rc
);
3647 } else { /* decode response */
3648 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
3650 if (rc
) /* BB add auto retry on EOPNOTSUPP? */
3652 else if (get_bcc(&pSMBr
->hdr
) < 40)
3653 rc
= -EIO
; /* bad smb */
3654 else if (pFindData
) {
3655 __u16 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
3656 memcpy((char *) pFindData
,
3657 (char *) &pSMBr
->hdr
.Protocol
+
3658 data_offset
, sizeof(FILE_ALL_INFO
));
3662 cifs_buf_release(pSMB
);
3664 goto QFileInfoRetry
;
3670 CIFSSMBQPathInfo(const int xid
, struct cifs_tcon
*tcon
,
3671 const unsigned char *searchName
,
3672 FILE_ALL_INFO
*pFindData
,
3673 int legacy
/* old style infolevel */,
3674 const struct nls_table
*nls_codepage
, int remap
)
3676 /* level 263 SMB_QUERY_FILE_ALL_INFO */
3677 TRANSACTION2_QPI_REQ
*pSMB
= NULL
;
3678 TRANSACTION2_QPI_RSP
*pSMBr
= NULL
;
3682 __u16 params
, byte_count
;
3684 /* cFYI(1, "In QPathInfo path %s", searchName); */
3686 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
3691 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
3693 cifsConvertToUCS((__le16
*) pSMB
->FileName
, searchName
,
3694 PATH_MAX
, nls_codepage
, remap
);
3695 name_len
++; /* trailing null */
3697 } else { /* BB improve the check for buffer overruns BB */
3698 name_len
= strnlen(searchName
, PATH_MAX
);
3699 name_len
++; /* trailing null */
3700 strncpy(pSMB
->FileName
, searchName
, name_len
);
3703 params
= 2 /* level */ + 4 /* reserved */ + name_len
/* includes NUL */;
3704 pSMB
->TotalDataCount
= 0;
3705 pSMB
->MaxParameterCount
= cpu_to_le16(2);
3706 /* BB find exact max SMB PDU from sess structure BB */
3707 pSMB
->MaxDataCount
= cpu_to_le16(4000);
3708 pSMB
->MaxSetupCount
= 0;
3712 pSMB
->Reserved2
= 0;
3713 pSMB
->ParameterOffset
= cpu_to_le16(offsetof(
3714 struct smb_com_transaction2_qpi_req
, InformationLevel
) - 4);
3715 pSMB
->DataCount
= 0;
3716 pSMB
->DataOffset
= 0;
3717 pSMB
->SetupCount
= 1;
3718 pSMB
->Reserved3
= 0;
3719 pSMB
->SubCommand
= cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION
);
3720 byte_count
= params
+ 1 /* pad */ ;
3721 pSMB
->TotalParameterCount
= cpu_to_le16(params
);
3722 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
3724 pSMB
->InformationLevel
= cpu_to_le16(SMB_INFO_STANDARD
);
3726 pSMB
->InformationLevel
= cpu_to_le16(SMB_QUERY_FILE_ALL_INFO
);
3727 pSMB
->Reserved4
= 0;
3728 inc_rfc1001_len(pSMB
, byte_count
);
3729 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
3731 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
3732 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
3734 cFYI(1, "Send error in QPathInfo = %d", rc
);
3735 } else { /* decode response */
3736 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
3738 if (rc
) /* BB add auto retry on EOPNOTSUPP? */
3740 else if (!legacy
&& get_bcc(&pSMBr
->hdr
) < 40)
3741 rc
= -EIO
; /* bad smb */
3742 else if (legacy
&& get_bcc(&pSMBr
->hdr
) < 24)
3743 rc
= -EIO
; /* 24 or 26 expected but we do not read
3745 else if (pFindData
) {
3747 __u16 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
3749 /* On legacy responses we do not read the last field,
3750 EAsize, fortunately since it varies by subdialect and
3751 also note it differs on Set vs. Get, ie two bytes or 4
3752 bytes depending but we don't care here */
3754 size
= sizeof(FILE_INFO_STANDARD
);
3756 size
= sizeof(FILE_ALL_INFO
);
3757 memcpy((char *) pFindData
,
3758 (char *) &pSMBr
->hdr
.Protocol
+
3763 cifs_buf_release(pSMB
);
3765 goto QPathInfoRetry
;
3771 CIFSSMBUnixQFileInfo(const int xid
, struct cifs_tcon
*tcon
,
3772 u16 netfid
, FILE_UNIX_BASIC_INFO
*pFindData
)
3774 struct smb_t2_qfi_req
*pSMB
= NULL
;
3775 struct smb_t2_qfi_rsp
*pSMBr
= NULL
;
3778 __u16 params
, byte_count
;
3781 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
3786 params
= 2 /* level */ + 2 /* fid */;
3787 pSMB
->t2
.TotalDataCount
= 0;
3788 pSMB
->t2
.MaxParameterCount
= cpu_to_le16(4);
3789 /* BB find exact max data count below from sess structure BB */
3790 pSMB
->t2
.MaxDataCount
= cpu_to_le16(CIFSMaxBufSize
);
3791 pSMB
->t2
.MaxSetupCount
= 0;
3792 pSMB
->t2
.Reserved
= 0;
3794 pSMB
->t2
.Timeout
= 0;
3795 pSMB
->t2
.Reserved2
= 0;
3796 pSMB
->t2
.ParameterOffset
= cpu_to_le16(offsetof(struct smb_t2_qfi_req
,
3798 pSMB
->t2
.DataCount
= 0;
3799 pSMB
->t2
.DataOffset
= 0;
3800 pSMB
->t2
.SetupCount
= 1;
3801 pSMB
->t2
.Reserved3
= 0;
3802 pSMB
->t2
.SubCommand
= cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION
);
3803 byte_count
= params
+ 1 /* pad */ ;
3804 pSMB
->t2
.TotalParameterCount
= cpu_to_le16(params
);
3805 pSMB
->t2
.ParameterCount
= pSMB
->t2
.TotalParameterCount
;
3806 pSMB
->InformationLevel
= cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC
);
3809 inc_rfc1001_len(pSMB
, byte_count
);
3811 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
3812 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
3814 cFYI(1, "Send error in QPathInfo = %d", rc
);
3815 } else { /* decode response */
3816 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
3818 if (rc
|| get_bcc(&pSMBr
->hdr
) < sizeof(FILE_UNIX_BASIC_INFO
)) {
3819 cERROR(1, "Malformed FILE_UNIX_BASIC_INFO response.\n"
3820 "Unix Extensions can be disabled on mount "
3821 "by specifying the nosfu mount option.");
3822 rc
= -EIO
; /* bad smb */
3824 __u16 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
3825 memcpy((char *) pFindData
,
3826 (char *) &pSMBr
->hdr
.Protocol
+
3828 sizeof(FILE_UNIX_BASIC_INFO
));
3832 cifs_buf_release(pSMB
);
3834 goto UnixQFileInfoRetry
;
3840 CIFSSMBUnixQPathInfo(const int xid
, struct cifs_tcon
*tcon
,
3841 const unsigned char *searchName
,
3842 FILE_UNIX_BASIC_INFO
*pFindData
,
3843 const struct nls_table
*nls_codepage
, int remap
)
3845 /* SMB_QUERY_FILE_UNIX_BASIC */
3846 TRANSACTION2_QPI_REQ
*pSMB
= NULL
;
3847 TRANSACTION2_QPI_RSP
*pSMBr
= NULL
;
3849 int bytes_returned
= 0;
3851 __u16 params
, byte_count
;
3853 cFYI(1, "In QPathInfo (Unix) the path %s", searchName
);
3855 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
3860 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
3862 cifsConvertToUCS((__le16
*) pSMB
->FileName
, searchName
,
3863 PATH_MAX
, nls_codepage
, remap
);
3864 name_len
++; /* trailing null */
3866 } else { /* BB improve the check for buffer overruns BB */
3867 name_len
= strnlen(searchName
, PATH_MAX
);
3868 name_len
++; /* trailing null */
3869 strncpy(pSMB
->FileName
, searchName
, name_len
);
3872 params
= 2 /* level */ + 4 /* reserved */ + name_len
/* includes NUL */;
3873 pSMB
->TotalDataCount
= 0;
3874 pSMB
->MaxParameterCount
= cpu_to_le16(2);
3875 /* BB find exact max SMB PDU from sess structure BB */
3876 pSMB
->MaxDataCount
= cpu_to_le16(4000);
3877 pSMB
->MaxSetupCount
= 0;
3881 pSMB
->Reserved2
= 0;
3882 pSMB
->ParameterOffset
= cpu_to_le16(offsetof(
3883 struct smb_com_transaction2_qpi_req
, InformationLevel
) - 4);
3884 pSMB
->DataCount
= 0;
3885 pSMB
->DataOffset
= 0;
3886 pSMB
->SetupCount
= 1;
3887 pSMB
->Reserved3
= 0;
3888 pSMB
->SubCommand
= cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION
);
3889 byte_count
= params
+ 1 /* pad */ ;
3890 pSMB
->TotalParameterCount
= cpu_to_le16(params
);
3891 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
3892 pSMB
->InformationLevel
= cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC
);
3893 pSMB
->Reserved4
= 0;
3894 inc_rfc1001_len(pSMB
, byte_count
);
3895 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
3897 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
3898 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
3900 cFYI(1, "Send error in QPathInfo = %d", rc
);
3901 } else { /* decode response */
3902 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
3904 if (rc
|| get_bcc(&pSMBr
->hdr
) < sizeof(FILE_UNIX_BASIC_INFO
)) {
3905 cERROR(1, "Malformed FILE_UNIX_BASIC_INFO response.\n"
3906 "Unix Extensions can be disabled on mount "
3907 "by specifying the nosfu mount option.");
3908 rc
= -EIO
; /* bad smb */
3910 __u16 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
3911 memcpy((char *) pFindData
,
3912 (char *) &pSMBr
->hdr
.Protocol
+
3914 sizeof(FILE_UNIX_BASIC_INFO
));
3917 cifs_buf_release(pSMB
);
3919 goto UnixQPathInfoRetry
;
3924 /* xid, tcon, searchName and codepage are input parms, rest are returned */
3926 CIFSFindFirst(const int xid
, struct cifs_tcon
*tcon
,
3927 const char *searchName
,
3928 const struct nls_table
*nls_codepage
,
3930 struct cifs_search_info
*psrch_inf
, int remap
, const char dirsep
)
3932 /* level 257 SMB_ */
3933 TRANSACTION2_FFIRST_REQ
*pSMB
= NULL
;
3934 TRANSACTION2_FFIRST_RSP
*pSMBr
= NULL
;
3935 T2_FFIRST_RSP_PARMS
*parms
;
3937 int bytes_returned
= 0;
3939 __u16 params
, byte_count
;
3941 cFYI(1, "In FindFirst for %s", searchName
);
3944 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
3949 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
3951 cifsConvertToUCS((__le16
*) pSMB
->FileName
, searchName
,
3952 PATH_MAX
, nls_codepage
, remap
);
3953 /* We can not add the asterik earlier in case
3954 it got remapped to 0xF03A as if it were part of the
3955 directory name instead of a wildcard */
3957 pSMB
->FileName
[name_len
] = dirsep
;
3958 pSMB
->FileName
[name_len
+1] = 0;
3959 pSMB
->FileName
[name_len
+2] = '*';
3960 pSMB
->FileName
[name_len
+3] = 0;
3961 name_len
+= 4; /* now the trailing null */
3962 pSMB
->FileName
[name_len
] = 0; /* null terminate just in case */
3963 pSMB
->FileName
[name_len
+1] = 0;
3965 } else { /* BB add check for overrun of SMB buf BB */
3966 name_len
= strnlen(searchName
, PATH_MAX
);
3967 /* BB fix here and in unicode clause above ie
3968 if (name_len > buffersize-header)
3969 free buffer exit; BB */
3970 strncpy(pSMB
->FileName
, searchName
, name_len
);
3971 pSMB
->FileName
[name_len
] = dirsep
;
3972 pSMB
->FileName
[name_len
+1] = '*';
3973 pSMB
->FileName
[name_len
+2] = 0;
3977 params
= 12 + name_len
/* includes null */ ;
3978 pSMB
->TotalDataCount
= 0; /* no EAs */
3979 pSMB
->MaxParameterCount
= cpu_to_le16(10);
3980 pSMB
->MaxDataCount
= cpu_to_le16((tcon
->ses
->server
->maxBuf
-
3981 MAX_CIFS_HDR_SIZE
) & 0xFFFFFF00);
3982 pSMB
->MaxSetupCount
= 0;
3986 pSMB
->Reserved2
= 0;
3987 byte_count
= params
+ 1 /* pad */ ;
3988 pSMB
->TotalParameterCount
= cpu_to_le16(params
);
3989 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
3990 pSMB
->ParameterOffset
= cpu_to_le16(
3991 offsetof(struct smb_com_transaction2_ffirst_req
, SearchAttributes
)
3993 pSMB
->DataCount
= 0;
3994 pSMB
->DataOffset
= 0;
3995 pSMB
->SetupCount
= 1; /* one byte, no need to make endian neutral */
3996 pSMB
->Reserved3
= 0;
3997 pSMB
->SubCommand
= cpu_to_le16(TRANS2_FIND_FIRST
);
3998 pSMB
->SearchAttributes
=
3999 cpu_to_le16(ATTR_READONLY
| ATTR_HIDDEN
| ATTR_SYSTEM
|
4001 pSMB
->SearchCount
= cpu_to_le16(CIFSMaxBufSize
/sizeof(FILE_UNIX_INFO
));
4002 pSMB
->SearchFlags
= cpu_to_le16(CIFS_SEARCH_CLOSE_AT_END
|
4003 CIFS_SEARCH_RETURN_RESUME
);
4004 pSMB
->InformationLevel
= cpu_to_le16(psrch_inf
->info_level
);
4006 /* BB what should we set StorageType to? Does it matter? BB */
4007 pSMB
->SearchStorageType
= 0;
4008 inc_rfc1001_len(pSMB
, byte_count
);
4009 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
4011 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
4012 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
4013 cifs_stats_inc(&tcon
->num_ffirst
);
4015 if (rc
) {/* BB add logic to retry regular search if Unix search
4016 rejected unexpectedly by server */
4017 /* BB Add code to handle unsupported level rc */
4018 cFYI(1, "Error in FindFirst = %d", rc
);
4020 cifs_buf_release(pSMB
);
4022 /* BB eventually could optimize out free and realloc of buf */
4025 goto findFirstRetry
;
4026 } else { /* decode response */
4027 /* BB remember to free buffer if error BB */
4028 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
4032 if (pSMBr
->hdr
.Flags2
& SMBFLG2_UNICODE
)
4033 psrch_inf
->unicode
= true;
4035 psrch_inf
->unicode
= false;
4037 psrch_inf
->ntwrk_buf_start
= (char *)pSMBr
;
4038 psrch_inf
->smallBuf
= 0;
4039 psrch_inf
->srch_entries_start
=
4040 (char *) &pSMBr
->hdr
.Protocol
+
4041 le16_to_cpu(pSMBr
->t2
.DataOffset
);
4042 parms
= (T2_FFIRST_RSP_PARMS
*)((char *) &pSMBr
->hdr
.Protocol
+
4043 le16_to_cpu(pSMBr
->t2
.ParameterOffset
));
4045 if (parms
->EndofSearch
)
4046 psrch_inf
->endOfSearch
= true;
4048 psrch_inf
->endOfSearch
= false;
4050 psrch_inf
->entries_in_buffer
=
4051 le16_to_cpu(parms
->SearchCount
);
4052 psrch_inf
->index_of_last_entry
= 2 /* skip . and .. */ +
4053 psrch_inf
->entries_in_buffer
;
4054 lnoff
= le16_to_cpu(parms
->LastNameOffset
);
4055 if (tcon
->ses
->server
->maxBuf
- MAX_CIFS_HDR_SIZE
<
4057 cERROR(1, "ignoring corrupt resume name");
4058 psrch_inf
->last_entry
= NULL
;
4062 psrch_inf
->last_entry
= psrch_inf
->srch_entries_start
+
4065 *pnetfid
= parms
->SearchHandle
;
4067 cifs_buf_release(pSMB
);
4074 int CIFSFindNext(const int xid
, struct cifs_tcon
*tcon
,
4075 __u16 searchHandle
, struct cifs_search_info
*psrch_inf
)
4077 TRANSACTION2_FNEXT_REQ
*pSMB
= NULL
;
4078 TRANSACTION2_FNEXT_RSP
*pSMBr
= NULL
;
4079 T2_FNEXT_RSP_PARMS
*parms
;
4080 char *response_data
;
4082 int bytes_returned
, name_len
;
4083 __u16 params
, byte_count
;
4085 cFYI(1, "In FindNext");
4087 if (psrch_inf
->endOfSearch
)
4090 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
4095 params
= 14; /* includes 2 bytes of null string, converted to LE below*/
4097 pSMB
->TotalDataCount
= 0; /* no EAs */
4098 pSMB
->MaxParameterCount
= cpu_to_le16(8);
4099 pSMB
->MaxDataCount
=
4100 cpu_to_le16((tcon
->ses
->server
->maxBuf
- MAX_CIFS_HDR_SIZE
) &
4102 pSMB
->MaxSetupCount
= 0;
4106 pSMB
->Reserved2
= 0;
4107 pSMB
->ParameterOffset
= cpu_to_le16(
4108 offsetof(struct smb_com_transaction2_fnext_req
,SearchHandle
) - 4);
4109 pSMB
->DataCount
= 0;
4110 pSMB
->DataOffset
= 0;
4111 pSMB
->SetupCount
= 1;
4112 pSMB
->Reserved3
= 0;
4113 pSMB
->SubCommand
= cpu_to_le16(TRANS2_FIND_NEXT
);
4114 pSMB
->SearchHandle
= searchHandle
; /* always kept as le */
4116 cpu_to_le16(CIFSMaxBufSize
/ sizeof(FILE_UNIX_INFO
));
4117 pSMB
->InformationLevel
= cpu_to_le16(psrch_inf
->info_level
);
4118 pSMB
->ResumeKey
= psrch_inf
->resume_key
;
4120 cpu_to_le16(CIFS_SEARCH_CLOSE_AT_END
| CIFS_SEARCH_RETURN_RESUME
);
4122 name_len
= psrch_inf
->resume_name_len
;
4124 if (name_len
< PATH_MAX
) {
4125 memcpy(pSMB
->ResumeFileName
, psrch_inf
->presume_name
, name_len
);
4126 byte_count
+= name_len
;
4127 /* 14 byte parm len above enough for 2 byte null terminator */
4128 pSMB
->ResumeFileName
[name_len
] = 0;
4129 pSMB
->ResumeFileName
[name_len
+1] = 0;
4132 goto FNext2_err_exit
;
4134 byte_count
= params
+ 1 /* pad */ ;
4135 pSMB
->TotalParameterCount
= cpu_to_le16(params
);
4136 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
4137 inc_rfc1001_len(pSMB
, byte_count
);
4138 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
4140 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
4141 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
4142 cifs_stats_inc(&tcon
->num_fnext
);
4145 psrch_inf
->endOfSearch
= true;
4146 cifs_buf_release(pSMB
);
4147 rc
= 0; /* search probably was closed at end of search*/
4149 cFYI(1, "FindNext returned = %d", rc
);
4150 } else { /* decode response */
4151 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
4156 /* BB fixme add lock for file (srch_info) struct here */
4157 if (pSMBr
->hdr
.Flags2
& SMBFLG2_UNICODE
)
4158 psrch_inf
->unicode
= true;
4160 psrch_inf
->unicode
= false;
4161 response_data
= (char *) &pSMBr
->hdr
.Protocol
+
4162 le16_to_cpu(pSMBr
->t2
.ParameterOffset
);
4163 parms
= (T2_FNEXT_RSP_PARMS
*)response_data
;
4164 response_data
= (char *)&pSMBr
->hdr
.Protocol
+
4165 le16_to_cpu(pSMBr
->t2
.DataOffset
);
4166 if (psrch_inf
->smallBuf
)
4167 cifs_small_buf_release(
4168 psrch_inf
->ntwrk_buf_start
);
4170 cifs_buf_release(psrch_inf
->ntwrk_buf_start
);
4171 psrch_inf
->srch_entries_start
= response_data
;
4172 psrch_inf
->ntwrk_buf_start
= (char *)pSMB
;
4173 psrch_inf
->smallBuf
= 0;
4174 if (parms
->EndofSearch
)
4175 psrch_inf
->endOfSearch
= true;
4177 psrch_inf
->endOfSearch
= false;
4178 psrch_inf
->entries_in_buffer
=
4179 le16_to_cpu(parms
->SearchCount
);
4180 psrch_inf
->index_of_last_entry
+=
4181 psrch_inf
->entries_in_buffer
;
4182 lnoff
= le16_to_cpu(parms
->LastNameOffset
);
4183 if (tcon
->ses
->server
->maxBuf
- MAX_CIFS_HDR_SIZE
<
4185 cERROR(1, "ignoring corrupt resume name");
4186 psrch_inf
->last_entry
= NULL
;
4189 psrch_inf
->last_entry
=
4190 psrch_inf
->srch_entries_start
+ lnoff
;
4192 /* cFYI(1, "fnxt2 entries in buf %d index_of_last %d",
4193 psrch_inf->entries_in_buffer, psrch_inf->index_of_last_entry); */
4195 /* BB fixme add unlock here */
4200 /* BB On error, should we leave previous search buf (and count and
4201 last entry fields) intact or free the previous one? */
4203 /* Note: On -EAGAIN error only caller can retry on handle based calls
4204 since file handle passed in no longer valid */
4207 cifs_buf_release(pSMB
);
4212 CIFSFindClose(const int xid
, struct cifs_tcon
*tcon
,
4213 const __u16 searchHandle
)
4216 FINDCLOSE_REQ
*pSMB
= NULL
;
4218 cFYI(1, "In CIFSSMBFindClose");
4219 rc
= small_smb_init(SMB_COM_FIND_CLOSE2
, 1, tcon
, (void **)&pSMB
);
4221 /* no sense returning error if session restarted
4222 as file handle has been closed */
4228 pSMB
->FileID
= searchHandle
;
4229 pSMB
->ByteCount
= 0;
4230 rc
= SendReceiveNoRsp(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
, 0);
4232 cERROR(1, "Send error in FindClose = %d", rc
);
4234 cifs_stats_inc(&tcon
->num_fclose
);
4236 /* Since session is dead, search handle closed on server already */
4244 CIFSGetSrvInodeNumber(const int xid
, struct cifs_tcon
*tcon
,
4245 const unsigned char *searchName
,
4246 __u64
*inode_number
,
4247 const struct nls_table
*nls_codepage
, int remap
)
4250 TRANSACTION2_QPI_REQ
*pSMB
= NULL
;
4251 TRANSACTION2_QPI_RSP
*pSMBr
= NULL
;
4252 int name_len
, bytes_returned
;
4253 __u16 params
, byte_count
;
4255 cFYI(1, "In GetSrvInodeNum for %s", searchName
);
4259 GetInodeNumberRetry
:
4260 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
4265 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
4267 cifsConvertToUCS((__le16
*) pSMB
->FileName
, searchName
,
4268 PATH_MAX
, nls_codepage
, remap
);
4269 name_len
++; /* trailing null */
4271 } else { /* BB improve the check for buffer overruns BB */
4272 name_len
= strnlen(searchName
, PATH_MAX
);
4273 name_len
++; /* trailing null */
4274 strncpy(pSMB
->FileName
, searchName
, name_len
);
4277 params
= 2 /* level */ + 4 /* rsrvd */ + name_len
/* incl null */ ;
4278 pSMB
->TotalDataCount
= 0;
4279 pSMB
->MaxParameterCount
= cpu_to_le16(2);
4280 /* BB find exact max data count below from sess structure BB */
4281 pSMB
->MaxDataCount
= cpu_to_le16(4000);
4282 pSMB
->MaxSetupCount
= 0;
4286 pSMB
->Reserved2
= 0;
4287 pSMB
->ParameterOffset
= cpu_to_le16(offsetof(
4288 struct smb_com_transaction2_qpi_req
, InformationLevel
) - 4);
4289 pSMB
->DataCount
= 0;
4290 pSMB
->DataOffset
= 0;
4291 pSMB
->SetupCount
= 1;
4292 pSMB
->Reserved3
= 0;
4293 pSMB
->SubCommand
= cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION
);
4294 byte_count
= params
+ 1 /* pad */ ;
4295 pSMB
->TotalParameterCount
= cpu_to_le16(params
);
4296 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
4297 pSMB
->InformationLevel
= cpu_to_le16(SMB_QUERY_FILE_INTERNAL_INFO
);
4298 pSMB
->Reserved4
= 0;
4299 inc_rfc1001_len(pSMB
, byte_count
);
4300 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
4302 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
4303 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
4305 cFYI(1, "error %d in QueryInternalInfo", rc
);
4307 /* decode response */
4308 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
4309 /* BB also check enough total bytes returned */
4310 if (rc
|| get_bcc(&pSMBr
->hdr
) < 2)
4311 /* If rc should we check for EOPNOSUPP and
4312 disable the srvino flag? or in caller? */
4313 rc
= -EIO
; /* bad smb */
4315 __u16 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
4316 __u16 count
= le16_to_cpu(pSMBr
->t2
.DataCount
);
4317 struct file_internal_info
*pfinfo
;
4318 /* BB Do we need a cast or hash here ? */
4320 cFYI(1, "Illegal size ret in QryIntrnlInf");
4322 goto GetInodeNumOut
;
4324 pfinfo
= (struct file_internal_info
*)
4325 (data_offset
+ (char *) &pSMBr
->hdr
.Protocol
);
4326 *inode_number
= le64_to_cpu(pfinfo
->UniqueId
);
4330 cifs_buf_release(pSMB
);
4332 goto GetInodeNumberRetry
;
4336 /* parses DFS refferal V3 structure
4337 * caller is responsible for freeing target_nodes
4340 * on failure - errno
4343 parse_DFS_referrals(TRANSACTION2_GET_DFS_REFER_RSP
*pSMBr
,
4344 unsigned int *num_of_nodes
,
4345 struct dfs_info3_param
**target_nodes
,
4346 const struct nls_table
*nls_codepage
, int remap
,
4347 const char *searchName
)
4352 struct dfs_referral_level_3
*ref
;
4354 if (pSMBr
->hdr
.Flags2
& SMBFLG2_UNICODE
)
4358 *num_of_nodes
= le16_to_cpu(pSMBr
->NumberOfReferrals
);
4360 if (*num_of_nodes
< 1) {
4361 cERROR(1, "num_referrals: must be at least > 0,"
4362 "but we get num_referrals = %d\n", *num_of_nodes
);
4364 goto parse_DFS_referrals_exit
;
4367 ref
= (struct dfs_referral_level_3
*) &(pSMBr
->referrals
);
4368 if (ref
->VersionNumber
!= cpu_to_le16(3)) {
4369 cERROR(1, "Referrals of V%d version are not supported,"
4370 "should be V3", le16_to_cpu(ref
->VersionNumber
));
4372 goto parse_DFS_referrals_exit
;
4375 /* get the upper boundary of the resp buffer */
4376 data_end
= (char *)(&(pSMBr
->PathConsumed
)) +
4377 le16_to_cpu(pSMBr
->t2
.DataCount
);
4379 cFYI(1, "num_referrals: %d dfs flags: 0x%x ...\n",
4381 le32_to_cpu(pSMBr
->DFSFlags
));
4383 *target_nodes
= kzalloc(sizeof(struct dfs_info3_param
) *
4384 *num_of_nodes
, GFP_KERNEL
);
4385 if (*target_nodes
== NULL
) {
4386 cERROR(1, "Failed to allocate buffer for target_nodes\n");
4388 goto parse_DFS_referrals_exit
;
4391 /* collect necessary data from referrals */
4392 for (i
= 0; i
< *num_of_nodes
; i
++) {
4395 struct dfs_info3_param
*node
= (*target_nodes
)+i
;
4397 node
->flags
= le32_to_cpu(pSMBr
->DFSFlags
);
4399 __le16
*tmp
= kmalloc(strlen(searchName
)*2 + 2,
4403 goto parse_DFS_referrals_exit
;
4405 cifsConvertToUCS((__le16
*) tmp
, searchName
,
4406 PATH_MAX
, nls_codepage
, remap
);
4407 node
->path_consumed
= cifs_ucs2_bytes(tmp
,
4408 le16_to_cpu(pSMBr
->PathConsumed
),
4412 node
->path_consumed
= le16_to_cpu(pSMBr
->PathConsumed
);
4414 node
->server_type
= le16_to_cpu(ref
->ServerType
);
4415 node
->ref_flag
= le16_to_cpu(ref
->ReferralEntryFlags
);
4418 temp
= (char *)ref
+ le16_to_cpu(ref
->DfsPathOffset
);
4419 max_len
= data_end
- temp
;
4420 node
->path_name
= cifs_strndup_from_ucs(temp
, max_len
,
4421 is_unicode
, nls_codepage
);
4422 if (!node
->path_name
) {
4424 goto parse_DFS_referrals_exit
;
4427 /* copy link target UNC */
4428 temp
= (char *)ref
+ le16_to_cpu(ref
->NetworkAddressOffset
);
4429 max_len
= data_end
- temp
;
4430 node
->node_name
= cifs_strndup_from_ucs(temp
, max_len
,
4431 is_unicode
, nls_codepage
);
4432 if (!node
->node_name
)
4436 parse_DFS_referrals_exit
:
4438 free_dfs_info_array(*target_nodes
, *num_of_nodes
);
4439 *target_nodes
= NULL
;
4446 CIFSGetDFSRefer(const int xid
, struct cifs_ses
*ses
,
4447 const unsigned char *searchName
,
4448 struct dfs_info3_param
**target_nodes
,
4449 unsigned int *num_of_nodes
,
4450 const struct nls_table
*nls_codepage
, int remap
)
4452 /* TRANS2_GET_DFS_REFERRAL */
4453 TRANSACTION2_GET_DFS_REFER_REQ
*pSMB
= NULL
;
4454 TRANSACTION2_GET_DFS_REFER_RSP
*pSMBr
= NULL
;
4458 __u16 params
, byte_count
;
4460 *target_nodes
= NULL
;
4462 cFYI(1, "In GetDFSRefer the path %s", searchName
);
4466 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, NULL
, (void **) &pSMB
,
4471 /* server pointer checked in called function,
4472 but should never be null here anyway */
4473 pSMB
->hdr
.Mid
= GetNextMid(ses
->server
);
4474 pSMB
->hdr
.Tid
= ses
->ipc_tid
;
4475 pSMB
->hdr
.Uid
= ses
->Suid
;
4476 if (ses
->capabilities
& CAP_STATUS32
)
4477 pSMB
->hdr
.Flags2
|= SMBFLG2_ERR_STATUS
;
4478 if (ses
->capabilities
& CAP_DFS
)
4479 pSMB
->hdr
.Flags2
|= SMBFLG2_DFS
;
4481 if (ses
->capabilities
& CAP_UNICODE
) {
4482 pSMB
->hdr
.Flags2
|= SMBFLG2_UNICODE
;
4484 cifsConvertToUCS((__le16
*) pSMB
->RequestFileName
,
4485 searchName
, PATH_MAX
, nls_codepage
, remap
);
4486 name_len
++; /* trailing null */
4488 } else { /* BB improve the check for buffer overruns BB */
4489 name_len
= strnlen(searchName
, PATH_MAX
);
4490 name_len
++; /* trailing null */
4491 strncpy(pSMB
->RequestFileName
, searchName
, name_len
);
4495 if (ses
->server
->sec_mode
&
4496 (SECMODE_SIGN_REQUIRED
| SECMODE_SIGN_ENABLED
))
4497 pSMB
->hdr
.Flags2
|= SMBFLG2_SECURITY_SIGNATURE
;
4500 pSMB
->hdr
.Uid
= ses
->Suid
;
4502 params
= 2 /* level */ + name_len
/*includes null */ ;
4503 pSMB
->TotalDataCount
= 0;
4504 pSMB
->DataCount
= 0;
4505 pSMB
->DataOffset
= 0;
4506 pSMB
->MaxParameterCount
= 0;
4507 /* BB find exact max SMB PDU from sess structure BB */
4508 pSMB
->MaxDataCount
= cpu_to_le16(4000);
4509 pSMB
->MaxSetupCount
= 0;
4513 pSMB
->Reserved2
= 0;
4514 pSMB
->ParameterOffset
= cpu_to_le16(offsetof(
4515 struct smb_com_transaction2_get_dfs_refer_req
, MaxReferralLevel
) - 4);
4516 pSMB
->SetupCount
= 1;
4517 pSMB
->Reserved3
= 0;
4518 pSMB
->SubCommand
= cpu_to_le16(TRANS2_GET_DFS_REFERRAL
);
4519 byte_count
= params
+ 3 /* pad */ ;
4520 pSMB
->ParameterCount
= cpu_to_le16(params
);
4521 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
4522 pSMB
->MaxReferralLevel
= cpu_to_le16(3);
4523 inc_rfc1001_len(pSMB
, byte_count
);
4524 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
4526 rc
= SendReceive(xid
, ses
, (struct smb_hdr
*) pSMB
,
4527 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
4529 cFYI(1, "Send error in GetDFSRefer = %d", rc
);
4532 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
4534 /* BB Also check if enough total bytes returned? */
4535 if (rc
|| get_bcc(&pSMBr
->hdr
) < 17) {
4536 rc
= -EIO
; /* bad smb */
4540 cFYI(1, "Decoding GetDFSRefer response BCC: %d Offset %d",
4541 get_bcc(&pSMBr
->hdr
),
4542 le16_to_cpu(pSMBr
->t2
.DataOffset
));
4544 /* parse returned result into more usable form */
4545 rc
= parse_DFS_referrals(pSMBr
, num_of_nodes
,
4546 target_nodes
, nls_codepage
, remap
,
4550 cifs_buf_release(pSMB
);
4558 /* Query File System Info such as free space to old servers such as Win 9x */
4560 SMBOldQFSInfo(const int xid
, struct cifs_tcon
*tcon
, struct kstatfs
*FSData
)
4562 /* level 0x01 SMB_QUERY_FILE_SYSTEM_INFO */
4563 TRANSACTION2_QFSI_REQ
*pSMB
= NULL
;
4564 TRANSACTION2_QFSI_RSP
*pSMBr
= NULL
;
4565 FILE_SYSTEM_ALLOC_INFO
*response_data
;
4567 int bytes_returned
= 0;
4568 __u16 params
, byte_count
;
4570 cFYI(1, "OldQFSInfo");
4572 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
4577 params
= 2; /* level */
4578 pSMB
->TotalDataCount
= 0;
4579 pSMB
->MaxParameterCount
= cpu_to_le16(2);
4580 pSMB
->MaxDataCount
= cpu_to_le16(1000);
4581 pSMB
->MaxSetupCount
= 0;
4585 pSMB
->Reserved2
= 0;
4586 byte_count
= params
+ 1 /* pad */ ;
4587 pSMB
->TotalParameterCount
= cpu_to_le16(params
);
4588 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
4589 pSMB
->ParameterOffset
= cpu_to_le16(offsetof(
4590 struct smb_com_transaction2_qfsi_req
, InformationLevel
) - 4);
4591 pSMB
->DataCount
= 0;
4592 pSMB
->DataOffset
= 0;
4593 pSMB
->SetupCount
= 1;
4594 pSMB
->Reserved3
= 0;
4595 pSMB
->SubCommand
= cpu_to_le16(TRANS2_QUERY_FS_INFORMATION
);
4596 pSMB
->InformationLevel
= cpu_to_le16(SMB_INFO_ALLOCATION
);
4597 inc_rfc1001_len(pSMB
, byte_count
);
4598 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
4600 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
4601 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
4603 cFYI(1, "Send error in QFSInfo = %d", rc
);
4604 } else { /* decode response */
4605 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
4607 if (rc
|| get_bcc(&pSMBr
->hdr
) < 18)
4608 rc
= -EIO
; /* bad smb */
4610 __u16 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
4611 cFYI(1, "qfsinf resp BCC: %d Offset %d",
4612 get_bcc(&pSMBr
->hdr
), data_offset
);
4614 response_data
= (FILE_SYSTEM_ALLOC_INFO
*)
4615 (((char *) &pSMBr
->hdr
.Protocol
) + data_offset
);
4617 le16_to_cpu(response_data
->BytesPerSector
) *
4618 le32_to_cpu(response_data
->
4619 SectorsPerAllocationUnit
);
4621 le32_to_cpu(response_data
->TotalAllocationUnits
);
4622 FSData
->f_bfree
= FSData
->f_bavail
=
4623 le32_to_cpu(response_data
->FreeAllocationUnits
);
4624 cFYI(1, "Blocks: %lld Free: %lld Block size %ld",
4625 (unsigned long long)FSData
->f_blocks
,
4626 (unsigned long long)FSData
->f_bfree
,
4630 cifs_buf_release(pSMB
);
4633 goto oldQFSInfoRetry
;
4639 CIFSSMBQFSInfo(const int xid
, struct cifs_tcon
*tcon
, struct kstatfs
*FSData
)
4641 /* level 0x103 SMB_QUERY_FILE_SYSTEM_INFO */
4642 TRANSACTION2_QFSI_REQ
*pSMB
= NULL
;
4643 TRANSACTION2_QFSI_RSP
*pSMBr
= NULL
;
4644 FILE_SYSTEM_INFO
*response_data
;
4646 int bytes_returned
= 0;
4647 __u16 params
, byte_count
;
4649 cFYI(1, "In QFSInfo");
4651 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
4656 params
= 2; /* level */
4657 pSMB
->TotalDataCount
= 0;
4658 pSMB
->MaxParameterCount
= cpu_to_le16(2);
4659 pSMB
->MaxDataCount
= cpu_to_le16(1000);
4660 pSMB
->MaxSetupCount
= 0;
4664 pSMB
->Reserved2
= 0;
4665 byte_count
= params
+ 1 /* pad */ ;
4666 pSMB
->TotalParameterCount
= cpu_to_le16(params
);
4667 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
4668 pSMB
->ParameterOffset
= cpu_to_le16(offsetof(
4669 struct smb_com_transaction2_qfsi_req
, InformationLevel
) - 4);
4670 pSMB
->DataCount
= 0;
4671 pSMB
->DataOffset
= 0;
4672 pSMB
->SetupCount
= 1;
4673 pSMB
->Reserved3
= 0;
4674 pSMB
->SubCommand
= cpu_to_le16(TRANS2_QUERY_FS_INFORMATION
);
4675 pSMB
->InformationLevel
= cpu_to_le16(SMB_QUERY_FS_SIZE_INFO
);
4676 inc_rfc1001_len(pSMB
, byte_count
);
4677 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
4679 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
4680 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
4682 cFYI(1, "Send error in QFSInfo = %d", rc
);
4683 } else { /* decode response */
4684 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
4686 if (rc
|| get_bcc(&pSMBr
->hdr
) < 24)
4687 rc
= -EIO
; /* bad smb */
4689 __u16 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
4693 *) (((char *) &pSMBr
->hdr
.Protocol
) +
4696 le32_to_cpu(response_data
->BytesPerSector
) *
4697 le32_to_cpu(response_data
->
4698 SectorsPerAllocationUnit
);
4700 le64_to_cpu(response_data
->TotalAllocationUnits
);
4701 FSData
->f_bfree
= FSData
->f_bavail
=
4702 le64_to_cpu(response_data
->FreeAllocationUnits
);
4703 cFYI(1, "Blocks: %lld Free: %lld Block size %ld",
4704 (unsigned long long)FSData
->f_blocks
,
4705 (unsigned long long)FSData
->f_bfree
,
4709 cifs_buf_release(pSMB
);
4718 CIFSSMBQFSAttributeInfo(const int xid
, struct cifs_tcon
*tcon
)
4720 /* level 0x105 SMB_QUERY_FILE_SYSTEM_INFO */
4721 TRANSACTION2_QFSI_REQ
*pSMB
= NULL
;
4722 TRANSACTION2_QFSI_RSP
*pSMBr
= NULL
;
4723 FILE_SYSTEM_ATTRIBUTE_INFO
*response_data
;
4725 int bytes_returned
= 0;
4726 __u16 params
, byte_count
;
4728 cFYI(1, "In QFSAttributeInfo");
4730 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
4735 params
= 2; /* level */
4736 pSMB
->TotalDataCount
= 0;
4737 pSMB
->MaxParameterCount
= cpu_to_le16(2);
4738 /* BB find exact max SMB PDU from sess structure BB */
4739 pSMB
->MaxDataCount
= cpu_to_le16(1000);
4740 pSMB
->MaxSetupCount
= 0;
4744 pSMB
->Reserved2
= 0;
4745 byte_count
= params
+ 1 /* pad */ ;
4746 pSMB
->TotalParameterCount
= cpu_to_le16(params
);
4747 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
4748 pSMB
->ParameterOffset
= cpu_to_le16(offsetof(
4749 struct smb_com_transaction2_qfsi_req
, InformationLevel
) - 4);
4750 pSMB
->DataCount
= 0;
4751 pSMB
->DataOffset
= 0;
4752 pSMB
->SetupCount
= 1;
4753 pSMB
->Reserved3
= 0;
4754 pSMB
->SubCommand
= cpu_to_le16(TRANS2_QUERY_FS_INFORMATION
);
4755 pSMB
->InformationLevel
= cpu_to_le16(SMB_QUERY_FS_ATTRIBUTE_INFO
);
4756 inc_rfc1001_len(pSMB
, byte_count
);
4757 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
4759 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
4760 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
4762 cERROR(1, "Send error in QFSAttributeInfo = %d", rc
);
4763 } else { /* decode response */
4764 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
4766 if (rc
|| get_bcc(&pSMBr
->hdr
) < 13) {
4767 /* BB also check if enough bytes returned */
4768 rc
= -EIO
; /* bad smb */
4770 __u16 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
4772 (FILE_SYSTEM_ATTRIBUTE_INFO
4773 *) (((char *) &pSMBr
->hdr
.Protocol
) +
4775 memcpy(&tcon
->fsAttrInfo
, response_data
,
4776 sizeof(FILE_SYSTEM_ATTRIBUTE_INFO
));
4779 cifs_buf_release(pSMB
);
4782 goto QFSAttributeRetry
;
4788 CIFSSMBQFSDeviceInfo(const int xid
, struct cifs_tcon
*tcon
)
4790 /* level 0x104 SMB_QUERY_FILE_SYSTEM_INFO */
4791 TRANSACTION2_QFSI_REQ
*pSMB
= NULL
;
4792 TRANSACTION2_QFSI_RSP
*pSMBr
= NULL
;
4793 FILE_SYSTEM_DEVICE_INFO
*response_data
;
4795 int bytes_returned
= 0;
4796 __u16 params
, byte_count
;
4798 cFYI(1, "In QFSDeviceInfo");
4800 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
4805 params
= 2; /* level */
4806 pSMB
->TotalDataCount
= 0;
4807 pSMB
->MaxParameterCount
= cpu_to_le16(2);
4808 /* BB find exact max SMB PDU from sess structure BB */
4809 pSMB
->MaxDataCount
= cpu_to_le16(1000);
4810 pSMB
->MaxSetupCount
= 0;
4814 pSMB
->Reserved2
= 0;
4815 byte_count
= params
+ 1 /* pad */ ;
4816 pSMB
->TotalParameterCount
= cpu_to_le16(params
);
4817 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
4818 pSMB
->ParameterOffset
= cpu_to_le16(offsetof(
4819 struct smb_com_transaction2_qfsi_req
, InformationLevel
) - 4);
4821 pSMB
->DataCount
= 0;
4822 pSMB
->DataOffset
= 0;
4823 pSMB
->SetupCount
= 1;
4824 pSMB
->Reserved3
= 0;
4825 pSMB
->SubCommand
= cpu_to_le16(TRANS2_QUERY_FS_INFORMATION
);
4826 pSMB
->InformationLevel
= cpu_to_le16(SMB_QUERY_FS_DEVICE_INFO
);
4827 inc_rfc1001_len(pSMB
, byte_count
);
4828 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
4830 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
4831 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
4833 cFYI(1, "Send error in QFSDeviceInfo = %d", rc
);
4834 } else { /* decode response */
4835 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
4837 if (rc
|| get_bcc(&pSMBr
->hdr
) <
4838 sizeof(FILE_SYSTEM_DEVICE_INFO
))
4839 rc
= -EIO
; /* bad smb */
4841 __u16 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
4843 (FILE_SYSTEM_DEVICE_INFO
*)
4844 (((char *) &pSMBr
->hdr
.Protocol
) +
4846 memcpy(&tcon
->fsDevInfo
, response_data
,
4847 sizeof(FILE_SYSTEM_DEVICE_INFO
));
4850 cifs_buf_release(pSMB
);
4853 goto QFSDeviceRetry
;
4859 CIFSSMBQFSUnixInfo(const int xid
, struct cifs_tcon
*tcon
)
4861 /* level 0x200 SMB_QUERY_CIFS_UNIX_INFO */
4862 TRANSACTION2_QFSI_REQ
*pSMB
= NULL
;
4863 TRANSACTION2_QFSI_RSP
*pSMBr
= NULL
;
4864 FILE_SYSTEM_UNIX_INFO
*response_data
;
4866 int bytes_returned
= 0;
4867 __u16 params
, byte_count
;
4869 cFYI(1, "In QFSUnixInfo");
4871 rc
= smb_init_no_reconnect(SMB_COM_TRANSACTION2
, 15, tcon
,
4872 (void **) &pSMB
, (void **) &pSMBr
);
4876 params
= 2; /* level */
4877 pSMB
->TotalDataCount
= 0;
4878 pSMB
->DataCount
= 0;
4879 pSMB
->DataOffset
= 0;
4880 pSMB
->MaxParameterCount
= cpu_to_le16(2);
4881 /* BB find exact max SMB PDU from sess structure BB */
4882 pSMB
->MaxDataCount
= cpu_to_le16(100);
4883 pSMB
->MaxSetupCount
= 0;
4887 pSMB
->Reserved2
= 0;
4888 byte_count
= params
+ 1 /* pad */ ;
4889 pSMB
->ParameterCount
= cpu_to_le16(params
);
4890 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
4891 pSMB
->ParameterOffset
= cpu_to_le16(offsetof(struct
4892 smb_com_transaction2_qfsi_req
, InformationLevel
) - 4);
4893 pSMB
->SetupCount
= 1;
4894 pSMB
->Reserved3
= 0;
4895 pSMB
->SubCommand
= cpu_to_le16(TRANS2_QUERY_FS_INFORMATION
);
4896 pSMB
->InformationLevel
= cpu_to_le16(SMB_QUERY_CIFS_UNIX_INFO
);
4897 inc_rfc1001_len(pSMB
, byte_count
);
4898 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
4900 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
4901 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
4903 cERROR(1, "Send error in QFSUnixInfo = %d", rc
);
4904 } else { /* decode response */
4905 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
4907 if (rc
|| get_bcc(&pSMBr
->hdr
) < 13) {
4908 rc
= -EIO
; /* bad smb */
4910 __u16 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
4912 (FILE_SYSTEM_UNIX_INFO
4913 *) (((char *) &pSMBr
->hdr
.Protocol
) +
4915 memcpy(&tcon
->fsUnixInfo
, response_data
,
4916 sizeof(FILE_SYSTEM_UNIX_INFO
));
4919 cifs_buf_release(pSMB
);
4929 CIFSSMBSetFSUnixInfo(const int xid
, struct cifs_tcon
*tcon
, __u64 cap
)
4931 /* level 0x200 SMB_SET_CIFS_UNIX_INFO */
4932 TRANSACTION2_SETFSI_REQ
*pSMB
= NULL
;
4933 TRANSACTION2_SETFSI_RSP
*pSMBr
= NULL
;
4935 int bytes_returned
= 0;
4936 __u16 params
, param_offset
, offset
, byte_count
;
4938 cFYI(1, "In SETFSUnixInfo");
4940 /* BB switch to small buf init to save memory */
4941 rc
= smb_init_no_reconnect(SMB_COM_TRANSACTION2
, 15, tcon
,
4942 (void **) &pSMB
, (void **) &pSMBr
);
4946 params
= 4; /* 2 bytes zero followed by info level. */
4947 pSMB
->MaxSetupCount
= 0;
4951 pSMB
->Reserved2
= 0;
4952 param_offset
= offsetof(struct smb_com_transaction2_setfsi_req
, FileNum
)
4954 offset
= param_offset
+ params
;
4956 pSMB
->MaxParameterCount
= cpu_to_le16(4);
4957 /* BB find exact max SMB PDU from sess structure BB */
4958 pSMB
->MaxDataCount
= cpu_to_le16(100);
4959 pSMB
->SetupCount
= 1;
4960 pSMB
->Reserved3
= 0;
4961 pSMB
->SubCommand
= cpu_to_le16(TRANS2_SET_FS_INFORMATION
);
4962 byte_count
= 1 /* pad */ + params
+ 12;
4964 pSMB
->DataCount
= cpu_to_le16(12);
4965 pSMB
->ParameterCount
= cpu_to_le16(params
);
4966 pSMB
->TotalDataCount
= pSMB
->DataCount
;
4967 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
4968 pSMB
->ParameterOffset
= cpu_to_le16(param_offset
);
4969 pSMB
->DataOffset
= cpu_to_le16(offset
);
4973 pSMB
->InformationLevel
= cpu_to_le16(SMB_SET_CIFS_UNIX_INFO
);
4976 pSMB
->ClientUnixMajor
= cpu_to_le16(CIFS_UNIX_MAJOR_VERSION
);
4977 pSMB
->ClientUnixMinor
= cpu_to_le16(CIFS_UNIX_MINOR_VERSION
);
4978 pSMB
->ClientUnixCap
= cpu_to_le64(cap
);
4980 inc_rfc1001_len(pSMB
, byte_count
);
4981 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
4983 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
4984 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
4986 cERROR(1, "Send error in SETFSUnixInfo = %d", rc
);
4987 } else { /* decode response */
4988 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
4990 rc
= -EIO
; /* bad smb */
4992 cifs_buf_release(pSMB
);
4995 goto SETFSUnixRetry
;
5003 CIFSSMBQFSPosixInfo(const int xid
, struct cifs_tcon
*tcon
,
5004 struct kstatfs
*FSData
)
5006 /* level 0x201 SMB_QUERY_CIFS_POSIX_INFO */
5007 TRANSACTION2_QFSI_REQ
*pSMB
= NULL
;
5008 TRANSACTION2_QFSI_RSP
*pSMBr
= NULL
;
5009 FILE_SYSTEM_POSIX_INFO
*response_data
;
5011 int bytes_returned
= 0;
5012 __u16 params
, byte_count
;
5014 cFYI(1, "In QFSPosixInfo");
5016 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
5021 params
= 2; /* level */
5022 pSMB
->TotalDataCount
= 0;
5023 pSMB
->DataCount
= 0;
5024 pSMB
->DataOffset
= 0;
5025 pSMB
->MaxParameterCount
= cpu_to_le16(2);
5026 /* BB find exact max SMB PDU from sess structure BB */
5027 pSMB
->MaxDataCount
= cpu_to_le16(100);
5028 pSMB
->MaxSetupCount
= 0;
5032 pSMB
->Reserved2
= 0;
5033 byte_count
= params
+ 1 /* pad */ ;
5034 pSMB
->ParameterCount
= cpu_to_le16(params
);
5035 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
5036 pSMB
->ParameterOffset
= cpu_to_le16(offsetof(struct
5037 smb_com_transaction2_qfsi_req
, InformationLevel
) - 4);
5038 pSMB
->SetupCount
= 1;
5039 pSMB
->Reserved3
= 0;
5040 pSMB
->SubCommand
= cpu_to_le16(TRANS2_QUERY_FS_INFORMATION
);
5041 pSMB
->InformationLevel
= cpu_to_le16(SMB_QUERY_POSIX_FS_INFO
);
5042 inc_rfc1001_len(pSMB
, byte_count
);
5043 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
5045 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
5046 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
5048 cFYI(1, "Send error in QFSUnixInfo = %d", rc
);
5049 } else { /* decode response */
5050 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
5052 if (rc
|| get_bcc(&pSMBr
->hdr
) < 13) {
5053 rc
= -EIO
; /* bad smb */
5055 __u16 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
5057 (FILE_SYSTEM_POSIX_INFO
5058 *) (((char *) &pSMBr
->hdr
.Protocol
) +
5061 le32_to_cpu(response_data
->BlockSize
);
5063 le64_to_cpu(response_data
->TotalBlocks
);
5065 le64_to_cpu(response_data
->BlocksAvail
);
5066 if (response_data
->UserBlocksAvail
== cpu_to_le64(-1)) {
5067 FSData
->f_bavail
= FSData
->f_bfree
;
5070 le64_to_cpu(response_data
->UserBlocksAvail
);
5072 if (response_data
->TotalFileNodes
!= cpu_to_le64(-1))
5074 le64_to_cpu(response_data
->TotalFileNodes
);
5075 if (response_data
->FreeFileNodes
!= cpu_to_le64(-1))
5077 le64_to_cpu(response_data
->FreeFileNodes
);
5080 cifs_buf_release(pSMB
);
5089 /* We can not use write of zero bytes trick to
5090 set file size due to need for large file support. Also note that
5091 this SetPathInfo is preferred to SetFileInfo based method in next
5092 routine which is only needed to work around a sharing violation bug
5093 in Samba which this routine can run into */
5096 CIFSSMBSetEOF(const int xid
, struct cifs_tcon
*tcon
, const char *fileName
,
5097 __u64 size
, bool SetAllocation
,
5098 const struct nls_table
*nls_codepage
, int remap
)
5100 struct smb_com_transaction2_spi_req
*pSMB
= NULL
;
5101 struct smb_com_transaction2_spi_rsp
*pSMBr
= NULL
;
5102 struct file_end_of_file_info
*parm_data
;
5105 int bytes_returned
= 0;
5106 __u16 params
, byte_count
, data_count
, param_offset
, offset
;
5108 cFYI(1, "In SetEOF");
5110 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
5115 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
5117 cifsConvertToUCS((__le16
*) pSMB
->FileName
, fileName
,
5118 PATH_MAX
, nls_codepage
, remap
);
5119 name_len
++; /* trailing null */
5121 } else { /* BB improve the check for buffer overruns BB */
5122 name_len
= strnlen(fileName
, PATH_MAX
);
5123 name_len
++; /* trailing null */
5124 strncpy(pSMB
->FileName
, fileName
, name_len
);
5126 params
= 6 + name_len
;
5127 data_count
= sizeof(struct file_end_of_file_info
);
5128 pSMB
->MaxParameterCount
= cpu_to_le16(2);
5129 pSMB
->MaxDataCount
= cpu_to_le16(4100);
5130 pSMB
->MaxSetupCount
= 0;
5134 pSMB
->Reserved2
= 0;
5135 param_offset
= offsetof(struct smb_com_transaction2_spi_req
,
5136 InformationLevel
) - 4;
5137 offset
= param_offset
+ params
;
5138 if (SetAllocation
) {
5139 if (tcon
->ses
->capabilities
& CAP_INFOLEVEL_PASSTHRU
)
5140 pSMB
->InformationLevel
=
5141 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2
);
5143 pSMB
->InformationLevel
=
5144 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO
);
5145 } else /* Set File Size */ {
5146 if (tcon
->ses
->capabilities
& CAP_INFOLEVEL_PASSTHRU
)
5147 pSMB
->InformationLevel
=
5148 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO2
);
5150 pSMB
->InformationLevel
=
5151 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO
);
5155 (struct file_end_of_file_info
*) (((char *) &pSMB
->hdr
.Protocol
) +
5157 pSMB
->ParameterOffset
= cpu_to_le16(param_offset
);
5158 pSMB
->DataOffset
= cpu_to_le16(offset
);
5159 pSMB
->SetupCount
= 1;
5160 pSMB
->Reserved3
= 0;
5161 pSMB
->SubCommand
= cpu_to_le16(TRANS2_SET_PATH_INFORMATION
);
5162 byte_count
= 3 /* pad */ + params
+ data_count
;
5163 pSMB
->DataCount
= cpu_to_le16(data_count
);
5164 pSMB
->TotalDataCount
= pSMB
->DataCount
;
5165 pSMB
->ParameterCount
= cpu_to_le16(params
);
5166 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
5167 pSMB
->Reserved4
= 0;
5168 inc_rfc1001_len(pSMB
, byte_count
);
5169 parm_data
->FileSize
= cpu_to_le64(size
);
5170 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
5171 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
5172 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
5174 cFYI(1, "SetPathInfo (file size) returned %d", rc
);
5176 cifs_buf_release(pSMB
);
5185 CIFSSMBSetFileSize(const int xid
, struct cifs_tcon
*tcon
, __u64 size
,
5186 __u16 fid
, __u32 pid_of_opener
, bool SetAllocation
)
5188 struct smb_com_transaction2_sfi_req
*pSMB
= NULL
;
5189 struct file_end_of_file_info
*parm_data
;
5191 __u16 params
, param_offset
, offset
, byte_count
, count
;
5193 cFYI(1, "SetFileSize (via SetFileInfo) %lld",
5195 rc
= small_smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
);
5200 pSMB
->hdr
.Pid
= cpu_to_le16((__u16
)pid_of_opener
);
5201 pSMB
->hdr
.PidHigh
= cpu_to_le16((__u16
)(pid_of_opener
>> 16));
5204 pSMB
->MaxSetupCount
= 0;
5208 pSMB
->Reserved2
= 0;
5209 param_offset
= offsetof(struct smb_com_transaction2_sfi_req
, Fid
) - 4;
5210 offset
= param_offset
+ params
;
5212 count
= sizeof(struct file_end_of_file_info
);
5213 pSMB
->MaxParameterCount
= cpu_to_le16(2);
5214 /* BB find exact max SMB PDU from sess structure BB */
5215 pSMB
->MaxDataCount
= cpu_to_le16(1000);
5216 pSMB
->SetupCount
= 1;
5217 pSMB
->Reserved3
= 0;
5218 pSMB
->SubCommand
= cpu_to_le16(TRANS2_SET_FILE_INFORMATION
);
5219 byte_count
= 3 /* pad */ + params
+ count
;
5220 pSMB
->DataCount
= cpu_to_le16(count
);
5221 pSMB
->ParameterCount
= cpu_to_le16(params
);
5222 pSMB
->TotalDataCount
= pSMB
->DataCount
;
5223 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
5224 pSMB
->ParameterOffset
= cpu_to_le16(param_offset
);
5226 (struct file_end_of_file_info
*) (((char *) &pSMB
->hdr
.Protocol
)
5228 pSMB
->DataOffset
= cpu_to_le16(offset
);
5229 parm_data
->FileSize
= cpu_to_le64(size
);
5231 if (SetAllocation
) {
5232 if (tcon
->ses
->capabilities
& CAP_INFOLEVEL_PASSTHRU
)
5233 pSMB
->InformationLevel
=
5234 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2
);
5236 pSMB
->InformationLevel
=
5237 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO
);
5238 } else /* Set File Size */ {
5239 if (tcon
->ses
->capabilities
& CAP_INFOLEVEL_PASSTHRU
)
5240 pSMB
->InformationLevel
=
5241 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO2
);
5243 pSMB
->InformationLevel
=
5244 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO
);
5246 pSMB
->Reserved4
= 0;
5247 inc_rfc1001_len(pSMB
, byte_count
);
5248 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
5249 rc
= SendReceiveNoRsp(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
, 0);
5251 cFYI(1, "Send error in SetFileInfo (SetFileSize) = %d", rc
);
5254 /* Note: On -EAGAIN error only caller can retry on handle based calls
5255 since file handle passed in no longer valid */
5260 /* Some legacy servers such as NT4 require that the file times be set on
5261 an open handle, rather than by pathname - this is awkward due to
5262 potential access conflicts on the open, but it is unavoidable for these
5263 old servers since the only other choice is to go from 100 nanosecond DCE
5264 time and resort to the original setpathinfo level which takes the ancient
5265 DOS time format with 2 second granularity */
5267 CIFSSMBSetFileInfo(const int xid
, struct cifs_tcon
*tcon
,
5268 const FILE_BASIC_INFO
*data
, __u16 fid
, __u32 pid_of_opener
)
5270 struct smb_com_transaction2_sfi_req
*pSMB
= NULL
;
5273 __u16 params
, param_offset
, offset
, byte_count
, count
;
5275 cFYI(1, "Set Times (via SetFileInfo)");
5276 rc
= small_smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
);
5281 pSMB
->hdr
.Pid
= cpu_to_le16((__u16
)pid_of_opener
);
5282 pSMB
->hdr
.PidHigh
= cpu_to_le16((__u16
)(pid_of_opener
>> 16));
5285 pSMB
->MaxSetupCount
= 0;
5289 pSMB
->Reserved2
= 0;
5290 param_offset
= offsetof(struct smb_com_transaction2_sfi_req
, Fid
) - 4;
5291 offset
= param_offset
+ params
;
5293 data_offset
= (char *) (&pSMB
->hdr
.Protocol
) + offset
;
5295 count
= sizeof(FILE_BASIC_INFO
);
5296 pSMB
->MaxParameterCount
= cpu_to_le16(2);
5297 /* BB find max SMB PDU from sess */
5298 pSMB
->MaxDataCount
= cpu_to_le16(1000);
5299 pSMB
->SetupCount
= 1;
5300 pSMB
->Reserved3
= 0;
5301 pSMB
->SubCommand
= cpu_to_le16(TRANS2_SET_FILE_INFORMATION
);
5302 byte_count
= 3 /* pad */ + params
+ count
;
5303 pSMB
->DataCount
= cpu_to_le16(count
);
5304 pSMB
->ParameterCount
= cpu_to_le16(params
);
5305 pSMB
->TotalDataCount
= pSMB
->DataCount
;
5306 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
5307 pSMB
->ParameterOffset
= cpu_to_le16(param_offset
);
5308 pSMB
->DataOffset
= cpu_to_le16(offset
);
5310 if (tcon
->ses
->capabilities
& CAP_INFOLEVEL_PASSTHRU
)
5311 pSMB
->InformationLevel
= cpu_to_le16(SMB_SET_FILE_BASIC_INFO2
);
5313 pSMB
->InformationLevel
= cpu_to_le16(SMB_SET_FILE_BASIC_INFO
);
5314 pSMB
->Reserved4
= 0;
5315 inc_rfc1001_len(pSMB
, byte_count
);
5316 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
5317 memcpy(data_offset
, data
, sizeof(FILE_BASIC_INFO
));
5318 rc
= SendReceiveNoRsp(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
, 0);
5320 cFYI(1, "Send error in Set Time (SetFileInfo) = %d", rc
);
5322 /* Note: On -EAGAIN error only caller can retry on handle based calls
5323 since file handle passed in no longer valid */
5329 CIFSSMBSetFileDisposition(const int xid
, struct cifs_tcon
*tcon
,
5330 bool delete_file
, __u16 fid
, __u32 pid_of_opener
)
5332 struct smb_com_transaction2_sfi_req
*pSMB
= NULL
;
5335 __u16 params
, param_offset
, offset
, byte_count
, count
;
5337 cFYI(1, "Set File Disposition (via SetFileInfo)");
5338 rc
= small_smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
);
5343 pSMB
->hdr
.Pid
= cpu_to_le16((__u16
)pid_of_opener
);
5344 pSMB
->hdr
.PidHigh
= cpu_to_le16((__u16
)(pid_of_opener
>> 16));
5347 pSMB
->MaxSetupCount
= 0;
5351 pSMB
->Reserved2
= 0;
5352 param_offset
= offsetof(struct smb_com_transaction2_sfi_req
, Fid
) - 4;
5353 offset
= param_offset
+ params
;
5355 data_offset
= (char *) (&pSMB
->hdr
.Protocol
) + offset
;
5358 pSMB
->MaxParameterCount
= cpu_to_le16(2);
5359 /* BB find max SMB PDU from sess */
5360 pSMB
->MaxDataCount
= cpu_to_le16(1000);
5361 pSMB
->SetupCount
= 1;
5362 pSMB
->Reserved3
= 0;
5363 pSMB
->SubCommand
= cpu_to_le16(TRANS2_SET_FILE_INFORMATION
);
5364 byte_count
= 3 /* pad */ + params
+ count
;
5365 pSMB
->DataCount
= cpu_to_le16(count
);
5366 pSMB
->ParameterCount
= cpu_to_le16(params
);
5367 pSMB
->TotalDataCount
= pSMB
->DataCount
;
5368 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
5369 pSMB
->ParameterOffset
= cpu_to_le16(param_offset
);
5370 pSMB
->DataOffset
= cpu_to_le16(offset
);
5372 pSMB
->InformationLevel
= cpu_to_le16(SMB_SET_FILE_DISPOSITION_INFO
);
5373 pSMB
->Reserved4
= 0;
5374 inc_rfc1001_len(pSMB
, byte_count
);
5375 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
5376 *data_offset
= delete_file
? 1 : 0;
5377 rc
= SendReceiveNoRsp(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
, 0);
5379 cFYI(1, "Send error in SetFileDisposition = %d", rc
);
5385 CIFSSMBSetPathInfo(const int xid
, struct cifs_tcon
*tcon
,
5386 const char *fileName
, const FILE_BASIC_INFO
*data
,
5387 const struct nls_table
*nls_codepage
, int remap
)
5389 TRANSACTION2_SPI_REQ
*pSMB
= NULL
;
5390 TRANSACTION2_SPI_RSP
*pSMBr
= NULL
;
5393 int bytes_returned
= 0;
5395 __u16 params
, param_offset
, offset
, byte_count
, count
;
5397 cFYI(1, "In SetTimes");
5400 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
5405 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
5407 cifsConvertToUCS((__le16
*) pSMB
->FileName
, fileName
,
5408 PATH_MAX
, nls_codepage
, remap
);
5409 name_len
++; /* trailing null */
5411 } else { /* BB improve the check for buffer overruns BB */
5412 name_len
= strnlen(fileName
, PATH_MAX
);
5413 name_len
++; /* trailing null */
5414 strncpy(pSMB
->FileName
, fileName
, name_len
);
5417 params
= 6 + name_len
;
5418 count
= sizeof(FILE_BASIC_INFO
);
5419 pSMB
->MaxParameterCount
= cpu_to_le16(2);
5420 /* BB find max SMB PDU from sess structure BB */
5421 pSMB
->MaxDataCount
= cpu_to_le16(1000);
5422 pSMB
->MaxSetupCount
= 0;
5426 pSMB
->Reserved2
= 0;
5427 param_offset
= offsetof(struct smb_com_transaction2_spi_req
,
5428 InformationLevel
) - 4;
5429 offset
= param_offset
+ params
;
5430 data_offset
= (char *) (&pSMB
->hdr
.Protocol
) + offset
;
5431 pSMB
->ParameterOffset
= cpu_to_le16(param_offset
);
5432 pSMB
->DataOffset
= cpu_to_le16(offset
);
5433 pSMB
->SetupCount
= 1;
5434 pSMB
->Reserved3
= 0;
5435 pSMB
->SubCommand
= cpu_to_le16(TRANS2_SET_PATH_INFORMATION
);
5436 byte_count
= 3 /* pad */ + params
+ count
;
5438 pSMB
->DataCount
= cpu_to_le16(count
);
5439 pSMB
->ParameterCount
= cpu_to_le16(params
);
5440 pSMB
->TotalDataCount
= pSMB
->DataCount
;
5441 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
5442 if (tcon
->ses
->capabilities
& CAP_INFOLEVEL_PASSTHRU
)
5443 pSMB
->InformationLevel
= cpu_to_le16(SMB_SET_FILE_BASIC_INFO2
);
5445 pSMB
->InformationLevel
= cpu_to_le16(SMB_SET_FILE_BASIC_INFO
);
5446 pSMB
->Reserved4
= 0;
5447 inc_rfc1001_len(pSMB
, byte_count
);
5448 memcpy(data_offset
, data
, sizeof(FILE_BASIC_INFO
));
5449 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
5450 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
5451 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
5453 cFYI(1, "SetPathInfo (times) returned %d", rc
);
5455 cifs_buf_release(pSMB
);
5463 /* Can not be used to set time stamps yet (due to old DOS time format) */
5464 /* Can be used to set attributes */
5465 #if 0 /* Possibly not needed - since it turns out that strangely NT4 has a bug
5466 handling it anyway and NT4 was what we thought it would be needed for
5467 Do not delete it until we prove whether needed for Win9x though */
5469 CIFSSMBSetAttrLegacy(int xid
, struct cifs_tcon
*tcon
, char *fileName
,
5470 __u16 dos_attrs
, const struct nls_table
*nls_codepage
)
5472 SETATTR_REQ
*pSMB
= NULL
;
5473 SETATTR_RSP
*pSMBr
= NULL
;
5478 cFYI(1, "In SetAttrLegacy");
5481 rc
= smb_init(SMB_COM_SETATTR
, 8, tcon
, (void **) &pSMB
,
5486 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
5488 ConvertToUCS((__le16
*) pSMB
->fileName
, fileName
,
5489 PATH_MAX
, nls_codepage
);
5490 name_len
++; /* trailing null */
5492 } else { /* BB improve the check for buffer overruns BB */
5493 name_len
= strnlen(fileName
, PATH_MAX
);
5494 name_len
++; /* trailing null */
5495 strncpy(pSMB
->fileName
, fileName
, name_len
);
5497 pSMB
->attr
= cpu_to_le16(dos_attrs
);
5498 pSMB
->BufferFormat
= 0x04;
5499 inc_rfc1001_len(pSMB
, name_len
+ 1);
5500 pSMB
->ByteCount
= cpu_to_le16(name_len
+ 1);
5501 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
5502 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
5504 cFYI(1, "Error in LegacySetAttr = %d", rc
);
5506 cifs_buf_release(pSMB
);
5509 goto SetAttrLgcyRetry
;
5513 #endif /* temporarily unneeded SetAttr legacy function */
5516 cifs_fill_unix_set_info(FILE_UNIX_BASIC_INFO
*data_offset
,
5517 const struct cifs_unix_set_info_args
*args
)
5519 u64 mode
= args
->mode
;
5522 * Samba server ignores set of file size to zero due to bugs in some
5523 * older clients, but we should be precise - we use SetFileSize to
5524 * set file size and do not want to truncate file size to zero
5525 * accidentally as happened on one Samba server beta by putting
5526 * zero instead of -1 here
5528 data_offset
->EndOfFile
= cpu_to_le64(NO_CHANGE_64
);
5529 data_offset
->NumOfBytes
= cpu_to_le64(NO_CHANGE_64
);
5530 data_offset
->LastStatusChange
= cpu_to_le64(args
->ctime
);
5531 data_offset
->LastAccessTime
= cpu_to_le64(args
->atime
);
5532 data_offset
->LastModificationTime
= cpu_to_le64(args
->mtime
);
5533 data_offset
->Uid
= cpu_to_le64(args
->uid
);
5534 data_offset
->Gid
= cpu_to_le64(args
->gid
);
5535 /* better to leave device as zero when it is */
5536 data_offset
->DevMajor
= cpu_to_le64(MAJOR(args
->device
));
5537 data_offset
->DevMinor
= cpu_to_le64(MINOR(args
->device
));
5538 data_offset
->Permissions
= cpu_to_le64(mode
);
5541 data_offset
->Type
= cpu_to_le32(UNIX_FILE
);
5542 else if (S_ISDIR(mode
))
5543 data_offset
->Type
= cpu_to_le32(UNIX_DIR
);
5544 else if (S_ISLNK(mode
))
5545 data_offset
->Type
= cpu_to_le32(UNIX_SYMLINK
);
5546 else if (S_ISCHR(mode
))
5547 data_offset
->Type
= cpu_to_le32(UNIX_CHARDEV
);
5548 else if (S_ISBLK(mode
))
5549 data_offset
->Type
= cpu_to_le32(UNIX_BLOCKDEV
);
5550 else if (S_ISFIFO(mode
))
5551 data_offset
->Type
= cpu_to_le32(UNIX_FIFO
);
5552 else if (S_ISSOCK(mode
))
5553 data_offset
->Type
= cpu_to_le32(UNIX_SOCKET
);
5557 CIFSSMBUnixSetFileInfo(const int xid
, struct cifs_tcon
*tcon
,
5558 const struct cifs_unix_set_info_args
*args
,
5559 u16 fid
, u32 pid_of_opener
)
5561 struct smb_com_transaction2_sfi_req
*pSMB
= NULL
;
5562 FILE_UNIX_BASIC_INFO
*data_offset
;
5564 u16 params
, param_offset
, offset
, byte_count
, count
;
5566 cFYI(1, "Set Unix Info (via SetFileInfo)");
5567 rc
= small_smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
);
5572 pSMB
->hdr
.Pid
= cpu_to_le16((__u16
)pid_of_opener
);
5573 pSMB
->hdr
.PidHigh
= cpu_to_le16((__u16
)(pid_of_opener
>> 16));
5576 pSMB
->MaxSetupCount
= 0;
5580 pSMB
->Reserved2
= 0;
5581 param_offset
= offsetof(struct smb_com_transaction2_sfi_req
, Fid
) - 4;
5582 offset
= param_offset
+ params
;
5584 data_offset
= (FILE_UNIX_BASIC_INFO
*)
5585 ((char *)(&pSMB
->hdr
.Protocol
) + offset
);
5586 count
= sizeof(FILE_UNIX_BASIC_INFO
);
5588 pSMB
->MaxParameterCount
= cpu_to_le16(2);
5589 /* BB find max SMB PDU from sess */
5590 pSMB
->MaxDataCount
= cpu_to_le16(1000);
5591 pSMB
->SetupCount
= 1;
5592 pSMB
->Reserved3
= 0;
5593 pSMB
->SubCommand
= cpu_to_le16(TRANS2_SET_FILE_INFORMATION
);
5594 byte_count
= 3 /* pad */ + params
+ count
;
5595 pSMB
->DataCount
= cpu_to_le16(count
);
5596 pSMB
->ParameterCount
= cpu_to_le16(params
);
5597 pSMB
->TotalDataCount
= pSMB
->DataCount
;
5598 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
5599 pSMB
->ParameterOffset
= cpu_to_le16(param_offset
);
5600 pSMB
->DataOffset
= cpu_to_le16(offset
);
5602 pSMB
->InformationLevel
= cpu_to_le16(SMB_SET_FILE_UNIX_BASIC
);
5603 pSMB
->Reserved4
= 0;
5604 inc_rfc1001_len(pSMB
, byte_count
);
5605 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
5607 cifs_fill_unix_set_info(data_offset
, args
);
5609 rc
= SendReceiveNoRsp(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
, 0);
5611 cFYI(1, "Send error in Set Time (SetFileInfo) = %d", rc
);
5613 /* Note: On -EAGAIN error only caller can retry on handle based calls
5614 since file handle passed in no longer valid */
5620 CIFSSMBUnixSetPathInfo(const int xid
, struct cifs_tcon
*tcon
, char *fileName
,
5621 const struct cifs_unix_set_info_args
*args
,
5622 const struct nls_table
*nls_codepage
, int remap
)
5624 TRANSACTION2_SPI_REQ
*pSMB
= NULL
;
5625 TRANSACTION2_SPI_RSP
*pSMBr
= NULL
;
5628 int bytes_returned
= 0;
5629 FILE_UNIX_BASIC_INFO
*data_offset
;
5630 __u16 params
, param_offset
, offset
, count
, byte_count
;
5632 cFYI(1, "In SetUID/GID/Mode");
5634 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
5639 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
5641 cifsConvertToUCS((__le16
*) pSMB
->FileName
, fileName
,
5642 PATH_MAX
, nls_codepage
, remap
);
5643 name_len
++; /* trailing null */
5645 } else { /* BB improve the check for buffer overruns BB */
5646 name_len
= strnlen(fileName
, PATH_MAX
);
5647 name_len
++; /* trailing null */
5648 strncpy(pSMB
->FileName
, fileName
, name_len
);
5651 params
= 6 + name_len
;
5652 count
= sizeof(FILE_UNIX_BASIC_INFO
);
5653 pSMB
->MaxParameterCount
= cpu_to_le16(2);
5654 /* BB find max SMB PDU from sess structure BB */
5655 pSMB
->MaxDataCount
= cpu_to_le16(1000);
5656 pSMB
->MaxSetupCount
= 0;
5660 pSMB
->Reserved2
= 0;
5661 param_offset
= offsetof(struct smb_com_transaction2_spi_req
,
5662 InformationLevel
) - 4;
5663 offset
= param_offset
+ params
;
5665 (FILE_UNIX_BASIC_INFO
*) ((char *) &pSMB
->hdr
.Protocol
+
5667 memset(data_offset
, 0, count
);
5668 pSMB
->DataOffset
= cpu_to_le16(offset
);
5669 pSMB
->ParameterOffset
= cpu_to_le16(param_offset
);
5670 pSMB
->SetupCount
= 1;
5671 pSMB
->Reserved3
= 0;
5672 pSMB
->SubCommand
= cpu_to_le16(TRANS2_SET_PATH_INFORMATION
);
5673 byte_count
= 3 /* pad */ + params
+ count
;
5674 pSMB
->ParameterCount
= cpu_to_le16(params
);
5675 pSMB
->DataCount
= cpu_to_le16(count
);
5676 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
5677 pSMB
->TotalDataCount
= pSMB
->DataCount
;
5678 pSMB
->InformationLevel
= cpu_to_le16(SMB_SET_FILE_UNIX_BASIC
);
5679 pSMB
->Reserved4
= 0;
5680 inc_rfc1001_len(pSMB
, byte_count
);
5682 cifs_fill_unix_set_info(data_offset
, args
);
5684 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
5685 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
5686 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
5688 cFYI(1, "SetPathInfo (perms) returned %d", rc
);
5690 cifs_buf_release(pSMB
);
5696 #ifdef CONFIG_CIFS_XATTR
5698 * Do a path-based QUERY_ALL_EAS call and parse the result. This is a common
5699 * function used by listxattr and getxattr type calls. When ea_name is set,
5700 * it looks for that attribute name and stuffs that value into the EAData
5701 * buffer. When ea_name is NULL, it stuffs a list of attribute names into the
5702 * buffer. In both cases, the return value is either the length of the
5703 * resulting data or a negative error code. If EAData is a NULL pointer then
5704 * the data isn't copied to it, but the length is returned.
5707 CIFSSMBQAllEAs(const int xid
, struct cifs_tcon
*tcon
,
5708 const unsigned char *searchName
, const unsigned char *ea_name
,
5709 char *EAData
, size_t buf_size
,
5710 const struct nls_table
*nls_codepage
, int remap
)
5712 /* BB assumes one setup word */
5713 TRANSACTION2_QPI_REQ
*pSMB
= NULL
;
5714 TRANSACTION2_QPI_RSP
*pSMBr
= NULL
;
5718 struct fealist
*ea_response_data
;
5719 struct fea
*temp_fea
;
5722 __u16 params
, byte_count
, data_offset
;
5724 cFYI(1, "In Query All EAs path %s", searchName
);
5726 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
5731 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
5733 cifsConvertToUCS((__le16
*) pSMB
->FileName
, searchName
,
5734 PATH_MAX
, nls_codepage
, remap
);
5735 list_len
++; /* trailing null */
5737 } else { /* BB improve the check for buffer overruns BB */
5738 list_len
= strnlen(searchName
, PATH_MAX
);
5739 list_len
++; /* trailing null */
5740 strncpy(pSMB
->FileName
, searchName
, list_len
);
5743 params
= 2 /* level */ + 4 /* reserved */ + list_len
/* includes NUL */;
5744 pSMB
->TotalDataCount
= 0;
5745 pSMB
->MaxParameterCount
= cpu_to_le16(2);
5746 /* BB find exact max SMB PDU from sess structure BB */
5747 pSMB
->MaxDataCount
= cpu_to_le16(CIFSMaxBufSize
);
5748 pSMB
->MaxSetupCount
= 0;
5752 pSMB
->Reserved2
= 0;
5753 pSMB
->ParameterOffset
= cpu_to_le16(offsetof(
5754 struct smb_com_transaction2_qpi_req
, InformationLevel
) - 4);
5755 pSMB
->DataCount
= 0;
5756 pSMB
->DataOffset
= 0;
5757 pSMB
->SetupCount
= 1;
5758 pSMB
->Reserved3
= 0;
5759 pSMB
->SubCommand
= cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION
);
5760 byte_count
= params
+ 1 /* pad */ ;
5761 pSMB
->TotalParameterCount
= cpu_to_le16(params
);
5762 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
5763 pSMB
->InformationLevel
= cpu_to_le16(SMB_INFO_QUERY_ALL_EAS
);
5764 pSMB
->Reserved4
= 0;
5765 inc_rfc1001_len(pSMB
, byte_count
);
5766 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
5768 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
5769 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
5771 cFYI(1, "Send error in QueryAllEAs = %d", rc
);
5776 /* BB also check enough total bytes returned */
5777 /* BB we need to improve the validity checking
5778 of these trans2 responses */
5780 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
5781 if (rc
|| get_bcc(&pSMBr
->hdr
) < 4) {
5782 rc
= -EIO
; /* bad smb */
5786 /* check that length of list is not more than bcc */
5787 /* check that each entry does not go beyond length
5789 /* check that each element of each entry does not
5790 go beyond end of list */
5791 /* validate_trans2_offsets() */
5792 /* BB check if start of smb + data_offset > &bcc+ bcc */
5794 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
5795 ea_response_data
= (struct fealist
*)
5796 (((char *) &pSMBr
->hdr
.Protocol
) + data_offset
);
5798 list_len
= le32_to_cpu(ea_response_data
->list_len
);
5799 cFYI(1, "ea length %d", list_len
);
5800 if (list_len
<= 8) {
5801 cFYI(1, "empty EA list returned from server");
5805 /* make sure list_len doesn't go past end of SMB */
5806 end_of_smb
= (char *)pByteArea(&pSMBr
->hdr
) + get_bcc(&pSMBr
->hdr
);
5807 if ((char *)ea_response_data
+ list_len
> end_of_smb
) {
5808 cFYI(1, "EA list appears to go beyond SMB");
5813 /* account for ea list len */
5815 temp_fea
= ea_response_data
->list
;
5816 temp_ptr
= (char *)temp_fea
;
5817 while (list_len
> 0) {
5818 unsigned int name_len
;
5823 /* make sure we can read name_len and value_len */
5825 cFYI(1, "EA entry goes beyond length of list");
5830 name_len
= temp_fea
->name_len
;
5831 value_len
= le16_to_cpu(temp_fea
->value_len
);
5832 list_len
-= name_len
+ 1 + value_len
;
5834 cFYI(1, "EA entry goes beyond length of list");
5840 if (strncmp(ea_name
, temp_ptr
, name_len
) == 0) {
5841 temp_ptr
+= name_len
+ 1;
5845 if ((size_t)value_len
> buf_size
) {
5849 memcpy(EAData
, temp_ptr
, value_len
);
5853 /* account for prefix user. and trailing null */
5854 rc
+= (5 + 1 + name_len
);
5855 if (rc
< (int) buf_size
) {
5856 memcpy(EAData
, "user.", 5);
5858 memcpy(EAData
, temp_ptr
, name_len
);
5860 /* null terminate name */
5863 } else if (buf_size
== 0) {
5864 /* skip copy - calc size only */
5866 /* stop before overrun buffer */
5871 temp_ptr
+= name_len
+ 1 + value_len
;
5872 temp_fea
= (struct fea
*)temp_ptr
;
5875 /* didn't find the named attribute */
5880 cifs_buf_release(pSMB
);
5888 CIFSSMBSetEA(const int xid
, struct cifs_tcon
*tcon
, const char *fileName
,
5889 const char *ea_name
, const void *ea_value
,
5890 const __u16 ea_value_len
, const struct nls_table
*nls_codepage
,
5893 struct smb_com_transaction2_spi_req
*pSMB
= NULL
;
5894 struct smb_com_transaction2_spi_rsp
*pSMBr
= NULL
;
5895 struct fealist
*parm_data
;
5898 int bytes_returned
= 0;
5899 __u16 params
, param_offset
, byte_count
, offset
, count
;
5901 cFYI(1, "In SetEA");
5903 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
5908 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
5910 cifsConvertToUCS((__le16
*) pSMB
->FileName
, fileName
,
5911 PATH_MAX
, nls_codepage
, remap
);
5912 name_len
++; /* trailing null */
5914 } else { /* BB improve the check for buffer overruns BB */
5915 name_len
= strnlen(fileName
, PATH_MAX
);
5916 name_len
++; /* trailing null */
5917 strncpy(pSMB
->FileName
, fileName
, name_len
);
5920 params
= 6 + name_len
;
5922 /* done calculating parms using name_len of file name,
5923 now use name_len to calculate length of ea name
5924 we are going to create in the inode xattrs */
5925 if (ea_name
== NULL
)
5928 name_len
= strnlen(ea_name
, 255);
5930 count
= sizeof(*parm_data
) + ea_value_len
+ name_len
;
5931 pSMB
->MaxParameterCount
= cpu_to_le16(2);
5932 /* BB find max SMB PDU from sess */
5933 pSMB
->MaxDataCount
= cpu_to_le16(1000);
5934 pSMB
->MaxSetupCount
= 0;
5938 pSMB
->Reserved2
= 0;
5939 param_offset
= offsetof(struct smb_com_transaction2_spi_req
,
5940 InformationLevel
) - 4;
5941 offset
= param_offset
+ params
;
5942 pSMB
->InformationLevel
=
5943 cpu_to_le16(SMB_SET_FILE_EA
);
5946 (struct fealist
*) (((char *) &pSMB
->hdr
.Protocol
) +
5948 pSMB
->ParameterOffset
= cpu_to_le16(param_offset
);
5949 pSMB
->DataOffset
= cpu_to_le16(offset
);
5950 pSMB
->SetupCount
= 1;
5951 pSMB
->Reserved3
= 0;
5952 pSMB
->SubCommand
= cpu_to_le16(TRANS2_SET_PATH_INFORMATION
);
5953 byte_count
= 3 /* pad */ + params
+ count
;
5954 pSMB
->DataCount
= cpu_to_le16(count
);
5955 parm_data
->list_len
= cpu_to_le32(count
);
5956 parm_data
->list
[0].EA_flags
= 0;
5957 /* we checked above that name len is less than 255 */
5958 parm_data
->list
[0].name_len
= (__u8
)name_len
;
5959 /* EA names are always ASCII */
5961 strncpy(parm_data
->list
[0].name
, ea_name
, name_len
);
5962 parm_data
->list
[0].name
[name_len
] = 0;
5963 parm_data
->list
[0].value_len
= cpu_to_le16(ea_value_len
);
5964 /* caller ensures that ea_value_len is less than 64K but
5965 we need to ensure that it fits within the smb */
5967 /*BB add length check to see if it would fit in
5968 negotiated SMB buffer size BB */
5969 /* if (ea_value_len > buffer_size - 512 (enough for header)) */
5971 memcpy(parm_data
->list
[0].name
+name_len
+1,
5972 ea_value
, ea_value_len
);
5974 pSMB
->TotalDataCount
= pSMB
->DataCount
;
5975 pSMB
->ParameterCount
= cpu_to_le16(params
);
5976 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
5977 pSMB
->Reserved4
= 0;
5978 inc_rfc1001_len(pSMB
, byte_count
);
5979 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
5980 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
5981 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
5983 cFYI(1, "SetPathInfo (EA) returned %d", rc
);
5985 cifs_buf_release(pSMB
);
5994 #ifdef CONFIG_CIFS_DNOTIFY_EXPERIMENTAL /* BB unused temporarily */
5996 * Years ago the kernel added a "dnotify" function for Samba server,
5997 * to allow network clients (such as Windows) to display updated
5998 * lists of files in directory listings automatically when
5999 * files are added by one user when another user has the
6000 * same directory open on their desktop. The Linux cifs kernel
6001 * client hooked into the kernel side of this interface for
6002 * the same reason, but ironically when the VFS moved from
6003 * "dnotify" to "inotify" it became harder to plug in Linux
6004 * network file system clients (the most obvious use case
6005 * for notify interfaces is when multiple users can update
6006 * the contents of the same directory - exactly what network
6007 * file systems can do) although the server (Samba) could
6008 * still use it. For the short term we leave the worker
6009 * function ifdeffed out (below) until inotify is fixed
6010 * in the VFS to make it easier to plug in network file
6011 * system clients. If inotify turns out to be permanently
6012 * incompatible for network fs clients, we could instead simply
6013 * expose this config flag by adding a future cifs (and smb2) notify ioctl.
6015 int CIFSSMBNotify(const int xid
, struct cifs_tcon
*tcon
,
6016 const int notify_subdirs
, const __u16 netfid
,
6017 __u32 filter
, struct file
*pfile
, int multishot
,
6018 const struct nls_table
*nls_codepage
)
6021 struct smb_com_transaction_change_notify_req
*pSMB
= NULL
;
6022 struct smb_com_ntransaction_change_notify_rsp
*pSMBr
= NULL
;
6023 struct dir_notify_req
*dnotify_req
;
6026 cFYI(1, "In CIFSSMBNotify for file handle %d", (int)netfid
);
6027 rc
= smb_init(SMB_COM_NT_TRANSACT
, 23, tcon
, (void **) &pSMB
,
6032 pSMB
->TotalParameterCount
= 0 ;
6033 pSMB
->TotalDataCount
= 0;
6034 pSMB
->MaxParameterCount
= cpu_to_le32(2);
6035 /* BB find exact data count max from sess structure BB */
6036 pSMB
->MaxDataCount
= 0; /* same in little endian or be */
6037 /* BB VERIFY verify which is correct for above BB */
6038 pSMB
->MaxDataCount
= cpu_to_le32((tcon
->ses
->server
->maxBuf
-
6039 MAX_CIFS_HDR_SIZE
) & 0xFFFFFF00);
6041 pSMB
->MaxSetupCount
= 4;
6043 pSMB
->ParameterOffset
= 0;
6044 pSMB
->DataCount
= 0;
6045 pSMB
->DataOffset
= 0;
6046 pSMB
->SetupCount
= 4; /* single byte does not need le conversion */
6047 pSMB
->SubCommand
= cpu_to_le16(NT_TRANSACT_NOTIFY_CHANGE
);
6048 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
6050 pSMB
->WatchTree
= 1; /* one byte - no le conversion needed */
6051 pSMB
->Reserved2
= 0;
6052 pSMB
->CompletionFilter
= cpu_to_le32(filter
);
6053 pSMB
->Fid
= netfid
; /* file handle always le */
6054 pSMB
->ByteCount
= 0;
6056 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
6057 (struct smb_hdr
*)pSMBr
, &bytes_returned
,
6060 cFYI(1, "Error in Notify = %d", rc
);
6062 /* Add file to outstanding requests */
6063 /* BB change to kmem cache alloc */
6064 dnotify_req
= kmalloc(
6065 sizeof(struct dir_notify_req
),
6068 dnotify_req
->Pid
= pSMB
->hdr
.Pid
;
6069 dnotify_req
->PidHigh
= pSMB
->hdr
.PidHigh
;
6070 dnotify_req
->Mid
= pSMB
->hdr
.Mid
;
6071 dnotify_req
->Tid
= pSMB
->hdr
.Tid
;
6072 dnotify_req
->Uid
= pSMB
->hdr
.Uid
;
6073 dnotify_req
->netfid
= netfid
;
6074 dnotify_req
->pfile
= pfile
;
6075 dnotify_req
->filter
= filter
;
6076 dnotify_req
->multishot
= multishot
;
6077 spin_lock(&GlobalMid_Lock
);
6078 list_add_tail(&dnotify_req
->lhead
,
6079 &GlobalDnotifyReqList
);
6080 spin_unlock(&GlobalMid_Lock
);
6084 cifs_buf_release(pSMB
);
6087 #endif /* was needed for dnotify, and will be needed for inotify when VFS fix */