4 * Copyright (C) International Business Machines Corp., 2002,2005
5 * Author(s): Steve French (sfrench@us.ibm.com)
7 * Contains the routines for constructing the SMB PDUs themselves
9 * This library is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU Lesser General Public License as published
11 * by the Free Software Foundation; either version 2.1 of the License, or
12 * (at your option) any later version.
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
17 * the GNU Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public License
20 * along with this library; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 /* SMB/CIFS PDU handling routines here - except for leftovers in connect.c */
25 /* These are mostly routines that operate on a pathname, or on a tree id */
26 /* (mounted volume), but there are eight handle based routines which must be */
27 /* treated slightly different for reconnection purposes since we never want */
28 /* to reuse a stale file handle and the caller knows the file handle */
31 #include <linux/kernel.h>
32 #include <linux/vfs.h>
33 #include <linux/posix_acl_xattr.h>
34 #include <asm/uaccess.h>
37 #include "cifsproto.h"
38 #include "cifs_unicode.h"
39 #include "cifs_debug.h"
41 #ifdef CONFIG_CIFS_POSIX
46 {CIFS_PROT, "\2NT LM 0.12"},
47 {CIFS_PROT, "\2POSIX 2"},
55 {CIFS_PROT, "\2NT LM 0.12"},
61 /* Mark as invalid, all open files on tree connections since they
62 were closed when session to server was lost */
63 static void mark_open_files_invalid(struct cifsTconInfo * pTcon)
65 struct cifsFileInfo *open_file = NULL;
66 struct list_head * tmp;
67 struct list_head * tmp1;
69 /* list all files open on tree connection and mark them invalid */
70 write_lock(&GlobalSMBSeslock);
71 list_for_each_safe(tmp, tmp1, &pTcon->openFileList) {
72 open_file = list_entry(tmp,struct cifsFileInfo, tlist);
74 open_file->invalidHandle = TRUE;
77 write_unlock(&GlobalSMBSeslock);
78 /* BB Add call to invalidate_inodes(sb) for all superblocks mounted
82 /* If the return code is zero, this function must fill in request_buf pointer */
84 small_smb_init(int smb_command, int wct, struct cifsTconInfo *tcon,
85 void **request_buf /* returned */)
89 /* SMBs NegProt, SessSetup, uLogoff do not have tcon yet so
90 check for tcp and smb session status done differently
91 for those three - in the calling routine */
93 if((tcon->ses) && (tcon->ses->status != CifsExiting) &&
95 struct nls_table *nls_codepage;
96 /* Give Demultiplex thread up to 10 seconds to
97 reconnect, should be greater than cifs socket
98 timeout which is 7 seconds */
99 while(tcon->ses->server->tcpStatus == CifsNeedReconnect) {
100 wait_event_interruptible_timeout(tcon->ses->server->response_q,
101 (tcon->ses->server->tcpStatus == CifsGood), 10 * HZ);
102 if(tcon->ses->server->tcpStatus == CifsNeedReconnect) {
103 /* on "soft" mounts we wait once */
104 if((tcon->retry == FALSE) ||
105 (tcon->ses->status == CifsExiting)) {
106 cFYI(1,("gave up waiting on reconnect in smb_init"));
108 } /* else "hard" mount - keep retrying
109 until process is killed or server
110 comes back on-line */
111 } else /* TCP session is reestablished now */
116 nls_codepage = load_nls_default();
117 /* need to prevent multiple threads trying to
118 simultaneously reconnect the same SMB session */
119 down(&tcon->ses->sesSem);
120 if(tcon->ses->status == CifsNeedReconnect)
121 rc = cifs_setup_session(0, tcon->ses,
123 if(!rc && (tcon->tidStatus == CifsNeedReconnect)) {
124 mark_open_files_invalid(tcon);
125 rc = CIFSTCon(0, tcon->ses, tcon->treeName, tcon
127 up(&tcon->ses->sesSem);
129 atomic_inc(&tconInfoReconnectCount);
131 cFYI(1, ("reconnect tcon rc = %d", rc));
132 /* Removed call to reopen open files here -
133 it is safer (and faster) to reopen files
134 one at a time as needed in read and write */
136 /* Check if handle based operation so we
137 know whether we can continue or not without
138 returning to caller to reset file handle */
139 switch(smb_command) {
140 case SMB_COM_READ_ANDX:
141 case SMB_COM_WRITE_ANDX:
143 case SMB_COM_FIND_CLOSE2:
144 case SMB_COM_LOCKING_ANDX: {
145 unload_nls(nls_codepage);
150 up(&tcon->ses->sesSem);
152 unload_nls(nls_codepage);
161 *request_buf = cifs_small_buf_get();
162 if (*request_buf == NULL) {
163 /* BB should we add a retry in here if not a writepage? */
167 header_assemble((struct smb_hdr *) *request_buf, smb_command, tcon,wct);
169 #ifdef CONFIG_CIFS_STATS
171 atomic_inc(&tcon->num_smbs_sent);
173 #endif /* CONFIG_CIFS_STATS */
177 /* If the return code is zero, this function must fill in request_buf pointer */
179 smb_init(int smb_command, int wct, struct cifsTconInfo *tcon,
180 void **request_buf /* returned */ ,
181 void **response_buf /* returned */ )
185 /* SMBs NegProt, SessSetup, uLogoff do not have tcon yet so
186 check for tcp and smb session status done differently
187 for those three - in the calling routine */
189 if((tcon->ses) && (tcon->ses->status != CifsExiting) &&
190 (tcon->ses->server)){
191 struct nls_table *nls_codepage;
192 /* Give Demultiplex thread up to 10 seconds to
193 reconnect, should be greater than cifs socket
194 timeout which is 7 seconds */
195 while(tcon->ses->server->tcpStatus == CifsNeedReconnect) {
196 wait_event_interruptible_timeout(tcon->ses->server->response_q,
197 (tcon->ses->server->tcpStatus == CifsGood), 10 * HZ);
198 if(tcon->ses->server->tcpStatus ==
200 /* on "soft" mounts we wait once */
201 if((tcon->retry == FALSE) ||
202 (tcon->ses->status == CifsExiting)) {
203 cFYI(1,("gave up waiting on reconnect in smb_init"));
205 } /* else "hard" mount - keep retrying
206 until process is killed or server
208 } else /* TCP session is reestablished now */
213 nls_codepage = load_nls_default();
214 /* need to prevent multiple threads trying to
215 simultaneously reconnect the same SMB session */
216 down(&tcon->ses->sesSem);
217 if(tcon->ses->status == CifsNeedReconnect)
218 rc = cifs_setup_session(0, tcon->ses,
220 if(!rc && (tcon->tidStatus == CifsNeedReconnect)) {
221 mark_open_files_invalid(tcon);
222 rc = CIFSTCon(0, tcon->ses, tcon->treeName,
224 up(&tcon->ses->sesSem);
226 atomic_inc(&tconInfoReconnectCount);
228 cFYI(1, ("reconnect tcon rc = %d", rc));
229 /* Removed call to reopen open files here -
230 it is safer (and faster) to reopen files
231 one at a time as needed in read and write */
233 /* Check if handle based operation so we
234 know whether we can continue or not without
235 returning to caller to reset file handle */
236 switch(smb_command) {
237 case SMB_COM_READ_ANDX:
238 case SMB_COM_WRITE_ANDX:
240 case SMB_COM_FIND_CLOSE2:
241 case SMB_COM_LOCKING_ANDX: {
242 unload_nls(nls_codepage);
247 up(&tcon->ses->sesSem);
249 unload_nls(nls_codepage);
258 *request_buf = cifs_buf_get();
259 if (*request_buf == NULL) {
260 /* BB should we add a retry in here if not a writepage? */
263 /* Although the original thought was we needed the response buf for */
264 /* potential retries of smb operations it turns out we can determine */
265 /* from the mid flags when the request buffer can be resent without */
266 /* having to use a second distinct buffer for the response */
267 *response_buf = *request_buf;
269 header_assemble((struct smb_hdr *) *request_buf, smb_command, tcon,
272 #ifdef CONFIG_CIFS_STATS
274 atomic_inc(&tcon->num_smbs_sent);
276 #endif /* CONFIG_CIFS_STATS */
280 static int validate_t2(struct smb_t2_rsp * pSMB)
286 /* check for plausible wct, bcc and t2 data and parm sizes */
287 /* check for parm and data offset going beyond end of smb */
288 if(pSMB->hdr.WordCount >= 10) {
289 if((le16_to_cpu(pSMB->t2_rsp.ParameterOffset) <= 1024) &&
290 (le16_to_cpu(pSMB->t2_rsp.DataOffset) <= 1024)) {
291 /* check that bcc is at least as big as parms + data */
292 /* check that bcc is less than negotiated smb buffer */
293 total_size = le16_to_cpu(pSMB->t2_rsp.ParameterCount);
294 if(total_size < 512) {
295 total_size+=le16_to_cpu(pSMB->t2_rsp.DataCount);
296 /* BCC le converted in SendReceive */
297 pBCC = (pSMB->hdr.WordCount * 2) +
298 sizeof(struct smb_hdr) +
300 if((total_size <= (*(u16 *)pBCC)) &&
302 CIFSMaxBufSize+MAX_CIFS_HDR_SIZE)) {
309 cifs_dump_mem("Invalid transact2 SMB: ",(char *)pSMB,
310 sizeof(struct smb_t2_rsp) + 16);
314 CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses)
317 NEGOTIATE_RSP *pSMBr;
320 struct TCP_Server_Info * server;
324 server = ses->server;
329 rc = smb_init(SMB_COM_NEGOTIATE, 0, NULL /* no tcon yet */ ,
330 (void **) &pSMB, (void **) &pSMBr);
334 pSMB->hdr.Flags2 |= SMBFLG2_UNICODE;
335 if (extended_security)
336 pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC;
338 count = strlen(protocols[0].name) + 1;
339 strncpy(pSMB->DialectsArray, protocols[0].name, 30);
340 /* null guaranteed to be at end of source and target buffers anyway */
342 pSMB->hdr.smb_buf_length += count;
343 pSMB->ByteCount = cpu_to_le16(count);
345 rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB,
346 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
348 server->secMode = pSMBr->SecurityMode;
349 server->secType = NTLM; /* BB override default for
350 NTLMv2 or kerberos v5 */
351 /* one byte - no need to convert this or EncryptionKeyLen
352 from little endian */
353 server->maxReq = le16_to_cpu(pSMBr->MaxMpxCount);
354 /* probably no need to store and check maxvcs */
356 min(le32_to_cpu(pSMBr->MaxBufferSize),
357 (__u32) CIFSMaxBufSize + MAX_CIFS_HDR_SIZE);
358 server->maxRw = le32_to_cpu(pSMBr->MaxRawSize);
359 cFYI(0, ("Max buf = %d ", ses->server->maxBuf));
360 GETU32(ses->server->sessid) = le32_to_cpu(pSMBr->SessionKey);
361 server->capabilities = le32_to_cpu(pSMBr->Capabilities);
362 server->timeZone = le16_to_cpu(pSMBr->ServerTimeZone);
363 /* BB with UTC do we ever need to be using srvr timezone? */
364 if (pSMBr->EncryptionKeyLength == CIFS_CRYPTO_KEY_SIZE) {
365 memcpy(server->cryptKey, pSMBr->u.EncryptionKey,
366 CIFS_CRYPTO_KEY_SIZE);
367 } else if ((pSMBr->hdr.Flags2 & SMBFLG2_EXT_SEC)
368 && (pSMBr->EncryptionKeyLength == 0)) {
369 /* decode security blob */
373 /* BB might be helpful to save off the domain of server here */
375 if ((pSMBr->hdr.Flags2 & SMBFLG2_EXT_SEC) &&
376 (server->capabilities & CAP_EXTENDED_SECURITY)) {
377 count = pSMBr->ByteCount;
380 else if (count == 16) {
381 server->secType = RawNTLMSSP;
382 if (server->socketUseCount.counter > 1) {
384 (server->server_GUID,
385 pSMBr->u.extended_response.
388 ("UID of server does not match previous connection to same ip address"));
396 memcpy(server->server_GUID,
397 pSMBr->u.extended_response.
400 rc = decode_negTokenInit(pSMBr->u.
406 /* BB Need to fill struct for sessetup here */
413 server->capabilities &= ~CAP_EXTENDED_SECURITY;
414 if(sign_CIFS_PDUs == FALSE) {
415 if(server->secMode & SECMODE_SIGN_REQUIRED)
417 ("Server requires /proc/fs/cifs/PacketSigningEnabled"));
418 server->secMode &= ~(SECMODE_SIGN_ENABLED | SECMODE_SIGN_REQUIRED);
419 } else if(sign_CIFS_PDUs == 1) {
420 if((server->secMode & SECMODE_SIGN_REQUIRED) == 0)
421 server->secMode &= ~(SECMODE_SIGN_ENABLED | SECMODE_SIGN_REQUIRED);
426 cifs_buf_release(pSMB);
431 CIFSSMBTDis(const int xid, struct cifsTconInfo *tcon)
433 struct smb_hdr *smb_buffer;
434 struct smb_hdr *smb_buffer_response; /* BB removeme BB */
438 cFYI(1, ("In tree disconnect"));
440 * If last user of the connection and
441 * connection alive - disconnect it
442 * If this is the last connection on the server session disconnect it
443 * (and inside session disconnect we should check if tcp socket needs
444 * to be freed and kernel thread woken up).
447 down(&tcon->tconSem);
451 atomic_dec(&tcon->useCount);
452 if (atomic_read(&tcon->useCount) > 0) {
457 /* No need to return error on this operation if tid invalidated and
458 closed on server already e.g. due to tcp session crashing */
459 if(tcon->tidStatus == CifsNeedReconnect) {
464 if((tcon->ses == NULL) || (tcon->ses->server == NULL)) {
468 rc = small_smb_init(SMB_COM_TREE_DISCONNECT, 0, tcon,
469 (void **)&smb_buffer);
474 smb_buffer_response = smb_buffer; /* BB removeme BB */
476 rc = SendReceive(xid, tcon->ses, smb_buffer, smb_buffer_response,
479 cFYI(1, ("Tree disconnect failed %d", rc));
482 cifs_small_buf_release(smb_buffer);
485 /* No need to return error on this operation if tid invalidated and
486 closed on server already e.g. due to tcp session crashing */
494 CIFSSMBLogoff(const int xid, struct cifsSesInfo *ses)
496 struct smb_hdr *smb_buffer_response;
497 LOGOFF_ANDX_REQ *pSMB;
501 cFYI(1, ("In SMBLogoff for session disconnect"));
507 atomic_dec(&ses->inUse);
508 if (atomic_read(&ses->inUse) > 0) {
512 rc = small_smb_init(SMB_COM_LOGOFF_ANDX, 2, NULL, (void **)&pSMB);
518 smb_buffer_response = (struct smb_hdr *)pSMB; /* BB removeme BB */
521 if(ses->server->secMode &
522 (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
523 pSMB->hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
526 pSMB->hdr.Uid = ses->Suid;
528 pSMB->AndXCommand = 0xFF;
529 rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB,
530 smb_buffer_response, &length, 0);
532 atomic_dec(&ses->server->socketUseCount);
533 if (atomic_read(&ses->server->socketUseCount) == 0) {
534 spin_lock(&GlobalMid_Lock);
535 ses->server->tcpStatus = CifsExiting;
536 spin_unlock(&GlobalMid_Lock);
541 cifs_small_buf_release(pSMB);
544 /* if session dead then we do not need to do ulogoff,
545 since server closed smb session, no sense reporting
553 CIFSSMBDelFile(const int xid, struct cifsTconInfo *tcon, const char *fileName,
554 const struct nls_table *nls_codepage, int remap)
556 DELETE_FILE_REQ *pSMB = NULL;
557 DELETE_FILE_RSP *pSMBr = NULL;
563 rc = smb_init(SMB_COM_DELETE, 1, tcon, (void **) &pSMB,
568 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
570 cifsConvertToUCS((__le16 *) pSMB->fileName, fileName,
571 PATH_MAX, nls_codepage, remap);
572 name_len++; /* trailing null */
574 } else { /* BB improve check for buffer overruns BB */
575 name_len = strnlen(fileName, PATH_MAX);
576 name_len++; /* trailing null */
577 strncpy(pSMB->fileName, fileName, name_len);
579 pSMB->SearchAttributes =
580 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM);
581 pSMB->BufferFormat = 0x04;
582 pSMB->hdr.smb_buf_length += name_len + 1;
583 pSMB->ByteCount = cpu_to_le16(name_len + 1);
584 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
585 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
587 cFYI(1, ("Error in RMFile = %d", rc));
589 #ifdef CONFIG_CIFS_STATS
591 atomic_inc(&tcon->num_deletes);
595 cifs_buf_release(pSMB);
603 CIFSSMBRmDir(const int xid, struct cifsTconInfo *tcon, const char *dirName,
604 const struct nls_table *nls_codepage, int remap)
606 DELETE_DIRECTORY_REQ *pSMB = NULL;
607 DELETE_DIRECTORY_RSP *pSMBr = NULL;
612 cFYI(1, ("In CIFSSMBRmDir"));
614 rc = smb_init(SMB_COM_DELETE_DIRECTORY, 0, tcon, (void **) &pSMB,
619 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
620 name_len = cifsConvertToUCS((__le16 *) pSMB->DirName, dirName,
621 PATH_MAX, nls_codepage, remap);
622 name_len++; /* trailing null */
624 } else { /* BB improve check for buffer overruns BB */
625 name_len = strnlen(dirName, PATH_MAX);
626 name_len++; /* trailing null */
627 strncpy(pSMB->DirName, dirName, name_len);
630 pSMB->BufferFormat = 0x04;
631 pSMB->hdr.smb_buf_length += name_len + 1;
632 pSMB->ByteCount = cpu_to_le16(name_len + 1);
633 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
634 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
636 cFYI(1, ("Error in RMDir = %d", rc));
638 #ifdef CONFIG_CIFS_STATS
640 atomic_inc(&tcon->num_rmdirs);
644 cifs_buf_release(pSMB);
651 CIFSSMBMkDir(const int xid, struct cifsTconInfo *tcon,
652 const char *name, const struct nls_table *nls_codepage, int remap)
655 CREATE_DIRECTORY_REQ *pSMB = NULL;
656 CREATE_DIRECTORY_RSP *pSMBr = NULL;
660 cFYI(1, ("In CIFSSMBMkDir"));
662 rc = smb_init(SMB_COM_CREATE_DIRECTORY, 0, tcon, (void **) &pSMB,
667 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
668 name_len = cifsConvertToUCS((__le16 *) pSMB->DirName, name,
669 PATH_MAX, nls_codepage, remap);
670 name_len++; /* trailing null */
672 } else { /* BB improve check for buffer overruns BB */
673 name_len = strnlen(name, PATH_MAX);
674 name_len++; /* trailing null */
675 strncpy(pSMB->DirName, name, name_len);
678 pSMB->BufferFormat = 0x04;
679 pSMB->hdr.smb_buf_length += name_len + 1;
680 pSMB->ByteCount = cpu_to_le16(name_len + 1);
681 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
682 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
684 cFYI(1, ("Error in Mkdir = %d", rc));
686 #ifdef CONFIG_CIFS_STATS
688 atomic_inc(&tcon->num_mkdirs);
691 cifs_buf_release(pSMB);
698 CIFSSMBOpen(const int xid, struct cifsTconInfo *tcon,
699 const char *fileName, const int openDisposition,
700 const int access_flags, const int create_options, __u16 * netfid,
701 int *pOplock, FILE_ALL_INFO * pfile_info,
702 const struct nls_table *nls_codepage, int remap)
705 OPEN_REQ *pSMB = NULL;
706 OPEN_RSP *pSMBr = NULL;
712 rc = smb_init(SMB_COM_NT_CREATE_ANDX, 24, tcon, (void **) &pSMB,
717 pSMB->AndXCommand = 0xFF; /* none */
719 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
720 count = 1; /* account for one byte pad to word boundary */
722 cifsConvertToUCS((__le16 *) (pSMB->fileName + 1),
723 fileName, PATH_MAX, nls_codepage, remap);
724 name_len++; /* trailing null */
726 pSMB->NameLength = cpu_to_le16(name_len);
727 } else { /* BB improve check for buffer overruns BB */
728 count = 0; /* no pad */
729 name_len = strnlen(fileName, PATH_MAX);
730 name_len++; /* trailing null */
731 pSMB->NameLength = cpu_to_le16(name_len);
732 strncpy(pSMB->fileName, fileName, name_len);
734 if (*pOplock & REQ_OPLOCK)
735 pSMB->OpenFlags = cpu_to_le32(REQ_OPLOCK);
736 else if (*pOplock & REQ_BATCHOPLOCK) {
737 pSMB->OpenFlags = cpu_to_le32(REQ_BATCHOPLOCK);
739 pSMB->DesiredAccess = cpu_to_le32(access_flags);
740 pSMB->AllocationSize = 0;
741 pSMB->FileAttributes = cpu_to_le32(ATTR_NORMAL);
742 /* XP does not handle ATTR_POSIX_SEMANTICS */
743 /* but it helps speed up case sensitive checks for other
744 servers such as Samba */
745 if (tcon->ses->capabilities & CAP_UNIX)
746 pSMB->FileAttributes |= cpu_to_le32(ATTR_POSIX_SEMANTICS);
748 /* if ((omode & S_IWUGO) == 0)
749 pSMB->FileAttributes |= cpu_to_le32(ATTR_READONLY);*/
750 /* Above line causes problems due to vfs splitting create into two
751 pieces - need to set mode after file created not while it is
753 pSMB->ShareAccess = cpu_to_le32(FILE_SHARE_ALL);
754 pSMB->CreateDisposition = cpu_to_le32(openDisposition);
755 pSMB->CreateOptions = cpu_to_le32(create_options);
756 /* BB Expirement with various impersonation levels and verify */
757 pSMB->ImpersonationLevel = cpu_to_le32(SECURITY_IMPERSONATION);
758 pSMB->SecurityFlags =
759 SECURITY_CONTEXT_TRACKING | SECURITY_EFFECTIVE_ONLY;
762 pSMB->hdr.smb_buf_length += count;
764 pSMB->ByteCount = cpu_to_le16(count);
765 /* long_op set to 1 to allow for oplock break timeouts */
766 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
767 (struct smb_hdr *) pSMBr, &bytes_returned, 1);
769 cFYI(1, ("Error in Open = %d", rc));
771 *pOplock = pSMBr->OplockLevel; /* 1 byte no need to le_to_cpu */
772 *netfid = pSMBr->Fid; /* cifs fid stays in le */
773 /* Let caller know file was created so we can set the mode. */
774 /* Do we care about the CreateAction in any other cases? */
775 if(cpu_to_le32(FILE_CREATE) == pSMBr->CreateAction)
776 *pOplock |= CIFS_CREATE_ACTION;
778 memcpy((char *)pfile_info,(char *)&pSMBr->CreationTime,
779 36 /* CreationTime to Attributes */);
780 /* the file_info buf is endian converted by caller */
781 pfile_info->AllocationSize = pSMBr->AllocationSize;
782 pfile_info->EndOfFile = pSMBr->EndOfFile;
783 pfile_info->NumberOfLinks = cpu_to_le32(1);
786 #ifdef CONFIG_CIFS_STATS
787 atomic_inc(&tcon->num_opens);
790 cifs_buf_release(pSMB);
796 /* If no buffer passed in, then caller wants to do the copy
797 as in the case of readpages so the SMB buffer must be
798 freed by the caller */
801 CIFSSMBRead(const int xid, struct cifsTconInfo *tcon,
802 const int netfid, const unsigned int count,
803 const __u64 lseek, unsigned int *nbytes, char **buf)
806 READ_REQ *pSMB = NULL;
807 READ_RSP *pSMBr = NULL;
808 char *pReadData = NULL;
811 cFYI(1,("Reading %d bytes on fid %d",count,netfid));
814 rc = smb_init(SMB_COM_READ_ANDX, 12, tcon, (void **) &pSMB,
819 /* tcon and ses pointer are checked in smb_init */
820 if (tcon->ses->server == NULL)
821 return -ECONNABORTED;
823 pSMB->AndXCommand = 0xFF; /* none */
825 pSMB->OffsetLow = cpu_to_le32(lseek & 0xFFFFFFFF);
826 pSMB->OffsetHigh = cpu_to_le32(lseek >> 32);
828 pSMB->MaxCount = cpu_to_le16(count & 0xFFFF);
829 pSMB->MaxCountHigh = cpu_to_le32(count >> 16);
830 pSMB->ByteCount = 0; /* no need to do le conversion since it is 0 */
832 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
833 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
835 cERROR(1, ("Send error in read = %d", rc));
837 int data_length = le16_to_cpu(pSMBr->DataLengthHigh);
838 data_length = data_length << 16;
839 data_length += le16_to_cpu(pSMBr->DataLength);
840 *nbytes = data_length;
842 /*check that DataLength would not go beyond end of SMB */
843 if ((data_length > CIFSMaxBufSize)
844 || (data_length > count)) {
845 cFYI(1,("bad length %d for count %d",data_length,count));
850 (char *) (&pSMBr->hdr.Protocol) +
851 le16_to_cpu(pSMBr->DataOffset);
852 /* if(rc = copy_to_user(buf, pReadData, data_length)) {
853 cERROR(1,("Faulting on read rc = %d",rc));
855 }*/ /* can not use copy_to_user when using page cache*/
857 memcpy(*buf,pReadData,data_length);
861 cifs_buf_release(pSMB);
865 /* Note: On -EAGAIN error only caller can retry on handle based calls
866 since file handle passed in no longer valid */
871 CIFSSMBWrite(const int xid, struct cifsTconInfo *tcon,
872 const int netfid, const unsigned int count,
873 const __u64 offset, unsigned int *nbytes, const char *buf,
874 const char __user * ubuf, const int long_op)
877 WRITE_REQ *pSMB = NULL;
878 WRITE_RSP *pSMBr = NULL;
883 /* cFYI(1,("write at %lld %d bytes",offset,count));*/
884 rc = smb_init(SMB_COM_WRITE_ANDX, 14, tcon, (void **) &pSMB,
888 /* tcon and ses pointer are checked in smb_init */
889 if (tcon->ses->server == NULL)
890 return -ECONNABORTED;
892 pSMB->AndXCommand = 0xFF; /* none */
894 pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF);
895 pSMB->OffsetHigh = cpu_to_le32(offset >> 32);
896 pSMB->Reserved = 0xFFFFFFFF;
900 /* Can increase buffer size if buffer is big enough in some cases - ie we
901 can send more if LARGE_WRITE_X capability returned by the server and if
902 our buffer is big enough or if we convert to iovecs on socket writes
903 and eliminate the copy to the CIFS buffer */
904 if(tcon->ses->capabilities & CAP_LARGE_WRITE_X) {
905 bytes_sent = min_t(const unsigned int, CIFSMaxBufSize, count);
907 bytes_sent = (tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE)
911 if (bytes_sent > count)
914 cpu_to_le16(offsetof(struct smb_com_write_req,Data) - 4);
916 memcpy(pSMB->Data,buf,bytes_sent);
918 if(copy_from_user(pSMB->Data,ubuf,bytes_sent)) {
919 cifs_buf_release(pSMB);
924 cifs_buf_release(pSMB);
928 byte_count = bytes_sent + 1 /* pad */ ; /* BB fix this for sends > 64K */
929 pSMB->DataLengthLow = cpu_to_le16(bytes_sent & 0xFFFF);
930 pSMB->DataLengthHigh = cpu_to_le16(bytes_sent >> 16);
931 pSMB->hdr.smb_buf_length += bytes_sent+1;
932 pSMB->ByteCount = cpu_to_le16(byte_count);
934 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
935 (struct smb_hdr *) pSMBr, &bytes_returned, long_op);
937 cFYI(1, ("Send error in write = %d", rc));
940 *nbytes = le16_to_cpu(pSMBr->CountHigh);
941 *nbytes = (*nbytes) << 16;
942 *nbytes += le16_to_cpu(pSMBr->Count);
945 cifs_buf_release(pSMB);
947 /* Note: On -EAGAIN error only caller can retry on handle based calls
948 since file handle passed in no longer valid */
953 #ifdef CONFIG_CIFS_EXPERIMENTAL
954 int CIFSSMBWrite2(const int xid, struct cifsTconInfo *tcon,
955 const int netfid, const unsigned int count,
956 const __u64 offset, unsigned int *nbytes, const char __user *buf,
960 WRITE_REQ *pSMB = NULL;
961 WRITE_RSP *pSMBr = NULL;
962 /*int bytes_returned;*/
966 rc = small_smb_init(SMB_COM_WRITE_ANDX, 14, tcon, (void **) &pSMB);
971 pSMBr = (WRITE_RSP *)pSMB; /* BB removeme BB */
973 /* tcon and ses pointer are checked in smb_init */
974 if (tcon->ses->server == NULL)
975 return -ECONNABORTED;
977 pSMB->AndXCommand = 0xFF; /* none */
979 pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF);
980 pSMB->OffsetHigh = cpu_to_le32(offset >> 32);
981 pSMB->Reserved = 0xFFFFFFFF;
984 bytes_sent = (tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE) & ~0xFF;
985 if (bytes_sent > count)
987 pSMB->DataLengthHigh = 0;
989 cpu_to_le16(offsetof(struct smb_com_write_req,Data) - 4);
991 byte_count = bytes_sent + 1 /* pad */ ;
992 pSMB->DataLengthLow = cpu_to_le16(bytes_sent);
993 pSMB->DataLengthHigh = 0;
994 pSMB->hdr.smb_buf_length += byte_count;
995 pSMB->ByteCount = cpu_to_le16(byte_count);
997 /* rc = SendReceive2(xid, tcon->ses, (struct smb_hdr *) pSMB,
998 (struct smb_hdr *) pSMBr, buf, buflen, &bytes_returned, long_op); */ /* BB fixme BB */
1000 cFYI(1, ("Send error in write2 (large write) = %d", rc));
1003 *nbytes = le16_to_cpu(pSMBr->Count);
1005 cifs_small_buf_release(pSMB);
1007 /* Note: On -EAGAIN error only caller can retry on handle based calls
1008 since file handle passed in no longer valid */
1012 #endif /* CIFS_EXPERIMENTAL */
1015 CIFSSMBLock(const int xid, struct cifsTconInfo *tcon,
1016 const __u16 smb_file_id, const __u64 len,
1017 const __u64 offset, const __u32 numUnlock,
1018 const __u32 numLock, const __u8 lockType, const int waitFlag)
1021 LOCK_REQ *pSMB = NULL;
1022 LOCK_RSP *pSMBr = NULL;
1027 cFYI(1, ("In CIFSSMBLock - timeout %d numLock %d",waitFlag,numLock));
1028 rc = small_smb_init(SMB_COM_LOCKING_ANDX, 8, tcon, (void **) &pSMB);
1033 pSMBr = (LOCK_RSP *)pSMB; /* BB removeme BB */
1035 if(lockType == LOCKING_ANDX_OPLOCK_RELEASE) {
1036 timeout = -1; /* no response expected */
1038 } else if (waitFlag == TRUE) {
1039 timeout = 3; /* blocking operation, no timeout */
1040 pSMB->Timeout = cpu_to_le32(-1);/* blocking - do not time out */
1045 pSMB->NumberOfLocks = cpu_to_le16(numLock);
1046 pSMB->NumberOfUnlocks = cpu_to_le16(numUnlock);
1047 pSMB->LockType = lockType;
1048 pSMB->AndXCommand = 0xFF; /* none */
1049 pSMB->Fid = smb_file_id; /* netfid stays le */
1051 if((numLock != 0) || (numUnlock != 0)) {
1052 pSMB->Locks[0].Pid = cpu_to_le16(current->tgid);
1053 /* BB where to store pid high? */
1054 pSMB->Locks[0].LengthLow = cpu_to_le32((u32)len);
1055 pSMB->Locks[0].LengthHigh = cpu_to_le32((u32)(len>>32));
1056 pSMB->Locks[0].OffsetLow = cpu_to_le32((u32)offset);
1057 pSMB->Locks[0].OffsetHigh = cpu_to_le32((u32)(offset>>32));
1058 count = sizeof(LOCKING_ANDX_RANGE);
1063 pSMB->hdr.smb_buf_length += count;
1064 pSMB->ByteCount = cpu_to_le16(count);
1066 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1067 (struct smb_hdr *) pSMBr, &bytes_returned, timeout);
1070 cFYI(1, ("Send error in Lock = %d", rc));
1072 cifs_small_buf_release(pSMB);
1074 /* Note: On -EAGAIN error only caller can retry on handle based calls
1075 since file handle passed in no longer valid */
1080 CIFSSMBClose(const int xid, struct cifsTconInfo *tcon, int smb_file_id)
1083 CLOSE_REQ *pSMB = NULL;
1084 CLOSE_RSP *pSMBr = NULL;
1086 cFYI(1, ("In CIFSSMBClose"));
1088 /* do not retry on dead session on close */
1089 rc = small_smb_init(SMB_COM_CLOSE, 3, tcon, (void **) &pSMB);
1095 pSMBr = (CLOSE_RSP *)pSMB; /* BB removeme BB */
1097 pSMB->FileID = (__u16) smb_file_id;
1098 pSMB->LastWriteTime = 0;
1099 pSMB->ByteCount = 0;
1100 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1101 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1104 /* EINTR is expected when user ctl-c to kill app */
1105 cERROR(1, ("Send error in Close = %d", rc));
1109 cifs_small_buf_release(pSMB);
1111 /* Since session is dead, file will be closed on server already */
1119 CIFSSMBRename(const int xid, struct cifsTconInfo *tcon,
1120 const char *fromName, const char *toName,
1121 const struct nls_table *nls_codepage, int remap)
1124 RENAME_REQ *pSMB = NULL;
1125 RENAME_RSP *pSMBr = NULL;
1127 int name_len, name_len2;
1130 cFYI(1, ("In CIFSSMBRename"));
1132 rc = smb_init(SMB_COM_RENAME, 1, tcon, (void **) &pSMB,
1137 pSMB->BufferFormat = 0x04;
1138 pSMB->SearchAttributes =
1139 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
1142 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1144 cifsConvertToUCS((__le16 *) pSMB->OldFileName, fromName,
1145 PATH_MAX, nls_codepage, remap);
1146 name_len++; /* trailing null */
1148 pSMB->OldFileName[name_len] = 0x04; /* pad */
1149 /* protocol requires ASCII signature byte on Unicode string */
1150 pSMB->OldFileName[name_len + 1] = 0x00;
1152 cifsConvertToUCS((__le16 *) &pSMB->OldFileName[name_len + 2],
1153 toName, PATH_MAX, nls_codepage, remap);
1154 name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
1155 name_len2 *= 2; /* convert to bytes */
1156 } else { /* BB improve the check for buffer overruns BB */
1157 name_len = strnlen(fromName, PATH_MAX);
1158 name_len++; /* trailing null */
1159 strncpy(pSMB->OldFileName, fromName, name_len);
1160 name_len2 = strnlen(toName, PATH_MAX);
1161 name_len2++; /* trailing null */
1162 pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */
1163 strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2);
1164 name_len2++; /* trailing null */
1165 name_len2++; /* signature byte */
1168 count = 1 /* 1st signature byte */ + name_len + name_len2;
1169 pSMB->hdr.smb_buf_length += count;
1170 pSMB->ByteCount = cpu_to_le16(count);
1172 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1173 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1175 cFYI(1, ("Send error in rename = %d", rc));
1178 #ifdef CONFIG_CIFS_STATS
1180 atomic_inc(&tcon->num_renames);
1184 cifs_buf_release(pSMB);
1192 int CIFSSMBRenameOpenFile(const int xid,struct cifsTconInfo *pTcon,
1193 int netfid, char * target_name,
1194 const struct nls_table * nls_codepage, int remap)
1196 struct smb_com_transaction2_sfi_req *pSMB = NULL;
1197 struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
1198 struct set_file_rename * rename_info;
1200 char dummy_string[30];
1202 int bytes_returned = 0;
1204 __u16 params, param_offset, offset, count, byte_count;
1206 cFYI(1, ("Rename to File by handle"));
1207 rc = smb_init(SMB_COM_TRANSACTION2, 15, pTcon, (void **) &pSMB,
1213 pSMB->MaxSetupCount = 0;
1217 pSMB->Reserved2 = 0;
1218 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
1219 offset = param_offset + params;
1221 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
1222 rename_info = (struct set_file_rename *) data_offset;
1223 pSMB->MaxParameterCount = cpu_to_le16(2);
1224 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB PDU from sess */
1225 pSMB->SetupCount = 1;
1226 pSMB->Reserved3 = 0;
1227 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
1228 byte_count = 3 /* pad */ + params;
1229 pSMB->ParameterCount = cpu_to_le16(params);
1230 pSMB->TotalParameterCount = pSMB->ParameterCount;
1231 pSMB->ParameterOffset = cpu_to_le16(param_offset);
1232 pSMB->DataOffset = cpu_to_le16(offset);
1233 /* construct random name ".cifs_tmp<inodenum><mid>" */
1234 rename_info->overwrite = cpu_to_le32(1);
1235 rename_info->root_fid = 0;
1236 /* unicode only call */
1237 if(target_name == NULL) {
1238 sprintf(dummy_string,"cifs%x",pSMB->hdr.Mid);
1239 len_of_str = cifsConvertToUCS((__le16 *)rename_info->target_name,
1240 dummy_string, 24, nls_codepage, remap);
1242 len_of_str = cifsConvertToUCS((__le16 *)rename_info->target_name,
1243 target_name, PATH_MAX, nls_codepage, remap);
1245 rename_info->target_name_len = cpu_to_le32(2 * len_of_str);
1246 count = 12 /* sizeof(struct set_file_rename) */ + (2 * len_of_str) + 2;
1247 byte_count += count;
1248 pSMB->DataCount = cpu_to_le16(count);
1249 pSMB->TotalDataCount = pSMB->DataCount;
1251 pSMB->InformationLevel =
1252 cpu_to_le16(SMB_SET_FILE_RENAME_INFORMATION);
1253 pSMB->Reserved4 = 0;
1254 pSMB->hdr.smb_buf_length += byte_count;
1255 pSMB->ByteCount = cpu_to_le16(byte_count);
1256 rc = SendReceive(xid, pTcon->ses, (struct smb_hdr *) pSMB,
1257 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1259 cFYI(1,("Send error in Rename (by file handle) = %d", rc));
1261 #ifdef CONFIG_CIFS_STATS
1263 atomic_inc(&pTcon->num_t2renames);
1266 cifs_buf_release(pSMB);
1268 /* Note: On -EAGAIN error only caller can retry on handle based calls
1269 since file handle passed in no longer valid */
1275 CIFSSMBCopy(const int xid, struct cifsTconInfo *tcon, const char * fromName,
1276 const __u16 target_tid, const char *toName, const int flags,
1277 const struct nls_table *nls_codepage, int remap)
1280 COPY_REQ *pSMB = NULL;
1281 COPY_RSP *pSMBr = NULL;
1283 int name_len, name_len2;
1286 cFYI(1, ("In CIFSSMBCopy"));
1288 rc = smb_init(SMB_COM_COPY, 1, tcon, (void **) &pSMB,
1293 pSMB->BufferFormat = 0x04;
1294 pSMB->Tid2 = target_tid;
1296 pSMB->Flags = cpu_to_le16(flags & COPY_TREE);
1298 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1299 name_len = cifsConvertToUCS((__le16 *) pSMB->OldFileName,
1300 fromName, PATH_MAX, nls_codepage,
1302 name_len++; /* trailing null */
1304 pSMB->OldFileName[name_len] = 0x04; /* pad */
1305 /* protocol requires ASCII signature byte on Unicode string */
1306 pSMB->OldFileName[name_len + 1] = 0x00;
1307 name_len2 = cifsConvertToUCS((__le16 *)&pSMB->OldFileName[name_len + 2],
1308 toName, PATH_MAX, nls_codepage, remap);
1309 name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
1310 name_len2 *= 2; /* convert to bytes */
1311 } else { /* BB improve the check for buffer overruns BB */
1312 name_len = strnlen(fromName, PATH_MAX);
1313 name_len++; /* trailing null */
1314 strncpy(pSMB->OldFileName, fromName, name_len);
1315 name_len2 = strnlen(toName, PATH_MAX);
1316 name_len2++; /* trailing null */
1317 pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */
1318 strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2);
1319 name_len2++; /* trailing null */
1320 name_len2++; /* signature byte */
1323 count = 1 /* 1st signature byte */ + name_len + name_len2;
1324 pSMB->hdr.smb_buf_length += count;
1325 pSMB->ByteCount = cpu_to_le16(count);
1327 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1328 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1330 cFYI(1, ("Send error in copy = %d with %d files copied",
1331 rc, le16_to_cpu(pSMBr->CopyCount)));
1334 cifs_buf_release(pSMB);
1343 CIFSUnixCreateSymLink(const int xid, struct cifsTconInfo *tcon,
1344 const char *fromName, const char *toName,
1345 const struct nls_table *nls_codepage)
1347 TRANSACTION2_SPI_REQ *pSMB = NULL;
1348 TRANSACTION2_SPI_RSP *pSMBr = NULL;
1351 int name_len_target;
1353 int bytes_returned = 0;
1354 __u16 params, param_offset, offset, byte_count;
1356 cFYI(1, ("In Symlink Unix style"));
1358 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
1363 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1365 cifs_strtoUCS((wchar_t *) pSMB->FileName, fromName, PATH_MAX
1366 /* find define for this maxpathcomponent */
1368 name_len++; /* trailing null */
1371 } else { /* BB improve the check for buffer overruns BB */
1372 name_len = strnlen(fromName, PATH_MAX);
1373 name_len++; /* trailing null */
1374 strncpy(pSMB->FileName, fromName, name_len);
1376 params = 6 + name_len;
1377 pSMB->MaxSetupCount = 0;
1381 pSMB->Reserved2 = 0;
1382 param_offset = offsetof(struct smb_com_transaction2_spi_req,
1383 InformationLevel) - 4;
1384 offset = param_offset + params;
1386 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
1387 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1389 cifs_strtoUCS((wchar_t *) data_offset, toName, PATH_MAX
1390 /* find define for this maxpathcomponent */
1392 name_len_target++; /* trailing null */
1393 name_len_target *= 2;
1394 } else { /* BB improve the check for buffer overruns BB */
1395 name_len_target = strnlen(toName, PATH_MAX);
1396 name_len_target++; /* trailing null */
1397 strncpy(data_offset, toName, name_len_target);
1400 pSMB->MaxParameterCount = cpu_to_le16(2);
1401 /* BB find exact max on data count below from sess */
1402 pSMB->MaxDataCount = cpu_to_le16(1000);
1403 pSMB->SetupCount = 1;
1404 pSMB->Reserved3 = 0;
1405 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
1406 byte_count = 3 /* pad */ + params + name_len_target;
1407 pSMB->DataCount = cpu_to_le16(name_len_target);
1408 pSMB->ParameterCount = cpu_to_le16(params);
1409 pSMB->TotalDataCount = pSMB->DataCount;
1410 pSMB->TotalParameterCount = pSMB->ParameterCount;
1411 pSMB->ParameterOffset = cpu_to_le16(param_offset);
1412 pSMB->DataOffset = cpu_to_le16(offset);
1413 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_LINK);
1414 pSMB->Reserved4 = 0;
1415 pSMB->hdr.smb_buf_length += byte_count;
1416 pSMB->ByteCount = cpu_to_le16(byte_count);
1417 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1418 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1421 ("Send error in SetPathInfo (create symlink) = %d",
1426 cifs_buf_release(pSMB);
1429 goto createSymLinkRetry;
1435 CIFSUnixCreateHardLink(const int xid, struct cifsTconInfo *tcon,
1436 const char *fromName, const char *toName,
1437 const struct nls_table *nls_codepage, int remap)
1439 TRANSACTION2_SPI_REQ *pSMB = NULL;
1440 TRANSACTION2_SPI_RSP *pSMBr = NULL;
1443 int name_len_target;
1445 int bytes_returned = 0;
1446 __u16 params, param_offset, offset, byte_count;
1448 cFYI(1, ("In Create Hard link Unix style"));
1449 createHardLinkRetry:
1450 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
1455 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1456 name_len = cifsConvertToUCS((__le16 *) pSMB->FileName, toName,
1457 PATH_MAX, nls_codepage, remap);
1458 name_len++; /* trailing null */
1461 } else { /* BB improve the check for buffer overruns BB */
1462 name_len = strnlen(toName, PATH_MAX);
1463 name_len++; /* trailing null */
1464 strncpy(pSMB->FileName, toName, name_len);
1466 params = 6 + name_len;
1467 pSMB->MaxSetupCount = 0;
1471 pSMB->Reserved2 = 0;
1472 param_offset = offsetof(struct smb_com_transaction2_spi_req,
1473 InformationLevel) - 4;
1474 offset = param_offset + params;
1476 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
1477 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1479 cifsConvertToUCS((__le16 *) data_offset, fromName, PATH_MAX,
1480 nls_codepage, remap);
1481 name_len_target++; /* trailing null */
1482 name_len_target *= 2;
1483 } else { /* BB improve the check for buffer overruns BB */
1484 name_len_target = strnlen(fromName, PATH_MAX);
1485 name_len_target++; /* trailing null */
1486 strncpy(data_offset, fromName, name_len_target);
1489 pSMB->MaxParameterCount = cpu_to_le16(2);
1490 /* BB find exact max on data count below from sess*/
1491 pSMB->MaxDataCount = cpu_to_le16(1000);
1492 pSMB->SetupCount = 1;
1493 pSMB->Reserved3 = 0;
1494 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
1495 byte_count = 3 /* pad */ + params + name_len_target;
1496 pSMB->ParameterCount = cpu_to_le16(params);
1497 pSMB->TotalParameterCount = pSMB->ParameterCount;
1498 pSMB->DataCount = cpu_to_le16(name_len_target);
1499 pSMB->TotalDataCount = pSMB->DataCount;
1500 pSMB->ParameterOffset = cpu_to_le16(param_offset);
1501 pSMB->DataOffset = cpu_to_le16(offset);
1502 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_HLINK);
1503 pSMB->Reserved4 = 0;
1504 pSMB->hdr.smb_buf_length += byte_count;
1505 pSMB->ByteCount = cpu_to_le16(byte_count);
1506 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1507 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1509 cFYI(1, ("Send error in SetPathInfo (hard link) = %d", rc));
1512 cifs_buf_release(pSMB);
1514 goto createHardLinkRetry;
1520 CIFSCreateHardLink(const int xid, struct cifsTconInfo *tcon,
1521 const char *fromName, const char *toName,
1522 const struct nls_table *nls_codepage, int remap)
1525 NT_RENAME_REQ *pSMB = NULL;
1526 RENAME_RSP *pSMBr = NULL;
1528 int name_len, name_len2;
1531 cFYI(1, ("In CIFSCreateHardLink"));
1532 winCreateHardLinkRetry:
1534 rc = smb_init(SMB_COM_NT_RENAME, 4, tcon, (void **) &pSMB,
1539 pSMB->SearchAttributes =
1540 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
1542 pSMB->Flags = cpu_to_le16(CREATE_HARD_LINK);
1543 pSMB->ClusterCount = 0;
1545 pSMB->BufferFormat = 0x04;
1547 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1549 cifsConvertToUCS((__le16 *) pSMB->OldFileName, fromName,
1550 PATH_MAX, nls_codepage, remap);
1551 name_len++; /* trailing null */
1553 pSMB->OldFileName[name_len] = 0; /* pad */
1554 pSMB->OldFileName[name_len + 1] = 0x04;
1556 cifsConvertToUCS((__le16 *)&pSMB->OldFileName[name_len + 2],
1557 toName, PATH_MAX, nls_codepage, remap);
1558 name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
1559 name_len2 *= 2; /* convert to bytes */
1560 } else { /* BB improve the check for buffer overruns BB */
1561 name_len = strnlen(fromName, PATH_MAX);
1562 name_len++; /* trailing null */
1563 strncpy(pSMB->OldFileName, fromName, name_len);
1564 name_len2 = strnlen(toName, PATH_MAX);
1565 name_len2++; /* trailing null */
1566 pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */
1567 strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2);
1568 name_len2++; /* trailing null */
1569 name_len2++; /* signature byte */
1572 count = 1 /* string type byte */ + name_len + name_len2;
1573 pSMB->hdr.smb_buf_length += count;
1574 pSMB->ByteCount = cpu_to_le16(count);
1576 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1577 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1579 cFYI(1, ("Send error in hard link (NT rename) = %d", rc));
1581 cifs_buf_release(pSMB);
1583 goto winCreateHardLinkRetry;
1589 CIFSSMBUnixQuerySymLink(const int xid, struct cifsTconInfo *tcon,
1590 const unsigned char *searchName,
1591 char *symlinkinfo, const int buflen,
1592 const struct nls_table *nls_codepage)
1594 /* SMB_QUERY_FILE_UNIX_LINK */
1595 TRANSACTION2_QPI_REQ *pSMB = NULL;
1596 TRANSACTION2_QPI_RSP *pSMBr = NULL;
1600 __u16 params, byte_count;
1602 cFYI(1, ("In QPathSymLinkInfo (Unix) for path %s", searchName));
1605 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
1610 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1612 cifs_strtoUCS((wchar_t *) pSMB->FileName, searchName, PATH_MAX
1613 /* find define for this maxpathcomponent */
1615 name_len++; /* trailing null */
1617 } else { /* BB improve the check for buffer overruns BB */
1618 name_len = strnlen(searchName, PATH_MAX);
1619 name_len++; /* trailing null */
1620 strncpy(pSMB->FileName, searchName, name_len);
1623 params = 2 /* level */ + 4 /* rsrvd */ + name_len /* incl null */ ;
1624 pSMB->TotalDataCount = 0;
1625 pSMB->MaxParameterCount = cpu_to_le16(2);
1626 /* BB find exact max data count below from sess structure BB */
1627 pSMB->MaxDataCount = cpu_to_le16(4000);
1628 pSMB->MaxSetupCount = 0;
1632 pSMB->Reserved2 = 0;
1633 pSMB->ParameterOffset = cpu_to_le16(offsetof(
1634 struct smb_com_transaction2_qpi_req ,InformationLevel) - 4);
1635 pSMB->DataCount = 0;
1636 pSMB->DataOffset = 0;
1637 pSMB->SetupCount = 1;
1638 pSMB->Reserved3 = 0;
1639 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
1640 byte_count = params + 1 /* pad */ ;
1641 pSMB->TotalParameterCount = cpu_to_le16(params);
1642 pSMB->ParameterCount = pSMB->TotalParameterCount;
1643 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_LINK);
1644 pSMB->Reserved4 = 0;
1645 pSMB->hdr.smb_buf_length += byte_count;
1646 pSMB->ByteCount = cpu_to_le16(byte_count);
1648 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1649 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1651 cFYI(1, ("Send error in QuerySymLinkInfo = %d", rc));
1653 /* decode response */
1655 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
1656 if (rc || (pSMBr->ByteCount < 2))
1657 /* BB also check enough total bytes returned */
1658 rc = -EIO; /* bad smb */
1660 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
1661 __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
1663 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
1664 name_len = UniStrnlen((wchar_t *) ((char *)
1665 &pSMBr->hdr.Protocol +data_offset),
1666 min_t(const int, buflen,count) / 2);
1667 /* BB FIXME investigate remapping reserved chars here */
1668 cifs_strfromUCS_le(symlinkinfo,
1669 (wchar_t *) ((char *)&pSMBr->hdr.Protocol +
1671 name_len, nls_codepage);
1673 strncpy(symlinkinfo,
1674 (char *) &pSMBr->hdr.Protocol +
1676 min_t(const int, buflen, count));
1678 symlinkinfo[buflen] = 0;
1679 /* just in case so calling code does not go off the end of buffer */
1682 cifs_buf_release(pSMB);
1684 goto querySymLinkRetry;
1689 CIFSSMBQueryReparseLinkInfo(const int xid, struct cifsTconInfo *tcon,
1690 const unsigned char *searchName,
1691 char *symlinkinfo, const int buflen,__u16 fid,
1692 const struct nls_table *nls_codepage)
1697 struct smb_com_transaction_ioctl_req * pSMB;
1698 struct smb_com_transaction_ioctl_rsp * pSMBr;
1700 cFYI(1, ("In Windows reparse style QueryLink for path %s", searchName));
1701 rc = smb_init(SMB_COM_NT_TRANSACT, 23, tcon, (void **) &pSMB,
1706 pSMB->TotalParameterCount = 0 ;
1707 pSMB->TotalDataCount = 0;
1708 pSMB->MaxParameterCount = cpu_to_le32(2);
1709 /* BB find exact data count max from sess structure BB */
1710 pSMB->MaxDataCount = cpu_to_le32(4000);
1711 pSMB->MaxSetupCount = 4;
1713 pSMB->ParameterOffset = 0;
1714 pSMB->DataCount = 0;
1715 pSMB->DataOffset = 0;
1716 pSMB->SetupCount = 4;
1717 pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_IOCTL);
1718 pSMB->ParameterCount = pSMB->TotalParameterCount;
1719 pSMB->FunctionCode = cpu_to_le32(FSCTL_GET_REPARSE_POINT);
1720 pSMB->IsFsctl = 1; /* FSCTL */
1721 pSMB->IsRootFlag = 0;
1722 pSMB->Fid = fid; /* file handle always le */
1723 pSMB->ByteCount = 0;
1725 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1726 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1728 cFYI(1, ("Send error in QueryReparseLinkInfo = %d", rc));
1729 } else { /* decode response */
1730 __u32 data_offset = le32_to_cpu(pSMBr->DataOffset);
1731 __u32 data_count = le32_to_cpu(pSMBr->DataCount);
1732 if ((pSMBr->ByteCount < 2) || (data_offset > 512))
1733 /* BB also check enough total bytes returned */
1734 rc = -EIO; /* bad smb */
1736 if(data_count && (data_count < 2048)) {
1737 char * end_of_smb = pSMBr->ByteCount + (char *)&pSMBr->ByteCount;
1739 struct reparse_data * reparse_buf = (struct reparse_data *)
1740 ((char *)&pSMBr->hdr.Protocol + data_offset);
1741 if((char*)reparse_buf >= end_of_smb) {
1745 if((reparse_buf->LinkNamesBuf +
1746 reparse_buf->TargetNameOffset +
1747 reparse_buf->TargetNameLen) >
1749 cFYI(1,("reparse buf extended beyond SMB"));
1754 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
1755 name_len = UniStrnlen((wchar_t *)
1756 (reparse_buf->LinkNamesBuf +
1757 reparse_buf->TargetNameOffset),
1758 min(buflen/2, reparse_buf->TargetNameLen / 2));
1759 cifs_strfromUCS_le(symlinkinfo,
1760 (wchar_t *) (reparse_buf->LinkNamesBuf +
1761 reparse_buf->TargetNameOffset),
1762 name_len, nls_codepage);
1763 } else { /* ASCII names */
1764 strncpy(symlinkinfo,reparse_buf->LinkNamesBuf +
1765 reparse_buf->TargetNameOffset,
1766 min_t(const int, buflen, reparse_buf->TargetNameLen));
1770 cFYI(1,("Invalid return data count on get reparse info ioctl"));
1772 symlinkinfo[buflen] = 0; /* just in case so the caller
1773 does not go off the end of the buffer */
1774 cFYI(1,("readlink result - %s ",symlinkinfo));
1779 cifs_buf_release(pSMB);
1781 /* Note: On -EAGAIN error only caller can retry on handle based calls
1782 since file handle passed in no longer valid */
1787 #ifdef CONFIG_CIFS_POSIX
1789 /*Convert an Access Control Entry from wire format to local POSIX xattr format*/
1790 static void cifs_convert_ace(posix_acl_xattr_entry * ace, struct cifs_posix_ace * cifs_ace)
1792 /* u8 cifs fields do not need le conversion */
1793 ace->e_perm = (__u16)cifs_ace->cifs_e_perm;
1794 ace->e_tag = (__u16)cifs_ace->cifs_e_tag;
1795 ace->e_id = (__u32)le64_to_cpu(cifs_ace->cifs_uid);
1796 /* cFYI(1,("perm %d tag %d id %d",ace->e_perm,ace->e_tag,ace->e_id)); */
1801 /* Convert ACL from CIFS POSIX wire format to local Linux POSIX ACL xattr */
1802 static int cifs_copy_posix_acl(char * trgt,char * src, const int buflen,
1803 const int acl_type,const int size_of_data_area)
1808 struct cifs_posix_ace * pACE;
1809 struct cifs_posix_acl * cifs_acl = (struct cifs_posix_acl *)src;
1810 posix_acl_xattr_header * local_acl = (posix_acl_xattr_header *)trgt;
1812 if (le16_to_cpu(cifs_acl->version) != CIFS_ACL_VERSION)
1815 if(acl_type & ACL_TYPE_ACCESS) {
1816 count = le16_to_cpu(cifs_acl->access_entry_count);
1817 pACE = &cifs_acl->ace_array[0];
1818 size = sizeof(struct cifs_posix_acl);
1819 size += sizeof(struct cifs_posix_ace) * count;
1820 /* check if we would go beyond end of SMB */
1821 if(size_of_data_area < size) {
1822 cFYI(1,("bad CIFS POSIX ACL size %d vs. %d",size_of_data_area,size));
1825 } else if(acl_type & ACL_TYPE_DEFAULT) {
1826 count = le16_to_cpu(cifs_acl->access_entry_count);
1827 size = sizeof(struct cifs_posix_acl);
1828 size += sizeof(struct cifs_posix_ace) * count;
1829 /* skip past access ACEs to get to default ACEs */
1830 pACE = &cifs_acl->ace_array[count];
1831 count = le16_to_cpu(cifs_acl->default_entry_count);
1832 size += sizeof(struct cifs_posix_ace) * count;
1833 /* check if we would go beyond end of SMB */
1834 if(size_of_data_area < size)
1841 size = posix_acl_xattr_size(count);
1842 if((buflen == 0) || (local_acl == NULL)) {
1843 /* used to query ACL EA size */
1844 } else if(size > buflen) {
1846 } else /* buffer big enough */ {
1847 local_acl->a_version = POSIX_ACL_XATTR_VERSION;
1848 for(i = 0;i < count ;i++) {
1849 cifs_convert_ace(&local_acl->a_entries[i],pACE);
1856 static __u16 convert_ace_to_cifs_ace(struct cifs_posix_ace * cifs_ace,
1857 const posix_acl_xattr_entry * local_ace)
1859 __u16 rc = 0; /* 0 = ACL converted ok */
1861 cifs_ace->cifs_e_perm = (__u8)cpu_to_le16(local_ace->e_perm);
1862 cifs_ace->cifs_e_tag = (__u8)cpu_to_le16(local_ace->e_tag);
1863 /* BB is there a better way to handle the large uid? */
1864 if(local_ace->e_id == -1) {
1865 /* Probably no need to le convert -1 on any arch but can not hurt */
1866 cifs_ace->cifs_uid = cpu_to_le64(-1);
1868 cifs_ace->cifs_uid = (__u64)cpu_to_le32(local_ace->e_id);
1869 /*cFYI(1,("perm %d tag %d id %d",ace->e_perm,ace->e_tag,ace->e_id));*/
1873 /* Convert ACL from local Linux POSIX xattr to CIFS POSIX ACL wire format */
1874 static __u16 ACL_to_cifs_posix(char * parm_data,const char * pACL,const int buflen,
1878 struct cifs_posix_acl * cifs_acl = (struct cifs_posix_acl *)parm_data;
1879 posix_acl_xattr_header * local_acl = (posix_acl_xattr_header *)pACL;
1883 if((buflen == 0) || (pACL == NULL) || (cifs_acl == NULL))
1886 count = posix_acl_xattr_count((size_t)buflen);
1887 cFYI(1,("setting acl with %d entries from buf of length %d and version of %d",
1888 count,buflen,local_acl->a_version));
1889 if(local_acl->a_version != 2) {
1890 cFYI(1,("unknown POSIX ACL version %d",local_acl->a_version));
1893 cifs_acl->version = cpu_to_le16(1);
1894 if(acl_type == ACL_TYPE_ACCESS)
1895 cifs_acl->access_entry_count = count;
1896 else if(acl_type == ACL_TYPE_DEFAULT)
1897 cifs_acl->default_entry_count = count;
1899 cFYI(1,("unknown ACL type %d",acl_type));
1902 for(i=0;i<count;i++) {
1903 rc = convert_ace_to_cifs_ace(&cifs_acl->ace_array[i],
1904 &local_acl->a_entries[i]);
1906 /* ACE not converted */
1911 rc = (__u16)(count * sizeof(struct cifs_posix_ace));
1912 rc += sizeof(struct cifs_posix_acl);
1913 /* BB add check to make sure ACL does not overflow SMB */
1919 CIFSSMBGetPosixACL(const int xid, struct cifsTconInfo *tcon,
1920 const unsigned char *searchName,
1921 char *acl_inf, const int buflen, const int acl_type,
1922 const struct nls_table *nls_codepage, int remap)
1924 /* SMB_QUERY_POSIX_ACL */
1925 TRANSACTION2_QPI_REQ *pSMB = NULL;
1926 TRANSACTION2_QPI_RSP *pSMBr = NULL;
1930 __u16 params, byte_count;
1932 cFYI(1, ("In GetPosixACL (Unix) for path %s", searchName));
1935 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
1940 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1942 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
1943 PATH_MAX, nls_codepage, remap);
1944 name_len++; /* trailing null */
1946 pSMB->FileName[name_len] = 0;
1947 pSMB->FileName[name_len+1] = 0;
1948 } else { /* BB improve the check for buffer overruns BB */
1949 name_len = strnlen(searchName, PATH_MAX);
1950 name_len++; /* trailing null */
1951 strncpy(pSMB->FileName, searchName, name_len);
1954 params = 2 /* level */ + 4 /* rsrvd */ + name_len /* incl null */ ;
1955 pSMB->TotalDataCount = 0;
1956 pSMB->MaxParameterCount = cpu_to_le16(2);
1957 /* BB find exact max data count below from sess structure BB */
1958 pSMB->MaxDataCount = cpu_to_le16(4000);
1959 pSMB->MaxSetupCount = 0;
1963 pSMB->Reserved2 = 0;
1964 pSMB->ParameterOffset = cpu_to_le16(
1965 offsetof(struct smb_com_transaction2_qpi_req ,InformationLevel) - 4);
1966 pSMB->DataCount = 0;
1967 pSMB->DataOffset = 0;
1968 pSMB->SetupCount = 1;
1969 pSMB->Reserved3 = 0;
1970 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
1971 byte_count = params + 1 /* pad */ ;
1972 pSMB->TotalParameterCount = cpu_to_le16(params);
1973 pSMB->ParameterCount = pSMB->TotalParameterCount;
1974 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_POSIX_ACL);
1975 pSMB->Reserved4 = 0;
1976 pSMB->hdr.smb_buf_length += byte_count;
1977 pSMB->ByteCount = cpu_to_le16(byte_count);
1979 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1980 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1982 cFYI(1, ("Send error in Query POSIX ACL = %d", rc));
1984 /* decode response */
1986 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
1987 if (rc || (pSMBr->ByteCount < 2))
1988 /* BB also check enough total bytes returned */
1989 rc = -EIO; /* bad smb */
1991 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
1992 __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
1993 rc = cifs_copy_posix_acl(acl_inf,
1994 (char *)&pSMBr->hdr.Protocol+data_offset,
1995 buflen,acl_type,count);
1998 cifs_buf_release(pSMB);
2005 CIFSSMBSetPosixACL(const int xid, struct cifsTconInfo *tcon,
2006 const unsigned char *fileName,
2007 const char *local_acl, const int buflen,
2009 const struct nls_table *nls_codepage, int remap)
2011 struct smb_com_transaction2_spi_req *pSMB = NULL;
2012 struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
2016 int bytes_returned = 0;
2017 __u16 params, byte_count, data_count, param_offset, offset;
2019 cFYI(1, ("In SetPosixACL (Unix) for path %s", fileName));
2021 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2025 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2027 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
2028 PATH_MAX, nls_codepage, remap);
2029 name_len++; /* trailing null */
2031 } else { /* BB improve the check for buffer overruns BB */
2032 name_len = strnlen(fileName, PATH_MAX);
2033 name_len++; /* trailing null */
2034 strncpy(pSMB->FileName, fileName, name_len);
2036 params = 6 + name_len;
2037 pSMB->MaxParameterCount = cpu_to_le16(2);
2038 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB size from sess */
2039 pSMB->MaxSetupCount = 0;
2043 pSMB->Reserved2 = 0;
2044 param_offset = offsetof(struct smb_com_transaction2_spi_req,
2045 InformationLevel) - 4;
2046 offset = param_offset + params;
2047 parm_data = ((char *) &pSMB->hdr.Protocol) + offset;
2048 pSMB->ParameterOffset = cpu_to_le16(param_offset);
2050 /* convert to on the wire format for POSIX ACL */
2051 data_count = ACL_to_cifs_posix(parm_data,local_acl,buflen,acl_type);
2053 if(data_count == 0) {
2055 goto setACLerrorExit;
2057 pSMB->DataOffset = cpu_to_le16(offset);
2058 pSMB->SetupCount = 1;
2059 pSMB->Reserved3 = 0;
2060 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
2061 pSMB->InformationLevel = cpu_to_le16(SMB_SET_POSIX_ACL);
2062 byte_count = 3 /* pad */ + params + data_count;
2063 pSMB->DataCount = cpu_to_le16(data_count);
2064 pSMB->TotalDataCount = pSMB->DataCount;
2065 pSMB->ParameterCount = cpu_to_le16(params);
2066 pSMB->TotalParameterCount = pSMB->ParameterCount;
2067 pSMB->Reserved4 = 0;
2068 pSMB->hdr.smb_buf_length += byte_count;
2069 pSMB->ByteCount = cpu_to_le16(byte_count);
2070 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2071 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2073 cFYI(1, ("Set POSIX ACL returned %d", rc));
2077 cifs_buf_release(pSMB);
2083 /* BB fix tabs in this function FIXME BB */
2085 CIFSGetExtAttr(const int xid, struct cifsTconInfo *tcon,
2086 const int netfid, __u64 * pExtAttrBits, __u64 *pMask)
2089 struct smb_t2_qfi_req *pSMB = NULL;
2090 struct smb_t2_qfi_rsp *pSMBr = NULL;
2092 __u16 params, byte_count;
2094 cFYI(1,("In GetExtAttr"));
2099 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2104 params = 2 /* level */ +2 /* fid */;
2105 pSMB->t2.TotalDataCount = 0;
2106 pSMB->t2.MaxParameterCount = cpu_to_le16(4);
2107 /* BB find exact max data count below from sess structure BB */
2108 pSMB->t2.MaxDataCount = cpu_to_le16(4000);
2109 pSMB->t2.MaxSetupCount = 0;
2110 pSMB->t2.Reserved = 0;
2112 pSMB->t2.Timeout = 0;
2113 pSMB->t2.Reserved2 = 0;
2114 pSMB->t2.ParameterOffset = cpu_to_le16(offsetof(struct smb_t2_qfi_req,
2116 pSMB->t2.DataCount = 0;
2117 pSMB->t2.DataOffset = 0;
2118 pSMB->t2.SetupCount = 1;
2119 pSMB->t2.Reserved3 = 0;
2120 pSMB->t2.SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION);
2121 byte_count = params + 1 /* pad */ ;
2122 pSMB->t2.TotalParameterCount = cpu_to_le16(params);
2123 pSMB->t2.ParameterCount = pSMB->t2.TotalParameterCount;
2124 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_ATTR_FLAGS);
2127 pSMB->hdr.smb_buf_length += byte_count;
2128 pSMB->t2.ByteCount = cpu_to_le16(byte_count);
2130 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2131 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2133 cFYI(1, ("error %d in GetExtAttr", rc));
2135 /* decode response */
2136 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
2137 if (rc || (pSMBr->ByteCount < 2))
2138 /* BB also check enough total bytes returned */
2139 /* If rc should we check for EOPNOSUPP and
2140 disable the srvino flag? or in caller? */
2141 rc = -EIO; /* bad smb */
2143 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
2144 __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
2145 struct file_chattr_info * pfinfo;
2146 /* BB Do we need a cast or hash here ? */
2148 cFYI(1, ("Illegal size ret in GetExtAttr"));
2152 pfinfo = (struct file_chattr_info *)
2153 (data_offset + (char *) &pSMBr->hdr.Protocol);
2154 *pExtAttrBits = le64_to_cpu(pfinfo->mode);
2155 *pMask = le64_to_cpu(pfinfo->mask);
2159 cifs_buf_release(pSMB);
2161 goto GetExtAttrRetry;
2166 #endif /* CONFIG_POSIX */
2169 CIFSSMBQPathInfo(const int xid, struct cifsTconInfo *tcon,
2170 const unsigned char *searchName,
2171 FILE_ALL_INFO * pFindData,
2172 const struct nls_table *nls_codepage, int remap)
2174 /* level 263 SMB_QUERY_FILE_ALL_INFO */
2175 TRANSACTION2_QPI_REQ *pSMB = NULL;
2176 TRANSACTION2_QPI_RSP *pSMBr = NULL;
2180 __u16 params, byte_count;
2182 /* cFYI(1, ("In QPathInfo path %s", searchName)); */
2184 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2189 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2191 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
2192 PATH_MAX, nls_codepage, remap);
2193 name_len++; /* trailing null */
2195 } else { /* BB improve the check for buffer overruns BB */
2196 name_len = strnlen(searchName, PATH_MAX);
2197 name_len++; /* trailing null */
2198 strncpy(pSMB->FileName, searchName, name_len);
2201 params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */ ;
2202 pSMB->TotalDataCount = 0;
2203 pSMB->MaxParameterCount = cpu_to_le16(2);
2204 pSMB->MaxDataCount = cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
2205 pSMB->MaxSetupCount = 0;
2209 pSMB->Reserved2 = 0;
2210 pSMB->ParameterOffset = cpu_to_le16(offsetof(
2211 struct smb_com_transaction2_qpi_req ,InformationLevel) - 4);
2212 pSMB->DataCount = 0;
2213 pSMB->DataOffset = 0;
2214 pSMB->SetupCount = 1;
2215 pSMB->Reserved3 = 0;
2216 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
2217 byte_count = params + 1 /* pad */ ;
2218 pSMB->TotalParameterCount = cpu_to_le16(params);
2219 pSMB->ParameterCount = pSMB->TotalParameterCount;
2220 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_ALL_INFO);
2221 pSMB->Reserved4 = 0;
2222 pSMB->hdr.smb_buf_length += byte_count;
2223 pSMB->ByteCount = cpu_to_le16(byte_count);
2225 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2226 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2228 cFYI(1, ("Send error in QPathInfo = %d", rc));
2229 } else { /* decode response */
2230 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
2232 if (rc || (pSMBr->ByteCount < 40))
2233 rc = -EIO; /* bad smb */
2234 else if (pFindData){
2235 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
2236 memcpy((char *) pFindData,
2237 (char *) &pSMBr->hdr.Protocol +
2238 data_offset, sizeof (FILE_ALL_INFO));
2242 cifs_buf_release(pSMB);
2244 goto QPathInfoRetry;
2250 CIFSSMBUnixQPathInfo(const int xid, struct cifsTconInfo *tcon,
2251 const unsigned char *searchName,
2252 FILE_UNIX_BASIC_INFO * pFindData,
2253 const struct nls_table *nls_codepage, int remap)
2255 /* SMB_QUERY_FILE_UNIX_BASIC */
2256 TRANSACTION2_QPI_REQ *pSMB = NULL;
2257 TRANSACTION2_QPI_RSP *pSMBr = NULL;
2259 int bytes_returned = 0;
2261 __u16 params, byte_count;
2263 cFYI(1, ("In QPathInfo (Unix) the path %s", searchName));
2265 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2270 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2272 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
2273 PATH_MAX, nls_codepage, remap);
2274 name_len++; /* trailing null */
2276 } else { /* BB improve the check for buffer overruns BB */
2277 name_len = strnlen(searchName, PATH_MAX);
2278 name_len++; /* trailing null */
2279 strncpy(pSMB->FileName, searchName, name_len);
2282 params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */ ;
2283 pSMB->TotalDataCount = 0;
2284 pSMB->MaxParameterCount = cpu_to_le16(2);
2285 /* BB find exact max SMB PDU from sess structure BB */
2286 pSMB->MaxDataCount = cpu_to_le16(4000);
2287 pSMB->MaxSetupCount = 0;
2291 pSMB->Reserved2 = 0;
2292 pSMB->ParameterOffset = cpu_to_le16(offsetof(
2293 struct smb_com_transaction2_qpi_req ,InformationLevel) - 4);
2294 pSMB->DataCount = 0;
2295 pSMB->DataOffset = 0;
2296 pSMB->SetupCount = 1;
2297 pSMB->Reserved3 = 0;
2298 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
2299 byte_count = params + 1 /* pad */ ;
2300 pSMB->TotalParameterCount = cpu_to_le16(params);
2301 pSMB->ParameterCount = pSMB->TotalParameterCount;
2302 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC);
2303 pSMB->Reserved4 = 0;
2304 pSMB->hdr.smb_buf_length += byte_count;
2305 pSMB->ByteCount = cpu_to_le16(byte_count);
2307 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2308 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2310 cFYI(1, ("Send error in QPathInfo = %d", rc));
2311 } else { /* decode response */
2312 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
2314 if (rc || (pSMBr->ByteCount < sizeof(FILE_UNIX_BASIC_INFO))) {
2315 rc = -EIO; /* bad smb */
2317 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
2318 memcpy((char *) pFindData,
2319 (char *) &pSMBr->hdr.Protocol +
2321 sizeof (FILE_UNIX_BASIC_INFO));
2324 cifs_buf_release(pSMB);
2326 goto UnixQPathInfoRetry;
2331 #if 0 /* function unused at present */
2332 int CIFSFindSingle(const int xid, struct cifsTconInfo *tcon,
2333 const char *searchName, FILE_ALL_INFO * findData,
2334 const struct nls_table *nls_codepage)
2336 /* level 257 SMB_ */
2337 TRANSACTION2_FFIRST_REQ *pSMB = NULL;
2338 TRANSACTION2_FFIRST_RSP *pSMBr = NULL;
2342 __u16 params, byte_count;
2344 cFYI(1, ("In FindUnique"));
2346 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2351 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2353 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName, PATH_MAX
2354 /* find define for this maxpathcomponent */
2356 name_len++; /* trailing null */
2358 } else { /* BB improve the check for buffer overruns BB */
2359 name_len = strnlen(searchName, PATH_MAX);
2360 name_len++; /* trailing null */
2361 strncpy(pSMB->FileName, searchName, name_len);
2364 params = 12 + name_len /* includes null */ ;
2365 pSMB->TotalDataCount = 0; /* no EAs */
2366 pSMB->MaxParameterCount = cpu_to_le16(2);
2367 pSMB->MaxDataCount = cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
2368 pSMB->MaxSetupCount = 0;
2372 pSMB->Reserved2 = 0;
2373 pSMB->ParameterOffset = cpu_to_le16(
2374 offsetof(struct smb_com_transaction2_ffirst_req,InformationLevel) - 4);
2375 pSMB->DataCount = 0;
2376 pSMB->DataOffset = 0;
2377 pSMB->SetupCount = 1; /* one byte, no need to le convert */
2378 pSMB->Reserved3 = 0;
2379 pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_FIRST);
2380 byte_count = params + 1 /* pad */ ;
2381 pSMB->TotalParameterCount = cpu_to_le16(params);
2382 pSMB->ParameterCount = pSMB->TotalParameterCount;
2383 pSMB->SearchAttributes =
2384 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
2386 pSMB->SearchCount = cpu_to_le16(16); /* BB increase */
2387 pSMB->SearchFlags = cpu_to_le16(1);
2388 pSMB->InformationLevel = cpu_to_le16(SMB_FIND_FILE_DIRECTORY_INFO);
2389 pSMB->SearchStorageType = 0; /* BB what should we set this to? BB */
2390 pSMB->hdr.smb_buf_length += byte_count;
2391 pSMB->ByteCount = cpu_to_le16(byte_count);
2393 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2394 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2397 cFYI(1, ("Send error in FindFileDirInfo = %d", rc));
2398 } else { /* decode response */
2399 #ifdef CONFIG_CIFS_STATS
2400 atomic_inc(&tcon->num_ffirst);
2405 cifs_buf_release(pSMB);
2407 goto findUniqueRetry;
2411 #endif /* end unused (temporarily) function */
2413 /* xid, tcon, searchName and codepage are input parms, rest are returned */
2415 CIFSFindFirst(const int xid, struct cifsTconInfo *tcon,
2416 const char *searchName,
2417 const struct nls_table *nls_codepage,
2419 struct cifs_search_info * psrch_inf, int remap, const char dirsep)
2421 /* level 257 SMB_ */
2422 TRANSACTION2_FFIRST_REQ *pSMB = NULL;
2423 TRANSACTION2_FFIRST_RSP *pSMBr = NULL;
2424 T2_FFIRST_RSP_PARMS * parms;
2426 int bytes_returned = 0;
2428 __u16 params, byte_count;
2430 cFYI(1, ("In FindFirst for %s",searchName));
2433 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2438 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2440 cifsConvertToUCS((__le16 *) pSMB->FileName,searchName,
2441 PATH_MAX, nls_codepage, remap);
2442 /* We can not add the asterik earlier in case
2443 it got remapped to 0xF03A as if it were part of the
2444 directory name instead of a wildcard */
2446 pSMB->FileName[name_len] = dirsep;
2447 pSMB->FileName[name_len+1] = 0;
2448 pSMB->FileName[name_len+2] = '*';
2449 pSMB->FileName[name_len+3] = 0;
2450 name_len += 4; /* now the trailing null */
2451 pSMB->FileName[name_len] = 0; /* null terminate just in case */
2452 pSMB->FileName[name_len+1] = 0;
2454 } else { /* BB add check for overrun of SMB buf BB */
2455 name_len = strnlen(searchName, PATH_MAX);
2456 /* BB fix here and in unicode clause above ie
2457 if(name_len > buffersize-header)
2458 free buffer exit; BB */
2459 strncpy(pSMB->FileName, searchName, name_len);
2460 pSMB->FileName[name_len] = dirsep;
2461 pSMB->FileName[name_len+1] = '*';
2462 pSMB->FileName[name_len+2] = 0;
2466 params = 12 + name_len /* includes null */ ;
2467 pSMB->TotalDataCount = 0; /* no EAs */
2468 pSMB->MaxParameterCount = cpu_to_le16(10);
2469 pSMB->MaxDataCount = cpu_to_le16((tcon->ses->server->maxBuf -
2470 MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
2471 pSMB->MaxSetupCount = 0;
2475 pSMB->Reserved2 = 0;
2476 byte_count = params + 1 /* pad */ ;
2477 pSMB->TotalParameterCount = cpu_to_le16(params);
2478 pSMB->ParameterCount = pSMB->TotalParameterCount;
2479 pSMB->ParameterOffset = cpu_to_le16(
2480 offsetof(struct smb_com_transaction2_ffirst_req, SearchAttributes) - 4);
2481 pSMB->DataCount = 0;
2482 pSMB->DataOffset = 0;
2483 pSMB->SetupCount = 1; /* one byte, no need to make endian neutral */
2484 pSMB->Reserved3 = 0;
2485 pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_FIRST);
2486 pSMB->SearchAttributes =
2487 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
2489 pSMB->SearchCount= cpu_to_le16(CIFSMaxBufSize/sizeof(FILE_UNIX_INFO));
2490 pSMB->SearchFlags = cpu_to_le16(CIFS_SEARCH_CLOSE_AT_END |
2491 CIFS_SEARCH_RETURN_RESUME);
2492 pSMB->InformationLevel = cpu_to_le16(psrch_inf->info_level);
2494 /* BB what should we set StorageType to? Does it matter? BB */
2495 pSMB->SearchStorageType = 0;
2496 pSMB->hdr.smb_buf_length += byte_count;
2497 pSMB->ByteCount = cpu_to_le16(byte_count);
2499 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2500 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2502 if (rc) {/* BB add logic to retry regular search if Unix search rejected unexpectedly by server */
2503 /* BB Add code to handle unsupported level rc */
2504 cFYI(1, ("Error in FindFirst = %d", rc));
2507 cifs_buf_release(pSMB);
2509 /* BB eventually could optimize out free and realloc of buf */
2512 goto findFirstRetry;
2513 } else { /* decode response */
2514 #ifdef CONFIG_CIFS_STATS
2515 atomic_inc(&tcon->num_ffirst);
2517 /* BB remember to free buffer if error BB */
2518 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
2520 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
2521 psrch_inf->unicode = TRUE;
2523 psrch_inf->unicode = FALSE;
2525 psrch_inf->ntwrk_buf_start = (char *)pSMBr;
2526 psrch_inf->srch_entries_start =
2527 (char *) &pSMBr->hdr.Protocol +
2528 le16_to_cpu(pSMBr->t2.DataOffset);
2529 parms = (T2_FFIRST_RSP_PARMS *)((char *) &pSMBr->hdr.Protocol +
2530 le16_to_cpu(pSMBr->t2.ParameterOffset));
2532 if(parms->EndofSearch)
2533 psrch_inf->endOfSearch = TRUE;
2535 psrch_inf->endOfSearch = FALSE;
2537 psrch_inf->entries_in_buffer = le16_to_cpu(parms->SearchCount);
2538 psrch_inf->index_of_last_entry =
2539 psrch_inf->entries_in_buffer;
2540 *pnetfid = parms->SearchHandle;
2542 cifs_buf_release(pSMB);
2549 int CIFSFindNext(const int xid, struct cifsTconInfo *tcon,
2550 __u16 searchHandle, struct cifs_search_info * psrch_inf)
2552 TRANSACTION2_FNEXT_REQ *pSMB = NULL;
2553 TRANSACTION2_FNEXT_RSP *pSMBr = NULL;
2554 T2_FNEXT_RSP_PARMS * parms;
2555 char *response_data;
2557 int bytes_returned, name_len;
2558 __u16 params, byte_count;
2560 cFYI(1, ("In FindNext"));
2562 if(psrch_inf->endOfSearch == TRUE)
2565 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2570 params = 14; /* includes 2 bytes of null string, converted to LE below */
2572 pSMB->TotalDataCount = 0; /* no EAs */
2573 pSMB->MaxParameterCount = cpu_to_le16(8);
2574 pSMB->MaxDataCount =
2575 cpu_to_le16((tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
2576 pSMB->MaxSetupCount = 0;
2580 pSMB->Reserved2 = 0;
2581 pSMB->ParameterOffset = cpu_to_le16(
2582 offsetof(struct smb_com_transaction2_fnext_req,SearchHandle) - 4);
2583 pSMB->DataCount = 0;
2584 pSMB->DataOffset = 0;
2585 pSMB->SetupCount = 1;
2586 pSMB->Reserved3 = 0;
2587 pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_NEXT);
2588 pSMB->SearchHandle = searchHandle; /* always kept as le */
2590 cpu_to_le16(CIFSMaxBufSize / sizeof (FILE_UNIX_INFO));
2591 /* test for Unix extensions */
2592 /* if (tcon->ses->capabilities & CAP_UNIX) {
2593 pSMB->InformationLevel = cpu_to_le16(SMB_FIND_FILE_UNIX);
2594 psrch_inf->info_level = SMB_FIND_FILE_UNIX;
2596 pSMB->InformationLevel =
2597 cpu_to_le16(SMB_FIND_FILE_DIRECTORY_INFO);
2598 psrch_inf->info_level = SMB_FIND_FILE_DIRECTORY_INFO;
2600 pSMB->InformationLevel = cpu_to_le16(psrch_inf->info_level);
2601 pSMB->ResumeKey = psrch_inf->resume_key;
2603 cpu_to_le16(CIFS_SEARCH_CLOSE_AT_END | CIFS_SEARCH_RETURN_RESUME);
2605 name_len = psrch_inf->resume_name_len;
2607 if(name_len < PATH_MAX) {
2608 memcpy(pSMB->ResumeFileName, psrch_inf->presume_name, name_len);
2609 byte_count += name_len;
2612 goto FNext2_err_exit;
2614 byte_count = params + 1 /* pad */ ;
2615 pSMB->TotalParameterCount = cpu_to_le16(params);
2616 pSMB->ParameterCount = pSMB->TotalParameterCount;
2617 pSMB->hdr.smb_buf_length += byte_count;
2618 pSMB->ByteCount = cpu_to_le16(byte_count);
2620 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2621 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2625 psrch_inf->endOfSearch = TRUE;
2626 rc = 0; /* search probably was closed at end of search above */
2628 cFYI(1, ("FindNext returned = %d", rc));
2629 } else { /* decode response */
2630 #ifdef CONFIG_CIFS_STATS
2631 atomic_inc(&tcon->num_fnext);
2633 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
2636 /* BB fixme add lock for file (srch_info) struct here */
2637 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
2638 psrch_inf->unicode = TRUE;
2640 psrch_inf->unicode = FALSE;
2641 response_data = (char *) &pSMBr->hdr.Protocol +
2642 le16_to_cpu(pSMBr->t2.ParameterOffset);
2643 parms = (T2_FNEXT_RSP_PARMS *)response_data;
2644 response_data = (char *)&pSMBr->hdr.Protocol +
2645 le16_to_cpu(pSMBr->t2.DataOffset);
2646 cifs_buf_release(psrch_inf->ntwrk_buf_start);
2647 psrch_inf->srch_entries_start = response_data;
2648 psrch_inf->ntwrk_buf_start = (char *)pSMB;
2649 if(parms->EndofSearch)
2650 psrch_inf->endOfSearch = TRUE;
2652 psrch_inf->endOfSearch = FALSE;
2654 psrch_inf->entries_in_buffer = le16_to_cpu(parms->SearchCount);
2655 psrch_inf->index_of_last_entry +=
2656 psrch_inf->entries_in_buffer;
2657 /* cFYI(1,("fnxt2 entries in buf %d index_of_last %d",psrch_inf->entries_in_buffer,psrch_inf->index_of_last_entry)); */
2659 /* BB fixme add unlock here */
2664 /* BB On error, should we leave previous search buf (and count and
2665 last entry fields) intact or free the previous one? */
2667 /* Note: On -EAGAIN error only caller can retry on handle based calls
2668 since file handle passed in no longer valid */
2671 cifs_buf_release(pSMB);
2677 CIFSFindClose(const int xid, struct cifsTconInfo *tcon, const __u16 searchHandle)
2680 FINDCLOSE_REQ *pSMB = NULL;
2681 CLOSE_RSP *pSMBr = NULL; /* BB removeme BB */
2684 cFYI(1, ("In CIFSSMBFindClose"));
2685 rc = small_smb_init(SMB_COM_FIND_CLOSE2, 1, tcon, (void **)&pSMB);
2687 /* no sense returning error if session restarted
2688 as file handle has been closed */
2694 pSMBr = (CLOSE_RSP *)pSMB; /* BB removeme BB */
2695 pSMB->FileID = searchHandle;
2696 pSMB->ByteCount = 0;
2697 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2698 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2700 cERROR(1, ("Send error in FindClose = %d", rc));
2702 #ifdef CONFIG_CIFS_STATS
2703 atomic_inc(&tcon->num_fclose);
2705 cifs_small_buf_release(pSMB);
2707 /* Since session is dead, search handle closed on server already */
2714 #ifdef CONFIG_CIFS_EXPERIMENTAL
2716 CIFSGetSrvInodeNumber(const int xid, struct cifsTconInfo *tcon,
2717 const unsigned char *searchName,
2718 __u64 * inode_number,
2719 const struct nls_table *nls_codepage, int remap)
2722 TRANSACTION2_QPI_REQ *pSMB = NULL;
2723 TRANSACTION2_QPI_RSP *pSMBr = NULL;
2724 int name_len, bytes_returned;
2725 __u16 params, byte_count;
2727 cFYI(1,("In GetSrvInodeNum for %s",searchName));
2731 GetInodeNumberRetry:
2732 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2738 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2740 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
2741 PATH_MAX,nls_codepage, remap);
2742 name_len++; /* trailing null */
2744 } else { /* BB improve the check for buffer overruns BB */
2745 name_len = strnlen(searchName, PATH_MAX);
2746 name_len++; /* trailing null */
2747 strncpy(pSMB->FileName, searchName, name_len);
2750 params = 2 /* level */ + 4 /* rsrvd */ + name_len /* incl null */ ;
2751 pSMB->TotalDataCount = 0;
2752 pSMB->MaxParameterCount = cpu_to_le16(2);
2753 /* BB find exact max data count below from sess structure BB */
2754 pSMB->MaxDataCount = cpu_to_le16(4000);
2755 pSMB->MaxSetupCount = 0;
2759 pSMB->Reserved2 = 0;
2760 pSMB->ParameterOffset = cpu_to_le16(offsetof(
2761 struct smb_com_transaction2_qpi_req ,InformationLevel) - 4);
2762 pSMB->DataCount = 0;
2763 pSMB->DataOffset = 0;
2764 pSMB->SetupCount = 1;
2765 pSMB->Reserved3 = 0;
2766 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
2767 byte_count = params + 1 /* pad */ ;
2768 pSMB->TotalParameterCount = cpu_to_le16(params);
2769 pSMB->ParameterCount = pSMB->TotalParameterCount;
2770 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_INTERNAL_INFO);
2771 pSMB->Reserved4 = 0;
2772 pSMB->hdr.smb_buf_length += byte_count;
2773 pSMB->ByteCount = cpu_to_le16(byte_count);
2775 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2776 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2778 cFYI(1, ("error %d in QueryInternalInfo", rc));
2780 /* decode response */
2781 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
2782 if (rc || (pSMBr->ByteCount < 2))
2783 /* BB also check enough total bytes returned */
2784 /* If rc should we check for EOPNOSUPP and
2785 disable the srvino flag? or in caller? */
2786 rc = -EIO; /* bad smb */
2788 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
2789 __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
2790 struct file_internal_info * pfinfo;
2791 /* BB Do we need a cast or hash here ? */
2793 cFYI(1, ("Illegal size ret in QryIntrnlInf"));
2795 goto GetInodeNumOut;
2797 pfinfo = (struct file_internal_info *)
2798 (data_offset + (char *) &pSMBr->hdr.Protocol);
2799 *inode_number = pfinfo->UniqueId;
2803 cifs_buf_release(pSMB);
2805 goto GetInodeNumberRetry;
2808 #endif /* CIFS_EXPERIMENTAL */
2811 CIFSGetDFSRefer(const int xid, struct cifsSesInfo *ses,
2812 const unsigned char *searchName,
2813 unsigned char **targetUNCs,
2814 unsigned int *number_of_UNC_in_array,
2815 const struct nls_table *nls_codepage, int remap)
2817 /* TRANS2_GET_DFS_REFERRAL */
2818 TRANSACTION2_GET_DFS_REFER_REQ *pSMB = NULL;
2819 TRANSACTION2_GET_DFS_REFER_RSP *pSMBr = NULL;
2820 struct dfs_referral_level_3 * referrals = NULL;
2826 __u16 params, byte_count;
2827 *number_of_UNC_in_array = 0;
2830 cFYI(1, ("In GetDFSRefer the path %s", searchName));
2834 rc = smb_init(SMB_COM_TRANSACTION2, 15, NULL, (void **) &pSMB,
2839 pSMB->hdr.Tid = ses->ipc_tid;
2840 pSMB->hdr.Uid = ses->Suid;
2841 if (ses->capabilities & CAP_STATUS32) {
2842 pSMB->hdr.Flags2 |= SMBFLG2_ERR_STATUS;
2844 if (ses->capabilities & CAP_DFS) {
2845 pSMB->hdr.Flags2 |= SMBFLG2_DFS;
2848 if (ses->capabilities & CAP_UNICODE) {
2849 pSMB->hdr.Flags2 |= SMBFLG2_UNICODE;
2851 cifsConvertToUCS((__le16 *) pSMB->RequestFileName,
2852 searchName, PATH_MAX, nls_codepage, remap);
2853 name_len++; /* trailing null */
2855 } else { /* BB improve the check for buffer overruns BB */
2856 name_len = strnlen(searchName, PATH_MAX);
2857 name_len++; /* trailing null */
2858 strncpy(pSMB->RequestFileName, searchName, name_len);
2861 params = 2 /* level */ + name_len /*includes null */ ;
2862 pSMB->TotalDataCount = 0;
2863 pSMB->DataCount = 0;
2864 pSMB->DataOffset = 0;
2865 pSMB->MaxParameterCount = 0;
2866 pSMB->MaxDataCount = cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
2867 pSMB->MaxSetupCount = 0;
2871 pSMB->Reserved2 = 0;
2872 pSMB->ParameterOffset = cpu_to_le16(offsetof(
2873 struct smb_com_transaction2_get_dfs_refer_req, MaxReferralLevel) - 4);
2874 pSMB->SetupCount = 1;
2875 pSMB->Reserved3 = 0;
2876 pSMB->SubCommand = cpu_to_le16(TRANS2_GET_DFS_REFERRAL);
2877 byte_count = params + 3 /* pad */ ;
2878 pSMB->ParameterCount = cpu_to_le16(params);
2879 pSMB->TotalParameterCount = pSMB->ParameterCount;
2880 pSMB->MaxReferralLevel = cpu_to_le16(3);
2881 pSMB->hdr.smb_buf_length += byte_count;
2882 pSMB->ByteCount = cpu_to_le16(byte_count);
2884 rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB,
2885 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2887 cFYI(1, ("Send error in GetDFSRefer = %d", rc));
2888 } else { /* decode response */
2889 /* BB Add logic to parse referrals here */
2890 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
2892 if (rc || (pSMBr->ByteCount < 17)) /* BB also check enough total bytes returned */
2893 rc = -EIO; /* bad smb */
2895 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
2896 __u16 data_count = le16_to_cpu(pSMBr->t2.DataCount);
2899 ("Decoding GetDFSRefer response. BCC: %d Offset %d",
2900 pSMBr->ByteCount, data_offset));
2902 (struct dfs_referral_level_3 *)
2903 (8 /* sizeof start of data block */ +
2905 (char *) &pSMBr->hdr.Protocol);
2906 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",
2907 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)));
2908 /* BB This field is actually two bytes in from start of
2909 data block so we could do safety check that DataBlock
2910 begins at address of pSMBr->NumberOfReferrals */
2911 *number_of_UNC_in_array = le16_to_cpu(pSMBr->NumberOfReferrals);
2913 /* BB Fix below so can return more than one referral */
2914 if(*number_of_UNC_in_array > 1)
2915 *number_of_UNC_in_array = 1;
2917 /* get the length of the strings describing refs */
2919 for(i=0;i<*number_of_UNC_in_array;i++) {
2920 /* make sure that DfsPathOffset not past end */
2921 __u16 offset = le16_to_cpu(referrals->DfsPathOffset);
2922 if (offset > data_count) {
2923 /* if invalid referral, stop here and do
2924 not try to copy any more */
2925 *number_of_UNC_in_array = i;
2928 temp = ((char *)referrals) + offset;
2930 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
2931 name_len += UniStrnlen((wchar_t *)temp,data_count);
2933 name_len += strnlen(temp,data_count);
2936 /* BB add check that referral pointer does not fall off end PDU */
2939 /* BB add check for name_len bigger than bcc */
2941 kmalloc(name_len+1+ (*number_of_UNC_in_array),GFP_KERNEL);
2942 if(*targetUNCs == NULL) {
2946 /* copy the ref strings */
2948 (struct dfs_referral_level_3 *)
2949 (8 /* sizeof data hdr */ +
2951 (char *) &pSMBr->hdr.Protocol);
2953 for(i=0;i<*number_of_UNC_in_array;i++) {
2954 temp = ((char *)referrals) + le16_to_cpu(referrals->DfsPathOffset);
2955 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
2956 cifs_strfromUCS_le(*targetUNCs,
2957 (wchar_t *) temp, name_len, nls_codepage);
2959 strncpy(*targetUNCs,temp,name_len);
2961 /* BB update target_uncs pointers */
2971 cifs_buf_release(pSMB);
2980 CIFSSMBQFSInfo(const int xid, struct cifsTconInfo *tcon, struct kstatfs *FSData)
2982 /* level 0x103 SMB_QUERY_FILE_SYSTEM_INFO */
2983 TRANSACTION2_QFSI_REQ *pSMB = NULL;
2984 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
2985 FILE_SYSTEM_INFO *response_data;
2987 int bytes_returned = 0;
2988 __u16 params, byte_count;
2990 cFYI(1, ("In QFSInfo"));
2992 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2997 params = 2; /* level */
2998 pSMB->TotalDataCount = 0;
2999 pSMB->MaxParameterCount = cpu_to_le16(2);
3000 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
3001 pSMB->MaxSetupCount = 0;
3005 pSMB->Reserved2 = 0;
3006 byte_count = params + 1 /* pad */ ;
3007 pSMB->TotalParameterCount = cpu_to_le16(params);
3008 pSMB->ParameterCount = pSMB->TotalParameterCount;
3009 pSMB->ParameterOffset = cpu_to_le16(offsetof(
3010 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
3011 pSMB->DataCount = 0;
3012 pSMB->DataOffset = 0;
3013 pSMB->SetupCount = 1;
3014 pSMB->Reserved3 = 0;
3015 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
3016 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_SIZE_INFO);
3017 pSMB->hdr.smb_buf_length += byte_count;
3018 pSMB->ByteCount = cpu_to_le16(byte_count);
3020 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3021 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3023 cERROR(1, ("Send error in QFSInfo = %d", rc));
3024 } else { /* decode response */
3025 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3027 if (rc || (pSMBr->ByteCount < 24)) /* BB alsO CHEck enough total bytes returned */
3028 rc = -EIO; /* bad smb */
3030 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3032 ("Decoding qfsinfo response. BCC: %d Offset %d",
3033 pSMBr->ByteCount, data_offset));
3037 *) (((char *) &pSMBr->hdr.Protocol) +
3040 le32_to_cpu(response_data->BytesPerSector) *
3041 le32_to_cpu(response_data->
3042 SectorsPerAllocationUnit);
3044 le64_to_cpu(response_data->TotalAllocationUnits);
3045 FSData->f_bfree = FSData->f_bavail =
3046 le64_to_cpu(response_data->FreeAllocationUnits);
3048 ("Blocks: %lld Free: %lld Block size %ld",
3049 (unsigned long long)FSData->f_blocks,
3050 (unsigned long long)FSData->f_bfree,
3054 cifs_buf_release(pSMB);
3063 CIFSSMBQFSAttributeInfo(const int xid, struct cifsTconInfo *tcon)
3065 /* level 0x105 SMB_QUERY_FILE_SYSTEM_INFO */
3066 TRANSACTION2_QFSI_REQ *pSMB = NULL;
3067 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
3068 FILE_SYSTEM_ATTRIBUTE_INFO *response_data;
3070 int bytes_returned = 0;
3071 __u16 params, byte_count;
3073 cFYI(1, ("In QFSAttributeInfo"));
3075 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3080 params = 2; /* level */
3081 pSMB->TotalDataCount = 0;
3082 pSMB->MaxParameterCount = cpu_to_le16(2);
3083 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
3084 pSMB->MaxSetupCount = 0;
3088 pSMB->Reserved2 = 0;
3089 byte_count = params + 1 /* pad */ ;
3090 pSMB->TotalParameterCount = cpu_to_le16(params);
3091 pSMB->ParameterCount = pSMB->TotalParameterCount;
3092 pSMB->ParameterOffset = cpu_to_le16(offsetof(
3093 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
3094 pSMB->DataCount = 0;
3095 pSMB->DataOffset = 0;
3096 pSMB->SetupCount = 1;
3097 pSMB->Reserved3 = 0;
3098 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
3099 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_ATTRIBUTE_INFO);
3100 pSMB->hdr.smb_buf_length += byte_count;
3101 pSMB->ByteCount = cpu_to_le16(byte_count);
3103 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3104 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3106 cERROR(1, ("Send error in QFSAttributeInfo = %d", rc));
3107 } else { /* decode response */
3108 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3110 if (rc || (pSMBr->ByteCount < 13)) { /* BB also check enough bytes returned */
3111 rc = -EIO; /* bad smb */
3113 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3115 (FILE_SYSTEM_ATTRIBUTE_INFO
3116 *) (((char *) &pSMBr->hdr.Protocol) +
3118 memcpy(&tcon->fsAttrInfo, response_data,
3119 sizeof (FILE_SYSTEM_ATTRIBUTE_INFO));
3122 cifs_buf_release(pSMB);
3125 goto QFSAttributeRetry;
3131 CIFSSMBQFSDeviceInfo(const int xid, struct cifsTconInfo *tcon)
3133 /* level 0x104 SMB_QUERY_FILE_SYSTEM_INFO */
3134 TRANSACTION2_QFSI_REQ *pSMB = NULL;
3135 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
3136 FILE_SYSTEM_DEVICE_INFO *response_data;
3138 int bytes_returned = 0;
3139 __u16 params, byte_count;
3141 cFYI(1, ("In QFSDeviceInfo"));
3143 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3148 params = 2; /* level */
3149 pSMB->TotalDataCount = 0;
3150 pSMB->MaxParameterCount = cpu_to_le16(2);
3151 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
3152 pSMB->MaxSetupCount = 0;
3156 pSMB->Reserved2 = 0;
3157 byte_count = params + 1 /* pad */ ;
3158 pSMB->TotalParameterCount = cpu_to_le16(params);
3159 pSMB->ParameterCount = pSMB->TotalParameterCount;
3160 pSMB->ParameterOffset = cpu_to_le16(offsetof(
3161 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
3163 pSMB->DataCount = 0;
3164 pSMB->DataOffset = 0;
3165 pSMB->SetupCount = 1;
3166 pSMB->Reserved3 = 0;
3167 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
3168 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_DEVICE_INFO);
3169 pSMB->hdr.smb_buf_length += byte_count;
3170 pSMB->ByteCount = cpu_to_le16(byte_count);
3172 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3173 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3175 cFYI(1, ("Send error in QFSDeviceInfo = %d", rc));
3176 } else { /* decode response */
3177 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3179 if (rc || (pSMBr->ByteCount < sizeof (FILE_SYSTEM_DEVICE_INFO)))
3180 rc = -EIO; /* bad smb */
3182 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3184 (FILE_SYSTEM_DEVICE_INFO *)
3185 (((char *) &pSMBr->hdr.Protocol) +
3187 memcpy(&tcon->fsDevInfo, response_data,
3188 sizeof (FILE_SYSTEM_DEVICE_INFO));
3191 cifs_buf_release(pSMB);
3194 goto QFSDeviceRetry;
3200 CIFSSMBQFSUnixInfo(const int xid, struct cifsTconInfo *tcon)
3202 /* level 0x200 SMB_QUERY_CIFS_UNIX_INFO */
3203 TRANSACTION2_QFSI_REQ *pSMB = NULL;
3204 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
3205 FILE_SYSTEM_UNIX_INFO *response_data;
3207 int bytes_returned = 0;
3208 __u16 params, byte_count;
3210 cFYI(1, ("In QFSUnixInfo"));
3212 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3217 params = 2; /* level */
3218 pSMB->TotalDataCount = 0;
3219 pSMB->DataCount = 0;
3220 pSMB->DataOffset = 0;
3221 pSMB->MaxParameterCount = cpu_to_le16(2);
3222 pSMB->MaxDataCount = cpu_to_le16(100); /* BB find exact max SMB PDU from sess structure BB */
3223 pSMB->MaxSetupCount = 0;
3227 pSMB->Reserved2 = 0;
3228 byte_count = params + 1 /* pad */ ;
3229 pSMB->ParameterCount = cpu_to_le16(params);
3230 pSMB->TotalParameterCount = pSMB->ParameterCount;
3231 pSMB->ParameterOffset = cpu_to_le16(offsetof(struct
3232 smb_com_transaction2_qfsi_req, InformationLevel) - 4);
3233 pSMB->SetupCount = 1;
3234 pSMB->Reserved3 = 0;
3235 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
3236 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_CIFS_UNIX_INFO);
3237 pSMB->hdr.smb_buf_length += byte_count;
3238 pSMB->ByteCount = cpu_to_le16(byte_count);
3240 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3241 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3243 cERROR(1, ("Send error in QFSUnixInfo = %d", rc));
3244 } else { /* decode response */
3245 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3247 if (rc || (pSMBr->ByteCount < 13)) {
3248 rc = -EIO; /* bad smb */
3250 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3252 (FILE_SYSTEM_UNIX_INFO
3253 *) (((char *) &pSMBr->hdr.Protocol) +
3255 memcpy(&tcon->fsUnixInfo, response_data,
3256 sizeof (FILE_SYSTEM_UNIX_INFO));
3259 cifs_buf_release(pSMB);
3269 CIFSSMBSETFSUnixInfo(const int xid, struct cifsTconInfo *tcon, __u64 cap)
3271 /* level 0x200 SMB_SET_CIFS_UNIX_INFO */
3272 TRANSACTION2_SETFSI_REQ *pSMB = NULL;
3273 TRANSACTION2_SETFSI_RSP *pSMBr = NULL;
3275 int bytes_returned = 0;
3276 __u16 params, param_offset, offset, byte_count;
3278 cFYI(1, ("In SETFSUnixInfo"));
3280 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3285 params = 4; /* 2 bytes zero followed by info level. */
3286 pSMB->MaxSetupCount = 0;
3290 pSMB->Reserved2 = 0;
3291 param_offset = offsetof(struct smb_com_transaction2_setfsi_req, FileNum) - 4;
3292 offset = param_offset + params;
3294 pSMB->MaxParameterCount = cpu_to_le16(4);
3295 pSMB->MaxDataCount = cpu_to_le16(100); /* BB find exact max SMB PDU from sess structure BB */
3296 pSMB->SetupCount = 1;
3297 pSMB->Reserved3 = 0;
3298 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FS_INFORMATION);
3299 byte_count = 1 /* pad */ + params + 12;
3301 pSMB->DataCount = cpu_to_le16(12);
3302 pSMB->ParameterCount = cpu_to_le16(params);
3303 pSMB->TotalDataCount = pSMB->DataCount;
3304 pSMB->TotalParameterCount = pSMB->ParameterCount;
3305 pSMB->ParameterOffset = cpu_to_le16(param_offset);
3306 pSMB->DataOffset = cpu_to_le16(offset);
3310 pSMB->InformationLevel = cpu_to_le16(SMB_SET_CIFS_UNIX_INFO);
3313 pSMB->ClientUnixMajor = cpu_to_le16(CIFS_UNIX_MAJOR_VERSION);
3314 pSMB->ClientUnixMinor = cpu_to_le16(CIFS_UNIX_MINOR_VERSION);
3315 pSMB->ClientUnixCap = cpu_to_le64(cap);
3317 pSMB->hdr.smb_buf_length += byte_count;
3318 pSMB->ByteCount = cpu_to_le16(byte_count);
3320 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3321 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3323 cERROR(1, ("Send error in SETFSUnixInfo = %d", rc));
3324 } else { /* decode response */
3325 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3327 rc = -EIO; /* bad smb */
3330 cifs_buf_release(pSMB);
3333 goto SETFSUnixRetry;
3341 CIFSSMBQFSPosixInfo(const int xid, struct cifsTconInfo *tcon,
3342 struct kstatfs *FSData)
3344 /* level 0x201 SMB_QUERY_CIFS_POSIX_INFO */
3345 TRANSACTION2_QFSI_REQ *pSMB = NULL;
3346 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
3347 FILE_SYSTEM_POSIX_INFO *response_data;
3349 int bytes_returned = 0;
3350 __u16 params, byte_count;
3352 cFYI(1, ("In QFSPosixInfo"));
3354 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3359 params = 2; /* level */
3360 pSMB->TotalDataCount = 0;
3361 pSMB->DataCount = 0;
3362 pSMB->DataOffset = 0;
3363 pSMB->MaxParameterCount = cpu_to_le16(2);
3364 pSMB->MaxDataCount = cpu_to_le16(100); /* BB find exact max SMB PDU from sess structure BB */
3365 pSMB->MaxSetupCount = 0;
3369 pSMB->Reserved2 = 0;
3370 byte_count = params + 1 /* pad */ ;
3371 pSMB->ParameterCount = cpu_to_le16(params);
3372 pSMB->TotalParameterCount = pSMB->ParameterCount;
3373 pSMB->ParameterOffset = cpu_to_le16(offsetof(struct
3374 smb_com_transaction2_qfsi_req, InformationLevel) - 4);
3375 pSMB->SetupCount = 1;
3376 pSMB->Reserved3 = 0;
3377 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
3378 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_POSIX_FS_INFO);
3379 pSMB->hdr.smb_buf_length += byte_count;
3380 pSMB->ByteCount = cpu_to_le16(byte_count);
3382 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3383 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3385 cFYI(1, ("Send error in QFSUnixInfo = %d", rc));
3386 } else { /* decode response */
3387 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3389 if (rc || (pSMBr->ByteCount < 13)) {
3390 rc = -EIO; /* bad smb */
3392 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3394 (FILE_SYSTEM_POSIX_INFO
3395 *) (((char *) &pSMBr->hdr.Protocol) +
3398 le32_to_cpu(response_data->BlockSize);
3400 le64_to_cpu(response_data->TotalBlocks);
3402 le64_to_cpu(response_data->BlocksAvail);
3403 if(response_data->UserBlocksAvail == -1) {
3404 FSData->f_bavail = FSData->f_bfree;
3407 le64_to_cpu(response_data->UserBlocksAvail);
3409 if(response_data->TotalFileNodes != -1)
3411 le64_to_cpu(response_data->TotalFileNodes);
3412 if(response_data->FreeFileNodes != -1)
3414 le64_to_cpu(response_data->FreeFileNodes);
3417 cifs_buf_release(pSMB);
3426 /* We can not use write of zero bytes trick to
3427 set file size due to need for large file support. Also note that
3428 this SetPathInfo is preferred to SetFileInfo based method in next
3429 routine which is only needed to work around a sharing violation bug
3430 in Samba which this routine can run into */
3433 CIFSSMBSetEOF(const int xid, struct cifsTconInfo *tcon, const char *fileName,
3434 __u64 size, int SetAllocation,
3435 const struct nls_table *nls_codepage, int remap)
3437 struct smb_com_transaction2_spi_req *pSMB = NULL;
3438 struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
3439 struct file_end_of_file_info *parm_data;
3442 int bytes_returned = 0;
3443 __u16 params, byte_count, data_count, param_offset, offset;
3445 cFYI(1, ("In SetEOF"));
3447 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3452 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3454 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
3455 PATH_MAX, nls_codepage, remap);
3456 name_len++; /* trailing null */
3458 } else { /* BB improve the check for buffer overruns BB */
3459 name_len = strnlen(fileName, PATH_MAX);
3460 name_len++; /* trailing null */
3461 strncpy(pSMB->FileName, fileName, name_len);
3463 params = 6 + name_len;
3464 data_count = sizeof (struct file_end_of_file_info);
3465 pSMB->MaxParameterCount = cpu_to_le16(2);
3466 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB size from sess */
3467 pSMB->MaxSetupCount = 0;
3471 pSMB->Reserved2 = 0;
3472 param_offset = offsetof(struct smb_com_transaction2_spi_req,
3473 InformationLevel) - 4;
3474 offset = param_offset + params;
3476 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
3477 pSMB->InformationLevel =
3478 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2);
3480 pSMB->InformationLevel =
3481 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO);
3482 } else /* Set File Size */ {
3483 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
3484 pSMB->InformationLevel =
3485 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO2);
3487 pSMB->InformationLevel =
3488 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO);
3492 (struct file_end_of_file_info *) (((char *) &pSMB->hdr.Protocol) +
3494 pSMB->ParameterOffset = cpu_to_le16(param_offset);
3495 pSMB->DataOffset = cpu_to_le16(offset);
3496 pSMB->SetupCount = 1;
3497 pSMB->Reserved3 = 0;
3498 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
3499 byte_count = 3 /* pad */ + params + data_count;
3500 pSMB->DataCount = cpu_to_le16(data_count);
3501 pSMB->TotalDataCount = pSMB->DataCount;
3502 pSMB->ParameterCount = cpu_to_le16(params);
3503 pSMB->TotalParameterCount = pSMB->ParameterCount;
3504 pSMB->Reserved4 = 0;
3505 pSMB->hdr.smb_buf_length += byte_count;
3506 parm_data->FileSize = cpu_to_le64(size);
3507 pSMB->ByteCount = cpu_to_le16(byte_count);
3508 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3509 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3511 cFYI(1, ("SetPathInfo (file size) returned %d", rc));
3514 cifs_buf_release(pSMB);
3523 CIFSSMBSetFileSize(const int xid, struct cifsTconInfo *tcon, __u64 size,
3524 __u16 fid, __u32 pid_of_opener, int SetAllocation)
3526 struct smb_com_transaction2_sfi_req *pSMB = NULL;
3527 struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
3529 struct file_end_of_file_info *parm_data;
3531 int bytes_returned = 0;
3532 __u16 params, param_offset, offset, byte_count, count;
3534 cFYI(1, ("SetFileSize (via SetFileInfo) %lld",
3536 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
3541 pSMBr = (struct smb_com_transaction2_sfi_rsp *)pSMB;
3543 pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
3544 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));
3547 pSMB->MaxSetupCount = 0;
3551 pSMB->Reserved2 = 0;
3552 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
3553 offset = param_offset + params;
3555 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
3557 count = sizeof(struct file_end_of_file_info);
3558 pSMB->MaxParameterCount = cpu_to_le16(2);
3559 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB PDU from sess */
3560 pSMB->SetupCount = 1;
3561 pSMB->Reserved3 = 0;
3562 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
3563 byte_count = 3 /* pad */ + params + count;
3564 pSMB->DataCount = cpu_to_le16(count);
3565 pSMB->ParameterCount = cpu_to_le16(params);
3566 pSMB->TotalDataCount = pSMB->DataCount;
3567 pSMB->TotalParameterCount = pSMB->ParameterCount;
3568 pSMB->ParameterOffset = cpu_to_le16(param_offset);
3570 (struct file_end_of_file_info *) (((char *) &pSMB->hdr.Protocol) +
3572 pSMB->DataOffset = cpu_to_le16(offset);
3573 parm_data->FileSize = cpu_to_le64(size);
3576 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
3577 pSMB->InformationLevel =
3578 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2);
3580 pSMB->InformationLevel =
3581 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO);
3582 } else /* Set File Size */ {
3583 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
3584 pSMB->InformationLevel =
3585 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO2);
3587 pSMB->InformationLevel =
3588 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO);
3590 pSMB->Reserved4 = 0;
3591 pSMB->hdr.smb_buf_length += byte_count;
3592 pSMB->ByteCount = cpu_to_le16(byte_count);
3593 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3594 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3597 ("Send error in SetFileInfo (SetFileSize) = %d",
3602 cifs_small_buf_release(pSMB);
3604 /* Note: On -EAGAIN error only caller can retry on handle based calls
3605 since file handle passed in no longer valid */
3610 /* Some legacy servers such as NT4 require that the file times be set on
3611 an open handle, rather than by pathname - this is awkward due to
3612 potential access conflicts on the open, but it is unavoidable for these
3613 old servers since the only other choice is to go from 100 nanosecond DCE
3614 time and resort to the original setpathinfo level which takes the ancient
3615 DOS time format with 2 second granularity */
3617 CIFSSMBSetFileTimes(const int xid, struct cifsTconInfo *tcon, const FILE_BASIC_INFO * data,
3620 struct smb_com_transaction2_sfi_req *pSMB = NULL;
3621 struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
3624 int bytes_returned = 0;
3625 __u16 params, param_offset, offset, byte_count, count;
3627 cFYI(1, ("Set Times (via SetFileInfo)"));
3628 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
3633 pSMBr = (struct smb_com_transaction2_sfi_rsp *)pSMB;
3635 /* At this point there is no need to override the current pid
3636 with the pid of the opener, but that could change if we someday
3637 use an existing handle (rather than opening one on the fly) */
3638 /* pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
3639 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));*/
3642 pSMB->MaxSetupCount = 0;
3646 pSMB->Reserved2 = 0;
3647 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
3648 offset = param_offset + params;
3650 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
3652 count = sizeof (FILE_BASIC_INFO);
3653 pSMB->MaxParameterCount = cpu_to_le16(2);
3654 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB PDU from sess */
3655 pSMB->SetupCount = 1;
3656 pSMB->Reserved3 = 0;
3657 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
3658 byte_count = 3 /* pad */ + params + count;
3659 pSMB->DataCount = cpu_to_le16(count);
3660 pSMB->ParameterCount = cpu_to_le16(params);
3661 pSMB->TotalDataCount = pSMB->DataCount;
3662 pSMB->TotalParameterCount = pSMB->ParameterCount;
3663 pSMB->ParameterOffset = cpu_to_le16(param_offset);
3664 pSMB->DataOffset = cpu_to_le16(offset);
3666 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
3667 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO2);
3669 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO);
3670 pSMB->Reserved4 = 0;
3671 pSMB->hdr.smb_buf_length += byte_count;
3672 pSMB->ByteCount = cpu_to_le16(byte_count);
3673 memcpy(data_offset,data,sizeof(FILE_BASIC_INFO));
3674 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3675 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3677 cFYI(1,("Send error in Set Time (SetFileInfo) = %d",rc));
3680 cifs_small_buf_release(pSMB);
3682 /* Note: On -EAGAIN error only caller can retry on handle based calls
3683 since file handle passed in no longer valid */
3690 CIFSSMBSetTimes(const int xid, struct cifsTconInfo *tcon, const char *fileName,
3691 const FILE_BASIC_INFO * data,
3692 const struct nls_table *nls_codepage, int remap)
3694 TRANSACTION2_SPI_REQ *pSMB = NULL;
3695 TRANSACTION2_SPI_RSP *pSMBr = NULL;
3698 int bytes_returned = 0;
3700 __u16 params, param_offset, offset, byte_count, count;
3702 cFYI(1, ("In SetTimes"));
3705 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3710 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3712 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
3713 PATH_MAX, nls_codepage, remap);
3714 name_len++; /* trailing null */
3716 } else { /* BB improve the check for buffer overruns BB */
3717 name_len = strnlen(fileName, PATH_MAX);
3718 name_len++; /* trailing null */
3719 strncpy(pSMB->FileName, fileName, name_len);
3722 params = 6 + name_len;
3723 count = sizeof (FILE_BASIC_INFO);
3724 pSMB->MaxParameterCount = cpu_to_le16(2);
3725 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
3726 pSMB->MaxSetupCount = 0;
3730 pSMB->Reserved2 = 0;
3731 param_offset = offsetof(struct smb_com_transaction2_spi_req,
3732 InformationLevel) - 4;
3733 offset = param_offset + params;
3734 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
3735 pSMB->ParameterOffset = cpu_to_le16(param_offset);
3736 pSMB->DataOffset = cpu_to_le16(offset);
3737 pSMB->SetupCount = 1;
3738 pSMB->Reserved3 = 0;
3739 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
3740 byte_count = 3 /* pad */ + params + count;
3742 pSMB->DataCount = cpu_to_le16(count);
3743 pSMB->ParameterCount = cpu_to_le16(params);
3744 pSMB->TotalDataCount = pSMB->DataCount;
3745 pSMB->TotalParameterCount = pSMB->ParameterCount;
3746 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
3747 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO2);
3749 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO);
3750 pSMB->Reserved4 = 0;
3751 pSMB->hdr.smb_buf_length += byte_count;
3752 memcpy(data_offset, data, sizeof (FILE_BASIC_INFO));
3753 pSMB->ByteCount = cpu_to_le16(byte_count);
3754 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3755 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3757 cFYI(1, ("SetPathInfo (times) returned %d", rc));
3760 cifs_buf_release(pSMB);
3768 /* Can not be used to set time stamps yet (due to old DOS time format) */
3769 /* Can be used to set attributes */
3770 #if 0 /* Possibly not needed - since it turns out that strangely NT4 has a bug
3771 handling it anyway and NT4 was what we thought it would be needed for
3772 Do not delete it until we prove whether needed for Win9x though */
3774 CIFSSMBSetAttrLegacy(int xid, struct cifsTconInfo *tcon, char *fileName,
3775 __u16 dos_attrs, const struct nls_table *nls_codepage)
3777 SETATTR_REQ *pSMB = NULL;
3778 SETATTR_RSP *pSMBr = NULL;
3783 cFYI(1, ("In SetAttrLegacy"));
3786 rc = smb_init(SMB_COM_SETATTR, 8, tcon, (void **) &pSMB,
3791 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3793 ConvertToUCS((__le16 *) pSMB->fileName, fileName,
3794 PATH_MAX, nls_codepage);
3795 name_len++; /* trailing null */
3797 } else { /* BB improve the check for buffer overruns BB */
3798 name_len = strnlen(fileName, PATH_MAX);
3799 name_len++; /* trailing null */
3800 strncpy(pSMB->fileName, fileName, name_len);
3802 pSMB->attr = cpu_to_le16(dos_attrs);
3803 pSMB->BufferFormat = 0x04;
3804 pSMB->hdr.smb_buf_length += name_len + 1;
3805 pSMB->ByteCount = cpu_to_le16(name_len + 1);
3806 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3807 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3809 cFYI(1, ("Error in LegacySetAttr = %d", rc));
3812 cifs_buf_release(pSMB);
3815 goto SetAttrLgcyRetry;
3819 #endif /* temporarily unneeded SetAttr legacy function */
3822 CIFSSMBUnixSetPerms(const int xid, struct cifsTconInfo *tcon,
3823 char *fileName, __u64 mode, __u64 uid, __u64 gid,
3824 dev_t device, const struct nls_table *nls_codepage,
3827 TRANSACTION2_SPI_REQ *pSMB = NULL;
3828 TRANSACTION2_SPI_RSP *pSMBr = NULL;
3831 int bytes_returned = 0;
3832 FILE_UNIX_BASIC_INFO *data_offset;
3833 __u16 params, param_offset, offset, count, byte_count;
3835 cFYI(1, ("In SetUID/GID/Mode"));
3837 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3842 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3844 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
3845 PATH_MAX, nls_codepage, remap);
3846 name_len++; /* trailing null */
3848 } else { /* BB improve the check for buffer overruns BB */
3849 name_len = strnlen(fileName, PATH_MAX);
3850 name_len++; /* trailing null */
3851 strncpy(pSMB->FileName, fileName, name_len);
3854 params = 6 + name_len;
3855 count = sizeof (FILE_UNIX_BASIC_INFO);
3856 pSMB->MaxParameterCount = cpu_to_le16(2);
3857 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
3858 pSMB->MaxSetupCount = 0;
3862 pSMB->Reserved2 = 0;
3863 param_offset = offsetof(struct smb_com_transaction2_spi_req,
3864 InformationLevel) - 4;
3865 offset = param_offset + params;
3867 (FILE_UNIX_BASIC_INFO *) ((char *) &pSMB->hdr.Protocol +
3869 memset(data_offset, 0, count);
3870 pSMB->DataOffset = cpu_to_le16(offset);
3871 pSMB->ParameterOffset = cpu_to_le16(param_offset);
3872 pSMB->SetupCount = 1;
3873 pSMB->Reserved3 = 0;
3874 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
3875 byte_count = 3 /* pad */ + params + count;
3876 pSMB->ParameterCount = cpu_to_le16(params);
3877 pSMB->DataCount = cpu_to_le16(count);
3878 pSMB->TotalParameterCount = pSMB->ParameterCount;
3879 pSMB->TotalDataCount = pSMB->DataCount;
3880 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_BASIC);
3881 pSMB->Reserved4 = 0;
3882 pSMB->hdr.smb_buf_length += byte_count;
3883 data_offset->Uid = cpu_to_le64(uid);
3884 data_offset->Gid = cpu_to_le64(gid);
3885 /* better to leave device as zero when it is */
3886 data_offset->DevMajor = cpu_to_le64(MAJOR(device));
3887 data_offset->DevMinor = cpu_to_le64(MINOR(device));
3888 data_offset->Permissions = cpu_to_le64(mode);
3891 data_offset->Type = cpu_to_le32(UNIX_FILE);
3892 else if(S_ISDIR(mode))
3893 data_offset->Type = cpu_to_le32(UNIX_DIR);
3894 else if(S_ISLNK(mode))
3895 data_offset->Type = cpu_to_le32(UNIX_SYMLINK);
3896 else if(S_ISCHR(mode))
3897 data_offset->Type = cpu_to_le32(UNIX_CHARDEV);
3898 else if(S_ISBLK(mode))
3899 data_offset->Type = cpu_to_le32(UNIX_BLOCKDEV);
3900 else if(S_ISFIFO(mode))
3901 data_offset->Type = cpu_to_le32(UNIX_FIFO);
3902 else if(S_ISSOCK(mode))
3903 data_offset->Type = cpu_to_le32(UNIX_SOCKET);
3906 pSMB->ByteCount = cpu_to_le16(byte_count);
3907 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3908 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3910 cFYI(1, ("SetPathInfo (perms) returned %d", rc));
3914 cifs_buf_release(pSMB);
3920 int CIFSSMBNotify(const int xid, struct cifsTconInfo *tcon,
3921 const int notify_subdirs, const __u16 netfid,
3922 __u32 filter, const struct nls_table *nls_codepage)
3925 struct smb_com_transaction_change_notify_req * pSMB = NULL;
3926 struct smb_com_transaction_change_notify_rsp * pSMBr = NULL;
3929 cFYI(1, ("In CIFSSMBNotify for file handle %d",(int)netfid));
3930 rc = smb_init(SMB_COM_NT_TRANSACT, 23, tcon, (void **) &pSMB,
3935 pSMB->TotalParameterCount = 0 ;
3936 pSMB->TotalDataCount = 0;
3937 pSMB->MaxParameterCount = cpu_to_le32(2);
3938 /* BB find exact data count max from sess structure BB */
3939 pSMB->MaxDataCount = 0; /* same in little endian or be */
3940 pSMB->MaxSetupCount = 4;
3942 pSMB->ParameterOffset = 0;
3943 pSMB->DataCount = 0;
3944 pSMB->DataOffset = 0;
3945 pSMB->SetupCount = 4; /* single byte does not need le conversion */
3946 pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_NOTIFY_CHANGE);
3947 pSMB->ParameterCount = pSMB->TotalParameterCount;
3949 pSMB->WatchTree = 1; /* one byte - no le conversion needed */
3950 pSMB->Reserved2 = 0;
3951 pSMB->CompletionFilter = cpu_to_le32(filter);
3952 pSMB->Fid = netfid; /* file handle always le */
3953 pSMB->ByteCount = 0;
3955 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3956 (struct smb_hdr *) pSMBr, &bytes_returned, -1);
3958 cFYI(1, ("Error in Notify = %d", rc));
3960 cifs_buf_release(pSMB);
3963 #ifdef CONFIG_CIFS_XATTR
3965 CIFSSMBQAllEAs(const int xid, struct cifsTconInfo *tcon,
3966 const unsigned char *searchName,
3967 char * EAData, size_t buf_size,
3968 const struct nls_table *nls_codepage, int remap)
3970 /* BB assumes one setup word */
3971 TRANSACTION2_QPI_REQ *pSMB = NULL;
3972 TRANSACTION2_QPI_RSP *pSMBr = NULL;
3976 struct fea * temp_fea;
3978 __u16 params, byte_count;
3980 cFYI(1, ("In Query All EAs path %s", searchName));
3982 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3987 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3989 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
3990 PATH_MAX, nls_codepage, remap);
3991 name_len++; /* trailing null */
3993 } else { /* BB improve the check for buffer overruns BB */
3994 name_len = strnlen(searchName, PATH_MAX);
3995 name_len++; /* trailing null */
3996 strncpy(pSMB->FileName, searchName, name_len);
3999 params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */ ;
4000 pSMB->TotalDataCount = 0;
4001 pSMB->MaxParameterCount = cpu_to_le16(2);
4002 pSMB->MaxDataCount = cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
4003 pSMB->MaxSetupCount = 0;
4007 pSMB->Reserved2 = 0;
4008 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4009 struct smb_com_transaction2_qpi_req ,InformationLevel) - 4);
4010 pSMB->DataCount = 0;
4011 pSMB->DataOffset = 0;
4012 pSMB->SetupCount = 1;
4013 pSMB->Reserved3 = 0;
4014 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
4015 byte_count = params + 1 /* pad */ ;
4016 pSMB->TotalParameterCount = cpu_to_le16(params);
4017 pSMB->ParameterCount = pSMB->TotalParameterCount;
4018 pSMB->InformationLevel = cpu_to_le16(SMB_INFO_QUERY_ALL_EAS);
4019 pSMB->Reserved4 = 0;
4020 pSMB->hdr.smb_buf_length += byte_count;
4021 pSMB->ByteCount = cpu_to_le16(byte_count);
4023 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4024 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4026 cFYI(1, ("Send error in QueryAllEAs = %d", rc));
4027 } else { /* decode response */
4028 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4030 /* BB also check enough total bytes returned */
4031 /* BB we need to improve the validity checking
4032 of these trans2 responses */
4033 if (rc || (pSMBr->ByteCount < 4))
4034 rc = -EIO; /* bad smb */
4035 /* else if (pFindData){
4036 memcpy((char *) pFindData,
4037 (char *) &pSMBr->hdr.Protocol +
4040 /* check that length of list is not more than bcc */
4041 /* check that each entry does not go beyond length
4043 /* check that each element of each entry does not
4044 go beyond end of list */
4045 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4046 struct fealist * ea_response_data;
4048 /* validate_trans2_offsets() */
4049 /* BB to check if(start of smb + data_offset > &bcc+ bcc)*/
4050 ea_response_data = (struct fealist *)
4051 (((char *) &pSMBr->hdr.Protocol) +
4053 name_len = le32_to_cpu(ea_response_data->list_len);
4054 cFYI(1,("ea length %d", name_len));
4056 /* returned EA size zeroed at top of function */
4057 cFYI(1,("empty EA list returned from server"));
4059 /* account for ea list len */
4061 temp_fea = ea_response_data->list;
4062 temp_ptr = (char *)temp_fea;
4063 while(name_len > 0) {
4067 rc += temp_fea->name_len;
4068 /* account for prefix user. and trailing null */
4070 if(rc<(int)buf_size) {
4071 memcpy(EAData,"user.",5);
4073 memcpy(EAData,temp_ptr,temp_fea->name_len);
4074 EAData+=temp_fea->name_len;
4075 /* null terminate name */
4077 EAData = EAData + 1;
4078 } else if(buf_size == 0) {
4079 /* skip copy - calc size only */
4081 /* stop before overrun buffer */
4085 name_len -= temp_fea->name_len;
4086 temp_ptr += temp_fea->name_len;
4087 /* account for trailing null */
4090 value_len = le16_to_cpu(temp_fea->value_len);
4091 name_len -= value_len;
4092 temp_ptr += value_len;
4093 /* BB check that temp_ptr is still within smb BB*/
4094 /* no trailing null to account for in value len */
4095 /* go on to next EA */
4096 temp_fea = (struct fea *)temp_ptr;
4102 cifs_buf_release(pSMB);
4109 ssize_t CIFSSMBQueryEA(const int xid,struct cifsTconInfo * tcon,
4110 const unsigned char * searchName,const unsigned char * ea_name,
4111 unsigned char * ea_value, size_t buf_size,
4112 const struct nls_table *nls_codepage, int remap)
4114 TRANSACTION2_QPI_REQ *pSMB = NULL;
4115 TRANSACTION2_QPI_RSP *pSMBr = NULL;
4119 struct fea * temp_fea;
4121 __u16 params, byte_count;
4123 cFYI(1, ("In Query EA path %s", searchName));
4125 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4130 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4132 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
4133 PATH_MAX, nls_codepage, remap);
4134 name_len++; /* trailing null */
4136 } else { /* BB improve the check for buffer overruns BB */
4137 name_len = strnlen(searchName, PATH_MAX);
4138 name_len++; /* trailing null */
4139 strncpy(pSMB->FileName, searchName, name_len);
4142 params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */ ;
4143 pSMB->TotalDataCount = 0;
4144 pSMB->MaxParameterCount = cpu_to_le16(2);
4145 pSMB->MaxDataCount = cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
4146 pSMB->MaxSetupCount = 0;
4150 pSMB->Reserved2 = 0;
4151 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4152 struct smb_com_transaction2_qpi_req ,InformationLevel) - 4);
4153 pSMB->DataCount = 0;
4154 pSMB->DataOffset = 0;
4155 pSMB->SetupCount = 1;
4156 pSMB->Reserved3 = 0;
4157 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
4158 byte_count = params + 1 /* pad */ ;
4159 pSMB->TotalParameterCount = cpu_to_le16(params);
4160 pSMB->ParameterCount = pSMB->TotalParameterCount;
4161 pSMB->InformationLevel = cpu_to_le16(SMB_INFO_QUERY_ALL_EAS);
4162 pSMB->Reserved4 = 0;
4163 pSMB->hdr.smb_buf_length += byte_count;
4164 pSMB->ByteCount = cpu_to_le16(byte_count);
4166 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4167 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4169 cFYI(1, ("Send error in Query EA = %d", rc));
4170 } else { /* decode response */
4171 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4173 /* BB also check enough total bytes returned */
4174 /* BB we need to improve the validity checking
4175 of these trans2 responses */
4176 if (rc || (pSMBr->ByteCount < 4))
4177 rc = -EIO; /* bad smb */
4178 /* else if (pFindData){
4179 memcpy((char *) pFindData,
4180 (char *) &pSMBr->hdr.Protocol +
4183 /* check that length of list is not more than bcc */
4184 /* check that each entry does not go beyond length
4186 /* check that each element of each entry does not
4187 go beyond end of list */
4188 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4189 struct fealist * ea_response_data;
4191 /* validate_trans2_offsets() */
4192 /* BB to check if(start of smb + data_offset > &bcc+ bcc)*/
4193 ea_response_data = (struct fealist *)
4194 (((char *) &pSMBr->hdr.Protocol) +
4196 name_len = le32_to_cpu(ea_response_data->list_len);
4197 cFYI(1,("ea length %d", name_len));
4199 /* returned EA size zeroed at top of function */
4200 cFYI(1,("empty EA list returned from server"));
4202 /* account for ea list len */
4204 temp_fea = ea_response_data->list;
4205 temp_ptr = (char *)temp_fea;
4206 /* loop through checking if we have a matching
4207 name and then return the associated value */
4208 while(name_len > 0) {
4212 value_len = le16_to_cpu(temp_fea->value_len);
4213 /* BB validate that value_len falls within SMB,
4214 even though maximum for name_len is 255 */
4215 if(memcmp(temp_fea->name,ea_name,
4216 temp_fea->name_len) == 0) {
4219 /* account for prefix user. and trailing null */
4220 if(rc<=(int)buf_size) {
4222 temp_fea->name+temp_fea->name_len+1,
4224 /* ea values, unlike ea names,
4225 are not null terminated */
4226 } else if(buf_size == 0) {
4227 /* skip copy - calc size only */
4229 /* stop before overrun buffer */
4234 name_len -= temp_fea->name_len;
4235 temp_ptr += temp_fea->name_len;
4236 /* account for trailing null */
4239 name_len -= value_len;
4240 temp_ptr += value_len;
4241 /* no trailing null to account for in value len */
4242 /* go on to next EA */
4243 temp_fea = (struct fea *)temp_ptr;
4249 cifs_buf_release(pSMB);
4257 CIFSSMBSetEA(const int xid, struct cifsTconInfo *tcon, const char *fileName,
4258 const char * ea_name, const void * ea_value,
4259 const __u16 ea_value_len, const struct nls_table *nls_codepage,
4262 struct smb_com_transaction2_spi_req *pSMB = NULL;
4263 struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
4264 struct fealist *parm_data;
4267 int bytes_returned = 0;
4268 __u16 params, param_offset, byte_count, offset, count;
4270 cFYI(1, ("In SetEA"));
4272 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4277 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4279 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
4280 PATH_MAX, nls_codepage, remap);
4281 name_len++; /* trailing null */
4283 } else { /* BB improve the check for buffer overruns BB */
4284 name_len = strnlen(fileName, PATH_MAX);
4285 name_len++; /* trailing null */
4286 strncpy(pSMB->FileName, fileName, name_len);
4289 params = 6 + name_len;
4291 /* done calculating parms using name_len of file name,
4292 now use name_len to calculate length of ea name
4293 we are going to create in the inode xattrs */
4297 name_len = strnlen(ea_name,255);
4299 count = sizeof(*parm_data) + ea_value_len + name_len + 1;
4300 pSMB->MaxParameterCount = cpu_to_le16(2);
4301 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB size from sess */
4302 pSMB->MaxSetupCount = 0;
4306 pSMB->Reserved2 = 0;
4307 param_offset = offsetof(struct smb_com_transaction2_spi_req,
4308 InformationLevel) - 4;
4309 offset = param_offset + params;
4310 pSMB->InformationLevel =
4311 cpu_to_le16(SMB_SET_FILE_EA);
4314 (struct fealist *) (((char *) &pSMB->hdr.Protocol) +
4316 pSMB->ParameterOffset = cpu_to_le16(param_offset);
4317 pSMB->DataOffset = cpu_to_le16(offset);
4318 pSMB->SetupCount = 1;
4319 pSMB->Reserved3 = 0;
4320 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
4321 byte_count = 3 /* pad */ + params + count;
4322 pSMB->DataCount = cpu_to_le16(count);
4323 parm_data->list_len = cpu_to_le32(count);
4324 parm_data->list[0].EA_flags = 0;
4325 /* we checked above that name len is less than 255 */
4326 parm_data->list[0].name_len = (__u8)name_len;;
4327 /* EA names are always ASCII */
4329 strncpy(parm_data->list[0].name,ea_name,name_len);
4330 parm_data->list[0].name[name_len] = 0;
4331 parm_data->list[0].value_len = cpu_to_le16(ea_value_len);
4332 /* caller ensures that ea_value_len is less than 64K but
4333 we need to ensure that it fits within the smb */
4335 /*BB add length check that it would fit in negotiated SMB buffer size BB */
4336 /* if(ea_value_len > buffer_size - 512 (enough for header)) */
4338 memcpy(parm_data->list[0].name+name_len+1,ea_value,ea_value_len);
4340 pSMB->TotalDataCount = pSMB->DataCount;
4341 pSMB->ParameterCount = cpu_to_le16(params);
4342 pSMB->TotalParameterCount = pSMB->ParameterCount;
4343 pSMB->Reserved4 = 0;
4344 pSMB->hdr.smb_buf_length += byte_count;
4345 pSMB->ByteCount = cpu_to_le16(byte_count);
4346 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4347 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4349 cFYI(1, ("SetPathInfo (EA) returned %d", rc));
4352 cifs_buf_release(pSMB);