Merge branch 'fixes' of git://git.linaro.org/people/rmk/linux-arm
[cascardo/linux.git] / fs / cifs / cifssmb.c
1 /*
2  *   fs/cifs/cifssmb.c
3  *
4  *   Copyright (C) International Business Machines  Corp., 2002,2010
5  *   Author(s): Steve French (sfrench@us.ibm.com)
6  *
7  *   Contains the routines for constructing the SMB PDUs themselves
8  *
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.
13  *
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.
18  *
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
22  */
23
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 */
29
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 <asm/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 "fscache.h"
46
47 #ifdef CONFIG_CIFS_POSIX
48 static struct {
49         int index;
50         char *name;
51 } protocols[] = {
52 #ifdef CONFIG_CIFS_WEAK_PW_HASH
53         {LANMAN_PROT, "\2LM1.2X002"},
54         {LANMAN2_PROT, "\2LANMAN2.1"},
55 #endif /* weak password hashing for legacy clients */
56         {CIFS_PROT, "\2NT LM 0.12"},
57         {POSIX_PROT, "\2POSIX 2"},
58         {BAD_PROT, "\2"}
59 };
60 #else
61 static struct {
62         int index;
63         char *name;
64 } protocols[] = {
65 #ifdef CONFIG_CIFS_WEAK_PW_HASH
66         {LANMAN_PROT, "\2LM1.2X002"},
67         {LANMAN2_PROT, "\2LANMAN2.1"},
68 #endif /* weak password hashing for legacy clients */
69         {CIFS_PROT, "\2NT LM 0.12"},
70         {BAD_PROT, "\2"}
71 };
72 #endif
73
74 /* define the number of elements in the cifs dialect array */
75 #ifdef CONFIG_CIFS_POSIX
76 #ifdef CONFIG_CIFS_WEAK_PW_HASH
77 #define CIFS_NUM_PROT 4
78 #else
79 #define CIFS_NUM_PROT 2
80 #endif /* CIFS_WEAK_PW_HASH */
81 #else /* not posix */
82 #ifdef CONFIG_CIFS_WEAK_PW_HASH
83 #define CIFS_NUM_PROT 3
84 #else
85 #define CIFS_NUM_PROT 1
86 #endif /* CONFIG_CIFS_WEAK_PW_HASH */
87 #endif /* CIFS_POSIX */
88
89 #ifdef CONFIG_HIGHMEM
90 /*
91  * On arches that have high memory, kmap address space is limited. By
92  * serializing the kmap operations on those arches, we ensure that we don't
93  * end up with a bunch of threads in writeback with partially mapped page
94  * arrays, stuck waiting for kmap to come back. That situation prevents
95  * progress and can deadlock.
96  */
97 static DEFINE_MUTEX(cifs_kmap_mutex);
98
99 static inline void
100 cifs_kmap_lock(void)
101 {
102         mutex_lock(&cifs_kmap_mutex);
103 }
104
105 static inline void
106 cifs_kmap_unlock(void)
107 {
108         mutex_unlock(&cifs_kmap_mutex);
109 }
110 #else /* !CONFIG_HIGHMEM */
111 #define cifs_kmap_lock() do { ; } while(0)
112 #define cifs_kmap_unlock() do { ; } while(0)
113 #endif /* CONFIG_HIGHMEM */
114
115 /*
116  * Mark as invalid, all open files on tree connections since they
117  * were closed when session to server was lost.
118  */
119 void
120 cifs_mark_open_files_invalid(struct cifs_tcon *tcon)
121 {
122         struct cifsFileInfo *open_file = NULL;
123         struct list_head *tmp;
124         struct list_head *tmp1;
125
126         /* list all files open on tree connection and mark them invalid */
127         spin_lock(&cifs_file_list_lock);
128         list_for_each_safe(tmp, tmp1, &tcon->openFileList) {
129                 open_file = list_entry(tmp, struct cifsFileInfo, tlist);
130                 open_file->invalidHandle = true;
131                 open_file->oplock_break_cancelled = true;
132         }
133         spin_unlock(&cifs_file_list_lock);
134         /*
135          * BB Add call to invalidate_inodes(sb) for all superblocks mounted
136          * to this tcon.
137          */
138 }
139
140 /* reconnect the socket, tcon, and smb session if needed */
141 static int
142 cifs_reconnect_tcon(struct cifs_tcon *tcon, int smb_command)
143 {
144         int rc;
145         struct cifs_ses *ses;
146         struct TCP_Server_Info *server;
147         struct nls_table *nls_codepage;
148
149         /*
150          * SMBs NegProt, SessSetup, uLogoff do not have tcon yet so check for
151          * tcp and smb session status done differently for those three - in the
152          * calling routine
153          */
154         if (!tcon)
155                 return 0;
156
157         ses = tcon->ses;
158         server = ses->server;
159
160         /*
161          * only tree disconnect, open, and write, (and ulogoff which does not
162          * have tcon) are allowed as we start force umount
163          */
164         if (tcon->tidStatus == CifsExiting) {
165                 if (smb_command != SMB_COM_WRITE_ANDX &&
166                     smb_command != SMB_COM_OPEN_ANDX &&
167                     smb_command != SMB_COM_TREE_DISCONNECT) {
168                         cFYI(1, "can not send cmd %d while umounting",
169                                 smb_command);
170                         return -ENODEV;
171                 }
172         }
173
174         /*
175          * Give demultiplex thread up to 10 seconds to reconnect, should be
176          * greater than cifs socket timeout which is 7 seconds
177          */
178         while (server->tcpStatus == CifsNeedReconnect) {
179                 wait_event_interruptible_timeout(server->response_q,
180                         (server->tcpStatus != CifsNeedReconnect), 10 * HZ);
181
182                 /* are we still trying to reconnect? */
183                 if (server->tcpStatus != CifsNeedReconnect)
184                         break;
185
186                 /*
187                  * on "soft" mounts we wait once. Hard mounts keep
188                  * retrying until process is killed or server comes
189                  * back on-line
190                  */
191                 if (!tcon->retry) {
192                         cFYI(1, "gave up waiting on reconnect in smb_init");
193                         return -EHOSTDOWN;
194                 }
195         }
196
197         if (!ses->need_reconnect && !tcon->need_reconnect)
198                 return 0;
199
200         nls_codepage = load_nls_default();
201
202         /*
203          * need to prevent multiple threads trying to simultaneously
204          * reconnect the same SMB session
205          */
206         mutex_lock(&ses->session_mutex);
207         rc = cifs_negotiate_protocol(0, ses);
208         if (rc == 0 && ses->need_reconnect)
209                 rc = cifs_setup_session(0, ses, nls_codepage);
210
211         /* do we need to reconnect tcon? */
212         if (rc || !tcon->need_reconnect) {
213                 mutex_unlock(&ses->session_mutex);
214                 goto out;
215         }
216
217         cifs_mark_open_files_invalid(tcon);
218         rc = CIFSTCon(0, ses, tcon->treeName, tcon, nls_codepage);
219         mutex_unlock(&ses->session_mutex);
220         cFYI(1, "reconnect tcon rc = %d", rc);
221
222         if (rc)
223                 goto out;
224
225         /*
226          * FIXME: check if wsize needs updated due to negotiated smb buffer
227          *        size shrinking
228          */
229         atomic_inc(&tconInfoReconnectCount);
230
231         /* tell server Unix caps we support */
232         if (ses->capabilities & CAP_UNIX)
233                 reset_cifs_unix_caps(0, tcon, NULL, NULL);
234
235         /*
236          * Removed call to reopen open files here. It is safer (and faster) to
237          * reopen files one at a time as needed in read and write.
238          *
239          * FIXME: what about file locks? don't we need to reclaim them ASAP?
240          */
241
242 out:
243         /*
244          * Check if handle based operation so we know whether we can continue
245          * or not without returning to caller to reset file handle
246          */
247         switch (smb_command) {
248         case SMB_COM_READ_ANDX:
249         case SMB_COM_WRITE_ANDX:
250         case SMB_COM_CLOSE:
251         case SMB_COM_FIND_CLOSE2:
252         case SMB_COM_LOCKING_ANDX:
253                 rc = -EAGAIN;
254         }
255
256         unload_nls(nls_codepage);
257         return rc;
258 }
259
260 /* Allocate and return pointer to an SMB request buffer, and set basic
261    SMB information in the SMB header.  If the return code is zero, this
262    function must have filled in request_buf pointer */
263 static int
264 small_smb_init(int smb_command, int wct, struct cifs_tcon *tcon,
265                 void **request_buf)
266 {
267         int rc;
268
269         rc = cifs_reconnect_tcon(tcon, smb_command);
270         if (rc)
271                 return rc;
272
273         *request_buf = cifs_small_buf_get();
274         if (*request_buf == NULL) {
275                 /* BB should we add a retry in here if not a writepage? */
276                 return -ENOMEM;
277         }
278
279         header_assemble((struct smb_hdr *) *request_buf, smb_command,
280                         tcon, wct);
281
282         if (tcon != NULL)
283                 cifs_stats_inc(&tcon->num_smbs_sent);
284
285         return 0;
286 }
287
288 int
289 small_smb_init_no_tc(const int smb_command, const int wct,
290                      struct cifs_ses *ses, void **request_buf)
291 {
292         int rc;
293         struct smb_hdr *buffer;
294
295         rc = small_smb_init(smb_command, wct, NULL, request_buf);
296         if (rc)
297                 return rc;
298
299         buffer = (struct smb_hdr *)*request_buf;
300         buffer->Mid = get_next_mid(ses->server);
301         if (ses->capabilities & CAP_UNICODE)
302                 buffer->Flags2 |= SMBFLG2_UNICODE;
303         if (ses->capabilities & CAP_STATUS32)
304                 buffer->Flags2 |= SMBFLG2_ERR_STATUS;
305
306         /* uid, tid can stay at zero as set in header assemble */
307
308         /* BB add support for turning on the signing when
309         this function is used after 1st of session setup requests */
310
311         return rc;
312 }
313
314 /* If the return code is zero, this function must fill in request_buf pointer */
315 static int
316 __smb_init(int smb_command, int wct, struct cifs_tcon *tcon,
317                         void **request_buf, void **response_buf)
318 {
319         *request_buf = cifs_buf_get();
320         if (*request_buf == NULL) {
321                 /* BB should we add a retry in here if not a writepage? */
322                 return -ENOMEM;
323         }
324     /* Although the original thought was we needed the response buf for  */
325     /* potential retries of smb operations it turns out we can determine */
326     /* from the mid flags when the request buffer can be resent without  */
327     /* having to use a second distinct buffer for the response */
328         if (response_buf)
329                 *response_buf = *request_buf;
330
331         header_assemble((struct smb_hdr *) *request_buf, smb_command, tcon,
332                         wct);
333
334         if (tcon != NULL)
335                 cifs_stats_inc(&tcon->num_smbs_sent);
336
337         return 0;
338 }
339
340 /* If the return code is zero, this function must fill in request_buf pointer */
341 static int
342 smb_init(int smb_command, int wct, struct cifs_tcon *tcon,
343          void **request_buf, void **response_buf)
344 {
345         int rc;
346
347         rc = cifs_reconnect_tcon(tcon, smb_command);
348         if (rc)
349                 return rc;
350
351         return __smb_init(smb_command, wct, tcon, request_buf, response_buf);
352 }
353
354 static int
355 smb_init_no_reconnect(int smb_command, int wct, struct cifs_tcon *tcon,
356                         void **request_buf, void **response_buf)
357 {
358         if (tcon->ses->need_reconnect || tcon->need_reconnect)
359                 return -EHOSTDOWN;
360
361         return __smb_init(smb_command, wct, tcon, request_buf, response_buf);
362 }
363
364 static int validate_t2(struct smb_t2_rsp *pSMB)
365 {
366         unsigned int total_size;
367
368         /* check for plausible wct */
369         if (pSMB->hdr.WordCount < 10)
370                 goto vt2_err;
371
372         /* check for parm and data offset going beyond end of smb */
373         if (get_unaligned_le16(&pSMB->t2_rsp.ParameterOffset) > 1024 ||
374             get_unaligned_le16(&pSMB->t2_rsp.DataOffset) > 1024)
375                 goto vt2_err;
376
377         total_size = get_unaligned_le16(&pSMB->t2_rsp.ParameterCount);
378         if (total_size >= 512)
379                 goto vt2_err;
380
381         /* check that bcc is at least as big as parms + data, and that it is
382          * less than negotiated smb buffer
383          */
384         total_size += get_unaligned_le16(&pSMB->t2_rsp.DataCount);
385         if (total_size > get_bcc(&pSMB->hdr) ||
386             total_size >= CIFSMaxBufSize + MAX_CIFS_HDR_SIZE)
387                 goto vt2_err;
388
389         return 0;
390 vt2_err:
391         cifs_dump_mem("Invalid transact2 SMB: ", (char *)pSMB,
392                 sizeof(struct smb_t2_rsp) + 16);
393         return -EINVAL;
394 }
395
396 int
397 CIFSSMBNegotiate(const unsigned int xid, struct cifs_ses *ses)
398 {
399         NEGOTIATE_REQ *pSMB;
400         NEGOTIATE_RSP *pSMBr;
401         int rc = 0;
402         int bytes_returned;
403         int i;
404         struct TCP_Server_Info *server;
405         u16 count;
406         unsigned int secFlags;
407
408         if (ses->server)
409                 server = ses->server;
410         else {
411                 rc = -EIO;
412                 return rc;
413         }
414         rc = smb_init(SMB_COM_NEGOTIATE, 0, NULL /* no tcon yet */ ,
415                       (void **) &pSMB, (void **) &pSMBr);
416         if (rc)
417                 return rc;
418
419         /* if any of auth flags (ie not sign or seal) are overriden use them */
420         if (ses->overrideSecFlg & (~(CIFSSEC_MUST_SIGN | CIFSSEC_MUST_SEAL)))
421                 secFlags = ses->overrideSecFlg;  /* BB FIXME fix sign flags? */
422         else /* if override flags set only sign/seal OR them with global auth */
423                 secFlags = global_secflags | ses->overrideSecFlg;
424
425         cFYI(1, "secFlags 0x%x", secFlags);
426
427         pSMB->hdr.Mid = get_next_mid(server);
428         pSMB->hdr.Flags2 |= (SMBFLG2_UNICODE | SMBFLG2_ERR_STATUS);
429
430         if ((secFlags & CIFSSEC_MUST_KRB5) == CIFSSEC_MUST_KRB5)
431                 pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC;
432         else if ((secFlags & CIFSSEC_AUTH_MASK) == CIFSSEC_MAY_KRB5) {
433                 cFYI(1, "Kerberos only mechanism, enable extended security");
434                 pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC;
435         } else if ((secFlags & CIFSSEC_MUST_NTLMSSP) == CIFSSEC_MUST_NTLMSSP)
436                 pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC;
437         else if ((secFlags & CIFSSEC_AUTH_MASK) == CIFSSEC_MAY_NTLMSSP) {
438                 cFYI(1, "NTLMSSP only mechanism, enable extended security");
439                 pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC;
440         }
441
442         count = 0;
443         for (i = 0; i < CIFS_NUM_PROT; i++) {
444                 strncpy(pSMB->DialectsArray+count, protocols[i].name, 16);
445                 count += strlen(protocols[i].name) + 1;
446                 /* null at end of source and target buffers anyway */
447         }
448         inc_rfc1001_len(pSMB, count);
449         pSMB->ByteCount = cpu_to_le16(count);
450
451         rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB,
452                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
453         if (rc != 0)
454                 goto neg_err_exit;
455
456         server->dialect = le16_to_cpu(pSMBr->DialectIndex);
457         cFYI(1, "Dialect: %d", server->dialect);
458         /* Check wct = 1 error case */
459         if ((pSMBr->hdr.WordCount < 13) || (server->dialect == BAD_PROT)) {
460                 /* core returns wct = 1, but we do not ask for core - otherwise
461                 small wct just comes when dialect index is -1 indicating we
462                 could not negotiate a common dialect */
463                 rc = -EOPNOTSUPP;
464                 goto neg_err_exit;
465 #ifdef CONFIG_CIFS_WEAK_PW_HASH
466         } else if ((pSMBr->hdr.WordCount == 13)
467                         && ((server->dialect == LANMAN_PROT)
468                                 || (server->dialect == LANMAN2_PROT))) {
469                 __s16 tmp;
470                 struct lanman_neg_rsp *rsp = (struct lanman_neg_rsp *)pSMBr;
471
472                 if ((secFlags & CIFSSEC_MAY_LANMAN) ||
473                         (secFlags & CIFSSEC_MAY_PLNTXT))
474                         server->secType = LANMAN;
475                 else {
476                         cERROR(1, "mount failed weak security disabled"
477                                    " in /proc/fs/cifs/SecurityFlags");
478                         rc = -EOPNOTSUPP;
479                         goto neg_err_exit;
480                 }
481                 server->sec_mode = le16_to_cpu(rsp->SecurityMode);
482                 server->maxReq = min_t(unsigned int,
483                                        le16_to_cpu(rsp->MaxMpxCount),
484                                        cifs_max_pending);
485                 set_credits(server, server->maxReq);
486                 server->maxBuf = le16_to_cpu(rsp->MaxBufSize);
487                 server->max_vcs = le16_to_cpu(rsp->MaxNumberVcs);
488                 /* even though we do not use raw we might as well set this
489                 accurately, in case we ever find a need for it */
490                 if ((le16_to_cpu(rsp->RawMode) & RAW_ENABLE) == RAW_ENABLE) {
491                         server->max_rw = 0xFF00;
492                         server->capabilities = CAP_MPX_MODE | CAP_RAW_MODE;
493                 } else {
494                         server->max_rw = 0;/* do not need to use raw anyway */
495                         server->capabilities = CAP_MPX_MODE;
496                 }
497                 tmp = (__s16)le16_to_cpu(rsp->ServerTimeZone);
498                 if (tmp == -1) {
499                         /* OS/2 often does not set timezone therefore
500                          * we must use server time to calc time zone.
501                          * Could deviate slightly from the right zone.
502                          * Smallest defined timezone difference is 15 minutes
503                          * (i.e. Nepal).  Rounding up/down is done to match
504                          * this requirement.
505                          */
506                         int val, seconds, remain, result;
507                         struct timespec ts, utc;
508                         utc = CURRENT_TIME;
509                         ts = cnvrtDosUnixTm(rsp->SrvTime.Date,
510                                             rsp->SrvTime.Time, 0);
511                         cFYI(1, "SrvTime %d sec since 1970 (utc: %d) diff: %d",
512                                 (int)ts.tv_sec, (int)utc.tv_sec,
513                                 (int)(utc.tv_sec - ts.tv_sec));
514                         val = (int)(utc.tv_sec - ts.tv_sec);
515                         seconds = abs(val);
516                         result = (seconds / MIN_TZ_ADJ) * MIN_TZ_ADJ;
517                         remain = seconds % MIN_TZ_ADJ;
518                         if (remain >= (MIN_TZ_ADJ / 2))
519                                 result += MIN_TZ_ADJ;
520                         if (val < 0)
521                                 result = -result;
522                         server->timeAdj = result;
523                 } else {
524                         server->timeAdj = (int)tmp;
525                         server->timeAdj *= 60; /* also in seconds */
526                 }
527                 cFYI(1, "server->timeAdj: %d seconds", server->timeAdj);
528
529
530                 /* BB get server time for time conversions and add
531                 code to use it and timezone since this is not UTC */
532
533                 if (rsp->EncryptionKeyLength ==
534                                 cpu_to_le16(CIFS_CRYPTO_KEY_SIZE)) {
535                         memcpy(ses->server->cryptkey, rsp->EncryptionKey,
536                                 CIFS_CRYPTO_KEY_SIZE);
537                 } else if (server->sec_mode & SECMODE_PW_ENCRYPT) {
538                         rc = -EIO; /* need cryptkey unless plain text */
539                         goto neg_err_exit;
540                 }
541
542                 cFYI(1, "LANMAN negotiated");
543                 /* we will not end up setting signing flags - as no signing
544                 was in LANMAN and server did not return the flags on */
545                 goto signing_check;
546 #else /* weak security disabled */
547         } else if (pSMBr->hdr.WordCount == 13) {
548                 cERROR(1, "mount failed, cifs module not built "
549                           "with CIFS_WEAK_PW_HASH support");
550                 rc = -EOPNOTSUPP;
551 #endif /* WEAK_PW_HASH */
552                 goto neg_err_exit;
553         } else if (pSMBr->hdr.WordCount != 17) {
554                 /* unknown wct */
555                 rc = -EOPNOTSUPP;
556                 goto neg_err_exit;
557         }
558         /* else wct == 17 NTLM */
559         server->sec_mode = pSMBr->SecurityMode;
560         if ((server->sec_mode & SECMODE_USER) == 0)
561                 cFYI(1, "share mode security");
562
563         if ((server->sec_mode & SECMODE_PW_ENCRYPT) == 0)
564 #ifdef CONFIG_CIFS_WEAK_PW_HASH
565                 if ((secFlags & CIFSSEC_MAY_PLNTXT) == 0)
566 #endif /* CIFS_WEAK_PW_HASH */
567                         cERROR(1, "Server requests plain text password"
568                                   " but client support disabled");
569
570         if ((secFlags & CIFSSEC_MUST_NTLMV2) == CIFSSEC_MUST_NTLMV2)
571                 server->secType = NTLMv2;
572         else if (secFlags & CIFSSEC_MAY_NTLM)
573                 server->secType = NTLM;
574         else if (secFlags & CIFSSEC_MAY_NTLMV2)
575                 server->secType = NTLMv2;
576         else if (secFlags & CIFSSEC_MAY_KRB5)
577                 server->secType = Kerberos;
578         else if (secFlags & CIFSSEC_MAY_NTLMSSP)
579                 server->secType = RawNTLMSSP;
580         else if (secFlags & CIFSSEC_MAY_LANMAN)
581                 server->secType = LANMAN;
582         else {
583                 rc = -EOPNOTSUPP;
584                 cERROR(1, "Invalid security type");
585                 goto neg_err_exit;
586         }
587         /* else ... any others ...? */
588
589         /* one byte, so no need to convert this or EncryptionKeyLen from
590            little endian */
591         server->maxReq = min_t(unsigned int, le16_to_cpu(pSMBr->MaxMpxCount),
592                                cifs_max_pending);
593         set_credits(server, server->maxReq);
594         /* probably no need to store and check maxvcs */
595         server->maxBuf = le32_to_cpu(pSMBr->MaxBufferSize);
596         server->max_rw = le32_to_cpu(pSMBr->MaxRawSize);
597         cFYI(DBG2, "Max buf = %d", ses->server->maxBuf);
598         server->capabilities = le32_to_cpu(pSMBr->Capabilities);
599         server->timeAdj = (int)(__s16)le16_to_cpu(pSMBr->ServerTimeZone);
600         server->timeAdj *= 60;
601         if (pSMBr->EncryptionKeyLength == CIFS_CRYPTO_KEY_SIZE) {
602                 memcpy(ses->server->cryptkey, pSMBr->u.EncryptionKey,
603                        CIFS_CRYPTO_KEY_SIZE);
604         } else if ((pSMBr->hdr.Flags2 & SMBFLG2_EXT_SEC ||
605                         server->capabilities & CAP_EXTENDED_SECURITY) &&
606                                 (pSMBr->EncryptionKeyLength == 0)) {
607                 /* decode security blob */
608                 count = get_bcc(&pSMBr->hdr);
609                 if (count < 16) {
610                         rc = -EIO;
611                         goto neg_err_exit;
612                 }
613                 spin_lock(&cifs_tcp_ses_lock);
614                 if (server->srv_count > 1) {
615                         spin_unlock(&cifs_tcp_ses_lock);
616                         if (memcmp(server->server_GUID,
617                                    pSMBr->u.extended_response.
618                                    GUID, 16) != 0) {
619                                 cFYI(1, "server UID changed");
620                                 memcpy(server->server_GUID,
621                                         pSMBr->u.extended_response.GUID,
622                                         16);
623                         }
624                 } else {
625                         spin_unlock(&cifs_tcp_ses_lock);
626                         memcpy(server->server_GUID,
627                                pSMBr->u.extended_response.GUID, 16);
628                 }
629
630                 if (count == 16) {
631                         server->secType = RawNTLMSSP;
632                 } else {
633                         rc = decode_negTokenInit(pSMBr->u.extended_response.
634                                                  SecurityBlob, count - 16,
635                                                  server);
636                         if (rc == 1)
637                                 rc = 0;
638                         else
639                                 rc = -EINVAL;
640                         if (server->secType == Kerberos) {
641                                 if (!server->sec_kerberos &&
642                                                 !server->sec_mskerberos)
643                                         rc = -EOPNOTSUPP;
644                         } else if (server->secType == RawNTLMSSP) {
645                                 if (!server->sec_ntlmssp)
646                                         rc = -EOPNOTSUPP;
647                         } else
648                                         rc = -EOPNOTSUPP;
649                 }
650         } else if (server->sec_mode & SECMODE_PW_ENCRYPT) {
651                 rc = -EIO; /* no crypt key only if plain text pwd */
652                 goto neg_err_exit;
653         } else
654                 server->capabilities &= ~CAP_EXTENDED_SECURITY;
655
656 #ifdef CONFIG_CIFS_WEAK_PW_HASH
657 signing_check:
658 #endif
659         if ((secFlags & CIFSSEC_MAY_SIGN) == 0) {
660                 /* MUST_SIGN already includes the MAY_SIGN FLAG
661                    so if this is zero it means that signing is disabled */
662                 cFYI(1, "Signing disabled");
663                 if (server->sec_mode & SECMODE_SIGN_REQUIRED) {
664                         cERROR(1, "Server requires "
665                                    "packet signing to be enabled in "
666                                    "/proc/fs/cifs/SecurityFlags.");
667                         rc = -EOPNOTSUPP;
668                 }
669                 server->sec_mode &=
670                         ~(SECMODE_SIGN_ENABLED | SECMODE_SIGN_REQUIRED);
671         } else if ((secFlags & CIFSSEC_MUST_SIGN) == CIFSSEC_MUST_SIGN) {
672                 /* signing required */
673                 cFYI(1, "Must sign - secFlags 0x%x", secFlags);
674                 if ((server->sec_mode &
675                         (SECMODE_SIGN_ENABLED | SECMODE_SIGN_REQUIRED)) == 0) {
676                         cERROR(1, "signing required but server lacks support");
677                         rc = -EOPNOTSUPP;
678                 } else
679                         server->sec_mode |= SECMODE_SIGN_REQUIRED;
680         } else {
681                 /* signing optional ie CIFSSEC_MAY_SIGN */
682                 if ((server->sec_mode & SECMODE_SIGN_REQUIRED) == 0)
683                         server->sec_mode &=
684                                 ~(SECMODE_SIGN_ENABLED | SECMODE_SIGN_REQUIRED);
685         }
686
687 neg_err_exit:
688         cifs_buf_release(pSMB);
689
690         cFYI(1, "negprot rc %d", rc);
691         return rc;
692 }
693
694 int
695 CIFSSMBTDis(const unsigned int xid, struct cifs_tcon *tcon)
696 {
697         struct smb_hdr *smb_buffer;
698         int rc = 0;
699
700         cFYI(1, "In tree disconnect");
701
702         /* BB: do we need to check this? These should never be NULL. */
703         if ((tcon->ses == NULL) || (tcon->ses->server == NULL))
704                 return -EIO;
705
706         /*
707          * No need to return error on this operation if tid invalidated and
708          * closed on server already e.g. due to tcp session crashing. Also,
709          * the tcon is no longer on the list, so no need to take lock before
710          * checking this.
711          */
712         if ((tcon->need_reconnect) || (tcon->ses->need_reconnect))
713                 return 0;
714
715         rc = small_smb_init(SMB_COM_TREE_DISCONNECT, 0, tcon,
716                             (void **)&smb_buffer);
717         if (rc)
718                 return rc;
719
720         rc = SendReceiveNoRsp(xid, tcon->ses, (char *)smb_buffer, 0);
721         if (rc)
722                 cFYI(1, "Tree disconnect failed %d", rc);
723
724         /* No need to return error on this operation if tid invalidated and
725            closed on server already e.g. due to tcp session crashing */
726         if (rc == -EAGAIN)
727                 rc = 0;
728
729         return rc;
730 }
731
732 /*
733  * This is a no-op for now. We're not really interested in the reply, but
734  * rather in the fact that the server sent one and that server->lstrp
735  * gets updated.
736  *
737  * FIXME: maybe we should consider checking that the reply matches request?
738  */
739 static void
740 cifs_echo_callback(struct mid_q_entry *mid)
741 {
742         struct TCP_Server_Info *server = mid->callback_data;
743
744         DeleteMidQEntry(mid);
745         add_credits(server, 1, CIFS_ECHO_OP);
746 }
747
748 int
749 CIFSSMBEcho(struct TCP_Server_Info *server)
750 {
751         ECHO_REQ *smb;
752         int rc = 0;
753         struct kvec iov;
754
755         cFYI(1, "In echo request");
756
757         rc = small_smb_init(SMB_COM_ECHO, 0, NULL, (void **)&smb);
758         if (rc)
759                 return rc;
760
761         /* set up echo request */
762         smb->hdr.Tid = 0xffff;
763         smb->hdr.WordCount = 1;
764         put_unaligned_le16(1, &smb->EchoCount);
765         put_bcc(1, &smb->hdr);
766         smb->Data[0] = 'a';
767         inc_rfc1001_len(smb, 3);
768         iov.iov_base = smb;
769         iov.iov_len = be32_to_cpu(smb->hdr.smb_buf_length) + 4;
770
771         rc = cifs_call_async(server, &iov, 1, NULL, cifs_echo_callback,
772                              server, CIFS_ASYNC_OP | CIFS_ECHO_OP);
773         if (rc)
774                 cFYI(1, "Echo request failed: %d", rc);
775
776         cifs_small_buf_release(smb);
777
778         return rc;
779 }
780
781 int
782 CIFSSMBLogoff(const unsigned int xid, struct cifs_ses *ses)
783 {
784         LOGOFF_ANDX_REQ *pSMB;
785         int rc = 0;
786
787         cFYI(1, "In SMBLogoff for session disconnect");
788
789         /*
790          * BB: do we need to check validity of ses and server? They should
791          * always be valid since we have an active reference. If not, that
792          * should probably be a BUG()
793          */
794         if (!ses || !ses->server)
795                 return -EIO;
796
797         mutex_lock(&ses->session_mutex);
798         if (ses->need_reconnect)
799                 goto session_already_dead; /* no need to send SMBlogoff if uid
800                                               already closed due to reconnect */
801         rc = small_smb_init(SMB_COM_LOGOFF_ANDX, 2, NULL, (void **)&pSMB);
802         if (rc) {
803                 mutex_unlock(&ses->session_mutex);
804                 return rc;
805         }
806
807         pSMB->hdr.Mid = get_next_mid(ses->server);
808
809         if (ses->server->sec_mode &
810                    (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
811                         pSMB->hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
812
813         pSMB->hdr.Uid = ses->Suid;
814
815         pSMB->AndXCommand = 0xFF;
816         rc = SendReceiveNoRsp(xid, ses, (char *) pSMB, 0);
817 session_already_dead:
818         mutex_unlock(&ses->session_mutex);
819
820         /* if session dead then we do not need to do ulogoff,
821                 since server closed smb session, no sense reporting
822                 error */
823         if (rc == -EAGAIN)
824                 rc = 0;
825         return rc;
826 }
827
828 int
829 CIFSPOSIXDelFile(const unsigned int xid, struct cifs_tcon *tcon,
830                  const char *fileName, __u16 type,
831                  const struct nls_table *nls_codepage, int remap)
832 {
833         TRANSACTION2_SPI_REQ *pSMB = NULL;
834         TRANSACTION2_SPI_RSP *pSMBr = NULL;
835         struct unlink_psx_rq *pRqD;
836         int name_len;
837         int rc = 0;
838         int bytes_returned = 0;
839         __u16 params, param_offset, offset, byte_count;
840
841         cFYI(1, "In POSIX delete");
842 PsxDelete:
843         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
844                       (void **) &pSMBr);
845         if (rc)
846                 return rc;
847
848         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
849                 name_len =
850                     cifsConvertToUTF16((__le16 *) pSMB->FileName, fileName,
851                                        PATH_MAX, nls_codepage, remap);
852                 name_len++;     /* trailing null */
853                 name_len *= 2;
854         } else { /* BB add path length overrun check */
855                 name_len = strnlen(fileName, PATH_MAX);
856                 name_len++;     /* trailing null */
857                 strncpy(pSMB->FileName, fileName, name_len);
858         }
859
860         params = 6 + name_len;
861         pSMB->MaxParameterCount = cpu_to_le16(2);
862         pSMB->MaxDataCount = 0; /* BB double check this with jra */
863         pSMB->MaxSetupCount = 0;
864         pSMB->Reserved = 0;
865         pSMB->Flags = 0;
866         pSMB->Timeout = 0;
867         pSMB->Reserved2 = 0;
868         param_offset = offsetof(struct smb_com_transaction2_spi_req,
869                                 InformationLevel) - 4;
870         offset = param_offset + params;
871
872         /* Setup pointer to Request Data (inode type) */
873         pRqD = (struct unlink_psx_rq *)(((char *)&pSMB->hdr.Protocol) + offset);
874         pRqD->type = cpu_to_le16(type);
875         pSMB->ParameterOffset = cpu_to_le16(param_offset);
876         pSMB->DataOffset = cpu_to_le16(offset);
877         pSMB->SetupCount = 1;
878         pSMB->Reserved3 = 0;
879         pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
880         byte_count = 3 /* pad */  + params + sizeof(struct unlink_psx_rq);
881
882         pSMB->DataCount = cpu_to_le16(sizeof(struct unlink_psx_rq));
883         pSMB->TotalDataCount = cpu_to_le16(sizeof(struct unlink_psx_rq));
884         pSMB->ParameterCount = cpu_to_le16(params);
885         pSMB->TotalParameterCount = pSMB->ParameterCount;
886         pSMB->InformationLevel = cpu_to_le16(SMB_POSIX_UNLINK);
887         pSMB->Reserved4 = 0;
888         inc_rfc1001_len(pSMB, byte_count);
889         pSMB->ByteCount = cpu_to_le16(byte_count);
890         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
891                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
892         if (rc)
893                 cFYI(1, "Posix delete returned %d", rc);
894         cifs_buf_release(pSMB);
895
896         cifs_stats_inc(&tcon->stats.cifs_stats.num_deletes);
897
898         if (rc == -EAGAIN)
899                 goto PsxDelete;
900
901         return rc;
902 }
903
904 int
905 CIFSSMBDelFile(const unsigned int xid, struct cifs_tcon *tcon,
906                const char *fileName, const struct nls_table *nls_codepage,
907                int remap)
908 {
909         DELETE_FILE_REQ *pSMB = NULL;
910         DELETE_FILE_RSP *pSMBr = NULL;
911         int rc = 0;
912         int bytes_returned;
913         int name_len;
914
915 DelFileRetry:
916         rc = smb_init(SMB_COM_DELETE, 1, tcon, (void **) &pSMB,
917                       (void **) &pSMBr);
918         if (rc)
919                 return rc;
920
921         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
922                 name_len =
923                     cifsConvertToUTF16((__le16 *) pSMB->fileName, fileName,
924                                        PATH_MAX, nls_codepage, remap);
925                 name_len++;     /* trailing null */
926                 name_len *= 2;
927         } else {                /* BB improve check for buffer overruns BB */
928                 name_len = strnlen(fileName, PATH_MAX);
929                 name_len++;     /* trailing null */
930                 strncpy(pSMB->fileName, fileName, name_len);
931         }
932         pSMB->SearchAttributes =
933             cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM);
934         pSMB->BufferFormat = 0x04;
935         inc_rfc1001_len(pSMB, name_len + 1);
936         pSMB->ByteCount = cpu_to_le16(name_len + 1);
937         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
938                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
939         cifs_stats_inc(&tcon->stats.cifs_stats.num_deletes);
940         if (rc)
941                 cFYI(1, "Error in RMFile = %d", rc);
942
943         cifs_buf_release(pSMB);
944         if (rc == -EAGAIN)
945                 goto DelFileRetry;
946
947         return rc;
948 }
949
950 int
951 CIFSSMBRmDir(const unsigned int xid, struct cifs_tcon *tcon,
952              const char *dirName, const struct nls_table *nls_codepage,
953              int remap)
954 {
955         DELETE_DIRECTORY_REQ *pSMB = NULL;
956         DELETE_DIRECTORY_RSP *pSMBr = NULL;
957         int rc = 0;
958         int bytes_returned;
959         int name_len;
960
961         cFYI(1, "In CIFSSMBRmDir");
962 RmDirRetry:
963         rc = smb_init(SMB_COM_DELETE_DIRECTORY, 0, tcon, (void **) &pSMB,
964                       (void **) &pSMBr);
965         if (rc)
966                 return rc;
967
968         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
969                 name_len = cifsConvertToUTF16((__le16 *) pSMB->DirName, dirName,
970                                               PATH_MAX, nls_codepage, remap);
971                 name_len++;     /* trailing null */
972                 name_len *= 2;
973         } else {                /* BB improve check for buffer overruns BB */
974                 name_len = strnlen(dirName, PATH_MAX);
975                 name_len++;     /* trailing null */
976                 strncpy(pSMB->DirName, dirName, name_len);
977         }
978
979         pSMB->BufferFormat = 0x04;
980         inc_rfc1001_len(pSMB, name_len + 1);
981         pSMB->ByteCount = cpu_to_le16(name_len + 1);
982         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
983                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
984         cifs_stats_inc(&tcon->stats.cifs_stats.num_rmdirs);
985         if (rc)
986                 cFYI(1, "Error in RMDir = %d", rc);
987
988         cifs_buf_release(pSMB);
989         if (rc == -EAGAIN)
990                 goto RmDirRetry;
991         return rc;
992 }
993
994 int
995 CIFSSMBMkDir(const unsigned int xid, struct cifs_tcon *tcon,
996              const char *name, const struct nls_table *nls_codepage, int remap)
997 {
998         int rc = 0;
999         CREATE_DIRECTORY_REQ *pSMB = NULL;
1000         CREATE_DIRECTORY_RSP *pSMBr = NULL;
1001         int bytes_returned;
1002         int name_len;
1003
1004         cFYI(1, "In CIFSSMBMkDir");
1005 MkDirRetry:
1006         rc = smb_init(SMB_COM_CREATE_DIRECTORY, 0, tcon, (void **) &pSMB,
1007                       (void **) &pSMBr);
1008         if (rc)
1009                 return rc;
1010
1011         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1012                 name_len = cifsConvertToUTF16((__le16 *) pSMB->DirName, name,
1013                                               PATH_MAX, nls_codepage, remap);
1014                 name_len++;     /* trailing null */
1015                 name_len *= 2;
1016         } else {                /* BB improve check for buffer overruns BB */
1017                 name_len = strnlen(name, PATH_MAX);
1018                 name_len++;     /* trailing null */
1019                 strncpy(pSMB->DirName, name, name_len);
1020         }
1021
1022         pSMB->BufferFormat = 0x04;
1023         inc_rfc1001_len(pSMB, name_len + 1);
1024         pSMB->ByteCount = cpu_to_le16(name_len + 1);
1025         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1026                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1027         cifs_stats_inc(&tcon->stats.cifs_stats.num_mkdirs);
1028         if (rc)
1029                 cFYI(1, "Error in Mkdir = %d", rc);
1030
1031         cifs_buf_release(pSMB);
1032         if (rc == -EAGAIN)
1033                 goto MkDirRetry;
1034         return rc;
1035 }
1036
1037 int
1038 CIFSPOSIXCreate(const unsigned int xid, struct cifs_tcon *tcon,
1039                 __u32 posix_flags, __u64 mode, __u16 *netfid,
1040                 FILE_UNIX_BASIC_INFO *pRetData, __u32 *pOplock,
1041                 const char *name, const struct nls_table *nls_codepage,
1042                 int remap)
1043 {
1044         TRANSACTION2_SPI_REQ *pSMB = NULL;
1045         TRANSACTION2_SPI_RSP *pSMBr = NULL;
1046         int name_len;
1047         int rc = 0;
1048         int bytes_returned = 0;
1049         __u16 params, param_offset, offset, byte_count, count;
1050         OPEN_PSX_REQ *pdata;
1051         OPEN_PSX_RSP *psx_rsp;
1052
1053         cFYI(1, "In POSIX Create");
1054 PsxCreat:
1055         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
1056                       (void **) &pSMBr);
1057         if (rc)
1058                 return rc;
1059
1060         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1061                 name_len =
1062                     cifsConvertToUTF16((__le16 *) pSMB->FileName, name,
1063                                        PATH_MAX, nls_codepage, remap);
1064                 name_len++;     /* trailing null */
1065                 name_len *= 2;
1066         } else {        /* BB improve the check for buffer overruns BB */
1067                 name_len = strnlen(name, PATH_MAX);
1068                 name_len++;     /* trailing null */
1069                 strncpy(pSMB->FileName, name, name_len);
1070         }
1071
1072         params = 6 + name_len;
1073         count = sizeof(OPEN_PSX_REQ);
1074         pSMB->MaxParameterCount = cpu_to_le16(2);
1075         pSMB->MaxDataCount = cpu_to_le16(1000); /* large enough */
1076         pSMB->MaxSetupCount = 0;
1077         pSMB->Reserved = 0;
1078         pSMB->Flags = 0;
1079         pSMB->Timeout = 0;
1080         pSMB->Reserved2 = 0;
1081         param_offset = offsetof(struct smb_com_transaction2_spi_req,
1082                                 InformationLevel) - 4;
1083         offset = param_offset + params;
1084         pdata = (OPEN_PSX_REQ *)(((char *)&pSMB->hdr.Protocol) + offset);
1085         pdata->Level = cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC);
1086         pdata->Permissions = cpu_to_le64(mode);
1087         pdata->PosixOpenFlags = cpu_to_le32(posix_flags);
1088         pdata->OpenFlags =  cpu_to_le32(*pOplock);
1089         pSMB->ParameterOffset = cpu_to_le16(param_offset);
1090         pSMB->DataOffset = cpu_to_le16(offset);
1091         pSMB->SetupCount = 1;
1092         pSMB->Reserved3 = 0;
1093         pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
1094         byte_count = 3 /* pad */  + params + count;
1095
1096         pSMB->DataCount = cpu_to_le16(count);
1097         pSMB->ParameterCount = cpu_to_le16(params);
1098         pSMB->TotalDataCount = pSMB->DataCount;
1099         pSMB->TotalParameterCount = pSMB->ParameterCount;
1100         pSMB->InformationLevel = cpu_to_le16(SMB_POSIX_OPEN);
1101         pSMB->Reserved4 = 0;
1102         inc_rfc1001_len(pSMB, byte_count);
1103         pSMB->ByteCount = cpu_to_le16(byte_count);
1104         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1105                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1106         if (rc) {
1107                 cFYI(1, "Posix create returned %d", rc);
1108                 goto psx_create_err;
1109         }
1110
1111         cFYI(1, "copying inode info");
1112         rc = validate_t2((struct smb_t2_rsp *)pSMBr);
1113
1114         if (rc || get_bcc(&pSMBr->hdr) < sizeof(OPEN_PSX_RSP)) {
1115                 rc = -EIO;      /* bad smb */
1116                 goto psx_create_err;
1117         }
1118
1119         /* copy return information to pRetData */
1120         psx_rsp = (OPEN_PSX_RSP *)((char *) &pSMBr->hdr.Protocol
1121                         + le16_to_cpu(pSMBr->t2.DataOffset));
1122
1123         *pOplock = le16_to_cpu(psx_rsp->OplockFlags);
1124         if (netfid)
1125                 *netfid = psx_rsp->Fid;   /* cifs fid stays in le */
1126         /* Let caller know file was created so we can set the mode. */
1127         /* Do we care about the CreateAction in any other cases? */
1128         if (cpu_to_le32(FILE_CREATE) == psx_rsp->CreateAction)
1129                 *pOplock |= CIFS_CREATE_ACTION;
1130         /* check to make sure response data is there */
1131         if (psx_rsp->ReturnedLevel != cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC)) {
1132                 pRetData->Type = cpu_to_le32(-1); /* unknown */
1133                 cFYI(DBG2, "unknown type");
1134         } else {
1135                 if (get_bcc(&pSMBr->hdr) < sizeof(OPEN_PSX_RSP)
1136                                         + sizeof(FILE_UNIX_BASIC_INFO)) {
1137                         cERROR(1, "Open response data too small");
1138                         pRetData->Type = cpu_to_le32(-1);
1139                         goto psx_create_err;
1140                 }
1141                 memcpy((char *) pRetData,
1142                         (char *)psx_rsp + sizeof(OPEN_PSX_RSP),
1143                         sizeof(FILE_UNIX_BASIC_INFO));
1144         }
1145
1146 psx_create_err:
1147         cifs_buf_release(pSMB);
1148
1149         if (posix_flags & SMB_O_DIRECTORY)
1150                 cifs_stats_inc(&tcon->stats.cifs_stats.num_posixmkdirs);
1151         else
1152                 cifs_stats_inc(&tcon->stats.cifs_stats.num_posixopens);
1153
1154         if (rc == -EAGAIN)
1155                 goto PsxCreat;
1156
1157         return rc;
1158 }
1159
1160 static __u16 convert_disposition(int disposition)
1161 {
1162         __u16 ofun = 0;
1163
1164         switch (disposition) {
1165                 case FILE_SUPERSEDE:
1166                         ofun = SMBOPEN_OCREATE | SMBOPEN_OTRUNC;
1167                         break;
1168                 case FILE_OPEN:
1169                         ofun = SMBOPEN_OAPPEND;
1170                         break;
1171                 case FILE_CREATE:
1172                         ofun = SMBOPEN_OCREATE;
1173                         break;
1174                 case FILE_OPEN_IF:
1175                         ofun = SMBOPEN_OCREATE | SMBOPEN_OAPPEND;
1176                         break;
1177                 case FILE_OVERWRITE:
1178                         ofun = SMBOPEN_OTRUNC;
1179                         break;
1180                 case FILE_OVERWRITE_IF:
1181                         ofun = SMBOPEN_OCREATE | SMBOPEN_OTRUNC;
1182                         break;
1183                 default:
1184                         cFYI(1, "unknown disposition %d", disposition);
1185                         ofun =  SMBOPEN_OAPPEND; /* regular open */
1186         }
1187         return ofun;
1188 }
1189
1190 static int
1191 access_flags_to_smbopen_mode(const int access_flags)
1192 {
1193         int masked_flags = access_flags & (GENERIC_READ | GENERIC_WRITE);
1194
1195         if (masked_flags == GENERIC_READ)
1196                 return SMBOPEN_READ;
1197         else if (masked_flags == GENERIC_WRITE)
1198                 return SMBOPEN_WRITE;
1199
1200         /* just go for read/write */
1201         return SMBOPEN_READWRITE;
1202 }
1203
1204 int
1205 SMBLegacyOpen(const unsigned int xid, struct cifs_tcon *tcon,
1206             const char *fileName, const int openDisposition,
1207             const int access_flags, const int create_options, __u16 *netfid,
1208             int *pOplock, FILE_ALL_INFO *pfile_info,
1209             const struct nls_table *nls_codepage, int remap)
1210 {
1211         int rc = -EACCES;
1212         OPENX_REQ *pSMB = NULL;
1213         OPENX_RSP *pSMBr = NULL;
1214         int bytes_returned;
1215         int name_len;
1216         __u16 count;
1217
1218 OldOpenRetry:
1219         rc = smb_init(SMB_COM_OPEN_ANDX, 15, tcon, (void **) &pSMB,
1220                       (void **) &pSMBr);
1221         if (rc)
1222                 return rc;
1223
1224         pSMB->AndXCommand = 0xFF;       /* none */
1225
1226         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1227                 count = 1;      /* account for one byte pad to word boundary */
1228                 name_len =
1229                    cifsConvertToUTF16((__le16 *) (pSMB->fileName + 1),
1230                                       fileName, PATH_MAX, nls_codepage, remap);
1231                 name_len++;     /* trailing null */
1232                 name_len *= 2;
1233         } else {                /* BB improve check for buffer overruns BB */
1234                 count = 0;      /* no pad */
1235                 name_len = strnlen(fileName, PATH_MAX);
1236                 name_len++;     /* trailing null */
1237                 strncpy(pSMB->fileName, fileName, name_len);
1238         }
1239         if (*pOplock & REQ_OPLOCK)
1240                 pSMB->OpenFlags = cpu_to_le16(REQ_OPLOCK);
1241         else if (*pOplock & REQ_BATCHOPLOCK)
1242                 pSMB->OpenFlags = cpu_to_le16(REQ_BATCHOPLOCK);
1243
1244         pSMB->OpenFlags |= cpu_to_le16(REQ_MORE_INFO);
1245         pSMB->Mode = cpu_to_le16(access_flags_to_smbopen_mode(access_flags));
1246         pSMB->Mode |= cpu_to_le16(0x40); /* deny none */
1247         /* set file as system file if special file such
1248            as fifo and server expecting SFU style and
1249            no Unix extensions */
1250
1251         if (create_options & CREATE_OPTION_SPECIAL)
1252                 pSMB->FileAttributes = cpu_to_le16(ATTR_SYSTEM);
1253         else /* BB FIXME BB */
1254                 pSMB->FileAttributes = cpu_to_le16(0/*ATTR_NORMAL*/);
1255
1256         if (create_options & CREATE_OPTION_READONLY)
1257                 pSMB->FileAttributes |= cpu_to_le16(ATTR_READONLY);
1258
1259         /* BB FIXME BB */
1260 /*      pSMB->CreateOptions = cpu_to_le32(create_options &
1261                                                  CREATE_OPTIONS_MASK); */
1262         /* BB FIXME END BB */
1263
1264         pSMB->Sattr = cpu_to_le16(ATTR_HIDDEN | ATTR_SYSTEM | ATTR_DIRECTORY);
1265         pSMB->OpenFunction = cpu_to_le16(convert_disposition(openDisposition));
1266         count += name_len;
1267         inc_rfc1001_len(pSMB, count);
1268
1269         pSMB->ByteCount = cpu_to_le16(count);
1270         /* long_op set to 1 to allow for oplock break timeouts */
1271         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1272                         (struct smb_hdr *)pSMBr, &bytes_returned, 0);
1273         cifs_stats_inc(&tcon->stats.cifs_stats.num_opens);
1274         if (rc) {
1275                 cFYI(1, "Error in Open = %d", rc);
1276         } else {
1277         /* BB verify if wct == 15 */
1278
1279 /*              *pOplock = pSMBr->OplockLevel; */ /* BB take from action field*/
1280
1281                 *netfid = pSMBr->Fid;   /* cifs fid stays in le */
1282                 /* Let caller know file was created so we can set the mode. */
1283                 /* Do we care about the CreateAction in any other cases? */
1284         /* BB FIXME BB */
1285 /*              if (cpu_to_le32(FILE_CREATE) == pSMBr->CreateAction)
1286                         *pOplock |= CIFS_CREATE_ACTION; */
1287         /* BB FIXME END */
1288
1289                 if (pfile_info) {
1290                         pfile_info->CreationTime = 0; /* BB convert CreateTime*/
1291                         pfile_info->LastAccessTime = 0; /* BB fixme */
1292                         pfile_info->LastWriteTime = 0; /* BB fixme */
1293                         pfile_info->ChangeTime = 0;  /* BB fixme */
1294                         pfile_info->Attributes =
1295                                 cpu_to_le32(le16_to_cpu(pSMBr->FileAttributes));
1296                         /* the file_info buf is endian converted by caller */
1297                         pfile_info->AllocationSize =
1298                                 cpu_to_le64(le32_to_cpu(pSMBr->EndOfFile));
1299                         pfile_info->EndOfFile = pfile_info->AllocationSize;
1300                         pfile_info->NumberOfLinks = cpu_to_le32(1);
1301                         pfile_info->DeletePending = 0;
1302                 }
1303         }
1304
1305         cifs_buf_release(pSMB);
1306         if (rc == -EAGAIN)
1307                 goto OldOpenRetry;
1308         return rc;
1309 }
1310
1311 int
1312 CIFSSMBOpen(const unsigned int xid, struct cifs_tcon *tcon,
1313             const char *fileName, const int openDisposition,
1314             const int access_flags, const int create_options, __u16 *netfid,
1315             int *pOplock, FILE_ALL_INFO *pfile_info,
1316             const struct nls_table *nls_codepage, int remap)
1317 {
1318         int rc = -EACCES;
1319         OPEN_REQ *pSMB = NULL;
1320         OPEN_RSP *pSMBr = NULL;
1321         int bytes_returned;
1322         int name_len;
1323         __u16 count;
1324
1325 openRetry:
1326         rc = smb_init(SMB_COM_NT_CREATE_ANDX, 24, tcon, (void **) &pSMB,
1327                       (void **) &pSMBr);
1328         if (rc)
1329                 return rc;
1330
1331         pSMB->AndXCommand = 0xFF;       /* none */
1332
1333         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1334                 count = 1;      /* account for one byte pad to word boundary */
1335                 name_len =
1336                     cifsConvertToUTF16((__le16 *) (pSMB->fileName + 1),
1337                                        fileName, PATH_MAX, nls_codepage, remap);
1338                 name_len++;     /* trailing null */
1339                 name_len *= 2;
1340                 pSMB->NameLength = cpu_to_le16(name_len);
1341         } else {                /* BB improve check for buffer overruns BB */
1342                 count = 0;      /* no pad */
1343                 name_len = strnlen(fileName, PATH_MAX);
1344                 name_len++;     /* trailing null */
1345                 pSMB->NameLength = cpu_to_le16(name_len);
1346                 strncpy(pSMB->fileName, fileName, name_len);
1347         }
1348         if (*pOplock & REQ_OPLOCK)
1349                 pSMB->OpenFlags = cpu_to_le32(REQ_OPLOCK);
1350         else if (*pOplock & REQ_BATCHOPLOCK)
1351                 pSMB->OpenFlags = cpu_to_le32(REQ_BATCHOPLOCK);
1352         pSMB->DesiredAccess = cpu_to_le32(access_flags);
1353         pSMB->AllocationSize = 0;
1354         /* set file as system file if special file such
1355            as fifo and server expecting SFU style and
1356            no Unix extensions */
1357         if (create_options & CREATE_OPTION_SPECIAL)
1358                 pSMB->FileAttributes = cpu_to_le32(ATTR_SYSTEM);
1359         else
1360                 pSMB->FileAttributes = cpu_to_le32(ATTR_NORMAL);
1361
1362         /* XP does not handle ATTR_POSIX_SEMANTICS */
1363         /* but it helps speed up case sensitive checks for other
1364         servers such as Samba */
1365         if (tcon->ses->capabilities & CAP_UNIX)
1366                 pSMB->FileAttributes |= cpu_to_le32(ATTR_POSIX_SEMANTICS);
1367
1368         if (create_options & CREATE_OPTION_READONLY)
1369                 pSMB->FileAttributes |= cpu_to_le32(ATTR_READONLY);
1370
1371         pSMB->ShareAccess = cpu_to_le32(FILE_SHARE_ALL);
1372         pSMB->CreateDisposition = cpu_to_le32(openDisposition);
1373         pSMB->CreateOptions = cpu_to_le32(create_options & CREATE_OPTIONS_MASK);
1374         /* BB Expirement with various impersonation levels and verify */
1375         pSMB->ImpersonationLevel = cpu_to_le32(SECURITY_IMPERSONATION);
1376         pSMB->SecurityFlags =
1377             SECURITY_CONTEXT_TRACKING | SECURITY_EFFECTIVE_ONLY;
1378
1379         count += name_len;
1380         inc_rfc1001_len(pSMB, count);
1381
1382         pSMB->ByteCount = cpu_to_le16(count);
1383         /* long_op set to 1 to allow for oplock break timeouts */
1384         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1385                         (struct smb_hdr *)pSMBr, &bytes_returned, 0);
1386         cifs_stats_inc(&tcon->stats.cifs_stats.num_opens);
1387         if (rc) {
1388                 cFYI(1, "Error in Open = %d", rc);
1389         } else {
1390                 *pOplock = pSMBr->OplockLevel; /* 1 byte no need to le_to_cpu */
1391                 *netfid = pSMBr->Fid;   /* cifs fid stays in le */
1392                 /* Let caller know file was created so we can set the mode. */
1393                 /* Do we care about the CreateAction in any other cases? */
1394                 if (cpu_to_le32(FILE_CREATE) == pSMBr->CreateAction)
1395                         *pOplock |= CIFS_CREATE_ACTION;
1396                 if (pfile_info) {
1397                         memcpy((char *)pfile_info, (char *)&pSMBr->CreationTime,
1398                                 36 /* CreationTime to Attributes */);
1399                         /* the file_info buf is endian converted by caller */
1400                         pfile_info->AllocationSize = pSMBr->AllocationSize;
1401                         pfile_info->EndOfFile = pSMBr->EndOfFile;
1402                         pfile_info->NumberOfLinks = cpu_to_le32(1);
1403                         pfile_info->DeletePending = 0;
1404                 }
1405         }
1406
1407         cifs_buf_release(pSMB);
1408         if (rc == -EAGAIN)
1409                 goto openRetry;
1410         return rc;
1411 }
1412
1413 /*
1414  * Discard any remaining data in the current SMB. To do this, we borrow the
1415  * current bigbuf.
1416  */
1417 static int
1418 cifs_readv_discard(struct TCP_Server_Info *server, struct mid_q_entry *mid)
1419 {
1420         unsigned int rfclen = get_rfc1002_length(server->smallbuf);
1421         int remaining = rfclen + 4 - server->total_read;
1422         struct cifs_readdata *rdata = mid->callback_data;
1423
1424         while (remaining > 0) {
1425                 int length;
1426
1427                 length = cifs_read_from_socket(server, server->bigbuf,
1428                                 min_t(unsigned int, remaining,
1429                                     CIFSMaxBufSize + MAX_HEADER_SIZE(server)));
1430                 if (length < 0)
1431                         return length;
1432                 server->total_read += length;
1433                 remaining -= length;
1434         }
1435
1436         dequeue_mid(mid, rdata->result);
1437         return 0;
1438 }
1439
1440 static int
1441 cifs_readv_receive(struct TCP_Server_Info *server, struct mid_q_entry *mid)
1442 {
1443         int length, len;
1444         unsigned int data_offset, data_len;
1445         struct cifs_readdata *rdata = mid->callback_data;
1446         char *buf = server->smallbuf;
1447         unsigned int buflen = get_rfc1002_length(buf) + 4;
1448
1449         cFYI(1, "%s: mid=%llu offset=%llu bytes=%u", __func__,
1450                 mid->mid, rdata->offset, rdata->bytes);
1451
1452         /*
1453          * read the rest of READ_RSP header (sans Data array), or whatever we
1454          * can if there's not enough data. At this point, we've read down to
1455          * the Mid.
1456          */
1457         len = min_t(unsigned int, buflen, server->vals->read_rsp_size) -
1458                                                         HEADER_SIZE(server) + 1;
1459
1460         rdata->iov[0].iov_base = buf + HEADER_SIZE(server) - 1;
1461         rdata->iov[0].iov_len = len;
1462
1463         length = cifs_readv_from_socket(server, rdata->iov, 1, len);
1464         if (length < 0)
1465                 return length;
1466         server->total_read += length;
1467
1468         /* Was the SMB read successful? */
1469         rdata->result = server->ops->map_error(buf, false);
1470         if (rdata->result != 0) {
1471                 cFYI(1, "%s: server returned error %d", __func__,
1472                         rdata->result);
1473                 return cifs_readv_discard(server, mid);
1474         }
1475
1476         /* Is there enough to get to the rest of the READ_RSP header? */
1477         if (server->total_read < server->vals->read_rsp_size) {
1478                 cFYI(1, "%s: server returned short header. got=%u expected=%zu",
1479                         __func__, server->total_read,
1480                         server->vals->read_rsp_size);
1481                 rdata->result = -EIO;
1482                 return cifs_readv_discard(server, mid);
1483         }
1484
1485         data_offset = server->ops->read_data_offset(buf) + 4;
1486         if (data_offset < server->total_read) {
1487                 /*
1488                  * win2k8 sometimes sends an offset of 0 when the read
1489                  * is beyond the EOF. Treat it as if the data starts just after
1490                  * the header.
1491                  */
1492                 cFYI(1, "%s: data offset (%u) inside read response header",
1493                         __func__, data_offset);
1494                 data_offset = server->total_read;
1495         } else if (data_offset > MAX_CIFS_SMALL_BUFFER_SIZE) {
1496                 /* data_offset is beyond the end of smallbuf */
1497                 cFYI(1, "%s: data offset (%u) beyond end of smallbuf",
1498                         __func__, data_offset);
1499                 rdata->result = -EIO;
1500                 return cifs_readv_discard(server, mid);
1501         }
1502
1503         cFYI(1, "%s: total_read=%u data_offset=%u", __func__,
1504                 server->total_read, data_offset);
1505
1506         len = data_offset - server->total_read;
1507         if (len > 0) {
1508                 /* read any junk before data into the rest of smallbuf */
1509                 rdata->iov[0].iov_base = buf + server->total_read;
1510                 rdata->iov[0].iov_len = len;
1511                 length = cifs_readv_from_socket(server, rdata->iov, 1, len);
1512                 if (length < 0)
1513                         return length;
1514                 server->total_read += length;
1515         }
1516
1517         /* set up first iov for signature check */
1518         rdata->iov[0].iov_base = buf;
1519         rdata->iov[0].iov_len = server->total_read;
1520         cFYI(1, "0: iov_base=%p iov_len=%zu",
1521                 rdata->iov[0].iov_base, rdata->iov[0].iov_len);
1522
1523         /* how much data is in the response? */
1524         data_len = server->ops->read_data_length(buf);
1525         if (data_offset + data_len > buflen) {
1526                 /* data_len is corrupt -- discard frame */
1527                 rdata->result = -EIO;
1528                 return cifs_readv_discard(server, mid);
1529         }
1530
1531         /* marshal up the page array */
1532         cifs_kmap_lock();
1533         len = rdata->marshal_iov(rdata, data_len);
1534         cifs_kmap_unlock();
1535         data_len -= len;
1536
1537         /* issue the read if we have any iovecs left to fill */
1538         if (rdata->nr_iov > 1) {
1539                 length = cifs_readv_from_socket(server, &rdata->iov[1],
1540                                                 rdata->nr_iov - 1, len);
1541                 if (length < 0)
1542                         return length;
1543                 server->total_read += length;
1544         } else {
1545                 length = 0;
1546         }
1547
1548         rdata->bytes = length;
1549
1550         cFYI(1, "total_read=%u buflen=%u remaining=%u", server->total_read,
1551                 buflen, data_len);
1552
1553         /* discard anything left over */
1554         if (server->total_read < buflen)
1555                 return cifs_readv_discard(server, mid);
1556
1557         dequeue_mid(mid, false);
1558         return length;
1559 }
1560
1561 static void
1562 cifs_readv_callback(struct mid_q_entry *mid)
1563 {
1564         struct cifs_readdata *rdata = mid->callback_data;
1565         struct cifs_tcon *tcon = tlink_tcon(rdata->cfile->tlink);
1566         struct TCP_Server_Info *server = tcon->ses->server;
1567
1568         cFYI(1, "%s: mid=%llu state=%d result=%d bytes=%u", __func__,
1569                 mid->mid, mid->mid_state, rdata->result, rdata->bytes);
1570
1571         switch (mid->mid_state) {
1572         case MID_RESPONSE_RECEIVED:
1573                 /* result already set, check signature */
1574                 if (server->sec_mode &
1575                     (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED)) {
1576                         if (cifs_verify_signature(rdata->iov, rdata->nr_iov,
1577                                           server, mid->sequence_number + 1))
1578                                 cERROR(1, "Unexpected SMB signature");
1579                 }
1580                 /* FIXME: should this be counted toward the initiating task? */
1581                 task_io_account_read(rdata->bytes);
1582                 cifs_stats_bytes_read(tcon, rdata->bytes);
1583                 break;
1584         case MID_REQUEST_SUBMITTED:
1585         case MID_RETRY_NEEDED:
1586                 rdata->result = -EAGAIN;
1587                 break;
1588         default:
1589                 rdata->result = -EIO;
1590         }
1591
1592         queue_work(cifsiod_wq, &rdata->work);
1593         DeleteMidQEntry(mid);
1594         add_credits(server, 1, 0);
1595 }
1596
1597 /* cifs_async_readv - send an async write, and set up mid to handle result */
1598 int
1599 cifs_async_readv(struct cifs_readdata *rdata)
1600 {
1601         int rc;
1602         READ_REQ *smb = NULL;
1603         int wct;
1604         struct cifs_tcon *tcon = tlink_tcon(rdata->cfile->tlink);
1605
1606         cFYI(1, "%s: offset=%llu bytes=%u", __func__,
1607                 rdata->offset, rdata->bytes);
1608
1609         if (tcon->ses->capabilities & CAP_LARGE_FILES)
1610                 wct = 12;
1611         else {
1612                 wct = 10; /* old style read */
1613                 if ((rdata->offset >> 32) > 0)  {
1614                         /* can not handle this big offset for old */
1615                         return -EIO;
1616                 }
1617         }
1618
1619         rc = small_smb_init(SMB_COM_READ_ANDX, wct, tcon, (void **)&smb);
1620         if (rc)
1621                 return rc;
1622
1623         smb->hdr.Pid = cpu_to_le16((__u16)rdata->pid);
1624         smb->hdr.PidHigh = cpu_to_le16((__u16)(rdata->pid >> 16));
1625
1626         smb->AndXCommand = 0xFF;        /* none */
1627         smb->Fid = rdata->cfile->netfid;
1628         smb->OffsetLow = cpu_to_le32(rdata->offset & 0xFFFFFFFF);
1629         if (wct == 12)
1630                 smb->OffsetHigh = cpu_to_le32(rdata->offset >> 32);
1631         smb->Remaining = 0;
1632         smb->MaxCount = cpu_to_le16(rdata->bytes & 0xFFFF);
1633         smb->MaxCountHigh = cpu_to_le32(rdata->bytes >> 16);
1634         if (wct == 12)
1635                 smb->ByteCount = 0;
1636         else {
1637                 /* old style read */
1638                 struct smb_com_readx_req *smbr =
1639                         (struct smb_com_readx_req *)smb;
1640                 smbr->ByteCount = 0;
1641         }
1642
1643         /* 4 for RFC1001 length + 1 for BCC */
1644         rdata->iov[0].iov_base = smb;
1645         rdata->iov[0].iov_len = be32_to_cpu(smb->hdr.smb_buf_length) + 4;
1646
1647         kref_get(&rdata->refcount);
1648         rc = cifs_call_async(tcon->ses->server, rdata->iov, 1,
1649                              cifs_readv_receive, cifs_readv_callback,
1650                              rdata, 0);
1651
1652         if (rc == 0)
1653                 cifs_stats_inc(&tcon->stats.cifs_stats.num_reads);
1654         else
1655                 kref_put(&rdata->refcount, cifs_readdata_release);
1656
1657         cifs_small_buf_release(smb);
1658         return rc;
1659 }
1660
1661 int
1662 CIFSSMBRead(const unsigned int xid, struct cifs_io_parms *io_parms,
1663             unsigned int *nbytes, char **buf, int *pbuf_type)
1664 {
1665         int rc = -EACCES;
1666         READ_REQ *pSMB = NULL;
1667         READ_RSP *pSMBr = NULL;
1668         char *pReadData = NULL;
1669         int wct;
1670         int resp_buf_type = 0;
1671         struct kvec iov[1];
1672         __u32 pid = io_parms->pid;
1673         __u16 netfid = io_parms->netfid;
1674         __u64 offset = io_parms->offset;
1675         struct cifs_tcon *tcon = io_parms->tcon;
1676         unsigned int count = io_parms->length;
1677
1678         cFYI(1, "Reading %d bytes on fid %d", count, netfid);
1679         if (tcon->ses->capabilities & CAP_LARGE_FILES)
1680                 wct = 12;
1681         else {
1682                 wct = 10; /* old style read */
1683                 if ((offset >> 32) > 0)  {
1684                         /* can not handle this big offset for old */
1685                         return -EIO;
1686                 }
1687         }
1688
1689         *nbytes = 0;
1690         rc = small_smb_init(SMB_COM_READ_ANDX, wct, tcon, (void **) &pSMB);
1691         if (rc)
1692                 return rc;
1693
1694         pSMB->hdr.Pid = cpu_to_le16((__u16)pid);
1695         pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid >> 16));
1696
1697         /* tcon and ses pointer are checked in smb_init */
1698         if (tcon->ses->server == NULL)
1699                 return -ECONNABORTED;
1700
1701         pSMB->AndXCommand = 0xFF;       /* none */
1702         pSMB->Fid = netfid;
1703         pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF);
1704         if (wct == 12)
1705                 pSMB->OffsetHigh = cpu_to_le32(offset >> 32);
1706
1707         pSMB->Remaining = 0;
1708         pSMB->MaxCount = cpu_to_le16(count & 0xFFFF);
1709         pSMB->MaxCountHigh = cpu_to_le32(count >> 16);
1710         if (wct == 12)
1711                 pSMB->ByteCount = 0;  /* no need to do le conversion since 0 */
1712         else {
1713                 /* old style read */
1714                 struct smb_com_readx_req *pSMBW =
1715                         (struct smb_com_readx_req *)pSMB;
1716                 pSMBW->ByteCount = 0;
1717         }
1718
1719         iov[0].iov_base = (char *)pSMB;
1720         iov[0].iov_len = be32_to_cpu(pSMB->hdr.smb_buf_length) + 4;
1721         rc = SendReceive2(xid, tcon->ses, iov, 1 /* num iovecs */,
1722                          &resp_buf_type, CIFS_LOG_ERROR);
1723         cifs_stats_inc(&tcon->stats.cifs_stats.num_reads);
1724         pSMBr = (READ_RSP *)iov[0].iov_base;
1725         if (rc) {
1726                 cERROR(1, "Send error in read = %d", rc);
1727         } else {
1728                 int data_length = le16_to_cpu(pSMBr->DataLengthHigh);
1729                 data_length = data_length << 16;
1730                 data_length += le16_to_cpu(pSMBr->DataLength);
1731                 *nbytes = data_length;
1732
1733                 /*check that DataLength would not go beyond end of SMB */
1734                 if ((data_length > CIFSMaxBufSize)
1735                                 || (data_length > count)) {
1736                         cFYI(1, "bad length %d for count %d",
1737                                  data_length, count);
1738                         rc = -EIO;
1739                         *nbytes = 0;
1740                 } else {
1741                         pReadData = (char *) (&pSMBr->hdr.Protocol) +
1742                                         le16_to_cpu(pSMBr->DataOffset);
1743 /*                      if (rc = copy_to_user(buf, pReadData, data_length)) {
1744                                 cERROR(1, "Faulting on read rc = %d",rc);
1745                                 rc = -EFAULT;
1746                         }*/ /* can not use copy_to_user when using page cache*/
1747                         if (*buf)
1748                                 memcpy(*buf, pReadData, data_length);
1749                 }
1750         }
1751
1752 /*      cifs_small_buf_release(pSMB); */ /* Freed earlier now in SendReceive2 */
1753         if (*buf) {
1754                 if (resp_buf_type == CIFS_SMALL_BUFFER)
1755                         cifs_small_buf_release(iov[0].iov_base);
1756                 else if (resp_buf_type == CIFS_LARGE_BUFFER)
1757                         cifs_buf_release(iov[0].iov_base);
1758         } else if (resp_buf_type != CIFS_NO_BUFFER) {
1759                 /* return buffer to caller to free */
1760                 *buf = iov[0].iov_base;
1761                 if (resp_buf_type == CIFS_SMALL_BUFFER)
1762                         *pbuf_type = CIFS_SMALL_BUFFER;
1763                 else if (resp_buf_type == CIFS_LARGE_BUFFER)
1764                         *pbuf_type = CIFS_LARGE_BUFFER;
1765         } /* else no valid buffer on return - leave as null */
1766
1767         /* Note: On -EAGAIN error only caller can retry on handle based calls
1768                 since file handle passed in no longer valid */
1769         return rc;
1770 }
1771
1772
1773 int
1774 CIFSSMBWrite(const unsigned int xid, struct cifs_io_parms *io_parms,
1775              unsigned int *nbytes, const char *buf,
1776              const char __user *ubuf, const int long_op)
1777 {
1778         int rc = -EACCES;
1779         WRITE_REQ *pSMB = NULL;
1780         WRITE_RSP *pSMBr = NULL;
1781         int bytes_returned, wct;
1782         __u32 bytes_sent;
1783         __u16 byte_count;
1784         __u32 pid = io_parms->pid;
1785         __u16 netfid = io_parms->netfid;
1786         __u64 offset = io_parms->offset;
1787         struct cifs_tcon *tcon = io_parms->tcon;
1788         unsigned int count = io_parms->length;
1789
1790         *nbytes = 0;
1791
1792         /* cFYI(1, "write at %lld %d bytes", offset, count);*/
1793         if (tcon->ses == NULL)
1794                 return -ECONNABORTED;
1795
1796         if (tcon->ses->capabilities & CAP_LARGE_FILES)
1797                 wct = 14;
1798         else {
1799                 wct = 12;
1800                 if ((offset >> 32) > 0) {
1801                         /* can not handle big offset for old srv */
1802                         return -EIO;
1803                 }
1804         }
1805
1806         rc = smb_init(SMB_COM_WRITE_ANDX, wct, tcon, (void **) &pSMB,
1807                       (void **) &pSMBr);
1808         if (rc)
1809                 return rc;
1810
1811         pSMB->hdr.Pid = cpu_to_le16((__u16)pid);
1812         pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid >> 16));
1813
1814         /* tcon and ses pointer are checked in smb_init */
1815         if (tcon->ses->server == NULL)
1816                 return -ECONNABORTED;
1817
1818         pSMB->AndXCommand = 0xFF;       /* none */
1819         pSMB->Fid = netfid;
1820         pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF);
1821         if (wct == 14)
1822                 pSMB->OffsetHigh = cpu_to_le32(offset >> 32);
1823
1824         pSMB->Reserved = 0xFFFFFFFF;
1825         pSMB->WriteMode = 0;
1826         pSMB->Remaining = 0;
1827
1828         /* Can increase buffer size if buffer is big enough in some cases ie we
1829         can send more if LARGE_WRITE_X capability returned by the server and if
1830         our buffer is big enough or if we convert to iovecs on socket writes
1831         and eliminate the copy to the CIFS buffer */
1832         if (tcon->ses->capabilities & CAP_LARGE_WRITE_X) {
1833                 bytes_sent = min_t(const unsigned int, CIFSMaxBufSize, count);
1834         } else {
1835                 bytes_sent = (tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE)
1836                          & ~0xFF;
1837         }
1838
1839         if (bytes_sent > count)
1840                 bytes_sent = count;
1841         pSMB->DataOffset =
1842                 cpu_to_le16(offsetof(struct smb_com_write_req, Data) - 4);
1843         if (buf)
1844                 memcpy(pSMB->Data, buf, bytes_sent);
1845         else if (ubuf) {
1846                 if (copy_from_user(pSMB->Data, ubuf, bytes_sent)) {
1847                         cifs_buf_release(pSMB);
1848                         return -EFAULT;
1849                 }
1850         } else if (count != 0) {
1851                 /* No buffer */
1852                 cifs_buf_release(pSMB);
1853                 return -EINVAL;
1854         } /* else setting file size with write of zero bytes */
1855         if (wct == 14)
1856                 byte_count = bytes_sent + 1; /* pad */
1857         else /* wct == 12 */
1858                 byte_count = bytes_sent + 5; /* bigger pad, smaller smb hdr */
1859
1860         pSMB->DataLengthLow = cpu_to_le16(bytes_sent & 0xFFFF);
1861         pSMB->DataLengthHigh = cpu_to_le16(bytes_sent >> 16);
1862         inc_rfc1001_len(pSMB, byte_count);
1863
1864         if (wct == 14)
1865                 pSMB->ByteCount = cpu_to_le16(byte_count);
1866         else { /* old style write has byte count 4 bytes earlier
1867                   so 4 bytes pad  */
1868                 struct smb_com_writex_req *pSMBW =
1869                         (struct smb_com_writex_req *)pSMB;
1870                 pSMBW->ByteCount = cpu_to_le16(byte_count);
1871         }
1872
1873         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1874                          (struct smb_hdr *) pSMBr, &bytes_returned, long_op);
1875         cifs_stats_inc(&tcon->stats.cifs_stats.num_writes);
1876         if (rc) {
1877                 cFYI(1, "Send error in write = %d", rc);
1878         } else {
1879                 *nbytes = le16_to_cpu(pSMBr->CountHigh);
1880                 *nbytes = (*nbytes) << 16;
1881                 *nbytes += le16_to_cpu(pSMBr->Count);
1882
1883                 /*
1884                  * Mask off high 16 bits when bytes written as returned by the
1885                  * server is greater than bytes requested by the client. Some
1886                  * OS/2 servers are known to set incorrect CountHigh values.
1887                  */
1888                 if (*nbytes > count)
1889                         *nbytes &= 0xFFFF;
1890         }
1891
1892         cifs_buf_release(pSMB);
1893
1894         /* Note: On -EAGAIN error only caller can retry on handle based calls
1895                 since file handle passed in no longer valid */
1896
1897         return rc;
1898 }
1899
1900 void
1901 cifs_writedata_release(struct kref *refcount)
1902 {
1903         struct cifs_writedata *wdata = container_of(refcount,
1904                                         struct cifs_writedata, refcount);
1905
1906         if (wdata->cfile)
1907                 cifsFileInfo_put(wdata->cfile);
1908
1909         kfree(wdata);
1910 }
1911
1912 /*
1913  * Write failed with a retryable error. Resend the write request. It's also
1914  * possible that the page was redirtied so re-clean the page.
1915  */
1916 static void
1917 cifs_writev_requeue(struct cifs_writedata *wdata)
1918 {
1919         int i, rc;
1920         struct inode *inode = wdata->cfile->dentry->d_inode;
1921
1922         for (i = 0; i < wdata->nr_pages; i++) {
1923                 lock_page(wdata->pages[i]);
1924                 clear_page_dirty_for_io(wdata->pages[i]);
1925         }
1926
1927         do {
1928                 rc = cifs_async_writev(wdata);
1929         } while (rc == -EAGAIN);
1930
1931         for (i = 0; i < wdata->nr_pages; i++) {
1932                 if (rc != 0)
1933                         SetPageError(wdata->pages[i]);
1934                 unlock_page(wdata->pages[i]);
1935         }
1936
1937         mapping_set_error(inode->i_mapping, rc);
1938         kref_put(&wdata->refcount, cifs_writedata_release);
1939 }
1940
1941 void
1942 cifs_writev_complete(struct work_struct *work)
1943 {
1944         struct cifs_writedata *wdata = container_of(work,
1945                                                 struct cifs_writedata, work);
1946         struct inode *inode = wdata->cfile->dentry->d_inode;
1947         int i = 0;
1948
1949         if (wdata->result == 0) {
1950                 spin_lock(&inode->i_lock);
1951                 cifs_update_eof(CIFS_I(inode), wdata->offset, wdata->bytes);
1952                 spin_unlock(&inode->i_lock);
1953                 cifs_stats_bytes_written(tlink_tcon(wdata->cfile->tlink),
1954                                          wdata->bytes);
1955         } else if (wdata->sync_mode == WB_SYNC_ALL && wdata->result == -EAGAIN)
1956                 return cifs_writev_requeue(wdata);
1957
1958         for (i = 0; i < wdata->nr_pages; i++) {
1959                 struct page *page = wdata->pages[i];
1960                 if (wdata->result == -EAGAIN)
1961                         __set_page_dirty_nobuffers(page);
1962                 else if (wdata->result < 0)
1963                         SetPageError(page);
1964                 end_page_writeback(page);
1965                 page_cache_release(page);
1966         }
1967         if (wdata->result != -EAGAIN)
1968                 mapping_set_error(inode->i_mapping, wdata->result);
1969         kref_put(&wdata->refcount, cifs_writedata_release);
1970 }
1971
1972 struct cifs_writedata *
1973 cifs_writedata_alloc(unsigned int nr_pages, work_func_t complete)
1974 {
1975         struct cifs_writedata *wdata;
1976
1977         /* this would overflow */
1978         if (nr_pages == 0) {
1979                 cERROR(1, "%s: called with nr_pages == 0!", __func__);
1980                 return NULL;
1981         }
1982
1983         /* writedata + number of page pointers */
1984         wdata = kzalloc(sizeof(*wdata) +
1985                         sizeof(struct page *) * (nr_pages - 1), GFP_NOFS);
1986         if (wdata != NULL) {
1987                 kref_init(&wdata->refcount);
1988                 INIT_LIST_HEAD(&wdata->list);
1989                 init_completion(&wdata->done);
1990                 INIT_WORK(&wdata->work, complete);
1991         }
1992         return wdata;
1993 }
1994
1995 /*
1996  * Check the mid_state and signature on received buffer (if any), and queue the
1997  * workqueue completion task.
1998  */
1999 static void
2000 cifs_writev_callback(struct mid_q_entry *mid)
2001 {
2002         struct cifs_writedata *wdata = mid->callback_data;
2003         struct cifs_tcon *tcon = tlink_tcon(wdata->cfile->tlink);
2004         unsigned int written;
2005         WRITE_RSP *smb = (WRITE_RSP *)mid->resp_buf;
2006
2007         switch (mid->mid_state) {
2008         case MID_RESPONSE_RECEIVED:
2009                 wdata->result = cifs_check_receive(mid, tcon->ses->server, 0);
2010                 if (wdata->result != 0)
2011                         break;
2012
2013                 written = le16_to_cpu(smb->CountHigh);
2014                 written <<= 16;
2015                 written += le16_to_cpu(smb->Count);
2016                 /*
2017                  * Mask off high 16 bits when bytes written as returned
2018                  * by the server is greater than bytes requested by the
2019                  * client. OS/2 servers are known to set incorrect
2020                  * CountHigh values.
2021                  */
2022                 if (written > wdata->bytes)
2023                         written &= 0xFFFF;
2024
2025                 if (written < wdata->bytes)
2026                         wdata->result = -ENOSPC;
2027                 else
2028                         wdata->bytes = written;
2029                 break;
2030         case MID_REQUEST_SUBMITTED:
2031         case MID_RETRY_NEEDED:
2032                 wdata->result = -EAGAIN;
2033                 break;
2034         default:
2035                 wdata->result = -EIO;
2036                 break;
2037         }
2038
2039         queue_work(cifsiod_wq, &wdata->work);
2040         DeleteMidQEntry(mid);
2041         add_credits(tcon->ses->server, 1, 0);
2042 }
2043
2044 /* cifs_async_writev - send an async write, and set up mid to handle result */
2045 int
2046 cifs_async_writev(struct cifs_writedata *wdata)
2047 {
2048         int i, rc = -EACCES;
2049         WRITE_REQ *smb = NULL;
2050         int wct;
2051         struct cifs_tcon *tcon = tlink_tcon(wdata->cfile->tlink);
2052         struct kvec *iov = NULL;
2053
2054         if (tcon->ses->capabilities & CAP_LARGE_FILES) {
2055                 wct = 14;
2056         } else {
2057                 wct = 12;
2058                 if (wdata->offset >> 32 > 0) {
2059                         /* can not handle big offset for old srv */
2060                         return -EIO;
2061                 }
2062         }
2063
2064         rc = small_smb_init(SMB_COM_WRITE_ANDX, wct, tcon, (void **)&smb);
2065         if (rc)
2066                 goto async_writev_out;
2067
2068         /* 1 iov per page + 1 for header */
2069         iov = kzalloc((wdata->nr_pages + 1) * sizeof(*iov), GFP_NOFS);
2070         if (iov == NULL) {
2071                 rc = -ENOMEM;
2072                 goto async_writev_out;
2073         }
2074
2075         smb->hdr.Pid = cpu_to_le16((__u16)wdata->pid);
2076         smb->hdr.PidHigh = cpu_to_le16((__u16)(wdata->pid >> 16));
2077
2078         smb->AndXCommand = 0xFF;        /* none */
2079         smb->Fid = wdata->cfile->netfid;
2080         smb->OffsetLow = cpu_to_le32(wdata->offset & 0xFFFFFFFF);
2081         if (wct == 14)
2082                 smb->OffsetHigh = cpu_to_le32(wdata->offset >> 32);
2083         smb->Reserved = 0xFFFFFFFF;
2084         smb->WriteMode = 0;
2085         smb->Remaining = 0;
2086
2087         smb->DataOffset =
2088             cpu_to_le16(offsetof(struct smb_com_write_req, Data) - 4);
2089
2090         /* 4 for RFC1001 length + 1 for BCC */
2091         iov[0].iov_len = be32_to_cpu(smb->hdr.smb_buf_length) + 4 + 1;
2092         iov[0].iov_base = smb;
2093
2094         /*
2095          * This function should marshal up the page array into the kvec
2096          * array, reserving [0] for the header. It should kmap the pages
2097          * and set the iov_len properly for each one. It may also set
2098          * wdata->bytes too.
2099          */
2100         cifs_kmap_lock();
2101         wdata->marshal_iov(iov, wdata);
2102         cifs_kmap_unlock();
2103
2104         cFYI(1, "async write at %llu %u bytes", wdata->offset, wdata->bytes);
2105
2106         smb->DataLengthLow = cpu_to_le16(wdata->bytes & 0xFFFF);
2107         smb->DataLengthHigh = cpu_to_le16(wdata->bytes >> 16);
2108
2109         if (wct == 14) {
2110                 inc_rfc1001_len(&smb->hdr, wdata->bytes + 1);
2111                 put_bcc(wdata->bytes + 1, &smb->hdr);
2112         } else {
2113                 /* wct == 12 */
2114                 struct smb_com_writex_req *smbw =
2115                                 (struct smb_com_writex_req *)smb;
2116                 inc_rfc1001_len(&smbw->hdr, wdata->bytes + 5);
2117                 put_bcc(wdata->bytes + 5, &smbw->hdr);
2118                 iov[0].iov_len += 4; /* pad bigger by four bytes */
2119         }
2120
2121         kref_get(&wdata->refcount);
2122         rc = cifs_call_async(tcon->ses->server, iov, wdata->nr_pages + 1,
2123                              NULL, cifs_writev_callback, wdata, 0);
2124
2125         if (rc == 0)
2126                 cifs_stats_inc(&tcon->stats.cifs_stats.num_writes);
2127         else
2128                 kref_put(&wdata->refcount, cifs_writedata_release);
2129
2130         /* send is done, unmap pages */
2131         for (i = 0; i < wdata->nr_pages; i++)
2132                 kunmap(wdata->pages[i]);
2133
2134 async_writev_out:
2135         cifs_small_buf_release(smb);
2136         kfree(iov);
2137         return rc;
2138 }
2139
2140 int
2141 CIFSSMBWrite2(const unsigned int xid, struct cifs_io_parms *io_parms,
2142               unsigned int *nbytes, struct kvec *iov, int n_vec,
2143               const int long_op)
2144 {
2145         int rc = -EACCES;
2146         WRITE_REQ *pSMB = NULL;
2147         int wct;
2148         int smb_hdr_len;
2149         int resp_buf_type = 0;
2150         __u32 pid = io_parms->pid;
2151         __u16 netfid = io_parms->netfid;
2152         __u64 offset = io_parms->offset;
2153         struct cifs_tcon *tcon = io_parms->tcon;
2154         unsigned int count = io_parms->length;
2155
2156         *nbytes = 0;
2157
2158         cFYI(1, "write2 at %lld %d bytes", (long long)offset, count);
2159
2160         if (tcon->ses->capabilities & CAP_LARGE_FILES) {
2161                 wct = 14;
2162         } else {
2163                 wct = 12;
2164                 if ((offset >> 32) > 0) {
2165                         /* can not handle big offset for old srv */
2166                         return -EIO;
2167                 }
2168         }
2169         rc = small_smb_init(SMB_COM_WRITE_ANDX, wct, tcon, (void **) &pSMB);
2170         if (rc)
2171                 return rc;
2172
2173         pSMB->hdr.Pid = cpu_to_le16((__u16)pid);
2174         pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid >> 16));
2175
2176         /* tcon and ses pointer are checked in smb_init */
2177         if (tcon->ses->server == NULL)
2178                 return -ECONNABORTED;
2179
2180         pSMB->AndXCommand = 0xFF;       /* none */
2181         pSMB->Fid = netfid;
2182         pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF);
2183         if (wct == 14)
2184                 pSMB->OffsetHigh = cpu_to_le32(offset >> 32);
2185         pSMB->Reserved = 0xFFFFFFFF;
2186         pSMB->WriteMode = 0;
2187         pSMB->Remaining = 0;
2188
2189         pSMB->DataOffset =
2190             cpu_to_le16(offsetof(struct smb_com_write_req, Data) - 4);
2191
2192         pSMB->DataLengthLow = cpu_to_le16(count & 0xFFFF);
2193         pSMB->DataLengthHigh = cpu_to_le16(count >> 16);
2194         /* header + 1 byte pad */
2195         smb_hdr_len = be32_to_cpu(pSMB->hdr.smb_buf_length) + 1;
2196         if (wct == 14)
2197                 inc_rfc1001_len(pSMB, count + 1);
2198         else /* wct == 12 */
2199                 inc_rfc1001_len(pSMB, count + 5); /* smb data starts later */
2200         if (wct == 14)
2201                 pSMB->ByteCount = cpu_to_le16(count + 1);
2202         else /* wct == 12 */ /* bigger pad, smaller smb hdr, keep offset ok */ {
2203                 struct smb_com_writex_req *pSMBW =
2204                                 (struct smb_com_writex_req *)pSMB;
2205                 pSMBW->ByteCount = cpu_to_le16(count + 5);
2206         }
2207         iov[0].iov_base = pSMB;
2208         if (wct == 14)
2209                 iov[0].iov_len = smb_hdr_len + 4;
2210         else /* wct == 12 pad bigger by four bytes */
2211                 iov[0].iov_len = smb_hdr_len + 8;
2212
2213
2214         rc = SendReceive2(xid, tcon->ses, iov, n_vec + 1, &resp_buf_type,
2215                           long_op);
2216         cifs_stats_inc(&tcon->stats.cifs_stats.num_writes);
2217         if (rc) {
2218                 cFYI(1, "Send error Write2 = %d", rc);
2219         } else if (resp_buf_type == 0) {
2220                 /* presumably this can not happen, but best to be safe */
2221                 rc = -EIO;
2222         } else {
2223                 WRITE_RSP *pSMBr = (WRITE_RSP *)iov[0].iov_base;
2224                 *nbytes = le16_to_cpu(pSMBr->CountHigh);
2225                 *nbytes = (*nbytes) << 16;
2226                 *nbytes += le16_to_cpu(pSMBr->Count);
2227
2228                 /*
2229                  * Mask off high 16 bits when bytes written as returned by the
2230                  * server is greater than bytes requested by the client. OS/2
2231                  * servers are known to set incorrect CountHigh values.
2232                  */
2233                 if (*nbytes > count)
2234                         *nbytes &= 0xFFFF;
2235         }
2236
2237 /*      cifs_small_buf_release(pSMB); */ /* Freed earlier now in SendReceive2 */
2238         if (resp_buf_type == CIFS_SMALL_BUFFER)
2239                 cifs_small_buf_release(iov[0].iov_base);
2240         else if (resp_buf_type == CIFS_LARGE_BUFFER)
2241                 cifs_buf_release(iov[0].iov_base);
2242
2243         /* Note: On -EAGAIN error only caller can retry on handle based calls
2244                 since file handle passed in no longer valid */
2245
2246         return rc;
2247 }
2248
2249 int cifs_lockv(const unsigned int xid, struct cifs_tcon *tcon,
2250                const __u16 netfid, const __u8 lock_type, const __u32 num_unlock,
2251                const __u32 num_lock, LOCKING_ANDX_RANGE *buf)
2252 {
2253         int rc = 0;
2254         LOCK_REQ *pSMB = NULL;
2255         struct kvec iov[2];
2256         int resp_buf_type;
2257         __u16 count;
2258
2259         cFYI(1, "cifs_lockv num lock %d num unlock %d", num_lock, num_unlock);
2260
2261         rc = small_smb_init(SMB_COM_LOCKING_ANDX, 8, tcon, (void **) &pSMB);
2262         if (rc)
2263                 return rc;
2264
2265         pSMB->Timeout = 0;
2266         pSMB->NumberOfLocks = cpu_to_le16(num_lock);
2267         pSMB->NumberOfUnlocks = cpu_to_le16(num_unlock);
2268         pSMB->LockType = lock_type;
2269         pSMB->AndXCommand = 0xFF; /* none */
2270         pSMB->Fid = netfid; /* netfid stays le */
2271
2272         count = (num_unlock + num_lock) * sizeof(LOCKING_ANDX_RANGE);
2273         inc_rfc1001_len(pSMB, count);
2274         pSMB->ByteCount = cpu_to_le16(count);
2275
2276         iov[0].iov_base = (char *)pSMB;
2277         iov[0].iov_len = be32_to_cpu(pSMB->hdr.smb_buf_length) + 4 -
2278                          (num_unlock + num_lock) * sizeof(LOCKING_ANDX_RANGE);
2279         iov[1].iov_base = (char *)buf;
2280         iov[1].iov_len = (num_unlock + num_lock) * sizeof(LOCKING_ANDX_RANGE);
2281
2282         cifs_stats_inc(&tcon->stats.cifs_stats.num_locks);
2283         rc = SendReceive2(xid, tcon->ses, iov, 2, &resp_buf_type, CIFS_NO_RESP);
2284         if (rc)
2285                 cFYI(1, "Send error in cifs_lockv = %d", rc);
2286
2287         return rc;
2288 }
2289
2290 int
2291 CIFSSMBLock(const unsigned int xid, struct cifs_tcon *tcon,
2292             const __u16 smb_file_id, const __u32 netpid, const __u64 len,
2293             const __u64 offset, const __u32 numUnlock,
2294             const __u32 numLock, const __u8 lockType,
2295             const bool waitFlag, const __u8 oplock_level)
2296 {
2297         int rc = 0;
2298         LOCK_REQ *pSMB = NULL;
2299 /*      LOCK_RSP *pSMBr = NULL; */ /* No response data other than rc to parse */
2300         int bytes_returned;
2301         int flags = 0;
2302         __u16 count;
2303
2304         cFYI(1, "CIFSSMBLock timeout %d numLock %d", (int)waitFlag, numLock);
2305         rc = small_smb_init(SMB_COM_LOCKING_ANDX, 8, tcon, (void **) &pSMB);
2306
2307         if (rc)
2308                 return rc;
2309
2310         if (lockType == LOCKING_ANDX_OPLOCK_RELEASE) {
2311                 /* no response expected */
2312                 flags = CIFS_ASYNC_OP | CIFS_OBREAK_OP;
2313                 pSMB->Timeout = 0;
2314         } else if (waitFlag) {
2315                 flags = CIFS_BLOCKING_OP; /* blocking operation, no timeout */
2316                 pSMB->Timeout = cpu_to_le32(-1);/* blocking - do not time out */
2317         } else {
2318                 pSMB->Timeout = 0;
2319         }
2320
2321         pSMB->NumberOfLocks = cpu_to_le16(numLock);
2322         pSMB->NumberOfUnlocks = cpu_to_le16(numUnlock);
2323         pSMB->LockType = lockType;
2324         pSMB->OplockLevel = oplock_level;
2325         pSMB->AndXCommand = 0xFF;       /* none */
2326         pSMB->Fid = smb_file_id; /* netfid stays le */
2327
2328         if ((numLock != 0) || (numUnlock != 0)) {
2329                 pSMB->Locks[0].Pid = cpu_to_le16(netpid);
2330                 /* BB where to store pid high? */
2331                 pSMB->Locks[0].LengthLow = cpu_to_le32((u32)len);
2332                 pSMB->Locks[0].LengthHigh = cpu_to_le32((u32)(len>>32));
2333                 pSMB->Locks[0].OffsetLow = cpu_to_le32((u32)offset);
2334                 pSMB->Locks[0].OffsetHigh = cpu_to_le32((u32)(offset>>32));
2335                 count = sizeof(LOCKING_ANDX_RANGE);
2336         } else {
2337                 /* oplock break */
2338                 count = 0;
2339         }
2340         inc_rfc1001_len(pSMB, count);
2341         pSMB->ByteCount = cpu_to_le16(count);
2342
2343         if (waitFlag) {
2344                 rc = SendReceiveBlockingLock(xid, tcon, (struct smb_hdr *) pSMB,
2345                         (struct smb_hdr *) pSMB, &bytes_returned);
2346                 cifs_small_buf_release(pSMB);
2347         } else {
2348                 rc = SendReceiveNoRsp(xid, tcon->ses, (char *)pSMB, flags);
2349                 /* SMB buffer freed by function above */
2350         }
2351         cifs_stats_inc(&tcon->stats.cifs_stats.num_locks);
2352         if (rc)
2353                 cFYI(1, "Send error in Lock = %d", rc);
2354
2355         /* Note: On -EAGAIN error only caller can retry on handle based calls
2356         since file handle passed in no longer valid */
2357         return rc;
2358 }
2359
2360 int
2361 CIFSSMBPosixLock(const unsigned int xid, struct cifs_tcon *tcon,
2362                 const __u16 smb_file_id, const __u32 netpid,
2363                 const loff_t start_offset, const __u64 len,
2364                 struct file_lock *pLockData, const __u16 lock_type,
2365                 const bool waitFlag)
2366 {
2367         struct smb_com_transaction2_sfi_req *pSMB  = NULL;
2368         struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
2369         struct cifs_posix_lock *parm_data;
2370         int rc = 0;
2371         int timeout = 0;
2372         int bytes_returned = 0;
2373         int resp_buf_type = 0;
2374         __u16 params, param_offset, offset, byte_count, count;
2375         struct kvec iov[1];
2376
2377         cFYI(1, "Posix Lock");
2378
2379         rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
2380
2381         if (rc)
2382                 return rc;
2383
2384         pSMBr = (struct smb_com_transaction2_sfi_rsp *)pSMB;
2385
2386         params = 6;
2387         pSMB->MaxSetupCount = 0;
2388         pSMB->Reserved = 0;
2389         pSMB->Flags = 0;
2390         pSMB->Reserved2 = 0;
2391         param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
2392         offset = param_offset + params;
2393
2394         count = sizeof(struct cifs_posix_lock);
2395         pSMB->MaxParameterCount = cpu_to_le16(2);
2396         pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB from sess */
2397         pSMB->SetupCount = 1;
2398         pSMB->Reserved3 = 0;
2399         if (pLockData)
2400                 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION);
2401         else
2402                 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
2403         byte_count = 3 /* pad */  + params + count;
2404         pSMB->DataCount = cpu_to_le16(count);
2405         pSMB->ParameterCount = cpu_to_le16(params);
2406         pSMB->TotalDataCount = pSMB->DataCount;
2407         pSMB->TotalParameterCount = pSMB->ParameterCount;
2408         pSMB->ParameterOffset = cpu_to_le16(param_offset);
2409         parm_data = (struct cifs_posix_lock *)
2410                         (((char *) &pSMB->hdr.Protocol) + offset);
2411
2412         parm_data->lock_type = cpu_to_le16(lock_type);
2413         if (waitFlag) {
2414                 timeout = CIFS_BLOCKING_OP; /* blocking operation, no timeout */
2415                 parm_data->lock_flags = cpu_to_le16(1);
2416                 pSMB->Timeout = cpu_to_le32(-1);
2417         } else
2418                 pSMB->Timeout = 0;
2419
2420         parm_data->pid = cpu_to_le32(netpid);
2421         parm_data->start = cpu_to_le64(start_offset);
2422         parm_data->length = cpu_to_le64(len);  /* normalize negative numbers */
2423
2424         pSMB->DataOffset = cpu_to_le16(offset);
2425         pSMB->Fid = smb_file_id;
2426         pSMB->InformationLevel = cpu_to_le16(SMB_SET_POSIX_LOCK);
2427         pSMB->Reserved4 = 0;
2428         inc_rfc1001_len(pSMB, byte_count);
2429         pSMB->ByteCount = cpu_to_le16(byte_count);
2430         if (waitFlag) {
2431                 rc = SendReceiveBlockingLock(xid, tcon, (struct smb_hdr *) pSMB,
2432                         (struct smb_hdr *) pSMBr, &bytes_returned);
2433         } else {
2434                 iov[0].iov_base = (char *)pSMB;
2435                 iov[0].iov_len = be32_to_cpu(pSMB->hdr.smb_buf_length) + 4;
2436                 rc = SendReceive2(xid, tcon->ses, iov, 1 /* num iovecs */,
2437                                 &resp_buf_type, timeout);
2438                 pSMB = NULL; /* request buf already freed by SendReceive2. Do
2439                                 not try to free it twice below on exit */
2440                 pSMBr = (struct smb_com_transaction2_sfi_rsp *)iov[0].iov_base;
2441         }
2442
2443         if (rc) {
2444                 cFYI(1, "Send error in Posix Lock = %d", rc);
2445         } else if (pLockData) {
2446                 /* lock structure can be returned on get */
2447                 __u16 data_offset;
2448                 __u16 data_count;
2449                 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
2450
2451                 if (rc || get_bcc(&pSMBr->hdr) < sizeof(*parm_data)) {
2452                         rc = -EIO;      /* bad smb */
2453                         goto plk_err_exit;
2454                 }
2455                 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
2456                 data_count  = le16_to_cpu(pSMBr->t2.DataCount);
2457                 if (data_count < sizeof(struct cifs_posix_lock)) {
2458                         rc = -EIO;
2459                         goto plk_err_exit;
2460                 }
2461                 parm_data = (struct cifs_posix_lock *)
2462                         ((char *)&pSMBr->hdr.Protocol + data_offset);
2463                 if (parm_data->lock_type == __constant_cpu_to_le16(CIFS_UNLCK))
2464                         pLockData->fl_type = F_UNLCK;
2465                 else {
2466                         if (parm_data->lock_type ==
2467                                         __constant_cpu_to_le16(CIFS_RDLCK))
2468                                 pLockData->fl_type = F_RDLCK;
2469                         else if (parm_data->lock_type ==
2470                                         __constant_cpu_to_le16(CIFS_WRLCK))
2471                                 pLockData->fl_type = F_WRLCK;
2472
2473                         pLockData->fl_start = le64_to_cpu(parm_data->start);
2474                         pLockData->fl_end = pLockData->fl_start +
2475                                         le64_to_cpu(parm_data->length) - 1;
2476                         pLockData->fl_pid = le32_to_cpu(parm_data->pid);
2477                 }
2478         }
2479
2480 plk_err_exit:
2481         if (pSMB)
2482                 cifs_small_buf_release(pSMB);
2483
2484         if (resp_buf_type == CIFS_SMALL_BUFFER)
2485                 cifs_small_buf_release(iov[0].iov_base);
2486         else if (resp_buf_type == CIFS_LARGE_BUFFER)
2487                 cifs_buf_release(iov[0].iov_base);
2488
2489         /* Note: On -EAGAIN error only caller can retry on handle based calls
2490            since file handle passed in no longer valid */
2491
2492         return rc;
2493 }
2494
2495
2496 int
2497 CIFSSMBClose(const unsigned int xid, struct cifs_tcon *tcon, int smb_file_id)
2498 {
2499         int rc = 0;
2500         CLOSE_REQ *pSMB = NULL;
2501         cFYI(1, "In CIFSSMBClose");
2502
2503 /* do not retry on dead session on close */
2504         rc = small_smb_init(SMB_COM_CLOSE, 3, tcon, (void **) &pSMB);
2505         if (rc == -EAGAIN)
2506                 return 0;
2507         if (rc)
2508                 return rc;
2509
2510         pSMB->FileID = (__u16) smb_file_id;
2511         pSMB->LastWriteTime = 0xFFFFFFFF;
2512         pSMB->ByteCount = 0;
2513         rc = SendReceiveNoRsp(xid, tcon->ses, (char *) pSMB, 0);
2514         cifs_stats_inc(&tcon->stats.cifs_stats.num_closes);
2515         if (rc) {
2516                 if (rc != -EINTR) {
2517                         /* EINTR is expected when user ctl-c to kill app */
2518                         cERROR(1, "Send error in Close = %d", rc);
2519                 }
2520         }
2521
2522         /* Since session is dead, file will be closed on server already */
2523         if (rc == -EAGAIN)
2524                 rc = 0;
2525
2526         return rc;
2527 }
2528
2529 int
2530 CIFSSMBFlush(const unsigned int xid, struct cifs_tcon *tcon, int smb_file_id)
2531 {
2532         int rc = 0;
2533         FLUSH_REQ *pSMB = NULL;
2534         cFYI(1, "In CIFSSMBFlush");
2535
2536         rc = small_smb_init(SMB_COM_FLUSH, 1, tcon, (void **) &pSMB);
2537         if (rc)
2538                 return rc;
2539
2540         pSMB->FileID = (__u16) smb_file_id;
2541         pSMB->ByteCount = 0;
2542         rc = SendReceiveNoRsp(xid, tcon->ses, (char *) pSMB, 0);
2543         cifs_stats_inc(&tcon->stats.cifs_stats.num_flushes);
2544         if (rc)
2545                 cERROR(1, "Send error in Flush = %d", rc);
2546
2547         return rc;
2548 }
2549
2550 int
2551 CIFSSMBRename(const unsigned int xid, struct cifs_tcon *tcon,
2552               const char *fromName, const char *toName,
2553               const struct nls_table *nls_codepage, int remap)
2554 {
2555         int rc = 0;
2556         RENAME_REQ *pSMB = NULL;
2557         RENAME_RSP *pSMBr = NULL;
2558         int bytes_returned;
2559         int name_len, name_len2;
2560         __u16 count;
2561
2562         cFYI(1, "In CIFSSMBRename");
2563 renameRetry:
2564         rc = smb_init(SMB_COM_RENAME, 1, tcon, (void **) &pSMB,
2565                       (void **) &pSMBr);
2566         if (rc)
2567                 return rc;
2568
2569         pSMB->BufferFormat = 0x04;
2570         pSMB->SearchAttributes =
2571             cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
2572                         ATTR_DIRECTORY);
2573
2574         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2575                 name_len =
2576                     cifsConvertToUTF16((__le16 *) pSMB->OldFileName, fromName,
2577                                        PATH_MAX, nls_codepage, remap);
2578                 name_len++;     /* trailing null */
2579                 name_len *= 2;
2580                 pSMB->OldFileName[name_len] = 0x04;     /* pad */
2581         /* protocol requires ASCII signature byte on Unicode string */
2582                 pSMB->OldFileName[name_len + 1] = 0x00;
2583                 name_len2 =
2584                     cifsConvertToUTF16((__le16 *)&pSMB->OldFileName[name_len+2],
2585                                        toName, PATH_MAX, nls_codepage, remap);
2586                 name_len2 += 1 /* trailing null */  + 1 /* Signature word */ ;
2587                 name_len2 *= 2; /* convert to bytes */
2588         } else {        /* BB improve the check for buffer overruns BB */
2589                 name_len = strnlen(fromName, PATH_MAX);
2590                 name_len++;     /* trailing null */
2591                 strncpy(pSMB->OldFileName, fromName, name_len);
2592                 name_len2 = strnlen(toName, PATH_MAX);
2593                 name_len2++;    /* trailing null */
2594                 pSMB->OldFileName[name_len] = 0x04;  /* 2nd buffer format */
2595                 strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2);
2596                 name_len2++;    /* trailing null */
2597                 name_len2++;    /* signature byte */
2598         }
2599
2600         count = 1 /* 1st signature byte */  + name_len + name_len2;
2601         inc_rfc1001_len(pSMB, count);
2602         pSMB->ByteCount = cpu_to_le16(count);
2603
2604         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2605                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2606         cifs_stats_inc(&tcon->stats.cifs_stats.num_renames);
2607         if (rc)
2608                 cFYI(1, "Send error in rename = %d", rc);
2609
2610         cifs_buf_release(pSMB);
2611
2612         if (rc == -EAGAIN)
2613                 goto renameRetry;
2614
2615         return rc;
2616 }
2617
2618 int CIFSSMBRenameOpenFile(const unsigned int xid, struct cifs_tcon *pTcon,
2619                 int netfid, const char *target_name,
2620                 const struct nls_table *nls_codepage, int remap)
2621 {
2622         struct smb_com_transaction2_sfi_req *pSMB  = NULL;
2623         struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
2624         struct set_file_rename *rename_info;
2625         char *data_offset;
2626         char dummy_string[30];
2627         int rc = 0;
2628         int bytes_returned = 0;
2629         int len_of_str;
2630         __u16 params, param_offset, offset, count, byte_count;
2631
2632         cFYI(1, "Rename to File by handle");
2633         rc = smb_init(SMB_COM_TRANSACTION2, 15, pTcon, (void **) &pSMB,
2634                         (void **) &pSMBr);
2635         if (rc)
2636                 return rc;
2637
2638         params = 6;
2639         pSMB->MaxSetupCount = 0;
2640         pSMB->Reserved = 0;
2641         pSMB->Flags = 0;
2642         pSMB->Timeout = 0;
2643         pSMB->Reserved2 = 0;
2644         param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
2645         offset = param_offset + params;
2646
2647         data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
2648         rename_info = (struct set_file_rename *) data_offset;
2649         pSMB->MaxParameterCount = cpu_to_le16(2);
2650         pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB from sess */
2651         pSMB->SetupCount = 1;
2652         pSMB->Reserved3 = 0;
2653         pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
2654         byte_count = 3 /* pad */  + params;
2655         pSMB->ParameterCount = cpu_to_le16(params);
2656         pSMB->TotalParameterCount = pSMB->ParameterCount;
2657         pSMB->ParameterOffset = cpu_to_le16(param_offset);
2658         pSMB->DataOffset = cpu_to_le16(offset);
2659         /* construct random name ".cifs_tmp<inodenum><mid>" */
2660         rename_info->overwrite = cpu_to_le32(1);
2661         rename_info->root_fid  = 0;
2662         /* unicode only call */
2663         if (target_name == NULL) {
2664                 sprintf(dummy_string, "cifs%x", pSMB->hdr.Mid);
2665                 len_of_str =
2666                         cifsConvertToUTF16((__le16 *)rename_info->target_name,
2667                                         dummy_string, 24, nls_codepage, remap);
2668         } else {
2669                 len_of_str =
2670                         cifsConvertToUTF16((__le16 *)rename_info->target_name,
2671                                         target_name, PATH_MAX, nls_codepage,
2672                                         remap);
2673         }
2674         rename_info->target_name_len = cpu_to_le32(2 * len_of_str);
2675         count = 12 /* sizeof(struct set_file_rename) */ + (2 * len_of_str);
2676         byte_count += count;
2677         pSMB->DataCount = cpu_to_le16(count);
2678         pSMB->TotalDataCount = pSMB->DataCount;
2679         pSMB->Fid = netfid;
2680         pSMB->InformationLevel =
2681                 cpu_to_le16(SMB_SET_FILE_RENAME_INFORMATION);
2682         pSMB->Reserved4 = 0;
2683         inc_rfc1001_len(pSMB, byte_count);
2684         pSMB->ByteCount = cpu_to_le16(byte_count);
2685         rc = SendReceive(xid, pTcon->ses, (struct smb_hdr *) pSMB,
2686                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2687         cifs_stats_inc(&pTcon->stats.cifs_stats.num_t2renames);
2688         if (rc)
2689                 cFYI(1, "Send error in Rename (by file handle) = %d", rc);
2690
2691         cifs_buf_release(pSMB);
2692
2693         /* Note: On -EAGAIN error only caller can retry on handle based calls
2694                 since file handle passed in no longer valid */
2695
2696         return rc;
2697 }
2698
2699 int
2700 CIFSSMBCopy(const unsigned int xid, struct cifs_tcon *tcon,
2701             const char *fromName, const __u16 target_tid, const char *toName,
2702             const int flags, const struct nls_table *nls_codepage, int remap)
2703 {
2704         int rc = 0;
2705         COPY_REQ *pSMB = NULL;
2706         COPY_RSP *pSMBr = NULL;
2707         int bytes_returned;
2708         int name_len, name_len2;
2709         __u16 count;
2710
2711         cFYI(1, "In CIFSSMBCopy");
2712 copyRetry:
2713         rc = smb_init(SMB_COM_COPY, 1, tcon, (void **) &pSMB,
2714                         (void **) &pSMBr);
2715         if (rc)
2716                 return rc;
2717
2718         pSMB->BufferFormat = 0x04;
2719         pSMB->Tid2 = target_tid;
2720
2721         pSMB->Flags = cpu_to_le16(flags & COPY_TREE);
2722
2723         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2724                 name_len = cifsConvertToUTF16((__le16 *) pSMB->OldFileName,
2725                                               fromName, PATH_MAX, nls_codepage,
2726                                               remap);
2727                 name_len++;     /* trailing null */
2728                 name_len *= 2;
2729                 pSMB->OldFileName[name_len] = 0x04;     /* pad */
2730                 /* protocol requires ASCII signature byte on Unicode string */
2731                 pSMB->OldFileName[name_len + 1] = 0x00;
2732                 name_len2 =
2733                     cifsConvertToUTF16((__le16 *)&pSMB->OldFileName[name_len+2],
2734                                        toName, PATH_MAX, nls_codepage, remap);
2735                 name_len2 += 1 /* trailing null */  + 1 /* Signature word */ ;
2736                 name_len2 *= 2; /* convert to bytes */
2737         } else {        /* BB improve the check for buffer overruns BB */
2738                 name_len = strnlen(fromName, PATH_MAX);
2739                 name_len++;     /* trailing null */
2740                 strncpy(pSMB->OldFileName, fromName, name_len);
2741                 name_len2 = strnlen(toName, PATH_MAX);
2742                 name_len2++;    /* trailing null */
2743                 pSMB->OldFileName[name_len] = 0x04;  /* 2nd buffer format */
2744                 strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2);
2745                 name_len2++;    /* trailing null */
2746                 name_len2++;    /* signature byte */
2747         }
2748
2749         count = 1 /* 1st signature byte */  + name_len + name_len2;
2750         inc_rfc1001_len(pSMB, count);
2751         pSMB->ByteCount = cpu_to_le16(count);
2752
2753         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2754                 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2755         if (rc) {
2756                 cFYI(1, "Send error in copy = %d with %d files copied",
2757                         rc, le16_to_cpu(pSMBr->CopyCount));
2758         }
2759         cifs_buf_release(pSMB);
2760
2761         if (rc == -EAGAIN)
2762                 goto copyRetry;
2763
2764         return rc;
2765 }
2766
2767 int
2768 CIFSUnixCreateSymLink(const unsigned int xid, struct cifs_tcon *tcon,
2769                       const char *fromName, const char *toName,
2770                       const struct nls_table *nls_codepage)
2771 {
2772         TRANSACTION2_SPI_REQ *pSMB = NULL;
2773         TRANSACTION2_SPI_RSP *pSMBr = NULL;
2774         char *data_offset;
2775         int name_len;
2776         int name_len_target;
2777         int rc = 0;
2778         int bytes_returned = 0;
2779         __u16 params, param_offset, offset, byte_count;
2780
2781         cFYI(1, "In Symlink Unix style");
2782 createSymLinkRetry:
2783         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2784                       (void **) &pSMBr);
2785         if (rc)
2786                 return rc;
2787
2788         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2789                 name_len =
2790                     cifs_strtoUTF16((__le16 *) pSMB->FileName, fromName,
2791                                     /* find define for this maxpathcomponent */
2792                                     PATH_MAX, nls_codepage);
2793                 name_len++;     /* trailing null */
2794                 name_len *= 2;
2795
2796         } else {        /* BB improve the check for buffer overruns BB */
2797                 name_len = strnlen(fromName, PATH_MAX);
2798                 name_len++;     /* trailing null */
2799                 strncpy(pSMB->FileName, fromName, name_len);
2800         }
2801         params = 6 + name_len;
2802         pSMB->MaxSetupCount = 0;
2803         pSMB->Reserved = 0;
2804         pSMB->Flags = 0;
2805         pSMB->Timeout = 0;
2806         pSMB->Reserved2 = 0;
2807         param_offset = offsetof(struct smb_com_transaction2_spi_req,
2808                                 InformationLevel) - 4;
2809         offset = param_offset + params;
2810
2811         data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
2812         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2813                 name_len_target =
2814                     cifs_strtoUTF16((__le16 *) data_offset, toName, PATH_MAX
2815                                     /* find define for this maxpathcomponent */
2816                                     , nls_codepage);
2817                 name_len_target++;      /* trailing null */
2818                 name_len_target *= 2;
2819         } else {        /* BB improve the check for buffer overruns BB */
2820                 name_len_target = strnlen(toName, PATH_MAX);
2821                 name_len_target++;      /* trailing null */
2822                 strncpy(data_offset, toName, name_len_target);
2823         }
2824
2825         pSMB->MaxParameterCount = cpu_to_le16(2);
2826         /* BB find exact max on data count below from sess */
2827         pSMB->MaxDataCount = cpu_to_le16(1000);
2828         pSMB->SetupCount = 1;
2829         pSMB->Reserved3 = 0;
2830         pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
2831         byte_count = 3 /* pad */  + params + name_len_target;
2832         pSMB->DataCount = cpu_to_le16(name_len_target);
2833         pSMB->ParameterCount = cpu_to_le16(params);
2834         pSMB->TotalDataCount = pSMB->DataCount;
2835         pSMB->TotalParameterCount = pSMB->ParameterCount;
2836         pSMB->ParameterOffset = cpu_to_le16(param_offset);
2837         pSMB->DataOffset = cpu_to_le16(offset);
2838         pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_LINK);
2839         pSMB->Reserved4 = 0;
2840         inc_rfc1001_len(pSMB, byte_count);
2841         pSMB->ByteCount = cpu_to_le16(byte_count);
2842         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2843                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2844         cifs_stats_inc(&tcon->stats.cifs_stats.num_symlinks);
2845         if (rc)
2846                 cFYI(1, "Send error in SetPathInfo create symlink = %d", rc);
2847
2848         cifs_buf_release(pSMB);
2849
2850         if (rc == -EAGAIN)
2851                 goto createSymLinkRetry;
2852
2853         return rc;
2854 }
2855
2856 int
2857 CIFSUnixCreateHardLink(const unsigned int xid, struct cifs_tcon *tcon,
2858                        const char *fromName, const char *toName,
2859                        const struct nls_table *nls_codepage, int remap)
2860 {
2861         TRANSACTION2_SPI_REQ *pSMB = NULL;
2862         TRANSACTION2_SPI_RSP *pSMBr = NULL;
2863         char *data_offset;
2864         int name_len;
2865         int name_len_target;
2866         int rc = 0;
2867         int bytes_returned = 0;
2868         __u16 params, param_offset, offset, byte_count;
2869
2870         cFYI(1, "In Create Hard link Unix style");
2871 createHardLinkRetry:
2872         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2873                       (void **) &pSMBr);
2874         if (rc)
2875                 return rc;
2876
2877         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2878                 name_len = cifsConvertToUTF16((__le16 *) pSMB->FileName, toName,
2879                                               PATH_MAX, nls_codepage, remap);
2880                 name_len++;     /* trailing null */
2881                 name_len *= 2;
2882
2883         } else {        /* BB improve the check for buffer overruns BB */
2884                 name_len = strnlen(toName, PATH_MAX);
2885                 name_len++;     /* trailing null */
2886                 strncpy(pSMB->FileName, toName, name_len);
2887         }
2888         params = 6 + name_len;
2889         pSMB->MaxSetupCount = 0;
2890         pSMB->Reserved = 0;
2891         pSMB->Flags = 0;
2892         pSMB->Timeout = 0;
2893         pSMB->Reserved2 = 0;
2894         param_offset = offsetof(struct smb_com_transaction2_spi_req,
2895                                 InformationLevel) - 4;
2896         offset = param_offset + params;
2897
2898         data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
2899         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2900                 name_len_target =
2901                     cifsConvertToUTF16((__le16 *) data_offset, fromName,
2902                                        PATH_MAX, nls_codepage, remap);
2903                 name_len_target++;      /* trailing null */
2904                 name_len_target *= 2;
2905         } else {        /* BB improve the check for buffer overruns BB */
2906                 name_len_target = strnlen(fromName, PATH_MAX);
2907                 name_len_target++;      /* trailing null */
2908                 strncpy(data_offset, fromName, name_len_target);
2909         }
2910
2911         pSMB->MaxParameterCount = cpu_to_le16(2);
2912         /* BB find exact max on data count below from sess*/
2913         pSMB->MaxDataCount = cpu_to_le16(1000);
2914         pSMB->SetupCount = 1;
2915         pSMB->Reserved3 = 0;
2916         pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
2917         byte_count = 3 /* pad */  + params + name_len_target;
2918         pSMB->ParameterCount = cpu_to_le16(params);
2919         pSMB->TotalParameterCount = pSMB->ParameterCount;
2920         pSMB->DataCount = cpu_to_le16(name_len_target);
2921         pSMB->TotalDataCount = pSMB->DataCount;
2922         pSMB->ParameterOffset = cpu_to_le16(param_offset);
2923         pSMB->DataOffset = cpu_to_le16(offset);
2924         pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_HLINK);
2925         pSMB->Reserved4 = 0;
2926         inc_rfc1001_len(pSMB, byte_count);
2927         pSMB->ByteCount = cpu_to_le16(byte_count);
2928         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2929                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2930         cifs_stats_inc(&tcon->stats.cifs_stats.num_hardlinks);
2931         if (rc)
2932                 cFYI(1, "Send error in SetPathInfo (hard link) = %d", rc);
2933
2934         cifs_buf_release(pSMB);
2935         if (rc == -EAGAIN)
2936                 goto createHardLinkRetry;
2937
2938         return rc;
2939 }
2940
2941 int
2942 CIFSCreateHardLink(const unsigned int xid, struct cifs_tcon *tcon,
2943                    const char *fromName, const char *toName,
2944                    const struct nls_table *nls_codepage, int remap)
2945 {
2946         int rc = 0;
2947         NT_RENAME_REQ *pSMB = NULL;
2948         RENAME_RSP *pSMBr = NULL;
2949         int bytes_returned;
2950         int name_len, name_len2;
2951         __u16 count;
2952
2953         cFYI(1, "In CIFSCreateHardLink");
2954 winCreateHardLinkRetry:
2955
2956         rc = smb_init(SMB_COM_NT_RENAME, 4, tcon, (void **) &pSMB,
2957                       (void **) &pSMBr);
2958         if (rc)
2959                 return rc;
2960
2961         pSMB->SearchAttributes =
2962             cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
2963                         ATTR_DIRECTORY);
2964         pSMB->Flags = cpu_to_le16(CREATE_HARD_LINK);
2965         pSMB->ClusterCount = 0;
2966
2967         pSMB->BufferFormat = 0x04;
2968
2969         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2970                 name_len =
2971                     cifsConvertToUTF16((__le16 *) pSMB->OldFileName, fromName,
2972                                        PATH_MAX, nls_codepage, remap);
2973                 name_len++;     /* trailing null */
2974                 name_len *= 2;
2975
2976                 /* protocol specifies ASCII buffer format (0x04) for unicode */
2977                 pSMB->OldFileName[name_len] = 0x04;
2978                 pSMB->OldFileName[name_len + 1] = 0x00; /* pad */
2979                 name_len2 =
2980                     cifsConvertToUTF16((__le16 *)&pSMB->OldFileName[name_len+2],
2981                                        toName, PATH_MAX, nls_codepage, remap);
2982                 name_len2 += 1 /* trailing null */  + 1 /* Signature word */ ;
2983                 name_len2 *= 2; /* convert to bytes */
2984         } else {        /* BB improve the check for buffer overruns BB */
2985                 name_len = strnlen(fromName, PATH_MAX);
2986                 name_len++;     /* trailing null */
2987                 strncpy(pSMB->OldFileName, fromName, name_len);
2988                 name_len2 = strnlen(toName, PATH_MAX);
2989                 name_len2++;    /* trailing null */
2990                 pSMB->OldFileName[name_len] = 0x04;     /* 2nd buffer format */
2991                 strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2);
2992                 name_len2++;    /* trailing null */
2993                 name_len2++;    /* signature byte */
2994         }
2995
2996         count = 1 /* string type byte */  + name_len + name_len2;
2997         inc_rfc1001_len(pSMB, count);
2998         pSMB->ByteCount = cpu_to_le16(count);
2999
3000         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3001                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3002         cifs_stats_inc(&tcon->stats.cifs_stats.num_hardlinks);
3003         if (rc)
3004                 cFYI(1, "Send error in hard link (NT rename) = %d", rc);
3005
3006         cifs_buf_release(pSMB);
3007         if (rc == -EAGAIN)
3008                 goto winCreateHardLinkRetry;
3009
3010         return rc;
3011 }
3012
3013 int
3014 CIFSSMBUnixQuerySymLink(const unsigned int xid, struct cifs_tcon *tcon,
3015                         const unsigned char *searchName, char **symlinkinfo,
3016                         const struct nls_table *nls_codepage)
3017 {
3018 /* SMB_QUERY_FILE_UNIX_LINK */
3019         TRANSACTION2_QPI_REQ *pSMB = NULL;
3020         TRANSACTION2_QPI_RSP *pSMBr = NULL;
3021         int rc = 0;
3022         int bytes_returned;
3023         int name_len;
3024         __u16 params, byte_count;
3025         char *data_start;
3026
3027         cFYI(1, "In QPathSymLinkInfo (Unix) for path %s", searchName);
3028
3029 querySymLinkRetry:
3030         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3031                       (void **) &pSMBr);
3032         if (rc)
3033                 return rc;
3034
3035         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3036                 name_len =
3037                         cifs_strtoUTF16((__le16 *) pSMB->FileName, searchName,
3038                                         PATH_MAX, nls_codepage);
3039                 name_len++;     /* trailing null */
3040                 name_len *= 2;
3041         } else {        /* BB improve the check for buffer overruns BB */
3042                 name_len = strnlen(searchName, PATH_MAX);
3043                 name_len++;     /* trailing null */
3044                 strncpy(pSMB->FileName, searchName, name_len);
3045         }
3046
3047         params = 2 /* level */  + 4 /* rsrvd */  + name_len /* incl null */ ;
3048         pSMB->TotalDataCount = 0;
3049         pSMB->MaxParameterCount = cpu_to_le16(2);
3050         pSMB->MaxDataCount = cpu_to_le16(CIFSMaxBufSize);
3051         pSMB->MaxSetupCount = 0;
3052         pSMB->Reserved = 0;
3053         pSMB->Flags = 0;
3054         pSMB->Timeout = 0;
3055         pSMB->Reserved2 = 0;
3056         pSMB->ParameterOffset = cpu_to_le16(offsetof(
3057         struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
3058         pSMB->DataCount = 0;
3059         pSMB->DataOffset = 0;
3060         pSMB->SetupCount = 1;
3061         pSMB->Reserved3 = 0;
3062         pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
3063         byte_count = params + 1 /* pad */ ;
3064         pSMB->TotalParameterCount = cpu_to_le16(params);
3065         pSMB->ParameterCount = pSMB->TotalParameterCount;
3066         pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_LINK);
3067         pSMB->Reserved4 = 0;
3068         inc_rfc1001_len(pSMB, byte_count);
3069         pSMB->ByteCount = cpu_to_le16(byte_count);
3070
3071         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3072                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3073         if (rc) {
3074                 cFYI(1, "Send error in QuerySymLinkInfo = %d", rc);
3075         } else {
3076                 /* decode response */
3077
3078                 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3079                 /* BB also check enough total bytes returned */
3080                 if (rc || get_bcc(&pSMBr->hdr) < 2)
3081                         rc = -EIO;
3082                 else {
3083                         bool is_unicode;
3084                         u16 count = le16_to_cpu(pSMBr->t2.DataCount);
3085
3086                         data_start = ((char *) &pSMBr->hdr.Protocol) +
3087                                            le16_to_cpu(pSMBr->t2.DataOffset);
3088
3089                         if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
3090                                 is_unicode = true;
3091                         else
3092                                 is_unicode = false;
3093
3094                         /* BB FIXME investigate remapping reserved chars here */
3095                         *symlinkinfo = cifs_strndup_from_utf16(data_start,
3096                                         count, is_unicode, nls_codepage);
3097                         if (!*symlinkinfo)
3098                                 rc = -ENOMEM;
3099                 }
3100         }
3101         cifs_buf_release(pSMB);
3102         if (rc == -EAGAIN)
3103                 goto querySymLinkRetry;
3104         return rc;
3105 }
3106
3107 #ifdef CONFIG_CIFS_SYMLINK_EXPERIMENTAL
3108 /*
3109  *      Recent Windows versions now create symlinks more frequently
3110  *      and they use the "reparse point" mechanism below.  We can of course
3111  *      do symlinks nicely to Samba and other servers which support the
3112  *      CIFS Unix Extensions and we can also do SFU symlinks and "client only"
3113  *      "MF" symlinks optionally, but for recent Windows we really need to
3114  *      reenable the code below and fix the cifs_symlink callers to handle this.
3115  *      In the interim this code has been moved to its own config option so
3116  *      it is not compiled in by default until callers fixed up and more tested.
3117  */
3118 int
3119 CIFSSMBQueryReparseLinkInfo(const unsigned int xid, struct cifs_tcon *tcon,
3120                         const unsigned char *searchName,
3121                         char *symlinkinfo, const int buflen, __u16 fid,
3122                         const struct nls_table *nls_codepage)
3123 {
3124         int rc = 0;
3125         int bytes_returned;
3126         struct smb_com_transaction_ioctl_req *pSMB;
3127         struct smb_com_transaction_ioctl_rsp *pSMBr;
3128
3129         cFYI(1, "In Windows reparse style QueryLink for path %s", searchName);
3130         rc = smb_init(SMB_COM_NT_TRANSACT, 23, tcon, (void **) &pSMB,
3131                       (void **) &pSMBr);
3132         if (rc)
3133                 return rc;
3134
3135         pSMB->TotalParameterCount = 0 ;
3136         pSMB->TotalDataCount = 0;
3137         pSMB->MaxParameterCount = cpu_to_le32(2);
3138         /* BB find exact data count max from sess structure BB */
3139         pSMB->MaxDataCount = cpu_to_le32(CIFSMaxBufSize & 0xFFFFFF00);
3140         pSMB->MaxSetupCount = 4;
3141         pSMB->Reserved = 0;
3142         pSMB->ParameterOffset = 0;
3143         pSMB->DataCount = 0;
3144         pSMB->DataOffset = 0;
3145         pSMB->SetupCount = 4;
3146         pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_IOCTL);
3147         pSMB->ParameterCount = pSMB->TotalParameterCount;
3148         pSMB->FunctionCode = cpu_to_le32(FSCTL_GET_REPARSE_POINT);
3149         pSMB->IsFsctl = 1; /* FSCTL */
3150         pSMB->IsRootFlag = 0;
3151         pSMB->Fid = fid; /* file handle always le */
3152         pSMB->ByteCount = 0;
3153
3154         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3155                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3156         if (rc) {
3157                 cFYI(1, "Send error in QueryReparseLinkInfo = %d", rc);
3158         } else {                /* decode response */
3159                 __u32 data_offset = le32_to_cpu(pSMBr->DataOffset);
3160                 __u32 data_count = le32_to_cpu(pSMBr->DataCount);
3161                 if (get_bcc(&pSMBr->hdr) < 2 || data_offset > 512) {
3162                         /* BB also check enough total bytes returned */
3163                         rc = -EIO;      /* bad smb */
3164                         goto qreparse_out;
3165                 }
3166                 if (data_count && (data_count < 2048)) {
3167                         char *end_of_smb = 2 /* sizeof byte count */ +
3168                                get_bcc(&pSMBr->hdr) + (char *)&pSMBr->ByteCount;
3169
3170                         struct reparse_data *reparse_buf =
3171                                                 (struct reparse_data *)
3172                                                 ((char *)&pSMBr->hdr.Protocol
3173                                                                  + data_offset);
3174                         if ((char *)reparse_buf >= end_of_smb) {
3175                                 rc = -EIO;
3176                                 goto qreparse_out;
3177                         }
3178                         if ((reparse_buf->LinkNamesBuf +
3179                                 reparse_buf->TargetNameOffset +
3180                                 reparse_buf->TargetNameLen) > end_of_smb) {
3181                                 cFYI(1, "reparse buf beyond SMB");
3182                                 rc = -EIO;
3183                                 goto qreparse_out;
3184                         }
3185
3186                         if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
3187                                 cifs_from_ucs2(symlinkinfo, (__le16 *)
3188                                                 (reparse_buf->LinkNamesBuf +
3189                                                 reparse_buf->TargetNameOffset),
3190                                                 buflen,
3191                                                 reparse_buf->TargetNameLen,
3192                                                 nls_codepage, 0);
3193                         } else { /* ASCII names */
3194                                 strncpy(symlinkinfo,
3195                                         reparse_buf->LinkNamesBuf +
3196                                         reparse_buf->TargetNameOffset,
3197                                         min_t(const int, buflen,
3198                                            reparse_buf->TargetNameLen));
3199                         }
3200                 } else {
3201                         rc = -EIO;
3202                         cFYI(1, "Invalid return data count on "
3203                                  "get reparse info ioctl");
3204                 }
3205                 symlinkinfo[buflen] = 0; /* just in case so the caller
3206                                         does not go off the end of the buffer */
3207                 cFYI(1, "readlink result - %s", symlinkinfo);
3208         }
3209
3210 qreparse_out:
3211         cifs_buf_release(pSMB);
3212
3213         /* Note: On -EAGAIN error only caller can retry on handle based calls
3214                 since file handle passed in no longer valid */
3215
3216         return rc;
3217 }
3218 #endif /* CIFS_SYMLINK_EXPERIMENTAL */ /* BB temporarily unused */
3219
3220 #ifdef CONFIG_CIFS_POSIX
3221
3222 /*Convert an Access Control Entry from wire format to local POSIX xattr format*/
3223 static void cifs_convert_ace(posix_acl_xattr_entry *ace,
3224                              struct cifs_posix_ace *cifs_ace)
3225 {
3226         /* u8 cifs fields do not need le conversion */
3227         ace->e_perm = cpu_to_le16(cifs_ace->cifs_e_perm);
3228         ace->e_tag  = cpu_to_le16(cifs_ace->cifs_e_tag);
3229         ace->e_id   = cpu_to_le32(le64_to_cpu(cifs_ace->cifs_uid));
3230         /* cFYI(1, "perm %d tag %d id %d",ace->e_perm,ace->e_tag,ace->e_id); */
3231
3232         return;
3233 }
3234
3235 /* Convert ACL from CIFS POSIX wire format to local Linux POSIX ACL xattr */
3236 static int cifs_copy_posix_acl(char *trgt, char *src, const int buflen,
3237                                const int acl_type, const int size_of_data_area)
3238 {
3239         int size =  0;
3240         int i;
3241         __u16 count;
3242         struct cifs_posix_ace *pACE;
3243         struct cifs_posix_acl *cifs_acl = (struct cifs_posix_acl *)src;
3244         posix_acl_xattr_header *local_acl = (posix_acl_xattr_header *)trgt;
3245
3246         if (le16_to_cpu(cifs_acl->version) != CIFS_ACL_VERSION)
3247                 return -EOPNOTSUPP;
3248
3249         if (acl_type & ACL_TYPE_ACCESS) {
3250                 count = le16_to_cpu(cifs_acl->access_entry_count);
3251                 pACE = &cifs_acl->ace_array[0];
3252                 size = sizeof(struct cifs_posix_acl);
3253                 size += sizeof(struct cifs_posix_ace) * count;
3254                 /* check if we would go beyond end of SMB */
3255                 if (size_of_data_area < size) {
3256                         cFYI(1, "bad CIFS POSIX ACL size %d vs. %d",
3257                                 size_of_data_area, size);
3258                         return -EINVAL;
3259                 }
3260         } else if (acl_type & ACL_TYPE_DEFAULT) {
3261                 count = le16_to_cpu(cifs_acl->access_entry_count);
3262                 size = sizeof(struct cifs_posix_acl);
3263                 size += sizeof(struct cifs_posix_ace) * count;
3264 /* skip past access ACEs to get to default ACEs */
3265                 pACE = &cifs_acl->ace_array[count];
3266                 count = le16_to_cpu(cifs_acl->default_entry_count);
3267                 size += sizeof(struct cifs_posix_ace) * count;
3268                 /* check if we would go beyond end of SMB */
3269                 if (size_of_data_area < size)
3270                         return -EINVAL;
3271         } else {
3272                 /* illegal type */
3273                 return -EINVAL;
3274         }
3275
3276         size = posix_acl_xattr_size(count);
3277         if ((buflen == 0) || (local_acl == NULL)) {
3278                 /* used to query ACL EA size */
3279         } else if (size > buflen) {
3280                 return -ERANGE;
3281         } else /* buffer big enough */ {
3282                 local_acl->a_version = cpu_to_le32(POSIX_ACL_XATTR_VERSION);
3283                 for (i = 0; i < count ; i++) {
3284                         cifs_convert_ace(&local_acl->a_entries[i], pACE);
3285                         pACE++;
3286                 }
3287         }
3288         return size;
3289 }
3290
3291 static __u16 convert_ace_to_cifs_ace(struct cifs_posix_ace *cifs_ace,
3292                                      const posix_acl_xattr_entry *local_ace)
3293 {
3294         __u16 rc = 0; /* 0 = ACL converted ok */
3295
3296         cifs_ace->cifs_e_perm = le16_to_cpu(local_ace->e_perm);
3297         cifs_ace->cifs_e_tag =  le16_to_cpu(local_ace->e_tag);
3298         /* BB is there a better way to handle the large uid? */
3299         if (local_ace->e_id == cpu_to_le32(-1)) {
3300         /* Probably no need to le convert -1 on any arch but can not hurt */
3301                 cifs_ace->cifs_uid = cpu_to_le64(-1);
3302         } else
3303                 cifs_ace->cifs_uid = cpu_to_le64(le32_to_cpu(local_ace->e_id));
3304         /*cFYI(1, "perm %d tag %d id %d",ace->e_perm,ace->e_tag,ace->e_id);*/
3305         return rc;
3306 }
3307
3308 /* Convert ACL from local Linux POSIX xattr to CIFS POSIX ACL wire format */
3309 static __u16 ACL_to_cifs_posix(char *parm_data, const char *pACL,
3310                                const int buflen, const int acl_type)
3311 {
3312         __u16 rc = 0;
3313         struct cifs_posix_acl *cifs_acl = (struct cifs_posix_acl *)parm_data;
3314         posix_acl_xattr_header *local_acl = (posix_acl_xattr_header *)pACL;
3315         int count;
3316         int i;
3317
3318         if ((buflen == 0) || (pACL == NULL) || (cifs_acl == NULL))
3319                 return 0;
3320
3321         count = posix_acl_xattr_count((size_t)buflen);
3322         cFYI(1, "setting acl with %d entries from buf of length %d and "
3323                 "version of %d",
3324                 count, buflen, le32_to_cpu(local_acl->a_version));
3325         if (le32_to_cpu(local_acl->a_version) != 2) {
3326                 cFYI(1, "unknown POSIX ACL version %d",
3327                      le32_to_cpu(local_acl->a_version));
3328                 return 0;
3329         }
3330         cifs_acl->version = cpu_to_le16(1);
3331         if (acl_type == ACL_TYPE_ACCESS)
3332                 cifs_acl->access_entry_count = cpu_to_le16(count);
3333         else if (acl_type == ACL_TYPE_DEFAULT)
3334                 cifs_acl->default_entry_count = cpu_to_le16(count);
3335         else {
3336                 cFYI(1, "unknown ACL type %d", acl_type);
3337                 return 0;
3338         }
3339         for (i = 0; i < count; i++) {
3340                 rc = convert_ace_to_cifs_ace(&cifs_acl->ace_array[i],
3341                                         &local_acl->a_entries[i]);
3342                 if (rc != 0) {
3343                         /* ACE not converted */
3344                         break;
3345                 }
3346         }
3347         if (rc == 0) {
3348                 rc = (__u16)(count * sizeof(struct cifs_posix_ace));
3349                 rc += sizeof(struct cifs_posix_acl);
3350                 /* BB add check to make sure ACL does not overflow SMB */
3351         }
3352         return rc;
3353 }
3354
3355 int
3356 CIFSSMBGetPosixACL(const unsigned int xid, struct cifs_tcon *tcon,
3357                    const unsigned char *searchName,
3358                    char *acl_inf, const int buflen, const int acl_type,
3359                    const struct nls_table *nls_codepage, int remap)
3360 {
3361 /* SMB_QUERY_POSIX_ACL */
3362         TRANSACTION2_QPI_REQ *pSMB = NULL;
3363         TRANSACTION2_QPI_RSP *pSMBr = NULL;
3364         int rc = 0;
3365         int bytes_returned;
3366         int name_len;
3367         __u16 params, byte_count;
3368
3369         cFYI(1, "In GetPosixACL (Unix) for path %s", searchName);
3370
3371 queryAclRetry:
3372         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3373                 (void **) &pSMBr);
3374         if (rc)
3375                 return rc;
3376
3377         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3378                 name_len =
3379                         cifsConvertToUTF16((__le16 *) pSMB->FileName,
3380                                            searchName, PATH_MAX, nls_codepage,
3381                                            remap);
3382                 name_len++;     /* trailing null */
3383                 name_len *= 2;
3384                 pSMB->FileName[name_len] = 0;
3385                 pSMB->FileName[name_len+1] = 0;
3386         } else {        /* BB improve the check for buffer overruns BB */
3387                 name_len = strnlen(searchName, PATH_MAX);
3388                 name_len++;     /* trailing null */
3389                 strncpy(pSMB->FileName, searchName, name_len);
3390         }
3391
3392         params = 2 /* level */  + 4 /* rsrvd */  + name_len /* incl null */ ;
3393         pSMB->TotalDataCount = 0;
3394         pSMB->MaxParameterCount = cpu_to_le16(2);
3395         /* BB find exact max data count below from sess structure BB */
3396         pSMB->MaxDataCount = cpu_to_le16(4000);
3397         pSMB->MaxSetupCount = 0;
3398         pSMB->Reserved = 0;
3399         pSMB->Flags = 0;
3400         pSMB->Timeout = 0;
3401         pSMB->Reserved2 = 0;
3402         pSMB->ParameterOffset = cpu_to_le16(
3403                 offsetof(struct smb_com_transaction2_qpi_req,
3404                          InformationLevel) - 4);
3405         pSMB->DataCount = 0;
3406         pSMB->DataOffset = 0;
3407         pSMB->SetupCount = 1;
3408         pSMB->Reserved3 = 0;
3409         pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
3410         byte_count = params + 1 /* pad */ ;
3411         pSMB->TotalParameterCount = cpu_to_le16(params);
3412         pSMB->ParameterCount = pSMB->TotalParameterCount;
3413         pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_POSIX_ACL);
3414         pSMB->Reserved4 = 0;
3415         inc_rfc1001_len(pSMB, byte_count);
3416         pSMB->ByteCount = cpu_to_le16(byte_count);
3417
3418         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3419                 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3420         cifs_stats_inc(&tcon->stats.cifs_stats.num_acl_get);
3421         if (rc) {
3422                 cFYI(1, "Send error in Query POSIX ACL = %d", rc);
3423         } else {
3424                 /* decode response */
3425
3426                 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3427                 /* BB also check enough total bytes returned */
3428                 if (rc || get_bcc(&pSMBr->hdr) < 2)
3429                         rc = -EIO;      /* bad smb */
3430                 else {
3431                         __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3432                         __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
3433                         rc = cifs_copy_posix_acl(acl_inf,
3434                                 (char *)&pSMBr->hdr.Protocol+data_offset,
3435                                 buflen, acl_type, count);
3436                 }
3437         }
3438         cifs_buf_release(pSMB);
3439         if (rc == -EAGAIN)
3440                 goto queryAclRetry;
3441         return rc;
3442 }
3443
3444 int
3445 CIFSSMBSetPosixACL(const unsigned int xid, struct cifs_tcon *tcon,
3446                    const unsigned char *fileName,
3447                    const char *local_acl, const int buflen,
3448                    const int acl_type,
3449                    const struct nls_table *nls_codepage, int remap)
3450 {
3451         struct smb_com_transaction2_spi_req *pSMB = NULL;
3452         struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
3453         char *parm_data;
3454         int name_len;
3455         int rc = 0;
3456         int bytes_returned = 0;
3457         __u16 params, byte_count, data_count, param_offset, offset;
3458
3459         cFYI(1, "In SetPosixACL (Unix) for path %s", fileName);
3460 setAclRetry:
3461         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3462                       (void **) &pSMBr);
3463         if (rc)
3464                 return rc;
3465         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3466                 name_len =
3467                         cifsConvertToUTF16((__le16 *) pSMB->FileName, fileName,
3468                                            PATH_MAX, nls_codepage, remap);
3469                 name_len++;     /* trailing null */
3470                 name_len *= 2;
3471         } else {        /* BB improve the check for buffer overruns BB */
3472                 name_len = strnlen(fileName, PATH_MAX);
3473                 name_len++;     /* trailing null */
3474                 strncpy(pSMB->FileName, fileName, name_len);
3475         }
3476         params = 6 + name_len;
3477         pSMB->MaxParameterCount = cpu_to_le16(2);
3478         /* BB find max SMB size from sess */
3479         pSMB->MaxDataCount = cpu_to_le16(1000);
3480         pSMB->MaxSetupCount = 0;
3481         pSMB->Reserved = 0;
3482         pSMB->Flags = 0;
3483         pSMB->Timeout = 0;
3484         pSMB->Reserved2 = 0;
3485         param_offset = offsetof(struct smb_com_transaction2_spi_req,
3486                                 InformationLevel) - 4;
3487         offset = param_offset + params;
3488         parm_data = ((char *) &pSMB->hdr.Protocol) + offset;
3489         pSMB->ParameterOffset = cpu_to_le16(param_offset);
3490
3491         /* convert to on the wire format for POSIX ACL */
3492         data_count = ACL_to_cifs_posix(parm_data, local_acl, buflen, acl_type);
3493
3494         if (data_count == 0) {
3495                 rc = -EOPNOTSUPP;
3496                 goto setACLerrorExit;
3497         }
3498         pSMB->DataOffset = cpu_to_le16(offset);
3499         pSMB->SetupCount = 1;
3500         pSMB->Reserved3 = 0;
3501         pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
3502         pSMB->InformationLevel = cpu_to_le16(SMB_SET_POSIX_ACL);
3503         byte_count = 3 /* pad */  + params + data_count;
3504         pSMB->DataCount = cpu_to_le16(data_count);
3505         pSMB->TotalDataCount = pSMB->DataCount;
3506         pSMB->ParameterCount = cpu_to_le16(params);
3507         pSMB->TotalParameterCount = pSMB->ParameterCount;
3508         pSMB->Reserved4 = 0;
3509         inc_rfc1001_len(pSMB, byte_count);
3510         pSMB->ByteCount = cpu_to_le16(byte_count);
3511         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3512                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3513         if (rc)
3514                 cFYI(1, "Set POSIX ACL returned %d", rc);
3515
3516 setACLerrorExit:
3517         cifs_buf_release(pSMB);
3518         if (rc == -EAGAIN)
3519                 goto setAclRetry;
3520         return rc;
3521 }
3522
3523 /* BB fix tabs in this function FIXME BB */
3524 int
3525 CIFSGetExtAttr(const unsigned int xid, struct cifs_tcon *tcon,
3526                const int netfid, __u64 *pExtAttrBits, __u64 *pMask)
3527 {
3528         int rc = 0;
3529         struct smb_t2_qfi_req *pSMB = NULL;
3530         struct smb_t2_qfi_rsp *pSMBr = NULL;
3531         int bytes_returned;
3532         __u16 params, byte_count;
3533
3534         cFYI(1, "In GetExtAttr");
3535         if (tcon == NULL)
3536                 return -ENODEV;
3537
3538 GetExtAttrRetry:
3539         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3540                         (void **) &pSMBr);
3541         if (rc)
3542                 return rc;
3543
3544         params = 2 /* level */ + 2 /* fid */;
3545         pSMB->t2.TotalDataCount = 0;
3546         pSMB->t2.MaxParameterCount = cpu_to_le16(4);
3547         /* BB find exact max data count below from sess structure BB */
3548         pSMB->t2.MaxDataCount = cpu_to_le16(4000);
3549         pSMB->t2.MaxSetupCount = 0;
3550         pSMB->t2.Reserved = 0;
3551         pSMB->t2.Flags = 0;
3552         pSMB->t2.Timeout = 0;
3553         pSMB->t2.Reserved2 = 0;
3554         pSMB->t2.ParameterOffset = cpu_to_le16(offsetof(struct smb_t2_qfi_req,
3555                                                Fid) - 4);
3556         pSMB->t2.DataCount = 0;
3557         pSMB->t2.DataOffset = 0;
3558         pSMB->t2.SetupCount = 1;
3559         pSMB->t2.Reserved3 = 0;
3560         pSMB->t2.SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION);
3561         byte_count = params + 1 /* pad */ ;
3562         pSMB->t2.TotalParameterCount = cpu_to_le16(params);
3563         pSMB->t2.ParameterCount = pSMB->t2.TotalParameterCount;
3564         pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_ATTR_FLAGS);
3565         pSMB->Pad = 0;
3566         pSMB->Fid = netfid;
3567         inc_rfc1001_len(pSMB, byte_count);
3568         pSMB->t2.ByteCount = cpu_to_le16(byte_count);
3569
3570         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3571                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3572         if (rc) {
3573                 cFYI(1, "error %d in GetExtAttr", rc);
3574         } else {
3575                 /* decode response */
3576                 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3577                 /* BB also check enough total bytes returned */
3578                 if (rc || get_bcc(&pSMBr->hdr) < 2)
3579                         /* If rc should we check for EOPNOSUPP and
3580                            disable the srvino flag? or in caller? */
3581                         rc = -EIO;      /* bad smb */
3582                 else {
3583                         __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3584                         __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
3585                         struct file_chattr_info *pfinfo;
3586                         /* BB Do we need a cast or hash here ? */
3587                         if (count != 16) {
3588                                 cFYI(1, "Illegal size ret in GetExtAttr");
3589                                 rc = -EIO;
3590                                 goto GetExtAttrOut;
3591                         }
3592                         pfinfo = (struct file_chattr_info *)
3593                                  (data_offset + (char *) &pSMBr->hdr.Protocol);
3594                         *pExtAttrBits = le64_to_cpu(pfinfo->mode);
3595                         *pMask = le64_to_cpu(pfinfo->mask);
3596                 }
3597         }
3598 GetExtAttrOut:
3599         cifs_buf_release(pSMB);
3600         if (rc == -EAGAIN)
3601                 goto GetExtAttrRetry;
3602         return rc;
3603 }
3604
3605 #endif /* CONFIG_POSIX */
3606
3607 #ifdef CONFIG_CIFS_ACL
3608 /*
3609  * Initialize NT TRANSACT SMB into small smb request buffer.  This assumes that
3610  * all NT TRANSACTS that we init here have total parm and data under about 400
3611  * bytes (to fit in small cifs buffer size), which is the case so far, it
3612  * easily fits. NB: Setup words themselves and ByteCount MaxSetupCount (size of
3613  * returned setup area) and MaxParameterCount (returned parms size) must be set
3614  * by caller
3615  */
3616 static int
3617 smb_init_nttransact(const __u16 sub_command, const int setup_count,
3618                    const int parm_len, struct cifs_tcon *tcon,
3619                    void **ret_buf)
3620 {
3621         int rc;
3622         __u32 temp_offset;
3623         struct smb_com_ntransact_req *pSMB;
3624
3625         rc = small_smb_init(SMB_COM_NT_TRANSACT, 19 + setup_count, tcon,
3626                                 (void **)&pSMB);
3627         if (rc)
3628                 return rc;
3629         *ret_buf = (void *)pSMB;
3630         pSMB->Reserved = 0;
3631         pSMB->TotalParameterCount = cpu_to_le32(parm_len);
3632         pSMB->TotalDataCount  = 0;
3633         pSMB->MaxDataCount = cpu_to_le32(CIFSMaxBufSize & 0xFFFFFF00);
3634         pSMB->ParameterCount = pSMB->TotalParameterCount;
3635         pSMB->DataCount  = pSMB->TotalDataCount;
3636         temp_offset = offsetof(struct smb_com_ntransact_req, Parms) +
3637                         (setup_count * 2) - 4 /* for rfc1001 length itself */;
3638         pSMB->ParameterOffset = cpu_to_le32(temp_offset);
3639         pSMB->DataOffset = cpu_to_le32(temp_offset + parm_len);
3640         pSMB->SetupCount = setup_count; /* no need to le convert byte fields */
3641         pSMB->SubCommand = cpu_to_le16(sub_command);
3642         return 0;
3643 }
3644
3645 static int
3646 validate_ntransact(char *buf, char **ppparm, char **ppdata,
3647                    __u32 *pparmlen, __u32 *pdatalen)
3648 {
3649         char *end_of_smb;
3650         __u32 data_count, data_offset, parm_count, parm_offset;
3651         struct smb_com_ntransact_rsp *pSMBr;
3652         u16 bcc;
3653
3654         *pdatalen = 0;
3655         *pparmlen = 0;
3656
3657         if (buf == NULL)
3658                 return -EINVAL;
3659
3660         pSMBr = (struct smb_com_ntransact_rsp *)buf;
3661
3662         bcc = get_bcc(&pSMBr->hdr);
3663         end_of_smb = 2 /* sizeof byte count */ + bcc +
3664                         (char *)&pSMBr->ByteCount;
3665
3666         data_offset = le32_to_cpu(pSMBr->DataOffset);
3667         data_count = le32_to_cpu(pSMBr->DataCount);
3668         parm_offset = le32_to_cpu(pSMBr->ParameterOffset);
3669         parm_count = le32_to_cpu(pSMBr->ParameterCount);
3670
3671         *ppparm = (char *)&pSMBr->hdr.Protocol + parm_offset;
3672         *ppdata = (char *)&pSMBr->hdr.Protocol + data_offset;
3673
3674         /* should we also check that parm and data areas do not overlap? */
3675         if (*ppparm > end_of_smb) {
3676                 cFYI(1, "parms start after end of smb");
3677                 return -EINVAL;
3678         } else if (parm_count + *ppparm > end_of_smb) {
3679                 cFYI(1, "parm end after end of smb");
3680                 return -EINVAL;
3681         } else if (*ppdata > end_of_smb) {
3682                 cFYI(1, "data starts after end of smb");
3683                 return -EINVAL;
3684         } else if (data_count + *ppdata > end_of_smb) {
3685                 cFYI(1, "data %p + count %d (%p) past smb end %p start %p",
3686                         *ppdata, data_count, (data_count + *ppdata),
3687                         end_of_smb, pSMBr);
3688                 return -EINVAL;
3689         } else if (parm_count + data_count > bcc) {
3690                 cFYI(1, "parm count and data count larger than SMB");
3691                 return -EINVAL;
3692         }
3693         *pdatalen = data_count;
3694         *pparmlen = parm_count;
3695         return 0;
3696 }
3697
3698 /* Get Security Descriptor (by handle) from remote server for a file or dir */
3699 int
3700 CIFSSMBGetCIFSACL(const unsigned int xid, struct cifs_tcon *tcon, __u16 fid,
3701                   struct cifs_ntsd **acl_inf, __u32 *pbuflen)
3702 {
3703         int rc = 0;
3704         int buf_type = 0;
3705         QUERY_SEC_DESC_REQ *pSMB;
3706         struct kvec iov[1];
3707
3708         cFYI(1, "GetCifsACL");
3709
3710         *pbuflen = 0;
3711         *acl_inf = NULL;
3712
3713         rc = smb_init_nttransact(NT_TRANSACT_QUERY_SECURITY_DESC, 0,
3714                         8 /* parm len */, tcon, (void **) &pSMB);
3715         if (rc)
3716                 return rc;
3717
3718         pSMB->MaxParameterCount = cpu_to_le32(4);
3719         /* BB TEST with big acls that might need to be e.g. larger than 16K */
3720         pSMB->MaxSetupCount = 0;
3721         pSMB->Fid = fid; /* file handle always le */
3722         pSMB->AclFlags = cpu_to_le32(CIFS_ACL_OWNER | CIFS_ACL_GROUP |
3723                                      CIFS_ACL_DACL);
3724         pSMB->ByteCount = cpu_to_le16(11); /* 3 bytes pad + 8 bytes parm */
3725         inc_rfc1001_len(pSMB, 11);
3726         iov[0].iov_base = (char *)pSMB;
3727         iov[0].iov_len = be32_to_cpu(pSMB->hdr.smb_buf_length) + 4;
3728
3729         rc = SendReceive2(xid, tcon->ses, iov, 1 /* num iovec */, &buf_type,
3730                          0);
3731         cifs_stats_inc(&tcon->stats.cifs_stats.num_acl_get);
3732         if (rc) {
3733                 cFYI(1, "Send error in QuerySecDesc = %d", rc);
3734         } else {                /* decode response */
3735                 __le32 *parm;
3736                 __u32 parm_len;
3737                 __u32 acl_len;
3738                 struct smb_com_ntransact_rsp *pSMBr;
3739                 char *pdata;
3740
3741 /* validate_nttransact */
3742                 rc = validate_ntransact(iov[0].iov_base, (char **)&parm,
3743                                         &pdata, &parm_len, pbuflen);
3744                 if (rc)
3745                         goto qsec_out;
3746                 pSMBr = (struct smb_com_ntransact_rsp *)iov[0].iov_base;
3747
3748                 cFYI(1, "smb %p parm %p data %p", pSMBr, parm, *acl_inf);
3749
3750                 if (le32_to_cpu(pSMBr->ParameterCount) != 4) {
3751                         rc = -EIO;      /* bad smb */
3752                         *pbuflen = 0;
3753                         goto qsec_out;
3754                 }
3755
3756 /* BB check that data area is minimum length and as big as acl_len */
3757
3758                 acl_len = le32_to_cpu(*parm);
3759                 if (acl_len != *pbuflen) {
3760                         cERROR(1, "acl length %d does not match %d",
3761                                    acl_len, *pbuflen);
3762                         if (*pbuflen > acl_len)
3763                                 *pbuflen = acl_len;
3764                 }
3765
3766                 /* check if buffer is big enough for the acl
3767                    header followed by the smallest SID */
3768                 if ((*pbuflen < sizeof(struct cifs_ntsd) + 8) ||
3769                     (*pbuflen >= 64 * 1024)) {
3770                         cERROR(1, "bad acl length %d", *pbuflen);
3771                         rc = -EINVAL;
3772                         *pbuflen = 0;
3773                 } else {
3774                         *acl_inf = kmalloc(*pbuflen, GFP_KERNEL);
3775                         if (*acl_inf == NULL) {
3776                                 *pbuflen = 0;
3777                                 rc = -ENOMEM;
3778                         }
3779                         memcpy(*acl_inf, pdata, *pbuflen);
3780                 }
3781         }
3782 qsec_out:
3783         if (buf_type == CIFS_SMALL_BUFFER)
3784                 cifs_small_buf_release(iov[0].iov_base);
3785         else if (buf_type == CIFS_LARGE_BUFFER)
3786                 cifs_buf_release(iov[0].iov_base);
3787 /*      cifs_small_buf_release(pSMB); */ /* Freed earlier now in SendReceive2 */
3788         return rc;
3789 }
3790
3791 int
3792 CIFSSMBSetCIFSACL(const unsigned int xid, struct cifs_tcon *tcon, __u16 fid,
3793                         struct cifs_ntsd *pntsd, __u32 acllen, int aclflag)
3794 {
3795         __u16 byte_count, param_count, data_count, param_offset, data_offset;
3796         int rc = 0;
3797         int bytes_returned = 0;
3798         SET_SEC_DESC_REQ *pSMB = NULL;
3799         void *pSMBr;
3800
3801 setCifsAclRetry:
3802         rc = smb_init(SMB_COM_NT_TRANSACT, 19, tcon, (void **) &pSMB, &pSMBr);
3803         if (rc)
3804                 return rc;
3805
3806         pSMB->MaxSetupCount = 0;
3807         pSMB->Reserved = 0;
3808
3809         param_count = 8;
3810         param_offset = offsetof(struct smb_com_transaction_ssec_req, Fid) - 4;
3811         data_count = acllen;
3812         data_offset = param_offset + param_count;
3813         byte_count = 3 /* pad */  + param_count;
3814
3815         pSMB->DataCount = cpu_to_le32(data_count);
3816         pSMB->TotalDataCount = pSMB->DataCount;
3817         pSMB->MaxParameterCount = cpu_to_le32(4);
3818         pSMB->MaxDataCount = cpu_to_le32(16384);
3819         pSMB->ParameterCount = cpu_to_le32(param_count);
3820         pSMB->ParameterOffset = cpu_to_le32(param_offset);
3821         pSMB->TotalParameterCount = pSMB->ParameterCount;
3822         pSMB->DataOffset = cpu_to_le32(data_offset);
3823         pSMB->SetupCount = 0;
3824         pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_SET_SECURITY_DESC);
3825         pSMB->ByteCount = cpu_to_le16(byte_count+data_count);
3826
3827         pSMB->Fid = fid; /* file handle always le */
3828         pSMB->Reserved2 = 0;
3829         pSMB->AclFlags = cpu_to_le32(aclflag);
3830
3831         if (pntsd && acllen) {
3832                 memcpy((char *)pSMBr + offsetof(struct smb_hdr, Protocol) +
3833                                 data_offset, pntsd, acllen);
3834                 inc_rfc1001_len(pSMB, byte_count + data_count);
3835         } else
3836                 inc_rfc1001_len(pSMB, byte_count);
3837
3838         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3839                 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3840
3841         cFYI(1, "SetCIFSACL bytes_returned: %d, rc: %d", bytes_returned, rc);
3842         if (rc)
3843                 cFYI(1, "Set CIFS ACL returned %d", rc);
3844         cifs_buf_release(pSMB);
3845
3846         if (rc == -EAGAIN)
3847                 goto setCifsAclRetry;
3848
3849         return (rc);
3850 }
3851
3852 #endif /* CONFIG_CIFS_ACL */
3853
3854 /* Legacy Query Path Information call for lookup to old servers such
3855    as Win9x/WinME */
3856 int
3857 SMBQueryInformation(const unsigned int xid, struct cifs_tcon *tcon,
3858                     const char *search_name, FILE_ALL_INFO *data,
3859                     const struct nls_table *nls_codepage, int remap)
3860 {
3861         QUERY_INFORMATION_REQ *pSMB;
3862         QUERY_INFORMATION_RSP *pSMBr;
3863         int rc = 0;
3864         int bytes_returned;
3865         int name_len;
3866
3867         cFYI(1, "In SMBQPath path %s", search_name);
3868 QInfRetry:
3869         rc = smb_init(SMB_COM_QUERY_INFORMATION, 0, tcon, (void **) &pSMB,
3870                       (void **) &pSMBr);
3871         if (rc)
3872                 return rc;
3873
3874         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3875                 name_len =
3876                         cifsConvertToUTF16((__le16 *) pSMB->FileName,
3877                                            search_name, PATH_MAX, nls_codepage,
3878                                            remap);
3879                 name_len++;     /* trailing null */
3880                 name_len *= 2;
3881         } else {
3882                 name_len = strnlen(search_name, PATH_MAX);
3883                 name_len++;     /* trailing null */
3884                 strncpy(pSMB->FileName, search_name, name_len);
3885         }
3886         pSMB->BufferFormat = 0x04;
3887         name_len++; /* account for buffer type byte */
3888         inc_rfc1001_len(pSMB, (__u16)name_len);
3889         pSMB->ByteCount = cpu_to_le16(name_len);
3890
3891         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3892                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3893         if (rc) {
3894                 cFYI(1, "Send error in QueryInfo = %d", rc);
3895         } else if (data) {
3896                 struct timespec ts;
3897                 __u32 time = le32_to_cpu(pSMBr->last_write_time);
3898
3899                 /* decode response */
3900                 /* BB FIXME - add time zone adjustment BB */
3901                 memset(data, 0, sizeof(FILE_ALL_INFO));
3902                 ts.tv_nsec = 0;
3903                 ts.tv_sec = time;
3904                 /* decode time fields */
3905                 data->ChangeTime = cpu_to_le64(cifs_UnixTimeToNT(ts));
3906                 data->LastWriteTime = data->ChangeTime;
3907                 data->LastAccessTime = 0;
3908                 data->AllocationSize =
3909                         cpu_to_le64(le32_to_cpu(pSMBr->size));
3910                 data->EndOfFile = data->AllocationSize;
3911                 data->Attributes =
3912                         cpu_to_le32(le16_to_cpu(pSMBr->attr));
3913         } else
3914                 rc = -EIO; /* bad buffer passed in */
3915
3916         cifs_buf_release(pSMB);
3917
3918         if (rc == -EAGAIN)
3919                 goto QInfRetry;
3920
3921         return rc;
3922 }
3923
3924 int
3925 CIFSSMBQFileInfo(const unsigned int xid, struct cifs_tcon *tcon,
3926                  u16 netfid, FILE_ALL_INFO *pFindData)
3927 {
3928         struct smb_t2_qfi_req *pSMB = NULL;
3929         struct smb_t2_qfi_rsp *pSMBr = NULL;
3930         int rc = 0;
3931         int bytes_returned;
3932         __u16 params, byte_count;
3933
3934 QFileInfoRetry:
3935         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3936                       (void **) &pSMBr);
3937         if (rc)
3938                 return rc;
3939
3940         params = 2 /* level */ + 2 /* fid */;
3941         pSMB->t2.TotalDataCount = 0;
3942         pSMB->t2.MaxParameterCount = cpu_to_le16(4);
3943         /* BB find exact max data count below from sess structure BB */
3944         pSMB->t2.MaxDataCount = cpu_to_le16(CIFSMaxBufSize);
3945         pSMB->t2.MaxSetupCount = 0;
3946         pSMB->t2.Reserved = 0;
3947         pSMB->t2.Flags = 0;
3948         pSMB->t2.Timeout = 0;
3949         pSMB->t2.Reserved2 = 0;
3950         pSMB->t2.ParameterOffset = cpu_to_le16(offsetof(struct smb_t2_qfi_req,
3951                                                Fid) - 4);
3952         pSMB->t2.DataCount = 0;
3953         pSMB->t2.DataOffset = 0;
3954         pSMB->t2.SetupCount = 1;
3955         pSMB->t2.Reserved3 = 0;
3956         pSMB->t2.SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION);
3957         byte_count = params + 1 /* pad */ ;
3958         pSMB->t2.TotalParameterCount = cpu_to_le16(params);
3959         pSMB->t2.ParameterCount = pSMB->t2.TotalParameterCount;
3960         pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_ALL_INFO);
3961         pSMB->Pad = 0;
3962         pSMB->Fid = netfid;
3963         inc_rfc1001_len(pSMB, byte_count);
3964
3965         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3966                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3967         if (rc) {
3968                 cFYI(1, "Send error in QPathInfo = %d", rc);
3969         } else {                /* decode response */
3970                 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3971
3972                 if (rc) /* BB add auto retry on EOPNOTSUPP? */
3973                         rc = -EIO;
3974                 else if (get_bcc(&pSMBr->hdr) < 40)
3975                         rc = -EIO;      /* bad smb */
3976                 else if (pFindData) {
3977                         __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3978                         memcpy((char *) pFindData,
3979                                (char *) &pSMBr->hdr.Protocol +
3980                                data_offset, sizeof(FILE_ALL_INFO));
3981                 } else
3982                     rc = -ENOMEM;
3983         }
3984         cifs_buf_release(pSMB);
3985         if (rc == -EAGAIN)
3986                 goto QFileInfoRetry;
3987
3988         return rc;
3989 }
3990
3991 int
3992 CIFSSMBQPathInfo(const unsigned int xid, struct cifs_tcon *tcon,
3993                  const char *search_name, FILE_ALL_INFO *data,
3994                  int legacy /* old style infolevel */,
3995                  const struct nls_table *nls_codepage, int remap)
3996 {
3997         /* level 263 SMB_QUERY_FILE_ALL_INFO */
3998         TRANSACTION2_QPI_REQ *pSMB = NULL;
3999         TRANSACTION2_QPI_RSP *pSMBr = NULL;
4000         int rc = 0;
4001         int bytes_returned;
4002         int name_len;
4003         __u16 params, byte_count;
4004
4005         /* cFYI(1, "In QPathInfo path %s", search_name); */
4006 QPathInfoRetry:
4007         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4008                       (void **) &pSMBr);
4009         if (rc)
4010                 return rc;
4011
4012         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4013                 name_len =
4014                     cifsConvertToUTF16((__le16 *) pSMB->FileName, search_name,
4015                                        PATH_MAX, nls_codepage, remap);
4016                 name_len++;     /* trailing null */
4017                 name_len *= 2;
4018         } else {        /* BB improve the check for buffer overruns BB */
4019                 name_len = strnlen(search_name, PATH_MAX);
4020                 name_len++;     /* trailing null */
4021                 strncpy(pSMB->FileName, search_name, name_len);
4022         }
4023
4024         params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */;
4025         pSMB->TotalDataCount = 0;
4026         pSMB->MaxParameterCount = cpu_to_le16(2);
4027         /* BB find exact max SMB PDU from sess structure BB */
4028         pSMB->MaxDataCount = cpu_to_le16(4000);
4029         pSMB->MaxSetupCount = 0;
4030         pSMB->Reserved = 0;
4031         pSMB->Flags = 0;
4032         pSMB->Timeout = 0;
4033         pSMB->Reserved2 = 0;
4034         pSMB->ParameterOffset = cpu_to_le16(offsetof(
4035         struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
4036         pSMB->DataCount = 0;
4037         pSMB->DataOffset = 0;
4038         pSMB->SetupCount = 1;
4039         pSMB->Reserved3 = 0;
4040         pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
4041         byte_count = params + 1 /* pad */ ;
4042         pSMB->TotalParameterCount = cpu_to_le16(params);
4043         pSMB->ParameterCount = pSMB->TotalParameterCount;
4044         if (legacy)
4045                 pSMB->InformationLevel = cpu_to_le16(SMB_INFO_STANDARD);
4046         else
4047                 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_ALL_INFO);
4048         pSMB->Reserved4 = 0;
4049         inc_rfc1001_len(pSMB, byte_count);
4050         pSMB->ByteCount = cpu_to_le16(byte_count);
4051
4052         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4053                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4054         if (rc) {
4055                 cFYI(1, "Send error in QPathInfo = %d", rc);
4056         } else {                /* decode response */
4057                 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4058
4059                 if (rc) /* BB add auto retry on EOPNOTSUPP? */
4060                         rc = -EIO;
4061                 else if (!legacy && get_bcc(&pSMBr->hdr) < 40)
4062                         rc = -EIO;      /* bad smb */
4063                 else if (legacy && get_bcc(&pSMBr->hdr) < 24)
4064                         rc = -EIO;  /* 24 or 26 expected but we do not read
4065                                         last field */
4066                 else if (data) {
4067                         int size;
4068                         __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4069
4070                         /*
4071                          * On legacy responses we do not read the last field,
4072                          * EAsize, fortunately since it varies by subdialect and
4073                          * also note it differs on Set vs Get, ie two bytes or 4
4074                          * bytes depending but we don't care here.
4075                          */
4076                         if (legacy)
4077                                 size = sizeof(FILE_INFO_STANDARD);
4078                         else
4079                                 size = sizeof(FILE_ALL_INFO);
4080                         memcpy((char *) data, (char *) &pSMBr->hdr.Protocol +
4081                                data_offset, size);
4082                 } else
4083                     rc = -ENOMEM;
4084         }
4085         cifs_buf_release(pSMB);
4086         if (rc == -EAGAIN)
4087                 goto QPathInfoRetry;
4088
4089         return rc;
4090 }
4091
4092 int
4093 CIFSSMBUnixQFileInfo(const unsigned int xid, struct cifs_tcon *tcon,
4094                  u16 netfid, FILE_UNIX_BASIC_INFO *pFindData)
4095 {
4096         struct smb_t2_qfi_req *pSMB = NULL;
4097         struct smb_t2_qfi_rsp *pSMBr = NULL;
4098         int rc = 0;
4099         int bytes_returned;
4100         __u16 params, byte_count;
4101
4102 UnixQFileInfoRetry:
4103         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4104                       (void **) &pSMBr);
4105         if (rc)
4106                 return rc;
4107
4108         params = 2 /* level */ + 2 /* fid */;
4109         pSMB->t2.TotalDataCount = 0;
4110         pSMB->t2.MaxParameterCount = cpu_to_le16(4);
4111         /* BB find exact max data count below from sess structure BB */
4112         pSMB->t2.MaxDataCount = cpu_to_le16(CIFSMaxBufSize);
4113         pSMB->t2.MaxSetupCount = 0;
4114         pSMB->t2.Reserved = 0;
4115         pSMB->t2.Flags = 0;
4116         pSMB->t2.Timeout = 0;
4117         pSMB->t2.Reserved2 = 0;
4118         pSMB->t2.ParameterOffset = cpu_to_le16(offsetof(struct smb_t2_qfi_req,
4119                                                Fid) - 4);
4120         pSMB->t2.DataCount = 0;
4121         pSMB->t2.DataOffset = 0;
4122         pSMB->t2.SetupCount = 1;
4123         pSMB->t2.Reserved3 = 0;
4124         pSMB->t2.SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION);
4125         byte_count = params + 1 /* pad */ ;
4126         pSMB->t2.TotalParameterCount = cpu_to_le16(params);
4127         pSMB->t2.ParameterCount = pSMB->t2.TotalParameterCount;
4128         pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC);
4129         pSMB->Pad = 0;
4130         pSMB->Fid = netfid;
4131         inc_rfc1001_len(pSMB, byte_count);
4132
4133         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4134                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4135         if (rc) {
4136                 cFYI(1, "Send error in QPathInfo = %d", rc);
4137         } else {                /* decode response */
4138                 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4139
4140                 if (rc || get_bcc(&pSMBr->hdr) < sizeof(FILE_UNIX_BASIC_INFO)) {
4141                         cERROR(1, "Malformed FILE_UNIX_BASIC_INFO response. "
4142                                    "Unix Extensions can be disabled on mount "
4143                                    "by specifying the nosfu mount option.");
4144                         rc = -EIO;      /* bad smb */
4145                 } else {
4146                         __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4147                         memcpy((char *) pFindData,
4148                                (char *) &pSMBr->hdr.Protocol +
4149                                data_offset,
4150                                sizeof(FILE_UNIX_BASIC_INFO));
4151                 }
4152         }
4153
4154         cifs_buf_release(pSMB);
4155         if (rc == -EAGAIN)
4156                 goto UnixQFileInfoRetry;
4157
4158         return rc;
4159 }
4160
4161 int
4162 CIFSSMBUnixQPathInfo(const unsigned int xid, struct cifs_tcon *tcon,
4163                      const unsigned char *searchName,
4164                      FILE_UNIX_BASIC_INFO *pFindData,
4165                      const struct nls_table *nls_codepage, int remap)
4166 {
4167 /* SMB_QUERY_FILE_UNIX_BASIC */
4168         TRANSACTION2_QPI_REQ *pSMB = NULL;
4169         TRANSACTION2_QPI_RSP *pSMBr = NULL;
4170         int rc = 0;
4171         int bytes_returned = 0;
4172         int name_len;
4173         __u16 params, byte_count;
4174
4175         cFYI(1, "In QPathInfo (Unix) the path %s", searchName);
4176 UnixQPathInfoRetry:
4177         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4178                       (void **) &pSMBr);
4179         if (rc)
4180                 return rc;
4181
4182         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4183                 name_len =
4184                     cifsConvertToUTF16((__le16 *) pSMB->FileName, searchName,
4185                                        PATH_MAX, nls_codepage, remap);
4186                 name_len++;     /* trailing null */
4187                 name_len *= 2;
4188         } else {        /* BB improve the check for buffer overruns BB */
4189                 name_len = strnlen(searchName, PATH_MAX);
4190                 name_len++;     /* trailing null */
4191                 strncpy(pSMB->FileName, searchName, name_len);
4192         }
4193
4194         params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */;
4195         pSMB->TotalDataCount = 0;
4196         pSMB->MaxParameterCount = cpu_to_le16(2);
4197         /* BB find exact max SMB PDU from sess structure BB */
4198         pSMB->MaxDataCount = cpu_to_le16(4000);
4199         pSMB->MaxSetupCount = 0;
4200         pSMB->Reserved = 0;
4201         pSMB->Flags = 0;
4202         pSMB->Timeout = 0;
4203         pSMB->Reserved2 = 0;
4204         pSMB->ParameterOffset = cpu_to_le16(offsetof(
4205         struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
4206         pSMB->DataCount = 0;
4207         pSMB->DataOffset = 0;
4208         pSMB->SetupCount = 1;
4209         pSMB->Reserved3 = 0;
4210         pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
4211         byte_count = params + 1 /* pad */ ;
4212         pSMB->TotalParameterCount = cpu_to_le16(params);
4213         pSMB->ParameterCount = pSMB->TotalParameterCount;
4214         pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC);
4215         pSMB->Reserved4 = 0;
4216         inc_rfc1001_len(pSMB, byte_count);
4217         pSMB->ByteCount = cpu_to_le16(byte_count);
4218
4219         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4220                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4221         if (rc) {
4222                 cFYI(1, "Send error in QPathInfo = %d", rc);
4223         } else {                /* decode response */
4224                 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4225
4226                 if (rc || get_bcc(&pSMBr->hdr) < sizeof(FILE_UNIX_BASIC_INFO)) {
4227                         cERROR(1, "Malformed FILE_UNIX_BASIC_INFO response. "
4228                                    "Unix Extensions can be disabled on mount "
4229                                    "by specifying the nosfu mount option.");
4230                         rc = -EIO;      /* bad smb */
4231                 } else {
4232                         __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4233                         memcpy((char *) pFindData,
4234                                (char *) &pSMBr->hdr.Protocol +
4235                                data_offset,
4236                                sizeof(FILE_UNIX_BASIC_INFO));
4237                 }
4238         }
4239         cifs_buf_release(pSMB);
4240         if (rc == -EAGAIN)
4241                 goto UnixQPathInfoRetry;
4242
4243         return rc;
4244 }
4245
4246 /* xid, tcon, searchName and codepage are input parms, rest are returned */
4247 int
4248 CIFSFindFirst(const unsigned int xid, struct cifs_tcon *tcon,
4249               const char *searchName,
4250               const struct nls_table *nls_codepage,
4251               __u16 *pnetfid, __u16 search_flags,
4252               struct cifs_search_info *psrch_inf, int remap, const char dirsep)
4253 {
4254 /* level 257 SMB_ */
4255         TRANSACTION2_FFIRST_REQ *pSMB = NULL;
4256         TRANSACTION2_FFIRST_RSP *pSMBr = NULL;
4257         T2_FFIRST_RSP_PARMS *parms;
4258         int rc = 0;
4259         int bytes_returned = 0;
4260         int name_len;
4261         __u16 params, byte_count;
4262
4263         cFYI(1, "In FindFirst for %s", searchName);
4264
4265 findFirstRetry:
4266         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4267                       (void **) &pSMBr);
4268         if (rc)
4269                 return rc;
4270
4271         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4272                 name_len =
4273                     cifsConvertToUTF16((__le16 *) pSMB->FileName, searchName,
4274                                        PATH_MAX, nls_codepage, remap);
4275                 /* We can not add the asterik earlier in case
4276                 it got remapped to 0xF03A as if it were part of the
4277                 directory name instead of a wildcard */
4278                 name_len *= 2;
4279                 pSMB->FileName[name_len] = dirsep;
4280                 pSMB->FileName[name_len+1] = 0;
4281                 pSMB->FileName[name_len+2] = '*';
4282                 pSMB->FileName[name_len+3] = 0;
4283                 name_len += 4; /* now the trailing null */
4284                 pSMB->FileName[name_len] = 0; /* null terminate just in case */
4285                 pSMB->FileName[name_len+1] = 0;
4286                 name_len += 2;
4287         } else {        /* BB add check for overrun of SMB buf BB */
4288                 name_len = strnlen(searchName, PATH_MAX);
4289 /* BB fix here and in unicode clause above ie
4290                 if (name_len > buffersize-header)
4291                         free buffer exit; BB */
4292                 strncpy(pSMB->FileName, searchName, name_len);
4293                 pSMB->FileName[name_len] = dirsep;
4294                 pSMB->FileName[name_len+1] = '*';
4295                 pSMB->FileName[name_len+2] = 0;
4296                 name_len += 3;
4297         }
4298
4299         params = 12 + name_len /* includes null */ ;
4300         pSMB->TotalDataCount = 0;       /* no EAs */
4301         pSMB->MaxParameterCount = cpu_to_le16(10);
4302         pSMB->MaxDataCount = cpu_to_le16(CIFSMaxBufSize & 0xFFFFFF00);
4303         pSMB->MaxSetupCount = 0;
4304         pSMB->Reserved = 0;
4305         pSMB->Flags = 0;
4306         pSMB->Timeout = 0;
4307         pSMB->Reserved2 = 0;
4308         byte_count = params + 1 /* pad */ ;
4309         pSMB->TotalParameterCount = cpu_to_le16(params);
4310         pSMB->ParameterCount = pSMB->TotalParameterCount;
4311         pSMB->ParameterOffset = cpu_to_le16(
4312               offsetof(struct smb_com_transaction2_ffirst_req, SearchAttributes)
4313                 - 4);
4314         pSMB->DataCount = 0;
4315         pSMB->DataOffset = 0;
4316         pSMB->SetupCount = 1;   /* one byte, no need to make endian neutral */
4317         pSMB->Reserved3 = 0;
4318         pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_FIRST);
4319         pSMB->SearchAttributes =
4320             cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
4321                         ATTR_DIRECTORY);
4322         pSMB->SearchCount = cpu_to_le16(CIFSMaxBufSize/sizeof(FILE_UNIX_INFO));
4323         pSMB->SearchFlags = cpu_to_le16(search_flags);
4324         pSMB->InformationLevel = cpu_to_le16(psrch_inf->info_level);
4325
4326         /* BB what should we set StorageType to? Does it matter? BB */
4327         pSMB->SearchStorageType = 0;
4328         inc_rfc1001_len(pSMB, byte_count);
4329         pSMB->ByteCount = cpu_to_le16(byte_count);
4330
4331         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4332                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4333         cifs_stats_inc(&tcon->stats.cifs_stats.num_ffirst);
4334
4335         if (rc) {/* BB add logic to retry regular search if Unix search
4336                         rejected unexpectedly by server */
4337                 /* BB Add code to handle unsupported level rc */
4338                 cFYI(1, "Error in FindFirst = %d", rc);
4339
4340                 cifs_buf_release(pSMB);
4341
4342                 /* BB eventually could optimize out free and realloc of buf */
4343                 /*    for this case */
4344                 if (rc == -EAGAIN)
4345                         goto findFirstRetry;
4346         } else { /* decode response */
4347                 /* BB remember to free buffer if error BB */
4348                 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4349                 if (rc == 0) {
4350                         unsigned int lnoff;
4351
4352                         if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
4353                                 psrch_inf->unicode = true;
4354                         else
4355                                 psrch_inf->unicode = false;
4356
4357                         psrch_inf->ntwrk_buf_start = (char *)pSMBr;
4358                         psrch_inf->smallBuf = 0;
4359                         psrch_inf->srch_entries_start =
4360                                 (char *) &pSMBr->hdr.Protocol +
4361                                         le16_to_cpu(pSMBr->t2.DataOffset);
4362                         parms = (T2_FFIRST_RSP_PARMS *)((char *) &pSMBr->hdr.Protocol +
4363                                le16_to_cpu(pSMBr->t2.ParameterOffset));
4364
4365                         if (parms->EndofSearch)
4366                                 psrch_inf->endOfSearch = true;
4367                         else
4368                                 psrch_inf->endOfSearch = false;
4369
4370                         psrch_inf->entries_in_buffer =
4371                                         le16_to_cpu(parms->SearchCount);
4372                         psrch_inf->index_of_last_entry = 2 /* skip . and .. */ +
4373                                 psrch_inf->entries_in_buffer;
4374                         lnoff = le16_to_cpu(parms->LastNameOffset);
4375                         if (CIFSMaxBufSize < lnoff) {
4376                                 cERROR(1, "ignoring corrupt resume name");
4377                                 psrch_inf->last_entry = NULL;
4378                                 return rc;
4379                         }
4380
4381                         psrch_inf->last_entry = psrch_inf->srch_entries_start +
4382                                                         lnoff;
4383
4384                         *pnetfid = parms->SearchHandle;
4385                 } else {
4386                         cifs_buf_release(pSMB);
4387                 }
4388         }
4389
4390         return rc;
4391 }
4392
4393 int CIFSFindNext(const unsigned int xid, struct cifs_tcon *tcon,
4394                  __u16 searchHandle, __u16 search_flags,
4395                  struct cifs_search_info *psrch_inf)
4396 {
4397         TRANSACTION2_FNEXT_REQ *pSMB = NULL;
4398         TRANSACTION2_FNEXT_RSP *pSMBr = NULL;
4399         T2_FNEXT_RSP_PARMS *parms;
4400         char *response_data;
4401         int rc = 0;
4402         int bytes_returned;
4403         unsigned int name_len;
4404         __u16 params, byte_count;
4405
4406         cFYI(1, "In FindNext");
4407
4408         if (psrch_inf->endOfSearch)
4409                 return -ENOENT;
4410
4411         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4412                 (void **) &pSMBr);
4413         if (rc)
4414                 return rc;
4415
4416         params = 14; /* includes 2 bytes of null string, converted to LE below*/
4417         byte_count = 0;
4418         pSMB->TotalDataCount = 0;       /* no EAs */
4419         pSMB->MaxParameterCount = cpu_to_le16(8);
4420         pSMB->MaxDataCount = cpu_to_le16(CIFSMaxBufSize & 0xFFFFFF00);
4421         pSMB->MaxSetupCount = 0;
4422         pSMB->Reserved = 0;
4423         pSMB->Flags = 0;
4424         pSMB->Timeout = 0;
4425         pSMB->Reserved2 = 0;
4426         pSMB->ParameterOffset =  cpu_to_le16(
4427               offsetof(struct smb_com_transaction2_fnext_req,SearchHandle) - 4);
4428         pSMB->DataCount = 0;
4429         pSMB->DataOffset = 0;
4430         pSMB->SetupCount = 1;
4431         pSMB->Reserved3 = 0;
4432         pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_NEXT);
4433         pSMB->SearchHandle = searchHandle;      /* always kept as le */
4434         pSMB->SearchCount =
4435                 cpu_to_le16(CIFSMaxBufSize / sizeof(FILE_UNIX_INFO));
4436         pSMB->InformationLevel = cpu_to_le16(psrch_inf->info_level);
4437         pSMB->ResumeKey = psrch_inf->resume_key;
4438         pSMB->SearchFlags = cpu_to_le16(search_flags);
4439
4440         name_len = psrch_inf->resume_name_len;
4441         params += name_len;
4442         if (name_len < PATH_MAX) {
4443                 memcpy(pSMB->ResumeFileName, psrch_inf->presume_name, name_len);
4444                 byte_count += name_len;
4445                 /* 14 byte parm len above enough for 2 byte null terminator */
4446                 pSMB->ResumeFileName[name_len] = 0;
4447                 pSMB->ResumeFileName[name_len+1] = 0;
4448         } else {
4449                 rc = -EINVAL;
4450                 goto FNext2_err_exit;
4451         }
4452         byte_count = params + 1 /* pad */ ;
4453         pSMB->TotalParameterCount = cpu_to_le16(params);
4454         pSMB->ParameterCount = pSMB->TotalParameterCount;
4455         inc_rfc1001_len(pSMB, byte_count);
4456         pSMB->ByteCount = cpu_to_le16(byte_count);
4457
4458         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4459                         (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4460         cifs_stats_inc(&tcon->stats.cifs_stats.num_fnext);
4461         if (rc) {
4462                 if (rc == -EBADF) {
4463                         psrch_inf->endOfSearch = true;
4464                         cifs_buf_release(pSMB);
4465                         rc = 0; /* search probably was closed at end of search*/
4466                 } else
4467                         cFYI(1, "FindNext returned = %d", rc);
4468         } else {                /* decode response */
4469                 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4470
4471                 if (rc == 0) {
4472                         unsigned int lnoff;
4473
4474                         /* BB fixme add lock for file (srch_info) struct here */
4475                         if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
4476                                 psrch_inf->unicode = true;
4477                         else
4478                                 psrch_inf->unicode = false;
4479                         response_data = (char *) &pSMBr->hdr.Protocol +
4480                                le16_to_cpu(pSMBr->t2.ParameterOffset);
4481                         parms = (T2_FNEXT_RSP_PARMS *)response_data;
4482                         response_data = (char *)&pSMBr->hdr.Protocol +
4483                                 le16_to_cpu(pSMBr->t2.DataOffset);
4484                         if (psrch_inf->smallBuf)
4485                                 cifs_small_buf_release(
4486                                         psrch_inf->ntwrk_buf_start);
4487                         else
4488                                 cifs_buf_release(psrch_inf->ntwrk_buf_start);
4489                         psrch_inf->srch_entries_start = response_data;
4490                         psrch_inf->ntwrk_buf_start = (char *)pSMB;
4491                         psrch_inf->smallBuf = 0;
4492                         if (parms->EndofSearch)
4493                                 psrch_inf->endOfSearch = true;
4494                         else
4495                                 psrch_inf->endOfSearch = false;
4496                         psrch_inf->entries_in_buffer =
4497                                                 le16_to_cpu(parms->SearchCount);
4498                         psrch_inf->index_of_last_entry +=
4499                                 psrch_inf->entries_in_buffer;
4500                         lnoff = le16_to_cpu(parms->LastNameOffset);
4501                         if (CIFSMaxBufSize < lnoff) {
4502                                 cERROR(1, "ignoring corrupt resume name");
4503                                 psrch_inf->last_entry = NULL;
4504                                 return rc;
4505                         } else
4506                                 psrch_inf->last_entry =
4507                                         psrch_inf->srch_entries_start + lnoff;
4508
4509 /*  cFYI(1, "fnxt2 entries in buf %d index_of_last %d",
4510             psrch_inf->entries_in_buffer, psrch_inf->index_of_last_entry); */
4511
4512                         /* BB fixme add unlock here */
4513                 }
4514
4515         }
4516
4517         /* BB On error, should we leave previous search buf (and count and
4518         last entry fields) intact or free the previous one? */
4519
4520         /* Note: On -EAGAIN error only caller can retry on handle based calls
4521         since file handle passed in no longer valid */
4522 FNext2_err_exit:
4523         if (rc != 0)
4524                 cifs_buf_release(pSMB);
4525         return rc;
4526 }
4527
4528 int
4529 CIFSFindClose(const unsigned int xid, struct cifs_tcon *tcon,
4530               const __u16 searchHandle)
4531 {
4532         int rc = 0;
4533         FINDCLOSE_REQ *pSMB = NULL;
4534
4535         cFYI(1, "In CIFSSMBFindClose");
4536         rc = small_smb_init(SMB_COM_FIND_CLOSE2, 1, tcon, (void **)&pSMB);
4537
4538         /* no sense returning error if session restarted
4539                 as file handle has been closed */
4540         if (rc == -EAGAIN)
4541                 return 0;
4542         if (rc)
4543                 return rc;
4544
4545         pSMB->FileID = searchHandle;
4546         pSMB->ByteCount = 0;
4547         rc = SendReceiveNoRsp(xid, tcon->ses, (char *) pSMB, 0);
4548         if (rc)
4549                 cERROR(1, "Send error in FindClose = %d", rc);
4550
4551         cifs_stats_inc(&tcon->stats.cifs_stats.num_fclose);
4552
4553         /* Since session is dead, search handle closed on server already */
4554         if (rc == -EAGAIN)
4555                 rc = 0;
4556
4557         return rc;
4558 }
4559
4560 int
4561 CIFSGetSrvInodeNumber(const unsigned int xid, struct cifs_tcon *tcon,
4562                       const char *search_name, __u64 *inode_number,
4563                       const struct nls_table *nls_codepage, int remap)
4564 {
4565         int rc = 0;
4566         TRANSACTION2_QPI_REQ *pSMB = NULL;
4567         TRANSACTION2_QPI_RSP *pSMBr = NULL;
4568         int name_len, bytes_returned;
4569         __u16 params, byte_count;
4570
4571         cFYI(1, "In GetSrvInodeNum for %s", search_name);
4572         if (tcon == NULL)
4573                 return -ENODEV;
4574
4575 GetInodeNumberRetry:
4576         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4577                       (void **) &pSMBr);
4578         if (rc)
4579                 return rc;
4580
4581         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4582                 name_len =
4583                         cifsConvertToUTF16((__le16 *) pSMB->FileName,
4584                                            search_name, PATH_MAX, nls_codepage,
4585                                            remap);
4586                 name_len++;     /* trailing null */
4587                 name_len *= 2;
4588         } else {        /* BB improve the check for buffer overruns BB */
4589                 name_len = strnlen(search_name, PATH_MAX);
4590                 name_len++;     /* trailing null */
4591                 strncpy(pSMB->FileName, search_name, name_len);
4592         }
4593
4594         params = 2 /* level */  + 4 /* rsrvd */  + name_len /* incl null */ ;
4595         pSMB->TotalDataCount = 0;
4596         pSMB->MaxParameterCount = cpu_to_le16(2);
4597         /* BB find exact max data count below from sess structure BB */
4598         pSMB->MaxDataCount = cpu_to_le16(4000);
4599         pSMB->MaxSetupCount = 0;
4600         pSMB->Reserved = 0;
4601         pSMB->Flags = 0;
4602         pSMB->Timeout = 0;
4603         pSMB->Reserved2 = 0;
4604         pSMB->ParameterOffset = cpu_to_le16(offsetof(
4605                 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
4606         pSMB->DataCount = 0;
4607         pSMB->DataOffset = 0;
4608         pSMB->SetupCount = 1;
4609         pSMB->Reserved3 = 0;
4610         pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
4611         byte_count = params + 1 /* pad */ ;
4612         pSMB->TotalParameterCount = cpu_to_le16(params);
4613         pSMB->ParameterCount = pSMB->TotalParameterCount;
4614         pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_INTERNAL_INFO);
4615         pSMB->Reserved4 = 0;
4616         inc_rfc1001_len(pSMB, byte_count);
4617         pSMB->ByteCount = cpu_to_le16(byte_count);
4618
4619         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4620                 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4621         if (rc) {
4622                 cFYI(1, "error %d in QueryInternalInfo", rc);
4623         } else {
4624                 /* decode response */
4625                 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4626                 /* BB also check enough total bytes returned */
4627                 if (rc || get_bcc(&pSMBr->hdr) < 2)
4628                         /* If rc should we check for EOPNOSUPP and
4629                         disable the srvino flag? or in caller? */
4630                         rc = -EIO;      /* bad smb */
4631                 else {
4632                         __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4633                         __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
4634                         struct file_internal_info *pfinfo;
4635                         /* BB Do we need a cast or hash here ? */
4636                         if (count < 8) {
4637                                 cFYI(1, "Illegal size ret in QryIntrnlInf");
4638                                 rc = -EIO;
4639                                 goto GetInodeNumOut;
4640                         }
4641                         pfinfo = (struct file_internal_info *)
4642                                 (data_offset + (char *) &pSMBr->hdr.Protocol);
4643                         *inode_number = le64_to_cpu(pfinfo->UniqueId);
4644                 }
4645         }
4646 GetInodeNumOut:
4647         cifs_buf_release(pSMB);
4648         if (rc == -EAGAIN)
4649                 goto GetInodeNumberRetry;
4650         return rc;
4651 }
4652
4653 /* parses DFS refferal V3 structure
4654  * caller is responsible for freeing target_nodes
4655  * returns:
4656  *      on success - 0
4657  *      on failure - errno
4658  */
4659 static int
4660 parse_DFS_referrals(TRANSACTION2_GET_DFS_REFER_RSP *pSMBr,
4661                 unsigned int *num_of_nodes,
4662                 struct dfs_info3_param **target_nodes,
4663                 const struct nls_table *nls_codepage, int remap,
4664                 const char *searchName)
4665 {
4666         int i, rc = 0;
4667         char *data_end;
4668         bool is_unicode;
4669         struct dfs_referral_level_3 *ref;
4670
4671         if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
4672                 is_unicode = true;
4673         else
4674                 is_unicode = false;
4675         *num_of_nodes = le16_to_cpu(pSMBr->NumberOfReferrals);
4676
4677         if (*num_of_nodes < 1) {
4678                 cERROR(1, "num_referrals: must be at least > 0,"
4679                         "but we get num_referrals = %d", *num_of_nodes);
4680                 rc = -EINVAL;
4681                 goto parse_DFS_referrals_exit;
4682         }
4683
4684         ref = (struct dfs_referral_level_3 *) &(pSMBr->referrals);
4685         if (ref->VersionNumber != cpu_to_le16(3)) {
4686                 cERROR(1, "Referrals of V%d version are not supported,"
4687                         "should be V3", le16_to_cpu(ref->VersionNumber));
4688                 rc = -EINVAL;
4689                 goto parse_DFS_referrals_exit;
4690         }
4691
4692         /* get the upper boundary of the resp buffer */
4693         data_end = (char *)(&(pSMBr->PathConsumed)) +
4694                                 le16_to_cpu(pSMBr->t2.DataCount);
4695
4696         cFYI(1, "num_referrals: %d dfs flags: 0x%x ...",
4697                         *num_of_nodes,
4698                         le32_to_cpu(pSMBr->DFSFlags));
4699
4700         *target_nodes = kzalloc(sizeof(struct dfs_info3_param) *
4701                         *num_of_nodes, GFP_KERNEL);
4702         if (*target_nodes == NULL) {
4703                 cERROR(1, "Failed to allocate buffer for target_nodes");
4704                 rc = -ENOMEM;
4705                 goto parse_DFS_referrals_exit;
4706         }
4707
4708         /* collect necessary data from referrals */
4709         for (i = 0; i < *num_of_nodes; i++) {
4710                 char *temp;
4711                 int max_len;
4712                 struct dfs_info3_param *node = (*target_nodes)+i;
4713
4714                 node->flags = le32_to_cpu(pSMBr->DFSFlags);
4715                 if (is_unicode) {
4716                         __le16 *tmp = kmalloc(strlen(searchName)*2 + 2,
4717                                                 GFP_KERNEL);
4718                         if (tmp == NULL) {
4719                                 rc = -ENOMEM;
4720                                 goto parse_DFS_referrals_exit;
4721                         }
4722                         cifsConvertToUTF16((__le16 *) tmp, searchName,
4723                                            PATH_MAX, nls_codepage, remap);
4724                         node->path_consumed = cifs_utf16_bytes(tmp,
4725                                         le16_to_cpu(pSMBr->PathConsumed),
4726                                         nls_codepage);
4727                         kfree(tmp);
4728                 } else
4729                         node->path_consumed = le16_to_cpu(pSMBr->PathConsumed);
4730
4731                 node->server_type = le16_to_cpu(ref->ServerType);
4732                 node->ref_flag = le16_to_cpu(ref->ReferralEntryFlags);
4733
4734                 /* copy DfsPath */
4735                 temp = (char *)ref + le16_to_cpu(ref->DfsPathOffset);
4736                 max_len = data_end - temp;
4737                 node->path_name = cifs_strndup_from_utf16(temp, max_len,
4738                                                 is_unicode, nls_codepage);
4739                 if (!node->path_name) {
4740                         rc = -ENOMEM;
4741                         goto parse_DFS_referrals_exit;
4742                 }
4743
4744                 /* copy link target UNC */
4745                 temp = (char *)ref + le16_to_cpu(ref->NetworkAddressOffset);
4746                 max_len = data_end - temp;
4747                 node->node_name = cifs_strndup_from_utf16(temp, max_len,
4748                                                 is_unicode, nls_codepage);
4749                 if (!node->node_name) {
4750                         rc = -ENOMEM;
4751                         goto parse_DFS_referrals_exit;
4752                 }
4753
4754                 ref++;
4755         }
4756
4757 parse_DFS_referrals_exit:
4758         if (rc) {
4759                 free_dfs_info_array(*target_nodes, *num_of_nodes);
4760                 *target_nodes = NULL;
4761                 *num_of_nodes = 0;
4762         }
4763         return rc;
4764 }
4765
4766 int
4767 CIFSGetDFSRefer(const unsigned int xid, struct cifs_ses *ses,
4768                 const char *search_name, struct dfs_info3_param **target_nodes,
4769                 unsigned int *num_of_nodes,
4770                 const struct nls_table *nls_codepage, int remap)
4771 {
4772 /* TRANS2_GET_DFS_REFERRAL */
4773         TRANSACTION2_GET_DFS_REFER_REQ *pSMB = NULL;
4774         TRANSACTION2_GET_DFS_REFER_RSP *pSMBr = NULL;
4775         int rc = 0;
4776         int bytes_returned;
4777         int name_len;
4778         __u16 params, byte_count;
4779         *num_of_nodes = 0;
4780         *target_nodes = NULL;
4781
4782         cFYI(1, "In GetDFSRefer the path %s", search_name);
4783         if (ses == NULL)
4784                 return -ENODEV;
4785 getDFSRetry:
4786         rc = smb_init(SMB_COM_TRANSACTION2, 15, NULL, (void **) &pSMB,
4787                       (void **) &pSMBr);
4788         if (rc)
4789                 return rc;
4790
4791         /* server pointer checked in called function,
4792         but should never be null here anyway */
4793         pSMB->hdr.Mid = get_next_mid(ses->server);
4794         pSMB->hdr.Tid = ses->ipc_tid;
4795         pSMB->hdr.Uid = ses->Suid;
4796         if (ses->capabilities & CAP_STATUS32)
4797                 pSMB->hdr.Flags2 |= SMBFLG2_ERR_STATUS;
4798         if (ses->capabilities & CAP_DFS)
4799                 pSMB->hdr.Flags2 |= SMBFLG2_DFS;
4800
4801         if (ses->capabilities & CAP_UNICODE) {
4802                 pSMB->hdr.Flags2 |= SMBFLG2_UNICODE;
4803                 name_len =
4804                     cifsConvertToUTF16((__le16 *) pSMB->RequestFileName,
4805                                        search_name, PATH_MAX, nls_codepage,
4806                                        remap);
4807                 name_len++;     /* trailing null */
4808                 name_len *= 2;
4809         } else {        /* BB improve the check for buffer overruns BB */
4810                 name_len = strnlen(search_name, PATH_MAX);
4811                 name_len++;     /* trailing null */
4812                 strncpy(pSMB->RequestFileName, search_name, name_len);
4813         }
4814
4815         if (ses->server) {
4816                 if (ses->server->sec_mode &
4817                    (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
4818                         pSMB->hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
4819         }
4820
4821         pSMB->hdr.Uid = ses->Suid;
4822
4823         params = 2 /* level */  + name_len /*includes null */ ;
4824         pSMB->TotalDataCount = 0;
4825         pSMB->DataCount = 0;
4826         pSMB->DataOffset = 0;
4827         pSMB->MaxParameterCount = 0;
4828         /* BB find exact max SMB PDU from sess structure BB */
4829         pSMB->MaxDataCount = cpu_to_le16(4000);
4830         pSMB->MaxSetupCount = 0;
4831         pSMB->Reserved = 0;
4832         pSMB->Flags = 0;
4833         pSMB->Timeout = 0;
4834         pSMB->Reserved2 = 0;
4835         pSMB->ParameterOffset = cpu_to_le16(offsetof(
4836           struct smb_com_transaction2_get_dfs_refer_req, MaxReferralLevel) - 4);
4837         pSMB->SetupCount = 1;
4838         pSMB->Reserved3 = 0;
4839         pSMB->SubCommand = cpu_to_le16(TRANS2_GET_DFS_REFERRAL);
4840         byte_count = params + 3 /* pad */ ;
4841         pSMB->ParameterCount = cpu_to_le16(params);
4842         pSMB->TotalParameterCount = pSMB->ParameterCount;
4843         pSMB->MaxReferralLevel = cpu_to_le16(3);
4844         inc_rfc1001_len(pSMB, byte_count);
4845         pSMB->ByteCount = cpu_to_le16(byte_count);
4846
4847         rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB,
4848                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4849         if (rc) {
4850                 cFYI(1, "Send error in GetDFSRefer = %d", rc);
4851                 goto GetDFSRefExit;
4852         }
4853         rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4854
4855         /* BB Also check if enough total bytes returned? */
4856         if (rc || get_bcc(&pSMBr->hdr) < 17) {
4857                 rc = -EIO;      /* bad smb */
4858                 goto GetDFSRefExit;
4859         }
4860
4861         cFYI(1, "Decoding GetDFSRefer response BCC: %d  Offset %d",
4862                                 get_bcc(&pSMBr->hdr),
4863                                 le16_to_cpu(pSMBr->t2.DataOffset));
4864
4865         /* parse returned result into more usable form */
4866         rc = parse_DFS_referrals(pSMBr, num_of_nodes,
4867                                  target_nodes, nls_codepage, remap,
4868                                  search_name);
4869
4870 GetDFSRefExit:
4871         cifs_buf_release(pSMB);
4872
4873         if (rc == -EAGAIN)
4874                 goto getDFSRetry;
4875
4876         return rc;
4877 }
4878
4879 /* Query File System Info such as free space to old servers such as Win 9x */
4880 int
4881 SMBOldQFSInfo(const unsigned int xid, struct cifs_tcon *tcon,
4882               struct kstatfs *FSData)
4883 {
4884 /* level 0x01 SMB_QUERY_FILE_SYSTEM_INFO */
4885         TRANSACTION2_QFSI_REQ *pSMB = NULL;
4886         TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4887         FILE_SYSTEM_ALLOC_INFO *response_data;
4888         int rc = 0;
4889         int bytes_returned = 0;
4890         __u16 params, byte_count;
4891
4892         cFYI(1, "OldQFSInfo");
4893 oldQFSInfoRetry:
4894         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4895                 (void **) &pSMBr);
4896         if (rc)
4897                 return rc;
4898
4899         params = 2;     /* level */
4900         pSMB->TotalDataCount = 0;
4901         pSMB->MaxParameterCount = cpu_to_le16(2);
4902         pSMB->MaxDataCount = cpu_to_le16(1000);
4903         pSMB->MaxSetupCount = 0;
4904         pSMB->Reserved = 0;
4905         pSMB->Flags = 0;
4906         pSMB->Timeout = 0;
4907         pSMB->Reserved2 = 0;
4908         byte_count = params + 1 /* pad */ ;
4909         pSMB->TotalParameterCount = cpu_to_le16(params);
4910         pSMB->ParameterCount = pSMB->TotalParameterCount;
4911         pSMB->ParameterOffset = cpu_to_le16(offsetof(
4912         struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4913         pSMB->DataCount = 0;
4914         pSMB->DataOffset = 0;
4915         pSMB->SetupCount = 1;
4916         pSMB->Reserved3 = 0;
4917         pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4918         pSMB->InformationLevel = cpu_to_le16(SMB_INFO_ALLOCATION);
4919         inc_rfc1001_len(pSMB, byte_count);
4920         pSMB->ByteCount = cpu_to_le16(byte_count);
4921
4922         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4923                 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4924         if (rc) {
4925                 cFYI(1, "Send error in QFSInfo = %d", rc);
4926         } else {                /* decode response */
4927                 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4928
4929                 if (rc || get_bcc(&pSMBr->hdr) < 18)
4930                         rc = -EIO;      /* bad smb */
4931                 else {
4932                         __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4933                         cFYI(1, "qfsinf resp BCC: %d  Offset %d",
4934                                  get_bcc(&pSMBr->hdr), data_offset);
4935
4936                         response_data = (FILE_SYSTEM_ALLOC_INFO *)
4937                                 (((char *) &pSMBr->hdr.Protocol) + data_offset);
4938                         FSData->f_bsize =
4939                                 le16_to_cpu(response_data->BytesPerSector) *
4940                                 le32_to_cpu(response_data->
4941                                         SectorsPerAllocationUnit);
4942                         FSData->f_blocks =
4943                                le32_to_cpu(response_data->TotalAllocationUnits);
4944                         FSData->f_bfree = FSData->f_bavail =
4945                                 le32_to_cpu(response_data->FreeAllocationUnits);
4946                         cFYI(1, "Blocks: %lld  Free: %lld Block size %ld",
4947                              (unsigned long long)FSData->f_blocks,
4948                              (unsigned long long)FSData->f_bfree,
4949                              FSData->f_bsize);
4950                 }
4951         }
4952         cifs_buf_release(pSMB);
4953
4954         if (rc == -EAGAIN)
4955                 goto oldQFSInfoRetry;
4956
4957         return rc;
4958 }
4959
4960 int
4961 CIFSSMBQFSInfo(const unsigned int xid, struct cifs_tcon *tcon,
4962                struct kstatfs *FSData)
4963 {
4964 /* level 0x103 SMB_QUERY_FILE_SYSTEM_INFO */
4965         TRANSACTION2_QFSI_REQ *pSMB = NULL;
4966         TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4967         FILE_SYSTEM_INFO *response_data;
4968         int rc = 0;
4969         int bytes_returned = 0;
4970         __u16 params, byte_count;
4971
4972         cFYI(1, "In QFSInfo");
4973 QFSInfoRetry:
4974         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4975                       (void **) &pSMBr);
4976         if (rc)
4977                 return rc;
4978
4979         params = 2;     /* level */
4980         pSMB->TotalDataCount = 0;
4981         pSMB->MaxParameterCount = cpu_to_le16(2);
4982         pSMB->MaxDataCount = cpu_to_le16(1000);
4983         pSMB->MaxSetupCount = 0;
4984         pSMB->Reserved = 0;
4985         pSMB->Flags = 0;
4986         pSMB->Timeout = 0;
4987         pSMB->Reserved2 = 0;
4988         byte_count = params + 1 /* pad */ ;
4989         pSMB->TotalParameterCount = cpu_to_le16(params);
4990         pSMB->ParameterCount = pSMB->TotalParameterCount;
4991         pSMB->ParameterOffset = cpu_to_le16(offsetof(
4992                 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4993         pSMB->DataCount = 0;
4994         pSMB->DataOffset = 0;
4995         pSMB->SetupCount = 1;
4996         pSMB->Reserved3 = 0;
4997         pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4998         pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_SIZE_INFO);
4999         inc_rfc1001_len(pSMB, byte_count);
5000         pSMB->ByteCount = cpu_to_le16(byte_count);
5001
5002         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5003                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5004         if (rc) {
5005                 cFYI(1, "Send error in QFSInfo = %d", rc);
5006         } else {                /* decode response */
5007                 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
5008
5009                 if (rc || get_bcc(&pSMBr->hdr) < 24)
5010                         rc = -EIO;      /* bad smb */
5011                 else {
5012                         __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
5013
5014                         response_data =
5015                             (FILE_SYSTEM_INFO
5016                              *) (((char *) &pSMBr->hdr.Protocol) +
5017                                  data_offset);
5018                         FSData->f_bsize =
5019                             le32_to_cpu(response_data->BytesPerSector) *
5020                             le32_to_cpu(response_data->
5021                                         SectorsPerAllocationUnit);
5022                         FSData->f_blocks =
5023                             le64_to_cpu(response_data->TotalAllocationUnits);
5024                         FSData->f_bfree = FSData->f_bavail =
5025                             le64_to_cpu(response_data->FreeAllocationUnits);
5026                         cFYI(1, "Blocks: %lld  Free: %lld Block size %ld",
5027                              (unsigned long long)FSData->f_blocks,
5028                              (unsigned long long)FSData->f_bfree,
5029                              FSData->f_bsize);
5030                 }
5031         }
5032         cifs_buf_release(pSMB);
5033
5034         if (rc == -EAGAIN)
5035                 goto QFSInfoRetry;
5036
5037         return rc;
5038 }
5039
5040 int
5041 CIFSSMBQFSAttributeInfo(const unsigned int xid, struct cifs_tcon *tcon)
5042 {
5043 /* level 0x105  SMB_QUERY_FILE_SYSTEM_INFO */
5044         TRANSACTION2_QFSI_REQ *pSMB = NULL;
5045         TRANSACTION2_QFSI_RSP *pSMBr = NULL;
5046         FILE_SYSTEM_ATTRIBUTE_INFO *response_data;
5047         int rc = 0;
5048         int bytes_returned = 0;
5049         __u16 params, byte_count;
5050
5051         cFYI(1, "In QFSAttributeInfo");
5052 QFSAttributeRetry:
5053         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5054                       (void **) &pSMBr);
5055         if (rc)
5056                 return rc;
5057
5058         params = 2;     /* level */
5059         pSMB->TotalDataCount = 0;
5060         pSMB->MaxParameterCount = cpu_to_le16(2);
5061         /* BB find exact max SMB PDU from sess structure BB */
5062         pSMB->MaxDataCount = cpu_to_le16(1000);
5063         pSMB->MaxSetupCount = 0;
5064         pSMB->Reserved = 0;
5065         pSMB->Flags = 0;
5066         pSMB->Timeout = 0;
5067         pSMB->Reserved2 = 0;
5068         byte_count = params + 1 /* pad */ ;
5069         pSMB->TotalParameterCount = cpu_to_le16(params);
5070         pSMB->ParameterCount = pSMB->TotalParameterCount;
5071         pSMB->ParameterOffset = cpu_to_le16(offsetof(
5072                 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
5073         pSMB->DataCount = 0;
5074         pSMB->DataOffset = 0;
5075         pSMB->SetupCount = 1;
5076         pSMB->Reserved3 = 0;
5077         pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
5078         pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_ATTRIBUTE_INFO);
5079         inc_rfc1001_len(pSMB, byte_count);
5080         pSMB->ByteCount = cpu_to_le16(byte_count);
5081
5082         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5083                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5084         if (rc) {
5085                 cERROR(1, "Send error in QFSAttributeInfo = %d", rc);
5086         } else {                /* decode response */
5087                 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
5088
5089                 if (rc || get_bcc(&pSMBr->hdr) < 13) {
5090                         /* BB also check if enough bytes returned */
5091                         rc = -EIO;      /* bad smb */
5092                 } else {
5093                         __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
5094                         response_data =
5095                             (FILE_SYSTEM_ATTRIBUTE_INFO
5096                              *) (((char *) &pSMBr->hdr.Protocol) +
5097                                  data_offset);
5098                         memcpy(&tcon->fsAttrInfo, response_data,
5099                                sizeof(FILE_SYSTEM_ATTRIBUTE_INFO));
5100                 }
5101         }
5102         cifs_buf_release(pSMB);
5103
5104         if (rc == -EAGAIN)
5105                 goto QFSAttributeRetry;
5106
5107         return rc;
5108 }
5109
5110 int
5111 CIFSSMBQFSDeviceInfo(const unsigned int xid, struct cifs_tcon *tcon)
5112 {
5113 /* level 0x104 SMB_QUERY_FILE_SYSTEM_INFO */
5114         TRANSACTION2_QFSI_REQ *pSMB = NULL;
5115         TRANSACTION2_QFSI_RSP *pSMBr = NULL;
5116         FILE_SYSTEM_DEVICE_INFO *response_data;
5117         int rc = 0;
5118         int bytes_returned = 0;
5119         __u16 params, byte_count;
5120
5121         cFYI(1, "In QFSDeviceInfo");
5122 QFSDeviceRetry:
5123         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5124                       (void **) &pSMBr);
5125         if (rc)
5126                 return rc;
5127
5128         params = 2;     /* level */
5129         pSMB->TotalDataCount = 0;
5130         pSMB->MaxParameterCount = cpu_to_le16(2);
5131         /* BB find exact max SMB PDU from sess structure BB */
5132         pSMB->MaxDataCount = cpu_to_le16(1000);
5133         pSMB->MaxSetupCount = 0;
5134         pSMB->Reserved = 0;
5135         pSMB->Flags = 0;
5136         pSMB->Timeout = 0;
5137         pSMB->Reserved2 = 0;
5138         byte_count = params + 1 /* pad */ ;
5139         pSMB->TotalParameterCount = cpu_to_le16(params);
5140         pSMB->ParameterCount = pSMB->TotalParameterCount;
5141         pSMB->ParameterOffset = cpu_to_le16(offsetof(
5142                 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
5143
5144         pSMB->DataCount = 0;
5145         pSMB->DataOffset = 0;
5146         pSMB->SetupCount = 1;
5147         pSMB->Reserved3 = 0;
5148         pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
5149         pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_DEVICE_INFO);
5150         inc_rfc1001_len(pSMB, byte_count);
5151         pSMB->ByteCount = cpu_to_le16(byte_count);
5152
5153         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5154                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5155         if (rc) {
5156                 cFYI(1, "Send error in QFSDeviceInfo = %d", rc);
5157         } else {                /* decode response */
5158                 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
5159
5160                 if (rc || get_bcc(&pSMBr->hdr) <
5161                           sizeof(FILE_SYSTEM_DEVICE_INFO))
5162                         rc = -EIO;      /* bad smb */
5163                 else {
5164                         __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
5165                         response_data =
5166                             (FILE_SYSTEM_DEVICE_INFO *)
5167                                 (((char *) &pSMBr->hdr.Protocol) +
5168                                  data_offset);
5169                         memcpy(&tcon->fsDevInfo, response_data,
5170                                sizeof(FILE_SYSTEM_DEVICE_INFO));
5171                 }
5172         }
5173         cifs_buf_release(pSMB);
5174
5175         if (rc == -EAGAIN)
5176                 goto QFSDeviceRetry;
5177
5178         return rc;
5179 }
5180
5181 int
5182 CIFSSMBQFSUnixInfo(const unsigned int xid, struct cifs_tcon *tcon)
5183 {
5184 /* level 0x200  SMB_QUERY_CIFS_UNIX_INFO */
5185         TRANSACTION2_QFSI_REQ *pSMB = NULL;
5186         TRANSACTION2_QFSI_RSP *pSMBr = NULL;
5187         FILE_SYSTEM_UNIX_INFO *response_data;
5188         int rc = 0;
5189         int bytes_returned = 0;
5190         __u16 params, byte_count;
5191
5192         cFYI(1, "In QFSUnixInfo");
5193 QFSUnixRetry:
5194         rc = smb_init_no_reconnect(SMB_COM_TRANSACTION2, 15, tcon,
5195                                    (void **) &pSMB, (void **) &pSMBr);
5196         if (rc)
5197                 return rc;
5198
5199         params = 2;     /* level */
5200         pSMB->TotalDataCount = 0;
5201         pSMB->DataCount = 0;
5202         pSMB->DataOffset = 0;
5203         pSMB->MaxParameterCount = cpu_to_le16(2);
5204         /* BB find exact max SMB PDU from sess structure BB */
5205         pSMB->MaxDataCount = cpu_to_le16(100);
5206         pSMB->MaxSetupCount = 0;
5207         pSMB->Reserved = 0;
5208         pSMB->Flags = 0;
5209         pSMB->Timeout = 0;
5210         pSMB->Reserved2 = 0;
5211         byte_count = params + 1 /* pad */ ;
5212         pSMB->ParameterCount = cpu_to_le16(params);
5213         pSMB->TotalParameterCount = pSMB->ParameterCount;
5214         pSMB->ParameterOffset = cpu_to_le16(offsetof(struct
5215                         smb_com_transaction2_qfsi_req, InformationLevel) - 4);
5216         pSMB->SetupCount = 1;
5217         pSMB->Reserved3 = 0;
5218         pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
5219         pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_CIFS_UNIX_INFO);
5220         inc_rfc1001_len(pSMB, byte_count);
5221         pSMB->ByteCount = cpu_to_le16(byte_count);
5222
5223         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5224                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5225         if (rc) {
5226                 cERROR(1, "Send error in QFSUnixInfo = %d", rc);
5227         } else {                /* decode response */
5228                 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
5229
5230                 if (rc || get_bcc(&pSMBr->hdr) < 13) {
5231                         rc = -EIO;      /* bad smb */
5232                 } else {
5233                         __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
5234                         response_data =
5235                             (FILE_SYSTEM_UNIX_INFO
5236                              *) (((char *) &pSMBr->hdr.Protocol) +
5237                                  data_offset);
5238                         memcpy(&tcon->fsUnixInfo, response_data,
5239                                sizeof(FILE_SYSTEM_UNIX_INFO));
5240                 }
5241         }
5242         cifs_buf_release(pSMB);
5243
5244         if (rc == -EAGAIN)
5245                 goto QFSUnixRetry;
5246
5247
5248         return rc;
5249 }
5250
5251 int
5252 CIFSSMBSetFSUnixInfo(const unsigned int xid, struct cifs_tcon *tcon, __u64 cap)
5253 {
5254 /* level 0x200  SMB_SET_CIFS_UNIX_INFO */
5255         TRANSACTION2_SETFSI_REQ *pSMB = NULL;
5256         TRANSACTION2_SETFSI_RSP *pSMBr = NULL;
5257         int rc = 0;
5258         int bytes_returned = 0;
5259         __u16 params, param_offset, offset, byte_count;
5260
5261         cFYI(1, "In SETFSUnixInfo");
5262 SETFSUnixRetry:
5263         /* BB switch to small buf init to save memory */
5264         rc = smb_init_no_reconnect(SMB_COM_TRANSACTION2, 15, tcon,
5265                                         (void **) &pSMB, (void **) &pSMBr);
5266         if (rc)
5267                 return rc;
5268
5269         params = 4;     /* 2 bytes zero followed by info level. */
5270         pSMB->MaxSetupCount = 0;
5271         pSMB->Reserved = 0;
5272         pSMB->Flags = 0;
5273         pSMB->Timeout = 0;
5274         pSMB->Reserved2 = 0;
5275         param_offset = offsetof(struct smb_com_transaction2_setfsi_req, FileNum)
5276                                 - 4;
5277         offset = param_offset + params;
5278
5279         pSMB->MaxParameterCount = cpu_to_le16(4);
5280         /* BB find exact max SMB PDU from sess structure BB */
5281         pSMB->MaxDataCount = cpu_to_le16(100);
5282         pSMB->SetupCount = 1;
5283         pSMB->Reserved3 = 0;
5284         pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FS_INFORMATION);
5285         byte_count = 1 /* pad */ + params + 12;
5286
5287         pSMB->DataCount = cpu_to_le16(12);
5288         pSMB->ParameterCount = cpu_to_le16(params);
5289         pSMB->TotalDataCount = pSMB->DataCount;
5290         pSMB->TotalParameterCount = pSMB->ParameterCount;
5291         pSMB->ParameterOffset = cpu_to_le16(param_offset);
5292         pSMB->DataOffset = cpu_to_le16(offset);
5293
5294         /* Params. */
5295         pSMB->FileNum = 0;
5296         pSMB->InformationLevel = cpu_to_le16(SMB_SET_CIFS_UNIX_INFO);
5297
5298         /* Data. */
5299         pSMB->ClientUnixMajor = cpu_to_le16(CIFS_UNIX_MAJOR_VERSION);
5300         pSMB->ClientUnixMinor = cpu_to_le16(CIFS_UNIX_MINOR_VERSION);
5301         pSMB->ClientUnixCap = cpu_to_le64(cap);
5302
5303         inc_rfc1001_len(pSMB, byte_count);
5304         pSMB->ByteCount = cpu_to_le16(byte_count);
5305
5306         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5307                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5308         if (rc) {
5309                 cERROR(1, "Send error in SETFSUnixInfo = %d", rc);
5310         } else {                /* decode response */
5311                 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
5312                 if (rc)
5313                         rc = -EIO;      /* bad smb */
5314         }
5315         cifs_buf_release(pSMB);
5316
5317         if (rc == -EAGAIN)
5318                 goto SETFSUnixRetry;
5319
5320         return rc;
5321 }
5322
5323
5324
5325 int
5326 CIFSSMBQFSPosixInfo(const unsigned int xid, struct cifs_tcon *tcon,
5327                    struct kstatfs *FSData)
5328 {
5329 /* level 0x201  SMB_QUERY_CIFS_POSIX_INFO */
5330         TRANSACTION2_QFSI_REQ *pSMB = NULL;
5331         TRANSACTION2_QFSI_RSP *pSMBr = NULL;
5332         FILE_SYSTEM_POSIX_INFO *response_data;
5333         int rc = 0;
5334         int bytes_returned = 0;
5335         __u16 params, byte_count;
5336
5337         cFYI(1, "In QFSPosixInfo");
5338 QFSPosixRetry:
5339         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5340                       (void **) &pSMBr);
5341         if (rc)
5342                 return rc;
5343
5344         params = 2;     /* level */
5345         pSMB->TotalDataCount = 0;
5346         pSMB->DataCount = 0;
5347         pSMB->DataOffset = 0;
5348         pSMB->MaxParameterCount = cpu_to_le16(2);
5349         /* BB find exact max SMB PDU from sess structure BB */
5350         pSMB->MaxDataCount = cpu_to_le16(100);
5351         pSMB->MaxSetupCount = 0;
5352         pSMB->Reserved = 0;
5353         pSMB->Flags = 0;
5354         pSMB->Timeout = 0;
5355         pSMB->Reserved2 = 0;
5356         byte_count = params + 1 /* pad */ ;
5357         pSMB->ParameterCount = cpu_to_le16(params);
5358         pSMB->TotalParameterCount = pSMB->ParameterCount;
5359         pSMB->ParameterOffset = cpu_to_le16(offsetof(struct
5360                         smb_com_transaction2_qfsi_req, InformationLevel) - 4);
5361         pSMB->SetupCount = 1;
5362         pSMB->Reserved3 = 0;
5363         pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
5364         pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_POSIX_FS_INFO);
5365         inc_rfc1001_len(pSMB, byte_count);
5366         pSMB->ByteCount = cpu_to_le16(byte_count);
5367
5368         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5369                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5370         if (rc) {
5371                 cFYI(1, "Send error in QFSUnixInfo = %d", rc);
5372         } else {                /* decode response */
5373                 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
5374
5375                 if (rc || get_bcc(&pSMBr->hdr) < 13) {
5376                         rc = -EIO;      /* bad smb */
5377                 } else {
5378                         __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
5379                         response_data =
5380                             (FILE_SYSTEM_POSIX_INFO
5381                              *) (((char *) &pSMBr->hdr.Protocol) +
5382                                  data_offset);
5383                         FSData->f_bsize =
5384                                         le32_to_cpu(response_data->BlockSize);
5385                         FSData->f_blocks =
5386                                         le64_to_cpu(response_data->TotalBlocks);
5387                         FSData->f_bfree =
5388                             le64_to_cpu(response_data->BlocksAvail);
5389                         if (response_data->UserBlocksAvail == cpu_to_le64(-1)) {
5390                                 FSData->f_bavail = FSData->f_bfree;
5391                         } else {
5392                                 FSData->f_bavail =
5393                                     le64_to_cpu(response_data->UserBlocksAvail);
5394                         }
5395                         if (response_data->TotalFileNodes != cpu_to_le64(-1))
5396                                 FSData->f_files =
5397                                      le64_to_cpu(response_data->TotalFileNodes);
5398                         if (response_data->FreeFileNodes != cpu_to_le64(-1))
5399                                 FSData->f_ffree =
5400                                       le64_to_cpu(response_data->FreeFileNodes);
5401                 }
5402         }
5403         cifs_buf_release(pSMB);
5404
5405         if (rc == -EAGAIN)
5406                 goto QFSPosixRetry;
5407
5408         return rc;
5409 }
5410
5411
5412 /* We can not use write of zero bytes trick to
5413    set file size due to need for large file support.  Also note that
5414    this SetPathInfo is preferred to SetFileInfo based method in next
5415    routine which is only needed to work around a sharing violation bug
5416    in Samba which this routine can run into */
5417
5418 int
5419 CIFSSMBSetEOF(const unsigned int xid, struct cifs_tcon *tcon,
5420               const char *fileName, __u64 size, bool SetAllocation,
5421               const struct nls_table *nls_codepage, int remap)
5422 {
5423         struct smb_com_transaction2_spi_req *pSMB = NULL;
5424         struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
5425         struct file_end_of_file_info *parm_data;
5426         int name_len;
5427         int rc = 0;
5428         int bytes_returned = 0;
5429         __u16 params, byte_count, data_count, param_offset, offset;
5430
5431         cFYI(1, "In SetEOF");
5432 SetEOFRetry:
5433         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5434                       (void **) &pSMBr);
5435         if (rc)
5436                 return rc;
5437
5438         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5439                 name_len =
5440                     cifsConvertToUTF16((__le16 *) pSMB->FileName, fileName,
5441                                        PATH_MAX, nls_codepage, remap);
5442                 name_len++;     /* trailing null */
5443                 name_len *= 2;
5444         } else {        /* BB improve the check for buffer overruns BB */
5445                 name_len = strnlen(fileName, PATH_MAX);
5446                 name_len++;     /* trailing null */
5447                 strncpy(pSMB->FileName, fileName, name_len);
5448         }
5449         params = 6 + name_len;
5450         data_count = sizeof(struct file_end_of_file_info);
5451         pSMB->MaxParameterCount = cpu_to_le16(2);
5452         pSMB->MaxDataCount = cpu_to_le16(4100);
5453         pSMB->MaxSetupCount = 0;
5454         pSMB->Reserved = 0;
5455         pSMB->Flags = 0;
5456         pSMB->Timeout = 0;
5457         pSMB->Reserved2 = 0;
5458         param_offset = offsetof(struct smb_com_transaction2_spi_req,
5459                                 InformationLevel) - 4;
5460         offset = param_offset + params;
5461         if (SetAllocation) {
5462                 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
5463                         pSMB->InformationLevel =
5464                                 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2);
5465                 else
5466                         pSMB->InformationLevel =
5467                                 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO);
5468         } else /* Set File Size */  {
5469             if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
5470                     pSMB->InformationLevel =
5471                                 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO2);
5472             else
5473                     pSMB->InformationLevel =
5474                                 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO);
5475         }
5476
5477         parm_data =
5478             (struct file_end_of_file_info *) (((char *) &pSMB->hdr.Protocol) +
5479                                        offset);
5480         pSMB->ParameterOffset = cpu_to_le16(param_offset);
5481         pSMB->DataOffset = cpu_to_le16(offset);
5482         pSMB->SetupCount = 1;
5483         pSMB->Reserved3 = 0;
5484         pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
5485         byte_count = 3 /* pad */  + params + data_count;
5486         pSMB->DataCount = cpu_to_le16(data_count);
5487         pSMB->TotalDataCount = pSMB->DataCount;
5488         pSMB->ParameterCount = cpu_to_le16(params);
5489         pSMB->TotalParameterCount = pSMB->ParameterCount;
5490         pSMB->Reserved4 = 0;
5491         inc_rfc1001_len(pSMB, byte_count);
5492         parm_data->FileSize = cpu_to_le64(size);
5493         pSMB->ByteCount = cpu_to_le16(byte_count);
5494         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5495                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5496         if (rc)
5497                 cFYI(1, "SetPathInfo (file size) returned %d", rc);
5498
5499         cifs_buf_release(pSMB);
5500
5501         if (rc == -EAGAIN)
5502                 goto SetEOFRetry;
5503
5504         return rc;
5505 }
5506
5507 int
5508 CIFSSMBSetFileSize(const unsigned int xid, struct cifs_tcon *tcon, __u64 size,
5509                    __u16 fid, __u32 pid_of_opener, bool SetAllocation)
5510 {
5511         struct smb_com_transaction2_sfi_req *pSMB  = NULL;
5512         struct file_end_of_file_info *parm_data;
5513         int rc = 0;
5514         __u16 params, param_offset, offset, byte_count, count;
5515
5516         cFYI(1, "SetFileSize (via SetFileInfo) %lld",
5517                         (long long)size);
5518         rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
5519
5520         if (rc)
5521                 return rc;
5522
5523         pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
5524         pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));
5525
5526         params = 6;
5527         pSMB->MaxSetupCount = 0;
5528         pSMB->Reserved = 0;
5529         pSMB->Flags = 0;
5530         pSMB->Timeout = 0;
5531         pSMB->Reserved2 = 0;
5532         param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
5533         offset = param_offset + params;
5534
5535         count = sizeof(struct file_end_of_file_info);
5536         pSMB->MaxParameterCount = cpu_to_le16(2);
5537         /* BB find exact max SMB PDU from sess structure BB */
5538         pSMB->MaxDataCount = cpu_to_le16(1000);
5539         pSMB->SetupCount = 1;
5540         pSMB->Reserved3 = 0;
5541         pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
5542         byte_count = 3 /* pad */  + params + count;
5543         pSMB->DataCount = cpu_to_le16(count);
5544         pSMB->ParameterCount = cpu_to_le16(params);
5545         pSMB->TotalDataCount = pSMB->DataCount;
5546         pSMB->TotalParameterCount = pSMB->ParameterCount;
5547         pSMB->ParameterOffset = cpu_to_le16(param_offset);
5548         parm_data =
5549                 (struct file_end_of_file_info *) (((char *) &pSMB->hdr.Protocol)
5550                                 + offset);
5551         pSMB->DataOffset = cpu_to_le16(offset);
5552         parm_data->FileSize = cpu_to_le64(size);
5553         pSMB->Fid = fid;
5554         if (SetAllocation) {
5555                 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
5556                         pSMB->InformationLevel =
5557                                 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2);
5558                 else
5559                         pSMB->InformationLevel =
5560                                 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO);
5561         } else /* Set File Size */  {
5562             if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
5563                     pSMB->InformationLevel =
5564                                 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO2);
5565             else
5566                     pSMB->InformationLevel =
5567                                 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO);
5568         }
5569         pSMB->Reserved4 = 0;
5570         inc_rfc1001_len(pSMB, byte_count);
5571         pSMB->ByteCount = cpu_to_le16(byte_count);
5572         rc = SendReceiveNoRsp(xid, tcon->ses, (char *) pSMB, 0);
5573         if (rc) {
5574                 cFYI(1, "Send error in SetFileInfo (SetFileSize) = %d", rc);
5575         }
5576
5577         /* Note: On -EAGAIN error only caller can retry on handle based calls
5578                 since file handle passed in no longer valid */
5579
5580         return rc;
5581 }
5582
5583 /* Some legacy servers such as NT4 require that the file times be set on
5584    an open handle, rather than by pathname - this is awkward due to
5585    potential access conflicts on the open, but it is unavoidable for these
5586    old servers since the only other choice is to go from 100 nanosecond DCE
5587    time and resort to the original setpathinfo level which takes the ancient
5588    DOS time format with 2 second granularity */
5589 int
5590 CIFSSMBSetFileInfo(const unsigned int xid, struct cifs_tcon *tcon,
5591                     const FILE_BASIC_INFO *data, __u16 fid, __u32 pid_of_opener)
5592 {
5593         struct smb_com_transaction2_sfi_req *pSMB  = NULL;
5594         char *data_offset;
5595         int rc = 0;
5596         __u16 params, param_offset, offset, byte_count, count;
5597
5598         cFYI(1, "Set Times (via SetFileInfo)");
5599         rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
5600
5601         if (rc)
5602                 return rc;
5603
5604         pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
5605         pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));
5606
5607         params = 6;
5608         pSMB->MaxSetupCount = 0;
5609         pSMB->Reserved = 0;
5610         pSMB->Flags = 0;
5611         pSMB->Timeout = 0;
5612         pSMB->Reserved2 = 0;
5613         param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
5614         offset = param_offset + params;
5615
5616         data_offset = (char *)pSMB +
5617                         offsetof(struct smb_hdr, Protocol) + offset;
5618
5619         count = sizeof(FILE_BASIC_INFO);
5620         pSMB->MaxParameterCount = cpu_to_le16(2);
5621         /* BB find max SMB PDU from sess */
5622         pSMB->MaxDataCount = cpu_to_le16(1000);
5623         pSMB->SetupCount = 1;
5624         pSMB->Reserved3 = 0;
5625         pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
5626         byte_count = 3 /* pad */  + params + count;
5627         pSMB->DataCount = cpu_to_le16(count);
5628         pSMB->ParameterCount = cpu_to_le16(params);
5629         pSMB->TotalDataCount = pSMB->DataCount;
5630         pSMB->TotalParameterCount = pSMB->ParameterCount;
5631         pSMB->ParameterOffset = cpu_to_le16(param_offset);
5632         pSMB->DataOffset = cpu_to_le16(offset);
5633         pSMB->Fid = fid;
5634         if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
5635                 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO2);
5636         else
5637                 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO);
5638         pSMB->Reserved4 = 0;
5639         inc_rfc1001_len(pSMB, byte_count);
5640         pSMB->ByteCount = cpu_to_le16(byte_count);
5641         memcpy(data_offset, data, sizeof(FILE_BASIC_INFO));
5642         rc = SendReceiveNoRsp(xid, tcon->ses, (char *) pSMB, 0);
5643         if (rc)
5644                 cFYI(1, "Send error in Set Time (SetFileInfo) = %d", rc);
5645
5646         /* Note: On -EAGAIN error only caller can retry on handle based calls
5647                 since file handle passed in no longer valid */
5648
5649         return rc;
5650 }
5651
5652 int
5653 CIFSSMBSetFileDisposition(const unsigned int xid, struct cifs_tcon *tcon,
5654                           bool delete_file, __u16 fid, __u32 pid_of_opener)
5655 {
5656         struct smb_com_transaction2_sfi_req *pSMB  = NULL;
5657         char *data_offset;
5658         int rc = 0;
5659         __u16 params, param_offset, offset, byte_count, count;
5660
5661         cFYI(1, "Set File Disposition (via SetFileInfo)");
5662         rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
5663
5664         if (rc)
5665                 return rc;
5666
5667         pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
5668         pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));
5669
5670         params = 6;
5671         pSMB->MaxSetupCount = 0;
5672         pSMB->Reserved = 0;
5673         pSMB->Flags = 0;
5674         pSMB->Timeout = 0;
5675         pSMB->Reserved2 = 0;
5676         param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
5677         offset = param_offset + params;
5678
5679         data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
5680
5681         count = 1;
5682         pSMB->MaxParameterCount = cpu_to_le16(2);
5683         /* BB find max SMB PDU from sess */
5684         pSMB->MaxDataCount = cpu_to_le16(1000);
5685         pSMB->SetupCount = 1;
5686         pSMB->Reserved3 = 0;
5687         pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
5688         byte_count = 3 /* pad */  + params + count;
5689         pSMB->DataCount = cpu_to_le16(count);
5690         pSMB->ParameterCount = cpu_to_le16(params);
5691         pSMB->TotalDataCount = pSMB->DataCount;
5692         pSMB->TotalParameterCount = pSMB->ParameterCount;
5693         pSMB->ParameterOffset = cpu_to_le16(param_offset);
5694         pSMB->DataOffset = cpu_to_le16(offset);
5695         pSMB->Fid = fid;
5696         pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_DISPOSITION_INFO);
5697         pSMB->Reserved4 = 0;
5698         inc_rfc1001_len(pSMB, byte_count);
5699         pSMB->ByteCount = cpu_to_le16(byte_count);
5700         *data_offset = delete_file ? 1 : 0;
5701         rc = SendReceiveNoRsp(xid, tcon->ses, (char *) pSMB, 0);
5702         if (rc)
5703                 cFYI(1, "Send error in SetFileDisposition = %d", rc);
5704
5705         return rc;
5706 }
5707
5708 int
5709 CIFSSMBSetPathInfo(const unsigned int xid, struct cifs_tcon *tcon,
5710                    const char *fileName, const FILE_BASIC_INFO *data,
5711                    const struct nls_table *nls_codepage, int remap)
5712 {
5713         TRANSACTION2_SPI_REQ *pSMB = NULL;
5714         TRANSACTION2_SPI_RSP *pSMBr = NULL;
5715         int name_len;
5716         int rc = 0;
5717         int bytes_returned = 0;
5718         char *data_offset;
5719         __u16 params, param_offset, offset, byte_count, count;
5720
5721         cFYI(1, "In SetTimes");
5722
5723 SetTimesRetry:
5724         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5725                       (void **) &pSMBr);
5726         if (rc)
5727                 return rc;
5728
5729         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5730                 name_len =
5731                     cifsConvertToUTF16((__le16 *) pSMB->FileName, fileName,
5732                                        PATH_MAX, nls_codepage, remap);
5733                 name_len++;     /* trailing null */
5734                 name_len *= 2;
5735         } else {        /* BB improve the check for buffer overruns BB */
5736                 name_len = strnlen(fileName, PATH_MAX);
5737                 name_len++;     /* trailing null */
5738                 strncpy(pSMB->FileName, fileName, name_len);
5739         }
5740
5741         params = 6 + name_len;
5742         count = sizeof(FILE_BASIC_INFO);
5743         pSMB->MaxParameterCount = cpu_to_le16(2);
5744         /* BB find max SMB PDU from sess structure BB */
5745         pSMB->MaxDataCount = cpu_to_le16(1000);
5746         pSMB->MaxSetupCount = 0;
5747         pSMB->Reserved = 0;
5748         pSMB->Flags = 0;
5749         pSMB->Timeout = 0;
5750         pSMB->Reserved2 = 0;
5751         param_offset = offsetof(struct smb_com_transaction2_spi_req,
5752                                 InformationLevel) - 4;
5753         offset = param_offset + params;
5754         data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
5755         pSMB->ParameterOffset = cpu_to_le16(param_offset);
5756         pSMB->DataOffset = cpu_to_le16(offset);
5757         pSMB->SetupCount = 1;
5758         pSMB->Reserved3 = 0;
5759         pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
5760         byte_count = 3 /* pad */  + params + count;
5761
5762         pSMB->DataCount = cpu_to_le16(count);
5763         pSMB->ParameterCount = cpu_to_le16(params);
5764         pSMB->TotalDataCount = pSMB->DataCount;
5765         pSMB->TotalParameterCount = pSMB->ParameterCount;
5766         if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
5767                 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO2);
5768         else
5769                 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO);
5770         pSMB->Reserved4 = 0;
5771         inc_rfc1001_len(pSMB, byte_count);
5772         memcpy(data_offset, data, sizeof(FILE_BASIC_INFO));
5773         pSMB->ByteCount = cpu_to_le16(byte_count);
5774         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5775                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5776         if (rc)
5777                 cFYI(1, "SetPathInfo (times) returned %d", rc);
5778
5779         cifs_buf_release(pSMB);
5780
5781         if (rc == -EAGAIN)
5782                 goto SetTimesRetry;
5783
5784         return rc;
5785 }
5786
5787 /* Can not be used to set time stamps yet (due to old DOS time format) */
5788 /* Can be used to set attributes */
5789 #if 0  /* Possibly not needed - since it turns out that strangely NT4 has a bug
5790           handling it anyway and NT4 was what we thought it would be needed for
5791           Do not delete it until we prove whether needed for Win9x though */
5792 int
5793 CIFSSMBSetAttrLegacy(unsigned int xid, struct cifs_tcon *tcon, char *fileName,
5794                 __u16 dos_attrs, const struct nls_table *nls_codepage)
5795 {
5796         SETATTR_REQ *pSMB = NULL;
5797         SETATTR_RSP *pSMBr = NULL;
5798         int rc = 0;
5799         int bytes_returned;
5800         int name_len;
5801
5802         cFYI(1, "In SetAttrLegacy");
5803
5804 SetAttrLgcyRetry:
5805         rc = smb_init(SMB_COM_SETATTR, 8, tcon, (void **) &pSMB,
5806                       (void **) &pSMBr);
5807         if (rc)
5808                 return rc;
5809
5810         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5811                 name_len =
5812                         ConvertToUTF16((__le16 *) pSMB->fileName, fileName,
5813                                        PATH_MAX, nls_codepage);
5814                 name_len++;     /* trailing null */
5815                 name_len *= 2;
5816         } else {        /* BB improve the check for buffer overruns BB */
5817                 name_len = strnlen(fileName, PATH_MAX);
5818                 name_len++;     /* trailing null */
5819                 strncpy(pSMB->fileName, fileName, name_len);
5820         }
5821         pSMB->attr = cpu_to_le16(dos_attrs);
5822         pSMB->BufferFormat = 0x04;
5823         inc_rfc1001_len(pSMB, name_len + 1);
5824         pSMB->ByteCount = cpu_to_le16(name_len + 1);
5825         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5826                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5827         if (rc)
5828                 cFYI(1, "Error in LegacySetAttr = %d", rc);
5829
5830         cifs_buf_release(pSMB);
5831
5832         if (rc == -EAGAIN)
5833                 goto SetAttrLgcyRetry;
5834
5835         return rc;
5836 }
5837 #endif /* temporarily unneeded SetAttr legacy function */
5838
5839 static void
5840 cifs_fill_unix_set_info(FILE_UNIX_BASIC_INFO *data_offset,
5841                         const struct cifs_unix_set_info_args *args)
5842 {
5843         u64 mode = args->mode;
5844
5845         /*
5846          * Samba server ignores set of file size to zero due to bugs in some
5847          * older clients, but we should be precise - we use SetFileSize to
5848          * set file size and do not want to truncate file size to zero
5849          * accidentally as happened on one Samba server beta by putting
5850          * zero instead of -1 here
5851          */
5852         data_offset->EndOfFile = cpu_to_le64(NO_CHANGE_64);
5853         data_offset->NumOfBytes = cpu_to_le64(NO_CHANGE_64);
5854         data_offset->LastStatusChange = cpu_to_le64(args->ctime);
5855         data_offset->LastAccessTime = cpu_to_le64(args->atime);
5856         data_offset->LastModificationTime = cpu_to_le64(args->mtime);
5857         data_offset->Uid = cpu_to_le64(args->uid);
5858         data_offset->Gid = cpu_to_le64(args->gid);
5859         /* better to leave device as zero when it is  */
5860         data_offset->DevMajor = cpu_to_le64(MAJOR(args->device));
5861         data_offset->DevMinor = cpu_to_le64(MINOR(args->device));
5862         data_offset->Permissions = cpu_to_le64(mode);
5863
5864         if (S_ISREG(mode))
5865                 data_offset->Type = cpu_to_le32(UNIX_FILE);
5866         else if (S_ISDIR(mode))
5867                 data_offset->Type = cpu_to_le32(UNIX_DIR);
5868         else if (S_ISLNK(mode))
5869                 data_offset->Type = cpu_to_le32(UNIX_SYMLINK);
5870         else if (S_ISCHR(mode))
5871                 data_offset->Type = cpu_to_le32(UNIX_CHARDEV);
5872         else if (S_ISBLK(mode))
5873                 data_offset->Type = cpu_to_le32(UNIX_BLOCKDEV);
5874         else if (S_ISFIFO(mode))
5875                 data_offset->Type = cpu_to_le32(UNIX_FIFO);
5876         else if (S_ISSOCK(mode))
5877                 data_offset->Type = cpu_to_le32(UNIX_SOCKET);
5878 }
5879
5880 int
5881 CIFSSMBUnixSetFileInfo(const unsigned int xid, struct cifs_tcon *tcon,
5882                        const struct cifs_unix_set_info_args *args,
5883                        u16 fid, u32 pid_of_opener)
5884 {
5885         struct smb_com_transaction2_sfi_req *pSMB  = NULL;
5886         char *data_offset;
5887         int rc = 0;
5888         u16 params, param_offset, offset, byte_count, count;
5889
5890         cFYI(1, "Set Unix Info (via SetFileInfo)");
5891         rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
5892
5893         if (rc)
5894                 return rc;
5895
5896         pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
5897         pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));
5898
5899         params = 6;
5900         pSMB->MaxSetupCount = 0;
5901         pSMB->Reserved = 0;
5902         pSMB->Flags = 0;
5903         pSMB->Timeout = 0;
5904         pSMB->Reserved2 = 0;
5905         param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
5906         offset = param_offset + params;
5907
5908         data_offset = (char *)pSMB +
5909                         offsetof(struct smb_hdr, Protocol) + offset;
5910
5911         count = sizeof(FILE_UNIX_BASIC_INFO);
5912
5913         pSMB->MaxParameterCount = cpu_to_le16(2);
5914         /* BB find max SMB PDU from sess */
5915         pSMB->MaxDataCount = cpu_to_le16(1000);
5916         pSMB->SetupCount = 1;
5917         pSMB->Reserved3 = 0;
5918         pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
5919         byte_count = 3 /* pad */  + params + count;
5920         pSMB->DataCount = cpu_to_le16(count);
5921         pSMB->ParameterCount = cpu_to_le16(params);
5922         pSMB->TotalDataCount = pSMB->DataCount;
5923         pSMB->TotalParameterCount = pSMB->ParameterCount;
5924         pSMB->ParameterOffset = cpu_to_le16(param_offset);
5925         pSMB->DataOffset = cpu_to_le16(offset);
5926         pSMB->Fid = fid;
5927         pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_BASIC);
5928         pSMB->Reserved4 = 0;
5929         inc_rfc1001_len(pSMB, byte_count);
5930         pSMB->ByteCount = cpu_to_le16(byte_count);
5931
5932         cifs_fill_unix_set_info((FILE_UNIX_BASIC_INFO *)data_offset, args);
5933
5934         rc = SendReceiveNoRsp(xid, tcon->ses, (char *) pSMB, 0);
5935         if (rc)
5936                 cFYI(1, "Send error in Set Time (SetFileInfo) = %d", rc);
5937
5938         /* Note: On -EAGAIN error only caller can retry on handle based calls
5939                 since file handle passed in no longer valid */
5940
5941         return rc;
5942 }
5943
5944 int
5945 CIFSSMBUnixSetPathInfo(const unsigned int xid, struct cifs_tcon *tcon,
5946                        char *fileName,
5947                        const struct cifs_unix_set_info_args *args,
5948                        const struct nls_table *nls_codepage, int remap)
5949 {
5950         TRANSACTION2_SPI_REQ *pSMB = NULL;
5951         TRANSACTION2_SPI_RSP *pSMBr = NULL;
5952         int name_len;
5953         int rc = 0;
5954         int bytes_returned = 0;
5955         FILE_UNIX_BASIC_INFO *data_offset;
5956         __u16 params, param_offset, offset, count, byte_count;
5957
5958         cFYI(1, "In SetUID/GID/Mode");
5959 setPermsRetry:
5960         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5961                       (void **) &pSMBr);
5962         if (rc)
5963                 return rc;
5964
5965         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5966                 name_len =
5967                     cifsConvertToUTF16((__le16 *) pSMB->FileName, fileName,
5968                                        PATH_MAX, nls_codepage, remap);
5969                 name_len++;     /* trailing null */
5970                 name_len *= 2;
5971         } else {        /* BB improve the check for buffer overruns BB */
5972                 name_len = strnlen(fileName, PATH_MAX);
5973                 name_len++;     /* trailing null */
5974                 strncpy(pSMB->FileName, fileName, name_len);
5975         }
5976
5977         params = 6 + name_len;
5978         count = sizeof(FILE_UNIX_BASIC_INFO);
5979         pSMB->MaxParameterCount = cpu_to_le16(2);
5980         /* BB find max SMB PDU from sess structure BB */
5981         pSMB->MaxDataCount = cpu_to_le16(1000);
5982         pSMB->MaxSetupCount = 0;
5983         pSMB->Reserved = 0;
5984         pSMB->Flags = 0;
5985         pSMB->Timeout = 0;
5986         pSMB->Reserved2 = 0;
5987         param_offset = offsetof(struct smb_com_transaction2_spi_req,
5988                                 InformationLevel) - 4;
5989         offset = param_offset + params;
5990         data_offset =
5991             (FILE_UNIX_BASIC_INFO *) ((char *) &pSMB->hdr.Protocol +
5992                                       offset);
5993         memset(data_offset, 0, count);
5994         pSMB->DataOffset = cpu_to_le16(offset);
5995         pSMB->ParameterOffset = cpu_to_le16(param_offset);
5996         pSMB->SetupCount = 1;
5997         pSMB->Reserved3 = 0;
5998         pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
5999         byte_count = 3 /* pad */  + params + count;
6000         pSMB->ParameterCount = cpu_to_le16(params);
6001         pSMB->DataCount = cpu_to_le16(count);
6002         pSMB->TotalParameterCount = pSMB->ParameterCount;
6003         pSMB->TotalDataCount = pSMB->DataCount;
6004         pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_BASIC);
6005         pSMB->Reserved4 = 0;
6006         inc_rfc1001_len(pSMB, byte_count);
6007
6008         cifs_fill_unix_set_info(data_offset, args);
6009
6010         pSMB->ByteCount = cpu_to_le16(byte_count);
6011         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
6012                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
6013         if (rc)
6014                 cFYI(1, "SetPathInfo (perms) returned %d", rc);
6015
6016         cifs_buf_release(pSMB);
6017         if (rc == -EAGAIN)
6018                 goto setPermsRetry;
6019         return rc;
6020 }
6021
6022 #ifdef CONFIG_CIFS_XATTR
6023 /*
6024  * Do a path-based QUERY_ALL_EAS call and parse the result. This is a common
6025  * function used by listxattr and getxattr type calls. When ea_name is set,
6026  * it looks for that attribute name and stuffs that value into the EAData
6027  * buffer. When ea_name is NULL, it stuffs a list of attribute names into the
6028  * buffer. In both cases, the return value is either the length of the
6029  * resulting data or a negative error code. If EAData is a NULL pointer then
6030  * the data isn't copied to it, but the length is returned.
6031  */
6032 ssize_t
6033 CIFSSMBQAllEAs(const unsigned int xid, struct cifs_tcon *tcon,
6034                 const unsigned char *searchName, const unsigned char *ea_name,
6035                 char *EAData, size_t buf_size,
6036                 const struct nls_table *nls_codepage, int remap)
6037 {
6038                 /* BB assumes one setup word */
6039         TRANSACTION2_QPI_REQ *pSMB = NULL;
6040         TRANSACTION2_QPI_RSP *pSMBr = NULL;
6041         int rc = 0;
6042         int bytes_returned;
6043         int list_len;
6044         struct fealist *ea_response_data;
6045         struct fea *temp_fea;
6046         char *temp_ptr;
6047         char *end_of_smb;
6048         __u16 params, byte_count, data_offset;
6049         unsigned int ea_name_len = ea_name ? strlen(ea_name) : 0;
6050
6051         cFYI(1, "In Query All EAs path %s", searchName);
6052 QAllEAsRetry:
6053         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
6054                       (void **) &pSMBr);
6055         if (rc)
6056                 return rc;
6057
6058         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
6059                 list_len =
6060                     cifsConvertToUTF16((__le16 *) pSMB->FileName, searchName,
6061                                        PATH_MAX, nls_codepage, remap);
6062                 list_len++;     /* trailing null */
6063                 list_len *= 2;
6064         } else {        /* BB improve the check for buffer overruns BB */
6065                 list_len = strnlen(searchName, PATH_MAX);
6066                 list_len++;     /* trailing null */
6067                 strncpy(pSMB->FileName, searchName, list_len);
6068         }
6069
6070         params = 2 /* level */ + 4 /* reserved */ + list_len /* includes NUL */;
6071         pSMB->TotalDataCount = 0;
6072         pSMB->MaxParameterCount = cpu_to_le16(2);
6073         /* BB find exact max SMB PDU from sess structure BB */
6074         pSMB->MaxDataCount = cpu_to_le16(CIFSMaxBufSize);
6075         pSMB->MaxSetupCount = 0;
6076         pSMB->Reserved = 0;
6077         pSMB->Flags = 0;
6078         pSMB->Timeout = 0;
6079         pSMB->Reserved2 = 0;
6080         pSMB->ParameterOffset = cpu_to_le16(offsetof(
6081         struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
6082         pSMB->DataCount = 0;
6083         pSMB->DataOffset = 0;
6084         pSMB->SetupCount = 1;
6085         pSMB->Reserved3 = 0;
6086         pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
6087         byte_count = params + 1 /* pad */ ;
6088         pSMB->TotalParameterCount = cpu_to_le16(params);
6089         pSMB->ParameterCount = pSMB->TotalParameterCount;
6090         pSMB->InformationLevel = cpu_to_le16(SMB_INFO_QUERY_ALL_EAS);
6091         pSMB->Reserved4 = 0;
6092         inc_rfc1001_len(pSMB, byte_count);
6093         pSMB->ByteCount = cpu_to_le16(byte_count);
6094
6095         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
6096                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
6097         if (rc) {
6098                 cFYI(1, "Send error in QueryAllEAs = %d", rc);
6099                 goto QAllEAsOut;
6100         }
6101
6102
6103         /* BB also check enough total bytes returned */
6104         /* BB we need to improve the validity checking
6105         of these trans2 responses */
6106
6107         rc = validate_t2((struct smb_t2_rsp *)pSMBr);
6108         if (rc || get_bcc(&pSMBr->hdr) < 4) {
6109                 rc = -EIO;      /* bad smb */
6110                 goto QAllEAsOut;
6111         }
6112
6113         /* check that length of list is not more than bcc */
6114         /* check that each entry does not go beyond length
6115            of list */
6116         /* check that each element of each entry does not
6117            go beyond end of list */
6118         /* validate_trans2_offsets() */
6119         /* BB check if start of smb + data_offset > &bcc+ bcc */
6120
6121         data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
6122         ea_response_data = (struct fealist *)
6123                                 (((char *) &pSMBr->hdr.Protocol) + data_offset);
6124
6125         list_len = le32_to_cpu(ea_response_data->list_len);
6126         cFYI(1, "ea length %d", list_len);
6127         if (list_len <= 8) {
6128                 cFYI(1, "empty EA list returned from server");
6129                 goto QAllEAsOut;
6130         }
6131
6132         /* make sure list_len doesn't go past end of SMB */
6133         end_of_smb = (char *)pByteArea(&pSMBr->hdr) + get_bcc(&pSMBr->hdr);
6134         if ((char *)ea_response_data + list_len > end_of_smb) {
6135                 cFYI(1, "EA list appears to go beyond SMB");
6136                 rc = -EIO;
6137                 goto QAllEAsOut;
6138         }
6139
6140         /* account for ea list len */
6141         list_len -= 4;
6142         temp_fea = ea_response_data->list;
6143         temp_ptr = (char *)temp_fea;
6144         while (list_len > 0) {
6145                 unsigned int name_len;
6146                 __u16 value_len;
6147
6148                 list_len -= 4;
6149                 temp_ptr += 4;
6150                 /* make sure we can read name_len and value_len */
6151                 if (list_len < 0) {
6152                         cFYI(1, "EA entry goes beyond length of list");
6153                         rc = -EIO;
6154                         goto QAllEAsOut;
6155                 }
6156
6157                 name_len = temp_fea->name_len;
6158                 value_len = le16_to_cpu(temp_fea->value_len);
6159                 list_len -= name_len + 1 + value_len;
6160                 if (list_len < 0) {
6161                         cFYI(1, "EA entry goes beyond length of list");
6162                         rc = -EIO;
6163                         goto QAllEAsOut;
6164                 }
6165
6166                 if (ea_name) {
6167                         if (ea_name_len == name_len &&
6168                             memcmp(ea_name, temp_ptr, name_len) == 0) {
6169                                 temp_ptr += name_len + 1;
6170                                 rc = value_len;
6171                                 if (buf_size == 0)
6172                                         goto QAllEAsOut;
6173                                 if ((size_t)value_len > buf_size) {
6174                                         rc = -ERANGE;
6175                                         goto QAllEAsOut;
6176                                 }
6177                                 memcpy(EAData, temp_ptr, value_len);
6178                                 goto QAllEAsOut;
6179                         }
6180                 } else {
6181                         /* account for prefix user. and trailing null */
6182                         rc += (5 + 1 + name_len);
6183                         if (rc < (int) buf_size) {
6184                                 memcpy(EAData, "user.", 5);
6185                                 EAData += 5;
6186                                 memcpy(EAData, temp_ptr, name_len);
6187                                 EAData += name_len;
6188                                 /* null terminate name */
6189                                 *EAData = 0;
6190                                 ++EAData;
6191                         } else if (buf_size == 0) {
6192                                 /* skip copy - calc size only */
6193                         } else {
6194                                 /* stop before overrun buffer */
6195                                 rc = -ERANGE;
6196                                 break;
6197                         }
6198                 }
6199                 temp_ptr += name_len + 1 + value_len;
6200                 temp_fea = (struct fea *)temp_ptr;
6201         }
6202
6203         /* didn't find the named attribute */
6204         if (ea_name)
6205                 rc = -ENODATA;
6206
6207 QAllEAsOut:
6208         cifs_buf_release(pSMB);
6209         if (rc == -EAGAIN)
6210                 goto QAllEAsRetry;
6211
6212         return (ssize_t)rc;
6213 }
6214
6215 int
6216 CIFSSMBSetEA(const unsigned int xid, struct cifs_tcon *tcon,
6217              const char *fileName, const char *ea_name, const void *ea_value,
6218              const __u16 ea_value_len, const struct nls_table *nls_codepage,
6219              int remap)
6220 {
6221         struct smb_com_transaction2_spi_req *pSMB = NULL;
6222         struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
6223         struct fealist *parm_data;
6224         int name_len;
6225         int rc = 0;
6226         int bytes_returned = 0;
6227         __u16 params, param_offset, byte_count, offset, count;
6228
6229         cFYI(1, "In SetEA");
6230 SetEARetry:
6231         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
6232                       (void **) &pSMBr);
6233         if (rc)
6234                 return rc;
6235
6236         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
6237                 name_len =
6238                     cifsConvertToUTF16((__le16 *) pSMB->FileName, fileName,
6239                                        PATH_MAX, nls_codepage, remap);
6240                 name_len++;     /* trailing null */
6241                 name_len *= 2;
6242         } else {        /* BB improve the check for buffer overruns BB */
6243                 name_len = strnlen(fileName, PATH_MAX);
6244                 name_len++;     /* trailing null */
6245                 strncpy(pSMB->FileName, fileName, name_len);
6246         }
6247
6248         params = 6 + name_len;
6249
6250         /* done calculating parms using name_len of file name,
6251         now use name_len to calculate length of ea name
6252         we are going to create in the inode xattrs */
6253         if (ea_name == NULL)
6254                 name_len = 0;
6255         else
6256                 name_len = strnlen(ea_name, 255);
6257
6258         count = sizeof(*parm_data) + ea_value_len + name_len;
6259         pSMB->MaxParameterCount = cpu_to_le16(2);
6260         /* BB find max SMB PDU from sess */
6261         pSMB->MaxDataCount = cpu_to_le16(1000);
6262         pSMB->MaxSetupCount = 0;
6263         pSMB->Reserved = 0;
6264         pSMB->Flags = 0;
6265         pSMB->Timeout = 0;
6266         pSMB->Reserved2 = 0;
6267         param_offset = offsetof(struct smb_com_transaction2_spi_req,
6268                                 InformationLevel) - 4;
6269         offset = param_offset + params;
6270         pSMB->InformationLevel =
6271                 cpu_to_le16(SMB_SET_FILE_EA);
6272
6273         parm_data =
6274                 (struct fealist *) (((char *) &pSMB->hdr.Protocol) +
6275                                        offset);
6276         pSMB->ParameterOffset = cpu_to_le16(param_offset);
6277         pSMB->DataOffset = cpu_to_le16(offset);
6278         pSMB->SetupCount = 1;
6279         pSMB->Reserved3 = 0;
6280         pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
6281         byte_count = 3 /* pad */  + params + count;
6282         pSMB->DataCount = cpu_to_le16(count);
6283         parm_data->list_len = cpu_to_le32(count);
6284         parm_data->list[0].EA_flags = 0;
6285         /* we checked above that name len is less than 255 */
6286         parm_data->list[0].name_len = (__u8)name_len;
6287         /* EA names are always ASCII */
6288         if (ea_name)
6289                 strncpy(parm_data->list[0].name, ea_name, name_len);
6290         parm_data->list[0].name[name_len] = 0;
6291         parm_data->list[0].value_len = cpu_to_le16(ea_value_len);
6292         /* caller ensures that ea_value_len is less than 64K but
6293         we need to ensure that it fits within the smb */
6294
6295         /*BB add length check to see if it would fit in
6296              negotiated SMB buffer size BB */
6297         /* if (ea_value_len > buffer_size - 512 (enough for header)) */
6298         if (ea_value_len)
6299                 memcpy(parm_data->list[0].name+name_len+1,
6300                        ea_value, ea_value_len);
6301
6302         pSMB->TotalDataCount = pSMB->DataCount;
6303         pSMB->ParameterCount = cpu_to_le16(params);
6304         pSMB->TotalParameterCount = pSMB->ParameterCount;
6305         pSMB->Reserved4 = 0;
6306         inc_rfc1001_len(pSMB, byte_count);
6307         pSMB->ByteCount = cpu_to_le16(byte_count);
6308         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
6309                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
6310         if (rc)
6311                 cFYI(1, "SetPathInfo (EA) returned %d", rc);
6312
6313         cifs_buf_release(pSMB);
6314
6315         if (rc == -EAGAIN)
6316                 goto SetEARetry;
6317
6318         return rc;
6319 }
6320 #endif
6321
6322 #ifdef CONFIG_CIFS_DNOTIFY_EXPERIMENTAL /* BB unused temporarily */
6323 /*
6324  *      Years ago the kernel added a "dnotify" function for Samba server,
6325  *      to allow network clients (such as Windows) to display updated
6326  *      lists of files in directory listings automatically when
6327  *      files are added by one user when another user has the
6328  *      same directory open on their desktop.  The Linux cifs kernel
6329  *      client hooked into the kernel side of this interface for
6330  *      the same reason, but ironically when the VFS moved from
6331  *      "dnotify" to "inotify" it became harder to plug in Linux
6332  *      network file system clients (the most obvious use case
6333  *      for notify interfaces is when multiple users can update
6334  *      the contents of the same directory - exactly what network
6335  *      file systems can do) although the server (Samba) could
6336  *      still use it.  For the short term we leave the worker
6337  *      function ifdeffed out (below) until inotify is fixed
6338  *      in the VFS to make it easier to plug in network file
6339  *      system clients.  If inotify turns out to be permanently
6340  *      incompatible for network fs clients, we could instead simply
6341  *      expose this config flag by adding a future cifs (and smb2) notify ioctl.
6342  */
6343 int CIFSSMBNotify(const unsigned int xid, struct cifs_tcon *tcon,
6344                   const int notify_subdirs, const __u16 netfid,
6345                   __u32 filter, struct file *pfile, int multishot,
6346                   const struct nls_table *nls_codepage)
6347 {
6348         int rc = 0;
6349         struct smb_com_transaction_change_notify_req *pSMB = NULL;
6350         struct smb_com_ntransaction_change_notify_rsp *pSMBr = NULL;
6351         struct dir_notify_req *dnotify_req;
6352         int bytes_returned;
6353
6354         cFYI(1, "In CIFSSMBNotify for file handle %d", (int)netfid);
6355         rc = smb_init(SMB_COM_NT_TRANSACT, 23, tcon, (void **) &pSMB,
6356                       (void **) &pSMBr);
6357         if (rc)
6358                 return rc;
6359
6360         pSMB->TotalParameterCount = 0 ;
6361         pSMB->TotalDataCount = 0;
6362         pSMB->MaxParameterCount = cpu_to_le32(2);
6363         pSMB->MaxDataCount = cpu_to_le32(CIFSMaxBufSize & 0xFFFFFF00);
6364         pSMB->MaxSetupCount = 4;
6365         pSMB->Reserved = 0;
6366         pSMB->ParameterOffset = 0;
6367         pSMB->DataCount = 0;
6368         pSMB->DataOffset = 0;
6369         pSMB->SetupCount = 4; /* single byte does not need le conversion */
6370         pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_NOTIFY_CHANGE);
6371         pSMB->ParameterCount = pSMB->TotalParameterCount;
6372         if (notify_subdirs)
6373                 pSMB->WatchTree = 1; /* one byte - no le conversion needed */
6374         pSMB->Reserved2 = 0;
6375         pSMB->CompletionFilter = cpu_to_le32(filter);
6376         pSMB->Fid = netfid; /* file handle always le */
6377         pSMB->ByteCount = 0;
6378
6379         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
6380                          (struct smb_hdr *)pSMBr, &bytes_returned,
6381                          CIFS_ASYNC_OP);
6382         if (rc) {
6383                 cFYI(1, "Error in Notify = %d", rc);
6384         } else {
6385                 /* Add file to outstanding requests */
6386                 /* BB change to kmem cache alloc */
6387                 dnotify_req = kmalloc(
6388                                                 sizeof(struct dir_notify_req),
6389                                                  GFP_KERNEL);
6390                 if (dnotify_req) {
6391                         dnotify_req->Pid = pSMB->hdr.Pid;
6392                         dnotify_req->PidHigh = pSMB->hdr.PidHigh;
6393                         dnotify_req->Mid = pSMB->hdr.Mid;
6394                         dnotify_req->Tid = pSMB->hdr.Tid;
6395                         dnotify_req->Uid = pSMB->hdr.Uid;
6396                         dnotify_req->netfid = netfid;
6397                         dnotify_req->pfile = pfile;
6398                         dnotify_req->filter = filter;
6399                         dnotify_req->multishot = multishot;
6400                         spin_lock(&GlobalMid_Lock);
6401                         list_add_tail(&dnotify_req->lhead,
6402                                         &GlobalDnotifyReqList);
6403                         spin_unlock(&GlobalMid_Lock);
6404                 } else
6405                         rc = -ENOMEM;
6406         }
6407         cifs_buf_release(pSMB);
6408         return rc;
6409 }
6410 #endif /* was needed for dnotify, and will be needed for inotify when VFS fix */