4 * Copyright (C) International Business Machines Corp., 2002,2005
5 * Author(s): Steve French (sfrench@us.ibm.com)
7 * Contains the routines for constructing the SMB PDUs themselves
9 * This library is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU Lesser General Public License as published
11 * by the Free Software Foundation; either version 2.1 of the License, or
12 * (at your option) any later version.
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
17 * the GNU Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public License
20 * along with this library; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 /* SMB/CIFS PDU handling routines here - except for leftovers in connect.c */
25 /* These are mostly routines that operate on a pathname, or on a tree id */
26 /* (mounted volume), but there are eight handle based routines which must be */
27 /* treated slightly different for reconnection purposes since we never want */
28 /* to reuse a stale file handle and the caller knows the file handle */
31 #include <linux/kernel.h>
32 #include <linux/vfs.h>
33 #include <linux/posix_acl_xattr.h>
34 #include <asm/uaccess.h>
37 #include "cifsproto.h"
38 #include "cifs_unicode.h"
39 #include "cifs_debug.h"
41 #ifdef CONFIG_CIFS_POSIX
46 {CIFS_PROT
, "\2NT LM 0.12"},
47 {CIFS_PROT
, "\2POSIX 2"},
55 {CIFS_PROT
, "\2NT LM 0.12"},
61 /* Mark as invalid, all open files on tree connections since they
62 were closed when session to server was lost */
63 static void mark_open_files_invalid(struct cifsTconInfo
* pTcon
)
65 struct cifsFileInfo
*open_file
= NULL
;
66 struct list_head
* tmp
;
67 struct list_head
* tmp1
;
69 /* list all files open on tree connection and mark them invalid */
70 write_lock(&GlobalSMBSeslock
);
71 list_for_each_safe(tmp
, tmp1
, &pTcon
->openFileList
) {
72 open_file
= list_entry(tmp
,struct cifsFileInfo
, tlist
);
74 open_file
->invalidHandle
= TRUE
;
77 write_unlock(&GlobalSMBSeslock
);
78 /* BB Add call to invalidate_inodes(sb) for all superblocks mounted
82 /* If the return code is zero, this function must fill in request_buf pointer */
84 small_smb_init(int smb_command
, int wct
, struct cifsTconInfo
*tcon
,
85 void **request_buf
/* returned */)
89 /* SMBs NegProt, SessSetup, uLogoff do not have tcon yet so
90 check for tcp and smb session status done differently
91 for those three - in the calling routine */
93 if(tcon
->tidStatus
== CifsExiting
) {
94 /* only tree disconnect, open, and write,
95 (and ulogoff which does not have tcon)
96 are allowed as we start force umount */
97 if((smb_command
!= SMB_COM_WRITE_ANDX
) &&
98 (smb_command
!= SMB_COM_OPEN_ANDX
) &&
99 (smb_command
!= SMB_COM_TREE_DISCONNECT
)) {
100 cFYI(1,("can not send cmd %d while umounting",
105 if((tcon
->ses
) && (tcon
->ses
->status
!= CifsExiting
) &&
106 (tcon
->ses
->server
)){
107 struct nls_table
*nls_codepage
;
108 /* Give Demultiplex thread up to 10 seconds to
109 reconnect, should be greater than cifs socket
110 timeout which is 7 seconds */
111 while(tcon
->ses
->server
->tcpStatus
== CifsNeedReconnect
) {
112 wait_event_interruptible_timeout(tcon
->ses
->server
->response_q
,
113 (tcon
->ses
->server
->tcpStatus
== CifsGood
), 10 * HZ
);
114 if(tcon
->ses
->server
->tcpStatus
== CifsNeedReconnect
) {
115 /* on "soft" mounts we wait once */
116 if((tcon
->retry
== FALSE
) ||
117 (tcon
->ses
->status
== CifsExiting
)) {
118 cFYI(1,("gave up waiting on reconnect in smb_init"));
120 } /* else "hard" mount - keep retrying
121 until process is killed or server
122 comes back on-line */
123 } else /* TCP session is reestablished now */
128 nls_codepage
= load_nls_default();
129 /* need to prevent multiple threads trying to
130 simultaneously reconnect the same SMB session */
131 down(&tcon
->ses
->sesSem
);
132 if(tcon
->ses
->status
== CifsNeedReconnect
)
133 rc
= cifs_setup_session(0, tcon
->ses
,
135 if(!rc
&& (tcon
->tidStatus
== CifsNeedReconnect
)) {
136 mark_open_files_invalid(tcon
);
137 rc
= CIFSTCon(0, tcon
->ses
, tcon
->treeName
, tcon
139 up(&tcon
->ses
->sesSem
);
140 /* BB FIXME add code to check if wsize needs
141 update due to negotiated smb buffer size
144 atomic_inc(&tconInfoReconnectCount
);
146 cFYI(1, ("reconnect tcon rc = %d", rc
));
147 /* Removed call to reopen open files here -
148 it is safer (and faster) to reopen files
149 one at a time as needed in read and write */
151 /* Check if handle based operation so we
152 know whether we can continue or not without
153 returning to caller to reset file handle */
154 switch(smb_command
) {
155 case SMB_COM_READ_ANDX
:
156 case SMB_COM_WRITE_ANDX
:
158 case SMB_COM_FIND_CLOSE2
:
159 case SMB_COM_LOCKING_ANDX
: {
160 unload_nls(nls_codepage
);
165 up(&tcon
->ses
->sesSem
);
167 unload_nls(nls_codepage
);
176 *request_buf
= cifs_small_buf_get();
177 if (*request_buf
== NULL
) {
178 /* BB should we add a retry in here if not a writepage? */
182 header_assemble((struct smb_hdr
*) *request_buf
, smb_command
, tcon
,wct
);
185 cifs_stats_inc(&tcon
->num_smbs_sent
);
190 /* If the return code is zero, this function must fill in request_buf pointer */
192 smb_init(int smb_command
, int wct
, struct cifsTconInfo
*tcon
,
193 void **request_buf
/* returned */ ,
194 void **response_buf
/* returned */ )
198 /* SMBs NegProt, SessSetup, uLogoff do not have tcon yet so
199 check for tcp and smb session status done differently
200 for those three - in the calling routine */
202 if(tcon
->tidStatus
== CifsExiting
) {
203 /* only tree disconnect, open, and write,
204 (and ulogoff which does not have tcon)
205 are allowed as we start force umount */
206 if((smb_command
!= SMB_COM_WRITE_ANDX
) &&
207 (smb_command
!= SMB_COM_OPEN_ANDX
) &&
208 (smb_command
!= SMB_COM_TREE_DISCONNECT
)) {
209 cFYI(1,("can not send cmd %d while umounting",
215 if((tcon
->ses
) && (tcon
->ses
->status
!= CifsExiting
) &&
216 (tcon
->ses
->server
)){
217 struct nls_table
*nls_codepage
;
218 /* Give Demultiplex thread up to 10 seconds to
219 reconnect, should be greater than cifs socket
220 timeout which is 7 seconds */
221 while(tcon
->ses
->server
->tcpStatus
== CifsNeedReconnect
) {
222 wait_event_interruptible_timeout(tcon
->ses
->server
->response_q
,
223 (tcon
->ses
->server
->tcpStatus
== CifsGood
), 10 * HZ
);
224 if(tcon
->ses
->server
->tcpStatus
==
226 /* on "soft" mounts we wait once */
227 if((tcon
->retry
== FALSE
) ||
228 (tcon
->ses
->status
== CifsExiting
)) {
229 cFYI(1,("gave up waiting on reconnect in smb_init"));
231 } /* else "hard" mount - keep retrying
232 until process is killed or server
234 } else /* TCP session is reestablished now */
239 nls_codepage
= load_nls_default();
240 /* need to prevent multiple threads trying to
241 simultaneously reconnect the same SMB session */
242 down(&tcon
->ses
->sesSem
);
243 if(tcon
->ses
->status
== CifsNeedReconnect
)
244 rc
= cifs_setup_session(0, tcon
->ses
,
246 if(!rc
&& (tcon
->tidStatus
== CifsNeedReconnect
)) {
247 mark_open_files_invalid(tcon
);
248 rc
= CIFSTCon(0, tcon
->ses
, tcon
->treeName
,
250 up(&tcon
->ses
->sesSem
);
251 /* BB FIXME add code to check if wsize needs
252 update due to negotiated smb buffer size
255 atomic_inc(&tconInfoReconnectCount
);
257 cFYI(1, ("reconnect tcon rc = %d", rc
));
258 /* Removed call to reopen open files here -
259 it is safer (and faster) to reopen files
260 one at a time as needed in read and write */
262 /* Check if handle based operation so we
263 know whether we can continue or not without
264 returning to caller to reset file handle */
265 switch(smb_command
) {
266 case SMB_COM_READ_ANDX
:
267 case SMB_COM_WRITE_ANDX
:
269 case SMB_COM_FIND_CLOSE2
:
270 case SMB_COM_LOCKING_ANDX
: {
271 unload_nls(nls_codepage
);
276 up(&tcon
->ses
->sesSem
);
278 unload_nls(nls_codepage
);
287 *request_buf
= cifs_buf_get();
288 if (*request_buf
== NULL
) {
289 /* BB should we add a retry in here if not a writepage? */
292 /* Although the original thought was we needed the response buf for */
293 /* potential retries of smb operations it turns out we can determine */
294 /* from the mid flags when the request buffer can be resent without */
295 /* having to use a second distinct buffer for the response */
296 *response_buf
= *request_buf
;
298 header_assemble((struct smb_hdr
*) *request_buf
, smb_command
, tcon
,
302 cifs_stats_inc(&tcon
->num_smbs_sent
);
307 static int validate_t2(struct smb_t2_rsp
* pSMB
)
313 /* check for plausible wct, bcc and t2 data and parm sizes */
314 /* check for parm and data offset going beyond end of smb */
315 if(pSMB
->hdr
.WordCount
>= 10) {
316 if((le16_to_cpu(pSMB
->t2_rsp
.ParameterOffset
) <= 1024) &&
317 (le16_to_cpu(pSMB
->t2_rsp
.DataOffset
) <= 1024)) {
318 /* check that bcc is at least as big as parms + data */
319 /* check that bcc is less than negotiated smb buffer */
320 total_size
= le16_to_cpu(pSMB
->t2_rsp
.ParameterCount
);
321 if(total_size
< 512) {
322 total_size
+=le16_to_cpu(pSMB
->t2_rsp
.DataCount
);
323 /* BCC le converted in SendReceive */
324 pBCC
= (pSMB
->hdr
.WordCount
* 2) +
325 sizeof(struct smb_hdr
) +
327 if((total_size
<= (*(u16
*)pBCC
)) &&
329 CIFSMaxBufSize
+MAX_CIFS_HDR_SIZE
)) {
336 cifs_dump_mem("Invalid transact2 SMB: ",(char *)pSMB
,
337 sizeof(struct smb_t2_rsp
) + 16);
341 CIFSSMBNegotiate(unsigned int xid
, struct cifsSesInfo
*ses
)
344 NEGOTIATE_RSP
*pSMBr
;
347 struct TCP_Server_Info
* server
;
351 server
= ses
->server
;
356 rc
= smb_init(SMB_COM_NEGOTIATE
, 0, NULL
/* no tcon yet */ ,
357 (void **) &pSMB
, (void **) &pSMBr
);
360 pSMB
->hdr
.Mid
= GetNextMid(server
);
361 pSMB
->hdr
.Flags2
|= SMBFLG2_UNICODE
;
362 if (extended_security
)
363 pSMB
->hdr
.Flags2
|= SMBFLG2_EXT_SEC
;
365 count
= strlen(protocols
[0].name
) + 1;
366 strncpy(pSMB
->DialectsArray
, protocols
[0].name
, 30);
367 /* null guaranteed to be at end of source and target buffers anyway */
369 pSMB
->hdr
.smb_buf_length
+= count
;
370 pSMB
->ByteCount
= cpu_to_le16(count
);
372 rc
= SendReceive(xid
, ses
, (struct smb_hdr
*) pSMB
,
373 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
375 server
->secMode
= pSMBr
->SecurityMode
;
376 server
->secType
= NTLM
; /* BB override default for
377 NTLMv2 or kerberos v5 */
378 /* one byte - no need to convert this or EncryptionKeyLen
379 from little endian */
380 server
->maxReq
= le16_to_cpu(pSMBr
->MaxMpxCount
);
381 /* probably no need to store and check maxvcs */
383 min(le32_to_cpu(pSMBr
->MaxBufferSize
),
384 (__u32
) CIFSMaxBufSize
+ MAX_CIFS_HDR_SIZE
);
385 server
->maxRw
= le32_to_cpu(pSMBr
->MaxRawSize
);
386 cFYI(0, ("Max buf = %d ", ses
->server
->maxBuf
));
387 GETU32(ses
->server
->sessid
) = le32_to_cpu(pSMBr
->SessionKey
);
388 server
->capabilities
= le32_to_cpu(pSMBr
->Capabilities
);
389 server
->timeZone
= le16_to_cpu(pSMBr
->ServerTimeZone
);
390 /* BB with UTC do we ever need to be using srvr timezone? */
391 if (pSMBr
->EncryptionKeyLength
== CIFS_CRYPTO_KEY_SIZE
) {
392 memcpy(server
->cryptKey
, pSMBr
->u
.EncryptionKey
,
393 CIFS_CRYPTO_KEY_SIZE
);
394 } else if ((pSMBr
->hdr
.Flags2
& SMBFLG2_EXT_SEC
)
395 && (pSMBr
->EncryptionKeyLength
== 0)) {
396 /* decode security blob */
400 /* BB might be helpful to save off the domain of server here */
402 if ((pSMBr
->hdr
.Flags2
& SMBFLG2_EXT_SEC
) &&
403 (server
->capabilities
& CAP_EXTENDED_SECURITY
)) {
404 count
= pSMBr
->ByteCount
;
407 else if (count
== 16) {
408 server
->secType
= RawNTLMSSP
;
409 if (server
->socketUseCount
.counter
> 1) {
411 (server
->server_GUID
,
412 pSMBr
->u
.extended_response
.
415 ("UID of server does not match previous connection to same ip address"));
423 memcpy(server
->server_GUID
,
424 pSMBr
->u
.extended_response
.
427 rc
= decode_negTokenInit(pSMBr
->u
.
433 /* BB Need to fill struct for sessetup here */
440 server
->capabilities
&= ~CAP_EXTENDED_SECURITY
;
441 if(sign_CIFS_PDUs
== FALSE
) {
442 if(server
->secMode
& SECMODE_SIGN_REQUIRED
)
444 ("Server requires /proc/fs/cifs/PacketSigningEnabled"));
445 server
->secMode
&= ~(SECMODE_SIGN_ENABLED
| SECMODE_SIGN_REQUIRED
);
446 } else if(sign_CIFS_PDUs
== 1) {
447 if((server
->secMode
& SECMODE_SIGN_REQUIRED
) == 0)
448 server
->secMode
&= ~(SECMODE_SIGN_ENABLED
| SECMODE_SIGN_REQUIRED
);
453 cifs_buf_release(pSMB
);
458 CIFSSMBTDis(const int xid
, struct cifsTconInfo
*tcon
)
460 struct smb_hdr
*smb_buffer
;
461 struct smb_hdr
*smb_buffer_response
; /* BB removeme BB */
465 cFYI(1, ("In tree disconnect"));
467 * If last user of the connection and
468 * connection alive - disconnect it
469 * If this is the last connection on the server session disconnect it
470 * (and inside session disconnect we should check if tcp socket needs
471 * to be freed and kernel thread woken up).
474 down(&tcon
->tconSem
);
478 atomic_dec(&tcon
->useCount
);
479 if (atomic_read(&tcon
->useCount
) > 0) {
484 /* No need to return error on this operation if tid invalidated and
485 closed on server already e.g. due to tcp session crashing */
486 if(tcon
->tidStatus
== CifsNeedReconnect
) {
491 if((tcon
->ses
== NULL
) || (tcon
->ses
->server
== NULL
)) {
495 rc
= small_smb_init(SMB_COM_TREE_DISCONNECT
, 0, tcon
,
496 (void **)&smb_buffer
);
501 smb_buffer_response
= smb_buffer
; /* BB removeme BB */
503 rc
= SendReceive(xid
, tcon
->ses
, smb_buffer
, smb_buffer_response
,
506 cFYI(1, ("Tree disconnect failed %d", rc
));
509 cifs_small_buf_release(smb_buffer
);
512 /* No need to return error on this operation if tid invalidated and
513 closed on server already e.g. due to tcp session crashing */
521 CIFSSMBLogoff(const int xid
, struct cifsSesInfo
*ses
)
523 struct smb_hdr
*smb_buffer_response
;
524 LOGOFF_ANDX_REQ
*pSMB
;
528 cFYI(1, ("In SMBLogoff for session disconnect"));
534 atomic_dec(&ses
->inUse
);
535 if (atomic_read(&ses
->inUse
) > 0) {
539 rc
= small_smb_init(SMB_COM_LOGOFF_ANDX
, 2, NULL
, (void **)&pSMB
);
545 smb_buffer_response
= (struct smb_hdr
*)pSMB
; /* BB removeme BB */
548 pSMB
->hdr
.Mid
= GetNextMid(ses
->server
);
550 if(ses
->server
->secMode
&
551 (SECMODE_SIGN_REQUIRED
| SECMODE_SIGN_ENABLED
))
552 pSMB
->hdr
.Flags2
|= SMBFLG2_SECURITY_SIGNATURE
;
555 pSMB
->hdr
.Uid
= ses
->Suid
;
557 pSMB
->AndXCommand
= 0xFF;
558 rc
= SendReceive(xid
, ses
, (struct smb_hdr
*) pSMB
,
559 smb_buffer_response
, &length
, 0);
561 atomic_dec(&ses
->server
->socketUseCount
);
562 if (atomic_read(&ses
->server
->socketUseCount
) == 0) {
563 spin_lock(&GlobalMid_Lock
);
564 ses
->server
->tcpStatus
= CifsExiting
;
565 spin_unlock(&GlobalMid_Lock
);
570 cifs_small_buf_release(pSMB
);
572 /* if session dead then we do not need to do ulogoff,
573 since server closed smb session, no sense reporting
581 CIFSSMBDelFile(const int xid
, struct cifsTconInfo
*tcon
, const char *fileName
,
582 const struct nls_table
*nls_codepage
, int remap
)
584 DELETE_FILE_REQ
*pSMB
= NULL
;
585 DELETE_FILE_RSP
*pSMBr
= NULL
;
591 rc
= smb_init(SMB_COM_DELETE
, 1, tcon
, (void **) &pSMB
,
596 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
598 cifsConvertToUCS((__le16
*) pSMB
->fileName
, fileName
,
599 PATH_MAX
, nls_codepage
, remap
);
600 name_len
++; /* trailing null */
602 } else { /* BB improve check for buffer overruns BB */
603 name_len
= strnlen(fileName
, PATH_MAX
);
604 name_len
++; /* trailing null */
605 strncpy(pSMB
->fileName
, fileName
, name_len
);
607 pSMB
->SearchAttributes
=
608 cpu_to_le16(ATTR_READONLY
| ATTR_HIDDEN
| ATTR_SYSTEM
);
609 pSMB
->BufferFormat
= 0x04;
610 pSMB
->hdr
.smb_buf_length
+= name_len
+ 1;
611 pSMB
->ByteCount
= cpu_to_le16(name_len
+ 1);
612 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
613 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
614 cifs_stats_inc(&tcon
->num_deletes
);
616 cFYI(1, ("Error in RMFile = %d", rc
));
619 cifs_buf_release(pSMB
);
627 CIFSSMBRmDir(const int xid
, struct cifsTconInfo
*tcon
, const char *dirName
,
628 const struct nls_table
*nls_codepage
, int remap
)
630 DELETE_DIRECTORY_REQ
*pSMB
= NULL
;
631 DELETE_DIRECTORY_RSP
*pSMBr
= NULL
;
636 cFYI(1, ("In CIFSSMBRmDir"));
638 rc
= smb_init(SMB_COM_DELETE_DIRECTORY
, 0, tcon
, (void **) &pSMB
,
643 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
644 name_len
= cifsConvertToUCS((__le16
*) pSMB
->DirName
, dirName
,
645 PATH_MAX
, nls_codepage
, remap
);
646 name_len
++; /* trailing null */
648 } else { /* BB improve check for buffer overruns BB */
649 name_len
= strnlen(dirName
, PATH_MAX
);
650 name_len
++; /* trailing null */
651 strncpy(pSMB
->DirName
, dirName
, name_len
);
654 pSMB
->BufferFormat
= 0x04;
655 pSMB
->hdr
.smb_buf_length
+= name_len
+ 1;
656 pSMB
->ByteCount
= cpu_to_le16(name_len
+ 1);
657 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
658 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
659 cifs_stats_inc(&tcon
->num_rmdirs
);
661 cFYI(1, ("Error in RMDir = %d", rc
));
664 cifs_buf_release(pSMB
);
671 CIFSSMBMkDir(const int xid
, struct cifsTconInfo
*tcon
,
672 const char *name
, const struct nls_table
*nls_codepage
, int remap
)
675 CREATE_DIRECTORY_REQ
*pSMB
= NULL
;
676 CREATE_DIRECTORY_RSP
*pSMBr
= NULL
;
680 cFYI(1, ("In CIFSSMBMkDir"));
682 rc
= smb_init(SMB_COM_CREATE_DIRECTORY
, 0, tcon
, (void **) &pSMB
,
687 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
688 name_len
= cifsConvertToUCS((__le16
*) pSMB
->DirName
, name
,
689 PATH_MAX
, nls_codepage
, remap
);
690 name_len
++; /* trailing null */
692 } else { /* BB improve check for buffer overruns BB */
693 name_len
= strnlen(name
, PATH_MAX
);
694 name_len
++; /* trailing null */
695 strncpy(pSMB
->DirName
, name
, name_len
);
698 pSMB
->BufferFormat
= 0x04;
699 pSMB
->hdr
.smb_buf_length
+= name_len
+ 1;
700 pSMB
->ByteCount
= cpu_to_le16(name_len
+ 1);
701 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
702 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
703 cifs_stats_inc(&tcon
->num_mkdirs
);
705 cFYI(1, ("Error in Mkdir = %d", rc
));
708 cifs_buf_release(pSMB
);
714 static __u16
convert_disposition(int disposition
)
718 switch (disposition
) {
720 ofun
= SMBOPEN_OCREATE
| SMBOPEN_OTRUNC
;
723 ofun
= SMBOPEN_OAPPEND
;
726 ofun
= SMBOPEN_OCREATE
;
729 ofun
= SMBOPEN_OCREATE
| SMBOPEN_OAPPEND
;
732 ofun
= SMBOPEN_OTRUNC
;
734 case FILE_OVERWRITE_IF
:
735 ofun
= SMBOPEN_OCREATE
| SMBOPEN_OTRUNC
;
738 cFYI(1,("unknown disposition %d",disposition
));
739 ofun
= SMBOPEN_OAPPEND
; /* regular open */
745 SMBLegacyOpen(const int xid
, struct cifsTconInfo
*tcon
,
746 const char *fileName
, const int openDisposition
,
747 const int access_flags
, const int create_options
, __u16
* netfid
,
748 int *pOplock
, FILE_ALL_INFO
* pfile_info
,
749 const struct nls_table
*nls_codepage
, int remap
)
752 OPENX_REQ
*pSMB
= NULL
;
753 OPENX_RSP
*pSMBr
= NULL
;
759 rc
= smb_init(SMB_COM_OPEN_ANDX
, 15, tcon
, (void **) &pSMB
,
764 pSMB
->AndXCommand
= 0xFF; /* none */
766 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
767 count
= 1; /* account for one byte pad to word boundary */
769 cifsConvertToUCS((__le16
*) (pSMB
->fileName
+ 1),
770 fileName
, PATH_MAX
, nls_codepage
, remap
);
771 name_len
++; /* trailing null */
773 } else { /* BB improve check for buffer overruns BB */
774 count
= 0; /* no pad */
775 name_len
= strnlen(fileName
, PATH_MAX
);
776 name_len
++; /* trailing null */
777 strncpy(pSMB
->fileName
, fileName
, name_len
);
779 if (*pOplock
& REQ_OPLOCK
)
780 pSMB
->OpenFlags
= cpu_to_le16(REQ_OPLOCK
);
781 else if (*pOplock
& REQ_BATCHOPLOCK
) {
782 pSMB
->OpenFlags
= cpu_to_le16(REQ_BATCHOPLOCK
);
784 pSMB
->OpenFlags
|= cpu_to_le16(REQ_MORE_INFO
);
785 /* BB fixme add conversion for access_flags to bits 0 - 2 of mode */
791 pSMB
->Mode
= cpu_to_le16(2);
792 pSMB
->Mode
|= cpu_to_le16(0x40); /* deny none */
793 /* set file as system file if special file such
794 as fifo and server expecting SFU style and
795 no Unix extensions */
797 if(create_options
& CREATE_OPTION_SPECIAL
)
798 pSMB
->FileAttributes
= cpu_to_le16(ATTR_SYSTEM
);
800 pSMB
->FileAttributes
= cpu_to_le16(0/*ATTR_NORMAL*/); /* BB FIXME */
802 /* if ((omode & S_IWUGO) == 0)
803 pSMB->FileAttributes |= cpu_to_le32(ATTR_READONLY);*/
804 /* Above line causes problems due to vfs splitting create into two
805 pieces - need to set mode after file created not while it is
809 /* pSMB->CreateOptions = cpu_to_le32(create_options & CREATE_OPTIONS_MASK); */
810 /* BB FIXME END BB */
812 pSMB
->Sattr
= cpu_to_le16(ATTR_HIDDEN
| ATTR_SYSTEM
| ATTR_DIRECTORY
);
813 pSMB
->OpenFunction
= cpu_to_le16(convert_disposition(openDisposition
));
815 pSMB
->hdr
.smb_buf_length
+= count
;
817 pSMB
->ByteCount
= cpu_to_le16(count
);
818 /* long_op set to 1 to allow for oplock break timeouts */
819 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
820 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 1);
821 cifs_stats_inc(&tcon
->num_opens
);
823 cFYI(1, ("Error in Open = %d", rc
));
825 /* BB verify if wct == 15 */
827 /* *pOplock = pSMBr->OplockLevel; */ /* BB take from action field BB */
829 *netfid
= pSMBr
->Fid
; /* cifs fid stays in le */
830 /* Let caller know file was created so we can set the mode. */
831 /* Do we care about the CreateAction in any other cases? */
833 /* if(cpu_to_le32(FILE_CREATE) == pSMBr->CreateAction)
834 *pOplock |= CIFS_CREATE_ACTION; */
838 pfile_info
->CreationTime
= 0; /* BB convert CreateTime*/
839 pfile_info
->LastAccessTime
= 0; /* BB fixme */
840 pfile_info
->LastWriteTime
= 0; /* BB fixme */
841 pfile_info
->ChangeTime
= 0; /* BB fixme */
842 pfile_info
->Attributes
=
843 cpu_to_le32(le16_to_cpu(pSMBr
->FileAttributes
));
844 /* the file_info buf is endian converted by caller */
845 pfile_info
->AllocationSize
=
846 cpu_to_le64(le32_to_cpu(pSMBr
->EndOfFile
));
847 pfile_info
->EndOfFile
= pfile_info
->AllocationSize
;
848 pfile_info
->NumberOfLinks
= cpu_to_le32(1);
852 cifs_buf_release(pSMB
);
859 CIFSSMBOpen(const int xid
, struct cifsTconInfo
*tcon
,
860 const char *fileName
, const int openDisposition
,
861 const int access_flags
, const int create_options
, __u16
* netfid
,
862 int *pOplock
, FILE_ALL_INFO
* pfile_info
,
863 const struct nls_table
*nls_codepage
, int remap
)
866 OPEN_REQ
*pSMB
= NULL
;
867 OPEN_RSP
*pSMBr
= NULL
;
873 rc
= smb_init(SMB_COM_NT_CREATE_ANDX
, 24, tcon
, (void **) &pSMB
,
878 pSMB
->AndXCommand
= 0xFF; /* none */
880 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
881 count
= 1; /* account for one byte pad to word boundary */
883 cifsConvertToUCS((__le16
*) (pSMB
->fileName
+ 1),
884 fileName
, PATH_MAX
, nls_codepage
, remap
);
885 name_len
++; /* trailing null */
887 pSMB
->NameLength
= cpu_to_le16(name_len
);
888 } else { /* BB improve check for buffer overruns BB */
889 count
= 0; /* no pad */
890 name_len
= strnlen(fileName
, PATH_MAX
);
891 name_len
++; /* trailing null */
892 pSMB
->NameLength
= cpu_to_le16(name_len
);
893 strncpy(pSMB
->fileName
, fileName
, name_len
);
895 if (*pOplock
& REQ_OPLOCK
)
896 pSMB
->OpenFlags
= cpu_to_le32(REQ_OPLOCK
);
897 else if (*pOplock
& REQ_BATCHOPLOCK
) {
898 pSMB
->OpenFlags
= cpu_to_le32(REQ_BATCHOPLOCK
);
900 pSMB
->DesiredAccess
= cpu_to_le32(access_flags
);
901 pSMB
->AllocationSize
= 0;
902 /* set file as system file if special file such
903 as fifo and server expecting SFU style and
904 no Unix extensions */
905 if(create_options
& CREATE_OPTION_SPECIAL
)
906 pSMB
->FileAttributes
= cpu_to_le32(ATTR_SYSTEM
);
908 pSMB
->FileAttributes
= cpu_to_le32(ATTR_NORMAL
);
909 /* XP does not handle ATTR_POSIX_SEMANTICS */
910 /* but it helps speed up case sensitive checks for other
911 servers such as Samba */
912 if (tcon
->ses
->capabilities
& CAP_UNIX
)
913 pSMB
->FileAttributes
|= cpu_to_le32(ATTR_POSIX_SEMANTICS
);
915 /* if ((omode & S_IWUGO) == 0)
916 pSMB->FileAttributes |= cpu_to_le32(ATTR_READONLY);*/
917 /* Above line causes problems due to vfs splitting create into two
918 pieces - need to set mode after file created not while it is
920 pSMB
->ShareAccess
= cpu_to_le32(FILE_SHARE_ALL
);
921 pSMB
->CreateDisposition
= cpu_to_le32(openDisposition
);
922 pSMB
->CreateOptions
= cpu_to_le32(create_options
& CREATE_OPTIONS_MASK
);
923 /* BB Expirement with various impersonation levels and verify */
924 pSMB
->ImpersonationLevel
= cpu_to_le32(SECURITY_IMPERSONATION
);
925 pSMB
->SecurityFlags
=
926 SECURITY_CONTEXT_TRACKING
| SECURITY_EFFECTIVE_ONLY
;
929 pSMB
->hdr
.smb_buf_length
+= count
;
931 pSMB
->ByteCount
= cpu_to_le16(count
);
932 /* long_op set to 1 to allow for oplock break timeouts */
933 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
934 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 1);
935 cifs_stats_inc(&tcon
->num_opens
);
937 cFYI(1, ("Error in Open = %d", rc
));
939 *pOplock
= pSMBr
->OplockLevel
; /* 1 byte no need to le_to_cpu */
940 *netfid
= pSMBr
->Fid
; /* cifs fid stays in le */
941 /* Let caller know file was created so we can set the mode. */
942 /* Do we care about the CreateAction in any other cases? */
943 if(cpu_to_le32(FILE_CREATE
) == pSMBr
->CreateAction
)
944 *pOplock
|= CIFS_CREATE_ACTION
;
946 memcpy((char *)pfile_info
,(char *)&pSMBr
->CreationTime
,
947 36 /* CreationTime to Attributes */);
948 /* the file_info buf is endian converted by caller */
949 pfile_info
->AllocationSize
= pSMBr
->AllocationSize
;
950 pfile_info
->EndOfFile
= pSMBr
->EndOfFile
;
951 pfile_info
->NumberOfLinks
= cpu_to_le32(1);
955 cifs_buf_release(pSMB
);
961 /* If no buffer passed in, then caller wants to do the copy
962 as in the case of readpages so the SMB buffer must be
963 freed by the caller */
966 CIFSSMBRead(const int xid
, struct cifsTconInfo
*tcon
,
967 const int netfid
, const unsigned int count
,
968 const __u64 lseek
, unsigned int *nbytes
, char **buf
)
971 READ_REQ
*pSMB
= NULL
;
972 READ_RSP
*pSMBr
= NULL
;
973 char *pReadData
= NULL
;
977 cFYI(1,("Reading %d bytes on fid %d",count
,netfid
));
978 if(tcon
->ses
->capabilities
& CAP_LARGE_FILES
)
981 wct
= 10; /* old style read */
984 rc
= smb_init(SMB_COM_READ_ANDX
, wct
, tcon
, (void **) &pSMB
,
989 /* tcon and ses pointer are checked in smb_init */
990 if (tcon
->ses
->server
== NULL
)
991 return -ECONNABORTED
;
993 pSMB
->AndXCommand
= 0xFF; /* none */
995 pSMB
->OffsetLow
= cpu_to_le32(lseek
& 0xFFFFFFFF);
997 pSMB
->OffsetHigh
= cpu_to_le32(lseek
>> 32);
998 else if((lseek
>> 32) > 0) /* can not handle this big offset for old */
1001 pSMB
->Remaining
= 0;
1002 pSMB
->MaxCount
= cpu_to_le16(count
& 0xFFFF);
1003 pSMB
->MaxCountHigh
= cpu_to_le32(count
>> 16);
1005 pSMB
->ByteCount
= 0; /* no need to do le conversion since 0 */
1007 /* old style read */
1008 struct smb_com_readx_req
* pSMBW
=
1009 (struct smb_com_readx_req
*)pSMB
;
1010 pSMBW
->ByteCount
= 0;
1013 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
1014 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
1015 cifs_stats_inc(&tcon
->num_reads
);
1017 cERROR(1, ("Send error in read = %d", rc
));
1019 int data_length
= le16_to_cpu(pSMBr
->DataLengthHigh
);
1020 data_length
= data_length
<< 16;
1021 data_length
+= le16_to_cpu(pSMBr
->DataLength
);
1022 *nbytes
= data_length
;
1024 /*check that DataLength would not go beyond end of SMB */
1025 if ((data_length
> CIFSMaxBufSize
)
1026 || (data_length
> count
)) {
1027 cFYI(1,("bad length %d for count %d",data_length
,count
));
1032 (char *) (&pSMBr
->hdr
.Protocol
) +
1033 le16_to_cpu(pSMBr
->DataOffset
);
1034 /* if(rc = copy_to_user(buf, pReadData, data_length)) {
1035 cERROR(1,("Faulting on read rc = %d",rc));
1037 }*/ /* can not use copy_to_user when using page cache*/
1039 memcpy(*buf
,pReadData
,data_length
);
1043 cifs_buf_release(pSMB
);
1045 *buf
= (char *)pSMB
;
1047 /* Note: On -EAGAIN error only caller can retry on handle based calls
1048 since file handle passed in no longer valid */
1053 CIFSSMBWrite(const int xid
, struct cifsTconInfo
*tcon
,
1054 const int netfid
, const unsigned int count
,
1055 const __u64 offset
, unsigned int *nbytes
, const char *buf
,
1056 const char __user
* ubuf
, const int long_op
)
1059 WRITE_REQ
*pSMB
= NULL
;
1060 WRITE_RSP
*pSMBr
= NULL
;
1061 int bytes_returned
, wct
;
1065 /* cFYI(1,("write at %lld %d bytes",offset,count));*/
1066 if(tcon
->ses
== NULL
)
1067 return -ECONNABORTED
;
1069 if(tcon
->ses
->capabilities
& CAP_LARGE_FILES
)
1074 rc
= smb_init(SMB_COM_WRITE_ANDX
, wct
, tcon
, (void **) &pSMB
,
1078 /* tcon and ses pointer are checked in smb_init */
1079 if (tcon
->ses
->server
== NULL
)
1080 return -ECONNABORTED
;
1082 pSMB
->AndXCommand
= 0xFF; /* none */
1084 pSMB
->OffsetLow
= cpu_to_le32(offset
& 0xFFFFFFFF);
1086 pSMB
->OffsetHigh
= cpu_to_le32(offset
>> 32);
1087 else if((offset
>> 32) > 0) /* can not handle this big offset for old */
1090 pSMB
->Reserved
= 0xFFFFFFFF;
1091 pSMB
->WriteMode
= 0;
1092 pSMB
->Remaining
= 0;
1094 /* Can increase buffer size if buffer is big enough in some cases - ie we
1095 can send more if LARGE_WRITE_X capability returned by the server and if
1096 our buffer is big enough or if we convert to iovecs on socket writes
1097 and eliminate the copy to the CIFS buffer */
1098 if(tcon
->ses
->capabilities
& CAP_LARGE_WRITE_X
) {
1099 bytes_sent
= min_t(const unsigned int, CIFSMaxBufSize
, count
);
1101 bytes_sent
= (tcon
->ses
->server
->maxBuf
- MAX_CIFS_HDR_SIZE
)
1105 if (bytes_sent
> count
)
1108 cpu_to_le16(offsetof(struct smb_com_write_req
,Data
) - 4);
1110 memcpy(pSMB
->Data
,buf
,bytes_sent
);
1112 if(copy_from_user(pSMB
->Data
,ubuf
,bytes_sent
)) {
1113 cifs_buf_release(pSMB
);
1116 } else if (count
!= 0) {
1118 cifs_buf_release(pSMB
);
1120 } /* else setting file size with write of zero bytes */
1122 byte_count
= bytes_sent
+ 1; /* pad */
1123 else /* wct == 12 */ {
1124 byte_count
= bytes_sent
+ 5; /* bigger pad, smaller smb hdr */
1126 pSMB
->DataLengthLow
= cpu_to_le16(bytes_sent
& 0xFFFF);
1127 pSMB
->DataLengthHigh
= cpu_to_le16(bytes_sent
>> 16);
1128 pSMB
->hdr
.smb_buf_length
+= byte_count
;
1131 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
1132 else { /* old style write has byte count 4 bytes earlier so 4 bytes pad */
1133 struct smb_com_writex_req
* pSMBW
=
1134 (struct smb_com_writex_req
*)pSMB
;
1135 pSMBW
->ByteCount
= cpu_to_le16(byte_count
);
1138 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
1139 (struct smb_hdr
*) pSMBr
, &bytes_returned
, long_op
);
1140 cifs_stats_inc(&tcon
->num_writes
);
1142 cFYI(1, ("Send error in write = %d", rc
));
1145 *nbytes
= le16_to_cpu(pSMBr
->CountHigh
);
1146 *nbytes
= (*nbytes
) << 16;
1147 *nbytes
+= le16_to_cpu(pSMBr
->Count
);
1150 cifs_buf_release(pSMB
);
1152 /* Note: On -EAGAIN error only caller can retry on handle based calls
1153 since file handle passed in no longer valid */
1158 #ifdef CONFIG_CIFS_EXPERIMENTAL
1160 CIFSSMBWrite2(const int xid
, struct cifsTconInfo
*tcon
,
1161 const int netfid
, const unsigned int count
,
1162 const __u64 offset
, unsigned int *nbytes
, struct kvec
*iov
,
1163 int n_vec
, const int long_op
)
1166 WRITE_REQ
*pSMB
= NULL
;
1167 int bytes_returned
, wct
;
1170 /* BB removeme BB */
1171 cFYI(1,("write2 at %lld %d bytes", (long long)offset
, count
));
1173 if(tcon
->ses
->capabilities
& CAP_LARGE_FILES
)
1177 rc
= small_smb_init(SMB_COM_WRITE_ANDX
, wct
, tcon
, (void **) &pSMB
);
1180 /* tcon and ses pointer are checked in smb_init */
1181 if (tcon
->ses
->server
== NULL
)
1182 return -ECONNABORTED
;
1184 pSMB
->AndXCommand
= 0xFF; /* none */
1186 pSMB
->OffsetLow
= cpu_to_le32(offset
& 0xFFFFFFFF);
1188 pSMB
->OffsetHigh
= cpu_to_le32(offset
>> 32);
1189 else if((offset
>> 32) > 0) /* can not handle this big offset for old */
1191 pSMB
->Reserved
= 0xFFFFFFFF;
1192 pSMB
->WriteMode
= 0;
1193 pSMB
->Remaining
= 0;
1196 cpu_to_le16(offsetof(struct smb_com_write_req
,Data
) - 4);
1198 pSMB
->DataLengthLow
= cpu_to_le16(count
& 0xFFFF);
1199 pSMB
->DataLengthHigh
= cpu_to_le16(count
>> 16);
1200 smb_hdr_len
= pSMB
->hdr
.smb_buf_length
+ 1; /* hdr + 1 byte pad */
1202 pSMB
->hdr
.smb_buf_length
+= count
+1;
1203 else /* wct == 12 */
1204 pSMB
->hdr
.smb_buf_length
+= count
+5; /* smb data starts later */
1206 pSMB
->ByteCount
= cpu_to_le16(count
+ 1);
1207 else /* wct == 12 */ /* bigger pad, smaller smb hdr, keep offset ok */ {
1208 struct smb_com_writex_req
* pSMBW
=
1209 (struct smb_com_writex_req
*)pSMB
;
1210 pSMBW
->ByteCount
= cpu_to_le16(count
+ 5);
1212 iov
[0].iov_base
= pSMB
;
1213 iov
[0].iov_len
= smb_hdr_len
+ 4;
1215 rc
= SendReceive2(xid
, tcon
->ses
, iov
, n_vec
+ 1, &bytes_returned
,
1217 cifs_stats_inc(&tcon
->num_writes
);
1219 cFYI(1, ("Send error Write2 = %d", rc
));
1222 WRITE_RSP
* pSMBr
= (WRITE_RSP
*)pSMB
;
1223 *nbytes
= le16_to_cpu(pSMBr
->CountHigh
);
1224 *nbytes
= (*nbytes
) << 16;
1225 *nbytes
+= le16_to_cpu(pSMBr
->Count
);
1228 cifs_small_buf_release(pSMB
);
1230 /* Note: On -EAGAIN error only caller can retry on handle based calls
1231 since file handle passed in no longer valid */
1237 #endif /* CIFS_EXPERIMENTAL */
1240 CIFSSMBLock(const int xid
, struct cifsTconInfo
*tcon
,
1241 const __u16 smb_file_id
, const __u64 len
,
1242 const __u64 offset
, const __u32 numUnlock
,
1243 const __u32 numLock
, const __u8 lockType
, const int waitFlag
)
1246 LOCK_REQ
*pSMB
= NULL
;
1247 LOCK_RSP
*pSMBr
= NULL
;
1252 cFYI(1, ("In CIFSSMBLock - timeout %d numLock %d",waitFlag
,numLock
));
1253 rc
= small_smb_init(SMB_COM_LOCKING_ANDX
, 8, tcon
, (void **) &pSMB
);
1258 pSMBr
= (LOCK_RSP
*)pSMB
; /* BB removeme BB */
1260 if(lockType
== LOCKING_ANDX_OPLOCK_RELEASE
) {
1261 timeout
= -1; /* no response expected */
1263 } else if (waitFlag
== TRUE
) {
1264 timeout
= 3; /* blocking operation, no timeout */
1265 pSMB
->Timeout
= cpu_to_le32(-1);/* blocking - do not time out */
1270 pSMB
->NumberOfLocks
= cpu_to_le16(numLock
);
1271 pSMB
->NumberOfUnlocks
= cpu_to_le16(numUnlock
);
1272 pSMB
->LockType
= lockType
;
1273 pSMB
->AndXCommand
= 0xFF; /* none */
1274 pSMB
->Fid
= smb_file_id
; /* netfid stays le */
1276 if((numLock
!= 0) || (numUnlock
!= 0)) {
1277 pSMB
->Locks
[0].Pid
= cpu_to_le16(current
->tgid
);
1278 /* BB where to store pid high? */
1279 pSMB
->Locks
[0].LengthLow
= cpu_to_le32((u32
)len
);
1280 pSMB
->Locks
[0].LengthHigh
= cpu_to_le32((u32
)(len
>>32));
1281 pSMB
->Locks
[0].OffsetLow
= cpu_to_le32((u32
)offset
);
1282 pSMB
->Locks
[0].OffsetHigh
= cpu_to_le32((u32
)(offset
>>32));
1283 count
= sizeof(LOCKING_ANDX_RANGE
);
1288 pSMB
->hdr
.smb_buf_length
+= count
;
1289 pSMB
->ByteCount
= cpu_to_le16(count
);
1291 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
1292 (struct smb_hdr
*) pSMBr
, &bytes_returned
, timeout
);
1293 cifs_stats_inc(&tcon
->num_locks
);
1295 cFYI(1, ("Send error in Lock = %d", rc
));
1297 cifs_small_buf_release(pSMB
);
1299 /* Note: On -EAGAIN error only caller can retry on handle based calls
1300 since file handle passed in no longer valid */
1305 CIFSSMBClose(const int xid
, struct cifsTconInfo
*tcon
, int smb_file_id
)
1308 CLOSE_REQ
*pSMB
= NULL
;
1309 CLOSE_RSP
*pSMBr
= NULL
;
1311 cFYI(1, ("In CIFSSMBClose"));
1313 /* do not retry on dead session on close */
1314 rc
= small_smb_init(SMB_COM_CLOSE
, 3, tcon
, (void **) &pSMB
);
1320 pSMBr
= (CLOSE_RSP
*)pSMB
; /* BB removeme BB */
1322 pSMB
->FileID
= (__u16
) smb_file_id
;
1323 pSMB
->LastWriteTime
= 0;
1324 pSMB
->ByteCount
= 0;
1325 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
1326 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
1327 cifs_stats_inc(&tcon
->num_closes
);
1330 /* EINTR is expected when user ctl-c to kill app */
1331 cERROR(1, ("Send error in Close = %d", rc
));
1335 cifs_small_buf_release(pSMB
);
1337 /* Since session is dead, file will be closed on server already */
1345 CIFSSMBRename(const int xid
, struct cifsTconInfo
*tcon
,
1346 const char *fromName
, const char *toName
,
1347 const struct nls_table
*nls_codepage
, int remap
)
1350 RENAME_REQ
*pSMB
= NULL
;
1351 RENAME_RSP
*pSMBr
= NULL
;
1353 int name_len
, name_len2
;
1356 cFYI(1, ("In CIFSSMBRename"));
1358 rc
= smb_init(SMB_COM_RENAME
, 1, tcon
, (void **) &pSMB
,
1363 pSMB
->BufferFormat
= 0x04;
1364 pSMB
->SearchAttributes
=
1365 cpu_to_le16(ATTR_READONLY
| ATTR_HIDDEN
| ATTR_SYSTEM
|
1368 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
1370 cifsConvertToUCS((__le16
*) pSMB
->OldFileName
, fromName
,
1371 PATH_MAX
, nls_codepage
, remap
);
1372 name_len
++; /* trailing null */
1374 pSMB
->OldFileName
[name_len
] = 0x04; /* pad */
1375 /* protocol requires ASCII signature byte on Unicode string */
1376 pSMB
->OldFileName
[name_len
+ 1] = 0x00;
1378 cifsConvertToUCS((__le16
*) &pSMB
->OldFileName
[name_len
+ 2],
1379 toName
, PATH_MAX
, nls_codepage
, remap
);
1380 name_len2
+= 1 /* trailing null */ + 1 /* Signature word */ ;
1381 name_len2
*= 2; /* convert to bytes */
1382 } else { /* BB improve the check for buffer overruns BB */
1383 name_len
= strnlen(fromName
, PATH_MAX
);
1384 name_len
++; /* trailing null */
1385 strncpy(pSMB
->OldFileName
, fromName
, name_len
);
1386 name_len2
= strnlen(toName
, PATH_MAX
);
1387 name_len2
++; /* trailing null */
1388 pSMB
->OldFileName
[name_len
] = 0x04; /* 2nd buffer format */
1389 strncpy(&pSMB
->OldFileName
[name_len
+ 1], toName
, name_len2
);
1390 name_len2
++; /* trailing null */
1391 name_len2
++; /* signature byte */
1394 count
= 1 /* 1st signature byte */ + name_len
+ name_len2
;
1395 pSMB
->hdr
.smb_buf_length
+= count
;
1396 pSMB
->ByteCount
= cpu_to_le16(count
);
1398 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
1399 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
1400 cifs_stats_inc(&tcon
->num_renames
);
1402 cFYI(1, ("Send error in rename = %d", rc
));
1405 cifs_buf_release(pSMB
);
1413 int CIFSSMBRenameOpenFile(const int xid
,struct cifsTconInfo
*pTcon
,
1414 int netfid
, char * target_name
,
1415 const struct nls_table
* nls_codepage
, int remap
)
1417 struct smb_com_transaction2_sfi_req
*pSMB
= NULL
;
1418 struct smb_com_transaction2_sfi_rsp
*pSMBr
= NULL
;
1419 struct set_file_rename
* rename_info
;
1421 char dummy_string
[30];
1423 int bytes_returned
= 0;
1425 __u16 params
, param_offset
, offset
, count
, byte_count
;
1427 cFYI(1, ("Rename to File by handle"));
1428 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, pTcon
, (void **) &pSMB
,
1434 pSMB
->MaxSetupCount
= 0;
1438 pSMB
->Reserved2
= 0;
1439 param_offset
= offsetof(struct smb_com_transaction2_sfi_req
, Fid
) - 4;
1440 offset
= param_offset
+ params
;
1442 data_offset
= (char *) (&pSMB
->hdr
.Protocol
) + offset
;
1443 rename_info
= (struct set_file_rename
*) data_offset
;
1444 pSMB
->MaxParameterCount
= cpu_to_le16(2);
1445 pSMB
->MaxDataCount
= cpu_to_le16(1000); /* BB find max SMB PDU from sess */
1446 pSMB
->SetupCount
= 1;
1447 pSMB
->Reserved3
= 0;
1448 pSMB
->SubCommand
= cpu_to_le16(TRANS2_SET_FILE_INFORMATION
);
1449 byte_count
= 3 /* pad */ + params
;
1450 pSMB
->ParameterCount
= cpu_to_le16(params
);
1451 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
1452 pSMB
->ParameterOffset
= cpu_to_le16(param_offset
);
1453 pSMB
->DataOffset
= cpu_to_le16(offset
);
1454 /* construct random name ".cifs_tmp<inodenum><mid>" */
1455 rename_info
->overwrite
= cpu_to_le32(1);
1456 rename_info
->root_fid
= 0;
1457 /* unicode only call */
1458 if(target_name
== NULL
) {
1459 sprintf(dummy_string
,"cifs%x",pSMB
->hdr
.Mid
);
1460 len_of_str
= cifsConvertToUCS((__le16
*)rename_info
->target_name
,
1461 dummy_string
, 24, nls_codepage
, remap
);
1463 len_of_str
= cifsConvertToUCS((__le16
*)rename_info
->target_name
,
1464 target_name
, PATH_MAX
, nls_codepage
, remap
);
1466 rename_info
->target_name_len
= cpu_to_le32(2 * len_of_str
);
1467 count
= 12 /* sizeof(struct set_file_rename) */ + (2 * len_of_str
) + 2;
1468 byte_count
+= count
;
1469 pSMB
->DataCount
= cpu_to_le16(count
);
1470 pSMB
->TotalDataCount
= pSMB
->DataCount
;
1472 pSMB
->InformationLevel
=
1473 cpu_to_le16(SMB_SET_FILE_RENAME_INFORMATION
);
1474 pSMB
->Reserved4
= 0;
1475 pSMB
->hdr
.smb_buf_length
+= byte_count
;
1476 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
1477 rc
= SendReceive(xid
, pTcon
->ses
, (struct smb_hdr
*) pSMB
,
1478 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
1479 cifs_stats_inc(&pTcon
->num_t2renames
);
1481 cFYI(1,("Send error in Rename (by file handle) = %d", rc
));
1484 cifs_buf_release(pSMB
);
1486 /* Note: On -EAGAIN error only caller can retry on handle based calls
1487 since file handle passed in no longer valid */
1493 CIFSSMBCopy(const int xid
, struct cifsTconInfo
*tcon
, const char * fromName
,
1494 const __u16 target_tid
, const char *toName
, const int flags
,
1495 const struct nls_table
*nls_codepage
, int remap
)
1498 COPY_REQ
*pSMB
= NULL
;
1499 COPY_RSP
*pSMBr
= NULL
;
1501 int name_len
, name_len2
;
1504 cFYI(1, ("In CIFSSMBCopy"));
1506 rc
= smb_init(SMB_COM_COPY
, 1, tcon
, (void **) &pSMB
,
1511 pSMB
->BufferFormat
= 0x04;
1512 pSMB
->Tid2
= target_tid
;
1514 pSMB
->Flags
= cpu_to_le16(flags
& COPY_TREE
);
1516 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
1517 name_len
= cifsConvertToUCS((__le16
*) pSMB
->OldFileName
,
1518 fromName
, PATH_MAX
, nls_codepage
,
1520 name_len
++; /* trailing null */
1522 pSMB
->OldFileName
[name_len
] = 0x04; /* pad */
1523 /* protocol requires ASCII signature byte on Unicode string */
1524 pSMB
->OldFileName
[name_len
+ 1] = 0x00;
1525 name_len2
= cifsConvertToUCS((__le16
*)&pSMB
->OldFileName
[name_len
+ 2],
1526 toName
, PATH_MAX
, nls_codepage
, remap
);
1527 name_len2
+= 1 /* trailing null */ + 1 /* Signature word */ ;
1528 name_len2
*= 2; /* convert to bytes */
1529 } else { /* BB improve the check for buffer overruns BB */
1530 name_len
= strnlen(fromName
, PATH_MAX
);
1531 name_len
++; /* trailing null */
1532 strncpy(pSMB
->OldFileName
, fromName
, name_len
);
1533 name_len2
= strnlen(toName
, PATH_MAX
);
1534 name_len2
++; /* trailing null */
1535 pSMB
->OldFileName
[name_len
] = 0x04; /* 2nd buffer format */
1536 strncpy(&pSMB
->OldFileName
[name_len
+ 1], toName
, name_len2
);
1537 name_len2
++; /* trailing null */
1538 name_len2
++; /* signature byte */
1541 count
= 1 /* 1st signature byte */ + name_len
+ name_len2
;
1542 pSMB
->hdr
.smb_buf_length
+= count
;
1543 pSMB
->ByteCount
= cpu_to_le16(count
);
1545 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
1546 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
1548 cFYI(1, ("Send error in copy = %d with %d files copied",
1549 rc
, le16_to_cpu(pSMBr
->CopyCount
)));
1552 cifs_buf_release(pSMB
);
1561 CIFSUnixCreateSymLink(const int xid
, struct cifsTconInfo
*tcon
,
1562 const char *fromName
, const char *toName
,
1563 const struct nls_table
*nls_codepage
)
1565 TRANSACTION2_SPI_REQ
*pSMB
= NULL
;
1566 TRANSACTION2_SPI_RSP
*pSMBr
= NULL
;
1569 int name_len_target
;
1571 int bytes_returned
= 0;
1572 __u16 params
, param_offset
, offset
, byte_count
;
1574 cFYI(1, ("In Symlink Unix style"));
1576 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
1581 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
1583 cifs_strtoUCS((__le16
*) pSMB
->FileName
, fromName
, PATH_MAX
1584 /* find define for this maxpathcomponent */
1586 name_len
++; /* trailing null */
1589 } else { /* BB improve the check for buffer overruns BB */
1590 name_len
= strnlen(fromName
, PATH_MAX
);
1591 name_len
++; /* trailing null */
1592 strncpy(pSMB
->FileName
, fromName
, name_len
);
1594 params
= 6 + name_len
;
1595 pSMB
->MaxSetupCount
= 0;
1599 pSMB
->Reserved2
= 0;
1600 param_offset
= offsetof(struct smb_com_transaction2_spi_req
,
1601 InformationLevel
) - 4;
1602 offset
= param_offset
+ params
;
1604 data_offset
= (char *) (&pSMB
->hdr
.Protocol
) + offset
;
1605 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
1607 cifs_strtoUCS((__le16
*) data_offset
, toName
, PATH_MAX
1608 /* find define for this maxpathcomponent */
1610 name_len_target
++; /* trailing null */
1611 name_len_target
*= 2;
1612 } else { /* BB improve the check for buffer overruns BB */
1613 name_len_target
= strnlen(toName
, PATH_MAX
);
1614 name_len_target
++; /* trailing null */
1615 strncpy(data_offset
, toName
, name_len_target
);
1618 pSMB
->MaxParameterCount
= cpu_to_le16(2);
1619 /* BB find exact max on data count below from sess */
1620 pSMB
->MaxDataCount
= cpu_to_le16(1000);
1621 pSMB
->SetupCount
= 1;
1622 pSMB
->Reserved3
= 0;
1623 pSMB
->SubCommand
= cpu_to_le16(TRANS2_SET_PATH_INFORMATION
);
1624 byte_count
= 3 /* pad */ + params
+ name_len_target
;
1625 pSMB
->DataCount
= cpu_to_le16(name_len_target
);
1626 pSMB
->ParameterCount
= cpu_to_le16(params
);
1627 pSMB
->TotalDataCount
= pSMB
->DataCount
;
1628 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
1629 pSMB
->ParameterOffset
= cpu_to_le16(param_offset
);
1630 pSMB
->DataOffset
= cpu_to_le16(offset
);
1631 pSMB
->InformationLevel
= cpu_to_le16(SMB_SET_FILE_UNIX_LINK
);
1632 pSMB
->Reserved4
= 0;
1633 pSMB
->hdr
.smb_buf_length
+= byte_count
;
1634 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
1635 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
1636 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
1637 cifs_stats_inc(&tcon
->num_symlinks
);
1640 ("Send error in SetPathInfo (create symlink) = %d",
1645 cifs_buf_release(pSMB
);
1648 goto createSymLinkRetry
;
1654 CIFSUnixCreateHardLink(const int xid
, struct cifsTconInfo
*tcon
,
1655 const char *fromName
, const char *toName
,
1656 const struct nls_table
*nls_codepage
, int remap
)
1658 TRANSACTION2_SPI_REQ
*pSMB
= NULL
;
1659 TRANSACTION2_SPI_RSP
*pSMBr
= NULL
;
1662 int name_len_target
;
1664 int bytes_returned
= 0;
1665 __u16 params
, param_offset
, offset
, byte_count
;
1667 cFYI(1, ("In Create Hard link Unix style"));
1668 createHardLinkRetry
:
1669 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
1674 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
1675 name_len
= cifsConvertToUCS((__le16
*) pSMB
->FileName
, toName
,
1676 PATH_MAX
, nls_codepage
, remap
);
1677 name_len
++; /* trailing null */
1680 } else { /* BB improve the check for buffer overruns BB */
1681 name_len
= strnlen(toName
, PATH_MAX
);
1682 name_len
++; /* trailing null */
1683 strncpy(pSMB
->FileName
, toName
, name_len
);
1685 params
= 6 + name_len
;
1686 pSMB
->MaxSetupCount
= 0;
1690 pSMB
->Reserved2
= 0;
1691 param_offset
= offsetof(struct smb_com_transaction2_spi_req
,
1692 InformationLevel
) - 4;
1693 offset
= param_offset
+ params
;
1695 data_offset
= (char *) (&pSMB
->hdr
.Protocol
) + offset
;
1696 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
1698 cifsConvertToUCS((__le16
*) data_offset
, fromName
, PATH_MAX
,
1699 nls_codepage
, remap
);
1700 name_len_target
++; /* trailing null */
1701 name_len_target
*= 2;
1702 } else { /* BB improve the check for buffer overruns BB */
1703 name_len_target
= strnlen(fromName
, PATH_MAX
);
1704 name_len_target
++; /* trailing null */
1705 strncpy(data_offset
, fromName
, name_len_target
);
1708 pSMB
->MaxParameterCount
= cpu_to_le16(2);
1709 /* BB find exact max on data count below from sess*/
1710 pSMB
->MaxDataCount
= cpu_to_le16(1000);
1711 pSMB
->SetupCount
= 1;
1712 pSMB
->Reserved3
= 0;
1713 pSMB
->SubCommand
= cpu_to_le16(TRANS2_SET_PATH_INFORMATION
);
1714 byte_count
= 3 /* pad */ + params
+ name_len_target
;
1715 pSMB
->ParameterCount
= cpu_to_le16(params
);
1716 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
1717 pSMB
->DataCount
= cpu_to_le16(name_len_target
);
1718 pSMB
->TotalDataCount
= pSMB
->DataCount
;
1719 pSMB
->ParameterOffset
= cpu_to_le16(param_offset
);
1720 pSMB
->DataOffset
= cpu_to_le16(offset
);
1721 pSMB
->InformationLevel
= cpu_to_le16(SMB_SET_FILE_UNIX_HLINK
);
1722 pSMB
->Reserved4
= 0;
1723 pSMB
->hdr
.smb_buf_length
+= byte_count
;
1724 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
1725 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
1726 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
1727 cifs_stats_inc(&tcon
->num_hardlinks
);
1729 cFYI(1, ("Send error in SetPathInfo (hard link) = %d", rc
));
1732 cifs_buf_release(pSMB
);
1734 goto createHardLinkRetry
;
1740 CIFSCreateHardLink(const int xid
, struct cifsTconInfo
*tcon
,
1741 const char *fromName
, const char *toName
,
1742 const struct nls_table
*nls_codepage
, int remap
)
1745 NT_RENAME_REQ
*pSMB
= NULL
;
1746 RENAME_RSP
*pSMBr
= NULL
;
1748 int name_len
, name_len2
;
1751 cFYI(1, ("In CIFSCreateHardLink"));
1752 winCreateHardLinkRetry
:
1754 rc
= smb_init(SMB_COM_NT_RENAME
, 4, tcon
, (void **) &pSMB
,
1759 pSMB
->SearchAttributes
=
1760 cpu_to_le16(ATTR_READONLY
| ATTR_HIDDEN
| ATTR_SYSTEM
|
1762 pSMB
->Flags
= cpu_to_le16(CREATE_HARD_LINK
);
1763 pSMB
->ClusterCount
= 0;
1765 pSMB
->BufferFormat
= 0x04;
1767 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
1769 cifsConvertToUCS((__le16
*) pSMB
->OldFileName
, fromName
,
1770 PATH_MAX
, nls_codepage
, remap
);
1771 name_len
++; /* trailing null */
1773 pSMB
->OldFileName
[name_len
] = 0; /* pad */
1774 pSMB
->OldFileName
[name_len
+ 1] = 0x04;
1776 cifsConvertToUCS((__le16
*)&pSMB
->OldFileName
[name_len
+ 2],
1777 toName
, PATH_MAX
, nls_codepage
, remap
);
1778 name_len2
+= 1 /* trailing null */ + 1 /* Signature word */ ;
1779 name_len2
*= 2; /* convert to bytes */
1780 } else { /* BB improve the check for buffer overruns BB */
1781 name_len
= strnlen(fromName
, PATH_MAX
);
1782 name_len
++; /* trailing null */
1783 strncpy(pSMB
->OldFileName
, fromName
, name_len
);
1784 name_len2
= strnlen(toName
, PATH_MAX
);
1785 name_len2
++; /* trailing null */
1786 pSMB
->OldFileName
[name_len
] = 0x04; /* 2nd buffer format */
1787 strncpy(&pSMB
->OldFileName
[name_len
+ 1], toName
, name_len2
);
1788 name_len2
++; /* trailing null */
1789 name_len2
++; /* signature byte */
1792 count
= 1 /* string type byte */ + name_len
+ name_len2
;
1793 pSMB
->hdr
.smb_buf_length
+= count
;
1794 pSMB
->ByteCount
= cpu_to_le16(count
);
1796 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
1797 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
1798 cifs_stats_inc(&tcon
->num_hardlinks
);
1800 cFYI(1, ("Send error in hard link (NT rename) = %d", rc
));
1802 cifs_buf_release(pSMB
);
1804 goto winCreateHardLinkRetry
;
1810 CIFSSMBUnixQuerySymLink(const int xid
, struct cifsTconInfo
*tcon
,
1811 const unsigned char *searchName
,
1812 char *symlinkinfo
, const int buflen
,
1813 const struct nls_table
*nls_codepage
)
1815 /* SMB_QUERY_FILE_UNIX_LINK */
1816 TRANSACTION2_QPI_REQ
*pSMB
= NULL
;
1817 TRANSACTION2_QPI_RSP
*pSMBr
= NULL
;
1821 __u16 params
, byte_count
;
1823 cFYI(1, ("In QPathSymLinkInfo (Unix) for path %s", searchName
));
1826 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
1831 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
1833 cifs_strtoUCS((__le16
*) pSMB
->FileName
, searchName
, PATH_MAX
1834 /* find define for this maxpathcomponent */
1836 name_len
++; /* trailing null */
1838 } else { /* BB improve the check for buffer overruns BB */
1839 name_len
= strnlen(searchName
, PATH_MAX
);
1840 name_len
++; /* trailing null */
1841 strncpy(pSMB
->FileName
, searchName
, name_len
);
1844 params
= 2 /* level */ + 4 /* rsrvd */ + name_len
/* incl null */ ;
1845 pSMB
->TotalDataCount
= 0;
1846 pSMB
->MaxParameterCount
= cpu_to_le16(2);
1847 /* BB find exact max data count below from sess structure BB */
1848 pSMB
->MaxDataCount
= cpu_to_le16(4000);
1849 pSMB
->MaxSetupCount
= 0;
1853 pSMB
->Reserved2
= 0;
1854 pSMB
->ParameterOffset
= cpu_to_le16(offsetof(
1855 struct smb_com_transaction2_qpi_req
,InformationLevel
) - 4);
1856 pSMB
->DataCount
= 0;
1857 pSMB
->DataOffset
= 0;
1858 pSMB
->SetupCount
= 1;
1859 pSMB
->Reserved3
= 0;
1860 pSMB
->SubCommand
= cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION
);
1861 byte_count
= params
+ 1 /* pad */ ;
1862 pSMB
->TotalParameterCount
= cpu_to_le16(params
);
1863 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
1864 pSMB
->InformationLevel
= cpu_to_le16(SMB_QUERY_FILE_UNIX_LINK
);
1865 pSMB
->Reserved4
= 0;
1866 pSMB
->hdr
.smb_buf_length
+= byte_count
;
1867 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
1869 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
1870 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
1872 cFYI(1, ("Send error in QuerySymLinkInfo = %d", rc
));
1874 /* decode response */
1876 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
1877 if (rc
|| (pSMBr
->ByteCount
< 2))
1878 /* BB also check enough total bytes returned */
1879 rc
= -EIO
; /* bad smb */
1881 __u16 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
1882 __u16 count
= le16_to_cpu(pSMBr
->t2
.DataCount
);
1884 if (pSMBr
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
1885 name_len
= UniStrnlen((wchar_t *) ((char *)
1886 &pSMBr
->hdr
.Protocol
+data_offset
),
1887 min_t(const int, buflen
,count
) / 2);
1888 /* BB FIXME investigate remapping reserved chars here */
1889 cifs_strfromUCS_le(symlinkinfo
,
1890 (__le16
*) ((char *)&pSMBr
->hdr
.Protocol
+
1892 name_len
, nls_codepage
);
1894 strncpy(symlinkinfo
,
1895 (char *) &pSMBr
->hdr
.Protocol
+
1897 min_t(const int, buflen
, count
));
1899 symlinkinfo
[buflen
] = 0;
1900 /* just in case so calling code does not go off the end of buffer */
1903 cifs_buf_release(pSMB
);
1905 goto querySymLinkRetry
;
1910 CIFSSMBQueryReparseLinkInfo(const int xid
, struct cifsTconInfo
*tcon
,
1911 const unsigned char *searchName
,
1912 char *symlinkinfo
, const int buflen
,__u16 fid
,
1913 const struct nls_table
*nls_codepage
)
1918 struct smb_com_transaction_ioctl_req
* pSMB
;
1919 struct smb_com_transaction_ioctl_rsp
* pSMBr
;
1921 cFYI(1, ("In Windows reparse style QueryLink for path %s", searchName
));
1922 rc
= smb_init(SMB_COM_NT_TRANSACT
, 23, tcon
, (void **) &pSMB
,
1927 pSMB
->TotalParameterCount
= 0 ;
1928 pSMB
->TotalDataCount
= 0;
1929 pSMB
->MaxParameterCount
= cpu_to_le32(2);
1930 /* BB find exact data count max from sess structure BB */
1931 pSMB
->MaxDataCount
= cpu_to_le32(4000);
1932 pSMB
->MaxSetupCount
= 4;
1934 pSMB
->ParameterOffset
= 0;
1935 pSMB
->DataCount
= 0;
1936 pSMB
->DataOffset
= 0;
1937 pSMB
->SetupCount
= 4;
1938 pSMB
->SubCommand
= cpu_to_le16(NT_TRANSACT_IOCTL
);
1939 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
1940 pSMB
->FunctionCode
= cpu_to_le32(FSCTL_GET_REPARSE_POINT
);
1941 pSMB
->IsFsctl
= 1; /* FSCTL */
1942 pSMB
->IsRootFlag
= 0;
1943 pSMB
->Fid
= fid
; /* file handle always le */
1944 pSMB
->ByteCount
= 0;
1946 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
1947 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
1949 cFYI(1, ("Send error in QueryReparseLinkInfo = %d", rc
));
1950 } else { /* decode response */
1951 __u32 data_offset
= le32_to_cpu(pSMBr
->DataOffset
);
1952 __u32 data_count
= le32_to_cpu(pSMBr
->DataCount
);
1953 if ((pSMBr
->ByteCount
< 2) || (data_offset
> 512))
1954 /* BB also check enough total bytes returned */
1955 rc
= -EIO
; /* bad smb */
1957 if(data_count
&& (data_count
< 2048)) {
1958 char * end_of_smb
= pSMBr
->ByteCount
+ (char *)&pSMBr
->ByteCount
;
1960 struct reparse_data
* reparse_buf
= (struct reparse_data
*)
1961 ((char *)&pSMBr
->hdr
.Protocol
+ data_offset
);
1962 if((char*)reparse_buf
>= end_of_smb
) {
1966 if((reparse_buf
->LinkNamesBuf
+
1967 reparse_buf
->TargetNameOffset
+
1968 reparse_buf
->TargetNameLen
) >
1970 cFYI(1,("reparse buf extended beyond SMB"));
1975 if (pSMBr
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
1976 name_len
= UniStrnlen((wchar_t *)
1977 (reparse_buf
->LinkNamesBuf
+
1978 reparse_buf
->TargetNameOffset
),
1979 min(buflen
/2, reparse_buf
->TargetNameLen
/ 2));
1980 cifs_strfromUCS_le(symlinkinfo
,
1981 (__le16
*) (reparse_buf
->LinkNamesBuf
+
1982 reparse_buf
->TargetNameOffset
),
1983 name_len
, nls_codepage
);
1984 } else { /* ASCII names */
1985 strncpy(symlinkinfo
,reparse_buf
->LinkNamesBuf
+
1986 reparse_buf
->TargetNameOffset
,
1987 min_t(const int, buflen
, reparse_buf
->TargetNameLen
));
1991 cFYI(1,("Invalid return data count on get reparse info ioctl"));
1993 symlinkinfo
[buflen
] = 0; /* just in case so the caller
1994 does not go off the end of the buffer */
1995 cFYI(1,("readlink result - %s ",symlinkinfo
));
1999 cifs_buf_release(pSMB
);
2001 /* Note: On -EAGAIN error only caller can retry on handle based calls
2002 since file handle passed in no longer valid */
2007 #ifdef CONFIG_CIFS_POSIX
2009 /*Convert an Access Control Entry from wire format to local POSIX xattr format*/
2010 static void cifs_convert_ace(posix_acl_xattr_entry
* ace
, struct cifs_posix_ace
* cifs_ace
)
2012 /* u8 cifs fields do not need le conversion */
2013 ace
->e_perm
= cpu_to_le16(cifs_ace
->cifs_e_perm
);
2014 ace
->e_tag
= cpu_to_le16(cifs_ace
->cifs_e_tag
);
2015 ace
->e_id
= cpu_to_le32(le64_to_cpu(cifs_ace
->cifs_uid
));
2016 /* cFYI(1,("perm %d tag %d id %d",ace->e_perm,ace->e_tag,ace->e_id)); */
2021 /* Convert ACL from CIFS POSIX wire format to local Linux POSIX ACL xattr */
2022 static int cifs_copy_posix_acl(char * trgt
,char * src
, const int buflen
,
2023 const int acl_type
,const int size_of_data_area
)
2028 struct cifs_posix_ace
* pACE
;
2029 struct cifs_posix_acl
* cifs_acl
= (struct cifs_posix_acl
*)src
;
2030 posix_acl_xattr_header
* local_acl
= (posix_acl_xattr_header
*)trgt
;
2032 if (le16_to_cpu(cifs_acl
->version
) != CIFS_ACL_VERSION
)
2035 if(acl_type
& ACL_TYPE_ACCESS
) {
2036 count
= le16_to_cpu(cifs_acl
->access_entry_count
);
2037 pACE
= &cifs_acl
->ace_array
[0];
2038 size
= sizeof(struct cifs_posix_acl
);
2039 size
+= sizeof(struct cifs_posix_ace
) * count
;
2040 /* check if we would go beyond end of SMB */
2041 if(size_of_data_area
< size
) {
2042 cFYI(1,("bad CIFS POSIX ACL size %d vs. %d",size_of_data_area
,size
));
2045 } else if(acl_type
& ACL_TYPE_DEFAULT
) {
2046 count
= le16_to_cpu(cifs_acl
->access_entry_count
);
2047 size
= sizeof(struct cifs_posix_acl
);
2048 size
+= sizeof(struct cifs_posix_ace
) * count
;
2049 /* skip past access ACEs to get to default ACEs */
2050 pACE
= &cifs_acl
->ace_array
[count
];
2051 count
= le16_to_cpu(cifs_acl
->default_entry_count
);
2052 size
+= sizeof(struct cifs_posix_ace
) * count
;
2053 /* check if we would go beyond end of SMB */
2054 if(size_of_data_area
< size
)
2061 size
= posix_acl_xattr_size(count
);
2062 if((buflen
== 0) || (local_acl
== NULL
)) {
2063 /* used to query ACL EA size */
2064 } else if(size
> buflen
) {
2066 } else /* buffer big enough */ {
2067 local_acl
->a_version
= cpu_to_le32(POSIX_ACL_XATTR_VERSION
);
2068 for(i
= 0;i
< count
;i
++) {
2069 cifs_convert_ace(&local_acl
->a_entries
[i
],pACE
);
2076 static __u16
convert_ace_to_cifs_ace(struct cifs_posix_ace
* cifs_ace
,
2077 const posix_acl_xattr_entry
* local_ace
)
2079 __u16 rc
= 0; /* 0 = ACL converted ok */
2081 cifs_ace
->cifs_e_perm
= le16_to_cpu(local_ace
->e_perm
);
2082 cifs_ace
->cifs_e_tag
= le16_to_cpu(local_ace
->e_tag
);
2083 /* BB is there a better way to handle the large uid? */
2084 if(local_ace
->e_id
== cpu_to_le32(-1)) {
2085 /* Probably no need to le convert -1 on any arch but can not hurt */
2086 cifs_ace
->cifs_uid
= cpu_to_le64(-1);
2088 cifs_ace
->cifs_uid
= cpu_to_le64(le32_to_cpu(local_ace
->e_id
));
2089 /*cFYI(1,("perm %d tag %d id %d",ace->e_perm,ace->e_tag,ace->e_id));*/
2093 /* Convert ACL from local Linux POSIX xattr to CIFS POSIX ACL wire format */
2094 static __u16
ACL_to_cifs_posix(char * parm_data
,const char * pACL
,const int buflen
,
2098 struct cifs_posix_acl
* cifs_acl
= (struct cifs_posix_acl
*)parm_data
;
2099 posix_acl_xattr_header
* local_acl
= (posix_acl_xattr_header
*)pACL
;
2103 if((buflen
== 0) || (pACL
== NULL
) || (cifs_acl
== NULL
))
2106 count
= posix_acl_xattr_count((size_t)buflen
);
2107 cFYI(1,("setting acl with %d entries from buf of length %d and version of %d",
2108 count
, buflen
, le32_to_cpu(local_acl
->a_version
)));
2109 if(le32_to_cpu(local_acl
->a_version
) != 2) {
2110 cFYI(1,("unknown POSIX ACL version %d",
2111 le32_to_cpu(local_acl
->a_version
)));
2114 cifs_acl
->version
= cpu_to_le16(1);
2115 if(acl_type
== ACL_TYPE_ACCESS
)
2116 cifs_acl
->access_entry_count
= cpu_to_le16(count
);
2117 else if(acl_type
== ACL_TYPE_DEFAULT
)
2118 cifs_acl
->default_entry_count
= cpu_to_le16(count
);
2120 cFYI(1,("unknown ACL type %d",acl_type
));
2123 for(i
=0;i
<count
;i
++) {
2124 rc
= convert_ace_to_cifs_ace(&cifs_acl
->ace_array
[i
],
2125 &local_acl
->a_entries
[i
]);
2127 /* ACE not converted */
2132 rc
= (__u16
)(count
* sizeof(struct cifs_posix_ace
));
2133 rc
+= sizeof(struct cifs_posix_acl
);
2134 /* BB add check to make sure ACL does not overflow SMB */
2140 CIFSSMBGetPosixACL(const int xid
, struct cifsTconInfo
*tcon
,
2141 const unsigned char *searchName
,
2142 char *acl_inf
, const int buflen
, const int acl_type
,
2143 const struct nls_table
*nls_codepage
, int remap
)
2145 /* SMB_QUERY_POSIX_ACL */
2146 TRANSACTION2_QPI_REQ
*pSMB
= NULL
;
2147 TRANSACTION2_QPI_RSP
*pSMBr
= NULL
;
2151 __u16 params
, byte_count
;
2153 cFYI(1, ("In GetPosixACL (Unix) for path %s", searchName
));
2156 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
2161 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
2163 cifsConvertToUCS((__le16
*) pSMB
->FileName
, searchName
,
2164 PATH_MAX
, nls_codepage
, remap
);
2165 name_len
++; /* trailing null */
2167 pSMB
->FileName
[name_len
] = 0;
2168 pSMB
->FileName
[name_len
+1] = 0;
2169 } else { /* BB improve the check for buffer overruns BB */
2170 name_len
= strnlen(searchName
, PATH_MAX
);
2171 name_len
++; /* trailing null */
2172 strncpy(pSMB
->FileName
, searchName
, name_len
);
2175 params
= 2 /* level */ + 4 /* rsrvd */ + name_len
/* incl null */ ;
2176 pSMB
->TotalDataCount
= 0;
2177 pSMB
->MaxParameterCount
= cpu_to_le16(2);
2178 /* BB find exact max data count below from sess structure BB */
2179 pSMB
->MaxDataCount
= cpu_to_le16(4000);
2180 pSMB
->MaxSetupCount
= 0;
2184 pSMB
->Reserved2
= 0;
2185 pSMB
->ParameterOffset
= cpu_to_le16(
2186 offsetof(struct smb_com_transaction2_qpi_req
,InformationLevel
) - 4);
2187 pSMB
->DataCount
= 0;
2188 pSMB
->DataOffset
= 0;
2189 pSMB
->SetupCount
= 1;
2190 pSMB
->Reserved3
= 0;
2191 pSMB
->SubCommand
= cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION
);
2192 byte_count
= params
+ 1 /* pad */ ;
2193 pSMB
->TotalParameterCount
= cpu_to_le16(params
);
2194 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
2195 pSMB
->InformationLevel
= cpu_to_le16(SMB_QUERY_POSIX_ACL
);
2196 pSMB
->Reserved4
= 0;
2197 pSMB
->hdr
.smb_buf_length
+= byte_count
;
2198 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
2200 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
2201 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
2203 cFYI(1, ("Send error in Query POSIX ACL = %d", rc
));
2205 /* decode response */
2207 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
2208 if (rc
|| (pSMBr
->ByteCount
< 2))
2209 /* BB also check enough total bytes returned */
2210 rc
= -EIO
; /* bad smb */
2212 __u16 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
2213 __u16 count
= le16_to_cpu(pSMBr
->t2
.DataCount
);
2214 rc
= cifs_copy_posix_acl(acl_inf
,
2215 (char *)&pSMBr
->hdr
.Protocol
+data_offset
,
2216 buflen
,acl_type
,count
);
2219 cifs_buf_release(pSMB
);
2226 CIFSSMBSetPosixACL(const int xid
, struct cifsTconInfo
*tcon
,
2227 const unsigned char *fileName
,
2228 const char *local_acl
, const int buflen
,
2230 const struct nls_table
*nls_codepage
, int remap
)
2232 struct smb_com_transaction2_spi_req
*pSMB
= NULL
;
2233 struct smb_com_transaction2_spi_rsp
*pSMBr
= NULL
;
2237 int bytes_returned
= 0;
2238 __u16 params
, byte_count
, data_count
, param_offset
, offset
;
2240 cFYI(1, ("In SetPosixACL (Unix) for path %s", fileName
));
2242 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
2246 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
2248 cifsConvertToUCS((__le16
*) pSMB
->FileName
, fileName
,
2249 PATH_MAX
, nls_codepage
, remap
);
2250 name_len
++; /* trailing null */
2252 } else { /* BB improve the check for buffer overruns BB */
2253 name_len
= strnlen(fileName
, PATH_MAX
);
2254 name_len
++; /* trailing null */
2255 strncpy(pSMB
->FileName
, fileName
, name_len
);
2257 params
= 6 + name_len
;
2258 pSMB
->MaxParameterCount
= cpu_to_le16(2);
2259 pSMB
->MaxDataCount
= cpu_to_le16(1000); /* BB find max SMB size from sess */
2260 pSMB
->MaxSetupCount
= 0;
2264 pSMB
->Reserved2
= 0;
2265 param_offset
= offsetof(struct smb_com_transaction2_spi_req
,
2266 InformationLevel
) - 4;
2267 offset
= param_offset
+ params
;
2268 parm_data
= ((char *) &pSMB
->hdr
.Protocol
) + offset
;
2269 pSMB
->ParameterOffset
= cpu_to_le16(param_offset
);
2271 /* convert to on the wire format for POSIX ACL */
2272 data_count
= ACL_to_cifs_posix(parm_data
,local_acl
,buflen
,acl_type
);
2274 if(data_count
== 0) {
2276 goto setACLerrorExit
;
2278 pSMB
->DataOffset
= cpu_to_le16(offset
);
2279 pSMB
->SetupCount
= 1;
2280 pSMB
->Reserved3
= 0;
2281 pSMB
->SubCommand
= cpu_to_le16(TRANS2_SET_PATH_INFORMATION
);
2282 pSMB
->InformationLevel
= cpu_to_le16(SMB_SET_POSIX_ACL
);
2283 byte_count
= 3 /* pad */ + params
+ data_count
;
2284 pSMB
->DataCount
= cpu_to_le16(data_count
);
2285 pSMB
->TotalDataCount
= pSMB
->DataCount
;
2286 pSMB
->ParameterCount
= cpu_to_le16(params
);
2287 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
2288 pSMB
->Reserved4
= 0;
2289 pSMB
->hdr
.smb_buf_length
+= byte_count
;
2290 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
2291 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
2292 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
2294 cFYI(1, ("Set POSIX ACL returned %d", rc
));
2298 cifs_buf_release(pSMB
);
2304 /* BB fix tabs in this function FIXME BB */
2306 CIFSGetExtAttr(const int xid
, struct cifsTconInfo
*tcon
,
2307 const int netfid
, __u64
* pExtAttrBits
, __u64
*pMask
)
2310 struct smb_t2_qfi_req
*pSMB
= NULL
;
2311 struct smb_t2_qfi_rsp
*pSMBr
= NULL
;
2313 __u16 params
, byte_count
;
2315 cFYI(1,("In GetExtAttr"));
2320 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
2325 params
= 2 /* level */ +2 /* fid */;
2326 pSMB
->t2
.TotalDataCount
= 0;
2327 pSMB
->t2
.MaxParameterCount
= cpu_to_le16(4);
2328 /* BB find exact max data count below from sess structure BB */
2329 pSMB
->t2
.MaxDataCount
= cpu_to_le16(4000);
2330 pSMB
->t2
.MaxSetupCount
= 0;
2331 pSMB
->t2
.Reserved
= 0;
2333 pSMB
->t2
.Timeout
= 0;
2334 pSMB
->t2
.Reserved2
= 0;
2335 pSMB
->t2
.ParameterOffset
= cpu_to_le16(offsetof(struct smb_t2_qfi_req
,
2337 pSMB
->t2
.DataCount
= 0;
2338 pSMB
->t2
.DataOffset
= 0;
2339 pSMB
->t2
.SetupCount
= 1;
2340 pSMB
->t2
.Reserved3
= 0;
2341 pSMB
->t2
.SubCommand
= cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION
);
2342 byte_count
= params
+ 1 /* pad */ ;
2343 pSMB
->t2
.TotalParameterCount
= cpu_to_le16(params
);
2344 pSMB
->t2
.ParameterCount
= pSMB
->t2
.TotalParameterCount
;
2345 pSMB
->InformationLevel
= cpu_to_le16(SMB_QUERY_ATTR_FLAGS
);
2348 pSMB
->hdr
.smb_buf_length
+= byte_count
;
2349 pSMB
->t2
.ByteCount
= cpu_to_le16(byte_count
);
2351 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
2352 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
2354 cFYI(1, ("error %d in GetExtAttr", rc
));
2356 /* decode response */
2357 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
2358 if (rc
|| (pSMBr
->ByteCount
< 2))
2359 /* BB also check enough total bytes returned */
2360 /* If rc should we check for EOPNOSUPP and
2361 disable the srvino flag? or in caller? */
2362 rc
= -EIO
; /* bad smb */
2364 __u16 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
2365 __u16 count
= le16_to_cpu(pSMBr
->t2
.DataCount
);
2366 struct file_chattr_info
* pfinfo
;
2367 /* BB Do we need a cast or hash here ? */
2369 cFYI(1, ("Illegal size ret in GetExtAttr"));
2373 pfinfo
= (struct file_chattr_info
*)
2374 (data_offset
+ (char *) &pSMBr
->hdr
.Protocol
);
2375 *pExtAttrBits
= le64_to_cpu(pfinfo
->mode
);
2376 *pMask
= le64_to_cpu(pfinfo
->mask
);
2380 cifs_buf_release(pSMB
);
2382 goto GetExtAttrRetry
;
2387 #endif /* CONFIG_POSIX */
2389 /* Legacy Query Path Information call for lookup to old servers such
2391 int SMBQueryInformation(const int xid
, struct cifsTconInfo
*tcon
,
2392 const unsigned char *searchName
,
2393 FILE_ALL_INFO
* pFinfo
,
2394 const struct nls_table
*nls_codepage
, int remap
)
2396 QUERY_INFORMATION_REQ
* pSMB
;
2397 QUERY_INFORMATION_RSP
* pSMBr
;
2402 cFYI(1, ("In SMBQPath path %s", searchName
));
2404 rc
= smb_init(SMB_COM_QUERY_INFORMATION
, 0, tcon
, (void **) &pSMB
,
2409 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
2411 cifsConvertToUCS((__le16
*) pSMB
->FileName
, searchName
,
2412 PATH_MAX
, nls_codepage
, remap
);
2413 name_len
++; /* trailing null */
2416 name_len
= strnlen(searchName
, PATH_MAX
);
2417 name_len
++; /* trailing null */
2418 strncpy(pSMB
->FileName
, searchName
, name_len
);
2420 pSMB
->BufferFormat
= 0x04;
2421 name_len
++; /* account for buffer type byte */
2422 pSMB
->hdr
.smb_buf_length
+= (__u16
) name_len
;
2423 pSMB
->ByteCount
= cpu_to_le16(name_len
);
2425 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
2426 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
2428 cFYI(1, ("Send error in QueryInfo = %d", rc
));
2429 } else if (pFinfo
) { /* decode response */
2430 memset(pFinfo
, 0, sizeof(FILE_ALL_INFO
));
2431 pFinfo
->AllocationSize
=
2432 cpu_to_le64(le32_to_cpu(pSMBr
->size
));
2433 pFinfo
->EndOfFile
= pFinfo
->AllocationSize
;
2434 pFinfo
->Attributes
=
2435 cpu_to_le32(le16_to_cpu(pSMBr
->attr
));
2437 rc
= -EIO
; /* bad buffer passed in */
2439 cifs_buf_release(pSMB
);
2451 CIFSSMBQPathInfo(const int xid
, struct cifsTconInfo
*tcon
,
2452 const unsigned char *searchName
,
2453 FILE_ALL_INFO
* pFindData
,
2454 const struct nls_table
*nls_codepage
, int remap
)
2456 /* level 263 SMB_QUERY_FILE_ALL_INFO */
2457 TRANSACTION2_QPI_REQ
*pSMB
= NULL
;
2458 TRANSACTION2_QPI_RSP
*pSMBr
= NULL
;
2462 __u16 params
, byte_count
;
2464 /* cFYI(1, ("In QPathInfo path %s", searchName)); */
2466 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
2471 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
2473 cifsConvertToUCS((__le16
*) pSMB
->FileName
, searchName
,
2474 PATH_MAX
, nls_codepage
, remap
);
2475 name_len
++; /* trailing null */
2477 } else { /* BB improve the check for buffer overruns BB */
2478 name_len
= strnlen(searchName
, PATH_MAX
);
2479 name_len
++; /* trailing null */
2480 strncpy(pSMB
->FileName
, searchName
, name_len
);
2483 params
= 2 /* level */ + 4 /* reserved */ + name_len
/* includes NUL */ ;
2484 pSMB
->TotalDataCount
= 0;
2485 pSMB
->MaxParameterCount
= cpu_to_le16(2);
2486 pSMB
->MaxDataCount
= cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
2487 pSMB
->MaxSetupCount
= 0;
2491 pSMB
->Reserved2
= 0;
2492 pSMB
->ParameterOffset
= cpu_to_le16(offsetof(
2493 struct smb_com_transaction2_qpi_req
,InformationLevel
) - 4);
2494 pSMB
->DataCount
= 0;
2495 pSMB
->DataOffset
= 0;
2496 pSMB
->SetupCount
= 1;
2497 pSMB
->Reserved3
= 0;
2498 pSMB
->SubCommand
= cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION
);
2499 byte_count
= params
+ 1 /* pad */ ;
2500 pSMB
->TotalParameterCount
= cpu_to_le16(params
);
2501 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
2502 pSMB
->InformationLevel
= cpu_to_le16(SMB_QUERY_FILE_ALL_INFO
);
2503 pSMB
->Reserved4
= 0;
2504 pSMB
->hdr
.smb_buf_length
+= byte_count
;
2505 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
2507 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
2508 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
2510 cFYI(1, ("Send error in QPathInfo = %d", rc
));
2511 } else { /* decode response */
2512 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
2514 if (rc
|| (pSMBr
->ByteCount
< 40))
2515 rc
= -EIO
; /* bad smb */
2516 else if (pFindData
){
2517 __u16 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
2518 memcpy((char *) pFindData
,
2519 (char *) &pSMBr
->hdr
.Protocol
+
2520 data_offset
, sizeof (FILE_ALL_INFO
));
2524 cifs_buf_release(pSMB
);
2526 goto QPathInfoRetry
;
2532 CIFSSMBUnixQPathInfo(const int xid
, struct cifsTconInfo
*tcon
,
2533 const unsigned char *searchName
,
2534 FILE_UNIX_BASIC_INFO
* pFindData
,
2535 const struct nls_table
*nls_codepage
, int remap
)
2537 /* SMB_QUERY_FILE_UNIX_BASIC */
2538 TRANSACTION2_QPI_REQ
*pSMB
= NULL
;
2539 TRANSACTION2_QPI_RSP
*pSMBr
= NULL
;
2541 int bytes_returned
= 0;
2543 __u16 params
, byte_count
;
2545 cFYI(1, ("In QPathInfo (Unix) the path %s", searchName
));
2547 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
2552 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
2554 cifsConvertToUCS((__le16
*) pSMB
->FileName
, searchName
,
2555 PATH_MAX
, nls_codepage
, remap
);
2556 name_len
++; /* trailing null */
2558 } else { /* BB improve the check for buffer overruns BB */
2559 name_len
= strnlen(searchName
, PATH_MAX
);
2560 name_len
++; /* trailing null */
2561 strncpy(pSMB
->FileName
, searchName
, name_len
);
2564 params
= 2 /* level */ + 4 /* reserved */ + name_len
/* includes NUL */ ;
2565 pSMB
->TotalDataCount
= 0;
2566 pSMB
->MaxParameterCount
= cpu_to_le16(2);
2567 /* BB find exact max SMB PDU from sess structure BB */
2568 pSMB
->MaxDataCount
= cpu_to_le16(4000);
2569 pSMB
->MaxSetupCount
= 0;
2573 pSMB
->Reserved2
= 0;
2574 pSMB
->ParameterOffset
= cpu_to_le16(offsetof(
2575 struct smb_com_transaction2_qpi_req
,InformationLevel
) - 4);
2576 pSMB
->DataCount
= 0;
2577 pSMB
->DataOffset
= 0;
2578 pSMB
->SetupCount
= 1;
2579 pSMB
->Reserved3
= 0;
2580 pSMB
->SubCommand
= cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION
);
2581 byte_count
= params
+ 1 /* pad */ ;
2582 pSMB
->TotalParameterCount
= cpu_to_le16(params
);
2583 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
2584 pSMB
->InformationLevel
= cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC
);
2585 pSMB
->Reserved4
= 0;
2586 pSMB
->hdr
.smb_buf_length
+= byte_count
;
2587 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
2589 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
2590 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
2592 cFYI(1, ("Send error in QPathInfo = %d", rc
));
2593 } else { /* decode response */
2594 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
2596 if (rc
|| (pSMBr
->ByteCount
< sizeof(FILE_UNIX_BASIC_INFO
))) {
2597 rc
= -EIO
; /* bad smb */
2599 __u16 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
2600 memcpy((char *) pFindData
,
2601 (char *) &pSMBr
->hdr
.Protocol
+
2603 sizeof (FILE_UNIX_BASIC_INFO
));
2606 cifs_buf_release(pSMB
);
2608 goto UnixQPathInfoRetry
;
2613 #if 0 /* function unused at present */
2614 int CIFSFindSingle(const int xid
, struct cifsTconInfo
*tcon
,
2615 const char *searchName
, FILE_ALL_INFO
* findData
,
2616 const struct nls_table
*nls_codepage
)
2618 /* level 257 SMB_ */
2619 TRANSACTION2_FFIRST_REQ
*pSMB
= NULL
;
2620 TRANSACTION2_FFIRST_RSP
*pSMBr
= NULL
;
2624 __u16 params
, byte_count
;
2626 cFYI(1, ("In FindUnique"));
2628 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
2633 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
2635 cifsConvertToUCS((__le16
*) pSMB
->FileName
, searchName
, PATH_MAX
2636 /* find define for this maxpathcomponent */
2638 name_len
++; /* trailing null */
2640 } else { /* BB improve the check for buffer overruns BB */
2641 name_len
= strnlen(searchName
, PATH_MAX
);
2642 name_len
++; /* trailing null */
2643 strncpy(pSMB
->FileName
, searchName
, name_len
);
2646 params
= 12 + name_len
/* includes null */ ;
2647 pSMB
->TotalDataCount
= 0; /* no EAs */
2648 pSMB
->MaxParameterCount
= cpu_to_le16(2);
2649 pSMB
->MaxDataCount
= cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
2650 pSMB
->MaxSetupCount
= 0;
2654 pSMB
->Reserved2
= 0;
2655 pSMB
->ParameterOffset
= cpu_to_le16(
2656 offsetof(struct smb_com_transaction2_ffirst_req
,InformationLevel
) - 4);
2657 pSMB
->DataCount
= 0;
2658 pSMB
->DataOffset
= 0;
2659 pSMB
->SetupCount
= 1; /* one byte, no need to le convert */
2660 pSMB
->Reserved3
= 0;
2661 pSMB
->SubCommand
= cpu_to_le16(TRANS2_FIND_FIRST
);
2662 byte_count
= params
+ 1 /* pad */ ;
2663 pSMB
->TotalParameterCount
= cpu_to_le16(params
);
2664 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
2665 pSMB
->SearchAttributes
=
2666 cpu_to_le16(ATTR_READONLY
| ATTR_HIDDEN
| ATTR_SYSTEM
|
2668 pSMB
->SearchCount
= cpu_to_le16(16); /* BB increase */
2669 pSMB
->SearchFlags
= cpu_to_le16(1);
2670 pSMB
->InformationLevel
= cpu_to_le16(SMB_FIND_FILE_DIRECTORY_INFO
);
2671 pSMB
->SearchStorageType
= 0; /* BB what should we set this to? BB */
2672 pSMB
->hdr
.smb_buf_length
+= byte_count
;
2673 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
2675 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
2676 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
2679 cFYI(1, ("Send error in FindFileDirInfo = %d", rc
));
2680 } else { /* decode response */
2681 cifs_stats_inc(&tcon
->num_ffirst
);
2685 cifs_buf_release(pSMB
);
2687 goto findUniqueRetry
;
2691 #endif /* end unused (temporarily) function */
2693 /* xid, tcon, searchName and codepage are input parms, rest are returned */
2695 CIFSFindFirst(const int xid
, struct cifsTconInfo
*tcon
,
2696 const char *searchName
,
2697 const struct nls_table
*nls_codepage
,
2699 struct cifs_search_info
* psrch_inf
, int remap
, const char dirsep
)
2701 /* level 257 SMB_ */
2702 TRANSACTION2_FFIRST_REQ
*pSMB
= NULL
;
2703 TRANSACTION2_FFIRST_RSP
*pSMBr
= NULL
;
2704 T2_FFIRST_RSP_PARMS
* parms
;
2706 int bytes_returned
= 0;
2708 __u16 params
, byte_count
;
2710 cFYI(1, ("In FindFirst for %s",searchName
));
2713 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
2718 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
2720 cifsConvertToUCS((__le16
*) pSMB
->FileName
,searchName
,
2721 PATH_MAX
, nls_codepage
, remap
);
2722 /* We can not add the asterik earlier in case
2723 it got remapped to 0xF03A as if it were part of the
2724 directory name instead of a wildcard */
2726 pSMB
->FileName
[name_len
] = dirsep
;
2727 pSMB
->FileName
[name_len
+1] = 0;
2728 pSMB
->FileName
[name_len
+2] = '*';
2729 pSMB
->FileName
[name_len
+3] = 0;
2730 name_len
+= 4; /* now the trailing null */
2731 pSMB
->FileName
[name_len
] = 0; /* null terminate just in case */
2732 pSMB
->FileName
[name_len
+1] = 0;
2734 } else { /* BB add check for overrun of SMB buf BB */
2735 name_len
= strnlen(searchName
, PATH_MAX
);
2736 /* BB fix here and in unicode clause above ie
2737 if(name_len > buffersize-header)
2738 free buffer exit; BB */
2739 strncpy(pSMB
->FileName
, searchName
, name_len
);
2740 pSMB
->FileName
[name_len
] = dirsep
;
2741 pSMB
->FileName
[name_len
+1] = '*';
2742 pSMB
->FileName
[name_len
+2] = 0;
2746 params
= 12 + name_len
/* includes null */ ;
2747 pSMB
->TotalDataCount
= 0; /* no EAs */
2748 pSMB
->MaxParameterCount
= cpu_to_le16(10);
2749 pSMB
->MaxDataCount
= cpu_to_le16((tcon
->ses
->server
->maxBuf
-
2750 MAX_CIFS_HDR_SIZE
) & 0xFFFFFF00);
2751 pSMB
->MaxSetupCount
= 0;
2755 pSMB
->Reserved2
= 0;
2756 byte_count
= params
+ 1 /* pad */ ;
2757 pSMB
->TotalParameterCount
= cpu_to_le16(params
);
2758 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
2759 pSMB
->ParameterOffset
= cpu_to_le16(
2760 offsetof(struct smb_com_transaction2_ffirst_req
, SearchAttributes
) - 4);
2761 pSMB
->DataCount
= 0;
2762 pSMB
->DataOffset
= 0;
2763 pSMB
->SetupCount
= 1; /* one byte, no need to make endian neutral */
2764 pSMB
->Reserved3
= 0;
2765 pSMB
->SubCommand
= cpu_to_le16(TRANS2_FIND_FIRST
);
2766 pSMB
->SearchAttributes
=
2767 cpu_to_le16(ATTR_READONLY
| ATTR_HIDDEN
| ATTR_SYSTEM
|
2769 pSMB
->SearchCount
= cpu_to_le16(CIFSMaxBufSize
/sizeof(FILE_UNIX_INFO
));
2770 pSMB
->SearchFlags
= cpu_to_le16(CIFS_SEARCH_CLOSE_AT_END
|
2771 CIFS_SEARCH_RETURN_RESUME
);
2772 pSMB
->InformationLevel
= cpu_to_le16(psrch_inf
->info_level
);
2774 /* BB what should we set StorageType to? Does it matter? BB */
2775 pSMB
->SearchStorageType
= 0;
2776 pSMB
->hdr
.smb_buf_length
+= byte_count
;
2777 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
2779 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
2780 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
2781 cifs_stats_inc(&tcon
->num_ffirst
);
2783 if (rc
) {/* BB add logic to retry regular search if Unix search rejected unexpectedly by server */
2784 /* BB Add code to handle unsupported level rc */
2785 cFYI(1, ("Error in FindFirst = %d", rc
));
2788 cifs_buf_release(pSMB
);
2790 /* BB eventually could optimize out free and realloc of buf */
2793 goto findFirstRetry
;
2794 } else { /* decode response */
2795 /* BB remember to free buffer if error BB */
2796 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
2798 if (pSMBr
->hdr
.Flags2
& SMBFLG2_UNICODE
)
2799 psrch_inf
->unicode
= TRUE
;
2801 psrch_inf
->unicode
= FALSE
;
2803 psrch_inf
->ntwrk_buf_start
= (char *)pSMBr
;
2804 psrch_inf
->srch_entries_start
=
2805 (char *) &pSMBr
->hdr
.Protocol
+
2806 le16_to_cpu(pSMBr
->t2
.DataOffset
);
2807 parms
= (T2_FFIRST_RSP_PARMS
*)((char *) &pSMBr
->hdr
.Protocol
+
2808 le16_to_cpu(pSMBr
->t2
.ParameterOffset
));
2810 if(parms
->EndofSearch
)
2811 psrch_inf
->endOfSearch
= TRUE
;
2813 psrch_inf
->endOfSearch
= FALSE
;
2815 psrch_inf
->entries_in_buffer
= le16_to_cpu(parms
->SearchCount
);
2816 psrch_inf
->index_of_last_entry
=
2817 psrch_inf
->entries_in_buffer
;
2818 *pnetfid
= parms
->SearchHandle
;
2820 cifs_buf_release(pSMB
);
2827 int CIFSFindNext(const int xid
, struct cifsTconInfo
*tcon
,
2828 __u16 searchHandle
, struct cifs_search_info
* psrch_inf
)
2830 TRANSACTION2_FNEXT_REQ
*pSMB
= NULL
;
2831 TRANSACTION2_FNEXT_RSP
*pSMBr
= NULL
;
2832 T2_FNEXT_RSP_PARMS
* parms
;
2833 char *response_data
;
2835 int bytes_returned
, name_len
;
2836 __u16 params
, byte_count
;
2838 cFYI(1, ("In FindNext"));
2840 if(psrch_inf
->endOfSearch
== TRUE
)
2843 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
2848 params
= 14; /* includes 2 bytes of null string, converted to LE below */
2850 pSMB
->TotalDataCount
= 0; /* no EAs */
2851 pSMB
->MaxParameterCount
= cpu_to_le16(8);
2852 pSMB
->MaxDataCount
=
2853 cpu_to_le16((tcon
->ses
->server
->maxBuf
- MAX_CIFS_HDR_SIZE
) & 0xFFFFFF00);
2854 pSMB
->MaxSetupCount
= 0;
2858 pSMB
->Reserved2
= 0;
2859 pSMB
->ParameterOffset
= cpu_to_le16(
2860 offsetof(struct smb_com_transaction2_fnext_req
,SearchHandle
) - 4);
2861 pSMB
->DataCount
= 0;
2862 pSMB
->DataOffset
= 0;
2863 pSMB
->SetupCount
= 1;
2864 pSMB
->Reserved3
= 0;
2865 pSMB
->SubCommand
= cpu_to_le16(TRANS2_FIND_NEXT
);
2866 pSMB
->SearchHandle
= searchHandle
; /* always kept as le */
2868 cpu_to_le16(CIFSMaxBufSize
/ sizeof (FILE_UNIX_INFO
));
2869 /* test for Unix extensions */
2870 /* if (tcon->ses->capabilities & CAP_UNIX) {
2871 pSMB->InformationLevel = cpu_to_le16(SMB_FIND_FILE_UNIX);
2872 psrch_inf->info_level = SMB_FIND_FILE_UNIX;
2874 pSMB->InformationLevel =
2875 cpu_to_le16(SMB_FIND_FILE_DIRECTORY_INFO);
2876 psrch_inf->info_level = SMB_FIND_FILE_DIRECTORY_INFO;
2878 pSMB
->InformationLevel
= cpu_to_le16(psrch_inf
->info_level
);
2879 pSMB
->ResumeKey
= psrch_inf
->resume_key
;
2881 cpu_to_le16(CIFS_SEARCH_CLOSE_AT_END
| CIFS_SEARCH_RETURN_RESUME
);
2883 name_len
= psrch_inf
->resume_name_len
;
2885 if(name_len
< PATH_MAX
) {
2886 memcpy(pSMB
->ResumeFileName
, psrch_inf
->presume_name
, name_len
);
2887 byte_count
+= name_len
;
2888 /* 14 byte parm len above enough for 2 byte null terminator */
2889 pSMB
->ResumeFileName
[name_len
] = 0;
2890 pSMB
->ResumeFileName
[name_len
+1] = 0;
2893 goto FNext2_err_exit
;
2895 byte_count
= params
+ 1 /* pad */ ;
2896 pSMB
->TotalParameterCount
= cpu_to_le16(params
);
2897 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
2898 pSMB
->hdr
.smb_buf_length
+= byte_count
;
2899 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
2901 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
2902 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
2903 cifs_stats_inc(&tcon
->num_fnext
);
2906 psrch_inf
->endOfSearch
= TRUE
;
2907 rc
= 0; /* search probably was closed at end of search above */
2909 cFYI(1, ("FindNext returned = %d", rc
));
2910 } else { /* decode response */
2911 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
2914 /* BB fixme add lock for file (srch_info) struct here */
2915 if (pSMBr
->hdr
.Flags2
& SMBFLG2_UNICODE
)
2916 psrch_inf
->unicode
= TRUE
;
2918 psrch_inf
->unicode
= FALSE
;
2919 response_data
= (char *) &pSMBr
->hdr
.Protocol
+
2920 le16_to_cpu(pSMBr
->t2
.ParameterOffset
);
2921 parms
= (T2_FNEXT_RSP_PARMS
*)response_data
;
2922 response_data
= (char *)&pSMBr
->hdr
.Protocol
+
2923 le16_to_cpu(pSMBr
->t2
.DataOffset
);
2924 cifs_buf_release(psrch_inf
->ntwrk_buf_start
);
2925 psrch_inf
->srch_entries_start
= response_data
;
2926 psrch_inf
->ntwrk_buf_start
= (char *)pSMB
;
2927 if(parms
->EndofSearch
)
2928 psrch_inf
->endOfSearch
= TRUE
;
2930 psrch_inf
->endOfSearch
= FALSE
;
2932 psrch_inf
->entries_in_buffer
= le16_to_cpu(parms
->SearchCount
);
2933 psrch_inf
->index_of_last_entry
+=
2934 psrch_inf
->entries_in_buffer
;
2935 /* cFYI(1,("fnxt2 entries in buf %d index_of_last %d",psrch_inf->entries_in_buffer,psrch_inf->index_of_last_entry)); */
2937 /* BB fixme add unlock here */
2942 /* BB On error, should we leave previous search buf (and count and
2943 last entry fields) intact or free the previous one? */
2945 /* Note: On -EAGAIN error only caller can retry on handle based calls
2946 since file handle passed in no longer valid */
2949 cifs_buf_release(pSMB
);
2955 CIFSFindClose(const int xid
, struct cifsTconInfo
*tcon
, const __u16 searchHandle
)
2958 FINDCLOSE_REQ
*pSMB
= NULL
;
2959 CLOSE_RSP
*pSMBr
= NULL
; /* BB removeme BB */
2962 cFYI(1, ("In CIFSSMBFindClose"));
2963 rc
= small_smb_init(SMB_COM_FIND_CLOSE2
, 1, tcon
, (void **)&pSMB
);
2965 /* no sense returning error if session restarted
2966 as file handle has been closed */
2972 pSMBr
= (CLOSE_RSP
*)pSMB
; /* BB removeme BB */
2973 pSMB
->FileID
= searchHandle
;
2974 pSMB
->ByteCount
= 0;
2975 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
2976 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
2978 cERROR(1, ("Send error in FindClose = %d", rc
));
2980 cifs_stats_inc(&tcon
->num_fclose
);
2981 cifs_small_buf_release(pSMB
);
2983 /* Since session is dead, search handle closed on server already */
2991 CIFSGetSrvInodeNumber(const int xid
, struct cifsTconInfo
*tcon
,
2992 const unsigned char *searchName
,
2993 __u64
* inode_number
,
2994 const struct nls_table
*nls_codepage
, int remap
)
2997 TRANSACTION2_QPI_REQ
*pSMB
= NULL
;
2998 TRANSACTION2_QPI_RSP
*pSMBr
= NULL
;
2999 int name_len
, bytes_returned
;
3000 __u16 params
, byte_count
;
3002 cFYI(1,("In GetSrvInodeNum for %s",searchName
));
3006 GetInodeNumberRetry
:
3007 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
3013 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
3015 cifsConvertToUCS((__le16
*) pSMB
->FileName
, searchName
,
3016 PATH_MAX
,nls_codepage
, remap
);
3017 name_len
++; /* trailing null */
3019 } else { /* BB improve the check for buffer overruns BB */
3020 name_len
= strnlen(searchName
, PATH_MAX
);
3021 name_len
++; /* trailing null */
3022 strncpy(pSMB
->FileName
, searchName
, name_len
);
3025 params
= 2 /* level */ + 4 /* rsrvd */ + name_len
/* incl null */ ;
3026 pSMB
->TotalDataCount
= 0;
3027 pSMB
->MaxParameterCount
= cpu_to_le16(2);
3028 /* BB find exact max data count below from sess structure BB */
3029 pSMB
->MaxDataCount
= cpu_to_le16(4000);
3030 pSMB
->MaxSetupCount
= 0;
3034 pSMB
->Reserved2
= 0;
3035 pSMB
->ParameterOffset
= cpu_to_le16(offsetof(
3036 struct smb_com_transaction2_qpi_req
,InformationLevel
) - 4);
3037 pSMB
->DataCount
= 0;
3038 pSMB
->DataOffset
= 0;
3039 pSMB
->SetupCount
= 1;
3040 pSMB
->Reserved3
= 0;
3041 pSMB
->SubCommand
= cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION
);
3042 byte_count
= params
+ 1 /* pad */ ;
3043 pSMB
->TotalParameterCount
= cpu_to_le16(params
);
3044 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
3045 pSMB
->InformationLevel
= cpu_to_le16(SMB_QUERY_FILE_INTERNAL_INFO
);
3046 pSMB
->Reserved4
= 0;
3047 pSMB
->hdr
.smb_buf_length
+= byte_count
;
3048 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
3050 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
3051 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
3053 cFYI(1, ("error %d in QueryInternalInfo", rc
));
3055 /* decode response */
3056 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
3057 if (rc
|| (pSMBr
->ByteCount
< 2))
3058 /* BB also check enough total bytes returned */
3059 /* If rc should we check for EOPNOSUPP and
3060 disable the srvino flag? or in caller? */
3061 rc
= -EIO
; /* bad smb */
3063 __u16 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
3064 __u16 count
= le16_to_cpu(pSMBr
->t2
.DataCount
);
3065 struct file_internal_info
* pfinfo
;
3066 /* BB Do we need a cast or hash here ? */
3068 cFYI(1, ("Illegal size ret in QryIntrnlInf"));
3070 goto GetInodeNumOut
;
3072 pfinfo
= (struct file_internal_info
*)
3073 (data_offset
+ (char *) &pSMBr
->hdr
.Protocol
);
3074 *inode_number
= pfinfo
->UniqueId
;
3078 cifs_buf_release(pSMB
);
3080 goto GetInodeNumberRetry
;
3085 CIFSGetDFSRefer(const int xid
, struct cifsSesInfo
*ses
,
3086 const unsigned char *searchName
,
3087 unsigned char **targetUNCs
,
3088 unsigned int *number_of_UNC_in_array
,
3089 const struct nls_table
*nls_codepage
, int remap
)
3091 /* TRANS2_GET_DFS_REFERRAL */
3092 TRANSACTION2_GET_DFS_REFER_REQ
*pSMB
= NULL
;
3093 TRANSACTION2_GET_DFS_REFER_RSP
*pSMBr
= NULL
;
3094 struct dfs_referral_level_3
* referrals
= NULL
;
3100 __u16 params
, byte_count
;
3101 *number_of_UNC_in_array
= 0;
3104 cFYI(1, ("In GetDFSRefer the path %s", searchName
));
3108 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, NULL
, (void **) &pSMB
,
3113 /* server pointer checked in called function,
3114 but should never be null here anyway */
3115 pSMB
->hdr
.Mid
= GetNextMid(ses
->server
);
3116 pSMB
->hdr
.Tid
= ses
->ipc_tid
;
3117 pSMB
->hdr
.Uid
= ses
->Suid
;
3118 if (ses
->capabilities
& CAP_STATUS32
) {
3119 pSMB
->hdr
.Flags2
|= SMBFLG2_ERR_STATUS
;
3121 if (ses
->capabilities
& CAP_DFS
) {
3122 pSMB
->hdr
.Flags2
|= SMBFLG2_DFS
;
3125 if (ses
->capabilities
& CAP_UNICODE
) {
3126 pSMB
->hdr
.Flags2
|= SMBFLG2_UNICODE
;
3128 cifsConvertToUCS((__le16
*) pSMB
->RequestFileName
,
3129 searchName
, PATH_MAX
, nls_codepage
, remap
);
3130 name_len
++; /* trailing null */
3132 } else { /* BB improve the check for buffer overruns BB */
3133 name_len
= strnlen(searchName
, PATH_MAX
);
3134 name_len
++; /* trailing null */
3135 strncpy(pSMB
->RequestFileName
, searchName
, name_len
);
3138 params
= 2 /* level */ + name_len
/*includes null */ ;
3139 pSMB
->TotalDataCount
= 0;
3140 pSMB
->DataCount
= 0;
3141 pSMB
->DataOffset
= 0;
3142 pSMB
->MaxParameterCount
= 0;
3143 pSMB
->MaxDataCount
= cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
3144 pSMB
->MaxSetupCount
= 0;
3148 pSMB
->Reserved2
= 0;
3149 pSMB
->ParameterOffset
= cpu_to_le16(offsetof(
3150 struct smb_com_transaction2_get_dfs_refer_req
, MaxReferralLevel
) - 4);
3151 pSMB
->SetupCount
= 1;
3152 pSMB
->Reserved3
= 0;
3153 pSMB
->SubCommand
= cpu_to_le16(TRANS2_GET_DFS_REFERRAL
);
3154 byte_count
= params
+ 3 /* pad */ ;
3155 pSMB
->ParameterCount
= cpu_to_le16(params
);
3156 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
3157 pSMB
->MaxReferralLevel
= cpu_to_le16(3);
3158 pSMB
->hdr
.smb_buf_length
+= byte_count
;
3159 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
3161 rc
= SendReceive(xid
, ses
, (struct smb_hdr
*) pSMB
,
3162 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
3164 cFYI(1, ("Send error in GetDFSRefer = %d", rc
));
3165 } else { /* decode response */
3166 /* BB Add logic to parse referrals here */
3167 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
3169 if (rc
|| (pSMBr
->ByteCount
< 17)) /* BB also check enough total bytes returned */
3170 rc
= -EIO
; /* bad smb */
3172 __u16 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
3173 __u16 data_count
= le16_to_cpu(pSMBr
->t2
.DataCount
);
3176 ("Decoding GetDFSRefer response. BCC: %d Offset %d",
3177 pSMBr
->ByteCount
, data_offset
));
3179 (struct dfs_referral_level_3
*)
3180 (8 /* sizeof start of data block */ +
3182 (char *) &pSMBr
->hdr
.Protocol
);
3183 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",
3184 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
)));
3185 /* BB This field is actually two bytes in from start of
3186 data block so we could do safety check that DataBlock
3187 begins at address of pSMBr->NumberOfReferrals */
3188 *number_of_UNC_in_array
= le16_to_cpu(pSMBr
->NumberOfReferrals
);
3190 /* BB Fix below so can return more than one referral */
3191 if(*number_of_UNC_in_array
> 1)
3192 *number_of_UNC_in_array
= 1;
3194 /* get the length of the strings describing refs */
3196 for(i
=0;i
<*number_of_UNC_in_array
;i
++) {
3197 /* make sure that DfsPathOffset not past end */
3198 __u16 offset
= le16_to_cpu(referrals
->DfsPathOffset
);
3199 if (offset
> data_count
) {
3200 /* if invalid referral, stop here and do
3201 not try to copy any more */
3202 *number_of_UNC_in_array
= i
;
3205 temp
= ((char *)referrals
) + offset
;
3207 if (pSMBr
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
3208 name_len
+= UniStrnlen((wchar_t *)temp
,data_count
);
3210 name_len
+= strnlen(temp
,data_count
);
3213 /* BB add check that referral pointer does not fall off end PDU */
3216 /* BB add check for name_len bigger than bcc */
3218 kmalloc(name_len
+1+ (*number_of_UNC_in_array
),GFP_KERNEL
);
3219 if(*targetUNCs
== NULL
) {
3223 /* copy the ref strings */
3225 (struct dfs_referral_level_3
*)
3226 (8 /* sizeof data hdr */ +
3228 (char *) &pSMBr
->hdr
.Protocol
);
3230 for(i
=0;i
<*number_of_UNC_in_array
;i
++) {
3231 temp
= ((char *)referrals
) + le16_to_cpu(referrals
->DfsPathOffset
);
3232 if (pSMBr
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
3233 cifs_strfromUCS_le(*targetUNCs
,
3234 (__le16
*) temp
, name_len
, nls_codepage
);
3236 strncpy(*targetUNCs
,temp
,name_len
);
3238 /* BB update target_uncs pointers */
3248 cifs_buf_release(pSMB
);
3256 /* Query File System Info such as free space to old servers such as Win 9x */
3258 SMBOldQFSInfo(const int xid
, struct cifsTconInfo
*tcon
, struct kstatfs
*FSData
)
3260 /* level 0x01 SMB_QUERY_FILE_SYSTEM_INFO */
3261 TRANSACTION2_QFSI_REQ
*pSMB
= NULL
;
3262 TRANSACTION2_QFSI_RSP
*pSMBr
= NULL
;
3263 FILE_SYSTEM_ALLOC_INFO
*response_data
;
3265 int bytes_returned
= 0;
3266 __u16 params
, byte_count
;
3268 cFYI(1, ("OldQFSInfo"));
3270 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
3274 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
3279 params
= 2; /* level */
3280 pSMB
->TotalDataCount
= 0;
3281 pSMB
->MaxParameterCount
= cpu_to_le16(2);
3282 pSMB
->MaxDataCount
= cpu_to_le16(1000);
3283 pSMB
->MaxSetupCount
= 0;
3287 pSMB
->Reserved2
= 0;
3288 byte_count
= params
+ 1 /* pad */ ;
3289 pSMB
->TotalParameterCount
= cpu_to_le16(params
);
3290 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
3291 pSMB
->ParameterOffset
= cpu_to_le16(offsetof(
3292 struct smb_com_transaction2_qfsi_req
, InformationLevel
) - 4);
3293 pSMB
->DataCount
= 0;
3294 pSMB
->DataOffset
= 0;
3295 pSMB
->SetupCount
= 1;
3296 pSMB
->Reserved3
= 0;
3297 pSMB
->SubCommand
= cpu_to_le16(TRANS2_QUERY_FS_INFORMATION
);
3298 pSMB
->InformationLevel
= cpu_to_le16(SMB_INFO_ALLOCATION
);
3299 pSMB
->hdr
.smb_buf_length
+= byte_count
;
3300 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
3302 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
3303 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
3305 cFYI(1, ("Send error in QFSInfo = %d", rc
));
3306 } else { /* decode response */
3307 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
3309 if (rc
|| (pSMBr
->ByteCount
< 18))
3310 rc
= -EIO
; /* bad smb */
3312 __u16 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
3313 cFYI(1,("qfsinf resp BCC: %d Offset %d",
3314 pSMBr
->ByteCount
, data_offset
));
3317 (FILE_SYSTEM_ALLOC_INFO
*)
3318 (((char *) &pSMBr
->hdr
.Protocol
) + data_offset
);
3320 le16_to_cpu(response_data
->BytesPerSector
) *
3321 le32_to_cpu(response_data
->
3322 SectorsPerAllocationUnit
);
3324 le32_to_cpu(response_data
->TotalAllocationUnits
);
3325 FSData
->f_bfree
= FSData
->f_bavail
=
3326 le32_to_cpu(response_data
->FreeAllocationUnits
);
3328 ("Blocks: %lld Free: %lld Block size %ld",
3329 (unsigned long long)FSData
->f_blocks
,
3330 (unsigned long long)FSData
->f_bfree
,
3334 cifs_buf_release(pSMB
);
3337 goto oldQFSInfoRetry
;
3343 CIFSSMBQFSInfo(const int xid
, struct cifsTconInfo
*tcon
, struct kstatfs
*FSData
)
3345 /* level 0x103 SMB_QUERY_FILE_SYSTEM_INFO */
3346 TRANSACTION2_QFSI_REQ
*pSMB
= NULL
;
3347 TRANSACTION2_QFSI_RSP
*pSMBr
= NULL
;
3348 FILE_SYSTEM_INFO
*response_data
;
3350 int bytes_returned
= 0;
3351 __u16 params
, byte_count
;
3353 cFYI(1, ("In QFSInfo"));
3355 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
3360 params
= 2; /* level */
3361 pSMB
->TotalDataCount
= 0;
3362 pSMB
->MaxParameterCount
= cpu_to_le16(2);
3363 pSMB
->MaxDataCount
= cpu_to_le16(1000);
3364 pSMB
->MaxSetupCount
= 0;
3368 pSMB
->Reserved2
= 0;
3369 byte_count
= params
+ 1 /* pad */ ;
3370 pSMB
->TotalParameterCount
= cpu_to_le16(params
);
3371 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
3372 pSMB
->ParameterOffset
= cpu_to_le16(offsetof(
3373 struct smb_com_transaction2_qfsi_req
, InformationLevel
) - 4);
3374 pSMB
->DataCount
= 0;
3375 pSMB
->DataOffset
= 0;
3376 pSMB
->SetupCount
= 1;
3377 pSMB
->Reserved3
= 0;
3378 pSMB
->SubCommand
= cpu_to_le16(TRANS2_QUERY_FS_INFORMATION
);
3379 pSMB
->InformationLevel
= cpu_to_le16(SMB_QUERY_FS_SIZE_INFO
);
3380 pSMB
->hdr
.smb_buf_length
+= byte_count
;
3381 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
3383 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
3384 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
3386 cFYI(1, ("Send error in QFSInfo = %d", rc
));
3387 } else { /* decode response */
3388 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
3390 if (rc
|| (pSMBr
->ByteCount
< 24))
3391 rc
= -EIO
; /* bad smb */
3393 __u16 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
3397 *) (((char *) &pSMBr
->hdr
.Protocol
) +
3400 le32_to_cpu(response_data
->BytesPerSector
) *
3401 le32_to_cpu(response_data
->
3402 SectorsPerAllocationUnit
);
3404 le64_to_cpu(response_data
->TotalAllocationUnits
);
3405 FSData
->f_bfree
= FSData
->f_bavail
=
3406 le64_to_cpu(response_data
->FreeAllocationUnits
);
3408 ("Blocks: %lld Free: %lld Block size %ld",
3409 (unsigned long long)FSData
->f_blocks
,
3410 (unsigned long long)FSData
->f_bfree
,
3414 cifs_buf_release(pSMB
);
3423 CIFSSMBQFSAttributeInfo(const int xid
, struct cifsTconInfo
*tcon
)
3425 /* level 0x105 SMB_QUERY_FILE_SYSTEM_INFO */
3426 TRANSACTION2_QFSI_REQ
*pSMB
= NULL
;
3427 TRANSACTION2_QFSI_RSP
*pSMBr
= NULL
;
3428 FILE_SYSTEM_ATTRIBUTE_INFO
*response_data
;
3430 int bytes_returned
= 0;
3431 __u16 params
, byte_count
;
3433 cFYI(1, ("In QFSAttributeInfo"));
3435 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
3440 params
= 2; /* level */
3441 pSMB
->TotalDataCount
= 0;
3442 pSMB
->MaxParameterCount
= cpu_to_le16(2);
3443 pSMB
->MaxDataCount
= cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
3444 pSMB
->MaxSetupCount
= 0;
3448 pSMB
->Reserved2
= 0;
3449 byte_count
= params
+ 1 /* pad */ ;
3450 pSMB
->TotalParameterCount
= cpu_to_le16(params
);
3451 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
3452 pSMB
->ParameterOffset
= cpu_to_le16(offsetof(
3453 struct smb_com_transaction2_qfsi_req
, InformationLevel
) - 4);
3454 pSMB
->DataCount
= 0;
3455 pSMB
->DataOffset
= 0;
3456 pSMB
->SetupCount
= 1;
3457 pSMB
->Reserved3
= 0;
3458 pSMB
->SubCommand
= cpu_to_le16(TRANS2_QUERY_FS_INFORMATION
);
3459 pSMB
->InformationLevel
= cpu_to_le16(SMB_QUERY_FS_ATTRIBUTE_INFO
);
3460 pSMB
->hdr
.smb_buf_length
+= byte_count
;
3461 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
3463 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
3464 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
3466 cERROR(1, ("Send error in QFSAttributeInfo = %d", rc
));
3467 } else { /* decode response */
3468 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
3470 if (rc
|| (pSMBr
->ByteCount
< 13)) { /* BB also check enough bytes returned */
3471 rc
= -EIO
; /* bad smb */
3473 __u16 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
3475 (FILE_SYSTEM_ATTRIBUTE_INFO
3476 *) (((char *) &pSMBr
->hdr
.Protocol
) +
3478 memcpy(&tcon
->fsAttrInfo
, response_data
,
3479 sizeof (FILE_SYSTEM_ATTRIBUTE_INFO
));
3482 cifs_buf_release(pSMB
);
3485 goto QFSAttributeRetry
;
3491 CIFSSMBQFSDeviceInfo(const int xid
, struct cifsTconInfo
*tcon
)
3493 /* level 0x104 SMB_QUERY_FILE_SYSTEM_INFO */
3494 TRANSACTION2_QFSI_REQ
*pSMB
= NULL
;
3495 TRANSACTION2_QFSI_RSP
*pSMBr
= NULL
;
3496 FILE_SYSTEM_DEVICE_INFO
*response_data
;
3498 int bytes_returned
= 0;
3499 __u16 params
, byte_count
;
3501 cFYI(1, ("In QFSDeviceInfo"));
3503 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
3508 params
= 2; /* level */
3509 pSMB
->TotalDataCount
= 0;
3510 pSMB
->MaxParameterCount
= cpu_to_le16(2);
3511 pSMB
->MaxDataCount
= cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
3512 pSMB
->MaxSetupCount
= 0;
3516 pSMB
->Reserved2
= 0;
3517 byte_count
= params
+ 1 /* pad */ ;
3518 pSMB
->TotalParameterCount
= cpu_to_le16(params
);
3519 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
3520 pSMB
->ParameterOffset
= cpu_to_le16(offsetof(
3521 struct smb_com_transaction2_qfsi_req
, InformationLevel
) - 4);
3523 pSMB
->DataCount
= 0;
3524 pSMB
->DataOffset
= 0;
3525 pSMB
->SetupCount
= 1;
3526 pSMB
->Reserved3
= 0;
3527 pSMB
->SubCommand
= cpu_to_le16(TRANS2_QUERY_FS_INFORMATION
);
3528 pSMB
->InformationLevel
= cpu_to_le16(SMB_QUERY_FS_DEVICE_INFO
);
3529 pSMB
->hdr
.smb_buf_length
+= byte_count
;
3530 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
3532 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
3533 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
3535 cFYI(1, ("Send error in QFSDeviceInfo = %d", rc
));
3536 } else { /* decode response */
3537 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
3539 if (rc
|| (pSMBr
->ByteCount
< sizeof (FILE_SYSTEM_DEVICE_INFO
)))
3540 rc
= -EIO
; /* bad smb */
3542 __u16 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
3544 (FILE_SYSTEM_DEVICE_INFO
*)
3545 (((char *) &pSMBr
->hdr
.Protocol
) +
3547 memcpy(&tcon
->fsDevInfo
, response_data
,
3548 sizeof (FILE_SYSTEM_DEVICE_INFO
));
3551 cifs_buf_release(pSMB
);
3554 goto QFSDeviceRetry
;
3560 CIFSSMBQFSUnixInfo(const int xid
, struct cifsTconInfo
*tcon
)
3562 /* level 0x200 SMB_QUERY_CIFS_UNIX_INFO */
3563 TRANSACTION2_QFSI_REQ
*pSMB
= NULL
;
3564 TRANSACTION2_QFSI_RSP
*pSMBr
= NULL
;
3565 FILE_SYSTEM_UNIX_INFO
*response_data
;
3567 int bytes_returned
= 0;
3568 __u16 params
, byte_count
;
3570 cFYI(1, ("In QFSUnixInfo"));
3572 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
3577 params
= 2; /* level */
3578 pSMB
->TotalDataCount
= 0;
3579 pSMB
->DataCount
= 0;
3580 pSMB
->DataOffset
= 0;
3581 pSMB
->MaxParameterCount
= cpu_to_le16(2);
3582 pSMB
->MaxDataCount
= cpu_to_le16(100); /* BB find exact max SMB PDU from sess structure BB */
3583 pSMB
->MaxSetupCount
= 0;
3587 pSMB
->Reserved2
= 0;
3588 byte_count
= params
+ 1 /* pad */ ;
3589 pSMB
->ParameterCount
= cpu_to_le16(params
);
3590 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
3591 pSMB
->ParameterOffset
= cpu_to_le16(offsetof(struct
3592 smb_com_transaction2_qfsi_req
, InformationLevel
) - 4);
3593 pSMB
->SetupCount
= 1;
3594 pSMB
->Reserved3
= 0;
3595 pSMB
->SubCommand
= cpu_to_le16(TRANS2_QUERY_FS_INFORMATION
);
3596 pSMB
->InformationLevel
= cpu_to_le16(SMB_QUERY_CIFS_UNIX_INFO
);
3597 pSMB
->hdr
.smb_buf_length
+= byte_count
;
3598 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
3600 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
3601 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
3603 cERROR(1, ("Send error in QFSUnixInfo = %d", rc
));
3604 } else { /* decode response */
3605 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
3607 if (rc
|| (pSMBr
->ByteCount
< 13)) {
3608 rc
= -EIO
; /* bad smb */
3610 __u16 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
3612 (FILE_SYSTEM_UNIX_INFO
3613 *) (((char *) &pSMBr
->hdr
.Protocol
) +
3615 memcpy(&tcon
->fsUnixInfo
, response_data
,
3616 sizeof (FILE_SYSTEM_UNIX_INFO
));
3619 cifs_buf_release(pSMB
);
3629 CIFSSMBSetFSUnixInfo(const int xid
, struct cifsTconInfo
*tcon
, __u64 cap
)
3631 /* level 0x200 SMB_SET_CIFS_UNIX_INFO */
3632 TRANSACTION2_SETFSI_REQ
*pSMB
= NULL
;
3633 TRANSACTION2_SETFSI_RSP
*pSMBr
= NULL
;
3635 int bytes_returned
= 0;
3636 __u16 params
, param_offset
, offset
, byte_count
;
3638 cFYI(1, ("In SETFSUnixInfo"));
3640 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
3645 params
= 4; /* 2 bytes zero followed by info level. */
3646 pSMB
->MaxSetupCount
= 0;
3650 pSMB
->Reserved2
= 0;
3651 param_offset
= offsetof(struct smb_com_transaction2_setfsi_req
, FileNum
) - 4;
3652 offset
= param_offset
+ params
;
3654 pSMB
->MaxParameterCount
= cpu_to_le16(4);
3655 pSMB
->MaxDataCount
= cpu_to_le16(100); /* BB find exact max SMB PDU from sess structure BB */
3656 pSMB
->SetupCount
= 1;
3657 pSMB
->Reserved3
= 0;
3658 pSMB
->SubCommand
= cpu_to_le16(TRANS2_SET_FS_INFORMATION
);
3659 byte_count
= 1 /* pad */ + params
+ 12;
3661 pSMB
->DataCount
= cpu_to_le16(12);
3662 pSMB
->ParameterCount
= cpu_to_le16(params
);
3663 pSMB
->TotalDataCount
= pSMB
->DataCount
;
3664 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
3665 pSMB
->ParameterOffset
= cpu_to_le16(param_offset
);
3666 pSMB
->DataOffset
= cpu_to_le16(offset
);
3670 pSMB
->InformationLevel
= cpu_to_le16(SMB_SET_CIFS_UNIX_INFO
);
3673 pSMB
->ClientUnixMajor
= cpu_to_le16(CIFS_UNIX_MAJOR_VERSION
);
3674 pSMB
->ClientUnixMinor
= cpu_to_le16(CIFS_UNIX_MINOR_VERSION
);
3675 pSMB
->ClientUnixCap
= cpu_to_le64(cap
);
3677 pSMB
->hdr
.smb_buf_length
+= byte_count
;
3678 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
3680 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
3681 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
3683 cERROR(1, ("Send error in SETFSUnixInfo = %d", rc
));
3684 } else { /* decode response */
3685 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
3687 rc
= -EIO
; /* bad smb */
3690 cifs_buf_release(pSMB
);
3693 goto SETFSUnixRetry
;
3701 CIFSSMBQFSPosixInfo(const int xid
, struct cifsTconInfo
*tcon
,
3702 struct kstatfs
*FSData
)
3704 /* level 0x201 SMB_QUERY_CIFS_POSIX_INFO */
3705 TRANSACTION2_QFSI_REQ
*pSMB
= NULL
;
3706 TRANSACTION2_QFSI_RSP
*pSMBr
= NULL
;
3707 FILE_SYSTEM_POSIX_INFO
*response_data
;
3709 int bytes_returned
= 0;
3710 __u16 params
, byte_count
;
3712 cFYI(1, ("In QFSPosixInfo"));
3714 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
3719 params
= 2; /* level */
3720 pSMB
->TotalDataCount
= 0;
3721 pSMB
->DataCount
= 0;
3722 pSMB
->DataOffset
= 0;
3723 pSMB
->MaxParameterCount
= cpu_to_le16(2);
3724 pSMB
->MaxDataCount
= cpu_to_le16(100); /* BB find exact max SMB PDU from sess structure BB */
3725 pSMB
->MaxSetupCount
= 0;
3729 pSMB
->Reserved2
= 0;
3730 byte_count
= params
+ 1 /* pad */ ;
3731 pSMB
->ParameterCount
= cpu_to_le16(params
);
3732 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
3733 pSMB
->ParameterOffset
= cpu_to_le16(offsetof(struct
3734 smb_com_transaction2_qfsi_req
, InformationLevel
) - 4);
3735 pSMB
->SetupCount
= 1;
3736 pSMB
->Reserved3
= 0;
3737 pSMB
->SubCommand
= cpu_to_le16(TRANS2_QUERY_FS_INFORMATION
);
3738 pSMB
->InformationLevel
= cpu_to_le16(SMB_QUERY_POSIX_FS_INFO
);
3739 pSMB
->hdr
.smb_buf_length
+= byte_count
;
3740 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
3742 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
3743 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
3745 cFYI(1, ("Send error in QFSUnixInfo = %d", rc
));
3746 } else { /* decode response */
3747 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
3749 if (rc
|| (pSMBr
->ByteCount
< 13)) {
3750 rc
= -EIO
; /* bad smb */
3752 __u16 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
3754 (FILE_SYSTEM_POSIX_INFO
3755 *) (((char *) &pSMBr
->hdr
.Protocol
) +
3758 le32_to_cpu(response_data
->BlockSize
);
3760 le64_to_cpu(response_data
->TotalBlocks
);
3762 le64_to_cpu(response_data
->BlocksAvail
);
3763 if(response_data
->UserBlocksAvail
== cpu_to_le64(-1)) {
3764 FSData
->f_bavail
= FSData
->f_bfree
;
3767 le64_to_cpu(response_data
->UserBlocksAvail
);
3769 if(response_data
->TotalFileNodes
!= cpu_to_le64(-1))
3771 le64_to_cpu(response_data
->TotalFileNodes
);
3772 if(response_data
->FreeFileNodes
!= cpu_to_le64(-1))
3774 le64_to_cpu(response_data
->FreeFileNodes
);
3777 cifs_buf_release(pSMB
);
3786 /* We can not use write of zero bytes trick to
3787 set file size due to need for large file support. Also note that
3788 this SetPathInfo is preferred to SetFileInfo based method in next
3789 routine which is only needed to work around a sharing violation bug
3790 in Samba which this routine can run into */
3793 CIFSSMBSetEOF(const int xid
, struct cifsTconInfo
*tcon
, const char *fileName
,
3794 __u64 size
, int SetAllocation
,
3795 const struct nls_table
*nls_codepage
, int remap
)
3797 struct smb_com_transaction2_spi_req
*pSMB
= NULL
;
3798 struct smb_com_transaction2_spi_rsp
*pSMBr
= NULL
;
3799 struct file_end_of_file_info
*parm_data
;
3802 int bytes_returned
= 0;
3803 __u16 params
, byte_count
, data_count
, param_offset
, offset
;
3805 cFYI(1, ("In SetEOF"));
3807 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
3812 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
3814 cifsConvertToUCS((__le16
*) pSMB
->FileName
, fileName
,
3815 PATH_MAX
, nls_codepage
, remap
);
3816 name_len
++; /* trailing null */
3818 } else { /* BB improve the check for buffer overruns BB */
3819 name_len
= strnlen(fileName
, PATH_MAX
);
3820 name_len
++; /* trailing null */
3821 strncpy(pSMB
->FileName
, fileName
, name_len
);
3823 params
= 6 + name_len
;
3824 data_count
= sizeof (struct file_end_of_file_info
);
3825 pSMB
->MaxParameterCount
= cpu_to_le16(2);
3826 pSMB
->MaxDataCount
= cpu_to_le16(4100);
3827 pSMB
->MaxSetupCount
= 0;
3831 pSMB
->Reserved2
= 0;
3832 param_offset
= offsetof(struct smb_com_transaction2_spi_req
,
3833 InformationLevel
) - 4;
3834 offset
= param_offset
+ params
;
3836 if (tcon
->ses
->capabilities
& CAP_INFOLEVEL_PASSTHRU
)
3837 pSMB
->InformationLevel
=
3838 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2
);
3840 pSMB
->InformationLevel
=
3841 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO
);
3842 } else /* Set File Size */ {
3843 if (tcon
->ses
->capabilities
& CAP_INFOLEVEL_PASSTHRU
)
3844 pSMB
->InformationLevel
=
3845 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO2
);
3847 pSMB
->InformationLevel
=
3848 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO
);
3852 (struct file_end_of_file_info
*) (((char *) &pSMB
->hdr
.Protocol
) +
3854 pSMB
->ParameterOffset
= cpu_to_le16(param_offset
);
3855 pSMB
->DataOffset
= cpu_to_le16(offset
);
3856 pSMB
->SetupCount
= 1;
3857 pSMB
->Reserved3
= 0;
3858 pSMB
->SubCommand
= cpu_to_le16(TRANS2_SET_PATH_INFORMATION
);
3859 byte_count
= 3 /* pad */ + params
+ data_count
;
3860 pSMB
->DataCount
= cpu_to_le16(data_count
);
3861 pSMB
->TotalDataCount
= pSMB
->DataCount
;
3862 pSMB
->ParameterCount
= cpu_to_le16(params
);
3863 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
3864 pSMB
->Reserved4
= 0;
3865 pSMB
->hdr
.smb_buf_length
+= byte_count
;
3866 parm_data
->FileSize
= cpu_to_le64(size
);
3867 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
3868 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
3869 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
3871 cFYI(1, ("SetPathInfo (file size) returned %d", rc
));
3874 cifs_buf_release(pSMB
);
3883 CIFSSMBSetFileSize(const int xid
, struct cifsTconInfo
*tcon
, __u64 size
,
3884 __u16 fid
, __u32 pid_of_opener
, int SetAllocation
)
3886 struct smb_com_transaction2_sfi_req
*pSMB
= NULL
;
3887 struct smb_com_transaction2_sfi_rsp
*pSMBr
= NULL
;
3889 struct file_end_of_file_info
*parm_data
;
3891 int bytes_returned
= 0;
3892 __u16 params
, param_offset
, offset
, byte_count
, count
;
3894 cFYI(1, ("SetFileSize (via SetFileInfo) %lld",
3896 rc
= small_smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
);
3901 pSMBr
= (struct smb_com_transaction2_sfi_rsp
*)pSMB
;
3903 pSMB
->hdr
.Pid
= cpu_to_le16((__u16
)pid_of_opener
);
3904 pSMB
->hdr
.PidHigh
= cpu_to_le16((__u16
)(pid_of_opener
>> 16));
3907 pSMB
->MaxSetupCount
= 0;
3911 pSMB
->Reserved2
= 0;
3912 param_offset
= offsetof(struct smb_com_transaction2_sfi_req
, Fid
) - 4;
3913 offset
= param_offset
+ params
;
3915 data_offset
= (char *) (&pSMB
->hdr
.Protocol
) + offset
;
3917 count
= sizeof(struct file_end_of_file_info
);
3918 pSMB
->MaxParameterCount
= cpu_to_le16(2);
3919 pSMB
->MaxDataCount
= cpu_to_le16(1000); /* BB find max SMB PDU from sess */
3920 pSMB
->SetupCount
= 1;
3921 pSMB
->Reserved3
= 0;
3922 pSMB
->SubCommand
= cpu_to_le16(TRANS2_SET_FILE_INFORMATION
);
3923 byte_count
= 3 /* pad */ + params
+ count
;
3924 pSMB
->DataCount
= cpu_to_le16(count
);
3925 pSMB
->ParameterCount
= cpu_to_le16(params
);
3926 pSMB
->TotalDataCount
= pSMB
->DataCount
;
3927 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
3928 pSMB
->ParameterOffset
= cpu_to_le16(param_offset
);
3930 (struct file_end_of_file_info
*) (((char *) &pSMB
->hdr
.Protocol
) +
3932 pSMB
->DataOffset
= cpu_to_le16(offset
);
3933 parm_data
->FileSize
= cpu_to_le64(size
);
3936 if (tcon
->ses
->capabilities
& CAP_INFOLEVEL_PASSTHRU
)
3937 pSMB
->InformationLevel
=
3938 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2
);
3940 pSMB
->InformationLevel
=
3941 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO
);
3942 } else /* Set File Size */ {
3943 if (tcon
->ses
->capabilities
& CAP_INFOLEVEL_PASSTHRU
)
3944 pSMB
->InformationLevel
=
3945 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO2
);
3947 pSMB
->InformationLevel
=
3948 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO
);
3950 pSMB
->Reserved4
= 0;
3951 pSMB
->hdr
.smb_buf_length
+= byte_count
;
3952 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
3953 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
3954 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
3957 ("Send error in SetFileInfo (SetFileSize) = %d",
3962 cifs_small_buf_release(pSMB
);
3964 /* Note: On -EAGAIN error only caller can retry on handle based calls
3965 since file handle passed in no longer valid */
3970 /* Some legacy servers such as NT4 require that the file times be set on
3971 an open handle, rather than by pathname - this is awkward due to
3972 potential access conflicts on the open, but it is unavoidable for these
3973 old servers since the only other choice is to go from 100 nanosecond DCE
3974 time and resort to the original setpathinfo level which takes the ancient
3975 DOS time format with 2 second granularity */
3977 CIFSSMBSetFileTimes(const int xid
, struct cifsTconInfo
*tcon
, const FILE_BASIC_INFO
* data
,
3980 struct smb_com_transaction2_sfi_req
*pSMB
= NULL
;
3981 struct smb_com_transaction2_sfi_rsp
*pSMBr
= NULL
;
3984 int bytes_returned
= 0;
3985 __u16 params
, param_offset
, offset
, byte_count
, count
;
3987 cFYI(1, ("Set Times (via SetFileInfo)"));
3988 rc
= small_smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
);
3993 pSMBr
= (struct smb_com_transaction2_sfi_rsp
*)pSMB
;
3995 /* At this point there is no need to override the current pid
3996 with the pid of the opener, but that could change if we someday
3997 use an existing handle (rather than opening one on the fly) */
3998 /* pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
3999 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));*/
4002 pSMB
->MaxSetupCount
= 0;
4006 pSMB
->Reserved2
= 0;
4007 param_offset
= offsetof(struct smb_com_transaction2_sfi_req
, Fid
) - 4;
4008 offset
= param_offset
+ params
;
4010 data_offset
= (char *) (&pSMB
->hdr
.Protocol
) + offset
;
4012 count
= sizeof (FILE_BASIC_INFO
);
4013 pSMB
->MaxParameterCount
= cpu_to_le16(2);
4014 pSMB
->MaxDataCount
= cpu_to_le16(1000); /* BB find max SMB PDU from sess */
4015 pSMB
->SetupCount
= 1;
4016 pSMB
->Reserved3
= 0;
4017 pSMB
->SubCommand
= cpu_to_le16(TRANS2_SET_FILE_INFORMATION
);
4018 byte_count
= 3 /* pad */ + params
+ count
;
4019 pSMB
->DataCount
= cpu_to_le16(count
);
4020 pSMB
->ParameterCount
= cpu_to_le16(params
);
4021 pSMB
->TotalDataCount
= pSMB
->DataCount
;
4022 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
4023 pSMB
->ParameterOffset
= cpu_to_le16(param_offset
);
4024 pSMB
->DataOffset
= cpu_to_le16(offset
);
4026 if (tcon
->ses
->capabilities
& CAP_INFOLEVEL_PASSTHRU
)
4027 pSMB
->InformationLevel
= cpu_to_le16(SMB_SET_FILE_BASIC_INFO2
);
4029 pSMB
->InformationLevel
= cpu_to_le16(SMB_SET_FILE_BASIC_INFO
);
4030 pSMB
->Reserved4
= 0;
4031 pSMB
->hdr
.smb_buf_length
+= byte_count
;
4032 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
4033 memcpy(data_offset
,data
,sizeof(FILE_BASIC_INFO
));
4034 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
4035 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
4037 cFYI(1,("Send error in Set Time (SetFileInfo) = %d",rc
));
4040 cifs_small_buf_release(pSMB
);
4042 /* Note: On -EAGAIN error only caller can retry on handle based calls
4043 since file handle passed in no longer valid */
4050 CIFSSMBSetTimes(const int xid
, struct cifsTconInfo
*tcon
, const char *fileName
,
4051 const FILE_BASIC_INFO
* data
,
4052 const struct nls_table
*nls_codepage
, int remap
)
4054 TRANSACTION2_SPI_REQ
*pSMB
= NULL
;
4055 TRANSACTION2_SPI_RSP
*pSMBr
= NULL
;
4058 int bytes_returned
= 0;
4060 __u16 params
, param_offset
, offset
, byte_count
, count
;
4062 cFYI(1, ("In SetTimes"));
4065 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
4070 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
4072 cifsConvertToUCS((__le16
*) pSMB
->FileName
, fileName
,
4073 PATH_MAX
, nls_codepage
, remap
);
4074 name_len
++; /* trailing null */
4076 } else { /* BB improve the check for buffer overruns BB */
4077 name_len
= strnlen(fileName
, PATH_MAX
);
4078 name_len
++; /* trailing null */
4079 strncpy(pSMB
->FileName
, fileName
, name_len
);
4082 params
= 6 + name_len
;
4083 count
= sizeof (FILE_BASIC_INFO
);
4084 pSMB
->MaxParameterCount
= cpu_to_le16(2);
4085 pSMB
->MaxDataCount
= cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
4086 pSMB
->MaxSetupCount
= 0;
4090 pSMB
->Reserved2
= 0;
4091 param_offset
= offsetof(struct smb_com_transaction2_spi_req
,
4092 InformationLevel
) - 4;
4093 offset
= param_offset
+ params
;
4094 data_offset
= (char *) (&pSMB
->hdr
.Protocol
) + offset
;
4095 pSMB
->ParameterOffset
= cpu_to_le16(param_offset
);
4096 pSMB
->DataOffset
= cpu_to_le16(offset
);
4097 pSMB
->SetupCount
= 1;
4098 pSMB
->Reserved3
= 0;
4099 pSMB
->SubCommand
= cpu_to_le16(TRANS2_SET_PATH_INFORMATION
);
4100 byte_count
= 3 /* pad */ + params
+ count
;
4102 pSMB
->DataCount
= cpu_to_le16(count
);
4103 pSMB
->ParameterCount
= cpu_to_le16(params
);
4104 pSMB
->TotalDataCount
= pSMB
->DataCount
;
4105 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
4106 if (tcon
->ses
->capabilities
& CAP_INFOLEVEL_PASSTHRU
)
4107 pSMB
->InformationLevel
= cpu_to_le16(SMB_SET_FILE_BASIC_INFO2
);
4109 pSMB
->InformationLevel
= cpu_to_le16(SMB_SET_FILE_BASIC_INFO
);
4110 pSMB
->Reserved4
= 0;
4111 pSMB
->hdr
.smb_buf_length
+= byte_count
;
4112 memcpy(data_offset
, data
, sizeof (FILE_BASIC_INFO
));
4113 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
4114 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
4115 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
4117 cFYI(1, ("SetPathInfo (times) returned %d", rc
));
4120 cifs_buf_release(pSMB
);
4128 /* Can not be used to set time stamps yet (due to old DOS time format) */
4129 /* Can be used to set attributes */
4130 #if 0 /* Possibly not needed - since it turns out that strangely NT4 has a bug
4131 handling it anyway and NT4 was what we thought it would be needed for
4132 Do not delete it until we prove whether needed for Win9x though */
4134 CIFSSMBSetAttrLegacy(int xid
, struct cifsTconInfo
*tcon
, char *fileName
,
4135 __u16 dos_attrs
, const struct nls_table
*nls_codepage
)
4137 SETATTR_REQ
*pSMB
= NULL
;
4138 SETATTR_RSP
*pSMBr
= NULL
;
4143 cFYI(1, ("In SetAttrLegacy"));
4146 rc
= smb_init(SMB_COM_SETATTR
, 8, tcon
, (void **) &pSMB
,
4151 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
4153 ConvertToUCS((__le16
*) pSMB
->fileName
, fileName
,
4154 PATH_MAX
, nls_codepage
);
4155 name_len
++; /* trailing null */
4157 } else { /* BB improve the check for buffer overruns BB */
4158 name_len
= strnlen(fileName
, PATH_MAX
);
4159 name_len
++; /* trailing null */
4160 strncpy(pSMB
->fileName
, fileName
, name_len
);
4162 pSMB
->attr
= cpu_to_le16(dos_attrs
);
4163 pSMB
->BufferFormat
= 0x04;
4164 pSMB
->hdr
.smb_buf_length
+= name_len
+ 1;
4165 pSMB
->ByteCount
= cpu_to_le16(name_len
+ 1);
4166 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
4167 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
4169 cFYI(1, ("Error in LegacySetAttr = %d", rc
));
4172 cifs_buf_release(pSMB
);
4175 goto SetAttrLgcyRetry
;
4179 #endif /* temporarily unneeded SetAttr legacy function */
4182 CIFSSMBUnixSetPerms(const int xid
, struct cifsTconInfo
*tcon
,
4183 char *fileName
, __u64 mode
, __u64 uid
, __u64 gid
,
4184 dev_t device
, const struct nls_table
*nls_codepage
,
4187 TRANSACTION2_SPI_REQ
*pSMB
= NULL
;
4188 TRANSACTION2_SPI_RSP
*pSMBr
= NULL
;
4191 int bytes_returned
= 0;
4192 FILE_UNIX_BASIC_INFO
*data_offset
;
4193 __u16 params
, param_offset
, offset
, count
, byte_count
;
4195 cFYI(1, ("In SetUID/GID/Mode"));
4197 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
4202 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
4204 cifsConvertToUCS((__le16
*) pSMB
->FileName
, fileName
,
4205 PATH_MAX
, nls_codepage
, remap
);
4206 name_len
++; /* trailing null */
4208 } else { /* BB improve the check for buffer overruns BB */
4209 name_len
= strnlen(fileName
, PATH_MAX
);
4210 name_len
++; /* trailing null */
4211 strncpy(pSMB
->FileName
, fileName
, name_len
);
4214 params
= 6 + name_len
;
4215 count
= sizeof (FILE_UNIX_BASIC_INFO
);
4216 pSMB
->MaxParameterCount
= cpu_to_le16(2);
4217 pSMB
->MaxDataCount
= cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
4218 pSMB
->MaxSetupCount
= 0;
4222 pSMB
->Reserved2
= 0;
4223 param_offset
= offsetof(struct smb_com_transaction2_spi_req
,
4224 InformationLevel
) - 4;
4225 offset
= param_offset
+ params
;
4227 (FILE_UNIX_BASIC_INFO
*) ((char *) &pSMB
->hdr
.Protocol
+
4229 memset(data_offset
, 0, count
);
4230 pSMB
->DataOffset
= cpu_to_le16(offset
);
4231 pSMB
->ParameterOffset
= cpu_to_le16(param_offset
);
4232 pSMB
->SetupCount
= 1;
4233 pSMB
->Reserved3
= 0;
4234 pSMB
->SubCommand
= cpu_to_le16(TRANS2_SET_PATH_INFORMATION
);
4235 byte_count
= 3 /* pad */ + params
+ count
;
4236 pSMB
->ParameterCount
= cpu_to_le16(params
);
4237 pSMB
->DataCount
= cpu_to_le16(count
);
4238 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
4239 pSMB
->TotalDataCount
= pSMB
->DataCount
;
4240 pSMB
->InformationLevel
= cpu_to_le16(SMB_SET_FILE_UNIX_BASIC
);
4241 pSMB
->Reserved4
= 0;
4242 pSMB
->hdr
.smb_buf_length
+= byte_count
;
4243 data_offset
->Uid
= cpu_to_le64(uid
);
4244 data_offset
->Gid
= cpu_to_le64(gid
);
4245 /* better to leave device as zero when it is */
4246 data_offset
->DevMajor
= cpu_to_le64(MAJOR(device
));
4247 data_offset
->DevMinor
= cpu_to_le64(MINOR(device
));
4248 data_offset
->Permissions
= cpu_to_le64(mode
);
4251 data_offset
->Type
= cpu_to_le32(UNIX_FILE
);
4252 else if(S_ISDIR(mode
))
4253 data_offset
->Type
= cpu_to_le32(UNIX_DIR
);
4254 else if(S_ISLNK(mode
))
4255 data_offset
->Type
= cpu_to_le32(UNIX_SYMLINK
);
4256 else if(S_ISCHR(mode
))
4257 data_offset
->Type
= cpu_to_le32(UNIX_CHARDEV
);
4258 else if(S_ISBLK(mode
))
4259 data_offset
->Type
= cpu_to_le32(UNIX_BLOCKDEV
);
4260 else if(S_ISFIFO(mode
))
4261 data_offset
->Type
= cpu_to_le32(UNIX_FIFO
);
4262 else if(S_ISSOCK(mode
))
4263 data_offset
->Type
= cpu_to_le32(UNIX_SOCKET
);
4266 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
4267 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
4268 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
4270 cFYI(1, ("SetPathInfo (perms) returned %d", rc
));
4274 cifs_buf_release(pSMB
);
4280 int CIFSSMBNotify(const int xid
, struct cifsTconInfo
*tcon
,
4281 const int notify_subdirs
, const __u16 netfid
,
4282 __u32 filter
, struct file
* pfile
, int multishot
,
4283 const struct nls_table
*nls_codepage
)
4286 struct smb_com_transaction_change_notify_req
* pSMB
= NULL
;
4287 struct smb_com_transaction_change_notify_rsp
* pSMBr
= NULL
;
4288 struct dir_notify_req
*dnotify_req
;
4291 cFYI(1, ("In CIFSSMBNotify for file handle %d",(int)netfid
));
4292 rc
= smb_init(SMB_COM_NT_TRANSACT
, 23, tcon
, (void **) &pSMB
,
4297 pSMB
->TotalParameterCount
= 0 ;
4298 pSMB
->TotalDataCount
= 0;
4299 pSMB
->MaxParameterCount
= cpu_to_le32(2);
4300 /* BB find exact data count max from sess structure BB */
4301 pSMB
->MaxDataCount
= 0; /* same in little endian or be */
4302 pSMB
->MaxSetupCount
= 4;
4304 pSMB
->ParameterOffset
= 0;
4305 pSMB
->DataCount
= 0;
4306 pSMB
->DataOffset
= 0;
4307 pSMB
->SetupCount
= 4; /* single byte does not need le conversion */
4308 pSMB
->SubCommand
= cpu_to_le16(NT_TRANSACT_NOTIFY_CHANGE
);
4309 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
4311 pSMB
->WatchTree
= 1; /* one byte - no le conversion needed */
4312 pSMB
->Reserved2
= 0;
4313 pSMB
->CompletionFilter
= cpu_to_le32(filter
);
4314 pSMB
->Fid
= netfid
; /* file handle always le */
4315 pSMB
->ByteCount
= 0;
4317 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
4318 (struct smb_hdr
*) pSMBr
, &bytes_returned
, -1);
4320 cFYI(1, ("Error in Notify = %d", rc
));
4322 /* Add file to outstanding requests */
4323 /* BB change to kmem cache alloc */
4324 dnotify_req
= (struct dir_notify_req
*) kmalloc(
4325 sizeof(struct dir_notify_req
),
4328 dnotify_req
->Pid
= pSMB
->hdr
.Pid
;
4329 dnotify_req
->PidHigh
= pSMB
->hdr
.PidHigh
;
4330 dnotify_req
->Mid
= pSMB
->hdr
.Mid
;
4331 dnotify_req
->Tid
= pSMB
->hdr
.Tid
;
4332 dnotify_req
->Uid
= pSMB
->hdr
.Uid
;
4333 dnotify_req
->netfid
= netfid
;
4334 dnotify_req
->pfile
= pfile
;
4335 dnotify_req
->filter
= filter
;
4336 dnotify_req
->multishot
= multishot
;
4337 spin_lock(&GlobalMid_Lock
);
4338 list_add_tail(&dnotify_req
->lhead
,
4339 &GlobalDnotifyReqList
);
4340 spin_unlock(&GlobalMid_Lock
);
4344 cifs_buf_release(pSMB
);
4347 #ifdef CONFIG_CIFS_XATTR
4349 CIFSSMBQAllEAs(const int xid
, struct cifsTconInfo
*tcon
,
4350 const unsigned char *searchName
,
4351 char * EAData
, size_t buf_size
,
4352 const struct nls_table
*nls_codepage
, int remap
)
4354 /* BB assumes one setup word */
4355 TRANSACTION2_QPI_REQ
*pSMB
= NULL
;
4356 TRANSACTION2_QPI_RSP
*pSMBr
= NULL
;
4360 struct fea
* temp_fea
;
4362 __u16 params
, byte_count
;
4364 cFYI(1, ("In Query All EAs path %s", searchName
));
4366 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
4371 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
4373 cifsConvertToUCS((__le16
*) pSMB
->FileName
, searchName
,
4374 PATH_MAX
, nls_codepage
, remap
);
4375 name_len
++; /* trailing null */
4377 } else { /* BB improve the check for buffer overruns BB */
4378 name_len
= strnlen(searchName
, PATH_MAX
);
4379 name_len
++; /* trailing null */
4380 strncpy(pSMB
->FileName
, searchName
, name_len
);
4383 params
= 2 /* level */ + 4 /* reserved */ + name_len
/* includes NUL */ ;
4384 pSMB
->TotalDataCount
= 0;
4385 pSMB
->MaxParameterCount
= cpu_to_le16(2);
4386 pSMB
->MaxDataCount
= cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
4387 pSMB
->MaxSetupCount
= 0;
4391 pSMB
->Reserved2
= 0;
4392 pSMB
->ParameterOffset
= cpu_to_le16(offsetof(
4393 struct smb_com_transaction2_qpi_req
,InformationLevel
) - 4);
4394 pSMB
->DataCount
= 0;
4395 pSMB
->DataOffset
= 0;
4396 pSMB
->SetupCount
= 1;
4397 pSMB
->Reserved3
= 0;
4398 pSMB
->SubCommand
= cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION
);
4399 byte_count
= params
+ 1 /* pad */ ;
4400 pSMB
->TotalParameterCount
= cpu_to_le16(params
);
4401 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
4402 pSMB
->InformationLevel
= cpu_to_le16(SMB_INFO_QUERY_ALL_EAS
);
4403 pSMB
->Reserved4
= 0;
4404 pSMB
->hdr
.smb_buf_length
+= byte_count
;
4405 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
4407 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
4408 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
4410 cFYI(1, ("Send error in QueryAllEAs = %d", rc
));
4411 } else { /* decode response */
4412 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
4414 /* BB also check enough total bytes returned */
4415 /* BB we need to improve the validity checking
4416 of these trans2 responses */
4417 if (rc
|| (pSMBr
->ByteCount
< 4))
4418 rc
= -EIO
; /* bad smb */
4419 /* else if (pFindData){
4420 memcpy((char *) pFindData,
4421 (char *) &pSMBr->hdr.Protocol +
4424 /* check that length of list is not more than bcc */
4425 /* check that each entry does not go beyond length
4427 /* check that each element of each entry does not
4428 go beyond end of list */
4429 __u16 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
4430 struct fealist
* ea_response_data
;
4432 /* validate_trans2_offsets() */
4433 /* BB to check if(start of smb + data_offset > &bcc+ bcc)*/
4434 ea_response_data
= (struct fealist
*)
4435 (((char *) &pSMBr
->hdr
.Protocol
) +
4437 name_len
= le32_to_cpu(ea_response_data
->list_len
);
4438 cFYI(1,("ea length %d", name_len
));
4440 /* returned EA size zeroed at top of function */
4441 cFYI(1,("empty EA list returned from server"));
4443 /* account for ea list len */
4445 temp_fea
= ea_response_data
->list
;
4446 temp_ptr
= (char *)temp_fea
;
4447 while(name_len
> 0) {
4451 rc
+= temp_fea
->name_len
;
4452 /* account for prefix user. and trailing null */
4454 if(rc
<(int)buf_size
) {
4455 memcpy(EAData
,"user.",5);
4457 memcpy(EAData
,temp_ptr
,temp_fea
->name_len
);
4458 EAData
+=temp_fea
->name_len
;
4459 /* null terminate name */
4461 EAData
= EAData
+ 1;
4462 } else if(buf_size
== 0) {
4463 /* skip copy - calc size only */
4465 /* stop before overrun buffer */
4469 name_len
-= temp_fea
->name_len
;
4470 temp_ptr
+= temp_fea
->name_len
;
4471 /* account for trailing null */
4474 value_len
= le16_to_cpu(temp_fea
->value_len
);
4475 name_len
-= value_len
;
4476 temp_ptr
+= value_len
;
4477 /* BB check that temp_ptr is still within smb BB*/
4478 /* no trailing null to account for in value len */
4479 /* go on to next EA */
4480 temp_fea
= (struct fea
*)temp_ptr
;
4486 cifs_buf_release(pSMB
);
4493 ssize_t
CIFSSMBQueryEA(const int xid
,struct cifsTconInfo
* tcon
,
4494 const unsigned char * searchName
,const unsigned char * ea_name
,
4495 unsigned char * ea_value
, size_t buf_size
,
4496 const struct nls_table
*nls_codepage
, int remap
)
4498 TRANSACTION2_QPI_REQ
*pSMB
= NULL
;
4499 TRANSACTION2_QPI_RSP
*pSMBr
= NULL
;
4503 struct fea
* temp_fea
;
4505 __u16 params
, byte_count
;
4507 cFYI(1, ("In Query EA path %s", searchName
));
4509 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
4514 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
4516 cifsConvertToUCS((__le16
*) pSMB
->FileName
, searchName
,
4517 PATH_MAX
, nls_codepage
, remap
);
4518 name_len
++; /* trailing null */
4520 } else { /* BB improve the check for buffer overruns BB */
4521 name_len
= strnlen(searchName
, PATH_MAX
);
4522 name_len
++; /* trailing null */
4523 strncpy(pSMB
->FileName
, searchName
, name_len
);
4526 params
= 2 /* level */ + 4 /* reserved */ + name_len
/* includes NUL */ ;
4527 pSMB
->TotalDataCount
= 0;
4528 pSMB
->MaxParameterCount
= cpu_to_le16(2);
4529 pSMB
->MaxDataCount
= cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
4530 pSMB
->MaxSetupCount
= 0;
4534 pSMB
->Reserved2
= 0;
4535 pSMB
->ParameterOffset
= cpu_to_le16(offsetof(
4536 struct smb_com_transaction2_qpi_req
,InformationLevel
) - 4);
4537 pSMB
->DataCount
= 0;
4538 pSMB
->DataOffset
= 0;
4539 pSMB
->SetupCount
= 1;
4540 pSMB
->Reserved3
= 0;
4541 pSMB
->SubCommand
= cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION
);
4542 byte_count
= params
+ 1 /* pad */ ;
4543 pSMB
->TotalParameterCount
= cpu_to_le16(params
);
4544 pSMB
->ParameterCount
= pSMB
->TotalParameterCount
;
4545 pSMB
->InformationLevel
= cpu_to_le16(SMB_INFO_QUERY_ALL_EAS
);
4546 pSMB
->Reserved4
= 0;
4547 pSMB
->hdr
.smb_buf_length
+= byte_count
;
4548 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
4550 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
4551 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
4553 cFYI(1, ("Send error in Query EA = %d", rc
));
4554 } else { /* decode response */
4555 rc
= validate_t2((struct smb_t2_rsp
*)pSMBr
);
4557 /* BB also check enough total bytes returned */
4558 /* BB we need to improve the validity checking
4559 of these trans2 responses */
4560 if (rc
|| (pSMBr
->ByteCount
< 4))
4561 rc
= -EIO
; /* bad smb */
4562 /* else if (pFindData){
4563 memcpy((char *) pFindData,
4564 (char *) &pSMBr->hdr.Protocol +
4567 /* check that length of list is not more than bcc */
4568 /* check that each entry does not go beyond length
4570 /* check that each element of each entry does not
4571 go beyond end of list */
4572 __u16 data_offset
= le16_to_cpu(pSMBr
->t2
.DataOffset
);
4573 struct fealist
* ea_response_data
;
4575 /* validate_trans2_offsets() */
4576 /* BB to check if(start of smb + data_offset > &bcc+ bcc)*/
4577 ea_response_data
= (struct fealist
*)
4578 (((char *) &pSMBr
->hdr
.Protocol
) +
4580 name_len
= le32_to_cpu(ea_response_data
->list_len
);
4581 cFYI(1,("ea length %d", name_len
));
4583 /* returned EA size zeroed at top of function */
4584 cFYI(1,("empty EA list returned from server"));
4586 /* account for ea list len */
4588 temp_fea
= ea_response_data
->list
;
4589 temp_ptr
= (char *)temp_fea
;
4590 /* loop through checking if we have a matching
4591 name and then return the associated value */
4592 while(name_len
> 0) {
4596 value_len
= le16_to_cpu(temp_fea
->value_len
);
4597 /* BB validate that value_len falls within SMB,
4598 even though maximum for name_len is 255 */
4599 if(memcmp(temp_fea
->name
,ea_name
,
4600 temp_fea
->name_len
) == 0) {
4603 /* account for prefix user. and trailing null */
4604 if(rc
<=(int)buf_size
) {
4606 temp_fea
->name
+temp_fea
->name_len
+1,
4608 /* ea values, unlike ea names,
4609 are not null terminated */
4610 } else if(buf_size
== 0) {
4611 /* skip copy - calc size only */
4613 /* stop before overrun buffer */
4618 name_len
-= temp_fea
->name_len
;
4619 temp_ptr
+= temp_fea
->name_len
;
4620 /* account for trailing null */
4623 name_len
-= value_len
;
4624 temp_ptr
+= value_len
;
4625 /* no trailing null to account for in value len */
4626 /* go on to next EA */
4627 temp_fea
= (struct fea
*)temp_ptr
;
4633 cifs_buf_release(pSMB
);
4641 CIFSSMBSetEA(const int xid
, struct cifsTconInfo
*tcon
, const char *fileName
,
4642 const char * ea_name
, const void * ea_value
,
4643 const __u16 ea_value_len
, const struct nls_table
*nls_codepage
,
4646 struct smb_com_transaction2_spi_req
*pSMB
= NULL
;
4647 struct smb_com_transaction2_spi_rsp
*pSMBr
= NULL
;
4648 struct fealist
*parm_data
;
4651 int bytes_returned
= 0;
4652 __u16 params
, param_offset
, byte_count
, offset
, count
;
4654 cFYI(1, ("In SetEA"));
4656 rc
= smb_init(SMB_COM_TRANSACTION2
, 15, tcon
, (void **) &pSMB
,
4661 if (pSMB
->hdr
.Flags2
& SMBFLG2_UNICODE
) {
4663 cifsConvertToUCS((__le16
*) pSMB
->FileName
, fileName
,
4664 PATH_MAX
, nls_codepage
, remap
);
4665 name_len
++; /* trailing null */
4667 } else { /* BB improve the check for buffer overruns BB */
4668 name_len
= strnlen(fileName
, PATH_MAX
);
4669 name_len
++; /* trailing null */
4670 strncpy(pSMB
->FileName
, fileName
, name_len
);
4673 params
= 6 + name_len
;
4675 /* done calculating parms using name_len of file name,
4676 now use name_len to calculate length of ea name
4677 we are going to create in the inode xattrs */
4681 name_len
= strnlen(ea_name
,255);
4683 count
= sizeof(*parm_data
) + ea_value_len
+ name_len
+ 1;
4684 pSMB
->MaxParameterCount
= cpu_to_le16(2);
4685 pSMB
->MaxDataCount
= cpu_to_le16(1000); /* BB find max SMB size from sess */
4686 pSMB
->MaxSetupCount
= 0;
4690 pSMB
->Reserved2
= 0;
4691 param_offset
= offsetof(struct smb_com_transaction2_spi_req
,
4692 InformationLevel
) - 4;
4693 offset
= param_offset
+ params
;
4694 pSMB
->InformationLevel
=
4695 cpu_to_le16(SMB_SET_FILE_EA
);
4698 (struct fealist
*) (((char *) &pSMB
->hdr
.Protocol
) +
4700 pSMB
->ParameterOffset
= cpu_to_le16(param_offset
);
4701 pSMB
->DataOffset
= cpu_to_le16(offset
);
4702 pSMB
->SetupCount
= 1;
4703 pSMB
->Reserved3
= 0;
4704 pSMB
->SubCommand
= cpu_to_le16(TRANS2_SET_PATH_INFORMATION
);
4705 byte_count
= 3 /* pad */ + params
+ count
;
4706 pSMB
->DataCount
= cpu_to_le16(count
);
4707 parm_data
->list_len
= cpu_to_le32(count
);
4708 parm_data
->list
[0].EA_flags
= 0;
4709 /* we checked above that name len is less than 255 */
4710 parm_data
->list
[0].name_len
= (__u8
)name_len
;;
4711 /* EA names are always ASCII */
4713 strncpy(parm_data
->list
[0].name
,ea_name
,name_len
);
4714 parm_data
->list
[0].name
[name_len
] = 0;
4715 parm_data
->list
[0].value_len
= cpu_to_le16(ea_value_len
);
4716 /* caller ensures that ea_value_len is less than 64K but
4717 we need to ensure that it fits within the smb */
4719 /*BB add length check that it would fit in negotiated SMB buffer size BB */
4720 /* if(ea_value_len > buffer_size - 512 (enough for header)) */
4722 memcpy(parm_data
->list
[0].name
+name_len
+1,ea_value
,ea_value_len
);
4724 pSMB
->TotalDataCount
= pSMB
->DataCount
;
4725 pSMB
->ParameterCount
= cpu_to_le16(params
);
4726 pSMB
->TotalParameterCount
= pSMB
->ParameterCount
;
4727 pSMB
->Reserved4
= 0;
4728 pSMB
->hdr
.smb_buf_length
+= byte_count
;
4729 pSMB
->ByteCount
= cpu_to_le16(byte_count
);
4730 rc
= SendReceive(xid
, tcon
->ses
, (struct smb_hdr
*) pSMB
,
4731 (struct smb_hdr
*) pSMBr
, &bytes_returned
, 0);
4733 cFYI(1, ("SetPathInfo (EA) returned %d", rc
));
4736 cifs_buf_release(pSMB
);