4 * Copyright (C) International Business Machines Corp., 2002,2006
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 different for reconnection purposes since we never want */
28 /* to reuse a stale file handle and the caller knows the file handle */
31 #include <linux/kernel.h>
32 #include <linux/vfs.h>
33 #include <linux/posix_acl_xattr.h>
34 #include <asm/uaccess.h>
37 #include "cifsproto.h"
38 #include "cifs_unicode.h"
39 #include "cifs_debug.h"
42 #ifdef CONFIG_CIFS_POSIX
47 #ifdef CONFIG_CIFS_WEAK_PW_HASH
48 {LANMAN_PROT
, "\2LM1.2X002"},
49 #endif /* weak password hashing for legacy clients */
50 {CIFS_PROT
, "\2NT LM 0.12"},
51 {POSIX_PROT
, "\2POSIX 2"},
59 #ifdef CONFIG_CIFS_WEAK_PW_HASH
60 {LANMAN_PROT
, "\2LM1.2X002"},
61 #endif /* weak password hashing for legacy clients */
62 {CIFS_PROT
, "\2NT LM 0.12"},
67 /* define the number of elements in the cifs dialect array */
68 #ifdef CONFIG_CIFS_POSIX
69 #ifdef CONFIG_CIFS_WEAK_PW_HASH
70 #define CIFS_NUM_PROT 3
72 #define CIFS_NUM_PROT 2
73 #endif /* CIFS_WEAK_PW_HASH */
75 #ifdef CONFIG_CIFS_WEAK_PW_HASH
76 #define CIFS_NUM_PROT 2
78 #define CIFS_NUM_PROT 1
79 #endif /* CONFIG_CIFS_WEAK_PW_HASH */
80 #endif /* CIFS_POSIX */
83 /* Mark as invalid, all open files on tree connections since they
84 were closed when session to server was lost */
85 static void mark_open_files_invalid(struct cifsTconInfo
* pTcon
)
87 struct cifsFileInfo
*open_file
= NULL
;
88 struct list_head
* tmp
;
89 struct list_head
* tmp1
;
91 /* list all files open on tree connection and mark them invalid */
92 write_lock(&GlobalSMBSeslock
);
93 list_for_each_safe(tmp
, tmp1
, &pTcon
->openFileList
) {
94 open_file
= list_entry(tmp
,struct cifsFileInfo
, tlist
);
96 open_file
->invalidHandle
= TRUE
;
99 write_unlock(&GlobalSMBSeslock
);
100 /* BB Add call to invalidate_inodes(sb) for all superblocks mounted
104 /* If the return code is zero, this function must fill in request_buf pointer */
106 small_smb_init(int smb_command
, int wct
, struct cifsTconInfo
*tcon
,
107 void **request_buf
/* returned */)
111 /* SMBs NegProt, SessSetup, uLogoff do not have tcon yet so
112 check for tcp and smb session status done differently
113 for those three - in the calling routine */
115 if(tcon
->tidStatus
== CifsExiting
) {
116 /* only tree disconnect, open, and write,
117 (and ulogoff which does not have tcon)
118 are allowed as we start force umount */
119 if((smb_command
!= SMB_COM_WRITE_ANDX
) &&
120 (smb_command
!= SMB_COM_OPEN_ANDX
) &&
121 (smb_command
!= SMB_COM_TREE_DISCONNECT
)) {
122 cFYI(1,("can not send cmd %d while umounting",
127 if((tcon
->ses
) && (tcon
->ses
->status
!= CifsExiting
) &&
128 (tcon
->ses
->server
)){
129 struct nls_table
*nls_codepage
;
130 /* Give Demultiplex thread up to 10 seconds to
131 reconnect, should be greater than cifs socket
132 timeout which is 7 seconds */
133 while(tcon
->ses
->server
->tcpStatus
== CifsNeedReconnect
) {
134 wait_event_interruptible_timeout(tcon
->ses
->server
->response_q
,
135 (tcon
->ses
->server
->tcpStatus
== CifsGood
), 10 * HZ
);
136 if(tcon
->ses
->server
->tcpStatus
== CifsNeedReconnect
) {
137 /* on "soft" mounts we wait once */
138 if((tcon
->retry
== FALSE
) ||
139 (tcon
->ses
->status
== CifsExiting
)) {
140 cFYI(1,("gave up waiting on reconnect in smb_init"));
142 } /* else "hard" mount - keep retrying
143 until process is killed or server
144 comes back on-line */
145 } else /* TCP session is reestablished now */
150 nls_codepage
= load_nls_default();
151 /* need to prevent multiple threads trying to
152 simultaneously reconnect the same SMB session */
153 down(&tcon
->ses
->sesSem
);
154 if(tcon
->ses
->status
== CifsNeedReconnect
)
155 rc
= cifs_setup_session(0, tcon
->ses
,
157 if(!rc
&& (tcon
->tidStatus
== CifsNeedReconnect
)) {
158 mark_open_files_invalid(tcon
);
159 rc
= CIFSTCon(0, tcon
->ses
, tcon
->treeName
, tcon
161 up(&tcon
->ses
->sesSem
);
162 /* BB FIXME add code to check if wsize needs
163 update due to negotiated smb buffer size
166 atomic_inc(&tconInfoReconnectCount
);
168 cFYI(1, ("reconnect tcon rc = %d", rc
));
169 /* Removed call to reopen open files here -
170 it is safer (and faster) to reopen files
171 one at a time as needed in read and write */
173 /* Check if handle based operation so we
174 know whether we can continue or not without
175 returning to caller to reset file handle */
176 switch(smb_command
) {
177 case SMB_COM_READ_ANDX
:
178 case SMB_COM_WRITE_ANDX
:
180 case SMB_COM_FIND_CLOSE2
:
181 case SMB_COM_LOCKING_ANDX
: {
182 unload_nls(nls_codepage
);
187 up(&tcon
->ses
->sesSem
);
189 unload_nls(nls_codepage
);
198 *request_buf
= cifs_small_buf_get();
199 if (*request_buf
== NULL
) {
200 /* BB should we add a retry in here if not a writepage? */
204 header_assemble((struct smb_hdr
*) *request_buf
, smb_command
, tcon
,wct
);
207 cifs_stats_inc(&tcon
->num_smbs_sent
);
213 small_smb_init_no_tc(const int smb_command
, const int wct
,
214 struct cifsSesInfo
*ses
, void **request_buf
)
217 struct smb_hdr
* buffer
;
219 rc
= small_smb_init(smb_command
, wct
, NULL
, request_buf
);
223 buffer
= (struct smb_hdr
*)*request_buf
;
224 buffer
->Mid
= GetNextMid(ses
->server
);
225 if (ses
->capabilities
& CAP_UNICODE
)
226 buffer
->Flags2
|= SMBFLG2_UNICODE
;
227 if (ses
->capabilities
& CAP_STATUS32
)
228 buffer
->Flags2
|= SMBFLG2_ERR_STATUS
;
230 /* uid, tid can stay at zero as set in header assemble */
232 /* BB add support for turning on the signing when
233 this function is used after 1st of session setup requests */
238 /* If the return code is zero, this function must fill in request_buf pointer */
240 smb_init(int smb_command
, int wct
, struct cifsTconInfo
*tcon
,
241 void **request_buf
/* returned */ ,
242 void **response_buf
/* returned */ )
246 /* SMBs NegProt, SessSetup, uLogoff do not have tcon yet so
247 check for tcp and smb session status done differently
248 for those three - in the calling routine */
250 if(tcon
->tidStatus
== CifsExiting
) {
251 /* only tree disconnect, open, and write,
252 (and ulogoff which does not have tcon)
253 are allowed as we start force umount */
254 if((smb_command
!= SMB_COM_WRITE_ANDX
) &&
255 (smb_command
!= SMB_COM_OPEN_ANDX
) &&
256 (smb_command
!= SMB_COM_TREE_DISCONNECT
)) {
257 cFYI(1,("can not send cmd %d while umounting",
263 if((tcon
->ses
) && (tcon
->ses
->status
!= CifsExiting
) &&
264 (tcon
->ses
->server
)){
265 struct nls_table
*nls_codepage
;
266 /* Give Demultiplex thread up to 10 seconds to
267 reconnect, should be greater than cifs socket
268 timeout which is 7 seconds */
269 while(tcon
->ses
->server
->tcpStatus
== CifsNeedReconnect
) {
270 wait_event_interruptible_timeout(tcon
->ses
->server
->response_q
,
271 (tcon
->ses
->server
->tcpStatus
== CifsGood
), 10 * HZ
);
272 if(tcon
->ses
->server
->tcpStatus
==
274 /* on "soft" mounts we wait once */
275 if((tcon
->retry
== FALSE
) ||
276 (tcon
->ses
->status
== CifsExiting
)) {
277 cFYI(1,("gave up waiting on reconnect in smb_init"));
279 } /* else "hard" mount - keep retrying
280 until process is killed or server
282 } else /* TCP session is reestablished now */
287 nls_codepage
= load_nls_default();
288 /* need to prevent multiple threads trying to
289 simultaneously reconnect the same SMB session */
290 down(&tcon
->ses
->sesSem
);
291 if(tcon
->ses
->status
== CifsNeedReconnect
)
292 rc
= cifs_setup_session(0, tcon
->ses
,
294 if(!rc
&& (tcon
->tidStatus
== CifsNeedReconnect
)) {
295 mark_open_files_invalid(tcon
);
296 rc
= CIFSTCon(0, tcon
->ses
, tcon
->treeName
,
298 up(&tcon
->ses
->sesSem
);
299 /* BB FIXME add code to check if wsize needs
300 update due to negotiated smb buffer size
303 atomic_inc(&tconInfoReconnectCount
);
305 cFYI(1, ("reconnect tcon rc = %d", rc
));
306 /* Removed call to reopen open files here -
307 it is safer (and faster) to reopen files
308 one at a time as needed in read and write */
310 /* Check if handle based operation so we
311 know whether we can continue or not without
312 returning to caller to reset file handle */
313 switch(smb_command
) {
314 case SMB_COM_READ_ANDX
:
315 case SMB_COM_WRITE_ANDX
:
317 case SMB_COM_FIND_CLOSE2
:
318 case SMB_COM_LOCKING_ANDX
: {
319 unload_nls(nls_codepage
);
324 up(&tcon
->ses
->sesSem
);
326 unload_nls(nls_codepage
);
335 *request_buf
= cifs_buf_get();
336 if (*request_buf
== NULL
) {
337 /* BB should we add a retry in here if not a writepage? */
340 /* Although the original thought was we needed the response buf for */
341 /* potential retries of smb operations it turns out we can determine */
342 /* from the mid flags when the request buffer can be resent without */
343 /* having to use a second distinct buffer for the response */
345 *response_buf
= *request_buf
;
347 header_assemble((struct smb_hdr
*) *request_buf
, smb_command
, tcon
,
351 cifs_stats_inc(&tcon
->num_smbs_sent
);
356 static int validate_t2(struct smb_t2_rsp
* pSMB
)
362 /* check for plausible wct, bcc and t2 data and parm sizes */
363 /* check for parm and data offset going beyond end of smb */
364 if(pSMB
->hdr
.WordCount
>= 10) {
365 if((le16_to_cpu(pSMB
->t2_rsp
.ParameterOffset
) <= 1024) &&
366 (le16_to_cpu(pSMB
->t2_rsp
.DataOffset
) <= 1024)) {
367 /* check that bcc is at least as big as parms + data */
368 /* check that bcc is less than negotiated smb buffer */
369 total_size
= le16_to_cpu(pSMB
->t2_rsp
.ParameterCount
);
370 if(total_size
< 512) {
371 total_size
+=le16_to_cpu(pSMB
->t2_rsp
.DataCount
);
372 /* BCC le converted in SendReceive */
373 pBCC
= (pSMB
->hdr
.WordCount
* 2) +
374 sizeof(struct smb_hdr
) +
376 if((total_size
<= (*(u16
*)pBCC
)) &&
378 CIFSMaxBufSize
+MAX_CIFS_HDR_SIZE
)) {
385 cifs_dump_mem("Invalid transact2 SMB: ",(char *)pSMB
,
386 sizeof(struct smb_t2_rsp
) + 16);
390 CIFSSMBNegotiate(unsigned int xid
, struct cifsSesInfo
*ses
)
393 NEGOTIATE_RSP
*pSMBr
;
397 struct TCP_Server_Info
* server
;
399 unsigned int secFlags
;
402 server
= ses
->server
;
407 rc
= smb_init(SMB_COM_NEGOTIATE
, 0, NULL
/* no tcon yet */ ,
408 (void **) &pSMB
, (void **) &pSMBr
);
412 /* if any of auth flags (ie not sign or seal) are overriden use them */
413 if(ses
->overrideSecFlg
& (~(CIFSSEC_MUST_SIGN
| CIFSSEC_MUST_SEAL
)))
414 secFlags
= ses
->overrideSecFlg
;
415 else /* if override flags set only sign/seal OR them with global auth */
416 secFlags
= extended_security
| ses
->overrideSecFlg
;
418 cFYI(1,("secFlags 0x%x",secFlags
));
420 pSMB
->hdr
.Mid
= GetNextMid(server
);
421 pSMB
->hdr
.Flags2
|= SMBFLG2_UNICODE
;
422 if((secFlags
& CIFSSEC_MUST_KRB5
) == CIFSSEC_MUST_KRB5
)
423 pSMB
->hdr
.Flags2
|= SMBFLG2_EXT_SEC
;
426 for(i
=0;i
<CIFS_NUM_PROT
;i
++) {
427 strncpy(pSMB
->DialectsArray
+count
, protocols
[i
].name
, 16);
428 count
+= strlen(protocols
[i
].name
) + 1;
429 /* null at end of source and target buffers anyway */
431 pSMB
->hdr
.smb_buf_length
+= count
;
432 pSMB
->ByteCount
= cpu_to_le16(count
);
434 rc
= SendReceive(xid
, ses
, (struct smb_hdr
*) pSMB
,
435 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
439 cFYI(1,("Dialect: %d", pSMBr
->DialectIndex
));
440 /* Check wct = 1 error case */
441 if((pSMBr
->hdr
.WordCount
< 13) || (pSMBr
->DialectIndex
== BAD_PROT
)) {
442 /* core returns wct = 1, but we do not ask for core - otherwise
443 small wct just comes when dialect index is -1 indicating we
444 could not negotiate a common dialect */
447 #ifdef CONFIG_CIFS_WEAK_PW_HASH
448 } else if((pSMBr
->hdr
.WordCount
== 13)
449 && (pSMBr
->DialectIndex
== LANMAN_PROT
)) {
450 struct lanman_neg_rsp
* rsp
= (struct lanman_neg_rsp
*)pSMBr
;
452 if((secFlags
& CIFSSEC_MAY_LANMAN
) ||
453 (secFlags
& CIFSSEC_MAY_PLNTXT
))
454 server
->secType
= LANMAN
;
456 cERROR(1, ("mount failed weak security disabled"
457 " in /proc/fs/cifs/SecurityFlags"));
461 server
->secMode
= (__u8
)le16_to_cpu(rsp
->SecurityMode
);
462 server
->maxReq
= le16_to_cpu(rsp
->MaxMpxCount
);
463 server
->maxBuf
= min((__u32
)le16_to_cpu(rsp
->MaxBufSize
),
464 (__u32
)CIFSMaxBufSize
+ MAX_CIFS_HDR_SIZE
);
465 GETU32(server
->sessid
) = le32_to_cpu(rsp
->SessionKey
);
466 /* even though we do not use raw we might as well set this
467 accurately, in case we ever find a need for it */
468 if((le16_to_cpu(rsp
->RawMode
) & RAW_ENABLE
) == RAW_ENABLE
) {
469 server
->maxRw
= 0xFF00;
470 server
->capabilities
= CAP_MPX_MODE
| CAP_RAW_MODE
;
472 server
->maxRw
= 0;/* we do not need to use raw anyway */
473 server
->capabilities
= CAP_MPX_MODE
;
475 server
->timeZone
= le16_to_cpu(rsp
->ServerTimeZone
);
477 /* BB get server time for time conversions and add
478 code to use it and timezone since this is not UTC */
480 if (rsp
->EncryptionKeyLength
== CIFS_CRYPTO_KEY_SIZE
) {
481 memcpy(server
->cryptKey
, rsp
->EncryptionKey
,
482 CIFS_CRYPTO_KEY_SIZE
);
483 } else if (server
->secMode
& SECMODE_PW_ENCRYPT
) {
484 rc
= -EIO
; /* need cryptkey unless plain text */
488 cFYI(1,("LANMAN negotiated"));
489 /* we will not end up setting signing flags - as no signing
490 was in LANMAN and server did not return the flags on */
492 #else /* weak security disabled */
493 } else if(pSMBr
->hdr
.WordCount
== 13) {
494 cERROR(1,("mount failed, cifs module not built "
495 "with CIFS_WEAK_PW_HASH support"));
497 #endif /* WEAK_PW_HASH */
499 } else if(pSMBr
->hdr
.WordCount
!= 17) {
504 /* else wct == 17 NTLM */
505 server
->secMode
= pSMBr
->SecurityMode
;
506 if((server
->secMode
& SECMODE_USER
) == 0)
507 cFYI(1,("share mode security"));
509 if((server
->secMode
& SECMODE_PW_ENCRYPT
) == 0)
510 #ifdef CONFIG_CIFS_WEAK_PW_HASH
511 if ((secFlags
& CIFSSEC_MAY_PLNTXT
) == 0)
512 #endif /* CIFS_WEAK_PW_HASH */
513 cERROR(1,("Server requests plain text password"
514 " but client support disabled"));
516 if((secFlags
& CIFSSEC_MUST_NTLMV2
) == CIFSSEC_MUST_NTLMV2
)
517 server
->secType
= NTLMv2
;
518 else if(secFlags
& CIFSSEC_MAY_NTLM
)
519 server
->secType
= NTLM
;
520 else if(secFlags
& CIFSSEC_MAY_NTLMV2
)
521 server
->secType
= NTLMv2
;
522 /* else krb5 ... any others ... */
524 /* one byte, so no need to convert this or EncryptionKeyLen from
526 server
->maxReq
= le16_to_cpu(pSMBr
->MaxMpxCount
);
527 /* probably no need to store and check maxvcs */
528 server
->maxBuf
= min(le32_to_cpu(pSMBr
->MaxBufferSize
),
529 (__u32
) CIFSMaxBufSize
+ MAX_CIFS_HDR_SIZE
);
530 server
->maxRw
= le32_to_cpu(pSMBr
->MaxRawSize
);
531 cFYI(0, ("Max buf = %d", ses
->server
->maxBuf
));
532 GETU32(ses
->server
->sessid
) = le32_to_cpu(pSMBr
->SessionKey
);
533 server
->capabilities
= le32_to_cpu(pSMBr
->Capabilities
);
534 server
->timeZone
= le16_to_cpu(pSMBr
->ServerTimeZone
);
535 if (pSMBr
->EncryptionKeyLength
== CIFS_CRYPTO_KEY_SIZE
) {
536 memcpy(server
->cryptKey
, pSMBr
->u
.EncryptionKey
,
537 CIFS_CRYPTO_KEY_SIZE
);
538 } else if ((pSMBr
->hdr
.Flags2
& SMBFLG2_EXT_SEC
)
539 && (pSMBr
->EncryptionKeyLength
== 0)) {
540 /* decode security blob */
541 } else if (server
->secMode
& SECMODE_PW_ENCRYPT
) {
542 rc
= -EIO
; /* no crypt key only if plain text pwd */
546 /* BB might be helpful to save off the domain of server here */
548 if ((pSMBr
->hdr
.Flags2
& SMBFLG2_EXT_SEC
) &&
549 (server
->capabilities
& CAP_EXTENDED_SECURITY
)) {
550 count
= pSMBr
->ByteCount
;
553 else if (count
== 16) {
554 server
->secType
= RawNTLMSSP
;
555 if (server
->socketUseCount
.counter
> 1) {
556 if (memcmp(server
->server_GUID
,
557 pSMBr
->u
.extended_response
.
559 cFYI(1, ("server UID changed"));
560 memcpy(server
->server_GUID
,
561 pSMBr
->u
.extended_response
.GUID
,
565 memcpy(server
->server_GUID
,
566 pSMBr
->u
.extended_response
.GUID
, 16);
568 rc
= decode_negTokenInit(pSMBr
->u
.extended_response
.
573 /* BB Need to fill struct for sessetup here */
580 server
->capabilities
&= ~CAP_EXTENDED_SECURITY
;
582 #ifdef CONFIG_CIFS_WEAK_PW_HASH
585 if(sign_CIFS_PDUs
== FALSE
) {
586 if(server
->secMode
& SECMODE_SIGN_REQUIRED
)
587 cERROR(1,("Server requires "
588 "/proc/fs/cifs/PacketSigningEnabled to be on"));
590 ~(SECMODE_SIGN_ENABLED
| SECMODE_SIGN_REQUIRED
);
591 } else if(sign_CIFS_PDUs
== 1) {
592 if((server
->secMode
& SECMODE_SIGN_REQUIRED
) == 0)
594 ~(SECMODE_SIGN_ENABLED
| SECMODE_SIGN_REQUIRED
);
595 } else if(sign_CIFS_PDUs
== 2) {
596 if((server
->secMode
&
597 (SECMODE_SIGN_ENABLED
| SECMODE_SIGN_REQUIRED
)) == 0) {
598 cERROR(1,("signing required but server lacks support"));
602 cifs_buf_release(pSMB
);
604 cFYI(1,("negprot rc %d",rc
));
609 CIFSSMBTDis(const int xid
, struct cifsTconInfo
*tcon
)
611 struct smb_hdr
*smb_buffer
;
612 struct smb_hdr
*smb_buffer_response
; /* BB removeme BB */
616 cFYI(1, ("In tree disconnect"));
618 * If last user of the connection and
619 * connection alive - disconnect it
620 * If this is the last connection on the server session disconnect it
621 * (and inside session disconnect we should check if tcp socket needs
622 * to be freed and kernel thread woken up).
625 down(&tcon
->tconSem
);
629 atomic_dec(&tcon
->useCount
);
630 if (atomic_read(&tcon
->useCount
) > 0) {
635 /* No need to return error on this operation if tid invalidated and
636 closed on server already e.g. due to tcp session crashing */
637 if(tcon
->tidStatus
== CifsNeedReconnect
) {
642 if((tcon
->ses
== NULL
) || (tcon
->ses
->server
== NULL
)) {
646 rc
= small_smb_init(SMB_COM_TREE_DISCONNECT
, 0, tcon
,
647 (void **)&smb_buffer
);
652 smb_buffer_response
= smb_buffer
; /* BB removeme BB */
654 rc
= SendReceive(xid
, tcon
->ses
, smb_buffer
, smb_buffer_response
,
657 cFYI(1, ("Tree disconnect failed %d", rc
));
660 cifs_small_buf_release(smb_buffer
);
663 /* No need to return error on this operation if tid invalidated and
664 closed on server already e.g. due to tcp session crashing */
672 CIFSSMBLogoff(const int xid
, struct cifsSesInfo
*ses
)
674 struct smb_hdr
*smb_buffer_response
;
675 LOGOFF_ANDX_REQ
*pSMB
;
679 cFYI(1, ("In SMBLogoff for session disconnect"));
685 atomic_dec(&ses
->inUse
);
686 if (atomic_read(&ses
->inUse
) > 0) {
690 rc
= small_smb_init(SMB_COM_LOGOFF_ANDX
, 2, NULL
, (void **)&pSMB
);
696 smb_buffer_response
= (struct smb_hdr
*)pSMB
; /* BB removeme BB */
699 pSMB
->hdr
.Mid
= GetNextMid(ses
->server
);
701 if(ses
->server
->secMode
&
702 (SECMODE_SIGN_REQUIRED
| SECMODE_SIGN_ENABLED
))
703 pSMB
->hdr
.Flags2
|= SMBFLG2_SECURITY_SIGNATURE
;
706 pSMB
->hdr
.Uid
= ses
->Suid
;
708 pSMB
->AndXCommand
= 0xFF;
709 rc
= SendReceive(xid
, ses
, (struct smb_hdr
*) pSMB
,
710 smb_buffer_response
, &length
, 0);
712 atomic_dec(&ses
->server
->socketUseCount
);
713 if (atomic_read(&ses
->server
->socketUseCount
) == 0) {
714 spin_lock(&GlobalMid_Lock
);
715 ses
->server
->tcpStatus
= CifsExiting
;
716 spin_unlock(&GlobalMid_Lock
);
721 cifs_small_buf_release(pSMB
);
723 /* if session dead then we do not need to do ulogoff,
724 since server closed smb session, no sense reporting
732 CIFSSMBDelFile(const int xid
, struct cifsTconInfo
*tcon
, const char *fileName
,
733 const struct nls_table
*nls_codepage
, int remap
)
735 DELETE_FILE_REQ
*pSMB
= NULL
;
736 DELETE_FILE_RSP
*pSMBr
= NULL
;
742 rc
= smb_init(SMB_COM_DELETE
, 1, tcon
, (void **) &pSMB
,
747 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
749 cifsConvertToUCS((__le16
*) pSMB
->fileName
, fileName
,
750 PATH_MAX
, nls_codepage
, remap
);
751 name_len
++; /* trailing null */
753 } else { /* BB improve check for buffer overruns BB */
754 name_len
= strnlen(fileName
, PATH_MAX
);
755 name_len
++; /* trailing null */
756 strncpy(pSMB
->fileName
, fileName
, name_len
);
758 pSMB
->SearchAttributes
=
759 cpu_to_le16(ATTR_READONLY
| ATTR_HIDDEN
| ATTR_SYSTEM
);
760 pSMB
->BufferFormat
= 0x04;
761 pSMB
->hdr
.smb_buf_length
+= name_len
+ 1;
762 pSMB
->ByteCount
= cpu_to_le16(name_len
+ 1);
763 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
764 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
765 cifs_stats_inc(&tcon
->num_deletes
);
767 cFYI(1, ("Error in RMFile = %d", rc
));
770 cifs_buf_release(pSMB
);
778 CIFSSMBRmDir(const int xid
, struct cifsTconInfo
*tcon
, const char *dirName
,
779 const struct nls_table
*nls_codepage
, int remap
)
781 DELETE_DIRECTORY_REQ
*pSMB
= NULL
;
782 DELETE_DIRECTORY_RSP
*pSMBr
= NULL
;
787 cFYI(1, ("In CIFSSMBRmDir"));
789 rc
= smb_init(SMB_COM_DELETE_DIRECTORY
, 0, tcon
, (void **) &pSMB
,
794 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
795 name_len
= cifsConvertToUCS((__le16
*) pSMB
->DirName
, dirName
,
796 PATH_MAX
, nls_codepage
, remap
);
797 name_len
++; /* trailing null */
799 } else { /* BB improve check for buffer overruns BB */
800 name_len
= strnlen(dirName
, PATH_MAX
);
801 name_len
++; /* trailing null */
802 strncpy(pSMB
->DirName
, dirName
, name_len
);
805 pSMB
->BufferFormat
= 0x04;
806 pSMB
->hdr
.smb_buf_length
+= name_len
+ 1;
807 pSMB
->ByteCount
= cpu_to_le16(name_len
+ 1);
808 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
809 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
810 cifs_stats_inc(&tcon
->num_rmdirs
);
812 cFYI(1, ("Error in RMDir = %d", rc
));
815 cifs_buf_release(pSMB
);
822 CIFSSMBMkDir(const int xid
, struct cifsTconInfo
*tcon
,
823 const char *name
, const struct nls_table
*nls_codepage
, int remap
)
826 CREATE_DIRECTORY_REQ
*pSMB
= NULL
;
827 CREATE_DIRECTORY_RSP
*pSMBr
= NULL
;
831 cFYI(1, ("In CIFSSMBMkDir"));
833 rc
= smb_init(SMB_COM_CREATE_DIRECTORY
, 0, tcon
, (void **) &pSMB
,
838 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
839 name_len
= cifsConvertToUCS((__le16
*) pSMB
->DirName
, name
,
840 PATH_MAX
, nls_codepage
, remap
);
841 name_len
++; /* trailing null */
843 } else { /* BB improve check for buffer overruns BB */
844 name_len
= strnlen(name
, PATH_MAX
);
845 name_len
++; /* trailing null */
846 strncpy(pSMB
->DirName
, name
, name_len
);
849 pSMB
->BufferFormat
= 0x04;
850 pSMB
->hdr
.smb_buf_length
+= name_len
+ 1;
851 pSMB
->ByteCount
= cpu_to_le16(name_len
+ 1);
852 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
853 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
854 cifs_stats_inc(&tcon
->num_mkdirs
);
856 cFYI(1, ("Error in Mkdir = %d", rc
));
859 cifs_buf_release(pSMB
);
865 static __u16
convert_disposition(int disposition
)
869 switch (disposition
) {
871 ofun
= SMBOPEN_OCREATE
| SMBOPEN_OTRUNC
;
874 ofun
= SMBOPEN_OAPPEND
;
877 ofun
= SMBOPEN_OCREATE
;
880 ofun
= SMBOPEN_OCREATE
| SMBOPEN_OAPPEND
;
883 ofun
= SMBOPEN_OTRUNC
;
885 case FILE_OVERWRITE_IF
:
886 ofun
= SMBOPEN_OCREATE
| SMBOPEN_OTRUNC
;
889 cFYI(1,("unknown disposition %d",disposition
));
890 ofun
= SMBOPEN_OAPPEND
; /* regular open */
896 SMBLegacyOpen(const int xid
, struct cifsTconInfo
*tcon
,
897 const char *fileName
, const int openDisposition
,
898 const int access_flags
, const int create_options
, __u16
* netfid
,
899 int *pOplock
, FILE_ALL_INFO
* pfile_info
,
900 const struct nls_table
*nls_codepage
, int remap
)
903 OPENX_REQ
*pSMB
= NULL
;
904 OPENX_RSP
*pSMBr
= NULL
;
910 rc
= smb_init(SMB_COM_OPEN_ANDX
, 15, tcon
, (void **) &pSMB
,
915 pSMB
->AndXCommand
= 0xFF; /* none */
917 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
918 count
= 1; /* account for one byte pad to word boundary */
920 cifsConvertToUCS((__le16
*) (pSMB
->fileName
+ 1),
921 fileName
, PATH_MAX
, nls_codepage
, remap
);
922 name_len
++; /* trailing null */
924 } else { /* BB improve check for buffer overruns BB */
925 count
= 0; /* no pad */
926 name_len
= strnlen(fileName
, PATH_MAX
);
927 name_len
++; /* trailing null */
928 strncpy(pSMB
->fileName
, fileName
, name_len
);
930 if (*pOplock
& REQ_OPLOCK
)
931 pSMB
->OpenFlags
= cpu_to_le16(REQ_OPLOCK
);
932 else if (*pOplock
& REQ_BATCHOPLOCK
) {
933 pSMB
->OpenFlags
= cpu_to_le16(REQ_BATCHOPLOCK
);
935 pSMB
->OpenFlags
|= cpu_to_le16(REQ_MORE_INFO
);
936 /* BB fixme add conversion for access_flags to bits 0 - 2 of mode */
942 pSMB
->Mode
= cpu_to_le16(2);
943 pSMB
->Mode
|= cpu_to_le16(0x40); /* deny none */
944 /* set file as system file if special file such
945 as fifo and server expecting SFU style and
946 no Unix extensions */
948 if(create_options
& CREATE_OPTION_SPECIAL
)
949 pSMB
->FileAttributes
= cpu_to_le16(ATTR_SYSTEM
);
951 pSMB
->FileAttributes
= cpu_to_le16(0/*ATTR_NORMAL*/); /* BB FIXME */
953 /* if ((omode & S_IWUGO) == 0)
954 pSMB->FileAttributes |= cpu_to_le32(ATTR_READONLY);*/
955 /* Above line causes problems due to vfs splitting create into two
956 pieces - need to set mode after file created not while it is
960 /* pSMB->CreateOptions = cpu_to_le32(create_options & CREATE_OPTIONS_MASK); */
961 /* BB FIXME END BB */
963 pSMB
->Sattr
= cpu_to_le16(ATTR_HIDDEN
| ATTR_SYSTEM
| ATTR_DIRECTORY
);
964 pSMB
->OpenFunction
= cpu_to_le16(convert_disposition(openDisposition
));
966 pSMB
->hdr
.smb_buf_length
+= count
;
968 pSMB
->ByteCount
= cpu_to_le16(count
);
969 /* long_op set to 1 to allow for oplock break timeouts */
970 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
971 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 1);
972 cifs_stats_inc(&tcon
->num_opens
);
974 cFYI(1, ("Error in Open = %d", rc
));
976 /* BB verify if wct == 15 */
978 /* *pOplock = pSMBr->OplockLevel; */ /* BB take from action field BB */
980 *netfid
= pSMBr
->Fid
; /* cifs fid stays in le */
981 /* Let caller know file was created so we can set the mode. */
982 /* Do we care about the CreateAction in any other cases? */
984 /* if(cpu_to_le32(FILE_CREATE) == pSMBr->CreateAction)
985 *pOplock |= CIFS_CREATE_ACTION; */
989 pfile_info
->CreationTime
= 0; /* BB convert CreateTime*/
990 pfile_info
->LastAccessTime
= 0; /* BB fixme */
991 pfile_info
->LastWriteTime
= 0; /* BB fixme */
992 pfile_info
->ChangeTime
= 0; /* BB fixme */
993 pfile_info
->Attributes
=
994 cpu_to_le32(le16_to_cpu(pSMBr
->FileAttributes
));
995 /* the file_info buf is endian converted by caller */
996 pfile_info
->AllocationSize
=
997 cpu_to_le64(le32_to_cpu(pSMBr
->EndOfFile
));
998 pfile_info
->EndOfFile
= pfile_info
->AllocationSize
;
999 pfile_info
->NumberOfLinks
= cpu_to_le32(1);
1003 cifs_buf_release(pSMB
);
1010 CIFSSMBOpen(const int xid
, struct cifsTconInfo
*tcon
,
1011 const char *fileName
, const int openDisposition
,
1012 const int access_flags
, const int create_options
, __u16
* netfid
,
1013 int *pOplock
, FILE_ALL_INFO
* pfile_info
,
1014 const struct nls_table
*nls_codepage
, int remap
)
1017 OPEN_REQ
*pSMB
= NULL
;
1018 OPEN_RSP
*pSMBr
= NULL
;
1024 rc
= smb_init(SMB_COM_NT_CREATE_ANDX
, 24, tcon
, (void **) &pSMB
,
1029 pSMB
->AndXCommand
= 0xFF; /* none */
1031 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
1032 count
= 1; /* account for one byte pad to word boundary */
1034 cifsConvertToUCS((__le16
*) (pSMB
->fileName
+ 1),
1035 fileName
, PATH_MAX
, nls_codepage
, remap
);
1036 name_len
++; /* trailing null */
1038 pSMB
->NameLength
= cpu_to_le16(name_len
);
1039 } else { /* BB improve check for buffer overruns BB */
1040 count
= 0; /* no pad */
1041 name_len
= strnlen(fileName
, PATH_MAX
);
1042 name_len
++; /* trailing null */
1043 pSMB
->NameLength
= cpu_to_le16(name_len
);
1044 strncpy(pSMB
->fileName
, fileName
, name_len
);
1046 if (*pOplock
& REQ_OPLOCK
)
1047 pSMB
->OpenFlags
= cpu_to_le32(REQ_OPLOCK
);
1048 else if (*pOplock
& REQ_BATCHOPLOCK
) {
1049 pSMB
->OpenFlags
= cpu_to_le32(REQ_BATCHOPLOCK
);
1051 pSMB
->DesiredAccess
= cpu_to_le32(access_flags
);
1052 pSMB
->AllocationSize
= 0;
1053 /* set file as system file if special file such
1054 as fifo and server expecting SFU style and
1055 no Unix extensions */
1056 if(create_options
& CREATE_OPTION_SPECIAL
)
1057 pSMB
->FileAttributes
= cpu_to_le32(ATTR_SYSTEM
);
1059 pSMB
->FileAttributes
= cpu_to_le32(ATTR_NORMAL
);
1060 /* XP does not handle ATTR_POSIX_SEMANTICS */
1061 /* but it helps speed up case sensitive checks for other
1062 servers such as Samba */
1063 if (tcon
->ses
->capabilities
& CAP_UNIX
)
1064 pSMB
->FileAttributes
|= cpu_to_le32(ATTR_POSIX_SEMANTICS
);
1066 /* if ((omode & S_IWUGO) == 0)
1067 pSMB->FileAttributes |= cpu_to_le32(ATTR_READONLY);*/
1068 /* Above line causes problems due to vfs splitting create into two
1069 pieces - need to set mode after file created not while it is
1071 pSMB
->ShareAccess
= cpu_to_le32(FILE_SHARE_ALL
);
1072 pSMB
->CreateDisposition
= cpu_to_le32(openDisposition
);
1073 pSMB
->CreateOptions
= cpu_to_le32(create_options
& CREATE_OPTIONS_MASK
);
1074 /* BB Expirement with various impersonation levels and verify */
1075 pSMB
->ImpersonationLevel
= cpu_to_le32(SECURITY_IMPERSONATION
);
1076 pSMB
->SecurityFlags
=
1077 SECURITY_CONTEXT_TRACKING
| SECURITY_EFFECTIVE_ONLY
;
1080 pSMB
->hdr
.smb_buf_length
+= count
;
1082 pSMB
->ByteCount
= cpu_to_le16(count
);
1083 /* long_op set to 1 to allow for oplock break timeouts */
1084 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
1085 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 1);
1086 cifs_stats_inc(&tcon
->num_opens
);
1088 cFYI(1, ("Error in Open = %d", rc
));
1090 *pOplock
= pSMBr
->OplockLevel
; /* 1 byte no need to le_to_cpu */
1091 *netfid
= pSMBr
->Fid
; /* cifs fid stays in le */
1092 /* Let caller know file was created so we can set the mode. */
1093 /* Do we care about the CreateAction in any other cases? */
1094 if(cpu_to_le32(FILE_CREATE
) == pSMBr
->CreateAction
)
1095 *pOplock
|= CIFS_CREATE_ACTION
;
1097 memcpy((char *)pfile_info
,(char *)&pSMBr
->CreationTime
,
1098 36 /* CreationTime to Attributes */);
1099 /* the file_info buf is endian converted by caller */
1100 pfile_info
->AllocationSize
= pSMBr
->AllocationSize
;
1101 pfile_info
->EndOfFile
= pSMBr
->EndOfFile
;
1102 pfile_info
->NumberOfLinks
= cpu_to_le32(1);
1106 cifs_buf_release(pSMB
);
1113 CIFSSMBRead(const int xid
, struct cifsTconInfo
*tcon
,
1114 const int netfid
, const unsigned int count
,
1115 const __u64 lseek
, unsigned int *nbytes
, char **buf
,
1119 READ_REQ
*pSMB
= NULL
;
1120 READ_RSP
*pSMBr
= NULL
;
1121 char *pReadData
= NULL
;
1123 int resp_buf_type
= 0;
1126 cFYI(1,("Reading %d bytes on fid %d",count
,netfid
));
1127 if(tcon
->ses
->capabilities
& CAP_LARGE_FILES
)
1130 wct
= 10; /* old style read */
1133 rc
= small_smb_init(SMB_COM_READ_ANDX
, wct
, tcon
, (void **) &pSMB
);
1137 /* tcon and ses pointer are checked in smb_init */
1138 if (tcon
->ses
->server
== NULL
)
1139 return -ECONNABORTED
;
1141 pSMB
->AndXCommand
= 0xFF; /* none */
1143 pSMB
->OffsetLow
= cpu_to_le32(lseek
& 0xFFFFFFFF);
1145 pSMB
->OffsetHigh
= cpu_to_le32(lseek
>> 32);
1146 else if((lseek
>> 32) > 0) /* can not handle this big offset for old */
1149 pSMB
->Remaining
= 0;
1150 pSMB
->MaxCount
= cpu_to_le16(count
& 0xFFFF);
1151 pSMB
->MaxCountHigh
= cpu_to_le32(count
>> 16);
1153 pSMB
->ByteCount
= 0; /* no need to do le conversion since 0 */
1155 /* old style read */
1156 struct smb_com_readx_req
* pSMBW
=
1157 (struct smb_com_readx_req
*)pSMB
;
1158 pSMBW
->ByteCount
= 0;
1161 iov
[0].iov_base
= (char *)pSMB
;
1162 iov
[0].iov_len
= pSMB
->hdr
.smb_buf_length
+ 4;
1163 rc
= SendReceive2(xid
, tcon
->ses
, iov
,
1166 cifs_stats_inc(&tcon
->num_reads
);
1167 pSMBr
= (READ_RSP
*)iov
[0].iov_base
;
1169 cERROR(1, ("Send error in read = %d", rc
));
1171 int data_length
= le16_to_cpu(pSMBr
->DataLengthHigh
);
1172 data_length
= data_length
<< 16;
1173 data_length
+= le16_to_cpu(pSMBr
->DataLength
);
1174 *nbytes
= data_length
;
1176 /*check that DataLength would not go beyond end of SMB */
1177 if ((data_length
> CIFSMaxBufSize
)
1178 || (data_length
> count
)) {
1179 cFYI(1,("bad length %d for count %d",data_length
,count
));
1183 pReadData
= (char *) (&pSMBr
->hdr
.Protocol
) +
1184 le16_to_cpu(pSMBr
->DataOffset
);
1185 /* if(rc = copy_to_user(buf, pReadData, data_length)) {
1186 cERROR(1,("Faulting on read rc = %d",rc));
1188 }*/ /* can not use copy_to_user when using page cache*/
1190 memcpy(*buf
,pReadData
,data_length
);
1194 /* cifs_small_buf_release(pSMB); */ /* Freed earlier now in SendReceive2 */
1196 if(resp_buf_type
== CIFS_SMALL_BUFFER
)
1197 cifs_small_buf_release(iov
[0].iov_base
);
1198 else if(resp_buf_type
== CIFS_LARGE_BUFFER
)
1199 cifs_buf_release(iov
[0].iov_base
);
1200 } else if(resp_buf_type
!= CIFS_NO_BUFFER
) {
1201 /* return buffer to caller to free */
1202 *buf
= iov
[0].iov_base
;
1203 if(resp_buf_type
== CIFS_SMALL_BUFFER
)
1204 *pbuf_type
= CIFS_SMALL_BUFFER
;
1205 else if(resp_buf_type
== CIFS_LARGE_BUFFER
)
1206 *pbuf_type
= CIFS_LARGE_BUFFER
;
1207 } /* else no valid buffer on return - leave as null */
1209 /* Note: On -EAGAIN error only caller can retry on handle based calls
1210 since file handle passed in no longer valid */
1216 CIFSSMBWrite(const int xid
, struct cifsTconInfo
*tcon
,
1217 const int netfid
, const unsigned int count
,
1218 const __u64 offset
, unsigned int *nbytes
, const char *buf
,
1219 const char __user
* ubuf
, const int long_op
)
1222 WRITE_REQ
*pSMB
= NULL
;
1223 WRITE_RSP
*pSMBr
= NULL
;
1224 int bytes_returned
, wct
;
1228 /* cFYI(1,("write at %lld %d bytes",offset,count));*/
1229 if(tcon
->ses
== NULL
)
1230 return -ECONNABORTED
;
1232 if(tcon
->ses
->capabilities
& CAP_LARGE_FILES
)
1237 rc
= smb_init(SMB_COM_WRITE_ANDX
, wct
, tcon
, (void **) &pSMB
,
1241 /* tcon and ses pointer are checked in smb_init */
1242 if (tcon
->ses
->server
== NULL
)
1243 return -ECONNABORTED
;
1245 pSMB
->AndXCommand
= 0xFF; /* none */
1247 pSMB
->OffsetLow
= cpu_to_le32(offset
& 0xFFFFFFFF);
1249 pSMB
->OffsetHigh
= cpu_to_le32(offset
>> 32);
1250 else if((offset
>> 32) > 0) /* can not handle this big offset for old */
1253 pSMB
->Reserved
= 0xFFFFFFFF;
1254 pSMB
->WriteMode
= 0;
1255 pSMB
->Remaining
= 0;
1257 /* Can increase buffer size if buffer is big enough in some cases - ie we
1258 can send more if LARGE_WRITE_X capability returned by the server and if
1259 our buffer is big enough or if we convert to iovecs on socket writes
1260 and eliminate the copy to the CIFS buffer */
1261 if(tcon
->ses
->capabilities
& CAP_LARGE_WRITE_X
) {
1262 bytes_sent
= min_t(const unsigned int, CIFSMaxBufSize
, count
);
1264 bytes_sent
= (tcon
->ses
->server
->maxBuf
- MAX_CIFS_HDR_SIZE
)
1268 if (bytes_sent
> count
)
1271 cpu_to_le16(offsetof(struct smb_com_write_req
,Data
) - 4);
1273 memcpy(pSMB
->Data
,buf
,bytes_sent
);
1275 if(copy_from_user(pSMB
->Data
,ubuf
,bytes_sent
)) {
1276 cifs_buf_release(pSMB
);
1279 } else if (count
!= 0) {
1281 cifs_buf_release(pSMB
);
1283 } /* else setting file size with write of zero bytes */
1285 byte_count
= bytes_sent
+ 1; /* pad */
1286 else /* wct == 12 */ {
1287 byte_count
= bytes_sent
+ 5; /* bigger pad, smaller smb hdr */
1289 pSMB
->DataLengthLow
= cpu_to_le16(bytes_sent
& 0xFFFF);
1290 pSMB
->DataLengthHigh
= cpu_to_le16(bytes_sent
>> 16);
1291 pSMB
->hdr
.smb_buf_length
+= byte_count
;
1294 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
1295 else { /* old style write has byte count 4 bytes earlier so 4 bytes pad */
1296 struct smb_com_writex_req
* pSMBW
=
1297 (struct smb_com_writex_req
*)pSMB
;
1298 pSMBW
->ByteCount
= cpu_to_le16(byte_count
);
1301 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
1302 (struct smb_hdr
*) pSMBr
, &bytes_returned
, long_op
);
1303 cifs_stats_inc(&tcon
->num_writes
);
1305 cFYI(1, ("Send error in write = %d", rc
));
1308 *nbytes
= le16_to_cpu(pSMBr
->CountHigh
);
1309 *nbytes
= (*nbytes
) << 16;
1310 *nbytes
+= le16_to_cpu(pSMBr
->Count
);
1313 cifs_buf_release(pSMB
);
1315 /* Note: On -EAGAIN error only caller can retry on handle based calls
1316 since file handle passed in no longer valid */
1322 CIFSSMBWrite2(const int xid
, struct cifsTconInfo
*tcon
,
1323 const int netfid
, const unsigned int count
,
1324 const __u64 offset
, unsigned int *nbytes
, struct kvec
*iov
,
1325 int n_vec
, const int long_op
)
1328 WRITE_REQ
*pSMB
= NULL
;
1331 int resp_buf_type
= 0;
1333 cFYI(1,("write2 at %lld %d bytes", (long long)offset
, count
));
1335 if(tcon
->ses
->capabilities
& CAP_LARGE_FILES
)
1339 rc
= small_smb_init(SMB_COM_WRITE_ANDX
, wct
, tcon
, (void **) &pSMB
);
1342 /* tcon and ses pointer are checked in smb_init */
1343 if (tcon
->ses
->server
== NULL
)
1344 return -ECONNABORTED
;
1346 pSMB
->AndXCommand
= 0xFF; /* none */
1348 pSMB
->OffsetLow
= cpu_to_le32(offset
& 0xFFFFFFFF);
1350 pSMB
->OffsetHigh
= cpu_to_le32(offset
>> 32);
1351 else if((offset
>> 32) > 0) /* can not handle this big offset for old */
1353 pSMB
->Reserved
= 0xFFFFFFFF;
1354 pSMB
->WriteMode
= 0;
1355 pSMB
->Remaining
= 0;
1358 cpu_to_le16(offsetof(struct smb_com_write_req
,Data
) - 4);
1360 pSMB
->DataLengthLow
= cpu_to_le16(count
& 0xFFFF);
1361 pSMB
->DataLengthHigh
= cpu_to_le16(count
>> 16);
1362 smb_hdr_len
= pSMB
->hdr
.smb_buf_length
+ 1; /* hdr + 1 byte pad */
1364 pSMB
->hdr
.smb_buf_length
+= count
+1;
1365 else /* wct == 12 */
1366 pSMB
->hdr
.smb_buf_length
+= count
+5; /* smb data starts later */
1368 pSMB
->ByteCount
= cpu_to_le16(count
+ 1);
1369 else /* wct == 12 */ /* bigger pad, smaller smb hdr, keep offset ok */ {
1370 struct smb_com_writex_req
* pSMBW
=
1371 (struct smb_com_writex_req
*)pSMB
;
1372 pSMBW
->ByteCount
= cpu_to_le16(count
+ 5);
1374 iov
[0].iov_base
= pSMB
;
1376 iov
[0].iov_len
= smb_hdr_len
+ 4;
1377 else /* wct == 12 pad bigger by four bytes */
1378 iov
[0].iov_len
= smb_hdr_len
+ 8;
1381 rc
= SendReceive2(xid
, tcon
->ses
, iov
, n_vec
+ 1, &resp_buf_type
,
1383 cifs_stats_inc(&tcon
->num_writes
);
1385 cFYI(1, ("Send error Write2 = %d", rc
));
1387 } else if(resp_buf_type
== 0) {
1388 /* presumably this can not happen, but best to be safe */
1392 WRITE_RSP
* pSMBr
= (WRITE_RSP
*)iov
[0].iov_base
;
1393 *nbytes
= le16_to_cpu(pSMBr
->CountHigh
);
1394 *nbytes
= (*nbytes
) << 16;
1395 *nbytes
+= le16_to_cpu(pSMBr
->Count
);
1398 /* cifs_small_buf_release(pSMB); */ /* Freed earlier now in SendReceive2 */
1399 if(resp_buf_type
== CIFS_SMALL_BUFFER
)
1400 cifs_small_buf_release(iov
[0].iov_base
);
1401 else if(resp_buf_type
== CIFS_LARGE_BUFFER
)
1402 cifs_buf_release(iov
[0].iov_base
);
1404 /* Note: On -EAGAIN error only caller can retry on handle based calls
1405 since file handle passed in no longer valid */
1412 CIFSSMBLock(const int xid
, struct cifsTconInfo
*tcon
,
1413 const __u16 smb_file_id
, const __u64 len
,
1414 const __u64 offset
, const __u32 numUnlock
,
1415 const __u32 numLock
, const __u8 lockType
, const int waitFlag
)
1418 LOCK_REQ
*pSMB
= NULL
;
1419 LOCK_RSP
*pSMBr
= NULL
;
1424 cFYI(1, ("In CIFSSMBLock - timeout %d numLock %d",waitFlag
,numLock
));
1425 rc
= small_smb_init(SMB_COM_LOCKING_ANDX
, 8, tcon
, (void **) &pSMB
);
1430 pSMBr
= (LOCK_RSP
*)pSMB
; /* BB removeme BB */
1432 if(lockType
== LOCKING_ANDX_OPLOCK_RELEASE
) {
1433 timeout
= -1; /* no response expected */
1435 } else if (waitFlag
== TRUE
) {
1436 timeout
= 3; /* blocking operation, no timeout */
1437 pSMB
->Timeout
= cpu_to_le32(-1);/* blocking - do not time out */
1442 pSMB
->NumberOfLocks
= cpu_to_le16(numLock
);
1443 pSMB
->NumberOfUnlocks
= cpu_to_le16(numUnlock
);
1444 pSMB
->LockType
= lockType
;
1445 pSMB
->AndXCommand
= 0xFF; /* none */
1446 pSMB
->Fid
= smb_file_id
; /* netfid stays le */
1448 if((numLock
!= 0) || (numUnlock
!= 0)) {
1449 pSMB
->Locks
[0].Pid
= cpu_to_le16(current
->tgid
);
1450 /* BB where to store pid high? */
1451 pSMB
->Locks
[0].LengthLow
= cpu_to_le32((u32
)len
);
1452 pSMB
->Locks
[0].LengthHigh
= cpu_to_le32((u32
)(len
>>32));
1453 pSMB
->Locks
[0].OffsetLow
= cpu_to_le32((u32
)offset
);
1454 pSMB
->Locks
[0].OffsetHigh
= cpu_to_le32((u32
)(offset
>>32));
1455 count
= sizeof(LOCKING_ANDX_RANGE
);
1460 pSMB
->hdr
.smb_buf_length
+= count
;
1461 pSMB
->ByteCount
= cpu_to_le16(count
);
1463 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
1464 (struct smb_hdr
*) pSMBr
, &bytes_returned
, timeout
);
1465 cifs_stats_inc(&tcon
->num_locks
);
1467 cFYI(1, ("Send error in Lock = %d", rc
));
1469 cifs_small_buf_release(pSMB
);
1471 /* Note: On -EAGAIN error only caller can retry on handle based calls
1472 since file handle passed in no longer valid */
1477 CIFSSMBPosixLock(const int xid
, struct cifsTconInfo
*tcon
,
1478 const __u16 smb_file_id
, const int get_flag
, const __u64 len
,
1479 struct file_lock
*pLockData
, const __u16 lock_type
,
1482 struct smb_com_transaction2_sfi_req
*pSMB
= NULL
;
1483 struct smb_com_transaction2_sfi_rsp
*pSMBr
= NULL
;
1485 struct cifs_posix_lock
*parm_data
;
1487 int bytes_returned
= 0;
1488 __u16 params
, param_offset
, offset
, byte_count
, count
;
1490 cFYI(1, ("Posix Lock"));
1492 if(pLockData
== NULL
)
1495 rc
= small_smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
);
1500 pSMBr
= (struct smb_com_transaction2_sfi_rsp
*)pSMB
;
1503 pSMB
->MaxSetupCount
= 0;
1507 pSMB
->Reserved2
= 0;
1508 param_offset
= offsetof(struct smb_com_transaction2_sfi_req
, Fid
) - 4;
1509 offset
= param_offset
+ params
;
1511 data_offset
= (char *) (&pSMB
->hdr
.Protocol
) + offset
;
1513 count
= sizeof(struct cifs_posix_lock
);
1514 pSMB
->MaxParameterCount
= cpu_to_le16(2);
1515 pSMB
->MaxDataCount
= cpu_to_le16(1000); /* BB find max SMB PDU from sess */
1516 pSMB
->SetupCount
= 1;
1517 pSMB
->Reserved3
= 0;
1519 pSMB
->SubCommand
= cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION
);
1521 pSMB
->SubCommand
= cpu_to_le16(TRANS2_SET_FILE_INFORMATION
);
1522 byte_count
= 3 /* pad */ + params
+ count
;
1523 pSMB
->DataCount
= cpu_to_le16(count
);
1524 pSMB
->ParameterCount
= cpu_to_le16(params
);
1525 pSMB
->TotalDataCount
= pSMB
->DataCount
;
1526 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
1527 pSMB
->ParameterOffset
= cpu_to_le16(param_offset
);
1528 parm_data
= (struct cifs_posix_lock
*)
1529 (((char *) &pSMB
->hdr
.Protocol
) + offset
);
1531 parm_data
->lock_type
= cpu_to_le16(lock_type
);
1533 parm_data
->lock_flags
= cpu_to_le16(1);
1534 parm_data
->pid
= cpu_to_le32(current
->tgid
);
1535 parm_data
->start
= cpu_to_le64(pLockData
->fl_start
);
1536 parm_data
->length
= cpu_to_le64(len
); /* normalize negative numbers */
1538 pSMB
->DataOffset
= cpu_to_le16(offset
);
1539 pSMB
->Fid
= smb_file_id
;
1540 pSMB
->InformationLevel
= cpu_to_le16(SMB_SET_POSIX_LOCK
);
1541 pSMB
->Reserved4
= 0;
1542 pSMB
->hdr
.smb_buf_length
+= byte_count
;
1543 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
1544 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
1545 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
1547 cFYI(1, ("Send error in Posix Lock = %d", rc
));
1548 } else if (get_flag
) {
1549 /* lock structure can be returned on get */
1552 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
1554 if (rc
|| (pSMBr
->ByteCount
< sizeof(struct cifs_posix_lock
))) {
1555 rc
= -EIO
; /* bad smb */
1558 if(pLockData
== NULL
) {
1562 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
1563 data_count
= le16_to_cpu(pSMBr
->t2
.DataCount
);
1564 if(data_count
< sizeof(struct cifs_posix_lock
)) {
1568 parm_data
= (struct cifs_posix_lock
*)
1569 ((char *)&pSMBr
->hdr
.Protocol
+ data_offset
);
1570 if(parm_data
->lock_type
== cpu_to_le16(CIFS_UNLCK
))
1571 pLockData
->fl_type
= F_UNLCK
;
1576 cifs_small_buf_release(pSMB
);
1578 /* Note: On -EAGAIN error only caller can retry on handle based calls
1579 since file handle passed in no longer valid */
1586 CIFSSMBClose(const int xid
, struct cifsTconInfo
*tcon
, int smb_file_id
)
1589 CLOSE_REQ
*pSMB
= NULL
;
1590 CLOSE_RSP
*pSMBr
= NULL
;
1592 cFYI(1, ("In CIFSSMBClose"));
1594 /* do not retry on dead session on close */
1595 rc
= small_smb_init(SMB_COM_CLOSE
, 3, tcon
, (void **) &pSMB
);
1601 pSMBr
= (CLOSE_RSP
*)pSMB
; /* BB removeme BB */
1603 pSMB
->FileID
= (__u16
) smb_file_id
;
1604 pSMB
->LastWriteTime
= 0;
1605 pSMB
->ByteCount
= 0;
1606 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
1607 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
1608 cifs_stats_inc(&tcon
->num_closes
);
1611 /* EINTR is expected when user ctl-c to kill app */
1612 cERROR(1, ("Send error in Close = %d", rc
));
1616 cifs_small_buf_release(pSMB
);
1618 /* Since session is dead, file will be closed on server already */
1626 CIFSSMBRename(const int xid
, struct cifsTconInfo
*tcon
,
1627 const char *fromName
, const char *toName
,
1628 const struct nls_table
*nls_codepage
, int remap
)
1631 RENAME_REQ
*pSMB
= NULL
;
1632 RENAME_RSP
*pSMBr
= NULL
;
1634 int name_len
, name_len2
;
1637 cFYI(1, ("In CIFSSMBRename"));
1639 rc
= smb_init(SMB_COM_RENAME
, 1, tcon
, (void **) &pSMB
,
1644 pSMB
->BufferFormat
= 0x04;
1645 pSMB
->SearchAttributes
=
1646 cpu_to_le16(ATTR_READONLY
| ATTR_HIDDEN
| ATTR_SYSTEM
|
1649 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
1651 cifsConvertToUCS((__le16
*) pSMB
->OldFileName
, fromName
,
1652 PATH_MAX
, nls_codepage
, remap
);
1653 name_len
++; /* trailing null */
1655 pSMB
->OldFileName
[name_len
] = 0x04; /* pad */
1656 /* protocol requires ASCII signature byte on Unicode string */
1657 pSMB
->OldFileName
[name_len
+ 1] = 0x00;
1659 cifsConvertToUCS((__le16
*) &pSMB
->OldFileName
[name_len
+ 2],
1660 toName
, PATH_MAX
, nls_codepage
, remap
);
1661 name_len2
+= 1 /* trailing null */ + 1 /* Signature word */ ;
1662 name_len2
*= 2; /* convert to bytes */
1663 } else { /* BB improve the check for buffer overruns BB */
1664 name_len
= strnlen(fromName
, PATH_MAX
);
1665 name_len
++; /* trailing null */
1666 strncpy(pSMB
->OldFileName
, fromName
, name_len
);
1667 name_len2
= strnlen(toName
, PATH_MAX
);
1668 name_len2
++; /* trailing null */
1669 pSMB
->OldFileName
[name_len
] = 0x04; /* 2nd buffer format */
1670 strncpy(&pSMB
->OldFileName
[name_len
+ 1], toName
, name_len2
);
1671 name_len2
++; /* trailing null */
1672 name_len2
++; /* signature byte */
1675 count
= 1 /* 1st signature byte */ + name_len
+ name_len2
;
1676 pSMB
->hdr
.smb_buf_length
+= count
;
1677 pSMB
->ByteCount
= cpu_to_le16(count
);
1679 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
1680 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
1681 cifs_stats_inc(&tcon
->num_renames
);
1683 cFYI(1, ("Send error in rename = %d", rc
));
1686 cifs_buf_release(pSMB
);
1694 int CIFSSMBRenameOpenFile(const int xid
,struct cifsTconInfo
*pTcon
,
1695 int netfid
, char * target_name
,
1696 const struct nls_table
* nls_codepage
, int remap
)
1698 struct smb_com_transaction2_sfi_req
*pSMB
= NULL
;
1699 struct smb_com_transaction2_sfi_rsp
*pSMBr
= NULL
;
1700 struct set_file_rename
* rename_info
;
1702 char dummy_string
[30];
1704 int bytes_returned
= 0;
1706 __u16 params
, param_offset
, offset
, count
, byte_count
;
1708 cFYI(1, ("Rename to File by handle"));
1709 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, pTcon
, (void **) &pSMB
,
1715 pSMB
->MaxSetupCount
= 0;
1719 pSMB
->Reserved2
= 0;
1720 param_offset
= offsetof(struct smb_com_transaction2_sfi_req
, Fid
) - 4;
1721 offset
= param_offset
+ params
;
1723 data_offset
= (char *) (&pSMB
->hdr
.Protocol
) + offset
;
1724 rename_info
= (struct set_file_rename
*) data_offset
;
1725 pSMB
->MaxParameterCount
= cpu_to_le16(2);
1726 pSMB
->MaxDataCount
= cpu_to_le16(1000); /* BB find max SMB PDU from sess */
1727 pSMB
->SetupCount
= 1;
1728 pSMB
->Reserved3
= 0;
1729 pSMB
->SubCommand
= cpu_to_le16(TRANS2_SET_FILE_INFORMATION
);
1730 byte_count
= 3 /* pad */ + params
;
1731 pSMB
->ParameterCount
= cpu_to_le16(params
);
1732 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
1733 pSMB
->ParameterOffset
= cpu_to_le16(param_offset
);
1734 pSMB
->DataOffset
= cpu_to_le16(offset
);
1735 /* construct random name ".cifs_tmp<inodenum><mid>" */
1736 rename_info
->overwrite
= cpu_to_le32(1);
1737 rename_info
->root_fid
= 0;
1738 /* unicode only call */
1739 if(target_name
== NULL
) {
1740 sprintf(dummy_string
,"cifs%x",pSMB
->hdr
.Mid
);
1741 len_of_str
= cifsConvertToUCS((__le16
*)rename_info
->target_name
,
1742 dummy_string
, 24, nls_codepage
, remap
);
1744 len_of_str
= cifsConvertToUCS((__le16
*)rename_info
->target_name
,
1745 target_name
, PATH_MAX
, nls_codepage
, remap
);
1747 rename_info
->target_name_len
= cpu_to_le32(2 * len_of_str
);
1748 count
= 12 /* sizeof(struct set_file_rename) */ + (2 * len_of_str
) + 2;
1749 byte_count
+= count
;
1750 pSMB
->DataCount
= cpu_to_le16(count
);
1751 pSMB
->TotalDataCount
= pSMB
->DataCount
;
1753 pSMB
->InformationLevel
=
1754 cpu_to_le16(SMB_SET_FILE_RENAME_INFORMATION
);
1755 pSMB
->Reserved4
= 0;
1756 pSMB
->hdr
.smb_buf_length
+= byte_count
;
1757 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
1758 rc
= SendReceive(xid
, pTcon
->ses
, (struct smb_hdr
*) pSMB
,
1759 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
1760 cifs_stats_inc(&pTcon
->num_t2renames
);
1762 cFYI(1,("Send error in Rename (by file handle) = %d", rc
));
1765 cifs_buf_release(pSMB
);
1767 /* Note: On -EAGAIN error only caller can retry on handle based calls
1768 since file handle passed in no longer valid */
1774 CIFSSMBCopy(const int xid
, struct cifsTconInfo
*tcon
, const char * fromName
,
1775 const __u16 target_tid
, const char *toName
, const int flags
,
1776 const struct nls_table
*nls_codepage
, int remap
)
1779 COPY_REQ
*pSMB
= NULL
;
1780 COPY_RSP
*pSMBr
= NULL
;
1782 int name_len
, name_len2
;
1785 cFYI(1, ("In CIFSSMBCopy"));
1787 rc
= smb_init(SMB_COM_COPY
, 1, tcon
, (void **) &pSMB
,
1792 pSMB
->BufferFormat
= 0x04;
1793 pSMB
->Tid2
= target_tid
;
1795 pSMB
->Flags
= cpu_to_le16(flags
& COPY_TREE
);
1797 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
1798 name_len
= cifsConvertToUCS((__le16
*) pSMB
->OldFileName
,
1799 fromName
, PATH_MAX
, nls_codepage
,
1801 name_len
++; /* trailing null */
1803 pSMB
->OldFileName
[name_len
] = 0x04; /* pad */
1804 /* protocol requires ASCII signature byte on Unicode string */
1805 pSMB
->OldFileName
[name_len
+ 1] = 0x00;
1806 name_len2
= cifsConvertToUCS((__le16
*)&pSMB
->OldFileName
[name_len
+ 2],
1807 toName
, PATH_MAX
, nls_codepage
, remap
);
1808 name_len2
+= 1 /* trailing null */ + 1 /* Signature word */ ;
1809 name_len2
*= 2; /* convert to bytes */
1810 } else { /* BB improve the check for buffer overruns BB */
1811 name_len
= strnlen(fromName
, PATH_MAX
);
1812 name_len
++; /* trailing null */
1813 strncpy(pSMB
->OldFileName
, fromName
, name_len
);
1814 name_len2
= strnlen(toName
, PATH_MAX
);
1815 name_len2
++; /* trailing null */
1816 pSMB
->OldFileName
[name_len
] = 0x04; /* 2nd buffer format */
1817 strncpy(&pSMB
->OldFileName
[name_len
+ 1], toName
, name_len2
);
1818 name_len2
++; /* trailing null */
1819 name_len2
++; /* signature byte */
1822 count
= 1 /* 1st signature byte */ + name_len
+ name_len2
;
1823 pSMB
->hdr
.smb_buf_length
+= count
;
1824 pSMB
->ByteCount
= cpu_to_le16(count
);
1826 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
1827 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
1829 cFYI(1, ("Send error in copy = %d with %d files copied",
1830 rc
, le16_to_cpu(pSMBr
->CopyCount
)));
1833 cifs_buf_release(pSMB
);
1842 CIFSUnixCreateSymLink(const int xid
, struct cifsTconInfo
*tcon
,
1843 const char *fromName
, const char *toName
,
1844 const struct nls_table
*nls_codepage
)
1846 TRANSACTION2_SPI_REQ
*pSMB
= NULL
;
1847 TRANSACTION2_SPI_RSP
*pSMBr
= NULL
;
1850 int name_len_target
;
1852 int bytes_returned
= 0;
1853 __u16 params
, param_offset
, offset
, byte_count
;
1855 cFYI(1, ("In Symlink Unix style"));
1857 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
1862 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
1864 cifs_strtoUCS((__le16
*) pSMB
->FileName
, fromName
, PATH_MAX
1865 /* find define for this maxpathcomponent */
1867 name_len
++; /* trailing null */
1870 } else { /* BB improve the check for buffer overruns BB */
1871 name_len
= strnlen(fromName
, PATH_MAX
);
1872 name_len
++; /* trailing null */
1873 strncpy(pSMB
->FileName
, fromName
, name_len
);
1875 params
= 6 + name_len
;
1876 pSMB
->MaxSetupCount
= 0;
1880 pSMB
->Reserved2
= 0;
1881 param_offset
= offsetof(struct smb_com_transaction2_spi_req
,
1882 InformationLevel
) - 4;
1883 offset
= param_offset
+ params
;
1885 data_offset
= (char *) (&pSMB
->hdr
.Protocol
) + offset
;
1886 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
1888 cifs_strtoUCS((__le16
*) data_offset
, toName
, PATH_MAX
1889 /* find define for this maxpathcomponent */
1891 name_len_target
++; /* trailing null */
1892 name_len_target
*= 2;
1893 } else { /* BB improve the check for buffer overruns BB */
1894 name_len_target
= strnlen(toName
, PATH_MAX
);
1895 name_len_target
++; /* trailing null */
1896 strncpy(data_offset
, toName
, name_len_target
);
1899 pSMB
->MaxParameterCount
= cpu_to_le16(2);
1900 /* BB find exact max on data count below from sess */
1901 pSMB
->MaxDataCount
= cpu_to_le16(1000);
1902 pSMB
->SetupCount
= 1;
1903 pSMB
->Reserved3
= 0;
1904 pSMB
->SubCommand
= cpu_to_le16(TRANS2_SET_PATH_INFORMATION
);
1905 byte_count
= 3 /* pad */ + params
+ name_len_target
;
1906 pSMB
->DataCount
= cpu_to_le16(name_len_target
);
1907 pSMB
->ParameterCount
= cpu_to_le16(params
);
1908 pSMB
->TotalDataCount
= pSMB
->DataCount
;
1909 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
1910 pSMB
->ParameterOffset
= cpu_to_le16(param_offset
);
1911 pSMB
->DataOffset
= cpu_to_le16(offset
);
1912 pSMB
->InformationLevel
= cpu_to_le16(SMB_SET_FILE_UNIX_LINK
);
1913 pSMB
->Reserved4
= 0;
1914 pSMB
->hdr
.smb_buf_length
+= byte_count
;
1915 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
1916 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
1917 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
1918 cifs_stats_inc(&tcon
->num_symlinks
);
1921 ("Send error in SetPathInfo (create symlink) = %d",
1926 cifs_buf_release(pSMB
);
1929 goto createSymLinkRetry
;
1935 CIFSUnixCreateHardLink(const int xid
, struct cifsTconInfo
*tcon
,
1936 const char *fromName
, const char *toName
,
1937 const struct nls_table
*nls_codepage
, int remap
)
1939 TRANSACTION2_SPI_REQ
*pSMB
= NULL
;
1940 TRANSACTION2_SPI_RSP
*pSMBr
= NULL
;
1943 int name_len_target
;
1945 int bytes_returned
= 0;
1946 __u16 params
, param_offset
, offset
, byte_count
;
1948 cFYI(1, ("In Create Hard link Unix style"));
1949 createHardLinkRetry
:
1950 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
1955 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
1956 name_len
= cifsConvertToUCS((__le16
*) pSMB
->FileName
, toName
,
1957 PATH_MAX
, nls_codepage
, remap
);
1958 name_len
++; /* trailing null */
1961 } else { /* BB improve the check for buffer overruns BB */
1962 name_len
= strnlen(toName
, PATH_MAX
);
1963 name_len
++; /* trailing null */
1964 strncpy(pSMB
->FileName
, toName
, name_len
);
1966 params
= 6 + name_len
;
1967 pSMB
->MaxSetupCount
= 0;
1971 pSMB
->Reserved2
= 0;
1972 param_offset
= offsetof(struct smb_com_transaction2_spi_req
,
1973 InformationLevel
) - 4;
1974 offset
= param_offset
+ params
;
1976 data_offset
= (char *) (&pSMB
->hdr
.Protocol
) + offset
;
1977 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
1979 cifsConvertToUCS((__le16
*) data_offset
, fromName
, PATH_MAX
,
1980 nls_codepage
, remap
);
1981 name_len_target
++; /* trailing null */
1982 name_len_target
*= 2;
1983 } else { /* BB improve the check for buffer overruns BB */
1984 name_len_target
= strnlen(fromName
, PATH_MAX
);
1985 name_len_target
++; /* trailing null */
1986 strncpy(data_offset
, fromName
, name_len_target
);
1989 pSMB
->MaxParameterCount
= cpu_to_le16(2);
1990 /* BB find exact max on data count below from sess*/
1991 pSMB
->MaxDataCount
= cpu_to_le16(1000);
1992 pSMB
->SetupCount
= 1;
1993 pSMB
->Reserved3
= 0;
1994 pSMB
->SubCommand
= cpu_to_le16(TRANS2_SET_PATH_INFORMATION
);
1995 byte_count
= 3 /* pad */ + params
+ name_len_target
;
1996 pSMB
->ParameterCount
= cpu_to_le16(params
);
1997 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
1998 pSMB
->DataCount
= cpu_to_le16(name_len_target
);
1999 pSMB
->TotalDataCount
= pSMB
->DataCount
;
2000 pSMB
->ParameterOffset
= cpu_to_le16(param_offset
);
2001 pSMB
->DataOffset
= cpu_to_le16(offset
);
2002 pSMB
->InformationLevel
= cpu_to_le16(SMB_SET_FILE_UNIX_HLINK
);
2003 pSMB
->Reserved4
= 0;
2004 pSMB
->hdr
.smb_buf_length
+= byte_count
;
2005 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
2006 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
2007 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
2008 cifs_stats_inc(&tcon
->num_hardlinks
);
2010 cFYI(1, ("Send error in SetPathInfo (hard link) = %d", rc
));
2013 cifs_buf_release(pSMB
);
2015 goto createHardLinkRetry
;
2021 CIFSCreateHardLink(const int xid
, struct cifsTconInfo
*tcon
,
2022 const char *fromName
, const char *toName
,
2023 const struct nls_table
*nls_codepage
, int remap
)
2026 NT_RENAME_REQ
*pSMB
= NULL
;
2027 RENAME_RSP
*pSMBr
= NULL
;
2029 int name_len
, name_len2
;
2032 cFYI(1, ("In CIFSCreateHardLink"));
2033 winCreateHardLinkRetry
:
2035 rc
= smb_init(SMB_COM_NT_RENAME
, 4, tcon
, (void **) &pSMB
,
2040 pSMB
->SearchAttributes
=
2041 cpu_to_le16(ATTR_READONLY
| ATTR_HIDDEN
| ATTR_SYSTEM
|
2043 pSMB
->Flags
= cpu_to_le16(CREATE_HARD_LINK
);
2044 pSMB
->ClusterCount
= 0;
2046 pSMB
->BufferFormat
= 0x04;
2048 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
2050 cifsConvertToUCS((__le16
*) pSMB
->OldFileName
, fromName
,
2051 PATH_MAX
, nls_codepage
, remap
);
2052 name_len
++; /* trailing null */
2054 pSMB
->OldFileName
[name_len
] = 0; /* pad */
2055 pSMB
->OldFileName
[name_len
+ 1] = 0x04;
2057 cifsConvertToUCS((__le16
*)&pSMB
->OldFileName
[name_len
+ 2],
2058 toName
, PATH_MAX
, nls_codepage
, remap
);
2059 name_len2
+= 1 /* trailing null */ + 1 /* Signature word */ ;
2060 name_len2
*= 2; /* convert to bytes */
2061 } else { /* BB improve the check for buffer overruns BB */
2062 name_len
= strnlen(fromName
, PATH_MAX
);
2063 name_len
++; /* trailing null */
2064 strncpy(pSMB
->OldFileName
, fromName
, name_len
);
2065 name_len2
= strnlen(toName
, PATH_MAX
);
2066 name_len2
++; /* trailing null */
2067 pSMB
->OldFileName
[name_len
] = 0x04; /* 2nd buffer format */
2068 strncpy(&pSMB
->OldFileName
[name_len
+ 1], toName
, name_len2
);
2069 name_len2
++; /* trailing null */
2070 name_len2
++; /* signature byte */
2073 count
= 1 /* string type byte */ + name_len
+ name_len2
;
2074 pSMB
->hdr
.smb_buf_length
+= count
;
2075 pSMB
->ByteCount
= cpu_to_le16(count
);
2077 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
2078 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
2079 cifs_stats_inc(&tcon
->num_hardlinks
);
2081 cFYI(1, ("Send error in hard link (NT rename) = %d", rc
));
2083 cifs_buf_release(pSMB
);
2085 goto winCreateHardLinkRetry
;
2091 CIFSSMBUnixQuerySymLink(const int xid
, struct cifsTconInfo
*tcon
,
2092 const unsigned char *searchName
,
2093 char *symlinkinfo
, const int buflen
,
2094 const struct nls_table
*nls_codepage
)
2096 /* SMB_QUERY_FILE_UNIX_LINK */
2097 TRANSACTION2_QPI_REQ
*pSMB
= NULL
;
2098 TRANSACTION2_QPI_RSP
*pSMBr
= NULL
;
2102 __u16 params
, byte_count
;
2104 cFYI(1, ("In QPathSymLinkInfo (Unix) for path %s", searchName
));
2107 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
2112 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
2114 cifs_strtoUCS((__le16
*) pSMB
->FileName
, searchName
, PATH_MAX
2115 /* find define for this maxpathcomponent */
2117 name_len
++; /* trailing null */
2119 } else { /* BB improve the check for buffer overruns BB */
2120 name_len
= strnlen(searchName
, PATH_MAX
);
2121 name_len
++; /* trailing null */
2122 strncpy(pSMB
->FileName
, searchName
, name_len
);
2125 params
= 2 /* level */ + 4 /* rsrvd */ + name_len
/* incl null */ ;
2126 pSMB
->TotalDataCount
= 0;
2127 pSMB
->MaxParameterCount
= cpu_to_le16(2);
2128 /* BB find exact max data count below from sess structure BB */
2129 pSMB
->MaxDataCount
= cpu_to_le16(4000);
2130 pSMB
->MaxSetupCount
= 0;
2134 pSMB
->Reserved2
= 0;
2135 pSMB
->ParameterOffset
= cpu_to_le16(offsetof(
2136 struct smb_com_transaction2_qpi_req
,InformationLevel
) - 4);
2137 pSMB
->DataCount
= 0;
2138 pSMB
->DataOffset
= 0;
2139 pSMB
->SetupCount
= 1;
2140 pSMB
->Reserved3
= 0;
2141 pSMB
->SubCommand
= cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION
);
2142 byte_count
= params
+ 1 /* pad */ ;
2143 pSMB
->TotalParameterCount
= cpu_to_le16(params
);
2144 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
2145 pSMB
->InformationLevel
= cpu_to_le16(SMB_QUERY_FILE_UNIX_LINK
);
2146 pSMB
->Reserved4
= 0;
2147 pSMB
->hdr
.smb_buf_length
+= byte_count
;
2148 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
2150 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
2151 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
2153 cFYI(1, ("Send error in QuerySymLinkInfo = %d", rc
));
2155 /* decode response */
2157 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
2158 if (rc
|| (pSMBr
->ByteCount
< 2))
2159 /* BB also check enough total bytes returned */
2160 rc
= -EIO
; /* bad smb */
2162 __u16 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
2163 __u16 count
= le16_to_cpu(pSMBr
->t2
.DataCount
);
2165 if (pSMBr
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
2166 name_len
= UniStrnlen((wchar_t *) ((char *)
2167 &pSMBr
->hdr
.Protocol
+data_offset
),
2168 min_t(const int, buflen
,count
) / 2);
2169 /* BB FIXME investigate remapping reserved chars here */
2170 cifs_strfromUCS_le(symlinkinfo
,
2171 (__le16
*) ((char *)&pSMBr
->hdr
.Protocol
+
2173 name_len
, nls_codepage
);
2175 strncpy(symlinkinfo
,
2176 (char *) &pSMBr
->hdr
.Protocol
+
2178 min_t(const int, buflen
, count
));
2180 symlinkinfo
[buflen
] = 0;
2181 /* just in case so calling code does not go off the end of buffer */
2184 cifs_buf_release(pSMB
);
2186 goto querySymLinkRetry
;
2190 /* Initialize NT TRANSACT SMB into small smb request buffer.
2191 This assumes that all NT TRANSACTS that we init here have
2192 total parm and data under about 400 bytes (to fit in small cifs
2193 buffer size), which is the case so far, it easily fits. NB:
2194 Setup words themselves and ByteCount
2195 MaxSetupCount (size of returned setup area) and
2196 MaxParameterCount (returned parms size) must be set by caller */
2198 smb_init_ntransact(const __u16 sub_command
, const int setup_count
,
2199 const int parm_len
, struct cifsTconInfo
*tcon
,
2204 struct smb_com_ntransact_req
* pSMB
;
2206 rc
= small_smb_init(SMB_COM_NT_TRANSACT
, 19 + setup_count
, tcon
,
2210 *ret_buf
= (void *)pSMB
;
2212 pSMB
->TotalParameterCount
= cpu_to_le32(parm_len
);
2213 pSMB
->TotalDataCount
= 0;
2214 pSMB
->MaxDataCount
= cpu_to_le32((tcon
->ses
->server
->maxBuf
-
2215 MAX_CIFS_HDR_SIZE
) & 0xFFFFFF00);
2216 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
2217 pSMB
->DataCount
= pSMB
->TotalDataCount
;
2218 temp_offset
= offsetof(struct smb_com_ntransact_req
, Parms
) +
2219 (setup_count
* 2) - 4 /* for rfc1001 length itself */;
2220 pSMB
->ParameterOffset
= cpu_to_le32(temp_offset
);
2221 pSMB
->DataOffset
= cpu_to_le32(temp_offset
+ parm_len
);
2222 pSMB
->SetupCount
= setup_count
; /* no need to le convert byte fields */
2223 pSMB
->SubCommand
= cpu_to_le16(sub_command
);
2228 validate_ntransact(char * buf
, char ** ppparm
, char ** ppdata
,
2229 int * pdatalen
, int * pparmlen
)
2232 __u32 data_count
, data_offset
, parm_count
, parm_offset
;
2233 struct smb_com_ntransact_rsp
* pSMBr
;
2238 pSMBr
= (struct smb_com_ntransact_rsp
*)buf
;
2240 /* ByteCount was converted from little endian in SendReceive */
2241 end_of_smb
= 2 /* sizeof byte count */ + pSMBr
->ByteCount
+
2242 (char *)&pSMBr
->ByteCount
;
2245 data_offset
= le32_to_cpu(pSMBr
->DataOffset
);
2246 data_count
= le32_to_cpu(pSMBr
->DataCount
);
2247 parm_offset
= le32_to_cpu(pSMBr
->ParameterOffset
);
2248 parm_count
= le32_to_cpu(pSMBr
->ParameterCount
);
2250 *ppparm
= (char *)&pSMBr
->hdr
.Protocol
+ parm_offset
;
2251 *ppdata
= (char *)&pSMBr
->hdr
.Protocol
+ data_offset
;
2253 /* should we also check that parm and data areas do not overlap? */
2254 if(*ppparm
> end_of_smb
) {
2255 cFYI(1,("parms start after end of smb"));
2257 } else if(parm_count
+ *ppparm
> end_of_smb
) {
2258 cFYI(1,("parm end after end of smb"));
2260 } else if(*ppdata
> end_of_smb
) {
2261 cFYI(1,("data starts after end of smb"));
2263 } else if(data_count
+ *ppdata
> end_of_smb
) {
2264 cFYI(1,("data %p + count %d (%p) ends after end of smb %p start %p",
2265 *ppdata
, data_count
, (data_count
+ *ppdata
), end_of_smb
, pSMBr
)); /* BB FIXME */
2267 } else if(parm_count
+ data_count
> pSMBr
->ByteCount
) {
2268 cFYI(1,("parm count and data count larger than SMB"));
2275 CIFSSMBQueryReparseLinkInfo(const int xid
, struct cifsTconInfo
*tcon
,
2276 const unsigned char *searchName
,
2277 char *symlinkinfo
, const int buflen
,__u16 fid
,
2278 const struct nls_table
*nls_codepage
)
2283 struct smb_com_transaction_ioctl_req
* pSMB
;
2284 struct smb_com_transaction_ioctl_rsp
* pSMBr
;
2286 cFYI(1, ("In Windows reparse style QueryLink for path %s", searchName
));
2287 rc
= smb_init(SMB_COM_NT_TRANSACT
, 23, tcon
, (void **) &pSMB
,
2292 pSMB
->TotalParameterCount
= 0 ;
2293 pSMB
->TotalDataCount
= 0;
2294 pSMB
->MaxParameterCount
= cpu_to_le32(2);
2295 /* BB find exact data count max from sess structure BB */
2296 pSMB
->MaxDataCount
= cpu_to_le32((tcon
->ses
->server
->maxBuf
-
2297 MAX_CIFS_HDR_SIZE
) & 0xFFFFFF00);
2298 pSMB
->MaxSetupCount
= 4;
2300 pSMB
->ParameterOffset
= 0;
2301 pSMB
->DataCount
= 0;
2302 pSMB
->DataOffset
= 0;
2303 pSMB
->SetupCount
= 4;
2304 pSMB
->SubCommand
= cpu_to_le16(NT_TRANSACT_IOCTL
);
2305 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
2306 pSMB
->FunctionCode
= cpu_to_le32(FSCTL_GET_REPARSE_POINT
);
2307 pSMB
->IsFsctl
= 1; /* FSCTL */
2308 pSMB
->IsRootFlag
= 0;
2309 pSMB
->Fid
= fid
; /* file handle always le */
2310 pSMB
->ByteCount
= 0;
2312 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
2313 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
2315 cFYI(1, ("Send error in QueryReparseLinkInfo = %d", rc
));
2316 } else { /* decode response */
2317 __u32 data_offset
= le32_to_cpu(pSMBr
->DataOffset
);
2318 __u32 data_count
= le32_to_cpu(pSMBr
->DataCount
);
2319 if ((pSMBr
->ByteCount
< 2) || (data_offset
> 512))
2320 /* BB also check enough total bytes returned */
2321 rc
= -EIO
; /* bad smb */
2323 if(data_count
&& (data_count
< 2048)) {
2324 char * end_of_smb
= 2 /* sizeof byte count */ +
2326 (char *)&pSMBr
->ByteCount
;
2328 struct reparse_data
* reparse_buf
= (struct reparse_data
*)
2329 ((char *)&pSMBr
->hdr
.Protocol
+ data_offset
);
2330 if((char*)reparse_buf
>= end_of_smb
) {
2334 if((reparse_buf
->LinkNamesBuf
+
2335 reparse_buf
->TargetNameOffset
+
2336 reparse_buf
->TargetNameLen
) >
2338 cFYI(1,("reparse buf extended beyond SMB"));
2343 if (pSMBr
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
2344 name_len
= UniStrnlen((wchar_t *)
2345 (reparse_buf
->LinkNamesBuf
+
2346 reparse_buf
->TargetNameOffset
),
2347 min(buflen
/2, reparse_buf
->TargetNameLen
/ 2));
2348 cifs_strfromUCS_le(symlinkinfo
,
2349 (__le16
*) (reparse_buf
->LinkNamesBuf
+
2350 reparse_buf
->TargetNameOffset
),
2351 name_len
, nls_codepage
);
2352 } else { /* ASCII names */
2353 strncpy(symlinkinfo
,reparse_buf
->LinkNamesBuf
+
2354 reparse_buf
->TargetNameOffset
,
2355 min_t(const int, buflen
, reparse_buf
->TargetNameLen
));
2359 cFYI(1,("Invalid return data count on get reparse info ioctl"));
2361 symlinkinfo
[buflen
] = 0; /* just in case so the caller
2362 does not go off the end of the buffer */
2363 cFYI(1,("readlink result - %s",symlinkinfo
));
2367 cifs_buf_release(pSMB
);
2369 /* Note: On -EAGAIN error only caller can retry on handle based calls
2370 since file handle passed in no longer valid */
2375 #ifdef CONFIG_CIFS_POSIX
2377 /*Convert an Access Control Entry from wire format to local POSIX xattr format*/
2378 static void cifs_convert_ace(posix_acl_xattr_entry
* ace
, struct cifs_posix_ace
* cifs_ace
)
2380 /* u8 cifs fields do not need le conversion */
2381 ace
->e_perm
= cpu_to_le16(cifs_ace
->cifs_e_perm
);
2382 ace
->e_tag
= cpu_to_le16(cifs_ace
->cifs_e_tag
);
2383 ace
->e_id
= cpu_to_le32(le64_to_cpu(cifs_ace
->cifs_uid
));
2384 /* cFYI(1,("perm %d tag %d id %d",ace->e_perm,ace->e_tag,ace->e_id)); */
2389 /* Convert ACL from CIFS POSIX wire format to local Linux POSIX ACL xattr */
2390 static int cifs_copy_posix_acl(char * trgt
,char * src
, const int buflen
,
2391 const int acl_type
,const int size_of_data_area
)
2396 struct cifs_posix_ace
* pACE
;
2397 struct cifs_posix_acl
* cifs_acl
= (struct cifs_posix_acl
*)src
;
2398 posix_acl_xattr_header
* local_acl
= (posix_acl_xattr_header
*)trgt
;
2400 if (le16_to_cpu(cifs_acl
->version
) != CIFS_ACL_VERSION
)
2403 if(acl_type
& ACL_TYPE_ACCESS
) {
2404 count
= le16_to_cpu(cifs_acl
->access_entry_count
);
2405 pACE
= &cifs_acl
->ace_array
[0];
2406 size
= sizeof(struct cifs_posix_acl
);
2407 size
+= sizeof(struct cifs_posix_ace
) * count
;
2408 /* check if we would go beyond end of SMB */
2409 if(size_of_data_area
< size
) {
2410 cFYI(1,("bad CIFS POSIX ACL size %d vs. %d",size_of_data_area
,size
));
2413 } else if(acl_type
& ACL_TYPE_DEFAULT
) {
2414 count
= le16_to_cpu(cifs_acl
->access_entry_count
);
2415 size
= sizeof(struct cifs_posix_acl
);
2416 size
+= sizeof(struct cifs_posix_ace
) * count
;
2417 /* skip past access ACEs to get to default ACEs */
2418 pACE
= &cifs_acl
->ace_array
[count
];
2419 count
= le16_to_cpu(cifs_acl
->default_entry_count
);
2420 size
+= sizeof(struct cifs_posix_ace
) * count
;
2421 /* check if we would go beyond end of SMB */
2422 if(size_of_data_area
< size
)
2429 size
= posix_acl_xattr_size(count
);
2430 if((buflen
== 0) || (local_acl
== NULL
)) {
2431 /* used to query ACL EA size */
2432 } else if(size
> buflen
) {
2434 } else /* buffer big enough */ {
2435 local_acl
->a_version
= cpu_to_le32(POSIX_ACL_XATTR_VERSION
);
2436 for(i
= 0;i
< count
;i
++) {
2437 cifs_convert_ace(&local_acl
->a_entries
[i
],pACE
);
2444 static __u16
convert_ace_to_cifs_ace(struct cifs_posix_ace
* cifs_ace
,
2445 const posix_acl_xattr_entry
* local_ace
)
2447 __u16 rc
= 0; /* 0 = ACL converted ok */
2449 cifs_ace
->cifs_e_perm
= le16_to_cpu(local_ace
->e_perm
);
2450 cifs_ace
->cifs_e_tag
= le16_to_cpu(local_ace
->e_tag
);
2451 /* BB is there a better way to handle the large uid? */
2452 if(local_ace
->e_id
== cpu_to_le32(-1)) {
2453 /* Probably no need to le convert -1 on any arch but can not hurt */
2454 cifs_ace
->cifs_uid
= cpu_to_le64(-1);
2456 cifs_ace
->cifs_uid
= cpu_to_le64(le32_to_cpu(local_ace
->e_id
));
2457 /*cFYI(1,("perm %d tag %d id %d",ace->e_perm,ace->e_tag,ace->e_id));*/
2461 /* Convert ACL from local Linux POSIX xattr to CIFS POSIX ACL wire format */
2462 static __u16
ACL_to_cifs_posix(char * parm_data
,const char * pACL
,const int buflen
,
2466 struct cifs_posix_acl
* cifs_acl
= (struct cifs_posix_acl
*)parm_data
;
2467 posix_acl_xattr_header
* local_acl
= (posix_acl_xattr_header
*)pACL
;
2471 if((buflen
== 0) || (pACL
== NULL
) || (cifs_acl
== NULL
))
2474 count
= posix_acl_xattr_count((size_t)buflen
);
2475 cFYI(1,("setting acl with %d entries from buf of length %d and version of %d",
2476 count
, buflen
, le32_to_cpu(local_acl
->a_version
)));
2477 if(le32_to_cpu(local_acl
->a_version
) != 2) {
2478 cFYI(1,("unknown POSIX ACL version %d",
2479 le32_to_cpu(local_acl
->a_version
)));
2482 cifs_acl
->version
= cpu_to_le16(1);
2483 if(acl_type
== ACL_TYPE_ACCESS
)
2484 cifs_acl
->access_entry_count
= cpu_to_le16(count
);
2485 else if(acl_type
== ACL_TYPE_DEFAULT
)
2486 cifs_acl
->default_entry_count
= cpu_to_le16(count
);
2488 cFYI(1,("unknown ACL type %d",acl_type
));
2491 for(i
=0;i
<count
;i
++) {
2492 rc
= convert_ace_to_cifs_ace(&cifs_acl
->ace_array
[i
],
2493 &local_acl
->a_entries
[i
]);
2495 /* ACE not converted */
2500 rc
= (__u16
)(count
* sizeof(struct cifs_posix_ace
));
2501 rc
+= sizeof(struct cifs_posix_acl
);
2502 /* BB add check to make sure ACL does not overflow SMB */
2508 CIFSSMBGetPosixACL(const int xid
, struct cifsTconInfo
*tcon
,
2509 const unsigned char *searchName
,
2510 char *acl_inf
, const int buflen
, const int acl_type
,
2511 const struct nls_table
*nls_codepage
, int remap
)
2513 /* SMB_QUERY_POSIX_ACL */
2514 TRANSACTION2_QPI_REQ
*pSMB
= NULL
;
2515 TRANSACTION2_QPI_RSP
*pSMBr
= NULL
;
2519 __u16 params
, byte_count
;
2521 cFYI(1, ("In GetPosixACL (Unix) for path %s", searchName
));
2524 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
2529 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
2531 cifsConvertToUCS((__le16
*) pSMB
->FileName
, searchName
,
2532 PATH_MAX
, nls_codepage
, remap
);
2533 name_len
++; /* trailing null */
2535 pSMB
->FileName
[name_len
] = 0;
2536 pSMB
->FileName
[name_len
+1] = 0;
2537 } else { /* BB improve the check for buffer overruns BB */
2538 name_len
= strnlen(searchName
, PATH_MAX
);
2539 name_len
++; /* trailing null */
2540 strncpy(pSMB
->FileName
, searchName
, name_len
);
2543 params
= 2 /* level */ + 4 /* rsrvd */ + name_len
/* incl null */ ;
2544 pSMB
->TotalDataCount
= 0;
2545 pSMB
->MaxParameterCount
= cpu_to_le16(2);
2546 /* BB find exact max data count below from sess structure BB */
2547 pSMB
->MaxDataCount
= cpu_to_le16(4000);
2548 pSMB
->MaxSetupCount
= 0;
2552 pSMB
->Reserved2
= 0;
2553 pSMB
->ParameterOffset
= cpu_to_le16(
2554 offsetof(struct smb_com_transaction2_qpi_req
,InformationLevel
) - 4);
2555 pSMB
->DataCount
= 0;
2556 pSMB
->DataOffset
= 0;
2557 pSMB
->SetupCount
= 1;
2558 pSMB
->Reserved3
= 0;
2559 pSMB
->SubCommand
= cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION
);
2560 byte_count
= params
+ 1 /* pad */ ;
2561 pSMB
->TotalParameterCount
= cpu_to_le16(params
);
2562 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
2563 pSMB
->InformationLevel
= cpu_to_le16(SMB_QUERY_POSIX_ACL
);
2564 pSMB
->Reserved4
= 0;
2565 pSMB
->hdr
.smb_buf_length
+= byte_count
;
2566 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
2568 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
2569 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
2570 cifs_stats_inc(&tcon
->num_acl_get
);
2572 cFYI(1, ("Send error in Query POSIX ACL = %d", rc
));
2574 /* decode response */
2576 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
2577 if (rc
|| (pSMBr
->ByteCount
< 2))
2578 /* BB also check enough total bytes returned */
2579 rc
= -EIO
; /* bad smb */
2581 __u16 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
2582 __u16 count
= le16_to_cpu(pSMBr
->t2
.DataCount
);
2583 rc
= cifs_copy_posix_acl(acl_inf
,
2584 (char *)&pSMBr
->hdr
.Protocol
+data_offset
,
2585 buflen
,acl_type
,count
);
2588 cifs_buf_release(pSMB
);
2595 CIFSSMBSetPosixACL(const int xid
, struct cifsTconInfo
*tcon
,
2596 const unsigned char *fileName
,
2597 const char *local_acl
, const int buflen
,
2599 const struct nls_table
*nls_codepage
, int remap
)
2601 struct smb_com_transaction2_spi_req
*pSMB
= NULL
;
2602 struct smb_com_transaction2_spi_rsp
*pSMBr
= NULL
;
2606 int bytes_returned
= 0;
2607 __u16 params
, byte_count
, data_count
, param_offset
, offset
;
2609 cFYI(1, ("In SetPosixACL (Unix) for path %s", fileName
));
2611 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
2615 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
2617 cifsConvertToUCS((__le16
*) pSMB
->FileName
, fileName
,
2618 PATH_MAX
, nls_codepage
, remap
);
2619 name_len
++; /* trailing null */
2621 } else { /* BB improve the check for buffer overruns BB */
2622 name_len
= strnlen(fileName
, PATH_MAX
);
2623 name_len
++; /* trailing null */
2624 strncpy(pSMB
->FileName
, fileName
, name_len
);
2626 params
= 6 + name_len
;
2627 pSMB
->MaxParameterCount
= cpu_to_le16(2);
2628 pSMB
->MaxDataCount
= cpu_to_le16(1000); /* BB find max SMB size from sess */
2629 pSMB
->MaxSetupCount
= 0;
2633 pSMB
->Reserved2
= 0;
2634 param_offset
= offsetof(struct smb_com_transaction2_spi_req
,
2635 InformationLevel
) - 4;
2636 offset
= param_offset
+ params
;
2637 parm_data
= ((char *) &pSMB
->hdr
.Protocol
) + offset
;
2638 pSMB
->ParameterOffset
= cpu_to_le16(param_offset
);
2640 /* convert to on the wire format for POSIX ACL */
2641 data_count
= ACL_to_cifs_posix(parm_data
,local_acl
,buflen
,acl_type
);
2643 if(data_count
== 0) {
2645 goto setACLerrorExit
;
2647 pSMB
->DataOffset
= cpu_to_le16(offset
);
2648 pSMB
->SetupCount
= 1;
2649 pSMB
->Reserved3
= 0;
2650 pSMB
->SubCommand
= cpu_to_le16(TRANS2_SET_PATH_INFORMATION
);
2651 pSMB
->InformationLevel
= cpu_to_le16(SMB_SET_POSIX_ACL
);
2652 byte_count
= 3 /* pad */ + params
+ data_count
;
2653 pSMB
->DataCount
= cpu_to_le16(data_count
);
2654 pSMB
->TotalDataCount
= pSMB
->DataCount
;
2655 pSMB
->ParameterCount
= cpu_to_le16(params
);
2656 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
2657 pSMB
->Reserved4
= 0;
2658 pSMB
->hdr
.smb_buf_length
+= byte_count
;
2659 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
2660 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
2661 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
2663 cFYI(1, ("Set POSIX ACL returned %d", rc
));
2667 cifs_buf_release(pSMB
);
2673 /* BB fix tabs in this function FIXME BB */
2675 CIFSGetExtAttr(const int xid
, struct cifsTconInfo
*tcon
,
2676 const int netfid
, __u64
* pExtAttrBits
, __u64
*pMask
)
2679 struct smb_t2_qfi_req
*pSMB
= NULL
;
2680 struct smb_t2_qfi_rsp
*pSMBr
= NULL
;
2682 __u16 params
, byte_count
;
2684 cFYI(1,("In GetExtAttr"));
2689 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
2694 params
= 2 /* level */ +2 /* fid */;
2695 pSMB
->t2
.TotalDataCount
= 0;
2696 pSMB
->t2
.MaxParameterCount
= cpu_to_le16(4);
2697 /* BB find exact max data count below from sess structure BB */
2698 pSMB
->t2
.MaxDataCount
= cpu_to_le16(4000);
2699 pSMB
->t2
.MaxSetupCount
= 0;
2700 pSMB
->t2
.Reserved
= 0;
2702 pSMB
->t2
.Timeout
= 0;
2703 pSMB
->t2
.Reserved2
= 0;
2704 pSMB
->t2
.ParameterOffset
= cpu_to_le16(offsetof(struct smb_t2_qfi_req
,
2706 pSMB
->t2
.DataCount
= 0;
2707 pSMB
->t2
.DataOffset
= 0;
2708 pSMB
->t2
.SetupCount
= 1;
2709 pSMB
->t2
.Reserved3
= 0;
2710 pSMB
->t2
.SubCommand
= cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION
);
2711 byte_count
= params
+ 1 /* pad */ ;
2712 pSMB
->t2
.TotalParameterCount
= cpu_to_le16(params
);
2713 pSMB
->t2
.ParameterCount
= pSMB
->t2
.TotalParameterCount
;
2714 pSMB
->InformationLevel
= cpu_to_le16(SMB_QUERY_ATTR_FLAGS
);
2717 pSMB
->hdr
.smb_buf_length
+= byte_count
;
2718 pSMB
->t2
.ByteCount
= cpu_to_le16(byte_count
);
2720 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
2721 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
2723 cFYI(1, ("error %d in GetExtAttr", rc
));
2725 /* decode response */
2726 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
2727 if (rc
|| (pSMBr
->ByteCount
< 2))
2728 /* BB also check enough total bytes returned */
2729 /* If rc should we check for EOPNOSUPP and
2730 disable the srvino flag? or in caller? */
2731 rc
= -EIO
; /* bad smb */
2733 __u16 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
2734 __u16 count
= le16_to_cpu(pSMBr
->t2
.DataCount
);
2735 struct file_chattr_info
* pfinfo
;
2736 /* BB Do we need a cast or hash here ? */
2738 cFYI(1, ("Illegal size ret in GetExtAttr"));
2742 pfinfo
= (struct file_chattr_info
*)
2743 (data_offset
+ (char *) &pSMBr
->hdr
.Protocol
);
2744 *pExtAttrBits
= le64_to_cpu(pfinfo
->mode
);
2745 *pMask
= le64_to_cpu(pfinfo
->mask
);
2749 cifs_buf_release(pSMB
);
2751 goto GetExtAttrRetry
;
2756 #endif /* CONFIG_POSIX */
2759 /* security id for everyone */
2760 const struct cifs_sid sid_everyone
= {1, 1, {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0}};
2762 const struct cifs_sid sid_user
= {1, 2 , {0, 0, 0, 0, 0, 5}, {32, 545, 0, 0}};
2764 /* Convert CIFS ACL to POSIX form */
2765 static int parse_sec_desc(struct cifs_sid
* psec_desc
, int acl_len
)
2770 /* Get Security Descriptor (by handle) from remote server for a file or dir */
2772 CIFSSMBGetCIFSACL(const int xid
, struct cifsTconInfo
*tcon
, __u16 fid
,
2773 /* BB fix up return info */ char *acl_inf
, const int buflen
,
2774 const int acl_type
/* ACCESS/DEFAULT not sure implication */)
2778 QUERY_SEC_DESC_REQ
* pSMB
;
2781 cFYI(1, ("GetCifsACL"));
2783 rc
= smb_init_ntransact(NT_TRANSACT_QUERY_SECURITY_DESC
, 0,
2784 8 /* parm len */, tcon
, (void **) &pSMB
);
2788 pSMB
->MaxParameterCount
= cpu_to_le32(4);
2789 /* BB TEST with big acls that might need to be e.g. larger than 16K */
2790 pSMB
->MaxSetupCount
= 0;
2791 pSMB
->Fid
= fid
; /* file handle always le */
2792 pSMB
->AclFlags
= cpu_to_le32(CIFS_ACL_OWNER
| CIFS_ACL_GROUP
|
2794 pSMB
->ByteCount
= cpu_to_le16(11); /* 3 bytes pad + 8 bytes parm */
2795 pSMB
->hdr
.smb_buf_length
+= 11;
2796 iov
[0].iov_base
= (char *)pSMB
;
2797 iov
[0].iov_len
= pSMB
->hdr
.smb_buf_length
+ 4;
2799 rc
= SendReceive2(xid
, tcon
->ses
, iov
, 1 /* num iovec */, &buf_type
, 0);
2800 cifs_stats_inc(&tcon
->num_acl_get
);
2802 cFYI(1, ("Send error in QuerySecDesc = %d", rc
));
2803 } else { /* decode response */
2804 struct cifs_sid
* psec_desc
;
2809 struct smb_com_ntransact_rsp
* pSMBr
;
2811 /* validate_nttransact */
2812 rc
= validate_ntransact(iov
[0].iov_base
, (char **)&parm
,
2813 (char **)&psec_desc
,
2814 &parm_len
, &data_len
);
2818 pSMBr
= (struct smb_com_ntransact_rsp
*)iov
[0].iov_base
;
2820 cERROR(1,("smb %p parm %p data %p",pSMBr
,parm
,psec_desc
)); /* BB removeme BB */
2822 if (le32_to_cpu(pSMBr
->ParameterCount
) != 4) {
2823 rc
= -EIO
; /* bad smb */
2827 /* BB check that data area is minimum length and as big as acl_len */
2829 acl_len
= le32_to_cpu(*(__le32
*)parm
);
2830 /* BB check if(acl_len > bufsize) */
2832 parse_sec_desc(psec_desc
, acl_len
);
2835 if(buf_type
== CIFS_SMALL_BUFFER
)
2836 cifs_small_buf_release(iov
[0].iov_base
);
2837 else if(buf_type
== CIFS_LARGE_BUFFER
)
2838 cifs_buf_release(iov
[0].iov_base
);
2839 /* cifs_small_buf_release(pSMB); */ /* Freed earlier now in SendReceive2 */
2844 /* Legacy Query Path Information call for lookup to old servers such
2846 int SMBQueryInformation(const int xid
, struct cifsTconInfo
*tcon
,
2847 const unsigned char *searchName
,
2848 FILE_ALL_INFO
* pFinfo
,
2849 const struct nls_table
*nls_codepage
, int remap
)
2851 QUERY_INFORMATION_REQ
* pSMB
;
2852 QUERY_INFORMATION_RSP
* pSMBr
;
2857 cFYI(1, ("In SMBQPath path %s", searchName
));
2859 rc
= smb_init(SMB_COM_QUERY_INFORMATION
, 0, tcon
, (void **) &pSMB
,
2864 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
2866 cifsConvertToUCS((__le16
*) pSMB
->FileName
, searchName
,
2867 PATH_MAX
, nls_codepage
, remap
);
2868 name_len
++; /* trailing null */
2871 name_len
= strnlen(searchName
, PATH_MAX
);
2872 name_len
++; /* trailing null */
2873 strncpy(pSMB
->FileName
, searchName
, name_len
);
2875 pSMB
->BufferFormat
= 0x04;
2876 name_len
++; /* account for buffer type byte */
2877 pSMB
->hdr
.smb_buf_length
+= (__u16
) name_len
;
2878 pSMB
->ByteCount
= cpu_to_le16(name_len
);
2880 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
2881 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
2883 cFYI(1, ("Send error in QueryInfo = %d", rc
));
2884 } else if (pFinfo
) { /* decode response */
2885 memset(pFinfo
, 0, sizeof(FILE_ALL_INFO
));
2886 pFinfo
->AllocationSize
=
2887 cpu_to_le64(le32_to_cpu(pSMBr
->size
));
2888 pFinfo
->EndOfFile
= pFinfo
->AllocationSize
;
2889 pFinfo
->Attributes
=
2890 cpu_to_le32(le16_to_cpu(pSMBr
->attr
));
2892 rc
= -EIO
; /* bad buffer passed in */
2894 cifs_buf_release(pSMB
);
2906 CIFSSMBQPathInfo(const int xid
, struct cifsTconInfo
*tcon
,
2907 const unsigned char *searchName
,
2908 FILE_ALL_INFO
* pFindData
,
2909 const struct nls_table
*nls_codepage
, int remap
)
2911 /* level 263 SMB_QUERY_FILE_ALL_INFO */
2912 TRANSACTION2_QPI_REQ
*pSMB
= NULL
;
2913 TRANSACTION2_QPI_RSP
*pSMBr
= NULL
;
2917 __u16 params
, byte_count
;
2919 /* cFYI(1, ("In QPathInfo path %s", searchName)); */
2921 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
2926 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
2928 cifsConvertToUCS((__le16
*) pSMB
->FileName
, searchName
,
2929 PATH_MAX
, nls_codepage
, remap
);
2930 name_len
++; /* trailing null */
2932 } else { /* BB improve the check for buffer overruns BB */
2933 name_len
= strnlen(searchName
, PATH_MAX
);
2934 name_len
++; /* trailing null */
2935 strncpy(pSMB
->FileName
, searchName
, name_len
);
2938 params
= 2 /* level */ + 4 /* reserved */ + name_len
/* includes NUL */ ;
2939 pSMB
->TotalDataCount
= 0;
2940 pSMB
->MaxParameterCount
= cpu_to_le16(2);
2941 pSMB
->MaxDataCount
= cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
2942 pSMB
->MaxSetupCount
= 0;
2946 pSMB
->Reserved2
= 0;
2947 pSMB
->ParameterOffset
= cpu_to_le16(offsetof(
2948 struct smb_com_transaction2_qpi_req
,InformationLevel
) - 4);
2949 pSMB
->DataCount
= 0;
2950 pSMB
->DataOffset
= 0;
2951 pSMB
->SetupCount
= 1;
2952 pSMB
->Reserved3
= 0;
2953 pSMB
->SubCommand
= cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION
);
2954 byte_count
= params
+ 1 /* pad */ ;
2955 pSMB
->TotalParameterCount
= cpu_to_le16(params
);
2956 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
2957 pSMB
->InformationLevel
= cpu_to_le16(SMB_QUERY_FILE_ALL_INFO
);
2958 pSMB
->Reserved4
= 0;
2959 pSMB
->hdr
.smb_buf_length
+= byte_count
;
2960 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
2962 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
2963 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
2965 cFYI(1, ("Send error in QPathInfo = %d", rc
));
2966 } else { /* decode response */
2967 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
2969 if (rc
|| (pSMBr
->ByteCount
< 40))
2970 rc
= -EIO
; /* bad smb */
2971 else if (pFindData
){
2972 __u16 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
2973 memcpy((char *) pFindData
,
2974 (char *) &pSMBr
->hdr
.Protocol
+
2975 data_offset
, sizeof (FILE_ALL_INFO
));
2979 cifs_buf_release(pSMB
);
2981 goto QPathInfoRetry
;
2987 CIFSSMBUnixQPathInfo(const int xid
, struct cifsTconInfo
*tcon
,
2988 const unsigned char *searchName
,
2989 FILE_UNIX_BASIC_INFO
* pFindData
,
2990 const struct nls_table
*nls_codepage
, int remap
)
2992 /* SMB_QUERY_FILE_UNIX_BASIC */
2993 TRANSACTION2_QPI_REQ
*pSMB
= NULL
;
2994 TRANSACTION2_QPI_RSP
*pSMBr
= NULL
;
2996 int bytes_returned
= 0;
2998 __u16 params
, byte_count
;
3000 cFYI(1, ("In QPathInfo (Unix) the path %s", searchName
));
3002 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
3007 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
3009 cifsConvertToUCS((__le16
*) pSMB
->FileName
, searchName
,
3010 PATH_MAX
, nls_codepage
, remap
);
3011 name_len
++; /* trailing null */
3013 } else { /* BB improve the check for buffer overruns BB */
3014 name_len
= strnlen(searchName
, PATH_MAX
);
3015 name_len
++; /* trailing null */
3016 strncpy(pSMB
->FileName
, searchName
, name_len
);
3019 params
= 2 /* level */ + 4 /* reserved */ + name_len
/* includes NUL */ ;
3020 pSMB
->TotalDataCount
= 0;
3021 pSMB
->MaxParameterCount
= cpu_to_le16(2);
3022 /* BB find exact max SMB PDU from sess structure BB */
3023 pSMB
->MaxDataCount
= cpu_to_le16(4000);
3024 pSMB
->MaxSetupCount
= 0;
3028 pSMB
->Reserved2
= 0;
3029 pSMB
->ParameterOffset
= cpu_to_le16(offsetof(
3030 struct smb_com_transaction2_qpi_req
,InformationLevel
) - 4);
3031 pSMB
->DataCount
= 0;
3032 pSMB
->DataOffset
= 0;
3033 pSMB
->SetupCount
= 1;
3034 pSMB
->Reserved3
= 0;
3035 pSMB
->SubCommand
= cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION
);
3036 byte_count
= params
+ 1 /* pad */ ;
3037 pSMB
->TotalParameterCount
= cpu_to_le16(params
);
3038 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
3039 pSMB
->InformationLevel
= cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC
);
3040 pSMB
->Reserved4
= 0;
3041 pSMB
->hdr
.smb_buf_length
+= byte_count
;
3042 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
3044 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
3045 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
3047 cFYI(1, ("Send error in QPathInfo = %d", rc
));
3048 } else { /* decode response */
3049 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
3051 if (rc
|| (pSMBr
->ByteCount
< sizeof(FILE_UNIX_BASIC_INFO
))) {
3052 rc
= -EIO
; /* bad smb */
3054 __u16 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
3055 memcpy((char *) pFindData
,
3056 (char *) &pSMBr
->hdr
.Protocol
+
3058 sizeof (FILE_UNIX_BASIC_INFO
));
3061 cifs_buf_release(pSMB
);
3063 goto UnixQPathInfoRetry
;
3068 #if 0 /* function unused at present */
3069 int CIFSFindSingle(const int xid
, struct cifsTconInfo
*tcon
,
3070 const char *searchName
, FILE_ALL_INFO
* findData
,
3071 const struct nls_table
*nls_codepage
)
3073 /* level 257 SMB_ */
3074 TRANSACTION2_FFIRST_REQ
*pSMB
= NULL
;
3075 TRANSACTION2_FFIRST_RSP
*pSMBr
= NULL
;
3079 __u16 params
, byte_count
;
3081 cFYI(1, ("In FindUnique"));
3083 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
3088 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
3090 cifsConvertToUCS((__le16
*) pSMB
->FileName
, searchName
, PATH_MAX
3091 /* find define for this maxpathcomponent */
3093 name_len
++; /* trailing null */
3095 } else { /* BB improve the check for buffer overruns BB */
3096 name_len
= strnlen(searchName
, PATH_MAX
);
3097 name_len
++; /* trailing null */
3098 strncpy(pSMB
->FileName
, searchName
, name_len
);
3101 params
= 12 + name_len
/* includes null */ ;
3102 pSMB
->TotalDataCount
= 0; /* no EAs */
3103 pSMB
->MaxParameterCount
= cpu_to_le16(2);
3104 pSMB
->MaxDataCount
= cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
3105 pSMB
->MaxSetupCount
= 0;
3109 pSMB
->Reserved2
= 0;
3110 pSMB
->ParameterOffset
= cpu_to_le16(
3111 offsetof(struct smb_com_transaction2_ffirst_req
,InformationLevel
) - 4);
3112 pSMB
->DataCount
= 0;
3113 pSMB
->DataOffset
= 0;
3114 pSMB
->SetupCount
= 1; /* one byte, no need to le convert */
3115 pSMB
->Reserved3
= 0;
3116 pSMB
->SubCommand
= cpu_to_le16(TRANS2_FIND_FIRST
);
3117 byte_count
= params
+ 1 /* pad */ ;
3118 pSMB
->TotalParameterCount
= cpu_to_le16(params
);
3119 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
3120 pSMB
->SearchAttributes
=
3121 cpu_to_le16(ATTR_READONLY
| ATTR_HIDDEN
| ATTR_SYSTEM
|
3123 pSMB
->SearchCount
= cpu_to_le16(16); /* BB increase */
3124 pSMB
->SearchFlags
= cpu_to_le16(1);
3125 pSMB
->InformationLevel
= cpu_to_le16(SMB_FIND_FILE_DIRECTORY_INFO
);
3126 pSMB
->SearchStorageType
= 0; /* BB what should we set this to? BB */
3127 pSMB
->hdr
.smb_buf_length
+= byte_count
;
3128 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
3130 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
3131 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
3134 cFYI(1, ("Send error in FindFileDirInfo = %d", rc
));
3135 } else { /* decode response */
3136 cifs_stats_inc(&tcon
->num_ffirst
);
3140 cifs_buf_release(pSMB
);
3142 goto findUniqueRetry
;
3146 #endif /* end unused (temporarily) function */
3148 /* xid, tcon, searchName and codepage are input parms, rest are returned */
3150 CIFSFindFirst(const int xid
, struct cifsTconInfo
*tcon
,
3151 const char *searchName
,
3152 const struct nls_table
*nls_codepage
,
3154 struct cifs_search_info
* psrch_inf
, int remap
, const char dirsep
)
3156 /* level 257 SMB_ */
3157 TRANSACTION2_FFIRST_REQ
*pSMB
= NULL
;
3158 TRANSACTION2_FFIRST_RSP
*pSMBr
= NULL
;
3159 T2_FFIRST_RSP_PARMS
* parms
;
3161 int bytes_returned
= 0;
3163 __u16 params
, byte_count
;
3165 cFYI(1, ("In FindFirst for %s",searchName
));
3168 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
3173 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
3175 cifsConvertToUCS((__le16
*) pSMB
->FileName
,searchName
,
3176 PATH_MAX
, nls_codepage
, remap
);
3177 /* We can not add the asterik earlier in case
3178 it got remapped to 0xF03A as if it were part of the
3179 directory name instead of a wildcard */
3181 pSMB
->FileName
[name_len
] = dirsep
;
3182 pSMB
->FileName
[name_len
+1] = 0;
3183 pSMB
->FileName
[name_len
+2] = '*';
3184 pSMB
->FileName
[name_len
+3] = 0;
3185 name_len
+= 4; /* now the trailing null */
3186 pSMB
->FileName
[name_len
] = 0; /* null terminate just in case */
3187 pSMB
->FileName
[name_len
+1] = 0;
3189 } else { /* BB add check for overrun of SMB buf BB */
3190 name_len
= strnlen(searchName
, PATH_MAX
);
3191 /* BB fix here and in unicode clause above ie
3192 if(name_len > buffersize-header)
3193 free buffer exit; BB */
3194 strncpy(pSMB
->FileName
, searchName
, name_len
);
3195 pSMB
->FileName
[name_len
] = dirsep
;
3196 pSMB
->FileName
[name_len
+1] = '*';
3197 pSMB
->FileName
[name_len
+2] = 0;
3201 params
= 12 + name_len
/* includes null */ ;
3202 pSMB
->TotalDataCount
= 0; /* no EAs */
3203 pSMB
->MaxParameterCount
= cpu_to_le16(10);
3204 pSMB
->MaxDataCount
= cpu_to_le16((tcon
->ses
->server
->maxBuf
-
3205 MAX_CIFS_HDR_SIZE
) & 0xFFFFFF00);
3206 pSMB
->MaxSetupCount
= 0;
3210 pSMB
->Reserved2
= 0;
3211 byte_count
= params
+ 1 /* pad */ ;
3212 pSMB
->TotalParameterCount
= cpu_to_le16(params
);
3213 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
3214 pSMB
->ParameterOffset
= cpu_to_le16(
3215 offsetof(struct smb_com_transaction2_ffirst_req
, SearchAttributes
)
3217 pSMB
->DataCount
= 0;
3218 pSMB
->DataOffset
= 0;
3219 pSMB
->SetupCount
= 1; /* one byte, no need to make endian neutral */
3220 pSMB
->Reserved3
= 0;
3221 pSMB
->SubCommand
= cpu_to_le16(TRANS2_FIND_FIRST
);
3222 pSMB
->SearchAttributes
=
3223 cpu_to_le16(ATTR_READONLY
| ATTR_HIDDEN
| ATTR_SYSTEM
|
3225 pSMB
->SearchCount
= cpu_to_le16(CIFSMaxBufSize
/sizeof(FILE_UNIX_INFO
));
3226 pSMB
->SearchFlags
= cpu_to_le16(CIFS_SEARCH_CLOSE_AT_END
|
3227 CIFS_SEARCH_RETURN_RESUME
);
3228 pSMB
->InformationLevel
= cpu_to_le16(psrch_inf
->info_level
);
3230 /* BB what should we set StorageType to? Does it matter? BB */
3231 pSMB
->SearchStorageType
= 0;
3232 pSMB
->hdr
.smb_buf_length
+= byte_count
;
3233 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
3235 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
3236 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
3237 cifs_stats_inc(&tcon
->num_ffirst
);
3239 if (rc
) {/* BB add logic to retry regular search if Unix search
3240 rejected unexpectedly by server */
3241 /* BB Add code to handle unsupported level rc */
3242 cFYI(1, ("Error in FindFirst = %d", rc
));
3244 cifs_buf_release(pSMB
);
3246 /* BB eventually could optimize out free and realloc of buf */
3249 goto findFirstRetry
;
3250 } else { /* decode response */
3251 /* BB remember to free buffer if error BB */
3252 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
3254 if (pSMBr
->hdr
.Flags2
& SMBFLG2_UNICODE
)
3255 psrch_inf
->unicode
= TRUE
;
3257 psrch_inf
->unicode
= FALSE
;
3259 psrch_inf
->ntwrk_buf_start
= (char *)pSMBr
;
3260 psrch_inf
->smallBuf
= 0;
3261 psrch_inf
->srch_entries_start
=
3262 (char *) &pSMBr
->hdr
.Protocol
+
3263 le16_to_cpu(pSMBr
->t2
.DataOffset
);
3264 parms
= (T2_FFIRST_RSP_PARMS
*)((char *) &pSMBr
->hdr
.Protocol
+
3265 le16_to_cpu(pSMBr
->t2
.ParameterOffset
));
3267 if(parms
->EndofSearch
)
3268 psrch_inf
->endOfSearch
= TRUE
;
3270 psrch_inf
->endOfSearch
= FALSE
;
3272 psrch_inf
->entries_in_buffer
= le16_to_cpu(parms
->SearchCount
);
3273 psrch_inf
->index_of_last_entry
= 2 /* skip . and .. */ +
3274 psrch_inf
->entries_in_buffer
;
3275 *pnetfid
= parms
->SearchHandle
;
3277 cifs_buf_release(pSMB
);
3284 int CIFSFindNext(const int xid
, struct cifsTconInfo
*tcon
,
3285 __u16 searchHandle
, struct cifs_search_info
* psrch_inf
)
3287 TRANSACTION2_FNEXT_REQ
*pSMB
= NULL
;
3288 TRANSACTION2_FNEXT_RSP
*pSMBr
= NULL
;
3289 T2_FNEXT_RSP_PARMS
* parms
;
3290 char *response_data
;
3292 int bytes_returned
, name_len
;
3293 __u16 params
, byte_count
;
3295 cFYI(1, ("In FindNext"));
3297 if(psrch_inf
->endOfSearch
== TRUE
)
3300 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
3305 params
= 14; /* includes 2 bytes of null string, converted to LE below */
3307 pSMB
->TotalDataCount
= 0; /* no EAs */
3308 pSMB
->MaxParameterCount
= cpu_to_le16(8);
3309 pSMB
->MaxDataCount
=
3310 cpu_to_le16((tcon
->ses
->server
->maxBuf
- MAX_CIFS_HDR_SIZE
) & 0xFFFFFF00);
3311 pSMB
->MaxSetupCount
= 0;
3315 pSMB
->Reserved2
= 0;
3316 pSMB
->ParameterOffset
= cpu_to_le16(
3317 offsetof(struct smb_com_transaction2_fnext_req
,SearchHandle
) - 4);
3318 pSMB
->DataCount
= 0;
3319 pSMB
->DataOffset
= 0;
3320 pSMB
->SetupCount
= 1;
3321 pSMB
->Reserved3
= 0;
3322 pSMB
->SubCommand
= cpu_to_le16(TRANS2_FIND_NEXT
);
3323 pSMB
->SearchHandle
= searchHandle
; /* always kept as le */
3325 cpu_to_le16(CIFSMaxBufSize
/ sizeof (FILE_UNIX_INFO
));
3326 /* test for Unix extensions */
3327 /* if (tcon->ses->capabilities & CAP_UNIX) {
3328 pSMB->InformationLevel = cpu_to_le16(SMB_FIND_FILE_UNIX);
3329 psrch_inf->info_level = SMB_FIND_FILE_UNIX;
3331 pSMB->InformationLevel =
3332 cpu_to_le16(SMB_FIND_FILE_DIRECTORY_INFO);
3333 psrch_inf->info_level = SMB_FIND_FILE_DIRECTORY_INFO;
3335 pSMB
->InformationLevel
= cpu_to_le16(psrch_inf
->info_level
);
3336 pSMB
->ResumeKey
= psrch_inf
->resume_key
;
3338 cpu_to_le16(CIFS_SEARCH_CLOSE_AT_END
| CIFS_SEARCH_RETURN_RESUME
);
3340 name_len
= psrch_inf
->resume_name_len
;
3342 if(name_len
< PATH_MAX
) {
3343 memcpy(pSMB
->ResumeFileName
, psrch_inf
->presume_name
, name_len
);
3344 byte_count
+= name_len
;
3345 /* 14 byte parm len above enough for 2 byte null terminator */
3346 pSMB
->ResumeFileName
[name_len
] = 0;
3347 pSMB
->ResumeFileName
[name_len
+1] = 0;
3350 goto FNext2_err_exit
;
3352 byte_count
= params
+ 1 /* pad */ ;
3353 pSMB
->TotalParameterCount
= cpu_to_le16(params
);
3354 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
3355 pSMB
->hdr
.smb_buf_length
+= byte_count
;
3356 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
3358 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
3359 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
3360 cifs_stats_inc(&tcon
->num_fnext
);
3363 psrch_inf
->endOfSearch
= TRUE
;
3364 rc
= 0; /* search probably was closed at end of search above */
3366 cFYI(1, ("FindNext returned = %d", rc
));
3367 } else { /* decode response */
3368 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
3371 /* BB fixme add lock for file (srch_info) struct here */
3372 if (pSMBr
->hdr
.Flags2
& SMBFLG2_UNICODE
)
3373 psrch_inf
->unicode
= TRUE
;
3375 psrch_inf
->unicode
= FALSE
;
3376 response_data
= (char *) &pSMBr
->hdr
.Protocol
+
3377 le16_to_cpu(pSMBr
->t2
.ParameterOffset
);
3378 parms
= (T2_FNEXT_RSP_PARMS
*)response_data
;
3379 response_data
= (char *)&pSMBr
->hdr
.Protocol
+
3380 le16_to_cpu(pSMBr
->t2
.DataOffset
);
3381 if(psrch_inf
->smallBuf
)
3382 cifs_small_buf_release(
3383 psrch_inf
->ntwrk_buf_start
);
3385 cifs_buf_release(psrch_inf
->ntwrk_buf_start
);
3386 psrch_inf
->srch_entries_start
= response_data
;
3387 psrch_inf
->ntwrk_buf_start
= (char *)pSMB
;
3388 psrch_inf
->smallBuf
= 0;
3389 if(parms
->EndofSearch
)
3390 psrch_inf
->endOfSearch
= TRUE
;
3392 psrch_inf
->endOfSearch
= FALSE
;
3394 psrch_inf
->entries_in_buffer
= le16_to_cpu(parms
->SearchCount
);
3395 psrch_inf
->index_of_last_entry
+=
3396 psrch_inf
->entries_in_buffer
;
3397 /* cFYI(1,("fnxt2 entries in buf %d index_of_last %d",psrch_inf->entries_in_buffer,psrch_inf->index_of_last_entry)); */
3399 /* BB fixme add unlock here */
3404 /* BB On error, should we leave previous search buf (and count and
3405 last entry fields) intact or free the previous one? */
3407 /* Note: On -EAGAIN error only caller can retry on handle based calls
3408 since file handle passed in no longer valid */
3411 cifs_buf_release(pSMB
);
3417 CIFSFindClose(const int xid
, struct cifsTconInfo
*tcon
, const __u16 searchHandle
)
3420 FINDCLOSE_REQ
*pSMB
= NULL
;
3421 CLOSE_RSP
*pSMBr
= NULL
; /* BB removeme BB */
3424 cFYI(1, ("In CIFSSMBFindClose"));
3425 rc
= small_smb_init(SMB_COM_FIND_CLOSE2
, 1, tcon
, (void **)&pSMB
);
3427 /* no sense returning error if session restarted
3428 as file handle has been closed */
3434 pSMBr
= (CLOSE_RSP
*)pSMB
; /* BB removeme BB */
3435 pSMB
->FileID
= searchHandle
;
3436 pSMB
->ByteCount
= 0;
3437 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
3438 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
3440 cERROR(1, ("Send error in FindClose = %d", rc
));
3442 cifs_stats_inc(&tcon
->num_fclose
);
3443 cifs_small_buf_release(pSMB
);
3445 /* Since session is dead, search handle closed on server already */
3453 CIFSGetSrvInodeNumber(const int xid
, struct cifsTconInfo
*tcon
,
3454 const unsigned char *searchName
,
3455 __u64
* inode_number
,
3456 const struct nls_table
*nls_codepage
, int remap
)
3459 TRANSACTION2_QPI_REQ
*pSMB
= NULL
;
3460 TRANSACTION2_QPI_RSP
*pSMBr
= NULL
;
3461 int name_len
, bytes_returned
;
3462 __u16 params
, byte_count
;
3464 cFYI(1,("In GetSrvInodeNum for %s",searchName
));
3468 GetInodeNumberRetry
:
3469 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
3475 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
3477 cifsConvertToUCS((__le16
*) pSMB
->FileName
, searchName
,
3478 PATH_MAX
,nls_codepage
, remap
);
3479 name_len
++; /* trailing null */
3481 } else { /* BB improve the check for buffer overruns BB */
3482 name_len
= strnlen(searchName
, PATH_MAX
);
3483 name_len
++; /* trailing null */
3484 strncpy(pSMB
->FileName
, searchName
, name_len
);
3487 params
= 2 /* level */ + 4 /* rsrvd */ + name_len
/* incl null */ ;
3488 pSMB
->TotalDataCount
= 0;
3489 pSMB
->MaxParameterCount
= cpu_to_le16(2);
3490 /* BB find exact max data count below from sess structure BB */
3491 pSMB
->MaxDataCount
= cpu_to_le16(4000);
3492 pSMB
->MaxSetupCount
= 0;
3496 pSMB
->Reserved2
= 0;
3497 pSMB
->ParameterOffset
= cpu_to_le16(offsetof(
3498 struct smb_com_transaction2_qpi_req
,InformationLevel
) - 4);
3499 pSMB
->DataCount
= 0;
3500 pSMB
->DataOffset
= 0;
3501 pSMB
->SetupCount
= 1;
3502 pSMB
->Reserved3
= 0;
3503 pSMB
->SubCommand
= cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION
);
3504 byte_count
= params
+ 1 /* pad */ ;
3505 pSMB
->TotalParameterCount
= cpu_to_le16(params
);
3506 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
3507 pSMB
->InformationLevel
= cpu_to_le16(SMB_QUERY_FILE_INTERNAL_INFO
);
3508 pSMB
->Reserved4
= 0;
3509 pSMB
->hdr
.smb_buf_length
+= byte_count
;
3510 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
3512 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
3513 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
3515 cFYI(1, ("error %d in QueryInternalInfo", rc
));
3517 /* decode response */
3518 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
3519 if (rc
|| (pSMBr
->ByteCount
< 2))
3520 /* BB also check enough total bytes returned */
3521 /* If rc should we check for EOPNOSUPP and
3522 disable the srvino flag? or in caller? */
3523 rc
= -EIO
; /* bad smb */
3525 __u16 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
3526 __u16 count
= le16_to_cpu(pSMBr
->t2
.DataCount
);
3527 struct file_internal_info
* pfinfo
;
3528 /* BB Do we need a cast or hash here ? */
3530 cFYI(1, ("Illegal size ret in QryIntrnlInf"));
3532 goto GetInodeNumOut
;
3534 pfinfo
= (struct file_internal_info
*)
3535 (data_offset
+ (char *) &pSMBr
->hdr
.Protocol
);
3536 *inode_number
= pfinfo
->UniqueId
;
3540 cifs_buf_release(pSMB
);
3542 goto GetInodeNumberRetry
;
3547 CIFSGetDFSRefer(const int xid
, struct cifsSesInfo
*ses
,
3548 const unsigned char *searchName
,
3549 unsigned char **targetUNCs
,
3550 unsigned int *number_of_UNC_in_array
,
3551 const struct nls_table
*nls_codepage
, int remap
)
3553 /* TRANS2_GET_DFS_REFERRAL */
3554 TRANSACTION2_GET_DFS_REFER_REQ
*pSMB
= NULL
;
3555 TRANSACTION2_GET_DFS_REFER_RSP
*pSMBr
= NULL
;
3556 struct dfs_referral_level_3
* referrals
= NULL
;
3562 __u16 params
, byte_count
;
3563 *number_of_UNC_in_array
= 0;
3566 cFYI(1, ("In GetDFSRefer the path %s", searchName
));
3570 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, NULL
, (void **) &pSMB
,
3575 /* server pointer checked in called function,
3576 but should never be null here anyway */
3577 pSMB
->hdr
.Mid
= GetNextMid(ses
->server
);
3578 pSMB
->hdr
.Tid
= ses
->ipc_tid
;
3579 pSMB
->hdr
.Uid
= ses
->Suid
;
3580 if (ses
->capabilities
& CAP_STATUS32
) {
3581 pSMB
->hdr
.Flags2
|= SMBFLG2_ERR_STATUS
;
3583 if (ses
->capabilities
& CAP_DFS
) {
3584 pSMB
->hdr
.Flags2
|= SMBFLG2_DFS
;
3587 if (ses
->capabilities
& CAP_UNICODE
) {
3588 pSMB
->hdr
.Flags2
|= SMBFLG2_UNICODE
;
3590 cifsConvertToUCS((__le16
*) pSMB
->RequestFileName
,
3591 searchName
, PATH_MAX
, nls_codepage
, remap
);
3592 name_len
++; /* trailing null */
3594 } else { /* BB improve the check for buffer overruns BB */
3595 name_len
= strnlen(searchName
, PATH_MAX
);
3596 name_len
++; /* trailing null */
3597 strncpy(pSMB
->RequestFileName
, searchName
, name_len
);
3600 params
= 2 /* level */ + name_len
/*includes null */ ;
3601 pSMB
->TotalDataCount
= 0;
3602 pSMB
->DataCount
= 0;
3603 pSMB
->DataOffset
= 0;
3604 pSMB
->MaxParameterCount
= 0;
3605 pSMB
->MaxDataCount
= cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
3606 pSMB
->MaxSetupCount
= 0;
3610 pSMB
->Reserved2
= 0;
3611 pSMB
->ParameterOffset
= cpu_to_le16(offsetof(
3612 struct smb_com_transaction2_get_dfs_refer_req
, MaxReferralLevel
) - 4);
3613 pSMB
->SetupCount
= 1;
3614 pSMB
->Reserved3
= 0;
3615 pSMB
->SubCommand
= cpu_to_le16(TRANS2_GET_DFS_REFERRAL
);
3616 byte_count
= params
+ 3 /* pad */ ;
3617 pSMB
->ParameterCount
= cpu_to_le16(params
);
3618 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
3619 pSMB
->MaxReferralLevel
= cpu_to_le16(3);
3620 pSMB
->hdr
.smb_buf_length
+= byte_count
;
3621 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
3623 rc
= SendReceive(xid
, ses
, (struct smb_hdr
*) pSMB
,
3624 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
3626 cFYI(1, ("Send error in GetDFSRefer = %d", rc
));
3627 } else { /* decode response */
3628 /* BB Add logic to parse referrals here */
3629 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
3631 if (rc
|| (pSMBr
->ByteCount
< 17)) /* BB also check enough total bytes returned */
3632 rc
= -EIO
; /* bad smb */
3634 __u16 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
3635 __u16 data_count
= le16_to_cpu(pSMBr
->t2
.DataCount
);
3638 ("Decoding GetDFSRefer response. BCC: %d Offset %d",
3639 pSMBr
->ByteCount
, data_offset
));
3641 (struct dfs_referral_level_3
*)
3642 (8 /* sizeof start of data block */ +
3644 (char *) &pSMBr
->hdr
.Protocol
);
3645 cFYI(1,("num_referrals: %d dfs flags: 0x%x ... \nfor referral one refer size: 0x%x srv type: 0x%x refer flags: 0x%x ttl: 0x%x",
3646 le16_to_cpu(pSMBr
->NumberOfReferrals
),le16_to_cpu(pSMBr
->DFSFlags
), le16_to_cpu(referrals
->ReferralSize
),le16_to_cpu(referrals
->ServerType
),le16_to_cpu(referrals
->ReferralFlags
),le16_to_cpu(referrals
->TimeToLive
)));
3647 /* BB This field is actually two bytes in from start of
3648 data block so we could do safety check that DataBlock
3649 begins at address of pSMBr->NumberOfReferrals */
3650 *number_of_UNC_in_array
= le16_to_cpu(pSMBr
->NumberOfReferrals
);
3652 /* BB Fix below so can return more than one referral */
3653 if(*number_of_UNC_in_array
> 1)
3654 *number_of_UNC_in_array
= 1;
3656 /* get the length of the strings describing refs */
3658 for(i
=0;i
<*number_of_UNC_in_array
;i
++) {
3659 /* make sure that DfsPathOffset not past end */
3660 __u16 offset
= le16_to_cpu(referrals
->DfsPathOffset
);
3661 if (offset
> data_count
) {
3662 /* if invalid referral, stop here and do
3663 not try to copy any more */
3664 *number_of_UNC_in_array
= i
;
3667 temp
= ((char *)referrals
) + offset
;
3669 if (pSMBr
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
3670 name_len
+= UniStrnlen((wchar_t *)temp
,data_count
);
3672 name_len
+= strnlen(temp
,data_count
);
3675 /* BB add check that referral pointer does not fall off end PDU */
3678 /* BB add check for name_len bigger than bcc */
3680 kmalloc(name_len
+1+ (*number_of_UNC_in_array
),GFP_KERNEL
);
3681 if(*targetUNCs
== NULL
) {
3685 /* copy the ref strings */
3687 (struct dfs_referral_level_3
*)
3688 (8 /* sizeof data hdr */ +
3690 (char *) &pSMBr
->hdr
.Protocol
);
3692 for(i
=0;i
<*number_of_UNC_in_array
;i
++) {
3693 temp
= ((char *)referrals
) + le16_to_cpu(referrals
->DfsPathOffset
);
3694 if (pSMBr
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
3695 cifs_strfromUCS_le(*targetUNCs
,
3696 (__le16
*) temp
, name_len
, nls_codepage
);
3698 strncpy(*targetUNCs
,temp
,name_len
);
3700 /* BB update target_uncs pointers */
3710 cifs_buf_release(pSMB
);
3718 /* Query File System Info such as free space to old servers such as Win 9x */
3720 SMBOldQFSInfo(const int xid
, struct cifsTconInfo
*tcon
, struct kstatfs
*FSData
)
3722 /* level 0x01 SMB_QUERY_FILE_SYSTEM_INFO */
3723 TRANSACTION2_QFSI_REQ
*pSMB
= NULL
;
3724 TRANSACTION2_QFSI_RSP
*pSMBr
= NULL
;
3725 FILE_SYSTEM_ALLOC_INFO
*response_data
;
3727 int bytes_returned
= 0;
3728 __u16 params
, byte_count
;
3730 cFYI(1, ("OldQFSInfo"));
3732 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
3736 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
3741 params
= 2; /* level */
3742 pSMB
->TotalDataCount
= 0;
3743 pSMB
->MaxParameterCount
= cpu_to_le16(2);
3744 pSMB
->MaxDataCount
= cpu_to_le16(1000);
3745 pSMB
->MaxSetupCount
= 0;
3749 pSMB
->Reserved2
= 0;
3750 byte_count
= params
+ 1 /* pad */ ;
3751 pSMB
->TotalParameterCount
= cpu_to_le16(params
);
3752 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
3753 pSMB
->ParameterOffset
= cpu_to_le16(offsetof(
3754 struct smb_com_transaction2_qfsi_req
, InformationLevel
) - 4);
3755 pSMB
->DataCount
= 0;
3756 pSMB
->DataOffset
= 0;
3757 pSMB
->SetupCount
= 1;
3758 pSMB
->Reserved3
= 0;
3759 pSMB
->SubCommand
= cpu_to_le16(TRANS2_QUERY_FS_INFORMATION
);
3760 pSMB
->InformationLevel
= cpu_to_le16(SMB_INFO_ALLOCATION
);
3761 pSMB
->hdr
.smb_buf_length
+= byte_count
;
3762 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
3764 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
3765 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
3767 cFYI(1, ("Send error in QFSInfo = %d", rc
));
3768 } else { /* decode response */
3769 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
3771 if (rc
|| (pSMBr
->ByteCount
< 18))
3772 rc
= -EIO
; /* bad smb */
3774 __u16 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
3775 cFYI(1,("qfsinf resp BCC: %d Offset %d",
3776 pSMBr
->ByteCount
, data_offset
));
3779 (FILE_SYSTEM_ALLOC_INFO
*)
3780 (((char *) &pSMBr
->hdr
.Protocol
) + data_offset
);
3782 le16_to_cpu(response_data
->BytesPerSector
) *
3783 le32_to_cpu(response_data
->
3784 SectorsPerAllocationUnit
);
3786 le32_to_cpu(response_data
->TotalAllocationUnits
);
3787 FSData
->f_bfree
= FSData
->f_bavail
=
3788 le32_to_cpu(response_data
->FreeAllocationUnits
);
3790 ("Blocks: %lld Free: %lld Block size %ld",
3791 (unsigned long long)FSData
->f_blocks
,
3792 (unsigned long long)FSData
->f_bfree
,
3796 cifs_buf_release(pSMB
);
3799 goto oldQFSInfoRetry
;
3805 CIFSSMBQFSInfo(const int xid
, struct cifsTconInfo
*tcon
, struct kstatfs
*FSData
)
3807 /* level 0x103 SMB_QUERY_FILE_SYSTEM_INFO */
3808 TRANSACTION2_QFSI_REQ
*pSMB
= NULL
;
3809 TRANSACTION2_QFSI_RSP
*pSMBr
= NULL
;
3810 FILE_SYSTEM_INFO
*response_data
;
3812 int bytes_returned
= 0;
3813 __u16 params
, byte_count
;
3815 cFYI(1, ("In QFSInfo"));
3817 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
3822 params
= 2; /* level */
3823 pSMB
->TotalDataCount
= 0;
3824 pSMB
->MaxParameterCount
= cpu_to_le16(2);
3825 pSMB
->MaxDataCount
= cpu_to_le16(1000);
3826 pSMB
->MaxSetupCount
= 0;
3830 pSMB
->Reserved2
= 0;
3831 byte_count
= params
+ 1 /* pad */ ;
3832 pSMB
->TotalParameterCount
= cpu_to_le16(params
);
3833 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
3834 pSMB
->ParameterOffset
= cpu_to_le16(offsetof(
3835 struct smb_com_transaction2_qfsi_req
, InformationLevel
) - 4);
3836 pSMB
->DataCount
= 0;
3837 pSMB
->DataOffset
= 0;
3838 pSMB
->SetupCount
= 1;
3839 pSMB
->Reserved3
= 0;
3840 pSMB
->SubCommand
= cpu_to_le16(TRANS2_QUERY_FS_INFORMATION
);
3841 pSMB
->InformationLevel
= cpu_to_le16(SMB_QUERY_FS_SIZE_INFO
);
3842 pSMB
->hdr
.smb_buf_length
+= byte_count
;
3843 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
3845 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
3846 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
3848 cFYI(1, ("Send error in QFSInfo = %d", rc
));
3849 } else { /* decode response */
3850 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
3852 if (rc
|| (pSMBr
->ByteCount
< 24))
3853 rc
= -EIO
; /* bad smb */
3855 __u16 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
3859 *) (((char *) &pSMBr
->hdr
.Protocol
) +
3862 le32_to_cpu(response_data
->BytesPerSector
) *
3863 le32_to_cpu(response_data
->
3864 SectorsPerAllocationUnit
);
3866 le64_to_cpu(response_data
->TotalAllocationUnits
);
3867 FSData
->f_bfree
= FSData
->f_bavail
=
3868 le64_to_cpu(response_data
->FreeAllocationUnits
);
3870 ("Blocks: %lld Free: %lld Block size %ld",
3871 (unsigned long long)FSData
->f_blocks
,
3872 (unsigned long long)FSData
->f_bfree
,
3876 cifs_buf_release(pSMB
);
3885 CIFSSMBQFSAttributeInfo(const int xid
, struct cifsTconInfo
*tcon
)
3887 /* level 0x105 SMB_QUERY_FILE_SYSTEM_INFO */
3888 TRANSACTION2_QFSI_REQ
*pSMB
= NULL
;
3889 TRANSACTION2_QFSI_RSP
*pSMBr
= NULL
;
3890 FILE_SYSTEM_ATTRIBUTE_INFO
*response_data
;
3892 int bytes_returned
= 0;
3893 __u16 params
, byte_count
;
3895 cFYI(1, ("In QFSAttributeInfo"));
3897 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
3902 params
= 2; /* level */
3903 pSMB
->TotalDataCount
= 0;
3904 pSMB
->MaxParameterCount
= cpu_to_le16(2);
3905 pSMB
->MaxDataCount
= cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
3906 pSMB
->MaxSetupCount
= 0;
3910 pSMB
->Reserved2
= 0;
3911 byte_count
= params
+ 1 /* pad */ ;
3912 pSMB
->TotalParameterCount
= cpu_to_le16(params
);
3913 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
3914 pSMB
->ParameterOffset
= cpu_to_le16(offsetof(
3915 struct smb_com_transaction2_qfsi_req
, InformationLevel
) - 4);
3916 pSMB
->DataCount
= 0;
3917 pSMB
->DataOffset
= 0;
3918 pSMB
->SetupCount
= 1;
3919 pSMB
->Reserved3
= 0;
3920 pSMB
->SubCommand
= cpu_to_le16(TRANS2_QUERY_FS_INFORMATION
);
3921 pSMB
->InformationLevel
= cpu_to_le16(SMB_QUERY_FS_ATTRIBUTE_INFO
);
3922 pSMB
->hdr
.smb_buf_length
+= byte_count
;
3923 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
3925 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
3926 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
3928 cERROR(1, ("Send error in QFSAttributeInfo = %d", rc
));
3929 } else { /* decode response */
3930 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
3932 if (rc
|| (pSMBr
->ByteCount
< 13)) { /* BB also check enough bytes returned */
3933 rc
= -EIO
; /* bad smb */
3935 __u16 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
3937 (FILE_SYSTEM_ATTRIBUTE_INFO
3938 *) (((char *) &pSMBr
->hdr
.Protocol
) +
3940 memcpy(&tcon
->fsAttrInfo
, response_data
,
3941 sizeof (FILE_SYSTEM_ATTRIBUTE_INFO
));
3944 cifs_buf_release(pSMB
);
3947 goto QFSAttributeRetry
;
3953 CIFSSMBQFSDeviceInfo(const int xid
, struct cifsTconInfo
*tcon
)
3955 /* level 0x104 SMB_QUERY_FILE_SYSTEM_INFO */
3956 TRANSACTION2_QFSI_REQ
*pSMB
= NULL
;
3957 TRANSACTION2_QFSI_RSP
*pSMBr
= NULL
;
3958 FILE_SYSTEM_DEVICE_INFO
*response_data
;
3960 int bytes_returned
= 0;
3961 __u16 params
, byte_count
;
3963 cFYI(1, ("In QFSDeviceInfo"));
3965 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
3970 params
= 2; /* level */
3971 pSMB
->TotalDataCount
= 0;
3972 pSMB
->MaxParameterCount
= cpu_to_le16(2);
3973 pSMB
->MaxDataCount
= cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
3974 pSMB
->MaxSetupCount
= 0;
3978 pSMB
->Reserved2
= 0;
3979 byte_count
= params
+ 1 /* pad */ ;
3980 pSMB
->TotalParameterCount
= cpu_to_le16(params
);
3981 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
3982 pSMB
->ParameterOffset
= cpu_to_le16(offsetof(
3983 struct smb_com_transaction2_qfsi_req
, InformationLevel
) - 4);
3985 pSMB
->DataCount
= 0;
3986 pSMB
->DataOffset
= 0;
3987 pSMB
->SetupCount
= 1;
3988 pSMB
->Reserved3
= 0;
3989 pSMB
->SubCommand
= cpu_to_le16(TRANS2_QUERY_FS_INFORMATION
);
3990 pSMB
->InformationLevel
= cpu_to_le16(SMB_QUERY_FS_DEVICE_INFO
);
3991 pSMB
->hdr
.smb_buf_length
+= byte_count
;
3992 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
3994 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
3995 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
3997 cFYI(1, ("Send error in QFSDeviceInfo = %d", rc
));
3998 } else { /* decode response */
3999 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
4001 if (rc
|| (pSMBr
->ByteCount
< sizeof (FILE_SYSTEM_DEVICE_INFO
)))
4002 rc
= -EIO
; /* bad smb */
4004 __u16 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
4006 (FILE_SYSTEM_DEVICE_INFO
*)
4007 (((char *) &pSMBr
->hdr
.Protocol
) +
4009 memcpy(&tcon
->fsDevInfo
, response_data
,
4010 sizeof (FILE_SYSTEM_DEVICE_INFO
));
4013 cifs_buf_release(pSMB
);
4016 goto QFSDeviceRetry
;
4022 CIFSSMBQFSUnixInfo(const int xid
, struct cifsTconInfo
*tcon
)
4024 /* level 0x200 SMB_QUERY_CIFS_UNIX_INFO */
4025 TRANSACTION2_QFSI_REQ
*pSMB
= NULL
;
4026 TRANSACTION2_QFSI_RSP
*pSMBr
= NULL
;
4027 FILE_SYSTEM_UNIX_INFO
*response_data
;
4029 int bytes_returned
= 0;
4030 __u16 params
, byte_count
;
4032 cFYI(1, ("In QFSUnixInfo"));
4034 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
4039 params
= 2; /* level */
4040 pSMB
->TotalDataCount
= 0;
4041 pSMB
->DataCount
= 0;
4042 pSMB
->DataOffset
= 0;
4043 pSMB
->MaxParameterCount
= cpu_to_le16(2);
4044 pSMB
->MaxDataCount
= cpu_to_le16(100); /* BB find exact max SMB PDU from sess structure BB */
4045 pSMB
->MaxSetupCount
= 0;
4049 pSMB
->Reserved2
= 0;
4050 byte_count
= params
+ 1 /* pad */ ;
4051 pSMB
->ParameterCount
= cpu_to_le16(params
);
4052 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
4053 pSMB
->ParameterOffset
= cpu_to_le16(offsetof(struct
4054 smb_com_transaction2_qfsi_req
, InformationLevel
) - 4);
4055 pSMB
->SetupCount
= 1;
4056 pSMB
->Reserved3
= 0;
4057 pSMB
->SubCommand
= cpu_to_le16(TRANS2_QUERY_FS_INFORMATION
);
4058 pSMB
->InformationLevel
= cpu_to_le16(SMB_QUERY_CIFS_UNIX_INFO
);
4059 pSMB
->hdr
.smb_buf_length
+= byte_count
;
4060 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
4062 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
4063 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
4065 cERROR(1, ("Send error in QFSUnixInfo = %d", rc
));
4066 } else { /* decode response */
4067 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
4069 if (rc
|| (pSMBr
->ByteCount
< 13)) {
4070 rc
= -EIO
; /* bad smb */
4072 __u16 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
4074 (FILE_SYSTEM_UNIX_INFO
4075 *) (((char *) &pSMBr
->hdr
.Protocol
) +
4077 memcpy(&tcon
->fsUnixInfo
, response_data
,
4078 sizeof (FILE_SYSTEM_UNIX_INFO
));
4081 cifs_buf_release(pSMB
);
4091 CIFSSMBSetFSUnixInfo(const int xid
, struct cifsTconInfo
*tcon
, __u64 cap
)
4093 /* level 0x200 SMB_SET_CIFS_UNIX_INFO */
4094 TRANSACTION2_SETFSI_REQ
*pSMB
= NULL
;
4095 TRANSACTION2_SETFSI_RSP
*pSMBr
= NULL
;
4097 int bytes_returned
= 0;
4098 __u16 params
, param_offset
, offset
, byte_count
;
4100 cFYI(1, ("In SETFSUnixInfo"));
4102 /* BB switch to small buf init to save memory */
4103 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
4108 params
= 4; /* 2 bytes zero followed by info level. */
4109 pSMB
->MaxSetupCount
= 0;
4113 pSMB
->Reserved2
= 0;
4114 param_offset
= offsetof(struct smb_com_transaction2_setfsi_req
, FileNum
) - 4;
4115 offset
= param_offset
+ params
;
4117 pSMB
->MaxParameterCount
= cpu_to_le16(4);
4118 pSMB
->MaxDataCount
= cpu_to_le16(100); /* BB find exact max SMB PDU from sess structure BB */
4119 pSMB
->SetupCount
= 1;
4120 pSMB
->Reserved3
= 0;
4121 pSMB
->SubCommand
= cpu_to_le16(TRANS2_SET_FS_INFORMATION
);
4122 byte_count
= 1 /* pad */ + params
+ 12;
4124 pSMB
->DataCount
= cpu_to_le16(12);
4125 pSMB
->ParameterCount
= cpu_to_le16(params
);
4126 pSMB
->TotalDataCount
= pSMB
->DataCount
;
4127 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
4128 pSMB
->ParameterOffset
= cpu_to_le16(param_offset
);
4129 pSMB
->DataOffset
= cpu_to_le16(offset
);
4133 pSMB
->InformationLevel
= cpu_to_le16(SMB_SET_CIFS_UNIX_INFO
);
4136 pSMB
->ClientUnixMajor
= cpu_to_le16(CIFS_UNIX_MAJOR_VERSION
);
4137 pSMB
->ClientUnixMinor
= cpu_to_le16(CIFS_UNIX_MINOR_VERSION
);
4138 pSMB
->ClientUnixCap
= cpu_to_le64(cap
);
4140 pSMB
->hdr
.smb_buf_length
+= byte_count
;
4141 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
4143 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
4144 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
4146 cERROR(1, ("Send error in SETFSUnixInfo = %d", rc
));
4147 } else { /* decode response */
4148 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
4150 rc
= -EIO
; /* bad smb */
4153 cifs_buf_release(pSMB
);
4156 goto SETFSUnixRetry
;
4164 CIFSSMBQFSPosixInfo(const int xid
, struct cifsTconInfo
*tcon
,
4165 struct kstatfs
*FSData
)
4167 /* level 0x201 SMB_QUERY_CIFS_POSIX_INFO */
4168 TRANSACTION2_QFSI_REQ
*pSMB
= NULL
;
4169 TRANSACTION2_QFSI_RSP
*pSMBr
= NULL
;
4170 FILE_SYSTEM_POSIX_INFO
*response_data
;
4172 int bytes_returned
= 0;
4173 __u16 params
, byte_count
;
4175 cFYI(1, ("In QFSPosixInfo"));
4177 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
4182 params
= 2; /* level */
4183 pSMB
->TotalDataCount
= 0;
4184 pSMB
->DataCount
= 0;
4185 pSMB
->DataOffset
= 0;
4186 pSMB
->MaxParameterCount
= cpu_to_le16(2);
4187 pSMB
->MaxDataCount
= cpu_to_le16(100); /* BB find exact max SMB PDU from sess structure BB */
4188 pSMB
->MaxSetupCount
= 0;
4192 pSMB
->Reserved2
= 0;
4193 byte_count
= params
+ 1 /* pad */ ;
4194 pSMB
->ParameterCount
= cpu_to_le16(params
);
4195 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
4196 pSMB
->ParameterOffset
= cpu_to_le16(offsetof(struct
4197 smb_com_transaction2_qfsi_req
, InformationLevel
) - 4);
4198 pSMB
->SetupCount
= 1;
4199 pSMB
->Reserved3
= 0;
4200 pSMB
->SubCommand
= cpu_to_le16(TRANS2_QUERY_FS_INFORMATION
);
4201 pSMB
->InformationLevel
= cpu_to_le16(SMB_QUERY_POSIX_FS_INFO
);
4202 pSMB
->hdr
.smb_buf_length
+= byte_count
;
4203 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
4205 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
4206 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
4208 cFYI(1, ("Send error in QFSUnixInfo = %d", rc
));
4209 } else { /* decode response */
4210 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
4212 if (rc
|| (pSMBr
->ByteCount
< 13)) {
4213 rc
= -EIO
; /* bad smb */
4215 __u16 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
4217 (FILE_SYSTEM_POSIX_INFO
4218 *) (((char *) &pSMBr
->hdr
.Protocol
) +
4221 le32_to_cpu(response_data
->BlockSize
);
4223 le64_to_cpu(response_data
->TotalBlocks
);
4225 le64_to_cpu(response_data
->BlocksAvail
);
4226 if(response_data
->UserBlocksAvail
== cpu_to_le64(-1)) {
4227 FSData
->f_bavail
= FSData
->f_bfree
;
4230 le64_to_cpu(response_data
->UserBlocksAvail
);
4232 if(response_data
->TotalFileNodes
!= cpu_to_le64(-1))
4234 le64_to_cpu(response_data
->TotalFileNodes
);
4235 if(response_data
->FreeFileNodes
!= cpu_to_le64(-1))
4237 le64_to_cpu(response_data
->FreeFileNodes
);
4240 cifs_buf_release(pSMB
);
4249 /* We can not use write of zero bytes trick to
4250 set file size due to need for large file support. Also note that
4251 this SetPathInfo is preferred to SetFileInfo based method in next
4252 routine which is only needed to work around a sharing violation bug
4253 in Samba which this routine can run into */
4256 CIFSSMBSetEOF(const int xid
, struct cifsTconInfo
*tcon
, const char *fileName
,
4257 __u64 size
, int SetAllocation
,
4258 const struct nls_table
*nls_codepage
, int remap
)
4260 struct smb_com_transaction2_spi_req
*pSMB
= NULL
;
4261 struct smb_com_transaction2_spi_rsp
*pSMBr
= NULL
;
4262 struct file_end_of_file_info
*parm_data
;
4265 int bytes_returned
= 0;
4266 __u16 params
, byte_count
, data_count
, param_offset
, offset
;
4268 cFYI(1, ("In SetEOF"));
4270 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
4275 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
4277 cifsConvertToUCS((__le16
*) pSMB
->FileName
, fileName
,
4278 PATH_MAX
, nls_codepage
, remap
);
4279 name_len
++; /* trailing null */
4281 } else { /* BB improve the check for buffer overruns BB */
4282 name_len
= strnlen(fileName
, PATH_MAX
);
4283 name_len
++; /* trailing null */
4284 strncpy(pSMB
->FileName
, fileName
, name_len
);
4286 params
= 6 + name_len
;
4287 data_count
= sizeof (struct file_end_of_file_info
);
4288 pSMB
->MaxParameterCount
= cpu_to_le16(2);
4289 pSMB
->MaxDataCount
= cpu_to_le16(4100);
4290 pSMB
->MaxSetupCount
= 0;
4294 pSMB
->Reserved2
= 0;
4295 param_offset
= offsetof(struct smb_com_transaction2_spi_req
,
4296 InformationLevel
) - 4;
4297 offset
= param_offset
+ params
;
4299 if (tcon
->ses
->capabilities
& CAP_INFOLEVEL_PASSTHRU
)
4300 pSMB
->InformationLevel
=
4301 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2
);
4303 pSMB
->InformationLevel
=
4304 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO
);
4305 } else /* Set File Size */ {
4306 if (tcon
->ses
->capabilities
& CAP_INFOLEVEL_PASSTHRU
)
4307 pSMB
->InformationLevel
=
4308 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO2
);
4310 pSMB
->InformationLevel
=
4311 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO
);
4315 (struct file_end_of_file_info
*) (((char *) &pSMB
->hdr
.Protocol
) +
4317 pSMB
->ParameterOffset
= cpu_to_le16(param_offset
);
4318 pSMB
->DataOffset
= cpu_to_le16(offset
);
4319 pSMB
->SetupCount
= 1;
4320 pSMB
->Reserved3
= 0;
4321 pSMB
->SubCommand
= cpu_to_le16(TRANS2_SET_PATH_INFORMATION
);
4322 byte_count
= 3 /* pad */ + params
+ data_count
;
4323 pSMB
->DataCount
= cpu_to_le16(data_count
);
4324 pSMB
->TotalDataCount
= pSMB
->DataCount
;
4325 pSMB
->ParameterCount
= cpu_to_le16(params
);
4326 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
4327 pSMB
->Reserved4
= 0;
4328 pSMB
->hdr
.smb_buf_length
+= byte_count
;
4329 parm_data
->FileSize
= cpu_to_le64(size
);
4330 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
4331 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
4332 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
4334 cFYI(1, ("SetPathInfo (file size) returned %d", rc
));
4337 cifs_buf_release(pSMB
);
4346 CIFSSMBSetFileSize(const int xid
, struct cifsTconInfo
*tcon
, __u64 size
,
4347 __u16 fid
, __u32 pid_of_opener
, int SetAllocation
)
4349 struct smb_com_transaction2_sfi_req
*pSMB
= NULL
;
4350 struct smb_com_transaction2_sfi_rsp
*pSMBr
= NULL
;
4352 struct file_end_of_file_info
*parm_data
;
4354 int bytes_returned
= 0;
4355 __u16 params
, param_offset
, offset
, byte_count
, count
;
4357 cFYI(1, ("SetFileSize (via SetFileInfo) %lld",
4359 rc
= small_smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
);
4364 pSMBr
= (struct smb_com_transaction2_sfi_rsp
*)pSMB
;
4366 pSMB
->hdr
.Pid
= cpu_to_le16((__u16
)pid_of_opener
);
4367 pSMB
->hdr
.PidHigh
= cpu_to_le16((__u16
)(pid_of_opener
>> 16));
4370 pSMB
->MaxSetupCount
= 0;
4374 pSMB
->Reserved2
= 0;
4375 param_offset
= offsetof(struct smb_com_transaction2_sfi_req
, Fid
) - 4;
4376 offset
= param_offset
+ params
;
4378 data_offset
= (char *) (&pSMB
->hdr
.Protocol
) + offset
;
4380 count
= sizeof(struct file_end_of_file_info
);
4381 pSMB
->MaxParameterCount
= cpu_to_le16(2);
4382 pSMB
->MaxDataCount
= cpu_to_le16(1000); /* BB find max SMB PDU from sess */
4383 pSMB
->SetupCount
= 1;
4384 pSMB
->Reserved3
= 0;
4385 pSMB
->SubCommand
= cpu_to_le16(TRANS2_SET_FILE_INFORMATION
);
4386 byte_count
= 3 /* pad */ + params
+ count
;
4387 pSMB
->DataCount
= cpu_to_le16(count
);
4388 pSMB
->ParameterCount
= cpu_to_le16(params
);
4389 pSMB
->TotalDataCount
= pSMB
->DataCount
;
4390 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
4391 pSMB
->ParameterOffset
= cpu_to_le16(param_offset
);
4393 (struct file_end_of_file_info
*) (((char *) &pSMB
->hdr
.Protocol
) +
4395 pSMB
->DataOffset
= cpu_to_le16(offset
);
4396 parm_data
->FileSize
= cpu_to_le64(size
);
4399 if (tcon
->ses
->capabilities
& CAP_INFOLEVEL_PASSTHRU
)
4400 pSMB
->InformationLevel
=
4401 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2
);
4403 pSMB
->InformationLevel
=
4404 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO
);
4405 } else /* Set File Size */ {
4406 if (tcon
->ses
->capabilities
& CAP_INFOLEVEL_PASSTHRU
)
4407 pSMB
->InformationLevel
=
4408 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO2
);
4410 pSMB
->InformationLevel
=
4411 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO
);
4413 pSMB
->Reserved4
= 0;
4414 pSMB
->hdr
.smb_buf_length
+= byte_count
;
4415 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
4416 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
4417 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
4420 ("Send error in SetFileInfo (SetFileSize) = %d",
4425 cifs_small_buf_release(pSMB
);
4427 /* Note: On -EAGAIN error only caller can retry on handle based calls
4428 since file handle passed in no longer valid */
4433 /* Some legacy servers such as NT4 require that the file times be set on
4434 an open handle, rather than by pathname - this is awkward due to
4435 potential access conflicts on the open, but it is unavoidable for these
4436 old servers since the only other choice is to go from 100 nanosecond DCE
4437 time and resort to the original setpathinfo level which takes the ancient
4438 DOS time format with 2 second granularity */
4440 CIFSSMBSetFileTimes(const int xid
, struct cifsTconInfo
*tcon
, const FILE_BASIC_INFO
* data
,
4443 struct smb_com_transaction2_sfi_req
*pSMB
= NULL
;
4444 struct smb_com_transaction2_sfi_rsp
*pSMBr
= NULL
;
4447 int bytes_returned
= 0;
4448 __u16 params
, param_offset
, offset
, byte_count
, count
;
4450 cFYI(1, ("Set Times (via SetFileInfo)"));
4451 rc
= small_smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
);
4456 pSMBr
= (struct smb_com_transaction2_sfi_rsp
*)pSMB
;
4458 /* At this point there is no need to override the current pid
4459 with the pid of the opener, but that could change if we someday
4460 use an existing handle (rather than opening one on the fly) */
4461 /* pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
4462 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));*/
4465 pSMB
->MaxSetupCount
= 0;
4469 pSMB
->Reserved2
= 0;
4470 param_offset
= offsetof(struct smb_com_transaction2_sfi_req
, Fid
) - 4;
4471 offset
= param_offset
+ params
;
4473 data_offset
= (char *) (&pSMB
->hdr
.Protocol
) + offset
;
4475 count
= sizeof (FILE_BASIC_INFO
);
4476 pSMB
->MaxParameterCount
= cpu_to_le16(2);
4477 pSMB
->MaxDataCount
= cpu_to_le16(1000); /* BB find max SMB PDU from sess */
4478 pSMB
->SetupCount
= 1;
4479 pSMB
->Reserved3
= 0;
4480 pSMB
->SubCommand
= cpu_to_le16(TRANS2_SET_FILE_INFORMATION
);
4481 byte_count
= 3 /* pad */ + params
+ count
;
4482 pSMB
->DataCount
= cpu_to_le16(count
);
4483 pSMB
->ParameterCount
= cpu_to_le16(params
);
4484 pSMB
->TotalDataCount
= pSMB
->DataCount
;
4485 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
4486 pSMB
->ParameterOffset
= cpu_to_le16(param_offset
);
4487 pSMB
->DataOffset
= cpu_to_le16(offset
);
4489 if (tcon
->ses
->capabilities
& CAP_INFOLEVEL_PASSTHRU
)
4490 pSMB
->InformationLevel
= cpu_to_le16(SMB_SET_FILE_BASIC_INFO2
);
4492 pSMB
->InformationLevel
= cpu_to_le16(SMB_SET_FILE_BASIC_INFO
);
4493 pSMB
->Reserved4
= 0;
4494 pSMB
->hdr
.smb_buf_length
+= byte_count
;
4495 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
4496 memcpy(data_offset
,data
,sizeof(FILE_BASIC_INFO
));
4497 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
4498 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
4500 cFYI(1,("Send error in Set Time (SetFileInfo) = %d",rc
));
4503 cifs_small_buf_release(pSMB
);
4505 /* Note: On -EAGAIN error only caller can retry on handle based calls
4506 since file handle passed in no longer valid */
4513 CIFSSMBSetTimes(const int xid
, struct cifsTconInfo
*tcon
, const char *fileName
,
4514 const FILE_BASIC_INFO
* data
,
4515 const struct nls_table
*nls_codepage
, int remap
)
4517 TRANSACTION2_SPI_REQ
*pSMB
= NULL
;
4518 TRANSACTION2_SPI_RSP
*pSMBr
= NULL
;
4521 int bytes_returned
= 0;
4523 __u16 params
, param_offset
, offset
, byte_count
, count
;
4525 cFYI(1, ("In SetTimes"));
4528 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
4533 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
4535 cifsConvertToUCS((__le16
*) pSMB
->FileName
, fileName
,
4536 PATH_MAX
, nls_codepage
, remap
);
4537 name_len
++; /* trailing null */
4539 } else { /* BB improve the check for buffer overruns BB */
4540 name_len
= strnlen(fileName
, PATH_MAX
);
4541 name_len
++; /* trailing null */
4542 strncpy(pSMB
->FileName
, fileName
, name_len
);
4545 params
= 6 + name_len
;
4546 count
= sizeof (FILE_BASIC_INFO
);
4547 pSMB
->MaxParameterCount
= cpu_to_le16(2);
4548 pSMB
->MaxDataCount
= cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
4549 pSMB
->MaxSetupCount
= 0;
4553 pSMB
->Reserved2
= 0;
4554 param_offset
= offsetof(struct smb_com_transaction2_spi_req
,
4555 InformationLevel
) - 4;
4556 offset
= param_offset
+ params
;
4557 data_offset
= (char *) (&pSMB
->hdr
.Protocol
) + offset
;
4558 pSMB
->ParameterOffset
= cpu_to_le16(param_offset
);
4559 pSMB
->DataOffset
= cpu_to_le16(offset
);
4560 pSMB
->SetupCount
= 1;
4561 pSMB
->Reserved3
= 0;
4562 pSMB
->SubCommand
= cpu_to_le16(TRANS2_SET_PATH_INFORMATION
);
4563 byte_count
= 3 /* pad */ + params
+ count
;
4565 pSMB
->DataCount
= cpu_to_le16(count
);
4566 pSMB
->ParameterCount
= cpu_to_le16(params
);
4567 pSMB
->TotalDataCount
= pSMB
->DataCount
;
4568 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
4569 if (tcon
->ses
->capabilities
& CAP_INFOLEVEL_PASSTHRU
)
4570 pSMB
->InformationLevel
= cpu_to_le16(SMB_SET_FILE_BASIC_INFO2
);
4572 pSMB
->InformationLevel
= cpu_to_le16(SMB_SET_FILE_BASIC_INFO
);
4573 pSMB
->Reserved4
= 0;
4574 pSMB
->hdr
.smb_buf_length
+= byte_count
;
4575 memcpy(data_offset
, data
, sizeof (FILE_BASIC_INFO
));
4576 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
4577 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
4578 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
4580 cFYI(1, ("SetPathInfo (times) returned %d", rc
));
4583 cifs_buf_release(pSMB
);
4591 /* Can not be used to set time stamps yet (due to old DOS time format) */
4592 /* Can be used to set attributes */
4593 #if 0 /* Possibly not needed - since it turns out that strangely NT4 has a bug
4594 handling it anyway and NT4 was what we thought it would be needed for
4595 Do not delete it until we prove whether needed for Win9x though */
4597 CIFSSMBSetAttrLegacy(int xid
, struct cifsTconInfo
*tcon
, char *fileName
,
4598 __u16 dos_attrs
, const struct nls_table
*nls_codepage
)
4600 SETATTR_REQ
*pSMB
= NULL
;
4601 SETATTR_RSP
*pSMBr
= NULL
;
4606 cFYI(1, ("In SetAttrLegacy"));
4609 rc
= smb_init(SMB_COM_SETATTR
, 8, tcon
, (void **) &pSMB
,
4614 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
4616 ConvertToUCS((__le16
*) pSMB
->fileName
, fileName
,
4617 PATH_MAX
, nls_codepage
);
4618 name_len
++; /* trailing null */
4620 } else { /* BB improve the check for buffer overruns BB */
4621 name_len
= strnlen(fileName
, PATH_MAX
);
4622 name_len
++; /* trailing null */
4623 strncpy(pSMB
->fileName
, fileName
, name_len
);
4625 pSMB
->attr
= cpu_to_le16(dos_attrs
);
4626 pSMB
->BufferFormat
= 0x04;
4627 pSMB
->hdr
.smb_buf_length
+= name_len
+ 1;
4628 pSMB
->ByteCount
= cpu_to_le16(name_len
+ 1);
4629 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
4630 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
4632 cFYI(1, ("Error in LegacySetAttr = %d", rc
));
4635 cifs_buf_release(pSMB
);
4638 goto SetAttrLgcyRetry
;
4642 #endif /* temporarily unneeded SetAttr legacy function */
4645 CIFSSMBUnixSetPerms(const int xid
, struct cifsTconInfo
*tcon
,
4646 char *fileName
, __u64 mode
, __u64 uid
, __u64 gid
,
4647 dev_t device
, const struct nls_table
*nls_codepage
,
4650 TRANSACTION2_SPI_REQ
*pSMB
= NULL
;
4651 TRANSACTION2_SPI_RSP
*pSMBr
= NULL
;
4654 int bytes_returned
= 0;
4655 FILE_UNIX_BASIC_INFO
*data_offset
;
4656 __u16 params
, param_offset
, offset
, count
, byte_count
;
4658 cFYI(1, ("In SetUID/GID/Mode"));
4660 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
4665 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
4667 cifsConvertToUCS((__le16
*) pSMB
->FileName
, fileName
,
4668 PATH_MAX
, nls_codepage
, remap
);
4669 name_len
++; /* trailing null */
4671 } else { /* BB improve the check for buffer overruns BB */
4672 name_len
= strnlen(fileName
, PATH_MAX
);
4673 name_len
++; /* trailing null */
4674 strncpy(pSMB
->FileName
, fileName
, name_len
);
4677 params
= 6 + name_len
;
4678 count
= sizeof (FILE_UNIX_BASIC_INFO
);
4679 pSMB
->MaxParameterCount
= cpu_to_le16(2);
4680 pSMB
->MaxDataCount
= cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
4681 pSMB
->MaxSetupCount
= 0;
4685 pSMB
->Reserved2
= 0;
4686 param_offset
= offsetof(struct smb_com_transaction2_spi_req
,
4687 InformationLevel
) - 4;
4688 offset
= param_offset
+ params
;
4690 (FILE_UNIX_BASIC_INFO
*) ((char *) &pSMB
->hdr
.Protocol
+
4692 memset(data_offset
, 0, count
);
4693 pSMB
->DataOffset
= cpu_to_le16(offset
);
4694 pSMB
->ParameterOffset
= cpu_to_le16(param_offset
);
4695 pSMB
->SetupCount
= 1;
4696 pSMB
->Reserved3
= 0;
4697 pSMB
->SubCommand
= cpu_to_le16(TRANS2_SET_PATH_INFORMATION
);
4698 byte_count
= 3 /* pad */ + params
+ count
;
4699 pSMB
->ParameterCount
= cpu_to_le16(params
);
4700 pSMB
->DataCount
= cpu_to_le16(count
);
4701 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
4702 pSMB
->TotalDataCount
= pSMB
->DataCount
;
4703 pSMB
->InformationLevel
= cpu_to_le16(SMB_SET_FILE_UNIX_BASIC
);
4704 pSMB
->Reserved4
= 0;
4705 pSMB
->hdr
.smb_buf_length
+= byte_count
;
4706 data_offset
->Uid
= cpu_to_le64(uid
);
4707 data_offset
->Gid
= cpu_to_le64(gid
);
4708 /* better to leave device as zero when it is */
4709 data_offset
->DevMajor
= cpu_to_le64(MAJOR(device
));
4710 data_offset
->DevMinor
= cpu_to_le64(MINOR(device
));
4711 data_offset
->Permissions
= cpu_to_le64(mode
);
4714 data_offset
->Type
= cpu_to_le32(UNIX_FILE
);
4715 else if(S_ISDIR(mode
))
4716 data_offset
->Type
= cpu_to_le32(UNIX_DIR
);
4717 else if(S_ISLNK(mode
))
4718 data_offset
->Type
= cpu_to_le32(UNIX_SYMLINK
);
4719 else if(S_ISCHR(mode
))
4720 data_offset
->Type
= cpu_to_le32(UNIX_CHARDEV
);
4721 else if(S_ISBLK(mode
))
4722 data_offset
->Type
= cpu_to_le32(UNIX_BLOCKDEV
);
4723 else if(S_ISFIFO(mode
))
4724 data_offset
->Type
= cpu_to_le32(UNIX_FIFO
);
4725 else if(S_ISSOCK(mode
))
4726 data_offset
->Type
= cpu_to_le32(UNIX_SOCKET
);
4729 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
4730 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
4731 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
4733 cFYI(1, ("SetPathInfo (perms) returned %d", rc
));
4737 cifs_buf_release(pSMB
);
4743 int CIFSSMBNotify(const int xid
, struct cifsTconInfo
*tcon
,
4744 const int notify_subdirs
, const __u16 netfid
,
4745 __u32 filter
, struct file
* pfile
, int multishot
,
4746 const struct nls_table
*nls_codepage
)
4749 struct smb_com_transaction_change_notify_req
* pSMB
= NULL
;
4750 struct smb_com_ntransaction_change_notify_rsp
* pSMBr
= NULL
;
4751 struct dir_notify_req
*dnotify_req
;
4754 cFYI(1, ("In CIFSSMBNotify for file handle %d",(int)netfid
));
4755 rc
= smb_init(SMB_COM_NT_TRANSACT
, 23, tcon
, (void **) &pSMB
,
4760 pSMB
->TotalParameterCount
= 0 ;
4761 pSMB
->TotalDataCount
= 0;
4762 pSMB
->MaxParameterCount
= cpu_to_le32(2);
4763 /* BB find exact data count max from sess structure BB */
4764 pSMB
->MaxDataCount
= 0; /* same in little endian or be */
4765 /* BB VERIFY verify which is correct for above BB */
4766 pSMB
->MaxDataCount
= cpu_to_le32((tcon
->ses
->server
->maxBuf
-
4767 MAX_CIFS_HDR_SIZE
) & 0xFFFFFF00);
4769 pSMB
->MaxSetupCount
= 4;
4771 pSMB
->ParameterOffset
= 0;
4772 pSMB
->DataCount
= 0;
4773 pSMB
->DataOffset
= 0;
4774 pSMB
->SetupCount
= 4; /* single byte does not need le conversion */
4775 pSMB
->SubCommand
= cpu_to_le16(NT_TRANSACT_NOTIFY_CHANGE
);
4776 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
4778 pSMB
->WatchTree
= 1; /* one byte - no le conversion needed */
4779 pSMB
->Reserved2
= 0;
4780 pSMB
->CompletionFilter
= cpu_to_le32(filter
);
4781 pSMB
->Fid
= netfid
; /* file handle always le */
4782 pSMB
->ByteCount
= 0;
4784 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
4785 (struct smb_hdr
*) pSMBr
, &bytes_returned
, -1);
4787 cFYI(1, ("Error in Notify = %d", rc
));
4789 /* Add file to outstanding requests */
4790 /* BB change to kmem cache alloc */
4791 dnotify_req
= (struct dir_notify_req
*) kmalloc(
4792 sizeof(struct dir_notify_req
),
4795 dnotify_req
->Pid
= pSMB
->hdr
.Pid
;
4796 dnotify_req
->PidHigh
= pSMB
->hdr
.PidHigh
;
4797 dnotify_req
->Mid
= pSMB
->hdr
.Mid
;
4798 dnotify_req
->Tid
= pSMB
->hdr
.Tid
;
4799 dnotify_req
->Uid
= pSMB
->hdr
.Uid
;
4800 dnotify_req
->netfid
= netfid
;
4801 dnotify_req
->pfile
= pfile
;
4802 dnotify_req
->filter
= filter
;
4803 dnotify_req
->multishot
= multishot
;
4804 spin_lock(&GlobalMid_Lock
);
4805 list_add_tail(&dnotify_req
->lhead
,
4806 &GlobalDnotifyReqList
);
4807 spin_unlock(&GlobalMid_Lock
);
4811 cifs_buf_release(pSMB
);
4814 #ifdef CONFIG_CIFS_XATTR
4816 CIFSSMBQAllEAs(const int xid
, struct cifsTconInfo
*tcon
,
4817 const unsigned char *searchName
,
4818 char * EAData
, size_t buf_size
,
4819 const struct nls_table
*nls_codepage
, int remap
)
4821 /* BB assumes one setup word */
4822 TRANSACTION2_QPI_REQ
*pSMB
= NULL
;
4823 TRANSACTION2_QPI_RSP
*pSMBr
= NULL
;
4827 struct fea
* temp_fea
;
4829 __u16 params
, byte_count
;
4831 cFYI(1, ("In Query All EAs path %s", searchName
));
4833 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
4838 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
4840 cifsConvertToUCS((__le16
*) pSMB
->FileName
, searchName
,
4841 PATH_MAX
, nls_codepage
, remap
);
4842 name_len
++; /* trailing null */
4844 } else { /* BB improve the check for buffer overruns BB */
4845 name_len
= strnlen(searchName
, PATH_MAX
);
4846 name_len
++; /* trailing null */
4847 strncpy(pSMB
->FileName
, searchName
, name_len
);
4850 params
= 2 /* level */ + 4 /* reserved */ + name_len
/* includes NUL */ ;
4851 pSMB
->TotalDataCount
= 0;
4852 pSMB
->MaxParameterCount
= cpu_to_le16(2);
4853 pSMB
->MaxDataCount
= cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
4854 pSMB
->MaxSetupCount
= 0;
4858 pSMB
->Reserved2
= 0;
4859 pSMB
->ParameterOffset
= cpu_to_le16(offsetof(
4860 struct smb_com_transaction2_qpi_req
,InformationLevel
) - 4);
4861 pSMB
->DataCount
= 0;
4862 pSMB
->DataOffset
= 0;
4863 pSMB
->SetupCount
= 1;
4864 pSMB
->Reserved3
= 0;
4865 pSMB
->SubCommand
= cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION
);
4866 byte_count
= params
+ 1 /* pad */ ;
4867 pSMB
->TotalParameterCount
= cpu_to_le16(params
);
4868 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
4869 pSMB
->InformationLevel
= cpu_to_le16(SMB_INFO_QUERY_ALL_EAS
);
4870 pSMB
->Reserved4
= 0;
4871 pSMB
->hdr
.smb_buf_length
+= byte_count
;
4872 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
4874 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
4875 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
4877 cFYI(1, ("Send error in QueryAllEAs = %d", rc
));
4878 } else { /* decode response */
4879 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
4881 /* BB also check enough total bytes returned */
4882 /* BB we need to improve the validity checking
4883 of these trans2 responses */
4884 if (rc
|| (pSMBr
->ByteCount
< 4))
4885 rc
= -EIO
; /* bad smb */
4886 /* else if (pFindData){
4887 memcpy((char *) pFindData,
4888 (char *) &pSMBr->hdr.Protocol +
4891 /* check that length of list is not more than bcc */
4892 /* check that each entry does not go beyond length
4894 /* check that each element of each entry does not
4895 go beyond end of list */
4896 __u16 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
4897 struct fealist
* ea_response_data
;
4899 /* validate_trans2_offsets() */
4900 /* BB to check if(start of smb + data_offset > &bcc+ bcc)*/
4901 ea_response_data
= (struct fealist
*)
4902 (((char *) &pSMBr
->hdr
.Protocol
) +
4904 name_len
= le32_to_cpu(ea_response_data
->list_len
);
4905 cFYI(1,("ea length %d", name_len
));
4907 /* returned EA size zeroed at top of function */
4908 cFYI(1,("empty EA list returned from server"));
4910 /* account for ea list len */
4912 temp_fea
= ea_response_data
->list
;
4913 temp_ptr
= (char *)temp_fea
;
4914 while(name_len
> 0) {
4918 rc
+= temp_fea
->name_len
;
4919 /* account for prefix user. and trailing null */
4921 if(rc
<(int)buf_size
) {
4922 memcpy(EAData
,"user.",5);
4924 memcpy(EAData
,temp_ptr
,temp_fea
->name_len
);
4925 EAData
+=temp_fea
->name_len
;
4926 /* null terminate name */
4928 EAData
= EAData
+ 1;
4929 } else if(buf_size
== 0) {
4930 /* skip copy - calc size only */
4932 /* stop before overrun buffer */
4936 name_len
-= temp_fea
->name_len
;
4937 temp_ptr
+= temp_fea
->name_len
;
4938 /* account for trailing null */
4941 value_len
= le16_to_cpu(temp_fea
->value_len
);
4942 name_len
-= value_len
;
4943 temp_ptr
+= value_len
;
4944 /* BB check that temp_ptr is still within smb BB*/
4945 /* no trailing null to account for in value len */
4946 /* go on to next EA */
4947 temp_fea
= (struct fea
*)temp_ptr
;
4953 cifs_buf_release(pSMB
);
4960 ssize_t
CIFSSMBQueryEA(const int xid
,struct cifsTconInfo
* tcon
,
4961 const unsigned char * searchName
,const unsigned char * ea_name
,
4962 unsigned char * ea_value
, size_t buf_size
,
4963 const struct nls_table
*nls_codepage
, int remap
)
4965 TRANSACTION2_QPI_REQ
*pSMB
= NULL
;
4966 TRANSACTION2_QPI_RSP
*pSMBr
= NULL
;
4970 struct fea
* temp_fea
;
4972 __u16 params
, byte_count
;
4974 cFYI(1, ("In Query EA path %s", searchName
));
4976 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
4981 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
4983 cifsConvertToUCS((__le16
*) pSMB
->FileName
, searchName
,
4984 PATH_MAX
, nls_codepage
, remap
);
4985 name_len
++; /* trailing null */
4987 } else { /* BB improve the check for buffer overruns BB */
4988 name_len
= strnlen(searchName
, PATH_MAX
);
4989 name_len
++; /* trailing null */
4990 strncpy(pSMB
->FileName
, searchName
, name_len
);
4993 params
= 2 /* level */ + 4 /* reserved */ + name_len
/* includes NUL */ ;
4994 pSMB
->TotalDataCount
= 0;
4995 pSMB
->MaxParameterCount
= cpu_to_le16(2);
4996 pSMB
->MaxDataCount
= cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
4997 pSMB
->MaxSetupCount
= 0;
5001 pSMB
->Reserved2
= 0;
5002 pSMB
->ParameterOffset
= cpu_to_le16(offsetof(
5003 struct smb_com_transaction2_qpi_req
,InformationLevel
) - 4);
5004 pSMB
->DataCount
= 0;
5005 pSMB
->DataOffset
= 0;
5006 pSMB
->SetupCount
= 1;
5007 pSMB
->Reserved3
= 0;
5008 pSMB
->SubCommand
= cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION
);
5009 byte_count
= params
+ 1 /* pad */ ;
5010 pSMB
->TotalParameterCount
= cpu_to_le16(params
);
5011 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
5012 pSMB
->InformationLevel
= cpu_to_le16(SMB_INFO_QUERY_ALL_EAS
);
5013 pSMB
->Reserved4
= 0;
5014 pSMB
->hdr
.smb_buf_length
+= byte_count
;
5015 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
5017 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
5018 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
5020 cFYI(1, ("Send error in Query EA = %d", rc
));
5021 } else { /* decode response */
5022 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
5024 /* BB also check enough total bytes returned */
5025 /* BB we need to improve the validity checking
5026 of these trans2 responses */
5027 if (rc
|| (pSMBr
->ByteCount
< 4))
5028 rc
= -EIO
; /* bad smb */
5029 /* else if (pFindData){
5030 memcpy((char *) pFindData,
5031 (char *) &pSMBr->hdr.Protocol +
5034 /* check that length of list is not more than bcc */
5035 /* check that each entry does not go beyond length
5037 /* check that each element of each entry does not
5038 go beyond end of list */
5039 __u16 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
5040 struct fealist
* ea_response_data
;
5042 /* validate_trans2_offsets() */
5043 /* BB to check if(start of smb + data_offset > &bcc+ bcc)*/
5044 ea_response_data
= (struct fealist
*)
5045 (((char *) &pSMBr
->hdr
.Protocol
) +
5047 name_len
= le32_to_cpu(ea_response_data
->list_len
);
5048 cFYI(1,("ea length %d", name_len
));
5050 /* returned EA size zeroed at top of function */
5051 cFYI(1,("empty EA list returned from server"));
5053 /* account for ea list len */
5055 temp_fea
= ea_response_data
->list
;
5056 temp_ptr
= (char *)temp_fea
;
5057 /* loop through checking if we have a matching
5058 name and then return the associated value */
5059 while(name_len
> 0) {
5063 value_len
= le16_to_cpu(temp_fea
->value_len
);
5064 /* BB validate that value_len falls within SMB,
5065 even though maximum for name_len is 255 */
5066 if(memcmp(temp_fea
->name
,ea_name
,
5067 temp_fea
->name_len
) == 0) {
5070 /* account for prefix user. and trailing null */
5071 if(rc
<=(int)buf_size
) {
5073 temp_fea
->name
+temp_fea
->name_len
+1,
5075 /* ea values, unlike ea names,
5076 are not null terminated */
5077 } else if(buf_size
== 0) {
5078 /* skip copy - calc size only */
5080 /* stop before overrun buffer */
5085 name_len
-= temp_fea
->name_len
;
5086 temp_ptr
+= temp_fea
->name_len
;
5087 /* account for trailing null */
5090 name_len
-= value_len
;
5091 temp_ptr
+= value_len
;
5092 /* no trailing null to account for in value len */
5093 /* go on to next EA */
5094 temp_fea
= (struct fea
*)temp_ptr
;
5100 cifs_buf_release(pSMB
);
5108 CIFSSMBSetEA(const int xid
, struct cifsTconInfo
*tcon
, const char *fileName
,
5109 const char * ea_name
, const void * ea_value
,
5110 const __u16 ea_value_len
, const struct nls_table
*nls_codepage
,
5113 struct smb_com_transaction2_spi_req
*pSMB
= NULL
;
5114 struct smb_com_transaction2_spi_rsp
*pSMBr
= NULL
;
5115 struct fealist
*parm_data
;
5118 int bytes_returned
= 0;
5119 __u16 params
, param_offset
, byte_count
, offset
, count
;
5121 cFYI(1, ("In SetEA"));
5123 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
5128 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
5130 cifsConvertToUCS((__le16
*) pSMB
->FileName
, fileName
,
5131 PATH_MAX
, nls_codepage
, remap
);
5132 name_len
++; /* trailing null */
5134 } else { /* BB improve the check for buffer overruns BB */
5135 name_len
= strnlen(fileName
, PATH_MAX
);
5136 name_len
++; /* trailing null */
5137 strncpy(pSMB
->FileName
, fileName
, name_len
);
5140 params
= 6 + name_len
;
5142 /* done calculating parms using name_len of file name,
5143 now use name_len to calculate length of ea name
5144 we are going to create in the inode xattrs */
5148 name_len
= strnlen(ea_name
,255);
5150 count
= sizeof(*parm_data
) + ea_value_len
+ name_len
+ 1;
5151 pSMB
->MaxParameterCount
= cpu_to_le16(2);
5152 pSMB
->MaxDataCount
= cpu_to_le16(1000); /* BB find max SMB size from sess */
5153 pSMB
->MaxSetupCount
= 0;
5157 pSMB
->Reserved2
= 0;
5158 param_offset
= offsetof(struct smb_com_transaction2_spi_req
,
5159 InformationLevel
) - 4;
5160 offset
= param_offset
+ params
;
5161 pSMB
->InformationLevel
=
5162 cpu_to_le16(SMB_SET_FILE_EA
);
5165 (struct fealist
*) (((char *) &pSMB
->hdr
.Protocol
) +
5167 pSMB
->ParameterOffset
= cpu_to_le16(param_offset
);
5168 pSMB
->DataOffset
= cpu_to_le16(offset
);
5169 pSMB
->SetupCount
= 1;
5170 pSMB
->Reserved3
= 0;
5171 pSMB
->SubCommand
= cpu_to_le16(TRANS2_SET_PATH_INFORMATION
);
5172 byte_count
= 3 /* pad */ + params
+ count
;
5173 pSMB
->DataCount
= cpu_to_le16(count
);
5174 parm_data
->list_len
= cpu_to_le32(count
);
5175 parm_data
->list
[0].EA_flags
= 0;
5176 /* we checked above that name len is less than 255 */
5177 parm_data
->list
[0].name_len
= (__u8
)name_len
;
5178 /* EA names are always ASCII */
5180 strncpy(parm_data
->list
[0].name
,ea_name
,name_len
);
5181 parm_data
->list
[0].name
[name_len
] = 0;
5182 parm_data
->list
[0].value_len
= cpu_to_le16(ea_value_len
);
5183 /* caller ensures that ea_value_len is less than 64K but
5184 we need to ensure that it fits within the smb */
5186 /*BB add length check that it would fit in negotiated SMB buffer size BB */
5187 /* if(ea_value_len > buffer_size - 512 (enough for header)) */
5189 memcpy(parm_data
->list
[0].name
+name_len
+1,ea_value
,ea_value_len
);
5191 pSMB
->TotalDataCount
= pSMB
->DataCount
;
5192 pSMB
->ParameterCount
= cpu_to_le16(params
);
5193 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
5194 pSMB
->Reserved4
= 0;
5195 pSMB
->hdr
.smb_buf_length
+= byte_count
;
5196 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
5197 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
5198 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
5200 cFYI(1, ("SetPathInfo (EA) returned %d", rc
));
5203 cifs_buf_release(pSMB
);