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);
170 cifs_stats_inc(&tcon->num_smbs_sent);
175 /* If the return code is zero, this function must fill in request_buf pointer */
177 smb_init(int smb_command, int wct, struct cifsTconInfo *tcon,
178 void **request_buf /* returned */ ,
179 void **response_buf /* returned */ )
183 /* SMBs NegProt, SessSetup, uLogoff do not have tcon yet so
184 check for tcp and smb session status done differently
185 for those three - in the calling routine */
187 if((tcon->ses) && (tcon->ses->status != CifsExiting) &&
188 (tcon->ses->server)){
189 struct nls_table *nls_codepage;
190 /* Give Demultiplex thread up to 10 seconds to
191 reconnect, should be greater than cifs socket
192 timeout which is 7 seconds */
193 while(tcon->ses->server->tcpStatus == CifsNeedReconnect) {
194 wait_event_interruptible_timeout(tcon->ses->server->response_q,
195 (tcon->ses->server->tcpStatus == CifsGood), 10 * HZ);
196 if(tcon->ses->server->tcpStatus ==
198 /* on "soft" mounts we wait once */
199 if((tcon->retry == FALSE) ||
200 (tcon->ses->status == CifsExiting)) {
201 cFYI(1,("gave up waiting on reconnect in smb_init"));
203 } /* else "hard" mount - keep retrying
204 until process is killed or server
206 } else /* TCP session is reestablished now */
211 nls_codepage = load_nls_default();
212 /* need to prevent multiple threads trying to
213 simultaneously reconnect the same SMB session */
214 down(&tcon->ses->sesSem);
215 if(tcon->ses->status == CifsNeedReconnect)
216 rc = cifs_setup_session(0, tcon->ses,
218 if(!rc && (tcon->tidStatus == CifsNeedReconnect)) {
219 mark_open_files_invalid(tcon);
220 rc = CIFSTCon(0, tcon->ses, tcon->treeName,
222 up(&tcon->ses->sesSem);
224 atomic_inc(&tconInfoReconnectCount);
226 cFYI(1, ("reconnect tcon rc = %d", rc));
227 /* Removed call to reopen open files here -
228 it is safer (and faster) to reopen files
229 one at a time as needed in read and write */
231 /* Check if handle based operation so we
232 know whether we can continue or not without
233 returning to caller to reset file handle */
234 switch(smb_command) {
235 case SMB_COM_READ_ANDX:
236 case SMB_COM_WRITE_ANDX:
238 case SMB_COM_FIND_CLOSE2:
239 case SMB_COM_LOCKING_ANDX: {
240 unload_nls(nls_codepage);
245 up(&tcon->ses->sesSem);
247 unload_nls(nls_codepage);
256 *request_buf = cifs_buf_get();
257 if (*request_buf == NULL) {
258 /* BB should we add a retry in here if not a writepage? */
261 /* Although the original thought was we needed the response buf for */
262 /* potential retries of smb operations it turns out we can determine */
263 /* from the mid flags when the request buffer can be resent without */
264 /* having to use a second distinct buffer for the response */
265 *response_buf = *request_buf;
267 header_assemble((struct smb_hdr *) *request_buf, smb_command, tcon,
271 cifs_stats_inc(&tcon->num_smbs_sent);
276 static int validate_t2(struct smb_t2_rsp * pSMB)
282 /* check for plausible wct, bcc and t2 data and parm sizes */
283 /* check for parm and data offset going beyond end of smb */
284 if(pSMB->hdr.WordCount >= 10) {
285 if((le16_to_cpu(pSMB->t2_rsp.ParameterOffset) <= 1024) &&
286 (le16_to_cpu(pSMB->t2_rsp.DataOffset) <= 1024)) {
287 /* check that bcc is at least as big as parms + data */
288 /* check that bcc is less than negotiated smb buffer */
289 total_size = le16_to_cpu(pSMB->t2_rsp.ParameterCount);
290 if(total_size < 512) {
291 total_size+=le16_to_cpu(pSMB->t2_rsp.DataCount);
292 /* BCC le converted in SendReceive */
293 pBCC = (pSMB->hdr.WordCount * 2) +
294 sizeof(struct smb_hdr) +
296 if((total_size <= (*(u16 *)pBCC)) &&
298 CIFSMaxBufSize+MAX_CIFS_HDR_SIZE)) {
305 cifs_dump_mem("Invalid transact2 SMB: ",(char *)pSMB,
306 sizeof(struct smb_t2_rsp) + 16);
310 CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses)
313 NEGOTIATE_RSP *pSMBr;
316 struct TCP_Server_Info * server;
320 server = ses->server;
325 rc = smb_init(SMB_COM_NEGOTIATE, 0, NULL /* no tcon yet */ ,
326 (void **) &pSMB, (void **) &pSMBr);
329 pSMB->hdr.Mid = GetNextMid(server);
330 pSMB->hdr.Flags2 |= SMBFLG2_UNICODE;
331 if (extended_security)
332 pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC;
334 count = strlen(protocols[0].name) + 1;
335 strncpy(pSMB->DialectsArray, protocols[0].name, 30);
336 /* null guaranteed to be at end of source and target buffers anyway */
338 pSMB->hdr.smb_buf_length += count;
339 pSMB->ByteCount = cpu_to_le16(count);
341 rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB,
342 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
344 server->secMode = pSMBr->SecurityMode;
345 server->secType = NTLM; /* BB override default for
346 NTLMv2 or kerberos v5 */
347 /* one byte - no need to convert this or EncryptionKeyLen
348 from little endian */
349 server->maxReq = le16_to_cpu(pSMBr->MaxMpxCount);
350 /* probably no need to store and check maxvcs */
352 min(le32_to_cpu(pSMBr->MaxBufferSize),
353 (__u32) CIFSMaxBufSize + MAX_CIFS_HDR_SIZE);
354 server->maxRw = le32_to_cpu(pSMBr->MaxRawSize);
355 cFYI(0, ("Max buf = %d ", ses->server->maxBuf));
356 GETU32(ses->server->sessid) = le32_to_cpu(pSMBr->SessionKey);
357 server->capabilities = le32_to_cpu(pSMBr->Capabilities);
358 server->timeZone = le16_to_cpu(pSMBr->ServerTimeZone);
359 /* BB with UTC do we ever need to be using srvr timezone? */
360 if (pSMBr->EncryptionKeyLength == CIFS_CRYPTO_KEY_SIZE) {
361 memcpy(server->cryptKey, pSMBr->u.EncryptionKey,
362 CIFS_CRYPTO_KEY_SIZE);
363 } else if ((pSMBr->hdr.Flags2 & SMBFLG2_EXT_SEC)
364 && (pSMBr->EncryptionKeyLength == 0)) {
365 /* decode security blob */
369 /* BB might be helpful to save off the domain of server here */
371 if ((pSMBr->hdr.Flags2 & SMBFLG2_EXT_SEC) &&
372 (server->capabilities & CAP_EXTENDED_SECURITY)) {
373 count = pSMBr->ByteCount;
376 else if (count == 16) {
377 server->secType = RawNTLMSSP;
378 if (server->socketUseCount.counter > 1) {
380 (server->server_GUID,
381 pSMBr->u.extended_response.
384 ("UID of server does not match previous connection to same ip address"));
392 memcpy(server->server_GUID,
393 pSMBr->u.extended_response.
396 rc = decode_negTokenInit(pSMBr->u.
402 /* BB Need to fill struct for sessetup here */
409 server->capabilities &= ~CAP_EXTENDED_SECURITY;
410 if(sign_CIFS_PDUs == FALSE) {
411 if(server->secMode & SECMODE_SIGN_REQUIRED)
413 ("Server requires /proc/fs/cifs/PacketSigningEnabled"));
414 server->secMode &= ~(SECMODE_SIGN_ENABLED | SECMODE_SIGN_REQUIRED);
415 } else if(sign_CIFS_PDUs == 1) {
416 if((server->secMode & SECMODE_SIGN_REQUIRED) == 0)
417 server->secMode &= ~(SECMODE_SIGN_ENABLED | SECMODE_SIGN_REQUIRED);
422 cifs_buf_release(pSMB);
427 CIFSSMBTDis(const int xid, struct cifsTconInfo *tcon)
429 struct smb_hdr *smb_buffer;
430 struct smb_hdr *smb_buffer_response; /* BB removeme BB */
434 cFYI(1, ("In tree disconnect"));
436 * If last user of the connection and
437 * connection alive - disconnect it
438 * If this is the last connection on the server session disconnect it
439 * (and inside session disconnect we should check if tcp socket needs
440 * to be freed and kernel thread woken up).
443 down(&tcon->tconSem);
447 atomic_dec(&tcon->useCount);
448 if (atomic_read(&tcon->useCount) > 0) {
453 /* No need to return error on this operation if tid invalidated and
454 closed on server already e.g. due to tcp session crashing */
455 if(tcon->tidStatus == CifsNeedReconnect) {
460 if((tcon->ses == NULL) || (tcon->ses->server == NULL)) {
464 rc = small_smb_init(SMB_COM_TREE_DISCONNECT, 0, tcon,
465 (void **)&smb_buffer);
470 smb_buffer_response = smb_buffer; /* BB removeme BB */
472 rc = SendReceive(xid, tcon->ses, smb_buffer, smb_buffer_response,
475 cFYI(1, ("Tree disconnect failed %d", rc));
478 cifs_small_buf_release(smb_buffer);
481 /* No need to return error on this operation if tid invalidated and
482 closed on server already e.g. due to tcp session crashing */
490 CIFSSMBLogoff(const int xid, struct cifsSesInfo *ses)
492 struct smb_hdr *smb_buffer_response;
493 LOGOFF_ANDX_REQ *pSMB;
497 cFYI(1, ("In SMBLogoff for session disconnect"));
503 atomic_dec(&ses->inUse);
504 if (atomic_read(&ses->inUse) > 0) {
508 rc = small_smb_init(SMB_COM_LOGOFF_ANDX, 2, NULL, (void **)&pSMB);
514 smb_buffer_response = (struct smb_hdr *)pSMB; /* BB removeme BB */
517 pSMB->hdr.Mid = GetNextMid(ses->server);
519 if(ses->server->secMode &
520 (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
521 pSMB->hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
524 pSMB->hdr.Uid = ses->Suid;
526 pSMB->AndXCommand = 0xFF;
527 rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB,
528 smb_buffer_response, &length, 0);
530 atomic_dec(&ses->server->socketUseCount);
531 if (atomic_read(&ses->server->socketUseCount) == 0) {
532 spin_lock(&GlobalMid_Lock);
533 ses->server->tcpStatus = CifsExiting;
534 spin_unlock(&GlobalMid_Lock);
539 cifs_small_buf_release(pSMB);
541 /* if session dead then we do not need to do ulogoff,
542 since server closed smb session, no sense reporting
550 CIFSSMBDelFile(const int xid, struct cifsTconInfo *tcon, const char *fileName,
551 const struct nls_table *nls_codepage, int remap)
553 DELETE_FILE_REQ *pSMB = NULL;
554 DELETE_FILE_RSP *pSMBr = NULL;
560 rc = smb_init(SMB_COM_DELETE, 1, tcon, (void **) &pSMB,
565 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
567 cifsConvertToUCS((__le16 *) pSMB->fileName, fileName,
568 PATH_MAX, nls_codepage, remap);
569 name_len++; /* trailing null */
571 } else { /* BB improve check for buffer overruns BB */
572 name_len = strnlen(fileName, PATH_MAX);
573 name_len++; /* trailing null */
574 strncpy(pSMB->fileName, fileName, name_len);
576 pSMB->SearchAttributes =
577 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM);
578 pSMB->BufferFormat = 0x04;
579 pSMB->hdr.smb_buf_length += name_len + 1;
580 pSMB->ByteCount = cpu_to_le16(name_len + 1);
581 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
582 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
583 cifs_stats_inc(&tcon->num_deletes);
585 cFYI(1, ("Error in RMFile = %d", rc));
588 cifs_buf_release(pSMB);
596 CIFSSMBRmDir(const int xid, struct cifsTconInfo *tcon, const char *dirName,
597 const struct nls_table *nls_codepage, int remap)
599 DELETE_DIRECTORY_REQ *pSMB = NULL;
600 DELETE_DIRECTORY_RSP *pSMBr = NULL;
605 cFYI(1, ("In CIFSSMBRmDir"));
607 rc = smb_init(SMB_COM_DELETE_DIRECTORY, 0, tcon, (void **) &pSMB,
612 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
613 name_len = cifsConvertToUCS((__le16 *) pSMB->DirName, dirName,
614 PATH_MAX, nls_codepage, remap);
615 name_len++; /* trailing null */
617 } else { /* BB improve check for buffer overruns BB */
618 name_len = strnlen(dirName, PATH_MAX);
619 name_len++; /* trailing null */
620 strncpy(pSMB->DirName, dirName, name_len);
623 pSMB->BufferFormat = 0x04;
624 pSMB->hdr.smb_buf_length += name_len + 1;
625 pSMB->ByteCount = cpu_to_le16(name_len + 1);
626 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
627 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
628 cifs_stats_inc(&tcon->num_rmdirs);
630 cFYI(1, ("Error in RMDir = %d", rc));
633 cifs_buf_release(pSMB);
640 CIFSSMBMkDir(const int xid, struct cifsTconInfo *tcon,
641 const char *name, const struct nls_table *nls_codepage, int remap)
644 CREATE_DIRECTORY_REQ *pSMB = NULL;
645 CREATE_DIRECTORY_RSP *pSMBr = NULL;
649 cFYI(1, ("In CIFSSMBMkDir"));
651 rc = smb_init(SMB_COM_CREATE_DIRECTORY, 0, tcon, (void **) &pSMB,
656 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
657 name_len = cifsConvertToUCS((__le16 *) pSMB->DirName, name,
658 PATH_MAX, nls_codepage, remap);
659 name_len++; /* trailing null */
661 } else { /* BB improve check for buffer overruns BB */
662 name_len = strnlen(name, PATH_MAX);
663 name_len++; /* trailing null */
664 strncpy(pSMB->DirName, name, name_len);
667 pSMB->BufferFormat = 0x04;
668 pSMB->hdr.smb_buf_length += name_len + 1;
669 pSMB->ByteCount = cpu_to_le16(name_len + 1);
670 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
671 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
672 cifs_stats_inc(&tcon->num_mkdirs);
674 cFYI(1, ("Error in Mkdir = %d", rc));
677 cifs_buf_release(pSMB);
684 CIFSSMBOpen(const int xid, struct cifsTconInfo *tcon,
685 const char *fileName, const int openDisposition,
686 const int access_flags, const int create_options, __u16 * netfid,
687 int *pOplock, FILE_ALL_INFO * pfile_info,
688 const struct nls_table *nls_codepage, int remap)
691 OPEN_REQ *pSMB = NULL;
692 OPEN_RSP *pSMBr = NULL;
698 rc = smb_init(SMB_COM_NT_CREATE_ANDX, 24, tcon, (void **) &pSMB,
703 pSMB->AndXCommand = 0xFF; /* none */
705 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
706 count = 1; /* account for one byte pad to word boundary */
708 cifsConvertToUCS((__le16 *) (pSMB->fileName + 1),
709 fileName, PATH_MAX, nls_codepage, remap);
710 name_len++; /* trailing null */
712 pSMB->NameLength = cpu_to_le16(name_len);
713 } else { /* BB improve check for buffer overruns BB */
714 count = 0; /* no pad */
715 name_len = strnlen(fileName, PATH_MAX);
716 name_len++; /* trailing null */
717 pSMB->NameLength = cpu_to_le16(name_len);
718 strncpy(pSMB->fileName, fileName, name_len);
720 if (*pOplock & REQ_OPLOCK)
721 pSMB->OpenFlags = cpu_to_le32(REQ_OPLOCK);
722 else if (*pOplock & REQ_BATCHOPLOCK) {
723 pSMB->OpenFlags = cpu_to_le32(REQ_BATCHOPLOCK);
725 pSMB->DesiredAccess = cpu_to_le32(access_flags);
726 pSMB->AllocationSize = 0;
727 /* set file as system file if special file such
728 as fifo and server expecting SFU style and
729 no Unix extensions */
730 if(create_options & CREATE_OPTION_SPECIAL)
731 pSMB->FileAttributes = cpu_to_le32(ATTR_SYSTEM);
733 pSMB->FileAttributes = cpu_to_le32(ATTR_NORMAL);
734 /* XP does not handle ATTR_POSIX_SEMANTICS */
735 /* but it helps speed up case sensitive checks for other
736 servers such as Samba */
737 if (tcon->ses->capabilities & CAP_UNIX)
738 pSMB->FileAttributes |= cpu_to_le32(ATTR_POSIX_SEMANTICS);
740 /* if ((omode & S_IWUGO) == 0)
741 pSMB->FileAttributes |= cpu_to_le32(ATTR_READONLY);*/
742 /* Above line causes problems due to vfs splitting create into two
743 pieces - need to set mode after file created not while it is
745 pSMB->ShareAccess = cpu_to_le32(FILE_SHARE_ALL);
746 pSMB->CreateDisposition = cpu_to_le32(openDisposition);
747 pSMB->CreateOptions = cpu_to_le32(create_options & CREATE_OPTIONS_MASK);
748 /* BB Expirement with various impersonation levels and verify */
749 pSMB->ImpersonationLevel = cpu_to_le32(SECURITY_IMPERSONATION);
750 pSMB->SecurityFlags =
751 SECURITY_CONTEXT_TRACKING | SECURITY_EFFECTIVE_ONLY;
754 pSMB->hdr.smb_buf_length += count;
756 pSMB->ByteCount = cpu_to_le16(count);
757 /* long_op set to 1 to allow for oplock break timeouts */
758 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
759 (struct smb_hdr *) pSMBr, &bytes_returned, 1);
760 cifs_stats_inc(&tcon->num_opens);
762 cFYI(1, ("Error in Open = %d", rc));
764 *pOplock = pSMBr->OplockLevel; /* 1 byte no need to le_to_cpu */
765 *netfid = pSMBr->Fid; /* cifs fid stays in le */
766 /* Let caller know file was created so we can set the mode. */
767 /* Do we care about the CreateAction in any other cases? */
768 if(cpu_to_le32(FILE_CREATE) == pSMBr->CreateAction)
769 *pOplock |= CIFS_CREATE_ACTION;
771 memcpy((char *)pfile_info,(char *)&pSMBr->CreationTime,
772 36 /* CreationTime to Attributes */);
773 /* the file_info buf is endian converted by caller */
774 pfile_info->AllocationSize = pSMBr->AllocationSize;
775 pfile_info->EndOfFile = pSMBr->EndOfFile;
776 pfile_info->NumberOfLinks = cpu_to_le32(1);
780 cifs_buf_release(pSMB);
786 /* If no buffer passed in, then caller wants to do the copy
787 as in the case of readpages so the SMB buffer must be
788 freed by the caller */
791 CIFSSMBRead(const int xid, struct cifsTconInfo *tcon,
792 const int netfid, const unsigned int count,
793 const __u64 lseek, unsigned int *nbytes, char **buf)
796 READ_REQ *pSMB = NULL;
797 READ_RSP *pSMBr = NULL;
798 char *pReadData = NULL;
801 cFYI(1,("Reading %d bytes on fid %d",count,netfid));
804 rc = smb_init(SMB_COM_READ_ANDX, 12, tcon, (void **) &pSMB,
809 /* tcon and ses pointer are checked in smb_init */
810 if (tcon->ses->server == NULL)
811 return -ECONNABORTED;
813 pSMB->AndXCommand = 0xFF; /* none */
815 pSMB->OffsetLow = cpu_to_le32(lseek & 0xFFFFFFFF);
816 pSMB->OffsetHigh = cpu_to_le32(lseek >> 32);
818 pSMB->MaxCount = cpu_to_le16(count & 0xFFFF);
819 pSMB->MaxCountHigh = cpu_to_le32(count >> 16);
820 pSMB->ByteCount = 0; /* no need to do le conversion since it is 0 */
822 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
823 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
824 cifs_stats_inc(&tcon->num_reads);
826 cERROR(1, ("Send error in read = %d", rc));
828 int data_length = le16_to_cpu(pSMBr->DataLengthHigh);
829 data_length = data_length << 16;
830 data_length += le16_to_cpu(pSMBr->DataLength);
831 *nbytes = data_length;
833 /*check that DataLength would not go beyond end of SMB */
834 if ((data_length > CIFSMaxBufSize)
835 || (data_length > count)) {
836 cFYI(1,("bad length %d for count %d",data_length,count));
841 (char *) (&pSMBr->hdr.Protocol) +
842 le16_to_cpu(pSMBr->DataOffset);
843 /* if(rc = copy_to_user(buf, pReadData, data_length)) {
844 cERROR(1,("Faulting on read rc = %d",rc));
846 }*/ /* can not use copy_to_user when using page cache*/
848 memcpy(*buf,pReadData,data_length);
852 cifs_buf_release(pSMB);
856 /* Note: On -EAGAIN error only caller can retry on handle based calls
857 since file handle passed in no longer valid */
862 CIFSSMBWrite(const int xid, struct cifsTconInfo *tcon,
863 const int netfid, const unsigned int count,
864 const __u64 offset, unsigned int *nbytes, const char *buf,
865 const char __user * ubuf, const int long_op)
868 WRITE_REQ *pSMB = NULL;
869 WRITE_RSP *pSMBr = NULL;
874 /* cFYI(1,("write at %lld %d bytes",offset,count));*/
875 rc = smb_init(SMB_COM_WRITE_ANDX, 14, tcon, (void **) &pSMB,
879 /* tcon and ses pointer are checked in smb_init */
880 if (tcon->ses->server == NULL)
881 return -ECONNABORTED;
883 pSMB->AndXCommand = 0xFF; /* none */
885 pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF);
886 pSMB->OffsetHigh = cpu_to_le32(offset >> 32);
887 pSMB->Reserved = 0xFFFFFFFF;
891 /* Can increase buffer size if buffer is big enough in some cases - ie we
892 can send more if LARGE_WRITE_X capability returned by the server and if
893 our buffer is big enough or if we convert to iovecs on socket writes
894 and eliminate the copy to the CIFS buffer */
895 if(tcon->ses->capabilities & CAP_LARGE_WRITE_X) {
896 bytes_sent = min_t(const unsigned int, CIFSMaxBufSize, count);
898 bytes_sent = (tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE)
902 if (bytes_sent > count)
905 cpu_to_le16(offsetof(struct smb_com_write_req,Data) - 4);
907 memcpy(pSMB->Data,buf,bytes_sent);
909 if(copy_from_user(pSMB->Data,ubuf,bytes_sent)) {
910 cifs_buf_release(pSMB);
915 cifs_buf_release(pSMB);
919 byte_count = bytes_sent + 1 /* pad */ ; /* BB fix this for sends > 64K */
920 pSMB->DataLengthLow = cpu_to_le16(bytes_sent & 0xFFFF);
921 pSMB->DataLengthHigh = cpu_to_le16(bytes_sent >> 16);
922 pSMB->hdr.smb_buf_length += bytes_sent+1;
923 pSMB->ByteCount = cpu_to_le16(byte_count);
925 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
926 (struct smb_hdr *) pSMBr, &bytes_returned, long_op);
927 cifs_stats_inc(&tcon->num_writes);
929 cFYI(1, ("Send error in write = %d", rc));
932 *nbytes = le16_to_cpu(pSMBr->CountHigh);
933 *nbytes = (*nbytes) << 16;
934 *nbytes += le16_to_cpu(pSMBr->Count);
937 cifs_buf_release(pSMB);
939 /* Note: On -EAGAIN error only caller can retry on handle based calls
940 since file handle passed in no longer valid */
945 #ifdef CONFIG_CIFS_EXPERIMENTAL
947 CIFSSMBWrite2(const int xid, struct cifsTconInfo *tcon,
948 const int netfid, const unsigned int count,
949 const __u64 offset, unsigned int *nbytes, const char *buf,
953 WRITE_REQ *pSMB = NULL;
959 cFYI(1,("write2 at %lld %d bytes",offset,count)); /* BB removeme BB */
960 rc = small_smb_init(SMB_COM_WRITE_ANDX, 14, tcon, (void **) &pSMB);
963 /* tcon and ses pointer are checked in smb_init */
964 if (tcon->ses->server == NULL)
965 return -ECONNABORTED;
967 pSMB->AndXCommand = 0xFF; /* none */
969 pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF);
970 pSMB->OffsetHigh = cpu_to_le32(offset >> 32);
971 pSMB->Reserved = 0xFFFFFFFF;
975 /* Can increase buffer size if buffer is big enough in some cases - ie
976 can send more if LARGE_WRITE_X capability returned by the server and if
977 our buffer is big enough or if we convert to iovecs on socket writes
978 and eliminate the copy to the CIFS buffer */
979 if(tcon->ses->capabilities & CAP_LARGE_WRITE_X) {
980 bytes_sent = min_t(const unsigned int, CIFSMaxBufSize, count);
982 bytes_sent = (tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE)
986 if (bytes_sent > count)
989 cpu_to_le16(offsetof(struct smb_com_write_req,Data) - 4);
991 byte_count = bytes_sent + 1 /* pad */ ; /* BB fix this for sends > 64K */
992 pSMB->DataLengthLow = cpu_to_le16(bytes_sent & 0xFFFF);
993 pSMB->DataLengthHigh = cpu_to_le16(bytes_sent >> 16);
994 smb_hdr_len = pSMB->hdr.smb_buf_length + 1; /* hdr + 1 byte pad */
995 pSMB->hdr.smb_buf_length += bytes_sent+1;
996 pSMB->ByteCount = cpu_to_le16(byte_count);
998 rc = SendReceive2(xid, tcon->ses, (struct smb_hdr *) pSMB, smb_hdr_len,
999 buf, bytes_sent, &bytes_returned, long_op);
1000 cifs_stats_inc(&tcon->num_writes);
1002 cFYI(1, ("Send error in write = %d", rc));
1005 WRITE_RSP * pSMBr = (WRITE_RSP *)pSMB;
1006 *nbytes = le16_to_cpu(pSMBr->CountHigh);
1007 *nbytes = (*nbytes) << 16;
1008 *nbytes += le16_to_cpu(pSMBr->Count);
1011 cifs_small_buf_release(pSMB);
1013 /* Note: On -EAGAIN error only caller can retry on handle based calls
1014 since file handle passed in no longer valid */
1020 #endif /* CIFS_EXPERIMENTAL */
1023 CIFSSMBLock(const int xid, struct cifsTconInfo *tcon,
1024 const __u16 smb_file_id, const __u64 len,
1025 const __u64 offset, const __u32 numUnlock,
1026 const __u32 numLock, const __u8 lockType, const int waitFlag)
1029 LOCK_REQ *pSMB = NULL;
1030 LOCK_RSP *pSMBr = NULL;
1035 cFYI(1, ("In CIFSSMBLock - timeout %d numLock %d",waitFlag,numLock));
1036 rc = small_smb_init(SMB_COM_LOCKING_ANDX, 8, tcon, (void **) &pSMB);
1041 pSMBr = (LOCK_RSP *)pSMB; /* BB removeme BB */
1043 if(lockType == LOCKING_ANDX_OPLOCK_RELEASE) {
1044 timeout = -1; /* no response expected */
1046 } else if (waitFlag == TRUE) {
1047 timeout = 3; /* blocking operation, no timeout */
1048 pSMB->Timeout = cpu_to_le32(-1);/* blocking - do not time out */
1053 pSMB->NumberOfLocks = cpu_to_le16(numLock);
1054 pSMB->NumberOfUnlocks = cpu_to_le16(numUnlock);
1055 pSMB->LockType = lockType;
1056 pSMB->AndXCommand = 0xFF; /* none */
1057 pSMB->Fid = smb_file_id; /* netfid stays le */
1059 if((numLock != 0) || (numUnlock != 0)) {
1060 pSMB->Locks[0].Pid = cpu_to_le16(current->tgid);
1061 /* BB where to store pid high? */
1062 pSMB->Locks[0].LengthLow = cpu_to_le32((u32)len);
1063 pSMB->Locks[0].LengthHigh = cpu_to_le32((u32)(len>>32));
1064 pSMB->Locks[0].OffsetLow = cpu_to_le32((u32)offset);
1065 pSMB->Locks[0].OffsetHigh = cpu_to_le32((u32)(offset>>32));
1066 count = sizeof(LOCKING_ANDX_RANGE);
1071 pSMB->hdr.smb_buf_length += count;
1072 pSMB->ByteCount = cpu_to_le16(count);
1074 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1075 (struct smb_hdr *) pSMBr, &bytes_returned, timeout);
1076 cifs_stats_inc(&tcon->num_locks);
1078 cFYI(1, ("Send error in Lock = %d", rc));
1080 cifs_small_buf_release(pSMB);
1082 /* Note: On -EAGAIN error only caller can retry on handle based calls
1083 since file handle passed in no longer valid */
1088 CIFSSMBClose(const int xid, struct cifsTconInfo *tcon, int smb_file_id)
1091 CLOSE_REQ *pSMB = NULL;
1092 CLOSE_RSP *pSMBr = NULL;
1094 cFYI(1, ("In CIFSSMBClose"));
1096 /* do not retry on dead session on close */
1097 rc = small_smb_init(SMB_COM_CLOSE, 3, tcon, (void **) &pSMB);
1103 pSMBr = (CLOSE_RSP *)pSMB; /* BB removeme BB */
1105 pSMB->FileID = (__u16) smb_file_id;
1106 pSMB->LastWriteTime = 0;
1107 pSMB->ByteCount = 0;
1108 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1109 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1110 cifs_stats_inc(&tcon->num_closes);
1113 /* EINTR is expected when user ctl-c to kill app */
1114 cERROR(1, ("Send error in Close = %d", rc));
1118 cifs_small_buf_release(pSMB);
1120 /* Since session is dead, file will be closed on server already */
1128 CIFSSMBRename(const int xid, struct cifsTconInfo *tcon,
1129 const char *fromName, const char *toName,
1130 const struct nls_table *nls_codepage, int remap)
1133 RENAME_REQ *pSMB = NULL;
1134 RENAME_RSP *pSMBr = NULL;
1136 int name_len, name_len2;
1139 cFYI(1, ("In CIFSSMBRename"));
1141 rc = smb_init(SMB_COM_RENAME, 1, tcon, (void **) &pSMB,
1146 pSMB->BufferFormat = 0x04;
1147 pSMB->SearchAttributes =
1148 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
1151 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1153 cifsConvertToUCS((__le16 *) pSMB->OldFileName, fromName,
1154 PATH_MAX, nls_codepage, remap);
1155 name_len++; /* trailing null */
1157 pSMB->OldFileName[name_len] = 0x04; /* pad */
1158 /* protocol requires ASCII signature byte on Unicode string */
1159 pSMB->OldFileName[name_len + 1] = 0x00;
1161 cifsConvertToUCS((__le16 *) &pSMB->OldFileName[name_len + 2],
1162 toName, PATH_MAX, nls_codepage, remap);
1163 name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
1164 name_len2 *= 2; /* convert to bytes */
1165 } else { /* BB improve the check for buffer overruns BB */
1166 name_len = strnlen(fromName, PATH_MAX);
1167 name_len++; /* trailing null */
1168 strncpy(pSMB->OldFileName, fromName, name_len);
1169 name_len2 = strnlen(toName, PATH_MAX);
1170 name_len2++; /* trailing null */
1171 pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */
1172 strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2);
1173 name_len2++; /* trailing null */
1174 name_len2++; /* signature byte */
1177 count = 1 /* 1st signature byte */ + name_len + name_len2;
1178 pSMB->hdr.smb_buf_length += count;
1179 pSMB->ByteCount = cpu_to_le16(count);
1181 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1182 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1183 cifs_stats_inc(&tcon->num_renames);
1185 cFYI(1, ("Send error in rename = %d", rc));
1188 cifs_buf_release(pSMB);
1196 int CIFSSMBRenameOpenFile(const int xid,struct cifsTconInfo *pTcon,
1197 int netfid, char * target_name,
1198 const struct nls_table * nls_codepage, int remap)
1200 struct smb_com_transaction2_sfi_req *pSMB = NULL;
1201 struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
1202 struct set_file_rename * rename_info;
1204 char dummy_string[30];
1206 int bytes_returned = 0;
1208 __u16 params, param_offset, offset, count, byte_count;
1210 cFYI(1, ("Rename to File by handle"));
1211 rc = smb_init(SMB_COM_TRANSACTION2, 15, pTcon, (void **) &pSMB,
1217 pSMB->MaxSetupCount = 0;
1221 pSMB->Reserved2 = 0;
1222 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
1223 offset = param_offset + params;
1225 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
1226 rename_info = (struct set_file_rename *) data_offset;
1227 pSMB->MaxParameterCount = cpu_to_le16(2);
1228 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB PDU from sess */
1229 pSMB->SetupCount = 1;
1230 pSMB->Reserved3 = 0;
1231 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
1232 byte_count = 3 /* pad */ + params;
1233 pSMB->ParameterCount = cpu_to_le16(params);
1234 pSMB->TotalParameterCount = pSMB->ParameterCount;
1235 pSMB->ParameterOffset = cpu_to_le16(param_offset);
1236 pSMB->DataOffset = cpu_to_le16(offset);
1237 /* construct random name ".cifs_tmp<inodenum><mid>" */
1238 rename_info->overwrite = cpu_to_le32(1);
1239 rename_info->root_fid = 0;
1240 /* unicode only call */
1241 if(target_name == NULL) {
1242 sprintf(dummy_string,"cifs%x",pSMB->hdr.Mid);
1243 len_of_str = cifsConvertToUCS((__le16 *)rename_info->target_name,
1244 dummy_string, 24, nls_codepage, remap);
1246 len_of_str = cifsConvertToUCS((__le16 *)rename_info->target_name,
1247 target_name, PATH_MAX, nls_codepage, remap);
1249 rename_info->target_name_len = cpu_to_le32(2 * len_of_str);
1250 count = 12 /* sizeof(struct set_file_rename) */ + (2 * len_of_str) + 2;
1251 byte_count += count;
1252 pSMB->DataCount = cpu_to_le16(count);
1253 pSMB->TotalDataCount = pSMB->DataCount;
1255 pSMB->InformationLevel =
1256 cpu_to_le16(SMB_SET_FILE_RENAME_INFORMATION);
1257 pSMB->Reserved4 = 0;
1258 pSMB->hdr.smb_buf_length += byte_count;
1259 pSMB->ByteCount = cpu_to_le16(byte_count);
1260 rc = SendReceive(xid, pTcon->ses, (struct smb_hdr *) pSMB,
1261 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1262 cifs_stats_inc(&pTcon->num_t2renames);
1264 cFYI(1,("Send error in Rename (by file handle) = %d", rc));
1267 cifs_buf_release(pSMB);
1269 /* Note: On -EAGAIN error only caller can retry on handle based calls
1270 since file handle passed in no longer valid */
1276 CIFSSMBCopy(const int xid, struct cifsTconInfo *tcon, const char * fromName,
1277 const __u16 target_tid, const char *toName, const int flags,
1278 const struct nls_table *nls_codepage, int remap)
1281 COPY_REQ *pSMB = NULL;
1282 COPY_RSP *pSMBr = NULL;
1284 int name_len, name_len2;
1287 cFYI(1, ("In CIFSSMBCopy"));
1289 rc = smb_init(SMB_COM_COPY, 1, tcon, (void **) &pSMB,
1294 pSMB->BufferFormat = 0x04;
1295 pSMB->Tid2 = target_tid;
1297 pSMB->Flags = cpu_to_le16(flags & COPY_TREE);
1299 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1300 name_len = cifsConvertToUCS((__le16 *) pSMB->OldFileName,
1301 fromName, PATH_MAX, nls_codepage,
1303 name_len++; /* trailing null */
1305 pSMB->OldFileName[name_len] = 0x04; /* pad */
1306 /* protocol requires ASCII signature byte on Unicode string */
1307 pSMB->OldFileName[name_len + 1] = 0x00;
1308 name_len2 = cifsConvertToUCS((__le16 *)&pSMB->OldFileName[name_len + 2],
1309 toName, PATH_MAX, nls_codepage, remap);
1310 name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
1311 name_len2 *= 2; /* convert to bytes */
1312 } else { /* BB improve the check for buffer overruns BB */
1313 name_len = strnlen(fromName, PATH_MAX);
1314 name_len++; /* trailing null */
1315 strncpy(pSMB->OldFileName, fromName, name_len);
1316 name_len2 = strnlen(toName, PATH_MAX);
1317 name_len2++; /* trailing null */
1318 pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */
1319 strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2);
1320 name_len2++; /* trailing null */
1321 name_len2++; /* signature byte */
1324 count = 1 /* 1st signature byte */ + name_len + name_len2;
1325 pSMB->hdr.smb_buf_length += count;
1326 pSMB->ByteCount = cpu_to_le16(count);
1328 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1329 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1331 cFYI(1, ("Send error in copy = %d with %d files copied",
1332 rc, le16_to_cpu(pSMBr->CopyCount)));
1335 cifs_buf_release(pSMB);
1344 CIFSUnixCreateSymLink(const int xid, struct cifsTconInfo *tcon,
1345 const char *fromName, const char *toName,
1346 const struct nls_table *nls_codepage)
1348 TRANSACTION2_SPI_REQ *pSMB = NULL;
1349 TRANSACTION2_SPI_RSP *pSMBr = NULL;
1352 int name_len_target;
1354 int bytes_returned = 0;
1355 __u16 params, param_offset, offset, byte_count;
1357 cFYI(1, ("In Symlink Unix style"));
1359 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
1364 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1366 cifs_strtoUCS((wchar_t *) pSMB->FileName, fromName, PATH_MAX
1367 /* find define for this maxpathcomponent */
1369 name_len++; /* trailing null */
1372 } else { /* BB improve the check for buffer overruns BB */
1373 name_len = strnlen(fromName, PATH_MAX);
1374 name_len++; /* trailing null */
1375 strncpy(pSMB->FileName, fromName, name_len);
1377 params = 6 + name_len;
1378 pSMB->MaxSetupCount = 0;
1382 pSMB->Reserved2 = 0;
1383 param_offset = offsetof(struct smb_com_transaction2_spi_req,
1384 InformationLevel) - 4;
1385 offset = param_offset + params;
1387 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
1388 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1390 cifs_strtoUCS((wchar_t *) data_offset, toName, PATH_MAX
1391 /* find define for this maxpathcomponent */
1393 name_len_target++; /* trailing null */
1394 name_len_target *= 2;
1395 } else { /* BB improve the check for buffer overruns BB */
1396 name_len_target = strnlen(toName, PATH_MAX);
1397 name_len_target++; /* trailing null */
1398 strncpy(data_offset, toName, name_len_target);
1401 pSMB->MaxParameterCount = cpu_to_le16(2);
1402 /* BB find exact max on data count below from sess */
1403 pSMB->MaxDataCount = cpu_to_le16(1000);
1404 pSMB->SetupCount = 1;
1405 pSMB->Reserved3 = 0;
1406 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
1407 byte_count = 3 /* pad */ + params + name_len_target;
1408 pSMB->DataCount = cpu_to_le16(name_len_target);
1409 pSMB->ParameterCount = cpu_to_le16(params);
1410 pSMB->TotalDataCount = pSMB->DataCount;
1411 pSMB->TotalParameterCount = pSMB->ParameterCount;
1412 pSMB->ParameterOffset = cpu_to_le16(param_offset);
1413 pSMB->DataOffset = cpu_to_le16(offset);
1414 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_LINK);
1415 pSMB->Reserved4 = 0;
1416 pSMB->hdr.smb_buf_length += byte_count;
1417 pSMB->ByteCount = cpu_to_le16(byte_count);
1418 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1419 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1420 cifs_stats_inc(&tcon->num_symlinks);
1423 ("Send error in SetPathInfo (create symlink) = %d",
1428 cifs_buf_release(pSMB);
1431 goto createSymLinkRetry;
1437 CIFSUnixCreateHardLink(const int xid, struct cifsTconInfo *tcon,
1438 const char *fromName, const char *toName,
1439 const struct nls_table *nls_codepage, int remap)
1441 TRANSACTION2_SPI_REQ *pSMB = NULL;
1442 TRANSACTION2_SPI_RSP *pSMBr = NULL;
1445 int name_len_target;
1447 int bytes_returned = 0;
1448 __u16 params, param_offset, offset, byte_count;
1450 cFYI(1, ("In Create Hard link Unix style"));
1451 createHardLinkRetry:
1452 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
1457 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1458 name_len = cifsConvertToUCS((__le16 *) pSMB->FileName, toName,
1459 PATH_MAX, nls_codepage, remap);
1460 name_len++; /* trailing null */
1463 } else { /* BB improve the check for buffer overruns BB */
1464 name_len = strnlen(toName, PATH_MAX);
1465 name_len++; /* trailing null */
1466 strncpy(pSMB->FileName, toName, name_len);
1468 params = 6 + name_len;
1469 pSMB->MaxSetupCount = 0;
1473 pSMB->Reserved2 = 0;
1474 param_offset = offsetof(struct smb_com_transaction2_spi_req,
1475 InformationLevel) - 4;
1476 offset = param_offset + params;
1478 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
1479 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1481 cifsConvertToUCS((__le16 *) data_offset, fromName, PATH_MAX,
1482 nls_codepage, remap);
1483 name_len_target++; /* trailing null */
1484 name_len_target *= 2;
1485 } else { /* BB improve the check for buffer overruns BB */
1486 name_len_target = strnlen(fromName, PATH_MAX);
1487 name_len_target++; /* trailing null */
1488 strncpy(data_offset, fromName, name_len_target);
1491 pSMB->MaxParameterCount = cpu_to_le16(2);
1492 /* BB find exact max on data count below from sess*/
1493 pSMB->MaxDataCount = cpu_to_le16(1000);
1494 pSMB->SetupCount = 1;
1495 pSMB->Reserved3 = 0;
1496 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
1497 byte_count = 3 /* pad */ + params + name_len_target;
1498 pSMB->ParameterCount = cpu_to_le16(params);
1499 pSMB->TotalParameterCount = pSMB->ParameterCount;
1500 pSMB->DataCount = cpu_to_le16(name_len_target);
1501 pSMB->TotalDataCount = pSMB->DataCount;
1502 pSMB->ParameterOffset = cpu_to_le16(param_offset);
1503 pSMB->DataOffset = cpu_to_le16(offset);
1504 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_HLINK);
1505 pSMB->Reserved4 = 0;
1506 pSMB->hdr.smb_buf_length += byte_count;
1507 pSMB->ByteCount = cpu_to_le16(byte_count);
1508 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1509 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1510 cifs_stats_inc(&tcon->num_hardlinks);
1512 cFYI(1, ("Send error in SetPathInfo (hard link) = %d", rc));
1515 cifs_buf_release(pSMB);
1517 goto createHardLinkRetry;
1523 CIFSCreateHardLink(const int xid, struct cifsTconInfo *tcon,
1524 const char *fromName, const char *toName,
1525 const struct nls_table *nls_codepage, int remap)
1528 NT_RENAME_REQ *pSMB = NULL;
1529 RENAME_RSP *pSMBr = NULL;
1531 int name_len, name_len2;
1534 cFYI(1, ("In CIFSCreateHardLink"));
1535 winCreateHardLinkRetry:
1537 rc = smb_init(SMB_COM_NT_RENAME, 4, tcon, (void **) &pSMB,
1542 pSMB->SearchAttributes =
1543 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
1545 pSMB->Flags = cpu_to_le16(CREATE_HARD_LINK);
1546 pSMB->ClusterCount = 0;
1548 pSMB->BufferFormat = 0x04;
1550 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1552 cifsConvertToUCS((__le16 *) pSMB->OldFileName, fromName,
1553 PATH_MAX, nls_codepage, remap);
1554 name_len++; /* trailing null */
1556 pSMB->OldFileName[name_len] = 0; /* pad */
1557 pSMB->OldFileName[name_len + 1] = 0x04;
1559 cifsConvertToUCS((__le16 *)&pSMB->OldFileName[name_len + 2],
1560 toName, PATH_MAX, nls_codepage, remap);
1561 name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
1562 name_len2 *= 2; /* convert to bytes */
1563 } else { /* BB improve the check for buffer overruns BB */
1564 name_len = strnlen(fromName, PATH_MAX);
1565 name_len++; /* trailing null */
1566 strncpy(pSMB->OldFileName, fromName, name_len);
1567 name_len2 = strnlen(toName, PATH_MAX);
1568 name_len2++; /* trailing null */
1569 pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */
1570 strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2);
1571 name_len2++; /* trailing null */
1572 name_len2++; /* signature byte */
1575 count = 1 /* string type byte */ + name_len + name_len2;
1576 pSMB->hdr.smb_buf_length += count;
1577 pSMB->ByteCount = cpu_to_le16(count);
1579 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1580 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1581 cifs_stats_inc(&tcon->num_hardlinks);
1583 cFYI(1, ("Send error in hard link (NT rename) = %d", rc));
1585 cifs_buf_release(pSMB);
1587 goto winCreateHardLinkRetry;
1593 CIFSSMBUnixQuerySymLink(const int xid, struct cifsTconInfo *tcon,
1594 const unsigned char *searchName,
1595 char *symlinkinfo, const int buflen,
1596 const struct nls_table *nls_codepage)
1598 /* SMB_QUERY_FILE_UNIX_LINK */
1599 TRANSACTION2_QPI_REQ *pSMB = NULL;
1600 TRANSACTION2_QPI_RSP *pSMBr = NULL;
1604 __u16 params, byte_count;
1606 cFYI(1, ("In QPathSymLinkInfo (Unix) for path %s", searchName));
1609 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
1614 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1616 cifs_strtoUCS((wchar_t *) pSMB->FileName, searchName, PATH_MAX
1617 /* find define for this maxpathcomponent */
1619 name_len++; /* trailing null */
1621 } else { /* BB improve the check for buffer overruns BB */
1622 name_len = strnlen(searchName, PATH_MAX);
1623 name_len++; /* trailing null */
1624 strncpy(pSMB->FileName, searchName, name_len);
1627 params = 2 /* level */ + 4 /* rsrvd */ + name_len /* incl null */ ;
1628 pSMB->TotalDataCount = 0;
1629 pSMB->MaxParameterCount = cpu_to_le16(2);
1630 /* BB find exact max data count below from sess structure BB */
1631 pSMB->MaxDataCount = cpu_to_le16(4000);
1632 pSMB->MaxSetupCount = 0;
1636 pSMB->Reserved2 = 0;
1637 pSMB->ParameterOffset = cpu_to_le16(offsetof(
1638 struct smb_com_transaction2_qpi_req ,InformationLevel) - 4);
1639 pSMB->DataCount = 0;
1640 pSMB->DataOffset = 0;
1641 pSMB->SetupCount = 1;
1642 pSMB->Reserved3 = 0;
1643 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
1644 byte_count = params + 1 /* pad */ ;
1645 pSMB->TotalParameterCount = cpu_to_le16(params);
1646 pSMB->ParameterCount = pSMB->TotalParameterCount;
1647 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_LINK);
1648 pSMB->Reserved4 = 0;
1649 pSMB->hdr.smb_buf_length += byte_count;
1650 pSMB->ByteCount = cpu_to_le16(byte_count);
1652 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1653 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1655 cFYI(1, ("Send error in QuerySymLinkInfo = %d", rc));
1657 /* decode response */
1659 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
1660 if (rc || (pSMBr->ByteCount < 2))
1661 /* BB also check enough total bytes returned */
1662 rc = -EIO; /* bad smb */
1664 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
1665 __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
1667 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
1668 name_len = UniStrnlen((wchar_t *) ((char *)
1669 &pSMBr->hdr.Protocol +data_offset),
1670 min_t(const int, buflen,count) / 2);
1671 /* BB FIXME investigate remapping reserved chars here */
1672 cifs_strfromUCS_le(symlinkinfo,
1673 (wchar_t *) ((char *)&pSMBr->hdr.Protocol +
1675 name_len, nls_codepage);
1677 strncpy(symlinkinfo,
1678 (char *) &pSMBr->hdr.Protocol +
1680 min_t(const int, buflen, count));
1682 symlinkinfo[buflen] = 0;
1683 /* just in case so calling code does not go off the end of buffer */
1686 cifs_buf_release(pSMB);
1688 goto querySymLinkRetry;
1693 CIFSSMBQueryReparseLinkInfo(const int xid, struct cifsTconInfo *tcon,
1694 const unsigned char *searchName,
1695 char *symlinkinfo, const int buflen,__u16 fid,
1696 const struct nls_table *nls_codepage)
1701 struct smb_com_transaction_ioctl_req * pSMB;
1702 struct smb_com_transaction_ioctl_rsp * pSMBr;
1704 cFYI(1, ("In Windows reparse style QueryLink for path %s", searchName));
1705 rc = smb_init(SMB_COM_NT_TRANSACT, 23, tcon, (void **) &pSMB,
1710 pSMB->TotalParameterCount = 0 ;
1711 pSMB->TotalDataCount = 0;
1712 pSMB->MaxParameterCount = cpu_to_le32(2);
1713 /* BB find exact data count max from sess structure BB */
1714 pSMB->MaxDataCount = cpu_to_le32(4000);
1715 pSMB->MaxSetupCount = 4;
1717 pSMB->ParameterOffset = 0;
1718 pSMB->DataCount = 0;
1719 pSMB->DataOffset = 0;
1720 pSMB->SetupCount = 4;
1721 pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_IOCTL);
1722 pSMB->ParameterCount = pSMB->TotalParameterCount;
1723 pSMB->FunctionCode = cpu_to_le32(FSCTL_GET_REPARSE_POINT);
1724 pSMB->IsFsctl = 1; /* FSCTL */
1725 pSMB->IsRootFlag = 0;
1726 pSMB->Fid = fid; /* file handle always le */
1727 pSMB->ByteCount = 0;
1729 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1730 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1732 cFYI(1, ("Send error in QueryReparseLinkInfo = %d", rc));
1733 } else { /* decode response */
1734 __u32 data_offset = le32_to_cpu(pSMBr->DataOffset);
1735 __u32 data_count = le32_to_cpu(pSMBr->DataCount);
1736 if ((pSMBr->ByteCount < 2) || (data_offset > 512))
1737 /* BB also check enough total bytes returned */
1738 rc = -EIO; /* bad smb */
1740 if(data_count && (data_count < 2048)) {
1741 char * end_of_smb = pSMBr->ByteCount + (char *)&pSMBr->ByteCount;
1743 struct reparse_data * reparse_buf = (struct reparse_data *)
1744 ((char *)&pSMBr->hdr.Protocol + data_offset);
1745 if((char*)reparse_buf >= end_of_smb) {
1749 if((reparse_buf->LinkNamesBuf +
1750 reparse_buf->TargetNameOffset +
1751 reparse_buf->TargetNameLen) >
1753 cFYI(1,("reparse buf extended beyond SMB"));
1758 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
1759 name_len = UniStrnlen((wchar_t *)
1760 (reparse_buf->LinkNamesBuf +
1761 reparse_buf->TargetNameOffset),
1762 min(buflen/2, reparse_buf->TargetNameLen / 2));
1763 cifs_strfromUCS_le(symlinkinfo,
1764 (wchar_t *) (reparse_buf->LinkNamesBuf +
1765 reparse_buf->TargetNameOffset),
1766 name_len, nls_codepage);
1767 } else { /* ASCII names */
1768 strncpy(symlinkinfo,reparse_buf->LinkNamesBuf +
1769 reparse_buf->TargetNameOffset,
1770 min_t(const int, buflen, reparse_buf->TargetNameLen));
1774 cFYI(1,("Invalid return data count on get reparse info ioctl"));
1776 symlinkinfo[buflen] = 0; /* just in case so the caller
1777 does not go off the end of the buffer */
1778 cFYI(1,("readlink result - %s ",symlinkinfo));
1782 cifs_buf_release(pSMB);
1784 /* Note: On -EAGAIN error only caller can retry on handle based calls
1785 since file handle passed in no longer valid */
1790 #ifdef CONFIG_CIFS_POSIX
1792 /*Convert an Access Control Entry from wire format to local POSIX xattr format*/
1793 static void cifs_convert_ace(posix_acl_xattr_entry * ace, struct cifs_posix_ace * cifs_ace)
1795 /* u8 cifs fields do not need le conversion */
1796 ace->e_perm = (__u16)cifs_ace->cifs_e_perm;
1797 ace->e_tag = (__u16)cifs_ace->cifs_e_tag;
1798 ace->e_id = (__u32)le64_to_cpu(cifs_ace->cifs_uid);
1799 /* cFYI(1,("perm %d tag %d id %d",ace->e_perm,ace->e_tag,ace->e_id)); */
1804 /* Convert ACL from CIFS POSIX wire format to local Linux POSIX ACL xattr */
1805 static int cifs_copy_posix_acl(char * trgt,char * src, const int buflen,
1806 const int acl_type,const int size_of_data_area)
1811 struct cifs_posix_ace * pACE;
1812 struct cifs_posix_acl * cifs_acl = (struct cifs_posix_acl *)src;
1813 posix_acl_xattr_header * local_acl = (posix_acl_xattr_header *)trgt;
1815 if (le16_to_cpu(cifs_acl->version) != CIFS_ACL_VERSION)
1818 if(acl_type & ACL_TYPE_ACCESS) {
1819 count = le16_to_cpu(cifs_acl->access_entry_count);
1820 pACE = &cifs_acl->ace_array[0];
1821 size = sizeof(struct cifs_posix_acl);
1822 size += sizeof(struct cifs_posix_ace) * count;
1823 /* check if we would go beyond end of SMB */
1824 if(size_of_data_area < size) {
1825 cFYI(1,("bad CIFS POSIX ACL size %d vs. %d",size_of_data_area,size));
1828 } else if(acl_type & ACL_TYPE_DEFAULT) {
1829 count = le16_to_cpu(cifs_acl->access_entry_count);
1830 size = sizeof(struct cifs_posix_acl);
1831 size += sizeof(struct cifs_posix_ace) * count;
1832 /* skip past access ACEs to get to default ACEs */
1833 pACE = &cifs_acl->ace_array[count];
1834 count = le16_to_cpu(cifs_acl->default_entry_count);
1835 size += sizeof(struct cifs_posix_ace) * count;
1836 /* check if we would go beyond end of SMB */
1837 if(size_of_data_area < size)
1844 size = posix_acl_xattr_size(count);
1845 if((buflen == 0) || (local_acl == NULL)) {
1846 /* used to query ACL EA size */
1847 } else if(size > buflen) {
1849 } else /* buffer big enough */ {
1850 local_acl->a_version = POSIX_ACL_XATTR_VERSION;
1851 for(i = 0;i < count ;i++) {
1852 cifs_convert_ace(&local_acl->a_entries[i],pACE);
1859 static __u16 convert_ace_to_cifs_ace(struct cifs_posix_ace * cifs_ace,
1860 const posix_acl_xattr_entry * local_ace)
1862 __u16 rc = 0; /* 0 = ACL converted ok */
1864 cifs_ace->cifs_e_perm = (__u8)cpu_to_le16(local_ace->e_perm);
1865 cifs_ace->cifs_e_tag = (__u8)cpu_to_le16(local_ace->e_tag);
1866 /* BB is there a better way to handle the large uid? */
1867 if(local_ace->e_id == -1) {
1868 /* Probably no need to le convert -1 on any arch but can not hurt */
1869 cifs_ace->cifs_uid = cpu_to_le64(-1);
1871 cifs_ace->cifs_uid = (__u64)cpu_to_le32(local_ace->e_id);
1872 /*cFYI(1,("perm %d tag %d id %d",ace->e_perm,ace->e_tag,ace->e_id));*/
1876 /* Convert ACL from local Linux POSIX xattr to CIFS POSIX ACL wire format */
1877 static __u16 ACL_to_cifs_posix(char * parm_data,const char * pACL,const int buflen,
1881 struct cifs_posix_acl * cifs_acl = (struct cifs_posix_acl *)parm_data;
1882 posix_acl_xattr_header * local_acl = (posix_acl_xattr_header *)pACL;
1886 if((buflen == 0) || (pACL == NULL) || (cifs_acl == NULL))
1889 count = posix_acl_xattr_count((size_t)buflen);
1890 cFYI(1,("setting acl with %d entries from buf of length %d and version of %d",
1891 count,buflen,local_acl->a_version));
1892 if(local_acl->a_version != 2) {
1893 cFYI(1,("unknown POSIX ACL version %d",local_acl->a_version));
1896 cifs_acl->version = cpu_to_le16(1);
1897 if(acl_type == ACL_TYPE_ACCESS)
1898 cifs_acl->access_entry_count = count;
1899 else if(acl_type == ACL_TYPE_DEFAULT)
1900 cifs_acl->default_entry_count = count;
1902 cFYI(1,("unknown ACL type %d",acl_type));
1905 for(i=0;i<count;i++) {
1906 rc = convert_ace_to_cifs_ace(&cifs_acl->ace_array[i],
1907 &local_acl->a_entries[i]);
1909 /* ACE not converted */
1914 rc = (__u16)(count * sizeof(struct cifs_posix_ace));
1915 rc += sizeof(struct cifs_posix_acl);
1916 /* BB add check to make sure ACL does not overflow SMB */
1922 CIFSSMBGetPosixACL(const int xid, struct cifsTconInfo *tcon,
1923 const unsigned char *searchName,
1924 char *acl_inf, const int buflen, const int acl_type,
1925 const struct nls_table *nls_codepage, int remap)
1927 /* SMB_QUERY_POSIX_ACL */
1928 TRANSACTION2_QPI_REQ *pSMB = NULL;
1929 TRANSACTION2_QPI_RSP *pSMBr = NULL;
1933 __u16 params, byte_count;
1935 cFYI(1, ("In GetPosixACL (Unix) for path %s", searchName));
1938 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
1943 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1945 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
1946 PATH_MAX, nls_codepage, remap);
1947 name_len++; /* trailing null */
1949 pSMB->FileName[name_len] = 0;
1950 pSMB->FileName[name_len+1] = 0;
1951 } else { /* BB improve the check for buffer overruns BB */
1952 name_len = strnlen(searchName, PATH_MAX);
1953 name_len++; /* trailing null */
1954 strncpy(pSMB->FileName, searchName, name_len);
1957 params = 2 /* level */ + 4 /* rsrvd */ + name_len /* incl null */ ;
1958 pSMB->TotalDataCount = 0;
1959 pSMB->MaxParameterCount = cpu_to_le16(2);
1960 /* BB find exact max data count below from sess structure BB */
1961 pSMB->MaxDataCount = cpu_to_le16(4000);
1962 pSMB->MaxSetupCount = 0;
1966 pSMB->Reserved2 = 0;
1967 pSMB->ParameterOffset = cpu_to_le16(
1968 offsetof(struct smb_com_transaction2_qpi_req ,InformationLevel) - 4);
1969 pSMB->DataCount = 0;
1970 pSMB->DataOffset = 0;
1971 pSMB->SetupCount = 1;
1972 pSMB->Reserved3 = 0;
1973 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
1974 byte_count = params + 1 /* pad */ ;
1975 pSMB->TotalParameterCount = cpu_to_le16(params);
1976 pSMB->ParameterCount = pSMB->TotalParameterCount;
1977 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_POSIX_ACL);
1978 pSMB->Reserved4 = 0;
1979 pSMB->hdr.smb_buf_length += byte_count;
1980 pSMB->ByteCount = cpu_to_le16(byte_count);
1982 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1983 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1985 cFYI(1, ("Send error in Query POSIX ACL = %d", rc));
1987 /* decode response */
1989 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
1990 if (rc || (pSMBr->ByteCount < 2))
1991 /* BB also check enough total bytes returned */
1992 rc = -EIO; /* bad smb */
1994 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
1995 __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
1996 rc = cifs_copy_posix_acl(acl_inf,
1997 (char *)&pSMBr->hdr.Protocol+data_offset,
1998 buflen,acl_type,count);
2001 cifs_buf_release(pSMB);
2008 CIFSSMBSetPosixACL(const int xid, struct cifsTconInfo *tcon,
2009 const unsigned char *fileName,
2010 const char *local_acl, const int buflen,
2012 const struct nls_table *nls_codepage, int remap)
2014 struct smb_com_transaction2_spi_req *pSMB = NULL;
2015 struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
2019 int bytes_returned = 0;
2020 __u16 params, byte_count, data_count, param_offset, offset;
2022 cFYI(1, ("In SetPosixACL (Unix) for path %s", fileName));
2024 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2028 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2030 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
2031 PATH_MAX, nls_codepage, remap);
2032 name_len++; /* trailing null */
2034 } else { /* BB improve the check for buffer overruns BB */
2035 name_len = strnlen(fileName, PATH_MAX);
2036 name_len++; /* trailing null */
2037 strncpy(pSMB->FileName, fileName, name_len);
2039 params = 6 + name_len;
2040 pSMB->MaxParameterCount = cpu_to_le16(2);
2041 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB size from sess */
2042 pSMB->MaxSetupCount = 0;
2046 pSMB->Reserved2 = 0;
2047 param_offset = offsetof(struct smb_com_transaction2_spi_req,
2048 InformationLevel) - 4;
2049 offset = param_offset + params;
2050 parm_data = ((char *) &pSMB->hdr.Protocol) + offset;
2051 pSMB->ParameterOffset = cpu_to_le16(param_offset);
2053 /* convert to on the wire format for POSIX ACL */
2054 data_count = ACL_to_cifs_posix(parm_data,local_acl,buflen,acl_type);
2056 if(data_count == 0) {
2058 goto setACLerrorExit;
2060 pSMB->DataOffset = cpu_to_le16(offset);
2061 pSMB->SetupCount = 1;
2062 pSMB->Reserved3 = 0;
2063 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
2064 pSMB->InformationLevel = cpu_to_le16(SMB_SET_POSIX_ACL);
2065 byte_count = 3 /* pad */ + params + data_count;
2066 pSMB->DataCount = cpu_to_le16(data_count);
2067 pSMB->TotalDataCount = pSMB->DataCount;
2068 pSMB->ParameterCount = cpu_to_le16(params);
2069 pSMB->TotalParameterCount = pSMB->ParameterCount;
2070 pSMB->Reserved4 = 0;
2071 pSMB->hdr.smb_buf_length += byte_count;
2072 pSMB->ByteCount = cpu_to_le16(byte_count);
2073 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2074 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2076 cFYI(1, ("Set POSIX ACL returned %d", rc));
2080 cifs_buf_release(pSMB);
2086 /* BB fix tabs in this function FIXME BB */
2088 CIFSGetExtAttr(const int xid, struct cifsTconInfo *tcon,
2089 const int netfid, __u64 * pExtAttrBits, __u64 *pMask)
2092 struct smb_t2_qfi_req *pSMB = NULL;
2093 struct smb_t2_qfi_rsp *pSMBr = NULL;
2095 __u16 params, byte_count;
2097 cFYI(1,("In GetExtAttr"));
2102 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2107 params = 2 /* level */ +2 /* fid */;
2108 pSMB->t2.TotalDataCount = 0;
2109 pSMB->t2.MaxParameterCount = cpu_to_le16(4);
2110 /* BB find exact max data count below from sess structure BB */
2111 pSMB->t2.MaxDataCount = cpu_to_le16(4000);
2112 pSMB->t2.MaxSetupCount = 0;
2113 pSMB->t2.Reserved = 0;
2115 pSMB->t2.Timeout = 0;
2116 pSMB->t2.Reserved2 = 0;
2117 pSMB->t2.ParameterOffset = cpu_to_le16(offsetof(struct smb_t2_qfi_req,
2119 pSMB->t2.DataCount = 0;
2120 pSMB->t2.DataOffset = 0;
2121 pSMB->t2.SetupCount = 1;
2122 pSMB->t2.Reserved3 = 0;
2123 pSMB->t2.SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION);
2124 byte_count = params + 1 /* pad */ ;
2125 pSMB->t2.TotalParameterCount = cpu_to_le16(params);
2126 pSMB->t2.ParameterCount = pSMB->t2.TotalParameterCount;
2127 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_ATTR_FLAGS);
2130 pSMB->hdr.smb_buf_length += byte_count;
2131 pSMB->t2.ByteCount = cpu_to_le16(byte_count);
2133 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2134 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2136 cFYI(1, ("error %d in GetExtAttr", rc));
2138 /* decode response */
2139 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
2140 if (rc || (pSMBr->ByteCount < 2))
2141 /* BB also check enough total bytes returned */
2142 /* If rc should we check for EOPNOSUPP and
2143 disable the srvino flag? or in caller? */
2144 rc = -EIO; /* bad smb */
2146 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
2147 __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
2148 struct file_chattr_info * pfinfo;
2149 /* BB Do we need a cast or hash here ? */
2151 cFYI(1, ("Illegal size ret in GetExtAttr"));
2155 pfinfo = (struct file_chattr_info *)
2156 (data_offset + (char *) &pSMBr->hdr.Protocol);
2157 *pExtAttrBits = le64_to_cpu(pfinfo->mode);
2158 *pMask = le64_to_cpu(pfinfo->mask);
2162 cifs_buf_release(pSMB);
2164 goto GetExtAttrRetry;
2169 #endif /* CONFIG_POSIX */
2171 /* Legacy Query Path Information call for lookup to old servers such
2173 int SMBQueryInformation(const int xid, struct cifsTconInfo *tcon,
2174 const unsigned char *searchName,
2175 FILE_ALL_INFO * pFinfo,
2176 const struct nls_table *nls_codepage, int remap)
2178 QUERY_INFORMATION_REQ * pSMB;
2179 QUERY_INFORMATION_RSP * pSMBr;
2184 cFYI(1, ("In SMBQPath path %s", searchName));
2186 rc = smb_init(SMB_COM_QUERY_INFORMATION, 0, tcon, (void **) &pSMB,
2191 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2193 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
2194 PATH_MAX, nls_codepage, remap);
2195 name_len++; /* trailing null */
2198 name_len = strnlen(searchName, PATH_MAX);
2199 name_len++; /* trailing null */
2200 strncpy(pSMB->FileName, searchName, name_len);
2202 pSMB->BufferFormat = 0x04;
2203 name_len++; /* account for buffer type byte */
2204 pSMB->hdr.smb_buf_length += (__u16) name_len;
2205 pSMB->ByteCount = cpu_to_le16(name_len);
2207 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2208 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2210 cFYI(1, ("Send error in QueryInfo = %d", rc));
2211 } else if (pFinfo) { /* decode response */
2212 memset(pFinfo, 0, sizeof(FILE_ALL_INFO));
2213 pFinfo->AllocationSize = (__le64) pSMBr->size;
2214 pFinfo->EndOfFile = (__le64) pSMBr->size;
2215 pFinfo->Attributes = (__le32) pSMBr->attr;
2217 rc = -EIO; /* bad buffer passed in */
2219 cifs_buf_release(pSMB);
2231 CIFSSMBQPathInfo(const int xid, struct cifsTconInfo *tcon,
2232 const unsigned char *searchName,
2233 FILE_ALL_INFO * pFindData,
2234 const struct nls_table *nls_codepage, int remap)
2236 /* level 263 SMB_QUERY_FILE_ALL_INFO */
2237 TRANSACTION2_QPI_REQ *pSMB = NULL;
2238 TRANSACTION2_QPI_RSP *pSMBr = NULL;
2242 __u16 params, byte_count;
2244 /* cFYI(1, ("In QPathInfo path %s", searchName)); */
2246 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2251 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2253 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
2254 PATH_MAX, nls_codepage, remap);
2255 name_len++; /* trailing null */
2257 } else { /* BB improve the check for buffer overruns BB */
2258 name_len = strnlen(searchName, PATH_MAX);
2259 name_len++; /* trailing null */
2260 strncpy(pSMB->FileName, searchName, name_len);
2263 params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */ ;
2264 pSMB->TotalDataCount = 0;
2265 pSMB->MaxParameterCount = cpu_to_le16(2);
2266 pSMB->MaxDataCount = cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
2267 pSMB->MaxSetupCount = 0;
2271 pSMB->Reserved2 = 0;
2272 pSMB->ParameterOffset = cpu_to_le16(offsetof(
2273 struct smb_com_transaction2_qpi_req ,InformationLevel) - 4);
2274 pSMB->DataCount = 0;
2275 pSMB->DataOffset = 0;
2276 pSMB->SetupCount = 1;
2277 pSMB->Reserved3 = 0;
2278 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
2279 byte_count = params + 1 /* pad */ ;
2280 pSMB->TotalParameterCount = cpu_to_le16(params);
2281 pSMB->ParameterCount = pSMB->TotalParameterCount;
2282 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_ALL_INFO);
2283 pSMB->Reserved4 = 0;
2284 pSMB->hdr.smb_buf_length += byte_count;
2285 pSMB->ByteCount = cpu_to_le16(byte_count);
2287 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2288 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2290 cFYI(1, ("Send error in QPathInfo = %d", rc));
2291 } else { /* decode response */
2292 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
2294 if (rc || (pSMBr->ByteCount < 40))
2295 rc = -EIO; /* bad smb */
2296 else if (pFindData){
2297 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
2298 memcpy((char *) pFindData,
2299 (char *) &pSMBr->hdr.Protocol +
2300 data_offset, sizeof (FILE_ALL_INFO));
2304 cifs_buf_release(pSMB);
2306 goto QPathInfoRetry;
2312 CIFSSMBUnixQPathInfo(const int xid, struct cifsTconInfo *tcon,
2313 const unsigned char *searchName,
2314 FILE_UNIX_BASIC_INFO * pFindData,
2315 const struct nls_table *nls_codepage, int remap)
2317 /* SMB_QUERY_FILE_UNIX_BASIC */
2318 TRANSACTION2_QPI_REQ *pSMB = NULL;
2319 TRANSACTION2_QPI_RSP *pSMBr = NULL;
2321 int bytes_returned = 0;
2323 __u16 params, byte_count;
2325 cFYI(1, ("In QPathInfo (Unix) the path %s", searchName));
2327 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2332 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2334 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
2335 PATH_MAX, nls_codepage, remap);
2336 name_len++; /* trailing null */
2338 } else { /* BB improve the check for buffer overruns BB */
2339 name_len = strnlen(searchName, PATH_MAX);
2340 name_len++; /* trailing null */
2341 strncpy(pSMB->FileName, searchName, name_len);
2344 params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */ ;
2345 pSMB->TotalDataCount = 0;
2346 pSMB->MaxParameterCount = cpu_to_le16(2);
2347 /* BB find exact max SMB PDU from sess structure BB */
2348 pSMB->MaxDataCount = cpu_to_le16(4000);
2349 pSMB->MaxSetupCount = 0;
2353 pSMB->Reserved2 = 0;
2354 pSMB->ParameterOffset = cpu_to_le16(offsetof(
2355 struct smb_com_transaction2_qpi_req ,InformationLevel) - 4);
2356 pSMB->DataCount = 0;
2357 pSMB->DataOffset = 0;
2358 pSMB->SetupCount = 1;
2359 pSMB->Reserved3 = 0;
2360 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
2361 byte_count = params + 1 /* pad */ ;
2362 pSMB->TotalParameterCount = cpu_to_le16(params);
2363 pSMB->ParameterCount = pSMB->TotalParameterCount;
2364 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC);
2365 pSMB->Reserved4 = 0;
2366 pSMB->hdr.smb_buf_length += byte_count;
2367 pSMB->ByteCount = cpu_to_le16(byte_count);
2369 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2370 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2372 cFYI(1, ("Send error in QPathInfo = %d", rc));
2373 } else { /* decode response */
2374 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
2376 if (rc || (pSMBr->ByteCount < sizeof(FILE_UNIX_BASIC_INFO))) {
2377 rc = -EIO; /* bad smb */
2379 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
2380 memcpy((char *) pFindData,
2381 (char *) &pSMBr->hdr.Protocol +
2383 sizeof (FILE_UNIX_BASIC_INFO));
2386 cifs_buf_release(pSMB);
2388 goto UnixQPathInfoRetry;
2393 #if 0 /* function unused at present */
2394 int CIFSFindSingle(const int xid, struct cifsTconInfo *tcon,
2395 const char *searchName, FILE_ALL_INFO * findData,
2396 const struct nls_table *nls_codepage)
2398 /* level 257 SMB_ */
2399 TRANSACTION2_FFIRST_REQ *pSMB = NULL;
2400 TRANSACTION2_FFIRST_RSP *pSMBr = NULL;
2404 __u16 params, byte_count;
2406 cFYI(1, ("In FindUnique"));
2408 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2413 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2415 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName, PATH_MAX
2416 /* find define for this maxpathcomponent */
2418 name_len++; /* trailing null */
2420 } else { /* BB improve the check for buffer overruns BB */
2421 name_len = strnlen(searchName, PATH_MAX);
2422 name_len++; /* trailing null */
2423 strncpy(pSMB->FileName, searchName, name_len);
2426 params = 12 + name_len /* includes null */ ;
2427 pSMB->TotalDataCount = 0; /* no EAs */
2428 pSMB->MaxParameterCount = cpu_to_le16(2);
2429 pSMB->MaxDataCount = cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
2430 pSMB->MaxSetupCount = 0;
2434 pSMB->Reserved2 = 0;
2435 pSMB->ParameterOffset = cpu_to_le16(
2436 offsetof(struct smb_com_transaction2_ffirst_req,InformationLevel) - 4);
2437 pSMB->DataCount = 0;
2438 pSMB->DataOffset = 0;
2439 pSMB->SetupCount = 1; /* one byte, no need to le convert */
2440 pSMB->Reserved3 = 0;
2441 pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_FIRST);
2442 byte_count = params + 1 /* pad */ ;
2443 pSMB->TotalParameterCount = cpu_to_le16(params);
2444 pSMB->ParameterCount = pSMB->TotalParameterCount;
2445 pSMB->SearchAttributes =
2446 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
2448 pSMB->SearchCount = cpu_to_le16(16); /* BB increase */
2449 pSMB->SearchFlags = cpu_to_le16(1);
2450 pSMB->InformationLevel = cpu_to_le16(SMB_FIND_FILE_DIRECTORY_INFO);
2451 pSMB->SearchStorageType = 0; /* BB what should we set this to? BB */
2452 pSMB->hdr.smb_buf_length += byte_count;
2453 pSMB->ByteCount = cpu_to_le16(byte_count);
2455 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2456 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2459 cFYI(1, ("Send error in FindFileDirInfo = %d", rc));
2460 } else { /* decode response */
2461 cifs_stats_inc(&tcon->num_ffirst);
2465 cifs_buf_release(pSMB);
2467 goto findUniqueRetry;
2471 #endif /* end unused (temporarily) function */
2473 /* xid, tcon, searchName and codepage are input parms, rest are returned */
2475 CIFSFindFirst(const int xid, struct cifsTconInfo *tcon,
2476 const char *searchName,
2477 const struct nls_table *nls_codepage,
2479 struct cifs_search_info * psrch_inf, int remap, const char dirsep)
2481 /* level 257 SMB_ */
2482 TRANSACTION2_FFIRST_REQ *pSMB = NULL;
2483 TRANSACTION2_FFIRST_RSP *pSMBr = NULL;
2484 T2_FFIRST_RSP_PARMS * parms;
2486 int bytes_returned = 0;
2488 __u16 params, byte_count;
2490 cFYI(1, ("In FindFirst for %s",searchName));
2493 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2498 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2500 cifsConvertToUCS((__le16 *) pSMB->FileName,searchName,
2501 PATH_MAX, nls_codepage, remap);
2502 /* We can not add the asterik earlier in case
2503 it got remapped to 0xF03A as if it were part of the
2504 directory name instead of a wildcard */
2506 pSMB->FileName[name_len] = dirsep;
2507 pSMB->FileName[name_len+1] = 0;
2508 pSMB->FileName[name_len+2] = '*';
2509 pSMB->FileName[name_len+3] = 0;
2510 name_len += 4; /* now the trailing null */
2511 pSMB->FileName[name_len] = 0; /* null terminate just in case */
2512 pSMB->FileName[name_len+1] = 0;
2514 } else { /* BB add check for overrun of SMB buf BB */
2515 name_len = strnlen(searchName, PATH_MAX);
2516 /* BB fix here and in unicode clause above ie
2517 if(name_len > buffersize-header)
2518 free buffer exit; BB */
2519 strncpy(pSMB->FileName, searchName, name_len);
2520 pSMB->FileName[name_len] = dirsep;
2521 pSMB->FileName[name_len+1] = '*';
2522 pSMB->FileName[name_len+2] = 0;
2526 params = 12 + name_len /* includes null */ ;
2527 pSMB->TotalDataCount = 0; /* no EAs */
2528 pSMB->MaxParameterCount = cpu_to_le16(10);
2529 pSMB->MaxDataCount = cpu_to_le16((tcon->ses->server->maxBuf -
2530 MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
2531 pSMB->MaxSetupCount = 0;
2535 pSMB->Reserved2 = 0;
2536 byte_count = params + 1 /* pad */ ;
2537 pSMB->TotalParameterCount = cpu_to_le16(params);
2538 pSMB->ParameterCount = pSMB->TotalParameterCount;
2539 pSMB->ParameterOffset = cpu_to_le16(
2540 offsetof(struct smb_com_transaction2_ffirst_req, SearchAttributes) - 4);
2541 pSMB->DataCount = 0;
2542 pSMB->DataOffset = 0;
2543 pSMB->SetupCount = 1; /* one byte, no need to make endian neutral */
2544 pSMB->Reserved3 = 0;
2545 pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_FIRST);
2546 pSMB->SearchAttributes =
2547 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
2549 pSMB->SearchCount= cpu_to_le16(CIFSMaxBufSize/sizeof(FILE_UNIX_INFO));
2550 pSMB->SearchFlags = cpu_to_le16(CIFS_SEARCH_CLOSE_AT_END |
2551 CIFS_SEARCH_RETURN_RESUME);
2552 pSMB->InformationLevel = cpu_to_le16(psrch_inf->info_level);
2554 /* BB what should we set StorageType to? Does it matter? BB */
2555 pSMB->SearchStorageType = 0;
2556 pSMB->hdr.smb_buf_length += byte_count;
2557 pSMB->ByteCount = cpu_to_le16(byte_count);
2559 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2560 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2561 cifs_stats_inc(&tcon->num_ffirst);
2563 if (rc) {/* BB add logic to retry regular search if Unix search rejected unexpectedly by server */
2564 /* BB Add code to handle unsupported level rc */
2565 cFYI(1, ("Error in FindFirst = %d", rc));
2568 cifs_buf_release(pSMB);
2570 /* BB eventually could optimize out free and realloc of buf */
2573 goto findFirstRetry;
2574 } else { /* decode response */
2575 /* BB remember to free buffer if error BB */
2576 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
2578 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
2579 psrch_inf->unicode = TRUE;
2581 psrch_inf->unicode = FALSE;
2583 psrch_inf->ntwrk_buf_start = (char *)pSMBr;
2584 psrch_inf->srch_entries_start =
2585 (char *) &pSMBr->hdr.Protocol +
2586 le16_to_cpu(pSMBr->t2.DataOffset);
2587 parms = (T2_FFIRST_RSP_PARMS *)((char *) &pSMBr->hdr.Protocol +
2588 le16_to_cpu(pSMBr->t2.ParameterOffset));
2590 if(parms->EndofSearch)
2591 psrch_inf->endOfSearch = TRUE;
2593 psrch_inf->endOfSearch = FALSE;
2595 psrch_inf->entries_in_buffer = le16_to_cpu(parms->SearchCount);
2596 psrch_inf->index_of_last_entry =
2597 psrch_inf->entries_in_buffer;
2598 *pnetfid = parms->SearchHandle;
2600 cifs_buf_release(pSMB);
2607 int CIFSFindNext(const int xid, struct cifsTconInfo *tcon,
2608 __u16 searchHandle, struct cifs_search_info * psrch_inf)
2610 TRANSACTION2_FNEXT_REQ *pSMB = NULL;
2611 TRANSACTION2_FNEXT_RSP *pSMBr = NULL;
2612 T2_FNEXT_RSP_PARMS * parms;
2613 char *response_data;
2615 int bytes_returned, name_len;
2616 __u16 params, byte_count;
2618 cFYI(1, ("In FindNext"));
2620 if(psrch_inf->endOfSearch == TRUE)
2623 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2628 params = 14; /* includes 2 bytes of null string, converted to LE below */
2630 pSMB->TotalDataCount = 0; /* no EAs */
2631 pSMB->MaxParameterCount = cpu_to_le16(8);
2632 pSMB->MaxDataCount =
2633 cpu_to_le16((tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
2634 pSMB->MaxSetupCount = 0;
2638 pSMB->Reserved2 = 0;
2639 pSMB->ParameterOffset = cpu_to_le16(
2640 offsetof(struct smb_com_transaction2_fnext_req,SearchHandle) - 4);
2641 pSMB->DataCount = 0;
2642 pSMB->DataOffset = 0;
2643 pSMB->SetupCount = 1;
2644 pSMB->Reserved3 = 0;
2645 pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_NEXT);
2646 pSMB->SearchHandle = searchHandle; /* always kept as le */
2648 cpu_to_le16(CIFSMaxBufSize / sizeof (FILE_UNIX_INFO));
2649 /* test for Unix extensions */
2650 /* if (tcon->ses->capabilities & CAP_UNIX) {
2651 pSMB->InformationLevel = cpu_to_le16(SMB_FIND_FILE_UNIX);
2652 psrch_inf->info_level = SMB_FIND_FILE_UNIX;
2654 pSMB->InformationLevel =
2655 cpu_to_le16(SMB_FIND_FILE_DIRECTORY_INFO);
2656 psrch_inf->info_level = SMB_FIND_FILE_DIRECTORY_INFO;
2658 pSMB->InformationLevel = cpu_to_le16(psrch_inf->info_level);
2659 pSMB->ResumeKey = psrch_inf->resume_key;
2661 cpu_to_le16(CIFS_SEARCH_CLOSE_AT_END | CIFS_SEARCH_RETURN_RESUME);
2663 name_len = psrch_inf->resume_name_len;
2665 if(name_len < PATH_MAX) {
2666 memcpy(pSMB->ResumeFileName, psrch_inf->presume_name, name_len);
2667 byte_count += name_len;
2668 /* 14 byte parm len above enough for 2 byte null terminator */
2669 pSMB->ResumeFileName[name_len] = 0;
2670 pSMB->ResumeFileName[name_len+1] = 0;
2673 goto FNext2_err_exit;
2675 byte_count = params + 1 /* pad */ ;
2676 pSMB->TotalParameterCount = cpu_to_le16(params);
2677 pSMB->ParameterCount = pSMB->TotalParameterCount;
2678 pSMB->hdr.smb_buf_length += byte_count;
2679 pSMB->ByteCount = cpu_to_le16(byte_count);
2681 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2682 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2683 cifs_stats_inc(&tcon->num_fnext);
2686 psrch_inf->endOfSearch = TRUE;
2687 rc = 0; /* search probably was closed at end of search above */
2689 cFYI(1, ("FindNext returned = %d", rc));
2690 } else { /* decode response */
2691 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
2694 /* BB fixme add lock for file (srch_info) struct here */
2695 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
2696 psrch_inf->unicode = TRUE;
2698 psrch_inf->unicode = FALSE;
2699 response_data = (char *) &pSMBr->hdr.Protocol +
2700 le16_to_cpu(pSMBr->t2.ParameterOffset);
2701 parms = (T2_FNEXT_RSP_PARMS *)response_data;
2702 response_data = (char *)&pSMBr->hdr.Protocol +
2703 le16_to_cpu(pSMBr->t2.DataOffset);
2704 cifs_buf_release(psrch_inf->ntwrk_buf_start);
2705 psrch_inf->srch_entries_start = response_data;
2706 psrch_inf->ntwrk_buf_start = (char *)pSMB;
2707 if(parms->EndofSearch)
2708 psrch_inf->endOfSearch = TRUE;
2710 psrch_inf->endOfSearch = FALSE;
2712 psrch_inf->entries_in_buffer = le16_to_cpu(parms->SearchCount);
2713 psrch_inf->index_of_last_entry +=
2714 psrch_inf->entries_in_buffer;
2715 /* cFYI(1,("fnxt2 entries in buf %d index_of_last %d",psrch_inf->entries_in_buffer,psrch_inf->index_of_last_entry)); */
2717 /* BB fixme add unlock here */
2722 /* BB On error, should we leave previous search buf (and count and
2723 last entry fields) intact or free the previous one? */
2725 /* Note: On -EAGAIN error only caller can retry on handle based calls
2726 since file handle passed in no longer valid */
2729 cifs_buf_release(pSMB);
2735 CIFSFindClose(const int xid, struct cifsTconInfo *tcon, const __u16 searchHandle)
2738 FINDCLOSE_REQ *pSMB = NULL;
2739 CLOSE_RSP *pSMBr = NULL; /* BB removeme BB */
2742 cFYI(1, ("In CIFSSMBFindClose"));
2743 rc = small_smb_init(SMB_COM_FIND_CLOSE2, 1, tcon, (void **)&pSMB);
2745 /* no sense returning error if session restarted
2746 as file handle has been closed */
2752 pSMBr = (CLOSE_RSP *)pSMB; /* BB removeme BB */
2753 pSMB->FileID = searchHandle;
2754 pSMB->ByteCount = 0;
2755 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2756 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2758 cERROR(1, ("Send error in FindClose = %d", rc));
2760 cifs_stats_inc(&tcon->num_fclose);
2761 cifs_small_buf_release(pSMB);
2763 /* Since session is dead, search handle closed on server already */
2770 #ifdef CONFIG_CIFS_EXPERIMENTAL
2772 CIFSGetSrvInodeNumber(const int xid, struct cifsTconInfo *tcon,
2773 const unsigned char *searchName,
2774 __u64 * inode_number,
2775 const struct nls_table *nls_codepage, int remap)
2778 TRANSACTION2_QPI_REQ *pSMB = NULL;
2779 TRANSACTION2_QPI_RSP *pSMBr = NULL;
2780 int name_len, bytes_returned;
2781 __u16 params, byte_count;
2783 cFYI(1,("In GetSrvInodeNum for %s",searchName));
2787 GetInodeNumberRetry:
2788 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2794 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2796 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
2797 PATH_MAX,nls_codepage, remap);
2798 name_len++; /* trailing null */
2800 } else { /* BB improve the check for buffer overruns BB */
2801 name_len = strnlen(searchName, PATH_MAX);
2802 name_len++; /* trailing null */
2803 strncpy(pSMB->FileName, searchName, name_len);
2806 params = 2 /* level */ + 4 /* rsrvd */ + name_len /* incl null */ ;
2807 pSMB->TotalDataCount = 0;
2808 pSMB->MaxParameterCount = cpu_to_le16(2);
2809 /* BB find exact max data count below from sess structure BB */
2810 pSMB->MaxDataCount = cpu_to_le16(4000);
2811 pSMB->MaxSetupCount = 0;
2815 pSMB->Reserved2 = 0;
2816 pSMB->ParameterOffset = cpu_to_le16(offsetof(
2817 struct smb_com_transaction2_qpi_req ,InformationLevel) - 4);
2818 pSMB->DataCount = 0;
2819 pSMB->DataOffset = 0;
2820 pSMB->SetupCount = 1;
2821 pSMB->Reserved3 = 0;
2822 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
2823 byte_count = params + 1 /* pad */ ;
2824 pSMB->TotalParameterCount = cpu_to_le16(params);
2825 pSMB->ParameterCount = pSMB->TotalParameterCount;
2826 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_INTERNAL_INFO);
2827 pSMB->Reserved4 = 0;
2828 pSMB->hdr.smb_buf_length += byte_count;
2829 pSMB->ByteCount = cpu_to_le16(byte_count);
2831 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2832 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2834 cFYI(1, ("error %d in QueryInternalInfo", rc));
2836 /* decode response */
2837 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
2838 if (rc || (pSMBr->ByteCount < 2))
2839 /* BB also check enough total bytes returned */
2840 /* If rc should we check for EOPNOSUPP and
2841 disable the srvino flag? or in caller? */
2842 rc = -EIO; /* bad smb */
2844 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
2845 __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
2846 struct file_internal_info * pfinfo;
2847 /* BB Do we need a cast or hash here ? */
2849 cFYI(1, ("Illegal size ret in QryIntrnlInf"));
2851 goto GetInodeNumOut;
2853 pfinfo = (struct file_internal_info *)
2854 (data_offset + (char *) &pSMBr->hdr.Protocol);
2855 *inode_number = pfinfo->UniqueId;
2859 cifs_buf_release(pSMB);
2861 goto GetInodeNumberRetry;
2864 #endif /* CIFS_EXPERIMENTAL */
2867 CIFSGetDFSRefer(const int xid, struct cifsSesInfo *ses,
2868 const unsigned char *searchName,
2869 unsigned char **targetUNCs,
2870 unsigned int *number_of_UNC_in_array,
2871 const struct nls_table *nls_codepage, int remap)
2873 /* TRANS2_GET_DFS_REFERRAL */
2874 TRANSACTION2_GET_DFS_REFER_REQ *pSMB = NULL;
2875 TRANSACTION2_GET_DFS_REFER_RSP *pSMBr = NULL;
2876 struct dfs_referral_level_3 * referrals = NULL;
2882 __u16 params, byte_count;
2883 *number_of_UNC_in_array = 0;
2886 cFYI(1, ("In GetDFSRefer the path %s", searchName));
2890 rc = smb_init(SMB_COM_TRANSACTION2, 15, NULL, (void **) &pSMB,
2895 /* server pointer checked in called function,
2896 but should never be null here anyway */
2897 pSMB->hdr.Mid = GetNextMid(ses->server);
2898 pSMB->hdr.Tid = ses->ipc_tid;
2899 pSMB->hdr.Uid = ses->Suid;
2900 if (ses->capabilities & CAP_STATUS32) {
2901 pSMB->hdr.Flags2 |= SMBFLG2_ERR_STATUS;
2903 if (ses->capabilities & CAP_DFS) {
2904 pSMB->hdr.Flags2 |= SMBFLG2_DFS;
2907 if (ses->capabilities & CAP_UNICODE) {
2908 pSMB->hdr.Flags2 |= SMBFLG2_UNICODE;
2910 cifsConvertToUCS((__le16 *) pSMB->RequestFileName,
2911 searchName, PATH_MAX, nls_codepage, remap);
2912 name_len++; /* trailing null */
2914 } else { /* BB improve the check for buffer overruns BB */
2915 name_len = strnlen(searchName, PATH_MAX);
2916 name_len++; /* trailing null */
2917 strncpy(pSMB->RequestFileName, searchName, name_len);
2920 params = 2 /* level */ + name_len /*includes null */ ;
2921 pSMB->TotalDataCount = 0;
2922 pSMB->DataCount = 0;
2923 pSMB->DataOffset = 0;
2924 pSMB->MaxParameterCount = 0;
2925 pSMB->MaxDataCount = cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
2926 pSMB->MaxSetupCount = 0;
2930 pSMB->Reserved2 = 0;
2931 pSMB->ParameterOffset = cpu_to_le16(offsetof(
2932 struct smb_com_transaction2_get_dfs_refer_req, MaxReferralLevel) - 4);
2933 pSMB->SetupCount = 1;
2934 pSMB->Reserved3 = 0;
2935 pSMB->SubCommand = cpu_to_le16(TRANS2_GET_DFS_REFERRAL);
2936 byte_count = params + 3 /* pad */ ;
2937 pSMB->ParameterCount = cpu_to_le16(params);
2938 pSMB->TotalParameterCount = pSMB->ParameterCount;
2939 pSMB->MaxReferralLevel = cpu_to_le16(3);
2940 pSMB->hdr.smb_buf_length += byte_count;
2941 pSMB->ByteCount = cpu_to_le16(byte_count);
2943 rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB,
2944 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2946 cFYI(1, ("Send error in GetDFSRefer = %d", rc));
2947 } else { /* decode response */
2948 /* BB Add logic to parse referrals here */
2949 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
2951 if (rc || (pSMBr->ByteCount < 17)) /* BB also check enough total bytes returned */
2952 rc = -EIO; /* bad smb */
2954 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
2955 __u16 data_count = le16_to_cpu(pSMBr->t2.DataCount);
2958 ("Decoding GetDFSRefer response. BCC: %d Offset %d",
2959 pSMBr->ByteCount, data_offset));
2961 (struct dfs_referral_level_3 *)
2962 (8 /* sizeof start of data block */ +
2964 (char *) &pSMBr->hdr.Protocol);
2965 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",
2966 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)));
2967 /* BB This field is actually two bytes in from start of
2968 data block so we could do safety check that DataBlock
2969 begins at address of pSMBr->NumberOfReferrals */
2970 *number_of_UNC_in_array = le16_to_cpu(pSMBr->NumberOfReferrals);
2972 /* BB Fix below so can return more than one referral */
2973 if(*number_of_UNC_in_array > 1)
2974 *number_of_UNC_in_array = 1;
2976 /* get the length of the strings describing refs */
2978 for(i=0;i<*number_of_UNC_in_array;i++) {
2979 /* make sure that DfsPathOffset not past end */
2980 __u16 offset = le16_to_cpu(referrals->DfsPathOffset);
2981 if (offset > data_count) {
2982 /* if invalid referral, stop here and do
2983 not try to copy any more */
2984 *number_of_UNC_in_array = i;
2987 temp = ((char *)referrals) + offset;
2989 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
2990 name_len += UniStrnlen((wchar_t *)temp,data_count);
2992 name_len += strnlen(temp,data_count);
2995 /* BB add check that referral pointer does not fall off end PDU */
2998 /* BB add check for name_len bigger than bcc */
3000 kmalloc(name_len+1+ (*number_of_UNC_in_array),GFP_KERNEL);
3001 if(*targetUNCs == NULL) {
3005 /* copy the ref strings */
3007 (struct dfs_referral_level_3 *)
3008 (8 /* sizeof data hdr */ +
3010 (char *) &pSMBr->hdr.Protocol);
3012 for(i=0;i<*number_of_UNC_in_array;i++) {
3013 temp = ((char *)referrals) + le16_to_cpu(referrals->DfsPathOffset);
3014 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
3015 cifs_strfromUCS_le(*targetUNCs,
3016 (wchar_t *) temp, name_len, nls_codepage);
3018 strncpy(*targetUNCs,temp,name_len);
3020 /* BB update target_uncs pointers */
3030 cifs_buf_release(pSMB);
3039 CIFSSMBQFSInfo(const int xid, struct cifsTconInfo *tcon, struct kstatfs *FSData)
3041 /* level 0x103 SMB_QUERY_FILE_SYSTEM_INFO */
3042 TRANSACTION2_QFSI_REQ *pSMB = NULL;
3043 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
3044 FILE_SYSTEM_INFO *response_data;
3046 int bytes_returned = 0;
3047 __u16 params, byte_count;
3049 cFYI(1, ("In QFSInfo"));
3051 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3056 params = 2; /* level */
3057 pSMB->TotalDataCount = 0;
3058 pSMB->MaxParameterCount = cpu_to_le16(2);
3059 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
3060 pSMB->MaxSetupCount = 0;
3064 pSMB->Reserved2 = 0;
3065 byte_count = params + 1 /* pad */ ;
3066 pSMB->TotalParameterCount = cpu_to_le16(params);
3067 pSMB->ParameterCount = pSMB->TotalParameterCount;
3068 pSMB->ParameterOffset = cpu_to_le16(offsetof(
3069 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
3070 pSMB->DataCount = 0;
3071 pSMB->DataOffset = 0;
3072 pSMB->SetupCount = 1;
3073 pSMB->Reserved3 = 0;
3074 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
3075 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_SIZE_INFO);
3076 pSMB->hdr.smb_buf_length += byte_count;
3077 pSMB->ByteCount = cpu_to_le16(byte_count);
3079 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3080 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3082 cERROR(1, ("Send error in QFSInfo = %d", rc));
3083 } else { /* decode response */
3084 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3086 if (rc || (pSMBr->ByteCount < 24)) /* BB alsO CHEck enough total bytes returned */
3087 rc = -EIO; /* bad smb */
3089 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3091 ("Decoding qfsinfo response. BCC: %d Offset %d",
3092 pSMBr->ByteCount, data_offset));
3096 *) (((char *) &pSMBr->hdr.Protocol) +
3099 le32_to_cpu(response_data->BytesPerSector) *
3100 le32_to_cpu(response_data->
3101 SectorsPerAllocationUnit);
3103 le64_to_cpu(response_data->TotalAllocationUnits);
3104 FSData->f_bfree = FSData->f_bavail =
3105 le64_to_cpu(response_data->FreeAllocationUnits);
3107 ("Blocks: %lld Free: %lld Block size %ld",
3108 (unsigned long long)FSData->f_blocks,
3109 (unsigned long long)FSData->f_bfree,
3113 cifs_buf_release(pSMB);
3122 CIFSSMBQFSAttributeInfo(const int xid, struct cifsTconInfo *tcon)
3124 /* level 0x105 SMB_QUERY_FILE_SYSTEM_INFO */
3125 TRANSACTION2_QFSI_REQ *pSMB = NULL;
3126 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
3127 FILE_SYSTEM_ATTRIBUTE_INFO *response_data;
3129 int bytes_returned = 0;
3130 __u16 params, byte_count;
3132 cFYI(1, ("In QFSAttributeInfo"));
3134 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3139 params = 2; /* level */
3140 pSMB->TotalDataCount = 0;
3141 pSMB->MaxParameterCount = cpu_to_le16(2);
3142 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
3143 pSMB->MaxSetupCount = 0;
3147 pSMB->Reserved2 = 0;
3148 byte_count = params + 1 /* pad */ ;
3149 pSMB->TotalParameterCount = cpu_to_le16(params);
3150 pSMB->ParameterCount = pSMB->TotalParameterCount;
3151 pSMB->ParameterOffset = cpu_to_le16(offsetof(
3152 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
3153 pSMB->DataCount = 0;
3154 pSMB->DataOffset = 0;
3155 pSMB->SetupCount = 1;
3156 pSMB->Reserved3 = 0;
3157 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
3158 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_ATTRIBUTE_INFO);
3159 pSMB->hdr.smb_buf_length += byte_count;
3160 pSMB->ByteCount = cpu_to_le16(byte_count);
3162 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3163 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3165 cERROR(1, ("Send error in QFSAttributeInfo = %d", rc));
3166 } else { /* decode response */
3167 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3169 if (rc || (pSMBr->ByteCount < 13)) { /* BB also check enough bytes returned */
3170 rc = -EIO; /* bad smb */
3172 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3174 (FILE_SYSTEM_ATTRIBUTE_INFO
3175 *) (((char *) &pSMBr->hdr.Protocol) +
3177 memcpy(&tcon->fsAttrInfo, response_data,
3178 sizeof (FILE_SYSTEM_ATTRIBUTE_INFO));
3181 cifs_buf_release(pSMB);
3184 goto QFSAttributeRetry;
3190 CIFSSMBQFSDeviceInfo(const int xid, struct cifsTconInfo *tcon)
3192 /* level 0x104 SMB_QUERY_FILE_SYSTEM_INFO */
3193 TRANSACTION2_QFSI_REQ *pSMB = NULL;
3194 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
3195 FILE_SYSTEM_DEVICE_INFO *response_data;
3197 int bytes_returned = 0;
3198 __u16 params, byte_count;
3200 cFYI(1, ("In QFSDeviceInfo"));
3202 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3207 params = 2; /* level */
3208 pSMB->TotalDataCount = 0;
3209 pSMB->MaxParameterCount = cpu_to_le16(2);
3210 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
3211 pSMB->MaxSetupCount = 0;
3215 pSMB->Reserved2 = 0;
3216 byte_count = params + 1 /* pad */ ;
3217 pSMB->TotalParameterCount = cpu_to_le16(params);
3218 pSMB->ParameterCount = pSMB->TotalParameterCount;
3219 pSMB->ParameterOffset = cpu_to_le16(offsetof(
3220 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
3222 pSMB->DataCount = 0;
3223 pSMB->DataOffset = 0;
3224 pSMB->SetupCount = 1;
3225 pSMB->Reserved3 = 0;
3226 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
3227 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_DEVICE_INFO);
3228 pSMB->hdr.smb_buf_length += byte_count;
3229 pSMB->ByteCount = cpu_to_le16(byte_count);
3231 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3232 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3234 cFYI(1, ("Send error in QFSDeviceInfo = %d", rc));
3235 } else { /* decode response */
3236 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3238 if (rc || (pSMBr->ByteCount < sizeof (FILE_SYSTEM_DEVICE_INFO)))
3239 rc = -EIO; /* bad smb */
3241 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3243 (FILE_SYSTEM_DEVICE_INFO *)
3244 (((char *) &pSMBr->hdr.Protocol) +
3246 memcpy(&tcon->fsDevInfo, response_data,
3247 sizeof (FILE_SYSTEM_DEVICE_INFO));
3250 cifs_buf_release(pSMB);
3253 goto QFSDeviceRetry;
3259 CIFSSMBQFSUnixInfo(const int xid, struct cifsTconInfo *tcon)
3261 /* level 0x200 SMB_QUERY_CIFS_UNIX_INFO */
3262 TRANSACTION2_QFSI_REQ *pSMB = NULL;
3263 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
3264 FILE_SYSTEM_UNIX_INFO *response_data;
3266 int bytes_returned = 0;
3267 __u16 params, byte_count;
3269 cFYI(1, ("In QFSUnixInfo"));
3271 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3276 params = 2; /* level */
3277 pSMB->TotalDataCount = 0;
3278 pSMB->DataCount = 0;
3279 pSMB->DataOffset = 0;
3280 pSMB->MaxParameterCount = cpu_to_le16(2);
3281 pSMB->MaxDataCount = cpu_to_le16(100); /* BB find exact max SMB PDU from sess structure BB */
3282 pSMB->MaxSetupCount = 0;
3286 pSMB->Reserved2 = 0;
3287 byte_count = params + 1 /* pad */ ;
3288 pSMB->ParameterCount = cpu_to_le16(params);
3289 pSMB->TotalParameterCount = pSMB->ParameterCount;
3290 pSMB->ParameterOffset = cpu_to_le16(offsetof(struct
3291 smb_com_transaction2_qfsi_req, InformationLevel) - 4);
3292 pSMB->SetupCount = 1;
3293 pSMB->Reserved3 = 0;
3294 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
3295 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_CIFS_UNIX_INFO);
3296 pSMB->hdr.smb_buf_length += byte_count;
3297 pSMB->ByteCount = cpu_to_le16(byte_count);
3299 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3300 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3302 cERROR(1, ("Send error in QFSUnixInfo = %d", rc));
3303 } else { /* decode response */
3304 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3306 if (rc || (pSMBr->ByteCount < 13)) {
3307 rc = -EIO; /* bad smb */
3309 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3311 (FILE_SYSTEM_UNIX_INFO
3312 *) (((char *) &pSMBr->hdr.Protocol) +
3314 memcpy(&tcon->fsUnixInfo, response_data,
3315 sizeof (FILE_SYSTEM_UNIX_INFO));
3318 cifs_buf_release(pSMB);
3328 CIFSSMBSetFSUnixInfo(const int xid, struct cifsTconInfo *tcon, __u64 cap)
3330 /* level 0x200 SMB_SET_CIFS_UNIX_INFO */
3331 TRANSACTION2_SETFSI_REQ *pSMB = NULL;
3332 TRANSACTION2_SETFSI_RSP *pSMBr = NULL;
3334 int bytes_returned = 0;
3335 __u16 params, param_offset, offset, byte_count;
3337 cFYI(1, ("In SETFSUnixInfo"));
3339 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3344 params = 4; /* 2 bytes zero followed by info level. */
3345 pSMB->MaxSetupCount = 0;
3349 pSMB->Reserved2 = 0;
3350 param_offset = offsetof(struct smb_com_transaction2_setfsi_req, FileNum) - 4;
3351 offset = param_offset + params;
3353 pSMB->MaxParameterCount = cpu_to_le16(4);
3354 pSMB->MaxDataCount = cpu_to_le16(100); /* BB find exact max SMB PDU from sess structure BB */
3355 pSMB->SetupCount = 1;
3356 pSMB->Reserved3 = 0;
3357 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FS_INFORMATION);
3358 byte_count = 1 /* pad */ + params + 12;
3360 pSMB->DataCount = cpu_to_le16(12);
3361 pSMB->ParameterCount = cpu_to_le16(params);
3362 pSMB->TotalDataCount = pSMB->DataCount;
3363 pSMB->TotalParameterCount = pSMB->ParameterCount;
3364 pSMB->ParameterOffset = cpu_to_le16(param_offset);
3365 pSMB->DataOffset = cpu_to_le16(offset);
3369 pSMB->InformationLevel = cpu_to_le16(SMB_SET_CIFS_UNIX_INFO);
3372 pSMB->ClientUnixMajor = cpu_to_le16(CIFS_UNIX_MAJOR_VERSION);
3373 pSMB->ClientUnixMinor = cpu_to_le16(CIFS_UNIX_MINOR_VERSION);
3374 pSMB->ClientUnixCap = cpu_to_le64(cap);
3376 pSMB->hdr.smb_buf_length += byte_count;
3377 pSMB->ByteCount = cpu_to_le16(byte_count);
3379 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3380 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3382 cERROR(1, ("Send error in SETFSUnixInfo = %d", rc));
3383 } else { /* decode response */
3384 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3386 rc = -EIO; /* bad smb */
3389 cifs_buf_release(pSMB);
3392 goto SETFSUnixRetry;
3400 CIFSSMBQFSPosixInfo(const int xid, struct cifsTconInfo *tcon,
3401 struct kstatfs *FSData)
3403 /* level 0x201 SMB_QUERY_CIFS_POSIX_INFO */
3404 TRANSACTION2_QFSI_REQ *pSMB = NULL;
3405 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
3406 FILE_SYSTEM_POSIX_INFO *response_data;
3408 int bytes_returned = 0;
3409 __u16 params, byte_count;
3411 cFYI(1, ("In QFSPosixInfo"));
3413 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3418 params = 2; /* level */
3419 pSMB->TotalDataCount = 0;
3420 pSMB->DataCount = 0;
3421 pSMB->DataOffset = 0;
3422 pSMB->MaxParameterCount = cpu_to_le16(2);
3423 pSMB->MaxDataCount = cpu_to_le16(100); /* BB find exact max SMB PDU from sess structure BB */
3424 pSMB->MaxSetupCount = 0;
3428 pSMB->Reserved2 = 0;
3429 byte_count = params + 1 /* pad */ ;
3430 pSMB->ParameterCount = cpu_to_le16(params);
3431 pSMB->TotalParameterCount = pSMB->ParameterCount;
3432 pSMB->ParameterOffset = cpu_to_le16(offsetof(struct
3433 smb_com_transaction2_qfsi_req, InformationLevel) - 4);
3434 pSMB->SetupCount = 1;
3435 pSMB->Reserved3 = 0;
3436 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
3437 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_POSIX_FS_INFO);
3438 pSMB->hdr.smb_buf_length += byte_count;
3439 pSMB->ByteCount = cpu_to_le16(byte_count);
3441 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3442 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3444 cFYI(1, ("Send error in QFSUnixInfo = %d", rc));
3445 } else { /* decode response */
3446 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3448 if (rc || (pSMBr->ByteCount < 13)) {
3449 rc = -EIO; /* bad smb */
3451 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3453 (FILE_SYSTEM_POSIX_INFO
3454 *) (((char *) &pSMBr->hdr.Protocol) +
3457 le32_to_cpu(response_data->BlockSize);
3459 le64_to_cpu(response_data->TotalBlocks);
3461 le64_to_cpu(response_data->BlocksAvail);
3462 if(response_data->UserBlocksAvail == -1) {
3463 FSData->f_bavail = FSData->f_bfree;
3466 le64_to_cpu(response_data->UserBlocksAvail);
3468 if(response_data->TotalFileNodes != -1)
3470 le64_to_cpu(response_data->TotalFileNodes);
3471 if(response_data->FreeFileNodes != -1)
3473 le64_to_cpu(response_data->FreeFileNodes);
3476 cifs_buf_release(pSMB);
3485 /* We can not use write of zero bytes trick to
3486 set file size due to need for large file support. Also note that
3487 this SetPathInfo is preferred to SetFileInfo based method in next
3488 routine which is only needed to work around a sharing violation bug
3489 in Samba which this routine can run into */
3492 CIFSSMBSetEOF(const int xid, struct cifsTconInfo *tcon, const char *fileName,
3493 __u64 size, int SetAllocation,
3494 const struct nls_table *nls_codepage, int remap)
3496 struct smb_com_transaction2_spi_req *pSMB = NULL;
3497 struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
3498 struct file_end_of_file_info *parm_data;
3501 int bytes_returned = 0;
3502 __u16 params, byte_count, data_count, param_offset, offset;
3504 cFYI(1, ("In SetEOF"));
3506 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3511 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3513 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
3514 PATH_MAX, nls_codepage, remap);
3515 name_len++; /* trailing null */
3517 } else { /* BB improve the check for buffer overruns BB */
3518 name_len = strnlen(fileName, PATH_MAX);
3519 name_len++; /* trailing null */
3520 strncpy(pSMB->FileName, fileName, name_len);
3522 params = 6 + name_len;
3523 data_count = sizeof (struct file_end_of_file_info);
3524 pSMB->MaxParameterCount = cpu_to_le16(2);
3525 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB size from sess */
3526 pSMB->MaxSetupCount = 0;
3530 pSMB->Reserved2 = 0;
3531 param_offset = offsetof(struct smb_com_transaction2_spi_req,
3532 InformationLevel) - 4;
3533 offset = param_offset + params;
3535 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
3536 pSMB->InformationLevel =
3537 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2);
3539 pSMB->InformationLevel =
3540 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO);
3541 } else /* Set File Size */ {
3542 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
3543 pSMB->InformationLevel =
3544 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO2);
3546 pSMB->InformationLevel =
3547 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO);
3551 (struct file_end_of_file_info *) (((char *) &pSMB->hdr.Protocol) +
3553 pSMB->ParameterOffset = cpu_to_le16(param_offset);
3554 pSMB->DataOffset = cpu_to_le16(offset);
3555 pSMB->SetupCount = 1;
3556 pSMB->Reserved3 = 0;
3557 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
3558 byte_count = 3 /* pad */ + params + data_count;
3559 pSMB->DataCount = cpu_to_le16(data_count);
3560 pSMB->TotalDataCount = pSMB->DataCount;
3561 pSMB->ParameterCount = cpu_to_le16(params);
3562 pSMB->TotalParameterCount = pSMB->ParameterCount;
3563 pSMB->Reserved4 = 0;
3564 pSMB->hdr.smb_buf_length += byte_count;
3565 parm_data->FileSize = cpu_to_le64(size);
3566 pSMB->ByteCount = cpu_to_le16(byte_count);
3567 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3568 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3570 cFYI(1, ("SetPathInfo (file size) returned %d", rc));
3573 cifs_buf_release(pSMB);
3582 CIFSSMBSetFileSize(const int xid, struct cifsTconInfo *tcon, __u64 size,
3583 __u16 fid, __u32 pid_of_opener, int SetAllocation)
3585 struct smb_com_transaction2_sfi_req *pSMB = NULL;
3586 struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
3588 struct file_end_of_file_info *parm_data;
3590 int bytes_returned = 0;
3591 __u16 params, param_offset, offset, byte_count, count;
3593 cFYI(1, ("SetFileSize (via SetFileInfo) %lld",
3595 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
3600 pSMBr = (struct smb_com_transaction2_sfi_rsp *)pSMB;
3602 pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
3603 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));
3606 pSMB->MaxSetupCount = 0;
3610 pSMB->Reserved2 = 0;
3611 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
3612 offset = param_offset + params;
3614 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
3616 count = sizeof(struct file_end_of_file_info);
3617 pSMB->MaxParameterCount = cpu_to_le16(2);
3618 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB PDU from sess */
3619 pSMB->SetupCount = 1;
3620 pSMB->Reserved3 = 0;
3621 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
3622 byte_count = 3 /* pad */ + params + count;
3623 pSMB->DataCount = cpu_to_le16(count);
3624 pSMB->ParameterCount = cpu_to_le16(params);
3625 pSMB->TotalDataCount = pSMB->DataCount;
3626 pSMB->TotalParameterCount = pSMB->ParameterCount;
3627 pSMB->ParameterOffset = cpu_to_le16(param_offset);
3629 (struct file_end_of_file_info *) (((char *) &pSMB->hdr.Protocol) +
3631 pSMB->DataOffset = cpu_to_le16(offset);
3632 parm_data->FileSize = cpu_to_le64(size);
3635 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
3636 pSMB->InformationLevel =
3637 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2);
3639 pSMB->InformationLevel =
3640 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO);
3641 } else /* Set File Size */ {
3642 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
3643 pSMB->InformationLevel =
3644 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO2);
3646 pSMB->InformationLevel =
3647 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO);
3649 pSMB->Reserved4 = 0;
3650 pSMB->hdr.smb_buf_length += byte_count;
3651 pSMB->ByteCount = cpu_to_le16(byte_count);
3652 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3653 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3656 ("Send error in SetFileInfo (SetFileSize) = %d",
3661 cifs_small_buf_release(pSMB);
3663 /* Note: On -EAGAIN error only caller can retry on handle based calls
3664 since file handle passed in no longer valid */
3669 /* Some legacy servers such as NT4 require that the file times be set on
3670 an open handle, rather than by pathname - this is awkward due to
3671 potential access conflicts on the open, but it is unavoidable for these
3672 old servers since the only other choice is to go from 100 nanosecond DCE
3673 time and resort to the original setpathinfo level which takes the ancient
3674 DOS time format with 2 second granularity */
3676 CIFSSMBSetFileTimes(const int xid, struct cifsTconInfo *tcon, const FILE_BASIC_INFO * data,
3679 struct smb_com_transaction2_sfi_req *pSMB = NULL;
3680 struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
3683 int bytes_returned = 0;
3684 __u16 params, param_offset, offset, byte_count, count;
3686 cFYI(1, ("Set Times (via SetFileInfo)"));
3687 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
3692 pSMBr = (struct smb_com_transaction2_sfi_rsp *)pSMB;
3694 /* At this point there is no need to override the current pid
3695 with the pid of the opener, but that could change if we someday
3696 use an existing handle (rather than opening one on the fly) */
3697 /* pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
3698 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));*/
3701 pSMB->MaxSetupCount = 0;
3705 pSMB->Reserved2 = 0;
3706 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
3707 offset = param_offset + params;
3709 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
3711 count = sizeof (FILE_BASIC_INFO);
3712 pSMB->MaxParameterCount = cpu_to_le16(2);
3713 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB PDU from sess */
3714 pSMB->SetupCount = 1;
3715 pSMB->Reserved3 = 0;
3716 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
3717 byte_count = 3 /* pad */ + params + count;
3718 pSMB->DataCount = cpu_to_le16(count);
3719 pSMB->ParameterCount = cpu_to_le16(params);
3720 pSMB->TotalDataCount = pSMB->DataCount;
3721 pSMB->TotalParameterCount = pSMB->ParameterCount;
3722 pSMB->ParameterOffset = cpu_to_le16(param_offset);
3723 pSMB->DataOffset = cpu_to_le16(offset);
3725 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
3726 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO2);
3728 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO);
3729 pSMB->Reserved4 = 0;
3730 pSMB->hdr.smb_buf_length += byte_count;
3731 pSMB->ByteCount = cpu_to_le16(byte_count);
3732 memcpy(data_offset,data,sizeof(FILE_BASIC_INFO));
3733 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3734 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3736 cFYI(1,("Send error in Set Time (SetFileInfo) = %d",rc));
3739 cifs_small_buf_release(pSMB);
3741 /* Note: On -EAGAIN error only caller can retry on handle based calls
3742 since file handle passed in no longer valid */
3749 CIFSSMBSetTimes(const int xid, struct cifsTconInfo *tcon, const char *fileName,
3750 const FILE_BASIC_INFO * data,
3751 const struct nls_table *nls_codepage, int remap)
3753 TRANSACTION2_SPI_REQ *pSMB = NULL;
3754 TRANSACTION2_SPI_RSP *pSMBr = NULL;
3757 int bytes_returned = 0;
3759 __u16 params, param_offset, offset, byte_count, count;
3761 cFYI(1, ("In SetTimes"));
3764 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3769 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3771 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
3772 PATH_MAX, nls_codepage, remap);
3773 name_len++; /* trailing null */
3775 } else { /* BB improve the check for buffer overruns BB */
3776 name_len = strnlen(fileName, PATH_MAX);
3777 name_len++; /* trailing null */
3778 strncpy(pSMB->FileName, fileName, name_len);
3781 params = 6 + name_len;
3782 count = sizeof (FILE_BASIC_INFO);
3783 pSMB->MaxParameterCount = cpu_to_le16(2);
3784 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
3785 pSMB->MaxSetupCount = 0;
3789 pSMB->Reserved2 = 0;
3790 param_offset = offsetof(struct smb_com_transaction2_spi_req,
3791 InformationLevel) - 4;
3792 offset = param_offset + params;
3793 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
3794 pSMB->ParameterOffset = cpu_to_le16(param_offset);
3795 pSMB->DataOffset = cpu_to_le16(offset);
3796 pSMB->SetupCount = 1;
3797 pSMB->Reserved3 = 0;
3798 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
3799 byte_count = 3 /* pad */ + params + count;
3801 pSMB->DataCount = cpu_to_le16(count);
3802 pSMB->ParameterCount = cpu_to_le16(params);
3803 pSMB->TotalDataCount = pSMB->DataCount;
3804 pSMB->TotalParameterCount = pSMB->ParameterCount;
3805 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
3806 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO2);
3808 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO);
3809 pSMB->Reserved4 = 0;
3810 pSMB->hdr.smb_buf_length += byte_count;
3811 memcpy(data_offset, data, sizeof (FILE_BASIC_INFO));
3812 pSMB->ByteCount = cpu_to_le16(byte_count);
3813 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3814 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3816 cFYI(1, ("SetPathInfo (times) returned %d", rc));
3819 cifs_buf_release(pSMB);
3827 /* Can not be used to set time stamps yet (due to old DOS time format) */
3828 /* Can be used to set attributes */
3829 #if 0 /* Possibly not needed - since it turns out that strangely NT4 has a bug
3830 handling it anyway and NT4 was what we thought it would be needed for
3831 Do not delete it until we prove whether needed for Win9x though */
3833 CIFSSMBSetAttrLegacy(int xid, struct cifsTconInfo *tcon, char *fileName,
3834 __u16 dos_attrs, const struct nls_table *nls_codepage)
3836 SETATTR_REQ *pSMB = NULL;
3837 SETATTR_RSP *pSMBr = NULL;
3842 cFYI(1, ("In SetAttrLegacy"));
3845 rc = smb_init(SMB_COM_SETATTR, 8, tcon, (void **) &pSMB,
3850 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3852 ConvertToUCS((__le16 *) pSMB->fileName, fileName,
3853 PATH_MAX, nls_codepage);
3854 name_len++; /* trailing null */
3856 } else { /* BB improve the check for buffer overruns BB */
3857 name_len = strnlen(fileName, PATH_MAX);
3858 name_len++; /* trailing null */
3859 strncpy(pSMB->fileName, fileName, name_len);
3861 pSMB->attr = cpu_to_le16(dos_attrs);
3862 pSMB->BufferFormat = 0x04;
3863 pSMB->hdr.smb_buf_length += name_len + 1;
3864 pSMB->ByteCount = cpu_to_le16(name_len + 1);
3865 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3866 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3868 cFYI(1, ("Error in LegacySetAttr = %d", rc));
3871 cifs_buf_release(pSMB);
3874 goto SetAttrLgcyRetry;
3878 #endif /* temporarily unneeded SetAttr legacy function */
3881 CIFSSMBUnixSetPerms(const int xid, struct cifsTconInfo *tcon,
3882 char *fileName, __u64 mode, __u64 uid, __u64 gid,
3883 dev_t device, const struct nls_table *nls_codepage,
3886 TRANSACTION2_SPI_REQ *pSMB = NULL;
3887 TRANSACTION2_SPI_RSP *pSMBr = NULL;
3890 int bytes_returned = 0;
3891 FILE_UNIX_BASIC_INFO *data_offset;
3892 __u16 params, param_offset, offset, count, byte_count;
3894 cFYI(1, ("In SetUID/GID/Mode"));
3896 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3901 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3903 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
3904 PATH_MAX, nls_codepage, remap);
3905 name_len++; /* trailing null */
3907 } else { /* BB improve the check for buffer overruns BB */
3908 name_len = strnlen(fileName, PATH_MAX);
3909 name_len++; /* trailing null */
3910 strncpy(pSMB->FileName, fileName, name_len);
3913 params = 6 + name_len;
3914 count = sizeof (FILE_UNIX_BASIC_INFO);
3915 pSMB->MaxParameterCount = cpu_to_le16(2);
3916 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
3917 pSMB->MaxSetupCount = 0;
3921 pSMB->Reserved2 = 0;
3922 param_offset = offsetof(struct smb_com_transaction2_spi_req,
3923 InformationLevel) - 4;
3924 offset = param_offset + params;
3926 (FILE_UNIX_BASIC_INFO *) ((char *) &pSMB->hdr.Protocol +
3928 memset(data_offset, 0, count);
3929 pSMB->DataOffset = cpu_to_le16(offset);
3930 pSMB->ParameterOffset = cpu_to_le16(param_offset);
3931 pSMB->SetupCount = 1;
3932 pSMB->Reserved3 = 0;
3933 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
3934 byte_count = 3 /* pad */ + params + count;
3935 pSMB->ParameterCount = cpu_to_le16(params);
3936 pSMB->DataCount = cpu_to_le16(count);
3937 pSMB->TotalParameterCount = pSMB->ParameterCount;
3938 pSMB->TotalDataCount = pSMB->DataCount;
3939 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_BASIC);
3940 pSMB->Reserved4 = 0;
3941 pSMB->hdr.smb_buf_length += byte_count;
3942 data_offset->Uid = cpu_to_le64(uid);
3943 data_offset->Gid = cpu_to_le64(gid);
3944 /* better to leave device as zero when it is */
3945 data_offset->DevMajor = cpu_to_le64(MAJOR(device));
3946 data_offset->DevMinor = cpu_to_le64(MINOR(device));
3947 data_offset->Permissions = cpu_to_le64(mode);
3950 data_offset->Type = cpu_to_le32(UNIX_FILE);
3951 else if(S_ISDIR(mode))
3952 data_offset->Type = cpu_to_le32(UNIX_DIR);
3953 else if(S_ISLNK(mode))
3954 data_offset->Type = cpu_to_le32(UNIX_SYMLINK);
3955 else if(S_ISCHR(mode))
3956 data_offset->Type = cpu_to_le32(UNIX_CHARDEV);
3957 else if(S_ISBLK(mode))
3958 data_offset->Type = cpu_to_le32(UNIX_BLOCKDEV);
3959 else if(S_ISFIFO(mode))
3960 data_offset->Type = cpu_to_le32(UNIX_FIFO);
3961 else if(S_ISSOCK(mode))
3962 data_offset->Type = cpu_to_le32(UNIX_SOCKET);
3965 pSMB->ByteCount = cpu_to_le16(byte_count);
3966 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3967 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3969 cFYI(1, ("SetPathInfo (perms) returned %d", rc));
3973 cifs_buf_release(pSMB);
3979 int CIFSSMBNotify(const int xid, struct cifsTconInfo *tcon,
3980 const int notify_subdirs, const __u16 netfid,
3981 __u32 filter, const struct nls_table *nls_codepage)
3984 struct smb_com_transaction_change_notify_req * pSMB = NULL;
3985 struct smb_com_transaction_change_notify_rsp * pSMBr = NULL;
3986 struct dir_notify_req *dnotify_req;
3989 cFYI(1, ("In CIFSSMBNotify for file handle %d",(int)netfid));
3990 rc = smb_init(SMB_COM_NT_TRANSACT, 23, tcon, (void **) &pSMB,
3995 pSMB->TotalParameterCount = 0 ;
3996 pSMB->TotalDataCount = 0;
3997 pSMB->MaxParameterCount = cpu_to_le32(2);
3998 /* BB find exact data count max from sess structure BB */
3999 pSMB->MaxDataCount = 0; /* same in little endian or be */
4000 pSMB->MaxSetupCount = 4;
4002 pSMB->ParameterOffset = 0;
4003 pSMB->DataCount = 0;
4004 pSMB->DataOffset = 0;
4005 pSMB->SetupCount = 4; /* single byte does not need le conversion */
4006 pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_NOTIFY_CHANGE);
4007 pSMB->ParameterCount = pSMB->TotalParameterCount;
4009 pSMB->WatchTree = 1; /* one byte - no le conversion needed */
4010 pSMB->Reserved2 = 0;
4011 pSMB->CompletionFilter = cpu_to_le32(filter);
4012 pSMB->Fid = netfid; /* file handle always le */
4013 pSMB->ByteCount = 0;
4015 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4016 (struct smb_hdr *) pSMBr, &bytes_returned, -1);
4018 cFYI(1, ("Error in Notify = %d", rc));
4020 /* Add file to outstanding requests */
4021 dnotify_req = (struct dir_notify_req *) kmalloc(
4022 sizeof(struct dir_notify_req), GFP_KERNEL);
4023 dnotify_req->Pid = pSMB->hdr.Pid;
4024 dnotify_req->PidHigh = pSMB->hdr.PidHigh;
4025 dnotify_req->Mid = pSMB->hdr.Mid;
4026 dnotify_req->Tid = pSMB->hdr.Tid;
4027 dnotify_req->Uid = pSMB->hdr.Uid;
4028 dnotify_req->netfid = netfid;
4029 dnotify_req->dentry = dentry;
4030 dnotify_req->filter = filter;
4031 dnotify_req->multishot = multishot;
4032 spin_lock(&GlobalMid_Lock);
4033 list_add_tail(&dnotify_req->lhead, &GlobalDnotifyReqList);
4034 spin_unlock(&GlobalMid_Lock);
4036 cifs_buf_release(pSMB);
4039 #ifdef CONFIG_CIFS_XATTR
4041 CIFSSMBQAllEAs(const int xid, struct cifsTconInfo *tcon,
4042 const unsigned char *searchName,
4043 char * EAData, size_t buf_size,
4044 const struct nls_table *nls_codepage, int remap)
4046 /* BB assumes one setup word */
4047 TRANSACTION2_QPI_REQ *pSMB = NULL;
4048 TRANSACTION2_QPI_RSP *pSMBr = NULL;
4052 struct fea * temp_fea;
4054 __u16 params, byte_count;
4056 cFYI(1, ("In Query All EAs path %s", searchName));
4058 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4063 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4065 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
4066 PATH_MAX, nls_codepage, remap);
4067 name_len++; /* trailing null */
4069 } else { /* BB improve the check for buffer overruns BB */
4070 name_len = strnlen(searchName, PATH_MAX);
4071 name_len++; /* trailing null */
4072 strncpy(pSMB->FileName, searchName, name_len);
4075 params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */ ;
4076 pSMB->TotalDataCount = 0;
4077 pSMB->MaxParameterCount = cpu_to_le16(2);
4078 pSMB->MaxDataCount = cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
4079 pSMB->MaxSetupCount = 0;
4083 pSMB->Reserved2 = 0;
4084 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4085 struct smb_com_transaction2_qpi_req ,InformationLevel) - 4);
4086 pSMB->DataCount = 0;
4087 pSMB->DataOffset = 0;
4088 pSMB->SetupCount = 1;
4089 pSMB->Reserved3 = 0;
4090 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
4091 byte_count = params + 1 /* pad */ ;
4092 pSMB->TotalParameterCount = cpu_to_le16(params);
4093 pSMB->ParameterCount = pSMB->TotalParameterCount;
4094 pSMB->InformationLevel = cpu_to_le16(SMB_INFO_QUERY_ALL_EAS);
4095 pSMB->Reserved4 = 0;
4096 pSMB->hdr.smb_buf_length += byte_count;
4097 pSMB->ByteCount = cpu_to_le16(byte_count);
4099 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4100 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4102 cFYI(1, ("Send error in QueryAllEAs = %d", rc));
4103 } else { /* decode response */
4104 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4106 /* BB also check enough total bytes returned */
4107 /* BB we need to improve the validity checking
4108 of these trans2 responses */
4109 if (rc || (pSMBr->ByteCount < 4))
4110 rc = -EIO; /* bad smb */
4111 /* else if (pFindData){
4112 memcpy((char *) pFindData,
4113 (char *) &pSMBr->hdr.Protocol +
4116 /* check that length of list is not more than bcc */
4117 /* check that each entry does not go beyond length
4119 /* check that each element of each entry does not
4120 go beyond end of list */
4121 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4122 struct fealist * ea_response_data;
4124 /* validate_trans2_offsets() */
4125 /* BB to check if(start of smb + data_offset > &bcc+ bcc)*/
4126 ea_response_data = (struct fealist *)
4127 (((char *) &pSMBr->hdr.Protocol) +
4129 name_len = le32_to_cpu(ea_response_data->list_len);
4130 cFYI(1,("ea length %d", name_len));
4132 /* returned EA size zeroed at top of function */
4133 cFYI(1,("empty EA list returned from server"));
4135 /* account for ea list len */
4137 temp_fea = ea_response_data->list;
4138 temp_ptr = (char *)temp_fea;
4139 while(name_len > 0) {
4143 rc += temp_fea->name_len;
4144 /* account for prefix user. and trailing null */
4146 if(rc<(int)buf_size) {
4147 memcpy(EAData,"user.",5);
4149 memcpy(EAData,temp_ptr,temp_fea->name_len);
4150 EAData+=temp_fea->name_len;
4151 /* null terminate name */
4153 EAData = EAData + 1;
4154 } else if(buf_size == 0) {
4155 /* skip copy - calc size only */
4157 /* stop before overrun buffer */
4161 name_len -= temp_fea->name_len;
4162 temp_ptr += temp_fea->name_len;
4163 /* account for trailing null */
4166 value_len = le16_to_cpu(temp_fea->value_len);
4167 name_len -= value_len;
4168 temp_ptr += value_len;
4169 /* BB check that temp_ptr is still within smb BB*/
4170 /* no trailing null to account for in value len */
4171 /* go on to next EA */
4172 temp_fea = (struct fea *)temp_ptr;
4178 cifs_buf_release(pSMB);
4185 ssize_t CIFSSMBQueryEA(const int xid,struct cifsTconInfo * tcon,
4186 const unsigned char * searchName,const unsigned char * ea_name,
4187 unsigned char * ea_value, size_t buf_size,
4188 const struct nls_table *nls_codepage, int remap)
4190 TRANSACTION2_QPI_REQ *pSMB = NULL;
4191 TRANSACTION2_QPI_RSP *pSMBr = NULL;
4195 struct fea * temp_fea;
4197 __u16 params, byte_count;
4199 cFYI(1, ("In Query EA path %s", searchName));
4201 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4206 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4208 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
4209 PATH_MAX, nls_codepage, remap);
4210 name_len++; /* trailing null */
4212 } else { /* BB improve the check for buffer overruns BB */
4213 name_len = strnlen(searchName, PATH_MAX);
4214 name_len++; /* trailing null */
4215 strncpy(pSMB->FileName, searchName, name_len);
4218 params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */ ;
4219 pSMB->TotalDataCount = 0;
4220 pSMB->MaxParameterCount = cpu_to_le16(2);
4221 pSMB->MaxDataCount = cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
4222 pSMB->MaxSetupCount = 0;
4226 pSMB->Reserved2 = 0;
4227 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4228 struct smb_com_transaction2_qpi_req ,InformationLevel) - 4);
4229 pSMB->DataCount = 0;
4230 pSMB->DataOffset = 0;
4231 pSMB->SetupCount = 1;
4232 pSMB->Reserved3 = 0;
4233 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
4234 byte_count = params + 1 /* pad */ ;
4235 pSMB->TotalParameterCount = cpu_to_le16(params);
4236 pSMB->ParameterCount = pSMB->TotalParameterCount;
4237 pSMB->InformationLevel = cpu_to_le16(SMB_INFO_QUERY_ALL_EAS);
4238 pSMB->Reserved4 = 0;
4239 pSMB->hdr.smb_buf_length += byte_count;
4240 pSMB->ByteCount = cpu_to_le16(byte_count);
4242 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4243 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4245 cFYI(1, ("Send error in Query EA = %d", rc));
4246 } else { /* decode response */
4247 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4249 /* BB also check enough total bytes returned */
4250 /* BB we need to improve the validity checking
4251 of these trans2 responses */
4252 if (rc || (pSMBr->ByteCount < 4))
4253 rc = -EIO; /* bad smb */
4254 /* else if (pFindData){
4255 memcpy((char *) pFindData,
4256 (char *) &pSMBr->hdr.Protocol +
4259 /* check that length of list is not more than bcc */
4260 /* check that each entry does not go beyond length
4262 /* check that each element of each entry does not
4263 go beyond end of list */
4264 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4265 struct fealist * ea_response_data;
4267 /* validate_trans2_offsets() */
4268 /* BB to check if(start of smb + data_offset > &bcc+ bcc)*/
4269 ea_response_data = (struct fealist *)
4270 (((char *) &pSMBr->hdr.Protocol) +
4272 name_len = le32_to_cpu(ea_response_data->list_len);
4273 cFYI(1,("ea length %d", name_len));
4275 /* returned EA size zeroed at top of function */
4276 cFYI(1,("empty EA list returned from server"));
4278 /* account for ea list len */
4280 temp_fea = ea_response_data->list;
4281 temp_ptr = (char *)temp_fea;
4282 /* loop through checking if we have a matching
4283 name and then return the associated value */
4284 while(name_len > 0) {
4288 value_len = le16_to_cpu(temp_fea->value_len);
4289 /* BB validate that value_len falls within SMB,
4290 even though maximum for name_len is 255 */
4291 if(memcmp(temp_fea->name,ea_name,
4292 temp_fea->name_len) == 0) {
4295 /* account for prefix user. and trailing null */
4296 if(rc<=(int)buf_size) {
4298 temp_fea->name+temp_fea->name_len+1,
4300 /* ea values, unlike ea names,
4301 are not null terminated */
4302 } else if(buf_size == 0) {
4303 /* skip copy - calc size only */
4305 /* stop before overrun buffer */
4310 name_len -= temp_fea->name_len;
4311 temp_ptr += temp_fea->name_len;
4312 /* account for trailing null */
4315 name_len -= value_len;
4316 temp_ptr += value_len;
4317 /* no trailing null to account for in value len */
4318 /* go on to next EA */
4319 temp_fea = (struct fea *)temp_ptr;
4325 cifs_buf_release(pSMB);
4333 CIFSSMBSetEA(const int xid, struct cifsTconInfo *tcon, const char *fileName,
4334 const char * ea_name, const void * ea_value,
4335 const __u16 ea_value_len, const struct nls_table *nls_codepage,
4338 struct smb_com_transaction2_spi_req *pSMB = NULL;
4339 struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
4340 struct fealist *parm_data;
4343 int bytes_returned = 0;
4344 __u16 params, param_offset, byte_count, offset, count;
4346 cFYI(1, ("In SetEA"));
4348 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4353 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4355 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
4356 PATH_MAX, nls_codepage, remap);
4357 name_len++; /* trailing null */
4359 } else { /* BB improve the check for buffer overruns BB */
4360 name_len = strnlen(fileName, PATH_MAX);
4361 name_len++; /* trailing null */
4362 strncpy(pSMB->FileName, fileName, name_len);
4365 params = 6 + name_len;
4367 /* done calculating parms using name_len of file name,
4368 now use name_len to calculate length of ea name
4369 we are going to create in the inode xattrs */
4373 name_len = strnlen(ea_name,255);
4375 count = sizeof(*parm_data) + ea_value_len + name_len + 1;
4376 pSMB->MaxParameterCount = cpu_to_le16(2);
4377 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB size from sess */
4378 pSMB->MaxSetupCount = 0;
4382 pSMB->Reserved2 = 0;
4383 param_offset = offsetof(struct smb_com_transaction2_spi_req,
4384 InformationLevel) - 4;
4385 offset = param_offset + params;
4386 pSMB->InformationLevel =
4387 cpu_to_le16(SMB_SET_FILE_EA);
4390 (struct fealist *) (((char *) &pSMB->hdr.Protocol) +
4392 pSMB->ParameterOffset = cpu_to_le16(param_offset);
4393 pSMB->DataOffset = cpu_to_le16(offset);
4394 pSMB->SetupCount = 1;
4395 pSMB->Reserved3 = 0;
4396 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
4397 byte_count = 3 /* pad */ + params + count;
4398 pSMB->DataCount = cpu_to_le16(count);
4399 parm_data->list_len = cpu_to_le32(count);
4400 parm_data->list[0].EA_flags = 0;
4401 /* we checked above that name len is less than 255 */
4402 parm_data->list[0].name_len = (__u8)name_len;;
4403 /* EA names are always ASCII */
4405 strncpy(parm_data->list[0].name,ea_name,name_len);
4406 parm_data->list[0].name[name_len] = 0;
4407 parm_data->list[0].value_len = cpu_to_le16(ea_value_len);
4408 /* caller ensures that ea_value_len is less than 64K but
4409 we need to ensure that it fits within the smb */
4411 /*BB add length check that it would fit in negotiated SMB buffer size BB */
4412 /* if(ea_value_len > buffer_size - 512 (enough for header)) */
4414 memcpy(parm_data->list[0].name+name_len+1,ea_value,ea_value_len);
4416 pSMB->TotalDataCount = pSMB->DataCount;
4417 pSMB->ParameterCount = cpu_to_le16(params);
4418 pSMB->TotalParameterCount = pSMB->ParameterCount;
4419 pSMB->Reserved4 = 0;
4420 pSMB->hdr.smb_buf_length += byte_count;
4421 pSMB->ByteCount = cpu_to_le16(byte_count);
4422 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4423 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4425 cFYI(1, ("SetPathInfo (EA) returned %d", rc));
4428 cifs_buf_release(pSMB);