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 pSMB
->FileAttributes
= cpu_to_le32(ATTR_NORMAL
);
742 /* XP does not handle ATTR_POSIX_SEMANTICS */
743 /* but it helps speed up case sensitive checks for other
744 servers such as Samba */
745 if (tcon
->ses
->capabilities
& CAP_UNIX
)
746 pSMB
->FileAttributes
|= cpu_to_le32(ATTR_POSIX_SEMANTICS
);
748 /* if ((omode & S_IWUGO) == 0)
749 pSMB->FileAttributes |= cpu_to_le32(ATTR_READONLY);*/
750 /* Above line causes problems due to vfs splitting create into two
751 pieces - need to set mode after file created not while it is
753 pSMB
->ShareAccess
= cpu_to_le32(FILE_SHARE_ALL
);
754 pSMB
->CreateDisposition
= cpu_to_le32(openDisposition
);
755 pSMB
->CreateOptions
= cpu_to_le32(create_options
);
756 /* BB Expirement with various impersonation levels and verify */
757 pSMB
->ImpersonationLevel
= cpu_to_le32(SECURITY_IMPERSONATION
);
758 pSMB
->SecurityFlags
=
759 SECURITY_CONTEXT_TRACKING
| SECURITY_EFFECTIVE_ONLY
;
762 pSMB
->hdr
.smb_buf_length
+= count
;
764 pSMB
->ByteCount
= cpu_to_le16(count
);
765 /* long_op set to 1 to allow for oplock break timeouts */
766 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
767 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 1);
769 cFYI(1, ("Error in Open = %d", rc
));
771 *pOplock
= pSMBr
->OplockLevel
; /* 1 byte no need to le_to_cpu */
772 *netfid
= pSMBr
->Fid
; /* cifs fid stays in le */
773 /* Let caller know file was created so we can set the mode. */
774 /* Do we care about the CreateAction in any other cases? */
775 if(cpu_to_le32(FILE_CREATE
) == pSMBr
->CreateAction
)
776 *pOplock
|= CIFS_CREATE_ACTION
;
778 memcpy((char *)pfile_info
,(char *)&pSMBr
->CreationTime
,
779 36 /* CreationTime to Attributes */);
780 /* the file_info buf is endian converted by caller */
781 pfile_info
->AllocationSize
= pSMBr
->AllocationSize
;
782 pfile_info
->EndOfFile
= pSMBr
->EndOfFile
;
783 pfile_info
->NumberOfLinks
= cpu_to_le32(1);
786 #ifdef CONFIG_CIFS_STATS
787 atomic_inc(&tcon
->num_opens
);
790 cifs_buf_release(pSMB
);
796 /* If no buffer passed in, then caller wants to do the copy
797 as in the case of readpages so the SMB buffer must be
798 freed by the caller */
801 CIFSSMBRead(const int xid
, struct cifsTconInfo
*tcon
,
802 const int netfid
, const unsigned int count
,
803 const __u64 lseek
, unsigned int *nbytes
, char **buf
)
806 READ_REQ
*pSMB
= NULL
;
807 READ_RSP
*pSMBr
= NULL
;
808 char *pReadData
= NULL
;
811 cFYI(1,("Reading %d bytes on fid %d",count
,netfid
));
814 rc
= smb_init(SMB_COM_READ_ANDX
, 12, tcon
, (void **) &pSMB
,
819 /* tcon and ses pointer are checked in smb_init */
820 if (tcon
->ses
->server
== NULL
)
821 return -ECONNABORTED
;
823 pSMB
->AndXCommand
= 0xFF; /* none */
825 pSMB
->OffsetLow
= cpu_to_le32(lseek
& 0xFFFFFFFF);
826 pSMB
->OffsetHigh
= cpu_to_le32(lseek
>> 32);
828 pSMB
->MaxCount
= cpu_to_le16(count
& 0xFFFF);
829 pSMB
->MaxCountHigh
= cpu_to_le32(count
>> 16);
830 pSMB
->ByteCount
= 0; /* no need to do le conversion since it is 0 */
832 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
833 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
835 cERROR(1, ("Send error in read = %d", rc
));
837 int data_length
= le16_to_cpu(pSMBr
->DataLengthHigh
);
838 data_length
= data_length
<< 16;
839 data_length
+= le16_to_cpu(pSMBr
->DataLength
);
840 *nbytes
= data_length
;
842 /*check that DataLength would not go beyond end of SMB */
843 if ((data_length
> CIFSMaxBufSize
)
844 || (data_length
> count
)) {
845 cFYI(1,("bad length %d for count %d",data_length
,count
));
850 (char *) (&pSMBr
->hdr
.Protocol
) +
851 le16_to_cpu(pSMBr
->DataOffset
);
852 /* if(rc = copy_to_user(buf, pReadData, data_length)) {
853 cERROR(1,("Faulting on read rc = %d",rc));
855 }*/ /* can not use copy_to_user when using page cache*/
857 memcpy(*buf
,pReadData
,data_length
);
861 cifs_buf_release(pSMB
);
865 /* Note: On -EAGAIN error only caller can retry on handle based calls
866 since file handle passed in no longer valid */
871 CIFSSMBWrite(const int xid
, struct cifsTconInfo
*tcon
,
872 const int netfid
, const unsigned int count
,
873 const __u64 offset
, unsigned int *nbytes
, const char *buf
,
874 const char __user
* ubuf
, const int long_op
)
877 WRITE_REQ
*pSMB
= NULL
;
878 WRITE_RSP
*pSMBr
= NULL
;
883 /* cFYI(1,("write at %lld %d bytes",offset,count));*/
884 rc
= smb_init(SMB_COM_WRITE_ANDX
, 14, tcon
, (void **) &pSMB
,
888 /* tcon and ses pointer are checked in smb_init */
889 if (tcon
->ses
->server
== NULL
)
890 return -ECONNABORTED
;
892 pSMB
->AndXCommand
= 0xFF; /* none */
894 pSMB
->OffsetLow
= cpu_to_le32(offset
& 0xFFFFFFFF);
895 pSMB
->OffsetHigh
= cpu_to_le32(offset
>> 32);
896 pSMB
->Reserved
= 0xFFFFFFFF;
900 /* Can increase buffer size if buffer is big enough in some cases - ie we
901 can send more if LARGE_WRITE_X capability returned by the server and if
902 our buffer is big enough or if we convert to iovecs on socket writes
903 and eliminate the copy to the CIFS buffer */
904 if(tcon
->ses
->capabilities
& CAP_LARGE_WRITE_X
) {
905 bytes_sent
= min_t(const unsigned int, CIFSMaxBufSize
, count
);
907 bytes_sent
= (tcon
->ses
->server
->maxBuf
- MAX_CIFS_HDR_SIZE
)
911 if (bytes_sent
> count
)
914 cpu_to_le16(offsetof(struct smb_com_write_req
,Data
) - 4);
916 memcpy(pSMB
->Data
,buf
,bytes_sent
);
918 if(copy_from_user(pSMB
->Data
,ubuf
,bytes_sent
)) {
919 cifs_buf_release(pSMB
);
924 cifs_buf_release(pSMB
);
928 byte_count
= bytes_sent
+ 1 /* pad */ ; /* BB fix this for sends > 64K */
929 pSMB
->DataLengthLow
= cpu_to_le16(bytes_sent
& 0xFFFF);
930 pSMB
->DataLengthHigh
= cpu_to_le16(bytes_sent
>> 16);
931 pSMB
->hdr
.smb_buf_length
+= bytes_sent
+1;
932 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
934 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
935 (struct smb_hdr
*) pSMBr
, &bytes_returned
, long_op
);
937 cFYI(1, ("Send error in write = %d", rc
));
940 *nbytes
= le16_to_cpu(pSMBr
->CountHigh
);
941 *nbytes
= (*nbytes
) << 16;
942 *nbytes
+= le16_to_cpu(pSMBr
->Count
);
945 cifs_buf_release(pSMB
);
947 /* Note: On -EAGAIN error only caller can retry on handle based calls
948 since file handle passed in no longer valid */
953 #ifdef CONFIG_CIFS_EXPERIMENTAL
955 CIFSSMBWrite2(const int xid
, struct cifsTconInfo
*tcon
,
956 const int netfid
, const unsigned int count
,
957 const __u64 offset
, unsigned int *nbytes
, const char *buf
,
961 WRITE_REQ
*pSMB
= NULL
;
967 cERROR(1,("write2 at %lld %d bytes",offset
,count
)); /* BB removeme BB */
968 rc
= small_smb_init(SMB_COM_WRITE_ANDX
, 14, tcon
, (void **) &pSMB
);
971 /* tcon and ses pointer are checked in smb_init */
972 if (tcon
->ses
->server
== NULL
)
973 return -ECONNABORTED
;
975 pSMB
->AndXCommand
= 0xFF; /* none */
977 pSMB
->OffsetLow
= cpu_to_le32(offset
& 0xFFFFFFFF);
978 pSMB
->OffsetHigh
= cpu_to_le32(offset
>> 32);
979 pSMB
->Reserved
= 0xFFFFFFFF;
983 /* Can increase buffer size if buffer is big enough in some cases - ie
984 can send more if LARGE_WRITE_X capability returned by the server and if
985 our buffer is big enough or if we convert to iovecs on socket writes
986 and eliminate the copy to the CIFS buffer */
987 if(tcon
->ses
->capabilities
& CAP_LARGE_WRITE_X
) {
988 bytes_sent
= min_t(const unsigned int, CIFSMaxBufSize
, count
);
990 bytes_sent
= (tcon
->ses
->server
->maxBuf
- MAX_CIFS_HDR_SIZE
)
994 if (bytes_sent
> count
)
997 cpu_to_le16(offsetof(struct smb_com_write_req
,Data
) - 4);
999 byte_count
= bytes_sent
+ 1 /* pad */ ; /* BB fix this for sends > 64K */
1000 pSMB
->DataLengthLow
= cpu_to_le16(bytes_sent
& 0xFFFF);
1001 pSMB
->DataLengthHigh
= cpu_to_le16(bytes_sent
>> 16);
1002 smb_hdr_len
= pSMB
->hdr
.smb_buf_length
+ 1; /* hdr + 1 byte pad */
1003 pSMB
->hdr
.smb_buf_length
+= bytes_sent
+1;
1004 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
1006 rc
= SendReceive2(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
, smb_hdr_len
,
1007 buf
, bytes_sent
, &bytes_returned
, long_op
);
1009 cFYI(1, ("Send error in write = %d", rc
));
1012 WRITE_RSP
* pSMBr
= (WRITE_RSP
*)pSMB
;
1013 *nbytes
= le16_to_cpu(pSMBr
->CountHigh
);
1014 *nbytes
= (*nbytes
) << 16;
1015 *nbytes
+= le16_to_cpu(pSMBr
->Count
);
1018 cifs_small_buf_release(pSMB
);
1020 /* Note: On -EAGAIN error only caller can retry on handle based calls
1021 since file handle passed in no longer valid */
1027 #endif /* CIFS_EXPERIMENTAL */
1030 CIFSSMBLock(const int xid
, struct cifsTconInfo
*tcon
,
1031 const __u16 smb_file_id
, const __u64 len
,
1032 const __u64 offset
, const __u32 numUnlock
,
1033 const __u32 numLock
, const __u8 lockType
, const int waitFlag
)
1036 LOCK_REQ
*pSMB
= NULL
;
1037 LOCK_RSP
*pSMBr
= NULL
;
1042 cFYI(1, ("In CIFSSMBLock - timeout %d numLock %d",waitFlag
,numLock
));
1043 rc
= small_smb_init(SMB_COM_LOCKING_ANDX
, 8, tcon
, (void **) &pSMB
);
1048 pSMBr
= (LOCK_RSP
*)pSMB
; /* BB removeme BB */
1050 if(lockType
== LOCKING_ANDX_OPLOCK_RELEASE
) {
1051 timeout
= -1; /* no response expected */
1053 } else if (waitFlag
== TRUE
) {
1054 timeout
= 3; /* blocking operation, no timeout */
1055 pSMB
->Timeout
= cpu_to_le32(-1);/* blocking - do not time out */
1060 pSMB
->NumberOfLocks
= cpu_to_le16(numLock
);
1061 pSMB
->NumberOfUnlocks
= cpu_to_le16(numUnlock
);
1062 pSMB
->LockType
= lockType
;
1063 pSMB
->AndXCommand
= 0xFF; /* none */
1064 pSMB
->Fid
= smb_file_id
; /* netfid stays le */
1066 if((numLock
!= 0) || (numUnlock
!= 0)) {
1067 pSMB
->Locks
[0].Pid
= cpu_to_le16(current
->tgid
);
1068 /* BB where to store pid high? */
1069 pSMB
->Locks
[0].LengthLow
= cpu_to_le32((u32
)len
);
1070 pSMB
->Locks
[0].LengthHigh
= cpu_to_le32((u32
)(len
>>32));
1071 pSMB
->Locks
[0].OffsetLow
= cpu_to_le32((u32
)offset
);
1072 pSMB
->Locks
[0].OffsetHigh
= cpu_to_le32((u32
)(offset
>>32));
1073 count
= sizeof(LOCKING_ANDX_RANGE
);
1078 pSMB
->hdr
.smb_buf_length
+= count
;
1079 pSMB
->ByteCount
= cpu_to_le16(count
);
1081 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
1082 (struct smb_hdr
*) pSMBr
, &bytes_returned
, timeout
);
1085 cFYI(1, ("Send error in Lock = %d", rc
));
1087 cifs_small_buf_release(pSMB
);
1089 /* Note: On -EAGAIN error only caller can retry on handle based calls
1090 since file handle passed in no longer valid */
1095 CIFSSMBClose(const int xid
, struct cifsTconInfo
*tcon
, int smb_file_id
)
1098 CLOSE_REQ
*pSMB
= NULL
;
1099 CLOSE_RSP
*pSMBr
= NULL
;
1101 cFYI(1, ("In CIFSSMBClose"));
1103 /* do not retry on dead session on close */
1104 rc
= small_smb_init(SMB_COM_CLOSE
, 3, tcon
, (void **) &pSMB
);
1110 pSMBr
= (CLOSE_RSP
*)pSMB
; /* BB removeme BB */
1112 pSMB
->FileID
= (__u16
) smb_file_id
;
1113 pSMB
->LastWriteTime
= 0;
1114 pSMB
->ByteCount
= 0;
1115 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
1116 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
1119 /* EINTR is expected when user ctl-c to kill app */
1120 cERROR(1, ("Send error in Close = %d", rc
));
1124 cifs_small_buf_release(pSMB
);
1126 /* Since session is dead, file will be closed on server already */
1134 CIFSSMBRename(const int xid
, struct cifsTconInfo
*tcon
,
1135 const char *fromName
, const char *toName
,
1136 const struct nls_table
*nls_codepage
, int remap
)
1139 RENAME_REQ
*pSMB
= NULL
;
1140 RENAME_RSP
*pSMBr
= NULL
;
1142 int name_len
, name_len2
;
1145 cFYI(1, ("In CIFSSMBRename"));
1147 rc
= smb_init(SMB_COM_RENAME
, 1, tcon
, (void **) &pSMB
,
1152 pSMB
->BufferFormat
= 0x04;
1153 pSMB
->SearchAttributes
=
1154 cpu_to_le16(ATTR_READONLY
| ATTR_HIDDEN
| ATTR_SYSTEM
|
1157 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
1159 cifsConvertToUCS((__le16
*) pSMB
->OldFileName
, fromName
,
1160 PATH_MAX
, nls_codepage
, remap
);
1161 name_len
++; /* trailing null */
1163 pSMB
->OldFileName
[name_len
] = 0x04; /* pad */
1164 /* protocol requires ASCII signature byte on Unicode string */
1165 pSMB
->OldFileName
[name_len
+ 1] = 0x00;
1167 cifsConvertToUCS((__le16
*) &pSMB
->OldFileName
[name_len
+ 2],
1168 toName
, PATH_MAX
, nls_codepage
, remap
);
1169 name_len2
+= 1 /* trailing null */ + 1 /* Signature word */ ;
1170 name_len2
*= 2; /* convert to bytes */
1171 } else { /* BB improve the check for buffer overruns BB */
1172 name_len
= strnlen(fromName
, PATH_MAX
);
1173 name_len
++; /* trailing null */
1174 strncpy(pSMB
->OldFileName
, fromName
, name_len
);
1175 name_len2
= strnlen(toName
, PATH_MAX
);
1176 name_len2
++; /* trailing null */
1177 pSMB
->OldFileName
[name_len
] = 0x04; /* 2nd buffer format */
1178 strncpy(&pSMB
->OldFileName
[name_len
+ 1], toName
, name_len2
);
1179 name_len2
++; /* trailing null */
1180 name_len2
++; /* signature byte */
1183 count
= 1 /* 1st signature byte */ + name_len
+ name_len2
;
1184 pSMB
->hdr
.smb_buf_length
+= count
;
1185 pSMB
->ByteCount
= cpu_to_le16(count
);
1187 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
1188 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
1190 cFYI(1, ("Send error in rename = %d", rc
));
1193 #ifdef CONFIG_CIFS_STATS
1195 atomic_inc(&tcon
->num_renames
);
1199 cifs_buf_release(pSMB
);
1207 int CIFSSMBRenameOpenFile(const int xid
,struct cifsTconInfo
*pTcon
,
1208 int netfid
, char * target_name
,
1209 const struct nls_table
* nls_codepage
, int remap
)
1211 struct smb_com_transaction2_sfi_req
*pSMB
= NULL
;
1212 struct smb_com_transaction2_sfi_rsp
*pSMBr
= NULL
;
1213 struct set_file_rename
* rename_info
;
1215 char dummy_string
[30];
1217 int bytes_returned
= 0;
1219 __u16 params
, param_offset
, offset
, count
, byte_count
;
1221 cFYI(1, ("Rename to File by handle"));
1222 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, pTcon
, (void **) &pSMB
,
1228 pSMB
->MaxSetupCount
= 0;
1232 pSMB
->Reserved2
= 0;
1233 param_offset
= offsetof(struct smb_com_transaction2_sfi_req
, Fid
) - 4;
1234 offset
= param_offset
+ params
;
1236 data_offset
= (char *) (&pSMB
->hdr
.Protocol
) + offset
;
1237 rename_info
= (struct set_file_rename
*) data_offset
;
1238 pSMB
->MaxParameterCount
= cpu_to_le16(2);
1239 pSMB
->MaxDataCount
= cpu_to_le16(1000); /* BB find max SMB PDU from sess */
1240 pSMB
->SetupCount
= 1;
1241 pSMB
->Reserved3
= 0;
1242 pSMB
->SubCommand
= cpu_to_le16(TRANS2_SET_FILE_INFORMATION
);
1243 byte_count
= 3 /* pad */ + params
;
1244 pSMB
->ParameterCount
= cpu_to_le16(params
);
1245 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
1246 pSMB
->ParameterOffset
= cpu_to_le16(param_offset
);
1247 pSMB
->DataOffset
= cpu_to_le16(offset
);
1248 /* construct random name ".cifs_tmp<inodenum><mid>" */
1249 rename_info
->overwrite
= cpu_to_le32(1);
1250 rename_info
->root_fid
= 0;
1251 /* unicode only call */
1252 if(target_name
== NULL
) {
1253 sprintf(dummy_string
,"cifs%x",pSMB
->hdr
.Mid
);
1254 len_of_str
= cifsConvertToUCS((__le16
*)rename_info
->target_name
,
1255 dummy_string
, 24, nls_codepage
, remap
);
1257 len_of_str
= cifsConvertToUCS((__le16
*)rename_info
->target_name
,
1258 target_name
, PATH_MAX
, nls_codepage
, remap
);
1260 rename_info
->target_name_len
= cpu_to_le32(2 * len_of_str
);
1261 count
= 12 /* sizeof(struct set_file_rename) */ + (2 * len_of_str
) + 2;
1262 byte_count
+= count
;
1263 pSMB
->DataCount
= cpu_to_le16(count
);
1264 pSMB
->TotalDataCount
= pSMB
->DataCount
;
1266 pSMB
->InformationLevel
=
1267 cpu_to_le16(SMB_SET_FILE_RENAME_INFORMATION
);
1268 pSMB
->Reserved4
= 0;
1269 pSMB
->hdr
.smb_buf_length
+= byte_count
;
1270 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
1271 rc
= SendReceive(xid
, pTcon
->ses
, (struct smb_hdr
*) pSMB
,
1272 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
1274 cFYI(1,("Send error in Rename (by file handle) = %d", rc
));
1276 #ifdef CONFIG_CIFS_STATS
1278 atomic_inc(&pTcon
->num_t2renames
);
1281 cifs_buf_release(pSMB
);
1283 /* Note: On -EAGAIN error only caller can retry on handle based calls
1284 since file handle passed in no longer valid */
1290 CIFSSMBCopy(const int xid
, struct cifsTconInfo
*tcon
, const char * fromName
,
1291 const __u16 target_tid
, const char *toName
, const int flags
,
1292 const struct nls_table
*nls_codepage
, int remap
)
1295 COPY_REQ
*pSMB
= NULL
;
1296 COPY_RSP
*pSMBr
= NULL
;
1298 int name_len
, name_len2
;
1301 cFYI(1, ("In CIFSSMBCopy"));
1303 rc
= smb_init(SMB_COM_COPY
, 1, tcon
, (void **) &pSMB
,
1308 pSMB
->BufferFormat
= 0x04;
1309 pSMB
->Tid2
= target_tid
;
1311 pSMB
->Flags
= cpu_to_le16(flags
& COPY_TREE
);
1313 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
1314 name_len
= cifsConvertToUCS((__le16
*) pSMB
->OldFileName
,
1315 fromName
, PATH_MAX
, nls_codepage
,
1317 name_len
++; /* trailing null */
1319 pSMB
->OldFileName
[name_len
] = 0x04; /* pad */
1320 /* protocol requires ASCII signature byte on Unicode string */
1321 pSMB
->OldFileName
[name_len
+ 1] = 0x00;
1322 name_len2
= cifsConvertToUCS((__le16
*)&pSMB
->OldFileName
[name_len
+ 2],
1323 toName
, PATH_MAX
, nls_codepage
, remap
);
1324 name_len2
+= 1 /* trailing null */ + 1 /* Signature word */ ;
1325 name_len2
*= 2; /* convert to bytes */
1326 } else { /* BB improve the check for buffer overruns BB */
1327 name_len
= strnlen(fromName
, PATH_MAX
);
1328 name_len
++; /* trailing null */
1329 strncpy(pSMB
->OldFileName
, fromName
, name_len
);
1330 name_len2
= strnlen(toName
, PATH_MAX
);
1331 name_len2
++; /* trailing null */
1332 pSMB
->OldFileName
[name_len
] = 0x04; /* 2nd buffer format */
1333 strncpy(&pSMB
->OldFileName
[name_len
+ 1], toName
, name_len2
);
1334 name_len2
++; /* trailing null */
1335 name_len2
++; /* signature byte */
1338 count
= 1 /* 1st signature byte */ + name_len
+ name_len2
;
1339 pSMB
->hdr
.smb_buf_length
+= count
;
1340 pSMB
->ByteCount
= cpu_to_le16(count
);
1342 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
1343 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
1345 cFYI(1, ("Send error in copy = %d with %d files copied",
1346 rc
, le16_to_cpu(pSMBr
->CopyCount
)));
1349 cifs_buf_release(pSMB
);
1358 CIFSUnixCreateSymLink(const int xid
, struct cifsTconInfo
*tcon
,
1359 const char *fromName
, const char *toName
,
1360 const struct nls_table
*nls_codepage
)
1362 TRANSACTION2_SPI_REQ
*pSMB
= NULL
;
1363 TRANSACTION2_SPI_RSP
*pSMBr
= NULL
;
1366 int name_len_target
;
1368 int bytes_returned
= 0;
1369 __u16 params
, param_offset
, offset
, byte_count
;
1371 cFYI(1, ("In Symlink Unix style"));
1373 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
1378 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
1380 cifs_strtoUCS((wchar_t *) pSMB
->FileName
, fromName
, PATH_MAX
1381 /* find define for this maxpathcomponent */
1383 name_len
++; /* trailing null */
1386 } else { /* BB improve the check for buffer overruns BB */
1387 name_len
= strnlen(fromName
, PATH_MAX
);
1388 name_len
++; /* trailing null */
1389 strncpy(pSMB
->FileName
, fromName
, name_len
);
1391 params
= 6 + name_len
;
1392 pSMB
->MaxSetupCount
= 0;
1396 pSMB
->Reserved2
= 0;
1397 param_offset
= offsetof(struct smb_com_transaction2_spi_req
,
1398 InformationLevel
) - 4;
1399 offset
= param_offset
+ params
;
1401 data_offset
= (char *) (&pSMB
->hdr
.Protocol
) + offset
;
1402 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
1404 cifs_strtoUCS((wchar_t *) data_offset
, toName
, PATH_MAX
1405 /* find define for this maxpathcomponent */
1407 name_len_target
++; /* trailing null */
1408 name_len_target
*= 2;
1409 } else { /* BB improve the check for buffer overruns BB */
1410 name_len_target
= strnlen(toName
, PATH_MAX
);
1411 name_len_target
++; /* trailing null */
1412 strncpy(data_offset
, toName
, name_len_target
);
1415 pSMB
->MaxParameterCount
= cpu_to_le16(2);
1416 /* BB find exact max on data count below from sess */
1417 pSMB
->MaxDataCount
= cpu_to_le16(1000);
1418 pSMB
->SetupCount
= 1;
1419 pSMB
->Reserved3
= 0;
1420 pSMB
->SubCommand
= cpu_to_le16(TRANS2_SET_PATH_INFORMATION
);
1421 byte_count
= 3 /* pad */ + params
+ name_len_target
;
1422 pSMB
->DataCount
= cpu_to_le16(name_len_target
);
1423 pSMB
->ParameterCount
= cpu_to_le16(params
);
1424 pSMB
->TotalDataCount
= pSMB
->DataCount
;
1425 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
1426 pSMB
->ParameterOffset
= cpu_to_le16(param_offset
);
1427 pSMB
->DataOffset
= cpu_to_le16(offset
);
1428 pSMB
->InformationLevel
= cpu_to_le16(SMB_SET_FILE_UNIX_LINK
);
1429 pSMB
->Reserved4
= 0;
1430 pSMB
->hdr
.smb_buf_length
+= byte_count
;
1431 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
1432 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
1433 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
1436 ("Send error in SetPathInfo (create symlink) = %d",
1441 cifs_buf_release(pSMB
);
1444 goto createSymLinkRetry
;
1450 CIFSUnixCreateHardLink(const int xid
, struct cifsTconInfo
*tcon
,
1451 const char *fromName
, const char *toName
,
1452 const struct nls_table
*nls_codepage
, int remap
)
1454 TRANSACTION2_SPI_REQ
*pSMB
= NULL
;
1455 TRANSACTION2_SPI_RSP
*pSMBr
= NULL
;
1458 int name_len_target
;
1460 int bytes_returned
= 0;
1461 __u16 params
, param_offset
, offset
, byte_count
;
1463 cFYI(1, ("In Create Hard link Unix style"));
1464 createHardLinkRetry
:
1465 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
1470 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
1471 name_len
= cifsConvertToUCS((__le16
*) pSMB
->FileName
, toName
,
1472 PATH_MAX
, nls_codepage
, remap
);
1473 name_len
++; /* trailing null */
1476 } else { /* BB improve the check for buffer overruns BB */
1477 name_len
= strnlen(toName
, PATH_MAX
);
1478 name_len
++; /* trailing null */
1479 strncpy(pSMB
->FileName
, toName
, name_len
);
1481 params
= 6 + name_len
;
1482 pSMB
->MaxSetupCount
= 0;
1486 pSMB
->Reserved2
= 0;
1487 param_offset
= offsetof(struct smb_com_transaction2_spi_req
,
1488 InformationLevel
) - 4;
1489 offset
= param_offset
+ params
;
1491 data_offset
= (char *) (&pSMB
->hdr
.Protocol
) + offset
;
1492 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
1494 cifsConvertToUCS((__le16
*) data_offset
, fromName
, PATH_MAX
,
1495 nls_codepage
, remap
);
1496 name_len_target
++; /* trailing null */
1497 name_len_target
*= 2;
1498 } else { /* BB improve the check for buffer overruns BB */
1499 name_len_target
= strnlen(fromName
, PATH_MAX
);
1500 name_len_target
++; /* trailing null */
1501 strncpy(data_offset
, fromName
, name_len_target
);
1504 pSMB
->MaxParameterCount
= cpu_to_le16(2);
1505 /* BB find exact max on data count below from sess*/
1506 pSMB
->MaxDataCount
= cpu_to_le16(1000);
1507 pSMB
->SetupCount
= 1;
1508 pSMB
->Reserved3
= 0;
1509 pSMB
->SubCommand
= cpu_to_le16(TRANS2_SET_PATH_INFORMATION
);
1510 byte_count
= 3 /* pad */ + params
+ name_len_target
;
1511 pSMB
->ParameterCount
= cpu_to_le16(params
);
1512 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
1513 pSMB
->DataCount
= cpu_to_le16(name_len_target
);
1514 pSMB
->TotalDataCount
= pSMB
->DataCount
;
1515 pSMB
->ParameterOffset
= cpu_to_le16(param_offset
);
1516 pSMB
->DataOffset
= cpu_to_le16(offset
);
1517 pSMB
->InformationLevel
= cpu_to_le16(SMB_SET_FILE_UNIX_HLINK
);
1518 pSMB
->Reserved4
= 0;
1519 pSMB
->hdr
.smb_buf_length
+= byte_count
;
1520 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
1521 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
1522 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
1524 cFYI(1, ("Send error in SetPathInfo (hard link) = %d", rc
));
1527 cifs_buf_release(pSMB
);
1529 goto createHardLinkRetry
;
1535 CIFSCreateHardLink(const int xid
, struct cifsTconInfo
*tcon
,
1536 const char *fromName
, const char *toName
,
1537 const struct nls_table
*nls_codepage
, int remap
)
1540 NT_RENAME_REQ
*pSMB
= NULL
;
1541 RENAME_RSP
*pSMBr
= NULL
;
1543 int name_len
, name_len2
;
1546 cFYI(1, ("In CIFSCreateHardLink"));
1547 winCreateHardLinkRetry
:
1549 rc
= smb_init(SMB_COM_NT_RENAME
, 4, tcon
, (void **) &pSMB
,
1554 pSMB
->SearchAttributes
=
1555 cpu_to_le16(ATTR_READONLY
| ATTR_HIDDEN
| ATTR_SYSTEM
|
1557 pSMB
->Flags
= cpu_to_le16(CREATE_HARD_LINK
);
1558 pSMB
->ClusterCount
= 0;
1560 pSMB
->BufferFormat
= 0x04;
1562 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
1564 cifsConvertToUCS((__le16
*) pSMB
->OldFileName
, fromName
,
1565 PATH_MAX
, nls_codepage
, remap
);
1566 name_len
++; /* trailing null */
1568 pSMB
->OldFileName
[name_len
] = 0; /* pad */
1569 pSMB
->OldFileName
[name_len
+ 1] = 0x04;
1571 cifsConvertToUCS((__le16
*)&pSMB
->OldFileName
[name_len
+ 2],
1572 toName
, PATH_MAX
, nls_codepage
, remap
);
1573 name_len2
+= 1 /* trailing null */ + 1 /* Signature word */ ;
1574 name_len2
*= 2; /* convert to bytes */
1575 } else { /* BB improve the check for buffer overruns BB */
1576 name_len
= strnlen(fromName
, PATH_MAX
);
1577 name_len
++; /* trailing null */
1578 strncpy(pSMB
->OldFileName
, fromName
, name_len
);
1579 name_len2
= strnlen(toName
, PATH_MAX
);
1580 name_len2
++; /* trailing null */
1581 pSMB
->OldFileName
[name_len
] = 0x04; /* 2nd buffer format */
1582 strncpy(&pSMB
->OldFileName
[name_len
+ 1], toName
, name_len2
);
1583 name_len2
++; /* trailing null */
1584 name_len2
++; /* signature byte */
1587 count
= 1 /* string type byte */ + name_len
+ name_len2
;
1588 pSMB
->hdr
.smb_buf_length
+= count
;
1589 pSMB
->ByteCount
= cpu_to_le16(count
);
1591 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
1592 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
1594 cFYI(1, ("Send error in hard link (NT rename) = %d", rc
));
1596 cifs_buf_release(pSMB
);
1598 goto winCreateHardLinkRetry
;
1604 CIFSSMBUnixQuerySymLink(const int xid
, struct cifsTconInfo
*tcon
,
1605 const unsigned char *searchName
,
1606 char *symlinkinfo
, const int buflen
,
1607 const struct nls_table
*nls_codepage
)
1609 /* SMB_QUERY_FILE_UNIX_LINK */
1610 TRANSACTION2_QPI_REQ
*pSMB
= NULL
;
1611 TRANSACTION2_QPI_RSP
*pSMBr
= NULL
;
1615 __u16 params
, byte_count
;
1617 cFYI(1, ("In QPathSymLinkInfo (Unix) for path %s", searchName
));
1620 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
1625 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
1627 cifs_strtoUCS((wchar_t *) pSMB
->FileName
, searchName
, PATH_MAX
1628 /* find define for this maxpathcomponent */
1630 name_len
++; /* trailing null */
1632 } else { /* BB improve the check for buffer overruns BB */
1633 name_len
= strnlen(searchName
, PATH_MAX
);
1634 name_len
++; /* trailing null */
1635 strncpy(pSMB
->FileName
, searchName
, name_len
);
1638 params
= 2 /* level */ + 4 /* rsrvd */ + name_len
/* incl null */ ;
1639 pSMB
->TotalDataCount
= 0;
1640 pSMB
->MaxParameterCount
= cpu_to_le16(2);
1641 /* BB find exact max data count below from sess structure BB */
1642 pSMB
->MaxDataCount
= cpu_to_le16(4000);
1643 pSMB
->MaxSetupCount
= 0;
1647 pSMB
->Reserved2
= 0;
1648 pSMB
->ParameterOffset
= cpu_to_le16(offsetof(
1649 struct smb_com_transaction2_qpi_req
,InformationLevel
) - 4);
1650 pSMB
->DataCount
= 0;
1651 pSMB
->DataOffset
= 0;
1652 pSMB
->SetupCount
= 1;
1653 pSMB
->Reserved3
= 0;
1654 pSMB
->SubCommand
= cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION
);
1655 byte_count
= params
+ 1 /* pad */ ;
1656 pSMB
->TotalParameterCount
= cpu_to_le16(params
);
1657 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
1658 pSMB
->InformationLevel
= cpu_to_le16(SMB_QUERY_FILE_UNIX_LINK
);
1659 pSMB
->Reserved4
= 0;
1660 pSMB
->hdr
.smb_buf_length
+= byte_count
;
1661 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
1663 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
1664 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
1666 cFYI(1, ("Send error in QuerySymLinkInfo = %d", rc
));
1668 /* decode response */
1670 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
1671 if (rc
|| (pSMBr
->ByteCount
< 2))
1672 /* BB also check enough total bytes returned */
1673 rc
= -EIO
; /* bad smb */
1675 __u16 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
1676 __u16 count
= le16_to_cpu(pSMBr
->t2
.DataCount
);
1678 if (pSMBr
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
1679 name_len
= UniStrnlen((wchar_t *) ((char *)
1680 &pSMBr
->hdr
.Protocol
+data_offset
),
1681 min_t(const int, buflen
,count
) / 2);
1682 /* BB FIXME investigate remapping reserved chars here */
1683 cifs_strfromUCS_le(symlinkinfo
,
1684 (wchar_t *) ((char *)&pSMBr
->hdr
.Protocol
+
1686 name_len
, nls_codepage
);
1688 strncpy(symlinkinfo
,
1689 (char *) &pSMBr
->hdr
.Protocol
+
1691 min_t(const int, buflen
, count
));
1693 symlinkinfo
[buflen
] = 0;
1694 /* just in case so calling code does not go off the end of buffer */
1697 cifs_buf_release(pSMB
);
1699 goto querySymLinkRetry
;
1704 CIFSSMBQueryReparseLinkInfo(const int xid
, struct cifsTconInfo
*tcon
,
1705 const unsigned char *searchName
,
1706 char *symlinkinfo
, const int buflen
,__u16 fid
,
1707 const struct nls_table
*nls_codepage
)
1712 struct smb_com_transaction_ioctl_req
* pSMB
;
1713 struct smb_com_transaction_ioctl_rsp
* pSMBr
;
1715 cFYI(1, ("In Windows reparse style QueryLink for path %s", searchName
));
1716 rc
= smb_init(SMB_COM_NT_TRANSACT
, 23, tcon
, (void **) &pSMB
,
1721 pSMB
->TotalParameterCount
= 0 ;
1722 pSMB
->TotalDataCount
= 0;
1723 pSMB
->MaxParameterCount
= cpu_to_le32(2);
1724 /* BB find exact data count max from sess structure BB */
1725 pSMB
->MaxDataCount
= cpu_to_le32(4000);
1726 pSMB
->MaxSetupCount
= 4;
1728 pSMB
->ParameterOffset
= 0;
1729 pSMB
->DataCount
= 0;
1730 pSMB
->DataOffset
= 0;
1731 pSMB
->SetupCount
= 4;
1732 pSMB
->SubCommand
= cpu_to_le16(NT_TRANSACT_IOCTL
);
1733 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
1734 pSMB
->FunctionCode
= cpu_to_le32(FSCTL_GET_REPARSE_POINT
);
1735 pSMB
->IsFsctl
= 1; /* FSCTL */
1736 pSMB
->IsRootFlag
= 0;
1737 pSMB
->Fid
= fid
; /* file handle always le */
1738 pSMB
->ByteCount
= 0;
1740 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
1741 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
1743 cFYI(1, ("Send error in QueryReparseLinkInfo = %d", rc
));
1744 } else { /* decode response */
1745 __u32 data_offset
= le32_to_cpu(pSMBr
->DataOffset
);
1746 __u32 data_count
= le32_to_cpu(pSMBr
->DataCount
);
1747 if ((pSMBr
->ByteCount
< 2) || (data_offset
> 512))
1748 /* BB also check enough total bytes returned */
1749 rc
= -EIO
; /* bad smb */
1751 if(data_count
&& (data_count
< 2048)) {
1752 char * end_of_smb
= pSMBr
->ByteCount
+ (char *)&pSMBr
->ByteCount
;
1754 struct reparse_data
* reparse_buf
= (struct reparse_data
*)
1755 ((char *)&pSMBr
->hdr
.Protocol
+ data_offset
);
1756 if((char*)reparse_buf
>= end_of_smb
) {
1760 if((reparse_buf
->LinkNamesBuf
+
1761 reparse_buf
->TargetNameOffset
+
1762 reparse_buf
->TargetNameLen
) >
1764 cFYI(1,("reparse buf extended beyond SMB"));
1769 if (pSMBr
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
1770 name_len
= UniStrnlen((wchar_t *)
1771 (reparse_buf
->LinkNamesBuf
+
1772 reparse_buf
->TargetNameOffset
),
1773 min(buflen
/2, reparse_buf
->TargetNameLen
/ 2));
1774 cifs_strfromUCS_le(symlinkinfo
,
1775 (wchar_t *) (reparse_buf
->LinkNamesBuf
+
1776 reparse_buf
->TargetNameOffset
),
1777 name_len
, nls_codepage
);
1778 } else { /* ASCII names */
1779 strncpy(symlinkinfo
,reparse_buf
->LinkNamesBuf
+
1780 reparse_buf
->TargetNameOffset
,
1781 min_t(const int, buflen
, reparse_buf
->TargetNameLen
));
1785 cFYI(1,("Invalid return data count on get reparse info ioctl"));
1787 symlinkinfo
[buflen
] = 0; /* just in case so the caller
1788 does not go off the end of the buffer */
1789 cFYI(1,("readlink result - %s ",symlinkinfo
));
1794 cifs_buf_release(pSMB
);
1796 /* Note: On -EAGAIN error only caller can retry on handle based calls
1797 since file handle passed in no longer valid */
1802 #ifdef CONFIG_CIFS_POSIX
1804 /*Convert an Access Control Entry from wire format to local POSIX xattr format*/
1805 static void cifs_convert_ace(posix_acl_xattr_entry
* ace
, struct cifs_posix_ace
* cifs_ace
)
1807 /* u8 cifs fields do not need le conversion */
1808 ace
->e_perm
= (__u16
)cifs_ace
->cifs_e_perm
;
1809 ace
->e_tag
= (__u16
)cifs_ace
->cifs_e_tag
;
1810 ace
->e_id
= (__u32
)le64_to_cpu(cifs_ace
->cifs_uid
);
1811 /* cFYI(1,("perm %d tag %d id %d",ace->e_perm,ace->e_tag,ace->e_id)); */
1816 /* Convert ACL from CIFS POSIX wire format to local Linux POSIX ACL xattr */
1817 static int cifs_copy_posix_acl(char * trgt
,char * src
, const int buflen
,
1818 const int acl_type
,const int size_of_data_area
)
1823 struct cifs_posix_ace
* pACE
;
1824 struct cifs_posix_acl
* cifs_acl
= (struct cifs_posix_acl
*)src
;
1825 posix_acl_xattr_header
* local_acl
= (posix_acl_xattr_header
*)trgt
;
1827 if (le16_to_cpu(cifs_acl
->version
) != CIFS_ACL_VERSION
)
1830 if(acl_type
& ACL_TYPE_ACCESS
) {
1831 count
= le16_to_cpu(cifs_acl
->access_entry_count
);
1832 pACE
= &cifs_acl
->ace_array
[0];
1833 size
= sizeof(struct cifs_posix_acl
);
1834 size
+= sizeof(struct cifs_posix_ace
) * count
;
1835 /* check if we would go beyond end of SMB */
1836 if(size_of_data_area
< size
) {
1837 cFYI(1,("bad CIFS POSIX ACL size %d vs. %d",size_of_data_area
,size
));
1840 } else if(acl_type
& ACL_TYPE_DEFAULT
) {
1841 count
= le16_to_cpu(cifs_acl
->access_entry_count
);
1842 size
= sizeof(struct cifs_posix_acl
);
1843 size
+= sizeof(struct cifs_posix_ace
) * count
;
1844 /* skip past access ACEs to get to default ACEs */
1845 pACE
= &cifs_acl
->ace_array
[count
];
1846 count
= le16_to_cpu(cifs_acl
->default_entry_count
);
1847 size
+= sizeof(struct cifs_posix_ace
) * count
;
1848 /* check if we would go beyond end of SMB */
1849 if(size_of_data_area
< size
)
1856 size
= posix_acl_xattr_size(count
);
1857 if((buflen
== 0) || (local_acl
== NULL
)) {
1858 /* used to query ACL EA size */
1859 } else if(size
> buflen
) {
1861 } else /* buffer big enough */ {
1862 local_acl
->a_version
= POSIX_ACL_XATTR_VERSION
;
1863 for(i
= 0;i
< count
;i
++) {
1864 cifs_convert_ace(&local_acl
->a_entries
[i
],pACE
);
1871 static __u16
convert_ace_to_cifs_ace(struct cifs_posix_ace
* cifs_ace
,
1872 const posix_acl_xattr_entry
* local_ace
)
1874 __u16 rc
= 0; /* 0 = ACL converted ok */
1876 cifs_ace
->cifs_e_perm
= (__u8
)cpu_to_le16(local_ace
->e_perm
);
1877 cifs_ace
->cifs_e_tag
= (__u8
)cpu_to_le16(local_ace
->e_tag
);
1878 /* BB is there a better way to handle the large uid? */
1879 if(local_ace
->e_id
== -1) {
1880 /* Probably no need to le convert -1 on any arch but can not hurt */
1881 cifs_ace
->cifs_uid
= cpu_to_le64(-1);
1883 cifs_ace
->cifs_uid
= (__u64
)cpu_to_le32(local_ace
->e_id
);
1884 /*cFYI(1,("perm %d tag %d id %d",ace->e_perm,ace->e_tag,ace->e_id));*/
1888 /* Convert ACL from local Linux POSIX xattr to CIFS POSIX ACL wire format */
1889 static __u16
ACL_to_cifs_posix(char * parm_data
,const char * pACL
,const int buflen
,
1893 struct cifs_posix_acl
* cifs_acl
= (struct cifs_posix_acl
*)parm_data
;
1894 posix_acl_xattr_header
* local_acl
= (posix_acl_xattr_header
*)pACL
;
1898 if((buflen
== 0) || (pACL
== NULL
) || (cifs_acl
== NULL
))
1901 count
= posix_acl_xattr_count((size_t)buflen
);
1902 cFYI(1,("setting acl with %d entries from buf of length %d and version of %d",
1903 count
,buflen
,local_acl
->a_version
));
1904 if(local_acl
->a_version
!= 2) {
1905 cFYI(1,("unknown POSIX ACL version %d",local_acl
->a_version
));
1908 cifs_acl
->version
= cpu_to_le16(1);
1909 if(acl_type
== ACL_TYPE_ACCESS
)
1910 cifs_acl
->access_entry_count
= count
;
1911 else if(acl_type
== ACL_TYPE_DEFAULT
)
1912 cifs_acl
->default_entry_count
= count
;
1914 cFYI(1,("unknown ACL type %d",acl_type
));
1917 for(i
=0;i
<count
;i
++) {
1918 rc
= convert_ace_to_cifs_ace(&cifs_acl
->ace_array
[i
],
1919 &local_acl
->a_entries
[i
]);
1921 /* ACE not converted */
1926 rc
= (__u16
)(count
* sizeof(struct cifs_posix_ace
));
1927 rc
+= sizeof(struct cifs_posix_acl
);
1928 /* BB add check to make sure ACL does not overflow SMB */
1934 CIFSSMBGetPosixACL(const int xid
, struct cifsTconInfo
*tcon
,
1935 const unsigned char *searchName
,
1936 char *acl_inf
, const int buflen
, const int acl_type
,
1937 const struct nls_table
*nls_codepage
, int remap
)
1939 /* SMB_QUERY_POSIX_ACL */
1940 TRANSACTION2_QPI_REQ
*pSMB
= NULL
;
1941 TRANSACTION2_QPI_RSP
*pSMBr
= NULL
;
1945 __u16 params
, byte_count
;
1947 cFYI(1, ("In GetPosixACL (Unix) for path %s", searchName
));
1950 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
1955 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
1957 cifsConvertToUCS((__le16
*) pSMB
->FileName
, searchName
,
1958 PATH_MAX
, nls_codepage
, remap
);
1959 name_len
++; /* trailing null */
1961 pSMB
->FileName
[name_len
] = 0;
1962 pSMB
->FileName
[name_len
+1] = 0;
1963 } else { /* BB improve the check for buffer overruns BB */
1964 name_len
= strnlen(searchName
, PATH_MAX
);
1965 name_len
++; /* trailing null */
1966 strncpy(pSMB
->FileName
, searchName
, name_len
);
1969 params
= 2 /* level */ + 4 /* rsrvd */ + name_len
/* incl null */ ;
1970 pSMB
->TotalDataCount
= 0;
1971 pSMB
->MaxParameterCount
= cpu_to_le16(2);
1972 /* BB find exact max data count below from sess structure BB */
1973 pSMB
->MaxDataCount
= cpu_to_le16(4000);
1974 pSMB
->MaxSetupCount
= 0;
1978 pSMB
->Reserved2
= 0;
1979 pSMB
->ParameterOffset
= cpu_to_le16(
1980 offsetof(struct smb_com_transaction2_qpi_req
,InformationLevel
) - 4);
1981 pSMB
->DataCount
= 0;
1982 pSMB
->DataOffset
= 0;
1983 pSMB
->SetupCount
= 1;
1984 pSMB
->Reserved3
= 0;
1985 pSMB
->SubCommand
= cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION
);
1986 byte_count
= params
+ 1 /* pad */ ;
1987 pSMB
->TotalParameterCount
= cpu_to_le16(params
);
1988 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
1989 pSMB
->InformationLevel
= cpu_to_le16(SMB_QUERY_POSIX_ACL
);
1990 pSMB
->Reserved4
= 0;
1991 pSMB
->hdr
.smb_buf_length
+= byte_count
;
1992 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
1994 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
1995 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
1997 cFYI(1, ("Send error in Query POSIX ACL = %d", rc
));
1999 /* decode response */
2001 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
2002 if (rc
|| (pSMBr
->ByteCount
< 2))
2003 /* BB also check enough total bytes returned */
2004 rc
= -EIO
; /* bad smb */
2006 __u16 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
2007 __u16 count
= le16_to_cpu(pSMBr
->t2
.DataCount
);
2008 rc
= cifs_copy_posix_acl(acl_inf
,
2009 (char *)&pSMBr
->hdr
.Protocol
+data_offset
,
2010 buflen
,acl_type
,count
);
2013 cifs_buf_release(pSMB
);
2020 CIFSSMBSetPosixACL(const int xid
, struct cifsTconInfo
*tcon
,
2021 const unsigned char *fileName
,
2022 const char *local_acl
, const int buflen
,
2024 const struct nls_table
*nls_codepage
, int remap
)
2026 struct smb_com_transaction2_spi_req
*pSMB
= NULL
;
2027 struct smb_com_transaction2_spi_rsp
*pSMBr
= NULL
;
2031 int bytes_returned
= 0;
2032 __u16 params
, byte_count
, data_count
, param_offset
, offset
;
2034 cFYI(1, ("In SetPosixACL (Unix) for path %s", fileName
));
2036 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
2040 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
2042 cifsConvertToUCS((__le16
*) pSMB
->FileName
, fileName
,
2043 PATH_MAX
, nls_codepage
, remap
);
2044 name_len
++; /* trailing null */
2046 } else { /* BB improve the check for buffer overruns BB */
2047 name_len
= strnlen(fileName
, PATH_MAX
);
2048 name_len
++; /* trailing null */
2049 strncpy(pSMB
->FileName
, fileName
, name_len
);
2051 params
= 6 + name_len
;
2052 pSMB
->MaxParameterCount
= cpu_to_le16(2);
2053 pSMB
->MaxDataCount
= cpu_to_le16(1000); /* BB find max SMB size from sess */
2054 pSMB
->MaxSetupCount
= 0;
2058 pSMB
->Reserved2
= 0;
2059 param_offset
= offsetof(struct smb_com_transaction2_spi_req
,
2060 InformationLevel
) - 4;
2061 offset
= param_offset
+ params
;
2062 parm_data
= ((char *) &pSMB
->hdr
.Protocol
) + offset
;
2063 pSMB
->ParameterOffset
= cpu_to_le16(param_offset
);
2065 /* convert to on the wire format for POSIX ACL */
2066 data_count
= ACL_to_cifs_posix(parm_data
,local_acl
,buflen
,acl_type
);
2068 if(data_count
== 0) {
2070 goto setACLerrorExit
;
2072 pSMB
->DataOffset
= cpu_to_le16(offset
);
2073 pSMB
->SetupCount
= 1;
2074 pSMB
->Reserved3
= 0;
2075 pSMB
->SubCommand
= cpu_to_le16(TRANS2_SET_PATH_INFORMATION
);
2076 pSMB
->InformationLevel
= cpu_to_le16(SMB_SET_POSIX_ACL
);
2077 byte_count
= 3 /* pad */ + params
+ data_count
;
2078 pSMB
->DataCount
= cpu_to_le16(data_count
);
2079 pSMB
->TotalDataCount
= pSMB
->DataCount
;
2080 pSMB
->ParameterCount
= cpu_to_le16(params
);
2081 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
2082 pSMB
->Reserved4
= 0;
2083 pSMB
->hdr
.smb_buf_length
+= byte_count
;
2084 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
2085 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
2086 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
2088 cFYI(1, ("Set POSIX ACL returned %d", rc
));
2092 cifs_buf_release(pSMB
);
2098 /* BB fix tabs in this function FIXME BB */
2100 CIFSGetExtAttr(const int xid
, struct cifsTconInfo
*tcon
,
2101 const int netfid
, __u64
* pExtAttrBits
, __u64
*pMask
)
2104 struct smb_t2_qfi_req
*pSMB
= NULL
;
2105 struct smb_t2_qfi_rsp
*pSMBr
= NULL
;
2107 __u16 params
, byte_count
;
2109 cFYI(1,("In GetExtAttr"));
2114 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
2119 params
= 2 /* level */ +2 /* fid */;
2120 pSMB
->t2
.TotalDataCount
= 0;
2121 pSMB
->t2
.MaxParameterCount
= cpu_to_le16(4);
2122 /* BB find exact max data count below from sess structure BB */
2123 pSMB
->t2
.MaxDataCount
= cpu_to_le16(4000);
2124 pSMB
->t2
.MaxSetupCount
= 0;
2125 pSMB
->t2
.Reserved
= 0;
2127 pSMB
->t2
.Timeout
= 0;
2128 pSMB
->t2
.Reserved2
= 0;
2129 pSMB
->t2
.ParameterOffset
= cpu_to_le16(offsetof(struct smb_t2_qfi_req
,
2131 pSMB
->t2
.DataCount
= 0;
2132 pSMB
->t2
.DataOffset
= 0;
2133 pSMB
->t2
.SetupCount
= 1;
2134 pSMB
->t2
.Reserved3
= 0;
2135 pSMB
->t2
.SubCommand
= cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION
);
2136 byte_count
= params
+ 1 /* pad */ ;
2137 pSMB
->t2
.TotalParameterCount
= cpu_to_le16(params
);
2138 pSMB
->t2
.ParameterCount
= pSMB
->t2
.TotalParameterCount
;
2139 pSMB
->InformationLevel
= cpu_to_le16(SMB_QUERY_ATTR_FLAGS
);
2142 pSMB
->hdr
.smb_buf_length
+= byte_count
;
2143 pSMB
->t2
.ByteCount
= cpu_to_le16(byte_count
);
2145 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
2146 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
2148 cFYI(1, ("error %d in GetExtAttr", rc
));
2150 /* decode response */
2151 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
2152 if (rc
|| (pSMBr
->ByteCount
< 2))
2153 /* BB also check enough total bytes returned */
2154 /* If rc should we check for EOPNOSUPP and
2155 disable the srvino flag? or in caller? */
2156 rc
= -EIO
; /* bad smb */
2158 __u16 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
2159 __u16 count
= le16_to_cpu(pSMBr
->t2
.DataCount
);
2160 struct file_chattr_info
* pfinfo
;
2161 /* BB Do we need a cast or hash here ? */
2163 cFYI(1, ("Illegal size ret in GetExtAttr"));
2167 pfinfo
= (struct file_chattr_info
*)
2168 (data_offset
+ (char *) &pSMBr
->hdr
.Protocol
);
2169 *pExtAttrBits
= le64_to_cpu(pfinfo
->mode
);
2170 *pMask
= le64_to_cpu(pfinfo
->mask
);
2174 cifs_buf_release(pSMB
);
2176 goto GetExtAttrRetry
;
2181 #endif /* CONFIG_POSIX */
2184 CIFSSMBQPathInfo(const int xid
, struct cifsTconInfo
*tcon
,
2185 const unsigned char *searchName
,
2186 FILE_ALL_INFO
* pFindData
,
2187 const struct nls_table
*nls_codepage
, int remap
)
2189 /* level 263 SMB_QUERY_FILE_ALL_INFO */
2190 TRANSACTION2_QPI_REQ
*pSMB
= NULL
;
2191 TRANSACTION2_QPI_RSP
*pSMBr
= NULL
;
2195 __u16 params
, byte_count
;
2197 /* cFYI(1, ("In QPathInfo path %s", searchName)); */
2199 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
2204 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
2206 cifsConvertToUCS((__le16
*) pSMB
->FileName
, searchName
,
2207 PATH_MAX
, nls_codepage
, remap
);
2208 name_len
++; /* trailing null */
2210 } else { /* BB improve the check for buffer overruns BB */
2211 name_len
= strnlen(searchName
, PATH_MAX
);
2212 name_len
++; /* trailing null */
2213 strncpy(pSMB
->FileName
, searchName
, name_len
);
2216 params
= 2 /* level */ + 4 /* reserved */ + name_len
/* includes NUL */ ;
2217 pSMB
->TotalDataCount
= 0;
2218 pSMB
->MaxParameterCount
= cpu_to_le16(2);
2219 pSMB
->MaxDataCount
= cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
2220 pSMB
->MaxSetupCount
= 0;
2224 pSMB
->Reserved2
= 0;
2225 pSMB
->ParameterOffset
= cpu_to_le16(offsetof(
2226 struct smb_com_transaction2_qpi_req
,InformationLevel
) - 4);
2227 pSMB
->DataCount
= 0;
2228 pSMB
->DataOffset
= 0;
2229 pSMB
->SetupCount
= 1;
2230 pSMB
->Reserved3
= 0;
2231 pSMB
->SubCommand
= cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION
);
2232 byte_count
= params
+ 1 /* pad */ ;
2233 pSMB
->TotalParameterCount
= cpu_to_le16(params
);
2234 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
2235 pSMB
->InformationLevel
= cpu_to_le16(SMB_QUERY_FILE_ALL_INFO
);
2236 pSMB
->Reserved4
= 0;
2237 pSMB
->hdr
.smb_buf_length
+= byte_count
;
2238 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
2240 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
2241 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
2243 cFYI(1, ("Send error in QPathInfo = %d", rc
));
2244 } else { /* decode response */
2245 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
2247 if (rc
|| (pSMBr
->ByteCount
< 40))
2248 rc
= -EIO
; /* bad smb */
2249 else if (pFindData
){
2250 __u16 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
2251 memcpy((char *) pFindData
,
2252 (char *) &pSMBr
->hdr
.Protocol
+
2253 data_offset
, sizeof (FILE_ALL_INFO
));
2257 cifs_buf_release(pSMB
);
2259 goto QPathInfoRetry
;
2265 CIFSSMBUnixQPathInfo(const int xid
, struct cifsTconInfo
*tcon
,
2266 const unsigned char *searchName
,
2267 FILE_UNIX_BASIC_INFO
* pFindData
,
2268 const struct nls_table
*nls_codepage
, int remap
)
2270 /* SMB_QUERY_FILE_UNIX_BASIC */
2271 TRANSACTION2_QPI_REQ
*pSMB
= NULL
;
2272 TRANSACTION2_QPI_RSP
*pSMBr
= NULL
;
2274 int bytes_returned
= 0;
2276 __u16 params
, byte_count
;
2278 cFYI(1, ("In QPathInfo (Unix) the path %s", searchName
));
2280 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
2285 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
2287 cifsConvertToUCS((__le16
*) pSMB
->FileName
, searchName
,
2288 PATH_MAX
, nls_codepage
, remap
);
2289 name_len
++; /* trailing null */
2291 } else { /* BB improve the check for buffer overruns BB */
2292 name_len
= strnlen(searchName
, PATH_MAX
);
2293 name_len
++; /* trailing null */
2294 strncpy(pSMB
->FileName
, searchName
, name_len
);
2297 params
= 2 /* level */ + 4 /* reserved */ + name_len
/* includes NUL */ ;
2298 pSMB
->TotalDataCount
= 0;
2299 pSMB
->MaxParameterCount
= cpu_to_le16(2);
2300 /* BB find exact max SMB PDU from sess structure BB */
2301 pSMB
->MaxDataCount
= cpu_to_le16(4000);
2302 pSMB
->MaxSetupCount
= 0;
2306 pSMB
->Reserved2
= 0;
2307 pSMB
->ParameterOffset
= cpu_to_le16(offsetof(
2308 struct smb_com_transaction2_qpi_req
,InformationLevel
) - 4);
2309 pSMB
->DataCount
= 0;
2310 pSMB
->DataOffset
= 0;
2311 pSMB
->SetupCount
= 1;
2312 pSMB
->Reserved3
= 0;
2313 pSMB
->SubCommand
= cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION
);
2314 byte_count
= params
+ 1 /* pad */ ;
2315 pSMB
->TotalParameterCount
= cpu_to_le16(params
);
2316 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
2317 pSMB
->InformationLevel
= cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC
);
2318 pSMB
->Reserved4
= 0;
2319 pSMB
->hdr
.smb_buf_length
+= byte_count
;
2320 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
2322 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
2323 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
2325 cFYI(1, ("Send error in QPathInfo = %d", rc
));
2326 } else { /* decode response */
2327 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
2329 if (rc
|| (pSMBr
->ByteCount
< sizeof(FILE_UNIX_BASIC_INFO
))) {
2330 rc
= -EIO
; /* bad smb */
2332 __u16 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
2333 memcpy((char *) pFindData
,
2334 (char *) &pSMBr
->hdr
.Protocol
+
2336 sizeof (FILE_UNIX_BASIC_INFO
));
2339 cifs_buf_release(pSMB
);
2341 goto UnixQPathInfoRetry
;
2346 #if 0 /* function unused at present */
2347 int CIFSFindSingle(const int xid
, struct cifsTconInfo
*tcon
,
2348 const char *searchName
, FILE_ALL_INFO
* findData
,
2349 const struct nls_table
*nls_codepage
)
2351 /* level 257 SMB_ */
2352 TRANSACTION2_FFIRST_REQ
*pSMB
= NULL
;
2353 TRANSACTION2_FFIRST_RSP
*pSMBr
= NULL
;
2357 __u16 params
, byte_count
;
2359 cFYI(1, ("In FindUnique"));
2361 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
2366 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
2368 cifsConvertToUCS((__le16
*) pSMB
->FileName
, searchName
, PATH_MAX
2369 /* find define for this maxpathcomponent */
2371 name_len
++; /* trailing null */
2373 } else { /* BB improve the check for buffer overruns BB */
2374 name_len
= strnlen(searchName
, PATH_MAX
);
2375 name_len
++; /* trailing null */
2376 strncpy(pSMB
->FileName
, searchName
, name_len
);
2379 params
= 12 + name_len
/* includes null */ ;
2380 pSMB
->TotalDataCount
= 0; /* no EAs */
2381 pSMB
->MaxParameterCount
= cpu_to_le16(2);
2382 pSMB
->MaxDataCount
= cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
2383 pSMB
->MaxSetupCount
= 0;
2387 pSMB
->Reserved2
= 0;
2388 pSMB
->ParameterOffset
= cpu_to_le16(
2389 offsetof(struct smb_com_transaction2_ffirst_req
,InformationLevel
) - 4);
2390 pSMB
->DataCount
= 0;
2391 pSMB
->DataOffset
= 0;
2392 pSMB
->SetupCount
= 1; /* one byte, no need to le convert */
2393 pSMB
->Reserved3
= 0;
2394 pSMB
->SubCommand
= cpu_to_le16(TRANS2_FIND_FIRST
);
2395 byte_count
= params
+ 1 /* pad */ ;
2396 pSMB
->TotalParameterCount
= cpu_to_le16(params
);
2397 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
2398 pSMB
->SearchAttributes
=
2399 cpu_to_le16(ATTR_READONLY
| ATTR_HIDDEN
| ATTR_SYSTEM
|
2401 pSMB
->SearchCount
= cpu_to_le16(16); /* BB increase */
2402 pSMB
->SearchFlags
= cpu_to_le16(1);
2403 pSMB
->InformationLevel
= cpu_to_le16(SMB_FIND_FILE_DIRECTORY_INFO
);
2404 pSMB
->SearchStorageType
= 0; /* BB what should we set this to? BB */
2405 pSMB
->hdr
.smb_buf_length
+= byte_count
;
2406 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
2408 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
2409 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
2412 cFYI(1, ("Send error in FindFileDirInfo = %d", rc
));
2413 } else { /* decode response */
2418 cifs_buf_release(pSMB
);
2420 goto findUniqueRetry
;
2424 #endif /* end unused (temporarily) function */
2426 /* xid, tcon, searchName and codepage are input parms, rest are returned */
2428 CIFSFindFirst(const int xid
, struct cifsTconInfo
*tcon
,
2429 const char *searchName
,
2430 const struct nls_table
*nls_codepage
,
2432 struct cifs_search_info
* psrch_inf
, int remap
)
2434 /* level 257 SMB_ */
2435 TRANSACTION2_FFIRST_REQ
*pSMB
= NULL
;
2436 TRANSACTION2_FFIRST_RSP
*pSMBr
= NULL
;
2437 T2_FFIRST_RSP_PARMS
* parms
;
2439 int bytes_returned
= 0;
2441 __u16 params
, byte_count
;
2443 cFYI(1, ("In FindFirst for %s",searchName
));
2446 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
2451 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
2453 cifsConvertToUCS((__le16
*) pSMB
->FileName
,searchName
,
2454 PATH_MAX
, nls_codepage
, remap
);
2455 /* We can not add the asterik earlier in case
2456 it got remapped to 0xF03A as if it were part of the
2457 directory name instead of a wildcard */
2459 pSMB
->FileName
[name_len
] = '\\';
2460 pSMB
->FileName
[name_len
+1] = 0;
2461 pSMB
->FileName
[name_len
+2] = '*';
2462 pSMB
->FileName
[name_len
+3] = 0;
2463 name_len
+= 4; /* now the trailing null */
2464 pSMB
->FileName
[name_len
] = 0; /* null terminate just in case */
2465 pSMB
->FileName
[name_len
+1] = 0;
2467 } else { /* BB add check for overrun of SMB buf BB */
2468 name_len
= strnlen(searchName
, PATH_MAX
);
2469 /* BB fix here and in unicode clause above ie
2470 if(name_len > buffersize-header)
2471 free buffer exit; BB */
2472 strncpy(pSMB
->FileName
, searchName
, name_len
);
2473 pSMB
->FileName
[name_len
] = '\\';
2474 pSMB
->FileName
[name_len
+1] = '*';
2475 pSMB
->FileName
[name_len
+2] = 0;
2479 params
= 12 + name_len
/* includes null */ ;
2480 pSMB
->TotalDataCount
= 0; /* no EAs */
2481 pSMB
->MaxParameterCount
= cpu_to_le16(10);
2482 pSMB
->MaxDataCount
= cpu_to_le16((tcon
->ses
->server
->maxBuf
-
2483 MAX_CIFS_HDR_SIZE
) & 0xFFFFFF00);
2484 pSMB
->MaxSetupCount
= 0;
2488 pSMB
->Reserved2
= 0;
2489 byte_count
= params
+ 1 /* pad */ ;
2490 pSMB
->TotalParameterCount
= cpu_to_le16(params
);
2491 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
2492 pSMB
->ParameterOffset
= cpu_to_le16(
2493 offsetof(struct smb_com_transaction2_ffirst_req
, SearchAttributes
) - 4);
2494 pSMB
->DataCount
= 0;
2495 pSMB
->DataOffset
= 0;
2496 pSMB
->SetupCount
= 1; /* one byte, no need to make endian neutral */
2497 pSMB
->Reserved3
= 0;
2498 pSMB
->SubCommand
= cpu_to_le16(TRANS2_FIND_FIRST
);
2499 pSMB
->SearchAttributes
=
2500 cpu_to_le16(ATTR_READONLY
| ATTR_HIDDEN
| ATTR_SYSTEM
|
2502 pSMB
->SearchCount
= cpu_to_le16(CIFSMaxBufSize
/sizeof(FILE_UNIX_INFO
));
2503 pSMB
->SearchFlags
= cpu_to_le16(CIFS_SEARCH_CLOSE_AT_END
|
2504 CIFS_SEARCH_RETURN_RESUME
);
2505 pSMB
->InformationLevel
= cpu_to_le16(psrch_inf
->info_level
);
2507 /* BB what should we set StorageType to? Does it matter? BB */
2508 pSMB
->SearchStorageType
= 0;
2509 pSMB
->hdr
.smb_buf_length
+= byte_count
;
2510 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
2512 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
2513 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
2515 if (rc
) {/* BB add logic to retry regular search if Unix search rejected unexpectedly by server */
2516 /* BB Add code to handle unsupported level rc */
2517 cFYI(1, ("Error in FindFirst = %d", rc
));
2520 cifs_buf_release(pSMB
);
2522 /* BB eventually could optimize out free and realloc of buf */
2525 goto findFirstRetry
;
2526 } else { /* decode response */
2527 /* BB remember to free buffer if error BB */
2528 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
2530 if (pSMBr
->hdr
.Flags2
& SMBFLG2_UNICODE
)
2531 psrch_inf
->unicode
= TRUE
;
2533 psrch_inf
->unicode
= FALSE
;
2535 psrch_inf
->ntwrk_buf_start
= (char *)pSMBr
;
2536 psrch_inf
->srch_entries_start
=
2537 (char *) &pSMBr
->hdr
.Protocol
+
2538 le16_to_cpu(pSMBr
->t2
.DataOffset
);
2539 parms
= (T2_FFIRST_RSP_PARMS
*)((char *) &pSMBr
->hdr
.Protocol
+
2540 le16_to_cpu(pSMBr
->t2
.ParameterOffset
));
2542 if(parms
->EndofSearch
)
2543 psrch_inf
->endOfSearch
= TRUE
;
2545 psrch_inf
->endOfSearch
= FALSE
;
2547 psrch_inf
->entries_in_buffer
= le16_to_cpu(parms
->SearchCount
);
2548 psrch_inf
->index_of_last_entry
=
2549 psrch_inf
->entries_in_buffer
;
2550 *pnetfid
= parms
->SearchHandle
;
2552 cifs_buf_release(pSMB
);
2559 int CIFSFindNext(const int xid
, struct cifsTconInfo
*tcon
,
2560 __u16 searchHandle
, struct cifs_search_info
* psrch_inf
)
2562 TRANSACTION2_FNEXT_REQ
*pSMB
= NULL
;
2563 TRANSACTION2_FNEXT_RSP
*pSMBr
= NULL
;
2564 T2_FNEXT_RSP_PARMS
* parms
;
2565 char *response_data
;
2567 int bytes_returned
, name_len
;
2568 __u16 params
, byte_count
;
2570 cFYI(1, ("In FindNext"));
2572 if(psrch_inf
->endOfSearch
== TRUE
)
2575 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
2580 params
= 14; /* includes 2 bytes of null string, converted to LE below */
2582 pSMB
->TotalDataCount
= 0; /* no EAs */
2583 pSMB
->MaxParameterCount
= cpu_to_le16(8);
2584 pSMB
->MaxDataCount
=
2585 cpu_to_le16((tcon
->ses
->server
->maxBuf
- MAX_CIFS_HDR_SIZE
) & 0xFFFFFF00);
2586 pSMB
->MaxSetupCount
= 0;
2590 pSMB
->Reserved2
= 0;
2591 pSMB
->ParameterOffset
= cpu_to_le16(
2592 offsetof(struct smb_com_transaction2_fnext_req
,SearchHandle
) - 4);
2593 pSMB
->DataCount
= 0;
2594 pSMB
->DataOffset
= 0;
2595 pSMB
->SetupCount
= 1;
2596 pSMB
->Reserved3
= 0;
2597 pSMB
->SubCommand
= cpu_to_le16(TRANS2_FIND_NEXT
);
2598 pSMB
->SearchHandle
= searchHandle
; /* always kept as le */
2600 cpu_to_le16(CIFSMaxBufSize
/ sizeof (FILE_UNIX_INFO
));
2601 /* test for Unix extensions */
2602 /* if (tcon->ses->capabilities & CAP_UNIX) {
2603 pSMB->InformationLevel = cpu_to_le16(SMB_FIND_FILE_UNIX);
2604 psrch_inf->info_level = SMB_FIND_FILE_UNIX;
2606 pSMB->InformationLevel =
2607 cpu_to_le16(SMB_FIND_FILE_DIRECTORY_INFO);
2608 psrch_inf->info_level = SMB_FIND_FILE_DIRECTORY_INFO;
2610 pSMB
->InformationLevel
= cpu_to_le16(psrch_inf
->info_level
);
2611 pSMB
->ResumeKey
= psrch_inf
->resume_key
;
2613 cpu_to_le16(CIFS_SEARCH_CLOSE_AT_END
| CIFS_SEARCH_RETURN_RESUME
);
2615 name_len
= psrch_inf
->resume_name_len
;
2617 if(name_len
< PATH_MAX
) {
2618 memcpy(pSMB
->ResumeFileName
, psrch_inf
->presume_name
, name_len
);
2619 byte_count
+= name_len
;
2622 goto FNext2_err_exit
;
2624 byte_count
= params
+ 1 /* pad */ ;
2625 pSMB
->TotalParameterCount
= cpu_to_le16(params
);
2626 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
2627 pSMB
->hdr
.smb_buf_length
+= byte_count
;
2628 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
2630 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
2631 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
2635 psrch_inf
->endOfSearch
= TRUE
;
2636 rc
= 0; /* search probably was closed at end of search above */
2638 cFYI(1, ("FindNext returned = %d", rc
));
2639 } else { /* decode response */
2640 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
2643 /* BB fixme add lock for file (srch_info) struct here */
2644 if (pSMBr
->hdr
.Flags2
& SMBFLG2_UNICODE
)
2645 psrch_inf
->unicode
= TRUE
;
2647 psrch_inf
->unicode
= FALSE
;
2648 response_data
= (char *) &pSMBr
->hdr
.Protocol
+
2649 le16_to_cpu(pSMBr
->t2
.ParameterOffset
);
2650 parms
= (T2_FNEXT_RSP_PARMS
*)response_data
;
2651 response_data
= (char *)&pSMBr
->hdr
.Protocol
+
2652 le16_to_cpu(pSMBr
->t2
.DataOffset
);
2653 cifs_buf_release(psrch_inf
->ntwrk_buf_start
);
2654 psrch_inf
->srch_entries_start
= response_data
;
2655 psrch_inf
->ntwrk_buf_start
= (char *)pSMB
;
2656 if(parms
->EndofSearch
)
2657 psrch_inf
->endOfSearch
= TRUE
;
2659 psrch_inf
->endOfSearch
= FALSE
;
2661 psrch_inf
->entries_in_buffer
= le16_to_cpu(parms
->SearchCount
);
2662 psrch_inf
->index_of_last_entry
+=
2663 psrch_inf
->entries_in_buffer
;
2664 /* cFYI(1,("fnxt2 entries in buf %d index_of_last %d",psrch_inf->entries_in_buffer,psrch_inf->index_of_last_entry)); */
2666 /* BB fixme add unlock here */
2671 /* BB On error, should we leave previous search buf (and count and
2672 last entry fields) intact or free the previous one? */
2674 /* Note: On -EAGAIN error only caller can retry on handle based calls
2675 since file handle passed in no longer valid */
2678 cifs_buf_release(pSMB
);
2684 CIFSFindClose(const int xid
, struct cifsTconInfo
*tcon
, const __u16 searchHandle
)
2687 FINDCLOSE_REQ
*pSMB
= NULL
;
2688 CLOSE_RSP
*pSMBr
= NULL
; /* BB removeme BB */
2691 cFYI(1, ("In CIFSSMBFindClose"));
2692 rc
= small_smb_init(SMB_COM_FIND_CLOSE2
, 1, tcon
, (void **)&pSMB
);
2694 /* no sense returning error if session restarted
2695 as file handle has been closed */
2701 pSMBr
= (CLOSE_RSP
*)pSMB
; /* BB removeme BB */
2702 pSMB
->FileID
= searchHandle
;
2703 pSMB
->ByteCount
= 0;
2704 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
2705 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
2707 cERROR(1, ("Send error in FindClose = %d", rc
));
2709 cifs_small_buf_release(pSMB
);
2711 /* Since session is dead, search handle closed on server already */
2718 #ifdef CONFIG_CIFS_EXPERIMENTAL
2720 CIFSGetSrvInodeNumber(const int xid
, struct cifsTconInfo
*tcon
,
2721 const unsigned char *searchName
,
2722 __u64
* inode_number
,
2723 const struct nls_table
*nls_codepage
, int remap
)
2726 TRANSACTION2_QPI_REQ
*pSMB
= NULL
;
2727 TRANSACTION2_QPI_RSP
*pSMBr
= NULL
;
2728 int name_len
, bytes_returned
;
2729 __u16 params
, byte_count
;
2731 cFYI(1,("In GetSrvInodeNum for %s",searchName
));
2735 GetInodeNumberRetry
:
2736 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
2742 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
2744 cifsConvertToUCS((__le16
*) pSMB
->FileName
, searchName
,
2745 PATH_MAX
,nls_codepage
, remap
);
2746 name_len
++; /* trailing null */
2748 } else { /* BB improve the check for buffer overruns BB */
2749 name_len
= strnlen(searchName
, PATH_MAX
);
2750 name_len
++; /* trailing null */
2751 strncpy(pSMB
->FileName
, searchName
, name_len
);
2754 params
= 2 /* level */ + 4 /* rsrvd */ + name_len
/* incl null */ ;
2755 pSMB
->TotalDataCount
= 0;
2756 pSMB
->MaxParameterCount
= cpu_to_le16(2);
2757 /* BB find exact max data count below from sess structure BB */
2758 pSMB
->MaxDataCount
= cpu_to_le16(4000);
2759 pSMB
->MaxSetupCount
= 0;
2763 pSMB
->Reserved2
= 0;
2764 pSMB
->ParameterOffset
= cpu_to_le16(offsetof(
2765 struct smb_com_transaction2_qpi_req
,InformationLevel
) - 4);
2766 pSMB
->DataCount
= 0;
2767 pSMB
->DataOffset
= 0;
2768 pSMB
->SetupCount
= 1;
2769 pSMB
->Reserved3
= 0;
2770 pSMB
->SubCommand
= cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION
);
2771 byte_count
= params
+ 1 /* pad */ ;
2772 pSMB
->TotalParameterCount
= cpu_to_le16(params
);
2773 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
2774 pSMB
->InformationLevel
= cpu_to_le16(SMB_QUERY_FILE_INTERNAL_INFO
);
2775 pSMB
->Reserved4
= 0;
2776 pSMB
->hdr
.smb_buf_length
+= byte_count
;
2777 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
2779 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
2780 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
2782 cFYI(1, ("error %d in QueryInternalInfo", rc
));
2784 /* decode response */
2785 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
2786 if (rc
|| (pSMBr
->ByteCount
< 2))
2787 /* BB also check enough total bytes returned */
2788 /* If rc should we check for EOPNOSUPP and
2789 disable the srvino flag? or in caller? */
2790 rc
= -EIO
; /* bad smb */
2792 __u16 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
2793 __u16 count
= le16_to_cpu(pSMBr
->t2
.DataCount
);
2794 struct file_internal_info
* pfinfo
;
2795 /* BB Do we need a cast or hash here ? */
2797 cFYI(1, ("Illegal size ret in QryIntrnlInf"));
2799 goto GetInodeNumOut
;
2801 pfinfo
= (struct file_internal_info
*)
2802 (data_offset
+ (char *) &pSMBr
->hdr
.Protocol
);
2803 *inode_number
= pfinfo
->UniqueId
;
2807 cifs_buf_release(pSMB
);
2809 goto GetInodeNumberRetry
;
2812 #endif /* CIFS_EXPERIMENTAL */
2815 CIFSGetDFSRefer(const int xid
, struct cifsSesInfo
*ses
,
2816 const unsigned char *searchName
,
2817 unsigned char **targetUNCs
,
2818 unsigned int *number_of_UNC_in_array
,
2819 const struct nls_table
*nls_codepage
, int remap
)
2821 /* TRANS2_GET_DFS_REFERRAL */
2822 TRANSACTION2_GET_DFS_REFER_REQ
*pSMB
= NULL
;
2823 TRANSACTION2_GET_DFS_REFER_RSP
*pSMBr
= NULL
;
2824 struct dfs_referral_level_3
* referrals
= NULL
;
2830 __u16 params
, byte_count
;
2831 *number_of_UNC_in_array
= 0;
2834 cFYI(1, ("In GetDFSRefer the path %s", searchName
));
2838 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, NULL
, (void **) &pSMB
,
2843 pSMB
->hdr
.Tid
= ses
->ipc_tid
;
2844 pSMB
->hdr
.Uid
= ses
->Suid
;
2845 if (ses
->capabilities
& CAP_STATUS32
) {
2846 pSMB
->hdr
.Flags2
|= SMBFLG2_ERR_STATUS
;
2848 if (ses
->capabilities
& CAP_DFS
) {
2849 pSMB
->hdr
.Flags2
|= SMBFLG2_DFS
;
2852 if (ses
->capabilities
& CAP_UNICODE
) {
2853 pSMB
->hdr
.Flags2
|= SMBFLG2_UNICODE
;
2855 cifsConvertToUCS((__le16
*) pSMB
->RequestFileName
,
2856 searchName
, PATH_MAX
, nls_codepage
, remap
);
2857 name_len
++; /* trailing null */
2859 } else { /* BB improve the check for buffer overruns BB */
2860 name_len
= strnlen(searchName
, PATH_MAX
);
2861 name_len
++; /* trailing null */
2862 strncpy(pSMB
->RequestFileName
, searchName
, name_len
);
2865 params
= 2 /* level */ + name_len
/*includes null */ ;
2866 pSMB
->TotalDataCount
= 0;
2867 pSMB
->DataCount
= 0;
2868 pSMB
->DataOffset
= 0;
2869 pSMB
->MaxParameterCount
= 0;
2870 pSMB
->MaxDataCount
= cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
2871 pSMB
->MaxSetupCount
= 0;
2875 pSMB
->Reserved2
= 0;
2876 pSMB
->ParameterOffset
= cpu_to_le16(offsetof(
2877 struct smb_com_transaction2_get_dfs_refer_req
, MaxReferralLevel
) - 4);
2878 pSMB
->SetupCount
= 1;
2879 pSMB
->Reserved3
= 0;
2880 pSMB
->SubCommand
= cpu_to_le16(TRANS2_GET_DFS_REFERRAL
);
2881 byte_count
= params
+ 3 /* pad */ ;
2882 pSMB
->ParameterCount
= cpu_to_le16(params
);
2883 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
2884 pSMB
->MaxReferralLevel
= cpu_to_le16(3);
2885 pSMB
->hdr
.smb_buf_length
+= byte_count
;
2886 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
2888 rc
= SendReceive(xid
, ses
, (struct smb_hdr
*) pSMB
,
2889 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
2891 cFYI(1, ("Send error in GetDFSRefer = %d", rc
));
2892 } else { /* decode response */
2893 /* BB Add logic to parse referrals here */
2894 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
2896 if (rc
|| (pSMBr
->ByteCount
< 17)) /* BB also check enough total bytes returned */
2897 rc
= -EIO
; /* bad smb */
2899 __u16 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
2900 __u16 data_count
= le16_to_cpu(pSMBr
->t2
.DataCount
);
2903 ("Decoding GetDFSRefer response. BCC: %d Offset %d",
2904 pSMBr
->ByteCount
, data_offset
));
2906 (struct dfs_referral_level_3
*)
2907 (8 /* sizeof start of data block */ +
2909 (char *) &pSMBr
->hdr
.Protocol
);
2910 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",
2911 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
)));
2912 /* BB This field is actually two bytes in from start of
2913 data block so we could do safety check that DataBlock
2914 begins at address of pSMBr->NumberOfReferrals */
2915 *number_of_UNC_in_array
= le16_to_cpu(pSMBr
->NumberOfReferrals
);
2917 /* BB Fix below so can return more than one referral */
2918 if(*number_of_UNC_in_array
> 1)
2919 *number_of_UNC_in_array
= 1;
2921 /* get the length of the strings describing refs */
2923 for(i
=0;i
<*number_of_UNC_in_array
;i
++) {
2924 /* make sure that DfsPathOffset not past end */
2925 __u16 offset
= le16_to_cpu(referrals
->DfsPathOffset
);
2926 if (offset
> data_count
) {
2927 /* if invalid referral, stop here and do
2928 not try to copy any more */
2929 *number_of_UNC_in_array
= i
;
2932 temp
= ((char *)referrals
) + offset
;
2934 if (pSMBr
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
2935 name_len
+= UniStrnlen((wchar_t *)temp
,data_count
);
2937 name_len
+= strnlen(temp
,data_count
);
2940 /* BB add check that referral pointer does not fall off end PDU */
2943 /* BB add check for name_len bigger than bcc */
2945 kmalloc(name_len
+1+ (*number_of_UNC_in_array
),GFP_KERNEL
);
2946 if(*targetUNCs
== NULL
) {
2950 /* copy the ref strings */
2952 (struct dfs_referral_level_3
*)
2953 (8 /* sizeof data hdr */ +
2955 (char *) &pSMBr
->hdr
.Protocol
);
2957 for(i
=0;i
<*number_of_UNC_in_array
;i
++) {
2958 temp
= ((char *)referrals
) + le16_to_cpu(referrals
->DfsPathOffset
);
2959 if (pSMBr
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
2960 cifs_strfromUCS_le(*targetUNCs
,
2961 (wchar_t *) temp
, name_len
, nls_codepage
);
2963 strncpy(*targetUNCs
,temp
,name_len
);
2965 /* BB update target_uncs pointers */
2975 cifs_buf_release(pSMB
);
2984 CIFSSMBQFSInfo(const int xid
, struct cifsTconInfo
*tcon
, struct kstatfs
*FSData
)
2986 /* level 0x103 SMB_QUERY_FILE_SYSTEM_INFO */
2987 TRANSACTION2_QFSI_REQ
*pSMB
= NULL
;
2988 TRANSACTION2_QFSI_RSP
*pSMBr
= NULL
;
2989 FILE_SYSTEM_INFO
*response_data
;
2991 int bytes_returned
= 0;
2992 __u16 params
, byte_count
;
2994 cFYI(1, ("In QFSInfo"));
2996 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
3001 params
= 2; /* level */
3002 pSMB
->TotalDataCount
= 0;
3003 pSMB
->MaxParameterCount
= cpu_to_le16(2);
3004 pSMB
->MaxDataCount
= cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
3005 pSMB
->MaxSetupCount
= 0;
3009 pSMB
->Reserved2
= 0;
3010 byte_count
= params
+ 1 /* pad */ ;
3011 pSMB
->TotalParameterCount
= cpu_to_le16(params
);
3012 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
3013 pSMB
->ParameterOffset
= cpu_to_le16(offsetof(
3014 struct smb_com_transaction2_qfsi_req
, InformationLevel
) - 4);
3015 pSMB
->DataCount
= 0;
3016 pSMB
->DataOffset
= 0;
3017 pSMB
->SetupCount
= 1;
3018 pSMB
->Reserved3
= 0;
3019 pSMB
->SubCommand
= cpu_to_le16(TRANS2_QUERY_FS_INFORMATION
);
3020 pSMB
->InformationLevel
= cpu_to_le16(SMB_QUERY_FS_SIZE_INFO
);
3021 pSMB
->hdr
.smb_buf_length
+= byte_count
;
3022 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
3024 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
3025 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
3027 cERROR(1, ("Send error in QFSInfo = %d", rc
));
3028 } else { /* decode response */
3029 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
3031 if (rc
|| (pSMBr
->ByteCount
< 24)) /* BB alsO CHEck enough total bytes returned */
3032 rc
= -EIO
; /* bad smb */
3034 __u16 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
3036 ("Decoding qfsinfo response. BCC: %d Offset %d",
3037 pSMBr
->ByteCount
, data_offset
));
3041 *) (((char *) &pSMBr
->hdr
.Protocol
) +
3044 le32_to_cpu(response_data
->BytesPerSector
) *
3045 le32_to_cpu(response_data
->
3046 SectorsPerAllocationUnit
);
3048 le64_to_cpu(response_data
->TotalAllocationUnits
);
3049 FSData
->f_bfree
= FSData
->f_bavail
=
3050 le64_to_cpu(response_data
->FreeAllocationUnits
);
3052 ("Blocks: %lld Free: %lld Block size %ld",
3053 (unsigned long long)FSData
->f_blocks
,
3054 (unsigned long long)FSData
->f_bfree
,
3058 cifs_buf_release(pSMB
);
3067 CIFSSMBQFSAttributeInfo(const int xid
, struct cifsTconInfo
*tcon
)
3069 /* level 0x105 SMB_QUERY_FILE_SYSTEM_INFO */
3070 TRANSACTION2_QFSI_REQ
*pSMB
= NULL
;
3071 TRANSACTION2_QFSI_RSP
*pSMBr
= NULL
;
3072 FILE_SYSTEM_ATTRIBUTE_INFO
*response_data
;
3074 int bytes_returned
= 0;
3075 __u16 params
, byte_count
;
3077 cFYI(1, ("In QFSAttributeInfo"));
3079 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
3084 params
= 2; /* level */
3085 pSMB
->TotalDataCount
= 0;
3086 pSMB
->MaxParameterCount
= cpu_to_le16(2);
3087 pSMB
->MaxDataCount
= cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
3088 pSMB
->MaxSetupCount
= 0;
3092 pSMB
->Reserved2
= 0;
3093 byte_count
= params
+ 1 /* pad */ ;
3094 pSMB
->TotalParameterCount
= cpu_to_le16(params
);
3095 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
3096 pSMB
->ParameterOffset
= cpu_to_le16(offsetof(
3097 struct smb_com_transaction2_qfsi_req
, InformationLevel
) - 4);
3098 pSMB
->DataCount
= 0;
3099 pSMB
->DataOffset
= 0;
3100 pSMB
->SetupCount
= 1;
3101 pSMB
->Reserved3
= 0;
3102 pSMB
->SubCommand
= cpu_to_le16(TRANS2_QUERY_FS_INFORMATION
);
3103 pSMB
->InformationLevel
= cpu_to_le16(SMB_QUERY_FS_ATTRIBUTE_INFO
);
3104 pSMB
->hdr
.smb_buf_length
+= byte_count
;
3105 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
3107 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
3108 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
3110 cERROR(1, ("Send error in QFSAttributeInfo = %d", rc
));
3111 } else { /* decode response */
3112 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
3114 if (rc
|| (pSMBr
->ByteCount
< 13)) { /* BB also check enough bytes returned */
3115 rc
= -EIO
; /* bad smb */
3117 __u16 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
3119 (FILE_SYSTEM_ATTRIBUTE_INFO
3120 *) (((char *) &pSMBr
->hdr
.Protocol
) +
3122 memcpy(&tcon
->fsAttrInfo
, response_data
,
3123 sizeof (FILE_SYSTEM_ATTRIBUTE_INFO
));
3126 cifs_buf_release(pSMB
);
3129 goto QFSAttributeRetry
;
3135 CIFSSMBQFSDeviceInfo(const int xid
, struct cifsTconInfo
*tcon
)
3137 /* level 0x104 SMB_QUERY_FILE_SYSTEM_INFO */
3138 TRANSACTION2_QFSI_REQ
*pSMB
= NULL
;
3139 TRANSACTION2_QFSI_RSP
*pSMBr
= NULL
;
3140 FILE_SYSTEM_DEVICE_INFO
*response_data
;
3142 int bytes_returned
= 0;
3143 __u16 params
, byte_count
;
3145 cFYI(1, ("In QFSDeviceInfo"));
3147 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
3152 params
= 2; /* level */
3153 pSMB
->TotalDataCount
= 0;
3154 pSMB
->MaxParameterCount
= cpu_to_le16(2);
3155 pSMB
->MaxDataCount
= cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
3156 pSMB
->MaxSetupCount
= 0;
3160 pSMB
->Reserved2
= 0;
3161 byte_count
= params
+ 1 /* pad */ ;
3162 pSMB
->TotalParameterCount
= cpu_to_le16(params
);
3163 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
3164 pSMB
->ParameterOffset
= cpu_to_le16(offsetof(
3165 struct smb_com_transaction2_qfsi_req
, InformationLevel
) - 4);
3167 pSMB
->DataCount
= 0;
3168 pSMB
->DataOffset
= 0;
3169 pSMB
->SetupCount
= 1;
3170 pSMB
->Reserved3
= 0;
3171 pSMB
->SubCommand
= cpu_to_le16(TRANS2_QUERY_FS_INFORMATION
);
3172 pSMB
->InformationLevel
= cpu_to_le16(SMB_QUERY_FS_DEVICE_INFO
);
3173 pSMB
->hdr
.smb_buf_length
+= byte_count
;
3174 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
3176 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
3177 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
3179 cFYI(1, ("Send error in QFSDeviceInfo = %d", rc
));
3180 } else { /* decode response */
3181 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
3183 if (rc
|| (pSMBr
->ByteCount
< sizeof (FILE_SYSTEM_DEVICE_INFO
)))
3184 rc
= -EIO
; /* bad smb */
3186 __u16 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
3188 (FILE_SYSTEM_DEVICE_INFO
*)
3189 (((char *) &pSMBr
->hdr
.Protocol
) +
3191 memcpy(&tcon
->fsDevInfo
, response_data
,
3192 sizeof (FILE_SYSTEM_DEVICE_INFO
));
3195 cifs_buf_release(pSMB
);
3198 goto QFSDeviceRetry
;
3204 CIFSSMBQFSUnixInfo(const int xid
, struct cifsTconInfo
*tcon
)
3206 /* level 0x200 SMB_QUERY_CIFS_UNIX_INFO */
3207 TRANSACTION2_QFSI_REQ
*pSMB
= NULL
;
3208 TRANSACTION2_QFSI_RSP
*pSMBr
= NULL
;
3209 FILE_SYSTEM_UNIX_INFO
*response_data
;
3211 int bytes_returned
= 0;
3212 __u16 params
, byte_count
;
3214 cFYI(1, ("In QFSUnixInfo"));
3216 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
3221 params
= 2; /* level */
3222 pSMB
->TotalDataCount
= 0;
3223 pSMB
->DataCount
= 0;
3224 pSMB
->DataOffset
= 0;
3225 pSMB
->MaxParameterCount
= cpu_to_le16(2);
3226 pSMB
->MaxDataCount
= cpu_to_le16(100); /* BB find exact max SMB PDU from sess structure BB */
3227 pSMB
->MaxSetupCount
= 0;
3231 pSMB
->Reserved2
= 0;
3232 byte_count
= params
+ 1 /* pad */ ;
3233 pSMB
->ParameterCount
= cpu_to_le16(params
);
3234 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
3235 pSMB
->ParameterOffset
= cpu_to_le16(offsetof(struct
3236 smb_com_transaction2_qfsi_req
, InformationLevel
) - 4);
3237 pSMB
->SetupCount
= 1;
3238 pSMB
->Reserved3
= 0;
3239 pSMB
->SubCommand
= cpu_to_le16(TRANS2_QUERY_FS_INFORMATION
);
3240 pSMB
->InformationLevel
= cpu_to_le16(SMB_QUERY_CIFS_UNIX_INFO
);
3241 pSMB
->hdr
.smb_buf_length
+= byte_count
;
3242 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
3244 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
3245 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
3247 cERROR(1, ("Send error in QFSUnixInfo = %d", rc
));
3248 } else { /* decode response */
3249 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
3251 if (rc
|| (pSMBr
->ByteCount
< 13)) {
3252 rc
= -EIO
; /* bad smb */
3254 __u16 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
3256 (FILE_SYSTEM_UNIX_INFO
3257 *) (((char *) &pSMBr
->hdr
.Protocol
) +
3259 memcpy(&tcon
->fsUnixInfo
, response_data
,
3260 sizeof (FILE_SYSTEM_UNIX_INFO
));
3263 cifs_buf_release(pSMB
);
3274 CIFSSMBQFSPosixInfo(const int xid
, struct cifsTconInfo
*tcon
,
3275 struct kstatfs
*FSData
)
3277 /* level 0x201 SMB_QUERY_CIFS_POSIX_INFO */
3278 TRANSACTION2_QFSI_REQ
*pSMB
= NULL
;
3279 TRANSACTION2_QFSI_RSP
*pSMBr
= NULL
;
3280 FILE_SYSTEM_POSIX_INFO
*response_data
;
3282 int bytes_returned
= 0;
3283 __u16 params
, byte_count
;
3285 cFYI(1, ("In QFSPosixInfo"));
3287 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
3292 params
= 2; /* level */
3293 pSMB
->TotalDataCount
= 0;
3294 pSMB
->DataCount
= 0;
3295 pSMB
->DataOffset
= 0;
3296 pSMB
->MaxParameterCount
= cpu_to_le16(2);
3297 pSMB
->MaxDataCount
= cpu_to_le16(100); /* BB find exact max SMB PDU from sess structure BB */
3298 pSMB
->MaxSetupCount
= 0;
3302 pSMB
->Reserved2
= 0;
3303 byte_count
= params
+ 1 /* pad */ ;
3304 pSMB
->ParameterCount
= cpu_to_le16(params
);
3305 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
3306 pSMB
->ParameterOffset
= cpu_to_le16(offsetof(struct
3307 smb_com_transaction2_qfsi_req
, InformationLevel
) - 4);
3308 pSMB
->SetupCount
= 1;
3309 pSMB
->Reserved3
= 0;
3310 pSMB
->SubCommand
= cpu_to_le16(TRANS2_QUERY_FS_INFORMATION
);
3311 pSMB
->InformationLevel
= cpu_to_le16(SMB_QUERY_POSIX_FS_INFO
);
3312 pSMB
->hdr
.smb_buf_length
+= byte_count
;
3313 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
3315 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
3316 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
3318 cFYI(1, ("Send error in QFSUnixInfo = %d", rc
));
3319 } else { /* decode response */
3320 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
3322 if (rc
|| (pSMBr
->ByteCount
< 13)) {
3323 rc
= -EIO
; /* bad smb */
3325 __u16 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
3327 (FILE_SYSTEM_POSIX_INFO
3328 *) (((char *) &pSMBr
->hdr
.Protocol
) +
3331 le32_to_cpu(response_data
->BlockSize
);
3333 le64_to_cpu(response_data
->TotalBlocks
);
3335 le64_to_cpu(response_data
->BlocksAvail
);
3336 if(response_data
->UserBlocksAvail
== -1) {
3337 FSData
->f_bavail
= FSData
->f_bfree
;
3340 le64_to_cpu(response_data
->UserBlocksAvail
);
3342 if(response_data
->TotalFileNodes
!= -1)
3344 le64_to_cpu(response_data
->TotalFileNodes
);
3345 if(response_data
->FreeFileNodes
!= -1)
3347 le64_to_cpu(response_data
->FreeFileNodes
);
3350 cifs_buf_release(pSMB
);
3359 /* We can not use write of zero bytes trick to
3360 set file size due to need for large file support. Also note that
3361 this SetPathInfo is preferred to SetFileInfo based method in next
3362 routine which is only needed to work around a sharing violation bug
3363 in Samba which this routine can run into */
3366 CIFSSMBSetEOF(const int xid
, struct cifsTconInfo
*tcon
, const char *fileName
,
3367 __u64 size
, int SetAllocation
,
3368 const struct nls_table
*nls_codepage
, int remap
)
3370 struct smb_com_transaction2_spi_req
*pSMB
= NULL
;
3371 struct smb_com_transaction2_spi_rsp
*pSMBr
= NULL
;
3372 struct file_end_of_file_info
*parm_data
;
3375 int bytes_returned
= 0;
3376 __u16 params
, byte_count
, data_count
, param_offset
, offset
;
3378 cFYI(1, ("In SetEOF"));
3380 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
3385 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
3387 cifsConvertToUCS((__le16
*) pSMB
->FileName
, fileName
,
3388 PATH_MAX
, nls_codepage
, remap
);
3389 name_len
++; /* trailing null */
3391 } else { /* BB improve the check for buffer overruns BB */
3392 name_len
= strnlen(fileName
, PATH_MAX
);
3393 name_len
++; /* trailing null */
3394 strncpy(pSMB
->FileName
, fileName
, name_len
);
3396 params
= 6 + name_len
;
3397 data_count
= sizeof (struct file_end_of_file_info
);
3398 pSMB
->MaxParameterCount
= cpu_to_le16(2);
3399 pSMB
->MaxDataCount
= cpu_to_le16(1000); /* BB find max SMB size from sess */
3400 pSMB
->MaxSetupCount
= 0;
3404 pSMB
->Reserved2
= 0;
3405 param_offset
= offsetof(struct smb_com_transaction2_spi_req
,
3406 InformationLevel
) - 4;
3407 offset
= param_offset
+ params
;
3409 if (tcon
->ses
->capabilities
& CAP_INFOLEVEL_PASSTHRU
)
3410 pSMB
->InformationLevel
=
3411 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2
);
3413 pSMB
->InformationLevel
=
3414 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO
);
3415 } else /* Set File Size */ {
3416 if (tcon
->ses
->capabilities
& CAP_INFOLEVEL_PASSTHRU
)
3417 pSMB
->InformationLevel
=
3418 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO2
);
3420 pSMB
->InformationLevel
=
3421 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO
);
3425 (struct file_end_of_file_info
*) (((char *) &pSMB
->hdr
.Protocol
) +
3427 pSMB
->ParameterOffset
= cpu_to_le16(param_offset
);
3428 pSMB
->DataOffset
= cpu_to_le16(offset
);
3429 pSMB
->SetupCount
= 1;
3430 pSMB
->Reserved3
= 0;
3431 pSMB
->SubCommand
= cpu_to_le16(TRANS2_SET_PATH_INFORMATION
);
3432 byte_count
= 3 /* pad */ + params
+ data_count
;
3433 pSMB
->DataCount
= cpu_to_le16(data_count
);
3434 pSMB
->TotalDataCount
= pSMB
->DataCount
;
3435 pSMB
->ParameterCount
= cpu_to_le16(params
);
3436 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
3437 pSMB
->Reserved4
= 0;
3438 pSMB
->hdr
.smb_buf_length
+= byte_count
;
3439 parm_data
->FileSize
= cpu_to_le64(size
);
3440 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
3441 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
3442 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
3444 cFYI(1, ("SetPathInfo (file size) returned %d", rc
));
3447 cifs_buf_release(pSMB
);
3456 CIFSSMBSetFileSize(const int xid
, struct cifsTconInfo
*tcon
, __u64 size
,
3457 __u16 fid
, __u32 pid_of_opener
, int SetAllocation
)
3459 struct smb_com_transaction2_sfi_req
*pSMB
= NULL
;
3460 struct smb_com_transaction2_sfi_rsp
*pSMBr
= NULL
;
3462 struct file_end_of_file_info
*parm_data
;
3464 int bytes_returned
= 0;
3465 __u16 params
, param_offset
, offset
, byte_count
, count
;
3467 cFYI(1, ("SetFileSize (via SetFileInfo) %lld",
3469 rc
= small_smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
);
3474 pSMBr
= (struct smb_com_transaction2_sfi_rsp
*)pSMB
;
3476 pSMB
->hdr
.Pid
= cpu_to_le16((__u16
)pid_of_opener
);
3477 pSMB
->hdr
.PidHigh
= cpu_to_le16((__u16
)(pid_of_opener
>> 16));
3480 pSMB
->MaxSetupCount
= 0;
3484 pSMB
->Reserved2
= 0;
3485 param_offset
= offsetof(struct smb_com_transaction2_sfi_req
, Fid
) - 4;
3486 offset
= param_offset
+ params
;
3488 data_offset
= (char *) (&pSMB
->hdr
.Protocol
) + offset
;
3490 count
= sizeof(struct file_end_of_file_info
);
3491 pSMB
->MaxParameterCount
= cpu_to_le16(2);
3492 pSMB
->MaxDataCount
= cpu_to_le16(1000); /* BB find max SMB PDU from sess */
3493 pSMB
->SetupCount
= 1;
3494 pSMB
->Reserved3
= 0;
3495 pSMB
->SubCommand
= cpu_to_le16(TRANS2_SET_FILE_INFORMATION
);
3496 byte_count
= 3 /* pad */ + params
+ count
;
3497 pSMB
->DataCount
= cpu_to_le16(count
);
3498 pSMB
->ParameterCount
= cpu_to_le16(params
);
3499 pSMB
->TotalDataCount
= pSMB
->DataCount
;
3500 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
3501 pSMB
->ParameterOffset
= cpu_to_le16(param_offset
);
3503 (struct file_end_of_file_info
*) (((char *) &pSMB
->hdr
.Protocol
) +
3505 pSMB
->DataOffset
= cpu_to_le16(offset
);
3506 parm_data
->FileSize
= cpu_to_le64(size
);
3509 if (tcon
->ses
->capabilities
& CAP_INFOLEVEL_PASSTHRU
)
3510 pSMB
->InformationLevel
=
3511 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2
);
3513 pSMB
->InformationLevel
=
3514 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO
);
3515 } else /* Set File Size */ {
3516 if (tcon
->ses
->capabilities
& CAP_INFOLEVEL_PASSTHRU
)
3517 pSMB
->InformationLevel
=
3518 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO2
);
3520 pSMB
->InformationLevel
=
3521 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO
);
3523 pSMB
->Reserved4
= 0;
3524 pSMB
->hdr
.smb_buf_length
+= byte_count
;
3525 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
3526 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
3527 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
3530 ("Send error in SetFileInfo (SetFileSize) = %d",
3535 cifs_small_buf_release(pSMB
);
3537 /* Note: On -EAGAIN error only caller can retry on handle based calls
3538 since file handle passed in no longer valid */
3543 /* Some legacy servers such as NT4 require that the file times be set on
3544 an open handle, rather than by pathname - this is awkward due to
3545 potential access conflicts on the open, but it is unavoidable for these
3546 old servers since the only other choice is to go from 100 nanosecond DCE
3547 time and resort to the original setpathinfo level which takes the ancient
3548 DOS time format with 2 second granularity */
3550 CIFSSMBSetFileTimes(const int xid
, struct cifsTconInfo
*tcon
, const FILE_BASIC_INFO
* data
,
3553 struct smb_com_transaction2_sfi_req
*pSMB
= NULL
;
3554 struct smb_com_transaction2_sfi_rsp
*pSMBr
= NULL
;
3557 int bytes_returned
= 0;
3558 __u16 params
, param_offset
, offset
, byte_count
, count
;
3560 cFYI(1, ("Set Times (via SetFileInfo)"));
3561 rc
= small_smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
);
3566 pSMBr
= (struct smb_com_transaction2_sfi_rsp
*)pSMB
;
3568 /* At this point there is no need to override the current pid
3569 with the pid of the opener, but that could change if we someday
3570 use an existing handle (rather than opening one on the fly) */
3571 /* pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
3572 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));*/
3575 pSMB
->MaxSetupCount
= 0;
3579 pSMB
->Reserved2
= 0;
3580 param_offset
= offsetof(struct smb_com_transaction2_sfi_req
, Fid
) - 4;
3581 offset
= param_offset
+ params
;
3583 data_offset
= (char *) (&pSMB
->hdr
.Protocol
) + offset
;
3585 count
= sizeof (FILE_BASIC_INFO
);
3586 pSMB
->MaxParameterCount
= cpu_to_le16(2);
3587 pSMB
->MaxDataCount
= cpu_to_le16(1000); /* BB find max SMB PDU from sess */
3588 pSMB
->SetupCount
= 1;
3589 pSMB
->Reserved3
= 0;
3590 pSMB
->SubCommand
= cpu_to_le16(TRANS2_SET_FILE_INFORMATION
);
3591 byte_count
= 3 /* pad */ + params
+ count
;
3592 pSMB
->DataCount
= cpu_to_le16(count
);
3593 pSMB
->ParameterCount
= cpu_to_le16(params
);
3594 pSMB
->TotalDataCount
= pSMB
->DataCount
;
3595 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
3596 pSMB
->ParameterOffset
= cpu_to_le16(param_offset
);
3597 pSMB
->DataOffset
= cpu_to_le16(offset
);
3599 if (tcon
->ses
->capabilities
& CAP_INFOLEVEL_PASSTHRU
)
3600 pSMB
->InformationLevel
= cpu_to_le16(SMB_SET_FILE_BASIC_INFO2
);
3602 pSMB
->InformationLevel
= cpu_to_le16(SMB_SET_FILE_BASIC_INFO
);
3603 pSMB
->Reserved4
= 0;
3604 pSMB
->hdr
.smb_buf_length
+= byte_count
;
3605 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
3606 memcpy(data_offset
,data
,sizeof(FILE_BASIC_INFO
));
3607 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
3608 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
3610 cFYI(1,("Send error in Set Time (SetFileInfo) = %d",rc
));
3613 cifs_small_buf_release(pSMB
);
3615 /* Note: On -EAGAIN error only caller can retry on handle based calls
3616 since file handle passed in no longer valid */
3623 CIFSSMBSetTimes(const int xid
, struct cifsTconInfo
*tcon
, const char *fileName
,
3624 const FILE_BASIC_INFO
* data
,
3625 const struct nls_table
*nls_codepage
, int remap
)
3627 TRANSACTION2_SPI_REQ
*pSMB
= NULL
;
3628 TRANSACTION2_SPI_RSP
*pSMBr
= NULL
;
3631 int bytes_returned
= 0;
3633 __u16 params
, param_offset
, offset
, byte_count
, count
;
3635 cFYI(1, ("In SetTimes"));
3638 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
3643 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
3645 cifsConvertToUCS((__le16
*) pSMB
->FileName
, fileName
,
3646 PATH_MAX
, nls_codepage
, remap
);
3647 name_len
++; /* trailing null */
3649 } else { /* BB improve the check for buffer overruns BB */
3650 name_len
= strnlen(fileName
, PATH_MAX
);
3651 name_len
++; /* trailing null */
3652 strncpy(pSMB
->FileName
, fileName
, name_len
);
3655 params
= 6 + name_len
;
3656 count
= sizeof (FILE_BASIC_INFO
);
3657 pSMB
->MaxParameterCount
= cpu_to_le16(2);
3658 pSMB
->MaxDataCount
= cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
3659 pSMB
->MaxSetupCount
= 0;
3663 pSMB
->Reserved2
= 0;
3664 param_offset
= offsetof(struct smb_com_transaction2_spi_req
,
3665 InformationLevel
) - 4;
3666 offset
= param_offset
+ params
;
3667 data_offset
= (char *) (&pSMB
->hdr
.Protocol
) + offset
;
3668 pSMB
->ParameterOffset
= cpu_to_le16(param_offset
);
3669 pSMB
->DataOffset
= cpu_to_le16(offset
);
3670 pSMB
->SetupCount
= 1;
3671 pSMB
->Reserved3
= 0;
3672 pSMB
->SubCommand
= cpu_to_le16(TRANS2_SET_PATH_INFORMATION
);
3673 byte_count
= 3 /* pad */ + params
+ count
;
3675 pSMB
->DataCount
= cpu_to_le16(count
);
3676 pSMB
->ParameterCount
= cpu_to_le16(params
);
3677 pSMB
->TotalDataCount
= pSMB
->DataCount
;
3678 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
3679 if (tcon
->ses
->capabilities
& CAP_INFOLEVEL_PASSTHRU
)
3680 pSMB
->InformationLevel
= cpu_to_le16(SMB_SET_FILE_BASIC_INFO2
);
3682 pSMB
->InformationLevel
= cpu_to_le16(SMB_SET_FILE_BASIC_INFO
);
3683 pSMB
->Reserved4
= 0;
3684 pSMB
->hdr
.smb_buf_length
+= byte_count
;
3685 memcpy(data_offset
, data
, sizeof (FILE_BASIC_INFO
));
3686 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
3687 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
3688 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
3690 cFYI(1, ("SetPathInfo (times) returned %d", rc
));
3693 cifs_buf_release(pSMB
);
3701 /* Can not be used to set time stamps yet (due to old DOS time format) */
3702 /* Can be used to set attributes */
3703 #if 0 /* Possibly not needed - since it turns out that strangely NT4 has a bug
3704 handling it anyway and NT4 was what we thought it would be needed for
3705 Do not delete it until we prove whether needed for Win9x though */
3707 CIFSSMBSetAttrLegacy(int xid
, struct cifsTconInfo
*tcon
, char *fileName
,
3708 __u16 dos_attrs
, const struct nls_table
*nls_codepage
)
3710 SETATTR_REQ
*pSMB
= NULL
;
3711 SETATTR_RSP
*pSMBr
= NULL
;
3716 cFYI(1, ("In SetAttrLegacy"));
3719 rc
= smb_init(SMB_COM_SETATTR
, 8, tcon
, (void **) &pSMB
,
3724 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
3726 ConvertToUCS((__le16
*) pSMB
->fileName
, fileName
,
3727 PATH_MAX
, nls_codepage
);
3728 name_len
++; /* trailing null */
3730 } else { /* BB improve the check for buffer overruns BB */
3731 name_len
= strnlen(fileName
, PATH_MAX
);
3732 name_len
++; /* trailing null */
3733 strncpy(pSMB
->fileName
, fileName
, name_len
);
3735 pSMB
->attr
= cpu_to_le16(dos_attrs
);
3736 pSMB
->BufferFormat
= 0x04;
3737 pSMB
->hdr
.smb_buf_length
+= name_len
+ 1;
3738 pSMB
->ByteCount
= cpu_to_le16(name_len
+ 1);
3739 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
3740 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
3742 cFYI(1, ("Error in LegacySetAttr = %d", rc
));
3745 cifs_buf_release(pSMB
);
3748 goto SetAttrLgcyRetry
;
3752 #endif /* temporarily unneeded SetAttr legacy function */
3755 CIFSSMBUnixSetPerms(const int xid
, struct cifsTconInfo
*tcon
,
3756 char *fileName
, __u64 mode
, __u64 uid
, __u64 gid
,
3757 dev_t device
, const struct nls_table
*nls_codepage
,
3760 TRANSACTION2_SPI_REQ
*pSMB
= NULL
;
3761 TRANSACTION2_SPI_RSP
*pSMBr
= NULL
;
3764 int bytes_returned
= 0;
3765 FILE_UNIX_BASIC_INFO
*data_offset
;
3766 __u16 params
, param_offset
, offset
, count
, byte_count
;
3768 cFYI(1, ("In SetUID/GID/Mode"));
3770 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
3775 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
3777 cifsConvertToUCS((__le16
*) pSMB
->FileName
, fileName
,
3778 PATH_MAX
, nls_codepage
, remap
);
3779 name_len
++; /* trailing null */
3781 } else { /* BB improve the check for buffer overruns BB */
3782 name_len
= strnlen(fileName
, PATH_MAX
);
3783 name_len
++; /* trailing null */
3784 strncpy(pSMB
->FileName
, fileName
, name_len
);
3787 params
= 6 + name_len
;
3788 count
= sizeof (FILE_UNIX_BASIC_INFO
);
3789 pSMB
->MaxParameterCount
= cpu_to_le16(2);
3790 pSMB
->MaxDataCount
= cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
3791 pSMB
->MaxSetupCount
= 0;
3795 pSMB
->Reserved2
= 0;
3796 param_offset
= offsetof(struct smb_com_transaction2_spi_req
,
3797 InformationLevel
) - 4;
3798 offset
= param_offset
+ params
;
3800 (FILE_UNIX_BASIC_INFO
*) ((char *) &pSMB
->hdr
.Protocol
+
3802 memset(data_offset
, 0, count
);
3803 pSMB
->DataOffset
= cpu_to_le16(offset
);
3804 pSMB
->ParameterOffset
= cpu_to_le16(param_offset
);
3805 pSMB
->SetupCount
= 1;
3806 pSMB
->Reserved3
= 0;
3807 pSMB
->SubCommand
= cpu_to_le16(TRANS2_SET_PATH_INFORMATION
);
3808 byte_count
= 3 /* pad */ + params
+ count
;
3809 pSMB
->ParameterCount
= cpu_to_le16(params
);
3810 pSMB
->DataCount
= cpu_to_le16(count
);
3811 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
3812 pSMB
->TotalDataCount
= pSMB
->DataCount
;
3813 pSMB
->InformationLevel
= cpu_to_le16(SMB_SET_FILE_UNIX_BASIC
);
3814 pSMB
->Reserved4
= 0;
3815 pSMB
->hdr
.smb_buf_length
+= byte_count
;
3816 data_offset
->Uid
= cpu_to_le64(uid
);
3817 data_offset
->Gid
= cpu_to_le64(gid
);
3818 /* better to leave device as zero when it is */
3819 data_offset
->DevMajor
= cpu_to_le64(MAJOR(device
));
3820 data_offset
->DevMinor
= cpu_to_le64(MINOR(device
));
3821 data_offset
->Permissions
= cpu_to_le64(mode
);
3824 data_offset
->Type
= cpu_to_le32(UNIX_FILE
);
3825 else if(S_ISDIR(mode
))
3826 data_offset
->Type
= cpu_to_le32(UNIX_DIR
);
3827 else if(S_ISLNK(mode
))
3828 data_offset
->Type
= cpu_to_le32(UNIX_SYMLINK
);
3829 else if(S_ISCHR(mode
))
3830 data_offset
->Type
= cpu_to_le32(UNIX_CHARDEV
);
3831 else if(S_ISBLK(mode
))
3832 data_offset
->Type
= cpu_to_le32(UNIX_BLOCKDEV
);
3833 else if(S_ISFIFO(mode
))
3834 data_offset
->Type
= cpu_to_le32(UNIX_FIFO
);
3835 else if(S_ISSOCK(mode
))
3836 data_offset
->Type
= cpu_to_le32(UNIX_SOCKET
);
3839 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
3840 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
3841 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
3843 cFYI(1, ("SetPathInfo (perms) returned %d", rc
));
3847 cifs_buf_release(pSMB
);
3853 int CIFSSMBNotify(const int xid
, struct cifsTconInfo
*tcon
,
3854 const int notify_subdirs
, const __u16 netfid
,
3855 __u32 filter
, const struct nls_table
*nls_codepage
)
3858 struct smb_com_transaction_change_notify_req
* pSMB
= NULL
;
3859 struct smb_com_transaction_change_notify_rsp
* pSMBr
= NULL
;
3862 cFYI(1, ("In CIFSSMBNotify for file handle %d",(int)netfid
));
3863 rc
= smb_init(SMB_COM_NT_TRANSACT
, 23, tcon
, (void **) &pSMB
,
3868 pSMB
->TotalParameterCount
= 0 ;
3869 pSMB
->TotalDataCount
= 0;
3870 pSMB
->MaxParameterCount
= cpu_to_le32(2);
3871 /* BB find exact data count max from sess structure BB */
3872 pSMB
->MaxDataCount
= 0; /* same in little endian or be */
3873 pSMB
->MaxSetupCount
= 4;
3875 pSMB
->ParameterOffset
= 0;
3876 pSMB
->DataCount
= 0;
3877 pSMB
->DataOffset
= 0;
3878 pSMB
->SetupCount
= 4; /* single byte does not need le conversion */
3879 pSMB
->SubCommand
= cpu_to_le16(NT_TRANSACT_NOTIFY_CHANGE
);
3880 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
3882 pSMB
->WatchTree
= 1; /* one byte - no le conversion needed */
3883 pSMB
->Reserved2
= 0;
3884 pSMB
->CompletionFilter
= cpu_to_le32(filter
);
3885 pSMB
->Fid
= netfid
; /* file handle always le */
3886 pSMB
->ByteCount
= 0;
3888 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
3889 (struct smb_hdr
*) pSMBr
, &bytes_returned
, -1);
3891 cFYI(1, ("Error in Notify = %d", rc
));
3893 cifs_buf_release(pSMB
);
3896 #ifdef CONFIG_CIFS_XATTR
3898 CIFSSMBQAllEAs(const int xid
, struct cifsTconInfo
*tcon
,
3899 const unsigned char *searchName
,
3900 char * EAData
, size_t buf_size
,
3901 const struct nls_table
*nls_codepage
, int remap
)
3903 /* BB assumes one setup word */
3904 TRANSACTION2_QPI_REQ
*pSMB
= NULL
;
3905 TRANSACTION2_QPI_RSP
*pSMBr
= NULL
;
3909 struct fea
* temp_fea
;
3911 __u16 params
, byte_count
;
3913 cFYI(1, ("In Query All EAs path %s", searchName
));
3915 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
3920 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
3922 cifsConvertToUCS((__le16
*) pSMB
->FileName
, searchName
,
3923 PATH_MAX
, nls_codepage
, remap
);
3924 name_len
++; /* trailing null */
3926 } else { /* BB improve the check for buffer overruns BB */
3927 name_len
= strnlen(searchName
, PATH_MAX
);
3928 name_len
++; /* trailing null */
3929 strncpy(pSMB
->FileName
, searchName
, name_len
);
3932 params
= 2 /* level */ + 4 /* reserved */ + name_len
/* includes NUL */ ;
3933 pSMB
->TotalDataCount
= 0;
3934 pSMB
->MaxParameterCount
= cpu_to_le16(2);
3935 pSMB
->MaxDataCount
= cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
3936 pSMB
->MaxSetupCount
= 0;
3940 pSMB
->Reserved2
= 0;
3941 pSMB
->ParameterOffset
= cpu_to_le16(offsetof(
3942 struct smb_com_transaction2_qpi_req
,InformationLevel
) - 4);
3943 pSMB
->DataCount
= 0;
3944 pSMB
->DataOffset
= 0;
3945 pSMB
->SetupCount
= 1;
3946 pSMB
->Reserved3
= 0;
3947 pSMB
->SubCommand
= cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION
);
3948 byte_count
= params
+ 1 /* pad */ ;
3949 pSMB
->TotalParameterCount
= cpu_to_le16(params
);
3950 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
3951 pSMB
->InformationLevel
= cpu_to_le16(SMB_INFO_QUERY_ALL_EAS
);
3952 pSMB
->Reserved4
= 0;
3953 pSMB
->hdr
.smb_buf_length
+= byte_count
;
3954 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
3956 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
3957 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
3959 cFYI(1, ("Send error in QueryAllEAs = %d", rc
));
3960 } else { /* decode response */
3961 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
3963 /* BB also check enough total bytes returned */
3964 /* BB we need to improve the validity checking
3965 of these trans2 responses */
3966 if (rc
|| (pSMBr
->ByteCount
< 4))
3967 rc
= -EIO
; /* bad smb */
3968 /* else if (pFindData){
3969 memcpy((char *) pFindData,
3970 (char *) &pSMBr->hdr.Protocol +
3973 /* check that length of list is not more than bcc */
3974 /* check that each entry does not go beyond length
3976 /* check that each element of each entry does not
3977 go beyond end of list */
3978 __u16 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
3979 struct fealist
* ea_response_data
;
3981 /* validate_trans2_offsets() */
3982 /* BB to check if(start of smb + data_offset > &bcc+ bcc)*/
3983 ea_response_data
= (struct fealist
*)
3984 (((char *) &pSMBr
->hdr
.Protocol
) +
3986 name_len
= le32_to_cpu(ea_response_data
->list_len
);
3987 cFYI(1,("ea length %d", name_len
));
3989 /* returned EA size zeroed at top of function */
3990 cFYI(1,("empty EA list returned from server"));
3992 /* account for ea list len */
3994 temp_fea
= ea_response_data
->list
;
3995 temp_ptr
= (char *)temp_fea
;
3996 while(name_len
> 0) {
4000 rc
+= temp_fea
->name_len
;
4001 /* account for prefix user. and trailing null */
4003 if(rc
<(int)buf_size
) {
4004 memcpy(EAData
,"user.",5);
4006 memcpy(EAData
,temp_ptr
,temp_fea
->name_len
);
4007 EAData
+=temp_fea
->name_len
;
4008 /* null terminate name */
4010 EAData
= EAData
+ 1;
4011 } else if(buf_size
== 0) {
4012 /* skip copy - calc size only */
4014 /* stop before overrun buffer */
4018 name_len
-= temp_fea
->name_len
;
4019 temp_ptr
+= temp_fea
->name_len
;
4020 /* account for trailing null */
4023 value_len
= le16_to_cpu(temp_fea
->value_len
);
4024 name_len
-= value_len
;
4025 temp_ptr
+= value_len
;
4026 /* BB check that temp_ptr is still within smb BB*/
4027 /* no trailing null to account for in value len */
4028 /* go on to next EA */
4029 temp_fea
= (struct fea
*)temp_ptr
;
4035 cifs_buf_release(pSMB
);
4042 ssize_t
CIFSSMBQueryEA(const int xid
,struct cifsTconInfo
* tcon
,
4043 const unsigned char * searchName
,const unsigned char * ea_name
,
4044 unsigned char * ea_value
, size_t buf_size
,
4045 const struct nls_table
*nls_codepage
, int remap
)
4047 TRANSACTION2_QPI_REQ
*pSMB
= NULL
;
4048 TRANSACTION2_QPI_RSP
*pSMBr
= NULL
;
4052 struct fea
* temp_fea
;
4054 __u16 params
, byte_count
;
4056 cFYI(1, ("In Query EA path %s", searchName
));
4058 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
4063 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
4065 cifsConvertToUCS((__le16
*) pSMB
->FileName
, searchName
,
4066 PATH_MAX
, nls_codepage
, remap
);
4067 name_len
++; /* trailing null */
4069 } else { /* BB improve the check for buffer overruns BB */
4070 name_len
= strnlen(searchName
, PATH_MAX
);
4071 name_len
++; /* trailing null */
4072 strncpy(pSMB
->FileName
, searchName
, name_len
);
4075 params
= 2 /* level */ + 4 /* reserved */ + name_len
/* includes NUL */ ;
4076 pSMB
->TotalDataCount
= 0;
4077 pSMB
->MaxParameterCount
= cpu_to_le16(2);
4078 pSMB
->MaxDataCount
= cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
4079 pSMB
->MaxSetupCount
= 0;
4083 pSMB
->Reserved2
= 0;
4084 pSMB
->ParameterOffset
= cpu_to_le16(offsetof(
4085 struct smb_com_transaction2_qpi_req
,InformationLevel
) - 4);
4086 pSMB
->DataCount
= 0;
4087 pSMB
->DataOffset
= 0;
4088 pSMB
->SetupCount
= 1;
4089 pSMB
->Reserved3
= 0;
4090 pSMB
->SubCommand
= cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION
);
4091 byte_count
= params
+ 1 /* pad */ ;
4092 pSMB
->TotalParameterCount
= cpu_to_le16(params
);
4093 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
4094 pSMB
->InformationLevel
= cpu_to_le16(SMB_INFO_QUERY_ALL_EAS
);
4095 pSMB
->Reserved4
= 0;
4096 pSMB
->hdr
.smb_buf_length
+= byte_count
;
4097 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
4099 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
4100 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
4102 cFYI(1, ("Send error in Query EA = %d", rc
));
4103 } else { /* decode response */
4104 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
4106 /* BB also check enough total bytes returned */
4107 /* BB we need to improve the validity checking
4108 of these trans2 responses */
4109 if (rc
|| (pSMBr
->ByteCount
< 4))
4110 rc
= -EIO
; /* bad smb */
4111 /* else if (pFindData){
4112 memcpy((char *) pFindData,
4113 (char *) &pSMBr->hdr.Protocol +
4116 /* check that length of list is not more than bcc */
4117 /* check that each entry does not go beyond length
4119 /* check that each element of each entry does not
4120 go beyond end of list */
4121 __u16 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
4122 struct fealist
* ea_response_data
;
4124 /* validate_trans2_offsets() */
4125 /* BB to check if(start of smb + data_offset > &bcc+ bcc)*/
4126 ea_response_data
= (struct fealist
*)
4127 (((char *) &pSMBr
->hdr
.Protocol
) +
4129 name_len
= le32_to_cpu(ea_response_data
->list_len
);
4130 cFYI(1,("ea length %d", name_len
));
4132 /* returned EA size zeroed at top of function */
4133 cFYI(1,("empty EA list returned from server"));
4135 /* account for ea list len */
4137 temp_fea
= ea_response_data
->list
;
4138 temp_ptr
= (char *)temp_fea
;
4139 /* loop through checking if we have a matching
4140 name and then return the associated value */
4141 while(name_len
> 0) {
4145 value_len
= le16_to_cpu(temp_fea
->value_len
);
4146 /* BB validate that value_len falls within SMB,
4147 even though maximum for name_len is 255 */
4148 if(memcmp(temp_fea
->name
,ea_name
,
4149 temp_fea
->name_len
) == 0) {
4152 /* account for prefix user. and trailing null */
4153 if(rc
<=(int)buf_size
) {
4155 temp_fea
->name
+temp_fea
->name_len
+1,
4157 /* ea values, unlike ea names,
4158 are not null terminated */
4159 } else if(buf_size
== 0) {
4160 /* skip copy - calc size only */
4162 /* stop before overrun buffer */
4167 name_len
-= temp_fea
->name_len
;
4168 temp_ptr
+= temp_fea
->name_len
;
4169 /* account for trailing null */
4172 name_len
-= value_len
;
4173 temp_ptr
+= value_len
;
4174 /* no trailing null to account for in value len */
4175 /* go on to next EA */
4176 temp_fea
= (struct fea
*)temp_ptr
;
4182 cifs_buf_release(pSMB
);
4190 CIFSSMBSetEA(const int xid
, struct cifsTconInfo
*tcon
, const char *fileName
,
4191 const char * ea_name
, const void * ea_value
,
4192 const __u16 ea_value_len
, const struct nls_table
*nls_codepage
,
4195 struct smb_com_transaction2_spi_req
*pSMB
= NULL
;
4196 struct smb_com_transaction2_spi_rsp
*pSMBr
= NULL
;
4197 struct fealist
*parm_data
;
4200 int bytes_returned
= 0;
4201 __u16 params
, param_offset
, byte_count
, offset
, count
;
4203 cFYI(1, ("In SetEA"));
4205 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
4210 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
4212 cifsConvertToUCS((__le16
*) pSMB
->FileName
, fileName
,
4213 PATH_MAX
, nls_codepage
, remap
);
4214 name_len
++; /* trailing null */
4216 } else { /* BB improve the check for buffer overruns BB */
4217 name_len
= strnlen(fileName
, PATH_MAX
);
4218 name_len
++; /* trailing null */
4219 strncpy(pSMB
->FileName
, fileName
, name_len
);
4222 params
= 6 + name_len
;
4224 /* done calculating parms using name_len of file name,
4225 now use name_len to calculate length of ea name
4226 we are going to create in the inode xattrs */
4230 name_len
= strnlen(ea_name
,255);
4232 count
= sizeof(*parm_data
) + ea_value_len
+ name_len
+ 1;
4233 pSMB
->MaxParameterCount
= cpu_to_le16(2);
4234 pSMB
->MaxDataCount
= cpu_to_le16(1000); /* BB find max SMB size from sess */
4235 pSMB
->MaxSetupCount
= 0;
4239 pSMB
->Reserved2
= 0;
4240 param_offset
= offsetof(struct smb_com_transaction2_spi_req
,
4241 InformationLevel
) - 4;
4242 offset
= param_offset
+ params
;
4243 pSMB
->InformationLevel
=
4244 cpu_to_le16(SMB_SET_FILE_EA
);
4247 (struct fealist
*) (((char *) &pSMB
->hdr
.Protocol
) +
4249 pSMB
->ParameterOffset
= cpu_to_le16(param_offset
);
4250 pSMB
->DataOffset
= cpu_to_le16(offset
);
4251 pSMB
->SetupCount
= 1;
4252 pSMB
->Reserved3
= 0;
4253 pSMB
->SubCommand
= cpu_to_le16(TRANS2_SET_PATH_INFORMATION
);
4254 byte_count
= 3 /* pad */ + params
+ count
;
4255 pSMB
->DataCount
= cpu_to_le16(count
);
4256 parm_data
->list_len
= cpu_to_le32(count
);
4257 parm_data
->list
[0].EA_flags
= 0;
4258 /* we checked above that name len is less than 255 */
4259 parm_data
->list
[0].name_len
= (__u8
)name_len
;;
4260 /* EA names are always ASCII */
4262 strncpy(parm_data
->list
[0].name
,ea_name
,name_len
);
4263 parm_data
->list
[0].name
[name_len
] = 0;
4264 parm_data
->list
[0].value_len
= cpu_to_le16(ea_value_len
);
4265 /* caller ensures that ea_value_len is less than 64K but
4266 we need to ensure that it fits within the smb */
4268 /*BB add length check that it would fit in negotiated SMB buffer size BB */
4269 /* if(ea_value_len > buffer_size - 512 (enough for header)) */
4271 memcpy(parm_data
->list
[0].name
+name_len
+1,ea_value
,ea_value_len
);
4273 pSMB
->TotalDataCount
= pSMB
->DataCount
;
4274 pSMB
->ParameterCount
= cpu_to_le16(params
);
4275 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
4276 pSMB
->Reserved4
= 0;
4277 pSMB
->hdr
.smb_buf_length
+= byte_count
;
4278 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
4279 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
4280 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
4282 cFYI(1, ("SetPathInfo (EA) returned %d", rc
));
4285 cifs_buf_release(pSMB
);