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