4 * Copyright (C) International Business Machines Corp., 2002,2006
5 * Author(s): Steve French (sfrench@us.ibm.com)
7 * Contains the routines for constructing the SMB PDUs themselves
9 * This library is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU Lesser General Public License as published
11 * by the Free Software Foundation; either version 2.1 of the License, or
12 * (at your option) any later version.
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
17 * the GNU Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public License
20 * along with this library; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 /* SMB/CIFS PDU handling routines here - except for leftovers in connect.c */
25 /* These are mostly routines that operate on a pathname, or on a tree id */
26 /* (mounted volume), but there are eight handle based routines which must be */
27 /* treated slightly different for reconnection purposes since we never want */
28 /* to reuse a stale file handle and the caller knows the file handle */
31 #include <linux/kernel.h>
32 #include <linux/vfs.h>
33 #include <linux/posix_acl_xattr.h>
34 #include <asm/uaccess.h>
37 #include "cifsproto.h"
38 #include "cifs_unicode.h"
39 #include "cifs_debug.h"
42 #ifdef CONFIG_CIFS_POSIX
47 #ifdef CONFIG_CIFS_WEAK_PW_HASH
48 {LANMAN_PROT, "\2LM1.2X002"},
49 {LANMAN2_PROT, "\2LANMAN2.1"},
50 #endif /* weak password hashing for legacy clients */
51 {CIFS_PROT, "\2NT LM 0.12"},
52 {POSIX_PROT, "\2POSIX 2"},
60 #ifdef CONFIG_CIFS_WEAK_PW_HASH
61 {LANMAN_PROT, "\2LM1.2X002"},
62 #endif /* weak password hashing for legacy clients */
63 {CIFS_PROT, "\2NT LM 0.12"},
68 /* define the number of elements in the cifs dialect array */
69 #ifdef CONFIG_CIFS_POSIX
70 #ifdef CONFIG_CIFS_WEAK_PW_HASH
71 #define CIFS_NUM_PROT 4
73 #define CIFS_NUM_PROT 2
74 #endif /* CIFS_WEAK_PW_HASH */
76 #ifdef CONFIG_CIFS_WEAK_PW_HASH
77 #define CIFS_NUM_PROT 3
79 #define CIFS_NUM_PROT 1
80 #endif /* CONFIG_CIFS_WEAK_PW_HASH */
81 #endif /* CIFS_POSIX */
84 /* Mark as invalid, all open files on tree connections since they
85 were closed when session to server was lost */
86 static void mark_open_files_invalid(struct cifsTconInfo * pTcon)
88 struct cifsFileInfo *open_file = NULL;
89 struct list_head * tmp;
90 struct list_head * tmp1;
92 /* list all files open on tree connection and mark them invalid */
93 write_lock(&GlobalSMBSeslock);
94 list_for_each_safe(tmp, tmp1, &pTcon->openFileList) {
95 open_file = list_entry(tmp,struct cifsFileInfo, tlist);
97 open_file->invalidHandle = TRUE;
100 write_unlock(&GlobalSMBSeslock);
101 /* BB Add call to invalidate_inodes(sb) for all superblocks mounted
105 /* If the return code is zero, this function must fill in request_buf pointer */
107 small_smb_init(int smb_command, int wct, struct cifsTconInfo *tcon,
108 void **request_buf /* returned */)
112 /* SMBs NegProt, SessSetup, uLogoff do not have tcon yet so
113 check for tcp and smb session status done differently
114 for those three - in the calling routine */
116 if(tcon->tidStatus == CifsExiting) {
117 /* only tree disconnect, open, and write,
118 (and ulogoff which does not have tcon)
119 are allowed as we start force umount */
120 if((smb_command != SMB_COM_WRITE_ANDX) &&
121 (smb_command != SMB_COM_OPEN_ANDX) &&
122 (smb_command != SMB_COM_TREE_DISCONNECT)) {
123 cFYI(1,("can not send cmd %d while umounting",
128 if((tcon->ses) && (tcon->ses->status != CifsExiting) &&
129 (tcon->ses->server)){
130 struct nls_table *nls_codepage;
131 /* Give Demultiplex thread up to 10 seconds to
132 reconnect, should be greater than cifs socket
133 timeout which is 7 seconds */
134 while(tcon->ses->server->tcpStatus == CifsNeedReconnect) {
135 wait_event_interruptible_timeout(tcon->ses->server->response_q,
136 (tcon->ses->server->tcpStatus == CifsGood), 10 * HZ);
137 if(tcon->ses->server->tcpStatus == CifsNeedReconnect) {
138 /* on "soft" mounts we wait once */
139 if((tcon->retry == FALSE) ||
140 (tcon->ses->status == CifsExiting)) {
141 cFYI(1,("gave up waiting on reconnect in smb_init"));
143 } /* else "hard" mount - keep retrying
144 until process is killed or server
145 comes back on-line */
146 } else /* TCP session is reestablished now */
151 nls_codepage = load_nls_default();
152 /* need to prevent multiple threads trying to
153 simultaneously reconnect the same SMB session */
154 down(&tcon->ses->sesSem);
155 if(tcon->ses->status == CifsNeedReconnect)
156 rc = cifs_setup_session(0, tcon->ses,
158 if(!rc && (tcon->tidStatus == CifsNeedReconnect)) {
159 mark_open_files_invalid(tcon);
160 rc = CIFSTCon(0, tcon->ses, tcon->treeName, tcon
162 up(&tcon->ses->sesSem);
163 /* BB FIXME add code to check if wsize needs
164 update due to negotiated smb buffer size
167 atomic_inc(&tconInfoReconnectCount);
169 cFYI(1, ("reconnect tcon rc = %d", rc));
170 /* Removed call to reopen open files here -
171 it is safer (and faster) to reopen files
172 one at a time as needed in read and write */
174 /* Check if handle based operation so we
175 know whether we can continue or not without
176 returning to caller to reset file handle */
177 switch(smb_command) {
178 case SMB_COM_READ_ANDX:
179 case SMB_COM_WRITE_ANDX:
181 case SMB_COM_FIND_CLOSE2:
182 case SMB_COM_LOCKING_ANDX: {
183 unload_nls(nls_codepage);
188 up(&tcon->ses->sesSem);
190 unload_nls(nls_codepage);
199 *request_buf = cifs_small_buf_get();
200 if (*request_buf == NULL) {
201 /* BB should we add a retry in here if not a writepage? */
205 header_assemble((struct smb_hdr *) *request_buf, smb_command, tcon,wct);
208 cifs_stats_inc(&tcon->num_smbs_sent);
214 small_smb_init_no_tc(const int smb_command, const int wct,
215 struct cifsSesInfo *ses, void **request_buf)
218 struct smb_hdr * buffer;
220 rc = small_smb_init(smb_command, wct, NULL, request_buf);
224 buffer = (struct smb_hdr *)*request_buf;
225 buffer->Mid = GetNextMid(ses->server);
226 if (ses->capabilities & CAP_UNICODE)
227 buffer->Flags2 |= SMBFLG2_UNICODE;
228 if (ses->capabilities & CAP_STATUS32)
229 buffer->Flags2 |= SMBFLG2_ERR_STATUS;
231 /* uid, tid can stay at zero as set in header assemble */
233 /* BB add support for turning on the signing when
234 this function is used after 1st of session setup requests */
239 /* If the return code is zero, this function must fill in request_buf pointer */
241 smb_init(int smb_command, int wct, struct cifsTconInfo *tcon,
242 void **request_buf /* returned */ ,
243 void **response_buf /* returned */ )
247 /* SMBs NegProt, SessSetup, uLogoff do not have tcon yet so
248 check for tcp and smb session status done differently
249 for those three - in the calling routine */
251 if(tcon->tidStatus == CifsExiting) {
252 /* only tree disconnect, open, and write,
253 (and ulogoff which does not have tcon)
254 are allowed as we start force umount */
255 if((smb_command != SMB_COM_WRITE_ANDX) &&
256 (smb_command != SMB_COM_OPEN_ANDX) &&
257 (smb_command != SMB_COM_TREE_DISCONNECT)) {
258 cFYI(1,("can not send cmd %d while umounting",
264 if((tcon->ses) && (tcon->ses->status != CifsExiting) &&
265 (tcon->ses->server)){
266 struct nls_table *nls_codepage;
267 /* Give Demultiplex thread up to 10 seconds to
268 reconnect, should be greater than cifs socket
269 timeout which is 7 seconds */
270 while(tcon->ses->server->tcpStatus == CifsNeedReconnect) {
271 wait_event_interruptible_timeout(tcon->ses->server->response_q,
272 (tcon->ses->server->tcpStatus == CifsGood), 10 * HZ);
273 if(tcon->ses->server->tcpStatus ==
275 /* on "soft" mounts we wait once */
276 if((tcon->retry == FALSE) ||
277 (tcon->ses->status == CifsExiting)) {
278 cFYI(1,("gave up waiting on reconnect in smb_init"));
280 } /* else "hard" mount - keep retrying
281 until process is killed or server
283 } else /* TCP session is reestablished now */
288 nls_codepage = load_nls_default();
289 /* need to prevent multiple threads trying to
290 simultaneously reconnect the same SMB session */
291 down(&tcon->ses->sesSem);
292 if(tcon->ses->status == CifsNeedReconnect)
293 rc = cifs_setup_session(0, tcon->ses,
295 if(!rc && (tcon->tidStatus == CifsNeedReconnect)) {
296 mark_open_files_invalid(tcon);
297 rc = CIFSTCon(0, tcon->ses, tcon->treeName,
299 up(&tcon->ses->sesSem);
300 /* BB FIXME add code to check if wsize needs
301 update due to negotiated smb buffer size
304 atomic_inc(&tconInfoReconnectCount);
306 cFYI(1, ("reconnect tcon rc = %d", rc));
307 /* Removed call to reopen open files here -
308 it is safer (and faster) to reopen files
309 one at a time as needed in read and write */
311 /* Check if handle based operation so we
312 know whether we can continue or not without
313 returning to caller to reset file handle */
314 switch(smb_command) {
315 case SMB_COM_READ_ANDX:
316 case SMB_COM_WRITE_ANDX:
318 case SMB_COM_FIND_CLOSE2:
319 case SMB_COM_LOCKING_ANDX: {
320 unload_nls(nls_codepage);
325 up(&tcon->ses->sesSem);
327 unload_nls(nls_codepage);
336 *request_buf = cifs_buf_get();
337 if (*request_buf == NULL) {
338 /* BB should we add a retry in here if not a writepage? */
341 /* Although the original thought was we needed the response buf for */
342 /* potential retries of smb operations it turns out we can determine */
343 /* from the mid flags when the request buffer can be resent without */
344 /* having to use a second distinct buffer for the response */
346 *response_buf = *request_buf;
348 header_assemble((struct smb_hdr *) *request_buf, smb_command, tcon,
352 cifs_stats_inc(&tcon->num_smbs_sent);
357 static int validate_t2(struct smb_t2_rsp * pSMB)
363 /* check for plausible wct, bcc and t2 data and parm sizes */
364 /* check for parm and data offset going beyond end of smb */
365 if(pSMB->hdr.WordCount >= 10) {
366 if((le16_to_cpu(pSMB->t2_rsp.ParameterOffset) <= 1024) &&
367 (le16_to_cpu(pSMB->t2_rsp.DataOffset) <= 1024)) {
368 /* check that bcc is at least as big as parms + data */
369 /* check that bcc is less than negotiated smb buffer */
370 total_size = le16_to_cpu(pSMB->t2_rsp.ParameterCount);
371 if(total_size < 512) {
372 total_size+=le16_to_cpu(pSMB->t2_rsp.DataCount);
373 /* BCC le converted in SendReceive */
374 pBCC = (pSMB->hdr.WordCount * 2) +
375 sizeof(struct smb_hdr) +
377 if((total_size <= (*(u16 *)pBCC)) &&
379 CIFSMaxBufSize+MAX_CIFS_HDR_SIZE)) {
386 cifs_dump_mem("Invalid transact2 SMB: ",(char *)pSMB,
387 sizeof(struct smb_t2_rsp) + 16);
391 CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses)
394 NEGOTIATE_RSP *pSMBr;
398 struct TCP_Server_Info * server;
400 unsigned int secFlags;
403 server = ses->server;
408 rc = smb_init(SMB_COM_NEGOTIATE, 0, NULL /* no tcon yet */ ,
409 (void **) &pSMB, (void **) &pSMBr);
413 /* if any of auth flags (ie not sign or seal) are overriden use them */
414 if(ses->overrideSecFlg & (~(CIFSSEC_MUST_SIGN | CIFSSEC_MUST_SEAL)))
415 secFlags = ses->overrideSecFlg;
416 else /* if override flags set only sign/seal OR them with global auth */
417 secFlags = extended_security | ses->overrideSecFlg;
419 cFYI(1,("secFlags 0x%x",secFlags));
421 pSMB->hdr.Mid = GetNextMid(server);
422 pSMB->hdr.Flags2 |= SMBFLG2_UNICODE;
423 if((secFlags & CIFSSEC_MUST_KRB5) == CIFSSEC_MUST_KRB5)
424 pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC;
427 for(i=0;i<CIFS_NUM_PROT;i++) {
428 strncpy(pSMB->DialectsArray+count, protocols[i].name, 16);
429 count += strlen(protocols[i].name) + 1;
430 /* null at end of source and target buffers anyway */
432 pSMB->hdr.smb_buf_length += count;
433 pSMB->ByteCount = cpu_to_le16(count);
435 rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB,
436 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
440 cFYI(1,("Dialect: %d", pSMBr->DialectIndex));
441 /* Check wct = 1 error case */
442 if((pSMBr->hdr.WordCount < 13) || (pSMBr->DialectIndex == BAD_PROT)) {
443 /* core returns wct = 1, but we do not ask for core - otherwise
444 small wct just comes when dialect index is -1 indicating we
445 could not negotiate a common dialect */
448 #ifdef CONFIG_CIFS_WEAK_PW_HASH
449 } else if((pSMBr->hdr.WordCount == 13)
450 && ((pSMBr->DialectIndex == LANMAN_PROT)
451 || (pSMBr->DialectIndex == LANMAN2_PROT))) {
453 struct lanman_neg_rsp * rsp = (struct lanman_neg_rsp *)pSMBr;
455 if((secFlags & CIFSSEC_MAY_LANMAN) ||
456 (secFlags & CIFSSEC_MAY_PLNTXT))
457 server->secType = LANMAN;
459 cERROR(1, ("mount failed weak security disabled"
460 " in /proc/fs/cifs/SecurityFlags"));
464 server->secMode = (__u8)le16_to_cpu(rsp->SecurityMode);
465 server->maxReq = le16_to_cpu(rsp->MaxMpxCount);
466 server->maxBuf = min((__u32)le16_to_cpu(rsp->MaxBufSize),
467 (__u32)CIFSMaxBufSize + MAX_CIFS_HDR_SIZE);
468 GETU32(server->sessid) = le32_to_cpu(rsp->SessionKey);
469 /* even though we do not use raw we might as well set this
470 accurately, in case we ever find a need for it */
471 if((le16_to_cpu(rsp->RawMode) & RAW_ENABLE) == RAW_ENABLE) {
472 server->maxRw = 0xFF00;
473 server->capabilities = CAP_MPX_MODE | CAP_RAW_MODE;
475 server->maxRw = 0;/* we do not need to use raw anyway */
476 server->capabilities = CAP_MPX_MODE;
478 tmp = le16_to_cpu(rsp->ServerTimeZone);
479 if (tmp == (int)0xffff) {
480 /* OS/2 often does not set timezone therefore
481 * we must use server time to calc time zone.
482 * Could deviate slightly from the right zone. Not easy
483 * to adjust, since timezones are not always a multiple
484 * of 60 (sometimes 30 minutes - are there smaller?)
486 struct timespec ts, utc;
488 ts = cnvrtDosUnixTm(le16_to_cpu(rsp->SrvTime.Date),
489 le16_to_cpu(rsp->SrvTime.Time));
490 cFYI(1,("SrvTime: %d sec since 1970 (utc: %d) diff: %d",
491 (int)ts.tv_sec, (int)utc.tv_sec,
492 (int)(utc.tv_sec - ts.tv_sec)));
493 tmp = (int)(utc.tv_sec - ts.tv_sec);
494 adjust = tmp < 0 ? -29 : 29;
495 tmp = ((tmp + adjust) / 60) * 60;
496 server->timeAdj = tmp;
498 server->timeAdj = tmp * 60; /* also in seconds */
500 cFYI(1,("server->timeAdj: %d seconds", server->timeAdj));
503 /* BB get server time for time conversions and add
504 code to use it and timezone since this is not UTC */
506 if (rsp->EncryptionKeyLength ==
507 cpu_to_le16(CIFS_CRYPTO_KEY_SIZE)) {
508 memcpy(server->cryptKey, rsp->EncryptionKey,
509 CIFS_CRYPTO_KEY_SIZE);
510 } else if (server->secMode & SECMODE_PW_ENCRYPT) {
511 rc = -EIO; /* need cryptkey unless plain text */
515 cFYI(1,("LANMAN negotiated"));
516 /* we will not end up setting signing flags - as no signing
517 was in LANMAN and server did not return the flags on */
519 #else /* weak security disabled */
520 } else if(pSMBr->hdr.WordCount == 13) {
521 cERROR(1,("mount failed, cifs module not built "
522 "with CIFS_WEAK_PW_HASH support"));
524 #endif /* WEAK_PW_HASH */
526 } else if(pSMBr->hdr.WordCount != 17) {
531 /* else wct == 17 NTLM */
532 server->secMode = pSMBr->SecurityMode;
533 if((server->secMode & SECMODE_USER) == 0)
534 cFYI(1,("share mode security"));
536 if((server->secMode & SECMODE_PW_ENCRYPT) == 0)
537 #ifdef CONFIG_CIFS_WEAK_PW_HASH
538 if ((secFlags & CIFSSEC_MAY_PLNTXT) == 0)
539 #endif /* CIFS_WEAK_PW_HASH */
540 cERROR(1,("Server requests plain text password"
541 " but client support disabled"));
543 if((secFlags & CIFSSEC_MUST_NTLMV2) == CIFSSEC_MUST_NTLMV2)
544 server->secType = NTLMv2;
545 else if(secFlags & CIFSSEC_MAY_NTLM)
546 server->secType = NTLM;
547 else if(secFlags & CIFSSEC_MAY_NTLMV2)
548 server->secType = NTLMv2;
549 /* else krb5 ... any others ... */
551 /* one byte, so no need to convert this or EncryptionKeyLen from
553 server->maxReq = le16_to_cpu(pSMBr->MaxMpxCount);
554 /* probably no need to store and check maxvcs */
555 server->maxBuf = min(le32_to_cpu(pSMBr->MaxBufferSize),
556 (__u32) CIFSMaxBufSize + MAX_CIFS_HDR_SIZE);
557 server->maxRw = le32_to_cpu(pSMBr->MaxRawSize);
558 cFYI(0, ("Max buf = %d", ses->server->maxBuf));
559 GETU32(ses->server->sessid) = le32_to_cpu(pSMBr->SessionKey);
560 server->capabilities = le32_to_cpu(pSMBr->Capabilities);
561 server->timeAdj = le16_to_cpu(pSMBr->ServerTimeZone) * 60;
562 if (pSMBr->EncryptionKeyLength == CIFS_CRYPTO_KEY_SIZE) {
563 memcpy(server->cryptKey, pSMBr->u.EncryptionKey,
564 CIFS_CRYPTO_KEY_SIZE);
565 } else if ((pSMBr->hdr.Flags2 & SMBFLG2_EXT_SEC)
566 && (pSMBr->EncryptionKeyLength == 0)) {
567 /* decode security blob */
568 } else if (server->secMode & SECMODE_PW_ENCRYPT) {
569 rc = -EIO; /* no crypt key only if plain text pwd */
573 /* BB might be helpful to save off the domain of server here */
575 if ((pSMBr->hdr.Flags2 & SMBFLG2_EXT_SEC) &&
576 (server->capabilities & CAP_EXTENDED_SECURITY)) {
577 count = pSMBr->ByteCount;
580 else if (count == 16) {
581 server->secType = RawNTLMSSP;
582 if (server->socketUseCount.counter > 1) {
583 if (memcmp(server->server_GUID,
584 pSMBr->u.extended_response.
586 cFYI(1, ("server UID changed"));
587 memcpy(server->server_GUID,
588 pSMBr->u.extended_response.GUID,
592 memcpy(server->server_GUID,
593 pSMBr->u.extended_response.GUID, 16);
595 rc = decode_negTokenInit(pSMBr->u.extended_response.
600 /* BB Need to fill struct for sessetup here */
607 server->capabilities &= ~CAP_EXTENDED_SECURITY;
609 #ifdef CONFIG_CIFS_WEAK_PW_HASH
612 if(sign_CIFS_PDUs == FALSE) {
613 if(server->secMode & SECMODE_SIGN_REQUIRED)
614 cERROR(1,("Server requires "
615 "/proc/fs/cifs/PacketSigningEnabled to be on"));
617 ~(SECMODE_SIGN_ENABLED | SECMODE_SIGN_REQUIRED);
618 } else if(sign_CIFS_PDUs == 1) {
619 if((server->secMode & SECMODE_SIGN_REQUIRED) == 0)
621 ~(SECMODE_SIGN_ENABLED | SECMODE_SIGN_REQUIRED);
622 } else if(sign_CIFS_PDUs == 2) {
623 if((server->secMode &
624 (SECMODE_SIGN_ENABLED | SECMODE_SIGN_REQUIRED)) == 0) {
625 cERROR(1,("signing required but server lacks support"));
629 cifs_buf_release(pSMB);
631 cFYI(1,("negprot rc %d",rc));
636 CIFSSMBTDis(const int xid, struct cifsTconInfo *tcon)
638 struct smb_hdr *smb_buffer;
639 struct smb_hdr *smb_buffer_response; /* BB removeme BB */
643 cFYI(1, ("In tree disconnect"));
645 * If last user of the connection and
646 * connection alive - disconnect it
647 * If this is the last connection on the server session disconnect it
648 * (and inside session disconnect we should check if tcp socket needs
649 * to be freed and kernel thread woken up).
652 down(&tcon->tconSem);
656 atomic_dec(&tcon->useCount);
657 if (atomic_read(&tcon->useCount) > 0) {
662 /* No need to return error on this operation if tid invalidated and
663 closed on server already e.g. due to tcp session crashing */
664 if(tcon->tidStatus == CifsNeedReconnect) {
669 if((tcon->ses == NULL) || (tcon->ses->server == NULL)) {
673 rc = small_smb_init(SMB_COM_TREE_DISCONNECT, 0, tcon,
674 (void **)&smb_buffer);
679 smb_buffer_response = smb_buffer; /* BB removeme BB */
681 rc = SendReceive(xid, tcon->ses, smb_buffer, smb_buffer_response,
684 cFYI(1, ("Tree disconnect failed %d", rc));
687 cifs_small_buf_release(smb_buffer);
690 /* No need to return error on this operation if tid invalidated and
691 closed on server already e.g. due to tcp session crashing */
699 CIFSSMBLogoff(const int xid, struct cifsSesInfo *ses)
701 struct smb_hdr *smb_buffer_response;
702 LOGOFF_ANDX_REQ *pSMB;
706 cFYI(1, ("In SMBLogoff for session disconnect"));
712 atomic_dec(&ses->inUse);
713 if (atomic_read(&ses->inUse) > 0) {
717 rc = small_smb_init(SMB_COM_LOGOFF_ANDX, 2, NULL, (void **)&pSMB);
723 smb_buffer_response = (struct smb_hdr *)pSMB; /* BB removeme BB */
726 pSMB->hdr.Mid = GetNextMid(ses->server);
728 if(ses->server->secMode &
729 (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
730 pSMB->hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
733 pSMB->hdr.Uid = ses->Suid;
735 pSMB->AndXCommand = 0xFF;
736 rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB,
737 smb_buffer_response, &length, 0);
739 atomic_dec(&ses->server->socketUseCount);
740 if (atomic_read(&ses->server->socketUseCount) == 0) {
741 spin_lock(&GlobalMid_Lock);
742 ses->server->tcpStatus = CifsExiting;
743 spin_unlock(&GlobalMid_Lock);
748 cifs_small_buf_release(pSMB);
750 /* if session dead then we do not need to do ulogoff,
751 since server closed smb session, no sense reporting
759 CIFSSMBDelFile(const int xid, struct cifsTconInfo *tcon, const char *fileName,
760 const struct nls_table *nls_codepage, int remap)
762 DELETE_FILE_REQ *pSMB = NULL;
763 DELETE_FILE_RSP *pSMBr = NULL;
769 rc = smb_init(SMB_COM_DELETE, 1, tcon, (void **) &pSMB,
774 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
776 cifsConvertToUCS((__le16 *) pSMB->fileName, fileName,
777 PATH_MAX, nls_codepage, remap);
778 name_len++; /* trailing null */
780 } else { /* BB improve check for buffer overruns BB */
781 name_len = strnlen(fileName, PATH_MAX);
782 name_len++; /* trailing null */
783 strncpy(pSMB->fileName, fileName, name_len);
785 pSMB->SearchAttributes =
786 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM);
787 pSMB->BufferFormat = 0x04;
788 pSMB->hdr.smb_buf_length += name_len + 1;
789 pSMB->ByteCount = cpu_to_le16(name_len + 1);
790 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
791 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
792 cifs_stats_inc(&tcon->num_deletes);
794 cFYI(1, ("Error in RMFile = %d", rc));
797 cifs_buf_release(pSMB);
805 CIFSSMBRmDir(const int xid, struct cifsTconInfo *tcon, const char *dirName,
806 const struct nls_table *nls_codepage, int remap)
808 DELETE_DIRECTORY_REQ *pSMB = NULL;
809 DELETE_DIRECTORY_RSP *pSMBr = NULL;
814 cFYI(1, ("In CIFSSMBRmDir"));
816 rc = smb_init(SMB_COM_DELETE_DIRECTORY, 0, tcon, (void **) &pSMB,
821 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
822 name_len = cifsConvertToUCS((__le16 *) pSMB->DirName, dirName,
823 PATH_MAX, nls_codepage, remap);
824 name_len++; /* trailing null */
826 } else { /* BB improve check for buffer overruns BB */
827 name_len = strnlen(dirName, PATH_MAX);
828 name_len++; /* trailing null */
829 strncpy(pSMB->DirName, dirName, name_len);
832 pSMB->BufferFormat = 0x04;
833 pSMB->hdr.smb_buf_length += name_len + 1;
834 pSMB->ByteCount = cpu_to_le16(name_len + 1);
835 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
836 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
837 cifs_stats_inc(&tcon->num_rmdirs);
839 cFYI(1, ("Error in RMDir = %d", rc));
842 cifs_buf_release(pSMB);
849 CIFSSMBMkDir(const int xid, struct cifsTconInfo *tcon,
850 const char *name, const struct nls_table *nls_codepage, int remap)
853 CREATE_DIRECTORY_REQ *pSMB = NULL;
854 CREATE_DIRECTORY_RSP *pSMBr = NULL;
858 cFYI(1, ("In CIFSSMBMkDir"));
860 rc = smb_init(SMB_COM_CREATE_DIRECTORY, 0, tcon, (void **) &pSMB,
865 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
866 name_len = cifsConvertToUCS((__le16 *) pSMB->DirName, name,
867 PATH_MAX, nls_codepage, remap);
868 name_len++; /* trailing null */
870 } else { /* BB improve check for buffer overruns BB */
871 name_len = strnlen(name, PATH_MAX);
872 name_len++; /* trailing null */
873 strncpy(pSMB->DirName, name, name_len);
876 pSMB->BufferFormat = 0x04;
877 pSMB->hdr.smb_buf_length += name_len + 1;
878 pSMB->ByteCount = cpu_to_le16(name_len + 1);
879 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
880 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
881 cifs_stats_inc(&tcon->num_mkdirs);
883 cFYI(1, ("Error in Mkdir = %d", rc));
886 cifs_buf_release(pSMB);
892 static __u16 convert_disposition(int disposition)
896 switch (disposition) {
898 ofun = SMBOPEN_OCREATE | SMBOPEN_OTRUNC;
901 ofun = SMBOPEN_OAPPEND;
904 ofun = SMBOPEN_OCREATE;
907 ofun = SMBOPEN_OCREATE | SMBOPEN_OAPPEND;
910 ofun = SMBOPEN_OTRUNC;
912 case FILE_OVERWRITE_IF:
913 ofun = SMBOPEN_OCREATE | SMBOPEN_OTRUNC;
916 cFYI(1,("unknown disposition %d",disposition));
917 ofun = SMBOPEN_OAPPEND; /* regular open */
923 SMBLegacyOpen(const int xid, struct cifsTconInfo *tcon,
924 const char *fileName, const int openDisposition,
925 const int access_flags, const int create_options, __u16 * netfid,
926 int *pOplock, FILE_ALL_INFO * pfile_info,
927 const struct nls_table *nls_codepage, int remap)
930 OPENX_REQ *pSMB = NULL;
931 OPENX_RSP *pSMBr = NULL;
937 rc = smb_init(SMB_COM_OPEN_ANDX, 15, tcon, (void **) &pSMB,
942 pSMB->AndXCommand = 0xFF; /* none */
944 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
945 count = 1; /* account for one byte pad to word boundary */
947 cifsConvertToUCS((__le16 *) (pSMB->fileName + 1),
948 fileName, PATH_MAX, nls_codepage, remap);
949 name_len++; /* trailing null */
951 } else { /* BB improve check for buffer overruns BB */
952 count = 0; /* no pad */
953 name_len = strnlen(fileName, PATH_MAX);
954 name_len++; /* trailing null */
955 strncpy(pSMB->fileName, fileName, name_len);
957 if (*pOplock & REQ_OPLOCK)
958 pSMB->OpenFlags = cpu_to_le16(REQ_OPLOCK);
959 else if (*pOplock & REQ_BATCHOPLOCK) {
960 pSMB->OpenFlags = cpu_to_le16(REQ_BATCHOPLOCK);
962 pSMB->OpenFlags |= cpu_to_le16(REQ_MORE_INFO);
963 /* BB fixme add conversion for access_flags to bits 0 - 2 of mode */
969 pSMB->Mode = cpu_to_le16(2);
970 pSMB->Mode |= cpu_to_le16(0x40); /* deny none */
971 /* set file as system file if special file such
972 as fifo and server expecting SFU style and
973 no Unix extensions */
975 if(create_options & CREATE_OPTION_SPECIAL)
976 pSMB->FileAttributes = cpu_to_le16(ATTR_SYSTEM);
978 pSMB->FileAttributes = cpu_to_le16(0/*ATTR_NORMAL*/); /* BB FIXME */
980 /* if ((omode & S_IWUGO) == 0)
981 pSMB->FileAttributes |= cpu_to_le32(ATTR_READONLY);*/
982 /* Above line causes problems due to vfs splitting create into two
983 pieces - need to set mode after file created not while it is
987 /* pSMB->CreateOptions = cpu_to_le32(create_options & CREATE_OPTIONS_MASK); */
988 /* BB FIXME END BB */
990 pSMB->Sattr = cpu_to_le16(ATTR_HIDDEN | ATTR_SYSTEM | ATTR_DIRECTORY);
991 pSMB->OpenFunction = cpu_to_le16(convert_disposition(openDisposition));
993 pSMB->hdr.smb_buf_length += count;
995 pSMB->ByteCount = cpu_to_le16(count);
996 /* long_op set to 1 to allow for oplock break timeouts */
997 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
998 (struct smb_hdr *) pSMBr, &bytes_returned, 1);
999 cifs_stats_inc(&tcon->num_opens);
1001 cFYI(1, ("Error in Open = %d", rc));
1003 /* BB verify if wct == 15 */
1005 /* *pOplock = pSMBr->OplockLevel; */ /* BB take from action field BB */
1007 *netfid = pSMBr->Fid; /* cifs fid stays in le */
1008 /* Let caller know file was created so we can set the mode. */
1009 /* Do we care about the CreateAction in any other cases? */
1011 /* if(cpu_to_le32(FILE_CREATE) == pSMBr->CreateAction)
1012 *pOplock |= CIFS_CREATE_ACTION; */
1016 pfile_info->CreationTime = 0; /* BB convert CreateTime*/
1017 pfile_info->LastAccessTime = 0; /* BB fixme */
1018 pfile_info->LastWriteTime = 0; /* BB fixme */
1019 pfile_info->ChangeTime = 0; /* BB fixme */
1020 pfile_info->Attributes =
1021 cpu_to_le32(le16_to_cpu(pSMBr->FileAttributes));
1022 /* the file_info buf is endian converted by caller */
1023 pfile_info->AllocationSize =
1024 cpu_to_le64(le32_to_cpu(pSMBr->EndOfFile));
1025 pfile_info->EndOfFile = pfile_info->AllocationSize;
1026 pfile_info->NumberOfLinks = cpu_to_le32(1);
1030 cifs_buf_release(pSMB);
1037 CIFSSMBOpen(const int xid, struct cifsTconInfo *tcon,
1038 const char *fileName, const int openDisposition,
1039 const int access_flags, const int create_options, __u16 * netfid,
1040 int *pOplock, FILE_ALL_INFO * pfile_info,
1041 const struct nls_table *nls_codepage, int remap)
1044 OPEN_REQ *pSMB = NULL;
1045 OPEN_RSP *pSMBr = NULL;
1051 rc = smb_init(SMB_COM_NT_CREATE_ANDX, 24, tcon, (void **) &pSMB,
1056 pSMB->AndXCommand = 0xFF; /* none */
1058 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1059 count = 1; /* account for one byte pad to word boundary */
1061 cifsConvertToUCS((__le16 *) (pSMB->fileName + 1),
1062 fileName, PATH_MAX, nls_codepage, remap);
1063 name_len++; /* trailing null */
1065 pSMB->NameLength = cpu_to_le16(name_len);
1066 } else { /* BB improve check for buffer overruns BB */
1067 count = 0; /* no pad */
1068 name_len = strnlen(fileName, PATH_MAX);
1069 name_len++; /* trailing null */
1070 pSMB->NameLength = cpu_to_le16(name_len);
1071 strncpy(pSMB->fileName, fileName, name_len);
1073 if (*pOplock & REQ_OPLOCK)
1074 pSMB->OpenFlags = cpu_to_le32(REQ_OPLOCK);
1075 else if (*pOplock & REQ_BATCHOPLOCK) {
1076 pSMB->OpenFlags = cpu_to_le32(REQ_BATCHOPLOCK);
1078 pSMB->DesiredAccess = cpu_to_le32(access_flags);
1079 pSMB->AllocationSize = 0;
1080 /* set file as system file if special file such
1081 as fifo and server expecting SFU style and
1082 no Unix extensions */
1083 if(create_options & CREATE_OPTION_SPECIAL)
1084 pSMB->FileAttributes = cpu_to_le32(ATTR_SYSTEM);
1086 pSMB->FileAttributes = cpu_to_le32(ATTR_NORMAL);
1087 /* XP does not handle ATTR_POSIX_SEMANTICS */
1088 /* but it helps speed up case sensitive checks for other
1089 servers such as Samba */
1090 if (tcon->ses->capabilities & CAP_UNIX)
1091 pSMB->FileAttributes |= cpu_to_le32(ATTR_POSIX_SEMANTICS);
1093 /* if ((omode & S_IWUGO) == 0)
1094 pSMB->FileAttributes |= cpu_to_le32(ATTR_READONLY);*/
1095 /* Above line causes problems due to vfs splitting create into two
1096 pieces - need to set mode after file created not while it is
1098 pSMB->ShareAccess = cpu_to_le32(FILE_SHARE_ALL);
1099 pSMB->CreateDisposition = cpu_to_le32(openDisposition);
1100 pSMB->CreateOptions = cpu_to_le32(create_options & CREATE_OPTIONS_MASK);
1101 /* BB Expirement with various impersonation levels and verify */
1102 pSMB->ImpersonationLevel = cpu_to_le32(SECURITY_IMPERSONATION);
1103 pSMB->SecurityFlags =
1104 SECURITY_CONTEXT_TRACKING | SECURITY_EFFECTIVE_ONLY;
1107 pSMB->hdr.smb_buf_length += count;
1109 pSMB->ByteCount = cpu_to_le16(count);
1110 /* long_op set to 1 to allow for oplock break timeouts */
1111 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1112 (struct smb_hdr *) pSMBr, &bytes_returned, 1);
1113 cifs_stats_inc(&tcon->num_opens);
1115 cFYI(1, ("Error in Open = %d", rc));
1117 *pOplock = pSMBr->OplockLevel; /* 1 byte no need to le_to_cpu */
1118 *netfid = pSMBr->Fid; /* cifs fid stays in le */
1119 /* Let caller know file was created so we can set the mode. */
1120 /* Do we care about the CreateAction in any other cases? */
1121 if(cpu_to_le32(FILE_CREATE) == pSMBr->CreateAction)
1122 *pOplock |= CIFS_CREATE_ACTION;
1124 memcpy((char *)pfile_info,(char *)&pSMBr->CreationTime,
1125 36 /* CreationTime to Attributes */);
1126 /* the file_info buf is endian converted by caller */
1127 pfile_info->AllocationSize = pSMBr->AllocationSize;
1128 pfile_info->EndOfFile = pSMBr->EndOfFile;
1129 pfile_info->NumberOfLinks = cpu_to_le32(1);
1133 cifs_buf_release(pSMB);
1140 CIFSSMBRead(const int xid, struct cifsTconInfo *tcon,
1141 const int netfid, const unsigned int count,
1142 const __u64 lseek, unsigned int *nbytes, char **buf,
1146 READ_REQ *pSMB = NULL;
1147 READ_RSP *pSMBr = NULL;
1148 char *pReadData = NULL;
1150 int resp_buf_type = 0;
1153 cFYI(1,("Reading %d bytes on fid %d",count,netfid));
1154 if(tcon->ses->capabilities & CAP_LARGE_FILES)
1157 wct = 10; /* old style read */
1160 rc = small_smb_init(SMB_COM_READ_ANDX, wct, tcon, (void **) &pSMB);
1164 /* tcon and ses pointer are checked in smb_init */
1165 if (tcon->ses->server == NULL)
1166 return -ECONNABORTED;
1168 pSMB->AndXCommand = 0xFF; /* none */
1170 pSMB->OffsetLow = cpu_to_le32(lseek & 0xFFFFFFFF);
1172 pSMB->OffsetHigh = cpu_to_le32(lseek >> 32);
1173 else if((lseek >> 32) > 0) /* can not handle this big offset for old */
1176 pSMB->Remaining = 0;
1177 pSMB->MaxCount = cpu_to_le16(count & 0xFFFF);
1178 pSMB->MaxCountHigh = cpu_to_le32(count >> 16);
1180 pSMB->ByteCount = 0; /* no need to do le conversion since 0 */
1182 /* old style read */
1183 struct smb_com_readx_req * pSMBW =
1184 (struct smb_com_readx_req *)pSMB;
1185 pSMBW->ByteCount = 0;
1188 iov[0].iov_base = (char *)pSMB;
1189 iov[0].iov_len = pSMB->hdr.smb_buf_length + 4;
1190 rc = SendReceive2(xid, tcon->ses, iov,
1193 cifs_stats_inc(&tcon->num_reads);
1194 pSMBr = (READ_RSP *)iov[0].iov_base;
1196 cERROR(1, ("Send error in read = %d", rc));
1198 int data_length = le16_to_cpu(pSMBr->DataLengthHigh);
1199 data_length = data_length << 16;
1200 data_length += le16_to_cpu(pSMBr->DataLength);
1201 *nbytes = data_length;
1203 /*check that DataLength would not go beyond end of SMB */
1204 if ((data_length > CIFSMaxBufSize)
1205 || (data_length > count)) {
1206 cFYI(1,("bad length %d for count %d",data_length,count));
1210 pReadData = (char *) (&pSMBr->hdr.Protocol) +
1211 le16_to_cpu(pSMBr->DataOffset);
1212 /* if(rc = copy_to_user(buf, pReadData, data_length)) {
1213 cERROR(1,("Faulting on read rc = %d",rc));
1215 }*/ /* can not use copy_to_user when using page cache*/
1217 memcpy(*buf,pReadData,data_length);
1221 /* cifs_small_buf_release(pSMB); */ /* Freed earlier now in SendReceive2 */
1223 if(resp_buf_type == CIFS_SMALL_BUFFER)
1224 cifs_small_buf_release(iov[0].iov_base);
1225 else if(resp_buf_type == CIFS_LARGE_BUFFER)
1226 cifs_buf_release(iov[0].iov_base);
1227 } else if(resp_buf_type != CIFS_NO_BUFFER) {
1228 /* return buffer to caller to free */
1229 *buf = iov[0].iov_base;
1230 if(resp_buf_type == CIFS_SMALL_BUFFER)
1231 *pbuf_type = CIFS_SMALL_BUFFER;
1232 else if(resp_buf_type == CIFS_LARGE_BUFFER)
1233 *pbuf_type = CIFS_LARGE_BUFFER;
1234 } /* else no valid buffer on return - leave as null */
1236 /* Note: On -EAGAIN error only caller can retry on handle based calls
1237 since file handle passed in no longer valid */
1243 CIFSSMBWrite(const int xid, struct cifsTconInfo *tcon,
1244 const int netfid, const unsigned int count,
1245 const __u64 offset, unsigned int *nbytes, const char *buf,
1246 const char __user * ubuf, const int long_op)
1249 WRITE_REQ *pSMB = NULL;
1250 WRITE_RSP *pSMBr = NULL;
1251 int bytes_returned, wct;
1255 /* cFYI(1,("write at %lld %d bytes",offset,count));*/
1256 if(tcon->ses == NULL)
1257 return -ECONNABORTED;
1259 if(tcon->ses->capabilities & CAP_LARGE_FILES)
1264 rc = smb_init(SMB_COM_WRITE_ANDX, wct, tcon, (void **) &pSMB,
1268 /* tcon and ses pointer are checked in smb_init */
1269 if (tcon->ses->server == NULL)
1270 return -ECONNABORTED;
1272 pSMB->AndXCommand = 0xFF; /* none */
1274 pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF);
1276 pSMB->OffsetHigh = cpu_to_le32(offset >> 32);
1277 else if((offset >> 32) > 0) /* can not handle this big offset for old */
1280 pSMB->Reserved = 0xFFFFFFFF;
1281 pSMB->WriteMode = 0;
1282 pSMB->Remaining = 0;
1284 /* Can increase buffer size if buffer is big enough in some cases - ie we
1285 can send more if LARGE_WRITE_X capability returned by the server and if
1286 our buffer is big enough or if we convert to iovecs on socket writes
1287 and eliminate the copy to the CIFS buffer */
1288 if(tcon->ses->capabilities & CAP_LARGE_WRITE_X) {
1289 bytes_sent = min_t(const unsigned int, CIFSMaxBufSize, count);
1291 bytes_sent = (tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE)
1295 if (bytes_sent > count)
1298 cpu_to_le16(offsetof(struct smb_com_write_req,Data) - 4);
1300 memcpy(pSMB->Data,buf,bytes_sent);
1302 if(copy_from_user(pSMB->Data,ubuf,bytes_sent)) {
1303 cifs_buf_release(pSMB);
1306 } else if (count != 0) {
1308 cifs_buf_release(pSMB);
1310 } /* else setting file size with write of zero bytes */
1312 byte_count = bytes_sent + 1; /* pad */
1313 else /* wct == 12 */ {
1314 byte_count = bytes_sent + 5; /* bigger pad, smaller smb hdr */
1316 pSMB->DataLengthLow = cpu_to_le16(bytes_sent & 0xFFFF);
1317 pSMB->DataLengthHigh = cpu_to_le16(bytes_sent >> 16);
1318 pSMB->hdr.smb_buf_length += byte_count;
1321 pSMB->ByteCount = cpu_to_le16(byte_count);
1322 else { /* old style write has byte count 4 bytes earlier so 4 bytes pad */
1323 struct smb_com_writex_req * pSMBW =
1324 (struct smb_com_writex_req *)pSMB;
1325 pSMBW->ByteCount = cpu_to_le16(byte_count);
1328 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1329 (struct smb_hdr *) pSMBr, &bytes_returned, long_op);
1330 cifs_stats_inc(&tcon->num_writes);
1332 cFYI(1, ("Send error in write = %d", rc));
1335 *nbytes = le16_to_cpu(pSMBr->CountHigh);
1336 *nbytes = (*nbytes) << 16;
1337 *nbytes += le16_to_cpu(pSMBr->Count);
1340 cifs_buf_release(pSMB);
1342 /* Note: On -EAGAIN error only caller can retry on handle based calls
1343 since file handle passed in no longer valid */
1349 CIFSSMBWrite2(const int xid, struct cifsTconInfo *tcon,
1350 const int netfid, const unsigned int count,
1351 const __u64 offset, unsigned int *nbytes, struct kvec *iov,
1352 int n_vec, const int long_op)
1355 WRITE_REQ *pSMB = NULL;
1358 int resp_buf_type = 0;
1360 cFYI(1,("write2 at %lld %d bytes", (long long)offset, count));
1362 if(tcon->ses->capabilities & CAP_LARGE_FILES)
1366 rc = small_smb_init(SMB_COM_WRITE_ANDX, wct, tcon, (void **) &pSMB);
1369 /* tcon and ses pointer are checked in smb_init */
1370 if (tcon->ses->server == NULL)
1371 return -ECONNABORTED;
1373 pSMB->AndXCommand = 0xFF; /* none */
1375 pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF);
1377 pSMB->OffsetHigh = cpu_to_le32(offset >> 32);
1378 else if((offset >> 32) > 0) /* can not handle this big offset for old */
1380 pSMB->Reserved = 0xFFFFFFFF;
1381 pSMB->WriteMode = 0;
1382 pSMB->Remaining = 0;
1385 cpu_to_le16(offsetof(struct smb_com_write_req,Data) - 4);
1387 pSMB->DataLengthLow = cpu_to_le16(count & 0xFFFF);
1388 pSMB->DataLengthHigh = cpu_to_le16(count >> 16);
1389 smb_hdr_len = pSMB->hdr.smb_buf_length + 1; /* hdr + 1 byte pad */
1391 pSMB->hdr.smb_buf_length += count+1;
1392 else /* wct == 12 */
1393 pSMB->hdr.smb_buf_length += count+5; /* smb data starts later */
1395 pSMB->ByteCount = cpu_to_le16(count + 1);
1396 else /* wct == 12 */ /* bigger pad, smaller smb hdr, keep offset ok */ {
1397 struct smb_com_writex_req * pSMBW =
1398 (struct smb_com_writex_req *)pSMB;
1399 pSMBW->ByteCount = cpu_to_le16(count + 5);
1401 iov[0].iov_base = pSMB;
1403 iov[0].iov_len = smb_hdr_len + 4;
1404 else /* wct == 12 pad bigger by four bytes */
1405 iov[0].iov_len = smb_hdr_len + 8;
1408 rc = SendReceive2(xid, tcon->ses, iov, n_vec + 1, &resp_buf_type,
1410 cifs_stats_inc(&tcon->num_writes);
1412 cFYI(1, ("Send error Write2 = %d", rc));
1414 } else if(resp_buf_type == 0) {
1415 /* presumably this can not happen, but best to be safe */
1419 WRITE_RSP * pSMBr = (WRITE_RSP *)iov[0].iov_base;
1420 *nbytes = le16_to_cpu(pSMBr->CountHigh);
1421 *nbytes = (*nbytes) << 16;
1422 *nbytes += le16_to_cpu(pSMBr->Count);
1425 /* cifs_small_buf_release(pSMB); */ /* Freed earlier now in SendReceive2 */
1426 if(resp_buf_type == CIFS_SMALL_BUFFER)
1427 cifs_small_buf_release(iov[0].iov_base);
1428 else if(resp_buf_type == CIFS_LARGE_BUFFER)
1429 cifs_buf_release(iov[0].iov_base);
1431 /* Note: On -EAGAIN error only caller can retry on handle based calls
1432 since file handle passed in no longer valid */
1439 CIFSSMBLock(const int xid, struct cifsTconInfo *tcon,
1440 const __u16 smb_file_id, const __u64 len,
1441 const __u64 offset, const __u32 numUnlock,
1442 const __u32 numLock, const __u8 lockType, const int waitFlag)
1445 LOCK_REQ *pSMB = NULL;
1446 LOCK_RSP *pSMBr = NULL;
1451 cFYI(1, ("In CIFSSMBLock - timeout %d numLock %d",waitFlag,numLock));
1452 rc = small_smb_init(SMB_COM_LOCKING_ANDX, 8, tcon, (void **) &pSMB);
1457 pSMBr = (LOCK_RSP *)pSMB; /* BB removeme BB */
1459 if(lockType == LOCKING_ANDX_OPLOCK_RELEASE) {
1460 timeout = -1; /* no response expected */
1462 } else if (waitFlag == TRUE) {
1463 timeout = 3; /* blocking operation, no timeout */
1464 pSMB->Timeout = cpu_to_le32(-1);/* blocking - do not time out */
1469 pSMB->NumberOfLocks = cpu_to_le16(numLock);
1470 pSMB->NumberOfUnlocks = cpu_to_le16(numUnlock);
1471 pSMB->LockType = lockType;
1472 pSMB->AndXCommand = 0xFF; /* none */
1473 pSMB->Fid = smb_file_id; /* netfid stays le */
1475 if((numLock != 0) || (numUnlock != 0)) {
1476 pSMB->Locks[0].Pid = cpu_to_le16(current->tgid);
1477 /* BB where to store pid high? */
1478 pSMB->Locks[0].LengthLow = cpu_to_le32((u32)len);
1479 pSMB->Locks[0].LengthHigh = cpu_to_le32((u32)(len>>32));
1480 pSMB->Locks[0].OffsetLow = cpu_to_le32((u32)offset);
1481 pSMB->Locks[0].OffsetHigh = cpu_to_le32((u32)(offset>>32));
1482 count = sizeof(LOCKING_ANDX_RANGE);
1487 pSMB->hdr.smb_buf_length += count;
1488 pSMB->ByteCount = cpu_to_le16(count);
1491 rc = SendReceiveBlockingLock(xid, tcon, (struct smb_hdr *) pSMB,
1492 (struct smb_hdr *) pSMBr, &bytes_returned);
1494 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1495 (struct smb_hdr *) pSMBr, &bytes_returned, timeout);
1497 cifs_stats_inc(&tcon->num_locks);
1499 cFYI(1, ("Send error in Lock = %d", rc));
1501 cifs_small_buf_release(pSMB);
1503 /* Note: On -EAGAIN error only caller can retry on handle based calls
1504 since file handle passed in no longer valid */
1509 CIFSSMBPosixLock(const int xid, struct cifsTconInfo *tcon,
1510 const __u16 smb_file_id, const int get_flag, const __u64 len,
1511 struct file_lock *pLockData, const __u16 lock_type,
1514 struct smb_com_transaction2_sfi_req *pSMB = NULL;
1515 struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
1517 struct cifs_posix_lock *parm_data;
1520 int bytes_returned = 0;
1521 __u16 params, param_offset, offset, byte_count, count;
1523 cFYI(1, ("Posix Lock"));
1525 if(pLockData == NULL)
1528 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
1533 pSMBr = (struct smb_com_transaction2_sfi_rsp *)pSMB;
1536 pSMB->MaxSetupCount = 0;
1539 pSMB->Reserved2 = 0;
1540 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
1541 offset = param_offset + params;
1543 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
1545 count = sizeof(struct cifs_posix_lock);
1546 pSMB->MaxParameterCount = cpu_to_le16(2);
1547 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB PDU from sess */
1548 pSMB->SetupCount = 1;
1549 pSMB->Reserved3 = 0;
1551 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION);
1553 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
1554 byte_count = 3 /* pad */ + params + count;
1555 pSMB->DataCount = cpu_to_le16(count);
1556 pSMB->ParameterCount = cpu_to_le16(params);
1557 pSMB->TotalDataCount = pSMB->DataCount;
1558 pSMB->TotalParameterCount = pSMB->ParameterCount;
1559 pSMB->ParameterOffset = cpu_to_le16(param_offset);
1560 parm_data = (struct cifs_posix_lock *)
1561 (((char *) &pSMB->hdr.Protocol) + offset);
1563 parm_data->lock_type = cpu_to_le16(lock_type);
1565 timeout = 3; /* blocking operation, no timeout */
1566 parm_data->lock_flags = cpu_to_le16(1);
1567 pSMB->Timeout = cpu_to_le32(-1);
1571 parm_data->pid = cpu_to_le32(current->tgid);
1572 parm_data->start = cpu_to_le64(pLockData->fl_start);
1573 parm_data->length = cpu_to_le64(len); /* normalize negative numbers */
1575 pSMB->DataOffset = cpu_to_le16(offset);
1576 pSMB->Fid = smb_file_id;
1577 pSMB->InformationLevel = cpu_to_le16(SMB_SET_POSIX_LOCK);
1578 pSMB->Reserved4 = 0;
1579 pSMB->hdr.smb_buf_length += byte_count;
1580 pSMB->ByteCount = cpu_to_le16(byte_count);
1582 rc = SendReceiveBlockingLock(xid, tcon, (struct smb_hdr *) pSMB,
1583 (struct smb_hdr *) pSMBr, &bytes_returned);
1585 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1586 (struct smb_hdr *) pSMBr, &bytes_returned, timeout);
1590 cFYI(1, ("Send error in Posix Lock = %d", rc));
1591 } else if (get_flag) {
1592 /* lock structure can be returned on get */
1595 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
1597 if (rc || (pSMBr->ByteCount < sizeof(struct cifs_posix_lock))) {
1598 rc = -EIO; /* bad smb */
1601 if(pLockData == NULL) {
1605 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
1606 data_count = le16_to_cpu(pSMBr->t2.DataCount);
1607 if(data_count < sizeof(struct cifs_posix_lock)) {
1611 parm_data = (struct cifs_posix_lock *)
1612 ((char *)&pSMBr->hdr.Protocol + data_offset);
1613 if(parm_data->lock_type == cpu_to_le16(CIFS_UNLCK))
1614 pLockData->fl_type = F_UNLCK;
1619 cifs_small_buf_release(pSMB);
1621 /* Note: On -EAGAIN error only caller can retry on handle based calls
1622 since file handle passed in no longer valid */
1629 CIFSSMBClose(const int xid, struct cifsTconInfo *tcon, int smb_file_id)
1632 CLOSE_REQ *pSMB = NULL;
1633 CLOSE_RSP *pSMBr = NULL;
1635 cFYI(1, ("In CIFSSMBClose"));
1637 /* do not retry on dead session on close */
1638 rc = small_smb_init(SMB_COM_CLOSE, 3, tcon, (void **) &pSMB);
1644 pSMBr = (CLOSE_RSP *)pSMB; /* BB removeme BB */
1646 pSMB->FileID = (__u16) smb_file_id;
1647 pSMB->LastWriteTime = 0;
1648 pSMB->ByteCount = 0;
1649 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1650 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1651 cifs_stats_inc(&tcon->num_closes);
1654 /* EINTR is expected when user ctl-c to kill app */
1655 cERROR(1, ("Send error in Close = %d", rc));
1659 cifs_small_buf_release(pSMB);
1661 /* Since session is dead, file will be closed on server already */
1669 CIFSSMBRename(const int xid, struct cifsTconInfo *tcon,
1670 const char *fromName, const char *toName,
1671 const struct nls_table *nls_codepage, int remap)
1674 RENAME_REQ *pSMB = NULL;
1675 RENAME_RSP *pSMBr = NULL;
1677 int name_len, name_len2;
1680 cFYI(1, ("In CIFSSMBRename"));
1682 rc = smb_init(SMB_COM_RENAME, 1, tcon, (void **) &pSMB,
1687 pSMB->BufferFormat = 0x04;
1688 pSMB->SearchAttributes =
1689 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
1692 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1694 cifsConvertToUCS((__le16 *) pSMB->OldFileName, fromName,
1695 PATH_MAX, nls_codepage, remap);
1696 name_len++; /* trailing null */
1698 pSMB->OldFileName[name_len] = 0x04; /* pad */
1699 /* protocol requires ASCII signature byte on Unicode string */
1700 pSMB->OldFileName[name_len + 1] = 0x00;
1702 cifsConvertToUCS((__le16 *) &pSMB->OldFileName[name_len + 2],
1703 toName, PATH_MAX, nls_codepage, remap);
1704 name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
1705 name_len2 *= 2; /* convert to bytes */
1706 } else { /* BB improve the check for buffer overruns BB */
1707 name_len = strnlen(fromName, PATH_MAX);
1708 name_len++; /* trailing null */
1709 strncpy(pSMB->OldFileName, fromName, name_len);
1710 name_len2 = strnlen(toName, PATH_MAX);
1711 name_len2++; /* trailing null */
1712 pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */
1713 strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2);
1714 name_len2++; /* trailing null */
1715 name_len2++; /* signature byte */
1718 count = 1 /* 1st signature byte */ + name_len + name_len2;
1719 pSMB->hdr.smb_buf_length += count;
1720 pSMB->ByteCount = cpu_to_le16(count);
1722 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1723 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1724 cifs_stats_inc(&tcon->num_renames);
1726 cFYI(1, ("Send error in rename = %d", rc));
1729 cifs_buf_release(pSMB);
1737 int CIFSSMBRenameOpenFile(const int xid,struct cifsTconInfo *pTcon,
1738 int netfid, char * target_name,
1739 const struct nls_table * nls_codepage, int remap)
1741 struct smb_com_transaction2_sfi_req *pSMB = NULL;
1742 struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
1743 struct set_file_rename * rename_info;
1745 char dummy_string[30];
1747 int bytes_returned = 0;
1749 __u16 params, param_offset, offset, count, byte_count;
1751 cFYI(1, ("Rename to File by handle"));
1752 rc = smb_init(SMB_COM_TRANSACTION2, 15, pTcon, (void **) &pSMB,
1758 pSMB->MaxSetupCount = 0;
1762 pSMB->Reserved2 = 0;
1763 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
1764 offset = param_offset + params;
1766 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
1767 rename_info = (struct set_file_rename *) data_offset;
1768 pSMB->MaxParameterCount = cpu_to_le16(2);
1769 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB PDU from sess */
1770 pSMB->SetupCount = 1;
1771 pSMB->Reserved3 = 0;
1772 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
1773 byte_count = 3 /* pad */ + params;
1774 pSMB->ParameterCount = cpu_to_le16(params);
1775 pSMB->TotalParameterCount = pSMB->ParameterCount;
1776 pSMB->ParameterOffset = cpu_to_le16(param_offset);
1777 pSMB->DataOffset = cpu_to_le16(offset);
1778 /* construct random name ".cifs_tmp<inodenum><mid>" */
1779 rename_info->overwrite = cpu_to_le32(1);
1780 rename_info->root_fid = 0;
1781 /* unicode only call */
1782 if(target_name == NULL) {
1783 sprintf(dummy_string,"cifs%x",pSMB->hdr.Mid);
1784 len_of_str = cifsConvertToUCS((__le16 *)rename_info->target_name,
1785 dummy_string, 24, nls_codepage, remap);
1787 len_of_str = cifsConvertToUCS((__le16 *)rename_info->target_name,
1788 target_name, PATH_MAX, nls_codepage, remap);
1790 rename_info->target_name_len = cpu_to_le32(2 * len_of_str);
1791 count = 12 /* sizeof(struct set_file_rename) */ + (2 * len_of_str) + 2;
1792 byte_count += count;
1793 pSMB->DataCount = cpu_to_le16(count);
1794 pSMB->TotalDataCount = pSMB->DataCount;
1796 pSMB->InformationLevel =
1797 cpu_to_le16(SMB_SET_FILE_RENAME_INFORMATION);
1798 pSMB->Reserved4 = 0;
1799 pSMB->hdr.smb_buf_length += byte_count;
1800 pSMB->ByteCount = cpu_to_le16(byte_count);
1801 rc = SendReceive(xid, pTcon->ses, (struct smb_hdr *) pSMB,
1802 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1803 cifs_stats_inc(&pTcon->num_t2renames);
1805 cFYI(1,("Send error in Rename (by file handle) = %d", rc));
1808 cifs_buf_release(pSMB);
1810 /* Note: On -EAGAIN error only caller can retry on handle based calls
1811 since file handle passed in no longer valid */
1817 CIFSSMBCopy(const int xid, struct cifsTconInfo *tcon, const char * fromName,
1818 const __u16 target_tid, const char *toName, const int flags,
1819 const struct nls_table *nls_codepage, int remap)
1822 COPY_REQ *pSMB = NULL;
1823 COPY_RSP *pSMBr = NULL;
1825 int name_len, name_len2;
1828 cFYI(1, ("In CIFSSMBCopy"));
1830 rc = smb_init(SMB_COM_COPY, 1, tcon, (void **) &pSMB,
1835 pSMB->BufferFormat = 0x04;
1836 pSMB->Tid2 = target_tid;
1838 pSMB->Flags = cpu_to_le16(flags & COPY_TREE);
1840 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1841 name_len = cifsConvertToUCS((__le16 *) pSMB->OldFileName,
1842 fromName, PATH_MAX, nls_codepage,
1844 name_len++; /* trailing null */
1846 pSMB->OldFileName[name_len] = 0x04; /* pad */
1847 /* protocol requires ASCII signature byte on Unicode string */
1848 pSMB->OldFileName[name_len + 1] = 0x00;
1849 name_len2 = cifsConvertToUCS((__le16 *)&pSMB->OldFileName[name_len + 2],
1850 toName, PATH_MAX, nls_codepage, remap);
1851 name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
1852 name_len2 *= 2; /* convert to bytes */
1853 } else { /* BB improve the check for buffer overruns BB */
1854 name_len = strnlen(fromName, PATH_MAX);
1855 name_len++; /* trailing null */
1856 strncpy(pSMB->OldFileName, fromName, name_len);
1857 name_len2 = strnlen(toName, PATH_MAX);
1858 name_len2++; /* trailing null */
1859 pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */
1860 strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2);
1861 name_len2++; /* trailing null */
1862 name_len2++; /* signature byte */
1865 count = 1 /* 1st signature byte */ + name_len + name_len2;
1866 pSMB->hdr.smb_buf_length += count;
1867 pSMB->ByteCount = cpu_to_le16(count);
1869 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1870 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1872 cFYI(1, ("Send error in copy = %d with %d files copied",
1873 rc, le16_to_cpu(pSMBr->CopyCount)));
1876 cifs_buf_release(pSMB);
1885 CIFSUnixCreateSymLink(const int xid, struct cifsTconInfo *tcon,
1886 const char *fromName, const char *toName,
1887 const struct nls_table *nls_codepage)
1889 TRANSACTION2_SPI_REQ *pSMB = NULL;
1890 TRANSACTION2_SPI_RSP *pSMBr = NULL;
1893 int name_len_target;
1895 int bytes_returned = 0;
1896 __u16 params, param_offset, offset, byte_count;
1898 cFYI(1, ("In Symlink Unix style"));
1900 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
1905 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1907 cifs_strtoUCS((__le16 *) pSMB->FileName, fromName, PATH_MAX
1908 /* find define for this maxpathcomponent */
1910 name_len++; /* trailing null */
1913 } else { /* BB improve the check for buffer overruns BB */
1914 name_len = strnlen(fromName, PATH_MAX);
1915 name_len++; /* trailing null */
1916 strncpy(pSMB->FileName, fromName, name_len);
1918 params = 6 + name_len;
1919 pSMB->MaxSetupCount = 0;
1923 pSMB->Reserved2 = 0;
1924 param_offset = offsetof(struct smb_com_transaction2_spi_req,
1925 InformationLevel) - 4;
1926 offset = param_offset + params;
1928 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
1929 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1931 cifs_strtoUCS((__le16 *) data_offset, toName, PATH_MAX
1932 /* find define for this maxpathcomponent */
1934 name_len_target++; /* trailing null */
1935 name_len_target *= 2;
1936 } else { /* BB improve the check for buffer overruns BB */
1937 name_len_target = strnlen(toName, PATH_MAX);
1938 name_len_target++; /* trailing null */
1939 strncpy(data_offset, toName, name_len_target);
1942 pSMB->MaxParameterCount = cpu_to_le16(2);
1943 /* BB find exact max on data count below from sess */
1944 pSMB->MaxDataCount = cpu_to_le16(1000);
1945 pSMB->SetupCount = 1;
1946 pSMB->Reserved3 = 0;
1947 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
1948 byte_count = 3 /* pad */ + params + name_len_target;
1949 pSMB->DataCount = cpu_to_le16(name_len_target);
1950 pSMB->ParameterCount = cpu_to_le16(params);
1951 pSMB->TotalDataCount = pSMB->DataCount;
1952 pSMB->TotalParameterCount = pSMB->ParameterCount;
1953 pSMB->ParameterOffset = cpu_to_le16(param_offset);
1954 pSMB->DataOffset = cpu_to_le16(offset);
1955 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_LINK);
1956 pSMB->Reserved4 = 0;
1957 pSMB->hdr.smb_buf_length += byte_count;
1958 pSMB->ByteCount = cpu_to_le16(byte_count);
1959 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1960 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1961 cifs_stats_inc(&tcon->num_symlinks);
1964 ("Send error in SetPathInfo (create symlink) = %d",
1969 cifs_buf_release(pSMB);
1972 goto createSymLinkRetry;
1978 CIFSUnixCreateHardLink(const int xid, struct cifsTconInfo *tcon,
1979 const char *fromName, const char *toName,
1980 const struct nls_table *nls_codepage, int remap)
1982 TRANSACTION2_SPI_REQ *pSMB = NULL;
1983 TRANSACTION2_SPI_RSP *pSMBr = NULL;
1986 int name_len_target;
1988 int bytes_returned = 0;
1989 __u16 params, param_offset, offset, byte_count;
1991 cFYI(1, ("In Create Hard link Unix style"));
1992 createHardLinkRetry:
1993 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
1998 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1999 name_len = cifsConvertToUCS((__le16 *) pSMB->FileName, toName,
2000 PATH_MAX, nls_codepage, remap);
2001 name_len++; /* trailing null */
2004 } else { /* BB improve the check for buffer overruns BB */
2005 name_len = strnlen(toName, PATH_MAX);
2006 name_len++; /* trailing null */
2007 strncpy(pSMB->FileName, toName, name_len);
2009 params = 6 + name_len;
2010 pSMB->MaxSetupCount = 0;
2014 pSMB->Reserved2 = 0;
2015 param_offset = offsetof(struct smb_com_transaction2_spi_req,
2016 InformationLevel) - 4;
2017 offset = param_offset + params;
2019 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
2020 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2022 cifsConvertToUCS((__le16 *) data_offset, fromName, PATH_MAX,
2023 nls_codepage, remap);
2024 name_len_target++; /* trailing null */
2025 name_len_target *= 2;
2026 } else { /* BB improve the check for buffer overruns BB */
2027 name_len_target = strnlen(fromName, PATH_MAX);
2028 name_len_target++; /* trailing null */
2029 strncpy(data_offset, fromName, name_len_target);
2032 pSMB->MaxParameterCount = cpu_to_le16(2);
2033 /* BB find exact max on data count below from sess*/
2034 pSMB->MaxDataCount = cpu_to_le16(1000);
2035 pSMB->SetupCount = 1;
2036 pSMB->Reserved3 = 0;
2037 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
2038 byte_count = 3 /* pad */ + params + name_len_target;
2039 pSMB->ParameterCount = cpu_to_le16(params);
2040 pSMB->TotalParameterCount = pSMB->ParameterCount;
2041 pSMB->DataCount = cpu_to_le16(name_len_target);
2042 pSMB->TotalDataCount = pSMB->DataCount;
2043 pSMB->ParameterOffset = cpu_to_le16(param_offset);
2044 pSMB->DataOffset = cpu_to_le16(offset);
2045 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_HLINK);
2046 pSMB->Reserved4 = 0;
2047 pSMB->hdr.smb_buf_length += byte_count;
2048 pSMB->ByteCount = cpu_to_le16(byte_count);
2049 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2050 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2051 cifs_stats_inc(&tcon->num_hardlinks);
2053 cFYI(1, ("Send error in SetPathInfo (hard link) = %d", rc));
2056 cifs_buf_release(pSMB);
2058 goto createHardLinkRetry;
2064 CIFSCreateHardLink(const int xid, struct cifsTconInfo *tcon,
2065 const char *fromName, const char *toName,
2066 const struct nls_table *nls_codepage, int remap)
2069 NT_RENAME_REQ *pSMB = NULL;
2070 RENAME_RSP *pSMBr = NULL;
2072 int name_len, name_len2;
2075 cFYI(1, ("In CIFSCreateHardLink"));
2076 winCreateHardLinkRetry:
2078 rc = smb_init(SMB_COM_NT_RENAME, 4, tcon, (void **) &pSMB,
2083 pSMB->SearchAttributes =
2084 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
2086 pSMB->Flags = cpu_to_le16(CREATE_HARD_LINK);
2087 pSMB->ClusterCount = 0;
2089 pSMB->BufferFormat = 0x04;
2091 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2093 cifsConvertToUCS((__le16 *) pSMB->OldFileName, fromName,
2094 PATH_MAX, nls_codepage, remap);
2095 name_len++; /* trailing null */
2097 pSMB->OldFileName[name_len] = 0; /* pad */
2098 pSMB->OldFileName[name_len + 1] = 0x04;
2100 cifsConvertToUCS((__le16 *)&pSMB->OldFileName[name_len + 2],
2101 toName, PATH_MAX, nls_codepage, remap);
2102 name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
2103 name_len2 *= 2; /* convert to bytes */
2104 } else { /* BB improve the check for buffer overruns BB */
2105 name_len = strnlen(fromName, PATH_MAX);
2106 name_len++; /* trailing null */
2107 strncpy(pSMB->OldFileName, fromName, name_len);
2108 name_len2 = strnlen(toName, PATH_MAX);
2109 name_len2++; /* trailing null */
2110 pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */
2111 strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2);
2112 name_len2++; /* trailing null */
2113 name_len2++; /* signature byte */
2116 count = 1 /* string type byte */ + name_len + name_len2;
2117 pSMB->hdr.smb_buf_length += count;
2118 pSMB->ByteCount = cpu_to_le16(count);
2120 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2121 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2122 cifs_stats_inc(&tcon->num_hardlinks);
2124 cFYI(1, ("Send error in hard link (NT rename) = %d", rc));
2126 cifs_buf_release(pSMB);
2128 goto winCreateHardLinkRetry;
2134 CIFSSMBUnixQuerySymLink(const int xid, struct cifsTconInfo *tcon,
2135 const unsigned char *searchName,
2136 char *symlinkinfo, const int buflen,
2137 const struct nls_table *nls_codepage)
2139 /* SMB_QUERY_FILE_UNIX_LINK */
2140 TRANSACTION2_QPI_REQ *pSMB = NULL;
2141 TRANSACTION2_QPI_RSP *pSMBr = NULL;
2145 __u16 params, byte_count;
2147 cFYI(1, ("In QPathSymLinkInfo (Unix) for path %s", searchName));
2150 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2155 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2157 cifs_strtoUCS((__le16 *) pSMB->FileName, searchName, PATH_MAX
2158 /* find define for this maxpathcomponent */
2160 name_len++; /* trailing null */
2162 } else { /* BB improve the check for buffer overruns BB */
2163 name_len = strnlen(searchName, PATH_MAX);
2164 name_len++; /* trailing null */
2165 strncpy(pSMB->FileName, searchName, name_len);
2168 params = 2 /* level */ + 4 /* rsrvd */ + name_len /* incl null */ ;
2169 pSMB->TotalDataCount = 0;
2170 pSMB->MaxParameterCount = cpu_to_le16(2);
2171 /* BB find exact max data count below from sess structure BB */
2172 pSMB->MaxDataCount = cpu_to_le16(4000);
2173 pSMB->MaxSetupCount = 0;
2177 pSMB->Reserved2 = 0;
2178 pSMB->ParameterOffset = cpu_to_le16(offsetof(
2179 struct smb_com_transaction2_qpi_req ,InformationLevel) - 4);
2180 pSMB->DataCount = 0;
2181 pSMB->DataOffset = 0;
2182 pSMB->SetupCount = 1;
2183 pSMB->Reserved3 = 0;
2184 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
2185 byte_count = params + 1 /* pad */ ;
2186 pSMB->TotalParameterCount = cpu_to_le16(params);
2187 pSMB->ParameterCount = pSMB->TotalParameterCount;
2188 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_LINK);
2189 pSMB->Reserved4 = 0;
2190 pSMB->hdr.smb_buf_length += byte_count;
2191 pSMB->ByteCount = cpu_to_le16(byte_count);
2193 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2194 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2196 cFYI(1, ("Send error in QuerySymLinkInfo = %d", rc));
2198 /* decode response */
2200 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
2201 if (rc || (pSMBr->ByteCount < 2))
2202 /* BB also check enough total bytes returned */
2203 rc = -EIO; /* bad smb */
2205 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
2206 __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
2208 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
2209 name_len = UniStrnlen((wchar_t *) ((char *)
2210 &pSMBr->hdr.Protocol +data_offset),
2211 min_t(const int, buflen,count) / 2);
2212 /* BB FIXME investigate remapping reserved chars here */
2213 cifs_strfromUCS_le(symlinkinfo,
2214 (__le16 *) ((char *)&pSMBr->hdr.Protocol +
2216 name_len, nls_codepage);
2218 strncpy(symlinkinfo,
2219 (char *) &pSMBr->hdr.Protocol +
2221 min_t(const int, buflen, count));
2223 symlinkinfo[buflen] = 0;
2224 /* just in case so calling code does not go off the end of buffer */
2227 cifs_buf_release(pSMB);
2229 goto querySymLinkRetry;
2233 /* Initialize NT TRANSACT SMB into small smb request buffer.
2234 This assumes that all NT TRANSACTS that we init here have
2235 total parm and data under about 400 bytes (to fit in small cifs
2236 buffer size), which is the case so far, it easily fits. NB:
2237 Setup words themselves and ByteCount
2238 MaxSetupCount (size of returned setup area) and
2239 MaxParameterCount (returned parms size) must be set by caller */
2241 smb_init_ntransact(const __u16 sub_command, const int setup_count,
2242 const int parm_len, struct cifsTconInfo *tcon,
2247 struct smb_com_ntransact_req * pSMB;
2249 rc = small_smb_init(SMB_COM_NT_TRANSACT, 19 + setup_count, tcon,
2253 *ret_buf = (void *)pSMB;
2255 pSMB->TotalParameterCount = cpu_to_le32(parm_len);
2256 pSMB->TotalDataCount = 0;
2257 pSMB->MaxDataCount = cpu_to_le32((tcon->ses->server->maxBuf -
2258 MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
2259 pSMB->ParameterCount = pSMB->TotalParameterCount;
2260 pSMB->DataCount = pSMB->TotalDataCount;
2261 temp_offset = offsetof(struct smb_com_ntransact_req, Parms) +
2262 (setup_count * 2) - 4 /* for rfc1001 length itself */;
2263 pSMB->ParameterOffset = cpu_to_le32(temp_offset);
2264 pSMB->DataOffset = cpu_to_le32(temp_offset + parm_len);
2265 pSMB->SetupCount = setup_count; /* no need to le convert byte fields */
2266 pSMB->SubCommand = cpu_to_le16(sub_command);
2271 validate_ntransact(char * buf, char ** ppparm, char ** ppdata,
2272 int * pdatalen, int * pparmlen)
2275 __u32 data_count, data_offset, parm_count, parm_offset;
2276 struct smb_com_ntransact_rsp * pSMBr;
2281 pSMBr = (struct smb_com_ntransact_rsp *)buf;
2283 /* ByteCount was converted from little endian in SendReceive */
2284 end_of_smb = 2 /* sizeof byte count */ + pSMBr->ByteCount +
2285 (char *)&pSMBr->ByteCount;
2288 data_offset = le32_to_cpu(pSMBr->DataOffset);
2289 data_count = le32_to_cpu(pSMBr->DataCount);
2290 parm_offset = le32_to_cpu(pSMBr->ParameterOffset);
2291 parm_count = le32_to_cpu(pSMBr->ParameterCount);
2293 *ppparm = (char *)&pSMBr->hdr.Protocol + parm_offset;
2294 *ppdata = (char *)&pSMBr->hdr.Protocol + data_offset;
2296 /* should we also check that parm and data areas do not overlap? */
2297 if(*ppparm > end_of_smb) {
2298 cFYI(1,("parms start after end of smb"));
2300 } else if(parm_count + *ppparm > end_of_smb) {
2301 cFYI(1,("parm end after end of smb"));
2303 } else if(*ppdata > end_of_smb) {
2304 cFYI(1,("data starts after end of smb"));
2306 } else if(data_count + *ppdata > end_of_smb) {
2307 cFYI(1,("data %p + count %d (%p) ends after end of smb %p start %p",
2308 *ppdata, data_count, (data_count + *ppdata), end_of_smb, pSMBr)); /* BB FIXME */
2310 } else if(parm_count + data_count > pSMBr->ByteCount) {
2311 cFYI(1,("parm count and data count larger than SMB"));
2318 CIFSSMBQueryReparseLinkInfo(const int xid, struct cifsTconInfo *tcon,
2319 const unsigned char *searchName,
2320 char *symlinkinfo, const int buflen,__u16 fid,
2321 const struct nls_table *nls_codepage)
2326 struct smb_com_transaction_ioctl_req * pSMB;
2327 struct smb_com_transaction_ioctl_rsp * pSMBr;
2329 cFYI(1, ("In Windows reparse style QueryLink for path %s", searchName));
2330 rc = smb_init(SMB_COM_NT_TRANSACT, 23, tcon, (void **) &pSMB,
2335 pSMB->TotalParameterCount = 0 ;
2336 pSMB->TotalDataCount = 0;
2337 pSMB->MaxParameterCount = cpu_to_le32(2);
2338 /* BB find exact data count max from sess structure BB */
2339 pSMB->MaxDataCount = cpu_to_le32((tcon->ses->server->maxBuf -
2340 MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
2341 pSMB->MaxSetupCount = 4;
2343 pSMB->ParameterOffset = 0;
2344 pSMB->DataCount = 0;
2345 pSMB->DataOffset = 0;
2346 pSMB->SetupCount = 4;
2347 pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_IOCTL);
2348 pSMB->ParameterCount = pSMB->TotalParameterCount;
2349 pSMB->FunctionCode = cpu_to_le32(FSCTL_GET_REPARSE_POINT);
2350 pSMB->IsFsctl = 1; /* FSCTL */
2351 pSMB->IsRootFlag = 0;
2352 pSMB->Fid = fid; /* file handle always le */
2353 pSMB->ByteCount = 0;
2355 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2356 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2358 cFYI(1, ("Send error in QueryReparseLinkInfo = %d", rc));
2359 } else { /* decode response */
2360 __u32 data_offset = le32_to_cpu(pSMBr->DataOffset);
2361 __u32 data_count = le32_to_cpu(pSMBr->DataCount);
2362 if ((pSMBr->ByteCount < 2) || (data_offset > 512))
2363 /* BB also check enough total bytes returned */
2364 rc = -EIO; /* bad smb */
2366 if(data_count && (data_count < 2048)) {
2367 char * end_of_smb = 2 /* sizeof byte count */ +
2369 (char *)&pSMBr->ByteCount;
2371 struct reparse_data * reparse_buf = (struct reparse_data *)
2372 ((char *)&pSMBr->hdr.Protocol + data_offset);
2373 if((char*)reparse_buf >= end_of_smb) {
2377 if((reparse_buf->LinkNamesBuf +
2378 reparse_buf->TargetNameOffset +
2379 reparse_buf->TargetNameLen) >
2381 cFYI(1,("reparse buf extended beyond SMB"));
2386 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
2387 name_len = UniStrnlen((wchar_t *)
2388 (reparse_buf->LinkNamesBuf +
2389 reparse_buf->TargetNameOffset),
2390 min(buflen/2, reparse_buf->TargetNameLen / 2));
2391 cifs_strfromUCS_le(symlinkinfo,
2392 (__le16 *) (reparse_buf->LinkNamesBuf +
2393 reparse_buf->TargetNameOffset),
2394 name_len, nls_codepage);
2395 } else { /* ASCII names */
2396 strncpy(symlinkinfo,reparse_buf->LinkNamesBuf +
2397 reparse_buf->TargetNameOffset,
2398 min_t(const int, buflen, reparse_buf->TargetNameLen));
2402 cFYI(1,("Invalid return data count on get reparse info ioctl"));
2404 symlinkinfo[buflen] = 0; /* just in case so the caller
2405 does not go off the end of the buffer */
2406 cFYI(1,("readlink result - %s",symlinkinfo));
2410 cifs_buf_release(pSMB);
2412 /* Note: On -EAGAIN error only caller can retry on handle based calls
2413 since file handle passed in no longer valid */
2418 #ifdef CONFIG_CIFS_POSIX
2420 /*Convert an Access Control Entry from wire format to local POSIX xattr format*/
2421 static void cifs_convert_ace(posix_acl_xattr_entry * ace, struct cifs_posix_ace * cifs_ace)
2423 /* u8 cifs fields do not need le conversion */
2424 ace->e_perm = cpu_to_le16(cifs_ace->cifs_e_perm);
2425 ace->e_tag = cpu_to_le16(cifs_ace->cifs_e_tag);
2426 ace->e_id = cpu_to_le32(le64_to_cpu(cifs_ace->cifs_uid));
2427 /* cFYI(1,("perm %d tag %d id %d",ace->e_perm,ace->e_tag,ace->e_id)); */
2432 /* Convert ACL from CIFS POSIX wire format to local Linux POSIX ACL xattr */
2433 static int cifs_copy_posix_acl(char * trgt,char * src, const int buflen,
2434 const int acl_type,const int size_of_data_area)
2439 struct cifs_posix_ace * pACE;
2440 struct cifs_posix_acl * cifs_acl = (struct cifs_posix_acl *)src;
2441 posix_acl_xattr_header * local_acl = (posix_acl_xattr_header *)trgt;
2443 if (le16_to_cpu(cifs_acl->version) != CIFS_ACL_VERSION)
2446 if(acl_type & ACL_TYPE_ACCESS) {
2447 count = le16_to_cpu(cifs_acl->access_entry_count);
2448 pACE = &cifs_acl->ace_array[0];
2449 size = sizeof(struct cifs_posix_acl);
2450 size += sizeof(struct cifs_posix_ace) * count;
2451 /* check if we would go beyond end of SMB */
2452 if(size_of_data_area < size) {
2453 cFYI(1,("bad CIFS POSIX ACL size %d vs. %d",size_of_data_area,size));
2456 } else if(acl_type & ACL_TYPE_DEFAULT) {
2457 count = le16_to_cpu(cifs_acl->access_entry_count);
2458 size = sizeof(struct cifs_posix_acl);
2459 size += sizeof(struct cifs_posix_ace) * count;
2460 /* skip past access ACEs to get to default ACEs */
2461 pACE = &cifs_acl->ace_array[count];
2462 count = le16_to_cpu(cifs_acl->default_entry_count);
2463 size += sizeof(struct cifs_posix_ace) * count;
2464 /* check if we would go beyond end of SMB */
2465 if(size_of_data_area < size)
2472 size = posix_acl_xattr_size(count);
2473 if((buflen == 0) || (local_acl == NULL)) {
2474 /* used to query ACL EA size */
2475 } else if(size > buflen) {
2477 } else /* buffer big enough */ {
2478 local_acl->a_version = cpu_to_le32(POSIX_ACL_XATTR_VERSION);
2479 for(i = 0;i < count ;i++) {
2480 cifs_convert_ace(&local_acl->a_entries[i],pACE);
2487 static __u16 convert_ace_to_cifs_ace(struct cifs_posix_ace * cifs_ace,
2488 const posix_acl_xattr_entry * local_ace)
2490 __u16 rc = 0; /* 0 = ACL converted ok */
2492 cifs_ace->cifs_e_perm = le16_to_cpu(local_ace->e_perm);
2493 cifs_ace->cifs_e_tag = le16_to_cpu(local_ace->e_tag);
2494 /* BB is there a better way to handle the large uid? */
2495 if(local_ace->e_id == cpu_to_le32(-1)) {
2496 /* Probably no need to le convert -1 on any arch but can not hurt */
2497 cifs_ace->cifs_uid = cpu_to_le64(-1);
2499 cifs_ace->cifs_uid = cpu_to_le64(le32_to_cpu(local_ace->e_id));
2500 /*cFYI(1,("perm %d tag %d id %d",ace->e_perm,ace->e_tag,ace->e_id));*/
2504 /* Convert ACL from local Linux POSIX xattr to CIFS POSIX ACL wire format */
2505 static __u16 ACL_to_cifs_posix(char * parm_data,const char * pACL,const int buflen,
2509 struct cifs_posix_acl * cifs_acl = (struct cifs_posix_acl *)parm_data;
2510 posix_acl_xattr_header * local_acl = (posix_acl_xattr_header *)pACL;
2514 if((buflen == 0) || (pACL == NULL) || (cifs_acl == NULL))
2517 count = posix_acl_xattr_count((size_t)buflen);
2518 cFYI(1,("setting acl with %d entries from buf of length %d and version of %d",
2519 count, buflen, le32_to_cpu(local_acl->a_version)));
2520 if(le32_to_cpu(local_acl->a_version) != 2) {
2521 cFYI(1,("unknown POSIX ACL version %d",
2522 le32_to_cpu(local_acl->a_version)));
2525 cifs_acl->version = cpu_to_le16(1);
2526 if(acl_type == ACL_TYPE_ACCESS)
2527 cifs_acl->access_entry_count = cpu_to_le16(count);
2528 else if(acl_type == ACL_TYPE_DEFAULT)
2529 cifs_acl->default_entry_count = cpu_to_le16(count);
2531 cFYI(1,("unknown ACL type %d",acl_type));
2534 for(i=0;i<count;i++) {
2535 rc = convert_ace_to_cifs_ace(&cifs_acl->ace_array[i],
2536 &local_acl->a_entries[i]);
2538 /* ACE not converted */
2543 rc = (__u16)(count * sizeof(struct cifs_posix_ace));
2544 rc += sizeof(struct cifs_posix_acl);
2545 /* BB add check to make sure ACL does not overflow SMB */
2551 CIFSSMBGetPosixACL(const int xid, struct cifsTconInfo *tcon,
2552 const unsigned char *searchName,
2553 char *acl_inf, const int buflen, const int acl_type,
2554 const struct nls_table *nls_codepage, int remap)
2556 /* SMB_QUERY_POSIX_ACL */
2557 TRANSACTION2_QPI_REQ *pSMB = NULL;
2558 TRANSACTION2_QPI_RSP *pSMBr = NULL;
2562 __u16 params, byte_count;
2564 cFYI(1, ("In GetPosixACL (Unix) for path %s", searchName));
2567 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2572 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2574 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
2575 PATH_MAX, nls_codepage, remap);
2576 name_len++; /* trailing null */
2578 pSMB->FileName[name_len] = 0;
2579 pSMB->FileName[name_len+1] = 0;
2580 } else { /* BB improve the check for buffer overruns BB */
2581 name_len = strnlen(searchName, PATH_MAX);
2582 name_len++; /* trailing null */
2583 strncpy(pSMB->FileName, searchName, name_len);
2586 params = 2 /* level */ + 4 /* rsrvd */ + name_len /* incl null */ ;
2587 pSMB->TotalDataCount = 0;
2588 pSMB->MaxParameterCount = cpu_to_le16(2);
2589 /* BB find exact max data count below from sess structure BB */
2590 pSMB->MaxDataCount = cpu_to_le16(4000);
2591 pSMB->MaxSetupCount = 0;
2595 pSMB->Reserved2 = 0;
2596 pSMB->ParameterOffset = cpu_to_le16(
2597 offsetof(struct smb_com_transaction2_qpi_req ,InformationLevel) - 4);
2598 pSMB->DataCount = 0;
2599 pSMB->DataOffset = 0;
2600 pSMB->SetupCount = 1;
2601 pSMB->Reserved3 = 0;
2602 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
2603 byte_count = params + 1 /* pad */ ;
2604 pSMB->TotalParameterCount = cpu_to_le16(params);
2605 pSMB->ParameterCount = pSMB->TotalParameterCount;
2606 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_POSIX_ACL);
2607 pSMB->Reserved4 = 0;
2608 pSMB->hdr.smb_buf_length += byte_count;
2609 pSMB->ByteCount = cpu_to_le16(byte_count);
2611 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2612 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2613 cifs_stats_inc(&tcon->num_acl_get);
2615 cFYI(1, ("Send error in Query POSIX ACL = %d", rc));
2617 /* decode response */
2619 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
2620 if (rc || (pSMBr->ByteCount < 2))
2621 /* BB also check enough total bytes returned */
2622 rc = -EIO; /* bad smb */
2624 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
2625 __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
2626 rc = cifs_copy_posix_acl(acl_inf,
2627 (char *)&pSMBr->hdr.Protocol+data_offset,
2628 buflen,acl_type,count);
2631 cifs_buf_release(pSMB);
2638 CIFSSMBSetPosixACL(const int xid, struct cifsTconInfo *tcon,
2639 const unsigned char *fileName,
2640 const char *local_acl, const int buflen,
2642 const struct nls_table *nls_codepage, int remap)
2644 struct smb_com_transaction2_spi_req *pSMB = NULL;
2645 struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
2649 int bytes_returned = 0;
2650 __u16 params, byte_count, data_count, param_offset, offset;
2652 cFYI(1, ("In SetPosixACL (Unix) for path %s", fileName));
2654 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2658 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2660 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
2661 PATH_MAX, nls_codepage, remap);
2662 name_len++; /* trailing null */
2664 } else { /* BB improve the check for buffer overruns BB */
2665 name_len = strnlen(fileName, PATH_MAX);
2666 name_len++; /* trailing null */
2667 strncpy(pSMB->FileName, fileName, name_len);
2669 params = 6 + name_len;
2670 pSMB->MaxParameterCount = cpu_to_le16(2);
2671 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB size from sess */
2672 pSMB->MaxSetupCount = 0;
2676 pSMB->Reserved2 = 0;
2677 param_offset = offsetof(struct smb_com_transaction2_spi_req,
2678 InformationLevel) - 4;
2679 offset = param_offset + params;
2680 parm_data = ((char *) &pSMB->hdr.Protocol) + offset;
2681 pSMB->ParameterOffset = cpu_to_le16(param_offset);
2683 /* convert to on the wire format for POSIX ACL */
2684 data_count = ACL_to_cifs_posix(parm_data,local_acl,buflen,acl_type);
2686 if(data_count == 0) {
2688 goto setACLerrorExit;
2690 pSMB->DataOffset = cpu_to_le16(offset);
2691 pSMB->SetupCount = 1;
2692 pSMB->Reserved3 = 0;
2693 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
2694 pSMB->InformationLevel = cpu_to_le16(SMB_SET_POSIX_ACL);
2695 byte_count = 3 /* pad */ + params + data_count;
2696 pSMB->DataCount = cpu_to_le16(data_count);
2697 pSMB->TotalDataCount = pSMB->DataCount;
2698 pSMB->ParameterCount = cpu_to_le16(params);
2699 pSMB->TotalParameterCount = pSMB->ParameterCount;
2700 pSMB->Reserved4 = 0;
2701 pSMB->hdr.smb_buf_length += byte_count;
2702 pSMB->ByteCount = cpu_to_le16(byte_count);
2703 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2704 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2706 cFYI(1, ("Set POSIX ACL returned %d", rc));
2710 cifs_buf_release(pSMB);
2716 /* BB fix tabs in this function FIXME BB */
2718 CIFSGetExtAttr(const int xid, struct cifsTconInfo *tcon,
2719 const int netfid, __u64 * pExtAttrBits, __u64 *pMask)
2722 struct smb_t2_qfi_req *pSMB = NULL;
2723 struct smb_t2_qfi_rsp *pSMBr = NULL;
2725 __u16 params, byte_count;
2727 cFYI(1,("In GetExtAttr"));
2732 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2737 params = 2 /* level */ +2 /* fid */;
2738 pSMB->t2.TotalDataCount = 0;
2739 pSMB->t2.MaxParameterCount = cpu_to_le16(4);
2740 /* BB find exact max data count below from sess structure BB */
2741 pSMB->t2.MaxDataCount = cpu_to_le16(4000);
2742 pSMB->t2.MaxSetupCount = 0;
2743 pSMB->t2.Reserved = 0;
2745 pSMB->t2.Timeout = 0;
2746 pSMB->t2.Reserved2 = 0;
2747 pSMB->t2.ParameterOffset = cpu_to_le16(offsetof(struct smb_t2_qfi_req,
2749 pSMB->t2.DataCount = 0;
2750 pSMB->t2.DataOffset = 0;
2751 pSMB->t2.SetupCount = 1;
2752 pSMB->t2.Reserved3 = 0;
2753 pSMB->t2.SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION);
2754 byte_count = params + 1 /* pad */ ;
2755 pSMB->t2.TotalParameterCount = cpu_to_le16(params);
2756 pSMB->t2.ParameterCount = pSMB->t2.TotalParameterCount;
2757 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_ATTR_FLAGS);
2760 pSMB->hdr.smb_buf_length += byte_count;
2761 pSMB->t2.ByteCount = cpu_to_le16(byte_count);
2763 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2764 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2766 cFYI(1, ("error %d in GetExtAttr", rc));
2768 /* decode response */
2769 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
2770 if (rc || (pSMBr->ByteCount < 2))
2771 /* BB also check enough total bytes returned */
2772 /* If rc should we check for EOPNOSUPP and
2773 disable the srvino flag? or in caller? */
2774 rc = -EIO; /* bad smb */
2776 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
2777 __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
2778 struct file_chattr_info * pfinfo;
2779 /* BB Do we need a cast or hash here ? */
2781 cFYI(1, ("Illegal size ret in GetExtAttr"));
2785 pfinfo = (struct file_chattr_info *)
2786 (data_offset + (char *) &pSMBr->hdr.Protocol);
2787 *pExtAttrBits = le64_to_cpu(pfinfo->mode);
2788 *pMask = le64_to_cpu(pfinfo->mask);
2792 cifs_buf_release(pSMB);
2794 goto GetExtAttrRetry;
2799 #endif /* CONFIG_POSIX */
2802 /* security id for everyone */
2803 const static struct cifs_sid sid_everyone =
2804 {1, 1, {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0}};
2806 const static struct cifs_sid sid_user =
2807 {1, 2 , {0, 0, 0, 0, 0, 5}, {32, 545, 0, 0}};
2809 /* Convert CIFS ACL to POSIX form */
2810 static int parse_sec_desc(struct cifs_sid * psec_desc, int acl_len)
2815 /* Get Security Descriptor (by handle) from remote server for a file or dir */
2817 CIFSSMBGetCIFSACL(const int xid, struct cifsTconInfo *tcon, __u16 fid,
2818 /* BB fix up return info */ char *acl_inf, const int buflen,
2819 const int acl_type /* ACCESS/DEFAULT not sure implication */)
2823 QUERY_SEC_DESC_REQ * pSMB;
2826 cFYI(1, ("GetCifsACL"));
2828 rc = smb_init_ntransact(NT_TRANSACT_QUERY_SECURITY_DESC, 0,
2829 8 /* parm len */, tcon, (void **) &pSMB);
2833 pSMB->MaxParameterCount = cpu_to_le32(4);
2834 /* BB TEST with big acls that might need to be e.g. larger than 16K */
2835 pSMB->MaxSetupCount = 0;
2836 pSMB->Fid = fid; /* file handle always le */
2837 pSMB->AclFlags = cpu_to_le32(CIFS_ACL_OWNER | CIFS_ACL_GROUP |
2839 pSMB->ByteCount = cpu_to_le16(11); /* 3 bytes pad + 8 bytes parm */
2840 pSMB->hdr.smb_buf_length += 11;
2841 iov[0].iov_base = (char *)pSMB;
2842 iov[0].iov_len = pSMB->hdr.smb_buf_length + 4;
2844 rc = SendReceive2(xid, tcon->ses, iov, 1 /* num iovec */, &buf_type, 0);
2845 cifs_stats_inc(&tcon->num_acl_get);
2847 cFYI(1, ("Send error in QuerySecDesc = %d", rc));
2848 } else { /* decode response */
2849 struct cifs_sid * psec_desc;
2854 struct smb_com_ntransact_rsp * pSMBr;
2856 /* validate_nttransact */
2857 rc = validate_ntransact(iov[0].iov_base, (char **)&parm,
2858 (char **)&psec_desc,
2859 &parm_len, &data_len);
2863 pSMBr = (struct smb_com_ntransact_rsp *)iov[0].iov_base;
2865 cERROR(1,("smb %p parm %p data %p",pSMBr,parm,psec_desc)); /* BB removeme BB */
2867 if (le32_to_cpu(pSMBr->ParameterCount) != 4) {
2868 rc = -EIO; /* bad smb */
2872 /* BB check that data area is minimum length and as big as acl_len */
2874 acl_len = le32_to_cpu(*(__le32 *)parm);
2875 /* BB check if(acl_len > bufsize) */
2877 parse_sec_desc(psec_desc, acl_len);
2880 if(buf_type == CIFS_SMALL_BUFFER)
2881 cifs_small_buf_release(iov[0].iov_base);
2882 else if(buf_type == CIFS_LARGE_BUFFER)
2883 cifs_buf_release(iov[0].iov_base);
2884 /* cifs_small_buf_release(pSMB); */ /* Freed earlier now in SendReceive2 */
2888 /* Legacy Query Path Information call for lookup to old servers such
2890 int SMBQueryInformation(const int xid, struct cifsTconInfo *tcon,
2891 const unsigned char *searchName,
2892 FILE_ALL_INFO * pFinfo,
2893 const struct nls_table *nls_codepage, int remap)
2895 QUERY_INFORMATION_REQ * pSMB;
2896 QUERY_INFORMATION_RSP * pSMBr;
2901 cFYI(1, ("In SMBQPath path %s", searchName));
2903 rc = smb_init(SMB_COM_QUERY_INFORMATION, 0, tcon, (void **) &pSMB,
2908 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2910 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
2911 PATH_MAX, nls_codepage, remap);
2912 name_len++; /* trailing null */
2915 name_len = strnlen(searchName, PATH_MAX);
2916 name_len++; /* trailing null */
2917 strncpy(pSMB->FileName, searchName, name_len);
2919 pSMB->BufferFormat = 0x04;
2920 name_len++; /* account for buffer type byte */
2921 pSMB->hdr.smb_buf_length += (__u16) name_len;
2922 pSMB->ByteCount = cpu_to_le16(name_len);
2924 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2925 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2927 cFYI(1, ("Send error in QueryInfo = %d", rc));
2928 } else if (pFinfo) { /* decode response */
2930 __u32 time = le32_to_cpu(pSMBr->last_write_time);
2931 /* BB FIXME - add time zone adjustment BB */
2932 memset(pFinfo, 0, sizeof(FILE_ALL_INFO));
2935 /* decode time fields */
2936 pFinfo->ChangeTime = cifs_UnixTimeToNT(ts);
2937 pFinfo->LastWriteTime = pFinfo->ChangeTime;
2938 pFinfo->LastAccessTime = 0;
2939 pFinfo->AllocationSize =
2940 cpu_to_le64(le32_to_cpu(pSMBr->size));
2941 pFinfo->EndOfFile = pFinfo->AllocationSize;
2942 pFinfo->Attributes =
2943 cpu_to_le32(le16_to_cpu(pSMBr->attr));
2945 rc = -EIO; /* bad buffer passed in */
2947 cifs_buf_release(pSMB);
2959 CIFSSMBQPathInfo(const int xid, struct cifsTconInfo *tcon,
2960 const unsigned char *searchName,
2961 FILE_ALL_INFO * pFindData,
2962 const struct nls_table *nls_codepage, int remap)
2964 /* level 263 SMB_QUERY_FILE_ALL_INFO */
2965 TRANSACTION2_QPI_REQ *pSMB = NULL;
2966 TRANSACTION2_QPI_RSP *pSMBr = NULL;
2970 __u16 params, byte_count;
2972 /* cFYI(1, ("In QPathInfo path %s", searchName)); */
2974 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2979 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2981 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
2982 PATH_MAX, nls_codepage, remap);
2983 name_len++; /* trailing null */
2985 } else { /* BB improve the check for buffer overruns BB */
2986 name_len = strnlen(searchName, PATH_MAX);
2987 name_len++; /* trailing null */
2988 strncpy(pSMB->FileName, searchName, name_len);
2991 params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */ ;
2992 pSMB->TotalDataCount = 0;
2993 pSMB->MaxParameterCount = cpu_to_le16(2);
2994 pSMB->MaxDataCount = cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
2995 pSMB->MaxSetupCount = 0;
2999 pSMB->Reserved2 = 0;
3000 pSMB->ParameterOffset = cpu_to_le16(offsetof(
3001 struct smb_com_transaction2_qpi_req ,InformationLevel) - 4);
3002 pSMB->DataCount = 0;
3003 pSMB->DataOffset = 0;
3004 pSMB->SetupCount = 1;
3005 pSMB->Reserved3 = 0;
3006 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
3007 byte_count = params + 1 /* pad */ ;
3008 pSMB->TotalParameterCount = cpu_to_le16(params);
3009 pSMB->ParameterCount = pSMB->TotalParameterCount;
3010 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_ALL_INFO);
3011 pSMB->Reserved4 = 0;
3012 pSMB->hdr.smb_buf_length += byte_count;
3013 pSMB->ByteCount = cpu_to_le16(byte_count);
3015 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3016 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3018 cFYI(1, ("Send error in QPathInfo = %d", rc));
3019 } else { /* decode response */
3020 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3022 if (rc || (pSMBr->ByteCount < 40))
3023 rc = -EIO; /* bad smb */
3024 else if (pFindData){
3025 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3026 memcpy((char *) pFindData,
3027 (char *) &pSMBr->hdr.Protocol +
3028 data_offset, sizeof (FILE_ALL_INFO));
3032 cifs_buf_release(pSMB);
3034 goto QPathInfoRetry;
3040 CIFSSMBUnixQPathInfo(const int xid, struct cifsTconInfo *tcon,
3041 const unsigned char *searchName,
3042 FILE_UNIX_BASIC_INFO * pFindData,
3043 const struct nls_table *nls_codepage, int remap)
3045 /* SMB_QUERY_FILE_UNIX_BASIC */
3046 TRANSACTION2_QPI_REQ *pSMB = NULL;
3047 TRANSACTION2_QPI_RSP *pSMBr = NULL;
3049 int bytes_returned = 0;
3051 __u16 params, byte_count;
3053 cFYI(1, ("In QPathInfo (Unix) the path %s", searchName));
3055 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3060 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3062 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
3063 PATH_MAX, nls_codepage, remap);
3064 name_len++; /* trailing null */
3066 } else { /* BB improve the check for buffer overruns BB */
3067 name_len = strnlen(searchName, PATH_MAX);
3068 name_len++; /* trailing null */
3069 strncpy(pSMB->FileName, searchName, name_len);
3072 params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */ ;
3073 pSMB->TotalDataCount = 0;
3074 pSMB->MaxParameterCount = cpu_to_le16(2);
3075 /* BB find exact max SMB PDU from sess structure BB */
3076 pSMB->MaxDataCount = cpu_to_le16(4000);
3077 pSMB->MaxSetupCount = 0;
3081 pSMB->Reserved2 = 0;
3082 pSMB->ParameterOffset = cpu_to_le16(offsetof(
3083 struct smb_com_transaction2_qpi_req ,InformationLevel) - 4);
3084 pSMB->DataCount = 0;
3085 pSMB->DataOffset = 0;
3086 pSMB->SetupCount = 1;
3087 pSMB->Reserved3 = 0;
3088 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
3089 byte_count = params + 1 /* pad */ ;
3090 pSMB->TotalParameterCount = cpu_to_le16(params);
3091 pSMB->ParameterCount = pSMB->TotalParameterCount;
3092 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC);
3093 pSMB->Reserved4 = 0;
3094 pSMB->hdr.smb_buf_length += byte_count;
3095 pSMB->ByteCount = cpu_to_le16(byte_count);
3097 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3098 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3100 cFYI(1, ("Send error in QPathInfo = %d", rc));
3101 } else { /* decode response */
3102 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3104 if (rc || (pSMBr->ByteCount < sizeof(FILE_UNIX_BASIC_INFO))) {
3105 rc = -EIO; /* bad smb */
3107 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3108 memcpy((char *) pFindData,
3109 (char *) &pSMBr->hdr.Protocol +
3111 sizeof (FILE_UNIX_BASIC_INFO));
3114 cifs_buf_release(pSMB);
3116 goto UnixQPathInfoRetry;
3121 #if 0 /* function unused at present */
3122 int CIFSFindSingle(const int xid, struct cifsTconInfo *tcon,
3123 const char *searchName, FILE_ALL_INFO * findData,
3124 const struct nls_table *nls_codepage)
3126 /* level 257 SMB_ */
3127 TRANSACTION2_FFIRST_REQ *pSMB = NULL;
3128 TRANSACTION2_FFIRST_RSP *pSMBr = NULL;
3132 __u16 params, byte_count;
3134 cFYI(1, ("In FindUnique"));
3136 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3141 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3143 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName, PATH_MAX
3144 /* find define for this maxpathcomponent */
3146 name_len++; /* trailing null */
3148 } else { /* BB improve the check for buffer overruns BB */
3149 name_len = strnlen(searchName, PATH_MAX);
3150 name_len++; /* trailing null */
3151 strncpy(pSMB->FileName, searchName, name_len);
3154 params = 12 + name_len /* includes null */ ;
3155 pSMB->TotalDataCount = 0; /* no EAs */
3156 pSMB->MaxParameterCount = cpu_to_le16(2);
3157 pSMB->MaxDataCount = cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
3158 pSMB->MaxSetupCount = 0;
3162 pSMB->Reserved2 = 0;
3163 pSMB->ParameterOffset = cpu_to_le16(
3164 offsetof(struct smb_com_transaction2_ffirst_req,InformationLevel) - 4);
3165 pSMB->DataCount = 0;
3166 pSMB->DataOffset = 0;
3167 pSMB->SetupCount = 1; /* one byte, no need to le convert */
3168 pSMB->Reserved3 = 0;
3169 pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_FIRST);
3170 byte_count = params + 1 /* pad */ ;
3171 pSMB->TotalParameterCount = cpu_to_le16(params);
3172 pSMB->ParameterCount = pSMB->TotalParameterCount;
3173 pSMB->SearchAttributes =
3174 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
3176 pSMB->SearchCount = cpu_to_le16(16); /* BB increase */
3177 pSMB->SearchFlags = cpu_to_le16(1);
3178 pSMB->InformationLevel = cpu_to_le16(SMB_FIND_FILE_DIRECTORY_INFO);
3179 pSMB->SearchStorageType = 0; /* BB what should we set this to? BB */
3180 pSMB->hdr.smb_buf_length += byte_count;
3181 pSMB->ByteCount = cpu_to_le16(byte_count);
3183 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3184 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3187 cFYI(1, ("Send error in FindFileDirInfo = %d", rc));
3188 } else { /* decode response */
3189 cifs_stats_inc(&tcon->num_ffirst);
3193 cifs_buf_release(pSMB);
3195 goto findUniqueRetry;
3199 #endif /* end unused (temporarily) function */
3201 /* xid, tcon, searchName and codepage are input parms, rest are returned */
3203 CIFSFindFirst(const int xid, struct cifsTconInfo *tcon,
3204 const char *searchName,
3205 const struct nls_table *nls_codepage,
3207 struct cifs_search_info * psrch_inf, int remap, const char dirsep)
3209 /* level 257 SMB_ */
3210 TRANSACTION2_FFIRST_REQ *pSMB = NULL;
3211 TRANSACTION2_FFIRST_RSP *pSMBr = NULL;
3212 T2_FFIRST_RSP_PARMS * parms;
3214 int bytes_returned = 0;
3216 __u16 params, byte_count;
3218 cFYI(1, ("In FindFirst for %s",searchName));
3221 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3226 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3228 cifsConvertToUCS((__le16 *) pSMB->FileName,searchName,
3229 PATH_MAX, nls_codepage, remap);
3230 /* We can not add the asterik earlier in case
3231 it got remapped to 0xF03A as if it were part of the
3232 directory name instead of a wildcard */
3234 pSMB->FileName[name_len] = dirsep;
3235 pSMB->FileName[name_len+1] = 0;
3236 pSMB->FileName[name_len+2] = '*';
3237 pSMB->FileName[name_len+3] = 0;
3238 name_len += 4; /* now the trailing null */
3239 pSMB->FileName[name_len] = 0; /* null terminate just in case */
3240 pSMB->FileName[name_len+1] = 0;
3242 } else { /* BB add check for overrun of SMB buf BB */
3243 name_len = strnlen(searchName, PATH_MAX);
3244 /* BB fix here and in unicode clause above ie
3245 if(name_len > buffersize-header)
3246 free buffer exit; BB */
3247 strncpy(pSMB->FileName, searchName, name_len);
3248 pSMB->FileName[name_len] = dirsep;
3249 pSMB->FileName[name_len+1] = '*';
3250 pSMB->FileName[name_len+2] = 0;
3254 params = 12 + name_len /* includes null */ ;
3255 pSMB->TotalDataCount = 0; /* no EAs */
3256 pSMB->MaxParameterCount = cpu_to_le16(10);
3257 pSMB->MaxDataCount = cpu_to_le16((tcon->ses->server->maxBuf -
3258 MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
3259 pSMB->MaxSetupCount = 0;
3263 pSMB->Reserved2 = 0;
3264 byte_count = params + 1 /* pad */ ;
3265 pSMB->TotalParameterCount = cpu_to_le16(params);
3266 pSMB->ParameterCount = pSMB->TotalParameterCount;
3267 pSMB->ParameterOffset = cpu_to_le16(
3268 offsetof(struct smb_com_transaction2_ffirst_req, SearchAttributes)
3270 pSMB->DataCount = 0;
3271 pSMB->DataOffset = 0;
3272 pSMB->SetupCount = 1; /* one byte, no need to make endian neutral */
3273 pSMB->Reserved3 = 0;
3274 pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_FIRST);
3275 pSMB->SearchAttributes =
3276 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
3278 pSMB->SearchCount= cpu_to_le16(CIFSMaxBufSize/sizeof(FILE_UNIX_INFO));
3279 pSMB->SearchFlags = cpu_to_le16(CIFS_SEARCH_CLOSE_AT_END |
3280 CIFS_SEARCH_RETURN_RESUME);
3281 pSMB->InformationLevel = cpu_to_le16(psrch_inf->info_level);
3283 /* BB what should we set StorageType to? Does it matter? BB */
3284 pSMB->SearchStorageType = 0;
3285 pSMB->hdr.smb_buf_length += byte_count;
3286 pSMB->ByteCount = cpu_to_le16(byte_count);
3288 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3289 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3290 cifs_stats_inc(&tcon->num_ffirst);
3292 if (rc) {/* BB add logic to retry regular search if Unix search
3293 rejected unexpectedly by server */
3294 /* BB Add code to handle unsupported level rc */
3295 cFYI(1, ("Error in FindFirst = %d", rc));
3297 cifs_buf_release(pSMB);
3299 /* BB eventually could optimize out free and realloc of buf */
3302 goto findFirstRetry;
3303 } else { /* decode response */
3304 /* BB remember to free buffer if error BB */
3305 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3307 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
3308 psrch_inf->unicode = TRUE;
3310 psrch_inf->unicode = FALSE;
3312 psrch_inf->ntwrk_buf_start = (char *)pSMBr;
3313 psrch_inf->smallBuf = 0;
3314 psrch_inf->srch_entries_start =
3315 (char *) &pSMBr->hdr.Protocol +
3316 le16_to_cpu(pSMBr->t2.DataOffset);
3317 parms = (T2_FFIRST_RSP_PARMS *)((char *) &pSMBr->hdr.Protocol +
3318 le16_to_cpu(pSMBr->t2.ParameterOffset));
3320 if(parms->EndofSearch)
3321 psrch_inf->endOfSearch = TRUE;
3323 psrch_inf->endOfSearch = FALSE;
3325 psrch_inf->entries_in_buffer = le16_to_cpu(parms->SearchCount);
3326 psrch_inf->index_of_last_entry = 2 /* skip . and .. */ +
3327 psrch_inf->entries_in_buffer;
3328 *pnetfid = parms->SearchHandle;
3330 cifs_buf_release(pSMB);
3337 int CIFSFindNext(const int xid, struct cifsTconInfo *tcon,
3338 __u16 searchHandle, struct cifs_search_info * psrch_inf)
3340 TRANSACTION2_FNEXT_REQ *pSMB = NULL;
3341 TRANSACTION2_FNEXT_RSP *pSMBr = NULL;
3342 T2_FNEXT_RSP_PARMS * parms;
3343 char *response_data;
3345 int bytes_returned, name_len;
3346 __u16 params, byte_count;
3348 cFYI(1, ("In FindNext"));
3350 if(psrch_inf->endOfSearch == TRUE)
3353 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3358 params = 14; /* includes 2 bytes of null string, converted to LE below */
3360 pSMB->TotalDataCount = 0; /* no EAs */
3361 pSMB->MaxParameterCount = cpu_to_le16(8);
3362 pSMB->MaxDataCount =
3363 cpu_to_le16((tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
3364 pSMB->MaxSetupCount = 0;
3368 pSMB->Reserved2 = 0;
3369 pSMB->ParameterOffset = cpu_to_le16(
3370 offsetof(struct smb_com_transaction2_fnext_req,SearchHandle) - 4);
3371 pSMB->DataCount = 0;
3372 pSMB->DataOffset = 0;
3373 pSMB->SetupCount = 1;
3374 pSMB->Reserved3 = 0;
3375 pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_NEXT);
3376 pSMB->SearchHandle = searchHandle; /* always kept as le */
3378 cpu_to_le16(CIFSMaxBufSize / sizeof (FILE_UNIX_INFO));
3379 /* test for Unix extensions */
3380 /* if (tcon->ses->capabilities & CAP_UNIX) {
3381 pSMB->InformationLevel = cpu_to_le16(SMB_FIND_FILE_UNIX);
3382 psrch_inf->info_level = SMB_FIND_FILE_UNIX;
3384 pSMB->InformationLevel =
3385 cpu_to_le16(SMB_FIND_FILE_DIRECTORY_INFO);
3386 psrch_inf->info_level = SMB_FIND_FILE_DIRECTORY_INFO;
3388 pSMB->InformationLevel = cpu_to_le16(psrch_inf->info_level);
3389 pSMB->ResumeKey = psrch_inf->resume_key;
3391 cpu_to_le16(CIFS_SEARCH_CLOSE_AT_END | CIFS_SEARCH_RETURN_RESUME);
3393 name_len = psrch_inf->resume_name_len;
3395 if(name_len < PATH_MAX) {
3396 memcpy(pSMB->ResumeFileName, psrch_inf->presume_name, name_len);
3397 byte_count += name_len;
3398 /* 14 byte parm len above enough for 2 byte null terminator */
3399 pSMB->ResumeFileName[name_len] = 0;
3400 pSMB->ResumeFileName[name_len+1] = 0;
3403 goto FNext2_err_exit;
3405 byte_count = params + 1 /* pad */ ;
3406 pSMB->TotalParameterCount = cpu_to_le16(params);
3407 pSMB->ParameterCount = pSMB->TotalParameterCount;
3408 pSMB->hdr.smb_buf_length += byte_count;
3409 pSMB->ByteCount = cpu_to_le16(byte_count);
3411 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3412 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3413 cifs_stats_inc(&tcon->num_fnext);
3416 psrch_inf->endOfSearch = TRUE;
3417 rc = 0; /* search probably was closed at end of search above */
3419 cFYI(1, ("FindNext returned = %d", rc));
3420 } else { /* decode response */
3421 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3424 /* BB fixme add lock for file (srch_info) struct here */
3425 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
3426 psrch_inf->unicode = TRUE;
3428 psrch_inf->unicode = FALSE;
3429 response_data = (char *) &pSMBr->hdr.Protocol +
3430 le16_to_cpu(pSMBr->t2.ParameterOffset);
3431 parms = (T2_FNEXT_RSP_PARMS *)response_data;
3432 response_data = (char *)&pSMBr->hdr.Protocol +
3433 le16_to_cpu(pSMBr->t2.DataOffset);
3434 if(psrch_inf->smallBuf)
3435 cifs_small_buf_release(
3436 psrch_inf->ntwrk_buf_start);
3438 cifs_buf_release(psrch_inf->ntwrk_buf_start);
3439 psrch_inf->srch_entries_start = response_data;
3440 psrch_inf->ntwrk_buf_start = (char *)pSMB;
3441 psrch_inf->smallBuf = 0;
3442 if(parms->EndofSearch)
3443 psrch_inf->endOfSearch = TRUE;
3445 psrch_inf->endOfSearch = FALSE;
3447 psrch_inf->entries_in_buffer = le16_to_cpu(parms->SearchCount);
3448 psrch_inf->index_of_last_entry +=
3449 psrch_inf->entries_in_buffer;
3450 /* cFYI(1,("fnxt2 entries in buf %d index_of_last %d",psrch_inf->entries_in_buffer,psrch_inf->index_of_last_entry)); */
3452 /* BB fixme add unlock here */
3457 /* BB On error, should we leave previous search buf (and count and
3458 last entry fields) intact or free the previous one? */
3460 /* Note: On -EAGAIN error only caller can retry on handle based calls
3461 since file handle passed in no longer valid */
3464 cifs_buf_release(pSMB);
3470 CIFSFindClose(const int xid, struct cifsTconInfo *tcon, const __u16 searchHandle)
3473 FINDCLOSE_REQ *pSMB = NULL;
3474 CLOSE_RSP *pSMBr = NULL; /* BB removeme BB */
3477 cFYI(1, ("In CIFSSMBFindClose"));
3478 rc = small_smb_init(SMB_COM_FIND_CLOSE2, 1, tcon, (void **)&pSMB);
3480 /* no sense returning error if session restarted
3481 as file handle has been closed */
3487 pSMBr = (CLOSE_RSP *)pSMB; /* BB removeme BB */
3488 pSMB->FileID = searchHandle;
3489 pSMB->ByteCount = 0;
3490 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3491 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3493 cERROR(1, ("Send error in FindClose = %d", rc));
3495 cifs_stats_inc(&tcon->num_fclose);
3496 cifs_small_buf_release(pSMB);
3498 /* Since session is dead, search handle closed on server already */
3506 CIFSGetSrvInodeNumber(const int xid, struct cifsTconInfo *tcon,
3507 const unsigned char *searchName,
3508 __u64 * inode_number,
3509 const struct nls_table *nls_codepage, int remap)
3512 TRANSACTION2_QPI_REQ *pSMB = NULL;
3513 TRANSACTION2_QPI_RSP *pSMBr = NULL;
3514 int name_len, bytes_returned;
3515 __u16 params, byte_count;
3517 cFYI(1,("In GetSrvInodeNum for %s",searchName));
3521 GetInodeNumberRetry:
3522 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3528 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3530 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
3531 PATH_MAX,nls_codepage, remap);
3532 name_len++; /* trailing null */
3534 } else { /* BB improve the check for buffer overruns BB */
3535 name_len = strnlen(searchName, PATH_MAX);
3536 name_len++; /* trailing null */
3537 strncpy(pSMB->FileName, searchName, name_len);
3540 params = 2 /* level */ + 4 /* rsrvd */ + name_len /* incl null */ ;
3541 pSMB->TotalDataCount = 0;
3542 pSMB->MaxParameterCount = cpu_to_le16(2);
3543 /* BB find exact max data count below from sess structure BB */
3544 pSMB->MaxDataCount = cpu_to_le16(4000);
3545 pSMB->MaxSetupCount = 0;
3549 pSMB->Reserved2 = 0;
3550 pSMB->ParameterOffset = cpu_to_le16(offsetof(
3551 struct smb_com_transaction2_qpi_req ,InformationLevel) - 4);
3552 pSMB->DataCount = 0;
3553 pSMB->DataOffset = 0;
3554 pSMB->SetupCount = 1;
3555 pSMB->Reserved3 = 0;
3556 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
3557 byte_count = params + 1 /* pad */ ;
3558 pSMB->TotalParameterCount = cpu_to_le16(params);
3559 pSMB->ParameterCount = pSMB->TotalParameterCount;
3560 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_INTERNAL_INFO);
3561 pSMB->Reserved4 = 0;
3562 pSMB->hdr.smb_buf_length += byte_count;
3563 pSMB->ByteCount = cpu_to_le16(byte_count);
3565 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3566 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3568 cFYI(1, ("error %d in QueryInternalInfo", rc));
3570 /* decode response */
3571 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3572 if (rc || (pSMBr->ByteCount < 2))
3573 /* BB also check enough total bytes returned */
3574 /* If rc should we check for EOPNOSUPP and
3575 disable the srvino flag? or in caller? */
3576 rc = -EIO; /* bad smb */
3578 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3579 __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
3580 struct file_internal_info * pfinfo;
3581 /* BB Do we need a cast or hash here ? */
3583 cFYI(1, ("Illegal size ret in QryIntrnlInf"));
3585 goto GetInodeNumOut;
3587 pfinfo = (struct file_internal_info *)
3588 (data_offset + (char *) &pSMBr->hdr.Protocol);
3589 *inode_number = pfinfo->UniqueId;
3593 cifs_buf_release(pSMB);
3595 goto GetInodeNumberRetry;
3600 CIFSGetDFSRefer(const int xid, struct cifsSesInfo *ses,
3601 const unsigned char *searchName,
3602 unsigned char **targetUNCs,
3603 unsigned int *number_of_UNC_in_array,
3604 const struct nls_table *nls_codepage, int remap)
3606 /* TRANS2_GET_DFS_REFERRAL */
3607 TRANSACTION2_GET_DFS_REFER_REQ *pSMB = NULL;
3608 TRANSACTION2_GET_DFS_REFER_RSP *pSMBr = NULL;
3609 struct dfs_referral_level_3 * referrals = NULL;
3615 __u16 params, byte_count;
3616 *number_of_UNC_in_array = 0;
3619 cFYI(1, ("In GetDFSRefer the path %s", searchName));
3623 rc = smb_init(SMB_COM_TRANSACTION2, 15, NULL, (void **) &pSMB,
3628 /* server pointer checked in called function,
3629 but should never be null here anyway */
3630 pSMB->hdr.Mid = GetNextMid(ses->server);
3631 pSMB->hdr.Tid = ses->ipc_tid;
3632 pSMB->hdr.Uid = ses->Suid;
3633 if (ses->capabilities & CAP_STATUS32) {
3634 pSMB->hdr.Flags2 |= SMBFLG2_ERR_STATUS;
3636 if (ses->capabilities & CAP_DFS) {
3637 pSMB->hdr.Flags2 |= SMBFLG2_DFS;
3640 if (ses->capabilities & CAP_UNICODE) {
3641 pSMB->hdr.Flags2 |= SMBFLG2_UNICODE;
3643 cifsConvertToUCS((__le16 *) pSMB->RequestFileName,
3644 searchName, PATH_MAX, nls_codepage, remap);
3645 name_len++; /* trailing null */
3647 } else { /* BB improve the check for buffer overruns BB */
3648 name_len = strnlen(searchName, PATH_MAX);
3649 name_len++; /* trailing null */
3650 strncpy(pSMB->RequestFileName, searchName, name_len);
3653 params = 2 /* level */ + name_len /*includes null */ ;
3654 pSMB->TotalDataCount = 0;
3655 pSMB->DataCount = 0;
3656 pSMB->DataOffset = 0;
3657 pSMB->MaxParameterCount = 0;
3658 pSMB->MaxDataCount = cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
3659 pSMB->MaxSetupCount = 0;
3663 pSMB->Reserved2 = 0;
3664 pSMB->ParameterOffset = cpu_to_le16(offsetof(
3665 struct smb_com_transaction2_get_dfs_refer_req, MaxReferralLevel) - 4);
3666 pSMB->SetupCount = 1;
3667 pSMB->Reserved3 = 0;
3668 pSMB->SubCommand = cpu_to_le16(TRANS2_GET_DFS_REFERRAL);
3669 byte_count = params + 3 /* pad */ ;
3670 pSMB->ParameterCount = cpu_to_le16(params);
3671 pSMB->TotalParameterCount = pSMB->ParameterCount;
3672 pSMB->MaxReferralLevel = cpu_to_le16(3);
3673 pSMB->hdr.smb_buf_length += byte_count;
3674 pSMB->ByteCount = cpu_to_le16(byte_count);
3676 rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB,
3677 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3679 cFYI(1, ("Send error in GetDFSRefer = %d", rc));
3680 } else { /* decode response */
3681 /* BB Add logic to parse referrals here */
3682 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3684 if (rc || (pSMBr->ByteCount < 17)) /* BB also check enough total bytes returned */
3685 rc = -EIO; /* bad smb */
3687 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3688 __u16 data_count = le16_to_cpu(pSMBr->t2.DataCount);
3691 ("Decoding GetDFSRefer response. BCC: %d Offset %d",
3692 pSMBr->ByteCount, data_offset));
3694 (struct dfs_referral_level_3 *)
3695 (8 /* sizeof start of data block */ +
3697 (char *) &pSMBr->hdr.Protocol);
3698 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",
3699 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)));
3700 /* BB This field is actually two bytes in from start of
3701 data block so we could do safety check that DataBlock
3702 begins at address of pSMBr->NumberOfReferrals */
3703 *number_of_UNC_in_array = le16_to_cpu(pSMBr->NumberOfReferrals);
3705 /* BB Fix below so can return more than one referral */
3706 if(*number_of_UNC_in_array > 1)
3707 *number_of_UNC_in_array = 1;
3709 /* get the length of the strings describing refs */
3711 for(i=0;i<*number_of_UNC_in_array;i++) {
3712 /* make sure that DfsPathOffset not past end */
3713 __u16 offset = le16_to_cpu(referrals->DfsPathOffset);
3714 if (offset > data_count) {
3715 /* if invalid referral, stop here and do
3716 not try to copy any more */
3717 *number_of_UNC_in_array = i;
3720 temp = ((char *)referrals) + offset;
3722 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
3723 name_len += UniStrnlen((wchar_t *)temp,data_count);
3725 name_len += strnlen(temp,data_count);
3728 /* BB add check that referral pointer does not fall off end PDU */
3731 /* BB add check for name_len bigger than bcc */
3733 kmalloc(name_len+1+ (*number_of_UNC_in_array),GFP_KERNEL);
3734 if(*targetUNCs == NULL) {
3738 /* copy the ref strings */
3740 (struct dfs_referral_level_3 *)
3741 (8 /* sizeof data hdr */ +
3743 (char *) &pSMBr->hdr.Protocol);
3745 for(i=0;i<*number_of_UNC_in_array;i++) {
3746 temp = ((char *)referrals) + le16_to_cpu(referrals->DfsPathOffset);
3747 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
3748 cifs_strfromUCS_le(*targetUNCs,
3749 (__le16 *) temp, name_len, nls_codepage);
3751 strncpy(*targetUNCs,temp,name_len);
3753 /* BB update target_uncs pointers */
3763 cifs_buf_release(pSMB);
3771 /* Query File System Info such as free space to old servers such as Win 9x */
3773 SMBOldQFSInfo(const int xid, struct cifsTconInfo *tcon, struct kstatfs *FSData)
3775 /* level 0x01 SMB_QUERY_FILE_SYSTEM_INFO */
3776 TRANSACTION2_QFSI_REQ *pSMB = NULL;
3777 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
3778 FILE_SYSTEM_ALLOC_INFO *response_data;
3780 int bytes_returned = 0;
3781 __u16 params, byte_count;
3783 cFYI(1, ("OldQFSInfo"));
3785 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3789 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3794 params = 2; /* level */
3795 pSMB->TotalDataCount = 0;
3796 pSMB->MaxParameterCount = cpu_to_le16(2);
3797 pSMB->MaxDataCount = cpu_to_le16(1000);
3798 pSMB->MaxSetupCount = 0;
3802 pSMB->Reserved2 = 0;
3803 byte_count = params + 1 /* pad */ ;
3804 pSMB->TotalParameterCount = cpu_to_le16(params);
3805 pSMB->ParameterCount = pSMB->TotalParameterCount;
3806 pSMB->ParameterOffset = cpu_to_le16(offsetof(
3807 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
3808 pSMB->DataCount = 0;
3809 pSMB->DataOffset = 0;
3810 pSMB->SetupCount = 1;
3811 pSMB->Reserved3 = 0;
3812 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
3813 pSMB->InformationLevel = cpu_to_le16(SMB_INFO_ALLOCATION);
3814 pSMB->hdr.smb_buf_length += byte_count;
3815 pSMB->ByteCount = cpu_to_le16(byte_count);
3817 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3818 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3820 cFYI(1, ("Send error in QFSInfo = %d", rc));
3821 } else { /* decode response */
3822 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3824 if (rc || (pSMBr->ByteCount < 18))
3825 rc = -EIO; /* bad smb */
3827 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3828 cFYI(1,("qfsinf resp BCC: %d Offset %d",
3829 pSMBr->ByteCount, data_offset));
3832 (FILE_SYSTEM_ALLOC_INFO *)
3833 (((char *) &pSMBr->hdr.Protocol) + data_offset);
3835 le16_to_cpu(response_data->BytesPerSector) *
3836 le32_to_cpu(response_data->
3837 SectorsPerAllocationUnit);
3839 le32_to_cpu(response_data->TotalAllocationUnits);
3840 FSData->f_bfree = FSData->f_bavail =
3841 le32_to_cpu(response_data->FreeAllocationUnits);
3843 ("Blocks: %lld Free: %lld Block size %ld",
3844 (unsigned long long)FSData->f_blocks,
3845 (unsigned long long)FSData->f_bfree,
3849 cifs_buf_release(pSMB);
3852 goto oldQFSInfoRetry;
3858 CIFSSMBQFSInfo(const int xid, struct cifsTconInfo *tcon, struct kstatfs *FSData)
3860 /* level 0x103 SMB_QUERY_FILE_SYSTEM_INFO */
3861 TRANSACTION2_QFSI_REQ *pSMB = NULL;
3862 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
3863 FILE_SYSTEM_INFO *response_data;
3865 int bytes_returned = 0;
3866 __u16 params, byte_count;
3868 cFYI(1, ("In QFSInfo"));
3870 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3875 params = 2; /* level */
3876 pSMB->TotalDataCount = 0;
3877 pSMB->MaxParameterCount = cpu_to_le16(2);
3878 pSMB->MaxDataCount = cpu_to_le16(1000);
3879 pSMB->MaxSetupCount = 0;
3883 pSMB->Reserved2 = 0;
3884 byte_count = params + 1 /* pad */ ;
3885 pSMB->TotalParameterCount = cpu_to_le16(params);
3886 pSMB->ParameterCount = pSMB->TotalParameterCount;
3887 pSMB->ParameterOffset = cpu_to_le16(offsetof(
3888 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
3889 pSMB->DataCount = 0;
3890 pSMB->DataOffset = 0;
3891 pSMB->SetupCount = 1;
3892 pSMB->Reserved3 = 0;
3893 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
3894 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_SIZE_INFO);
3895 pSMB->hdr.smb_buf_length += byte_count;
3896 pSMB->ByteCount = cpu_to_le16(byte_count);
3898 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3899 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3901 cFYI(1, ("Send error in QFSInfo = %d", rc));
3902 } else { /* decode response */
3903 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3905 if (rc || (pSMBr->ByteCount < 24))
3906 rc = -EIO; /* bad smb */
3908 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3912 *) (((char *) &pSMBr->hdr.Protocol) +
3915 le32_to_cpu(response_data->BytesPerSector) *
3916 le32_to_cpu(response_data->
3917 SectorsPerAllocationUnit);
3919 le64_to_cpu(response_data->TotalAllocationUnits);
3920 FSData->f_bfree = FSData->f_bavail =
3921 le64_to_cpu(response_data->FreeAllocationUnits);
3923 ("Blocks: %lld Free: %lld Block size %ld",
3924 (unsigned long long)FSData->f_blocks,
3925 (unsigned long long)FSData->f_bfree,
3929 cifs_buf_release(pSMB);
3938 CIFSSMBQFSAttributeInfo(const int xid, struct cifsTconInfo *tcon)
3940 /* level 0x105 SMB_QUERY_FILE_SYSTEM_INFO */
3941 TRANSACTION2_QFSI_REQ *pSMB = NULL;
3942 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
3943 FILE_SYSTEM_ATTRIBUTE_INFO *response_data;
3945 int bytes_returned = 0;
3946 __u16 params, byte_count;
3948 cFYI(1, ("In QFSAttributeInfo"));
3950 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3955 params = 2; /* level */
3956 pSMB->TotalDataCount = 0;
3957 pSMB->MaxParameterCount = cpu_to_le16(2);
3958 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
3959 pSMB->MaxSetupCount = 0;
3963 pSMB->Reserved2 = 0;
3964 byte_count = params + 1 /* pad */ ;
3965 pSMB->TotalParameterCount = cpu_to_le16(params);
3966 pSMB->ParameterCount = pSMB->TotalParameterCount;
3967 pSMB->ParameterOffset = cpu_to_le16(offsetof(
3968 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
3969 pSMB->DataCount = 0;
3970 pSMB->DataOffset = 0;
3971 pSMB->SetupCount = 1;
3972 pSMB->Reserved3 = 0;
3973 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
3974 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_ATTRIBUTE_INFO);
3975 pSMB->hdr.smb_buf_length += byte_count;
3976 pSMB->ByteCount = cpu_to_le16(byte_count);
3978 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3979 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3981 cERROR(1, ("Send error in QFSAttributeInfo = %d", rc));
3982 } else { /* decode response */
3983 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3985 if (rc || (pSMBr->ByteCount < 13)) { /* BB also check enough bytes returned */
3986 rc = -EIO; /* bad smb */
3988 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3990 (FILE_SYSTEM_ATTRIBUTE_INFO
3991 *) (((char *) &pSMBr->hdr.Protocol) +
3993 memcpy(&tcon->fsAttrInfo, response_data,
3994 sizeof (FILE_SYSTEM_ATTRIBUTE_INFO));
3997 cifs_buf_release(pSMB);
4000 goto QFSAttributeRetry;
4006 CIFSSMBQFSDeviceInfo(const int xid, struct cifsTconInfo *tcon)
4008 /* level 0x104 SMB_QUERY_FILE_SYSTEM_INFO */
4009 TRANSACTION2_QFSI_REQ *pSMB = NULL;
4010 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4011 FILE_SYSTEM_DEVICE_INFO *response_data;
4013 int bytes_returned = 0;
4014 __u16 params, byte_count;
4016 cFYI(1, ("In QFSDeviceInfo"));
4018 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4023 params = 2; /* level */
4024 pSMB->TotalDataCount = 0;
4025 pSMB->MaxParameterCount = cpu_to_le16(2);
4026 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
4027 pSMB->MaxSetupCount = 0;
4031 pSMB->Reserved2 = 0;
4032 byte_count = params + 1 /* pad */ ;
4033 pSMB->TotalParameterCount = cpu_to_le16(params);
4034 pSMB->ParameterCount = pSMB->TotalParameterCount;
4035 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4036 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4038 pSMB->DataCount = 0;
4039 pSMB->DataOffset = 0;
4040 pSMB->SetupCount = 1;
4041 pSMB->Reserved3 = 0;
4042 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4043 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_DEVICE_INFO);
4044 pSMB->hdr.smb_buf_length += byte_count;
4045 pSMB->ByteCount = cpu_to_le16(byte_count);
4047 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4048 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4050 cFYI(1, ("Send error in QFSDeviceInfo = %d", rc));
4051 } else { /* decode response */
4052 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4054 if (rc || (pSMBr->ByteCount < sizeof (FILE_SYSTEM_DEVICE_INFO)))
4055 rc = -EIO; /* bad smb */
4057 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4059 (FILE_SYSTEM_DEVICE_INFO *)
4060 (((char *) &pSMBr->hdr.Protocol) +
4062 memcpy(&tcon->fsDevInfo, response_data,
4063 sizeof (FILE_SYSTEM_DEVICE_INFO));
4066 cifs_buf_release(pSMB);
4069 goto QFSDeviceRetry;
4075 CIFSSMBQFSUnixInfo(const int xid, struct cifsTconInfo *tcon)
4077 /* level 0x200 SMB_QUERY_CIFS_UNIX_INFO */
4078 TRANSACTION2_QFSI_REQ *pSMB = NULL;
4079 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4080 FILE_SYSTEM_UNIX_INFO *response_data;
4082 int bytes_returned = 0;
4083 __u16 params, byte_count;
4085 cFYI(1, ("In QFSUnixInfo"));
4087 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4092 params = 2; /* level */
4093 pSMB->TotalDataCount = 0;
4094 pSMB->DataCount = 0;
4095 pSMB->DataOffset = 0;
4096 pSMB->MaxParameterCount = cpu_to_le16(2);
4097 pSMB->MaxDataCount = cpu_to_le16(100); /* BB find exact max SMB PDU from sess structure BB */
4098 pSMB->MaxSetupCount = 0;
4102 pSMB->Reserved2 = 0;
4103 byte_count = params + 1 /* pad */ ;
4104 pSMB->ParameterCount = cpu_to_le16(params);
4105 pSMB->TotalParameterCount = pSMB->ParameterCount;
4106 pSMB->ParameterOffset = cpu_to_le16(offsetof(struct
4107 smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4108 pSMB->SetupCount = 1;
4109 pSMB->Reserved3 = 0;
4110 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4111 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_CIFS_UNIX_INFO);
4112 pSMB->hdr.smb_buf_length += byte_count;
4113 pSMB->ByteCount = cpu_to_le16(byte_count);
4115 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4116 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4118 cERROR(1, ("Send error in QFSUnixInfo = %d", rc));
4119 } else { /* decode response */
4120 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4122 if (rc || (pSMBr->ByteCount < 13)) {
4123 rc = -EIO; /* bad smb */
4125 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4127 (FILE_SYSTEM_UNIX_INFO
4128 *) (((char *) &pSMBr->hdr.Protocol) +
4130 memcpy(&tcon->fsUnixInfo, response_data,
4131 sizeof (FILE_SYSTEM_UNIX_INFO));
4134 cifs_buf_release(pSMB);
4144 CIFSSMBSetFSUnixInfo(const int xid, struct cifsTconInfo *tcon, __u64 cap)
4146 /* level 0x200 SMB_SET_CIFS_UNIX_INFO */
4147 TRANSACTION2_SETFSI_REQ *pSMB = NULL;
4148 TRANSACTION2_SETFSI_RSP *pSMBr = NULL;
4150 int bytes_returned = 0;
4151 __u16 params, param_offset, offset, byte_count;
4153 cFYI(1, ("In SETFSUnixInfo"));
4155 /* BB switch to small buf init to save memory */
4156 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4161 params = 4; /* 2 bytes zero followed by info level. */
4162 pSMB->MaxSetupCount = 0;
4166 pSMB->Reserved2 = 0;
4167 param_offset = offsetof(struct smb_com_transaction2_setfsi_req, FileNum) - 4;
4168 offset = param_offset + params;
4170 pSMB->MaxParameterCount = cpu_to_le16(4);
4171 pSMB->MaxDataCount = cpu_to_le16(100); /* BB find exact max SMB PDU from sess structure BB */
4172 pSMB->SetupCount = 1;
4173 pSMB->Reserved3 = 0;
4174 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FS_INFORMATION);
4175 byte_count = 1 /* pad */ + params + 12;
4177 pSMB->DataCount = cpu_to_le16(12);
4178 pSMB->ParameterCount = cpu_to_le16(params);
4179 pSMB->TotalDataCount = pSMB->DataCount;
4180 pSMB->TotalParameterCount = pSMB->ParameterCount;
4181 pSMB->ParameterOffset = cpu_to_le16(param_offset);
4182 pSMB->DataOffset = cpu_to_le16(offset);
4186 pSMB->InformationLevel = cpu_to_le16(SMB_SET_CIFS_UNIX_INFO);
4189 pSMB->ClientUnixMajor = cpu_to_le16(CIFS_UNIX_MAJOR_VERSION);
4190 pSMB->ClientUnixMinor = cpu_to_le16(CIFS_UNIX_MINOR_VERSION);
4191 pSMB->ClientUnixCap = cpu_to_le64(cap);
4193 pSMB->hdr.smb_buf_length += byte_count;
4194 pSMB->ByteCount = cpu_to_le16(byte_count);
4196 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4197 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4199 cERROR(1, ("Send error in SETFSUnixInfo = %d", rc));
4200 } else { /* decode response */
4201 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4203 rc = -EIO; /* bad smb */
4206 cifs_buf_release(pSMB);
4209 goto SETFSUnixRetry;
4217 CIFSSMBQFSPosixInfo(const int xid, struct cifsTconInfo *tcon,
4218 struct kstatfs *FSData)
4220 /* level 0x201 SMB_QUERY_CIFS_POSIX_INFO */
4221 TRANSACTION2_QFSI_REQ *pSMB = NULL;
4222 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4223 FILE_SYSTEM_POSIX_INFO *response_data;
4225 int bytes_returned = 0;
4226 __u16 params, byte_count;
4228 cFYI(1, ("In QFSPosixInfo"));
4230 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4235 params = 2; /* level */
4236 pSMB->TotalDataCount = 0;
4237 pSMB->DataCount = 0;
4238 pSMB->DataOffset = 0;
4239 pSMB->MaxParameterCount = cpu_to_le16(2);
4240 pSMB->MaxDataCount = cpu_to_le16(100); /* BB find exact max SMB PDU from sess structure BB */
4241 pSMB->MaxSetupCount = 0;
4245 pSMB->Reserved2 = 0;
4246 byte_count = params + 1 /* pad */ ;
4247 pSMB->ParameterCount = cpu_to_le16(params);
4248 pSMB->TotalParameterCount = pSMB->ParameterCount;
4249 pSMB->ParameterOffset = cpu_to_le16(offsetof(struct
4250 smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4251 pSMB->SetupCount = 1;
4252 pSMB->Reserved3 = 0;
4253 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4254 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_POSIX_FS_INFO);
4255 pSMB->hdr.smb_buf_length += byte_count;
4256 pSMB->ByteCount = cpu_to_le16(byte_count);
4258 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4259 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4261 cFYI(1, ("Send error in QFSUnixInfo = %d", rc));
4262 } else { /* decode response */
4263 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4265 if (rc || (pSMBr->ByteCount < 13)) {
4266 rc = -EIO; /* bad smb */
4268 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4270 (FILE_SYSTEM_POSIX_INFO
4271 *) (((char *) &pSMBr->hdr.Protocol) +
4274 le32_to_cpu(response_data->BlockSize);
4276 le64_to_cpu(response_data->TotalBlocks);
4278 le64_to_cpu(response_data->BlocksAvail);
4279 if(response_data->UserBlocksAvail == cpu_to_le64(-1)) {
4280 FSData->f_bavail = FSData->f_bfree;
4283 le64_to_cpu(response_data->UserBlocksAvail);
4285 if(response_data->TotalFileNodes != cpu_to_le64(-1))
4287 le64_to_cpu(response_data->TotalFileNodes);
4288 if(response_data->FreeFileNodes != cpu_to_le64(-1))
4290 le64_to_cpu(response_data->FreeFileNodes);
4293 cifs_buf_release(pSMB);
4302 /* We can not use write of zero bytes trick to
4303 set file size due to need for large file support. Also note that
4304 this SetPathInfo is preferred to SetFileInfo based method in next
4305 routine which is only needed to work around a sharing violation bug
4306 in Samba which this routine can run into */
4309 CIFSSMBSetEOF(const int xid, struct cifsTconInfo *tcon, const char *fileName,
4310 __u64 size, int SetAllocation,
4311 const struct nls_table *nls_codepage, int remap)
4313 struct smb_com_transaction2_spi_req *pSMB = NULL;
4314 struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
4315 struct file_end_of_file_info *parm_data;
4318 int bytes_returned = 0;
4319 __u16 params, byte_count, data_count, param_offset, offset;
4321 cFYI(1, ("In SetEOF"));
4323 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4328 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4330 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
4331 PATH_MAX, nls_codepage, remap);
4332 name_len++; /* trailing null */
4334 } else { /* BB improve the check for buffer overruns BB */
4335 name_len = strnlen(fileName, PATH_MAX);
4336 name_len++; /* trailing null */
4337 strncpy(pSMB->FileName, fileName, name_len);
4339 params = 6 + name_len;
4340 data_count = sizeof (struct file_end_of_file_info);
4341 pSMB->MaxParameterCount = cpu_to_le16(2);
4342 pSMB->MaxDataCount = cpu_to_le16(4100);
4343 pSMB->MaxSetupCount = 0;
4347 pSMB->Reserved2 = 0;
4348 param_offset = offsetof(struct smb_com_transaction2_spi_req,
4349 InformationLevel) - 4;
4350 offset = param_offset + params;
4352 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
4353 pSMB->InformationLevel =
4354 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2);
4356 pSMB->InformationLevel =
4357 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO);
4358 } else /* Set File Size */ {
4359 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
4360 pSMB->InformationLevel =
4361 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO2);
4363 pSMB->InformationLevel =
4364 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO);
4368 (struct file_end_of_file_info *) (((char *) &pSMB->hdr.Protocol) +
4370 pSMB->ParameterOffset = cpu_to_le16(param_offset);
4371 pSMB->DataOffset = cpu_to_le16(offset);
4372 pSMB->SetupCount = 1;
4373 pSMB->Reserved3 = 0;
4374 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
4375 byte_count = 3 /* pad */ + params + data_count;
4376 pSMB->DataCount = cpu_to_le16(data_count);
4377 pSMB->TotalDataCount = pSMB->DataCount;
4378 pSMB->ParameterCount = cpu_to_le16(params);
4379 pSMB->TotalParameterCount = pSMB->ParameterCount;
4380 pSMB->Reserved4 = 0;
4381 pSMB->hdr.smb_buf_length += byte_count;
4382 parm_data->FileSize = cpu_to_le64(size);
4383 pSMB->ByteCount = cpu_to_le16(byte_count);
4384 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4385 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4387 cFYI(1, ("SetPathInfo (file size) returned %d", rc));
4390 cifs_buf_release(pSMB);
4399 CIFSSMBSetFileSize(const int xid, struct cifsTconInfo *tcon, __u64 size,
4400 __u16 fid, __u32 pid_of_opener, int SetAllocation)
4402 struct smb_com_transaction2_sfi_req *pSMB = NULL;
4403 struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
4405 struct file_end_of_file_info *parm_data;
4407 int bytes_returned = 0;
4408 __u16 params, param_offset, offset, byte_count, count;
4410 cFYI(1, ("SetFileSize (via SetFileInfo) %lld",
4412 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
4417 pSMBr = (struct smb_com_transaction2_sfi_rsp *)pSMB;
4419 pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
4420 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));
4423 pSMB->MaxSetupCount = 0;
4427 pSMB->Reserved2 = 0;
4428 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
4429 offset = param_offset + params;
4431 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
4433 count = sizeof(struct file_end_of_file_info);
4434 pSMB->MaxParameterCount = cpu_to_le16(2);
4435 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB PDU from sess */
4436 pSMB->SetupCount = 1;
4437 pSMB->Reserved3 = 0;
4438 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
4439 byte_count = 3 /* pad */ + params + count;
4440 pSMB->DataCount = cpu_to_le16(count);
4441 pSMB->ParameterCount = cpu_to_le16(params);
4442 pSMB->TotalDataCount = pSMB->DataCount;
4443 pSMB->TotalParameterCount = pSMB->ParameterCount;
4444 pSMB->ParameterOffset = cpu_to_le16(param_offset);
4446 (struct file_end_of_file_info *) (((char *) &pSMB->hdr.Protocol) +
4448 pSMB->DataOffset = cpu_to_le16(offset);
4449 parm_data->FileSize = cpu_to_le64(size);
4452 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
4453 pSMB->InformationLevel =
4454 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2);
4456 pSMB->InformationLevel =
4457 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO);
4458 } else /* Set File Size */ {
4459 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
4460 pSMB->InformationLevel =
4461 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO2);
4463 pSMB->InformationLevel =
4464 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO);
4466 pSMB->Reserved4 = 0;
4467 pSMB->hdr.smb_buf_length += byte_count;
4468 pSMB->ByteCount = cpu_to_le16(byte_count);
4469 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4470 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4473 ("Send error in SetFileInfo (SetFileSize) = %d",
4478 cifs_small_buf_release(pSMB);
4480 /* Note: On -EAGAIN error only caller can retry on handle based calls
4481 since file handle passed in no longer valid */
4486 /* Some legacy servers such as NT4 require that the file times be set on
4487 an open handle, rather than by pathname - this is awkward due to
4488 potential access conflicts on the open, but it is unavoidable for these
4489 old servers since the only other choice is to go from 100 nanosecond DCE
4490 time and resort to the original setpathinfo level which takes the ancient
4491 DOS time format with 2 second granularity */
4493 CIFSSMBSetFileTimes(const int xid, struct cifsTconInfo *tcon, const FILE_BASIC_INFO * data,
4496 struct smb_com_transaction2_sfi_req *pSMB = NULL;
4497 struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
4500 int bytes_returned = 0;
4501 __u16 params, param_offset, offset, byte_count, count;
4503 cFYI(1, ("Set Times (via SetFileInfo)"));
4504 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
4509 pSMBr = (struct smb_com_transaction2_sfi_rsp *)pSMB;
4511 /* At this point there is no need to override the current pid
4512 with the pid of the opener, but that could change if we someday
4513 use an existing handle (rather than opening one on the fly) */
4514 /* pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
4515 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));*/
4518 pSMB->MaxSetupCount = 0;
4522 pSMB->Reserved2 = 0;
4523 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
4524 offset = param_offset + params;
4526 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
4528 count = sizeof (FILE_BASIC_INFO);
4529 pSMB->MaxParameterCount = cpu_to_le16(2);
4530 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB PDU from sess */
4531 pSMB->SetupCount = 1;
4532 pSMB->Reserved3 = 0;
4533 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
4534 byte_count = 3 /* pad */ + params + count;
4535 pSMB->DataCount = cpu_to_le16(count);
4536 pSMB->ParameterCount = cpu_to_le16(params);
4537 pSMB->TotalDataCount = pSMB->DataCount;
4538 pSMB->TotalParameterCount = pSMB->ParameterCount;
4539 pSMB->ParameterOffset = cpu_to_le16(param_offset);
4540 pSMB->DataOffset = cpu_to_le16(offset);
4542 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
4543 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO2);
4545 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO);
4546 pSMB->Reserved4 = 0;
4547 pSMB->hdr.smb_buf_length += byte_count;
4548 pSMB->ByteCount = cpu_to_le16(byte_count);
4549 memcpy(data_offset,data,sizeof(FILE_BASIC_INFO));
4550 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4551 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4553 cFYI(1,("Send error in Set Time (SetFileInfo) = %d",rc));
4556 cifs_small_buf_release(pSMB);
4558 /* Note: On -EAGAIN error only caller can retry on handle based calls
4559 since file handle passed in no longer valid */
4566 CIFSSMBSetTimes(const int xid, struct cifsTconInfo *tcon, const char *fileName,
4567 const FILE_BASIC_INFO * data,
4568 const struct nls_table *nls_codepage, int remap)
4570 TRANSACTION2_SPI_REQ *pSMB = NULL;
4571 TRANSACTION2_SPI_RSP *pSMBr = NULL;
4574 int bytes_returned = 0;
4576 __u16 params, param_offset, offset, byte_count, count;
4578 cFYI(1, ("In SetTimes"));
4581 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4586 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4588 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
4589 PATH_MAX, nls_codepage, remap);
4590 name_len++; /* trailing null */
4592 } else { /* BB improve the check for buffer overruns BB */
4593 name_len = strnlen(fileName, PATH_MAX);
4594 name_len++; /* trailing null */
4595 strncpy(pSMB->FileName, fileName, name_len);
4598 params = 6 + name_len;
4599 count = sizeof (FILE_BASIC_INFO);
4600 pSMB->MaxParameterCount = cpu_to_le16(2);
4601 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
4602 pSMB->MaxSetupCount = 0;
4606 pSMB->Reserved2 = 0;
4607 param_offset = offsetof(struct smb_com_transaction2_spi_req,
4608 InformationLevel) - 4;
4609 offset = param_offset + params;
4610 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
4611 pSMB->ParameterOffset = cpu_to_le16(param_offset);
4612 pSMB->DataOffset = cpu_to_le16(offset);
4613 pSMB->SetupCount = 1;
4614 pSMB->Reserved3 = 0;
4615 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
4616 byte_count = 3 /* pad */ + params + count;
4618 pSMB->DataCount = cpu_to_le16(count);
4619 pSMB->ParameterCount = cpu_to_le16(params);
4620 pSMB->TotalDataCount = pSMB->DataCount;
4621 pSMB->TotalParameterCount = pSMB->ParameterCount;
4622 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
4623 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO2);
4625 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO);
4626 pSMB->Reserved4 = 0;
4627 pSMB->hdr.smb_buf_length += byte_count;
4628 memcpy(data_offset, data, sizeof (FILE_BASIC_INFO));
4629 pSMB->ByteCount = cpu_to_le16(byte_count);
4630 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4631 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4633 cFYI(1, ("SetPathInfo (times) returned %d", rc));
4636 cifs_buf_release(pSMB);
4644 /* Can not be used to set time stamps yet (due to old DOS time format) */
4645 /* Can be used to set attributes */
4646 #if 0 /* Possibly not needed - since it turns out that strangely NT4 has a bug
4647 handling it anyway and NT4 was what we thought it would be needed for
4648 Do not delete it until we prove whether needed for Win9x though */
4650 CIFSSMBSetAttrLegacy(int xid, struct cifsTconInfo *tcon, char *fileName,
4651 __u16 dos_attrs, const struct nls_table *nls_codepage)
4653 SETATTR_REQ *pSMB = NULL;
4654 SETATTR_RSP *pSMBr = NULL;
4659 cFYI(1, ("In SetAttrLegacy"));
4662 rc = smb_init(SMB_COM_SETATTR, 8, tcon, (void **) &pSMB,
4667 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4669 ConvertToUCS((__le16 *) pSMB->fileName, fileName,
4670 PATH_MAX, nls_codepage);
4671 name_len++; /* trailing null */
4673 } else { /* BB improve the check for buffer overruns BB */
4674 name_len = strnlen(fileName, PATH_MAX);
4675 name_len++; /* trailing null */
4676 strncpy(pSMB->fileName, fileName, name_len);
4678 pSMB->attr = cpu_to_le16(dos_attrs);
4679 pSMB->BufferFormat = 0x04;
4680 pSMB->hdr.smb_buf_length += name_len + 1;
4681 pSMB->ByteCount = cpu_to_le16(name_len + 1);
4682 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4683 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4685 cFYI(1, ("Error in LegacySetAttr = %d", rc));
4688 cifs_buf_release(pSMB);
4691 goto SetAttrLgcyRetry;
4695 #endif /* temporarily unneeded SetAttr legacy function */
4698 CIFSSMBUnixSetPerms(const int xid, struct cifsTconInfo *tcon,
4699 char *fileName, __u64 mode, __u64 uid, __u64 gid,
4700 dev_t device, const struct nls_table *nls_codepage,
4703 TRANSACTION2_SPI_REQ *pSMB = NULL;
4704 TRANSACTION2_SPI_RSP *pSMBr = NULL;
4707 int bytes_returned = 0;
4708 FILE_UNIX_BASIC_INFO *data_offset;
4709 __u16 params, param_offset, offset, count, byte_count;
4711 cFYI(1, ("In SetUID/GID/Mode"));
4713 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4718 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4720 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
4721 PATH_MAX, nls_codepage, remap);
4722 name_len++; /* trailing null */
4724 } else { /* BB improve the check for buffer overruns BB */
4725 name_len = strnlen(fileName, PATH_MAX);
4726 name_len++; /* trailing null */
4727 strncpy(pSMB->FileName, fileName, name_len);
4730 params = 6 + name_len;
4731 count = sizeof (FILE_UNIX_BASIC_INFO);
4732 pSMB->MaxParameterCount = cpu_to_le16(2);
4733 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
4734 pSMB->MaxSetupCount = 0;
4738 pSMB->Reserved2 = 0;
4739 param_offset = offsetof(struct smb_com_transaction2_spi_req,
4740 InformationLevel) - 4;
4741 offset = param_offset + params;
4743 (FILE_UNIX_BASIC_INFO *) ((char *) &pSMB->hdr.Protocol +
4745 memset(data_offset, 0, count);
4746 pSMB->DataOffset = cpu_to_le16(offset);
4747 pSMB->ParameterOffset = cpu_to_le16(param_offset);
4748 pSMB->SetupCount = 1;
4749 pSMB->Reserved3 = 0;
4750 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
4751 byte_count = 3 /* pad */ + params + count;
4752 pSMB->ParameterCount = cpu_to_le16(params);
4753 pSMB->DataCount = cpu_to_le16(count);
4754 pSMB->TotalParameterCount = pSMB->ParameterCount;
4755 pSMB->TotalDataCount = pSMB->DataCount;
4756 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_BASIC);
4757 pSMB->Reserved4 = 0;
4758 pSMB->hdr.smb_buf_length += byte_count;
4759 data_offset->Uid = cpu_to_le64(uid);
4760 data_offset->Gid = cpu_to_le64(gid);
4761 /* better to leave device as zero when it is */
4762 data_offset->DevMajor = cpu_to_le64(MAJOR(device));
4763 data_offset->DevMinor = cpu_to_le64(MINOR(device));
4764 data_offset->Permissions = cpu_to_le64(mode);
4767 data_offset->Type = cpu_to_le32(UNIX_FILE);
4768 else if(S_ISDIR(mode))
4769 data_offset->Type = cpu_to_le32(UNIX_DIR);
4770 else if(S_ISLNK(mode))
4771 data_offset->Type = cpu_to_le32(UNIX_SYMLINK);
4772 else if(S_ISCHR(mode))
4773 data_offset->Type = cpu_to_le32(UNIX_CHARDEV);
4774 else if(S_ISBLK(mode))
4775 data_offset->Type = cpu_to_le32(UNIX_BLOCKDEV);
4776 else if(S_ISFIFO(mode))
4777 data_offset->Type = cpu_to_le32(UNIX_FIFO);
4778 else if(S_ISSOCK(mode))
4779 data_offset->Type = cpu_to_le32(UNIX_SOCKET);
4782 pSMB->ByteCount = cpu_to_le16(byte_count);
4783 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4784 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4786 cFYI(1, ("SetPathInfo (perms) returned %d", rc));
4790 cifs_buf_release(pSMB);
4796 int CIFSSMBNotify(const int xid, struct cifsTconInfo *tcon,
4797 const int notify_subdirs, const __u16 netfid,
4798 __u32 filter, struct file * pfile, int multishot,
4799 const struct nls_table *nls_codepage)
4802 struct smb_com_transaction_change_notify_req * pSMB = NULL;
4803 struct smb_com_ntransaction_change_notify_rsp * pSMBr = NULL;
4804 struct dir_notify_req *dnotify_req;
4807 cFYI(1, ("In CIFSSMBNotify for file handle %d",(int)netfid));
4808 rc = smb_init(SMB_COM_NT_TRANSACT, 23, tcon, (void **) &pSMB,
4813 pSMB->TotalParameterCount = 0 ;
4814 pSMB->TotalDataCount = 0;
4815 pSMB->MaxParameterCount = cpu_to_le32(2);
4816 /* BB find exact data count max from sess structure BB */
4817 pSMB->MaxDataCount = 0; /* same in little endian or be */
4818 /* BB VERIFY verify which is correct for above BB */
4819 pSMB->MaxDataCount = cpu_to_le32((tcon->ses->server->maxBuf -
4820 MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
4822 pSMB->MaxSetupCount = 4;
4824 pSMB->ParameterOffset = 0;
4825 pSMB->DataCount = 0;
4826 pSMB->DataOffset = 0;
4827 pSMB->SetupCount = 4; /* single byte does not need le conversion */
4828 pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_NOTIFY_CHANGE);
4829 pSMB->ParameterCount = pSMB->TotalParameterCount;
4831 pSMB->WatchTree = 1; /* one byte - no le conversion needed */
4832 pSMB->Reserved2 = 0;
4833 pSMB->CompletionFilter = cpu_to_le32(filter);
4834 pSMB->Fid = netfid; /* file handle always le */
4835 pSMB->ByteCount = 0;
4837 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4838 (struct smb_hdr *) pSMBr, &bytes_returned, -1);
4840 cFYI(1, ("Error in Notify = %d", rc));
4842 /* Add file to outstanding requests */
4843 /* BB change to kmem cache alloc */
4844 dnotify_req = (struct dir_notify_req *) kmalloc(
4845 sizeof(struct dir_notify_req),
4848 dnotify_req->Pid = pSMB->hdr.Pid;
4849 dnotify_req->PidHigh = pSMB->hdr.PidHigh;
4850 dnotify_req->Mid = pSMB->hdr.Mid;
4851 dnotify_req->Tid = pSMB->hdr.Tid;
4852 dnotify_req->Uid = pSMB->hdr.Uid;
4853 dnotify_req->netfid = netfid;
4854 dnotify_req->pfile = pfile;
4855 dnotify_req->filter = filter;
4856 dnotify_req->multishot = multishot;
4857 spin_lock(&GlobalMid_Lock);
4858 list_add_tail(&dnotify_req->lhead,
4859 &GlobalDnotifyReqList);
4860 spin_unlock(&GlobalMid_Lock);
4864 cifs_buf_release(pSMB);
4867 #ifdef CONFIG_CIFS_XATTR
4869 CIFSSMBQAllEAs(const int xid, struct cifsTconInfo *tcon,
4870 const unsigned char *searchName,
4871 char * EAData, size_t buf_size,
4872 const struct nls_table *nls_codepage, int remap)
4874 /* BB assumes one setup word */
4875 TRANSACTION2_QPI_REQ *pSMB = NULL;
4876 TRANSACTION2_QPI_RSP *pSMBr = NULL;
4880 struct fea * temp_fea;
4882 __u16 params, byte_count;
4884 cFYI(1, ("In Query All EAs path %s", searchName));
4886 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4891 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4893 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
4894 PATH_MAX, nls_codepage, remap);
4895 name_len++; /* trailing null */
4897 } else { /* BB improve the check for buffer overruns BB */
4898 name_len = strnlen(searchName, PATH_MAX);
4899 name_len++; /* trailing null */
4900 strncpy(pSMB->FileName, searchName, name_len);
4903 params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */ ;
4904 pSMB->TotalDataCount = 0;
4905 pSMB->MaxParameterCount = cpu_to_le16(2);
4906 pSMB->MaxDataCount = cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
4907 pSMB->MaxSetupCount = 0;
4911 pSMB->Reserved2 = 0;
4912 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4913 struct smb_com_transaction2_qpi_req ,InformationLevel) - 4);
4914 pSMB->DataCount = 0;
4915 pSMB->DataOffset = 0;
4916 pSMB->SetupCount = 1;
4917 pSMB->Reserved3 = 0;
4918 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
4919 byte_count = params + 1 /* pad */ ;
4920 pSMB->TotalParameterCount = cpu_to_le16(params);
4921 pSMB->ParameterCount = pSMB->TotalParameterCount;
4922 pSMB->InformationLevel = cpu_to_le16(SMB_INFO_QUERY_ALL_EAS);
4923 pSMB->Reserved4 = 0;
4924 pSMB->hdr.smb_buf_length += byte_count;
4925 pSMB->ByteCount = cpu_to_le16(byte_count);
4927 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4928 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4930 cFYI(1, ("Send error in QueryAllEAs = %d", rc));
4931 } else { /* decode response */
4932 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4934 /* BB also check enough total bytes returned */
4935 /* BB we need to improve the validity checking
4936 of these trans2 responses */
4937 if (rc || (pSMBr->ByteCount < 4))
4938 rc = -EIO; /* bad smb */
4939 /* else if (pFindData){
4940 memcpy((char *) pFindData,
4941 (char *) &pSMBr->hdr.Protocol +
4944 /* check that length of list is not more than bcc */
4945 /* check that each entry does not go beyond length
4947 /* check that each element of each entry does not
4948 go beyond end of list */
4949 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4950 struct fealist * ea_response_data;
4952 /* validate_trans2_offsets() */
4953 /* BB to check if(start of smb + data_offset > &bcc+ bcc)*/
4954 ea_response_data = (struct fealist *)
4955 (((char *) &pSMBr->hdr.Protocol) +
4957 name_len = le32_to_cpu(ea_response_data->list_len);
4958 cFYI(1,("ea length %d", name_len));
4960 /* returned EA size zeroed at top of function */
4961 cFYI(1,("empty EA list returned from server"));
4963 /* account for ea list len */
4965 temp_fea = ea_response_data->list;
4966 temp_ptr = (char *)temp_fea;
4967 while(name_len > 0) {
4971 rc += temp_fea->name_len;
4972 /* account for prefix user. and trailing null */
4974 if(rc<(int)buf_size) {
4975 memcpy(EAData,"user.",5);
4977 memcpy(EAData,temp_ptr,temp_fea->name_len);
4978 EAData+=temp_fea->name_len;
4979 /* null terminate name */
4981 EAData = EAData + 1;
4982 } else if(buf_size == 0) {
4983 /* skip copy - calc size only */
4985 /* stop before overrun buffer */
4989 name_len -= temp_fea->name_len;
4990 temp_ptr += temp_fea->name_len;
4991 /* account for trailing null */
4994 value_len = le16_to_cpu(temp_fea->value_len);
4995 name_len -= value_len;
4996 temp_ptr += value_len;
4997 /* BB check that temp_ptr is still within smb BB*/
4998 /* no trailing null to account for in value len */
4999 /* go on to next EA */
5000 temp_fea = (struct fea *)temp_ptr;
5006 cifs_buf_release(pSMB);
5013 ssize_t CIFSSMBQueryEA(const int xid,struct cifsTconInfo * tcon,
5014 const unsigned char * searchName,const unsigned char * ea_name,
5015 unsigned char * ea_value, size_t buf_size,
5016 const struct nls_table *nls_codepage, int remap)
5018 TRANSACTION2_QPI_REQ *pSMB = NULL;
5019 TRANSACTION2_QPI_RSP *pSMBr = NULL;
5023 struct fea * temp_fea;
5025 __u16 params, byte_count;
5027 cFYI(1, ("In Query EA path %s", searchName));
5029 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5034 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5036 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
5037 PATH_MAX, nls_codepage, remap);
5038 name_len++; /* trailing null */
5040 } else { /* BB improve the check for buffer overruns BB */
5041 name_len = strnlen(searchName, PATH_MAX);
5042 name_len++; /* trailing null */
5043 strncpy(pSMB->FileName, searchName, name_len);
5046 params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */ ;
5047 pSMB->TotalDataCount = 0;
5048 pSMB->MaxParameterCount = cpu_to_le16(2);
5049 pSMB->MaxDataCount = cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
5050 pSMB->MaxSetupCount = 0;
5054 pSMB->Reserved2 = 0;
5055 pSMB->ParameterOffset = cpu_to_le16(offsetof(
5056 struct smb_com_transaction2_qpi_req ,InformationLevel) - 4);
5057 pSMB->DataCount = 0;
5058 pSMB->DataOffset = 0;
5059 pSMB->SetupCount = 1;
5060 pSMB->Reserved3 = 0;
5061 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
5062 byte_count = params + 1 /* pad */ ;
5063 pSMB->TotalParameterCount = cpu_to_le16(params);
5064 pSMB->ParameterCount = pSMB->TotalParameterCount;
5065 pSMB->InformationLevel = cpu_to_le16(SMB_INFO_QUERY_ALL_EAS);
5066 pSMB->Reserved4 = 0;
5067 pSMB->hdr.smb_buf_length += byte_count;
5068 pSMB->ByteCount = cpu_to_le16(byte_count);
5070 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5071 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5073 cFYI(1, ("Send error in Query EA = %d", rc));
5074 } else { /* decode response */
5075 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
5077 /* BB also check enough total bytes returned */
5078 /* BB we need to improve the validity checking
5079 of these trans2 responses */
5080 if (rc || (pSMBr->ByteCount < 4))
5081 rc = -EIO; /* bad smb */
5082 /* else if (pFindData){
5083 memcpy((char *) pFindData,
5084 (char *) &pSMBr->hdr.Protocol +
5087 /* check that length of list is not more than bcc */
5088 /* check that each entry does not go beyond length
5090 /* check that each element of each entry does not
5091 go beyond end of list */
5092 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
5093 struct fealist * ea_response_data;
5095 /* validate_trans2_offsets() */
5096 /* BB to check if(start of smb + data_offset > &bcc+ bcc)*/
5097 ea_response_data = (struct fealist *)
5098 (((char *) &pSMBr->hdr.Protocol) +
5100 name_len = le32_to_cpu(ea_response_data->list_len);
5101 cFYI(1,("ea length %d", name_len));
5103 /* returned EA size zeroed at top of function */
5104 cFYI(1,("empty EA list returned from server"));
5106 /* account for ea list len */
5108 temp_fea = ea_response_data->list;
5109 temp_ptr = (char *)temp_fea;
5110 /* loop through checking if we have a matching
5111 name and then return the associated value */
5112 while(name_len > 0) {
5116 value_len = le16_to_cpu(temp_fea->value_len);
5117 /* BB validate that value_len falls within SMB,
5118 even though maximum for name_len is 255 */
5119 if(memcmp(temp_fea->name,ea_name,
5120 temp_fea->name_len) == 0) {
5123 /* account for prefix user. and trailing null */
5124 if(rc<=(int)buf_size) {
5126 temp_fea->name+temp_fea->name_len+1,
5128 /* ea values, unlike ea names,
5129 are not null terminated */
5130 } else if(buf_size == 0) {
5131 /* skip copy - calc size only */
5133 /* stop before overrun buffer */
5138 name_len -= temp_fea->name_len;
5139 temp_ptr += temp_fea->name_len;
5140 /* account for trailing null */
5143 name_len -= value_len;
5144 temp_ptr += value_len;
5145 /* no trailing null to account for in value len */
5146 /* go on to next EA */
5147 temp_fea = (struct fea *)temp_ptr;
5153 cifs_buf_release(pSMB);
5161 CIFSSMBSetEA(const int xid, struct cifsTconInfo *tcon, const char *fileName,
5162 const char * ea_name, const void * ea_value,
5163 const __u16 ea_value_len, const struct nls_table *nls_codepage,
5166 struct smb_com_transaction2_spi_req *pSMB = NULL;
5167 struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
5168 struct fealist *parm_data;
5171 int bytes_returned = 0;
5172 __u16 params, param_offset, byte_count, offset, count;
5174 cFYI(1, ("In SetEA"));
5176 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5181 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5183 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
5184 PATH_MAX, nls_codepage, remap);
5185 name_len++; /* trailing null */
5187 } else { /* BB improve the check for buffer overruns BB */
5188 name_len = strnlen(fileName, PATH_MAX);
5189 name_len++; /* trailing null */
5190 strncpy(pSMB->FileName, fileName, name_len);
5193 params = 6 + name_len;
5195 /* done calculating parms using name_len of file name,
5196 now use name_len to calculate length of ea name
5197 we are going to create in the inode xattrs */
5201 name_len = strnlen(ea_name,255);
5203 count = sizeof(*parm_data) + ea_value_len + name_len + 1;
5204 pSMB->MaxParameterCount = cpu_to_le16(2);
5205 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB size from sess */
5206 pSMB->MaxSetupCount = 0;
5210 pSMB->Reserved2 = 0;
5211 param_offset = offsetof(struct smb_com_transaction2_spi_req,
5212 InformationLevel) - 4;
5213 offset = param_offset + params;
5214 pSMB->InformationLevel =
5215 cpu_to_le16(SMB_SET_FILE_EA);
5218 (struct fealist *) (((char *) &pSMB->hdr.Protocol) +
5220 pSMB->ParameterOffset = cpu_to_le16(param_offset);
5221 pSMB->DataOffset = cpu_to_le16(offset);
5222 pSMB->SetupCount = 1;
5223 pSMB->Reserved3 = 0;
5224 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
5225 byte_count = 3 /* pad */ + params + count;
5226 pSMB->DataCount = cpu_to_le16(count);
5227 parm_data->list_len = cpu_to_le32(count);
5228 parm_data->list[0].EA_flags = 0;
5229 /* we checked above that name len is less than 255 */
5230 parm_data->list[0].name_len = (__u8)name_len;
5231 /* EA names are always ASCII */
5233 strncpy(parm_data->list[0].name,ea_name,name_len);
5234 parm_data->list[0].name[name_len] = 0;
5235 parm_data->list[0].value_len = cpu_to_le16(ea_value_len);
5236 /* caller ensures that ea_value_len is less than 64K but
5237 we need to ensure that it fits within the smb */
5239 /*BB add length check that it would fit in negotiated SMB buffer size BB */
5240 /* if(ea_value_len > buffer_size - 512 (enough for header)) */
5242 memcpy(parm_data->list[0].name+name_len+1,ea_value,ea_value_len);
5244 pSMB->TotalDataCount = pSMB->DataCount;
5245 pSMB->ParameterCount = cpu_to_le16(params);
5246 pSMB->TotalParameterCount = pSMB->ParameterCount;
5247 pSMB->Reserved4 = 0;
5248 pSMB->hdr.smb_buf_length += byte_count;
5249 pSMB->ByteCount = cpu_to_le16(byte_count);
5250 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5251 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5253 cFYI(1, ("SetPathInfo (EA) returned %d", rc));
5256 cifs_buf_release(pSMB);