4 * Copyright (C) International Business Machines Corp., 2002,2007
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 /* If the return code is zero, this function must fill in request_buf pointer */
107 small_smb_init(int smb_command
, int wct
, struct cifsTconInfo
*tcon
,
108 void **request_buf
/* returned */)
112 /* SMBs NegProt, SessSetup, uLogoff do not have tcon yet so
113 check for tcp and smb session status done differently
114 for those three - in the calling routine */
116 if (tcon
->tidStatus
== CifsExiting
) {
117 /* only tree disconnect, open, and write,
118 (and ulogoff which does not have tcon)
119 are allowed as we start force umount */
120 if ((smb_command
!= SMB_COM_WRITE_ANDX
) &&
121 (smb_command
!= SMB_COM_OPEN_ANDX
) &&
122 (smb_command
!= SMB_COM_TREE_DISCONNECT
)) {
123 cFYI(1, ("can not send cmd %d while umounting",
128 if ((tcon
->ses
) && (tcon
->ses
->status
!= CifsExiting
) &&
129 (tcon
->ses
->server
)) {
130 struct nls_table
*nls_codepage
;
131 /* Give Demultiplex thread up to 10 seconds to
132 reconnect, should be greater than cifs socket
133 timeout which is 7 seconds */
134 while (tcon
->ses
->server
->tcpStatus
==
136 wait_event_interruptible_timeout(tcon
->ses
->server
->response_q
,
137 (tcon
->ses
->server
->tcpStatus
==
139 if (tcon
->ses
->server
->tcpStatus
==
141 /* on "soft" mounts we wait once */
142 if ((tcon
->retry
== FALSE
) ||
143 (tcon
->ses
->status
== CifsExiting
)) {
144 cFYI(1, ("gave up waiting on "
145 "reconnect in smb_init"));
147 } /* else "hard" mount - keep retrying
148 until process is killed or server
149 comes back on-line */
150 } else /* TCP session is reestablished now */
154 nls_codepage
= load_nls_default();
155 /* need to prevent multiple threads trying to
156 simultaneously reconnect the same SMB session */
157 down(&tcon
->ses
->sesSem
);
158 if (tcon
->ses
->status
== CifsNeedReconnect
)
159 rc
= cifs_setup_session(0, tcon
->ses
,
161 if (!rc
&& (tcon
->tidStatus
== CifsNeedReconnect
)) {
162 mark_open_files_invalid(tcon
);
163 rc
= CIFSTCon(0, tcon
->ses
, tcon
->treeName
,
165 up(&tcon
->ses
->sesSem
);
166 /* tell server which Unix caps we support */
167 if (tcon
->ses
->capabilities
& CAP_UNIX
)
168 reset_cifs_unix_caps(0 /* no xid */,
170 NULL
/* we do not know sb */,
171 NULL
/* no vol info */);
172 /* BB FIXME add code to check if wsize needs
173 update due to negotiated smb buffer size
176 atomic_inc(&tconInfoReconnectCount
);
178 cFYI(1, ("reconnect tcon rc = %d", rc
));
179 /* Removed call to reopen open files here.
180 It is safer (and faster) to reopen files
181 one at a time as needed in read and write */
183 /* Check if handle based operation so we
184 know whether we can continue or not without
185 returning to caller to reset file handle */
186 switch (smb_command
) {
187 case SMB_COM_READ_ANDX
:
188 case SMB_COM_WRITE_ANDX
:
190 case SMB_COM_FIND_CLOSE2
:
191 case SMB_COM_LOCKING_ANDX
: {
192 unload_nls(nls_codepage
);
197 up(&tcon
->ses
->sesSem
);
199 unload_nls(nls_codepage
);
208 *request_buf
= cifs_small_buf_get();
209 if (*request_buf
== NULL
) {
210 /* BB should we add a retry in here if not a writepage? */
214 header_assemble((struct smb_hdr
*) *request_buf
, smb_command
,
218 cifs_stats_inc(&tcon
->num_smbs_sent
);
224 small_smb_init_no_tc(const int smb_command
, const int wct
,
225 struct cifsSesInfo
*ses
, void **request_buf
)
228 struct smb_hdr
*buffer
;
230 rc
= small_smb_init(smb_command
, wct
, NULL
, request_buf
);
234 buffer
= (struct smb_hdr
*)*request_buf
;
235 buffer
->Mid
= GetNextMid(ses
->server
);
236 if (ses
->capabilities
& CAP_UNICODE
)
237 buffer
->Flags2
|= SMBFLG2_UNICODE
;
238 if (ses
->capabilities
& CAP_STATUS32
)
239 buffer
->Flags2
|= SMBFLG2_ERR_STATUS
;
241 /* uid, tid can stay at zero as set in header assemble */
243 /* BB add support for turning on the signing when
244 this function is used after 1st of session setup requests */
249 /* If the return code is zero, this function must fill in request_buf pointer */
251 smb_init(int smb_command
, int wct
, struct cifsTconInfo
*tcon
,
252 void **request_buf
/* returned */ ,
253 void **response_buf
/* returned */ )
257 /* SMBs NegProt, SessSetup, uLogoff do not have tcon yet so
258 check for tcp and smb session status done differently
259 for those three - in the calling routine */
261 if (tcon
->tidStatus
== CifsExiting
) {
262 /* only tree disconnect, open, and write,
263 (and ulogoff which does not have tcon)
264 are allowed as we start force umount */
265 if ((smb_command
!= SMB_COM_WRITE_ANDX
) &&
266 (smb_command
!= SMB_COM_OPEN_ANDX
) &&
267 (smb_command
!= SMB_COM_TREE_DISCONNECT
)) {
268 cFYI(1, ("can not send cmd %d while umounting",
274 if ((tcon
->ses
) && (tcon
->ses
->status
!= CifsExiting
) &&
275 (tcon
->ses
->server
)) {
276 struct nls_table
*nls_codepage
;
277 /* Give Demultiplex thread up to 10 seconds to
278 reconnect, should be greater than cifs socket
279 timeout which is 7 seconds */
280 while (tcon
->ses
->server
->tcpStatus
==
282 wait_event_interruptible_timeout(tcon
->ses
->server
->response_q
,
283 (tcon
->ses
->server
->tcpStatus
==
285 if (tcon
->ses
->server
->tcpStatus
==
287 /* on "soft" mounts we wait once */
288 if ((tcon
->retry
== FALSE
) ||
289 (tcon
->ses
->status
== CifsExiting
)) {
290 cFYI(1, ("gave up waiting on "
291 "reconnect in smb_init"));
293 } /* else "hard" mount - keep retrying
294 until process is killed or server
296 } else /* TCP session is reestablished now */
299 nls_codepage
= load_nls_default();
300 /* need to prevent multiple threads trying to
301 simultaneously reconnect the same SMB session */
302 down(&tcon
->ses
->sesSem
);
303 if (tcon
->ses
->status
== CifsNeedReconnect
)
304 rc
= cifs_setup_session(0, tcon
->ses
,
306 if (!rc
&& (tcon
->tidStatus
== CifsNeedReconnect
)) {
307 mark_open_files_invalid(tcon
);
308 rc
= CIFSTCon(0, tcon
->ses
, tcon
->treeName
,
310 up(&tcon
->ses
->sesSem
);
311 /* tell server which Unix caps we support */
312 if (tcon
->ses
->capabilities
& CAP_UNIX
)
313 reset_cifs_unix_caps(0 /* no xid */,
315 NULL
/* do not know sb */,
316 NULL
/* no vol info */);
317 /* BB FIXME add code to check if wsize needs
318 update due to negotiated smb buffer size
321 atomic_inc(&tconInfoReconnectCount
);
323 cFYI(1, ("reconnect tcon rc = %d", rc
));
324 /* Removed call to reopen open files here.
325 It is safer (and faster) to reopen files
326 one at a time as needed in read and write */
328 /* Check if handle based operation so we
329 know whether we can continue or not without
330 returning to caller to reset file handle */
331 switch (smb_command
) {
332 case SMB_COM_READ_ANDX
:
333 case SMB_COM_WRITE_ANDX
:
335 case SMB_COM_FIND_CLOSE2
:
336 case SMB_COM_LOCKING_ANDX
: {
337 unload_nls(nls_codepage
);
342 up(&tcon
->ses
->sesSem
);
344 unload_nls(nls_codepage
);
353 *request_buf
= cifs_buf_get();
354 if (*request_buf
== NULL
) {
355 /* BB should we add a retry in here if not a writepage? */
358 /* Although the original thought was we needed the response buf for */
359 /* potential retries of smb operations it turns out we can determine */
360 /* from the mid flags when the request buffer can be resent without */
361 /* having to use a second distinct buffer for the response */
363 *response_buf
= *request_buf
;
365 header_assemble((struct smb_hdr
*) *request_buf
, smb_command
, tcon
,
369 cifs_stats_inc(&tcon
->num_smbs_sent
);
374 static int validate_t2(struct smb_t2_rsp
*pSMB
)
380 /* check for plausible wct, bcc and t2 data and parm sizes */
381 /* check for parm and data offset going beyond end of smb */
382 if (pSMB
->hdr
.WordCount
>= 10) {
383 if ((le16_to_cpu(pSMB
->t2_rsp
.ParameterOffset
) <= 1024) &&
384 (le16_to_cpu(pSMB
->t2_rsp
.DataOffset
) <= 1024)) {
385 /* check that bcc is at least as big as parms + data */
386 /* check that bcc is less than negotiated smb buffer */
387 total_size
= le16_to_cpu(pSMB
->t2_rsp
.ParameterCount
);
388 if (total_size
< 512) {
390 le16_to_cpu(pSMB
->t2_rsp
.DataCount
);
391 /* BCC le converted in SendReceive */
392 pBCC
= (pSMB
->hdr
.WordCount
* 2) +
393 sizeof(struct smb_hdr
) +
395 if ((total_size
<= (*(u16
*)pBCC
)) &&
397 CIFSMaxBufSize
+MAX_CIFS_HDR_SIZE
)) {
403 cifs_dump_mem("Invalid transact2 SMB: ", (char *)pSMB
,
404 sizeof(struct smb_t2_rsp
) + 16);
408 CIFSSMBNegotiate(unsigned int xid
, struct cifsSesInfo
*ses
)
411 NEGOTIATE_RSP
*pSMBr
;
415 struct TCP_Server_Info
*server
;
417 unsigned int secFlags
;
421 server
= ses
->server
;
426 rc
= smb_init(SMB_COM_NEGOTIATE
, 0, NULL
/* no tcon yet */ ,
427 (void **) &pSMB
, (void **) &pSMBr
);
431 /* if any of auth flags (ie not sign or seal) are overriden use them */
432 if (ses
->overrideSecFlg
& (~(CIFSSEC_MUST_SIGN
| CIFSSEC_MUST_SEAL
)))
433 secFlags
= ses
->overrideSecFlg
; /* BB FIXME fix sign flags? */
434 else /* if override flags set only sign/seal OR them with global auth */
435 secFlags
= extended_security
| ses
->overrideSecFlg
;
437 cFYI(1, ("secFlags 0x%x", secFlags
));
439 pSMB
->hdr
.Mid
= GetNextMid(server
);
440 pSMB
->hdr
.Flags2
|= (SMBFLG2_UNICODE
| SMBFLG2_ERR_STATUS
);
442 if ((secFlags
& CIFSSEC_MUST_KRB5
) == CIFSSEC_MUST_KRB5
)
443 pSMB
->hdr
.Flags2
|= SMBFLG2_EXT_SEC
;
444 else if ((secFlags
& CIFSSEC_AUTH_MASK
) == CIFSSEC_MAY_KRB5
) {
445 cFYI(1, ("Kerberos only mechanism, enable extended security"));
446 pSMB
->hdr
.Flags2
|= SMBFLG2_EXT_SEC
;
450 for (i
= 0; i
< CIFS_NUM_PROT
; i
++) {
451 strncpy(pSMB
->DialectsArray
+count
, protocols
[i
].name
, 16);
452 count
+= strlen(protocols
[i
].name
) + 1;
453 /* null at end of source and target buffers anyway */
455 pSMB
->hdr
.smb_buf_length
+= count
;
456 pSMB
->ByteCount
= cpu_to_le16(count
);
458 rc
= SendReceive(xid
, ses
, (struct smb_hdr
*) pSMB
,
459 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
463 dialect
= le16_to_cpu(pSMBr
->DialectIndex
);
464 cFYI(1, ("Dialect: %d", dialect
));
465 /* Check wct = 1 error case */
466 if ((pSMBr
->hdr
.WordCount
< 13) || (dialect
== BAD_PROT
)) {
467 /* core returns wct = 1, but we do not ask for core - otherwise
468 small wct just comes when dialect index is -1 indicating we
469 could not negotiate a common dialect */
472 #ifdef CONFIG_CIFS_WEAK_PW_HASH
473 } else if ((pSMBr
->hdr
.WordCount
== 13)
474 && ((dialect
== LANMAN_PROT
)
475 || (dialect
== LANMAN2_PROT
))) {
477 struct lanman_neg_rsp
*rsp
= (struct lanman_neg_rsp
*)pSMBr
;
479 if ((secFlags
& CIFSSEC_MAY_LANMAN
) ||
480 (secFlags
& CIFSSEC_MAY_PLNTXT
))
481 server
->secType
= LANMAN
;
483 cERROR(1, ("mount failed weak security disabled"
484 " in /proc/fs/cifs/SecurityFlags"));
488 server
->secMode
= (__u8
)le16_to_cpu(rsp
->SecurityMode
);
489 server
->maxReq
= le16_to_cpu(rsp
->MaxMpxCount
);
490 server
->maxBuf
= min((__u32
)le16_to_cpu(rsp
->MaxBufSize
),
491 (__u32
)CIFSMaxBufSize
+ MAX_CIFS_HDR_SIZE
);
492 GETU32(server
->sessid
) = le32_to_cpu(rsp
->SessionKey
);
493 /* even though we do not use raw we might as well set this
494 accurately, in case we ever find a need for it */
495 if ((le16_to_cpu(rsp
->RawMode
) & RAW_ENABLE
) == RAW_ENABLE
) {
496 server
->maxRw
= 0xFF00;
497 server
->capabilities
= CAP_MPX_MODE
| CAP_RAW_MODE
;
499 server
->maxRw
= 0;/* we do not need to use raw anyway */
500 server
->capabilities
= CAP_MPX_MODE
;
502 tmp
= (__s16
)le16_to_cpu(rsp
->ServerTimeZone
);
504 /* OS/2 often does not set timezone therefore
505 * we must use server time to calc time zone.
506 * Could deviate slightly from the right zone.
507 * Smallest defined timezone difference is 15 minutes
508 * (i.e. Nepal). Rounding up/down is done to match
511 int val
, seconds
, remain
, result
;
512 struct timespec ts
, utc
;
514 ts
= cnvrtDosUnixTm(le16_to_cpu(rsp
->SrvTime
.Date
),
515 le16_to_cpu(rsp
->SrvTime
.Time
));
516 cFYI(1, ("SrvTime %d sec since 1970 (utc: %d) diff: %d",
517 (int)ts
.tv_sec
, (int)utc
.tv_sec
,
518 (int)(utc
.tv_sec
- ts
.tv_sec
)));
519 val
= (int)(utc
.tv_sec
- ts
.tv_sec
);
521 result
= (seconds
/ MIN_TZ_ADJ
) * MIN_TZ_ADJ
;
522 remain
= seconds
% MIN_TZ_ADJ
;
523 if (remain
>= (MIN_TZ_ADJ
/ 2))
524 result
+= MIN_TZ_ADJ
;
527 server
->timeAdj
= result
;
529 server
->timeAdj
= (int)tmp
;
530 server
->timeAdj
*= 60; /* also in seconds */
532 cFYI(1, ("server->timeAdj: %d seconds", server
->timeAdj
));
535 /* BB get server time for time conversions and add
536 code to use it and timezone since this is not UTC */
538 if (rsp
->EncryptionKeyLength
==
539 cpu_to_le16(CIFS_CRYPTO_KEY_SIZE
)) {
540 memcpy(server
->cryptKey
, rsp
->EncryptionKey
,
541 CIFS_CRYPTO_KEY_SIZE
);
542 } else if (server
->secMode
& SECMODE_PW_ENCRYPT
) {
543 rc
= -EIO
; /* need cryptkey unless plain text */
547 cFYI(1, ("LANMAN negotiated"));
548 /* we will not end up setting signing flags - as no signing
549 was in LANMAN and server did not return the flags on */
551 #else /* weak security disabled */
552 } else if (pSMBr
->hdr
.WordCount
== 13) {
553 cERROR(1, ("mount failed, cifs module not built "
554 "with CIFS_WEAK_PW_HASH support"));
556 #endif /* WEAK_PW_HASH */
558 } else if (pSMBr
->hdr
.WordCount
!= 17) {
563 /* else wct == 17 NTLM */
564 server
->secMode
= pSMBr
->SecurityMode
;
565 if ((server
->secMode
& SECMODE_USER
) == 0)
566 cFYI(1, ("share mode security"));
568 if ((server
->secMode
& SECMODE_PW_ENCRYPT
) == 0)
569 #ifdef CONFIG_CIFS_WEAK_PW_HASH
570 if ((secFlags
& CIFSSEC_MAY_PLNTXT
) == 0)
571 #endif /* CIFS_WEAK_PW_HASH */
572 cERROR(1, ("Server requests plain text password"
573 " but client support disabled"));
575 if ((secFlags
& CIFSSEC_MUST_NTLMV2
) == CIFSSEC_MUST_NTLMV2
)
576 server
->secType
= NTLMv2
;
577 else if (secFlags
& CIFSSEC_MAY_NTLM
)
578 server
->secType
= NTLM
;
579 else if (secFlags
& CIFSSEC_MAY_NTLMV2
)
580 server
->secType
= NTLMv2
;
581 else if (secFlags
& CIFSSEC_MAY_KRB5
)
582 server
->secType
= Kerberos
;
583 else if (secFlags
& CIFSSEC_MAY_LANMAN
)
584 server
->secType
= LANMAN
;
585 /* #ifdef CONFIG_CIFS_EXPERIMENTAL
586 else if (secFlags & CIFSSEC_MAY_PLNTXT)
591 cERROR(1, ("Invalid security type"));
594 /* else ... any others ...? */
596 /* one byte, so no need to convert this or EncryptionKeyLen from
598 server
->maxReq
= le16_to_cpu(pSMBr
->MaxMpxCount
);
599 /* probably no need to store and check maxvcs */
600 server
->maxBuf
= min(le32_to_cpu(pSMBr
->MaxBufferSize
),
601 (__u32
) CIFSMaxBufSize
+ MAX_CIFS_HDR_SIZE
);
602 server
->maxRw
= le32_to_cpu(pSMBr
->MaxRawSize
);
603 cFYI(0, ("Max buf = %d", ses
->server
->maxBuf
));
604 GETU32(ses
->server
->sessid
) = le32_to_cpu(pSMBr
->SessionKey
);
605 server
->capabilities
= le32_to_cpu(pSMBr
->Capabilities
);
606 server
->timeAdj
= (int)(__s16
)le16_to_cpu(pSMBr
->ServerTimeZone
);
607 server
->timeAdj
*= 60;
608 if (pSMBr
->EncryptionKeyLength
== CIFS_CRYPTO_KEY_SIZE
) {
609 memcpy(server
->cryptKey
, pSMBr
->u
.EncryptionKey
,
610 CIFS_CRYPTO_KEY_SIZE
);
611 } else if ((pSMBr
->hdr
.Flags2
& SMBFLG2_EXT_SEC
)
612 && (pSMBr
->EncryptionKeyLength
== 0)) {
613 /* decode security blob */
614 } else if (server
->secMode
& SECMODE_PW_ENCRYPT
) {
615 rc
= -EIO
; /* no crypt key only if plain text pwd */
619 /* BB might be helpful to save off the domain of server here */
621 if ((pSMBr
->hdr
.Flags2
& SMBFLG2_EXT_SEC
) &&
622 (server
->capabilities
& CAP_EXTENDED_SECURITY
)) {
623 count
= pSMBr
->ByteCount
;
629 if (server
->socketUseCount
.counter
> 1) {
630 if (memcmp(server
->server_GUID
,
631 pSMBr
->u
.extended_response
.
633 cFYI(1, ("server UID changed"));
634 memcpy(server
->server_GUID
,
635 pSMBr
->u
.extended_response
.GUID
,
639 memcpy(server
->server_GUID
,
640 pSMBr
->u
.extended_response
.GUID
, 16);
643 server
->secType
= RawNTLMSSP
;
645 rc
= decode_negTokenInit(pSMBr
->u
.extended_response
.
656 server
->capabilities
&= ~CAP_EXTENDED_SECURITY
;
658 #ifdef CONFIG_CIFS_WEAK_PW_HASH
661 if ((secFlags
& CIFSSEC_MAY_SIGN
) == 0) {
662 /* MUST_SIGN already includes the MAY_SIGN FLAG
663 so if this is zero it means that signing is disabled */
664 cFYI(1, ("Signing disabled"));
665 if (server
->secMode
& SECMODE_SIGN_REQUIRED
) {
666 cERROR(1, ("Server requires "
667 "packet signing to be enabled in "
668 "/proc/fs/cifs/SecurityFlags."));
672 ~(SECMODE_SIGN_ENABLED
| SECMODE_SIGN_REQUIRED
);
673 } else if ((secFlags
& CIFSSEC_MUST_SIGN
) == CIFSSEC_MUST_SIGN
) {
674 /* signing required */
675 cFYI(1, ("Must sign - secFlags 0x%x", secFlags
));
676 if ((server
->secMode
&
677 (SECMODE_SIGN_ENABLED
| SECMODE_SIGN_REQUIRED
)) == 0) {
679 ("signing required but server lacks support"));
682 server
->secMode
|= SECMODE_SIGN_REQUIRED
;
684 /* signing optional ie CIFSSEC_MAY_SIGN */
685 if ((server
->secMode
& SECMODE_SIGN_REQUIRED
) == 0)
687 ~(SECMODE_SIGN_ENABLED
| SECMODE_SIGN_REQUIRED
);
691 cifs_buf_release(pSMB
);
693 cFYI(1, ("negprot rc %d", rc
));
698 CIFSSMBTDis(const int xid
, struct cifsTconInfo
*tcon
)
700 struct smb_hdr
*smb_buffer
;
703 cFYI(1, ("In tree disconnect"));
705 * If last user of the connection and
706 * connection alive - disconnect it
707 * If this is the last connection on the server session disconnect it
708 * (and inside session disconnect we should check if tcp socket needs
709 * to be freed and kernel thread woken up).
712 down(&tcon
->tconSem
);
716 atomic_dec(&tcon
->useCount
);
717 if (atomic_read(&tcon
->useCount
) > 0) {
722 /* No need to return error on this operation if tid invalidated and
723 closed on server already e.g. due to tcp session crashing */
724 if (tcon
->tidStatus
== CifsNeedReconnect
) {
729 if ((tcon
->ses
== NULL
) || (tcon
->ses
->server
== NULL
)) {
733 rc
= small_smb_init(SMB_COM_TREE_DISCONNECT
, 0, tcon
,
734 (void **)&smb_buffer
);
740 rc
= SendReceiveNoRsp(xid
, tcon
->ses
, smb_buffer
, 0);
742 cFYI(1, ("Tree disconnect failed %d", rc
));
746 /* No need to return error on this operation if tid invalidated and
747 closed on server already e.g. due to tcp session crashing */
755 CIFSSMBLogoff(const int xid
, struct cifsSesInfo
*ses
)
757 LOGOFF_ANDX_REQ
*pSMB
;
760 cFYI(1, ("In SMBLogoff for session disconnect"));
766 atomic_dec(&ses
->inUse
);
767 if (atomic_read(&ses
->inUse
) > 0) {
771 rc
= small_smb_init(SMB_COM_LOGOFF_ANDX
, 2, NULL
, (void **)&pSMB
);
778 pSMB
->hdr
.Mid
= GetNextMid(ses
->server
);
780 if (ses
->server
->secMode
&
781 (SECMODE_SIGN_REQUIRED
| SECMODE_SIGN_ENABLED
))
782 pSMB
->hdr
.Flags2
|= SMBFLG2_SECURITY_SIGNATURE
;
785 pSMB
->hdr
.Uid
= ses
->Suid
;
787 pSMB
->AndXCommand
= 0xFF;
788 rc
= SendReceiveNoRsp(xid
, ses
, (struct smb_hdr
*) pSMB
, 0);
790 atomic_dec(&ses
->server
->socketUseCount
);
791 if (atomic_read(&ses
->server
->socketUseCount
) == 0) {
792 spin_lock(&GlobalMid_Lock
);
793 ses
->server
->tcpStatus
= CifsExiting
;
794 spin_unlock(&GlobalMid_Lock
);
800 /* if session dead then we do not need to do ulogoff,
801 since server closed smb session, no sense reporting
809 CIFSPOSIXDelFile(const int xid
, struct cifsTconInfo
*tcon
, const char *fileName
,
810 __u16 type
, const struct nls_table
*nls_codepage
, int remap
)
812 TRANSACTION2_SPI_REQ
*pSMB
= NULL
;
813 TRANSACTION2_SPI_RSP
*pSMBr
= NULL
;
814 struct unlink_psx_rq
*pRqD
;
817 int bytes_returned
= 0;
818 __u16 params
, param_offset
, offset
, byte_count
;
820 cFYI(1, ("In POSIX delete"));
822 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
827 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
829 cifsConvertToUCS((__le16
*) pSMB
->FileName
, fileName
,
830 PATH_MAX
, nls_codepage
, remap
);
831 name_len
++; /* trailing null */
833 } else { /* BB add path length overrun check */
834 name_len
= strnlen(fileName
, PATH_MAX
);
835 name_len
++; /* trailing null */
836 strncpy(pSMB
->FileName
, fileName
, name_len
);
839 params
= 6 + name_len
;
840 pSMB
->MaxParameterCount
= cpu_to_le16(2);
841 pSMB
->MaxDataCount
= 0; /* BB double check this with jra */
842 pSMB
->MaxSetupCount
= 0;
847 param_offset
= offsetof(struct smb_com_transaction2_spi_req
,
848 InformationLevel
) - 4;
849 offset
= param_offset
+ params
;
851 /* Setup pointer to Request Data (inode type) */
852 pRqD
= (struct unlink_psx_rq
*)(((char *)&pSMB
->hdr
.Protocol
) + offset
);
853 pRqD
->type
= cpu_to_le16(type
);
854 pSMB
->ParameterOffset
= cpu_to_le16(param_offset
);
855 pSMB
->DataOffset
= cpu_to_le16(offset
);
856 pSMB
->SetupCount
= 1;
858 pSMB
->SubCommand
= cpu_to_le16(TRANS2_SET_PATH_INFORMATION
);
859 byte_count
= 3 /* pad */ + params
+ sizeof(struct unlink_psx_rq
);
861 pSMB
->DataCount
= cpu_to_le16(sizeof(struct unlink_psx_rq
));
862 pSMB
->TotalDataCount
= cpu_to_le16(sizeof(struct unlink_psx_rq
));
863 pSMB
->ParameterCount
= cpu_to_le16(params
);
864 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
865 pSMB
->InformationLevel
= cpu_to_le16(SMB_POSIX_UNLINK
);
867 pSMB
->hdr
.smb_buf_length
+= byte_count
;
868 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
869 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
870 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
872 cFYI(1, ("Posix delete returned %d", rc
));
874 cifs_buf_release(pSMB
);
876 cifs_stats_inc(&tcon
->num_deletes
);
885 CIFSSMBDelFile(const int xid
, struct cifsTconInfo
*tcon
, const char *fileName
,
886 const struct nls_table
*nls_codepage
, int remap
)
888 DELETE_FILE_REQ
*pSMB
= NULL
;
889 DELETE_FILE_RSP
*pSMBr
= NULL
;
895 rc
= smb_init(SMB_COM_DELETE
, 1, tcon
, (void **) &pSMB
,
900 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
902 cifsConvertToUCS((__le16
*) pSMB
->fileName
, fileName
,
903 PATH_MAX
, nls_codepage
, remap
);
904 name_len
++; /* trailing null */
906 } else { /* BB improve check for buffer overruns BB */
907 name_len
= strnlen(fileName
, PATH_MAX
);
908 name_len
++; /* trailing null */
909 strncpy(pSMB
->fileName
, fileName
, name_len
);
911 pSMB
->SearchAttributes
=
912 cpu_to_le16(ATTR_READONLY
| ATTR_HIDDEN
| ATTR_SYSTEM
);
913 pSMB
->BufferFormat
= 0x04;
914 pSMB
->hdr
.smb_buf_length
+= name_len
+ 1;
915 pSMB
->ByteCount
= cpu_to_le16(name_len
+ 1);
916 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
917 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
918 cifs_stats_inc(&tcon
->num_deletes
);
920 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
));
968 cifs_buf_release(pSMB
);
975 CIFSSMBMkDir(const int xid
, struct cifsTconInfo
*tcon
,
976 const char *name
, const struct nls_table
*nls_codepage
, int remap
)
979 CREATE_DIRECTORY_REQ
*pSMB
= NULL
;
980 CREATE_DIRECTORY_RSP
*pSMBr
= NULL
;
984 cFYI(1, ("In CIFSSMBMkDir"));
986 rc
= smb_init(SMB_COM_CREATE_DIRECTORY
, 0, tcon
, (void **) &pSMB
,
991 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
992 name_len
= cifsConvertToUCS((__le16
*) pSMB
->DirName
, name
,
993 PATH_MAX
, nls_codepage
, remap
);
994 name_len
++; /* trailing null */
996 } else { /* BB improve check for buffer overruns BB */
997 name_len
= strnlen(name
, PATH_MAX
);
998 name_len
++; /* trailing null */
999 strncpy(pSMB
->DirName
, name
, name_len
);
1002 pSMB
->BufferFormat
= 0x04;
1003 pSMB
->hdr
.smb_buf_length
+= name_len
+ 1;
1004 pSMB
->ByteCount
= cpu_to_le16(name_len
+ 1);
1005 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
1006 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
1007 cifs_stats_inc(&tcon
->num_mkdirs
);
1009 cFYI(1, ("Error in Mkdir = %d", rc
));
1012 cifs_buf_release(pSMB
);
1019 CIFSPOSIXCreate(const int xid
, struct cifsTconInfo
*tcon
, __u32 posix_flags
,
1020 __u64 mode
, __u16
* netfid
, FILE_UNIX_BASIC_INFO
*pRetData
,
1021 __u32
*pOplock
, const char *name
,
1022 const struct nls_table
*nls_codepage
, int remap
)
1024 TRANSACTION2_SPI_REQ
*pSMB
= NULL
;
1025 TRANSACTION2_SPI_RSP
*pSMBr
= NULL
;
1028 int bytes_returned
= 0;
1029 __u16 params
, param_offset
, offset
, byte_count
, count
;
1030 OPEN_PSX_REQ
* pdata
;
1031 OPEN_PSX_RSP
* psx_rsp
;
1033 cFYI(1, ("In POSIX Create"));
1035 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
1040 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
1042 cifsConvertToUCS((__le16
*) pSMB
->FileName
, name
,
1043 PATH_MAX
, nls_codepage
, remap
);
1044 name_len
++; /* trailing null */
1046 } else { /* BB improve the check for buffer overruns BB */
1047 name_len
= strnlen(name
, PATH_MAX
);
1048 name_len
++; /* trailing null */
1049 strncpy(pSMB
->FileName
, name
, name_len
);
1052 params
= 6 + name_len
;
1053 count
= sizeof(OPEN_PSX_REQ
);
1054 pSMB
->MaxParameterCount
= cpu_to_le16(2);
1055 pSMB
->MaxDataCount
= cpu_to_le16(1000); /* large enough */
1056 pSMB
->MaxSetupCount
= 0;
1060 pSMB
->Reserved2
= 0;
1061 param_offset
= offsetof(struct smb_com_transaction2_spi_req
,
1062 InformationLevel
) - 4;
1063 offset
= param_offset
+ params
;
1064 pdata
= (OPEN_PSX_REQ
*)(((char *)&pSMB
->hdr
.Protocol
) + offset
);
1065 pdata
->Level
= cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC
);
1066 pdata
->Permissions
= cpu_to_le64(mode
);
1067 pdata
->PosixOpenFlags
= cpu_to_le32(posix_flags
);
1068 pdata
->OpenFlags
= cpu_to_le32(*pOplock
);
1069 pSMB
->ParameterOffset
= cpu_to_le16(param_offset
);
1070 pSMB
->DataOffset
= cpu_to_le16(offset
);
1071 pSMB
->SetupCount
= 1;
1072 pSMB
->Reserved3
= 0;
1073 pSMB
->SubCommand
= cpu_to_le16(TRANS2_SET_PATH_INFORMATION
);
1074 byte_count
= 3 /* pad */ + params
+ count
;
1076 pSMB
->DataCount
= cpu_to_le16(count
);
1077 pSMB
->ParameterCount
= cpu_to_le16(params
);
1078 pSMB
->TotalDataCount
= pSMB
->DataCount
;
1079 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
1080 pSMB
->InformationLevel
= cpu_to_le16(SMB_POSIX_OPEN
);
1081 pSMB
->Reserved4
= 0;
1082 pSMB
->hdr
.smb_buf_length
+= byte_count
;
1083 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
1084 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
1085 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
1087 cFYI(1, ("Posix create returned %d", rc
));
1088 goto psx_create_err
;
1091 cFYI(1, ("copying inode info"));
1092 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
1094 if (rc
|| (pSMBr
->ByteCount
< sizeof(OPEN_PSX_RSP
))) {
1095 rc
= -EIO
; /* bad smb */
1096 goto psx_create_err
;
1099 /* copy return information to pRetData */
1100 psx_rsp
= (OPEN_PSX_RSP
*)((char *) &pSMBr
->hdr
.Protocol
1101 + le16_to_cpu(pSMBr
->t2
.DataOffset
));
1103 *pOplock
= le16_to_cpu(psx_rsp
->OplockFlags
);
1105 *netfid
= psx_rsp
->Fid
; /* cifs fid stays in le */
1106 /* Let caller know file was created so we can set the mode. */
1107 /* Do we care about the CreateAction in any other cases? */
1108 if (cpu_to_le32(FILE_CREATE
) == psx_rsp
->CreateAction
)
1109 *pOplock
|= CIFS_CREATE_ACTION
;
1110 /* check to make sure response data is there */
1111 if (psx_rsp
->ReturnedLevel
!= cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC
)) {
1112 pRetData
->Type
= cpu_to_le32(-1); /* unknown */
1113 #ifdef CONFIG_CIFS_DEBUG2
1114 cFYI(1, ("unknown type"));
1117 if (pSMBr
->ByteCount
< sizeof(OPEN_PSX_RSP
)
1118 + sizeof(FILE_UNIX_BASIC_INFO
)) {
1119 cERROR(1, ("Open response data too small"));
1120 pRetData
->Type
= cpu_to_le32(-1);
1121 goto psx_create_err
;
1123 memcpy((char *) pRetData
,
1124 (char *)psx_rsp
+ sizeof(OPEN_PSX_RSP
),
1125 sizeof(FILE_UNIX_BASIC_INFO
));
1129 cifs_buf_release(pSMB
);
1131 cifs_stats_inc(&tcon
->num_mkdirs
);
1139 static __u16
convert_disposition(int disposition
)
1143 switch (disposition
) {
1144 case FILE_SUPERSEDE
:
1145 ofun
= SMBOPEN_OCREATE
| SMBOPEN_OTRUNC
;
1148 ofun
= SMBOPEN_OAPPEND
;
1151 ofun
= SMBOPEN_OCREATE
;
1154 ofun
= SMBOPEN_OCREATE
| SMBOPEN_OAPPEND
;
1156 case FILE_OVERWRITE
:
1157 ofun
= SMBOPEN_OTRUNC
;
1159 case FILE_OVERWRITE_IF
:
1160 ofun
= SMBOPEN_OCREATE
| SMBOPEN_OTRUNC
;
1163 cFYI(1, ("unknown disposition %d", disposition
));
1164 ofun
= SMBOPEN_OAPPEND
; /* regular open */
1170 SMBLegacyOpen(const int xid
, struct cifsTconInfo
*tcon
,
1171 const char *fileName
, const int openDisposition
,
1172 const int access_flags
, const int create_options
, __u16
* netfid
,
1173 int *pOplock
, FILE_ALL_INFO
* pfile_info
,
1174 const struct nls_table
*nls_codepage
, int remap
)
1177 OPENX_REQ
*pSMB
= NULL
;
1178 OPENX_RSP
*pSMBr
= NULL
;
1184 rc
= smb_init(SMB_COM_OPEN_ANDX
, 15, tcon
, (void **) &pSMB
,
1189 pSMB
->AndXCommand
= 0xFF; /* none */
1191 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
1192 count
= 1; /* account for one byte pad to word boundary */
1194 cifsConvertToUCS((__le16
*) (pSMB
->fileName
+ 1),
1195 fileName
, PATH_MAX
, nls_codepage
, remap
);
1196 name_len
++; /* trailing null */
1198 } else { /* BB improve check for buffer overruns BB */
1199 count
= 0; /* no pad */
1200 name_len
= strnlen(fileName
, PATH_MAX
);
1201 name_len
++; /* trailing null */
1202 strncpy(pSMB
->fileName
, fileName
, name_len
);
1204 if (*pOplock
& REQ_OPLOCK
)
1205 pSMB
->OpenFlags
= cpu_to_le16(REQ_OPLOCK
);
1206 else if (*pOplock
& REQ_BATCHOPLOCK
)
1207 pSMB
->OpenFlags
= cpu_to_le16(REQ_BATCHOPLOCK
);
1209 pSMB
->OpenFlags
|= cpu_to_le16(REQ_MORE_INFO
);
1210 /* BB fixme add conversion for access_flags to bits 0 - 2 of mode */
1216 pSMB
->Mode
= cpu_to_le16(2);
1217 pSMB
->Mode
|= cpu_to_le16(0x40); /* deny none */
1218 /* set file as system file if special file such
1219 as fifo and server expecting SFU style and
1220 no Unix extensions */
1222 if (create_options
& CREATE_OPTION_SPECIAL
)
1223 pSMB
->FileAttributes
= cpu_to_le16(ATTR_SYSTEM
);
1225 pSMB
->FileAttributes
= cpu_to_le16(0/*ATTR_NORMAL*/); /* BB FIXME */
1227 /* if ((omode & S_IWUGO) == 0)
1228 pSMB->FileAttributes |= cpu_to_le32(ATTR_READONLY);*/
1229 /* Above line causes problems due to vfs splitting create into two
1230 pieces - need to set mode after file created not while it is
1234 /* pSMB->CreateOptions = cpu_to_le32(create_options &
1235 CREATE_OPTIONS_MASK); */
1236 /* BB FIXME END BB */
1238 pSMB
->Sattr
= cpu_to_le16(ATTR_HIDDEN
| ATTR_SYSTEM
| ATTR_DIRECTORY
);
1239 pSMB
->OpenFunction
= cpu_to_le16(convert_disposition(openDisposition
));
1241 pSMB
->hdr
.smb_buf_length
+= count
;
1243 pSMB
->ByteCount
= cpu_to_le16(count
);
1244 /* long_op set to 1 to allow for oplock break timeouts */
1245 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
1246 (struct smb_hdr
*)pSMBr
, &bytes_returned
, CIFS_LONG_OP
);
1247 cifs_stats_inc(&tcon
->num_opens
);
1249 cFYI(1, ("Error in Open = %d", rc
));
1251 /* BB verify if wct == 15 */
1253 /* *pOplock = pSMBr->OplockLevel; */ /* BB take from action field BB */
1255 *netfid
= pSMBr
->Fid
; /* cifs fid stays in le */
1256 /* Let caller know file was created so we can set the mode. */
1257 /* Do we care about the CreateAction in any other cases? */
1259 /* if (cpu_to_le32(FILE_CREATE) == pSMBr->CreateAction)
1260 *pOplock |= CIFS_CREATE_ACTION; */
1264 pfile_info
->CreationTime
= 0; /* BB convert CreateTime*/
1265 pfile_info
->LastAccessTime
= 0; /* BB fixme */
1266 pfile_info
->LastWriteTime
= 0; /* BB fixme */
1267 pfile_info
->ChangeTime
= 0; /* BB fixme */
1268 pfile_info
->Attributes
=
1269 cpu_to_le32(le16_to_cpu(pSMBr
->FileAttributes
));
1270 /* the file_info buf is endian converted by caller */
1271 pfile_info
->AllocationSize
=
1272 cpu_to_le64(le32_to_cpu(pSMBr
->EndOfFile
));
1273 pfile_info
->EndOfFile
= pfile_info
->AllocationSize
;
1274 pfile_info
->NumberOfLinks
= cpu_to_le32(1);
1278 cifs_buf_release(pSMB
);
1285 CIFSSMBOpen(const int xid
, struct cifsTconInfo
*tcon
,
1286 const char *fileName
, const int openDisposition
,
1287 const int access_flags
, const int create_options
, __u16
* netfid
,
1288 int *pOplock
, FILE_ALL_INFO
* pfile_info
,
1289 const struct nls_table
*nls_codepage
, int remap
)
1292 OPEN_REQ
*pSMB
= NULL
;
1293 OPEN_RSP
*pSMBr
= NULL
;
1299 rc
= smb_init(SMB_COM_NT_CREATE_ANDX
, 24, tcon
, (void **) &pSMB
,
1304 pSMB
->AndXCommand
= 0xFF; /* none */
1306 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
1307 count
= 1; /* account for one byte pad to word boundary */
1309 cifsConvertToUCS((__le16
*) (pSMB
->fileName
+ 1),
1310 fileName
, PATH_MAX
, nls_codepage
, remap
);
1311 name_len
++; /* trailing null */
1313 pSMB
->NameLength
= cpu_to_le16(name_len
);
1314 } else { /* BB improve check for buffer overruns BB */
1315 count
= 0; /* no pad */
1316 name_len
= strnlen(fileName
, PATH_MAX
);
1317 name_len
++; /* trailing null */
1318 pSMB
->NameLength
= cpu_to_le16(name_len
);
1319 strncpy(pSMB
->fileName
, fileName
, name_len
);
1321 if (*pOplock
& REQ_OPLOCK
)
1322 pSMB
->OpenFlags
= cpu_to_le32(REQ_OPLOCK
);
1323 else if (*pOplock
& REQ_BATCHOPLOCK
)
1324 pSMB
->OpenFlags
= cpu_to_le32(REQ_BATCHOPLOCK
);
1325 pSMB
->DesiredAccess
= cpu_to_le32(access_flags
);
1326 pSMB
->AllocationSize
= 0;
1327 /* set file as system file if special file such
1328 as fifo and server expecting SFU style and
1329 no Unix extensions */
1330 if (create_options
& CREATE_OPTION_SPECIAL
)
1331 pSMB
->FileAttributes
= cpu_to_le32(ATTR_SYSTEM
);
1333 pSMB
->FileAttributes
= cpu_to_le32(ATTR_NORMAL
);
1334 /* XP does not handle ATTR_POSIX_SEMANTICS */
1335 /* but it helps speed up case sensitive checks for other
1336 servers such as Samba */
1337 if (tcon
->ses
->capabilities
& CAP_UNIX
)
1338 pSMB
->FileAttributes
|= cpu_to_le32(ATTR_POSIX_SEMANTICS
);
1340 /* if ((omode & S_IWUGO) == 0)
1341 pSMB->FileAttributes |= cpu_to_le32(ATTR_READONLY);*/
1342 /* Above line causes problems due to vfs splitting create into two
1343 pieces - need to set mode after file created not while it is
1345 pSMB
->ShareAccess
= cpu_to_le32(FILE_SHARE_ALL
);
1346 pSMB
->CreateDisposition
= cpu_to_le32(openDisposition
);
1347 pSMB
->CreateOptions
= cpu_to_le32(create_options
& CREATE_OPTIONS_MASK
);
1348 /* BB Expirement with various impersonation levels and verify */
1349 pSMB
->ImpersonationLevel
= cpu_to_le32(SECURITY_IMPERSONATION
);
1350 pSMB
->SecurityFlags
=
1351 SECURITY_CONTEXT_TRACKING
| SECURITY_EFFECTIVE_ONLY
;
1354 pSMB
->hdr
.smb_buf_length
+= count
;
1356 pSMB
->ByteCount
= cpu_to_le16(count
);
1357 /* long_op set to 1 to allow for oplock break timeouts */
1358 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
1359 (struct smb_hdr
*)pSMBr
, &bytes_returned
, CIFS_LONG_OP
);
1360 cifs_stats_inc(&tcon
->num_opens
);
1362 cFYI(1, ("Error in Open = %d", rc
));
1364 *pOplock
= pSMBr
->OplockLevel
; /* 1 byte no need to le_to_cpu */
1365 *netfid
= pSMBr
->Fid
; /* cifs fid stays in le */
1366 /* Let caller know file was created so we can set the mode. */
1367 /* Do we care about the CreateAction in any other cases? */
1368 if (cpu_to_le32(FILE_CREATE
) == pSMBr
->CreateAction
)
1369 *pOplock
|= CIFS_CREATE_ACTION
;
1371 memcpy((char *)pfile_info
, (char *)&pSMBr
->CreationTime
,
1372 36 /* CreationTime to Attributes */);
1373 /* the file_info buf is endian converted by caller */
1374 pfile_info
->AllocationSize
= pSMBr
->AllocationSize
;
1375 pfile_info
->EndOfFile
= pSMBr
->EndOfFile
;
1376 pfile_info
->NumberOfLinks
= cpu_to_le32(1);
1380 cifs_buf_release(pSMB
);
1387 CIFSSMBRead(const int xid
, struct cifsTconInfo
*tcon
, const int netfid
,
1388 const unsigned int count
, const __u64 lseek
, unsigned int *nbytes
,
1389 char **buf
, int *pbuf_type
)
1392 READ_REQ
*pSMB
= NULL
;
1393 READ_RSP
*pSMBr
= NULL
;
1394 char *pReadData
= NULL
;
1396 int resp_buf_type
= 0;
1399 cFYI(1, ("Reading %d bytes on fid %d", count
, netfid
));
1400 if (tcon
->ses
->capabilities
& CAP_LARGE_FILES
)
1403 wct
= 10; /* old style read */
1406 rc
= small_smb_init(SMB_COM_READ_ANDX
, wct
, tcon
, (void **) &pSMB
);
1410 /* tcon and ses pointer are checked in smb_init */
1411 if (tcon
->ses
->server
== NULL
)
1412 return -ECONNABORTED
;
1414 pSMB
->AndXCommand
= 0xFF; /* none */
1416 pSMB
->OffsetLow
= cpu_to_le32(lseek
& 0xFFFFFFFF);
1418 pSMB
->OffsetHigh
= cpu_to_le32(lseek
>> 32);
1419 else if ((lseek
>> 32) > 0) /* can not handle this big offset for old */
1422 pSMB
->Remaining
= 0;
1423 pSMB
->MaxCount
= cpu_to_le16(count
& 0xFFFF);
1424 pSMB
->MaxCountHigh
= cpu_to_le32(count
>> 16);
1426 pSMB
->ByteCount
= 0; /* no need to do le conversion since 0 */
1428 /* old style read */
1429 struct smb_com_readx_req
*pSMBW
=
1430 (struct smb_com_readx_req
*)pSMB
;
1431 pSMBW
->ByteCount
= 0;
1434 iov
[0].iov_base
= (char *)pSMB
;
1435 iov
[0].iov_len
= pSMB
->hdr
.smb_buf_length
+ 4;
1436 rc
= SendReceive2(xid
, tcon
->ses
, iov
, 1 /* num iovecs */,
1437 &resp_buf_type
, CIFS_STD_OP
| CIFS_LOG_ERROR
);
1438 cifs_stats_inc(&tcon
->num_reads
);
1439 pSMBr
= (READ_RSP
*)iov
[0].iov_base
;
1441 cERROR(1, ("Send error in read = %d", rc
));
1443 int data_length
= le16_to_cpu(pSMBr
->DataLengthHigh
);
1444 data_length
= data_length
<< 16;
1445 data_length
+= le16_to_cpu(pSMBr
->DataLength
);
1446 *nbytes
= data_length
;
1448 /*check that DataLength would not go beyond end of SMB */
1449 if ((data_length
> CIFSMaxBufSize
)
1450 || (data_length
> count
)) {
1451 cFYI(1, ("bad length %d for count %d",
1452 data_length
, count
));
1456 pReadData
= (char *) (&pSMBr
->hdr
.Protocol
) +
1457 le16_to_cpu(pSMBr
->DataOffset
);
1458 /* if (rc = copy_to_user(buf, pReadData, data_length)) {
1459 cERROR(1,("Faulting on read rc = %d",rc));
1461 }*/ /* can not use copy_to_user when using page cache*/
1463 memcpy(*buf
, pReadData
, data_length
);
1467 /* cifs_small_buf_release(pSMB); */ /* Freed earlier now in SendReceive2 */
1469 if (resp_buf_type
== CIFS_SMALL_BUFFER
)
1470 cifs_small_buf_release(iov
[0].iov_base
);
1471 else if (resp_buf_type
== CIFS_LARGE_BUFFER
)
1472 cifs_buf_release(iov
[0].iov_base
);
1473 } else if (resp_buf_type
!= CIFS_NO_BUFFER
) {
1474 /* return buffer to caller to free */
1475 *buf
= iov
[0].iov_base
;
1476 if (resp_buf_type
== CIFS_SMALL_BUFFER
)
1477 *pbuf_type
= CIFS_SMALL_BUFFER
;
1478 else if (resp_buf_type
== CIFS_LARGE_BUFFER
)
1479 *pbuf_type
= CIFS_LARGE_BUFFER
;
1480 } /* else no valid buffer on return - leave as null */
1482 /* Note: On -EAGAIN error only caller can retry on handle based calls
1483 since file handle passed in no longer valid */
1489 CIFSSMBWrite(const int xid
, struct cifsTconInfo
*tcon
,
1490 const int netfid
, const unsigned int count
,
1491 const __u64 offset
, unsigned int *nbytes
, const char *buf
,
1492 const char __user
*ubuf
, const int long_op
)
1495 WRITE_REQ
*pSMB
= NULL
;
1496 WRITE_RSP
*pSMBr
= NULL
;
1497 int bytes_returned
, wct
;
1501 /* cFYI(1,("write at %lld %d bytes",offset,count));*/
1502 if (tcon
->ses
== NULL
)
1503 return -ECONNABORTED
;
1505 if (tcon
->ses
->capabilities
& CAP_LARGE_FILES
)
1510 rc
= smb_init(SMB_COM_WRITE_ANDX
, wct
, tcon
, (void **) &pSMB
,
1514 /* tcon and ses pointer are checked in smb_init */
1515 if (tcon
->ses
->server
== NULL
)
1516 return -ECONNABORTED
;
1518 pSMB
->AndXCommand
= 0xFF; /* none */
1520 pSMB
->OffsetLow
= cpu_to_le32(offset
& 0xFFFFFFFF);
1522 pSMB
->OffsetHigh
= cpu_to_le32(offset
>> 32);
1523 else if ((offset
>> 32) > 0) /* can not handle big offset for old srv */
1526 pSMB
->Reserved
= 0xFFFFFFFF;
1527 pSMB
->WriteMode
= 0;
1528 pSMB
->Remaining
= 0;
1530 /* Can increase buffer size if buffer is big enough in some cases ie we
1531 can send more if LARGE_WRITE_X capability returned by the server and if
1532 our buffer is big enough or if we convert to iovecs on socket writes
1533 and eliminate the copy to the CIFS buffer */
1534 if (tcon
->ses
->capabilities
& CAP_LARGE_WRITE_X
) {
1535 bytes_sent
= min_t(const unsigned int, CIFSMaxBufSize
, count
);
1537 bytes_sent
= (tcon
->ses
->server
->maxBuf
- MAX_CIFS_HDR_SIZE
)
1541 if (bytes_sent
> count
)
1544 cpu_to_le16(offsetof(struct smb_com_write_req
, Data
) - 4);
1546 memcpy(pSMB
->Data
, buf
, bytes_sent
);
1548 if (copy_from_user(pSMB
->Data
, ubuf
, bytes_sent
)) {
1549 cifs_buf_release(pSMB
);
1552 } else if (count
!= 0) {
1554 cifs_buf_release(pSMB
);
1556 } /* else setting file size with write of zero bytes */
1558 byte_count
= bytes_sent
+ 1; /* pad */
1559 else /* wct == 12 */ {
1560 byte_count
= bytes_sent
+ 5; /* bigger pad, smaller smb hdr */
1562 pSMB
->DataLengthLow
= cpu_to_le16(bytes_sent
& 0xFFFF);
1563 pSMB
->DataLengthHigh
= cpu_to_le16(bytes_sent
>> 16);
1564 pSMB
->hdr
.smb_buf_length
+= byte_count
;
1567 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
1568 else { /* old style write has byte count 4 bytes earlier
1570 struct smb_com_writex_req
*pSMBW
=
1571 (struct smb_com_writex_req
*)pSMB
;
1572 pSMBW
->ByteCount
= cpu_to_le16(byte_count
);
1575 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
1576 (struct smb_hdr
*) pSMBr
, &bytes_returned
, long_op
);
1577 cifs_stats_inc(&tcon
->num_writes
);
1579 cFYI(1, ("Send error in write = %d", rc
));
1582 *nbytes
= le16_to_cpu(pSMBr
->CountHigh
);
1583 *nbytes
= (*nbytes
) << 16;
1584 *nbytes
+= le16_to_cpu(pSMBr
->Count
);
1587 * Mask off high 16 bits when bytes written as returned by the
1588 * server is greater than bytes requested by the client. Some
1589 * OS/2 servers are known to set incorrect CountHigh values.
1591 if (*nbytes
> count
)
1595 cifs_buf_release(pSMB
);
1597 /* Note: On -EAGAIN error only caller can retry on handle based calls
1598 since file handle passed in no longer valid */
1604 CIFSSMBWrite2(const int xid
, struct cifsTconInfo
*tcon
,
1605 const int netfid
, const unsigned int count
,
1606 const __u64 offset
, unsigned int *nbytes
, struct kvec
*iov
,
1607 int n_vec
, const int long_op
)
1610 WRITE_REQ
*pSMB
= NULL
;
1613 int resp_buf_type
= 0;
1615 cFYI(1, ("write2 at %lld %d bytes", (long long)offset
, count
));
1617 if (tcon
->ses
->capabilities
& CAP_LARGE_FILES
)
1621 rc
= small_smb_init(SMB_COM_WRITE_ANDX
, wct
, tcon
, (void **) &pSMB
);
1624 /* tcon and ses pointer are checked in smb_init */
1625 if (tcon
->ses
->server
== NULL
)
1626 return -ECONNABORTED
;
1628 pSMB
->AndXCommand
= 0xFF; /* none */
1630 pSMB
->OffsetLow
= cpu_to_le32(offset
& 0xFFFFFFFF);
1632 pSMB
->OffsetHigh
= cpu_to_le32(offset
>> 32);
1633 else if ((offset
>> 32) > 0) /* can not handle big offset for old srv */
1635 pSMB
->Reserved
= 0xFFFFFFFF;
1636 pSMB
->WriteMode
= 0;
1637 pSMB
->Remaining
= 0;
1640 cpu_to_le16(offsetof(struct smb_com_write_req
, Data
) - 4);
1642 pSMB
->DataLengthLow
= cpu_to_le16(count
& 0xFFFF);
1643 pSMB
->DataLengthHigh
= cpu_to_le16(count
>> 16);
1644 smb_hdr_len
= pSMB
->hdr
.smb_buf_length
+ 1; /* hdr + 1 byte pad */
1646 pSMB
->hdr
.smb_buf_length
+= count
+1;
1647 else /* wct == 12 */
1648 pSMB
->hdr
.smb_buf_length
+= count
+5; /* smb data starts later */
1650 pSMB
->ByteCount
= cpu_to_le16(count
+ 1);
1651 else /* wct == 12 */ /* bigger pad, smaller smb hdr, keep offset ok */ {
1652 struct smb_com_writex_req
*pSMBW
=
1653 (struct smb_com_writex_req
*)pSMB
;
1654 pSMBW
->ByteCount
= cpu_to_le16(count
+ 5);
1656 iov
[0].iov_base
= pSMB
;
1658 iov
[0].iov_len
= smb_hdr_len
+ 4;
1659 else /* wct == 12 pad bigger by four bytes */
1660 iov
[0].iov_len
= smb_hdr_len
+ 8;
1663 rc
= SendReceive2(xid
, tcon
->ses
, iov
, n_vec
+ 1, &resp_buf_type
,
1665 cifs_stats_inc(&tcon
->num_writes
);
1667 cFYI(1, ("Send error Write2 = %d", rc
));
1669 } else if (resp_buf_type
== 0) {
1670 /* presumably this can not happen, but best to be safe */
1674 WRITE_RSP
* pSMBr
= (WRITE_RSP
*)iov
[0].iov_base
;
1675 *nbytes
= le16_to_cpu(pSMBr
->CountHigh
);
1676 *nbytes
= (*nbytes
) << 16;
1677 *nbytes
+= le16_to_cpu(pSMBr
->Count
);
1680 * Mask off high 16 bits when bytes written as returned by the
1681 * server is greater than bytes requested by the client. OS/2
1682 * servers are known to set incorrect CountHigh values.
1684 if (*nbytes
> count
)
1688 /* cifs_small_buf_release(pSMB); */ /* Freed earlier now in SendReceive2 */
1689 if (resp_buf_type
== CIFS_SMALL_BUFFER
)
1690 cifs_small_buf_release(iov
[0].iov_base
);
1691 else if (resp_buf_type
== CIFS_LARGE_BUFFER
)
1692 cifs_buf_release(iov
[0].iov_base
);
1694 /* Note: On -EAGAIN error only caller can retry on handle based calls
1695 since file handle passed in no longer valid */
1702 CIFSSMBLock(const int xid
, struct cifsTconInfo
*tcon
,
1703 const __u16 smb_file_id
, const __u64 len
,
1704 const __u64 offset
, const __u32 numUnlock
,
1705 const __u32 numLock
, const __u8 lockType
, const int waitFlag
)
1708 LOCK_REQ
*pSMB
= NULL
;
1709 LOCK_RSP
*pSMBr
= NULL
;
1714 cFYI(1, ("CIFSSMBLock timeout %d numLock %d", waitFlag
, numLock
));
1715 rc
= small_smb_init(SMB_COM_LOCKING_ANDX
, 8, tcon
, (void **) &pSMB
);
1720 pSMBr
= (LOCK_RSP
*)pSMB
; /* BB removeme BB */
1722 if (lockType
== LOCKING_ANDX_OPLOCK_RELEASE
) {
1723 timeout
= CIFS_ASYNC_OP
; /* no response expected */
1725 } else if (waitFlag
== TRUE
) {
1726 timeout
= CIFS_BLOCKING_OP
; /* blocking operation, no timeout */
1727 pSMB
->Timeout
= cpu_to_le32(-1);/* blocking - do not time out */
1732 pSMB
->NumberOfLocks
= cpu_to_le16(numLock
);
1733 pSMB
->NumberOfUnlocks
= cpu_to_le16(numUnlock
);
1734 pSMB
->LockType
= lockType
;
1735 pSMB
->AndXCommand
= 0xFF; /* none */
1736 pSMB
->Fid
= smb_file_id
; /* netfid stays le */
1738 if ((numLock
!= 0) || (numUnlock
!= 0)) {
1739 pSMB
->Locks
[0].Pid
= cpu_to_le16(current
->tgid
);
1740 /* BB where to store pid high? */
1741 pSMB
->Locks
[0].LengthLow
= cpu_to_le32((u32
)len
);
1742 pSMB
->Locks
[0].LengthHigh
= cpu_to_le32((u32
)(len
>>32));
1743 pSMB
->Locks
[0].OffsetLow
= cpu_to_le32((u32
)offset
);
1744 pSMB
->Locks
[0].OffsetHigh
= cpu_to_le32((u32
)(offset
>>32));
1745 count
= sizeof(LOCKING_ANDX_RANGE
);
1750 pSMB
->hdr
.smb_buf_length
+= count
;
1751 pSMB
->ByteCount
= cpu_to_le16(count
);
1754 rc
= SendReceiveBlockingLock(xid
, tcon
, (struct smb_hdr
*) pSMB
,
1755 (struct smb_hdr
*) pSMBr
, &bytes_returned
);
1756 cifs_small_buf_release(pSMB
);
1758 rc
= SendReceiveNoRsp(xid
, tcon
->ses
, (struct smb_hdr
*)pSMB
,
1760 /* SMB buffer freed by function above */
1762 cifs_stats_inc(&tcon
->num_locks
);
1764 cFYI(1, ("Send error in Lock = %d", rc
));
1767 /* Note: On -EAGAIN error only caller can retry on handle based calls
1768 since file handle passed in no longer valid */
1773 CIFSSMBPosixLock(const int xid
, struct cifsTconInfo
*tcon
,
1774 const __u16 smb_file_id
, const int get_flag
, const __u64 len
,
1775 struct file_lock
*pLockData
, const __u16 lock_type
,
1778 struct smb_com_transaction2_sfi_req
*pSMB
= NULL
;
1779 struct smb_com_transaction2_sfi_rsp
*pSMBr
= NULL
;
1780 struct cifs_posix_lock
*parm_data
;
1783 int bytes_returned
= 0;
1784 int resp_buf_type
= 0;
1785 __u16 params
, param_offset
, offset
, byte_count
, count
;
1788 cFYI(1, ("Posix Lock"));
1790 if (pLockData
== NULL
)
1793 rc
= small_smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
);
1798 pSMBr
= (struct smb_com_transaction2_sfi_rsp
*)pSMB
;
1801 pSMB
->MaxSetupCount
= 0;
1804 pSMB
->Reserved2
= 0;
1805 param_offset
= offsetof(struct smb_com_transaction2_sfi_req
, Fid
) - 4;
1806 offset
= param_offset
+ params
;
1808 count
= sizeof(struct cifs_posix_lock
);
1809 pSMB
->MaxParameterCount
= cpu_to_le16(2);
1810 pSMB
->MaxDataCount
= cpu_to_le16(1000); /* BB find max SMB PDU from sess */
1811 pSMB
->SetupCount
= 1;
1812 pSMB
->Reserved3
= 0;
1814 pSMB
->SubCommand
= cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION
);
1816 pSMB
->SubCommand
= cpu_to_le16(TRANS2_SET_FILE_INFORMATION
);
1817 byte_count
= 3 /* pad */ + params
+ count
;
1818 pSMB
->DataCount
= cpu_to_le16(count
);
1819 pSMB
->ParameterCount
= cpu_to_le16(params
);
1820 pSMB
->TotalDataCount
= pSMB
->DataCount
;
1821 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
1822 pSMB
->ParameterOffset
= cpu_to_le16(param_offset
);
1823 parm_data
= (struct cifs_posix_lock
*)
1824 (((char *) &pSMB
->hdr
.Protocol
) + offset
);
1826 parm_data
->lock_type
= cpu_to_le16(lock_type
);
1828 timeout
= CIFS_BLOCKING_OP
; /* blocking operation, no timeout */
1829 parm_data
->lock_flags
= cpu_to_le16(1);
1830 pSMB
->Timeout
= cpu_to_le32(-1);
1834 parm_data
->pid
= cpu_to_le32(current
->tgid
);
1835 parm_data
->start
= cpu_to_le64(pLockData
->fl_start
);
1836 parm_data
->length
= cpu_to_le64(len
); /* normalize negative numbers */
1838 pSMB
->DataOffset
= cpu_to_le16(offset
);
1839 pSMB
->Fid
= smb_file_id
;
1840 pSMB
->InformationLevel
= cpu_to_le16(SMB_SET_POSIX_LOCK
);
1841 pSMB
->Reserved4
= 0;
1842 pSMB
->hdr
.smb_buf_length
+= byte_count
;
1843 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
1845 rc
= SendReceiveBlockingLock(xid
, tcon
, (struct smb_hdr
*) pSMB
,
1846 (struct smb_hdr
*) pSMBr
, &bytes_returned
);
1848 iov
[0].iov_base
= (char *)pSMB
;
1849 iov
[0].iov_len
= pSMB
->hdr
.smb_buf_length
+ 4;
1850 rc
= SendReceive2(xid
, tcon
->ses
, iov
, 1 /* num iovecs */,
1851 &resp_buf_type
, timeout
);
1852 pSMB
= NULL
; /* request buf already freed by SendReceive2. Do
1853 not try to free it twice below on exit */
1854 pSMBr
= (struct smb_com_transaction2_sfi_rsp
*)iov
[0].iov_base
;
1858 cFYI(1, ("Send error in Posix Lock = %d", rc
));
1859 } else if (get_flag
) {
1860 /* lock structure can be returned on get */
1863 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
1865 if (rc
|| (pSMBr
->ByteCount
< sizeof(struct cifs_posix_lock
))) {
1866 rc
= -EIO
; /* bad smb */
1869 if (pLockData
== NULL
) {
1873 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
1874 data_count
= le16_to_cpu(pSMBr
->t2
.DataCount
);
1875 if (data_count
< sizeof(struct cifs_posix_lock
)) {
1879 parm_data
= (struct cifs_posix_lock
*)
1880 ((char *)&pSMBr
->hdr
.Protocol
+ data_offset
);
1881 if (parm_data
->lock_type
== cpu_to_le16(CIFS_UNLCK
))
1882 pLockData
->fl_type
= F_UNLCK
;
1887 cifs_small_buf_release(pSMB
);
1889 if (resp_buf_type
== CIFS_SMALL_BUFFER
)
1890 cifs_small_buf_release(iov
[0].iov_base
);
1891 else if (resp_buf_type
== CIFS_LARGE_BUFFER
)
1892 cifs_buf_release(iov
[0].iov_base
);
1894 /* Note: On -EAGAIN error only caller can retry on handle based calls
1895 since file handle passed in no longer valid */
1902 CIFSSMBClose(const int xid
, struct cifsTconInfo
*tcon
, int smb_file_id
)
1905 CLOSE_REQ
*pSMB
= NULL
;
1906 cFYI(1, ("In CIFSSMBClose"));
1908 /* do not retry on dead session on close */
1909 rc
= small_smb_init(SMB_COM_CLOSE
, 3, tcon
, (void **) &pSMB
);
1915 pSMB
->FileID
= (__u16
) smb_file_id
;
1916 pSMB
->LastWriteTime
= 0xFFFFFFFF;
1917 pSMB
->ByteCount
= 0;
1918 rc
= SendReceiveNoRsp(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
, 0);
1919 cifs_stats_inc(&tcon
->num_closes
);
1922 /* EINTR is expected when user ctl-c to kill app */
1923 cERROR(1, ("Send error in Close = %d", rc
));
1927 /* Since session is dead, file will be closed on server already */
1935 CIFSSMBRename(const int xid
, struct cifsTconInfo
*tcon
,
1936 const char *fromName
, const char *toName
,
1937 const struct nls_table
*nls_codepage
, int remap
)
1940 RENAME_REQ
*pSMB
= NULL
;
1941 RENAME_RSP
*pSMBr
= NULL
;
1943 int name_len
, name_len2
;
1946 cFYI(1, ("In CIFSSMBRename"));
1948 rc
= smb_init(SMB_COM_RENAME
, 1, tcon
, (void **) &pSMB
,
1953 pSMB
->BufferFormat
= 0x04;
1954 pSMB
->SearchAttributes
=
1955 cpu_to_le16(ATTR_READONLY
| ATTR_HIDDEN
| ATTR_SYSTEM
|
1958 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
1960 cifsConvertToUCS((__le16
*) pSMB
->OldFileName
, fromName
,
1961 PATH_MAX
, nls_codepage
, remap
);
1962 name_len
++; /* trailing null */
1964 pSMB
->OldFileName
[name_len
] = 0x04; /* pad */
1965 /* protocol requires ASCII signature byte on Unicode string */
1966 pSMB
->OldFileName
[name_len
+ 1] = 0x00;
1968 cifsConvertToUCS((__le16
*) &pSMB
->OldFileName
[name_len
+ 2],
1969 toName
, PATH_MAX
, nls_codepage
, remap
);
1970 name_len2
+= 1 /* trailing null */ + 1 /* Signature word */ ;
1971 name_len2
*= 2; /* convert to bytes */
1972 } else { /* BB improve the check for buffer overruns BB */
1973 name_len
= strnlen(fromName
, PATH_MAX
);
1974 name_len
++; /* trailing null */
1975 strncpy(pSMB
->OldFileName
, fromName
, name_len
);
1976 name_len2
= strnlen(toName
, PATH_MAX
);
1977 name_len2
++; /* trailing null */
1978 pSMB
->OldFileName
[name_len
] = 0x04; /* 2nd buffer format */
1979 strncpy(&pSMB
->OldFileName
[name_len
+ 1], toName
, name_len2
);
1980 name_len2
++; /* trailing null */
1981 name_len2
++; /* signature byte */
1984 count
= 1 /* 1st signature byte */ + name_len
+ name_len2
;
1985 pSMB
->hdr
.smb_buf_length
+= count
;
1986 pSMB
->ByteCount
= cpu_to_le16(count
);
1988 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
1989 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
1990 cifs_stats_inc(&tcon
->num_renames
);
1992 cFYI(1, ("Send error in rename = %d", rc
));
1995 cifs_buf_release(pSMB
);
2003 int CIFSSMBRenameOpenFile(const int xid
, struct cifsTconInfo
*pTcon
,
2004 int netfid
, char *target_name
,
2005 const struct nls_table
*nls_codepage
, int remap
)
2007 struct smb_com_transaction2_sfi_req
*pSMB
= NULL
;
2008 struct smb_com_transaction2_sfi_rsp
*pSMBr
= NULL
;
2009 struct set_file_rename
*rename_info
;
2011 char dummy_string
[30];
2013 int bytes_returned
= 0;
2015 __u16 params
, param_offset
, offset
, count
, byte_count
;
2017 cFYI(1, ("Rename to File by handle"));
2018 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, pTcon
, (void **) &pSMB
,
2024 pSMB
->MaxSetupCount
= 0;
2028 pSMB
->Reserved2
= 0;
2029 param_offset
= offsetof(struct smb_com_transaction2_sfi_req
, Fid
) - 4;
2030 offset
= param_offset
+ params
;
2032 data_offset
= (char *) (&pSMB
->hdr
.Protocol
) + offset
;
2033 rename_info
= (struct set_file_rename
*) data_offset
;
2034 pSMB
->MaxParameterCount
= cpu_to_le16(2);
2035 pSMB
->MaxDataCount
= cpu_to_le16(1000); /* BB find max SMB PDU from sess */
2036 pSMB
->SetupCount
= 1;
2037 pSMB
->Reserved3
= 0;
2038 pSMB
->SubCommand
= cpu_to_le16(TRANS2_SET_FILE_INFORMATION
);
2039 byte_count
= 3 /* pad */ + params
;
2040 pSMB
->ParameterCount
= cpu_to_le16(params
);
2041 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
2042 pSMB
->ParameterOffset
= cpu_to_le16(param_offset
);
2043 pSMB
->DataOffset
= cpu_to_le16(offset
);
2044 /* construct random name ".cifs_tmp<inodenum><mid>" */
2045 rename_info
->overwrite
= cpu_to_le32(1);
2046 rename_info
->root_fid
= 0;
2047 /* unicode only call */
2048 if (target_name
== NULL
) {
2049 sprintf(dummy_string
, "cifs%x", pSMB
->hdr
.Mid
);
2050 len_of_str
= cifsConvertToUCS((__le16
*)rename_info
->target_name
,
2051 dummy_string
, 24, nls_codepage
, remap
);
2053 len_of_str
= cifsConvertToUCS((__le16
*)rename_info
->target_name
,
2054 target_name
, PATH_MAX
, nls_codepage
,
2057 rename_info
->target_name_len
= cpu_to_le32(2 * len_of_str
);
2058 count
= 12 /* sizeof(struct set_file_rename) */ + (2 * len_of_str
) + 2;
2059 byte_count
+= count
;
2060 pSMB
->DataCount
= cpu_to_le16(count
);
2061 pSMB
->TotalDataCount
= pSMB
->DataCount
;
2063 pSMB
->InformationLevel
=
2064 cpu_to_le16(SMB_SET_FILE_RENAME_INFORMATION
);
2065 pSMB
->Reserved4
= 0;
2066 pSMB
->hdr
.smb_buf_length
+= byte_count
;
2067 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
2068 rc
= SendReceive(xid
, pTcon
->ses
, (struct smb_hdr
*) pSMB
,
2069 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
2070 cifs_stats_inc(&pTcon
->num_t2renames
);
2072 cFYI(1, ("Send error in Rename (by file handle) = %d", rc
));
2075 cifs_buf_release(pSMB
);
2077 /* Note: On -EAGAIN error only caller can retry on handle based calls
2078 since file handle passed in no longer valid */
2084 CIFSSMBCopy(const int xid
, struct cifsTconInfo
*tcon
, const char *fromName
,
2085 const __u16 target_tid
, const char *toName
, const int flags
,
2086 const struct nls_table
*nls_codepage
, int remap
)
2089 COPY_REQ
*pSMB
= NULL
;
2090 COPY_RSP
*pSMBr
= NULL
;
2092 int name_len
, name_len2
;
2095 cFYI(1, ("In CIFSSMBCopy"));
2097 rc
= smb_init(SMB_COM_COPY
, 1, tcon
, (void **) &pSMB
,
2102 pSMB
->BufferFormat
= 0x04;
2103 pSMB
->Tid2
= target_tid
;
2105 pSMB
->Flags
= cpu_to_le16(flags
& COPY_TREE
);
2107 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
2108 name_len
= cifsConvertToUCS((__le16
*) pSMB
->OldFileName
,
2109 fromName
, PATH_MAX
, nls_codepage
,
2111 name_len
++; /* trailing null */
2113 pSMB
->OldFileName
[name_len
] = 0x04; /* pad */
2114 /* protocol requires ASCII signature byte on Unicode string */
2115 pSMB
->OldFileName
[name_len
+ 1] = 0x00;
2117 cifsConvertToUCS((__le16
*)&pSMB
->OldFileName
[name_len
+ 2],
2118 toName
, PATH_MAX
, nls_codepage
, remap
);
2119 name_len2
+= 1 /* trailing null */ + 1 /* Signature word */ ;
2120 name_len2
*= 2; /* convert to bytes */
2121 } else { /* BB improve the check for buffer overruns BB */
2122 name_len
= strnlen(fromName
, PATH_MAX
);
2123 name_len
++; /* trailing null */
2124 strncpy(pSMB
->OldFileName
, fromName
, name_len
);
2125 name_len2
= strnlen(toName
, PATH_MAX
);
2126 name_len2
++; /* trailing null */
2127 pSMB
->OldFileName
[name_len
] = 0x04; /* 2nd buffer format */
2128 strncpy(&pSMB
->OldFileName
[name_len
+ 1], toName
, name_len2
);
2129 name_len2
++; /* trailing null */
2130 name_len2
++; /* signature byte */
2133 count
= 1 /* 1st signature byte */ + name_len
+ name_len2
;
2134 pSMB
->hdr
.smb_buf_length
+= count
;
2135 pSMB
->ByteCount
= cpu_to_le16(count
);
2137 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
2138 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
2140 cFYI(1, ("Send error in copy = %d with %d files copied",
2141 rc
, le16_to_cpu(pSMBr
->CopyCount
)));
2144 cifs_buf_release(pSMB
);
2153 CIFSUnixCreateSymLink(const int xid
, struct cifsTconInfo
*tcon
,
2154 const char *fromName
, const char *toName
,
2155 const struct nls_table
*nls_codepage
)
2157 TRANSACTION2_SPI_REQ
*pSMB
= NULL
;
2158 TRANSACTION2_SPI_RSP
*pSMBr
= NULL
;
2161 int name_len_target
;
2163 int bytes_returned
= 0;
2164 __u16 params
, param_offset
, offset
, byte_count
;
2166 cFYI(1, ("In Symlink Unix style"));
2168 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
2173 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
2175 cifs_strtoUCS((__le16
*) pSMB
->FileName
, fromName
, PATH_MAX
2176 /* find define for this maxpathcomponent */
2178 name_len
++; /* trailing null */
2181 } else { /* BB improve the check for buffer overruns BB */
2182 name_len
= strnlen(fromName
, PATH_MAX
);
2183 name_len
++; /* trailing null */
2184 strncpy(pSMB
->FileName
, fromName
, name_len
);
2186 params
= 6 + name_len
;
2187 pSMB
->MaxSetupCount
= 0;
2191 pSMB
->Reserved2
= 0;
2192 param_offset
= offsetof(struct smb_com_transaction2_spi_req
,
2193 InformationLevel
) - 4;
2194 offset
= param_offset
+ params
;
2196 data_offset
= (char *) (&pSMB
->hdr
.Protocol
) + offset
;
2197 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
2199 cifs_strtoUCS((__le16
*) data_offset
, toName
, PATH_MAX
2200 /* find define for this maxpathcomponent */
2202 name_len_target
++; /* trailing null */
2203 name_len_target
*= 2;
2204 } else { /* BB improve the check for buffer overruns BB */
2205 name_len_target
= strnlen(toName
, PATH_MAX
);
2206 name_len_target
++; /* trailing null */
2207 strncpy(data_offset
, toName
, name_len_target
);
2210 pSMB
->MaxParameterCount
= cpu_to_le16(2);
2211 /* BB find exact max on data count below from sess */
2212 pSMB
->MaxDataCount
= cpu_to_le16(1000);
2213 pSMB
->SetupCount
= 1;
2214 pSMB
->Reserved3
= 0;
2215 pSMB
->SubCommand
= cpu_to_le16(TRANS2_SET_PATH_INFORMATION
);
2216 byte_count
= 3 /* pad */ + params
+ name_len_target
;
2217 pSMB
->DataCount
= cpu_to_le16(name_len_target
);
2218 pSMB
->ParameterCount
= cpu_to_le16(params
);
2219 pSMB
->TotalDataCount
= pSMB
->DataCount
;
2220 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
2221 pSMB
->ParameterOffset
= cpu_to_le16(param_offset
);
2222 pSMB
->DataOffset
= cpu_to_le16(offset
);
2223 pSMB
->InformationLevel
= cpu_to_le16(SMB_SET_FILE_UNIX_LINK
);
2224 pSMB
->Reserved4
= 0;
2225 pSMB
->hdr
.smb_buf_length
+= byte_count
;
2226 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
2227 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
2228 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
2229 cifs_stats_inc(&tcon
->num_symlinks
);
2231 cFYI(1, ("Send error in SetPathInfo create symlink = %d", rc
));
2235 cifs_buf_release(pSMB
);
2238 goto createSymLinkRetry
;
2244 CIFSUnixCreateHardLink(const int xid
, struct cifsTconInfo
*tcon
,
2245 const char *fromName
, const char *toName
,
2246 const struct nls_table
*nls_codepage
, int remap
)
2248 TRANSACTION2_SPI_REQ
*pSMB
= NULL
;
2249 TRANSACTION2_SPI_RSP
*pSMBr
= NULL
;
2252 int name_len_target
;
2254 int bytes_returned
= 0;
2255 __u16 params
, param_offset
, offset
, byte_count
;
2257 cFYI(1, ("In Create Hard link Unix style"));
2258 createHardLinkRetry
:
2259 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
2264 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
2265 name_len
= cifsConvertToUCS((__le16
*) pSMB
->FileName
, toName
,
2266 PATH_MAX
, nls_codepage
, remap
);
2267 name_len
++; /* trailing null */
2270 } else { /* BB improve the check for buffer overruns BB */
2271 name_len
= strnlen(toName
, PATH_MAX
);
2272 name_len
++; /* trailing null */
2273 strncpy(pSMB
->FileName
, toName
, name_len
);
2275 params
= 6 + name_len
;
2276 pSMB
->MaxSetupCount
= 0;
2280 pSMB
->Reserved2
= 0;
2281 param_offset
= offsetof(struct smb_com_transaction2_spi_req
,
2282 InformationLevel
) - 4;
2283 offset
= param_offset
+ params
;
2285 data_offset
= (char *) (&pSMB
->hdr
.Protocol
) + offset
;
2286 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
2288 cifsConvertToUCS((__le16
*) data_offset
, fromName
, PATH_MAX
,
2289 nls_codepage
, remap
);
2290 name_len_target
++; /* trailing null */
2291 name_len_target
*= 2;
2292 } else { /* BB improve the check for buffer overruns BB */
2293 name_len_target
= strnlen(fromName
, PATH_MAX
);
2294 name_len_target
++; /* trailing null */
2295 strncpy(data_offset
, fromName
, name_len_target
);
2298 pSMB
->MaxParameterCount
= cpu_to_le16(2);
2299 /* BB find exact max on data count below from sess*/
2300 pSMB
->MaxDataCount
= cpu_to_le16(1000);
2301 pSMB
->SetupCount
= 1;
2302 pSMB
->Reserved3
= 0;
2303 pSMB
->SubCommand
= cpu_to_le16(TRANS2_SET_PATH_INFORMATION
);
2304 byte_count
= 3 /* pad */ + params
+ name_len_target
;
2305 pSMB
->ParameterCount
= cpu_to_le16(params
);
2306 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
2307 pSMB
->DataCount
= cpu_to_le16(name_len_target
);
2308 pSMB
->TotalDataCount
= pSMB
->DataCount
;
2309 pSMB
->ParameterOffset
= cpu_to_le16(param_offset
);
2310 pSMB
->DataOffset
= cpu_to_le16(offset
);
2311 pSMB
->InformationLevel
= cpu_to_le16(SMB_SET_FILE_UNIX_HLINK
);
2312 pSMB
->Reserved4
= 0;
2313 pSMB
->hdr
.smb_buf_length
+= byte_count
;
2314 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
2315 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
2316 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
2317 cifs_stats_inc(&tcon
->num_hardlinks
);
2319 cFYI(1, ("Send error in SetPathInfo (hard link) = %d", rc
));
2322 cifs_buf_release(pSMB
);
2324 goto createHardLinkRetry
;
2330 CIFSCreateHardLink(const int xid
, struct cifsTconInfo
*tcon
,
2331 const char *fromName
, const char *toName
,
2332 const struct nls_table
*nls_codepage
, int remap
)
2335 NT_RENAME_REQ
*pSMB
= NULL
;
2336 RENAME_RSP
*pSMBr
= NULL
;
2338 int name_len
, name_len2
;
2341 cFYI(1, ("In CIFSCreateHardLink"));
2342 winCreateHardLinkRetry
:
2344 rc
= smb_init(SMB_COM_NT_RENAME
, 4, tcon
, (void **) &pSMB
,
2349 pSMB
->SearchAttributes
=
2350 cpu_to_le16(ATTR_READONLY
| ATTR_HIDDEN
| ATTR_SYSTEM
|
2352 pSMB
->Flags
= cpu_to_le16(CREATE_HARD_LINK
);
2353 pSMB
->ClusterCount
= 0;
2355 pSMB
->BufferFormat
= 0x04;
2357 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
2359 cifsConvertToUCS((__le16
*) pSMB
->OldFileName
, fromName
,
2360 PATH_MAX
, nls_codepage
, remap
);
2361 name_len
++; /* trailing null */
2363 pSMB
->OldFileName
[name_len
] = 0; /* pad */
2364 pSMB
->OldFileName
[name_len
+ 1] = 0x04;
2366 cifsConvertToUCS((__le16
*)&pSMB
->OldFileName
[name_len
+ 2],
2367 toName
, PATH_MAX
, nls_codepage
, remap
);
2368 name_len2
+= 1 /* trailing null */ + 1 /* Signature word */ ;
2369 name_len2
*= 2; /* convert to bytes */
2370 } else { /* BB improve the check for buffer overruns BB */
2371 name_len
= strnlen(fromName
, PATH_MAX
);
2372 name_len
++; /* trailing null */
2373 strncpy(pSMB
->OldFileName
, fromName
, name_len
);
2374 name_len2
= strnlen(toName
, PATH_MAX
);
2375 name_len2
++; /* trailing null */
2376 pSMB
->OldFileName
[name_len
] = 0x04; /* 2nd buffer format */
2377 strncpy(&pSMB
->OldFileName
[name_len
+ 1], toName
, name_len2
);
2378 name_len2
++; /* trailing null */
2379 name_len2
++; /* signature byte */
2382 count
= 1 /* string type byte */ + name_len
+ name_len2
;
2383 pSMB
->hdr
.smb_buf_length
+= count
;
2384 pSMB
->ByteCount
= cpu_to_le16(count
);
2386 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
2387 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
2388 cifs_stats_inc(&tcon
->num_hardlinks
);
2390 cFYI(1, ("Send error in hard link (NT rename) = %d", rc
));
2392 cifs_buf_release(pSMB
);
2394 goto winCreateHardLinkRetry
;
2400 CIFSSMBUnixQuerySymLink(const int xid
, struct cifsTconInfo
*tcon
,
2401 const unsigned char *searchName
,
2402 char *symlinkinfo
, const int buflen
,
2403 const struct nls_table
*nls_codepage
)
2405 /* SMB_QUERY_FILE_UNIX_LINK */
2406 TRANSACTION2_QPI_REQ
*pSMB
= NULL
;
2407 TRANSACTION2_QPI_RSP
*pSMBr
= NULL
;
2411 __u16 params
, byte_count
;
2413 cFYI(1, ("In QPathSymLinkInfo (Unix) for path %s", searchName
));
2416 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
2421 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
2423 cifs_strtoUCS((__le16
*) pSMB
->FileName
, searchName
,
2424 PATH_MAX
, nls_codepage
);
2425 name_len
++; /* trailing null */
2427 } else { /* BB improve the check for buffer overruns BB */
2428 name_len
= strnlen(searchName
, PATH_MAX
);
2429 name_len
++; /* trailing null */
2430 strncpy(pSMB
->FileName
, searchName
, name_len
);
2433 params
= 2 /* level */ + 4 /* rsrvd */ + name_len
/* incl null */ ;
2434 pSMB
->TotalDataCount
= 0;
2435 pSMB
->MaxParameterCount
= cpu_to_le16(2);
2436 /* BB find exact max data count below from sess structure BB */
2437 pSMB
->MaxDataCount
= cpu_to_le16(4000);
2438 pSMB
->MaxSetupCount
= 0;
2442 pSMB
->Reserved2
= 0;
2443 pSMB
->ParameterOffset
= cpu_to_le16(offsetof(
2444 struct smb_com_transaction2_qpi_req
, InformationLevel
) - 4);
2445 pSMB
->DataCount
= 0;
2446 pSMB
->DataOffset
= 0;
2447 pSMB
->SetupCount
= 1;
2448 pSMB
->Reserved3
= 0;
2449 pSMB
->SubCommand
= cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION
);
2450 byte_count
= params
+ 1 /* pad */ ;
2451 pSMB
->TotalParameterCount
= cpu_to_le16(params
);
2452 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
2453 pSMB
->InformationLevel
= cpu_to_le16(SMB_QUERY_FILE_UNIX_LINK
);
2454 pSMB
->Reserved4
= 0;
2455 pSMB
->hdr
.smb_buf_length
+= byte_count
;
2456 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
2458 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
2459 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
2461 cFYI(1, ("Send error in QuerySymLinkInfo = %d", rc
));
2463 /* decode response */
2465 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
2466 if (rc
|| (pSMBr
->ByteCount
< 2))
2467 /* BB also check enough total bytes returned */
2468 rc
= -EIO
; /* bad smb */
2470 __u16 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
2471 __u16 count
= le16_to_cpu(pSMBr
->t2
.DataCount
);
2473 if (pSMBr
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
2474 name_len
= UniStrnlen((wchar_t *) ((char *)
2475 &pSMBr
->hdr
.Protocol
+ data_offset
),
2476 min_t(const int, buflen
, count
) / 2);
2477 /* BB FIXME investigate remapping reserved chars here */
2478 cifs_strfromUCS_le(symlinkinfo
,
2479 (__le16
*) ((char *)&pSMBr
->hdr
.Protocol
2481 name_len
, nls_codepage
);
2483 strncpy(symlinkinfo
,
2484 (char *) &pSMBr
->hdr
.Protocol
+
2486 min_t(const int, buflen
, count
));
2488 symlinkinfo
[buflen
] = 0;
2489 /* just in case so calling code does not go off the end of buffer */
2492 cifs_buf_release(pSMB
);
2494 goto querySymLinkRetry
;
2498 #ifdef CONFIG_CIFS_EXPERIMENTAL
2499 /* Initialize NT TRANSACT SMB into small smb request buffer.
2500 This assumes that all NT TRANSACTS that we init here have
2501 total parm and data under about 400 bytes (to fit in small cifs
2502 buffer size), which is the case so far, it easily fits. NB:
2503 Setup words themselves and ByteCount
2504 MaxSetupCount (size of returned setup area) and
2505 MaxParameterCount (returned parms size) must be set by caller */
2507 smb_init_nttransact(const __u16 sub_command
, const int setup_count
,
2508 const int parm_len
, struct cifsTconInfo
*tcon
,
2513 struct smb_com_ntransact_req
*pSMB
;
2515 rc
= small_smb_init(SMB_COM_NT_TRANSACT
, 19 + setup_count
, tcon
,
2519 *ret_buf
= (void *)pSMB
;
2521 pSMB
->TotalParameterCount
= cpu_to_le32(parm_len
);
2522 pSMB
->TotalDataCount
= 0;
2523 pSMB
->MaxDataCount
= cpu_to_le32((tcon
->ses
->server
->maxBuf
-
2524 MAX_CIFS_HDR_SIZE
) & 0xFFFFFF00);
2525 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
2526 pSMB
->DataCount
= pSMB
->TotalDataCount
;
2527 temp_offset
= offsetof(struct smb_com_ntransact_req
, Parms
) +
2528 (setup_count
* 2) - 4 /* for rfc1001 length itself */;
2529 pSMB
->ParameterOffset
= cpu_to_le32(temp_offset
);
2530 pSMB
->DataOffset
= cpu_to_le32(temp_offset
+ parm_len
);
2531 pSMB
->SetupCount
= setup_count
; /* no need to le convert byte fields */
2532 pSMB
->SubCommand
= cpu_to_le16(sub_command
);
2537 validate_ntransact(char *buf
, char **ppparm
, char **ppdata
,
2538 __u32
*pparmlen
, __u32
*pdatalen
)
2541 __u32 data_count
, data_offset
, parm_count
, parm_offset
;
2542 struct smb_com_ntransact_rsp
*pSMBr
;
2550 pSMBr
= (struct smb_com_ntransact_rsp
*)buf
;
2552 /* ByteCount was converted from little endian in SendReceive */
2553 end_of_smb
= 2 /* sizeof byte count */ + pSMBr
->ByteCount
+
2554 (char *)&pSMBr
->ByteCount
;
2556 data_offset
= le32_to_cpu(pSMBr
->DataOffset
);
2557 data_count
= le32_to_cpu(pSMBr
->DataCount
);
2558 parm_offset
= le32_to_cpu(pSMBr
->ParameterOffset
);
2559 parm_count
= le32_to_cpu(pSMBr
->ParameterCount
);
2561 *ppparm
= (char *)&pSMBr
->hdr
.Protocol
+ parm_offset
;
2562 *ppdata
= (char *)&pSMBr
->hdr
.Protocol
+ data_offset
;
2564 /* should we also check that parm and data areas do not overlap? */
2565 if (*ppparm
> end_of_smb
) {
2566 cFYI(1, ("parms start after end of smb"));
2568 } else if (parm_count
+ *ppparm
> end_of_smb
) {
2569 cFYI(1, ("parm end after end of smb"));
2571 } else if (*ppdata
> end_of_smb
) {
2572 cFYI(1, ("data starts after end of smb"));
2574 } else if (data_count
+ *ppdata
> end_of_smb
) {
2575 cFYI(1, ("data %p + count %d (%p) ends after end of smb %p start %p",
2576 *ppdata
, data_count
, (data_count
+ *ppdata
),
2577 end_of_smb
, pSMBr
));
2579 } else if (parm_count
+ data_count
> pSMBr
->ByteCount
) {
2580 cFYI(1, ("parm count and data count larger than SMB"));
2583 *pdatalen
= data_count
;
2584 *pparmlen
= parm_count
;
2587 #endif /* CIFS_EXPERIMENTAL */
2590 CIFSSMBQueryReparseLinkInfo(const int xid
, struct cifsTconInfo
*tcon
,
2591 const unsigned char *searchName
,
2592 char *symlinkinfo
, const int buflen
, __u16 fid
,
2593 const struct nls_table
*nls_codepage
)
2598 struct smb_com_transaction_ioctl_req
*pSMB
;
2599 struct smb_com_transaction_ioctl_rsp
*pSMBr
;
2601 cFYI(1, ("In Windows reparse style QueryLink for path %s", searchName
));
2602 rc
= smb_init(SMB_COM_NT_TRANSACT
, 23, tcon
, (void **) &pSMB
,
2607 pSMB
->TotalParameterCount
= 0 ;
2608 pSMB
->TotalDataCount
= 0;
2609 pSMB
->MaxParameterCount
= cpu_to_le32(2);
2610 /* BB find exact data count max from sess structure BB */
2611 pSMB
->MaxDataCount
= cpu_to_le32((tcon
->ses
->server
->maxBuf
-
2612 MAX_CIFS_HDR_SIZE
) & 0xFFFFFF00);
2613 pSMB
->MaxSetupCount
= 4;
2615 pSMB
->ParameterOffset
= 0;
2616 pSMB
->DataCount
= 0;
2617 pSMB
->DataOffset
= 0;
2618 pSMB
->SetupCount
= 4;
2619 pSMB
->SubCommand
= cpu_to_le16(NT_TRANSACT_IOCTL
);
2620 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
2621 pSMB
->FunctionCode
= cpu_to_le32(FSCTL_GET_REPARSE_POINT
);
2622 pSMB
->IsFsctl
= 1; /* FSCTL */
2623 pSMB
->IsRootFlag
= 0;
2624 pSMB
->Fid
= fid
; /* file handle always le */
2625 pSMB
->ByteCount
= 0;
2627 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
2628 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
2630 cFYI(1, ("Send error in QueryReparseLinkInfo = %d", rc
));
2631 } else { /* decode response */
2632 __u32 data_offset
= le32_to_cpu(pSMBr
->DataOffset
);
2633 __u32 data_count
= le32_to_cpu(pSMBr
->DataCount
);
2634 if ((pSMBr
->ByteCount
< 2) || (data_offset
> 512))
2635 /* BB also check enough total bytes returned */
2636 rc
= -EIO
; /* bad smb */
2638 if (data_count
&& (data_count
< 2048)) {
2639 char *end_of_smb
= 2 /* sizeof byte count */ +
2641 (char *)&pSMBr
->ByteCount
;
2643 struct reparse_data
*reparse_buf
=
2644 (struct reparse_data
*)
2645 ((char *)&pSMBr
->hdr
.Protocol
2647 if ((char *)reparse_buf
>= end_of_smb
) {
2651 if ((reparse_buf
->LinkNamesBuf
+
2652 reparse_buf
->TargetNameOffset
+
2653 reparse_buf
->TargetNameLen
) >
2655 cFYI(1, ("reparse buf beyond SMB"));
2660 if (pSMBr
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
2661 name_len
= UniStrnlen((wchar_t *)
2662 (reparse_buf
->LinkNamesBuf
+
2663 reparse_buf
->TargetNameOffset
),
2665 reparse_buf
->TargetNameLen
/ 2));
2666 cifs_strfromUCS_le(symlinkinfo
,
2667 (__le16
*) (reparse_buf
->LinkNamesBuf
+
2668 reparse_buf
->TargetNameOffset
),
2669 name_len
, nls_codepage
);
2670 } else { /* ASCII names */
2671 strncpy(symlinkinfo
,
2672 reparse_buf
->LinkNamesBuf
+
2673 reparse_buf
->TargetNameOffset
,
2674 min_t(const int, buflen
,
2675 reparse_buf
->TargetNameLen
));
2679 cFYI(1, ("Invalid return data count on "
2680 "get reparse info ioctl"));
2682 symlinkinfo
[buflen
] = 0; /* just in case so the caller
2683 does not go off the end of the buffer */
2684 cFYI(1, ("readlink result - %s", symlinkinfo
));
2688 cifs_buf_release(pSMB
);
2690 /* Note: On -EAGAIN error only caller can retry on handle based calls
2691 since file handle passed in no longer valid */
2696 #ifdef CONFIG_CIFS_POSIX
2698 /*Convert an Access Control Entry from wire format to local POSIX xattr format*/
2699 static void cifs_convert_ace(posix_acl_xattr_entry
*ace
,
2700 struct cifs_posix_ace
*cifs_ace
)
2702 /* u8 cifs fields do not need le conversion */
2703 ace
->e_perm
= cpu_to_le16(cifs_ace
->cifs_e_perm
);
2704 ace
->e_tag
= cpu_to_le16(cifs_ace
->cifs_e_tag
);
2705 ace
->e_id
= cpu_to_le32(le64_to_cpu(cifs_ace
->cifs_uid
));
2706 /* cFYI(1,("perm %d tag %d id %d",ace->e_perm,ace->e_tag,ace->e_id)); */
2711 /* Convert ACL from CIFS POSIX wire format to local Linux POSIX ACL xattr */
2712 static int cifs_copy_posix_acl(char *trgt
, char *src
, const int buflen
,
2713 const int acl_type
, const int size_of_data_area
)
2718 struct cifs_posix_ace
*pACE
;
2719 struct cifs_posix_acl
*cifs_acl
= (struct cifs_posix_acl
*)src
;
2720 posix_acl_xattr_header
*local_acl
= (posix_acl_xattr_header
*)trgt
;
2722 if (le16_to_cpu(cifs_acl
->version
) != CIFS_ACL_VERSION
)
2725 if (acl_type
& ACL_TYPE_ACCESS
) {
2726 count
= le16_to_cpu(cifs_acl
->access_entry_count
);
2727 pACE
= &cifs_acl
->ace_array
[0];
2728 size
= sizeof(struct cifs_posix_acl
);
2729 size
+= sizeof(struct cifs_posix_ace
) * count
;
2730 /* check if we would go beyond end of SMB */
2731 if (size_of_data_area
< size
) {
2732 cFYI(1, ("bad CIFS POSIX ACL size %d vs. %d",
2733 size_of_data_area
, size
));
2736 } else if (acl_type
& ACL_TYPE_DEFAULT
) {
2737 count
= le16_to_cpu(cifs_acl
->access_entry_count
);
2738 size
= sizeof(struct cifs_posix_acl
);
2739 size
+= sizeof(struct cifs_posix_ace
) * count
;
2740 /* skip past access ACEs to get to default ACEs */
2741 pACE
= &cifs_acl
->ace_array
[count
];
2742 count
= le16_to_cpu(cifs_acl
->default_entry_count
);
2743 size
+= sizeof(struct cifs_posix_ace
) * count
;
2744 /* check if we would go beyond end of SMB */
2745 if (size_of_data_area
< size
)
2752 size
= posix_acl_xattr_size(count
);
2753 if ((buflen
== 0) || (local_acl
== NULL
)) {
2754 /* used to query ACL EA size */
2755 } else if (size
> buflen
) {
2757 } else /* buffer big enough */ {
2758 local_acl
->a_version
= cpu_to_le32(POSIX_ACL_XATTR_VERSION
);
2759 for (i
= 0; i
< count
; i
++) {
2760 cifs_convert_ace(&local_acl
->a_entries
[i
], pACE
);
2767 static __u16
convert_ace_to_cifs_ace(struct cifs_posix_ace
*cifs_ace
,
2768 const posix_acl_xattr_entry
*local_ace
)
2770 __u16 rc
= 0; /* 0 = ACL converted ok */
2772 cifs_ace
->cifs_e_perm
= le16_to_cpu(local_ace
->e_perm
);
2773 cifs_ace
->cifs_e_tag
= le16_to_cpu(local_ace
->e_tag
);
2774 /* BB is there a better way to handle the large uid? */
2775 if (local_ace
->e_id
== cpu_to_le32(-1)) {
2776 /* Probably no need to le convert -1 on any arch but can not hurt */
2777 cifs_ace
->cifs_uid
= cpu_to_le64(-1);
2779 cifs_ace
->cifs_uid
= cpu_to_le64(le32_to_cpu(local_ace
->e_id
));
2780 /*cFYI(1,("perm %d tag %d id %d",ace->e_perm,ace->e_tag,ace->e_id));*/
2784 /* Convert ACL from local Linux POSIX xattr to CIFS POSIX ACL wire format */
2785 static __u16
ACL_to_cifs_posix(char *parm_data
, const char *pACL
,
2786 const int buflen
, const int acl_type
)
2789 struct cifs_posix_acl
*cifs_acl
= (struct cifs_posix_acl
*)parm_data
;
2790 posix_acl_xattr_header
*local_acl
= (posix_acl_xattr_header
*)pACL
;
2794 if ((buflen
== 0) || (pACL
== NULL
) || (cifs_acl
== NULL
))
2797 count
= posix_acl_xattr_count((size_t)buflen
);
2798 cFYI(1, ("setting acl with %d entries from buf of length %d and "
2800 count
, buflen
, le32_to_cpu(local_acl
->a_version
)));
2801 if (le32_to_cpu(local_acl
->a_version
) != 2) {
2802 cFYI(1, ("unknown POSIX ACL version %d",
2803 le32_to_cpu(local_acl
->a_version
)));
2806 cifs_acl
->version
= cpu_to_le16(1);
2807 if (acl_type
== ACL_TYPE_ACCESS
)
2808 cifs_acl
->access_entry_count
= cpu_to_le16(count
);
2809 else if (acl_type
== ACL_TYPE_DEFAULT
)
2810 cifs_acl
->default_entry_count
= cpu_to_le16(count
);
2812 cFYI(1, ("unknown ACL type %d", acl_type
));
2815 for (i
= 0; i
< count
; i
++) {
2816 rc
= convert_ace_to_cifs_ace(&cifs_acl
->ace_array
[i
],
2817 &local_acl
->a_entries
[i
]);
2819 /* ACE not converted */
2824 rc
= (__u16
)(count
* sizeof(struct cifs_posix_ace
));
2825 rc
+= sizeof(struct cifs_posix_acl
);
2826 /* BB add check to make sure ACL does not overflow SMB */
2832 CIFSSMBGetPosixACL(const int xid
, struct cifsTconInfo
*tcon
,
2833 const unsigned char *searchName
,
2834 char *acl_inf
, const int buflen
, const int acl_type
,
2835 const struct nls_table
*nls_codepage
, int remap
)
2837 /* SMB_QUERY_POSIX_ACL */
2838 TRANSACTION2_QPI_REQ
*pSMB
= NULL
;
2839 TRANSACTION2_QPI_RSP
*pSMBr
= NULL
;
2843 __u16 params
, byte_count
;
2845 cFYI(1, ("In GetPosixACL (Unix) for path %s", searchName
));
2848 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
2853 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
2855 cifsConvertToUCS((__le16
*) pSMB
->FileName
, searchName
,
2856 PATH_MAX
, nls_codepage
, remap
);
2857 name_len
++; /* trailing null */
2859 pSMB
->FileName
[name_len
] = 0;
2860 pSMB
->FileName
[name_len
+1] = 0;
2861 } else { /* BB improve the check for buffer overruns BB */
2862 name_len
= strnlen(searchName
, PATH_MAX
);
2863 name_len
++; /* trailing null */
2864 strncpy(pSMB
->FileName
, searchName
, name_len
);
2867 params
= 2 /* level */ + 4 /* rsrvd */ + name_len
/* incl null */ ;
2868 pSMB
->TotalDataCount
= 0;
2869 pSMB
->MaxParameterCount
= cpu_to_le16(2);
2870 /* BB find exact max data count below from sess structure BB */
2871 pSMB
->MaxDataCount
= cpu_to_le16(4000);
2872 pSMB
->MaxSetupCount
= 0;
2876 pSMB
->Reserved2
= 0;
2877 pSMB
->ParameterOffset
= cpu_to_le16(
2878 offsetof(struct smb_com_transaction2_qpi_req
,
2879 InformationLevel
) - 4);
2880 pSMB
->DataCount
= 0;
2881 pSMB
->DataOffset
= 0;
2882 pSMB
->SetupCount
= 1;
2883 pSMB
->Reserved3
= 0;
2884 pSMB
->SubCommand
= cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION
);
2885 byte_count
= params
+ 1 /* pad */ ;
2886 pSMB
->TotalParameterCount
= cpu_to_le16(params
);
2887 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
2888 pSMB
->InformationLevel
= cpu_to_le16(SMB_QUERY_POSIX_ACL
);
2889 pSMB
->Reserved4
= 0;
2890 pSMB
->hdr
.smb_buf_length
+= byte_count
;
2891 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
2893 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
2894 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
2895 cifs_stats_inc(&tcon
->num_acl_get
);
2897 cFYI(1, ("Send error in Query POSIX ACL = %d", rc
));
2899 /* decode response */
2901 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
2902 if (rc
|| (pSMBr
->ByteCount
< 2))
2903 /* BB also check enough total bytes returned */
2904 rc
= -EIO
; /* bad smb */
2906 __u16 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
2907 __u16 count
= le16_to_cpu(pSMBr
->t2
.DataCount
);
2908 rc
= cifs_copy_posix_acl(acl_inf
,
2909 (char *)&pSMBr
->hdr
.Protocol
+data_offset
,
2910 buflen
, acl_type
, count
);
2913 cifs_buf_release(pSMB
);
2920 CIFSSMBSetPosixACL(const int xid
, struct cifsTconInfo
*tcon
,
2921 const unsigned char *fileName
,
2922 const char *local_acl
, const int buflen
,
2924 const struct nls_table
*nls_codepage
, int remap
)
2926 struct smb_com_transaction2_spi_req
*pSMB
= NULL
;
2927 struct smb_com_transaction2_spi_rsp
*pSMBr
= NULL
;
2931 int bytes_returned
= 0;
2932 __u16 params
, byte_count
, data_count
, param_offset
, offset
;
2934 cFYI(1, ("In SetPosixACL (Unix) for path %s", fileName
));
2936 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
2940 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
2942 cifsConvertToUCS((__le16
*) pSMB
->FileName
, fileName
,
2943 PATH_MAX
, nls_codepage
, remap
);
2944 name_len
++; /* trailing null */
2946 } else { /* BB improve the check for buffer overruns BB */
2947 name_len
= strnlen(fileName
, PATH_MAX
);
2948 name_len
++; /* trailing null */
2949 strncpy(pSMB
->FileName
, fileName
, name_len
);
2951 params
= 6 + name_len
;
2952 pSMB
->MaxParameterCount
= cpu_to_le16(2);
2953 pSMB
->MaxDataCount
= cpu_to_le16(1000); /* BB find max SMB size from sess */
2954 pSMB
->MaxSetupCount
= 0;
2958 pSMB
->Reserved2
= 0;
2959 param_offset
= offsetof(struct smb_com_transaction2_spi_req
,
2960 InformationLevel
) - 4;
2961 offset
= param_offset
+ params
;
2962 parm_data
= ((char *) &pSMB
->hdr
.Protocol
) + offset
;
2963 pSMB
->ParameterOffset
= cpu_to_le16(param_offset
);
2965 /* convert to on the wire format for POSIX ACL */
2966 data_count
= ACL_to_cifs_posix(parm_data
, local_acl
, buflen
, acl_type
);
2968 if (data_count
== 0) {
2970 goto setACLerrorExit
;
2972 pSMB
->DataOffset
= cpu_to_le16(offset
);
2973 pSMB
->SetupCount
= 1;
2974 pSMB
->Reserved3
= 0;
2975 pSMB
->SubCommand
= cpu_to_le16(TRANS2_SET_PATH_INFORMATION
);
2976 pSMB
->InformationLevel
= cpu_to_le16(SMB_SET_POSIX_ACL
);
2977 byte_count
= 3 /* pad */ + params
+ data_count
;
2978 pSMB
->DataCount
= cpu_to_le16(data_count
);
2979 pSMB
->TotalDataCount
= pSMB
->DataCount
;
2980 pSMB
->ParameterCount
= cpu_to_le16(params
);
2981 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
2982 pSMB
->Reserved4
= 0;
2983 pSMB
->hdr
.smb_buf_length
+= byte_count
;
2984 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
2985 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
2986 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
2988 cFYI(1, ("Set POSIX ACL returned %d", rc
));
2992 cifs_buf_release(pSMB
);
2998 /* BB fix tabs in this function FIXME BB */
3000 CIFSGetExtAttr(const int xid
, struct cifsTconInfo
*tcon
,
3001 const int netfid
, __u64
* pExtAttrBits
, __u64
*pMask
)
3004 struct smb_t2_qfi_req
*pSMB
= NULL
;
3005 struct smb_t2_qfi_rsp
*pSMBr
= NULL
;
3007 __u16 params
, byte_count
;
3009 cFYI(1, ("In GetExtAttr"));
3014 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
3019 params
= 2 /* level */ +2 /* fid */;
3020 pSMB
->t2
.TotalDataCount
= 0;
3021 pSMB
->t2
.MaxParameterCount
= cpu_to_le16(4);
3022 /* BB find exact max data count below from sess structure BB */
3023 pSMB
->t2
.MaxDataCount
= cpu_to_le16(4000);
3024 pSMB
->t2
.MaxSetupCount
= 0;
3025 pSMB
->t2
.Reserved
= 0;
3027 pSMB
->t2
.Timeout
= 0;
3028 pSMB
->t2
.Reserved2
= 0;
3029 pSMB
->t2
.ParameterOffset
= cpu_to_le16(offsetof(struct smb_t2_qfi_req
,
3031 pSMB
->t2
.DataCount
= 0;
3032 pSMB
->t2
.DataOffset
= 0;
3033 pSMB
->t2
.SetupCount
= 1;
3034 pSMB
->t2
.Reserved3
= 0;
3035 pSMB
->t2
.SubCommand
= cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION
);
3036 byte_count
= params
+ 1 /* pad */ ;
3037 pSMB
->t2
.TotalParameterCount
= cpu_to_le16(params
);
3038 pSMB
->t2
.ParameterCount
= pSMB
->t2
.TotalParameterCount
;
3039 pSMB
->InformationLevel
= cpu_to_le16(SMB_QUERY_ATTR_FLAGS
);
3042 pSMB
->hdr
.smb_buf_length
+= byte_count
;
3043 pSMB
->t2
.ByteCount
= cpu_to_le16(byte_count
);
3045 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
3046 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
3048 cFYI(1, ("error %d in GetExtAttr", rc
));
3050 /* decode response */
3051 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
3052 if (rc
|| (pSMBr
->ByteCount
< 2))
3053 /* BB also check enough total bytes returned */
3054 /* If rc should we check for EOPNOSUPP and
3055 disable the srvino flag? or in caller? */
3056 rc
= -EIO
; /* bad smb */
3058 __u16 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
3059 __u16 count
= le16_to_cpu(pSMBr
->t2
.DataCount
);
3060 struct file_chattr_info
*pfinfo
;
3061 /* BB Do we need a cast or hash here ? */
3063 cFYI(1, ("Illegal size ret in GetExtAttr"));
3067 pfinfo
= (struct file_chattr_info
*)
3068 (data_offset
+ (char *) &pSMBr
->hdr
.Protocol
);
3069 *pExtAttrBits
= le64_to_cpu(pfinfo
->mode
);
3070 *pMask
= le64_to_cpu(pfinfo
->mask
);
3074 cifs_buf_release(pSMB
);
3076 goto GetExtAttrRetry
;
3080 #endif /* CONFIG_POSIX */
3082 #ifdef CONFIG_CIFS_EXPERIMENTAL
3083 /* Get Security Descriptor (by handle) from remote server for a file or dir */
3085 CIFSSMBGetCIFSACL(const int xid
, struct cifsTconInfo
*tcon
, __u16 fid
,
3086 struct cifs_ntsd
**acl_inf
, __u32
*pbuflen
)
3090 QUERY_SEC_DESC_REQ
* pSMB
;
3093 cFYI(1, ("GetCifsACL"));
3098 rc
= smb_init_nttransact(NT_TRANSACT_QUERY_SECURITY_DESC
, 0,
3099 8 /* parm len */, tcon
, (void **) &pSMB
);
3103 pSMB
->MaxParameterCount
= cpu_to_le32(4);
3104 /* BB TEST with big acls that might need to be e.g. larger than 16K */
3105 pSMB
->MaxSetupCount
= 0;
3106 pSMB
->Fid
= fid
; /* file handle always le */
3107 pSMB
->AclFlags
= cpu_to_le32(CIFS_ACL_OWNER
| CIFS_ACL_GROUP
|
3109 pSMB
->ByteCount
= cpu_to_le16(11); /* 3 bytes pad + 8 bytes parm */
3110 pSMB
->hdr
.smb_buf_length
+= 11;
3111 iov
[0].iov_base
= (char *)pSMB
;
3112 iov
[0].iov_len
= pSMB
->hdr
.smb_buf_length
+ 4;
3114 rc
= SendReceive2(xid
, tcon
->ses
, iov
, 1 /* num iovec */, &buf_type
,
3116 cifs_stats_inc(&tcon
->num_acl_get
);
3118 cFYI(1, ("Send error in QuerySecDesc = %d", rc
));
3119 } else { /* decode response */
3123 struct smb_com_ntransact_rsp
*pSMBr
;
3126 /* validate_nttransact */
3127 rc
= validate_ntransact(iov
[0].iov_base
, (char **)&parm
,
3128 &pdata
, &parm_len
, pbuflen
);
3131 pSMBr
= (struct smb_com_ntransact_rsp
*)iov
[0].iov_base
;
3133 cFYI(1, ("smb %p parm %p data %p", pSMBr
, parm
, *acl_inf
));
3135 if (le32_to_cpu(pSMBr
->ParameterCount
) != 4) {
3136 rc
= -EIO
; /* bad smb */
3141 /* BB check that data area is minimum length and as big as acl_len */
3143 acl_len
= le32_to_cpu(*parm
);
3144 if (acl_len
!= *pbuflen
) {
3145 cERROR(1, ("acl length %d does not match %d",
3146 acl_len
, *pbuflen
));
3147 if (*pbuflen
> acl_len
)
3151 /* check if buffer is big enough for the acl
3152 header followed by the smallest SID */
3153 if ((*pbuflen
< sizeof(struct cifs_ntsd
) + 8) ||
3154 (*pbuflen
>= 64 * 1024)) {
3155 cERROR(1, ("bad acl length %d", *pbuflen
));
3159 *acl_inf
= kmalloc(*pbuflen
, GFP_KERNEL
);
3160 if (*acl_inf
== NULL
) {
3164 memcpy(*acl_inf
, pdata
, *pbuflen
);
3168 if (buf_type
== CIFS_SMALL_BUFFER
)
3169 cifs_small_buf_release(iov
[0].iov_base
);
3170 else if (buf_type
== CIFS_LARGE_BUFFER
)
3171 cifs_buf_release(iov
[0].iov_base
);
3172 /* cifs_small_buf_release(pSMB); */ /* Freed earlier now in SendReceive2 */
3175 #endif /* CONFIG_CIFS_EXPERIMENTAL */
3177 /* Legacy Query Path Information call for lookup to old servers such
3179 int SMBQueryInformation(const int xid
, struct cifsTconInfo
*tcon
,
3180 const unsigned char *searchName
,
3181 FILE_ALL_INFO
*pFinfo
,
3182 const struct nls_table
*nls_codepage
, int remap
)
3184 QUERY_INFORMATION_REQ
* pSMB
;
3185 QUERY_INFORMATION_RSP
* pSMBr
;
3190 cFYI(1, ("In SMBQPath path %s", searchName
));
3192 rc
= smb_init(SMB_COM_QUERY_INFORMATION
, 0, tcon
, (void **) &pSMB
,
3197 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
3199 cifsConvertToUCS((__le16
*) pSMB
->FileName
, searchName
,
3200 PATH_MAX
, nls_codepage
, remap
);
3201 name_len
++; /* trailing null */
3204 name_len
= strnlen(searchName
, PATH_MAX
);
3205 name_len
++; /* trailing null */
3206 strncpy(pSMB
->FileName
, searchName
, name_len
);
3208 pSMB
->BufferFormat
= 0x04;
3209 name_len
++; /* account for buffer type byte */
3210 pSMB
->hdr
.smb_buf_length
+= (__u16
) name_len
;
3211 pSMB
->ByteCount
= cpu_to_le16(name_len
);
3213 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
3214 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
3216 cFYI(1, ("Send error in QueryInfo = %d", rc
));
3217 } else if (pFinfo
) { /* decode response */
3219 __u32 time
= le32_to_cpu(pSMBr
->last_write_time
);
3220 /* BB FIXME - add time zone adjustment BB */
3221 memset(pFinfo
, 0, sizeof(FILE_ALL_INFO
));
3224 /* decode time fields */
3225 pFinfo
->ChangeTime
= cpu_to_le64(cifs_UnixTimeToNT(ts
));
3226 pFinfo
->LastWriteTime
= pFinfo
->ChangeTime
;
3227 pFinfo
->LastAccessTime
= 0;
3228 pFinfo
->AllocationSize
=
3229 cpu_to_le64(le32_to_cpu(pSMBr
->size
));
3230 pFinfo
->EndOfFile
= pFinfo
->AllocationSize
;
3231 pFinfo
->Attributes
=
3232 cpu_to_le32(le16_to_cpu(pSMBr
->attr
));
3234 rc
= -EIO
; /* bad buffer passed in */
3236 cifs_buf_release(pSMB
);
3248 CIFSSMBQPathInfo(const int xid
, struct cifsTconInfo
*tcon
,
3249 const unsigned char *searchName
,
3250 FILE_ALL_INFO
* pFindData
,
3251 int legacy
/* old style infolevel */,
3252 const struct nls_table
*nls_codepage
, int remap
)
3254 /* level 263 SMB_QUERY_FILE_ALL_INFO */
3255 TRANSACTION2_QPI_REQ
*pSMB
= NULL
;
3256 TRANSACTION2_QPI_RSP
*pSMBr
= NULL
;
3260 __u16 params
, byte_count
;
3262 /* cFYI(1, ("In QPathInfo path %s", searchName)); */
3264 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
3269 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
3271 cifsConvertToUCS((__le16
*) pSMB
->FileName
, searchName
,
3272 PATH_MAX
, nls_codepage
, remap
);
3273 name_len
++; /* trailing null */
3275 } else { /* BB improve the check for buffer overruns BB */
3276 name_len
= strnlen(searchName
, PATH_MAX
);
3277 name_len
++; /* trailing null */
3278 strncpy(pSMB
->FileName
, searchName
, name_len
);
3281 params
= 2 /* level */ + 4 /* reserved */ + name_len
/* includes NUL */;
3282 pSMB
->TotalDataCount
= 0;
3283 pSMB
->MaxParameterCount
= cpu_to_le16(2);
3284 pSMB
->MaxDataCount
= cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
3285 pSMB
->MaxSetupCount
= 0;
3289 pSMB
->Reserved2
= 0;
3290 pSMB
->ParameterOffset
= cpu_to_le16(offsetof(
3291 struct smb_com_transaction2_qpi_req
, InformationLevel
) - 4);
3292 pSMB
->DataCount
= 0;
3293 pSMB
->DataOffset
= 0;
3294 pSMB
->SetupCount
= 1;
3295 pSMB
->Reserved3
= 0;
3296 pSMB
->SubCommand
= cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION
);
3297 byte_count
= params
+ 1 /* pad */ ;
3298 pSMB
->TotalParameterCount
= cpu_to_le16(params
);
3299 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
3301 pSMB
->InformationLevel
= cpu_to_le16(SMB_INFO_STANDARD
);
3303 pSMB
->InformationLevel
= cpu_to_le16(SMB_QUERY_FILE_ALL_INFO
);
3304 pSMB
->Reserved4
= 0;
3305 pSMB
->hdr
.smb_buf_length
+= byte_count
;
3306 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
3308 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
3309 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
3311 cFYI(1, ("Send error in QPathInfo = %d", rc
));
3312 } else { /* decode response */
3313 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
3315 if (rc
) /* BB add auto retry on EOPNOTSUPP? */
3317 else if (!legacy
&& (pSMBr
->ByteCount
< 40))
3318 rc
= -EIO
; /* bad smb */
3319 else if (legacy
&& (pSMBr
->ByteCount
< 24))
3320 rc
= -EIO
; /* 24 or 26 expected but we do not read
3322 else if (pFindData
) {
3324 __u16 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
3325 if (legacy
) /* we do not read the last field, EAsize,
3326 fortunately since it varies by subdialect
3327 and on Set vs. Get, is two bytes or 4
3328 bytes depending but we don't care here */
3329 size
= sizeof(FILE_INFO_STANDARD
);
3331 size
= sizeof(FILE_ALL_INFO
);
3332 memcpy((char *) pFindData
,
3333 (char *) &pSMBr
->hdr
.Protocol
+
3338 cifs_buf_release(pSMB
);
3340 goto QPathInfoRetry
;
3346 CIFSSMBUnixQPathInfo(const int xid
, struct cifsTconInfo
*tcon
,
3347 const unsigned char *searchName
,
3348 FILE_UNIX_BASIC_INFO
* pFindData
,
3349 const struct nls_table
*nls_codepage
, int remap
)
3351 /* SMB_QUERY_FILE_UNIX_BASIC */
3352 TRANSACTION2_QPI_REQ
*pSMB
= NULL
;
3353 TRANSACTION2_QPI_RSP
*pSMBr
= NULL
;
3355 int bytes_returned
= 0;
3357 __u16 params
, byte_count
;
3359 cFYI(1, ("In QPathInfo (Unix) the path %s", searchName
));
3361 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
3366 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
3368 cifsConvertToUCS((__le16
*) pSMB
->FileName
, searchName
,
3369 PATH_MAX
, nls_codepage
, remap
);
3370 name_len
++; /* trailing null */
3372 } else { /* BB improve the check for buffer overruns BB */
3373 name_len
= strnlen(searchName
, PATH_MAX
);
3374 name_len
++; /* trailing null */
3375 strncpy(pSMB
->FileName
, searchName
, name_len
);
3378 params
= 2 /* level */ + 4 /* reserved */ + name_len
/* includes NUL */;
3379 pSMB
->TotalDataCount
= 0;
3380 pSMB
->MaxParameterCount
= cpu_to_le16(2);
3381 /* BB find exact max SMB PDU from sess structure BB */
3382 pSMB
->MaxDataCount
= cpu_to_le16(4000);
3383 pSMB
->MaxSetupCount
= 0;
3387 pSMB
->Reserved2
= 0;
3388 pSMB
->ParameterOffset
= cpu_to_le16(offsetof(
3389 struct smb_com_transaction2_qpi_req
, InformationLevel
) - 4);
3390 pSMB
->DataCount
= 0;
3391 pSMB
->DataOffset
= 0;
3392 pSMB
->SetupCount
= 1;
3393 pSMB
->Reserved3
= 0;
3394 pSMB
->SubCommand
= cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION
);
3395 byte_count
= params
+ 1 /* pad */ ;
3396 pSMB
->TotalParameterCount
= cpu_to_le16(params
);
3397 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
3398 pSMB
->InformationLevel
= cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC
);
3399 pSMB
->Reserved4
= 0;
3400 pSMB
->hdr
.smb_buf_length
+= byte_count
;
3401 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
3403 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
3404 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
3406 cFYI(1, ("Send error in QPathInfo = %d", rc
));
3407 } else { /* decode response */
3408 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
3410 if (rc
|| (pSMBr
->ByteCount
< sizeof(FILE_UNIX_BASIC_INFO
))) {
3411 cERROR(1, ("Malformed FILE_UNIX_BASIC_INFO response.\n"
3412 "Unix Extensions can be disabled on mount "
3413 "by specifying the nosfu mount option."));
3414 rc
= -EIO
; /* bad smb */
3416 __u16 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
3417 memcpy((char *) pFindData
,
3418 (char *) &pSMBr
->hdr
.Protocol
+
3420 sizeof(FILE_UNIX_BASIC_INFO
));
3423 cifs_buf_release(pSMB
);
3425 goto UnixQPathInfoRetry
;
3430 #if 0 /* function unused at present */
3431 int CIFSFindSingle(const int xid
, struct cifsTconInfo
*tcon
,
3432 const char *searchName
, FILE_ALL_INFO
* findData
,
3433 const struct nls_table
*nls_codepage
)
3435 /* level 257 SMB_ */
3436 TRANSACTION2_FFIRST_REQ
*pSMB
= NULL
;
3437 TRANSACTION2_FFIRST_RSP
*pSMBr
= NULL
;
3441 __u16 params
, byte_count
;
3443 cFYI(1, ("In FindUnique"));
3445 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
3450 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
3452 cifsConvertToUCS((__le16
*) pSMB
->FileName
, searchName
,
3453 PATH_MAX
, nls_codepage
);
3454 name_len
++; /* trailing null */
3456 } else { /* BB improve the check for buffer overruns BB */
3457 name_len
= strnlen(searchName
, PATH_MAX
);
3458 name_len
++; /* trailing null */
3459 strncpy(pSMB
->FileName
, searchName
, name_len
);
3462 params
= 12 + name_len
/* includes null */ ;
3463 pSMB
->TotalDataCount
= 0; /* no EAs */
3464 pSMB
->MaxParameterCount
= cpu_to_le16(2);
3465 pSMB
->MaxDataCount
= cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
3466 pSMB
->MaxSetupCount
= 0;
3470 pSMB
->Reserved2
= 0;
3471 pSMB
->ParameterOffset
= cpu_to_le16(
3472 offsetof(struct smb_com_transaction2_ffirst_req
, InformationLevel
)-4);
3473 pSMB
->DataCount
= 0;
3474 pSMB
->DataOffset
= 0;
3475 pSMB
->SetupCount
= 1; /* one byte, no need to le convert */
3476 pSMB
->Reserved3
= 0;
3477 pSMB
->SubCommand
= cpu_to_le16(TRANS2_FIND_FIRST
);
3478 byte_count
= params
+ 1 /* pad */ ;
3479 pSMB
->TotalParameterCount
= cpu_to_le16(params
);
3480 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
3481 pSMB
->SearchAttributes
=
3482 cpu_to_le16(ATTR_READONLY
| ATTR_HIDDEN
| ATTR_SYSTEM
|
3484 pSMB
->SearchCount
= cpu_to_le16(16); /* BB increase */
3485 pSMB
->SearchFlags
= cpu_to_le16(1);
3486 pSMB
->InformationLevel
= cpu_to_le16(SMB_FIND_FILE_DIRECTORY_INFO
);
3487 pSMB
->SearchStorageType
= 0; /* BB what should we set this to? BB */
3488 pSMB
->hdr
.smb_buf_length
+= byte_count
;
3489 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
3491 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
3492 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
3495 cFYI(1, ("Send error in FindFileDirInfo = %d", rc
));
3496 } else { /* decode response */
3497 cifs_stats_inc(&tcon
->num_ffirst
);
3501 cifs_buf_release(pSMB
);
3503 goto findUniqueRetry
;
3507 #endif /* end unused (temporarily) function */
3509 /* xid, tcon, searchName and codepage are input parms, rest are returned */
3511 CIFSFindFirst(const int xid
, struct cifsTconInfo
*tcon
,
3512 const char *searchName
,
3513 const struct nls_table
*nls_codepage
,
3515 struct cifs_search_info
*psrch_inf
, int remap
, const char dirsep
)
3517 /* level 257 SMB_ */
3518 TRANSACTION2_FFIRST_REQ
*pSMB
= NULL
;
3519 TRANSACTION2_FFIRST_RSP
*pSMBr
= NULL
;
3520 T2_FFIRST_RSP_PARMS
* parms
;
3522 int bytes_returned
= 0;
3524 __u16 params
, byte_count
;
3526 cFYI(1, ("In FindFirst for %s", searchName
));
3529 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
3534 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
3536 cifsConvertToUCS((__le16
*) pSMB
->FileName
, searchName
,
3537 PATH_MAX
, nls_codepage
, remap
);
3538 /* We can not add the asterik earlier in case
3539 it got remapped to 0xF03A as if it were part of the
3540 directory name instead of a wildcard */
3542 pSMB
->FileName
[name_len
] = dirsep
;
3543 pSMB
->FileName
[name_len
+1] = 0;
3544 pSMB
->FileName
[name_len
+2] = '*';
3545 pSMB
->FileName
[name_len
+3] = 0;
3546 name_len
+= 4; /* now the trailing null */
3547 pSMB
->FileName
[name_len
] = 0; /* null terminate just in case */
3548 pSMB
->FileName
[name_len
+1] = 0;
3550 } else { /* BB add check for overrun of SMB buf BB */
3551 name_len
= strnlen(searchName
, PATH_MAX
);
3552 /* BB fix here and in unicode clause above ie
3553 if (name_len > buffersize-header)
3554 free buffer exit; BB */
3555 strncpy(pSMB
->FileName
, searchName
, name_len
);
3556 pSMB
->FileName
[name_len
] = dirsep
;
3557 pSMB
->FileName
[name_len
+1] = '*';
3558 pSMB
->FileName
[name_len
+2] = 0;
3562 params
= 12 + name_len
/* includes null */ ;
3563 pSMB
->TotalDataCount
= 0; /* no EAs */
3564 pSMB
->MaxParameterCount
= cpu_to_le16(10);
3565 pSMB
->MaxDataCount
= cpu_to_le16((tcon
->ses
->server
->maxBuf
-
3566 MAX_CIFS_HDR_SIZE
) & 0xFFFFFF00);
3567 pSMB
->MaxSetupCount
= 0;
3571 pSMB
->Reserved2
= 0;
3572 byte_count
= params
+ 1 /* pad */ ;
3573 pSMB
->TotalParameterCount
= cpu_to_le16(params
);
3574 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
3575 pSMB
->ParameterOffset
= cpu_to_le16(
3576 offsetof(struct smb_com_transaction2_ffirst_req
, SearchAttributes
)
3578 pSMB
->DataCount
= 0;
3579 pSMB
->DataOffset
= 0;
3580 pSMB
->SetupCount
= 1; /* one byte, no need to make endian neutral */
3581 pSMB
->Reserved3
= 0;
3582 pSMB
->SubCommand
= cpu_to_le16(TRANS2_FIND_FIRST
);
3583 pSMB
->SearchAttributes
=
3584 cpu_to_le16(ATTR_READONLY
| ATTR_HIDDEN
| ATTR_SYSTEM
|
3586 pSMB
->SearchCount
= cpu_to_le16(CIFSMaxBufSize
/sizeof(FILE_UNIX_INFO
));
3587 pSMB
->SearchFlags
= cpu_to_le16(CIFS_SEARCH_CLOSE_AT_END
|
3588 CIFS_SEARCH_RETURN_RESUME
);
3589 pSMB
->InformationLevel
= cpu_to_le16(psrch_inf
->info_level
);
3591 /* BB what should we set StorageType to? Does it matter? BB */
3592 pSMB
->SearchStorageType
= 0;
3593 pSMB
->hdr
.smb_buf_length
+= byte_count
;
3594 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
3596 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
3597 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
3598 cifs_stats_inc(&tcon
->num_ffirst
);
3600 if (rc
) {/* BB add logic to retry regular search if Unix search
3601 rejected unexpectedly by server */
3602 /* BB Add code to handle unsupported level rc */
3603 cFYI(1, ("Error in FindFirst = %d", rc
));
3605 cifs_buf_release(pSMB
);
3607 /* BB eventually could optimize out free and realloc of buf */
3610 goto findFirstRetry
;
3611 } else { /* decode response */
3612 /* BB remember to free buffer if error BB */
3613 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
3615 if (pSMBr
->hdr
.Flags2
& SMBFLG2_UNICODE
)
3616 psrch_inf
->unicode
= TRUE
;
3618 psrch_inf
->unicode
= FALSE
;
3620 psrch_inf
->ntwrk_buf_start
= (char *)pSMBr
;
3621 psrch_inf
->smallBuf
= 0;
3622 psrch_inf
->srch_entries_start
=
3623 (char *) &pSMBr
->hdr
.Protocol
+
3624 le16_to_cpu(pSMBr
->t2
.DataOffset
);
3625 parms
= (T2_FFIRST_RSP_PARMS
*)((char *) &pSMBr
->hdr
.Protocol
+
3626 le16_to_cpu(pSMBr
->t2
.ParameterOffset
));
3628 if (parms
->EndofSearch
)
3629 psrch_inf
->endOfSearch
= TRUE
;
3631 psrch_inf
->endOfSearch
= FALSE
;
3633 psrch_inf
->entries_in_buffer
=
3634 le16_to_cpu(parms
->SearchCount
);
3635 psrch_inf
->index_of_last_entry
= 2 /* skip . and .. */ +
3636 psrch_inf
->entries_in_buffer
;
3637 *pnetfid
= parms
->SearchHandle
;
3639 cifs_buf_release(pSMB
);
3646 int CIFSFindNext(const int xid
, struct cifsTconInfo
*tcon
,
3647 __u16 searchHandle
, struct cifs_search_info
*psrch_inf
)
3649 TRANSACTION2_FNEXT_REQ
*pSMB
= NULL
;
3650 TRANSACTION2_FNEXT_RSP
*pSMBr
= NULL
;
3651 T2_FNEXT_RSP_PARMS
* parms
;
3652 char *response_data
;
3654 int bytes_returned
, name_len
;
3655 __u16 params
, byte_count
;
3657 cFYI(1, ("In FindNext"));
3659 if (psrch_inf
->endOfSearch
== TRUE
)
3662 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
3667 params
= 14; /* includes 2 bytes of null string, converted to LE below*/
3669 pSMB
->TotalDataCount
= 0; /* no EAs */
3670 pSMB
->MaxParameterCount
= cpu_to_le16(8);
3671 pSMB
->MaxDataCount
=
3672 cpu_to_le16((tcon
->ses
->server
->maxBuf
- MAX_CIFS_HDR_SIZE
) &
3674 pSMB
->MaxSetupCount
= 0;
3678 pSMB
->Reserved2
= 0;
3679 pSMB
->ParameterOffset
= cpu_to_le16(
3680 offsetof(struct smb_com_transaction2_fnext_req
,SearchHandle
) - 4);
3681 pSMB
->DataCount
= 0;
3682 pSMB
->DataOffset
= 0;
3683 pSMB
->SetupCount
= 1;
3684 pSMB
->Reserved3
= 0;
3685 pSMB
->SubCommand
= cpu_to_le16(TRANS2_FIND_NEXT
);
3686 pSMB
->SearchHandle
= searchHandle
; /* always kept as le */
3688 cpu_to_le16(CIFSMaxBufSize
/ sizeof(FILE_UNIX_INFO
));
3689 pSMB
->InformationLevel
= cpu_to_le16(psrch_inf
->info_level
);
3690 pSMB
->ResumeKey
= psrch_inf
->resume_key
;
3692 cpu_to_le16(CIFS_SEARCH_CLOSE_AT_END
| CIFS_SEARCH_RETURN_RESUME
);
3694 name_len
= psrch_inf
->resume_name_len
;
3696 if (name_len
< PATH_MAX
) {
3697 memcpy(pSMB
->ResumeFileName
, psrch_inf
->presume_name
, name_len
);
3698 byte_count
+= name_len
;
3699 /* 14 byte parm len above enough for 2 byte null terminator */
3700 pSMB
->ResumeFileName
[name_len
] = 0;
3701 pSMB
->ResumeFileName
[name_len
+1] = 0;
3704 goto FNext2_err_exit
;
3706 byte_count
= params
+ 1 /* pad */ ;
3707 pSMB
->TotalParameterCount
= cpu_to_le16(params
);
3708 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
3709 pSMB
->hdr
.smb_buf_length
+= byte_count
;
3710 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
3712 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
3713 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
3714 cifs_stats_inc(&tcon
->num_fnext
);
3717 psrch_inf
->endOfSearch
= TRUE
;
3718 rc
= 0; /* search probably was closed at end of search*/
3720 cFYI(1, ("FindNext returned = %d", rc
));
3721 } else { /* decode response */
3722 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
3725 /* BB fixme add lock for file (srch_info) struct here */
3726 if (pSMBr
->hdr
.Flags2
& SMBFLG2_UNICODE
)
3727 psrch_inf
->unicode
= TRUE
;
3729 psrch_inf
->unicode
= FALSE
;
3730 response_data
= (char *) &pSMBr
->hdr
.Protocol
+
3731 le16_to_cpu(pSMBr
->t2
.ParameterOffset
);
3732 parms
= (T2_FNEXT_RSP_PARMS
*)response_data
;
3733 response_data
= (char *)&pSMBr
->hdr
.Protocol
+
3734 le16_to_cpu(pSMBr
->t2
.DataOffset
);
3735 if (psrch_inf
->smallBuf
)
3736 cifs_small_buf_release(
3737 psrch_inf
->ntwrk_buf_start
);
3739 cifs_buf_release(psrch_inf
->ntwrk_buf_start
);
3740 psrch_inf
->srch_entries_start
= response_data
;
3741 psrch_inf
->ntwrk_buf_start
= (char *)pSMB
;
3742 psrch_inf
->smallBuf
= 0;
3743 if (parms
->EndofSearch
)
3744 psrch_inf
->endOfSearch
= TRUE
;
3746 psrch_inf
->endOfSearch
= FALSE
;
3747 psrch_inf
->entries_in_buffer
=
3748 le16_to_cpu(parms
->SearchCount
);
3749 psrch_inf
->index_of_last_entry
+=
3750 psrch_inf
->entries_in_buffer
;
3751 /* cFYI(1,("fnxt2 entries in buf %d index_of_last %d",
3752 psrch_inf->entries_in_buffer, psrch_inf->index_of_last_entry)); */
3754 /* BB fixme add unlock here */
3759 /* BB On error, should we leave previous search buf (and count and
3760 last entry fields) intact or free the previous one? */
3762 /* Note: On -EAGAIN error only caller can retry on handle based calls
3763 since file handle passed in no longer valid */
3766 cifs_buf_release(pSMB
);
3771 CIFSFindClose(const int xid
, struct cifsTconInfo
*tcon
,
3772 const __u16 searchHandle
)
3775 FINDCLOSE_REQ
*pSMB
= NULL
;
3777 cFYI(1, ("In CIFSSMBFindClose"));
3778 rc
= small_smb_init(SMB_COM_FIND_CLOSE2
, 1, tcon
, (void **)&pSMB
);
3780 /* no sense returning error if session restarted
3781 as file handle has been closed */
3787 pSMB
->FileID
= searchHandle
;
3788 pSMB
->ByteCount
= 0;
3789 rc
= SendReceiveNoRsp(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
, 0);
3791 cERROR(1, ("Send error in FindClose = %d", rc
));
3793 cifs_stats_inc(&tcon
->num_fclose
);
3795 /* Since session is dead, search handle closed on server already */
3803 CIFSGetSrvInodeNumber(const int xid
, struct cifsTconInfo
*tcon
,
3804 const unsigned char *searchName
,
3805 __u64
* inode_number
,
3806 const struct nls_table
*nls_codepage
, int remap
)
3809 TRANSACTION2_QPI_REQ
*pSMB
= NULL
;
3810 TRANSACTION2_QPI_RSP
*pSMBr
= NULL
;
3811 int name_len
, bytes_returned
;
3812 __u16 params
, byte_count
;
3814 cFYI(1, ("In GetSrvInodeNum for %s", searchName
));
3818 GetInodeNumberRetry
:
3819 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
3824 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
3826 cifsConvertToUCS((__le16
*) pSMB
->FileName
, searchName
,
3827 PATH_MAX
, nls_codepage
, remap
);
3828 name_len
++; /* trailing null */
3830 } else { /* BB improve the check for buffer overruns BB */
3831 name_len
= strnlen(searchName
, PATH_MAX
);
3832 name_len
++; /* trailing null */
3833 strncpy(pSMB
->FileName
, searchName
, name_len
);
3836 params
= 2 /* level */ + 4 /* rsrvd */ + name_len
/* incl null */ ;
3837 pSMB
->TotalDataCount
= 0;
3838 pSMB
->MaxParameterCount
= cpu_to_le16(2);
3839 /* BB find exact max data count below from sess structure BB */
3840 pSMB
->MaxDataCount
= cpu_to_le16(4000);
3841 pSMB
->MaxSetupCount
= 0;
3845 pSMB
->Reserved2
= 0;
3846 pSMB
->ParameterOffset
= cpu_to_le16(offsetof(
3847 struct smb_com_transaction2_qpi_req
, InformationLevel
) - 4);
3848 pSMB
->DataCount
= 0;
3849 pSMB
->DataOffset
= 0;
3850 pSMB
->SetupCount
= 1;
3851 pSMB
->Reserved3
= 0;
3852 pSMB
->SubCommand
= cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION
);
3853 byte_count
= params
+ 1 /* pad */ ;
3854 pSMB
->TotalParameterCount
= cpu_to_le16(params
);
3855 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
3856 pSMB
->InformationLevel
= cpu_to_le16(SMB_QUERY_FILE_INTERNAL_INFO
);
3857 pSMB
->Reserved4
= 0;
3858 pSMB
->hdr
.smb_buf_length
+= byte_count
;
3859 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
3861 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
3862 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
3864 cFYI(1, ("error %d in QueryInternalInfo", rc
));
3866 /* decode response */
3867 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
3868 if (rc
|| (pSMBr
->ByteCount
< 2))
3869 /* BB also check enough total bytes returned */
3870 /* If rc should we check for EOPNOSUPP and
3871 disable the srvino flag? or in caller? */
3872 rc
= -EIO
; /* bad smb */
3874 __u16 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
3875 __u16 count
= le16_to_cpu(pSMBr
->t2
.DataCount
);
3876 struct file_internal_info
*pfinfo
;
3877 /* BB Do we need a cast or hash here ? */
3879 cFYI(1, ("Illegal size ret in QryIntrnlInf"));
3881 goto GetInodeNumOut
;
3883 pfinfo
= (struct file_internal_info
*)
3884 (data_offset
+ (char *) &pSMBr
->hdr
.Protocol
);
3885 *inode_number
= pfinfo
->UniqueId
;
3889 cifs_buf_release(pSMB
);
3891 goto GetInodeNumberRetry
;
3896 CIFSGetDFSRefer(const int xid
, struct cifsSesInfo
*ses
,
3897 const unsigned char *searchName
,
3898 unsigned char **targetUNCs
,
3899 unsigned int *number_of_UNC_in_array
,
3900 const struct nls_table
*nls_codepage
, int remap
)
3902 /* TRANS2_GET_DFS_REFERRAL */
3903 TRANSACTION2_GET_DFS_REFER_REQ
*pSMB
= NULL
;
3904 TRANSACTION2_GET_DFS_REFER_RSP
*pSMBr
= NULL
;
3905 struct dfs_referral_level_3
*referrals
= NULL
;
3911 __u16 params
, byte_count
;
3912 *number_of_UNC_in_array
= 0;
3915 cFYI(1, ("In GetDFSRefer the path %s", searchName
));
3919 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, NULL
, (void **) &pSMB
,
3924 /* server pointer checked in called function,
3925 but should never be null here anyway */
3926 pSMB
->hdr
.Mid
= GetNextMid(ses
->server
);
3927 pSMB
->hdr
.Tid
= ses
->ipc_tid
;
3928 pSMB
->hdr
.Uid
= ses
->Suid
;
3929 if (ses
->capabilities
& CAP_STATUS32
)
3930 pSMB
->hdr
.Flags2
|= SMBFLG2_ERR_STATUS
;
3931 if (ses
->capabilities
& CAP_DFS
)
3932 pSMB
->hdr
.Flags2
|= SMBFLG2_DFS
;
3934 if (ses
->capabilities
& CAP_UNICODE
) {
3935 pSMB
->hdr
.Flags2
|= SMBFLG2_UNICODE
;
3937 cifsConvertToUCS((__le16
*) pSMB
->RequestFileName
,
3938 searchName
, PATH_MAX
, nls_codepage
, remap
);
3939 name_len
++; /* trailing null */
3941 } else { /* BB improve the check for buffer overruns BB */
3942 name_len
= strnlen(searchName
, PATH_MAX
);
3943 name_len
++; /* trailing null */
3944 strncpy(pSMB
->RequestFileName
, searchName
, name_len
);
3948 if (ses
->server
->secMode
&
3949 (SECMODE_SIGN_REQUIRED
| SECMODE_SIGN_ENABLED
))
3950 pSMB
->hdr
.Flags2
|= SMBFLG2_SECURITY_SIGNATURE
;
3953 pSMB
->hdr
.Uid
= ses
->Suid
;
3955 params
= 2 /* level */ + name_len
/*includes null */ ;
3956 pSMB
->TotalDataCount
= 0;
3957 pSMB
->DataCount
= 0;
3958 pSMB
->DataOffset
= 0;
3959 pSMB
->MaxParameterCount
= 0;
3960 pSMB
->MaxDataCount
= cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
3961 pSMB
->MaxSetupCount
= 0;
3965 pSMB
->Reserved2
= 0;
3966 pSMB
->ParameterOffset
= cpu_to_le16(offsetof(
3967 struct smb_com_transaction2_get_dfs_refer_req
, MaxReferralLevel
) - 4);
3968 pSMB
->SetupCount
= 1;
3969 pSMB
->Reserved3
= 0;
3970 pSMB
->SubCommand
= cpu_to_le16(TRANS2_GET_DFS_REFERRAL
);
3971 byte_count
= params
+ 3 /* pad */ ;
3972 pSMB
->ParameterCount
= cpu_to_le16(params
);
3973 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
3974 pSMB
->MaxReferralLevel
= cpu_to_le16(3);
3975 pSMB
->hdr
.smb_buf_length
+= byte_count
;
3976 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
3978 rc
= SendReceive(xid
, ses
, (struct smb_hdr
*) pSMB
,
3979 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
3981 cFYI(1, ("Send error in GetDFSRefer = %d", rc
));
3982 } else { /* decode response */
3983 /* BB Add logic to parse referrals here */
3984 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
3986 /* BB Also check if enough total bytes returned? */
3987 if (rc
|| (pSMBr
->ByteCount
< 17))
3988 rc
= -EIO
; /* bad smb */
3990 __u16 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
3991 __u16 data_count
= le16_to_cpu(pSMBr
->t2
.DataCount
);
3994 ("Decoding GetDFSRefer response BCC: %d Offset %d",
3995 pSMBr
->ByteCount
, data_offset
));
3997 (struct dfs_referral_level_3
*)
3998 (8 /* sizeof start of data block */ +
4000 (char *) &pSMBr
->hdr
.Protocol
);
4001 cFYI(1, ("num_referrals: %d dfs flags: 0x%x ... \n"
4002 "for referral one refer size: 0x%x srv "
4003 "type: 0x%x refer flags: 0x%x ttl: 0x%x",
4004 le16_to_cpu(pSMBr
->NumberOfReferrals
),
4005 le16_to_cpu(pSMBr
->DFSFlags
),
4006 le16_to_cpu(referrals
->ReferralSize
),
4007 le16_to_cpu(referrals
->ServerType
),
4008 le16_to_cpu(referrals
->ReferralFlags
),
4009 le16_to_cpu(referrals
->TimeToLive
)));
4010 /* BB This field is actually two bytes in from start of
4011 data block so we could do safety check that DataBlock
4012 begins at address of pSMBr->NumberOfReferrals */
4013 *number_of_UNC_in_array
=
4014 le16_to_cpu(pSMBr
->NumberOfReferrals
);
4016 /* BB Fix below so can return more than one referral */
4017 if (*number_of_UNC_in_array
> 1)
4018 *number_of_UNC_in_array
= 1;
4020 /* get the length of the strings describing refs */
4022 for (i
= 0; i
< *number_of_UNC_in_array
; i
++) {
4023 /* make sure that DfsPathOffset not past end */
4025 le16_to_cpu(referrals
->DfsPathOffset
);
4026 if (offset
> data_count
) {
4027 /* if invalid referral, stop here and do
4028 not try to copy any more */
4029 *number_of_UNC_in_array
= i
;
4032 temp
= ((char *)referrals
) + offset
;
4034 if (pSMBr
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
4035 name_len
+= UniStrnlen((wchar_t *)temp
,
4038 name_len
+= strnlen(temp
, data_count
);
4041 /* BB add check that referral pointer does
4042 not fall off end PDU */
4044 /* BB add check for name_len bigger than bcc */
4046 kmalloc(name_len
+1+(*number_of_UNC_in_array
),
4048 if (*targetUNCs
== NULL
) {
4052 /* copy the ref strings */
4053 referrals
= (struct dfs_referral_level_3
*)
4054 (8 /* sizeof data hdr */ + data_offset
+
4055 (char *) &pSMBr
->hdr
.Protocol
);
4057 for (i
= 0; i
< *number_of_UNC_in_array
; i
++) {
4058 temp
= ((char *)referrals
) +
4059 le16_to_cpu(referrals
->DfsPathOffset
);
4060 if (pSMBr
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
4061 cifs_strfromUCS_le(*targetUNCs
,
4066 strncpy(*targetUNCs
, temp
, name_len
);
4068 /* BB update target_uncs pointers */
4078 cifs_buf_release(pSMB
);
4086 /* Query File System Info such as free space to old servers such as Win 9x */
4088 SMBOldQFSInfo(const int xid
, struct cifsTconInfo
*tcon
, struct kstatfs
*FSData
)
4090 /* level 0x01 SMB_QUERY_FILE_SYSTEM_INFO */
4091 TRANSACTION2_QFSI_REQ
*pSMB
= NULL
;
4092 TRANSACTION2_QFSI_RSP
*pSMBr
= NULL
;
4093 FILE_SYSTEM_ALLOC_INFO
*response_data
;
4095 int bytes_returned
= 0;
4096 __u16 params
, byte_count
;
4098 cFYI(1, ("OldQFSInfo"));
4100 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
4105 params
= 2; /* level */
4106 pSMB
->TotalDataCount
= 0;
4107 pSMB
->MaxParameterCount
= cpu_to_le16(2);
4108 pSMB
->MaxDataCount
= cpu_to_le16(1000);
4109 pSMB
->MaxSetupCount
= 0;
4113 pSMB
->Reserved2
= 0;
4114 byte_count
= params
+ 1 /* pad */ ;
4115 pSMB
->TotalParameterCount
= cpu_to_le16(params
);
4116 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
4117 pSMB
->ParameterOffset
= cpu_to_le16(offsetof(
4118 struct smb_com_transaction2_qfsi_req
, InformationLevel
) - 4);
4119 pSMB
->DataCount
= 0;
4120 pSMB
->DataOffset
= 0;
4121 pSMB
->SetupCount
= 1;
4122 pSMB
->Reserved3
= 0;
4123 pSMB
->SubCommand
= cpu_to_le16(TRANS2_QUERY_FS_INFORMATION
);
4124 pSMB
->InformationLevel
= cpu_to_le16(SMB_INFO_ALLOCATION
);
4125 pSMB
->hdr
.smb_buf_length
+= byte_count
;
4126 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
4128 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
4129 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
4131 cFYI(1, ("Send error in QFSInfo = %d", rc
));
4132 } else { /* decode response */
4133 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
4135 if (rc
|| (pSMBr
->ByteCount
< 18))
4136 rc
= -EIO
; /* bad smb */
4138 __u16 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
4139 cFYI(1, ("qfsinf resp BCC: %d Offset %d",
4140 pSMBr
->ByteCount
, data_offset
));
4142 response_data
= (FILE_SYSTEM_ALLOC_INFO
*)
4143 (((char *) &pSMBr
->hdr
.Protocol
) + data_offset
);
4145 le16_to_cpu(response_data
->BytesPerSector
) *
4146 le32_to_cpu(response_data
->
4147 SectorsPerAllocationUnit
);
4149 le32_to_cpu(response_data
->TotalAllocationUnits
);
4150 FSData
->f_bfree
= FSData
->f_bavail
=
4151 le32_to_cpu(response_data
->FreeAllocationUnits
);
4153 ("Blocks: %lld Free: %lld Block size %ld",
4154 (unsigned long long)FSData
->f_blocks
,
4155 (unsigned long long)FSData
->f_bfree
,
4159 cifs_buf_release(pSMB
);
4162 goto oldQFSInfoRetry
;
4168 CIFSSMBQFSInfo(const int xid
, struct cifsTconInfo
*tcon
, struct kstatfs
*FSData
)
4170 /* level 0x103 SMB_QUERY_FILE_SYSTEM_INFO */
4171 TRANSACTION2_QFSI_REQ
*pSMB
= NULL
;
4172 TRANSACTION2_QFSI_RSP
*pSMBr
= NULL
;
4173 FILE_SYSTEM_INFO
*response_data
;
4175 int bytes_returned
= 0;
4176 __u16 params
, byte_count
;
4178 cFYI(1, ("In QFSInfo"));
4180 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
4185 params
= 2; /* level */
4186 pSMB
->TotalDataCount
= 0;
4187 pSMB
->MaxParameterCount
= cpu_to_le16(2);
4188 pSMB
->MaxDataCount
= cpu_to_le16(1000);
4189 pSMB
->MaxSetupCount
= 0;
4193 pSMB
->Reserved2
= 0;
4194 byte_count
= params
+ 1 /* pad */ ;
4195 pSMB
->TotalParameterCount
= cpu_to_le16(params
);
4196 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
4197 pSMB
->ParameterOffset
= cpu_to_le16(offsetof(
4198 struct smb_com_transaction2_qfsi_req
, InformationLevel
) - 4);
4199 pSMB
->DataCount
= 0;
4200 pSMB
->DataOffset
= 0;
4201 pSMB
->SetupCount
= 1;
4202 pSMB
->Reserved3
= 0;
4203 pSMB
->SubCommand
= cpu_to_le16(TRANS2_QUERY_FS_INFORMATION
);
4204 pSMB
->InformationLevel
= cpu_to_le16(SMB_QUERY_FS_SIZE_INFO
);
4205 pSMB
->hdr
.smb_buf_length
+= byte_count
;
4206 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
4208 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
4209 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
4211 cFYI(1, ("Send error in QFSInfo = %d", rc
));
4212 } else { /* decode response */
4213 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
4215 if (rc
|| (pSMBr
->ByteCount
< 24))
4216 rc
= -EIO
; /* bad smb */
4218 __u16 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
4222 *) (((char *) &pSMBr
->hdr
.Protocol
) +
4225 le32_to_cpu(response_data
->BytesPerSector
) *
4226 le32_to_cpu(response_data
->
4227 SectorsPerAllocationUnit
);
4229 le64_to_cpu(response_data
->TotalAllocationUnits
);
4230 FSData
->f_bfree
= FSData
->f_bavail
=
4231 le64_to_cpu(response_data
->FreeAllocationUnits
);
4233 ("Blocks: %lld Free: %lld Block size %ld",
4234 (unsigned long long)FSData
->f_blocks
,
4235 (unsigned long long)FSData
->f_bfree
,
4239 cifs_buf_release(pSMB
);
4248 CIFSSMBQFSAttributeInfo(const int xid
, struct cifsTconInfo
*tcon
)
4250 /* level 0x105 SMB_QUERY_FILE_SYSTEM_INFO */
4251 TRANSACTION2_QFSI_REQ
*pSMB
= NULL
;
4252 TRANSACTION2_QFSI_RSP
*pSMBr
= NULL
;
4253 FILE_SYSTEM_ATTRIBUTE_INFO
*response_data
;
4255 int bytes_returned
= 0;
4256 __u16 params
, byte_count
;
4258 cFYI(1, ("In QFSAttributeInfo"));
4260 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
4265 params
= 2; /* level */
4266 pSMB
->TotalDataCount
= 0;
4267 pSMB
->MaxParameterCount
= cpu_to_le16(2);
4268 pSMB
->MaxDataCount
= cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
4269 pSMB
->MaxSetupCount
= 0;
4273 pSMB
->Reserved2
= 0;
4274 byte_count
= params
+ 1 /* pad */ ;
4275 pSMB
->TotalParameterCount
= cpu_to_le16(params
);
4276 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
4277 pSMB
->ParameterOffset
= cpu_to_le16(offsetof(
4278 struct smb_com_transaction2_qfsi_req
, InformationLevel
) - 4);
4279 pSMB
->DataCount
= 0;
4280 pSMB
->DataOffset
= 0;
4281 pSMB
->SetupCount
= 1;
4282 pSMB
->Reserved3
= 0;
4283 pSMB
->SubCommand
= cpu_to_le16(TRANS2_QUERY_FS_INFORMATION
);
4284 pSMB
->InformationLevel
= cpu_to_le16(SMB_QUERY_FS_ATTRIBUTE_INFO
);
4285 pSMB
->hdr
.smb_buf_length
+= byte_count
;
4286 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
4288 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
4289 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
4291 cERROR(1, ("Send error in QFSAttributeInfo = %d", rc
));
4292 } else { /* decode response */
4293 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
4295 if (rc
|| (pSMBr
->ByteCount
< 13)) {
4296 /* BB also check if enough bytes returned */
4297 rc
= -EIO
; /* bad smb */
4299 __u16 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
4301 (FILE_SYSTEM_ATTRIBUTE_INFO
4302 *) (((char *) &pSMBr
->hdr
.Protocol
) +
4304 memcpy(&tcon
->fsAttrInfo
, response_data
,
4305 sizeof(FILE_SYSTEM_ATTRIBUTE_INFO
));
4308 cifs_buf_release(pSMB
);
4311 goto QFSAttributeRetry
;
4317 CIFSSMBQFSDeviceInfo(const int xid
, struct cifsTconInfo
*tcon
)
4319 /* level 0x104 SMB_QUERY_FILE_SYSTEM_INFO */
4320 TRANSACTION2_QFSI_REQ
*pSMB
= NULL
;
4321 TRANSACTION2_QFSI_RSP
*pSMBr
= NULL
;
4322 FILE_SYSTEM_DEVICE_INFO
*response_data
;
4324 int bytes_returned
= 0;
4325 __u16 params
, byte_count
;
4327 cFYI(1, ("In QFSDeviceInfo"));
4329 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
4334 params
= 2; /* level */
4335 pSMB
->TotalDataCount
= 0;
4336 pSMB
->MaxParameterCount
= cpu_to_le16(2);
4337 pSMB
->MaxDataCount
= cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
4338 pSMB
->MaxSetupCount
= 0;
4342 pSMB
->Reserved2
= 0;
4343 byte_count
= params
+ 1 /* pad */ ;
4344 pSMB
->TotalParameterCount
= cpu_to_le16(params
);
4345 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
4346 pSMB
->ParameterOffset
= cpu_to_le16(offsetof(
4347 struct smb_com_transaction2_qfsi_req
, InformationLevel
) - 4);
4349 pSMB
->DataCount
= 0;
4350 pSMB
->DataOffset
= 0;
4351 pSMB
->SetupCount
= 1;
4352 pSMB
->Reserved3
= 0;
4353 pSMB
->SubCommand
= cpu_to_le16(TRANS2_QUERY_FS_INFORMATION
);
4354 pSMB
->InformationLevel
= cpu_to_le16(SMB_QUERY_FS_DEVICE_INFO
);
4355 pSMB
->hdr
.smb_buf_length
+= byte_count
;
4356 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
4358 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
4359 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
4361 cFYI(1, ("Send error in QFSDeviceInfo = %d", rc
));
4362 } else { /* decode response */
4363 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
4365 if (rc
|| (pSMBr
->ByteCount
< sizeof(FILE_SYSTEM_DEVICE_INFO
)))
4366 rc
= -EIO
; /* bad smb */
4368 __u16 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
4370 (FILE_SYSTEM_DEVICE_INFO
*)
4371 (((char *) &pSMBr
->hdr
.Protocol
) +
4373 memcpy(&tcon
->fsDevInfo
, response_data
,
4374 sizeof(FILE_SYSTEM_DEVICE_INFO
));
4377 cifs_buf_release(pSMB
);
4380 goto QFSDeviceRetry
;
4386 CIFSSMBQFSUnixInfo(const int xid
, struct cifsTconInfo
*tcon
)
4388 /* level 0x200 SMB_QUERY_CIFS_UNIX_INFO */
4389 TRANSACTION2_QFSI_REQ
*pSMB
= NULL
;
4390 TRANSACTION2_QFSI_RSP
*pSMBr
= NULL
;
4391 FILE_SYSTEM_UNIX_INFO
*response_data
;
4393 int bytes_returned
= 0;
4394 __u16 params
, byte_count
;
4396 cFYI(1, ("In QFSUnixInfo"));
4398 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
4403 params
= 2; /* level */
4404 pSMB
->TotalDataCount
= 0;
4405 pSMB
->DataCount
= 0;
4406 pSMB
->DataOffset
= 0;
4407 pSMB
->MaxParameterCount
= cpu_to_le16(2);
4408 pSMB
->MaxDataCount
= cpu_to_le16(100); /* BB find exact max SMB PDU from sess structure BB */
4409 pSMB
->MaxSetupCount
= 0;
4413 pSMB
->Reserved2
= 0;
4414 byte_count
= params
+ 1 /* pad */ ;
4415 pSMB
->ParameterCount
= cpu_to_le16(params
);
4416 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
4417 pSMB
->ParameterOffset
= cpu_to_le16(offsetof(struct
4418 smb_com_transaction2_qfsi_req
, InformationLevel
) - 4);
4419 pSMB
->SetupCount
= 1;
4420 pSMB
->Reserved3
= 0;
4421 pSMB
->SubCommand
= cpu_to_le16(TRANS2_QUERY_FS_INFORMATION
);
4422 pSMB
->InformationLevel
= cpu_to_le16(SMB_QUERY_CIFS_UNIX_INFO
);
4423 pSMB
->hdr
.smb_buf_length
+= byte_count
;
4424 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
4426 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
4427 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
4429 cERROR(1, ("Send error in QFSUnixInfo = %d", rc
));
4430 } else { /* decode response */
4431 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
4433 if (rc
|| (pSMBr
->ByteCount
< 13)) {
4434 rc
= -EIO
; /* bad smb */
4436 __u16 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
4438 (FILE_SYSTEM_UNIX_INFO
4439 *) (((char *) &pSMBr
->hdr
.Protocol
) +
4441 memcpy(&tcon
->fsUnixInfo
, response_data
,
4442 sizeof(FILE_SYSTEM_UNIX_INFO
));
4445 cifs_buf_release(pSMB
);
4455 CIFSSMBSetFSUnixInfo(const int xid
, struct cifsTconInfo
*tcon
, __u64 cap
)
4457 /* level 0x200 SMB_SET_CIFS_UNIX_INFO */
4458 TRANSACTION2_SETFSI_REQ
*pSMB
= NULL
;
4459 TRANSACTION2_SETFSI_RSP
*pSMBr
= NULL
;
4461 int bytes_returned
= 0;
4462 __u16 params
, param_offset
, offset
, byte_count
;
4464 cFYI(1, ("In SETFSUnixInfo"));
4466 /* BB switch to small buf init to save memory */
4467 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
4472 params
= 4; /* 2 bytes zero followed by info level. */
4473 pSMB
->MaxSetupCount
= 0;
4477 pSMB
->Reserved2
= 0;
4478 param_offset
= offsetof(struct smb_com_transaction2_setfsi_req
, FileNum
)
4480 offset
= param_offset
+ params
;
4482 pSMB
->MaxParameterCount
= cpu_to_le16(4);
4483 pSMB
->MaxDataCount
= cpu_to_le16(100); /* BB find exact max SMB PDU from sess structure BB */
4484 pSMB
->SetupCount
= 1;
4485 pSMB
->Reserved3
= 0;
4486 pSMB
->SubCommand
= cpu_to_le16(TRANS2_SET_FS_INFORMATION
);
4487 byte_count
= 1 /* pad */ + params
+ 12;
4489 pSMB
->DataCount
= cpu_to_le16(12);
4490 pSMB
->ParameterCount
= cpu_to_le16(params
);
4491 pSMB
->TotalDataCount
= pSMB
->DataCount
;
4492 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
4493 pSMB
->ParameterOffset
= cpu_to_le16(param_offset
);
4494 pSMB
->DataOffset
= cpu_to_le16(offset
);
4498 pSMB
->InformationLevel
= cpu_to_le16(SMB_SET_CIFS_UNIX_INFO
);
4501 pSMB
->ClientUnixMajor
= cpu_to_le16(CIFS_UNIX_MAJOR_VERSION
);
4502 pSMB
->ClientUnixMinor
= cpu_to_le16(CIFS_UNIX_MINOR_VERSION
);
4503 pSMB
->ClientUnixCap
= cpu_to_le64(cap
);
4505 pSMB
->hdr
.smb_buf_length
+= byte_count
;
4506 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
4508 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
4509 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
4511 cERROR(1, ("Send error in SETFSUnixInfo = %d", rc
));
4512 } else { /* decode response */
4513 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
4515 rc
= -EIO
; /* bad smb */
4518 cifs_buf_release(pSMB
);
4521 goto SETFSUnixRetry
;
4529 CIFSSMBQFSPosixInfo(const int xid
, struct cifsTconInfo
*tcon
,
4530 struct kstatfs
*FSData
)
4532 /* level 0x201 SMB_QUERY_CIFS_POSIX_INFO */
4533 TRANSACTION2_QFSI_REQ
*pSMB
= NULL
;
4534 TRANSACTION2_QFSI_RSP
*pSMBr
= NULL
;
4535 FILE_SYSTEM_POSIX_INFO
*response_data
;
4537 int bytes_returned
= 0;
4538 __u16 params
, byte_count
;
4540 cFYI(1, ("In QFSPosixInfo"));
4542 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
4547 params
= 2; /* level */
4548 pSMB
->TotalDataCount
= 0;
4549 pSMB
->DataCount
= 0;
4550 pSMB
->DataOffset
= 0;
4551 pSMB
->MaxParameterCount
= cpu_to_le16(2);
4552 pSMB
->MaxDataCount
= cpu_to_le16(100); /* BB find exact max SMB PDU from sess structure BB */
4553 pSMB
->MaxSetupCount
= 0;
4557 pSMB
->Reserved2
= 0;
4558 byte_count
= params
+ 1 /* pad */ ;
4559 pSMB
->ParameterCount
= cpu_to_le16(params
);
4560 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
4561 pSMB
->ParameterOffset
= cpu_to_le16(offsetof(struct
4562 smb_com_transaction2_qfsi_req
, InformationLevel
) - 4);
4563 pSMB
->SetupCount
= 1;
4564 pSMB
->Reserved3
= 0;
4565 pSMB
->SubCommand
= cpu_to_le16(TRANS2_QUERY_FS_INFORMATION
);
4566 pSMB
->InformationLevel
= cpu_to_le16(SMB_QUERY_POSIX_FS_INFO
);
4567 pSMB
->hdr
.smb_buf_length
+= byte_count
;
4568 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
4570 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
4571 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
4573 cFYI(1, ("Send error in QFSUnixInfo = %d", rc
));
4574 } else { /* decode response */
4575 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
4577 if (rc
|| (pSMBr
->ByteCount
< 13)) {
4578 rc
= -EIO
; /* bad smb */
4580 __u16 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
4582 (FILE_SYSTEM_POSIX_INFO
4583 *) (((char *) &pSMBr
->hdr
.Protocol
) +
4586 le32_to_cpu(response_data
->BlockSize
);
4588 le64_to_cpu(response_data
->TotalBlocks
);
4590 le64_to_cpu(response_data
->BlocksAvail
);
4591 if (response_data
->UserBlocksAvail
== cpu_to_le64(-1)) {
4592 FSData
->f_bavail
= FSData
->f_bfree
;
4595 le64_to_cpu(response_data
->UserBlocksAvail
);
4597 if (response_data
->TotalFileNodes
!= cpu_to_le64(-1))
4599 le64_to_cpu(response_data
->TotalFileNodes
);
4600 if (response_data
->FreeFileNodes
!= cpu_to_le64(-1))
4602 le64_to_cpu(response_data
->FreeFileNodes
);
4605 cifs_buf_release(pSMB
);
4614 /* We can not use write of zero bytes trick to
4615 set file size due to need for large file support. Also note that
4616 this SetPathInfo is preferred to SetFileInfo based method in next
4617 routine which is only needed to work around a sharing violation bug
4618 in Samba which this routine can run into */
4621 CIFSSMBSetEOF(const int xid
, struct cifsTconInfo
*tcon
, const char *fileName
,
4622 __u64 size
, int SetAllocation
,
4623 const struct nls_table
*nls_codepage
, int remap
)
4625 struct smb_com_transaction2_spi_req
*pSMB
= NULL
;
4626 struct smb_com_transaction2_spi_rsp
*pSMBr
= NULL
;
4627 struct file_end_of_file_info
*parm_data
;
4630 int bytes_returned
= 0;
4631 __u16 params
, byte_count
, data_count
, param_offset
, offset
;
4633 cFYI(1, ("In SetEOF"));
4635 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
4640 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
4642 cifsConvertToUCS((__le16
*) pSMB
->FileName
, fileName
,
4643 PATH_MAX
, nls_codepage
, remap
);
4644 name_len
++; /* trailing null */
4646 } else { /* BB improve the check for buffer overruns BB */
4647 name_len
= strnlen(fileName
, PATH_MAX
);
4648 name_len
++; /* trailing null */
4649 strncpy(pSMB
->FileName
, fileName
, name_len
);
4651 params
= 6 + name_len
;
4652 data_count
= sizeof(struct file_end_of_file_info
);
4653 pSMB
->MaxParameterCount
= cpu_to_le16(2);
4654 pSMB
->MaxDataCount
= cpu_to_le16(4100);
4655 pSMB
->MaxSetupCount
= 0;
4659 pSMB
->Reserved2
= 0;
4660 param_offset
= offsetof(struct smb_com_transaction2_spi_req
,
4661 InformationLevel
) - 4;
4662 offset
= param_offset
+ params
;
4663 if (SetAllocation
) {
4664 if (tcon
->ses
->capabilities
& CAP_INFOLEVEL_PASSTHRU
)
4665 pSMB
->InformationLevel
=
4666 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2
);
4668 pSMB
->InformationLevel
=
4669 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO
);
4670 } else /* Set File Size */ {
4671 if (tcon
->ses
->capabilities
& CAP_INFOLEVEL_PASSTHRU
)
4672 pSMB
->InformationLevel
=
4673 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO2
);
4675 pSMB
->InformationLevel
=
4676 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO
);
4680 (struct file_end_of_file_info
*) (((char *) &pSMB
->hdr
.Protocol
) +
4682 pSMB
->ParameterOffset
= cpu_to_le16(param_offset
);
4683 pSMB
->DataOffset
= cpu_to_le16(offset
);
4684 pSMB
->SetupCount
= 1;
4685 pSMB
->Reserved3
= 0;
4686 pSMB
->SubCommand
= cpu_to_le16(TRANS2_SET_PATH_INFORMATION
);
4687 byte_count
= 3 /* pad */ + params
+ data_count
;
4688 pSMB
->DataCount
= cpu_to_le16(data_count
);
4689 pSMB
->TotalDataCount
= pSMB
->DataCount
;
4690 pSMB
->ParameterCount
= cpu_to_le16(params
);
4691 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
4692 pSMB
->Reserved4
= 0;
4693 pSMB
->hdr
.smb_buf_length
+= byte_count
;
4694 parm_data
->FileSize
= cpu_to_le64(size
);
4695 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
4696 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
4697 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
4699 cFYI(1, ("SetPathInfo (file size) returned %d", rc
));
4702 cifs_buf_release(pSMB
);
4711 CIFSSMBSetFileSize(const int xid
, struct cifsTconInfo
*tcon
, __u64 size
,
4712 __u16 fid
, __u32 pid_of_opener
, int SetAllocation
)
4714 struct smb_com_transaction2_sfi_req
*pSMB
= NULL
;
4716 struct file_end_of_file_info
*parm_data
;
4718 __u16 params
, param_offset
, offset
, byte_count
, count
;
4720 cFYI(1, ("SetFileSize (via SetFileInfo) %lld",
4722 rc
= small_smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
);
4727 pSMB
->hdr
.Pid
= cpu_to_le16((__u16
)pid_of_opener
);
4728 pSMB
->hdr
.PidHigh
= cpu_to_le16((__u16
)(pid_of_opener
>> 16));
4731 pSMB
->MaxSetupCount
= 0;
4735 pSMB
->Reserved2
= 0;
4736 param_offset
= offsetof(struct smb_com_transaction2_sfi_req
, Fid
) - 4;
4737 offset
= param_offset
+ params
;
4739 data_offset
= (char *) (&pSMB
->hdr
.Protocol
) + offset
;
4741 count
= sizeof(struct file_end_of_file_info
);
4742 pSMB
->MaxParameterCount
= cpu_to_le16(2);
4743 pSMB
->MaxDataCount
= cpu_to_le16(1000); /* BB find max SMB PDU from sess */
4744 pSMB
->SetupCount
= 1;
4745 pSMB
->Reserved3
= 0;
4746 pSMB
->SubCommand
= cpu_to_le16(TRANS2_SET_FILE_INFORMATION
);
4747 byte_count
= 3 /* pad */ + params
+ count
;
4748 pSMB
->DataCount
= cpu_to_le16(count
);
4749 pSMB
->ParameterCount
= cpu_to_le16(params
);
4750 pSMB
->TotalDataCount
= pSMB
->DataCount
;
4751 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
4752 pSMB
->ParameterOffset
= cpu_to_le16(param_offset
);
4754 (struct file_end_of_file_info
*) (((char *) &pSMB
->hdr
.Protocol
)
4756 pSMB
->DataOffset
= cpu_to_le16(offset
);
4757 parm_data
->FileSize
= cpu_to_le64(size
);
4759 if (SetAllocation
) {
4760 if (tcon
->ses
->capabilities
& CAP_INFOLEVEL_PASSTHRU
)
4761 pSMB
->InformationLevel
=
4762 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2
);
4764 pSMB
->InformationLevel
=
4765 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO
);
4766 } else /* Set File Size */ {
4767 if (tcon
->ses
->capabilities
& CAP_INFOLEVEL_PASSTHRU
)
4768 pSMB
->InformationLevel
=
4769 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO2
);
4771 pSMB
->InformationLevel
=
4772 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO
);
4774 pSMB
->Reserved4
= 0;
4775 pSMB
->hdr
.smb_buf_length
+= byte_count
;
4776 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
4777 rc
= SendReceiveNoRsp(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
, 0);
4780 ("Send error in SetFileInfo (SetFileSize) = %d",
4784 /* Note: On -EAGAIN error only caller can retry on handle based calls
4785 since file handle passed in no longer valid */
4790 /* Some legacy servers such as NT4 require that the file times be set on
4791 an open handle, rather than by pathname - this is awkward due to
4792 potential access conflicts on the open, but it is unavoidable for these
4793 old servers since the only other choice is to go from 100 nanosecond DCE
4794 time and resort to the original setpathinfo level which takes the ancient
4795 DOS time format with 2 second granularity */
4797 CIFSSMBSetFileTimes(const int xid
, struct cifsTconInfo
*tcon
,
4798 const FILE_BASIC_INFO
*data
, __u16 fid
)
4800 struct smb_com_transaction2_sfi_req
*pSMB
= NULL
;
4803 __u16 params
, param_offset
, offset
, byte_count
, count
;
4805 cFYI(1, ("Set Times (via SetFileInfo)"));
4806 rc
= small_smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
);
4811 /* At this point there is no need to override the current pid
4812 with the pid of the opener, but that could change if we someday
4813 use an existing handle (rather than opening one on the fly) */
4814 /* pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
4815 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));*/
4818 pSMB
->MaxSetupCount
= 0;
4822 pSMB
->Reserved2
= 0;
4823 param_offset
= offsetof(struct smb_com_transaction2_sfi_req
, Fid
) - 4;
4824 offset
= param_offset
+ params
;
4826 data_offset
= (char *) (&pSMB
->hdr
.Protocol
) + offset
;
4828 count
= sizeof(FILE_BASIC_INFO
);
4829 pSMB
->MaxParameterCount
= cpu_to_le16(2);
4830 pSMB
->MaxDataCount
= cpu_to_le16(1000); /* BB find max SMB PDU from sess */
4831 pSMB
->SetupCount
= 1;
4832 pSMB
->Reserved3
= 0;
4833 pSMB
->SubCommand
= cpu_to_le16(TRANS2_SET_FILE_INFORMATION
);
4834 byte_count
= 3 /* pad */ + params
+ count
;
4835 pSMB
->DataCount
= cpu_to_le16(count
);
4836 pSMB
->ParameterCount
= cpu_to_le16(params
);
4837 pSMB
->TotalDataCount
= pSMB
->DataCount
;
4838 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
4839 pSMB
->ParameterOffset
= cpu_to_le16(param_offset
);
4840 pSMB
->DataOffset
= cpu_to_le16(offset
);
4842 if (tcon
->ses
->capabilities
& CAP_INFOLEVEL_PASSTHRU
)
4843 pSMB
->InformationLevel
= cpu_to_le16(SMB_SET_FILE_BASIC_INFO2
);
4845 pSMB
->InformationLevel
= cpu_to_le16(SMB_SET_FILE_BASIC_INFO
);
4846 pSMB
->Reserved4
= 0;
4847 pSMB
->hdr
.smb_buf_length
+= byte_count
;
4848 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
4849 memcpy(data_offset
, data
, sizeof(FILE_BASIC_INFO
));
4850 rc
= SendReceiveNoRsp(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
, 0);
4852 cFYI(1, ("Send error in Set Time (SetFileInfo) = %d", rc
));
4855 /* Note: On -EAGAIN error only caller can retry on handle based calls
4856 since file handle passed in no longer valid */
4863 CIFSSMBSetTimes(const int xid
, struct cifsTconInfo
*tcon
, const char *fileName
,
4864 const FILE_BASIC_INFO
*data
,
4865 const struct nls_table
*nls_codepage
, int remap
)
4867 TRANSACTION2_SPI_REQ
*pSMB
= NULL
;
4868 TRANSACTION2_SPI_RSP
*pSMBr
= NULL
;
4871 int bytes_returned
= 0;
4873 __u16 params
, param_offset
, offset
, byte_count
, count
;
4875 cFYI(1, ("In SetTimes"));
4878 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
4883 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
4885 cifsConvertToUCS((__le16
*) pSMB
->FileName
, fileName
,
4886 PATH_MAX
, nls_codepage
, remap
);
4887 name_len
++; /* trailing null */
4889 } else { /* BB improve the check for buffer overruns BB */
4890 name_len
= strnlen(fileName
, PATH_MAX
);
4891 name_len
++; /* trailing null */
4892 strncpy(pSMB
->FileName
, fileName
, name_len
);
4895 params
= 6 + name_len
;
4896 count
= sizeof(FILE_BASIC_INFO
);
4897 pSMB
->MaxParameterCount
= cpu_to_le16(2);
4898 pSMB
->MaxDataCount
= cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
4899 pSMB
->MaxSetupCount
= 0;
4903 pSMB
->Reserved2
= 0;
4904 param_offset
= offsetof(struct smb_com_transaction2_spi_req
,
4905 InformationLevel
) - 4;
4906 offset
= param_offset
+ params
;
4907 data_offset
= (char *) (&pSMB
->hdr
.Protocol
) + offset
;
4908 pSMB
->ParameterOffset
= cpu_to_le16(param_offset
);
4909 pSMB
->DataOffset
= cpu_to_le16(offset
);
4910 pSMB
->SetupCount
= 1;
4911 pSMB
->Reserved3
= 0;
4912 pSMB
->SubCommand
= cpu_to_le16(TRANS2_SET_PATH_INFORMATION
);
4913 byte_count
= 3 /* pad */ + params
+ count
;
4915 pSMB
->DataCount
= cpu_to_le16(count
);
4916 pSMB
->ParameterCount
= cpu_to_le16(params
);
4917 pSMB
->TotalDataCount
= pSMB
->DataCount
;
4918 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
4919 if (tcon
->ses
->capabilities
& CAP_INFOLEVEL_PASSTHRU
)
4920 pSMB
->InformationLevel
= cpu_to_le16(SMB_SET_FILE_BASIC_INFO2
);
4922 pSMB
->InformationLevel
= cpu_to_le16(SMB_SET_FILE_BASIC_INFO
);
4923 pSMB
->Reserved4
= 0;
4924 pSMB
->hdr
.smb_buf_length
+= byte_count
;
4925 memcpy(data_offset
, data
, sizeof(FILE_BASIC_INFO
));
4926 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
4927 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
4928 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
4930 cFYI(1, ("SetPathInfo (times) returned %d", rc
));
4933 cifs_buf_release(pSMB
);
4941 /* Can not be used to set time stamps yet (due to old DOS time format) */
4942 /* Can be used to set attributes */
4943 #if 0 /* Possibly not needed - since it turns out that strangely NT4 has a bug
4944 handling it anyway and NT4 was what we thought it would be needed for
4945 Do not delete it until we prove whether needed for Win9x though */
4947 CIFSSMBSetAttrLegacy(int xid
, struct cifsTconInfo
*tcon
, char *fileName
,
4948 __u16 dos_attrs
, const struct nls_table
*nls_codepage
)
4950 SETATTR_REQ
*pSMB
= NULL
;
4951 SETATTR_RSP
*pSMBr
= NULL
;
4956 cFYI(1, ("In SetAttrLegacy"));
4959 rc
= smb_init(SMB_COM_SETATTR
, 8, tcon
, (void **) &pSMB
,
4964 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
4966 ConvertToUCS((__le16
*) pSMB
->fileName
, fileName
,
4967 PATH_MAX
, nls_codepage
);
4968 name_len
++; /* trailing null */
4970 } else { /* BB improve the check for buffer overruns BB */
4971 name_len
= strnlen(fileName
, PATH_MAX
);
4972 name_len
++; /* trailing null */
4973 strncpy(pSMB
->fileName
, fileName
, name_len
);
4975 pSMB
->attr
= cpu_to_le16(dos_attrs
);
4976 pSMB
->BufferFormat
= 0x04;
4977 pSMB
->hdr
.smb_buf_length
+= name_len
+ 1;
4978 pSMB
->ByteCount
= cpu_to_le16(name_len
+ 1);
4979 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
4980 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
4982 cFYI(1, ("Error in LegacySetAttr = %d", rc
));
4985 cifs_buf_release(pSMB
);
4988 goto SetAttrLgcyRetry
;
4992 #endif /* temporarily unneeded SetAttr legacy function */
4995 CIFSSMBUnixSetPerms(const int xid
, struct cifsTconInfo
*tcon
,
4996 char *fileName
, __u64 mode
, __u64 uid
, __u64 gid
,
4997 dev_t device
, const struct nls_table
*nls_codepage
,
5000 TRANSACTION2_SPI_REQ
*pSMB
= NULL
;
5001 TRANSACTION2_SPI_RSP
*pSMBr
= NULL
;
5004 int bytes_returned
= 0;
5005 FILE_UNIX_BASIC_INFO
*data_offset
;
5006 __u16 params
, param_offset
, offset
, count
, byte_count
;
5008 cFYI(1, ("In SetUID/GID/Mode"));
5010 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
5015 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
5017 cifsConvertToUCS((__le16
*) pSMB
->FileName
, fileName
,
5018 PATH_MAX
, nls_codepage
, remap
);
5019 name_len
++; /* trailing null */
5021 } else { /* BB improve the check for buffer overruns BB */
5022 name_len
= strnlen(fileName
, PATH_MAX
);
5023 name_len
++; /* trailing null */
5024 strncpy(pSMB
->FileName
, fileName
, name_len
);
5027 params
= 6 + name_len
;
5028 count
= sizeof(FILE_UNIX_BASIC_INFO
);
5029 pSMB
->MaxParameterCount
= cpu_to_le16(2);
5030 pSMB
->MaxDataCount
= cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
5031 pSMB
->MaxSetupCount
= 0;
5035 pSMB
->Reserved2
= 0;
5036 param_offset
= offsetof(struct smb_com_transaction2_spi_req
,
5037 InformationLevel
) - 4;
5038 offset
= param_offset
+ params
;
5040 (FILE_UNIX_BASIC_INFO
*) ((char *) &pSMB
->hdr
.Protocol
+
5042 memset(data_offset
, 0, count
);
5043 pSMB
->DataOffset
= cpu_to_le16(offset
);
5044 pSMB
->ParameterOffset
= cpu_to_le16(param_offset
);
5045 pSMB
->SetupCount
= 1;
5046 pSMB
->Reserved3
= 0;
5047 pSMB
->SubCommand
= cpu_to_le16(TRANS2_SET_PATH_INFORMATION
);
5048 byte_count
= 3 /* pad */ + params
+ count
;
5049 pSMB
->ParameterCount
= cpu_to_le16(params
);
5050 pSMB
->DataCount
= cpu_to_le16(count
);
5051 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
5052 pSMB
->TotalDataCount
= pSMB
->DataCount
;
5053 pSMB
->InformationLevel
= cpu_to_le16(SMB_SET_FILE_UNIX_BASIC
);
5054 pSMB
->Reserved4
= 0;
5055 pSMB
->hdr
.smb_buf_length
+= byte_count
;
5056 /* Samba server ignores set of file size to zero due to bugs in some
5057 older clients, but we should be precise - we use SetFileSize to
5058 set file size and do not want to truncate file size to zero
5059 accidently as happened on one Samba server beta by putting
5060 zero instead of -1 here */
5061 data_offset
->EndOfFile
= NO_CHANGE_64
;
5062 data_offset
->NumOfBytes
= NO_CHANGE_64
;
5063 data_offset
->LastStatusChange
= NO_CHANGE_64
;
5064 data_offset
->LastAccessTime
= NO_CHANGE_64
;
5065 data_offset
->LastModificationTime
= NO_CHANGE_64
;
5066 data_offset
->Uid
= cpu_to_le64(uid
);
5067 data_offset
->Gid
= cpu_to_le64(gid
);
5068 /* better to leave device as zero when it is */
5069 data_offset
->DevMajor
= cpu_to_le64(MAJOR(device
));
5070 data_offset
->DevMinor
= cpu_to_le64(MINOR(device
));
5071 data_offset
->Permissions
= cpu_to_le64(mode
);
5074 data_offset
->Type
= cpu_to_le32(UNIX_FILE
);
5075 else if (S_ISDIR(mode
))
5076 data_offset
->Type
= cpu_to_le32(UNIX_DIR
);
5077 else if (S_ISLNK(mode
))
5078 data_offset
->Type
= cpu_to_le32(UNIX_SYMLINK
);
5079 else if (S_ISCHR(mode
))
5080 data_offset
->Type
= cpu_to_le32(UNIX_CHARDEV
);
5081 else if (S_ISBLK(mode
))
5082 data_offset
->Type
= cpu_to_le32(UNIX_BLOCKDEV
);
5083 else if (S_ISFIFO(mode
))
5084 data_offset
->Type
= cpu_to_le32(UNIX_FIFO
);
5085 else if (S_ISSOCK(mode
))
5086 data_offset
->Type
= cpu_to_le32(UNIX_SOCKET
);
5089 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
5090 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
5091 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
5093 cFYI(1, ("SetPathInfo (perms) returned %d", rc
));
5097 cifs_buf_release(pSMB
);
5103 int CIFSSMBNotify(const int xid
, struct cifsTconInfo
*tcon
,
5104 const int notify_subdirs
, const __u16 netfid
,
5105 __u32 filter
, struct file
*pfile
, int multishot
,
5106 const struct nls_table
*nls_codepage
)
5109 struct smb_com_transaction_change_notify_req
*pSMB
= NULL
;
5110 struct smb_com_ntransaction_change_notify_rsp
*pSMBr
= NULL
;
5111 struct dir_notify_req
*dnotify_req
;
5114 cFYI(1, ("In CIFSSMBNotify for file handle %d", (int)netfid
));
5115 rc
= smb_init(SMB_COM_NT_TRANSACT
, 23, tcon
, (void **) &pSMB
,
5120 pSMB
->TotalParameterCount
= 0 ;
5121 pSMB
->TotalDataCount
= 0;
5122 pSMB
->MaxParameterCount
= cpu_to_le32(2);
5123 /* BB find exact data count max from sess structure BB */
5124 pSMB
->MaxDataCount
= 0; /* same in little endian or be */
5125 /* BB VERIFY verify which is correct for above BB */
5126 pSMB
->MaxDataCount
= cpu_to_le32((tcon
->ses
->server
->maxBuf
-
5127 MAX_CIFS_HDR_SIZE
) & 0xFFFFFF00);
5129 pSMB
->MaxSetupCount
= 4;
5131 pSMB
->ParameterOffset
= 0;
5132 pSMB
->DataCount
= 0;
5133 pSMB
->DataOffset
= 0;
5134 pSMB
->SetupCount
= 4; /* single byte does not need le conversion */
5135 pSMB
->SubCommand
= cpu_to_le16(NT_TRANSACT_NOTIFY_CHANGE
);
5136 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
5138 pSMB
->WatchTree
= 1; /* one byte - no le conversion needed */
5139 pSMB
->Reserved2
= 0;
5140 pSMB
->CompletionFilter
= cpu_to_le32(filter
);
5141 pSMB
->Fid
= netfid
; /* file handle always le */
5142 pSMB
->ByteCount
= 0;
5144 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
5145 (struct smb_hdr
*)pSMBr
, &bytes_returned
,
5148 cFYI(1, ("Error in Notify = %d", rc
));
5150 /* Add file to outstanding requests */
5151 /* BB change to kmem cache alloc */
5152 dnotify_req
= kmalloc(
5153 sizeof(struct dir_notify_req
),
5156 dnotify_req
->Pid
= pSMB
->hdr
.Pid
;
5157 dnotify_req
->PidHigh
= pSMB
->hdr
.PidHigh
;
5158 dnotify_req
->Mid
= pSMB
->hdr
.Mid
;
5159 dnotify_req
->Tid
= pSMB
->hdr
.Tid
;
5160 dnotify_req
->Uid
= pSMB
->hdr
.Uid
;
5161 dnotify_req
->netfid
= netfid
;
5162 dnotify_req
->pfile
= pfile
;
5163 dnotify_req
->filter
= filter
;
5164 dnotify_req
->multishot
= multishot
;
5165 spin_lock(&GlobalMid_Lock
);
5166 list_add_tail(&dnotify_req
->lhead
,
5167 &GlobalDnotifyReqList
);
5168 spin_unlock(&GlobalMid_Lock
);
5172 cifs_buf_release(pSMB
);
5175 #ifdef CONFIG_CIFS_XATTR
5177 CIFSSMBQAllEAs(const int xid
, struct cifsTconInfo
*tcon
,
5178 const unsigned char *searchName
,
5179 char *EAData
, size_t buf_size
,
5180 const struct nls_table
*nls_codepage
, int remap
)
5182 /* BB assumes one setup word */
5183 TRANSACTION2_QPI_REQ
*pSMB
= NULL
;
5184 TRANSACTION2_QPI_RSP
*pSMBr
= NULL
;
5188 struct fea
*temp_fea
;
5190 __u16 params
, byte_count
;
5192 cFYI(1, ("In Query All EAs path %s", searchName
));
5194 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
5199 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
5201 cifsConvertToUCS((__le16
*) pSMB
->FileName
, searchName
,
5202 PATH_MAX
, nls_codepage
, remap
);
5203 name_len
++; /* trailing null */
5205 } else { /* BB improve the check for buffer overruns BB */
5206 name_len
= strnlen(searchName
, PATH_MAX
);
5207 name_len
++; /* trailing null */
5208 strncpy(pSMB
->FileName
, searchName
, name_len
);
5211 params
= 2 /* level */ + 4 /* reserved */ + name_len
/* includes NUL */;
5212 pSMB
->TotalDataCount
= 0;
5213 pSMB
->MaxParameterCount
= cpu_to_le16(2);
5214 pSMB
->MaxDataCount
= cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
5215 pSMB
->MaxSetupCount
= 0;
5219 pSMB
->Reserved2
= 0;
5220 pSMB
->ParameterOffset
= cpu_to_le16(offsetof(
5221 struct smb_com_transaction2_qpi_req
, InformationLevel
) - 4);
5222 pSMB
->DataCount
= 0;
5223 pSMB
->DataOffset
= 0;
5224 pSMB
->SetupCount
= 1;
5225 pSMB
->Reserved3
= 0;
5226 pSMB
->SubCommand
= cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION
);
5227 byte_count
= params
+ 1 /* pad */ ;
5228 pSMB
->TotalParameterCount
= cpu_to_le16(params
);
5229 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
5230 pSMB
->InformationLevel
= cpu_to_le16(SMB_INFO_QUERY_ALL_EAS
);
5231 pSMB
->Reserved4
= 0;
5232 pSMB
->hdr
.smb_buf_length
+= byte_count
;
5233 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
5235 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
5236 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
5238 cFYI(1, ("Send error in QueryAllEAs = %d", rc
));
5239 } else { /* decode response */
5240 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
5242 /* BB also check enough total bytes returned */
5243 /* BB we need to improve the validity checking
5244 of these trans2 responses */
5245 if (rc
|| (pSMBr
->ByteCount
< 4))
5246 rc
= -EIO
; /* bad smb */
5247 /* else if (pFindData){
5248 memcpy((char *) pFindData,
5249 (char *) &pSMBr->hdr.Protocol +
5252 /* check that length of list is not more than bcc */
5253 /* check that each entry does not go beyond length
5255 /* check that each element of each entry does not
5256 go beyond end of list */
5257 __u16 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
5258 struct fealist
*ea_response_data
;
5260 /* validate_trans2_offsets() */
5261 /* BB check if start of smb + data_offset > &bcc+ bcc */
5262 ea_response_data
= (struct fealist
*)
5263 (((char *) &pSMBr
->hdr
.Protocol
) +
5265 name_len
= le32_to_cpu(ea_response_data
->list_len
);
5266 cFYI(1, ("ea length %d", name_len
));
5267 if (name_len
<= 8) {
5268 /* returned EA size zeroed at top of function */
5269 cFYI(1, ("empty EA list returned from server"));
5271 /* account for ea list len */
5273 temp_fea
= ea_response_data
->list
;
5274 temp_ptr
= (char *)temp_fea
;
5275 while (name_len
> 0) {
5279 rc
+= temp_fea
->name_len
;
5280 /* account for prefix user. and trailing null */
5282 if (rc
< (int)buf_size
) {
5283 memcpy(EAData
, "user.", 5);
5285 memcpy(EAData
, temp_ptr
,
5286 temp_fea
->name_len
);
5287 EAData
+= temp_fea
->name_len
;
5288 /* null terminate name */
5290 EAData
= EAData
+ 1;
5291 } else if (buf_size
== 0) {
5292 /* skip copy - calc size only */
5294 /* stop before overrun buffer */
5298 name_len
-= temp_fea
->name_len
;
5299 temp_ptr
+= temp_fea
->name_len
;
5300 /* account for trailing null */
5304 le16_to_cpu(temp_fea
->value_len
);
5305 name_len
-= value_len
;
5306 temp_ptr
+= value_len
;
5307 /* BB check that temp_ptr is still
5310 /* no trailing null to account for
5312 /* go on to next EA */
5313 temp_fea
= (struct fea
*)temp_ptr
;
5319 cifs_buf_release(pSMB
);
5326 ssize_t
CIFSSMBQueryEA(const int xid
, struct cifsTconInfo
*tcon
,
5327 const unsigned char *searchName
, const unsigned char *ea_name
,
5328 unsigned char *ea_value
, size_t buf_size
,
5329 const struct nls_table
*nls_codepage
, int remap
)
5331 TRANSACTION2_QPI_REQ
*pSMB
= NULL
;
5332 TRANSACTION2_QPI_RSP
*pSMBr
= NULL
;
5336 struct fea
*temp_fea
;
5338 __u16 params
, byte_count
;
5340 cFYI(1, ("In Query EA path %s", searchName
));
5342 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
5347 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
5349 cifsConvertToUCS((__le16
*) pSMB
->FileName
, searchName
,
5350 PATH_MAX
, nls_codepage
, remap
);
5351 name_len
++; /* trailing null */
5353 } else { /* BB improve the check for buffer overruns BB */
5354 name_len
= strnlen(searchName
, PATH_MAX
);
5355 name_len
++; /* trailing null */
5356 strncpy(pSMB
->FileName
, searchName
, name_len
);
5359 params
= 2 /* level */ + 4 /* reserved */ + name_len
/* includes NUL */;
5360 pSMB
->TotalDataCount
= 0;
5361 pSMB
->MaxParameterCount
= cpu_to_le16(2);
5362 pSMB
->MaxDataCount
= cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
5363 pSMB
->MaxSetupCount
= 0;
5367 pSMB
->Reserved2
= 0;
5368 pSMB
->ParameterOffset
= cpu_to_le16(offsetof(
5369 struct smb_com_transaction2_qpi_req
, InformationLevel
) - 4);
5370 pSMB
->DataCount
= 0;
5371 pSMB
->DataOffset
= 0;
5372 pSMB
->SetupCount
= 1;
5373 pSMB
->Reserved3
= 0;
5374 pSMB
->SubCommand
= cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION
);
5375 byte_count
= params
+ 1 /* pad */ ;
5376 pSMB
->TotalParameterCount
= cpu_to_le16(params
);
5377 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
5378 pSMB
->InformationLevel
= cpu_to_le16(SMB_INFO_QUERY_ALL_EAS
);
5379 pSMB
->Reserved4
= 0;
5380 pSMB
->hdr
.smb_buf_length
+= byte_count
;
5381 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
5383 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
5384 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
5386 cFYI(1, ("Send error in Query EA = %d", rc
));
5387 } else { /* decode response */
5388 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
5390 /* BB also check enough total bytes returned */
5391 /* BB we need to improve the validity checking
5392 of these trans2 responses */
5393 if (rc
|| (pSMBr
->ByteCount
< 4))
5394 rc
= -EIO
; /* bad smb */
5395 /* else if (pFindData){
5396 memcpy((char *) pFindData,
5397 (char *) &pSMBr->hdr.Protocol +
5400 /* check that length of list is not more than bcc */
5401 /* check that each entry does not go beyond length
5403 /* check that each element of each entry does not
5404 go beyond end of list */
5405 __u16 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
5406 struct fealist
*ea_response_data
;
5408 /* validate_trans2_offsets() */
5409 /* BB check if start of smb + data_offset > &bcc+ bcc*/
5410 ea_response_data
= (struct fealist
*)
5411 (((char *) &pSMBr
->hdr
.Protocol
) +
5413 name_len
= le32_to_cpu(ea_response_data
->list_len
);
5414 cFYI(1, ("ea length %d", name_len
));
5415 if (name_len
<= 8) {
5416 /* returned EA size zeroed at top of function */
5417 cFYI(1, ("empty EA list returned from server"));
5419 /* account for ea list len */
5421 temp_fea
= ea_response_data
->list
;
5422 temp_ptr
= (char *)temp_fea
;
5423 /* loop through checking if we have a matching
5424 name and then return the associated value */
5425 while (name_len
> 0) {
5430 le16_to_cpu(temp_fea
->value_len
);
5431 /* BB validate that value_len falls within SMB,
5432 even though maximum for name_len is 255 */
5433 if (memcmp(temp_fea
->name
, ea_name
,
5434 temp_fea
->name_len
) == 0) {
5437 /* account for prefix user. and trailing null */
5438 if (rc
<= (int)buf_size
) {
5440 temp_fea
->name
+temp_fea
->name_len
+1,
5442 /* ea values, unlike ea
5445 } else if (buf_size
== 0) {
5446 /* skip copy - calc size only */
5448 /* stop before overrun buffer */
5453 name_len
-= temp_fea
->name_len
;
5454 temp_ptr
+= temp_fea
->name_len
;
5455 /* account for trailing null */
5458 name_len
-= value_len
;
5459 temp_ptr
+= value_len
;
5460 /* No trailing null to account for in
5461 value_len. Go on to next EA */
5462 temp_fea
= (struct fea
*)temp_ptr
;
5468 cifs_buf_release(pSMB
);
5476 CIFSSMBSetEA(const int xid
, struct cifsTconInfo
*tcon
, const char *fileName
,
5477 const char *ea_name
, const void *ea_value
,
5478 const __u16 ea_value_len
, const struct nls_table
*nls_codepage
,
5481 struct smb_com_transaction2_spi_req
*pSMB
= NULL
;
5482 struct smb_com_transaction2_spi_rsp
*pSMBr
= NULL
;
5483 struct fealist
*parm_data
;
5486 int bytes_returned
= 0;
5487 __u16 params
, param_offset
, byte_count
, offset
, count
;
5489 cFYI(1, ("In SetEA"));
5491 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
5496 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
5498 cifsConvertToUCS((__le16
*) pSMB
->FileName
, fileName
,
5499 PATH_MAX
, nls_codepage
, remap
);
5500 name_len
++; /* trailing null */
5502 } else { /* BB improve the check for buffer overruns BB */
5503 name_len
= strnlen(fileName
, PATH_MAX
);
5504 name_len
++; /* trailing null */
5505 strncpy(pSMB
->FileName
, fileName
, name_len
);
5508 params
= 6 + name_len
;
5510 /* done calculating parms using name_len of file name,
5511 now use name_len to calculate length of ea name
5512 we are going to create in the inode xattrs */
5513 if (ea_name
== NULL
)
5516 name_len
= strnlen(ea_name
, 255);
5518 count
= sizeof(*parm_data
) + ea_value_len
+ name_len
+ 1;
5519 pSMB
->MaxParameterCount
= cpu_to_le16(2);
5520 pSMB
->MaxDataCount
= cpu_to_le16(1000); /* BB find max SMB size from sess */
5521 pSMB
->MaxSetupCount
= 0;
5525 pSMB
->Reserved2
= 0;
5526 param_offset
= offsetof(struct smb_com_transaction2_spi_req
,
5527 InformationLevel
) - 4;
5528 offset
= param_offset
+ params
;
5529 pSMB
->InformationLevel
=
5530 cpu_to_le16(SMB_SET_FILE_EA
);
5533 (struct fealist
*) (((char *) &pSMB
->hdr
.Protocol
) +
5535 pSMB
->ParameterOffset
= cpu_to_le16(param_offset
);
5536 pSMB
->DataOffset
= cpu_to_le16(offset
);
5537 pSMB
->SetupCount
= 1;
5538 pSMB
->Reserved3
= 0;
5539 pSMB
->SubCommand
= cpu_to_le16(TRANS2_SET_PATH_INFORMATION
);
5540 byte_count
= 3 /* pad */ + params
+ count
;
5541 pSMB
->DataCount
= cpu_to_le16(count
);
5542 parm_data
->list_len
= cpu_to_le32(count
);
5543 parm_data
->list
[0].EA_flags
= 0;
5544 /* we checked above that name len is less than 255 */
5545 parm_data
->list
[0].name_len
= (__u8
)name_len
;
5546 /* EA names are always ASCII */
5548 strncpy(parm_data
->list
[0].name
, ea_name
, name_len
);
5549 parm_data
->list
[0].name
[name_len
] = 0;
5550 parm_data
->list
[0].value_len
= cpu_to_le16(ea_value_len
);
5551 /* caller ensures that ea_value_len is less than 64K but
5552 we need to ensure that it fits within the smb */
5554 /*BB add length check to see if it would fit in
5555 negotiated SMB buffer size BB */
5556 /* if (ea_value_len > buffer_size - 512 (enough for header)) */
5558 memcpy(parm_data
->list
[0].name
+name_len
+1,
5559 ea_value
, ea_value_len
);
5561 pSMB
->TotalDataCount
= pSMB
->DataCount
;
5562 pSMB
->ParameterCount
= cpu_to_le16(params
);
5563 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
5564 pSMB
->Reserved4
= 0;
5565 pSMB
->hdr
.smb_buf_length
+= byte_count
;
5566 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
5567 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
5568 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
5570 cFYI(1, ("SetPathInfo (EA) returned %d", rc
));
5573 cifs_buf_release(pSMB
);