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 to this tcon */
81 /* If the return code is zero, this function must fill in request_buf pointer */
83 small_smb_init(int smb_command
, int wct
, struct cifsTconInfo
*tcon
,
84 void **request_buf
/* returned */)
88 /* SMBs NegProt, SessSetup, uLogoff do not have tcon yet so
89 check for tcp and smb session status done differently
90 for those three - in the calling routine */
92 if((tcon
->ses
) && (tcon
->ses
->server
)){
93 struct nls_table
*nls_codepage
;
94 /* Give Demultiplex thread up to 10 seconds to
95 reconnect, should be greater than cifs socket
96 timeout which is 7 seconds */
97 while(tcon
->ses
->server
->tcpStatus
== CifsNeedReconnect
) {
98 wait_event_interruptible_timeout(tcon
->ses
->server
->response_q
,
99 (tcon
->ses
->server
->tcpStatus
== CifsGood
), 10 * HZ
);
100 if(tcon
->ses
->server
->tcpStatus
== CifsNeedReconnect
) {
101 /* on "soft" mounts we wait once */
102 if((tcon
->retry
== FALSE
) ||
103 (tcon
->ses
->status
== CifsExiting
)) {
104 cFYI(1,("gave up waiting on reconnect in smb_init"));
106 } /* else "hard" mount - keep retrying until
107 process is killed or server comes back up */
108 } else /* TCP session is reestablished now */
113 nls_codepage
= load_nls_default();
114 /* need to prevent multiple threads trying to
115 simultaneously reconnect the same SMB session */
116 down(&tcon
->ses
->sesSem
);
117 if(tcon
->ses
->status
== CifsNeedReconnect
)
118 rc
= cifs_setup_session(0, tcon
->ses
, nls_codepage
);
119 if(!rc
&& (tcon
->tidStatus
== CifsNeedReconnect
)) {
120 mark_open_files_invalid(tcon
);
121 rc
= CIFSTCon(0, tcon
->ses
, tcon
->treeName
, tcon
,
123 up(&tcon
->ses
->sesSem
);
125 atomic_inc(&tconInfoReconnectCount
);
127 cFYI(1, ("reconnect tcon rc = %d", rc
));
128 /* Removed call to reopen open files here -
129 it is safer (and faster) to reopen files
130 one at a time as needed in read and write */
132 /* Check if handle based operation so we
133 know whether we can continue or not without
134 returning to caller to reset file handle */
135 switch(smb_command
) {
136 case SMB_COM_READ_ANDX
:
137 case SMB_COM_WRITE_ANDX
:
139 case SMB_COM_FIND_CLOSE2
:
140 case SMB_COM_LOCKING_ANDX
: {
141 unload_nls(nls_codepage
);
146 up(&tcon
->ses
->sesSem
);
148 unload_nls(nls_codepage
);
157 *request_buf
= cifs_small_buf_get();
158 if (*request_buf
== NULL
) {
159 /* BB should we add a retry in here if not a writepage? */
163 header_assemble((struct smb_hdr
*) *request_buf
, smb_command
, tcon
,wct
);
165 #ifdef CONFIG_CIFS_STATS
167 atomic_inc(&tcon
->num_smbs_sent
);
169 #endif /* CONFIG_CIFS_STATS */
173 /* If the return code is zero, this function must fill in request_buf pointer */
175 smb_init(int smb_command
, int wct
, struct cifsTconInfo
*tcon
,
176 void **request_buf
/* returned */ ,
177 void **response_buf
/* returned */ )
181 /* SMBs NegProt, SessSetup, uLogoff do not have tcon yet so
182 check for tcp and smb session status done differently
183 for those three - in the calling routine */
185 if((tcon
->ses
) && (tcon
->ses
->server
)){
186 struct nls_table
*nls_codepage
;
187 /* Give Demultiplex thread up to 10 seconds to
188 reconnect, should be greater than cifs socket
189 timeout which is 7 seconds */
190 while(tcon
->ses
->server
->tcpStatus
== CifsNeedReconnect
) {
191 wait_event_interruptible_timeout(tcon
->ses
->server
->response_q
,
192 (tcon
->ses
->server
->tcpStatus
== CifsGood
), 10 * HZ
);
193 if(tcon
->ses
->server
->tcpStatus
== CifsNeedReconnect
) {
194 /* on "soft" mounts we wait once */
195 if((tcon
->retry
== FALSE
) ||
196 (tcon
->ses
->status
== CifsExiting
)) {
197 cFYI(1,("gave up waiting on reconnect in smb_init"));
199 } /* else "hard" mount - keep retrying until
200 process is killed or server comes back up */
201 } else /* TCP session is reestablished now */
206 nls_codepage
= load_nls_default();
207 /* need to prevent multiple threads trying to
208 simultaneously reconnect the same SMB session */
209 down(&tcon
->ses
->sesSem
);
210 if(tcon
->ses
->status
== CifsNeedReconnect
)
211 rc
= cifs_setup_session(0, tcon
->ses
, nls_codepage
);
212 if(!rc
&& (tcon
->tidStatus
== CifsNeedReconnect
)) {
213 mark_open_files_invalid(tcon
);
214 rc
= CIFSTCon(0, tcon
->ses
, tcon
->treeName
, tcon
,
216 up(&tcon
->ses
->sesSem
);
218 atomic_inc(&tconInfoReconnectCount
);
220 cFYI(1, ("reconnect tcon rc = %d", rc
));
221 /* Removed call to reopen open files here -
222 it is safer (and faster) to reopen files
223 one at a time as needed in read and write */
225 /* Check if handle based operation so we
226 know whether we can continue or not without
227 returning to caller to reset file handle */
228 switch(smb_command
) {
229 case SMB_COM_READ_ANDX
:
230 case SMB_COM_WRITE_ANDX
:
232 case SMB_COM_FIND_CLOSE2
:
233 case SMB_COM_LOCKING_ANDX
: {
234 unload_nls(nls_codepage
);
239 up(&tcon
->ses
->sesSem
);
241 unload_nls(nls_codepage
);
250 *request_buf
= cifs_buf_get();
251 if (*request_buf
== NULL
) {
252 /* BB should we add a retry in here if not a writepage? */
255 /* Although the original thought was we needed the response buf for */
256 /* potential retries of smb operations it turns out we can determine */
257 /* from the mid flags when the request buffer can be resent without */
258 /* having to use a second distinct buffer for the response */
259 *response_buf
= *request_buf
;
261 header_assemble((struct smb_hdr
*) *request_buf
, smb_command
, tcon
,
264 #ifdef CONFIG_CIFS_STATS
266 atomic_inc(&tcon
->num_smbs_sent
);
268 #endif /* CONFIG_CIFS_STATS */
272 static int validate_t2(struct smb_t2_rsp
* pSMB
)
278 /* check for plausible wct, bcc and t2 data and parm sizes */
279 /* check for parm and data offset going beyond end of smb */
280 if(pSMB
->hdr
.WordCount
>= 10) {
281 if((le16_to_cpu(pSMB
->t2_rsp
.ParameterOffset
) <= 1024) &&
282 (le16_to_cpu(pSMB
->t2_rsp
.DataOffset
) <= 1024)) {
283 /* check that bcc is at least as big as parms + data */
284 /* check that bcc is less than negotiated smb buffer */
285 total_size
= le16_to_cpu(pSMB
->t2_rsp
.ParameterCount
);
286 if(total_size
< 512) {
287 total_size
+=le16_to_cpu(pSMB
->t2_rsp
.DataCount
);
288 /* BCC le converted in SendReceive */
289 pBCC
= (pSMB
->hdr
.WordCount
* 2) + sizeof(struct smb_hdr
) +
291 if((total_size
<= (*(u16
*)pBCC
)) &&
293 CIFSMaxBufSize
+MAX_CIFS_HDR_SIZE
)) {
300 cifs_dump_mem("Invalid transact2 SMB: ",(char *)pSMB
,
301 sizeof(struct smb_t2_rsp
) + 16);
305 CIFSSMBNegotiate(unsigned int xid
, struct cifsSesInfo
*ses
)
308 NEGOTIATE_RSP
*pSMBr
;
311 struct TCP_Server_Info
* server
;
315 server
= ses
->server
;
320 rc
= smb_init(SMB_COM_NEGOTIATE
, 0, NULL
/* no tcon yet */ ,
321 (void **) &pSMB
, (void **) &pSMBr
);
325 pSMB
->hdr
.Flags2
|= SMBFLG2_UNICODE
;
326 if (extended_security
)
327 pSMB
->hdr
.Flags2
|= SMBFLG2_EXT_SEC
;
329 count
= strlen(protocols
[0].name
) + 1;
330 strncpy(pSMB
->DialectsArray
, protocols
[0].name
, 30);
331 /* null guaranteed to be at end of source and target buffers anyway */
333 pSMB
->hdr
.smb_buf_length
+= count
;
334 pSMB
->ByteCount
= cpu_to_le16(count
);
336 rc
= SendReceive(xid
, ses
, (struct smb_hdr
*) pSMB
,
337 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
339 server
->secMode
= pSMBr
->SecurityMode
;
340 server
->secType
= NTLM
; /* BB override default for NTLMv2 or krb*/
341 /* one byte - no need to convert this or EncryptionKeyLen from le,*/
342 server
->maxReq
= le16_to_cpu(pSMBr
->MaxMpxCount
);
343 /* probably no need to store and check maxvcs */
345 min(le32_to_cpu(pSMBr
->MaxBufferSize
),
346 (__u32
) CIFSMaxBufSize
+ MAX_CIFS_HDR_SIZE
);
347 server
->maxRw
= le32_to_cpu(pSMBr
->MaxRawSize
);
348 cFYI(0, ("Max buf = %d ", ses
->server
->maxBuf
));
349 GETU32(ses
->server
->sessid
) = le32_to_cpu(pSMBr
->SessionKey
);
350 server
->capabilities
= le32_to_cpu(pSMBr
->Capabilities
);
351 server
->timeZone
= le16_to_cpu(pSMBr
->ServerTimeZone
);
352 /* BB with UTC do we ever need to be using srvr timezone? */
353 if (pSMBr
->EncryptionKeyLength
== CIFS_CRYPTO_KEY_SIZE
) {
354 memcpy(server
->cryptKey
, pSMBr
->u
.EncryptionKey
,
355 CIFS_CRYPTO_KEY_SIZE
);
356 } else if ((pSMBr
->hdr
.Flags2
& SMBFLG2_EXT_SEC
)
357 && (pSMBr
->EncryptionKeyLength
== 0)) {
358 /* decode security blob */
362 /* BB might be helpful to save off the domain of server here */
364 if ((pSMBr
->hdr
.Flags2
& SMBFLG2_EXT_SEC
) &&
365 (server
->capabilities
& CAP_EXTENDED_SECURITY
)) {
366 count
= pSMBr
->ByteCount
;
369 else if (count
== 16) {
370 server
->secType
= RawNTLMSSP
;
371 if (server
->socketUseCount
.counter
> 1) {
373 (server
->server_GUID
,
374 pSMBr
->u
.extended_response
.
377 ("UID of server does not match previous connection to same ip address"));
385 memcpy(server
->server_GUID
,
386 pSMBr
->u
.extended_response
.
389 rc
= decode_negTokenInit(pSMBr
->u
.
395 /* BB Need to fill struct for sessetup here */
402 server
->capabilities
&= ~CAP_EXTENDED_SECURITY
;
403 if(sign_CIFS_PDUs
== FALSE
) {
404 if(server
->secMode
& SECMODE_SIGN_REQUIRED
)
406 ("Server requires /proc/fs/cifs/PacketSigningEnabled"));
407 server
->secMode
&= ~(SECMODE_SIGN_ENABLED
| SECMODE_SIGN_REQUIRED
);
408 } else if(sign_CIFS_PDUs
== 1) {
409 if((server
->secMode
& SECMODE_SIGN_REQUIRED
) == 0)
410 server
->secMode
&= ~(SECMODE_SIGN_ENABLED
| SECMODE_SIGN_REQUIRED
);
415 cifs_buf_release(pSMB
);
420 CIFSSMBTDis(const int xid
, struct cifsTconInfo
*tcon
)
422 struct smb_hdr
*smb_buffer
;
423 struct smb_hdr
*smb_buffer_response
; /* BB removeme BB */
427 cFYI(1, ("In tree disconnect"));
429 * If last user of the connection and
430 * connection alive - disconnect it
431 * If this is the last connection on the server session disconnect it
432 * (and inside session disconnect we should check if tcp socket needs
433 * to be freed and kernel thread woken up).
436 down(&tcon
->tconSem
);
440 atomic_dec(&tcon
->useCount
);
441 if (atomic_read(&tcon
->useCount
) > 0) {
446 /* No need to return error on this operation if tid invalidated and
447 closed on server already e.g. due to tcp session crashing */
448 if(tcon
->tidStatus
== CifsNeedReconnect
) {
453 if((tcon
->ses
== NULL
) || (tcon
->ses
->server
== NULL
)) {
457 rc
= small_smb_init(SMB_COM_TREE_DISCONNECT
, 0, tcon
, (void **)&smb_buffer
);
462 smb_buffer_response
= smb_buffer
; /* BB removeme BB */
464 rc
= SendReceive(xid
, tcon
->ses
, smb_buffer
, smb_buffer_response
,
467 cFYI(1, (" Tree disconnect failed %d", rc
));
470 cifs_small_buf_release(smb_buffer
);
473 /* No need to return error on this operation if tid invalidated and
474 closed on server already e.g. due to tcp session crashing */
482 CIFSSMBLogoff(const int xid
, struct cifsSesInfo
*ses
)
484 struct smb_hdr
*smb_buffer_response
;
485 LOGOFF_ANDX_REQ
*pSMB
;
489 cFYI(1, ("In SMBLogoff for session disconnect"));
495 atomic_dec(&ses
->inUse
);
496 if (atomic_read(&ses
->inUse
) > 0) {
500 rc
= small_smb_init(SMB_COM_LOGOFF_ANDX
, 2, NULL
, (void **)&pSMB
);
506 smb_buffer_response
= (struct smb_hdr
*)pSMB
; /* BB removeme BB */
509 if(ses
->server
->secMode
&
510 (SECMODE_SIGN_REQUIRED
| SECMODE_SIGN_ENABLED
))
511 pSMB
->hdr
.Flags2
|= SMBFLG2_SECURITY_SIGNATURE
;
514 pSMB
->hdr
.Uid
= ses
->Suid
;
516 pSMB
->AndXCommand
= 0xFF;
517 rc
= SendReceive(xid
, ses
, (struct smb_hdr
*) pSMB
,
518 smb_buffer_response
, &length
, 0);
520 atomic_dec(&ses
->server
->socketUseCount
);
521 if (atomic_read(&ses
->server
->socketUseCount
) == 0) {
522 spin_lock(&GlobalMid_Lock
);
523 ses
->server
->tcpStatus
= CifsExiting
;
524 spin_unlock(&GlobalMid_Lock
);
529 cifs_small_buf_release(pSMB
);
532 /* if session dead then we do not need to do ulogoff,
533 since server closed smb session, no sense reporting
541 CIFSSMBDelFile(const int xid
, struct cifsTconInfo
*tcon
, const char *fileName
,
542 const struct nls_table
*nls_codepage
, int remap
)
544 DELETE_FILE_REQ
*pSMB
= NULL
;
545 DELETE_FILE_RSP
*pSMBr
= NULL
;
551 rc
= smb_init(SMB_COM_DELETE
, 1, tcon
, (void **) &pSMB
,
556 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
558 cifsConvertToUCS((__u16
*) pSMB
->fileName
, fileName
,
559 PATH_MAX
, nls_codepage
, remap
);
560 name_len
++; /* trailing null */
562 } else { /* BB improve the check for buffer overruns BB */
563 name_len
= strnlen(fileName
, PATH_MAX
);
564 name_len
++; /* trailing null */
565 strncpy(pSMB
->fileName
, fileName
, name_len
);
567 pSMB
->SearchAttributes
=
568 cpu_to_le16(ATTR_READONLY
| ATTR_HIDDEN
| ATTR_SYSTEM
);
569 pSMB
->BufferFormat
= 0x04;
570 pSMB
->hdr
.smb_buf_length
+= name_len
+ 1;
571 pSMB
->ByteCount
= cpu_to_le16(name_len
+ 1);
572 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
573 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
575 cFYI(1, ("Error in RMFile = %d", rc
));
577 #ifdef CONFIG_CIFS_STATS
579 atomic_inc(&tcon
->num_deletes
);
583 cifs_buf_release(pSMB
);
591 CIFSSMBRmDir(const int xid
, struct cifsTconInfo
*tcon
, const char *dirName
,
592 const struct nls_table
*nls_codepage
, int remap
)
594 DELETE_DIRECTORY_REQ
*pSMB
= NULL
;
595 DELETE_DIRECTORY_RSP
*pSMBr
= NULL
;
600 cFYI(1, ("In CIFSSMBRmDir"));
602 rc
= smb_init(SMB_COM_DELETE_DIRECTORY
, 0, tcon
, (void **) &pSMB
,
607 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
608 name_len
= cifsConvertToUCS((__le16
*) pSMB
->DirName
, dirName
,
609 PATH_MAX
, nls_codepage
, remap
);
610 name_len
++; /* trailing null */
612 } else { /* BB improve the check for buffer overruns BB */
613 name_len
= strnlen(dirName
, PATH_MAX
);
614 name_len
++; /* trailing null */
615 strncpy(pSMB
->DirName
, dirName
, name_len
);
618 pSMB
->BufferFormat
= 0x04;
619 pSMB
->hdr
.smb_buf_length
+= name_len
+ 1;
620 pSMB
->ByteCount
= cpu_to_le16(name_len
+ 1);
621 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
622 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
624 cFYI(1, ("Error in RMDir = %d", rc
));
626 #ifdef CONFIG_CIFS_STATS
628 atomic_inc(&tcon
->num_rmdirs
);
632 cifs_buf_release(pSMB
);
639 CIFSSMBMkDir(const int xid
, struct cifsTconInfo
*tcon
,
640 const char *name
, const struct nls_table
*nls_codepage
, int remap
)
643 CREATE_DIRECTORY_REQ
*pSMB
= NULL
;
644 CREATE_DIRECTORY_RSP
*pSMBr
= NULL
;
648 cFYI(1, ("In CIFSSMBMkDir"));
650 rc
= smb_init(SMB_COM_CREATE_DIRECTORY
, 0, tcon
, (void **) &pSMB
,
655 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
656 name_len
= cifsConvertToUCS((__u16
*) pSMB
->DirName
, name
,
657 PATH_MAX
, nls_codepage
, remap
);
658 name_len
++; /* trailing null */
660 } else { /* BB improve the check for buffer overruns BB */
661 name_len
= strnlen(name
, PATH_MAX
);
662 name_len
++; /* trailing null */
663 strncpy(pSMB
->DirName
, name
, name_len
);
666 pSMB
->BufferFormat
= 0x04;
667 pSMB
->hdr
.smb_buf_length
+= name_len
+ 1;
668 pSMB
->ByteCount
= cpu_to_le16(name_len
+ 1);
669 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
670 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
672 cFYI(1, ("Error in Mkdir = %d", rc
));
674 #ifdef CONFIG_CIFS_STATS
676 atomic_inc(&tcon
->num_mkdirs
);
679 cifs_buf_release(pSMB
);
686 CIFSSMBOpen(const int xid
, struct cifsTconInfo
*tcon
,
687 const char *fileName
, const int openDisposition
,
688 const int access_flags
, const int create_options
, __u16
* netfid
,
689 int *pOplock
, FILE_ALL_INFO
* pfile_info
,
690 const struct nls_table
*nls_codepage
, int remap
)
693 OPEN_REQ
*pSMB
= NULL
;
694 OPEN_RSP
*pSMBr
= NULL
;
700 rc
= smb_init(SMB_COM_NT_CREATE_ANDX
, 24, tcon
, (void **) &pSMB
,
705 pSMB
->AndXCommand
= 0xFF; /* none */
707 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
708 count
= 1; /* account for one byte pad to word boundary */
710 cifsConvertToUCS((__u16
*) (pSMB
->fileName
+ 1),
711 fileName
, PATH_MAX
, nls_codepage
, remap
);
712 name_len
++; /* trailing null */
714 pSMB
->NameLength
= cpu_to_le16(name_len
);
715 } else { /* BB improve the check for buffer overruns BB */
716 count
= 0; /* no pad */
717 name_len
= strnlen(fileName
, PATH_MAX
);
718 name_len
++; /* trailing null */
719 pSMB
->NameLength
= cpu_to_le16(name_len
);
720 strncpy(pSMB
->fileName
, fileName
, name_len
);
722 if (*pOplock
& REQ_OPLOCK
)
723 pSMB
->OpenFlags
= cpu_to_le32(REQ_OPLOCK
);
724 else if (*pOplock
& REQ_BATCHOPLOCK
) {
725 pSMB
->OpenFlags
= cpu_to_le32(REQ_BATCHOPLOCK
);
727 pSMB
->DesiredAccess
= cpu_to_le32(access_flags
);
728 pSMB
->AllocationSize
= 0;
729 pSMB
->FileAttributes
= cpu_to_le32(ATTR_NORMAL
);
730 /* XP does not handle ATTR_POSIX_SEMANTICS */
731 /* but it helps speed up case sensitive checks for other
732 servers such as Samba */
733 if (tcon
->ses
->capabilities
& CAP_UNIX
)
734 pSMB
->FileAttributes
|= cpu_to_le32(ATTR_POSIX_SEMANTICS
);
736 /* if ((omode & S_IWUGO) == 0)
737 pSMB->FileAttributes |= cpu_to_le32(ATTR_READONLY);*/
738 /* Above line causes problems due to vfs splitting create into two
739 pieces - need to set mode after file created not while it is
741 pSMB
->ShareAccess
= cpu_to_le32(FILE_SHARE_ALL
);
742 pSMB
->CreateDisposition
= cpu_to_le32(openDisposition
);
743 pSMB
->CreateOptions
= cpu_to_le32(create_options
);
744 pSMB
->ImpersonationLevel
= cpu_to_le32(SECURITY_IMPERSONATION
); /* BB ??*/
745 pSMB
->SecurityFlags
=
746 SECURITY_CONTEXT_TRACKING
| SECURITY_EFFECTIVE_ONLY
;
749 pSMB
->hdr
.smb_buf_length
+= count
;
751 pSMB
->ByteCount
= cpu_to_le16(count
);
752 /* long_op set to 1 to allow for oplock break timeouts */
753 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
754 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 1);
756 cFYI(1, ("Error in Open = %d", rc
));
758 *pOplock
= pSMBr
->OplockLevel
; /* one byte no need to le_to_cpu */
759 *netfid
= pSMBr
->Fid
; /* cifs fid stays in le */
760 /* Let caller know file was created so we can set the mode. */
761 /* Do we care about the CreateAction in any other cases? */
762 if(cpu_to_le32(FILE_CREATE
) == pSMBr
->CreateAction
)
763 *pOplock
|= CIFS_CREATE_ACTION
;
765 memcpy((char *)pfile_info
,(char *)&pSMBr
->CreationTime
,
766 36 /* CreationTime to Attributes */);
767 /* the file_info buf is endian converted by caller */
768 pfile_info
->AllocationSize
= pSMBr
->AllocationSize
;
769 pfile_info
->EndOfFile
= pSMBr
->EndOfFile
;
770 pfile_info
->NumberOfLinks
= cpu_to_le32(1);
773 #ifdef CONFIG_CIFS_STATS
774 atomic_inc(&tcon
->num_opens
);
777 cifs_buf_release(pSMB
);
783 /* If no buffer passed in, then caller wants to do the copy
784 as in the case of readpages so the SMB buffer must be
785 freed by the caller */
788 CIFSSMBRead(const int xid
, struct cifsTconInfo
*tcon
,
789 const int netfid
, const unsigned int count
,
790 const __u64 lseek
, unsigned int *nbytes
, char **buf
)
793 READ_REQ
*pSMB
= NULL
;
794 READ_RSP
*pSMBr
= NULL
;
795 char *pReadData
= NULL
;
798 cFYI(1,("Reading %d bytes on fid %d",count
,netfid
));
801 rc
= smb_init(SMB_COM_READ_ANDX
, 12, tcon
, (void **) &pSMB
,
806 /* tcon and ses pointer are checked in smb_init */
807 if (tcon
->ses
->server
== NULL
)
808 return -ECONNABORTED
;
810 pSMB
->AndXCommand
= 0xFF; /* none */
812 pSMB
->OffsetLow
= cpu_to_le32(lseek
& 0xFFFFFFFF);
813 pSMB
->OffsetHigh
= cpu_to_le32(lseek
>> 32);
815 pSMB
->MaxCount
= cpu_to_le16(count
& 0xFFFF);
816 pSMB
->MaxCountHigh
= cpu_to_le32(count
>> 16);
817 pSMB
->ByteCount
= 0; /* no need to do le conversion since it is 0 */
819 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
820 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
822 cERROR(1, ("Send error in read = %d", rc
));
824 int data_length
= le16_to_cpu(pSMBr
->DataLengthHigh
);
825 data_length
= data_length
<< 16;
826 data_length
+= le16_to_cpu(pSMBr
->DataLength
);
827 *nbytes
= data_length
;
829 /*check that DataLength would not go beyond end of SMB */
830 if ((data_length
> CIFSMaxBufSize
)
831 || (data_length
> count
)) {
832 cFYI(1,("bad length %d for count %d",data_length
,count
));
837 (char *) (&pSMBr
->hdr
.Protocol
) +
838 le16_to_cpu(pSMBr
->DataOffset
);
839 /* if(rc = copy_to_user(buf, pReadData, data_length)) {
840 cERROR(1,("Faulting on read rc = %d",rc));
842 }*/ /* can not use copy_to_user when using page cache*/
844 memcpy(*buf
,pReadData
,data_length
);
848 cifs_buf_release(pSMB
);
852 /* Note: On -EAGAIN error only caller can retry on handle based calls
853 since file handle passed in no longer valid */
858 CIFSSMBWrite(const int xid
, struct cifsTconInfo
*tcon
,
859 const int netfid
, const unsigned int count
,
860 const __u64 offset
, unsigned int *nbytes
, const char *buf
,
861 const char __user
* ubuf
, const int long_op
)
864 WRITE_REQ
*pSMB
= NULL
;
865 WRITE_RSP
*pSMBr
= NULL
;
870 /* cFYI(1,("write at %lld %d bytes",offset,count));*/
871 rc
= smb_init(SMB_COM_WRITE_ANDX
, 14, tcon
, (void **) &pSMB
,
875 /* tcon and ses pointer are checked in smb_init */
876 if (tcon
->ses
->server
== NULL
)
877 return -ECONNABORTED
;
879 pSMB
->AndXCommand
= 0xFF; /* none */
881 pSMB
->OffsetLow
= cpu_to_le32(offset
& 0xFFFFFFFF);
882 pSMB
->OffsetHigh
= cpu_to_le32(offset
>> 32);
883 pSMB
->Reserved
= 0xFFFFFFFF;
887 /* Can increase buffer size if buffer is big enough in some cases - ie we
888 can send more if LARGE_WRITE_X capability returned by the server and if
889 our buffer is big enough or if we convert to iovecs on socket writes
890 and eliminate the copy to the CIFS buffer */
891 if(tcon
->ses
->capabilities
& CAP_LARGE_WRITE_X
) {
892 bytes_sent
= min_t(const unsigned int, CIFSMaxBufSize
, count
);
894 bytes_sent
= (tcon
->ses
->server
->maxBuf
- MAX_CIFS_HDR_SIZE
)
898 if (bytes_sent
> count
)
901 cpu_to_le16(offsetof(struct smb_com_write_req
,Data
) - 4);
903 memcpy(pSMB
->Data
,buf
,bytes_sent
);
905 if(copy_from_user(pSMB
->Data
,ubuf
,bytes_sent
)) {
906 cifs_buf_release(pSMB
);
911 cifs_buf_release(pSMB
);
915 byte_count
= bytes_sent
+ 1 /* pad */ ; /* BB fix this for sends > 64K */
916 pSMB
->DataLengthLow
= cpu_to_le16(bytes_sent
& 0xFFFF);
917 pSMB
->DataLengthHigh
= cpu_to_le16(bytes_sent
>> 16);
918 pSMB
->hdr
.smb_buf_length
+= bytes_sent
+1;
919 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
921 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
922 (struct smb_hdr
*) pSMBr
, &bytes_returned
, long_op
);
924 cFYI(1, ("Send error in write = %d", rc
));
927 *nbytes
= le16_to_cpu(pSMBr
->CountHigh
);
928 *nbytes
= (*nbytes
) << 16;
929 *nbytes
+= le16_to_cpu(pSMBr
->Count
);
932 cifs_buf_release(pSMB
);
934 /* Note: On -EAGAIN error only caller can retry on handle based calls
935 since file handle passed in no longer valid */
940 #ifdef CONFIG_CIFS_EXPERIMENTAL
941 int CIFSSMBWrite2(const int xid
, struct cifsTconInfo
*tcon
,
942 const int netfid
, const unsigned int count
,
943 const __u64 offset
, unsigned int *nbytes
, const char __user
*buf
,
947 WRITE_REQ
*pSMB
= NULL
;
948 WRITE_RSP
*pSMBr
= NULL
;
949 /*int bytes_returned;*/
953 rc
= small_smb_init(SMB_COM_WRITE_ANDX
, 14, tcon
, (void **) &pSMB
);
958 pSMBr
= (WRITE_RSP
*)pSMB
; /* BB removeme BB */
960 /* tcon and ses pointer are checked in smb_init */
961 if (tcon
->ses
->server
== NULL
)
962 return -ECONNABORTED
;
964 pSMB
->AndXCommand
= 0xFF; /* none */
966 pSMB
->OffsetLow
= cpu_to_le32(offset
& 0xFFFFFFFF);
967 pSMB
->OffsetHigh
= cpu_to_le32(offset
>> 32);
968 pSMB
->Reserved
= 0xFFFFFFFF;
971 bytes_sent
= (tcon
->ses
->server
->maxBuf
- MAX_CIFS_HDR_SIZE
) & ~0xFF;
972 if (bytes_sent
> count
)
974 pSMB
->DataLengthHigh
= 0;
976 cpu_to_le16(offsetof(struct smb_com_write_req
,Data
) - 4);
978 byte_count
= bytes_sent
+ 1 /* pad */ ;
979 pSMB
->DataLengthLow
= cpu_to_le16(bytes_sent
);
980 pSMB
->DataLengthHigh
= 0;
981 pSMB
->hdr
.smb_buf_length
+= byte_count
;
982 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
984 /* rc = SendReceive2(xid, tcon->ses, (struct smb_hdr *) pSMB,
985 (struct smb_hdr *) pSMBr, buf, buflen, &bytes_returned, long_op); */ /* BB fixme BB */
987 cFYI(1, ("Send error in write2 (large write) = %d", rc
));
990 *nbytes
= le16_to_cpu(pSMBr
->Count
);
992 cifs_small_buf_release(pSMB
);
994 /* Note: On -EAGAIN error only caller can retry on handle based calls
995 since file handle passed in no longer valid */
999 #endif /* CIFS_EXPERIMENTAL */
1002 CIFSSMBLock(const int xid
, struct cifsTconInfo
*tcon
,
1003 const __u16 smb_file_id
, const __u64 len
,
1004 const __u64 offset
, const __u32 numUnlock
,
1005 const __u32 numLock
, const __u8 lockType
, const int waitFlag
)
1008 LOCK_REQ
*pSMB
= NULL
;
1009 LOCK_RSP
*pSMBr
= NULL
;
1014 cFYI(1, ("In CIFSSMBLock - timeout %d numLock %d",waitFlag
,numLock
));
1015 rc
= smb_init(SMB_COM_LOCKING_ANDX
, 8, tcon
, (void **) &pSMB
,
1020 if(lockType
== LOCKING_ANDX_OPLOCK_RELEASE
) {
1021 timeout
= -1; /* no response expected */
1023 } else if (waitFlag
== TRUE
) {
1024 timeout
= 3; /* blocking operation, no timeout */
1025 pSMB
->Timeout
= cpu_to_le32(-1);/* blocking - do not time out */
1030 pSMB
->NumberOfLocks
= cpu_to_le16(numLock
);
1031 pSMB
->NumberOfUnlocks
= cpu_to_le16(numUnlock
);
1032 pSMB
->LockType
= lockType
;
1033 pSMB
->AndXCommand
= 0xFF; /* none */
1034 pSMB
->Fid
= smb_file_id
; /* netfid stays le */
1036 if((numLock
!= 0) || (numUnlock
!= 0)) {
1037 pSMB
->Locks
[0].Pid
= cpu_to_le16(current
->tgid
);
1038 /* BB where to store pid high? */
1039 pSMB
->Locks
[0].LengthLow
= cpu_to_le32((u32
)len
);
1040 pSMB
->Locks
[0].LengthHigh
= cpu_to_le32((u32
)(len
>>32));
1041 pSMB
->Locks
[0].OffsetLow
= cpu_to_le32((u32
)offset
);
1042 pSMB
->Locks
[0].OffsetHigh
= cpu_to_le32((u32
)(offset
>>32));
1043 count
= sizeof(LOCKING_ANDX_RANGE
);
1048 pSMB
->hdr
.smb_buf_length
+= count
;
1049 pSMB
->ByteCount
= cpu_to_le16(count
);
1051 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
1052 (struct smb_hdr
*) pSMBr
, &bytes_returned
, timeout
);
1055 cFYI(1, ("Send error in Lock = %d", rc
));
1057 cifs_buf_release(pSMB
);
1059 /* Note: On -EAGAIN error only caller can retry on handle based calls
1060 since file handle passed in no longer valid */
1065 CIFSSMBClose(const int xid
, struct cifsTconInfo
*tcon
, int smb_file_id
)
1068 CLOSE_REQ
*pSMB
= NULL
;
1069 CLOSE_RSP
*pSMBr
= NULL
;
1071 cFYI(1, ("In CIFSSMBClose"));
1073 /* do not retry on dead session on close */
1074 rc
= small_smb_init(SMB_COM_CLOSE
, 3, tcon
, (void **) &pSMB
);
1080 pSMBr
= (CLOSE_RSP
*)pSMB
; /* BB removeme BB */
1082 pSMB
->FileID
= (__u16
) smb_file_id
;
1083 pSMB
->LastWriteTime
= 0;
1084 pSMB
->ByteCount
= 0;
1085 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
1086 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
1089 /* EINTR is expected when user ctl-c to kill app */
1090 cERROR(1, ("Send error in Close = %d", rc
));
1094 cifs_small_buf_release(pSMB
);
1096 /* Since session is dead, file will be closed on server already */
1104 CIFSSMBRename(const int xid
, struct cifsTconInfo
*tcon
,
1105 const char *fromName
, const char *toName
,
1106 const struct nls_table
*nls_codepage
, int remap
)
1109 RENAME_REQ
*pSMB
= NULL
;
1110 RENAME_RSP
*pSMBr
= NULL
;
1112 int name_len
, name_len2
;
1115 cFYI(1, ("In CIFSSMBRename"));
1117 rc
= smb_init(SMB_COM_RENAME
, 1, tcon
, (void **) &pSMB
,
1122 pSMB
->BufferFormat
= 0x04;
1123 pSMB
->SearchAttributes
=
1124 cpu_to_le16(ATTR_READONLY
| ATTR_HIDDEN
| ATTR_SYSTEM
|
1127 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
1129 cifsConvertToUCS((__u16
*) pSMB
->OldFileName
, fromName
,
1130 PATH_MAX
, nls_codepage
, remap
);
1131 name_len
++; /* trailing null */
1133 pSMB
->OldFileName
[name_len
] = 0x04; /* pad */
1134 /* protocol requires ASCII signature byte on Unicode string */
1135 pSMB
->OldFileName
[name_len
+ 1] = 0x00;
1137 cifsConvertToUCS((__u16
*) &pSMB
->OldFileName
[name_len
+ 2],
1138 toName
, PATH_MAX
, nls_codepage
, remap
);
1139 name_len2
+= 1 /* trailing null */ + 1 /* Signature word */ ;
1140 name_len2
*= 2; /* convert to bytes */
1141 } else { /* BB improve the check for buffer overruns BB */
1142 name_len
= strnlen(fromName
, PATH_MAX
);
1143 name_len
++; /* trailing null */
1144 strncpy(pSMB
->OldFileName
, fromName
, name_len
);
1145 name_len2
= strnlen(toName
, PATH_MAX
);
1146 name_len2
++; /* trailing null */
1147 pSMB
->OldFileName
[name_len
] = 0x04; /* 2nd buffer format */
1148 strncpy(&pSMB
->OldFileName
[name_len
+ 1], toName
, name_len2
);
1149 name_len2
++; /* trailing null */
1150 name_len2
++; /* signature byte */
1153 count
= 1 /* 1st signature byte */ + name_len
+ name_len2
;
1154 pSMB
->hdr
.smb_buf_length
+= count
;
1155 pSMB
->ByteCount
= cpu_to_le16(count
);
1157 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
1158 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
1160 cFYI(1, ("Send error in rename = %d", rc
));
1163 #ifdef CONFIG_CIFS_STATS
1165 atomic_inc(&tcon
->num_renames
);
1169 cifs_buf_release(pSMB
);
1177 int CIFSSMBRenameOpenFile(const int xid
,struct cifsTconInfo
*pTcon
,
1178 int netfid
, char * target_name
,
1179 const struct nls_table
* nls_codepage
, int remap
)
1181 struct smb_com_transaction2_sfi_req
*pSMB
= NULL
;
1182 struct smb_com_transaction2_sfi_rsp
*pSMBr
= NULL
;
1183 struct set_file_rename
* rename_info
;
1185 char dummy_string
[30];
1187 int bytes_returned
= 0;
1189 __u16 params
, param_offset
, offset
, count
, byte_count
;
1191 cFYI(1, ("Rename to File by handle"));
1192 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, pTcon
, (void **) &pSMB
,
1198 pSMB
->MaxSetupCount
= 0;
1202 pSMB
->Reserved2
= 0;
1203 param_offset
= offsetof(struct smb_com_transaction2_sfi_req
, Fid
) - 4;
1204 offset
= param_offset
+ params
;
1206 data_offset
= (char *) (&pSMB
->hdr
.Protocol
) + offset
;
1207 rename_info
= (struct set_file_rename
*) data_offset
;
1208 pSMB
->MaxParameterCount
= cpu_to_le16(2);
1209 pSMB
->MaxDataCount
= cpu_to_le16(1000); /* BB find max SMB PDU from sess */
1210 pSMB
->SetupCount
= 1;
1211 pSMB
->Reserved3
= 0;
1212 pSMB
->SubCommand
= cpu_to_le16(TRANS2_SET_FILE_INFORMATION
);
1213 byte_count
= 3 /* pad */ + params
;
1214 pSMB
->ParameterCount
= cpu_to_le16(params
);
1215 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
1216 pSMB
->ParameterOffset
= cpu_to_le16(param_offset
);
1217 pSMB
->DataOffset
= cpu_to_le16(offset
);
1218 /* construct random name ".cifs_tmp<inodenum><mid>" */
1219 rename_info
->overwrite
= cpu_to_le32(1);
1220 rename_info
->root_fid
= 0;
1221 /* unicode only call */
1222 if(target_name
== NULL
) {
1223 sprintf(dummy_string
,"cifs%x",pSMB
->hdr
.Mid
);
1224 len_of_str
= cifsConvertToUCS((__u16
*)rename_info
->target_name
,
1225 dummy_string
, 24, nls_codepage
, remap
);
1227 len_of_str
= cifsConvertToUCS((__u16
*)rename_info
->target_name
,
1228 target_name
, PATH_MAX
, nls_codepage
, remap
);
1230 rename_info
->target_name_len
= cpu_to_le32(2 * len_of_str
);
1231 count
= 12 /* sizeof(struct set_file_rename) */ + (2 * len_of_str
) + 2;
1232 byte_count
+= count
;
1233 pSMB
->DataCount
= cpu_to_le16(count
);
1234 pSMB
->TotalDataCount
= pSMB
->DataCount
;
1236 pSMB
->InformationLevel
=
1237 cpu_to_le16(SMB_SET_FILE_RENAME_INFORMATION
);
1238 pSMB
->Reserved4
= 0;
1239 pSMB
->hdr
.smb_buf_length
+= byte_count
;
1240 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
1241 rc
= SendReceive(xid
, pTcon
->ses
, (struct smb_hdr
*) pSMB
,
1242 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
1244 cFYI(1,("Send error in Rename (by file handle) = %d", rc
));
1246 #ifdef CONFIG_CIFS_STATS
1248 atomic_inc(&pTcon
->num_t2renames
);
1251 cifs_buf_release(pSMB
);
1253 /* Note: On -EAGAIN error only caller can retry on handle based calls
1254 since file handle passed in no longer valid */
1260 CIFSSMBCopy(const int xid
, struct cifsTconInfo
*tcon
, const char * fromName
,
1261 const __u16 target_tid
, const char *toName
, const int flags
,
1262 const struct nls_table
*nls_codepage
, int remap
)
1265 COPY_REQ
*pSMB
= NULL
;
1266 COPY_RSP
*pSMBr
= NULL
;
1268 int name_len
, name_len2
;
1271 cFYI(1, ("In CIFSSMBCopy"));
1273 rc
= smb_init(SMB_COM_COPY
, 1, tcon
, (void **) &pSMB
,
1278 pSMB
->BufferFormat
= 0x04;
1279 pSMB
->Tid2
= target_tid
;
1281 pSMB
->Flags
= cpu_to_le16(flags
& COPY_TREE
);
1283 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
1284 name_len
= cifsConvertToUCS((__u16
*) pSMB
->OldFileName
,
1285 fromName
, PATH_MAX
, nls_codepage
,
1287 name_len
++; /* trailing null */
1289 pSMB
->OldFileName
[name_len
] = 0x04; /* pad */
1290 /* protocol requires ASCII signature byte on Unicode string */
1291 pSMB
->OldFileName
[name_len
+ 1] = 0x00;
1292 name_len2
= cifsConvertToUCS((__u16
*)&pSMB
->OldFileName
[name_len
+ 2],
1293 toName
, PATH_MAX
, nls_codepage
, remap
);
1294 name_len2
+= 1 /* trailing null */ + 1 /* Signature word */ ;
1295 name_len2
*= 2; /* convert to bytes */
1296 } else { /* BB improve the check for buffer overruns BB */
1297 name_len
= strnlen(fromName
, PATH_MAX
);
1298 name_len
++; /* trailing null */
1299 strncpy(pSMB
->OldFileName
, fromName
, name_len
);
1300 name_len2
= strnlen(toName
, PATH_MAX
);
1301 name_len2
++; /* trailing null */
1302 pSMB
->OldFileName
[name_len
] = 0x04; /* 2nd buffer format */
1303 strncpy(&pSMB
->OldFileName
[name_len
+ 1], toName
, name_len2
);
1304 name_len2
++; /* trailing null */
1305 name_len2
++; /* signature byte */
1308 count
= 1 /* 1st signature byte */ + name_len
+ name_len2
;
1309 pSMB
->hdr
.smb_buf_length
+= count
;
1310 pSMB
->ByteCount
= cpu_to_le16(count
);
1312 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
1313 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
1315 cFYI(1, ("Send error in copy = %d with %d files copied",
1316 rc
, le16_to_cpu(pSMBr
->CopyCount
)));
1319 cifs_buf_release(pSMB
);
1328 CIFSUnixCreateSymLink(const int xid
, struct cifsTconInfo
*tcon
,
1329 const char *fromName
, const char *toName
,
1330 const struct nls_table
*nls_codepage
)
1332 TRANSACTION2_SPI_REQ
*pSMB
= NULL
;
1333 TRANSACTION2_SPI_RSP
*pSMBr
= NULL
;
1336 int name_len_target
;
1338 int bytes_returned
= 0;
1339 __u16 params
, param_offset
, offset
, byte_count
;
1341 cFYI(1, ("In Symlink Unix style"));
1343 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
1348 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
1350 cifs_strtoUCS((wchar_t *) pSMB
->FileName
, fromName
, PATH_MAX
1351 /* find define for this maxpathcomponent */
1353 name_len
++; /* trailing null */
1356 } else { /* BB improve the check for buffer overruns BB */
1357 name_len
= strnlen(fromName
, PATH_MAX
);
1358 name_len
++; /* trailing null */
1359 strncpy(pSMB
->FileName
, fromName
, name_len
);
1361 params
= 6 + name_len
;
1362 pSMB
->MaxSetupCount
= 0;
1366 pSMB
->Reserved2
= 0;
1367 param_offset
= offsetof(struct smb_com_transaction2_spi_req
,
1368 InformationLevel
) - 4;
1369 offset
= param_offset
+ params
;
1371 data_offset
= (char *) (&pSMB
->hdr
.Protocol
) + offset
;
1372 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
1374 cifs_strtoUCS((wchar_t *) data_offset
, toName
, PATH_MAX
1375 /* find define for this maxpathcomponent */
1377 name_len_target
++; /* trailing null */
1378 name_len_target
*= 2;
1379 } else { /* BB improve the check for buffer overruns BB */
1380 name_len_target
= strnlen(toName
, PATH_MAX
);
1381 name_len_target
++; /* trailing null */
1382 strncpy(data_offset
, toName
, name_len_target
);
1385 pSMB
->MaxParameterCount
= cpu_to_le16(2);
1386 /* BB find exact max on data count below from sess */
1387 pSMB
->MaxDataCount
= cpu_to_le16(1000);
1388 pSMB
->SetupCount
= 1;
1389 pSMB
->Reserved3
= 0;
1390 pSMB
->SubCommand
= cpu_to_le16(TRANS2_SET_PATH_INFORMATION
);
1391 byte_count
= 3 /* pad */ + params
+ name_len_target
;
1392 pSMB
->DataCount
= cpu_to_le16(name_len_target
);
1393 pSMB
->ParameterCount
= cpu_to_le16(params
);
1394 pSMB
->TotalDataCount
= pSMB
->DataCount
;
1395 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
1396 pSMB
->ParameterOffset
= cpu_to_le16(param_offset
);
1397 pSMB
->DataOffset
= cpu_to_le16(offset
);
1398 pSMB
->InformationLevel
= cpu_to_le16(SMB_SET_FILE_UNIX_LINK
);
1399 pSMB
->Reserved4
= 0;
1400 pSMB
->hdr
.smb_buf_length
+= byte_count
;
1401 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
1402 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
1403 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
1406 ("Send error in SetPathInfo (create symlink) = %d",
1411 cifs_buf_release(pSMB
);
1414 goto createSymLinkRetry
;
1420 CIFSUnixCreateHardLink(const int xid
, struct cifsTconInfo
*tcon
,
1421 const char *fromName
, const char *toName
,
1422 const struct nls_table
*nls_codepage
, int remap
)
1424 TRANSACTION2_SPI_REQ
*pSMB
= NULL
;
1425 TRANSACTION2_SPI_RSP
*pSMBr
= NULL
;
1428 int name_len_target
;
1430 int bytes_returned
= 0;
1431 __u16 params
, param_offset
, offset
, byte_count
;
1433 cFYI(1, ("In Create Hard link Unix style"));
1434 createHardLinkRetry
:
1435 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
1440 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
1441 name_len
= cifsConvertToUCS((__u16
*) pSMB
->FileName
, toName
,
1442 PATH_MAX
, nls_codepage
, remap
);
1443 name_len
++; /* trailing null */
1446 } else { /* BB improve the check for buffer overruns BB */
1447 name_len
= strnlen(toName
, PATH_MAX
);
1448 name_len
++; /* trailing null */
1449 strncpy(pSMB
->FileName
, toName
, name_len
);
1451 params
= 6 + name_len
;
1452 pSMB
->MaxSetupCount
= 0;
1456 pSMB
->Reserved2
= 0;
1457 param_offset
= offsetof(struct smb_com_transaction2_spi_req
,
1458 InformationLevel
) - 4;
1459 offset
= param_offset
+ params
;
1461 data_offset
= (char *) (&pSMB
->hdr
.Protocol
) + offset
;
1462 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
1464 cifsConvertToUCS((__u16
*) data_offset
, fromName
, PATH_MAX
,
1465 nls_codepage
, remap
);
1466 name_len_target
++; /* trailing null */
1467 name_len_target
*= 2;
1468 } else { /* BB improve the check for buffer overruns BB */
1469 name_len_target
= strnlen(fromName
, PATH_MAX
);
1470 name_len_target
++; /* trailing null */
1471 strncpy(data_offset
, fromName
, name_len_target
);
1474 pSMB
->MaxParameterCount
= cpu_to_le16(2);
1475 /* BB find exact max on data count below from sess*/
1476 pSMB
->MaxDataCount
= cpu_to_le16(1000);
1477 pSMB
->SetupCount
= 1;
1478 pSMB
->Reserved3
= 0;
1479 pSMB
->SubCommand
= cpu_to_le16(TRANS2_SET_PATH_INFORMATION
);
1480 byte_count
= 3 /* pad */ + params
+ name_len_target
;
1481 pSMB
->ParameterCount
= cpu_to_le16(params
);
1482 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
1483 pSMB
->DataCount
= cpu_to_le16(name_len_target
);
1484 pSMB
->TotalDataCount
= pSMB
->DataCount
;
1485 pSMB
->ParameterOffset
= cpu_to_le16(param_offset
);
1486 pSMB
->DataOffset
= cpu_to_le16(offset
);
1487 pSMB
->InformationLevel
= cpu_to_le16(SMB_SET_FILE_UNIX_HLINK
);
1488 pSMB
->Reserved4
= 0;
1489 pSMB
->hdr
.smb_buf_length
+= byte_count
;
1490 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
1491 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
1492 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
1494 cFYI(1, ("Send error in SetPathInfo (hard link) = %d", rc
));
1497 cifs_buf_release(pSMB
);
1499 goto createHardLinkRetry
;
1505 CIFSCreateHardLink(const int xid
, struct cifsTconInfo
*tcon
,
1506 const char *fromName
, const char *toName
,
1507 const struct nls_table
*nls_codepage
, int remap
)
1510 NT_RENAME_REQ
*pSMB
= NULL
;
1511 RENAME_RSP
*pSMBr
= NULL
;
1513 int name_len
, name_len2
;
1516 cFYI(1, ("In CIFSCreateHardLink"));
1517 winCreateHardLinkRetry
:
1519 rc
= smb_init(SMB_COM_NT_RENAME
, 4, tcon
, (void **) &pSMB
,
1524 pSMB
->SearchAttributes
=
1525 cpu_to_le16(ATTR_READONLY
| ATTR_HIDDEN
| ATTR_SYSTEM
|
1527 pSMB
->Flags
= cpu_to_le16(CREATE_HARD_LINK
);
1528 pSMB
->ClusterCount
= 0;
1530 pSMB
->BufferFormat
= 0x04;
1532 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
1534 cifsConvertToUCS((__u16
*) pSMB
->OldFileName
, fromName
,
1535 PATH_MAX
, nls_codepage
, remap
);
1536 name_len
++; /* trailing null */
1538 pSMB
->OldFileName
[name_len
] = 0; /* pad */
1539 pSMB
->OldFileName
[name_len
+ 1] = 0x04;
1541 cifsConvertToUCS((__u16
*)&pSMB
->OldFileName
[name_len
+ 2],
1542 toName
, PATH_MAX
, nls_codepage
, remap
);
1543 name_len2
+= 1 /* trailing null */ + 1 /* Signature word */ ;
1544 name_len2
*= 2; /* convert to bytes */
1545 } else { /* BB improve the check for buffer overruns BB */
1546 name_len
= strnlen(fromName
, PATH_MAX
);
1547 name_len
++; /* trailing null */
1548 strncpy(pSMB
->OldFileName
, fromName
, name_len
);
1549 name_len2
= strnlen(toName
, PATH_MAX
);
1550 name_len2
++; /* trailing null */
1551 pSMB
->OldFileName
[name_len
] = 0x04; /* 2nd buffer format */
1552 strncpy(&pSMB
->OldFileName
[name_len
+ 1], toName
, name_len2
);
1553 name_len2
++; /* trailing null */
1554 name_len2
++; /* signature byte */
1557 count
= 1 /* string type byte */ + name_len
+ name_len2
;
1558 pSMB
->hdr
.smb_buf_length
+= count
;
1559 pSMB
->ByteCount
= cpu_to_le16(count
);
1561 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
1562 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
1564 cFYI(1, ("Send error in hard link (NT rename) = %d", rc
));
1566 cifs_buf_release(pSMB
);
1568 goto winCreateHardLinkRetry
;
1574 CIFSSMBUnixQuerySymLink(const int xid
, struct cifsTconInfo
*tcon
,
1575 const unsigned char *searchName
,
1576 char *symlinkinfo
, const int buflen
,
1577 const struct nls_table
*nls_codepage
)
1579 /* SMB_QUERY_FILE_UNIX_LINK */
1580 TRANSACTION2_QPI_REQ
*pSMB
= NULL
;
1581 TRANSACTION2_QPI_RSP
*pSMBr
= NULL
;
1585 __u16 params
, byte_count
;
1587 cFYI(1, ("In QPathSymLinkInfo (Unix) for path %s", searchName
));
1590 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
1595 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
1597 cifs_strtoUCS((wchar_t *) pSMB
->FileName
, searchName
, PATH_MAX
1598 /* find define for this maxpathcomponent */
1600 name_len
++; /* trailing null */
1602 } else { /* BB improve the check for buffer overruns BB */
1603 name_len
= strnlen(searchName
, PATH_MAX
);
1604 name_len
++; /* trailing null */
1605 strncpy(pSMB
->FileName
, searchName
, name_len
);
1608 params
= 2 /* level */ + 4 /* rsrvd */ + name_len
/* incl null */ ;
1609 pSMB
->TotalDataCount
= 0;
1610 pSMB
->MaxParameterCount
= cpu_to_le16(2);
1611 /* BB find exact max data count below from sess structure BB */
1612 pSMB
->MaxDataCount
= cpu_to_le16(4000);
1613 pSMB
->MaxSetupCount
= 0;
1617 pSMB
->Reserved2
= 0;
1618 pSMB
->ParameterOffset
= cpu_to_le16(offsetof(
1619 struct smb_com_transaction2_qpi_req
,InformationLevel
) - 4);
1620 pSMB
->DataCount
= 0;
1621 pSMB
->DataOffset
= 0;
1622 pSMB
->SetupCount
= 1;
1623 pSMB
->Reserved3
= 0;
1624 pSMB
->SubCommand
= cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION
);
1625 byte_count
= params
+ 1 /* pad */ ;
1626 pSMB
->TotalParameterCount
= cpu_to_le16(params
);
1627 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
1628 pSMB
->InformationLevel
= cpu_to_le16(SMB_QUERY_FILE_UNIX_LINK
);
1629 pSMB
->Reserved4
= 0;
1630 pSMB
->hdr
.smb_buf_length
+= byte_count
;
1631 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
1633 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
1634 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
1636 cFYI(1, ("Send error in QuerySymLinkInfo = %d", rc
));
1638 /* decode response */
1640 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
1641 if (rc
|| (pSMBr
->ByteCount
< 2))
1642 /* BB also check enough total bytes returned */
1643 rc
= -EIO
; /* bad smb */
1645 __u16 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
1646 __u16 count
= le16_to_cpu(pSMBr
->t2
.DataCount
);
1648 if (pSMBr
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
1649 name_len
= UniStrnlen((wchar_t *) ((char *)
1650 &pSMBr
->hdr
.Protocol
+data_offset
),
1651 min_t(const int, buflen
,count
) / 2);
1652 /* BB FIXME investigate remapping reserved chars here */
1653 cifs_strfromUCS_le(symlinkinfo
,
1654 (wchar_t *) ((char *)&pSMBr
->hdr
.Protocol
+
1656 name_len
, nls_codepage
);
1658 strncpy(symlinkinfo
,
1659 (char *) &pSMBr
->hdr
.Protocol
+
1661 min_t(const int, buflen
, count
));
1663 symlinkinfo
[buflen
] = 0;
1664 /* just in case so calling code does not go off the end of buffer */
1667 cifs_buf_release(pSMB
);
1669 goto querySymLinkRetry
;
1674 CIFSSMBQueryReparseLinkInfo(const int xid
, struct cifsTconInfo
*tcon
,
1675 const unsigned char *searchName
,
1676 char *symlinkinfo
, const int buflen
,__u16 fid
,
1677 const struct nls_table
*nls_codepage
)
1682 struct smb_com_transaction_ioctl_req
* pSMB
;
1683 struct smb_com_transaction_ioctl_rsp
* pSMBr
;
1685 cFYI(1, ("In Windows reparse style QueryLink for path %s", searchName
));
1686 rc
= smb_init(SMB_COM_NT_TRANSACT
, 23, tcon
, (void **) &pSMB
,
1691 pSMB
->TotalParameterCount
= 0 ;
1692 pSMB
->TotalDataCount
= 0;
1693 pSMB
->MaxParameterCount
= cpu_to_le32(2);
1694 /* BB find exact data count max from sess structure BB */
1695 pSMB
->MaxDataCount
= cpu_to_le32(4000);
1696 pSMB
->MaxSetupCount
= 4;
1698 pSMB
->ParameterOffset
= 0;
1699 pSMB
->DataCount
= 0;
1700 pSMB
->DataOffset
= 0;
1701 pSMB
->SetupCount
= 4;
1702 pSMB
->SubCommand
= cpu_to_le16(NT_TRANSACT_IOCTL
);
1703 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
1704 pSMB
->FunctionCode
= cpu_to_le32(FSCTL_GET_REPARSE_POINT
);
1705 pSMB
->IsFsctl
= 1; /* FSCTL */
1706 pSMB
->IsRootFlag
= 0;
1707 pSMB
->Fid
= fid
; /* file handle always le */
1708 pSMB
->ByteCount
= 0;
1710 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
1711 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
1713 cFYI(1, ("Send error in QueryReparseLinkInfo = %d", rc
));
1714 } else { /* decode response */
1715 __u32 data_offset
= le32_to_cpu(pSMBr
->DataOffset
);
1716 __u32 data_count
= le32_to_cpu(pSMBr
->DataCount
);
1717 if ((pSMBr
->ByteCount
< 2) || (data_offset
> 512))
1718 /* BB also check enough total bytes returned */
1719 rc
= -EIO
; /* bad smb */
1721 if(data_count
&& (data_count
< 2048)) {
1722 char * end_of_smb
= pSMBr
->ByteCount
+ (char *)&pSMBr
->ByteCount
;
1724 struct reparse_data
* reparse_buf
= (struct reparse_data
*)
1725 ((char *)&pSMBr
->hdr
.Protocol
+ data_offset
);
1726 if((char*)reparse_buf
>= end_of_smb
) {
1730 if((reparse_buf
->LinkNamesBuf
+
1731 reparse_buf
->TargetNameOffset
+
1732 reparse_buf
->TargetNameLen
) >
1734 cFYI(1,("reparse buf extended beyond SMB"));
1739 if (pSMBr
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
1740 name_len
= UniStrnlen((wchar_t *)
1741 (reparse_buf
->LinkNamesBuf
+
1742 reparse_buf
->TargetNameOffset
),
1743 min(buflen
/2, reparse_buf
->TargetNameLen
/ 2));
1744 cifs_strfromUCS_le(symlinkinfo
,
1745 (wchar_t *) (reparse_buf
->LinkNamesBuf
+
1746 reparse_buf
->TargetNameOffset
),
1747 name_len
, nls_codepage
);
1748 } else { /* ASCII names */
1749 strncpy(symlinkinfo
,reparse_buf
->LinkNamesBuf
+
1750 reparse_buf
->TargetNameOffset
,
1751 min_t(const int, buflen
, reparse_buf
->TargetNameLen
));
1755 cFYI(1,("Invalid return data count on get reparse info ioctl"));
1757 symlinkinfo
[buflen
] = 0; /* just in case so the caller
1758 does not go off the end of the buffer */
1759 cFYI(1,("readlink result - %s ",symlinkinfo
));
1764 cifs_buf_release(pSMB
);
1766 /* Note: On -EAGAIN error only caller can retry on handle based calls
1767 since file handle passed in no longer valid */
1772 #ifdef CONFIG_CIFS_POSIX
1774 /*Convert an Access Control Entry from wire format to local POSIX xattr format*/
1775 static void cifs_convert_ace(posix_acl_xattr_entry
* ace
, struct cifs_posix_ace
* cifs_ace
)
1777 /* u8 cifs fields do not need le conversion */
1778 ace
->e_perm
= (__u16
)cifs_ace
->cifs_e_perm
;
1779 ace
->e_tag
= (__u16
)cifs_ace
->cifs_e_tag
;
1780 ace
->e_id
= (__u32
)le64_to_cpu(cifs_ace
->cifs_uid
);
1781 /* cFYI(1,("perm %d tag %d id %d",ace->e_perm,ace->e_tag,ace->e_id)); */
1786 /* Convert ACL from CIFS POSIX wire format to local Linux POSIX ACL xattr */
1787 static int cifs_copy_posix_acl(char * trgt
,char * src
, const int buflen
,
1788 const int acl_type
,const int size_of_data_area
)
1793 struct cifs_posix_ace
* pACE
;
1794 struct cifs_posix_acl
* cifs_acl
= (struct cifs_posix_acl
*)src
;
1795 posix_acl_xattr_header
* local_acl
= (posix_acl_xattr_header
*)trgt
;
1797 if (le16_to_cpu(cifs_acl
->version
) != CIFS_ACL_VERSION
)
1800 if(acl_type
& ACL_TYPE_ACCESS
) {
1801 count
= le16_to_cpu(cifs_acl
->access_entry_count
);
1802 pACE
= &cifs_acl
->ace_array
[0];
1803 size
= sizeof(struct cifs_posix_acl
);
1804 size
+= sizeof(struct cifs_posix_ace
) * count
;
1805 /* check if we would go beyond end of SMB */
1806 if(size_of_data_area
< size
) {
1807 cFYI(1,("bad CIFS POSIX ACL size %d vs. %d",size_of_data_area
,size
));
1810 } else if(acl_type
& ACL_TYPE_DEFAULT
) {
1811 count
= le16_to_cpu(cifs_acl
->access_entry_count
);
1812 size
= sizeof(struct cifs_posix_acl
);
1813 size
+= sizeof(struct cifs_posix_ace
) * count
;
1814 /* skip past access ACEs to get to default ACEs */
1815 pACE
= &cifs_acl
->ace_array
[count
];
1816 count
= le16_to_cpu(cifs_acl
->default_entry_count
);
1817 size
+= sizeof(struct cifs_posix_ace
) * count
;
1818 /* check if we would go beyond end of SMB */
1819 if(size_of_data_area
< size
)
1826 size
= posix_acl_xattr_size(count
);
1827 if((buflen
== 0) || (local_acl
== NULL
)) {
1828 /* used to query ACL EA size */
1829 } else if(size
> buflen
) {
1831 } else /* buffer big enough */ {
1832 local_acl
->a_version
= POSIX_ACL_XATTR_VERSION
;
1833 for(i
= 0;i
< count
;i
++) {
1834 cifs_convert_ace(&local_acl
->a_entries
[i
],pACE
);
1841 static __u16
convert_ace_to_cifs_ace(struct cifs_posix_ace
* cifs_ace
,
1842 const posix_acl_xattr_entry
* local_ace
)
1844 __u16 rc
= 0; /* 0 = ACL converted ok */
1846 cifs_ace
->cifs_e_perm
= (__u8
)cpu_to_le16(local_ace
->e_perm
);
1847 cifs_ace
->cifs_e_tag
= (__u8
)cpu_to_le16(local_ace
->e_tag
);
1848 /* BB is there a better way to handle the large uid? */
1849 if(local_ace
->e_id
== -1) {
1850 /* Probably no need to le convert -1 on any arch but can not hurt */
1851 cifs_ace
->cifs_uid
= cpu_to_le64(-1);
1853 cifs_ace
->cifs_uid
= (__u64
)cpu_to_le32(local_ace
->e_id
);
1854 /*cFYI(1,("perm %d tag %d id %d",ace->e_perm,ace->e_tag,ace->e_id));*/
1858 /* Convert ACL from local Linux POSIX xattr to CIFS POSIX ACL wire format */
1859 static __u16
ACL_to_cifs_posix(char * parm_data
,const char * pACL
,const int buflen
,
1863 struct cifs_posix_acl
* cifs_acl
= (struct cifs_posix_acl
*)parm_data
;
1864 posix_acl_xattr_header
* local_acl
= (posix_acl_xattr_header
*)pACL
;
1868 if((buflen
== 0) || (pACL
== NULL
) || (cifs_acl
== NULL
))
1871 count
= posix_acl_xattr_count((size_t)buflen
);
1872 cFYI(1,("setting acl with %d entries from buf of length %d and version of %d",
1873 count
,buflen
,local_acl
->a_version
));
1874 if(local_acl
->a_version
!= 2) {
1875 cFYI(1,("unknown POSIX ACL version %d",local_acl
->a_version
));
1878 cifs_acl
->version
= cpu_to_le16(1);
1879 if(acl_type
== ACL_TYPE_ACCESS
)
1880 cifs_acl
->access_entry_count
= count
;
1881 else if(acl_type
== ACL_TYPE_DEFAULT
)
1882 cifs_acl
->default_entry_count
= count
;
1884 cFYI(1,("unknown ACL type %d",acl_type
));
1887 for(i
=0;i
<count
;i
++) {
1888 rc
= convert_ace_to_cifs_ace(&cifs_acl
->ace_array
[i
],
1889 &local_acl
->a_entries
[i
]);
1891 /* ACE not converted */
1896 rc
= (__u16
)(count
* sizeof(struct cifs_posix_ace
));
1897 rc
+= sizeof(struct cifs_posix_acl
);
1898 /* BB add check to make sure ACL does not overflow SMB */
1904 CIFSSMBGetPosixACL(const int xid
, struct cifsTconInfo
*tcon
,
1905 const unsigned char *searchName
,
1906 char *acl_inf
, const int buflen
, const int acl_type
,
1907 const struct nls_table
*nls_codepage
, int remap
)
1909 /* SMB_QUERY_POSIX_ACL */
1910 TRANSACTION2_QPI_REQ
*pSMB
= NULL
;
1911 TRANSACTION2_QPI_RSP
*pSMBr
= NULL
;
1915 __u16 params
, byte_count
;
1917 cFYI(1, ("In GetPosixACL (Unix) for path %s", searchName
));
1920 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
1925 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
1927 cifsConvertToUCS((__u16
*) pSMB
->FileName
, searchName
,
1928 PATH_MAX
, nls_codepage
, remap
);
1929 name_len
++; /* trailing null */
1931 pSMB
->FileName
[name_len
] = 0;
1932 pSMB
->FileName
[name_len
+1] = 0;
1933 } else { /* BB improve the check for buffer overruns BB */
1934 name_len
= strnlen(searchName
, PATH_MAX
);
1935 name_len
++; /* trailing null */
1936 strncpy(pSMB
->FileName
, searchName
, name_len
);
1939 params
= 2 /* level */ + 4 /* rsrvd */ + name_len
/* incl null */ ;
1940 pSMB
->TotalDataCount
= 0;
1941 pSMB
->MaxParameterCount
= cpu_to_le16(2);
1942 /* BB find exact max data count below from sess structure BB */
1943 pSMB
->MaxDataCount
= cpu_to_le16(4000);
1944 pSMB
->MaxSetupCount
= 0;
1948 pSMB
->Reserved2
= 0;
1949 pSMB
->ParameterOffset
= cpu_to_le16(
1950 offsetof(struct smb_com_transaction2_qpi_req
,InformationLevel
) - 4);
1951 pSMB
->DataCount
= 0;
1952 pSMB
->DataOffset
= 0;
1953 pSMB
->SetupCount
= 1;
1954 pSMB
->Reserved3
= 0;
1955 pSMB
->SubCommand
= cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION
);
1956 byte_count
= params
+ 1 /* pad */ ;
1957 pSMB
->TotalParameterCount
= cpu_to_le16(params
);
1958 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
1959 pSMB
->InformationLevel
= cpu_to_le16(SMB_QUERY_POSIX_ACL
);
1960 pSMB
->Reserved4
= 0;
1961 pSMB
->hdr
.smb_buf_length
+= byte_count
;
1962 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
1964 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
1965 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
1967 cFYI(1, ("Send error in Query POSIX ACL = %d", rc
));
1969 /* decode response */
1971 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
1972 if (rc
|| (pSMBr
->ByteCount
< 2))
1973 /* BB also check enough total bytes returned */
1974 rc
= -EIO
; /* bad smb */
1976 __u16 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
1977 __u16 count
= le16_to_cpu(pSMBr
->t2
.DataCount
);
1978 rc
= cifs_copy_posix_acl(acl_inf
,
1979 (char *)&pSMBr
->hdr
.Protocol
+data_offset
,
1980 buflen
,acl_type
,count
);
1983 cifs_buf_release(pSMB
);
1990 CIFSSMBSetPosixACL(const int xid
, struct cifsTconInfo
*tcon
,
1991 const unsigned char *fileName
,
1992 const char *local_acl
, const int buflen
,
1994 const struct nls_table
*nls_codepage
, int remap
)
1996 struct smb_com_transaction2_spi_req
*pSMB
= NULL
;
1997 struct smb_com_transaction2_spi_rsp
*pSMBr
= NULL
;
2001 int bytes_returned
= 0;
2002 __u16 params
, byte_count
, data_count
, param_offset
, offset
;
2004 cFYI(1, ("In SetPosixACL (Unix) for path %s", fileName
));
2006 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
2010 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
2012 cifsConvertToUCS((__u16
*) pSMB
->FileName
, fileName
,
2013 PATH_MAX
, nls_codepage
, remap
);
2014 name_len
++; /* trailing null */
2016 } else { /* BB improve the check for buffer overruns BB */
2017 name_len
= strnlen(fileName
, PATH_MAX
);
2018 name_len
++; /* trailing null */
2019 strncpy(pSMB
->FileName
, fileName
, name_len
);
2021 params
= 6 + name_len
;
2022 pSMB
->MaxParameterCount
= cpu_to_le16(2);
2023 pSMB
->MaxDataCount
= cpu_to_le16(1000); /* BB find max SMB size from sess */
2024 pSMB
->MaxSetupCount
= 0;
2028 pSMB
->Reserved2
= 0;
2029 param_offset
= offsetof(struct smb_com_transaction2_spi_req
,
2030 InformationLevel
) - 4;
2031 offset
= param_offset
+ params
;
2032 parm_data
= ((char *) &pSMB
->hdr
.Protocol
) + offset
;
2033 pSMB
->ParameterOffset
= cpu_to_le16(param_offset
);
2035 /* convert to on the wire format for POSIX ACL */
2036 data_count
= ACL_to_cifs_posix(parm_data
,local_acl
,buflen
,acl_type
);
2038 if(data_count
== 0) {
2040 goto setACLerrorExit
;
2042 pSMB
->DataOffset
= cpu_to_le16(offset
);
2043 pSMB
->SetupCount
= 1;
2044 pSMB
->Reserved3
= 0;
2045 pSMB
->SubCommand
= cpu_to_le16(TRANS2_SET_PATH_INFORMATION
);
2046 pSMB
->InformationLevel
= cpu_to_le16(SMB_SET_POSIX_ACL
);
2047 byte_count
= 3 /* pad */ + params
+ data_count
;
2048 pSMB
->DataCount
= cpu_to_le16(data_count
);
2049 pSMB
->TotalDataCount
= pSMB
->DataCount
;
2050 pSMB
->ParameterCount
= cpu_to_le16(params
);
2051 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
2052 pSMB
->Reserved4
= 0;
2053 pSMB
->hdr
.smb_buf_length
+= byte_count
;
2054 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
2055 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
2056 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
2058 cFYI(1, ("Set POSIX ACL returned %d", rc
));
2062 cifs_buf_release(pSMB
);
2068 /* BB fix tabs in this function FIXME BB */
2070 CIFSGetExtAttr(const int xid
, struct cifsTconInfo
*tcon
,
2071 const int netfid
, __u64
* pExtAttrBits
, __u64
*pMask
)
2074 struct smb_t2_qfi_req
*pSMB
= NULL
;
2075 struct smb_t2_qfi_rsp
*pSMBr
= NULL
;
2077 __u16 params
, byte_count
;
2079 cFYI(1,("In GetExtAttr"));
2084 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
2089 params
= 2 /* level */ +2 /* fid */;
2090 pSMB
->t2
.TotalDataCount
= 0;
2091 pSMB
->t2
.MaxParameterCount
= cpu_to_le16(4);
2092 /* BB find exact max data count below from sess structure BB */
2093 pSMB
->t2
.MaxDataCount
= cpu_to_le16(4000);
2094 pSMB
->t2
.MaxSetupCount
= 0;
2095 pSMB
->t2
.Reserved
= 0;
2097 pSMB
->t2
.Timeout
= 0;
2098 pSMB
->t2
.Reserved2
= 0;
2099 pSMB
->t2
.ParameterOffset
= cpu_to_le16(offsetof(struct smb_t2_qfi_req
,
2101 pSMB
->t2
.DataCount
= 0;
2102 pSMB
->t2
.DataOffset
= 0;
2103 pSMB
->t2
.SetupCount
= 1;
2104 pSMB
->t2
.Reserved3
= 0;
2105 pSMB
->t2
.SubCommand
= cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION
);
2106 byte_count
= params
+ 1 /* pad */ ;
2107 pSMB
->t2
.TotalParameterCount
= cpu_to_le16(params
);
2108 pSMB
->t2
.ParameterCount
= pSMB
->t2
.TotalParameterCount
;
2109 pSMB
->InformationLevel
= cpu_to_le16(SMB_QUERY_ATTR_FLAGS
);
2112 pSMB
->hdr
.smb_buf_length
+= byte_count
;
2113 pSMB
->t2
.ByteCount
= cpu_to_le16(byte_count
);
2115 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
2116 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
2118 cFYI(1, ("error %d in GetExtAttr", rc
));
2120 /* decode response */
2121 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
2122 if (rc
|| (pSMBr
->ByteCount
< 2))
2123 /* BB also check enough total bytes returned */
2124 /* If rc should we check for EOPNOSUPP and
2125 disable the srvino flag? or in caller? */
2126 rc
= -EIO
; /* bad smb */
2128 __u16 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
2129 __u16 count
= le16_to_cpu(pSMBr
->t2
.DataCount
);
2130 struct file_chattr_info
* pfinfo
;
2131 /* BB Do we need a cast or hash here ? */
2133 cFYI(1, ("Illegal size ret in GetExtAttr"));
2137 pfinfo
= (struct file_chattr_info
*)
2138 (data_offset
+ (char *) &pSMBr
->hdr
.Protocol
);
2139 *pExtAttrBits
= le64_to_cpu(pfinfo
->mode
);
2140 *pMask
= le64_to_cpu(pfinfo
->mask
);
2144 cifs_buf_release(pSMB
);
2146 goto GetExtAttrRetry
;
2151 #endif /* CONFIG_POSIX */
2154 CIFSSMBQPathInfo(const int xid
, struct cifsTconInfo
*tcon
,
2155 const unsigned char *searchName
,
2156 FILE_ALL_INFO
* pFindData
,
2157 const struct nls_table
*nls_codepage
, int remap
)
2159 /* level 263 SMB_QUERY_FILE_ALL_INFO */
2160 TRANSACTION2_QPI_REQ
*pSMB
= NULL
;
2161 TRANSACTION2_QPI_RSP
*pSMBr
= NULL
;
2165 __u16 params
, byte_count
;
2167 /* cFYI(1, ("In QPathInfo path %s", searchName)); */
2169 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
2174 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
2176 cifsConvertToUCS((__u16
*) pSMB
->FileName
, searchName
,
2177 PATH_MAX
, nls_codepage
, remap
);
2178 name_len
++; /* trailing null */
2180 } else { /* BB improve the check for buffer overruns BB */
2181 name_len
= strnlen(searchName
, PATH_MAX
);
2182 name_len
++; /* trailing null */
2183 strncpy(pSMB
->FileName
, searchName
, name_len
);
2186 params
= 2 /* level */ + 4 /* reserved */ + name_len
/* includes NUL */ ;
2187 pSMB
->TotalDataCount
= 0;
2188 pSMB
->MaxParameterCount
= cpu_to_le16(2);
2189 pSMB
->MaxDataCount
= cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
2190 pSMB
->MaxSetupCount
= 0;
2194 pSMB
->Reserved2
= 0;
2195 pSMB
->ParameterOffset
= cpu_to_le16(offsetof(
2196 struct smb_com_transaction2_qpi_req
,InformationLevel
) - 4);
2197 pSMB
->DataCount
= 0;
2198 pSMB
->DataOffset
= 0;
2199 pSMB
->SetupCount
= 1;
2200 pSMB
->Reserved3
= 0;
2201 pSMB
->SubCommand
= cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION
);
2202 byte_count
= params
+ 1 /* pad */ ;
2203 pSMB
->TotalParameterCount
= cpu_to_le16(params
);
2204 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
2205 pSMB
->InformationLevel
= cpu_to_le16(SMB_QUERY_FILE_ALL_INFO
);
2206 pSMB
->Reserved4
= 0;
2207 pSMB
->hdr
.smb_buf_length
+= byte_count
;
2208 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
2210 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
2211 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
2213 cFYI(1, ("Send error in QPathInfo = %d", rc
));
2214 } else { /* decode response */
2215 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
2217 if (rc
|| (pSMBr
->ByteCount
< 40))
2218 rc
= -EIO
; /* bad smb */
2219 else if (pFindData
){
2220 __u16 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
2221 memcpy((char *) pFindData
,
2222 (char *) &pSMBr
->hdr
.Protocol
+
2223 data_offset
, sizeof (FILE_ALL_INFO
));
2227 cifs_buf_release(pSMB
);
2229 goto QPathInfoRetry
;
2235 CIFSSMBUnixQPathInfo(const int xid
, struct cifsTconInfo
*tcon
,
2236 const unsigned char *searchName
,
2237 FILE_UNIX_BASIC_INFO
* pFindData
,
2238 const struct nls_table
*nls_codepage
, int remap
)
2240 /* SMB_QUERY_FILE_UNIX_BASIC */
2241 TRANSACTION2_QPI_REQ
*pSMB
= NULL
;
2242 TRANSACTION2_QPI_RSP
*pSMBr
= NULL
;
2244 int bytes_returned
= 0;
2246 __u16 params
, byte_count
;
2248 cFYI(1, ("In QPathInfo (Unix) the path %s", searchName
));
2250 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
2255 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
2257 cifsConvertToUCS((__u16
*) pSMB
->FileName
, searchName
,
2258 PATH_MAX
, nls_codepage
, remap
);
2259 name_len
++; /* trailing null */
2261 } else { /* BB improve the check for buffer overruns BB */
2262 name_len
= strnlen(searchName
, PATH_MAX
);
2263 name_len
++; /* trailing null */
2264 strncpy(pSMB
->FileName
, searchName
, name_len
);
2267 params
= 2 /* level */ + 4 /* reserved */ + name_len
/* includes NUL */ ;
2268 pSMB
->TotalDataCount
= 0;
2269 pSMB
->MaxParameterCount
= cpu_to_le16(2);
2270 /* BB find exact max SMB PDU from sess structure BB */
2271 pSMB
->MaxDataCount
= cpu_to_le16(4000);
2272 pSMB
->MaxSetupCount
= 0;
2276 pSMB
->Reserved2
= 0;
2277 pSMB
->ParameterOffset
= cpu_to_le16(offsetof(
2278 struct smb_com_transaction2_qpi_req
,InformationLevel
) - 4);
2279 pSMB
->DataCount
= 0;
2280 pSMB
->DataOffset
= 0;
2281 pSMB
->SetupCount
= 1;
2282 pSMB
->Reserved3
= 0;
2283 pSMB
->SubCommand
= cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION
);
2284 byte_count
= params
+ 1 /* pad */ ;
2285 pSMB
->TotalParameterCount
= cpu_to_le16(params
);
2286 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
2287 pSMB
->InformationLevel
= cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC
);
2288 pSMB
->Reserved4
= 0;
2289 pSMB
->hdr
.smb_buf_length
+= byte_count
;
2290 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
2292 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
2293 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
2295 cFYI(1, ("Send error in QPathInfo = %d", rc
));
2296 } else { /* decode response */
2297 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
2299 if (rc
|| (pSMBr
->ByteCount
< sizeof(FILE_UNIX_BASIC_INFO
))) {
2300 rc
= -EIO
; /* bad smb */
2302 __u16 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
2303 memcpy((char *) pFindData
,
2304 (char *) &pSMBr
->hdr
.Protocol
+
2306 sizeof (FILE_UNIX_BASIC_INFO
));
2309 cifs_buf_release(pSMB
);
2311 goto UnixQPathInfoRetry
;
2316 #if 0 /* function unused at present */
2317 int CIFSFindSingle(const int xid
, struct cifsTconInfo
*tcon
,
2318 const char *searchName
, FILE_ALL_INFO
* findData
,
2319 const struct nls_table
*nls_codepage
)
2321 /* level 257 SMB_ */
2322 TRANSACTION2_FFIRST_REQ
*pSMB
= NULL
;
2323 TRANSACTION2_FFIRST_RSP
*pSMBr
= NULL
;
2327 __u16 params
, byte_count
;
2329 cFYI(1, ("In FindUnique"));
2331 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
2336 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
2338 cifsConvertToUCS((wchar_t *) pSMB
->FileName
, searchName
, PATH_MAX
2339 /* find define for this maxpathcomponent */
2341 name_len
++; /* trailing null */
2343 } else { /* BB improve the check for buffer overruns BB */
2344 name_len
= strnlen(searchName
, PATH_MAX
);
2345 name_len
++; /* trailing null */
2346 strncpy(pSMB
->FileName
, searchName
, name_len
);
2349 params
= 12 + name_len
/* includes null */ ;
2350 pSMB
->TotalDataCount
= 0; /* no EAs */
2351 pSMB
->MaxParameterCount
= cpu_to_le16(2);
2352 pSMB
->MaxDataCount
= cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
2353 pSMB
->MaxSetupCount
= 0;
2357 pSMB
->Reserved2
= 0;
2358 pSMB
->ParameterOffset
= cpu_to_le16(
2359 offsetof(struct smb_com_transaction2_ffirst_req
,InformationLevel
) - 4);
2360 pSMB
->DataCount
= 0;
2361 pSMB
->DataOffset
= 0;
2362 pSMB
->SetupCount
= 1; /* one byte, no need to le convert */
2363 pSMB
->Reserved3
= 0;
2364 pSMB
->SubCommand
= cpu_to_le16(TRANS2_FIND_FIRST
);
2365 byte_count
= params
+ 1 /* pad */ ;
2366 pSMB
->TotalParameterCount
= cpu_to_le16(params
);
2367 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
2368 pSMB
->SearchAttributes
=
2369 cpu_to_le16(ATTR_READONLY
| ATTR_HIDDEN
| ATTR_SYSTEM
|
2371 pSMB
->SearchCount
= cpu_to_le16(16); /* BB increase */
2372 pSMB
->SearchFlags
= cpu_to_le16(1);
2373 pSMB
->InformationLevel
= cpu_to_le16(SMB_FIND_FILE_DIRECTORY_INFO
);
2374 pSMB
->SearchStorageType
= 0; /* BB what should we set this to? BB */
2375 pSMB
->hdr
.smb_buf_length
+= byte_count
;
2376 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
2378 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
2379 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
2382 cFYI(1, ("Send error in FindFileDirInfo = %d", rc
));
2383 } else { /* decode response */
2388 cifs_buf_release(pSMB
);
2390 goto findUniqueRetry
;
2394 #endif /* end unused (temporarily) function */
2396 /* xid, tcon, searchName and codepage are input parms, rest are returned */
2398 CIFSFindFirst(const int xid
, struct cifsTconInfo
*tcon
,
2399 const char *searchName
,
2400 const struct nls_table
*nls_codepage
,
2402 struct cifs_search_info
* psrch_inf
, int remap
)
2404 /* level 257 SMB_ */
2405 TRANSACTION2_FFIRST_REQ
*pSMB
= NULL
;
2406 TRANSACTION2_FFIRST_RSP
*pSMBr
= NULL
;
2407 T2_FFIRST_RSP_PARMS
* parms
;
2409 int bytes_returned
= 0;
2411 __u16 params
, byte_count
;
2413 cFYI(1, ("In FindFirst for %s",searchName
));
2416 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
2421 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
2423 cifsConvertToUCS((__u16
*) pSMB
->FileName
,searchName
,
2424 PATH_MAX
, nls_codepage
, remap
);
2425 /* We can not add the asterik earlier in case
2426 it got remapped to 0xF03A as if it were part of the
2427 directory name instead of a wildcard */
2429 pSMB
->FileName
[name_len
] = '\\';
2430 pSMB
->FileName
[name_len
+1] = 0;
2431 pSMB
->FileName
[name_len
+2] = '*';
2432 pSMB
->FileName
[name_len
+3] = 0;
2433 name_len
+= 4; /* now the trailing null */
2434 pSMB
->FileName
[name_len
] = 0; /* null terminate just in case */
2435 pSMB
->FileName
[name_len
+1] = 0;
2437 } else { /* BB add check for overrun of SMB buf BB */
2438 name_len
= strnlen(searchName
, PATH_MAX
);
2439 name_len
++; /* trailing null */
2440 /* BB fix here and in unicode clause above ie
2441 if(name_len > buffersize-header)
2442 free buffer exit; BB */
2443 strncpy(pSMB
->FileName
, searchName
, name_len
);
2444 pSMB
->FileName
[name_len
] = 0; /* just in case */
2447 params
= 12 + name_len
/* includes null */ ;
2448 pSMB
->TotalDataCount
= 0; /* no EAs */
2449 pSMB
->MaxParameterCount
= cpu_to_le16(10);
2450 pSMB
->MaxDataCount
= cpu_to_le16((tcon
->ses
->server
->maxBuf
-
2451 MAX_CIFS_HDR_SIZE
) & 0xFFFFFF00);
2452 pSMB
->MaxSetupCount
= 0;
2456 pSMB
->Reserved2
= 0;
2457 byte_count
= params
+ 1 /* pad */ ;
2458 pSMB
->TotalParameterCount
= cpu_to_le16(params
);
2459 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
2460 pSMB
->ParameterOffset
= cpu_to_le16(
2461 offsetof(struct smb_com_transaction2_ffirst_req
, SearchAttributes
) - 4);
2462 pSMB
->DataCount
= 0;
2463 pSMB
->DataOffset
= 0;
2464 pSMB
->SetupCount
= 1; /* one byte, no need to make endian neutral */
2465 pSMB
->Reserved3
= 0;
2466 pSMB
->SubCommand
= cpu_to_le16(TRANS2_FIND_FIRST
);
2467 pSMB
->SearchAttributes
=
2468 cpu_to_le16(ATTR_READONLY
| ATTR_HIDDEN
| ATTR_SYSTEM
|
2470 pSMB
->SearchCount
= cpu_to_le16(CIFSMaxBufSize
/sizeof(FILE_UNIX_INFO
));
2471 pSMB
->SearchFlags
= cpu_to_le16(CIFS_SEARCH_CLOSE_AT_END
|
2472 CIFS_SEARCH_RETURN_RESUME
);
2473 pSMB
->InformationLevel
= cpu_to_le16(psrch_inf
->info_level
);
2475 /* BB what should we set StorageType to? Does it matter? BB */
2476 pSMB
->SearchStorageType
= 0;
2477 pSMB
->hdr
.smb_buf_length
+= byte_count
;
2478 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
2480 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
2481 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
2483 if (rc
) {/* BB add logic to retry regular search if Unix search rejected unexpectedly by server */
2484 /* BB Add code to handle unsupported level rc */
2485 cFYI(1, ("Error in FindFirst = %d", rc
));
2488 cifs_buf_release(pSMB
);
2490 /* BB eventually could optimize out free and realloc of buf */
2493 goto findFirstRetry
;
2494 } else { /* decode response */
2495 /* BB remember to free buffer if error BB */
2496 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
2498 if (pSMBr
->hdr
.Flags2
& SMBFLG2_UNICODE
)
2499 psrch_inf
->unicode
= TRUE
;
2501 psrch_inf
->unicode
= FALSE
;
2503 psrch_inf
->ntwrk_buf_start
= (char *)pSMBr
;
2504 psrch_inf
->srch_entries_start
=
2505 (char *) &pSMBr
->hdr
.Protocol
+
2506 le16_to_cpu(pSMBr
->t2
.DataOffset
);
2508 parms
= (T2_FFIRST_RSP_PARMS
*)((char *) &pSMBr
->hdr
.Protocol
+
2509 le16_to_cpu(pSMBr
->t2
.ParameterOffset
));
2511 if(parms
->EndofSearch
)
2512 psrch_inf
->endOfSearch
= TRUE
;
2514 psrch_inf
->endOfSearch
= FALSE
;
2516 psrch_inf
->entries_in_buffer
= le16_to_cpu(parms
->SearchCount
);
2517 psrch_inf
->index_of_last_entry
=
2518 psrch_inf
->entries_in_buffer
;
2519 /*cFYI(1,("entries in buf %d index_of_last %d",psrch_inf->entries_in_buffer,psrch_inf->index_of_last_entry)); */
2520 *pnetfid
= parms
->SearchHandle
;
2522 cifs_buf_release(pSMB
);
2529 int CIFSFindNext(const int xid
, struct cifsTconInfo
*tcon
,
2530 __u16 searchHandle
, struct cifs_search_info
* psrch_inf
)
2532 TRANSACTION2_FNEXT_REQ
*pSMB
= NULL
;
2533 TRANSACTION2_FNEXT_RSP
*pSMBr
= NULL
;
2534 T2_FNEXT_RSP_PARMS
* parms
;
2535 char *response_data
;
2537 int bytes_returned
, name_len
;
2538 __u16 params
, byte_count
;
2540 cFYI(1, ("In FindNext"));
2542 if(psrch_inf
->endOfSearch
== TRUE
)
2545 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
2550 params
= 14; /* includes 2 bytes of null string, converted to LE below */
2552 pSMB
->TotalDataCount
= 0; /* no EAs */
2553 pSMB
->MaxParameterCount
= cpu_to_le16(8);
2554 pSMB
->MaxDataCount
=
2555 cpu_to_le16((tcon
->ses
->server
->maxBuf
- MAX_CIFS_HDR_SIZE
) & 0xFFFFFF00);
2556 pSMB
->MaxSetupCount
= 0;
2560 pSMB
->Reserved2
= 0;
2561 pSMB
->ParameterOffset
= cpu_to_le16(
2562 offsetof(struct smb_com_transaction2_fnext_req
,SearchHandle
) - 4);
2563 pSMB
->DataCount
= 0;
2564 pSMB
->DataOffset
= 0;
2565 pSMB
->SetupCount
= 1;
2566 pSMB
->Reserved3
= 0;
2567 pSMB
->SubCommand
= cpu_to_le16(TRANS2_FIND_NEXT
);
2568 pSMB
->SearchHandle
= searchHandle
; /* always kept as le */
2570 cpu_to_le16(CIFSMaxBufSize
/ sizeof (FILE_UNIX_INFO
));
2571 /* test for Unix extensions */
2572 /* if (tcon->ses->capabilities & CAP_UNIX) {
2573 pSMB->InformationLevel = cpu_to_le16(SMB_FIND_FILE_UNIX);
2574 psrch_inf->info_level = SMB_FIND_FILE_UNIX;
2576 pSMB->InformationLevel =
2577 cpu_to_le16(SMB_FIND_FILE_DIRECTORY_INFO);
2578 psrch_inf->info_level = SMB_FIND_FILE_DIRECTORY_INFO;
2580 pSMB
->InformationLevel
= cpu_to_le16(psrch_inf
->info_level
);
2581 pSMB
->ResumeKey
= psrch_inf
->resume_key
;
2583 cpu_to_le16(CIFS_SEARCH_CLOSE_AT_END
| CIFS_SEARCH_RETURN_RESUME
);
2585 name_len
= psrch_inf
->resume_name_len
;
2587 if(name_len
< PATH_MAX
) {
2588 memcpy(pSMB
->ResumeFileName
, psrch_inf
->presume_name
, name_len
);
2589 byte_count
+= name_len
;
2592 goto FNext2_err_exit
;
2594 byte_count
= params
+ 1 /* pad */ ;
2595 pSMB
->TotalParameterCount
= cpu_to_le16(params
);
2596 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
2597 pSMB
->hdr
.smb_buf_length
+= byte_count
;
2598 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
2600 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
2601 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
2605 psrch_inf
->endOfSearch
= TRUE
;
2606 rc
= 0; /* search probably was closed at end of search above */
2608 cFYI(1, ("FindNext returned = %d", rc
));
2609 } else { /* decode response */
2610 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
2613 /* BB fixme add lock for file (srch_info) struct here */
2614 if (pSMBr
->hdr
.Flags2
& SMBFLG2_UNICODE
)
2615 psrch_inf
->unicode
= TRUE
;
2617 psrch_inf
->unicode
= FALSE
;
2618 response_data
= (char *) &pSMBr
->hdr
.Protocol
+
2619 le16_to_cpu(pSMBr
->t2
.ParameterOffset
);
2620 parms
= (T2_FNEXT_RSP_PARMS
*)response_data
;
2621 response_data
= (char *)&pSMBr
->hdr
.Protocol
+
2622 le16_to_cpu(pSMBr
->t2
.DataOffset
);
2623 cifs_buf_release(psrch_inf
->ntwrk_buf_start
);
2624 psrch_inf
->srch_entries_start
= response_data
;
2625 psrch_inf
->ntwrk_buf_start
= (char *)pSMB
;
2626 if(parms
->EndofSearch
)
2627 psrch_inf
->endOfSearch
= TRUE
;
2629 psrch_inf
->endOfSearch
= FALSE
;
2631 psrch_inf
->entries_in_buffer
= le16_to_cpu(parms
->SearchCount
);
2632 psrch_inf
->index_of_last_entry
+=
2633 psrch_inf
->entries_in_buffer
;
2634 /* cFYI(1,("fnxt2 entries in buf %d index_of_last %d",psrch_inf->entries_in_buffer,psrch_inf->index_of_last_entry)); */
2636 /* BB fixme add unlock here */
2641 /* BB On error, should we leave previous search buf (and count and
2642 last entry fields) intact or free the previous one? */
2644 /* Note: On -EAGAIN error only caller can retry on handle based calls
2645 since file handle passed in no longer valid */
2648 cifs_buf_release(pSMB
);
2654 CIFSFindClose(const int xid
, struct cifsTconInfo
*tcon
, const __u16 searchHandle
)
2657 FINDCLOSE_REQ
*pSMB
= NULL
;
2658 CLOSE_RSP
*pSMBr
= NULL
; /* BB removeme BB */
2661 cFYI(1, ("In CIFSSMBFindClose"));
2662 rc
= small_smb_init(SMB_COM_FIND_CLOSE2
, 1, tcon
, (void **)&pSMB
);
2664 /* no sense returning error if session restarted
2665 as file handle has been closed */
2671 pSMBr
= (CLOSE_RSP
*)pSMB
; /* BB removeme BB */
2672 pSMB
->FileID
= searchHandle
;
2673 pSMB
->ByteCount
= 0;
2674 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
2675 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
2677 cERROR(1, ("Send error in FindClose = %d", rc
));
2679 cifs_small_buf_release(pSMB
);
2681 /* Since session is dead, search handle closed on server already */
2688 #ifdef CONFIG_CIFS_EXPERIMENTAL
2690 CIFSGetSrvInodeNumber(const int xid
, struct cifsTconInfo
*tcon
,
2691 const unsigned char *searchName
,
2692 __u64
* inode_number
,
2693 const struct nls_table
*nls_codepage
, int remap
)
2696 TRANSACTION2_QPI_REQ
*pSMB
= NULL
;
2697 TRANSACTION2_QPI_RSP
*pSMBr
= NULL
;
2698 int name_len
, bytes_returned
;
2699 __u16 params
, byte_count
;
2701 cFYI(1,("In GetSrvInodeNum for %s",searchName
));
2705 GetInodeNumberRetry
:
2706 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
2712 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
2714 cifsConvertToUCS((__u16
*) pSMB
->FileName
, searchName
,
2715 PATH_MAX
,nls_codepage
, remap
);
2716 name_len
++; /* trailing null */
2718 } else { /* BB improve the check for buffer overruns BB */
2719 name_len
= strnlen(searchName
, PATH_MAX
);
2720 name_len
++; /* trailing null */
2721 strncpy(pSMB
->FileName
, searchName
, name_len
);
2724 params
= 2 /* level */ + 4 /* rsrvd */ + name_len
/* incl null */ ;
2725 pSMB
->TotalDataCount
= 0;
2726 pSMB
->MaxParameterCount
= cpu_to_le16(2);
2727 /* BB find exact max data count below from sess structure BB */
2728 pSMB
->MaxDataCount
= cpu_to_le16(4000);
2729 pSMB
->MaxSetupCount
= 0;
2733 pSMB
->Reserved2
= 0;
2734 pSMB
->ParameterOffset
= cpu_to_le16(offsetof(
2735 struct smb_com_transaction2_qpi_req
,InformationLevel
) - 4);
2736 pSMB
->DataCount
= 0;
2737 pSMB
->DataOffset
= 0;
2738 pSMB
->SetupCount
= 1;
2739 pSMB
->Reserved3
= 0;
2740 pSMB
->SubCommand
= cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION
);
2741 byte_count
= params
+ 1 /* pad */ ;
2742 pSMB
->TotalParameterCount
= cpu_to_le16(params
);
2743 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
2744 pSMB
->InformationLevel
= cpu_to_le16(SMB_QUERY_FILE_INTERNAL_INFO
);
2745 pSMB
->Reserved4
= 0;
2746 pSMB
->hdr
.smb_buf_length
+= byte_count
;
2747 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
2749 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
2750 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
2752 cFYI(1, ("error %d in QueryInternalInfo", rc
));
2754 /* decode response */
2755 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
2756 if (rc
|| (pSMBr
->ByteCount
< 2))
2757 /* BB also check enough total bytes returned */
2758 /* If rc should we check for EOPNOSUPP and
2759 disable the srvino flag? or in caller? */
2760 rc
= -EIO
; /* bad smb */
2762 __u16 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
2763 __u16 count
= le16_to_cpu(pSMBr
->t2
.DataCount
);
2764 struct file_internal_info
* pfinfo
;
2765 /* BB Do we need a cast or hash here ? */
2767 cFYI(1, ("Illegal size ret in QryIntrnlInf"));
2769 goto GetInodeNumOut
;
2771 pfinfo
= (struct file_internal_info
*)
2772 (data_offset
+ (char *) &pSMBr
->hdr
.Protocol
);
2773 *inode_number
= pfinfo
->UniqueId
;
2777 cifs_buf_release(pSMB
);
2779 goto GetInodeNumberRetry
;
2782 #endif /* CIFS_EXPERIMENTAL */
2785 CIFSGetDFSRefer(const int xid
, struct cifsSesInfo
*ses
,
2786 const unsigned char *searchName
,
2787 unsigned char **targetUNCs
,
2788 unsigned int *number_of_UNC_in_array
,
2789 const struct nls_table
*nls_codepage
, int remap
)
2791 /* TRANS2_GET_DFS_REFERRAL */
2792 TRANSACTION2_GET_DFS_REFER_REQ
*pSMB
= NULL
;
2793 TRANSACTION2_GET_DFS_REFER_RSP
*pSMBr
= NULL
;
2794 struct dfs_referral_level_3
* referrals
= NULL
;
2800 __u16 params
, byte_count
;
2801 *number_of_UNC_in_array
= 0;
2804 cFYI(1, ("In GetDFSRefer the path %s", searchName
));
2808 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, NULL
, (void **) &pSMB
,
2813 pSMB
->hdr
.Tid
= ses
->ipc_tid
;
2814 pSMB
->hdr
.Uid
= ses
->Suid
;
2815 if (ses
->capabilities
& CAP_STATUS32
) {
2816 pSMB
->hdr
.Flags2
|= SMBFLG2_ERR_STATUS
;
2818 if (ses
->capabilities
& CAP_DFS
) {
2819 pSMB
->hdr
.Flags2
|= SMBFLG2_DFS
;
2822 if (ses
->capabilities
& CAP_UNICODE
) {
2823 pSMB
->hdr
.Flags2
|= SMBFLG2_UNICODE
;
2825 cifsConvertToUCS((__u16
*) pSMB
->RequestFileName
,
2826 searchName
, PATH_MAX
, nls_codepage
, remap
);
2827 name_len
++; /* trailing null */
2829 } else { /* BB improve the check for buffer overruns BB */
2830 name_len
= strnlen(searchName
, PATH_MAX
);
2831 name_len
++; /* trailing null */
2832 strncpy(pSMB
->RequestFileName
, searchName
, name_len
);
2835 params
= 2 /* level */ + name_len
/*includes null */ ;
2836 pSMB
->TotalDataCount
= 0;
2837 pSMB
->DataCount
= 0;
2838 pSMB
->DataOffset
= 0;
2839 pSMB
->MaxParameterCount
= 0;
2840 pSMB
->MaxDataCount
= cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
2841 pSMB
->MaxSetupCount
= 0;
2845 pSMB
->Reserved2
= 0;
2846 pSMB
->ParameterOffset
= cpu_to_le16(offsetof(
2847 struct smb_com_transaction2_get_dfs_refer_req
, MaxReferralLevel
) - 4);
2848 pSMB
->SetupCount
= 1;
2849 pSMB
->Reserved3
= 0;
2850 pSMB
->SubCommand
= cpu_to_le16(TRANS2_GET_DFS_REFERRAL
);
2851 byte_count
= params
+ 3 /* pad */ ;
2852 pSMB
->ParameterCount
= cpu_to_le16(params
);
2853 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
2854 pSMB
->MaxReferralLevel
= cpu_to_le16(3);
2855 pSMB
->hdr
.smb_buf_length
+= byte_count
;
2856 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
2858 rc
= SendReceive(xid
, ses
, (struct smb_hdr
*) pSMB
,
2859 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
2861 cFYI(1, ("Send error in GetDFSRefer = %d", rc
));
2862 } else { /* decode response */
2863 /* BB Add logic to parse referrals here */
2864 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
2866 if (rc
|| (pSMBr
->ByteCount
< 17)) /* BB also check enough total bytes returned */
2867 rc
= -EIO
; /* bad smb */
2869 __u16 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
2870 __u16 data_count
= le16_to_cpu(pSMBr
->t2
.DataCount
);
2873 ("Decoding GetDFSRefer response. BCC: %d Offset %d",
2874 pSMBr
->ByteCount
, data_offset
));
2876 (struct dfs_referral_level_3
*)
2877 (8 /* sizeof start of data block */ +
2879 (char *) &pSMBr
->hdr
.Protocol
);
2880 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",
2881 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
)));
2882 /* BB This field is actually two bytes in from start of
2883 data block so we could do safety check that DataBlock
2884 begins at address of pSMBr->NumberOfReferrals */
2885 *number_of_UNC_in_array
= le16_to_cpu(pSMBr
->NumberOfReferrals
);
2887 /* BB Fix below so can return more than one referral */
2888 if(*number_of_UNC_in_array
> 1)
2889 *number_of_UNC_in_array
= 1;
2891 /* get the length of the strings describing refs */
2893 for(i
=0;i
<*number_of_UNC_in_array
;i
++) {
2894 /* make sure that DfsPathOffset not past end */
2895 __u16 offset
= le16_to_cpu(referrals
->DfsPathOffset
);
2896 if (offset
> data_count
) {
2897 /* if invalid referral, stop here and do
2898 not try to copy any more */
2899 *number_of_UNC_in_array
= i
;
2902 temp
= ((char *)referrals
) + offset
;
2904 if (pSMBr
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
2905 name_len
+= UniStrnlen((wchar_t *)temp
,data_count
);
2907 name_len
+= strnlen(temp
,data_count
);
2910 /* BB add check that referral pointer does not fall off end PDU */
2913 /* BB add check for name_len bigger than bcc */
2915 kmalloc(name_len
+1+ (*number_of_UNC_in_array
),GFP_KERNEL
);
2916 if(*targetUNCs
== NULL
) {
2920 /* copy the ref strings */
2922 (struct dfs_referral_level_3
*)
2923 (8 /* sizeof data hdr */ +
2925 (char *) &pSMBr
->hdr
.Protocol
);
2927 for(i
=0;i
<*number_of_UNC_in_array
;i
++) {
2928 temp
= ((char *)referrals
) + le16_to_cpu(referrals
->DfsPathOffset
);
2929 if (pSMBr
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
2930 cifs_strfromUCS_le(*targetUNCs
,
2931 (wchar_t *) temp
, name_len
, nls_codepage
);
2933 strncpy(*targetUNCs
,temp
,name_len
);
2935 /* BB update target_uncs pointers */
2945 cifs_buf_release(pSMB
);
2954 CIFSSMBQFSInfo(const int xid
, struct cifsTconInfo
*tcon
, struct kstatfs
*FSData
)
2956 /* level 0x103 SMB_QUERY_FILE_SYSTEM_INFO */
2957 TRANSACTION2_QFSI_REQ
*pSMB
= NULL
;
2958 TRANSACTION2_QFSI_RSP
*pSMBr
= NULL
;
2959 FILE_SYSTEM_INFO
*response_data
;
2961 int bytes_returned
= 0;
2962 __u16 params
, byte_count
;
2964 cFYI(1, ("In QFSInfo"));
2966 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
2971 params
= 2; /* level */
2972 pSMB
->TotalDataCount
= 0;
2973 pSMB
->MaxParameterCount
= cpu_to_le16(2);
2974 pSMB
->MaxDataCount
= cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
2975 pSMB
->MaxSetupCount
= 0;
2979 pSMB
->Reserved2
= 0;
2980 byte_count
= params
+ 1 /* pad */ ;
2981 pSMB
->TotalParameterCount
= cpu_to_le16(params
);
2982 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
2983 pSMB
->ParameterOffset
= cpu_to_le16(offsetof(
2984 struct smb_com_transaction2_qfsi_req
, InformationLevel
) - 4);
2985 pSMB
->DataCount
= 0;
2986 pSMB
->DataOffset
= 0;
2987 pSMB
->SetupCount
= 1;
2988 pSMB
->Reserved3
= 0;
2989 pSMB
->SubCommand
= cpu_to_le16(TRANS2_QUERY_FS_INFORMATION
);
2990 pSMB
->InformationLevel
= cpu_to_le16(SMB_QUERY_FS_SIZE_INFO
);
2991 pSMB
->hdr
.smb_buf_length
+= byte_count
;
2992 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
2994 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
2995 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
2997 cERROR(1, ("Send error in QFSInfo = %d", rc
));
2998 } else { /* decode response */
2999 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
3001 if (rc
|| (pSMBr
->ByteCount
< 24)) /* BB alsO CHEck enough total bytes returned */
3002 rc
= -EIO
; /* bad smb */
3004 __u16 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
3006 ("Decoding qfsinfo response. BCC: %d Offset %d",
3007 pSMBr
->ByteCount
, data_offset
));
3011 *) (((char *) &pSMBr
->hdr
.Protocol
) +
3014 le32_to_cpu(response_data
->BytesPerSector
) *
3015 le32_to_cpu(response_data
->
3016 SectorsPerAllocationUnit
);
3018 le64_to_cpu(response_data
->TotalAllocationUnits
);
3019 FSData
->f_bfree
= FSData
->f_bavail
=
3020 le64_to_cpu(response_data
->FreeAllocationUnits
);
3022 ("Blocks: %lld Free: %lld Block size %ld",
3023 (unsigned long long)FSData
->f_blocks
,
3024 (unsigned long long)FSData
->f_bfree
,
3028 cifs_buf_release(pSMB
);
3037 CIFSSMBQFSAttributeInfo(const int xid
, struct cifsTconInfo
*tcon
)
3039 /* level 0x105 SMB_QUERY_FILE_SYSTEM_INFO */
3040 TRANSACTION2_QFSI_REQ
*pSMB
= NULL
;
3041 TRANSACTION2_QFSI_RSP
*pSMBr
= NULL
;
3042 FILE_SYSTEM_ATTRIBUTE_INFO
*response_data
;
3044 int bytes_returned
= 0;
3045 __u16 params
, byte_count
;
3047 cFYI(1, ("In QFSAttributeInfo"));
3049 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
3054 params
= 2; /* level */
3055 pSMB
->TotalDataCount
= 0;
3056 pSMB
->MaxParameterCount
= cpu_to_le16(2);
3057 pSMB
->MaxDataCount
= cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
3058 pSMB
->MaxSetupCount
= 0;
3062 pSMB
->Reserved2
= 0;
3063 byte_count
= params
+ 1 /* pad */ ;
3064 pSMB
->TotalParameterCount
= cpu_to_le16(params
);
3065 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
3066 pSMB
->ParameterOffset
= cpu_to_le16(offsetof(
3067 struct smb_com_transaction2_qfsi_req
, InformationLevel
) - 4);
3068 pSMB
->DataCount
= 0;
3069 pSMB
->DataOffset
= 0;
3070 pSMB
->SetupCount
= 1;
3071 pSMB
->Reserved3
= 0;
3072 pSMB
->SubCommand
= cpu_to_le16(TRANS2_QUERY_FS_INFORMATION
);
3073 pSMB
->InformationLevel
= cpu_to_le16(SMB_QUERY_FS_ATTRIBUTE_INFO
);
3074 pSMB
->hdr
.smb_buf_length
+= byte_count
;
3075 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
3077 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
3078 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
3080 cERROR(1, ("Send error in QFSAttributeInfo = %d", rc
));
3081 } else { /* decode response */
3082 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
3084 if (rc
|| (pSMBr
->ByteCount
< 13)) { /* BB also check enough bytes returned */
3085 rc
= -EIO
; /* bad smb */
3087 __u16 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
3089 (FILE_SYSTEM_ATTRIBUTE_INFO
3090 *) (((char *) &pSMBr
->hdr
.Protocol
) +
3092 memcpy(&tcon
->fsAttrInfo
, response_data
,
3093 sizeof (FILE_SYSTEM_ATTRIBUTE_INFO
));
3096 cifs_buf_release(pSMB
);
3099 goto QFSAttributeRetry
;
3105 CIFSSMBQFSDeviceInfo(const int xid
, struct cifsTconInfo
*tcon
)
3107 /* level 0x104 SMB_QUERY_FILE_SYSTEM_INFO */
3108 TRANSACTION2_QFSI_REQ
*pSMB
= NULL
;
3109 TRANSACTION2_QFSI_RSP
*pSMBr
= NULL
;
3110 FILE_SYSTEM_DEVICE_INFO
*response_data
;
3112 int bytes_returned
= 0;
3113 __u16 params
, byte_count
;
3115 cFYI(1, ("In QFSDeviceInfo"));
3117 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
3122 params
= 2; /* level */
3123 pSMB
->TotalDataCount
= 0;
3124 pSMB
->MaxParameterCount
= cpu_to_le16(2);
3125 pSMB
->MaxDataCount
= cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
3126 pSMB
->MaxSetupCount
= 0;
3130 pSMB
->Reserved2
= 0;
3131 byte_count
= params
+ 1 /* pad */ ;
3132 pSMB
->TotalParameterCount
= cpu_to_le16(params
);
3133 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
3134 pSMB
->ParameterOffset
= cpu_to_le16(offsetof(
3135 struct smb_com_transaction2_qfsi_req
, InformationLevel
) - 4);
3137 pSMB
->DataCount
= 0;
3138 pSMB
->DataOffset
= 0;
3139 pSMB
->SetupCount
= 1;
3140 pSMB
->Reserved3
= 0;
3141 pSMB
->SubCommand
= cpu_to_le16(TRANS2_QUERY_FS_INFORMATION
);
3142 pSMB
->InformationLevel
= cpu_to_le16(SMB_QUERY_FS_DEVICE_INFO
);
3143 pSMB
->hdr
.smb_buf_length
+= byte_count
;
3144 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
3146 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
3147 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
3149 cFYI(1, ("Send error in QFSDeviceInfo = %d", rc
));
3150 } else { /* decode response */
3151 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
3153 if (rc
|| (pSMBr
->ByteCount
< sizeof (FILE_SYSTEM_DEVICE_INFO
)))
3154 rc
= -EIO
; /* bad smb */
3156 __u16 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
3158 (FILE_SYSTEM_DEVICE_INFO
*)
3159 (((char *) &pSMBr
->hdr
.Protocol
) +
3161 memcpy(&tcon
->fsDevInfo
, response_data
,
3162 sizeof (FILE_SYSTEM_DEVICE_INFO
));
3165 cifs_buf_release(pSMB
);
3168 goto QFSDeviceRetry
;
3174 CIFSSMBQFSUnixInfo(const int xid
, struct cifsTconInfo
*tcon
)
3176 /* level 0x200 SMB_QUERY_CIFS_UNIX_INFO */
3177 TRANSACTION2_QFSI_REQ
*pSMB
= NULL
;
3178 TRANSACTION2_QFSI_RSP
*pSMBr
= NULL
;
3179 FILE_SYSTEM_UNIX_INFO
*response_data
;
3181 int bytes_returned
= 0;
3182 __u16 params
, byte_count
;
3184 cFYI(1, ("In QFSUnixInfo"));
3186 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
3191 params
= 2; /* level */
3192 pSMB
->TotalDataCount
= 0;
3193 pSMB
->DataCount
= 0;
3194 pSMB
->DataOffset
= 0;
3195 pSMB
->MaxParameterCount
= cpu_to_le16(2);
3196 pSMB
->MaxDataCount
= cpu_to_le16(100); /* BB find exact max SMB PDU from sess structure BB */
3197 pSMB
->MaxSetupCount
= 0;
3201 pSMB
->Reserved2
= 0;
3202 byte_count
= params
+ 1 /* pad */ ;
3203 pSMB
->ParameterCount
= cpu_to_le16(params
);
3204 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
3205 pSMB
->ParameterOffset
= cpu_to_le16(offsetof(struct
3206 smb_com_transaction2_qfsi_req
, InformationLevel
) - 4);
3207 pSMB
->SetupCount
= 1;
3208 pSMB
->Reserved3
= 0;
3209 pSMB
->SubCommand
= cpu_to_le16(TRANS2_QUERY_FS_INFORMATION
);
3210 pSMB
->InformationLevel
= cpu_to_le16(SMB_QUERY_CIFS_UNIX_INFO
);
3211 pSMB
->hdr
.smb_buf_length
+= byte_count
;
3212 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
3214 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
3215 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
3217 cERROR(1, ("Send error in QFSUnixInfo = %d", rc
));
3218 } else { /* decode response */
3219 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
3221 if (rc
|| (pSMBr
->ByteCount
< 13)) {
3222 rc
= -EIO
; /* bad smb */
3224 __u16 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
3226 (FILE_SYSTEM_UNIX_INFO
3227 *) (((char *) &pSMBr
->hdr
.Protocol
) +
3229 memcpy(&tcon
->fsUnixInfo
, response_data
,
3230 sizeof (FILE_SYSTEM_UNIX_INFO
));
3233 cifs_buf_release(pSMB
);
3244 CIFSSMBQFSPosixInfo(const int xid
, struct cifsTconInfo
*tcon
,
3245 struct kstatfs
*FSData
)
3247 /* level 0x201 SMB_QUERY_CIFS_POSIX_INFO */
3248 TRANSACTION2_QFSI_REQ
*pSMB
= NULL
;
3249 TRANSACTION2_QFSI_RSP
*pSMBr
= NULL
;
3250 FILE_SYSTEM_POSIX_INFO
*response_data
;
3252 int bytes_returned
= 0;
3253 __u16 params
, byte_count
;
3255 cFYI(1, ("In QFSPosixInfo"));
3257 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
3262 params
= 2; /* level */
3263 pSMB
->TotalDataCount
= 0;
3264 pSMB
->DataCount
= 0;
3265 pSMB
->DataOffset
= 0;
3266 pSMB
->MaxParameterCount
= cpu_to_le16(2);
3267 pSMB
->MaxDataCount
= cpu_to_le16(100); /* BB find exact max SMB PDU from sess structure BB */
3268 pSMB
->MaxSetupCount
= 0;
3272 pSMB
->Reserved2
= 0;
3273 byte_count
= params
+ 1 /* pad */ ;
3274 pSMB
->ParameterCount
= cpu_to_le16(params
);
3275 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
3276 pSMB
->ParameterOffset
= cpu_to_le16(offsetof(struct
3277 smb_com_transaction2_qfsi_req
, InformationLevel
) - 4);
3278 pSMB
->SetupCount
= 1;
3279 pSMB
->Reserved3
= 0;
3280 pSMB
->SubCommand
= cpu_to_le16(TRANS2_QUERY_FS_INFORMATION
);
3281 pSMB
->InformationLevel
= cpu_to_le16(SMB_QUERY_POSIX_FS_INFO
);
3282 pSMB
->hdr
.smb_buf_length
+= byte_count
;
3283 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
3285 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
3286 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
3288 cFYI(1, ("Send error in QFSUnixInfo = %d", rc
));
3289 } else { /* decode response */
3290 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
3292 if (rc
|| (pSMBr
->ByteCount
< 13)) {
3293 rc
= -EIO
; /* bad smb */
3295 __u16 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
3297 (FILE_SYSTEM_POSIX_INFO
3298 *) (((char *) &pSMBr
->hdr
.Protocol
) +
3301 le32_to_cpu(response_data
->BlockSize
);
3303 le64_to_cpu(response_data
->TotalBlocks
);
3305 le64_to_cpu(response_data
->BlocksAvail
);
3306 if(response_data
->UserBlocksAvail
== -1) {
3307 FSData
->f_bavail
= FSData
->f_bfree
;
3310 le64_to_cpu(response_data
->UserBlocksAvail
);
3312 if(response_data
->TotalFileNodes
!= -1)
3314 le64_to_cpu(response_data
->TotalFileNodes
);
3315 if(response_data
->FreeFileNodes
!= -1)
3317 le64_to_cpu(response_data
->FreeFileNodes
);
3320 cifs_buf_release(pSMB
);
3329 /* We can not use write of zero bytes trick to
3330 set file size due to need for large file support. Also note that
3331 this SetPathInfo is preferred to SetFileInfo based method in next
3332 routine which is only needed to work around a sharing violation bug
3333 in Samba which this routine can run into */
3336 CIFSSMBSetEOF(const int xid
, struct cifsTconInfo
*tcon
, const char *fileName
,
3337 __u64 size
, int SetAllocation
,
3338 const struct nls_table
*nls_codepage
, int remap
)
3340 struct smb_com_transaction2_spi_req
*pSMB
= NULL
;
3341 struct smb_com_transaction2_spi_rsp
*pSMBr
= NULL
;
3342 struct file_end_of_file_info
*parm_data
;
3345 int bytes_returned
= 0;
3346 __u16 params
, byte_count
, data_count
, param_offset
, offset
;
3348 cFYI(1, ("In SetEOF"));
3350 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
3355 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
3357 cifsConvertToUCS((__u16
*) pSMB
->FileName
, fileName
,
3358 PATH_MAX
, nls_codepage
, remap
);
3359 name_len
++; /* trailing null */
3361 } else { /* BB improve the check for buffer overruns BB */
3362 name_len
= strnlen(fileName
, PATH_MAX
);
3363 name_len
++; /* trailing null */
3364 strncpy(pSMB
->FileName
, fileName
, name_len
);
3366 params
= 6 + name_len
;
3367 data_count
= sizeof (struct file_end_of_file_info
);
3368 pSMB
->MaxParameterCount
= cpu_to_le16(2);
3369 pSMB
->MaxDataCount
= cpu_to_le16(1000); /* BB find max SMB size from sess */
3370 pSMB
->MaxSetupCount
= 0;
3374 pSMB
->Reserved2
= 0;
3375 param_offset
= offsetof(struct smb_com_transaction2_spi_req
,
3376 InformationLevel
) - 4;
3377 offset
= param_offset
+ params
;
3379 if (tcon
->ses
->capabilities
& CAP_INFOLEVEL_PASSTHRU
)
3380 pSMB
->InformationLevel
=
3381 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2
);
3383 pSMB
->InformationLevel
=
3384 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO
);
3385 } else /* Set File Size */ {
3386 if (tcon
->ses
->capabilities
& CAP_INFOLEVEL_PASSTHRU
)
3387 pSMB
->InformationLevel
=
3388 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO2
);
3390 pSMB
->InformationLevel
=
3391 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO
);
3395 (struct file_end_of_file_info
*) (((char *) &pSMB
->hdr
.Protocol
) +
3397 pSMB
->ParameterOffset
= cpu_to_le16(param_offset
);
3398 pSMB
->DataOffset
= cpu_to_le16(offset
);
3399 pSMB
->SetupCount
= 1;
3400 pSMB
->Reserved3
= 0;
3401 pSMB
->SubCommand
= cpu_to_le16(TRANS2_SET_PATH_INFORMATION
);
3402 byte_count
= 3 /* pad */ + params
+ data_count
;
3403 pSMB
->DataCount
= cpu_to_le16(data_count
);
3404 pSMB
->TotalDataCount
= pSMB
->DataCount
;
3405 pSMB
->ParameterCount
= cpu_to_le16(params
);
3406 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
3407 pSMB
->Reserved4
= 0;
3408 pSMB
->hdr
.smb_buf_length
+= byte_count
;
3409 parm_data
->FileSize
= cpu_to_le64(size
);
3410 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
3411 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
3412 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
3414 cFYI(1, ("SetPathInfo (file size) returned %d", rc
));
3417 cifs_buf_release(pSMB
);
3426 CIFSSMBSetFileSize(const int xid
, struct cifsTconInfo
*tcon
, __u64 size
,
3427 __u16 fid
, __u32 pid_of_opener
, int SetAllocation
)
3429 struct smb_com_transaction2_sfi_req
*pSMB
= NULL
;
3430 struct smb_com_transaction2_sfi_rsp
*pSMBr
= NULL
;
3432 struct file_end_of_file_info
*parm_data
;
3434 int bytes_returned
= 0;
3435 __u16 params
, param_offset
, offset
, byte_count
, count
;
3437 cFYI(1, ("SetFileSize (via SetFileInfo) %lld",
3439 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
3444 pSMB
->hdr
.Pid
= cpu_to_le16((__u16
)pid_of_opener
);
3445 pSMB
->hdr
.PidHigh
= cpu_to_le16((__u16
)(pid_of_opener
>> 16));
3448 pSMB
->MaxSetupCount
= 0;
3452 pSMB
->Reserved2
= 0;
3453 param_offset
= offsetof(struct smb_com_transaction2_sfi_req
, Fid
) - 4;
3454 offset
= param_offset
+ params
;
3456 data_offset
= (char *) (&pSMB
->hdr
.Protocol
) + offset
;
3458 count
= sizeof(struct file_end_of_file_info
);
3459 pSMB
->MaxParameterCount
= cpu_to_le16(2);
3460 pSMB
->MaxDataCount
= cpu_to_le16(1000); /* BB find max SMB PDU from sess */
3461 pSMB
->SetupCount
= 1;
3462 pSMB
->Reserved3
= 0;
3463 pSMB
->SubCommand
= cpu_to_le16(TRANS2_SET_FILE_INFORMATION
);
3464 byte_count
= 3 /* pad */ + params
+ count
;
3465 pSMB
->DataCount
= cpu_to_le16(count
);
3466 pSMB
->ParameterCount
= cpu_to_le16(params
);
3467 pSMB
->TotalDataCount
= pSMB
->DataCount
;
3468 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
3469 pSMB
->ParameterOffset
= cpu_to_le16(param_offset
);
3471 (struct file_end_of_file_info
*) (((char *) &pSMB
->hdr
.Protocol
) +
3473 pSMB
->DataOffset
= cpu_to_le16(offset
);
3474 parm_data
->FileSize
= cpu_to_le64(size
);
3477 if (tcon
->ses
->capabilities
& CAP_INFOLEVEL_PASSTHRU
)
3478 pSMB
->InformationLevel
=
3479 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2
);
3481 pSMB
->InformationLevel
=
3482 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO
);
3483 } else /* Set File Size */ {
3484 if (tcon
->ses
->capabilities
& CAP_INFOLEVEL_PASSTHRU
)
3485 pSMB
->InformationLevel
=
3486 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO2
);
3488 pSMB
->InformationLevel
=
3489 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO
);
3491 pSMB
->Reserved4
= 0;
3492 pSMB
->hdr
.smb_buf_length
+= byte_count
;
3493 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
3494 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
3495 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
3498 ("Send error in SetFileInfo (SetFileSize) = %d",
3503 cifs_buf_release(pSMB
);
3505 /* Note: On -EAGAIN error only caller can retry on handle based calls
3506 since file handle passed in no longer valid */
3511 /* Some legacy servers such as NT4 require that the file times be set on
3512 an open handle, rather than by pathname - this is awkward due to
3513 potential access conflicts on the open, but it is unavoidable for these
3514 old servers since the only other choice is to go from 100 nanosecond DCE
3515 time and resort to the original setpathinfo level which takes the ancient
3516 DOS time format with 2 second granularity */
3518 CIFSSMBSetFileTimes(const int xid
, struct cifsTconInfo
*tcon
, const FILE_BASIC_INFO
* data
,
3521 struct smb_com_transaction2_sfi_req
*pSMB
= NULL
;
3522 struct smb_com_transaction2_sfi_rsp
*pSMBr
= NULL
;
3525 int bytes_returned
= 0;
3526 __u16 params
, param_offset
, offset
, byte_count
, count
;
3528 cFYI(1, ("Set Times (via SetFileInfo)"));
3529 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
3534 /* At this point there is no need to override the current pid
3535 with the pid of the opener, but that could change if we someday
3536 use an existing handle (rather than opening one on the fly) */
3537 /* pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
3538 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));*/
3541 pSMB
->MaxSetupCount
= 0;
3545 pSMB
->Reserved2
= 0;
3546 param_offset
= offsetof(struct smb_com_transaction2_sfi_req
, Fid
) - 4;
3547 offset
= param_offset
+ params
;
3549 data_offset
= (char *) (&pSMB
->hdr
.Protocol
) + offset
;
3551 count
= sizeof (FILE_BASIC_INFO
);
3552 pSMB
->MaxParameterCount
= cpu_to_le16(2);
3553 pSMB
->MaxDataCount
= cpu_to_le16(1000); /* BB find max SMB PDU from sess */
3554 pSMB
->SetupCount
= 1;
3555 pSMB
->Reserved3
= 0;
3556 pSMB
->SubCommand
= cpu_to_le16(TRANS2_SET_FILE_INFORMATION
);
3557 byte_count
= 3 /* pad */ + params
+ count
;
3558 pSMB
->DataCount
= cpu_to_le16(count
);
3559 pSMB
->ParameterCount
= cpu_to_le16(params
);
3560 pSMB
->TotalDataCount
= pSMB
->DataCount
;
3561 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
3562 pSMB
->ParameterOffset
= cpu_to_le16(param_offset
);
3563 pSMB
->DataOffset
= cpu_to_le16(offset
);
3565 if (tcon
->ses
->capabilities
& CAP_INFOLEVEL_PASSTHRU
)
3566 pSMB
->InformationLevel
= cpu_to_le16(SMB_SET_FILE_BASIC_INFO2
);
3568 pSMB
->InformationLevel
= cpu_to_le16(SMB_SET_FILE_BASIC_INFO
);
3569 pSMB
->Reserved4
= 0;
3570 pSMB
->hdr
.smb_buf_length
+= byte_count
;
3571 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
3572 memcpy(data_offset
,data
,sizeof(FILE_BASIC_INFO
));
3573 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
3574 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
3576 cFYI(1,("Send error in Set Time (SetFileInfo) = %d",rc
));
3579 cifs_buf_release(pSMB
);
3581 /* Note: On -EAGAIN error only caller can retry on handle based calls
3582 since file handle passed in no longer valid */
3589 CIFSSMBSetTimes(const int xid
, struct cifsTconInfo
*tcon
, const char *fileName
,
3590 const FILE_BASIC_INFO
* data
,
3591 const struct nls_table
*nls_codepage
, int remap
)
3593 TRANSACTION2_SPI_REQ
*pSMB
= NULL
;
3594 TRANSACTION2_SPI_RSP
*pSMBr
= NULL
;
3597 int bytes_returned
= 0;
3599 __u16 params
, param_offset
, offset
, byte_count
, count
;
3601 cFYI(1, ("In SetTimes"));
3604 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
3609 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
3611 cifsConvertToUCS((__u16
*) pSMB
->FileName
, fileName
,
3612 PATH_MAX
, nls_codepage
, remap
);
3613 name_len
++; /* trailing null */
3615 } else { /* BB improve the check for buffer overruns BB */
3616 name_len
= strnlen(fileName
, PATH_MAX
);
3617 name_len
++; /* trailing null */
3618 strncpy(pSMB
->FileName
, fileName
, name_len
);
3621 params
= 6 + name_len
;
3622 count
= sizeof (FILE_BASIC_INFO
);
3623 pSMB
->MaxParameterCount
= cpu_to_le16(2);
3624 pSMB
->MaxDataCount
= cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
3625 pSMB
->MaxSetupCount
= 0;
3629 pSMB
->Reserved2
= 0;
3630 param_offset
= offsetof(struct smb_com_transaction2_spi_req
,
3631 InformationLevel
) - 4;
3632 offset
= param_offset
+ params
;
3633 data_offset
= (char *) (&pSMB
->hdr
.Protocol
) + offset
;
3634 pSMB
->ParameterOffset
= cpu_to_le16(param_offset
);
3635 pSMB
->DataOffset
= cpu_to_le16(offset
);
3636 pSMB
->SetupCount
= 1;
3637 pSMB
->Reserved3
= 0;
3638 pSMB
->SubCommand
= cpu_to_le16(TRANS2_SET_PATH_INFORMATION
);
3639 byte_count
= 3 /* pad */ + params
+ count
;
3641 pSMB
->DataCount
= cpu_to_le16(count
);
3642 pSMB
->ParameterCount
= cpu_to_le16(params
);
3643 pSMB
->TotalDataCount
= pSMB
->DataCount
;
3644 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
3645 if (tcon
->ses
->capabilities
& CAP_INFOLEVEL_PASSTHRU
)
3646 pSMB
->InformationLevel
= cpu_to_le16(SMB_SET_FILE_BASIC_INFO2
);
3648 pSMB
->InformationLevel
= cpu_to_le16(SMB_SET_FILE_BASIC_INFO
);
3649 pSMB
->Reserved4
= 0;
3650 pSMB
->hdr
.smb_buf_length
+= byte_count
;
3651 memcpy(data_offset
, data
, sizeof (FILE_BASIC_INFO
));
3652 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
3653 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
3654 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
3656 cFYI(1, ("SetPathInfo (times) returned %d", rc
));
3659 cifs_buf_release(pSMB
);
3667 /* Can not be used to set time stamps yet (due to old DOS time format) */
3668 /* Can be used to set attributes */
3669 #if 0 /* Possibly not needed - since it turns out that strangely NT4 has a bug
3670 handling it anyway and NT4 was what we thought it would be needed for
3671 Do not delete it until we prove whether needed for Win9x though */
3673 CIFSSMBSetAttrLegacy(int xid
, struct cifsTconInfo
*tcon
, char *fileName
,
3674 __u16 dos_attrs
, const struct nls_table
*nls_codepage
)
3676 SETATTR_REQ
*pSMB
= NULL
;
3677 SETATTR_RSP
*pSMBr
= NULL
;
3682 cFYI(1, ("In SetAttrLegacy"));
3685 rc
= smb_init(SMB_COM_SETATTR
, 8, tcon
, (void **) &pSMB
,
3690 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
3692 ConvertToUCS((wchar_t *) pSMB
->fileName
, fileName
,
3693 PATH_MAX
, nls_codepage
);
3694 name_len
++; /* trailing null */
3696 } else { /* BB improve the check for buffer overruns BB */
3697 name_len
= strnlen(fileName
, PATH_MAX
);
3698 name_len
++; /* trailing null */
3699 strncpy(pSMB
->fileName
, fileName
, name_len
);
3701 pSMB
->attr
= cpu_to_le16(dos_attrs
);
3702 pSMB
->BufferFormat
= 0x04;
3703 pSMB
->hdr
.smb_buf_length
+= name_len
+ 1;
3704 pSMB
->ByteCount
= cpu_to_le16(name_len
+ 1);
3705 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
3706 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
3708 cFYI(1, ("Error in LegacySetAttr = %d", rc
));
3711 cifs_buf_release(pSMB
);
3714 goto SetAttrLgcyRetry
;
3718 #endif /* temporarily unneeded SetAttr legacy function */
3721 CIFSSMBUnixSetPerms(const int xid
, struct cifsTconInfo
*tcon
,
3722 char *fileName
, __u64 mode
, __u64 uid
, __u64 gid
,
3723 dev_t device
, const struct nls_table
*nls_codepage
,
3726 TRANSACTION2_SPI_REQ
*pSMB
= NULL
;
3727 TRANSACTION2_SPI_RSP
*pSMBr
= NULL
;
3730 int bytes_returned
= 0;
3731 FILE_UNIX_BASIC_INFO
*data_offset
;
3732 __u16 params
, param_offset
, offset
, count
, byte_count
;
3734 cFYI(1, ("In SetUID/GID/Mode"));
3736 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
3741 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
3743 cifsConvertToUCS((__u16
*) pSMB
->FileName
, fileName
,
3744 PATH_MAX
, nls_codepage
, remap
);
3745 name_len
++; /* trailing null */
3747 } else { /* BB improve the check for buffer overruns BB */
3748 name_len
= strnlen(fileName
, PATH_MAX
);
3749 name_len
++; /* trailing null */
3750 strncpy(pSMB
->FileName
, fileName
, name_len
);
3753 params
= 6 + name_len
;
3754 count
= sizeof (FILE_UNIX_BASIC_INFO
);
3755 pSMB
->MaxParameterCount
= cpu_to_le16(2);
3756 pSMB
->MaxDataCount
= cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
3757 pSMB
->MaxSetupCount
= 0;
3761 pSMB
->Reserved2
= 0;
3762 param_offset
= offsetof(struct smb_com_transaction2_spi_req
,
3763 InformationLevel
) - 4;
3764 offset
= param_offset
+ params
;
3766 (FILE_UNIX_BASIC_INFO
*) ((char *) &pSMB
->hdr
.Protocol
+
3768 memset(data_offset
, 0, count
);
3769 pSMB
->DataOffset
= cpu_to_le16(offset
);
3770 pSMB
->ParameterOffset
= cpu_to_le16(param_offset
);
3771 pSMB
->SetupCount
= 1;
3772 pSMB
->Reserved3
= 0;
3773 pSMB
->SubCommand
= cpu_to_le16(TRANS2_SET_PATH_INFORMATION
);
3774 byte_count
= 3 /* pad */ + params
+ count
;
3775 pSMB
->ParameterCount
= cpu_to_le16(params
);
3776 pSMB
->DataCount
= cpu_to_le16(count
);
3777 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
3778 pSMB
->TotalDataCount
= pSMB
->DataCount
;
3779 pSMB
->InformationLevel
= cpu_to_le16(SMB_SET_FILE_UNIX_BASIC
);
3780 pSMB
->Reserved4
= 0;
3781 pSMB
->hdr
.smb_buf_length
+= byte_count
;
3782 data_offset
->Uid
= cpu_to_le64(uid
);
3783 data_offset
->Gid
= cpu_to_le64(gid
);
3784 /* better to leave device as zero when it is */
3785 data_offset
->DevMajor
= cpu_to_le64(MAJOR(device
));
3786 data_offset
->DevMinor
= cpu_to_le64(MINOR(device
));
3787 data_offset
->Permissions
= cpu_to_le64(mode
);
3790 data_offset
->Type
= cpu_to_le32(UNIX_FILE
);
3791 else if(S_ISDIR(mode
))
3792 data_offset
->Type
= cpu_to_le32(UNIX_DIR
);
3793 else if(S_ISLNK(mode
))
3794 data_offset
->Type
= cpu_to_le32(UNIX_SYMLINK
);
3795 else if(S_ISCHR(mode
))
3796 data_offset
->Type
= cpu_to_le32(UNIX_CHARDEV
);
3797 else if(S_ISBLK(mode
))
3798 data_offset
->Type
= cpu_to_le32(UNIX_BLOCKDEV
);
3799 else if(S_ISFIFO(mode
))
3800 data_offset
->Type
= cpu_to_le32(UNIX_FIFO
);
3801 else if(S_ISSOCK(mode
))
3802 data_offset
->Type
= cpu_to_le32(UNIX_SOCKET
);
3805 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
3806 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
3807 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
3809 cFYI(1, ("SetPathInfo (perms) returned %d", rc
));
3813 cifs_buf_release(pSMB
);
3819 int CIFSSMBNotify(const int xid
, struct cifsTconInfo
*tcon
,
3820 const int notify_subdirs
, const __u16 netfid
,
3821 __u32 filter
, const struct nls_table
*nls_codepage
)
3824 struct smb_com_transaction_change_notify_req
* pSMB
= NULL
;
3825 struct smb_com_transaction_change_notify_rsp
* pSMBr
= NULL
;
3828 cFYI(1, ("In CIFSSMBNotify for file handle %d",(int)netfid
));
3829 rc
= smb_init(SMB_COM_NT_TRANSACT
, 23, tcon
, (void **) &pSMB
,
3834 pSMB
->TotalParameterCount
= 0 ;
3835 pSMB
->TotalDataCount
= 0;
3836 pSMB
->MaxParameterCount
= cpu_to_le32(2);
3837 /* BB find exact data count max from sess structure BB */
3838 pSMB
->MaxDataCount
= 0; /* same in little endian or be */
3839 pSMB
->MaxSetupCount
= 4;
3841 pSMB
->ParameterOffset
= 0;
3842 pSMB
->DataCount
= 0;
3843 pSMB
->DataOffset
= 0;
3844 pSMB
->SetupCount
= 4; /* single byte does not need le conversion */
3845 pSMB
->SubCommand
= cpu_to_le16(NT_TRANSACT_NOTIFY_CHANGE
);
3846 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
3848 pSMB
->WatchTree
= 1; /* one byte - no le conversion needed */
3849 pSMB
->Reserved2
= 0;
3850 pSMB
->CompletionFilter
= cpu_to_le32(filter
);
3851 pSMB
->Fid
= netfid
; /* file handle always le */
3852 pSMB
->ByteCount
= 0;
3854 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
3855 (struct smb_hdr
*) pSMBr
, &bytes_returned
, -1);
3857 cFYI(1, ("Error in Notify = %d", rc
));
3859 cifs_buf_release(pSMB
);
3862 #ifdef CONFIG_CIFS_XATTR
3864 CIFSSMBQAllEAs(const int xid
, struct cifsTconInfo
*tcon
,
3865 const unsigned char *searchName
,
3866 char * EAData
, size_t buf_size
,
3867 const struct nls_table
*nls_codepage
, int remap
)
3869 /* BB assumes one setup word */
3870 TRANSACTION2_QPI_REQ
*pSMB
= NULL
;
3871 TRANSACTION2_QPI_RSP
*pSMBr
= NULL
;
3875 struct fea
* temp_fea
;
3877 __u16 params
, byte_count
;
3879 cFYI(1, ("In Query All EAs path %s", searchName
));
3881 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
3886 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
3888 cifsConvertToUCS((wchar_t *) pSMB
->FileName
, searchName
,
3889 PATH_MAX
, nls_codepage
, remap
);
3890 name_len
++; /* trailing null */
3892 } else { /* BB improve the check for buffer overruns BB */
3893 name_len
= strnlen(searchName
, PATH_MAX
);
3894 name_len
++; /* trailing null */
3895 strncpy(pSMB
->FileName
, searchName
, name_len
);
3898 params
= 2 /* level */ + 4 /* reserved */ + name_len
/* includes NUL */ ;
3899 pSMB
->TotalDataCount
= 0;
3900 pSMB
->MaxParameterCount
= cpu_to_le16(2);
3901 pSMB
->MaxDataCount
= cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
3902 pSMB
->MaxSetupCount
= 0;
3906 pSMB
->Reserved2
= 0;
3907 pSMB
->ParameterOffset
= cpu_to_le16(offsetof(
3908 struct smb_com_transaction2_qpi_req
,InformationLevel
) - 4);
3909 pSMB
->DataCount
= 0;
3910 pSMB
->DataOffset
= 0;
3911 pSMB
->SetupCount
= 1;
3912 pSMB
->Reserved3
= 0;
3913 pSMB
->SubCommand
= cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION
);
3914 byte_count
= params
+ 1 /* pad */ ;
3915 pSMB
->TotalParameterCount
= cpu_to_le16(params
);
3916 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
3917 pSMB
->InformationLevel
= cpu_to_le16(SMB_INFO_QUERY_ALL_EAS
);
3918 pSMB
->Reserved4
= 0;
3919 pSMB
->hdr
.smb_buf_length
+= byte_count
;
3920 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
3922 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
3923 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
3925 cFYI(1, ("Send error in QueryAllEAs = %d", rc
));
3926 } else { /* decode response */
3927 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
3929 /* BB also check enough total bytes returned */
3930 /* BB we need to improve the validity checking
3931 of these trans2 responses */
3932 if (rc
|| (pSMBr
->ByteCount
< 4))
3933 rc
= -EIO
; /* bad smb */
3934 /* else if (pFindData){
3935 memcpy((char *) pFindData,
3936 (char *) &pSMBr->hdr.Protocol +
3939 /* check that length of list is not more than bcc */
3940 /* check that each entry does not go beyond length
3942 /* check that each element of each entry does not
3943 go beyond end of list */
3944 __u16 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
3945 struct fealist
* ea_response_data
;
3947 /* validate_trans2_offsets() */
3948 /* BB to check if(start of smb + data_offset > &bcc+ bcc)*/
3949 ea_response_data
= (struct fealist
*)
3950 (((char *) &pSMBr
->hdr
.Protocol
) +
3952 name_len
= le32_to_cpu(ea_response_data
->list_len
);
3953 cFYI(1,("ea length %d", name_len
));
3955 /* returned EA size zeroed at top of function */
3956 cFYI(1,("empty EA list returned from server"));
3958 /* account for ea list len */
3960 temp_fea
= ea_response_data
->list
;
3961 temp_ptr
= (char *)temp_fea
;
3962 while(name_len
> 0) {
3966 rc
+= temp_fea
->name_len
;
3967 /* account for prefix user. and trailing null */
3969 if(rc
<(int)buf_size
) {
3970 memcpy(EAData
,"user.",5);
3972 memcpy(EAData
,temp_ptr
,temp_fea
->name_len
);
3973 EAData
+=temp_fea
->name_len
;
3974 /* null terminate name */
3976 EAData
= EAData
+ 1;
3977 } else if(buf_size
== 0) {
3978 /* skip copy - calc size only */
3980 /* stop before overrun buffer */
3984 name_len
-= temp_fea
->name_len
;
3985 temp_ptr
+= temp_fea
->name_len
;
3986 /* account for trailing null */
3989 value_len
= le16_to_cpu(temp_fea
->value_len
);
3990 name_len
-= value_len
;
3991 temp_ptr
+= value_len
;
3992 /* BB check that temp_ptr is still within smb BB*/
3993 /* no trailing null to account for in value len */
3994 /* go on to next EA */
3995 temp_fea
= (struct fea
*)temp_ptr
;
4001 cifs_buf_release(pSMB
);
4008 ssize_t
CIFSSMBQueryEA(const int xid
,struct cifsTconInfo
* tcon
,
4009 const unsigned char * searchName
,const unsigned char * ea_name
,
4010 unsigned char * ea_value
, size_t buf_size
,
4011 const struct nls_table
*nls_codepage
, int remap
)
4013 TRANSACTION2_QPI_REQ
*pSMB
= NULL
;
4014 TRANSACTION2_QPI_RSP
*pSMBr
= NULL
;
4018 struct fea
* temp_fea
;
4020 __u16 params
, byte_count
;
4022 cFYI(1, ("In Query EA path %s", searchName
));
4024 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
4029 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
4031 cifsConvertToUCS((__u16
*) pSMB
->FileName
, searchName
,
4032 PATH_MAX
, nls_codepage
, remap
);
4033 name_len
++; /* trailing null */
4035 } else { /* BB improve the check for buffer overruns BB */
4036 name_len
= strnlen(searchName
, PATH_MAX
);
4037 name_len
++; /* trailing null */
4038 strncpy(pSMB
->FileName
, searchName
, name_len
);
4041 params
= 2 /* level */ + 4 /* reserved */ + name_len
/* includes NUL */ ;
4042 pSMB
->TotalDataCount
= 0;
4043 pSMB
->MaxParameterCount
= cpu_to_le16(2);
4044 pSMB
->MaxDataCount
= cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
4045 pSMB
->MaxSetupCount
= 0;
4049 pSMB
->Reserved2
= 0;
4050 pSMB
->ParameterOffset
= cpu_to_le16(offsetof(
4051 struct smb_com_transaction2_qpi_req
,InformationLevel
) - 4);
4052 pSMB
->DataCount
= 0;
4053 pSMB
->DataOffset
= 0;
4054 pSMB
->SetupCount
= 1;
4055 pSMB
->Reserved3
= 0;
4056 pSMB
->SubCommand
= cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION
);
4057 byte_count
= params
+ 1 /* pad */ ;
4058 pSMB
->TotalParameterCount
= cpu_to_le16(params
);
4059 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
4060 pSMB
->InformationLevel
= cpu_to_le16(SMB_INFO_QUERY_ALL_EAS
);
4061 pSMB
->Reserved4
= 0;
4062 pSMB
->hdr
.smb_buf_length
+= byte_count
;
4063 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
4065 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
4066 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
4068 cFYI(1, ("Send error in Query EA = %d", rc
));
4069 } else { /* decode response */
4070 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
4072 /* BB also check enough total bytes returned */
4073 /* BB we need to improve the validity checking
4074 of these trans2 responses */
4075 if (rc
|| (pSMBr
->ByteCount
< 4))
4076 rc
= -EIO
; /* bad smb */
4077 /* else if (pFindData){
4078 memcpy((char *) pFindData,
4079 (char *) &pSMBr->hdr.Protocol +
4082 /* check that length of list is not more than bcc */
4083 /* check that each entry does not go beyond length
4085 /* check that each element of each entry does not
4086 go beyond end of list */
4087 __u16 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
4088 struct fealist
* ea_response_data
;
4090 /* validate_trans2_offsets() */
4091 /* BB to check if(start of smb + data_offset > &bcc+ bcc)*/
4092 ea_response_data
= (struct fealist
*)
4093 (((char *) &pSMBr
->hdr
.Protocol
) +
4095 name_len
= le32_to_cpu(ea_response_data
->list_len
);
4096 cFYI(1,("ea length %d", name_len
));
4098 /* returned EA size zeroed at top of function */
4099 cFYI(1,("empty EA list returned from server"));
4101 /* account for ea list len */
4103 temp_fea
= ea_response_data
->list
;
4104 temp_ptr
= (char *)temp_fea
;
4105 /* loop through checking if we have a matching
4106 name and then return the associated value */
4107 while(name_len
> 0) {
4111 value_len
= le16_to_cpu(temp_fea
->value_len
);
4112 /* BB validate that value_len falls within SMB,
4113 even though maximum for name_len is 255 */
4114 if(memcmp(temp_fea
->name
,ea_name
,
4115 temp_fea
->name_len
) == 0) {
4118 /* account for prefix user. and trailing null */
4119 if(rc
<=(int)buf_size
) {
4121 temp_fea
->name
+temp_fea
->name_len
+1,
4123 /* ea values, unlike ea names,
4124 are not null terminated */
4125 } else if(buf_size
== 0) {
4126 /* skip copy - calc size only */
4128 /* stop before overrun buffer */
4133 name_len
-= temp_fea
->name_len
;
4134 temp_ptr
+= temp_fea
->name_len
;
4135 /* account for trailing null */
4138 name_len
-= value_len
;
4139 temp_ptr
+= value_len
;
4140 /* no trailing null to account for in value len */
4141 /* go on to next EA */
4142 temp_fea
= (struct fea
*)temp_ptr
;
4148 cifs_buf_release(pSMB
);
4156 CIFSSMBSetEA(const int xid
, struct cifsTconInfo
*tcon
, const char *fileName
,
4157 const char * ea_name
, const void * ea_value
,
4158 const __u16 ea_value_len
, const struct nls_table
*nls_codepage
,
4161 struct smb_com_transaction2_spi_req
*pSMB
= NULL
;
4162 struct smb_com_transaction2_spi_rsp
*pSMBr
= NULL
;
4163 struct fealist
*parm_data
;
4166 int bytes_returned
= 0;
4167 __u16 params
, param_offset
, byte_count
, offset
, count
;
4169 cFYI(1, ("In SetEA"));
4171 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
4176 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
4178 cifsConvertToUCS((__u16
*) pSMB
->FileName
, fileName
,
4179 PATH_MAX
, nls_codepage
, remap
);
4180 name_len
++; /* trailing null */
4182 } else { /* BB improve the check for buffer overruns BB */
4183 name_len
= strnlen(fileName
, PATH_MAX
);
4184 name_len
++; /* trailing null */
4185 strncpy(pSMB
->FileName
, fileName
, name_len
);
4188 params
= 6 + name_len
;
4190 /* done calculating parms using name_len of file name,
4191 now use name_len to calculate length of ea name
4192 we are going to create in the inode xattrs */
4196 name_len
= strnlen(ea_name
,255);
4198 count
= sizeof(*parm_data
) + ea_value_len
+ name_len
+ 1;
4199 pSMB
->MaxParameterCount
= cpu_to_le16(2);
4200 pSMB
->MaxDataCount
= cpu_to_le16(1000); /* BB find max SMB size from sess */
4201 pSMB
->MaxSetupCount
= 0;
4205 pSMB
->Reserved2
= 0;
4206 param_offset
= offsetof(struct smb_com_transaction2_spi_req
,
4207 InformationLevel
) - 4;
4208 offset
= param_offset
+ params
;
4209 pSMB
->InformationLevel
=
4210 cpu_to_le16(SMB_SET_FILE_EA
);
4213 (struct fealist
*) (((char *) &pSMB
->hdr
.Protocol
) +
4215 pSMB
->ParameterOffset
= cpu_to_le16(param_offset
);
4216 pSMB
->DataOffset
= cpu_to_le16(offset
);
4217 pSMB
->SetupCount
= 1;
4218 pSMB
->Reserved3
= 0;
4219 pSMB
->SubCommand
= cpu_to_le16(TRANS2_SET_PATH_INFORMATION
);
4220 byte_count
= 3 /* pad */ + params
+ count
;
4221 pSMB
->DataCount
= cpu_to_le16(count
);
4222 parm_data
->list_len
= cpu_to_le32(count
);
4223 parm_data
->list
[0].EA_flags
= 0;
4224 /* we checked above that name len is less than 255 */
4225 parm_data
->list
[0].name_len
= (__u8
)name_len
;;
4226 /* EA names are always ASCII */
4228 strncpy(parm_data
->list
[0].name
,ea_name
,name_len
);
4229 parm_data
->list
[0].name
[name_len
] = 0;
4230 parm_data
->list
[0].value_len
= cpu_to_le16(ea_value_len
);
4231 /* caller ensures that ea_value_len is less than 64K but
4232 we need to ensure that it fits within the smb */
4234 /*BB add length check that it would fit in negotiated SMB buffer size BB */
4235 /* if(ea_value_len > buffer_size - 512 (enough for header)) */
4237 memcpy(parm_data
->list
[0].name
+name_len
+1,ea_value
,ea_value_len
);
4239 pSMB
->TotalDataCount
= pSMB
->DataCount
;
4240 pSMB
->ParameterCount
= cpu_to_le16(params
);
4241 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
4242 pSMB
->Reserved4
= 0;
4243 pSMB
->hdr
.smb_buf_length
+= byte_count
;
4244 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
4245 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
4246 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
4248 cFYI(1, ("SetPathInfo (EA) returned %d", rc
));
4251 cifs_buf_release(pSMB
);