4 * Copyright (C) International Business Machines Corp., 2002,2005
5 * Author(s): Steve French (sfrench@us.ibm.com)
7 * Contains the routines for constructing the SMB PDUs themselves
9 * This library is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU Lesser General Public License as published
11 * by the Free Software Foundation; either version 2.1 of the License, or
12 * (at your option) any later version.
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
17 * the GNU Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public License
20 * along with this library; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 /* SMB/CIFS PDU handling routines here - except for leftovers in connect.c */
25 /* These are mostly routines that operate on a pathname, or on a tree id */
26 /* (mounted volume), but there are eight handle based routines which must be */
27 /* treated slightly different for reconnection purposes since we never want */
28 /* to reuse a stale file handle and the caller knows the file handle */
31 #include <linux/kernel.h>
32 #include <linux/vfs.h>
33 #include <linux/posix_acl_xattr.h>
34 #include <asm/uaccess.h>
37 #include "cifsproto.h"
38 #include "cifs_unicode.h"
39 #include "cifs_debug.h"
41 #ifdef CONFIG_CIFS_POSIX
46 {CIFS_PROT, "\2NT LM 0.12"},
47 {CIFS_PROT, "\2POSIX 2"},
55 {CIFS_PROT, "\2NT LM 0.12"},
61 /* Mark as invalid, all open files on tree connections since they
62 were closed when session to server was lost */
63 static void mark_open_files_invalid(struct cifsTconInfo * pTcon)
65 struct cifsFileInfo *open_file = NULL;
66 struct list_head * tmp;
67 struct list_head * tmp1;
69 /* list all files open on tree connection and mark them invalid */
70 write_lock(&GlobalSMBSeslock);
71 list_for_each_safe(tmp, tmp1, &pTcon->openFileList) {
72 open_file = list_entry(tmp,struct cifsFileInfo, tlist);
74 open_file->invalidHandle = TRUE;
77 write_unlock(&GlobalSMBSeslock);
78 /* BB Add call to invalidate_inodes(sb) for all superblocks mounted
82 /* If the return code is zero, this function must fill in request_buf pointer */
84 small_smb_init(int smb_command, int wct, struct cifsTconInfo *tcon,
85 void **request_buf /* returned */)
89 /* SMBs NegProt, SessSetup, uLogoff do not have tcon yet so
90 check for tcp and smb session status done differently
91 for those three - in the calling routine */
93 if((tcon->ses) && (tcon->ses->status != CifsExiting) &&
95 struct nls_table *nls_codepage;
96 /* Give Demultiplex thread up to 10 seconds to
97 reconnect, should be greater than cifs socket
98 timeout which is 7 seconds */
99 while(tcon->ses->server->tcpStatus == CifsNeedReconnect) {
100 wait_event_interruptible_timeout(tcon->ses->server->response_q,
101 (tcon->ses->server->tcpStatus == CifsGood), 10 * HZ);
102 if(tcon->ses->server->tcpStatus == CifsNeedReconnect) {
103 /* on "soft" mounts we wait once */
104 if((tcon->retry == FALSE) ||
105 (tcon->ses->status == CifsExiting)) {
106 cFYI(1,("gave up waiting on reconnect in smb_init"));
108 } /* else "hard" mount - keep retrying
109 until process is killed or server
110 comes back on-line */
111 } else /* TCP session is reestablished now */
116 nls_codepage = load_nls_default();
117 /* need to prevent multiple threads trying to
118 simultaneously reconnect the same SMB session */
119 down(&tcon->ses->sesSem);
120 if(tcon->ses->status == CifsNeedReconnect)
121 rc = cifs_setup_session(0, tcon->ses,
123 if(!rc && (tcon->tidStatus == CifsNeedReconnect)) {
124 mark_open_files_invalid(tcon);
125 rc = CIFSTCon(0, tcon->ses, tcon->treeName, tcon
127 up(&tcon->ses->sesSem);
129 atomic_inc(&tconInfoReconnectCount);
131 cFYI(1, ("reconnect tcon rc = %d", rc));
132 /* Removed call to reopen open files here -
133 it is safer (and faster) to reopen files
134 one at a time as needed in read and write */
136 /* Check if handle based operation so we
137 know whether we can continue or not without
138 returning to caller to reset file handle */
139 switch(smb_command) {
140 case SMB_COM_READ_ANDX:
141 case SMB_COM_WRITE_ANDX:
143 case SMB_COM_FIND_CLOSE2:
144 case SMB_COM_LOCKING_ANDX: {
145 unload_nls(nls_codepage);
150 up(&tcon->ses->sesSem);
152 unload_nls(nls_codepage);
161 *request_buf = cifs_small_buf_get();
162 if (*request_buf == NULL) {
163 /* BB should we add a retry in here if not a writepage? */
167 header_assemble((struct smb_hdr *) *request_buf, smb_command, tcon,wct);
169 #ifdef CONFIG_CIFS_STATS
171 atomic_inc(&tcon->num_smbs_sent);
173 #endif /* CONFIG_CIFS_STATS */
177 /* If the return code is zero, this function must fill in request_buf pointer */
179 smb_init(int smb_command, int wct, struct cifsTconInfo *tcon,
180 void **request_buf /* returned */ ,
181 void **response_buf /* returned */ )
185 /* SMBs NegProt, SessSetup, uLogoff do not have tcon yet so
186 check for tcp and smb session status done differently
187 for those three - in the calling routine */
189 if((tcon->ses) && (tcon->ses->status != CifsExiting) &&
190 (tcon->ses->server)){
191 struct nls_table *nls_codepage;
192 /* Give Demultiplex thread up to 10 seconds to
193 reconnect, should be greater than cifs socket
194 timeout which is 7 seconds */
195 while(tcon->ses->server->tcpStatus == CifsNeedReconnect) {
196 wait_event_interruptible_timeout(tcon->ses->server->response_q,
197 (tcon->ses->server->tcpStatus == CifsGood), 10 * HZ);
198 if(tcon->ses->server->tcpStatus ==
200 /* on "soft" mounts we wait once */
201 if((tcon->retry == FALSE) ||
202 (tcon->ses->status == CifsExiting)) {
203 cFYI(1,("gave up waiting on reconnect in smb_init"));
205 } /* else "hard" mount - keep retrying
206 until process is killed or server
208 } else /* TCP session is reestablished now */
213 nls_codepage = load_nls_default();
214 /* need to prevent multiple threads trying to
215 simultaneously reconnect the same SMB session */
216 down(&tcon->ses->sesSem);
217 if(tcon->ses->status == CifsNeedReconnect)
218 rc = cifs_setup_session(0, tcon->ses,
220 if(!rc && (tcon->tidStatus == CifsNeedReconnect)) {
221 mark_open_files_invalid(tcon);
222 rc = CIFSTCon(0, tcon->ses, tcon->treeName,
224 up(&tcon->ses->sesSem);
226 atomic_inc(&tconInfoReconnectCount);
228 cFYI(1, ("reconnect tcon rc = %d", rc));
229 /* Removed call to reopen open files here -
230 it is safer (and faster) to reopen files
231 one at a time as needed in read and write */
233 /* Check if handle based operation so we
234 know whether we can continue or not without
235 returning to caller to reset file handle */
236 switch(smb_command) {
237 case SMB_COM_READ_ANDX:
238 case SMB_COM_WRITE_ANDX:
240 case SMB_COM_FIND_CLOSE2:
241 case SMB_COM_LOCKING_ANDX: {
242 unload_nls(nls_codepage);
247 up(&tcon->ses->sesSem);
249 unload_nls(nls_codepage);
258 *request_buf = cifs_buf_get();
259 if (*request_buf == NULL) {
260 /* BB should we add a retry in here if not a writepage? */
263 /* Although the original thought was we needed the response buf for */
264 /* potential retries of smb operations it turns out we can determine */
265 /* from the mid flags when the request buffer can be resent without */
266 /* having to use a second distinct buffer for the response */
267 *response_buf = *request_buf;
269 header_assemble((struct smb_hdr *) *request_buf, smb_command, tcon,
272 #ifdef CONFIG_CIFS_STATS
274 atomic_inc(&tcon->num_smbs_sent);
276 #endif /* CONFIG_CIFS_STATS */
280 static int validate_t2(struct smb_t2_rsp * pSMB)
286 /* check for plausible wct, bcc and t2 data and parm sizes */
287 /* check for parm and data offset going beyond end of smb */
288 if(pSMB->hdr.WordCount >= 10) {
289 if((le16_to_cpu(pSMB->t2_rsp.ParameterOffset) <= 1024) &&
290 (le16_to_cpu(pSMB->t2_rsp.DataOffset) <= 1024)) {
291 /* check that bcc is at least as big as parms + data */
292 /* check that bcc is less than negotiated smb buffer */
293 total_size = le16_to_cpu(pSMB->t2_rsp.ParameterCount);
294 if(total_size < 512) {
295 total_size+=le16_to_cpu(pSMB->t2_rsp.DataCount);
296 /* BCC le converted in SendReceive */
297 pBCC = (pSMB->hdr.WordCount * 2) +
298 sizeof(struct smb_hdr) +
300 if((total_size <= (*(u16 *)pBCC)) &&
302 CIFSMaxBufSize+MAX_CIFS_HDR_SIZE)) {
309 cifs_dump_mem("Invalid transact2 SMB: ",(char *)pSMB,
310 sizeof(struct smb_t2_rsp) + 16);
314 CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses)
317 NEGOTIATE_RSP *pSMBr;
320 struct TCP_Server_Info * server;
324 server = ses->server;
329 rc = smb_init(SMB_COM_NEGOTIATE, 0, NULL /* no tcon yet */ ,
330 (void **) &pSMB, (void **) &pSMBr);
334 pSMB->hdr.Flags2 |= SMBFLG2_UNICODE;
335 if (extended_security)
336 pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC;
338 count = strlen(protocols[0].name) + 1;
339 strncpy(pSMB->DialectsArray, protocols[0].name, 30);
340 /* null guaranteed to be at end of source and target buffers anyway */
342 pSMB->hdr.smb_buf_length += count;
343 pSMB->ByteCount = cpu_to_le16(count);
345 rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB,
346 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
348 server->secMode = pSMBr->SecurityMode;
349 server->secType = NTLM; /* BB override default for
350 NTLMv2 or kerberos v5 */
351 /* one byte - no need to convert this or EncryptionKeyLen
352 from little endian */
353 server->maxReq = le16_to_cpu(pSMBr->MaxMpxCount);
354 /* probably no need to store and check maxvcs */
356 min(le32_to_cpu(pSMBr->MaxBufferSize),
357 (__u32) CIFSMaxBufSize + MAX_CIFS_HDR_SIZE);
358 server->maxRw = le32_to_cpu(pSMBr->MaxRawSize);
359 cFYI(0, ("Max buf = %d ", ses->server->maxBuf));
360 GETU32(ses->server->sessid) = le32_to_cpu(pSMBr->SessionKey);
361 server->capabilities = le32_to_cpu(pSMBr->Capabilities);
362 server->timeZone = le16_to_cpu(pSMBr->ServerTimeZone);
363 /* BB with UTC do we ever need to be using srvr timezone? */
364 if (pSMBr->EncryptionKeyLength == CIFS_CRYPTO_KEY_SIZE) {
365 memcpy(server->cryptKey, pSMBr->u.EncryptionKey,
366 CIFS_CRYPTO_KEY_SIZE);
367 } else if ((pSMBr->hdr.Flags2 & SMBFLG2_EXT_SEC)
368 && (pSMBr->EncryptionKeyLength == 0)) {
369 /* decode security blob */
373 /* BB might be helpful to save off the domain of server here */
375 if ((pSMBr->hdr.Flags2 & SMBFLG2_EXT_SEC) &&
376 (server->capabilities & CAP_EXTENDED_SECURITY)) {
377 count = pSMBr->ByteCount;
380 else if (count == 16) {
381 server->secType = RawNTLMSSP;
382 if (server->socketUseCount.counter > 1) {
384 (server->server_GUID,
385 pSMBr->u.extended_response.
388 ("UID of server does not match previous connection to same ip address"));
396 memcpy(server->server_GUID,
397 pSMBr->u.extended_response.
400 rc = decode_negTokenInit(pSMBr->u.
406 /* BB Need to fill struct for sessetup here */
413 server->capabilities &= ~CAP_EXTENDED_SECURITY;
414 if(sign_CIFS_PDUs == FALSE) {
415 if(server->secMode & SECMODE_SIGN_REQUIRED)
417 ("Server requires /proc/fs/cifs/PacketSigningEnabled"));
418 server->secMode &= ~(SECMODE_SIGN_ENABLED | SECMODE_SIGN_REQUIRED);
419 } else if(sign_CIFS_PDUs == 1) {
420 if((server->secMode & SECMODE_SIGN_REQUIRED) == 0)
421 server->secMode &= ~(SECMODE_SIGN_ENABLED | SECMODE_SIGN_REQUIRED);
426 cifs_buf_release(pSMB);
431 CIFSSMBTDis(const int xid, struct cifsTconInfo *tcon)
433 struct smb_hdr *smb_buffer;
434 struct smb_hdr *smb_buffer_response; /* BB removeme BB */
438 cFYI(1, ("In tree disconnect"));
440 * If last user of the connection and
441 * connection alive - disconnect it
442 * If this is the last connection on the server session disconnect it
443 * (and inside session disconnect we should check if tcp socket needs
444 * to be freed and kernel thread woken up).
447 down(&tcon->tconSem);
451 atomic_dec(&tcon->useCount);
452 if (atomic_read(&tcon->useCount) > 0) {
457 /* No need to return error on this operation if tid invalidated and
458 closed on server already e.g. due to tcp session crashing */
459 if(tcon->tidStatus == CifsNeedReconnect) {
464 if((tcon->ses == NULL) || (tcon->ses->server == NULL)) {
468 rc = small_smb_init(SMB_COM_TREE_DISCONNECT, 0, tcon,
469 (void **)&smb_buffer);
474 smb_buffer_response = smb_buffer; /* BB removeme BB */
476 rc = SendReceive(xid, tcon->ses, smb_buffer, smb_buffer_response,
479 cFYI(1, ("Tree disconnect failed %d", rc));
482 cifs_small_buf_release(smb_buffer);
485 /* No need to return error on this operation if tid invalidated and
486 closed on server already e.g. due to tcp session crashing */
494 CIFSSMBLogoff(const int xid, struct cifsSesInfo *ses)
496 struct smb_hdr *smb_buffer_response;
497 LOGOFF_ANDX_REQ *pSMB;
501 cFYI(1, ("In SMBLogoff for session disconnect"));
507 atomic_dec(&ses->inUse);
508 if (atomic_read(&ses->inUse) > 0) {
512 rc = small_smb_init(SMB_COM_LOGOFF_ANDX, 2, NULL, (void **)&pSMB);
518 smb_buffer_response = (struct smb_hdr *)pSMB; /* BB removeme BB */
521 if(ses->server->secMode &
522 (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
523 pSMB->hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
526 pSMB->hdr.Uid = ses->Suid;
528 pSMB->AndXCommand = 0xFF;
529 rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB,
530 smb_buffer_response, &length, 0);
532 atomic_dec(&ses->server->socketUseCount);
533 if (atomic_read(&ses->server->socketUseCount) == 0) {
534 spin_lock(&GlobalMid_Lock);
535 ses->server->tcpStatus = CifsExiting;
536 spin_unlock(&GlobalMid_Lock);
541 cifs_small_buf_release(pSMB);
544 /* if session dead then we do not need to do ulogoff,
545 since server closed smb session, no sense reporting
553 CIFSSMBDelFile(const int xid, struct cifsTconInfo *tcon, const char *fileName,
554 const struct nls_table *nls_codepage, int remap)
556 DELETE_FILE_REQ *pSMB = NULL;
557 DELETE_FILE_RSP *pSMBr = NULL;
563 rc = smb_init(SMB_COM_DELETE, 1, tcon, (void **) &pSMB,
568 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
570 cifsConvertToUCS((__le16 *) pSMB->fileName, fileName,
571 PATH_MAX, nls_codepage, remap);
572 name_len++; /* trailing null */
574 } else { /* BB improve check for buffer overruns BB */
575 name_len = strnlen(fileName, PATH_MAX);
576 name_len++; /* trailing null */
577 strncpy(pSMB->fileName, fileName, name_len);
579 pSMB->SearchAttributes =
580 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM);
581 pSMB->BufferFormat = 0x04;
582 pSMB->hdr.smb_buf_length += name_len + 1;
583 pSMB->ByteCount = cpu_to_le16(name_len + 1);
584 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
585 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
587 cFYI(1, ("Error in RMFile = %d", rc));
589 #ifdef CONFIG_CIFS_STATS
591 atomic_inc(&tcon->num_deletes);
595 cifs_buf_release(pSMB);
603 CIFSSMBRmDir(const int xid, struct cifsTconInfo *tcon, const char *dirName,
604 const struct nls_table *nls_codepage, int remap)
606 DELETE_DIRECTORY_REQ *pSMB = NULL;
607 DELETE_DIRECTORY_RSP *pSMBr = NULL;
612 cFYI(1, ("In CIFSSMBRmDir"));
614 rc = smb_init(SMB_COM_DELETE_DIRECTORY, 0, tcon, (void **) &pSMB,
619 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
620 name_len = cifsConvertToUCS((__le16 *) pSMB->DirName, dirName,
621 PATH_MAX, nls_codepage, remap);
622 name_len++; /* trailing null */
624 } else { /* BB improve check for buffer overruns BB */
625 name_len = strnlen(dirName, PATH_MAX);
626 name_len++; /* trailing null */
627 strncpy(pSMB->DirName, dirName, name_len);
630 pSMB->BufferFormat = 0x04;
631 pSMB->hdr.smb_buf_length += name_len + 1;
632 pSMB->ByteCount = cpu_to_le16(name_len + 1);
633 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
634 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
636 cFYI(1, ("Error in RMDir = %d", rc));
638 #ifdef CONFIG_CIFS_STATS
640 atomic_inc(&tcon->num_rmdirs);
644 cifs_buf_release(pSMB);
651 CIFSSMBMkDir(const int xid, struct cifsTconInfo *tcon,
652 const char *name, const struct nls_table *nls_codepage, int remap)
655 CREATE_DIRECTORY_REQ *pSMB = NULL;
656 CREATE_DIRECTORY_RSP *pSMBr = NULL;
660 cFYI(1, ("In CIFSSMBMkDir"));
662 rc = smb_init(SMB_COM_CREATE_DIRECTORY, 0, tcon, (void **) &pSMB,
667 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
668 name_len = cifsConvertToUCS((__le16 *) pSMB->DirName, name,
669 PATH_MAX, nls_codepage, remap);
670 name_len++; /* trailing null */
672 } else { /* BB improve check for buffer overruns BB */
673 name_len = strnlen(name, PATH_MAX);
674 name_len++; /* trailing null */
675 strncpy(pSMB->DirName, name, name_len);
678 pSMB->BufferFormat = 0x04;
679 pSMB->hdr.smb_buf_length += name_len + 1;
680 pSMB->ByteCount = cpu_to_le16(name_len + 1);
681 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
682 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
684 cFYI(1, ("Error in Mkdir = %d", rc));
686 #ifdef CONFIG_CIFS_STATS
688 atomic_inc(&tcon->num_mkdirs);
691 cifs_buf_release(pSMB);
698 CIFSSMBOpen(const int xid, struct cifsTconInfo *tcon,
699 const char *fileName, const int openDisposition,
700 const int access_flags, const int create_options, __u16 * netfid,
701 int *pOplock, FILE_ALL_INFO * pfile_info,
702 const struct nls_table *nls_codepage, int remap)
705 OPEN_REQ *pSMB = NULL;
706 OPEN_RSP *pSMBr = NULL;
712 rc = smb_init(SMB_COM_NT_CREATE_ANDX, 24, tcon, (void **) &pSMB,
717 pSMB->AndXCommand = 0xFF; /* none */
719 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
720 count = 1; /* account for one byte pad to word boundary */
722 cifsConvertToUCS((__le16 *) (pSMB->fileName + 1),
723 fileName, PATH_MAX, nls_codepage, remap);
724 name_len++; /* trailing null */
726 pSMB->NameLength = cpu_to_le16(name_len);
727 } else { /* BB improve check for buffer overruns BB */
728 count = 0; /* no pad */
729 name_len = strnlen(fileName, PATH_MAX);
730 name_len++; /* trailing null */
731 pSMB->NameLength = cpu_to_le16(name_len);
732 strncpy(pSMB->fileName, fileName, name_len);
734 if (*pOplock & REQ_OPLOCK)
735 pSMB->OpenFlags = cpu_to_le32(REQ_OPLOCK);
736 else if (*pOplock & REQ_BATCHOPLOCK) {
737 pSMB->OpenFlags = cpu_to_le32(REQ_BATCHOPLOCK);
739 pSMB->DesiredAccess = cpu_to_le32(access_flags);
740 pSMB->AllocationSize = 0;
741 pSMB->FileAttributes = cpu_to_le32(ATTR_NORMAL);
742 /* XP does not handle ATTR_POSIX_SEMANTICS */
743 /* but it helps speed up case sensitive checks for other
744 servers such as Samba */
745 if (tcon->ses->capabilities & CAP_UNIX)
746 pSMB->FileAttributes |= cpu_to_le32(ATTR_POSIX_SEMANTICS);
748 /* if ((omode & S_IWUGO) == 0)
749 pSMB->FileAttributes |= cpu_to_le32(ATTR_READONLY);*/
750 /* Above line causes problems due to vfs splitting create into two
751 pieces - need to set mode after file created not while it is
753 pSMB->ShareAccess = cpu_to_le32(FILE_SHARE_ALL);
754 pSMB->CreateDisposition = cpu_to_le32(openDisposition);
755 pSMB->CreateOptions = cpu_to_le32(create_options);
756 /* BB Expirement with various impersonation levels and verify */
757 pSMB->ImpersonationLevel = cpu_to_le32(SECURITY_IMPERSONATION);
758 pSMB->SecurityFlags =
759 SECURITY_CONTEXT_TRACKING | SECURITY_EFFECTIVE_ONLY;
762 pSMB->hdr.smb_buf_length += count;
764 pSMB->ByteCount = cpu_to_le16(count);
765 /* long_op set to 1 to allow for oplock break timeouts */
766 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
767 (struct smb_hdr *) pSMBr, &bytes_returned, 1);
769 cFYI(1, ("Error in Open = %d", rc));
771 *pOplock = pSMBr->OplockLevel; /* 1 byte no need to le_to_cpu */
772 *netfid = pSMBr->Fid; /* cifs fid stays in le */
773 /* Let caller know file was created so we can set the mode. */
774 /* Do we care about the CreateAction in any other cases? */
775 if(cpu_to_le32(FILE_CREATE) == pSMBr->CreateAction)
776 *pOplock |= CIFS_CREATE_ACTION;
778 memcpy((char *)pfile_info,(char *)&pSMBr->CreationTime,
779 36 /* CreationTime to Attributes */);
780 /* the file_info buf is endian converted by caller */
781 pfile_info->AllocationSize = pSMBr->AllocationSize;
782 pfile_info->EndOfFile = pSMBr->EndOfFile;
783 pfile_info->NumberOfLinks = cpu_to_le32(1);
786 #ifdef CONFIG_CIFS_STATS
787 atomic_inc(&tcon->num_opens);
790 cifs_buf_release(pSMB);
796 /* If no buffer passed in, then caller wants to do the copy
797 as in the case of readpages so the SMB buffer must be
798 freed by the caller */
801 CIFSSMBRead(const int xid, struct cifsTconInfo *tcon,
802 const int netfid, const unsigned int count,
803 const __u64 lseek, unsigned int *nbytes, char **buf)
806 READ_REQ *pSMB = NULL;
807 READ_RSP *pSMBr = NULL;
808 char *pReadData = NULL;
811 cFYI(1,("Reading %d bytes on fid %d",count,netfid));
814 rc = smb_init(SMB_COM_READ_ANDX, 12, tcon, (void **) &pSMB,
819 /* tcon and ses pointer are checked in smb_init */
820 if (tcon->ses->server == NULL)
821 return -ECONNABORTED;
823 pSMB->AndXCommand = 0xFF; /* none */
825 pSMB->OffsetLow = cpu_to_le32(lseek & 0xFFFFFFFF);
826 pSMB->OffsetHigh = cpu_to_le32(lseek >> 32);
828 pSMB->MaxCount = cpu_to_le16(count & 0xFFFF);
829 pSMB->MaxCountHigh = cpu_to_le32(count >> 16);
830 pSMB->ByteCount = 0; /* no need to do le conversion since it is 0 */
832 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
833 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
835 cERROR(1, ("Send error in read = %d", rc));
837 int data_length = le16_to_cpu(pSMBr->DataLengthHigh);
838 data_length = data_length << 16;
839 data_length += le16_to_cpu(pSMBr->DataLength);
840 *nbytes = data_length;
842 /*check that DataLength would not go beyond end of SMB */
843 if ((data_length > CIFSMaxBufSize)
844 || (data_length > count)) {
845 cFYI(1,("bad length %d for count %d",data_length,count));
850 (char *) (&pSMBr->hdr.Protocol) +
851 le16_to_cpu(pSMBr->DataOffset);
852 /* if(rc = copy_to_user(buf, pReadData, data_length)) {
853 cERROR(1,("Faulting on read rc = %d",rc));
855 }*/ /* can not use copy_to_user when using page cache*/
857 memcpy(*buf,pReadData,data_length);
861 cifs_buf_release(pSMB);
865 /* Note: On -EAGAIN error only caller can retry on handle based calls
866 since file handle passed in no longer valid */
871 CIFSSMBWrite(const int xid, struct cifsTconInfo *tcon,
872 const int netfid, const unsigned int count,
873 const __u64 offset, unsigned int *nbytes, const char *buf,
874 const char __user * ubuf, const int long_op)
877 WRITE_REQ *pSMB = NULL;
878 WRITE_RSP *pSMBr = NULL;
883 /* cFYI(1,("write at %lld %d bytes",offset,count));*/
884 rc = smb_init(SMB_COM_WRITE_ANDX, 14, tcon, (void **) &pSMB,
888 /* tcon and ses pointer are checked in smb_init */
889 if (tcon->ses->server == NULL)
890 return -ECONNABORTED;
892 pSMB->AndXCommand = 0xFF; /* none */
894 pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF);
895 pSMB->OffsetHigh = cpu_to_le32(offset >> 32);
896 pSMB->Reserved = 0xFFFFFFFF;
900 /* Can increase buffer size if buffer is big enough in some cases - ie we
901 can send more if LARGE_WRITE_X capability returned by the server and if
902 our buffer is big enough or if we convert to iovecs on socket writes
903 and eliminate the copy to the CIFS buffer */
904 if(tcon->ses->capabilities & CAP_LARGE_WRITE_X) {
905 bytes_sent = min_t(const unsigned int, CIFSMaxBufSize, count);
907 bytes_sent = (tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE)
911 if (bytes_sent > count)
914 cpu_to_le16(offsetof(struct smb_com_write_req,Data) - 4);
916 memcpy(pSMB->Data,buf,bytes_sent);
918 if(copy_from_user(pSMB->Data,ubuf,bytes_sent)) {
919 cifs_buf_release(pSMB);
924 cifs_buf_release(pSMB);
928 byte_count = bytes_sent + 1 /* pad */ ; /* BB fix this for sends > 64K */
929 pSMB->DataLengthLow = cpu_to_le16(bytes_sent & 0xFFFF);
930 pSMB->DataLengthHigh = cpu_to_le16(bytes_sent >> 16);
931 pSMB->hdr.smb_buf_length += bytes_sent+1;
932 pSMB->ByteCount = cpu_to_le16(byte_count);
934 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
935 (struct smb_hdr *) pSMBr, &bytes_returned, long_op);
937 cFYI(1, ("Send error in write = %d", rc));
940 *nbytes = le16_to_cpu(pSMBr->CountHigh);
941 *nbytes = (*nbytes) << 16;
942 *nbytes += le16_to_cpu(pSMBr->Count);
945 cifs_buf_release(pSMB);
947 /* Note: On -EAGAIN error only caller can retry on handle based calls
948 since file handle passed in no longer valid */
953 #ifdef CONFIG_CIFS_EXPERIMENTAL
955 CIFSSMBWrite2(const int xid, struct cifsTconInfo *tcon,
956 const int netfid, const unsigned int count,
957 const __u64 offset, unsigned int *nbytes, const char *buf,
961 WRITE_REQ *pSMB = NULL;
967 cFYI(1,("write2 at %lld %d bytes",offset,count)); /* BB removeme BB */
968 rc = small_smb_init(SMB_COM_WRITE_ANDX, 14, tcon, (void **) &pSMB);
971 /* tcon and ses pointer are checked in smb_init */
972 if (tcon->ses->server == NULL)
973 return -ECONNABORTED;
975 pSMB->AndXCommand = 0xFF; /* none */
977 pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF);
978 pSMB->OffsetHigh = cpu_to_le32(offset >> 32);
979 pSMB->Reserved = 0xFFFFFFFF;
983 /* Can increase buffer size if buffer is big enough in some cases - ie
984 can send more if LARGE_WRITE_X capability returned by the server and if
985 our buffer is big enough or if we convert to iovecs on socket writes
986 and eliminate the copy to the CIFS buffer */
987 if(tcon->ses->capabilities & CAP_LARGE_WRITE_X) {
988 bytes_sent = min_t(const unsigned int, CIFSMaxBufSize, count);
990 bytes_sent = (tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE)
994 if (bytes_sent > count)
997 cpu_to_le16(offsetof(struct smb_com_write_req,Data) - 4);
999 byte_count = bytes_sent + 1 /* pad */ ; /* BB fix this for sends > 64K */
1000 pSMB->DataLengthLow = cpu_to_le16(bytes_sent & 0xFFFF);
1001 pSMB->DataLengthHigh = cpu_to_le16(bytes_sent >> 16);
1002 smb_hdr_len = pSMB->hdr.smb_buf_length + 1; /* hdr + 1 byte pad */
1003 pSMB->hdr.smb_buf_length += bytes_sent+1;
1004 pSMB->ByteCount = cpu_to_le16(byte_count);
1006 rc = SendReceive2(xid, tcon->ses, (struct smb_hdr *) pSMB, smb_hdr_len,
1007 buf, bytes_sent, &bytes_returned, long_op);
1009 cFYI(1, ("Send error in write = %d", rc));
1012 WRITE_RSP * pSMBr = (WRITE_RSP *)pSMB;
1013 *nbytes = le16_to_cpu(pSMBr->CountHigh);
1014 *nbytes = (*nbytes) << 16;
1015 *nbytes += le16_to_cpu(pSMBr->Count);
1018 cifs_small_buf_release(pSMB);
1020 /* Note: On -EAGAIN error only caller can retry on handle based calls
1021 since file handle passed in no longer valid */
1027 #endif /* CIFS_EXPERIMENTAL */
1030 CIFSSMBLock(const int xid, struct cifsTconInfo *tcon,
1031 const __u16 smb_file_id, const __u64 len,
1032 const __u64 offset, const __u32 numUnlock,
1033 const __u32 numLock, const __u8 lockType, const int waitFlag)
1036 LOCK_REQ *pSMB = NULL;
1037 LOCK_RSP *pSMBr = NULL;
1042 cFYI(1, ("In CIFSSMBLock - timeout %d numLock %d",waitFlag,numLock));
1043 rc = small_smb_init(SMB_COM_LOCKING_ANDX, 8, tcon, (void **) &pSMB);
1048 pSMBr = (LOCK_RSP *)pSMB; /* BB removeme BB */
1050 if(lockType == LOCKING_ANDX_OPLOCK_RELEASE) {
1051 timeout = -1; /* no response expected */
1053 } else if (waitFlag == TRUE) {
1054 timeout = 3; /* blocking operation, no timeout */
1055 pSMB->Timeout = cpu_to_le32(-1);/* blocking - do not time out */
1060 pSMB->NumberOfLocks = cpu_to_le16(numLock);
1061 pSMB->NumberOfUnlocks = cpu_to_le16(numUnlock);
1062 pSMB->LockType = lockType;
1063 pSMB->AndXCommand = 0xFF; /* none */
1064 pSMB->Fid = smb_file_id; /* netfid stays le */
1066 if((numLock != 0) || (numUnlock != 0)) {
1067 pSMB->Locks[0].Pid = cpu_to_le16(current->tgid);
1068 /* BB where to store pid high? */
1069 pSMB->Locks[0].LengthLow = cpu_to_le32((u32)len);
1070 pSMB->Locks[0].LengthHigh = cpu_to_le32((u32)(len>>32));
1071 pSMB->Locks[0].OffsetLow = cpu_to_le32((u32)offset);
1072 pSMB->Locks[0].OffsetHigh = cpu_to_le32((u32)(offset>>32));
1073 count = sizeof(LOCKING_ANDX_RANGE);
1078 pSMB->hdr.smb_buf_length += count;
1079 pSMB->ByteCount = cpu_to_le16(count);
1081 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1082 (struct smb_hdr *) pSMBr, &bytes_returned, timeout);
1085 cFYI(1, ("Send error in Lock = %d", rc));
1087 cifs_small_buf_release(pSMB);
1089 /* Note: On -EAGAIN error only caller can retry on handle based calls
1090 since file handle passed in no longer valid */
1095 CIFSSMBClose(const int xid, struct cifsTconInfo *tcon, int smb_file_id)
1098 CLOSE_REQ *pSMB = NULL;
1099 CLOSE_RSP *pSMBr = NULL;
1101 cFYI(1, ("In CIFSSMBClose"));
1103 /* do not retry on dead session on close */
1104 rc = small_smb_init(SMB_COM_CLOSE, 3, tcon, (void **) &pSMB);
1110 pSMBr = (CLOSE_RSP *)pSMB; /* BB removeme BB */
1112 pSMB->FileID = (__u16) smb_file_id;
1113 pSMB->LastWriteTime = 0;
1114 pSMB->ByteCount = 0;
1115 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1116 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1119 /* EINTR is expected when user ctl-c to kill app */
1120 cERROR(1, ("Send error in Close = %d", rc));
1124 cifs_small_buf_release(pSMB);
1126 /* Since session is dead, file will be closed on server already */
1134 CIFSSMBRename(const int xid, struct cifsTconInfo *tcon,
1135 const char *fromName, const char *toName,
1136 const struct nls_table *nls_codepage, int remap)
1139 RENAME_REQ *pSMB = NULL;
1140 RENAME_RSP *pSMBr = NULL;
1142 int name_len, name_len2;
1145 cFYI(1, ("In CIFSSMBRename"));
1147 rc = smb_init(SMB_COM_RENAME, 1, tcon, (void **) &pSMB,
1152 pSMB->BufferFormat = 0x04;
1153 pSMB->SearchAttributes =
1154 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
1157 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1159 cifsConvertToUCS((__le16 *) pSMB->OldFileName, fromName,
1160 PATH_MAX, nls_codepage, remap);
1161 name_len++; /* trailing null */
1163 pSMB->OldFileName[name_len] = 0x04; /* pad */
1164 /* protocol requires ASCII signature byte on Unicode string */
1165 pSMB->OldFileName[name_len + 1] = 0x00;
1167 cifsConvertToUCS((__le16 *) &pSMB->OldFileName[name_len + 2],
1168 toName, PATH_MAX, nls_codepage, remap);
1169 name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
1170 name_len2 *= 2; /* convert to bytes */
1171 } else { /* BB improve the check for buffer overruns BB */
1172 name_len = strnlen(fromName, PATH_MAX);
1173 name_len++; /* trailing null */
1174 strncpy(pSMB->OldFileName, fromName, name_len);
1175 name_len2 = strnlen(toName, PATH_MAX);
1176 name_len2++; /* trailing null */
1177 pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */
1178 strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2);
1179 name_len2++; /* trailing null */
1180 name_len2++; /* signature byte */
1183 count = 1 /* 1st signature byte */ + name_len + name_len2;
1184 pSMB->hdr.smb_buf_length += count;
1185 pSMB->ByteCount = cpu_to_le16(count);
1187 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1188 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1190 cFYI(1, ("Send error in rename = %d", rc));
1193 #ifdef CONFIG_CIFS_STATS
1195 atomic_inc(&tcon->num_renames);
1199 cifs_buf_release(pSMB);
1207 int CIFSSMBRenameOpenFile(const int xid,struct cifsTconInfo *pTcon,
1208 int netfid, char * target_name,
1209 const struct nls_table * nls_codepage, int remap)
1211 struct smb_com_transaction2_sfi_req *pSMB = NULL;
1212 struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
1213 struct set_file_rename * rename_info;
1215 char dummy_string[30];
1217 int bytes_returned = 0;
1219 __u16 params, param_offset, offset, count, byte_count;
1221 cFYI(1, ("Rename to File by handle"));
1222 rc = smb_init(SMB_COM_TRANSACTION2, 15, pTcon, (void **) &pSMB,
1228 pSMB->MaxSetupCount = 0;
1232 pSMB->Reserved2 = 0;
1233 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
1234 offset = param_offset + params;
1236 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
1237 rename_info = (struct set_file_rename *) data_offset;
1238 pSMB->MaxParameterCount = cpu_to_le16(2);
1239 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB PDU from sess */
1240 pSMB->SetupCount = 1;
1241 pSMB->Reserved3 = 0;
1242 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
1243 byte_count = 3 /* pad */ + params;
1244 pSMB->ParameterCount = cpu_to_le16(params);
1245 pSMB->TotalParameterCount = pSMB->ParameterCount;
1246 pSMB->ParameterOffset = cpu_to_le16(param_offset);
1247 pSMB->DataOffset = cpu_to_le16(offset);
1248 /* construct random name ".cifs_tmp<inodenum><mid>" */
1249 rename_info->overwrite = cpu_to_le32(1);
1250 rename_info->root_fid = 0;
1251 /* unicode only call */
1252 if(target_name == NULL) {
1253 sprintf(dummy_string,"cifs%x",pSMB->hdr.Mid);
1254 len_of_str = cifsConvertToUCS((__le16 *)rename_info->target_name,
1255 dummy_string, 24, nls_codepage, remap);
1257 len_of_str = cifsConvertToUCS((__le16 *)rename_info->target_name,
1258 target_name, PATH_MAX, nls_codepage, remap);
1260 rename_info->target_name_len = cpu_to_le32(2 * len_of_str);
1261 count = 12 /* sizeof(struct set_file_rename) */ + (2 * len_of_str) + 2;
1262 byte_count += count;
1263 pSMB->DataCount = cpu_to_le16(count);
1264 pSMB->TotalDataCount = pSMB->DataCount;
1266 pSMB->InformationLevel =
1267 cpu_to_le16(SMB_SET_FILE_RENAME_INFORMATION);
1268 pSMB->Reserved4 = 0;
1269 pSMB->hdr.smb_buf_length += byte_count;
1270 pSMB->ByteCount = cpu_to_le16(byte_count);
1271 rc = SendReceive(xid, pTcon->ses, (struct smb_hdr *) pSMB,
1272 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1274 cFYI(1,("Send error in Rename (by file handle) = %d", rc));
1276 #ifdef CONFIG_CIFS_STATS
1278 atomic_inc(&pTcon->num_t2renames);
1281 cifs_buf_release(pSMB);
1283 /* Note: On -EAGAIN error only caller can retry on handle based calls
1284 since file handle passed in no longer valid */
1290 CIFSSMBCopy(const int xid, struct cifsTconInfo *tcon, const char * fromName,
1291 const __u16 target_tid, const char *toName, const int flags,
1292 const struct nls_table *nls_codepage, int remap)
1295 COPY_REQ *pSMB = NULL;
1296 COPY_RSP *pSMBr = NULL;
1298 int name_len, name_len2;
1301 cFYI(1, ("In CIFSSMBCopy"));
1303 rc = smb_init(SMB_COM_COPY, 1, tcon, (void **) &pSMB,
1308 pSMB->BufferFormat = 0x04;
1309 pSMB->Tid2 = target_tid;
1311 pSMB->Flags = cpu_to_le16(flags & COPY_TREE);
1313 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1314 name_len = cifsConvertToUCS((__le16 *) pSMB->OldFileName,
1315 fromName, PATH_MAX, nls_codepage,
1317 name_len++; /* trailing null */
1319 pSMB->OldFileName[name_len] = 0x04; /* pad */
1320 /* protocol requires ASCII signature byte on Unicode string */
1321 pSMB->OldFileName[name_len + 1] = 0x00;
1322 name_len2 = cifsConvertToUCS((__le16 *)&pSMB->OldFileName[name_len + 2],
1323 toName, PATH_MAX, nls_codepage, remap);
1324 name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
1325 name_len2 *= 2; /* convert to bytes */
1326 } else { /* BB improve the check for buffer overruns BB */
1327 name_len = strnlen(fromName, PATH_MAX);
1328 name_len++; /* trailing null */
1329 strncpy(pSMB->OldFileName, fromName, name_len);
1330 name_len2 = strnlen(toName, PATH_MAX);
1331 name_len2++; /* trailing null */
1332 pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */
1333 strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2);
1334 name_len2++; /* trailing null */
1335 name_len2++; /* signature byte */
1338 count = 1 /* 1st signature byte */ + name_len + name_len2;
1339 pSMB->hdr.smb_buf_length += count;
1340 pSMB->ByteCount = cpu_to_le16(count);
1342 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1343 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1345 cFYI(1, ("Send error in copy = %d with %d files copied",
1346 rc, le16_to_cpu(pSMBr->CopyCount)));
1349 cifs_buf_release(pSMB);
1358 CIFSUnixCreateSymLink(const int xid, struct cifsTconInfo *tcon,
1359 const char *fromName, const char *toName,
1360 const struct nls_table *nls_codepage)
1362 TRANSACTION2_SPI_REQ *pSMB = NULL;
1363 TRANSACTION2_SPI_RSP *pSMBr = NULL;
1366 int name_len_target;
1368 int bytes_returned = 0;
1369 __u16 params, param_offset, offset, byte_count;
1371 cFYI(1, ("In Symlink Unix style"));
1373 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
1378 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1380 cifs_strtoUCS((wchar_t *) pSMB->FileName, fromName, PATH_MAX
1381 /* find define for this maxpathcomponent */
1383 name_len++; /* trailing null */
1386 } else { /* BB improve the check for buffer overruns BB */
1387 name_len = strnlen(fromName, PATH_MAX);
1388 name_len++; /* trailing null */
1389 strncpy(pSMB->FileName, fromName, name_len);
1391 params = 6 + name_len;
1392 pSMB->MaxSetupCount = 0;
1396 pSMB->Reserved2 = 0;
1397 param_offset = offsetof(struct smb_com_transaction2_spi_req,
1398 InformationLevel) - 4;
1399 offset = param_offset + params;
1401 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
1402 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1404 cifs_strtoUCS((wchar_t *) data_offset, toName, PATH_MAX
1405 /* find define for this maxpathcomponent */
1407 name_len_target++; /* trailing null */
1408 name_len_target *= 2;
1409 } else { /* BB improve the check for buffer overruns BB */
1410 name_len_target = strnlen(toName, PATH_MAX);
1411 name_len_target++; /* trailing null */
1412 strncpy(data_offset, toName, name_len_target);
1415 pSMB->MaxParameterCount = cpu_to_le16(2);
1416 /* BB find exact max on data count below from sess */
1417 pSMB->MaxDataCount = cpu_to_le16(1000);
1418 pSMB->SetupCount = 1;
1419 pSMB->Reserved3 = 0;
1420 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
1421 byte_count = 3 /* pad */ + params + name_len_target;
1422 pSMB->DataCount = cpu_to_le16(name_len_target);
1423 pSMB->ParameterCount = cpu_to_le16(params);
1424 pSMB->TotalDataCount = pSMB->DataCount;
1425 pSMB->TotalParameterCount = pSMB->ParameterCount;
1426 pSMB->ParameterOffset = cpu_to_le16(param_offset);
1427 pSMB->DataOffset = cpu_to_le16(offset);
1428 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_LINK);
1429 pSMB->Reserved4 = 0;
1430 pSMB->hdr.smb_buf_length += byte_count;
1431 pSMB->ByteCount = cpu_to_le16(byte_count);
1432 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1433 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1436 ("Send error in SetPathInfo (create symlink) = %d",
1441 cifs_buf_release(pSMB);
1444 goto createSymLinkRetry;
1450 CIFSUnixCreateHardLink(const int xid, struct cifsTconInfo *tcon,
1451 const char *fromName, const char *toName,
1452 const struct nls_table *nls_codepage, int remap)
1454 TRANSACTION2_SPI_REQ *pSMB = NULL;
1455 TRANSACTION2_SPI_RSP *pSMBr = NULL;
1458 int name_len_target;
1460 int bytes_returned = 0;
1461 __u16 params, param_offset, offset, byte_count;
1463 cFYI(1, ("In Create Hard link Unix style"));
1464 createHardLinkRetry:
1465 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
1470 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1471 name_len = cifsConvertToUCS((__le16 *) pSMB->FileName, toName,
1472 PATH_MAX, nls_codepage, remap);
1473 name_len++; /* trailing null */
1476 } else { /* BB improve the check for buffer overruns BB */
1477 name_len = strnlen(toName, PATH_MAX);
1478 name_len++; /* trailing null */
1479 strncpy(pSMB->FileName, toName, name_len);
1481 params = 6 + name_len;
1482 pSMB->MaxSetupCount = 0;
1486 pSMB->Reserved2 = 0;
1487 param_offset = offsetof(struct smb_com_transaction2_spi_req,
1488 InformationLevel) - 4;
1489 offset = param_offset + params;
1491 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
1492 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1494 cifsConvertToUCS((__le16 *) data_offset, fromName, PATH_MAX,
1495 nls_codepage, remap);
1496 name_len_target++; /* trailing null */
1497 name_len_target *= 2;
1498 } else { /* BB improve the check for buffer overruns BB */
1499 name_len_target = strnlen(fromName, PATH_MAX);
1500 name_len_target++; /* trailing null */
1501 strncpy(data_offset, fromName, name_len_target);
1504 pSMB->MaxParameterCount = cpu_to_le16(2);
1505 /* BB find exact max on data count below from sess*/
1506 pSMB->MaxDataCount = cpu_to_le16(1000);
1507 pSMB->SetupCount = 1;
1508 pSMB->Reserved3 = 0;
1509 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
1510 byte_count = 3 /* pad */ + params + name_len_target;
1511 pSMB->ParameterCount = cpu_to_le16(params);
1512 pSMB->TotalParameterCount = pSMB->ParameterCount;
1513 pSMB->DataCount = cpu_to_le16(name_len_target);
1514 pSMB->TotalDataCount = pSMB->DataCount;
1515 pSMB->ParameterOffset = cpu_to_le16(param_offset);
1516 pSMB->DataOffset = cpu_to_le16(offset);
1517 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_HLINK);
1518 pSMB->Reserved4 = 0;
1519 pSMB->hdr.smb_buf_length += byte_count;
1520 pSMB->ByteCount = cpu_to_le16(byte_count);
1521 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1522 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1524 cFYI(1, ("Send error in SetPathInfo (hard link) = %d", rc));
1527 cifs_buf_release(pSMB);
1529 goto createHardLinkRetry;
1535 CIFSCreateHardLink(const int xid, struct cifsTconInfo *tcon,
1536 const char *fromName, const char *toName,
1537 const struct nls_table *nls_codepage, int remap)
1540 NT_RENAME_REQ *pSMB = NULL;
1541 RENAME_RSP *pSMBr = NULL;
1543 int name_len, name_len2;
1546 cFYI(1, ("In CIFSCreateHardLink"));
1547 winCreateHardLinkRetry:
1549 rc = smb_init(SMB_COM_NT_RENAME, 4, tcon, (void **) &pSMB,
1554 pSMB->SearchAttributes =
1555 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
1557 pSMB->Flags = cpu_to_le16(CREATE_HARD_LINK);
1558 pSMB->ClusterCount = 0;
1560 pSMB->BufferFormat = 0x04;
1562 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1564 cifsConvertToUCS((__le16 *) pSMB->OldFileName, fromName,
1565 PATH_MAX, nls_codepage, remap);
1566 name_len++; /* trailing null */
1568 pSMB->OldFileName[name_len] = 0; /* pad */
1569 pSMB->OldFileName[name_len + 1] = 0x04;
1571 cifsConvertToUCS((__le16 *)&pSMB->OldFileName[name_len + 2],
1572 toName, PATH_MAX, nls_codepage, remap);
1573 name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
1574 name_len2 *= 2; /* convert to bytes */
1575 } else { /* BB improve the check for buffer overruns BB */
1576 name_len = strnlen(fromName, PATH_MAX);
1577 name_len++; /* trailing null */
1578 strncpy(pSMB->OldFileName, fromName, name_len);
1579 name_len2 = strnlen(toName, PATH_MAX);
1580 name_len2++; /* trailing null */
1581 pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */
1582 strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2);
1583 name_len2++; /* trailing null */
1584 name_len2++; /* signature byte */
1587 count = 1 /* string type byte */ + name_len + name_len2;
1588 pSMB->hdr.smb_buf_length += count;
1589 pSMB->ByteCount = cpu_to_le16(count);
1591 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1592 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1594 cFYI(1, ("Send error in hard link (NT rename) = %d", rc));
1596 cifs_buf_release(pSMB);
1598 goto winCreateHardLinkRetry;
1604 CIFSSMBUnixQuerySymLink(const int xid, struct cifsTconInfo *tcon,
1605 const unsigned char *searchName,
1606 char *symlinkinfo, const int buflen,
1607 const struct nls_table *nls_codepage)
1609 /* SMB_QUERY_FILE_UNIX_LINK */
1610 TRANSACTION2_QPI_REQ *pSMB = NULL;
1611 TRANSACTION2_QPI_RSP *pSMBr = NULL;
1615 __u16 params, byte_count;
1617 cFYI(1, ("In QPathSymLinkInfo (Unix) for path %s", searchName));
1620 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
1625 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1627 cifs_strtoUCS((wchar_t *) pSMB->FileName, searchName, PATH_MAX
1628 /* find define for this maxpathcomponent */
1630 name_len++; /* trailing null */
1632 } else { /* BB improve the check for buffer overruns BB */
1633 name_len = strnlen(searchName, PATH_MAX);
1634 name_len++; /* trailing null */
1635 strncpy(pSMB->FileName, searchName, name_len);
1638 params = 2 /* level */ + 4 /* rsrvd */ + name_len /* incl null */ ;
1639 pSMB->TotalDataCount = 0;
1640 pSMB->MaxParameterCount = cpu_to_le16(2);
1641 /* BB find exact max data count below from sess structure BB */
1642 pSMB->MaxDataCount = cpu_to_le16(4000);
1643 pSMB->MaxSetupCount = 0;
1647 pSMB->Reserved2 = 0;
1648 pSMB->ParameterOffset = cpu_to_le16(offsetof(
1649 struct smb_com_transaction2_qpi_req ,InformationLevel) - 4);
1650 pSMB->DataCount = 0;
1651 pSMB->DataOffset = 0;
1652 pSMB->SetupCount = 1;
1653 pSMB->Reserved3 = 0;
1654 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
1655 byte_count = params + 1 /* pad */ ;
1656 pSMB->TotalParameterCount = cpu_to_le16(params);
1657 pSMB->ParameterCount = pSMB->TotalParameterCount;
1658 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_LINK);
1659 pSMB->Reserved4 = 0;
1660 pSMB->hdr.smb_buf_length += byte_count;
1661 pSMB->ByteCount = cpu_to_le16(byte_count);
1663 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1664 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1666 cFYI(1, ("Send error in QuerySymLinkInfo = %d", rc));
1668 /* decode response */
1670 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
1671 if (rc || (pSMBr->ByteCount < 2))
1672 /* BB also check enough total bytes returned */
1673 rc = -EIO; /* bad smb */
1675 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
1676 __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
1678 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
1679 name_len = UniStrnlen((wchar_t *) ((char *)
1680 &pSMBr->hdr.Protocol +data_offset),
1681 min_t(const int, buflen,count) / 2);
1682 /* BB FIXME investigate remapping reserved chars here */
1683 cifs_strfromUCS_le(symlinkinfo,
1684 (wchar_t *) ((char *)&pSMBr->hdr.Protocol +
1686 name_len, nls_codepage);
1688 strncpy(symlinkinfo,
1689 (char *) &pSMBr->hdr.Protocol +
1691 min_t(const int, buflen, count));
1693 symlinkinfo[buflen] = 0;
1694 /* just in case so calling code does not go off the end of buffer */
1697 cifs_buf_release(pSMB);
1699 goto querySymLinkRetry;
1704 CIFSSMBQueryReparseLinkInfo(const int xid, struct cifsTconInfo *tcon,
1705 const unsigned char *searchName,
1706 char *symlinkinfo, const int buflen,__u16 fid,
1707 const struct nls_table *nls_codepage)
1712 struct smb_com_transaction_ioctl_req * pSMB;
1713 struct smb_com_transaction_ioctl_rsp * pSMBr;
1715 cFYI(1, ("In Windows reparse style QueryLink for path %s", searchName));
1716 rc = smb_init(SMB_COM_NT_TRANSACT, 23, tcon, (void **) &pSMB,
1721 pSMB->TotalParameterCount = 0 ;
1722 pSMB->TotalDataCount = 0;
1723 pSMB->MaxParameterCount = cpu_to_le32(2);
1724 /* BB find exact data count max from sess structure BB */
1725 pSMB->MaxDataCount = cpu_to_le32(4000);
1726 pSMB->MaxSetupCount = 4;
1728 pSMB->ParameterOffset = 0;
1729 pSMB->DataCount = 0;
1730 pSMB->DataOffset = 0;
1731 pSMB->SetupCount = 4;
1732 pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_IOCTL);
1733 pSMB->ParameterCount = pSMB->TotalParameterCount;
1734 pSMB->FunctionCode = cpu_to_le32(FSCTL_GET_REPARSE_POINT);
1735 pSMB->IsFsctl = 1; /* FSCTL */
1736 pSMB->IsRootFlag = 0;
1737 pSMB->Fid = fid; /* file handle always le */
1738 pSMB->ByteCount = 0;
1740 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1741 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1743 cFYI(1, ("Send error in QueryReparseLinkInfo = %d", rc));
1744 } else { /* decode response */
1745 __u32 data_offset = le32_to_cpu(pSMBr->DataOffset);
1746 __u32 data_count = le32_to_cpu(pSMBr->DataCount);
1747 if ((pSMBr->ByteCount < 2) || (data_offset > 512))
1748 /* BB also check enough total bytes returned */
1749 rc = -EIO; /* bad smb */
1751 if(data_count && (data_count < 2048)) {
1752 char * end_of_smb = pSMBr->ByteCount + (char *)&pSMBr->ByteCount;
1754 struct reparse_data * reparse_buf = (struct reparse_data *)
1755 ((char *)&pSMBr->hdr.Protocol + data_offset);
1756 if((char*)reparse_buf >= end_of_smb) {
1760 if((reparse_buf->LinkNamesBuf +
1761 reparse_buf->TargetNameOffset +
1762 reparse_buf->TargetNameLen) >
1764 cFYI(1,("reparse buf extended beyond SMB"));
1769 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
1770 name_len = UniStrnlen((wchar_t *)
1771 (reparse_buf->LinkNamesBuf +
1772 reparse_buf->TargetNameOffset),
1773 min(buflen/2, reparse_buf->TargetNameLen / 2));
1774 cifs_strfromUCS_le(symlinkinfo,
1775 (wchar_t *) (reparse_buf->LinkNamesBuf +
1776 reparse_buf->TargetNameOffset),
1777 name_len, nls_codepage);
1778 } else { /* ASCII names */
1779 strncpy(symlinkinfo,reparse_buf->LinkNamesBuf +
1780 reparse_buf->TargetNameOffset,
1781 min_t(const int, buflen, reparse_buf->TargetNameLen));
1785 cFYI(1,("Invalid return data count on get reparse info ioctl"));
1787 symlinkinfo[buflen] = 0; /* just in case so the caller
1788 does not go off the end of the buffer */
1789 cFYI(1,("readlink result - %s ",symlinkinfo));
1794 cifs_buf_release(pSMB);
1796 /* Note: On -EAGAIN error only caller can retry on handle based calls
1797 since file handle passed in no longer valid */
1802 #ifdef CONFIG_CIFS_POSIX
1804 /*Convert an Access Control Entry from wire format to local POSIX xattr format*/
1805 static void cifs_convert_ace(posix_acl_xattr_entry * ace, struct cifs_posix_ace * cifs_ace)
1807 /* u8 cifs fields do not need le conversion */
1808 ace->e_perm = (__u16)cifs_ace->cifs_e_perm;
1809 ace->e_tag = (__u16)cifs_ace->cifs_e_tag;
1810 ace->e_id = (__u32)le64_to_cpu(cifs_ace->cifs_uid);
1811 /* cFYI(1,("perm %d tag %d id %d",ace->e_perm,ace->e_tag,ace->e_id)); */
1816 /* Convert ACL from CIFS POSIX wire format to local Linux POSIX ACL xattr */
1817 static int cifs_copy_posix_acl(char * trgt,char * src, const int buflen,
1818 const int acl_type,const int size_of_data_area)
1823 struct cifs_posix_ace * pACE;
1824 struct cifs_posix_acl * cifs_acl = (struct cifs_posix_acl *)src;
1825 posix_acl_xattr_header * local_acl = (posix_acl_xattr_header *)trgt;
1827 if (le16_to_cpu(cifs_acl->version) != CIFS_ACL_VERSION)
1830 if(acl_type & ACL_TYPE_ACCESS) {
1831 count = le16_to_cpu(cifs_acl->access_entry_count);
1832 pACE = &cifs_acl->ace_array[0];
1833 size = sizeof(struct cifs_posix_acl);
1834 size += sizeof(struct cifs_posix_ace) * count;
1835 /* check if we would go beyond end of SMB */
1836 if(size_of_data_area < size) {
1837 cFYI(1,("bad CIFS POSIX ACL size %d vs. %d",size_of_data_area,size));
1840 } else if(acl_type & ACL_TYPE_DEFAULT) {
1841 count = le16_to_cpu(cifs_acl->access_entry_count);
1842 size = sizeof(struct cifs_posix_acl);
1843 size += sizeof(struct cifs_posix_ace) * count;
1844 /* skip past access ACEs to get to default ACEs */
1845 pACE = &cifs_acl->ace_array[count];
1846 count = le16_to_cpu(cifs_acl->default_entry_count);
1847 size += sizeof(struct cifs_posix_ace) * count;
1848 /* check if we would go beyond end of SMB */
1849 if(size_of_data_area < size)
1856 size = posix_acl_xattr_size(count);
1857 if((buflen == 0) || (local_acl == NULL)) {
1858 /* used to query ACL EA size */
1859 } else if(size > buflen) {
1861 } else /* buffer big enough */ {
1862 local_acl->a_version = POSIX_ACL_XATTR_VERSION;
1863 for(i = 0;i < count ;i++) {
1864 cifs_convert_ace(&local_acl->a_entries[i],pACE);
1871 static __u16 convert_ace_to_cifs_ace(struct cifs_posix_ace * cifs_ace,
1872 const posix_acl_xattr_entry * local_ace)
1874 __u16 rc = 0; /* 0 = ACL converted ok */
1876 cifs_ace->cifs_e_perm = (__u8)cpu_to_le16(local_ace->e_perm);
1877 cifs_ace->cifs_e_tag = (__u8)cpu_to_le16(local_ace->e_tag);
1878 /* BB is there a better way to handle the large uid? */
1879 if(local_ace->e_id == -1) {
1880 /* Probably no need to le convert -1 on any arch but can not hurt */
1881 cifs_ace->cifs_uid = cpu_to_le64(-1);
1883 cifs_ace->cifs_uid = (__u64)cpu_to_le32(local_ace->e_id);
1884 /*cFYI(1,("perm %d tag %d id %d",ace->e_perm,ace->e_tag,ace->e_id));*/
1888 /* Convert ACL from local Linux POSIX xattr to CIFS POSIX ACL wire format */
1889 static __u16 ACL_to_cifs_posix(char * parm_data,const char * pACL,const int buflen,
1893 struct cifs_posix_acl * cifs_acl = (struct cifs_posix_acl *)parm_data;
1894 posix_acl_xattr_header * local_acl = (posix_acl_xattr_header *)pACL;
1898 if((buflen == 0) || (pACL == NULL) || (cifs_acl == NULL))
1901 count = posix_acl_xattr_count((size_t)buflen);
1902 cFYI(1,("setting acl with %d entries from buf of length %d and version of %d",
1903 count,buflen,local_acl->a_version));
1904 if(local_acl->a_version != 2) {
1905 cFYI(1,("unknown POSIX ACL version %d",local_acl->a_version));
1908 cifs_acl->version = cpu_to_le16(1);
1909 if(acl_type == ACL_TYPE_ACCESS)
1910 cifs_acl->access_entry_count = count;
1911 else if(acl_type == ACL_TYPE_DEFAULT)
1912 cifs_acl->default_entry_count = count;
1914 cFYI(1,("unknown ACL type %d",acl_type));
1917 for(i=0;i<count;i++) {
1918 rc = convert_ace_to_cifs_ace(&cifs_acl->ace_array[i],
1919 &local_acl->a_entries[i]);
1921 /* ACE not converted */
1926 rc = (__u16)(count * sizeof(struct cifs_posix_ace));
1927 rc += sizeof(struct cifs_posix_acl);
1928 /* BB add check to make sure ACL does not overflow SMB */
1934 CIFSSMBGetPosixACL(const int xid, struct cifsTconInfo *tcon,
1935 const unsigned char *searchName,
1936 char *acl_inf, const int buflen, const int acl_type,
1937 const struct nls_table *nls_codepage, int remap)
1939 /* SMB_QUERY_POSIX_ACL */
1940 TRANSACTION2_QPI_REQ *pSMB = NULL;
1941 TRANSACTION2_QPI_RSP *pSMBr = NULL;
1945 __u16 params, byte_count;
1947 cFYI(1, ("In GetPosixACL (Unix) for path %s", searchName));
1950 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
1955 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1957 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
1958 PATH_MAX, nls_codepage, remap);
1959 name_len++; /* trailing null */
1961 pSMB->FileName[name_len] = 0;
1962 pSMB->FileName[name_len+1] = 0;
1963 } else { /* BB improve the check for buffer overruns BB */
1964 name_len = strnlen(searchName, PATH_MAX);
1965 name_len++; /* trailing null */
1966 strncpy(pSMB->FileName, searchName, name_len);
1969 params = 2 /* level */ + 4 /* rsrvd */ + name_len /* incl null */ ;
1970 pSMB->TotalDataCount = 0;
1971 pSMB->MaxParameterCount = cpu_to_le16(2);
1972 /* BB find exact max data count below from sess structure BB */
1973 pSMB->MaxDataCount = cpu_to_le16(4000);
1974 pSMB->MaxSetupCount = 0;
1978 pSMB->Reserved2 = 0;
1979 pSMB->ParameterOffset = cpu_to_le16(
1980 offsetof(struct smb_com_transaction2_qpi_req ,InformationLevel) - 4);
1981 pSMB->DataCount = 0;
1982 pSMB->DataOffset = 0;
1983 pSMB->SetupCount = 1;
1984 pSMB->Reserved3 = 0;
1985 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
1986 byte_count = params + 1 /* pad */ ;
1987 pSMB->TotalParameterCount = cpu_to_le16(params);
1988 pSMB->ParameterCount = pSMB->TotalParameterCount;
1989 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_POSIX_ACL);
1990 pSMB->Reserved4 = 0;
1991 pSMB->hdr.smb_buf_length += byte_count;
1992 pSMB->ByteCount = cpu_to_le16(byte_count);
1994 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1995 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1997 cFYI(1, ("Send error in Query POSIX ACL = %d", rc));
1999 /* decode response */
2001 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
2002 if (rc || (pSMBr->ByteCount < 2))
2003 /* BB also check enough total bytes returned */
2004 rc = -EIO; /* bad smb */
2006 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
2007 __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
2008 rc = cifs_copy_posix_acl(acl_inf,
2009 (char *)&pSMBr->hdr.Protocol+data_offset,
2010 buflen,acl_type,count);
2013 cifs_buf_release(pSMB);
2020 CIFSSMBSetPosixACL(const int xid, struct cifsTconInfo *tcon,
2021 const unsigned char *fileName,
2022 const char *local_acl, const int buflen,
2024 const struct nls_table *nls_codepage, int remap)
2026 struct smb_com_transaction2_spi_req *pSMB = NULL;
2027 struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
2031 int bytes_returned = 0;
2032 __u16 params, byte_count, data_count, param_offset, offset;
2034 cFYI(1, ("In SetPosixACL (Unix) for path %s", fileName));
2036 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2040 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2042 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
2043 PATH_MAX, nls_codepage, remap);
2044 name_len++; /* trailing null */
2046 } else { /* BB improve the check for buffer overruns BB */
2047 name_len = strnlen(fileName, PATH_MAX);
2048 name_len++; /* trailing null */
2049 strncpy(pSMB->FileName, fileName, name_len);
2051 params = 6 + name_len;
2052 pSMB->MaxParameterCount = cpu_to_le16(2);
2053 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB size from sess */
2054 pSMB->MaxSetupCount = 0;
2058 pSMB->Reserved2 = 0;
2059 param_offset = offsetof(struct smb_com_transaction2_spi_req,
2060 InformationLevel) - 4;
2061 offset = param_offset + params;
2062 parm_data = ((char *) &pSMB->hdr.Protocol) + offset;
2063 pSMB->ParameterOffset = cpu_to_le16(param_offset);
2065 /* convert to on the wire format for POSIX ACL */
2066 data_count = ACL_to_cifs_posix(parm_data,local_acl,buflen,acl_type);
2068 if(data_count == 0) {
2070 goto setACLerrorExit;
2072 pSMB->DataOffset = cpu_to_le16(offset);
2073 pSMB->SetupCount = 1;
2074 pSMB->Reserved3 = 0;
2075 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
2076 pSMB->InformationLevel = cpu_to_le16(SMB_SET_POSIX_ACL);
2077 byte_count = 3 /* pad */ + params + data_count;
2078 pSMB->DataCount = cpu_to_le16(data_count);
2079 pSMB->TotalDataCount = pSMB->DataCount;
2080 pSMB->ParameterCount = cpu_to_le16(params);
2081 pSMB->TotalParameterCount = pSMB->ParameterCount;
2082 pSMB->Reserved4 = 0;
2083 pSMB->hdr.smb_buf_length += byte_count;
2084 pSMB->ByteCount = cpu_to_le16(byte_count);
2085 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2086 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2088 cFYI(1, ("Set POSIX ACL returned %d", rc));
2092 cifs_buf_release(pSMB);
2098 /* BB fix tabs in this function FIXME BB */
2100 CIFSGetExtAttr(const int xid, struct cifsTconInfo *tcon,
2101 const int netfid, __u64 * pExtAttrBits, __u64 *pMask)
2104 struct smb_t2_qfi_req *pSMB = NULL;
2105 struct smb_t2_qfi_rsp *pSMBr = NULL;
2107 __u16 params, byte_count;
2109 cFYI(1,("In GetExtAttr"));
2114 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2119 params = 2 /* level */ +2 /* fid */;
2120 pSMB->t2.TotalDataCount = 0;
2121 pSMB->t2.MaxParameterCount = cpu_to_le16(4);
2122 /* BB find exact max data count below from sess structure BB */
2123 pSMB->t2.MaxDataCount = cpu_to_le16(4000);
2124 pSMB->t2.MaxSetupCount = 0;
2125 pSMB->t2.Reserved = 0;
2127 pSMB->t2.Timeout = 0;
2128 pSMB->t2.Reserved2 = 0;
2129 pSMB->t2.ParameterOffset = cpu_to_le16(offsetof(struct smb_t2_qfi_req,
2131 pSMB->t2.DataCount = 0;
2132 pSMB->t2.DataOffset = 0;
2133 pSMB->t2.SetupCount = 1;
2134 pSMB->t2.Reserved3 = 0;
2135 pSMB->t2.SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION);
2136 byte_count = params + 1 /* pad */ ;
2137 pSMB->t2.TotalParameterCount = cpu_to_le16(params);
2138 pSMB->t2.ParameterCount = pSMB->t2.TotalParameterCount;
2139 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_ATTR_FLAGS);
2142 pSMB->hdr.smb_buf_length += byte_count;
2143 pSMB->t2.ByteCount = cpu_to_le16(byte_count);
2145 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2146 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2148 cFYI(1, ("error %d in GetExtAttr", rc));
2150 /* decode response */
2151 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
2152 if (rc || (pSMBr->ByteCount < 2))
2153 /* BB also check enough total bytes returned */
2154 /* If rc should we check for EOPNOSUPP and
2155 disable the srvino flag? or in caller? */
2156 rc = -EIO; /* bad smb */
2158 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
2159 __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
2160 struct file_chattr_info * pfinfo;
2161 /* BB Do we need a cast or hash here ? */
2163 cFYI(1, ("Illegal size ret in GetExtAttr"));
2167 pfinfo = (struct file_chattr_info *)
2168 (data_offset + (char *) &pSMBr->hdr.Protocol);
2169 *pExtAttrBits = le64_to_cpu(pfinfo->mode);
2170 *pMask = le64_to_cpu(pfinfo->mask);
2174 cifs_buf_release(pSMB);
2176 goto GetExtAttrRetry;
2181 #endif /* CONFIG_POSIX */
2184 CIFSSMBQPathInfo(const int xid, struct cifsTconInfo *tcon,
2185 const unsigned char *searchName,
2186 FILE_ALL_INFO * pFindData,
2187 const struct nls_table *nls_codepage, int remap)
2189 /* level 263 SMB_QUERY_FILE_ALL_INFO */
2190 TRANSACTION2_QPI_REQ *pSMB = NULL;
2191 TRANSACTION2_QPI_RSP *pSMBr = NULL;
2195 __u16 params, byte_count;
2197 /* cFYI(1, ("In QPathInfo path %s", searchName)); */
2199 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2204 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2206 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
2207 PATH_MAX, nls_codepage, remap);
2208 name_len++; /* trailing null */
2210 } else { /* BB improve the check for buffer overruns BB */
2211 name_len = strnlen(searchName, PATH_MAX);
2212 name_len++; /* trailing null */
2213 strncpy(pSMB->FileName, searchName, name_len);
2216 params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */ ;
2217 pSMB->TotalDataCount = 0;
2218 pSMB->MaxParameterCount = cpu_to_le16(2);
2219 pSMB->MaxDataCount = cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
2220 pSMB->MaxSetupCount = 0;
2224 pSMB->Reserved2 = 0;
2225 pSMB->ParameterOffset = cpu_to_le16(offsetof(
2226 struct smb_com_transaction2_qpi_req ,InformationLevel) - 4);
2227 pSMB->DataCount = 0;
2228 pSMB->DataOffset = 0;
2229 pSMB->SetupCount = 1;
2230 pSMB->Reserved3 = 0;
2231 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
2232 byte_count = params + 1 /* pad */ ;
2233 pSMB->TotalParameterCount = cpu_to_le16(params);
2234 pSMB->ParameterCount = pSMB->TotalParameterCount;
2235 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_ALL_INFO);
2236 pSMB->Reserved4 = 0;
2237 pSMB->hdr.smb_buf_length += byte_count;
2238 pSMB->ByteCount = cpu_to_le16(byte_count);
2240 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2241 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2243 cFYI(1, ("Send error in QPathInfo = %d", rc));
2244 } else { /* decode response */
2245 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
2247 if (rc || (pSMBr->ByteCount < 40))
2248 rc = -EIO; /* bad smb */
2249 else if (pFindData){
2250 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
2251 memcpy((char *) pFindData,
2252 (char *) &pSMBr->hdr.Protocol +
2253 data_offset, sizeof (FILE_ALL_INFO));
2257 cifs_buf_release(pSMB);
2259 goto QPathInfoRetry;
2265 CIFSSMBUnixQPathInfo(const int xid, struct cifsTconInfo *tcon,
2266 const unsigned char *searchName,
2267 FILE_UNIX_BASIC_INFO * pFindData,
2268 const struct nls_table *nls_codepage, int remap)
2270 /* SMB_QUERY_FILE_UNIX_BASIC */
2271 TRANSACTION2_QPI_REQ *pSMB = NULL;
2272 TRANSACTION2_QPI_RSP *pSMBr = NULL;
2274 int bytes_returned = 0;
2276 __u16 params, byte_count;
2278 cFYI(1, ("In QPathInfo (Unix) the path %s", searchName));
2280 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2285 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2287 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
2288 PATH_MAX, nls_codepage, remap);
2289 name_len++; /* trailing null */
2291 } else { /* BB improve the check for buffer overruns BB */
2292 name_len = strnlen(searchName, PATH_MAX);
2293 name_len++; /* trailing null */
2294 strncpy(pSMB->FileName, searchName, name_len);
2297 params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */ ;
2298 pSMB->TotalDataCount = 0;
2299 pSMB->MaxParameterCount = cpu_to_le16(2);
2300 /* BB find exact max SMB PDU from sess structure BB */
2301 pSMB->MaxDataCount = cpu_to_le16(4000);
2302 pSMB->MaxSetupCount = 0;
2306 pSMB->Reserved2 = 0;
2307 pSMB->ParameterOffset = cpu_to_le16(offsetof(
2308 struct smb_com_transaction2_qpi_req ,InformationLevel) - 4);
2309 pSMB->DataCount = 0;
2310 pSMB->DataOffset = 0;
2311 pSMB->SetupCount = 1;
2312 pSMB->Reserved3 = 0;
2313 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
2314 byte_count = params + 1 /* pad */ ;
2315 pSMB->TotalParameterCount = cpu_to_le16(params);
2316 pSMB->ParameterCount = pSMB->TotalParameterCount;
2317 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC);
2318 pSMB->Reserved4 = 0;
2319 pSMB->hdr.smb_buf_length += byte_count;
2320 pSMB->ByteCount = cpu_to_le16(byte_count);
2322 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2323 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2325 cFYI(1, ("Send error in QPathInfo = %d", rc));
2326 } else { /* decode response */
2327 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
2329 if (rc || (pSMBr->ByteCount < sizeof(FILE_UNIX_BASIC_INFO))) {
2330 rc = -EIO; /* bad smb */
2332 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
2333 memcpy((char *) pFindData,
2334 (char *) &pSMBr->hdr.Protocol +
2336 sizeof (FILE_UNIX_BASIC_INFO));
2339 cifs_buf_release(pSMB);
2341 goto UnixQPathInfoRetry;
2346 #if 0 /* function unused at present */
2347 int CIFSFindSingle(const int xid, struct cifsTconInfo *tcon,
2348 const char *searchName, FILE_ALL_INFO * findData,
2349 const struct nls_table *nls_codepage)
2351 /* level 257 SMB_ */
2352 TRANSACTION2_FFIRST_REQ *pSMB = NULL;
2353 TRANSACTION2_FFIRST_RSP *pSMBr = NULL;
2357 __u16 params, byte_count;
2359 cFYI(1, ("In FindUnique"));
2361 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2366 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2368 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName, PATH_MAX
2369 /* find define for this maxpathcomponent */
2371 name_len++; /* trailing null */
2373 } else { /* BB improve the check for buffer overruns BB */
2374 name_len = strnlen(searchName, PATH_MAX);
2375 name_len++; /* trailing null */
2376 strncpy(pSMB->FileName, searchName, name_len);
2379 params = 12 + name_len /* includes null */ ;
2380 pSMB->TotalDataCount = 0; /* no EAs */
2381 pSMB->MaxParameterCount = cpu_to_le16(2);
2382 pSMB->MaxDataCount = cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
2383 pSMB->MaxSetupCount = 0;
2387 pSMB->Reserved2 = 0;
2388 pSMB->ParameterOffset = cpu_to_le16(
2389 offsetof(struct smb_com_transaction2_ffirst_req,InformationLevel) - 4);
2390 pSMB->DataCount = 0;
2391 pSMB->DataOffset = 0;
2392 pSMB->SetupCount = 1; /* one byte, no need to le convert */
2393 pSMB->Reserved3 = 0;
2394 pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_FIRST);
2395 byte_count = params + 1 /* pad */ ;
2396 pSMB->TotalParameterCount = cpu_to_le16(params);
2397 pSMB->ParameterCount = pSMB->TotalParameterCount;
2398 pSMB->SearchAttributes =
2399 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
2401 pSMB->SearchCount = cpu_to_le16(16); /* BB increase */
2402 pSMB->SearchFlags = cpu_to_le16(1);
2403 pSMB->InformationLevel = cpu_to_le16(SMB_FIND_FILE_DIRECTORY_INFO);
2404 pSMB->SearchStorageType = 0; /* BB what should we set this to? BB */
2405 pSMB->hdr.smb_buf_length += byte_count;
2406 pSMB->ByteCount = cpu_to_le16(byte_count);
2408 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2409 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2412 cFYI(1, ("Send error in FindFileDirInfo = %d", rc));
2413 } else { /* decode response */
2414 #ifdef CONFIG_CIFS_STATS
2415 atomic_inc(&tcon->num_ffirst);
2420 cifs_buf_release(pSMB);
2422 goto findUniqueRetry;
2426 #endif /* end unused (temporarily) function */
2428 /* xid, tcon, searchName and codepage are input parms, rest are returned */
2430 CIFSFindFirst(const int xid, struct cifsTconInfo *tcon,
2431 const char *searchName,
2432 const struct nls_table *nls_codepage,
2434 struct cifs_search_info * psrch_inf, int remap, const char dirsep)
2436 /* level 257 SMB_ */
2437 TRANSACTION2_FFIRST_REQ *pSMB = NULL;
2438 TRANSACTION2_FFIRST_RSP *pSMBr = NULL;
2439 T2_FFIRST_RSP_PARMS * parms;
2441 int bytes_returned = 0;
2443 __u16 params, byte_count;
2445 cFYI(1, ("In FindFirst for %s",searchName));
2448 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2453 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2455 cifsConvertToUCS((__le16 *) pSMB->FileName,searchName,
2456 PATH_MAX, nls_codepage, remap);
2457 /* We can not add the asterik earlier in case
2458 it got remapped to 0xF03A as if it were part of the
2459 directory name instead of a wildcard */
2461 pSMB->FileName[name_len] = dirsep;
2462 pSMB->FileName[name_len+1] = 0;
2463 pSMB->FileName[name_len+2] = '*';
2464 pSMB->FileName[name_len+3] = 0;
2465 name_len += 4; /* now the trailing null */
2466 pSMB->FileName[name_len] = 0; /* null terminate just in case */
2467 pSMB->FileName[name_len+1] = 0;
2469 } else { /* BB add check for overrun of SMB buf BB */
2470 name_len = strnlen(searchName, PATH_MAX);
2471 /* BB fix here and in unicode clause above ie
2472 if(name_len > buffersize-header)
2473 free buffer exit; BB */
2474 strncpy(pSMB->FileName, searchName, name_len);
2475 pSMB->FileName[name_len] = dirsep;
2476 pSMB->FileName[name_len+1] = '*';
2477 pSMB->FileName[name_len+2] = 0;
2481 params = 12 + name_len /* includes null */ ;
2482 pSMB->TotalDataCount = 0; /* no EAs */
2483 pSMB->MaxParameterCount = cpu_to_le16(10);
2484 pSMB->MaxDataCount = cpu_to_le16((tcon->ses->server->maxBuf -
2485 MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
2486 pSMB->MaxSetupCount = 0;
2490 pSMB->Reserved2 = 0;
2491 byte_count = params + 1 /* pad */ ;
2492 pSMB->TotalParameterCount = cpu_to_le16(params);
2493 pSMB->ParameterCount = pSMB->TotalParameterCount;
2494 pSMB->ParameterOffset = cpu_to_le16(
2495 offsetof(struct smb_com_transaction2_ffirst_req, SearchAttributes) - 4);
2496 pSMB->DataCount = 0;
2497 pSMB->DataOffset = 0;
2498 pSMB->SetupCount = 1; /* one byte, no need to make endian neutral */
2499 pSMB->Reserved3 = 0;
2500 pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_FIRST);
2501 pSMB->SearchAttributes =
2502 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
2504 pSMB->SearchCount= cpu_to_le16(CIFSMaxBufSize/sizeof(FILE_UNIX_INFO));
2505 pSMB->SearchFlags = cpu_to_le16(CIFS_SEARCH_CLOSE_AT_END |
2506 CIFS_SEARCH_RETURN_RESUME);
2507 pSMB->InformationLevel = cpu_to_le16(psrch_inf->info_level);
2509 /* BB what should we set StorageType to? Does it matter? BB */
2510 pSMB->SearchStorageType = 0;
2511 pSMB->hdr.smb_buf_length += byte_count;
2512 pSMB->ByteCount = cpu_to_le16(byte_count);
2514 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2515 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2517 if (rc) {/* BB add logic to retry regular search if Unix search rejected unexpectedly by server */
2518 /* BB Add code to handle unsupported level rc */
2519 cFYI(1, ("Error in FindFirst = %d", rc));
2522 cifs_buf_release(pSMB);
2524 /* BB eventually could optimize out free and realloc of buf */
2527 goto findFirstRetry;
2528 } else { /* decode response */
2529 #ifdef CONFIG_CIFS_STATS
2530 atomic_inc(&tcon->num_ffirst);
2532 /* BB remember to free buffer if error BB */
2533 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
2535 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
2536 psrch_inf->unicode = TRUE;
2538 psrch_inf->unicode = FALSE;
2540 psrch_inf->ntwrk_buf_start = (char *)pSMBr;
2541 psrch_inf->srch_entries_start =
2542 (char *) &pSMBr->hdr.Protocol +
2543 le16_to_cpu(pSMBr->t2.DataOffset);
2544 parms = (T2_FFIRST_RSP_PARMS *)((char *) &pSMBr->hdr.Protocol +
2545 le16_to_cpu(pSMBr->t2.ParameterOffset));
2547 if(parms->EndofSearch)
2548 psrch_inf->endOfSearch = TRUE;
2550 psrch_inf->endOfSearch = FALSE;
2552 psrch_inf->entries_in_buffer = le16_to_cpu(parms->SearchCount);
2553 psrch_inf->index_of_last_entry =
2554 psrch_inf->entries_in_buffer;
2555 *pnetfid = parms->SearchHandle;
2557 cifs_buf_release(pSMB);
2564 int CIFSFindNext(const int xid, struct cifsTconInfo *tcon,
2565 __u16 searchHandle, struct cifs_search_info * psrch_inf)
2567 TRANSACTION2_FNEXT_REQ *pSMB = NULL;
2568 TRANSACTION2_FNEXT_RSP *pSMBr = NULL;
2569 T2_FNEXT_RSP_PARMS * parms;
2570 char *response_data;
2572 int bytes_returned, name_len;
2573 __u16 params, byte_count;
2575 cFYI(1, ("In FindNext"));
2577 if(psrch_inf->endOfSearch == TRUE)
2580 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2585 params = 14; /* includes 2 bytes of null string, converted to LE below */
2587 pSMB->TotalDataCount = 0; /* no EAs */
2588 pSMB->MaxParameterCount = cpu_to_le16(8);
2589 pSMB->MaxDataCount =
2590 cpu_to_le16((tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
2591 pSMB->MaxSetupCount = 0;
2595 pSMB->Reserved2 = 0;
2596 pSMB->ParameterOffset = cpu_to_le16(
2597 offsetof(struct smb_com_transaction2_fnext_req,SearchHandle) - 4);
2598 pSMB->DataCount = 0;
2599 pSMB->DataOffset = 0;
2600 pSMB->SetupCount = 1;
2601 pSMB->Reserved3 = 0;
2602 pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_NEXT);
2603 pSMB->SearchHandle = searchHandle; /* always kept as le */
2605 cpu_to_le16(CIFSMaxBufSize / sizeof (FILE_UNIX_INFO));
2606 /* test for Unix extensions */
2607 /* if (tcon->ses->capabilities & CAP_UNIX) {
2608 pSMB->InformationLevel = cpu_to_le16(SMB_FIND_FILE_UNIX);
2609 psrch_inf->info_level = SMB_FIND_FILE_UNIX;
2611 pSMB->InformationLevel =
2612 cpu_to_le16(SMB_FIND_FILE_DIRECTORY_INFO);
2613 psrch_inf->info_level = SMB_FIND_FILE_DIRECTORY_INFO;
2615 pSMB->InformationLevel = cpu_to_le16(psrch_inf->info_level);
2616 pSMB->ResumeKey = psrch_inf->resume_key;
2618 cpu_to_le16(CIFS_SEARCH_CLOSE_AT_END | CIFS_SEARCH_RETURN_RESUME);
2620 name_len = psrch_inf->resume_name_len;
2622 if(name_len < PATH_MAX) {
2623 memcpy(pSMB->ResumeFileName, psrch_inf->presume_name, name_len);
2624 byte_count += name_len;
2627 goto FNext2_err_exit;
2629 byte_count = params + 1 /* pad */ ;
2630 pSMB->TotalParameterCount = cpu_to_le16(params);
2631 pSMB->ParameterCount = pSMB->TotalParameterCount;
2632 pSMB->hdr.smb_buf_length += byte_count;
2633 pSMB->ByteCount = cpu_to_le16(byte_count);
2635 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2636 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2640 psrch_inf->endOfSearch = TRUE;
2641 rc = 0; /* search probably was closed at end of search above */
2643 cFYI(1, ("FindNext returned = %d", rc));
2644 } else { /* decode response */
2645 #ifdef CONFIG_CIFS_STATS
2646 atomic_inc(&tcon->num_fnext);
2648 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
2651 /* BB fixme add lock for file (srch_info) struct here */
2652 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
2653 psrch_inf->unicode = TRUE;
2655 psrch_inf->unicode = FALSE;
2656 response_data = (char *) &pSMBr->hdr.Protocol +
2657 le16_to_cpu(pSMBr->t2.ParameterOffset);
2658 parms = (T2_FNEXT_RSP_PARMS *)response_data;
2659 response_data = (char *)&pSMBr->hdr.Protocol +
2660 le16_to_cpu(pSMBr->t2.DataOffset);
2661 cifs_buf_release(psrch_inf->ntwrk_buf_start);
2662 psrch_inf->srch_entries_start = response_data;
2663 psrch_inf->ntwrk_buf_start = (char *)pSMB;
2664 if(parms->EndofSearch)
2665 psrch_inf->endOfSearch = TRUE;
2667 psrch_inf->endOfSearch = FALSE;
2669 psrch_inf->entries_in_buffer = le16_to_cpu(parms->SearchCount);
2670 psrch_inf->index_of_last_entry +=
2671 psrch_inf->entries_in_buffer;
2672 /* cFYI(1,("fnxt2 entries in buf %d index_of_last %d",psrch_inf->entries_in_buffer,psrch_inf->index_of_last_entry)); */
2674 /* BB fixme add unlock here */
2679 /* BB On error, should we leave previous search buf (and count and
2680 last entry fields) intact or free the previous one? */
2682 /* Note: On -EAGAIN error only caller can retry on handle based calls
2683 since file handle passed in no longer valid */
2686 cifs_buf_release(pSMB);
2692 CIFSFindClose(const int xid, struct cifsTconInfo *tcon, const __u16 searchHandle)
2695 FINDCLOSE_REQ *pSMB = NULL;
2696 CLOSE_RSP *pSMBr = NULL; /* BB removeme BB */
2699 cFYI(1, ("In CIFSSMBFindClose"));
2700 rc = small_smb_init(SMB_COM_FIND_CLOSE2, 1, tcon, (void **)&pSMB);
2702 /* no sense returning error if session restarted
2703 as file handle has been closed */
2709 pSMBr = (CLOSE_RSP *)pSMB; /* BB removeme BB */
2710 pSMB->FileID = searchHandle;
2711 pSMB->ByteCount = 0;
2712 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2713 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2715 cERROR(1, ("Send error in FindClose = %d", rc));
2717 #ifdef CONFIG_CIFS_STATS
2718 atomic_inc(&tcon->num_fclose);
2720 cifs_small_buf_release(pSMB);
2722 /* Since session is dead, search handle closed on server already */
2729 #ifdef CONFIG_CIFS_EXPERIMENTAL
2731 CIFSGetSrvInodeNumber(const int xid, struct cifsTconInfo *tcon,
2732 const unsigned char *searchName,
2733 __u64 * inode_number,
2734 const struct nls_table *nls_codepage, int remap)
2737 TRANSACTION2_QPI_REQ *pSMB = NULL;
2738 TRANSACTION2_QPI_RSP *pSMBr = NULL;
2739 int name_len, bytes_returned;
2740 __u16 params, byte_count;
2742 cFYI(1,("In GetSrvInodeNum for %s",searchName));
2746 GetInodeNumberRetry:
2747 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2753 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2755 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
2756 PATH_MAX,nls_codepage, remap);
2757 name_len++; /* trailing null */
2759 } else { /* BB improve the check for buffer overruns BB */
2760 name_len = strnlen(searchName, PATH_MAX);
2761 name_len++; /* trailing null */
2762 strncpy(pSMB->FileName, searchName, name_len);
2765 params = 2 /* level */ + 4 /* rsrvd */ + name_len /* incl null */ ;
2766 pSMB->TotalDataCount = 0;
2767 pSMB->MaxParameterCount = cpu_to_le16(2);
2768 /* BB find exact max data count below from sess structure BB */
2769 pSMB->MaxDataCount = cpu_to_le16(4000);
2770 pSMB->MaxSetupCount = 0;
2774 pSMB->Reserved2 = 0;
2775 pSMB->ParameterOffset = cpu_to_le16(offsetof(
2776 struct smb_com_transaction2_qpi_req ,InformationLevel) - 4);
2777 pSMB->DataCount = 0;
2778 pSMB->DataOffset = 0;
2779 pSMB->SetupCount = 1;
2780 pSMB->Reserved3 = 0;
2781 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
2782 byte_count = params + 1 /* pad */ ;
2783 pSMB->TotalParameterCount = cpu_to_le16(params);
2784 pSMB->ParameterCount = pSMB->TotalParameterCount;
2785 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_INTERNAL_INFO);
2786 pSMB->Reserved4 = 0;
2787 pSMB->hdr.smb_buf_length += byte_count;
2788 pSMB->ByteCount = cpu_to_le16(byte_count);
2790 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2791 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2793 cFYI(1, ("error %d in QueryInternalInfo", rc));
2795 /* decode response */
2796 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
2797 if (rc || (pSMBr->ByteCount < 2))
2798 /* BB also check enough total bytes returned */
2799 /* If rc should we check for EOPNOSUPP and
2800 disable the srvino flag? or in caller? */
2801 rc = -EIO; /* bad smb */
2803 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
2804 __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
2805 struct file_internal_info * pfinfo;
2806 /* BB Do we need a cast or hash here ? */
2808 cFYI(1, ("Illegal size ret in QryIntrnlInf"));
2810 goto GetInodeNumOut;
2812 pfinfo = (struct file_internal_info *)
2813 (data_offset + (char *) &pSMBr->hdr.Protocol);
2814 *inode_number = pfinfo->UniqueId;
2818 cifs_buf_release(pSMB);
2820 goto GetInodeNumberRetry;
2823 #endif /* CIFS_EXPERIMENTAL */
2826 CIFSGetDFSRefer(const int xid, struct cifsSesInfo *ses,
2827 const unsigned char *searchName,
2828 unsigned char **targetUNCs,
2829 unsigned int *number_of_UNC_in_array,
2830 const struct nls_table *nls_codepage, int remap)
2832 /* TRANS2_GET_DFS_REFERRAL */
2833 TRANSACTION2_GET_DFS_REFER_REQ *pSMB = NULL;
2834 TRANSACTION2_GET_DFS_REFER_RSP *pSMBr = NULL;
2835 struct dfs_referral_level_3 * referrals = NULL;
2841 __u16 params, byte_count;
2842 *number_of_UNC_in_array = 0;
2845 cFYI(1, ("In GetDFSRefer the path %s", searchName));
2849 rc = smb_init(SMB_COM_TRANSACTION2, 15, NULL, (void **) &pSMB,
2854 pSMB->hdr.Tid = ses->ipc_tid;
2855 pSMB->hdr.Uid = ses->Suid;
2856 if (ses->capabilities & CAP_STATUS32) {
2857 pSMB->hdr.Flags2 |= SMBFLG2_ERR_STATUS;
2859 if (ses->capabilities & CAP_DFS) {
2860 pSMB->hdr.Flags2 |= SMBFLG2_DFS;
2863 if (ses->capabilities & CAP_UNICODE) {
2864 pSMB->hdr.Flags2 |= SMBFLG2_UNICODE;
2866 cifsConvertToUCS((__le16 *) pSMB->RequestFileName,
2867 searchName, PATH_MAX, nls_codepage, remap);
2868 name_len++; /* trailing null */
2870 } else { /* BB improve the check for buffer overruns BB */
2871 name_len = strnlen(searchName, PATH_MAX);
2872 name_len++; /* trailing null */
2873 strncpy(pSMB->RequestFileName, searchName, name_len);
2876 params = 2 /* level */ + name_len /*includes null */ ;
2877 pSMB->TotalDataCount = 0;
2878 pSMB->DataCount = 0;
2879 pSMB->DataOffset = 0;
2880 pSMB->MaxParameterCount = 0;
2881 pSMB->MaxDataCount = cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
2882 pSMB->MaxSetupCount = 0;
2886 pSMB->Reserved2 = 0;
2887 pSMB->ParameterOffset = cpu_to_le16(offsetof(
2888 struct smb_com_transaction2_get_dfs_refer_req, MaxReferralLevel) - 4);
2889 pSMB->SetupCount = 1;
2890 pSMB->Reserved3 = 0;
2891 pSMB->SubCommand = cpu_to_le16(TRANS2_GET_DFS_REFERRAL);
2892 byte_count = params + 3 /* pad */ ;
2893 pSMB->ParameterCount = cpu_to_le16(params);
2894 pSMB->TotalParameterCount = pSMB->ParameterCount;
2895 pSMB->MaxReferralLevel = cpu_to_le16(3);
2896 pSMB->hdr.smb_buf_length += byte_count;
2897 pSMB->ByteCount = cpu_to_le16(byte_count);
2899 rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB,
2900 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2902 cFYI(1, ("Send error in GetDFSRefer = %d", rc));
2903 } else { /* decode response */
2904 /* BB Add logic to parse referrals here */
2905 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
2907 if (rc || (pSMBr->ByteCount < 17)) /* BB also check enough total bytes returned */
2908 rc = -EIO; /* bad smb */
2910 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
2911 __u16 data_count = le16_to_cpu(pSMBr->t2.DataCount);
2914 ("Decoding GetDFSRefer response. BCC: %d Offset %d",
2915 pSMBr->ByteCount, data_offset));
2917 (struct dfs_referral_level_3 *)
2918 (8 /* sizeof start of data block */ +
2920 (char *) &pSMBr->hdr.Protocol);
2921 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",
2922 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)));
2923 /* BB This field is actually two bytes in from start of
2924 data block so we could do safety check that DataBlock
2925 begins at address of pSMBr->NumberOfReferrals */
2926 *number_of_UNC_in_array = le16_to_cpu(pSMBr->NumberOfReferrals);
2928 /* BB Fix below so can return more than one referral */
2929 if(*number_of_UNC_in_array > 1)
2930 *number_of_UNC_in_array = 1;
2932 /* get the length of the strings describing refs */
2934 for(i=0;i<*number_of_UNC_in_array;i++) {
2935 /* make sure that DfsPathOffset not past end */
2936 __u16 offset = le16_to_cpu(referrals->DfsPathOffset);
2937 if (offset > data_count) {
2938 /* if invalid referral, stop here and do
2939 not try to copy any more */
2940 *number_of_UNC_in_array = i;
2943 temp = ((char *)referrals) + offset;
2945 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
2946 name_len += UniStrnlen((wchar_t *)temp,data_count);
2948 name_len += strnlen(temp,data_count);
2951 /* BB add check that referral pointer does not fall off end PDU */
2954 /* BB add check for name_len bigger than bcc */
2956 kmalloc(name_len+1+ (*number_of_UNC_in_array),GFP_KERNEL);
2957 if(*targetUNCs == NULL) {
2961 /* copy the ref strings */
2963 (struct dfs_referral_level_3 *)
2964 (8 /* sizeof data hdr */ +
2966 (char *) &pSMBr->hdr.Protocol);
2968 for(i=0;i<*number_of_UNC_in_array;i++) {
2969 temp = ((char *)referrals) + le16_to_cpu(referrals->DfsPathOffset);
2970 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
2971 cifs_strfromUCS_le(*targetUNCs,
2972 (wchar_t *) temp, name_len, nls_codepage);
2974 strncpy(*targetUNCs,temp,name_len);
2976 /* BB update target_uncs pointers */
2986 cifs_buf_release(pSMB);
2995 CIFSSMBQFSInfo(const int xid, struct cifsTconInfo *tcon, struct kstatfs *FSData)
2997 /* level 0x103 SMB_QUERY_FILE_SYSTEM_INFO */
2998 TRANSACTION2_QFSI_REQ *pSMB = NULL;
2999 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
3000 FILE_SYSTEM_INFO *response_data;
3002 int bytes_returned = 0;
3003 __u16 params, byte_count;
3005 cFYI(1, ("In QFSInfo"));
3007 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3012 params = 2; /* level */
3013 pSMB->TotalDataCount = 0;
3014 pSMB->MaxParameterCount = cpu_to_le16(2);
3015 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
3016 pSMB->MaxSetupCount = 0;
3020 pSMB->Reserved2 = 0;
3021 byte_count = params + 1 /* pad */ ;
3022 pSMB->TotalParameterCount = cpu_to_le16(params);
3023 pSMB->ParameterCount = pSMB->TotalParameterCount;
3024 pSMB->ParameterOffset = cpu_to_le16(offsetof(
3025 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
3026 pSMB->DataCount = 0;
3027 pSMB->DataOffset = 0;
3028 pSMB->SetupCount = 1;
3029 pSMB->Reserved3 = 0;
3030 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
3031 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_SIZE_INFO);
3032 pSMB->hdr.smb_buf_length += byte_count;
3033 pSMB->ByteCount = cpu_to_le16(byte_count);
3035 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3036 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3038 cERROR(1, ("Send error in QFSInfo = %d", rc));
3039 } else { /* decode response */
3040 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3042 if (rc || (pSMBr->ByteCount < 24)) /* BB alsO CHEck enough total bytes returned */
3043 rc = -EIO; /* bad smb */
3045 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3047 ("Decoding qfsinfo response. BCC: %d Offset %d",
3048 pSMBr->ByteCount, data_offset));
3052 *) (((char *) &pSMBr->hdr.Protocol) +
3055 le32_to_cpu(response_data->BytesPerSector) *
3056 le32_to_cpu(response_data->
3057 SectorsPerAllocationUnit);
3059 le64_to_cpu(response_data->TotalAllocationUnits);
3060 FSData->f_bfree = FSData->f_bavail =
3061 le64_to_cpu(response_data->FreeAllocationUnits);
3063 ("Blocks: %lld Free: %lld Block size %ld",
3064 (unsigned long long)FSData->f_blocks,
3065 (unsigned long long)FSData->f_bfree,
3069 cifs_buf_release(pSMB);
3078 CIFSSMBQFSAttributeInfo(const int xid, struct cifsTconInfo *tcon)
3080 /* level 0x105 SMB_QUERY_FILE_SYSTEM_INFO */
3081 TRANSACTION2_QFSI_REQ *pSMB = NULL;
3082 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
3083 FILE_SYSTEM_ATTRIBUTE_INFO *response_data;
3085 int bytes_returned = 0;
3086 __u16 params, byte_count;
3088 cFYI(1, ("In QFSAttributeInfo"));
3090 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3095 params = 2; /* level */
3096 pSMB->TotalDataCount = 0;
3097 pSMB->MaxParameterCount = cpu_to_le16(2);
3098 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
3099 pSMB->MaxSetupCount = 0;
3103 pSMB->Reserved2 = 0;
3104 byte_count = params + 1 /* pad */ ;
3105 pSMB->TotalParameterCount = cpu_to_le16(params);
3106 pSMB->ParameterCount = pSMB->TotalParameterCount;
3107 pSMB->ParameterOffset = cpu_to_le16(offsetof(
3108 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
3109 pSMB->DataCount = 0;
3110 pSMB->DataOffset = 0;
3111 pSMB->SetupCount = 1;
3112 pSMB->Reserved3 = 0;
3113 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
3114 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_ATTRIBUTE_INFO);
3115 pSMB->hdr.smb_buf_length += byte_count;
3116 pSMB->ByteCount = cpu_to_le16(byte_count);
3118 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3119 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3121 cERROR(1, ("Send error in QFSAttributeInfo = %d", rc));
3122 } else { /* decode response */
3123 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3125 if (rc || (pSMBr->ByteCount < 13)) { /* BB also check enough bytes returned */
3126 rc = -EIO; /* bad smb */
3128 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3130 (FILE_SYSTEM_ATTRIBUTE_INFO
3131 *) (((char *) &pSMBr->hdr.Protocol) +
3133 memcpy(&tcon->fsAttrInfo, response_data,
3134 sizeof (FILE_SYSTEM_ATTRIBUTE_INFO));
3137 cifs_buf_release(pSMB);
3140 goto QFSAttributeRetry;
3146 CIFSSMBQFSDeviceInfo(const int xid, struct cifsTconInfo *tcon)
3148 /* level 0x104 SMB_QUERY_FILE_SYSTEM_INFO */
3149 TRANSACTION2_QFSI_REQ *pSMB = NULL;
3150 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
3151 FILE_SYSTEM_DEVICE_INFO *response_data;
3153 int bytes_returned = 0;
3154 __u16 params, byte_count;
3156 cFYI(1, ("In QFSDeviceInfo"));
3158 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3163 params = 2; /* level */
3164 pSMB->TotalDataCount = 0;
3165 pSMB->MaxParameterCount = cpu_to_le16(2);
3166 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
3167 pSMB->MaxSetupCount = 0;
3171 pSMB->Reserved2 = 0;
3172 byte_count = params + 1 /* pad */ ;
3173 pSMB->TotalParameterCount = cpu_to_le16(params);
3174 pSMB->ParameterCount = pSMB->TotalParameterCount;
3175 pSMB->ParameterOffset = cpu_to_le16(offsetof(
3176 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
3178 pSMB->DataCount = 0;
3179 pSMB->DataOffset = 0;
3180 pSMB->SetupCount = 1;
3181 pSMB->Reserved3 = 0;
3182 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
3183 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_DEVICE_INFO);
3184 pSMB->hdr.smb_buf_length += byte_count;
3185 pSMB->ByteCount = cpu_to_le16(byte_count);
3187 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3188 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3190 cFYI(1, ("Send error in QFSDeviceInfo = %d", rc));
3191 } else { /* decode response */
3192 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3194 if (rc || (pSMBr->ByteCount < sizeof (FILE_SYSTEM_DEVICE_INFO)))
3195 rc = -EIO; /* bad smb */
3197 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3199 (FILE_SYSTEM_DEVICE_INFO *)
3200 (((char *) &pSMBr->hdr.Protocol) +
3202 memcpy(&tcon->fsDevInfo, response_data,
3203 sizeof (FILE_SYSTEM_DEVICE_INFO));
3206 cifs_buf_release(pSMB);
3209 goto QFSDeviceRetry;
3215 CIFSSMBQFSUnixInfo(const int xid, struct cifsTconInfo *tcon)
3217 /* level 0x200 SMB_QUERY_CIFS_UNIX_INFO */
3218 TRANSACTION2_QFSI_REQ *pSMB = NULL;
3219 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
3220 FILE_SYSTEM_UNIX_INFO *response_data;
3222 int bytes_returned = 0;
3223 __u16 params, byte_count;
3225 cFYI(1, ("In QFSUnixInfo"));
3227 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3232 params = 2; /* level */
3233 pSMB->TotalDataCount = 0;
3234 pSMB->DataCount = 0;
3235 pSMB->DataOffset = 0;
3236 pSMB->MaxParameterCount = cpu_to_le16(2);
3237 pSMB->MaxDataCount = cpu_to_le16(100); /* BB find exact max SMB PDU from sess structure BB */
3238 pSMB->MaxSetupCount = 0;
3242 pSMB->Reserved2 = 0;
3243 byte_count = params + 1 /* pad */ ;
3244 pSMB->ParameterCount = cpu_to_le16(params);
3245 pSMB->TotalParameterCount = pSMB->ParameterCount;
3246 pSMB->ParameterOffset = cpu_to_le16(offsetof(struct
3247 smb_com_transaction2_qfsi_req, InformationLevel) - 4);
3248 pSMB->SetupCount = 1;
3249 pSMB->Reserved3 = 0;
3250 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
3251 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_CIFS_UNIX_INFO);
3252 pSMB->hdr.smb_buf_length += byte_count;
3253 pSMB->ByteCount = cpu_to_le16(byte_count);
3255 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3256 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3258 cERROR(1, ("Send error in QFSUnixInfo = %d", rc));
3259 } else { /* decode response */
3260 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3262 if (rc || (pSMBr->ByteCount < 13)) {
3263 rc = -EIO; /* bad smb */
3265 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3267 (FILE_SYSTEM_UNIX_INFO
3268 *) (((char *) &pSMBr->hdr.Protocol) +
3270 memcpy(&tcon->fsUnixInfo, response_data,
3271 sizeof (FILE_SYSTEM_UNIX_INFO));
3274 cifs_buf_release(pSMB);
3284 CIFSSMBSetFSUnixInfo(const int xid, struct cifsTconInfo *tcon, __u64 cap)
3286 /* level 0x200 SMB_SET_CIFS_UNIX_INFO */
3287 TRANSACTION2_SETFSI_REQ *pSMB = NULL;
3288 TRANSACTION2_SETFSI_RSP *pSMBr = NULL;
3290 int bytes_returned = 0;
3291 __u16 params, param_offset, offset, byte_count;
3293 cFYI(1, ("In SETFSUnixInfo"));
3295 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3300 params = 4; /* 2 bytes zero followed by info level. */
3301 pSMB->MaxSetupCount = 0;
3305 pSMB->Reserved2 = 0;
3306 param_offset = offsetof(struct smb_com_transaction2_setfsi_req, FileNum) - 4;
3307 offset = param_offset + params;
3309 pSMB->MaxParameterCount = cpu_to_le16(4);
3310 pSMB->MaxDataCount = cpu_to_le16(100); /* BB find exact max SMB PDU from sess structure BB */
3311 pSMB->SetupCount = 1;
3312 pSMB->Reserved3 = 0;
3313 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FS_INFORMATION);
3314 byte_count = 1 /* pad */ + params + 12;
3316 pSMB->DataCount = cpu_to_le16(12);
3317 pSMB->ParameterCount = cpu_to_le16(params);
3318 pSMB->TotalDataCount = pSMB->DataCount;
3319 pSMB->TotalParameterCount = pSMB->ParameterCount;
3320 pSMB->ParameterOffset = cpu_to_le16(param_offset);
3321 pSMB->DataOffset = cpu_to_le16(offset);
3325 pSMB->InformationLevel = cpu_to_le16(SMB_SET_CIFS_UNIX_INFO);
3328 pSMB->ClientUnixMajor = cpu_to_le16(CIFS_UNIX_MAJOR_VERSION);
3329 pSMB->ClientUnixMinor = cpu_to_le16(CIFS_UNIX_MINOR_VERSION);
3330 pSMB->ClientUnixCap = cpu_to_le64(cap);
3332 pSMB->hdr.smb_buf_length += byte_count;
3333 pSMB->ByteCount = cpu_to_le16(byte_count);
3335 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3336 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3338 cERROR(1, ("Send error in SETFSUnixInfo = %d", rc));
3339 } else { /* decode response */
3340 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3342 rc = -EIO; /* bad smb */
3345 cifs_buf_release(pSMB);
3348 goto SETFSUnixRetry;
3356 CIFSSMBQFSPosixInfo(const int xid, struct cifsTconInfo *tcon,
3357 struct kstatfs *FSData)
3359 /* level 0x201 SMB_QUERY_CIFS_POSIX_INFO */
3360 TRANSACTION2_QFSI_REQ *pSMB = NULL;
3361 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
3362 FILE_SYSTEM_POSIX_INFO *response_data;
3364 int bytes_returned = 0;
3365 __u16 params, byte_count;
3367 cFYI(1, ("In QFSPosixInfo"));
3369 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3374 params = 2; /* level */
3375 pSMB->TotalDataCount = 0;
3376 pSMB->DataCount = 0;
3377 pSMB->DataOffset = 0;
3378 pSMB->MaxParameterCount = cpu_to_le16(2);
3379 pSMB->MaxDataCount = cpu_to_le16(100); /* BB find exact max SMB PDU from sess structure BB */
3380 pSMB->MaxSetupCount = 0;
3384 pSMB->Reserved2 = 0;
3385 byte_count = params + 1 /* pad */ ;
3386 pSMB->ParameterCount = cpu_to_le16(params);
3387 pSMB->TotalParameterCount = pSMB->ParameterCount;
3388 pSMB->ParameterOffset = cpu_to_le16(offsetof(struct
3389 smb_com_transaction2_qfsi_req, InformationLevel) - 4);
3390 pSMB->SetupCount = 1;
3391 pSMB->Reserved3 = 0;
3392 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
3393 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_POSIX_FS_INFO);
3394 pSMB->hdr.smb_buf_length += byte_count;
3395 pSMB->ByteCount = cpu_to_le16(byte_count);
3397 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3398 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3400 cFYI(1, ("Send error in QFSUnixInfo = %d", rc));
3401 } else { /* decode response */
3402 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3404 if (rc || (pSMBr->ByteCount < 13)) {
3405 rc = -EIO; /* bad smb */
3407 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3409 (FILE_SYSTEM_POSIX_INFO
3410 *) (((char *) &pSMBr->hdr.Protocol) +
3413 le32_to_cpu(response_data->BlockSize);
3415 le64_to_cpu(response_data->TotalBlocks);
3417 le64_to_cpu(response_data->BlocksAvail);
3418 if(response_data->UserBlocksAvail == -1) {
3419 FSData->f_bavail = FSData->f_bfree;
3422 le64_to_cpu(response_data->UserBlocksAvail);
3424 if(response_data->TotalFileNodes != -1)
3426 le64_to_cpu(response_data->TotalFileNodes);
3427 if(response_data->FreeFileNodes != -1)
3429 le64_to_cpu(response_data->FreeFileNodes);
3432 cifs_buf_release(pSMB);
3441 /* We can not use write of zero bytes trick to
3442 set file size due to need for large file support. Also note that
3443 this SetPathInfo is preferred to SetFileInfo based method in next
3444 routine which is only needed to work around a sharing violation bug
3445 in Samba which this routine can run into */
3448 CIFSSMBSetEOF(const int xid, struct cifsTconInfo *tcon, const char *fileName,
3449 __u64 size, int SetAllocation,
3450 const struct nls_table *nls_codepage, int remap)
3452 struct smb_com_transaction2_spi_req *pSMB = NULL;
3453 struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
3454 struct file_end_of_file_info *parm_data;
3457 int bytes_returned = 0;
3458 __u16 params, byte_count, data_count, param_offset, offset;
3460 cFYI(1, ("In SetEOF"));
3462 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3467 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3469 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
3470 PATH_MAX, nls_codepage, remap);
3471 name_len++; /* trailing null */
3473 } else { /* BB improve the check for buffer overruns BB */
3474 name_len = strnlen(fileName, PATH_MAX);
3475 name_len++; /* trailing null */
3476 strncpy(pSMB->FileName, fileName, name_len);
3478 params = 6 + name_len;
3479 data_count = sizeof (struct file_end_of_file_info);
3480 pSMB->MaxParameterCount = cpu_to_le16(2);
3481 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB size from sess */
3482 pSMB->MaxSetupCount = 0;
3486 pSMB->Reserved2 = 0;
3487 param_offset = offsetof(struct smb_com_transaction2_spi_req,
3488 InformationLevel) - 4;
3489 offset = param_offset + params;
3491 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
3492 pSMB->InformationLevel =
3493 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2);
3495 pSMB->InformationLevel =
3496 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO);
3497 } else /* Set File Size */ {
3498 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
3499 pSMB->InformationLevel =
3500 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO2);
3502 pSMB->InformationLevel =
3503 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO);
3507 (struct file_end_of_file_info *) (((char *) &pSMB->hdr.Protocol) +
3509 pSMB->ParameterOffset = cpu_to_le16(param_offset);
3510 pSMB->DataOffset = cpu_to_le16(offset);
3511 pSMB->SetupCount = 1;
3512 pSMB->Reserved3 = 0;
3513 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
3514 byte_count = 3 /* pad */ + params + data_count;
3515 pSMB->DataCount = cpu_to_le16(data_count);
3516 pSMB->TotalDataCount = pSMB->DataCount;
3517 pSMB->ParameterCount = cpu_to_le16(params);
3518 pSMB->TotalParameterCount = pSMB->ParameterCount;
3519 pSMB->Reserved4 = 0;
3520 pSMB->hdr.smb_buf_length += byte_count;
3521 parm_data->FileSize = cpu_to_le64(size);
3522 pSMB->ByteCount = cpu_to_le16(byte_count);
3523 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3524 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3526 cFYI(1, ("SetPathInfo (file size) returned %d", rc));
3529 cifs_buf_release(pSMB);
3538 CIFSSMBSetFileSize(const int xid, struct cifsTconInfo *tcon, __u64 size,
3539 __u16 fid, __u32 pid_of_opener, int SetAllocation)
3541 struct smb_com_transaction2_sfi_req *pSMB = NULL;
3542 struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
3544 struct file_end_of_file_info *parm_data;
3546 int bytes_returned = 0;
3547 __u16 params, param_offset, offset, byte_count, count;
3549 cFYI(1, ("SetFileSize (via SetFileInfo) %lld",
3551 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
3556 pSMBr = (struct smb_com_transaction2_sfi_rsp *)pSMB;
3558 pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
3559 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));
3562 pSMB->MaxSetupCount = 0;
3566 pSMB->Reserved2 = 0;
3567 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
3568 offset = param_offset + params;
3570 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
3572 count = sizeof(struct file_end_of_file_info);
3573 pSMB->MaxParameterCount = cpu_to_le16(2);
3574 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB PDU from sess */
3575 pSMB->SetupCount = 1;
3576 pSMB->Reserved3 = 0;
3577 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
3578 byte_count = 3 /* pad */ + params + count;
3579 pSMB->DataCount = cpu_to_le16(count);
3580 pSMB->ParameterCount = cpu_to_le16(params);
3581 pSMB->TotalDataCount = pSMB->DataCount;
3582 pSMB->TotalParameterCount = pSMB->ParameterCount;
3583 pSMB->ParameterOffset = cpu_to_le16(param_offset);
3585 (struct file_end_of_file_info *) (((char *) &pSMB->hdr.Protocol) +
3587 pSMB->DataOffset = cpu_to_le16(offset);
3588 parm_data->FileSize = cpu_to_le64(size);
3591 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
3592 pSMB->InformationLevel =
3593 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2);
3595 pSMB->InformationLevel =
3596 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO);
3597 } else /* Set File Size */ {
3598 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
3599 pSMB->InformationLevel =
3600 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO2);
3602 pSMB->InformationLevel =
3603 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO);
3605 pSMB->Reserved4 = 0;
3606 pSMB->hdr.smb_buf_length += byte_count;
3607 pSMB->ByteCount = cpu_to_le16(byte_count);
3608 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3609 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3612 ("Send error in SetFileInfo (SetFileSize) = %d",
3617 cifs_small_buf_release(pSMB);
3619 /* Note: On -EAGAIN error only caller can retry on handle based calls
3620 since file handle passed in no longer valid */
3625 /* Some legacy servers such as NT4 require that the file times be set on
3626 an open handle, rather than by pathname - this is awkward due to
3627 potential access conflicts on the open, but it is unavoidable for these
3628 old servers since the only other choice is to go from 100 nanosecond DCE
3629 time and resort to the original setpathinfo level which takes the ancient
3630 DOS time format with 2 second granularity */
3632 CIFSSMBSetFileTimes(const int xid, struct cifsTconInfo *tcon, const FILE_BASIC_INFO * data,
3635 struct smb_com_transaction2_sfi_req *pSMB = NULL;
3636 struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
3639 int bytes_returned = 0;
3640 __u16 params, param_offset, offset, byte_count, count;
3642 cFYI(1, ("Set Times (via SetFileInfo)"));
3643 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
3648 pSMBr = (struct smb_com_transaction2_sfi_rsp *)pSMB;
3650 /* At this point there is no need to override the current pid
3651 with the pid of the opener, but that could change if we someday
3652 use an existing handle (rather than opening one on the fly) */
3653 /* pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
3654 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));*/
3657 pSMB->MaxSetupCount = 0;
3661 pSMB->Reserved2 = 0;
3662 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
3663 offset = param_offset + params;
3665 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
3667 count = sizeof (FILE_BASIC_INFO);
3668 pSMB->MaxParameterCount = cpu_to_le16(2);
3669 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB PDU from sess */
3670 pSMB->SetupCount = 1;
3671 pSMB->Reserved3 = 0;
3672 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
3673 byte_count = 3 /* pad */ + params + count;
3674 pSMB->DataCount = cpu_to_le16(count);
3675 pSMB->ParameterCount = cpu_to_le16(params);
3676 pSMB->TotalDataCount = pSMB->DataCount;
3677 pSMB->TotalParameterCount = pSMB->ParameterCount;
3678 pSMB->ParameterOffset = cpu_to_le16(param_offset);
3679 pSMB->DataOffset = cpu_to_le16(offset);
3681 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
3682 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO2);
3684 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO);
3685 pSMB->Reserved4 = 0;
3686 pSMB->hdr.smb_buf_length += byte_count;
3687 pSMB->ByteCount = cpu_to_le16(byte_count);
3688 memcpy(data_offset,data,sizeof(FILE_BASIC_INFO));
3689 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3690 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3692 cFYI(1,("Send error in Set Time (SetFileInfo) = %d",rc));
3695 cifs_small_buf_release(pSMB);
3697 /* Note: On -EAGAIN error only caller can retry on handle based calls
3698 since file handle passed in no longer valid */
3705 CIFSSMBSetTimes(const int xid, struct cifsTconInfo *tcon, const char *fileName,
3706 const FILE_BASIC_INFO * data,
3707 const struct nls_table *nls_codepage, int remap)
3709 TRANSACTION2_SPI_REQ *pSMB = NULL;
3710 TRANSACTION2_SPI_RSP *pSMBr = NULL;
3713 int bytes_returned = 0;
3715 __u16 params, param_offset, offset, byte_count, count;
3717 cFYI(1, ("In SetTimes"));
3720 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3725 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3727 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
3728 PATH_MAX, nls_codepage, remap);
3729 name_len++; /* trailing null */
3731 } else { /* BB improve the check for buffer overruns BB */
3732 name_len = strnlen(fileName, PATH_MAX);
3733 name_len++; /* trailing null */
3734 strncpy(pSMB->FileName, fileName, name_len);
3737 params = 6 + name_len;
3738 count = sizeof (FILE_BASIC_INFO);
3739 pSMB->MaxParameterCount = cpu_to_le16(2);
3740 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
3741 pSMB->MaxSetupCount = 0;
3745 pSMB->Reserved2 = 0;
3746 param_offset = offsetof(struct smb_com_transaction2_spi_req,
3747 InformationLevel) - 4;
3748 offset = param_offset + params;
3749 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
3750 pSMB->ParameterOffset = cpu_to_le16(param_offset);
3751 pSMB->DataOffset = cpu_to_le16(offset);
3752 pSMB->SetupCount = 1;
3753 pSMB->Reserved3 = 0;
3754 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
3755 byte_count = 3 /* pad */ + params + count;
3757 pSMB->DataCount = cpu_to_le16(count);
3758 pSMB->ParameterCount = cpu_to_le16(params);
3759 pSMB->TotalDataCount = pSMB->DataCount;
3760 pSMB->TotalParameterCount = pSMB->ParameterCount;
3761 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
3762 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO2);
3764 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO);
3765 pSMB->Reserved4 = 0;
3766 pSMB->hdr.smb_buf_length += byte_count;
3767 memcpy(data_offset, data, sizeof (FILE_BASIC_INFO));
3768 pSMB->ByteCount = cpu_to_le16(byte_count);
3769 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3770 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3772 cFYI(1, ("SetPathInfo (times) returned %d", rc));
3775 cifs_buf_release(pSMB);
3783 /* Can not be used to set time stamps yet (due to old DOS time format) */
3784 /* Can be used to set attributes */
3785 #if 0 /* Possibly not needed - since it turns out that strangely NT4 has a bug
3786 handling it anyway and NT4 was what we thought it would be needed for
3787 Do not delete it until we prove whether needed for Win9x though */
3789 CIFSSMBSetAttrLegacy(int xid, struct cifsTconInfo *tcon, char *fileName,
3790 __u16 dos_attrs, const struct nls_table *nls_codepage)
3792 SETATTR_REQ *pSMB = NULL;
3793 SETATTR_RSP *pSMBr = NULL;
3798 cFYI(1, ("In SetAttrLegacy"));
3801 rc = smb_init(SMB_COM_SETATTR, 8, tcon, (void **) &pSMB,
3806 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3808 ConvertToUCS((__le16 *) pSMB->fileName, fileName,
3809 PATH_MAX, nls_codepage);
3810 name_len++; /* trailing null */
3812 } else { /* BB improve the check for buffer overruns BB */
3813 name_len = strnlen(fileName, PATH_MAX);
3814 name_len++; /* trailing null */
3815 strncpy(pSMB->fileName, fileName, name_len);
3817 pSMB->attr = cpu_to_le16(dos_attrs);
3818 pSMB->BufferFormat = 0x04;
3819 pSMB->hdr.smb_buf_length += name_len + 1;
3820 pSMB->ByteCount = cpu_to_le16(name_len + 1);
3821 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3822 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3824 cFYI(1, ("Error in LegacySetAttr = %d", rc));
3827 cifs_buf_release(pSMB);
3830 goto SetAttrLgcyRetry;
3834 #endif /* temporarily unneeded SetAttr legacy function */
3837 CIFSSMBUnixSetPerms(const int xid, struct cifsTconInfo *tcon,
3838 char *fileName, __u64 mode, __u64 uid, __u64 gid,
3839 dev_t device, const struct nls_table *nls_codepage,
3842 TRANSACTION2_SPI_REQ *pSMB = NULL;
3843 TRANSACTION2_SPI_RSP *pSMBr = NULL;
3846 int bytes_returned = 0;
3847 FILE_UNIX_BASIC_INFO *data_offset;
3848 __u16 params, param_offset, offset, count, byte_count;
3850 cFYI(1, ("In SetUID/GID/Mode"));
3852 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3857 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3859 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
3860 PATH_MAX, nls_codepage, remap);
3861 name_len++; /* trailing null */
3863 } else { /* BB improve the check for buffer overruns BB */
3864 name_len = strnlen(fileName, PATH_MAX);
3865 name_len++; /* trailing null */
3866 strncpy(pSMB->FileName, fileName, name_len);
3869 params = 6 + name_len;
3870 count = sizeof (FILE_UNIX_BASIC_INFO);
3871 pSMB->MaxParameterCount = cpu_to_le16(2);
3872 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
3873 pSMB->MaxSetupCount = 0;
3877 pSMB->Reserved2 = 0;
3878 param_offset = offsetof(struct smb_com_transaction2_spi_req,
3879 InformationLevel) - 4;
3880 offset = param_offset + params;
3882 (FILE_UNIX_BASIC_INFO *) ((char *) &pSMB->hdr.Protocol +
3884 memset(data_offset, 0, count);
3885 pSMB->DataOffset = cpu_to_le16(offset);
3886 pSMB->ParameterOffset = cpu_to_le16(param_offset);
3887 pSMB->SetupCount = 1;
3888 pSMB->Reserved3 = 0;
3889 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
3890 byte_count = 3 /* pad */ + params + count;
3891 pSMB->ParameterCount = cpu_to_le16(params);
3892 pSMB->DataCount = cpu_to_le16(count);
3893 pSMB->TotalParameterCount = pSMB->ParameterCount;
3894 pSMB->TotalDataCount = pSMB->DataCount;
3895 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_BASIC);
3896 pSMB->Reserved4 = 0;
3897 pSMB->hdr.smb_buf_length += byte_count;
3898 data_offset->Uid = cpu_to_le64(uid);
3899 data_offset->Gid = cpu_to_le64(gid);
3900 /* better to leave device as zero when it is */
3901 data_offset->DevMajor = cpu_to_le64(MAJOR(device));
3902 data_offset->DevMinor = cpu_to_le64(MINOR(device));
3903 data_offset->Permissions = cpu_to_le64(mode);
3906 data_offset->Type = cpu_to_le32(UNIX_FILE);
3907 else if(S_ISDIR(mode))
3908 data_offset->Type = cpu_to_le32(UNIX_DIR);
3909 else if(S_ISLNK(mode))
3910 data_offset->Type = cpu_to_le32(UNIX_SYMLINK);
3911 else if(S_ISCHR(mode))
3912 data_offset->Type = cpu_to_le32(UNIX_CHARDEV);
3913 else if(S_ISBLK(mode))
3914 data_offset->Type = cpu_to_le32(UNIX_BLOCKDEV);
3915 else if(S_ISFIFO(mode))
3916 data_offset->Type = cpu_to_le32(UNIX_FIFO);
3917 else if(S_ISSOCK(mode))
3918 data_offset->Type = cpu_to_le32(UNIX_SOCKET);
3921 pSMB->ByteCount = cpu_to_le16(byte_count);
3922 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3923 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3925 cFYI(1, ("SetPathInfo (perms) returned %d", rc));
3929 cifs_buf_release(pSMB);
3935 int CIFSSMBNotify(const int xid, struct cifsTconInfo *tcon,
3936 const int notify_subdirs, const __u16 netfid,
3937 __u32 filter, const struct nls_table *nls_codepage)
3940 struct smb_com_transaction_change_notify_req * pSMB = NULL;
3941 struct smb_com_transaction_change_notify_rsp * pSMBr = NULL;
3944 cFYI(1, ("In CIFSSMBNotify for file handle %d",(int)netfid));
3945 rc = smb_init(SMB_COM_NT_TRANSACT, 23, tcon, (void **) &pSMB,
3950 pSMB->TotalParameterCount = 0 ;
3951 pSMB->TotalDataCount = 0;
3952 pSMB->MaxParameterCount = cpu_to_le32(2);
3953 /* BB find exact data count max from sess structure BB */
3954 pSMB->MaxDataCount = 0; /* same in little endian or be */
3955 pSMB->MaxSetupCount = 4;
3957 pSMB->ParameterOffset = 0;
3958 pSMB->DataCount = 0;
3959 pSMB->DataOffset = 0;
3960 pSMB->SetupCount = 4; /* single byte does not need le conversion */
3961 pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_NOTIFY_CHANGE);
3962 pSMB->ParameterCount = pSMB->TotalParameterCount;
3964 pSMB->WatchTree = 1; /* one byte - no le conversion needed */
3965 pSMB->Reserved2 = 0;
3966 pSMB->CompletionFilter = cpu_to_le32(filter);
3967 pSMB->Fid = netfid; /* file handle always le */
3968 pSMB->ByteCount = 0;
3970 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3971 (struct smb_hdr *) pSMBr, &bytes_returned, -1);
3973 cFYI(1, ("Error in Notify = %d", rc));
3975 cifs_buf_release(pSMB);
3978 #ifdef CONFIG_CIFS_XATTR
3980 CIFSSMBQAllEAs(const int xid, struct cifsTconInfo *tcon,
3981 const unsigned char *searchName,
3982 char * EAData, size_t buf_size,
3983 const struct nls_table *nls_codepage, int remap)
3985 /* BB assumes one setup word */
3986 TRANSACTION2_QPI_REQ *pSMB = NULL;
3987 TRANSACTION2_QPI_RSP *pSMBr = NULL;
3991 struct fea * temp_fea;
3993 __u16 params, byte_count;
3995 cFYI(1, ("In Query All EAs path %s", searchName));
3997 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4002 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4004 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
4005 PATH_MAX, nls_codepage, remap);
4006 name_len++; /* trailing null */
4008 } else { /* BB improve the check for buffer overruns BB */
4009 name_len = strnlen(searchName, PATH_MAX);
4010 name_len++; /* trailing null */
4011 strncpy(pSMB->FileName, searchName, name_len);
4014 params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */ ;
4015 pSMB->TotalDataCount = 0;
4016 pSMB->MaxParameterCount = cpu_to_le16(2);
4017 pSMB->MaxDataCount = cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
4018 pSMB->MaxSetupCount = 0;
4022 pSMB->Reserved2 = 0;
4023 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4024 struct smb_com_transaction2_qpi_req ,InformationLevel) - 4);
4025 pSMB->DataCount = 0;
4026 pSMB->DataOffset = 0;
4027 pSMB->SetupCount = 1;
4028 pSMB->Reserved3 = 0;
4029 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
4030 byte_count = params + 1 /* pad */ ;
4031 pSMB->TotalParameterCount = cpu_to_le16(params);
4032 pSMB->ParameterCount = pSMB->TotalParameterCount;
4033 pSMB->InformationLevel = cpu_to_le16(SMB_INFO_QUERY_ALL_EAS);
4034 pSMB->Reserved4 = 0;
4035 pSMB->hdr.smb_buf_length += byte_count;
4036 pSMB->ByteCount = cpu_to_le16(byte_count);
4038 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4039 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4041 cFYI(1, ("Send error in QueryAllEAs = %d", rc));
4042 } else { /* decode response */
4043 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4045 /* BB also check enough total bytes returned */
4046 /* BB we need to improve the validity checking
4047 of these trans2 responses */
4048 if (rc || (pSMBr->ByteCount < 4))
4049 rc = -EIO; /* bad smb */
4050 /* else if (pFindData){
4051 memcpy((char *) pFindData,
4052 (char *) &pSMBr->hdr.Protocol +
4055 /* check that length of list is not more than bcc */
4056 /* check that each entry does not go beyond length
4058 /* check that each element of each entry does not
4059 go beyond end of list */
4060 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4061 struct fealist * ea_response_data;
4063 /* validate_trans2_offsets() */
4064 /* BB to check if(start of smb + data_offset > &bcc+ bcc)*/
4065 ea_response_data = (struct fealist *)
4066 (((char *) &pSMBr->hdr.Protocol) +
4068 name_len = le32_to_cpu(ea_response_data->list_len);
4069 cFYI(1,("ea length %d", name_len));
4071 /* returned EA size zeroed at top of function */
4072 cFYI(1,("empty EA list returned from server"));
4074 /* account for ea list len */
4076 temp_fea = ea_response_data->list;
4077 temp_ptr = (char *)temp_fea;
4078 while(name_len > 0) {
4082 rc += temp_fea->name_len;
4083 /* account for prefix user. and trailing null */
4085 if(rc<(int)buf_size) {
4086 memcpy(EAData,"user.",5);
4088 memcpy(EAData,temp_ptr,temp_fea->name_len);
4089 EAData+=temp_fea->name_len;
4090 /* null terminate name */
4092 EAData = EAData + 1;
4093 } else if(buf_size == 0) {
4094 /* skip copy - calc size only */
4096 /* stop before overrun buffer */
4100 name_len -= temp_fea->name_len;
4101 temp_ptr += temp_fea->name_len;
4102 /* account for trailing null */
4105 value_len = le16_to_cpu(temp_fea->value_len);
4106 name_len -= value_len;
4107 temp_ptr += value_len;
4108 /* BB check that temp_ptr is still within smb BB*/
4109 /* no trailing null to account for in value len */
4110 /* go on to next EA */
4111 temp_fea = (struct fea *)temp_ptr;
4117 cifs_buf_release(pSMB);
4124 ssize_t CIFSSMBQueryEA(const int xid,struct cifsTconInfo * tcon,
4125 const unsigned char * searchName,const unsigned char * ea_name,
4126 unsigned char * ea_value, size_t buf_size,
4127 const struct nls_table *nls_codepage, int remap)
4129 TRANSACTION2_QPI_REQ *pSMB = NULL;
4130 TRANSACTION2_QPI_RSP *pSMBr = NULL;
4134 struct fea * temp_fea;
4136 __u16 params, byte_count;
4138 cFYI(1, ("In Query EA path %s", searchName));
4140 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4145 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4147 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
4148 PATH_MAX, nls_codepage, remap);
4149 name_len++; /* trailing null */
4151 } else { /* BB improve the check for buffer overruns BB */
4152 name_len = strnlen(searchName, PATH_MAX);
4153 name_len++; /* trailing null */
4154 strncpy(pSMB->FileName, searchName, name_len);
4157 params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */ ;
4158 pSMB->TotalDataCount = 0;
4159 pSMB->MaxParameterCount = cpu_to_le16(2);
4160 pSMB->MaxDataCount = cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
4161 pSMB->MaxSetupCount = 0;
4165 pSMB->Reserved2 = 0;
4166 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4167 struct smb_com_transaction2_qpi_req ,InformationLevel) - 4);
4168 pSMB->DataCount = 0;
4169 pSMB->DataOffset = 0;
4170 pSMB->SetupCount = 1;
4171 pSMB->Reserved3 = 0;
4172 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
4173 byte_count = params + 1 /* pad */ ;
4174 pSMB->TotalParameterCount = cpu_to_le16(params);
4175 pSMB->ParameterCount = pSMB->TotalParameterCount;
4176 pSMB->InformationLevel = cpu_to_le16(SMB_INFO_QUERY_ALL_EAS);
4177 pSMB->Reserved4 = 0;
4178 pSMB->hdr.smb_buf_length += byte_count;
4179 pSMB->ByteCount = cpu_to_le16(byte_count);
4181 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4182 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4184 cFYI(1, ("Send error in Query EA = %d", rc));
4185 } else { /* decode response */
4186 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4188 /* BB also check enough total bytes returned */
4189 /* BB we need to improve the validity checking
4190 of these trans2 responses */
4191 if (rc || (pSMBr->ByteCount < 4))
4192 rc = -EIO; /* bad smb */
4193 /* else if (pFindData){
4194 memcpy((char *) pFindData,
4195 (char *) &pSMBr->hdr.Protocol +
4198 /* check that length of list is not more than bcc */
4199 /* check that each entry does not go beyond length
4201 /* check that each element of each entry does not
4202 go beyond end of list */
4203 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4204 struct fealist * ea_response_data;
4206 /* validate_trans2_offsets() */
4207 /* BB to check if(start of smb + data_offset > &bcc+ bcc)*/
4208 ea_response_data = (struct fealist *)
4209 (((char *) &pSMBr->hdr.Protocol) +
4211 name_len = le32_to_cpu(ea_response_data->list_len);
4212 cFYI(1,("ea length %d", name_len));
4214 /* returned EA size zeroed at top of function */
4215 cFYI(1,("empty EA list returned from server"));
4217 /* account for ea list len */
4219 temp_fea = ea_response_data->list;
4220 temp_ptr = (char *)temp_fea;
4221 /* loop through checking if we have a matching
4222 name and then return the associated value */
4223 while(name_len > 0) {
4227 value_len = le16_to_cpu(temp_fea->value_len);
4228 /* BB validate that value_len falls within SMB,
4229 even though maximum for name_len is 255 */
4230 if(memcmp(temp_fea->name,ea_name,
4231 temp_fea->name_len) == 0) {
4234 /* account for prefix user. and trailing null */
4235 if(rc<=(int)buf_size) {
4237 temp_fea->name+temp_fea->name_len+1,
4239 /* ea values, unlike ea names,
4240 are not null terminated */
4241 } else if(buf_size == 0) {
4242 /* skip copy - calc size only */
4244 /* stop before overrun buffer */
4249 name_len -= temp_fea->name_len;
4250 temp_ptr += temp_fea->name_len;
4251 /* account for trailing null */
4254 name_len -= value_len;
4255 temp_ptr += value_len;
4256 /* no trailing null to account for in value len */
4257 /* go on to next EA */
4258 temp_fea = (struct fea *)temp_ptr;
4264 cifs_buf_release(pSMB);
4272 CIFSSMBSetEA(const int xid, struct cifsTconInfo *tcon, const char *fileName,
4273 const char * ea_name, const void * ea_value,
4274 const __u16 ea_value_len, const struct nls_table *nls_codepage,
4277 struct smb_com_transaction2_spi_req *pSMB = NULL;
4278 struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
4279 struct fealist *parm_data;
4282 int bytes_returned = 0;
4283 __u16 params, param_offset, byte_count, offset, count;
4285 cFYI(1, ("In SetEA"));
4287 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4292 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4294 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
4295 PATH_MAX, nls_codepage, remap);
4296 name_len++; /* trailing null */
4298 } else { /* BB improve the check for buffer overruns BB */
4299 name_len = strnlen(fileName, PATH_MAX);
4300 name_len++; /* trailing null */
4301 strncpy(pSMB->FileName, fileName, name_len);
4304 params = 6 + name_len;
4306 /* done calculating parms using name_len of file name,
4307 now use name_len to calculate length of ea name
4308 we are going to create in the inode xattrs */
4312 name_len = strnlen(ea_name,255);
4314 count = sizeof(*parm_data) + ea_value_len + name_len + 1;
4315 pSMB->MaxParameterCount = cpu_to_le16(2);
4316 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB size from sess */
4317 pSMB->MaxSetupCount = 0;
4321 pSMB->Reserved2 = 0;
4322 param_offset = offsetof(struct smb_com_transaction2_spi_req,
4323 InformationLevel) - 4;
4324 offset = param_offset + params;
4325 pSMB->InformationLevel =
4326 cpu_to_le16(SMB_SET_FILE_EA);
4329 (struct fealist *) (((char *) &pSMB->hdr.Protocol) +
4331 pSMB->ParameterOffset = cpu_to_le16(param_offset);
4332 pSMB->DataOffset = cpu_to_le16(offset);
4333 pSMB->SetupCount = 1;
4334 pSMB->Reserved3 = 0;
4335 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
4336 byte_count = 3 /* pad */ + params + count;
4337 pSMB->DataCount = cpu_to_le16(count);
4338 parm_data->list_len = cpu_to_le32(count);
4339 parm_data->list[0].EA_flags = 0;
4340 /* we checked above that name len is less than 255 */
4341 parm_data->list[0].name_len = (__u8)name_len;;
4342 /* EA names are always ASCII */
4344 strncpy(parm_data->list[0].name,ea_name,name_len);
4345 parm_data->list[0].name[name_len] = 0;
4346 parm_data->list[0].value_len = cpu_to_le16(ea_value_len);
4347 /* caller ensures that ea_value_len is less than 64K but
4348 we need to ensure that it fits within the smb */
4350 /*BB add length check that it would fit in negotiated SMB buffer size BB */
4351 /* if(ea_value_len > buffer_size - 512 (enough for header)) */
4353 memcpy(parm_data->list[0].name+name_len+1,ea_value,ea_value_len);
4355 pSMB->TotalDataCount = pSMB->DataCount;
4356 pSMB->ParameterCount = cpu_to_le16(params);
4357 pSMB->TotalParameterCount = pSMB->ParameterCount;
4358 pSMB->Reserved4 = 0;
4359 pSMB->hdr.smb_buf_length += byte_count;
4360 pSMB->ByteCount = cpu_to_le16(byte_count);
4361 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4362 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4364 cFYI(1, ("SetPathInfo (EA) returned %d", rc));
4367 cifs_buf_release(pSMB);