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
->ses
) && (tcon
->ses
->status
!= CifsExiting
) &&
95 struct nls_table
*nls_codepage
;
96 /* Give Demultiplex thread up to 10 seconds to
97 reconnect, should be greater than cifs socket
98 timeout which is 7 seconds */
99 while(tcon
->ses
->server
->tcpStatus
== CifsNeedReconnect
) {
100 wait_event_interruptible_timeout(tcon
->ses
->server
->response_q
,
101 (tcon
->ses
->server
->tcpStatus
== CifsGood
), 10 * HZ
);
102 if(tcon
->ses
->server
->tcpStatus
== CifsNeedReconnect
) {
103 /* on "soft" mounts we wait once */
104 if((tcon
->retry
== FALSE
) ||
105 (tcon
->ses
->status
== CifsExiting
)) {
106 cFYI(1,("gave up waiting on reconnect in smb_init"));
108 } /* else "hard" mount - keep retrying
109 until process is killed or server
110 comes back on-line */
111 } else /* TCP session is reestablished now */
116 nls_codepage
= load_nls_default();
117 /* need to prevent multiple threads trying to
118 simultaneously reconnect the same SMB session */
119 down(&tcon
->ses
->sesSem
);
120 if(tcon
->ses
->status
== CifsNeedReconnect
)
121 rc
= cifs_setup_session(0, tcon
->ses
,
123 if(!rc
&& (tcon
->tidStatus
== CifsNeedReconnect
)) {
124 mark_open_files_invalid(tcon
);
125 rc
= CIFSTCon(0, tcon
->ses
, tcon
->treeName
, tcon
127 up(&tcon
->ses
->sesSem
);
129 atomic_inc(&tconInfoReconnectCount
);
131 cFYI(1, ("reconnect tcon rc = %d", rc
));
132 /* Removed call to reopen open files here -
133 it is safer (and faster) to reopen files
134 one at a time as needed in read and write */
136 /* Check if handle based operation so we
137 know whether we can continue or not without
138 returning to caller to reset file handle */
139 switch(smb_command
) {
140 case SMB_COM_READ_ANDX
:
141 case SMB_COM_WRITE_ANDX
:
143 case SMB_COM_FIND_CLOSE2
:
144 case SMB_COM_LOCKING_ANDX
: {
145 unload_nls(nls_codepage
);
150 up(&tcon
->ses
->sesSem
);
152 unload_nls(nls_codepage
);
161 *request_buf
= cifs_small_buf_get();
162 if (*request_buf
== NULL
) {
163 /* BB should we add a retry in here if not a writepage? */
167 header_assemble((struct smb_hdr
*) *request_buf
, smb_command
, tcon
,wct
);
169 #ifdef CONFIG_CIFS_STATS
171 atomic_inc(&tcon
->num_smbs_sent
);
173 #endif /* CONFIG_CIFS_STATS */
177 /* If the return code is zero, this function must fill in request_buf pointer */
179 smb_init(int smb_command
, int wct
, struct cifsTconInfo
*tcon
,
180 void **request_buf
/* returned */ ,
181 void **response_buf
/* returned */ )
185 /* SMBs NegProt, SessSetup, uLogoff do not have tcon yet so
186 check for tcp and smb session status done differently
187 for those three - in the calling routine */
189 if((tcon
->ses
) && (tcon
->ses
->status
!= CifsExiting
) &&
190 (tcon
->ses
->server
)){
191 struct nls_table
*nls_codepage
;
192 /* Give Demultiplex thread up to 10 seconds to
193 reconnect, should be greater than cifs socket
194 timeout which is 7 seconds */
195 while(tcon
->ses
->server
->tcpStatus
== CifsNeedReconnect
) {
196 wait_event_interruptible_timeout(tcon
->ses
->server
->response_q
,
197 (tcon
->ses
->server
->tcpStatus
== CifsGood
), 10 * HZ
);
198 if(tcon
->ses
->server
->tcpStatus
==
200 /* on "soft" mounts we wait once */
201 if((tcon
->retry
== FALSE
) ||
202 (tcon
->ses
->status
== CifsExiting
)) {
203 cFYI(1,("gave up waiting on reconnect in smb_init"));
205 } /* else "hard" mount - keep retrying
206 until process is killed or server
208 } else /* TCP session is reestablished now */
213 nls_codepage
= load_nls_default();
214 /* need to prevent multiple threads trying to
215 simultaneously reconnect the same SMB session */
216 down(&tcon
->ses
->sesSem
);
217 if(tcon
->ses
->status
== CifsNeedReconnect
)
218 rc
= cifs_setup_session(0, tcon
->ses
,
220 if(!rc
&& (tcon
->tidStatus
== CifsNeedReconnect
)) {
221 mark_open_files_invalid(tcon
);
222 rc
= CIFSTCon(0, tcon
->ses
, tcon
->treeName
,
224 up(&tcon
->ses
->sesSem
);
226 atomic_inc(&tconInfoReconnectCount
);
228 cFYI(1, ("reconnect tcon rc = %d", rc
));
229 /* Removed call to reopen open files here -
230 it is safer (and faster) to reopen files
231 one at a time as needed in read and write */
233 /* Check if handle based operation so we
234 know whether we can continue or not without
235 returning to caller to reset file handle */
236 switch(smb_command
) {
237 case SMB_COM_READ_ANDX
:
238 case SMB_COM_WRITE_ANDX
:
240 case SMB_COM_FIND_CLOSE2
:
241 case SMB_COM_LOCKING_ANDX
: {
242 unload_nls(nls_codepage
);
247 up(&tcon
->ses
->sesSem
);
249 unload_nls(nls_codepage
);
258 *request_buf
= cifs_buf_get();
259 if (*request_buf
== NULL
) {
260 /* BB should we add a retry in here if not a writepage? */
263 /* Although the original thought was we needed the response buf for */
264 /* potential retries of smb operations it turns out we can determine */
265 /* from the mid flags when the request buffer can be resent without */
266 /* having to use a second distinct buffer for the response */
267 *response_buf
= *request_buf
;
269 header_assemble((struct smb_hdr
*) *request_buf
, smb_command
, tcon
,
272 #ifdef CONFIG_CIFS_STATS
274 atomic_inc(&tcon
->num_smbs_sent
);
276 #endif /* CONFIG_CIFS_STATS */
280 static int validate_t2(struct smb_t2_rsp
* pSMB
)
286 /* check for plausible wct, bcc and t2 data and parm sizes */
287 /* check for parm and data offset going beyond end of smb */
288 if(pSMB
->hdr
.WordCount
>= 10) {
289 if((le16_to_cpu(pSMB
->t2_rsp
.ParameterOffset
) <= 1024) &&
290 (le16_to_cpu(pSMB
->t2_rsp
.DataOffset
) <= 1024)) {
291 /* check that bcc is at least as big as parms + data */
292 /* check that bcc is less than negotiated smb buffer */
293 total_size
= le16_to_cpu(pSMB
->t2_rsp
.ParameterCount
);
294 if(total_size
< 512) {
295 total_size
+=le16_to_cpu(pSMB
->t2_rsp
.DataCount
);
296 /* BCC le converted in SendReceive */
297 pBCC
= (pSMB
->hdr
.WordCount
* 2) +
298 sizeof(struct smb_hdr
) +
300 if((total_size
<= (*(u16
*)pBCC
)) &&
302 CIFSMaxBufSize
+MAX_CIFS_HDR_SIZE
)) {
309 cifs_dump_mem("Invalid transact2 SMB: ",(char *)pSMB
,
310 sizeof(struct smb_t2_rsp
) + 16);
314 CIFSSMBNegotiate(unsigned int xid
, struct cifsSesInfo
*ses
)
317 NEGOTIATE_RSP
*pSMBr
;
320 struct TCP_Server_Info
* server
;
324 server
= ses
->server
;
329 rc
= smb_init(SMB_COM_NEGOTIATE
, 0, NULL
/* no tcon yet */ ,
330 (void **) &pSMB
, (void **) &pSMBr
);
334 pSMB
->hdr
.Flags2
|= SMBFLG2_UNICODE
;
335 if (extended_security
)
336 pSMB
->hdr
.Flags2
|= SMBFLG2_EXT_SEC
;
338 count
= strlen(protocols
[0].name
) + 1;
339 strncpy(pSMB
->DialectsArray
, protocols
[0].name
, 30);
340 /* null guaranteed to be at end of source and target buffers anyway */
342 pSMB
->hdr
.smb_buf_length
+= count
;
343 pSMB
->ByteCount
= cpu_to_le16(count
);
345 rc
= SendReceive(xid
, ses
, (struct smb_hdr
*) pSMB
,
346 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
348 server
->secMode
= pSMBr
->SecurityMode
;
349 server
->secType
= NTLM
; /* BB override default for
350 NTLMv2 or kerberos v5 */
351 /* one byte - no need to convert this or EncryptionKeyLen
352 from little endian */
353 server
->maxReq
= le16_to_cpu(pSMBr
->MaxMpxCount
);
354 /* probably no need to store and check maxvcs */
356 min(le32_to_cpu(pSMBr
->MaxBufferSize
),
357 (__u32
) CIFSMaxBufSize
+ MAX_CIFS_HDR_SIZE
);
358 server
->maxRw
= le32_to_cpu(pSMBr
->MaxRawSize
);
359 cFYI(0, ("Max buf = %d ", ses
->server
->maxBuf
));
360 GETU32(ses
->server
->sessid
) = le32_to_cpu(pSMBr
->SessionKey
);
361 server
->capabilities
= le32_to_cpu(pSMBr
->Capabilities
);
362 server
->timeZone
= le16_to_cpu(pSMBr
->ServerTimeZone
);
363 /* BB with UTC do we ever need to be using srvr timezone? */
364 if (pSMBr
->EncryptionKeyLength
== CIFS_CRYPTO_KEY_SIZE
) {
365 memcpy(server
->cryptKey
, pSMBr
->u
.EncryptionKey
,
366 CIFS_CRYPTO_KEY_SIZE
);
367 } else if ((pSMBr
->hdr
.Flags2
& SMBFLG2_EXT_SEC
)
368 && (pSMBr
->EncryptionKeyLength
== 0)) {
369 /* decode security blob */
373 /* BB might be helpful to save off the domain of server here */
375 if ((pSMBr
->hdr
.Flags2
& SMBFLG2_EXT_SEC
) &&
376 (server
->capabilities
& CAP_EXTENDED_SECURITY
)) {
377 count
= pSMBr
->ByteCount
;
380 else if (count
== 16) {
381 server
->secType
= RawNTLMSSP
;
382 if (server
->socketUseCount
.counter
> 1) {
384 (server
->server_GUID
,
385 pSMBr
->u
.extended_response
.
388 ("UID of server does not match previous connection to same ip address"));
396 memcpy(server
->server_GUID
,
397 pSMBr
->u
.extended_response
.
400 rc
= decode_negTokenInit(pSMBr
->u
.
406 /* BB Need to fill struct for sessetup here */
413 server
->capabilities
&= ~CAP_EXTENDED_SECURITY
;
414 if(sign_CIFS_PDUs
== FALSE
) {
415 if(server
->secMode
& SECMODE_SIGN_REQUIRED
)
417 ("Server requires /proc/fs/cifs/PacketSigningEnabled"));
418 server
->secMode
&= ~(SECMODE_SIGN_ENABLED
| SECMODE_SIGN_REQUIRED
);
419 } else if(sign_CIFS_PDUs
== 1) {
420 if((server
->secMode
& SECMODE_SIGN_REQUIRED
) == 0)
421 server
->secMode
&= ~(SECMODE_SIGN_ENABLED
| SECMODE_SIGN_REQUIRED
);
426 cifs_buf_release(pSMB
);
431 CIFSSMBTDis(const int xid
, struct cifsTconInfo
*tcon
)
433 struct smb_hdr
*smb_buffer
;
434 struct smb_hdr
*smb_buffer_response
; /* BB removeme BB */
438 cFYI(1, ("In tree disconnect"));
440 * If last user of the connection and
441 * connection alive - disconnect it
442 * If this is the last connection on the server session disconnect it
443 * (and inside session disconnect we should check if tcp socket needs
444 * to be freed and kernel thread woken up).
447 down(&tcon
->tconSem
);
451 atomic_dec(&tcon
->useCount
);
452 if (atomic_read(&tcon
->useCount
) > 0) {
457 /* No need to return error on this operation if tid invalidated and
458 closed on server already e.g. due to tcp session crashing */
459 if(tcon
->tidStatus
== CifsNeedReconnect
) {
464 if((tcon
->ses
== NULL
) || (tcon
->ses
->server
== NULL
)) {
468 rc
= small_smb_init(SMB_COM_TREE_DISCONNECT
, 0, tcon
,
469 (void **)&smb_buffer
);
474 smb_buffer_response
= smb_buffer
; /* BB removeme BB */
476 rc
= SendReceive(xid
, tcon
->ses
, smb_buffer
, smb_buffer_response
,
479 cFYI(1, ("Tree disconnect failed %d", rc
));
482 cifs_small_buf_release(smb_buffer
);
485 /* No need to return error on this operation if tid invalidated and
486 closed on server already e.g. due to tcp session crashing */
494 CIFSSMBLogoff(const int xid
, struct cifsSesInfo
*ses
)
496 struct smb_hdr
*smb_buffer_response
;
497 LOGOFF_ANDX_REQ
*pSMB
;
501 cFYI(1, ("In SMBLogoff for session disconnect"));
507 atomic_dec(&ses
->inUse
);
508 if (atomic_read(&ses
->inUse
) > 0) {
512 rc
= small_smb_init(SMB_COM_LOGOFF_ANDX
, 2, NULL
, (void **)&pSMB
);
518 smb_buffer_response
= (struct smb_hdr
*)pSMB
; /* BB removeme BB */
521 if(ses
->server
->secMode
&
522 (SECMODE_SIGN_REQUIRED
| SECMODE_SIGN_ENABLED
))
523 pSMB
->hdr
.Flags2
|= SMBFLG2_SECURITY_SIGNATURE
;
526 pSMB
->hdr
.Uid
= ses
->Suid
;
528 pSMB
->AndXCommand
= 0xFF;
529 rc
= SendReceive(xid
, ses
, (struct smb_hdr
*) pSMB
,
530 smb_buffer_response
, &length
, 0);
532 atomic_dec(&ses
->server
->socketUseCount
);
533 if (atomic_read(&ses
->server
->socketUseCount
) == 0) {
534 spin_lock(&GlobalMid_Lock
);
535 ses
->server
->tcpStatus
= CifsExiting
;
536 spin_unlock(&GlobalMid_Lock
);
541 cifs_small_buf_release(pSMB
);
544 /* if session dead then we do not need to do ulogoff,
545 since server closed smb session, no sense reporting
553 CIFSSMBDelFile(const int xid
, struct cifsTconInfo
*tcon
, const char *fileName
,
554 const struct nls_table
*nls_codepage
, int remap
)
556 DELETE_FILE_REQ
*pSMB
= NULL
;
557 DELETE_FILE_RSP
*pSMBr
= NULL
;
563 rc
= smb_init(SMB_COM_DELETE
, 1, tcon
, (void **) &pSMB
,
568 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
570 cifsConvertToUCS((__le16
*) pSMB
->fileName
, fileName
,
571 PATH_MAX
, nls_codepage
, remap
);
572 name_len
++; /* trailing null */
574 } else { /* BB improve check for buffer overruns BB */
575 name_len
= strnlen(fileName
, PATH_MAX
);
576 name_len
++; /* trailing null */
577 strncpy(pSMB
->fileName
, fileName
, name_len
);
579 pSMB
->SearchAttributes
=
580 cpu_to_le16(ATTR_READONLY
| ATTR_HIDDEN
| ATTR_SYSTEM
);
581 pSMB
->BufferFormat
= 0x04;
582 pSMB
->hdr
.smb_buf_length
+= name_len
+ 1;
583 pSMB
->ByteCount
= cpu_to_le16(name_len
+ 1);
584 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
585 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
587 cFYI(1, ("Error in RMFile = %d", rc
));
589 #ifdef CONFIG_CIFS_STATS
591 atomic_inc(&tcon
->num_deletes
);
595 cifs_buf_release(pSMB
);
603 CIFSSMBRmDir(const int xid
, struct cifsTconInfo
*tcon
, const char *dirName
,
604 const struct nls_table
*nls_codepage
, int remap
)
606 DELETE_DIRECTORY_REQ
*pSMB
= NULL
;
607 DELETE_DIRECTORY_RSP
*pSMBr
= NULL
;
612 cFYI(1, ("In CIFSSMBRmDir"));
614 rc
= smb_init(SMB_COM_DELETE_DIRECTORY
, 0, tcon
, (void **) &pSMB
,
619 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
620 name_len
= cifsConvertToUCS((__le16
*) pSMB
->DirName
, dirName
,
621 PATH_MAX
, nls_codepage
, remap
);
622 name_len
++; /* trailing null */
624 } else { /* BB improve check for buffer overruns BB */
625 name_len
= strnlen(dirName
, PATH_MAX
);
626 name_len
++; /* trailing null */
627 strncpy(pSMB
->DirName
, dirName
, name_len
);
630 pSMB
->BufferFormat
= 0x04;
631 pSMB
->hdr
.smb_buf_length
+= name_len
+ 1;
632 pSMB
->ByteCount
= cpu_to_le16(name_len
+ 1);
633 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
634 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
636 cFYI(1, ("Error in RMDir = %d", rc
));
638 #ifdef CONFIG_CIFS_STATS
640 atomic_inc(&tcon
->num_rmdirs
);
644 cifs_buf_release(pSMB
);
651 CIFSSMBMkDir(const int xid
, struct cifsTconInfo
*tcon
,
652 const char *name
, const struct nls_table
*nls_codepage
, int remap
)
655 CREATE_DIRECTORY_REQ
*pSMB
= NULL
;
656 CREATE_DIRECTORY_RSP
*pSMBr
= NULL
;
660 cFYI(1, ("In CIFSSMBMkDir"));
662 rc
= smb_init(SMB_COM_CREATE_DIRECTORY
, 0, tcon
, (void **) &pSMB
,
667 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
668 name_len
= cifsConvertToUCS((__le16
*) pSMB
->DirName
, name
,
669 PATH_MAX
, nls_codepage
, remap
);
670 name_len
++; /* trailing null */
672 } else { /* BB improve check for buffer overruns BB */
673 name_len
= strnlen(name
, PATH_MAX
);
674 name_len
++; /* trailing null */
675 strncpy(pSMB
->DirName
, name
, name_len
);
678 pSMB
->BufferFormat
= 0x04;
679 pSMB
->hdr
.smb_buf_length
+= name_len
+ 1;
680 pSMB
->ByteCount
= cpu_to_le16(name_len
+ 1);
681 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
682 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
684 cFYI(1, ("Error in Mkdir = %d", rc
));
686 #ifdef CONFIG_CIFS_STATS
688 atomic_inc(&tcon
->num_mkdirs
);
691 cifs_buf_release(pSMB
);
698 CIFSSMBOpen(const int xid
, struct cifsTconInfo
*tcon
,
699 const char *fileName
, const int openDisposition
,
700 const int access_flags
, const int create_options
, __u16
* netfid
,
701 int *pOplock
, FILE_ALL_INFO
* pfile_info
,
702 const struct nls_table
*nls_codepage
, int remap
)
705 OPEN_REQ
*pSMB
= NULL
;
706 OPEN_RSP
*pSMBr
= NULL
;
712 rc
= smb_init(SMB_COM_NT_CREATE_ANDX
, 24, tcon
, (void **) &pSMB
,
717 pSMB
->AndXCommand
= 0xFF; /* none */
719 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
720 count
= 1; /* account for one byte pad to word boundary */
722 cifsConvertToUCS((__le16
*) (pSMB
->fileName
+ 1),
723 fileName
, PATH_MAX
, nls_codepage
, remap
);
724 name_len
++; /* trailing null */
726 pSMB
->NameLength
= cpu_to_le16(name_len
);
727 } else { /* BB improve check for buffer overruns BB */
728 count
= 0; /* no pad */
729 name_len
= strnlen(fileName
, PATH_MAX
);
730 name_len
++; /* trailing null */
731 pSMB
->NameLength
= cpu_to_le16(name_len
);
732 strncpy(pSMB
->fileName
, fileName
, name_len
);
734 if (*pOplock
& REQ_OPLOCK
)
735 pSMB
->OpenFlags
= cpu_to_le32(REQ_OPLOCK
);
736 else if (*pOplock
& REQ_BATCHOPLOCK
) {
737 pSMB
->OpenFlags
= cpu_to_le32(REQ_BATCHOPLOCK
);
739 pSMB
->DesiredAccess
= cpu_to_le32(access_flags
);
740 pSMB
->AllocationSize
= 0;
741 /* set file as system file if special file such
742 as fifo and server expecting SFU style and
743 no Unix extensions */
744 if(create_options
& CREATE_OPTION_SPECIAL
)
745 pSMB
->FileAttributes
= cpu_to_le32(ATTR_SYSTEM
);
747 pSMB
->FileAttributes
= cpu_to_le32(ATTR_NORMAL
);
748 /* XP does not handle ATTR_POSIX_SEMANTICS */
749 /* but it helps speed up case sensitive checks for other
750 servers such as Samba */
751 if (tcon
->ses
->capabilities
& CAP_UNIX
)
752 pSMB
->FileAttributes
|= cpu_to_le32(ATTR_POSIX_SEMANTICS
);
754 /* if ((omode & S_IWUGO) == 0)
755 pSMB->FileAttributes |= cpu_to_le32(ATTR_READONLY);*/
756 /* Above line causes problems due to vfs splitting create into two
757 pieces - need to set mode after file created not while it is
759 pSMB
->ShareAccess
= cpu_to_le32(FILE_SHARE_ALL
);
760 pSMB
->CreateDisposition
= cpu_to_le32(openDisposition
);
761 pSMB
->CreateOptions
= cpu_to_le32(create_options
& CREATE_OPTIONS_MASK
);
762 /* BB Expirement with various impersonation levels and verify */
763 pSMB
->ImpersonationLevel
= cpu_to_le32(SECURITY_IMPERSONATION
);
764 pSMB
->SecurityFlags
=
765 SECURITY_CONTEXT_TRACKING
| SECURITY_EFFECTIVE_ONLY
;
768 pSMB
->hdr
.smb_buf_length
+= count
;
770 pSMB
->ByteCount
= cpu_to_le16(count
);
771 /* long_op set to 1 to allow for oplock break timeouts */
772 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
773 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 1);
775 cFYI(1, ("Error in Open = %d", rc
));
777 *pOplock
= pSMBr
->OplockLevel
; /* 1 byte no need to le_to_cpu */
778 *netfid
= pSMBr
->Fid
; /* cifs fid stays in le */
779 /* Let caller know file was created so we can set the mode. */
780 /* Do we care about the CreateAction in any other cases? */
781 if(cpu_to_le32(FILE_CREATE
) == pSMBr
->CreateAction
)
782 *pOplock
|= CIFS_CREATE_ACTION
;
784 memcpy((char *)pfile_info
,(char *)&pSMBr
->CreationTime
,
785 36 /* CreationTime to Attributes */);
786 /* the file_info buf is endian converted by caller */
787 pfile_info
->AllocationSize
= pSMBr
->AllocationSize
;
788 pfile_info
->EndOfFile
= pSMBr
->EndOfFile
;
789 pfile_info
->NumberOfLinks
= cpu_to_le32(1);
792 #ifdef CONFIG_CIFS_STATS
793 atomic_inc(&tcon
->num_opens
);
796 cifs_buf_release(pSMB
);
802 /* If no buffer passed in, then caller wants to do the copy
803 as in the case of readpages so the SMB buffer must be
804 freed by the caller */
807 CIFSSMBRead(const int xid
, struct cifsTconInfo
*tcon
,
808 const int netfid
, const unsigned int count
,
809 const __u64 lseek
, unsigned int *nbytes
, char **buf
)
812 READ_REQ
*pSMB
= NULL
;
813 READ_RSP
*pSMBr
= NULL
;
814 char *pReadData
= NULL
;
817 cFYI(1,("Reading %d bytes on fid %d",count
,netfid
));
820 rc
= smb_init(SMB_COM_READ_ANDX
, 12, tcon
, (void **) &pSMB
,
825 /* tcon and ses pointer are checked in smb_init */
826 if (tcon
->ses
->server
== NULL
)
827 return -ECONNABORTED
;
829 pSMB
->AndXCommand
= 0xFF; /* none */
831 pSMB
->OffsetLow
= cpu_to_le32(lseek
& 0xFFFFFFFF);
832 pSMB
->OffsetHigh
= cpu_to_le32(lseek
>> 32);
834 pSMB
->MaxCount
= cpu_to_le16(count
& 0xFFFF);
835 pSMB
->MaxCountHigh
= cpu_to_le32(count
>> 16);
836 pSMB
->ByteCount
= 0; /* no need to do le conversion since it is 0 */
838 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
839 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
841 cERROR(1, ("Send error in read = %d", rc
));
843 int data_length
= le16_to_cpu(pSMBr
->DataLengthHigh
);
844 data_length
= data_length
<< 16;
845 data_length
+= le16_to_cpu(pSMBr
->DataLength
);
846 *nbytes
= data_length
;
848 /*check that DataLength would not go beyond end of SMB */
849 if ((data_length
> CIFSMaxBufSize
)
850 || (data_length
> count
)) {
851 cFYI(1,("bad length %d for count %d",data_length
,count
));
856 (char *) (&pSMBr
->hdr
.Protocol
) +
857 le16_to_cpu(pSMBr
->DataOffset
);
858 /* if(rc = copy_to_user(buf, pReadData, data_length)) {
859 cERROR(1,("Faulting on read rc = %d",rc));
861 }*/ /* can not use copy_to_user when using page cache*/
863 memcpy(*buf
,pReadData
,data_length
);
867 cifs_buf_release(pSMB
);
871 /* Note: On -EAGAIN error only caller can retry on handle based calls
872 since file handle passed in no longer valid */
877 CIFSSMBWrite(const int xid
, struct cifsTconInfo
*tcon
,
878 const int netfid
, const unsigned int count
,
879 const __u64 offset
, unsigned int *nbytes
, const char *buf
,
880 const char __user
* ubuf
, const int long_op
)
883 WRITE_REQ
*pSMB
= NULL
;
884 WRITE_RSP
*pSMBr
= NULL
;
889 /* cFYI(1,("write at %lld %d bytes",offset,count));*/
890 rc
= smb_init(SMB_COM_WRITE_ANDX
, 14, tcon
, (void **) &pSMB
,
894 /* tcon and ses pointer are checked in smb_init */
895 if (tcon
->ses
->server
== NULL
)
896 return -ECONNABORTED
;
898 pSMB
->AndXCommand
= 0xFF; /* none */
900 pSMB
->OffsetLow
= cpu_to_le32(offset
& 0xFFFFFFFF);
901 pSMB
->OffsetHigh
= cpu_to_le32(offset
>> 32);
902 pSMB
->Reserved
= 0xFFFFFFFF;
906 /* Can increase buffer size if buffer is big enough in some cases - ie we
907 can send more if LARGE_WRITE_X capability returned by the server and if
908 our buffer is big enough or if we convert to iovecs on socket writes
909 and eliminate the copy to the CIFS buffer */
910 if(tcon
->ses
->capabilities
& CAP_LARGE_WRITE_X
) {
911 bytes_sent
= min_t(const unsigned int, CIFSMaxBufSize
, count
);
913 bytes_sent
= (tcon
->ses
->server
->maxBuf
- MAX_CIFS_HDR_SIZE
)
917 if (bytes_sent
> count
)
920 cpu_to_le16(offsetof(struct smb_com_write_req
,Data
) - 4);
922 memcpy(pSMB
->Data
,buf
,bytes_sent
);
924 if(copy_from_user(pSMB
->Data
,ubuf
,bytes_sent
)) {
925 cifs_buf_release(pSMB
);
930 cifs_buf_release(pSMB
);
934 byte_count
= bytes_sent
+ 1 /* pad */ ; /* BB fix this for sends > 64K */
935 pSMB
->DataLengthLow
= cpu_to_le16(bytes_sent
& 0xFFFF);
936 pSMB
->DataLengthHigh
= cpu_to_le16(bytes_sent
>> 16);
937 pSMB
->hdr
.smb_buf_length
+= bytes_sent
+1;
938 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
940 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
941 (struct smb_hdr
*) pSMBr
, &bytes_returned
, long_op
);
943 cFYI(1, ("Send error in write = %d", rc
));
946 *nbytes
= le16_to_cpu(pSMBr
->CountHigh
);
947 *nbytes
= (*nbytes
) << 16;
948 *nbytes
+= le16_to_cpu(pSMBr
->Count
);
951 cifs_buf_release(pSMB
);
953 /* Note: On -EAGAIN error only caller can retry on handle based calls
954 since file handle passed in no longer valid */
959 #ifdef CONFIG_CIFS_EXPERIMENTAL
961 CIFSSMBWrite2(const int xid
, struct cifsTconInfo
*tcon
,
962 const int netfid
, const unsigned int count
,
963 const __u64 offset
, unsigned int *nbytes
, const char *buf
,
967 WRITE_REQ
*pSMB
= NULL
;
973 cFYI(1,("write2 at %lld %d bytes",offset
,count
)); /* BB removeme BB */
974 rc
= small_smb_init(SMB_COM_WRITE_ANDX
, 14, tcon
, (void **) &pSMB
);
977 /* tcon and ses pointer are checked in smb_init */
978 if (tcon
->ses
->server
== NULL
)
979 return -ECONNABORTED
;
981 pSMB
->AndXCommand
= 0xFF; /* none */
983 pSMB
->OffsetLow
= cpu_to_le32(offset
& 0xFFFFFFFF);
984 pSMB
->OffsetHigh
= cpu_to_le32(offset
>> 32);
985 pSMB
->Reserved
= 0xFFFFFFFF;
989 /* Can increase buffer size if buffer is big enough in some cases - ie
990 can send more if LARGE_WRITE_X capability returned by the server and if
991 our buffer is big enough or if we convert to iovecs on socket writes
992 and eliminate the copy to the CIFS buffer */
993 if(tcon
->ses
->capabilities
& CAP_LARGE_WRITE_X
) {
994 bytes_sent
= min_t(const unsigned int, CIFSMaxBufSize
, count
);
996 bytes_sent
= (tcon
->ses
->server
->maxBuf
- MAX_CIFS_HDR_SIZE
)
1000 if (bytes_sent
> count
)
1003 cpu_to_le16(offsetof(struct smb_com_write_req
,Data
) - 4);
1005 byte_count
= bytes_sent
+ 1 /* pad */ ; /* BB fix this for sends > 64K */
1006 pSMB
->DataLengthLow
= cpu_to_le16(bytes_sent
& 0xFFFF);
1007 pSMB
->DataLengthHigh
= cpu_to_le16(bytes_sent
>> 16);
1008 smb_hdr_len
= pSMB
->hdr
.smb_buf_length
+ 1; /* hdr + 1 byte pad */
1009 pSMB
->hdr
.smb_buf_length
+= bytes_sent
+1;
1010 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
1012 rc
= SendReceive2(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
, smb_hdr_len
,
1013 buf
, bytes_sent
, &bytes_returned
, long_op
);
1015 cFYI(1, ("Send error in write = %d", rc
));
1018 WRITE_RSP
* pSMBr
= (WRITE_RSP
*)pSMB
;
1019 *nbytes
= le16_to_cpu(pSMBr
->CountHigh
);
1020 *nbytes
= (*nbytes
) << 16;
1021 *nbytes
+= le16_to_cpu(pSMBr
->Count
);
1024 cifs_small_buf_release(pSMB
);
1026 /* Note: On -EAGAIN error only caller can retry on handle based calls
1027 since file handle passed in no longer valid */
1033 #endif /* CIFS_EXPERIMENTAL */
1036 CIFSSMBLock(const int xid
, struct cifsTconInfo
*tcon
,
1037 const __u16 smb_file_id
, const __u64 len
,
1038 const __u64 offset
, const __u32 numUnlock
,
1039 const __u32 numLock
, const __u8 lockType
, const int waitFlag
)
1042 LOCK_REQ
*pSMB
= NULL
;
1043 LOCK_RSP
*pSMBr
= NULL
;
1048 cFYI(1, ("In CIFSSMBLock - timeout %d numLock %d",waitFlag
,numLock
));
1049 rc
= small_smb_init(SMB_COM_LOCKING_ANDX
, 8, tcon
, (void **) &pSMB
);
1054 pSMBr
= (LOCK_RSP
*)pSMB
; /* BB removeme BB */
1056 if(lockType
== LOCKING_ANDX_OPLOCK_RELEASE
) {
1057 timeout
= -1; /* no response expected */
1059 } else if (waitFlag
== TRUE
) {
1060 timeout
= 3; /* blocking operation, no timeout */
1061 pSMB
->Timeout
= cpu_to_le32(-1);/* blocking - do not time out */
1066 pSMB
->NumberOfLocks
= cpu_to_le16(numLock
);
1067 pSMB
->NumberOfUnlocks
= cpu_to_le16(numUnlock
);
1068 pSMB
->LockType
= lockType
;
1069 pSMB
->AndXCommand
= 0xFF; /* none */
1070 pSMB
->Fid
= smb_file_id
; /* netfid stays le */
1072 if((numLock
!= 0) || (numUnlock
!= 0)) {
1073 pSMB
->Locks
[0].Pid
= cpu_to_le16(current
->tgid
);
1074 /* BB where to store pid high? */
1075 pSMB
->Locks
[0].LengthLow
= cpu_to_le32((u32
)len
);
1076 pSMB
->Locks
[0].LengthHigh
= cpu_to_le32((u32
)(len
>>32));
1077 pSMB
->Locks
[0].OffsetLow
= cpu_to_le32((u32
)offset
);
1078 pSMB
->Locks
[0].OffsetHigh
= cpu_to_le32((u32
)(offset
>>32));
1079 count
= sizeof(LOCKING_ANDX_RANGE
);
1084 pSMB
->hdr
.smb_buf_length
+= count
;
1085 pSMB
->ByteCount
= cpu_to_le16(count
);
1087 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
1088 (struct smb_hdr
*) pSMBr
, &bytes_returned
, timeout
);
1091 cFYI(1, ("Send error in Lock = %d", rc
));
1093 cifs_small_buf_release(pSMB
);
1095 /* Note: On -EAGAIN error only caller can retry on handle based calls
1096 since file handle passed in no longer valid */
1101 CIFSSMBClose(const int xid
, struct cifsTconInfo
*tcon
, int smb_file_id
)
1104 CLOSE_REQ
*pSMB
= NULL
;
1105 CLOSE_RSP
*pSMBr
= NULL
;
1107 cFYI(1, ("In CIFSSMBClose"));
1109 /* do not retry on dead session on close */
1110 rc
= small_smb_init(SMB_COM_CLOSE
, 3, tcon
, (void **) &pSMB
);
1116 pSMBr
= (CLOSE_RSP
*)pSMB
; /* BB removeme BB */
1118 pSMB
->FileID
= (__u16
) smb_file_id
;
1119 pSMB
->LastWriteTime
= 0;
1120 pSMB
->ByteCount
= 0;
1121 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
1122 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
1125 /* EINTR is expected when user ctl-c to kill app */
1126 cERROR(1, ("Send error in Close = %d", rc
));
1130 cifs_small_buf_release(pSMB
);
1132 /* Since session is dead, file will be closed on server already */
1140 CIFSSMBRename(const int xid
, struct cifsTconInfo
*tcon
,
1141 const char *fromName
, const char *toName
,
1142 const struct nls_table
*nls_codepage
, int remap
)
1145 RENAME_REQ
*pSMB
= NULL
;
1146 RENAME_RSP
*pSMBr
= NULL
;
1148 int name_len
, name_len2
;
1151 cFYI(1, ("In CIFSSMBRename"));
1153 rc
= smb_init(SMB_COM_RENAME
, 1, tcon
, (void **) &pSMB
,
1158 pSMB
->BufferFormat
= 0x04;
1159 pSMB
->SearchAttributes
=
1160 cpu_to_le16(ATTR_READONLY
| ATTR_HIDDEN
| ATTR_SYSTEM
|
1163 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
1165 cifsConvertToUCS((__le16
*) pSMB
->OldFileName
, fromName
,
1166 PATH_MAX
, nls_codepage
, remap
);
1167 name_len
++; /* trailing null */
1169 pSMB
->OldFileName
[name_len
] = 0x04; /* pad */
1170 /* protocol requires ASCII signature byte on Unicode string */
1171 pSMB
->OldFileName
[name_len
+ 1] = 0x00;
1173 cifsConvertToUCS((__le16
*) &pSMB
->OldFileName
[name_len
+ 2],
1174 toName
, PATH_MAX
, nls_codepage
, remap
);
1175 name_len2
+= 1 /* trailing null */ + 1 /* Signature word */ ;
1176 name_len2
*= 2; /* convert to bytes */
1177 } else { /* BB improve the check for buffer overruns BB */
1178 name_len
= strnlen(fromName
, PATH_MAX
);
1179 name_len
++; /* trailing null */
1180 strncpy(pSMB
->OldFileName
, fromName
, name_len
);
1181 name_len2
= strnlen(toName
, PATH_MAX
);
1182 name_len2
++; /* trailing null */
1183 pSMB
->OldFileName
[name_len
] = 0x04; /* 2nd buffer format */
1184 strncpy(&pSMB
->OldFileName
[name_len
+ 1], toName
, name_len2
);
1185 name_len2
++; /* trailing null */
1186 name_len2
++; /* signature byte */
1189 count
= 1 /* 1st signature byte */ + name_len
+ name_len2
;
1190 pSMB
->hdr
.smb_buf_length
+= count
;
1191 pSMB
->ByteCount
= cpu_to_le16(count
);
1193 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
1194 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
1196 cFYI(1, ("Send error in rename = %d", rc
));
1199 #ifdef CONFIG_CIFS_STATS
1201 atomic_inc(&tcon
->num_renames
);
1205 cifs_buf_release(pSMB
);
1213 int CIFSSMBRenameOpenFile(const int xid
,struct cifsTconInfo
*pTcon
,
1214 int netfid
, char * target_name
,
1215 const struct nls_table
* nls_codepage
, int remap
)
1217 struct smb_com_transaction2_sfi_req
*pSMB
= NULL
;
1218 struct smb_com_transaction2_sfi_rsp
*pSMBr
= NULL
;
1219 struct set_file_rename
* rename_info
;
1221 char dummy_string
[30];
1223 int bytes_returned
= 0;
1225 __u16 params
, param_offset
, offset
, count
, byte_count
;
1227 cFYI(1, ("Rename to File by handle"));
1228 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, pTcon
, (void **) &pSMB
,
1234 pSMB
->MaxSetupCount
= 0;
1238 pSMB
->Reserved2
= 0;
1239 param_offset
= offsetof(struct smb_com_transaction2_sfi_req
, Fid
) - 4;
1240 offset
= param_offset
+ params
;
1242 data_offset
= (char *) (&pSMB
->hdr
.Protocol
) + offset
;
1243 rename_info
= (struct set_file_rename
*) data_offset
;
1244 pSMB
->MaxParameterCount
= cpu_to_le16(2);
1245 pSMB
->MaxDataCount
= cpu_to_le16(1000); /* BB find max SMB PDU from sess */
1246 pSMB
->SetupCount
= 1;
1247 pSMB
->Reserved3
= 0;
1248 pSMB
->SubCommand
= cpu_to_le16(TRANS2_SET_FILE_INFORMATION
);
1249 byte_count
= 3 /* pad */ + params
;
1250 pSMB
->ParameterCount
= cpu_to_le16(params
);
1251 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
1252 pSMB
->ParameterOffset
= cpu_to_le16(param_offset
);
1253 pSMB
->DataOffset
= cpu_to_le16(offset
);
1254 /* construct random name ".cifs_tmp<inodenum><mid>" */
1255 rename_info
->overwrite
= cpu_to_le32(1);
1256 rename_info
->root_fid
= 0;
1257 /* unicode only call */
1258 if(target_name
== NULL
) {
1259 sprintf(dummy_string
,"cifs%x",pSMB
->hdr
.Mid
);
1260 len_of_str
= cifsConvertToUCS((__le16
*)rename_info
->target_name
,
1261 dummy_string
, 24, nls_codepage
, remap
);
1263 len_of_str
= cifsConvertToUCS((__le16
*)rename_info
->target_name
,
1264 target_name
, PATH_MAX
, nls_codepage
, remap
);
1266 rename_info
->target_name_len
= cpu_to_le32(2 * len_of_str
);
1267 count
= 12 /* sizeof(struct set_file_rename) */ + (2 * len_of_str
) + 2;
1268 byte_count
+= count
;
1269 pSMB
->DataCount
= cpu_to_le16(count
);
1270 pSMB
->TotalDataCount
= pSMB
->DataCount
;
1272 pSMB
->InformationLevel
=
1273 cpu_to_le16(SMB_SET_FILE_RENAME_INFORMATION
);
1274 pSMB
->Reserved4
= 0;
1275 pSMB
->hdr
.smb_buf_length
+= byte_count
;
1276 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
1277 rc
= SendReceive(xid
, pTcon
->ses
, (struct smb_hdr
*) pSMB
,
1278 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
1280 cFYI(1,("Send error in Rename (by file handle) = %d", rc
));
1282 #ifdef CONFIG_CIFS_STATS
1284 atomic_inc(&pTcon
->num_t2renames
);
1287 cifs_buf_release(pSMB
);
1289 /* Note: On -EAGAIN error only caller can retry on handle based calls
1290 since file handle passed in no longer valid */
1296 CIFSSMBCopy(const int xid
, struct cifsTconInfo
*tcon
, const char * fromName
,
1297 const __u16 target_tid
, const char *toName
, const int flags
,
1298 const struct nls_table
*nls_codepage
, int remap
)
1301 COPY_REQ
*pSMB
= NULL
;
1302 COPY_RSP
*pSMBr
= NULL
;
1304 int name_len
, name_len2
;
1307 cFYI(1, ("In CIFSSMBCopy"));
1309 rc
= smb_init(SMB_COM_COPY
, 1, tcon
, (void **) &pSMB
,
1314 pSMB
->BufferFormat
= 0x04;
1315 pSMB
->Tid2
= target_tid
;
1317 pSMB
->Flags
= cpu_to_le16(flags
& COPY_TREE
);
1319 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
1320 name_len
= cifsConvertToUCS((__le16
*) pSMB
->OldFileName
,
1321 fromName
, PATH_MAX
, nls_codepage
,
1323 name_len
++; /* trailing null */
1325 pSMB
->OldFileName
[name_len
] = 0x04; /* pad */
1326 /* protocol requires ASCII signature byte on Unicode string */
1327 pSMB
->OldFileName
[name_len
+ 1] = 0x00;
1328 name_len2
= cifsConvertToUCS((__le16
*)&pSMB
->OldFileName
[name_len
+ 2],
1329 toName
, PATH_MAX
, nls_codepage
, remap
);
1330 name_len2
+= 1 /* trailing null */ + 1 /* Signature word */ ;
1331 name_len2
*= 2; /* convert to bytes */
1332 } else { /* BB improve the check for buffer overruns BB */
1333 name_len
= strnlen(fromName
, PATH_MAX
);
1334 name_len
++; /* trailing null */
1335 strncpy(pSMB
->OldFileName
, fromName
, name_len
);
1336 name_len2
= strnlen(toName
, PATH_MAX
);
1337 name_len2
++; /* trailing null */
1338 pSMB
->OldFileName
[name_len
] = 0x04; /* 2nd buffer format */
1339 strncpy(&pSMB
->OldFileName
[name_len
+ 1], toName
, name_len2
);
1340 name_len2
++; /* trailing null */
1341 name_len2
++; /* signature byte */
1344 count
= 1 /* 1st signature byte */ + name_len
+ name_len2
;
1345 pSMB
->hdr
.smb_buf_length
+= count
;
1346 pSMB
->ByteCount
= cpu_to_le16(count
);
1348 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
1349 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
1351 cFYI(1, ("Send error in copy = %d with %d files copied",
1352 rc
, le16_to_cpu(pSMBr
->CopyCount
)));
1355 cifs_buf_release(pSMB
);
1364 CIFSUnixCreateSymLink(const int xid
, struct cifsTconInfo
*tcon
,
1365 const char *fromName
, const char *toName
,
1366 const struct nls_table
*nls_codepage
)
1368 TRANSACTION2_SPI_REQ
*pSMB
= NULL
;
1369 TRANSACTION2_SPI_RSP
*pSMBr
= NULL
;
1372 int name_len_target
;
1374 int bytes_returned
= 0;
1375 __u16 params
, param_offset
, offset
, byte_count
;
1377 cFYI(1, ("In Symlink Unix style"));
1379 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
1384 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
1386 cifs_strtoUCS((wchar_t *) pSMB
->FileName
, fromName
, PATH_MAX
1387 /* find define for this maxpathcomponent */
1389 name_len
++; /* trailing null */
1392 } else { /* BB improve the check for buffer overruns BB */
1393 name_len
= strnlen(fromName
, PATH_MAX
);
1394 name_len
++; /* trailing null */
1395 strncpy(pSMB
->FileName
, fromName
, name_len
);
1397 params
= 6 + name_len
;
1398 pSMB
->MaxSetupCount
= 0;
1402 pSMB
->Reserved2
= 0;
1403 param_offset
= offsetof(struct smb_com_transaction2_spi_req
,
1404 InformationLevel
) - 4;
1405 offset
= param_offset
+ params
;
1407 data_offset
= (char *) (&pSMB
->hdr
.Protocol
) + offset
;
1408 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
1410 cifs_strtoUCS((wchar_t *) data_offset
, toName
, PATH_MAX
1411 /* find define for this maxpathcomponent */
1413 name_len_target
++; /* trailing null */
1414 name_len_target
*= 2;
1415 } else { /* BB improve the check for buffer overruns BB */
1416 name_len_target
= strnlen(toName
, PATH_MAX
);
1417 name_len_target
++; /* trailing null */
1418 strncpy(data_offset
, toName
, name_len_target
);
1421 pSMB
->MaxParameterCount
= cpu_to_le16(2);
1422 /* BB find exact max on data count below from sess */
1423 pSMB
->MaxDataCount
= cpu_to_le16(1000);
1424 pSMB
->SetupCount
= 1;
1425 pSMB
->Reserved3
= 0;
1426 pSMB
->SubCommand
= cpu_to_le16(TRANS2_SET_PATH_INFORMATION
);
1427 byte_count
= 3 /* pad */ + params
+ name_len_target
;
1428 pSMB
->DataCount
= cpu_to_le16(name_len_target
);
1429 pSMB
->ParameterCount
= cpu_to_le16(params
);
1430 pSMB
->TotalDataCount
= pSMB
->DataCount
;
1431 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
1432 pSMB
->ParameterOffset
= cpu_to_le16(param_offset
);
1433 pSMB
->DataOffset
= cpu_to_le16(offset
);
1434 pSMB
->InformationLevel
= cpu_to_le16(SMB_SET_FILE_UNIX_LINK
);
1435 pSMB
->Reserved4
= 0;
1436 pSMB
->hdr
.smb_buf_length
+= byte_count
;
1437 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
1438 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
1439 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
1442 ("Send error in SetPathInfo (create symlink) = %d",
1447 cifs_buf_release(pSMB
);
1450 goto createSymLinkRetry
;
1456 CIFSUnixCreateHardLink(const int xid
, struct cifsTconInfo
*tcon
,
1457 const char *fromName
, const char *toName
,
1458 const struct nls_table
*nls_codepage
, int remap
)
1460 TRANSACTION2_SPI_REQ
*pSMB
= NULL
;
1461 TRANSACTION2_SPI_RSP
*pSMBr
= NULL
;
1464 int name_len_target
;
1466 int bytes_returned
= 0;
1467 __u16 params
, param_offset
, offset
, byte_count
;
1469 cFYI(1, ("In Create Hard link Unix style"));
1470 createHardLinkRetry
:
1471 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
1476 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
1477 name_len
= cifsConvertToUCS((__le16
*) pSMB
->FileName
, toName
,
1478 PATH_MAX
, nls_codepage
, remap
);
1479 name_len
++; /* trailing null */
1482 } else { /* BB improve the check for buffer overruns BB */
1483 name_len
= strnlen(toName
, PATH_MAX
);
1484 name_len
++; /* trailing null */
1485 strncpy(pSMB
->FileName
, toName
, name_len
);
1487 params
= 6 + name_len
;
1488 pSMB
->MaxSetupCount
= 0;
1492 pSMB
->Reserved2
= 0;
1493 param_offset
= offsetof(struct smb_com_transaction2_spi_req
,
1494 InformationLevel
) - 4;
1495 offset
= param_offset
+ params
;
1497 data_offset
= (char *) (&pSMB
->hdr
.Protocol
) + offset
;
1498 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
1500 cifsConvertToUCS((__le16
*) data_offset
, fromName
, PATH_MAX
,
1501 nls_codepage
, remap
);
1502 name_len_target
++; /* trailing null */
1503 name_len_target
*= 2;
1504 } else { /* BB improve the check for buffer overruns BB */
1505 name_len_target
= strnlen(fromName
, PATH_MAX
);
1506 name_len_target
++; /* trailing null */
1507 strncpy(data_offset
, fromName
, name_len_target
);
1510 pSMB
->MaxParameterCount
= cpu_to_le16(2);
1511 /* BB find exact max on data count below from sess*/
1512 pSMB
->MaxDataCount
= cpu_to_le16(1000);
1513 pSMB
->SetupCount
= 1;
1514 pSMB
->Reserved3
= 0;
1515 pSMB
->SubCommand
= cpu_to_le16(TRANS2_SET_PATH_INFORMATION
);
1516 byte_count
= 3 /* pad */ + params
+ name_len_target
;
1517 pSMB
->ParameterCount
= cpu_to_le16(params
);
1518 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
1519 pSMB
->DataCount
= cpu_to_le16(name_len_target
);
1520 pSMB
->TotalDataCount
= pSMB
->DataCount
;
1521 pSMB
->ParameterOffset
= cpu_to_le16(param_offset
);
1522 pSMB
->DataOffset
= cpu_to_le16(offset
);
1523 pSMB
->InformationLevel
= cpu_to_le16(SMB_SET_FILE_UNIX_HLINK
);
1524 pSMB
->Reserved4
= 0;
1525 pSMB
->hdr
.smb_buf_length
+= byte_count
;
1526 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
1527 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
1528 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
1530 cFYI(1, ("Send error in SetPathInfo (hard link) = %d", rc
));
1533 cifs_buf_release(pSMB
);
1535 goto createHardLinkRetry
;
1541 CIFSCreateHardLink(const int xid
, struct cifsTconInfo
*tcon
,
1542 const char *fromName
, const char *toName
,
1543 const struct nls_table
*nls_codepage
, int remap
)
1546 NT_RENAME_REQ
*pSMB
= NULL
;
1547 RENAME_RSP
*pSMBr
= NULL
;
1549 int name_len
, name_len2
;
1552 cFYI(1, ("In CIFSCreateHardLink"));
1553 winCreateHardLinkRetry
:
1555 rc
= smb_init(SMB_COM_NT_RENAME
, 4, tcon
, (void **) &pSMB
,
1560 pSMB
->SearchAttributes
=
1561 cpu_to_le16(ATTR_READONLY
| ATTR_HIDDEN
| ATTR_SYSTEM
|
1563 pSMB
->Flags
= cpu_to_le16(CREATE_HARD_LINK
);
1564 pSMB
->ClusterCount
= 0;
1566 pSMB
->BufferFormat
= 0x04;
1568 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
1570 cifsConvertToUCS((__le16
*) pSMB
->OldFileName
, fromName
,
1571 PATH_MAX
, nls_codepage
, remap
);
1572 name_len
++; /* trailing null */
1574 pSMB
->OldFileName
[name_len
] = 0; /* pad */
1575 pSMB
->OldFileName
[name_len
+ 1] = 0x04;
1577 cifsConvertToUCS((__le16
*)&pSMB
->OldFileName
[name_len
+ 2],
1578 toName
, PATH_MAX
, nls_codepage
, remap
);
1579 name_len2
+= 1 /* trailing null */ + 1 /* Signature word */ ;
1580 name_len2
*= 2; /* convert to bytes */
1581 } else { /* BB improve the check for buffer overruns BB */
1582 name_len
= strnlen(fromName
, PATH_MAX
);
1583 name_len
++; /* trailing null */
1584 strncpy(pSMB
->OldFileName
, fromName
, name_len
);
1585 name_len2
= strnlen(toName
, PATH_MAX
);
1586 name_len2
++; /* trailing null */
1587 pSMB
->OldFileName
[name_len
] = 0x04; /* 2nd buffer format */
1588 strncpy(&pSMB
->OldFileName
[name_len
+ 1], toName
, name_len2
);
1589 name_len2
++; /* trailing null */
1590 name_len2
++; /* signature byte */
1593 count
= 1 /* string type byte */ + name_len
+ name_len2
;
1594 pSMB
->hdr
.smb_buf_length
+= count
;
1595 pSMB
->ByteCount
= cpu_to_le16(count
);
1597 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
1598 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
1600 cFYI(1, ("Send error in hard link (NT rename) = %d", rc
));
1602 cifs_buf_release(pSMB
);
1604 goto winCreateHardLinkRetry
;
1610 CIFSSMBUnixQuerySymLink(const int xid
, struct cifsTconInfo
*tcon
,
1611 const unsigned char *searchName
,
1612 char *symlinkinfo
, const int buflen
,
1613 const struct nls_table
*nls_codepage
)
1615 /* SMB_QUERY_FILE_UNIX_LINK */
1616 TRANSACTION2_QPI_REQ
*pSMB
= NULL
;
1617 TRANSACTION2_QPI_RSP
*pSMBr
= NULL
;
1621 __u16 params
, byte_count
;
1623 cFYI(1, ("In QPathSymLinkInfo (Unix) for path %s", searchName
));
1626 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
1631 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
1633 cifs_strtoUCS((wchar_t *) pSMB
->FileName
, searchName
, PATH_MAX
1634 /* find define for this maxpathcomponent */
1636 name_len
++; /* trailing null */
1638 } else { /* BB improve the check for buffer overruns BB */
1639 name_len
= strnlen(searchName
, PATH_MAX
);
1640 name_len
++; /* trailing null */
1641 strncpy(pSMB
->FileName
, searchName
, name_len
);
1644 params
= 2 /* level */ + 4 /* rsrvd */ + name_len
/* incl null */ ;
1645 pSMB
->TotalDataCount
= 0;
1646 pSMB
->MaxParameterCount
= cpu_to_le16(2);
1647 /* BB find exact max data count below from sess structure BB */
1648 pSMB
->MaxDataCount
= cpu_to_le16(4000);
1649 pSMB
->MaxSetupCount
= 0;
1653 pSMB
->Reserved2
= 0;
1654 pSMB
->ParameterOffset
= cpu_to_le16(offsetof(
1655 struct smb_com_transaction2_qpi_req
,InformationLevel
) - 4);
1656 pSMB
->DataCount
= 0;
1657 pSMB
->DataOffset
= 0;
1658 pSMB
->SetupCount
= 1;
1659 pSMB
->Reserved3
= 0;
1660 pSMB
->SubCommand
= cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION
);
1661 byte_count
= params
+ 1 /* pad */ ;
1662 pSMB
->TotalParameterCount
= cpu_to_le16(params
);
1663 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
1664 pSMB
->InformationLevel
= cpu_to_le16(SMB_QUERY_FILE_UNIX_LINK
);
1665 pSMB
->Reserved4
= 0;
1666 pSMB
->hdr
.smb_buf_length
+= byte_count
;
1667 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
1669 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
1670 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
1672 cFYI(1, ("Send error in QuerySymLinkInfo = %d", rc
));
1674 /* decode response */
1676 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
1677 if (rc
|| (pSMBr
->ByteCount
< 2))
1678 /* BB also check enough total bytes returned */
1679 rc
= -EIO
; /* bad smb */
1681 __u16 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
1682 __u16 count
= le16_to_cpu(pSMBr
->t2
.DataCount
);
1684 if (pSMBr
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
1685 name_len
= UniStrnlen((wchar_t *) ((char *)
1686 &pSMBr
->hdr
.Protocol
+data_offset
),
1687 min_t(const int, buflen
,count
) / 2);
1688 /* BB FIXME investigate remapping reserved chars here */
1689 cifs_strfromUCS_le(symlinkinfo
,
1690 (wchar_t *) ((char *)&pSMBr
->hdr
.Protocol
+
1692 name_len
, nls_codepage
);
1694 strncpy(symlinkinfo
,
1695 (char *) &pSMBr
->hdr
.Protocol
+
1697 min_t(const int, buflen
, count
));
1699 symlinkinfo
[buflen
] = 0;
1700 /* just in case so calling code does not go off the end of buffer */
1703 cifs_buf_release(pSMB
);
1705 goto querySymLinkRetry
;
1710 CIFSSMBQueryReparseLinkInfo(const int xid
, struct cifsTconInfo
*tcon
,
1711 const unsigned char *searchName
,
1712 char *symlinkinfo
, const int buflen
,__u16 fid
,
1713 const struct nls_table
*nls_codepage
)
1718 struct smb_com_transaction_ioctl_req
* pSMB
;
1719 struct smb_com_transaction_ioctl_rsp
* pSMBr
;
1721 cFYI(1, ("In Windows reparse style QueryLink for path %s", searchName
));
1722 rc
= smb_init(SMB_COM_NT_TRANSACT
, 23, tcon
, (void **) &pSMB
,
1727 pSMB
->TotalParameterCount
= 0 ;
1728 pSMB
->TotalDataCount
= 0;
1729 pSMB
->MaxParameterCount
= cpu_to_le32(2);
1730 /* BB find exact data count max from sess structure BB */
1731 pSMB
->MaxDataCount
= cpu_to_le32(4000);
1732 pSMB
->MaxSetupCount
= 4;
1734 pSMB
->ParameterOffset
= 0;
1735 pSMB
->DataCount
= 0;
1736 pSMB
->DataOffset
= 0;
1737 pSMB
->SetupCount
= 4;
1738 pSMB
->SubCommand
= cpu_to_le16(NT_TRANSACT_IOCTL
);
1739 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
1740 pSMB
->FunctionCode
= cpu_to_le32(FSCTL_GET_REPARSE_POINT
);
1741 pSMB
->IsFsctl
= 1; /* FSCTL */
1742 pSMB
->IsRootFlag
= 0;
1743 pSMB
->Fid
= fid
; /* file handle always le */
1744 pSMB
->ByteCount
= 0;
1746 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
1747 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
1749 cFYI(1, ("Send error in QueryReparseLinkInfo = %d", rc
));
1750 } else { /* decode response */
1751 __u32 data_offset
= le32_to_cpu(pSMBr
->DataOffset
);
1752 __u32 data_count
= le32_to_cpu(pSMBr
->DataCount
);
1753 if ((pSMBr
->ByteCount
< 2) || (data_offset
> 512))
1754 /* BB also check enough total bytes returned */
1755 rc
= -EIO
; /* bad smb */
1757 if(data_count
&& (data_count
< 2048)) {
1758 char * end_of_smb
= pSMBr
->ByteCount
+ (char *)&pSMBr
->ByteCount
;
1760 struct reparse_data
* reparse_buf
= (struct reparse_data
*)
1761 ((char *)&pSMBr
->hdr
.Protocol
+ data_offset
);
1762 if((char*)reparse_buf
>= end_of_smb
) {
1766 if((reparse_buf
->LinkNamesBuf
+
1767 reparse_buf
->TargetNameOffset
+
1768 reparse_buf
->TargetNameLen
) >
1770 cFYI(1,("reparse buf extended beyond SMB"));
1775 if (pSMBr
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
1776 name_len
= UniStrnlen((wchar_t *)
1777 (reparse_buf
->LinkNamesBuf
+
1778 reparse_buf
->TargetNameOffset
),
1779 min(buflen
/2, reparse_buf
->TargetNameLen
/ 2));
1780 cifs_strfromUCS_le(symlinkinfo
,
1781 (wchar_t *) (reparse_buf
->LinkNamesBuf
+
1782 reparse_buf
->TargetNameOffset
),
1783 name_len
, nls_codepage
);
1784 } else { /* ASCII names */
1785 strncpy(symlinkinfo
,reparse_buf
->LinkNamesBuf
+
1786 reparse_buf
->TargetNameOffset
,
1787 min_t(const int, buflen
, reparse_buf
->TargetNameLen
));
1791 cFYI(1,("Invalid return data count on get reparse info ioctl"));
1793 symlinkinfo
[buflen
] = 0; /* just in case so the caller
1794 does not go off the end of the buffer */
1795 cFYI(1,("readlink result - %s ",symlinkinfo
));
1800 cifs_buf_release(pSMB
);
1802 /* Note: On -EAGAIN error only caller can retry on handle based calls
1803 since file handle passed in no longer valid */
1808 #ifdef CONFIG_CIFS_POSIX
1810 /*Convert an Access Control Entry from wire format to local POSIX xattr format*/
1811 static void cifs_convert_ace(posix_acl_xattr_entry
* ace
, struct cifs_posix_ace
* cifs_ace
)
1813 /* u8 cifs fields do not need le conversion */
1814 ace
->e_perm
= (__u16
)cifs_ace
->cifs_e_perm
;
1815 ace
->e_tag
= (__u16
)cifs_ace
->cifs_e_tag
;
1816 ace
->e_id
= (__u32
)le64_to_cpu(cifs_ace
->cifs_uid
);
1817 /* cFYI(1,("perm %d tag %d id %d",ace->e_perm,ace->e_tag,ace->e_id)); */
1822 /* Convert ACL from CIFS POSIX wire format to local Linux POSIX ACL xattr */
1823 static int cifs_copy_posix_acl(char * trgt
,char * src
, const int buflen
,
1824 const int acl_type
,const int size_of_data_area
)
1829 struct cifs_posix_ace
* pACE
;
1830 struct cifs_posix_acl
* cifs_acl
= (struct cifs_posix_acl
*)src
;
1831 posix_acl_xattr_header
* local_acl
= (posix_acl_xattr_header
*)trgt
;
1833 if (le16_to_cpu(cifs_acl
->version
) != CIFS_ACL_VERSION
)
1836 if(acl_type
& ACL_TYPE_ACCESS
) {
1837 count
= le16_to_cpu(cifs_acl
->access_entry_count
);
1838 pACE
= &cifs_acl
->ace_array
[0];
1839 size
= sizeof(struct cifs_posix_acl
);
1840 size
+= sizeof(struct cifs_posix_ace
) * count
;
1841 /* check if we would go beyond end of SMB */
1842 if(size_of_data_area
< size
) {
1843 cFYI(1,("bad CIFS POSIX ACL size %d vs. %d",size_of_data_area
,size
));
1846 } else if(acl_type
& ACL_TYPE_DEFAULT
) {
1847 count
= le16_to_cpu(cifs_acl
->access_entry_count
);
1848 size
= sizeof(struct cifs_posix_acl
);
1849 size
+= sizeof(struct cifs_posix_ace
) * count
;
1850 /* skip past access ACEs to get to default ACEs */
1851 pACE
= &cifs_acl
->ace_array
[count
];
1852 count
= le16_to_cpu(cifs_acl
->default_entry_count
);
1853 size
+= sizeof(struct cifs_posix_ace
) * count
;
1854 /* check if we would go beyond end of SMB */
1855 if(size_of_data_area
< size
)
1862 size
= posix_acl_xattr_size(count
);
1863 if((buflen
== 0) || (local_acl
== NULL
)) {
1864 /* used to query ACL EA size */
1865 } else if(size
> buflen
) {
1867 } else /* buffer big enough */ {
1868 local_acl
->a_version
= POSIX_ACL_XATTR_VERSION
;
1869 for(i
= 0;i
< count
;i
++) {
1870 cifs_convert_ace(&local_acl
->a_entries
[i
],pACE
);
1877 static __u16
convert_ace_to_cifs_ace(struct cifs_posix_ace
* cifs_ace
,
1878 const posix_acl_xattr_entry
* local_ace
)
1880 __u16 rc
= 0; /* 0 = ACL converted ok */
1882 cifs_ace
->cifs_e_perm
= (__u8
)cpu_to_le16(local_ace
->e_perm
);
1883 cifs_ace
->cifs_e_tag
= (__u8
)cpu_to_le16(local_ace
->e_tag
);
1884 /* BB is there a better way to handle the large uid? */
1885 if(local_ace
->e_id
== -1) {
1886 /* Probably no need to le convert -1 on any arch but can not hurt */
1887 cifs_ace
->cifs_uid
= cpu_to_le64(-1);
1889 cifs_ace
->cifs_uid
= (__u64
)cpu_to_le32(local_ace
->e_id
);
1890 /*cFYI(1,("perm %d tag %d id %d",ace->e_perm,ace->e_tag,ace->e_id));*/
1894 /* Convert ACL from local Linux POSIX xattr to CIFS POSIX ACL wire format */
1895 static __u16
ACL_to_cifs_posix(char * parm_data
,const char * pACL
,const int buflen
,
1899 struct cifs_posix_acl
* cifs_acl
= (struct cifs_posix_acl
*)parm_data
;
1900 posix_acl_xattr_header
* local_acl
= (posix_acl_xattr_header
*)pACL
;
1904 if((buflen
== 0) || (pACL
== NULL
) || (cifs_acl
== NULL
))
1907 count
= posix_acl_xattr_count((size_t)buflen
);
1908 cFYI(1,("setting acl with %d entries from buf of length %d and version of %d",
1909 count
,buflen
,local_acl
->a_version
));
1910 if(local_acl
->a_version
!= 2) {
1911 cFYI(1,("unknown POSIX ACL version %d",local_acl
->a_version
));
1914 cifs_acl
->version
= cpu_to_le16(1);
1915 if(acl_type
== ACL_TYPE_ACCESS
)
1916 cifs_acl
->access_entry_count
= count
;
1917 else if(acl_type
== ACL_TYPE_DEFAULT
)
1918 cifs_acl
->default_entry_count
= count
;
1920 cFYI(1,("unknown ACL type %d",acl_type
));
1923 for(i
=0;i
<count
;i
++) {
1924 rc
= convert_ace_to_cifs_ace(&cifs_acl
->ace_array
[i
],
1925 &local_acl
->a_entries
[i
]);
1927 /* ACE not converted */
1932 rc
= (__u16
)(count
* sizeof(struct cifs_posix_ace
));
1933 rc
+= sizeof(struct cifs_posix_acl
);
1934 /* BB add check to make sure ACL does not overflow SMB */
1940 CIFSSMBGetPosixACL(const int xid
, struct cifsTconInfo
*tcon
,
1941 const unsigned char *searchName
,
1942 char *acl_inf
, const int buflen
, const int acl_type
,
1943 const struct nls_table
*nls_codepage
, int remap
)
1945 /* SMB_QUERY_POSIX_ACL */
1946 TRANSACTION2_QPI_REQ
*pSMB
= NULL
;
1947 TRANSACTION2_QPI_RSP
*pSMBr
= NULL
;
1951 __u16 params
, byte_count
;
1953 cFYI(1, ("In GetPosixACL (Unix) for path %s", searchName
));
1956 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
1961 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
1963 cifsConvertToUCS((__le16
*) pSMB
->FileName
, searchName
,
1964 PATH_MAX
, nls_codepage
, remap
);
1965 name_len
++; /* trailing null */
1967 pSMB
->FileName
[name_len
] = 0;
1968 pSMB
->FileName
[name_len
+1] = 0;
1969 } else { /* BB improve the check for buffer overruns BB */
1970 name_len
= strnlen(searchName
, PATH_MAX
);
1971 name_len
++; /* trailing null */
1972 strncpy(pSMB
->FileName
, searchName
, name_len
);
1975 params
= 2 /* level */ + 4 /* rsrvd */ + name_len
/* incl null */ ;
1976 pSMB
->TotalDataCount
= 0;
1977 pSMB
->MaxParameterCount
= cpu_to_le16(2);
1978 /* BB find exact max data count below from sess structure BB */
1979 pSMB
->MaxDataCount
= cpu_to_le16(4000);
1980 pSMB
->MaxSetupCount
= 0;
1984 pSMB
->Reserved2
= 0;
1985 pSMB
->ParameterOffset
= cpu_to_le16(
1986 offsetof(struct smb_com_transaction2_qpi_req
,InformationLevel
) - 4);
1987 pSMB
->DataCount
= 0;
1988 pSMB
->DataOffset
= 0;
1989 pSMB
->SetupCount
= 1;
1990 pSMB
->Reserved3
= 0;
1991 pSMB
->SubCommand
= cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION
);
1992 byte_count
= params
+ 1 /* pad */ ;
1993 pSMB
->TotalParameterCount
= cpu_to_le16(params
);
1994 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
1995 pSMB
->InformationLevel
= cpu_to_le16(SMB_QUERY_POSIX_ACL
);
1996 pSMB
->Reserved4
= 0;
1997 pSMB
->hdr
.smb_buf_length
+= byte_count
;
1998 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
2000 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
2001 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
2003 cFYI(1, ("Send error in Query POSIX ACL = %d", rc
));
2005 /* decode response */
2007 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
2008 if (rc
|| (pSMBr
->ByteCount
< 2))
2009 /* BB also check enough total bytes returned */
2010 rc
= -EIO
; /* bad smb */
2012 __u16 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
2013 __u16 count
= le16_to_cpu(pSMBr
->t2
.DataCount
);
2014 rc
= cifs_copy_posix_acl(acl_inf
,
2015 (char *)&pSMBr
->hdr
.Protocol
+data_offset
,
2016 buflen
,acl_type
,count
);
2019 cifs_buf_release(pSMB
);
2026 CIFSSMBSetPosixACL(const int xid
, struct cifsTconInfo
*tcon
,
2027 const unsigned char *fileName
,
2028 const char *local_acl
, const int buflen
,
2030 const struct nls_table
*nls_codepage
, int remap
)
2032 struct smb_com_transaction2_spi_req
*pSMB
= NULL
;
2033 struct smb_com_transaction2_spi_rsp
*pSMBr
= NULL
;
2037 int bytes_returned
= 0;
2038 __u16 params
, byte_count
, data_count
, param_offset
, offset
;
2040 cFYI(1, ("In SetPosixACL (Unix) for path %s", fileName
));
2042 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
2046 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
2048 cifsConvertToUCS((__le16
*) pSMB
->FileName
, fileName
,
2049 PATH_MAX
, nls_codepage
, remap
);
2050 name_len
++; /* trailing null */
2052 } else { /* BB improve the check for buffer overruns BB */
2053 name_len
= strnlen(fileName
, PATH_MAX
);
2054 name_len
++; /* trailing null */
2055 strncpy(pSMB
->FileName
, fileName
, name_len
);
2057 params
= 6 + name_len
;
2058 pSMB
->MaxParameterCount
= cpu_to_le16(2);
2059 pSMB
->MaxDataCount
= cpu_to_le16(1000); /* BB find max SMB size from sess */
2060 pSMB
->MaxSetupCount
= 0;
2064 pSMB
->Reserved2
= 0;
2065 param_offset
= offsetof(struct smb_com_transaction2_spi_req
,
2066 InformationLevel
) - 4;
2067 offset
= param_offset
+ params
;
2068 parm_data
= ((char *) &pSMB
->hdr
.Protocol
) + offset
;
2069 pSMB
->ParameterOffset
= cpu_to_le16(param_offset
);
2071 /* convert to on the wire format for POSIX ACL */
2072 data_count
= ACL_to_cifs_posix(parm_data
,local_acl
,buflen
,acl_type
);
2074 if(data_count
== 0) {
2076 goto setACLerrorExit
;
2078 pSMB
->DataOffset
= cpu_to_le16(offset
);
2079 pSMB
->SetupCount
= 1;
2080 pSMB
->Reserved3
= 0;
2081 pSMB
->SubCommand
= cpu_to_le16(TRANS2_SET_PATH_INFORMATION
);
2082 pSMB
->InformationLevel
= cpu_to_le16(SMB_SET_POSIX_ACL
);
2083 byte_count
= 3 /* pad */ + params
+ data_count
;
2084 pSMB
->DataCount
= cpu_to_le16(data_count
);
2085 pSMB
->TotalDataCount
= pSMB
->DataCount
;
2086 pSMB
->ParameterCount
= cpu_to_le16(params
);
2087 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
2088 pSMB
->Reserved4
= 0;
2089 pSMB
->hdr
.smb_buf_length
+= byte_count
;
2090 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
2091 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
2092 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
2094 cFYI(1, ("Set POSIX ACL returned %d", rc
));
2098 cifs_buf_release(pSMB
);
2104 /* BB fix tabs in this function FIXME BB */
2106 CIFSGetExtAttr(const int xid
, struct cifsTconInfo
*tcon
,
2107 const int netfid
, __u64
* pExtAttrBits
, __u64
*pMask
)
2110 struct smb_t2_qfi_req
*pSMB
= NULL
;
2111 struct smb_t2_qfi_rsp
*pSMBr
= NULL
;
2113 __u16 params
, byte_count
;
2115 cFYI(1,("In GetExtAttr"));
2120 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
2125 params
= 2 /* level */ +2 /* fid */;
2126 pSMB
->t2
.TotalDataCount
= 0;
2127 pSMB
->t2
.MaxParameterCount
= cpu_to_le16(4);
2128 /* BB find exact max data count below from sess structure BB */
2129 pSMB
->t2
.MaxDataCount
= cpu_to_le16(4000);
2130 pSMB
->t2
.MaxSetupCount
= 0;
2131 pSMB
->t2
.Reserved
= 0;
2133 pSMB
->t2
.Timeout
= 0;
2134 pSMB
->t2
.Reserved2
= 0;
2135 pSMB
->t2
.ParameterOffset
= cpu_to_le16(offsetof(struct smb_t2_qfi_req
,
2137 pSMB
->t2
.DataCount
= 0;
2138 pSMB
->t2
.DataOffset
= 0;
2139 pSMB
->t2
.SetupCount
= 1;
2140 pSMB
->t2
.Reserved3
= 0;
2141 pSMB
->t2
.SubCommand
= cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION
);
2142 byte_count
= params
+ 1 /* pad */ ;
2143 pSMB
->t2
.TotalParameterCount
= cpu_to_le16(params
);
2144 pSMB
->t2
.ParameterCount
= pSMB
->t2
.TotalParameterCount
;
2145 pSMB
->InformationLevel
= cpu_to_le16(SMB_QUERY_ATTR_FLAGS
);
2148 pSMB
->hdr
.smb_buf_length
+= byte_count
;
2149 pSMB
->t2
.ByteCount
= cpu_to_le16(byte_count
);
2151 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
2152 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
2154 cFYI(1, ("error %d in GetExtAttr", rc
));
2156 /* decode response */
2157 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
2158 if (rc
|| (pSMBr
->ByteCount
< 2))
2159 /* BB also check enough total bytes returned */
2160 /* If rc should we check for EOPNOSUPP and
2161 disable the srvino flag? or in caller? */
2162 rc
= -EIO
; /* bad smb */
2164 __u16 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
2165 __u16 count
= le16_to_cpu(pSMBr
->t2
.DataCount
);
2166 struct file_chattr_info
* pfinfo
;
2167 /* BB Do we need a cast or hash here ? */
2169 cFYI(1, ("Illegal size ret in GetExtAttr"));
2173 pfinfo
= (struct file_chattr_info
*)
2174 (data_offset
+ (char *) &pSMBr
->hdr
.Protocol
);
2175 *pExtAttrBits
= le64_to_cpu(pfinfo
->mode
);
2176 *pMask
= le64_to_cpu(pfinfo
->mask
);
2180 cifs_buf_release(pSMB
);
2182 goto GetExtAttrRetry
;
2187 #endif /* CONFIG_POSIX */
2190 CIFSSMBQPathInfo(const int xid
, struct cifsTconInfo
*tcon
,
2191 const unsigned char *searchName
,
2192 FILE_ALL_INFO
* pFindData
,
2193 const struct nls_table
*nls_codepage
, int remap
)
2195 /* level 263 SMB_QUERY_FILE_ALL_INFO */
2196 TRANSACTION2_QPI_REQ
*pSMB
= NULL
;
2197 TRANSACTION2_QPI_RSP
*pSMBr
= NULL
;
2201 __u16 params
, byte_count
;
2203 /* cFYI(1, ("In QPathInfo path %s", searchName)); */
2205 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
2210 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
2212 cifsConvertToUCS((__le16
*) pSMB
->FileName
, searchName
,
2213 PATH_MAX
, nls_codepage
, remap
);
2214 name_len
++; /* trailing null */
2216 } else { /* BB improve the check for buffer overruns BB */
2217 name_len
= strnlen(searchName
, PATH_MAX
);
2218 name_len
++; /* trailing null */
2219 strncpy(pSMB
->FileName
, searchName
, name_len
);
2222 params
= 2 /* level */ + 4 /* reserved */ + name_len
/* includes NUL */ ;
2223 pSMB
->TotalDataCount
= 0;
2224 pSMB
->MaxParameterCount
= cpu_to_le16(2);
2225 pSMB
->MaxDataCount
= cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
2226 pSMB
->MaxSetupCount
= 0;
2230 pSMB
->Reserved2
= 0;
2231 pSMB
->ParameterOffset
= cpu_to_le16(offsetof(
2232 struct smb_com_transaction2_qpi_req
,InformationLevel
) - 4);
2233 pSMB
->DataCount
= 0;
2234 pSMB
->DataOffset
= 0;
2235 pSMB
->SetupCount
= 1;
2236 pSMB
->Reserved3
= 0;
2237 pSMB
->SubCommand
= cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION
);
2238 byte_count
= params
+ 1 /* pad */ ;
2239 pSMB
->TotalParameterCount
= cpu_to_le16(params
);
2240 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
2241 pSMB
->InformationLevel
= cpu_to_le16(SMB_QUERY_FILE_ALL_INFO
);
2242 pSMB
->Reserved4
= 0;
2243 pSMB
->hdr
.smb_buf_length
+= byte_count
;
2244 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
2246 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
2247 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
2249 cFYI(1, ("Send error in QPathInfo = %d", rc
));
2250 } else { /* decode response */
2251 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
2253 if (rc
|| (pSMBr
->ByteCount
< 40))
2254 rc
= -EIO
; /* bad smb */
2255 else if (pFindData
){
2256 __u16 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
2257 memcpy((char *) pFindData
,
2258 (char *) &pSMBr
->hdr
.Protocol
+
2259 data_offset
, sizeof (FILE_ALL_INFO
));
2263 cifs_buf_release(pSMB
);
2265 goto QPathInfoRetry
;
2271 CIFSSMBUnixQPathInfo(const int xid
, struct cifsTconInfo
*tcon
,
2272 const unsigned char *searchName
,
2273 FILE_UNIX_BASIC_INFO
* pFindData
,
2274 const struct nls_table
*nls_codepage
, int remap
)
2276 /* SMB_QUERY_FILE_UNIX_BASIC */
2277 TRANSACTION2_QPI_REQ
*pSMB
= NULL
;
2278 TRANSACTION2_QPI_RSP
*pSMBr
= NULL
;
2280 int bytes_returned
= 0;
2282 __u16 params
, byte_count
;
2284 cFYI(1, ("In QPathInfo (Unix) the path %s", searchName
));
2286 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
2291 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
2293 cifsConvertToUCS((__le16
*) pSMB
->FileName
, searchName
,
2294 PATH_MAX
, nls_codepage
, remap
);
2295 name_len
++; /* trailing null */
2297 } else { /* BB improve the check for buffer overruns BB */
2298 name_len
= strnlen(searchName
, PATH_MAX
);
2299 name_len
++; /* trailing null */
2300 strncpy(pSMB
->FileName
, searchName
, name_len
);
2303 params
= 2 /* level */ + 4 /* reserved */ + name_len
/* includes NUL */ ;
2304 pSMB
->TotalDataCount
= 0;
2305 pSMB
->MaxParameterCount
= cpu_to_le16(2);
2306 /* BB find exact max SMB PDU from sess structure BB */
2307 pSMB
->MaxDataCount
= cpu_to_le16(4000);
2308 pSMB
->MaxSetupCount
= 0;
2312 pSMB
->Reserved2
= 0;
2313 pSMB
->ParameterOffset
= cpu_to_le16(offsetof(
2314 struct smb_com_transaction2_qpi_req
,InformationLevel
) - 4);
2315 pSMB
->DataCount
= 0;
2316 pSMB
->DataOffset
= 0;
2317 pSMB
->SetupCount
= 1;
2318 pSMB
->Reserved3
= 0;
2319 pSMB
->SubCommand
= cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION
);
2320 byte_count
= params
+ 1 /* pad */ ;
2321 pSMB
->TotalParameterCount
= cpu_to_le16(params
);
2322 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
2323 pSMB
->InformationLevel
= cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC
);
2324 pSMB
->Reserved4
= 0;
2325 pSMB
->hdr
.smb_buf_length
+= byte_count
;
2326 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
2328 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
2329 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
2331 cFYI(1, ("Send error in QPathInfo = %d", rc
));
2332 } else { /* decode response */
2333 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
2335 if (rc
|| (pSMBr
->ByteCount
< sizeof(FILE_UNIX_BASIC_INFO
))) {
2336 rc
= -EIO
; /* bad smb */
2338 __u16 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
2339 memcpy((char *) pFindData
,
2340 (char *) &pSMBr
->hdr
.Protocol
+
2342 sizeof (FILE_UNIX_BASIC_INFO
));
2345 cifs_buf_release(pSMB
);
2347 goto UnixQPathInfoRetry
;
2352 #if 0 /* function unused at present */
2353 int CIFSFindSingle(const int xid
, struct cifsTconInfo
*tcon
,
2354 const char *searchName
, FILE_ALL_INFO
* findData
,
2355 const struct nls_table
*nls_codepage
)
2357 /* level 257 SMB_ */
2358 TRANSACTION2_FFIRST_REQ
*pSMB
= NULL
;
2359 TRANSACTION2_FFIRST_RSP
*pSMBr
= NULL
;
2363 __u16 params
, byte_count
;
2365 cFYI(1, ("In FindUnique"));
2367 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
2372 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
2374 cifsConvertToUCS((__le16
*) pSMB
->FileName
, searchName
, PATH_MAX
2375 /* find define for this maxpathcomponent */
2377 name_len
++; /* trailing null */
2379 } else { /* BB improve the check for buffer overruns BB */
2380 name_len
= strnlen(searchName
, PATH_MAX
);
2381 name_len
++; /* trailing null */
2382 strncpy(pSMB
->FileName
, searchName
, name_len
);
2385 params
= 12 + name_len
/* includes null */ ;
2386 pSMB
->TotalDataCount
= 0; /* no EAs */
2387 pSMB
->MaxParameterCount
= cpu_to_le16(2);
2388 pSMB
->MaxDataCount
= cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
2389 pSMB
->MaxSetupCount
= 0;
2393 pSMB
->Reserved2
= 0;
2394 pSMB
->ParameterOffset
= cpu_to_le16(
2395 offsetof(struct smb_com_transaction2_ffirst_req
,InformationLevel
) - 4);
2396 pSMB
->DataCount
= 0;
2397 pSMB
->DataOffset
= 0;
2398 pSMB
->SetupCount
= 1; /* one byte, no need to le convert */
2399 pSMB
->Reserved3
= 0;
2400 pSMB
->SubCommand
= cpu_to_le16(TRANS2_FIND_FIRST
);
2401 byte_count
= params
+ 1 /* pad */ ;
2402 pSMB
->TotalParameterCount
= cpu_to_le16(params
);
2403 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
2404 pSMB
->SearchAttributes
=
2405 cpu_to_le16(ATTR_READONLY
| ATTR_HIDDEN
| ATTR_SYSTEM
|
2407 pSMB
->SearchCount
= cpu_to_le16(16); /* BB increase */
2408 pSMB
->SearchFlags
= cpu_to_le16(1);
2409 pSMB
->InformationLevel
= cpu_to_le16(SMB_FIND_FILE_DIRECTORY_INFO
);
2410 pSMB
->SearchStorageType
= 0; /* BB what should we set this to? BB */
2411 pSMB
->hdr
.smb_buf_length
+= byte_count
;
2412 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
2414 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
2415 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
2418 cFYI(1, ("Send error in FindFileDirInfo = %d", rc
));
2419 } else { /* decode response */
2420 #ifdef CONFIG_CIFS_STATS
2421 atomic_inc(&tcon
->num_ffirst
);
2426 cifs_buf_release(pSMB
);
2428 goto findUniqueRetry
;
2432 #endif /* end unused (temporarily) function */
2434 /* xid, tcon, searchName and codepage are input parms, rest are returned */
2436 CIFSFindFirst(const int xid
, struct cifsTconInfo
*tcon
,
2437 const char *searchName
,
2438 const struct nls_table
*nls_codepage
,
2440 struct cifs_search_info
* psrch_inf
, int remap
, const char dirsep
)
2442 /* level 257 SMB_ */
2443 TRANSACTION2_FFIRST_REQ
*pSMB
= NULL
;
2444 TRANSACTION2_FFIRST_RSP
*pSMBr
= NULL
;
2445 T2_FFIRST_RSP_PARMS
* parms
;
2447 int bytes_returned
= 0;
2449 __u16 params
, byte_count
;
2451 cFYI(1, ("In FindFirst for %s",searchName
));
2454 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
2459 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
2461 cifsConvertToUCS((__le16
*) pSMB
->FileName
,searchName
,
2462 PATH_MAX
, nls_codepage
, remap
);
2463 /* We can not add the asterik earlier in case
2464 it got remapped to 0xF03A as if it were part of the
2465 directory name instead of a wildcard */
2467 pSMB
->FileName
[name_len
] = dirsep
;
2468 pSMB
->FileName
[name_len
+1] = 0;
2469 pSMB
->FileName
[name_len
+2] = '*';
2470 pSMB
->FileName
[name_len
+3] = 0;
2471 name_len
+= 4; /* now the trailing null */
2472 pSMB
->FileName
[name_len
] = 0; /* null terminate just in case */
2473 pSMB
->FileName
[name_len
+1] = 0;
2475 } else { /* BB add check for overrun of SMB buf BB */
2476 name_len
= strnlen(searchName
, PATH_MAX
);
2477 /* BB fix here and in unicode clause above ie
2478 if(name_len > buffersize-header)
2479 free buffer exit; BB */
2480 strncpy(pSMB
->FileName
, searchName
, name_len
);
2481 pSMB
->FileName
[name_len
] = dirsep
;
2482 pSMB
->FileName
[name_len
+1] = '*';
2483 pSMB
->FileName
[name_len
+2] = 0;
2487 params
= 12 + name_len
/* includes null */ ;
2488 pSMB
->TotalDataCount
= 0; /* no EAs */
2489 pSMB
->MaxParameterCount
= cpu_to_le16(10);
2490 pSMB
->MaxDataCount
= cpu_to_le16((tcon
->ses
->server
->maxBuf
-
2491 MAX_CIFS_HDR_SIZE
) & 0xFFFFFF00);
2492 pSMB
->MaxSetupCount
= 0;
2496 pSMB
->Reserved2
= 0;
2497 byte_count
= params
+ 1 /* pad */ ;
2498 pSMB
->TotalParameterCount
= cpu_to_le16(params
);
2499 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
2500 pSMB
->ParameterOffset
= cpu_to_le16(
2501 offsetof(struct smb_com_transaction2_ffirst_req
, SearchAttributes
) - 4);
2502 pSMB
->DataCount
= 0;
2503 pSMB
->DataOffset
= 0;
2504 pSMB
->SetupCount
= 1; /* one byte, no need to make endian neutral */
2505 pSMB
->Reserved3
= 0;
2506 pSMB
->SubCommand
= cpu_to_le16(TRANS2_FIND_FIRST
);
2507 pSMB
->SearchAttributes
=
2508 cpu_to_le16(ATTR_READONLY
| ATTR_HIDDEN
| ATTR_SYSTEM
|
2510 pSMB
->SearchCount
= cpu_to_le16(CIFSMaxBufSize
/sizeof(FILE_UNIX_INFO
));
2511 pSMB
->SearchFlags
= cpu_to_le16(CIFS_SEARCH_CLOSE_AT_END
|
2512 CIFS_SEARCH_RETURN_RESUME
);
2513 pSMB
->InformationLevel
= cpu_to_le16(psrch_inf
->info_level
);
2515 /* BB what should we set StorageType to? Does it matter? BB */
2516 pSMB
->SearchStorageType
= 0;
2517 pSMB
->hdr
.smb_buf_length
+= byte_count
;
2518 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
2520 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
2521 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
2523 if (rc
) {/* BB add logic to retry regular search if Unix search rejected unexpectedly by server */
2524 /* BB Add code to handle unsupported level rc */
2525 cFYI(1, ("Error in FindFirst = %d", rc
));
2528 cifs_buf_release(pSMB
);
2530 /* BB eventually could optimize out free and realloc of buf */
2533 goto findFirstRetry
;
2534 } else { /* decode response */
2535 #ifdef CONFIG_CIFS_STATS
2536 atomic_inc(&tcon
->num_ffirst
);
2538 /* BB remember to free buffer if error BB */
2539 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
2541 if (pSMBr
->hdr
.Flags2
& SMBFLG2_UNICODE
)
2542 psrch_inf
->unicode
= TRUE
;
2544 psrch_inf
->unicode
= FALSE
;
2546 psrch_inf
->ntwrk_buf_start
= (char *)pSMBr
;
2547 psrch_inf
->srch_entries_start
=
2548 (char *) &pSMBr
->hdr
.Protocol
+
2549 le16_to_cpu(pSMBr
->t2
.DataOffset
);
2550 parms
= (T2_FFIRST_RSP_PARMS
*)((char *) &pSMBr
->hdr
.Protocol
+
2551 le16_to_cpu(pSMBr
->t2
.ParameterOffset
));
2553 if(parms
->EndofSearch
)
2554 psrch_inf
->endOfSearch
= TRUE
;
2556 psrch_inf
->endOfSearch
= FALSE
;
2558 psrch_inf
->entries_in_buffer
= le16_to_cpu(parms
->SearchCount
);
2559 psrch_inf
->index_of_last_entry
=
2560 psrch_inf
->entries_in_buffer
;
2561 *pnetfid
= parms
->SearchHandle
;
2563 cifs_buf_release(pSMB
);
2570 int CIFSFindNext(const int xid
, struct cifsTconInfo
*tcon
,
2571 __u16 searchHandle
, struct cifs_search_info
* psrch_inf
)
2573 TRANSACTION2_FNEXT_REQ
*pSMB
= NULL
;
2574 TRANSACTION2_FNEXT_RSP
*pSMBr
= NULL
;
2575 T2_FNEXT_RSP_PARMS
* parms
;
2576 char *response_data
;
2578 int bytes_returned
, name_len
;
2579 __u16 params
, byte_count
;
2581 cFYI(1, ("In FindNext"));
2583 if(psrch_inf
->endOfSearch
== TRUE
)
2586 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
2591 params
= 14; /* includes 2 bytes of null string, converted to LE below */
2593 pSMB
->TotalDataCount
= 0; /* no EAs */
2594 pSMB
->MaxParameterCount
= cpu_to_le16(8);
2595 pSMB
->MaxDataCount
=
2596 cpu_to_le16((tcon
->ses
->server
->maxBuf
- MAX_CIFS_HDR_SIZE
) & 0xFFFFFF00);
2597 pSMB
->MaxSetupCount
= 0;
2601 pSMB
->Reserved2
= 0;
2602 pSMB
->ParameterOffset
= cpu_to_le16(
2603 offsetof(struct smb_com_transaction2_fnext_req
,SearchHandle
) - 4);
2604 pSMB
->DataCount
= 0;
2605 pSMB
->DataOffset
= 0;
2606 pSMB
->SetupCount
= 1;
2607 pSMB
->Reserved3
= 0;
2608 pSMB
->SubCommand
= cpu_to_le16(TRANS2_FIND_NEXT
);
2609 pSMB
->SearchHandle
= searchHandle
; /* always kept as le */
2611 cpu_to_le16(CIFSMaxBufSize
/ sizeof (FILE_UNIX_INFO
));
2612 /* test for Unix extensions */
2613 /* if (tcon->ses->capabilities & CAP_UNIX) {
2614 pSMB->InformationLevel = cpu_to_le16(SMB_FIND_FILE_UNIX);
2615 psrch_inf->info_level = SMB_FIND_FILE_UNIX;
2617 pSMB->InformationLevel =
2618 cpu_to_le16(SMB_FIND_FILE_DIRECTORY_INFO);
2619 psrch_inf->info_level = SMB_FIND_FILE_DIRECTORY_INFO;
2621 pSMB
->InformationLevel
= cpu_to_le16(psrch_inf
->info_level
);
2622 pSMB
->ResumeKey
= psrch_inf
->resume_key
;
2624 cpu_to_le16(CIFS_SEARCH_CLOSE_AT_END
| CIFS_SEARCH_RETURN_RESUME
);
2626 name_len
= psrch_inf
->resume_name_len
;
2628 if(name_len
< PATH_MAX
) {
2629 memcpy(pSMB
->ResumeFileName
, psrch_inf
->presume_name
, name_len
);
2630 byte_count
+= name_len
;
2633 goto FNext2_err_exit
;
2635 byte_count
= params
+ 1 /* pad */ ;
2636 pSMB
->TotalParameterCount
= cpu_to_le16(params
);
2637 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
2638 pSMB
->hdr
.smb_buf_length
+= byte_count
;
2639 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
2641 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
2642 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
2646 psrch_inf
->endOfSearch
= TRUE
;
2647 rc
= 0; /* search probably was closed at end of search above */
2649 cFYI(1, ("FindNext returned = %d", rc
));
2650 } else { /* decode response */
2651 #ifdef CONFIG_CIFS_STATS
2652 atomic_inc(&tcon
->num_fnext
);
2654 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
2657 /* BB fixme add lock for file (srch_info) struct here */
2658 if (pSMBr
->hdr
.Flags2
& SMBFLG2_UNICODE
)
2659 psrch_inf
->unicode
= TRUE
;
2661 psrch_inf
->unicode
= FALSE
;
2662 response_data
= (char *) &pSMBr
->hdr
.Protocol
+
2663 le16_to_cpu(pSMBr
->t2
.ParameterOffset
);
2664 parms
= (T2_FNEXT_RSP_PARMS
*)response_data
;
2665 response_data
= (char *)&pSMBr
->hdr
.Protocol
+
2666 le16_to_cpu(pSMBr
->t2
.DataOffset
);
2667 cifs_buf_release(psrch_inf
->ntwrk_buf_start
);
2668 psrch_inf
->srch_entries_start
= response_data
;
2669 psrch_inf
->ntwrk_buf_start
= (char *)pSMB
;
2670 if(parms
->EndofSearch
)
2671 psrch_inf
->endOfSearch
= TRUE
;
2673 psrch_inf
->endOfSearch
= FALSE
;
2675 psrch_inf
->entries_in_buffer
= le16_to_cpu(parms
->SearchCount
);
2676 psrch_inf
->index_of_last_entry
+=
2677 psrch_inf
->entries_in_buffer
;
2678 /* cFYI(1,("fnxt2 entries in buf %d index_of_last %d",psrch_inf->entries_in_buffer,psrch_inf->index_of_last_entry)); */
2680 /* BB fixme add unlock here */
2685 /* BB On error, should we leave previous search buf (and count and
2686 last entry fields) intact or free the previous one? */
2688 /* Note: On -EAGAIN error only caller can retry on handle based calls
2689 since file handle passed in no longer valid */
2692 cifs_buf_release(pSMB
);
2698 CIFSFindClose(const int xid
, struct cifsTconInfo
*tcon
, const __u16 searchHandle
)
2701 FINDCLOSE_REQ
*pSMB
= NULL
;
2702 CLOSE_RSP
*pSMBr
= NULL
; /* BB removeme BB */
2705 cFYI(1, ("In CIFSSMBFindClose"));
2706 rc
= small_smb_init(SMB_COM_FIND_CLOSE2
, 1, tcon
, (void **)&pSMB
);
2708 /* no sense returning error if session restarted
2709 as file handle has been closed */
2715 pSMBr
= (CLOSE_RSP
*)pSMB
; /* BB removeme BB */
2716 pSMB
->FileID
= searchHandle
;
2717 pSMB
->ByteCount
= 0;
2718 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
2719 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
2721 cERROR(1, ("Send error in FindClose = %d", rc
));
2723 #ifdef CONFIG_CIFS_STATS
2724 atomic_inc(&tcon
->num_fclose
);
2726 cifs_small_buf_release(pSMB
);
2728 /* Since session is dead, search handle closed on server already */
2735 #ifdef CONFIG_CIFS_EXPERIMENTAL
2737 CIFSGetSrvInodeNumber(const int xid
, struct cifsTconInfo
*tcon
,
2738 const unsigned char *searchName
,
2739 __u64
* inode_number
,
2740 const struct nls_table
*nls_codepage
, int remap
)
2743 TRANSACTION2_QPI_REQ
*pSMB
= NULL
;
2744 TRANSACTION2_QPI_RSP
*pSMBr
= NULL
;
2745 int name_len
, bytes_returned
;
2746 __u16 params
, byte_count
;
2748 cFYI(1,("In GetSrvInodeNum for %s",searchName
));
2752 GetInodeNumberRetry
:
2753 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
2759 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
2761 cifsConvertToUCS((__le16
*) pSMB
->FileName
, searchName
,
2762 PATH_MAX
,nls_codepage
, remap
);
2763 name_len
++; /* trailing null */
2765 } else { /* BB improve the check for buffer overruns BB */
2766 name_len
= strnlen(searchName
, PATH_MAX
);
2767 name_len
++; /* trailing null */
2768 strncpy(pSMB
->FileName
, searchName
, name_len
);
2771 params
= 2 /* level */ + 4 /* rsrvd */ + name_len
/* incl null */ ;
2772 pSMB
->TotalDataCount
= 0;
2773 pSMB
->MaxParameterCount
= cpu_to_le16(2);
2774 /* BB find exact max data count below from sess structure BB */
2775 pSMB
->MaxDataCount
= cpu_to_le16(4000);
2776 pSMB
->MaxSetupCount
= 0;
2780 pSMB
->Reserved2
= 0;
2781 pSMB
->ParameterOffset
= cpu_to_le16(offsetof(
2782 struct smb_com_transaction2_qpi_req
,InformationLevel
) - 4);
2783 pSMB
->DataCount
= 0;
2784 pSMB
->DataOffset
= 0;
2785 pSMB
->SetupCount
= 1;
2786 pSMB
->Reserved3
= 0;
2787 pSMB
->SubCommand
= cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION
);
2788 byte_count
= params
+ 1 /* pad */ ;
2789 pSMB
->TotalParameterCount
= cpu_to_le16(params
);
2790 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
2791 pSMB
->InformationLevel
= cpu_to_le16(SMB_QUERY_FILE_INTERNAL_INFO
);
2792 pSMB
->Reserved4
= 0;
2793 pSMB
->hdr
.smb_buf_length
+= byte_count
;
2794 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
2796 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
2797 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
2799 cFYI(1, ("error %d in QueryInternalInfo", rc
));
2801 /* decode response */
2802 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
2803 if (rc
|| (pSMBr
->ByteCount
< 2))
2804 /* BB also check enough total bytes returned */
2805 /* If rc should we check for EOPNOSUPP and
2806 disable the srvino flag? or in caller? */
2807 rc
= -EIO
; /* bad smb */
2809 __u16 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
2810 __u16 count
= le16_to_cpu(pSMBr
->t2
.DataCount
);
2811 struct file_internal_info
* pfinfo
;
2812 /* BB Do we need a cast or hash here ? */
2814 cFYI(1, ("Illegal size ret in QryIntrnlInf"));
2816 goto GetInodeNumOut
;
2818 pfinfo
= (struct file_internal_info
*)
2819 (data_offset
+ (char *) &pSMBr
->hdr
.Protocol
);
2820 *inode_number
= pfinfo
->UniqueId
;
2824 cifs_buf_release(pSMB
);
2826 goto GetInodeNumberRetry
;
2829 #endif /* CIFS_EXPERIMENTAL */
2832 CIFSGetDFSRefer(const int xid
, struct cifsSesInfo
*ses
,
2833 const unsigned char *searchName
,
2834 unsigned char **targetUNCs
,
2835 unsigned int *number_of_UNC_in_array
,
2836 const struct nls_table
*nls_codepage
, int remap
)
2838 /* TRANS2_GET_DFS_REFERRAL */
2839 TRANSACTION2_GET_DFS_REFER_REQ
*pSMB
= NULL
;
2840 TRANSACTION2_GET_DFS_REFER_RSP
*pSMBr
= NULL
;
2841 struct dfs_referral_level_3
* referrals
= NULL
;
2847 __u16 params
, byte_count
;
2848 *number_of_UNC_in_array
= 0;
2851 cFYI(1, ("In GetDFSRefer the path %s", searchName
));
2855 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, NULL
, (void **) &pSMB
,
2860 pSMB
->hdr
.Tid
= ses
->ipc_tid
;
2861 pSMB
->hdr
.Uid
= ses
->Suid
;
2862 if (ses
->capabilities
& CAP_STATUS32
) {
2863 pSMB
->hdr
.Flags2
|= SMBFLG2_ERR_STATUS
;
2865 if (ses
->capabilities
& CAP_DFS
) {
2866 pSMB
->hdr
.Flags2
|= SMBFLG2_DFS
;
2869 if (ses
->capabilities
& CAP_UNICODE
) {
2870 pSMB
->hdr
.Flags2
|= SMBFLG2_UNICODE
;
2872 cifsConvertToUCS((__le16
*) pSMB
->RequestFileName
,
2873 searchName
, PATH_MAX
, nls_codepage
, remap
);
2874 name_len
++; /* trailing null */
2876 } else { /* BB improve the check for buffer overruns BB */
2877 name_len
= strnlen(searchName
, PATH_MAX
);
2878 name_len
++; /* trailing null */
2879 strncpy(pSMB
->RequestFileName
, searchName
, name_len
);
2882 params
= 2 /* level */ + name_len
/*includes null */ ;
2883 pSMB
->TotalDataCount
= 0;
2884 pSMB
->DataCount
= 0;
2885 pSMB
->DataOffset
= 0;
2886 pSMB
->MaxParameterCount
= 0;
2887 pSMB
->MaxDataCount
= cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
2888 pSMB
->MaxSetupCount
= 0;
2892 pSMB
->Reserved2
= 0;
2893 pSMB
->ParameterOffset
= cpu_to_le16(offsetof(
2894 struct smb_com_transaction2_get_dfs_refer_req
, MaxReferralLevel
) - 4);
2895 pSMB
->SetupCount
= 1;
2896 pSMB
->Reserved3
= 0;
2897 pSMB
->SubCommand
= cpu_to_le16(TRANS2_GET_DFS_REFERRAL
);
2898 byte_count
= params
+ 3 /* pad */ ;
2899 pSMB
->ParameterCount
= cpu_to_le16(params
);
2900 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
2901 pSMB
->MaxReferralLevel
= cpu_to_le16(3);
2902 pSMB
->hdr
.smb_buf_length
+= byte_count
;
2903 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
2905 rc
= SendReceive(xid
, ses
, (struct smb_hdr
*) pSMB
,
2906 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
2908 cFYI(1, ("Send error in GetDFSRefer = %d", rc
));
2909 } else { /* decode response */
2910 /* BB Add logic to parse referrals here */
2911 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
2913 if (rc
|| (pSMBr
->ByteCount
< 17)) /* BB also check enough total bytes returned */
2914 rc
= -EIO
; /* bad smb */
2916 __u16 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
2917 __u16 data_count
= le16_to_cpu(pSMBr
->t2
.DataCount
);
2920 ("Decoding GetDFSRefer response. BCC: %d Offset %d",
2921 pSMBr
->ByteCount
, data_offset
));
2923 (struct dfs_referral_level_3
*)
2924 (8 /* sizeof start of data block */ +
2926 (char *) &pSMBr
->hdr
.Protocol
);
2927 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",
2928 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
)));
2929 /* BB This field is actually two bytes in from start of
2930 data block so we could do safety check that DataBlock
2931 begins at address of pSMBr->NumberOfReferrals */
2932 *number_of_UNC_in_array
= le16_to_cpu(pSMBr
->NumberOfReferrals
);
2934 /* BB Fix below so can return more than one referral */
2935 if(*number_of_UNC_in_array
> 1)
2936 *number_of_UNC_in_array
= 1;
2938 /* get the length of the strings describing refs */
2940 for(i
=0;i
<*number_of_UNC_in_array
;i
++) {
2941 /* make sure that DfsPathOffset not past end */
2942 __u16 offset
= le16_to_cpu(referrals
->DfsPathOffset
);
2943 if (offset
> data_count
) {
2944 /* if invalid referral, stop here and do
2945 not try to copy any more */
2946 *number_of_UNC_in_array
= i
;
2949 temp
= ((char *)referrals
) + offset
;
2951 if (pSMBr
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
2952 name_len
+= UniStrnlen((wchar_t *)temp
,data_count
);
2954 name_len
+= strnlen(temp
,data_count
);
2957 /* BB add check that referral pointer does not fall off end PDU */
2960 /* BB add check for name_len bigger than bcc */
2962 kmalloc(name_len
+1+ (*number_of_UNC_in_array
),GFP_KERNEL
);
2963 if(*targetUNCs
== NULL
) {
2967 /* copy the ref strings */
2969 (struct dfs_referral_level_3
*)
2970 (8 /* sizeof data hdr */ +
2972 (char *) &pSMBr
->hdr
.Protocol
);
2974 for(i
=0;i
<*number_of_UNC_in_array
;i
++) {
2975 temp
= ((char *)referrals
) + le16_to_cpu(referrals
->DfsPathOffset
);
2976 if (pSMBr
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
2977 cifs_strfromUCS_le(*targetUNCs
,
2978 (wchar_t *) temp
, name_len
, nls_codepage
);
2980 strncpy(*targetUNCs
,temp
,name_len
);
2982 /* BB update target_uncs pointers */
2992 cifs_buf_release(pSMB
);
3001 CIFSSMBQFSInfo(const int xid
, struct cifsTconInfo
*tcon
, struct kstatfs
*FSData
)
3003 /* level 0x103 SMB_QUERY_FILE_SYSTEM_INFO */
3004 TRANSACTION2_QFSI_REQ
*pSMB
= NULL
;
3005 TRANSACTION2_QFSI_RSP
*pSMBr
= NULL
;
3006 FILE_SYSTEM_INFO
*response_data
;
3008 int bytes_returned
= 0;
3009 __u16 params
, byte_count
;
3011 cFYI(1, ("In QFSInfo"));
3013 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
3018 params
= 2; /* level */
3019 pSMB
->TotalDataCount
= 0;
3020 pSMB
->MaxParameterCount
= cpu_to_le16(2);
3021 pSMB
->MaxDataCount
= cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
3022 pSMB
->MaxSetupCount
= 0;
3026 pSMB
->Reserved2
= 0;
3027 byte_count
= params
+ 1 /* pad */ ;
3028 pSMB
->TotalParameterCount
= cpu_to_le16(params
);
3029 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
3030 pSMB
->ParameterOffset
= cpu_to_le16(offsetof(
3031 struct smb_com_transaction2_qfsi_req
, InformationLevel
) - 4);
3032 pSMB
->DataCount
= 0;
3033 pSMB
->DataOffset
= 0;
3034 pSMB
->SetupCount
= 1;
3035 pSMB
->Reserved3
= 0;
3036 pSMB
->SubCommand
= cpu_to_le16(TRANS2_QUERY_FS_INFORMATION
);
3037 pSMB
->InformationLevel
= cpu_to_le16(SMB_QUERY_FS_SIZE_INFO
);
3038 pSMB
->hdr
.smb_buf_length
+= byte_count
;
3039 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
3041 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
3042 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
3044 cERROR(1, ("Send error in QFSInfo = %d", rc
));
3045 } else { /* decode response */
3046 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
3048 if (rc
|| (pSMBr
->ByteCount
< 24)) /* BB alsO CHEck enough total bytes returned */
3049 rc
= -EIO
; /* bad smb */
3051 __u16 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
3053 ("Decoding qfsinfo response. BCC: %d Offset %d",
3054 pSMBr
->ByteCount
, data_offset
));
3058 *) (((char *) &pSMBr
->hdr
.Protocol
) +
3061 le32_to_cpu(response_data
->BytesPerSector
) *
3062 le32_to_cpu(response_data
->
3063 SectorsPerAllocationUnit
);
3065 le64_to_cpu(response_data
->TotalAllocationUnits
);
3066 FSData
->f_bfree
= FSData
->f_bavail
=
3067 le64_to_cpu(response_data
->FreeAllocationUnits
);
3069 ("Blocks: %lld Free: %lld Block size %ld",
3070 (unsigned long long)FSData
->f_blocks
,
3071 (unsigned long long)FSData
->f_bfree
,
3075 cifs_buf_release(pSMB
);
3084 CIFSSMBQFSAttributeInfo(const int xid
, struct cifsTconInfo
*tcon
)
3086 /* level 0x105 SMB_QUERY_FILE_SYSTEM_INFO */
3087 TRANSACTION2_QFSI_REQ
*pSMB
= NULL
;
3088 TRANSACTION2_QFSI_RSP
*pSMBr
= NULL
;
3089 FILE_SYSTEM_ATTRIBUTE_INFO
*response_data
;
3091 int bytes_returned
= 0;
3092 __u16 params
, byte_count
;
3094 cFYI(1, ("In QFSAttributeInfo"));
3096 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
3101 params
= 2; /* level */
3102 pSMB
->TotalDataCount
= 0;
3103 pSMB
->MaxParameterCount
= cpu_to_le16(2);
3104 pSMB
->MaxDataCount
= cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
3105 pSMB
->MaxSetupCount
= 0;
3109 pSMB
->Reserved2
= 0;
3110 byte_count
= params
+ 1 /* pad */ ;
3111 pSMB
->TotalParameterCount
= cpu_to_le16(params
);
3112 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
3113 pSMB
->ParameterOffset
= cpu_to_le16(offsetof(
3114 struct smb_com_transaction2_qfsi_req
, InformationLevel
) - 4);
3115 pSMB
->DataCount
= 0;
3116 pSMB
->DataOffset
= 0;
3117 pSMB
->SetupCount
= 1;
3118 pSMB
->Reserved3
= 0;
3119 pSMB
->SubCommand
= cpu_to_le16(TRANS2_QUERY_FS_INFORMATION
);
3120 pSMB
->InformationLevel
= cpu_to_le16(SMB_QUERY_FS_ATTRIBUTE_INFO
);
3121 pSMB
->hdr
.smb_buf_length
+= byte_count
;
3122 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
3124 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
3125 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
3127 cERROR(1, ("Send error in QFSAttributeInfo = %d", rc
));
3128 } else { /* decode response */
3129 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
3131 if (rc
|| (pSMBr
->ByteCount
< 13)) { /* BB also check enough bytes returned */
3132 rc
= -EIO
; /* bad smb */
3134 __u16 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
3136 (FILE_SYSTEM_ATTRIBUTE_INFO
3137 *) (((char *) &pSMBr
->hdr
.Protocol
) +
3139 memcpy(&tcon
->fsAttrInfo
, response_data
,
3140 sizeof (FILE_SYSTEM_ATTRIBUTE_INFO
));
3143 cifs_buf_release(pSMB
);
3146 goto QFSAttributeRetry
;
3152 CIFSSMBQFSDeviceInfo(const int xid
, struct cifsTconInfo
*tcon
)
3154 /* level 0x104 SMB_QUERY_FILE_SYSTEM_INFO */
3155 TRANSACTION2_QFSI_REQ
*pSMB
= NULL
;
3156 TRANSACTION2_QFSI_RSP
*pSMBr
= NULL
;
3157 FILE_SYSTEM_DEVICE_INFO
*response_data
;
3159 int bytes_returned
= 0;
3160 __u16 params
, byte_count
;
3162 cFYI(1, ("In QFSDeviceInfo"));
3164 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
3169 params
= 2; /* level */
3170 pSMB
->TotalDataCount
= 0;
3171 pSMB
->MaxParameterCount
= cpu_to_le16(2);
3172 pSMB
->MaxDataCount
= cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
3173 pSMB
->MaxSetupCount
= 0;
3177 pSMB
->Reserved2
= 0;
3178 byte_count
= params
+ 1 /* pad */ ;
3179 pSMB
->TotalParameterCount
= cpu_to_le16(params
);
3180 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
3181 pSMB
->ParameterOffset
= cpu_to_le16(offsetof(
3182 struct smb_com_transaction2_qfsi_req
, InformationLevel
) - 4);
3184 pSMB
->DataCount
= 0;
3185 pSMB
->DataOffset
= 0;
3186 pSMB
->SetupCount
= 1;
3187 pSMB
->Reserved3
= 0;
3188 pSMB
->SubCommand
= cpu_to_le16(TRANS2_QUERY_FS_INFORMATION
);
3189 pSMB
->InformationLevel
= cpu_to_le16(SMB_QUERY_FS_DEVICE_INFO
);
3190 pSMB
->hdr
.smb_buf_length
+= byte_count
;
3191 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
3193 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
3194 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
3196 cFYI(1, ("Send error in QFSDeviceInfo = %d", rc
));
3197 } else { /* decode response */
3198 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
3200 if (rc
|| (pSMBr
->ByteCount
< sizeof (FILE_SYSTEM_DEVICE_INFO
)))
3201 rc
= -EIO
; /* bad smb */
3203 __u16 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
3205 (FILE_SYSTEM_DEVICE_INFO
*)
3206 (((char *) &pSMBr
->hdr
.Protocol
) +
3208 memcpy(&tcon
->fsDevInfo
, response_data
,
3209 sizeof (FILE_SYSTEM_DEVICE_INFO
));
3212 cifs_buf_release(pSMB
);
3215 goto QFSDeviceRetry
;
3221 CIFSSMBQFSUnixInfo(const int xid
, struct cifsTconInfo
*tcon
)
3223 /* level 0x200 SMB_QUERY_CIFS_UNIX_INFO */
3224 TRANSACTION2_QFSI_REQ
*pSMB
= NULL
;
3225 TRANSACTION2_QFSI_RSP
*pSMBr
= NULL
;
3226 FILE_SYSTEM_UNIX_INFO
*response_data
;
3228 int bytes_returned
= 0;
3229 __u16 params
, byte_count
;
3231 cFYI(1, ("In QFSUnixInfo"));
3233 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
3238 params
= 2; /* level */
3239 pSMB
->TotalDataCount
= 0;
3240 pSMB
->DataCount
= 0;
3241 pSMB
->DataOffset
= 0;
3242 pSMB
->MaxParameterCount
= cpu_to_le16(2);
3243 pSMB
->MaxDataCount
= cpu_to_le16(100); /* BB find exact max SMB PDU from sess structure BB */
3244 pSMB
->MaxSetupCount
= 0;
3248 pSMB
->Reserved2
= 0;
3249 byte_count
= params
+ 1 /* pad */ ;
3250 pSMB
->ParameterCount
= cpu_to_le16(params
);
3251 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
3252 pSMB
->ParameterOffset
= cpu_to_le16(offsetof(struct
3253 smb_com_transaction2_qfsi_req
, InformationLevel
) - 4);
3254 pSMB
->SetupCount
= 1;
3255 pSMB
->Reserved3
= 0;
3256 pSMB
->SubCommand
= cpu_to_le16(TRANS2_QUERY_FS_INFORMATION
);
3257 pSMB
->InformationLevel
= cpu_to_le16(SMB_QUERY_CIFS_UNIX_INFO
);
3258 pSMB
->hdr
.smb_buf_length
+= byte_count
;
3259 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
3261 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
3262 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
3264 cERROR(1, ("Send error in QFSUnixInfo = %d", rc
));
3265 } else { /* decode response */
3266 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
3268 if (rc
|| (pSMBr
->ByteCount
< 13)) {
3269 rc
= -EIO
; /* bad smb */
3271 __u16 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
3273 (FILE_SYSTEM_UNIX_INFO
3274 *) (((char *) &pSMBr
->hdr
.Protocol
) +
3276 memcpy(&tcon
->fsUnixInfo
, response_data
,
3277 sizeof (FILE_SYSTEM_UNIX_INFO
));
3280 cifs_buf_release(pSMB
);
3290 CIFSSMBSetFSUnixInfo(const int xid
, struct cifsTconInfo
*tcon
, __u64 cap
)
3292 /* level 0x200 SMB_SET_CIFS_UNIX_INFO */
3293 TRANSACTION2_SETFSI_REQ
*pSMB
= NULL
;
3294 TRANSACTION2_SETFSI_RSP
*pSMBr
= NULL
;
3296 int bytes_returned
= 0;
3297 __u16 params
, param_offset
, offset
, byte_count
;
3299 cFYI(1, ("In SETFSUnixInfo"));
3301 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
3306 params
= 4; /* 2 bytes zero followed by info level. */
3307 pSMB
->MaxSetupCount
= 0;
3311 pSMB
->Reserved2
= 0;
3312 param_offset
= offsetof(struct smb_com_transaction2_setfsi_req
, FileNum
) - 4;
3313 offset
= param_offset
+ params
;
3315 pSMB
->MaxParameterCount
= cpu_to_le16(4);
3316 pSMB
->MaxDataCount
= cpu_to_le16(100); /* BB find exact max SMB PDU from sess structure BB */
3317 pSMB
->SetupCount
= 1;
3318 pSMB
->Reserved3
= 0;
3319 pSMB
->SubCommand
= cpu_to_le16(TRANS2_SET_FS_INFORMATION
);
3320 byte_count
= 1 /* pad */ + params
+ 12;
3322 pSMB
->DataCount
= cpu_to_le16(12);
3323 pSMB
->ParameterCount
= cpu_to_le16(params
);
3324 pSMB
->TotalDataCount
= pSMB
->DataCount
;
3325 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
3326 pSMB
->ParameterOffset
= cpu_to_le16(param_offset
);
3327 pSMB
->DataOffset
= cpu_to_le16(offset
);
3331 pSMB
->InformationLevel
= cpu_to_le16(SMB_SET_CIFS_UNIX_INFO
);
3334 pSMB
->ClientUnixMajor
= cpu_to_le16(CIFS_UNIX_MAJOR_VERSION
);
3335 pSMB
->ClientUnixMinor
= cpu_to_le16(CIFS_UNIX_MINOR_VERSION
);
3336 pSMB
->ClientUnixCap
= cpu_to_le64(cap
);
3338 pSMB
->hdr
.smb_buf_length
+= byte_count
;
3339 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
3341 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
3342 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
3344 cERROR(1, ("Send error in SETFSUnixInfo = %d", rc
));
3345 } else { /* decode response */
3346 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
3348 rc
= -EIO
; /* bad smb */
3351 cifs_buf_release(pSMB
);
3354 goto SETFSUnixRetry
;
3362 CIFSSMBQFSPosixInfo(const int xid
, struct cifsTconInfo
*tcon
,
3363 struct kstatfs
*FSData
)
3365 /* level 0x201 SMB_QUERY_CIFS_POSIX_INFO */
3366 TRANSACTION2_QFSI_REQ
*pSMB
= NULL
;
3367 TRANSACTION2_QFSI_RSP
*pSMBr
= NULL
;
3368 FILE_SYSTEM_POSIX_INFO
*response_data
;
3370 int bytes_returned
= 0;
3371 __u16 params
, byte_count
;
3373 cFYI(1, ("In QFSPosixInfo"));
3375 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
3380 params
= 2; /* level */
3381 pSMB
->TotalDataCount
= 0;
3382 pSMB
->DataCount
= 0;
3383 pSMB
->DataOffset
= 0;
3384 pSMB
->MaxParameterCount
= cpu_to_le16(2);
3385 pSMB
->MaxDataCount
= cpu_to_le16(100); /* BB find exact max SMB PDU from sess structure BB */
3386 pSMB
->MaxSetupCount
= 0;
3390 pSMB
->Reserved2
= 0;
3391 byte_count
= params
+ 1 /* pad */ ;
3392 pSMB
->ParameterCount
= cpu_to_le16(params
);
3393 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
3394 pSMB
->ParameterOffset
= cpu_to_le16(offsetof(struct
3395 smb_com_transaction2_qfsi_req
, InformationLevel
) - 4);
3396 pSMB
->SetupCount
= 1;
3397 pSMB
->Reserved3
= 0;
3398 pSMB
->SubCommand
= cpu_to_le16(TRANS2_QUERY_FS_INFORMATION
);
3399 pSMB
->InformationLevel
= cpu_to_le16(SMB_QUERY_POSIX_FS_INFO
);
3400 pSMB
->hdr
.smb_buf_length
+= byte_count
;
3401 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
3403 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
3404 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
3406 cFYI(1, ("Send error in QFSUnixInfo = %d", rc
));
3407 } else { /* decode response */
3408 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
3410 if (rc
|| (pSMBr
->ByteCount
< 13)) {
3411 rc
= -EIO
; /* bad smb */
3413 __u16 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
3415 (FILE_SYSTEM_POSIX_INFO
3416 *) (((char *) &pSMBr
->hdr
.Protocol
) +
3419 le32_to_cpu(response_data
->BlockSize
);
3421 le64_to_cpu(response_data
->TotalBlocks
);
3423 le64_to_cpu(response_data
->BlocksAvail
);
3424 if(response_data
->UserBlocksAvail
== -1) {
3425 FSData
->f_bavail
= FSData
->f_bfree
;
3428 le64_to_cpu(response_data
->UserBlocksAvail
);
3430 if(response_data
->TotalFileNodes
!= -1)
3432 le64_to_cpu(response_data
->TotalFileNodes
);
3433 if(response_data
->FreeFileNodes
!= -1)
3435 le64_to_cpu(response_data
->FreeFileNodes
);
3438 cifs_buf_release(pSMB
);
3447 /* We can not use write of zero bytes trick to
3448 set file size due to need for large file support. Also note that
3449 this SetPathInfo is preferred to SetFileInfo based method in next
3450 routine which is only needed to work around a sharing violation bug
3451 in Samba which this routine can run into */
3454 CIFSSMBSetEOF(const int xid
, struct cifsTconInfo
*tcon
, const char *fileName
,
3455 __u64 size
, int SetAllocation
,
3456 const struct nls_table
*nls_codepage
, int remap
)
3458 struct smb_com_transaction2_spi_req
*pSMB
= NULL
;
3459 struct smb_com_transaction2_spi_rsp
*pSMBr
= NULL
;
3460 struct file_end_of_file_info
*parm_data
;
3463 int bytes_returned
= 0;
3464 __u16 params
, byte_count
, data_count
, param_offset
, offset
;
3466 cFYI(1, ("In SetEOF"));
3468 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
3473 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
3475 cifsConvertToUCS((__le16
*) pSMB
->FileName
, fileName
,
3476 PATH_MAX
, nls_codepage
, remap
);
3477 name_len
++; /* trailing null */
3479 } else { /* BB improve the check for buffer overruns BB */
3480 name_len
= strnlen(fileName
, PATH_MAX
);
3481 name_len
++; /* trailing null */
3482 strncpy(pSMB
->FileName
, fileName
, name_len
);
3484 params
= 6 + name_len
;
3485 data_count
= sizeof (struct file_end_of_file_info
);
3486 pSMB
->MaxParameterCount
= cpu_to_le16(2);
3487 pSMB
->MaxDataCount
= cpu_to_le16(1000); /* BB find max SMB size from sess */
3488 pSMB
->MaxSetupCount
= 0;
3492 pSMB
->Reserved2
= 0;
3493 param_offset
= offsetof(struct smb_com_transaction2_spi_req
,
3494 InformationLevel
) - 4;
3495 offset
= param_offset
+ params
;
3497 if (tcon
->ses
->capabilities
& CAP_INFOLEVEL_PASSTHRU
)
3498 pSMB
->InformationLevel
=
3499 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2
);
3501 pSMB
->InformationLevel
=
3502 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO
);
3503 } else /* Set File Size */ {
3504 if (tcon
->ses
->capabilities
& CAP_INFOLEVEL_PASSTHRU
)
3505 pSMB
->InformationLevel
=
3506 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO2
);
3508 pSMB
->InformationLevel
=
3509 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO
);
3513 (struct file_end_of_file_info
*) (((char *) &pSMB
->hdr
.Protocol
) +
3515 pSMB
->ParameterOffset
= cpu_to_le16(param_offset
);
3516 pSMB
->DataOffset
= cpu_to_le16(offset
);
3517 pSMB
->SetupCount
= 1;
3518 pSMB
->Reserved3
= 0;
3519 pSMB
->SubCommand
= cpu_to_le16(TRANS2_SET_PATH_INFORMATION
);
3520 byte_count
= 3 /* pad */ + params
+ data_count
;
3521 pSMB
->DataCount
= cpu_to_le16(data_count
);
3522 pSMB
->TotalDataCount
= pSMB
->DataCount
;
3523 pSMB
->ParameterCount
= cpu_to_le16(params
);
3524 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
3525 pSMB
->Reserved4
= 0;
3526 pSMB
->hdr
.smb_buf_length
+= byte_count
;
3527 parm_data
->FileSize
= cpu_to_le64(size
);
3528 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, ("SetPathInfo (file size) returned %d", rc
));
3535 cifs_buf_release(pSMB
);
3544 CIFSSMBSetFileSize(const int xid
, struct cifsTconInfo
*tcon
, __u64 size
,
3545 __u16 fid
, __u32 pid_of_opener
, int SetAllocation
)
3547 struct smb_com_transaction2_sfi_req
*pSMB
= NULL
;
3548 struct smb_com_transaction2_sfi_rsp
*pSMBr
= NULL
;
3550 struct file_end_of_file_info
*parm_data
;
3552 int bytes_returned
= 0;
3553 __u16 params
, param_offset
, offset
, byte_count
, count
;
3555 cFYI(1, ("SetFileSize (via SetFileInfo) %lld",
3557 rc
= small_smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
);
3562 pSMBr
= (struct smb_com_transaction2_sfi_rsp
*)pSMB
;
3564 pSMB
->hdr
.Pid
= cpu_to_le16((__u16
)pid_of_opener
);
3565 pSMB
->hdr
.PidHigh
= cpu_to_le16((__u16
)(pid_of_opener
>> 16));
3568 pSMB
->MaxSetupCount
= 0;
3572 pSMB
->Reserved2
= 0;
3573 param_offset
= offsetof(struct smb_com_transaction2_sfi_req
, Fid
) - 4;
3574 offset
= param_offset
+ params
;
3576 data_offset
= (char *) (&pSMB
->hdr
.Protocol
) + offset
;
3578 count
= sizeof(struct file_end_of_file_info
);
3579 pSMB
->MaxParameterCount
= cpu_to_le16(2);
3580 pSMB
->MaxDataCount
= cpu_to_le16(1000); /* BB find max SMB PDU from sess */
3581 pSMB
->SetupCount
= 1;
3582 pSMB
->Reserved3
= 0;
3583 pSMB
->SubCommand
= cpu_to_le16(TRANS2_SET_FILE_INFORMATION
);
3584 byte_count
= 3 /* pad */ + params
+ count
;
3585 pSMB
->DataCount
= cpu_to_le16(count
);
3586 pSMB
->ParameterCount
= cpu_to_le16(params
);
3587 pSMB
->TotalDataCount
= pSMB
->DataCount
;
3588 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
3589 pSMB
->ParameterOffset
= cpu_to_le16(param_offset
);
3591 (struct file_end_of_file_info
*) (((char *) &pSMB
->hdr
.Protocol
) +
3593 pSMB
->DataOffset
= cpu_to_le16(offset
);
3594 parm_data
->FileSize
= cpu_to_le64(size
);
3597 if (tcon
->ses
->capabilities
& CAP_INFOLEVEL_PASSTHRU
)
3598 pSMB
->InformationLevel
=
3599 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2
);
3601 pSMB
->InformationLevel
=
3602 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO
);
3603 } else /* Set File Size */ {
3604 if (tcon
->ses
->capabilities
& CAP_INFOLEVEL_PASSTHRU
)
3605 pSMB
->InformationLevel
=
3606 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO2
);
3608 pSMB
->InformationLevel
=
3609 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO
);
3611 pSMB
->Reserved4
= 0;
3612 pSMB
->hdr
.smb_buf_length
+= byte_count
;
3613 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
3614 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
3615 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
3618 ("Send error in SetFileInfo (SetFileSize) = %d",
3623 cifs_small_buf_release(pSMB
);
3625 /* Note: On -EAGAIN error only caller can retry on handle based calls
3626 since file handle passed in no longer valid */
3631 /* Some legacy servers such as NT4 require that the file times be set on
3632 an open handle, rather than by pathname - this is awkward due to
3633 potential access conflicts on the open, but it is unavoidable for these
3634 old servers since the only other choice is to go from 100 nanosecond DCE
3635 time and resort to the original setpathinfo level which takes the ancient
3636 DOS time format with 2 second granularity */
3638 CIFSSMBSetFileTimes(const int xid
, struct cifsTconInfo
*tcon
, const FILE_BASIC_INFO
* data
,
3641 struct smb_com_transaction2_sfi_req
*pSMB
= NULL
;
3642 struct smb_com_transaction2_sfi_rsp
*pSMBr
= NULL
;
3645 int bytes_returned
= 0;
3646 __u16 params
, param_offset
, offset
, byte_count
, count
;
3648 cFYI(1, ("Set Times (via SetFileInfo)"));
3649 rc
= small_smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
);
3654 pSMBr
= (struct smb_com_transaction2_sfi_rsp
*)pSMB
;
3656 /* At this point there is no need to override the current pid
3657 with the pid of the opener, but that could change if we someday
3658 use an existing handle (rather than opening one on the fly) */
3659 /* pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
3660 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));*/
3663 pSMB
->MaxSetupCount
= 0;
3667 pSMB
->Reserved2
= 0;
3668 param_offset
= offsetof(struct smb_com_transaction2_sfi_req
, Fid
) - 4;
3669 offset
= param_offset
+ params
;
3671 data_offset
= (char *) (&pSMB
->hdr
.Protocol
) + offset
;
3673 count
= sizeof (FILE_BASIC_INFO
);
3674 pSMB
->MaxParameterCount
= cpu_to_le16(2);
3675 pSMB
->MaxDataCount
= cpu_to_le16(1000); /* BB find max SMB PDU from sess */
3676 pSMB
->SetupCount
= 1;
3677 pSMB
->Reserved3
= 0;
3678 pSMB
->SubCommand
= cpu_to_le16(TRANS2_SET_FILE_INFORMATION
);
3679 byte_count
= 3 /* pad */ + params
+ count
;
3680 pSMB
->DataCount
= cpu_to_le16(count
);
3681 pSMB
->ParameterCount
= cpu_to_le16(params
);
3682 pSMB
->TotalDataCount
= pSMB
->DataCount
;
3683 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
3684 pSMB
->ParameterOffset
= cpu_to_le16(param_offset
);
3685 pSMB
->DataOffset
= cpu_to_le16(offset
);
3687 if (tcon
->ses
->capabilities
& CAP_INFOLEVEL_PASSTHRU
)
3688 pSMB
->InformationLevel
= cpu_to_le16(SMB_SET_FILE_BASIC_INFO2
);
3690 pSMB
->InformationLevel
= cpu_to_le16(SMB_SET_FILE_BASIC_INFO
);
3691 pSMB
->Reserved4
= 0;
3692 pSMB
->hdr
.smb_buf_length
+= byte_count
;
3693 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
3694 memcpy(data_offset
,data
,sizeof(FILE_BASIC_INFO
));
3695 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
3696 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
3698 cFYI(1,("Send error in Set Time (SetFileInfo) = %d",rc
));
3701 cifs_small_buf_release(pSMB
);
3703 /* Note: On -EAGAIN error only caller can retry on handle based calls
3704 since file handle passed in no longer valid */
3711 CIFSSMBSetTimes(const int xid
, struct cifsTconInfo
*tcon
, const char *fileName
,
3712 const FILE_BASIC_INFO
* data
,
3713 const struct nls_table
*nls_codepage
, int remap
)
3715 TRANSACTION2_SPI_REQ
*pSMB
= NULL
;
3716 TRANSACTION2_SPI_RSP
*pSMBr
= NULL
;
3719 int bytes_returned
= 0;
3721 __u16 params
, param_offset
, offset
, byte_count
, count
;
3723 cFYI(1, ("In SetTimes"));
3726 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
3731 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
3733 cifsConvertToUCS((__le16
*) pSMB
->FileName
, fileName
,
3734 PATH_MAX
, nls_codepage
, remap
);
3735 name_len
++; /* trailing null */
3737 } else { /* BB improve the check for buffer overruns BB */
3738 name_len
= strnlen(fileName
, PATH_MAX
);
3739 name_len
++; /* trailing null */
3740 strncpy(pSMB
->FileName
, fileName
, name_len
);
3743 params
= 6 + name_len
;
3744 count
= sizeof (FILE_BASIC_INFO
);
3745 pSMB
->MaxParameterCount
= cpu_to_le16(2);
3746 pSMB
->MaxDataCount
= cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
3747 pSMB
->MaxSetupCount
= 0;
3751 pSMB
->Reserved2
= 0;
3752 param_offset
= offsetof(struct smb_com_transaction2_spi_req
,
3753 InformationLevel
) - 4;
3754 offset
= param_offset
+ params
;
3755 data_offset
= (char *) (&pSMB
->hdr
.Protocol
) + offset
;
3756 pSMB
->ParameterOffset
= cpu_to_le16(param_offset
);
3757 pSMB
->DataOffset
= cpu_to_le16(offset
);
3758 pSMB
->SetupCount
= 1;
3759 pSMB
->Reserved3
= 0;
3760 pSMB
->SubCommand
= cpu_to_le16(TRANS2_SET_PATH_INFORMATION
);
3761 byte_count
= 3 /* pad */ + params
+ count
;
3763 pSMB
->DataCount
= cpu_to_le16(count
);
3764 pSMB
->ParameterCount
= cpu_to_le16(params
);
3765 pSMB
->TotalDataCount
= pSMB
->DataCount
;
3766 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
3767 if (tcon
->ses
->capabilities
& CAP_INFOLEVEL_PASSTHRU
)
3768 pSMB
->InformationLevel
= cpu_to_le16(SMB_SET_FILE_BASIC_INFO2
);
3770 pSMB
->InformationLevel
= cpu_to_le16(SMB_SET_FILE_BASIC_INFO
);
3771 pSMB
->Reserved4
= 0;
3772 pSMB
->hdr
.smb_buf_length
+= byte_count
;
3773 memcpy(data_offset
, data
, sizeof (FILE_BASIC_INFO
));
3774 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
3775 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
3776 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
3778 cFYI(1, ("SetPathInfo (times) returned %d", rc
));
3781 cifs_buf_release(pSMB
);
3789 /* Can not be used to set time stamps yet (due to old DOS time format) */
3790 /* Can be used to set attributes */
3791 #if 0 /* Possibly not needed - since it turns out that strangely NT4 has a bug
3792 handling it anyway and NT4 was what we thought it would be needed for
3793 Do not delete it until we prove whether needed for Win9x though */
3795 CIFSSMBSetAttrLegacy(int xid
, struct cifsTconInfo
*tcon
, char *fileName
,
3796 __u16 dos_attrs
, const struct nls_table
*nls_codepage
)
3798 SETATTR_REQ
*pSMB
= NULL
;
3799 SETATTR_RSP
*pSMBr
= NULL
;
3804 cFYI(1, ("In SetAttrLegacy"));
3807 rc
= smb_init(SMB_COM_SETATTR
, 8, tcon
, (void **) &pSMB
,
3812 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
3814 ConvertToUCS((__le16
*) pSMB
->fileName
, fileName
,
3815 PATH_MAX
, nls_codepage
);
3816 name_len
++; /* trailing null */
3818 } else { /* BB improve the check for buffer overruns BB */
3819 name_len
= strnlen(fileName
, PATH_MAX
);
3820 name_len
++; /* trailing null */
3821 strncpy(pSMB
->fileName
, fileName
, name_len
);
3823 pSMB
->attr
= cpu_to_le16(dos_attrs
);
3824 pSMB
->BufferFormat
= 0x04;
3825 pSMB
->hdr
.smb_buf_length
+= name_len
+ 1;
3826 pSMB
->ByteCount
= cpu_to_le16(name_len
+ 1);
3827 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
3828 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
3830 cFYI(1, ("Error in LegacySetAttr = %d", rc
));
3833 cifs_buf_release(pSMB
);
3836 goto SetAttrLgcyRetry
;
3840 #endif /* temporarily unneeded SetAttr legacy function */
3843 CIFSSMBUnixSetPerms(const int xid
, struct cifsTconInfo
*tcon
,
3844 char *fileName
, __u64 mode
, __u64 uid
, __u64 gid
,
3845 dev_t device
, const struct nls_table
*nls_codepage
,
3848 TRANSACTION2_SPI_REQ
*pSMB
= NULL
;
3849 TRANSACTION2_SPI_RSP
*pSMBr
= NULL
;
3852 int bytes_returned
= 0;
3853 FILE_UNIX_BASIC_INFO
*data_offset
;
3854 __u16 params
, param_offset
, offset
, count
, byte_count
;
3856 cFYI(1, ("In SetUID/GID/Mode"));
3858 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
3863 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
3865 cifsConvertToUCS((__le16
*) pSMB
->FileName
, fileName
,
3866 PATH_MAX
, nls_codepage
, remap
);
3867 name_len
++; /* trailing null */
3869 } else { /* BB improve the check for buffer overruns BB */
3870 name_len
= strnlen(fileName
, PATH_MAX
);
3871 name_len
++; /* trailing null */
3872 strncpy(pSMB
->FileName
, fileName
, name_len
);
3875 params
= 6 + name_len
;
3876 count
= sizeof (FILE_UNIX_BASIC_INFO
);
3877 pSMB
->MaxParameterCount
= cpu_to_le16(2);
3878 pSMB
->MaxDataCount
= cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
3879 pSMB
->MaxSetupCount
= 0;
3883 pSMB
->Reserved2
= 0;
3884 param_offset
= offsetof(struct smb_com_transaction2_spi_req
,
3885 InformationLevel
) - 4;
3886 offset
= param_offset
+ params
;
3888 (FILE_UNIX_BASIC_INFO
*) ((char *) &pSMB
->hdr
.Protocol
+
3890 memset(data_offset
, 0, count
);
3891 pSMB
->DataOffset
= cpu_to_le16(offset
);
3892 pSMB
->ParameterOffset
= cpu_to_le16(param_offset
);
3893 pSMB
->SetupCount
= 1;
3894 pSMB
->Reserved3
= 0;
3895 pSMB
->SubCommand
= cpu_to_le16(TRANS2_SET_PATH_INFORMATION
);
3896 byte_count
= 3 /* pad */ + params
+ count
;
3897 pSMB
->ParameterCount
= cpu_to_le16(params
);
3898 pSMB
->DataCount
= cpu_to_le16(count
);
3899 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
3900 pSMB
->TotalDataCount
= pSMB
->DataCount
;
3901 pSMB
->InformationLevel
= cpu_to_le16(SMB_SET_FILE_UNIX_BASIC
);
3902 pSMB
->Reserved4
= 0;
3903 pSMB
->hdr
.smb_buf_length
+= byte_count
;
3904 data_offset
->Uid
= cpu_to_le64(uid
);
3905 data_offset
->Gid
= cpu_to_le64(gid
);
3906 /* better to leave device as zero when it is */
3907 data_offset
->DevMajor
= cpu_to_le64(MAJOR(device
));
3908 data_offset
->DevMinor
= cpu_to_le64(MINOR(device
));
3909 data_offset
->Permissions
= cpu_to_le64(mode
);
3912 data_offset
->Type
= cpu_to_le32(UNIX_FILE
);
3913 else if(S_ISDIR(mode
))
3914 data_offset
->Type
= cpu_to_le32(UNIX_DIR
);
3915 else if(S_ISLNK(mode
))
3916 data_offset
->Type
= cpu_to_le32(UNIX_SYMLINK
);
3917 else if(S_ISCHR(mode
))
3918 data_offset
->Type
= cpu_to_le32(UNIX_CHARDEV
);
3919 else if(S_ISBLK(mode
))
3920 data_offset
->Type
= cpu_to_le32(UNIX_BLOCKDEV
);
3921 else if(S_ISFIFO(mode
))
3922 data_offset
->Type
= cpu_to_le32(UNIX_FIFO
);
3923 else if(S_ISSOCK(mode
))
3924 data_offset
->Type
= cpu_to_le32(UNIX_SOCKET
);
3927 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
3928 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
3929 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
3931 cFYI(1, ("SetPathInfo (perms) returned %d", rc
));
3935 cifs_buf_release(pSMB
);
3941 int CIFSSMBNotify(const int xid
, struct cifsTconInfo
*tcon
,
3942 const int notify_subdirs
, const __u16 netfid
,
3943 __u32 filter
, const struct nls_table
*nls_codepage
)
3946 struct smb_com_transaction_change_notify_req
* pSMB
= NULL
;
3947 struct smb_com_transaction_change_notify_rsp
* pSMBr
= NULL
;
3950 cFYI(1, ("In CIFSSMBNotify for file handle %d",(int)netfid
));
3951 rc
= smb_init(SMB_COM_NT_TRANSACT
, 23, tcon
, (void **) &pSMB
,
3956 pSMB
->TotalParameterCount
= 0 ;
3957 pSMB
->TotalDataCount
= 0;
3958 pSMB
->MaxParameterCount
= cpu_to_le32(2);
3959 /* BB find exact data count max from sess structure BB */
3960 pSMB
->MaxDataCount
= 0; /* same in little endian or be */
3961 pSMB
->MaxSetupCount
= 4;
3963 pSMB
->ParameterOffset
= 0;
3964 pSMB
->DataCount
= 0;
3965 pSMB
->DataOffset
= 0;
3966 pSMB
->SetupCount
= 4; /* single byte does not need le conversion */
3967 pSMB
->SubCommand
= cpu_to_le16(NT_TRANSACT_NOTIFY_CHANGE
);
3968 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
3970 pSMB
->WatchTree
= 1; /* one byte - no le conversion needed */
3971 pSMB
->Reserved2
= 0;
3972 pSMB
->CompletionFilter
= cpu_to_le32(filter
);
3973 pSMB
->Fid
= netfid
; /* file handle always le */
3974 pSMB
->ByteCount
= 0;
3976 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
3977 (struct smb_hdr
*) pSMBr
, &bytes_returned
, -1);
3979 cFYI(1, ("Error in Notify = %d", rc
));
3981 cifs_buf_release(pSMB
);
3984 #ifdef CONFIG_CIFS_XATTR
3986 CIFSSMBQAllEAs(const int xid
, struct cifsTconInfo
*tcon
,
3987 const unsigned char *searchName
,
3988 char * EAData
, size_t buf_size
,
3989 const struct nls_table
*nls_codepage
, int remap
)
3991 /* BB assumes one setup word */
3992 TRANSACTION2_QPI_REQ
*pSMB
= NULL
;
3993 TRANSACTION2_QPI_RSP
*pSMBr
= NULL
;
3997 struct fea
* temp_fea
;
3999 __u16 params
, byte_count
;
4001 cFYI(1, ("In Query All EAs path %s", searchName
));
4003 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
4008 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
4010 cifsConvertToUCS((__le16
*) pSMB
->FileName
, searchName
,
4011 PATH_MAX
, nls_codepage
, remap
);
4012 name_len
++; /* trailing null */
4014 } else { /* BB improve the check for buffer overruns BB */
4015 name_len
= strnlen(searchName
, PATH_MAX
);
4016 name_len
++; /* trailing null */
4017 strncpy(pSMB
->FileName
, searchName
, name_len
);
4020 params
= 2 /* level */ + 4 /* reserved */ + name_len
/* includes NUL */ ;
4021 pSMB
->TotalDataCount
= 0;
4022 pSMB
->MaxParameterCount
= cpu_to_le16(2);
4023 pSMB
->MaxDataCount
= cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
4024 pSMB
->MaxSetupCount
= 0;
4028 pSMB
->Reserved2
= 0;
4029 pSMB
->ParameterOffset
= cpu_to_le16(offsetof(
4030 struct smb_com_transaction2_qpi_req
,InformationLevel
) - 4);
4031 pSMB
->DataCount
= 0;
4032 pSMB
->DataOffset
= 0;
4033 pSMB
->SetupCount
= 1;
4034 pSMB
->Reserved3
= 0;
4035 pSMB
->SubCommand
= cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION
);
4036 byte_count
= params
+ 1 /* pad */ ;
4037 pSMB
->TotalParameterCount
= cpu_to_le16(params
);
4038 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
4039 pSMB
->InformationLevel
= cpu_to_le16(SMB_INFO_QUERY_ALL_EAS
);
4040 pSMB
->Reserved4
= 0;
4041 pSMB
->hdr
.smb_buf_length
+= byte_count
;
4042 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
4044 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
4045 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
4047 cFYI(1, ("Send error in QueryAllEAs = %d", rc
));
4048 } else { /* decode response */
4049 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
4051 /* BB also check enough total bytes returned */
4052 /* BB we need to improve the validity checking
4053 of these trans2 responses */
4054 if (rc
|| (pSMBr
->ByteCount
< 4))
4055 rc
= -EIO
; /* bad smb */
4056 /* else if (pFindData){
4057 memcpy((char *) pFindData,
4058 (char *) &pSMBr->hdr.Protocol +
4061 /* check that length of list is not more than bcc */
4062 /* check that each entry does not go beyond length
4064 /* check that each element of each entry does not
4065 go beyond end of list */
4066 __u16 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
4067 struct fealist
* ea_response_data
;
4069 /* validate_trans2_offsets() */
4070 /* BB to check if(start of smb + data_offset > &bcc+ bcc)*/
4071 ea_response_data
= (struct fealist
*)
4072 (((char *) &pSMBr
->hdr
.Protocol
) +
4074 name_len
= le32_to_cpu(ea_response_data
->list_len
);
4075 cFYI(1,("ea length %d", name_len
));
4077 /* returned EA size zeroed at top of function */
4078 cFYI(1,("empty EA list returned from server"));
4080 /* account for ea list len */
4082 temp_fea
= ea_response_data
->list
;
4083 temp_ptr
= (char *)temp_fea
;
4084 while(name_len
> 0) {
4088 rc
+= temp_fea
->name_len
;
4089 /* account for prefix user. and trailing null */
4091 if(rc
<(int)buf_size
) {
4092 memcpy(EAData
,"user.",5);
4094 memcpy(EAData
,temp_ptr
,temp_fea
->name_len
);
4095 EAData
+=temp_fea
->name_len
;
4096 /* null terminate name */
4098 EAData
= EAData
+ 1;
4099 } else if(buf_size
== 0) {
4100 /* skip copy - calc size only */
4102 /* stop before overrun buffer */
4106 name_len
-= temp_fea
->name_len
;
4107 temp_ptr
+= temp_fea
->name_len
;
4108 /* account for trailing null */
4111 value_len
= le16_to_cpu(temp_fea
->value_len
);
4112 name_len
-= value_len
;
4113 temp_ptr
+= value_len
;
4114 /* BB check that temp_ptr is still within smb BB*/
4115 /* no trailing null to account for in value len */
4116 /* go on to next EA */
4117 temp_fea
= (struct fea
*)temp_ptr
;
4123 cifs_buf_release(pSMB
);
4130 ssize_t
CIFSSMBQueryEA(const int xid
,struct cifsTconInfo
* tcon
,
4131 const unsigned char * searchName
,const unsigned char * ea_name
,
4132 unsigned char * ea_value
, size_t buf_size
,
4133 const struct nls_table
*nls_codepage
, int remap
)
4135 TRANSACTION2_QPI_REQ
*pSMB
= NULL
;
4136 TRANSACTION2_QPI_RSP
*pSMBr
= NULL
;
4140 struct fea
* temp_fea
;
4142 __u16 params
, byte_count
;
4144 cFYI(1, ("In Query EA path %s", searchName
));
4146 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
4151 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
4153 cifsConvertToUCS((__le16
*) pSMB
->FileName
, searchName
,
4154 PATH_MAX
, nls_codepage
, remap
);
4155 name_len
++; /* trailing null */
4157 } else { /* BB improve the check for buffer overruns BB */
4158 name_len
= strnlen(searchName
, PATH_MAX
);
4159 name_len
++; /* trailing null */
4160 strncpy(pSMB
->FileName
, searchName
, name_len
);
4163 params
= 2 /* level */ + 4 /* reserved */ + name_len
/* includes NUL */ ;
4164 pSMB
->TotalDataCount
= 0;
4165 pSMB
->MaxParameterCount
= cpu_to_le16(2);
4166 pSMB
->MaxDataCount
= cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
4167 pSMB
->MaxSetupCount
= 0;
4171 pSMB
->Reserved2
= 0;
4172 pSMB
->ParameterOffset
= cpu_to_le16(offsetof(
4173 struct smb_com_transaction2_qpi_req
,InformationLevel
) - 4);
4174 pSMB
->DataCount
= 0;
4175 pSMB
->DataOffset
= 0;
4176 pSMB
->SetupCount
= 1;
4177 pSMB
->Reserved3
= 0;
4178 pSMB
->SubCommand
= cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION
);
4179 byte_count
= params
+ 1 /* pad */ ;
4180 pSMB
->TotalParameterCount
= cpu_to_le16(params
);
4181 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
4182 pSMB
->InformationLevel
= cpu_to_le16(SMB_INFO_QUERY_ALL_EAS
);
4183 pSMB
->Reserved4
= 0;
4184 pSMB
->hdr
.smb_buf_length
+= byte_count
;
4185 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
4187 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
4188 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
4190 cFYI(1, ("Send error in Query EA = %d", rc
));
4191 } else { /* decode response */
4192 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
4194 /* BB also check enough total bytes returned */
4195 /* BB we need to improve the validity checking
4196 of these trans2 responses */
4197 if (rc
|| (pSMBr
->ByteCount
< 4))
4198 rc
= -EIO
; /* bad smb */
4199 /* else if (pFindData){
4200 memcpy((char *) pFindData,
4201 (char *) &pSMBr->hdr.Protocol +
4204 /* check that length of list is not more than bcc */
4205 /* check that each entry does not go beyond length
4207 /* check that each element of each entry does not
4208 go beyond end of list */
4209 __u16 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
4210 struct fealist
* ea_response_data
;
4212 /* validate_trans2_offsets() */
4213 /* BB to check if(start of smb + data_offset > &bcc+ bcc)*/
4214 ea_response_data
= (struct fealist
*)
4215 (((char *) &pSMBr
->hdr
.Protocol
) +
4217 name_len
= le32_to_cpu(ea_response_data
->list_len
);
4218 cFYI(1,("ea length %d", name_len
));
4220 /* returned EA size zeroed at top of function */
4221 cFYI(1,("empty EA list returned from server"));
4223 /* account for ea list len */
4225 temp_fea
= ea_response_data
->list
;
4226 temp_ptr
= (char *)temp_fea
;
4227 /* loop through checking if we have a matching
4228 name and then return the associated value */
4229 while(name_len
> 0) {
4233 value_len
= le16_to_cpu(temp_fea
->value_len
);
4234 /* BB validate that value_len falls within SMB,
4235 even though maximum for name_len is 255 */
4236 if(memcmp(temp_fea
->name
,ea_name
,
4237 temp_fea
->name_len
) == 0) {
4240 /* account for prefix user. and trailing null */
4241 if(rc
<=(int)buf_size
) {
4243 temp_fea
->name
+temp_fea
->name_len
+1,
4245 /* ea values, unlike ea names,
4246 are not null terminated */
4247 } else if(buf_size
== 0) {
4248 /* skip copy - calc size only */
4250 /* stop before overrun buffer */
4255 name_len
-= temp_fea
->name_len
;
4256 temp_ptr
+= temp_fea
->name_len
;
4257 /* account for trailing null */
4260 name_len
-= value_len
;
4261 temp_ptr
+= value_len
;
4262 /* no trailing null to account for in value len */
4263 /* go on to next EA */
4264 temp_fea
= (struct fea
*)temp_ptr
;
4270 cifs_buf_release(pSMB
);
4278 CIFSSMBSetEA(const int xid
, struct cifsTconInfo
*tcon
, const char *fileName
,
4279 const char * ea_name
, const void * ea_value
,
4280 const __u16 ea_value_len
, const struct nls_table
*nls_codepage
,
4283 struct smb_com_transaction2_spi_req
*pSMB
= NULL
;
4284 struct smb_com_transaction2_spi_rsp
*pSMBr
= NULL
;
4285 struct fealist
*parm_data
;
4288 int bytes_returned
= 0;
4289 __u16 params
, param_offset
, byte_count
, offset
, count
;
4291 cFYI(1, ("In SetEA"));
4293 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
4298 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
4300 cifsConvertToUCS((__le16
*) pSMB
->FileName
, fileName
,
4301 PATH_MAX
, nls_codepage
, remap
);
4302 name_len
++; /* trailing null */
4304 } else { /* BB improve the check for buffer overruns BB */
4305 name_len
= strnlen(fileName
, PATH_MAX
);
4306 name_len
++; /* trailing null */
4307 strncpy(pSMB
->FileName
, fileName
, name_len
);
4310 params
= 6 + name_len
;
4312 /* done calculating parms using name_len of file name,
4313 now use name_len to calculate length of ea name
4314 we are going to create in the inode xattrs */
4318 name_len
= strnlen(ea_name
,255);
4320 count
= sizeof(*parm_data
) + ea_value_len
+ name_len
+ 1;
4321 pSMB
->MaxParameterCount
= cpu_to_le16(2);
4322 pSMB
->MaxDataCount
= cpu_to_le16(1000); /* BB find max SMB size from sess */
4323 pSMB
->MaxSetupCount
= 0;
4327 pSMB
->Reserved2
= 0;
4328 param_offset
= offsetof(struct smb_com_transaction2_spi_req
,
4329 InformationLevel
) - 4;
4330 offset
= param_offset
+ params
;
4331 pSMB
->InformationLevel
=
4332 cpu_to_le16(SMB_SET_FILE_EA
);
4335 (struct fealist
*) (((char *) &pSMB
->hdr
.Protocol
) +
4337 pSMB
->ParameterOffset
= cpu_to_le16(param_offset
);
4338 pSMB
->DataOffset
= cpu_to_le16(offset
);
4339 pSMB
->SetupCount
= 1;
4340 pSMB
->Reserved3
= 0;
4341 pSMB
->SubCommand
= cpu_to_le16(TRANS2_SET_PATH_INFORMATION
);
4342 byte_count
= 3 /* pad */ + params
+ count
;
4343 pSMB
->DataCount
= cpu_to_le16(count
);
4344 parm_data
->list_len
= cpu_to_le32(count
);
4345 parm_data
->list
[0].EA_flags
= 0;
4346 /* we checked above that name len is less than 255 */
4347 parm_data
->list
[0].name_len
= (__u8
)name_len
;;
4348 /* EA names are always ASCII */
4350 strncpy(parm_data
->list
[0].name
,ea_name
,name_len
);
4351 parm_data
->list
[0].name
[name_len
] = 0;
4352 parm_data
->list
[0].value_len
= cpu_to_le16(ea_value_len
);
4353 /* caller ensures that ea_value_len is less than 64K but
4354 we need to ensure that it fits within the smb */
4356 /*BB add length check that it would fit in negotiated SMB buffer size BB */
4357 /* if(ea_value_len > buffer_size - 512 (enough for header)) */
4359 memcpy(parm_data
->list
[0].name
+name_len
+1,ea_value
,ea_value_len
);
4361 pSMB
->TotalDataCount
= pSMB
->DataCount
;
4362 pSMB
->ParameterCount
= cpu_to_le16(params
);
4363 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
4364 pSMB
->Reserved4
= 0;
4365 pSMB
->hdr
.smb_buf_length
+= byte_count
;
4366 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
4367 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
4368 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
4370 cFYI(1, ("SetPathInfo (EA) returned %d", rc
));
4373 cifs_buf_release(pSMB
);