fanotify: merge duplicate events on parent and child
[linux/fpc-iii.git] / fs / cifs / cifssmb.c
blob6f6fb3606a5d6094b498c99851d21d81b135b952
1 /*
2 * fs/cifs/cifssmb.c
4 * Copyright (C) International Business Machines Corp., 2002,2010
5 * Author(s): Steve French (sfrench@us.ibm.com)
7 * Contains the routines for constructing the SMB PDUs themselves
9 * This library is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU Lesser General Public License as published
11 * by the Free Software Foundation; either version 2.1 of the License, or
12 * (at your option) any later version.
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
17 * the GNU Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public License
20 * along with this library; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 /* SMB/CIFS PDU handling routines here - except for leftovers in connect.c */
25 /* These are mostly routines that operate on a pathname, or on a tree id */
26 /* (mounted volume), but there are eight handle based routines which must be */
27 /* treated slightly differently for reconnection purposes since we never */
28 /* want to reuse a stale file handle and only the caller knows the file info */
30 #include <linux/fs.h>
31 #include <linux/kernel.h>
32 #include <linux/vfs.h>
33 #include <linux/slab.h>
34 #include <linux/posix_acl_xattr.h>
35 #include <linux/pagemap.h>
36 #include <linux/swap.h>
37 #include <linux/task_io_accounting_ops.h>
38 #include <linux/uaccess.h>
39 #include "cifspdu.h"
40 #include "cifsglob.h"
41 #include "cifsacl.h"
42 #include "cifsproto.h"
43 #include "cifs_unicode.h"
44 #include "cifs_debug.h"
45 #include "smb2proto.h"
46 #include "fscache.h"
47 #include "smbdirect.h"
48 #ifdef CONFIG_CIFS_DFS_UPCALL
49 #include "dfs_cache.h"
50 #endif
52 #ifdef CONFIG_CIFS_POSIX
53 static struct {
54 int index;
55 char *name;
56 } protocols[] = {
57 #ifdef CONFIG_CIFS_WEAK_PW_HASH
58 {LANMAN_PROT, "\2LM1.2X002"},
59 {LANMAN2_PROT, "\2LANMAN2.1"},
60 #endif /* weak password hashing for legacy clients */
61 {CIFS_PROT, "\2NT LM 0.12"},
62 {POSIX_PROT, "\2POSIX 2"},
63 {BAD_PROT, "\2"}
65 #else
66 static struct {
67 int index;
68 char *name;
69 } protocols[] = {
70 #ifdef CONFIG_CIFS_WEAK_PW_HASH
71 {LANMAN_PROT, "\2LM1.2X002"},
72 {LANMAN2_PROT, "\2LANMAN2.1"},
73 #endif /* weak password hashing for legacy clients */
74 {CIFS_PROT, "\2NT LM 0.12"},
75 {BAD_PROT, "\2"}
77 #endif
79 /* define the number of elements in the cifs dialect array */
80 #ifdef CONFIG_CIFS_POSIX
81 #ifdef CONFIG_CIFS_WEAK_PW_HASH
82 #define CIFS_NUM_PROT 4
83 #else
84 #define CIFS_NUM_PROT 2
85 #endif /* CIFS_WEAK_PW_HASH */
86 #else /* not posix */
87 #ifdef CONFIG_CIFS_WEAK_PW_HASH
88 #define CIFS_NUM_PROT 3
89 #else
90 #define CIFS_NUM_PROT 1
91 #endif /* CONFIG_CIFS_WEAK_PW_HASH */
92 #endif /* CIFS_POSIX */
95 * Mark as invalid, all open files on tree connections since they
96 * were closed when session to server was lost.
98 void
99 cifs_mark_open_files_invalid(struct cifs_tcon *tcon)
101 struct cifsFileInfo *open_file = NULL;
102 struct list_head *tmp;
103 struct list_head *tmp1;
105 /* list all files open on tree connection and mark them invalid */
106 spin_lock(&tcon->open_file_lock);
107 list_for_each_safe(tmp, tmp1, &tcon->openFileList) {
108 open_file = list_entry(tmp, struct cifsFileInfo, tlist);
109 open_file->invalidHandle = true;
110 open_file->oplock_break_cancelled = true;
112 spin_unlock(&tcon->open_file_lock);
114 mutex_lock(&tcon->crfid.fid_mutex);
115 tcon->crfid.is_valid = false;
116 /* cached handle is not valid, so SMB2_CLOSE won't be sent below */
117 close_shroot_lease_locked(&tcon->crfid);
118 memset(tcon->crfid.fid, 0, sizeof(struct cifs_fid));
119 mutex_unlock(&tcon->crfid.fid_mutex);
122 * BB Add call to invalidate_inodes(sb) for all superblocks mounted
123 * to this tcon.
127 #ifdef CONFIG_CIFS_DFS_UPCALL
128 static int __cifs_reconnect_tcon(const struct nls_table *nlsc,
129 struct cifs_tcon *tcon)
131 int rc;
132 struct dfs_cache_tgt_list tl;
133 struct dfs_cache_tgt_iterator *it = NULL;
134 char *tree;
135 const char *tcp_host;
136 size_t tcp_host_len;
137 const char *dfs_host;
138 size_t dfs_host_len;
140 tree = kzalloc(MAX_TREE_SIZE, GFP_KERNEL);
141 if (!tree)
142 return -ENOMEM;
144 if (tcon->ipc) {
145 scnprintf(tree, MAX_TREE_SIZE, "\\\\%s\\IPC$",
146 tcon->ses->server->hostname);
147 rc = CIFSTCon(0, tcon->ses, tree, tcon, nlsc);
148 goto out;
151 if (!tcon->dfs_path) {
152 rc = CIFSTCon(0, tcon->ses, tcon->treeName, tcon, nlsc);
153 goto out;
156 rc = dfs_cache_noreq_find(tcon->dfs_path + 1, NULL, &tl);
157 if (rc)
158 goto out;
160 extract_unc_hostname(tcon->ses->server->hostname, &tcp_host,
161 &tcp_host_len);
163 for (it = dfs_cache_get_tgt_iterator(&tl); it;
164 it = dfs_cache_get_next_tgt(&tl, it)) {
165 const char *tgt = dfs_cache_get_tgt_name(it);
167 extract_unc_hostname(tgt, &dfs_host, &dfs_host_len);
169 if (dfs_host_len != tcp_host_len
170 || strncasecmp(dfs_host, tcp_host, dfs_host_len) != 0) {
171 cifs_dbg(FYI, "%s: skipping %.*s, doesn't match %.*s",
172 __func__,
173 (int)dfs_host_len, dfs_host,
174 (int)tcp_host_len, tcp_host);
175 continue;
178 scnprintf(tree, MAX_TREE_SIZE, "\\%s", tgt);
180 rc = CIFSTCon(0, tcon->ses, tree, tcon, nlsc);
181 if (!rc)
182 break;
183 if (rc == -EREMOTE)
184 break;
187 if (!rc) {
188 if (it)
189 rc = dfs_cache_noreq_update_tgthint(tcon->dfs_path + 1,
190 it);
191 else
192 rc = -ENOENT;
194 dfs_cache_free_tgts(&tl);
195 out:
196 kfree(tree);
197 return rc;
199 #else
200 static inline int __cifs_reconnect_tcon(const struct nls_table *nlsc,
201 struct cifs_tcon *tcon)
203 return CIFSTCon(0, tcon->ses, tcon->treeName, tcon, nlsc);
205 #endif
207 /* reconnect the socket, tcon, and smb session if needed */
208 static int
209 cifs_reconnect_tcon(struct cifs_tcon *tcon, int smb_command)
211 int rc;
212 struct cifs_ses *ses;
213 struct TCP_Server_Info *server;
214 struct nls_table *nls_codepage;
215 int retries;
218 * SMBs NegProt, SessSetup, uLogoff do not have tcon yet so check for
219 * tcp and smb session status done differently for those three - in the
220 * calling routine
222 if (!tcon)
223 return 0;
225 ses = tcon->ses;
226 server = ses->server;
229 * only tree disconnect, open, and write, (and ulogoff which does not
230 * have tcon) are allowed as we start force umount
232 if (tcon->tidStatus == CifsExiting) {
233 if (smb_command != SMB_COM_WRITE_ANDX &&
234 smb_command != SMB_COM_OPEN_ANDX &&
235 smb_command != SMB_COM_TREE_DISCONNECT) {
236 cifs_dbg(FYI, "can not send cmd %d while umounting\n",
237 smb_command);
238 return -ENODEV;
242 retries = server->nr_targets;
245 * Give demultiplex thread up to 10 seconds to each target available for
246 * reconnect -- should be greater than cifs socket timeout which is 7
247 * seconds.
249 while (server->tcpStatus == CifsNeedReconnect) {
250 rc = wait_event_interruptible_timeout(server->response_q,
251 (server->tcpStatus != CifsNeedReconnect),
252 10 * HZ);
253 if (rc < 0) {
254 cifs_dbg(FYI, "%s: aborting reconnect due to a received"
255 " signal by the process\n", __func__);
256 return -ERESTARTSYS;
259 /* are we still trying to reconnect? */
260 if (server->tcpStatus != CifsNeedReconnect)
261 break;
263 if (retries && --retries)
264 continue;
267 * on "soft" mounts we wait once. Hard mounts keep
268 * retrying until process is killed or server comes
269 * back on-line
271 if (!tcon->retry) {
272 cifs_dbg(FYI, "gave up waiting on reconnect in smb_init\n");
273 return -EHOSTDOWN;
275 retries = server->nr_targets;
278 if (!ses->need_reconnect && !tcon->need_reconnect)
279 return 0;
281 nls_codepage = load_nls_default();
284 * need to prevent multiple threads trying to simultaneously
285 * reconnect the same SMB session
287 mutex_lock(&ses->session_mutex);
290 * Recheck after acquire mutex. If another thread is negotiating
291 * and the server never sends an answer the socket will be closed
292 * and tcpStatus set to reconnect.
294 if (server->tcpStatus == CifsNeedReconnect) {
295 rc = -EHOSTDOWN;
296 mutex_unlock(&ses->session_mutex);
297 goto out;
300 rc = cifs_negotiate_protocol(0, ses);
301 if (rc == 0 && ses->need_reconnect)
302 rc = cifs_setup_session(0, ses, nls_codepage);
304 /* do we need to reconnect tcon? */
305 if (rc || !tcon->need_reconnect) {
306 mutex_unlock(&ses->session_mutex);
307 goto out;
310 cifs_mark_open_files_invalid(tcon);
311 rc = __cifs_reconnect_tcon(nls_codepage, tcon);
312 mutex_unlock(&ses->session_mutex);
313 cifs_dbg(FYI, "reconnect tcon rc = %d\n", rc);
315 if (rc) {
316 printk_once(KERN_WARNING "reconnect tcon failed rc = %d\n", rc);
317 goto out;
320 atomic_inc(&tconInfoReconnectCount);
322 /* tell server Unix caps we support */
323 if (ses->capabilities & CAP_UNIX)
324 reset_cifs_unix_caps(0, tcon, NULL, NULL);
327 * Removed call to reopen open files here. It is safer (and faster) to
328 * reopen files one at a time as needed in read and write.
330 * FIXME: what about file locks? don't we need to reclaim them ASAP?
333 out:
335 * Check if handle based operation so we know whether we can continue
336 * or not without returning to caller to reset file handle
338 switch (smb_command) {
339 case SMB_COM_READ_ANDX:
340 case SMB_COM_WRITE_ANDX:
341 case SMB_COM_CLOSE:
342 case SMB_COM_FIND_CLOSE2:
343 case SMB_COM_LOCKING_ANDX:
344 rc = -EAGAIN;
347 unload_nls(nls_codepage);
348 return rc;
351 /* Allocate and return pointer to an SMB request buffer, and set basic
352 SMB information in the SMB header. If the return code is zero, this
353 function must have filled in request_buf pointer */
354 static int
355 small_smb_init(int smb_command, int wct, struct cifs_tcon *tcon,
356 void **request_buf)
358 int rc;
360 rc = cifs_reconnect_tcon(tcon, smb_command);
361 if (rc)
362 return rc;
364 *request_buf = cifs_small_buf_get();
365 if (*request_buf == NULL) {
366 /* BB should we add a retry in here if not a writepage? */
367 return -ENOMEM;
370 header_assemble((struct smb_hdr *) *request_buf, smb_command,
371 tcon, wct);
373 if (tcon != NULL)
374 cifs_stats_inc(&tcon->num_smbs_sent);
376 return 0;
380 small_smb_init_no_tc(const int smb_command, const int wct,
381 struct cifs_ses *ses, void **request_buf)
383 int rc;
384 struct smb_hdr *buffer;
386 rc = small_smb_init(smb_command, wct, NULL, request_buf);
387 if (rc)
388 return rc;
390 buffer = (struct smb_hdr *)*request_buf;
391 buffer->Mid = get_next_mid(ses->server);
392 if (ses->capabilities & CAP_UNICODE)
393 buffer->Flags2 |= SMBFLG2_UNICODE;
394 if (ses->capabilities & CAP_STATUS32)
395 buffer->Flags2 |= SMBFLG2_ERR_STATUS;
397 /* uid, tid can stay at zero as set in header assemble */
399 /* BB add support for turning on the signing when
400 this function is used after 1st of session setup requests */
402 return rc;
405 /* If the return code is zero, this function must fill in request_buf pointer */
406 static int
407 __smb_init(int smb_command, int wct, struct cifs_tcon *tcon,
408 void **request_buf, void **response_buf)
410 *request_buf = cifs_buf_get();
411 if (*request_buf == NULL) {
412 /* BB should we add a retry in here if not a writepage? */
413 return -ENOMEM;
415 /* Although the original thought was we needed the response buf for */
416 /* potential retries of smb operations it turns out we can determine */
417 /* from the mid flags when the request buffer can be resent without */
418 /* having to use a second distinct buffer for the response */
419 if (response_buf)
420 *response_buf = *request_buf;
422 header_assemble((struct smb_hdr *) *request_buf, smb_command, tcon,
423 wct);
425 if (tcon != NULL)
426 cifs_stats_inc(&tcon->num_smbs_sent);
428 return 0;
431 /* If the return code is zero, this function must fill in request_buf pointer */
432 static int
433 smb_init(int smb_command, int wct, struct cifs_tcon *tcon,
434 void **request_buf, void **response_buf)
436 int rc;
438 rc = cifs_reconnect_tcon(tcon, smb_command);
439 if (rc)
440 return rc;
442 return __smb_init(smb_command, wct, tcon, request_buf, response_buf);
445 static int
446 smb_init_no_reconnect(int smb_command, int wct, struct cifs_tcon *tcon,
447 void **request_buf, void **response_buf)
449 if (tcon->ses->need_reconnect || tcon->need_reconnect)
450 return -EHOSTDOWN;
452 return __smb_init(smb_command, wct, tcon, request_buf, response_buf);
455 static int validate_t2(struct smb_t2_rsp *pSMB)
457 unsigned int total_size;
459 /* check for plausible wct */
460 if (pSMB->hdr.WordCount < 10)
461 goto vt2_err;
463 /* check for parm and data offset going beyond end of smb */
464 if (get_unaligned_le16(&pSMB->t2_rsp.ParameterOffset) > 1024 ||
465 get_unaligned_le16(&pSMB->t2_rsp.DataOffset) > 1024)
466 goto vt2_err;
468 total_size = get_unaligned_le16(&pSMB->t2_rsp.ParameterCount);
469 if (total_size >= 512)
470 goto vt2_err;
472 /* check that bcc is at least as big as parms + data, and that it is
473 * less than negotiated smb buffer
475 total_size += get_unaligned_le16(&pSMB->t2_rsp.DataCount);
476 if (total_size > get_bcc(&pSMB->hdr) ||
477 total_size >= CIFSMaxBufSize + MAX_CIFS_HDR_SIZE)
478 goto vt2_err;
480 return 0;
481 vt2_err:
482 cifs_dump_mem("Invalid transact2 SMB: ", (char *)pSMB,
483 sizeof(struct smb_t2_rsp) + 16);
484 return -EINVAL;
487 static int
488 decode_ext_sec_blob(struct cifs_ses *ses, NEGOTIATE_RSP *pSMBr)
490 int rc = 0;
491 u16 count;
492 char *guid = pSMBr->u.extended_response.GUID;
493 struct TCP_Server_Info *server = ses->server;
495 count = get_bcc(&pSMBr->hdr);
496 if (count < SMB1_CLIENT_GUID_SIZE)
497 return -EIO;
499 spin_lock(&cifs_tcp_ses_lock);
500 if (server->srv_count > 1) {
501 spin_unlock(&cifs_tcp_ses_lock);
502 if (memcmp(server->server_GUID, guid, SMB1_CLIENT_GUID_SIZE) != 0) {
503 cifs_dbg(FYI, "server UID changed\n");
504 memcpy(server->server_GUID, guid, SMB1_CLIENT_GUID_SIZE);
506 } else {
507 spin_unlock(&cifs_tcp_ses_lock);
508 memcpy(server->server_GUID, guid, SMB1_CLIENT_GUID_SIZE);
511 if (count == SMB1_CLIENT_GUID_SIZE) {
512 server->sec_ntlmssp = true;
513 } else {
514 count -= SMB1_CLIENT_GUID_SIZE;
515 rc = decode_negTokenInit(
516 pSMBr->u.extended_response.SecurityBlob, count, server);
517 if (rc != 1)
518 return -EINVAL;
521 return 0;
525 cifs_enable_signing(struct TCP_Server_Info *server, bool mnt_sign_required)
527 bool srv_sign_required = server->sec_mode & server->vals->signing_required;
528 bool srv_sign_enabled = server->sec_mode & server->vals->signing_enabled;
529 bool mnt_sign_enabled = global_secflags & CIFSSEC_MAY_SIGN;
532 * Is signing required by mnt options? If not then check
533 * global_secflags to see if it is there.
535 if (!mnt_sign_required)
536 mnt_sign_required = ((global_secflags & CIFSSEC_MUST_SIGN) ==
537 CIFSSEC_MUST_SIGN);
540 * If signing is required then it's automatically enabled too,
541 * otherwise, check to see if the secflags allow it.
543 mnt_sign_enabled = mnt_sign_required ? mnt_sign_required :
544 (global_secflags & CIFSSEC_MAY_SIGN);
546 /* If server requires signing, does client allow it? */
547 if (srv_sign_required) {
548 if (!mnt_sign_enabled) {
549 cifs_dbg(VFS, "Server requires signing, but it's disabled in SecurityFlags!");
550 return -ENOTSUPP;
552 server->sign = true;
555 /* If client requires signing, does server allow it? */
556 if (mnt_sign_required) {
557 if (!srv_sign_enabled) {
558 cifs_dbg(VFS, "Server does not support signing!");
559 return -ENOTSUPP;
561 server->sign = true;
564 if (cifs_rdma_enabled(server) && server->sign)
565 cifs_dbg(VFS, "Signing is enabled, and RDMA read/write will be disabled");
567 return 0;
570 #ifdef CONFIG_CIFS_WEAK_PW_HASH
571 static int
572 decode_lanman_negprot_rsp(struct TCP_Server_Info *server, NEGOTIATE_RSP *pSMBr)
574 __s16 tmp;
575 struct lanman_neg_rsp *rsp = (struct lanman_neg_rsp *)pSMBr;
577 if (server->dialect != LANMAN_PROT && server->dialect != LANMAN2_PROT)
578 return -EOPNOTSUPP;
580 server->sec_mode = le16_to_cpu(rsp->SecurityMode);
581 server->maxReq = min_t(unsigned int,
582 le16_to_cpu(rsp->MaxMpxCount),
583 cifs_max_pending);
584 set_credits(server, server->maxReq);
585 server->maxBuf = le16_to_cpu(rsp->MaxBufSize);
586 /* even though we do not use raw we might as well set this
587 accurately, in case we ever find a need for it */
588 if ((le16_to_cpu(rsp->RawMode) & RAW_ENABLE) == RAW_ENABLE) {
589 server->max_rw = 0xFF00;
590 server->capabilities = CAP_MPX_MODE | CAP_RAW_MODE;
591 } else {
592 server->max_rw = 0;/* do not need to use raw anyway */
593 server->capabilities = CAP_MPX_MODE;
595 tmp = (__s16)le16_to_cpu(rsp->ServerTimeZone);
596 if (tmp == -1) {
597 /* OS/2 often does not set timezone therefore
598 * we must use server time to calc time zone.
599 * Could deviate slightly from the right zone.
600 * Smallest defined timezone difference is 15 minutes
601 * (i.e. Nepal). Rounding up/down is done to match
602 * this requirement.
604 int val, seconds, remain, result;
605 struct timespec64 ts;
606 time64_t utc = ktime_get_real_seconds();
607 ts = cnvrtDosUnixTm(rsp->SrvTime.Date,
608 rsp->SrvTime.Time, 0);
609 cifs_dbg(FYI, "SrvTime %lld sec since 1970 (utc: %lld) diff: %lld\n",
610 ts.tv_sec, utc,
611 utc - ts.tv_sec);
612 val = (int)(utc - ts.tv_sec);
613 seconds = abs(val);
614 result = (seconds / MIN_TZ_ADJ) * MIN_TZ_ADJ;
615 remain = seconds % MIN_TZ_ADJ;
616 if (remain >= (MIN_TZ_ADJ / 2))
617 result += MIN_TZ_ADJ;
618 if (val < 0)
619 result = -result;
620 server->timeAdj = result;
621 } else {
622 server->timeAdj = (int)tmp;
623 server->timeAdj *= 60; /* also in seconds */
625 cifs_dbg(FYI, "server->timeAdj: %d seconds\n", server->timeAdj);
628 /* BB get server time for time conversions and add
629 code to use it and timezone since this is not UTC */
631 if (rsp->EncryptionKeyLength ==
632 cpu_to_le16(CIFS_CRYPTO_KEY_SIZE)) {
633 memcpy(server->cryptkey, rsp->EncryptionKey,
634 CIFS_CRYPTO_KEY_SIZE);
635 } else if (server->sec_mode & SECMODE_PW_ENCRYPT) {
636 return -EIO; /* need cryptkey unless plain text */
639 cifs_dbg(FYI, "LANMAN negotiated\n");
640 return 0;
642 #else
643 static inline int
644 decode_lanman_negprot_rsp(struct TCP_Server_Info *server, NEGOTIATE_RSP *pSMBr)
646 cifs_dbg(VFS, "mount failed, cifs module not built with CIFS_WEAK_PW_HASH support\n");
647 return -EOPNOTSUPP;
649 #endif
651 static bool
652 should_set_ext_sec_flag(enum securityEnum sectype)
654 switch (sectype) {
655 case RawNTLMSSP:
656 case Kerberos:
657 return true;
658 case Unspecified:
659 if (global_secflags &
660 (CIFSSEC_MAY_KRB5 | CIFSSEC_MAY_NTLMSSP))
661 return true;
662 /* Fallthrough */
663 default:
664 return false;
669 CIFSSMBNegotiate(const unsigned int xid, struct cifs_ses *ses)
671 NEGOTIATE_REQ *pSMB;
672 NEGOTIATE_RSP *pSMBr;
673 int rc = 0;
674 int bytes_returned;
675 int i;
676 struct TCP_Server_Info *server = ses->server;
677 u16 count;
679 if (!server) {
680 WARN(1, "%s: server is NULL!\n", __func__);
681 return -EIO;
684 rc = smb_init(SMB_COM_NEGOTIATE, 0, NULL /* no tcon yet */ ,
685 (void **) &pSMB, (void **) &pSMBr);
686 if (rc)
687 return rc;
689 pSMB->hdr.Mid = get_next_mid(server);
690 pSMB->hdr.Flags2 |= (SMBFLG2_UNICODE | SMBFLG2_ERR_STATUS);
692 if (should_set_ext_sec_flag(ses->sectype)) {
693 cifs_dbg(FYI, "Requesting extended security.");
694 pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC;
697 count = 0;
699 * We know that all the name entries in the protocols array
700 * are short (< 16 bytes anyway) and are NUL terminated.
702 for (i = 0; i < CIFS_NUM_PROT; i++) {
703 size_t len = strlen(protocols[i].name) + 1;
705 memcpy(pSMB->DialectsArray+count, protocols[i].name, len);
706 count += len;
708 inc_rfc1001_len(pSMB, count);
709 pSMB->ByteCount = cpu_to_le16(count);
711 rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB,
712 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
713 if (rc != 0)
714 goto neg_err_exit;
716 server->dialect = le16_to_cpu(pSMBr->DialectIndex);
717 cifs_dbg(FYI, "Dialect: %d\n", server->dialect);
718 /* Check wct = 1 error case */
719 if ((pSMBr->hdr.WordCount < 13) || (server->dialect == BAD_PROT)) {
720 /* core returns wct = 1, but we do not ask for core - otherwise
721 small wct just comes when dialect index is -1 indicating we
722 could not negotiate a common dialect */
723 rc = -EOPNOTSUPP;
724 goto neg_err_exit;
725 } else if (pSMBr->hdr.WordCount == 13) {
726 server->negflavor = CIFS_NEGFLAVOR_LANMAN;
727 rc = decode_lanman_negprot_rsp(server, pSMBr);
728 goto signing_check;
729 } else if (pSMBr->hdr.WordCount != 17) {
730 /* unknown wct */
731 rc = -EOPNOTSUPP;
732 goto neg_err_exit;
734 /* else wct == 17, NTLM or better */
736 server->sec_mode = pSMBr->SecurityMode;
737 if ((server->sec_mode & SECMODE_USER) == 0)
738 cifs_dbg(FYI, "share mode security\n");
740 /* one byte, so no need to convert this or EncryptionKeyLen from
741 little endian */
742 server->maxReq = min_t(unsigned int, le16_to_cpu(pSMBr->MaxMpxCount),
743 cifs_max_pending);
744 set_credits(server, server->maxReq);
745 /* probably no need to store and check maxvcs */
746 server->maxBuf = le32_to_cpu(pSMBr->MaxBufferSize);
747 server->max_rw = le32_to_cpu(pSMBr->MaxRawSize);
748 cifs_dbg(NOISY, "Max buf = %d\n", ses->server->maxBuf);
749 server->capabilities = le32_to_cpu(pSMBr->Capabilities);
750 server->timeAdj = (int)(__s16)le16_to_cpu(pSMBr->ServerTimeZone);
751 server->timeAdj *= 60;
753 if (pSMBr->EncryptionKeyLength == CIFS_CRYPTO_KEY_SIZE) {
754 server->negflavor = CIFS_NEGFLAVOR_UNENCAP;
755 memcpy(ses->server->cryptkey, pSMBr->u.EncryptionKey,
756 CIFS_CRYPTO_KEY_SIZE);
757 } else if (pSMBr->hdr.Flags2 & SMBFLG2_EXT_SEC ||
758 server->capabilities & CAP_EXTENDED_SECURITY) {
759 server->negflavor = CIFS_NEGFLAVOR_EXTENDED;
760 rc = decode_ext_sec_blob(ses, pSMBr);
761 } else if (server->sec_mode & SECMODE_PW_ENCRYPT) {
762 rc = -EIO; /* no crypt key only if plain text pwd */
763 } else {
764 server->negflavor = CIFS_NEGFLAVOR_UNENCAP;
765 server->capabilities &= ~CAP_EXTENDED_SECURITY;
768 signing_check:
769 if (!rc)
770 rc = cifs_enable_signing(server, ses->sign);
771 neg_err_exit:
772 cifs_buf_release(pSMB);
774 cifs_dbg(FYI, "negprot rc %d\n", rc);
775 return rc;
779 CIFSSMBTDis(const unsigned int xid, struct cifs_tcon *tcon)
781 struct smb_hdr *smb_buffer;
782 int rc = 0;
784 cifs_dbg(FYI, "In tree disconnect\n");
786 /* BB: do we need to check this? These should never be NULL. */
787 if ((tcon->ses == NULL) || (tcon->ses->server == NULL))
788 return -EIO;
791 * No need to return error on this operation if tid invalidated and
792 * closed on server already e.g. due to tcp session crashing. Also,
793 * the tcon is no longer on the list, so no need to take lock before
794 * checking this.
796 if ((tcon->need_reconnect) || (tcon->ses->need_reconnect))
797 return 0;
799 rc = small_smb_init(SMB_COM_TREE_DISCONNECT, 0, tcon,
800 (void **)&smb_buffer);
801 if (rc)
802 return rc;
804 rc = SendReceiveNoRsp(xid, tcon->ses, (char *)smb_buffer, 0);
805 cifs_small_buf_release(smb_buffer);
806 if (rc)
807 cifs_dbg(FYI, "Tree disconnect failed %d\n", rc);
809 /* No need to return error on this operation if tid invalidated and
810 closed on server already e.g. due to tcp session crashing */
811 if (rc == -EAGAIN)
812 rc = 0;
814 return rc;
818 * This is a no-op for now. We're not really interested in the reply, but
819 * rather in the fact that the server sent one and that server->lstrp
820 * gets updated.
822 * FIXME: maybe we should consider checking that the reply matches request?
824 static void
825 cifs_echo_callback(struct mid_q_entry *mid)
827 struct TCP_Server_Info *server = mid->callback_data;
828 struct cifs_credits credits = { .value = 1, .instance = 0 };
830 DeleteMidQEntry(mid);
831 add_credits(server, &credits, CIFS_ECHO_OP);
835 CIFSSMBEcho(struct TCP_Server_Info *server)
837 ECHO_REQ *smb;
838 int rc = 0;
839 struct kvec iov[2];
840 struct smb_rqst rqst = { .rq_iov = iov,
841 .rq_nvec = 2 };
843 cifs_dbg(FYI, "In echo request\n");
845 rc = small_smb_init(SMB_COM_ECHO, 0, NULL, (void **)&smb);
846 if (rc)
847 return rc;
849 if (server->capabilities & CAP_UNICODE)
850 smb->hdr.Flags2 |= SMBFLG2_UNICODE;
852 /* set up echo request */
853 smb->hdr.Tid = 0xffff;
854 smb->hdr.WordCount = 1;
855 put_unaligned_le16(1, &smb->EchoCount);
856 put_bcc(1, &smb->hdr);
857 smb->Data[0] = 'a';
858 inc_rfc1001_len(smb, 3);
860 iov[0].iov_len = 4;
861 iov[0].iov_base = smb;
862 iov[1].iov_len = get_rfc1002_length(smb);
863 iov[1].iov_base = (char *)smb + 4;
865 rc = cifs_call_async(server, &rqst, NULL, cifs_echo_callback, NULL,
866 server, CIFS_NON_BLOCKING | CIFS_ECHO_OP, NULL);
867 if (rc)
868 cifs_dbg(FYI, "Echo request failed: %d\n", rc);
870 cifs_small_buf_release(smb);
872 return rc;
876 CIFSSMBLogoff(const unsigned int xid, struct cifs_ses *ses)
878 LOGOFF_ANDX_REQ *pSMB;
879 int rc = 0;
881 cifs_dbg(FYI, "In SMBLogoff for session disconnect\n");
884 * BB: do we need to check validity of ses and server? They should
885 * always be valid since we have an active reference. If not, that
886 * should probably be a BUG()
888 if (!ses || !ses->server)
889 return -EIO;
891 mutex_lock(&ses->session_mutex);
892 if (ses->need_reconnect)
893 goto session_already_dead; /* no need to send SMBlogoff if uid
894 already closed due to reconnect */
895 rc = small_smb_init(SMB_COM_LOGOFF_ANDX, 2, NULL, (void **)&pSMB);
896 if (rc) {
897 mutex_unlock(&ses->session_mutex);
898 return rc;
901 pSMB->hdr.Mid = get_next_mid(ses->server);
903 if (ses->server->sign)
904 pSMB->hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
906 pSMB->hdr.Uid = ses->Suid;
908 pSMB->AndXCommand = 0xFF;
909 rc = SendReceiveNoRsp(xid, ses, (char *) pSMB, 0);
910 cifs_small_buf_release(pSMB);
911 session_already_dead:
912 mutex_unlock(&ses->session_mutex);
914 /* if session dead then we do not need to do ulogoff,
915 since server closed smb session, no sense reporting
916 error */
917 if (rc == -EAGAIN)
918 rc = 0;
919 return rc;
923 CIFSPOSIXDelFile(const unsigned int xid, struct cifs_tcon *tcon,
924 const char *fileName, __u16 type,
925 const struct nls_table *nls_codepage, int remap)
927 TRANSACTION2_SPI_REQ *pSMB = NULL;
928 TRANSACTION2_SPI_RSP *pSMBr = NULL;
929 struct unlink_psx_rq *pRqD;
930 int name_len;
931 int rc = 0;
932 int bytes_returned = 0;
933 __u16 params, param_offset, offset, byte_count;
935 cifs_dbg(FYI, "In POSIX delete\n");
936 PsxDelete:
937 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
938 (void **) &pSMBr);
939 if (rc)
940 return rc;
942 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
943 name_len =
944 cifsConvertToUTF16((__le16 *) pSMB->FileName, fileName,
945 PATH_MAX, nls_codepage, remap);
946 name_len++; /* trailing null */
947 name_len *= 2;
948 } else {
949 name_len = copy_path_name(pSMB->FileName, fileName);
952 params = 6 + name_len;
953 pSMB->MaxParameterCount = cpu_to_le16(2);
954 pSMB->MaxDataCount = 0; /* BB double check this with jra */
955 pSMB->MaxSetupCount = 0;
956 pSMB->Reserved = 0;
957 pSMB->Flags = 0;
958 pSMB->Timeout = 0;
959 pSMB->Reserved2 = 0;
960 param_offset = offsetof(struct smb_com_transaction2_spi_req,
961 InformationLevel) - 4;
962 offset = param_offset + params;
964 /* Setup pointer to Request Data (inode type) */
965 pRqD = (struct unlink_psx_rq *)(((char *)&pSMB->hdr.Protocol) + offset);
966 pRqD->type = cpu_to_le16(type);
967 pSMB->ParameterOffset = cpu_to_le16(param_offset);
968 pSMB->DataOffset = cpu_to_le16(offset);
969 pSMB->SetupCount = 1;
970 pSMB->Reserved3 = 0;
971 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
972 byte_count = 3 /* pad */ + params + sizeof(struct unlink_psx_rq);
974 pSMB->DataCount = cpu_to_le16(sizeof(struct unlink_psx_rq));
975 pSMB->TotalDataCount = cpu_to_le16(sizeof(struct unlink_psx_rq));
976 pSMB->ParameterCount = cpu_to_le16(params);
977 pSMB->TotalParameterCount = pSMB->ParameterCount;
978 pSMB->InformationLevel = cpu_to_le16(SMB_POSIX_UNLINK);
979 pSMB->Reserved4 = 0;
980 inc_rfc1001_len(pSMB, byte_count);
981 pSMB->ByteCount = cpu_to_le16(byte_count);
982 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
983 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
984 if (rc)
985 cifs_dbg(FYI, "Posix delete returned %d\n", rc);
986 cifs_buf_release(pSMB);
988 cifs_stats_inc(&tcon->stats.cifs_stats.num_deletes);
990 if (rc == -EAGAIN)
991 goto PsxDelete;
993 return rc;
997 CIFSSMBDelFile(const unsigned int xid, struct cifs_tcon *tcon, const char *name,
998 struct cifs_sb_info *cifs_sb)
1000 DELETE_FILE_REQ *pSMB = NULL;
1001 DELETE_FILE_RSP *pSMBr = NULL;
1002 int rc = 0;
1003 int bytes_returned;
1004 int name_len;
1005 int remap = cifs_remap(cifs_sb);
1007 DelFileRetry:
1008 rc = smb_init(SMB_COM_DELETE, 1, tcon, (void **) &pSMB,
1009 (void **) &pSMBr);
1010 if (rc)
1011 return rc;
1013 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1014 name_len = cifsConvertToUTF16((__le16 *) pSMB->fileName, name,
1015 PATH_MAX, cifs_sb->local_nls,
1016 remap);
1017 name_len++; /* trailing null */
1018 name_len *= 2;
1019 } else {
1020 name_len = copy_path_name(pSMB->fileName, name);
1022 pSMB->SearchAttributes =
1023 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM);
1024 pSMB->BufferFormat = 0x04;
1025 inc_rfc1001_len(pSMB, name_len + 1);
1026 pSMB->ByteCount = cpu_to_le16(name_len + 1);
1027 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1028 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1029 cifs_stats_inc(&tcon->stats.cifs_stats.num_deletes);
1030 if (rc)
1031 cifs_dbg(FYI, "Error in RMFile = %d\n", rc);
1033 cifs_buf_release(pSMB);
1034 if (rc == -EAGAIN)
1035 goto DelFileRetry;
1037 return rc;
1041 CIFSSMBRmDir(const unsigned int xid, struct cifs_tcon *tcon, const char *name,
1042 struct cifs_sb_info *cifs_sb)
1044 DELETE_DIRECTORY_REQ *pSMB = NULL;
1045 DELETE_DIRECTORY_RSP *pSMBr = NULL;
1046 int rc = 0;
1047 int bytes_returned;
1048 int name_len;
1049 int remap = cifs_remap(cifs_sb);
1051 cifs_dbg(FYI, "In CIFSSMBRmDir\n");
1052 RmDirRetry:
1053 rc = smb_init(SMB_COM_DELETE_DIRECTORY, 0, tcon, (void **) &pSMB,
1054 (void **) &pSMBr);
1055 if (rc)
1056 return rc;
1058 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1059 name_len = cifsConvertToUTF16((__le16 *) pSMB->DirName, name,
1060 PATH_MAX, cifs_sb->local_nls,
1061 remap);
1062 name_len++; /* trailing null */
1063 name_len *= 2;
1064 } else {
1065 name_len = copy_path_name(pSMB->DirName, name);
1068 pSMB->BufferFormat = 0x04;
1069 inc_rfc1001_len(pSMB, name_len + 1);
1070 pSMB->ByteCount = cpu_to_le16(name_len + 1);
1071 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1072 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1073 cifs_stats_inc(&tcon->stats.cifs_stats.num_rmdirs);
1074 if (rc)
1075 cifs_dbg(FYI, "Error in RMDir = %d\n", rc);
1077 cifs_buf_release(pSMB);
1078 if (rc == -EAGAIN)
1079 goto RmDirRetry;
1080 return rc;
1084 CIFSSMBMkDir(const unsigned int xid, struct inode *inode, umode_t mode,
1085 struct cifs_tcon *tcon, const char *name,
1086 struct cifs_sb_info *cifs_sb)
1088 int rc = 0;
1089 CREATE_DIRECTORY_REQ *pSMB = NULL;
1090 CREATE_DIRECTORY_RSP *pSMBr = NULL;
1091 int bytes_returned;
1092 int name_len;
1093 int remap = cifs_remap(cifs_sb);
1095 cifs_dbg(FYI, "In CIFSSMBMkDir\n");
1096 MkDirRetry:
1097 rc = smb_init(SMB_COM_CREATE_DIRECTORY, 0, tcon, (void **) &pSMB,
1098 (void **) &pSMBr);
1099 if (rc)
1100 return rc;
1102 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1103 name_len = cifsConvertToUTF16((__le16 *) pSMB->DirName, name,
1104 PATH_MAX, cifs_sb->local_nls,
1105 remap);
1106 name_len++; /* trailing null */
1107 name_len *= 2;
1108 } else {
1109 name_len = copy_path_name(pSMB->DirName, name);
1112 pSMB->BufferFormat = 0x04;
1113 inc_rfc1001_len(pSMB, name_len + 1);
1114 pSMB->ByteCount = cpu_to_le16(name_len + 1);
1115 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1116 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1117 cifs_stats_inc(&tcon->stats.cifs_stats.num_mkdirs);
1118 if (rc)
1119 cifs_dbg(FYI, "Error in Mkdir = %d\n", rc);
1121 cifs_buf_release(pSMB);
1122 if (rc == -EAGAIN)
1123 goto MkDirRetry;
1124 return rc;
1128 CIFSPOSIXCreate(const unsigned int xid, struct cifs_tcon *tcon,
1129 __u32 posix_flags, __u64 mode, __u16 *netfid,
1130 FILE_UNIX_BASIC_INFO *pRetData, __u32 *pOplock,
1131 const char *name, const struct nls_table *nls_codepage,
1132 int remap)
1134 TRANSACTION2_SPI_REQ *pSMB = NULL;
1135 TRANSACTION2_SPI_RSP *pSMBr = NULL;
1136 int name_len;
1137 int rc = 0;
1138 int bytes_returned = 0;
1139 __u16 params, param_offset, offset, byte_count, count;
1140 OPEN_PSX_REQ *pdata;
1141 OPEN_PSX_RSP *psx_rsp;
1143 cifs_dbg(FYI, "In POSIX Create\n");
1144 PsxCreat:
1145 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
1146 (void **) &pSMBr);
1147 if (rc)
1148 return rc;
1150 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1151 name_len =
1152 cifsConvertToUTF16((__le16 *) pSMB->FileName, name,
1153 PATH_MAX, nls_codepage, remap);
1154 name_len++; /* trailing null */
1155 name_len *= 2;
1156 } else {
1157 name_len = copy_path_name(pSMB->FileName, name);
1160 params = 6 + name_len;
1161 count = sizeof(OPEN_PSX_REQ);
1162 pSMB->MaxParameterCount = cpu_to_le16(2);
1163 pSMB->MaxDataCount = cpu_to_le16(1000); /* large enough */
1164 pSMB->MaxSetupCount = 0;
1165 pSMB->Reserved = 0;
1166 pSMB->Flags = 0;
1167 pSMB->Timeout = 0;
1168 pSMB->Reserved2 = 0;
1169 param_offset = offsetof(struct smb_com_transaction2_spi_req,
1170 InformationLevel) - 4;
1171 offset = param_offset + params;
1172 pdata = (OPEN_PSX_REQ *)(((char *)&pSMB->hdr.Protocol) + offset);
1173 pdata->Level = cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC);
1174 pdata->Permissions = cpu_to_le64(mode);
1175 pdata->PosixOpenFlags = cpu_to_le32(posix_flags);
1176 pdata->OpenFlags = cpu_to_le32(*pOplock);
1177 pSMB->ParameterOffset = cpu_to_le16(param_offset);
1178 pSMB->DataOffset = cpu_to_le16(offset);
1179 pSMB->SetupCount = 1;
1180 pSMB->Reserved3 = 0;
1181 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
1182 byte_count = 3 /* pad */ + params + count;
1184 pSMB->DataCount = cpu_to_le16(count);
1185 pSMB->ParameterCount = cpu_to_le16(params);
1186 pSMB->TotalDataCount = pSMB->DataCount;
1187 pSMB->TotalParameterCount = pSMB->ParameterCount;
1188 pSMB->InformationLevel = cpu_to_le16(SMB_POSIX_OPEN);
1189 pSMB->Reserved4 = 0;
1190 inc_rfc1001_len(pSMB, byte_count);
1191 pSMB->ByteCount = cpu_to_le16(byte_count);
1192 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1193 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1194 if (rc) {
1195 cifs_dbg(FYI, "Posix create returned %d\n", rc);
1196 goto psx_create_err;
1199 cifs_dbg(FYI, "copying inode info\n");
1200 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
1202 if (rc || get_bcc(&pSMBr->hdr) < sizeof(OPEN_PSX_RSP)) {
1203 rc = -EIO; /* bad smb */
1204 goto psx_create_err;
1207 /* copy return information to pRetData */
1208 psx_rsp = (OPEN_PSX_RSP *)((char *) &pSMBr->hdr.Protocol
1209 + le16_to_cpu(pSMBr->t2.DataOffset));
1211 *pOplock = le16_to_cpu(psx_rsp->OplockFlags);
1212 if (netfid)
1213 *netfid = psx_rsp->Fid; /* cifs fid stays in le */
1214 /* Let caller know file was created so we can set the mode. */
1215 /* Do we care about the CreateAction in any other cases? */
1216 if (cpu_to_le32(FILE_CREATE) == psx_rsp->CreateAction)
1217 *pOplock |= CIFS_CREATE_ACTION;
1218 /* check to make sure response data is there */
1219 if (psx_rsp->ReturnedLevel != cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC)) {
1220 pRetData->Type = cpu_to_le32(-1); /* unknown */
1221 cifs_dbg(NOISY, "unknown type\n");
1222 } else {
1223 if (get_bcc(&pSMBr->hdr) < sizeof(OPEN_PSX_RSP)
1224 + sizeof(FILE_UNIX_BASIC_INFO)) {
1225 cifs_dbg(VFS, "Open response data too small\n");
1226 pRetData->Type = cpu_to_le32(-1);
1227 goto psx_create_err;
1229 memcpy((char *) pRetData,
1230 (char *)psx_rsp + sizeof(OPEN_PSX_RSP),
1231 sizeof(FILE_UNIX_BASIC_INFO));
1234 psx_create_err:
1235 cifs_buf_release(pSMB);
1237 if (posix_flags & SMB_O_DIRECTORY)
1238 cifs_stats_inc(&tcon->stats.cifs_stats.num_posixmkdirs);
1239 else
1240 cifs_stats_inc(&tcon->stats.cifs_stats.num_posixopens);
1242 if (rc == -EAGAIN)
1243 goto PsxCreat;
1245 return rc;
1248 static __u16 convert_disposition(int disposition)
1250 __u16 ofun = 0;
1252 switch (disposition) {
1253 case FILE_SUPERSEDE:
1254 ofun = SMBOPEN_OCREATE | SMBOPEN_OTRUNC;
1255 break;
1256 case FILE_OPEN:
1257 ofun = SMBOPEN_OAPPEND;
1258 break;
1259 case FILE_CREATE:
1260 ofun = SMBOPEN_OCREATE;
1261 break;
1262 case FILE_OPEN_IF:
1263 ofun = SMBOPEN_OCREATE | SMBOPEN_OAPPEND;
1264 break;
1265 case FILE_OVERWRITE:
1266 ofun = SMBOPEN_OTRUNC;
1267 break;
1268 case FILE_OVERWRITE_IF:
1269 ofun = SMBOPEN_OCREATE | SMBOPEN_OTRUNC;
1270 break;
1271 default:
1272 cifs_dbg(FYI, "unknown disposition %d\n", disposition);
1273 ofun = SMBOPEN_OAPPEND; /* regular open */
1275 return ofun;
1278 static int
1279 access_flags_to_smbopen_mode(const int access_flags)
1281 int masked_flags = access_flags & (GENERIC_READ | GENERIC_WRITE);
1283 if (masked_flags == GENERIC_READ)
1284 return SMBOPEN_READ;
1285 else if (masked_flags == GENERIC_WRITE)
1286 return SMBOPEN_WRITE;
1288 /* just go for read/write */
1289 return SMBOPEN_READWRITE;
1293 SMBLegacyOpen(const unsigned int xid, struct cifs_tcon *tcon,
1294 const char *fileName, const int openDisposition,
1295 const int access_flags, const int create_options, __u16 *netfid,
1296 int *pOplock, FILE_ALL_INFO *pfile_info,
1297 const struct nls_table *nls_codepage, int remap)
1299 int rc = -EACCES;
1300 OPENX_REQ *pSMB = NULL;
1301 OPENX_RSP *pSMBr = NULL;
1302 int bytes_returned;
1303 int name_len;
1304 __u16 count;
1306 OldOpenRetry:
1307 rc = smb_init(SMB_COM_OPEN_ANDX, 15, tcon, (void **) &pSMB,
1308 (void **) &pSMBr);
1309 if (rc)
1310 return rc;
1312 pSMB->AndXCommand = 0xFF; /* none */
1314 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1315 count = 1; /* account for one byte pad to word boundary */
1316 name_len =
1317 cifsConvertToUTF16((__le16 *) (pSMB->fileName + 1),
1318 fileName, PATH_MAX, nls_codepage, remap);
1319 name_len++; /* trailing null */
1320 name_len *= 2;
1321 } else {
1322 count = 0; /* no pad */
1323 name_len = copy_path_name(pSMB->fileName, fileName);
1325 if (*pOplock & REQ_OPLOCK)
1326 pSMB->OpenFlags = cpu_to_le16(REQ_OPLOCK);
1327 else if (*pOplock & REQ_BATCHOPLOCK)
1328 pSMB->OpenFlags = cpu_to_le16(REQ_BATCHOPLOCK);
1330 pSMB->OpenFlags |= cpu_to_le16(REQ_MORE_INFO);
1331 pSMB->Mode = cpu_to_le16(access_flags_to_smbopen_mode(access_flags));
1332 pSMB->Mode |= cpu_to_le16(0x40); /* deny none */
1333 /* set file as system file if special file such
1334 as fifo and server expecting SFU style and
1335 no Unix extensions */
1337 if (create_options & CREATE_OPTION_SPECIAL)
1338 pSMB->FileAttributes = cpu_to_le16(ATTR_SYSTEM);
1339 else /* BB FIXME BB */
1340 pSMB->FileAttributes = cpu_to_le16(0/*ATTR_NORMAL*/);
1342 if (create_options & CREATE_OPTION_READONLY)
1343 pSMB->FileAttributes |= cpu_to_le16(ATTR_READONLY);
1345 /* BB FIXME BB */
1346 /* pSMB->CreateOptions = cpu_to_le32(create_options &
1347 CREATE_OPTIONS_MASK); */
1348 /* BB FIXME END BB */
1350 pSMB->Sattr = cpu_to_le16(ATTR_HIDDEN | ATTR_SYSTEM | ATTR_DIRECTORY);
1351 pSMB->OpenFunction = cpu_to_le16(convert_disposition(openDisposition));
1352 count += name_len;
1353 inc_rfc1001_len(pSMB, count);
1355 pSMB->ByteCount = cpu_to_le16(count);
1356 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1357 (struct smb_hdr *)pSMBr, &bytes_returned, 0);
1358 cifs_stats_inc(&tcon->stats.cifs_stats.num_opens);
1359 if (rc) {
1360 cifs_dbg(FYI, "Error in Open = %d\n", rc);
1361 } else {
1362 /* BB verify if wct == 15 */
1364 /* *pOplock = pSMBr->OplockLevel; */ /* BB take from action field*/
1366 *netfid = pSMBr->Fid; /* cifs fid stays in le */
1367 /* Let caller know file was created so we can set the mode. */
1368 /* Do we care about the CreateAction in any other cases? */
1369 /* BB FIXME BB */
1370 /* if (cpu_to_le32(FILE_CREATE) == pSMBr->CreateAction)
1371 *pOplock |= CIFS_CREATE_ACTION; */
1372 /* BB FIXME END */
1374 if (pfile_info) {
1375 pfile_info->CreationTime = 0; /* BB convert CreateTime*/
1376 pfile_info->LastAccessTime = 0; /* BB fixme */
1377 pfile_info->LastWriteTime = 0; /* BB fixme */
1378 pfile_info->ChangeTime = 0; /* BB fixme */
1379 pfile_info->Attributes =
1380 cpu_to_le32(le16_to_cpu(pSMBr->FileAttributes));
1381 /* the file_info buf is endian converted by caller */
1382 pfile_info->AllocationSize =
1383 cpu_to_le64(le32_to_cpu(pSMBr->EndOfFile));
1384 pfile_info->EndOfFile = pfile_info->AllocationSize;
1385 pfile_info->NumberOfLinks = cpu_to_le32(1);
1386 pfile_info->DeletePending = 0;
1390 cifs_buf_release(pSMB);
1391 if (rc == -EAGAIN)
1392 goto OldOpenRetry;
1393 return rc;
1397 CIFS_open(const unsigned int xid, struct cifs_open_parms *oparms, int *oplock,
1398 FILE_ALL_INFO *buf)
1400 int rc;
1401 OPEN_REQ *req = NULL;
1402 OPEN_RSP *rsp = NULL;
1403 int bytes_returned;
1404 int name_len;
1405 __u16 count;
1406 struct cifs_sb_info *cifs_sb = oparms->cifs_sb;
1407 struct cifs_tcon *tcon = oparms->tcon;
1408 int remap = cifs_remap(cifs_sb);
1409 const struct nls_table *nls = cifs_sb->local_nls;
1410 int create_options = oparms->create_options;
1411 int desired_access = oparms->desired_access;
1412 int disposition = oparms->disposition;
1413 const char *path = oparms->path;
1415 openRetry:
1416 rc = smb_init(SMB_COM_NT_CREATE_ANDX, 24, tcon, (void **)&req,
1417 (void **)&rsp);
1418 if (rc)
1419 return rc;
1421 /* no commands go after this */
1422 req->AndXCommand = 0xFF;
1424 if (req->hdr.Flags2 & SMBFLG2_UNICODE) {
1425 /* account for one byte pad to word boundary */
1426 count = 1;
1427 name_len = cifsConvertToUTF16((__le16 *)(req->fileName + 1),
1428 path, PATH_MAX, nls, remap);
1429 /* trailing null */
1430 name_len++;
1431 name_len *= 2;
1432 req->NameLength = cpu_to_le16(name_len);
1433 } else {
1434 /* BB improve check for buffer overruns BB */
1435 /* no pad */
1436 count = 0;
1437 name_len = copy_path_name(req->fileName, path);
1438 req->NameLength = cpu_to_le16(name_len);
1441 if (*oplock & REQ_OPLOCK)
1442 req->OpenFlags = cpu_to_le32(REQ_OPLOCK);
1443 else if (*oplock & REQ_BATCHOPLOCK)
1444 req->OpenFlags = cpu_to_le32(REQ_BATCHOPLOCK);
1446 req->DesiredAccess = cpu_to_le32(desired_access);
1447 req->AllocationSize = 0;
1450 * Set file as system file if special file such as fifo and server
1451 * expecting SFU style and no Unix extensions.
1453 if (create_options & CREATE_OPTION_SPECIAL)
1454 req->FileAttributes = cpu_to_le32(ATTR_SYSTEM);
1455 else
1456 req->FileAttributes = cpu_to_le32(ATTR_NORMAL);
1459 * XP does not handle ATTR_POSIX_SEMANTICS but it helps speed up case
1460 * sensitive checks for other servers such as Samba.
1462 if (tcon->ses->capabilities & CAP_UNIX)
1463 req->FileAttributes |= cpu_to_le32(ATTR_POSIX_SEMANTICS);
1465 if (create_options & CREATE_OPTION_READONLY)
1466 req->FileAttributes |= cpu_to_le32(ATTR_READONLY);
1468 req->ShareAccess = cpu_to_le32(FILE_SHARE_ALL);
1469 req->CreateDisposition = cpu_to_le32(disposition);
1470 req->CreateOptions = cpu_to_le32(create_options & CREATE_OPTIONS_MASK);
1472 /* BB Expirement with various impersonation levels and verify */
1473 req->ImpersonationLevel = cpu_to_le32(SECURITY_IMPERSONATION);
1474 req->SecurityFlags = SECURITY_CONTEXT_TRACKING|SECURITY_EFFECTIVE_ONLY;
1476 count += name_len;
1477 inc_rfc1001_len(req, count);
1479 req->ByteCount = cpu_to_le16(count);
1480 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *)req,
1481 (struct smb_hdr *)rsp, &bytes_returned, 0);
1482 cifs_stats_inc(&tcon->stats.cifs_stats.num_opens);
1483 if (rc) {
1484 cifs_dbg(FYI, "Error in Open = %d\n", rc);
1485 cifs_buf_release(req);
1486 if (rc == -EAGAIN)
1487 goto openRetry;
1488 return rc;
1491 /* 1 byte no need to le_to_cpu */
1492 *oplock = rsp->OplockLevel;
1493 /* cifs fid stays in le */
1494 oparms->fid->netfid = rsp->Fid;
1495 oparms->fid->access = desired_access;
1497 /* Let caller know file was created so we can set the mode. */
1498 /* Do we care about the CreateAction in any other cases? */
1499 if (cpu_to_le32(FILE_CREATE) == rsp->CreateAction)
1500 *oplock |= CIFS_CREATE_ACTION;
1502 if (buf) {
1503 /* copy from CreationTime to Attributes */
1504 memcpy((char *)buf, (char *)&rsp->CreationTime, 36);
1505 /* the file_info buf is endian converted by caller */
1506 buf->AllocationSize = rsp->AllocationSize;
1507 buf->EndOfFile = rsp->EndOfFile;
1508 buf->NumberOfLinks = cpu_to_le32(1);
1509 buf->DeletePending = 0;
1512 cifs_buf_release(req);
1513 return rc;
1517 * Discard any remaining data in the current SMB. To do this, we borrow the
1518 * current bigbuf.
1521 cifs_discard_remaining_data(struct TCP_Server_Info *server)
1523 unsigned int rfclen = server->pdu_size;
1524 int remaining = rfclen + server->vals->header_preamble_size -
1525 server->total_read;
1527 while (remaining > 0) {
1528 int length;
1530 length = cifs_read_from_socket(server, server->bigbuf,
1531 min_t(unsigned int, remaining,
1532 CIFSMaxBufSize + MAX_HEADER_SIZE(server)));
1533 if (length < 0)
1534 return length;
1535 server->total_read += length;
1536 remaining -= length;
1539 return 0;
1542 static int
1543 __cifs_readv_discard(struct TCP_Server_Info *server, struct mid_q_entry *mid,
1544 bool malformed)
1546 int length;
1548 length = cifs_discard_remaining_data(server);
1549 dequeue_mid(mid, malformed);
1550 mid->resp_buf = server->smallbuf;
1551 server->smallbuf = NULL;
1552 return length;
1555 static int
1556 cifs_readv_discard(struct TCP_Server_Info *server, struct mid_q_entry *mid)
1558 struct cifs_readdata *rdata = mid->callback_data;
1560 return __cifs_readv_discard(server, mid, rdata->result);
1564 cifs_readv_receive(struct TCP_Server_Info *server, struct mid_q_entry *mid)
1566 int length, len;
1567 unsigned int data_offset, data_len;
1568 struct cifs_readdata *rdata = mid->callback_data;
1569 char *buf = server->smallbuf;
1570 unsigned int buflen = server->pdu_size +
1571 server->vals->header_preamble_size;
1572 bool use_rdma_mr = false;
1574 cifs_dbg(FYI, "%s: mid=%llu offset=%llu bytes=%u\n",
1575 __func__, mid->mid, rdata->offset, rdata->bytes);
1578 * read the rest of READ_RSP header (sans Data array), or whatever we
1579 * can if there's not enough data. At this point, we've read down to
1580 * the Mid.
1582 len = min_t(unsigned int, buflen, server->vals->read_rsp_size) -
1583 HEADER_SIZE(server) + 1;
1585 length = cifs_read_from_socket(server,
1586 buf + HEADER_SIZE(server) - 1, len);
1587 if (length < 0)
1588 return length;
1589 server->total_read += length;
1591 if (server->ops->is_session_expired &&
1592 server->ops->is_session_expired(buf)) {
1593 cifs_reconnect(server);
1594 wake_up(&server->response_q);
1595 return -1;
1598 if (server->ops->is_status_pending &&
1599 server->ops->is_status_pending(buf, server)) {
1600 cifs_discard_remaining_data(server);
1601 return -1;
1604 /* set up first two iov for signature check and to get credits */
1605 rdata->iov[0].iov_base = buf;
1606 rdata->iov[0].iov_len = server->vals->header_preamble_size;
1607 rdata->iov[1].iov_base = buf + server->vals->header_preamble_size;
1608 rdata->iov[1].iov_len =
1609 server->total_read - server->vals->header_preamble_size;
1610 cifs_dbg(FYI, "0: iov_base=%p iov_len=%zu\n",
1611 rdata->iov[0].iov_base, rdata->iov[0].iov_len);
1612 cifs_dbg(FYI, "1: iov_base=%p iov_len=%zu\n",
1613 rdata->iov[1].iov_base, rdata->iov[1].iov_len);
1615 /* Was the SMB read successful? */
1616 rdata->result = server->ops->map_error(buf, false);
1617 if (rdata->result != 0) {
1618 cifs_dbg(FYI, "%s: server returned error %d\n",
1619 __func__, rdata->result);
1620 /* normal error on read response */
1621 return __cifs_readv_discard(server, mid, false);
1624 /* Is there enough to get to the rest of the READ_RSP header? */
1625 if (server->total_read < server->vals->read_rsp_size) {
1626 cifs_dbg(FYI, "%s: server returned short header. got=%u expected=%zu\n",
1627 __func__, server->total_read,
1628 server->vals->read_rsp_size);
1629 rdata->result = -EIO;
1630 return cifs_readv_discard(server, mid);
1633 data_offset = server->ops->read_data_offset(buf) +
1634 server->vals->header_preamble_size;
1635 if (data_offset < server->total_read) {
1637 * win2k8 sometimes sends an offset of 0 when the read
1638 * is beyond the EOF. Treat it as if the data starts just after
1639 * the header.
1641 cifs_dbg(FYI, "%s: data offset (%u) inside read response header\n",
1642 __func__, data_offset);
1643 data_offset = server->total_read;
1644 } else if (data_offset > MAX_CIFS_SMALL_BUFFER_SIZE) {
1645 /* data_offset is beyond the end of smallbuf */
1646 cifs_dbg(FYI, "%s: data offset (%u) beyond end of smallbuf\n",
1647 __func__, data_offset);
1648 rdata->result = -EIO;
1649 return cifs_readv_discard(server, mid);
1652 cifs_dbg(FYI, "%s: total_read=%u data_offset=%u\n",
1653 __func__, server->total_read, data_offset);
1655 len = data_offset - server->total_read;
1656 if (len > 0) {
1657 /* read any junk before data into the rest of smallbuf */
1658 length = cifs_read_from_socket(server,
1659 buf + server->total_read, len);
1660 if (length < 0)
1661 return length;
1662 server->total_read += length;
1665 /* how much data is in the response? */
1666 #ifdef CONFIG_CIFS_SMB_DIRECT
1667 use_rdma_mr = rdata->mr;
1668 #endif
1669 data_len = server->ops->read_data_length(buf, use_rdma_mr);
1670 if (!use_rdma_mr && (data_offset + data_len > buflen)) {
1671 /* data_len is corrupt -- discard frame */
1672 rdata->result = -EIO;
1673 return cifs_readv_discard(server, mid);
1676 length = rdata->read_into_pages(server, rdata, data_len);
1677 if (length < 0)
1678 return length;
1680 server->total_read += length;
1682 cifs_dbg(FYI, "total_read=%u buflen=%u remaining=%u\n",
1683 server->total_read, buflen, data_len);
1685 /* discard anything left over */
1686 if (server->total_read < buflen)
1687 return cifs_readv_discard(server, mid);
1689 dequeue_mid(mid, false);
1690 mid->resp_buf = server->smallbuf;
1691 server->smallbuf = NULL;
1692 return length;
1695 static void
1696 cifs_readv_callback(struct mid_q_entry *mid)
1698 struct cifs_readdata *rdata = mid->callback_data;
1699 struct cifs_tcon *tcon = tlink_tcon(rdata->cfile->tlink);
1700 struct TCP_Server_Info *server = tcon->ses->server;
1701 struct smb_rqst rqst = { .rq_iov = rdata->iov,
1702 .rq_nvec = 2,
1703 .rq_pages = rdata->pages,
1704 .rq_offset = rdata->page_offset,
1705 .rq_npages = rdata->nr_pages,
1706 .rq_pagesz = rdata->pagesz,
1707 .rq_tailsz = rdata->tailsz };
1708 struct cifs_credits credits = { .value = 1, .instance = 0 };
1710 cifs_dbg(FYI, "%s: mid=%llu state=%d result=%d bytes=%u\n",
1711 __func__, mid->mid, mid->mid_state, rdata->result,
1712 rdata->bytes);
1714 switch (mid->mid_state) {
1715 case MID_RESPONSE_RECEIVED:
1716 /* result already set, check signature */
1717 if (server->sign) {
1718 int rc = 0;
1720 rc = cifs_verify_signature(&rqst, server,
1721 mid->sequence_number);
1722 if (rc)
1723 cifs_dbg(VFS, "SMB signature verification returned error = %d\n",
1724 rc);
1726 /* FIXME: should this be counted toward the initiating task? */
1727 task_io_account_read(rdata->got_bytes);
1728 cifs_stats_bytes_read(tcon, rdata->got_bytes);
1729 break;
1730 case MID_REQUEST_SUBMITTED:
1731 case MID_RETRY_NEEDED:
1732 rdata->result = -EAGAIN;
1733 if (server->sign && rdata->got_bytes)
1734 /* reset bytes number since we can not check a sign */
1735 rdata->got_bytes = 0;
1736 /* FIXME: should this be counted toward the initiating task? */
1737 task_io_account_read(rdata->got_bytes);
1738 cifs_stats_bytes_read(tcon, rdata->got_bytes);
1739 break;
1740 default:
1741 rdata->result = -EIO;
1744 queue_work(cifsiod_wq, &rdata->work);
1745 DeleteMidQEntry(mid);
1746 add_credits(server, &credits, 0);
1749 /* cifs_async_readv - send an async write, and set up mid to handle result */
1751 cifs_async_readv(struct cifs_readdata *rdata)
1753 int rc;
1754 READ_REQ *smb = NULL;
1755 int wct;
1756 struct cifs_tcon *tcon = tlink_tcon(rdata->cfile->tlink);
1757 struct smb_rqst rqst = { .rq_iov = rdata->iov,
1758 .rq_nvec = 2 };
1760 cifs_dbg(FYI, "%s: offset=%llu bytes=%u\n",
1761 __func__, rdata->offset, rdata->bytes);
1763 if (tcon->ses->capabilities & CAP_LARGE_FILES)
1764 wct = 12;
1765 else {
1766 wct = 10; /* old style read */
1767 if ((rdata->offset >> 32) > 0) {
1768 /* can not handle this big offset for old */
1769 return -EIO;
1773 rc = small_smb_init(SMB_COM_READ_ANDX, wct, tcon, (void **)&smb);
1774 if (rc)
1775 return rc;
1777 smb->hdr.Pid = cpu_to_le16((__u16)rdata->pid);
1778 smb->hdr.PidHigh = cpu_to_le16((__u16)(rdata->pid >> 16));
1780 smb->AndXCommand = 0xFF; /* none */
1781 smb->Fid = rdata->cfile->fid.netfid;
1782 smb->OffsetLow = cpu_to_le32(rdata->offset & 0xFFFFFFFF);
1783 if (wct == 12)
1784 smb->OffsetHigh = cpu_to_le32(rdata->offset >> 32);
1785 smb->Remaining = 0;
1786 smb->MaxCount = cpu_to_le16(rdata->bytes & 0xFFFF);
1787 smb->MaxCountHigh = cpu_to_le32(rdata->bytes >> 16);
1788 if (wct == 12)
1789 smb->ByteCount = 0;
1790 else {
1791 /* old style read */
1792 struct smb_com_readx_req *smbr =
1793 (struct smb_com_readx_req *)smb;
1794 smbr->ByteCount = 0;
1797 /* 4 for RFC1001 length + 1 for BCC */
1798 rdata->iov[0].iov_base = smb;
1799 rdata->iov[0].iov_len = 4;
1800 rdata->iov[1].iov_base = (char *)smb + 4;
1801 rdata->iov[1].iov_len = get_rfc1002_length(smb);
1803 kref_get(&rdata->refcount);
1804 rc = cifs_call_async(tcon->ses->server, &rqst, cifs_readv_receive,
1805 cifs_readv_callback, NULL, rdata, 0, NULL);
1807 if (rc == 0)
1808 cifs_stats_inc(&tcon->stats.cifs_stats.num_reads);
1809 else
1810 kref_put(&rdata->refcount, cifs_readdata_release);
1812 cifs_small_buf_release(smb);
1813 return rc;
1817 CIFSSMBRead(const unsigned int xid, struct cifs_io_parms *io_parms,
1818 unsigned int *nbytes, char **buf, int *pbuf_type)
1820 int rc = -EACCES;
1821 READ_REQ *pSMB = NULL;
1822 READ_RSP *pSMBr = NULL;
1823 char *pReadData = NULL;
1824 int wct;
1825 int resp_buf_type = 0;
1826 struct kvec iov[1];
1827 struct kvec rsp_iov;
1828 __u32 pid = io_parms->pid;
1829 __u16 netfid = io_parms->netfid;
1830 __u64 offset = io_parms->offset;
1831 struct cifs_tcon *tcon = io_parms->tcon;
1832 unsigned int count = io_parms->length;
1834 cifs_dbg(FYI, "Reading %d bytes on fid %d\n", count, netfid);
1835 if (tcon->ses->capabilities & CAP_LARGE_FILES)
1836 wct = 12;
1837 else {
1838 wct = 10; /* old style read */
1839 if ((offset >> 32) > 0) {
1840 /* can not handle this big offset for old */
1841 return -EIO;
1845 *nbytes = 0;
1846 rc = small_smb_init(SMB_COM_READ_ANDX, wct, tcon, (void **) &pSMB);
1847 if (rc)
1848 return rc;
1850 pSMB->hdr.Pid = cpu_to_le16((__u16)pid);
1851 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid >> 16));
1853 /* tcon and ses pointer are checked in smb_init */
1854 if (tcon->ses->server == NULL)
1855 return -ECONNABORTED;
1857 pSMB->AndXCommand = 0xFF; /* none */
1858 pSMB->Fid = netfid;
1859 pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF);
1860 if (wct == 12)
1861 pSMB->OffsetHigh = cpu_to_le32(offset >> 32);
1863 pSMB->Remaining = 0;
1864 pSMB->MaxCount = cpu_to_le16(count & 0xFFFF);
1865 pSMB->MaxCountHigh = cpu_to_le32(count >> 16);
1866 if (wct == 12)
1867 pSMB->ByteCount = 0; /* no need to do le conversion since 0 */
1868 else {
1869 /* old style read */
1870 struct smb_com_readx_req *pSMBW =
1871 (struct smb_com_readx_req *)pSMB;
1872 pSMBW->ByteCount = 0;
1875 iov[0].iov_base = (char *)pSMB;
1876 iov[0].iov_len = be32_to_cpu(pSMB->hdr.smb_buf_length) + 4;
1877 rc = SendReceive2(xid, tcon->ses, iov, 1, &resp_buf_type,
1878 CIFS_LOG_ERROR, &rsp_iov);
1879 cifs_small_buf_release(pSMB);
1880 cifs_stats_inc(&tcon->stats.cifs_stats.num_reads);
1881 pSMBr = (READ_RSP *)rsp_iov.iov_base;
1882 if (rc) {
1883 cifs_dbg(VFS, "Send error in read = %d\n", rc);
1884 } else {
1885 int data_length = le16_to_cpu(pSMBr->DataLengthHigh);
1886 data_length = data_length << 16;
1887 data_length += le16_to_cpu(pSMBr->DataLength);
1888 *nbytes = data_length;
1890 /*check that DataLength would not go beyond end of SMB */
1891 if ((data_length > CIFSMaxBufSize)
1892 || (data_length > count)) {
1893 cifs_dbg(FYI, "bad length %d for count %d\n",
1894 data_length, count);
1895 rc = -EIO;
1896 *nbytes = 0;
1897 } else {
1898 pReadData = (char *) (&pSMBr->hdr.Protocol) +
1899 le16_to_cpu(pSMBr->DataOffset);
1900 /* if (rc = copy_to_user(buf, pReadData, data_length)) {
1901 cifs_dbg(VFS, "Faulting on read rc = %d\n",rc);
1902 rc = -EFAULT;
1903 }*/ /* can not use copy_to_user when using page cache*/
1904 if (*buf)
1905 memcpy(*buf, pReadData, data_length);
1909 if (*buf) {
1910 free_rsp_buf(resp_buf_type, rsp_iov.iov_base);
1911 } else if (resp_buf_type != CIFS_NO_BUFFER) {
1912 /* return buffer to caller to free */
1913 *buf = rsp_iov.iov_base;
1914 if (resp_buf_type == CIFS_SMALL_BUFFER)
1915 *pbuf_type = CIFS_SMALL_BUFFER;
1916 else if (resp_buf_type == CIFS_LARGE_BUFFER)
1917 *pbuf_type = CIFS_LARGE_BUFFER;
1918 } /* else no valid buffer on return - leave as null */
1920 /* Note: On -EAGAIN error only caller can retry on handle based calls
1921 since file handle passed in no longer valid */
1922 return rc;
1927 CIFSSMBWrite(const unsigned int xid, struct cifs_io_parms *io_parms,
1928 unsigned int *nbytes, const char *buf)
1930 int rc = -EACCES;
1931 WRITE_REQ *pSMB = NULL;
1932 WRITE_RSP *pSMBr = NULL;
1933 int bytes_returned, wct;
1934 __u32 bytes_sent;
1935 __u16 byte_count;
1936 __u32 pid = io_parms->pid;
1937 __u16 netfid = io_parms->netfid;
1938 __u64 offset = io_parms->offset;
1939 struct cifs_tcon *tcon = io_parms->tcon;
1940 unsigned int count = io_parms->length;
1942 *nbytes = 0;
1944 /* cifs_dbg(FYI, "write at %lld %d bytes\n", offset, count);*/
1945 if (tcon->ses == NULL)
1946 return -ECONNABORTED;
1948 if (tcon->ses->capabilities & CAP_LARGE_FILES)
1949 wct = 14;
1950 else {
1951 wct = 12;
1952 if ((offset >> 32) > 0) {
1953 /* can not handle big offset for old srv */
1954 return -EIO;
1958 rc = smb_init(SMB_COM_WRITE_ANDX, wct, tcon, (void **) &pSMB,
1959 (void **) &pSMBr);
1960 if (rc)
1961 return rc;
1963 pSMB->hdr.Pid = cpu_to_le16((__u16)pid);
1964 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid >> 16));
1966 /* tcon and ses pointer are checked in smb_init */
1967 if (tcon->ses->server == NULL)
1968 return -ECONNABORTED;
1970 pSMB->AndXCommand = 0xFF; /* none */
1971 pSMB->Fid = netfid;
1972 pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF);
1973 if (wct == 14)
1974 pSMB->OffsetHigh = cpu_to_le32(offset >> 32);
1976 pSMB->Reserved = 0xFFFFFFFF;
1977 pSMB->WriteMode = 0;
1978 pSMB->Remaining = 0;
1980 /* Can increase buffer size if buffer is big enough in some cases ie we
1981 can send more if LARGE_WRITE_X capability returned by the server and if
1982 our buffer is big enough or if we convert to iovecs on socket writes
1983 and eliminate the copy to the CIFS buffer */
1984 if (tcon->ses->capabilities & CAP_LARGE_WRITE_X) {
1985 bytes_sent = min_t(const unsigned int, CIFSMaxBufSize, count);
1986 } else {
1987 bytes_sent = (tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE)
1988 & ~0xFF;
1991 if (bytes_sent > count)
1992 bytes_sent = count;
1993 pSMB->DataOffset =
1994 cpu_to_le16(offsetof(struct smb_com_write_req, Data) - 4);
1995 if (buf)
1996 memcpy(pSMB->Data, buf, bytes_sent);
1997 else if (count != 0) {
1998 /* No buffer */
1999 cifs_buf_release(pSMB);
2000 return -EINVAL;
2001 } /* else setting file size with write of zero bytes */
2002 if (wct == 14)
2003 byte_count = bytes_sent + 1; /* pad */
2004 else /* wct == 12 */
2005 byte_count = bytes_sent + 5; /* bigger pad, smaller smb hdr */
2007 pSMB->DataLengthLow = cpu_to_le16(bytes_sent & 0xFFFF);
2008 pSMB->DataLengthHigh = cpu_to_le16(bytes_sent >> 16);
2009 inc_rfc1001_len(pSMB, byte_count);
2011 if (wct == 14)
2012 pSMB->ByteCount = cpu_to_le16(byte_count);
2013 else { /* old style write has byte count 4 bytes earlier
2014 so 4 bytes pad */
2015 struct smb_com_writex_req *pSMBW =
2016 (struct smb_com_writex_req *)pSMB;
2017 pSMBW->ByteCount = cpu_to_le16(byte_count);
2020 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2021 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2022 cifs_stats_inc(&tcon->stats.cifs_stats.num_writes);
2023 if (rc) {
2024 cifs_dbg(FYI, "Send error in write = %d\n", rc);
2025 } else {
2026 *nbytes = le16_to_cpu(pSMBr->CountHigh);
2027 *nbytes = (*nbytes) << 16;
2028 *nbytes += le16_to_cpu(pSMBr->Count);
2031 * Mask off high 16 bits when bytes written as returned by the
2032 * server is greater than bytes requested by the client. Some
2033 * OS/2 servers are known to set incorrect CountHigh values.
2035 if (*nbytes > count)
2036 *nbytes &= 0xFFFF;
2039 cifs_buf_release(pSMB);
2041 /* Note: On -EAGAIN error only caller can retry on handle based calls
2042 since file handle passed in no longer valid */
2044 return rc;
2047 void
2048 cifs_writedata_release(struct kref *refcount)
2050 struct cifs_writedata *wdata = container_of(refcount,
2051 struct cifs_writedata, refcount);
2052 #ifdef CONFIG_CIFS_SMB_DIRECT
2053 if (wdata->mr) {
2054 smbd_deregister_mr(wdata->mr);
2055 wdata->mr = NULL;
2057 #endif
2059 if (wdata->cfile)
2060 cifsFileInfo_put(wdata->cfile);
2062 kvfree(wdata->pages);
2063 kfree(wdata);
2067 * Write failed with a retryable error. Resend the write request. It's also
2068 * possible that the page was redirtied so re-clean the page.
2070 static void
2071 cifs_writev_requeue(struct cifs_writedata *wdata)
2073 int i, rc = 0;
2074 struct inode *inode = d_inode(wdata->cfile->dentry);
2075 struct TCP_Server_Info *server;
2076 unsigned int rest_len;
2078 server = tlink_tcon(wdata->cfile->tlink)->ses->server;
2079 i = 0;
2080 rest_len = wdata->bytes;
2081 do {
2082 struct cifs_writedata *wdata2;
2083 unsigned int j, nr_pages, wsize, tailsz, cur_len;
2085 wsize = server->ops->wp_retry_size(inode);
2086 if (wsize < rest_len) {
2087 nr_pages = wsize / PAGE_SIZE;
2088 if (!nr_pages) {
2089 rc = -ENOTSUPP;
2090 break;
2092 cur_len = nr_pages * PAGE_SIZE;
2093 tailsz = PAGE_SIZE;
2094 } else {
2095 nr_pages = DIV_ROUND_UP(rest_len, PAGE_SIZE);
2096 cur_len = rest_len;
2097 tailsz = rest_len - (nr_pages - 1) * PAGE_SIZE;
2100 wdata2 = cifs_writedata_alloc(nr_pages, cifs_writev_complete);
2101 if (!wdata2) {
2102 rc = -ENOMEM;
2103 break;
2106 for (j = 0; j < nr_pages; j++) {
2107 wdata2->pages[j] = wdata->pages[i + j];
2108 lock_page(wdata2->pages[j]);
2109 clear_page_dirty_for_io(wdata2->pages[j]);
2112 wdata2->sync_mode = wdata->sync_mode;
2113 wdata2->nr_pages = nr_pages;
2114 wdata2->offset = page_offset(wdata2->pages[0]);
2115 wdata2->pagesz = PAGE_SIZE;
2116 wdata2->tailsz = tailsz;
2117 wdata2->bytes = cur_len;
2119 rc = cifs_get_writable_file(CIFS_I(inode), FIND_WR_ANY,
2120 &wdata2->cfile);
2121 if (!wdata2->cfile) {
2122 cifs_dbg(VFS, "No writable handle to retry writepages rc=%d\n",
2123 rc);
2124 if (!is_retryable_error(rc))
2125 rc = -EBADF;
2126 } else {
2127 wdata2->pid = wdata2->cfile->pid;
2128 rc = server->ops->async_writev(wdata2,
2129 cifs_writedata_release);
2132 for (j = 0; j < nr_pages; j++) {
2133 unlock_page(wdata2->pages[j]);
2134 if (rc != 0 && !is_retryable_error(rc)) {
2135 SetPageError(wdata2->pages[j]);
2136 end_page_writeback(wdata2->pages[j]);
2137 put_page(wdata2->pages[j]);
2141 if (rc) {
2142 kref_put(&wdata2->refcount, cifs_writedata_release);
2143 if (is_retryable_error(rc))
2144 continue;
2145 i += nr_pages;
2146 break;
2149 rest_len -= cur_len;
2150 i += nr_pages;
2151 } while (i < wdata->nr_pages);
2153 /* cleanup remaining pages from the original wdata */
2154 for (; i < wdata->nr_pages; i++) {
2155 SetPageError(wdata->pages[i]);
2156 end_page_writeback(wdata->pages[i]);
2157 put_page(wdata->pages[i]);
2160 if (rc != 0 && !is_retryable_error(rc))
2161 mapping_set_error(inode->i_mapping, rc);
2162 kref_put(&wdata->refcount, cifs_writedata_release);
2165 void
2166 cifs_writev_complete(struct work_struct *work)
2168 struct cifs_writedata *wdata = container_of(work,
2169 struct cifs_writedata, work);
2170 struct inode *inode = d_inode(wdata->cfile->dentry);
2171 int i = 0;
2173 if (wdata->result == 0) {
2174 spin_lock(&inode->i_lock);
2175 cifs_update_eof(CIFS_I(inode), wdata->offset, wdata->bytes);
2176 spin_unlock(&inode->i_lock);
2177 cifs_stats_bytes_written(tlink_tcon(wdata->cfile->tlink),
2178 wdata->bytes);
2179 } else if (wdata->sync_mode == WB_SYNC_ALL && wdata->result == -EAGAIN)
2180 return cifs_writev_requeue(wdata);
2182 for (i = 0; i < wdata->nr_pages; i++) {
2183 struct page *page = wdata->pages[i];
2184 if (wdata->result == -EAGAIN)
2185 __set_page_dirty_nobuffers(page);
2186 else if (wdata->result < 0)
2187 SetPageError(page);
2188 end_page_writeback(page);
2189 put_page(page);
2191 if (wdata->result != -EAGAIN)
2192 mapping_set_error(inode->i_mapping, wdata->result);
2193 kref_put(&wdata->refcount, cifs_writedata_release);
2196 struct cifs_writedata *
2197 cifs_writedata_alloc(unsigned int nr_pages, work_func_t complete)
2199 struct page **pages =
2200 kcalloc(nr_pages, sizeof(struct page *), GFP_NOFS);
2201 if (pages)
2202 return cifs_writedata_direct_alloc(pages, complete);
2204 return NULL;
2207 struct cifs_writedata *
2208 cifs_writedata_direct_alloc(struct page **pages, work_func_t complete)
2210 struct cifs_writedata *wdata;
2212 wdata = kzalloc(sizeof(*wdata), GFP_NOFS);
2213 if (wdata != NULL) {
2214 wdata->pages = pages;
2215 kref_init(&wdata->refcount);
2216 INIT_LIST_HEAD(&wdata->list);
2217 init_completion(&wdata->done);
2218 INIT_WORK(&wdata->work, complete);
2220 return wdata;
2224 * Check the mid_state and signature on received buffer (if any), and queue the
2225 * workqueue completion task.
2227 static void
2228 cifs_writev_callback(struct mid_q_entry *mid)
2230 struct cifs_writedata *wdata = mid->callback_data;
2231 struct cifs_tcon *tcon = tlink_tcon(wdata->cfile->tlink);
2232 unsigned int written;
2233 WRITE_RSP *smb = (WRITE_RSP *)mid->resp_buf;
2234 struct cifs_credits credits = { .value = 1, .instance = 0 };
2236 switch (mid->mid_state) {
2237 case MID_RESPONSE_RECEIVED:
2238 wdata->result = cifs_check_receive(mid, tcon->ses->server, 0);
2239 if (wdata->result != 0)
2240 break;
2242 written = le16_to_cpu(smb->CountHigh);
2243 written <<= 16;
2244 written += le16_to_cpu(smb->Count);
2246 * Mask off high 16 bits when bytes written as returned
2247 * by the server is greater than bytes requested by the
2248 * client. OS/2 servers are known to set incorrect
2249 * CountHigh values.
2251 if (written > wdata->bytes)
2252 written &= 0xFFFF;
2254 if (written < wdata->bytes)
2255 wdata->result = -ENOSPC;
2256 else
2257 wdata->bytes = written;
2258 break;
2259 case MID_REQUEST_SUBMITTED:
2260 case MID_RETRY_NEEDED:
2261 wdata->result = -EAGAIN;
2262 break;
2263 default:
2264 wdata->result = -EIO;
2265 break;
2268 queue_work(cifsiod_wq, &wdata->work);
2269 DeleteMidQEntry(mid);
2270 add_credits(tcon->ses->server, &credits, 0);
2273 /* cifs_async_writev - send an async write, and set up mid to handle result */
2275 cifs_async_writev(struct cifs_writedata *wdata,
2276 void (*release)(struct kref *kref))
2278 int rc = -EACCES;
2279 WRITE_REQ *smb = NULL;
2280 int wct;
2281 struct cifs_tcon *tcon = tlink_tcon(wdata->cfile->tlink);
2282 struct kvec iov[2];
2283 struct smb_rqst rqst = { };
2285 if (tcon->ses->capabilities & CAP_LARGE_FILES) {
2286 wct = 14;
2287 } else {
2288 wct = 12;
2289 if (wdata->offset >> 32 > 0) {
2290 /* can not handle big offset for old srv */
2291 return -EIO;
2295 rc = small_smb_init(SMB_COM_WRITE_ANDX, wct, tcon, (void **)&smb);
2296 if (rc)
2297 goto async_writev_out;
2299 smb->hdr.Pid = cpu_to_le16((__u16)wdata->pid);
2300 smb->hdr.PidHigh = cpu_to_le16((__u16)(wdata->pid >> 16));
2302 smb->AndXCommand = 0xFF; /* none */
2303 smb->Fid = wdata->cfile->fid.netfid;
2304 smb->OffsetLow = cpu_to_le32(wdata->offset & 0xFFFFFFFF);
2305 if (wct == 14)
2306 smb->OffsetHigh = cpu_to_le32(wdata->offset >> 32);
2307 smb->Reserved = 0xFFFFFFFF;
2308 smb->WriteMode = 0;
2309 smb->Remaining = 0;
2311 smb->DataOffset =
2312 cpu_to_le16(offsetof(struct smb_com_write_req, Data) - 4);
2314 /* 4 for RFC1001 length + 1 for BCC */
2315 iov[0].iov_len = 4;
2316 iov[0].iov_base = smb;
2317 iov[1].iov_len = get_rfc1002_length(smb) + 1;
2318 iov[1].iov_base = (char *)smb + 4;
2320 rqst.rq_iov = iov;
2321 rqst.rq_nvec = 2;
2322 rqst.rq_pages = wdata->pages;
2323 rqst.rq_offset = wdata->page_offset;
2324 rqst.rq_npages = wdata->nr_pages;
2325 rqst.rq_pagesz = wdata->pagesz;
2326 rqst.rq_tailsz = wdata->tailsz;
2328 cifs_dbg(FYI, "async write at %llu %u bytes\n",
2329 wdata->offset, wdata->bytes);
2331 smb->DataLengthLow = cpu_to_le16(wdata->bytes & 0xFFFF);
2332 smb->DataLengthHigh = cpu_to_le16(wdata->bytes >> 16);
2334 if (wct == 14) {
2335 inc_rfc1001_len(&smb->hdr, wdata->bytes + 1);
2336 put_bcc(wdata->bytes + 1, &smb->hdr);
2337 } else {
2338 /* wct == 12 */
2339 struct smb_com_writex_req *smbw =
2340 (struct smb_com_writex_req *)smb;
2341 inc_rfc1001_len(&smbw->hdr, wdata->bytes + 5);
2342 put_bcc(wdata->bytes + 5, &smbw->hdr);
2343 iov[1].iov_len += 4; /* pad bigger by four bytes */
2346 kref_get(&wdata->refcount);
2347 rc = cifs_call_async(tcon->ses->server, &rqst, NULL,
2348 cifs_writev_callback, NULL, wdata, 0, NULL);
2350 if (rc == 0)
2351 cifs_stats_inc(&tcon->stats.cifs_stats.num_writes);
2352 else
2353 kref_put(&wdata->refcount, release);
2355 async_writev_out:
2356 cifs_small_buf_release(smb);
2357 return rc;
2361 CIFSSMBWrite2(const unsigned int xid, struct cifs_io_parms *io_parms,
2362 unsigned int *nbytes, struct kvec *iov, int n_vec)
2364 int rc = -EACCES;
2365 WRITE_REQ *pSMB = NULL;
2366 int wct;
2367 int smb_hdr_len;
2368 int resp_buf_type = 0;
2369 __u32 pid = io_parms->pid;
2370 __u16 netfid = io_parms->netfid;
2371 __u64 offset = io_parms->offset;
2372 struct cifs_tcon *tcon = io_parms->tcon;
2373 unsigned int count = io_parms->length;
2374 struct kvec rsp_iov;
2376 *nbytes = 0;
2378 cifs_dbg(FYI, "write2 at %lld %d bytes\n", (long long)offset, count);
2380 if (tcon->ses->capabilities & CAP_LARGE_FILES) {
2381 wct = 14;
2382 } else {
2383 wct = 12;
2384 if ((offset >> 32) > 0) {
2385 /* can not handle big offset for old srv */
2386 return -EIO;
2389 rc = small_smb_init(SMB_COM_WRITE_ANDX, wct, tcon, (void **) &pSMB);
2390 if (rc)
2391 return rc;
2393 pSMB->hdr.Pid = cpu_to_le16((__u16)pid);
2394 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid >> 16));
2396 /* tcon and ses pointer are checked in smb_init */
2397 if (tcon->ses->server == NULL)
2398 return -ECONNABORTED;
2400 pSMB->AndXCommand = 0xFF; /* none */
2401 pSMB->Fid = netfid;
2402 pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF);
2403 if (wct == 14)
2404 pSMB->OffsetHigh = cpu_to_le32(offset >> 32);
2405 pSMB->Reserved = 0xFFFFFFFF;
2406 pSMB->WriteMode = 0;
2407 pSMB->Remaining = 0;
2409 pSMB->DataOffset =
2410 cpu_to_le16(offsetof(struct smb_com_write_req, Data) - 4);
2412 pSMB->DataLengthLow = cpu_to_le16(count & 0xFFFF);
2413 pSMB->DataLengthHigh = cpu_to_le16(count >> 16);
2414 /* header + 1 byte pad */
2415 smb_hdr_len = be32_to_cpu(pSMB->hdr.smb_buf_length) + 1;
2416 if (wct == 14)
2417 inc_rfc1001_len(pSMB, count + 1);
2418 else /* wct == 12 */
2419 inc_rfc1001_len(pSMB, count + 5); /* smb data starts later */
2420 if (wct == 14)
2421 pSMB->ByteCount = cpu_to_le16(count + 1);
2422 else /* wct == 12 */ /* bigger pad, smaller smb hdr, keep offset ok */ {
2423 struct smb_com_writex_req *pSMBW =
2424 (struct smb_com_writex_req *)pSMB;
2425 pSMBW->ByteCount = cpu_to_le16(count + 5);
2427 iov[0].iov_base = pSMB;
2428 if (wct == 14)
2429 iov[0].iov_len = smb_hdr_len + 4;
2430 else /* wct == 12 pad bigger by four bytes */
2431 iov[0].iov_len = smb_hdr_len + 8;
2433 rc = SendReceive2(xid, tcon->ses, iov, n_vec + 1, &resp_buf_type, 0,
2434 &rsp_iov);
2435 cifs_small_buf_release(pSMB);
2436 cifs_stats_inc(&tcon->stats.cifs_stats.num_writes);
2437 if (rc) {
2438 cifs_dbg(FYI, "Send error Write2 = %d\n", rc);
2439 } else if (resp_buf_type == 0) {
2440 /* presumably this can not happen, but best to be safe */
2441 rc = -EIO;
2442 } else {
2443 WRITE_RSP *pSMBr = (WRITE_RSP *)rsp_iov.iov_base;
2444 *nbytes = le16_to_cpu(pSMBr->CountHigh);
2445 *nbytes = (*nbytes) << 16;
2446 *nbytes += le16_to_cpu(pSMBr->Count);
2449 * Mask off high 16 bits when bytes written as returned by the
2450 * server is greater than bytes requested by the client. OS/2
2451 * servers are known to set incorrect CountHigh values.
2453 if (*nbytes > count)
2454 *nbytes &= 0xFFFF;
2457 free_rsp_buf(resp_buf_type, rsp_iov.iov_base);
2459 /* Note: On -EAGAIN error only caller can retry on handle based calls
2460 since file handle passed in no longer valid */
2462 return rc;
2465 int cifs_lockv(const unsigned int xid, struct cifs_tcon *tcon,
2466 const __u16 netfid, const __u8 lock_type, const __u32 num_unlock,
2467 const __u32 num_lock, LOCKING_ANDX_RANGE *buf)
2469 int rc = 0;
2470 LOCK_REQ *pSMB = NULL;
2471 struct kvec iov[2];
2472 struct kvec rsp_iov;
2473 int resp_buf_type;
2474 __u16 count;
2476 cifs_dbg(FYI, "cifs_lockv num lock %d num unlock %d\n",
2477 num_lock, num_unlock);
2479 rc = small_smb_init(SMB_COM_LOCKING_ANDX, 8, tcon, (void **) &pSMB);
2480 if (rc)
2481 return rc;
2483 pSMB->Timeout = 0;
2484 pSMB->NumberOfLocks = cpu_to_le16(num_lock);
2485 pSMB->NumberOfUnlocks = cpu_to_le16(num_unlock);
2486 pSMB->LockType = lock_type;
2487 pSMB->AndXCommand = 0xFF; /* none */
2488 pSMB->Fid = netfid; /* netfid stays le */
2490 count = (num_unlock + num_lock) * sizeof(LOCKING_ANDX_RANGE);
2491 inc_rfc1001_len(pSMB, count);
2492 pSMB->ByteCount = cpu_to_le16(count);
2494 iov[0].iov_base = (char *)pSMB;
2495 iov[0].iov_len = be32_to_cpu(pSMB->hdr.smb_buf_length) + 4 -
2496 (num_unlock + num_lock) * sizeof(LOCKING_ANDX_RANGE);
2497 iov[1].iov_base = (char *)buf;
2498 iov[1].iov_len = (num_unlock + num_lock) * sizeof(LOCKING_ANDX_RANGE);
2500 cifs_stats_inc(&tcon->stats.cifs_stats.num_locks);
2501 rc = SendReceive2(xid, tcon->ses, iov, 2, &resp_buf_type,
2502 CIFS_NO_RSP_BUF, &rsp_iov);
2503 cifs_small_buf_release(pSMB);
2504 if (rc)
2505 cifs_dbg(FYI, "Send error in cifs_lockv = %d\n", rc);
2507 return rc;
2511 CIFSSMBLock(const unsigned int xid, struct cifs_tcon *tcon,
2512 const __u16 smb_file_id, const __u32 netpid, const __u64 len,
2513 const __u64 offset, const __u32 numUnlock,
2514 const __u32 numLock, const __u8 lockType,
2515 const bool waitFlag, const __u8 oplock_level)
2517 int rc = 0;
2518 LOCK_REQ *pSMB = NULL;
2519 /* LOCK_RSP *pSMBr = NULL; */ /* No response data other than rc to parse */
2520 int bytes_returned;
2521 int flags = 0;
2522 __u16 count;
2524 cifs_dbg(FYI, "CIFSSMBLock timeout %d numLock %d\n",
2525 (int)waitFlag, numLock);
2526 rc = small_smb_init(SMB_COM_LOCKING_ANDX, 8, tcon, (void **) &pSMB);
2528 if (rc)
2529 return rc;
2531 if (lockType == LOCKING_ANDX_OPLOCK_RELEASE) {
2532 /* no response expected */
2533 flags = CIFS_NO_SRV_RSP | CIFS_NON_BLOCKING | CIFS_OBREAK_OP;
2534 pSMB->Timeout = 0;
2535 } else if (waitFlag) {
2536 flags = CIFS_BLOCKING_OP; /* blocking operation, no timeout */
2537 pSMB->Timeout = cpu_to_le32(-1);/* blocking - do not time out */
2538 } else {
2539 pSMB->Timeout = 0;
2542 pSMB->NumberOfLocks = cpu_to_le16(numLock);
2543 pSMB->NumberOfUnlocks = cpu_to_le16(numUnlock);
2544 pSMB->LockType = lockType;
2545 pSMB->OplockLevel = oplock_level;
2546 pSMB->AndXCommand = 0xFF; /* none */
2547 pSMB->Fid = smb_file_id; /* netfid stays le */
2549 if ((numLock != 0) || (numUnlock != 0)) {
2550 pSMB->Locks[0].Pid = cpu_to_le16(netpid);
2551 /* BB where to store pid high? */
2552 pSMB->Locks[0].LengthLow = cpu_to_le32((u32)len);
2553 pSMB->Locks[0].LengthHigh = cpu_to_le32((u32)(len>>32));
2554 pSMB->Locks[0].OffsetLow = cpu_to_le32((u32)offset);
2555 pSMB->Locks[0].OffsetHigh = cpu_to_le32((u32)(offset>>32));
2556 count = sizeof(LOCKING_ANDX_RANGE);
2557 } else {
2558 /* oplock break */
2559 count = 0;
2561 inc_rfc1001_len(pSMB, count);
2562 pSMB->ByteCount = cpu_to_le16(count);
2564 if (waitFlag)
2565 rc = SendReceiveBlockingLock(xid, tcon, (struct smb_hdr *) pSMB,
2566 (struct smb_hdr *) pSMB, &bytes_returned);
2567 else
2568 rc = SendReceiveNoRsp(xid, tcon->ses, (char *)pSMB, flags);
2569 cifs_small_buf_release(pSMB);
2570 cifs_stats_inc(&tcon->stats.cifs_stats.num_locks);
2571 if (rc)
2572 cifs_dbg(FYI, "Send error in Lock = %d\n", rc);
2574 /* Note: On -EAGAIN error only caller can retry on handle based calls
2575 since file handle passed in no longer valid */
2576 return rc;
2580 CIFSSMBPosixLock(const unsigned int xid, struct cifs_tcon *tcon,
2581 const __u16 smb_file_id, const __u32 netpid,
2582 const loff_t start_offset, const __u64 len,
2583 struct file_lock *pLockData, const __u16 lock_type,
2584 const bool waitFlag)
2586 struct smb_com_transaction2_sfi_req *pSMB = NULL;
2587 struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
2588 struct cifs_posix_lock *parm_data;
2589 int rc = 0;
2590 int timeout = 0;
2591 int bytes_returned = 0;
2592 int resp_buf_type = 0;
2593 __u16 params, param_offset, offset, byte_count, count;
2594 struct kvec iov[1];
2595 struct kvec rsp_iov;
2597 cifs_dbg(FYI, "Posix Lock\n");
2599 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
2601 if (rc)
2602 return rc;
2604 pSMBr = (struct smb_com_transaction2_sfi_rsp *)pSMB;
2606 params = 6;
2607 pSMB->MaxSetupCount = 0;
2608 pSMB->Reserved = 0;
2609 pSMB->Flags = 0;
2610 pSMB->Reserved2 = 0;
2611 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
2612 offset = param_offset + params;
2614 count = sizeof(struct cifs_posix_lock);
2615 pSMB->MaxParameterCount = cpu_to_le16(2);
2616 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB from sess */
2617 pSMB->SetupCount = 1;
2618 pSMB->Reserved3 = 0;
2619 if (pLockData)
2620 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION);
2621 else
2622 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
2623 byte_count = 3 /* pad */ + params + count;
2624 pSMB->DataCount = cpu_to_le16(count);
2625 pSMB->ParameterCount = cpu_to_le16(params);
2626 pSMB->TotalDataCount = pSMB->DataCount;
2627 pSMB->TotalParameterCount = pSMB->ParameterCount;
2628 pSMB->ParameterOffset = cpu_to_le16(param_offset);
2629 parm_data = (struct cifs_posix_lock *)
2630 (((char *) &pSMB->hdr.Protocol) + offset);
2632 parm_data->lock_type = cpu_to_le16(lock_type);
2633 if (waitFlag) {
2634 timeout = CIFS_BLOCKING_OP; /* blocking operation, no timeout */
2635 parm_data->lock_flags = cpu_to_le16(1);
2636 pSMB->Timeout = cpu_to_le32(-1);
2637 } else
2638 pSMB->Timeout = 0;
2640 parm_data->pid = cpu_to_le32(netpid);
2641 parm_data->start = cpu_to_le64(start_offset);
2642 parm_data->length = cpu_to_le64(len); /* normalize negative numbers */
2644 pSMB->DataOffset = cpu_to_le16(offset);
2645 pSMB->Fid = smb_file_id;
2646 pSMB->InformationLevel = cpu_to_le16(SMB_SET_POSIX_LOCK);
2647 pSMB->Reserved4 = 0;
2648 inc_rfc1001_len(pSMB, byte_count);
2649 pSMB->ByteCount = cpu_to_le16(byte_count);
2650 if (waitFlag) {
2651 rc = SendReceiveBlockingLock(xid, tcon, (struct smb_hdr *) pSMB,
2652 (struct smb_hdr *) pSMBr, &bytes_returned);
2653 } else {
2654 iov[0].iov_base = (char *)pSMB;
2655 iov[0].iov_len = be32_to_cpu(pSMB->hdr.smb_buf_length) + 4;
2656 rc = SendReceive2(xid, tcon->ses, iov, 1 /* num iovecs */,
2657 &resp_buf_type, timeout, &rsp_iov);
2658 pSMBr = (struct smb_com_transaction2_sfi_rsp *)rsp_iov.iov_base;
2660 cifs_small_buf_release(pSMB);
2662 if (rc) {
2663 cifs_dbg(FYI, "Send error in Posix Lock = %d\n", rc);
2664 } else if (pLockData) {
2665 /* lock structure can be returned on get */
2666 __u16 data_offset;
2667 __u16 data_count;
2668 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
2670 if (rc || get_bcc(&pSMBr->hdr) < sizeof(*parm_data)) {
2671 rc = -EIO; /* bad smb */
2672 goto plk_err_exit;
2674 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
2675 data_count = le16_to_cpu(pSMBr->t2.DataCount);
2676 if (data_count < sizeof(struct cifs_posix_lock)) {
2677 rc = -EIO;
2678 goto plk_err_exit;
2680 parm_data = (struct cifs_posix_lock *)
2681 ((char *)&pSMBr->hdr.Protocol + data_offset);
2682 if (parm_data->lock_type == cpu_to_le16(CIFS_UNLCK))
2683 pLockData->fl_type = F_UNLCK;
2684 else {
2685 if (parm_data->lock_type ==
2686 cpu_to_le16(CIFS_RDLCK))
2687 pLockData->fl_type = F_RDLCK;
2688 else if (parm_data->lock_type ==
2689 cpu_to_le16(CIFS_WRLCK))
2690 pLockData->fl_type = F_WRLCK;
2692 pLockData->fl_start = le64_to_cpu(parm_data->start);
2693 pLockData->fl_end = pLockData->fl_start +
2694 le64_to_cpu(parm_data->length) - 1;
2695 pLockData->fl_pid = -le32_to_cpu(parm_data->pid);
2699 plk_err_exit:
2700 free_rsp_buf(resp_buf_type, rsp_iov.iov_base);
2702 /* Note: On -EAGAIN error only caller can retry on handle based calls
2703 since file handle passed in no longer valid */
2705 return rc;
2710 CIFSSMBClose(const unsigned int xid, struct cifs_tcon *tcon, int smb_file_id)
2712 int rc = 0;
2713 CLOSE_REQ *pSMB = NULL;
2714 cifs_dbg(FYI, "In CIFSSMBClose\n");
2716 /* do not retry on dead session on close */
2717 rc = small_smb_init(SMB_COM_CLOSE, 3, tcon, (void **) &pSMB);
2718 if (rc == -EAGAIN)
2719 return 0;
2720 if (rc)
2721 return rc;
2723 pSMB->FileID = (__u16) smb_file_id;
2724 pSMB->LastWriteTime = 0xFFFFFFFF;
2725 pSMB->ByteCount = 0;
2726 rc = SendReceiveNoRsp(xid, tcon->ses, (char *) pSMB, 0);
2727 cifs_small_buf_release(pSMB);
2728 cifs_stats_inc(&tcon->stats.cifs_stats.num_closes);
2729 if (rc) {
2730 if (rc != -EINTR) {
2731 /* EINTR is expected when user ctl-c to kill app */
2732 cifs_dbg(VFS, "Send error in Close = %d\n", rc);
2736 /* Since session is dead, file will be closed on server already */
2737 if (rc == -EAGAIN)
2738 rc = 0;
2740 return rc;
2744 CIFSSMBFlush(const unsigned int xid, struct cifs_tcon *tcon, int smb_file_id)
2746 int rc = 0;
2747 FLUSH_REQ *pSMB = NULL;
2748 cifs_dbg(FYI, "In CIFSSMBFlush\n");
2750 rc = small_smb_init(SMB_COM_FLUSH, 1, tcon, (void **) &pSMB);
2751 if (rc)
2752 return rc;
2754 pSMB->FileID = (__u16) smb_file_id;
2755 pSMB->ByteCount = 0;
2756 rc = SendReceiveNoRsp(xid, tcon->ses, (char *) pSMB, 0);
2757 cifs_small_buf_release(pSMB);
2758 cifs_stats_inc(&tcon->stats.cifs_stats.num_flushes);
2759 if (rc)
2760 cifs_dbg(VFS, "Send error in Flush = %d\n", rc);
2762 return rc;
2766 CIFSSMBRename(const unsigned int xid, struct cifs_tcon *tcon,
2767 const char *from_name, const char *to_name,
2768 struct cifs_sb_info *cifs_sb)
2770 int rc = 0;
2771 RENAME_REQ *pSMB = NULL;
2772 RENAME_RSP *pSMBr = NULL;
2773 int bytes_returned;
2774 int name_len, name_len2;
2775 __u16 count;
2776 int remap = cifs_remap(cifs_sb);
2778 cifs_dbg(FYI, "In CIFSSMBRename\n");
2779 renameRetry:
2780 rc = smb_init(SMB_COM_RENAME, 1, tcon, (void **) &pSMB,
2781 (void **) &pSMBr);
2782 if (rc)
2783 return rc;
2785 pSMB->BufferFormat = 0x04;
2786 pSMB->SearchAttributes =
2787 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
2788 ATTR_DIRECTORY);
2790 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2791 name_len = cifsConvertToUTF16((__le16 *) pSMB->OldFileName,
2792 from_name, PATH_MAX,
2793 cifs_sb->local_nls, remap);
2794 name_len++; /* trailing null */
2795 name_len *= 2;
2796 pSMB->OldFileName[name_len] = 0x04; /* pad */
2797 /* protocol requires ASCII signature byte on Unicode string */
2798 pSMB->OldFileName[name_len + 1] = 0x00;
2799 name_len2 =
2800 cifsConvertToUTF16((__le16 *)&pSMB->OldFileName[name_len+2],
2801 to_name, PATH_MAX, cifs_sb->local_nls,
2802 remap);
2803 name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
2804 name_len2 *= 2; /* convert to bytes */
2805 } else {
2806 name_len = copy_path_name(pSMB->OldFileName, from_name);
2807 name_len2 = copy_path_name(pSMB->OldFileName+name_len+1, to_name);
2808 pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */
2809 name_len2++; /* signature byte */
2812 count = 1 /* 1st signature byte */ + name_len + name_len2;
2813 inc_rfc1001_len(pSMB, count);
2814 pSMB->ByteCount = cpu_to_le16(count);
2816 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2817 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2818 cifs_stats_inc(&tcon->stats.cifs_stats.num_renames);
2819 if (rc)
2820 cifs_dbg(FYI, "Send error in rename = %d\n", rc);
2822 cifs_buf_release(pSMB);
2824 if (rc == -EAGAIN)
2825 goto renameRetry;
2827 return rc;
2830 int CIFSSMBRenameOpenFile(const unsigned int xid, struct cifs_tcon *pTcon,
2831 int netfid, const char *target_name,
2832 const struct nls_table *nls_codepage, int remap)
2834 struct smb_com_transaction2_sfi_req *pSMB = NULL;
2835 struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
2836 struct set_file_rename *rename_info;
2837 char *data_offset;
2838 char dummy_string[30];
2839 int rc = 0;
2840 int bytes_returned = 0;
2841 int len_of_str;
2842 __u16 params, param_offset, offset, count, byte_count;
2844 cifs_dbg(FYI, "Rename to File by handle\n");
2845 rc = smb_init(SMB_COM_TRANSACTION2, 15, pTcon, (void **) &pSMB,
2846 (void **) &pSMBr);
2847 if (rc)
2848 return rc;
2850 params = 6;
2851 pSMB->MaxSetupCount = 0;
2852 pSMB->Reserved = 0;
2853 pSMB->Flags = 0;
2854 pSMB->Timeout = 0;
2855 pSMB->Reserved2 = 0;
2856 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
2857 offset = param_offset + params;
2859 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
2860 rename_info = (struct set_file_rename *) data_offset;
2861 pSMB->MaxParameterCount = cpu_to_le16(2);
2862 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB from sess */
2863 pSMB->SetupCount = 1;
2864 pSMB->Reserved3 = 0;
2865 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
2866 byte_count = 3 /* pad */ + params;
2867 pSMB->ParameterCount = cpu_to_le16(params);
2868 pSMB->TotalParameterCount = pSMB->ParameterCount;
2869 pSMB->ParameterOffset = cpu_to_le16(param_offset);
2870 pSMB->DataOffset = cpu_to_le16(offset);
2871 /* construct random name ".cifs_tmp<inodenum><mid>" */
2872 rename_info->overwrite = cpu_to_le32(1);
2873 rename_info->root_fid = 0;
2874 /* unicode only call */
2875 if (target_name == NULL) {
2876 sprintf(dummy_string, "cifs%x", pSMB->hdr.Mid);
2877 len_of_str =
2878 cifsConvertToUTF16((__le16 *)rename_info->target_name,
2879 dummy_string, 24, nls_codepage, remap);
2880 } else {
2881 len_of_str =
2882 cifsConvertToUTF16((__le16 *)rename_info->target_name,
2883 target_name, PATH_MAX, nls_codepage,
2884 remap);
2886 rename_info->target_name_len = cpu_to_le32(2 * len_of_str);
2887 count = 12 /* sizeof(struct set_file_rename) */ + (2 * len_of_str);
2888 byte_count += count;
2889 pSMB->DataCount = cpu_to_le16(count);
2890 pSMB->TotalDataCount = pSMB->DataCount;
2891 pSMB->Fid = netfid;
2892 pSMB->InformationLevel =
2893 cpu_to_le16(SMB_SET_FILE_RENAME_INFORMATION);
2894 pSMB->Reserved4 = 0;
2895 inc_rfc1001_len(pSMB, byte_count);
2896 pSMB->ByteCount = cpu_to_le16(byte_count);
2897 rc = SendReceive(xid, pTcon->ses, (struct smb_hdr *) pSMB,
2898 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2899 cifs_stats_inc(&pTcon->stats.cifs_stats.num_t2renames);
2900 if (rc)
2901 cifs_dbg(FYI, "Send error in Rename (by file handle) = %d\n",
2902 rc);
2904 cifs_buf_release(pSMB);
2906 /* Note: On -EAGAIN error only caller can retry on handle based calls
2907 since file handle passed in no longer valid */
2909 return rc;
2913 CIFSSMBCopy(const unsigned int xid, struct cifs_tcon *tcon,
2914 const char *fromName, const __u16 target_tid, const char *toName,
2915 const int flags, const struct nls_table *nls_codepage, int remap)
2917 int rc = 0;
2918 COPY_REQ *pSMB = NULL;
2919 COPY_RSP *pSMBr = NULL;
2920 int bytes_returned;
2921 int name_len, name_len2;
2922 __u16 count;
2924 cifs_dbg(FYI, "In CIFSSMBCopy\n");
2925 copyRetry:
2926 rc = smb_init(SMB_COM_COPY, 1, tcon, (void **) &pSMB,
2927 (void **) &pSMBr);
2928 if (rc)
2929 return rc;
2931 pSMB->BufferFormat = 0x04;
2932 pSMB->Tid2 = target_tid;
2934 pSMB->Flags = cpu_to_le16(flags & COPY_TREE);
2936 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2937 name_len = cifsConvertToUTF16((__le16 *) pSMB->OldFileName,
2938 fromName, PATH_MAX, nls_codepage,
2939 remap);
2940 name_len++; /* trailing null */
2941 name_len *= 2;
2942 pSMB->OldFileName[name_len] = 0x04; /* pad */
2943 /* protocol requires ASCII signature byte on Unicode string */
2944 pSMB->OldFileName[name_len + 1] = 0x00;
2945 name_len2 =
2946 cifsConvertToUTF16((__le16 *)&pSMB->OldFileName[name_len+2],
2947 toName, PATH_MAX, nls_codepage, remap);
2948 name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
2949 name_len2 *= 2; /* convert to bytes */
2950 } else {
2951 name_len = copy_path_name(pSMB->OldFileName, fromName);
2952 pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */
2953 name_len2 = copy_path_name(pSMB->OldFileName+name_len+1, toName);
2954 name_len2++; /* signature byte */
2957 count = 1 /* 1st signature byte */ + name_len + name_len2;
2958 inc_rfc1001_len(pSMB, count);
2959 pSMB->ByteCount = cpu_to_le16(count);
2961 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2962 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2963 if (rc) {
2964 cifs_dbg(FYI, "Send error in copy = %d with %d files copied\n",
2965 rc, le16_to_cpu(pSMBr->CopyCount));
2967 cifs_buf_release(pSMB);
2969 if (rc == -EAGAIN)
2970 goto copyRetry;
2972 return rc;
2976 CIFSUnixCreateSymLink(const unsigned int xid, struct cifs_tcon *tcon,
2977 const char *fromName, const char *toName,
2978 const struct nls_table *nls_codepage, int remap)
2980 TRANSACTION2_SPI_REQ *pSMB = NULL;
2981 TRANSACTION2_SPI_RSP *pSMBr = NULL;
2982 char *data_offset;
2983 int name_len;
2984 int name_len_target;
2985 int rc = 0;
2986 int bytes_returned = 0;
2987 __u16 params, param_offset, offset, byte_count;
2989 cifs_dbg(FYI, "In Symlink Unix style\n");
2990 createSymLinkRetry:
2991 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2992 (void **) &pSMBr);
2993 if (rc)
2994 return rc;
2996 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2997 name_len =
2998 cifsConvertToUTF16((__le16 *) pSMB->FileName, fromName,
2999 /* find define for this maxpathcomponent */
3000 PATH_MAX, nls_codepage, remap);
3001 name_len++; /* trailing null */
3002 name_len *= 2;
3004 } else {
3005 name_len = copy_path_name(pSMB->FileName, fromName);
3007 params = 6 + name_len;
3008 pSMB->MaxSetupCount = 0;
3009 pSMB->Reserved = 0;
3010 pSMB->Flags = 0;
3011 pSMB->Timeout = 0;
3012 pSMB->Reserved2 = 0;
3013 param_offset = offsetof(struct smb_com_transaction2_spi_req,
3014 InformationLevel) - 4;
3015 offset = param_offset + params;
3017 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
3018 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3019 name_len_target =
3020 cifsConvertToUTF16((__le16 *) data_offset, toName,
3021 /* find define for this maxpathcomponent */
3022 PATH_MAX, nls_codepage, remap);
3023 name_len_target++; /* trailing null */
3024 name_len_target *= 2;
3025 } else {
3026 name_len_target = copy_path_name(data_offset, toName);
3029 pSMB->MaxParameterCount = cpu_to_le16(2);
3030 /* BB find exact max on data count below from sess */
3031 pSMB->MaxDataCount = cpu_to_le16(1000);
3032 pSMB->SetupCount = 1;
3033 pSMB->Reserved3 = 0;
3034 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
3035 byte_count = 3 /* pad */ + params + name_len_target;
3036 pSMB->DataCount = cpu_to_le16(name_len_target);
3037 pSMB->ParameterCount = cpu_to_le16(params);
3038 pSMB->TotalDataCount = pSMB->DataCount;
3039 pSMB->TotalParameterCount = pSMB->ParameterCount;
3040 pSMB->ParameterOffset = cpu_to_le16(param_offset);
3041 pSMB->DataOffset = cpu_to_le16(offset);
3042 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_LINK);
3043 pSMB->Reserved4 = 0;
3044 inc_rfc1001_len(pSMB, byte_count);
3045 pSMB->ByteCount = cpu_to_le16(byte_count);
3046 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3047 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3048 cifs_stats_inc(&tcon->stats.cifs_stats.num_symlinks);
3049 if (rc)
3050 cifs_dbg(FYI, "Send error in SetPathInfo create symlink = %d\n",
3051 rc);
3053 cifs_buf_release(pSMB);
3055 if (rc == -EAGAIN)
3056 goto createSymLinkRetry;
3058 return rc;
3062 CIFSUnixCreateHardLink(const unsigned int xid, struct cifs_tcon *tcon,
3063 const char *fromName, const char *toName,
3064 const struct nls_table *nls_codepage, int remap)
3066 TRANSACTION2_SPI_REQ *pSMB = NULL;
3067 TRANSACTION2_SPI_RSP *pSMBr = NULL;
3068 char *data_offset;
3069 int name_len;
3070 int name_len_target;
3071 int rc = 0;
3072 int bytes_returned = 0;
3073 __u16 params, param_offset, offset, byte_count;
3075 cifs_dbg(FYI, "In Create Hard link Unix style\n");
3076 createHardLinkRetry:
3077 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3078 (void **) &pSMBr);
3079 if (rc)
3080 return rc;
3082 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3083 name_len = cifsConvertToUTF16((__le16 *) pSMB->FileName, toName,
3084 PATH_MAX, nls_codepage, remap);
3085 name_len++; /* trailing null */
3086 name_len *= 2;
3088 } else {
3089 name_len = copy_path_name(pSMB->FileName, toName);
3091 params = 6 + name_len;
3092 pSMB->MaxSetupCount = 0;
3093 pSMB->Reserved = 0;
3094 pSMB->Flags = 0;
3095 pSMB->Timeout = 0;
3096 pSMB->Reserved2 = 0;
3097 param_offset = offsetof(struct smb_com_transaction2_spi_req,
3098 InformationLevel) - 4;
3099 offset = param_offset + params;
3101 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
3102 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3103 name_len_target =
3104 cifsConvertToUTF16((__le16 *) data_offset, fromName,
3105 PATH_MAX, nls_codepage, remap);
3106 name_len_target++; /* trailing null */
3107 name_len_target *= 2;
3108 } else {
3109 name_len_target = copy_path_name(data_offset, fromName);
3112 pSMB->MaxParameterCount = cpu_to_le16(2);
3113 /* BB find exact max on data count below from sess*/
3114 pSMB->MaxDataCount = cpu_to_le16(1000);
3115 pSMB->SetupCount = 1;
3116 pSMB->Reserved3 = 0;
3117 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
3118 byte_count = 3 /* pad */ + params + name_len_target;
3119 pSMB->ParameterCount = cpu_to_le16(params);
3120 pSMB->TotalParameterCount = pSMB->ParameterCount;
3121 pSMB->DataCount = cpu_to_le16(name_len_target);
3122 pSMB->TotalDataCount = pSMB->DataCount;
3123 pSMB->ParameterOffset = cpu_to_le16(param_offset);
3124 pSMB->DataOffset = cpu_to_le16(offset);
3125 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_HLINK);
3126 pSMB->Reserved4 = 0;
3127 inc_rfc1001_len(pSMB, byte_count);
3128 pSMB->ByteCount = cpu_to_le16(byte_count);
3129 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3130 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3131 cifs_stats_inc(&tcon->stats.cifs_stats.num_hardlinks);
3132 if (rc)
3133 cifs_dbg(FYI, "Send error in SetPathInfo (hard link) = %d\n",
3134 rc);
3136 cifs_buf_release(pSMB);
3137 if (rc == -EAGAIN)
3138 goto createHardLinkRetry;
3140 return rc;
3144 CIFSCreateHardLink(const unsigned int xid, struct cifs_tcon *tcon,
3145 const char *from_name, const char *to_name,
3146 struct cifs_sb_info *cifs_sb)
3148 int rc = 0;
3149 NT_RENAME_REQ *pSMB = NULL;
3150 RENAME_RSP *pSMBr = NULL;
3151 int bytes_returned;
3152 int name_len, name_len2;
3153 __u16 count;
3154 int remap = cifs_remap(cifs_sb);
3156 cifs_dbg(FYI, "In CIFSCreateHardLink\n");
3157 winCreateHardLinkRetry:
3159 rc = smb_init(SMB_COM_NT_RENAME, 4, tcon, (void **) &pSMB,
3160 (void **) &pSMBr);
3161 if (rc)
3162 return rc;
3164 pSMB->SearchAttributes =
3165 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
3166 ATTR_DIRECTORY);
3167 pSMB->Flags = cpu_to_le16(CREATE_HARD_LINK);
3168 pSMB->ClusterCount = 0;
3170 pSMB->BufferFormat = 0x04;
3172 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3173 name_len =
3174 cifsConvertToUTF16((__le16 *) pSMB->OldFileName, from_name,
3175 PATH_MAX, cifs_sb->local_nls, remap);
3176 name_len++; /* trailing null */
3177 name_len *= 2;
3179 /* protocol specifies ASCII buffer format (0x04) for unicode */
3180 pSMB->OldFileName[name_len] = 0x04;
3181 pSMB->OldFileName[name_len + 1] = 0x00; /* pad */
3182 name_len2 =
3183 cifsConvertToUTF16((__le16 *)&pSMB->OldFileName[name_len+2],
3184 to_name, PATH_MAX, cifs_sb->local_nls,
3185 remap);
3186 name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
3187 name_len2 *= 2; /* convert to bytes */
3188 } else {
3189 name_len = copy_path_name(pSMB->OldFileName, from_name);
3190 pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */
3191 name_len2 = copy_path_name(pSMB->OldFileName+name_len+1, to_name);
3192 name_len2++; /* signature byte */
3195 count = 1 /* string type byte */ + name_len + name_len2;
3196 inc_rfc1001_len(pSMB, count);
3197 pSMB->ByteCount = cpu_to_le16(count);
3199 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3200 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3201 cifs_stats_inc(&tcon->stats.cifs_stats.num_hardlinks);
3202 if (rc)
3203 cifs_dbg(FYI, "Send error in hard link (NT rename) = %d\n", rc);
3205 cifs_buf_release(pSMB);
3206 if (rc == -EAGAIN)
3207 goto winCreateHardLinkRetry;
3209 return rc;
3213 CIFSSMBUnixQuerySymLink(const unsigned int xid, struct cifs_tcon *tcon,
3214 const unsigned char *searchName, char **symlinkinfo,
3215 const struct nls_table *nls_codepage, int remap)
3217 /* SMB_QUERY_FILE_UNIX_LINK */
3218 TRANSACTION2_QPI_REQ *pSMB = NULL;
3219 TRANSACTION2_QPI_RSP *pSMBr = NULL;
3220 int rc = 0;
3221 int bytes_returned;
3222 int name_len;
3223 __u16 params, byte_count;
3224 char *data_start;
3226 cifs_dbg(FYI, "In QPathSymLinkInfo (Unix) for path %s\n", searchName);
3228 querySymLinkRetry:
3229 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3230 (void **) &pSMBr);
3231 if (rc)
3232 return rc;
3234 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3235 name_len =
3236 cifsConvertToUTF16((__le16 *) pSMB->FileName,
3237 searchName, PATH_MAX, nls_codepage,
3238 remap);
3239 name_len++; /* trailing null */
3240 name_len *= 2;
3241 } else {
3242 name_len = copy_path_name(pSMB->FileName, searchName);
3245 params = 2 /* level */ + 4 /* rsrvd */ + name_len /* incl null */ ;
3246 pSMB->TotalDataCount = 0;
3247 pSMB->MaxParameterCount = cpu_to_le16(2);
3248 pSMB->MaxDataCount = cpu_to_le16(CIFSMaxBufSize);
3249 pSMB->MaxSetupCount = 0;
3250 pSMB->Reserved = 0;
3251 pSMB->Flags = 0;
3252 pSMB->Timeout = 0;
3253 pSMB->Reserved2 = 0;
3254 pSMB->ParameterOffset = cpu_to_le16(offsetof(
3255 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
3256 pSMB->DataCount = 0;
3257 pSMB->DataOffset = 0;
3258 pSMB->SetupCount = 1;
3259 pSMB->Reserved3 = 0;
3260 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
3261 byte_count = params + 1 /* pad */ ;
3262 pSMB->TotalParameterCount = cpu_to_le16(params);
3263 pSMB->ParameterCount = pSMB->TotalParameterCount;
3264 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_LINK);
3265 pSMB->Reserved4 = 0;
3266 inc_rfc1001_len(pSMB, byte_count);
3267 pSMB->ByteCount = cpu_to_le16(byte_count);
3269 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3270 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3271 if (rc) {
3272 cifs_dbg(FYI, "Send error in QuerySymLinkInfo = %d\n", rc);
3273 } else {
3274 /* decode response */
3276 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3277 /* BB also check enough total bytes returned */
3278 if (rc || get_bcc(&pSMBr->hdr) < 2)
3279 rc = -EIO;
3280 else {
3281 bool is_unicode;
3282 u16 count = le16_to_cpu(pSMBr->t2.DataCount);
3284 data_start = ((char *) &pSMBr->hdr.Protocol) +
3285 le16_to_cpu(pSMBr->t2.DataOffset);
3287 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
3288 is_unicode = true;
3289 else
3290 is_unicode = false;
3292 /* BB FIXME investigate remapping reserved chars here */
3293 *symlinkinfo = cifs_strndup_from_utf16(data_start,
3294 count, is_unicode, nls_codepage);
3295 if (!*symlinkinfo)
3296 rc = -ENOMEM;
3299 cifs_buf_release(pSMB);
3300 if (rc == -EAGAIN)
3301 goto querySymLinkRetry;
3302 return rc;
3306 * Recent Windows versions now create symlinks more frequently
3307 * and they use the "reparse point" mechanism below. We can of course
3308 * do symlinks nicely to Samba and other servers which support the
3309 * CIFS Unix Extensions and we can also do SFU symlinks and "client only"
3310 * "MF" symlinks optionally, but for recent Windows we really need to
3311 * reenable the code below and fix the cifs_symlink callers to handle this.
3312 * In the interim this code has been moved to its own config option so
3313 * it is not compiled in by default until callers fixed up and more tested.
3316 CIFSSMBQuerySymLink(const unsigned int xid, struct cifs_tcon *tcon,
3317 __u16 fid, char **symlinkinfo,
3318 const struct nls_table *nls_codepage)
3320 int rc = 0;
3321 int bytes_returned;
3322 struct smb_com_transaction_ioctl_req *pSMB;
3323 struct smb_com_transaction_ioctl_rsp *pSMBr;
3324 bool is_unicode;
3325 unsigned int sub_len;
3326 char *sub_start;
3327 struct reparse_symlink_data *reparse_buf;
3328 struct reparse_posix_data *posix_buf;
3329 __u32 data_offset, data_count;
3330 char *end_of_smb;
3332 cifs_dbg(FYI, "In Windows reparse style QueryLink for fid %u\n", fid);
3333 rc = smb_init(SMB_COM_NT_TRANSACT, 23, tcon, (void **) &pSMB,
3334 (void **) &pSMBr);
3335 if (rc)
3336 return rc;
3338 pSMB->TotalParameterCount = 0 ;
3339 pSMB->TotalDataCount = 0;
3340 pSMB->MaxParameterCount = cpu_to_le32(2);
3341 /* BB find exact data count max from sess structure BB */
3342 pSMB->MaxDataCount = cpu_to_le32(CIFSMaxBufSize & 0xFFFFFF00);
3343 pSMB->MaxSetupCount = 4;
3344 pSMB->Reserved = 0;
3345 pSMB->ParameterOffset = 0;
3346 pSMB->DataCount = 0;
3347 pSMB->DataOffset = 0;
3348 pSMB->SetupCount = 4;
3349 pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_IOCTL);
3350 pSMB->ParameterCount = pSMB->TotalParameterCount;
3351 pSMB->FunctionCode = cpu_to_le32(FSCTL_GET_REPARSE_POINT);
3352 pSMB->IsFsctl = 1; /* FSCTL */
3353 pSMB->IsRootFlag = 0;
3354 pSMB->Fid = fid; /* file handle always le */
3355 pSMB->ByteCount = 0;
3357 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3358 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3359 if (rc) {
3360 cifs_dbg(FYI, "Send error in QueryReparseLinkInfo = %d\n", rc);
3361 goto qreparse_out;
3364 data_offset = le32_to_cpu(pSMBr->DataOffset);
3365 data_count = le32_to_cpu(pSMBr->DataCount);
3366 if (get_bcc(&pSMBr->hdr) < 2 || data_offset > 512) {
3367 /* BB also check enough total bytes returned */
3368 rc = -EIO; /* bad smb */
3369 goto qreparse_out;
3371 if (!data_count || (data_count > 2048)) {
3372 rc = -EIO;
3373 cifs_dbg(FYI, "Invalid return data count on get reparse info ioctl\n");
3374 goto qreparse_out;
3376 end_of_smb = 2 + get_bcc(&pSMBr->hdr) + (char *)&pSMBr->ByteCount;
3377 reparse_buf = (struct reparse_symlink_data *)
3378 ((char *)&pSMBr->hdr.Protocol + data_offset);
3379 if ((char *)reparse_buf >= end_of_smb) {
3380 rc = -EIO;
3381 goto qreparse_out;
3383 if (reparse_buf->ReparseTag == cpu_to_le32(IO_REPARSE_TAG_NFS)) {
3384 cifs_dbg(FYI, "NFS style reparse tag\n");
3385 posix_buf = (struct reparse_posix_data *)reparse_buf;
3387 if (posix_buf->InodeType != cpu_to_le64(NFS_SPECFILE_LNK)) {
3388 cifs_dbg(FYI, "unsupported file type 0x%llx\n",
3389 le64_to_cpu(posix_buf->InodeType));
3390 rc = -EOPNOTSUPP;
3391 goto qreparse_out;
3393 is_unicode = true;
3394 sub_len = le16_to_cpu(reparse_buf->ReparseDataLength);
3395 if (posix_buf->PathBuffer + sub_len > end_of_smb) {
3396 cifs_dbg(FYI, "reparse buf beyond SMB\n");
3397 rc = -EIO;
3398 goto qreparse_out;
3400 *symlinkinfo = cifs_strndup_from_utf16(posix_buf->PathBuffer,
3401 sub_len, is_unicode, nls_codepage);
3402 goto qreparse_out;
3403 } else if (reparse_buf->ReparseTag !=
3404 cpu_to_le32(IO_REPARSE_TAG_SYMLINK)) {
3405 rc = -EOPNOTSUPP;
3406 goto qreparse_out;
3409 /* Reparse tag is NTFS symlink */
3410 sub_start = le16_to_cpu(reparse_buf->SubstituteNameOffset) +
3411 reparse_buf->PathBuffer;
3412 sub_len = le16_to_cpu(reparse_buf->SubstituteNameLength);
3413 if (sub_start + sub_len > end_of_smb) {
3414 cifs_dbg(FYI, "reparse buf beyond SMB\n");
3415 rc = -EIO;
3416 goto qreparse_out;
3418 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
3419 is_unicode = true;
3420 else
3421 is_unicode = false;
3423 /* BB FIXME investigate remapping reserved chars here */
3424 *symlinkinfo = cifs_strndup_from_utf16(sub_start, sub_len, is_unicode,
3425 nls_codepage);
3426 if (!*symlinkinfo)
3427 rc = -ENOMEM;
3428 qreparse_out:
3429 cifs_buf_release(pSMB);
3432 * Note: On -EAGAIN error only caller can retry on handle based calls
3433 * since file handle passed in no longer valid.
3435 return rc;
3439 CIFSSMB_set_compression(const unsigned int xid, struct cifs_tcon *tcon,
3440 __u16 fid)
3442 int rc = 0;
3443 int bytes_returned;
3444 struct smb_com_transaction_compr_ioctl_req *pSMB;
3445 struct smb_com_transaction_ioctl_rsp *pSMBr;
3447 cifs_dbg(FYI, "Set compression for %u\n", fid);
3448 rc = smb_init(SMB_COM_NT_TRANSACT, 23, tcon, (void **) &pSMB,
3449 (void **) &pSMBr);
3450 if (rc)
3451 return rc;
3453 pSMB->compression_state = cpu_to_le16(COMPRESSION_FORMAT_DEFAULT);
3455 pSMB->TotalParameterCount = 0;
3456 pSMB->TotalDataCount = cpu_to_le32(2);
3457 pSMB->MaxParameterCount = 0;
3458 pSMB->MaxDataCount = 0;
3459 pSMB->MaxSetupCount = 4;
3460 pSMB->Reserved = 0;
3461 pSMB->ParameterOffset = 0;
3462 pSMB->DataCount = cpu_to_le32(2);
3463 pSMB->DataOffset =
3464 cpu_to_le32(offsetof(struct smb_com_transaction_compr_ioctl_req,
3465 compression_state) - 4); /* 84 */
3466 pSMB->SetupCount = 4;
3467 pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_IOCTL);
3468 pSMB->ParameterCount = 0;
3469 pSMB->FunctionCode = cpu_to_le32(FSCTL_SET_COMPRESSION);
3470 pSMB->IsFsctl = 1; /* FSCTL */
3471 pSMB->IsRootFlag = 0;
3472 pSMB->Fid = fid; /* file handle always le */
3473 /* 3 byte pad, followed by 2 byte compress state */
3474 pSMB->ByteCount = cpu_to_le16(5);
3475 inc_rfc1001_len(pSMB, 5);
3477 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3478 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3479 if (rc)
3480 cifs_dbg(FYI, "Send error in SetCompression = %d\n", rc);
3482 cifs_buf_release(pSMB);
3485 * Note: On -EAGAIN error only caller can retry on handle based calls
3486 * since file handle passed in no longer valid.
3488 return rc;
3492 #ifdef CONFIG_CIFS_POSIX
3494 /*Convert an Access Control Entry from wire format to local POSIX xattr format*/
3495 static void cifs_convert_ace(struct posix_acl_xattr_entry *ace,
3496 struct cifs_posix_ace *cifs_ace)
3498 /* u8 cifs fields do not need le conversion */
3499 ace->e_perm = cpu_to_le16(cifs_ace->cifs_e_perm);
3500 ace->e_tag = cpu_to_le16(cifs_ace->cifs_e_tag);
3501 ace->e_id = cpu_to_le32(le64_to_cpu(cifs_ace->cifs_uid));
3503 cifs_dbg(FYI, "perm %d tag %d id %d\n",
3504 ace->e_perm, ace->e_tag, ace->e_id);
3507 return;
3510 /* Convert ACL from CIFS POSIX wire format to local Linux POSIX ACL xattr */
3511 static int cifs_copy_posix_acl(char *trgt, char *src, const int buflen,
3512 const int acl_type, const int size_of_data_area)
3514 int size = 0;
3515 int i;
3516 __u16 count;
3517 struct cifs_posix_ace *pACE;
3518 struct cifs_posix_acl *cifs_acl = (struct cifs_posix_acl *)src;
3519 struct posix_acl_xattr_header *local_acl = (void *)trgt;
3521 if (le16_to_cpu(cifs_acl->version) != CIFS_ACL_VERSION)
3522 return -EOPNOTSUPP;
3524 if (acl_type == ACL_TYPE_ACCESS) {
3525 count = le16_to_cpu(cifs_acl->access_entry_count);
3526 pACE = &cifs_acl->ace_array[0];
3527 size = sizeof(struct cifs_posix_acl);
3528 size += sizeof(struct cifs_posix_ace) * count;
3529 /* check if we would go beyond end of SMB */
3530 if (size_of_data_area < size) {
3531 cifs_dbg(FYI, "bad CIFS POSIX ACL size %d vs. %d\n",
3532 size_of_data_area, size);
3533 return -EINVAL;
3535 } else if (acl_type == ACL_TYPE_DEFAULT) {
3536 count = le16_to_cpu(cifs_acl->access_entry_count);
3537 size = sizeof(struct cifs_posix_acl);
3538 size += sizeof(struct cifs_posix_ace) * count;
3539 /* skip past access ACEs to get to default ACEs */
3540 pACE = &cifs_acl->ace_array[count];
3541 count = le16_to_cpu(cifs_acl->default_entry_count);
3542 size += sizeof(struct cifs_posix_ace) * count;
3543 /* check if we would go beyond end of SMB */
3544 if (size_of_data_area < size)
3545 return -EINVAL;
3546 } else {
3547 /* illegal type */
3548 return -EINVAL;
3551 size = posix_acl_xattr_size(count);
3552 if ((buflen == 0) || (local_acl == NULL)) {
3553 /* used to query ACL EA size */
3554 } else if (size > buflen) {
3555 return -ERANGE;
3556 } else /* buffer big enough */ {
3557 struct posix_acl_xattr_entry *ace = (void *)(local_acl + 1);
3559 local_acl->a_version = cpu_to_le32(POSIX_ACL_XATTR_VERSION);
3560 for (i = 0; i < count ; i++) {
3561 cifs_convert_ace(&ace[i], pACE);
3562 pACE++;
3565 return size;
3568 static void convert_ace_to_cifs_ace(struct cifs_posix_ace *cifs_ace,
3569 const struct posix_acl_xattr_entry *local_ace)
3571 cifs_ace->cifs_e_perm = le16_to_cpu(local_ace->e_perm);
3572 cifs_ace->cifs_e_tag = le16_to_cpu(local_ace->e_tag);
3573 /* BB is there a better way to handle the large uid? */
3574 if (local_ace->e_id == cpu_to_le32(-1)) {
3575 /* Probably no need to le convert -1 on any arch but can not hurt */
3576 cifs_ace->cifs_uid = cpu_to_le64(-1);
3577 } else
3578 cifs_ace->cifs_uid = cpu_to_le64(le32_to_cpu(local_ace->e_id));
3580 cifs_dbg(FYI, "perm %d tag %d id %d\n",
3581 ace->e_perm, ace->e_tag, ace->e_id);
3585 /* Convert ACL from local Linux POSIX xattr to CIFS POSIX ACL wire format */
3586 static __u16 ACL_to_cifs_posix(char *parm_data, const char *pACL,
3587 const int buflen, const int acl_type)
3589 __u16 rc = 0;
3590 struct cifs_posix_acl *cifs_acl = (struct cifs_posix_acl *)parm_data;
3591 struct posix_acl_xattr_header *local_acl = (void *)pACL;
3592 struct posix_acl_xattr_entry *ace = (void *)(local_acl + 1);
3593 int count;
3594 int i;
3596 if ((buflen == 0) || (pACL == NULL) || (cifs_acl == NULL))
3597 return 0;
3599 count = posix_acl_xattr_count((size_t)buflen);
3600 cifs_dbg(FYI, "setting acl with %d entries from buf of length %d and version of %d\n",
3601 count, buflen, le32_to_cpu(local_acl->a_version));
3602 if (le32_to_cpu(local_acl->a_version) != 2) {
3603 cifs_dbg(FYI, "unknown POSIX ACL version %d\n",
3604 le32_to_cpu(local_acl->a_version));
3605 return 0;
3607 cifs_acl->version = cpu_to_le16(1);
3608 if (acl_type == ACL_TYPE_ACCESS) {
3609 cifs_acl->access_entry_count = cpu_to_le16(count);
3610 cifs_acl->default_entry_count = cpu_to_le16(0xFFFF);
3611 } else if (acl_type == ACL_TYPE_DEFAULT) {
3612 cifs_acl->default_entry_count = cpu_to_le16(count);
3613 cifs_acl->access_entry_count = cpu_to_le16(0xFFFF);
3614 } else {
3615 cifs_dbg(FYI, "unknown ACL type %d\n", acl_type);
3616 return 0;
3618 for (i = 0; i < count; i++)
3619 convert_ace_to_cifs_ace(&cifs_acl->ace_array[i], &ace[i]);
3620 if (rc == 0) {
3621 rc = (__u16)(count * sizeof(struct cifs_posix_ace));
3622 rc += sizeof(struct cifs_posix_acl);
3623 /* BB add check to make sure ACL does not overflow SMB */
3625 return rc;
3629 CIFSSMBGetPosixACL(const unsigned int xid, struct cifs_tcon *tcon,
3630 const unsigned char *searchName,
3631 char *acl_inf, const int buflen, const int acl_type,
3632 const struct nls_table *nls_codepage, int remap)
3634 /* SMB_QUERY_POSIX_ACL */
3635 TRANSACTION2_QPI_REQ *pSMB = NULL;
3636 TRANSACTION2_QPI_RSP *pSMBr = NULL;
3637 int rc = 0;
3638 int bytes_returned;
3639 int name_len;
3640 __u16 params, byte_count;
3642 cifs_dbg(FYI, "In GetPosixACL (Unix) for path %s\n", searchName);
3644 queryAclRetry:
3645 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3646 (void **) &pSMBr);
3647 if (rc)
3648 return rc;
3650 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3651 name_len =
3652 cifsConvertToUTF16((__le16 *) pSMB->FileName,
3653 searchName, PATH_MAX, nls_codepage,
3654 remap);
3655 name_len++; /* trailing null */
3656 name_len *= 2;
3657 pSMB->FileName[name_len] = 0;
3658 pSMB->FileName[name_len+1] = 0;
3659 } else {
3660 name_len = copy_path_name(pSMB->FileName, searchName);
3663 params = 2 /* level */ + 4 /* rsrvd */ + name_len /* incl null */ ;
3664 pSMB->TotalDataCount = 0;
3665 pSMB->MaxParameterCount = cpu_to_le16(2);
3666 /* BB find exact max data count below from sess structure BB */
3667 pSMB->MaxDataCount = cpu_to_le16(4000);
3668 pSMB->MaxSetupCount = 0;
3669 pSMB->Reserved = 0;
3670 pSMB->Flags = 0;
3671 pSMB->Timeout = 0;
3672 pSMB->Reserved2 = 0;
3673 pSMB->ParameterOffset = cpu_to_le16(
3674 offsetof(struct smb_com_transaction2_qpi_req,
3675 InformationLevel) - 4);
3676 pSMB->DataCount = 0;
3677 pSMB->DataOffset = 0;
3678 pSMB->SetupCount = 1;
3679 pSMB->Reserved3 = 0;
3680 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
3681 byte_count = params + 1 /* pad */ ;
3682 pSMB->TotalParameterCount = cpu_to_le16(params);
3683 pSMB->ParameterCount = pSMB->TotalParameterCount;
3684 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_POSIX_ACL);
3685 pSMB->Reserved4 = 0;
3686 inc_rfc1001_len(pSMB, byte_count);
3687 pSMB->ByteCount = cpu_to_le16(byte_count);
3689 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3690 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3691 cifs_stats_inc(&tcon->stats.cifs_stats.num_acl_get);
3692 if (rc) {
3693 cifs_dbg(FYI, "Send error in Query POSIX ACL = %d\n", rc);
3694 } else {
3695 /* decode response */
3697 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3698 /* BB also check enough total bytes returned */
3699 if (rc || get_bcc(&pSMBr->hdr) < 2)
3700 rc = -EIO; /* bad smb */
3701 else {
3702 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3703 __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
3704 rc = cifs_copy_posix_acl(acl_inf,
3705 (char *)&pSMBr->hdr.Protocol+data_offset,
3706 buflen, acl_type, count);
3709 cifs_buf_release(pSMB);
3710 if (rc == -EAGAIN)
3711 goto queryAclRetry;
3712 return rc;
3716 CIFSSMBSetPosixACL(const unsigned int xid, struct cifs_tcon *tcon,
3717 const unsigned char *fileName,
3718 const char *local_acl, const int buflen,
3719 const int acl_type,
3720 const struct nls_table *nls_codepage, int remap)
3722 struct smb_com_transaction2_spi_req *pSMB = NULL;
3723 struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
3724 char *parm_data;
3725 int name_len;
3726 int rc = 0;
3727 int bytes_returned = 0;
3728 __u16 params, byte_count, data_count, param_offset, offset;
3730 cifs_dbg(FYI, "In SetPosixACL (Unix) for path %s\n", fileName);
3731 setAclRetry:
3732 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3733 (void **) &pSMBr);
3734 if (rc)
3735 return rc;
3736 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3737 name_len =
3738 cifsConvertToUTF16((__le16 *) pSMB->FileName, fileName,
3739 PATH_MAX, nls_codepage, remap);
3740 name_len++; /* trailing null */
3741 name_len *= 2;
3742 } else {
3743 name_len = copy_path_name(pSMB->FileName, fileName);
3745 params = 6 + name_len;
3746 pSMB->MaxParameterCount = cpu_to_le16(2);
3747 /* BB find max SMB size from sess */
3748 pSMB->MaxDataCount = cpu_to_le16(1000);
3749 pSMB->MaxSetupCount = 0;
3750 pSMB->Reserved = 0;
3751 pSMB->Flags = 0;
3752 pSMB->Timeout = 0;
3753 pSMB->Reserved2 = 0;
3754 param_offset = offsetof(struct smb_com_transaction2_spi_req,
3755 InformationLevel) - 4;
3756 offset = param_offset + params;
3757 parm_data = ((char *) &pSMB->hdr.Protocol) + offset;
3758 pSMB->ParameterOffset = cpu_to_le16(param_offset);
3760 /* convert to on the wire format for POSIX ACL */
3761 data_count = ACL_to_cifs_posix(parm_data, local_acl, buflen, acl_type);
3763 if (data_count == 0) {
3764 rc = -EOPNOTSUPP;
3765 goto setACLerrorExit;
3767 pSMB->DataOffset = cpu_to_le16(offset);
3768 pSMB->SetupCount = 1;
3769 pSMB->Reserved3 = 0;
3770 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
3771 pSMB->InformationLevel = cpu_to_le16(SMB_SET_POSIX_ACL);
3772 byte_count = 3 /* pad */ + params + data_count;
3773 pSMB->DataCount = cpu_to_le16(data_count);
3774 pSMB->TotalDataCount = pSMB->DataCount;
3775 pSMB->ParameterCount = cpu_to_le16(params);
3776 pSMB->TotalParameterCount = pSMB->ParameterCount;
3777 pSMB->Reserved4 = 0;
3778 inc_rfc1001_len(pSMB, byte_count);
3779 pSMB->ByteCount = cpu_to_le16(byte_count);
3780 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3781 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3782 if (rc)
3783 cifs_dbg(FYI, "Set POSIX ACL returned %d\n", rc);
3785 setACLerrorExit:
3786 cifs_buf_release(pSMB);
3787 if (rc == -EAGAIN)
3788 goto setAclRetry;
3789 return rc;
3792 /* BB fix tabs in this function FIXME BB */
3794 CIFSGetExtAttr(const unsigned int xid, struct cifs_tcon *tcon,
3795 const int netfid, __u64 *pExtAttrBits, __u64 *pMask)
3797 int rc = 0;
3798 struct smb_t2_qfi_req *pSMB = NULL;
3799 struct smb_t2_qfi_rsp *pSMBr = NULL;
3800 int bytes_returned;
3801 __u16 params, byte_count;
3803 cifs_dbg(FYI, "In GetExtAttr\n");
3804 if (tcon == NULL)
3805 return -ENODEV;
3807 GetExtAttrRetry:
3808 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3809 (void **) &pSMBr);
3810 if (rc)
3811 return rc;
3813 params = 2 /* level */ + 2 /* fid */;
3814 pSMB->t2.TotalDataCount = 0;
3815 pSMB->t2.MaxParameterCount = cpu_to_le16(4);
3816 /* BB find exact max data count below from sess structure BB */
3817 pSMB->t2.MaxDataCount = cpu_to_le16(4000);
3818 pSMB->t2.MaxSetupCount = 0;
3819 pSMB->t2.Reserved = 0;
3820 pSMB->t2.Flags = 0;
3821 pSMB->t2.Timeout = 0;
3822 pSMB->t2.Reserved2 = 0;
3823 pSMB->t2.ParameterOffset = cpu_to_le16(offsetof(struct smb_t2_qfi_req,
3824 Fid) - 4);
3825 pSMB->t2.DataCount = 0;
3826 pSMB->t2.DataOffset = 0;
3827 pSMB->t2.SetupCount = 1;
3828 pSMB->t2.Reserved3 = 0;
3829 pSMB->t2.SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION);
3830 byte_count = params + 1 /* pad */ ;
3831 pSMB->t2.TotalParameterCount = cpu_to_le16(params);
3832 pSMB->t2.ParameterCount = pSMB->t2.TotalParameterCount;
3833 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_ATTR_FLAGS);
3834 pSMB->Pad = 0;
3835 pSMB->Fid = netfid;
3836 inc_rfc1001_len(pSMB, byte_count);
3837 pSMB->t2.ByteCount = cpu_to_le16(byte_count);
3839 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3840 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3841 if (rc) {
3842 cifs_dbg(FYI, "error %d in GetExtAttr\n", rc);
3843 } else {
3844 /* decode response */
3845 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3846 /* BB also check enough total bytes returned */
3847 if (rc || get_bcc(&pSMBr->hdr) < 2)
3848 /* If rc should we check for EOPNOSUPP and
3849 disable the srvino flag? or in caller? */
3850 rc = -EIO; /* bad smb */
3851 else {
3852 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3853 __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
3854 struct file_chattr_info *pfinfo;
3855 /* BB Do we need a cast or hash here ? */
3856 if (count != 16) {
3857 cifs_dbg(FYI, "Illegal size ret in GetExtAttr\n");
3858 rc = -EIO;
3859 goto GetExtAttrOut;
3861 pfinfo = (struct file_chattr_info *)
3862 (data_offset + (char *) &pSMBr->hdr.Protocol);
3863 *pExtAttrBits = le64_to_cpu(pfinfo->mode);
3864 *pMask = le64_to_cpu(pfinfo->mask);
3867 GetExtAttrOut:
3868 cifs_buf_release(pSMB);
3869 if (rc == -EAGAIN)
3870 goto GetExtAttrRetry;
3871 return rc;
3874 #endif /* CONFIG_POSIX */
3877 * Initialize NT TRANSACT SMB into small smb request buffer. This assumes that
3878 * all NT TRANSACTS that we init here have total parm and data under about 400
3879 * bytes (to fit in small cifs buffer size), which is the case so far, it
3880 * easily fits. NB: Setup words themselves and ByteCount MaxSetupCount (size of
3881 * returned setup area) and MaxParameterCount (returned parms size) must be set
3882 * by caller
3884 static int
3885 smb_init_nttransact(const __u16 sub_command, const int setup_count,
3886 const int parm_len, struct cifs_tcon *tcon,
3887 void **ret_buf)
3889 int rc;
3890 __u32 temp_offset;
3891 struct smb_com_ntransact_req *pSMB;
3893 rc = small_smb_init(SMB_COM_NT_TRANSACT, 19 + setup_count, tcon,
3894 (void **)&pSMB);
3895 if (rc)
3896 return rc;
3897 *ret_buf = (void *)pSMB;
3898 pSMB->Reserved = 0;
3899 pSMB->TotalParameterCount = cpu_to_le32(parm_len);
3900 pSMB->TotalDataCount = 0;
3901 pSMB->MaxDataCount = cpu_to_le32(CIFSMaxBufSize & 0xFFFFFF00);
3902 pSMB->ParameterCount = pSMB->TotalParameterCount;
3903 pSMB->DataCount = pSMB->TotalDataCount;
3904 temp_offset = offsetof(struct smb_com_ntransact_req, Parms) +
3905 (setup_count * 2) - 4 /* for rfc1001 length itself */;
3906 pSMB->ParameterOffset = cpu_to_le32(temp_offset);
3907 pSMB->DataOffset = cpu_to_le32(temp_offset + parm_len);
3908 pSMB->SetupCount = setup_count; /* no need to le convert byte fields */
3909 pSMB->SubCommand = cpu_to_le16(sub_command);
3910 return 0;
3913 static int
3914 validate_ntransact(char *buf, char **ppparm, char **ppdata,
3915 __u32 *pparmlen, __u32 *pdatalen)
3917 char *end_of_smb;
3918 __u32 data_count, data_offset, parm_count, parm_offset;
3919 struct smb_com_ntransact_rsp *pSMBr;
3920 u16 bcc;
3922 *pdatalen = 0;
3923 *pparmlen = 0;
3925 if (buf == NULL)
3926 return -EINVAL;
3928 pSMBr = (struct smb_com_ntransact_rsp *)buf;
3930 bcc = get_bcc(&pSMBr->hdr);
3931 end_of_smb = 2 /* sizeof byte count */ + bcc +
3932 (char *)&pSMBr->ByteCount;
3934 data_offset = le32_to_cpu(pSMBr->DataOffset);
3935 data_count = le32_to_cpu(pSMBr->DataCount);
3936 parm_offset = le32_to_cpu(pSMBr->ParameterOffset);
3937 parm_count = le32_to_cpu(pSMBr->ParameterCount);
3939 *ppparm = (char *)&pSMBr->hdr.Protocol + parm_offset;
3940 *ppdata = (char *)&pSMBr->hdr.Protocol + data_offset;
3942 /* should we also check that parm and data areas do not overlap? */
3943 if (*ppparm > end_of_smb) {
3944 cifs_dbg(FYI, "parms start after end of smb\n");
3945 return -EINVAL;
3946 } else if (parm_count + *ppparm > end_of_smb) {
3947 cifs_dbg(FYI, "parm end after end of smb\n");
3948 return -EINVAL;
3949 } else if (*ppdata > end_of_smb) {
3950 cifs_dbg(FYI, "data starts after end of smb\n");
3951 return -EINVAL;
3952 } else if (data_count + *ppdata > end_of_smb) {
3953 cifs_dbg(FYI, "data %p + count %d (%p) past smb end %p start %p\n",
3954 *ppdata, data_count, (data_count + *ppdata),
3955 end_of_smb, pSMBr);
3956 return -EINVAL;
3957 } else if (parm_count + data_count > bcc) {
3958 cifs_dbg(FYI, "parm count and data count larger than SMB\n");
3959 return -EINVAL;
3961 *pdatalen = data_count;
3962 *pparmlen = parm_count;
3963 return 0;
3966 /* Get Security Descriptor (by handle) from remote server for a file or dir */
3968 CIFSSMBGetCIFSACL(const unsigned int xid, struct cifs_tcon *tcon, __u16 fid,
3969 struct cifs_ntsd **acl_inf, __u32 *pbuflen)
3971 int rc = 0;
3972 int buf_type = 0;
3973 QUERY_SEC_DESC_REQ *pSMB;
3974 struct kvec iov[1];
3975 struct kvec rsp_iov;
3977 cifs_dbg(FYI, "GetCifsACL\n");
3979 *pbuflen = 0;
3980 *acl_inf = NULL;
3982 rc = smb_init_nttransact(NT_TRANSACT_QUERY_SECURITY_DESC, 0,
3983 8 /* parm len */, tcon, (void **) &pSMB);
3984 if (rc)
3985 return rc;
3987 pSMB->MaxParameterCount = cpu_to_le32(4);
3988 /* BB TEST with big acls that might need to be e.g. larger than 16K */
3989 pSMB->MaxSetupCount = 0;
3990 pSMB->Fid = fid; /* file handle always le */
3991 pSMB->AclFlags = cpu_to_le32(CIFS_ACL_OWNER | CIFS_ACL_GROUP |
3992 CIFS_ACL_DACL);
3993 pSMB->ByteCount = cpu_to_le16(11); /* 3 bytes pad + 8 bytes parm */
3994 inc_rfc1001_len(pSMB, 11);
3995 iov[0].iov_base = (char *)pSMB;
3996 iov[0].iov_len = be32_to_cpu(pSMB->hdr.smb_buf_length) + 4;
3998 rc = SendReceive2(xid, tcon->ses, iov, 1 /* num iovec */, &buf_type,
3999 0, &rsp_iov);
4000 cifs_small_buf_release(pSMB);
4001 cifs_stats_inc(&tcon->stats.cifs_stats.num_acl_get);
4002 if (rc) {
4003 cifs_dbg(FYI, "Send error in QuerySecDesc = %d\n", rc);
4004 } else { /* decode response */
4005 __le32 *parm;
4006 __u32 parm_len;
4007 __u32 acl_len;
4008 struct smb_com_ntransact_rsp *pSMBr;
4009 char *pdata;
4011 /* validate_nttransact */
4012 rc = validate_ntransact(rsp_iov.iov_base, (char **)&parm,
4013 &pdata, &parm_len, pbuflen);
4014 if (rc)
4015 goto qsec_out;
4016 pSMBr = (struct smb_com_ntransact_rsp *)rsp_iov.iov_base;
4018 cifs_dbg(FYI, "smb %p parm %p data %p\n",
4019 pSMBr, parm, *acl_inf);
4021 if (le32_to_cpu(pSMBr->ParameterCount) != 4) {
4022 rc = -EIO; /* bad smb */
4023 *pbuflen = 0;
4024 goto qsec_out;
4027 /* BB check that data area is minimum length and as big as acl_len */
4029 acl_len = le32_to_cpu(*parm);
4030 if (acl_len != *pbuflen) {
4031 cifs_dbg(VFS, "acl length %d does not match %d\n",
4032 acl_len, *pbuflen);
4033 if (*pbuflen > acl_len)
4034 *pbuflen = acl_len;
4037 /* check if buffer is big enough for the acl
4038 header followed by the smallest SID */
4039 if ((*pbuflen < sizeof(struct cifs_ntsd) + 8) ||
4040 (*pbuflen >= 64 * 1024)) {
4041 cifs_dbg(VFS, "bad acl length %d\n", *pbuflen);
4042 rc = -EINVAL;
4043 *pbuflen = 0;
4044 } else {
4045 *acl_inf = kmemdup(pdata, *pbuflen, GFP_KERNEL);
4046 if (*acl_inf == NULL) {
4047 *pbuflen = 0;
4048 rc = -ENOMEM;
4052 qsec_out:
4053 free_rsp_buf(buf_type, rsp_iov.iov_base);
4054 return rc;
4058 CIFSSMBSetCIFSACL(const unsigned int xid, struct cifs_tcon *tcon, __u16 fid,
4059 struct cifs_ntsd *pntsd, __u32 acllen, int aclflag)
4061 __u16 byte_count, param_count, data_count, param_offset, data_offset;
4062 int rc = 0;
4063 int bytes_returned = 0;
4064 SET_SEC_DESC_REQ *pSMB = NULL;
4065 void *pSMBr;
4067 setCifsAclRetry:
4068 rc = smb_init(SMB_COM_NT_TRANSACT, 19, tcon, (void **) &pSMB, &pSMBr);
4069 if (rc)
4070 return rc;
4072 pSMB->MaxSetupCount = 0;
4073 pSMB->Reserved = 0;
4075 param_count = 8;
4076 param_offset = offsetof(struct smb_com_transaction_ssec_req, Fid) - 4;
4077 data_count = acllen;
4078 data_offset = param_offset + param_count;
4079 byte_count = 3 /* pad */ + param_count;
4081 pSMB->DataCount = cpu_to_le32(data_count);
4082 pSMB->TotalDataCount = pSMB->DataCount;
4083 pSMB->MaxParameterCount = cpu_to_le32(4);
4084 pSMB->MaxDataCount = cpu_to_le32(16384);
4085 pSMB->ParameterCount = cpu_to_le32(param_count);
4086 pSMB->ParameterOffset = cpu_to_le32(param_offset);
4087 pSMB->TotalParameterCount = pSMB->ParameterCount;
4088 pSMB->DataOffset = cpu_to_le32(data_offset);
4089 pSMB->SetupCount = 0;
4090 pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_SET_SECURITY_DESC);
4091 pSMB->ByteCount = cpu_to_le16(byte_count+data_count);
4093 pSMB->Fid = fid; /* file handle always le */
4094 pSMB->Reserved2 = 0;
4095 pSMB->AclFlags = cpu_to_le32(aclflag);
4097 if (pntsd && acllen) {
4098 memcpy((char *)pSMBr + offsetof(struct smb_hdr, Protocol) +
4099 data_offset, pntsd, acllen);
4100 inc_rfc1001_len(pSMB, byte_count + data_count);
4101 } else
4102 inc_rfc1001_len(pSMB, byte_count);
4104 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4105 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4107 cifs_dbg(FYI, "SetCIFSACL bytes_returned: %d, rc: %d\n",
4108 bytes_returned, rc);
4109 if (rc)
4110 cifs_dbg(FYI, "Set CIFS ACL returned %d\n", rc);
4111 cifs_buf_release(pSMB);
4113 if (rc == -EAGAIN)
4114 goto setCifsAclRetry;
4116 return (rc);
4120 /* Legacy Query Path Information call for lookup to old servers such
4121 as Win9x/WinME */
4123 SMBQueryInformation(const unsigned int xid, struct cifs_tcon *tcon,
4124 const char *search_name, FILE_ALL_INFO *data,
4125 const struct nls_table *nls_codepage, int remap)
4127 QUERY_INFORMATION_REQ *pSMB;
4128 QUERY_INFORMATION_RSP *pSMBr;
4129 int rc = 0;
4130 int bytes_returned;
4131 int name_len;
4133 cifs_dbg(FYI, "In SMBQPath path %s\n", search_name);
4134 QInfRetry:
4135 rc = smb_init(SMB_COM_QUERY_INFORMATION, 0, tcon, (void **) &pSMB,
4136 (void **) &pSMBr);
4137 if (rc)
4138 return rc;
4140 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4141 name_len =
4142 cifsConvertToUTF16((__le16 *) pSMB->FileName,
4143 search_name, PATH_MAX, nls_codepage,
4144 remap);
4145 name_len++; /* trailing null */
4146 name_len *= 2;
4147 } else {
4148 name_len = copy_path_name(pSMB->FileName, search_name);
4150 pSMB->BufferFormat = 0x04;
4151 name_len++; /* account for buffer type byte */
4152 inc_rfc1001_len(pSMB, (__u16)name_len);
4153 pSMB->ByteCount = cpu_to_le16(name_len);
4155 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4156 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4157 if (rc) {
4158 cifs_dbg(FYI, "Send error in QueryInfo = %d\n", rc);
4159 } else if (data) {
4160 struct timespec64 ts;
4161 __u32 time = le32_to_cpu(pSMBr->last_write_time);
4163 /* decode response */
4164 /* BB FIXME - add time zone adjustment BB */
4165 memset(data, 0, sizeof(FILE_ALL_INFO));
4166 ts.tv_nsec = 0;
4167 ts.tv_sec = time;
4168 /* decode time fields */
4169 data->ChangeTime = cpu_to_le64(cifs_UnixTimeToNT(ts));
4170 data->LastWriteTime = data->ChangeTime;
4171 data->LastAccessTime = 0;
4172 data->AllocationSize =
4173 cpu_to_le64(le32_to_cpu(pSMBr->size));
4174 data->EndOfFile = data->AllocationSize;
4175 data->Attributes =
4176 cpu_to_le32(le16_to_cpu(pSMBr->attr));
4177 } else
4178 rc = -EIO; /* bad buffer passed in */
4180 cifs_buf_release(pSMB);
4182 if (rc == -EAGAIN)
4183 goto QInfRetry;
4185 return rc;
4189 CIFSSMBQFileInfo(const unsigned int xid, struct cifs_tcon *tcon,
4190 u16 netfid, FILE_ALL_INFO *pFindData)
4192 struct smb_t2_qfi_req *pSMB = NULL;
4193 struct smb_t2_qfi_rsp *pSMBr = NULL;
4194 int rc = 0;
4195 int bytes_returned;
4196 __u16 params, byte_count;
4198 QFileInfoRetry:
4199 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4200 (void **) &pSMBr);
4201 if (rc)
4202 return rc;
4204 params = 2 /* level */ + 2 /* fid */;
4205 pSMB->t2.TotalDataCount = 0;
4206 pSMB->t2.MaxParameterCount = cpu_to_le16(4);
4207 /* BB find exact max data count below from sess structure BB */
4208 pSMB->t2.MaxDataCount = cpu_to_le16(CIFSMaxBufSize);
4209 pSMB->t2.MaxSetupCount = 0;
4210 pSMB->t2.Reserved = 0;
4211 pSMB->t2.Flags = 0;
4212 pSMB->t2.Timeout = 0;
4213 pSMB->t2.Reserved2 = 0;
4214 pSMB->t2.ParameterOffset = cpu_to_le16(offsetof(struct smb_t2_qfi_req,
4215 Fid) - 4);
4216 pSMB->t2.DataCount = 0;
4217 pSMB->t2.DataOffset = 0;
4218 pSMB->t2.SetupCount = 1;
4219 pSMB->t2.Reserved3 = 0;
4220 pSMB->t2.SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION);
4221 byte_count = params + 1 /* pad */ ;
4222 pSMB->t2.TotalParameterCount = cpu_to_le16(params);
4223 pSMB->t2.ParameterCount = pSMB->t2.TotalParameterCount;
4224 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_ALL_INFO);
4225 pSMB->Pad = 0;
4226 pSMB->Fid = netfid;
4227 inc_rfc1001_len(pSMB, byte_count);
4228 pSMB->t2.ByteCount = cpu_to_le16(byte_count);
4230 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4231 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4232 if (rc) {
4233 cifs_dbg(FYI, "Send error in QFileInfo = %d", rc);
4234 } else { /* decode response */
4235 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4237 if (rc) /* BB add auto retry on EOPNOTSUPP? */
4238 rc = -EIO;
4239 else if (get_bcc(&pSMBr->hdr) < 40)
4240 rc = -EIO; /* bad smb */
4241 else if (pFindData) {
4242 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4243 memcpy((char *) pFindData,
4244 (char *) &pSMBr->hdr.Protocol +
4245 data_offset, sizeof(FILE_ALL_INFO));
4246 } else
4247 rc = -ENOMEM;
4249 cifs_buf_release(pSMB);
4250 if (rc == -EAGAIN)
4251 goto QFileInfoRetry;
4253 return rc;
4257 CIFSSMBQPathInfo(const unsigned int xid, struct cifs_tcon *tcon,
4258 const char *search_name, FILE_ALL_INFO *data,
4259 int legacy /* old style infolevel */,
4260 const struct nls_table *nls_codepage, int remap)
4262 /* level 263 SMB_QUERY_FILE_ALL_INFO */
4263 TRANSACTION2_QPI_REQ *pSMB = NULL;
4264 TRANSACTION2_QPI_RSP *pSMBr = NULL;
4265 int rc = 0;
4266 int bytes_returned;
4267 int name_len;
4268 __u16 params, byte_count;
4270 /* cifs_dbg(FYI, "In QPathInfo path %s\n", search_name); */
4271 QPathInfoRetry:
4272 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4273 (void **) &pSMBr);
4274 if (rc)
4275 return rc;
4277 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4278 name_len =
4279 cifsConvertToUTF16((__le16 *) pSMB->FileName, search_name,
4280 PATH_MAX, nls_codepage, remap);
4281 name_len++; /* trailing null */
4282 name_len *= 2;
4283 } else {
4284 name_len = copy_path_name(pSMB->FileName, search_name);
4287 params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */;
4288 pSMB->TotalDataCount = 0;
4289 pSMB->MaxParameterCount = cpu_to_le16(2);
4290 /* BB find exact max SMB PDU from sess structure BB */
4291 pSMB->MaxDataCount = cpu_to_le16(4000);
4292 pSMB->MaxSetupCount = 0;
4293 pSMB->Reserved = 0;
4294 pSMB->Flags = 0;
4295 pSMB->Timeout = 0;
4296 pSMB->Reserved2 = 0;
4297 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4298 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
4299 pSMB->DataCount = 0;
4300 pSMB->DataOffset = 0;
4301 pSMB->SetupCount = 1;
4302 pSMB->Reserved3 = 0;
4303 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
4304 byte_count = params + 1 /* pad */ ;
4305 pSMB->TotalParameterCount = cpu_to_le16(params);
4306 pSMB->ParameterCount = pSMB->TotalParameterCount;
4307 if (legacy)
4308 pSMB->InformationLevel = cpu_to_le16(SMB_INFO_STANDARD);
4309 else
4310 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_ALL_INFO);
4311 pSMB->Reserved4 = 0;
4312 inc_rfc1001_len(pSMB, byte_count);
4313 pSMB->ByteCount = cpu_to_le16(byte_count);
4315 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4316 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4317 if (rc) {
4318 cifs_dbg(FYI, "Send error in QPathInfo = %d\n", rc);
4319 } else { /* decode response */
4320 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4322 if (rc) /* BB add auto retry on EOPNOTSUPP? */
4323 rc = -EIO;
4324 else if (!legacy && get_bcc(&pSMBr->hdr) < 40)
4325 rc = -EIO; /* bad smb */
4326 else if (legacy && get_bcc(&pSMBr->hdr) < 24)
4327 rc = -EIO; /* 24 or 26 expected but we do not read
4328 last field */
4329 else if (data) {
4330 int size;
4331 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4334 * On legacy responses we do not read the last field,
4335 * EAsize, fortunately since it varies by subdialect and
4336 * also note it differs on Set vs Get, ie two bytes or 4
4337 * bytes depending but we don't care here.
4339 if (legacy)
4340 size = sizeof(FILE_INFO_STANDARD);
4341 else
4342 size = sizeof(FILE_ALL_INFO);
4343 memcpy((char *) data, (char *) &pSMBr->hdr.Protocol +
4344 data_offset, size);
4345 } else
4346 rc = -ENOMEM;
4348 cifs_buf_release(pSMB);
4349 if (rc == -EAGAIN)
4350 goto QPathInfoRetry;
4352 return rc;
4356 CIFSSMBUnixQFileInfo(const unsigned int xid, struct cifs_tcon *tcon,
4357 u16 netfid, FILE_UNIX_BASIC_INFO *pFindData)
4359 struct smb_t2_qfi_req *pSMB = NULL;
4360 struct smb_t2_qfi_rsp *pSMBr = NULL;
4361 int rc = 0;
4362 int bytes_returned;
4363 __u16 params, byte_count;
4365 UnixQFileInfoRetry:
4366 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4367 (void **) &pSMBr);
4368 if (rc)
4369 return rc;
4371 params = 2 /* level */ + 2 /* fid */;
4372 pSMB->t2.TotalDataCount = 0;
4373 pSMB->t2.MaxParameterCount = cpu_to_le16(4);
4374 /* BB find exact max data count below from sess structure BB */
4375 pSMB->t2.MaxDataCount = cpu_to_le16(CIFSMaxBufSize);
4376 pSMB->t2.MaxSetupCount = 0;
4377 pSMB->t2.Reserved = 0;
4378 pSMB->t2.Flags = 0;
4379 pSMB->t2.Timeout = 0;
4380 pSMB->t2.Reserved2 = 0;
4381 pSMB->t2.ParameterOffset = cpu_to_le16(offsetof(struct smb_t2_qfi_req,
4382 Fid) - 4);
4383 pSMB->t2.DataCount = 0;
4384 pSMB->t2.DataOffset = 0;
4385 pSMB->t2.SetupCount = 1;
4386 pSMB->t2.Reserved3 = 0;
4387 pSMB->t2.SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION);
4388 byte_count = params + 1 /* pad */ ;
4389 pSMB->t2.TotalParameterCount = cpu_to_le16(params);
4390 pSMB->t2.ParameterCount = pSMB->t2.TotalParameterCount;
4391 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC);
4392 pSMB->Pad = 0;
4393 pSMB->Fid = netfid;
4394 inc_rfc1001_len(pSMB, byte_count);
4395 pSMB->t2.ByteCount = cpu_to_le16(byte_count);
4397 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4398 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4399 if (rc) {
4400 cifs_dbg(FYI, "Send error in UnixQFileInfo = %d", rc);
4401 } else { /* decode response */
4402 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4404 if (rc || get_bcc(&pSMBr->hdr) < sizeof(FILE_UNIX_BASIC_INFO)) {
4405 cifs_dbg(VFS, "Malformed FILE_UNIX_BASIC_INFO response. Unix Extensions can be disabled on mount by specifying the nosfu mount option.\n");
4406 rc = -EIO; /* bad smb */
4407 } else {
4408 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4409 memcpy((char *) pFindData,
4410 (char *) &pSMBr->hdr.Protocol +
4411 data_offset,
4412 sizeof(FILE_UNIX_BASIC_INFO));
4416 cifs_buf_release(pSMB);
4417 if (rc == -EAGAIN)
4418 goto UnixQFileInfoRetry;
4420 return rc;
4424 CIFSSMBUnixQPathInfo(const unsigned int xid, struct cifs_tcon *tcon,
4425 const unsigned char *searchName,
4426 FILE_UNIX_BASIC_INFO *pFindData,
4427 const struct nls_table *nls_codepage, int remap)
4429 /* SMB_QUERY_FILE_UNIX_BASIC */
4430 TRANSACTION2_QPI_REQ *pSMB = NULL;
4431 TRANSACTION2_QPI_RSP *pSMBr = NULL;
4432 int rc = 0;
4433 int bytes_returned = 0;
4434 int name_len;
4435 __u16 params, byte_count;
4437 cifs_dbg(FYI, "In QPathInfo (Unix) the path %s\n", searchName);
4438 UnixQPathInfoRetry:
4439 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4440 (void **) &pSMBr);
4441 if (rc)
4442 return rc;
4444 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4445 name_len =
4446 cifsConvertToUTF16((__le16 *) pSMB->FileName, searchName,
4447 PATH_MAX, nls_codepage, remap);
4448 name_len++; /* trailing null */
4449 name_len *= 2;
4450 } else {
4451 name_len = copy_path_name(pSMB->FileName, searchName);
4454 params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */;
4455 pSMB->TotalDataCount = 0;
4456 pSMB->MaxParameterCount = cpu_to_le16(2);
4457 /* BB find exact max SMB PDU from sess structure BB */
4458 pSMB->MaxDataCount = cpu_to_le16(4000);
4459 pSMB->MaxSetupCount = 0;
4460 pSMB->Reserved = 0;
4461 pSMB->Flags = 0;
4462 pSMB->Timeout = 0;
4463 pSMB->Reserved2 = 0;
4464 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4465 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
4466 pSMB->DataCount = 0;
4467 pSMB->DataOffset = 0;
4468 pSMB->SetupCount = 1;
4469 pSMB->Reserved3 = 0;
4470 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
4471 byte_count = params + 1 /* pad */ ;
4472 pSMB->TotalParameterCount = cpu_to_le16(params);
4473 pSMB->ParameterCount = pSMB->TotalParameterCount;
4474 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC);
4475 pSMB->Reserved4 = 0;
4476 inc_rfc1001_len(pSMB, byte_count);
4477 pSMB->ByteCount = cpu_to_le16(byte_count);
4479 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4480 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4481 if (rc) {
4482 cifs_dbg(FYI, "Send error in UnixQPathInfo = %d", rc);
4483 } else { /* decode response */
4484 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4486 if (rc || get_bcc(&pSMBr->hdr) < sizeof(FILE_UNIX_BASIC_INFO)) {
4487 cifs_dbg(VFS, "Malformed FILE_UNIX_BASIC_INFO response. Unix Extensions can be disabled on mount by specifying the nosfu mount option.\n");
4488 rc = -EIO; /* bad smb */
4489 } else {
4490 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4491 memcpy((char *) pFindData,
4492 (char *) &pSMBr->hdr.Protocol +
4493 data_offset,
4494 sizeof(FILE_UNIX_BASIC_INFO));
4497 cifs_buf_release(pSMB);
4498 if (rc == -EAGAIN)
4499 goto UnixQPathInfoRetry;
4501 return rc;
4504 /* xid, tcon, searchName and codepage are input parms, rest are returned */
4506 CIFSFindFirst(const unsigned int xid, struct cifs_tcon *tcon,
4507 const char *searchName, struct cifs_sb_info *cifs_sb,
4508 __u16 *pnetfid, __u16 search_flags,
4509 struct cifs_search_info *psrch_inf, bool msearch)
4511 /* level 257 SMB_ */
4512 TRANSACTION2_FFIRST_REQ *pSMB = NULL;
4513 TRANSACTION2_FFIRST_RSP *pSMBr = NULL;
4514 T2_FFIRST_RSP_PARMS *parms;
4515 int rc = 0;
4516 int bytes_returned = 0;
4517 int name_len, remap;
4518 __u16 params, byte_count;
4519 struct nls_table *nls_codepage;
4521 cifs_dbg(FYI, "In FindFirst for %s\n", searchName);
4523 findFirstRetry:
4524 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4525 (void **) &pSMBr);
4526 if (rc)
4527 return rc;
4529 nls_codepage = cifs_sb->local_nls;
4530 remap = cifs_remap(cifs_sb);
4532 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4533 name_len =
4534 cifsConvertToUTF16((__le16 *) pSMB->FileName, searchName,
4535 PATH_MAX, nls_codepage, remap);
4536 /* We can not add the asterik earlier in case
4537 it got remapped to 0xF03A as if it were part of the
4538 directory name instead of a wildcard */
4539 name_len *= 2;
4540 if (msearch) {
4541 pSMB->FileName[name_len] = CIFS_DIR_SEP(cifs_sb);
4542 pSMB->FileName[name_len+1] = 0;
4543 pSMB->FileName[name_len+2] = '*';
4544 pSMB->FileName[name_len+3] = 0;
4545 name_len += 4; /* now the trailing null */
4546 /* null terminate just in case */
4547 pSMB->FileName[name_len] = 0;
4548 pSMB->FileName[name_len+1] = 0;
4549 name_len += 2;
4551 } else {
4552 name_len = copy_path_name(pSMB->FileName, searchName);
4553 if (msearch) {
4554 if (WARN_ON_ONCE(name_len > PATH_MAX-2))
4555 name_len = PATH_MAX-2;
4556 /* overwrite nul byte */
4557 pSMB->FileName[name_len-1] = CIFS_DIR_SEP(cifs_sb);
4558 pSMB->FileName[name_len] = '*';
4559 pSMB->FileName[name_len+1] = 0;
4560 name_len += 2;
4564 params = 12 + name_len /* includes null */ ;
4565 pSMB->TotalDataCount = 0; /* no EAs */
4566 pSMB->MaxParameterCount = cpu_to_le16(10);
4567 pSMB->MaxDataCount = cpu_to_le16(CIFSMaxBufSize & 0xFFFFFF00);
4568 pSMB->MaxSetupCount = 0;
4569 pSMB->Reserved = 0;
4570 pSMB->Flags = 0;
4571 pSMB->Timeout = 0;
4572 pSMB->Reserved2 = 0;
4573 byte_count = params + 1 /* pad */ ;
4574 pSMB->TotalParameterCount = cpu_to_le16(params);
4575 pSMB->ParameterCount = pSMB->TotalParameterCount;
4576 pSMB->ParameterOffset = cpu_to_le16(
4577 offsetof(struct smb_com_transaction2_ffirst_req, SearchAttributes)
4578 - 4);
4579 pSMB->DataCount = 0;
4580 pSMB->DataOffset = 0;
4581 pSMB->SetupCount = 1; /* one byte, no need to make endian neutral */
4582 pSMB->Reserved3 = 0;
4583 pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_FIRST);
4584 pSMB->SearchAttributes =
4585 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
4586 ATTR_DIRECTORY);
4587 pSMB->SearchCount = cpu_to_le16(CIFSMaxBufSize/sizeof(FILE_UNIX_INFO));
4588 pSMB->SearchFlags = cpu_to_le16(search_flags);
4589 pSMB->InformationLevel = cpu_to_le16(psrch_inf->info_level);
4591 /* BB what should we set StorageType to? Does it matter? BB */
4592 pSMB->SearchStorageType = 0;
4593 inc_rfc1001_len(pSMB, byte_count);
4594 pSMB->ByteCount = cpu_to_le16(byte_count);
4596 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4597 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4598 cifs_stats_inc(&tcon->stats.cifs_stats.num_ffirst);
4600 if (rc) {/* BB add logic to retry regular search if Unix search
4601 rejected unexpectedly by server */
4602 /* BB Add code to handle unsupported level rc */
4603 cifs_dbg(FYI, "Error in FindFirst = %d\n", rc);
4605 cifs_buf_release(pSMB);
4607 /* BB eventually could optimize out free and realloc of buf */
4608 /* for this case */
4609 if (rc == -EAGAIN)
4610 goto findFirstRetry;
4611 } else { /* decode response */
4612 /* BB remember to free buffer if error BB */
4613 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4614 if (rc == 0) {
4615 unsigned int lnoff;
4617 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
4618 psrch_inf->unicode = true;
4619 else
4620 psrch_inf->unicode = false;
4622 psrch_inf->ntwrk_buf_start = (char *)pSMBr;
4623 psrch_inf->smallBuf = false;
4624 psrch_inf->srch_entries_start =
4625 (char *) &pSMBr->hdr.Protocol +
4626 le16_to_cpu(pSMBr->t2.DataOffset);
4627 parms = (T2_FFIRST_RSP_PARMS *)((char *) &pSMBr->hdr.Protocol +
4628 le16_to_cpu(pSMBr->t2.ParameterOffset));
4630 if (parms->EndofSearch)
4631 psrch_inf->endOfSearch = true;
4632 else
4633 psrch_inf->endOfSearch = false;
4635 psrch_inf->entries_in_buffer =
4636 le16_to_cpu(parms->SearchCount);
4637 psrch_inf->index_of_last_entry = 2 /* skip . and .. */ +
4638 psrch_inf->entries_in_buffer;
4639 lnoff = le16_to_cpu(parms->LastNameOffset);
4640 if (CIFSMaxBufSize < lnoff) {
4641 cifs_dbg(VFS, "ignoring corrupt resume name\n");
4642 psrch_inf->last_entry = NULL;
4643 return rc;
4646 psrch_inf->last_entry = psrch_inf->srch_entries_start +
4647 lnoff;
4649 if (pnetfid)
4650 *pnetfid = parms->SearchHandle;
4651 } else {
4652 cifs_buf_release(pSMB);
4656 return rc;
4659 int CIFSFindNext(const unsigned int xid, struct cifs_tcon *tcon,
4660 __u16 searchHandle, __u16 search_flags,
4661 struct cifs_search_info *psrch_inf)
4663 TRANSACTION2_FNEXT_REQ *pSMB = NULL;
4664 TRANSACTION2_FNEXT_RSP *pSMBr = NULL;
4665 T2_FNEXT_RSP_PARMS *parms;
4666 char *response_data;
4667 int rc = 0;
4668 int bytes_returned;
4669 unsigned int name_len;
4670 __u16 params, byte_count;
4672 cifs_dbg(FYI, "In FindNext\n");
4674 if (psrch_inf->endOfSearch)
4675 return -ENOENT;
4677 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4678 (void **) &pSMBr);
4679 if (rc)
4680 return rc;
4682 params = 14; /* includes 2 bytes of null string, converted to LE below*/
4683 byte_count = 0;
4684 pSMB->TotalDataCount = 0; /* no EAs */
4685 pSMB->MaxParameterCount = cpu_to_le16(8);
4686 pSMB->MaxDataCount = cpu_to_le16(CIFSMaxBufSize & 0xFFFFFF00);
4687 pSMB->MaxSetupCount = 0;
4688 pSMB->Reserved = 0;
4689 pSMB->Flags = 0;
4690 pSMB->Timeout = 0;
4691 pSMB->Reserved2 = 0;
4692 pSMB->ParameterOffset = cpu_to_le16(
4693 offsetof(struct smb_com_transaction2_fnext_req,SearchHandle) - 4);
4694 pSMB->DataCount = 0;
4695 pSMB->DataOffset = 0;
4696 pSMB->SetupCount = 1;
4697 pSMB->Reserved3 = 0;
4698 pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_NEXT);
4699 pSMB->SearchHandle = searchHandle; /* always kept as le */
4700 pSMB->SearchCount =
4701 cpu_to_le16(CIFSMaxBufSize / sizeof(FILE_UNIX_INFO));
4702 pSMB->InformationLevel = cpu_to_le16(psrch_inf->info_level);
4703 pSMB->ResumeKey = psrch_inf->resume_key;
4704 pSMB->SearchFlags = cpu_to_le16(search_flags);
4706 name_len = psrch_inf->resume_name_len;
4707 params += name_len;
4708 if (name_len < PATH_MAX) {
4709 memcpy(pSMB->ResumeFileName, psrch_inf->presume_name, name_len);
4710 byte_count += name_len;
4711 /* 14 byte parm len above enough for 2 byte null terminator */
4712 pSMB->ResumeFileName[name_len] = 0;
4713 pSMB->ResumeFileName[name_len+1] = 0;
4714 } else {
4715 rc = -EINVAL;
4716 goto FNext2_err_exit;
4718 byte_count = params + 1 /* pad */ ;
4719 pSMB->TotalParameterCount = cpu_to_le16(params);
4720 pSMB->ParameterCount = pSMB->TotalParameterCount;
4721 inc_rfc1001_len(pSMB, byte_count);
4722 pSMB->ByteCount = cpu_to_le16(byte_count);
4724 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4725 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4726 cifs_stats_inc(&tcon->stats.cifs_stats.num_fnext);
4727 if (rc) {
4728 if (rc == -EBADF) {
4729 psrch_inf->endOfSearch = true;
4730 cifs_buf_release(pSMB);
4731 rc = 0; /* search probably was closed at end of search*/
4732 } else
4733 cifs_dbg(FYI, "FindNext returned = %d\n", rc);
4734 } else { /* decode response */
4735 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4737 if (rc == 0) {
4738 unsigned int lnoff;
4740 /* BB fixme add lock for file (srch_info) struct here */
4741 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
4742 psrch_inf->unicode = true;
4743 else
4744 psrch_inf->unicode = false;
4745 response_data = (char *) &pSMBr->hdr.Protocol +
4746 le16_to_cpu(pSMBr->t2.ParameterOffset);
4747 parms = (T2_FNEXT_RSP_PARMS *)response_data;
4748 response_data = (char *)&pSMBr->hdr.Protocol +
4749 le16_to_cpu(pSMBr->t2.DataOffset);
4750 if (psrch_inf->smallBuf)
4751 cifs_small_buf_release(
4752 psrch_inf->ntwrk_buf_start);
4753 else
4754 cifs_buf_release(psrch_inf->ntwrk_buf_start);
4755 psrch_inf->srch_entries_start = response_data;
4756 psrch_inf->ntwrk_buf_start = (char *)pSMB;
4757 psrch_inf->smallBuf = false;
4758 if (parms->EndofSearch)
4759 psrch_inf->endOfSearch = true;
4760 else
4761 psrch_inf->endOfSearch = false;
4762 psrch_inf->entries_in_buffer =
4763 le16_to_cpu(parms->SearchCount);
4764 psrch_inf->index_of_last_entry +=
4765 psrch_inf->entries_in_buffer;
4766 lnoff = le16_to_cpu(parms->LastNameOffset);
4767 if (CIFSMaxBufSize < lnoff) {
4768 cifs_dbg(VFS, "ignoring corrupt resume name\n");
4769 psrch_inf->last_entry = NULL;
4770 return rc;
4771 } else
4772 psrch_inf->last_entry =
4773 psrch_inf->srch_entries_start + lnoff;
4775 /* cifs_dbg(FYI, "fnxt2 entries in buf %d index_of_last %d\n",
4776 psrch_inf->entries_in_buffer, psrch_inf->index_of_last_entry); */
4778 /* BB fixme add unlock here */
4783 /* BB On error, should we leave previous search buf (and count and
4784 last entry fields) intact or free the previous one? */
4786 /* Note: On -EAGAIN error only caller can retry on handle based calls
4787 since file handle passed in no longer valid */
4788 FNext2_err_exit:
4789 if (rc != 0)
4790 cifs_buf_release(pSMB);
4791 return rc;
4795 CIFSFindClose(const unsigned int xid, struct cifs_tcon *tcon,
4796 const __u16 searchHandle)
4798 int rc = 0;
4799 FINDCLOSE_REQ *pSMB = NULL;
4801 cifs_dbg(FYI, "In CIFSSMBFindClose\n");
4802 rc = small_smb_init(SMB_COM_FIND_CLOSE2, 1, tcon, (void **)&pSMB);
4804 /* no sense returning error if session restarted
4805 as file handle has been closed */
4806 if (rc == -EAGAIN)
4807 return 0;
4808 if (rc)
4809 return rc;
4811 pSMB->FileID = searchHandle;
4812 pSMB->ByteCount = 0;
4813 rc = SendReceiveNoRsp(xid, tcon->ses, (char *) pSMB, 0);
4814 cifs_small_buf_release(pSMB);
4815 if (rc)
4816 cifs_dbg(VFS, "Send error in FindClose = %d\n", rc);
4818 cifs_stats_inc(&tcon->stats.cifs_stats.num_fclose);
4820 /* Since session is dead, search handle closed on server already */
4821 if (rc == -EAGAIN)
4822 rc = 0;
4824 return rc;
4828 CIFSGetSrvInodeNumber(const unsigned int xid, struct cifs_tcon *tcon,
4829 const char *search_name, __u64 *inode_number,
4830 const struct nls_table *nls_codepage, int remap)
4832 int rc = 0;
4833 TRANSACTION2_QPI_REQ *pSMB = NULL;
4834 TRANSACTION2_QPI_RSP *pSMBr = NULL;
4835 int name_len, bytes_returned;
4836 __u16 params, byte_count;
4838 cifs_dbg(FYI, "In GetSrvInodeNum for %s\n", search_name);
4839 if (tcon == NULL)
4840 return -ENODEV;
4842 GetInodeNumberRetry:
4843 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4844 (void **) &pSMBr);
4845 if (rc)
4846 return rc;
4848 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4849 name_len =
4850 cifsConvertToUTF16((__le16 *) pSMB->FileName,
4851 search_name, PATH_MAX, nls_codepage,
4852 remap);
4853 name_len++; /* trailing null */
4854 name_len *= 2;
4855 } else {
4856 name_len = copy_path_name(pSMB->FileName, search_name);
4859 params = 2 /* level */ + 4 /* rsrvd */ + name_len /* incl null */ ;
4860 pSMB->TotalDataCount = 0;
4861 pSMB->MaxParameterCount = cpu_to_le16(2);
4862 /* BB find exact max data count below from sess structure BB */
4863 pSMB->MaxDataCount = cpu_to_le16(4000);
4864 pSMB->MaxSetupCount = 0;
4865 pSMB->Reserved = 0;
4866 pSMB->Flags = 0;
4867 pSMB->Timeout = 0;
4868 pSMB->Reserved2 = 0;
4869 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4870 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
4871 pSMB->DataCount = 0;
4872 pSMB->DataOffset = 0;
4873 pSMB->SetupCount = 1;
4874 pSMB->Reserved3 = 0;
4875 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
4876 byte_count = params + 1 /* pad */ ;
4877 pSMB->TotalParameterCount = cpu_to_le16(params);
4878 pSMB->ParameterCount = pSMB->TotalParameterCount;
4879 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_INTERNAL_INFO);
4880 pSMB->Reserved4 = 0;
4881 inc_rfc1001_len(pSMB, byte_count);
4882 pSMB->ByteCount = cpu_to_le16(byte_count);
4884 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4885 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4886 if (rc) {
4887 cifs_dbg(FYI, "error %d in QueryInternalInfo\n", rc);
4888 } else {
4889 /* decode response */
4890 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4891 /* BB also check enough total bytes returned */
4892 if (rc || get_bcc(&pSMBr->hdr) < 2)
4893 /* If rc should we check for EOPNOSUPP and
4894 disable the srvino flag? or in caller? */
4895 rc = -EIO; /* bad smb */
4896 else {
4897 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4898 __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
4899 struct file_internal_info *pfinfo;
4900 /* BB Do we need a cast or hash here ? */
4901 if (count < 8) {
4902 cifs_dbg(FYI, "Illegal size ret in QryIntrnlInf\n");
4903 rc = -EIO;
4904 goto GetInodeNumOut;
4906 pfinfo = (struct file_internal_info *)
4907 (data_offset + (char *) &pSMBr->hdr.Protocol);
4908 *inode_number = le64_to_cpu(pfinfo->UniqueId);
4911 GetInodeNumOut:
4912 cifs_buf_release(pSMB);
4913 if (rc == -EAGAIN)
4914 goto GetInodeNumberRetry;
4915 return rc;
4919 CIFSGetDFSRefer(const unsigned int xid, struct cifs_ses *ses,
4920 const char *search_name, struct dfs_info3_param **target_nodes,
4921 unsigned int *num_of_nodes,
4922 const struct nls_table *nls_codepage, int remap)
4924 /* TRANS2_GET_DFS_REFERRAL */
4925 TRANSACTION2_GET_DFS_REFER_REQ *pSMB = NULL;
4926 TRANSACTION2_GET_DFS_REFER_RSP *pSMBr = NULL;
4927 int rc = 0;
4928 int bytes_returned;
4929 int name_len;
4930 __u16 params, byte_count;
4931 *num_of_nodes = 0;
4932 *target_nodes = NULL;
4934 cifs_dbg(FYI, "In GetDFSRefer the path %s\n", search_name);
4935 if (ses == NULL || ses->tcon_ipc == NULL)
4936 return -ENODEV;
4938 getDFSRetry:
4939 rc = smb_init(SMB_COM_TRANSACTION2, 15, ses->tcon_ipc, (void **) &pSMB,
4940 (void **) &pSMBr);
4941 if (rc)
4942 return rc;
4944 /* server pointer checked in called function,
4945 but should never be null here anyway */
4946 pSMB->hdr.Mid = get_next_mid(ses->server);
4947 pSMB->hdr.Tid = ses->tcon_ipc->tid;
4948 pSMB->hdr.Uid = ses->Suid;
4949 if (ses->capabilities & CAP_STATUS32)
4950 pSMB->hdr.Flags2 |= SMBFLG2_ERR_STATUS;
4951 if (ses->capabilities & CAP_DFS)
4952 pSMB->hdr.Flags2 |= SMBFLG2_DFS;
4954 if (ses->capabilities & CAP_UNICODE) {
4955 pSMB->hdr.Flags2 |= SMBFLG2_UNICODE;
4956 name_len =
4957 cifsConvertToUTF16((__le16 *) pSMB->RequestFileName,
4958 search_name, PATH_MAX, nls_codepage,
4959 remap);
4960 name_len++; /* trailing null */
4961 name_len *= 2;
4962 } else { /* BB improve the check for buffer overruns BB */
4963 name_len = copy_path_name(pSMB->RequestFileName, search_name);
4966 if (ses->server->sign)
4967 pSMB->hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
4969 pSMB->hdr.Uid = ses->Suid;
4971 params = 2 /* level */ + name_len /*includes null */ ;
4972 pSMB->TotalDataCount = 0;
4973 pSMB->DataCount = 0;
4974 pSMB->DataOffset = 0;
4975 pSMB->MaxParameterCount = 0;
4976 /* BB find exact max SMB PDU from sess structure BB */
4977 pSMB->MaxDataCount = cpu_to_le16(4000);
4978 pSMB->MaxSetupCount = 0;
4979 pSMB->Reserved = 0;
4980 pSMB->Flags = 0;
4981 pSMB->Timeout = 0;
4982 pSMB->Reserved2 = 0;
4983 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4984 struct smb_com_transaction2_get_dfs_refer_req, MaxReferralLevel) - 4);
4985 pSMB->SetupCount = 1;
4986 pSMB->Reserved3 = 0;
4987 pSMB->SubCommand = cpu_to_le16(TRANS2_GET_DFS_REFERRAL);
4988 byte_count = params + 3 /* pad */ ;
4989 pSMB->ParameterCount = cpu_to_le16(params);
4990 pSMB->TotalParameterCount = pSMB->ParameterCount;
4991 pSMB->MaxReferralLevel = cpu_to_le16(3);
4992 inc_rfc1001_len(pSMB, byte_count);
4993 pSMB->ByteCount = cpu_to_le16(byte_count);
4995 rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB,
4996 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4997 if (rc) {
4998 cifs_dbg(FYI, "Send error in GetDFSRefer = %d\n", rc);
4999 goto GetDFSRefExit;
5001 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
5003 /* BB Also check if enough total bytes returned? */
5004 if (rc || get_bcc(&pSMBr->hdr) < 17) {
5005 rc = -EIO; /* bad smb */
5006 goto GetDFSRefExit;
5009 cifs_dbg(FYI, "Decoding GetDFSRefer response BCC: %d Offset %d\n",
5010 get_bcc(&pSMBr->hdr), le16_to_cpu(pSMBr->t2.DataOffset));
5012 /* parse returned result into more usable form */
5013 rc = parse_dfs_referrals(&pSMBr->dfs_data,
5014 le16_to_cpu(pSMBr->t2.DataCount),
5015 num_of_nodes, target_nodes, nls_codepage,
5016 remap, search_name,
5017 (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) != 0);
5019 GetDFSRefExit:
5020 cifs_buf_release(pSMB);
5022 if (rc == -EAGAIN)
5023 goto getDFSRetry;
5025 return rc;
5028 /* Query File System Info such as free space to old servers such as Win 9x */
5030 SMBOldQFSInfo(const unsigned int xid, struct cifs_tcon *tcon,
5031 struct kstatfs *FSData)
5033 /* level 0x01 SMB_QUERY_FILE_SYSTEM_INFO */
5034 TRANSACTION2_QFSI_REQ *pSMB = NULL;
5035 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
5036 FILE_SYSTEM_ALLOC_INFO *response_data;
5037 int rc = 0;
5038 int bytes_returned = 0;
5039 __u16 params, byte_count;
5041 cifs_dbg(FYI, "OldQFSInfo\n");
5042 oldQFSInfoRetry:
5043 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5044 (void **) &pSMBr);
5045 if (rc)
5046 return rc;
5048 params = 2; /* level */
5049 pSMB->TotalDataCount = 0;
5050 pSMB->MaxParameterCount = cpu_to_le16(2);
5051 pSMB->MaxDataCount = cpu_to_le16(1000);
5052 pSMB->MaxSetupCount = 0;
5053 pSMB->Reserved = 0;
5054 pSMB->Flags = 0;
5055 pSMB->Timeout = 0;
5056 pSMB->Reserved2 = 0;
5057 byte_count = params + 1 /* pad */ ;
5058 pSMB->TotalParameterCount = cpu_to_le16(params);
5059 pSMB->ParameterCount = pSMB->TotalParameterCount;
5060 pSMB->ParameterOffset = cpu_to_le16(offsetof(
5061 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
5062 pSMB->DataCount = 0;
5063 pSMB->DataOffset = 0;
5064 pSMB->SetupCount = 1;
5065 pSMB->Reserved3 = 0;
5066 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
5067 pSMB->InformationLevel = cpu_to_le16(SMB_INFO_ALLOCATION);
5068 inc_rfc1001_len(pSMB, 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);
5073 if (rc) {
5074 cifs_dbg(FYI, "Send error in QFSInfo = %d\n", rc);
5075 } else { /* decode response */
5076 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
5078 if (rc || get_bcc(&pSMBr->hdr) < 18)
5079 rc = -EIO; /* bad smb */
5080 else {
5081 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
5082 cifs_dbg(FYI, "qfsinf resp BCC: %d Offset %d\n",
5083 get_bcc(&pSMBr->hdr), data_offset);
5085 response_data = (FILE_SYSTEM_ALLOC_INFO *)
5086 (((char *) &pSMBr->hdr.Protocol) + data_offset);
5087 FSData->f_bsize =
5088 le16_to_cpu(response_data->BytesPerSector) *
5089 le32_to_cpu(response_data->
5090 SectorsPerAllocationUnit);
5092 * much prefer larger but if server doesn't report
5093 * a valid size than 4K is a reasonable minimum
5095 if (FSData->f_bsize < 512)
5096 FSData->f_bsize = 4096;
5098 FSData->f_blocks =
5099 le32_to_cpu(response_data->TotalAllocationUnits);
5100 FSData->f_bfree = FSData->f_bavail =
5101 le32_to_cpu(response_data->FreeAllocationUnits);
5102 cifs_dbg(FYI, "Blocks: %lld Free: %lld Block size %ld\n",
5103 (unsigned long long)FSData->f_blocks,
5104 (unsigned long long)FSData->f_bfree,
5105 FSData->f_bsize);
5108 cifs_buf_release(pSMB);
5110 if (rc == -EAGAIN)
5111 goto oldQFSInfoRetry;
5113 return rc;
5117 CIFSSMBQFSInfo(const unsigned int xid, struct cifs_tcon *tcon,
5118 struct kstatfs *FSData)
5120 /* level 0x103 SMB_QUERY_FILE_SYSTEM_INFO */
5121 TRANSACTION2_QFSI_REQ *pSMB = NULL;
5122 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
5123 FILE_SYSTEM_INFO *response_data;
5124 int rc = 0;
5125 int bytes_returned = 0;
5126 __u16 params, byte_count;
5128 cifs_dbg(FYI, "In QFSInfo\n");
5129 QFSInfoRetry:
5130 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5131 (void **) &pSMBr);
5132 if (rc)
5133 return rc;
5135 params = 2; /* level */
5136 pSMB->TotalDataCount = 0;
5137 pSMB->MaxParameterCount = cpu_to_le16(2);
5138 pSMB->MaxDataCount = cpu_to_le16(1000);
5139 pSMB->MaxSetupCount = 0;
5140 pSMB->Reserved = 0;
5141 pSMB->Flags = 0;
5142 pSMB->Timeout = 0;
5143 pSMB->Reserved2 = 0;
5144 byte_count = params + 1 /* pad */ ;
5145 pSMB->TotalParameterCount = cpu_to_le16(params);
5146 pSMB->ParameterCount = pSMB->TotalParameterCount;
5147 pSMB->ParameterOffset = cpu_to_le16(offsetof(
5148 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
5149 pSMB->DataCount = 0;
5150 pSMB->DataOffset = 0;
5151 pSMB->SetupCount = 1;
5152 pSMB->Reserved3 = 0;
5153 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
5154 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_SIZE_INFO);
5155 inc_rfc1001_len(pSMB, byte_count);
5156 pSMB->ByteCount = cpu_to_le16(byte_count);
5158 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5159 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5160 if (rc) {
5161 cifs_dbg(FYI, "Send error in QFSInfo = %d\n", rc);
5162 } else { /* decode response */
5163 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
5165 if (rc || get_bcc(&pSMBr->hdr) < 24)
5166 rc = -EIO; /* bad smb */
5167 else {
5168 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
5170 response_data =
5171 (FILE_SYSTEM_INFO
5172 *) (((char *) &pSMBr->hdr.Protocol) +
5173 data_offset);
5174 FSData->f_bsize =
5175 le32_to_cpu(response_data->BytesPerSector) *
5176 le32_to_cpu(response_data->
5177 SectorsPerAllocationUnit);
5179 * much prefer larger but if server doesn't report
5180 * a valid size than 4K is a reasonable minimum
5182 if (FSData->f_bsize < 512)
5183 FSData->f_bsize = 4096;
5185 FSData->f_blocks =
5186 le64_to_cpu(response_data->TotalAllocationUnits);
5187 FSData->f_bfree = FSData->f_bavail =
5188 le64_to_cpu(response_data->FreeAllocationUnits);
5189 cifs_dbg(FYI, "Blocks: %lld Free: %lld Block size %ld\n",
5190 (unsigned long long)FSData->f_blocks,
5191 (unsigned long long)FSData->f_bfree,
5192 FSData->f_bsize);
5195 cifs_buf_release(pSMB);
5197 if (rc == -EAGAIN)
5198 goto QFSInfoRetry;
5200 return rc;
5204 CIFSSMBQFSAttributeInfo(const unsigned int xid, struct cifs_tcon *tcon)
5206 /* level 0x105 SMB_QUERY_FILE_SYSTEM_INFO */
5207 TRANSACTION2_QFSI_REQ *pSMB = NULL;
5208 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
5209 FILE_SYSTEM_ATTRIBUTE_INFO *response_data;
5210 int rc = 0;
5211 int bytes_returned = 0;
5212 __u16 params, byte_count;
5214 cifs_dbg(FYI, "In QFSAttributeInfo\n");
5215 QFSAttributeRetry:
5216 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5217 (void **) &pSMBr);
5218 if (rc)
5219 return rc;
5221 params = 2; /* level */
5222 pSMB->TotalDataCount = 0;
5223 pSMB->MaxParameterCount = cpu_to_le16(2);
5224 /* BB find exact max SMB PDU from sess structure BB */
5225 pSMB->MaxDataCount = cpu_to_le16(1000);
5226 pSMB->MaxSetupCount = 0;
5227 pSMB->Reserved = 0;
5228 pSMB->Flags = 0;
5229 pSMB->Timeout = 0;
5230 pSMB->Reserved2 = 0;
5231 byte_count = params + 1 /* pad */ ;
5232 pSMB->TotalParameterCount = cpu_to_le16(params);
5233 pSMB->ParameterCount = pSMB->TotalParameterCount;
5234 pSMB->ParameterOffset = cpu_to_le16(offsetof(
5235 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
5236 pSMB->DataCount = 0;
5237 pSMB->DataOffset = 0;
5238 pSMB->SetupCount = 1;
5239 pSMB->Reserved3 = 0;
5240 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
5241 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_ATTRIBUTE_INFO);
5242 inc_rfc1001_len(pSMB, byte_count);
5243 pSMB->ByteCount = cpu_to_le16(byte_count);
5245 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5246 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5247 if (rc) {
5248 cifs_dbg(VFS, "Send error in QFSAttributeInfo = %d\n", rc);
5249 } else { /* decode response */
5250 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
5252 if (rc || get_bcc(&pSMBr->hdr) < 13) {
5253 /* BB also check if enough bytes returned */
5254 rc = -EIO; /* bad smb */
5255 } else {
5256 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
5257 response_data =
5258 (FILE_SYSTEM_ATTRIBUTE_INFO
5259 *) (((char *) &pSMBr->hdr.Protocol) +
5260 data_offset);
5261 memcpy(&tcon->fsAttrInfo, response_data,
5262 sizeof(FILE_SYSTEM_ATTRIBUTE_INFO));
5265 cifs_buf_release(pSMB);
5267 if (rc == -EAGAIN)
5268 goto QFSAttributeRetry;
5270 return rc;
5274 CIFSSMBQFSDeviceInfo(const unsigned int xid, struct cifs_tcon *tcon)
5276 /* level 0x104 SMB_QUERY_FILE_SYSTEM_INFO */
5277 TRANSACTION2_QFSI_REQ *pSMB = NULL;
5278 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
5279 FILE_SYSTEM_DEVICE_INFO *response_data;
5280 int rc = 0;
5281 int bytes_returned = 0;
5282 __u16 params, byte_count;
5284 cifs_dbg(FYI, "In QFSDeviceInfo\n");
5285 QFSDeviceRetry:
5286 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5287 (void **) &pSMBr);
5288 if (rc)
5289 return rc;
5291 params = 2; /* level */
5292 pSMB->TotalDataCount = 0;
5293 pSMB->MaxParameterCount = cpu_to_le16(2);
5294 /* BB find exact max SMB PDU from sess structure BB */
5295 pSMB->MaxDataCount = cpu_to_le16(1000);
5296 pSMB->MaxSetupCount = 0;
5297 pSMB->Reserved = 0;
5298 pSMB->Flags = 0;
5299 pSMB->Timeout = 0;
5300 pSMB->Reserved2 = 0;
5301 byte_count = params + 1 /* pad */ ;
5302 pSMB->TotalParameterCount = cpu_to_le16(params);
5303 pSMB->ParameterCount = pSMB->TotalParameterCount;
5304 pSMB->ParameterOffset = cpu_to_le16(offsetof(
5305 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
5307 pSMB->DataCount = 0;
5308 pSMB->DataOffset = 0;
5309 pSMB->SetupCount = 1;
5310 pSMB->Reserved3 = 0;
5311 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
5312 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_DEVICE_INFO);
5313 inc_rfc1001_len(pSMB, byte_count);
5314 pSMB->ByteCount = cpu_to_le16(byte_count);
5316 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5317 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5318 if (rc) {
5319 cifs_dbg(FYI, "Send error in QFSDeviceInfo = %d\n", rc);
5320 } else { /* decode response */
5321 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
5323 if (rc || get_bcc(&pSMBr->hdr) <
5324 sizeof(FILE_SYSTEM_DEVICE_INFO))
5325 rc = -EIO; /* bad smb */
5326 else {
5327 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
5328 response_data =
5329 (FILE_SYSTEM_DEVICE_INFO *)
5330 (((char *) &pSMBr->hdr.Protocol) +
5331 data_offset);
5332 memcpy(&tcon->fsDevInfo, response_data,
5333 sizeof(FILE_SYSTEM_DEVICE_INFO));
5336 cifs_buf_release(pSMB);
5338 if (rc == -EAGAIN)
5339 goto QFSDeviceRetry;
5341 return rc;
5345 CIFSSMBQFSUnixInfo(const unsigned int xid, struct cifs_tcon *tcon)
5347 /* level 0x200 SMB_QUERY_CIFS_UNIX_INFO */
5348 TRANSACTION2_QFSI_REQ *pSMB = NULL;
5349 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
5350 FILE_SYSTEM_UNIX_INFO *response_data;
5351 int rc = 0;
5352 int bytes_returned = 0;
5353 __u16 params, byte_count;
5355 cifs_dbg(FYI, "In QFSUnixInfo\n");
5356 QFSUnixRetry:
5357 rc = smb_init_no_reconnect(SMB_COM_TRANSACTION2, 15, tcon,
5358 (void **) &pSMB, (void **) &pSMBr);
5359 if (rc)
5360 return rc;
5362 params = 2; /* level */
5363 pSMB->TotalDataCount = 0;
5364 pSMB->DataCount = 0;
5365 pSMB->DataOffset = 0;
5366 pSMB->MaxParameterCount = cpu_to_le16(2);
5367 /* BB find exact max SMB PDU from sess structure BB */
5368 pSMB->MaxDataCount = cpu_to_le16(100);
5369 pSMB->MaxSetupCount = 0;
5370 pSMB->Reserved = 0;
5371 pSMB->Flags = 0;
5372 pSMB->Timeout = 0;
5373 pSMB->Reserved2 = 0;
5374 byte_count = params + 1 /* pad */ ;
5375 pSMB->ParameterCount = cpu_to_le16(params);
5376 pSMB->TotalParameterCount = pSMB->ParameterCount;
5377 pSMB->ParameterOffset = cpu_to_le16(offsetof(struct
5378 smb_com_transaction2_qfsi_req, InformationLevel) - 4);
5379 pSMB->SetupCount = 1;
5380 pSMB->Reserved3 = 0;
5381 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
5382 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_CIFS_UNIX_INFO);
5383 inc_rfc1001_len(pSMB, byte_count);
5384 pSMB->ByteCount = cpu_to_le16(byte_count);
5386 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5387 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5388 if (rc) {
5389 cifs_dbg(VFS, "Send error in QFSUnixInfo = %d\n", rc);
5390 } else { /* decode response */
5391 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
5393 if (rc || get_bcc(&pSMBr->hdr) < 13) {
5394 rc = -EIO; /* bad smb */
5395 } else {
5396 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
5397 response_data =
5398 (FILE_SYSTEM_UNIX_INFO
5399 *) (((char *) &pSMBr->hdr.Protocol) +
5400 data_offset);
5401 memcpy(&tcon->fsUnixInfo, response_data,
5402 sizeof(FILE_SYSTEM_UNIX_INFO));
5405 cifs_buf_release(pSMB);
5407 if (rc == -EAGAIN)
5408 goto QFSUnixRetry;
5411 return rc;
5415 CIFSSMBSetFSUnixInfo(const unsigned int xid, struct cifs_tcon *tcon, __u64 cap)
5417 /* level 0x200 SMB_SET_CIFS_UNIX_INFO */
5418 TRANSACTION2_SETFSI_REQ *pSMB = NULL;
5419 TRANSACTION2_SETFSI_RSP *pSMBr = NULL;
5420 int rc = 0;
5421 int bytes_returned = 0;
5422 __u16 params, param_offset, offset, byte_count;
5424 cifs_dbg(FYI, "In SETFSUnixInfo\n");
5425 SETFSUnixRetry:
5426 /* BB switch to small buf init to save memory */
5427 rc = smb_init_no_reconnect(SMB_COM_TRANSACTION2, 15, tcon,
5428 (void **) &pSMB, (void **) &pSMBr);
5429 if (rc)
5430 return rc;
5432 params = 4; /* 2 bytes zero followed by info level. */
5433 pSMB->MaxSetupCount = 0;
5434 pSMB->Reserved = 0;
5435 pSMB->Flags = 0;
5436 pSMB->Timeout = 0;
5437 pSMB->Reserved2 = 0;
5438 param_offset = offsetof(struct smb_com_transaction2_setfsi_req, FileNum)
5439 - 4;
5440 offset = param_offset + params;
5442 pSMB->MaxParameterCount = cpu_to_le16(4);
5443 /* BB find exact max SMB PDU from sess structure BB */
5444 pSMB->MaxDataCount = cpu_to_le16(100);
5445 pSMB->SetupCount = 1;
5446 pSMB->Reserved3 = 0;
5447 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FS_INFORMATION);
5448 byte_count = 1 /* pad */ + params + 12;
5450 pSMB->DataCount = cpu_to_le16(12);
5451 pSMB->ParameterCount = cpu_to_le16(params);
5452 pSMB->TotalDataCount = pSMB->DataCount;
5453 pSMB->TotalParameterCount = pSMB->ParameterCount;
5454 pSMB->ParameterOffset = cpu_to_le16(param_offset);
5455 pSMB->DataOffset = cpu_to_le16(offset);
5457 /* Params. */
5458 pSMB->FileNum = 0;
5459 pSMB->InformationLevel = cpu_to_le16(SMB_SET_CIFS_UNIX_INFO);
5461 /* Data. */
5462 pSMB->ClientUnixMajor = cpu_to_le16(CIFS_UNIX_MAJOR_VERSION);
5463 pSMB->ClientUnixMinor = cpu_to_le16(CIFS_UNIX_MINOR_VERSION);
5464 pSMB->ClientUnixCap = cpu_to_le64(cap);
5466 inc_rfc1001_len(pSMB, byte_count);
5467 pSMB->ByteCount = cpu_to_le16(byte_count);
5469 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5470 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5471 if (rc) {
5472 cifs_dbg(VFS, "Send error in SETFSUnixInfo = %d\n", rc);
5473 } else { /* decode response */
5474 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
5475 if (rc)
5476 rc = -EIO; /* bad smb */
5478 cifs_buf_release(pSMB);
5480 if (rc == -EAGAIN)
5481 goto SETFSUnixRetry;
5483 return rc;
5489 CIFSSMBQFSPosixInfo(const unsigned int xid, struct cifs_tcon *tcon,
5490 struct kstatfs *FSData)
5492 /* level 0x201 SMB_QUERY_CIFS_POSIX_INFO */
5493 TRANSACTION2_QFSI_REQ *pSMB = NULL;
5494 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
5495 FILE_SYSTEM_POSIX_INFO *response_data;
5496 int rc = 0;
5497 int bytes_returned = 0;
5498 __u16 params, byte_count;
5500 cifs_dbg(FYI, "In QFSPosixInfo\n");
5501 QFSPosixRetry:
5502 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5503 (void **) &pSMBr);
5504 if (rc)
5505 return rc;
5507 params = 2; /* level */
5508 pSMB->TotalDataCount = 0;
5509 pSMB->DataCount = 0;
5510 pSMB->DataOffset = 0;
5511 pSMB->MaxParameterCount = cpu_to_le16(2);
5512 /* BB find exact max SMB PDU from sess structure BB */
5513 pSMB->MaxDataCount = cpu_to_le16(100);
5514 pSMB->MaxSetupCount = 0;
5515 pSMB->Reserved = 0;
5516 pSMB->Flags = 0;
5517 pSMB->Timeout = 0;
5518 pSMB->Reserved2 = 0;
5519 byte_count = params + 1 /* pad */ ;
5520 pSMB->ParameterCount = cpu_to_le16(params);
5521 pSMB->TotalParameterCount = pSMB->ParameterCount;
5522 pSMB->ParameterOffset = cpu_to_le16(offsetof(struct
5523 smb_com_transaction2_qfsi_req, InformationLevel) - 4);
5524 pSMB->SetupCount = 1;
5525 pSMB->Reserved3 = 0;
5526 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
5527 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_POSIX_FS_INFO);
5528 inc_rfc1001_len(pSMB, byte_count);
5529 pSMB->ByteCount = cpu_to_le16(byte_count);
5531 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5532 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5533 if (rc) {
5534 cifs_dbg(FYI, "Send error in QFSUnixInfo = %d\n", rc);
5535 } else { /* decode response */
5536 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
5538 if (rc || get_bcc(&pSMBr->hdr) < 13) {
5539 rc = -EIO; /* bad smb */
5540 } else {
5541 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
5542 response_data =
5543 (FILE_SYSTEM_POSIX_INFO
5544 *) (((char *) &pSMBr->hdr.Protocol) +
5545 data_offset);
5546 FSData->f_bsize =
5547 le32_to_cpu(response_data->BlockSize);
5549 * much prefer larger but if server doesn't report
5550 * a valid size than 4K is a reasonable minimum
5552 if (FSData->f_bsize < 512)
5553 FSData->f_bsize = 4096;
5555 FSData->f_blocks =
5556 le64_to_cpu(response_data->TotalBlocks);
5557 FSData->f_bfree =
5558 le64_to_cpu(response_data->BlocksAvail);
5559 if (response_data->UserBlocksAvail == cpu_to_le64(-1)) {
5560 FSData->f_bavail = FSData->f_bfree;
5561 } else {
5562 FSData->f_bavail =
5563 le64_to_cpu(response_data->UserBlocksAvail);
5565 if (response_data->TotalFileNodes != cpu_to_le64(-1))
5566 FSData->f_files =
5567 le64_to_cpu(response_data->TotalFileNodes);
5568 if (response_data->FreeFileNodes != cpu_to_le64(-1))
5569 FSData->f_ffree =
5570 le64_to_cpu(response_data->FreeFileNodes);
5573 cifs_buf_release(pSMB);
5575 if (rc == -EAGAIN)
5576 goto QFSPosixRetry;
5578 return rc;
5583 * We can not use write of zero bytes trick to set file size due to need for
5584 * large file support. Also note that this SetPathInfo is preferred to
5585 * SetFileInfo based method in next routine which is only needed to work around
5586 * a sharing violation bugin Samba which this routine can run into.
5589 CIFSSMBSetEOF(const unsigned int xid, struct cifs_tcon *tcon,
5590 const char *file_name, __u64 size, struct cifs_sb_info *cifs_sb,
5591 bool set_allocation)
5593 struct smb_com_transaction2_spi_req *pSMB = NULL;
5594 struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
5595 struct file_end_of_file_info *parm_data;
5596 int name_len;
5597 int rc = 0;
5598 int bytes_returned = 0;
5599 int remap = cifs_remap(cifs_sb);
5601 __u16 params, byte_count, data_count, param_offset, offset;
5603 cifs_dbg(FYI, "In SetEOF\n");
5604 SetEOFRetry:
5605 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5606 (void **) &pSMBr);
5607 if (rc)
5608 return rc;
5610 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5611 name_len =
5612 cifsConvertToUTF16((__le16 *) pSMB->FileName, file_name,
5613 PATH_MAX, cifs_sb->local_nls, remap);
5614 name_len++; /* trailing null */
5615 name_len *= 2;
5616 } else {
5617 name_len = copy_path_name(pSMB->FileName, file_name);
5619 params = 6 + name_len;
5620 data_count = sizeof(struct file_end_of_file_info);
5621 pSMB->MaxParameterCount = cpu_to_le16(2);
5622 pSMB->MaxDataCount = cpu_to_le16(4100);
5623 pSMB->MaxSetupCount = 0;
5624 pSMB->Reserved = 0;
5625 pSMB->Flags = 0;
5626 pSMB->Timeout = 0;
5627 pSMB->Reserved2 = 0;
5628 param_offset = offsetof(struct smb_com_transaction2_spi_req,
5629 InformationLevel) - 4;
5630 offset = param_offset + params;
5631 if (set_allocation) {
5632 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
5633 pSMB->InformationLevel =
5634 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2);
5635 else
5636 pSMB->InformationLevel =
5637 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO);
5638 } else /* Set File Size */ {
5639 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
5640 pSMB->InformationLevel =
5641 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO2);
5642 else
5643 pSMB->InformationLevel =
5644 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO);
5647 parm_data =
5648 (struct file_end_of_file_info *) (((char *) &pSMB->hdr.Protocol) +
5649 offset);
5650 pSMB->ParameterOffset = cpu_to_le16(param_offset);
5651 pSMB->DataOffset = cpu_to_le16(offset);
5652 pSMB->SetupCount = 1;
5653 pSMB->Reserved3 = 0;
5654 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
5655 byte_count = 3 /* pad */ + params + data_count;
5656 pSMB->DataCount = cpu_to_le16(data_count);
5657 pSMB->TotalDataCount = pSMB->DataCount;
5658 pSMB->ParameterCount = cpu_to_le16(params);
5659 pSMB->TotalParameterCount = pSMB->ParameterCount;
5660 pSMB->Reserved4 = 0;
5661 inc_rfc1001_len(pSMB, byte_count);
5662 parm_data->FileSize = cpu_to_le64(size);
5663 pSMB->ByteCount = cpu_to_le16(byte_count);
5664 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5665 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5666 if (rc)
5667 cifs_dbg(FYI, "SetPathInfo (file size) returned %d\n", rc);
5669 cifs_buf_release(pSMB);
5671 if (rc == -EAGAIN)
5672 goto SetEOFRetry;
5674 return rc;
5678 CIFSSMBSetFileSize(const unsigned int xid, struct cifs_tcon *tcon,
5679 struct cifsFileInfo *cfile, __u64 size, bool set_allocation)
5681 struct smb_com_transaction2_sfi_req *pSMB = NULL;
5682 struct file_end_of_file_info *parm_data;
5683 int rc = 0;
5684 __u16 params, param_offset, offset, byte_count, count;
5686 cifs_dbg(FYI, "SetFileSize (via SetFileInfo) %lld\n",
5687 (long long)size);
5688 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
5690 if (rc)
5691 return rc;
5693 pSMB->hdr.Pid = cpu_to_le16((__u16)cfile->pid);
5694 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(cfile->pid >> 16));
5696 params = 6;
5697 pSMB->MaxSetupCount = 0;
5698 pSMB->Reserved = 0;
5699 pSMB->Flags = 0;
5700 pSMB->Timeout = 0;
5701 pSMB->Reserved2 = 0;
5702 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
5703 offset = param_offset + params;
5705 count = sizeof(struct file_end_of_file_info);
5706 pSMB->MaxParameterCount = cpu_to_le16(2);
5707 /* BB find exact max SMB PDU from sess structure BB */
5708 pSMB->MaxDataCount = cpu_to_le16(1000);
5709 pSMB->SetupCount = 1;
5710 pSMB->Reserved3 = 0;
5711 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
5712 byte_count = 3 /* pad */ + params + count;
5713 pSMB->DataCount = cpu_to_le16(count);
5714 pSMB->ParameterCount = cpu_to_le16(params);
5715 pSMB->TotalDataCount = pSMB->DataCount;
5716 pSMB->TotalParameterCount = pSMB->ParameterCount;
5717 pSMB->ParameterOffset = cpu_to_le16(param_offset);
5718 parm_data =
5719 (struct file_end_of_file_info *) (((char *) &pSMB->hdr.Protocol)
5720 + offset);
5721 pSMB->DataOffset = cpu_to_le16(offset);
5722 parm_data->FileSize = cpu_to_le64(size);
5723 pSMB->Fid = cfile->fid.netfid;
5724 if (set_allocation) {
5725 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
5726 pSMB->InformationLevel =
5727 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2);
5728 else
5729 pSMB->InformationLevel =
5730 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO);
5731 } else /* Set File Size */ {
5732 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
5733 pSMB->InformationLevel =
5734 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO2);
5735 else
5736 pSMB->InformationLevel =
5737 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO);
5739 pSMB->Reserved4 = 0;
5740 inc_rfc1001_len(pSMB, byte_count);
5741 pSMB->ByteCount = cpu_to_le16(byte_count);
5742 rc = SendReceiveNoRsp(xid, tcon->ses, (char *) pSMB, 0);
5743 cifs_small_buf_release(pSMB);
5744 if (rc) {
5745 cifs_dbg(FYI, "Send error in SetFileInfo (SetFileSize) = %d\n",
5746 rc);
5749 /* Note: On -EAGAIN error only caller can retry on handle based calls
5750 since file handle passed in no longer valid */
5752 return rc;
5755 /* Some legacy servers such as NT4 require that the file times be set on
5756 an open handle, rather than by pathname - this is awkward due to
5757 potential access conflicts on the open, but it is unavoidable for these
5758 old servers since the only other choice is to go from 100 nanosecond DCE
5759 time and resort to the original setpathinfo level which takes the ancient
5760 DOS time format with 2 second granularity */
5762 CIFSSMBSetFileInfo(const unsigned int xid, struct cifs_tcon *tcon,
5763 const FILE_BASIC_INFO *data, __u16 fid, __u32 pid_of_opener)
5765 struct smb_com_transaction2_sfi_req *pSMB = NULL;
5766 char *data_offset;
5767 int rc = 0;
5768 __u16 params, param_offset, offset, byte_count, count;
5770 cifs_dbg(FYI, "Set Times (via SetFileInfo)\n");
5771 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
5773 if (rc)
5774 return rc;
5776 pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
5777 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));
5779 params = 6;
5780 pSMB->MaxSetupCount = 0;
5781 pSMB->Reserved = 0;
5782 pSMB->Flags = 0;
5783 pSMB->Timeout = 0;
5784 pSMB->Reserved2 = 0;
5785 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
5786 offset = param_offset + params;
5788 data_offset = (char *)pSMB +
5789 offsetof(struct smb_hdr, Protocol) + offset;
5791 count = sizeof(FILE_BASIC_INFO);
5792 pSMB->MaxParameterCount = cpu_to_le16(2);
5793 /* BB find max SMB PDU from sess */
5794 pSMB->MaxDataCount = cpu_to_le16(1000);
5795 pSMB->SetupCount = 1;
5796 pSMB->Reserved3 = 0;
5797 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
5798 byte_count = 3 /* pad */ + params + count;
5799 pSMB->DataCount = cpu_to_le16(count);
5800 pSMB->ParameterCount = cpu_to_le16(params);
5801 pSMB->TotalDataCount = pSMB->DataCount;
5802 pSMB->TotalParameterCount = pSMB->ParameterCount;
5803 pSMB->ParameterOffset = cpu_to_le16(param_offset);
5804 pSMB->DataOffset = cpu_to_le16(offset);
5805 pSMB->Fid = fid;
5806 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
5807 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO2);
5808 else
5809 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO);
5810 pSMB->Reserved4 = 0;
5811 inc_rfc1001_len(pSMB, byte_count);
5812 pSMB->ByteCount = cpu_to_le16(byte_count);
5813 memcpy(data_offset, data, sizeof(FILE_BASIC_INFO));
5814 rc = SendReceiveNoRsp(xid, tcon->ses, (char *) pSMB, 0);
5815 cifs_small_buf_release(pSMB);
5816 if (rc)
5817 cifs_dbg(FYI, "Send error in Set Time (SetFileInfo) = %d\n",
5818 rc);
5820 /* Note: On -EAGAIN error only caller can retry on handle based calls
5821 since file handle passed in no longer valid */
5823 return rc;
5827 CIFSSMBSetFileDisposition(const unsigned int xid, struct cifs_tcon *tcon,
5828 bool delete_file, __u16 fid, __u32 pid_of_opener)
5830 struct smb_com_transaction2_sfi_req *pSMB = NULL;
5831 char *data_offset;
5832 int rc = 0;
5833 __u16 params, param_offset, offset, byte_count, count;
5835 cifs_dbg(FYI, "Set File Disposition (via SetFileInfo)\n");
5836 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
5838 if (rc)
5839 return rc;
5841 pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
5842 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));
5844 params = 6;
5845 pSMB->MaxSetupCount = 0;
5846 pSMB->Reserved = 0;
5847 pSMB->Flags = 0;
5848 pSMB->Timeout = 0;
5849 pSMB->Reserved2 = 0;
5850 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
5851 offset = param_offset + params;
5853 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
5855 count = 1;
5856 pSMB->MaxParameterCount = cpu_to_le16(2);
5857 /* BB find max SMB PDU from sess */
5858 pSMB->MaxDataCount = cpu_to_le16(1000);
5859 pSMB->SetupCount = 1;
5860 pSMB->Reserved3 = 0;
5861 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
5862 byte_count = 3 /* pad */ + params + count;
5863 pSMB->DataCount = cpu_to_le16(count);
5864 pSMB->ParameterCount = cpu_to_le16(params);
5865 pSMB->TotalDataCount = pSMB->DataCount;
5866 pSMB->TotalParameterCount = pSMB->ParameterCount;
5867 pSMB->ParameterOffset = cpu_to_le16(param_offset);
5868 pSMB->DataOffset = cpu_to_le16(offset);
5869 pSMB->Fid = fid;
5870 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_DISPOSITION_INFO);
5871 pSMB->Reserved4 = 0;
5872 inc_rfc1001_len(pSMB, byte_count);
5873 pSMB->ByteCount = cpu_to_le16(byte_count);
5874 *data_offset = delete_file ? 1 : 0;
5875 rc = SendReceiveNoRsp(xid, tcon->ses, (char *) pSMB, 0);
5876 cifs_small_buf_release(pSMB);
5877 if (rc)
5878 cifs_dbg(FYI, "Send error in SetFileDisposition = %d\n", rc);
5880 return rc;
5884 CIFSSMBSetPathInfo(const unsigned int xid, struct cifs_tcon *tcon,
5885 const char *fileName, const FILE_BASIC_INFO *data,
5886 const struct nls_table *nls_codepage, int remap)
5888 TRANSACTION2_SPI_REQ *pSMB = NULL;
5889 TRANSACTION2_SPI_RSP *pSMBr = NULL;
5890 int name_len;
5891 int rc = 0;
5892 int bytes_returned = 0;
5893 char *data_offset;
5894 __u16 params, param_offset, offset, byte_count, count;
5896 cifs_dbg(FYI, "In SetTimes\n");
5898 SetTimesRetry:
5899 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5900 (void **) &pSMBr);
5901 if (rc)
5902 return rc;
5904 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5905 name_len =
5906 cifsConvertToUTF16((__le16 *) pSMB->FileName, fileName,
5907 PATH_MAX, nls_codepage, remap);
5908 name_len++; /* trailing null */
5909 name_len *= 2;
5910 } else {
5911 name_len = copy_path_name(pSMB->FileName, fileName);
5914 params = 6 + name_len;
5915 count = sizeof(FILE_BASIC_INFO);
5916 pSMB->MaxParameterCount = cpu_to_le16(2);
5917 /* BB find max SMB PDU from sess structure BB */
5918 pSMB->MaxDataCount = cpu_to_le16(1000);
5919 pSMB->MaxSetupCount = 0;
5920 pSMB->Reserved = 0;
5921 pSMB->Flags = 0;
5922 pSMB->Timeout = 0;
5923 pSMB->Reserved2 = 0;
5924 param_offset = offsetof(struct smb_com_transaction2_spi_req,
5925 InformationLevel) - 4;
5926 offset = param_offset + params;
5927 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
5928 pSMB->ParameterOffset = cpu_to_le16(param_offset);
5929 pSMB->DataOffset = cpu_to_le16(offset);
5930 pSMB->SetupCount = 1;
5931 pSMB->Reserved3 = 0;
5932 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
5933 byte_count = 3 /* pad */ + params + count;
5935 pSMB->DataCount = cpu_to_le16(count);
5936 pSMB->ParameterCount = cpu_to_le16(params);
5937 pSMB->TotalDataCount = pSMB->DataCount;
5938 pSMB->TotalParameterCount = pSMB->ParameterCount;
5939 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
5940 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO2);
5941 else
5942 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO);
5943 pSMB->Reserved4 = 0;
5944 inc_rfc1001_len(pSMB, byte_count);
5945 memcpy(data_offset, data, sizeof(FILE_BASIC_INFO));
5946 pSMB->ByteCount = cpu_to_le16(byte_count);
5947 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5948 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5949 if (rc)
5950 cifs_dbg(FYI, "SetPathInfo (times) returned %d\n", rc);
5952 cifs_buf_release(pSMB);
5954 if (rc == -EAGAIN)
5955 goto SetTimesRetry;
5957 return rc;
5960 /* Can not be used to set time stamps yet (due to old DOS time format) */
5961 /* Can be used to set attributes */
5962 #if 0 /* Possibly not needed - since it turns out that strangely NT4 has a bug
5963 handling it anyway and NT4 was what we thought it would be needed for
5964 Do not delete it until we prove whether needed for Win9x though */
5966 CIFSSMBSetAttrLegacy(unsigned int xid, struct cifs_tcon *tcon, char *fileName,
5967 __u16 dos_attrs, const struct nls_table *nls_codepage)
5969 SETATTR_REQ *pSMB = NULL;
5970 SETATTR_RSP *pSMBr = NULL;
5971 int rc = 0;
5972 int bytes_returned;
5973 int name_len;
5975 cifs_dbg(FYI, "In SetAttrLegacy\n");
5977 SetAttrLgcyRetry:
5978 rc = smb_init(SMB_COM_SETATTR, 8, tcon, (void **) &pSMB,
5979 (void **) &pSMBr);
5980 if (rc)
5981 return rc;
5983 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5984 name_len =
5985 ConvertToUTF16((__le16 *) pSMB->fileName, fileName,
5986 PATH_MAX, nls_codepage);
5987 name_len++; /* trailing null */
5988 name_len *= 2;
5989 } else {
5990 name_len = copy_path_name(pSMB->fileName, fileName);
5992 pSMB->attr = cpu_to_le16(dos_attrs);
5993 pSMB->BufferFormat = 0x04;
5994 inc_rfc1001_len(pSMB, name_len + 1);
5995 pSMB->ByteCount = cpu_to_le16(name_len + 1);
5996 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5997 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5998 if (rc)
5999 cifs_dbg(FYI, "Error in LegacySetAttr = %d\n", rc);
6001 cifs_buf_release(pSMB);
6003 if (rc == -EAGAIN)
6004 goto SetAttrLgcyRetry;
6006 return rc;
6008 #endif /* temporarily unneeded SetAttr legacy function */
6010 static void
6011 cifs_fill_unix_set_info(FILE_UNIX_BASIC_INFO *data_offset,
6012 const struct cifs_unix_set_info_args *args)
6014 u64 uid = NO_CHANGE_64, gid = NO_CHANGE_64;
6015 u64 mode = args->mode;
6017 if (uid_valid(args->uid))
6018 uid = from_kuid(&init_user_ns, args->uid);
6019 if (gid_valid(args->gid))
6020 gid = from_kgid(&init_user_ns, args->gid);
6023 * Samba server ignores set of file size to zero due to bugs in some
6024 * older clients, but we should be precise - we use SetFileSize to
6025 * set file size and do not want to truncate file size to zero
6026 * accidentally as happened on one Samba server beta by putting
6027 * zero instead of -1 here
6029 data_offset->EndOfFile = cpu_to_le64(NO_CHANGE_64);
6030 data_offset->NumOfBytes = cpu_to_le64(NO_CHANGE_64);
6031 data_offset->LastStatusChange = cpu_to_le64(args->ctime);
6032 data_offset->LastAccessTime = cpu_to_le64(args->atime);
6033 data_offset->LastModificationTime = cpu_to_le64(args->mtime);
6034 data_offset->Uid = cpu_to_le64(uid);
6035 data_offset->Gid = cpu_to_le64(gid);
6036 /* better to leave device as zero when it is */
6037 data_offset->DevMajor = cpu_to_le64(MAJOR(args->device));
6038 data_offset->DevMinor = cpu_to_le64(MINOR(args->device));
6039 data_offset->Permissions = cpu_to_le64(mode);
6041 if (S_ISREG(mode))
6042 data_offset->Type = cpu_to_le32(UNIX_FILE);
6043 else if (S_ISDIR(mode))
6044 data_offset->Type = cpu_to_le32(UNIX_DIR);
6045 else if (S_ISLNK(mode))
6046 data_offset->Type = cpu_to_le32(UNIX_SYMLINK);
6047 else if (S_ISCHR(mode))
6048 data_offset->Type = cpu_to_le32(UNIX_CHARDEV);
6049 else if (S_ISBLK(mode))
6050 data_offset->Type = cpu_to_le32(UNIX_BLOCKDEV);
6051 else if (S_ISFIFO(mode))
6052 data_offset->Type = cpu_to_le32(UNIX_FIFO);
6053 else if (S_ISSOCK(mode))
6054 data_offset->Type = cpu_to_le32(UNIX_SOCKET);
6058 CIFSSMBUnixSetFileInfo(const unsigned int xid, struct cifs_tcon *tcon,
6059 const struct cifs_unix_set_info_args *args,
6060 u16 fid, u32 pid_of_opener)
6062 struct smb_com_transaction2_sfi_req *pSMB = NULL;
6063 char *data_offset;
6064 int rc = 0;
6065 u16 params, param_offset, offset, byte_count, count;
6067 cifs_dbg(FYI, "Set Unix Info (via SetFileInfo)\n");
6068 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
6070 if (rc)
6071 return rc;
6073 pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
6074 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));
6076 params = 6;
6077 pSMB->MaxSetupCount = 0;
6078 pSMB->Reserved = 0;
6079 pSMB->Flags = 0;
6080 pSMB->Timeout = 0;
6081 pSMB->Reserved2 = 0;
6082 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
6083 offset = param_offset + params;
6085 data_offset = (char *)pSMB +
6086 offsetof(struct smb_hdr, Protocol) + offset;
6088 count = sizeof(FILE_UNIX_BASIC_INFO);
6090 pSMB->MaxParameterCount = cpu_to_le16(2);
6091 /* BB find max SMB PDU from sess */
6092 pSMB->MaxDataCount = cpu_to_le16(1000);
6093 pSMB->SetupCount = 1;
6094 pSMB->Reserved3 = 0;
6095 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
6096 byte_count = 3 /* pad */ + params + count;
6097 pSMB->DataCount = cpu_to_le16(count);
6098 pSMB->ParameterCount = cpu_to_le16(params);
6099 pSMB->TotalDataCount = pSMB->DataCount;
6100 pSMB->TotalParameterCount = pSMB->ParameterCount;
6101 pSMB->ParameterOffset = cpu_to_le16(param_offset);
6102 pSMB->DataOffset = cpu_to_le16(offset);
6103 pSMB->Fid = fid;
6104 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_BASIC);
6105 pSMB->Reserved4 = 0;
6106 inc_rfc1001_len(pSMB, byte_count);
6107 pSMB->ByteCount = cpu_to_le16(byte_count);
6109 cifs_fill_unix_set_info((FILE_UNIX_BASIC_INFO *)data_offset, args);
6111 rc = SendReceiveNoRsp(xid, tcon->ses, (char *) pSMB, 0);
6112 cifs_small_buf_release(pSMB);
6113 if (rc)
6114 cifs_dbg(FYI, "Send error in Set Time (SetFileInfo) = %d\n",
6115 rc);
6117 /* Note: On -EAGAIN error only caller can retry on handle based calls
6118 since file handle passed in no longer valid */
6120 return rc;
6124 CIFSSMBUnixSetPathInfo(const unsigned int xid, struct cifs_tcon *tcon,
6125 const char *file_name,
6126 const struct cifs_unix_set_info_args *args,
6127 const struct nls_table *nls_codepage, int remap)
6129 TRANSACTION2_SPI_REQ *pSMB = NULL;
6130 TRANSACTION2_SPI_RSP *pSMBr = NULL;
6131 int name_len;
6132 int rc = 0;
6133 int bytes_returned = 0;
6134 FILE_UNIX_BASIC_INFO *data_offset;
6135 __u16 params, param_offset, offset, count, byte_count;
6137 cifs_dbg(FYI, "In SetUID/GID/Mode\n");
6138 setPermsRetry:
6139 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
6140 (void **) &pSMBr);
6141 if (rc)
6142 return rc;
6144 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
6145 name_len =
6146 cifsConvertToUTF16((__le16 *) pSMB->FileName, file_name,
6147 PATH_MAX, nls_codepage, remap);
6148 name_len++; /* trailing null */
6149 name_len *= 2;
6150 } else {
6151 name_len = copy_path_name(pSMB->FileName, file_name);
6154 params = 6 + name_len;
6155 count = sizeof(FILE_UNIX_BASIC_INFO);
6156 pSMB->MaxParameterCount = cpu_to_le16(2);
6157 /* BB find max SMB PDU from sess structure BB */
6158 pSMB->MaxDataCount = cpu_to_le16(1000);
6159 pSMB->MaxSetupCount = 0;
6160 pSMB->Reserved = 0;
6161 pSMB->Flags = 0;
6162 pSMB->Timeout = 0;
6163 pSMB->Reserved2 = 0;
6164 param_offset = offsetof(struct smb_com_transaction2_spi_req,
6165 InformationLevel) - 4;
6166 offset = param_offset + params;
6167 data_offset =
6168 (FILE_UNIX_BASIC_INFO *) ((char *) &pSMB->hdr.Protocol +
6169 offset);
6170 memset(data_offset, 0, count);
6171 pSMB->DataOffset = cpu_to_le16(offset);
6172 pSMB->ParameterOffset = cpu_to_le16(param_offset);
6173 pSMB->SetupCount = 1;
6174 pSMB->Reserved3 = 0;
6175 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
6176 byte_count = 3 /* pad */ + params + count;
6177 pSMB->ParameterCount = cpu_to_le16(params);
6178 pSMB->DataCount = cpu_to_le16(count);
6179 pSMB->TotalParameterCount = pSMB->ParameterCount;
6180 pSMB->TotalDataCount = pSMB->DataCount;
6181 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_BASIC);
6182 pSMB->Reserved4 = 0;
6183 inc_rfc1001_len(pSMB, byte_count);
6185 cifs_fill_unix_set_info(data_offset, args);
6187 pSMB->ByteCount = cpu_to_le16(byte_count);
6188 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
6189 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
6190 if (rc)
6191 cifs_dbg(FYI, "SetPathInfo (perms) returned %d\n", rc);
6193 cifs_buf_release(pSMB);
6194 if (rc == -EAGAIN)
6195 goto setPermsRetry;
6196 return rc;
6199 #ifdef CONFIG_CIFS_XATTR
6201 * Do a path-based QUERY_ALL_EAS call and parse the result. This is a common
6202 * function used by listxattr and getxattr type calls. When ea_name is set,
6203 * it looks for that attribute name and stuffs that value into the EAData
6204 * buffer. When ea_name is NULL, it stuffs a list of attribute names into the
6205 * buffer. In both cases, the return value is either the length of the
6206 * resulting data or a negative error code. If EAData is a NULL pointer then
6207 * the data isn't copied to it, but the length is returned.
6209 ssize_t
6210 CIFSSMBQAllEAs(const unsigned int xid, struct cifs_tcon *tcon,
6211 const unsigned char *searchName, const unsigned char *ea_name,
6212 char *EAData, size_t buf_size,
6213 struct cifs_sb_info *cifs_sb)
6215 /* BB assumes one setup word */
6216 TRANSACTION2_QPI_REQ *pSMB = NULL;
6217 TRANSACTION2_QPI_RSP *pSMBr = NULL;
6218 int remap = cifs_remap(cifs_sb);
6219 struct nls_table *nls_codepage = cifs_sb->local_nls;
6220 int rc = 0;
6221 int bytes_returned;
6222 int list_len;
6223 struct fealist *ea_response_data;
6224 struct fea *temp_fea;
6225 char *temp_ptr;
6226 char *end_of_smb;
6227 __u16 params, byte_count, data_offset;
6228 unsigned int ea_name_len = ea_name ? strlen(ea_name) : 0;
6230 cifs_dbg(FYI, "In Query All EAs path %s\n", searchName);
6231 QAllEAsRetry:
6232 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
6233 (void **) &pSMBr);
6234 if (rc)
6235 return rc;
6237 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
6238 list_len =
6239 cifsConvertToUTF16((__le16 *) pSMB->FileName, searchName,
6240 PATH_MAX, nls_codepage, remap);
6241 list_len++; /* trailing null */
6242 list_len *= 2;
6243 } else {
6244 list_len = copy_path_name(pSMB->FileName, searchName);
6247 params = 2 /* level */ + 4 /* reserved */ + list_len /* includes NUL */;
6248 pSMB->TotalDataCount = 0;
6249 pSMB->MaxParameterCount = cpu_to_le16(2);
6250 /* BB find exact max SMB PDU from sess structure BB */
6251 pSMB->MaxDataCount = cpu_to_le16(CIFSMaxBufSize);
6252 pSMB->MaxSetupCount = 0;
6253 pSMB->Reserved = 0;
6254 pSMB->Flags = 0;
6255 pSMB->Timeout = 0;
6256 pSMB->Reserved2 = 0;
6257 pSMB->ParameterOffset = cpu_to_le16(offsetof(
6258 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
6259 pSMB->DataCount = 0;
6260 pSMB->DataOffset = 0;
6261 pSMB->SetupCount = 1;
6262 pSMB->Reserved3 = 0;
6263 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
6264 byte_count = params + 1 /* pad */ ;
6265 pSMB->TotalParameterCount = cpu_to_le16(params);
6266 pSMB->ParameterCount = pSMB->TotalParameterCount;
6267 pSMB->InformationLevel = cpu_to_le16(SMB_INFO_QUERY_ALL_EAS);
6268 pSMB->Reserved4 = 0;
6269 inc_rfc1001_len(pSMB, byte_count);
6270 pSMB->ByteCount = cpu_to_le16(byte_count);
6272 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
6273 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
6274 if (rc) {
6275 cifs_dbg(FYI, "Send error in QueryAllEAs = %d\n", rc);
6276 goto QAllEAsOut;
6280 /* BB also check enough total bytes returned */
6281 /* BB we need to improve the validity checking
6282 of these trans2 responses */
6284 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
6285 if (rc || get_bcc(&pSMBr->hdr) < 4) {
6286 rc = -EIO; /* bad smb */
6287 goto QAllEAsOut;
6290 /* check that length of list is not more than bcc */
6291 /* check that each entry does not go beyond length
6292 of list */
6293 /* check that each element of each entry does not
6294 go beyond end of list */
6295 /* validate_trans2_offsets() */
6296 /* BB check if start of smb + data_offset > &bcc+ bcc */
6298 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
6299 ea_response_data = (struct fealist *)
6300 (((char *) &pSMBr->hdr.Protocol) + data_offset);
6302 list_len = le32_to_cpu(ea_response_data->list_len);
6303 cifs_dbg(FYI, "ea length %d\n", list_len);
6304 if (list_len <= 8) {
6305 cifs_dbg(FYI, "empty EA list returned from server\n");
6306 /* didn't find the named attribute */
6307 if (ea_name)
6308 rc = -ENODATA;
6309 goto QAllEAsOut;
6312 /* make sure list_len doesn't go past end of SMB */
6313 end_of_smb = (char *)pByteArea(&pSMBr->hdr) + get_bcc(&pSMBr->hdr);
6314 if ((char *)ea_response_data + list_len > end_of_smb) {
6315 cifs_dbg(FYI, "EA list appears to go beyond SMB\n");
6316 rc = -EIO;
6317 goto QAllEAsOut;
6320 /* account for ea list len */
6321 list_len -= 4;
6322 temp_fea = ea_response_data->list;
6323 temp_ptr = (char *)temp_fea;
6324 while (list_len > 0) {
6325 unsigned int name_len;
6326 __u16 value_len;
6328 list_len -= 4;
6329 temp_ptr += 4;
6330 /* make sure we can read name_len and value_len */
6331 if (list_len < 0) {
6332 cifs_dbg(FYI, "EA entry goes beyond length of list\n");
6333 rc = -EIO;
6334 goto QAllEAsOut;
6337 name_len = temp_fea->name_len;
6338 value_len = le16_to_cpu(temp_fea->value_len);
6339 list_len -= name_len + 1 + value_len;
6340 if (list_len < 0) {
6341 cifs_dbg(FYI, "EA entry goes beyond length of list\n");
6342 rc = -EIO;
6343 goto QAllEAsOut;
6346 if (ea_name) {
6347 if (ea_name_len == name_len &&
6348 memcmp(ea_name, temp_ptr, name_len) == 0) {
6349 temp_ptr += name_len + 1;
6350 rc = value_len;
6351 if (buf_size == 0)
6352 goto QAllEAsOut;
6353 if ((size_t)value_len > buf_size) {
6354 rc = -ERANGE;
6355 goto QAllEAsOut;
6357 memcpy(EAData, temp_ptr, value_len);
6358 goto QAllEAsOut;
6360 } else {
6361 /* account for prefix user. and trailing null */
6362 rc += (5 + 1 + name_len);
6363 if (rc < (int) buf_size) {
6364 memcpy(EAData, "user.", 5);
6365 EAData += 5;
6366 memcpy(EAData, temp_ptr, name_len);
6367 EAData += name_len;
6368 /* null terminate name */
6369 *EAData = 0;
6370 ++EAData;
6371 } else if (buf_size == 0) {
6372 /* skip copy - calc size only */
6373 } else {
6374 /* stop before overrun buffer */
6375 rc = -ERANGE;
6376 break;
6379 temp_ptr += name_len + 1 + value_len;
6380 temp_fea = (struct fea *)temp_ptr;
6383 /* didn't find the named attribute */
6384 if (ea_name)
6385 rc = -ENODATA;
6387 QAllEAsOut:
6388 cifs_buf_release(pSMB);
6389 if (rc == -EAGAIN)
6390 goto QAllEAsRetry;
6392 return (ssize_t)rc;
6396 CIFSSMBSetEA(const unsigned int xid, struct cifs_tcon *tcon,
6397 const char *fileName, const char *ea_name, const void *ea_value,
6398 const __u16 ea_value_len, const struct nls_table *nls_codepage,
6399 struct cifs_sb_info *cifs_sb)
6401 struct smb_com_transaction2_spi_req *pSMB = NULL;
6402 struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
6403 struct fealist *parm_data;
6404 int name_len;
6405 int rc = 0;
6406 int bytes_returned = 0;
6407 __u16 params, param_offset, byte_count, offset, count;
6408 int remap = cifs_remap(cifs_sb);
6410 cifs_dbg(FYI, "In SetEA\n");
6411 SetEARetry:
6412 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
6413 (void **) &pSMBr);
6414 if (rc)
6415 return rc;
6417 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
6418 name_len =
6419 cifsConvertToUTF16((__le16 *) pSMB->FileName, fileName,
6420 PATH_MAX, nls_codepage, remap);
6421 name_len++; /* trailing null */
6422 name_len *= 2;
6423 } else {
6424 name_len = copy_path_name(pSMB->FileName, fileName);
6427 params = 6 + name_len;
6429 /* done calculating parms using name_len of file name,
6430 now use name_len to calculate length of ea name
6431 we are going to create in the inode xattrs */
6432 if (ea_name == NULL)
6433 name_len = 0;
6434 else
6435 name_len = strnlen(ea_name, 255);
6437 count = sizeof(*parm_data) + ea_value_len + name_len;
6438 pSMB->MaxParameterCount = cpu_to_le16(2);
6439 /* BB find max SMB PDU from sess */
6440 pSMB->MaxDataCount = cpu_to_le16(1000);
6441 pSMB->MaxSetupCount = 0;
6442 pSMB->Reserved = 0;
6443 pSMB->Flags = 0;
6444 pSMB->Timeout = 0;
6445 pSMB->Reserved2 = 0;
6446 param_offset = offsetof(struct smb_com_transaction2_spi_req,
6447 InformationLevel) - 4;
6448 offset = param_offset + params;
6449 pSMB->InformationLevel =
6450 cpu_to_le16(SMB_SET_FILE_EA);
6452 parm_data = (void *)pSMB + offsetof(struct smb_hdr, Protocol) + offset;
6453 pSMB->ParameterOffset = cpu_to_le16(param_offset);
6454 pSMB->DataOffset = cpu_to_le16(offset);
6455 pSMB->SetupCount = 1;
6456 pSMB->Reserved3 = 0;
6457 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
6458 byte_count = 3 /* pad */ + params + count;
6459 pSMB->DataCount = cpu_to_le16(count);
6460 parm_data->list_len = cpu_to_le32(count);
6461 parm_data->list[0].EA_flags = 0;
6462 /* we checked above that name len is less than 255 */
6463 parm_data->list[0].name_len = (__u8)name_len;
6464 /* EA names are always ASCII */
6465 if (ea_name)
6466 strncpy(parm_data->list[0].name, ea_name, name_len);
6467 parm_data->list[0].name[name_len] = 0;
6468 parm_data->list[0].value_len = cpu_to_le16(ea_value_len);
6469 /* caller ensures that ea_value_len is less than 64K but
6470 we need to ensure that it fits within the smb */
6472 /*BB add length check to see if it would fit in
6473 negotiated SMB buffer size BB */
6474 /* if (ea_value_len > buffer_size - 512 (enough for header)) */
6475 if (ea_value_len)
6476 memcpy(parm_data->list[0].name+name_len+1,
6477 ea_value, ea_value_len);
6479 pSMB->TotalDataCount = pSMB->DataCount;
6480 pSMB->ParameterCount = cpu_to_le16(params);
6481 pSMB->TotalParameterCount = pSMB->ParameterCount;
6482 pSMB->Reserved4 = 0;
6483 inc_rfc1001_len(pSMB, byte_count);
6484 pSMB->ByteCount = cpu_to_le16(byte_count);
6485 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
6486 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
6487 if (rc)
6488 cifs_dbg(FYI, "SetPathInfo (EA) returned %d\n", rc);
6490 cifs_buf_release(pSMB);
6492 if (rc == -EAGAIN)
6493 goto SetEARetry;
6495 return rc;
6497 #endif