4 * Copyright (C) International Business Machines Corp., 2002,2005
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"
41 #ifdef CONFIG_CIFS_POSIX
46 {CIFS_PROT
, "\2NT LM 0.12"},
47 {CIFS_PROT
, "\2POSIX 2"},
55 {CIFS_PROT
, "\2NT LM 0.12"},
61 /* Mark as invalid, all open files on tree connections since they
62 were closed when session to server was lost */
63 static void mark_open_files_invalid(struct cifsTconInfo
* pTcon
)
65 struct cifsFileInfo
*open_file
= NULL
;
66 struct list_head
* tmp
;
67 struct list_head
* tmp1
;
69 /* list all files open on tree connection and mark them invalid */
70 write_lock(&GlobalSMBSeslock
);
71 list_for_each_safe(tmp
, tmp1
, &pTcon
->openFileList
) {
72 open_file
= list_entry(tmp
,struct cifsFileInfo
, tlist
);
74 open_file
->invalidHandle
= TRUE
;
77 write_unlock(&GlobalSMBSeslock
);
78 /* BB Add call to invalidate_inodes(sb) for all superblocks mounted
82 /* If the return code is zero, this function must fill in request_buf pointer */
84 small_smb_init(int smb_command
, int wct
, struct cifsTconInfo
*tcon
,
85 void **request_buf
/* returned */)
89 /* SMBs NegProt, SessSetup, uLogoff do not have tcon yet so
90 check for tcp and smb session status done differently
91 for those three - in the calling routine */
93 if(tcon
->tidStatus
== CifsExiting
) {
94 /* only tree disconnect, open, and write,
95 (and ulogoff which does not have tcon)
96 are allowed as we start force umount */
97 if((smb_command
!= SMB_COM_WRITE_ANDX
) &&
98 (smb_command
!= SMB_COM_OPEN_ANDX
) &&
99 (smb_command
!= SMB_COM_TREE_DISCONNECT
)) {
100 cFYI(1,("can not send cmd %d while umounting",
105 if((tcon
->ses
) && (tcon
->ses
->status
!= CifsExiting
) &&
106 (tcon
->ses
->server
)){
107 struct nls_table
*nls_codepage
;
108 /* Give Demultiplex thread up to 10 seconds to
109 reconnect, should be greater than cifs socket
110 timeout which is 7 seconds */
111 while(tcon
->ses
->server
->tcpStatus
== CifsNeedReconnect
) {
112 wait_event_interruptible_timeout(tcon
->ses
->server
->response_q
,
113 (tcon
->ses
->server
->tcpStatus
== CifsGood
), 10 * HZ
);
114 if(tcon
->ses
->server
->tcpStatus
== CifsNeedReconnect
) {
115 /* on "soft" mounts we wait once */
116 if((tcon
->retry
== FALSE
) ||
117 (tcon
->ses
->status
== CifsExiting
)) {
118 cFYI(1,("gave up waiting on reconnect in smb_init"));
120 } /* else "hard" mount - keep retrying
121 until process is killed or server
122 comes back on-line */
123 } else /* TCP session is reestablished now */
128 nls_codepage
= load_nls_default();
129 /* need to prevent multiple threads trying to
130 simultaneously reconnect the same SMB session */
131 down(&tcon
->ses
->sesSem
);
132 if(tcon
->ses
->status
== CifsNeedReconnect
)
133 rc
= cifs_setup_session(0, tcon
->ses
,
135 if(!rc
&& (tcon
->tidStatus
== CifsNeedReconnect
)) {
136 mark_open_files_invalid(tcon
);
137 rc
= CIFSTCon(0, tcon
->ses
, tcon
->treeName
, tcon
139 up(&tcon
->ses
->sesSem
);
140 /* BB FIXME add code to check if wsize needs
141 update due to negotiated smb buffer size
144 atomic_inc(&tconInfoReconnectCount
);
146 cFYI(1, ("reconnect tcon rc = %d", rc
));
147 /* Removed call to reopen open files here -
148 it is safer (and faster) to reopen files
149 one at a time as needed in read and write */
151 /* Check if handle based operation so we
152 know whether we can continue or not without
153 returning to caller to reset file handle */
154 switch(smb_command
) {
155 case SMB_COM_READ_ANDX
:
156 case SMB_COM_WRITE_ANDX
:
158 case SMB_COM_FIND_CLOSE2
:
159 case SMB_COM_LOCKING_ANDX
: {
160 unload_nls(nls_codepage
);
165 up(&tcon
->ses
->sesSem
);
167 unload_nls(nls_codepage
);
176 *request_buf
= cifs_small_buf_get();
177 if (*request_buf
== NULL
) {
178 /* BB should we add a retry in here if not a writepage? */
182 header_assemble((struct smb_hdr
*) *request_buf
, smb_command
, tcon
,wct
);
185 cifs_stats_inc(&tcon
->num_smbs_sent
);
190 /* If the return code is zero, this function must fill in request_buf pointer */
192 smb_init(int smb_command
, int wct
, struct cifsTconInfo
*tcon
,
193 void **request_buf
/* returned */ ,
194 void **response_buf
/* returned */ )
198 /* SMBs NegProt, SessSetup, uLogoff do not have tcon yet so
199 check for tcp and smb session status done differently
200 for those three - in the calling routine */
202 if(tcon
->tidStatus
== CifsExiting
) {
203 /* only tree disconnect, open, and write,
204 (and ulogoff which does not have tcon)
205 are allowed as we start force umount */
206 if((smb_command
!= SMB_COM_WRITE_ANDX
) &&
207 (smb_command
!= SMB_COM_OPEN_ANDX
) &&
208 (smb_command
!= SMB_COM_TREE_DISCONNECT
)) {
209 cFYI(1,("can not send cmd %d while umounting",
215 if((tcon
->ses
) && (tcon
->ses
->status
!= CifsExiting
) &&
216 (tcon
->ses
->server
)){
217 struct nls_table
*nls_codepage
;
218 /* Give Demultiplex thread up to 10 seconds to
219 reconnect, should be greater than cifs socket
220 timeout which is 7 seconds */
221 while(tcon
->ses
->server
->tcpStatus
== CifsNeedReconnect
) {
222 wait_event_interruptible_timeout(tcon
->ses
->server
->response_q
,
223 (tcon
->ses
->server
->tcpStatus
== CifsGood
), 10 * HZ
);
224 if(tcon
->ses
->server
->tcpStatus
==
226 /* on "soft" mounts we wait once */
227 if((tcon
->retry
== FALSE
) ||
228 (tcon
->ses
->status
== CifsExiting
)) {
229 cFYI(1,("gave up waiting on reconnect in smb_init"));
231 } /* else "hard" mount - keep retrying
232 until process is killed or server
234 } else /* TCP session is reestablished now */
239 nls_codepage
= load_nls_default();
240 /* need to prevent multiple threads trying to
241 simultaneously reconnect the same SMB session */
242 down(&tcon
->ses
->sesSem
);
243 if(tcon
->ses
->status
== CifsNeedReconnect
)
244 rc
= cifs_setup_session(0, tcon
->ses
,
246 if(!rc
&& (tcon
->tidStatus
== CifsNeedReconnect
)) {
247 mark_open_files_invalid(tcon
);
248 rc
= CIFSTCon(0, tcon
->ses
, tcon
->treeName
,
250 up(&tcon
->ses
->sesSem
);
251 /* BB FIXME add code to check if wsize needs
252 update due to negotiated smb buffer size
255 atomic_inc(&tconInfoReconnectCount
);
257 cFYI(1, ("reconnect tcon rc = %d", rc
));
258 /* Removed call to reopen open files here -
259 it is safer (and faster) to reopen files
260 one at a time as needed in read and write */
262 /* Check if handle based operation so we
263 know whether we can continue or not without
264 returning to caller to reset file handle */
265 switch(smb_command
) {
266 case SMB_COM_READ_ANDX
:
267 case SMB_COM_WRITE_ANDX
:
269 case SMB_COM_FIND_CLOSE2
:
270 case SMB_COM_LOCKING_ANDX
: {
271 unload_nls(nls_codepage
);
276 up(&tcon
->ses
->sesSem
);
278 unload_nls(nls_codepage
);
287 *request_buf
= cifs_buf_get();
288 if (*request_buf
== NULL
) {
289 /* BB should we add a retry in here if not a writepage? */
292 /* Although the original thought was we needed the response buf for */
293 /* potential retries of smb operations it turns out we can determine */
294 /* from the mid flags when the request buffer can be resent without */
295 /* having to use a second distinct buffer for the response */
296 *response_buf
= *request_buf
;
298 header_assemble((struct smb_hdr
*) *request_buf
, smb_command
, tcon
,
302 cifs_stats_inc(&tcon
->num_smbs_sent
);
307 static int validate_t2(struct smb_t2_rsp
* pSMB
)
313 /* check for plausible wct, bcc and t2 data and parm sizes */
314 /* check for parm and data offset going beyond end of smb */
315 if(pSMB
->hdr
.WordCount
>= 10) {
316 if((le16_to_cpu(pSMB
->t2_rsp
.ParameterOffset
) <= 1024) &&
317 (le16_to_cpu(pSMB
->t2_rsp
.DataOffset
) <= 1024)) {
318 /* check that bcc is at least as big as parms + data */
319 /* check that bcc is less than negotiated smb buffer */
320 total_size
= le16_to_cpu(pSMB
->t2_rsp
.ParameterCount
);
321 if(total_size
< 512) {
322 total_size
+=le16_to_cpu(pSMB
->t2_rsp
.DataCount
);
323 /* BCC le converted in SendReceive */
324 pBCC
= (pSMB
->hdr
.WordCount
* 2) +
325 sizeof(struct smb_hdr
) +
327 if((total_size
<= (*(u16
*)pBCC
)) &&
329 CIFSMaxBufSize
+MAX_CIFS_HDR_SIZE
)) {
336 cifs_dump_mem("Invalid transact2 SMB: ",(char *)pSMB
,
337 sizeof(struct smb_t2_rsp
) + 16);
341 CIFSSMBNegotiate(unsigned int xid
, struct cifsSesInfo
*ses
)
344 NEGOTIATE_RSP
*pSMBr
;
347 struct TCP_Server_Info
* server
;
351 server
= ses
->server
;
356 rc
= smb_init(SMB_COM_NEGOTIATE
, 0, NULL
/* no tcon yet */ ,
357 (void **) &pSMB
, (void **) &pSMBr
);
360 pSMB
->hdr
.Mid
= GetNextMid(server
);
361 pSMB
->hdr
.Flags2
|= SMBFLG2_UNICODE
;
362 if (extended_security
)
363 pSMB
->hdr
.Flags2
|= SMBFLG2_EXT_SEC
;
365 count
= strlen(protocols
[0].name
) + 1;
366 strncpy(pSMB
->DialectsArray
, protocols
[0].name
, 30);
367 /* null guaranteed to be at end of source and target buffers anyway */
369 pSMB
->hdr
.smb_buf_length
+= count
;
370 pSMB
->ByteCount
= cpu_to_le16(count
);
372 rc
= SendReceive(xid
, ses
, (struct smb_hdr
*) pSMB
,
373 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
375 server
->secMode
= pSMBr
->SecurityMode
;
376 server
->secType
= NTLM
; /* BB override default for
377 NTLMv2 or kerberos v5 */
378 /* one byte - no need to convert this or EncryptionKeyLen
379 from little endian */
380 server
->maxReq
= le16_to_cpu(pSMBr
->MaxMpxCount
);
381 /* probably no need to store and check maxvcs */
383 min(le32_to_cpu(pSMBr
->MaxBufferSize
),
384 (__u32
) CIFSMaxBufSize
+ MAX_CIFS_HDR_SIZE
);
385 server
->maxRw
= le32_to_cpu(pSMBr
->MaxRawSize
);
386 cFYI(0, ("Max buf = %d ", ses
->server
->maxBuf
));
387 GETU32(ses
->server
->sessid
) = le32_to_cpu(pSMBr
->SessionKey
);
388 server
->capabilities
= le32_to_cpu(pSMBr
->Capabilities
);
389 server
->timeZone
= le16_to_cpu(pSMBr
->ServerTimeZone
);
390 /* BB with UTC do we ever need to be using srvr timezone? */
391 if (pSMBr
->EncryptionKeyLength
== CIFS_CRYPTO_KEY_SIZE
) {
392 memcpy(server
->cryptKey
, pSMBr
->u
.EncryptionKey
,
393 CIFS_CRYPTO_KEY_SIZE
);
394 } else if ((pSMBr
->hdr
.Flags2
& SMBFLG2_EXT_SEC
)
395 && (pSMBr
->EncryptionKeyLength
== 0)) {
396 /* decode security blob */
400 /* BB might be helpful to save off the domain of server here */
402 if ((pSMBr
->hdr
.Flags2
& SMBFLG2_EXT_SEC
) &&
403 (server
->capabilities
& CAP_EXTENDED_SECURITY
)) {
404 count
= pSMBr
->ByteCount
;
407 else if (count
== 16) {
408 server
->secType
= RawNTLMSSP
;
409 if (server
->socketUseCount
.counter
> 1) {
411 (server
->server_GUID
,
412 pSMBr
->u
.extended_response
.
415 ("UID of server does not match previous connection to same ip address"));
423 memcpy(server
->server_GUID
,
424 pSMBr
->u
.extended_response
.
427 rc
= decode_negTokenInit(pSMBr
->u
.
433 /* BB Need to fill struct for sessetup here */
440 server
->capabilities
&= ~CAP_EXTENDED_SECURITY
;
441 if(sign_CIFS_PDUs
== FALSE
) {
442 if(server
->secMode
& SECMODE_SIGN_REQUIRED
)
444 ("Server requires /proc/fs/cifs/PacketSigningEnabled"));
445 server
->secMode
&= ~(SECMODE_SIGN_ENABLED
| SECMODE_SIGN_REQUIRED
);
446 } else if(sign_CIFS_PDUs
== 1) {
447 if((server
->secMode
& SECMODE_SIGN_REQUIRED
) == 0)
448 server
->secMode
&= ~(SECMODE_SIGN_ENABLED
| SECMODE_SIGN_REQUIRED
);
453 cifs_buf_release(pSMB
);
458 CIFSSMBTDis(const int xid
, struct cifsTconInfo
*tcon
)
460 struct smb_hdr
*smb_buffer
;
461 struct smb_hdr
*smb_buffer_response
; /* BB removeme BB */
465 cFYI(1, ("In tree disconnect"));
467 * If last user of the connection and
468 * connection alive - disconnect it
469 * If this is the last connection on the server session disconnect it
470 * (and inside session disconnect we should check if tcp socket needs
471 * to be freed and kernel thread woken up).
474 down(&tcon
->tconSem
);
478 atomic_dec(&tcon
->useCount
);
479 if (atomic_read(&tcon
->useCount
) > 0) {
484 /* No need to return error on this operation if tid invalidated and
485 closed on server already e.g. due to tcp session crashing */
486 if(tcon
->tidStatus
== CifsNeedReconnect
) {
491 if((tcon
->ses
== NULL
) || (tcon
->ses
->server
== NULL
)) {
495 rc
= small_smb_init(SMB_COM_TREE_DISCONNECT
, 0, tcon
,
496 (void **)&smb_buffer
);
501 smb_buffer_response
= smb_buffer
; /* BB removeme BB */
503 rc
= SendReceive(xid
, tcon
->ses
, smb_buffer
, smb_buffer_response
,
506 cFYI(1, ("Tree disconnect failed %d", rc
));
509 cifs_small_buf_release(smb_buffer
);
512 /* No need to return error on this operation if tid invalidated and
513 closed on server already e.g. due to tcp session crashing */
521 CIFSSMBLogoff(const int xid
, struct cifsSesInfo
*ses
)
523 struct smb_hdr
*smb_buffer_response
;
524 LOGOFF_ANDX_REQ
*pSMB
;
528 cFYI(1, ("In SMBLogoff for session disconnect"));
534 atomic_dec(&ses
->inUse
);
535 if (atomic_read(&ses
->inUse
) > 0) {
539 rc
= small_smb_init(SMB_COM_LOGOFF_ANDX
, 2, NULL
, (void **)&pSMB
);
545 smb_buffer_response
= (struct smb_hdr
*)pSMB
; /* BB removeme BB */
548 pSMB
->hdr
.Mid
= GetNextMid(ses
->server
);
550 if(ses
->server
->secMode
&
551 (SECMODE_SIGN_REQUIRED
| SECMODE_SIGN_ENABLED
))
552 pSMB
->hdr
.Flags2
|= SMBFLG2_SECURITY_SIGNATURE
;
555 pSMB
->hdr
.Uid
= ses
->Suid
;
557 pSMB
->AndXCommand
= 0xFF;
558 rc
= SendReceive(xid
, ses
, (struct smb_hdr
*) pSMB
,
559 smb_buffer_response
, &length
, 0);
561 atomic_dec(&ses
->server
->socketUseCount
);
562 if (atomic_read(&ses
->server
->socketUseCount
) == 0) {
563 spin_lock(&GlobalMid_Lock
);
564 ses
->server
->tcpStatus
= CifsExiting
;
565 spin_unlock(&GlobalMid_Lock
);
570 cifs_small_buf_release(pSMB
);
572 /* if session dead then we do not need to do ulogoff,
573 since server closed smb session, no sense reporting
581 CIFSSMBDelFile(const int xid
, struct cifsTconInfo
*tcon
, const char *fileName
,
582 const struct nls_table
*nls_codepage
, int remap
)
584 DELETE_FILE_REQ
*pSMB
= NULL
;
585 DELETE_FILE_RSP
*pSMBr
= NULL
;
591 rc
= smb_init(SMB_COM_DELETE
, 1, tcon
, (void **) &pSMB
,
596 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
598 cifsConvertToUCS((__le16
*) pSMB
->fileName
, fileName
,
599 PATH_MAX
, nls_codepage
, remap
);
600 name_len
++; /* trailing null */
602 } else { /* BB improve check for buffer overruns BB */
603 name_len
= strnlen(fileName
, PATH_MAX
);
604 name_len
++; /* trailing null */
605 strncpy(pSMB
->fileName
, fileName
, name_len
);
607 pSMB
->SearchAttributes
=
608 cpu_to_le16(ATTR_READONLY
| ATTR_HIDDEN
| ATTR_SYSTEM
);
609 pSMB
->BufferFormat
= 0x04;
610 pSMB
->hdr
.smb_buf_length
+= name_len
+ 1;
611 pSMB
->ByteCount
= cpu_to_le16(name_len
+ 1);
612 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
613 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
614 cifs_stats_inc(&tcon
->num_deletes
);
616 cFYI(1, ("Error in RMFile = %d", rc
));
619 cifs_buf_release(pSMB
);
627 CIFSSMBRmDir(const int xid
, struct cifsTconInfo
*tcon
, const char *dirName
,
628 const struct nls_table
*nls_codepage
, int remap
)
630 DELETE_DIRECTORY_REQ
*pSMB
= NULL
;
631 DELETE_DIRECTORY_RSP
*pSMBr
= NULL
;
636 cFYI(1, ("In CIFSSMBRmDir"));
638 rc
= smb_init(SMB_COM_DELETE_DIRECTORY
, 0, tcon
, (void **) &pSMB
,
643 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
644 name_len
= cifsConvertToUCS((__le16
*) pSMB
->DirName
, dirName
,
645 PATH_MAX
, nls_codepage
, remap
);
646 name_len
++; /* trailing null */
648 } else { /* BB improve check for buffer overruns BB */
649 name_len
= strnlen(dirName
, PATH_MAX
);
650 name_len
++; /* trailing null */
651 strncpy(pSMB
->DirName
, dirName
, name_len
);
654 pSMB
->BufferFormat
= 0x04;
655 pSMB
->hdr
.smb_buf_length
+= name_len
+ 1;
656 pSMB
->ByteCount
= cpu_to_le16(name_len
+ 1);
657 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
658 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
659 cifs_stats_inc(&tcon
->num_rmdirs
);
661 cFYI(1, ("Error in RMDir = %d", rc
));
664 cifs_buf_release(pSMB
);
671 CIFSSMBMkDir(const int xid
, struct cifsTconInfo
*tcon
,
672 const char *name
, const struct nls_table
*nls_codepage
, int remap
)
675 CREATE_DIRECTORY_REQ
*pSMB
= NULL
;
676 CREATE_DIRECTORY_RSP
*pSMBr
= NULL
;
680 cFYI(1, ("In CIFSSMBMkDir"));
682 rc
= smb_init(SMB_COM_CREATE_DIRECTORY
, 0, tcon
, (void **) &pSMB
,
687 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
688 name_len
= cifsConvertToUCS((__le16
*) pSMB
->DirName
, name
,
689 PATH_MAX
, nls_codepage
, remap
);
690 name_len
++; /* trailing null */
692 } else { /* BB improve check for buffer overruns BB */
693 name_len
= strnlen(name
, PATH_MAX
);
694 name_len
++; /* trailing null */
695 strncpy(pSMB
->DirName
, name
, name_len
);
698 pSMB
->BufferFormat
= 0x04;
699 pSMB
->hdr
.smb_buf_length
+= name_len
+ 1;
700 pSMB
->ByteCount
= cpu_to_le16(name_len
+ 1);
701 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
702 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
703 cifs_stats_inc(&tcon
->num_mkdirs
);
705 cFYI(1, ("Error in Mkdir = %d", rc
));
708 cifs_buf_release(pSMB
);
714 static __u16
convert_disposition(int disposition
)
718 switch (disposition
) {
720 ofun
= SMBOPEN_OCREATE
| SMBOPEN_OTRUNC
;
723 ofun
= SMBOPEN_OAPPEND
;
726 ofun
= SMBOPEN_OCREATE
;
729 ofun
= SMBOPEN_OCREATE
| SMBOPEN_OAPPEND
;
732 ofun
= SMBOPEN_OTRUNC
;
734 case FILE_OVERWRITE_IF
:
735 ofun
= SMBOPEN_OCREATE
| SMBOPEN_OTRUNC
;
738 cFYI(1,("unknown disposition %d",disposition
));
739 ofun
= SMBOPEN_OAPPEND
; /* regular open */
745 SMBLegacyOpen(const int xid
, struct cifsTconInfo
*tcon
,
746 const char *fileName
, const int openDisposition
,
747 const int access_flags
, const int create_options
, __u16
* netfid
,
748 int *pOplock
, FILE_ALL_INFO
* pfile_info
,
749 const struct nls_table
*nls_codepage
, int remap
)
752 OPENX_REQ
*pSMB
= NULL
;
753 OPENX_RSP
*pSMBr
= NULL
;
759 rc
= smb_init(SMB_COM_OPEN_ANDX
, 15, tcon
, (void **) &pSMB
,
764 pSMB
->AndXCommand
= 0xFF; /* none */
766 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
767 count
= 1; /* account for one byte pad to word boundary */
769 cifsConvertToUCS((__le16
*) (pSMB
->fileName
+ 1),
770 fileName
, PATH_MAX
, nls_codepage
, remap
);
771 name_len
++; /* trailing null */
773 } else { /* BB improve check for buffer overruns BB */
774 count
= 0; /* no pad */
775 name_len
= strnlen(fileName
, PATH_MAX
);
776 name_len
++; /* trailing null */
777 strncpy(pSMB
->fileName
, fileName
, name_len
);
779 if (*pOplock
& REQ_OPLOCK
)
780 pSMB
->OpenFlags
= cpu_to_le16(REQ_OPLOCK
);
781 else if (*pOplock
& REQ_BATCHOPLOCK
) {
782 pSMB
->OpenFlags
= cpu_to_le16(REQ_BATCHOPLOCK
);
784 pSMB
->OpenFlags
|= cpu_to_le16(REQ_MORE_INFO
);
785 /* BB fixme add conversion for access_flags to bits 0 - 2 of mode */
791 pSMB
->Mode
= cpu_to_le16(2);
792 pSMB
->Mode
|= cpu_to_le16(0x40); /* deny none */
793 /* set file as system file if special file such
794 as fifo and server expecting SFU style and
795 no Unix extensions */
797 if(create_options
& CREATE_OPTION_SPECIAL
)
798 pSMB
->FileAttributes
= cpu_to_le16(ATTR_SYSTEM
);
800 pSMB
->FileAttributes
= cpu_to_le16(0/*ATTR_NORMAL*/); /* BB FIXME */
802 /* if ((omode & S_IWUGO) == 0)
803 pSMB->FileAttributes |= cpu_to_le32(ATTR_READONLY);*/
804 /* Above line causes problems due to vfs splitting create into two
805 pieces - need to set mode after file created not while it is
809 /* pSMB->CreateOptions = cpu_to_le32(create_options & CREATE_OPTIONS_MASK); */
810 /* BB FIXME END BB */
812 pSMB
->Sattr
= cpu_to_le16(ATTR_HIDDEN
| ATTR_SYSTEM
| ATTR_DIRECTORY
);
813 pSMB
->OpenFunction
= cpu_to_le16(convert_disposition(openDisposition
));
815 pSMB
->hdr
.smb_buf_length
+= count
;
817 pSMB
->ByteCount
= cpu_to_le16(count
);
818 /* long_op set to 1 to allow for oplock break timeouts */
819 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
820 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 1);
821 cifs_stats_inc(&tcon
->num_opens
);
823 cFYI(1, ("Error in Open = %d", rc
));
825 /* BB verify if wct == 15 */
827 /* *pOplock = pSMBr->OplockLevel; */ /* BB take from action field BB */
829 *netfid
= pSMBr
->Fid
; /* cifs fid stays in le */
830 /* Let caller know file was created so we can set the mode. */
831 /* Do we care about the CreateAction in any other cases? */
833 /* if(cpu_to_le32(FILE_CREATE) == pSMBr->CreateAction)
834 *pOplock |= CIFS_CREATE_ACTION; */
838 pfile_info
->CreationTime
= 0; /* BB convert CreateTime*/
839 pfile_info
->LastAccessTime
= 0; /* BB fixme */
840 pfile_info
->LastWriteTime
= 0; /* BB fixme */
841 pfile_info
->ChangeTime
= 0; /* BB fixme */
842 pfile_info
->Attributes
=
843 cpu_to_le32(le16_to_cpu(pSMBr
->FileAttributes
));
844 /* the file_info buf is endian converted by caller */
845 pfile_info
->AllocationSize
=
846 cpu_to_le64(le32_to_cpu(pSMBr
->EndOfFile
));
847 pfile_info
->EndOfFile
= pfile_info
->AllocationSize
;
848 pfile_info
->NumberOfLinks
= cpu_to_le32(1);
852 cifs_buf_release(pSMB
);
859 CIFSSMBOpen(const int xid
, struct cifsTconInfo
*tcon
,
860 const char *fileName
, const int openDisposition
,
861 const int access_flags
, const int create_options
, __u16
* netfid
,
862 int *pOplock
, FILE_ALL_INFO
* pfile_info
,
863 const struct nls_table
*nls_codepage
, int remap
)
866 OPEN_REQ
*pSMB
= NULL
;
867 OPEN_RSP
*pSMBr
= NULL
;
873 rc
= smb_init(SMB_COM_NT_CREATE_ANDX
, 24, tcon
, (void **) &pSMB
,
878 pSMB
->AndXCommand
= 0xFF; /* none */
880 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
881 count
= 1; /* account for one byte pad to word boundary */
883 cifsConvertToUCS((__le16
*) (pSMB
->fileName
+ 1),
884 fileName
, PATH_MAX
, nls_codepage
, remap
);
885 name_len
++; /* trailing null */
887 pSMB
->NameLength
= cpu_to_le16(name_len
);
888 } else { /* BB improve check for buffer overruns BB */
889 count
= 0; /* no pad */
890 name_len
= strnlen(fileName
, PATH_MAX
);
891 name_len
++; /* trailing null */
892 pSMB
->NameLength
= cpu_to_le16(name_len
);
893 strncpy(pSMB
->fileName
, fileName
, name_len
);
895 if (*pOplock
& REQ_OPLOCK
)
896 pSMB
->OpenFlags
= cpu_to_le32(REQ_OPLOCK
);
897 else if (*pOplock
& REQ_BATCHOPLOCK
) {
898 pSMB
->OpenFlags
= cpu_to_le32(REQ_BATCHOPLOCK
);
900 pSMB
->DesiredAccess
= cpu_to_le32(access_flags
);
901 pSMB
->AllocationSize
= 0;
902 /* set file as system file if special file such
903 as fifo and server expecting SFU style and
904 no Unix extensions */
905 if(create_options
& CREATE_OPTION_SPECIAL
)
906 pSMB
->FileAttributes
= cpu_to_le32(ATTR_SYSTEM
);
908 pSMB
->FileAttributes
= cpu_to_le32(ATTR_NORMAL
);
909 /* XP does not handle ATTR_POSIX_SEMANTICS */
910 /* but it helps speed up case sensitive checks for other
911 servers such as Samba */
912 if (tcon
->ses
->capabilities
& CAP_UNIX
)
913 pSMB
->FileAttributes
|= cpu_to_le32(ATTR_POSIX_SEMANTICS
);
915 /* if ((omode & S_IWUGO) == 0)
916 pSMB->FileAttributes |= cpu_to_le32(ATTR_READONLY);*/
917 /* Above line causes problems due to vfs splitting create into two
918 pieces - need to set mode after file created not while it is
920 pSMB
->ShareAccess
= cpu_to_le32(FILE_SHARE_ALL
);
921 pSMB
->CreateDisposition
= cpu_to_le32(openDisposition
);
922 pSMB
->CreateOptions
= cpu_to_le32(create_options
& CREATE_OPTIONS_MASK
);
923 /* BB Expirement with various impersonation levels and verify */
924 pSMB
->ImpersonationLevel
= cpu_to_le32(SECURITY_IMPERSONATION
);
925 pSMB
->SecurityFlags
=
926 SECURITY_CONTEXT_TRACKING
| SECURITY_EFFECTIVE_ONLY
;
929 pSMB
->hdr
.smb_buf_length
+= count
;
931 pSMB
->ByteCount
= cpu_to_le16(count
);
932 /* long_op set to 1 to allow for oplock break timeouts */
933 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
934 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 1);
935 cifs_stats_inc(&tcon
->num_opens
);
937 cFYI(1, ("Error in Open = %d", rc
));
939 *pOplock
= pSMBr
->OplockLevel
; /* 1 byte no need to le_to_cpu */
940 *netfid
= pSMBr
->Fid
; /* cifs fid stays in le */
941 /* Let caller know file was created so we can set the mode. */
942 /* Do we care about the CreateAction in any other cases? */
943 if(cpu_to_le32(FILE_CREATE
) == pSMBr
->CreateAction
)
944 *pOplock
|= CIFS_CREATE_ACTION
;
946 memcpy((char *)pfile_info
,(char *)&pSMBr
->CreationTime
,
947 36 /* CreationTime to Attributes */);
948 /* the file_info buf is endian converted by caller */
949 pfile_info
->AllocationSize
= pSMBr
->AllocationSize
;
950 pfile_info
->EndOfFile
= pSMBr
->EndOfFile
;
951 pfile_info
->NumberOfLinks
= cpu_to_le32(1);
955 cifs_buf_release(pSMB
);
961 /* If no buffer passed in, then caller wants to do the copy
962 as in the case of readpages so the SMB buffer must be
963 freed by the caller */
966 CIFSSMBRead(const int xid
, struct cifsTconInfo
*tcon
,
967 const int netfid
, const unsigned int count
,
968 const __u64 lseek
, unsigned int *nbytes
, char **buf
)
971 READ_REQ
*pSMB
= NULL
;
972 READ_RSP
*pSMBr
= NULL
;
973 char *pReadData
= NULL
;
977 cFYI(1,("Reading %d bytes on fid %d",count
,netfid
));
978 if(tcon
->ses
->capabilities
& CAP_LARGE_FILES
)
981 wct
= 10; /* old style read */
984 rc
= smb_init(SMB_COM_READ_ANDX
, wct
, tcon
, (void **) &pSMB
,
989 /* tcon and ses pointer are checked in smb_init */
990 if (tcon
->ses
->server
== NULL
)
991 return -ECONNABORTED
;
993 pSMB
->AndXCommand
= 0xFF; /* none */
995 pSMB
->OffsetLow
= cpu_to_le32(lseek
& 0xFFFFFFFF);
997 pSMB
->OffsetHigh
= cpu_to_le32(lseek
>> 32);
998 else if((lseek
>> 32) > 0) /* can not handle this big offset for old */
1001 pSMB
->Remaining
= 0;
1002 pSMB
->MaxCount
= cpu_to_le16(count
& 0xFFFF);
1003 pSMB
->MaxCountHigh
= cpu_to_le32(count
>> 16);
1005 pSMB
->ByteCount
= 0; /* no need to do le conversion since 0 */
1007 /* old style read */
1008 struct smb_com_readx_req
* pSMBW
=
1009 (struct smb_com_readx_req
*)pSMB
;
1010 pSMBW
->ByteCount
= 0;
1013 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
1014 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
1015 cifs_stats_inc(&tcon
->num_reads
);
1017 cERROR(1, ("Send error in read = %d", rc
));
1019 int data_length
= le16_to_cpu(pSMBr
->DataLengthHigh
);
1020 data_length
= data_length
<< 16;
1021 data_length
+= le16_to_cpu(pSMBr
->DataLength
);
1022 *nbytes
= data_length
;
1024 /*check that DataLength would not go beyond end of SMB */
1025 if ((data_length
> CIFSMaxBufSize
)
1026 || (data_length
> count
)) {
1027 cFYI(1,("bad length %d for count %d",data_length
,count
));
1032 (char *) (&pSMBr
->hdr
.Protocol
) +
1033 le16_to_cpu(pSMBr
->DataOffset
);
1034 /* if(rc = copy_to_user(buf, pReadData, data_length)) {
1035 cERROR(1,("Faulting on read rc = %d",rc));
1037 }*/ /* can not use copy_to_user when using page cache*/
1039 memcpy(*buf
,pReadData
,data_length
);
1043 cifs_buf_release(pSMB
);
1045 *buf
= (char *)pSMB
;
1047 /* Note: On -EAGAIN error only caller can retry on handle based calls
1048 since file handle passed in no longer valid */
1053 CIFSSMBWrite(const int xid
, struct cifsTconInfo
*tcon
,
1054 const int netfid
, const unsigned int count
,
1055 const __u64 offset
, unsigned int *nbytes
, const char *buf
,
1056 const char __user
* ubuf
, const int long_op
)
1059 WRITE_REQ
*pSMB
= NULL
;
1060 WRITE_RSP
*pSMBr
= NULL
;
1061 int bytes_returned
, wct
;
1065 /* cFYI(1,("write at %lld %d bytes",offset,count));*/
1066 if(tcon
->ses
== NULL
)
1067 return -ECONNABORTED
;
1069 if(tcon
->ses
->capabilities
& CAP_LARGE_FILES
)
1074 rc
= smb_init(SMB_COM_WRITE_ANDX
, wct
, tcon
, (void **) &pSMB
,
1078 /* tcon and ses pointer are checked in smb_init */
1079 if (tcon
->ses
->server
== NULL
)
1080 return -ECONNABORTED
;
1082 pSMB
->AndXCommand
= 0xFF; /* none */
1084 pSMB
->OffsetLow
= cpu_to_le32(offset
& 0xFFFFFFFF);
1086 pSMB
->OffsetHigh
= cpu_to_le32(offset
>> 32);
1087 else if((offset
>> 32) > 0) /* can not handle this big offset for old */
1090 pSMB
->Reserved
= 0xFFFFFFFF;
1091 pSMB
->WriteMode
= 0;
1092 pSMB
->Remaining
= 0;
1094 /* Can increase buffer size if buffer is big enough in some cases - ie we
1095 can send more if LARGE_WRITE_X capability returned by the server and if
1096 our buffer is big enough or if we convert to iovecs on socket writes
1097 and eliminate the copy to the CIFS buffer */
1098 if(tcon
->ses
->capabilities
& CAP_LARGE_WRITE_X
) {
1099 bytes_sent
= min_t(const unsigned int, CIFSMaxBufSize
, count
);
1101 bytes_sent
= (tcon
->ses
->server
->maxBuf
- MAX_CIFS_HDR_SIZE
)
1105 if (bytes_sent
> count
)
1108 cpu_to_le16(offsetof(struct smb_com_write_req
,Data
) - 4);
1110 memcpy(pSMB
->Data
,buf
,bytes_sent
);
1112 if(copy_from_user(pSMB
->Data
,ubuf
,bytes_sent
)) {
1113 cifs_buf_release(pSMB
);
1116 } else if (count
!= 0) {
1118 cifs_buf_release(pSMB
);
1120 } /* else setting file size with write of zero bytes */
1122 byte_count
= bytes_sent
+ 1; /* pad */
1123 else /* wct == 12 */ {
1124 byte_count
= bytes_sent
+ 5; /* bigger pad, smaller smb hdr */
1126 pSMB
->DataLengthLow
= cpu_to_le16(bytes_sent
& 0xFFFF);
1127 pSMB
->DataLengthHigh
= cpu_to_le16(bytes_sent
>> 16);
1128 pSMB
->hdr
.smb_buf_length
+= byte_count
;
1131 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
1132 else { /* old style write has byte count 4 bytes earlier so 4 bytes pad */
1133 struct smb_com_writex_req
* pSMBW
=
1134 (struct smb_com_writex_req
*)pSMB
;
1135 pSMBW
->ByteCount
= cpu_to_le16(byte_count
);
1138 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
1139 (struct smb_hdr
*) pSMBr
, &bytes_returned
, long_op
);
1140 cifs_stats_inc(&tcon
->num_writes
);
1142 cFYI(1, ("Send error in write = %d", rc
));
1145 *nbytes
= le16_to_cpu(pSMBr
->CountHigh
);
1146 *nbytes
= (*nbytes
) << 16;
1147 *nbytes
+= le16_to_cpu(pSMBr
->Count
);
1150 cifs_buf_release(pSMB
);
1152 /* Note: On -EAGAIN error only caller can retry on handle based calls
1153 since file handle passed in no longer valid */
1159 CIFSSMBWrite2(const int xid
, struct cifsTconInfo
*tcon
,
1160 const int netfid
, const unsigned int count
,
1161 const __u64 offset
, unsigned int *nbytes
, struct kvec
*iov
,
1162 int n_vec
, const int long_op
)
1165 WRITE_REQ
*pSMB
= NULL
;
1166 int bytes_returned
, wct
;
1169 /* BB removeme BB */
1170 cFYI(1,("write2 at %lld %d bytes", (long long)offset
, count
));
1172 if(tcon
->ses
->capabilities
& CAP_LARGE_FILES
)
1176 rc
= small_smb_init(SMB_COM_WRITE_ANDX
, wct
, tcon
, (void **) &pSMB
);
1179 /* tcon and ses pointer are checked in smb_init */
1180 if (tcon
->ses
->server
== NULL
)
1181 return -ECONNABORTED
;
1183 pSMB
->AndXCommand
= 0xFF; /* none */
1185 pSMB
->OffsetLow
= cpu_to_le32(offset
& 0xFFFFFFFF);
1187 pSMB
->OffsetHigh
= cpu_to_le32(offset
>> 32);
1188 else if((offset
>> 32) > 0) /* can not handle this big offset for old */
1190 pSMB
->Reserved
= 0xFFFFFFFF;
1191 pSMB
->WriteMode
= 0;
1192 pSMB
->Remaining
= 0;
1195 cpu_to_le16(offsetof(struct smb_com_write_req
,Data
) - 4);
1197 pSMB
->DataLengthLow
= cpu_to_le16(count
& 0xFFFF);
1198 pSMB
->DataLengthHigh
= cpu_to_le16(count
>> 16);
1199 smb_hdr_len
= pSMB
->hdr
.smb_buf_length
+ 1; /* hdr + 1 byte pad */
1201 pSMB
->hdr
.smb_buf_length
+= count
+1;
1202 else /* wct == 12 */
1203 pSMB
->hdr
.smb_buf_length
+= count
+5; /* smb data starts later */
1205 pSMB
->ByteCount
= cpu_to_le16(count
+ 1);
1206 else /* wct == 12 */ /* bigger pad, smaller smb hdr, keep offset ok */ {
1207 struct smb_com_writex_req
* pSMBW
=
1208 (struct smb_com_writex_req
*)pSMB
;
1209 pSMBW
->ByteCount
= cpu_to_le16(count
+ 5);
1211 iov
[0].iov_base
= pSMB
;
1212 iov
[0].iov_len
= smb_hdr_len
+ 4;
1214 rc
= SendReceive2(xid
, tcon
->ses
, iov
, n_vec
+ 1, &bytes_returned
,
1216 cifs_stats_inc(&tcon
->num_writes
);
1218 cFYI(1, ("Send error Write2 = %d", rc
));
1221 WRITE_RSP
* pSMBr
= (WRITE_RSP
*)pSMB
;
1222 *nbytes
= le16_to_cpu(pSMBr
->CountHigh
);
1223 *nbytes
= (*nbytes
) << 16;
1224 *nbytes
+= le16_to_cpu(pSMBr
->Count
);
1227 cifs_small_buf_release(pSMB
);
1229 /* Note: On -EAGAIN error only caller can retry on handle based calls
1230 since file handle passed in no longer valid */
1237 CIFSSMBLock(const int xid
, struct cifsTconInfo
*tcon
,
1238 const __u16 smb_file_id
, const __u64 len
,
1239 const __u64 offset
, const __u32 numUnlock
,
1240 const __u32 numLock
, const __u8 lockType
, const int waitFlag
)
1243 LOCK_REQ
*pSMB
= NULL
;
1244 LOCK_RSP
*pSMBr
= NULL
;
1249 cFYI(1, ("In CIFSSMBLock - timeout %d numLock %d",waitFlag
,numLock
));
1250 rc
= small_smb_init(SMB_COM_LOCKING_ANDX
, 8, tcon
, (void **) &pSMB
);
1255 pSMBr
= (LOCK_RSP
*)pSMB
; /* BB removeme BB */
1257 if(lockType
== LOCKING_ANDX_OPLOCK_RELEASE
) {
1258 timeout
= -1; /* no response expected */
1260 } else if (waitFlag
== TRUE
) {
1261 timeout
= 3; /* blocking operation, no timeout */
1262 pSMB
->Timeout
= cpu_to_le32(-1);/* blocking - do not time out */
1267 pSMB
->NumberOfLocks
= cpu_to_le16(numLock
);
1268 pSMB
->NumberOfUnlocks
= cpu_to_le16(numUnlock
);
1269 pSMB
->LockType
= lockType
;
1270 pSMB
->AndXCommand
= 0xFF; /* none */
1271 pSMB
->Fid
= smb_file_id
; /* netfid stays le */
1273 if((numLock
!= 0) || (numUnlock
!= 0)) {
1274 pSMB
->Locks
[0].Pid
= cpu_to_le16(current
->tgid
);
1275 /* BB where to store pid high? */
1276 pSMB
->Locks
[0].LengthLow
= cpu_to_le32((u32
)len
);
1277 pSMB
->Locks
[0].LengthHigh
= cpu_to_le32((u32
)(len
>>32));
1278 pSMB
->Locks
[0].OffsetLow
= cpu_to_le32((u32
)offset
);
1279 pSMB
->Locks
[0].OffsetHigh
= cpu_to_le32((u32
)(offset
>>32));
1280 count
= sizeof(LOCKING_ANDX_RANGE
);
1285 pSMB
->hdr
.smb_buf_length
+= count
;
1286 pSMB
->ByteCount
= cpu_to_le16(count
);
1288 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
1289 (struct smb_hdr
*) pSMBr
, &bytes_returned
, timeout
);
1290 cifs_stats_inc(&tcon
->num_locks
);
1292 cFYI(1, ("Send error in Lock = %d", rc
));
1294 cifs_small_buf_release(pSMB
);
1296 /* Note: On -EAGAIN error only caller can retry on handle based calls
1297 since file handle passed in no longer valid */
1302 CIFSSMBClose(const int xid
, struct cifsTconInfo
*tcon
, int smb_file_id
)
1305 CLOSE_REQ
*pSMB
= NULL
;
1306 CLOSE_RSP
*pSMBr
= NULL
;
1308 cFYI(1, ("In CIFSSMBClose"));
1310 /* do not retry on dead session on close */
1311 rc
= small_smb_init(SMB_COM_CLOSE
, 3, tcon
, (void **) &pSMB
);
1317 pSMBr
= (CLOSE_RSP
*)pSMB
; /* BB removeme BB */
1319 pSMB
->FileID
= (__u16
) smb_file_id
;
1320 pSMB
->LastWriteTime
= 0;
1321 pSMB
->ByteCount
= 0;
1322 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
1323 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
1324 cifs_stats_inc(&tcon
->num_closes
);
1327 /* EINTR is expected when user ctl-c to kill app */
1328 cERROR(1, ("Send error in Close = %d", rc
));
1332 cifs_small_buf_release(pSMB
);
1334 /* Since session is dead, file will be closed on server already */
1342 CIFSSMBRename(const int xid
, struct cifsTconInfo
*tcon
,
1343 const char *fromName
, const char *toName
,
1344 const struct nls_table
*nls_codepage
, int remap
)
1347 RENAME_REQ
*pSMB
= NULL
;
1348 RENAME_RSP
*pSMBr
= NULL
;
1350 int name_len
, name_len2
;
1353 cFYI(1, ("In CIFSSMBRename"));
1355 rc
= smb_init(SMB_COM_RENAME
, 1, tcon
, (void **) &pSMB
,
1360 pSMB
->BufferFormat
= 0x04;
1361 pSMB
->SearchAttributes
=
1362 cpu_to_le16(ATTR_READONLY
| ATTR_HIDDEN
| ATTR_SYSTEM
|
1365 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
1367 cifsConvertToUCS((__le16
*) pSMB
->OldFileName
, fromName
,
1368 PATH_MAX
, nls_codepage
, remap
);
1369 name_len
++; /* trailing null */
1371 pSMB
->OldFileName
[name_len
] = 0x04; /* pad */
1372 /* protocol requires ASCII signature byte on Unicode string */
1373 pSMB
->OldFileName
[name_len
+ 1] = 0x00;
1375 cifsConvertToUCS((__le16
*) &pSMB
->OldFileName
[name_len
+ 2],
1376 toName
, PATH_MAX
, nls_codepage
, remap
);
1377 name_len2
+= 1 /* trailing null */ + 1 /* Signature word */ ;
1378 name_len2
*= 2; /* convert to bytes */
1379 } else { /* BB improve the check for buffer overruns BB */
1380 name_len
= strnlen(fromName
, PATH_MAX
);
1381 name_len
++; /* trailing null */
1382 strncpy(pSMB
->OldFileName
, fromName
, name_len
);
1383 name_len2
= strnlen(toName
, PATH_MAX
);
1384 name_len2
++; /* trailing null */
1385 pSMB
->OldFileName
[name_len
] = 0x04; /* 2nd buffer format */
1386 strncpy(&pSMB
->OldFileName
[name_len
+ 1], toName
, name_len2
);
1387 name_len2
++; /* trailing null */
1388 name_len2
++; /* signature byte */
1391 count
= 1 /* 1st signature byte */ + name_len
+ name_len2
;
1392 pSMB
->hdr
.smb_buf_length
+= count
;
1393 pSMB
->ByteCount
= cpu_to_le16(count
);
1395 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
1396 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
1397 cifs_stats_inc(&tcon
->num_renames
);
1399 cFYI(1, ("Send error in rename = %d", rc
));
1402 cifs_buf_release(pSMB
);
1410 int CIFSSMBRenameOpenFile(const int xid
,struct cifsTconInfo
*pTcon
,
1411 int netfid
, char * target_name
,
1412 const struct nls_table
* nls_codepage
, int remap
)
1414 struct smb_com_transaction2_sfi_req
*pSMB
= NULL
;
1415 struct smb_com_transaction2_sfi_rsp
*pSMBr
= NULL
;
1416 struct set_file_rename
* rename_info
;
1418 char dummy_string
[30];
1420 int bytes_returned
= 0;
1422 __u16 params
, param_offset
, offset
, count
, byte_count
;
1424 cFYI(1, ("Rename to File by handle"));
1425 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, pTcon
, (void **) &pSMB
,
1431 pSMB
->MaxSetupCount
= 0;
1435 pSMB
->Reserved2
= 0;
1436 param_offset
= offsetof(struct smb_com_transaction2_sfi_req
, Fid
) - 4;
1437 offset
= param_offset
+ params
;
1439 data_offset
= (char *) (&pSMB
->hdr
.Protocol
) + offset
;
1440 rename_info
= (struct set_file_rename
*) data_offset
;
1441 pSMB
->MaxParameterCount
= cpu_to_le16(2);
1442 pSMB
->MaxDataCount
= cpu_to_le16(1000); /* BB find max SMB PDU from sess */
1443 pSMB
->SetupCount
= 1;
1444 pSMB
->Reserved3
= 0;
1445 pSMB
->SubCommand
= cpu_to_le16(TRANS2_SET_FILE_INFORMATION
);
1446 byte_count
= 3 /* pad */ + params
;
1447 pSMB
->ParameterCount
= cpu_to_le16(params
);
1448 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
1449 pSMB
->ParameterOffset
= cpu_to_le16(param_offset
);
1450 pSMB
->DataOffset
= cpu_to_le16(offset
);
1451 /* construct random name ".cifs_tmp<inodenum><mid>" */
1452 rename_info
->overwrite
= cpu_to_le32(1);
1453 rename_info
->root_fid
= 0;
1454 /* unicode only call */
1455 if(target_name
== NULL
) {
1456 sprintf(dummy_string
,"cifs%x",pSMB
->hdr
.Mid
);
1457 len_of_str
= cifsConvertToUCS((__le16
*)rename_info
->target_name
,
1458 dummy_string
, 24, nls_codepage
, remap
);
1460 len_of_str
= cifsConvertToUCS((__le16
*)rename_info
->target_name
,
1461 target_name
, PATH_MAX
, nls_codepage
, remap
);
1463 rename_info
->target_name_len
= cpu_to_le32(2 * len_of_str
);
1464 count
= 12 /* sizeof(struct set_file_rename) */ + (2 * len_of_str
) + 2;
1465 byte_count
+= count
;
1466 pSMB
->DataCount
= cpu_to_le16(count
);
1467 pSMB
->TotalDataCount
= pSMB
->DataCount
;
1469 pSMB
->InformationLevel
=
1470 cpu_to_le16(SMB_SET_FILE_RENAME_INFORMATION
);
1471 pSMB
->Reserved4
= 0;
1472 pSMB
->hdr
.smb_buf_length
+= byte_count
;
1473 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
1474 rc
= SendReceive(xid
, pTcon
->ses
, (struct smb_hdr
*) pSMB
,
1475 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
1476 cifs_stats_inc(&pTcon
->num_t2renames
);
1478 cFYI(1,("Send error in Rename (by file handle) = %d", rc
));
1481 cifs_buf_release(pSMB
);
1483 /* Note: On -EAGAIN error only caller can retry on handle based calls
1484 since file handle passed in no longer valid */
1490 CIFSSMBCopy(const int xid
, struct cifsTconInfo
*tcon
, const char * fromName
,
1491 const __u16 target_tid
, const char *toName
, const int flags
,
1492 const struct nls_table
*nls_codepage
, int remap
)
1495 COPY_REQ
*pSMB
= NULL
;
1496 COPY_RSP
*pSMBr
= NULL
;
1498 int name_len
, name_len2
;
1501 cFYI(1, ("In CIFSSMBCopy"));
1503 rc
= smb_init(SMB_COM_COPY
, 1, tcon
, (void **) &pSMB
,
1508 pSMB
->BufferFormat
= 0x04;
1509 pSMB
->Tid2
= target_tid
;
1511 pSMB
->Flags
= cpu_to_le16(flags
& COPY_TREE
);
1513 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
1514 name_len
= cifsConvertToUCS((__le16
*) pSMB
->OldFileName
,
1515 fromName
, PATH_MAX
, nls_codepage
,
1517 name_len
++; /* trailing null */
1519 pSMB
->OldFileName
[name_len
] = 0x04; /* pad */
1520 /* protocol requires ASCII signature byte on Unicode string */
1521 pSMB
->OldFileName
[name_len
+ 1] = 0x00;
1522 name_len2
= cifsConvertToUCS((__le16
*)&pSMB
->OldFileName
[name_len
+ 2],
1523 toName
, PATH_MAX
, nls_codepage
, remap
);
1524 name_len2
+= 1 /* trailing null */ + 1 /* Signature word */ ;
1525 name_len2
*= 2; /* convert to bytes */
1526 } else { /* BB improve the check for buffer overruns BB */
1527 name_len
= strnlen(fromName
, PATH_MAX
);
1528 name_len
++; /* trailing null */
1529 strncpy(pSMB
->OldFileName
, fromName
, name_len
);
1530 name_len2
= strnlen(toName
, PATH_MAX
);
1531 name_len2
++; /* trailing null */
1532 pSMB
->OldFileName
[name_len
] = 0x04; /* 2nd buffer format */
1533 strncpy(&pSMB
->OldFileName
[name_len
+ 1], toName
, name_len2
);
1534 name_len2
++; /* trailing null */
1535 name_len2
++; /* signature byte */
1538 count
= 1 /* 1st signature byte */ + name_len
+ name_len2
;
1539 pSMB
->hdr
.smb_buf_length
+= count
;
1540 pSMB
->ByteCount
= cpu_to_le16(count
);
1542 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
1543 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
1545 cFYI(1, ("Send error in copy = %d with %d files copied",
1546 rc
, le16_to_cpu(pSMBr
->CopyCount
)));
1549 cifs_buf_release(pSMB
);
1558 CIFSUnixCreateSymLink(const int xid
, struct cifsTconInfo
*tcon
,
1559 const char *fromName
, const char *toName
,
1560 const struct nls_table
*nls_codepage
)
1562 TRANSACTION2_SPI_REQ
*pSMB
= NULL
;
1563 TRANSACTION2_SPI_RSP
*pSMBr
= NULL
;
1566 int name_len_target
;
1568 int bytes_returned
= 0;
1569 __u16 params
, param_offset
, offset
, byte_count
;
1571 cFYI(1, ("In Symlink Unix style"));
1573 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
1578 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
1580 cifs_strtoUCS((__le16
*) pSMB
->FileName
, fromName
, PATH_MAX
1581 /* find define for this maxpathcomponent */
1583 name_len
++; /* trailing null */
1586 } else { /* BB improve the check for buffer overruns BB */
1587 name_len
= strnlen(fromName
, PATH_MAX
);
1588 name_len
++; /* trailing null */
1589 strncpy(pSMB
->FileName
, fromName
, name_len
);
1591 params
= 6 + name_len
;
1592 pSMB
->MaxSetupCount
= 0;
1596 pSMB
->Reserved2
= 0;
1597 param_offset
= offsetof(struct smb_com_transaction2_spi_req
,
1598 InformationLevel
) - 4;
1599 offset
= param_offset
+ params
;
1601 data_offset
= (char *) (&pSMB
->hdr
.Protocol
) + offset
;
1602 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
1604 cifs_strtoUCS((__le16
*) data_offset
, toName
, PATH_MAX
1605 /* find define for this maxpathcomponent */
1607 name_len_target
++; /* trailing null */
1608 name_len_target
*= 2;
1609 } else { /* BB improve the check for buffer overruns BB */
1610 name_len_target
= strnlen(toName
, PATH_MAX
);
1611 name_len_target
++; /* trailing null */
1612 strncpy(data_offset
, toName
, name_len_target
);
1615 pSMB
->MaxParameterCount
= cpu_to_le16(2);
1616 /* BB find exact max on data count below from sess */
1617 pSMB
->MaxDataCount
= cpu_to_le16(1000);
1618 pSMB
->SetupCount
= 1;
1619 pSMB
->Reserved3
= 0;
1620 pSMB
->SubCommand
= cpu_to_le16(TRANS2_SET_PATH_INFORMATION
);
1621 byte_count
= 3 /* pad */ + params
+ name_len_target
;
1622 pSMB
->DataCount
= cpu_to_le16(name_len_target
);
1623 pSMB
->ParameterCount
= cpu_to_le16(params
);
1624 pSMB
->TotalDataCount
= pSMB
->DataCount
;
1625 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
1626 pSMB
->ParameterOffset
= cpu_to_le16(param_offset
);
1627 pSMB
->DataOffset
= cpu_to_le16(offset
);
1628 pSMB
->InformationLevel
= cpu_to_le16(SMB_SET_FILE_UNIX_LINK
);
1629 pSMB
->Reserved4
= 0;
1630 pSMB
->hdr
.smb_buf_length
+= byte_count
;
1631 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
1632 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
1633 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
1634 cifs_stats_inc(&tcon
->num_symlinks
);
1637 ("Send error in SetPathInfo (create symlink) = %d",
1642 cifs_buf_release(pSMB
);
1645 goto createSymLinkRetry
;
1651 CIFSUnixCreateHardLink(const int xid
, struct cifsTconInfo
*tcon
,
1652 const char *fromName
, const char *toName
,
1653 const struct nls_table
*nls_codepage
, int remap
)
1655 TRANSACTION2_SPI_REQ
*pSMB
= NULL
;
1656 TRANSACTION2_SPI_RSP
*pSMBr
= NULL
;
1659 int name_len_target
;
1661 int bytes_returned
= 0;
1662 __u16 params
, param_offset
, offset
, byte_count
;
1664 cFYI(1, ("In Create Hard link Unix style"));
1665 createHardLinkRetry
:
1666 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
1671 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
1672 name_len
= cifsConvertToUCS((__le16
*) pSMB
->FileName
, toName
,
1673 PATH_MAX
, nls_codepage
, remap
);
1674 name_len
++; /* trailing null */
1677 } else { /* BB improve the check for buffer overruns BB */
1678 name_len
= strnlen(toName
, PATH_MAX
);
1679 name_len
++; /* trailing null */
1680 strncpy(pSMB
->FileName
, toName
, name_len
);
1682 params
= 6 + name_len
;
1683 pSMB
->MaxSetupCount
= 0;
1687 pSMB
->Reserved2
= 0;
1688 param_offset
= offsetof(struct smb_com_transaction2_spi_req
,
1689 InformationLevel
) - 4;
1690 offset
= param_offset
+ params
;
1692 data_offset
= (char *) (&pSMB
->hdr
.Protocol
) + offset
;
1693 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
1695 cifsConvertToUCS((__le16
*) data_offset
, fromName
, PATH_MAX
,
1696 nls_codepage
, remap
);
1697 name_len_target
++; /* trailing null */
1698 name_len_target
*= 2;
1699 } else { /* BB improve the check for buffer overruns BB */
1700 name_len_target
= strnlen(fromName
, PATH_MAX
);
1701 name_len_target
++; /* trailing null */
1702 strncpy(data_offset
, fromName
, name_len_target
);
1705 pSMB
->MaxParameterCount
= cpu_to_le16(2);
1706 /* BB find exact max on data count below from sess*/
1707 pSMB
->MaxDataCount
= cpu_to_le16(1000);
1708 pSMB
->SetupCount
= 1;
1709 pSMB
->Reserved3
= 0;
1710 pSMB
->SubCommand
= cpu_to_le16(TRANS2_SET_PATH_INFORMATION
);
1711 byte_count
= 3 /* pad */ + params
+ name_len_target
;
1712 pSMB
->ParameterCount
= cpu_to_le16(params
);
1713 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
1714 pSMB
->DataCount
= cpu_to_le16(name_len_target
);
1715 pSMB
->TotalDataCount
= pSMB
->DataCount
;
1716 pSMB
->ParameterOffset
= cpu_to_le16(param_offset
);
1717 pSMB
->DataOffset
= cpu_to_le16(offset
);
1718 pSMB
->InformationLevel
= cpu_to_le16(SMB_SET_FILE_UNIX_HLINK
);
1719 pSMB
->Reserved4
= 0;
1720 pSMB
->hdr
.smb_buf_length
+= byte_count
;
1721 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
1722 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
1723 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
1724 cifs_stats_inc(&tcon
->num_hardlinks
);
1726 cFYI(1, ("Send error in SetPathInfo (hard link) = %d", rc
));
1729 cifs_buf_release(pSMB
);
1731 goto createHardLinkRetry
;
1737 CIFSCreateHardLink(const int xid
, struct cifsTconInfo
*tcon
,
1738 const char *fromName
, const char *toName
,
1739 const struct nls_table
*nls_codepage
, int remap
)
1742 NT_RENAME_REQ
*pSMB
= NULL
;
1743 RENAME_RSP
*pSMBr
= NULL
;
1745 int name_len
, name_len2
;
1748 cFYI(1, ("In CIFSCreateHardLink"));
1749 winCreateHardLinkRetry
:
1751 rc
= smb_init(SMB_COM_NT_RENAME
, 4, tcon
, (void **) &pSMB
,
1756 pSMB
->SearchAttributes
=
1757 cpu_to_le16(ATTR_READONLY
| ATTR_HIDDEN
| ATTR_SYSTEM
|
1759 pSMB
->Flags
= cpu_to_le16(CREATE_HARD_LINK
);
1760 pSMB
->ClusterCount
= 0;
1762 pSMB
->BufferFormat
= 0x04;
1764 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
1766 cifsConvertToUCS((__le16
*) pSMB
->OldFileName
, fromName
,
1767 PATH_MAX
, nls_codepage
, remap
);
1768 name_len
++; /* trailing null */
1770 pSMB
->OldFileName
[name_len
] = 0; /* pad */
1771 pSMB
->OldFileName
[name_len
+ 1] = 0x04;
1773 cifsConvertToUCS((__le16
*)&pSMB
->OldFileName
[name_len
+ 2],
1774 toName
, PATH_MAX
, nls_codepage
, remap
);
1775 name_len2
+= 1 /* trailing null */ + 1 /* Signature word */ ;
1776 name_len2
*= 2; /* convert to bytes */
1777 } else { /* BB improve the check for buffer overruns BB */
1778 name_len
= strnlen(fromName
, PATH_MAX
);
1779 name_len
++; /* trailing null */
1780 strncpy(pSMB
->OldFileName
, fromName
, name_len
);
1781 name_len2
= strnlen(toName
, PATH_MAX
);
1782 name_len2
++; /* trailing null */
1783 pSMB
->OldFileName
[name_len
] = 0x04; /* 2nd buffer format */
1784 strncpy(&pSMB
->OldFileName
[name_len
+ 1], toName
, name_len2
);
1785 name_len2
++; /* trailing null */
1786 name_len2
++; /* signature byte */
1789 count
= 1 /* string type byte */ + name_len
+ name_len2
;
1790 pSMB
->hdr
.smb_buf_length
+= count
;
1791 pSMB
->ByteCount
= cpu_to_le16(count
);
1793 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
1794 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
1795 cifs_stats_inc(&tcon
->num_hardlinks
);
1797 cFYI(1, ("Send error in hard link (NT rename) = %d", rc
));
1799 cifs_buf_release(pSMB
);
1801 goto winCreateHardLinkRetry
;
1807 CIFSSMBUnixQuerySymLink(const int xid
, struct cifsTconInfo
*tcon
,
1808 const unsigned char *searchName
,
1809 char *symlinkinfo
, const int buflen
,
1810 const struct nls_table
*nls_codepage
)
1812 /* SMB_QUERY_FILE_UNIX_LINK */
1813 TRANSACTION2_QPI_REQ
*pSMB
= NULL
;
1814 TRANSACTION2_QPI_RSP
*pSMBr
= NULL
;
1818 __u16 params
, byte_count
;
1820 cFYI(1, ("In QPathSymLinkInfo (Unix) for path %s", searchName
));
1823 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
1828 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
1830 cifs_strtoUCS((__le16
*) pSMB
->FileName
, searchName
, PATH_MAX
1831 /* find define for this maxpathcomponent */
1833 name_len
++; /* trailing null */
1835 } else { /* BB improve the check for buffer overruns BB */
1836 name_len
= strnlen(searchName
, PATH_MAX
);
1837 name_len
++; /* trailing null */
1838 strncpy(pSMB
->FileName
, searchName
, name_len
);
1841 params
= 2 /* level */ + 4 /* rsrvd */ + name_len
/* incl null */ ;
1842 pSMB
->TotalDataCount
= 0;
1843 pSMB
->MaxParameterCount
= cpu_to_le16(2);
1844 /* BB find exact max data count below from sess structure BB */
1845 pSMB
->MaxDataCount
= cpu_to_le16(4000);
1846 pSMB
->MaxSetupCount
= 0;
1850 pSMB
->Reserved2
= 0;
1851 pSMB
->ParameterOffset
= cpu_to_le16(offsetof(
1852 struct smb_com_transaction2_qpi_req
,InformationLevel
) - 4);
1853 pSMB
->DataCount
= 0;
1854 pSMB
->DataOffset
= 0;
1855 pSMB
->SetupCount
= 1;
1856 pSMB
->Reserved3
= 0;
1857 pSMB
->SubCommand
= cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION
);
1858 byte_count
= params
+ 1 /* pad */ ;
1859 pSMB
->TotalParameterCount
= cpu_to_le16(params
);
1860 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
1861 pSMB
->InformationLevel
= cpu_to_le16(SMB_QUERY_FILE_UNIX_LINK
);
1862 pSMB
->Reserved4
= 0;
1863 pSMB
->hdr
.smb_buf_length
+= byte_count
;
1864 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
1866 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
1867 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
1869 cFYI(1, ("Send error in QuerySymLinkInfo = %d", rc
));
1871 /* decode response */
1873 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
1874 if (rc
|| (pSMBr
->ByteCount
< 2))
1875 /* BB also check enough total bytes returned */
1876 rc
= -EIO
; /* bad smb */
1878 __u16 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
1879 __u16 count
= le16_to_cpu(pSMBr
->t2
.DataCount
);
1881 if (pSMBr
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
1882 name_len
= UniStrnlen((wchar_t *) ((char *)
1883 &pSMBr
->hdr
.Protocol
+data_offset
),
1884 min_t(const int, buflen
,count
) / 2);
1885 /* BB FIXME investigate remapping reserved chars here */
1886 cifs_strfromUCS_le(symlinkinfo
,
1887 (__le16
*) ((char *)&pSMBr
->hdr
.Protocol
+
1889 name_len
, nls_codepage
);
1891 strncpy(symlinkinfo
,
1892 (char *) &pSMBr
->hdr
.Protocol
+
1894 min_t(const int, buflen
, count
));
1896 symlinkinfo
[buflen
] = 0;
1897 /* just in case so calling code does not go off the end of buffer */
1900 cifs_buf_release(pSMB
);
1902 goto querySymLinkRetry
;
1907 CIFSSMBQueryReparseLinkInfo(const int xid
, struct cifsTconInfo
*tcon
,
1908 const unsigned char *searchName
,
1909 char *symlinkinfo
, const int buflen
,__u16 fid
,
1910 const struct nls_table
*nls_codepage
)
1915 struct smb_com_transaction_ioctl_req
* pSMB
;
1916 struct smb_com_transaction_ioctl_rsp
* pSMBr
;
1918 cFYI(1, ("In Windows reparse style QueryLink for path %s", searchName
));
1919 rc
= smb_init(SMB_COM_NT_TRANSACT
, 23, tcon
, (void **) &pSMB
,
1924 pSMB
->TotalParameterCount
= 0 ;
1925 pSMB
->TotalDataCount
= 0;
1926 pSMB
->MaxParameterCount
= cpu_to_le32(2);
1927 /* BB find exact data count max from sess structure BB */
1928 pSMB
->MaxDataCount
= cpu_to_le32(4000);
1929 pSMB
->MaxSetupCount
= 4;
1931 pSMB
->ParameterOffset
= 0;
1932 pSMB
->DataCount
= 0;
1933 pSMB
->DataOffset
= 0;
1934 pSMB
->SetupCount
= 4;
1935 pSMB
->SubCommand
= cpu_to_le16(NT_TRANSACT_IOCTL
);
1936 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
1937 pSMB
->FunctionCode
= cpu_to_le32(FSCTL_GET_REPARSE_POINT
);
1938 pSMB
->IsFsctl
= 1; /* FSCTL */
1939 pSMB
->IsRootFlag
= 0;
1940 pSMB
->Fid
= fid
; /* file handle always le */
1941 pSMB
->ByteCount
= 0;
1943 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
1944 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
1946 cFYI(1, ("Send error in QueryReparseLinkInfo = %d", rc
));
1947 } else { /* decode response */
1948 __u32 data_offset
= le32_to_cpu(pSMBr
->DataOffset
);
1949 __u32 data_count
= le32_to_cpu(pSMBr
->DataCount
);
1950 if ((pSMBr
->ByteCount
< 2) || (data_offset
> 512))
1951 /* BB also check enough total bytes returned */
1952 rc
= -EIO
; /* bad smb */
1954 if(data_count
&& (data_count
< 2048)) {
1955 char * end_of_smb
= pSMBr
->ByteCount
+ (char *)&pSMBr
->ByteCount
;
1957 struct reparse_data
* reparse_buf
= (struct reparse_data
*)
1958 ((char *)&pSMBr
->hdr
.Protocol
+ data_offset
);
1959 if((char*)reparse_buf
>= end_of_smb
) {
1963 if((reparse_buf
->LinkNamesBuf
+
1964 reparse_buf
->TargetNameOffset
+
1965 reparse_buf
->TargetNameLen
) >
1967 cFYI(1,("reparse buf extended beyond SMB"));
1972 if (pSMBr
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
1973 name_len
= UniStrnlen((wchar_t *)
1974 (reparse_buf
->LinkNamesBuf
+
1975 reparse_buf
->TargetNameOffset
),
1976 min(buflen
/2, reparse_buf
->TargetNameLen
/ 2));
1977 cifs_strfromUCS_le(symlinkinfo
,
1978 (__le16
*) (reparse_buf
->LinkNamesBuf
+
1979 reparse_buf
->TargetNameOffset
),
1980 name_len
, nls_codepage
);
1981 } else { /* ASCII names */
1982 strncpy(symlinkinfo
,reparse_buf
->LinkNamesBuf
+
1983 reparse_buf
->TargetNameOffset
,
1984 min_t(const int, buflen
, reparse_buf
->TargetNameLen
));
1988 cFYI(1,("Invalid return data count on get reparse info ioctl"));
1990 symlinkinfo
[buflen
] = 0; /* just in case so the caller
1991 does not go off the end of the buffer */
1992 cFYI(1,("readlink result - %s ",symlinkinfo
));
1996 cifs_buf_release(pSMB
);
1998 /* Note: On -EAGAIN error only caller can retry on handle based calls
1999 since file handle passed in no longer valid */
2004 #ifdef CONFIG_CIFS_POSIX
2006 /*Convert an Access Control Entry from wire format to local POSIX xattr format*/
2007 static void cifs_convert_ace(posix_acl_xattr_entry
* ace
, struct cifs_posix_ace
* cifs_ace
)
2009 /* u8 cifs fields do not need le conversion */
2010 ace
->e_perm
= cpu_to_le16(cifs_ace
->cifs_e_perm
);
2011 ace
->e_tag
= cpu_to_le16(cifs_ace
->cifs_e_tag
);
2012 ace
->e_id
= cpu_to_le32(le64_to_cpu(cifs_ace
->cifs_uid
));
2013 /* cFYI(1,("perm %d tag %d id %d",ace->e_perm,ace->e_tag,ace->e_id)); */
2018 /* Convert ACL from CIFS POSIX wire format to local Linux POSIX ACL xattr */
2019 static int cifs_copy_posix_acl(char * trgt
,char * src
, const int buflen
,
2020 const int acl_type
,const int size_of_data_area
)
2025 struct cifs_posix_ace
* pACE
;
2026 struct cifs_posix_acl
* cifs_acl
= (struct cifs_posix_acl
*)src
;
2027 posix_acl_xattr_header
* local_acl
= (posix_acl_xattr_header
*)trgt
;
2029 if (le16_to_cpu(cifs_acl
->version
) != CIFS_ACL_VERSION
)
2032 if(acl_type
& ACL_TYPE_ACCESS
) {
2033 count
= le16_to_cpu(cifs_acl
->access_entry_count
);
2034 pACE
= &cifs_acl
->ace_array
[0];
2035 size
= sizeof(struct cifs_posix_acl
);
2036 size
+= sizeof(struct cifs_posix_ace
) * count
;
2037 /* check if we would go beyond end of SMB */
2038 if(size_of_data_area
< size
) {
2039 cFYI(1,("bad CIFS POSIX ACL size %d vs. %d",size_of_data_area
,size
));
2042 } else if(acl_type
& ACL_TYPE_DEFAULT
) {
2043 count
= le16_to_cpu(cifs_acl
->access_entry_count
);
2044 size
= sizeof(struct cifs_posix_acl
);
2045 size
+= sizeof(struct cifs_posix_ace
) * count
;
2046 /* skip past access ACEs to get to default ACEs */
2047 pACE
= &cifs_acl
->ace_array
[count
];
2048 count
= le16_to_cpu(cifs_acl
->default_entry_count
);
2049 size
+= sizeof(struct cifs_posix_ace
) * count
;
2050 /* check if we would go beyond end of SMB */
2051 if(size_of_data_area
< size
)
2058 size
= posix_acl_xattr_size(count
);
2059 if((buflen
== 0) || (local_acl
== NULL
)) {
2060 /* used to query ACL EA size */
2061 } else if(size
> buflen
) {
2063 } else /* buffer big enough */ {
2064 local_acl
->a_version
= cpu_to_le32(POSIX_ACL_XATTR_VERSION
);
2065 for(i
= 0;i
< count
;i
++) {
2066 cifs_convert_ace(&local_acl
->a_entries
[i
],pACE
);
2073 static __u16
convert_ace_to_cifs_ace(struct cifs_posix_ace
* cifs_ace
,
2074 const posix_acl_xattr_entry
* local_ace
)
2076 __u16 rc
= 0; /* 0 = ACL converted ok */
2078 cifs_ace
->cifs_e_perm
= le16_to_cpu(local_ace
->e_perm
);
2079 cifs_ace
->cifs_e_tag
= le16_to_cpu(local_ace
->e_tag
);
2080 /* BB is there a better way to handle the large uid? */
2081 if(local_ace
->e_id
== cpu_to_le32(-1)) {
2082 /* Probably no need to le convert -1 on any arch but can not hurt */
2083 cifs_ace
->cifs_uid
= cpu_to_le64(-1);
2085 cifs_ace
->cifs_uid
= cpu_to_le64(le32_to_cpu(local_ace
->e_id
));
2086 /*cFYI(1,("perm %d tag %d id %d",ace->e_perm,ace->e_tag,ace->e_id));*/
2090 /* Convert ACL from local Linux POSIX xattr to CIFS POSIX ACL wire format */
2091 static __u16
ACL_to_cifs_posix(char * parm_data
,const char * pACL
,const int buflen
,
2095 struct cifs_posix_acl
* cifs_acl
= (struct cifs_posix_acl
*)parm_data
;
2096 posix_acl_xattr_header
* local_acl
= (posix_acl_xattr_header
*)pACL
;
2100 if((buflen
== 0) || (pACL
== NULL
) || (cifs_acl
== NULL
))
2103 count
= posix_acl_xattr_count((size_t)buflen
);
2104 cFYI(1,("setting acl with %d entries from buf of length %d and version of %d",
2105 count
, buflen
, le32_to_cpu(local_acl
->a_version
)));
2106 if(le32_to_cpu(local_acl
->a_version
) != 2) {
2107 cFYI(1,("unknown POSIX ACL version %d",
2108 le32_to_cpu(local_acl
->a_version
)));
2111 cifs_acl
->version
= cpu_to_le16(1);
2112 if(acl_type
== ACL_TYPE_ACCESS
)
2113 cifs_acl
->access_entry_count
= cpu_to_le16(count
);
2114 else if(acl_type
== ACL_TYPE_DEFAULT
)
2115 cifs_acl
->default_entry_count
= cpu_to_le16(count
);
2117 cFYI(1,("unknown ACL type %d",acl_type
));
2120 for(i
=0;i
<count
;i
++) {
2121 rc
= convert_ace_to_cifs_ace(&cifs_acl
->ace_array
[i
],
2122 &local_acl
->a_entries
[i
]);
2124 /* ACE not converted */
2129 rc
= (__u16
)(count
* sizeof(struct cifs_posix_ace
));
2130 rc
+= sizeof(struct cifs_posix_acl
);
2131 /* BB add check to make sure ACL does not overflow SMB */
2137 CIFSSMBGetPosixACL(const int xid
, struct cifsTconInfo
*tcon
,
2138 const unsigned char *searchName
,
2139 char *acl_inf
, const int buflen
, const int acl_type
,
2140 const struct nls_table
*nls_codepage
, int remap
)
2142 /* SMB_QUERY_POSIX_ACL */
2143 TRANSACTION2_QPI_REQ
*pSMB
= NULL
;
2144 TRANSACTION2_QPI_RSP
*pSMBr
= NULL
;
2148 __u16 params
, byte_count
;
2150 cFYI(1, ("In GetPosixACL (Unix) for path %s", searchName
));
2153 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
2158 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
2160 cifsConvertToUCS((__le16
*) pSMB
->FileName
, searchName
,
2161 PATH_MAX
, nls_codepage
, remap
);
2162 name_len
++; /* trailing null */
2164 pSMB
->FileName
[name_len
] = 0;
2165 pSMB
->FileName
[name_len
+1] = 0;
2166 } else { /* BB improve the check for buffer overruns BB */
2167 name_len
= strnlen(searchName
, PATH_MAX
);
2168 name_len
++; /* trailing null */
2169 strncpy(pSMB
->FileName
, searchName
, name_len
);
2172 params
= 2 /* level */ + 4 /* rsrvd */ + name_len
/* incl null */ ;
2173 pSMB
->TotalDataCount
= 0;
2174 pSMB
->MaxParameterCount
= cpu_to_le16(2);
2175 /* BB find exact max data count below from sess structure BB */
2176 pSMB
->MaxDataCount
= cpu_to_le16(4000);
2177 pSMB
->MaxSetupCount
= 0;
2181 pSMB
->Reserved2
= 0;
2182 pSMB
->ParameterOffset
= cpu_to_le16(
2183 offsetof(struct smb_com_transaction2_qpi_req
,InformationLevel
) - 4);
2184 pSMB
->DataCount
= 0;
2185 pSMB
->DataOffset
= 0;
2186 pSMB
->SetupCount
= 1;
2187 pSMB
->Reserved3
= 0;
2188 pSMB
->SubCommand
= cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION
);
2189 byte_count
= params
+ 1 /* pad */ ;
2190 pSMB
->TotalParameterCount
= cpu_to_le16(params
);
2191 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
2192 pSMB
->InformationLevel
= cpu_to_le16(SMB_QUERY_POSIX_ACL
);
2193 pSMB
->Reserved4
= 0;
2194 pSMB
->hdr
.smb_buf_length
+= byte_count
;
2195 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
2197 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
2198 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
2200 cFYI(1, ("Send error in Query POSIX ACL = %d", rc
));
2202 /* decode response */
2204 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
2205 if (rc
|| (pSMBr
->ByteCount
< 2))
2206 /* BB also check enough total bytes returned */
2207 rc
= -EIO
; /* bad smb */
2209 __u16 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
2210 __u16 count
= le16_to_cpu(pSMBr
->t2
.DataCount
);
2211 rc
= cifs_copy_posix_acl(acl_inf
,
2212 (char *)&pSMBr
->hdr
.Protocol
+data_offset
,
2213 buflen
,acl_type
,count
);
2216 cifs_buf_release(pSMB
);
2223 CIFSSMBSetPosixACL(const int xid
, struct cifsTconInfo
*tcon
,
2224 const unsigned char *fileName
,
2225 const char *local_acl
, const int buflen
,
2227 const struct nls_table
*nls_codepage
, int remap
)
2229 struct smb_com_transaction2_spi_req
*pSMB
= NULL
;
2230 struct smb_com_transaction2_spi_rsp
*pSMBr
= NULL
;
2234 int bytes_returned
= 0;
2235 __u16 params
, byte_count
, data_count
, param_offset
, offset
;
2237 cFYI(1, ("In SetPosixACL (Unix) for path %s", fileName
));
2239 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
2243 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
2245 cifsConvertToUCS((__le16
*) pSMB
->FileName
, fileName
,
2246 PATH_MAX
, nls_codepage
, remap
);
2247 name_len
++; /* trailing null */
2249 } else { /* BB improve the check for buffer overruns BB */
2250 name_len
= strnlen(fileName
, PATH_MAX
);
2251 name_len
++; /* trailing null */
2252 strncpy(pSMB
->FileName
, fileName
, name_len
);
2254 params
= 6 + name_len
;
2255 pSMB
->MaxParameterCount
= cpu_to_le16(2);
2256 pSMB
->MaxDataCount
= cpu_to_le16(1000); /* BB find max SMB size from sess */
2257 pSMB
->MaxSetupCount
= 0;
2261 pSMB
->Reserved2
= 0;
2262 param_offset
= offsetof(struct smb_com_transaction2_spi_req
,
2263 InformationLevel
) - 4;
2264 offset
= param_offset
+ params
;
2265 parm_data
= ((char *) &pSMB
->hdr
.Protocol
) + offset
;
2266 pSMB
->ParameterOffset
= cpu_to_le16(param_offset
);
2268 /* convert to on the wire format for POSIX ACL */
2269 data_count
= ACL_to_cifs_posix(parm_data
,local_acl
,buflen
,acl_type
);
2271 if(data_count
== 0) {
2273 goto setACLerrorExit
;
2275 pSMB
->DataOffset
= cpu_to_le16(offset
);
2276 pSMB
->SetupCount
= 1;
2277 pSMB
->Reserved3
= 0;
2278 pSMB
->SubCommand
= cpu_to_le16(TRANS2_SET_PATH_INFORMATION
);
2279 pSMB
->InformationLevel
= cpu_to_le16(SMB_SET_POSIX_ACL
);
2280 byte_count
= 3 /* pad */ + params
+ data_count
;
2281 pSMB
->DataCount
= cpu_to_le16(data_count
);
2282 pSMB
->TotalDataCount
= pSMB
->DataCount
;
2283 pSMB
->ParameterCount
= cpu_to_le16(params
);
2284 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
2285 pSMB
->Reserved4
= 0;
2286 pSMB
->hdr
.smb_buf_length
+= byte_count
;
2287 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
2288 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
2289 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
2291 cFYI(1, ("Set POSIX ACL returned %d", rc
));
2295 cifs_buf_release(pSMB
);
2301 /* BB fix tabs in this function FIXME BB */
2303 CIFSGetExtAttr(const int xid
, struct cifsTconInfo
*tcon
,
2304 const int netfid
, __u64
* pExtAttrBits
, __u64
*pMask
)
2307 struct smb_t2_qfi_req
*pSMB
= NULL
;
2308 struct smb_t2_qfi_rsp
*pSMBr
= NULL
;
2310 __u16 params
, byte_count
;
2312 cFYI(1,("In GetExtAttr"));
2317 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
2322 params
= 2 /* level */ +2 /* fid */;
2323 pSMB
->t2
.TotalDataCount
= 0;
2324 pSMB
->t2
.MaxParameterCount
= cpu_to_le16(4);
2325 /* BB find exact max data count below from sess structure BB */
2326 pSMB
->t2
.MaxDataCount
= cpu_to_le16(4000);
2327 pSMB
->t2
.MaxSetupCount
= 0;
2328 pSMB
->t2
.Reserved
= 0;
2330 pSMB
->t2
.Timeout
= 0;
2331 pSMB
->t2
.Reserved2
= 0;
2332 pSMB
->t2
.ParameterOffset
= cpu_to_le16(offsetof(struct smb_t2_qfi_req
,
2334 pSMB
->t2
.DataCount
= 0;
2335 pSMB
->t2
.DataOffset
= 0;
2336 pSMB
->t2
.SetupCount
= 1;
2337 pSMB
->t2
.Reserved3
= 0;
2338 pSMB
->t2
.SubCommand
= cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION
);
2339 byte_count
= params
+ 1 /* pad */ ;
2340 pSMB
->t2
.TotalParameterCount
= cpu_to_le16(params
);
2341 pSMB
->t2
.ParameterCount
= pSMB
->t2
.TotalParameterCount
;
2342 pSMB
->InformationLevel
= cpu_to_le16(SMB_QUERY_ATTR_FLAGS
);
2345 pSMB
->hdr
.smb_buf_length
+= byte_count
;
2346 pSMB
->t2
.ByteCount
= cpu_to_le16(byte_count
);
2348 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
2349 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
2351 cFYI(1, ("error %d in GetExtAttr", rc
));
2353 /* decode response */
2354 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
2355 if (rc
|| (pSMBr
->ByteCount
< 2))
2356 /* BB also check enough total bytes returned */
2357 /* If rc should we check for EOPNOSUPP and
2358 disable the srvino flag? or in caller? */
2359 rc
= -EIO
; /* bad smb */
2361 __u16 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
2362 __u16 count
= le16_to_cpu(pSMBr
->t2
.DataCount
);
2363 struct file_chattr_info
* pfinfo
;
2364 /* BB Do we need a cast or hash here ? */
2366 cFYI(1, ("Illegal size ret in GetExtAttr"));
2370 pfinfo
= (struct file_chattr_info
*)
2371 (data_offset
+ (char *) &pSMBr
->hdr
.Protocol
);
2372 *pExtAttrBits
= le64_to_cpu(pfinfo
->mode
);
2373 *pMask
= le64_to_cpu(pfinfo
->mask
);
2377 cifs_buf_release(pSMB
);
2379 goto GetExtAttrRetry
;
2384 #endif /* CONFIG_POSIX */
2386 /* Legacy Query Path Information call for lookup to old servers such
2388 int SMBQueryInformation(const int xid
, struct cifsTconInfo
*tcon
,
2389 const unsigned char *searchName
,
2390 FILE_ALL_INFO
* pFinfo
,
2391 const struct nls_table
*nls_codepage
, int remap
)
2393 QUERY_INFORMATION_REQ
* pSMB
;
2394 QUERY_INFORMATION_RSP
* pSMBr
;
2399 cFYI(1, ("In SMBQPath path %s", searchName
));
2401 rc
= smb_init(SMB_COM_QUERY_INFORMATION
, 0, tcon
, (void **) &pSMB
,
2406 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
2408 cifsConvertToUCS((__le16
*) pSMB
->FileName
, searchName
,
2409 PATH_MAX
, nls_codepage
, remap
);
2410 name_len
++; /* trailing null */
2413 name_len
= strnlen(searchName
, PATH_MAX
);
2414 name_len
++; /* trailing null */
2415 strncpy(pSMB
->FileName
, searchName
, name_len
);
2417 pSMB
->BufferFormat
= 0x04;
2418 name_len
++; /* account for buffer type byte */
2419 pSMB
->hdr
.smb_buf_length
+= (__u16
) name_len
;
2420 pSMB
->ByteCount
= cpu_to_le16(name_len
);
2422 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
2423 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
2425 cFYI(1, ("Send error in QueryInfo = %d", rc
));
2426 } else if (pFinfo
) { /* decode response */
2427 memset(pFinfo
, 0, sizeof(FILE_ALL_INFO
));
2428 pFinfo
->AllocationSize
=
2429 cpu_to_le64(le32_to_cpu(pSMBr
->size
));
2430 pFinfo
->EndOfFile
= pFinfo
->AllocationSize
;
2431 pFinfo
->Attributes
=
2432 cpu_to_le32(le16_to_cpu(pSMBr
->attr
));
2434 rc
= -EIO
; /* bad buffer passed in */
2436 cifs_buf_release(pSMB
);
2448 CIFSSMBQPathInfo(const int xid
, struct cifsTconInfo
*tcon
,
2449 const unsigned char *searchName
,
2450 FILE_ALL_INFO
* pFindData
,
2451 const struct nls_table
*nls_codepage
, int remap
)
2453 /* level 263 SMB_QUERY_FILE_ALL_INFO */
2454 TRANSACTION2_QPI_REQ
*pSMB
= NULL
;
2455 TRANSACTION2_QPI_RSP
*pSMBr
= NULL
;
2459 __u16 params
, byte_count
;
2461 /* cFYI(1, ("In QPathInfo path %s", searchName)); */
2463 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
2468 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
2470 cifsConvertToUCS((__le16
*) pSMB
->FileName
, searchName
,
2471 PATH_MAX
, nls_codepage
, remap
);
2472 name_len
++; /* trailing null */
2474 } else { /* BB improve the check for buffer overruns BB */
2475 name_len
= strnlen(searchName
, PATH_MAX
);
2476 name_len
++; /* trailing null */
2477 strncpy(pSMB
->FileName
, searchName
, name_len
);
2480 params
= 2 /* level */ + 4 /* reserved */ + name_len
/* includes NUL */ ;
2481 pSMB
->TotalDataCount
= 0;
2482 pSMB
->MaxParameterCount
= cpu_to_le16(2);
2483 pSMB
->MaxDataCount
= cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
2484 pSMB
->MaxSetupCount
= 0;
2488 pSMB
->Reserved2
= 0;
2489 pSMB
->ParameterOffset
= cpu_to_le16(offsetof(
2490 struct smb_com_transaction2_qpi_req
,InformationLevel
) - 4);
2491 pSMB
->DataCount
= 0;
2492 pSMB
->DataOffset
= 0;
2493 pSMB
->SetupCount
= 1;
2494 pSMB
->Reserved3
= 0;
2495 pSMB
->SubCommand
= cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION
);
2496 byte_count
= params
+ 1 /* pad */ ;
2497 pSMB
->TotalParameterCount
= cpu_to_le16(params
);
2498 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
2499 pSMB
->InformationLevel
= cpu_to_le16(SMB_QUERY_FILE_ALL_INFO
);
2500 pSMB
->Reserved4
= 0;
2501 pSMB
->hdr
.smb_buf_length
+= byte_count
;
2502 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
2504 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
2505 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
2507 cFYI(1, ("Send error in QPathInfo = %d", rc
));
2508 } else { /* decode response */
2509 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
2511 if (rc
|| (pSMBr
->ByteCount
< 40))
2512 rc
= -EIO
; /* bad smb */
2513 else if (pFindData
){
2514 __u16 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
2515 memcpy((char *) pFindData
,
2516 (char *) &pSMBr
->hdr
.Protocol
+
2517 data_offset
, sizeof (FILE_ALL_INFO
));
2521 cifs_buf_release(pSMB
);
2523 goto QPathInfoRetry
;
2529 CIFSSMBUnixQPathInfo(const int xid
, struct cifsTconInfo
*tcon
,
2530 const unsigned char *searchName
,
2531 FILE_UNIX_BASIC_INFO
* pFindData
,
2532 const struct nls_table
*nls_codepage
, int remap
)
2534 /* SMB_QUERY_FILE_UNIX_BASIC */
2535 TRANSACTION2_QPI_REQ
*pSMB
= NULL
;
2536 TRANSACTION2_QPI_RSP
*pSMBr
= NULL
;
2538 int bytes_returned
= 0;
2540 __u16 params
, byte_count
;
2542 cFYI(1, ("In QPathInfo (Unix) the path %s", searchName
));
2544 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
2549 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
2551 cifsConvertToUCS((__le16
*) pSMB
->FileName
, searchName
,
2552 PATH_MAX
, nls_codepage
, remap
);
2553 name_len
++; /* trailing null */
2555 } else { /* BB improve the check for buffer overruns BB */
2556 name_len
= strnlen(searchName
, PATH_MAX
);
2557 name_len
++; /* trailing null */
2558 strncpy(pSMB
->FileName
, searchName
, name_len
);
2561 params
= 2 /* level */ + 4 /* reserved */ + name_len
/* includes NUL */ ;
2562 pSMB
->TotalDataCount
= 0;
2563 pSMB
->MaxParameterCount
= cpu_to_le16(2);
2564 /* BB find exact max SMB PDU from sess structure BB */
2565 pSMB
->MaxDataCount
= cpu_to_le16(4000);
2566 pSMB
->MaxSetupCount
= 0;
2570 pSMB
->Reserved2
= 0;
2571 pSMB
->ParameterOffset
= cpu_to_le16(offsetof(
2572 struct smb_com_transaction2_qpi_req
,InformationLevel
) - 4);
2573 pSMB
->DataCount
= 0;
2574 pSMB
->DataOffset
= 0;
2575 pSMB
->SetupCount
= 1;
2576 pSMB
->Reserved3
= 0;
2577 pSMB
->SubCommand
= cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION
);
2578 byte_count
= params
+ 1 /* pad */ ;
2579 pSMB
->TotalParameterCount
= cpu_to_le16(params
);
2580 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
2581 pSMB
->InformationLevel
= cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC
);
2582 pSMB
->Reserved4
= 0;
2583 pSMB
->hdr
.smb_buf_length
+= byte_count
;
2584 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
2586 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
2587 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
2589 cFYI(1, ("Send error in QPathInfo = %d", rc
));
2590 } else { /* decode response */
2591 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
2593 if (rc
|| (pSMBr
->ByteCount
< sizeof(FILE_UNIX_BASIC_INFO
))) {
2594 rc
= -EIO
; /* bad smb */
2596 __u16 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
2597 memcpy((char *) pFindData
,
2598 (char *) &pSMBr
->hdr
.Protocol
+
2600 sizeof (FILE_UNIX_BASIC_INFO
));
2603 cifs_buf_release(pSMB
);
2605 goto UnixQPathInfoRetry
;
2610 #if 0 /* function unused at present */
2611 int CIFSFindSingle(const int xid
, struct cifsTconInfo
*tcon
,
2612 const char *searchName
, FILE_ALL_INFO
* findData
,
2613 const struct nls_table
*nls_codepage
)
2615 /* level 257 SMB_ */
2616 TRANSACTION2_FFIRST_REQ
*pSMB
= NULL
;
2617 TRANSACTION2_FFIRST_RSP
*pSMBr
= NULL
;
2621 __u16 params
, byte_count
;
2623 cFYI(1, ("In FindUnique"));
2625 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
2630 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
2632 cifsConvertToUCS((__le16
*) pSMB
->FileName
, searchName
, PATH_MAX
2633 /* find define for this maxpathcomponent */
2635 name_len
++; /* trailing null */
2637 } else { /* BB improve the check for buffer overruns BB */
2638 name_len
= strnlen(searchName
, PATH_MAX
);
2639 name_len
++; /* trailing null */
2640 strncpy(pSMB
->FileName
, searchName
, name_len
);
2643 params
= 12 + name_len
/* includes null */ ;
2644 pSMB
->TotalDataCount
= 0; /* no EAs */
2645 pSMB
->MaxParameterCount
= cpu_to_le16(2);
2646 pSMB
->MaxDataCount
= cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
2647 pSMB
->MaxSetupCount
= 0;
2651 pSMB
->Reserved2
= 0;
2652 pSMB
->ParameterOffset
= cpu_to_le16(
2653 offsetof(struct smb_com_transaction2_ffirst_req
,InformationLevel
) - 4);
2654 pSMB
->DataCount
= 0;
2655 pSMB
->DataOffset
= 0;
2656 pSMB
->SetupCount
= 1; /* one byte, no need to le convert */
2657 pSMB
->Reserved3
= 0;
2658 pSMB
->SubCommand
= cpu_to_le16(TRANS2_FIND_FIRST
);
2659 byte_count
= params
+ 1 /* pad */ ;
2660 pSMB
->TotalParameterCount
= cpu_to_le16(params
);
2661 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
2662 pSMB
->SearchAttributes
=
2663 cpu_to_le16(ATTR_READONLY
| ATTR_HIDDEN
| ATTR_SYSTEM
|
2665 pSMB
->SearchCount
= cpu_to_le16(16); /* BB increase */
2666 pSMB
->SearchFlags
= cpu_to_le16(1);
2667 pSMB
->InformationLevel
= cpu_to_le16(SMB_FIND_FILE_DIRECTORY_INFO
);
2668 pSMB
->SearchStorageType
= 0; /* BB what should we set this to? BB */
2669 pSMB
->hdr
.smb_buf_length
+= byte_count
;
2670 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
2672 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
2673 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
2676 cFYI(1, ("Send error in FindFileDirInfo = %d", rc
));
2677 } else { /* decode response */
2678 cifs_stats_inc(&tcon
->num_ffirst
);
2682 cifs_buf_release(pSMB
);
2684 goto findUniqueRetry
;
2688 #endif /* end unused (temporarily) function */
2690 /* xid, tcon, searchName and codepage are input parms, rest are returned */
2692 CIFSFindFirst(const int xid
, struct cifsTconInfo
*tcon
,
2693 const char *searchName
,
2694 const struct nls_table
*nls_codepage
,
2696 struct cifs_search_info
* psrch_inf
, int remap
, const char dirsep
)
2698 /* level 257 SMB_ */
2699 TRANSACTION2_FFIRST_REQ
*pSMB
= NULL
;
2700 TRANSACTION2_FFIRST_RSP
*pSMBr
= NULL
;
2701 T2_FFIRST_RSP_PARMS
* parms
;
2703 int bytes_returned
= 0;
2705 __u16 params
, byte_count
;
2707 cFYI(1, ("In FindFirst for %s",searchName
));
2710 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
2715 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
2717 cifsConvertToUCS((__le16
*) pSMB
->FileName
,searchName
,
2718 PATH_MAX
, nls_codepage
, remap
);
2719 /* We can not add the asterik earlier in case
2720 it got remapped to 0xF03A as if it were part of the
2721 directory name instead of a wildcard */
2723 pSMB
->FileName
[name_len
] = dirsep
;
2724 pSMB
->FileName
[name_len
+1] = 0;
2725 pSMB
->FileName
[name_len
+2] = '*';
2726 pSMB
->FileName
[name_len
+3] = 0;
2727 name_len
+= 4; /* now the trailing null */
2728 pSMB
->FileName
[name_len
] = 0; /* null terminate just in case */
2729 pSMB
->FileName
[name_len
+1] = 0;
2731 } else { /* BB add check for overrun of SMB buf BB */
2732 name_len
= strnlen(searchName
, PATH_MAX
);
2733 /* BB fix here and in unicode clause above ie
2734 if(name_len > buffersize-header)
2735 free buffer exit; BB */
2736 strncpy(pSMB
->FileName
, searchName
, name_len
);
2737 pSMB
->FileName
[name_len
] = dirsep
;
2738 pSMB
->FileName
[name_len
+1] = '*';
2739 pSMB
->FileName
[name_len
+2] = 0;
2743 params
= 12 + name_len
/* includes null */ ;
2744 pSMB
->TotalDataCount
= 0; /* no EAs */
2745 pSMB
->MaxParameterCount
= cpu_to_le16(10);
2746 pSMB
->MaxDataCount
= cpu_to_le16((tcon
->ses
->server
->maxBuf
-
2747 MAX_CIFS_HDR_SIZE
) & 0xFFFFFF00);
2748 pSMB
->MaxSetupCount
= 0;
2752 pSMB
->Reserved2
= 0;
2753 byte_count
= params
+ 1 /* pad */ ;
2754 pSMB
->TotalParameterCount
= cpu_to_le16(params
);
2755 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
2756 pSMB
->ParameterOffset
= cpu_to_le16(
2757 offsetof(struct smb_com_transaction2_ffirst_req
, SearchAttributes
) - 4);
2758 pSMB
->DataCount
= 0;
2759 pSMB
->DataOffset
= 0;
2760 pSMB
->SetupCount
= 1; /* one byte, no need to make endian neutral */
2761 pSMB
->Reserved3
= 0;
2762 pSMB
->SubCommand
= cpu_to_le16(TRANS2_FIND_FIRST
);
2763 pSMB
->SearchAttributes
=
2764 cpu_to_le16(ATTR_READONLY
| ATTR_HIDDEN
| ATTR_SYSTEM
|
2766 pSMB
->SearchCount
= cpu_to_le16(CIFSMaxBufSize
/sizeof(FILE_UNIX_INFO
));
2767 pSMB
->SearchFlags
= cpu_to_le16(CIFS_SEARCH_CLOSE_AT_END
|
2768 CIFS_SEARCH_RETURN_RESUME
);
2769 pSMB
->InformationLevel
= cpu_to_le16(psrch_inf
->info_level
);
2771 /* BB what should we set StorageType to? Does it matter? BB */
2772 pSMB
->SearchStorageType
= 0;
2773 pSMB
->hdr
.smb_buf_length
+= byte_count
;
2774 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
2776 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
2777 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
2778 cifs_stats_inc(&tcon
->num_ffirst
);
2780 if (rc
) {/* BB add logic to retry regular search if Unix search rejected unexpectedly by server */
2781 /* BB Add code to handle unsupported level rc */
2782 cFYI(1, ("Error in FindFirst = %d", rc
));
2785 cifs_buf_release(pSMB
);
2787 /* BB eventually could optimize out free and realloc of buf */
2790 goto findFirstRetry
;
2791 } else { /* decode response */
2792 /* BB remember to free buffer if error BB */
2793 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
2795 if (pSMBr
->hdr
.Flags2
& SMBFLG2_UNICODE
)
2796 psrch_inf
->unicode
= TRUE
;
2798 psrch_inf
->unicode
= FALSE
;
2800 psrch_inf
->ntwrk_buf_start
= (char *)pSMBr
;
2801 psrch_inf
->srch_entries_start
=
2802 (char *) &pSMBr
->hdr
.Protocol
+
2803 le16_to_cpu(pSMBr
->t2
.DataOffset
);
2804 parms
= (T2_FFIRST_RSP_PARMS
*)((char *) &pSMBr
->hdr
.Protocol
+
2805 le16_to_cpu(pSMBr
->t2
.ParameterOffset
));
2807 if(parms
->EndofSearch
)
2808 psrch_inf
->endOfSearch
= TRUE
;
2810 psrch_inf
->endOfSearch
= FALSE
;
2812 psrch_inf
->entries_in_buffer
= le16_to_cpu(parms
->SearchCount
);
2813 psrch_inf
->index_of_last_entry
=
2814 psrch_inf
->entries_in_buffer
;
2815 *pnetfid
= parms
->SearchHandle
;
2817 cifs_buf_release(pSMB
);
2824 int CIFSFindNext(const int xid
, struct cifsTconInfo
*tcon
,
2825 __u16 searchHandle
, struct cifs_search_info
* psrch_inf
)
2827 TRANSACTION2_FNEXT_REQ
*pSMB
= NULL
;
2828 TRANSACTION2_FNEXT_RSP
*pSMBr
= NULL
;
2829 T2_FNEXT_RSP_PARMS
* parms
;
2830 char *response_data
;
2832 int bytes_returned
, name_len
;
2833 __u16 params
, byte_count
;
2835 cFYI(1, ("In FindNext"));
2837 if(psrch_inf
->endOfSearch
== TRUE
)
2840 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
2845 params
= 14; /* includes 2 bytes of null string, converted to LE below */
2847 pSMB
->TotalDataCount
= 0; /* no EAs */
2848 pSMB
->MaxParameterCount
= cpu_to_le16(8);
2849 pSMB
->MaxDataCount
=
2850 cpu_to_le16((tcon
->ses
->server
->maxBuf
- MAX_CIFS_HDR_SIZE
) & 0xFFFFFF00);
2851 pSMB
->MaxSetupCount
= 0;
2855 pSMB
->Reserved2
= 0;
2856 pSMB
->ParameterOffset
= cpu_to_le16(
2857 offsetof(struct smb_com_transaction2_fnext_req
,SearchHandle
) - 4);
2858 pSMB
->DataCount
= 0;
2859 pSMB
->DataOffset
= 0;
2860 pSMB
->SetupCount
= 1;
2861 pSMB
->Reserved3
= 0;
2862 pSMB
->SubCommand
= cpu_to_le16(TRANS2_FIND_NEXT
);
2863 pSMB
->SearchHandle
= searchHandle
; /* always kept as le */
2865 cpu_to_le16(CIFSMaxBufSize
/ sizeof (FILE_UNIX_INFO
));
2866 /* test for Unix extensions */
2867 /* if (tcon->ses->capabilities & CAP_UNIX) {
2868 pSMB->InformationLevel = cpu_to_le16(SMB_FIND_FILE_UNIX);
2869 psrch_inf->info_level = SMB_FIND_FILE_UNIX;
2871 pSMB->InformationLevel =
2872 cpu_to_le16(SMB_FIND_FILE_DIRECTORY_INFO);
2873 psrch_inf->info_level = SMB_FIND_FILE_DIRECTORY_INFO;
2875 pSMB
->InformationLevel
= cpu_to_le16(psrch_inf
->info_level
);
2876 pSMB
->ResumeKey
= psrch_inf
->resume_key
;
2878 cpu_to_le16(CIFS_SEARCH_CLOSE_AT_END
| CIFS_SEARCH_RETURN_RESUME
);
2880 name_len
= psrch_inf
->resume_name_len
;
2882 if(name_len
< PATH_MAX
) {
2883 memcpy(pSMB
->ResumeFileName
, psrch_inf
->presume_name
, name_len
);
2884 byte_count
+= name_len
;
2885 /* 14 byte parm len above enough for 2 byte null terminator */
2886 pSMB
->ResumeFileName
[name_len
] = 0;
2887 pSMB
->ResumeFileName
[name_len
+1] = 0;
2890 goto FNext2_err_exit
;
2892 byte_count
= params
+ 1 /* pad */ ;
2893 pSMB
->TotalParameterCount
= cpu_to_le16(params
);
2894 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
2895 pSMB
->hdr
.smb_buf_length
+= byte_count
;
2896 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
2898 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
2899 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
2900 cifs_stats_inc(&tcon
->num_fnext
);
2903 psrch_inf
->endOfSearch
= TRUE
;
2904 rc
= 0; /* search probably was closed at end of search above */
2906 cFYI(1, ("FindNext returned = %d", rc
));
2907 } else { /* decode response */
2908 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
2911 /* BB fixme add lock for file (srch_info) struct here */
2912 if (pSMBr
->hdr
.Flags2
& SMBFLG2_UNICODE
)
2913 psrch_inf
->unicode
= TRUE
;
2915 psrch_inf
->unicode
= FALSE
;
2916 response_data
= (char *) &pSMBr
->hdr
.Protocol
+
2917 le16_to_cpu(pSMBr
->t2
.ParameterOffset
);
2918 parms
= (T2_FNEXT_RSP_PARMS
*)response_data
;
2919 response_data
= (char *)&pSMBr
->hdr
.Protocol
+
2920 le16_to_cpu(pSMBr
->t2
.DataOffset
);
2921 cifs_buf_release(psrch_inf
->ntwrk_buf_start
);
2922 psrch_inf
->srch_entries_start
= response_data
;
2923 psrch_inf
->ntwrk_buf_start
= (char *)pSMB
;
2924 if(parms
->EndofSearch
)
2925 psrch_inf
->endOfSearch
= TRUE
;
2927 psrch_inf
->endOfSearch
= FALSE
;
2929 psrch_inf
->entries_in_buffer
= le16_to_cpu(parms
->SearchCount
);
2930 psrch_inf
->index_of_last_entry
+=
2931 psrch_inf
->entries_in_buffer
;
2932 /* cFYI(1,("fnxt2 entries in buf %d index_of_last %d",psrch_inf->entries_in_buffer,psrch_inf->index_of_last_entry)); */
2934 /* BB fixme add unlock here */
2939 /* BB On error, should we leave previous search buf (and count and
2940 last entry fields) intact or free the previous one? */
2942 /* Note: On -EAGAIN error only caller can retry on handle based calls
2943 since file handle passed in no longer valid */
2946 cifs_buf_release(pSMB
);
2952 CIFSFindClose(const int xid
, struct cifsTconInfo
*tcon
, const __u16 searchHandle
)
2955 FINDCLOSE_REQ
*pSMB
= NULL
;
2956 CLOSE_RSP
*pSMBr
= NULL
; /* BB removeme BB */
2959 cFYI(1, ("In CIFSSMBFindClose"));
2960 rc
= small_smb_init(SMB_COM_FIND_CLOSE2
, 1, tcon
, (void **)&pSMB
);
2962 /* no sense returning error if session restarted
2963 as file handle has been closed */
2969 pSMBr
= (CLOSE_RSP
*)pSMB
; /* BB removeme BB */
2970 pSMB
->FileID
= searchHandle
;
2971 pSMB
->ByteCount
= 0;
2972 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
2973 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
2975 cERROR(1, ("Send error in FindClose = %d", rc
));
2977 cifs_stats_inc(&tcon
->num_fclose
);
2978 cifs_small_buf_release(pSMB
);
2980 /* Since session is dead, search handle closed on server already */
2988 CIFSGetSrvInodeNumber(const int xid
, struct cifsTconInfo
*tcon
,
2989 const unsigned char *searchName
,
2990 __u64
* inode_number
,
2991 const struct nls_table
*nls_codepage
, int remap
)
2994 TRANSACTION2_QPI_REQ
*pSMB
= NULL
;
2995 TRANSACTION2_QPI_RSP
*pSMBr
= NULL
;
2996 int name_len
, bytes_returned
;
2997 __u16 params
, byte_count
;
2999 cFYI(1,("In GetSrvInodeNum for %s",searchName
));
3003 GetInodeNumberRetry
:
3004 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
3010 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
3012 cifsConvertToUCS((__le16
*) pSMB
->FileName
, searchName
,
3013 PATH_MAX
,nls_codepage
, remap
);
3014 name_len
++; /* trailing null */
3016 } else { /* BB improve the check for buffer overruns BB */
3017 name_len
= strnlen(searchName
, PATH_MAX
);
3018 name_len
++; /* trailing null */
3019 strncpy(pSMB
->FileName
, searchName
, name_len
);
3022 params
= 2 /* level */ + 4 /* rsrvd */ + name_len
/* incl null */ ;
3023 pSMB
->TotalDataCount
= 0;
3024 pSMB
->MaxParameterCount
= cpu_to_le16(2);
3025 /* BB find exact max data count below from sess structure BB */
3026 pSMB
->MaxDataCount
= cpu_to_le16(4000);
3027 pSMB
->MaxSetupCount
= 0;
3031 pSMB
->Reserved2
= 0;
3032 pSMB
->ParameterOffset
= cpu_to_le16(offsetof(
3033 struct smb_com_transaction2_qpi_req
,InformationLevel
) - 4);
3034 pSMB
->DataCount
= 0;
3035 pSMB
->DataOffset
= 0;
3036 pSMB
->SetupCount
= 1;
3037 pSMB
->Reserved3
= 0;
3038 pSMB
->SubCommand
= cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION
);
3039 byte_count
= params
+ 1 /* pad */ ;
3040 pSMB
->TotalParameterCount
= cpu_to_le16(params
);
3041 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
3042 pSMB
->InformationLevel
= cpu_to_le16(SMB_QUERY_FILE_INTERNAL_INFO
);
3043 pSMB
->Reserved4
= 0;
3044 pSMB
->hdr
.smb_buf_length
+= byte_count
;
3045 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
3047 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
3048 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
3050 cFYI(1, ("error %d in QueryInternalInfo", rc
));
3052 /* decode response */
3053 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
3054 if (rc
|| (pSMBr
->ByteCount
< 2))
3055 /* BB also check enough total bytes returned */
3056 /* If rc should we check for EOPNOSUPP and
3057 disable the srvino flag? or in caller? */
3058 rc
= -EIO
; /* bad smb */
3060 __u16 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
3061 __u16 count
= le16_to_cpu(pSMBr
->t2
.DataCount
);
3062 struct file_internal_info
* pfinfo
;
3063 /* BB Do we need a cast or hash here ? */
3065 cFYI(1, ("Illegal size ret in QryIntrnlInf"));
3067 goto GetInodeNumOut
;
3069 pfinfo
= (struct file_internal_info
*)
3070 (data_offset
+ (char *) &pSMBr
->hdr
.Protocol
);
3071 *inode_number
= pfinfo
->UniqueId
;
3075 cifs_buf_release(pSMB
);
3077 goto GetInodeNumberRetry
;
3082 CIFSGetDFSRefer(const int xid
, struct cifsSesInfo
*ses
,
3083 const unsigned char *searchName
,
3084 unsigned char **targetUNCs
,
3085 unsigned int *number_of_UNC_in_array
,
3086 const struct nls_table
*nls_codepage
, int remap
)
3088 /* TRANS2_GET_DFS_REFERRAL */
3089 TRANSACTION2_GET_DFS_REFER_REQ
*pSMB
= NULL
;
3090 TRANSACTION2_GET_DFS_REFER_RSP
*pSMBr
= NULL
;
3091 struct dfs_referral_level_3
* referrals
= NULL
;
3097 __u16 params
, byte_count
;
3098 *number_of_UNC_in_array
= 0;
3101 cFYI(1, ("In GetDFSRefer the path %s", searchName
));
3105 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, NULL
, (void **) &pSMB
,
3110 /* server pointer checked in called function,
3111 but should never be null here anyway */
3112 pSMB
->hdr
.Mid
= GetNextMid(ses
->server
);
3113 pSMB
->hdr
.Tid
= ses
->ipc_tid
;
3114 pSMB
->hdr
.Uid
= ses
->Suid
;
3115 if (ses
->capabilities
& CAP_STATUS32
) {
3116 pSMB
->hdr
.Flags2
|= SMBFLG2_ERR_STATUS
;
3118 if (ses
->capabilities
& CAP_DFS
) {
3119 pSMB
->hdr
.Flags2
|= SMBFLG2_DFS
;
3122 if (ses
->capabilities
& CAP_UNICODE
) {
3123 pSMB
->hdr
.Flags2
|= SMBFLG2_UNICODE
;
3125 cifsConvertToUCS((__le16
*) pSMB
->RequestFileName
,
3126 searchName
, PATH_MAX
, nls_codepage
, remap
);
3127 name_len
++; /* trailing null */
3129 } else { /* BB improve the check for buffer overruns BB */
3130 name_len
= strnlen(searchName
, PATH_MAX
);
3131 name_len
++; /* trailing null */
3132 strncpy(pSMB
->RequestFileName
, searchName
, name_len
);
3135 params
= 2 /* level */ + name_len
/*includes null */ ;
3136 pSMB
->TotalDataCount
= 0;
3137 pSMB
->DataCount
= 0;
3138 pSMB
->DataOffset
= 0;
3139 pSMB
->MaxParameterCount
= 0;
3140 pSMB
->MaxDataCount
= cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
3141 pSMB
->MaxSetupCount
= 0;
3145 pSMB
->Reserved2
= 0;
3146 pSMB
->ParameterOffset
= cpu_to_le16(offsetof(
3147 struct smb_com_transaction2_get_dfs_refer_req
, MaxReferralLevel
) - 4);
3148 pSMB
->SetupCount
= 1;
3149 pSMB
->Reserved3
= 0;
3150 pSMB
->SubCommand
= cpu_to_le16(TRANS2_GET_DFS_REFERRAL
);
3151 byte_count
= params
+ 3 /* pad */ ;
3152 pSMB
->ParameterCount
= cpu_to_le16(params
);
3153 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
3154 pSMB
->MaxReferralLevel
= cpu_to_le16(3);
3155 pSMB
->hdr
.smb_buf_length
+= byte_count
;
3156 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
3158 rc
= SendReceive(xid
, ses
, (struct smb_hdr
*) pSMB
,
3159 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
3161 cFYI(1, ("Send error in GetDFSRefer = %d", rc
));
3162 } else { /* decode response */
3163 /* BB Add logic to parse referrals here */
3164 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
3166 if (rc
|| (pSMBr
->ByteCount
< 17)) /* BB also check enough total bytes returned */
3167 rc
= -EIO
; /* bad smb */
3169 __u16 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
3170 __u16 data_count
= le16_to_cpu(pSMBr
->t2
.DataCount
);
3173 ("Decoding GetDFSRefer response. BCC: %d Offset %d",
3174 pSMBr
->ByteCount
, data_offset
));
3176 (struct dfs_referral_level_3
*)
3177 (8 /* sizeof start of data block */ +
3179 (char *) &pSMBr
->hdr
.Protocol
);
3180 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",
3181 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
)));
3182 /* BB This field is actually two bytes in from start of
3183 data block so we could do safety check that DataBlock
3184 begins at address of pSMBr->NumberOfReferrals */
3185 *number_of_UNC_in_array
= le16_to_cpu(pSMBr
->NumberOfReferrals
);
3187 /* BB Fix below so can return more than one referral */
3188 if(*number_of_UNC_in_array
> 1)
3189 *number_of_UNC_in_array
= 1;
3191 /* get the length of the strings describing refs */
3193 for(i
=0;i
<*number_of_UNC_in_array
;i
++) {
3194 /* make sure that DfsPathOffset not past end */
3195 __u16 offset
= le16_to_cpu(referrals
->DfsPathOffset
);
3196 if (offset
> data_count
) {
3197 /* if invalid referral, stop here and do
3198 not try to copy any more */
3199 *number_of_UNC_in_array
= i
;
3202 temp
= ((char *)referrals
) + offset
;
3204 if (pSMBr
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
3205 name_len
+= UniStrnlen((wchar_t *)temp
,data_count
);
3207 name_len
+= strnlen(temp
,data_count
);
3210 /* BB add check that referral pointer does not fall off end PDU */
3213 /* BB add check for name_len bigger than bcc */
3215 kmalloc(name_len
+1+ (*number_of_UNC_in_array
),GFP_KERNEL
);
3216 if(*targetUNCs
== NULL
) {
3220 /* copy the ref strings */
3222 (struct dfs_referral_level_3
*)
3223 (8 /* sizeof data hdr */ +
3225 (char *) &pSMBr
->hdr
.Protocol
);
3227 for(i
=0;i
<*number_of_UNC_in_array
;i
++) {
3228 temp
= ((char *)referrals
) + le16_to_cpu(referrals
->DfsPathOffset
);
3229 if (pSMBr
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
3230 cifs_strfromUCS_le(*targetUNCs
,
3231 (__le16
*) temp
, name_len
, nls_codepage
);
3233 strncpy(*targetUNCs
,temp
,name_len
);
3235 /* BB update target_uncs pointers */
3245 cifs_buf_release(pSMB
);
3253 /* Query File System Info such as free space to old servers such as Win 9x */
3255 SMBOldQFSInfo(const int xid
, struct cifsTconInfo
*tcon
, struct kstatfs
*FSData
)
3257 /* level 0x01 SMB_QUERY_FILE_SYSTEM_INFO */
3258 TRANSACTION2_QFSI_REQ
*pSMB
= NULL
;
3259 TRANSACTION2_QFSI_RSP
*pSMBr
= NULL
;
3260 FILE_SYSTEM_ALLOC_INFO
*response_data
;
3262 int bytes_returned
= 0;
3263 __u16 params
, byte_count
;
3265 cFYI(1, ("OldQFSInfo"));
3267 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
3271 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
3276 params
= 2; /* level */
3277 pSMB
->TotalDataCount
= 0;
3278 pSMB
->MaxParameterCount
= cpu_to_le16(2);
3279 pSMB
->MaxDataCount
= cpu_to_le16(1000);
3280 pSMB
->MaxSetupCount
= 0;
3284 pSMB
->Reserved2
= 0;
3285 byte_count
= params
+ 1 /* pad */ ;
3286 pSMB
->TotalParameterCount
= cpu_to_le16(params
);
3287 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
3288 pSMB
->ParameterOffset
= cpu_to_le16(offsetof(
3289 struct smb_com_transaction2_qfsi_req
, InformationLevel
) - 4);
3290 pSMB
->DataCount
= 0;
3291 pSMB
->DataOffset
= 0;
3292 pSMB
->SetupCount
= 1;
3293 pSMB
->Reserved3
= 0;
3294 pSMB
->SubCommand
= cpu_to_le16(TRANS2_QUERY_FS_INFORMATION
);
3295 pSMB
->InformationLevel
= cpu_to_le16(SMB_INFO_ALLOCATION
);
3296 pSMB
->hdr
.smb_buf_length
+= byte_count
;
3297 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
3299 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
3300 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
3302 cFYI(1, ("Send error in QFSInfo = %d", rc
));
3303 } else { /* decode response */
3304 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
3306 if (rc
|| (pSMBr
->ByteCount
< 18))
3307 rc
= -EIO
; /* bad smb */
3309 __u16 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
3310 cFYI(1,("qfsinf resp BCC: %d Offset %d",
3311 pSMBr
->ByteCount
, data_offset
));
3314 (FILE_SYSTEM_ALLOC_INFO
*)
3315 (((char *) &pSMBr
->hdr
.Protocol
) + data_offset
);
3317 le16_to_cpu(response_data
->BytesPerSector
) *
3318 le32_to_cpu(response_data
->
3319 SectorsPerAllocationUnit
);
3321 le32_to_cpu(response_data
->TotalAllocationUnits
);
3322 FSData
->f_bfree
= FSData
->f_bavail
=
3323 le32_to_cpu(response_data
->FreeAllocationUnits
);
3325 ("Blocks: %lld Free: %lld Block size %ld",
3326 (unsigned long long)FSData
->f_blocks
,
3327 (unsigned long long)FSData
->f_bfree
,
3331 cifs_buf_release(pSMB
);
3334 goto oldQFSInfoRetry
;
3340 CIFSSMBQFSInfo(const int xid
, struct cifsTconInfo
*tcon
, struct kstatfs
*FSData
)
3342 /* level 0x103 SMB_QUERY_FILE_SYSTEM_INFO */
3343 TRANSACTION2_QFSI_REQ
*pSMB
= NULL
;
3344 TRANSACTION2_QFSI_RSP
*pSMBr
= NULL
;
3345 FILE_SYSTEM_INFO
*response_data
;
3347 int bytes_returned
= 0;
3348 __u16 params
, byte_count
;
3350 cFYI(1, ("In QFSInfo"));
3352 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
3357 params
= 2; /* level */
3358 pSMB
->TotalDataCount
= 0;
3359 pSMB
->MaxParameterCount
= cpu_to_le16(2);
3360 pSMB
->MaxDataCount
= cpu_to_le16(1000);
3361 pSMB
->MaxSetupCount
= 0;
3365 pSMB
->Reserved2
= 0;
3366 byte_count
= params
+ 1 /* pad */ ;
3367 pSMB
->TotalParameterCount
= cpu_to_le16(params
);
3368 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
3369 pSMB
->ParameterOffset
= cpu_to_le16(offsetof(
3370 struct smb_com_transaction2_qfsi_req
, InformationLevel
) - 4);
3371 pSMB
->DataCount
= 0;
3372 pSMB
->DataOffset
= 0;
3373 pSMB
->SetupCount
= 1;
3374 pSMB
->Reserved3
= 0;
3375 pSMB
->SubCommand
= cpu_to_le16(TRANS2_QUERY_FS_INFORMATION
);
3376 pSMB
->InformationLevel
= cpu_to_le16(SMB_QUERY_FS_SIZE_INFO
);
3377 pSMB
->hdr
.smb_buf_length
+= byte_count
;
3378 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
3380 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
3381 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
3383 cFYI(1, ("Send error in QFSInfo = %d", rc
));
3384 } else { /* decode response */
3385 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
3387 if (rc
|| (pSMBr
->ByteCount
< 24))
3388 rc
= -EIO
; /* bad smb */
3390 __u16 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
3394 *) (((char *) &pSMBr
->hdr
.Protocol
) +
3397 le32_to_cpu(response_data
->BytesPerSector
) *
3398 le32_to_cpu(response_data
->
3399 SectorsPerAllocationUnit
);
3401 le64_to_cpu(response_data
->TotalAllocationUnits
);
3402 FSData
->f_bfree
= FSData
->f_bavail
=
3403 le64_to_cpu(response_data
->FreeAllocationUnits
);
3405 ("Blocks: %lld Free: %lld Block size %ld",
3406 (unsigned long long)FSData
->f_blocks
,
3407 (unsigned long long)FSData
->f_bfree
,
3411 cifs_buf_release(pSMB
);
3420 CIFSSMBQFSAttributeInfo(const int xid
, struct cifsTconInfo
*tcon
)
3422 /* level 0x105 SMB_QUERY_FILE_SYSTEM_INFO */
3423 TRANSACTION2_QFSI_REQ
*pSMB
= NULL
;
3424 TRANSACTION2_QFSI_RSP
*pSMBr
= NULL
;
3425 FILE_SYSTEM_ATTRIBUTE_INFO
*response_data
;
3427 int bytes_returned
= 0;
3428 __u16 params
, byte_count
;
3430 cFYI(1, ("In QFSAttributeInfo"));
3432 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
3437 params
= 2; /* level */
3438 pSMB
->TotalDataCount
= 0;
3439 pSMB
->MaxParameterCount
= cpu_to_le16(2);
3440 pSMB
->MaxDataCount
= cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
3441 pSMB
->MaxSetupCount
= 0;
3445 pSMB
->Reserved2
= 0;
3446 byte_count
= params
+ 1 /* pad */ ;
3447 pSMB
->TotalParameterCount
= cpu_to_le16(params
);
3448 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
3449 pSMB
->ParameterOffset
= cpu_to_le16(offsetof(
3450 struct smb_com_transaction2_qfsi_req
, InformationLevel
) - 4);
3451 pSMB
->DataCount
= 0;
3452 pSMB
->DataOffset
= 0;
3453 pSMB
->SetupCount
= 1;
3454 pSMB
->Reserved3
= 0;
3455 pSMB
->SubCommand
= cpu_to_le16(TRANS2_QUERY_FS_INFORMATION
);
3456 pSMB
->InformationLevel
= cpu_to_le16(SMB_QUERY_FS_ATTRIBUTE_INFO
);
3457 pSMB
->hdr
.smb_buf_length
+= byte_count
;
3458 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
3460 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
3461 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
3463 cERROR(1, ("Send error in QFSAttributeInfo = %d", rc
));
3464 } else { /* decode response */
3465 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
3467 if (rc
|| (pSMBr
->ByteCount
< 13)) { /* BB also check enough bytes returned */
3468 rc
= -EIO
; /* bad smb */
3470 __u16 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
3472 (FILE_SYSTEM_ATTRIBUTE_INFO
3473 *) (((char *) &pSMBr
->hdr
.Protocol
) +
3475 memcpy(&tcon
->fsAttrInfo
, response_data
,
3476 sizeof (FILE_SYSTEM_ATTRIBUTE_INFO
));
3479 cifs_buf_release(pSMB
);
3482 goto QFSAttributeRetry
;
3488 CIFSSMBQFSDeviceInfo(const int xid
, struct cifsTconInfo
*tcon
)
3490 /* level 0x104 SMB_QUERY_FILE_SYSTEM_INFO */
3491 TRANSACTION2_QFSI_REQ
*pSMB
= NULL
;
3492 TRANSACTION2_QFSI_RSP
*pSMBr
= NULL
;
3493 FILE_SYSTEM_DEVICE_INFO
*response_data
;
3495 int bytes_returned
= 0;
3496 __u16 params
, byte_count
;
3498 cFYI(1, ("In QFSDeviceInfo"));
3500 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
3505 params
= 2; /* level */
3506 pSMB
->TotalDataCount
= 0;
3507 pSMB
->MaxParameterCount
= cpu_to_le16(2);
3508 pSMB
->MaxDataCount
= cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
3509 pSMB
->MaxSetupCount
= 0;
3513 pSMB
->Reserved2
= 0;
3514 byte_count
= params
+ 1 /* pad */ ;
3515 pSMB
->TotalParameterCount
= cpu_to_le16(params
);
3516 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
3517 pSMB
->ParameterOffset
= cpu_to_le16(offsetof(
3518 struct smb_com_transaction2_qfsi_req
, InformationLevel
) - 4);
3520 pSMB
->DataCount
= 0;
3521 pSMB
->DataOffset
= 0;
3522 pSMB
->SetupCount
= 1;
3523 pSMB
->Reserved3
= 0;
3524 pSMB
->SubCommand
= cpu_to_le16(TRANS2_QUERY_FS_INFORMATION
);
3525 pSMB
->InformationLevel
= cpu_to_le16(SMB_QUERY_FS_DEVICE_INFO
);
3526 pSMB
->hdr
.smb_buf_length
+= byte_count
;
3527 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
3529 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
3530 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
3532 cFYI(1, ("Send error in QFSDeviceInfo = %d", rc
));
3533 } else { /* decode response */
3534 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
3536 if (rc
|| (pSMBr
->ByteCount
< sizeof (FILE_SYSTEM_DEVICE_INFO
)))
3537 rc
= -EIO
; /* bad smb */
3539 __u16 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
3541 (FILE_SYSTEM_DEVICE_INFO
*)
3542 (((char *) &pSMBr
->hdr
.Protocol
) +
3544 memcpy(&tcon
->fsDevInfo
, response_data
,
3545 sizeof (FILE_SYSTEM_DEVICE_INFO
));
3548 cifs_buf_release(pSMB
);
3551 goto QFSDeviceRetry
;
3557 CIFSSMBQFSUnixInfo(const int xid
, struct cifsTconInfo
*tcon
)
3559 /* level 0x200 SMB_QUERY_CIFS_UNIX_INFO */
3560 TRANSACTION2_QFSI_REQ
*pSMB
= NULL
;
3561 TRANSACTION2_QFSI_RSP
*pSMBr
= NULL
;
3562 FILE_SYSTEM_UNIX_INFO
*response_data
;
3564 int bytes_returned
= 0;
3565 __u16 params
, byte_count
;
3567 cFYI(1, ("In QFSUnixInfo"));
3569 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
3574 params
= 2; /* level */
3575 pSMB
->TotalDataCount
= 0;
3576 pSMB
->DataCount
= 0;
3577 pSMB
->DataOffset
= 0;
3578 pSMB
->MaxParameterCount
= cpu_to_le16(2);
3579 pSMB
->MaxDataCount
= cpu_to_le16(100); /* BB find exact max SMB PDU from sess structure BB */
3580 pSMB
->MaxSetupCount
= 0;
3584 pSMB
->Reserved2
= 0;
3585 byte_count
= params
+ 1 /* pad */ ;
3586 pSMB
->ParameterCount
= cpu_to_le16(params
);
3587 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
3588 pSMB
->ParameterOffset
= cpu_to_le16(offsetof(struct
3589 smb_com_transaction2_qfsi_req
, InformationLevel
) - 4);
3590 pSMB
->SetupCount
= 1;
3591 pSMB
->Reserved3
= 0;
3592 pSMB
->SubCommand
= cpu_to_le16(TRANS2_QUERY_FS_INFORMATION
);
3593 pSMB
->InformationLevel
= cpu_to_le16(SMB_QUERY_CIFS_UNIX_INFO
);
3594 pSMB
->hdr
.smb_buf_length
+= byte_count
;
3595 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
3597 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
3598 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
3600 cERROR(1, ("Send error in QFSUnixInfo = %d", rc
));
3601 } else { /* decode response */
3602 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
3604 if (rc
|| (pSMBr
->ByteCount
< 13)) {
3605 rc
= -EIO
; /* bad smb */
3607 __u16 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
3609 (FILE_SYSTEM_UNIX_INFO
3610 *) (((char *) &pSMBr
->hdr
.Protocol
) +
3612 memcpy(&tcon
->fsUnixInfo
, response_data
,
3613 sizeof (FILE_SYSTEM_UNIX_INFO
));
3616 cifs_buf_release(pSMB
);
3626 CIFSSMBSetFSUnixInfo(const int xid
, struct cifsTconInfo
*tcon
, __u64 cap
)
3628 /* level 0x200 SMB_SET_CIFS_UNIX_INFO */
3629 TRANSACTION2_SETFSI_REQ
*pSMB
= NULL
;
3630 TRANSACTION2_SETFSI_RSP
*pSMBr
= NULL
;
3632 int bytes_returned
= 0;
3633 __u16 params
, param_offset
, offset
, byte_count
;
3635 cFYI(1, ("In SETFSUnixInfo"));
3637 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
3642 params
= 4; /* 2 bytes zero followed by info level. */
3643 pSMB
->MaxSetupCount
= 0;
3647 pSMB
->Reserved2
= 0;
3648 param_offset
= offsetof(struct smb_com_transaction2_setfsi_req
, FileNum
) - 4;
3649 offset
= param_offset
+ params
;
3651 pSMB
->MaxParameterCount
= cpu_to_le16(4);
3652 pSMB
->MaxDataCount
= cpu_to_le16(100); /* BB find exact max SMB PDU from sess structure BB */
3653 pSMB
->SetupCount
= 1;
3654 pSMB
->Reserved3
= 0;
3655 pSMB
->SubCommand
= cpu_to_le16(TRANS2_SET_FS_INFORMATION
);
3656 byte_count
= 1 /* pad */ + params
+ 12;
3658 pSMB
->DataCount
= cpu_to_le16(12);
3659 pSMB
->ParameterCount
= cpu_to_le16(params
);
3660 pSMB
->TotalDataCount
= pSMB
->DataCount
;
3661 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
3662 pSMB
->ParameterOffset
= cpu_to_le16(param_offset
);
3663 pSMB
->DataOffset
= cpu_to_le16(offset
);
3667 pSMB
->InformationLevel
= cpu_to_le16(SMB_SET_CIFS_UNIX_INFO
);
3670 pSMB
->ClientUnixMajor
= cpu_to_le16(CIFS_UNIX_MAJOR_VERSION
);
3671 pSMB
->ClientUnixMinor
= cpu_to_le16(CIFS_UNIX_MINOR_VERSION
);
3672 pSMB
->ClientUnixCap
= cpu_to_le64(cap
);
3674 pSMB
->hdr
.smb_buf_length
+= byte_count
;
3675 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
3677 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
3678 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
3680 cERROR(1, ("Send error in SETFSUnixInfo = %d", rc
));
3681 } else { /* decode response */
3682 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
3684 rc
= -EIO
; /* bad smb */
3687 cifs_buf_release(pSMB
);
3690 goto SETFSUnixRetry
;
3698 CIFSSMBQFSPosixInfo(const int xid
, struct cifsTconInfo
*tcon
,
3699 struct kstatfs
*FSData
)
3701 /* level 0x201 SMB_QUERY_CIFS_POSIX_INFO */
3702 TRANSACTION2_QFSI_REQ
*pSMB
= NULL
;
3703 TRANSACTION2_QFSI_RSP
*pSMBr
= NULL
;
3704 FILE_SYSTEM_POSIX_INFO
*response_data
;
3706 int bytes_returned
= 0;
3707 __u16 params
, byte_count
;
3709 cFYI(1, ("In QFSPosixInfo"));
3711 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
3716 params
= 2; /* level */
3717 pSMB
->TotalDataCount
= 0;
3718 pSMB
->DataCount
= 0;
3719 pSMB
->DataOffset
= 0;
3720 pSMB
->MaxParameterCount
= cpu_to_le16(2);
3721 pSMB
->MaxDataCount
= cpu_to_le16(100); /* BB find exact max SMB PDU from sess structure BB */
3722 pSMB
->MaxSetupCount
= 0;
3726 pSMB
->Reserved2
= 0;
3727 byte_count
= params
+ 1 /* pad */ ;
3728 pSMB
->ParameterCount
= cpu_to_le16(params
);
3729 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
3730 pSMB
->ParameterOffset
= cpu_to_le16(offsetof(struct
3731 smb_com_transaction2_qfsi_req
, InformationLevel
) - 4);
3732 pSMB
->SetupCount
= 1;
3733 pSMB
->Reserved3
= 0;
3734 pSMB
->SubCommand
= cpu_to_le16(TRANS2_QUERY_FS_INFORMATION
);
3735 pSMB
->InformationLevel
= cpu_to_le16(SMB_QUERY_POSIX_FS_INFO
);
3736 pSMB
->hdr
.smb_buf_length
+= byte_count
;
3737 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
3739 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
3740 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
3742 cFYI(1, ("Send error in QFSUnixInfo = %d", rc
));
3743 } else { /* decode response */
3744 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
3746 if (rc
|| (pSMBr
->ByteCount
< 13)) {
3747 rc
= -EIO
; /* bad smb */
3749 __u16 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
3751 (FILE_SYSTEM_POSIX_INFO
3752 *) (((char *) &pSMBr
->hdr
.Protocol
) +
3755 le32_to_cpu(response_data
->BlockSize
);
3757 le64_to_cpu(response_data
->TotalBlocks
);
3759 le64_to_cpu(response_data
->BlocksAvail
);
3760 if(response_data
->UserBlocksAvail
== cpu_to_le64(-1)) {
3761 FSData
->f_bavail
= FSData
->f_bfree
;
3764 le64_to_cpu(response_data
->UserBlocksAvail
);
3766 if(response_data
->TotalFileNodes
!= cpu_to_le64(-1))
3768 le64_to_cpu(response_data
->TotalFileNodes
);
3769 if(response_data
->FreeFileNodes
!= cpu_to_le64(-1))
3771 le64_to_cpu(response_data
->FreeFileNodes
);
3774 cifs_buf_release(pSMB
);
3783 /* We can not use write of zero bytes trick to
3784 set file size due to need for large file support. Also note that
3785 this SetPathInfo is preferred to SetFileInfo based method in next
3786 routine which is only needed to work around a sharing violation bug
3787 in Samba which this routine can run into */
3790 CIFSSMBSetEOF(const int xid
, struct cifsTconInfo
*tcon
, const char *fileName
,
3791 __u64 size
, int SetAllocation
,
3792 const struct nls_table
*nls_codepage
, int remap
)
3794 struct smb_com_transaction2_spi_req
*pSMB
= NULL
;
3795 struct smb_com_transaction2_spi_rsp
*pSMBr
= NULL
;
3796 struct file_end_of_file_info
*parm_data
;
3799 int bytes_returned
= 0;
3800 __u16 params
, byte_count
, data_count
, param_offset
, offset
;
3802 cFYI(1, ("In SetEOF"));
3804 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
3809 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
3811 cifsConvertToUCS((__le16
*) pSMB
->FileName
, fileName
,
3812 PATH_MAX
, nls_codepage
, remap
);
3813 name_len
++; /* trailing null */
3815 } else { /* BB improve the check for buffer overruns BB */
3816 name_len
= strnlen(fileName
, PATH_MAX
);
3817 name_len
++; /* trailing null */
3818 strncpy(pSMB
->FileName
, fileName
, name_len
);
3820 params
= 6 + name_len
;
3821 data_count
= sizeof (struct file_end_of_file_info
);
3822 pSMB
->MaxParameterCount
= cpu_to_le16(2);
3823 pSMB
->MaxDataCount
= cpu_to_le16(4100);
3824 pSMB
->MaxSetupCount
= 0;
3828 pSMB
->Reserved2
= 0;
3829 param_offset
= offsetof(struct smb_com_transaction2_spi_req
,
3830 InformationLevel
) - 4;
3831 offset
= param_offset
+ params
;
3833 if (tcon
->ses
->capabilities
& CAP_INFOLEVEL_PASSTHRU
)
3834 pSMB
->InformationLevel
=
3835 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2
);
3837 pSMB
->InformationLevel
=
3838 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO
);
3839 } else /* Set File Size */ {
3840 if (tcon
->ses
->capabilities
& CAP_INFOLEVEL_PASSTHRU
)
3841 pSMB
->InformationLevel
=
3842 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO2
);
3844 pSMB
->InformationLevel
=
3845 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO
);
3849 (struct file_end_of_file_info
*) (((char *) &pSMB
->hdr
.Protocol
) +
3851 pSMB
->ParameterOffset
= cpu_to_le16(param_offset
);
3852 pSMB
->DataOffset
= cpu_to_le16(offset
);
3853 pSMB
->SetupCount
= 1;
3854 pSMB
->Reserved3
= 0;
3855 pSMB
->SubCommand
= cpu_to_le16(TRANS2_SET_PATH_INFORMATION
);
3856 byte_count
= 3 /* pad */ + params
+ data_count
;
3857 pSMB
->DataCount
= cpu_to_le16(data_count
);
3858 pSMB
->TotalDataCount
= pSMB
->DataCount
;
3859 pSMB
->ParameterCount
= cpu_to_le16(params
);
3860 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
3861 pSMB
->Reserved4
= 0;
3862 pSMB
->hdr
.smb_buf_length
+= byte_count
;
3863 parm_data
->FileSize
= cpu_to_le64(size
);
3864 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
3865 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
3866 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
3868 cFYI(1, ("SetPathInfo (file size) returned %d", rc
));
3871 cifs_buf_release(pSMB
);
3880 CIFSSMBSetFileSize(const int xid
, struct cifsTconInfo
*tcon
, __u64 size
,
3881 __u16 fid
, __u32 pid_of_opener
, int SetAllocation
)
3883 struct smb_com_transaction2_sfi_req
*pSMB
= NULL
;
3884 struct smb_com_transaction2_sfi_rsp
*pSMBr
= NULL
;
3886 struct file_end_of_file_info
*parm_data
;
3888 int bytes_returned
= 0;
3889 __u16 params
, param_offset
, offset
, byte_count
, count
;
3891 cFYI(1, ("SetFileSize (via SetFileInfo) %lld",
3893 rc
= small_smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
);
3898 pSMBr
= (struct smb_com_transaction2_sfi_rsp
*)pSMB
;
3900 pSMB
->hdr
.Pid
= cpu_to_le16((__u16
)pid_of_opener
);
3901 pSMB
->hdr
.PidHigh
= cpu_to_le16((__u16
)(pid_of_opener
>> 16));
3904 pSMB
->MaxSetupCount
= 0;
3908 pSMB
->Reserved2
= 0;
3909 param_offset
= offsetof(struct smb_com_transaction2_sfi_req
, Fid
) - 4;
3910 offset
= param_offset
+ params
;
3912 data_offset
= (char *) (&pSMB
->hdr
.Protocol
) + offset
;
3914 count
= sizeof(struct file_end_of_file_info
);
3915 pSMB
->MaxParameterCount
= cpu_to_le16(2);
3916 pSMB
->MaxDataCount
= cpu_to_le16(1000); /* BB find max SMB PDU from sess */
3917 pSMB
->SetupCount
= 1;
3918 pSMB
->Reserved3
= 0;
3919 pSMB
->SubCommand
= cpu_to_le16(TRANS2_SET_FILE_INFORMATION
);
3920 byte_count
= 3 /* pad */ + params
+ count
;
3921 pSMB
->DataCount
= cpu_to_le16(count
);
3922 pSMB
->ParameterCount
= cpu_to_le16(params
);
3923 pSMB
->TotalDataCount
= pSMB
->DataCount
;
3924 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
3925 pSMB
->ParameterOffset
= cpu_to_le16(param_offset
);
3927 (struct file_end_of_file_info
*) (((char *) &pSMB
->hdr
.Protocol
) +
3929 pSMB
->DataOffset
= cpu_to_le16(offset
);
3930 parm_data
->FileSize
= cpu_to_le64(size
);
3933 if (tcon
->ses
->capabilities
& CAP_INFOLEVEL_PASSTHRU
)
3934 pSMB
->InformationLevel
=
3935 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2
);
3937 pSMB
->InformationLevel
=
3938 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO
);
3939 } else /* Set File Size */ {
3940 if (tcon
->ses
->capabilities
& CAP_INFOLEVEL_PASSTHRU
)
3941 pSMB
->InformationLevel
=
3942 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO2
);
3944 pSMB
->InformationLevel
=
3945 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO
);
3947 pSMB
->Reserved4
= 0;
3948 pSMB
->hdr
.smb_buf_length
+= byte_count
;
3949 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
3950 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
3951 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
3954 ("Send error in SetFileInfo (SetFileSize) = %d",
3959 cifs_small_buf_release(pSMB
);
3961 /* Note: On -EAGAIN error only caller can retry on handle based calls
3962 since file handle passed in no longer valid */
3967 /* Some legacy servers such as NT4 require that the file times be set on
3968 an open handle, rather than by pathname - this is awkward due to
3969 potential access conflicts on the open, but it is unavoidable for these
3970 old servers since the only other choice is to go from 100 nanosecond DCE
3971 time and resort to the original setpathinfo level which takes the ancient
3972 DOS time format with 2 second granularity */
3974 CIFSSMBSetFileTimes(const int xid
, struct cifsTconInfo
*tcon
, const FILE_BASIC_INFO
* data
,
3977 struct smb_com_transaction2_sfi_req
*pSMB
= NULL
;
3978 struct smb_com_transaction2_sfi_rsp
*pSMBr
= NULL
;
3981 int bytes_returned
= 0;
3982 __u16 params
, param_offset
, offset
, byte_count
, count
;
3984 cFYI(1, ("Set Times (via SetFileInfo)"));
3985 rc
= small_smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
);
3990 pSMBr
= (struct smb_com_transaction2_sfi_rsp
*)pSMB
;
3992 /* At this point there is no need to override the current pid
3993 with the pid of the opener, but that could change if we someday
3994 use an existing handle (rather than opening one on the fly) */
3995 /* pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
3996 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));*/
3999 pSMB
->MaxSetupCount
= 0;
4003 pSMB
->Reserved2
= 0;
4004 param_offset
= offsetof(struct smb_com_transaction2_sfi_req
, Fid
) - 4;
4005 offset
= param_offset
+ params
;
4007 data_offset
= (char *) (&pSMB
->hdr
.Protocol
) + offset
;
4009 count
= sizeof (FILE_BASIC_INFO
);
4010 pSMB
->MaxParameterCount
= cpu_to_le16(2);
4011 pSMB
->MaxDataCount
= cpu_to_le16(1000); /* BB find max SMB PDU from sess */
4012 pSMB
->SetupCount
= 1;
4013 pSMB
->Reserved3
= 0;
4014 pSMB
->SubCommand
= cpu_to_le16(TRANS2_SET_FILE_INFORMATION
);
4015 byte_count
= 3 /* pad */ + params
+ count
;
4016 pSMB
->DataCount
= cpu_to_le16(count
);
4017 pSMB
->ParameterCount
= cpu_to_le16(params
);
4018 pSMB
->TotalDataCount
= pSMB
->DataCount
;
4019 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
4020 pSMB
->ParameterOffset
= cpu_to_le16(param_offset
);
4021 pSMB
->DataOffset
= cpu_to_le16(offset
);
4023 if (tcon
->ses
->capabilities
& CAP_INFOLEVEL_PASSTHRU
)
4024 pSMB
->InformationLevel
= cpu_to_le16(SMB_SET_FILE_BASIC_INFO2
);
4026 pSMB
->InformationLevel
= cpu_to_le16(SMB_SET_FILE_BASIC_INFO
);
4027 pSMB
->Reserved4
= 0;
4028 pSMB
->hdr
.smb_buf_length
+= byte_count
;
4029 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
4030 memcpy(data_offset
,data
,sizeof(FILE_BASIC_INFO
));
4031 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
4032 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
4034 cFYI(1,("Send error in Set Time (SetFileInfo) = %d",rc
));
4037 cifs_small_buf_release(pSMB
);
4039 /* Note: On -EAGAIN error only caller can retry on handle based calls
4040 since file handle passed in no longer valid */
4047 CIFSSMBSetTimes(const int xid
, struct cifsTconInfo
*tcon
, const char *fileName
,
4048 const FILE_BASIC_INFO
* data
,
4049 const struct nls_table
*nls_codepage
, int remap
)
4051 TRANSACTION2_SPI_REQ
*pSMB
= NULL
;
4052 TRANSACTION2_SPI_RSP
*pSMBr
= NULL
;
4055 int bytes_returned
= 0;
4057 __u16 params
, param_offset
, offset
, byte_count
, count
;
4059 cFYI(1, ("In SetTimes"));
4062 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
4067 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
4069 cifsConvertToUCS((__le16
*) pSMB
->FileName
, fileName
,
4070 PATH_MAX
, nls_codepage
, remap
);
4071 name_len
++; /* trailing null */
4073 } else { /* BB improve the check for buffer overruns BB */
4074 name_len
= strnlen(fileName
, PATH_MAX
);
4075 name_len
++; /* trailing null */
4076 strncpy(pSMB
->FileName
, fileName
, name_len
);
4079 params
= 6 + name_len
;
4080 count
= sizeof (FILE_BASIC_INFO
);
4081 pSMB
->MaxParameterCount
= cpu_to_le16(2);
4082 pSMB
->MaxDataCount
= cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
4083 pSMB
->MaxSetupCount
= 0;
4087 pSMB
->Reserved2
= 0;
4088 param_offset
= offsetof(struct smb_com_transaction2_spi_req
,
4089 InformationLevel
) - 4;
4090 offset
= param_offset
+ params
;
4091 data_offset
= (char *) (&pSMB
->hdr
.Protocol
) + offset
;
4092 pSMB
->ParameterOffset
= cpu_to_le16(param_offset
);
4093 pSMB
->DataOffset
= cpu_to_le16(offset
);
4094 pSMB
->SetupCount
= 1;
4095 pSMB
->Reserved3
= 0;
4096 pSMB
->SubCommand
= cpu_to_le16(TRANS2_SET_PATH_INFORMATION
);
4097 byte_count
= 3 /* pad */ + params
+ count
;
4099 pSMB
->DataCount
= cpu_to_le16(count
);
4100 pSMB
->ParameterCount
= cpu_to_le16(params
);
4101 pSMB
->TotalDataCount
= pSMB
->DataCount
;
4102 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
4103 if (tcon
->ses
->capabilities
& CAP_INFOLEVEL_PASSTHRU
)
4104 pSMB
->InformationLevel
= cpu_to_le16(SMB_SET_FILE_BASIC_INFO2
);
4106 pSMB
->InformationLevel
= cpu_to_le16(SMB_SET_FILE_BASIC_INFO
);
4107 pSMB
->Reserved4
= 0;
4108 pSMB
->hdr
.smb_buf_length
+= byte_count
;
4109 memcpy(data_offset
, data
, sizeof (FILE_BASIC_INFO
));
4110 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
4111 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
4112 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
4114 cFYI(1, ("SetPathInfo (times) returned %d", rc
));
4117 cifs_buf_release(pSMB
);
4125 /* Can not be used to set time stamps yet (due to old DOS time format) */
4126 /* Can be used to set attributes */
4127 #if 0 /* Possibly not needed - since it turns out that strangely NT4 has a bug
4128 handling it anyway and NT4 was what we thought it would be needed for
4129 Do not delete it until we prove whether needed for Win9x though */
4131 CIFSSMBSetAttrLegacy(int xid
, struct cifsTconInfo
*tcon
, char *fileName
,
4132 __u16 dos_attrs
, const struct nls_table
*nls_codepage
)
4134 SETATTR_REQ
*pSMB
= NULL
;
4135 SETATTR_RSP
*pSMBr
= NULL
;
4140 cFYI(1, ("In SetAttrLegacy"));
4143 rc
= smb_init(SMB_COM_SETATTR
, 8, tcon
, (void **) &pSMB
,
4148 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
4150 ConvertToUCS((__le16
*) pSMB
->fileName
, fileName
,
4151 PATH_MAX
, nls_codepage
);
4152 name_len
++; /* trailing null */
4154 } else { /* BB improve the check for buffer overruns BB */
4155 name_len
= strnlen(fileName
, PATH_MAX
);
4156 name_len
++; /* trailing null */
4157 strncpy(pSMB
->fileName
, fileName
, name_len
);
4159 pSMB
->attr
= cpu_to_le16(dos_attrs
);
4160 pSMB
->BufferFormat
= 0x04;
4161 pSMB
->hdr
.smb_buf_length
+= name_len
+ 1;
4162 pSMB
->ByteCount
= cpu_to_le16(name_len
+ 1);
4163 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
4164 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
4166 cFYI(1, ("Error in LegacySetAttr = %d", rc
));
4169 cifs_buf_release(pSMB
);
4172 goto SetAttrLgcyRetry
;
4176 #endif /* temporarily unneeded SetAttr legacy function */
4179 CIFSSMBUnixSetPerms(const int xid
, struct cifsTconInfo
*tcon
,
4180 char *fileName
, __u64 mode
, __u64 uid
, __u64 gid
,
4181 dev_t device
, const struct nls_table
*nls_codepage
,
4184 TRANSACTION2_SPI_REQ
*pSMB
= NULL
;
4185 TRANSACTION2_SPI_RSP
*pSMBr
= NULL
;
4188 int bytes_returned
= 0;
4189 FILE_UNIX_BASIC_INFO
*data_offset
;
4190 __u16 params
, param_offset
, offset
, count
, byte_count
;
4192 cFYI(1, ("In SetUID/GID/Mode"));
4194 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
4199 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
4201 cifsConvertToUCS((__le16
*) pSMB
->FileName
, fileName
,
4202 PATH_MAX
, nls_codepage
, remap
);
4203 name_len
++; /* trailing null */
4205 } else { /* BB improve the check for buffer overruns BB */
4206 name_len
= strnlen(fileName
, PATH_MAX
);
4207 name_len
++; /* trailing null */
4208 strncpy(pSMB
->FileName
, fileName
, name_len
);
4211 params
= 6 + name_len
;
4212 count
= sizeof (FILE_UNIX_BASIC_INFO
);
4213 pSMB
->MaxParameterCount
= cpu_to_le16(2);
4214 pSMB
->MaxDataCount
= cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
4215 pSMB
->MaxSetupCount
= 0;
4219 pSMB
->Reserved2
= 0;
4220 param_offset
= offsetof(struct smb_com_transaction2_spi_req
,
4221 InformationLevel
) - 4;
4222 offset
= param_offset
+ params
;
4224 (FILE_UNIX_BASIC_INFO
*) ((char *) &pSMB
->hdr
.Protocol
+
4226 memset(data_offset
, 0, count
);
4227 pSMB
->DataOffset
= cpu_to_le16(offset
);
4228 pSMB
->ParameterOffset
= cpu_to_le16(param_offset
);
4229 pSMB
->SetupCount
= 1;
4230 pSMB
->Reserved3
= 0;
4231 pSMB
->SubCommand
= cpu_to_le16(TRANS2_SET_PATH_INFORMATION
);
4232 byte_count
= 3 /* pad */ + params
+ count
;
4233 pSMB
->ParameterCount
= cpu_to_le16(params
);
4234 pSMB
->DataCount
= cpu_to_le16(count
);
4235 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
4236 pSMB
->TotalDataCount
= pSMB
->DataCount
;
4237 pSMB
->InformationLevel
= cpu_to_le16(SMB_SET_FILE_UNIX_BASIC
);
4238 pSMB
->Reserved4
= 0;
4239 pSMB
->hdr
.smb_buf_length
+= byte_count
;
4240 data_offset
->Uid
= cpu_to_le64(uid
);
4241 data_offset
->Gid
= cpu_to_le64(gid
);
4242 /* better to leave device as zero when it is */
4243 data_offset
->DevMajor
= cpu_to_le64(MAJOR(device
));
4244 data_offset
->DevMinor
= cpu_to_le64(MINOR(device
));
4245 data_offset
->Permissions
= cpu_to_le64(mode
);
4248 data_offset
->Type
= cpu_to_le32(UNIX_FILE
);
4249 else if(S_ISDIR(mode
))
4250 data_offset
->Type
= cpu_to_le32(UNIX_DIR
);
4251 else if(S_ISLNK(mode
))
4252 data_offset
->Type
= cpu_to_le32(UNIX_SYMLINK
);
4253 else if(S_ISCHR(mode
))
4254 data_offset
->Type
= cpu_to_le32(UNIX_CHARDEV
);
4255 else if(S_ISBLK(mode
))
4256 data_offset
->Type
= cpu_to_le32(UNIX_BLOCKDEV
);
4257 else if(S_ISFIFO(mode
))
4258 data_offset
->Type
= cpu_to_le32(UNIX_FIFO
);
4259 else if(S_ISSOCK(mode
))
4260 data_offset
->Type
= cpu_to_le32(UNIX_SOCKET
);
4263 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
4264 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
4265 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
4267 cFYI(1, ("SetPathInfo (perms) returned %d", rc
));
4271 cifs_buf_release(pSMB
);
4277 int CIFSSMBNotify(const int xid
, struct cifsTconInfo
*tcon
,
4278 const int notify_subdirs
, const __u16 netfid
,
4279 __u32 filter
, struct file
* pfile
, int multishot
,
4280 const struct nls_table
*nls_codepage
)
4283 struct smb_com_transaction_change_notify_req
* pSMB
= NULL
;
4284 struct smb_com_transaction_change_notify_rsp
* pSMBr
= NULL
;
4285 struct dir_notify_req
*dnotify_req
;
4288 cFYI(1, ("In CIFSSMBNotify for file handle %d",(int)netfid
));
4289 rc
= smb_init(SMB_COM_NT_TRANSACT
, 23, tcon
, (void **) &pSMB
,
4294 pSMB
->TotalParameterCount
= 0 ;
4295 pSMB
->TotalDataCount
= 0;
4296 pSMB
->MaxParameterCount
= cpu_to_le32(2);
4297 /* BB find exact data count max from sess structure BB */
4298 pSMB
->MaxDataCount
= 0; /* same in little endian or be */
4299 pSMB
->MaxSetupCount
= 4;
4301 pSMB
->ParameterOffset
= 0;
4302 pSMB
->DataCount
= 0;
4303 pSMB
->DataOffset
= 0;
4304 pSMB
->SetupCount
= 4; /* single byte does not need le conversion */
4305 pSMB
->SubCommand
= cpu_to_le16(NT_TRANSACT_NOTIFY_CHANGE
);
4306 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
4308 pSMB
->WatchTree
= 1; /* one byte - no le conversion needed */
4309 pSMB
->Reserved2
= 0;
4310 pSMB
->CompletionFilter
= cpu_to_le32(filter
);
4311 pSMB
->Fid
= netfid
; /* file handle always le */
4312 pSMB
->ByteCount
= 0;
4314 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
4315 (struct smb_hdr
*) pSMBr
, &bytes_returned
, -1);
4317 cFYI(1, ("Error in Notify = %d", rc
));
4319 /* Add file to outstanding requests */
4320 /* BB change to kmem cache alloc */
4321 dnotify_req
= (struct dir_notify_req
*) kmalloc(
4322 sizeof(struct dir_notify_req
),
4325 dnotify_req
->Pid
= pSMB
->hdr
.Pid
;
4326 dnotify_req
->PidHigh
= pSMB
->hdr
.PidHigh
;
4327 dnotify_req
->Mid
= pSMB
->hdr
.Mid
;
4328 dnotify_req
->Tid
= pSMB
->hdr
.Tid
;
4329 dnotify_req
->Uid
= pSMB
->hdr
.Uid
;
4330 dnotify_req
->netfid
= netfid
;
4331 dnotify_req
->pfile
= pfile
;
4332 dnotify_req
->filter
= filter
;
4333 dnotify_req
->multishot
= multishot
;
4334 spin_lock(&GlobalMid_Lock
);
4335 list_add_tail(&dnotify_req
->lhead
,
4336 &GlobalDnotifyReqList
);
4337 spin_unlock(&GlobalMid_Lock
);
4341 cifs_buf_release(pSMB
);
4344 #ifdef CONFIG_CIFS_XATTR
4346 CIFSSMBQAllEAs(const int xid
, struct cifsTconInfo
*tcon
,
4347 const unsigned char *searchName
,
4348 char * EAData
, size_t buf_size
,
4349 const struct nls_table
*nls_codepage
, int remap
)
4351 /* BB assumes one setup word */
4352 TRANSACTION2_QPI_REQ
*pSMB
= NULL
;
4353 TRANSACTION2_QPI_RSP
*pSMBr
= NULL
;
4357 struct fea
* temp_fea
;
4359 __u16 params
, byte_count
;
4361 cFYI(1, ("In Query All EAs path %s", searchName
));
4363 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
4368 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
4370 cifsConvertToUCS((__le16
*) pSMB
->FileName
, searchName
,
4371 PATH_MAX
, nls_codepage
, remap
);
4372 name_len
++; /* trailing null */
4374 } else { /* BB improve the check for buffer overruns BB */
4375 name_len
= strnlen(searchName
, PATH_MAX
);
4376 name_len
++; /* trailing null */
4377 strncpy(pSMB
->FileName
, searchName
, name_len
);
4380 params
= 2 /* level */ + 4 /* reserved */ + name_len
/* includes NUL */ ;
4381 pSMB
->TotalDataCount
= 0;
4382 pSMB
->MaxParameterCount
= cpu_to_le16(2);
4383 pSMB
->MaxDataCount
= cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
4384 pSMB
->MaxSetupCount
= 0;
4388 pSMB
->Reserved2
= 0;
4389 pSMB
->ParameterOffset
= cpu_to_le16(offsetof(
4390 struct smb_com_transaction2_qpi_req
,InformationLevel
) - 4);
4391 pSMB
->DataCount
= 0;
4392 pSMB
->DataOffset
= 0;
4393 pSMB
->SetupCount
= 1;
4394 pSMB
->Reserved3
= 0;
4395 pSMB
->SubCommand
= cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION
);
4396 byte_count
= params
+ 1 /* pad */ ;
4397 pSMB
->TotalParameterCount
= cpu_to_le16(params
);
4398 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
4399 pSMB
->InformationLevel
= cpu_to_le16(SMB_INFO_QUERY_ALL_EAS
);
4400 pSMB
->Reserved4
= 0;
4401 pSMB
->hdr
.smb_buf_length
+= byte_count
;
4402 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
4404 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
4405 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
4407 cFYI(1, ("Send error in QueryAllEAs = %d", rc
));
4408 } else { /* decode response */
4409 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
4411 /* BB also check enough total bytes returned */
4412 /* BB we need to improve the validity checking
4413 of these trans2 responses */
4414 if (rc
|| (pSMBr
->ByteCount
< 4))
4415 rc
= -EIO
; /* bad smb */
4416 /* else if (pFindData){
4417 memcpy((char *) pFindData,
4418 (char *) &pSMBr->hdr.Protocol +
4421 /* check that length of list is not more than bcc */
4422 /* check that each entry does not go beyond length
4424 /* check that each element of each entry does not
4425 go beyond end of list */
4426 __u16 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
4427 struct fealist
* ea_response_data
;
4429 /* validate_trans2_offsets() */
4430 /* BB to check if(start of smb + data_offset > &bcc+ bcc)*/
4431 ea_response_data
= (struct fealist
*)
4432 (((char *) &pSMBr
->hdr
.Protocol
) +
4434 name_len
= le32_to_cpu(ea_response_data
->list_len
);
4435 cFYI(1,("ea length %d", name_len
));
4437 /* returned EA size zeroed at top of function */
4438 cFYI(1,("empty EA list returned from server"));
4440 /* account for ea list len */
4442 temp_fea
= ea_response_data
->list
;
4443 temp_ptr
= (char *)temp_fea
;
4444 while(name_len
> 0) {
4448 rc
+= temp_fea
->name_len
;
4449 /* account for prefix user. and trailing null */
4451 if(rc
<(int)buf_size
) {
4452 memcpy(EAData
,"user.",5);
4454 memcpy(EAData
,temp_ptr
,temp_fea
->name_len
);
4455 EAData
+=temp_fea
->name_len
;
4456 /* null terminate name */
4458 EAData
= EAData
+ 1;
4459 } else if(buf_size
== 0) {
4460 /* skip copy - calc size only */
4462 /* stop before overrun buffer */
4466 name_len
-= temp_fea
->name_len
;
4467 temp_ptr
+= temp_fea
->name_len
;
4468 /* account for trailing null */
4471 value_len
= le16_to_cpu(temp_fea
->value_len
);
4472 name_len
-= value_len
;
4473 temp_ptr
+= value_len
;
4474 /* BB check that temp_ptr is still within smb BB*/
4475 /* no trailing null to account for in value len */
4476 /* go on to next EA */
4477 temp_fea
= (struct fea
*)temp_ptr
;
4483 cifs_buf_release(pSMB
);
4490 ssize_t
CIFSSMBQueryEA(const int xid
,struct cifsTconInfo
* tcon
,
4491 const unsigned char * searchName
,const unsigned char * ea_name
,
4492 unsigned char * ea_value
, size_t buf_size
,
4493 const struct nls_table
*nls_codepage
, int remap
)
4495 TRANSACTION2_QPI_REQ
*pSMB
= NULL
;
4496 TRANSACTION2_QPI_RSP
*pSMBr
= NULL
;
4500 struct fea
* temp_fea
;
4502 __u16 params
, byte_count
;
4504 cFYI(1, ("In Query EA path %s", searchName
));
4506 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
4511 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
4513 cifsConvertToUCS((__le16
*) pSMB
->FileName
, searchName
,
4514 PATH_MAX
, nls_codepage
, remap
);
4515 name_len
++; /* trailing null */
4517 } else { /* BB improve the check for buffer overruns BB */
4518 name_len
= strnlen(searchName
, PATH_MAX
);
4519 name_len
++; /* trailing null */
4520 strncpy(pSMB
->FileName
, searchName
, name_len
);
4523 params
= 2 /* level */ + 4 /* reserved */ + name_len
/* includes NUL */ ;
4524 pSMB
->TotalDataCount
= 0;
4525 pSMB
->MaxParameterCount
= cpu_to_le16(2);
4526 pSMB
->MaxDataCount
= cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
4527 pSMB
->MaxSetupCount
= 0;
4531 pSMB
->Reserved2
= 0;
4532 pSMB
->ParameterOffset
= cpu_to_le16(offsetof(
4533 struct smb_com_transaction2_qpi_req
,InformationLevel
) - 4);
4534 pSMB
->DataCount
= 0;
4535 pSMB
->DataOffset
= 0;
4536 pSMB
->SetupCount
= 1;
4537 pSMB
->Reserved3
= 0;
4538 pSMB
->SubCommand
= cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION
);
4539 byte_count
= params
+ 1 /* pad */ ;
4540 pSMB
->TotalParameterCount
= cpu_to_le16(params
);
4541 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
4542 pSMB
->InformationLevel
= cpu_to_le16(SMB_INFO_QUERY_ALL_EAS
);
4543 pSMB
->Reserved4
= 0;
4544 pSMB
->hdr
.smb_buf_length
+= byte_count
;
4545 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
4547 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
4548 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
4550 cFYI(1, ("Send error in Query EA = %d", rc
));
4551 } else { /* decode response */
4552 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
4554 /* BB also check enough total bytes returned */
4555 /* BB we need to improve the validity checking
4556 of these trans2 responses */
4557 if (rc
|| (pSMBr
->ByteCount
< 4))
4558 rc
= -EIO
; /* bad smb */
4559 /* else if (pFindData){
4560 memcpy((char *) pFindData,
4561 (char *) &pSMBr->hdr.Protocol +
4564 /* check that length of list is not more than bcc */
4565 /* check that each entry does not go beyond length
4567 /* check that each element of each entry does not
4568 go beyond end of list */
4569 __u16 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
4570 struct fealist
* ea_response_data
;
4572 /* validate_trans2_offsets() */
4573 /* BB to check if(start of smb + data_offset > &bcc+ bcc)*/
4574 ea_response_data
= (struct fealist
*)
4575 (((char *) &pSMBr
->hdr
.Protocol
) +
4577 name_len
= le32_to_cpu(ea_response_data
->list_len
);
4578 cFYI(1,("ea length %d", name_len
));
4580 /* returned EA size zeroed at top of function */
4581 cFYI(1,("empty EA list returned from server"));
4583 /* account for ea list len */
4585 temp_fea
= ea_response_data
->list
;
4586 temp_ptr
= (char *)temp_fea
;
4587 /* loop through checking if we have a matching
4588 name and then return the associated value */
4589 while(name_len
> 0) {
4593 value_len
= le16_to_cpu(temp_fea
->value_len
);
4594 /* BB validate that value_len falls within SMB,
4595 even though maximum for name_len is 255 */
4596 if(memcmp(temp_fea
->name
,ea_name
,
4597 temp_fea
->name_len
) == 0) {
4600 /* account for prefix user. and trailing null */
4601 if(rc
<=(int)buf_size
) {
4603 temp_fea
->name
+temp_fea
->name_len
+1,
4605 /* ea values, unlike ea names,
4606 are not null terminated */
4607 } else if(buf_size
== 0) {
4608 /* skip copy - calc size only */
4610 /* stop before overrun buffer */
4615 name_len
-= temp_fea
->name_len
;
4616 temp_ptr
+= temp_fea
->name_len
;
4617 /* account for trailing null */
4620 name_len
-= value_len
;
4621 temp_ptr
+= value_len
;
4622 /* no trailing null to account for in value len */
4623 /* go on to next EA */
4624 temp_fea
= (struct fea
*)temp_ptr
;
4630 cifs_buf_release(pSMB
);
4638 CIFSSMBSetEA(const int xid
, struct cifsTconInfo
*tcon
, const char *fileName
,
4639 const char * ea_name
, const void * ea_value
,
4640 const __u16 ea_value_len
, const struct nls_table
*nls_codepage
,
4643 struct smb_com_transaction2_spi_req
*pSMB
= NULL
;
4644 struct smb_com_transaction2_spi_rsp
*pSMBr
= NULL
;
4645 struct fealist
*parm_data
;
4648 int bytes_returned
= 0;
4649 __u16 params
, param_offset
, byte_count
, offset
, count
;
4651 cFYI(1, ("In SetEA"));
4653 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
4658 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
4660 cifsConvertToUCS((__le16
*) pSMB
->FileName
, fileName
,
4661 PATH_MAX
, nls_codepage
, remap
);
4662 name_len
++; /* trailing null */
4664 } else { /* BB improve the check for buffer overruns BB */
4665 name_len
= strnlen(fileName
, PATH_MAX
);
4666 name_len
++; /* trailing null */
4667 strncpy(pSMB
->FileName
, fileName
, name_len
);
4670 params
= 6 + name_len
;
4672 /* done calculating parms using name_len of file name,
4673 now use name_len to calculate length of ea name
4674 we are going to create in the inode xattrs */
4678 name_len
= strnlen(ea_name
,255);
4680 count
= sizeof(*parm_data
) + ea_value_len
+ name_len
+ 1;
4681 pSMB
->MaxParameterCount
= cpu_to_le16(2);
4682 pSMB
->MaxDataCount
= cpu_to_le16(1000); /* BB find max SMB size from sess */
4683 pSMB
->MaxSetupCount
= 0;
4687 pSMB
->Reserved2
= 0;
4688 param_offset
= offsetof(struct smb_com_transaction2_spi_req
,
4689 InformationLevel
) - 4;
4690 offset
= param_offset
+ params
;
4691 pSMB
->InformationLevel
=
4692 cpu_to_le16(SMB_SET_FILE_EA
);
4695 (struct fealist
*) (((char *) &pSMB
->hdr
.Protocol
) +
4697 pSMB
->ParameterOffset
= cpu_to_le16(param_offset
);
4698 pSMB
->DataOffset
= cpu_to_le16(offset
);
4699 pSMB
->SetupCount
= 1;
4700 pSMB
->Reserved3
= 0;
4701 pSMB
->SubCommand
= cpu_to_le16(TRANS2_SET_PATH_INFORMATION
);
4702 byte_count
= 3 /* pad */ + params
+ count
;
4703 pSMB
->DataCount
= cpu_to_le16(count
);
4704 parm_data
->list_len
= cpu_to_le32(count
);
4705 parm_data
->list
[0].EA_flags
= 0;
4706 /* we checked above that name len is less than 255 */
4707 parm_data
->list
[0].name_len
= (__u8
)name_len
;;
4708 /* EA names are always ASCII */
4710 strncpy(parm_data
->list
[0].name
,ea_name
,name_len
);
4711 parm_data
->list
[0].name
[name_len
] = 0;
4712 parm_data
->list
[0].value_len
= cpu_to_le16(ea_value_len
);
4713 /* caller ensures that ea_value_len is less than 64K but
4714 we need to ensure that it fits within the smb */
4716 /*BB add length check that it would fit in negotiated SMB buffer size BB */
4717 /* if(ea_value_len > buffer_size - 512 (enough for header)) */
4719 memcpy(parm_data
->list
[0].name
+name_len
+1,ea_value
,ea_value_len
);
4721 pSMB
->TotalDataCount
= pSMB
->DataCount
;
4722 pSMB
->ParameterCount
= cpu_to_le16(params
);
4723 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
4724 pSMB
->Reserved4
= 0;
4725 pSMB
->hdr
.smb_buf_length
+= byte_count
;
4726 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
4727 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
4728 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
4730 cFYI(1, ("SetPathInfo (EA) returned %d", rc
));
4733 cifs_buf_release(pSMB
);