OSDN Git Service

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