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"
42 #ifdef CONFIG_CIFS_POSIX
47 {CIFS_PROT
, "\2NT LM 0.12"},
48 {CIFS_PROT
, "\2POSIX 2"},
56 {CIFS_PROT
, "\2NT LM 0.12"},
62 /* Mark as invalid, all open files on tree connections since they
63 were closed when session to server was lost */
64 static void mark_open_files_invalid(struct cifsTconInfo
* pTcon
)
66 struct cifsFileInfo
*open_file
= NULL
;
67 struct list_head
* tmp
;
68 struct list_head
* tmp1
;
70 /* list all files open on tree connection and mark them invalid */
71 write_lock(&GlobalSMBSeslock
);
72 list_for_each_safe(tmp
, tmp1
, &pTcon
->openFileList
) {
73 open_file
= list_entry(tmp
,struct cifsFileInfo
, tlist
);
75 open_file
->invalidHandle
= TRUE
;
78 write_unlock(&GlobalSMBSeslock
);
79 /* BB Add call to invalidate_inodes(sb) for all superblocks mounted
83 /* If the return code is zero, this function must fill in request_buf pointer */
85 small_smb_init(int smb_command
, int wct
, struct cifsTconInfo
*tcon
,
86 void **request_buf
/* returned */)
90 /* SMBs NegProt, SessSetup, uLogoff do not have tcon yet so
91 check for tcp and smb session status done differently
92 for those three - in the calling routine */
94 if(tcon
->tidStatus
== CifsExiting
) {
95 /* only tree disconnect, open, and write,
96 (and ulogoff which does not have tcon)
97 are allowed as we start force umount */
98 if((smb_command
!= SMB_COM_WRITE_ANDX
) &&
99 (smb_command
!= SMB_COM_OPEN_ANDX
) &&
100 (smb_command
!= SMB_COM_TREE_DISCONNECT
)) {
101 cFYI(1,("can not send cmd %d while umounting",
106 if((tcon
->ses
) && (tcon
->ses
->status
!= CifsExiting
) &&
107 (tcon
->ses
->server
)){
108 struct nls_table
*nls_codepage
;
109 /* Give Demultiplex thread up to 10 seconds to
110 reconnect, should be greater than cifs socket
111 timeout which is 7 seconds */
112 while(tcon
->ses
->server
->tcpStatus
== CifsNeedReconnect
) {
113 wait_event_interruptible_timeout(tcon
->ses
->server
->response_q
,
114 (tcon
->ses
->server
->tcpStatus
== CifsGood
), 10 * HZ
);
115 if(tcon
->ses
->server
->tcpStatus
== CifsNeedReconnect
) {
116 /* on "soft" mounts we wait once */
117 if((tcon
->retry
== FALSE
) ||
118 (tcon
->ses
->status
== CifsExiting
)) {
119 cFYI(1,("gave up waiting on reconnect in smb_init"));
121 } /* else "hard" mount - keep retrying
122 until process is killed or server
123 comes back on-line */
124 } else /* TCP session is reestablished now */
129 nls_codepage
= load_nls_default();
130 /* need to prevent multiple threads trying to
131 simultaneously reconnect the same SMB session */
132 down(&tcon
->ses
->sesSem
);
133 if(tcon
->ses
->status
== CifsNeedReconnect
)
134 rc
= cifs_setup_session(0, tcon
->ses
,
136 if(!rc
&& (tcon
->tidStatus
== CifsNeedReconnect
)) {
137 mark_open_files_invalid(tcon
);
138 rc
= CIFSTCon(0, tcon
->ses
, tcon
->treeName
, tcon
140 up(&tcon
->ses
->sesSem
);
141 /* BB FIXME add code to check if wsize needs
142 update due to negotiated smb buffer size
145 atomic_inc(&tconInfoReconnectCount
);
147 cFYI(1, ("reconnect tcon rc = %d", rc
));
148 /* Removed call to reopen open files here -
149 it is safer (and faster) to reopen files
150 one at a time as needed in read and write */
152 /* Check if handle based operation so we
153 know whether we can continue or not without
154 returning to caller to reset file handle */
155 switch(smb_command
) {
156 case SMB_COM_READ_ANDX
:
157 case SMB_COM_WRITE_ANDX
:
159 case SMB_COM_FIND_CLOSE2
:
160 case SMB_COM_LOCKING_ANDX
: {
161 unload_nls(nls_codepage
);
166 up(&tcon
->ses
->sesSem
);
168 unload_nls(nls_codepage
);
177 *request_buf
= cifs_small_buf_get();
178 if (*request_buf
== NULL
) {
179 /* BB should we add a retry in here if not a writepage? */
183 header_assemble((struct smb_hdr
*) *request_buf
, smb_command
, tcon
,wct
);
186 cifs_stats_inc(&tcon
->num_smbs_sent
);
191 /* If the return code is zero, this function must fill in request_buf pointer */
193 smb_init(int smb_command
, int wct
, struct cifsTconInfo
*tcon
,
194 void **request_buf
/* returned */ ,
195 void **response_buf
/* returned */ )
199 /* SMBs NegProt, SessSetup, uLogoff do not have tcon yet so
200 check for tcp and smb session status done differently
201 for those three - in the calling routine */
203 if(tcon
->tidStatus
== CifsExiting
) {
204 /* only tree disconnect, open, and write,
205 (and ulogoff which does not have tcon)
206 are allowed as we start force umount */
207 if((smb_command
!= SMB_COM_WRITE_ANDX
) &&
208 (smb_command
!= SMB_COM_OPEN_ANDX
) &&
209 (smb_command
!= SMB_COM_TREE_DISCONNECT
)) {
210 cFYI(1,("can not send cmd %d while umounting",
216 if((tcon
->ses
) && (tcon
->ses
->status
!= CifsExiting
) &&
217 (tcon
->ses
->server
)){
218 struct nls_table
*nls_codepage
;
219 /* Give Demultiplex thread up to 10 seconds to
220 reconnect, should be greater than cifs socket
221 timeout which is 7 seconds */
222 while(tcon
->ses
->server
->tcpStatus
== CifsNeedReconnect
) {
223 wait_event_interruptible_timeout(tcon
->ses
->server
->response_q
,
224 (tcon
->ses
->server
->tcpStatus
== CifsGood
), 10 * HZ
);
225 if(tcon
->ses
->server
->tcpStatus
==
227 /* on "soft" mounts we wait once */
228 if((tcon
->retry
== FALSE
) ||
229 (tcon
->ses
->status
== CifsExiting
)) {
230 cFYI(1,("gave up waiting on reconnect in smb_init"));
232 } /* else "hard" mount - keep retrying
233 until process is killed or server
235 } else /* TCP session is reestablished now */
240 nls_codepage
= load_nls_default();
241 /* need to prevent multiple threads trying to
242 simultaneously reconnect the same SMB session */
243 down(&tcon
->ses
->sesSem
);
244 if(tcon
->ses
->status
== CifsNeedReconnect
)
245 rc
= cifs_setup_session(0, tcon
->ses
,
247 if(!rc
&& (tcon
->tidStatus
== CifsNeedReconnect
)) {
248 mark_open_files_invalid(tcon
);
249 rc
= CIFSTCon(0, tcon
->ses
, tcon
->treeName
,
251 up(&tcon
->ses
->sesSem
);
252 /* BB FIXME add code to check if wsize needs
253 update due to negotiated smb buffer size
256 atomic_inc(&tconInfoReconnectCount
);
258 cFYI(1, ("reconnect tcon rc = %d", rc
));
259 /* Removed call to reopen open files here -
260 it is safer (and faster) to reopen files
261 one at a time as needed in read and write */
263 /* Check if handle based operation so we
264 know whether we can continue or not without
265 returning to caller to reset file handle */
266 switch(smb_command
) {
267 case SMB_COM_READ_ANDX
:
268 case SMB_COM_WRITE_ANDX
:
270 case SMB_COM_FIND_CLOSE2
:
271 case SMB_COM_LOCKING_ANDX
: {
272 unload_nls(nls_codepage
);
277 up(&tcon
->ses
->sesSem
);
279 unload_nls(nls_codepage
);
288 *request_buf
= cifs_buf_get();
289 if (*request_buf
== NULL
) {
290 /* BB should we add a retry in here if not a writepage? */
293 /* Although the original thought was we needed the response buf for */
294 /* potential retries of smb operations it turns out we can determine */
295 /* from the mid flags when the request buffer can be resent without */
296 /* having to use a second distinct buffer for the response */
297 *response_buf
= *request_buf
;
299 header_assemble((struct smb_hdr
*) *request_buf
, smb_command
, tcon
,
303 cifs_stats_inc(&tcon
->num_smbs_sent
);
308 static int validate_t2(struct smb_t2_rsp
* pSMB
)
314 /* check for plausible wct, bcc and t2 data and parm sizes */
315 /* check for parm and data offset going beyond end of smb */
316 if(pSMB
->hdr
.WordCount
>= 10) {
317 if((le16_to_cpu(pSMB
->t2_rsp
.ParameterOffset
) <= 1024) &&
318 (le16_to_cpu(pSMB
->t2_rsp
.DataOffset
) <= 1024)) {
319 /* check that bcc is at least as big as parms + data */
320 /* check that bcc is less than negotiated smb buffer */
321 total_size
= le16_to_cpu(pSMB
->t2_rsp
.ParameterCount
);
322 if(total_size
< 512) {
323 total_size
+=le16_to_cpu(pSMB
->t2_rsp
.DataCount
);
324 /* BCC le converted in SendReceive */
325 pBCC
= (pSMB
->hdr
.WordCount
* 2) +
326 sizeof(struct smb_hdr
) +
328 if((total_size
<= (*(u16
*)pBCC
)) &&
330 CIFSMaxBufSize
+MAX_CIFS_HDR_SIZE
)) {
337 cifs_dump_mem("Invalid transact2 SMB: ",(char *)pSMB
,
338 sizeof(struct smb_t2_rsp
) + 16);
342 CIFSSMBNegotiate(unsigned int xid
, struct cifsSesInfo
*ses
)
345 NEGOTIATE_RSP
*pSMBr
;
348 struct TCP_Server_Info
* server
;
352 server
= ses
->server
;
357 rc
= smb_init(SMB_COM_NEGOTIATE
, 0, NULL
/* no tcon yet */ ,
358 (void **) &pSMB
, (void **) &pSMBr
);
361 pSMB
->hdr
.Mid
= GetNextMid(server
);
362 pSMB
->hdr
.Flags2
|= SMBFLG2_UNICODE
;
363 if (extended_security
)
364 pSMB
->hdr
.Flags2
|= SMBFLG2_EXT_SEC
;
366 count
= strlen(protocols
[0].name
) + 1;
367 strncpy(pSMB
->DialectsArray
, protocols
[0].name
, 30);
368 /* null guaranteed to be at end of source and target buffers anyway */
370 pSMB
->hdr
.smb_buf_length
+= count
;
371 pSMB
->ByteCount
= cpu_to_le16(count
);
373 rc
= SendReceive(xid
, ses
, (struct smb_hdr
*) pSMB
,
374 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
376 server
->secMode
= pSMBr
->SecurityMode
;
377 if((server
->secMode
& SECMODE_USER
) == 0)
378 cFYI(1,("share mode security"));
379 server
->secType
= NTLM
; /* BB override default for
380 NTLMv2 or kerberos v5 */
381 /* one byte - no need to convert this or EncryptionKeyLen
382 from little endian */
383 server
->maxReq
= le16_to_cpu(pSMBr
->MaxMpxCount
);
384 /* probably no need to store and check maxvcs */
386 min(le32_to_cpu(pSMBr
->MaxBufferSize
),
387 (__u32
) CIFSMaxBufSize
+ MAX_CIFS_HDR_SIZE
);
388 server
->maxRw
= le32_to_cpu(pSMBr
->MaxRawSize
);
389 cFYI(0, ("Max buf = %d", ses
->server
->maxBuf
));
390 GETU32(ses
->server
->sessid
) = le32_to_cpu(pSMBr
->SessionKey
);
391 server
->capabilities
= le32_to_cpu(pSMBr
->Capabilities
);
392 server
->timeZone
= le16_to_cpu(pSMBr
->ServerTimeZone
);
393 /* BB with UTC do we ever need to be using srvr timezone? */
394 if (pSMBr
->EncryptionKeyLength
== CIFS_CRYPTO_KEY_SIZE
) {
395 memcpy(server
->cryptKey
, pSMBr
->u
.EncryptionKey
,
396 CIFS_CRYPTO_KEY_SIZE
);
397 } else if ((pSMBr
->hdr
.Flags2
& SMBFLG2_EXT_SEC
)
398 && (pSMBr
->EncryptionKeyLength
== 0)) {
399 /* decode security blob */
403 /* BB might be helpful to save off the domain of server here */
405 if ((pSMBr
->hdr
.Flags2
& SMBFLG2_EXT_SEC
) &&
406 (server
->capabilities
& CAP_EXTENDED_SECURITY
)) {
407 count
= pSMBr
->ByteCount
;
410 else if (count
== 16) {
411 server
->secType
= RawNTLMSSP
;
412 if (server
->socketUseCount
.counter
> 1) {
414 (server
->server_GUID
,
415 pSMBr
->u
.extended_response
.
417 cFYI(1, ("server UID changed"));
425 memcpy(server
->server_GUID
,
426 pSMBr
->u
.extended_response
.
429 rc
= decode_negTokenInit(pSMBr
->u
.
435 /* BB Need to fill struct for sessetup here */
442 server
->capabilities
&= ~CAP_EXTENDED_SECURITY
;
443 if(sign_CIFS_PDUs
== FALSE
) {
444 if(server
->secMode
& SECMODE_SIGN_REQUIRED
)
446 ("Server requires /proc/fs/cifs/PacketSigningEnabled"));
447 server
->secMode
&= ~(SECMODE_SIGN_ENABLED
| SECMODE_SIGN_REQUIRED
);
448 } else if(sign_CIFS_PDUs
== 1) {
449 if((server
->secMode
& SECMODE_SIGN_REQUIRED
) == 0)
450 server
->secMode
&= ~(SECMODE_SIGN_ENABLED
| SECMODE_SIGN_REQUIRED
);
455 cifs_buf_release(pSMB
);
460 CIFSSMBTDis(const int xid
, struct cifsTconInfo
*tcon
)
462 struct smb_hdr
*smb_buffer
;
463 struct smb_hdr
*smb_buffer_response
; /* BB removeme BB */
467 cFYI(1, ("In tree disconnect"));
469 * If last user of the connection and
470 * connection alive - disconnect it
471 * If this is the last connection on the server session disconnect it
472 * (and inside session disconnect we should check if tcp socket needs
473 * to be freed and kernel thread woken up).
476 down(&tcon
->tconSem
);
480 atomic_dec(&tcon
->useCount
);
481 if (atomic_read(&tcon
->useCount
) > 0) {
486 /* No need to return error on this operation if tid invalidated and
487 closed on server already e.g. due to tcp session crashing */
488 if(tcon
->tidStatus
== CifsNeedReconnect
) {
493 if((tcon
->ses
== NULL
) || (tcon
->ses
->server
== NULL
)) {
497 rc
= small_smb_init(SMB_COM_TREE_DISCONNECT
, 0, tcon
,
498 (void **)&smb_buffer
);
503 smb_buffer_response
= smb_buffer
; /* BB removeme BB */
505 rc
= SendReceive(xid
, tcon
->ses
, smb_buffer
, smb_buffer_response
,
508 cFYI(1, ("Tree disconnect failed %d", rc
));
511 cifs_small_buf_release(smb_buffer
);
514 /* No need to return error on this operation if tid invalidated and
515 closed on server already e.g. due to tcp session crashing */
523 CIFSSMBLogoff(const int xid
, struct cifsSesInfo
*ses
)
525 struct smb_hdr
*smb_buffer_response
;
526 LOGOFF_ANDX_REQ
*pSMB
;
530 cFYI(1, ("In SMBLogoff for session disconnect"));
536 atomic_dec(&ses
->inUse
);
537 if (atomic_read(&ses
->inUse
) > 0) {
541 rc
= small_smb_init(SMB_COM_LOGOFF_ANDX
, 2, NULL
, (void **)&pSMB
);
547 smb_buffer_response
= (struct smb_hdr
*)pSMB
; /* BB removeme BB */
550 pSMB
->hdr
.Mid
= GetNextMid(ses
->server
);
552 if(ses
->server
->secMode
&
553 (SECMODE_SIGN_REQUIRED
| SECMODE_SIGN_ENABLED
))
554 pSMB
->hdr
.Flags2
|= SMBFLG2_SECURITY_SIGNATURE
;
557 pSMB
->hdr
.Uid
= ses
->Suid
;
559 pSMB
->AndXCommand
= 0xFF;
560 rc
= SendReceive(xid
, ses
, (struct smb_hdr
*) pSMB
,
561 smb_buffer_response
, &length
, 0);
563 atomic_dec(&ses
->server
->socketUseCount
);
564 if (atomic_read(&ses
->server
->socketUseCount
) == 0) {
565 spin_lock(&GlobalMid_Lock
);
566 ses
->server
->tcpStatus
= CifsExiting
;
567 spin_unlock(&GlobalMid_Lock
);
572 cifs_small_buf_release(pSMB
);
574 /* if session dead then we do not need to do ulogoff,
575 since server closed smb session, no sense reporting
583 CIFSSMBDelFile(const int xid
, struct cifsTconInfo
*tcon
, const char *fileName
,
584 const struct nls_table
*nls_codepage
, int remap
)
586 DELETE_FILE_REQ
*pSMB
= NULL
;
587 DELETE_FILE_RSP
*pSMBr
= NULL
;
593 rc
= smb_init(SMB_COM_DELETE
, 1, tcon
, (void **) &pSMB
,
598 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
600 cifsConvertToUCS((__le16
*) pSMB
->fileName
, fileName
,
601 PATH_MAX
, nls_codepage
, remap
);
602 name_len
++; /* trailing null */
604 } else { /* BB improve check for buffer overruns BB */
605 name_len
= strnlen(fileName
, PATH_MAX
);
606 name_len
++; /* trailing null */
607 strncpy(pSMB
->fileName
, fileName
, name_len
);
609 pSMB
->SearchAttributes
=
610 cpu_to_le16(ATTR_READONLY
| ATTR_HIDDEN
| ATTR_SYSTEM
);
611 pSMB
->BufferFormat
= 0x04;
612 pSMB
->hdr
.smb_buf_length
+= name_len
+ 1;
613 pSMB
->ByteCount
= cpu_to_le16(name_len
+ 1);
614 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
615 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
616 cifs_stats_inc(&tcon
->num_deletes
);
618 cFYI(1, ("Error in RMFile = %d", rc
));
621 cifs_buf_release(pSMB
);
629 CIFSSMBRmDir(const int xid
, struct cifsTconInfo
*tcon
, const char *dirName
,
630 const struct nls_table
*nls_codepage
, int remap
)
632 DELETE_DIRECTORY_REQ
*pSMB
= NULL
;
633 DELETE_DIRECTORY_RSP
*pSMBr
= NULL
;
638 cFYI(1, ("In CIFSSMBRmDir"));
640 rc
= smb_init(SMB_COM_DELETE_DIRECTORY
, 0, tcon
, (void **) &pSMB
,
645 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
646 name_len
= cifsConvertToUCS((__le16
*) pSMB
->DirName
, dirName
,
647 PATH_MAX
, nls_codepage
, remap
);
648 name_len
++; /* trailing null */
650 } else { /* BB improve check for buffer overruns BB */
651 name_len
= strnlen(dirName
, PATH_MAX
);
652 name_len
++; /* trailing null */
653 strncpy(pSMB
->DirName
, dirName
, name_len
);
656 pSMB
->BufferFormat
= 0x04;
657 pSMB
->hdr
.smb_buf_length
+= name_len
+ 1;
658 pSMB
->ByteCount
= cpu_to_le16(name_len
+ 1);
659 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
660 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
661 cifs_stats_inc(&tcon
->num_rmdirs
);
663 cFYI(1, ("Error in RMDir = %d", rc
));
666 cifs_buf_release(pSMB
);
673 CIFSSMBMkDir(const int xid
, struct cifsTconInfo
*tcon
,
674 const char *name
, const struct nls_table
*nls_codepage
, int remap
)
677 CREATE_DIRECTORY_REQ
*pSMB
= NULL
;
678 CREATE_DIRECTORY_RSP
*pSMBr
= NULL
;
682 cFYI(1, ("In CIFSSMBMkDir"));
684 rc
= smb_init(SMB_COM_CREATE_DIRECTORY
, 0, tcon
, (void **) &pSMB
,
689 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
690 name_len
= cifsConvertToUCS((__le16
*) pSMB
->DirName
, name
,
691 PATH_MAX
, nls_codepage
, remap
);
692 name_len
++; /* trailing null */
694 } else { /* BB improve check for buffer overruns BB */
695 name_len
= strnlen(name
, PATH_MAX
);
696 name_len
++; /* trailing null */
697 strncpy(pSMB
->DirName
, name
, name_len
);
700 pSMB
->BufferFormat
= 0x04;
701 pSMB
->hdr
.smb_buf_length
+= name_len
+ 1;
702 pSMB
->ByteCount
= cpu_to_le16(name_len
+ 1);
703 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
704 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
705 cifs_stats_inc(&tcon
->num_mkdirs
);
707 cFYI(1, ("Error in Mkdir = %d", rc
));
710 cifs_buf_release(pSMB
);
716 static __u16
convert_disposition(int disposition
)
720 switch (disposition
) {
722 ofun
= SMBOPEN_OCREATE
| SMBOPEN_OTRUNC
;
725 ofun
= SMBOPEN_OAPPEND
;
728 ofun
= SMBOPEN_OCREATE
;
731 ofun
= SMBOPEN_OCREATE
| SMBOPEN_OAPPEND
;
734 ofun
= SMBOPEN_OTRUNC
;
736 case FILE_OVERWRITE_IF
:
737 ofun
= SMBOPEN_OCREATE
| SMBOPEN_OTRUNC
;
740 cFYI(1,("unknown disposition %d",disposition
));
741 ofun
= SMBOPEN_OAPPEND
; /* regular open */
747 SMBLegacyOpen(const int xid
, struct cifsTconInfo
*tcon
,
748 const char *fileName
, const int openDisposition
,
749 const int access_flags
, const int create_options
, __u16
* netfid
,
750 int *pOplock
, FILE_ALL_INFO
* pfile_info
,
751 const struct nls_table
*nls_codepage
, int remap
)
754 OPENX_REQ
*pSMB
= NULL
;
755 OPENX_RSP
*pSMBr
= NULL
;
761 rc
= smb_init(SMB_COM_OPEN_ANDX
, 15, tcon
, (void **) &pSMB
,
766 pSMB
->AndXCommand
= 0xFF; /* none */
768 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
769 count
= 1; /* account for one byte pad to word boundary */
771 cifsConvertToUCS((__le16
*) (pSMB
->fileName
+ 1),
772 fileName
, PATH_MAX
, nls_codepage
, remap
);
773 name_len
++; /* trailing null */
775 } else { /* BB improve check for buffer overruns BB */
776 count
= 0; /* no pad */
777 name_len
= strnlen(fileName
, PATH_MAX
);
778 name_len
++; /* trailing null */
779 strncpy(pSMB
->fileName
, fileName
, name_len
);
781 if (*pOplock
& REQ_OPLOCK
)
782 pSMB
->OpenFlags
= cpu_to_le16(REQ_OPLOCK
);
783 else if (*pOplock
& REQ_BATCHOPLOCK
) {
784 pSMB
->OpenFlags
= cpu_to_le16(REQ_BATCHOPLOCK
);
786 pSMB
->OpenFlags
|= cpu_to_le16(REQ_MORE_INFO
);
787 /* BB fixme add conversion for access_flags to bits 0 - 2 of mode */
793 pSMB
->Mode
= cpu_to_le16(2);
794 pSMB
->Mode
|= cpu_to_le16(0x40); /* deny none */
795 /* set file as system file if special file such
796 as fifo and server expecting SFU style and
797 no Unix extensions */
799 if(create_options
& CREATE_OPTION_SPECIAL
)
800 pSMB
->FileAttributes
= cpu_to_le16(ATTR_SYSTEM
);
802 pSMB
->FileAttributes
= cpu_to_le16(0/*ATTR_NORMAL*/); /* BB FIXME */
804 /* if ((omode & S_IWUGO) == 0)
805 pSMB->FileAttributes |= cpu_to_le32(ATTR_READONLY);*/
806 /* Above line causes problems due to vfs splitting create into two
807 pieces - need to set mode after file created not while it is
811 /* pSMB->CreateOptions = cpu_to_le32(create_options & CREATE_OPTIONS_MASK); */
812 /* BB FIXME END BB */
814 pSMB
->Sattr
= cpu_to_le16(ATTR_HIDDEN
| ATTR_SYSTEM
| ATTR_DIRECTORY
);
815 pSMB
->OpenFunction
= cpu_to_le16(convert_disposition(openDisposition
));
817 pSMB
->hdr
.smb_buf_length
+= count
;
819 pSMB
->ByteCount
= cpu_to_le16(count
);
820 /* long_op set to 1 to allow for oplock break timeouts */
821 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
822 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 1);
823 cifs_stats_inc(&tcon
->num_opens
);
825 cFYI(1, ("Error in Open = %d", rc
));
827 /* BB verify if wct == 15 */
829 /* *pOplock = pSMBr->OplockLevel; */ /* BB take from action field BB */
831 *netfid
= pSMBr
->Fid
; /* cifs fid stays in le */
832 /* Let caller know file was created so we can set the mode. */
833 /* Do we care about the CreateAction in any other cases? */
835 /* if(cpu_to_le32(FILE_CREATE) == pSMBr->CreateAction)
836 *pOplock |= CIFS_CREATE_ACTION; */
840 pfile_info
->CreationTime
= 0; /* BB convert CreateTime*/
841 pfile_info
->LastAccessTime
= 0; /* BB fixme */
842 pfile_info
->LastWriteTime
= 0; /* BB fixme */
843 pfile_info
->ChangeTime
= 0; /* BB fixme */
844 pfile_info
->Attributes
=
845 cpu_to_le32(le16_to_cpu(pSMBr
->FileAttributes
));
846 /* the file_info buf is endian converted by caller */
847 pfile_info
->AllocationSize
=
848 cpu_to_le64(le32_to_cpu(pSMBr
->EndOfFile
));
849 pfile_info
->EndOfFile
= pfile_info
->AllocationSize
;
850 pfile_info
->NumberOfLinks
= cpu_to_le32(1);
854 cifs_buf_release(pSMB
);
861 CIFSSMBOpen(const int xid
, struct cifsTconInfo
*tcon
,
862 const char *fileName
, const int openDisposition
,
863 const int access_flags
, const int create_options
, __u16
* netfid
,
864 int *pOplock
, FILE_ALL_INFO
* pfile_info
,
865 const struct nls_table
*nls_codepage
, int remap
)
868 OPEN_REQ
*pSMB
= NULL
;
869 OPEN_RSP
*pSMBr
= NULL
;
875 rc
= smb_init(SMB_COM_NT_CREATE_ANDX
, 24, tcon
, (void **) &pSMB
,
880 pSMB
->AndXCommand
= 0xFF; /* none */
882 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
883 count
= 1; /* account for one byte pad to word boundary */
885 cifsConvertToUCS((__le16
*) (pSMB
->fileName
+ 1),
886 fileName
, PATH_MAX
, nls_codepage
, remap
);
887 name_len
++; /* trailing null */
889 pSMB
->NameLength
= cpu_to_le16(name_len
);
890 } else { /* BB improve check for buffer overruns BB */
891 count
= 0; /* no pad */
892 name_len
= strnlen(fileName
, PATH_MAX
);
893 name_len
++; /* trailing null */
894 pSMB
->NameLength
= cpu_to_le16(name_len
);
895 strncpy(pSMB
->fileName
, fileName
, name_len
);
897 if (*pOplock
& REQ_OPLOCK
)
898 pSMB
->OpenFlags
= cpu_to_le32(REQ_OPLOCK
);
899 else if (*pOplock
& REQ_BATCHOPLOCK
) {
900 pSMB
->OpenFlags
= cpu_to_le32(REQ_BATCHOPLOCK
);
902 pSMB
->DesiredAccess
= cpu_to_le32(access_flags
);
903 pSMB
->AllocationSize
= 0;
904 /* set file as system file if special file such
905 as fifo and server expecting SFU style and
906 no Unix extensions */
907 if(create_options
& CREATE_OPTION_SPECIAL
)
908 pSMB
->FileAttributes
= cpu_to_le32(ATTR_SYSTEM
);
910 pSMB
->FileAttributes
= cpu_to_le32(ATTR_NORMAL
);
911 /* XP does not handle ATTR_POSIX_SEMANTICS */
912 /* but it helps speed up case sensitive checks for other
913 servers such as Samba */
914 if (tcon
->ses
->capabilities
& CAP_UNIX
)
915 pSMB
->FileAttributes
|= cpu_to_le32(ATTR_POSIX_SEMANTICS
);
917 /* if ((omode & S_IWUGO) == 0)
918 pSMB->FileAttributes |= cpu_to_le32(ATTR_READONLY);*/
919 /* Above line causes problems due to vfs splitting create into two
920 pieces - need to set mode after file created not while it is
922 pSMB
->ShareAccess
= cpu_to_le32(FILE_SHARE_ALL
);
923 pSMB
->CreateDisposition
= cpu_to_le32(openDisposition
);
924 pSMB
->CreateOptions
= cpu_to_le32(create_options
& CREATE_OPTIONS_MASK
);
925 /* BB Expirement with various impersonation levels and verify */
926 pSMB
->ImpersonationLevel
= cpu_to_le32(SECURITY_IMPERSONATION
);
927 pSMB
->SecurityFlags
=
928 SECURITY_CONTEXT_TRACKING
| SECURITY_EFFECTIVE_ONLY
;
931 pSMB
->hdr
.smb_buf_length
+= count
;
933 pSMB
->ByteCount
= cpu_to_le16(count
);
934 /* long_op set to 1 to allow for oplock break timeouts */
935 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
936 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 1);
937 cifs_stats_inc(&tcon
->num_opens
);
939 cFYI(1, ("Error in Open = %d", rc
));
941 *pOplock
= pSMBr
->OplockLevel
; /* 1 byte no need to le_to_cpu */
942 *netfid
= pSMBr
->Fid
; /* cifs fid stays in le */
943 /* Let caller know file was created so we can set the mode. */
944 /* Do we care about the CreateAction in any other cases? */
945 if(cpu_to_le32(FILE_CREATE
) == pSMBr
->CreateAction
)
946 *pOplock
|= CIFS_CREATE_ACTION
;
948 memcpy((char *)pfile_info
,(char *)&pSMBr
->CreationTime
,
949 36 /* CreationTime to Attributes */);
950 /* the file_info buf is endian converted by caller */
951 pfile_info
->AllocationSize
= pSMBr
->AllocationSize
;
952 pfile_info
->EndOfFile
= pSMBr
->EndOfFile
;
953 pfile_info
->NumberOfLinks
= cpu_to_le32(1);
957 cifs_buf_release(pSMB
);
964 CIFSSMBRead(const int xid
, struct cifsTconInfo
*tcon
,
965 const int netfid
, const unsigned int count
,
966 const __u64 lseek
, unsigned int *nbytes
, char **buf
,
970 READ_REQ
*pSMB
= NULL
;
971 READ_RSP
*pSMBr
= NULL
;
972 char *pReadData
= NULL
;
974 int resp_buf_type
= 0;
977 cFYI(1,("Reading %d bytes on fid %d",count
,netfid
));
978 if(tcon
->ses
->capabilities
& CAP_LARGE_FILES
)
981 wct
= 10; /* old style read */
984 rc
= small_smb_init(SMB_COM_READ_ANDX
, wct
, tcon
, (void **) &pSMB
);
988 /* tcon and ses pointer are checked in smb_init */
989 if (tcon
->ses
->server
== NULL
)
990 return -ECONNABORTED
;
992 pSMB
->AndXCommand
= 0xFF; /* none */
994 pSMB
->OffsetLow
= cpu_to_le32(lseek
& 0xFFFFFFFF);
996 pSMB
->OffsetHigh
= cpu_to_le32(lseek
>> 32);
997 else if((lseek
>> 32) > 0) /* can not handle this big offset for old */
1000 pSMB
->Remaining
= 0;
1001 pSMB
->MaxCount
= cpu_to_le16(count
& 0xFFFF);
1002 pSMB
->MaxCountHigh
= cpu_to_le32(count
>> 16);
1004 pSMB
->ByteCount
= 0; /* no need to do le conversion since 0 */
1006 /* old style read */
1007 struct smb_com_readx_req
* pSMBW
=
1008 (struct smb_com_readx_req
*)pSMB
;
1009 pSMBW
->ByteCount
= 0;
1012 iov
[0].iov_base
= (char *)pSMB
;
1013 iov
[0].iov_len
= pSMB
->hdr
.smb_buf_length
+ 4;
1014 rc
= SendReceive2(xid
, tcon
->ses
, iov
,
1017 cifs_stats_inc(&tcon
->num_reads
);
1018 pSMBr
= (READ_RSP
*)iov
[0].iov_base
;
1020 cERROR(1, ("Send error in read = %d", rc
));
1022 int data_length
= le16_to_cpu(pSMBr
->DataLengthHigh
);
1023 data_length
= data_length
<< 16;
1024 data_length
+= le16_to_cpu(pSMBr
->DataLength
);
1025 *nbytes
= data_length
;
1027 /*check that DataLength would not go beyond end of SMB */
1028 if ((data_length
> CIFSMaxBufSize
)
1029 || (data_length
> count
)) {
1030 cFYI(1,("bad length %d for count %d",data_length
,count
));
1034 pReadData
= (char *) (&pSMBr
->hdr
.Protocol
) +
1035 le16_to_cpu(pSMBr
->DataOffset
);
1036 /* if(rc = copy_to_user(buf, pReadData, data_length)) {
1037 cERROR(1,("Faulting on read rc = %d",rc));
1039 }*/ /* can not use copy_to_user when using page cache*/
1041 memcpy(*buf
,pReadData
,data_length
);
1045 cifs_small_buf_release(pSMB
);
1047 if(resp_buf_type
== CIFS_SMALL_BUFFER
)
1048 cifs_small_buf_release(iov
[0].iov_base
);
1049 else if(resp_buf_type
== CIFS_LARGE_BUFFER
)
1050 cifs_buf_release(iov
[0].iov_base
);
1051 } else if(resp_buf_type
!= CIFS_NO_BUFFER
) {
1052 /* return buffer to caller to free */
1053 *buf
= iov
[0].iov_base
;
1054 if(resp_buf_type
== CIFS_SMALL_BUFFER
)
1055 *pbuf_type
= CIFS_SMALL_BUFFER
;
1056 else if(resp_buf_type
== CIFS_LARGE_BUFFER
)
1057 *pbuf_type
= CIFS_LARGE_BUFFER
;
1058 } /* else no valid buffer on return - leave as null */
1060 /* Note: On -EAGAIN error only caller can retry on handle based calls
1061 since file handle passed in no longer valid */
1067 CIFSSMBWrite(const int xid
, struct cifsTconInfo
*tcon
,
1068 const int netfid
, const unsigned int count
,
1069 const __u64 offset
, unsigned int *nbytes
, const char *buf
,
1070 const char __user
* ubuf
, const int long_op
)
1073 WRITE_REQ
*pSMB
= NULL
;
1074 WRITE_RSP
*pSMBr
= NULL
;
1075 int bytes_returned
, wct
;
1079 /* cFYI(1,("write at %lld %d bytes",offset,count));*/
1080 if(tcon
->ses
== NULL
)
1081 return -ECONNABORTED
;
1083 if(tcon
->ses
->capabilities
& CAP_LARGE_FILES
)
1088 rc
= smb_init(SMB_COM_WRITE_ANDX
, wct
, tcon
, (void **) &pSMB
,
1092 /* tcon and ses pointer are checked in smb_init */
1093 if (tcon
->ses
->server
== NULL
)
1094 return -ECONNABORTED
;
1096 pSMB
->AndXCommand
= 0xFF; /* none */
1098 pSMB
->OffsetLow
= cpu_to_le32(offset
& 0xFFFFFFFF);
1100 pSMB
->OffsetHigh
= cpu_to_le32(offset
>> 32);
1101 else if((offset
>> 32) > 0) /* can not handle this big offset for old */
1104 pSMB
->Reserved
= 0xFFFFFFFF;
1105 pSMB
->WriteMode
= 0;
1106 pSMB
->Remaining
= 0;
1108 /* Can increase buffer size if buffer is big enough in some cases - ie we
1109 can send more if LARGE_WRITE_X capability returned by the server and if
1110 our buffer is big enough or if we convert to iovecs on socket writes
1111 and eliminate the copy to the CIFS buffer */
1112 if(tcon
->ses
->capabilities
& CAP_LARGE_WRITE_X
) {
1113 bytes_sent
= min_t(const unsigned int, CIFSMaxBufSize
, count
);
1115 bytes_sent
= (tcon
->ses
->server
->maxBuf
- MAX_CIFS_HDR_SIZE
)
1119 if (bytes_sent
> count
)
1122 cpu_to_le16(offsetof(struct smb_com_write_req
,Data
) - 4);
1124 memcpy(pSMB
->Data
,buf
,bytes_sent
);
1126 if(copy_from_user(pSMB
->Data
,ubuf
,bytes_sent
)) {
1127 cifs_buf_release(pSMB
);
1130 } else if (count
!= 0) {
1132 cifs_buf_release(pSMB
);
1134 } /* else setting file size with write of zero bytes */
1136 byte_count
= bytes_sent
+ 1; /* pad */
1137 else /* wct == 12 */ {
1138 byte_count
= bytes_sent
+ 5; /* bigger pad, smaller smb hdr */
1140 pSMB
->DataLengthLow
= cpu_to_le16(bytes_sent
& 0xFFFF);
1141 pSMB
->DataLengthHigh
= cpu_to_le16(bytes_sent
>> 16);
1142 pSMB
->hdr
.smb_buf_length
+= byte_count
;
1145 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
1146 else { /* old style write has byte count 4 bytes earlier so 4 bytes pad */
1147 struct smb_com_writex_req
* pSMBW
=
1148 (struct smb_com_writex_req
*)pSMB
;
1149 pSMBW
->ByteCount
= cpu_to_le16(byte_count
);
1152 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
1153 (struct smb_hdr
*) pSMBr
, &bytes_returned
, long_op
);
1154 cifs_stats_inc(&tcon
->num_writes
);
1156 cFYI(1, ("Send error in write = %d", rc
));
1159 *nbytes
= le16_to_cpu(pSMBr
->CountHigh
);
1160 *nbytes
= (*nbytes
) << 16;
1161 *nbytes
+= le16_to_cpu(pSMBr
->Count
);
1164 cifs_buf_release(pSMB
);
1166 /* Note: On -EAGAIN error only caller can retry on handle based calls
1167 since file handle passed in no longer valid */
1173 CIFSSMBWrite2(const int xid
, struct cifsTconInfo
*tcon
,
1174 const int netfid
, const unsigned int count
,
1175 const __u64 offset
, unsigned int *nbytes
, struct kvec
*iov
,
1176 int n_vec
, const int long_op
)
1179 WRITE_REQ
*pSMB
= NULL
;
1182 int resp_buf_type
= 0;
1184 cFYI(1,("write2 at %lld %d bytes", (long long)offset
, count
));
1186 if(tcon
->ses
->capabilities
& CAP_LARGE_FILES
)
1190 rc
= small_smb_init(SMB_COM_WRITE_ANDX
, wct
, tcon
, (void **) &pSMB
);
1193 /* tcon and ses pointer are checked in smb_init */
1194 if (tcon
->ses
->server
== NULL
)
1195 return -ECONNABORTED
;
1197 pSMB
->AndXCommand
= 0xFF; /* none */
1199 pSMB
->OffsetLow
= cpu_to_le32(offset
& 0xFFFFFFFF);
1201 pSMB
->OffsetHigh
= cpu_to_le32(offset
>> 32);
1202 else if((offset
>> 32) > 0) /* can not handle this big offset for old */
1204 pSMB
->Reserved
= 0xFFFFFFFF;
1205 pSMB
->WriteMode
= 0;
1206 pSMB
->Remaining
= 0;
1209 cpu_to_le16(offsetof(struct smb_com_write_req
,Data
) - 4);
1211 pSMB
->DataLengthLow
= cpu_to_le16(count
& 0xFFFF);
1212 pSMB
->DataLengthHigh
= cpu_to_le16(count
>> 16);
1213 smb_hdr_len
= pSMB
->hdr
.smb_buf_length
+ 1; /* hdr + 1 byte pad */
1215 pSMB
->hdr
.smb_buf_length
+= count
+1;
1216 else /* wct == 12 */
1217 pSMB
->hdr
.smb_buf_length
+= count
+5; /* smb data starts later */
1219 pSMB
->ByteCount
= cpu_to_le16(count
+ 1);
1220 else /* wct == 12 */ /* bigger pad, smaller smb hdr, keep offset ok */ {
1221 struct smb_com_writex_req
* pSMBW
=
1222 (struct smb_com_writex_req
*)pSMB
;
1223 pSMBW
->ByteCount
= cpu_to_le16(count
+ 5);
1225 iov
[0].iov_base
= pSMB
;
1227 iov
[0].iov_len
= smb_hdr_len
+ 4;
1228 else /* wct == 12 pad bigger by four bytes */
1229 iov
[0].iov_len
= smb_hdr_len
+ 8;
1232 rc
= SendReceive2(xid
, tcon
->ses
, iov
, n_vec
+ 1, &resp_buf_type
,
1234 cifs_stats_inc(&tcon
->num_writes
);
1236 cFYI(1, ("Send error Write2 = %d", rc
));
1238 } else if(resp_buf_type
== 0) {
1239 /* presumably this can not happen, but best to be safe */
1243 WRITE_RSP
* pSMBr
= (WRITE_RSP
*)iov
[0].iov_base
;
1244 *nbytes
= le16_to_cpu(pSMBr
->CountHigh
);
1245 *nbytes
= (*nbytes
) << 16;
1246 *nbytes
+= le16_to_cpu(pSMBr
->Count
);
1249 cifs_small_buf_release(pSMB
);
1250 if(resp_buf_type
== CIFS_SMALL_BUFFER
)
1251 cifs_small_buf_release(iov
[0].iov_base
);
1252 else if(resp_buf_type
== CIFS_LARGE_BUFFER
)
1253 cifs_buf_release(iov
[0].iov_base
);
1255 /* Note: On -EAGAIN error only caller can retry on handle based calls
1256 since file handle passed in no longer valid */
1263 CIFSSMBLock(const int xid
, struct cifsTconInfo
*tcon
,
1264 const __u16 smb_file_id
, const __u64 len
,
1265 const __u64 offset
, const __u32 numUnlock
,
1266 const __u32 numLock
, const __u8 lockType
, const int waitFlag
)
1269 LOCK_REQ
*pSMB
= NULL
;
1270 LOCK_RSP
*pSMBr
= NULL
;
1275 cFYI(1, ("In CIFSSMBLock - timeout %d numLock %d",waitFlag
,numLock
));
1276 rc
= small_smb_init(SMB_COM_LOCKING_ANDX
, 8, tcon
, (void **) &pSMB
);
1281 pSMBr
= (LOCK_RSP
*)pSMB
; /* BB removeme BB */
1283 if(lockType
== LOCKING_ANDX_OPLOCK_RELEASE
) {
1284 timeout
= -1; /* no response expected */
1286 } else if (waitFlag
== TRUE
) {
1287 timeout
= 3; /* blocking operation, no timeout */
1288 pSMB
->Timeout
= cpu_to_le32(-1);/* blocking - do not time out */
1293 pSMB
->NumberOfLocks
= cpu_to_le16(numLock
);
1294 pSMB
->NumberOfUnlocks
= cpu_to_le16(numUnlock
);
1295 pSMB
->LockType
= lockType
;
1296 pSMB
->AndXCommand
= 0xFF; /* none */
1297 pSMB
->Fid
= smb_file_id
; /* netfid stays le */
1299 if((numLock
!= 0) || (numUnlock
!= 0)) {
1300 pSMB
->Locks
[0].Pid
= cpu_to_le16(current
->tgid
);
1301 /* BB where to store pid high? */
1302 pSMB
->Locks
[0].LengthLow
= cpu_to_le32((u32
)len
);
1303 pSMB
->Locks
[0].LengthHigh
= cpu_to_le32((u32
)(len
>>32));
1304 pSMB
->Locks
[0].OffsetLow
= cpu_to_le32((u32
)offset
);
1305 pSMB
->Locks
[0].OffsetHigh
= cpu_to_le32((u32
)(offset
>>32));
1306 count
= sizeof(LOCKING_ANDX_RANGE
);
1311 pSMB
->hdr
.smb_buf_length
+= count
;
1312 pSMB
->ByteCount
= cpu_to_le16(count
);
1314 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
1315 (struct smb_hdr
*) pSMBr
, &bytes_returned
, timeout
);
1316 cifs_stats_inc(&tcon
->num_locks
);
1318 cFYI(1, ("Send error in Lock = %d", rc
));
1320 cifs_small_buf_release(pSMB
);
1322 /* Note: On -EAGAIN error only caller can retry on handle based calls
1323 since file handle passed in no longer valid */
1328 CIFSSMBClose(const int xid
, struct cifsTconInfo
*tcon
, int smb_file_id
)
1331 CLOSE_REQ
*pSMB
= NULL
;
1332 CLOSE_RSP
*pSMBr
= NULL
;
1334 cFYI(1, ("In CIFSSMBClose"));
1336 /* do not retry on dead session on close */
1337 rc
= small_smb_init(SMB_COM_CLOSE
, 3, tcon
, (void **) &pSMB
);
1343 pSMBr
= (CLOSE_RSP
*)pSMB
; /* BB removeme BB */
1345 pSMB
->FileID
= (__u16
) smb_file_id
;
1346 pSMB
->LastWriteTime
= 0;
1347 pSMB
->ByteCount
= 0;
1348 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
1349 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
1350 cifs_stats_inc(&tcon
->num_closes
);
1353 /* EINTR is expected when user ctl-c to kill app */
1354 cERROR(1, ("Send error in Close = %d", rc
));
1358 cifs_small_buf_release(pSMB
);
1360 /* Since session is dead, file will be closed on server already */
1368 CIFSSMBRename(const int xid
, struct cifsTconInfo
*tcon
,
1369 const char *fromName
, const char *toName
,
1370 const struct nls_table
*nls_codepage
, int remap
)
1373 RENAME_REQ
*pSMB
= NULL
;
1374 RENAME_RSP
*pSMBr
= NULL
;
1376 int name_len
, name_len2
;
1379 cFYI(1, ("In CIFSSMBRename"));
1381 rc
= smb_init(SMB_COM_RENAME
, 1, tcon
, (void **) &pSMB
,
1386 pSMB
->BufferFormat
= 0x04;
1387 pSMB
->SearchAttributes
=
1388 cpu_to_le16(ATTR_READONLY
| ATTR_HIDDEN
| ATTR_SYSTEM
|
1391 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
1393 cifsConvertToUCS((__le16
*) pSMB
->OldFileName
, fromName
,
1394 PATH_MAX
, nls_codepage
, remap
);
1395 name_len
++; /* trailing null */
1397 pSMB
->OldFileName
[name_len
] = 0x04; /* pad */
1398 /* protocol requires ASCII signature byte on Unicode string */
1399 pSMB
->OldFileName
[name_len
+ 1] = 0x00;
1401 cifsConvertToUCS((__le16
*) &pSMB
->OldFileName
[name_len
+ 2],
1402 toName
, PATH_MAX
, nls_codepage
, remap
);
1403 name_len2
+= 1 /* trailing null */ + 1 /* Signature word */ ;
1404 name_len2
*= 2; /* convert to bytes */
1405 } else { /* BB improve the check for buffer overruns BB */
1406 name_len
= strnlen(fromName
, PATH_MAX
);
1407 name_len
++; /* trailing null */
1408 strncpy(pSMB
->OldFileName
, fromName
, name_len
);
1409 name_len2
= strnlen(toName
, PATH_MAX
);
1410 name_len2
++; /* trailing null */
1411 pSMB
->OldFileName
[name_len
] = 0x04; /* 2nd buffer format */
1412 strncpy(&pSMB
->OldFileName
[name_len
+ 1], toName
, name_len2
);
1413 name_len2
++; /* trailing null */
1414 name_len2
++; /* signature byte */
1417 count
= 1 /* 1st signature byte */ + name_len
+ name_len2
;
1418 pSMB
->hdr
.smb_buf_length
+= count
;
1419 pSMB
->ByteCount
= cpu_to_le16(count
);
1421 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
1422 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
1423 cifs_stats_inc(&tcon
->num_renames
);
1425 cFYI(1, ("Send error in rename = %d", rc
));
1428 cifs_buf_release(pSMB
);
1436 int CIFSSMBRenameOpenFile(const int xid
,struct cifsTconInfo
*pTcon
,
1437 int netfid
, char * target_name
,
1438 const struct nls_table
* nls_codepage
, int remap
)
1440 struct smb_com_transaction2_sfi_req
*pSMB
= NULL
;
1441 struct smb_com_transaction2_sfi_rsp
*pSMBr
= NULL
;
1442 struct set_file_rename
* rename_info
;
1444 char dummy_string
[30];
1446 int bytes_returned
= 0;
1448 __u16 params
, param_offset
, offset
, count
, byte_count
;
1450 cFYI(1, ("Rename to File by handle"));
1451 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, pTcon
, (void **) &pSMB
,
1457 pSMB
->MaxSetupCount
= 0;
1461 pSMB
->Reserved2
= 0;
1462 param_offset
= offsetof(struct smb_com_transaction2_sfi_req
, Fid
) - 4;
1463 offset
= param_offset
+ params
;
1465 data_offset
= (char *) (&pSMB
->hdr
.Protocol
) + offset
;
1466 rename_info
= (struct set_file_rename
*) data_offset
;
1467 pSMB
->MaxParameterCount
= cpu_to_le16(2);
1468 pSMB
->MaxDataCount
= cpu_to_le16(1000); /* BB find max SMB PDU from sess */
1469 pSMB
->SetupCount
= 1;
1470 pSMB
->Reserved3
= 0;
1471 pSMB
->SubCommand
= cpu_to_le16(TRANS2_SET_FILE_INFORMATION
);
1472 byte_count
= 3 /* pad */ + params
;
1473 pSMB
->ParameterCount
= cpu_to_le16(params
);
1474 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
1475 pSMB
->ParameterOffset
= cpu_to_le16(param_offset
);
1476 pSMB
->DataOffset
= cpu_to_le16(offset
);
1477 /* construct random name ".cifs_tmp<inodenum><mid>" */
1478 rename_info
->overwrite
= cpu_to_le32(1);
1479 rename_info
->root_fid
= 0;
1480 /* unicode only call */
1481 if(target_name
== NULL
) {
1482 sprintf(dummy_string
,"cifs%x",pSMB
->hdr
.Mid
);
1483 len_of_str
= cifsConvertToUCS((__le16
*)rename_info
->target_name
,
1484 dummy_string
, 24, nls_codepage
, remap
);
1486 len_of_str
= cifsConvertToUCS((__le16
*)rename_info
->target_name
,
1487 target_name
, PATH_MAX
, nls_codepage
, remap
);
1489 rename_info
->target_name_len
= cpu_to_le32(2 * len_of_str
);
1490 count
= 12 /* sizeof(struct set_file_rename) */ + (2 * len_of_str
) + 2;
1491 byte_count
+= count
;
1492 pSMB
->DataCount
= cpu_to_le16(count
);
1493 pSMB
->TotalDataCount
= pSMB
->DataCount
;
1495 pSMB
->InformationLevel
=
1496 cpu_to_le16(SMB_SET_FILE_RENAME_INFORMATION
);
1497 pSMB
->Reserved4
= 0;
1498 pSMB
->hdr
.smb_buf_length
+= byte_count
;
1499 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
1500 rc
= SendReceive(xid
, pTcon
->ses
, (struct smb_hdr
*) pSMB
,
1501 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
1502 cifs_stats_inc(&pTcon
->num_t2renames
);
1504 cFYI(1,("Send error in Rename (by file handle) = %d", rc
));
1507 cifs_buf_release(pSMB
);
1509 /* Note: On -EAGAIN error only caller can retry on handle based calls
1510 since file handle passed in no longer valid */
1516 CIFSSMBCopy(const int xid
, struct cifsTconInfo
*tcon
, const char * fromName
,
1517 const __u16 target_tid
, const char *toName
, const int flags
,
1518 const struct nls_table
*nls_codepage
, int remap
)
1521 COPY_REQ
*pSMB
= NULL
;
1522 COPY_RSP
*pSMBr
= NULL
;
1524 int name_len
, name_len2
;
1527 cFYI(1, ("In CIFSSMBCopy"));
1529 rc
= smb_init(SMB_COM_COPY
, 1, tcon
, (void **) &pSMB
,
1534 pSMB
->BufferFormat
= 0x04;
1535 pSMB
->Tid2
= target_tid
;
1537 pSMB
->Flags
= cpu_to_le16(flags
& COPY_TREE
);
1539 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
1540 name_len
= cifsConvertToUCS((__le16
*) pSMB
->OldFileName
,
1541 fromName
, PATH_MAX
, nls_codepage
,
1543 name_len
++; /* trailing null */
1545 pSMB
->OldFileName
[name_len
] = 0x04; /* pad */
1546 /* protocol requires ASCII signature byte on Unicode string */
1547 pSMB
->OldFileName
[name_len
+ 1] = 0x00;
1548 name_len2
= cifsConvertToUCS((__le16
*)&pSMB
->OldFileName
[name_len
+ 2],
1549 toName
, PATH_MAX
, nls_codepage
, remap
);
1550 name_len2
+= 1 /* trailing null */ + 1 /* Signature word */ ;
1551 name_len2
*= 2; /* convert to bytes */
1552 } else { /* BB improve the check for buffer overruns BB */
1553 name_len
= strnlen(fromName
, PATH_MAX
);
1554 name_len
++; /* trailing null */
1555 strncpy(pSMB
->OldFileName
, fromName
, name_len
);
1556 name_len2
= strnlen(toName
, PATH_MAX
);
1557 name_len2
++; /* trailing null */
1558 pSMB
->OldFileName
[name_len
] = 0x04; /* 2nd buffer format */
1559 strncpy(&pSMB
->OldFileName
[name_len
+ 1], toName
, name_len2
);
1560 name_len2
++; /* trailing null */
1561 name_len2
++; /* signature byte */
1564 count
= 1 /* 1st signature byte */ + name_len
+ name_len2
;
1565 pSMB
->hdr
.smb_buf_length
+= count
;
1566 pSMB
->ByteCount
= cpu_to_le16(count
);
1568 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
1569 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
1571 cFYI(1, ("Send error in copy = %d with %d files copied",
1572 rc
, le16_to_cpu(pSMBr
->CopyCount
)));
1575 cifs_buf_release(pSMB
);
1584 CIFSUnixCreateSymLink(const int xid
, struct cifsTconInfo
*tcon
,
1585 const char *fromName
, const char *toName
,
1586 const struct nls_table
*nls_codepage
)
1588 TRANSACTION2_SPI_REQ
*pSMB
= NULL
;
1589 TRANSACTION2_SPI_RSP
*pSMBr
= NULL
;
1592 int name_len_target
;
1594 int bytes_returned
= 0;
1595 __u16 params
, param_offset
, offset
, byte_count
;
1597 cFYI(1, ("In Symlink Unix style"));
1599 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
1604 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
1606 cifs_strtoUCS((__le16
*) pSMB
->FileName
, fromName
, PATH_MAX
1607 /* find define for this maxpathcomponent */
1609 name_len
++; /* trailing null */
1612 } else { /* BB improve the check for buffer overruns BB */
1613 name_len
= strnlen(fromName
, PATH_MAX
);
1614 name_len
++; /* trailing null */
1615 strncpy(pSMB
->FileName
, fromName
, name_len
);
1617 params
= 6 + name_len
;
1618 pSMB
->MaxSetupCount
= 0;
1622 pSMB
->Reserved2
= 0;
1623 param_offset
= offsetof(struct smb_com_transaction2_spi_req
,
1624 InformationLevel
) - 4;
1625 offset
= param_offset
+ params
;
1627 data_offset
= (char *) (&pSMB
->hdr
.Protocol
) + offset
;
1628 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
1630 cifs_strtoUCS((__le16
*) data_offset
, toName
, PATH_MAX
1631 /* find define for this maxpathcomponent */
1633 name_len_target
++; /* trailing null */
1634 name_len_target
*= 2;
1635 } else { /* BB improve the check for buffer overruns BB */
1636 name_len_target
= strnlen(toName
, PATH_MAX
);
1637 name_len_target
++; /* trailing null */
1638 strncpy(data_offset
, toName
, name_len_target
);
1641 pSMB
->MaxParameterCount
= cpu_to_le16(2);
1642 /* BB find exact max on data count below from sess */
1643 pSMB
->MaxDataCount
= cpu_to_le16(1000);
1644 pSMB
->SetupCount
= 1;
1645 pSMB
->Reserved3
= 0;
1646 pSMB
->SubCommand
= cpu_to_le16(TRANS2_SET_PATH_INFORMATION
);
1647 byte_count
= 3 /* pad */ + params
+ name_len_target
;
1648 pSMB
->DataCount
= cpu_to_le16(name_len_target
);
1649 pSMB
->ParameterCount
= cpu_to_le16(params
);
1650 pSMB
->TotalDataCount
= pSMB
->DataCount
;
1651 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
1652 pSMB
->ParameterOffset
= cpu_to_le16(param_offset
);
1653 pSMB
->DataOffset
= cpu_to_le16(offset
);
1654 pSMB
->InformationLevel
= cpu_to_le16(SMB_SET_FILE_UNIX_LINK
);
1655 pSMB
->Reserved4
= 0;
1656 pSMB
->hdr
.smb_buf_length
+= byte_count
;
1657 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
1658 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
1659 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
1660 cifs_stats_inc(&tcon
->num_symlinks
);
1663 ("Send error in SetPathInfo (create symlink) = %d",
1668 cifs_buf_release(pSMB
);
1671 goto createSymLinkRetry
;
1677 CIFSUnixCreateHardLink(const int xid
, struct cifsTconInfo
*tcon
,
1678 const char *fromName
, const char *toName
,
1679 const struct nls_table
*nls_codepage
, int remap
)
1681 TRANSACTION2_SPI_REQ
*pSMB
= NULL
;
1682 TRANSACTION2_SPI_RSP
*pSMBr
= NULL
;
1685 int name_len_target
;
1687 int bytes_returned
= 0;
1688 __u16 params
, param_offset
, offset
, byte_count
;
1690 cFYI(1, ("In Create Hard link Unix style"));
1691 createHardLinkRetry
:
1692 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
1697 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
1698 name_len
= cifsConvertToUCS((__le16
*) pSMB
->FileName
, toName
,
1699 PATH_MAX
, nls_codepage
, remap
);
1700 name_len
++; /* trailing null */
1703 } else { /* BB improve the check for buffer overruns BB */
1704 name_len
= strnlen(toName
, PATH_MAX
);
1705 name_len
++; /* trailing null */
1706 strncpy(pSMB
->FileName
, toName
, name_len
);
1708 params
= 6 + name_len
;
1709 pSMB
->MaxSetupCount
= 0;
1713 pSMB
->Reserved2
= 0;
1714 param_offset
= offsetof(struct smb_com_transaction2_spi_req
,
1715 InformationLevel
) - 4;
1716 offset
= param_offset
+ params
;
1718 data_offset
= (char *) (&pSMB
->hdr
.Protocol
) + offset
;
1719 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
1721 cifsConvertToUCS((__le16
*) data_offset
, fromName
, PATH_MAX
,
1722 nls_codepage
, remap
);
1723 name_len_target
++; /* trailing null */
1724 name_len_target
*= 2;
1725 } else { /* BB improve the check for buffer overruns BB */
1726 name_len_target
= strnlen(fromName
, PATH_MAX
);
1727 name_len_target
++; /* trailing null */
1728 strncpy(data_offset
, fromName
, name_len_target
);
1731 pSMB
->MaxParameterCount
= cpu_to_le16(2);
1732 /* BB find exact max on data count below from sess*/
1733 pSMB
->MaxDataCount
= cpu_to_le16(1000);
1734 pSMB
->SetupCount
= 1;
1735 pSMB
->Reserved3
= 0;
1736 pSMB
->SubCommand
= cpu_to_le16(TRANS2_SET_PATH_INFORMATION
);
1737 byte_count
= 3 /* pad */ + params
+ name_len_target
;
1738 pSMB
->ParameterCount
= cpu_to_le16(params
);
1739 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
1740 pSMB
->DataCount
= cpu_to_le16(name_len_target
);
1741 pSMB
->TotalDataCount
= pSMB
->DataCount
;
1742 pSMB
->ParameterOffset
= cpu_to_le16(param_offset
);
1743 pSMB
->DataOffset
= cpu_to_le16(offset
);
1744 pSMB
->InformationLevel
= cpu_to_le16(SMB_SET_FILE_UNIX_HLINK
);
1745 pSMB
->Reserved4
= 0;
1746 pSMB
->hdr
.smb_buf_length
+= byte_count
;
1747 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
1748 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
1749 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
1750 cifs_stats_inc(&tcon
->num_hardlinks
);
1752 cFYI(1, ("Send error in SetPathInfo (hard link) = %d", rc
));
1755 cifs_buf_release(pSMB
);
1757 goto createHardLinkRetry
;
1763 CIFSCreateHardLink(const int xid
, struct cifsTconInfo
*tcon
,
1764 const char *fromName
, const char *toName
,
1765 const struct nls_table
*nls_codepage
, int remap
)
1768 NT_RENAME_REQ
*pSMB
= NULL
;
1769 RENAME_RSP
*pSMBr
= NULL
;
1771 int name_len
, name_len2
;
1774 cFYI(1, ("In CIFSCreateHardLink"));
1775 winCreateHardLinkRetry
:
1777 rc
= smb_init(SMB_COM_NT_RENAME
, 4, tcon
, (void **) &pSMB
,
1782 pSMB
->SearchAttributes
=
1783 cpu_to_le16(ATTR_READONLY
| ATTR_HIDDEN
| ATTR_SYSTEM
|
1785 pSMB
->Flags
= cpu_to_le16(CREATE_HARD_LINK
);
1786 pSMB
->ClusterCount
= 0;
1788 pSMB
->BufferFormat
= 0x04;
1790 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
1792 cifsConvertToUCS((__le16
*) pSMB
->OldFileName
, fromName
,
1793 PATH_MAX
, nls_codepage
, remap
);
1794 name_len
++; /* trailing null */
1796 pSMB
->OldFileName
[name_len
] = 0; /* pad */
1797 pSMB
->OldFileName
[name_len
+ 1] = 0x04;
1799 cifsConvertToUCS((__le16
*)&pSMB
->OldFileName
[name_len
+ 2],
1800 toName
, PATH_MAX
, nls_codepage
, remap
);
1801 name_len2
+= 1 /* trailing null */ + 1 /* Signature word */ ;
1802 name_len2
*= 2; /* convert to bytes */
1803 } else { /* BB improve the check for buffer overruns BB */
1804 name_len
= strnlen(fromName
, PATH_MAX
);
1805 name_len
++; /* trailing null */
1806 strncpy(pSMB
->OldFileName
, fromName
, name_len
);
1807 name_len2
= strnlen(toName
, PATH_MAX
);
1808 name_len2
++; /* trailing null */
1809 pSMB
->OldFileName
[name_len
] = 0x04; /* 2nd buffer format */
1810 strncpy(&pSMB
->OldFileName
[name_len
+ 1], toName
, name_len2
);
1811 name_len2
++; /* trailing null */
1812 name_len2
++; /* signature byte */
1815 count
= 1 /* string type byte */ + name_len
+ name_len2
;
1816 pSMB
->hdr
.smb_buf_length
+= count
;
1817 pSMB
->ByteCount
= cpu_to_le16(count
);
1819 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
1820 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
1821 cifs_stats_inc(&tcon
->num_hardlinks
);
1823 cFYI(1, ("Send error in hard link (NT rename) = %d", rc
));
1825 cifs_buf_release(pSMB
);
1827 goto winCreateHardLinkRetry
;
1833 CIFSSMBUnixQuerySymLink(const int xid
, struct cifsTconInfo
*tcon
,
1834 const unsigned char *searchName
,
1835 char *symlinkinfo
, const int buflen
,
1836 const struct nls_table
*nls_codepage
)
1838 /* SMB_QUERY_FILE_UNIX_LINK */
1839 TRANSACTION2_QPI_REQ
*pSMB
= NULL
;
1840 TRANSACTION2_QPI_RSP
*pSMBr
= NULL
;
1844 __u16 params
, byte_count
;
1846 cFYI(1, ("In QPathSymLinkInfo (Unix) for path %s", searchName
));
1849 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
1854 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
1856 cifs_strtoUCS((__le16
*) pSMB
->FileName
, searchName
, PATH_MAX
1857 /* find define for this maxpathcomponent */
1859 name_len
++; /* trailing null */
1861 } else { /* BB improve the check for buffer overruns BB */
1862 name_len
= strnlen(searchName
, PATH_MAX
);
1863 name_len
++; /* trailing null */
1864 strncpy(pSMB
->FileName
, searchName
, name_len
);
1867 params
= 2 /* level */ + 4 /* rsrvd */ + name_len
/* incl null */ ;
1868 pSMB
->TotalDataCount
= 0;
1869 pSMB
->MaxParameterCount
= cpu_to_le16(2);
1870 /* BB find exact max data count below from sess structure BB */
1871 pSMB
->MaxDataCount
= cpu_to_le16(4000);
1872 pSMB
->MaxSetupCount
= 0;
1876 pSMB
->Reserved2
= 0;
1877 pSMB
->ParameterOffset
= cpu_to_le16(offsetof(
1878 struct smb_com_transaction2_qpi_req
,InformationLevel
) - 4);
1879 pSMB
->DataCount
= 0;
1880 pSMB
->DataOffset
= 0;
1881 pSMB
->SetupCount
= 1;
1882 pSMB
->Reserved3
= 0;
1883 pSMB
->SubCommand
= cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION
);
1884 byte_count
= params
+ 1 /* pad */ ;
1885 pSMB
->TotalParameterCount
= cpu_to_le16(params
);
1886 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
1887 pSMB
->InformationLevel
= cpu_to_le16(SMB_QUERY_FILE_UNIX_LINK
);
1888 pSMB
->Reserved4
= 0;
1889 pSMB
->hdr
.smb_buf_length
+= byte_count
;
1890 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
1892 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
1893 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
1895 cFYI(1, ("Send error in QuerySymLinkInfo = %d", rc
));
1897 /* decode response */
1899 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
1900 if (rc
|| (pSMBr
->ByteCount
< 2))
1901 /* BB also check enough total bytes returned */
1902 rc
= -EIO
; /* bad smb */
1904 __u16 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
1905 __u16 count
= le16_to_cpu(pSMBr
->t2
.DataCount
);
1907 if (pSMBr
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
1908 name_len
= UniStrnlen((wchar_t *) ((char *)
1909 &pSMBr
->hdr
.Protocol
+data_offset
),
1910 min_t(const int, buflen
,count
) / 2);
1911 /* BB FIXME investigate remapping reserved chars here */
1912 cifs_strfromUCS_le(symlinkinfo
,
1913 (__le16
*) ((char *)&pSMBr
->hdr
.Protocol
+
1915 name_len
, nls_codepage
);
1917 strncpy(symlinkinfo
,
1918 (char *) &pSMBr
->hdr
.Protocol
+
1920 min_t(const int, buflen
, count
));
1922 symlinkinfo
[buflen
] = 0;
1923 /* just in case so calling code does not go off the end of buffer */
1926 cifs_buf_release(pSMB
);
1928 goto querySymLinkRetry
;
1932 /* Initialize NT TRANSACT SMB into small smb request buffer.
1933 This assumes that all NT TRANSACTS that we init here have
1934 total parm and data under about 400 bytes (to fit in small cifs
1935 buffer size), which is the case so far, it easily fits. NB:
1936 Setup words themselves and ByteCount
1937 MaxSetupCount (size of returned setup area) and
1938 MaxParameterCount (returned parms size) must be set by caller */
1940 smb_init_ntransact(const __u16 sub_command
, const int setup_count
,
1941 const int parm_len
, struct cifsTconInfo
*tcon
,
1946 struct smb_com_ntransact_req
* pSMB
;
1948 rc
= small_smb_init(SMB_COM_NT_TRANSACT
, 19 + setup_count
, tcon
,
1952 *ret_buf
= (void *)pSMB
;
1954 pSMB
->TotalParameterCount
= cpu_to_le32(parm_len
);
1955 pSMB
->TotalDataCount
= 0;
1956 pSMB
->MaxDataCount
= cpu_to_le32((tcon
->ses
->server
->maxBuf
-
1957 MAX_CIFS_HDR_SIZE
) & 0xFFFFFF00);
1958 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
1959 pSMB
->DataCount
= pSMB
->TotalDataCount
;
1960 temp_offset
= offsetof(struct smb_com_ntransact_req
, Parms
) +
1961 (setup_count
* 2) - 4 /* for rfc1001 length itself */;
1962 pSMB
->ParameterOffset
= cpu_to_le32(temp_offset
);
1963 pSMB
->DataOffset
= cpu_to_le32(temp_offset
+ parm_len
);
1964 pSMB
->SetupCount
= setup_count
; /* no need to le convert byte fields */
1965 pSMB
->SubCommand
= cpu_to_le16(sub_command
);
1970 validate_ntransact(char * buf
, char ** ppparm
, char ** ppdata
,
1971 int * pdatalen
, int * pparmlen
)
1974 __u32 data_count
, data_offset
, parm_count
, parm_offset
;
1975 struct smb_com_ntransact_rsp
* pSMBr
;
1980 pSMBr
= (struct smb_com_ntransact_rsp
*)buf
;
1982 /* ByteCount was converted from little endian in SendReceive */
1983 end_of_smb
= 2 /* sizeof byte count */ + pSMBr
->ByteCount
+
1984 (char *)&pSMBr
->ByteCount
;
1987 data_offset
= le32_to_cpu(pSMBr
->DataOffset
);
1988 data_count
= le32_to_cpu(pSMBr
->DataCount
);
1989 parm_offset
= le32_to_cpu(pSMBr
->ParameterOffset
);
1990 parm_count
= le32_to_cpu(pSMBr
->ParameterCount
);
1992 *ppparm
= (char *)&pSMBr
->hdr
.Protocol
+ parm_offset
;
1993 *ppdata
= (char *)&pSMBr
->hdr
.Protocol
+ data_offset
;
1995 /* should we also check that parm and data areas do not overlap? */
1996 if(*ppparm
> end_of_smb
) {
1997 cFYI(1,("parms start after end of smb"));
1999 } else if(parm_count
+ *ppparm
> end_of_smb
) {
2000 cFYI(1,("parm end after end of smb"));
2002 } else if(*ppdata
> end_of_smb
) {
2003 cFYI(1,("data starts after end of smb"));
2005 } else if(data_count
+ *ppdata
> end_of_smb
) {
2006 cFYI(1,("data %p + count %d (%p) ends after end of smb %p start %p",
2007 *ppdata
, data_count
, (data_count
+ *ppdata
), end_of_smb
, pSMBr
)); /* BB FIXME */
2009 } else if(parm_count
+ data_count
> pSMBr
->ByteCount
) {
2010 cFYI(1,("parm count and data count larger than SMB"));
2017 CIFSSMBQueryReparseLinkInfo(const int xid
, struct cifsTconInfo
*tcon
,
2018 const unsigned char *searchName
,
2019 char *symlinkinfo
, const int buflen
,__u16 fid
,
2020 const struct nls_table
*nls_codepage
)
2025 struct smb_com_transaction_ioctl_req
* pSMB
;
2026 struct smb_com_transaction_ioctl_rsp
* pSMBr
;
2028 cFYI(1, ("In Windows reparse style QueryLink for path %s", searchName
));
2029 rc
= smb_init(SMB_COM_NT_TRANSACT
, 23, tcon
, (void **) &pSMB
,
2034 pSMB
->TotalParameterCount
= 0 ;
2035 pSMB
->TotalDataCount
= 0;
2036 pSMB
->MaxParameterCount
= cpu_to_le32(2);
2037 /* BB find exact data count max from sess structure BB */
2038 pSMB
->MaxDataCount
= cpu_to_le32((tcon
->ses
->server
->maxBuf
-
2039 MAX_CIFS_HDR_SIZE
) & 0xFFFFFF00);
2040 pSMB
->MaxSetupCount
= 4;
2042 pSMB
->ParameterOffset
= 0;
2043 pSMB
->DataCount
= 0;
2044 pSMB
->DataOffset
= 0;
2045 pSMB
->SetupCount
= 4;
2046 pSMB
->SubCommand
= cpu_to_le16(NT_TRANSACT_IOCTL
);
2047 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
2048 pSMB
->FunctionCode
= cpu_to_le32(FSCTL_GET_REPARSE_POINT
);
2049 pSMB
->IsFsctl
= 1; /* FSCTL */
2050 pSMB
->IsRootFlag
= 0;
2051 pSMB
->Fid
= fid
; /* file handle always le */
2052 pSMB
->ByteCount
= 0;
2054 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
2055 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
2057 cFYI(1, ("Send error in QueryReparseLinkInfo = %d", rc
));
2058 } else { /* decode response */
2059 __u32 data_offset
= le32_to_cpu(pSMBr
->DataOffset
);
2060 __u32 data_count
= le32_to_cpu(pSMBr
->DataCount
);
2061 if ((pSMBr
->ByteCount
< 2) || (data_offset
> 512))
2062 /* BB also check enough total bytes returned */
2063 rc
= -EIO
; /* bad smb */
2065 if(data_count
&& (data_count
< 2048)) {
2066 char * end_of_smb
= 2 /* sizeof byte count */ +
2068 (char *)&pSMBr
->ByteCount
;
2070 struct reparse_data
* reparse_buf
= (struct reparse_data
*)
2071 ((char *)&pSMBr
->hdr
.Protocol
+ data_offset
);
2072 if((char*)reparse_buf
>= end_of_smb
) {
2076 if((reparse_buf
->LinkNamesBuf
+
2077 reparse_buf
->TargetNameOffset
+
2078 reparse_buf
->TargetNameLen
) >
2080 cFYI(1,("reparse buf extended beyond SMB"));
2085 if (pSMBr
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
2086 name_len
= UniStrnlen((wchar_t *)
2087 (reparse_buf
->LinkNamesBuf
+
2088 reparse_buf
->TargetNameOffset
),
2089 min(buflen
/2, reparse_buf
->TargetNameLen
/ 2));
2090 cifs_strfromUCS_le(symlinkinfo
,
2091 (__le16
*) (reparse_buf
->LinkNamesBuf
+
2092 reparse_buf
->TargetNameOffset
),
2093 name_len
, nls_codepage
);
2094 } else { /* ASCII names */
2095 strncpy(symlinkinfo
,reparse_buf
->LinkNamesBuf
+
2096 reparse_buf
->TargetNameOffset
,
2097 min_t(const int, buflen
, reparse_buf
->TargetNameLen
));
2101 cFYI(1,("Invalid return data count on get reparse info ioctl"));
2103 symlinkinfo
[buflen
] = 0; /* just in case so the caller
2104 does not go off the end of the buffer */
2105 cFYI(1,("readlink result - %s ",symlinkinfo
));
2109 cifs_buf_release(pSMB
);
2111 /* Note: On -EAGAIN error only caller can retry on handle based calls
2112 since file handle passed in no longer valid */
2117 #ifdef CONFIG_CIFS_POSIX
2119 /*Convert an Access Control Entry from wire format to local POSIX xattr format*/
2120 static void cifs_convert_ace(posix_acl_xattr_entry
* ace
, struct cifs_posix_ace
* cifs_ace
)
2122 /* u8 cifs fields do not need le conversion */
2123 ace
->e_perm
= cpu_to_le16(cifs_ace
->cifs_e_perm
);
2124 ace
->e_tag
= cpu_to_le16(cifs_ace
->cifs_e_tag
);
2125 ace
->e_id
= cpu_to_le32(le64_to_cpu(cifs_ace
->cifs_uid
));
2126 /* cFYI(1,("perm %d tag %d id %d",ace->e_perm,ace->e_tag,ace->e_id)); */
2131 /* Convert ACL from CIFS POSIX wire format to local Linux POSIX ACL xattr */
2132 static int cifs_copy_posix_acl(char * trgt
,char * src
, const int buflen
,
2133 const int acl_type
,const int size_of_data_area
)
2138 struct cifs_posix_ace
* pACE
;
2139 struct cifs_posix_acl
* cifs_acl
= (struct cifs_posix_acl
*)src
;
2140 posix_acl_xattr_header
* local_acl
= (posix_acl_xattr_header
*)trgt
;
2142 if (le16_to_cpu(cifs_acl
->version
) != CIFS_ACL_VERSION
)
2145 if(acl_type
& ACL_TYPE_ACCESS
) {
2146 count
= le16_to_cpu(cifs_acl
->access_entry_count
);
2147 pACE
= &cifs_acl
->ace_array
[0];
2148 size
= sizeof(struct cifs_posix_acl
);
2149 size
+= sizeof(struct cifs_posix_ace
) * count
;
2150 /* check if we would go beyond end of SMB */
2151 if(size_of_data_area
< size
) {
2152 cFYI(1,("bad CIFS POSIX ACL size %d vs. %d",size_of_data_area
,size
));
2155 } else if(acl_type
& ACL_TYPE_DEFAULT
) {
2156 count
= le16_to_cpu(cifs_acl
->access_entry_count
);
2157 size
= sizeof(struct cifs_posix_acl
);
2158 size
+= sizeof(struct cifs_posix_ace
) * count
;
2159 /* skip past access ACEs to get to default ACEs */
2160 pACE
= &cifs_acl
->ace_array
[count
];
2161 count
= le16_to_cpu(cifs_acl
->default_entry_count
);
2162 size
+= sizeof(struct cifs_posix_ace
) * count
;
2163 /* check if we would go beyond end of SMB */
2164 if(size_of_data_area
< size
)
2171 size
= posix_acl_xattr_size(count
);
2172 if((buflen
== 0) || (local_acl
== NULL
)) {
2173 /* used to query ACL EA size */
2174 } else if(size
> buflen
) {
2176 } else /* buffer big enough */ {
2177 local_acl
->a_version
= cpu_to_le32(POSIX_ACL_XATTR_VERSION
);
2178 for(i
= 0;i
< count
;i
++) {
2179 cifs_convert_ace(&local_acl
->a_entries
[i
],pACE
);
2186 static __u16
convert_ace_to_cifs_ace(struct cifs_posix_ace
* cifs_ace
,
2187 const posix_acl_xattr_entry
* local_ace
)
2189 __u16 rc
= 0; /* 0 = ACL converted ok */
2191 cifs_ace
->cifs_e_perm
= le16_to_cpu(local_ace
->e_perm
);
2192 cifs_ace
->cifs_e_tag
= le16_to_cpu(local_ace
->e_tag
);
2193 /* BB is there a better way to handle the large uid? */
2194 if(local_ace
->e_id
== cpu_to_le32(-1)) {
2195 /* Probably no need to le convert -1 on any arch but can not hurt */
2196 cifs_ace
->cifs_uid
= cpu_to_le64(-1);
2198 cifs_ace
->cifs_uid
= cpu_to_le64(le32_to_cpu(local_ace
->e_id
));
2199 /*cFYI(1,("perm %d tag %d id %d",ace->e_perm,ace->e_tag,ace->e_id));*/
2203 /* Convert ACL from local Linux POSIX xattr to CIFS POSIX ACL wire format */
2204 static __u16
ACL_to_cifs_posix(char * parm_data
,const char * pACL
,const int buflen
,
2208 struct cifs_posix_acl
* cifs_acl
= (struct cifs_posix_acl
*)parm_data
;
2209 posix_acl_xattr_header
* local_acl
= (posix_acl_xattr_header
*)pACL
;
2213 if((buflen
== 0) || (pACL
== NULL
) || (cifs_acl
== NULL
))
2216 count
= posix_acl_xattr_count((size_t)buflen
);
2217 cFYI(1,("setting acl with %d entries from buf of length %d and version of %d",
2218 count
, buflen
, le32_to_cpu(local_acl
->a_version
)));
2219 if(le32_to_cpu(local_acl
->a_version
) != 2) {
2220 cFYI(1,("unknown POSIX ACL version %d",
2221 le32_to_cpu(local_acl
->a_version
)));
2224 cifs_acl
->version
= cpu_to_le16(1);
2225 if(acl_type
== ACL_TYPE_ACCESS
)
2226 cifs_acl
->access_entry_count
= cpu_to_le16(count
);
2227 else if(acl_type
== ACL_TYPE_DEFAULT
)
2228 cifs_acl
->default_entry_count
= cpu_to_le16(count
);
2230 cFYI(1,("unknown ACL type %d",acl_type
));
2233 for(i
=0;i
<count
;i
++) {
2234 rc
= convert_ace_to_cifs_ace(&cifs_acl
->ace_array
[i
],
2235 &local_acl
->a_entries
[i
]);
2237 /* ACE not converted */
2242 rc
= (__u16
)(count
* sizeof(struct cifs_posix_ace
));
2243 rc
+= sizeof(struct cifs_posix_acl
);
2244 /* BB add check to make sure ACL does not overflow SMB */
2250 CIFSSMBGetPosixACL(const int xid
, struct cifsTconInfo
*tcon
,
2251 const unsigned char *searchName
,
2252 char *acl_inf
, const int buflen
, const int acl_type
,
2253 const struct nls_table
*nls_codepage
, int remap
)
2255 /* SMB_QUERY_POSIX_ACL */
2256 TRANSACTION2_QPI_REQ
*pSMB
= NULL
;
2257 TRANSACTION2_QPI_RSP
*pSMBr
= NULL
;
2261 __u16 params
, byte_count
;
2263 cFYI(1, ("In GetPosixACL (Unix) for path %s", searchName
));
2266 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
2271 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
2273 cifsConvertToUCS((__le16
*) pSMB
->FileName
, searchName
,
2274 PATH_MAX
, nls_codepage
, remap
);
2275 name_len
++; /* trailing null */
2277 pSMB
->FileName
[name_len
] = 0;
2278 pSMB
->FileName
[name_len
+1] = 0;
2279 } else { /* BB improve the check for buffer overruns BB */
2280 name_len
= strnlen(searchName
, PATH_MAX
);
2281 name_len
++; /* trailing null */
2282 strncpy(pSMB
->FileName
, searchName
, name_len
);
2285 params
= 2 /* level */ + 4 /* rsrvd */ + name_len
/* incl null */ ;
2286 pSMB
->TotalDataCount
= 0;
2287 pSMB
->MaxParameterCount
= cpu_to_le16(2);
2288 /* BB find exact max data count below from sess structure BB */
2289 pSMB
->MaxDataCount
= cpu_to_le16(4000);
2290 pSMB
->MaxSetupCount
= 0;
2294 pSMB
->Reserved2
= 0;
2295 pSMB
->ParameterOffset
= cpu_to_le16(
2296 offsetof(struct smb_com_transaction2_qpi_req
,InformationLevel
) - 4);
2297 pSMB
->DataCount
= 0;
2298 pSMB
->DataOffset
= 0;
2299 pSMB
->SetupCount
= 1;
2300 pSMB
->Reserved3
= 0;
2301 pSMB
->SubCommand
= cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION
);
2302 byte_count
= params
+ 1 /* pad */ ;
2303 pSMB
->TotalParameterCount
= cpu_to_le16(params
);
2304 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
2305 pSMB
->InformationLevel
= cpu_to_le16(SMB_QUERY_POSIX_ACL
);
2306 pSMB
->Reserved4
= 0;
2307 pSMB
->hdr
.smb_buf_length
+= byte_count
;
2308 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
2310 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
2311 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
2312 cifs_stats_inc(&tcon
->num_acl_get
);
2314 cFYI(1, ("Send error in Query POSIX ACL = %d", rc
));
2316 /* decode response */
2318 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
2319 if (rc
|| (pSMBr
->ByteCount
< 2))
2320 /* BB also check enough total bytes returned */
2321 rc
= -EIO
; /* bad smb */
2323 __u16 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
2324 __u16 count
= le16_to_cpu(pSMBr
->t2
.DataCount
);
2325 rc
= cifs_copy_posix_acl(acl_inf
,
2326 (char *)&pSMBr
->hdr
.Protocol
+data_offset
,
2327 buflen
,acl_type
,count
);
2330 cifs_buf_release(pSMB
);
2337 CIFSSMBSetPosixACL(const int xid
, struct cifsTconInfo
*tcon
,
2338 const unsigned char *fileName
,
2339 const char *local_acl
, const int buflen
,
2341 const struct nls_table
*nls_codepage
, int remap
)
2343 struct smb_com_transaction2_spi_req
*pSMB
= NULL
;
2344 struct smb_com_transaction2_spi_rsp
*pSMBr
= NULL
;
2348 int bytes_returned
= 0;
2349 __u16 params
, byte_count
, data_count
, param_offset
, offset
;
2351 cFYI(1, ("In SetPosixACL (Unix) for path %s", fileName
));
2353 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
2357 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
2359 cifsConvertToUCS((__le16
*) pSMB
->FileName
, fileName
,
2360 PATH_MAX
, nls_codepage
, remap
);
2361 name_len
++; /* trailing null */
2363 } else { /* BB improve the check for buffer overruns BB */
2364 name_len
= strnlen(fileName
, PATH_MAX
);
2365 name_len
++; /* trailing null */
2366 strncpy(pSMB
->FileName
, fileName
, name_len
);
2368 params
= 6 + name_len
;
2369 pSMB
->MaxParameterCount
= cpu_to_le16(2);
2370 pSMB
->MaxDataCount
= cpu_to_le16(1000); /* BB find max SMB size from sess */
2371 pSMB
->MaxSetupCount
= 0;
2375 pSMB
->Reserved2
= 0;
2376 param_offset
= offsetof(struct smb_com_transaction2_spi_req
,
2377 InformationLevel
) - 4;
2378 offset
= param_offset
+ params
;
2379 parm_data
= ((char *) &pSMB
->hdr
.Protocol
) + offset
;
2380 pSMB
->ParameterOffset
= cpu_to_le16(param_offset
);
2382 /* convert to on the wire format for POSIX ACL */
2383 data_count
= ACL_to_cifs_posix(parm_data
,local_acl
,buflen
,acl_type
);
2385 if(data_count
== 0) {
2387 goto setACLerrorExit
;
2389 pSMB
->DataOffset
= cpu_to_le16(offset
);
2390 pSMB
->SetupCount
= 1;
2391 pSMB
->Reserved3
= 0;
2392 pSMB
->SubCommand
= cpu_to_le16(TRANS2_SET_PATH_INFORMATION
);
2393 pSMB
->InformationLevel
= cpu_to_le16(SMB_SET_POSIX_ACL
);
2394 byte_count
= 3 /* pad */ + params
+ data_count
;
2395 pSMB
->DataCount
= cpu_to_le16(data_count
);
2396 pSMB
->TotalDataCount
= pSMB
->DataCount
;
2397 pSMB
->ParameterCount
= cpu_to_le16(params
);
2398 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
2399 pSMB
->Reserved4
= 0;
2400 pSMB
->hdr
.smb_buf_length
+= byte_count
;
2401 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
2402 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
2403 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
2405 cFYI(1, ("Set POSIX ACL returned %d", rc
));
2409 cifs_buf_release(pSMB
);
2415 /* BB fix tabs in this function FIXME BB */
2417 CIFSGetExtAttr(const int xid
, struct cifsTconInfo
*tcon
,
2418 const int netfid
, __u64
* pExtAttrBits
, __u64
*pMask
)
2421 struct smb_t2_qfi_req
*pSMB
= NULL
;
2422 struct smb_t2_qfi_rsp
*pSMBr
= NULL
;
2424 __u16 params
, byte_count
;
2426 cFYI(1,("In GetExtAttr"));
2431 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
2436 params
= 2 /* level */ +2 /* fid */;
2437 pSMB
->t2
.TotalDataCount
= 0;
2438 pSMB
->t2
.MaxParameterCount
= cpu_to_le16(4);
2439 /* BB find exact max data count below from sess structure BB */
2440 pSMB
->t2
.MaxDataCount
= cpu_to_le16(4000);
2441 pSMB
->t2
.MaxSetupCount
= 0;
2442 pSMB
->t2
.Reserved
= 0;
2444 pSMB
->t2
.Timeout
= 0;
2445 pSMB
->t2
.Reserved2
= 0;
2446 pSMB
->t2
.ParameterOffset
= cpu_to_le16(offsetof(struct smb_t2_qfi_req
,
2448 pSMB
->t2
.DataCount
= 0;
2449 pSMB
->t2
.DataOffset
= 0;
2450 pSMB
->t2
.SetupCount
= 1;
2451 pSMB
->t2
.Reserved3
= 0;
2452 pSMB
->t2
.SubCommand
= cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION
);
2453 byte_count
= params
+ 1 /* pad */ ;
2454 pSMB
->t2
.TotalParameterCount
= cpu_to_le16(params
);
2455 pSMB
->t2
.ParameterCount
= pSMB
->t2
.TotalParameterCount
;
2456 pSMB
->InformationLevel
= cpu_to_le16(SMB_QUERY_ATTR_FLAGS
);
2459 pSMB
->hdr
.smb_buf_length
+= byte_count
;
2460 pSMB
->t2
.ByteCount
= cpu_to_le16(byte_count
);
2462 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
2463 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
2465 cFYI(1, ("error %d in GetExtAttr", rc
));
2467 /* decode response */
2468 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
2469 if (rc
|| (pSMBr
->ByteCount
< 2))
2470 /* BB also check enough total bytes returned */
2471 /* If rc should we check for EOPNOSUPP and
2472 disable the srvino flag? or in caller? */
2473 rc
= -EIO
; /* bad smb */
2475 __u16 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
2476 __u16 count
= le16_to_cpu(pSMBr
->t2
.DataCount
);
2477 struct file_chattr_info
* pfinfo
;
2478 /* BB Do we need a cast or hash here ? */
2480 cFYI(1, ("Illegal size ret in GetExtAttr"));
2484 pfinfo
= (struct file_chattr_info
*)
2485 (data_offset
+ (char *) &pSMBr
->hdr
.Protocol
);
2486 *pExtAttrBits
= le64_to_cpu(pfinfo
->mode
);
2487 *pMask
= le64_to_cpu(pfinfo
->mask
);
2491 cifs_buf_release(pSMB
);
2493 goto GetExtAttrRetry
;
2498 #endif /* CONFIG_POSIX */
2501 /* security id for everyone */
2502 const struct cifs_sid sid_everyone
= {1, 1, {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0}};
2504 const struct cifs_sid sid_user
= {1, 2 , {0, 0, 0, 0, 0, 5}, {32, 545, 0, 0}};
2506 /* Convert CIFS ACL to POSIX form */
2507 static int parse_sec_desc(struct cifs_sid
* psec_desc
, int acl_len
)
2512 /* Get Security Descriptor (by handle) from remote server for a file or dir */
2514 CIFSSMBGetCIFSACL(const int xid
, struct cifsTconInfo
*tcon
, __u16 fid
,
2515 /* BB fix up return info */ char *acl_inf
, const int buflen
,
2516 const int acl_type
/* ACCESS/DEFAULT not sure implication */)
2520 QUERY_SEC_DESC_REQ
* pSMB
;
2523 cFYI(1, ("GetCifsACL"));
2525 rc
= smb_init_ntransact(NT_TRANSACT_QUERY_SECURITY_DESC
, 0,
2526 8 /* parm len */, tcon
, (void **) &pSMB
);
2530 pSMB
->MaxParameterCount
= cpu_to_le32(4);
2531 /* BB TEST with big acls that might need to be e.g. larger than 16K */
2532 pSMB
->MaxSetupCount
= 0;
2533 pSMB
->Fid
= fid
; /* file handle always le */
2534 pSMB
->AclFlags
= cpu_to_le32(CIFS_ACL_OWNER
| CIFS_ACL_GROUP
|
2536 pSMB
->ByteCount
= cpu_to_le16(11); /* 3 bytes pad + 8 bytes parm */
2537 pSMB
->hdr
.smb_buf_length
+= 11;
2538 iov
[0].iov_base
= (char *)pSMB
;
2539 iov
[0].iov_len
= pSMB
->hdr
.smb_buf_length
+ 4;
2541 rc
= SendReceive2(xid
, tcon
->ses
, iov
, 1 /* num iovec */, &buf_type
, 0);
2542 cifs_stats_inc(&tcon
->num_acl_get
);
2544 cFYI(1, ("Send error in QuerySecDesc = %d", rc
));
2545 } else { /* decode response */
2546 struct cifs_sid
* psec_desc
;
2551 struct smb_com_ntransact_rsp
* pSMBr
;
2553 /* validate_nttransact */
2554 rc
= validate_ntransact(iov
[0].iov_base
, (char **)&parm
,
2555 (char **)&psec_desc
,
2556 &parm_len
, &data_len
);
2560 pSMBr
= (struct smb_com_ntransact_rsp
*)iov
[0].iov_base
;
2562 cERROR(1,("smb %p parm %p data %p",pSMBr
,parm
,psec_desc
)); /* BB removeme BB */
2564 if (le32_to_cpu(pSMBr
->ParameterCount
) != 4) {
2565 rc
= -EIO
; /* bad smb */
2569 /* BB check that data area is minimum length and as big as acl_len */
2571 acl_len
= le32_to_cpu(*(__le32
*)parm
);
2572 /* BB check if(acl_len > bufsize) */
2574 parse_sec_desc(psec_desc
, acl_len
);
2577 if(buf_type
== CIFS_SMALL_BUFFER
)
2578 cifs_small_buf_release(iov
[0].iov_base
);
2579 else if(buf_type
== CIFS_LARGE_BUFFER
)
2580 cifs_buf_release(iov
[0].iov_base
);
2581 cifs_small_buf_release(pSMB
);
2586 /* Legacy Query Path Information call for lookup to old servers such
2588 int SMBQueryInformation(const int xid
, struct cifsTconInfo
*tcon
,
2589 const unsigned char *searchName
,
2590 FILE_ALL_INFO
* pFinfo
,
2591 const struct nls_table
*nls_codepage
, int remap
)
2593 QUERY_INFORMATION_REQ
* pSMB
;
2594 QUERY_INFORMATION_RSP
* pSMBr
;
2599 cFYI(1, ("In SMBQPath path %s", searchName
));
2601 rc
= smb_init(SMB_COM_QUERY_INFORMATION
, 0, tcon
, (void **) &pSMB
,
2606 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
2608 cifsConvertToUCS((__le16
*) pSMB
->FileName
, searchName
,
2609 PATH_MAX
, nls_codepage
, remap
);
2610 name_len
++; /* trailing null */
2613 name_len
= strnlen(searchName
, PATH_MAX
);
2614 name_len
++; /* trailing null */
2615 strncpy(pSMB
->FileName
, searchName
, name_len
);
2617 pSMB
->BufferFormat
= 0x04;
2618 name_len
++; /* account for buffer type byte */
2619 pSMB
->hdr
.smb_buf_length
+= (__u16
) name_len
;
2620 pSMB
->ByteCount
= cpu_to_le16(name_len
);
2622 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
2623 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
2625 cFYI(1, ("Send error in QueryInfo = %d", rc
));
2626 } else if (pFinfo
) { /* decode response */
2627 memset(pFinfo
, 0, sizeof(FILE_ALL_INFO
));
2628 pFinfo
->AllocationSize
=
2629 cpu_to_le64(le32_to_cpu(pSMBr
->size
));
2630 pFinfo
->EndOfFile
= pFinfo
->AllocationSize
;
2631 pFinfo
->Attributes
=
2632 cpu_to_le32(le16_to_cpu(pSMBr
->attr
));
2634 rc
= -EIO
; /* bad buffer passed in */
2636 cifs_buf_release(pSMB
);
2648 CIFSSMBQPathInfo(const int xid
, struct cifsTconInfo
*tcon
,
2649 const unsigned char *searchName
,
2650 FILE_ALL_INFO
* pFindData
,
2651 const struct nls_table
*nls_codepage
, int remap
)
2653 /* level 263 SMB_QUERY_FILE_ALL_INFO */
2654 TRANSACTION2_QPI_REQ
*pSMB
= NULL
;
2655 TRANSACTION2_QPI_RSP
*pSMBr
= NULL
;
2659 __u16 params
, byte_count
;
2661 /* cFYI(1, ("In QPathInfo path %s", searchName)); */
2663 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
2668 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
2670 cifsConvertToUCS((__le16
*) pSMB
->FileName
, searchName
,
2671 PATH_MAX
, nls_codepage
, remap
);
2672 name_len
++; /* trailing null */
2674 } else { /* BB improve the check for buffer overruns BB */
2675 name_len
= strnlen(searchName
, PATH_MAX
);
2676 name_len
++; /* trailing null */
2677 strncpy(pSMB
->FileName
, searchName
, name_len
);
2680 params
= 2 /* level */ + 4 /* reserved */ + name_len
/* includes NUL */ ;
2681 pSMB
->TotalDataCount
= 0;
2682 pSMB
->MaxParameterCount
= cpu_to_le16(2);
2683 pSMB
->MaxDataCount
= cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
2684 pSMB
->MaxSetupCount
= 0;
2688 pSMB
->Reserved2
= 0;
2689 pSMB
->ParameterOffset
= cpu_to_le16(offsetof(
2690 struct smb_com_transaction2_qpi_req
,InformationLevel
) - 4);
2691 pSMB
->DataCount
= 0;
2692 pSMB
->DataOffset
= 0;
2693 pSMB
->SetupCount
= 1;
2694 pSMB
->Reserved3
= 0;
2695 pSMB
->SubCommand
= cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION
);
2696 byte_count
= params
+ 1 /* pad */ ;
2697 pSMB
->TotalParameterCount
= cpu_to_le16(params
);
2698 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
2699 pSMB
->InformationLevel
= cpu_to_le16(SMB_QUERY_FILE_ALL_INFO
);
2700 pSMB
->Reserved4
= 0;
2701 pSMB
->hdr
.smb_buf_length
+= byte_count
;
2702 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
2704 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
2705 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
2707 cFYI(1, ("Send error in QPathInfo = %d", rc
));
2708 } else { /* decode response */
2709 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
2711 if (rc
|| (pSMBr
->ByteCount
< 40))
2712 rc
= -EIO
; /* bad smb */
2713 else if (pFindData
){
2714 __u16 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
2715 memcpy((char *) pFindData
,
2716 (char *) &pSMBr
->hdr
.Protocol
+
2717 data_offset
, sizeof (FILE_ALL_INFO
));
2721 cifs_buf_release(pSMB
);
2723 goto QPathInfoRetry
;
2729 CIFSSMBUnixQPathInfo(const int xid
, struct cifsTconInfo
*tcon
,
2730 const unsigned char *searchName
,
2731 FILE_UNIX_BASIC_INFO
* pFindData
,
2732 const struct nls_table
*nls_codepage
, int remap
)
2734 /* SMB_QUERY_FILE_UNIX_BASIC */
2735 TRANSACTION2_QPI_REQ
*pSMB
= NULL
;
2736 TRANSACTION2_QPI_RSP
*pSMBr
= NULL
;
2738 int bytes_returned
= 0;
2740 __u16 params
, byte_count
;
2742 cFYI(1, ("In QPathInfo (Unix) the path %s", searchName
));
2744 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
2749 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
2751 cifsConvertToUCS((__le16
*) pSMB
->FileName
, searchName
,
2752 PATH_MAX
, nls_codepage
, remap
);
2753 name_len
++; /* trailing null */
2755 } else { /* BB improve the check for buffer overruns BB */
2756 name_len
= strnlen(searchName
, PATH_MAX
);
2757 name_len
++; /* trailing null */
2758 strncpy(pSMB
->FileName
, searchName
, name_len
);
2761 params
= 2 /* level */ + 4 /* reserved */ + name_len
/* includes NUL */ ;
2762 pSMB
->TotalDataCount
= 0;
2763 pSMB
->MaxParameterCount
= cpu_to_le16(2);
2764 /* BB find exact max SMB PDU from sess structure BB */
2765 pSMB
->MaxDataCount
= cpu_to_le16(4000);
2766 pSMB
->MaxSetupCount
= 0;
2770 pSMB
->Reserved2
= 0;
2771 pSMB
->ParameterOffset
= cpu_to_le16(offsetof(
2772 struct smb_com_transaction2_qpi_req
,InformationLevel
) - 4);
2773 pSMB
->DataCount
= 0;
2774 pSMB
->DataOffset
= 0;
2775 pSMB
->SetupCount
= 1;
2776 pSMB
->Reserved3
= 0;
2777 pSMB
->SubCommand
= cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION
);
2778 byte_count
= params
+ 1 /* pad */ ;
2779 pSMB
->TotalParameterCount
= cpu_to_le16(params
);
2780 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
2781 pSMB
->InformationLevel
= cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC
);
2782 pSMB
->Reserved4
= 0;
2783 pSMB
->hdr
.smb_buf_length
+= byte_count
;
2784 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
2786 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
2787 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
2789 cFYI(1, ("Send error in QPathInfo = %d", rc
));
2790 } else { /* decode response */
2791 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
2793 if (rc
|| (pSMBr
->ByteCount
< sizeof(FILE_UNIX_BASIC_INFO
))) {
2794 rc
= -EIO
; /* bad smb */
2796 __u16 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
2797 memcpy((char *) pFindData
,
2798 (char *) &pSMBr
->hdr
.Protocol
+
2800 sizeof (FILE_UNIX_BASIC_INFO
));
2803 cifs_buf_release(pSMB
);
2805 goto UnixQPathInfoRetry
;
2810 #if 0 /* function unused at present */
2811 int CIFSFindSingle(const int xid
, struct cifsTconInfo
*tcon
,
2812 const char *searchName
, FILE_ALL_INFO
* findData
,
2813 const struct nls_table
*nls_codepage
)
2815 /* level 257 SMB_ */
2816 TRANSACTION2_FFIRST_REQ
*pSMB
= NULL
;
2817 TRANSACTION2_FFIRST_RSP
*pSMBr
= NULL
;
2821 __u16 params
, byte_count
;
2823 cFYI(1, ("In FindUnique"));
2825 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
2830 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
2832 cifsConvertToUCS((__le16
*) pSMB
->FileName
, searchName
, PATH_MAX
2833 /* find define for this maxpathcomponent */
2835 name_len
++; /* trailing null */
2837 } else { /* BB improve the check for buffer overruns BB */
2838 name_len
= strnlen(searchName
, PATH_MAX
);
2839 name_len
++; /* trailing null */
2840 strncpy(pSMB
->FileName
, searchName
, name_len
);
2843 params
= 12 + name_len
/* includes null */ ;
2844 pSMB
->TotalDataCount
= 0; /* no EAs */
2845 pSMB
->MaxParameterCount
= cpu_to_le16(2);
2846 pSMB
->MaxDataCount
= cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
2847 pSMB
->MaxSetupCount
= 0;
2851 pSMB
->Reserved2
= 0;
2852 pSMB
->ParameterOffset
= cpu_to_le16(
2853 offsetof(struct smb_com_transaction2_ffirst_req
,InformationLevel
) - 4);
2854 pSMB
->DataCount
= 0;
2855 pSMB
->DataOffset
= 0;
2856 pSMB
->SetupCount
= 1; /* one byte, no need to le convert */
2857 pSMB
->Reserved3
= 0;
2858 pSMB
->SubCommand
= cpu_to_le16(TRANS2_FIND_FIRST
);
2859 byte_count
= params
+ 1 /* pad */ ;
2860 pSMB
->TotalParameterCount
= cpu_to_le16(params
);
2861 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
2862 pSMB
->SearchAttributes
=
2863 cpu_to_le16(ATTR_READONLY
| ATTR_HIDDEN
| ATTR_SYSTEM
|
2865 pSMB
->SearchCount
= cpu_to_le16(16); /* BB increase */
2866 pSMB
->SearchFlags
= cpu_to_le16(1);
2867 pSMB
->InformationLevel
= cpu_to_le16(SMB_FIND_FILE_DIRECTORY_INFO
);
2868 pSMB
->SearchStorageType
= 0; /* BB what should we set this to? BB */
2869 pSMB
->hdr
.smb_buf_length
+= byte_count
;
2870 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
2872 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
2873 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
2876 cFYI(1, ("Send error in FindFileDirInfo = %d", rc
));
2877 } else { /* decode response */
2878 cifs_stats_inc(&tcon
->num_ffirst
);
2882 cifs_buf_release(pSMB
);
2884 goto findUniqueRetry
;
2888 #endif /* end unused (temporarily) function */
2890 /* xid, tcon, searchName and codepage are input parms, rest are returned */
2892 CIFSFindFirst(const int xid
, struct cifsTconInfo
*tcon
,
2893 const char *searchName
,
2894 const struct nls_table
*nls_codepage
,
2896 struct cifs_search_info
* psrch_inf
, int remap
, const char dirsep
)
2898 /* level 257 SMB_ */
2899 TRANSACTION2_FFIRST_REQ
*pSMB
= NULL
;
2900 TRANSACTION2_FFIRST_RSP
*pSMBr
= NULL
;
2901 T2_FFIRST_RSP_PARMS
* parms
;
2903 int bytes_returned
= 0;
2905 __u16 params
, byte_count
;
2907 cFYI(1, ("In FindFirst for %s",searchName
));
2910 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
2915 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
2917 cifsConvertToUCS((__le16
*) pSMB
->FileName
,searchName
,
2918 PATH_MAX
, nls_codepage
, remap
);
2919 /* We can not add the asterik earlier in case
2920 it got remapped to 0xF03A as if it were part of the
2921 directory name instead of a wildcard */
2923 pSMB
->FileName
[name_len
] = dirsep
;
2924 pSMB
->FileName
[name_len
+1] = 0;
2925 pSMB
->FileName
[name_len
+2] = '*';
2926 pSMB
->FileName
[name_len
+3] = 0;
2927 name_len
+= 4; /* now the trailing null */
2928 pSMB
->FileName
[name_len
] = 0; /* null terminate just in case */
2929 pSMB
->FileName
[name_len
+1] = 0;
2931 } else { /* BB add check for overrun of SMB buf BB */
2932 name_len
= strnlen(searchName
, PATH_MAX
);
2933 /* BB fix here and in unicode clause above ie
2934 if(name_len > buffersize-header)
2935 free buffer exit; BB */
2936 strncpy(pSMB
->FileName
, searchName
, name_len
);
2937 pSMB
->FileName
[name_len
] = dirsep
;
2938 pSMB
->FileName
[name_len
+1] = '*';
2939 pSMB
->FileName
[name_len
+2] = 0;
2943 params
= 12 + name_len
/* includes null */ ;
2944 pSMB
->TotalDataCount
= 0; /* no EAs */
2945 pSMB
->MaxParameterCount
= cpu_to_le16(10);
2946 pSMB
->MaxDataCount
= cpu_to_le16((tcon
->ses
->server
->maxBuf
-
2947 MAX_CIFS_HDR_SIZE
) & 0xFFFFFF00);
2948 pSMB
->MaxSetupCount
= 0;
2952 pSMB
->Reserved2
= 0;
2953 byte_count
= params
+ 1 /* pad */ ;
2954 pSMB
->TotalParameterCount
= cpu_to_le16(params
);
2955 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
2956 pSMB
->ParameterOffset
= cpu_to_le16(
2957 offsetof(struct smb_com_transaction2_ffirst_req
, SearchAttributes
) - 4);
2958 pSMB
->DataCount
= 0;
2959 pSMB
->DataOffset
= 0;
2960 pSMB
->SetupCount
= 1; /* one byte, no need to make endian neutral */
2961 pSMB
->Reserved3
= 0;
2962 pSMB
->SubCommand
= cpu_to_le16(TRANS2_FIND_FIRST
);
2963 pSMB
->SearchAttributes
=
2964 cpu_to_le16(ATTR_READONLY
| ATTR_HIDDEN
| ATTR_SYSTEM
|
2966 pSMB
->SearchCount
= cpu_to_le16(CIFSMaxBufSize
/sizeof(FILE_UNIX_INFO
));
2967 pSMB
->SearchFlags
= cpu_to_le16(CIFS_SEARCH_CLOSE_AT_END
|
2968 CIFS_SEARCH_RETURN_RESUME
);
2969 pSMB
->InformationLevel
= cpu_to_le16(psrch_inf
->info_level
);
2971 /* BB what should we set StorageType to? Does it matter? BB */
2972 pSMB
->SearchStorageType
= 0;
2973 pSMB
->hdr
.smb_buf_length
+= byte_count
;
2974 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
2976 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
2977 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
2978 cifs_stats_inc(&tcon
->num_ffirst
);
2980 if (rc
) {/* BB add logic to retry regular search if Unix search rejected unexpectedly by server */
2981 /* BB Add code to handle unsupported level rc */
2982 cFYI(1, ("Error in FindFirst = %d", rc
));
2985 cifs_buf_release(pSMB
);
2987 /* BB eventually could optimize out free and realloc of buf */
2990 goto findFirstRetry
;
2991 } else { /* decode response */
2992 /* BB remember to free buffer if error BB */
2993 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
2995 if (pSMBr
->hdr
.Flags2
& SMBFLG2_UNICODE
)
2996 psrch_inf
->unicode
= TRUE
;
2998 psrch_inf
->unicode
= FALSE
;
3000 psrch_inf
->ntwrk_buf_start
= (char *)pSMBr
;
3001 psrch_inf
->srch_entries_start
=
3002 (char *) &pSMBr
->hdr
.Protocol
+
3003 le16_to_cpu(pSMBr
->t2
.DataOffset
);
3004 parms
= (T2_FFIRST_RSP_PARMS
*)((char *) &pSMBr
->hdr
.Protocol
+
3005 le16_to_cpu(pSMBr
->t2
.ParameterOffset
));
3007 if(parms
->EndofSearch
)
3008 psrch_inf
->endOfSearch
= TRUE
;
3010 psrch_inf
->endOfSearch
= FALSE
;
3012 psrch_inf
->entries_in_buffer
= le16_to_cpu(parms
->SearchCount
);
3013 psrch_inf
->index_of_last_entry
=
3014 psrch_inf
->entries_in_buffer
;
3015 *pnetfid
= parms
->SearchHandle
;
3017 cifs_buf_release(pSMB
);
3024 int CIFSFindNext(const int xid
, struct cifsTconInfo
*tcon
,
3025 __u16 searchHandle
, struct cifs_search_info
* psrch_inf
)
3027 TRANSACTION2_FNEXT_REQ
*pSMB
= NULL
;
3028 TRANSACTION2_FNEXT_RSP
*pSMBr
= NULL
;
3029 T2_FNEXT_RSP_PARMS
* parms
;
3030 char *response_data
;
3032 int bytes_returned
, name_len
;
3033 __u16 params
, byte_count
;
3035 cFYI(1, ("In FindNext"));
3037 if(psrch_inf
->endOfSearch
== TRUE
)
3040 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
3045 params
= 14; /* includes 2 bytes of null string, converted to LE below */
3047 pSMB
->TotalDataCount
= 0; /* no EAs */
3048 pSMB
->MaxParameterCount
= cpu_to_le16(8);
3049 pSMB
->MaxDataCount
=
3050 cpu_to_le16((tcon
->ses
->server
->maxBuf
- MAX_CIFS_HDR_SIZE
) & 0xFFFFFF00);
3051 pSMB
->MaxSetupCount
= 0;
3055 pSMB
->Reserved2
= 0;
3056 pSMB
->ParameterOffset
= cpu_to_le16(
3057 offsetof(struct smb_com_transaction2_fnext_req
,SearchHandle
) - 4);
3058 pSMB
->DataCount
= 0;
3059 pSMB
->DataOffset
= 0;
3060 pSMB
->SetupCount
= 1;
3061 pSMB
->Reserved3
= 0;
3062 pSMB
->SubCommand
= cpu_to_le16(TRANS2_FIND_NEXT
);
3063 pSMB
->SearchHandle
= searchHandle
; /* always kept as le */
3065 cpu_to_le16(CIFSMaxBufSize
/ sizeof (FILE_UNIX_INFO
));
3066 /* test for Unix extensions */
3067 /* if (tcon->ses->capabilities & CAP_UNIX) {
3068 pSMB->InformationLevel = cpu_to_le16(SMB_FIND_FILE_UNIX);
3069 psrch_inf->info_level = SMB_FIND_FILE_UNIX;
3071 pSMB->InformationLevel =
3072 cpu_to_le16(SMB_FIND_FILE_DIRECTORY_INFO);
3073 psrch_inf->info_level = SMB_FIND_FILE_DIRECTORY_INFO;
3075 pSMB
->InformationLevel
= cpu_to_le16(psrch_inf
->info_level
);
3076 pSMB
->ResumeKey
= psrch_inf
->resume_key
;
3078 cpu_to_le16(CIFS_SEARCH_CLOSE_AT_END
| CIFS_SEARCH_RETURN_RESUME
);
3080 name_len
= psrch_inf
->resume_name_len
;
3082 if(name_len
< PATH_MAX
) {
3083 memcpy(pSMB
->ResumeFileName
, psrch_inf
->presume_name
, name_len
);
3084 byte_count
+= name_len
;
3085 /* 14 byte parm len above enough for 2 byte null terminator */
3086 pSMB
->ResumeFileName
[name_len
] = 0;
3087 pSMB
->ResumeFileName
[name_len
+1] = 0;
3090 goto FNext2_err_exit
;
3092 byte_count
= params
+ 1 /* pad */ ;
3093 pSMB
->TotalParameterCount
= cpu_to_le16(params
);
3094 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
3095 pSMB
->hdr
.smb_buf_length
+= byte_count
;
3096 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
3098 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
3099 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
3100 cifs_stats_inc(&tcon
->num_fnext
);
3103 psrch_inf
->endOfSearch
= TRUE
;
3104 rc
= 0; /* search probably was closed at end of search above */
3106 cFYI(1, ("FindNext returned = %d", rc
));
3107 } else { /* decode response */
3108 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
3111 /* BB fixme add lock for file (srch_info) struct here */
3112 if (pSMBr
->hdr
.Flags2
& SMBFLG2_UNICODE
)
3113 psrch_inf
->unicode
= TRUE
;
3115 psrch_inf
->unicode
= FALSE
;
3116 response_data
= (char *) &pSMBr
->hdr
.Protocol
+
3117 le16_to_cpu(pSMBr
->t2
.ParameterOffset
);
3118 parms
= (T2_FNEXT_RSP_PARMS
*)response_data
;
3119 response_data
= (char *)&pSMBr
->hdr
.Protocol
+
3120 le16_to_cpu(pSMBr
->t2
.DataOffset
);
3121 cifs_buf_release(psrch_inf
->ntwrk_buf_start
);
3122 psrch_inf
->srch_entries_start
= response_data
;
3123 psrch_inf
->ntwrk_buf_start
= (char *)pSMB
;
3124 if(parms
->EndofSearch
)
3125 psrch_inf
->endOfSearch
= TRUE
;
3127 psrch_inf
->endOfSearch
= FALSE
;
3129 psrch_inf
->entries_in_buffer
= le16_to_cpu(parms
->SearchCount
);
3130 psrch_inf
->index_of_last_entry
+=
3131 psrch_inf
->entries_in_buffer
;
3132 /* cFYI(1,("fnxt2 entries in buf %d index_of_last %d",psrch_inf->entries_in_buffer,psrch_inf->index_of_last_entry)); */
3134 /* BB fixme add unlock here */
3139 /* BB On error, should we leave previous search buf (and count and
3140 last entry fields) intact or free the previous one? */
3142 /* Note: On -EAGAIN error only caller can retry on handle based calls
3143 since file handle passed in no longer valid */
3146 cifs_buf_release(pSMB
);
3152 CIFSFindClose(const int xid
, struct cifsTconInfo
*tcon
, const __u16 searchHandle
)
3155 FINDCLOSE_REQ
*pSMB
= NULL
;
3156 CLOSE_RSP
*pSMBr
= NULL
; /* BB removeme BB */
3159 cFYI(1, ("In CIFSSMBFindClose"));
3160 rc
= small_smb_init(SMB_COM_FIND_CLOSE2
, 1, tcon
, (void **)&pSMB
);
3162 /* no sense returning error if session restarted
3163 as file handle has been closed */
3169 pSMBr
= (CLOSE_RSP
*)pSMB
; /* BB removeme BB */
3170 pSMB
->FileID
= searchHandle
;
3171 pSMB
->ByteCount
= 0;
3172 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
3173 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
3175 cERROR(1, ("Send error in FindClose = %d", rc
));
3177 cifs_stats_inc(&tcon
->num_fclose
);
3178 cifs_small_buf_release(pSMB
);
3180 /* Since session is dead, search handle closed on server already */
3188 CIFSGetSrvInodeNumber(const int xid
, struct cifsTconInfo
*tcon
,
3189 const unsigned char *searchName
,
3190 __u64
* inode_number
,
3191 const struct nls_table
*nls_codepage
, int remap
)
3194 TRANSACTION2_QPI_REQ
*pSMB
= NULL
;
3195 TRANSACTION2_QPI_RSP
*pSMBr
= NULL
;
3196 int name_len
, bytes_returned
;
3197 __u16 params
, byte_count
;
3199 cFYI(1,("In GetSrvInodeNum for %s",searchName
));
3203 GetInodeNumberRetry
:
3204 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
3210 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
3212 cifsConvertToUCS((__le16
*) pSMB
->FileName
, searchName
,
3213 PATH_MAX
,nls_codepage
, remap
);
3214 name_len
++; /* trailing null */
3216 } else { /* BB improve the check for buffer overruns BB */
3217 name_len
= strnlen(searchName
, PATH_MAX
);
3218 name_len
++; /* trailing null */
3219 strncpy(pSMB
->FileName
, searchName
, name_len
);
3222 params
= 2 /* level */ + 4 /* rsrvd */ + name_len
/* incl null */ ;
3223 pSMB
->TotalDataCount
= 0;
3224 pSMB
->MaxParameterCount
= cpu_to_le16(2);
3225 /* BB find exact max data count below from sess structure BB */
3226 pSMB
->MaxDataCount
= cpu_to_le16(4000);
3227 pSMB
->MaxSetupCount
= 0;
3231 pSMB
->Reserved2
= 0;
3232 pSMB
->ParameterOffset
= cpu_to_le16(offsetof(
3233 struct smb_com_transaction2_qpi_req
,InformationLevel
) - 4);
3234 pSMB
->DataCount
= 0;
3235 pSMB
->DataOffset
= 0;
3236 pSMB
->SetupCount
= 1;
3237 pSMB
->Reserved3
= 0;
3238 pSMB
->SubCommand
= cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION
);
3239 byte_count
= params
+ 1 /* pad */ ;
3240 pSMB
->TotalParameterCount
= cpu_to_le16(params
);
3241 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
3242 pSMB
->InformationLevel
= cpu_to_le16(SMB_QUERY_FILE_INTERNAL_INFO
);
3243 pSMB
->Reserved4
= 0;
3244 pSMB
->hdr
.smb_buf_length
+= byte_count
;
3245 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
3247 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
3248 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
3250 cFYI(1, ("error %d in QueryInternalInfo", rc
));
3252 /* decode response */
3253 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
3254 if (rc
|| (pSMBr
->ByteCount
< 2))
3255 /* BB also check enough total bytes returned */
3256 /* If rc should we check for EOPNOSUPP and
3257 disable the srvino flag? or in caller? */
3258 rc
= -EIO
; /* bad smb */
3260 __u16 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
3261 __u16 count
= le16_to_cpu(pSMBr
->t2
.DataCount
);
3262 struct file_internal_info
* pfinfo
;
3263 /* BB Do we need a cast or hash here ? */
3265 cFYI(1, ("Illegal size ret in QryIntrnlInf"));
3267 goto GetInodeNumOut
;
3269 pfinfo
= (struct file_internal_info
*)
3270 (data_offset
+ (char *) &pSMBr
->hdr
.Protocol
);
3271 *inode_number
= pfinfo
->UniqueId
;
3275 cifs_buf_release(pSMB
);
3277 goto GetInodeNumberRetry
;
3282 CIFSGetDFSRefer(const int xid
, struct cifsSesInfo
*ses
,
3283 const unsigned char *searchName
,
3284 unsigned char **targetUNCs
,
3285 unsigned int *number_of_UNC_in_array
,
3286 const struct nls_table
*nls_codepage
, int remap
)
3288 /* TRANS2_GET_DFS_REFERRAL */
3289 TRANSACTION2_GET_DFS_REFER_REQ
*pSMB
= NULL
;
3290 TRANSACTION2_GET_DFS_REFER_RSP
*pSMBr
= NULL
;
3291 struct dfs_referral_level_3
* referrals
= NULL
;
3297 __u16 params
, byte_count
;
3298 *number_of_UNC_in_array
= 0;
3301 cFYI(1, ("In GetDFSRefer the path %s", searchName
));
3305 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, NULL
, (void **) &pSMB
,
3310 /* server pointer checked in called function,
3311 but should never be null here anyway */
3312 pSMB
->hdr
.Mid
= GetNextMid(ses
->server
);
3313 pSMB
->hdr
.Tid
= ses
->ipc_tid
;
3314 pSMB
->hdr
.Uid
= ses
->Suid
;
3315 if (ses
->capabilities
& CAP_STATUS32
) {
3316 pSMB
->hdr
.Flags2
|= SMBFLG2_ERR_STATUS
;
3318 if (ses
->capabilities
& CAP_DFS
) {
3319 pSMB
->hdr
.Flags2
|= SMBFLG2_DFS
;
3322 if (ses
->capabilities
& CAP_UNICODE
) {
3323 pSMB
->hdr
.Flags2
|= SMBFLG2_UNICODE
;
3325 cifsConvertToUCS((__le16
*) pSMB
->RequestFileName
,
3326 searchName
, PATH_MAX
, nls_codepage
, remap
);
3327 name_len
++; /* trailing null */
3329 } else { /* BB improve the check for buffer overruns BB */
3330 name_len
= strnlen(searchName
, PATH_MAX
);
3331 name_len
++; /* trailing null */
3332 strncpy(pSMB
->RequestFileName
, searchName
, name_len
);
3335 params
= 2 /* level */ + name_len
/*includes null */ ;
3336 pSMB
->TotalDataCount
= 0;
3337 pSMB
->DataCount
= 0;
3338 pSMB
->DataOffset
= 0;
3339 pSMB
->MaxParameterCount
= 0;
3340 pSMB
->MaxDataCount
= cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
3341 pSMB
->MaxSetupCount
= 0;
3345 pSMB
->Reserved2
= 0;
3346 pSMB
->ParameterOffset
= cpu_to_le16(offsetof(
3347 struct smb_com_transaction2_get_dfs_refer_req
, MaxReferralLevel
) - 4);
3348 pSMB
->SetupCount
= 1;
3349 pSMB
->Reserved3
= 0;
3350 pSMB
->SubCommand
= cpu_to_le16(TRANS2_GET_DFS_REFERRAL
);
3351 byte_count
= params
+ 3 /* pad */ ;
3352 pSMB
->ParameterCount
= cpu_to_le16(params
);
3353 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
3354 pSMB
->MaxReferralLevel
= cpu_to_le16(3);
3355 pSMB
->hdr
.smb_buf_length
+= byte_count
;
3356 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
3358 rc
= SendReceive(xid
, ses
, (struct smb_hdr
*) pSMB
,
3359 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
3361 cFYI(1, ("Send error in GetDFSRefer = %d", rc
));
3362 } else { /* decode response */
3363 /* BB Add logic to parse referrals here */
3364 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
3366 if (rc
|| (pSMBr
->ByteCount
< 17)) /* BB also check enough total bytes returned */
3367 rc
= -EIO
; /* bad smb */
3369 __u16 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
3370 __u16 data_count
= le16_to_cpu(pSMBr
->t2
.DataCount
);
3373 ("Decoding GetDFSRefer response. BCC: %d Offset %d",
3374 pSMBr
->ByteCount
, data_offset
));
3376 (struct dfs_referral_level_3
*)
3377 (8 /* sizeof start of data block */ +
3379 (char *) &pSMBr
->hdr
.Protocol
);
3380 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",
3381 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
)));
3382 /* BB This field is actually two bytes in from start of
3383 data block so we could do safety check that DataBlock
3384 begins at address of pSMBr->NumberOfReferrals */
3385 *number_of_UNC_in_array
= le16_to_cpu(pSMBr
->NumberOfReferrals
);
3387 /* BB Fix below so can return more than one referral */
3388 if(*number_of_UNC_in_array
> 1)
3389 *number_of_UNC_in_array
= 1;
3391 /* get the length of the strings describing refs */
3393 for(i
=0;i
<*number_of_UNC_in_array
;i
++) {
3394 /* make sure that DfsPathOffset not past end */
3395 __u16 offset
= le16_to_cpu(referrals
->DfsPathOffset
);
3396 if (offset
> data_count
) {
3397 /* if invalid referral, stop here and do
3398 not try to copy any more */
3399 *number_of_UNC_in_array
= i
;
3402 temp
= ((char *)referrals
) + offset
;
3404 if (pSMBr
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
3405 name_len
+= UniStrnlen((wchar_t *)temp
,data_count
);
3407 name_len
+= strnlen(temp
,data_count
);
3410 /* BB add check that referral pointer does not fall off end PDU */
3413 /* BB add check for name_len bigger than bcc */
3415 kmalloc(name_len
+1+ (*number_of_UNC_in_array
),GFP_KERNEL
);
3416 if(*targetUNCs
== NULL
) {
3420 /* copy the ref strings */
3422 (struct dfs_referral_level_3
*)
3423 (8 /* sizeof data hdr */ +
3425 (char *) &pSMBr
->hdr
.Protocol
);
3427 for(i
=0;i
<*number_of_UNC_in_array
;i
++) {
3428 temp
= ((char *)referrals
) + le16_to_cpu(referrals
->DfsPathOffset
);
3429 if (pSMBr
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
3430 cifs_strfromUCS_le(*targetUNCs
,
3431 (__le16
*) temp
, name_len
, nls_codepage
);
3433 strncpy(*targetUNCs
,temp
,name_len
);
3435 /* BB update target_uncs pointers */
3445 cifs_buf_release(pSMB
);
3453 /* Query File System Info such as free space to old servers such as Win 9x */
3455 SMBOldQFSInfo(const int xid
, struct cifsTconInfo
*tcon
, struct kstatfs
*FSData
)
3457 /* level 0x01 SMB_QUERY_FILE_SYSTEM_INFO */
3458 TRANSACTION2_QFSI_REQ
*pSMB
= NULL
;
3459 TRANSACTION2_QFSI_RSP
*pSMBr
= NULL
;
3460 FILE_SYSTEM_ALLOC_INFO
*response_data
;
3462 int bytes_returned
= 0;
3463 __u16 params
, byte_count
;
3465 cFYI(1, ("OldQFSInfo"));
3467 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
3471 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
3476 params
= 2; /* level */
3477 pSMB
->TotalDataCount
= 0;
3478 pSMB
->MaxParameterCount
= cpu_to_le16(2);
3479 pSMB
->MaxDataCount
= cpu_to_le16(1000);
3480 pSMB
->MaxSetupCount
= 0;
3484 pSMB
->Reserved2
= 0;
3485 byte_count
= params
+ 1 /* pad */ ;
3486 pSMB
->TotalParameterCount
= cpu_to_le16(params
);
3487 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
3488 pSMB
->ParameterOffset
= cpu_to_le16(offsetof(
3489 struct smb_com_transaction2_qfsi_req
, InformationLevel
) - 4);
3490 pSMB
->DataCount
= 0;
3491 pSMB
->DataOffset
= 0;
3492 pSMB
->SetupCount
= 1;
3493 pSMB
->Reserved3
= 0;
3494 pSMB
->SubCommand
= cpu_to_le16(TRANS2_QUERY_FS_INFORMATION
);
3495 pSMB
->InformationLevel
= cpu_to_le16(SMB_INFO_ALLOCATION
);
3496 pSMB
->hdr
.smb_buf_length
+= byte_count
;
3497 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
3499 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
3500 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
3502 cFYI(1, ("Send error in QFSInfo = %d", rc
));
3503 } else { /* decode response */
3504 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
3506 if (rc
|| (pSMBr
->ByteCount
< 18))
3507 rc
= -EIO
; /* bad smb */
3509 __u16 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
3510 cFYI(1,("qfsinf resp BCC: %d Offset %d",
3511 pSMBr
->ByteCount
, data_offset
));
3514 (FILE_SYSTEM_ALLOC_INFO
*)
3515 (((char *) &pSMBr
->hdr
.Protocol
) + data_offset
);
3517 le16_to_cpu(response_data
->BytesPerSector
) *
3518 le32_to_cpu(response_data
->
3519 SectorsPerAllocationUnit
);
3521 le32_to_cpu(response_data
->TotalAllocationUnits
);
3522 FSData
->f_bfree
= FSData
->f_bavail
=
3523 le32_to_cpu(response_data
->FreeAllocationUnits
);
3525 ("Blocks: %lld Free: %lld Block size %ld",
3526 (unsigned long long)FSData
->f_blocks
,
3527 (unsigned long long)FSData
->f_bfree
,
3531 cifs_buf_release(pSMB
);
3534 goto oldQFSInfoRetry
;
3540 CIFSSMBQFSInfo(const int xid
, struct cifsTconInfo
*tcon
, struct kstatfs
*FSData
)
3542 /* level 0x103 SMB_QUERY_FILE_SYSTEM_INFO */
3543 TRANSACTION2_QFSI_REQ
*pSMB
= NULL
;
3544 TRANSACTION2_QFSI_RSP
*pSMBr
= NULL
;
3545 FILE_SYSTEM_INFO
*response_data
;
3547 int bytes_returned
= 0;
3548 __u16 params
, byte_count
;
3550 cFYI(1, ("In QFSInfo"));
3552 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
3557 params
= 2; /* level */
3558 pSMB
->TotalDataCount
= 0;
3559 pSMB
->MaxParameterCount
= cpu_to_le16(2);
3560 pSMB
->MaxDataCount
= cpu_to_le16(1000);
3561 pSMB
->MaxSetupCount
= 0;
3565 pSMB
->Reserved2
= 0;
3566 byte_count
= params
+ 1 /* pad */ ;
3567 pSMB
->TotalParameterCount
= cpu_to_le16(params
);
3568 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
3569 pSMB
->ParameterOffset
= cpu_to_le16(offsetof(
3570 struct smb_com_transaction2_qfsi_req
, InformationLevel
) - 4);
3571 pSMB
->DataCount
= 0;
3572 pSMB
->DataOffset
= 0;
3573 pSMB
->SetupCount
= 1;
3574 pSMB
->Reserved3
= 0;
3575 pSMB
->SubCommand
= cpu_to_le16(TRANS2_QUERY_FS_INFORMATION
);
3576 pSMB
->InformationLevel
= cpu_to_le16(SMB_QUERY_FS_SIZE_INFO
);
3577 pSMB
->hdr
.smb_buf_length
+= byte_count
;
3578 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
3580 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
3581 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
3583 cFYI(1, ("Send error in QFSInfo = %d", rc
));
3584 } else { /* decode response */
3585 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
3587 if (rc
|| (pSMBr
->ByteCount
< 24))
3588 rc
= -EIO
; /* bad smb */
3590 __u16 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
3594 *) (((char *) &pSMBr
->hdr
.Protocol
) +
3597 le32_to_cpu(response_data
->BytesPerSector
) *
3598 le32_to_cpu(response_data
->
3599 SectorsPerAllocationUnit
);
3601 le64_to_cpu(response_data
->TotalAllocationUnits
);
3602 FSData
->f_bfree
= FSData
->f_bavail
=
3603 le64_to_cpu(response_data
->FreeAllocationUnits
);
3605 ("Blocks: %lld Free: %lld Block size %ld",
3606 (unsigned long long)FSData
->f_blocks
,
3607 (unsigned long long)FSData
->f_bfree
,
3611 cifs_buf_release(pSMB
);
3620 CIFSSMBQFSAttributeInfo(const int xid
, struct cifsTconInfo
*tcon
)
3622 /* level 0x105 SMB_QUERY_FILE_SYSTEM_INFO */
3623 TRANSACTION2_QFSI_REQ
*pSMB
= NULL
;
3624 TRANSACTION2_QFSI_RSP
*pSMBr
= NULL
;
3625 FILE_SYSTEM_ATTRIBUTE_INFO
*response_data
;
3627 int bytes_returned
= 0;
3628 __u16 params
, byte_count
;
3630 cFYI(1, ("In QFSAttributeInfo"));
3632 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
3637 params
= 2; /* level */
3638 pSMB
->TotalDataCount
= 0;
3639 pSMB
->MaxParameterCount
= cpu_to_le16(2);
3640 pSMB
->MaxDataCount
= cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
3641 pSMB
->MaxSetupCount
= 0;
3645 pSMB
->Reserved2
= 0;
3646 byte_count
= params
+ 1 /* pad */ ;
3647 pSMB
->TotalParameterCount
= cpu_to_le16(params
);
3648 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
3649 pSMB
->ParameterOffset
= cpu_to_le16(offsetof(
3650 struct smb_com_transaction2_qfsi_req
, InformationLevel
) - 4);
3651 pSMB
->DataCount
= 0;
3652 pSMB
->DataOffset
= 0;
3653 pSMB
->SetupCount
= 1;
3654 pSMB
->Reserved3
= 0;
3655 pSMB
->SubCommand
= cpu_to_le16(TRANS2_QUERY_FS_INFORMATION
);
3656 pSMB
->InformationLevel
= cpu_to_le16(SMB_QUERY_FS_ATTRIBUTE_INFO
);
3657 pSMB
->hdr
.smb_buf_length
+= byte_count
;
3658 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
3660 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
3661 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
3663 cERROR(1, ("Send error in QFSAttributeInfo = %d", rc
));
3664 } else { /* decode response */
3665 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
3667 if (rc
|| (pSMBr
->ByteCount
< 13)) { /* BB also check enough bytes returned */
3668 rc
= -EIO
; /* bad smb */
3670 __u16 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
3672 (FILE_SYSTEM_ATTRIBUTE_INFO
3673 *) (((char *) &pSMBr
->hdr
.Protocol
) +
3675 memcpy(&tcon
->fsAttrInfo
, response_data
,
3676 sizeof (FILE_SYSTEM_ATTRIBUTE_INFO
));
3679 cifs_buf_release(pSMB
);
3682 goto QFSAttributeRetry
;
3688 CIFSSMBQFSDeviceInfo(const int xid
, struct cifsTconInfo
*tcon
)
3690 /* level 0x104 SMB_QUERY_FILE_SYSTEM_INFO */
3691 TRANSACTION2_QFSI_REQ
*pSMB
= NULL
;
3692 TRANSACTION2_QFSI_RSP
*pSMBr
= NULL
;
3693 FILE_SYSTEM_DEVICE_INFO
*response_data
;
3695 int bytes_returned
= 0;
3696 __u16 params
, byte_count
;
3698 cFYI(1, ("In QFSDeviceInfo"));
3700 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
3705 params
= 2; /* level */
3706 pSMB
->TotalDataCount
= 0;
3707 pSMB
->MaxParameterCount
= cpu_to_le16(2);
3708 pSMB
->MaxDataCount
= cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
3709 pSMB
->MaxSetupCount
= 0;
3713 pSMB
->Reserved2
= 0;
3714 byte_count
= params
+ 1 /* pad */ ;
3715 pSMB
->TotalParameterCount
= cpu_to_le16(params
);
3716 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
3717 pSMB
->ParameterOffset
= cpu_to_le16(offsetof(
3718 struct smb_com_transaction2_qfsi_req
, InformationLevel
) - 4);
3720 pSMB
->DataCount
= 0;
3721 pSMB
->DataOffset
= 0;
3722 pSMB
->SetupCount
= 1;
3723 pSMB
->Reserved3
= 0;
3724 pSMB
->SubCommand
= cpu_to_le16(TRANS2_QUERY_FS_INFORMATION
);
3725 pSMB
->InformationLevel
= cpu_to_le16(SMB_QUERY_FS_DEVICE_INFO
);
3726 pSMB
->hdr
.smb_buf_length
+= byte_count
;
3727 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
3729 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
3730 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
3732 cFYI(1, ("Send error in QFSDeviceInfo = %d", rc
));
3733 } else { /* decode response */
3734 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
3736 if (rc
|| (pSMBr
->ByteCount
< sizeof (FILE_SYSTEM_DEVICE_INFO
)))
3737 rc
= -EIO
; /* bad smb */
3739 __u16 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
3741 (FILE_SYSTEM_DEVICE_INFO
*)
3742 (((char *) &pSMBr
->hdr
.Protocol
) +
3744 memcpy(&tcon
->fsDevInfo
, response_data
,
3745 sizeof (FILE_SYSTEM_DEVICE_INFO
));
3748 cifs_buf_release(pSMB
);
3751 goto QFSDeviceRetry
;
3757 CIFSSMBQFSUnixInfo(const int xid
, struct cifsTconInfo
*tcon
)
3759 /* level 0x200 SMB_QUERY_CIFS_UNIX_INFO */
3760 TRANSACTION2_QFSI_REQ
*pSMB
= NULL
;
3761 TRANSACTION2_QFSI_RSP
*pSMBr
= NULL
;
3762 FILE_SYSTEM_UNIX_INFO
*response_data
;
3764 int bytes_returned
= 0;
3765 __u16 params
, byte_count
;
3767 cFYI(1, ("In QFSUnixInfo"));
3769 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
3774 params
= 2; /* level */
3775 pSMB
->TotalDataCount
= 0;
3776 pSMB
->DataCount
= 0;
3777 pSMB
->DataOffset
= 0;
3778 pSMB
->MaxParameterCount
= cpu_to_le16(2);
3779 pSMB
->MaxDataCount
= cpu_to_le16(100); /* BB find exact max SMB PDU from sess structure BB */
3780 pSMB
->MaxSetupCount
= 0;
3784 pSMB
->Reserved2
= 0;
3785 byte_count
= params
+ 1 /* pad */ ;
3786 pSMB
->ParameterCount
= cpu_to_le16(params
);
3787 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
3788 pSMB
->ParameterOffset
= cpu_to_le16(offsetof(struct
3789 smb_com_transaction2_qfsi_req
, InformationLevel
) - 4);
3790 pSMB
->SetupCount
= 1;
3791 pSMB
->Reserved3
= 0;
3792 pSMB
->SubCommand
= cpu_to_le16(TRANS2_QUERY_FS_INFORMATION
);
3793 pSMB
->InformationLevel
= cpu_to_le16(SMB_QUERY_CIFS_UNIX_INFO
);
3794 pSMB
->hdr
.smb_buf_length
+= byte_count
;
3795 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
3797 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
3798 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
3800 cERROR(1, ("Send error in QFSUnixInfo = %d", rc
));
3801 } else { /* decode response */
3802 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
3804 if (rc
|| (pSMBr
->ByteCount
< 13)) {
3805 rc
= -EIO
; /* bad smb */
3807 __u16 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
3809 (FILE_SYSTEM_UNIX_INFO
3810 *) (((char *) &pSMBr
->hdr
.Protocol
) +
3812 memcpy(&tcon
->fsUnixInfo
, response_data
,
3813 sizeof (FILE_SYSTEM_UNIX_INFO
));
3816 cifs_buf_release(pSMB
);
3826 CIFSSMBSetFSUnixInfo(const int xid
, struct cifsTconInfo
*tcon
, __u64 cap
)
3828 /* level 0x200 SMB_SET_CIFS_UNIX_INFO */
3829 TRANSACTION2_SETFSI_REQ
*pSMB
= NULL
;
3830 TRANSACTION2_SETFSI_RSP
*pSMBr
= NULL
;
3832 int bytes_returned
= 0;
3833 __u16 params
, param_offset
, offset
, byte_count
;
3835 cFYI(1, ("In SETFSUnixInfo"));
3837 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
3842 params
= 4; /* 2 bytes zero followed by info level. */
3843 pSMB
->MaxSetupCount
= 0;
3847 pSMB
->Reserved2
= 0;
3848 param_offset
= offsetof(struct smb_com_transaction2_setfsi_req
, FileNum
) - 4;
3849 offset
= param_offset
+ params
;
3851 pSMB
->MaxParameterCount
= cpu_to_le16(4);
3852 pSMB
->MaxDataCount
= cpu_to_le16(100); /* BB find exact max SMB PDU from sess structure BB */
3853 pSMB
->SetupCount
= 1;
3854 pSMB
->Reserved3
= 0;
3855 pSMB
->SubCommand
= cpu_to_le16(TRANS2_SET_FS_INFORMATION
);
3856 byte_count
= 1 /* pad */ + params
+ 12;
3858 pSMB
->DataCount
= cpu_to_le16(12);
3859 pSMB
->ParameterCount
= cpu_to_le16(params
);
3860 pSMB
->TotalDataCount
= pSMB
->DataCount
;
3861 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
3862 pSMB
->ParameterOffset
= cpu_to_le16(param_offset
);
3863 pSMB
->DataOffset
= cpu_to_le16(offset
);
3867 pSMB
->InformationLevel
= cpu_to_le16(SMB_SET_CIFS_UNIX_INFO
);
3870 pSMB
->ClientUnixMajor
= cpu_to_le16(CIFS_UNIX_MAJOR_VERSION
);
3871 pSMB
->ClientUnixMinor
= cpu_to_le16(CIFS_UNIX_MINOR_VERSION
);
3872 pSMB
->ClientUnixCap
= cpu_to_le64(cap
);
3874 pSMB
->hdr
.smb_buf_length
+= byte_count
;
3875 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
3877 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
3878 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
3880 cERROR(1, ("Send error in SETFSUnixInfo = %d", rc
));
3881 } else { /* decode response */
3882 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
3884 rc
= -EIO
; /* bad smb */
3887 cifs_buf_release(pSMB
);
3890 goto SETFSUnixRetry
;
3898 CIFSSMBQFSPosixInfo(const int xid
, struct cifsTconInfo
*tcon
,
3899 struct kstatfs
*FSData
)
3901 /* level 0x201 SMB_QUERY_CIFS_POSIX_INFO */
3902 TRANSACTION2_QFSI_REQ
*pSMB
= NULL
;
3903 TRANSACTION2_QFSI_RSP
*pSMBr
= NULL
;
3904 FILE_SYSTEM_POSIX_INFO
*response_data
;
3906 int bytes_returned
= 0;
3907 __u16 params
, byte_count
;
3909 cFYI(1, ("In QFSPosixInfo"));
3911 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
3916 params
= 2; /* level */
3917 pSMB
->TotalDataCount
= 0;
3918 pSMB
->DataCount
= 0;
3919 pSMB
->DataOffset
= 0;
3920 pSMB
->MaxParameterCount
= cpu_to_le16(2);
3921 pSMB
->MaxDataCount
= cpu_to_le16(100); /* BB find exact max SMB PDU from sess structure BB */
3922 pSMB
->MaxSetupCount
= 0;
3926 pSMB
->Reserved2
= 0;
3927 byte_count
= params
+ 1 /* pad */ ;
3928 pSMB
->ParameterCount
= cpu_to_le16(params
);
3929 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
3930 pSMB
->ParameterOffset
= cpu_to_le16(offsetof(struct
3931 smb_com_transaction2_qfsi_req
, InformationLevel
) - 4);
3932 pSMB
->SetupCount
= 1;
3933 pSMB
->Reserved3
= 0;
3934 pSMB
->SubCommand
= cpu_to_le16(TRANS2_QUERY_FS_INFORMATION
);
3935 pSMB
->InformationLevel
= cpu_to_le16(SMB_QUERY_POSIX_FS_INFO
);
3936 pSMB
->hdr
.smb_buf_length
+= byte_count
;
3937 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
3939 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
3940 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
3942 cFYI(1, ("Send error in QFSUnixInfo = %d", rc
));
3943 } else { /* decode response */
3944 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
3946 if (rc
|| (pSMBr
->ByteCount
< 13)) {
3947 rc
= -EIO
; /* bad smb */
3949 __u16 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
3951 (FILE_SYSTEM_POSIX_INFO
3952 *) (((char *) &pSMBr
->hdr
.Protocol
) +
3955 le32_to_cpu(response_data
->BlockSize
);
3957 le64_to_cpu(response_data
->TotalBlocks
);
3959 le64_to_cpu(response_data
->BlocksAvail
);
3960 if(response_data
->UserBlocksAvail
== cpu_to_le64(-1)) {
3961 FSData
->f_bavail
= FSData
->f_bfree
;
3964 le64_to_cpu(response_data
->UserBlocksAvail
);
3966 if(response_data
->TotalFileNodes
!= cpu_to_le64(-1))
3968 le64_to_cpu(response_data
->TotalFileNodes
);
3969 if(response_data
->FreeFileNodes
!= cpu_to_le64(-1))
3971 le64_to_cpu(response_data
->FreeFileNodes
);
3974 cifs_buf_release(pSMB
);
3983 /* We can not use write of zero bytes trick to
3984 set file size due to need for large file support. Also note that
3985 this SetPathInfo is preferred to SetFileInfo based method in next
3986 routine which is only needed to work around a sharing violation bug
3987 in Samba which this routine can run into */
3990 CIFSSMBSetEOF(const int xid
, struct cifsTconInfo
*tcon
, const char *fileName
,
3991 __u64 size
, int SetAllocation
,
3992 const struct nls_table
*nls_codepage
, int remap
)
3994 struct smb_com_transaction2_spi_req
*pSMB
= NULL
;
3995 struct smb_com_transaction2_spi_rsp
*pSMBr
= NULL
;
3996 struct file_end_of_file_info
*parm_data
;
3999 int bytes_returned
= 0;
4000 __u16 params
, byte_count
, data_count
, param_offset
, offset
;
4002 cFYI(1, ("In SetEOF"));
4004 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
4009 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
4011 cifsConvertToUCS((__le16
*) pSMB
->FileName
, fileName
,
4012 PATH_MAX
, nls_codepage
, remap
);
4013 name_len
++; /* trailing null */
4015 } else { /* BB improve the check for buffer overruns BB */
4016 name_len
= strnlen(fileName
, PATH_MAX
);
4017 name_len
++; /* trailing null */
4018 strncpy(pSMB
->FileName
, fileName
, name_len
);
4020 params
= 6 + name_len
;
4021 data_count
= sizeof (struct file_end_of_file_info
);
4022 pSMB
->MaxParameterCount
= cpu_to_le16(2);
4023 pSMB
->MaxDataCount
= cpu_to_le16(4100);
4024 pSMB
->MaxSetupCount
= 0;
4028 pSMB
->Reserved2
= 0;
4029 param_offset
= offsetof(struct smb_com_transaction2_spi_req
,
4030 InformationLevel
) - 4;
4031 offset
= param_offset
+ params
;
4033 if (tcon
->ses
->capabilities
& CAP_INFOLEVEL_PASSTHRU
)
4034 pSMB
->InformationLevel
=
4035 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2
);
4037 pSMB
->InformationLevel
=
4038 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO
);
4039 } else /* Set File Size */ {
4040 if (tcon
->ses
->capabilities
& CAP_INFOLEVEL_PASSTHRU
)
4041 pSMB
->InformationLevel
=
4042 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO2
);
4044 pSMB
->InformationLevel
=
4045 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO
);
4049 (struct file_end_of_file_info
*) (((char *) &pSMB
->hdr
.Protocol
) +
4051 pSMB
->ParameterOffset
= cpu_to_le16(param_offset
);
4052 pSMB
->DataOffset
= cpu_to_le16(offset
);
4053 pSMB
->SetupCount
= 1;
4054 pSMB
->Reserved3
= 0;
4055 pSMB
->SubCommand
= cpu_to_le16(TRANS2_SET_PATH_INFORMATION
);
4056 byte_count
= 3 /* pad */ + params
+ data_count
;
4057 pSMB
->DataCount
= cpu_to_le16(data_count
);
4058 pSMB
->TotalDataCount
= pSMB
->DataCount
;
4059 pSMB
->ParameterCount
= cpu_to_le16(params
);
4060 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
4061 pSMB
->Reserved4
= 0;
4062 pSMB
->hdr
.smb_buf_length
+= byte_count
;
4063 parm_data
->FileSize
= cpu_to_le64(size
);
4064 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, ("SetPathInfo (file size) returned %d", rc
));
4071 cifs_buf_release(pSMB
);
4080 CIFSSMBSetFileSize(const int xid
, struct cifsTconInfo
*tcon
, __u64 size
,
4081 __u16 fid
, __u32 pid_of_opener
, int SetAllocation
)
4083 struct smb_com_transaction2_sfi_req
*pSMB
= NULL
;
4084 struct smb_com_transaction2_sfi_rsp
*pSMBr
= NULL
;
4086 struct file_end_of_file_info
*parm_data
;
4088 int bytes_returned
= 0;
4089 __u16 params
, param_offset
, offset
, byte_count
, count
;
4091 cFYI(1, ("SetFileSize (via SetFileInfo) %lld",
4093 rc
= small_smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
);
4098 pSMBr
= (struct smb_com_transaction2_sfi_rsp
*)pSMB
;
4100 pSMB
->hdr
.Pid
= cpu_to_le16((__u16
)pid_of_opener
);
4101 pSMB
->hdr
.PidHigh
= cpu_to_le16((__u16
)(pid_of_opener
>> 16));
4104 pSMB
->MaxSetupCount
= 0;
4108 pSMB
->Reserved2
= 0;
4109 param_offset
= offsetof(struct smb_com_transaction2_sfi_req
, Fid
) - 4;
4110 offset
= param_offset
+ params
;
4112 data_offset
= (char *) (&pSMB
->hdr
.Protocol
) + offset
;
4114 count
= sizeof(struct file_end_of_file_info
);
4115 pSMB
->MaxParameterCount
= cpu_to_le16(2);
4116 pSMB
->MaxDataCount
= cpu_to_le16(1000); /* BB find max SMB PDU from sess */
4117 pSMB
->SetupCount
= 1;
4118 pSMB
->Reserved3
= 0;
4119 pSMB
->SubCommand
= cpu_to_le16(TRANS2_SET_FILE_INFORMATION
);
4120 byte_count
= 3 /* pad */ + params
+ count
;
4121 pSMB
->DataCount
= cpu_to_le16(count
);
4122 pSMB
->ParameterCount
= cpu_to_le16(params
);
4123 pSMB
->TotalDataCount
= pSMB
->DataCount
;
4124 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
4125 pSMB
->ParameterOffset
= cpu_to_le16(param_offset
);
4127 (struct file_end_of_file_info
*) (((char *) &pSMB
->hdr
.Protocol
) +
4129 pSMB
->DataOffset
= cpu_to_le16(offset
);
4130 parm_data
->FileSize
= cpu_to_le64(size
);
4133 if (tcon
->ses
->capabilities
& CAP_INFOLEVEL_PASSTHRU
)
4134 pSMB
->InformationLevel
=
4135 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2
);
4137 pSMB
->InformationLevel
=
4138 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO
);
4139 } else /* Set File Size */ {
4140 if (tcon
->ses
->capabilities
& CAP_INFOLEVEL_PASSTHRU
)
4141 pSMB
->InformationLevel
=
4142 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO2
);
4144 pSMB
->InformationLevel
=
4145 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO
);
4147 pSMB
->Reserved4
= 0;
4148 pSMB
->hdr
.smb_buf_length
+= byte_count
;
4149 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
4150 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
4151 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
4154 ("Send error in SetFileInfo (SetFileSize) = %d",
4159 cifs_small_buf_release(pSMB
);
4161 /* Note: On -EAGAIN error only caller can retry on handle based calls
4162 since file handle passed in no longer valid */
4167 /* Some legacy servers such as NT4 require that the file times be set on
4168 an open handle, rather than by pathname - this is awkward due to
4169 potential access conflicts on the open, but it is unavoidable for these
4170 old servers since the only other choice is to go from 100 nanosecond DCE
4171 time and resort to the original setpathinfo level which takes the ancient
4172 DOS time format with 2 second granularity */
4174 CIFSSMBSetFileTimes(const int xid
, struct cifsTconInfo
*tcon
, const FILE_BASIC_INFO
* data
,
4177 struct smb_com_transaction2_sfi_req
*pSMB
= NULL
;
4178 struct smb_com_transaction2_sfi_rsp
*pSMBr
= NULL
;
4181 int bytes_returned
= 0;
4182 __u16 params
, param_offset
, offset
, byte_count
, count
;
4184 cFYI(1, ("Set Times (via SetFileInfo)"));
4185 rc
= small_smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
);
4190 pSMBr
= (struct smb_com_transaction2_sfi_rsp
*)pSMB
;
4192 /* At this point there is no need to override the current pid
4193 with the pid of the opener, but that could change if we someday
4194 use an existing handle (rather than opening one on the fly) */
4195 /* pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
4196 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));*/
4199 pSMB
->MaxSetupCount
= 0;
4203 pSMB
->Reserved2
= 0;
4204 param_offset
= offsetof(struct smb_com_transaction2_sfi_req
, Fid
) - 4;
4205 offset
= param_offset
+ params
;
4207 data_offset
= (char *) (&pSMB
->hdr
.Protocol
) + offset
;
4209 count
= sizeof (FILE_BASIC_INFO
);
4210 pSMB
->MaxParameterCount
= cpu_to_le16(2);
4211 pSMB
->MaxDataCount
= cpu_to_le16(1000); /* BB find max SMB PDU from sess */
4212 pSMB
->SetupCount
= 1;
4213 pSMB
->Reserved3
= 0;
4214 pSMB
->SubCommand
= cpu_to_le16(TRANS2_SET_FILE_INFORMATION
);
4215 byte_count
= 3 /* pad */ + params
+ count
;
4216 pSMB
->DataCount
= cpu_to_le16(count
);
4217 pSMB
->ParameterCount
= cpu_to_le16(params
);
4218 pSMB
->TotalDataCount
= pSMB
->DataCount
;
4219 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
4220 pSMB
->ParameterOffset
= cpu_to_le16(param_offset
);
4221 pSMB
->DataOffset
= cpu_to_le16(offset
);
4223 if (tcon
->ses
->capabilities
& CAP_INFOLEVEL_PASSTHRU
)
4224 pSMB
->InformationLevel
= cpu_to_le16(SMB_SET_FILE_BASIC_INFO2
);
4226 pSMB
->InformationLevel
= cpu_to_le16(SMB_SET_FILE_BASIC_INFO
);
4227 pSMB
->Reserved4
= 0;
4228 pSMB
->hdr
.smb_buf_length
+= byte_count
;
4229 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
4230 memcpy(data_offset
,data
,sizeof(FILE_BASIC_INFO
));
4231 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
4232 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
4234 cFYI(1,("Send error in Set Time (SetFileInfo) = %d",rc
));
4237 cifs_small_buf_release(pSMB
);
4239 /* Note: On -EAGAIN error only caller can retry on handle based calls
4240 since file handle passed in no longer valid */
4247 CIFSSMBSetTimes(const int xid
, struct cifsTconInfo
*tcon
, const char *fileName
,
4248 const FILE_BASIC_INFO
* data
,
4249 const struct nls_table
*nls_codepage
, int remap
)
4251 TRANSACTION2_SPI_REQ
*pSMB
= NULL
;
4252 TRANSACTION2_SPI_RSP
*pSMBr
= NULL
;
4255 int bytes_returned
= 0;
4257 __u16 params
, param_offset
, offset
, byte_count
, count
;
4259 cFYI(1, ("In SetTimes"));
4262 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
4267 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
4269 cifsConvertToUCS((__le16
*) pSMB
->FileName
, fileName
,
4270 PATH_MAX
, nls_codepage
, remap
);
4271 name_len
++; /* trailing null */
4273 } else { /* BB improve the check for buffer overruns BB */
4274 name_len
= strnlen(fileName
, PATH_MAX
);
4275 name_len
++; /* trailing null */
4276 strncpy(pSMB
->FileName
, fileName
, name_len
);
4279 params
= 6 + name_len
;
4280 count
= sizeof (FILE_BASIC_INFO
);
4281 pSMB
->MaxParameterCount
= cpu_to_le16(2);
4282 pSMB
->MaxDataCount
= cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
4283 pSMB
->MaxSetupCount
= 0;
4287 pSMB
->Reserved2
= 0;
4288 param_offset
= offsetof(struct smb_com_transaction2_spi_req
,
4289 InformationLevel
) - 4;
4290 offset
= param_offset
+ params
;
4291 data_offset
= (char *) (&pSMB
->hdr
.Protocol
) + offset
;
4292 pSMB
->ParameterOffset
= cpu_to_le16(param_offset
);
4293 pSMB
->DataOffset
= cpu_to_le16(offset
);
4294 pSMB
->SetupCount
= 1;
4295 pSMB
->Reserved3
= 0;
4296 pSMB
->SubCommand
= cpu_to_le16(TRANS2_SET_PATH_INFORMATION
);
4297 byte_count
= 3 /* pad */ + params
+ count
;
4299 pSMB
->DataCount
= cpu_to_le16(count
);
4300 pSMB
->ParameterCount
= cpu_to_le16(params
);
4301 pSMB
->TotalDataCount
= pSMB
->DataCount
;
4302 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
4303 if (tcon
->ses
->capabilities
& CAP_INFOLEVEL_PASSTHRU
)
4304 pSMB
->InformationLevel
= cpu_to_le16(SMB_SET_FILE_BASIC_INFO2
);
4306 pSMB
->InformationLevel
= cpu_to_le16(SMB_SET_FILE_BASIC_INFO
);
4307 pSMB
->Reserved4
= 0;
4308 pSMB
->hdr
.smb_buf_length
+= byte_count
;
4309 memcpy(data_offset
, data
, sizeof (FILE_BASIC_INFO
));
4310 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
4311 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
4312 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
4314 cFYI(1, ("SetPathInfo (times) returned %d", rc
));
4317 cifs_buf_release(pSMB
);
4325 /* Can not be used to set time stamps yet (due to old DOS time format) */
4326 /* Can be used to set attributes */
4327 #if 0 /* Possibly not needed - since it turns out that strangely NT4 has a bug
4328 handling it anyway and NT4 was what we thought it would be needed for
4329 Do not delete it until we prove whether needed for Win9x though */
4331 CIFSSMBSetAttrLegacy(int xid
, struct cifsTconInfo
*tcon
, char *fileName
,
4332 __u16 dos_attrs
, const struct nls_table
*nls_codepage
)
4334 SETATTR_REQ
*pSMB
= NULL
;
4335 SETATTR_RSP
*pSMBr
= NULL
;
4340 cFYI(1, ("In SetAttrLegacy"));
4343 rc
= smb_init(SMB_COM_SETATTR
, 8, tcon
, (void **) &pSMB
,
4348 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
4350 ConvertToUCS((__le16
*) pSMB
->fileName
, fileName
,
4351 PATH_MAX
, nls_codepage
);
4352 name_len
++; /* trailing null */
4354 } else { /* BB improve the check for buffer overruns BB */
4355 name_len
= strnlen(fileName
, PATH_MAX
);
4356 name_len
++; /* trailing null */
4357 strncpy(pSMB
->fileName
, fileName
, name_len
);
4359 pSMB
->attr
= cpu_to_le16(dos_attrs
);
4360 pSMB
->BufferFormat
= 0x04;
4361 pSMB
->hdr
.smb_buf_length
+= name_len
+ 1;
4362 pSMB
->ByteCount
= cpu_to_le16(name_len
+ 1);
4363 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
4364 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
4366 cFYI(1, ("Error in LegacySetAttr = %d", rc
));
4369 cifs_buf_release(pSMB
);
4372 goto SetAttrLgcyRetry
;
4376 #endif /* temporarily unneeded SetAttr legacy function */
4379 CIFSSMBUnixSetPerms(const int xid
, struct cifsTconInfo
*tcon
,
4380 char *fileName
, __u64 mode
, __u64 uid
, __u64 gid
,
4381 dev_t device
, const struct nls_table
*nls_codepage
,
4384 TRANSACTION2_SPI_REQ
*pSMB
= NULL
;
4385 TRANSACTION2_SPI_RSP
*pSMBr
= NULL
;
4388 int bytes_returned
= 0;
4389 FILE_UNIX_BASIC_INFO
*data_offset
;
4390 __u16 params
, param_offset
, offset
, count
, byte_count
;
4392 cFYI(1, ("In SetUID/GID/Mode"));
4394 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
4399 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
4401 cifsConvertToUCS((__le16
*) pSMB
->FileName
, fileName
,
4402 PATH_MAX
, nls_codepage
, remap
);
4403 name_len
++; /* trailing null */
4405 } else { /* BB improve the check for buffer overruns BB */
4406 name_len
= strnlen(fileName
, PATH_MAX
);
4407 name_len
++; /* trailing null */
4408 strncpy(pSMB
->FileName
, fileName
, name_len
);
4411 params
= 6 + name_len
;
4412 count
= sizeof (FILE_UNIX_BASIC_INFO
);
4413 pSMB
->MaxParameterCount
= cpu_to_le16(2);
4414 pSMB
->MaxDataCount
= cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
4415 pSMB
->MaxSetupCount
= 0;
4419 pSMB
->Reserved2
= 0;
4420 param_offset
= offsetof(struct smb_com_transaction2_spi_req
,
4421 InformationLevel
) - 4;
4422 offset
= param_offset
+ params
;
4424 (FILE_UNIX_BASIC_INFO
*) ((char *) &pSMB
->hdr
.Protocol
+
4426 memset(data_offset
, 0, count
);
4427 pSMB
->DataOffset
= cpu_to_le16(offset
);
4428 pSMB
->ParameterOffset
= cpu_to_le16(param_offset
);
4429 pSMB
->SetupCount
= 1;
4430 pSMB
->Reserved3
= 0;
4431 pSMB
->SubCommand
= cpu_to_le16(TRANS2_SET_PATH_INFORMATION
);
4432 byte_count
= 3 /* pad */ + params
+ count
;
4433 pSMB
->ParameterCount
= cpu_to_le16(params
);
4434 pSMB
->DataCount
= cpu_to_le16(count
);
4435 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
4436 pSMB
->TotalDataCount
= pSMB
->DataCount
;
4437 pSMB
->InformationLevel
= cpu_to_le16(SMB_SET_FILE_UNIX_BASIC
);
4438 pSMB
->Reserved4
= 0;
4439 pSMB
->hdr
.smb_buf_length
+= byte_count
;
4440 data_offset
->Uid
= cpu_to_le64(uid
);
4441 data_offset
->Gid
= cpu_to_le64(gid
);
4442 /* better to leave device as zero when it is */
4443 data_offset
->DevMajor
= cpu_to_le64(MAJOR(device
));
4444 data_offset
->DevMinor
= cpu_to_le64(MINOR(device
));
4445 data_offset
->Permissions
= cpu_to_le64(mode
);
4448 data_offset
->Type
= cpu_to_le32(UNIX_FILE
);
4449 else if(S_ISDIR(mode
))
4450 data_offset
->Type
= cpu_to_le32(UNIX_DIR
);
4451 else if(S_ISLNK(mode
))
4452 data_offset
->Type
= cpu_to_le32(UNIX_SYMLINK
);
4453 else if(S_ISCHR(mode
))
4454 data_offset
->Type
= cpu_to_le32(UNIX_CHARDEV
);
4455 else if(S_ISBLK(mode
))
4456 data_offset
->Type
= cpu_to_le32(UNIX_BLOCKDEV
);
4457 else if(S_ISFIFO(mode
))
4458 data_offset
->Type
= cpu_to_le32(UNIX_FIFO
);
4459 else if(S_ISSOCK(mode
))
4460 data_offset
->Type
= cpu_to_le32(UNIX_SOCKET
);
4463 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
4464 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
4465 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
4467 cFYI(1, ("SetPathInfo (perms) returned %d", rc
));
4471 cifs_buf_release(pSMB
);
4477 int CIFSSMBNotify(const int xid
, struct cifsTconInfo
*tcon
,
4478 const int notify_subdirs
, const __u16 netfid
,
4479 __u32 filter
, struct file
* pfile
, int multishot
,
4480 const struct nls_table
*nls_codepage
)
4483 struct smb_com_transaction_change_notify_req
* pSMB
= NULL
;
4484 struct smb_com_ntransaction_change_notify_rsp
* pSMBr
= NULL
;
4485 struct dir_notify_req
*dnotify_req
;
4488 cFYI(1, ("In CIFSSMBNotify for file handle %d",(int)netfid
));
4489 rc
= smb_init(SMB_COM_NT_TRANSACT
, 23, tcon
, (void **) &pSMB
,
4494 pSMB
->TotalParameterCount
= 0 ;
4495 pSMB
->TotalDataCount
= 0;
4496 pSMB
->MaxParameterCount
= cpu_to_le32(2);
4497 /* BB find exact data count max from sess structure BB */
4498 pSMB
->MaxDataCount
= 0; /* same in little endian or be */
4499 /* BB VERIFY verify which is correct for above BB */
4500 pSMB
->MaxDataCount
= cpu_to_le32((tcon
->ses
->server
->maxBuf
-
4501 MAX_CIFS_HDR_SIZE
) & 0xFFFFFF00);
4503 pSMB
->MaxSetupCount
= 4;
4505 pSMB
->ParameterOffset
= 0;
4506 pSMB
->DataCount
= 0;
4507 pSMB
->DataOffset
= 0;
4508 pSMB
->SetupCount
= 4; /* single byte does not need le conversion */
4509 pSMB
->SubCommand
= cpu_to_le16(NT_TRANSACT_NOTIFY_CHANGE
);
4510 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
4512 pSMB
->WatchTree
= 1; /* one byte - no le conversion needed */
4513 pSMB
->Reserved2
= 0;
4514 pSMB
->CompletionFilter
= cpu_to_le32(filter
);
4515 pSMB
->Fid
= netfid
; /* file handle always le */
4516 pSMB
->ByteCount
= 0;
4518 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
4519 (struct smb_hdr
*) pSMBr
, &bytes_returned
, -1);
4521 cFYI(1, ("Error in Notify = %d", rc
));
4523 /* Add file to outstanding requests */
4524 /* BB change to kmem cache alloc */
4525 dnotify_req
= (struct dir_notify_req
*) kmalloc(
4526 sizeof(struct dir_notify_req
),
4529 dnotify_req
->Pid
= pSMB
->hdr
.Pid
;
4530 dnotify_req
->PidHigh
= pSMB
->hdr
.PidHigh
;
4531 dnotify_req
->Mid
= pSMB
->hdr
.Mid
;
4532 dnotify_req
->Tid
= pSMB
->hdr
.Tid
;
4533 dnotify_req
->Uid
= pSMB
->hdr
.Uid
;
4534 dnotify_req
->netfid
= netfid
;
4535 dnotify_req
->pfile
= pfile
;
4536 dnotify_req
->filter
= filter
;
4537 dnotify_req
->multishot
= multishot
;
4538 spin_lock(&GlobalMid_Lock
);
4539 list_add_tail(&dnotify_req
->lhead
,
4540 &GlobalDnotifyReqList
);
4541 spin_unlock(&GlobalMid_Lock
);
4545 cifs_buf_release(pSMB
);
4548 #ifdef CONFIG_CIFS_XATTR
4550 CIFSSMBQAllEAs(const int xid
, struct cifsTconInfo
*tcon
,
4551 const unsigned char *searchName
,
4552 char * EAData
, size_t buf_size
,
4553 const struct nls_table
*nls_codepage
, int remap
)
4555 /* BB assumes one setup word */
4556 TRANSACTION2_QPI_REQ
*pSMB
= NULL
;
4557 TRANSACTION2_QPI_RSP
*pSMBr
= NULL
;
4561 struct fea
* temp_fea
;
4563 __u16 params
, byte_count
;
4565 cFYI(1, ("In Query All EAs path %s", searchName
));
4567 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
4572 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
4574 cifsConvertToUCS((__le16
*) pSMB
->FileName
, searchName
,
4575 PATH_MAX
, nls_codepage
, remap
);
4576 name_len
++; /* trailing null */
4578 } else { /* BB improve the check for buffer overruns BB */
4579 name_len
= strnlen(searchName
, PATH_MAX
);
4580 name_len
++; /* trailing null */
4581 strncpy(pSMB
->FileName
, searchName
, name_len
);
4584 params
= 2 /* level */ + 4 /* reserved */ + name_len
/* includes NUL */ ;
4585 pSMB
->TotalDataCount
= 0;
4586 pSMB
->MaxParameterCount
= cpu_to_le16(2);
4587 pSMB
->MaxDataCount
= cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
4588 pSMB
->MaxSetupCount
= 0;
4592 pSMB
->Reserved2
= 0;
4593 pSMB
->ParameterOffset
= cpu_to_le16(offsetof(
4594 struct smb_com_transaction2_qpi_req
,InformationLevel
) - 4);
4595 pSMB
->DataCount
= 0;
4596 pSMB
->DataOffset
= 0;
4597 pSMB
->SetupCount
= 1;
4598 pSMB
->Reserved3
= 0;
4599 pSMB
->SubCommand
= cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION
);
4600 byte_count
= params
+ 1 /* pad */ ;
4601 pSMB
->TotalParameterCount
= cpu_to_le16(params
);
4602 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
4603 pSMB
->InformationLevel
= cpu_to_le16(SMB_INFO_QUERY_ALL_EAS
);
4604 pSMB
->Reserved4
= 0;
4605 pSMB
->hdr
.smb_buf_length
+= byte_count
;
4606 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
4608 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
4609 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
4611 cFYI(1, ("Send error in QueryAllEAs = %d", rc
));
4612 } else { /* decode response */
4613 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
4615 /* BB also check enough total bytes returned */
4616 /* BB we need to improve the validity checking
4617 of these trans2 responses */
4618 if (rc
|| (pSMBr
->ByteCount
< 4))
4619 rc
= -EIO
; /* bad smb */
4620 /* else if (pFindData){
4621 memcpy((char *) pFindData,
4622 (char *) &pSMBr->hdr.Protocol +
4625 /* check that length of list is not more than bcc */
4626 /* check that each entry does not go beyond length
4628 /* check that each element of each entry does not
4629 go beyond end of list */
4630 __u16 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
4631 struct fealist
* ea_response_data
;
4633 /* validate_trans2_offsets() */
4634 /* BB to check if(start of smb + data_offset > &bcc+ bcc)*/
4635 ea_response_data
= (struct fealist
*)
4636 (((char *) &pSMBr
->hdr
.Protocol
) +
4638 name_len
= le32_to_cpu(ea_response_data
->list_len
);
4639 cFYI(1,("ea length %d", name_len
));
4641 /* returned EA size zeroed at top of function */
4642 cFYI(1,("empty EA list returned from server"));
4644 /* account for ea list len */
4646 temp_fea
= ea_response_data
->list
;
4647 temp_ptr
= (char *)temp_fea
;
4648 while(name_len
> 0) {
4652 rc
+= temp_fea
->name_len
;
4653 /* account for prefix user. and trailing null */
4655 if(rc
<(int)buf_size
) {
4656 memcpy(EAData
,"user.",5);
4658 memcpy(EAData
,temp_ptr
,temp_fea
->name_len
);
4659 EAData
+=temp_fea
->name_len
;
4660 /* null terminate name */
4662 EAData
= EAData
+ 1;
4663 } else if(buf_size
== 0) {
4664 /* skip copy - calc size only */
4666 /* stop before overrun buffer */
4670 name_len
-= temp_fea
->name_len
;
4671 temp_ptr
+= temp_fea
->name_len
;
4672 /* account for trailing null */
4675 value_len
= le16_to_cpu(temp_fea
->value_len
);
4676 name_len
-= value_len
;
4677 temp_ptr
+= value_len
;
4678 /* BB check that temp_ptr is still within smb BB*/
4679 /* no trailing null to account for in value len */
4680 /* go on to next EA */
4681 temp_fea
= (struct fea
*)temp_ptr
;
4687 cifs_buf_release(pSMB
);
4694 ssize_t
CIFSSMBQueryEA(const int xid
,struct cifsTconInfo
* tcon
,
4695 const unsigned char * searchName
,const unsigned char * ea_name
,
4696 unsigned char * ea_value
, size_t buf_size
,
4697 const struct nls_table
*nls_codepage
, int remap
)
4699 TRANSACTION2_QPI_REQ
*pSMB
= NULL
;
4700 TRANSACTION2_QPI_RSP
*pSMBr
= NULL
;
4704 struct fea
* temp_fea
;
4706 __u16 params
, byte_count
;
4708 cFYI(1, ("In Query EA path %s", searchName
));
4710 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
4715 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
4717 cifsConvertToUCS((__le16
*) pSMB
->FileName
, searchName
,
4718 PATH_MAX
, nls_codepage
, remap
);
4719 name_len
++; /* trailing null */
4721 } else { /* BB improve the check for buffer overruns BB */
4722 name_len
= strnlen(searchName
, PATH_MAX
);
4723 name_len
++; /* trailing null */
4724 strncpy(pSMB
->FileName
, searchName
, name_len
);
4727 params
= 2 /* level */ + 4 /* reserved */ + name_len
/* includes NUL */ ;
4728 pSMB
->TotalDataCount
= 0;
4729 pSMB
->MaxParameterCount
= cpu_to_le16(2);
4730 pSMB
->MaxDataCount
= cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
4731 pSMB
->MaxSetupCount
= 0;
4735 pSMB
->Reserved2
= 0;
4736 pSMB
->ParameterOffset
= cpu_to_le16(offsetof(
4737 struct smb_com_transaction2_qpi_req
,InformationLevel
) - 4);
4738 pSMB
->DataCount
= 0;
4739 pSMB
->DataOffset
= 0;
4740 pSMB
->SetupCount
= 1;
4741 pSMB
->Reserved3
= 0;
4742 pSMB
->SubCommand
= cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION
);
4743 byte_count
= params
+ 1 /* pad */ ;
4744 pSMB
->TotalParameterCount
= cpu_to_le16(params
);
4745 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
4746 pSMB
->InformationLevel
= cpu_to_le16(SMB_INFO_QUERY_ALL_EAS
);
4747 pSMB
->Reserved4
= 0;
4748 pSMB
->hdr
.smb_buf_length
+= byte_count
;
4749 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
4751 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
4752 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
4754 cFYI(1, ("Send error in Query EA = %d", rc
));
4755 } else { /* decode response */
4756 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
4758 /* BB also check enough total bytes returned */
4759 /* BB we need to improve the validity checking
4760 of these trans2 responses */
4761 if (rc
|| (pSMBr
->ByteCount
< 4))
4762 rc
= -EIO
; /* bad smb */
4763 /* else if (pFindData){
4764 memcpy((char *) pFindData,
4765 (char *) &pSMBr->hdr.Protocol +
4768 /* check that length of list is not more than bcc */
4769 /* check that each entry does not go beyond length
4771 /* check that each element of each entry does not
4772 go beyond end of list */
4773 __u16 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
4774 struct fealist
* ea_response_data
;
4776 /* validate_trans2_offsets() */
4777 /* BB to check if(start of smb + data_offset > &bcc+ bcc)*/
4778 ea_response_data
= (struct fealist
*)
4779 (((char *) &pSMBr
->hdr
.Protocol
) +
4781 name_len
= le32_to_cpu(ea_response_data
->list_len
);
4782 cFYI(1,("ea length %d", name_len
));
4784 /* returned EA size zeroed at top of function */
4785 cFYI(1,("empty EA list returned from server"));
4787 /* account for ea list len */
4789 temp_fea
= ea_response_data
->list
;
4790 temp_ptr
= (char *)temp_fea
;
4791 /* loop through checking if we have a matching
4792 name and then return the associated value */
4793 while(name_len
> 0) {
4797 value_len
= le16_to_cpu(temp_fea
->value_len
);
4798 /* BB validate that value_len falls within SMB,
4799 even though maximum for name_len is 255 */
4800 if(memcmp(temp_fea
->name
,ea_name
,
4801 temp_fea
->name_len
) == 0) {
4804 /* account for prefix user. and trailing null */
4805 if(rc
<=(int)buf_size
) {
4807 temp_fea
->name
+temp_fea
->name_len
+1,
4809 /* ea values, unlike ea names,
4810 are not null terminated */
4811 } else if(buf_size
== 0) {
4812 /* skip copy - calc size only */
4814 /* stop before overrun buffer */
4819 name_len
-= temp_fea
->name_len
;
4820 temp_ptr
+= temp_fea
->name_len
;
4821 /* account for trailing null */
4824 name_len
-= value_len
;
4825 temp_ptr
+= value_len
;
4826 /* no trailing null to account for in value len */
4827 /* go on to next EA */
4828 temp_fea
= (struct fea
*)temp_ptr
;
4834 cifs_buf_release(pSMB
);
4842 CIFSSMBSetEA(const int xid
, struct cifsTconInfo
*tcon
, const char *fileName
,
4843 const char * ea_name
, const void * ea_value
,
4844 const __u16 ea_value_len
, const struct nls_table
*nls_codepage
,
4847 struct smb_com_transaction2_spi_req
*pSMB
= NULL
;
4848 struct smb_com_transaction2_spi_rsp
*pSMBr
= NULL
;
4849 struct fealist
*parm_data
;
4852 int bytes_returned
= 0;
4853 __u16 params
, param_offset
, byte_count
, offset
, count
;
4855 cFYI(1, ("In SetEA"));
4857 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
4862 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
4864 cifsConvertToUCS((__le16
*) pSMB
->FileName
, fileName
,
4865 PATH_MAX
, nls_codepage
, remap
);
4866 name_len
++; /* trailing null */
4868 } else { /* BB improve the check for buffer overruns BB */
4869 name_len
= strnlen(fileName
, PATH_MAX
);
4870 name_len
++; /* trailing null */
4871 strncpy(pSMB
->FileName
, fileName
, name_len
);
4874 params
= 6 + name_len
;
4876 /* done calculating parms using name_len of file name,
4877 now use name_len to calculate length of ea name
4878 we are going to create in the inode xattrs */
4882 name_len
= strnlen(ea_name
,255);
4884 count
= sizeof(*parm_data
) + ea_value_len
+ name_len
+ 1;
4885 pSMB
->MaxParameterCount
= cpu_to_le16(2);
4886 pSMB
->MaxDataCount
= cpu_to_le16(1000); /* BB find max SMB size from sess */
4887 pSMB
->MaxSetupCount
= 0;
4891 pSMB
->Reserved2
= 0;
4892 param_offset
= offsetof(struct smb_com_transaction2_spi_req
,
4893 InformationLevel
) - 4;
4894 offset
= param_offset
+ params
;
4895 pSMB
->InformationLevel
=
4896 cpu_to_le16(SMB_SET_FILE_EA
);
4899 (struct fealist
*) (((char *) &pSMB
->hdr
.Protocol
) +
4901 pSMB
->ParameterOffset
= cpu_to_le16(param_offset
);
4902 pSMB
->DataOffset
= cpu_to_le16(offset
);
4903 pSMB
->SetupCount
= 1;
4904 pSMB
->Reserved3
= 0;
4905 pSMB
->SubCommand
= cpu_to_le16(TRANS2_SET_PATH_INFORMATION
);
4906 byte_count
= 3 /* pad */ + params
+ count
;
4907 pSMB
->DataCount
= cpu_to_le16(count
);
4908 parm_data
->list_len
= cpu_to_le32(count
);
4909 parm_data
->list
[0].EA_flags
= 0;
4910 /* we checked above that name len is less than 255 */
4911 parm_data
->list
[0].name_len
= (__u8
)name_len
;;
4912 /* EA names are always ASCII */
4914 strncpy(parm_data
->list
[0].name
,ea_name
,name_len
);
4915 parm_data
->list
[0].name
[name_len
] = 0;
4916 parm_data
->list
[0].value_len
= cpu_to_le16(ea_value_len
);
4917 /* caller ensures that ea_value_len is less than 64K but
4918 we need to ensure that it fits within the smb */
4920 /*BB add length check that it would fit in negotiated SMB buffer size BB */
4921 /* if(ea_value_len > buffer_size - 512 (enough for header)) */
4923 memcpy(parm_data
->list
[0].name
+name_len
+1,ea_value
,ea_value_len
);
4925 pSMB
->TotalDataCount
= pSMB
->DataCount
;
4926 pSMB
->ParameterCount
= cpu_to_le16(params
);
4927 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
4928 pSMB
->Reserved4
= 0;
4929 pSMB
->hdr
.smb_buf_length
+= byte_count
;
4930 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
4931 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
4932 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
4934 cFYI(1, ("SetPathInfo (EA) returned %d", rc
));
4937 cifs_buf_release(pSMB
);