4 * Copyright (C) International Business Machines Corp., 2002,2006
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 {LANMAN2_PROT, "\2LANMAN2.1"},
63 #endif /* weak password hashing for legacy clients */
64 {CIFS_PROT, "\2NT LM 0.12"},
69 /* define the number of elements in the cifs dialect array */
70 #ifdef CONFIG_CIFS_POSIX
71 #ifdef CONFIG_CIFS_WEAK_PW_HASH
72 #define CIFS_NUM_PROT 4
74 #define CIFS_NUM_PROT 2
75 #endif /* CIFS_WEAK_PW_HASH */
77 #ifdef CONFIG_CIFS_WEAK_PW_HASH
78 #define CIFS_NUM_PROT 3
80 #define CIFS_NUM_PROT 1
81 #endif /* CONFIG_CIFS_WEAK_PW_HASH */
82 #endif /* CIFS_POSIX */
85 /* Mark as invalid, all open files on tree connections since they
86 were closed when session to server was lost */
87 static void mark_open_files_invalid(struct cifsTconInfo * pTcon)
89 struct cifsFileInfo *open_file = NULL;
90 struct list_head * tmp;
91 struct list_head * tmp1;
93 /* list all files open on tree connection and mark them invalid */
94 write_lock(&GlobalSMBSeslock);
95 list_for_each_safe(tmp, tmp1, &pTcon->openFileList) {
96 open_file = list_entry(tmp,struct cifsFileInfo, tlist);
98 open_file->invalidHandle = TRUE;
101 write_unlock(&GlobalSMBSeslock);
102 /* BB Add call to invalidate_inodes(sb) for all superblocks mounted
106 /* If the return code is zero, this function must fill in request_buf pointer */
108 small_smb_init(int smb_command, int wct, struct cifsTconInfo *tcon,
109 void **request_buf /* returned */)
113 /* SMBs NegProt, SessSetup, uLogoff do not have tcon yet so
114 check for tcp and smb session status done differently
115 for those three - in the calling routine */
117 if(tcon->tidStatus == CifsExiting) {
118 /* only tree disconnect, open, and write,
119 (and ulogoff which does not have tcon)
120 are allowed as we start force umount */
121 if((smb_command != SMB_COM_WRITE_ANDX) &&
122 (smb_command != SMB_COM_OPEN_ANDX) &&
123 (smb_command != SMB_COM_TREE_DISCONNECT)) {
124 cFYI(1,("can not send cmd %d while umounting",
129 if((tcon->ses) && (tcon->ses->status != CifsExiting) &&
130 (tcon->ses->server)){
131 struct nls_table *nls_codepage;
132 /* Give Demultiplex thread up to 10 seconds to
133 reconnect, should be greater than cifs socket
134 timeout which is 7 seconds */
135 while(tcon->ses->server->tcpStatus == CifsNeedReconnect) {
136 wait_event_interruptible_timeout(tcon->ses->server->response_q,
137 (tcon->ses->server->tcpStatus == CifsGood), 10 * HZ);
138 if(tcon->ses->server->tcpStatus == CifsNeedReconnect) {
139 /* on "soft" mounts we wait once */
140 if((tcon->retry == FALSE) ||
141 (tcon->ses->status == CifsExiting)) {
142 cFYI(1,("gave up waiting on reconnect in smb_init"));
144 } /* else "hard" mount - keep retrying
145 until process is killed or server
146 comes back on-line */
147 } else /* TCP session is reestablished now */
152 nls_codepage = load_nls_default();
153 /* need to prevent multiple threads trying to
154 simultaneously reconnect the same SMB session */
155 down(&tcon->ses->sesSem);
156 if(tcon->ses->status == CifsNeedReconnect)
157 rc = cifs_setup_session(0, tcon->ses,
159 if(!rc && (tcon->tidStatus == CifsNeedReconnect)) {
160 mark_open_files_invalid(tcon);
161 rc = CIFSTCon(0, tcon->ses, tcon->treeName, tcon
163 up(&tcon->ses->sesSem);
164 /* BB FIXME add code to check if wsize needs
165 update due to negotiated smb buffer size
168 atomic_inc(&tconInfoReconnectCount);
170 cFYI(1, ("reconnect tcon rc = %d", rc));
171 /* Removed call to reopen open files here -
172 it is safer (and faster) to reopen files
173 one at a time as needed in read and write */
175 /* Check if handle based operation so we
176 know whether we can continue or not without
177 returning to caller to reset file handle */
178 switch(smb_command) {
179 case SMB_COM_READ_ANDX:
180 case SMB_COM_WRITE_ANDX:
182 case SMB_COM_FIND_CLOSE2:
183 case SMB_COM_LOCKING_ANDX: {
184 unload_nls(nls_codepage);
189 up(&tcon->ses->sesSem);
191 unload_nls(nls_codepage);
200 *request_buf = cifs_small_buf_get();
201 if (*request_buf == NULL) {
202 /* BB should we add a retry in here if not a writepage? */
206 header_assemble((struct smb_hdr *) *request_buf, smb_command, tcon,wct);
209 cifs_stats_inc(&tcon->num_smbs_sent);
215 small_smb_init_no_tc(const int smb_command, const int wct,
216 struct cifsSesInfo *ses, void **request_buf)
219 struct smb_hdr * buffer;
221 rc = small_smb_init(smb_command, wct, NULL, request_buf);
225 buffer = (struct smb_hdr *)*request_buf;
226 buffer->Mid = GetNextMid(ses->server);
227 if (ses->capabilities & CAP_UNICODE)
228 buffer->Flags2 |= SMBFLG2_UNICODE;
229 if (ses->capabilities & CAP_STATUS32)
230 buffer->Flags2 |= SMBFLG2_ERR_STATUS;
232 /* uid, tid can stay at zero as set in header assemble */
234 /* BB add support for turning on the signing when
235 this function is used after 1st of session setup requests */
240 /* If the return code is zero, this function must fill in request_buf pointer */
242 smb_init(int smb_command, int wct, struct cifsTconInfo *tcon,
243 void **request_buf /* returned */ ,
244 void **response_buf /* returned */ )
248 /* SMBs NegProt, SessSetup, uLogoff do not have tcon yet so
249 check for tcp and smb session status done differently
250 for those three - in the calling routine */
252 if(tcon->tidStatus == CifsExiting) {
253 /* only tree disconnect, open, and write,
254 (and ulogoff which does not have tcon)
255 are allowed as we start force umount */
256 if((smb_command != SMB_COM_WRITE_ANDX) &&
257 (smb_command != SMB_COM_OPEN_ANDX) &&
258 (smb_command != SMB_COM_TREE_DISCONNECT)) {
259 cFYI(1,("can not send cmd %d while umounting",
265 if((tcon->ses) && (tcon->ses->status != CifsExiting) &&
266 (tcon->ses->server)){
267 struct nls_table *nls_codepage;
268 /* Give Demultiplex thread up to 10 seconds to
269 reconnect, should be greater than cifs socket
270 timeout which is 7 seconds */
271 while(tcon->ses->server->tcpStatus == CifsNeedReconnect) {
272 wait_event_interruptible_timeout(tcon->ses->server->response_q,
273 (tcon->ses->server->tcpStatus == CifsGood), 10 * HZ);
274 if(tcon->ses->server->tcpStatus ==
276 /* on "soft" mounts we wait once */
277 if((tcon->retry == FALSE) ||
278 (tcon->ses->status == CifsExiting)) {
279 cFYI(1,("gave up waiting on reconnect in smb_init"));
281 } /* else "hard" mount - keep retrying
282 until process is killed or server
284 } else /* TCP session is reestablished now */
289 nls_codepage = load_nls_default();
290 /* need to prevent multiple threads trying to
291 simultaneously reconnect the same SMB session */
292 down(&tcon->ses->sesSem);
293 if(tcon->ses->status == CifsNeedReconnect)
294 rc = cifs_setup_session(0, tcon->ses,
296 if(!rc && (tcon->tidStatus == CifsNeedReconnect)) {
297 mark_open_files_invalid(tcon);
298 rc = CIFSTCon(0, tcon->ses, tcon->treeName,
300 up(&tcon->ses->sesSem);
301 /* BB FIXME add code to check if wsize needs
302 update due to negotiated smb buffer size
305 atomic_inc(&tconInfoReconnectCount);
307 cFYI(1, ("reconnect tcon rc = %d", rc));
308 /* Removed call to reopen open files here -
309 it is safer (and faster) to reopen files
310 one at a time as needed in read and write */
312 /* Check if handle based operation so we
313 know whether we can continue or not without
314 returning to caller to reset file handle */
315 switch(smb_command) {
316 case SMB_COM_READ_ANDX:
317 case SMB_COM_WRITE_ANDX:
319 case SMB_COM_FIND_CLOSE2:
320 case SMB_COM_LOCKING_ANDX: {
321 unload_nls(nls_codepage);
326 up(&tcon->ses->sesSem);
328 unload_nls(nls_codepage);
337 *request_buf = cifs_buf_get();
338 if (*request_buf == NULL) {
339 /* BB should we add a retry in here if not a writepage? */
342 /* Although the original thought was we needed the response buf for */
343 /* potential retries of smb operations it turns out we can determine */
344 /* from the mid flags when the request buffer can be resent without */
345 /* having to use a second distinct buffer for the response */
347 *response_buf = *request_buf;
349 header_assemble((struct smb_hdr *) *request_buf, smb_command, tcon,
353 cifs_stats_inc(&tcon->num_smbs_sent);
358 static int validate_t2(struct smb_t2_rsp * pSMB)
364 /* check for plausible wct, bcc and t2 data and parm sizes */
365 /* check for parm and data offset going beyond end of smb */
366 if(pSMB->hdr.WordCount >= 10) {
367 if((le16_to_cpu(pSMB->t2_rsp.ParameterOffset) <= 1024) &&
368 (le16_to_cpu(pSMB->t2_rsp.DataOffset) <= 1024)) {
369 /* check that bcc is at least as big as parms + data */
370 /* check that bcc is less than negotiated smb buffer */
371 total_size = le16_to_cpu(pSMB->t2_rsp.ParameterCount);
372 if(total_size < 512) {
373 total_size+=le16_to_cpu(pSMB->t2_rsp.DataCount);
374 /* BCC le converted in SendReceive */
375 pBCC = (pSMB->hdr.WordCount * 2) +
376 sizeof(struct smb_hdr) +
378 if((total_size <= (*(u16 *)pBCC)) &&
380 CIFSMaxBufSize+MAX_CIFS_HDR_SIZE)) {
387 cifs_dump_mem("Invalid transact2 SMB: ",(char *)pSMB,
388 sizeof(struct smb_t2_rsp) + 16);
392 CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses)
395 NEGOTIATE_RSP *pSMBr;
399 struct TCP_Server_Info * server;
401 unsigned int secFlags;
404 server = ses->server;
409 rc = smb_init(SMB_COM_NEGOTIATE, 0, NULL /* no tcon yet */ ,
410 (void **) &pSMB, (void **) &pSMBr);
414 /* if any of auth flags (ie not sign or seal) are overriden use them */
415 if(ses->overrideSecFlg & (~(CIFSSEC_MUST_SIGN | CIFSSEC_MUST_SEAL)))
416 secFlags = ses->overrideSecFlg;
417 else /* if override flags set only sign/seal OR them with global auth */
418 secFlags = extended_security | ses->overrideSecFlg;
420 cFYI(1,("secFlags 0x%x",secFlags));
422 pSMB->hdr.Mid = GetNextMid(server);
423 pSMB->hdr.Flags2 |= SMBFLG2_UNICODE;
424 if((secFlags & CIFSSEC_MUST_KRB5) == CIFSSEC_MUST_KRB5)
425 pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC;
428 for(i=0;i<CIFS_NUM_PROT;i++) {
429 strncpy(pSMB->DialectsArray+count, protocols[i].name, 16);
430 count += strlen(protocols[i].name) + 1;
431 /* null at end of source and target buffers anyway */
433 pSMB->hdr.smb_buf_length += count;
434 pSMB->ByteCount = cpu_to_le16(count);
436 rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB,
437 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
441 cFYI(1,("Dialect: %d", pSMBr->DialectIndex));
442 /* Check wct = 1 error case */
443 if((pSMBr->hdr.WordCount < 13) || (pSMBr->DialectIndex == BAD_PROT)) {
444 /* core returns wct = 1, but we do not ask for core - otherwise
445 small wct just comes when dialect index is -1 indicating we
446 could not negotiate a common dialect */
449 #ifdef CONFIG_CIFS_WEAK_PW_HASH
450 } else if((pSMBr->hdr.WordCount == 13)
451 && ((pSMBr->DialectIndex == LANMAN_PROT)
452 || (pSMBr->DialectIndex == LANMAN2_PROT))) {
454 struct lanman_neg_rsp * rsp = (struct lanman_neg_rsp *)pSMBr;
456 if((secFlags & CIFSSEC_MAY_LANMAN) ||
457 (secFlags & CIFSSEC_MAY_PLNTXT))
458 server->secType = LANMAN;
460 cERROR(1, ("mount failed weak security disabled"
461 " in /proc/fs/cifs/SecurityFlags"));
465 server->secMode = (__u8)le16_to_cpu(rsp->SecurityMode);
466 server->maxReq = le16_to_cpu(rsp->MaxMpxCount);
467 server->maxBuf = min((__u32)le16_to_cpu(rsp->MaxBufSize),
468 (__u32)CIFSMaxBufSize + MAX_CIFS_HDR_SIZE);
469 GETU32(server->sessid) = le32_to_cpu(rsp->SessionKey);
470 /* even though we do not use raw we might as well set this
471 accurately, in case we ever find a need for it */
472 if((le16_to_cpu(rsp->RawMode) & RAW_ENABLE) == RAW_ENABLE) {
473 server->maxRw = 0xFF00;
474 server->capabilities = CAP_MPX_MODE | CAP_RAW_MODE;
476 server->maxRw = 0;/* we do not need to use raw anyway */
477 server->capabilities = CAP_MPX_MODE;
479 tmp = le16_to_cpu(rsp->ServerTimeZone);
480 if (tmp == (int)0xffff) {
481 /* OS/2 often does not set timezone therefore
482 * we must use server time to calc time zone.
483 * Could deviate slightly from the right zone. Not easy
484 * to adjust, since timezones are not always a multiple
485 * of 60 (sometimes 30 minutes - are there smaller?)
487 struct timespec ts, utc;
489 ts = cnvrtDosUnixTm(le16_to_cpu(rsp->SrvTime.Date),
490 le16_to_cpu(rsp->SrvTime.Time));
491 cFYI(1,("SrvTime: %d sec since 1970 (utc: %d) diff: %d",
492 (int)ts.tv_sec, (int)utc.tv_sec,
493 (int)(utc.tv_sec - ts.tv_sec)));
494 tmp = (int)(utc.tv_sec - ts.tv_sec);
495 adjust = tmp < 0 ? -29 : 29;
496 tmp = ((tmp + adjust) / 60) * 60;
497 server->timeAdj = tmp;
499 server->timeAdj = tmp * 60; /* also in seconds */
501 cFYI(1,("server->timeAdj: %d seconds", server->timeAdj));
504 /* BB get server time for time conversions and add
505 code to use it and timezone since this is not UTC */
507 if (rsp->EncryptionKeyLength ==
508 cpu_to_le16(CIFS_CRYPTO_KEY_SIZE)) {
509 memcpy(server->cryptKey, rsp->EncryptionKey,
510 CIFS_CRYPTO_KEY_SIZE);
511 } else if (server->secMode & SECMODE_PW_ENCRYPT) {
512 rc = -EIO; /* need cryptkey unless plain text */
516 cFYI(1,("LANMAN negotiated"));
517 /* we will not end up setting signing flags - as no signing
518 was in LANMAN and server did not return the flags on */
520 #else /* weak security disabled */
521 } else if(pSMBr->hdr.WordCount == 13) {
522 cERROR(1,("mount failed, cifs module not built "
523 "with CIFS_WEAK_PW_HASH support"));
525 #endif /* WEAK_PW_HASH */
527 } else if(pSMBr->hdr.WordCount != 17) {
532 /* else wct == 17 NTLM */
533 server->secMode = pSMBr->SecurityMode;
534 if((server->secMode & SECMODE_USER) == 0)
535 cFYI(1,("share mode security"));
537 if((server->secMode & SECMODE_PW_ENCRYPT) == 0)
538 #ifdef CONFIG_CIFS_WEAK_PW_HASH
539 if ((secFlags & CIFSSEC_MAY_PLNTXT) == 0)
540 #endif /* CIFS_WEAK_PW_HASH */
541 cERROR(1,("Server requests plain text password"
542 " but client support disabled"));
544 if((secFlags & CIFSSEC_MUST_NTLMV2) == CIFSSEC_MUST_NTLMV2)
545 server->secType = NTLMv2;
546 else if(secFlags & CIFSSEC_MAY_NTLM)
547 server->secType = NTLM;
548 else if(secFlags & CIFSSEC_MAY_NTLMV2)
549 server->secType = NTLMv2;
550 /* else krb5 ... any others ... */
552 /* one byte, so no need to convert this or EncryptionKeyLen from
554 server->maxReq = le16_to_cpu(pSMBr->MaxMpxCount);
555 /* probably no need to store and check maxvcs */
556 server->maxBuf = min(le32_to_cpu(pSMBr->MaxBufferSize),
557 (__u32) CIFSMaxBufSize + MAX_CIFS_HDR_SIZE);
558 server->maxRw = le32_to_cpu(pSMBr->MaxRawSize);
559 cFYI(0, ("Max buf = %d", ses->server->maxBuf));
560 GETU32(ses->server->sessid) = le32_to_cpu(pSMBr->SessionKey);
561 server->capabilities = le32_to_cpu(pSMBr->Capabilities);
562 server->timeAdj = le16_to_cpu(pSMBr->ServerTimeZone) * 60;
563 if (pSMBr->EncryptionKeyLength == CIFS_CRYPTO_KEY_SIZE) {
564 memcpy(server->cryptKey, pSMBr->u.EncryptionKey,
565 CIFS_CRYPTO_KEY_SIZE);
566 } else if ((pSMBr->hdr.Flags2 & SMBFLG2_EXT_SEC)
567 && (pSMBr->EncryptionKeyLength == 0)) {
568 /* decode security blob */
569 } else if (server->secMode & SECMODE_PW_ENCRYPT) {
570 rc = -EIO; /* no crypt key only if plain text pwd */
574 /* BB might be helpful to save off the domain of server here */
576 if ((pSMBr->hdr.Flags2 & SMBFLG2_EXT_SEC) &&
577 (server->capabilities & CAP_EXTENDED_SECURITY)) {
578 count = pSMBr->ByteCount;
581 else if (count == 16) {
582 server->secType = RawNTLMSSP;
583 if (server->socketUseCount.counter > 1) {
584 if (memcmp(server->server_GUID,
585 pSMBr->u.extended_response.
587 cFYI(1, ("server UID changed"));
588 memcpy(server->server_GUID,
589 pSMBr->u.extended_response.GUID,
593 memcpy(server->server_GUID,
594 pSMBr->u.extended_response.GUID, 16);
596 rc = decode_negTokenInit(pSMBr->u.extended_response.
601 /* BB Need to fill struct for sessetup here */
608 server->capabilities &= ~CAP_EXTENDED_SECURITY;
610 #ifdef CONFIG_CIFS_WEAK_PW_HASH
613 if(sign_CIFS_PDUs == FALSE) {
614 if(server->secMode & SECMODE_SIGN_REQUIRED)
615 cERROR(1,("Server requires "
616 "/proc/fs/cifs/PacketSigningEnabled to be on"));
618 ~(SECMODE_SIGN_ENABLED | SECMODE_SIGN_REQUIRED);
619 } else if(sign_CIFS_PDUs == 1) {
620 if((server->secMode & SECMODE_SIGN_REQUIRED) == 0)
622 ~(SECMODE_SIGN_ENABLED | SECMODE_SIGN_REQUIRED);
623 } else if(sign_CIFS_PDUs == 2) {
624 if((server->secMode &
625 (SECMODE_SIGN_ENABLED | SECMODE_SIGN_REQUIRED)) == 0) {
626 cERROR(1,("signing required but server lacks support"));
630 cifs_buf_release(pSMB);
632 cFYI(1,("negprot rc %d",rc));
637 CIFSSMBTDis(const int xid, struct cifsTconInfo *tcon)
639 struct smb_hdr *smb_buffer;
640 struct smb_hdr *smb_buffer_response; /* BB removeme BB */
644 cFYI(1, ("In tree disconnect"));
646 * If last user of the connection and
647 * connection alive - disconnect it
648 * If this is the last connection on the server session disconnect it
649 * (and inside session disconnect we should check if tcp socket needs
650 * to be freed and kernel thread woken up).
653 down(&tcon->tconSem);
657 atomic_dec(&tcon->useCount);
658 if (atomic_read(&tcon->useCount) > 0) {
663 /* No need to return error on this operation if tid invalidated and
664 closed on server already e.g. due to tcp session crashing */
665 if(tcon->tidStatus == CifsNeedReconnect) {
670 if((tcon->ses == NULL) || (tcon->ses->server == NULL)) {
674 rc = small_smb_init(SMB_COM_TREE_DISCONNECT, 0, tcon,
675 (void **)&smb_buffer);
680 smb_buffer_response = smb_buffer; /* BB removeme BB */
682 rc = SendReceive(xid, tcon->ses, smb_buffer, smb_buffer_response,
685 cFYI(1, ("Tree disconnect failed %d", rc));
688 cifs_small_buf_release(smb_buffer);
691 /* No need to return error on this operation if tid invalidated and
692 closed on server already e.g. due to tcp session crashing */
700 CIFSSMBLogoff(const int xid, struct cifsSesInfo *ses)
702 struct smb_hdr *smb_buffer_response;
703 LOGOFF_ANDX_REQ *pSMB;
707 cFYI(1, ("In SMBLogoff for session disconnect"));
713 atomic_dec(&ses->inUse);
714 if (atomic_read(&ses->inUse) > 0) {
718 rc = small_smb_init(SMB_COM_LOGOFF_ANDX, 2, NULL, (void **)&pSMB);
724 smb_buffer_response = (struct smb_hdr *)pSMB; /* BB removeme BB */
727 pSMB->hdr.Mid = GetNextMid(ses->server);
729 if(ses->server->secMode &
730 (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
731 pSMB->hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
734 pSMB->hdr.Uid = ses->Suid;
736 pSMB->AndXCommand = 0xFF;
737 rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB,
738 smb_buffer_response, &length, 0);
740 atomic_dec(&ses->server->socketUseCount);
741 if (atomic_read(&ses->server->socketUseCount) == 0) {
742 spin_lock(&GlobalMid_Lock);
743 ses->server->tcpStatus = CifsExiting;
744 spin_unlock(&GlobalMid_Lock);
749 cifs_small_buf_release(pSMB);
751 /* if session dead then we do not need to do ulogoff,
752 since server closed smb session, no sense reporting
760 CIFSSMBDelFile(const int xid, struct cifsTconInfo *tcon, const char *fileName,
761 const struct nls_table *nls_codepage, int remap)
763 DELETE_FILE_REQ *pSMB = NULL;
764 DELETE_FILE_RSP *pSMBr = NULL;
770 rc = smb_init(SMB_COM_DELETE, 1, tcon, (void **) &pSMB,
775 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
777 cifsConvertToUCS((__le16 *) pSMB->fileName, fileName,
778 PATH_MAX, nls_codepage, remap);
779 name_len++; /* trailing null */
781 } else { /* BB improve check for buffer overruns BB */
782 name_len = strnlen(fileName, PATH_MAX);
783 name_len++; /* trailing null */
784 strncpy(pSMB->fileName, fileName, name_len);
786 pSMB->SearchAttributes =
787 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM);
788 pSMB->BufferFormat = 0x04;
789 pSMB->hdr.smb_buf_length += name_len + 1;
790 pSMB->ByteCount = cpu_to_le16(name_len + 1);
791 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
792 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
793 cifs_stats_inc(&tcon->num_deletes);
795 cFYI(1, ("Error in RMFile = %d", rc));
798 cifs_buf_release(pSMB);
806 CIFSSMBRmDir(const int xid, struct cifsTconInfo *tcon, const char *dirName,
807 const struct nls_table *nls_codepage, int remap)
809 DELETE_DIRECTORY_REQ *pSMB = NULL;
810 DELETE_DIRECTORY_RSP *pSMBr = NULL;
815 cFYI(1, ("In CIFSSMBRmDir"));
817 rc = smb_init(SMB_COM_DELETE_DIRECTORY, 0, tcon, (void **) &pSMB,
822 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
823 name_len = cifsConvertToUCS((__le16 *) pSMB->DirName, dirName,
824 PATH_MAX, nls_codepage, remap);
825 name_len++; /* trailing null */
827 } else { /* BB improve check for buffer overruns BB */
828 name_len = strnlen(dirName, PATH_MAX);
829 name_len++; /* trailing null */
830 strncpy(pSMB->DirName, dirName, name_len);
833 pSMB->BufferFormat = 0x04;
834 pSMB->hdr.smb_buf_length += name_len + 1;
835 pSMB->ByteCount = cpu_to_le16(name_len + 1);
836 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
837 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
838 cifs_stats_inc(&tcon->num_rmdirs);
840 cFYI(1, ("Error in RMDir = %d", rc));
843 cifs_buf_release(pSMB);
850 CIFSSMBMkDir(const int xid, struct cifsTconInfo *tcon,
851 const char *name, const struct nls_table *nls_codepage, int remap)
854 CREATE_DIRECTORY_REQ *pSMB = NULL;
855 CREATE_DIRECTORY_RSP *pSMBr = NULL;
859 cFYI(1, ("In CIFSSMBMkDir"));
861 rc = smb_init(SMB_COM_CREATE_DIRECTORY, 0, tcon, (void **) &pSMB,
866 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
867 name_len = cifsConvertToUCS((__le16 *) pSMB->DirName, name,
868 PATH_MAX, nls_codepage, remap);
869 name_len++; /* trailing null */
871 } else { /* BB improve check for buffer overruns BB */
872 name_len = strnlen(name, PATH_MAX);
873 name_len++; /* trailing null */
874 strncpy(pSMB->DirName, name, name_len);
877 pSMB->BufferFormat = 0x04;
878 pSMB->hdr.smb_buf_length += name_len + 1;
879 pSMB->ByteCount = cpu_to_le16(name_len + 1);
880 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
881 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
882 cifs_stats_inc(&tcon->num_mkdirs);
884 cFYI(1, ("Error in Mkdir = %d", rc));
887 cifs_buf_release(pSMB);
893 static __u16 convert_disposition(int disposition)
897 switch (disposition) {
899 ofun = SMBOPEN_OCREATE | SMBOPEN_OTRUNC;
902 ofun = SMBOPEN_OAPPEND;
905 ofun = SMBOPEN_OCREATE;
908 ofun = SMBOPEN_OCREATE | SMBOPEN_OAPPEND;
911 ofun = SMBOPEN_OTRUNC;
913 case FILE_OVERWRITE_IF:
914 ofun = SMBOPEN_OCREATE | SMBOPEN_OTRUNC;
917 cFYI(1,("unknown disposition %d",disposition));
918 ofun = SMBOPEN_OAPPEND; /* regular open */
924 SMBLegacyOpen(const int xid, struct cifsTconInfo *tcon,
925 const char *fileName, const int openDisposition,
926 const int access_flags, const int create_options, __u16 * netfid,
927 int *pOplock, FILE_ALL_INFO * pfile_info,
928 const struct nls_table *nls_codepage, int remap)
931 OPENX_REQ *pSMB = NULL;
932 OPENX_RSP *pSMBr = NULL;
938 rc = smb_init(SMB_COM_OPEN_ANDX, 15, tcon, (void **) &pSMB,
943 pSMB->AndXCommand = 0xFF; /* none */
945 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
946 count = 1; /* account for one byte pad to word boundary */
948 cifsConvertToUCS((__le16 *) (pSMB->fileName + 1),
949 fileName, PATH_MAX, nls_codepage, remap);
950 name_len++; /* trailing null */
952 } else { /* BB improve check for buffer overruns BB */
953 count = 0; /* no pad */
954 name_len = strnlen(fileName, PATH_MAX);
955 name_len++; /* trailing null */
956 strncpy(pSMB->fileName, fileName, name_len);
958 if (*pOplock & REQ_OPLOCK)
959 pSMB->OpenFlags = cpu_to_le16(REQ_OPLOCK);
960 else if (*pOplock & REQ_BATCHOPLOCK) {
961 pSMB->OpenFlags = cpu_to_le16(REQ_BATCHOPLOCK);
963 pSMB->OpenFlags |= cpu_to_le16(REQ_MORE_INFO);
964 /* BB fixme add conversion for access_flags to bits 0 - 2 of mode */
970 pSMB->Mode = cpu_to_le16(2);
971 pSMB->Mode |= cpu_to_le16(0x40); /* deny none */
972 /* set file as system file if special file such
973 as fifo and server expecting SFU style and
974 no Unix extensions */
976 if(create_options & CREATE_OPTION_SPECIAL)
977 pSMB->FileAttributes = cpu_to_le16(ATTR_SYSTEM);
979 pSMB->FileAttributes = cpu_to_le16(0/*ATTR_NORMAL*/); /* BB FIXME */
981 /* if ((omode & S_IWUGO) == 0)
982 pSMB->FileAttributes |= cpu_to_le32(ATTR_READONLY);*/
983 /* Above line causes problems due to vfs splitting create into two
984 pieces - need to set mode after file created not while it is
988 /* pSMB->CreateOptions = cpu_to_le32(create_options & CREATE_OPTIONS_MASK); */
989 /* BB FIXME END BB */
991 pSMB->Sattr = cpu_to_le16(ATTR_HIDDEN | ATTR_SYSTEM | ATTR_DIRECTORY);
992 pSMB->OpenFunction = cpu_to_le16(convert_disposition(openDisposition));
994 pSMB->hdr.smb_buf_length += count;
996 pSMB->ByteCount = cpu_to_le16(count);
997 /* long_op set to 1 to allow for oplock break timeouts */
998 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
999 (struct smb_hdr *) pSMBr, &bytes_returned, 1);
1000 cifs_stats_inc(&tcon->num_opens);
1002 cFYI(1, ("Error in Open = %d", rc));
1004 /* BB verify if wct == 15 */
1006 /* *pOplock = pSMBr->OplockLevel; */ /* BB take from action field BB */
1008 *netfid = pSMBr->Fid; /* cifs fid stays in le */
1009 /* Let caller know file was created so we can set the mode. */
1010 /* Do we care about the CreateAction in any other cases? */
1012 /* if(cpu_to_le32(FILE_CREATE) == pSMBr->CreateAction)
1013 *pOplock |= CIFS_CREATE_ACTION; */
1017 pfile_info->CreationTime = 0; /* BB convert CreateTime*/
1018 pfile_info->LastAccessTime = 0; /* BB fixme */
1019 pfile_info->LastWriteTime = 0; /* BB fixme */
1020 pfile_info->ChangeTime = 0; /* BB fixme */
1021 pfile_info->Attributes =
1022 cpu_to_le32(le16_to_cpu(pSMBr->FileAttributes));
1023 /* the file_info buf is endian converted by caller */
1024 pfile_info->AllocationSize =
1025 cpu_to_le64(le32_to_cpu(pSMBr->EndOfFile));
1026 pfile_info->EndOfFile = pfile_info->AllocationSize;
1027 pfile_info->NumberOfLinks = cpu_to_le32(1);
1031 cifs_buf_release(pSMB);
1038 CIFSSMBOpen(const int xid, struct cifsTconInfo *tcon,
1039 const char *fileName, const int openDisposition,
1040 const int access_flags, const int create_options, __u16 * netfid,
1041 int *pOplock, FILE_ALL_INFO * pfile_info,
1042 const struct nls_table *nls_codepage, int remap)
1045 OPEN_REQ *pSMB = NULL;
1046 OPEN_RSP *pSMBr = NULL;
1052 rc = smb_init(SMB_COM_NT_CREATE_ANDX, 24, tcon, (void **) &pSMB,
1057 pSMB->AndXCommand = 0xFF; /* none */
1059 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1060 count = 1; /* account for one byte pad to word boundary */
1062 cifsConvertToUCS((__le16 *) (pSMB->fileName + 1),
1063 fileName, PATH_MAX, nls_codepage, remap);
1064 name_len++; /* trailing null */
1066 pSMB->NameLength = cpu_to_le16(name_len);
1067 } else { /* BB improve check for buffer overruns BB */
1068 count = 0; /* no pad */
1069 name_len = strnlen(fileName, PATH_MAX);
1070 name_len++; /* trailing null */
1071 pSMB->NameLength = cpu_to_le16(name_len);
1072 strncpy(pSMB->fileName, fileName, name_len);
1074 if (*pOplock & REQ_OPLOCK)
1075 pSMB->OpenFlags = cpu_to_le32(REQ_OPLOCK);
1076 else if (*pOplock & REQ_BATCHOPLOCK) {
1077 pSMB->OpenFlags = cpu_to_le32(REQ_BATCHOPLOCK);
1079 pSMB->DesiredAccess = cpu_to_le32(access_flags);
1080 pSMB->AllocationSize = 0;
1081 /* set file as system file if special file such
1082 as fifo and server expecting SFU style and
1083 no Unix extensions */
1084 if(create_options & CREATE_OPTION_SPECIAL)
1085 pSMB->FileAttributes = cpu_to_le32(ATTR_SYSTEM);
1087 pSMB->FileAttributes = cpu_to_le32(ATTR_NORMAL);
1088 /* XP does not handle ATTR_POSIX_SEMANTICS */
1089 /* but it helps speed up case sensitive checks for other
1090 servers such as Samba */
1091 if (tcon->ses->capabilities & CAP_UNIX)
1092 pSMB->FileAttributes |= cpu_to_le32(ATTR_POSIX_SEMANTICS);
1094 /* if ((omode & S_IWUGO) == 0)
1095 pSMB->FileAttributes |= cpu_to_le32(ATTR_READONLY);*/
1096 /* Above line causes problems due to vfs splitting create into two
1097 pieces - need to set mode after file created not while it is
1099 pSMB->ShareAccess = cpu_to_le32(FILE_SHARE_ALL);
1100 pSMB->CreateDisposition = cpu_to_le32(openDisposition);
1101 pSMB->CreateOptions = cpu_to_le32(create_options & CREATE_OPTIONS_MASK);
1102 /* BB Expirement with various impersonation levels and verify */
1103 pSMB->ImpersonationLevel = cpu_to_le32(SECURITY_IMPERSONATION);
1104 pSMB->SecurityFlags =
1105 SECURITY_CONTEXT_TRACKING | SECURITY_EFFECTIVE_ONLY;
1108 pSMB->hdr.smb_buf_length += count;
1110 pSMB->ByteCount = cpu_to_le16(count);
1111 /* long_op set to 1 to allow for oplock break timeouts */
1112 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1113 (struct smb_hdr *) pSMBr, &bytes_returned, 1);
1114 cifs_stats_inc(&tcon->num_opens);
1116 cFYI(1, ("Error in Open = %d", rc));
1118 *pOplock = pSMBr->OplockLevel; /* 1 byte no need to le_to_cpu */
1119 *netfid = pSMBr->Fid; /* cifs fid stays in le */
1120 /* Let caller know file was created so we can set the mode. */
1121 /* Do we care about the CreateAction in any other cases? */
1122 if(cpu_to_le32(FILE_CREATE) == pSMBr->CreateAction)
1123 *pOplock |= CIFS_CREATE_ACTION;
1125 memcpy((char *)pfile_info,(char *)&pSMBr->CreationTime,
1126 36 /* CreationTime to Attributes */);
1127 /* the file_info buf is endian converted by caller */
1128 pfile_info->AllocationSize = pSMBr->AllocationSize;
1129 pfile_info->EndOfFile = pSMBr->EndOfFile;
1130 pfile_info->NumberOfLinks = cpu_to_le32(1);
1134 cifs_buf_release(pSMB);
1141 CIFSSMBRead(const int xid, struct cifsTconInfo *tcon,
1142 const int netfid, const unsigned int count,
1143 const __u64 lseek, unsigned int *nbytes, char **buf,
1147 READ_REQ *pSMB = NULL;
1148 READ_RSP *pSMBr = NULL;
1149 char *pReadData = NULL;
1151 int resp_buf_type = 0;
1154 cFYI(1,("Reading %d bytes on fid %d",count,netfid));
1155 if(tcon->ses->capabilities & CAP_LARGE_FILES)
1158 wct = 10; /* old style read */
1161 rc = small_smb_init(SMB_COM_READ_ANDX, wct, tcon, (void **) &pSMB);
1165 /* tcon and ses pointer are checked in smb_init */
1166 if (tcon->ses->server == NULL)
1167 return -ECONNABORTED;
1169 pSMB->AndXCommand = 0xFF; /* none */
1171 pSMB->OffsetLow = cpu_to_le32(lseek & 0xFFFFFFFF);
1173 pSMB->OffsetHigh = cpu_to_le32(lseek >> 32);
1174 else if((lseek >> 32) > 0) /* can not handle this big offset for old */
1177 pSMB->Remaining = 0;
1178 pSMB->MaxCount = cpu_to_le16(count & 0xFFFF);
1179 pSMB->MaxCountHigh = cpu_to_le32(count >> 16);
1181 pSMB->ByteCount = 0; /* no need to do le conversion since 0 */
1183 /* old style read */
1184 struct smb_com_readx_req * pSMBW =
1185 (struct smb_com_readx_req *)pSMB;
1186 pSMBW->ByteCount = 0;
1189 iov[0].iov_base = (char *)pSMB;
1190 iov[0].iov_len = pSMB->hdr.smb_buf_length + 4;
1191 rc = SendReceive2(xid, tcon->ses, iov,
1194 cifs_stats_inc(&tcon->num_reads);
1195 pSMBr = (READ_RSP *)iov[0].iov_base;
1197 cERROR(1, ("Send error in read = %d", rc));
1199 int data_length = le16_to_cpu(pSMBr->DataLengthHigh);
1200 data_length = data_length << 16;
1201 data_length += le16_to_cpu(pSMBr->DataLength);
1202 *nbytes = data_length;
1204 /*check that DataLength would not go beyond end of SMB */
1205 if ((data_length > CIFSMaxBufSize)
1206 || (data_length > count)) {
1207 cFYI(1,("bad length %d for count %d",data_length,count));
1211 pReadData = (char *) (&pSMBr->hdr.Protocol) +
1212 le16_to_cpu(pSMBr->DataOffset);
1213 /* if(rc = copy_to_user(buf, pReadData, data_length)) {
1214 cERROR(1,("Faulting on read rc = %d",rc));
1216 }*/ /* can not use copy_to_user when using page cache*/
1218 memcpy(*buf,pReadData,data_length);
1222 /* cifs_small_buf_release(pSMB); */ /* Freed earlier now in SendReceive2 */
1224 if(resp_buf_type == CIFS_SMALL_BUFFER)
1225 cifs_small_buf_release(iov[0].iov_base);
1226 else if(resp_buf_type == CIFS_LARGE_BUFFER)
1227 cifs_buf_release(iov[0].iov_base);
1228 } else if(resp_buf_type != CIFS_NO_BUFFER) {
1229 /* return buffer to caller to free */
1230 *buf = iov[0].iov_base;
1231 if(resp_buf_type == CIFS_SMALL_BUFFER)
1232 *pbuf_type = CIFS_SMALL_BUFFER;
1233 else if(resp_buf_type == CIFS_LARGE_BUFFER)
1234 *pbuf_type = CIFS_LARGE_BUFFER;
1235 } /* else no valid buffer on return - leave as null */
1237 /* Note: On -EAGAIN error only caller can retry on handle based calls
1238 since file handle passed in no longer valid */
1244 CIFSSMBWrite(const int xid, struct cifsTconInfo *tcon,
1245 const int netfid, const unsigned int count,
1246 const __u64 offset, unsigned int *nbytes, const char *buf,
1247 const char __user * ubuf, const int long_op)
1250 WRITE_REQ *pSMB = NULL;
1251 WRITE_RSP *pSMBr = NULL;
1252 int bytes_returned, wct;
1256 /* cFYI(1,("write at %lld %d bytes",offset,count));*/
1257 if(tcon->ses == NULL)
1258 return -ECONNABORTED;
1260 if(tcon->ses->capabilities & CAP_LARGE_FILES)
1265 rc = smb_init(SMB_COM_WRITE_ANDX, wct, tcon, (void **) &pSMB,
1269 /* tcon and ses pointer are checked in smb_init */
1270 if (tcon->ses->server == NULL)
1271 return -ECONNABORTED;
1273 pSMB->AndXCommand = 0xFF; /* none */
1275 pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF);
1277 pSMB->OffsetHigh = cpu_to_le32(offset >> 32);
1278 else if((offset >> 32) > 0) /* can not handle this big offset for old */
1281 pSMB->Reserved = 0xFFFFFFFF;
1282 pSMB->WriteMode = 0;
1283 pSMB->Remaining = 0;
1285 /* Can increase buffer size if buffer is big enough in some cases - ie we
1286 can send more if LARGE_WRITE_X capability returned by the server and if
1287 our buffer is big enough or if we convert to iovecs on socket writes
1288 and eliminate the copy to the CIFS buffer */
1289 if(tcon->ses->capabilities & CAP_LARGE_WRITE_X) {
1290 bytes_sent = min_t(const unsigned int, CIFSMaxBufSize, count);
1292 bytes_sent = (tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE)
1296 if (bytes_sent > count)
1299 cpu_to_le16(offsetof(struct smb_com_write_req,Data) - 4);
1301 memcpy(pSMB->Data,buf,bytes_sent);
1303 if(copy_from_user(pSMB->Data,ubuf,bytes_sent)) {
1304 cifs_buf_release(pSMB);
1307 } else if (count != 0) {
1309 cifs_buf_release(pSMB);
1311 } /* else setting file size with write of zero bytes */
1313 byte_count = bytes_sent + 1; /* pad */
1314 else /* wct == 12 */ {
1315 byte_count = bytes_sent + 5; /* bigger pad, smaller smb hdr */
1317 pSMB->DataLengthLow = cpu_to_le16(bytes_sent & 0xFFFF);
1318 pSMB->DataLengthHigh = cpu_to_le16(bytes_sent >> 16);
1319 pSMB->hdr.smb_buf_length += byte_count;
1322 pSMB->ByteCount = cpu_to_le16(byte_count);
1323 else { /* old style write has byte count 4 bytes earlier so 4 bytes pad */
1324 struct smb_com_writex_req * pSMBW =
1325 (struct smb_com_writex_req *)pSMB;
1326 pSMBW->ByteCount = cpu_to_le16(byte_count);
1329 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1330 (struct smb_hdr *) pSMBr, &bytes_returned, long_op);
1331 cifs_stats_inc(&tcon->num_writes);
1333 cFYI(1, ("Send error in write = %d", rc));
1336 *nbytes = le16_to_cpu(pSMBr->CountHigh);
1337 *nbytes = (*nbytes) << 16;
1338 *nbytes += le16_to_cpu(pSMBr->Count);
1341 cifs_buf_release(pSMB);
1343 /* Note: On -EAGAIN error only caller can retry on handle based calls
1344 since file handle passed in no longer valid */
1350 CIFSSMBWrite2(const int xid, struct cifsTconInfo *tcon,
1351 const int netfid, const unsigned int count,
1352 const __u64 offset, unsigned int *nbytes, struct kvec *iov,
1353 int n_vec, const int long_op)
1356 WRITE_REQ *pSMB = NULL;
1359 int resp_buf_type = 0;
1361 cFYI(1,("write2 at %lld %d bytes", (long long)offset, count));
1363 if(tcon->ses->capabilities & CAP_LARGE_FILES)
1367 rc = small_smb_init(SMB_COM_WRITE_ANDX, wct, tcon, (void **) &pSMB);
1370 /* tcon and ses pointer are checked in smb_init */
1371 if (tcon->ses->server == NULL)
1372 return -ECONNABORTED;
1374 pSMB->AndXCommand = 0xFF; /* none */
1376 pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF);
1378 pSMB->OffsetHigh = cpu_to_le32(offset >> 32);
1379 else if((offset >> 32) > 0) /* can not handle this big offset for old */
1381 pSMB->Reserved = 0xFFFFFFFF;
1382 pSMB->WriteMode = 0;
1383 pSMB->Remaining = 0;
1386 cpu_to_le16(offsetof(struct smb_com_write_req,Data) - 4);
1388 pSMB->DataLengthLow = cpu_to_le16(count & 0xFFFF);
1389 pSMB->DataLengthHigh = cpu_to_le16(count >> 16);
1390 smb_hdr_len = pSMB->hdr.smb_buf_length + 1; /* hdr + 1 byte pad */
1392 pSMB->hdr.smb_buf_length += count+1;
1393 else /* wct == 12 */
1394 pSMB->hdr.smb_buf_length += count+5; /* smb data starts later */
1396 pSMB->ByteCount = cpu_to_le16(count + 1);
1397 else /* wct == 12 */ /* bigger pad, smaller smb hdr, keep offset ok */ {
1398 struct smb_com_writex_req * pSMBW =
1399 (struct smb_com_writex_req *)pSMB;
1400 pSMBW->ByteCount = cpu_to_le16(count + 5);
1402 iov[0].iov_base = pSMB;
1404 iov[0].iov_len = smb_hdr_len + 4;
1405 else /* wct == 12 pad bigger by four bytes */
1406 iov[0].iov_len = smb_hdr_len + 8;
1409 rc = SendReceive2(xid, tcon->ses, iov, n_vec + 1, &resp_buf_type,
1411 cifs_stats_inc(&tcon->num_writes);
1413 cFYI(1, ("Send error Write2 = %d", rc));
1415 } else if(resp_buf_type == 0) {
1416 /* presumably this can not happen, but best to be safe */
1420 WRITE_RSP * pSMBr = (WRITE_RSP *)iov[0].iov_base;
1421 *nbytes = le16_to_cpu(pSMBr->CountHigh);
1422 *nbytes = (*nbytes) << 16;
1423 *nbytes += le16_to_cpu(pSMBr->Count);
1426 /* cifs_small_buf_release(pSMB); */ /* Freed earlier now in SendReceive2 */
1427 if(resp_buf_type == CIFS_SMALL_BUFFER)
1428 cifs_small_buf_release(iov[0].iov_base);
1429 else if(resp_buf_type == CIFS_LARGE_BUFFER)
1430 cifs_buf_release(iov[0].iov_base);
1432 /* Note: On -EAGAIN error only caller can retry on handle based calls
1433 since file handle passed in no longer valid */
1440 CIFSSMBLock(const int xid, struct cifsTconInfo *tcon,
1441 const __u16 smb_file_id, const __u64 len,
1442 const __u64 offset, const __u32 numUnlock,
1443 const __u32 numLock, const __u8 lockType, const int waitFlag)
1446 LOCK_REQ *pSMB = NULL;
1447 LOCK_RSP *pSMBr = NULL;
1452 cFYI(1, ("In CIFSSMBLock - timeout %d numLock %d",waitFlag,numLock));
1453 rc = small_smb_init(SMB_COM_LOCKING_ANDX, 8, tcon, (void **) &pSMB);
1458 pSMBr = (LOCK_RSP *)pSMB; /* BB removeme BB */
1460 if(lockType == LOCKING_ANDX_OPLOCK_RELEASE) {
1461 timeout = -1; /* no response expected */
1463 } else if (waitFlag == TRUE) {
1464 timeout = 3; /* blocking operation, no timeout */
1465 pSMB->Timeout = cpu_to_le32(-1);/* blocking - do not time out */
1470 pSMB->NumberOfLocks = cpu_to_le16(numLock);
1471 pSMB->NumberOfUnlocks = cpu_to_le16(numUnlock);
1472 pSMB->LockType = lockType;
1473 pSMB->AndXCommand = 0xFF; /* none */
1474 pSMB->Fid = smb_file_id; /* netfid stays le */
1476 if((numLock != 0) || (numUnlock != 0)) {
1477 pSMB->Locks[0].Pid = cpu_to_le16(current->tgid);
1478 /* BB where to store pid high? */
1479 pSMB->Locks[0].LengthLow = cpu_to_le32((u32)len);
1480 pSMB->Locks[0].LengthHigh = cpu_to_le32((u32)(len>>32));
1481 pSMB->Locks[0].OffsetLow = cpu_to_le32((u32)offset);
1482 pSMB->Locks[0].OffsetHigh = cpu_to_le32((u32)(offset>>32));
1483 count = sizeof(LOCKING_ANDX_RANGE);
1488 pSMB->hdr.smb_buf_length += count;
1489 pSMB->ByteCount = cpu_to_le16(count);
1492 rc = SendReceiveBlockingLock(xid, tcon, (struct smb_hdr *) pSMB,
1493 (struct smb_hdr *) pSMBr, &bytes_returned);
1495 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1496 (struct smb_hdr *) pSMBr, &bytes_returned, timeout);
1498 cifs_stats_inc(&tcon->num_locks);
1500 cFYI(1, ("Send error in Lock = %d", rc));
1502 cifs_small_buf_release(pSMB);
1504 /* Note: On -EAGAIN error only caller can retry on handle based calls
1505 since file handle passed in no longer valid */
1510 CIFSSMBPosixLock(const int xid, struct cifsTconInfo *tcon,
1511 const __u16 smb_file_id, const int get_flag, const __u64 len,
1512 struct file_lock *pLockData, const __u16 lock_type,
1515 struct smb_com_transaction2_sfi_req *pSMB = NULL;
1516 struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
1518 struct cifs_posix_lock *parm_data;
1521 int bytes_returned = 0;
1522 __u16 params, param_offset, offset, byte_count, count;
1524 cFYI(1, ("Posix Lock"));
1526 if(pLockData == NULL)
1529 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
1534 pSMBr = (struct smb_com_transaction2_sfi_rsp *)pSMB;
1537 pSMB->MaxSetupCount = 0;
1540 pSMB->Reserved2 = 0;
1541 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
1542 offset = param_offset + params;
1544 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
1546 count = sizeof(struct cifs_posix_lock);
1547 pSMB->MaxParameterCount = cpu_to_le16(2);
1548 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB PDU from sess */
1549 pSMB->SetupCount = 1;
1550 pSMB->Reserved3 = 0;
1552 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION);
1554 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
1555 byte_count = 3 /* pad */ + params + count;
1556 pSMB->DataCount = cpu_to_le16(count);
1557 pSMB->ParameterCount = cpu_to_le16(params);
1558 pSMB->TotalDataCount = pSMB->DataCount;
1559 pSMB->TotalParameterCount = pSMB->ParameterCount;
1560 pSMB->ParameterOffset = cpu_to_le16(param_offset);
1561 parm_data = (struct cifs_posix_lock *)
1562 (((char *) &pSMB->hdr.Protocol) + offset);
1564 parm_data->lock_type = cpu_to_le16(lock_type);
1566 timeout = 3; /* blocking operation, no timeout */
1567 parm_data->lock_flags = cpu_to_le16(1);
1568 pSMB->Timeout = cpu_to_le32(-1);
1572 parm_data->pid = cpu_to_le32(current->tgid);
1573 parm_data->start = cpu_to_le64(pLockData->fl_start);
1574 parm_data->length = cpu_to_le64(len); /* normalize negative numbers */
1576 pSMB->DataOffset = cpu_to_le16(offset);
1577 pSMB->Fid = smb_file_id;
1578 pSMB->InformationLevel = cpu_to_le16(SMB_SET_POSIX_LOCK);
1579 pSMB->Reserved4 = 0;
1580 pSMB->hdr.smb_buf_length += byte_count;
1581 pSMB->ByteCount = cpu_to_le16(byte_count);
1583 rc = SendReceiveBlockingLock(xid, tcon, (struct smb_hdr *) pSMB,
1584 (struct smb_hdr *) pSMBr, &bytes_returned);
1586 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1587 (struct smb_hdr *) pSMBr, &bytes_returned, timeout);
1591 cFYI(1, ("Send error in Posix Lock = %d", rc));
1592 } else if (get_flag) {
1593 /* lock structure can be returned on get */
1596 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
1598 if (rc || (pSMBr->ByteCount < sizeof(struct cifs_posix_lock))) {
1599 rc = -EIO; /* bad smb */
1602 if(pLockData == NULL) {
1606 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
1607 data_count = le16_to_cpu(pSMBr->t2.DataCount);
1608 if(data_count < sizeof(struct cifs_posix_lock)) {
1612 parm_data = (struct cifs_posix_lock *)
1613 ((char *)&pSMBr->hdr.Protocol + data_offset);
1614 if(parm_data->lock_type == cpu_to_le16(CIFS_UNLCK))
1615 pLockData->fl_type = F_UNLCK;
1620 cifs_small_buf_release(pSMB);
1622 /* Note: On -EAGAIN error only caller can retry on handle based calls
1623 since file handle passed in no longer valid */
1630 CIFSSMBClose(const int xid, struct cifsTconInfo *tcon, int smb_file_id)
1633 CLOSE_REQ *pSMB = NULL;
1634 CLOSE_RSP *pSMBr = NULL;
1636 cFYI(1, ("In CIFSSMBClose"));
1638 /* do not retry on dead session on close */
1639 rc = small_smb_init(SMB_COM_CLOSE, 3, tcon, (void **) &pSMB);
1645 pSMBr = (CLOSE_RSP *)pSMB; /* BB removeme BB */
1647 pSMB->FileID = (__u16) smb_file_id;
1648 pSMB->LastWriteTime = 0;
1649 pSMB->ByteCount = 0;
1650 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1651 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1652 cifs_stats_inc(&tcon->num_closes);
1655 /* EINTR is expected when user ctl-c to kill app */
1656 cERROR(1, ("Send error in Close = %d", rc));
1660 cifs_small_buf_release(pSMB);
1662 /* Since session is dead, file will be closed on server already */
1670 CIFSSMBRename(const int xid, struct cifsTconInfo *tcon,
1671 const char *fromName, const char *toName,
1672 const struct nls_table *nls_codepage, int remap)
1675 RENAME_REQ *pSMB = NULL;
1676 RENAME_RSP *pSMBr = NULL;
1678 int name_len, name_len2;
1681 cFYI(1, ("In CIFSSMBRename"));
1683 rc = smb_init(SMB_COM_RENAME, 1, tcon, (void **) &pSMB,
1688 pSMB->BufferFormat = 0x04;
1689 pSMB->SearchAttributes =
1690 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
1693 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1695 cifsConvertToUCS((__le16 *) pSMB->OldFileName, fromName,
1696 PATH_MAX, nls_codepage, remap);
1697 name_len++; /* trailing null */
1699 pSMB->OldFileName[name_len] = 0x04; /* pad */
1700 /* protocol requires ASCII signature byte on Unicode string */
1701 pSMB->OldFileName[name_len + 1] = 0x00;
1703 cifsConvertToUCS((__le16 *) &pSMB->OldFileName[name_len + 2],
1704 toName, PATH_MAX, nls_codepage, remap);
1705 name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
1706 name_len2 *= 2; /* convert to bytes */
1707 } else { /* BB improve the check for buffer overruns BB */
1708 name_len = strnlen(fromName, PATH_MAX);
1709 name_len++; /* trailing null */
1710 strncpy(pSMB->OldFileName, fromName, name_len);
1711 name_len2 = strnlen(toName, PATH_MAX);
1712 name_len2++; /* trailing null */
1713 pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */
1714 strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2);
1715 name_len2++; /* trailing null */
1716 name_len2++; /* signature byte */
1719 count = 1 /* 1st signature byte */ + name_len + name_len2;
1720 pSMB->hdr.smb_buf_length += count;
1721 pSMB->ByteCount = cpu_to_le16(count);
1723 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1724 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1725 cifs_stats_inc(&tcon->num_renames);
1727 cFYI(1, ("Send error in rename = %d", rc));
1730 cifs_buf_release(pSMB);
1738 int CIFSSMBRenameOpenFile(const int xid,struct cifsTconInfo *pTcon,
1739 int netfid, char * target_name,
1740 const struct nls_table * nls_codepage, int remap)
1742 struct smb_com_transaction2_sfi_req *pSMB = NULL;
1743 struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
1744 struct set_file_rename * rename_info;
1746 char dummy_string[30];
1748 int bytes_returned = 0;
1750 __u16 params, param_offset, offset, count, byte_count;
1752 cFYI(1, ("Rename to File by handle"));
1753 rc = smb_init(SMB_COM_TRANSACTION2, 15, pTcon, (void **) &pSMB,
1759 pSMB->MaxSetupCount = 0;
1763 pSMB->Reserved2 = 0;
1764 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
1765 offset = param_offset + params;
1767 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
1768 rename_info = (struct set_file_rename *) data_offset;
1769 pSMB->MaxParameterCount = cpu_to_le16(2);
1770 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB PDU from sess */
1771 pSMB->SetupCount = 1;
1772 pSMB->Reserved3 = 0;
1773 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
1774 byte_count = 3 /* pad */ + params;
1775 pSMB->ParameterCount = cpu_to_le16(params);
1776 pSMB->TotalParameterCount = pSMB->ParameterCount;
1777 pSMB->ParameterOffset = cpu_to_le16(param_offset);
1778 pSMB->DataOffset = cpu_to_le16(offset);
1779 /* construct random name ".cifs_tmp<inodenum><mid>" */
1780 rename_info->overwrite = cpu_to_le32(1);
1781 rename_info->root_fid = 0;
1782 /* unicode only call */
1783 if(target_name == NULL) {
1784 sprintf(dummy_string,"cifs%x",pSMB->hdr.Mid);
1785 len_of_str = cifsConvertToUCS((__le16 *)rename_info->target_name,
1786 dummy_string, 24, nls_codepage, remap);
1788 len_of_str = cifsConvertToUCS((__le16 *)rename_info->target_name,
1789 target_name, PATH_MAX, nls_codepage, remap);
1791 rename_info->target_name_len = cpu_to_le32(2 * len_of_str);
1792 count = 12 /* sizeof(struct set_file_rename) */ + (2 * len_of_str) + 2;
1793 byte_count += count;
1794 pSMB->DataCount = cpu_to_le16(count);
1795 pSMB->TotalDataCount = pSMB->DataCount;
1797 pSMB->InformationLevel =
1798 cpu_to_le16(SMB_SET_FILE_RENAME_INFORMATION);
1799 pSMB->Reserved4 = 0;
1800 pSMB->hdr.smb_buf_length += byte_count;
1801 pSMB->ByteCount = cpu_to_le16(byte_count);
1802 rc = SendReceive(xid, pTcon->ses, (struct smb_hdr *) pSMB,
1803 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1804 cifs_stats_inc(&pTcon->num_t2renames);
1806 cFYI(1,("Send error in Rename (by file handle) = %d", rc));
1809 cifs_buf_release(pSMB);
1811 /* Note: On -EAGAIN error only caller can retry on handle based calls
1812 since file handle passed in no longer valid */
1818 CIFSSMBCopy(const int xid, struct cifsTconInfo *tcon, const char * fromName,
1819 const __u16 target_tid, const char *toName, const int flags,
1820 const struct nls_table *nls_codepage, int remap)
1823 COPY_REQ *pSMB = NULL;
1824 COPY_RSP *pSMBr = NULL;
1826 int name_len, name_len2;
1829 cFYI(1, ("In CIFSSMBCopy"));
1831 rc = smb_init(SMB_COM_COPY, 1, tcon, (void **) &pSMB,
1836 pSMB->BufferFormat = 0x04;
1837 pSMB->Tid2 = target_tid;
1839 pSMB->Flags = cpu_to_le16(flags & COPY_TREE);
1841 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1842 name_len = cifsConvertToUCS((__le16 *) pSMB->OldFileName,
1843 fromName, PATH_MAX, nls_codepage,
1845 name_len++; /* trailing null */
1847 pSMB->OldFileName[name_len] = 0x04; /* pad */
1848 /* protocol requires ASCII signature byte on Unicode string */
1849 pSMB->OldFileName[name_len + 1] = 0x00;
1850 name_len2 = cifsConvertToUCS((__le16 *)&pSMB->OldFileName[name_len + 2],
1851 toName, PATH_MAX, nls_codepage, remap);
1852 name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
1853 name_len2 *= 2; /* convert to bytes */
1854 } else { /* BB improve the check for buffer overruns BB */
1855 name_len = strnlen(fromName, PATH_MAX);
1856 name_len++; /* trailing null */
1857 strncpy(pSMB->OldFileName, fromName, name_len);
1858 name_len2 = strnlen(toName, PATH_MAX);
1859 name_len2++; /* trailing null */
1860 pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */
1861 strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2);
1862 name_len2++; /* trailing null */
1863 name_len2++; /* signature byte */
1866 count = 1 /* 1st signature byte */ + name_len + name_len2;
1867 pSMB->hdr.smb_buf_length += count;
1868 pSMB->ByteCount = cpu_to_le16(count);
1870 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1871 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1873 cFYI(1, ("Send error in copy = %d with %d files copied",
1874 rc, le16_to_cpu(pSMBr->CopyCount)));
1877 cifs_buf_release(pSMB);
1886 CIFSUnixCreateSymLink(const int xid, struct cifsTconInfo *tcon,
1887 const char *fromName, const char *toName,
1888 const struct nls_table *nls_codepage)
1890 TRANSACTION2_SPI_REQ *pSMB = NULL;
1891 TRANSACTION2_SPI_RSP *pSMBr = NULL;
1894 int name_len_target;
1896 int bytes_returned = 0;
1897 __u16 params, param_offset, offset, byte_count;
1899 cFYI(1, ("In Symlink Unix style"));
1901 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
1906 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1908 cifs_strtoUCS((__le16 *) pSMB->FileName, fromName, PATH_MAX
1909 /* find define for this maxpathcomponent */
1911 name_len++; /* trailing null */
1914 } else { /* BB improve the check for buffer overruns BB */
1915 name_len = strnlen(fromName, PATH_MAX);
1916 name_len++; /* trailing null */
1917 strncpy(pSMB->FileName, fromName, name_len);
1919 params = 6 + name_len;
1920 pSMB->MaxSetupCount = 0;
1924 pSMB->Reserved2 = 0;
1925 param_offset = offsetof(struct smb_com_transaction2_spi_req,
1926 InformationLevel) - 4;
1927 offset = param_offset + params;
1929 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
1930 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1932 cifs_strtoUCS((__le16 *) data_offset, toName, PATH_MAX
1933 /* find define for this maxpathcomponent */
1935 name_len_target++; /* trailing null */
1936 name_len_target *= 2;
1937 } else { /* BB improve the check for buffer overruns BB */
1938 name_len_target = strnlen(toName, PATH_MAX);
1939 name_len_target++; /* trailing null */
1940 strncpy(data_offset, toName, name_len_target);
1943 pSMB->MaxParameterCount = cpu_to_le16(2);
1944 /* BB find exact max on data count below from sess */
1945 pSMB->MaxDataCount = cpu_to_le16(1000);
1946 pSMB->SetupCount = 1;
1947 pSMB->Reserved3 = 0;
1948 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
1949 byte_count = 3 /* pad */ + params + name_len_target;
1950 pSMB->DataCount = cpu_to_le16(name_len_target);
1951 pSMB->ParameterCount = cpu_to_le16(params);
1952 pSMB->TotalDataCount = pSMB->DataCount;
1953 pSMB->TotalParameterCount = pSMB->ParameterCount;
1954 pSMB->ParameterOffset = cpu_to_le16(param_offset);
1955 pSMB->DataOffset = cpu_to_le16(offset);
1956 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_LINK);
1957 pSMB->Reserved4 = 0;
1958 pSMB->hdr.smb_buf_length += byte_count;
1959 pSMB->ByteCount = cpu_to_le16(byte_count);
1960 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1961 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1962 cifs_stats_inc(&tcon->num_symlinks);
1965 ("Send error in SetPathInfo (create symlink) = %d",
1970 cifs_buf_release(pSMB);
1973 goto createSymLinkRetry;
1979 CIFSUnixCreateHardLink(const int xid, struct cifsTconInfo *tcon,
1980 const char *fromName, const char *toName,
1981 const struct nls_table *nls_codepage, int remap)
1983 TRANSACTION2_SPI_REQ *pSMB = NULL;
1984 TRANSACTION2_SPI_RSP *pSMBr = NULL;
1987 int name_len_target;
1989 int bytes_returned = 0;
1990 __u16 params, param_offset, offset, byte_count;
1992 cFYI(1, ("In Create Hard link Unix style"));
1993 createHardLinkRetry:
1994 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
1999 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2000 name_len = cifsConvertToUCS((__le16 *) pSMB->FileName, toName,
2001 PATH_MAX, nls_codepage, remap);
2002 name_len++; /* trailing null */
2005 } else { /* BB improve the check for buffer overruns BB */
2006 name_len = strnlen(toName, PATH_MAX);
2007 name_len++; /* trailing null */
2008 strncpy(pSMB->FileName, toName, name_len);
2010 params = 6 + name_len;
2011 pSMB->MaxSetupCount = 0;
2015 pSMB->Reserved2 = 0;
2016 param_offset = offsetof(struct smb_com_transaction2_spi_req,
2017 InformationLevel) - 4;
2018 offset = param_offset + params;
2020 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
2021 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2023 cifsConvertToUCS((__le16 *) data_offset, fromName, PATH_MAX,
2024 nls_codepage, remap);
2025 name_len_target++; /* trailing null */
2026 name_len_target *= 2;
2027 } else { /* BB improve the check for buffer overruns BB */
2028 name_len_target = strnlen(fromName, PATH_MAX);
2029 name_len_target++; /* trailing null */
2030 strncpy(data_offset, fromName, name_len_target);
2033 pSMB->MaxParameterCount = cpu_to_le16(2);
2034 /* BB find exact max on data count below from sess*/
2035 pSMB->MaxDataCount = cpu_to_le16(1000);
2036 pSMB->SetupCount = 1;
2037 pSMB->Reserved3 = 0;
2038 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
2039 byte_count = 3 /* pad */ + params + name_len_target;
2040 pSMB->ParameterCount = cpu_to_le16(params);
2041 pSMB->TotalParameterCount = pSMB->ParameterCount;
2042 pSMB->DataCount = cpu_to_le16(name_len_target);
2043 pSMB->TotalDataCount = pSMB->DataCount;
2044 pSMB->ParameterOffset = cpu_to_le16(param_offset);
2045 pSMB->DataOffset = cpu_to_le16(offset);
2046 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_HLINK);
2047 pSMB->Reserved4 = 0;
2048 pSMB->hdr.smb_buf_length += byte_count;
2049 pSMB->ByteCount = cpu_to_le16(byte_count);
2050 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2051 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2052 cifs_stats_inc(&tcon->num_hardlinks);
2054 cFYI(1, ("Send error in SetPathInfo (hard link) = %d", rc));
2057 cifs_buf_release(pSMB);
2059 goto createHardLinkRetry;
2065 CIFSCreateHardLink(const int xid, struct cifsTconInfo *tcon,
2066 const char *fromName, const char *toName,
2067 const struct nls_table *nls_codepage, int remap)
2070 NT_RENAME_REQ *pSMB = NULL;
2071 RENAME_RSP *pSMBr = NULL;
2073 int name_len, name_len2;
2076 cFYI(1, ("In CIFSCreateHardLink"));
2077 winCreateHardLinkRetry:
2079 rc = smb_init(SMB_COM_NT_RENAME, 4, tcon, (void **) &pSMB,
2084 pSMB->SearchAttributes =
2085 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
2087 pSMB->Flags = cpu_to_le16(CREATE_HARD_LINK);
2088 pSMB->ClusterCount = 0;
2090 pSMB->BufferFormat = 0x04;
2092 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2094 cifsConvertToUCS((__le16 *) pSMB->OldFileName, fromName,
2095 PATH_MAX, nls_codepage, remap);
2096 name_len++; /* trailing null */
2098 pSMB->OldFileName[name_len] = 0; /* pad */
2099 pSMB->OldFileName[name_len + 1] = 0x04;
2101 cifsConvertToUCS((__le16 *)&pSMB->OldFileName[name_len + 2],
2102 toName, PATH_MAX, nls_codepage, remap);
2103 name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
2104 name_len2 *= 2; /* convert to bytes */
2105 } else { /* BB improve the check for buffer overruns BB */
2106 name_len = strnlen(fromName, PATH_MAX);
2107 name_len++; /* trailing null */
2108 strncpy(pSMB->OldFileName, fromName, name_len);
2109 name_len2 = strnlen(toName, PATH_MAX);
2110 name_len2++; /* trailing null */
2111 pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */
2112 strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2);
2113 name_len2++; /* trailing null */
2114 name_len2++; /* signature byte */
2117 count = 1 /* string type byte */ + name_len + name_len2;
2118 pSMB->hdr.smb_buf_length += count;
2119 pSMB->ByteCount = cpu_to_le16(count);
2121 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2122 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2123 cifs_stats_inc(&tcon->num_hardlinks);
2125 cFYI(1, ("Send error in hard link (NT rename) = %d", rc));
2127 cifs_buf_release(pSMB);
2129 goto winCreateHardLinkRetry;
2135 CIFSSMBUnixQuerySymLink(const int xid, struct cifsTconInfo *tcon,
2136 const unsigned char *searchName,
2137 char *symlinkinfo, const int buflen,
2138 const struct nls_table *nls_codepage)
2140 /* SMB_QUERY_FILE_UNIX_LINK */
2141 TRANSACTION2_QPI_REQ *pSMB = NULL;
2142 TRANSACTION2_QPI_RSP *pSMBr = NULL;
2146 __u16 params, byte_count;
2148 cFYI(1, ("In QPathSymLinkInfo (Unix) for path %s", searchName));
2151 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2156 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2158 cifs_strtoUCS((__le16 *) pSMB->FileName, searchName, PATH_MAX
2159 /* find define for this maxpathcomponent */
2161 name_len++; /* trailing null */
2163 } else { /* BB improve the check for buffer overruns BB */
2164 name_len = strnlen(searchName, PATH_MAX);
2165 name_len++; /* trailing null */
2166 strncpy(pSMB->FileName, searchName, name_len);
2169 params = 2 /* level */ + 4 /* rsrvd */ + name_len /* incl null */ ;
2170 pSMB->TotalDataCount = 0;
2171 pSMB->MaxParameterCount = cpu_to_le16(2);
2172 /* BB find exact max data count below from sess structure BB */
2173 pSMB->MaxDataCount = cpu_to_le16(4000);
2174 pSMB->MaxSetupCount = 0;
2178 pSMB->Reserved2 = 0;
2179 pSMB->ParameterOffset = cpu_to_le16(offsetof(
2180 struct smb_com_transaction2_qpi_req ,InformationLevel) - 4);
2181 pSMB->DataCount = 0;
2182 pSMB->DataOffset = 0;
2183 pSMB->SetupCount = 1;
2184 pSMB->Reserved3 = 0;
2185 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
2186 byte_count = params + 1 /* pad */ ;
2187 pSMB->TotalParameterCount = cpu_to_le16(params);
2188 pSMB->ParameterCount = pSMB->TotalParameterCount;
2189 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_LINK);
2190 pSMB->Reserved4 = 0;
2191 pSMB->hdr.smb_buf_length += byte_count;
2192 pSMB->ByteCount = cpu_to_le16(byte_count);
2194 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2195 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2197 cFYI(1, ("Send error in QuerySymLinkInfo = %d", rc));
2199 /* decode response */
2201 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
2202 if (rc || (pSMBr->ByteCount < 2))
2203 /* BB also check enough total bytes returned */
2204 rc = -EIO; /* bad smb */
2206 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
2207 __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
2209 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
2210 name_len = UniStrnlen((wchar_t *) ((char *)
2211 &pSMBr->hdr.Protocol +data_offset),
2212 min_t(const int, buflen,count) / 2);
2213 /* BB FIXME investigate remapping reserved chars here */
2214 cifs_strfromUCS_le(symlinkinfo,
2215 (__le16 *) ((char *)&pSMBr->hdr.Protocol +
2217 name_len, nls_codepage);
2219 strncpy(symlinkinfo,
2220 (char *) &pSMBr->hdr.Protocol +
2222 min_t(const int, buflen, count));
2224 symlinkinfo[buflen] = 0;
2225 /* just in case so calling code does not go off the end of buffer */
2228 cifs_buf_release(pSMB);
2230 goto querySymLinkRetry;
2234 /* Initialize NT TRANSACT SMB into small smb request buffer.
2235 This assumes that all NT TRANSACTS that we init here have
2236 total parm and data under about 400 bytes (to fit in small cifs
2237 buffer size), which is the case so far, it easily fits. NB:
2238 Setup words themselves and ByteCount
2239 MaxSetupCount (size of returned setup area) and
2240 MaxParameterCount (returned parms size) must be set by caller */
2242 smb_init_ntransact(const __u16 sub_command, const int setup_count,
2243 const int parm_len, struct cifsTconInfo *tcon,
2248 struct smb_com_ntransact_req * pSMB;
2250 rc = small_smb_init(SMB_COM_NT_TRANSACT, 19 + setup_count, tcon,
2254 *ret_buf = (void *)pSMB;
2256 pSMB->TotalParameterCount = cpu_to_le32(parm_len);
2257 pSMB->TotalDataCount = 0;
2258 pSMB->MaxDataCount = cpu_to_le32((tcon->ses->server->maxBuf -
2259 MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
2260 pSMB->ParameterCount = pSMB->TotalParameterCount;
2261 pSMB->DataCount = pSMB->TotalDataCount;
2262 temp_offset = offsetof(struct smb_com_ntransact_req, Parms) +
2263 (setup_count * 2) - 4 /* for rfc1001 length itself */;
2264 pSMB->ParameterOffset = cpu_to_le32(temp_offset);
2265 pSMB->DataOffset = cpu_to_le32(temp_offset + parm_len);
2266 pSMB->SetupCount = setup_count; /* no need to le convert byte fields */
2267 pSMB->SubCommand = cpu_to_le16(sub_command);
2272 validate_ntransact(char * buf, char ** ppparm, char ** ppdata,
2273 int * pdatalen, int * pparmlen)
2276 __u32 data_count, data_offset, parm_count, parm_offset;
2277 struct smb_com_ntransact_rsp * pSMBr;
2282 pSMBr = (struct smb_com_ntransact_rsp *)buf;
2284 /* ByteCount was converted from little endian in SendReceive */
2285 end_of_smb = 2 /* sizeof byte count */ + pSMBr->ByteCount +
2286 (char *)&pSMBr->ByteCount;
2289 data_offset = le32_to_cpu(pSMBr->DataOffset);
2290 data_count = le32_to_cpu(pSMBr->DataCount);
2291 parm_offset = le32_to_cpu(pSMBr->ParameterOffset);
2292 parm_count = le32_to_cpu(pSMBr->ParameterCount);
2294 *ppparm = (char *)&pSMBr->hdr.Protocol + parm_offset;
2295 *ppdata = (char *)&pSMBr->hdr.Protocol + data_offset;
2297 /* should we also check that parm and data areas do not overlap? */
2298 if(*ppparm > end_of_smb) {
2299 cFYI(1,("parms start after end of smb"));
2301 } else if(parm_count + *ppparm > end_of_smb) {
2302 cFYI(1,("parm end after end of smb"));
2304 } else if(*ppdata > end_of_smb) {
2305 cFYI(1,("data starts after end of smb"));
2307 } else if(data_count + *ppdata > end_of_smb) {
2308 cFYI(1,("data %p + count %d (%p) ends after end of smb %p start %p",
2309 *ppdata, data_count, (data_count + *ppdata), end_of_smb, pSMBr)); /* BB FIXME */
2311 } else if(parm_count + data_count > pSMBr->ByteCount) {
2312 cFYI(1,("parm count and data count larger than SMB"));
2319 CIFSSMBQueryReparseLinkInfo(const int xid, struct cifsTconInfo *tcon,
2320 const unsigned char *searchName,
2321 char *symlinkinfo, const int buflen,__u16 fid,
2322 const struct nls_table *nls_codepage)
2327 struct smb_com_transaction_ioctl_req * pSMB;
2328 struct smb_com_transaction_ioctl_rsp * pSMBr;
2330 cFYI(1, ("In Windows reparse style QueryLink for path %s", searchName));
2331 rc = smb_init(SMB_COM_NT_TRANSACT, 23, tcon, (void **) &pSMB,
2336 pSMB->TotalParameterCount = 0 ;
2337 pSMB->TotalDataCount = 0;
2338 pSMB->MaxParameterCount = cpu_to_le32(2);
2339 /* BB find exact data count max from sess structure BB */
2340 pSMB->MaxDataCount = cpu_to_le32((tcon->ses->server->maxBuf -
2341 MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
2342 pSMB->MaxSetupCount = 4;
2344 pSMB->ParameterOffset = 0;
2345 pSMB->DataCount = 0;
2346 pSMB->DataOffset = 0;
2347 pSMB->SetupCount = 4;
2348 pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_IOCTL);
2349 pSMB->ParameterCount = pSMB->TotalParameterCount;
2350 pSMB->FunctionCode = cpu_to_le32(FSCTL_GET_REPARSE_POINT);
2351 pSMB->IsFsctl = 1; /* FSCTL */
2352 pSMB->IsRootFlag = 0;
2353 pSMB->Fid = fid; /* file handle always le */
2354 pSMB->ByteCount = 0;
2356 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2357 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2359 cFYI(1, ("Send error in QueryReparseLinkInfo = %d", rc));
2360 } else { /* decode response */
2361 __u32 data_offset = le32_to_cpu(pSMBr->DataOffset);
2362 __u32 data_count = le32_to_cpu(pSMBr->DataCount);
2363 if ((pSMBr->ByteCount < 2) || (data_offset > 512))
2364 /* BB also check enough total bytes returned */
2365 rc = -EIO; /* bad smb */
2367 if(data_count && (data_count < 2048)) {
2368 char * end_of_smb = 2 /* sizeof byte count */ +
2370 (char *)&pSMBr->ByteCount;
2372 struct reparse_data * reparse_buf = (struct reparse_data *)
2373 ((char *)&pSMBr->hdr.Protocol + data_offset);
2374 if((char*)reparse_buf >= end_of_smb) {
2378 if((reparse_buf->LinkNamesBuf +
2379 reparse_buf->TargetNameOffset +
2380 reparse_buf->TargetNameLen) >
2382 cFYI(1,("reparse buf extended beyond SMB"));
2387 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
2388 name_len = UniStrnlen((wchar_t *)
2389 (reparse_buf->LinkNamesBuf +
2390 reparse_buf->TargetNameOffset),
2391 min(buflen/2, reparse_buf->TargetNameLen / 2));
2392 cifs_strfromUCS_le(symlinkinfo,
2393 (__le16 *) (reparse_buf->LinkNamesBuf +
2394 reparse_buf->TargetNameOffset),
2395 name_len, nls_codepage);
2396 } else { /* ASCII names */
2397 strncpy(symlinkinfo,reparse_buf->LinkNamesBuf +
2398 reparse_buf->TargetNameOffset,
2399 min_t(const int, buflen, reparse_buf->TargetNameLen));
2403 cFYI(1,("Invalid return data count on get reparse info ioctl"));
2405 symlinkinfo[buflen] = 0; /* just in case so the caller
2406 does not go off the end of the buffer */
2407 cFYI(1,("readlink result - %s",symlinkinfo));
2411 cifs_buf_release(pSMB);
2413 /* Note: On -EAGAIN error only caller can retry on handle based calls
2414 since file handle passed in no longer valid */
2419 #ifdef CONFIG_CIFS_POSIX
2421 /*Convert an Access Control Entry from wire format to local POSIX xattr format*/
2422 static void cifs_convert_ace(posix_acl_xattr_entry * ace, struct cifs_posix_ace * cifs_ace)
2424 /* u8 cifs fields do not need le conversion */
2425 ace->e_perm = cpu_to_le16(cifs_ace->cifs_e_perm);
2426 ace->e_tag = cpu_to_le16(cifs_ace->cifs_e_tag);
2427 ace->e_id = cpu_to_le32(le64_to_cpu(cifs_ace->cifs_uid));
2428 /* cFYI(1,("perm %d tag %d id %d",ace->e_perm,ace->e_tag,ace->e_id)); */
2433 /* Convert ACL from CIFS POSIX wire format to local Linux POSIX ACL xattr */
2434 static int cifs_copy_posix_acl(char * trgt,char * src, const int buflen,
2435 const int acl_type,const int size_of_data_area)
2440 struct cifs_posix_ace * pACE;
2441 struct cifs_posix_acl * cifs_acl = (struct cifs_posix_acl *)src;
2442 posix_acl_xattr_header * local_acl = (posix_acl_xattr_header *)trgt;
2444 if (le16_to_cpu(cifs_acl->version) != CIFS_ACL_VERSION)
2447 if(acl_type & ACL_TYPE_ACCESS) {
2448 count = le16_to_cpu(cifs_acl->access_entry_count);
2449 pACE = &cifs_acl->ace_array[0];
2450 size = sizeof(struct cifs_posix_acl);
2451 size += sizeof(struct cifs_posix_ace) * count;
2452 /* check if we would go beyond end of SMB */
2453 if(size_of_data_area < size) {
2454 cFYI(1,("bad CIFS POSIX ACL size %d vs. %d",size_of_data_area,size));
2457 } else if(acl_type & ACL_TYPE_DEFAULT) {
2458 count = le16_to_cpu(cifs_acl->access_entry_count);
2459 size = sizeof(struct cifs_posix_acl);
2460 size += sizeof(struct cifs_posix_ace) * count;
2461 /* skip past access ACEs to get to default ACEs */
2462 pACE = &cifs_acl->ace_array[count];
2463 count = le16_to_cpu(cifs_acl->default_entry_count);
2464 size += sizeof(struct cifs_posix_ace) * count;
2465 /* check if we would go beyond end of SMB */
2466 if(size_of_data_area < size)
2473 size = posix_acl_xattr_size(count);
2474 if((buflen == 0) || (local_acl == NULL)) {
2475 /* used to query ACL EA size */
2476 } else if(size > buflen) {
2478 } else /* buffer big enough */ {
2479 local_acl->a_version = cpu_to_le32(POSIX_ACL_XATTR_VERSION);
2480 for(i = 0;i < count ;i++) {
2481 cifs_convert_ace(&local_acl->a_entries[i],pACE);
2488 static __u16 convert_ace_to_cifs_ace(struct cifs_posix_ace * cifs_ace,
2489 const posix_acl_xattr_entry * local_ace)
2491 __u16 rc = 0; /* 0 = ACL converted ok */
2493 cifs_ace->cifs_e_perm = le16_to_cpu(local_ace->e_perm);
2494 cifs_ace->cifs_e_tag = le16_to_cpu(local_ace->e_tag);
2495 /* BB is there a better way to handle the large uid? */
2496 if(local_ace->e_id == cpu_to_le32(-1)) {
2497 /* Probably no need to le convert -1 on any arch but can not hurt */
2498 cifs_ace->cifs_uid = cpu_to_le64(-1);
2500 cifs_ace->cifs_uid = cpu_to_le64(le32_to_cpu(local_ace->e_id));
2501 /*cFYI(1,("perm %d tag %d id %d",ace->e_perm,ace->e_tag,ace->e_id));*/
2505 /* Convert ACL from local Linux POSIX xattr to CIFS POSIX ACL wire format */
2506 static __u16 ACL_to_cifs_posix(char * parm_data,const char * pACL,const int buflen,
2510 struct cifs_posix_acl * cifs_acl = (struct cifs_posix_acl *)parm_data;
2511 posix_acl_xattr_header * local_acl = (posix_acl_xattr_header *)pACL;
2515 if((buflen == 0) || (pACL == NULL) || (cifs_acl == NULL))
2518 count = posix_acl_xattr_count((size_t)buflen);
2519 cFYI(1,("setting acl with %d entries from buf of length %d and version of %d",
2520 count, buflen, le32_to_cpu(local_acl->a_version)));
2521 if(le32_to_cpu(local_acl->a_version) != 2) {
2522 cFYI(1,("unknown POSIX ACL version %d",
2523 le32_to_cpu(local_acl->a_version)));
2526 cifs_acl->version = cpu_to_le16(1);
2527 if(acl_type == ACL_TYPE_ACCESS)
2528 cifs_acl->access_entry_count = cpu_to_le16(count);
2529 else if(acl_type == ACL_TYPE_DEFAULT)
2530 cifs_acl->default_entry_count = cpu_to_le16(count);
2532 cFYI(1,("unknown ACL type %d",acl_type));
2535 for(i=0;i<count;i++) {
2536 rc = convert_ace_to_cifs_ace(&cifs_acl->ace_array[i],
2537 &local_acl->a_entries[i]);
2539 /* ACE not converted */
2544 rc = (__u16)(count * sizeof(struct cifs_posix_ace));
2545 rc += sizeof(struct cifs_posix_acl);
2546 /* BB add check to make sure ACL does not overflow SMB */
2552 CIFSSMBGetPosixACL(const int xid, struct cifsTconInfo *tcon,
2553 const unsigned char *searchName,
2554 char *acl_inf, const int buflen, const int acl_type,
2555 const struct nls_table *nls_codepage, int remap)
2557 /* SMB_QUERY_POSIX_ACL */
2558 TRANSACTION2_QPI_REQ *pSMB = NULL;
2559 TRANSACTION2_QPI_RSP *pSMBr = NULL;
2563 __u16 params, byte_count;
2565 cFYI(1, ("In GetPosixACL (Unix) for path %s", searchName));
2568 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2573 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2575 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
2576 PATH_MAX, nls_codepage, remap);
2577 name_len++; /* trailing null */
2579 pSMB->FileName[name_len] = 0;
2580 pSMB->FileName[name_len+1] = 0;
2581 } else { /* BB improve the check for buffer overruns BB */
2582 name_len = strnlen(searchName, PATH_MAX);
2583 name_len++; /* trailing null */
2584 strncpy(pSMB->FileName, searchName, name_len);
2587 params = 2 /* level */ + 4 /* rsrvd */ + name_len /* incl null */ ;
2588 pSMB->TotalDataCount = 0;
2589 pSMB->MaxParameterCount = cpu_to_le16(2);
2590 /* BB find exact max data count below from sess structure BB */
2591 pSMB->MaxDataCount = cpu_to_le16(4000);
2592 pSMB->MaxSetupCount = 0;
2596 pSMB->Reserved2 = 0;
2597 pSMB->ParameterOffset = cpu_to_le16(
2598 offsetof(struct smb_com_transaction2_qpi_req ,InformationLevel) - 4);
2599 pSMB->DataCount = 0;
2600 pSMB->DataOffset = 0;
2601 pSMB->SetupCount = 1;
2602 pSMB->Reserved3 = 0;
2603 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
2604 byte_count = params + 1 /* pad */ ;
2605 pSMB->TotalParameterCount = cpu_to_le16(params);
2606 pSMB->ParameterCount = pSMB->TotalParameterCount;
2607 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_POSIX_ACL);
2608 pSMB->Reserved4 = 0;
2609 pSMB->hdr.smb_buf_length += byte_count;
2610 pSMB->ByteCount = cpu_to_le16(byte_count);
2612 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2613 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2614 cifs_stats_inc(&tcon->num_acl_get);
2616 cFYI(1, ("Send error in Query POSIX ACL = %d", rc));
2618 /* decode response */
2620 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
2621 if (rc || (pSMBr->ByteCount < 2))
2622 /* BB also check enough total bytes returned */
2623 rc = -EIO; /* bad smb */
2625 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
2626 __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
2627 rc = cifs_copy_posix_acl(acl_inf,
2628 (char *)&pSMBr->hdr.Protocol+data_offset,
2629 buflen,acl_type,count);
2632 cifs_buf_release(pSMB);
2639 CIFSSMBSetPosixACL(const int xid, struct cifsTconInfo *tcon,
2640 const unsigned char *fileName,
2641 const char *local_acl, const int buflen,
2643 const struct nls_table *nls_codepage, int remap)
2645 struct smb_com_transaction2_spi_req *pSMB = NULL;
2646 struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
2650 int bytes_returned = 0;
2651 __u16 params, byte_count, data_count, param_offset, offset;
2653 cFYI(1, ("In SetPosixACL (Unix) for path %s", fileName));
2655 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2659 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2661 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
2662 PATH_MAX, nls_codepage, remap);
2663 name_len++; /* trailing null */
2665 } else { /* BB improve the check for buffer overruns BB */
2666 name_len = strnlen(fileName, PATH_MAX);
2667 name_len++; /* trailing null */
2668 strncpy(pSMB->FileName, fileName, name_len);
2670 params = 6 + name_len;
2671 pSMB->MaxParameterCount = cpu_to_le16(2);
2672 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB size from sess */
2673 pSMB->MaxSetupCount = 0;
2677 pSMB->Reserved2 = 0;
2678 param_offset = offsetof(struct smb_com_transaction2_spi_req,
2679 InformationLevel) - 4;
2680 offset = param_offset + params;
2681 parm_data = ((char *) &pSMB->hdr.Protocol) + offset;
2682 pSMB->ParameterOffset = cpu_to_le16(param_offset);
2684 /* convert to on the wire format for POSIX ACL */
2685 data_count = ACL_to_cifs_posix(parm_data,local_acl,buflen,acl_type);
2687 if(data_count == 0) {
2689 goto setACLerrorExit;
2691 pSMB->DataOffset = cpu_to_le16(offset);
2692 pSMB->SetupCount = 1;
2693 pSMB->Reserved3 = 0;
2694 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
2695 pSMB->InformationLevel = cpu_to_le16(SMB_SET_POSIX_ACL);
2696 byte_count = 3 /* pad */ + params + data_count;
2697 pSMB->DataCount = cpu_to_le16(data_count);
2698 pSMB->TotalDataCount = pSMB->DataCount;
2699 pSMB->ParameterCount = cpu_to_le16(params);
2700 pSMB->TotalParameterCount = pSMB->ParameterCount;
2701 pSMB->Reserved4 = 0;
2702 pSMB->hdr.smb_buf_length += byte_count;
2703 pSMB->ByteCount = cpu_to_le16(byte_count);
2704 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2705 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2707 cFYI(1, ("Set POSIX ACL returned %d", rc));
2711 cifs_buf_release(pSMB);
2717 /* BB fix tabs in this function FIXME BB */
2719 CIFSGetExtAttr(const int xid, struct cifsTconInfo *tcon,
2720 const int netfid, __u64 * pExtAttrBits, __u64 *pMask)
2723 struct smb_t2_qfi_req *pSMB = NULL;
2724 struct smb_t2_qfi_rsp *pSMBr = NULL;
2726 __u16 params, byte_count;
2728 cFYI(1,("In GetExtAttr"));
2733 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2738 params = 2 /* level */ +2 /* fid */;
2739 pSMB->t2.TotalDataCount = 0;
2740 pSMB->t2.MaxParameterCount = cpu_to_le16(4);
2741 /* BB find exact max data count below from sess structure BB */
2742 pSMB->t2.MaxDataCount = cpu_to_le16(4000);
2743 pSMB->t2.MaxSetupCount = 0;
2744 pSMB->t2.Reserved = 0;
2746 pSMB->t2.Timeout = 0;
2747 pSMB->t2.Reserved2 = 0;
2748 pSMB->t2.ParameterOffset = cpu_to_le16(offsetof(struct smb_t2_qfi_req,
2750 pSMB->t2.DataCount = 0;
2751 pSMB->t2.DataOffset = 0;
2752 pSMB->t2.SetupCount = 1;
2753 pSMB->t2.Reserved3 = 0;
2754 pSMB->t2.SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION);
2755 byte_count = params + 1 /* pad */ ;
2756 pSMB->t2.TotalParameterCount = cpu_to_le16(params);
2757 pSMB->t2.ParameterCount = pSMB->t2.TotalParameterCount;
2758 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_ATTR_FLAGS);
2761 pSMB->hdr.smb_buf_length += byte_count;
2762 pSMB->t2.ByteCount = cpu_to_le16(byte_count);
2764 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2765 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2767 cFYI(1, ("error %d in GetExtAttr", rc));
2769 /* decode response */
2770 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
2771 if (rc || (pSMBr->ByteCount < 2))
2772 /* BB also check enough total bytes returned */
2773 /* If rc should we check for EOPNOSUPP and
2774 disable the srvino flag? or in caller? */
2775 rc = -EIO; /* bad smb */
2777 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
2778 __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
2779 struct file_chattr_info * pfinfo;
2780 /* BB Do we need a cast or hash here ? */
2782 cFYI(1, ("Illegal size ret in GetExtAttr"));
2786 pfinfo = (struct file_chattr_info *)
2787 (data_offset + (char *) &pSMBr->hdr.Protocol);
2788 *pExtAttrBits = le64_to_cpu(pfinfo->mode);
2789 *pMask = le64_to_cpu(pfinfo->mask);
2793 cifs_buf_release(pSMB);
2795 goto GetExtAttrRetry;
2800 #endif /* CONFIG_POSIX */
2803 /* security id for everyone */
2804 const static struct cifs_sid sid_everyone =
2805 {1, 1, {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0}};
2807 const static struct cifs_sid sid_user =
2808 {1, 2 , {0, 0, 0, 0, 0, 5}, {32, 545, 0, 0}};
2810 /* Convert CIFS ACL to POSIX form */
2811 static int parse_sec_desc(struct cifs_sid * psec_desc, int acl_len)
2816 /* Get Security Descriptor (by handle) from remote server for a file or dir */
2818 CIFSSMBGetCIFSACL(const int xid, struct cifsTconInfo *tcon, __u16 fid,
2819 /* BB fix up return info */ char *acl_inf, const int buflen,
2820 const int acl_type /* ACCESS/DEFAULT not sure implication */)
2824 QUERY_SEC_DESC_REQ * pSMB;
2827 cFYI(1, ("GetCifsACL"));
2829 rc = smb_init_ntransact(NT_TRANSACT_QUERY_SECURITY_DESC, 0,
2830 8 /* parm len */, tcon, (void **) &pSMB);
2834 pSMB->MaxParameterCount = cpu_to_le32(4);
2835 /* BB TEST with big acls that might need to be e.g. larger than 16K */
2836 pSMB->MaxSetupCount = 0;
2837 pSMB->Fid = fid; /* file handle always le */
2838 pSMB->AclFlags = cpu_to_le32(CIFS_ACL_OWNER | CIFS_ACL_GROUP |
2840 pSMB->ByteCount = cpu_to_le16(11); /* 3 bytes pad + 8 bytes parm */
2841 pSMB->hdr.smb_buf_length += 11;
2842 iov[0].iov_base = (char *)pSMB;
2843 iov[0].iov_len = pSMB->hdr.smb_buf_length + 4;
2845 rc = SendReceive2(xid, tcon->ses, iov, 1 /* num iovec */, &buf_type, 0);
2846 cifs_stats_inc(&tcon->num_acl_get);
2848 cFYI(1, ("Send error in QuerySecDesc = %d", rc));
2849 } else { /* decode response */
2850 struct cifs_sid * psec_desc;
2855 struct smb_com_ntransact_rsp * pSMBr;
2857 /* validate_nttransact */
2858 rc = validate_ntransact(iov[0].iov_base, (char **)&parm,
2859 (char **)&psec_desc,
2860 &parm_len, &data_len);
2864 pSMBr = (struct smb_com_ntransact_rsp *)iov[0].iov_base;
2866 cERROR(1,("smb %p parm %p data %p",pSMBr,parm,psec_desc)); /* BB removeme BB */
2868 if (le32_to_cpu(pSMBr->ParameterCount) != 4) {
2869 rc = -EIO; /* bad smb */
2873 /* BB check that data area is minimum length and as big as acl_len */
2875 acl_len = le32_to_cpu(*(__le32 *)parm);
2876 /* BB check if(acl_len > bufsize) */
2878 parse_sec_desc(psec_desc, acl_len);
2881 if(buf_type == CIFS_SMALL_BUFFER)
2882 cifs_small_buf_release(iov[0].iov_base);
2883 else if(buf_type == CIFS_LARGE_BUFFER)
2884 cifs_buf_release(iov[0].iov_base);
2885 /* cifs_small_buf_release(pSMB); */ /* Freed earlier now in SendReceive2 */
2889 /* Legacy Query Path Information call for lookup to old servers such
2891 int SMBQueryInformation(const int xid, struct cifsTconInfo *tcon,
2892 const unsigned char *searchName,
2893 FILE_ALL_INFO * pFinfo,
2894 const struct nls_table *nls_codepage, int remap)
2896 QUERY_INFORMATION_REQ * pSMB;
2897 QUERY_INFORMATION_RSP * pSMBr;
2902 cFYI(1, ("In SMBQPath path %s", searchName));
2904 rc = smb_init(SMB_COM_QUERY_INFORMATION, 0, tcon, (void **) &pSMB,
2909 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2911 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
2912 PATH_MAX, nls_codepage, remap);
2913 name_len++; /* trailing null */
2916 name_len = strnlen(searchName, PATH_MAX);
2917 name_len++; /* trailing null */
2918 strncpy(pSMB->FileName, searchName, name_len);
2920 pSMB->BufferFormat = 0x04;
2921 name_len++; /* account for buffer type byte */
2922 pSMB->hdr.smb_buf_length += (__u16) name_len;
2923 pSMB->ByteCount = cpu_to_le16(name_len);
2925 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2926 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2928 cFYI(1, ("Send error in QueryInfo = %d", rc));
2929 } else if (pFinfo) { /* decode response */
2931 __u32 time = le32_to_cpu(pSMBr->last_write_time);
2932 /* BB FIXME - add time zone adjustment BB */
2933 memset(pFinfo, 0, sizeof(FILE_ALL_INFO));
2936 /* decode time fields */
2937 pFinfo->ChangeTime = cifs_UnixTimeToNT(ts);
2938 pFinfo->LastWriteTime = pFinfo->ChangeTime;
2939 pFinfo->LastAccessTime = 0;
2940 pFinfo->AllocationSize =
2941 cpu_to_le64(le32_to_cpu(pSMBr->size));
2942 pFinfo->EndOfFile = pFinfo->AllocationSize;
2943 pFinfo->Attributes =
2944 cpu_to_le32(le16_to_cpu(pSMBr->attr));
2946 rc = -EIO; /* bad buffer passed in */
2948 cifs_buf_release(pSMB);
2960 CIFSSMBQPathInfo(const int xid, struct cifsTconInfo *tcon,
2961 const unsigned char *searchName,
2962 FILE_ALL_INFO * pFindData,
2963 const struct nls_table *nls_codepage, int remap)
2965 /* level 263 SMB_QUERY_FILE_ALL_INFO */
2966 TRANSACTION2_QPI_REQ *pSMB = NULL;
2967 TRANSACTION2_QPI_RSP *pSMBr = NULL;
2971 __u16 params, byte_count;
2973 /* cFYI(1, ("In QPathInfo path %s", searchName)); */
2975 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2980 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2982 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
2983 PATH_MAX, nls_codepage, remap);
2984 name_len++; /* trailing null */
2986 } else { /* BB improve the check for buffer overruns BB */
2987 name_len = strnlen(searchName, PATH_MAX);
2988 name_len++; /* trailing null */
2989 strncpy(pSMB->FileName, searchName, name_len);
2992 params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */ ;
2993 pSMB->TotalDataCount = 0;
2994 pSMB->MaxParameterCount = cpu_to_le16(2);
2995 pSMB->MaxDataCount = cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
2996 pSMB->MaxSetupCount = 0;
3000 pSMB->Reserved2 = 0;
3001 pSMB->ParameterOffset = cpu_to_le16(offsetof(
3002 struct smb_com_transaction2_qpi_req ,InformationLevel) - 4);
3003 pSMB->DataCount = 0;
3004 pSMB->DataOffset = 0;
3005 pSMB->SetupCount = 1;
3006 pSMB->Reserved3 = 0;
3007 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
3008 byte_count = params + 1 /* pad */ ;
3009 pSMB->TotalParameterCount = cpu_to_le16(params);
3010 pSMB->ParameterCount = pSMB->TotalParameterCount;
3011 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_ALL_INFO);
3012 pSMB->Reserved4 = 0;
3013 pSMB->hdr.smb_buf_length += byte_count;
3014 pSMB->ByteCount = cpu_to_le16(byte_count);
3016 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3017 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3019 cFYI(1, ("Send error in QPathInfo = %d", rc));
3020 } else { /* decode response */
3021 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3023 if (rc || (pSMBr->ByteCount < 40))
3024 rc = -EIO; /* bad smb */
3025 else if (pFindData){
3026 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3027 memcpy((char *) pFindData,
3028 (char *) &pSMBr->hdr.Protocol +
3029 data_offset, sizeof (FILE_ALL_INFO));
3033 cifs_buf_release(pSMB);
3035 goto QPathInfoRetry;
3041 CIFSSMBUnixQPathInfo(const int xid, struct cifsTconInfo *tcon,
3042 const unsigned char *searchName,
3043 FILE_UNIX_BASIC_INFO * pFindData,
3044 const struct nls_table *nls_codepage, int remap)
3046 /* SMB_QUERY_FILE_UNIX_BASIC */
3047 TRANSACTION2_QPI_REQ *pSMB = NULL;
3048 TRANSACTION2_QPI_RSP *pSMBr = NULL;
3050 int bytes_returned = 0;
3052 __u16 params, byte_count;
3054 cFYI(1, ("In QPathInfo (Unix) the path %s", searchName));
3056 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3061 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3063 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
3064 PATH_MAX, nls_codepage, remap);
3065 name_len++; /* trailing null */
3067 } else { /* BB improve the check for buffer overruns BB */
3068 name_len = strnlen(searchName, PATH_MAX);
3069 name_len++; /* trailing null */
3070 strncpy(pSMB->FileName, searchName, name_len);
3073 params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */ ;
3074 pSMB->TotalDataCount = 0;
3075 pSMB->MaxParameterCount = cpu_to_le16(2);
3076 /* BB find exact max SMB PDU from sess structure BB */
3077 pSMB->MaxDataCount = cpu_to_le16(4000);
3078 pSMB->MaxSetupCount = 0;
3082 pSMB->Reserved2 = 0;
3083 pSMB->ParameterOffset = cpu_to_le16(offsetof(
3084 struct smb_com_transaction2_qpi_req ,InformationLevel) - 4);
3085 pSMB->DataCount = 0;
3086 pSMB->DataOffset = 0;
3087 pSMB->SetupCount = 1;
3088 pSMB->Reserved3 = 0;
3089 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
3090 byte_count = params + 1 /* pad */ ;
3091 pSMB->TotalParameterCount = cpu_to_le16(params);
3092 pSMB->ParameterCount = pSMB->TotalParameterCount;
3093 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC);
3094 pSMB->Reserved4 = 0;
3095 pSMB->hdr.smb_buf_length += byte_count;
3096 pSMB->ByteCount = cpu_to_le16(byte_count);
3098 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3099 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3101 cFYI(1, ("Send error in QPathInfo = %d", rc));
3102 } else { /* decode response */
3103 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3105 if (rc || (pSMBr->ByteCount < sizeof(FILE_UNIX_BASIC_INFO))) {
3106 rc = -EIO; /* bad smb */
3108 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3109 memcpy((char *) pFindData,
3110 (char *) &pSMBr->hdr.Protocol +
3112 sizeof (FILE_UNIX_BASIC_INFO));
3115 cifs_buf_release(pSMB);
3117 goto UnixQPathInfoRetry;
3122 #if 0 /* function unused at present */
3123 int CIFSFindSingle(const int xid, struct cifsTconInfo *tcon,
3124 const char *searchName, FILE_ALL_INFO * findData,
3125 const struct nls_table *nls_codepage)
3127 /* level 257 SMB_ */
3128 TRANSACTION2_FFIRST_REQ *pSMB = NULL;
3129 TRANSACTION2_FFIRST_RSP *pSMBr = NULL;
3133 __u16 params, byte_count;
3135 cFYI(1, ("In FindUnique"));
3137 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3142 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3144 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName, PATH_MAX
3145 /* find define for this maxpathcomponent */
3147 name_len++; /* trailing null */
3149 } else { /* BB improve the check for buffer overruns BB */
3150 name_len = strnlen(searchName, PATH_MAX);
3151 name_len++; /* trailing null */
3152 strncpy(pSMB->FileName, searchName, name_len);
3155 params = 12 + name_len /* includes null */ ;
3156 pSMB->TotalDataCount = 0; /* no EAs */
3157 pSMB->MaxParameterCount = cpu_to_le16(2);
3158 pSMB->MaxDataCount = cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
3159 pSMB->MaxSetupCount = 0;
3163 pSMB->Reserved2 = 0;
3164 pSMB->ParameterOffset = cpu_to_le16(
3165 offsetof(struct smb_com_transaction2_ffirst_req,InformationLevel) - 4);
3166 pSMB->DataCount = 0;
3167 pSMB->DataOffset = 0;
3168 pSMB->SetupCount = 1; /* one byte, no need to le convert */
3169 pSMB->Reserved3 = 0;
3170 pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_FIRST);
3171 byte_count = params + 1 /* pad */ ;
3172 pSMB->TotalParameterCount = cpu_to_le16(params);
3173 pSMB->ParameterCount = pSMB->TotalParameterCount;
3174 pSMB->SearchAttributes =
3175 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
3177 pSMB->SearchCount = cpu_to_le16(16); /* BB increase */
3178 pSMB->SearchFlags = cpu_to_le16(1);
3179 pSMB->InformationLevel = cpu_to_le16(SMB_FIND_FILE_DIRECTORY_INFO);
3180 pSMB->SearchStorageType = 0; /* BB what should we set this to? BB */
3181 pSMB->hdr.smb_buf_length += byte_count;
3182 pSMB->ByteCount = cpu_to_le16(byte_count);
3184 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3185 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3188 cFYI(1, ("Send error in FindFileDirInfo = %d", rc));
3189 } else { /* decode response */
3190 cifs_stats_inc(&tcon->num_ffirst);
3194 cifs_buf_release(pSMB);
3196 goto findUniqueRetry;
3200 #endif /* end unused (temporarily) function */
3202 /* xid, tcon, searchName and codepage are input parms, rest are returned */
3204 CIFSFindFirst(const int xid, struct cifsTconInfo *tcon,
3205 const char *searchName,
3206 const struct nls_table *nls_codepage,
3208 struct cifs_search_info * psrch_inf, int remap, const char dirsep)
3210 /* level 257 SMB_ */
3211 TRANSACTION2_FFIRST_REQ *pSMB = NULL;
3212 TRANSACTION2_FFIRST_RSP *pSMBr = NULL;
3213 T2_FFIRST_RSP_PARMS * parms;
3215 int bytes_returned = 0;
3217 __u16 params, byte_count;
3219 cFYI(1, ("In FindFirst for %s",searchName));
3222 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3227 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3229 cifsConvertToUCS((__le16 *) pSMB->FileName,searchName,
3230 PATH_MAX, nls_codepage, remap);
3231 /* We can not add the asterik earlier in case
3232 it got remapped to 0xF03A as if it were part of the
3233 directory name instead of a wildcard */
3235 pSMB->FileName[name_len] = dirsep;
3236 pSMB->FileName[name_len+1] = 0;
3237 pSMB->FileName[name_len+2] = '*';
3238 pSMB->FileName[name_len+3] = 0;
3239 name_len += 4; /* now the trailing null */
3240 pSMB->FileName[name_len] = 0; /* null terminate just in case */
3241 pSMB->FileName[name_len+1] = 0;
3243 } else { /* BB add check for overrun of SMB buf BB */
3244 name_len = strnlen(searchName, PATH_MAX);
3245 /* BB fix here and in unicode clause above ie
3246 if(name_len > buffersize-header)
3247 free buffer exit; BB */
3248 strncpy(pSMB->FileName, searchName, name_len);
3249 pSMB->FileName[name_len] = dirsep;
3250 pSMB->FileName[name_len+1] = '*';
3251 pSMB->FileName[name_len+2] = 0;
3255 params = 12 + name_len /* includes null */ ;
3256 pSMB->TotalDataCount = 0; /* no EAs */
3257 pSMB->MaxParameterCount = cpu_to_le16(10);
3258 pSMB->MaxDataCount = cpu_to_le16((tcon->ses->server->maxBuf -
3259 MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
3260 pSMB->MaxSetupCount = 0;
3264 pSMB->Reserved2 = 0;
3265 byte_count = params + 1 /* pad */ ;
3266 pSMB->TotalParameterCount = cpu_to_le16(params);
3267 pSMB->ParameterCount = pSMB->TotalParameterCount;
3268 pSMB->ParameterOffset = cpu_to_le16(
3269 offsetof(struct smb_com_transaction2_ffirst_req, SearchAttributes)
3271 pSMB->DataCount = 0;
3272 pSMB->DataOffset = 0;
3273 pSMB->SetupCount = 1; /* one byte, no need to make endian neutral */
3274 pSMB->Reserved3 = 0;
3275 pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_FIRST);
3276 pSMB->SearchAttributes =
3277 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
3279 pSMB->SearchCount= cpu_to_le16(CIFSMaxBufSize/sizeof(FILE_UNIX_INFO));
3280 pSMB->SearchFlags = cpu_to_le16(CIFS_SEARCH_CLOSE_AT_END |
3281 CIFS_SEARCH_RETURN_RESUME);
3282 pSMB->InformationLevel = cpu_to_le16(psrch_inf->info_level);
3284 /* BB what should we set StorageType to? Does it matter? BB */
3285 pSMB->SearchStorageType = 0;
3286 pSMB->hdr.smb_buf_length += byte_count;
3287 pSMB->ByteCount = cpu_to_le16(byte_count);
3289 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3290 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3291 cifs_stats_inc(&tcon->num_ffirst);
3293 if (rc) {/* BB add logic to retry regular search if Unix search
3294 rejected unexpectedly by server */
3295 /* BB Add code to handle unsupported level rc */
3296 cFYI(1, ("Error in FindFirst = %d", rc));
3298 cifs_buf_release(pSMB);
3300 /* BB eventually could optimize out free and realloc of buf */
3303 goto findFirstRetry;
3304 } else { /* decode response */
3305 /* BB remember to free buffer if error BB */
3306 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3308 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
3309 psrch_inf->unicode = TRUE;
3311 psrch_inf->unicode = FALSE;
3313 psrch_inf->ntwrk_buf_start = (char *)pSMBr;
3314 psrch_inf->smallBuf = 0;
3315 psrch_inf->srch_entries_start =
3316 (char *) &pSMBr->hdr.Protocol +
3317 le16_to_cpu(pSMBr->t2.DataOffset);
3318 parms = (T2_FFIRST_RSP_PARMS *)((char *) &pSMBr->hdr.Protocol +
3319 le16_to_cpu(pSMBr->t2.ParameterOffset));
3321 if(parms->EndofSearch)
3322 psrch_inf->endOfSearch = TRUE;
3324 psrch_inf->endOfSearch = FALSE;
3326 psrch_inf->entries_in_buffer = le16_to_cpu(parms->SearchCount);
3327 psrch_inf->index_of_last_entry = 2 /* skip . and .. */ +
3328 psrch_inf->entries_in_buffer;
3329 *pnetfid = parms->SearchHandle;
3331 cifs_buf_release(pSMB);
3338 int CIFSFindNext(const int xid, struct cifsTconInfo *tcon,
3339 __u16 searchHandle, struct cifs_search_info * psrch_inf)
3341 TRANSACTION2_FNEXT_REQ *pSMB = NULL;
3342 TRANSACTION2_FNEXT_RSP *pSMBr = NULL;
3343 T2_FNEXT_RSP_PARMS * parms;
3344 char *response_data;
3346 int bytes_returned, name_len;
3347 __u16 params, byte_count;
3349 cFYI(1, ("In FindNext"));
3351 if(psrch_inf->endOfSearch == TRUE)
3354 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3359 params = 14; /* includes 2 bytes of null string, converted to LE below */
3361 pSMB->TotalDataCount = 0; /* no EAs */
3362 pSMB->MaxParameterCount = cpu_to_le16(8);
3363 pSMB->MaxDataCount =
3364 cpu_to_le16((tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
3365 pSMB->MaxSetupCount = 0;
3369 pSMB->Reserved2 = 0;
3370 pSMB->ParameterOffset = cpu_to_le16(
3371 offsetof(struct smb_com_transaction2_fnext_req,SearchHandle) - 4);
3372 pSMB->DataCount = 0;
3373 pSMB->DataOffset = 0;
3374 pSMB->SetupCount = 1;
3375 pSMB->Reserved3 = 0;
3376 pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_NEXT);
3377 pSMB->SearchHandle = searchHandle; /* always kept as le */
3379 cpu_to_le16(CIFSMaxBufSize / sizeof (FILE_UNIX_INFO));
3380 /* test for Unix extensions */
3381 /* if (tcon->ses->capabilities & CAP_UNIX) {
3382 pSMB->InformationLevel = cpu_to_le16(SMB_FIND_FILE_UNIX);
3383 psrch_inf->info_level = SMB_FIND_FILE_UNIX;
3385 pSMB->InformationLevel =
3386 cpu_to_le16(SMB_FIND_FILE_DIRECTORY_INFO);
3387 psrch_inf->info_level = SMB_FIND_FILE_DIRECTORY_INFO;
3389 pSMB->InformationLevel = cpu_to_le16(psrch_inf->info_level);
3390 pSMB->ResumeKey = psrch_inf->resume_key;
3392 cpu_to_le16(CIFS_SEARCH_CLOSE_AT_END | CIFS_SEARCH_RETURN_RESUME);
3394 name_len = psrch_inf->resume_name_len;
3396 if(name_len < PATH_MAX) {
3397 memcpy(pSMB->ResumeFileName, psrch_inf->presume_name, name_len);
3398 byte_count += name_len;
3399 /* 14 byte parm len above enough for 2 byte null terminator */
3400 pSMB->ResumeFileName[name_len] = 0;
3401 pSMB->ResumeFileName[name_len+1] = 0;
3404 goto FNext2_err_exit;
3406 byte_count = params + 1 /* pad */ ;
3407 pSMB->TotalParameterCount = cpu_to_le16(params);
3408 pSMB->ParameterCount = pSMB->TotalParameterCount;
3409 pSMB->hdr.smb_buf_length += byte_count;
3410 pSMB->ByteCount = cpu_to_le16(byte_count);
3412 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3413 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3414 cifs_stats_inc(&tcon->num_fnext);
3417 psrch_inf->endOfSearch = TRUE;
3418 rc = 0; /* search probably was closed at end of search above */
3420 cFYI(1, ("FindNext returned = %d", rc));
3421 } else { /* decode response */
3422 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3425 /* BB fixme add lock for file (srch_info) struct here */
3426 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
3427 psrch_inf->unicode = TRUE;
3429 psrch_inf->unicode = FALSE;
3430 response_data = (char *) &pSMBr->hdr.Protocol +
3431 le16_to_cpu(pSMBr->t2.ParameterOffset);
3432 parms = (T2_FNEXT_RSP_PARMS *)response_data;
3433 response_data = (char *)&pSMBr->hdr.Protocol +
3434 le16_to_cpu(pSMBr->t2.DataOffset);
3435 if(psrch_inf->smallBuf)
3436 cifs_small_buf_release(
3437 psrch_inf->ntwrk_buf_start);
3439 cifs_buf_release(psrch_inf->ntwrk_buf_start);
3440 psrch_inf->srch_entries_start = response_data;
3441 psrch_inf->ntwrk_buf_start = (char *)pSMB;
3442 psrch_inf->smallBuf = 0;
3443 if(parms->EndofSearch)
3444 psrch_inf->endOfSearch = TRUE;
3446 psrch_inf->endOfSearch = FALSE;
3448 psrch_inf->entries_in_buffer = le16_to_cpu(parms->SearchCount);
3449 psrch_inf->index_of_last_entry +=
3450 psrch_inf->entries_in_buffer;
3451 /* cFYI(1,("fnxt2 entries in buf %d index_of_last %d",psrch_inf->entries_in_buffer,psrch_inf->index_of_last_entry)); */
3453 /* BB fixme add unlock here */
3458 /* BB On error, should we leave previous search buf (and count and
3459 last entry fields) intact or free the previous one? */
3461 /* Note: On -EAGAIN error only caller can retry on handle based calls
3462 since file handle passed in no longer valid */
3465 cifs_buf_release(pSMB);
3471 CIFSFindClose(const int xid, struct cifsTconInfo *tcon, const __u16 searchHandle)
3474 FINDCLOSE_REQ *pSMB = NULL;
3475 CLOSE_RSP *pSMBr = NULL; /* BB removeme BB */
3478 cFYI(1, ("In CIFSSMBFindClose"));
3479 rc = small_smb_init(SMB_COM_FIND_CLOSE2, 1, tcon, (void **)&pSMB);
3481 /* no sense returning error if session restarted
3482 as file handle has been closed */
3488 pSMBr = (CLOSE_RSP *)pSMB; /* BB removeme BB */
3489 pSMB->FileID = searchHandle;
3490 pSMB->ByteCount = 0;
3491 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3492 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3494 cERROR(1, ("Send error in FindClose = %d", rc));
3496 cifs_stats_inc(&tcon->num_fclose);
3497 cifs_small_buf_release(pSMB);
3499 /* Since session is dead, search handle closed on server already */
3507 CIFSGetSrvInodeNumber(const int xid, struct cifsTconInfo *tcon,
3508 const unsigned char *searchName,
3509 __u64 * inode_number,
3510 const struct nls_table *nls_codepage, int remap)
3513 TRANSACTION2_QPI_REQ *pSMB = NULL;
3514 TRANSACTION2_QPI_RSP *pSMBr = NULL;
3515 int name_len, bytes_returned;
3516 __u16 params, byte_count;
3518 cFYI(1,("In GetSrvInodeNum for %s",searchName));
3522 GetInodeNumberRetry:
3523 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3529 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3531 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
3532 PATH_MAX,nls_codepage, remap);
3533 name_len++; /* trailing null */
3535 } else { /* BB improve the check for buffer overruns BB */
3536 name_len = strnlen(searchName, PATH_MAX);
3537 name_len++; /* trailing null */
3538 strncpy(pSMB->FileName, searchName, name_len);
3541 params = 2 /* level */ + 4 /* rsrvd */ + name_len /* incl null */ ;
3542 pSMB->TotalDataCount = 0;
3543 pSMB->MaxParameterCount = cpu_to_le16(2);
3544 /* BB find exact max data count below from sess structure BB */
3545 pSMB->MaxDataCount = cpu_to_le16(4000);
3546 pSMB->MaxSetupCount = 0;
3550 pSMB->Reserved2 = 0;
3551 pSMB->ParameterOffset = cpu_to_le16(offsetof(
3552 struct smb_com_transaction2_qpi_req ,InformationLevel) - 4);
3553 pSMB->DataCount = 0;
3554 pSMB->DataOffset = 0;
3555 pSMB->SetupCount = 1;
3556 pSMB->Reserved3 = 0;
3557 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
3558 byte_count = params + 1 /* pad */ ;
3559 pSMB->TotalParameterCount = cpu_to_le16(params);
3560 pSMB->ParameterCount = pSMB->TotalParameterCount;
3561 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_INTERNAL_INFO);
3562 pSMB->Reserved4 = 0;
3563 pSMB->hdr.smb_buf_length += byte_count;
3564 pSMB->ByteCount = cpu_to_le16(byte_count);
3566 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3567 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3569 cFYI(1, ("error %d in QueryInternalInfo", rc));
3571 /* decode response */
3572 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3573 if (rc || (pSMBr->ByteCount < 2))
3574 /* BB also check enough total bytes returned */
3575 /* If rc should we check for EOPNOSUPP and
3576 disable the srvino flag? or in caller? */
3577 rc = -EIO; /* bad smb */
3579 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3580 __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
3581 struct file_internal_info * pfinfo;
3582 /* BB Do we need a cast or hash here ? */
3584 cFYI(1, ("Illegal size ret in QryIntrnlInf"));
3586 goto GetInodeNumOut;
3588 pfinfo = (struct file_internal_info *)
3589 (data_offset + (char *) &pSMBr->hdr.Protocol);
3590 *inode_number = pfinfo->UniqueId;
3594 cifs_buf_release(pSMB);
3596 goto GetInodeNumberRetry;
3601 CIFSGetDFSRefer(const int xid, struct cifsSesInfo *ses,
3602 const unsigned char *searchName,
3603 unsigned char **targetUNCs,
3604 unsigned int *number_of_UNC_in_array,
3605 const struct nls_table *nls_codepage, int remap)
3607 /* TRANS2_GET_DFS_REFERRAL */
3608 TRANSACTION2_GET_DFS_REFER_REQ *pSMB = NULL;
3609 TRANSACTION2_GET_DFS_REFER_RSP *pSMBr = NULL;
3610 struct dfs_referral_level_3 * referrals = NULL;
3616 __u16 params, byte_count;
3617 *number_of_UNC_in_array = 0;
3620 cFYI(1, ("In GetDFSRefer the path %s", searchName));
3624 rc = smb_init(SMB_COM_TRANSACTION2, 15, NULL, (void **) &pSMB,
3629 /* server pointer checked in called function,
3630 but should never be null here anyway */
3631 pSMB->hdr.Mid = GetNextMid(ses->server);
3632 pSMB->hdr.Tid = ses->ipc_tid;
3633 pSMB->hdr.Uid = ses->Suid;
3634 if (ses->capabilities & CAP_STATUS32) {
3635 pSMB->hdr.Flags2 |= SMBFLG2_ERR_STATUS;
3637 if (ses->capabilities & CAP_DFS) {
3638 pSMB->hdr.Flags2 |= SMBFLG2_DFS;
3641 if (ses->capabilities & CAP_UNICODE) {
3642 pSMB->hdr.Flags2 |= SMBFLG2_UNICODE;
3644 cifsConvertToUCS((__le16 *) pSMB->RequestFileName,
3645 searchName, PATH_MAX, nls_codepage, remap);
3646 name_len++; /* trailing null */
3648 } else { /* BB improve the check for buffer overruns BB */
3649 name_len = strnlen(searchName, PATH_MAX);
3650 name_len++; /* trailing null */
3651 strncpy(pSMB->RequestFileName, searchName, name_len);
3654 params = 2 /* level */ + name_len /*includes null */ ;
3655 pSMB->TotalDataCount = 0;
3656 pSMB->DataCount = 0;
3657 pSMB->DataOffset = 0;
3658 pSMB->MaxParameterCount = 0;
3659 pSMB->MaxDataCount = cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
3660 pSMB->MaxSetupCount = 0;
3664 pSMB->Reserved2 = 0;
3665 pSMB->ParameterOffset = cpu_to_le16(offsetof(
3666 struct smb_com_transaction2_get_dfs_refer_req, MaxReferralLevel) - 4);
3667 pSMB->SetupCount = 1;
3668 pSMB->Reserved3 = 0;
3669 pSMB->SubCommand = cpu_to_le16(TRANS2_GET_DFS_REFERRAL);
3670 byte_count = params + 3 /* pad */ ;
3671 pSMB->ParameterCount = cpu_to_le16(params);
3672 pSMB->TotalParameterCount = pSMB->ParameterCount;
3673 pSMB->MaxReferralLevel = cpu_to_le16(3);
3674 pSMB->hdr.smb_buf_length += byte_count;
3675 pSMB->ByteCount = cpu_to_le16(byte_count);
3677 rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB,
3678 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3680 cFYI(1, ("Send error in GetDFSRefer = %d", rc));
3681 } else { /* decode response */
3682 /* BB Add logic to parse referrals here */
3683 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3685 if (rc || (pSMBr->ByteCount < 17)) /* BB also check enough total bytes returned */
3686 rc = -EIO; /* bad smb */
3688 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3689 __u16 data_count = le16_to_cpu(pSMBr->t2.DataCount);
3692 ("Decoding GetDFSRefer response. BCC: %d Offset %d",
3693 pSMBr->ByteCount, data_offset));
3695 (struct dfs_referral_level_3 *)
3696 (8 /* sizeof start of data block */ +
3698 (char *) &pSMBr->hdr.Protocol);
3699 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",
3700 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)));
3701 /* BB This field is actually two bytes in from start of
3702 data block so we could do safety check that DataBlock
3703 begins at address of pSMBr->NumberOfReferrals */
3704 *number_of_UNC_in_array = le16_to_cpu(pSMBr->NumberOfReferrals);
3706 /* BB Fix below so can return more than one referral */
3707 if(*number_of_UNC_in_array > 1)
3708 *number_of_UNC_in_array = 1;
3710 /* get the length of the strings describing refs */
3712 for(i=0;i<*number_of_UNC_in_array;i++) {
3713 /* make sure that DfsPathOffset not past end */
3714 __u16 offset = le16_to_cpu(referrals->DfsPathOffset);
3715 if (offset > data_count) {
3716 /* if invalid referral, stop here and do
3717 not try to copy any more */
3718 *number_of_UNC_in_array = i;
3721 temp = ((char *)referrals) + offset;
3723 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
3724 name_len += UniStrnlen((wchar_t *)temp,data_count);
3726 name_len += strnlen(temp,data_count);
3729 /* BB add check that referral pointer does not fall off end PDU */
3732 /* BB add check for name_len bigger than bcc */
3734 kmalloc(name_len+1+ (*number_of_UNC_in_array),GFP_KERNEL);
3735 if(*targetUNCs == NULL) {
3739 /* copy the ref strings */
3741 (struct dfs_referral_level_3 *)
3742 (8 /* sizeof data hdr */ +
3744 (char *) &pSMBr->hdr.Protocol);
3746 for(i=0;i<*number_of_UNC_in_array;i++) {
3747 temp = ((char *)referrals) + le16_to_cpu(referrals->DfsPathOffset);
3748 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
3749 cifs_strfromUCS_le(*targetUNCs,
3750 (__le16 *) temp, name_len, nls_codepage);
3752 strncpy(*targetUNCs,temp,name_len);
3754 /* BB update target_uncs pointers */
3764 cifs_buf_release(pSMB);
3772 /* Query File System Info such as free space to old servers such as Win 9x */
3774 SMBOldQFSInfo(const int xid, struct cifsTconInfo *tcon, struct kstatfs *FSData)
3776 /* level 0x01 SMB_QUERY_FILE_SYSTEM_INFO */
3777 TRANSACTION2_QFSI_REQ *pSMB = NULL;
3778 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
3779 FILE_SYSTEM_ALLOC_INFO *response_data;
3781 int bytes_returned = 0;
3782 __u16 params, byte_count;
3784 cFYI(1, ("OldQFSInfo"));
3786 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3790 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3795 params = 2; /* level */
3796 pSMB->TotalDataCount = 0;
3797 pSMB->MaxParameterCount = cpu_to_le16(2);
3798 pSMB->MaxDataCount = cpu_to_le16(1000);
3799 pSMB->MaxSetupCount = 0;
3803 pSMB->Reserved2 = 0;
3804 byte_count = params + 1 /* pad */ ;
3805 pSMB->TotalParameterCount = cpu_to_le16(params);
3806 pSMB->ParameterCount = pSMB->TotalParameterCount;
3807 pSMB->ParameterOffset = cpu_to_le16(offsetof(
3808 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
3809 pSMB->DataCount = 0;
3810 pSMB->DataOffset = 0;
3811 pSMB->SetupCount = 1;
3812 pSMB->Reserved3 = 0;
3813 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
3814 pSMB->InformationLevel = cpu_to_le16(SMB_INFO_ALLOCATION);
3815 pSMB->hdr.smb_buf_length += byte_count;
3816 pSMB->ByteCount = cpu_to_le16(byte_count);
3818 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3819 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3821 cFYI(1, ("Send error in QFSInfo = %d", rc));
3822 } else { /* decode response */
3823 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3825 if (rc || (pSMBr->ByteCount < 18))
3826 rc = -EIO; /* bad smb */
3828 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3829 cFYI(1,("qfsinf resp BCC: %d Offset %d",
3830 pSMBr->ByteCount, data_offset));
3833 (FILE_SYSTEM_ALLOC_INFO *)
3834 (((char *) &pSMBr->hdr.Protocol) + data_offset);
3836 le16_to_cpu(response_data->BytesPerSector) *
3837 le32_to_cpu(response_data->
3838 SectorsPerAllocationUnit);
3840 le32_to_cpu(response_data->TotalAllocationUnits);
3841 FSData->f_bfree = FSData->f_bavail =
3842 le32_to_cpu(response_data->FreeAllocationUnits);
3844 ("Blocks: %lld Free: %lld Block size %ld",
3845 (unsigned long long)FSData->f_blocks,
3846 (unsigned long long)FSData->f_bfree,
3850 cifs_buf_release(pSMB);
3853 goto oldQFSInfoRetry;
3859 CIFSSMBQFSInfo(const int xid, struct cifsTconInfo *tcon, struct kstatfs *FSData)
3861 /* level 0x103 SMB_QUERY_FILE_SYSTEM_INFO */
3862 TRANSACTION2_QFSI_REQ *pSMB = NULL;
3863 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
3864 FILE_SYSTEM_INFO *response_data;
3866 int bytes_returned = 0;
3867 __u16 params, byte_count;
3869 cFYI(1, ("In QFSInfo"));
3871 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3876 params = 2; /* level */
3877 pSMB->TotalDataCount = 0;
3878 pSMB->MaxParameterCount = cpu_to_le16(2);
3879 pSMB->MaxDataCount = cpu_to_le16(1000);
3880 pSMB->MaxSetupCount = 0;
3884 pSMB->Reserved2 = 0;
3885 byte_count = params + 1 /* pad */ ;
3886 pSMB->TotalParameterCount = cpu_to_le16(params);
3887 pSMB->ParameterCount = pSMB->TotalParameterCount;
3888 pSMB->ParameterOffset = cpu_to_le16(offsetof(
3889 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
3890 pSMB->DataCount = 0;
3891 pSMB->DataOffset = 0;
3892 pSMB->SetupCount = 1;
3893 pSMB->Reserved3 = 0;
3894 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
3895 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_SIZE_INFO);
3896 pSMB->hdr.smb_buf_length += byte_count;
3897 pSMB->ByteCount = cpu_to_le16(byte_count);
3899 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3900 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3902 cFYI(1, ("Send error in QFSInfo = %d", rc));
3903 } else { /* decode response */
3904 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3906 if (rc || (pSMBr->ByteCount < 24))
3907 rc = -EIO; /* bad smb */
3909 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3913 *) (((char *) &pSMBr->hdr.Protocol) +
3916 le32_to_cpu(response_data->BytesPerSector) *
3917 le32_to_cpu(response_data->
3918 SectorsPerAllocationUnit);
3920 le64_to_cpu(response_data->TotalAllocationUnits);
3921 FSData->f_bfree = FSData->f_bavail =
3922 le64_to_cpu(response_data->FreeAllocationUnits);
3924 ("Blocks: %lld Free: %lld Block size %ld",
3925 (unsigned long long)FSData->f_blocks,
3926 (unsigned long long)FSData->f_bfree,
3930 cifs_buf_release(pSMB);
3939 CIFSSMBQFSAttributeInfo(const int xid, struct cifsTconInfo *tcon)
3941 /* level 0x105 SMB_QUERY_FILE_SYSTEM_INFO */
3942 TRANSACTION2_QFSI_REQ *pSMB = NULL;
3943 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
3944 FILE_SYSTEM_ATTRIBUTE_INFO *response_data;
3946 int bytes_returned = 0;
3947 __u16 params, byte_count;
3949 cFYI(1, ("In QFSAttributeInfo"));
3951 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3956 params = 2; /* level */
3957 pSMB->TotalDataCount = 0;
3958 pSMB->MaxParameterCount = cpu_to_le16(2);
3959 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
3960 pSMB->MaxSetupCount = 0;
3964 pSMB->Reserved2 = 0;
3965 byte_count = params + 1 /* pad */ ;
3966 pSMB->TotalParameterCount = cpu_to_le16(params);
3967 pSMB->ParameterCount = pSMB->TotalParameterCount;
3968 pSMB->ParameterOffset = cpu_to_le16(offsetof(
3969 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
3970 pSMB->DataCount = 0;
3971 pSMB->DataOffset = 0;
3972 pSMB->SetupCount = 1;
3973 pSMB->Reserved3 = 0;
3974 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
3975 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_ATTRIBUTE_INFO);
3976 pSMB->hdr.smb_buf_length += byte_count;
3977 pSMB->ByteCount = cpu_to_le16(byte_count);
3979 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3980 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3982 cERROR(1, ("Send error in QFSAttributeInfo = %d", rc));
3983 } else { /* decode response */
3984 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3986 if (rc || (pSMBr->ByteCount < 13)) { /* BB also check enough bytes returned */
3987 rc = -EIO; /* bad smb */
3989 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3991 (FILE_SYSTEM_ATTRIBUTE_INFO
3992 *) (((char *) &pSMBr->hdr.Protocol) +
3994 memcpy(&tcon->fsAttrInfo, response_data,
3995 sizeof (FILE_SYSTEM_ATTRIBUTE_INFO));
3998 cifs_buf_release(pSMB);
4001 goto QFSAttributeRetry;
4007 CIFSSMBQFSDeviceInfo(const int xid, struct cifsTconInfo *tcon)
4009 /* level 0x104 SMB_QUERY_FILE_SYSTEM_INFO */
4010 TRANSACTION2_QFSI_REQ *pSMB = NULL;
4011 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4012 FILE_SYSTEM_DEVICE_INFO *response_data;
4014 int bytes_returned = 0;
4015 __u16 params, byte_count;
4017 cFYI(1, ("In QFSDeviceInfo"));
4019 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4024 params = 2; /* level */
4025 pSMB->TotalDataCount = 0;
4026 pSMB->MaxParameterCount = cpu_to_le16(2);
4027 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
4028 pSMB->MaxSetupCount = 0;
4032 pSMB->Reserved2 = 0;
4033 byte_count = params + 1 /* pad */ ;
4034 pSMB->TotalParameterCount = cpu_to_le16(params);
4035 pSMB->ParameterCount = pSMB->TotalParameterCount;
4036 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4037 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4039 pSMB->DataCount = 0;
4040 pSMB->DataOffset = 0;
4041 pSMB->SetupCount = 1;
4042 pSMB->Reserved3 = 0;
4043 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4044 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_DEVICE_INFO);
4045 pSMB->hdr.smb_buf_length += byte_count;
4046 pSMB->ByteCount = cpu_to_le16(byte_count);
4048 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4049 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4051 cFYI(1, ("Send error in QFSDeviceInfo = %d", rc));
4052 } else { /* decode response */
4053 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4055 if (rc || (pSMBr->ByteCount < sizeof (FILE_SYSTEM_DEVICE_INFO)))
4056 rc = -EIO; /* bad smb */
4058 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4060 (FILE_SYSTEM_DEVICE_INFO *)
4061 (((char *) &pSMBr->hdr.Protocol) +
4063 memcpy(&tcon->fsDevInfo, response_data,
4064 sizeof (FILE_SYSTEM_DEVICE_INFO));
4067 cifs_buf_release(pSMB);
4070 goto QFSDeviceRetry;
4076 CIFSSMBQFSUnixInfo(const int xid, struct cifsTconInfo *tcon)
4078 /* level 0x200 SMB_QUERY_CIFS_UNIX_INFO */
4079 TRANSACTION2_QFSI_REQ *pSMB = NULL;
4080 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4081 FILE_SYSTEM_UNIX_INFO *response_data;
4083 int bytes_returned = 0;
4084 __u16 params, byte_count;
4086 cFYI(1, ("In QFSUnixInfo"));
4088 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4093 params = 2; /* level */
4094 pSMB->TotalDataCount = 0;
4095 pSMB->DataCount = 0;
4096 pSMB->DataOffset = 0;
4097 pSMB->MaxParameterCount = cpu_to_le16(2);
4098 pSMB->MaxDataCount = cpu_to_le16(100); /* BB find exact max SMB PDU from sess structure BB */
4099 pSMB->MaxSetupCount = 0;
4103 pSMB->Reserved2 = 0;
4104 byte_count = params + 1 /* pad */ ;
4105 pSMB->ParameterCount = cpu_to_le16(params);
4106 pSMB->TotalParameterCount = pSMB->ParameterCount;
4107 pSMB->ParameterOffset = cpu_to_le16(offsetof(struct
4108 smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4109 pSMB->SetupCount = 1;
4110 pSMB->Reserved3 = 0;
4111 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4112 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_CIFS_UNIX_INFO);
4113 pSMB->hdr.smb_buf_length += byte_count;
4114 pSMB->ByteCount = cpu_to_le16(byte_count);
4116 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4117 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4119 cERROR(1, ("Send error in QFSUnixInfo = %d", rc));
4120 } else { /* decode response */
4121 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4123 if (rc || (pSMBr->ByteCount < 13)) {
4124 rc = -EIO; /* bad smb */
4126 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4128 (FILE_SYSTEM_UNIX_INFO
4129 *) (((char *) &pSMBr->hdr.Protocol) +
4131 memcpy(&tcon->fsUnixInfo, response_data,
4132 sizeof (FILE_SYSTEM_UNIX_INFO));
4135 cifs_buf_release(pSMB);
4145 CIFSSMBSetFSUnixInfo(const int xid, struct cifsTconInfo *tcon, __u64 cap)
4147 /* level 0x200 SMB_SET_CIFS_UNIX_INFO */
4148 TRANSACTION2_SETFSI_REQ *pSMB = NULL;
4149 TRANSACTION2_SETFSI_RSP *pSMBr = NULL;
4151 int bytes_returned = 0;
4152 __u16 params, param_offset, offset, byte_count;
4154 cFYI(1, ("In SETFSUnixInfo"));
4156 /* BB switch to small buf init to save memory */
4157 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4162 params = 4; /* 2 bytes zero followed by info level. */
4163 pSMB->MaxSetupCount = 0;
4167 pSMB->Reserved2 = 0;
4168 param_offset = offsetof(struct smb_com_transaction2_setfsi_req, FileNum) - 4;
4169 offset = param_offset + params;
4171 pSMB->MaxParameterCount = cpu_to_le16(4);
4172 pSMB->MaxDataCount = cpu_to_le16(100); /* BB find exact max SMB PDU from sess structure BB */
4173 pSMB->SetupCount = 1;
4174 pSMB->Reserved3 = 0;
4175 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FS_INFORMATION);
4176 byte_count = 1 /* pad */ + params + 12;
4178 pSMB->DataCount = cpu_to_le16(12);
4179 pSMB->ParameterCount = cpu_to_le16(params);
4180 pSMB->TotalDataCount = pSMB->DataCount;
4181 pSMB->TotalParameterCount = pSMB->ParameterCount;
4182 pSMB->ParameterOffset = cpu_to_le16(param_offset);
4183 pSMB->DataOffset = cpu_to_le16(offset);
4187 pSMB->InformationLevel = cpu_to_le16(SMB_SET_CIFS_UNIX_INFO);
4190 pSMB->ClientUnixMajor = cpu_to_le16(CIFS_UNIX_MAJOR_VERSION);
4191 pSMB->ClientUnixMinor = cpu_to_le16(CIFS_UNIX_MINOR_VERSION);
4192 pSMB->ClientUnixCap = cpu_to_le64(cap);
4194 pSMB->hdr.smb_buf_length += byte_count;
4195 pSMB->ByteCount = cpu_to_le16(byte_count);
4197 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4198 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4200 cERROR(1, ("Send error in SETFSUnixInfo = %d", rc));
4201 } else { /* decode response */
4202 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4204 rc = -EIO; /* bad smb */
4207 cifs_buf_release(pSMB);
4210 goto SETFSUnixRetry;
4218 CIFSSMBQFSPosixInfo(const int xid, struct cifsTconInfo *tcon,
4219 struct kstatfs *FSData)
4221 /* level 0x201 SMB_QUERY_CIFS_POSIX_INFO */
4222 TRANSACTION2_QFSI_REQ *pSMB = NULL;
4223 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4224 FILE_SYSTEM_POSIX_INFO *response_data;
4226 int bytes_returned = 0;
4227 __u16 params, byte_count;
4229 cFYI(1, ("In QFSPosixInfo"));
4231 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4236 params = 2; /* level */
4237 pSMB->TotalDataCount = 0;
4238 pSMB->DataCount = 0;
4239 pSMB->DataOffset = 0;
4240 pSMB->MaxParameterCount = cpu_to_le16(2);
4241 pSMB->MaxDataCount = cpu_to_le16(100); /* BB find exact max SMB PDU from sess structure BB */
4242 pSMB->MaxSetupCount = 0;
4246 pSMB->Reserved2 = 0;
4247 byte_count = params + 1 /* pad */ ;
4248 pSMB->ParameterCount = cpu_to_le16(params);
4249 pSMB->TotalParameterCount = pSMB->ParameterCount;
4250 pSMB->ParameterOffset = cpu_to_le16(offsetof(struct
4251 smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4252 pSMB->SetupCount = 1;
4253 pSMB->Reserved3 = 0;
4254 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4255 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_POSIX_FS_INFO);
4256 pSMB->hdr.smb_buf_length += byte_count;
4257 pSMB->ByteCount = cpu_to_le16(byte_count);
4259 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4260 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4262 cFYI(1, ("Send error in QFSUnixInfo = %d", rc));
4263 } else { /* decode response */
4264 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4266 if (rc || (pSMBr->ByteCount < 13)) {
4267 rc = -EIO; /* bad smb */
4269 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4271 (FILE_SYSTEM_POSIX_INFO
4272 *) (((char *) &pSMBr->hdr.Protocol) +
4275 le32_to_cpu(response_data->BlockSize);
4277 le64_to_cpu(response_data->TotalBlocks);
4279 le64_to_cpu(response_data->BlocksAvail);
4280 if(response_data->UserBlocksAvail == cpu_to_le64(-1)) {
4281 FSData->f_bavail = FSData->f_bfree;
4284 le64_to_cpu(response_data->UserBlocksAvail);
4286 if(response_data->TotalFileNodes != cpu_to_le64(-1))
4288 le64_to_cpu(response_data->TotalFileNodes);
4289 if(response_data->FreeFileNodes != cpu_to_le64(-1))
4291 le64_to_cpu(response_data->FreeFileNodes);
4294 cifs_buf_release(pSMB);
4303 /* We can not use write of zero bytes trick to
4304 set file size due to need for large file support. Also note that
4305 this SetPathInfo is preferred to SetFileInfo based method in next
4306 routine which is only needed to work around a sharing violation bug
4307 in Samba which this routine can run into */
4310 CIFSSMBSetEOF(const int xid, struct cifsTconInfo *tcon, const char *fileName,
4311 __u64 size, int SetAllocation,
4312 const struct nls_table *nls_codepage, int remap)
4314 struct smb_com_transaction2_spi_req *pSMB = NULL;
4315 struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
4316 struct file_end_of_file_info *parm_data;
4319 int bytes_returned = 0;
4320 __u16 params, byte_count, data_count, param_offset, offset;
4322 cFYI(1, ("In SetEOF"));
4324 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4329 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4331 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
4332 PATH_MAX, nls_codepage, remap);
4333 name_len++; /* trailing null */
4335 } else { /* BB improve the check for buffer overruns BB */
4336 name_len = strnlen(fileName, PATH_MAX);
4337 name_len++; /* trailing null */
4338 strncpy(pSMB->FileName, fileName, name_len);
4340 params = 6 + name_len;
4341 data_count = sizeof (struct file_end_of_file_info);
4342 pSMB->MaxParameterCount = cpu_to_le16(2);
4343 pSMB->MaxDataCount = cpu_to_le16(4100);
4344 pSMB->MaxSetupCount = 0;
4348 pSMB->Reserved2 = 0;
4349 param_offset = offsetof(struct smb_com_transaction2_spi_req,
4350 InformationLevel) - 4;
4351 offset = param_offset + params;
4353 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
4354 pSMB->InformationLevel =
4355 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2);
4357 pSMB->InformationLevel =
4358 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO);
4359 } else /* Set File Size */ {
4360 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
4361 pSMB->InformationLevel =
4362 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO2);
4364 pSMB->InformationLevel =
4365 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO);
4369 (struct file_end_of_file_info *) (((char *) &pSMB->hdr.Protocol) +
4371 pSMB->ParameterOffset = cpu_to_le16(param_offset);
4372 pSMB->DataOffset = cpu_to_le16(offset);
4373 pSMB->SetupCount = 1;
4374 pSMB->Reserved3 = 0;
4375 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
4376 byte_count = 3 /* pad */ + params + data_count;
4377 pSMB->DataCount = cpu_to_le16(data_count);
4378 pSMB->TotalDataCount = pSMB->DataCount;
4379 pSMB->ParameterCount = cpu_to_le16(params);
4380 pSMB->TotalParameterCount = pSMB->ParameterCount;
4381 pSMB->Reserved4 = 0;
4382 pSMB->hdr.smb_buf_length += byte_count;
4383 parm_data->FileSize = cpu_to_le64(size);
4384 pSMB->ByteCount = cpu_to_le16(byte_count);
4385 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4386 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4388 cFYI(1, ("SetPathInfo (file size) returned %d", rc));
4391 cifs_buf_release(pSMB);
4400 CIFSSMBSetFileSize(const int xid, struct cifsTconInfo *tcon, __u64 size,
4401 __u16 fid, __u32 pid_of_opener, int SetAllocation)
4403 struct smb_com_transaction2_sfi_req *pSMB = NULL;
4404 struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
4406 struct file_end_of_file_info *parm_data;
4408 int bytes_returned = 0;
4409 __u16 params, param_offset, offset, byte_count, count;
4411 cFYI(1, ("SetFileSize (via SetFileInfo) %lld",
4413 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
4418 pSMBr = (struct smb_com_transaction2_sfi_rsp *)pSMB;
4420 pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
4421 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));
4424 pSMB->MaxSetupCount = 0;
4428 pSMB->Reserved2 = 0;
4429 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
4430 offset = param_offset + params;
4432 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
4434 count = sizeof(struct file_end_of_file_info);
4435 pSMB->MaxParameterCount = cpu_to_le16(2);
4436 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB PDU from sess */
4437 pSMB->SetupCount = 1;
4438 pSMB->Reserved3 = 0;
4439 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
4440 byte_count = 3 /* pad */ + params + count;
4441 pSMB->DataCount = cpu_to_le16(count);
4442 pSMB->ParameterCount = cpu_to_le16(params);
4443 pSMB->TotalDataCount = pSMB->DataCount;
4444 pSMB->TotalParameterCount = pSMB->ParameterCount;
4445 pSMB->ParameterOffset = cpu_to_le16(param_offset);
4447 (struct file_end_of_file_info *) (((char *) &pSMB->hdr.Protocol) +
4449 pSMB->DataOffset = cpu_to_le16(offset);
4450 parm_data->FileSize = cpu_to_le64(size);
4453 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
4454 pSMB->InformationLevel =
4455 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2);
4457 pSMB->InformationLevel =
4458 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO);
4459 } else /* Set File Size */ {
4460 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
4461 pSMB->InformationLevel =
4462 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO2);
4464 pSMB->InformationLevel =
4465 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO);
4467 pSMB->Reserved4 = 0;
4468 pSMB->hdr.smb_buf_length += byte_count;
4469 pSMB->ByteCount = cpu_to_le16(byte_count);
4470 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4471 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4474 ("Send error in SetFileInfo (SetFileSize) = %d",
4479 cifs_small_buf_release(pSMB);
4481 /* Note: On -EAGAIN error only caller can retry on handle based calls
4482 since file handle passed in no longer valid */
4487 /* Some legacy servers such as NT4 require that the file times be set on
4488 an open handle, rather than by pathname - this is awkward due to
4489 potential access conflicts on the open, but it is unavoidable for these
4490 old servers since the only other choice is to go from 100 nanosecond DCE
4491 time and resort to the original setpathinfo level which takes the ancient
4492 DOS time format with 2 second granularity */
4494 CIFSSMBSetFileTimes(const int xid, struct cifsTconInfo *tcon, const FILE_BASIC_INFO * data,
4497 struct smb_com_transaction2_sfi_req *pSMB = NULL;
4498 struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
4501 int bytes_returned = 0;
4502 __u16 params, param_offset, offset, byte_count, count;
4504 cFYI(1, ("Set Times (via SetFileInfo)"));
4505 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
4510 pSMBr = (struct smb_com_transaction2_sfi_rsp *)pSMB;
4512 /* At this point there is no need to override the current pid
4513 with the pid of the opener, but that could change if we someday
4514 use an existing handle (rather than opening one on the fly) */
4515 /* pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
4516 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));*/
4519 pSMB->MaxSetupCount = 0;
4523 pSMB->Reserved2 = 0;
4524 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
4525 offset = param_offset + params;
4527 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
4529 count = sizeof (FILE_BASIC_INFO);
4530 pSMB->MaxParameterCount = cpu_to_le16(2);
4531 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB PDU from sess */
4532 pSMB->SetupCount = 1;
4533 pSMB->Reserved3 = 0;
4534 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
4535 byte_count = 3 /* pad */ + params + count;
4536 pSMB->DataCount = cpu_to_le16(count);
4537 pSMB->ParameterCount = cpu_to_le16(params);
4538 pSMB->TotalDataCount = pSMB->DataCount;
4539 pSMB->TotalParameterCount = pSMB->ParameterCount;
4540 pSMB->ParameterOffset = cpu_to_le16(param_offset);
4541 pSMB->DataOffset = cpu_to_le16(offset);
4543 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
4544 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO2);
4546 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO);
4547 pSMB->Reserved4 = 0;
4548 pSMB->hdr.smb_buf_length += byte_count;
4549 pSMB->ByteCount = cpu_to_le16(byte_count);
4550 memcpy(data_offset,data,sizeof(FILE_BASIC_INFO));
4551 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4552 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4554 cFYI(1,("Send error in Set Time (SetFileInfo) = %d",rc));
4557 cifs_small_buf_release(pSMB);
4559 /* Note: On -EAGAIN error only caller can retry on handle based calls
4560 since file handle passed in no longer valid */
4567 CIFSSMBSetTimes(const int xid, struct cifsTconInfo *tcon, const char *fileName,
4568 const FILE_BASIC_INFO * data,
4569 const struct nls_table *nls_codepage, int remap)
4571 TRANSACTION2_SPI_REQ *pSMB = NULL;
4572 TRANSACTION2_SPI_RSP *pSMBr = NULL;
4575 int bytes_returned = 0;
4577 __u16 params, param_offset, offset, byte_count, count;
4579 cFYI(1, ("In SetTimes"));
4582 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4587 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4589 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
4590 PATH_MAX, nls_codepage, remap);
4591 name_len++; /* trailing null */
4593 } else { /* BB improve the check for buffer overruns BB */
4594 name_len = strnlen(fileName, PATH_MAX);
4595 name_len++; /* trailing null */
4596 strncpy(pSMB->FileName, fileName, name_len);
4599 params = 6 + name_len;
4600 count = sizeof (FILE_BASIC_INFO);
4601 pSMB->MaxParameterCount = cpu_to_le16(2);
4602 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
4603 pSMB->MaxSetupCount = 0;
4607 pSMB->Reserved2 = 0;
4608 param_offset = offsetof(struct smb_com_transaction2_spi_req,
4609 InformationLevel) - 4;
4610 offset = param_offset + params;
4611 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
4612 pSMB->ParameterOffset = cpu_to_le16(param_offset);
4613 pSMB->DataOffset = cpu_to_le16(offset);
4614 pSMB->SetupCount = 1;
4615 pSMB->Reserved3 = 0;
4616 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
4617 byte_count = 3 /* pad */ + params + count;
4619 pSMB->DataCount = cpu_to_le16(count);
4620 pSMB->ParameterCount = cpu_to_le16(params);
4621 pSMB->TotalDataCount = pSMB->DataCount;
4622 pSMB->TotalParameterCount = pSMB->ParameterCount;
4623 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
4624 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO2);
4626 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO);
4627 pSMB->Reserved4 = 0;
4628 pSMB->hdr.smb_buf_length += byte_count;
4629 memcpy(data_offset, data, sizeof (FILE_BASIC_INFO));
4630 pSMB->ByteCount = cpu_to_le16(byte_count);
4631 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4632 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4634 cFYI(1, ("SetPathInfo (times) returned %d", rc));
4637 cifs_buf_release(pSMB);
4645 /* Can not be used to set time stamps yet (due to old DOS time format) */
4646 /* Can be used to set attributes */
4647 #if 0 /* Possibly not needed - since it turns out that strangely NT4 has a bug
4648 handling it anyway and NT4 was what we thought it would be needed for
4649 Do not delete it until we prove whether needed for Win9x though */
4651 CIFSSMBSetAttrLegacy(int xid, struct cifsTconInfo *tcon, char *fileName,
4652 __u16 dos_attrs, const struct nls_table *nls_codepage)
4654 SETATTR_REQ *pSMB = NULL;
4655 SETATTR_RSP *pSMBr = NULL;
4660 cFYI(1, ("In SetAttrLegacy"));
4663 rc = smb_init(SMB_COM_SETATTR, 8, tcon, (void **) &pSMB,
4668 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4670 ConvertToUCS((__le16 *) pSMB->fileName, fileName,
4671 PATH_MAX, nls_codepage);
4672 name_len++; /* trailing null */
4674 } else { /* BB improve the check for buffer overruns BB */
4675 name_len = strnlen(fileName, PATH_MAX);
4676 name_len++; /* trailing null */
4677 strncpy(pSMB->fileName, fileName, name_len);
4679 pSMB->attr = cpu_to_le16(dos_attrs);
4680 pSMB->BufferFormat = 0x04;
4681 pSMB->hdr.smb_buf_length += name_len + 1;
4682 pSMB->ByteCount = cpu_to_le16(name_len + 1);
4683 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4684 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4686 cFYI(1, ("Error in LegacySetAttr = %d", rc));
4689 cifs_buf_release(pSMB);
4692 goto SetAttrLgcyRetry;
4696 #endif /* temporarily unneeded SetAttr legacy function */
4699 CIFSSMBUnixSetPerms(const int xid, struct cifsTconInfo *tcon,
4700 char *fileName, __u64 mode, __u64 uid, __u64 gid,
4701 dev_t device, const struct nls_table *nls_codepage,
4704 TRANSACTION2_SPI_REQ *pSMB = NULL;
4705 TRANSACTION2_SPI_RSP *pSMBr = NULL;
4708 int bytes_returned = 0;
4709 FILE_UNIX_BASIC_INFO *data_offset;
4710 __u16 params, param_offset, offset, count, byte_count;
4712 cFYI(1, ("In SetUID/GID/Mode"));
4714 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4719 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4721 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
4722 PATH_MAX, nls_codepage, remap);
4723 name_len++; /* trailing null */
4725 } else { /* BB improve the check for buffer overruns BB */
4726 name_len = strnlen(fileName, PATH_MAX);
4727 name_len++; /* trailing null */
4728 strncpy(pSMB->FileName, fileName, name_len);
4731 params = 6 + name_len;
4732 count = sizeof (FILE_UNIX_BASIC_INFO);
4733 pSMB->MaxParameterCount = cpu_to_le16(2);
4734 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
4735 pSMB->MaxSetupCount = 0;
4739 pSMB->Reserved2 = 0;
4740 param_offset = offsetof(struct smb_com_transaction2_spi_req,
4741 InformationLevel) - 4;
4742 offset = param_offset + params;
4744 (FILE_UNIX_BASIC_INFO *) ((char *) &pSMB->hdr.Protocol +
4746 memset(data_offset, 0, count);
4747 pSMB->DataOffset = cpu_to_le16(offset);
4748 pSMB->ParameterOffset = cpu_to_le16(param_offset);
4749 pSMB->SetupCount = 1;
4750 pSMB->Reserved3 = 0;
4751 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
4752 byte_count = 3 /* pad */ + params + count;
4753 pSMB->ParameterCount = cpu_to_le16(params);
4754 pSMB->DataCount = cpu_to_le16(count);
4755 pSMB->TotalParameterCount = pSMB->ParameterCount;
4756 pSMB->TotalDataCount = pSMB->DataCount;
4757 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_BASIC);
4758 pSMB->Reserved4 = 0;
4759 pSMB->hdr.smb_buf_length += byte_count;
4760 data_offset->Uid = cpu_to_le64(uid);
4761 data_offset->Gid = cpu_to_le64(gid);
4762 /* better to leave device as zero when it is */
4763 data_offset->DevMajor = cpu_to_le64(MAJOR(device));
4764 data_offset->DevMinor = cpu_to_le64(MINOR(device));
4765 data_offset->Permissions = cpu_to_le64(mode);
4768 data_offset->Type = cpu_to_le32(UNIX_FILE);
4769 else if(S_ISDIR(mode))
4770 data_offset->Type = cpu_to_le32(UNIX_DIR);
4771 else if(S_ISLNK(mode))
4772 data_offset->Type = cpu_to_le32(UNIX_SYMLINK);
4773 else if(S_ISCHR(mode))
4774 data_offset->Type = cpu_to_le32(UNIX_CHARDEV);
4775 else if(S_ISBLK(mode))
4776 data_offset->Type = cpu_to_le32(UNIX_BLOCKDEV);
4777 else if(S_ISFIFO(mode))
4778 data_offset->Type = cpu_to_le32(UNIX_FIFO);
4779 else if(S_ISSOCK(mode))
4780 data_offset->Type = cpu_to_le32(UNIX_SOCKET);
4783 pSMB->ByteCount = cpu_to_le16(byte_count);
4784 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4785 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4787 cFYI(1, ("SetPathInfo (perms) returned %d", rc));
4791 cifs_buf_release(pSMB);
4797 int CIFSSMBNotify(const int xid, struct cifsTconInfo *tcon,
4798 const int notify_subdirs, const __u16 netfid,
4799 __u32 filter, struct file * pfile, int multishot,
4800 const struct nls_table *nls_codepage)
4803 struct smb_com_transaction_change_notify_req * pSMB = NULL;
4804 struct smb_com_ntransaction_change_notify_rsp * pSMBr = NULL;
4805 struct dir_notify_req *dnotify_req;
4808 cFYI(1, ("In CIFSSMBNotify for file handle %d",(int)netfid));
4809 rc = smb_init(SMB_COM_NT_TRANSACT, 23, tcon, (void **) &pSMB,
4814 pSMB->TotalParameterCount = 0 ;
4815 pSMB->TotalDataCount = 0;
4816 pSMB->MaxParameterCount = cpu_to_le32(2);
4817 /* BB find exact data count max from sess structure BB */
4818 pSMB->MaxDataCount = 0; /* same in little endian or be */
4819 /* BB VERIFY verify which is correct for above BB */
4820 pSMB->MaxDataCount = cpu_to_le32((tcon->ses->server->maxBuf -
4821 MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
4823 pSMB->MaxSetupCount = 4;
4825 pSMB->ParameterOffset = 0;
4826 pSMB->DataCount = 0;
4827 pSMB->DataOffset = 0;
4828 pSMB->SetupCount = 4; /* single byte does not need le conversion */
4829 pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_NOTIFY_CHANGE);
4830 pSMB->ParameterCount = pSMB->TotalParameterCount;
4832 pSMB->WatchTree = 1; /* one byte - no le conversion needed */
4833 pSMB->Reserved2 = 0;
4834 pSMB->CompletionFilter = cpu_to_le32(filter);
4835 pSMB->Fid = netfid; /* file handle always le */
4836 pSMB->ByteCount = 0;
4838 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4839 (struct smb_hdr *) pSMBr, &bytes_returned, -1);
4841 cFYI(1, ("Error in Notify = %d", rc));
4843 /* Add file to outstanding requests */
4844 /* BB change to kmem cache alloc */
4845 dnotify_req = (struct dir_notify_req *) kmalloc(
4846 sizeof(struct dir_notify_req),
4849 dnotify_req->Pid = pSMB->hdr.Pid;
4850 dnotify_req->PidHigh = pSMB->hdr.PidHigh;
4851 dnotify_req->Mid = pSMB->hdr.Mid;
4852 dnotify_req->Tid = pSMB->hdr.Tid;
4853 dnotify_req->Uid = pSMB->hdr.Uid;
4854 dnotify_req->netfid = netfid;
4855 dnotify_req->pfile = pfile;
4856 dnotify_req->filter = filter;
4857 dnotify_req->multishot = multishot;
4858 spin_lock(&GlobalMid_Lock);
4859 list_add_tail(&dnotify_req->lhead,
4860 &GlobalDnotifyReqList);
4861 spin_unlock(&GlobalMid_Lock);
4865 cifs_buf_release(pSMB);
4868 #ifdef CONFIG_CIFS_XATTR
4870 CIFSSMBQAllEAs(const int xid, struct cifsTconInfo *tcon,
4871 const unsigned char *searchName,
4872 char * EAData, size_t buf_size,
4873 const struct nls_table *nls_codepage, int remap)
4875 /* BB assumes one setup word */
4876 TRANSACTION2_QPI_REQ *pSMB = NULL;
4877 TRANSACTION2_QPI_RSP *pSMBr = NULL;
4881 struct fea * temp_fea;
4883 __u16 params, byte_count;
4885 cFYI(1, ("In Query All EAs path %s", searchName));
4887 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4892 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4894 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
4895 PATH_MAX, nls_codepage, remap);
4896 name_len++; /* trailing null */
4898 } else { /* BB improve the check for buffer overruns BB */
4899 name_len = strnlen(searchName, PATH_MAX);
4900 name_len++; /* trailing null */
4901 strncpy(pSMB->FileName, searchName, name_len);
4904 params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */ ;
4905 pSMB->TotalDataCount = 0;
4906 pSMB->MaxParameterCount = cpu_to_le16(2);
4907 pSMB->MaxDataCount = cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
4908 pSMB->MaxSetupCount = 0;
4912 pSMB->Reserved2 = 0;
4913 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4914 struct smb_com_transaction2_qpi_req ,InformationLevel) - 4);
4915 pSMB->DataCount = 0;
4916 pSMB->DataOffset = 0;
4917 pSMB->SetupCount = 1;
4918 pSMB->Reserved3 = 0;
4919 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
4920 byte_count = params + 1 /* pad */ ;
4921 pSMB->TotalParameterCount = cpu_to_le16(params);
4922 pSMB->ParameterCount = pSMB->TotalParameterCount;
4923 pSMB->InformationLevel = cpu_to_le16(SMB_INFO_QUERY_ALL_EAS);
4924 pSMB->Reserved4 = 0;
4925 pSMB->hdr.smb_buf_length += byte_count;
4926 pSMB->ByteCount = cpu_to_le16(byte_count);
4928 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4929 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4931 cFYI(1, ("Send error in QueryAllEAs = %d", rc));
4932 } else { /* decode response */
4933 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4935 /* BB also check enough total bytes returned */
4936 /* BB we need to improve the validity checking
4937 of these trans2 responses */
4938 if (rc || (pSMBr->ByteCount < 4))
4939 rc = -EIO; /* bad smb */
4940 /* else if (pFindData){
4941 memcpy((char *) pFindData,
4942 (char *) &pSMBr->hdr.Protocol +
4945 /* check that length of list is not more than bcc */
4946 /* check that each entry does not go beyond length
4948 /* check that each element of each entry does not
4949 go beyond end of list */
4950 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4951 struct fealist * ea_response_data;
4953 /* validate_trans2_offsets() */
4954 /* BB to check if(start of smb + data_offset > &bcc+ bcc)*/
4955 ea_response_data = (struct fealist *)
4956 (((char *) &pSMBr->hdr.Protocol) +
4958 name_len = le32_to_cpu(ea_response_data->list_len);
4959 cFYI(1,("ea length %d", name_len));
4961 /* returned EA size zeroed at top of function */
4962 cFYI(1,("empty EA list returned from server"));
4964 /* account for ea list len */
4966 temp_fea = ea_response_data->list;
4967 temp_ptr = (char *)temp_fea;
4968 while(name_len > 0) {
4972 rc += temp_fea->name_len;
4973 /* account for prefix user. and trailing null */
4975 if(rc<(int)buf_size) {
4976 memcpy(EAData,"user.",5);
4978 memcpy(EAData,temp_ptr,temp_fea->name_len);
4979 EAData+=temp_fea->name_len;
4980 /* null terminate name */
4982 EAData = EAData + 1;
4983 } else if(buf_size == 0) {
4984 /* skip copy - calc size only */
4986 /* stop before overrun buffer */
4990 name_len -= temp_fea->name_len;
4991 temp_ptr += temp_fea->name_len;
4992 /* account for trailing null */
4995 value_len = le16_to_cpu(temp_fea->value_len);
4996 name_len -= value_len;
4997 temp_ptr += value_len;
4998 /* BB check that temp_ptr is still within smb BB*/
4999 /* no trailing null to account for in value len */
5000 /* go on to next EA */
5001 temp_fea = (struct fea *)temp_ptr;
5007 cifs_buf_release(pSMB);
5014 ssize_t CIFSSMBQueryEA(const int xid,struct cifsTconInfo * tcon,
5015 const unsigned char * searchName,const unsigned char * ea_name,
5016 unsigned char * ea_value, size_t buf_size,
5017 const struct nls_table *nls_codepage, int remap)
5019 TRANSACTION2_QPI_REQ *pSMB = NULL;
5020 TRANSACTION2_QPI_RSP *pSMBr = NULL;
5024 struct fea * temp_fea;
5026 __u16 params, byte_count;
5028 cFYI(1, ("In Query EA path %s", searchName));
5030 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5035 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5037 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
5038 PATH_MAX, nls_codepage, remap);
5039 name_len++; /* trailing null */
5041 } else { /* BB improve the check for buffer overruns BB */
5042 name_len = strnlen(searchName, PATH_MAX);
5043 name_len++; /* trailing null */
5044 strncpy(pSMB->FileName, searchName, name_len);
5047 params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */ ;
5048 pSMB->TotalDataCount = 0;
5049 pSMB->MaxParameterCount = cpu_to_le16(2);
5050 pSMB->MaxDataCount = cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
5051 pSMB->MaxSetupCount = 0;
5055 pSMB->Reserved2 = 0;
5056 pSMB->ParameterOffset = cpu_to_le16(offsetof(
5057 struct smb_com_transaction2_qpi_req ,InformationLevel) - 4);
5058 pSMB->DataCount = 0;
5059 pSMB->DataOffset = 0;
5060 pSMB->SetupCount = 1;
5061 pSMB->Reserved3 = 0;
5062 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
5063 byte_count = params + 1 /* pad */ ;
5064 pSMB->TotalParameterCount = cpu_to_le16(params);
5065 pSMB->ParameterCount = pSMB->TotalParameterCount;
5066 pSMB->InformationLevel = cpu_to_le16(SMB_INFO_QUERY_ALL_EAS);
5067 pSMB->Reserved4 = 0;
5068 pSMB->hdr.smb_buf_length += byte_count;
5069 pSMB->ByteCount = cpu_to_le16(byte_count);
5071 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5072 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5074 cFYI(1, ("Send error in Query EA = %d", rc));
5075 } else { /* decode response */
5076 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
5078 /* BB also check enough total bytes returned */
5079 /* BB we need to improve the validity checking
5080 of these trans2 responses */
5081 if (rc || (pSMBr->ByteCount < 4))
5082 rc = -EIO; /* bad smb */
5083 /* else if (pFindData){
5084 memcpy((char *) pFindData,
5085 (char *) &pSMBr->hdr.Protocol +
5088 /* check that length of list is not more than bcc */
5089 /* check that each entry does not go beyond length
5091 /* check that each element of each entry does not
5092 go beyond end of list */
5093 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
5094 struct fealist * ea_response_data;
5096 /* validate_trans2_offsets() */
5097 /* BB to check if(start of smb + data_offset > &bcc+ bcc)*/
5098 ea_response_data = (struct fealist *)
5099 (((char *) &pSMBr->hdr.Protocol) +
5101 name_len = le32_to_cpu(ea_response_data->list_len);
5102 cFYI(1,("ea length %d", name_len));
5104 /* returned EA size zeroed at top of function */
5105 cFYI(1,("empty EA list returned from server"));
5107 /* account for ea list len */
5109 temp_fea = ea_response_data->list;
5110 temp_ptr = (char *)temp_fea;
5111 /* loop through checking if we have a matching
5112 name and then return the associated value */
5113 while(name_len > 0) {
5117 value_len = le16_to_cpu(temp_fea->value_len);
5118 /* BB validate that value_len falls within SMB,
5119 even though maximum for name_len is 255 */
5120 if(memcmp(temp_fea->name,ea_name,
5121 temp_fea->name_len) == 0) {
5124 /* account for prefix user. and trailing null */
5125 if(rc<=(int)buf_size) {
5127 temp_fea->name+temp_fea->name_len+1,
5129 /* ea values, unlike ea names,
5130 are not null terminated */
5131 } else if(buf_size == 0) {
5132 /* skip copy - calc size only */
5134 /* stop before overrun buffer */
5139 name_len -= temp_fea->name_len;
5140 temp_ptr += temp_fea->name_len;
5141 /* account for trailing null */
5144 name_len -= value_len;
5145 temp_ptr += value_len;
5146 /* no trailing null to account for in value len */
5147 /* go on to next EA */
5148 temp_fea = (struct fea *)temp_ptr;
5154 cifs_buf_release(pSMB);
5162 CIFSSMBSetEA(const int xid, struct cifsTconInfo *tcon, const char *fileName,
5163 const char * ea_name, const void * ea_value,
5164 const __u16 ea_value_len, const struct nls_table *nls_codepage,
5167 struct smb_com_transaction2_spi_req *pSMB = NULL;
5168 struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
5169 struct fealist *parm_data;
5172 int bytes_returned = 0;
5173 __u16 params, param_offset, byte_count, offset, count;
5175 cFYI(1, ("In SetEA"));
5177 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5182 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5184 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
5185 PATH_MAX, nls_codepage, remap);
5186 name_len++; /* trailing null */
5188 } else { /* BB improve the check for buffer overruns BB */
5189 name_len = strnlen(fileName, PATH_MAX);
5190 name_len++; /* trailing null */
5191 strncpy(pSMB->FileName, fileName, name_len);
5194 params = 6 + name_len;
5196 /* done calculating parms using name_len of file name,
5197 now use name_len to calculate length of ea name
5198 we are going to create in the inode xattrs */
5202 name_len = strnlen(ea_name,255);
5204 count = sizeof(*parm_data) + ea_value_len + name_len + 1;
5205 pSMB->MaxParameterCount = cpu_to_le16(2);
5206 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB size from sess */
5207 pSMB->MaxSetupCount = 0;
5211 pSMB->Reserved2 = 0;
5212 param_offset = offsetof(struct smb_com_transaction2_spi_req,
5213 InformationLevel) - 4;
5214 offset = param_offset + params;
5215 pSMB->InformationLevel =
5216 cpu_to_le16(SMB_SET_FILE_EA);
5219 (struct fealist *) (((char *) &pSMB->hdr.Protocol) +
5221 pSMB->ParameterOffset = cpu_to_le16(param_offset);
5222 pSMB->DataOffset = cpu_to_le16(offset);
5223 pSMB->SetupCount = 1;
5224 pSMB->Reserved3 = 0;
5225 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
5226 byte_count = 3 /* pad */ + params + count;
5227 pSMB->DataCount = cpu_to_le16(count);
5228 parm_data->list_len = cpu_to_le32(count);
5229 parm_data->list[0].EA_flags = 0;
5230 /* we checked above that name len is less than 255 */
5231 parm_data->list[0].name_len = (__u8)name_len;
5232 /* EA names are always ASCII */
5234 strncpy(parm_data->list[0].name,ea_name,name_len);
5235 parm_data->list[0].name[name_len] = 0;
5236 parm_data->list[0].value_len = cpu_to_le16(ea_value_len);
5237 /* caller ensures that ea_value_len is less than 64K but
5238 we need to ensure that it fits within the smb */
5240 /*BB add length check that it would fit in negotiated SMB buffer size BB */
5241 /* if(ea_value_len > buffer_size - 512 (enough for header)) */
5243 memcpy(parm_data->list[0].name+name_len+1,ea_value,ea_value_len);
5245 pSMB->TotalDataCount = pSMB->DataCount;
5246 pSMB->ParameterCount = cpu_to_le16(params);
5247 pSMB->TotalParameterCount = pSMB->ParameterCount;
5248 pSMB->Reserved4 = 0;
5249 pSMB->hdr.smb_buf_length += byte_count;
5250 pSMB->ByteCount = cpu_to_le16(byte_count);
5251 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5252 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5254 cFYI(1, ("SetPathInfo (EA) returned %d", rc));
5257 cifs_buf_release(pSMB);