4 * Copyright (C) International Business Machines Corp., 2002,2008
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/posix_acl_xattr.h>
34 #include <asm/uaccess.h>
38 #include "cifsproto.h"
39 #include "cifs_unicode.h"
40 #include "cifs_debug.h"
42 #ifdef CONFIG_CIFS_POSIX
47 #ifdef CONFIG_CIFS_WEAK_PW_HASH
48 {LANMAN_PROT
, "\2LM1.2X002"},
49 {LANMAN2_PROT
, "\2LANMAN2.1"},
50 #endif /* weak password hashing for legacy clients */
51 {CIFS_PROT
, "\2NT LM 0.12"},
52 {POSIX_PROT
, "\2POSIX 2"},
60 #ifdef CONFIG_CIFS_WEAK_PW_HASH
61 {LANMAN_PROT
, "\2LM1.2X002"},
62 {LANMAN2_PROT
, "\2LANMAN2.1"},
63 #endif /* weak password hashing for legacy clients */
64 {CIFS_PROT
, "\2NT LM 0.12"},
69 /* define the number of elements in the cifs dialect array */
70 #ifdef CONFIG_CIFS_POSIX
71 #ifdef CONFIG_CIFS_WEAK_PW_HASH
72 #define CIFS_NUM_PROT 4
74 #define CIFS_NUM_PROT 2
75 #endif /* CIFS_WEAK_PW_HASH */
77 #ifdef CONFIG_CIFS_WEAK_PW_HASH
78 #define CIFS_NUM_PROT 3
80 #define CIFS_NUM_PROT 1
81 #endif /* CONFIG_CIFS_WEAK_PW_HASH */
82 #endif /* CIFS_POSIX */
85 /* Mark as invalid, all open files on tree connections since they
86 were closed when session to server was lost */
87 static void mark_open_files_invalid(struct cifsTconInfo
*pTcon
)
89 struct cifsFileInfo
*open_file
= NULL
;
90 struct list_head
*tmp
;
91 struct list_head
*tmp1
;
93 /* list all files open on tree connection and mark them invalid */
94 write_lock(&GlobalSMBSeslock
);
95 list_for_each_safe(tmp
, tmp1
, &pTcon
->openFileList
) {
96 open_file
= list_entry(tmp
, struct cifsFileInfo
, tlist
);
98 open_file
->invalidHandle
= TRUE
;
100 write_unlock(&GlobalSMBSeslock
);
101 /* BB Add call to invalidate_inodes(sb) for all superblocks mounted
105 /* Allocate and return pointer to an SMB request buffer, and set basic
106 SMB information in the SMB header. If the return code is zero, this
107 function must have filled in request_buf pointer */
109 small_smb_init(int smb_command
, int wct
, struct cifsTconInfo
*tcon
,
114 /* SMBs NegProt, SessSetup, uLogoff do not have tcon yet so
115 check for tcp and smb session status done differently
116 for those three - in the calling routine */
118 if (tcon
->tidStatus
== CifsExiting
) {
119 /* only tree disconnect, open, and write,
120 (and ulogoff which does not have tcon)
121 are allowed as we start force umount */
122 if ((smb_command
!= SMB_COM_WRITE_ANDX
) &&
123 (smb_command
!= SMB_COM_OPEN_ANDX
) &&
124 (smb_command
!= SMB_COM_TREE_DISCONNECT
)) {
125 cFYI(1, ("can not send cmd %d while umounting",
130 if ((tcon
->ses
) && (tcon
->ses
->status
!= CifsExiting
) &&
131 (tcon
->ses
->server
)) {
132 struct nls_table
*nls_codepage
;
133 /* Give Demultiplex thread up to 10 seconds to
134 reconnect, should be greater than cifs socket
135 timeout which is 7 seconds */
136 while (tcon
->ses
->server
->tcpStatus
==
138 wait_event_interruptible_timeout(tcon
->ses
->server
->response_q
,
139 (tcon
->ses
->server
->tcpStatus
==
141 if (tcon
->ses
->server
->tcpStatus
==
143 /* on "soft" mounts we wait once */
144 if ((tcon
->retry
== FALSE
) ||
145 (tcon
->ses
->status
== CifsExiting
)) {
146 cFYI(1, ("gave up waiting on "
147 "reconnect in smb_init"));
149 } /* else "hard" mount - keep retrying
150 until process is killed or server
151 comes back on-line */
152 } else /* TCP session is reestablished now */
156 nls_codepage
= load_nls_default();
157 /* need to prevent multiple threads trying to
158 simultaneously reconnect the same SMB session */
159 down(&tcon
->ses
->sesSem
);
160 if (tcon
->ses
->status
== CifsNeedReconnect
)
161 rc
= cifs_setup_session(0, tcon
->ses
,
163 if (!rc
&& (tcon
->tidStatus
== CifsNeedReconnect
)) {
164 mark_open_files_invalid(tcon
);
165 rc
= CIFSTCon(0, tcon
->ses
, tcon
->treeName
,
167 up(&tcon
->ses
->sesSem
);
168 /* tell server which Unix caps we support */
169 if (tcon
->ses
->capabilities
& CAP_UNIX
)
170 reset_cifs_unix_caps(0 /* no xid */,
172 NULL
/* we do not know sb */,
173 NULL
/* no vol info */);
174 /* BB FIXME add code to check if wsize needs
175 update due to negotiated smb buffer size
178 atomic_inc(&tconInfoReconnectCount
);
180 cFYI(1, ("reconnect tcon rc = %d", rc
));
181 /* Removed call to reopen open files here.
182 It is safer (and faster) to reopen files
183 one at a time as needed in read and write */
185 /* Check if handle based operation so we
186 know whether we can continue or not without
187 returning to caller to reset file handle */
188 switch (smb_command
) {
189 case SMB_COM_READ_ANDX
:
190 case SMB_COM_WRITE_ANDX
:
192 case SMB_COM_FIND_CLOSE2
:
193 case SMB_COM_LOCKING_ANDX
: {
194 unload_nls(nls_codepage
);
199 up(&tcon
->ses
->sesSem
);
201 unload_nls(nls_codepage
);
210 *request_buf
= cifs_small_buf_get();
211 if (*request_buf
== NULL
) {
212 /* BB should we add a retry in here if not a writepage? */
216 header_assemble((struct smb_hdr
*) *request_buf
, smb_command
,
220 cifs_stats_inc(&tcon
->num_smbs_sent
);
226 small_smb_init_no_tc(const int smb_command
, const int wct
,
227 struct cifsSesInfo
*ses
, void **request_buf
)
230 struct smb_hdr
*buffer
;
232 rc
= small_smb_init(smb_command
, wct
, NULL
, request_buf
);
236 buffer
= (struct smb_hdr
*)*request_buf
;
237 buffer
->Mid
= GetNextMid(ses
->server
);
238 if (ses
->capabilities
& CAP_UNICODE
)
239 buffer
->Flags2
|= SMBFLG2_UNICODE
;
240 if (ses
->capabilities
& CAP_STATUS32
)
241 buffer
->Flags2
|= SMBFLG2_ERR_STATUS
;
243 /* uid, tid can stay at zero as set in header assemble */
245 /* BB add support for turning on the signing when
246 this function is used after 1st of session setup requests */
251 /* If the return code is zero, this function must fill in request_buf pointer */
253 smb_init(int smb_command
, int wct
, struct cifsTconInfo
*tcon
,
254 void **request_buf
/* returned */ ,
255 void **response_buf
/* returned */ )
259 /* SMBs NegProt, SessSetup, uLogoff do not have tcon yet so
260 check for tcp and smb session status done differently
261 for those three - in the calling routine */
263 if (tcon
->tidStatus
== CifsExiting
) {
264 /* only tree disconnect, open, and write,
265 (and ulogoff which does not have tcon)
266 are allowed as we start force umount */
267 if ((smb_command
!= SMB_COM_WRITE_ANDX
) &&
268 (smb_command
!= SMB_COM_OPEN_ANDX
) &&
269 (smb_command
!= SMB_COM_TREE_DISCONNECT
)) {
270 cFYI(1, ("can not send cmd %d while umounting",
276 if ((tcon
->ses
) && (tcon
->ses
->status
!= CifsExiting
) &&
277 (tcon
->ses
->server
)) {
278 struct nls_table
*nls_codepage
;
279 /* Give Demultiplex thread up to 10 seconds to
280 reconnect, should be greater than cifs socket
281 timeout which is 7 seconds */
282 while (tcon
->ses
->server
->tcpStatus
==
284 wait_event_interruptible_timeout(tcon
->ses
->server
->response_q
,
285 (tcon
->ses
->server
->tcpStatus
==
287 if (tcon
->ses
->server
->tcpStatus
==
289 /* on "soft" mounts we wait once */
290 if ((tcon
->retry
== FALSE
) ||
291 (tcon
->ses
->status
== CifsExiting
)) {
292 cFYI(1, ("gave up waiting on "
293 "reconnect in smb_init"));
295 } /* else "hard" mount - keep retrying
296 until process is killed or server
298 } else /* TCP session is reestablished now */
301 nls_codepage
= load_nls_default();
302 /* need to prevent multiple threads trying to
303 simultaneously reconnect the same SMB session */
304 down(&tcon
->ses
->sesSem
);
305 if (tcon
->ses
->status
== CifsNeedReconnect
)
306 rc
= cifs_setup_session(0, tcon
->ses
,
308 if (!rc
&& (tcon
->tidStatus
== CifsNeedReconnect
)) {
309 mark_open_files_invalid(tcon
);
310 rc
= CIFSTCon(0, tcon
->ses
, tcon
->treeName
,
312 up(&tcon
->ses
->sesSem
);
313 /* tell server which Unix caps we support */
314 if (tcon
->ses
->capabilities
& CAP_UNIX
)
315 reset_cifs_unix_caps(0 /* no xid */,
317 NULL
/* do not know sb */,
318 NULL
/* no vol info */);
319 /* BB FIXME add code to check if wsize needs
320 update due to negotiated smb buffer size
323 atomic_inc(&tconInfoReconnectCount
);
325 cFYI(1, ("reconnect tcon rc = %d", rc
));
326 /* Removed call to reopen open files here.
327 It is safer (and faster) to reopen files
328 one at a time as needed in read and write */
330 /* Check if handle based operation so we
331 know whether we can continue or not without
332 returning to caller to reset file handle */
333 switch (smb_command
) {
334 case SMB_COM_READ_ANDX
:
335 case SMB_COM_WRITE_ANDX
:
337 case SMB_COM_FIND_CLOSE2
:
338 case SMB_COM_LOCKING_ANDX
: {
339 unload_nls(nls_codepage
);
344 up(&tcon
->ses
->sesSem
);
346 unload_nls(nls_codepage
);
355 *request_buf
= cifs_buf_get();
356 if (*request_buf
== NULL
) {
357 /* BB should we add a retry in here if not a writepage? */
360 /* Although the original thought was we needed the response buf for */
361 /* potential retries of smb operations it turns out we can determine */
362 /* from the mid flags when the request buffer can be resent without */
363 /* having to use a second distinct buffer for the response */
365 *response_buf
= *request_buf
;
367 header_assemble((struct smb_hdr
*) *request_buf
, smb_command
, tcon
,
371 cifs_stats_inc(&tcon
->num_smbs_sent
);
376 static int validate_t2(struct smb_t2_rsp
*pSMB
)
382 /* check for plausible wct, bcc and t2 data and parm sizes */
383 /* check for parm and data offset going beyond end of smb */
384 if (pSMB
->hdr
.WordCount
>= 10) {
385 if ((le16_to_cpu(pSMB
->t2_rsp
.ParameterOffset
) <= 1024) &&
386 (le16_to_cpu(pSMB
->t2_rsp
.DataOffset
) <= 1024)) {
387 /* check that bcc is at least as big as parms + data */
388 /* check that bcc is less than negotiated smb buffer */
389 total_size
= le16_to_cpu(pSMB
->t2_rsp
.ParameterCount
);
390 if (total_size
< 512) {
392 le16_to_cpu(pSMB
->t2_rsp
.DataCount
);
393 /* BCC le converted in SendReceive */
394 pBCC
= (pSMB
->hdr
.WordCount
* 2) +
395 sizeof(struct smb_hdr
) +
397 if ((total_size
<= (*(u16
*)pBCC
)) &&
399 CIFSMaxBufSize
+MAX_CIFS_HDR_SIZE
)) {
405 cifs_dump_mem("Invalid transact2 SMB: ", (char *)pSMB
,
406 sizeof(struct smb_t2_rsp
) + 16);
410 CIFSSMBNegotiate(unsigned int xid
, struct cifsSesInfo
*ses
)
413 NEGOTIATE_RSP
*pSMBr
;
417 struct TCP_Server_Info
*server
;
419 unsigned int secFlags
;
423 server
= ses
->server
;
428 rc
= smb_init(SMB_COM_NEGOTIATE
, 0, NULL
/* no tcon yet */ ,
429 (void **) &pSMB
, (void **) &pSMBr
);
433 /* if any of auth flags (ie not sign or seal) are overriden use them */
434 if (ses
->overrideSecFlg
& (~(CIFSSEC_MUST_SIGN
| CIFSSEC_MUST_SEAL
)))
435 secFlags
= ses
->overrideSecFlg
; /* BB FIXME fix sign flags? */
436 else /* if override flags set only sign/seal OR them with global auth */
437 secFlags
= extended_security
| ses
->overrideSecFlg
;
439 cFYI(1, ("secFlags 0x%x", secFlags
));
441 pSMB
->hdr
.Mid
= GetNextMid(server
);
442 pSMB
->hdr
.Flags2
|= (SMBFLG2_UNICODE
| SMBFLG2_ERR_STATUS
);
444 if ((secFlags
& CIFSSEC_MUST_KRB5
) == CIFSSEC_MUST_KRB5
)
445 pSMB
->hdr
.Flags2
|= SMBFLG2_EXT_SEC
;
446 else if ((secFlags
& CIFSSEC_AUTH_MASK
) == CIFSSEC_MAY_KRB5
) {
447 cFYI(1, ("Kerberos only mechanism, enable extended security"));
448 pSMB
->hdr
.Flags2
|= SMBFLG2_EXT_SEC
;
452 for (i
= 0; i
< CIFS_NUM_PROT
; i
++) {
453 strncpy(pSMB
->DialectsArray
+count
, protocols
[i
].name
, 16);
454 count
+= strlen(protocols
[i
].name
) + 1;
455 /* null at end of source and target buffers anyway */
457 pSMB
->hdr
.smb_buf_length
+= count
;
458 pSMB
->ByteCount
= cpu_to_le16(count
);
460 rc
= SendReceive(xid
, ses
, (struct smb_hdr
*) pSMB
,
461 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
465 dialect
= le16_to_cpu(pSMBr
->DialectIndex
);
466 cFYI(1, ("Dialect: %d", dialect
));
467 /* Check wct = 1 error case */
468 if ((pSMBr
->hdr
.WordCount
< 13) || (dialect
== BAD_PROT
)) {
469 /* core returns wct = 1, but we do not ask for core - otherwise
470 small wct just comes when dialect index is -1 indicating we
471 could not negotiate a common dialect */
474 #ifdef CONFIG_CIFS_WEAK_PW_HASH
475 } else if ((pSMBr
->hdr
.WordCount
== 13)
476 && ((dialect
== LANMAN_PROT
)
477 || (dialect
== LANMAN2_PROT
))) {
479 struct lanman_neg_rsp
*rsp
= (struct lanman_neg_rsp
*)pSMBr
;
481 if ((secFlags
& CIFSSEC_MAY_LANMAN
) ||
482 (secFlags
& CIFSSEC_MAY_PLNTXT
))
483 server
->secType
= LANMAN
;
485 cERROR(1, ("mount failed weak security disabled"
486 " in /proc/fs/cifs/SecurityFlags"));
490 server
->secMode
= (__u8
)le16_to_cpu(rsp
->SecurityMode
);
491 server
->maxReq
= le16_to_cpu(rsp
->MaxMpxCount
);
492 server
->maxBuf
= min((__u32
)le16_to_cpu(rsp
->MaxBufSize
),
493 (__u32
)CIFSMaxBufSize
+ MAX_CIFS_HDR_SIZE
);
494 GETU32(server
->sessid
) = le32_to_cpu(rsp
->SessionKey
);
495 /* even though we do not use raw we might as well set this
496 accurately, in case we ever find a need for it */
497 if ((le16_to_cpu(rsp
->RawMode
) & RAW_ENABLE
) == RAW_ENABLE
) {
498 server
->maxRw
= 0xFF00;
499 server
->capabilities
= CAP_MPX_MODE
| CAP_RAW_MODE
;
501 server
->maxRw
= 0;/* we do not need to use raw anyway */
502 server
->capabilities
= CAP_MPX_MODE
;
504 tmp
= (__s16
)le16_to_cpu(rsp
->ServerTimeZone
);
506 /* OS/2 often does not set timezone therefore
507 * we must use server time to calc time zone.
508 * Could deviate slightly from the right zone.
509 * Smallest defined timezone difference is 15 minutes
510 * (i.e. Nepal). Rounding up/down is done to match
513 int val
, seconds
, remain
, result
;
514 struct timespec ts
, utc
;
516 ts
= cnvrtDosUnixTm(le16_to_cpu(rsp
->SrvTime
.Date
),
517 le16_to_cpu(rsp
->SrvTime
.Time
));
518 cFYI(1, ("SrvTime %d sec since 1970 (utc: %d) diff: %d",
519 (int)ts
.tv_sec
, (int)utc
.tv_sec
,
520 (int)(utc
.tv_sec
- ts
.tv_sec
)));
521 val
= (int)(utc
.tv_sec
- ts
.tv_sec
);
523 result
= (seconds
/ MIN_TZ_ADJ
) * MIN_TZ_ADJ
;
524 remain
= seconds
% MIN_TZ_ADJ
;
525 if (remain
>= (MIN_TZ_ADJ
/ 2))
526 result
+= MIN_TZ_ADJ
;
529 server
->timeAdj
= result
;
531 server
->timeAdj
= (int)tmp
;
532 server
->timeAdj
*= 60; /* also in seconds */
534 cFYI(1, ("server->timeAdj: %d seconds", server
->timeAdj
));
537 /* BB get server time for time conversions and add
538 code to use it and timezone since this is not UTC */
540 if (rsp
->EncryptionKeyLength
==
541 cpu_to_le16(CIFS_CRYPTO_KEY_SIZE
)) {
542 memcpy(server
->cryptKey
, rsp
->EncryptionKey
,
543 CIFS_CRYPTO_KEY_SIZE
);
544 } else if (server
->secMode
& SECMODE_PW_ENCRYPT
) {
545 rc
= -EIO
; /* need cryptkey unless plain text */
549 cFYI(1, ("LANMAN negotiated"));
550 /* we will not end up setting signing flags - as no signing
551 was in LANMAN and server did not return the flags on */
553 #else /* weak security disabled */
554 } else if (pSMBr
->hdr
.WordCount
== 13) {
555 cERROR(1, ("mount failed, cifs module not built "
556 "with CIFS_WEAK_PW_HASH support"));
558 #endif /* WEAK_PW_HASH */
560 } else if (pSMBr
->hdr
.WordCount
!= 17) {
565 /* else wct == 17 NTLM */
566 server
->secMode
= pSMBr
->SecurityMode
;
567 if ((server
->secMode
& SECMODE_USER
) == 0)
568 cFYI(1, ("share mode security"));
570 if ((server
->secMode
& SECMODE_PW_ENCRYPT
) == 0)
571 #ifdef CONFIG_CIFS_WEAK_PW_HASH
572 if ((secFlags
& CIFSSEC_MAY_PLNTXT
) == 0)
573 #endif /* CIFS_WEAK_PW_HASH */
574 cERROR(1, ("Server requests plain text password"
575 " but client support disabled"));
577 if ((secFlags
& CIFSSEC_MUST_NTLMV2
) == CIFSSEC_MUST_NTLMV2
)
578 server
->secType
= NTLMv2
;
579 else if (secFlags
& CIFSSEC_MAY_NTLM
)
580 server
->secType
= NTLM
;
581 else if (secFlags
& CIFSSEC_MAY_NTLMV2
)
582 server
->secType
= NTLMv2
;
583 else if (secFlags
& CIFSSEC_MAY_KRB5
)
584 server
->secType
= Kerberos
;
585 else if (secFlags
& CIFSSEC_MAY_LANMAN
)
586 server
->secType
= LANMAN
;
587 /* #ifdef CONFIG_CIFS_EXPERIMENTAL
588 else if (secFlags & CIFSSEC_MAY_PLNTXT)
593 cERROR(1, ("Invalid security type"));
596 /* else ... any others ...? */
598 /* one byte, so no need to convert this or EncryptionKeyLen from
600 server
->maxReq
= le16_to_cpu(pSMBr
->MaxMpxCount
);
601 /* probably no need to store and check maxvcs */
602 server
->maxBuf
= min(le32_to_cpu(pSMBr
->MaxBufferSize
),
603 (__u32
) CIFSMaxBufSize
+ MAX_CIFS_HDR_SIZE
);
604 server
->maxRw
= le32_to_cpu(pSMBr
->MaxRawSize
);
605 cFYI(DBG2
, ("Max buf = %d", ses
->server
->maxBuf
));
606 GETU32(ses
->server
->sessid
) = le32_to_cpu(pSMBr
->SessionKey
);
607 server
->capabilities
= le32_to_cpu(pSMBr
->Capabilities
);
608 server
->timeAdj
= (int)(__s16
)le16_to_cpu(pSMBr
->ServerTimeZone
);
609 server
->timeAdj
*= 60;
610 if (pSMBr
->EncryptionKeyLength
== CIFS_CRYPTO_KEY_SIZE
) {
611 memcpy(server
->cryptKey
, pSMBr
->u
.EncryptionKey
,
612 CIFS_CRYPTO_KEY_SIZE
);
613 } else if ((pSMBr
->hdr
.Flags2
& SMBFLG2_EXT_SEC
)
614 && (pSMBr
->EncryptionKeyLength
== 0)) {
615 /* decode security blob */
616 } else if (server
->secMode
& SECMODE_PW_ENCRYPT
) {
617 rc
= -EIO
; /* no crypt key only if plain text pwd */
621 /* BB might be helpful to save off the domain of server here */
623 if ((pSMBr
->hdr
.Flags2
& SMBFLG2_EXT_SEC
) &&
624 (server
->capabilities
& CAP_EXTENDED_SECURITY
)) {
625 count
= pSMBr
->ByteCount
;
631 if (server
->socketUseCount
.counter
> 1) {
632 if (memcmp(server
->server_GUID
,
633 pSMBr
->u
.extended_response
.
635 cFYI(1, ("server UID changed"));
636 memcpy(server
->server_GUID
,
637 pSMBr
->u
.extended_response
.GUID
,
641 memcpy(server
->server_GUID
,
642 pSMBr
->u
.extended_response
.GUID
, 16);
645 server
->secType
= RawNTLMSSP
;
647 rc
= decode_negTokenInit(pSMBr
->u
.extended_response
.
658 server
->capabilities
&= ~CAP_EXTENDED_SECURITY
;
660 #ifdef CONFIG_CIFS_WEAK_PW_HASH
663 if ((secFlags
& CIFSSEC_MAY_SIGN
) == 0) {
664 /* MUST_SIGN already includes the MAY_SIGN FLAG
665 so if this is zero it means that signing is disabled */
666 cFYI(1, ("Signing disabled"));
667 if (server
->secMode
& SECMODE_SIGN_REQUIRED
) {
668 cERROR(1, ("Server requires "
669 "packet signing to be enabled in "
670 "/proc/fs/cifs/SecurityFlags."));
674 ~(SECMODE_SIGN_ENABLED
| SECMODE_SIGN_REQUIRED
);
675 } else if ((secFlags
& CIFSSEC_MUST_SIGN
) == CIFSSEC_MUST_SIGN
) {
676 /* signing required */
677 cFYI(1, ("Must sign - secFlags 0x%x", secFlags
));
678 if ((server
->secMode
&
679 (SECMODE_SIGN_ENABLED
| SECMODE_SIGN_REQUIRED
)) == 0) {
681 ("signing required but server lacks support"));
684 server
->secMode
|= SECMODE_SIGN_REQUIRED
;
686 /* signing optional ie CIFSSEC_MAY_SIGN */
687 if ((server
->secMode
& SECMODE_SIGN_REQUIRED
) == 0)
689 ~(SECMODE_SIGN_ENABLED
| SECMODE_SIGN_REQUIRED
);
693 cifs_buf_release(pSMB
);
695 cFYI(1, ("negprot rc %d", rc
));
700 CIFSSMBTDis(const int xid
, struct cifsTconInfo
*tcon
)
702 struct smb_hdr
*smb_buffer
;
705 cFYI(1, ("In tree disconnect"));
707 * If last user of the connection and
708 * connection alive - disconnect it
709 * If this is the last connection on the server session disconnect it
710 * (and inside session disconnect we should check if tcp socket needs
711 * to be freed and kernel thread woken up).
714 down(&tcon
->tconSem
);
718 atomic_dec(&tcon
->useCount
);
719 if (atomic_read(&tcon
->useCount
) > 0) {
724 /* No need to return error on this operation if tid invalidated and
725 closed on server already e.g. due to tcp session crashing */
726 if (tcon
->tidStatus
== CifsNeedReconnect
) {
731 if ((tcon
->ses
== NULL
) || (tcon
->ses
->server
== NULL
)) {
735 rc
= small_smb_init(SMB_COM_TREE_DISCONNECT
, 0, tcon
,
736 (void **)&smb_buffer
);
742 rc
= SendReceiveNoRsp(xid
, tcon
->ses
, smb_buffer
, 0);
744 cFYI(1, ("Tree disconnect failed %d", rc
));
748 /* No need to return error on this operation if tid invalidated and
749 closed on server already e.g. due to tcp session crashing */
757 CIFSSMBLogoff(const int xid
, struct cifsSesInfo
*ses
)
759 LOGOFF_ANDX_REQ
*pSMB
;
762 cFYI(1, ("In SMBLogoff for session disconnect"));
768 atomic_dec(&ses
->inUse
);
769 if (atomic_read(&ses
->inUse
) > 0) {
773 rc
= small_smb_init(SMB_COM_LOGOFF_ANDX
, 2, NULL
, (void **)&pSMB
);
780 pSMB
->hdr
.Mid
= GetNextMid(ses
->server
);
782 if (ses
->server
->secMode
&
783 (SECMODE_SIGN_REQUIRED
| SECMODE_SIGN_ENABLED
))
784 pSMB
->hdr
.Flags2
|= SMBFLG2_SECURITY_SIGNATURE
;
787 pSMB
->hdr
.Uid
= ses
->Suid
;
789 pSMB
->AndXCommand
= 0xFF;
790 rc
= SendReceiveNoRsp(xid
, ses
, (struct smb_hdr
*) pSMB
, 0);
792 atomic_dec(&ses
->server
->socketUseCount
);
793 if (atomic_read(&ses
->server
->socketUseCount
) == 0) {
794 spin_lock(&GlobalMid_Lock
);
795 ses
->server
->tcpStatus
= CifsExiting
;
796 spin_unlock(&GlobalMid_Lock
);
802 /* if session dead then we do not need to do ulogoff,
803 since server closed smb session, no sense reporting
811 CIFSPOSIXDelFile(const int xid
, struct cifsTconInfo
*tcon
, const char *fileName
,
812 __u16 type
, const struct nls_table
*nls_codepage
, int remap
)
814 TRANSACTION2_SPI_REQ
*pSMB
= NULL
;
815 TRANSACTION2_SPI_RSP
*pSMBr
= NULL
;
816 struct unlink_psx_rq
*pRqD
;
819 int bytes_returned
= 0;
820 __u16 params
, param_offset
, offset
, byte_count
;
822 cFYI(1, ("In POSIX delete"));
824 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
829 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
831 cifsConvertToUCS((__le16
*) pSMB
->FileName
, fileName
,
832 PATH_MAX
, nls_codepage
, remap
);
833 name_len
++; /* trailing null */
835 } else { /* BB add path length overrun check */
836 name_len
= strnlen(fileName
, PATH_MAX
);
837 name_len
++; /* trailing null */
838 strncpy(pSMB
->FileName
, fileName
, name_len
);
841 params
= 6 + name_len
;
842 pSMB
->MaxParameterCount
= cpu_to_le16(2);
843 pSMB
->MaxDataCount
= 0; /* BB double check this with jra */
844 pSMB
->MaxSetupCount
= 0;
849 param_offset
= offsetof(struct smb_com_transaction2_spi_req
,
850 InformationLevel
) - 4;
851 offset
= param_offset
+ params
;
853 /* Setup pointer to Request Data (inode type) */
854 pRqD
= (struct unlink_psx_rq
*)(((char *)&pSMB
->hdr
.Protocol
) + offset
);
855 pRqD
->type
= cpu_to_le16(type
);
856 pSMB
->ParameterOffset
= cpu_to_le16(param_offset
);
857 pSMB
->DataOffset
= cpu_to_le16(offset
);
858 pSMB
->SetupCount
= 1;
860 pSMB
->SubCommand
= cpu_to_le16(TRANS2_SET_PATH_INFORMATION
);
861 byte_count
= 3 /* pad */ + params
+ sizeof(struct unlink_psx_rq
);
863 pSMB
->DataCount
= cpu_to_le16(sizeof(struct unlink_psx_rq
));
864 pSMB
->TotalDataCount
= cpu_to_le16(sizeof(struct unlink_psx_rq
));
865 pSMB
->ParameterCount
= cpu_to_le16(params
);
866 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
867 pSMB
->InformationLevel
= cpu_to_le16(SMB_POSIX_UNLINK
);
869 pSMB
->hdr
.smb_buf_length
+= byte_count
;
870 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
871 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
872 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
874 cFYI(1, ("Posix delete returned %d", rc
));
875 cifs_buf_release(pSMB
);
877 cifs_stats_inc(&tcon
->num_deletes
);
886 CIFSSMBDelFile(const int xid
, struct cifsTconInfo
*tcon
, const char *fileName
,
887 const struct nls_table
*nls_codepage
, int remap
)
889 DELETE_FILE_REQ
*pSMB
= NULL
;
890 DELETE_FILE_RSP
*pSMBr
= NULL
;
896 rc
= smb_init(SMB_COM_DELETE
, 1, tcon
, (void **) &pSMB
,
901 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
903 cifsConvertToUCS((__le16
*) pSMB
->fileName
, fileName
,
904 PATH_MAX
, nls_codepage
, remap
);
905 name_len
++; /* trailing null */
907 } else { /* BB improve check for buffer overruns BB */
908 name_len
= strnlen(fileName
, PATH_MAX
);
909 name_len
++; /* trailing null */
910 strncpy(pSMB
->fileName
, fileName
, name_len
);
912 pSMB
->SearchAttributes
=
913 cpu_to_le16(ATTR_READONLY
| ATTR_HIDDEN
| ATTR_SYSTEM
);
914 pSMB
->BufferFormat
= 0x04;
915 pSMB
->hdr
.smb_buf_length
+= name_len
+ 1;
916 pSMB
->ByteCount
= cpu_to_le16(name_len
+ 1);
917 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
918 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
919 cifs_stats_inc(&tcon
->num_deletes
);
921 cFYI(1, ("Error in RMFile = %d", rc
));
923 cifs_buf_release(pSMB
);
931 CIFSSMBRmDir(const int xid
, struct cifsTconInfo
*tcon
, const char *dirName
,
932 const struct nls_table
*nls_codepage
, int remap
)
934 DELETE_DIRECTORY_REQ
*pSMB
= NULL
;
935 DELETE_DIRECTORY_RSP
*pSMBr
= NULL
;
940 cFYI(1, ("In CIFSSMBRmDir"));
942 rc
= smb_init(SMB_COM_DELETE_DIRECTORY
, 0, tcon
, (void **) &pSMB
,
947 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
948 name_len
= cifsConvertToUCS((__le16
*) pSMB
->DirName
, dirName
,
949 PATH_MAX
, nls_codepage
, remap
);
950 name_len
++; /* trailing null */
952 } else { /* BB improve check for buffer overruns BB */
953 name_len
= strnlen(dirName
, PATH_MAX
);
954 name_len
++; /* trailing null */
955 strncpy(pSMB
->DirName
, dirName
, name_len
);
958 pSMB
->BufferFormat
= 0x04;
959 pSMB
->hdr
.smb_buf_length
+= name_len
+ 1;
960 pSMB
->ByteCount
= cpu_to_le16(name_len
+ 1);
961 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
962 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
963 cifs_stats_inc(&tcon
->num_rmdirs
);
965 cFYI(1, ("Error in RMDir = %d", rc
));
967 cifs_buf_release(pSMB
);
974 CIFSSMBMkDir(const int xid
, struct cifsTconInfo
*tcon
,
975 const char *name
, const struct nls_table
*nls_codepage
, int remap
)
978 CREATE_DIRECTORY_REQ
*pSMB
= NULL
;
979 CREATE_DIRECTORY_RSP
*pSMBr
= NULL
;
983 cFYI(1, ("In CIFSSMBMkDir"));
985 rc
= smb_init(SMB_COM_CREATE_DIRECTORY
, 0, tcon
, (void **) &pSMB
,
990 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
991 name_len
= cifsConvertToUCS((__le16
*) pSMB
->DirName
, name
,
992 PATH_MAX
, nls_codepage
, remap
);
993 name_len
++; /* trailing null */
995 } else { /* BB improve check for buffer overruns BB */
996 name_len
= strnlen(name
, PATH_MAX
);
997 name_len
++; /* trailing null */
998 strncpy(pSMB
->DirName
, name
, name_len
);
1001 pSMB
->BufferFormat
= 0x04;
1002 pSMB
->hdr
.smb_buf_length
+= name_len
+ 1;
1003 pSMB
->ByteCount
= cpu_to_le16(name_len
+ 1);
1004 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
1005 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
1006 cifs_stats_inc(&tcon
->num_mkdirs
);
1008 cFYI(1, ("Error in Mkdir = %d", rc
));
1010 cifs_buf_release(pSMB
);
1017 CIFSPOSIXCreate(const int xid
, struct cifsTconInfo
*tcon
, __u32 posix_flags
,
1018 __u64 mode
, __u16
*netfid
, FILE_UNIX_BASIC_INFO
*pRetData
,
1019 __u32
*pOplock
, const char *name
,
1020 const struct nls_table
*nls_codepage
, int remap
)
1022 TRANSACTION2_SPI_REQ
*pSMB
= NULL
;
1023 TRANSACTION2_SPI_RSP
*pSMBr
= NULL
;
1026 int bytes_returned
= 0;
1027 __u16 params
, param_offset
, offset
, byte_count
, count
;
1028 OPEN_PSX_REQ
*pdata
;
1029 OPEN_PSX_RSP
*psx_rsp
;
1031 cFYI(1, ("In POSIX Create"));
1033 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
1038 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
1040 cifsConvertToUCS((__le16
*) pSMB
->FileName
, name
,
1041 PATH_MAX
, nls_codepage
, remap
);
1042 name_len
++; /* trailing null */
1044 } else { /* BB improve the check for buffer overruns BB */
1045 name_len
= strnlen(name
, PATH_MAX
);
1046 name_len
++; /* trailing null */
1047 strncpy(pSMB
->FileName
, name
, name_len
);
1050 params
= 6 + name_len
;
1051 count
= sizeof(OPEN_PSX_REQ
);
1052 pSMB
->MaxParameterCount
= cpu_to_le16(2);
1053 pSMB
->MaxDataCount
= cpu_to_le16(1000); /* large enough */
1054 pSMB
->MaxSetupCount
= 0;
1058 pSMB
->Reserved2
= 0;
1059 param_offset
= offsetof(struct smb_com_transaction2_spi_req
,
1060 InformationLevel
) - 4;
1061 offset
= param_offset
+ params
;
1062 pdata
= (OPEN_PSX_REQ
*)(((char *)&pSMB
->hdr
.Protocol
) + offset
);
1063 pdata
->Level
= cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC
);
1064 pdata
->Permissions
= cpu_to_le64(mode
);
1065 pdata
->PosixOpenFlags
= cpu_to_le32(posix_flags
);
1066 pdata
->OpenFlags
= cpu_to_le32(*pOplock
);
1067 pSMB
->ParameterOffset
= cpu_to_le16(param_offset
);
1068 pSMB
->DataOffset
= cpu_to_le16(offset
);
1069 pSMB
->SetupCount
= 1;
1070 pSMB
->Reserved3
= 0;
1071 pSMB
->SubCommand
= cpu_to_le16(TRANS2_SET_PATH_INFORMATION
);
1072 byte_count
= 3 /* pad */ + params
+ count
;
1074 pSMB
->DataCount
= cpu_to_le16(count
);
1075 pSMB
->ParameterCount
= cpu_to_le16(params
);
1076 pSMB
->TotalDataCount
= pSMB
->DataCount
;
1077 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
1078 pSMB
->InformationLevel
= cpu_to_le16(SMB_POSIX_OPEN
);
1079 pSMB
->Reserved4
= 0;
1080 pSMB
->hdr
.smb_buf_length
+= byte_count
;
1081 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
1082 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
1083 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
1085 cFYI(1, ("Posix create returned %d", rc
));
1086 goto psx_create_err
;
1089 cFYI(1, ("copying inode info"));
1090 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
1092 if (rc
|| (pSMBr
->ByteCount
< sizeof(OPEN_PSX_RSP
))) {
1093 rc
= -EIO
; /* bad smb */
1094 goto psx_create_err
;
1097 /* copy return information to pRetData */
1098 psx_rsp
= (OPEN_PSX_RSP
*)((char *) &pSMBr
->hdr
.Protocol
1099 + le16_to_cpu(pSMBr
->t2
.DataOffset
));
1101 *pOplock
= le16_to_cpu(psx_rsp
->OplockFlags
);
1103 *netfid
= psx_rsp
->Fid
; /* cifs fid stays in le */
1104 /* Let caller know file was created so we can set the mode. */
1105 /* Do we care about the CreateAction in any other cases? */
1106 if (cpu_to_le32(FILE_CREATE
) == psx_rsp
->CreateAction
)
1107 *pOplock
|= CIFS_CREATE_ACTION
;
1108 /* check to make sure response data is there */
1109 if (psx_rsp
->ReturnedLevel
!= cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC
)) {
1110 pRetData
->Type
= cpu_to_le32(-1); /* unknown */
1111 cFYI(DBG2
, ("unknown type"));
1113 if (pSMBr
->ByteCount
< sizeof(OPEN_PSX_RSP
)
1114 + sizeof(FILE_UNIX_BASIC_INFO
)) {
1115 cERROR(1, ("Open response data too small"));
1116 pRetData
->Type
= cpu_to_le32(-1);
1117 goto psx_create_err
;
1119 memcpy((char *) pRetData
,
1120 (char *)psx_rsp
+ sizeof(OPEN_PSX_RSP
),
1121 sizeof(FILE_UNIX_BASIC_INFO
));
1125 cifs_buf_release(pSMB
);
1127 cifs_stats_inc(&tcon
->num_mkdirs
);
1135 static __u16
convert_disposition(int disposition
)
1139 switch (disposition
) {
1140 case FILE_SUPERSEDE
:
1141 ofun
= SMBOPEN_OCREATE
| SMBOPEN_OTRUNC
;
1144 ofun
= SMBOPEN_OAPPEND
;
1147 ofun
= SMBOPEN_OCREATE
;
1150 ofun
= SMBOPEN_OCREATE
| SMBOPEN_OAPPEND
;
1152 case FILE_OVERWRITE
:
1153 ofun
= SMBOPEN_OTRUNC
;
1155 case FILE_OVERWRITE_IF
:
1156 ofun
= SMBOPEN_OCREATE
| SMBOPEN_OTRUNC
;
1159 cFYI(1, ("unknown disposition %d", disposition
));
1160 ofun
= SMBOPEN_OAPPEND
; /* regular open */
1166 SMBLegacyOpen(const int xid
, struct cifsTconInfo
*tcon
,
1167 const char *fileName
, const int openDisposition
,
1168 const int access_flags
, const int create_options
, __u16
*netfid
,
1169 int *pOplock
, FILE_ALL_INFO
*pfile_info
,
1170 const struct nls_table
*nls_codepage
, int remap
)
1173 OPENX_REQ
*pSMB
= NULL
;
1174 OPENX_RSP
*pSMBr
= NULL
;
1180 rc
= smb_init(SMB_COM_OPEN_ANDX
, 15, tcon
, (void **) &pSMB
,
1185 pSMB
->AndXCommand
= 0xFF; /* none */
1187 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
1188 count
= 1; /* account for one byte pad to word boundary */
1190 cifsConvertToUCS((__le16
*) (pSMB
->fileName
+ 1),
1191 fileName
, PATH_MAX
, nls_codepage
, remap
);
1192 name_len
++; /* trailing null */
1194 } else { /* BB improve check for buffer overruns BB */
1195 count
= 0; /* no pad */
1196 name_len
= strnlen(fileName
, PATH_MAX
);
1197 name_len
++; /* trailing null */
1198 strncpy(pSMB
->fileName
, fileName
, name_len
);
1200 if (*pOplock
& REQ_OPLOCK
)
1201 pSMB
->OpenFlags
= cpu_to_le16(REQ_OPLOCK
);
1202 else if (*pOplock
& REQ_BATCHOPLOCK
)
1203 pSMB
->OpenFlags
= cpu_to_le16(REQ_BATCHOPLOCK
);
1205 pSMB
->OpenFlags
|= cpu_to_le16(REQ_MORE_INFO
);
1206 /* BB fixme add conversion for access_flags to bits 0 - 2 of mode */
1212 pSMB
->Mode
= cpu_to_le16(2);
1213 pSMB
->Mode
|= cpu_to_le16(0x40); /* deny none */
1214 /* set file as system file if special file such
1215 as fifo and server expecting SFU style and
1216 no Unix extensions */
1218 if (create_options
& CREATE_OPTION_SPECIAL
)
1219 pSMB
->FileAttributes
= cpu_to_le16(ATTR_SYSTEM
);
1220 else /* BB FIXME BB */
1221 pSMB
->FileAttributes
= cpu_to_le16(0/*ATTR_NORMAL*/);
1223 /* if ((omode & S_IWUGO) == 0)
1224 pSMB->FileAttributes |= cpu_to_le32(ATTR_READONLY);*/
1225 /* Above line causes problems due to vfs splitting create into two
1226 pieces - need to set mode after file created not while it is
1230 /* pSMB->CreateOptions = cpu_to_le32(create_options &
1231 CREATE_OPTIONS_MASK); */
1232 /* BB FIXME END BB */
1234 pSMB
->Sattr
= cpu_to_le16(ATTR_HIDDEN
| ATTR_SYSTEM
| ATTR_DIRECTORY
);
1235 pSMB
->OpenFunction
= cpu_to_le16(convert_disposition(openDisposition
));
1237 pSMB
->hdr
.smb_buf_length
+= count
;
1239 pSMB
->ByteCount
= cpu_to_le16(count
);
1240 /* long_op set to 1 to allow for oplock break timeouts */
1241 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
1242 (struct smb_hdr
*)pSMBr
, &bytes_returned
, CIFS_LONG_OP
);
1243 cifs_stats_inc(&tcon
->num_opens
);
1245 cFYI(1, ("Error in Open = %d", rc
));
1247 /* BB verify if wct == 15 */
1249 /* *pOplock = pSMBr->OplockLevel; */ /* BB take from action field BB */
1251 *netfid
= pSMBr
->Fid
; /* cifs fid stays in le */
1252 /* Let caller know file was created so we can set the mode. */
1253 /* Do we care about the CreateAction in any other cases? */
1255 /* if (cpu_to_le32(FILE_CREATE) == pSMBr->CreateAction)
1256 *pOplock |= CIFS_CREATE_ACTION; */
1260 pfile_info
->CreationTime
= 0; /* BB convert CreateTime*/
1261 pfile_info
->LastAccessTime
= 0; /* BB fixme */
1262 pfile_info
->LastWriteTime
= 0; /* BB fixme */
1263 pfile_info
->ChangeTime
= 0; /* BB fixme */
1264 pfile_info
->Attributes
=
1265 cpu_to_le32(le16_to_cpu(pSMBr
->FileAttributes
));
1266 /* the file_info buf is endian converted by caller */
1267 pfile_info
->AllocationSize
=
1268 cpu_to_le64(le32_to_cpu(pSMBr
->EndOfFile
));
1269 pfile_info
->EndOfFile
= pfile_info
->AllocationSize
;
1270 pfile_info
->NumberOfLinks
= cpu_to_le32(1);
1274 cifs_buf_release(pSMB
);
1281 CIFSSMBOpen(const int xid
, struct cifsTconInfo
*tcon
,
1282 const char *fileName
, const int openDisposition
,
1283 const int access_flags
, const int create_options
, __u16
*netfid
,
1284 int *pOplock
, FILE_ALL_INFO
*pfile_info
,
1285 const struct nls_table
*nls_codepage
, int remap
)
1288 OPEN_REQ
*pSMB
= NULL
;
1289 OPEN_RSP
*pSMBr
= NULL
;
1295 rc
= smb_init(SMB_COM_NT_CREATE_ANDX
, 24, tcon
, (void **) &pSMB
,
1300 pSMB
->AndXCommand
= 0xFF; /* none */
1302 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
1303 count
= 1; /* account for one byte pad to word boundary */
1305 cifsConvertToUCS((__le16
*) (pSMB
->fileName
+ 1),
1306 fileName
, PATH_MAX
, nls_codepage
, remap
);
1307 name_len
++; /* trailing null */
1309 pSMB
->NameLength
= cpu_to_le16(name_len
);
1310 } else { /* BB improve check for buffer overruns BB */
1311 count
= 0; /* no pad */
1312 name_len
= strnlen(fileName
, PATH_MAX
);
1313 name_len
++; /* trailing null */
1314 pSMB
->NameLength
= cpu_to_le16(name_len
);
1315 strncpy(pSMB
->fileName
, fileName
, name_len
);
1317 if (*pOplock
& REQ_OPLOCK
)
1318 pSMB
->OpenFlags
= cpu_to_le32(REQ_OPLOCK
);
1319 else if (*pOplock
& REQ_BATCHOPLOCK
)
1320 pSMB
->OpenFlags
= cpu_to_le32(REQ_BATCHOPLOCK
);
1321 pSMB
->DesiredAccess
= cpu_to_le32(access_flags
);
1322 pSMB
->AllocationSize
= 0;
1323 /* set file as system file if special file such
1324 as fifo and server expecting SFU style and
1325 no Unix extensions */
1326 if (create_options
& CREATE_OPTION_SPECIAL
)
1327 pSMB
->FileAttributes
= cpu_to_le32(ATTR_SYSTEM
);
1329 pSMB
->FileAttributes
= cpu_to_le32(ATTR_NORMAL
);
1330 /* XP does not handle ATTR_POSIX_SEMANTICS */
1331 /* but it helps speed up case sensitive checks for other
1332 servers such as Samba */
1333 if (tcon
->ses
->capabilities
& CAP_UNIX
)
1334 pSMB
->FileAttributes
|= cpu_to_le32(ATTR_POSIX_SEMANTICS
);
1336 /* if ((omode & S_IWUGO) == 0)
1337 pSMB->FileAttributes |= cpu_to_le32(ATTR_READONLY);*/
1338 /* Above line causes problems due to vfs splitting create into two
1339 pieces - need to set mode after file created not while it is
1341 pSMB
->ShareAccess
= cpu_to_le32(FILE_SHARE_ALL
);
1342 pSMB
->CreateDisposition
= cpu_to_le32(openDisposition
);
1343 pSMB
->CreateOptions
= cpu_to_le32(create_options
& CREATE_OPTIONS_MASK
);
1344 /* BB Expirement with various impersonation levels and verify */
1345 pSMB
->ImpersonationLevel
= cpu_to_le32(SECURITY_IMPERSONATION
);
1346 pSMB
->SecurityFlags
=
1347 SECURITY_CONTEXT_TRACKING
| SECURITY_EFFECTIVE_ONLY
;
1350 pSMB
->hdr
.smb_buf_length
+= count
;
1352 pSMB
->ByteCount
= cpu_to_le16(count
);
1353 /* long_op set to 1 to allow for oplock break timeouts */
1354 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
1355 (struct smb_hdr
*)pSMBr
, &bytes_returned
, CIFS_LONG_OP
);
1356 cifs_stats_inc(&tcon
->num_opens
);
1358 cFYI(1, ("Error in Open = %d", rc
));
1360 *pOplock
= pSMBr
->OplockLevel
; /* 1 byte no need to le_to_cpu */
1361 *netfid
= pSMBr
->Fid
; /* cifs fid stays in le */
1362 /* Let caller know file was created so we can set the mode. */
1363 /* Do we care about the CreateAction in any other cases? */
1364 if (cpu_to_le32(FILE_CREATE
) == pSMBr
->CreateAction
)
1365 *pOplock
|= CIFS_CREATE_ACTION
;
1367 memcpy((char *)pfile_info
, (char *)&pSMBr
->CreationTime
,
1368 36 /* CreationTime to Attributes */);
1369 /* the file_info buf is endian converted by caller */
1370 pfile_info
->AllocationSize
= pSMBr
->AllocationSize
;
1371 pfile_info
->EndOfFile
= pSMBr
->EndOfFile
;
1372 pfile_info
->NumberOfLinks
= cpu_to_le32(1);
1376 cifs_buf_release(pSMB
);
1383 CIFSSMBRead(const int xid
, struct cifsTconInfo
*tcon
, const int netfid
,
1384 const unsigned int count
, const __u64 lseek
, unsigned int *nbytes
,
1385 char **buf
, int *pbuf_type
)
1388 READ_REQ
*pSMB
= NULL
;
1389 READ_RSP
*pSMBr
= NULL
;
1390 char *pReadData
= NULL
;
1392 int resp_buf_type
= 0;
1395 cFYI(1, ("Reading %d bytes on fid %d", count
, netfid
));
1396 if (tcon
->ses
->capabilities
& CAP_LARGE_FILES
)
1399 wct
= 10; /* old style read */
1402 rc
= small_smb_init(SMB_COM_READ_ANDX
, wct
, tcon
, (void **) &pSMB
);
1406 /* tcon and ses pointer are checked in smb_init */
1407 if (tcon
->ses
->server
== NULL
)
1408 return -ECONNABORTED
;
1410 pSMB
->AndXCommand
= 0xFF; /* none */
1412 pSMB
->OffsetLow
= cpu_to_le32(lseek
& 0xFFFFFFFF);
1414 pSMB
->OffsetHigh
= cpu_to_le32(lseek
>> 32);
1415 else if ((lseek
>> 32) > 0) /* can not handle this big offset for old */
1418 pSMB
->Remaining
= 0;
1419 pSMB
->MaxCount
= cpu_to_le16(count
& 0xFFFF);
1420 pSMB
->MaxCountHigh
= cpu_to_le32(count
>> 16);
1422 pSMB
->ByteCount
= 0; /* no need to do le conversion since 0 */
1424 /* old style read */
1425 struct smb_com_readx_req
*pSMBW
=
1426 (struct smb_com_readx_req
*)pSMB
;
1427 pSMBW
->ByteCount
= 0;
1430 iov
[0].iov_base
= (char *)pSMB
;
1431 iov
[0].iov_len
= pSMB
->hdr
.smb_buf_length
+ 4;
1432 rc
= SendReceive2(xid
, tcon
->ses
, iov
, 1 /* num iovecs */,
1433 &resp_buf_type
, CIFS_STD_OP
| CIFS_LOG_ERROR
);
1434 cifs_stats_inc(&tcon
->num_reads
);
1435 pSMBr
= (READ_RSP
*)iov
[0].iov_base
;
1437 cERROR(1, ("Send error in read = %d", rc
));
1439 int data_length
= le16_to_cpu(pSMBr
->DataLengthHigh
);
1440 data_length
= data_length
<< 16;
1441 data_length
+= le16_to_cpu(pSMBr
->DataLength
);
1442 *nbytes
= data_length
;
1444 /*check that DataLength would not go beyond end of SMB */
1445 if ((data_length
> CIFSMaxBufSize
)
1446 || (data_length
> count
)) {
1447 cFYI(1, ("bad length %d for count %d",
1448 data_length
, count
));
1452 pReadData
= (char *) (&pSMBr
->hdr
.Protocol
) +
1453 le16_to_cpu(pSMBr
->DataOffset
);
1454 /* if (rc = copy_to_user(buf, pReadData, data_length)) {
1455 cERROR(1,("Faulting on read rc = %d",rc));
1457 }*/ /* can not use copy_to_user when using page cache*/
1459 memcpy(*buf
, pReadData
, data_length
);
1463 /* cifs_small_buf_release(pSMB); */ /* Freed earlier now in SendReceive2 */
1465 if (resp_buf_type
== CIFS_SMALL_BUFFER
)
1466 cifs_small_buf_release(iov
[0].iov_base
);
1467 else if (resp_buf_type
== CIFS_LARGE_BUFFER
)
1468 cifs_buf_release(iov
[0].iov_base
);
1469 } else if (resp_buf_type
!= CIFS_NO_BUFFER
) {
1470 /* return buffer to caller to free */
1471 *buf
= iov
[0].iov_base
;
1472 if (resp_buf_type
== CIFS_SMALL_BUFFER
)
1473 *pbuf_type
= CIFS_SMALL_BUFFER
;
1474 else if (resp_buf_type
== CIFS_LARGE_BUFFER
)
1475 *pbuf_type
= CIFS_LARGE_BUFFER
;
1476 } /* else no valid buffer on return - leave as null */
1478 /* Note: On -EAGAIN error only caller can retry on handle based calls
1479 since file handle passed in no longer valid */
1485 CIFSSMBWrite(const int xid
, struct cifsTconInfo
*tcon
,
1486 const int netfid
, const unsigned int count
,
1487 const __u64 offset
, unsigned int *nbytes
, const char *buf
,
1488 const char __user
*ubuf
, const int long_op
)
1491 WRITE_REQ
*pSMB
= NULL
;
1492 WRITE_RSP
*pSMBr
= NULL
;
1493 int bytes_returned
, wct
;
1497 /* cFYI(1,("write at %lld %d bytes",offset,count));*/
1498 if (tcon
->ses
== NULL
)
1499 return -ECONNABORTED
;
1501 if (tcon
->ses
->capabilities
& CAP_LARGE_FILES
)
1506 rc
= smb_init(SMB_COM_WRITE_ANDX
, wct
, tcon
, (void **) &pSMB
,
1510 /* tcon and ses pointer are checked in smb_init */
1511 if (tcon
->ses
->server
== NULL
)
1512 return -ECONNABORTED
;
1514 pSMB
->AndXCommand
= 0xFF; /* none */
1516 pSMB
->OffsetLow
= cpu_to_le32(offset
& 0xFFFFFFFF);
1518 pSMB
->OffsetHigh
= cpu_to_le32(offset
>> 32);
1519 else if ((offset
>> 32) > 0) /* can not handle big offset for old srv */
1522 pSMB
->Reserved
= 0xFFFFFFFF;
1523 pSMB
->WriteMode
= 0;
1524 pSMB
->Remaining
= 0;
1526 /* Can increase buffer size if buffer is big enough in some cases ie we
1527 can send more if LARGE_WRITE_X capability returned by the server and if
1528 our buffer is big enough or if we convert to iovecs on socket writes
1529 and eliminate the copy to the CIFS buffer */
1530 if (tcon
->ses
->capabilities
& CAP_LARGE_WRITE_X
) {
1531 bytes_sent
= min_t(const unsigned int, CIFSMaxBufSize
, count
);
1533 bytes_sent
= (tcon
->ses
->server
->maxBuf
- MAX_CIFS_HDR_SIZE
)
1537 if (bytes_sent
> count
)
1540 cpu_to_le16(offsetof(struct smb_com_write_req
, Data
) - 4);
1542 memcpy(pSMB
->Data
, buf
, bytes_sent
);
1544 if (copy_from_user(pSMB
->Data
, ubuf
, bytes_sent
)) {
1545 cifs_buf_release(pSMB
);
1548 } else if (count
!= 0) {
1550 cifs_buf_release(pSMB
);
1552 } /* else setting file size with write of zero bytes */
1554 byte_count
= bytes_sent
+ 1; /* pad */
1555 else /* wct == 12 */
1556 byte_count
= bytes_sent
+ 5; /* bigger pad, smaller smb hdr */
1558 pSMB
->DataLengthLow
= cpu_to_le16(bytes_sent
& 0xFFFF);
1559 pSMB
->DataLengthHigh
= cpu_to_le16(bytes_sent
>> 16);
1560 pSMB
->hdr
.smb_buf_length
+= byte_count
;
1563 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
1564 else { /* old style write has byte count 4 bytes earlier
1566 struct smb_com_writex_req
*pSMBW
=
1567 (struct smb_com_writex_req
*)pSMB
;
1568 pSMBW
->ByteCount
= cpu_to_le16(byte_count
);
1571 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
1572 (struct smb_hdr
*) pSMBr
, &bytes_returned
, long_op
);
1573 cifs_stats_inc(&tcon
->num_writes
);
1575 cFYI(1, ("Send error in write = %d", rc
));
1578 *nbytes
= le16_to_cpu(pSMBr
->CountHigh
);
1579 *nbytes
= (*nbytes
) << 16;
1580 *nbytes
+= le16_to_cpu(pSMBr
->Count
);
1583 cifs_buf_release(pSMB
);
1585 /* Note: On -EAGAIN error only caller can retry on handle based calls
1586 since file handle passed in no longer valid */
1592 CIFSSMBWrite2(const int xid
, struct cifsTconInfo
*tcon
,
1593 const int netfid
, const unsigned int count
,
1594 const __u64 offset
, unsigned int *nbytes
, struct kvec
*iov
,
1595 int n_vec
, const int long_op
)
1598 WRITE_REQ
*pSMB
= NULL
;
1601 int resp_buf_type
= 0;
1603 cFYI(1, ("write2 at %lld %d bytes", (long long)offset
, count
));
1605 if (tcon
->ses
->capabilities
& CAP_LARGE_FILES
)
1609 rc
= small_smb_init(SMB_COM_WRITE_ANDX
, wct
, tcon
, (void **) &pSMB
);
1612 /* tcon and ses pointer are checked in smb_init */
1613 if (tcon
->ses
->server
== NULL
)
1614 return -ECONNABORTED
;
1616 pSMB
->AndXCommand
= 0xFF; /* none */
1618 pSMB
->OffsetLow
= cpu_to_le32(offset
& 0xFFFFFFFF);
1620 pSMB
->OffsetHigh
= cpu_to_le32(offset
>> 32);
1621 else if ((offset
>> 32) > 0) /* can not handle big offset for old srv */
1623 pSMB
->Reserved
= 0xFFFFFFFF;
1624 pSMB
->WriteMode
= 0;
1625 pSMB
->Remaining
= 0;
1628 cpu_to_le16(offsetof(struct smb_com_write_req
, Data
) - 4);
1630 pSMB
->DataLengthLow
= cpu_to_le16(count
& 0xFFFF);
1631 pSMB
->DataLengthHigh
= cpu_to_le16(count
>> 16);
1632 smb_hdr_len
= pSMB
->hdr
.smb_buf_length
+ 1; /* hdr + 1 byte pad */
1634 pSMB
->hdr
.smb_buf_length
+= count
+1;
1635 else /* wct == 12 */
1636 pSMB
->hdr
.smb_buf_length
+= count
+5; /* smb data starts later */
1638 pSMB
->ByteCount
= cpu_to_le16(count
+ 1);
1639 else /* wct == 12 */ /* bigger pad, smaller smb hdr, keep offset ok */ {
1640 struct smb_com_writex_req
*pSMBW
=
1641 (struct smb_com_writex_req
*)pSMB
;
1642 pSMBW
->ByteCount
= cpu_to_le16(count
+ 5);
1644 iov
[0].iov_base
= pSMB
;
1646 iov
[0].iov_len
= smb_hdr_len
+ 4;
1647 else /* wct == 12 pad bigger by four bytes */
1648 iov
[0].iov_len
= smb_hdr_len
+ 8;
1651 rc
= SendReceive2(xid
, tcon
->ses
, iov
, n_vec
+ 1, &resp_buf_type
,
1653 cifs_stats_inc(&tcon
->num_writes
);
1655 cFYI(1, ("Send error Write2 = %d", rc
));
1657 } else if (resp_buf_type
== 0) {
1658 /* presumably this can not happen, but best to be safe */
1662 WRITE_RSP
*pSMBr
= (WRITE_RSP
*)iov
[0].iov_base
;
1663 *nbytes
= le16_to_cpu(pSMBr
->CountHigh
);
1664 *nbytes
= (*nbytes
) << 16;
1665 *nbytes
+= le16_to_cpu(pSMBr
->Count
);
1668 /* cifs_small_buf_release(pSMB); */ /* Freed earlier now in SendReceive2 */
1669 if (resp_buf_type
== CIFS_SMALL_BUFFER
)
1670 cifs_small_buf_release(iov
[0].iov_base
);
1671 else if (resp_buf_type
== CIFS_LARGE_BUFFER
)
1672 cifs_buf_release(iov
[0].iov_base
);
1674 /* Note: On -EAGAIN error only caller can retry on handle based calls
1675 since file handle passed in no longer valid */
1682 CIFSSMBLock(const int xid
, struct cifsTconInfo
*tcon
,
1683 const __u16 smb_file_id
, const __u64 len
,
1684 const __u64 offset
, const __u32 numUnlock
,
1685 const __u32 numLock
, const __u8 lockType
, const int waitFlag
)
1688 LOCK_REQ
*pSMB
= NULL
;
1689 LOCK_RSP
*pSMBr
= NULL
;
1694 cFYI(1, ("CIFSSMBLock timeout %d numLock %d", waitFlag
, numLock
));
1695 rc
= small_smb_init(SMB_COM_LOCKING_ANDX
, 8, tcon
, (void **) &pSMB
);
1700 pSMBr
= (LOCK_RSP
*)pSMB
; /* BB removeme BB */
1702 if (lockType
== LOCKING_ANDX_OPLOCK_RELEASE
) {
1703 timeout
= CIFS_ASYNC_OP
; /* no response expected */
1705 } else if (waitFlag
== TRUE
) {
1706 timeout
= CIFS_BLOCKING_OP
; /* blocking operation, no timeout */
1707 pSMB
->Timeout
= cpu_to_le32(-1);/* blocking - do not time out */
1712 pSMB
->NumberOfLocks
= cpu_to_le16(numLock
);
1713 pSMB
->NumberOfUnlocks
= cpu_to_le16(numUnlock
);
1714 pSMB
->LockType
= lockType
;
1715 pSMB
->AndXCommand
= 0xFF; /* none */
1716 pSMB
->Fid
= smb_file_id
; /* netfid stays le */
1718 if ((numLock
!= 0) || (numUnlock
!= 0)) {
1719 pSMB
->Locks
[0].Pid
= cpu_to_le16(current
->tgid
);
1720 /* BB where to store pid high? */
1721 pSMB
->Locks
[0].LengthLow
= cpu_to_le32((u32
)len
);
1722 pSMB
->Locks
[0].LengthHigh
= cpu_to_le32((u32
)(len
>>32));
1723 pSMB
->Locks
[0].OffsetLow
= cpu_to_le32((u32
)offset
);
1724 pSMB
->Locks
[0].OffsetHigh
= cpu_to_le32((u32
)(offset
>>32));
1725 count
= sizeof(LOCKING_ANDX_RANGE
);
1730 pSMB
->hdr
.smb_buf_length
+= count
;
1731 pSMB
->ByteCount
= cpu_to_le16(count
);
1734 rc
= SendReceiveBlockingLock(xid
, tcon
, (struct smb_hdr
*) pSMB
,
1735 (struct smb_hdr
*) pSMBr
, &bytes_returned
);
1736 cifs_small_buf_release(pSMB
);
1738 rc
= SendReceiveNoRsp(xid
, tcon
->ses
, (struct smb_hdr
*)pSMB
,
1740 /* SMB buffer freed by function above */
1742 cifs_stats_inc(&tcon
->num_locks
);
1744 cFYI(1, ("Send error in Lock = %d", rc
));
1746 /* Note: On -EAGAIN error only caller can retry on handle based calls
1747 since file handle passed in no longer valid */
1752 CIFSSMBPosixLock(const int xid
, struct cifsTconInfo
*tcon
,
1753 const __u16 smb_file_id
, const int get_flag
, const __u64 len
,
1754 struct file_lock
*pLockData
, const __u16 lock_type
,
1757 struct smb_com_transaction2_sfi_req
*pSMB
= NULL
;
1758 struct smb_com_transaction2_sfi_rsp
*pSMBr
= NULL
;
1759 struct cifs_posix_lock
*parm_data
;
1762 int bytes_returned
= 0;
1763 int resp_buf_type
= 0;
1764 __u16 params
, param_offset
, offset
, byte_count
, count
;
1767 cFYI(1, ("Posix Lock"));
1769 if (pLockData
== NULL
)
1772 rc
= small_smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
);
1777 pSMBr
= (struct smb_com_transaction2_sfi_rsp
*)pSMB
;
1780 pSMB
->MaxSetupCount
= 0;
1783 pSMB
->Reserved2
= 0;
1784 param_offset
= offsetof(struct smb_com_transaction2_sfi_req
, Fid
) - 4;
1785 offset
= param_offset
+ params
;
1787 count
= sizeof(struct cifs_posix_lock
);
1788 pSMB
->MaxParameterCount
= cpu_to_le16(2);
1789 pSMB
->MaxDataCount
= cpu_to_le16(1000); /* BB find max SMB from sess */
1790 pSMB
->SetupCount
= 1;
1791 pSMB
->Reserved3
= 0;
1793 pSMB
->SubCommand
= cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION
);
1795 pSMB
->SubCommand
= cpu_to_le16(TRANS2_SET_FILE_INFORMATION
);
1796 byte_count
= 3 /* pad */ + params
+ count
;
1797 pSMB
->DataCount
= cpu_to_le16(count
);
1798 pSMB
->ParameterCount
= cpu_to_le16(params
);
1799 pSMB
->TotalDataCount
= pSMB
->DataCount
;
1800 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
1801 pSMB
->ParameterOffset
= cpu_to_le16(param_offset
);
1802 parm_data
= (struct cifs_posix_lock
*)
1803 (((char *) &pSMB
->hdr
.Protocol
) + offset
);
1805 parm_data
->lock_type
= cpu_to_le16(lock_type
);
1807 timeout
= CIFS_BLOCKING_OP
; /* blocking operation, no timeout */
1808 parm_data
->lock_flags
= cpu_to_le16(1);
1809 pSMB
->Timeout
= cpu_to_le32(-1);
1813 parm_data
->pid
= cpu_to_le32(current
->tgid
);
1814 parm_data
->start
= cpu_to_le64(pLockData
->fl_start
);
1815 parm_data
->length
= cpu_to_le64(len
); /* normalize negative numbers */
1817 pSMB
->DataOffset
= cpu_to_le16(offset
);
1818 pSMB
->Fid
= smb_file_id
;
1819 pSMB
->InformationLevel
= cpu_to_le16(SMB_SET_POSIX_LOCK
);
1820 pSMB
->Reserved4
= 0;
1821 pSMB
->hdr
.smb_buf_length
+= byte_count
;
1822 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
1824 rc
= SendReceiveBlockingLock(xid
, tcon
, (struct smb_hdr
*) pSMB
,
1825 (struct smb_hdr
*) pSMBr
, &bytes_returned
);
1827 iov
[0].iov_base
= (char *)pSMB
;
1828 iov
[0].iov_len
= pSMB
->hdr
.smb_buf_length
+ 4;
1829 rc
= SendReceive2(xid
, tcon
->ses
, iov
, 1 /* num iovecs */,
1830 &resp_buf_type
, timeout
);
1831 pSMB
= NULL
; /* request buf already freed by SendReceive2. Do
1832 not try to free it twice below on exit */
1833 pSMBr
= (struct smb_com_transaction2_sfi_rsp
*)iov
[0].iov_base
;
1837 cFYI(1, ("Send error in Posix Lock = %d", rc
));
1838 } else if (get_flag
) {
1839 /* lock structure can be returned on get */
1842 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
1844 if (rc
|| (pSMBr
->ByteCount
< sizeof(struct cifs_posix_lock
))) {
1845 rc
= -EIO
; /* bad smb */
1848 if (pLockData
== NULL
) {
1852 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
1853 data_count
= le16_to_cpu(pSMBr
->t2
.DataCount
);
1854 if (data_count
< sizeof(struct cifs_posix_lock
)) {
1858 parm_data
= (struct cifs_posix_lock
*)
1859 ((char *)&pSMBr
->hdr
.Protocol
+ data_offset
);
1860 if (parm_data
->lock_type
== cpu_to_le16(CIFS_UNLCK
))
1861 pLockData
->fl_type
= F_UNLCK
;
1866 cifs_small_buf_release(pSMB
);
1868 if (resp_buf_type
== CIFS_SMALL_BUFFER
)
1869 cifs_small_buf_release(iov
[0].iov_base
);
1870 else if (resp_buf_type
== CIFS_LARGE_BUFFER
)
1871 cifs_buf_release(iov
[0].iov_base
);
1873 /* Note: On -EAGAIN error only caller can retry on handle based calls
1874 since file handle passed in no longer valid */
1881 CIFSSMBClose(const int xid
, struct cifsTconInfo
*tcon
, int smb_file_id
)
1884 CLOSE_REQ
*pSMB
= NULL
;
1885 cFYI(1, ("In CIFSSMBClose"));
1887 /* do not retry on dead session on close */
1888 rc
= small_smb_init(SMB_COM_CLOSE
, 3, tcon
, (void **) &pSMB
);
1894 pSMB
->FileID
= (__u16
) smb_file_id
;
1895 pSMB
->LastWriteTime
= 0xFFFFFFFF;
1896 pSMB
->ByteCount
= 0;
1897 rc
= SendReceiveNoRsp(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
, 0);
1898 cifs_stats_inc(&tcon
->num_closes
);
1901 /* EINTR is expected when user ctl-c to kill app */
1902 cERROR(1, ("Send error in Close = %d", rc
));
1906 /* Since session is dead, file will be closed on server already */
1914 CIFSSMBRename(const int xid
, struct cifsTconInfo
*tcon
,
1915 const char *fromName
, const char *toName
,
1916 const struct nls_table
*nls_codepage
, int remap
)
1919 RENAME_REQ
*pSMB
= NULL
;
1920 RENAME_RSP
*pSMBr
= NULL
;
1922 int name_len
, name_len2
;
1925 cFYI(1, ("In CIFSSMBRename"));
1927 rc
= smb_init(SMB_COM_RENAME
, 1, tcon
, (void **) &pSMB
,
1932 pSMB
->BufferFormat
= 0x04;
1933 pSMB
->SearchAttributes
=
1934 cpu_to_le16(ATTR_READONLY
| ATTR_HIDDEN
| ATTR_SYSTEM
|
1937 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
1939 cifsConvertToUCS((__le16
*) pSMB
->OldFileName
, fromName
,
1940 PATH_MAX
, nls_codepage
, remap
);
1941 name_len
++; /* trailing null */
1943 pSMB
->OldFileName
[name_len
] = 0x04; /* pad */
1944 /* protocol requires ASCII signature byte on Unicode string */
1945 pSMB
->OldFileName
[name_len
+ 1] = 0x00;
1947 cifsConvertToUCS((__le16
*) &pSMB
->OldFileName
[name_len
+ 2],
1948 toName
, PATH_MAX
, nls_codepage
, remap
);
1949 name_len2
+= 1 /* trailing null */ + 1 /* Signature word */ ;
1950 name_len2
*= 2; /* convert to bytes */
1951 } else { /* BB improve the check for buffer overruns BB */
1952 name_len
= strnlen(fromName
, PATH_MAX
);
1953 name_len
++; /* trailing null */
1954 strncpy(pSMB
->OldFileName
, fromName
, name_len
);
1955 name_len2
= strnlen(toName
, PATH_MAX
);
1956 name_len2
++; /* trailing null */
1957 pSMB
->OldFileName
[name_len
] = 0x04; /* 2nd buffer format */
1958 strncpy(&pSMB
->OldFileName
[name_len
+ 1], toName
, name_len2
);
1959 name_len2
++; /* trailing null */
1960 name_len2
++; /* signature byte */
1963 count
= 1 /* 1st signature byte */ + name_len
+ name_len2
;
1964 pSMB
->hdr
.smb_buf_length
+= count
;
1965 pSMB
->ByteCount
= cpu_to_le16(count
);
1967 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
1968 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
1969 cifs_stats_inc(&tcon
->num_renames
);
1971 cFYI(1, ("Send error in rename = %d", rc
));
1973 cifs_buf_release(pSMB
);
1981 int CIFSSMBRenameOpenFile(const int xid
, struct cifsTconInfo
*pTcon
,
1982 int netfid
, char *target_name
,
1983 const struct nls_table
*nls_codepage
, int remap
)
1985 struct smb_com_transaction2_sfi_req
*pSMB
= NULL
;
1986 struct smb_com_transaction2_sfi_rsp
*pSMBr
= NULL
;
1987 struct set_file_rename
*rename_info
;
1989 char dummy_string
[30];
1991 int bytes_returned
= 0;
1993 __u16 params
, param_offset
, offset
, count
, byte_count
;
1995 cFYI(1, ("Rename to File by handle"));
1996 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, pTcon
, (void **) &pSMB
,
2002 pSMB
->MaxSetupCount
= 0;
2006 pSMB
->Reserved2
= 0;
2007 param_offset
= offsetof(struct smb_com_transaction2_sfi_req
, Fid
) - 4;
2008 offset
= param_offset
+ params
;
2010 data_offset
= (char *) (&pSMB
->hdr
.Protocol
) + offset
;
2011 rename_info
= (struct set_file_rename
*) data_offset
;
2012 pSMB
->MaxParameterCount
= cpu_to_le16(2);
2013 pSMB
->MaxDataCount
= cpu_to_le16(1000); /* BB find max SMB from sess */
2014 pSMB
->SetupCount
= 1;
2015 pSMB
->Reserved3
= 0;
2016 pSMB
->SubCommand
= cpu_to_le16(TRANS2_SET_FILE_INFORMATION
);
2017 byte_count
= 3 /* pad */ + params
;
2018 pSMB
->ParameterCount
= cpu_to_le16(params
);
2019 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
2020 pSMB
->ParameterOffset
= cpu_to_le16(param_offset
);
2021 pSMB
->DataOffset
= cpu_to_le16(offset
);
2022 /* construct random name ".cifs_tmp<inodenum><mid>" */
2023 rename_info
->overwrite
= cpu_to_le32(1);
2024 rename_info
->root_fid
= 0;
2025 /* unicode only call */
2026 if (target_name
== NULL
) {
2027 sprintf(dummy_string
, "cifs%x", pSMB
->hdr
.Mid
);
2028 len_of_str
= cifsConvertToUCS((__le16
*)rename_info
->target_name
,
2029 dummy_string
, 24, nls_codepage
, remap
);
2031 len_of_str
= cifsConvertToUCS((__le16
*)rename_info
->target_name
,
2032 target_name
, PATH_MAX
, nls_codepage
,
2035 rename_info
->target_name_len
= cpu_to_le32(2 * len_of_str
);
2036 count
= 12 /* sizeof(struct set_file_rename) */ + (2 * len_of_str
) + 2;
2037 byte_count
+= count
;
2038 pSMB
->DataCount
= cpu_to_le16(count
);
2039 pSMB
->TotalDataCount
= pSMB
->DataCount
;
2041 pSMB
->InformationLevel
=
2042 cpu_to_le16(SMB_SET_FILE_RENAME_INFORMATION
);
2043 pSMB
->Reserved4
= 0;
2044 pSMB
->hdr
.smb_buf_length
+= byte_count
;
2045 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
2046 rc
= SendReceive(xid
, pTcon
->ses
, (struct smb_hdr
*) pSMB
,
2047 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
2048 cifs_stats_inc(&pTcon
->num_t2renames
);
2050 cFYI(1, ("Send error in Rename (by file handle) = %d", rc
));
2052 cifs_buf_release(pSMB
);
2054 /* Note: On -EAGAIN error only caller can retry on handle based calls
2055 since file handle passed in no longer valid */
2061 CIFSSMBCopy(const int xid
, struct cifsTconInfo
*tcon
, const char *fromName
,
2062 const __u16 target_tid
, const char *toName
, const int flags
,
2063 const struct nls_table
*nls_codepage
, int remap
)
2066 COPY_REQ
*pSMB
= NULL
;
2067 COPY_RSP
*pSMBr
= NULL
;
2069 int name_len
, name_len2
;
2072 cFYI(1, ("In CIFSSMBCopy"));
2074 rc
= smb_init(SMB_COM_COPY
, 1, tcon
, (void **) &pSMB
,
2079 pSMB
->BufferFormat
= 0x04;
2080 pSMB
->Tid2
= target_tid
;
2082 pSMB
->Flags
= cpu_to_le16(flags
& COPY_TREE
);
2084 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
2085 name_len
= cifsConvertToUCS((__le16
*) pSMB
->OldFileName
,
2086 fromName
, PATH_MAX
, nls_codepage
,
2088 name_len
++; /* trailing null */
2090 pSMB
->OldFileName
[name_len
] = 0x04; /* pad */
2091 /* protocol requires ASCII signature byte on Unicode string */
2092 pSMB
->OldFileName
[name_len
+ 1] = 0x00;
2094 cifsConvertToUCS((__le16
*)&pSMB
->OldFileName
[name_len
+ 2],
2095 toName
, PATH_MAX
, nls_codepage
, remap
);
2096 name_len2
+= 1 /* trailing null */ + 1 /* Signature word */ ;
2097 name_len2
*= 2; /* convert to bytes */
2098 } else { /* BB improve the check for buffer overruns BB */
2099 name_len
= strnlen(fromName
, PATH_MAX
);
2100 name_len
++; /* trailing null */
2101 strncpy(pSMB
->OldFileName
, fromName
, name_len
);
2102 name_len2
= strnlen(toName
, PATH_MAX
);
2103 name_len2
++; /* trailing null */
2104 pSMB
->OldFileName
[name_len
] = 0x04; /* 2nd buffer format */
2105 strncpy(&pSMB
->OldFileName
[name_len
+ 1], toName
, name_len2
);
2106 name_len2
++; /* trailing null */
2107 name_len2
++; /* signature byte */
2110 count
= 1 /* 1st signature byte */ + name_len
+ name_len2
;
2111 pSMB
->hdr
.smb_buf_length
+= count
;
2112 pSMB
->ByteCount
= cpu_to_le16(count
);
2114 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
2115 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
2117 cFYI(1, ("Send error in copy = %d with %d files copied",
2118 rc
, le16_to_cpu(pSMBr
->CopyCount
)));
2121 cifs_buf_release(pSMB
);
2130 CIFSUnixCreateSymLink(const int xid
, struct cifsTconInfo
*tcon
,
2131 const char *fromName
, const char *toName
,
2132 const struct nls_table
*nls_codepage
)
2134 TRANSACTION2_SPI_REQ
*pSMB
= NULL
;
2135 TRANSACTION2_SPI_RSP
*pSMBr
= NULL
;
2138 int name_len_target
;
2140 int bytes_returned
= 0;
2141 __u16 params
, param_offset
, offset
, byte_count
;
2143 cFYI(1, ("In Symlink Unix style"));
2145 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
2150 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
2152 cifs_strtoUCS((__le16
*) pSMB
->FileName
, fromName
, PATH_MAX
2153 /* find define for this maxpathcomponent */
2155 name_len
++; /* trailing null */
2158 } else { /* BB improve the check for buffer overruns BB */
2159 name_len
= strnlen(fromName
, PATH_MAX
);
2160 name_len
++; /* trailing null */
2161 strncpy(pSMB
->FileName
, fromName
, name_len
);
2163 params
= 6 + name_len
;
2164 pSMB
->MaxSetupCount
= 0;
2168 pSMB
->Reserved2
= 0;
2169 param_offset
= offsetof(struct smb_com_transaction2_spi_req
,
2170 InformationLevel
) - 4;
2171 offset
= param_offset
+ params
;
2173 data_offset
= (char *) (&pSMB
->hdr
.Protocol
) + offset
;
2174 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
2176 cifs_strtoUCS((__le16
*) data_offset
, toName
, PATH_MAX
2177 /* find define for this maxpathcomponent */
2179 name_len_target
++; /* trailing null */
2180 name_len_target
*= 2;
2181 } else { /* BB improve the check for buffer overruns BB */
2182 name_len_target
= strnlen(toName
, PATH_MAX
);
2183 name_len_target
++; /* trailing null */
2184 strncpy(data_offset
, toName
, name_len_target
);
2187 pSMB
->MaxParameterCount
= cpu_to_le16(2);
2188 /* BB find exact max on data count below from sess */
2189 pSMB
->MaxDataCount
= cpu_to_le16(1000);
2190 pSMB
->SetupCount
= 1;
2191 pSMB
->Reserved3
= 0;
2192 pSMB
->SubCommand
= cpu_to_le16(TRANS2_SET_PATH_INFORMATION
);
2193 byte_count
= 3 /* pad */ + params
+ name_len_target
;
2194 pSMB
->DataCount
= cpu_to_le16(name_len_target
);
2195 pSMB
->ParameterCount
= cpu_to_le16(params
);
2196 pSMB
->TotalDataCount
= pSMB
->DataCount
;
2197 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
2198 pSMB
->ParameterOffset
= cpu_to_le16(param_offset
);
2199 pSMB
->DataOffset
= cpu_to_le16(offset
);
2200 pSMB
->InformationLevel
= cpu_to_le16(SMB_SET_FILE_UNIX_LINK
);
2201 pSMB
->Reserved4
= 0;
2202 pSMB
->hdr
.smb_buf_length
+= byte_count
;
2203 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
2204 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
2205 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
2206 cifs_stats_inc(&tcon
->num_symlinks
);
2208 cFYI(1, ("Send error in SetPathInfo create symlink = %d", rc
));
2211 cifs_buf_release(pSMB
);
2214 goto createSymLinkRetry
;
2220 CIFSUnixCreateHardLink(const int xid
, struct cifsTconInfo
*tcon
,
2221 const char *fromName
, const char *toName
,
2222 const struct nls_table
*nls_codepage
, int remap
)
2224 TRANSACTION2_SPI_REQ
*pSMB
= NULL
;
2225 TRANSACTION2_SPI_RSP
*pSMBr
= NULL
;
2228 int name_len_target
;
2230 int bytes_returned
= 0;
2231 __u16 params
, param_offset
, offset
, byte_count
;
2233 cFYI(1, ("In Create Hard link Unix style"));
2234 createHardLinkRetry
:
2235 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
2240 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
2241 name_len
= cifsConvertToUCS((__le16
*) pSMB
->FileName
, toName
,
2242 PATH_MAX
, nls_codepage
, remap
);
2243 name_len
++; /* trailing null */
2246 } else { /* BB improve the check for buffer overruns BB */
2247 name_len
= strnlen(toName
, PATH_MAX
);
2248 name_len
++; /* trailing null */
2249 strncpy(pSMB
->FileName
, toName
, name_len
);
2251 params
= 6 + name_len
;
2252 pSMB
->MaxSetupCount
= 0;
2256 pSMB
->Reserved2
= 0;
2257 param_offset
= offsetof(struct smb_com_transaction2_spi_req
,
2258 InformationLevel
) - 4;
2259 offset
= param_offset
+ params
;
2261 data_offset
= (char *) (&pSMB
->hdr
.Protocol
) + offset
;
2262 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
2264 cifsConvertToUCS((__le16
*) data_offset
, fromName
, PATH_MAX
,
2265 nls_codepage
, remap
);
2266 name_len_target
++; /* trailing null */
2267 name_len_target
*= 2;
2268 } else { /* BB improve the check for buffer overruns BB */
2269 name_len_target
= strnlen(fromName
, PATH_MAX
);
2270 name_len_target
++; /* trailing null */
2271 strncpy(data_offset
, fromName
, name_len_target
);
2274 pSMB
->MaxParameterCount
= cpu_to_le16(2);
2275 /* BB find exact max on data count below from sess*/
2276 pSMB
->MaxDataCount
= cpu_to_le16(1000);
2277 pSMB
->SetupCount
= 1;
2278 pSMB
->Reserved3
= 0;
2279 pSMB
->SubCommand
= cpu_to_le16(TRANS2_SET_PATH_INFORMATION
);
2280 byte_count
= 3 /* pad */ + params
+ name_len_target
;
2281 pSMB
->ParameterCount
= cpu_to_le16(params
);
2282 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
2283 pSMB
->DataCount
= cpu_to_le16(name_len_target
);
2284 pSMB
->TotalDataCount
= pSMB
->DataCount
;
2285 pSMB
->ParameterOffset
= cpu_to_le16(param_offset
);
2286 pSMB
->DataOffset
= cpu_to_le16(offset
);
2287 pSMB
->InformationLevel
= cpu_to_le16(SMB_SET_FILE_UNIX_HLINK
);
2288 pSMB
->Reserved4
= 0;
2289 pSMB
->hdr
.smb_buf_length
+= byte_count
;
2290 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
2291 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
2292 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
2293 cifs_stats_inc(&tcon
->num_hardlinks
);
2295 cFYI(1, ("Send error in SetPathInfo (hard link) = %d", rc
));
2297 cifs_buf_release(pSMB
);
2299 goto createHardLinkRetry
;
2305 CIFSCreateHardLink(const int xid
, struct cifsTconInfo
*tcon
,
2306 const char *fromName
, const char *toName
,
2307 const struct nls_table
*nls_codepage
, int remap
)
2310 NT_RENAME_REQ
*pSMB
= NULL
;
2311 RENAME_RSP
*pSMBr
= NULL
;
2313 int name_len
, name_len2
;
2316 cFYI(1, ("In CIFSCreateHardLink"));
2317 winCreateHardLinkRetry
:
2319 rc
= smb_init(SMB_COM_NT_RENAME
, 4, tcon
, (void **) &pSMB
,
2324 pSMB
->SearchAttributes
=
2325 cpu_to_le16(ATTR_READONLY
| ATTR_HIDDEN
| ATTR_SYSTEM
|
2327 pSMB
->Flags
= cpu_to_le16(CREATE_HARD_LINK
);
2328 pSMB
->ClusterCount
= 0;
2330 pSMB
->BufferFormat
= 0x04;
2332 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
2334 cifsConvertToUCS((__le16
*) pSMB
->OldFileName
, fromName
,
2335 PATH_MAX
, nls_codepage
, remap
);
2336 name_len
++; /* trailing null */
2338 pSMB
->OldFileName
[name_len
] = 0; /* pad */
2339 pSMB
->OldFileName
[name_len
+ 1] = 0x04;
2341 cifsConvertToUCS((__le16
*)&pSMB
->OldFileName
[name_len
+ 2],
2342 toName
, PATH_MAX
, nls_codepage
, remap
);
2343 name_len2
+= 1 /* trailing null */ + 1 /* Signature word */ ;
2344 name_len2
*= 2; /* convert to bytes */
2345 } else { /* BB improve the check for buffer overruns BB */
2346 name_len
= strnlen(fromName
, PATH_MAX
);
2347 name_len
++; /* trailing null */
2348 strncpy(pSMB
->OldFileName
, fromName
, name_len
);
2349 name_len2
= strnlen(toName
, PATH_MAX
);
2350 name_len2
++; /* trailing null */
2351 pSMB
->OldFileName
[name_len
] = 0x04; /* 2nd buffer format */
2352 strncpy(&pSMB
->OldFileName
[name_len
+ 1], toName
, name_len2
);
2353 name_len2
++; /* trailing null */
2354 name_len2
++; /* signature byte */
2357 count
= 1 /* string type byte */ + name_len
+ name_len2
;
2358 pSMB
->hdr
.smb_buf_length
+= count
;
2359 pSMB
->ByteCount
= cpu_to_le16(count
);
2361 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
2362 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
2363 cifs_stats_inc(&tcon
->num_hardlinks
);
2365 cFYI(1, ("Send error in hard link (NT rename) = %d", rc
));
2367 cifs_buf_release(pSMB
);
2369 goto winCreateHardLinkRetry
;
2375 CIFSSMBUnixQuerySymLink(const int xid
, struct cifsTconInfo
*tcon
,
2376 const unsigned char *searchName
,
2377 char *symlinkinfo
, const int buflen
,
2378 const struct nls_table
*nls_codepage
)
2380 /* SMB_QUERY_FILE_UNIX_LINK */
2381 TRANSACTION2_QPI_REQ
*pSMB
= NULL
;
2382 TRANSACTION2_QPI_RSP
*pSMBr
= NULL
;
2386 __u16 params
, byte_count
;
2388 cFYI(1, ("In QPathSymLinkInfo (Unix) for path %s", searchName
));
2391 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
2396 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
2398 cifs_strtoUCS((__le16
*) pSMB
->FileName
, searchName
,
2399 PATH_MAX
, nls_codepage
);
2400 name_len
++; /* trailing null */
2402 } else { /* BB improve the check for buffer overruns BB */
2403 name_len
= strnlen(searchName
, PATH_MAX
);
2404 name_len
++; /* trailing null */
2405 strncpy(pSMB
->FileName
, searchName
, name_len
);
2408 params
= 2 /* level */ + 4 /* rsrvd */ + name_len
/* incl null */ ;
2409 pSMB
->TotalDataCount
= 0;
2410 pSMB
->MaxParameterCount
= cpu_to_le16(2);
2411 /* BB find exact max data count below from sess structure BB */
2412 pSMB
->MaxDataCount
= cpu_to_le16(4000);
2413 pSMB
->MaxSetupCount
= 0;
2417 pSMB
->Reserved2
= 0;
2418 pSMB
->ParameterOffset
= cpu_to_le16(offsetof(
2419 struct smb_com_transaction2_qpi_req
, InformationLevel
) - 4);
2420 pSMB
->DataCount
= 0;
2421 pSMB
->DataOffset
= 0;
2422 pSMB
->SetupCount
= 1;
2423 pSMB
->Reserved3
= 0;
2424 pSMB
->SubCommand
= cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION
);
2425 byte_count
= params
+ 1 /* pad */ ;
2426 pSMB
->TotalParameterCount
= cpu_to_le16(params
);
2427 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
2428 pSMB
->InformationLevel
= cpu_to_le16(SMB_QUERY_FILE_UNIX_LINK
);
2429 pSMB
->Reserved4
= 0;
2430 pSMB
->hdr
.smb_buf_length
+= byte_count
;
2431 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
2433 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
2434 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
2436 cFYI(1, ("Send error in QuerySymLinkInfo = %d", rc
));
2438 /* decode response */
2440 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
2441 if (rc
|| (pSMBr
->ByteCount
< 2))
2442 /* BB also check enough total bytes returned */
2443 rc
= -EIO
; /* bad smb */
2445 __u16 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
2446 __u16 count
= le16_to_cpu(pSMBr
->t2
.DataCount
);
2448 if (pSMBr
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
2449 name_len
= UniStrnlen((wchar_t *) ((char *)
2450 &pSMBr
->hdr
.Protocol
+ data_offset
),
2451 min_t(const int, buflen
, count
) / 2);
2452 /* BB FIXME investigate remapping reserved chars here */
2453 cifs_strfromUCS_le(symlinkinfo
,
2454 (__le16
*) ((char *)&pSMBr
->hdr
.Protocol
2456 name_len
, nls_codepage
);
2458 strncpy(symlinkinfo
,
2459 (char *) &pSMBr
->hdr
.Protocol
+
2461 min_t(const int, buflen
, count
));
2463 symlinkinfo
[buflen
] = 0;
2464 /* just in case so calling code does not go off the end of buffer */
2467 cifs_buf_release(pSMB
);
2469 goto querySymLinkRetry
;
2473 #ifdef CONFIG_CIFS_EXPERIMENTAL
2474 /* Initialize NT TRANSACT SMB into small smb request buffer.
2475 This assumes that all NT TRANSACTS that we init here have
2476 total parm and data under about 400 bytes (to fit in small cifs
2477 buffer size), which is the case so far, it easily fits. NB:
2478 Setup words themselves and ByteCount
2479 MaxSetupCount (size of returned setup area) and
2480 MaxParameterCount (returned parms size) must be set by caller */
2482 smb_init_nttransact(const __u16 sub_command
, const int setup_count
,
2483 const int parm_len
, struct cifsTconInfo
*tcon
,
2488 struct smb_com_ntransact_req
*pSMB
;
2490 rc
= small_smb_init(SMB_COM_NT_TRANSACT
, 19 + setup_count
, tcon
,
2494 *ret_buf
= (void *)pSMB
;
2496 pSMB
->TotalParameterCount
= cpu_to_le32(parm_len
);
2497 pSMB
->TotalDataCount
= 0;
2498 pSMB
->MaxDataCount
= cpu_to_le32((tcon
->ses
->server
->maxBuf
-
2499 MAX_CIFS_HDR_SIZE
) & 0xFFFFFF00);
2500 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
2501 pSMB
->DataCount
= pSMB
->TotalDataCount
;
2502 temp_offset
= offsetof(struct smb_com_ntransact_req
, Parms
) +
2503 (setup_count
* 2) - 4 /* for rfc1001 length itself */;
2504 pSMB
->ParameterOffset
= cpu_to_le32(temp_offset
);
2505 pSMB
->DataOffset
= cpu_to_le32(temp_offset
+ parm_len
);
2506 pSMB
->SetupCount
= setup_count
; /* no need to le convert byte fields */
2507 pSMB
->SubCommand
= cpu_to_le16(sub_command
);
2512 validate_ntransact(char *buf
, char **ppparm
, char **ppdata
,
2513 __u32
*pparmlen
, __u32
*pdatalen
)
2516 __u32 data_count
, data_offset
, parm_count
, parm_offset
;
2517 struct smb_com_ntransact_rsp
*pSMBr
;
2525 pSMBr
= (struct smb_com_ntransact_rsp
*)buf
;
2527 /* ByteCount was converted from little endian in SendReceive */
2528 end_of_smb
= 2 /* sizeof byte count */ + pSMBr
->ByteCount
+
2529 (char *)&pSMBr
->ByteCount
;
2531 data_offset
= le32_to_cpu(pSMBr
->DataOffset
);
2532 data_count
= le32_to_cpu(pSMBr
->DataCount
);
2533 parm_offset
= le32_to_cpu(pSMBr
->ParameterOffset
);
2534 parm_count
= le32_to_cpu(pSMBr
->ParameterCount
);
2536 *ppparm
= (char *)&pSMBr
->hdr
.Protocol
+ parm_offset
;
2537 *ppdata
= (char *)&pSMBr
->hdr
.Protocol
+ data_offset
;
2539 /* should we also check that parm and data areas do not overlap? */
2540 if (*ppparm
> end_of_smb
) {
2541 cFYI(1, ("parms start after end of smb"));
2543 } else if (parm_count
+ *ppparm
> end_of_smb
) {
2544 cFYI(1, ("parm end after end of smb"));
2546 } else if (*ppdata
> end_of_smb
) {
2547 cFYI(1, ("data starts after end of smb"));
2549 } else if (data_count
+ *ppdata
> end_of_smb
) {
2550 cFYI(1, ("data %p + count %d (%p) ends after end of smb %p start %p",
2551 *ppdata
, data_count
, (data_count
+ *ppdata
),
2552 end_of_smb
, pSMBr
));
2554 } else if (parm_count
+ data_count
> pSMBr
->ByteCount
) {
2555 cFYI(1, ("parm count and data count larger than SMB"));
2558 *pdatalen
= data_count
;
2559 *pparmlen
= parm_count
;
2562 #endif /* CIFS_EXPERIMENTAL */
2565 CIFSSMBQueryReparseLinkInfo(const int xid
, struct cifsTconInfo
*tcon
,
2566 const unsigned char *searchName
,
2567 char *symlinkinfo
, const int buflen
, __u16 fid
,
2568 const struct nls_table
*nls_codepage
)
2573 struct smb_com_transaction_ioctl_req
*pSMB
;
2574 struct smb_com_transaction_ioctl_rsp
*pSMBr
;
2576 cFYI(1, ("In Windows reparse style QueryLink for path %s", searchName
));
2577 rc
= smb_init(SMB_COM_NT_TRANSACT
, 23, tcon
, (void **) &pSMB
,
2582 pSMB
->TotalParameterCount
= 0 ;
2583 pSMB
->TotalDataCount
= 0;
2584 pSMB
->MaxParameterCount
= cpu_to_le32(2);
2585 /* BB find exact data count max from sess structure BB */
2586 pSMB
->MaxDataCount
= cpu_to_le32((tcon
->ses
->server
->maxBuf
-
2587 MAX_CIFS_HDR_SIZE
) & 0xFFFFFF00);
2588 pSMB
->MaxSetupCount
= 4;
2590 pSMB
->ParameterOffset
= 0;
2591 pSMB
->DataCount
= 0;
2592 pSMB
->DataOffset
= 0;
2593 pSMB
->SetupCount
= 4;
2594 pSMB
->SubCommand
= cpu_to_le16(NT_TRANSACT_IOCTL
);
2595 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
2596 pSMB
->FunctionCode
= cpu_to_le32(FSCTL_GET_REPARSE_POINT
);
2597 pSMB
->IsFsctl
= 1; /* FSCTL */
2598 pSMB
->IsRootFlag
= 0;
2599 pSMB
->Fid
= fid
; /* file handle always le */
2600 pSMB
->ByteCount
= 0;
2602 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
2603 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
2605 cFYI(1, ("Send error in QueryReparseLinkInfo = %d", rc
));
2606 } else { /* decode response */
2607 __u32 data_offset
= le32_to_cpu(pSMBr
->DataOffset
);
2608 __u32 data_count
= le32_to_cpu(pSMBr
->DataCount
);
2609 if ((pSMBr
->ByteCount
< 2) || (data_offset
> 512))
2610 /* BB also check enough total bytes returned */
2611 rc
= -EIO
; /* bad smb */
2613 if (data_count
&& (data_count
< 2048)) {
2614 char *end_of_smb
= 2 /* sizeof byte count */ +
2616 (char *)&pSMBr
->ByteCount
;
2618 struct reparse_data
*reparse_buf
=
2619 (struct reparse_data
*)
2620 ((char *)&pSMBr
->hdr
.Protocol
2622 if ((char *)reparse_buf
>= end_of_smb
) {
2626 if ((reparse_buf
->LinkNamesBuf
+
2627 reparse_buf
->TargetNameOffset
+
2628 reparse_buf
->TargetNameLen
) >
2630 cFYI(1, ("reparse buf beyond SMB"));
2635 if (pSMBr
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
2636 name_len
= UniStrnlen((wchar_t *)
2637 (reparse_buf
->LinkNamesBuf
+
2638 reparse_buf
->TargetNameOffset
),
2640 reparse_buf
->TargetNameLen
/ 2));
2641 cifs_strfromUCS_le(symlinkinfo
,
2642 (__le16
*) (reparse_buf
->LinkNamesBuf
+
2643 reparse_buf
->TargetNameOffset
),
2644 name_len
, nls_codepage
);
2645 } else { /* ASCII names */
2646 strncpy(symlinkinfo
,
2647 reparse_buf
->LinkNamesBuf
+
2648 reparse_buf
->TargetNameOffset
,
2649 min_t(const int, buflen
,
2650 reparse_buf
->TargetNameLen
));
2654 cFYI(1, ("Invalid return data count on "
2655 "get reparse info ioctl"));
2657 symlinkinfo
[buflen
] = 0; /* just in case so the caller
2658 does not go off the end of the buffer */
2659 cFYI(1, ("readlink result - %s", symlinkinfo
));
2663 cifs_buf_release(pSMB
);
2665 /* Note: On -EAGAIN error only caller can retry on handle based calls
2666 since file handle passed in no longer valid */
2671 #ifdef CONFIG_CIFS_POSIX
2673 /*Convert an Access Control Entry from wire format to local POSIX xattr format*/
2674 static void cifs_convert_ace(posix_acl_xattr_entry
*ace
,
2675 struct cifs_posix_ace
*cifs_ace
)
2677 /* u8 cifs fields do not need le conversion */
2678 ace
->e_perm
= cpu_to_le16(cifs_ace
->cifs_e_perm
);
2679 ace
->e_tag
= cpu_to_le16(cifs_ace
->cifs_e_tag
);
2680 ace
->e_id
= cpu_to_le32(le64_to_cpu(cifs_ace
->cifs_uid
));
2681 /* cFYI(1,("perm %d tag %d id %d",ace->e_perm,ace->e_tag,ace->e_id)); */
2686 /* Convert ACL from CIFS POSIX wire format to local Linux POSIX ACL xattr */
2687 static int cifs_copy_posix_acl(char *trgt
, char *src
, const int buflen
,
2688 const int acl_type
, const int size_of_data_area
)
2693 struct cifs_posix_ace
*pACE
;
2694 struct cifs_posix_acl
*cifs_acl
= (struct cifs_posix_acl
*)src
;
2695 posix_acl_xattr_header
*local_acl
= (posix_acl_xattr_header
*)trgt
;
2697 if (le16_to_cpu(cifs_acl
->version
) != CIFS_ACL_VERSION
)
2700 if (acl_type
& ACL_TYPE_ACCESS
) {
2701 count
= le16_to_cpu(cifs_acl
->access_entry_count
);
2702 pACE
= &cifs_acl
->ace_array
[0];
2703 size
= sizeof(struct cifs_posix_acl
);
2704 size
+= sizeof(struct cifs_posix_ace
) * count
;
2705 /* check if we would go beyond end of SMB */
2706 if (size_of_data_area
< size
) {
2707 cFYI(1, ("bad CIFS POSIX ACL size %d vs. %d",
2708 size_of_data_area
, size
));
2711 } else if (acl_type
& ACL_TYPE_DEFAULT
) {
2712 count
= le16_to_cpu(cifs_acl
->access_entry_count
);
2713 size
= sizeof(struct cifs_posix_acl
);
2714 size
+= sizeof(struct cifs_posix_ace
) * count
;
2715 /* skip past access ACEs to get to default ACEs */
2716 pACE
= &cifs_acl
->ace_array
[count
];
2717 count
= le16_to_cpu(cifs_acl
->default_entry_count
);
2718 size
+= sizeof(struct cifs_posix_ace
) * count
;
2719 /* check if we would go beyond end of SMB */
2720 if (size_of_data_area
< size
)
2727 size
= posix_acl_xattr_size(count
);
2728 if ((buflen
== 0) || (local_acl
== NULL
)) {
2729 /* used to query ACL EA size */
2730 } else if (size
> buflen
) {
2732 } else /* buffer big enough */ {
2733 local_acl
->a_version
= cpu_to_le32(POSIX_ACL_XATTR_VERSION
);
2734 for (i
= 0; i
< count
; i
++) {
2735 cifs_convert_ace(&local_acl
->a_entries
[i
], pACE
);
2742 static __u16
convert_ace_to_cifs_ace(struct cifs_posix_ace
*cifs_ace
,
2743 const posix_acl_xattr_entry
*local_ace
)
2745 __u16 rc
= 0; /* 0 = ACL converted ok */
2747 cifs_ace
->cifs_e_perm
= le16_to_cpu(local_ace
->e_perm
);
2748 cifs_ace
->cifs_e_tag
= le16_to_cpu(local_ace
->e_tag
);
2749 /* BB is there a better way to handle the large uid? */
2750 if (local_ace
->e_id
== cpu_to_le32(-1)) {
2751 /* Probably no need to le convert -1 on any arch but can not hurt */
2752 cifs_ace
->cifs_uid
= cpu_to_le64(-1);
2754 cifs_ace
->cifs_uid
= cpu_to_le64(le32_to_cpu(local_ace
->e_id
));
2755 /*cFYI(1,("perm %d tag %d id %d",ace->e_perm,ace->e_tag,ace->e_id));*/
2759 /* Convert ACL from local Linux POSIX xattr to CIFS POSIX ACL wire format */
2760 static __u16
ACL_to_cifs_posix(char *parm_data
, const char *pACL
,
2761 const int buflen
, const int acl_type
)
2764 struct cifs_posix_acl
*cifs_acl
= (struct cifs_posix_acl
*)parm_data
;
2765 posix_acl_xattr_header
*local_acl
= (posix_acl_xattr_header
*)pACL
;
2769 if ((buflen
== 0) || (pACL
== NULL
) || (cifs_acl
== NULL
))
2772 count
= posix_acl_xattr_count((size_t)buflen
);
2773 cFYI(1, ("setting acl with %d entries from buf of length %d and "
2775 count
, buflen
, le32_to_cpu(local_acl
->a_version
)));
2776 if (le32_to_cpu(local_acl
->a_version
) != 2) {
2777 cFYI(1, ("unknown POSIX ACL version %d",
2778 le32_to_cpu(local_acl
->a_version
)));
2781 cifs_acl
->version
= cpu_to_le16(1);
2782 if (acl_type
== ACL_TYPE_ACCESS
)
2783 cifs_acl
->access_entry_count
= cpu_to_le16(count
);
2784 else if (acl_type
== ACL_TYPE_DEFAULT
)
2785 cifs_acl
->default_entry_count
= cpu_to_le16(count
);
2787 cFYI(1, ("unknown ACL type %d", acl_type
));
2790 for (i
= 0; i
< count
; i
++) {
2791 rc
= convert_ace_to_cifs_ace(&cifs_acl
->ace_array
[i
],
2792 &local_acl
->a_entries
[i
]);
2794 /* ACE not converted */
2799 rc
= (__u16
)(count
* sizeof(struct cifs_posix_ace
));
2800 rc
+= sizeof(struct cifs_posix_acl
);
2801 /* BB add check to make sure ACL does not overflow SMB */
2807 CIFSSMBGetPosixACL(const int xid
, struct cifsTconInfo
*tcon
,
2808 const unsigned char *searchName
,
2809 char *acl_inf
, const int buflen
, const int acl_type
,
2810 const struct nls_table
*nls_codepage
, int remap
)
2812 /* SMB_QUERY_POSIX_ACL */
2813 TRANSACTION2_QPI_REQ
*pSMB
= NULL
;
2814 TRANSACTION2_QPI_RSP
*pSMBr
= NULL
;
2818 __u16 params
, byte_count
;
2820 cFYI(1, ("In GetPosixACL (Unix) for path %s", searchName
));
2823 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
2828 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
2830 cifsConvertToUCS((__le16
*) pSMB
->FileName
, searchName
,
2831 PATH_MAX
, nls_codepage
, remap
);
2832 name_len
++; /* trailing null */
2834 pSMB
->FileName
[name_len
] = 0;
2835 pSMB
->FileName
[name_len
+1] = 0;
2836 } else { /* BB improve the check for buffer overruns BB */
2837 name_len
= strnlen(searchName
, PATH_MAX
);
2838 name_len
++; /* trailing null */
2839 strncpy(pSMB
->FileName
, searchName
, name_len
);
2842 params
= 2 /* level */ + 4 /* rsrvd */ + name_len
/* incl null */ ;
2843 pSMB
->TotalDataCount
= 0;
2844 pSMB
->MaxParameterCount
= cpu_to_le16(2);
2845 /* BB find exact max data count below from sess structure BB */
2846 pSMB
->MaxDataCount
= cpu_to_le16(4000);
2847 pSMB
->MaxSetupCount
= 0;
2851 pSMB
->Reserved2
= 0;
2852 pSMB
->ParameterOffset
= cpu_to_le16(
2853 offsetof(struct smb_com_transaction2_qpi_req
,
2854 InformationLevel
) - 4);
2855 pSMB
->DataCount
= 0;
2856 pSMB
->DataOffset
= 0;
2857 pSMB
->SetupCount
= 1;
2858 pSMB
->Reserved3
= 0;
2859 pSMB
->SubCommand
= cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION
);
2860 byte_count
= params
+ 1 /* pad */ ;
2861 pSMB
->TotalParameterCount
= cpu_to_le16(params
);
2862 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
2863 pSMB
->InformationLevel
= cpu_to_le16(SMB_QUERY_POSIX_ACL
);
2864 pSMB
->Reserved4
= 0;
2865 pSMB
->hdr
.smb_buf_length
+= byte_count
;
2866 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
2868 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
2869 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
2870 cifs_stats_inc(&tcon
->num_acl_get
);
2872 cFYI(1, ("Send error in Query POSIX ACL = %d", rc
));
2874 /* decode response */
2876 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
2877 if (rc
|| (pSMBr
->ByteCount
< 2))
2878 /* BB also check enough total bytes returned */
2879 rc
= -EIO
; /* bad smb */
2881 __u16 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
2882 __u16 count
= le16_to_cpu(pSMBr
->t2
.DataCount
);
2883 rc
= cifs_copy_posix_acl(acl_inf
,
2884 (char *)&pSMBr
->hdr
.Protocol
+data_offset
,
2885 buflen
, acl_type
, count
);
2888 cifs_buf_release(pSMB
);
2895 CIFSSMBSetPosixACL(const int xid
, struct cifsTconInfo
*tcon
,
2896 const unsigned char *fileName
,
2897 const char *local_acl
, const int buflen
,
2899 const struct nls_table
*nls_codepage
, int remap
)
2901 struct smb_com_transaction2_spi_req
*pSMB
= NULL
;
2902 struct smb_com_transaction2_spi_rsp
*pSMBr
= NULL
;
2906 int bytes_returned
= 0;
2907 __u16 params
, byte_count
, data_count
, param_offset
, offset
;
2909 cFYI(1, ("In SetPosixACL (Unix) for path %s", fileName
));
2911 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
2915 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
2917 cifsConvertToUCS((__le16
*) pSMB
->FileName
, fileName
,
2918 PATH_MAX
, nls_codepage
, remap
);
2919 name_len
++; /* trailing null */
2921 } else { /* BB improve the check for buffer overruns BB */
2922 name_len
= strnlen(fileName
, PATH_MAX
);
2923 name_len
++; /* trailing null */
2924 strncpy(pSMB
->FileName
, fileName
, name_len
);
2926 params
= 6 + name_len
;
2927 pSMB
->MaxParameterCount
= cpu_to_le16(2);
2928 pSMB
->MaxDataCount
= cpu_to_le16(1000); /* BB find max SMB size from sess */
2929 pSMB
->MaxSetupCount
= 0;
2933 pSMB
->Reserved2
= 0;
2934 param_offset
= offsetof(struct smb_com_transaction2_spi_req
,
2935 InformationLevel
) - 4;
2936 offset
= param_offset
+ params
;
2937 parm_data
= ((char *) &pSMB
->hdr
.Protocol
) + offset
;
2938 pSMB
->ParameterOffset
= cpu_to_le16(param_offset
);
2940 /* convert to on the wire format for POSIX ACL */
2941 data_count
= ACL_to_cifs_posix(parm_data
, local_acl
, buflen
, acl_type
);
2943 if (data_count
== 0) {
2945 goto setACLerrorExit
;
2947 pSMB
->DataOffset
= cpu_to_le16(offset
);
2948 pSMB
->SetupCount
= 1;
2949 pSMB
->Reserved3
= 0;
2950 pSMB
->SubCommand
= cpu_to_le16(TRANS2_SET_PATH_INFORMATION
);
2951 pSMB
->InformationLevel
= cpu_to_le16(SMB_SET_POSIX_ACL
);
2952 byte_count
= 3 /* pad */ + params
+ data_count
;
2953 pSMB
->DataCount
= cpu_to_le16(data_count
);
2954 pSMB
->TotalDataCount
= pSMB
->DataCount
;
2955 pSMB
->ParameterCount
= cpu_to_le16(params
);
2956 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
2957 pSMB
->Reserved4
= 0;
2958 pSMB
->hdr
.smb_buf_length
+= byte_count
;
2959 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
2960 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
2961 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
2963 cFYI(1, ("Set POSIX ACL returned %d", rc
));
2966 cifs_buf_release(pSMB
);
2972 /* BB fix tabs in this function FIXME BB */
2974 CIFSGetExtAttr(const int xid
, struct cifsTconInfo
*tcon
,
2975 const int netfid
, __u64
*pExtAttrBits
, __u64
*pMask
)
2978 struct smb_t2_qfi_req
*pSMB
= NULL
;
2979 struct smb_t2_qfi_rsp
*pSMBr
= NULL
;
2981 __u16 params
, byte_count
;
2983 cFYI(1, ("In GetExtAttr"));
2988 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
2993 params
= 2 /* level */ + 2 /* fid */;
2994 pSMB
->t2
.TotalDataCount
= 0;
2995 pSMB
->t2
.MaxParameterCount
= cpu_to_le16(4);
2996 /* BB find exact max data count below from sess structure BB */
2997 pSMB
->t2
.MaxDataCount
= cpu_to_le16(4000);
2998 pSMB
->t2
.MaxSetupCount
= 0;
2999 pSMB
->t2
.Reserved
= 0;
3001 pSMB
->t2
.Timeout
= 0;
3002 pSMB
->t2
.Reserved2
= 0;
3003 pSMB
->t2
.ParameterOffset
= cpu_to_le16(offsetof(struct smb_t2_qfi_req
,
3005 pSMB
->t2
.DataCount
= 0;
3006 pSMB
->t2
.DataOffset
= 0;
3007 pSMB
->t2
.SetupCount
= 1;
3008 pSMB
->t2
.Reserved3
= 0;
3009 pSMB
->t2
.SubCommand
= cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION
);
3010 byte_count
= params
+ 1 /* pad */ ;
3011 pSMB
->t2
.TotalParameterCount
= cpu_to_le16(params
);
3012 pSMB
->t2
.ParameterCount
= pSMB
->t2
.TotalParameterCount
;
3013 pSMB
->InformationLevel
= cpu_to_le16(SMB_QUERY_ATTR_FLAGS
);
3016 pSMB
->hdr
.smb_buf_length
+= byte_count
;
3017 pSMB
->t2
.ByteCount
= cpu_to_le16(byte_count
);
3019 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
3020 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
3022 cFYI(1, ("error %d in GetExtAttr", rc
));
3024 /* decode response */
3025 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
3026 if (rc
|| (pSMBr
->ByteCount
< 2))
3027 /* BB also check enough total bytes returned */
3028 /* If rc should we check for EOPNOSUPP and
3029 disable the srvino flag? or in caller? */
3030 rc
= -EIO
; /* bad smb */
3032 __u16 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
3033 __u16 count
= le16_to_cpu(pSMBr
->t2
.DataCount
);
3034 struct file_chattr_info
*pfinfo
;
3035 /* BB Do we need a cast or hash here ? */
3037 cFYI(1, ("Illegal size ret in GetExtAttr"));
3041 pfinfo
= (struct file_chattr_info
*)
3042 (data_offset
+ (char *) &pSMBr
->hdr
.Protocol
);
3043 *pExtAttrBits
= le64_to_cpu(pfinfo
->mode
);
3044 *pMask
= le64_to_cpu(pfinfo
->mask
);
3048 cifs_buf_release(pSMB
);
3050 goto GetExtAttrRetry
;
3054 #endif /* CONFIG_POSIX */
3056 #ifdef CONFIG_CIFS_EXPERIMENTAL
3057 /* Get Security Descriptor (by handle) from remote server for a file or dir */
3059 CIFSSMBGetCIFSACL(const int xid
, struct cifsTconInfo
*tcon
, __u16 fid
,
3060 struct cifs_ntsd
**acl_inf
, __u32
*pbuflen
)
3064 QUERY_SEC_DESC_REQ
*pSMB
;
3067 cFYI(1, ("GetCifsACL"));
3072 rc
= smb_init_nttransact(NT_TRANSACT_QUERY_SECURITY_DESC
, 0,
3073 8 /* parm len */, tcon
, (void **) &pSMB
);
3077 pSMB
->MaxParameterCount
= cpu_to_le32(4);
3078 /* BB TEST with big acls that might need to be e.g. larger than 16K */
3079 pSMB
->MaxSetupCount
= 0;
3080 pSMB
->Fid
= fid
; /* file handle always le */
3081 pSMB
->AclFlags
= cpu_to_le32(CIFS_ACL_OWNER
| CIFS_ACL_GROUP
|
3083 pSMB
->ByteCount
= cpu_to_le16(11); /* 3 bytes pad + 8 bytes parm */
3084 pSMB
->hdr
.smb_buf_length
+= 11;
3085 iov
[0].iov_base
= (char *)pSMB
;
3086 iov
[0].iov_len
= pSMB
->hdr
.smb_buf_length
+ 4;
3088 rc
= SendReceive2(xid
, tcon
->ses
, iov
, 1 /* num iovec */, &buf_type
,
3090 cifs_stats_inc(&tcon
->num_acl_get
);
3092 cFYI(1, ("Send error in QuerySecDesc = %d", rc
));
3093 } else { /* decode response */
3097 struct smb_com_ntransact_rsp
*pSMBr
;
3100 /* validate_nttransact */
3101 rc
= validate_ntransact(iov
[0].iov_base
, (char **)&parm
,
3102 &pdata
, &parm_len
, pbuflen
);
3105 pSMBr
= (struct smb_com_ntransact_rsp
*)iov
[0].iov_base
;
3107 cFYI(1, ("smb %p parm %p data %p", pSMBr
, parm
, *acl_inf
));
3109 if (le32_to_cpu(pSMBr
->ParameterCount
) != 4) {
3110 rc
= -EIO
; /* bad smb */
3115 /* BB check that data area is minimum length and as big as acl_len */
3117 acl_len
= le32_to_cpu(*parm
);
3118 if (acl_len
!= *pbuflen
) {
3119 cERROR(1, ("acl length %d does not match %d",
3120 acl_len
, *pbuflen
));
3121 if (*pbuflen
> acl_len
)
3125 /* check if buffer is big enough for the acl
3126 header followed by the smallest SID */
3127 if ((*pbuflen
< sizeof(struct cifs_ntsd
) + 8) ||
3128 (*pbuflen
>= 64 * 1024)) {
3129 cERROR(1, ("bad acl length %d", *pbuflen
));
3133 *acl_inf
= kmalloc(*pbuflen
, GFP_KERNEL
);
3134 if (*acl_inf
== NULL
) {
3138 memcpy(*acl_inf
, pdata
, *pbuflen
);
3142 if (buf_type
== CIFS_SMALL_BUFFER
)
3143 cifs_small_buf_release(iov
[0].iov_base
);
3144 else if (buf_type
== CIFS_LARGE_BUFFER
)
3145 cifs_buf_release(iov
[0].iov_base
);
3146 /* cifs_small_buf_release(pSMB); */ /* Freed earlier now in SendReceive2 */
3151 CIFSSMBSetCIFSACL(const int xid
, struct cifsTconInfo
*tcon
, __u16 fid
,
3152 struct cifs_ntsd
*pntsd
, __u32 acllen
)
3154 __u16 byte_count
, param_count
, data_count
, param_offset
, data_offset
;
3156 int bytes_returned
= 0;
3157 SET_SEC_DESC_REQ
*pSMB
= NULL
;
3158 NTRANSACT_RSP
*pSMBr
= NULL
;
3161 rc
= smb_init(SMB_COM_NT_TRANSACT
, 19, tcon
, (void **) &pSMB
,
3166 pSMB
->MaxSetupCount
= 0;
3170 param_offset
= offsetof(struct smb_com_transaction_ssec_req
, Fid
) - 4;
3171 data_count
= acllen
;
3172 data_offset
= param_offset
+ param_count
;
3173 byte_count
= 3 /* pad */ + param_count
;
3175 pSMB
->DataCount
= cpu_to_le32(data_count
);
3176 pSMB
->TotalDataCount
= pSMB
->DataCount
;
3177 pSMB
->MaxParameterCount
= cpu_to_le32(4);
3178 pSMB
->MaxDataCount
= cpu_to_le32(16384);
3179 pSMB
->ParameterCount
= cpu_to_le32(param_count
);
3180 pSMB
->ParameterOffset
= cpu_to_le32(param_offset
);
3181 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
3182 pSMB
->DataOffset
= cpu_to_le32(data_offset
);
3183 pSMB
->SetupCount
= 0;
3184 pSMB
->SubCommand
= cpu_to_le16(NT_TRANSACT_SET_SECURITY_DESC
);
3185 pSMB
->ByteCount
= cpu_to_le16(byte_count
+data_count
);
3187 pSMB
->Fid
= fid
; /* file handle always le */
3188 pSMB
->Reserved2
= 0;
3189 pSMB
->AclFlags
= cpu_to_le32(CIFS_ACL_DACL
);
3191 if (pntsd
&& acllen
) {
3192 memcpy((char *) &pSMBr
->hdr
.Protocol
+ data_offset
,
3195 pSMB
->hdr
.smb_buf_length
+= (byte_count
+ data_count
);
3198 pSMB
->hdr
.smb_buf_length
+= byte_count
;
3200 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
3201 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
3203 cFYI(1, ("SetCIFSACL bytes_returned: %d, rc: %d", bytes_returned
, rc
));
3205 cFYI(1, ("Set CIFS ACL returned %d", rc
));
3206 cifs_buf_release(pSMB
);
3209 goto setCifsAclRetry
;
3214 #endif /* CONFIG_CIFS_EXPERIMENTAL */
3216 /* Legacy Query Path Information call for lookup to old servers such
3218 int SMBQueryInformation(const int xid
, struct cifsTconInfo
*tcon
,
3219 const unsigned char *searchName
,
3220 FILE_ALL_INFO
*pFinfo
,
3221 const struct nls_table
*nls_codepage
, int remap
)
3223 QUERY_INFORMATION_REQ
*pSMB
;
3224 QUERY_INFORMATION_RSP
*pSMBr
;
3229 cFYI(1, ("In SMBQPath path %s", searchName
));
3231 rc
= smb_init(SMB_COM_QUERY_INFORMATION
, 0, tcon
, (void **) &pSMB
,
3236 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
3238 cifsConvertToUCS((__le16
*) pSMB
->FileName
, searchName
,
3239 PATH_MAX
, nls_codepage
, remap
);
3240 name_len
++; /* trailing null */
3243 name_len
= strnlen(searchName
, PATH_MAX
);
3244 name_len
++; /* trailing null */
3245 strncpy(pSMB
->FileName
, searchName
, name_len
);
3247 pSMB
->BufferFormat
= 0x04;
3248 name_len
++; /* account for buffer type byte */
3249 pSMB
->hdr
.smb_buf_length
+= (__u16
) name_len
;
3250 pSMB
->ByteCount
= cpu_to_le16(name_len
);
3252 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
3253 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
3255 cFYI(1, ("Send error in QueryInfo = %d", rc
));
3256 } else if (pFinfo
) {
3258 __u32 time
= le32_to_cpu(pSMBr
->last_write_time
);
3260 /* decode response */
3261 /* BB FIXME - add time zone adjustment BB */
3262 memset(pFinfo
, 0, sizeof(FILE_ALL_INFO
));
3265 /* decode time fields */
3266 pFinfo
->ChangeTime
= cpu_to_le64(cifs_UnixTimeToNT(ts
));
3267 pFinfo
->LastWriteTime
= pFinfo
->ChangeTime
;
3268 pFinfo
->LastAccessTime
= 0;
3269 pFinfo
->AllocationSize
=
3270 cpu_to_le64(le32_to_cpu(pSMBr
->size
));
3271 pFinfo
->EndOfFile
= pFinfo
->AllocationSize
;
3272 pFinfo
->Attributes
=
3273 cpu_to_le32(le16_to_cpu(pSMBr
->attr
));
3275 rc
= -EIO
; /* bad buffer passed in */
3277 cifs_buf_release(pSMB
);
3289 CIFSSMBQPathInfo(const int xid
, struct cifsTconInfo
*tcon
,
3290 const unsigned char *searchName
,
3291 FILE_ALL_INFO
*pFindData
,
3292 int legacy
/* old style infolevel */,
3293 const struct nls_table
*nls_codepage
, int remap
)
3295 /* level 263 SMB_QUERY_FILE_ALL_INFO */
3296 TRANSACTION2_QPI_REQ
*pSMB
= NULL
;
3297 TRANSACTION2_QPI_RSP
*pSMBr
= NULL
;
3301 __u16 params
, byte_count
;
3303 /* cFYI(1, ("In QPathInfo path %s", searchName)); */
3305 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
3310 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
3312 cifsConvertToUCS((__le16
*) pSMB
->FileName
, searchName
,
3313 PATH_MAX
, nls_codepage
, remap
);
3314 name_len
++; /* trailing null */
3316 } else { /* BB improve the check for buffer overruns BB */
3317 name_len
= strnlen(searchName
, PATH_MAX
);
3318 name_len
++; /* trailing null */
3319 strncpy(pSMB
->FileName
, searchName
, name_len
);
3322 params
= 2 /* level */ + 4 /* reserved */ + name_len
/* includes NUL */;
3323 pSMB
->TotalDataCount
= 0;
3324 pSMB
->MaxParameterCount
= cpu_to_le16(2);
3325 pSMB
->MaxDataCount
= cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
3326 pSMB
->MaxSetupCount
= 0;
3330 pSMB
->Reserved2
= 0;
3331 pSMB
->ParameterOffset
= cpu_to_le16(offsetof(
3332 struct smb_com_transaction2_qpi_req
, InformationLevel
) - 4);
3333 pSMB
->DataCount
= 0;
3334 pSMB
->DataOffset
= 0;
3335 pSMB
->SetupCount
= 1;
3336 pSMB
->Reserved3
= 0;
3337 pSMB
->SubCommand
= cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION
);
3338 byte_count
= params
+ 1 /* pad */ ;
3339 pSMB
->TotalParameterCount
= cpu_to_le16(params
);
3340 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
3342 pSMB
->InformationLevel
= cpu_to_le16(SMB_INFO_STANDARD
);
3344 pSMB
->InformationLevel
= cpu_to_le16(SMB_QUERY_FILE_ALL_INFO
);
3345 pSMB
->Reserved4
= 0;
3346 pSMB
->hdr
.smb_buf_length
+= byte_count
;
3347 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
3349 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
3350 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
3352 cFYI(1, ("Send error in QPathInfo = %d", rc
));
3353 } else { /* decode response */
3354 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
3356 if (rc
) /* BB add auto retry on EOPNOTSUPP? */
3358 else if (!legacy
&& (pSMBr
->ByteCount
< 40))
3359 rc
= -EIO
; /* bad smb */
3360 else if (legacy
&& (pSMBr
->ByteCount
< 24))
3361 rc
= -EIO
; /* 24 or 26 expected but we do not read
3363 else if (pFindData
) {
3365 __u16 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
3367 /* On legacy responses we do not read the last field,
3368 EAsize, fortunately since it varies by subdialect and
3369 also note it differs on Set vs. Get, ie two bytes or 4
3370 bytes depending but we don't care here */
3372 size
= sizeof(FILE_INFO_STANDARD
);
3374 size
= sizeof(FILE_ALL_INFO
);
3375 memcpy((char *) pFindData
,
3376 (char *) &pSMBr
->hdr
.Protocol
+
3381 cifs_buf_release(pSMB
);
3383 goto QPathInfoRetry
;
3389 CIFSSMBUnixQPathInfo(const int xid
, struct cifsTconInfo
*tcon
,
3390 const unsigned char *searchName
,
3391 FILE_UNIX_BASIC_INFO
* pFindData
,
3392 const struct nls_table
*nls_codepage
, int remap
)
3394 /* SMB_QUERY_FILE_UNIX_BASIC */
3395 TRANSACTION2_QPI_REQ
*pSMB
= NULL
;
3396 TRANSACTION2_QPI_RSP
*pSMBr
= NULL
;
3398 int bytes_returned
= 0;
3400 __u16 params
, byte_count
;
3402 cFYI(1, ("In QPathInfo (Unix) the path %s", searchName
));
3404 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
3409 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
3411 cifsConvertToUCS((__le16
*) pSMB
->FileName
, searchName
,
3412 PATH_MAX
, nls_codepage
, remap
);
3413 name_len
++; /* trailing null */
3415 } else { /* BB improve the check for buffer overruns BB */
3416 name_len
= strnlen(searchName
, PATH_MAX
);
3417 name_len
++; /* trailing null */
3418 strncpy(pSMB
->FileName
, searchName
, name_len
);
3421 params
= 2 /* level */ + 4 /* reserved */ + name_len
/* includes NUL */;
3422 pSMB
->TotalDataCount
= 0;
3423 pSMB
->MaxParameterCount
= cpu_to_le16(2);
3424 /* BB find exact max SMB PDU from sess structure BB */
3425 pSMB
->MaxDataCount
= cpu_to_le16(4000);
3426 pSMB
->MaxSetupCount
= 0;
3430 pSMB
->Reserved2
= 0;
3431 pSMB
->ParameterOffset
= cpu_to_le16(offsetof(
3432 struct smb_com_transaction2_qpi_req
, InformationLevel
) - 4);
3433 pSMB
->DataCount
= 0;
3434 pSMB
->DataOffset
= 0;
3435 pSMB
->SetupCount
= 1;
3436 pSMB
->Reserved3
= 0;
3437 pSMB
->SubCommand
= cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION
);
3438 byte_count
= params
+ 1 /* pad */ ;
3439 pSMB
->TotalParameterCount
= cpu_to_le16(params
);
3440 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
3441 pSMB
->InformationLevel
= cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC
);
3442 pSMB
->Reserved4
= 0;
3443 pSMB
->hdr
.smb_buf_length
+= byte_count
;
3444 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
3446 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
3447 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
3449 cFYI(1, ("Send error in QPathInfo = %d", rc
));
3450 } else { /* decode response */
3451 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
3453 if (rc
|| (pSMBr
->ByteCount
< sizeof(FILE_UNIX_BASIC_INFO
))) {
3454 cERROR(1, ("Malformed FILE_UNIX_BASIC_INFO response.\n"
3455 "Unix Extensions can be disabled on mount "
3456 "by specifying the nosfu mount option."));
3457 rc
= -EIO
; /* bad smb */
3459 __u16 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
3460 memcpy((char *) pFindData
,
3461 (char *) &pSMBr
->hdr
.Protocol
+
3463 sizeof(FILE_UNIX_BASIC_INFO
));
3466 cifs_buf_release(pSMB
);
3468 goto UnixQPathInfoRetry
;
3473 /* xid, tcon, searchName and codepage are input parms, rest are returned */
3475 CIFSFindFirst(const int xid
, struct cifsTconInfo
*tcon
,
3476 const char *searchName
,
3477 const struct nls_table
*nls_codepage
,
3479 struct cifs_search_info
*psrch_inf
, int remap
, const char dirsep
)
3481 /* level 257 SMB_ */
3482 TRANSACTION2_FFIRST_REQ
*pSMB
= NULL
;
3483 TRANSACTION2_FFIRST_RSP
*pSMBr
= NULL
;
3484 T2_FFIRST_RSP_PARMS
*parms
;
3486 int bytes_returned
= 0;
3488 __u16 params
, byte_count
;
3490 cFYI(1, ("In FindFirst for %s", searchName
));
3493 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
3498 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
3500 cifsConvertToUCS((__le16
*) pSMB
->FileName
, searchName
,
3501 PATH_MAX
, nls_codepage
, remap
);
3502 /* We can not add the asterik earlier in case
3503 it got remapped to 0xF03A as if it were part of the
3504 directory name instead of a wildcard */
3506 pSMB
->FileName
[name_len
] = dirsep
;
3507 pSMB
->FileName
[name_len
+1] = 0;
3508 pSMB
->FileName
[name_len
+2] = '*';
3509 pSMB
->FileName
[name_len
+3] = 0;
3510 name_len
+= 4; /* now the trailing null */
3511 pSMB
->FileName
[name_len
] = 0; /* null terminate just in case */
3512 pSMB
->FileName
[name_len
+1] = 0;
3514 } else { /* BB add check for overrun of SMB buf BB */
3515 name_len
= strnlen(searchName
, PATH_MAX
);
3516 /* BB fix here and in unicode clause above ie
3517 if (name_len > buffersize-header)
3518 free buffer exit; BB */
3519 strncpy(pSMB
->FileName
, searchName
, name_len
);
3520 pSMB
->FileName
[name_len
] = dirsep
;
3521 pSMB
->FileName
[name_len
+1] = '*';
3522 pSMB
->FileName
[name_len
+2] = 0;
3526 params
= 12 + name_len
/* includes null */ ;
3527 pSMB
->TotalDataCount
= 0; /* no EAs */
3528 pSMB
->MaxParameterCount
= cpu_to_le16(10);
3529 pSMB
->MaxDataCount
= cpu_to_le16((tcon
->ses
->server
->maxBuf
-
3530 MAX_CIFS_HDR_SIZE
) & 0xFFFFFF00);
3531 pSMB
->MaxSetupCount
= 0;
3535 pSMB
->Reserved2
= 0;
3536 byte_count
= params
+ 1 /* pad */ ;
3537 pSMB
->TotalParameterCount
= cpu_to_le16(params
);
3538 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
3539 pSMB
->ParameterOffset
= cpu_to_le16(
3540 offsetof(struct smb_com_transaction2_ffirst_req
, SearchAttributes
)
3542 pSMB
->DataCount
= 0;
3543 pSMB
->DataOffset
= 0;
3544 pSMB
->SetupCount
= 1; /* one byte, no need to make endian neutral */
3545 pSMB
->Reserved3
= 0;
3546 pSMB
->SubCommand
= cpu_to_le16(TRANS2_FIND_FIRST
);
3547 pSMB
->SearchAttributes
=
3548 cpu_to_le16(ATTR_READONLY
| ATTR_HIDDEN
| ATTR_SYSTEM
|
3550 pSMB
->SearchCount
= cpu_to_le16(CIFSMaxBufSize
/sizeof(FILE_UNIX_INFO
));
3551 pSMB
->SearchFlags
= cpu_to_le16(CIFS_SEARCH_CLOSE_AT_END
|
3552 CIFS_SEARCH_RETURN_RESUME
);
3553 pSMB
->InformationLevel
= cpu_to_le16(psrch_inf
->info_level
);
3555 /* BB what should we set StorageType to? Does it matter? BB */
3556 pSMB
->SearchStorageType
= 0;
3557 pSMB
->hdr
.smb_buf_length
+= byte_count
;
3558 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
3560 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
3561 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
3562 cifs_stats_inc(&tcon
->num_ffirst
);
3564 if (rc
) {/* BB add logic to retry regular search if Unix search
3565 rejected unexpectedly by server */
3566 /* BB Add code to handle unsupported level rc */
3567 cFYI(1, ("Error in FindFirst = %d", rc
));
3569 cifs_buf_release(pSMB
);
3571 /* BB eventually could optimize out free and realloc of buf */
3574 goto findFirstRetry
;
3575 } else { /* decode response */
3576 /* BB remember to free buffer if error BB */
3577 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
3579 if (pSMBr
->hdr
.Flags2
& SMBFLG2_UNICODE
)
3580 psrch_inf
->unicode
= TRUE
;
3582 psrch_inf
->unicode
= FALSE
;
3584 psrch_inf
->ntwrk_buf_start
= (char *)pSMBr
;
3585 psrch_inf
->smallBuf
= 0;
3586 psrch_inf
->srch_entries_start
=
3587 (char *) &pSMBr
->hdr
.Protocol
+
3588 le16_to_cpu(pSMBr
->t2
.DataOffset
);
3589 parms
= (T2_FFIRST_RSP_PARMS
*)((char *) &pSMBr
->hdr
.Protocol
+
3590 le16_to_cpu(pSMBr
->t2
.ParameterOffset
));
3592 if (parms
->EndofSearch
)
3593 psrch_inf
->endOfSearch
= TRUE
;
3595 psrch_inf
->endOfSearch
= FALSE
;
3597 psrch_inf
->entries_in_buffer
=
3598 le16_to_cpu(parms
->SearchCount
);
3599 psrch_inf
->index_of_last_entry
= 2 /* skip . and .. */ +
3600 psrch_inf
->entries_in_buffer
;
3601 *pnetfid
= parms
->SearchHandle
;
3603 cifs_buf_release(pSMB
);
3610 int CIFSFindNext(const int xid
, struct cifsTconInfo
*tcon
,
3611 __u16 searchHandle
, struct cifs_search_info
*psrch_inf
)
3613 TRANSACTION2_FNEXT_REQ
*pSMB
= NULL
;
3614 TRANSACTION2_FNEXT_RSP
*pSMBr
= NULL
;
3615 T2_FNEXT_RSP_PARMS
*parms
;
3616 char *response_data
;
3618 int bytes_returned
, name_len
;
3619 __u16 params
, byte_count
;
3621 cFYI(1, ("In FindNext"));
3623 if (psrch_inf
->endOfSearch
== TRUE
)
3626 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
3631 params
= 14; /* includes 2 bytes of null string, converted to LE below*/
3633 pSMB
->TotalDataCount
= 0; /* no EAs */
3634 pSMB
->MaxParameterCount
= cpu_to_le16(8);
3635 pSMB
->MaxDataCount
=
3636 cpu_to_le16((tcon
->ses
->server
->maxBuf
- MAX_CIFS_HDR_SIZE
) &
3638 pSMB
->MaxSetupCount
= 0;
3642 pSMB
->Reserved2
= 0;
3643 pSMB
->ParameterOffset
= cpu_to_le16(
3644 offsetof(struct smb_com_transaction2_fnext_req
,SearchHandle
) - 4);
3645 pSMB
->DataCount
= 0;
3646 pSMB
->DataOffset
= 0;
3647 pSMB
->SetupCount
= 1;
3648 pSMB
->Reserved3
= 0;
3649 pSMB
->SubCommand
= cpu_to_le16(TRANS2_FIND_NEXT
);
3650 pSMB
->SearchHandle
= searchHandle
; /* always kept as le */
3652 cpu_to_le16(CIFSMaxBufSize
/ sizeof(FILE_UNIX_INFO
));
3653 pSMB
->InformationLevel
= cpu_to_le16(psrch_inf
->info_level
);
3654 pSMB
->ResumeKey
= psrch_inf
->resume_key
;
3656 cpu_to_le16(CIFS_SEARCH_CLOSE_AT_END
| CIFS_SEARCH_RETURN_RESUME
);
3658 name_len
= psrch_inf
->resume_name_len
;
3660 if (name_len
< PATH_MAX
) {
3661 memcpy(pSMB
->ResumeFileName
, psrch_inf
->presume_name
, name_len
);
3662 byte_count
+= name_len
;
3663 /* 14 byte parm len above enough for 2 byte null terminator */
3664 pSMB
->ResumeFileName
[name_len
] = 0;
3665 pSMB
->ResumeFileName
[name_len
+1] = 0;
3668 goto FNext2_err_exit
;
3670 byte_count
= params
+ 1 /* pad */ ;
3671 pSMB
->TotalParameterCount
= cpu_to_le16(params
);
3672 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
3673 pSMB
->hdr
.smb_buf_length
+= byte_count
;
3674 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
3676 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
3677 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
3678 cifs_stats_inc(&tcon
->num_fnext
);
3681 psrch_inf
->endOfSearch
= TRUE
;
3682 rc
= 0; /* search probably was closed at end of search*/
3684 cFYI(1, ("FindNext returned = %d", rc
));
3685 } else { /* decode response */
3686 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
3689 /* BB fixme add lock for file (srch_info) struct here */
3690 if (pSMBr
->hdr
.Flags2
& SMBFLG2_UNICODE
)
3691 psrch_inf
->unicode
= TRUE
;
3693 psrch_inf
->unicode
= FALSE
;
3694 response_data
= (char *) &pSMBr
->hdr
.Protocol
+
3695 le16_to_cpu(pSMBr
->t2
.ParameterOffset
);
3696 parms
= (T2_FNEXT_RSP_PARMS
*)response_data
;
3697 response_data
= (char *)&pSMBr
->hdr
.Protocol
+
3698 le16_to_cpu(pSMBr
->t2
.DataOffset
);
3699 if (psrch_inf
->smallBuf
)
3700 cifs_small_buf_release(
3701 psrch_inf
->ntwrk_buf_start
);
3703 cifs_buf_release(psrch_inf
->ntwrk_buf_start
);
3704 psrch_inf
->srch_entries_start
= response_data
;
3705 psrch_inf
->ntwrk_buf_start
= (char *)pSMB
;
3706 psrch_inf
->smallBuf
= 0;
3707 if (parms
->EndofSearch
)
3708 psrch_inf
->endOfSearch
= TRUE
;
3710 psrch_inf
->endOfSearch
= FALSE
;
3711 psrch_inf
->entries_in_buffer
=
3712 le16_to_cpu(parms
->SearchCount
);
3713 psrch_inf
->index_of_last_entry
+=
3714 psrch_inf
->entries_in_buffer
;
3715 /* cFYI(1,("fnxt2 entries in buf %d index_of_last %d",
3716 psrch_inf->entries_in_buffer, psrch_inf->index_of_last_entry)); */
3718 /* BB fixme add unlock here */
3723 /* BB On error, should we leave previous search buf (and count and
3724 last entry fields) intact or free the previous one? */
3726 /* Note: On -EAGAIN error only caller can retry on handle based calls
3727 since file handle passed in no longer valid */
3730 cifs_buf_release(pSMB
);
3735 CIFSFindClose(const int xid
, struct cifsTconInfo
*tcon
,
3736 const __u16 searchHandle
)
3739 FINDCLOSE_REQ
*pSMB
= NULL
;
3741 cFYI(1, ("In CIFSSMBFindClose"));
3742 rc
= small_smb_init(SMB_COM_FIND_CLOSE2
, 1, tcon
, (void **)&pSMB
);
3744 /* no sense returning error if session restarted
3745 as file handle has been closed */
3751 pSMB
->FileID
= searchHandle
;
3752 pSMB
->ByteCount
= 0;
3753 rc
= SendReceiveNoRsp(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
, 0);
3755 cERROR(1, ("Send error in FindClose = %d", rc
));
3757 cifs_stats_inc(&tcon
->num_fclose
);
3759 /* Since session is dead, search handle closed on server already */
3767 CIFSGetSrvInodeNumber(const int xid
, struct cifsTconInfo
*tcon
,
3768 const unsigned char *searchName
,
3769 __u64
*inode_number
,
3770 const struct nls_table
*nls_codepage
, int remap
)
3773 TRANSACTION2_QPI_REQ
*pSMB
= NULL
;
3774 TRANSACTION2_QPI_RSP
*pSMBr
= NULL
;
3775 int name_len
, bytes_returned
;
3776 __u16 params
, byte_count
;
3778 cFYI(1, ("In GetSrvInodeNum for %s", searchName
));
3782 GetInodeNumberRetry
:
3783 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
3788 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
3790 cifsConvertToUCS((__le16
*) pSMB
->FileName
, searchName
,
3791 PATH_MAX
, nls_codepage
, remap
);
3792 name_len
++; /* trailing null */
3794 } else { /* BB improve the check for buffer overruns BB */
3795 name_len
= strnlen(searchName
, PATH_MAX
);
3796 name_len
++; /* trailing null */
3797 strncpy(pSMB
->FileName
, searchName
, name_len
);
3800 params
= 2 /* level */ + 4 /* rsrvd */ + name_len
/* incl null */ ;
3801 pSMB
->TotalDataCount
= 0;
3802 pSMB
->MaxParameterCount
= cpu_to_le16(2);
3803 /* BB find exact max data count below from sess structure BB */
3804 pSMB
->MaxDataCount
= cpu_to_le16(4000);
3805 pSMB
->MaxSetupCount
= 0;
3809 pSMB
->Reserved2
= 0;
3810 pSMB
->ParameterOffset
= cpu_to_le16(offsetof(
3811 struct smb_com_transaction2_qpi_req
, InformationLevel
) - 4);
3812 pSMB
->DataCount
= 0;
3813 pSMB
->DataOffset
= 0;
3814 pSMB
->SetupCount
= 1;
3815 pSMB
->Reserved3
= 0;
3816 pSMB
->SubCommand
= cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION
);
3817 byte_count
= params
+ 1 /* pad */ ;
3818 pSMB
->TotalParameterCount
= cpu_to_le16(params
);
3819 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
3820 pSMB
->InformationLevel
= cpu_to_le16(SMB_QUERY_FILE_INTERNAL_INFO
);
3821 pSMB
->Reserved4
= 0;
3822 pSMB
->hdr
.smb_buf_length
+= byte_count
;
3823 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
3825 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
3826 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
3828 cFYI(1, ("error %d in QueryInternalInfo", rc
));
3830 /* decode response */
3831 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
3832 if (rc
|| (pSMBr
->ByteCount
< 2))
3833 /* BB also check enough total bytes returned */
3834 /* If rc should we check for EOPNOSUPP and
3835 disable the srvino flag? or in caller? */
3836 rc
= -EIO
; /* bad smb */
3838 __u16 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
3839 __u16 count
= le16_to_cpu(pSMBr
->t2
.DataCount
);
3840 struct file_internal_info
*pfinfo
;
3841 /* BB Do we need a cast or hash here ? */
3843 cFYI(1, ("Illegal size ret in QryIntrnlInf"));
3845 goto GetInodeNumOut
;
3847 pfinfo
= (struct file_internal_info
*)
3848 (data_offset
+ (char *) &pSMBr
->hdr
.Protocol
);
3849 *inode_number
= pfinfo
->UniqueId
;
3853 cifs_buf_release(pSMB
);
3855 goto GetInodeNumberRetry
;
3860 CIFSGetDFSRefer(const int xid
, struct cifsSesInfo
*ses
,
3861 const unsigned char *searchName
,
3862 unsigned char **targetUNCs
,
3863 unsigned int *number_of_UNC_in_array
,
3864 const struct nls_table
*nls_codepage
, int remap
)
3866 /* TRANS2_GET_DFS_REFERRAL */
3867 TRANSACTION2_GET_DFS_REFER_REQ
*pSMB
= NULL
;
3868 TRANSACTION2_GET_DFS_REFER_RSP
*pSMBr
= NULL
;
3869 struct dfs_referral_level_3
*referrals
= NULL
;
3875 __u16 params
, byte_count
;
3876 *number_of_UNC_in_array
= 0;
3879 cFYI(1, ("In GetDFSRefer the path %s", searchName
));
3883 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, NULL
, (void **) &pSMB
,
3888 /* server pointer checked in called function,
3889 but should never be null here anyway */
3890 pSMB
->hdr
.Mid
= GetNextMid(ses
->server
);
3891 pSMB
->hdr
.Tid
= ses
->ipc_tid
;
3892 pSMB
->hdr
.Uid
= ses
->Suid
;
3893 if (ses
->capabilities
& CAP_STATUS32
)
3894 pSMB
->hdr
.Flags2
|= SMBFLG2_ERR_STATUS
;
3895 if (ses
->capabilities
& CAP_DFS
)
3896 pSMB
->hdr
.Flags2
|= SMBFLG2_DFS
;
3898 if (ses
->capabilities
& CAP_UNICODE
) {
3899 pSMB
->hdr
.Flags2
|= SMBFLG2_UNICODE
;
3901 cifsConvertToUCS((__le16
*) pSMB
->RequestFileName
,
3902 searchName
, PATH_MAX
, nls_codepage
, remap
);
3903 name_len
++; /* trailing null */
3905 } else { /* BB improve the check for buffer overruns BB */
3906 name_len
= strnlen(searchName
, PATH_MAX
);
3907 name_len
++; /* trailing null */
3908 strncpy(pSMB
->RequestFileName
, searchName
, name_len
);
3912 if (ses
->server
->secMode
&
3913 (SECMODE_SIGN_REQUIRED
| SECMODE_SIGN_ENABLED
))
3914 pSMB
->hdr
.Flags2
|= SMBFLG2_SECURITY_SIGNATURE
;
3917 pSMB
->hdr
.Uid
= ses
->Suid
;
3919 params
= 2 /* level */ + name_len
/*includes null */ ;
3920 pSMB
->TotalDataCount
= 0;
3921 pSMB
->DataCount
= 0;
3922 pSMB
->DataOffset
= 0;
3923 pSMB
->MaxParameterCount
= 0;
3924 pSMB
->MaxDataCount
= cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
3925 pSMB
->MaxSetupCount
= 0;
3929 pSMB
->Reserved2
= 0;
3930 pSMB
->ParameterOffset
= cpu_to_le16(offsetof(
3931 struct smb_com_transaction2_get_dfs_refer_req
, MaxReferralLevel
) - 4);
3932 pSMB
->SetupCount
= 1;
3933 pSMB
->Reserved3
= 0;
3934 pSMB
->SubCommand
= cpu_to_le16(TRANS2_GET_DFS_REFERRAL
);
3935 byte_count
= params
+ 3 /* pad */ ;
3936 pSMB
->ParameterCount
= cpu_to_le16(params
);
3937 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
3938 pSMB
->MaxReferralLevel
= cpu_to_le16(3);
3939 pSMB
->hdr
.smb_buf_length
+= byte_count
;
3940 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
3942 rc
= SendReceive(xid
, ses
, (struct smb_hdr
*) pSMB
,
3943 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
3945 cFYI(1, ("Send error in GetDFSRefer = %d", rc
));
3946 } else { /* decode response */
3947 /* BB Add logic to parse referrals here */
3948 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
3950 /* BB Also check if enough total bytes returned? */
3951 if (rc
|| (pSMBr
->ByteCount
< 17))
3952 rc
= -EIO
; /* bad smb */
3954 __u16 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
3955 __u16 data_count
= le16_to_cpu(pSMBr
->t2
.DataCount
);
3958 ("Decoding GetDFSRefer response BCC: %d Offset %d",
3959 pSMBr
->ByteCount
, data_offset
));
3961 (struct dfs_referral_level_3
*)
3962 (8 /* sizeof start of data block */ +
3964 (char *) &pSMBr
->hdr
.Protocol
);
3965 cFYI(1, ("num_referrals: %d dfs flags: 0x%x ... \n"
3966 "for referral one refer size: 0x%x srv "
3967 "type: 0x%x refer flags: 0x%x ttl: 0x%x",
3968 le16_to_cpu(pSMBr
->NumberOfReferrals
),
3969 le16_to_cpu(pSMBr
->DFSFlags
),
3970 le16_to_cpu(referrals
->ReferralSize
),
3971 le16_to_cpu(referrals
->ServerType
),
3972 le16_to_cpu(referrals
->ReferralFlags
),
3973 le16_to_cpu(referrals
->TimeToLive
)));
3974 /* BB This field is actually two bytes in from start of
3975 data block so we could do safety check that DataBlock
3976 begins at address of pSMBr->NumberOfReferrals */
3977 *number_of_UNC_in_array
=
3978 le16_to_cpu(pSMBr
->NumberOfReferrals
);
3980 /* BB Fix below so can return more than one referral */
3981 if (*number_of_UNC_in_array
> 1)
3982 *number_of_UNC_in_array
= 1;
3984 /* get the length of the strings describing refs */
3986 for (i
= 0; i
< *number_of_UNC_in_array
; i
++) {
3987 /* make sure that DfsPathOffset not past end */
3989 le16_to_cpu(referrals
->DfsPathOffset
);
3990 if (offset
> data_count
) {
3991 /* if invalid referral, stop here and do
3992 not try to copy any more */
3993 *number_of_UNC_in_array
= i
;
3996 temp
= ((char *)referrals
) + offset
;
3998 if (pSMBr
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
3999 name_len
+= UniStrnlen((wchar_t *)temp
,
4002 name_len
+= strnlen(temp
, data_count
);
4005 /* BB add check that referral pointer does
4006 not fall off end PDU */
4008 /* BB add check for name_len bigger than bcc */
4010 kmalloc(name_len
+1+(*number_of_UNC_in_array
),
4012 if (*targetUNCs
== NULL
) {
4016 /* copy the ref strings */
4017 referrals
= (struct dfs_referral_level_3
*)
4018 (8 /* sizeof data hdr */ + data_offset
+
4019 (char *) &pSMBr
->hdr
.Protocol
);
4021 for (i
= 0; i
< *number_of_UNC_in_array
; i
++) {
4022 temp
= ((char *)referrals
) +
4023 le16_to_cpu(referrals
->DfsPathOffset
);
4024 if (pSMBr
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
4025 cifs_strfromUCS_le(*targetUNCs
,
4030 strncpy(*targetUNCs
, temp
, name_len
);
4032 /* BB update target_uncs pointers */
4042 cifs_buf_release(pSMB
);
4050 /* Query File System Info such as free space to old servers such as Win 9x */
4052 SMBOldQFSInfo(const int xid
, struct cifsTconInfo
*tcon
, struct kstatfs
*FSData
)
4054 /* level 0x01 SMB_QUERY_FILE_SYSTEM_INFO */
4055 TRANSACTION2_QFSI_REQ
*pSMB
= NULL
;
4056 TRANSACTION2_QFSI_RSP
*pSMBr
= NULL
;
4057 FILE_SYSTEM_ALLOC_INFO
*response_data
;
4059 int bytes_returned
= 0;
4060 __u16 params
, byte_count
;
4062 cFYI(1, ("OldQFSInfo"));
4064 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
4069 params
= 2; /* level */
4070 pSMB
->TotalDataCount
= 0;
4071 pSMB
->MaxParameterCount
= cpu_to_le16(2);
4072 pSMB
->MaxDataCount
= cpu_to_le16(1000);
4073 pSMB
->MaxSetupCount
= 0;
4077 pSMB
->Reserved2
= 0;
4078 byte_count
= params
+ 1 /* pad */ ;
4079 pSMB
->TotalParameterCount
= cpu_to_le16(params
);
4080 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
4081 pSMB
->ParameterOffset
= cpu_to_le16(offsetof(
4082 struct smb_com_transaction2_qfsi_req
, InformationLevel
) - 4);
4083 pSMB
->DataCount
= 0;
4084 pSMB
->DataOffset
= 0;
4085 pSMB
->SetupCount
= 1;
4086 pSMB
->Reserved3
= 0;
4087 pSMB
->SubCommand
= cpu_to_le16(TRANS2_QUERY_FS_INFORMATION
);
4088 pSMB
->InformationLevel
= cpu_to_le16(SMB_INFO_ALLOCATION
);
4089 pSMB
->hdr
.smb_buf_length
+= byte_count
;
4090 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
4092 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
4093 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
4095 cFYI(1, ("Send error in QFSInfo = %d", rc
));
4096 } else { /* decode response */
4097 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
4099 if (rc
|| (pSMBr
->ByteCount
< 18))
4100 rc
= -EIO
; /* bad smb */
4102 __u16 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
4103 cFYI(1, ("qfsinf resp BCC: %d Offset %d",
4104 pSMBr
->ByteCount
, data_offset
));
4106 response_data
= (FILE_SYSTEM_ALLOC_INFO
*)
4107 (((char *) &pSMBr
->hdr
.Protocol
) + data_offset
);
4109 le16_to_cpu(response_data
->BytesPerSector
) *
4110 le32_to_cpu(response_data
->
4111 SectorsPerAllocationUnit
);
4113 le32_to_cpu(response_data
->TotalAllocationUnits
);
4114 FSData
->f_bfree
= FSData
->f_bavail
=
4115 le32_to_cpu(response_data
->FreeAllocationUnits
);
4117 ("Blocks: %lld Free: %lld Block size %ld",
4118 (unsigned long long)FSData
->f_blocks
,
4119 (unsigned long long)FSData
->f_bfree
,
4123 cifs_buf_release(pSMB
);
4126 goto oldQFSInfoRetry
;
4132 CIFSSMBQFSInfo(const int xid
, struct cifsTconInfo
*tcon
, struct kstatfs
*FSData
)
4134 /* level 0x103 SMB_QUERY_FILE_SYSTEM_INFO */
4135 TRANSACTION2_QFSI_REQ
*pSMB
= NULL
;
4136 TRANSACTION2_QFSI_RSP
*pSMBr
= NULL
;
4137 FILE_SYSTEM_INFO
*response_data
;
4139 int bytes_returned
= 0;
4140 __u16 params
, byte_count
;
4142 cFYI(1, ("In QFSInfo"));
4144 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
4149 params
= 2; /* level */
4150 pSMB
->TotalDataCount
= 0;
4151 pSMB
->MaxParameterCount
= cpu_to_le16(2);
4152 pSMB
->MaxDataCount
= cpu_to_le16(1000);
4153 pSMB
->MaxSetupCount
= 0;
4157 pSMB
->Reserved2
= 0;
4158 byte_count
= params
+ 1 /* pad */ ;
4159 pSMB
->TotalParameterCount
= cpu_to_le16(params
);
4160 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
4161 pSMB
->ParameterOffset
= cpu_to_le16(offsetof(
4162 struct smb_com_transaction2_qfsi_req
, InformationLevel
) - 4);
4163 pSMB
->DataCount
= 0;
4164 pSMB
->DataOffset
= 0;
4165 pSMB
->SetupCount
= 1;
4166 pSMB
->Reserved3
= 0;
4167 pSMB
->SubCommand
= cpu_to_le16(TRANS2_QUERY_FS_INFORMATION
);
4168 pSMB
->InformationLevel
= cpu_to_le16(SMB_QUERY_FS_SIZE_INFO
);
4169 pSMB
->hdr
.smb_buf_length
+= byte_count
;
4170 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
4172 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
4173 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
4175 cFYI(1, ("Send error in QFSInfo = %d", rc
));
4176 } else { /* decode response */
4177 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
4179 if (rc
|| (pSMBr
->ByteCount
< 24))
4180 rc
= -EIO
; /* bad smb */
4182 __u16 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
4186 *) (((char *) &pSMBr
->hdr
.Protocol
) +
4189 le32_to_cpu(response_data
->BytesPerSector
) *
4190 le32_to_cpu(response_data
->
4191 SectorsPerAllocationUnit
);
4193 le64_to_cpu(response_data
->TotalAllocationUnits
);
4194 FSData
->f_bfree
= FSData
->f_bavail
=
4195 le64_to_cpu(response_data
->FreeAllocationUnits
);
4197 ("Blocks: %lld Free: %lld Block size %ld",
4198 (unsigned long long)FSData
->f_blocks
,
4199 (unsigned long long)FSData
->f_bfree
,
4203 cifs_buf_release(pSMB
);
4212 CIFSSMBQFSAttributeInfo(const int xid
, struct cifsTconInfo
*tcon
)
4214 /* level 0x105 SMB_QUERY_FILE_SYSTEM_INFO */
4215 TRANSACTION2_QFSI_REQ
*pSMB
= NULL
;
4216 TRANSACTION2_QFSI_RSP
*pSMBr
= NULL
;
4217 FILE_SYSTEM_ATTRIBUTE_INFO
*response_data
;
4219 int bytes_returned
= 0;
4220 __u16 params
, byte_count
;
4222 cFYI(1, ("In QFSAttributeInfo"));
4224 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
4229 params
= 2; /* level */
4230 pSMB
->TotalDataCount
= 0;
4231 pSMB
->MaxParameterCount
= cpu_to_le16(2);
4232 pSMB
->MaxDataCount
= cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
4233 pSMB
->MaxSetupCount
= 0;
4237 pSMB
->Reserved2
= 0;
4238 byte_count
= params
+ 1 /* pad */ ;
4239 pSMB
->TotalParameterCount
= cpu_to_le16(params
);
4240 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
4241 pSMB
->ParameterOffset
= cpu_to_le16(offsetof(
4242 struct smb_com_transaction2_qfsi_req
, InformationLevel
) - 4);
4243 pSMB
->DataCount
= 0;
4244 pSMB
->DataOffset
= 0;
4245 pSMB
->SetupCount
= 1;
4246 pSMB
->Reserved3
= 0;
4247 pSMB
->SubCommand
= cpu_to_le16(TRANS2_QUERY_FS_INFORMATION
);
4248 pSMB
->InformationLevel
= cpu_to_le16(SMB_QUERY_FS_ATTRIBUTE_INFO
);
4249 pSMB
->hdr
.smb_buf_length
+= byte_count
;
4250 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
4252 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
4253 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
4255 cERROR(1, ("Send error in QFSAttributeInfo = %d", rc
));
4256 } else { /* decode response */
4257 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
4259 if (rc
|| (pSMBr
->ByteCount
< 13)) {
4260 /* BB also check if enough bytes returned */
4261 rc
= -EIO
; /* bad smb */
4263 __u16 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
4265 (FILE_SYSTEM_ATTRIBUTE_INFO
4266 *) (((char *) &pSMBr
->hdr
.Protocol
) +
4268 memcpy(&tcon
->fsAttrInfo
, response_data
,
4269 sizeof(FILE_SYSTEM_ATTRIBUTE_INFO
));
4272 cifs_buf_release(pSMB
);
4275 goto QFSAttributeRetry
;
4281 CIFSSMBQFSDeviceInfo(const int xid
, struct cifsTconInfo
*tcon
)
4283 /* level 0x104 SMB_QUERY_FILE_SYSTEM_INFO */
4284 TRANSACTION2_QFSI_REQ
*pSMB
= NULL
;
4285 TRANSACTION2_QFSI_RSP
*pSMBr
= NULL
;
4286 FILE_SYSTEM_DEVICE_INFO
*response_data
;
4288 int bytes_returned
= 0;
4289 __u16 params
, byte_count
;
4291 cFYI(1, ("In QFSDeviceInfo"));
4293 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
4298 params
= 2; /* level */
4299 pSMB
->TotalDataCount
= 0;
4300 pSMB
->MaxParameterCount
= cpu_to_le16(2);
4301 pSMB
->MaxDataCount
= cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
4302 pSMB
->MaxSetupCount
= 0;
4306 pSMB
->Reserved2
= 0;
4307 byte_count
= params
+ 1 /* pad */ ;
4308 pSMB
->TotalParameterCount
= cpu_to_le16(params
);
4309 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
4310 pSMB
->ParameterOffset
= cpu_to_le16(offsetof(
4311 struct smb_com_transaction2_qfsi_req
, InformationLevel
) - 4);
4313 pSMB
->DataCount
= 0;
4314 pSMB
->DataOffset
= 0;
4315 pSMB
->SetupCount
= 1;
4316 pSMB
->Reserved3
= 0;
4317 pSMB
->SubCommand
= cpu_to_le16(TRANS2_QUERY_FS_INFORMATION
);
4318 pSMB
->InformationLevel
= cpu_to_le16(SMB_QUERY_FS_DEVICE_INFO
);
4319 pSMB
->hdr
.smb_buf_length
+= byte_count
;
4320 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
4322 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
4323 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
4325 cFYI(1, ("Send error in QFSDeviceInfo = %d", rc
));
4326 } else { /* decode response */
4327 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
4329 if (rc
|| (pSMBr
->ByteCount
< sizeof(FILE_SYSTEM_DEVICE_INFO
)))
4330 rc
= -EIO
; /* bad smb */
4332 __u16 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
4334 (FILE_SYSTEM_DEVICE_INFO
*)
4335 (((char *) &pSMBr
->hdr
.Protocol
) +
4337 memcpy(&tcon
->fsDevInfo
, response_data
,
4338 sizeof(FILE_SYSTEM_DEVICE_INFO
));
4341 cifs_buf_release(pSMB
);
4344 goto QFSDeviceRetry
;
4350 CIFSSMBQFSUnixInfo(const int xid
, struct cifsTconInfo
*tcon
)
4352 /* level 0x200 SMB_QUERY_CIFS_UNIX_INFO */
4353 TRANSACTION2_QFSI_REQ
*pSMB
= NULL
;
4354 TRANSACTION2_QFSI_RSP
*pSMBr
= NULL
;
4355 FILE_SYSTEM_UNIX_INFO
*response_data
;
4357 int bytes_returned
= 0;
4358 __u16 params
, byte_count
;
4360 cFYI(1, ("In QFSUnixInfo"));
4362 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
4367 params
= 2; /* level */
4368 pSMB
->TotalDataCount
= 0;
4369 pSMB
->DataCount
= 0;
4370 pSMB
->DataOffset
= 0;
4371 pSMB
->MaxParameterCount
= cpu_to_le16(2);
4372 pSMB
->MaxDataCount
= cpu_to_le16(100); /* BB find exact max SMB PDU from sess structure BB */
4373 pSMB
->MaxSetupCount
= 0;
4377 pSMB
->Reserved2
= 0;
4378 byte_count
= params
+ 1 /* pad */ ;
4379 pSMB
->ParameterCount
= cpu_to_le16(params
);
4380 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
4381 pSMB
->ParameterOffset
= cpu_to_le16(offsetof(struct
4382 smb_com_transaction2_qfsi_req
, InformationLevel
) - 4);
4383 pSMB
->SetupCount
= 1;
4384 pSMB
->Reserved3
= 0;
4385 pSMB
->SubCommand
= cpu_to_le16(TRANS2_QUERY_FS_INFORMATION
);
4386 pSMB
->InformationLevel
= cpu_to_le16(SMB_QUERY_CIFS_UNIX_INFO
);
4387 pSMB
->hdr
.smb_buf_length
+= byte_count
;
4388 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
4390 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
4391 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
4393 cERROR(1, ("Send error in QFSUnixInfo = %d", rc
));
4394 } else { /* decode response */
4395 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
4397 if (rc
|| (pSMBr
->ByteCount
< 13)) {
4398 rc
= -EIO
; /* bad smb */
4400 __u16 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
4402 (FILE_SYSTEM_UNIX_INFO
4403 *) (((char *) &pSMBr
->hdr
.Protocol
) +
4405 memcpy(&tcon
->fsUnixInfo
, response_data
,
4406 sizeof(FILE_SYSTEM_UNIX_INFO
));
4409 cifs_buf_release(pSMB
);
4419 CIFSSMBSetFSUnixInfo(const int xid
, struct cifsTconInfo
*tcon
, __u64 cap
)
4421 /* level 0x200 SMB_SET_CIFS_UNIX_INFO */
4422 TRANSACTION2_SETFSI_REQ
*pSMB
= NULL
;
4423 TRANSACTION2_SETFSI_RSP
*pSMBr
= NULL
;
4425 int bytes_returned
= 0;
4426 __u16 params
, param_offset
, offset
, byte_count
;
4428 cFYI(1, ("In SETFSUnixInfo"));
4430 /* BB switch to small buf init to save memory */
4431 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
4436 params
= 4; /* 2 bytes zero followed by info level. */
4437 pSMB
->MaxSetupCount
= 0;
4441 pSMB
->Reserved2
= 0;
4442 param_offset
= offsetof(struct smb_com_transaction2_setfsi_req
, FileNum
)
4444 offset
= param_offset
+ params
;
4446 pSMB
->MaxParameterCount
= cpu_to_le16(4);
4447 pSMB
->MaxDataCount
= cpu_to_le16(100); /* BB find exact max SMB PDU from sess structure BB */
4448 pSMB
->SetupCount
= 1;
4449 pSMB
->Reserved3
= 0;
4450 pSMB
->SubCommand
= cpu_to_le16(TRANS2_SET_FS_INFORMATION
);
4451 byte_count
= 1 /* pad */ + params
+ 12;
4453 pSMB
->DataCount
= cpu_to_le16(12);
4454 pSMB
->ParameterCount
= cpu_to_le16(params
);
4455 pSMB
->TotalDataCount
= pSMB
->DataCount
;
4456 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
4457 pSMB
->ParameterOffset
= cpu_to_le16(param_offset
);
4458 pSMB
->DataOffset
= cpu_to_le16(offset
);
4462 pSMB
->InformationLevel
= cpu_to_le16(SMB_SET_CIFS_UNIX_INFO
);
4465 pSMB
->ClientUnixMajor
= cpu_to_le16(CIFS_UNIX_MAJOR_VERSION
);
4466 pSMB
->ClientUnixMinor
= cpu_to_le16(CIFS_UNIX_MINOR_VERSION
);
4467 pSMB
->ClientUnixCap
= cpu_to_le64(cap
);
4469 pSMB
->hdr
.smb_buf_length
+= byte_count
;
4470 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
4472 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
4473 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
4475 cERROR(1, ("Send error in SETFSUnixInfo = %d", rc
));
4476 } else { /* decode response */
4477 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
4479 rc
= -EIO
; /* bad smb */
4481 cifs_buf_release(pSMB
);
4484 goto SETFSUnixRetry
;
4492 CIFSSMBQFSPosixInfo(const int xid
, struct cifsTconInfo
*tcon
,
4493 struct kstatfs
*FSData
)
4495 /* level 0x201 SMB_QUERY_CIFS_POSIX_INFO */
4496 TRANSACTION2_QFSI_REQ
*pSMB
= NULL
;
4497 TRANSACTION2_QFSI_RSP
*pSMBr
= NULL
;
4498 FILE_SYSTEM_POSIX_INFO
*response_data
;
4500 int bytes_returned
= 0;
4501 __u16 params
, byte_count
;
4503 cFYI(1, ("In QFSPosixInfo"));
4505 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
4510 params
= 2; /* level */
4511 pSMB
->TotalDataCount
= 0;
4512 pSMB
->DataCount
= 0;
4513 pSMB
->DataOffset
= 0;
4514 pSMB
->MaxParameterCount
= cpu_to_le16(2);
4515 pSMB
->MaxDataCount
= cpu_to_le16(100); /* BB find exact max SMB PDU from sess structure BB */
4516 pSMB
->MaxSetupCount
= 0;
4520 pSMB
->Reserved2
= 0;
4521 byte_count
= params
+ 1 /* pad */ ;
4522 pSMB
->ParameterCount
= cpu_to_le16(params
);
4523 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
4524 pSMB
->ParameterOffset
= cpu_to_le16(offsetof(struct
4525 smb_com_transaction2_qfsi_req
, InformationLevel
) - 4);
4526 pSMB
->SetupCount
= 1;
4527 pSMB
->Reserved3
= 0;
4528 pSMB
->SubCommand
= cpu_to_le16(TRANS2_QUERY_FS_INFORMATION
);
4529 pSMB
->InformationLevel
= cpu_to_le16(SMB_QUERY_POSIX_FS_INFO
);
4530 pSMB
->hdr
.smb_buf_length
+= byte_count
;
4531 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
4533 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
4534 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
4536 cFYI(1, ("Send error in QFSUnixInfo = %d", rc
));
4537 } else { /* decode response */
4538 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
4540 if (rc
|| (pSMBr
->ByteCount
< 13)) {
4541 rc
= -EIO
; /* bad smb */
4543 __u16 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
4545 (FILE_SYSTEM_POSIX_INFO
4546 *) (((char *) &pSMBr
->hdr
.Protocol
) +
4549 le32_to_cpu(response_data
->BlockSize
);
4551 le64_to_cpu(response_data
->TotalBlocks
);
4553 le64_to_cpu(response_data
->BlocksAvail
);
4554 if (response_data
->UserBlocksAvail
== cpu_to_le64(-1)) {
4555 FSData
->f_bavail
= FSData
->f_bfree
;
4558 le64_to_cpu(response_data
->UserBlocksAvail
);
4560 if (response_data
->TotalFileNodes
!= cpu_to_le64(-1))
4562 le64_to_cpu(response_data
->TotalFileNodes
);
4563 if (response_data
->FreeFileNodes
!= cpu_to_le64(-1))
4565 le64_to_cpu(response_data
->FreeFileNodes
);
4568 cifs_buf_release(pSMB
);
4577 /* We can not use write of zero bytes trick to
4578 set file size due to need for large file support. Also note that
4579 this SetPathInfo is preferred to SetFileInfo based method in next
4580 routine which is only needed to work around a sharing violation bug
4581 in Samba which this routine can run into */
4584 CIFSSMBSetEOF(const int xid
, struct cifsTconInfo
*tcon
, const char *fileName
,
4585 __u64 size
, int SetAllocation
,
4586 const struct nls_table
*nls_codepage
, int remap
)
4588 struct smb_com_transaction2_spi_req
*pSMB
= NULL
;
4589 struct smb_com_transaction2_spi_rsp
*pSMBr
= NULL
;
4590 struct file_end_of_file_info
*parm_data
;
4593 int bytes_returned
= 0;
4594 __u16 params
, byte_count
, data_count
, param_offset
, offset
;
4596 cFYI(1, ("In SetEOF"));
4598 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
4603 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
4605 cifsConvertToUCS((__le16
*) pSMB
->FileName
, fileName
,
4606 PATH_MAX
, nls_codepage
, remap
);
4607 name_len
++; /* trailing null */
4609 } else { /* BB improve the check for buffer overruns BB */
4610 name_len
= strnlen(fileName
, PATH_MAX
);
4611 name_len
++; /* trailing null */
4612 strncpy(pSMB
->FileName
, fileName
, name_len
);
4614 params
= 6 + name_len
;
4615 data_count
= sizeof(struct file_end_of_file_info
);
4616 pSMB
->MaxParameterCount
= cpu_to_le16(2);
4617 pSMB
->MaxDataCount
= cpu_to_le16(4100);
4618 pSMB
->MaxSetupCount
= 0;
4622 pSMB
->Reserved2
= 0;
4623 param_offset
= offsetof(struct smb_com_transaction2_spi_req
,
4624 InformationLevel
) - 4;
4625 offset
= param_offset
+ params
;
4626 if (SetAllocation
) {
4627 if (tcon
->ses
->capabilities
& CAP_INFOLEVEL_PASSTHRU
)
4628 pSMB
->InformationLevel
=
4629 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2
);
4631 pSMB
->InformationLevel
=
4632 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO
);
4633 } else /* Set File Size */ {
4634 if (tcon
->ses
->capabilities
& CAP_INFOLEVEL_PASSTHRU
)
4635 pSMB
->InformationLevel
=
4636 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO2
);
4638 pSMB
->InformationLevel
=
4639 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO
);
4643 (struct file_end_of_file_info
*) (((char *) &pSMB
->hdr
.Protocol
) +
4645 pSMB
->ParameterOffset
= cpu_to_le16(param_offset
);
4646 pSMB
->DataOffset
= cpu_to_le16(offset
);
4647 pSMB
->SetupCount
= 1;
4648 pSMB
->Reserved3
= 0;
4649 pSMB
->SubCommand
= cpu_to_le16(TRANS2_SET_PATH_INFORMATION
);
4650 byte_count
= 3 /* pad */ + params
+ data_count
;
4651 pSMB
->DataCount
= cpu_to_le16(data_count
);
4652 pSMB
->TotalDataCount
= pSMB
->DataCount
;
4653 pSMB
->ParameterCount
= cpu_to_le16(params
);
4654 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
4655 pSMB
->Reserved4
= 0;
4656 pSMB
->hdr
.smb_buf_length
+= byte_count
;
4657 parm_data
->FileSize
= cpu_to_le64(size
);
4658 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
4659 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
4660 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
4662 cFYI(1, ("SetPathInfo (file size) returned %d", rc
));
4664 cifs_buf_release(pSMB
);
4673 CIFSSMBSetFileSize(const int xid
, struct cifsTconInfo
*tcon
, __u64 size
,
4674 __u16 fid
, __u32 pid_of_opener
, int SetAllocation
)
4676 struct smb_com_transaction2_sfi_req
*pSMB
= NULL
;
4678 struct file_end_of_file_info
*parm_data
;
4680 __u16 params
, param_offset
, offset
, byte_count
, count
;
4682 cFYI(1, ("SetFileSize (via SetFileInfo) %lld",
4684 rc
= small_smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
);
4689 pSMB
->hdr
.Pid
= cpu_to_le16((__u16
)pid_of_opener
);
4690 pSMB
->hdr
.PidHigh
= cpu_to_le16((__u16
)(pid_of_opener
>> 16));
4693 pSMB
->MaxSetupCount
= 0;
4697 pSMB
->Reserved2
= 0;
4698 param_offset
= offsetof(struct smb_com_transaction2_sfi_req
, Fid
) - 4;
4699 offset
= param_offset
+ params
;
4701 data_offset
= (char *) (&pSMB
->hdr
.Protocol
) + offset
;
4703 count
= sizeof(struct file_end_of_file_info
);
4704 pSMB
->MaxParameterCount
= cpu_to_le16(2);
4705 pSMB
->MaxDataCount
= cpu_to_le16(1000); /* BB find max SMB PDU from sess */
4706 pSMB
->SetupCount
= 1;
4707 pSMB
->Reserved3
= 0;
4708 pSMB
->SubCommand
= cpu_to_le16(TRANS2_SET_FILE_INFORMATION
);
4709 byte_count
= 3 /* pad */ + params
+ count
;
4710 pSMB
->DataCount
= cpu_to_le16(count
);
4711 pSMB
->ParameterCount
= cpu_to_le16(params
);
4712 pSMB
->TotalDataCount
= pSMB
->DataCount
;
4713 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
4714 pSMB
->ParameterOffset
= cpu_to_le16(param_offset
);
4716 (struct file_end_of_file_info
*) (((char *) &pSMB
->hdr
.Protocol
)
4718 pSMB
->DataOffset
= cpu_to_le16(offset
);
4719 parm_data
->FileSize
= cpu_to_le64(size
);
4721 if (SetAllocation
) {
4722 if (tcon
->ses
->capabilities
& CAP_INFOLEVEL_PASSTHRU
)
4723 pSMB
->InformationLevel
=
4724 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2
);
4726 pSMB
->InformationLevel
=
4727 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO
);
4728 } else /* Set File Size */ {
4729 if (tcon
->ses
->capabilities
& CAP_INFOLEVEL_PASSTHRU
)
4730 pSMB
->InformationLevel
=
4731 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO2
);
4733 pSMB
->InformationLevel
=
4734 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO
);
4736 pSMB
->Reserved4
= 0;
4737 pSMB
->hdr
.smb_buf_length
+= byte_count
;
4738 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
4739 rc
= SendReceiveNoRsp(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
, 0);
4742 ("Send error in SetFileInfo (SetFileSize) = %d",
4746 /* Note: On -EAGAIN error only caller can retry on handle based calls
4747 since file handle passed in no longer valid */
4752 /* Some legacy servers such as NT4 require that the file times be set on
4753 an open handle, rather than by pathname - this is awkward due to
4754 potential access conflicts on the open, but it is unavoidable for these
4755 old servers since the only other choice is to go from 100 nanosecond DCE
4756 time and resort to the original setpathinfo level which takes the ancient
4757 DOS time format with 2 second granularity */
4759 CIFSSMBSetFileTimes(const int xid
, struct cifsTconInfo
*tcon
,
4760 const FILE_BASIC_INFO
*data
, __u16 fid
)
4762 struct smb_com_transaction2_sfi_req
*pSMB
= NULL
;
4765 __u16 params
, param_offset
, offset
, byte_count
, count
;
4767 cFYI(1, ("Set Times (via SetFileInfo)"));
4768 rc
= small_smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
);
4773 /* At this point there is no need to override the current pid
4774 with the pid of the opener, but that could change if we someday
4775 use an existing handle (rather than opening one on the fly) */
4776 /* pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
4777 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));*/
4780 pSMB
->MaxSetupCount
= 0;
4784 pSMB
->Reserved2
= 0;
4785 param_offset
= offsetof(struct smb_com_transaction2_sfi_req
, Fid
) - 4;
4786 offset
= param_offset
+ params
;
4788 data_offset
= (char *) (&pSMB
->hdr
.Protocol
) + offset
;
4790 count
= sizeof(FILE_BASIC_INFO
);
4791 pSMB
->MaxParameterCount
= cpu_to_le16(2);
4792 pSMB
->MaxDataCount
= cpu_to_le16(1000); /* BB find max SMB PDU from sess */
4793 pSMB
->SetupCount
= 1;
4794 pSMB
->Reserved3
= 0;
4795 pSMB
->SubCommand
= cpu_to_le16(TRANS2_SET_FILE_INFORMATION
);
4796 byte_count
= 3 /* pad */ + params
+ count
;
4797 pSMB
->DataCount
= cpu_to_le16(count
);
4798 pSMB
->ParameterCount
= cpu_to_le16(params
);
4799 pSMB
->TotalDataCount
= pSMB
->DataCount
;
4800 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
4801 pSMB
->ParameterOffset
= cpu_to_le16(param_offset
);
4802 pSMB
->DataOffset
= cpu_to_le16(offset
);
4804 if (tcon
->ses
->capabilities
& CAP_INFOLEVEL_PASSTHRU
)
4805 pSMB
->InformationLevel
= cpu_to_le16(SMB_SET_FILE_BASIC_INFO2
);
4807 pSMB
->InformationLevel
= cpu_to_le16(SMB_SET_FILE_BASIC_INFO
);
4808 pSMB
->Reserved4
= 0;
4809 pSMB
->hdr
.smb_buf_length
+= byte_count
;
4810 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
4811 memcpy(data_offset
, data
, sizeof(FILE_BASIC_INFO
));
4812 rc
= SendReceiveNoRsp(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
, 0);
4814 cFYI(1, ("Send error in Set Time (SetFileInfo) = %d", rc
));
4816 /* Note: On -EAGAIN error only caller can retry on handle based calls
4817 since file handle passed in no longer valid */
4824 CIFSSMBSetTimes(const int xid
, struct cifsTconInfo
*tcon
, const char *fileName
,
4825 const FILE_BASIC_INFO
*data
,
4826 const struct nls_table
*nls_codepage
, int remap
)
4828 TRANSACTION2_SPI_REQ
*pSMB
= NULL
;
4829 TRANSACTION2_SPI_RSP
*pSMBr
= NULL
;
4832 int bytes_returned
= 0;
4834 __u16 params
, param_offset
, offset
, byte_count
, count
;
4836 cFYI(1, ("In SetTimes"));
4839 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
4844 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
4846 cifsConvertToUCS((__le16
*) pSMB
->FileName
, fileName
,
4847 PATH_MAX
, nls_codepage
, remap
);
4848 name_len
++; /* trailing null */
4850 } else { /* BB improve the check for buffer overruns BB */
4851 name_len
= strnlen(fileName
, PATH_MAX
);
4852 name_len
++; /* trailing null */
4853 strncpy(pSMB
->FileName
, fileName
, name_len
);
4856 params
= 6 + name_len
;
4857 count
= sizeof(FILE_BASIC_INFO
);
4858 pSMB
->MaxParameterCount
= cpu_to_le16(2);
4859 pSMB
->MaxDataCount
= cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
4860 pSMB
->MaxSetupCount
= 0;
4864 pSMB
->Reserved2
= 0;
4865 param_offset
= offsetof(struct smb_com_transaction2_spi_req
,
4866 InformationLevel
) - 4;
4867 offset
= param_offset
+ params
;
4868 data_offset
= (char *) (&pSMB
->hdr
.Protocol
) + offset
;
4869 pSMB
->ParameterOffset
= cpu_to_le16(param_offset
);
4870 pSMB
->DataOffset
= cpu_to_le16(offset
);
4871 pSMB
->SetupCount
= 1;
4872 pSMB
->Reserved3
= 0;
4873 pSMB
->SubCommand
= cpu_to_le16(TRANS2_SET_PATH_INFORMATION
);
4874 byte_count
= 3 /* pad */ + params
+ count
;
4876 pSMB
->DataCount
= cpu_to_le16(count
);
4877 pSMB
->ParameterCount
= cpu_to_le16(params
);
4878 pSMB
->TotalDataCount
= pSMB
->DataCount
;
4879 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
4880 if (tcon
->ses
->capabilities
& CAP_INFOLEVEL_PASSTHRU
)
4881 pSMB
->InformationLevel
= cpu_to_le16(SMB_SET_FILE_BASIC_INFO2
);
4883 pSMB
->InformationLevel
= cpu_to_le16(SMB_SET_FILE_BASIC_INFO
);
4884 pSMB
->Reserved4
= 0;
4885 pSMB
->hdr
.smb_buf_length
+= byte_count
;
4886 memcpy(data_offset
, data
, sizeof(FILE_BASIC_INFO
));
4887 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
4888 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
4889 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
4891 cFYI(1, ("SetPathInfo (times) returned %d", rc
));
4893 cifs_buf_release(pSMB
);
4901 /* Can not be used to set time stamps yet (due to old DOS time format) */
4902 /* Can be used to set attributes */
4903 #if 0 /* Possibly not needed - since it turns out that strangely NT4 has a bug
4904 handling it anyway and NT4 was what we thought it would be needed for
4905 Do not delete it until we prove whether needed for Win9x though */
4907 CIFSSMBSetAttrLegacy(int xid
, struct cifsTconInfo
*tcon
, char *fileName
,
4908 __u16 dos_attrs
, const struct nls_table
*nls_codepage
)
4910 SETATTR_REQ
*pSMB
= NULL
;
4911 SETATTR_RSP
*pSMBr
= NULL
;
4916 cFYI(1, ("In SetAttrLegacy"));
4919 rc
= smb_init(SMB_COM_SETATTR
, 8, tcon
, (void **) &pSMB
,
4924 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
4926 ConvertToUCS((__le16
*) pSMB
->fileName
, fileName
,
4927 PATH_MAX
, nls_codepage
);
4928 name_len
++; /* trailing null */
4930 } else { /* BB improve the check for buffer overruns BB */
4931 name_len
= strnlen(fileName
, PATH_MAX
);
4932 name_len
++; /* trailing null */
4933 strncpy(pSMB
->fileName
, fileName
, name_len
);
4935 pSMB
->attr
= cpu_to_le16(dos_attrs
);
4936 pSMB
->BufferFormat
= 0x04;
4937 pSMB
->hdr
.smb_buf_length
+= name_len
+ 1;
4938 pSMB
->ByteCount
= cpu_to_le16(name_len
+ 1);
4939 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
4940 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
4942 cFYI(1, ("Error in LegacySetAttr = %d", rc
));
4944 cifs_buf_release(pSMB
);
4947 goto SetAttrLgcyRetry
;
4951 #endif /* temporarily unneeded SetAttr legacy function */
4954 CIFSSMBUnixSetPerms(const int xid
, struct cifsTconInfo
*tcon
,
4955 char *fileName
, __u64 mode
, __u64 uid
, __u64 gid
,
4956 dev_t device
, const struct nls_table
*nls_codepage
,
4959 TRANSACTION2_SPI_REQ
*pSMB
= NULL
;
4960 TRANSACTION2_SPI_RSP
*pSMBr
= NULL
;
4963 int bytes_returned
= 0;
4964 FILE_UNIX_BASIC_INFO
*data_offset
;
4965 __u16 params
, param_offset
, offset
, count
, byte_count
;
4967 cFYI(1, ("In SetUID/GID/Mode"));
4969 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
4974 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
4976 cifsConvertToUCS((__le16
*) pSMB
->FileName
, fileName
,
4977 PATH_MAX
, nls_codepage
, remap
);
4978 name_len
++; /* trailing null */
4980 } else { /* BB improve the check for buffer overruns BB */
4981 name_len
= strnlen(fileName
, PATH_MAX
);
4982 name_len
++; /* trailing null */
4983 strncpy(pSMB
->FileName
, fileName
, name_len
);
4986 params
= 6 + name_len
;
4987 count
= sizeof(FILE_UNIX_BASIC_INFO
);
4988 pSMB
->MaxParameterCount
= cpu_to_le16(2);
4989 pSMB
->MaxDataCount
= cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
4990 pSMB
->MaxSetupCount
= 0;
4994 pSMB
->Reserved2
= 0;
4995 param_offset
= offsetof(struct smb_com_transaction2_spi_req
,
4996 InformationLevel
) - 4;
4997 offset
= param_offset
+ params
;
4999 (FILE_UNIX_BASIC_INFO
*) ((char *) &pSMB
->hdr
.Protocol
+
5001 memset(data_offset
, 0, count
);
5002 pSMB
->DataOffset
= cpu_to_le16(offset
);
5003 pSMB
->ParameterOffset
= cpu_to_le16(param_offset
);
5004 pSMB
->SetupCount
= 1;
5005 pSMB
->Reserved3
= 0;
5006 pSMB
->SubCommand
= cpu_to_le16(TRANS2_SET_PATH_INFORMATION
);
5007 byte_count
= 3 /* pad */ + params
+ count
;
5008 pSMB
->ParameterCount
= cpu_to_le16(params
);
5009 pSMB
->DataCount
= cpu_to_le16(count
);
5010 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
5011 pSMB
->TotalDataCount
= pSMB
->DataCount
;
5012 pSMB
->InformationLevel
= cpu_to_le16(SMB_SET_FILE_UNIX_BASIC
);
5013 pSMB
->Reserved4
= 0;
5014 pSMB
->hdr
.smb_buf_length
+= byte_count
;
5015 /* Samba server ignores set of file size to zero due to bugs in some
5016 older clients, but we should be precise - we use SetFileSize to
5017 set file size and do not want to truncate file size to zero
5018 accidently as happened on one Samba server beta by putting
5019 zero instead of -1 here */
5020 data_offset
->EndOfFile
= NO_CHANGE_64
;
5021 data_offset
->NumOfBytes
= NO_CHANGE_64
;
5022 data_offset
->LastStatusChange
= NO_CHANGE_64
;
5023 data_offset
->LastAccessTime
= NO_CHANGE_64
;
5024 data_offset
->LastModificationTime
= NO_CHANGE_64
;
5025 data_offset
->Uid
= cpu_to_le64(uid
);
5026 data_offset
->Gid
= cpu_to_le64(gid
);
5027 /* better to leave device as zero when it is */
5028 data_offset
->DevMajor
= cpu_to_le64(MAJOR(device
));
5029 data_offset
->DevMinor
= cpu_to_le64(MINOR(device
));
5030 data_offset
->Permissions
= cpu_to_le64(mode
);
5033 data_offset
->Type
= cpu_to_le32(UNIX_FILE
);
5034 else if (S_ISDIR(mode
))
5035 data_offset
->Type
= cpu_to_le32(UNIX_DIR
);
5036 else if (S_ISLNK(mode
))
5037 data_offset
->Type
= cpu_to_le32(UNIX_SYMLINK
);
5038 else if (S_ISCHR(mode
))
5039 data_offset
->Type
= cpu_to_le32(UNIX_CHARDEV
);
5040 else if (S_ISBLK(mode
))
5041 data_offset
->Type
= cpu_to_le32(UNIX_BLOCKDEV
);
5042 else if (S_ISFIFO(mode
))
5043 data_offset
->Type
= cpu_to_le32(UNIX_FIFO
);
5044 else if (S_ISSOCK(mode
))
5045 data_offset
->Type
= cpu_to_le32(UNIX_SOCKET
);
5048 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
5049 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
5050 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
5052 cFYI(1, ("SetPathInfo (perms) returned %d", rc
));
5055 cifs_buf_release(pSMB
);
5061 int CIFSSMBNotify(const int xid
, struct cifsTconInfo
*tcon
,
5062 const int notify_subdirs
, const __u16 netfid
,
5063 __u32 filter
, struct file
*pfile
, int multishot
,
5064 const struct nls_table
*nls_codepage
)
5067 struct smb_com_transaction_change_notify_req
*pSMB
= NULL
;
5068 struct smb_com_ntransaction_change_notify_rsp
*pSMBr
= NULL
;
5069 struct dir_notify_req
*dnotify_req
;
5072 cFYI(1, ("In CIFSSMBNotify for file handle %d", (int)netfid
));
5073 rc
= smb_init(SMB_COM_NT_TRANSACT
, 23, tcon
, (void **) &pSMB
,
5078 pSMB
->TotalParameterCount
= 0 ;
5079 pSMB
->TotalDataCount
= 0;
5080 pSMB
->MaxParameterCount
= cpu_to_le32(2);
5081 /* BB find exact data count max from sess structure BB */
5082 pSMB
->MaxDataCount
= 0; /* same in little endian or be */
5083 /* BB VERIFY verify which is correct for above BB */
5084 pSMB
->MaxDataCount
= cpu_to_le32((tcon
->ses
->server
->maxBuf
-
5085 MAX_CIFS_HDR_SIZE
) & 0xFFFFFF00);
5087 pSMB
->MaxSetupCount
= 4;
5089 pSMB
->ParameterOffset
= 0;
5090 pSMB
->DataCount
= 0;
5091 pSMB
->DataOffset
= 0;
5092 pSMB
->SetupCount
= 4; /* single byte does not need le conversion */
5093 pSMB
->SubCommand
= cpu_to_le16(NT_TRANSACT_NOTIFY_CHANGE
);
5094 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
5096 pSMB
->WatchTree
= 1; /* one byte - no le conversion needed */
5097 pSMB
->Reserved2
= 0;
5098 pSMB
->CompletionFilter
= cpu_to_le32(filter
);
5099 pSMB
->Fid
= netfid
; /* file handle always le */
5100 pSMB
->ByteCount
= 0;
5102 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
5103 (struct smb_hdr
*)pSMBr
, &bytes_returned
,
5106 cFYI(1, ("Error in Notify = %d", rc
));
5108 /* Add file to outstanding requests */
5109 /* BB change to kmem cache alloc */
5110 dnotify_req
= kmalloc(
5111 sizeof(struct dir_notify_req
),
5114 dnotify_req
->Pid
= pSMB
->hdr
.Pid
;
5115 dnotify_req
->PidHigh
= pSMB
->hdr
.PidHigh
;
5116 dnotify_req
->Mid
= pSMB
->hdr
.Mid
;
5117 dnotify_req
->Tid
= pSMB
->hdr
.Tid
;
5118 dnotify_req
->Uid
= pSMB
->hdr
.Uid
;
5119 dnotify_req
->netfid
= netfid
;
5120 dnotify_req
->pfile
= pfile
;
5121 dnotify_req
->filter
= filter
;
5122 dnotify_req
->multishot
= multishot
;
5123 spin_lock(&GlobalMid_Lock
);
5124 list_add_tail(&dnotify_req
->lhead
,
5125 &GlobalDnotifyReqList
);
5126 spin_unlock(&GlobalMid_Lock
);
5130 cifs_buf_release(pSMB
);
5133 #ifdef CONFIG_CIFS_XATTR
5135 CIFSSMBQAllEAs(const int xid
, struct cifsTconInfo
*tcon
,
5136 const unsigned char *searchName
,
5137 char *EAData
, size_t buf_size
,
5138 const struct nls_table
*nls_codepage
, int remap
)
5140 /* BB assumes one setup word */
5141 TRANSACTION2_QPI_REQ
*pSMB
= NULL
;
5142 TRANSACTION2_QPI_RSP
*pSMBr
= NULL
;
5146 struct fea
*temp_fea
;
5148 __u16 params
, byte_count
;
5150 cFYI(1, ("In Query All EAs path %s", searchName
));
5152 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
5157 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
5159 cifsConvertToUCS((__le16
*) pSMB
->FileName
, searchName
,
5160 PATH_MAX
, nls_codepage
, remap
);
5161 name_len
++; /* trailing null */
5163 } else { /* BB improve the check for buffer overruns BB */
5164 name_len
= strnlen(searchName
, PATH_MAX
);
5165 name_len
++; /* trailing null */
5166 strncpy(pSMB
->FileName
, searchName
, name_len
);
5169 params
= 2 /* level */ + 4 /* reserved */ + name_len
/* includes NUL */;
5170 pSMB
->TotalDataCount
= 0;
5171 pSMB
->MaxParameterCount
= cpu_to_le16(2);
5172 pSMB
->MaxDataCount
= cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
5173 pSMB
->MaxSetupCount
= 0;
5177 pSMB
->Reserved2
= 0;
5178 pSMB
->ParameterOffset
= cpu_to_le16(offsetof(
5179 struct smb_com_transaction2_qpi_req
, InformationLevel
) - 4);
5180 pSMB
->DataCount
= 0;
5181 pSMB
->DataOffset
= 0;
5182 pSMB
->SetupCount
= 1;
5183 pSMB
->Reserved3
= 0;
5184 pSMB
->SubCommand
= cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION
);
5185 byte_count
= params
+ 1 /* pad */ ;
5186 pSMB
->TotalParameterCount
= cpu_to_le16(params
);
5187 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
5188 pSMB
->InformationLevel
= cpu_to_le16(SMB_INFO_QUERY_ALL_EAS
);
5189 pSMB
->Reserved4
= 0;
5190 pSMB
->hdr
.smb_buf_length
+= byte_count
;
5191 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
5193 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
5194 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
5196 cFYI(1, ("Send error in QueryAllEAs = %d", rc
));
5197 } else { /* decode response */
5198 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
5200 /* BB also check enough total bytes returned */
5201 /* BB we need to improve the validity checking
5202 of these trans2 responses */
5203 if (rc
|| (pSMBr
->ByteCount
< 4))
5204 rc
= -EIO
; /* bad smb */
5205 /* else if (pFindData){
5206 memcpy((char *) pFindData,
5207 (char *) &pSMBr->hdr.Protocol +
5210 /* check that length of list is not more than bcc */
5211 /* check that each entry does not go beyond length
5213 /* check that each element of each entry does not
5214 go beyond end of list */
5215 __u16 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
5216 struct fealist
*ea_response_data
;
5218 /* validate_trans2_offsets() */
5219 /* BB check if start of smb + data_offset > &bcc+ bcc */
5220 ea_response_data
= (struct fealist
*)
5221 (((char *) &pSMBr
->hdr
.Protocol
) +
5223 name_len
= le32_to_cpu(ea_response_data
->list_len
);
5224 cFYI(1, ("ea length %d", name_len
));
5225 if (name_len
<= 8) {
5226 /* returned EA size zeroed at top of function */
5227 cFYI(1, ("empty EA list returned from server"));
5229 /* account for ea list len */
5231 temp_fea
= ea_response_data
->list
;
5232 temp_ptr
= (char *)temp_fea
;
5233 while (name_len
> 0) {
5237 rc
+= temp_fea
->name_len
;
5238 /* account for prefix user. and trailing null */
5240 if (rc
< (int)buf_size
) {
5241 memcpy(EAData
, "user.", 5);
5243 memcpy(EAData
, temp_ptr
,
5244 temp_fea
->name_len
);
5245 EAData
+= temp_fea
->name_len
;
5246 /* null terminate name */
5248 EAData
= EAData
+ 1;
5249 } else if (buf_size
== 0) {
5250 /* skip copy - calc size only */
5252 /* stop before overrun buffer */
5256 name_len
-= temp_fea
->name_len
;
5257 temp_ptr
+= temp_fea
->name_len
;
5258 /* account for trailing null */
5262 le16_to_cpu(temp_fea
->value_len
);
5263 name_len
-= value_len
;
5264 temp_ptr
+= value_len
;
5265 /* BB check that temp_ptr is still
5268 /* no trailing null to account for
5270 /* go on to next EA */
5271 temp_fea
= (struct fea
*)temp_ptr
;
5277 cifs_buf_release(pSMB
);
5284 ssize_t
CIFSSMBQueryEA(const int xid
, struct cifsTconInfo
*tcon
,
5285 const unsigned char *searchName
, const unsigned char *ea_name
,
5286 unsigned char *ea_value
, size_t buf_size
,
5287 const struct nls_table
*nls_codepage
, int remap
)
5289 TRANSACTION2_QPI_REQ
*pSMB
= NULL
;
5290 TRANSACTION2_QPI_RSP
*pSMBr
= NULL
;
5294 struct fea
*temp_fea
;
5296 __u16 params
, byte_count
;
5298 cFYI(1, ("In Query EA path %s", searchName
));
5300 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
5305 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
5307 cifsConvertToUCS((__le16
*) pSMB
->FileName
, searchName
,
5308 PATH_MAX
, nls_codepage
, remap
);
5309 name_len
++; /* trailing null */
5311 } else { /* BB improve the check for buffer overruns BB */
5312 name_len
= strnlen(searchName
, PATH_MAX
);
5313 name_len
++; /* trailing null */
5314 strncpy(pSMB
->FileName
, searchName
, name_len
);
5317 params
= 2 /* level */ + 4 /* reserved */ + name_len
/* includes NUL */;
5318 pSMB
->TotalDataCount
= 0;
5319 pSMB
->MaxParameterCount
= cpu_to_le16(2);
5320 pSMB
->MaxDataCount
= cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
5321 pSMB
->MaxSetupCount
= 0;
5325 pSMB
->Reserved2
= 0;
5326 pSMB
->ParameterOffset
= cpu_to_le16(offsetof(
5327 struct smb_com_transaction2_qpi_req
, InformationLevel
) - 4);
5328 pSMB
->DataCount
= 0;
5329 pSMB
->DataOffset
= 0;
5330 pSMB
->SetupCount
= 1;
5331 pSMB
->Reserved3
= 0;
5332 pSMB
->SubCommand
= cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION
);
5333 byte_count
= params
+ 1 /* pad */ ;
5334 pSMB
->TotalParameterCount
= cpu_to_le16(params
);
5335 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
5336 pSMB
->InformationLevel
= cpu_to_le16(SMB_INFO_QUERY_ALL_EAS
);
5337 pSMB
->Reserved4
= 0;
5338 pSMB
->hdr
.smb_buf_length
+= byte_count
;
5339 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
5341 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
5342 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
5344 cFYI(1, ("Send error in Query EA = %d", rc
));
5345 } else { /* decode response */
5346 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
5348 /* BB also check enough total bytes returned */
5349 /* BB we need to improve the validity checking
5350 of these trans2 responses */
5351 if (rc
|| (pSMBr
->ByteCount
< 4))
5352 rc
= -EIO
; /* bad smb */
5353 /* else if (pFindData){
5354 memcpy((char *) pFindData,
5355 (char *) &pSMBr->hdr.Protocol +
5358 /* check that length of list is not more than bcc */
5359 /* check that each entry does not go beyond length
5361 /* check that each element of each entry does not
5362 go beyond end of list */
5363 __u16 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
5364 struct fealist
*ea_response_data
;
5366 /* validate_trans2_offsets() */
5367 /* BB check if start of smb + data_offset > &bcc+ bcc*/
5368 ea_response_data
= (struct fealist
*)
5369 (((char *) &pSMBr
->hdr
.Protocol
) +
5371 name_len
= le32_to_cpu(ea_response_data
->list_len
);
5372 cFYI(1, ("ea length %d", name_len
));
5373 if (name_len
<= 8) {
5374 /* returned EA size zeroed at top of function */
5375 cFYI(1, ("empty EA list returned from server"));
5377 /* account for ea list len */
5379 temp_fea
= ea_response_data
->list
;
5380 temp_ptr
= (char *)temp_fea
;
5381 /* loop through checking if we have a matching
5382 name and then return the associated value */
5383 while (name_len
> 0) {
5388 le16_to_cpu(temp_fea
->value_len
);
5389 /* BB validate that value_len falls within SMB,
5390 even though maximum for name_len is 255 */
5391 if (memcmp(temp_fea
->name
, ea_name
,
5392 temp_fea
->name_len
) == 0) {
5395 /* account for prefix user. and trailing null */
5396 if (rc
<= (int)buf_size
) {
5398 temp_fea
->name
+temp_fea
->name_len
+1,
5400 /* ea values, unlike ea
5403 } else if (buf_size
== 0) {
5404 /* skip copy - calc size only */
5406 /* stop before overrun buffer */
5411 name_len
-= temp_fea
->name_len
;
5412 temp_ptr
+= temp_fea
->name_len
;
5413 /* account for trailing null */
5416 name_len
-= value_len
;
5417 temp_ptr
+= value_len
;
5418 /* No trailing null to account for in
5419 value_len. Go on to next EA */
5420 temp_fea
= (struct fea
*)temp_ptr
;
5426 cifs_buf_release(pSMB
);
5434 CIFSSMBSetEA(const int xid
, struct cifsTconInfo
*tcon
, const char *fileName
,
5435 const char *ea_name
, const void *ea_value
,
5436 const __u16 ea_value_len
, const struct nls_table
*nls_codepage
,
5439 struct smb_com_transaction2_spi_req
*pSMB
= NULL
;
5440 struct smb_com_transaction2_spi_rsp
*pSMBr
= NULL
;
5441 struct fealist
*parm_data
;
5444 int bytes_returned
= 0;
5445 __u16 params
, param_offset
, byte_count
, offset
, count
;
5447 cFYI(1, ("In SetEA"));
5449 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
5454 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
5456 cifsConvertToUCS((__le16
*) pSMB
->FileName
, fileName
,
5457 PATH_MAX
, nls_codepage
, remap
);
5458 name_len
++; /* trailing null */
5460 } else { /* BB improve the check for buffer overruns BB */
5461 name_len
= strnlen(fileName
, PATH_MAX
);
5462 name_len
++; /* trailing null */
5463 strncpy(pSMB
->FileName
, fileName
, name_len
);
5466 params
= 6 + name_len
;
5468 /* done calculating parms using name_len of file name,
5469 now use name_len to calculate length of ea name
5470 we are going to create in the inode xattrs */
5471 if (ea_name
== NULL
)
5474 name_len
= strnlen(ea_name
, 255);
5476 count
= sizeof(*parm_data
) + ea_value_len
+ name_len
;
5477 pSMB
->MaxParameterCount
= cpu_to_le16(2);
5478 pSMB
->MaxDataCount
= cpu_to_le16(1000); /* BB find max SMB size from sess */
5479 pSMB
->MaxSetupCount
= 0;
5483 pSMB
->Reserved2
= 0;
5484 param_offset
= offsetof(struct smb_com_transaction2_spi_req
,
5485 InformationLevel
) - 4;
5486 offset
= param_offset
+ params
;
5487 pSMB
->InformationLevel
=
5488 cpu_to_le16(SMB_SET_FILE_EA
);
5491 (struct fealist
*) (((char *) &pSMB
->hdr
.Protocol
) +
5493 pSMB
->ParameterOffset
= cpu_to_le16(param_offset
);
5494 pSMB
->DataOffset
= cpu_to_le16(offset
);
5495 pSMB
->SetupCount
= 1;
5496 pSMB
->Reserved3
= 0;
5497 pSMB
->SubCommand
= cpu_to_le16(TRANS2_SET_PATH_INFORMATION
);
5498 byte_count
= 3 /* pad */ + params
+ count
;
5499 pSMB
->DataCount
= cpu_to_le16(count
);
5500 parm_data
->list_len
= cpu_to_le32(count
);
5501 parm_data
->list
[0].EA_flags
= 0;
5502 /* we checked above that name len is less than 255 */
5503 parm_data
->list
[0].name_len
= (__u8
)name_len
;
5504 /* EA names are always ASCII */
5506 strncpy(parm_data
->list
[0].name
, ea_name
, name_len
);
5507 parm_data
->list
[0].name
[name_len
] = 0;
5508 parm_data
->list
[0].value_len
= cpu_to_le16(ea_value_len
);
5509 /* caller ensures that ea_value_len is less than 64K but
5510 we need to ensure that it fits within the smb */
5512 /*BB add length check to see if it would fit in
5513 negotiated SMB buffer size BB */
5514 /* if (ea_value_len > buffer_size - 512 (enough for header)) */
5516 memcpy(parm_data
->list
[0].name
+name_len
+1,
5517 ea_value
, ea_value_len
);
5519 pSMB
->TotalDataCount
= pSMB
->DataCount
;
5520 pSMB
->ParameterCount
= cpu_to_le16(params
);
5521 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
5522 pSMB
->Reserved4
= 0;
5523 pSMB
->hdr
.smb_buf_length
+= byte_count
;
5524 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
5525 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
5526 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
5528 cFYI(1, ("SetPathInfo (EA) returned %d", rc
));
5530 cifs_buf_release(pSMB
);