s3:smbd: add support for SMB2 Keepalive (SMB2 Echo)
[ira/wip.git] / source3 / smbd / trans2.c
1 /*
2    Unix SMB/CIFS implementation.
3    SMB transaction2 handling
4    Copyright (C) Jeremy Allison                 1994-2007
5    Copyright (C) Stefan (metze) Metzmacher      2003
6    Copyright (C) Volker Lendecke                2005-2007
7    Copyright (C) Steve French                   2005
8    Copyright (C) James Peach                    2006-2007
9
10    Extensively modified by Andrew Tridgell, 1995
11
12    This program is free software; you can redistribute it and/or modify
13    it under the terms of the GNU General Public License as published by
14    the Free Software Foundation; either version 3 of the License, or
15    (at your option) any later version.
16
17    This program is distributed in the hope that it will be useful,
18    but WITHOUT ANY WARRANTY; without even the implied warranty of
19    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20    GNU General Public License for more details.
21
22    You should have received a copy of the GNU General Public License
23    along with this program.  If not, see <http://www.gnu.org/licenses/>.
24 */
25
26 #include "includes.h"
27 #include "version.h"
28 #include "smbd/globals.h"
29 #include "../libcli/auth/libcli_auth.h"
30
31 extern enum protocol_types Protocol;
32
33 #define DIR_ENTRY_SAFETY_MARGIN 4096
34
35 static char *store_file_unix_basic(connection_struct *conn,
36                                 char *pdata,
37                                 files_struct *fsp,
38                                 const SMB_STRUCT_STAT *psbuf);
39
40 static char *store_file_unix_basic_info2(connection_struct *conn,
41                                 char *pdata,
42                                 files_struct *fsp,
43                                 const SMB_STRUCT_STAT *psbuf);
44
45 /********************************************************************
46  Roundup a value to the nearest allocation roundup size boundary.
47  Only do this for Windows clients.
48 ********************************************************************/
49
50 uint64_t smb_roundup(connection_struct *conn, uint64_t val)
51 {
52         uint64_t rval = lp_allocation_roundup_size(SNUM(conn));
53
54         /* Only roundup for Windows clients. */
55         enum remote_arch_types ra_type = get_remote_arch();
56         if (rval && (ra_type != RA_SAMBA) && (ra_type != RA_CIFSFS)) {
57                 val = SMB_ROUNDUP(val,rval);
58         }
59         return val;
60 }
61
62 /****************************************************************************
63  Utility functions for dealing with extended attributes.
64 ****************************************************************************/
65
66 /****************************************************************************
67  Refuse to allow clients to overwrite our private xattrs.
68 ****************************************************************************/
69
70 static bool samba_private_attr_name(const char *unix_ea_name)
71 {
72         static const char * const prohibited_ea_names[] = {
73                 SAMBA_POSIX_INHERITANCE_EA_NAME,
74                 SAMBA_XATTR_DOS_ATTRIB,
75                 NULL
76         };
77
78         int i;
79
80         for (i = 0; prohibited_ea_names[i]; i++) {
81                 if (strequal( prohibited_ea_names[i], unix_ea_name))
82                         return true;
83         }
84         if (StrnCaseCmp(unix_ea_name, SAMBA_XATTR_DOSSTREAM_PREFIX,
85                         strlen(SAMBA_XATTR_DOSSTREAM_PREFIX)) == 0) {
86                 return true;
87         }
88         return false;
89 }
90
91 /****************************************************************************
92  Get one EA value. Fill in a struct ea_struct.
93 ****************************************************************************/
94
95 NTSTATUS get_ea_value(TALLOC_CTX *mem_ctx, connection_struct *conn,
96                       files_struct *fsp, const char *fname,
97                       const char *ea_name, struct ea_struct *pea)
98 {
99         /* Get the value of this xattr. Max size is 64k. */
100         size_t attr_size = 256;
101         char *val = NULL;
102         ssize_t sizeret;
103
104  again:
105
106         val = TALLOC_REALLOC_ARRAY(mem_ctx, val, char, attr_size);
107         if (!val) {
108                 return NT_STATUS_NO_MEMORY;
109         }
110
111         if (fsp && fsp->fh->fd != -1) {
112                 sizeret = SMB_VFS_FGETXATTR(fsp, ea_name, val, attr_size);
113         } else {
114                 sizeret = SMB_VFS_GETXATTR(conn, fname, ea_name, val, attr_size);
115         }
116
117         if (sizeret == -1 && errno == ERANGE && attr_size != 65536) {
118                 attr_size = 65536;
119                 goto again;
120         }
121
122         if (sizeret == -1) {
123                 return map_nt_error_from_unix(errno);
124         }
125
126         DEBUG(10,("get_ea_value: EA %s is of length %u\n", ea_name, (unsigned int)sizeret));
127         dump_data(10, (uint8 *)val, sizeret);
128
129         pea->flags = 0;
130         if (strnequal(ea_name, "user.", 5)) {
131                 pea->name = talloc_strdup(mem_ctx, &ea_name[5]);
132         } else {
133                 pea->name = talloc_strdup(mem_ctx, ea_name);
134         }
135         if (pea->name == NULL) {
136                 TALLOC_FREE(val);
137                 return NT_STATUS_NO_MEMORY;
138         }
139         pea->value.data = (unsigned char *)val;
140         pea->value.length = (size_t)sizeret;
141         return NT_STATUS_OK;
142 }
143
144 NTSTATUS get_ea_names_from_file(TALLOC_CTX *mem_ctx, connection_struct *conn,
145                                 files_struct *fsp, const char *fname,
146                                 char ***pnames, size_t *pnum_names)
147 {
148         /* Get a list of all xattrs. Max namesize is 64k. */
149         size_t ea_namelist_size = 1024;
150         char *ea_namelist = NULL;
151
152         char *p;
153         char **names, **tmp;
154         size_t num_names;
155         ssize_t sizeret = -1;
156
157         if (!lp_ea_support(SNUM(conn))) {
158                 *pnames = NULL;
159                 *pnum_names = 0;
160                 return NT_STATUS_OK;
161         }
162
163         /*
164          * TALLOC the result early to get the talloc hierarchy right.
165          */
166
167         names = TALLOC_ARRAY(mem_ctx, char *, 1);
168         if (names == NULL) {
169                 DEBUG(0, ("talloc failed\n"));
170                 return NT_STATUS_NO_MEMORY;
171         }
172
173         while (ea_namelist_size <= 65536) {
174
175                 ea_namelist = TALLOC_REALLOC_ARRAY(
176                         names, ea_namelist, char, ea_namelist_size);
177                 if (ea_namelist == NULL) {
178                         DEBUG(0, ("talloc failed\n"));
179                         TALLOC_FREE(names);
180                         return NT_STATUS_NO_MEMORY;
181                 }
182
183                 if (fsp && fsp->fh->fd != -1) {
184                         sizeret = SMB_VFS_FLISTXATTR(fsp, ea_namelist,
185                                                      ea_namelist_size);
186                 } else {
187                         sizeret = SMB_VFS_LISTXATTR(conn, fname, ea_namelist,
188                                                     ea_namelist_size);
189                 }
190
191                 if ((sizeret == -1) && (errno == ERANGE)) {
192                         ea_namelist_size *= 2;
193                 }
194                 else {
195                         break;
196                 }
197         }
198
199         if (sizeret == -1) {
200                 TALLOC_FREE(names);
201                 return map_nt_error_from_unix(errno);
202         }
203
204         DEBUG(10, ("get_ea_list_from_file: ea_namelist size = %u\n",
205                    (unsigned int)sizeret));
206
207         if (sizeret == 0) {
208                 TALLOC_FREE(names);
209                 *pnames = NULL;
210                 *pnum_names = 0;
211                 return NT_STATUS_OK;
212         }
213
214         /*
215          * Ensure the result is 0-terminated
216          */
217
218         if (ea_namelist[sizeret-1] != '\0') {
219                 TALLOC_FREE(names);
220                 return NT_STATUS_INTERNAL_ERROR;
221         }
222
223         /*
224          * count the names
225          */
226         num_names = 0;
227
228         for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p)+1) {
229                 num_names += 1;
230         }
231
232         tmp = TALLOC_REALLOC_ARRAY(mem_ctx, names, char *, num_names);
233         if (tmp == NULL) {
234                 DEBUG(0, ("talloc failed\n"));
235                 TALLOC_FREE(names);
236                 return NT_STATUS_NO_MEMORY;
237         }
238
239         names = tmp;
240         num_names = 0;
241
242         for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p)+1) {
243                 names[num_names++] = p;
244         }
245
246         *pnames = names;
247         *pnum_names = num_names;
248         return NT_STATUS_OK;
249 }
250
251 /****************************************************************************
252  Return a linked list of the total EA's. Plus the total size
253 ****************************************************************************/
254
255 static struct ea_list *get_ea_list_from_file(TALLOC_CTX *mem_ctx, connection_struct *conn, files_struct *fsp,
256                                         const char *fname, size_t *pea_total_len)
257 {
258         /* Get a list of all xattrs. Max namesize is 64k. */
259         size_t i, num_names;
260         char **names;
261         struct ea_list *ea_list_head = NULL;
262         NTSTATUS status;
263
264         *pea_total_len = 0;
265
266         if (!lp_ea_support(SNUM(conn))) {
267                 return NULL;
268         }
269
270         status = get_ea_names_from_file(talloc_tos(), conn, fsp, fname,
271                                         &names, &num_names);
272
273         if (!NT_STATUS_IS_OK(status) || (num_names == 0)) {
274                 return NULL;
275         }
276
277         for (i=0; i<num_names; i++) {
278                 struct ea_list *listp;
279                 fstring dos_ea_name;
280
281                 if (strnequal(names[i], "system.", 7)
282                     || samba_private_attr_name(names[i]))
283                         continue;
284
285                 listp = TALLOC_P(mem_ctx, struct ea_list);
286                 if (listp == NULL) {
287                         return NULL;
288                 }
289
290                 if (!NT_STATUS_IS_OK(get_ea_value(mem_ctx, conn, fsp,
291                                                   fname, names[i],
292                                                   &listp->ea))) {
293                         return NULL;
294                 }
295
296                 push_ascii_fstring(dos_ea_name, listp->ea.name);
297
298                 *pea_total_len +=
299                         4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
300
301                 DEBUG(10,("get_ea_list_from_file: total_len = %u, %s, val len "
302                           "= %u\n", (unsigned int)*pea_total_len, dos_ea_name,
303                           (unsigned int)listp->ea.value.length));
304
305                 DLIST_ADD_END(ea_list_head, listp, struct ea_list *);
306
307         }
308
309         /* Add on 4 for total length. */
310         if (*pea_total_len) {
311                 *pea_total_len += 4;
312         }
313
314         DEBUG(10, ("get_ea_list_from_file: total_len = %u\n",
315                    (unsigned int)*pea_total_len));
316
317         return ea_list_head;
318 }
319
320 /****************************************************************************
321  Fill a qfilepathinfo buffer with EA's. Returns the length of the buffer
322  that was filled.
323 ****************************************************************************/
324
325 static unsigned int fill_ea_buffer(TALLOC_CTX *mem_ctx, char *pdata, unsigned int total_data_size,
326         connection_struct *conn, struct ea_list *ea_list)
327 {
328         unsigned int ret_data_size = 4;
329         char *p = pdata;
330
331         SMB_ASSERT(total_data_size >= 4);
332
333         if (!lp_ea_support(SNUM(conn))) {
334                 SIVAL(pdata,4,0);
335                 return 4;
336         }
337
338         for (p = pdata + 4; ea_list; ea_list = ea_list->next) {
339                 size_t dos_namelen;
340                 fstring dos_ea_name;
341                 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
342                 dos_namelen = strlen(dos_ea_name);
343                 if (dos_namelen > 255 || dos_namelen == 0) {
344                         break;
345                 }
346                 if (ea_list->ea.value.length > 65535) {
347                         break;
348                 }
349                 if (4 + dos_namelen + 1 + ea_list->ea.value.length > total_data_size) {
350                         break;
351                 }
352
353                 /* We know we have room. */
354                 SCVAL(p,0,ea_list->ea.flags);
355                 SCVAL(p,1,dos_namelen);
356                 SSVAL(p,2,ea_list->ea.value.length);
357                 fstrcpy(p+4, dos_ea_name);
358                 memcpy( p + 4 + dos_namelen + 1, ea_list->ea.value.data, ea_list->ea.value.length);
359
360                 total_data_size -= 4 + dos_namelen + 1 + ea_list->ea.value.length;
361                 p += 4 + dos_namelen + 1 + ea_list->ea.value.length;
362         }
363
364         ret_data_size = PTR_DIFF(p, pdata);
365         DEBUG(10,("fill_ea_buffer: data_size = %u\n", ret_data_size ));
366         SIVAL(pdata,0,ret_data_size);
367         return ret_data_size;
368 }
369
370 static unsigned int estimate_ea_size(connection_struct *conn, files_struct *fsp, const char *fname)
371 {
372         size_t total_ea_len = 0;
373         TALLOC_CTX *mem_ctx = NULL;
374
375         if (!lp_ea_support(SNUM(conn))) {
376                 return 0;
377         }
378         mem_ctx = talloc_tos();
379         (void)get_ea_list_from_file(mem_ctx, conn, fsp, fname, &total_ea_len);
380         return total_ea_len;
381 }
382
383 /****************************************************************************
384  Ensure the EA name is case insensitive by matching any existing EA name.
385 ****************************************************************************/
386
387 static void canonicalize_ea_name(connection_struct *conn, files_struct *fsp, const char *fname, fstring unix_ea_name)
388 {
389         size_t total_ea_len;
390         TALLOC_CTX *mem_ctx = talloc_tos();
391         struct ea_list *ea_list = get_ea_list_from_file(mem_ctx, conn, fsp, fname, &total_ea_len);
392
393         for (; ea_list; ea_list = ea_list->next) {
394                 if (strequal(&unix_ea_name[5], ea_list->ea.name)) {
395                         DEBUG(10,("canonicalize_ea_name: %s -> %s\n",
396                                 &unix_ea_name[5], ea_list->ea.name));
397                         safe_strcpy(&unix_ea_name[5], ea_list->ea.name, sizeof(fstring)-6);
398                         break;
399                 }
400         }
401 }
402
403 /****************************************************************************
404  Set or delete an extended attribute.
405 ****************************************************************************/
406
407 NTSTATUS set_ea(connection_struct *conn, files_struct *fsp, const char *fname, struct ea_list *ea_list)
408 {
409         if (!lp_ea_support(SNUM(conn))) {
410                 return NT_STATUS_EAS_NOT_SUPPORTED;
411         }
412
413         for (;ea_list; ea_list = ea_list->next) {
414                 int ret;
415                 fstring unix_ea_name;
416
417                 fstrcpy(unix_ea_name, "user."); /* All EA's must start with user. */
418                 fstrcat(unix_ea_name, ea_list->ea.name);
419
420                 canonicalize_ea_name(conn, fsp, fname, unix_ea_name);
421
422                 DEBUG(10,("set_ea: ea_name %s ealen = %u\n", unix_ea_name, (unsigned int)ea_list->ea.value.length));
423
424                 if (samba_private_attr_name(unix_ea_name)) {
425                         DEBUG(10,("set_ea: ea name %s is a private Samba name.\n", unix_ea_name));
426                         return NT_STATUS_ACCESS_DENIED;
427                 }
428
429                 if (ea_list->ea.value.length == 0) {
430                         /* Remove the attribute. */
431                         if (fsp && (fsp->fh->fd != -1)) {
432                                 DEBUG(10,("set_ea: deleting ea name %s on file %s by file descriptor.\n",
433                                         unix_ea_name, fsp->fsp_name));
434                                 ret = SMB_VFS_FREMOVEXATTR(fsp, unix_ea_name);
435                         } else {
436                                 DEBUG(10,("set_ea: deleting ea name %s on file %s.\n",
437                                         unix_ea_name, fname));
438                                 ret = SMB_VFS_REMOVEXATTR(conn, fname, unix_ea_name);
439                         }
440 #ifdef ENOATTR
441                         /* Removing a non existent attribute always succeeds. */
442                         if (ret == -1 && errno == ENOATTR) {
443                                 DEBUG(10,("set_ea: deleting ea name %s didn't exist - succeeding by default.\n",
444                                                 unix_ea_name));
445                                 ret = 0;
446                         }
447 #endif
448                 } else {
449                         if (fsp && (fsp->fh->fd != -1)) {
450                                 DEBUG(10,("set_ea: setting ea name %s on file %s by file descriptor.\n",
451                                         unix_ea_name, fsp->fsp_name));
452                                 ret = SMB_VFS_FSETXATTR(fsp, unix_ea_name,
453                                                         ea_list->ea.value.data, ea_list->ea.value.length, 0);
454                         } else {
455                                 DEBUG(10,("set_ea: setting ea name %s on file %s.\n",
456                                         unix_ea_name, fname));
457                                 ret = SMB_VFS_SETXATTR(conn, fname, unix_ea_name,
458                                                         ea_list->ea.value.data, ea_list->ea.value.length, 0);
459                         }
460                 }
461
462                 if (ret == -1) {
463 #ifdef ENOTSUP
464                         if (errno == ENOTSUP) {
465                                 return NT_STATUS_EAS_NOT_SUPPORTED;
466                         }
467 #endif
468                         return map_nt_error_from_unix(errno);
469                 }
470
471         }
472         return NT_STATUS_OK;
473 }
474 /****************************************************************************
475  Read a list of EA names from an incoming data buffer. Create an ea_list with them.
476 ****************************************************************************/
477
478 static struct ea_list *read_ea_name_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
479 {
480         struct ea_list *ea_list_head = NULL;
481         size_t converted_size, offset = 0;
482
483         while (offset + 2 < data_size) {
484                 struct ea_list *eal = TALLOC_ZERO_P(ctx, struct ea_list);
485                 unsigned int namelen = CVAL(pdata,offset);
486
487                 offset++; /* Go past the namelen byte. */
488
489                 /* integer wrap paranioa. */
490                 if ((offset + namelen < offset) || (offset + namelen < namelen) ||
491                                 (offset > data_size) || (namelen > data_size) ||
492                                 (offset + namelen >= data_size)) {
493                         break;
494                 }
495                 /* Ensure the name is null terminated. */
496                 if (pdata[offset + namelen] != '\0') {
497                         return NULL;
498                 }
499                 if (!pull_ascii_talloc(ctx, &eal->ea.name, &pdata[offset],
500                                        &converted_size)) {
501                         DEBUG(0,("read_ea_name_list: pull_ascii_talloc "
502                                  "failed: %s", strerror(errno)));
503                 }
504                 if (!eal->ea.name) {
505                         return NULL;
506                 }
507
508                 offset += (namelen + 1); /* Go past the name + terminating zero. */
509                 DLIST_ADD_END(ea_list_head, eal, struct ea_list *);
510                 DEBUG(10,("read_ea_name_list: read ea name %s\n", eal->ea.name));
511         }
512
513         return ea_list_head;
514 }
515
516 /****************************************************************************
517  Read one EA list entry from the buffer.
518 ****************************************************************************/
519
520 struct ea_list *read_ea_list_entry(TALLOC_CTX *ctx, const char *pdata, size_t data_size, size_t *pbytes_used)
521 {
522         struct ea_list *eal = TALLOC_ZERO_P(ctx, struct ea_list);
523         uint16 val_len;
524         unsigned int namelen;
525         size_t converted_size;
526
527         if (!eal) {
528                 return NULL;
529         }
530
531         if (data_size < 6) {
532                 return NULL;
533         }
534
535         eal->ea.flags = CVAL(pdata,0);
536         namelen = CVAL(pdata,1);
537         val_len = SVAL(pdata,2);
538
539         if (4 + namelen + 1 + val_len > data_size) {
540                 return NULL;
541         }
542
543         /* Ensure the name is null terminated. */
544         if (pdata[namelen + 4] != '\0') {
545                 return NULL;
546         }
547         if (!pull_ascii_talloc(ctx, &eal->ea.name, pdata + 4, &converted_size)) {
548                 DEBUG(0,("read_ea_list_entry: pull_ascii_talloc failed: %s",
549                          strerror(errno)));
550         }
551         if (!eal->ea.name) {
552                 return NULL;
553         }
554
555         eal->ea.value = data_blob_talloc(eal, NULL, (size_t)val_len + 1);
556         if (!eal->ea.value.data) {
557                 return NULL;
558         }
559
560         memcpy(eal->ea.value.data, pdata + 4 + namelen + 1, val_len);
561
562         /* Ensure we're null terminated just in case we print the value. */
563         eal->ea.value.data[val_len] = '\0';
564         /* But don't count the null. */
565         eal->ea.value.length--;
566
567         if (pbytes_used) {
568                 *pbytes_used = 4 + namelen + 1 + val_len;
569         }
570
571         DEBUG(10,("read_ea_list_entry: read ea name %s\n", eal->ea.name));
572         dump_data(10, eal->ea.value.data, eal->ea.value.length);
573
574         return eal;
575 }
576
577 /****************************************************************************
578  Read a list of EA names and data from an incoming data buffer. Create an ea_list with them.
579 ****************************************************************************/
580
581 static struct ea_list *read_ea_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
582 {
583         struct ea_list *ea_list_head = NULL;
584         size_t offset = 0;
585         size_t bytes_used = 0;
586
587         while (offset < data_size) {
588                 struct ea_list *eal = read_ea_list_entry(ctx, pdata + offset, data_size - offset, &bytes_used);
589
590                 if (!eal) {
591                         return NULL;
592                 }
593
594                 DLIST_ADD_END(ea_list_head, eal, struct ea_list *);
595                 offset += bytes_used;
596         }
597
598         return ea_list_head;
599 }
600
601 /****************************************************************************
602  Count the total EA size needed.
603 ****************************************************************************/
604
605 static size_t ea_list_size(struct ea_list *ealist)
606 {
607         fstring dos_ea_name;
608         struct ea_list *listp;
609         size_t ret = 0;
610
611         for (listp = ealist; listp; listp = listp->next) {
612                 push_ascii_fstring(dos_ea_name, listp->ea.name);
613                 ret += 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
614         }
615         /* Add on 4 for total length. */
616         if (ret) {
617                 ret += 4;
618         }
619
620         return ret;
621 }
622
623 /****************************************************************************
624  Return a union of EA's from a file list and a list of names.
625  The TALLOC context for the two lists *MUST* be identical as we steal
626  memory from one list to add to another. JRA.
627 ****************************************************************************/
628
629 static struct ea_list *ea_list_union(struct ea_list *name_list, struct ea_list *file_list, size_t *total_ea_len)
630 {
631         struct ea_list *nlistp, *flistp;
632
633         for (nlistp = name_list; nlistp; nlistp = nlistp->next) {
634                 for (flistp = file_list; flistp; flistp = flistp->next) {
635                         if (strequal(nlistp->ea.name, flistp->ea.name)) {
636                                 break;
637                         }
638                 }
639
640                 if (flistp) {
641                         /* Copy the data from this entry. */
642                         nlistp->ea.flags = flistp->ea.flags;
643                         nlistp->ea.value = flistp->ea.value;
644                 } else {
645                         /* Null entry. */
646                         nlistp->ea.flags = 0;
647                         ZERO_STRUCT(nlistp->ea.value);
648                 }
649         }
650
651         *total_ea_len = ea_list_size(name_list);
652         return name_list;
653 }
654
655 /****************************************************************************
656   Send the required number of replies back.
657   We assume all fields other than the data fields are
658   set correctly for the type of call.
659   HACK ! Always assumes smb_setup field is zero.
660 ****************************************************************************/
661
662 void send_trans2_replies(connection_struct *conn,
663                         struct smb_request *req,
664                          const char *params,
665                          int paramsize,
666                          const char *pdata,
667                          int datasize,
668                          int max_data_bytes)
669 {
670         /* As we are using a protocol > LANMAN1 then the max_send
671          variable must have been set in the sessetupX call.
672          This takes precedence over the max_xmit field in the
673          global struct. These different max_xmit variables should
674          be merged as this is now too confusing */
675
676         int data_to_send = datasize;
677         int params_to_send = paramsize;
678         int useable_space;
679         const char *pp = params;
680         const char *pd = pdata;
681         int params_sent_thistime, data_sent_thistime, total_sent_thistime;
682         int alignment_offset = 1; /* JRA. This used to be 3. Set to 1 to make netmon parse ok. */
683         int data_alignment_offset = 0;
684         bool overflow = False;
685
686         /* Modify the data_to_send and datasize and set the error if
687            we're trying to send more than max_data_bytes. We still send
688            the part of the packet(s) that fit. Strange, but needed
689            for OS/2. */
690
691         if (max_data_bytes > 0 && datasize > max_data_bytes) {
692                 DEBUG(5,("send_trans2_replies: max_data_bytes %d exceeded by data %d\n",
693                         max_data_bytes, datasize ));
694                 datasize = data_to_send = max_data_bytes;
695                 overflow = True;
696         }
697
698         /* If there genuinely are no parameters or data to send just send the empty packet */
699
700         if(params_to_send == 0 && data_to_send == 0) {
701                 reply_outbuf(req, 10, 0);
702                 show_msg((char *)req->outbuf);
703                 return;
704         }
705
706         /* When sending params and data ensure that both are nicely aligned */
707         /* Only do this alignment when there is also data to send - else
708                 can cause NT redirector problems. */
709
710         if (((params_to_send % 4) != 0) && (data_to_send != 0))
711                 data_alignment_offset = 4 - (params_to_send % 4);
712
713         /* Space is bufsize minus Netbios over TCP header minus SMB header */
714         /* The alignment_offset is to align the param bytes on an even byte
715                 boundary. NT 4.0 Beta needs this to work correctly. */
716
717         useable_space = max_send - (smb_size
718                                     + 2 * 10 /* wct */
719                                     + alignment_offset
720                                     + data_alignment_offset);
721
722         if (useable_space < 0) {
723                 DEBUG(0, ("send_trans2_replies failed sanity useable_space "
724                           "= %d!!!", useable_space));
725                 exit_server_cleanly("send_trans2_replies: Not enough space");
726         }
727
728         while (params_to_send || data_to_send) {
729                 /* Calculate whether we will totally or partially fill this packet */
730
731                 total_sent_thistime = params_to_send + data_to_send;
732
733                 /* We can never send more than useable_space */
734                 /*
735                  * Note that 'useable_space' does not include the alignment offsets,
736                  * but we must include the alignment offsets in the calculation of
737                  * the length of the data we send over the wire, as the alignment offsets
738                  * are sent here. Fix from Marc_Jacobsen@hp.com.
739                  */
740
741                 total_sent_thistime = MIN(total_sent_thistime, useable_space);
742
743                 reply_outbuf(req, 10, total_sent_thistime + alignment_offset
744                              + data_alignment_offset);
745
746                 /*
747                  * We might have SMBtrans2s in req which was transferred to
748                  * the outbuf, fix that.
749                  */
750                 SCVAL(req->outbuf, smb_com, SMBtrans2);
751
752                 /* Set total params and data to be sent */
753                 SSVAL(req->outbuf,smb_tprcnt,paramsize);
754                 SSVAL(req->outbuf,smb_tdrcnt,datasize);
755
756                 /* Calculate how many parameters and data we can fit into
757                  * this packet. Parameters get precedence
758                  */
759
760                 params_sent_thistime = MIN(params_to_send,useable_space);
761                 data_sent_thistime = useable_space - params_sent_thistime;
762                 data_sent_thistime = MIN(data_sent_thistime,data_to_send);
763
764                 SSVAL(req->outbuf,smb_prcnt, params_sent_thistime);
765
766                 /* smb_proff is the offset from the start of the SMB header to the
767                         parameter bytes, however the first 4 bytes of outbuf are
768                         the Netbios over TCP header. Thus use smb_base() to subtract
769                         them from the calculation */
770
771                 SSVAL(req->outbuf,smb_proff,
772                       ((smb_buf(req->outbuf)+alignment_offset)
773                        - smb_base(req->outbuf)));
774
775                 if(params_sent_thistime == 0)
776                         SSVAL(req->outbuf,smb_prdisp,0);
777                 else
778                         /* Absolute displacement of param bytes sent in this packet */
779                         SSVAL(req->outbuf,smb_prdisp,pp - params);
780
781                 SSVAL(req->outbuf,smb_drcnt, data_sent_thistime);
782                 if(data_sent_thistime == 0) {
783                         SSVAL(req->outbuf,smb_droff,0);
784                         SSVAL(req->outbuf,smb_drdisp, 0);
785                 } else {
786                         /* The offset of the data bytes is the offset of the
787                                 parameter bytes plus the number of parameters being sent this time */
788                         SSVAL(req->outbuf, smb_droff,
789                               ((smb_buf(req->outbuf)+alignment_offset)
790                                - smb_base(req->outbuf))
791                               + params_sent_thistime + data_alignment_offset);
792                         SSVAL(req->outbuf,smb_drdisp, pd - pdata);
793                 }
794
795                 /* Initialize the padding for alignment */
796
797                 if (alignment_offset != 0) {
798                         memset(smb_buf(req->outbuf), 0, alignment_offset);
799                 }
800
801                 /* Copy the param bytes into the packet */
802
803                 if(params_sent_thistime) {
804                         memcpy((smb_buf(req->outbuf)+alignment_offset), pp,
805                                params_sent_thistime);
806                 }
807
808                 /* Copy in the data bytes */
809                 if(data_sent_thistime) {
810                         if (data_alignment_offset != 0) {
811                                 memset((smb_buf(req->outbuf)+alignment_offset+
812                                         params_sent_thistime), 0,
813                                        data_alignment_offset);
814                         }
815                         memcpy(smb_buf(req->outbuf)+alignment_offset
816                                +params_sent_thistime+data_alignment_offset,
817                                pd,data_sent_thistime);
818                 }
819
820                 DEBUG(9,("t2_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n",
821                         params_sent_thistime, data_sent_thistime, useable_space));
822                 DEBUG(9,("t2_rep: params_to_send = %d, data_to_send = %d, paramsize = %d, datasize = %d\n",
823                         params_to_send, data_to_send, paramsize, datasize));
824
825                 if (overflow) {
826                         error_packet_set((char *)req->outbuf,
827                                          ERRDOS,ERRbufferoverflow,
828                                          STATUS_BUFFER_OVERFLOW,
829                                          __LINE__,__FILE__);
830                 }
831
832                 /* Send the packet */
833                 show_msg((char *)req->outbuf);
834                 if (!srv_send_smb(smbd_server_fd(),
835                                 (char *)req->outbuf,
836                                 true, req->seqnum+1,
837                                 IS_CONN_ENCRYPTED(conn),
838                                 &req->pcd))
839                         exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
840
841                 TALLOC_FREE(req->outbuf);
842
843                 pp += params_sent_thistime;
844                 pd += data_sent_thistime;
845
846                 params_to_send -= params_sent_thistime;
847                 data_to_send -= data_sent_thistime;
848
849                 /* Sanity check */
850                 if(params_to_send < 0 || data_to_send < 0) {
851                         DEBUG(0,("send_trans2_replies failed sanity check pts = %d, dts = %d\n!!!",
852                                 params_to_send, data_to_send));
853                         return;
854                 }
855         }
856
857         return;
858 }
859
860 /****************************************************************************
861  Reply to a TRANSACT2_OPEN.
862 ****************************************************************************/
863
864 static void call_trans2open(connection_struct *conn,
865                             struct smb_request *req,
866                             char **pparams, int total_params,
867                             char **ppdata, int total_data,
868                             unsigned int max_data_bytes)
869 {
870         char *params = *pparams;
871         char *pdata = *ppdata;
872         int deny_mode;
873         int32 open_attr;
874         bool oplock_request;
875 #if 0
876         bool return_additional_info;
877         int16 open_sattr;
878         time_t open_time;
879 #endif
880         int open_ofun;
881         uint32 open_size;
882         char *pname;
883         char *fname = NULL;
884         SMB_OFF_T size=0;
885         int fattr=0,mtime=0;
886         SMB_INO_T inode = 0;
887         SMB_STRUCT_STAT sbuf;
888         int smb_action = 0;
889         files_struct *fsp;
890         struct ea_list *ea_list = NULL;
891         uint16 flags = 0;
892         NTSTATUS status;
893         uint32 access_mask;
894         uint32 share_mode;
895         uint32 create_disposition;
896         uint32 create_options = 0;
897         TALLOC_CTX *ctx = talloc_tos();
898
899         SET_STAT_INVALID(sbuf);
900
901         /*
902          * Ensure we have enough parameters to perform the operation.
903          */
904
905         if (total_params < 29) {
906                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
907                 return;
908         }
909
910         flags = SVAL(params, 0);
911         deny_mode = SVAL(params, 2);
912         open_attr = SVAL(params,6);
913         oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
914         if (oplock_request) {
915                 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
916         }
917
918 #if 0
919         return_additional_info = BITSETW(params,0);
920         open_sattr = SVAL(params, 4);
921         open_time = make_unix_date3(params+8);
922 #endif
923         open_ofun = SVAL(params,12);
924         open_size = IVAL(params,14);
925         pname = &params[28];
926
927         if (IS_IPC(conn)) {
928                 reply_doserror(req, ERRSRV, ERRaccess);
929                 return;
930         }
931
932         srvstr_get_path(ctx, params, req->flags2, &fname, pname,
933                         total_params - 28, STR_TERMINATE,
934                         &status);
935         if (!NT_STATUS_IS_OK(status)) {
936                 reply_nterror(req, status);
937                 return;
938         }
939
940         DEBUG(3,("call_trans2open %s deny_mode=0x%x attr=%d ofun=0x%x size=%d\n",
941                 fname, (unsigned int)deny_mode, (unsigned int)open_attr,
942                 (unsigned int)open_ofun, open_size));
943
944         if (open_ofun == 0) {
945                 reply_nterror(req, NT_STATUS_OBJECT_NAME_COLLISION);
946                 return;
947         }
948
949         if (!map_open_params_to_ntcreate(fname, deny_mode, open_ofun,
950                                 &access_mask,
951                                 &share_mode,
952                                 &create_disposition,
953                                 &create_options)) {
954                 reply_doserror(req, ERRDOS, ERRbadaccess);
955                 return;
956         }
957
958         /* Any data in this call is an EA list. */
959         if (total_data && (total_data != 4) && !lp_ea_support(SNUM(conn))) {
960                 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
961                 return;
962         }
963
964         if (total_data != 4) {
965                 if (total_data < 10) {
966                         reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
967                         return;
968                 }
969
970                 if (IVAL(pdata,0) > total_data) {
971                         DEBUG(10,("call_trans2open: bad total data size (%u) > %u\n",
972                                 IVAL(pdata,0), (unsigned int)total_data));
973                         reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
974                         return;
975                 }
976
977                 ea_list = read_ea_list(talloc_tos(), pdata + 4,
978                                        total_data - 4);
979                 if (!ea_list) {
980                         reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
981                         return;
982                 }
983         } else if (IVAL(pdata,0) != 4) {
984                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
985                 return;
986         }
987
988         status = SMB_VFS_CREATE_FILE(
989                 conn,                                   /* conn */
990                 req,                                    /* req */
991                 0,                                      /* root_dir_fid */
992                 fname,                                  /* fname */
993                 CFF_DOS_PATH,                           /* create_file_flags */
994                 access_mask,                            /* access_mask */
995                 share_mode,                             /* share_access */
996                 create_disposition,                     /* create_disposition*/
997                 create_options,                         /* create_options */
998                 open_attr,                              /* file_attributes */
999                 oplock_request,                         /* oplock_request */
1000                 open_size,                              /* allocation_size */
1001                 NULL,                                   /* sd */
1002                 ea_list,                                /* ea_list */
1003                 &fsp,                                   /* result */
1004                 &smb_action,                            /* pinfo */
1005                 &sbuf);                                 /* psbuf */
1006
1007         if (!NT_STATUS_IS_OK(status)) {
1008                 if (open_was_deferred(req->mid)) {
1009                         /* We have re-scheduled this call. */
1010                         return;
1011                 }
1012                 reply_openerror(req, status);
1013                 return;
1014         }
1015
1016         size = get_file_size_stat(&sbuf);
1017         fattr = dos_mode(conn,fsp->fsp_name,&sbuf);
1018         mtime = sbuf.st_mtime;
1019         inode = sbuf.st_ino;
1020         if (fattr & aDIR) {
1021                 close_file(req, fsp, ERROR_CLOSE);
1022                 reply_doserror(req, ERRDOS,ERRnoaccess);
1023                 return;
1024         }
1025
1026         /* Realloc the size of parameters and data we will return */
1027         *pparams = (char *)SMB_REALLOC(*pparams, 30);
1028         if(*pparams == NULL ) {
1029                 reply_nterror(req, NT_STATUS_NO_MEMORY);
1030                 return;
1031         }
1032         params = *pparams;
1033
1034         SSVAL(params,0,fsp->fnum);
1035         SSVAL(params,2,fattr);
1036         srv_put_dos_date2(params,4, mtime);
1037         SIVAL(params,8, (uint32)size);
1038         SSVAL(params,12,deny_mode);
1039         SSVAL(params,14,0); /* open_type - file or directory. */
1040         SSVAL(params,16,0); /* open_state - only valid for IPC device. */
1041
1042         if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1043                 smb_action |= EXTENDED_OPLOCK_GRANTED;
1044         }
1045
1046         SSVAL(params,18,smb_action);
1047
1048         /*
1049          * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
1050          */
1051         SIVAL(params,20,inode);
1052         SSVAL(params,24,0); /* Padding. */
1053         if (flags & 8) {
1054                 uint32 ea_size = estimate_ea_size(conn, fsp, fsp->fsp_name);
1055                 SIVAL(params, 26, ea_size);
1056         } else {
1057                 SIVAL(params, 26, 0);
1058         }
1059
1060         /* Send the required number of replies */
1061         send_trans2_replies(conn, req, params, 30, *ppdata, 0, max_data_bytes);
1062 }
1063
1064 /*********************************************************
1065  Routine to check if a given string matches exactly.
1066  as a special case a mask of "." does NOT match. That
1067  is required for correct wildcard semantics
1068  Case can be significant or not.
1069 **********************************************************/
1070
1071 static bool exact_match(connection_struct *conn,
1072                 const char *str,
1073                 const char *mask)
1074 {
1075         if (mask[0] == '.' && mask[1] == 0)
1076                 return False;
1077         if (dptr_has_wild(conn->dirptr)) {
1078                 return False;
1079         }
1080         if (conn->case_sensitive)
1081                 return strcmp(str,mask)==0;
1082         else
1083                 return StrCaseCmp(str,mask) == 0;
1084 }
1085
1086 /****************************************************************************
1087  Return the filetype for UNIX extensions.
1088 ****************************************************************************/
1089
1090 static uint32 unix_filetype(mode_t mode)
1091 {
1092         if(S_ISREG(mode))
1093                 return UNIX_TYPE_FILE;
1094         else if(S_ISDIR(mode))
1095                 return UNIX_TYPE_DIR;
1096 #ifdef S_ISLNK
1097         else if(S_ISLNK(mode))
1098                 return UNIX_TYPE_SYMLINK;
1099 #endif
1100 #ifdef S_ISCHR
1101         else if(S_ISCHR(mode))
1102                 return UNIX_TYPE_CHARDEV;
1103 #endif
1104 #ifdef S_ISBLK
1105         else if(S_ISBLK(mode))
1106                 return UNIX_TYPE_BLKDEV;
1107 #endif
1108 #ifdef S_ISFIFO
1109         else if(S_ISFIFO(mode))
1110                 return UNIX_TYPE_FIFO;
1111 #endif
1112 #ifdef S_ISSOCK
1113         else if(S_ISSOCK(mode))
1114                 return UNIX_TYPE_SOCKET;
1115 #endif
1116
1117         DEBUG(0,("unix_filetype: unknown filetype %u\n", (unsigned)mode));
1118         return UNIX_TYPE_UNKNOWN;
1119 }
1120
1121 /****************************************************************************
1122  Map wire perms onto standard UNIX permissions. Obey share restrictions.
1123 ****************************************************************************/
1124
1125 enum perm_type { PERM_NEW_FILE, PERM_NEW_DIR, PERM_EXISTING_FILE, PERM_EXISTING_DIR};
1126
1127 static NTSTATUS unix_perms_from_wire( connection_struct *conn,
1128                                 SMB_STRUCT_STAT *psbuf,
1129                                 uint32 perms,
1130                                 enum perm_type ptype,
1131                                 mode_t *ret_perms)
1132 {
1133         mode_t ret = 0;
1134
1135         if (perms == SMB_MODE_NO_CHANGE) {
1136                 if (!VALID_STAT(*psbuf)) {
1137                         return NT_STATUS_INVALID_PARAMETER;
1138                 } else {
1139                         *ret_perms = psbuf->st_mode;
1140                         return NT_STATUS_OK;
1141                 }
1142         }
1143
1144         ret |= ((perms & UNIX_X_OTH ) ? S_IXOTH : 0);
1145         ret |= ((perms & UNIX_W_OTH ) ? S_IWOTH : 0);
1146         ret |= ((perms & UNIX_R_OTH ) ? S_IROTH : 0);
1147         ret |= ((perms & UNIX_X_GRP ) ? S_IXGRP : 0);
1148         ret |= ((perms & UNIX_W_GRP ) ? S_IWGRP : 0);
1149         ret |= ((perms & UNIX_R_GRP ) ? S_IRGRP : 0);
1150         ret |= ((perms & UNIX_X_USR ) ? S_IXUSR : 0);
1151         ret |= ((perms & UNIX_W_USR ) ? S_IWUSR : 0);
1152         ret |= ((perms & UNIX_R_USR ) ? S_IRUSR : 0);
1153 #ifdef S_ISVTX
1154         ret |= ((perms & UNIX_STICKY ) ? S_ISVTX : 0);
1155 #endif
1156 #ifdef S_ISGID
1157         ret |= ((perms & UNIX_SET_GID ) ? S_ISGID : 0);
1158 #endif
1159 #ifdef S_ISUID
1160         ret |= ((perms & UNIX_SET_UID ) ? S_ISUID : 0);
1161 #endif
1162
1163         switch (ptype) {
1164         case PERM_NEW_FILE:
1165                 /* Apply mode mask */
1166                 ret &= lp_create_mask(SNUM(conn));
1167                 /* Add in force bits */
1168                 ret |= lp_force_create_mode(SNUM(conn));
1169                 break;
1170         case PERM_NEW_DIR:
1171                 ret &= lp_dir_mask(SNUM(conn));
1172                 /* Add in force bits */
1173                 ret |= lp_force_dir_mode(SNUM(conn));
1174                 break;
1175         case PERM_EXISTING_FILE:
1176                 /* Apply mode mask */
1177                 ret &= lp_security_mask(SNUM(conn));
1178                 /* Add in force bits */
1179                 ret |= lp_force_security_mode(SNUM(conn));
1180                 break;
1181         case PERM_EXISTING_DIR:
1182                 /* Apply mode mask */
1183                 ret &= lp_dir_security_mask(SNUM(conn));
1184                 /* Add in force bits */
1185                 ret |= lp_force_dir_security_mode(SNUM(conn));
1186                 break;
1187         }
1188
1189         *ret_perms = ret;
1190         return NT_STATUS_OK;
1191 }
1192
1193 /****************************************************************************
1194  Needed to show the msdfs symlinks as directories. Modifies psbuf
1195  to be a directory if it's a msdfs link.
1196 ****************************************************************************/
1197
1198 static bool check_msdfs_link(connection_struct *conn,
1199                                 const char *pathname,
1200                                 SMB_STRUCT_STAT *psbuf)
1201 {
1202         int saved_errno = errno;
1203         if(lp_host_msdfs() &&
1204                 lp_msdfs_root(SNUM(conn)) &&
1205                 is_msdfs_link(conn, pathname, psbuf)) {
1206
1207                 DEBUG(5,("check_msdfs_link: Masquerading msdfs link %s "
1208                         "as a directory\n",
1209                         pathname));
1210                 psbuf->st_mode = (psbuf->st_mode & 0xFFF) | S_IFDIR;
1211                 errno = saved_errno;
1212                 return true;
1213         }
1214         errno = saved_errno;
1215         return false;
1216 }
1217
1218
1219 /****************************************************************************
1220  Get a level dependent lanman2 dir entry.
1221 ****************************************************************************/
1222
1223 static bool get_lanman2_dir_entry(TALLOC_CTX *ctx,
1224                                 connection_struct *conn,
1225                                 uint16 flags2,
1226                                 const char *path_mask,
1227                                 uint32 dirtype,
1228                                 int info_level,
1229                                 int requires_resume_key,
1230                                 bool dont_descend,
1231                                 bool ask_sharemode,
1232                                 char **ppdata,
1233                                 char *base_data,
1234                                 char *end_data,
1235                                 int space_remaining,
1236                                 bool *out_of_space,
1237                                 bool *got_exact_match,
1238                                 int *last_entry_off,
1239                                 struct ea_list *name_list)
1240 {
1241         char *dname;
1242         bool found = False;
1243         SMB_STRUCT_STAT sbuf;
1244         const char *mask = NULL;
1245         char *pathreal = NULL;
1246         char *fname = NULL;
1247         char *p, *q, *pdata = *ppdata;
1248         uint32 reskey=0;
1249         long prev_dirpos=0;
1250         uint32 mode=0;
1251         SMB_OFF_T file_size = 0;
1252         uint64_t allocation_size = 0;
1253         uint32 len;
1254         struct timespec mdate_ts, adate_ts, create_date_ts;
1255         time_t mdate = (time_t)0, adate = (time_t)0, create_date = (time_t)0;
1256         char *nameptr;
1257         char *last_entry_ptr;
1258         bool was_8_3;
1259         uint32 nt_extmode; /* Used for NT connections instead of mode */
1260         bool needslash = ( conn->dirpath[strlen(conn->dirpath) -1] != '/');
1261         bool check_mangled_names = lp_manglednames(conn->params);
1262         char mangled_name[13]; /* mangled 8.3 name. */
1263
1264         *out_of_space = False;
1265         *got_exact_match = False;
1266
1267         ZERO_STRUCT(mdate_ts);
1268         ZERO_STRUCT(adate_ts);
1269         ZERO_STRUCT(create_date_ts);
1270
1271         if (!conn->dirptr) {
1272                 return(False);
1273         }
1274
1275         p = strrchr_m(path_mask,'/');
1276         if(p != NULL) {
1277                 if(p[1] == '\0') {
1278                         mask = talloc_strdup(ctx,"*.*");
1279                 } else {
1280                         mask = p+1;
1281                 }
1282         } else {
1283                 mask = path_mask;
1284         }
1285
1286         while (!found) {
1287                 bool got_match;
1288                 bool ms_dfs_link = False;
1289
1290                 /* Needed if we run out of space */
1291                 long curr_dirpos = prev_dirpos = dptr_TellDir(conn->dirptr);
1292                 dname = dptr_ReadDirName(ctx,conn->dirptr,&curr_dirpos,&sbuf);
1293
1294                 /*
1295                  * Due to bugs in NT client redirectors we are not using
1296                  * resume keys any more - set them to zero.
1297                  * Check out the related comments in findfirst/findnext.
1298                  * JRA.
1299                  */
1300
1301                 reskey = 0;
1302
1303                 DEBUG(8,("get_lanman2_dir_entry:readdir on dirptr 0x%lx now at offset %ld\n",
1304                         (long)conn->dirptr,curr_dirpos));
1305
1306                 if (!dname) {
1307                         return(False);
1308                 }
1309
1310                 /*
1311                  * fname may get mangled, dname is never mangled.
1312                  * Whenever we're accessing the filesystem we use
1313                  * pathreal which is composed from dname.
1314                  */
1315
1316                 pathreal = NULL;
1317                 fname = dname;
1318
1319                 /* Mangle fname if it's an illegal name. */
1320                 if (mangle_must_mangle(dname,conn->params)) {
1321                         if (!name_to_8_3(dname,mangled_name,True,conn->params)) {
1322                                 TALLOC_FREE(fname);
1323                                 continue; /* Error - couldn't mangle. */
1324                         }
1325                         fname = talloc_strdup(ctx, mangled_name);
1326                         if (!fname) {
1327                                 return False;
1328                         }
1329                 }
1330
1331                 if(!(got_match = *got_exact_match = exact_match(conn, fname, mask))) {
1332                         got_match = mask_match(fname, mask, conn->case_sensitive);
1333                 }
1334
1335                 if(!got_match && check_mangled_names &&
1336                    !mangle_is_8_3(fname, False, conn->params)) {
1337                         /*
1338                          * It turns out that NT matches wildcards against
1339                          * both long *and* short names. This may explain some
1340                          * of the wildcard wierdness from old DOS clients
1341                          * that some people have been seeing.... JRA.
1342                          */
1343                         /* Force the mangling into 8.3. */
1344                         if (!name_to_8_3( fname, mangled_name, False, conn->params)) {
1345                                 TALLOC_FREE(fname);
1346                                 continue; /* Error - couldn't mangle. */
1347                         }
1348
1349                         if(!(got_match = *got_exact_match = exact_match(conn, mangled_name, mask))) {
1350                                 got_match = mask_match(mangled_name, mask, conn->case_sensitive);
1351                         }
1352                 }
1353
1354                 if (got_match) {
1355                         bool isdots = (ISDOT(dname) || ISDOTDOT(dname));
1356
1357                         if (dont_descend && !isdots) {
1358                                 TALLOC_FREE(fname);
1359                                 continue;
1360                         }
1361
1362                         if (needslash) {
1363                                 pathreal = NULL;
1364                                 pathreal = talloc_asprintf(ctx,
1365                                         "%s/%s",
1366                                         conn->dirpath,
1367                                         dname);
1368                         } else {
1369                                 pathreal = talloc_asprintf(ctx,
1370                                         "%s%s",
1371                                         conn->dirpath,
1372                                         dname);
1373                         }
1374
1375                         if (!pathreal) {
1376                                 TALLOC_FREE(fname);
1377                                 return False;
1378                         }
1379
1380                         if (INFO_LEVEL_IS_UNIX(info_level)) {
1381                                 if (SMB_VFS_LSTAT(conn,pathreal,&sbuf) != 0) {
1382                                         DEBUG(5,("get_lanman2_dir_entry:Couldn't lstat [%s] (%s)\n",
1383                                                 pathreal,strerror(errno)));
1384                                         TALLOC_FREE(pathreal);
1385                                         TALLOC_FREE(fname);
1386                                         continue;
1387                                 }
1388                         } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,pathreal,&sbuf) != 0) {
1389                                 /* Needed to show the msdfs symlinks as
1390                                  * directories */
1391
1392                                 ms_dfs_link = check_msdfs_link(conn, pathreal, &sbuf);
1393                                 if (!ms_dfs_link) {
1394                                         DEBUG(5,("get_lanman2_dir_entry:Couldn't stat [%s] (%s)\n",
1395                                                 pathreal,strerror(errno)));
1396                                         TALLOC_FREE(pathreal);
1397                                         TALLOC_FREE(fname);
1398                                         continue;
1399                                 }
1400                         }
1401
1402                         if (ms_dfs_link) {
1403                                 mode = dos_mode_msdfs(conn,pathreal,&sbuf);
1404                         } else {
1405                                 mode = dos_mode(conn,pathreal,&sbuf);
1406                         }
1407
1408                         if (!dir_check_ftype(conn,mode,dirtype)) {
1409                                 DEBUG(5,("get_lanman2_dir_entry: [%s] attribs didn't match %x\n",fname,dirtype));
1410                                 TALLOC_FREE(pathreal);
1411                                 TALLOC_FREE(fname);
1412                                 continue;
1413                         }
1414
1415                         if (!(mode & aDIR)) {
1416                                 file_size = get_file_size_stat(&sbuf);
1417                         }
1418                         allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn,NULL,&sbuf);
1419
1420                         mdate_ts = get_mtimespec(&sbuf);
1421                         adate_ts = get_atimespec(&sbuf);
1422                         create_date_ts = get_create_timespec(&sbuf,
1423                             lp_fake_dir_create_times(SNUM(conn)));
1424
1425                         if (ask_sharemode) {
1426                                 struct timespec write_time_ts;
1427                                 struct file_id fileid;
1428
1429                                 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
1430                                 get_file_infos(fileid, NULL, &write_time_ts);
1431                                 if (!null_timespec(write_time_ts)) {
1432                                         mdate_ts = write_time_ts;
1433                                 }
1434                         }
1435
1436                         if (lp_dos_filetime_resolution(SNUM(conn))) {
1437                                 dos_filetime_timespec(&create_date_ts);
1438                                 dos_filetime_timespec(&mdate_ts);
1439                                 dos_filetime_timespec(&adate_ts);
1440                         }
1441
1442                         create_date = convert_timespec_to_time_t(create_date_ts);
1443                         mdate = convert_timespec_to_time_t(mdate_ts);
1444                         adate = convert_timespec_to_time_t(adate_ts);
1445
1446                         DEBUG(5,("get_lanman2_dir_entry: found %s fname=%s\n",
1447                                 pathreal,fname));
1448
1449                         found = True;
1450
1451                         dptr_DirCacheAdd(conn->dirptr, dname, curr_dirpos);
1452                 }
1453
1454                 if (!found)
1455                         TALLOC_FREE(fname);
1456         }
1457
1458         p = pdata;
1459         last_entry_ptr = p;
1460
1461         nt_extmode = mode ? mode : FILE_ATTRIBUTE_NORMAL;
1462
1463         switch (info_level) {
1464                 case SMB_FIND_INFO_STANDARD:
1465                         DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1466                         if(requires_resume_key) {
1467                                 SIVAL(p,0,reskey);
1468                                 p += 4;
1469                         }
1470                         srv_put_dos_date2(p,0,create_date);
1471                         srv_put_dos_date2(p,4,adate);
1472                         srv_put_dos_date2(p,8,mdate);
1473                         SIVAL(p,12,(uint32)file_size);
1474                         SIVAL(p,16,(uint32)allocation_size);
1475                         SSVAL(p,20,mode);
1476                         p += 23;
1477                         nameptr = p;
1478                         if (flags2 & FLAGS2_UNICODE_STRINGS) {
1479                                 p += ucs2_align(base_data, p, 0);
1480                         }
1481                         len = srvstr_push(base_data, flags2, p,
1482                                           fname, PTR_DIFF(end_data, p),
1483                                           STR_TERMINATE);
1484                         if (flags2 & FLAGS2_UNICODE_STRINGS) {
1485                                 if (len > 2) {
1486                                         SCVAL(nameptr, -1, len - 2);
1487                                 } else {
1488                                         SCVAL(nameptr, -1, 0);
1489                                 }
1490                         } else {
1491                                 if (len > 1) {
1492                                         SCVAL(nameptr, -1, len - 1);
1493                                 } else {
1494                                         SCVAL(nameptr, -1, 0);
1495                                 }
1496                         }
1497                         p += len;
1498                         break;
1499
1500                 case SMB_FIND_EA_SIZE:
1501                         DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_SIZE\n"));
1502                         if(requires_resume_key) {
1503                                 SIVAL(p,0,reskey);
1504                                 p += 4;
1505                         }
1506                         srv_put_dos_date2(p,0,create_date);
1507                         srv_put_dos_date2(p,4,adate);
1508                         srv_put_dos_date2(p,8,mdate);
1509                         SIVAL(p,12,(uint32)file_size);
1510                         SIVAL(p,16,(uint32)allocation_size);
1511                         SSVAL(p,20,mode);
1512                         {
1513                                 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1514                                 SIVAL(p,22,ea_size); /* Extended attributes */
1515                         }
1516                         p += 27;
1517                         nameptr = p - 1;
1518                         len = srvstr_push(base_data, flags2,
1519                                           p, fname, PTR_DIFF(end_data, p),
1520                                           STR_TERMINATE | STR_NOALIGN);
1521                         if (flags2 & FLAGS2_UNICODE_STRINGS) {
1522                                 if (len > 2) {
1523                                         len -= 2;
1524                                 } else {
1525                                         len = 0;
1526                                 }
1527                         } else {
1528                                 if (len > 1) {
1529                                         len -= 1;
1530                                 } else {
1531                                         len = 0;
1532                                 }
1533                         }
1534                         SCVAL(nameptr,0,len);
1535                         p += len;
1536                         SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1537                         break;
1538
1539                 case SMB_FIND_EA_LIST:
1540                 {
1541                         struct ea_list *file_list = NULL;
1542                         size_t ea_len = 0;
1543
1544                         DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_LIST\n"));
1545                         if (!name_list) {
1546                                 return False;
1547                         }
1548                         if(requires_resume_key) {
1549                                 SIVAL(p,0,reskey);
1550                                 p += 4;
1551                         }
1552                         srv_put_dos_date2(p,0,create_date);
1553                         srv_put_dos_date2(p,4,adate);
1554                         srv_put_dos_date2(p,8,mdate);
1555                         SIVAL(p,12,(uint32)file_size);
1556                         SIVAL(p,16,(uint32)allocation_size);
1557                         SSVAL(p,20,mode);
1558                         p += 22; /* p now points to the EA area. */
1559
1560                         file_list = get_ea_list_from_file(ctx, conn, NULL, pathreal, &ea_len);
1561                         name_list = ea_list_union(name_list, file_list, &ea_len);
1562
1563                         /* We need to determine if this entry will fit in the space available. */
1564                         /* Max string size is 255 bytes. */
1565                         if (PTR_DIFF(p + 255 + ea_len,pdata) > space_remaining) {
1566                                 /* Move the dirptr back to prev_dirpos */
1567                                 dptr_SeekDir(conn->dirptr, prev_dirpos);
1568                                 *out_of_space = True;
1569                                 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1570                                 return False; /* Not finished - just out of space */
1571                         }
1572
1573                         /* Push the ea_data followed by the name. */
1574                         p += fill_ea_buffer(ctx, p, space_remaining, conn, name_list);
1575                         nameptr = p;
1576                         len = srvstr_push(base_data, flags2,
1577                                           p + 1, fname, PTR_DIFF(end_data, p+1),
1578                                           STR_TERMINATE | STR_NOALIGN);
1579                         if (flags2 & FLAGS2_UNICODE_STRINGS) {
1580                                 if (len > 2) {
1581                                         len -= 2;
1582                                 } else {
1583                                         len = 0;
1584                                 }
1585                         } else {
1586                                 if (len > 1) {
1587                                         len -= 1;
1588                                 } else {
1589                                         len = 0;
1590                                 }
1591                         }
1592                         SCVAL(nameptr,0,len);
1593                         p += len + 1;
1594                         SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1595                         break;
1596                 }
1597
1598                 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1599                         DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
1600                         was_8_3 = mangle_is_8_3(fname, True, conn->params);
1601                         p += 4;
1602                         SIVAL(p,0,reskey); p += 4;
1603                         put_long_date_timespec(p,create_date_ts); p += 8;
1604                         put_long_date_timespec(p,adate_ts); p += 8;
1605                         put_long_date_timespec(p,mdate_ts); p += 8;
1606                         put_long_date_timespec(p,mdate_ts); p += 8;
1607                         SOFF_T(p,0,file_size); p += 8;
1608                         SOFF_T(p,0,allocation_size); p += 8;
1609                         SIVAL(p,0,nt_extmode); p += 4;
1610                         q = p; p += 4; /* q is placeholder for name length. */
1611                         {
1612                                 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1613                                 SIVAL(p,0,ea_size); /* Extended attributes */
1614                                 p += 4;
1615                         }
1616                         /* Clear the short name buffer. This is
1617                          * IMPORTANT as not doing so will trigger
1618                          * a Win2k client bug. JRA.
1619                          */
1620                         if (!was_8_3 && check_mangled_names) {
1621                                 if (!name_to_8_3(fname,mangled_name,True,
1622                                                    conn->params)) {
1623                                         /* Error - mangle failed ! */
1624                                         memset(mangled_name,'\0',12);
1625                                 }
1626                                 mangled_name[12] = 0;
1627                                 len = srvstr_push(base_data, flags2,
1628                                                   p+2, mangled_name, 24,
1629                                                   STR_UPPER|STR_UNICODE);
1630                                 if (len < 24) {
1631                                         memset(p + 2 + len,'\0',24 - len);
1632                                 }
1633                                 SSVAL(p, 0, len);
1634                         } else {
1635                                 memset(p,'\0',26);
1636                         }
1637                         p += 2 + 24;
1638                         len = srvstr_push(base_data, flags2, p,
1639                                           fname, PTR_DIFF(end_data, p),
1640                                           STR_TERMINATE_ASCII);
1641                         SIVAL(q,0,len);
1642                         p += len;
1643                         SIVAL(p,0,0); /* Ensure any padding is null. */
1644                         len = PTR_DIFF(p, pdata);
1645                         len = (len + 3) & ~3;
1646                         SIVAL(pdata,0,len);
1647                         p = pdata + len;
1648                         break;
1649
1650                 case SMB_FIND_FILE_DIRECTORY_INFO:
1651                         DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
1652                         p += 4;
1653                         SIVAL(p,0,reskey); p += 4;
1654                         put_long_date_timespec(p,create_date_ts); p += 8;
1655                         put_long_date_timespec(p,adate_ts); p += 8;
1656                         put_long_date_timespec(p,mdate_ts); p += 8;
1657                         put_long_date_timespec(p,mdate_ts); p += 8;
1658                         SOFF_T(p,0,file_size); p += 8;
1659                         SOFF_T(p,0,allocation_size); p += 8;
1660                         SIVAL(p,0,nt_extmode); p += 4;
1661                         len = srvstr_push(base_data, flags2,
1662                                           p + 4, fname, PTR_DIFF(end_data, p+4),
1663                                           STR_TERMINATE_ASCII);
1664                         SIVAL(p,0,len);
1665                         p += 4 + len;
1666                         SIVAL(p,0,0); /* Ensure any padding is null. */
1667                         len = PTR_DIFF(p, pdata);
1668                         len = (len + 3) & ~3;
1669                         SIVAL(pdata,0,len);
1670                         p = pdata + len;
1671                         break;
1672
1673                 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1674                         DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
1675                         p += 4;
1676                         SIVAL(p,0,reskey); p += 4;
1677                         put_long_date_timespec(p,create_date_ts); p += 8;
1678                         put_long_date_timespec(p,adate_ts); p += 8;
1679                         put_long_date_timespec(p,mdate_ts); p += 8;
1680                         put_long_date_timespec(p,mdate_ts); p += 8;
1681                         SOFF_T(p,0,file_size); p += 8;
1682                         SOFF_T(p,0,allocation_size); p += 8;
1683                         SIVAL(p,0,nt_extmode); p += 4;
1684                         q = p; p += 4; /* q is placeholder for name length. */
1685                         {
1686                                 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1687                                 SIVAL(p,0,ea_size); /* Extended attributes */
1688                                 p +=4;
1689                         }
1690                         len = srvstr_push(base_data, flags2, p,
1691                                           fname, PTR_DIFF(end_data, p),
1692                                           STR_TERMINATE_ASCII);
1693                         SIVAL(q, 0, len);
1694                         p += len;
1695
1696                         SIVAL(p,0,0); /* Ensure any padding is null. */
1697                         len = PTR_DIFF(p, pdata);
1698                         len = (len + 3) & ~3;
1699                         SIVAL(pdata,0,len);
1700                         p = pdata + len;
1701                         break;
1702
1703                 case SMB_FIND_FILE_NAMES_INFO:
1704                         DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
1705                         p += 4;
1706                         SIVAL(p,0,reskey); p += 4;
1707                         p += 4;
1708                         /* this must *not* be null terminated or w2k gets in a loop trying to set an
1709                            acl on a dir (tridge) */
1710                         len = srvstr_push(base_data, flags2, p,
1711                                           fname, PTR_DIFF(end_data, p),
1712                                           STR_TERMINATE_ASCII);
1713                         SIVAL(p, -4, len);
1714                         p += len;
1715                         SIVAL(p,0,0); /* Ensure any padding is null. */
1716                         len = PTR_DIFF(p, pdata);
1717                         len = (len + 3) & ~3;
1718                         SIVAL(pdata,0,len);
1719                         p = pdata + len;
1720                         break;
1721
1722                 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1723                         DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
1724                         p += 4;
1725                         SIVAL(p,0,reskey); p += 4;
1726                         put_long_date_timespec(p,create_date_ts); p += 8;
1727                         put_long_date_timespec(p,adate_ts); p += 8;
1728                         put_long_date_timespec(p,mdate_ts); p += 8;
1729                         put_long_date_timespec(p,mdate_ts); p += 8;
1730                         SOFF_T(p,0,file_size); p += 8;
1731                         SOFF_T(p,0,allocation_size); p += 8;
1732                         SIVAL(p,0,nt_extmode); p += 4;
1733                         q = p; p += 4; /* q is placeholder for name length. */
1734                         {
1735                                 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1736                                 SIVAL(p,0,ea_size); /* Extended attributes */
1737                                 p +=4;
1738                         }
1739                         SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */
1740                         SIVAL(p,0,sbuf.st_ino); p += 4; /* FileIndexLow */
1741                         SIVAL(p,0,sbuf.st_dev); p += 4; /* FileIndexHigh */
1742                         len = srvstr_push(base_data, flags2, p,
1743                                           fname, PTR_DIFF(end_data, p),
1744                                           STR_TERMINATE_ASCII);
1745                         SIVAL(q, 0, len);
1746                         p += len; 
1747                         SIVAL(p,0,0); /* Ensure any padding is null. */
1748                         len = PTR_DIFF(p, pdata);
1749                         len = (len + 3) & ~3;
1750                         SIVAL(pdata,0,len);
1751                         p = pdata + len;
1752                         break;
1753
1754                 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1755                         DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
1756                         was_8_3 = mangle_is_8_3(fname, True, conn->params);
1757                         p += 4;
1758                         SIVAL(p,0,reskey); p += 4;
1759                         put_long_date_timespec(p,create_date_ts); p += 8;
1760                         put_long_date_timespec(p,adate_ts); p += 8;
1761                         put_long_date_timespec(p,mdate_ts); p += 8;
1762                         put_long_date_timespec(p,mdate_ts); p += 8;
1763                         SOFF_T(p,0,file_size); p += 8;
1764                         SOFF_T(p,0,allocation_size); p += 8;
1765                         SIVAL(p,0,nt_extmode); p += 4;
1766                         q = p; p += 4; /* q is placeholder for name length */
1767                         {
1768                                 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1769                                 SIVAL(p,0,ea_size); /* Extended attributes */
1770                                 p +=4;
1771                         }
1772                         /* Clear the short name buffer. This is
1773                          * IMPORTANT as not doing so will trigger
1774                          * a Win2k client bug. JRA.
1775                          */
1776                         if (!was_8_3 && check_mangled_names) {
1777                                 if (!name_to_8_3(fname,mangled_name,True,
1778                                                 conn->params)) {
1779                                         /* Error - mangle failed ! */
1780                                         memset(mangled_name,'\0',12);
1781                                 }
1782                                 mangled_name[12] = 0;
1783                                 len = srvstr_push(base_data, flags2,
1784                                                   p+2, mangled_name, 24,
1785                                                   STR_UPPER|STR_UNICODE);
1786                                 SSVAL(p, 0, len);
1787                                 if (len < 24) {
1788                                         memset(p + 2 + len,'\0',24 - len);
1789                                 }
1790                                 SSVAL(p, 0, len);
1791                         } else {
1792                                 memset(p,'\0',26);
1793                         }
1794                         p += 26;
1795                         SSVAL(p,0,0); p += 2; /* Reserved ? */
1796                         SIVAL(p,0,sbuf.st_ino); p += 4; /* FileIndexLow */
1797                         SIVAL(p,0,sbuf.st_dev); p += 4; /* FileIndexHigh */
1798                         len = srvstr_push(base_data, flags2, p,
1799                                           fname, PTR_DIFF(end_data, p),
1800                                           STR_TERMINATE_ASCII);
1801                         SIVAL(q,0,len);
1802                         p += len;
1803                         SIVAL(p,0,0); /* Ensure any padding is null. */
1804                         len = PTR_DIFF(p, pdata);
1805                         len = (len + 3) & ~3;
1806                         SIVAL(pdata,0,len);
1807                         p = pdata + len;
1808                         break;
1809
1810                 /* CIFS UNIX Extension. */
1811
1812                 case SMB_FIND_FILE_UNIX:
1813                 case SMB_FIND_FILE_UNIX_INFO2:
1814                         p+= 4;
1815                         SIVAL(p,0,reskey); p+= 4;    /* Used for continuing search. */
1816
1817                         /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
1818
1819                         if (info_level == SMB_FIND_FILE_UNIX) {
1820                                 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX\n"));
1821                                 p = store_file_unix_basic(conn, p,
1822                                                         NULL, &sbuf);
1823                                 len = srvstr_push(base_data, flags2, p,
1824                                                   fname, PTR_DIFF(end_data, p),
1825                                                   STR_TERMINATE);
1826                         } else {
1827                                 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n"));
1828                                 p = store_file_unix_basic_info2(conn, p,
1829                                                         NULL, &sbuf);
1830                                 nameptr = p;
1831                                 p += 4;
1832                                 len = srvstr_push(base_data, flags2, p, fname,
1833                                                   PTR_DIFF(end_data, p), 0);
1834                                 SIVAL(nameptr, 0, len);
1835                         }
1836
1837                         p += len;
1838                         SIVAL(p,0,0); /* Ensure any padding is null. */
1839
1840                         len = PTR_DIFF(p, pdata);
1841                         len = (len + 3) & ~3;
1842                         SIVAL(pdata,0,len);     /* Offset from this structure to the beginning of the next one */
1843                         p = pdata + len;
1844                         /* End of SMB_QUERY_FILE_UNIX_BASIC */
1845
1846                         break;
1847
1848                 default:
1849                         TALLOC_FREE(fname);
1850                         return(False);
1851         }
1852
1853         TALLOC_FREE(fname);
1854         if (PTR_DIFF(p,pdata) > space_remaining) {
1855                 /* Move the dirptr back to prev_dirpos */
1856                 dptr_SeekDir(conn->dirptr, prev_dirpos);
1857                 *out_of_space = True;
1858                 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1859                 return False; /* Not finished - just out of space */
1860         }
1861
1862         /* Setup the last entry pointer, as an offset from base_data */
1863         *last_entry_off = PTR_DIFF(last_entry_ptr,base_data);
1864         /* Advance the data pointer to the next slot */
1865         *ppdata = p;
1866
1867         return(found);
1868 }
1869
1870 /****************************************************************************
1871  Reply to a TRANS2_FINDFIRST.
1872 ****************************************************************************/
1873
1874 static void call_trans2findfirst(connection_struct *conn,
1875                                  struct smb_request *req,
1876                                  char **pparams, int total_params,
1877                                  char **ppdata, int total_data,
1878                                  unsigned int max_data_bytes)
1879 {
1880         /* We must be careful here that we don't return more than the
1881                 allowed number of data bytes. If this means returning fewer than
1882                 maxentries then so be it. We assume that the redirector has
1883                 enough room for the fixed number of parameter bytes it has
1884                 requested. */
1885         char *params = *pparams;
1886         char *pdata = *ppdata;
1887         char *data_end;
1888         uint32 dirtype;
1889         int maxentries;
1890         uint16 findfirst_flags;
1891         bool close_after_first;
1892         bool close_if_end;
1893         bool requires_resume_key;
1894         int info_level;
1895         char *directory = NULL;
1896         char *mask = NULL;
1897         char *p;
1898         int last_entry_off=0;
1899         int dptr_num = -1;
1900         int numentries = 0;
1901         int i;
1902         bool finished = False;
1903         bool dont_descend = False;
1904         bool out_of_space = False;
1905         int space_remaining;
1906         bool mask_contains_wcard = False;
1907         SMB_STRUCT_STAT sbuf;
1908         struct ea_list *ea_list = NULL;
1909         NTSTATUS ntstatus = NT_STATUS_OK;
1910         bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
1911         TALLOC_CTX *ctx = talloc_tos();
1912
1913         if (total_params < 13) {
1914                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1915                 return;
1916         }
1917
1918         dirtype = SVAL(params,0);
1919         maxentries = SVAL(params,2);
1920         findfirst_flags = SVAL(params,4);
1921         close_after_first = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE);
1922         close_if_end = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
1923         requires_resume_key = (findfirst_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
1924         info_level = SVAL(params,6);
1925
1926         DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \
1927 close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n",
1928                 (unsigned int)dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
1929                 info_level, max_data_bytes));
1930
1931         if (!maxentries) {
1932                 /* W2K3 seems to treat zero as 1. */
1933                 maxentries = 1;
1934         }
1935
1936         switch (info_level) {
1937                 case SMB_FIND_INFO_STANDARD:
1938                 case SMB_FIND_EA_SIZE:
1939                 case SMB_FIND_EA_LIST:
1940                 case SMB_FIND_FILE_DIRECTORY_INFO:
1941                 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1942                 case SMB_FIND_FILE_NAMES_INFO:
1943                 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1944                 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1945                 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1946                         break;
1947                 case SMB_FIND_FILE_UNIX:
1948                 case SMB_FIND_FILE_UNIX_INFO2:
1949                         /* Always use filesystem for UNIX mtime query. */
1950                         ask_sharemode = false;
1951                         if (!lp_unix_extensions()) {
1952                                 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
1953                                 return;
1954                         }
1955                         break;
1956                 default:
1957                         reply_nterror(req, NT_STATUS_INVALID_LEVEL);
1958                         return;
1959         }
1960
1961         srvstr_get_path_wcard(ctx, params, req->flags2, &directory,
1962                               params+12, total_params - 12,
1963                               STR_TERMINATE, &ntstatus, &mask_contains_wcard);
1964         if (!NT_STATUS_IS_OK(ntstatus)) {
1965                 reply_nterror(req, ntstatus);
1966                 return;
1967         }
1968
1969         ntstatus = resolve_dfspath_wcard(ctx, conn,
1970                         req->flags2 & FLAGS2_DFS_PATHNAMES,
1971                         directory,
1972                         &directory,
1973                         &mask_contains_wcard);
1974         if (!NT_STATUS_IS_OK(ntstatus)) {
1975                 if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_PATH_NOT_COVERED)) {
1976                         reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1977                                         ERRSRV, ERRbadpath);
1978                         return;
1979                 }
1980                 reply_nterror(req, ntstatus);
1981                 return;
1982         }
1983
1984         ntstatus = unix_convert(ctx, conn, directory, True, &directory, &mask, &sbuf);
1985         if (!NT_STATUS_IS_OK(ntstatus)) {
1986                 reply_nterror(req, ntstatus);
1987                 return;
1988         }
1989
1990         ntstatus = check_name(conn, directory);
1991         if (!NT_STATUS_IS_OK(ntstatus)) {
1992                 reply_nterror(req, ntstatus);
1993                 return;
1994         }
1995
1996         p = strrchr_m(directory,'/');
1997         if(p == NULL) {
1998                 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
1999                 if((directory[0] == '.') && (directory[1] == '\0')) {
2000                         mask = talloc_strdup(ctx,"*");
2001                         if (!mask) {
2002                                 reply_nterror(req, NT_STATUS_NO_MEMORY);
2003                                 return;
2004                         }
2005                         mask_contains_wcard = True;
2006                 }
2007                 directory = talloc_strdup(talloc_tos(), "./");
2008                 if (!directory) {
2009                         reply_nterror(req, NT_STATUS_NO_MEMORY);
2010                         return;
2011                 }
2012         } else {
2013                 *p = 0;
2014         }
2015
2016         DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
2017
2018         if (info_level == SMB_FIND_EA_LIST) {
2019                 uint32 ea_size;
2020
2021                 if (total_data < 4) {
2022                         reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2023                         return;
2024                 }
2025
2026                 ea_size = IVAL(pdata,0);
2027                 if (ea_size != total_data) {
2028                         DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
2029 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2030                         reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2031                         return;
2032                 }
2033
2034                 if (!lp_ea_support(SNUM(conn))) {
2035                         reply_doserror(req, ERRDOS, ERReasnotsupported);
2036                         return;
2037                 }
2038
2039                 /* Pull out the list of names. */
2040                 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2041                 if (!ea_list) {
2042                         reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2043                         return;
2044                 }
2045         }
2046
2047         *ppdata = (char *)SMB_REALLOC(
2048                 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2049         if(*ppdata == NULL ) {
2050                 reply_nterror(req, NT_STATUS_NO_MEMORY);
2051                 return;
2052         }
2053         pdata = *ppdata;
2054         data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2055
2056         /* Realloc the params space */
2057         *pparams = (char *)SMB_REALLOC(*pparams, 10);
2058         if (*pparams == NULL) {
2059                 reply_nterror(req, NT_STATUS_NO_MEMORY);
2060                 return;
2061         }
2062         params = *pparams;
2063
2064         /* Save the wildcard match and attribs we are using on this directory -
2065                 needed as lanman2 assumes these are being saved between calls */
2066
2067         ntstatus = dptr_create(conn,
2068                                 directory,
2069                                 False,
2070                                 True,
2071                                 req->smbpid,
2072                                 mask,
2073                                 mask_contains_wcard,
2074                                 dirtype,
2075                                 &conn->dirptr);
2076
2077         if (!NT_STATUS_IS_OK(ntstatus)) {
2078                 reply_nterror(req, ntstatus);
2079                 return;
2080         }
2081
2082         dptr_num = dptr_dnum(conn->dirptr);
2083         DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n", dptr_num, mask, dirtype));
2084
2085         /* Initialize per TRANS2_FIND_FIRST operation data */
2086         dptr_init_search_op(conn->dirptr);
2087
2088         /* We don't need to check for VOL here as this is returned by
2089                 a different TRANS2 call. */
2090
2091         DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n", conn->dirpath,lp_dontdescend(SNUM(conn))));
2092         if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
2093                 dont_descend = True;
2094
2095         p = pdata;
2096         space_remaining = max_data_bytes;
2097         out_of_space = False;
2098
2099         for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
2100                 bool got_exact_match = False;
2101
2102                 /* this is a heuristic to avoid seeking the dirptr except when
2103                         absolutely necessary. It allows for a filename of about 40 chars */
2104                 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2105                         out_of_space = True;
2106                         finished = False;
2107                 } else {
2108                         finished = !get_lanman2_dir_entry(ctx,
2109                                         conn,
2110                                         req->flags2,
2111                                         mask,dirtype,info_level,
2112                                         requires_resume_key,dont_descend,
2113                                         ask_sharemode,
2114                                         &p,pdata,data_end,
2115                                         space_remaining, &out_of_space,
2116                                         &got_exact_match,
2117                                         &last_entry_off, ea_list);
2118                 }
2119
2120                 if (finished && out_of_space)
2121                         finished = False;
2122
2123                 if (!finished && !out_of_space)
2124                         numentries++;
2125
2126                 /*
2127                  * As an optimisation if we know we aren't looking
2128                  * for a wildcard name (ie. the name matches the wildcard exactly)
2129                  * then we can finish on any (first) match.
2130                  * This speeds up large directory searches. JRA.
2131                  */
2132
2133                 if(got_exact_match)
2134                         finished = True;
2135
2136                 /* Ensure space_remaining never goes -ve. */
2137                 if (PTR_DIFF(p,pdata) > max_data_bytes) {
2138                         space_remaining = 0;
2139                         out_of_space = true;
2140                 } else {
2141                         space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2142                 }
2143         }
2144
2145         /* Check if we can close the dirptr */
2146         if(close_after_first || (finished && close_if_end)) {
2147                 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
2148                 dptr_close(&dptr_num);
2149         }
2150
2151         /*
2152          * If there are no matching entries we must return ERRDOS/ERRbadfile -
2153          * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
2154          * the protocol level is less than NT1. Tested with smbclient. JRA.
2155          * This should fix the OS/2 client bug #2335.
2156          */
2157
2158         if(numentries == 0) {
2159                 dptr_close(&dptr_num);
2160                 if (Protocol < PROTOCOL_NT1) {
2161                         reply_doserror(req, ERRDOS, ERRnofiles);
2162                         return;
2163                 } else {
2164                         reply_botherror(req, NT_STATUS_NO_SUCH_FILE,
2165                                         ERRDOS, ERRbadfile);
2166                         return;
2167                 }
2168         }
2169
2170         /* At this point pdata points to numentries directory entries. */
2171
2172         /* Set up the return parameter block */
2173         SSVAL(params,0,dptr_num);
2174         SSVAL(params,2,numentries);
2175         SSVAL(params,4,finished);
2176         SSVAL(params,6,0); /* Never an EA error */
2177         SSVAL(params,8,last_entry_off);
2178
2179         send_trans2_replies(conn, req, params, 10, pdata, PTR_DIFF(p,pdata),
2180                             max_data_bytes);
2181
2182         if ((! *directory) && dptr_path(dptr_num)) {
2183                 directory = talloc_strdup(talloc_tos(),dptr_path(dptr_num));
2184                 if (!directory) {
2185                         reply_nterror(req, NT_STATUS_NO_MEMORY);
2186                 }
2187         }
2188
2189         DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2190                 smb_fn_name(req->cmd),
2191                 mask, directory, dirtype, numentries ) );
2192
2193         /*
2194          * Force a name mangle here to ensure that the
2195          * mask as an 8.3 name is top of the mangled cache.
2196          * The reasons for this are subtle. Don't remove
2197          * this code unless you know what you are doing
2198          * (see PR#13758). JRA.
2199          */
2200
2201         if(!mangle_is_8_3_wildcards( mask, False, conn->params)) {
2202                 char mangled_name[13];
2203                 name_to_8_3(mask, mangled_name, True, conn->params);
2204         }
2205
2206         return;
2207 }
2208
2209 /****************************************************************************
2210  Reply to a TRANS2_FINDNEXT.
2211 ****************************************************************************/
2212
2213 static void call_trans2findnext(connection_struct *conn,
2214                                 struct smb_request *req,
2215                                 char **pparams, int total_params,
2216                                 char **ppdata, int total_data,
2217                                 unsigned int max_data_bytes)
2218 {
2219         /* We must be careful here that we don't return more than the
2220                 allowed number of data bytes. If this means returning fewer than
2221                 maxentries then so be it. We assume that the redirector has
2222                 enough room for the fixed number of parameter bytes it has
2223                 requested. */
2224         char *params = *pparams;
2225         char *pdata = *ppdata;
2226         char *data_end;
2227         int dptr_num;
2228         int maxentries;
2229         uint16 info_level;
2230         uint32 resume_key;
2231         uint16 findnext_flags;
2232         bool close_after_request;
2233         bool close_if_end;
2234         bool requires_resume_key;
2235         bool continue_bit;
2236         bool mask_contains_wcard = False;
2237         char *resume_name = NULL;
2238         const char *mask = NULL;
2239         const char *directory = NULL;
2240         char *p = NULL;
2241         uint16 dirtype;
2242         int numentries = 0;
2243         int i, last_entry_off=0;
2244         bool finished = False;
2245         bool dont_descend = False;
2246         bool out_of_space = False;
2247         int space_remaining;
2248         struct ea_list *ea_list = NULL;
2249         NTSTATUS ntstatus = NT_STATUS_OK;
2250         bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
2251         TALLOC_CTX *ctx = talloc_tos();
2252
2253         if (total_params < 13) {
2254                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2255                 return;
2256         }
2257
2258         dptr_num = SVAL(params,0);
2259         maxentries = SVAL(params,2);
2260         info_level = SVAL(params,4);
2261         resume_key = IVAL(params,6);
2262         findnext_flags = SVAL(params,10);
2263         close_after_request = (findnext_flags & FLAG_TRANS2_FIND_CLOSE);
2264         close_if_end = (findnext_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2265         requires_resume_key = (findnext_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2266         continue_bit = (findnext_flags & FLAG_TRANS2_FIND_CONTINUE);
2267
2268         srvstr_get_path_wcard(ctx, params, req->flags2, &resume_name,
2269                               params+12,
2270                               total_params - 12, STR_TERMINATE, &ntstatus,
2271                               &mask_contains_wcard);
2272         if (!NT_STATUS_IS_OK(ntstatus)) {
2273                 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
2274                    complain (it thinks we're asking for the directory above the shared
2275                    path or an invalid name). Catch this as the resume name is only compared, never used in
2276                    a file access. JRA. */
2277                 srvstr_pull_talloc(ctx, params, req->flags2,
2278                                 &resume_name, params+12,
2279                                 total_params - 12,
2280                                 STR_TERMINATE);
2281
2282                 if (!resume_name || !(ISDOT(resume_name) || ISDOTDOT(resume_name))) {
2283                         reply_nterror(req, ntstatus);
2284                         return;
2285                 }
2286         }
2287
2288         DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
2289 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
2290 resume_key = %d resume name = %s continue=%d level = %d\n",
2291                 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end, 
2292                 requires_resume_key, resume_key, resume_name, continue_bit, info_level));
2293
2294         if (!maxentries) {
2295                 /* W2K3 seems to treat zero as 1. */
2296                 maxentries = 1;
2297         }
2298
2299         switch (info_level) {
2300                 case SMB_FIND_INFO_STANDARD:
2301                 case SMB_FIND_EA_SIZE:
2302                 case SMB_FIND_EA_LIST:
2303                 case SMB_FIND_FILE_DIRECTORY_INFO:
2304                 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2305                 case SMB_FIND_FILE_NAMES_INFO:
2306                 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2307                 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2308                 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2309                         break;
2310                 case SMB_FIND_FILE_UNIX:
2311                 case SMB_FIND_FILE_UNIX_INFO2:
2312                         /* Always use filesystem for UNIX mtime query. */
2313                         ask_sharemode = false;
2314                         if (!lp_unix_extensions()) {
2315                                 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2316                                 return;
2317                         }
2318                         break;
2319                 default:
2320                         reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2321                         return;
2322         }
2323
2324         if (info_level == SMB_FIND_EA_LIST) {
2325                 uint32 ea_size;
2326
2327                 if (total_data < 4) {
2328                         reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2329                         return;
2330                 }
2331
2332                 ea_size = IVAL(pdata,0);
2333                 if (ea_size != total_data) {
2334                         DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
2335 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2336                         reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2337                         return;
2338                 }
2339
2340                 if (!lp_ea_support(SNUM(conn))) {
2341                         reply_doserror(req, ERRDOS, ERReasnotsupported);
2342                         return;
2343                 }
2344
2345                 /* Pull out the list of names. */
2346                 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2347                 if (!ea_list) {
2348                         reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2349                         return;
2350                 }
2351         }
2352
2353         *ppdata = (char *)SMB_REALLOC(
2354                 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2355         if(*ppdata == NULL) {
2356                 reply_nterror(req, NT_STATUS_NO_MEMORY);
2357                 return;
2358         }
2359
2360         pdata = *ppdata;
2361         data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2362
2363         /* Realloc the params space */
2364         *pparams = (char *)SMB_REALLOC(*pparams, 6*SIZEOFWORD);
2365         if(*pparams == NULL ) {
2366                 reply_nterror(req, NT_STATUS_NO_MEMORY);
2367                 return;
2368         }
2369
2370         params = *pparams;
2371
2372         /* Check that the dptr is valid */
2373         if(!(conn->dirptr = dptr_fetch_lanman2(dptr_num))) {
2374                 reply_doserror(req, ERRDOS, ERRnofiles);
2375                 return;
2376         }
2377
2378         string_set(&conn->dirpath,dptr_path(dptr_num));
2379
2380         /* Get the wildcard mask from the dptr */
2381         if((p = dptr_wcard(dptr_num))== NULL) {
2382                 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
2383                 reply_doserror(req, ERRDOS, ERRnofiles);
2384                 return;
2385         }
2386
2387         mask = p;
2388         directory = conn->dirpath;
2389
2390         /* Get the attr mask from the dptr */
2391         dirtype = dptr_attr(dptr_num);
2392
2393         DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld)\n",
2394                 dptr_num, mask, dirtype,
2395                 (long)conn->dirptr,
2396                 dptr_TellDir(conn->dirptr)));
2397
2398         /* Initialize per TRANS2_FIND_NEXT operation data */
2399         dptr_init_search_op(conn->dirptr);
2400
2401         /* We don't need to check for VOL here as this is returned by
2402                 a different TRANS2 call. */
2403
2404         DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",conn->dirpath,lp_dontdescend(SNUM(conn))));
2405         if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
2406                 dont_descend = True;
2407
2408         p = pdata;
2409         space_remaining = max_data_bytes;
2410         out_of_space = False;
2411
2412         /*
2413          * Seek to the correct position. We no longer use the resume key but
2414          * depend on the last file name instead.
2415          */
2416
2417         if(*resume_name && !continue_bit) {
2418                 SMB_STRUCT_STAT st;
2419
2420                 long current_pos = 0;
2421                 /*
2422                  * Remember, name_to_8_3 is called by
2423                  * get_lanman2_dir_entry(), so the resume name
2424                  * could be mangled. Ensure we check the unmangled name.
2425                  */
2426
2427                 if (mangle_is_mangled(resume_name, conn->params)) {
2428                         char *new_resume_name = NULL;
2429                         mangle_lookup_name_from_8_3(ctx,
2430                                                 resume_name,
2431                                                 &new_resume_name,
2432                                                 conn->params);
2433                         if (new_resume_name) {
2434                                 resume_name = new_resume_name;
2435                         }
2436                 }
2437
2438                 /*
2439                  * Fix for NT redirector problem triggered by resume key indexes
2440                  * changing between directory scans. We now return a resume key of 0
2441                  * and instead look for the filename to continue from (also given
2442                  * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
2443                  * findfirst/findnext (as is usual) then the directory pointer
2444                  * should already be at the correct place.
2445                  */
2446
2447                 finished = !dptr_SearchDir(conn->dirptr, resume_name, &current_pos, &st);
2448         } /* end if resume_name && !continue_bit */
2449
2450         for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
2451                 bool got_exact_match = False;
2452
2453                 /* this is a heuristic to avoid seeking the dirptr except when 
2454                         absolutely necessary. It allows for a filename of about 40 chars */
2455                 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2456                         out_of_space = True;
2457                         finished = False;
2458                 } else {
2459                         finished = !get_lanman2_dir_entry(ctx,
2460                                                 conn,
2461                                                 req->flags2,
2462                                                 mask,dirtype,info_level,
2463                                                 requires_resume_key,dont_descend,
2464                                                 ask_sharemode,
2465                                                 &p,pdata,data_end,
2466                                                 space_remaining, &out_of_space,
2467                                                 &got_exact_match,
2468                                                 &last_entry_off, ea_list);
2469                 }
2470
2471                 if (finished && out_of_space)
2472                         finished = False;
2473
2474                 if (!finished && !out_of_space)
2475                         numentries++;
2476
2477                 /*
2478                  * As an optimisation if we know we aren't looking
2479                  * for a wildcard name (ie. the name matches the wildcard exactly)
2480                  * then we can finish on any (first) match.
2481                  * This speeds up large directory searches. JRA.
2482                  */
2483
2484                 if(got_exact_match)
2485                         finished = True;
2486
2487                 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2488         }
2489
2490         DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2491                 smb_fn_name(req->cmd),
2492                 mask, directory, dirtype, numentries ) );
2493
2494         /* Check if we can close the dirptr */
2495         if(close_after_request || (finished && close_if_end)) {
2496                 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
2497                 dptr_close(&dptr_num); /* This frees up the saved mask */
2498         }
2499
2500         /* Set up the return parameter block */
2501         SSVAL(params,0,numentries);
2502         SSVAL(params,2,finished);
2503         SSVAL(params,4,0); /* Never an EA error */
2504         SSVAL(params,6,last_entry_off);
2505
2506         send_trans2_replies(conn, req, params, 8, pdata, PTR_DIFF(p,pdata),
2507                             max_data_bytes);
2508
2509         return;
2510 }
2511
2512 unsigned char *create_volume_objectid(connection_struct *conn, unsigned char objid[16])
2513 {
2514         E_md4hash(lp_servicename(SNUM(conn)),objid);
2515         return objid;
2516 }
2517
2518 static void samba_extended_info_version(struct smb_extended_info *extended_info)
2519 {
2520         SMB_ASSERT(extended_info != NULL);
2521
2522         extended_info->samba_magic = SAMBA_EXTENDED_INFO_MAGIC;
2523         extended_info->samba_version = ((SAMBA_VERSION_MAJOR & 0xff) << 24)
2524                                        | ((SAMBA_VERSION_MINOR & 0xff) << 16)
2525                                        | ((SAMBA_VERSION_RELEASE & 0xff) << 8);
2526 #ifdef SAMBA_VERSION_REVISION
2527         extended_info->samba_version |= (tolower(*SAMBA_VERSION_REVISION) - 'a' + 1) & 0xff;
2528 #endif
2529         extended_info->samba_subversion = 0;
2530 #ifdef SAMBA_VERSION_RC_RELEASE
2531         extended_info->samba_subversion |= (SAMBA_VERSION_RC_RELEASE & 0xff) << 24;
2532 #else
2533 #ifdef SAMBA_VERSION_PRE_RELEASE
2534         extended_info->samba_subversion |= (SAMBA_VERSION_PRE_RELEASE & 0xff) << 16;
2535 #endif
2536 #endif
2537 #ifdef SAMBA_VERSION_VENDOR_PATCH
2538         extended_info->samba_subversion |= (SAMBA_VERSION_VENDOR_PATCH & 0xffff);
2539 #endif
2540         extended_info->samba_gitcommitdate = 0;
2541 #ifdef SAMBA_VERSION_GIT_COMMIT_TIME
2542         unix_to_nt_time(&extended_info->samba_gitcommitdate, SAMBA_VERSION_GIT_COMMIT_TIME);
2543 #endif
2544
2545         memset(extended_info->samba_version_string, 0,
2546                sizeof(extended_info->samba_version_string));
2547
2548         snprintf (extended_info->samba_version_string,
2549                   sizeof(extended_info->samba_version_string),
2550                   "%s", samba_version_string());
2551 }
2552
2553 /****************************************************************************
2554  Reply to a TRANS2_QFSINFO (query filesystem info).
2555 ****************************************************************************/
2556
2557 static void call_trans2qfsinfo(connection_struct *conn,
2558                                struct smb_request *req,
2559                                char **pparams, int total_params,
2560                                char **ppdata, int total_data,
2561                                unsigned int max_data_bytes)
2562 {
2563         char *pdata, *end_data;
2564         char *params = *pparams;
2565         uint16 info_level;
2566         int data_len, len;
2567         SMB_STRUCT_STAT st;
2568         const char *vname = volume_label(SNUM(conn));
2569         int snum = SNUM(conn);
2570         char *fstype = lp_fstype(SNUM(conn));
2571         uint32 additional_flags = 0;
2572         
2573         if (total_params < 2) {
2574                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2575                 return;
2576         }
2577
2578         info_level = SVAL(params,0);
2579
2580         if (IS_IPC(conn)) {
2581                 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
2582                         DEBUG(0,("call_trans2qfsinfo: not an allowed "
2583                                 "info level (0x%x) on IPC$.\n",
2584                                 (unsigned int)info_level));
2585                         reply_nterror(req, NT_STATUS_ACCESS_DENIED);
2586                         return;
2587                 }
2588         }
2589
2590         if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
2591                 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
2592                         DEBUG(0,("call_trans2qfsinfo: encryption required "
2593                                 "and info level 0x%x sent.\n",
2594                                 (unsigned int)info_level));
2595                         exit_server_cleanly("encryption required "
2596                                 "on connection");
2597                         return;
2598                 }
2599         }
2600
2601         DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
2602
2603         if(SMB_VFS_STAT(conn,".",&st)!=0) {
2604                 DEBUG(2,("call_trans2qfsinfo: stat of . failed (%s)\n", strerror(errno)));
2605                 reply_doserror(req, ERRSRV, ERRinvdevice);
2606                 return;
2607         }
2608
2609         *ppdata = (char *)SMB_REALLOC(
2610                 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2611         if (*ppdata == NULL ) {
2612                 reply_nterror(req, NT_STATUS_NO_MEMORY);
2613                 return;
2614         }
2615
2616         pdata = *ppdata;
2617         memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2618         end_data = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2619
2620         switch (info_level) {
2621                 case SMB_INFO_ALLOCATION:
2622                 {
2623                         uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2624                         data_len = 18;
2625                         if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
2626                                 reply_unixerror(req, ERRHRD, ERRgeneral);
2627                                 return;
2628                         }
2629
2630                         block_size = lp_block_size(snum);
2631                         if (bsize < block_size) {
2632                                 uint64_t factor = block_size/bsize;
2633                                 bsize = block_size;
2634                                 dsize /= factor;
2635                                 dfree /= factor;
2636                         }
2637                         if (bsize > block_size) {
2638                                 uint64_t factor = bsize/block_size;
2639                                 bsize = block_size;
2640                                 dsize *= factor;
2641                                 dfree *= factor;
2642                         }
2643                         bytes_per_sector = 512;
2644                         sectors_per_unit = bsize/bytes_per_sector;
2645
2646                         DEBUG(5,("call_trans2qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
2647 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
2648                                 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2649
2650                         SIVAL(pdata,l1_idFileSystem,st.st_dev);
2651                         SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
2652                         SIVAL(pdata,l1_cUnit,dsize);
2653                         SIVAL(pdata,l1_cUnitAvail,dfree);
2654                         SSVAL(pdata,l1_cbSector,bytes_per_sector);
2655                         break;
2656                 }
2657
2658                 case SMB_INFO_VOLUME:
2659                         /* Return volume name */
2660                         /* 
2661                          * Add volume serial number - hash of a combination of
2662                          * the called hostname and the service name.
2663                          */
2664                         SIVAL(pdata,0,str_checksum(lp_servicename(snum)) ^ (str_checksum(get_local_machine_name())<<16) );
2665                         /*
2666                          * Win2k3 and previous mess this up by sending a name length
2667                          * one byte short. I believe only older clients (OS/2 Win9x) use
2668                          * this call so try fixing this by adding a terminating null to
2669                          * the pushed string. The change here was adding the STR_TERMINATE. JRA.
2670                          */
2671                         len = srvstr_push(
2672                                 pdata, req->flags2,
2673                                 pdata+l2_vol_szVolLabel, vname,
2674                                 PTR_DIFF(end_data, pdata+l2_vol_szVolLabel),
2675                                 STR_NOALIGN|STR_TERMINATE);
2676                         SCVAL(pdata,l2_vol_cch,len);
2677                         data_len = l2_vol_szVolLabel + len;
2678                         DEBUG(5,("call_trans2qfsinfo : time = %x, namelen = %d, name = %s\n",
2679                                 (unsigned)st.st_ctime, len, vname));
2680                         break;
2681
2682                 case SMB_QUERY_FS_ATTRIBUTE_INFO:
2683                 case SMB_FS_ATTRIBUTE_INFORMATION:
2684
2685                         additional_flags = 0;
2686 #if defined(HAVE_SYS_QUOTAS)
2687                         additional_flags |= FILE_VOLUME_QUOTAS;
2688 #endif
2689
2690                         if(lp_nt_acl_support(SNUM(conn))) {
2691                                 additional_flags |= FILE_PERSISTENT_ACLS;
2692                         }
2693
2694                         /* Capabilities are filled in at connection time through STATVFS call */
2695                         additional_flags |= conn->fs_capabilities;
2696
2697                         SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
2698                                 FILE_SUPPORTS_OBJECT_IDS|FILE_UNICODE_ON_DISK|
2699                                 additional_flags); /* FS ATTRIBUTES */
2700
2701                         SIVAL(pdata,4,255); /* Max filename component length */
2702                         /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
2703                                 and will think we can't do long filenames */
2704                         len = srvstr_push(pdata, req->flags2, pdata+12, fstype,
2705                                           PTR_DIFF(end_data, pdata+12),
2706                                           STR_UNICODE);
2707                         SIVAL(pdata,8,len);
2708                         data_len = 12 + len;
2709                         break;
2710
2711                 case SMB_QUERY_FS_LABEL_INFO:
2712                 case SMB_FS_LABEL_INFORMATION:
2713                         len = srvstr_push(pdata, req->flags2, pdata+4, vname,
2714                                           PTR_DIFF(end_data, pdata+4), 0);
2715                         data_len = 4 + len;
2716                         SIVAL(pdata,0,len);
2717                         break;
2718
2719                 case SMB_QUERY_FS_VOLUME_INFO:      
2720                 case SMB_FS_VOLUME_INFORMATION:
2721
2722                         /* 
2723                          * Add volume serial number - hash of a combination of
2724                          * the called hostname and the service name.
2725                          */
2726                         SIVAL(pdata,8,str_checksum(lp_servicename(snum)) ^ 
2727                                 (str_checksum(get_local_machine_name())<<16));
2728
2729                         /* Max label len is 32 characters. */
2730                         len = srvstr_push(pdata, req->flags2, pdata+18, vname,
2731                                           PTR_DIFF(end_data, pdata+18),
2732                                           STR_UNICODE);
2733                         SIVAL(pdata,12,len);
2734                         data_len = 18+len;
2735
2736                         DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n", 
2737                                 (int)strlen(vname),vname, lp_servicename(snum)));
2738                         break;
2739
2740                 case SMB_QUERY_FS_SIZE_INFO:
2741                 case SMB_FS_SIZE_INFORMATION:
2742                 {
2743                         uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2744                         data_len = 24;
2745                         if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
2746                                 reply_unixerror(req, ERRHRD, ERRgeneral);
2747                                 return;
2748                         }
2749                         block_size = lp_block_size(snum);
2750                         if (bsize < block_size) {
2751                                 uint64_t factor = block_size/bsize;
2752                                 bsize = block_size;
2753                                 dsize /= factor;
2754                                 dfree /= factor;
2755                         }
2756                         if (bsize > block_size) {
2757                                 uint64_t factor = bsize/block_size;
2758                                 bsize = block_size;
2759                                 dsize *= factor;
2760                                 dfree *= factor;
2761                         }
2762                         bytes_per_sector = 512;
2763                         sectors_per_unit = bsize/bytes_per_sector;
2764                         DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2765 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2766                                 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2767                         SBIG_UINT(pdata,0,dsize);
2768                         SBIG_UINT(pdata,8,dfree);
2769                         SIVAL(pdata,16,sectors_per_unit);
2770                         SIVAL(pdata,20,bytes_per_sector);
2771                         break;
2772                 }
2773
2774                 case SMB_FS_FULL_SIZE_INFORMATION:
2775                 {
2776                         uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2777                         data_len = 32;
2778                         if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
2779                                 reply_unixerror(req, ERRHRD, ERRgeneral);
2780                                 return;
2781                         }
2782                         block_size = lp_block_size(snum);
2783                         if (bsize < block_size) {
2784                                 uint64_t factor = block_size/bsize;
2785                                 bsize = block_size;
2786                                 dsize /= factor;
2787                                 dfree /= factor;
2788                         }
2789                         if (bsize > block_size) {
2790                                 uint64_t factor = bsize/block_size;
2791                                 bsize = block_size;
2792                                 dsize *= factor;
2793                                 dfree *= factor;
2794                         }
2795                         bytes_per_sector = 512;
2796                         sectors_per_unit = bsize/bytes_per_sector;
2797                         DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2798 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2799                                 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2800                         SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
2801                         SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
2802                         SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
2803                         SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
2804                         SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
2805                         break;
2806                 }
2807
2808                 case SMB_QUERY_FS_DEVICE_INFO:
2809                 case SMB_FS_DEVICE_INFORMATION:
2810                         data_len = 8;
2811                         SIVAL(pdata,0,0); /* dev type */
2812                         SIVAL(pdata,4,0); /* characteristics */
2813                         break;
2814
2815 #ifdef HAVE_SYS_QUOTAS
2816                 case SMB_FS_QUOTA_INFORMATION:
2817                 /* 
2818                  * what we have to send --metze:
2819                  *
2820                  * Unknown1:            24 NULL bytes
2821                  * Soft Quota Treshold: 8 bytes seems like uint64_t or so
2822                  * Hard Quota Limit:    8 bytes seems like uint64_t or so
2823                  * Quota Flags:         2 byte :
2824                  * Unknown3:            6 NULL bytes
2825                  *
2826                  * 48 bytes total
2827                  * 
2828                  * details for Quota Flags:
2829                  * 
2830                  * 0x0020 Log Limit: log if the user exceeds his Hard Quota
2831                  * 0x0010 Log Warn:  log if the user exceeds his Soft Quota
2832                  * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
2833                  * 0x0001 Enable Quotas: enable quota for this fs
2834                  *
2835                  */
2836                 {
2837                         /* we need to fake up a fsp here,
2838                          * because its not send in this call
2839                          */
2840                         files_struct fsp;
2841                         SMB_NTQUOTA_STRUCT quotas;
2842                         
2843                         ZERO_STRUCT(fsp);
2844                         ZERO_STRUCT(quotas);
2845                         
2846                         fsp.conn = conn;
2847                         fsp.fnum = -1;
2848                         
2849                         /* access check */
2850                         if (conn->server_info->utok.uid != 0) {
2851                                 DEBUG(0,("set_user_quota: access_denied "
2852                                          "service [%s] user [%s]\n",
2853                                          lp_servicename(SNUM(conn)),
2854                                          conn->server_info->unix_name));
2855                                 reply_doserror(req, ERRDOS, ERRnoaccess);
2856                                 return;
2857                         }
2858                         
2859                         if (vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
2860                                 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2861                                 reply_doserror(req, ERRSRV, ERRerror);
2862                                 return;
2863                         }
2864
2865                         data_len = 48;
2866
2867                         DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",lp_servicename(SNUM(conn))));          
2868                 
2869                         /* Unknown1 24 NULL bytes*/
2870                         SBIG_UINT(pdata,0,(uint64_t)0);
2871                         SBIG_UINT(pdata,8,(uint64_t)0);
2872                         SBIG_UINT(pdata,16,(uint64_t)0);
2873                 
2874                         /* Default Soft Quota 8 bytes */
2875                         SBIG_UINT(pdata,24,quotas.softlim);
2876
2877                         /* Default Hard Quota 8 bytes */
2878                         SBIG_UINT(pdata,32,quotas.hardlim);
2879         
2880                         /* Quota flag 2 bytes */
2881                         SSVAL(pdata,40,quotas.qflags);
2882                 
2883                         /* Unknown3 6 NULL bytes */
2884                         SSVAL(pdata,42,0);
2885                         SIVAL(pdata,44,0);
2886                         
2887                         break;
2888                 }
2889 #endif /* HAVE_SYS_QUOTAS */
2890                 case SMB_FS_OBJECTID_INFORMATION:
2891                 {
2892                         unsigned char objid[16];
2893                         struct smb_extended_info extended_info;
2894                         memcpy(pdata,create_volume_objectid(conn, objid),16);
2895                         samba_extended_info_version (&extended_info);
2896                         SIVAL(pdata,16,extended_info.samba_magic);
2897                         SIVAL(pdata,20,extended_info.samba_version);
2898                         SIVAL(pdata,24,extended_info.samba_subversion);
2899                         SBIG_UINT(pdata,28,extended_info.samba_gitcommitdate);
2900                         memcpy(pdata+36,extended_info.samba_version_string,28);
2901                         data_len = 64;
2902                         break;
2903                 }
2904
2905                 /*
2906                  * Query the version and capabilities of the CIFS UNIX extensions
2907                  * in use.
2908                  */
2909
2910                 case SMB_QUERY_CIFS_UNIX_INFO:
2911                 {
2912                         bool large_write = lp_min_receive_file_size() &&
2913                                         !srv_is_signing_active(smbd_server_conn);
2914                         bool large_read = !srv_is_signing_active(smbd_server_conn);
2915                         int encrypt_caps = 0;
2916
2917                         if (!lp_unix_extensions()) {
2918                                 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2919                                 return;
2920                         }
2921
2922                         switch (conn->encrypt_level) {
2923                         case 0:
2924                                 encrypt_caps = 0;
2925                                 break;
2926                         case 1:
2927                         case Auto:
2928                                 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP;
2929                                 break;
2930                         case Required:
2931                                 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP|
2932                                                 CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP;
2933                                 large_write = false;
2934                                 large_read = false;
2935                                 break;
2936                         }
2937
2938                         data_len = 12;
2939                         SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
2940                         SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
2941
2942                         /* We have POSIX ACLs, pathname, encryption, 
2943                          * large read/write, and locking capability. */
2944
2945                         SBIG_UINT(pdata,4,((uint64_t)(
2946                                         CIFS_UNIX_POSIX_ACLS_CAP|
2947                                         CIFS_UNIX_POSIX_PATHNAMES_CAP|
2948                                         CIFS_UNIX_FCNTL_LOCKS_CAP|
2949                                         CIFS_UNIX_EXTATTR_CAP|
2950                                         CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP|
2951                                         encrypt_caps|
2952                                         (large_read ? CIFS_UNIX_LARGE_READ_CAP : 0) |
2953                                         (large_write ?
2954                                         CIFS_UNIX_LARGE_WRITE_CAP : 0))));
2955                         break;
2956                 }
2957
2958                 case SMB_QUERY_POSIX_FS_INFO:
2959                 {
2960                         int rc;
2961                         vfs_statvfs_struct svfs;
2962
2963                         if (!lp_unix_extensions()) {
2964                                 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2965                                 return;
2966                         }
2967
2968                         rc = SMB_VFS_STATVFS(conn, ".", &svfs);
2969
2970                         if (!rc) {
2971                                 data_len = 56;
2972                                 SIVAL(pdata,0,svfs.OptimalTransferSize);
2973                                 SIVAL(pdata,4,svfs.BlockSize);
2974                                 SBIG_UINT(pdata,8,svfs.TotalBlocks);
2975                                 SBIG_UINT(pdata,16,svfs.BlocksAvail);
2976                                 SBIG_UINT(pdata,24,svfs.UserBlocksAvail);
2977                                 SBIG_UINT(pdata,32,svfs.TotalFileNodes);
2978                                 SBIG_UINT(pdata,40,svfs.FreeFileNodes);
2979                                 SBIG_UINT(pdata,48,svfs.FsIdentifier);
2980                                 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
2981 #ifdef EOPNOTSUPP
2982                         } else if (rc == EOPNOTSUPP) {
2983                                 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2984                                 return;
2985 #endif /* EOPNOTSUPP */
2986                         } else {
2987                                 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2988                                 reply_doserror(req, ERRSRV, ERRerror);
2989                                 return;
2990                         }
2991                         break;
2992                 }
2993
2994                 case SMB_QUERY_POSIX_WHOAMI:
2995                 {
2996                         uint32_t flags = 0;
2997                         uint32_t sid_bytes;
2998                         int i;
2999
3000                         if (!lp_unix_extensions()) {
3001                                 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3002                                 return;
3003                         }
3004
3005                         if (max_data_bytes < 40) {
3006                                 reply_nterror(req, NT_STATUS_BUFFER_TOO_SMALL);
3007                                 return;
3008                         }
3009
3010                         /* We ARE guest if global_sid_Builtin_Guests is
3011                          * in our list of SIDs.
3012                          */
3013                         if (nt_token_check_sid(&global_sid_Builtin_Guests,
3014                                                conn->server_info->ptok)) {
3015                                 flags |= SMB_WHOAMI_GUEST;
3016                         }
3017
3018                         /* We are NOT guest if global_sid_Authenticated_Users
3019                          * is in our list of SIDs.
3020                          */
3021                         if (nt_token_check_sid(&global_sid_Authenticated_Users,
3022                                                conn->server_info->ptok)) {
3023                                 flags &= ~SMB_WHOAMI_GUEST;
3024                         }
3025
3026                         /* NOTE: 8 bytes for UID/GID, irrespective of native
3027                          * platform size. This matches
3028                          * SMB_QUERY_FILE_UNIX_BASIC and friends.
3029                          */
3030                         data_len = 4 /* flags */
3031                             + 4 /* flag mask */
3032                             + 8 /* uid */
3033                             + 8 /* gid */
3034                             + 4 /* ngroups */
3035                             + 4 /* num_sids */
3036                             + 4 /* SID bytes */
3037                             + 4 /* pad/reserved */
3038                             + (conn->server_info->utok.ngroups * 8)
3039                                 /* groups list */
3040                             + (conn->server_info->ptok->num_sids *
3041                                     SID_MAX_SIZE)
3042                                 /* SID list */;
3043
3044                         SIVAL(pdata, 0, flags);
3045                         SIVAL(pdata, 4, SMB_WHOAMI_MASK);
3046                         SBIG_UINT(pdata, 8,
3047                                   (uint64_t)conn->server_info->utok.uid);
3048                         SBIG_UINT(pdata, 16,
3049                                   (uint64_t)conn->server_info->utok.gid);
3050
3051
3052                         if (data_len >= max_data_bytes) {
3053                                 /* Potential overflow, skip the GIDs and SIDs. */
3054
3055                                 SIVAL(pdata, 24, 0); /* num_groups */
3056                                 SIVAL(pdata, 28, 0); /* num_sids */
3057                                 SIVAL(pdata, 32, 0); /* num_sid_bytes */
3058                                 SIVAL(pdata, 36, 0); /* reserved */
3059
3060                                 data_len = 40;
3061                                 break;
3062                         }
3063
3064                         SIVAL(pdata, 24, conn->server_info->utok.ngroups);
3065                         SIVAL(pdata, 28, conn->server_info->num_sids);
3066
3067                         /* We walk the SID list twice, but this call is fairly
3068                          * infrequent, and I don't expect that it's performance
3069                          * sensitive -- jpeach
3070                          */
3071                         for (i = 0, sid_bytes = 0;
3072                              i < conn->server_info->ptok->num_sids; ++i) {
3073                                 sid_bytes += ndr_size_dom_sid(
3074                                         &conn->server_info->ptok->user_sids[i],
3075                                         NULL, 
3076                                         0);
3077                         }
3078
3079                         /* SID list byte count */
3080                         SIVAL(pdata, 32, sid_bytes);
3081
3082                         /* 4 bytes pad/reserved - must be zero */
3083                         SIVAL(pdata, 36, 0);
3084                         data_len = 40;
3085
3086                         /* GID list */
3087                         for (i = 0; i < conn->server_info->utok.ngroups; ++i) {
3088                                 SBIG_UINT(pdata, data_len,
3089                                           (uint64_t)conn->server_info->utok.groups[i]);
3090                                 data_len += 8;
3091                         }
3092
3093                         /* SID list */
3094                         for (i = 0;
3095                             i < conn->server_info->ptok->num_sids; ++i) {
3096                                 int sid_len = ndr_size_dom_sid(
3097                                         &conn->server_info->ptok->user_sids[i],
3098                                         NULL,
3099                                         0);
3100
3101                                 sid_linearize(pdata + data_len, sid_len,
3102                                     &conn->server_info->ptok->user_sids[i]);
3103                                 data_len += sid_len;
3104                         }
3105
3106                         break;
3107                 }
3108
3109                 case SMB_MAC_QUERY_FS_INFO:
3110                         /*
3111                          * Thursby MAC extension... ONLY on NTFS filesystems
3112                          * once we do streams then we don't need this
3113                          */
3114                         if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
3115                                 data_len = 88;
3116                                 SIVAL(pdata,84,0x100); /* Don't support mac... */
3117                                 break;
3118                         }
3119                         /* drop through */
3120                 default:
3121                         reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3122                         return;
3123         }
3124
3125
3126         send_trans2_replies(conn, req, params, 0, pdata, data_len,
3127                             max_data_bytes);
3128
3129         DEBUG( 4, ( "%s info_level = %d\n",
3130                     smb_fn_name(req->cmd), info_level) );
3131
3132         return;
3133 }
3134
3135 /****************************************************************************
3136  Reply to a TRANS2_SETFSINFO (set filesystem info).
3137 ****************************************************************************/
3138
3139 static void call_trans2setfsinfo(connection_struct *conn,
3140                                  struct smb_request *req,
3141                                  char **pparams, int total_params,
3142                                  char **ppdata, int total_data,
3143                                  unsigned int max_data_bytes)
3144 {
3145         char *pdata = *ppdata;
3146         char *params = *pparams;
3147         uint16 info_level;
3148
3149         DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",lp_servicename(SNUM(conn))));
3150
3151         /*  */
3152         if (total_params < 4) {
3153                 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
3154                         total_params));
3155                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3156                 return;
3157         }
3158
3159         info_level = SVAL(params,2);
3160
3161         if (IS_IPC(conn)) {
3162                 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION &&
3163                                 info_level != SMB_SET_CIFS_UNIX_INFO) {
3164                         DEBUG(0,("call_trans2setfsinfo: not an allowed "
3165                                 "info level (0x%x) on IPC$.\n",
3166                                 (unsigned int)info_level));
3167                         reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3168                         return;
3169                 }
3170         }
3171
3172         if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
3173                 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION) {
3174                         DEBUG(0,("call_trans2setfsinfo: encryption required "
3175                                 "and info level 0x%x sent.\n",
3176                                 (unsigned int)info_level));
3177                         exit_server_cleanly("encryption required "
3178                                 "on connection");
3179                         return;
3180                 }
3181         }
3182
3183         switch(info_level) {
3184                 case SMB_SET_CIFS_UNIX_INFO:
3185                         {
3186                                 uint16 client_unix_major;
3187                                 uint16 client_unix_minor;
3188                                 uint32 client_unix_cap_low;
3189                                 uint32 client_unix_cap_high;
3190
3191                                 if (!lp_unix_extensions()) {
3192                                         reply_nterror(req,
3193                                                       NT_STATUS_INVALID_LEVEL);
3194                                         return;
3195                                 }
3196
3197                                 /* There should be 12 bytes of capabilities set. */
3198                                 if (total_data < 8) {
3199                                         reply_nterror(
3200                                                 req,
3201                                                 NT_STATUS_INVALID_PARAMETER);
3202                                         return;
3203                                 }
3204                                 client_unix_major = SVAL(pdata,0);
3205                                 client_unix_minor = SVAL(pdata,2);
3206                                 client_unix_cap_low = IVAL(pdata,4);
3207                                 client_unix_cap_high = IVAL(pdata,8);
3208                                 /* Just print these values for now. */
3209                                 DEBUG(10,("call_trans2setfsinfo: set unix info. major = %u, minor = %u \
3210 cap_low = 0x%x, cap_high = 0x%x\n",
3211                                         (unsigned int)client_unix_major,
3212                                         (unsigned int)client_unix_minor,
3213                                         (unsigned int)client_unix_cap_low,
3214                                         (unsigned int)client_unix_cap_high ));
3215
3216                                 /* Here is where we must switch to posix pathname processing... */
3217                                 if (client_unix_cap_low & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
3218                                         lp_set_posix_pathnames();
3219                                         mangle_change_to_posix();
3220                                 }
3221
3222                                 if ((client_unix_cap_low & CIFS_UNIX_FCNTL_LOCKS_CAP) &&
3223                                     !(client_unix_cap_low & CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP)) {
3224                                         /* Client that knows how to do posix locks,
3225                                          * but not posix open/mkdir operations. Set a
3226                                          * default type for read/write checks. */
3227
3228                                         lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK);
3229
3230                                 }
3231                                 break;
3232                         }
3233
3234                 case SMB_REQUEST_TRANSPORT_ENCRYPTION:
3235                         {
3236                                 NTSTATUS status;
3237                                 size_t param_len = 0;
3238                                 size_t data_len = total_data;
3239
3240                                 if (!lp_unix_extensions()) {
3241                                         reply_nterror(
3242                                                 req,
3243                                                 NT_STATUS_INVALID_LEVEL);
3244                                         return;
3245                                 }
3246
3247                                 if (lp_smb_encrypt(SNUM(conn)) == false) {
3248                                         reply_nterror(
3249                                                 req,
3250                                                 NT_STATUS_NOT_SUPPORTED);
3251                                         return;
3252                                 }
3253
3254                                 DEBUG( 4,("call_trans2setfsinfo: "
3255                                         "request transport encryption.\n"));
3256
3257                                 status = srv_request_encryption_setup(conn,
3258                                                                 (unsigned char **)ppdata,
3259                                                                 &data_len,
3260                                                                 (unsigned char **)pparams,
3261                                                                 &param_len);
3262
3263                                 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED) &&
3264                                                 !NT_STATUS_IS_OK(status)) {
3265                                         reply_nterror(req, status);
3266                                         return;
3267                                 }
3268
3269                                 send_trans2_replies(conn, req,
3270                                                 *pparams,
3271                                                 param_len,
3272                                                 *ppdata,
3273                                                 data_len,
3274                                                 max_data_bytes);
3275
3276                                 if (NT_STATUS_IS_OK(status)) {
3277                                         /* Server-side transport
3278                                          * encryption is now *on*. */
3279                                         status = srv_encryption_start(conn);
3280                                         if (!NT_STATUS_IS_OK(status)) {
3281                                                 exit_server_cleanly(
3282                                                         "Failure in setting "
3283                                                         "up encrypted transport");
3284                                         }
3285                                 }
3286                                 return;
3287                         }
3288
3289                 case SMB_FS_QUOTA_INFORMATION:
3290                         {
3291                                 files_struct *fsp = NULL;
3292                                 SMB_NTQUOTA_STRUCT quotas;
3293         
3294                                 ZERO_STRUCT(quotas);
3295
3296                                 /* access check */
3297                                 if ((conn->server_info->utok.uid != 0)
3298                                     ||!CAN_WRITE(conn)) {
3299                                         DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
3300                                                  lp_servicename(SNUM(conn)),
3301                                                  conn->server_info->unix_name));
3302                                         reply_doserror(req, ERRSRV, ERRaccess);
3303                                         return;
3304                                 }
3305
3306                                 /* note: normaly there're 48 bytes,
3307                                  * but we didn't use the last 6 bytes for now 
3308                                  * --metze 
3309                                  */
3310                                 fsp = file_fsp(req, SVAL(params,0));
3311
3312                                 if (!check_fsp_ntquota_handle(conn, req,
3313                                                               fsp)) {
3314                                         DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
3315                                         reply_nterror(
3316                                                 req, NT_STATUS_INVALID_HANDLE);
3317                                         return;
3318                                 }
3319
3320                                 if (total_data < 42) {
3321                                         DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
3322                                                 total_data));
3323                                         reply_nterror(
3324                                                 req,
3325                                                 NT_STATUS_INVALID_PARAMETER);
3326                                         return;
3327                                 }
3328                         
3329                                 /* unknown_1 24 NULL bytes in pdata*/
3330                 
3331                                 /* the soft quotas 8 bytes (uint64_t)*/
3332                                 quotas.softlim = (uint64_t)IVAL(pdata,24);
3333 #ifdef LARGE_SMB_OFF_T
3334                                 quotas.softlim |= (((uint64_t)IVAL(pdata,28)) << 32);
3335 #else /* LARGE_SMB_OFF_T */
3336                                 if ((IVAL(pdata,28) != 0)&&
3337                                         ((quotas.softlim != 0xFFFFFFFF)||
3338                                         (IVAL(pdata,28)!=0xFFFFFFFF))) {
3339                                         /* more than 32 bits? */
3340                                         reply_nterror(
3341                                                 req,
3342                                                 NT_STATUS_INVALID_PARAMETER);
3343                                         return;
3344                                 }
3345 #endif /* LARGE_SMB_OFF_T */
3346                 
3347                                 /* the hard quotas 8 bytes (uint64_t)*/
3348                                 quotas.hardlim = (uint64_t)IVAL(pdata,32);
3349 #ifdef LARGE_SMB_OFF_T
3350                                 quotas.hardlim |= (((uint64_t)IVAL(pdata,36)) << 32);
3351 #else /* LARGE_SMB_OFF_T */
3352                                 if ((IVAL(pdata,36) != 0)&&
3353                                         ((quotas.hardlim != 0xFFFFFFFF)||
3354                                         (IVAL(pdata,36)!=0xFFFFFFFF))) {
3355                                         /* more than 32 bits? */
3356                                         reply_nterror(
3357                                                 req,
3358                                                 NT_STATUS_INVALID_PARAMETER);
3359                                         return;
3360                                 }
3361 #endif /* LARGE_SMB_OFF_T */
3362                 
3363                                 /* quota_flags 2 bytes **/
3364                                 quotas.qflags = SVAL(pdata,40);
3365                 
3366                                 /* unknown_2 6 NULL bytes follow*/
3367                 
3368                                 /* now set the quotas */
3369                                 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
3370                                         DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
3371                                         reply_doserror(req, ERRSRV, ERRerror);
3372                                         return;
3373                                 }
3374                         
3375                                 break;
3376                         }
3377                 default:
3378                         DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
3379                                 info_level));
3380                         reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3381                         return;
3382                         break;
3383         }
3384
3385         /* 
3386          * sending this reply works fine, 
3387          * but I'm not sure it's the same 
3388          * like windows do...
3389          * --metze
3390          */
3391         reply_outbuf(req, 10, 0);
3392 }
3393
3394 #if defined(HAVE_POSIX_ACLS)
3395 /****************************************************************************
3396  Utility function to count the number of entries in a POSIX acl.
3397 ****************************************************************************/
3398
3399 static unsigned int count_acl_entries(connection_struct *conn, SMB_ACL_T posix_acl)
3400 {
3401         unsigned int ace_count = 0;
3402         int entry_id = SMB_ACL_FIRST_ENTRY;
3403         SMB_ACL_ENTRY_T entry;
3404
3405         while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
3406                 /* get_next... */
3407                 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3408                         entry_id = SMB_ACL_NEXT_ENTRY;
3409                 }
3410                 ace_count++;
3411         }
3412         return ace_count;
3413 }
3414
3415 /****************************************************************************
3416  Utility function to marshall a POSIX acl into wire format.
3417 ****************************************************************************/
3418
3419 static bool marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_STAT *pst, SMB_ACL_T posix_acl)
3420 {
3421         int entry_id = SMB_ACL_FIRST_ENTRY;
3422         SMB_ACL_ENTRY_T entry;
3423
3424         while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
3425                 SMB_ACL_TAG_T tagtype;
3426                 SMB_ACL_PERMSET_T permset;
3427                 unsigned char perms = 0;
3428                 unsigned int own_grp;
3429
3430                 /* get_next... */
3431                 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3432                         entry_id = SMB_ACL_NEXT_ENTRY;
3433                 }
3434
3435                 if (SMB_VFS_SYS_ACL_GET_TAG_TYPE(conn, entry, &tagtype) == -1) {
3436                         DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
3437                         return False;
3438                 }
3439
3440                 if (SMB_VFS_SYS_ACL_GET_PERMSET(conn, entry, &permset) == -1) {
3441                         DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
3442                         return False;
3443                 }
3444
3445                 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_READ) ? SMB_POSIX_ACL_READ : 0);
3446                 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_WRITE) ? SMB_POSIX_ACL_WRITE : 0);
3447                 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_EXECUTE) ? SMB_POSIX_ACL_EXECUTE : 0);
3448
3449                 SCVAL(pdata,1,perms);
3450
3451                 switch (tagtype) {
3452                         case SMB_ACL_USER_OBJ:
3453                                 SCVAL(pdata,0,SMB_POSIX_ACL_USER_OBJ);
3454                                 own_grp = (unsigned int)pst->st_uid;
3455                                 SIVAL(pdata,2,own_grp);
3456                                 SIVAL(pdata,6,0);
3457                                 break;
3458                         case SMB_ACL_USER:
3459                                 {
3460                                         uid_t *puid = (uid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3461                                         if (!puid) {
3462                                                 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3463                                                 return False;
3464                                         }
3465                                         own_grp = (unsigned int)*puid;
3466                                         SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)puid,tagtype);
3467                                         SCVAL(pdata,0,SMB_POSIX_ACL_USER);
3468                                         SIVAL(pdata,2,own_grp);
3469                                         SIVAL(pdata,6,0);
3470                                         break;
3471                                 }
3472                         case SMB_ACL_GROUP_OBJ:
3473                                 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP_OBJ);
3474                                 own_grp = (unsigned int)pst->st_gid;
3475                                 SIVAL(pdata,2,own_grp);
3476                                 SIVAL(pdata,6,0);
3477                                 break;
3478                         case SMB_ACL_GROUP:
3479                                 {
3480                                         gid_t *pgid= (gid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3481                                         if (!pgid) {
3482                                                 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3483                                                 return False;
3484                                         }
3485                                         own_grp = (unsigned int)*pgid;
3486                                         SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)pgid,tagtype);
3487                                         SCVAL(pdata,0,SMB_POSIX_ACL_GROUP);
3488                                         SIVAL(pdata,2,own_grp);
3489                                         SIVAL(pdata,6,0);
3490                                         break;
3491                                 }
3492                         case SMB_ACL_MASK:
3493                                 SCVAL(pdata,0,SMB_POSIX_ACL_MASK);
3494                                 SIVAL(pdata,2,0xFFFFFFFF);
3495                                 SIVAL(pdata,6,0xFFFFFFFF);
3496                                 break;
3497                         case SMB_ACL_OTHER:
3498                                 SCVAL(pdata,0,SMB_POSIX_ACL_OTHER);
3499                                 SIVAL(pdata,2,0xFFFFFFFF);
3500                                 SIVAL(pdata,6,0xFFFFFFFF);
3501                                 break;
3502                         default:
3503                                 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
3504                                 return False;
3505                 }
3506                 pdata += SMB_POSIX_ACL_ENTRY_SIZE;
3507         }
3508
3509         return True;
3510 }
3511 #endif
3512
3513 /****************************************************************************
3514  Store the FILE_UNIX_BASIC info.
3515 ****************************************************************************/
3516
3517 static char *store_file_unix_basic(connection_struct *conn,
3518                                 char *pdata,
3519                                 files_struct *fsp,
3520                                 const SMB_STRUCT_STAT *psbuf)
3521 {
3522         DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
3523         DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf->st_mode));
3524
3525         SOFF_T(pdata,0,get_file_size_stat(psbuf));             /* File size 64 Bit */
3526         pdata += 8;
3527
3528         SOFF_T(pdata,0,SMB_VFS_GET_ALLOC_SIZE(conn,fsp,psbuf)); /* Number of bytes used on disk - 64 Bit */
3529         pdata += 8;
3530
3531         put_long_date_timespec(pdata,get_ctimespec(psbuf));       /* Change Time 64 Bit */
3532         put_long_date_timespec(pdata+8,get_atimespec(psbuf));     /* Last access time 64 Bit */
3533         put_long_date_timespec(pdata+16,get_mtimespec(psbuf));    /* Last modification time 64 Bit */
3534         pdata += 24;
3535
3536         SIVAL(pdata,0,psbuf->st_uid);               /* user id for the owner */
3537         SIVAL(pdata,4,0);
3538         pdata += 8;
3539
3540         SIVAL(pdata,0,psbuf->st_gid);               /* group id of owner */
3541         SIVAL(pdata,4,0);
3542         pdata += 8;
3543
3544         SIVAL(pdata,0,unix_filetype(psbuf->st_mode));
3545         pdata += 4;
3546
3547         SIVAL(pdata,0,unix_dev_major(psbuf->st_rdev));   /* Major device number if type is device */
3548         SIVAL(pdata,4,0);
3549         pdata += 8;
3550
3551         SIVAL(pdata,0,unix_dev_minor(psbuf->st_rdev));   /* Minor device number if type is device */
3552         SIVAL(pdata,4,0);
3553         pdata += 8;
3554
3555         SINO_T_VAL(pdata,0,(SMB_INO_T)psbuf->st_ino);   /* inode number */
3556         pdata += 8;
3557                                 
3558         SIVAL(pdata,0, unix_perms_to_wire(psbuf->st_mode));     /* Standard UNIX file permissions */
3559         SIVAL(pdata,4,0);
3560         pdata += 8;
3561
3562         SIVAL(pdata,0,psbuf->st_nlink);             /* number of hard links */
3563         SIVAL(pdata,4,0);
3564         pdata += 8;
3565
3566         return pdata;
3567 }
3568
3569 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
3570  * the chflags(2) (or equivalent) flags.
3571  *
3572  * XXX: this really should be behind the VFS interface. To do this, we would
3573  * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
3574  * Each VFS module could then implement its own mapping as appropriate for the
3575  * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
3576  */
3577 static const struct {unsigned stat_fflag; unsigned smb_fflag;}
3578         info2_flags_map[] =
3579 {
3580 #ifdef UF_NODUMP
3581     { UF_NODUMP, EXT_DO_NOT_BACKUP },
3582 #endif
3583
3584 #ifdef UF_IMMUTABLE
3585     { UF_IMMUTABLE, EXT_IMMUTABLE },
3586 #endif
3587
3588 #ifdef UF_APPEND
3589     { UF_APPEND, EXT_OPEN_APPEND_ONLY },
3590 #endif
3591
3592 #ifdef UF_HIDDEN
3593     { UF_HIDDEN, EXT_HIDDEN },
3594 #endif
3595
3596     /* Do not remove. We need to guarantee that this array has at least one
3597      * entry to build on HP-UX.
3598      */
3599     { 0, 0 }
3600
3601 };
3602
3603 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT *psbuf,
3604                                 uint32 *smb_fflags, uint32 *smb_fmask)
3605 {
3606 #ifdef HAVE_STAT_ST_FLAGS
3607         int i;
3608
3609         for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
3610             *smb_fmask |= info2_flags_map[i].smb_fflag;
3611             if (psbuf->st_flags & info2_flags_map[i].stat_fflag) {
3612                     *smb_fflags |= info2_flags_map[i].smb_fflag;
3613             }
3614         }
3615 #endif /* HAVE_STAT_ST_FLAGS */
3616 }
3617
3618 static bool map_info2_flags_to_sbuf(const SMB_STRUCT_STAT *psbuf,
3619                                 const uint32 smb_fflags,
3620                                 const uint32 smb_fmask,
3621                                 int *stat_fflags)
3622 {
3623 #ifdef HAVE_STAT_ST_FLAGS
3624         uint32 max_fmask = 0;
3625         int i;
3626
3627         *stat_fflags = psbuf->st_flags;
3628
3629         /* For each flags requested in smb_fmask, check the state of the
3630          * corresponding flag in smb_fflags and set or clear the matching
3631          * stat flag.
3632          */
3633
3634         for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
3635             max_fmask |= info2_flags_map[i].smb_fflag;
3636             if (smb_fmask & info2_flags_map[i].smb_fflag) {
3637                     if (smb_fflags & info2_flags_map[i].smb_fflag) {
3638                             *stat_fflags |= info2_flags_map[i].stat_fflag;
3639                     } else {
3640                             *stat_fflags &= ~info2_flags_map[i].stat_fflag;
3641                     }
3642             }
3643         }
3644
3645         /* If smb_fmask is asking to set any bits that are not supported by
3646          * our flag mappings, we should fail.
3647          */
3648         if ((smb_fmask & max_fmask) != smb_fmask) {
3649                 return False;
3650         }
3651
3652         return True;
3653 #else
3654         return False;
3655 #endif /* HAVE_STAT_ST_FLAGS */
3656 }
3657
3658
3659 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
3660  * of file flags and birth (create) time.
3661  */
3662 static char *store_file_unix_basic_info2(connection_struct *conn,
3663                                 char *pdata,
3664                                 files_struct *fsp,
3665                                 const SMB_STRUCT_STAT *psbuf)
3666 {
3667         uint32 file_flags = 0;
3668         uint32 flags_mask = 0;
3669
3670         pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
3671
3672         /* Create (birth) time 64 bit */
3673         put_long_date_timespec(pdata, get_create_timespec(psbuf, False));
3674         pdata += 8;
3675
3676         map_info2_flags_from_sbuf(psbuf, &file_flags, &flags_mask);
3677         SIVAL(pdata, 0, file_flags); /* flags */
3678         SIVAL(pdata, 4, flags_mask); /* mask */
3679         pdata += 8;
3680
3681         return pdata;
3682 }
3683
3684 static NTSTATUS marshall_stream_info(unsigned int num_streams,
3685                                      const struct stream_struct *streams,
3686                                      char *data,
3687                                      unsigned int max_data_bytes,
3688                                      unsigned int *data_size)
3689 {
3690         unsigned int i;
3691         unsigned int ofs = 0;
3692
3693         for (i = 0; i < num_streams && ofs <= max_data_bytes; i++) {
3694                 unsigned int next_offset;
3695                 size_t namelen;
3696                 smb_ucs2_t *namebuf;
3697
3698                 if (!push_ucs2_talloc(talloc_tos(), &namebuf,
3699                                       streams[i].name, &namelen) ||
3700                     namelen <= 2)
3701                 {
3702                         return NT_STATUS_INVALID_PARAMETER;
3703                 }
3704
3705                 /*
3706                  * name_buf is now null-terminated, we need to marshall as not
3707                  * terminated
3708                  */
3709
3710                 namelen -= 2;
3711
3712                 SIVAL(data, ofs+4, namelen);
3713                 SOFF_T(data, ofs+8, streams[i].size);
3714                 SOFF_T(data, ofs+16, streams[i].alloc_size);
3715                 memcpy(data+ofs+24, namebuf, namelen);
3716                 TALLOC_FREE(namebuf);
3717
3718                 next_offset = ofs + 24 + namelen;
3719
3720                 if (i == num_streams-1) {
3721                         SIVAL(data, ofs, 0);
3722                 }
3723                 else {
3724                         unsigned int align = ndr_align_size(next_offset, 8);
3725
3726                         memset(data+next_offset, 0, align);
3727                         next_offset += align;
3728
3729                         SIVAL(data, ofs, next_offset - ofs);
3730                         ofs = next_offset;
3731                 }
3732
3733                 ofs = next_offset;
3734         }
3735
3736         *data_size = ofs;
3737
3738         return NT_STATUS_OK;
3739 }
3740
3741 /****************************************************************************
3742  Reply to a TRANSACT2_QFILEINFO on a PIPE !
3743 ****************************************************************************/
3744
3745 static void call_trans2qpipeinfo(connection_struct *conn,
3746                                  struct smb_request *req,
3747                                  unsigned int tran_call,
3748                                  char **pparams, int total_params,
3749                                  char **ppdata, int total_data,
3750                                  unsigned int max_data_bytes)
3751 {
3752         char *params = *pparams;
3753         char *pdata = *ppdata;
3754         unsigned int data_size = 0;
3755         unsigned int param_size = 2;
3756         uint16 info_level;
3757         files_struct *fsp;
3758
3759         if (!params) {
3760                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3761                 return;
3762         }
3763
3764         if (total_params < 4) {
3765                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3766                 return;
3767         }
3768
3769         fsp = file_fsp(req, SVAL(params,0));
3770         if (!fsp_is_np(fsp)) {
3771                 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
3772                 return;
3773         }
3774
3775         info_level = SVAL(params,2);
3776
3777         *pparams = (char *)SMB_REALLOC(*pparams,2);
3778         if (*pparams == NULL) {
3779                 reply_nterror(req, NT_STATUS_NO_MEMORY);
3780                 return;
3781         }
3782         params = *pparams;
3783         SSVAL(params,0,0);
3784         data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
3785         *ppdata = (char *)SMB_REALLOC(*ppdata, data_size); 
3786         if (*ppdata == NULL ) {
3787                 reply_nterror(req, NT_STATUS_NO_MEMORY);
3788                 return;
3789         }
3790         pdata = *ppdata;
3791
3792         switch (info_level) {
3793                 case SMB_FILE_STANDARD_INFORMATION:
3794                         memset(pdata,0,24);
3795                         SOFF_T(pdata,0,4096LL);
3796                         SIVAL(pdata,16,1);
3797                         SIVAL(pdata,20,1);
3798                         data_size = 24;
3799                         break;
3800
3801                 default:
3802                         reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3803                         return;
3804         }
3805
3806         send_trans2_replies(conn, req, params, param_size, *ppdata, data_size,
3807                             max_data_bytes);
3808
3809         return;
3810 }
3811
3812 /****************************************************************************
3813  Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
3814  file name or file id).
3815 ****************************************************************************/
3816
3817 static void call_trans2qfilepathinfo(connection_struct *conn,
3818                                      struct smb_request *req,
3819                                      unsigned int tran_call,
3820                                      char **pparams, int total_params,
3821                                      char **ppdata, int total_data,
3822                                      unsigned int max_data_bytes)
3823 {
3824         char *params = *pparams;
3825         char *pdata = *ppdata;
3826         char *dstart, *dend;
3827         uint16 info_level;
3828         int mode=0;
3829         int nlink;
3830         SMB_OFF_T file_size=0;
3831         uint64_t allocation_size=0;
3832         unsigned int data_size = 0;
3833         unsigned int param_size = 2;
3834         SMB_STRUCT_STAT sbuf;
3835         char *dos_fname = NULL;
3836         char *fname = NULL;
3837         char *fullpathname;
3838         char *base_name;
3839         char *p;
3840         SMB_OFF_T pos = 0;
3841         bool delete_pending = False;
3842         int len;
3843         time_t create_time, mtime, atime;
3844         struct timespec create_time_ts, mtime_ts, atime_ts;
3845         struct timespec write_time_ts;
3846         files_struct *fsp = NULL;
3847         struct file_id fileid;
3848         struct ea_list *ea_list = NULL;
3849         char *lock_data = NULL;
3850         bool ms_dfs_link = false;
3851         TALLOC_CTX *ctx = talloc_tos();
3852
3853         if (!params) {
3854                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3855                 return;
3856         }
3857
3858         ZERO_STRUCT(sbuf);
3859         ZERO_STRUCT(write_time_ts);
3860
3861         if (tran_call == TRANSACT2_QFILEINFO) {
3862                 if (total_params < 4) {
3863                         reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3864                         return;
3865                 }
3866
3867                 if (IS_IPC(conn)) {
3868                         call_trans2qpipeinfo(conn, req, tran_call,
3869                                              pparams, total_params,
3870                                              ppdata, total_data,
3871                                              max_data_bytes);
3872                         return;
3873                 }
3874
3875                 fsp = file_fsp(req, SVAL(params,0));
3876                 info_level = SVAL(params,2);
3877
3878                 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
3879
3880                 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
3881                         reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3882                         return;
3883                 }
3884
3885                 /* Initial check for valid fsp ptr. */
3886                 if (!check_fsp_open(conn, req, fsp)) {
3887                         return;
3888                 }
3889
3890                 fname = talloc_strdup(talloc_tos(),fsp->fsp_name);
3891                 if (!fname) {
3892                         reply_nterror(req, NT_STATUS_NO_MEMORY);
3893                         return;
3894                 }
3895
3896                 if(fsp->fake_file_handle) {
3897                         /*
3898                          * This is actually for the QUOTA_FAKE_FILE --metze
3899                          */
3900
3901                         /* We know this name is ok, it's already passed the checks. */
3902
3903                 } else if(fsp && (fsp->is_directory || fsp->fh->fd == -1)) {
3904                         /*
3905                          * This is actually a QFILEINFO on a directory
3906                          * handle (returned from an NT SMB). NT5.0 seems
3907                          * to do this call. JRA.
3908                          */
3909
3910                         if (INFO_LEVEL_IS_UNIX(info_level)) {
3911                                 /* Always do lstat for UNIX calls. */
3912                                 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
3913                                         DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
3914                                         reply_unixerror(req,ERRDOS,ERRbadpath);
3915                                         return;
3916                                 }
3917                         } else if (SMB_VFS_STAT(conn,fname,&sbuf)) {
3918                                 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
3919                                 reply_unixerror(req, ERRDOS, ERRbadpath);
3920                                 return;
3921                         }
3922
3923                         fileid = vfs_file_id_from_sbuf(conn, &sbuf);
3924                         get_file_infos(fileid, &delete_pending, &write_time_ts);
3925                 } else {
3926                         /*
3927                          * Original code - this is an open file.
3928                          */
3929                         if (!check_fsp(conn, req, fsp)) {
3930                                 return;
3931                         }
3932
3933                         if (SMB_VFS_FSTAT(fsp, &sbuf) != 0) {
3934                                 DEBUG(3,("fstat of fnum %d failed (%s)\n", fsp->fnum, strerror(errno)));
3935                                 reply_unixerror(req, ERRDOS, ERRbadfid);
3936                                 return;
3937                         }
3938                         pos = fsp->fh->position_information;
3939                         fileid = vfs_file_id_from_sbuf(conn, &sbuf);
3940                         get_file_infos(fileid, &delete_pending, &write_time_ts);
3941                 }
3942
3943         } else {
3944                 NTSTATUS status = NT_STATUS_OK;
3945
3946                 /* qpathinfo */
3947                 if (total_params < 7) {
3948                         reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3949                         return;
3950                 }
3951
3952                 info_level = SVAL(params,0);
3953
3954                 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
3955
3956                 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
3957                         reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3958                         return;
3959                 }
3960
3961                 srvstr_get_path(ctx, params, req->flags2, &fname, &params[6],
3962                                 total_params - 6,
3963                                 STR_TERMINATE, &status);
3964                 if (!NT_STATUS_IS_OK(status)) {
3965                         reply_nterror(req, status);
3966                         return;
3967                 }
3968
3969                 status = resolve_dfspath(ctx,
3970                                         conn,
3971                                         req->flags2 & FLAGS2_DFS_PATHNAMES,
3972                                         fname,
3973                                         &fname);
3974                 if (!NT_STATUS_IS_OK(status)) {
3975                         if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
3976                                 reply_botherror(req,
3977                                                 NT_STATUS_PATH_NOT_COVERED,
3978                                                 ERRSRV, ERRbadpath);
3979                         }
3980                         reply_nterror(req, status);
3981                         return;
3982                 }
3983
3984                 status = unix_convert(ctx, conn, fname, False, &fname, NULL, &sbuf);
3985                 if (!NT_STATUS_IS_OK(status)) {
3986                         reply_nterror(req, status);
3987                         return;
3988                 }
3989                 status = check_name(conn, fname);
3990                 if (!NT_STATUS_IS_OK(status)) {
3991                         DEBUG(3,("call_trans2qfilepathinfo: fileinfo of %s failed (%s)\n",fname,nt_errstr(status)));
3992                         reply_nterror(req, status);
3993                         return;
3994                 }
3995
3996                 if ((conn->fs_capabilities & FILE_NAMED_STREAMS)
3997                     && is_ntfs_stream_name(fname)) {
3998                         char *base;
3999                         SMB_STRUCT_STAT bsbuf;
4000
4001                         status = split_ntfs_stream_name(talloc_tos(), fname,
4002                                                         &base, NULL);
4003                         if (!NT_STATUS_IS_OK(status)) {
4004                                 DEBUG(10, ("create_file_unixpath: "
4005                                         "split_ntfs_stream_name failed: %s\n",
4006                                         nt_errstr(status)));
4007                                 reply_nterror(req, status);
4008                                 return;
4009                         }
4010
4011                         SMB_ASSERT(!is_ntfs_stream_name(base)); /* paranoia.. */
4012
4013                         if (INFO_LEVEL_IS_UNIX(info_level)) {
4014                                 /* Always do lstat for UNIX calls. */
4015                                 if (SMB_VFS_LSTAT(conn,base,&bsbuf)) {
4016                                         DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",base,strerror(errno)));
4017                                         reply_unixerror(req,ERRDOS,ERRbadpath);
4018                                         return;
4019                                 }
4020                         } else {
4021                                 if (SMB_VFS_STAT(conn,base,&bsbuf) != 0) {
4022                                         DEBUG(3,("call_trans2qfilepathinfo: fileinfo of %s failed (%s)\n",base,strerror(errno)));
4023                                         reply_unixerror(req,ERRDOS,ERRbadpath);
4024                                         return;
4025                                 }
4026                         }
4027
4028                         fileid = vfs_file_id_from_sbuf(conn, &bsbuf);
4029                         get_file_infos(fileid, &delete_pending, NULL);
4030                         if (delete_pending) {
4031                                 reply_nterror(req, NT_STATUS_DELETE_PENDING);
4032                                 return;
4033                         }
4034                 }
4035
4036                 if (INFO_LEVEL_IS_UNIX(info_level)) {
4037                         /* Always do lstat for UNIX calls. */
4038                         if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
4039                                 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
4040                                 reply_unixerror(req, ERRDOS, ERRbadpath);
4041                                 return;
4042                         }
4043
4044                 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,fname,&sbuf) && (info_level != SMB_INFO_IS_NAME_VALID)) {
4045                         ms_dfs_link = check_msdfs_link(conn,fname,&sbuf);
4046
4047                         if (!ms_dfs_link) {
4048                                 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
4049                                 reply_unixerror(req, ERRDOS, ERRbadpath);
4050                                 return;
4051                         }
4052                 }
4053
4054                 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
4055                 get_file_infos(fileid, &delete_pending, &write_time_ts);
4056                 if (delete_pending) {
4057                         reply_nterror(req, NT_STATUS_DELETE_PENDING);
4058                         return;
4059                 }
4060         }
4061
4062         if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
4063                 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4064                 return;
4065         }
4066
4067         DEBUG(3,("call_trans2qfilepathinfo %s (fnum = %d) level=%d call=%d total_data=%d\n",
4068                 fname,fsp ? fsp->fnum : -1, info_level,tran_call,total_data));
4069
4070         p = strrchr_m(fname,'/');
4071         if (!p)
4072                 base_name = fname;
4073         else
4074                 base_name = p+1;
4075
4076         if (ms_dfs_link) {
4077                 mode = dos_mode_msdfs(conn,fname,&sbuf);
4078         } else {
4079                 mode = dos_mode(conn,fname,&sbuf);
4080         }
4081         if (!mode)
4082                 mode = FILE_ATTRIBUTE_NORMAL;
4083
4084         nlink = sbuf.st_nlink;
4085
4086         if (nlink && (mode&aDIR)) {
4087                 nlink = 1;
4088         }
4089
4090         if ((nlink > 0) && delete_pending) {
4091                 nlink -= 1;
4092         }
4093
4094         fullpathname = fname;
4095         if (!(mode & aDIR))
4096                 file_size = get_file_size_stat(&sbuf);
4097
4098         /* Pull out any data sent here before we realloc. */
4099         switch (info_level) {
4100                 case SMB_INFO_QUERY_EAS_FROM_LIST:
4101                 {
4102                         /* Pull any EA list from the data portion. */
4103                         uint32 ea_size;
4104
4105                         if (total_data < 4) {
4106                                 reply_nterror(
4107                                         req, NT_STATUS_INVALID_PARAMETER);
4108                                 return;
4109                         }
4110                         ea_size = IVAL(pdata,0);
4111
4112                         if (total_data > 0 && ea_size != total_data) {
4113                                 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
4114 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
4115                                 reply_nterror(
4116                                         req, NT_STATUS_INVALID_PARAMETER);
4117                                 return;
4118                         }
4119
4120                         if (!lp_ea_support(SNUM(conn))) {
4121                                 reply_doserror(req, ERRDOS,
4122                                                ERReasnotsupported);
4123                                 return;
4124                         }
4125
4126                         /* Pull out the list of names. */
4127                         ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
4128                         if (!ea_list) {
4129                                 reply_nterror(
4130                                         req, NT_STATUS_INVALID_PARAMETER);
4131                                 return;
4132                         }
4133                         break;
4134                 }
4135
4136                 case SMB_QUERY_POSIX_LOCK:
4137                 {
4138                         if (fsp == NULL || fsp->fh->fd == -1) {
4139                                 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
4140                                 return;
4141                         }
4142
4143                         if (total_data != POSIX_LOCK_DATA_SIZE) {
4144                                 reply_nterror(
4145                                         req, NT_STATUS_INVALID_PARAMETER);
4146                                 return;
4147                         }
4148
4149                         /* Copy the lock range data. */
4150                         lock_data = (char *)TALLOC_MEMDUP(
4151                                 ctx, pdata, total_data);
4152                         if (!lock_data) {
4153                                 reply_nterror(req, NT_STATUS_NO_MEMORY);
4154                                 return;
4155                         }
4156                 }
4157                 default:
4158                         break;
4159         }
4160
4161         *pparams = (char *)SMB_REALLOC(*pparams,2);
4162         if (*pparams == NULL) {
4163                 reply_nterror(req, NT_STATUS_NO_MEMORY);
4164                 return;
4165         }
4166         params = *pparams;
4167         SSVAL(params,0,0);
4168         data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
4169         *ppdata = (char *)SMB_REALLOC(*ppdata, data_size); 
4170         if (*ppdata == NULL ) {
4171                 reply_nterror(req, NT_STATUS_NO_MEMORY);
4172                 return;
4173         }
4174         pdata = *ppdata;
4175         dstart = pdata;
4176         dend = dstart + data_size - 1;
4177
4178         create_time_ts = get_create_timespec(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
4179         mtime_ts = get_mtimespec(&sbuf);
4180         atime_ts = get_atimespec(&sbuf);
4181
4182         allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn,fsp,&sbuf);
4183
4184         if (!fsp) {
4185                 /* Do we have this path open ? */
4186                 files_struct *fsp1;
4187                 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
4188                 fsp1 = file_find_di_first(fileid);
4189                 if (fsp1 && fsp1->initial_allocation_size) {
4190                         allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp1, &sbuf);
4191                 }
4192         }
4193
4194         if (!null_timespec(write_time_ts) && !INFO_LEVEL_IS_UNIX(info_level)) {
4195                 mtime_ts = write_time_ts;
4196         }
4197
4198         if (lp_dos_filetime_resolution(SNUM(conn))) {
4199                 dos_filetime_timespec(&create_time_ts);
4200                 dos_filetime_timespec(&mtime_ts);
4201                 dos_filetime_timespec(&atime_ts);
4202         }
4203
4204         create_time = convert_timespec_to_time_t(create_time_ts);
4205         mtime = convert_timespec_to_time_t(mtime_ts);
4206         atime = convert_timespec_to_time_t(atime_ts);
4207
4208         /* NT expects the name to be in an exact form of the *full*
4209            filename. See the trans2 torture test */
4210         if (ISDOT(base_name)) {
4211                 dos_fname = talloc_strdup(ctx, "\\");
4212                 if (!dos_fname) {
4213                         reply_nterror(req, NT_STATUS_NO_MEMORY);
4214                         return;
4215                 }
4216         } else {
4217                 dos_fname = talloc_asprintf(ctx,
4218                                 "\\%s",
4219                                 fname);
4220                 if (!dos_fname) {
4221                         reply_nterror(req, NT_STATUS_NO_MEMORY);
4222                         return;
4223                 }
4224                 string_replace(dos_fname, '/', '\\');
4225         }
4226
4227         switch (info_level) {
4228                 case SMB_INFO_STANDARD:
4229                         DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_STANDARD\n"));
4230                         data_size = 22;
4231                         srv_put_dos_date2(pdata,l1_fdateCreation,create_time);
4232                         srv_put_dos_date2(pdata,l1_fdateLastAccess,atime);
4233                         srv_put_dos_date2(pdata,l1_fdateLastWrite,mtime); /* write time */
4234                         SIVAL(pdata,l1_cbFile,(uint32)file_size);
4235                         SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
4236                         SSVAL(pdata,l1_attrFile,mode);
4237                         break;
4238
4239                 case SMB_INFO_QUERY_EA_SIZE:
4240                 {
4241                         unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
4242                         DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
4243                         data_size = 26;
4244                         srv_put_dos_date2(pdata,0,create_time);
4245                         srv_put_dos_date2(pdata,4,atime);
4246                         srv_put_dos_date2(pdata,8,mtime); /* write time */
4247                         SIVAL(pdata,12,(uint32)file_size);
4248                         SIVAL(pdata,16,(uint32)allocation_size);
4249                         SSVAL(pdata,20,mode);
4250                         SIVAL(pdata,22,ea_size);
4251                         break;
4252                 }
4253
4254                 case SMB_INFO_IS_NAME_VALID:
4255                         DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
4256                         if (tran_call == TRANSACT2_QFILEINFO) {
4257                                 /* os/2 needs this ? really ?*/
4258                                 reply_doserror(req, ERRDOS, ERRbadfunc);
4259                                 return;
4260                         }
4261                         data_size = 0;
4262                         param_size = 0;
4263                         break;
4264
4265                 case SMB_INFO_QUERY_EAS_FROM_LIST:
4266                 {
4267                         size_t total_ea_len = 0;
4268                         struct ea_list *ea_file_list = NULL;
4269
4270                         DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
4271
4272                         ea_file_list = get_ea_list_from_file(ctx, conn, fsp, fname, &total_ea_len);
4273                         ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
4274
4275                         if (!ea_list || (total_ea_len > data_size)) {
4276                                 data_size = 4;
4277                                 SIVAL(pdata,0,4);   /* EA List Length must be set to 4 if no EA's. */
4278                                 break;
4279                         }
4280
4281                         data_size = fill_ea_buffer(ctx, pdata, data_size, conn, ea_list);
4282                         break;
4283                 }
4284
4285                 case SMB_INFO_QUERY_ALL_EAS:
4286                 {
4287                         /* We have data_size bytes to put EA's into. */
4288                         size_t total_ea_len = 0;
4289
4290                         DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
4291
4292                         ea_list = get_ea_list_from_file(ctx, conn, fsp, fname, &total_ea_len);
4293                         if (!ea_list || (total_ea_len > data_size)) {
4294                                 data_size = 4;
4295                                 SIVAL(pdata,0,4);   /* EA List Length must be set to 4 if no EA's. */
4296                                 break;
4297                         }
4298
4299                         data_size = fill_ea_buffer(ctx, pdata, data_size, conn, ea_list);
4300                         break;
4301                 }
4302
4303                 case SMB_FILE_BASIC_INFORMATION:
4304                 case SMB_QUERY_FILE_BASIC_INFO:
4305
4306                         if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
4307                                 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
4308                                 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
4309                         } else {
4310                                 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
4311                                 data_size = 40;
4312                                 SIVAL(pdata,36,0);
4313                         }
4314                         put_long_date_timespec(pdata,create_time_ts);
4315                         put_long_date_timespec(pdata+8,atime_ts);
4316                         put_long_date_timespec(pdata+16,mtime_ts); /* write time */
4317                         put_long_date_timespec(pdata+24,mtime_ts); /* change time */
4318                         SIVAL(pdata,32,mode);
4319
4320                         DEBUG(5,("SMB_QFBI - "));
4321                         DEBUG(5,("create: %s ", ctime(&create_time)));
4322                         DEBUG(5,("access: %s ", ctime(&atime)));
4323                         DEBUG(5,("write: %s ", ctime(&mtime)));
4324                         DEBUG(5,("change: %s ", ctime(&mtime)));
4325                         DEBUG(5,("mode: %x\n", mode));
4326                         break;
4327
4328                 case SMB_FILE_STANDARD_INFORMATION:
4329                 case SMB_QUERY_FILE_STANDARD_INFO:
4330
4331                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
4332                         data_size = 24;
4333                         SOFF_T(pdata,0,allocation_size);
4334                         SOFF_T(pdata,8,file_size);
4335                         SIVAL(pdata,16,nlink);
4336                         SCVAL(pdata,20,delete_pending?1:0);
4337                         SCVAL(pdata,21,(mode&aDIR)?1:0);
4338                         SSVAL(pdata,22,0); /* Padding. */
4339                         break;
4340
4341                 case SMB_FILE_EA_INFORMATION:
4342                 case SMB_QUERY_FILE_EA_INFO:
4343                 {
4344                         unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
4345                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
4346                         data_size = 4;
4347                         SIVAL(pdata,0,ea_size);
4348                         break;
4349                 }
4350
4351                 /* Get the 8.3 name - used if NT SMB was negotiated. */
4352                 case SMB_QUERY_FILE_ALT_NAME_INFO:
4353                 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
4354                 {
4355                         char mangled_name[13];
4356                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
4357                         if (!name_to_8_3(base_name,mangled_name,
4358                                                 True,conn->params)) {
4359                                 reply_nterror(
4360                                         req,
4361                                         NT_STATUS_NO_MEMORY);
4362                         }
4363                         len = srvstr_push(dstart, req->flags2,
4364                                           pdata+4, mangled_name,
4365                                           PTR_DIFF(dend, pdata+4),
4366                                           STR_UNICODE);
4367                         data_size = 4 + len;
4368                         SIVAL(pdata,0,len);
4369                         break;
4370                 }
4371
4372                 case SMB_QUERY_FILE_NAME_INFO:
4373                         /*
4374                           this must be *exactly* right for ACLs on mapped drives to work
4375                          */
4376                         len = srvstr_push(dstart, req->flags2,
4377                                           pdata+4, dos_fname,
4378                                           PTR_DIFF(dend, pdata+4),
4379                                           STR_UNICODE);
4380                         DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
4381                         data_size = 4 + len;
4382                         SIVAL(pdata,0,len);
4383                         break;
4384
4385                 case SMB_FILE_ALLOCATION_INFORMATION:
4386                 case SMB_QUERY_FILE_ALLOCATION_INFO:
4387                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
4388                         data_size = 8;
4389                         SOFF_T(pdata,0,allocation_size);
4390                         break;
4391
4392                 case SMB_FILE_END_OF_FILE_INFORMATION:
4393                 case SMB_QUERY_FILE_END_OF_FILEINFO:
4394                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
4395                         data_size = 8;
4396                         SOFF_T(pdata,0,file_size);
4397                         break;
4398
4399                 case SMB_QUERY_FILE_ALL_INFO:
4400                 case SMB_FILE_ALL_INFORMATION:
4401                 {
4402                         unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
4403                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
4404                         put_long_date_timespec(pdata,create_time_ts);
4405                         put_long_date_timespec(pdata+8,atime_ts);
4406                         put_long_date_timespec(pdata+16,mtime_ts); /* write time */
4407                         put_long_date_timespec(pdata+24,mtime_ts); /* change time */
4408                         SIVAL(pdata,32,mode);
4409                         SIVAL(pdata,36,0); /* padding. */
4410                         pdata += 40;
4411                         SOFF_T(pdata,0,allocation_size);
4412                         SOFF_T(pdata,8,file_size);
4413                         SIVAL(pdata,16,nlink);
4414                         SCVAL(pdata,20,delete_pending);
4415                         SCVAL(pdata,21,(mode&aDIR)?1:0);
4416                         SSVAL(pdata,22,0);
4417                         pdata += 24;
4418                         SIVAL(pdata,0,ea_size);
4419                         pdata += 4; /* EA info */
4420                         len = srvstr_push(dstart, req->flags2,
4421                                           pdata+4, dos_fname,
4422                                           PTR_DIFF(dend, pdata+4),
4423                                           STR_UNICODE);
4424                         SIVAL(pdata,0,len);
4425                         pdata += 4 + len;
4426                         data_size = PTR_DIFF(pdata,(*ppdata));
4427                         break;
4428                 }
4429                 case SMB_FILE_INTERNAL_INFORMATION:
4430                         /* This should be an index number - looks like
4431                            dev/ino to me :-) 
4432
4433                            I think this causes us to fail the IFSKIT
4434                            BasicFileInformationTest. -tpot */
4435
4436                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
4437                         SIVAL(pdata,0,sbuf.st_ino); /* FileIndexLow */
4438                         SIVAL(pdata,4,sbuf.st_dev); /* FileIndexHigh */
4439                         data_size = 8;
4440                         break;
4441
4442                 case SMB_FILE_ACCESS_INFORMATION:
4443                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
4444                         if (fsp) {
4445                                 SIVAL(pdata,0,fsp->access_mask);
4446                         } else {
4447                                 /* GENERIC_EXECUTE mapping from Windows */
4448                                 SIVAL(pdata,0,0x12019F);
4449                         }
4450                         data_size = 4;
4451                         break;
4452
4453                 case SMB_FILE_NAME_INFORMATION:
4454                         /* Pathname with leading '\'. */
4455                         {
4456                                 size_t byte_len;
4457                                 byte_len = dos_PutUniCode(pdata+4,dos_fname,(size_t)max_data_bytes,False);
4458                                 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
4459                                 SIVAL(pdata,0,byte_len);
4460                                 data_size = 4 + byte_len;
4461                                 break;
4462                         }
4463
4464                 case SMB_FILE_DISPOSITION_INFORMATION:
4465                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
4466                         data_size = 1;
4467                         SCVAL(pdata,0,delete_pending);
4468                         break;
4469
4470                 case SMB_FILE_POSITION_INFORMATION:
4471                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
4472                         data_size = 8;
4473                         SOFF_T(pdata,0,pos);
4474                         break;
4475
4476                 case SMB_FILE_MODE_INFORMATION:
4477                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
4478                         SIVAL(pdata,0,mode);
4479                         data_size = 4;
4480                         break;
4481
4482                 case SMB_FILE_ALIGNMENT_INFORMATION:
4483                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
4484                         SIVAL(pdata,0,0); /* No alignment needed. */
4485                         data_size = 4;
4486                         break;
4487
4488                 /*
4489                  * NT4 server just returns "invalid query" to this - if we try
4490                  * to answer it then NTws gets a BSOD! (tridge).  W2K seems to
4491                  * want this. JRA.
4492                  */
4493                 /* The first statement above is false - verified using Thursby
4494                  * client against NT4 -- gcolley.
4495                  */
4496                 case SMB_QUERY_FILE_STREAM_INFO:
4497                 case SMB_FILE_STREAM_INFORMATION: {
4498                         unsigned int num_streams;
4499                         struct stream_struct *streams;
4500                         NTSTATUS status;
4501
4502                         DEBUG(10,("call_trans2qfilepathinfo: "
4503                                   "SMB_FILE_STREAM_INFORMATION\n"));
4504
4505                         status = SMB_VFS_STREAMINFO(
4506                                 conn, fsp, fname, talloc_tos(),
4507                                 &num_streams, &streams);
4508
4509                         if (!NT_STATUS_IS_OK(status)) {
4510                                 DEBUG(10, ("could not get stream info: %s\n",
4511                                            nt_errstr(status)));
4512                                 reply_nterror(req, status);
4513                                 return;
4514                         }
4515
4516                         status = marshall_stream_info(num_streams, streams,
4517                                                       pdata, max_data_bytes,
4518                                                       &data_size);
4519
4520                         if (!NT_STATUS_IS_OK(status)) {
4521                                 DEBUG(10, ("marshall_stream_info failed: %s\n",
4522                                            nt_errstr(status)));
4523                                 reply_nterror(req, status);
4524                                 return;
4525                         }
4526
4527                         TALLOC_FREE(streams);
4528
4529                         break;
4530                 }
4531                 case SMB_QUERY_COMPRESSION_INFO:
4532                 case SMB_FILE_COMPRESSION_INFORMATION:
4533                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
4534                         SOFF_T(pdata,0,file_size);
4535                         SIVAL(pdata,8,0); /* ??? */
4536                         SIVAL(pdata,12,0); /* ??? */
4537                         data_size = 16;
4538                         break;
4539
4540                 case SMB_FILE_NETWORK_OPEN_INFORMATION:
4541                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
4542                         put_long_date_timespec(pdata,create_time_ts);
4543                         put_long_date_timespec(pdata+8,atime_ts);
4544                         put_long_date_timespec(pdata+16,mtime_ts); /* write time */
4545                         put_long_date_timespec(pdata+24,mtime_ts); /* change time */
4546                         SOFF_T(pdata,32,allocation_size);
4547                         SOFF_T(pdata,40,file_size);
4548                         SIVAL(pdata,48,mode);
4549                         SIVAL(pdata,52,0); /* ??? */
4550                         data_size = 56;
4551                         break;
4552
4553                 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
4554                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
4555                         SIVAL(pdata,0,mode);
4556                         SIVAL(pdata,4,0);
4557                         data_size = 8;
4558                         break;
4559
4560                 /*
4561                  * CIFS UNIX Extensions.
4562                  */
4563
4564                 case SMB_QUERY_FILE_UNIX_BASIC:
4565
4566                         pdata = store_file_unix_basic(conn, pdata, fsp, &sbuf);
4567                         data_size = PTR_DIFF(pdata,(*ppdata));
4568
4569                         {
4570                                 int i;
4571                                 DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_BASIC "));
4572
4573                                 for (i=0; i<100; i++)
4574                                         DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
4575                                 DEBUG(4,("\n"));
4576                         }
4577
4578                         break;
4579
4580                 case SMB_QUERY_FILE_UNIX_INFO2:
4581
4582                         pdata = store_file_unix_basic_info2(conn, pdata, fsp, &sbuf);
4583                         data_size = PTR_DIFF(pdata,(*ppdata));
4584
4585                         {
4586                                 int i;
4587                                 DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
4588
4589                                 for (i=0; i<100; i++)
4590                                         DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
4591                                 DEBUG(4,("\n"));
4592                         }
4593
4594                         break;
4595
4596                 case SMB_QUERY_FILE_UNIX_LINK:
4597                         {
4598                                 char *buffer = TALLOC_ARRAY(ctx, char, PATH_MAX+1);
4599
4600                                 if (!buffer) {
4601                                         reply_nterror(req, NT_STATUS_NO_MEMORY);
4602                                         return;
4603                                 }
4604
4605                                 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
4606 #ifdef S_ISLNK
4607                                 if(!S_ISLNK(sbuf.st_mode)) {
4608                                         reply_unixerror(req, ERRSRV,
4609                                                         ERRbadlink);
4610                                         return;
4611                                 }
4612 #else
4613                                 reply_unixerror(req, ERRDOS, ERRbadlink);
4614                                 return;
4615 #endif
4616                                 len = SMB_VFS_READLINK(conn,fullpathname,
4617                                                 buffer, PATH_MAX);
4618                                 if (len == -1) {
4619                                         reply_unixerror(req, ERRDOS,
4620                                                         ERRnoaccess);
4621                                         return;
4622                                 }
4623                                 buffer[len] = 0;
4624                                 len = srvstr_push(dstart, req->flags2,
4625                                                   pdata, buffer,
4626                                                   PTR_DIFF(dend, pdata),
4627                                                   STR_TERMINATE);
4628                                 pdata += len;
4629                                 data_size = PTR_DIFF(pdata,(*ppdata));
4630
4631                                 break;
4632                         }
4633
4634 #if defined(HAVE_POSIX_ACLS)
4635                 case SMB_QUERY_POSIX_ACL:
4636                         {
4637                                 SMB_ACL_T file_acl = NULL;
4638                                 SMB_ACL_T def_acl = NULL;
4639                                 uint16 num_file_acls = 0;
4640                                 uint16 num_def_acls = 0;
4641
4642                                 if (fsp && !fsp->is_directory && (fsp->fh->fd != -1)) {
4643                                         file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp);
4644                                 } else {
4645                                         file_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_ACCESS);
4646                                 }
4647
4648                                 if (file_acl == NULL && no_acl_syscall_error(errno)) {
4649                                         DEBUG(5,("call_trans2qfilepathinfo: ACLs not implemented on filesystem containing %s\n",
4650                                                 fname ));
4651                                         reply_nterror(
4652                                                 req,
4653                                                 NT_STATUS_NOT_IMPLEMENTED);
4654                                         return;
4655                                 }
4656
4657                                 if (S_ISDIR(sbuf.st_mode)) {
4658                                         if (fsp && fsp->is_directory) {
4659                                                 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fsp->fsp_name, SMB_ACL_TYPE_DEFAULT);
4660                                         } else {
4661                                                 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_DEFAULT);
4662                                         }
4663                                         def_acl = free_empty_sys_acl(conn, def_acl);
4664                                 }
4665
4666                                 num_file_acls = count_acl_entries(conn, file_acl);
4667                                 num_def_acls = count_acl_entries(conn, def_acl);
4668
4669                                 if ( data_size < (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE) {
4670                                         DEBUG(5,("call_trans2qfilepathinfo: data_size too small (%u) need %u\n",
4671                                                 data_size,
4672                                                 (unsigned int)((num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE +
4673                                                         SMB_POSIX_ACL_HEADER_SIZE) ));
4674                                         if (file_acl) {
4675                                                 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4676                                         }
4677                                         if (def_acl) {
4678                                                 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4679                                         }
4680                                         reply_nterror(
4681                                                 req,
4682                                                 NT_STATUS_BUFFER_TOO_SMALL);
4683                                         return;
4684                                 }
4685
4686                                 SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
4687                                 SSVAL(pdata,2,num_file_acls);
4688                                 SSVAL(pdata,4,num_def_acls);
4689                                 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE, &sbuf, file_acl)) {
4690                                         if (file_acl) {
4691                                                 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4692                                         }
4693                                         if (def_acl) {
4694                                                 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4695                                         }
4696                                         reply_nterror(
4697                                                 req, NT_STATUS_INTERNAL_ERROR);
4698                                         return;
4699                                 }
4700                                 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE + (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE), &sbuf, def_acl)) {
4701                                         if (file_acl) {
4702                                                 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4703                                         }
4704                                         if (def_acl) {
4705                                                 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4706                                         }
4707                                         reply_nterror(
4708                                                 req,
4709                                                 NT_STATUS_INTERNAL_ERROR);
4710                                         return;
4711                                 }
4712
4713                                 if (file_acl) {
4714                                         SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4715                                 }
4716                                 if (def_acl) {
4717                                         SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4718                                 }
4719                                 data_size = (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE;
4720                                 break;
4721                         }
4722 #endif
4723
4724
4725                 case SMB_QUERY_POSIX_LOCK:
4726                 {
4727                         NTSTATUS status = NT_STATUS_INVALID_LEVEL;
4728                         uint64_t count;
4729                         uint64_t offset;
4730                         uint32 lock_pid;
4731                         enum brl_type lock_type;
4732
4733                         if (total_data != POSIX_LOCK_DATA_SIZE) {
4734                                 reply_nterror(
4735                                         req, NT_STATUS_INVALID_PARAMETER);
4736                                 return;
4737                         }
4738
4739                         switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
4740                                 case POSIX_LOCK_TYPE_READ:
4741                                         lock_type = READ_LOCK;
4742                                         break;
4743                                 case POSIX_LOCK_TYPE_WRITE:
4744                                         lock_type = WRITE_LOCK;
4745                                         break;
4746                                 case POSIX_LOCK_TYPE_UNLOCK:
4747                                 default:
4748                                         /* There's no point in asking for an unlock... */
4749                                         reply_nterror(
4750                                                 req,
4751                                                 NT_STATUS_INVALID_PARAMETER);
4752                                         return;
4753                         }
4754
4755                         lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
4756 #if defined(HAVE_LONGLONG)
4757                         offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
4758                                         ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
4759                         count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
4760                                         ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
4761 #else /* HAVE_LONGLONG */
4762                         offset = (uint64_t)IVAL(pdata,POSIX_LOCK_START_OFFSET);
4763                         count = (uint64_t)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
4764 #endif /* HAVE_LONGLONG */
4765
4766                         status = query_lock(fsp,
4767                                         &lock_pid,
4768                                         &count,
4769                                         &offset,
4770                                         &lock_type,
4771                                         POSIX_LOCK);
4772
4773                         if (ERROR_WAS_LOCK_DENIED(status)) {
4774                                 /* Here we need to report who has it locked... */
4775                                 data_size = POSIX_LOCK_DATA_SIZE;
4776
4777                                 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, lock_type);
4778                                 SSVAL(pdata, POSIX_LOCK_FLAGS_OFFSET, 0);
4779                                 SIVAL(pdata, POSIX_LOCK_PID_OFFSET, lock_pid);
4780 #if defined(HAVE_LONGLONG)
4781                                 SIVAL(pdata, POSIX_LOCK_START_OFFSET, (uint32)(offset & 0xFFFFFFFF));
4782                                 SIVAL(pdata, POSIX_LOCK_START_OFFSET + 4, (uint32)((offset >> 32) & 0xFFFFFFFF));
4783                                 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, (uint32)(count & 0xFFFFFFFF));
4784                                 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET + 4, (uint32)((count >> 32) & 0xFFFFFFFF));
4785 #else /* HAVE_LONGLONG */
4786                                 SIVAL(pdata, POSIX_LOCK_START_OFFSET, offset);
4787                                 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, count);
4788 #endif /* HAVE_LONGLONG */
4789
4790                         } else if (NT_STATUS_IS_OK(status)) {
4791                                 /* For success we just return a copy of what we sent
4792                                    with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
4793                                 data_size = POSIX_LOCK_DATA_SIZE;
4794                                 memcpy(pdata, lock_data, POSIX_LOCK_DATA_SIZE);
4795                                 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, POSIX_LOCK_TYPE_UNLOCK);
4796                         } else {
4797                                 reply_nterror(req, status);
4798                                 return;
4799                         }
4800                         break;
4801                 }
4802
4803                 default:
4804                         reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4805                         return;
4806         }
4807
4808         send_trans2_replies(conn, req, params, param_size, *ppdata, data_size,
4809                             max_data_bytes);
4810
4811         return;
4812 }
4813
4814 /****************************************************************************
4815  Set a hard link (called by UNIX extensions and by NT rename with HARD link
4816  code.
4817 ****************************************************************************/
4818
4819 NTSTATUS hardlink_internals(TALLOC_CTX *ctx,
4820                 connection_struct *conn,
4821                 const char *oldname_in,
4822                 const char *newname_in)
4823 {
4824         SMB_STRUCT_STAT sbuf1, sbuf2;
4825         char *last_component_oldname = NULL;
4826         char *last_component_newname = NULL;
4827         char *oldname = NULL;
4828         char *newname = NULL;
4829         NTSTATUS status = NT_STATUS_OK;
4830
4831         ZERO_STRUCT(sbuf1);
4832         ZERO_STRUCT(sbuf2);
4833
4834         status = unix_convert(ctx, conn, oldname_in, False, &oldname,
4835                         &last_component_oldname, &sbuf1);
4836         if (!NT_STATUS_IS_OK(status)) {
4837                 return status;
4838         }
4839
4840         status = check_name(conn, oldname);
4841         if (!NT_STATUS_IS_OK(status)) {
4842                 return status;
4843         }
4844
4845         /* source must already exist. */
4846         if (!VALID_STAT(sbuf1)) {
4847                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4848         }
4849
4850         status = unix_convert(ctx, conn, newname_in, False, &newname,
4851                         &last_component_newname, &sbuf2);
4852         if (!NT_STATUS_IS_OK(status)) {
4853                 return status;
4854         }
4855
4856         status = check_name(conn, newname);
4857         if (!NT_STATUS_IS_OK(status)) {
4858                 return status;
4859         }
4860
4861         /* Disallow if newname already exists. */
4862         if (VALID_STAT(sbuf2)) {
4863                 return NT_STATUS_OBJECT_NAME_COLLISION;
4864         }
4865
4866         /* No links from a directory. */
4867         if (S_ISDIR(sbuf1.st_mode)) {
4868                 return NT_STATUS_FILE_IS_A_DIRECTORY;
4869         }
4870
4871         /* Ensure this is within the share. */
4872         status = check_reduced_name(conn, oldname);
4873         if (!NT_STATUS_IS_OK(status)) {
4874                 return status;
4875         }
4876
4877         DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n", newname, oldname ));
4878
4879         if (SMB_VFS_LINK(conn,oldname,newname) != 0) {
4880                 status = map_nt_error_from_unix(errno);
4881                 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
4882                                 nt_errstr(status), newname, oldname));
4883         }
4884
4885         return status;
4886 }
4887
4888 /****************************************************************************
4889  Deal with setting the time from any of the setfilepathinfo functions.
4890 ****************************************************************************/
4891
4892 NTSTATUS smb_set_file_time(connection_struct *conn,
4893                            files_struct *fsp,
4894                            const char *fname,
4895                            const SMB_STRUCT_STAT *psbuf,
4896                            struct smb_file_time *ft,
4897                            bool setting_write_time)
4898 {
4899         uint32 action =
4900                 FILE_NOTIFY_CHANGE_LAST_ACCESS
4901                 |FILE_NOTIFY_CHANGE_LAST_WRITE;
4902
4903         if (!VALID_STAT(*psbuf)) {
4904                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4905         }
4906
4907         /* get some defaults (no modifications) if any info is zero or -1. */
4908         if (null_timespec(ft->atime)) {
4909                 ft->atime= get_atimespec(psbuf);
4910                 action &= ~FILE_NOTIFY_CHANGE_LAST_ACCESS;
4911         }
4912
4913         if (null_timespec(ft->mtime)) {
4914                 ft->mtime = get_mtimespec(psbuf);
4915                 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
4916         }
4917
4918         if (!setting_write_time) {
4919                 /* ft->mtime comes from change time, not write time. */
4920                 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
4921         }
4922
4923         DEBUG(5,("smb_set_filetime: actime: %s\n ",
4924                 time_to_asc(convert_timespec_to_time_t(ft->atime))));
4925         DEBUG(5,("smb_set_filetime: modtime: %s\n ",
4926                 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
4927         if (!null_timespec(ft->create_time)) {
4928                 DEBUG(5,("smb_set_file_time: createtime: %s\n ",
4929                    time_to_asc(convert_timespec_to_time_t(ft->create_time))));
4930         }
4931
4932         /*
4933          * Try and set the times of this file if
4934          * they are different from the current values.
4935          */
4936
4937         {
4938                 struct timespec mts = get_mtimespec(psbuf);
4939                 struct timespec ats = get_atimespec(psbuf);
4940                 if ((timespec_compare(&ft->atime, &ats) == 0) &&
4941                     (timespec_compare(&ft->mtime, &mts) == 0)) {
4942                         return NT_STATUS_OK;
4943                 }
4944         }
4945
4946         if (setting_write_time) {
4947                 /*
4948                  * This was a setfileinfo on an open file.
4949                  * NT does this a lot. We also need to 
4950                  * set the time here, as it can be read by 
4951                  * FindFirst/FindNext and with the patch for bug #2045
4952                  * in smbd/fileio.c it ensures that this timestamp is
4953                  * kept sticky even after a write. We save the request
4954                  * away and will set it on file close and after a write. JRA.
4955                  */
4956
4957                 DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n",
4958                           time_to_asc(convert_timespec_to_time_t(ft->mtime))));
4959
4960                 if (fsp != NULL) {
4961                         if (fsp->base_fsp) {
4962                                 set_sticky_write_time_fsp(fsp->base_fsp,
4963                                                           ft->mtime);
4964                         } else {
4965                                 set_sticky_write_time_fsp(fsp, ft->mtime);
4966                         }
4967                 } else {
4968                         set_sticky_write_time_path(conn, fname,
4969                                             vfs_file_id_from_sbuf(conn, psbuf),
4970                                             ft->mtime);
4971                 }
4972         }
4973
4974         DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
4975
4976         if (fsp && fsp->base_fsp) {
4977                 fname = fsp->base_fsp->fsp_name;
4978         }
4979
4980         if(file_ntimes(conn, fname, ft)!=0) {
4981                 return map_nt_error_from_unix(errno);
4982         }
4983         notify_fname(conn, NOTIFY_ACTION_MODIFIED, action, fname);
4984
4985         return NT_STATUS_OK;
4986 }
4987
4988 /****************************************************************************
4989  Deal with setting the dosmode from any of the setfilepathinfo functions.
4990 ****************************************************************************/
4991
4992 static NTSTATUS smb_set_file_dosmode(connection_struct *conn,
4993                                 files_struct *fsp,
4994                                 const char *fname,
4995                                 SMB_STRUCT_STAT *psbuf,
4996                                 uint32 dosmode)
4997 {
4998         if (!VALID_STAT(*psbuf)) {
4999                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5000         }
5001
5002         if (fsp) {
5003                 if (fsp->base_fsp) {
5004                         fname = fsp->base_fsp->fsp_name;
5005                 } else {
5006                         fname = fsp->fsp_name;
5007                 }
5008         }
5009                 
5010         if (dosmode) {
5011                 if (S_ISDIR(psbuf->st_mode)) {
5012                         dosmode |= aDIR;
5013                 } else {
5014                         dosmode &= ~aDIR;
5015                 }
5016         }
5017
5018         DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode));
5019
5020         /* check the mode isn't different, before changing it */
5021         if ((dosmode != 0) && (dosmode != dos_mode(conn, fname, psbuf))) {
5022
5023                 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode 0x%x\n",
5024                                         fname, (unsigned int)dosmode ));
5025
5026                 if(file_set_dosmode(conn, fname, dosmode, psbuf, NULL, false)) {
5027                         DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of %s failed (%s)\n",
5028                                                 fname, strerror(errno)));
5029                         return map_nt_error_from_unix(errno);
5030                 }
5031         }
5032         return NT_STATUS_OK;
5033 }
5034
5035 /****************************************************************************
5036  Deal with setting the size from any of the setfilepathinfo functions.
5037 ****************************************************************************/
5038
5039 static NTSTATUS smb_set_file_size(connection_struct *conn,
5040                                   struct smb_request *req,
5041                                 files_struct *fsp,
5042                                 const char *fname,
5043                                 SMB_STRUCT_STAT *psbuf,
5044                                 SMB_OFF_T size)
5045 {
5046         NTSTATUS status = NT_STATUS_OK;
5047         files_struct *new_fsp = NULL;
5048
5049         if (!VALID_STAT(*psbuf)) {
5050                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5051         }
5052
5053         DEBUG(6,("smb_set_file_size: size: %.0f ", (double)size));
5054
5055         if (size == get_file_size_stat(psbuf)) {
5056                 return NT_STATUS_OK;
5057         }
5058
5059         DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
5060                 fname, (double)size ));
5061
5062         if (fsp && fsp->fh->fd != -1) {
5063                 /* Handle based call. */
5064                 if (vfs_set_filelen(fsp, size) == -1) {
5065                         return map_nt_error_from_unix(errno);
5066                 }
5067                 trigger_write_time_update_immediate(fsp);
5068                 return NT_STATUS_OK;
5069         }
5070
5071         status = SMB_VFS_CREATE_FILE(
5072                 conn,                                   /* conn */
5073                 req,                                    /* req */
5074                 0,                                      /* root_dir_fid */
5075                 fname,                                  /* fname */
5076                 0,                                      /* create_file_flags */
5077                 FILE_WRITE_ATTRIBUTES,                  /* access_mask */
5078                 (FILE_SHARE_READ | FILE_SHARE_WRITE |   /* share_access */
5079                     FILE_SHARE_DELETE),
5080                 FILE_OPEN,                              /* create_disposition*/
5081                 0,                                      /* create_options */
5082                 FILE_ATTRIBUTE_NORMAL,                  /* file_attributes */
5083                 FORCE_OPLOCK_BREAK_TO_NONE,             /* oplock_request */
5084                 0,                                      /* allocation_size */
5085                 NULL,                                   /* sd */
5086                 NULL,                                   /* ea_list */
5087                 &new_fsp,                               /* result */
5088                 NULL,                                   /* pinfo */
5089                 psbuf);                                 /* psbuf */
5090
5091         if (!NT_STATUS_IS_OK(status)) {
5092                 /* NB. We check for open_was_deferred in the caller. */
5093                 return status;
5094         }
5095
5096         if (vfs_set_filelen(new_fsp, size) == -1) {
5097                 status = map_nt_error_from_unix(errno);
5098                 close_file(req, new_fsp,NORMAL_CLOSE);
5099                 return status;
5100         }
5101
5102         trigger_write_time_update_immediate(new_fsp);
5103         close_file(req, new_fsp,NORMAL_CLOSE);
5104         return NT_STATUS_OK;
5105 }
5106
5107 /****************************************************************************
5108  Deal with SMB_INFO_SET_EA.
5109 ****************************************************************************/
5110
5111 static NTSTATUS smb_info_set_ea(connection_struct *conn,
5112                                 const char *pdata,
5113                                 int total_data,
5114                                 files_struct *fsp,
5115                                 const char *fname)
5116 {
5117         struct ea_list *ea_list = NULL;
5118         TALLOC_CTX *ctx = NULL;
5119         NTSTATUS status = NT_STATUS_OK;
5120
5121         if (total_data < 10) {
5122
5123                 /* OS/2 workplace shell seems to send SET_EA requests of "null"
5124                    length. They seem to have no effect. Bug #3212. JRA */
5125
5126                 if ((total_data == 4) && (IVAL(pdata,0) == 4)) {
5127                         /* We're done. We only get EA info in this call. */
5128                         return NT_STATUS_OK;
5129                 }
5130
5131                 return NT_STATUS_INVALID_PARAMETER;
5132         }
5133
5134         if (IVAL(pdata,0) > total_data) {
5135                 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
5136                         IVAL(pdata,0), (unsigned int)total_data));
5137                 return NT_STATUS_INVALID_PARAMETER;
5138         }
5139
5140         ctx = talloc_tos();
5141         ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
5142         if (!ea_list) {
5143                 return NT_STATUS_INVALID_PARAMETER;
5144         }
5145         status = set_ea(conn, fsp, fname, ea_list);
5146
5147         return status;
5148 }
5149
5150 /****************************************************************************
5151  Deal with SMB_SET_FILE_DISPOSITION_INFO.
5152 ****************************************************************************/
5153
5154 static NTSTATUS smb_set_file_disposition_info(connection_struct *conn,
5155                                 const char *pdata,
5156                                 int total_data,
5157                                 files_struct *fsp,
5158                                 const char *fname,
5159                                 SMB_STRUCT_STAT *psbuf)
5160 {
5161         NTSTATUS status = NT_STATUS_OK;
5162         bool delete_on_close;
5163         uint32 dosmode = 0;
5164
5165         if (total_data < 1) {
5166                 return NT_STATUS_INVALID_PARAMETER;
5167         }
5168
5169         if (fsp == NULL) {
5170                 return NT_STATUS_INVALID_HANDLE;
5171         }
5172
5173         delete_on_close = (CVAL(pdata,0) ? True : False);
5174         dosmode = dos_mode(conn, fname, psbuf);
5175
5176         DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
5177                 "delete_on_close = %u\n",
5178                 fsp->fsp_name,
5179                 (unsigned int)dosmode,
5180                 (unsigned int)delete_on_close ));
5181
5182         status = can_set_delete_on_close(fsp, delete_on_close, dosmode);
5183  
5184         if (!NT_STATUS_IS_OK(status)) {
5185                 return status;
5186         }
5187
5188         /* The set is across all open files on this dev/inode pair. */
5189         if (!set_delete_on_close(fsp, delete_on_close,
5190                                  &conn->server_info->utok)) {
5191                 return NT_STATUS_ACCESS_DENIED;
5192         }
5193         return NT_STATUS_OK;
5194 }
5195
5196 /****************************************************************************
5197  Deal with SMB_FILE_POSITION_INFORMATION.
5198 ****************************************************************************/
5199
5200 static NTSTATUS smb_file_position_information(connection_struct *conn,
5201                                 const char *pdata,
5202                                 int total_data,
5203                                 files_struct *fsp)
5204 {
5205         uint64_t position_information;
5206
5207         if (total_data < 8) {
5208                 return NT_STATUS_INVALID_PARAMETER;
5209         }
5210
5211         if (fsp == NULL) {
5212                 /* Ignore on pathname based set. */
5213                 return NT_STATUS_OK;
5214         }
5215
5216         position_information = (uint64_t)IVAL(pdata,0);
5217 #ifdef LARGE_SMB_OFF_T
5218         position_information |= (((uint64_t)IVAL(pdata,4)) << 32);
5219 #else /* LARGE_SMB_OFF_T */
5220         if (IVAL(pdata,4) != 0) {
5221                 /* more than 32 bits? */
5222                 return NT_STATUS_INVALID_PARAMETER;
5223         }
5224 #endif /* LARGE_SMB_OFF_T */
5225
5226         DEBUG(10,("smb_file_position_information: Set file position information for file %s to %.0f\n",
5227                 fsp->fsp_name, (double)position_information ));
5228         fsp->fh->position_information = position_information;
5229         return NT_STATUS_OK;
5230 }
5231
5232 /****************************************************************************
5233  Deal with SMB_FILE_MODE_INFORMATION.
5234 ****************************************************************************/
5235
5236 static NTSTATUS smb_file_mode_information(connection_struct *conn,
5237                                 const char *pdata,
5238                                 int total_data)
5239 {
5240         uint32 mode;
5241
5242         if (total_data < 4) {
5243                 return NT_STATUS_INVALID_PARAMETER;
5244         }
5245         mode = IVAL(pdata,0);
5246         if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
5247                 return NT_STATUS_INVALID_PARAMETER;
5248         }
5249         return NT_STATUS_OK;
5250 }
5251
5252 /****************************************************************************
5253  Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
5254 ****************************************************************************/
5255
5256 static NTSTATUS smb_set_file_unix_link(connection_struct *conn,
5257                                        struct smb_request *req,
5258                                        const char *pdata,
5259                                        int total_data,
5260                                        const char *fname)
5261 {
5262         char *link_target = NULL;
5263         const char *newname = fname;
5264         NTSTATUS status = NT_STATUS_OK;
5265         TALLOC_CTX *ctx = talloc_tos();
5266
5267         /* Set a symbolic link. */
5268         /* Don't allow this if follow links is false. */
5269
5270         if (total_data == 0) {
5271                 return NT_STATUS_INVALID_PARAMETER;
5272         }
5273
5274         if (!lp_symlinks(SNUM(conn))) {
5275                 return NT_STATUS_ACCESS_DENIED;
5276         }
5277
5278         srvstr_pull_talloc(ctx, pdata, req->flags2, &link_target, pdata,
5279                     total_data, STR_TERMINATE);
5280
5281         if (!link_target) {
5282                 return NT_STATUS_INVALID_PARAMETER;
5283         }
5284
5285         /* !widelinks forces the target path to be within the share. */
5286         /* This means we can interpret the target as a pathname. */
5287         if (!lp_widelinks(SNUM(conn))) {
5288                 char *rel_name = NULL;
5289                 char *last_dirp = NULL;
5290
5291                 if (*link_target == '/') {
5292                         /* No absolute paths allowed. */
5293                         return NT_STATUS_ACCESS_DENIED;
5294                 }
5295                 rel_name = talloc_strdup(ctx,newname);
5296                 if (!rel_name) {
5297                         return NT_STATUS_NO_MEMORY;
5298                 }
5299                 last_dirp = strrchr_m(rel_name, '/');
5300                 if (last_dirp) {
5301                         last_dirp[1] = '\0';
5302                 } else {
5303                         rel_name = talloc_strdup(ctx,"./");
5304                         if (!rel_name) {
5305                                 return NT_STATUS_NO_MEMORY;
5306                         }
5307                 }
5308                 rel_name = talloc_asprintf_append(rel_name,
5309                                 "%s",
5310                                 link_target);
5311                 if (!rel_name) {
5312                         return NT_STATUS_NO_MEMORY;
5313                 }
5314
5315                 status = check_name(conn, rel_name);
5316                 if (!NT_STATUS_IS_OK(status)) {
5317                         return status;
5318                 }
5319         }
5320
5321         DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
5322                         newname, link_target ));
5323
5324         if (SMB_VFS_SYMLINK(conn,link_target,newname) != 0) {
5325                 return map_nt_error_from_unix(errno);
5326         }
5327
5328         return NT_STATUS_OK;
5329 }
5330
5331 /****************************************************************************
5332  Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
5333 ****************************************************************************/
5334
5335 static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn,
5336                                         struct smb_request *req,
5337                                         const char *pdata, int total_data,
5338                                         const char *fname)
5339 {
5340         char *oldname = NULL;
5341         TALLOC_CTX *ctx = talloc_tos();
5342         NTSTATUS status = NT_STATUS_OK;
5343
5344         /* Set a hard link. */
5345         if (total_data == 0) {
5346                 return NT_STATUS_INVALID_PARAMETER;
5347         }
5348
5349         srvstr_get_path(ctx, pdata, req->flags2, &oldname, pdata,
5350                         total_data, STR_TERMINATE, &status);
5351         if (!NT_STATUS_IS_OK(status)) {
5352                 return status;
5353         }
5354
5355         status = resolve_dfspath(ctx, conn,
5356                                 req->flags2 & FLAGS2_DFS_PATHNAMES,
5357                                 oldname,
5358                                 &oldname);
5359         if (!NT_STATUS_IS_OK(status)) {
5360                 return status;
5361         }
5362
5363         DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
5364                 fname, oldname));
5365
5366         return hardlink_internals(ctx, conn, oldname, fname);
5367 }
5368
5369 /****************************************************************************
5370  Deal with SMB_FILE_RENAME_INFORMATION.
5371 ****************************************************************************/
5372
5373 static NTSTATUS smb_file_rename_information(connection_struct *conn,
5374                                             struct smb_request *req,
5375                                             const char *pdata,
5376                                             int total_data,
5377                                             files_struct *fsp,
5378                                             const char *fname)
5379 {
5380         bool overwrite;
5381         uint32 root_fid;
5382         uint32 len;
5383         char *newname = NULL;
5384         char *base_name = NULL;
5385         bool dest_has_wcard = False;
5386         SMB_STRUCT_STAT sbuf;
5387         char *newname_last_component = NULL;
5388         NTSTATUS status = NT_STATUS_OK;
5389         char *p;
5390         TALLOC_CTX *ctx = talloc_tos();
5391
5392         if (total_data < 13) {
5393                 return NT_STATUS_INVALID_PARAMETER;
5394         }
5395
5396         ZERO_STRUCT(sbuf);
5397
5398         overwrite = (CVAL(pdata,0) ? True : False);
5399         root_fid = IVAL(pdata,4);
5400         len = IVAL(pdata,8);
5401
5402         if (len > (total_data - 12) || (len == 0) || (root_fid != 0)) {
5403                 return NT_STATUS_INVALID_PARAMETER;
5404         }
5405
5406         srvstr_get_path_wcard(ctx, pdata, req->flags2, &newname, &pdata[12],
5407                               len, 0, &status,
5408                               &dest_has_wcard);
5409         if (!NT_STATUS_IS_OK(status)) {
5410                 return status;
5411         }
5412
5413         DEBUG(10,("smb_file_rename_information: got name |%s|\n",
5414                                 newname));
5415
5416         status = resolve_dfspath_wcard(ctx, conn,
5417                                        req->flags2 & FLAGS2_DFS_PATHNAMES,
5418                                        newname,
5419                                        &newname,
5420                                        &dest_has_wcard);
5421         if (!NT_STATUS_IS_OK(status)) {
5422                 return status;
5423         }
5424
5425         /* Check the new name has no '/' characters. */
5426         if (strchr_m(newname, '/')) {
5427                 return NT_STATUS_NOT_SUPPORTED;
5428         }
5429
5430         if (fsp && fsp->base_fsp) {
5431                 /* newname must be a stream name. */
5432                 if (newname[0] != ':') {
5433                         return NT_STATUS_NOT_SUPPORTED;
5434                 }
5435                 base_name = talloc_asprintf(ctx, "%s%s",
5436                                            fsp->base_fsp->fsp_name,
5437                                            newname);
5438                 if (!base_name) {
5439                         return NT_STATUS_NO_MEMORY;
5440                 }
5441         } else {
5442                 /* newname must *not* be a stream name. */
5443                 if (is_ntfs_stream_name(newname)) {
5444                         return NT_STATUS_NOT_SUPPORTED;
5445                 }
5446
5447                 /* Create the base directory. */
5448                 base_name = talloc_strdup(ctx, fname);
5449                 if (!base_name) {
5450                         return NT_STATUS_NO_MEMORY;
5451                 }
5452                 p = strrchr_m(base_name, '/');
5453                 if (p) {
5454                         p[1] = '\0';
5455                 } else {
5456                         base_name = talloc_strdup(ctx, "./");
5457                         if (!base_name) {
5458                                 return NT_STATUS_NO_MEMORY;
5459                         }
5460                 }
5461                 /* Append the new name. */
5462                 base_name = talloc_asprintf_append(base_name,
5463                                 "%s",
5464                                 newname);
5465                 if (!base_name) {
5466                         return NT_STATUS_NO_MEMORY;
5467                 }
5468
5469                 status = unix_convert(ctx, conn, newname, False,
5470                                 &newname,
5471                                 &newname_last_component,
5472                                 &sbuf);
5473
5474                 /* If an error we expect this to be
5475                  * NT_STATUS_OBJECT_PATH_NOT_FOUND */
5476
5477                 if (!NT_STATUS_IS_OK(status)
5478                     && !NT_STATUS_EQUAL(NT_STATUS_OBJECT_PATH_NOT_FOUND,
5479                                         status)) {
5480                         return status;
5481                 }
5482         }
5483
5484         if (fsp) {
5485                 DEBUG(10,("smb_file_rename_information: SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
5486                         fsp->fnum, fsp->fsp_name, base_name ));
5487                 status = rename_internals_fsp(conn, fsp, base_name,
5488                                               newname_last_component, 0,
5489                                               overwrite);
5490         } else {
5491                 DEBUG(10,("smb_file_rename_information: SMB_FILE_RENAME_INFORMATION %s -> %s\n",
5492                         fname, base_name ));
5493                 status = rename_internals(ctx, conn, req, fname, base_name, 0,
5494                                         overwrite, False, dest_has_wcard,
5495                                         FILE_WRITE_ATTRIBUTES);
5496         }
5497
5498         return status;
5499 }
5500
5501 /****************************************************************************
5502  Deal with SMB_SET_POSIX_ACL.
5503 ****************************************************************************/
5504
5505 #if defined(HAVE_POSIX_ACLS)
5506 static NTSTATUS smb_set_posix_acl(connection_struct *conn,
5507                                 const char *pdata,
5508                                 int total_data,
5509                                 files_struct *fsp,
5510                                 const char *fname,
5511                                 SMB_STRUCT_STAT *psbuf)
5512 {
5513         uint16 posix_acl_version;
5514         uint16 num_file_acls;
5515         uint16 num_def_acls;
5516         bool valid_file_acls = True;
5517         bool valid_def_acls = True;
5518
5519         if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
5520                 return NT_STATUS_INVALID_PARAMETER;
5521         }
5522         posix_acl_version = SVAL(pdata,0);
5523         num_file_acls = SVAL(pdata,2);
5524         num_def_acls = SVAL(pdata,4);
5525
5526         if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
5527                 valid_file_acls = False;
5528                 num_file_acls = 0;
5529         }
5530
5531         if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
5532                 valid_def_acls = False;
5533                 num_def_acls = 0;
5534         }
5535
5536         if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
5537                 return NT_STATUS_INVALID_PARAMETER;
5538         }
5539
5540         if (total_data < SMB_POSIX_ACL_HEADER_SIZE +
5541                         (num_file_acls+num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE) {
5542                 return NT_STATUS_INVALID_PARAMETER;
5543         }
5544
5545         DEBUG(10,("smb_set_posix_acl: file %s num_file_acls = %u, num_def_acls = %u\n",
5546                 fname ? fname : fsp->fsp_name,
5547                 (unsigned int)num_file_acls,
5548                 (unsigned int)num_def_acls));
5549
5550         if (valid_file_acls && !set_unix_posix_acl(conn, fsp, fname, num_file_acls,
5551                         pdata + SMB_POSIX_ACL_HEADER_SIZE)) {
5552                 return map_nt_error_from_unix(errno);
5553         }
5554
5555         if (valid_def_acls && !set_unix_posix_default_acl(conn, fname, psbuf, num_def_acls,
5556                         pdata + SMB_POSIX_ACL_HEADER_SIZE +
5557                         (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE))) {
5558                 return map_nt_error_from_unix(errno);
5559         }
5560         return NT_STATUS_OK;
5561 }
5562 #endif
5563
5564 /****************************************************************************
5565  Deal with SMB_SET_POSIX_LOCK.
5566 ****************************************************************************/
5567
5568 static NTSTATUS smb_set_posix_lock(connection_struct *conn,
5569                                 struct smb_request *req,
5570                                 const char *pdata,
5571                                 int total_data,
5572                                 files_struct *fsp)
5573 {
5574         uint64_t count;
5575         uint64_t offset;
5576         uint32 lock_pid;
5577         bool blocking_lock = False;
5578         enum brl_type lock_type;
5579
5580         NTSTATUS status = NT_STATUS_OK;
5581
5582         if (fsp == NULL || fsp->fh->fd == -1) {
5583                 return NT_STATUS_INVALID_HANDLE;
5584         }
5585
5586         if (total_data != POSIX_LOCK_DATA_SIZE) {
5587                 return NT_STATUS_INVALID_PARAMETER;
5588         }
5589
5590         switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
5591                 case POSIX_LOCK_TYPE_READ:
5592                         lock_type = READ_LOCK;
5593                         break;
5594                 case POSIX_LOCK_TYPE_WRITE:
5595                         /* Return the right POSIX-mappable error code for files opened read-only. */
5596                         if (!fsp->can_write) {
5597                                 return NT_STATUS_INVALID_HANDLE;
5598                         }
5599                         lock_type = WRITE_LOCK;
5600                         break;
5601                 case POSIX_LOCK_TYPE_UNLOCK:
5602                         lock_type = UNLOCK_LOCK;
5603                         break;
5604                 default:
5605                         return NT_STATUS_INVALID_PARAMETER;
5606         }
5607
5608         if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_NOWAIT) {
5609                 blocking_lock = False;
5610         } else if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_WAIT) {
5611                 blocking_lock = True;
5612         } else {
5613                 return NT_STATUS_INVALID_PARAMETER;
5614         }
5615
5616         if (!lp_blocking_locks(SNUM(conn))) { 
5617                 blocking_lock = False;
5618         }
5619
5620         lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
5621 #if defined(HAVE_LONGLONG)
5622         offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
5623                         ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
5624         count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
5625                         ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
5626 #else /* HAVE_LONGLONG */
5627         offset = (uint64_t)IVAL(pdata,POSIX_LOCK_START_OFFSET);
5628         count = (uint64_t)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
5629 #endif /* HAVE_LONGLONG */
5630
5631         DEBUG(10,("smb_set_posix_lock: file %s, lock_type = %u,"
5632                         "lock_pid = %u, count = %.0f, offset = %.0f\n",
5633                 fsp->fsp_name,
5634                 (unsigned int)lock_type,
5635                 (unsigned int)lock_pid,
5636                 (double)count,
5637                 (double)offset ));
5638
5639         if (lock_type == UNLOCK_LOCK) {
5640                 status = do_unlock(smbd_messaging_context(),
5641                                 fsp,
5642                                 lock_pid,
5643                                 count,
5644                                 offset,
5645                                 POSIX_LOCK);
5646         } else {
5647                 uint32 block_smbpid;
5648
5649                 struct byte_range_lock *br_lck = do_lock(smbd_messaging_context(),
5650                                                         fsp,
5651                                                         lock_pid,
5652                                                         count,
5653                                                         offset,
5654                                                         lock_type,
5655                                                         POSIX_LOCK,
5656                                                         blocking_lock,
5657                                                         &status,
5658                                                         &block_smbpid,
5659                                                         NULL);
5660
5661                 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
5662                         /*
5663                          * A blocking lock was requested. Package up
5664                          * this smb into a queued request and push it
5665                          * onto the blocking lock queue.
5666                          */
5667                         if(push_blocking_lock_request(br_lck,
5668                                                 req,
5669                                                 fsp,
5670                                                 -1, /* infinite timeout. */
5671                                                 0,
5672                                                 lock_pid,
5673                                                 lock_type,
5674                                                 POSIX_LOCK,
5675                                                 offset,
5676                                                 count,
5677                                                 block_smbpid)) {
5678                                 TALLOC_FREE(br_lck);
5679                                 return status;
5680                         }
5681                 }
5682                 TALLOC_FREE(br_lck);
5683         }
5684
5685         return status;
5686 }
5687
5688 /****************************************************************************
5689  Deal with SMB_INFO_STANDARD.
5690 ****************************************************************************/
5691
5692 static NTSTATUS smb_set_info_standard(connection_struct *conn,
5693                                         const char *pdata,
5694                                         int total_data,
5695                                         files_struct *fsp,
5696                                         const char *fname,
5697                                         const SMB_STRUCT_STAT *psbuf)
5698 {
5699         struct smb_file_time ft;
5700         ZERO_STRUCT(ft);
5701
5702         if (total_data < 12) {
5703                 return NT_STATUS_INVALID_PARAMETER;
5704         }
5705
5706         /* create time */
5707         ft.create_time = interpret_long_date(pdata);
5708
5709         /* access time */
5710         ft.atime = interpret_long_date(pdata + 8);
5711
5712         /* write time */
5713         ft.mtime = interpret_long_date(pdata + 16);
5714
5715         DEBUG(10,("smb_set_info_standard: file %s\n",
5716                 fname ? fname : fsp->fsp_name ));
5717
5718         return smb_set_file_time(conn,
5719                                 fsp,
5720                                 fname,
5721                                 psbuf,
5722                                 &ft,
5723                                 true);
5724 }
5725
5726 /****************************************************************************
5727  Deal with SMB_SET_FILE_BASIC_INFO.
5728 ****************************************************************************/
5729
5730 static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
5731                                         const char *pdata,
5732                                         int total_data,
5733                                         files_struct *fsp,
5734                                         const char *fname,
5735                                         SMB_STRUCT_STAT *psbuf)
5736 {
5737         /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
5738         struct timespec write_time;
5739         struct timespec changed_time;
5740         struct smb_file_time ft;
5741         uint32 dosmode = 0;
5742         NTSTATUS status = NT_STATUS_OK;
5743         bool setting_write_time = true;
5744
5745         ZERO_STRUCT(ft);
5746
5747         if (total_data < 36) {
5748                 return NT_STATUS_INVALID_PARAMETER;
5749         }
5750
5751         /* Set the attributes */
5752         dosmode = IVAL(pdata,32);
5753         status = smb_set_file_dosmode(conn, fsp, fname, psbuf, dosmode);
5754         if (!NT_STATUS_IS_OK(status)) {
5755                 return status;
5756         }
5757
5758         /* access time */
5759         ft.atime = interpret_long_date(pdata+8);
5760
5761         write_time = interpret_long_date(pdata+16);
5762         changed_time = interpret_long_date(pdata+24);
5763
5764         /* mtime */
5765         ft.mtime = timespec_min(&write_time, &changed_time);
5766
5767         /* create time */
5768         ft.create_time = interpret_long_date(pdata);
5769
5770         if ((timespec_compare(&write_time, &ft.mtime) == 1) &&
5771             !null_timespec(write_time)) {
5772                 ft.mtime = write_time;
5773         }
5774
5775         /* Prefer a defined time to an undefined one. */
5776         if (null_timespec(ft.mtime)) {
5777                 if (null_timespec(write_time)) {
5778                         ft.mtime = changed_time;
5779                         setting_write_time = false;
5780                 } else {
5781                         ft.mtime = write_time;
5782                 }
5783         }
5784
5785         DEBUG(10,("smb_set_file_basic_info: file %s\n",
5786                 fname ? fname : fsp->fsp_name ));
5787
5788         return smb_set_file_time(conn,
5789                                 fsp,
5790                                 fname,
5791                                 psbuf,
5792                                 &ft,
5793                                 setting_write_time);
5794 }
5795
5796 /****************************************************************************
5797  Deal with SMB_SET_FILE_ALLOCATION_INFO.
5798 ****************************************************************************/
5799
5800 static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
5801                                              struct smb_request *req,
5802                                         const char *pdata,
5803                                         int total_data,
5804                                         files_struct *fsp,
5805                                         const char *fname,
5806                                         SMB_STRUCT_STAT *psbuf)
5807 {
5808         uint64_t allocation_size = 0;
5809         NTSTATUS status = NT_STATUS_OK;
5810         files_struct *new_fsp = NULL;
5811
5812         if (!VALID_STAT(*psbuf)) {
5813                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5814         }
5815
5816         if (total_data < 8) {
5817                 return NT_STATUS_INVALID_PARAMETER;
5818         }
5819
5820         allocation_size = (uint64_t)IVAL(pdata,0);
5821 #ifdef LARGE_SMB_OFF_T
5822         allocation_size |= (((uint64_t)IVAL(pdata,4)) << 32);
5823 #else /* LARGE_SMB_OFF_T */
5824         if (IVAL(pdata,4) != 0) {
5825                 /* more than 32 bits? */
5826                 return NT_STATUS_INVALID_PARAMETER;
5827         }
5828 #endif /* LARGE_SMB_OFF_T */
5829
5830         DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for file %s to %.0f\n",
5831                         fname, (double)allocation_size ));
5832
5833         if (allocation_size) {
5834                 allocation_size = smb_roundup(conn, allocation_size);
5835         }
5836
5837         DEBUG(10,("smb_set_file_allocation_info: file %s : setting new allocation size to %.0f\n",
5838                         fname, (double)allocation_size ));
5839
5840         if (fsp && fsp->fh->fd != -1) {
5841                 /* Open file handle. */
5842                 /* Only change if needed. */
5843                 if (allocation_size != get_file_size_stat(psbuf)) {
5844                         if (vfs_allocate_file_space(fsp, allocation_size) == -1) {
5845                                 return map_nt_error_from_unix(errno);
5846                         }
5847                 }
5848                 /* But always update the time. */
5849                 /*
5850                  * This is equivalent to a write. Ensure it's seen immediately
5851                  * if there are no pending writes.
5852                  */
5853                 trigger_write_time_update_immediate(fsp);
5854                 return NT_STATUS_OK;
5855         }
5856
5857         /* Pathname or stat or directory file. */
5858
5859         status = SMB_VFS_CREATE_FILE(
5860                 conn,                                   /* conn */
5861                 req,                                    /* req */
5862                 0,                                      /* root_dir_fid */
5863                 fname,                                  /* fname */
5864                 0,                                      /* create_file_flags */
5865                 FILE_WRITE_DATA,                        /* access_mask */
5866                 (FILE_SHARE_READ | FILE_SHARE_WRITE |   /* share_access */
5867                     FILE_SHARE_DELETE),
5868                 FILE_OPEN,                              /* create_disposition*/
5869                 0,                                      /* create_options */
5870                 FILE_ATTRIBUTE_NORMAL,                  /* file_attributes */
5871                 FORCE_OPLOCK_BREAK_TO_NONE,             /* oplock_request */
5872                 0,                                      /* allocation_size */
5873                 NULL,                                   /* sd */
5874                 NULL,                                   /* ea_list */
5875                 &new_fsp,                               /* result */
5876                 NULL,                                   /* pinfo */
5877                 psbuf);                                 /* psbuf */
5878
5879         if (!NT_STATUS_IS_OK(status)) {
5880                 /* NB. We check for open_was_deferred in the caller. */
5881                 return status;
5882         }
5883
5884         /* Only change if needed. */
5885         if (allocation_size != get_file_size_stat(psbuf)) {
5886                 if (vfs_allocate_file_space(new_fsp, allocation_size) == -1) {
5887                         status = map_nt_error_from_unix(errno);
5888                         close_file(req, new_fsp, NORMAL_CLOSE);
5889                         return status;
5890                 }
5891         }
5892
5893         /* Changing the allocation size should set the last mod time. */
5894         /*
5895          * This is equivalent to a write. Ensure it's seen immediately
5896          * if there are no pending writes.
5897          */
5898         trigger_write_time_update_immediate(new_fsp);
5899
5900         close_file(req, new_fsp, NORMAL_CLOSE);
5901         return NT_STATUS_OK;
5902 }
5903
5904 /****************************************************************************
5905  Deal with SMB_SET_FILE_END_OF_FILE_INFO.
5906 ****************************************************************************/
5907
5908 static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn,
5909                                               struct smb_request *req,
5910                                         const char *pdata,
5911                                         int total_data,
5912                                         files_struct *fsp,
5913                                         const char *fname,
5914                                         SMB_STRUCT_STAT *psbuf)
5915 {
5916         SMB_OFF_T size;
5917
5918         if (total_data < 8) {
5919                 return NT_STATUS_INVALID_PARAMETER;
5920         }
5921
5922         size = IVAL(pdata,0);
5923 #ifdef LARGE_SMB_OFF_T
5924         size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
5925 #else /* LARGE_SMB_OFF_T */
5926         if (IVAL(pdata,4) != 0) {
5927                 /* more than 32 bits? */
5928                 return NT_STATUS_INVALID_PARAMETER;
5929         }
5930 #endif /* LARGE_SMB_OFF_T */
5931         DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
5932                 "file %s to %.0f\n", fname, (double)size ));
5933
5934         return smb_set_file_size(conn, req,
5935                                 fsp,
5936                                 fname,
5937                                 psbuf,
5938                                 size);
5939 }
5940
5941 /****************************************************************************
5942  Allow a UNIX info mknod.
5943 ****************************************************************************/
5944
5945 static NTSTATUS smb_unix_mknod(connection_struct *conn,
5946                                         const char *pdata,
5947                                         int total_data,
5948                                         const char *fname,
5949                                         SMB_STRUCT_STAT *psbuf)
5950 {
5951         uint32 file_type = IVAL(pdata,56);
5952 #if defined(HAVE_MAKEDEV)
5953         uint32 dev_major = IVAL(pdata,60);
5954         uint32 dev_minor = IVAL(pdata,68);
5955 #endif
5956         SMB_DEV_T dev = (SMB_DEV_T)0;
5957         uint32 raw_unixmode = IVAL(pdata,84);
5958         NTSTATUS status;
5959         mode_t unixmode;
5960
5961         if (total_data < 100) {
5962                 return NT_STATUS_INVALID_PARAMETER;
5963         }
5964
5965         status = unix_perms_from_wire(conn, psbuf, raw_unixmode, PERM_NEW_FILE, &unixmode);
5966         if (!NT_STATUS_IS_OK(status)) {
5967                 return status;
5968         }
5969
5970 #if defined(HAVE_MAKEDEV)
5971         dev = makedev(dev_major, dev_minor);
5972 #endif
5973
5974         switch (file_type) {
5975 #if defined(S_IFIFO)
5976                 case UNIX_TYPE_FIFO:
5977                         unixmode |= S_IFIFO;
5978                         break;
5979 #endif
5980 #if defined(S_IFSOCK)
5981                 case UNIX_TYPE_SOCKET:
5982                         unixmode |= S_IFSOCK;
5983                         break;
5984 #endif
5985 #if defined(S_IFCHR)
5986                 case UNIX_TYPE_CHARDEV:
5987                         unixmode |= S_IFCHR;
5988                         break;
5989 #endif
5990 #if defined(S_IFBLK)
5991                 case UNIX_TYPE_BLKDEV:
5992                         unixmode |= S_IFBLK;
5993                         break;
5994 #endif
5995                 default:
5996                         return NT_STATUS_INVALID_PARAMETER;
5997         }
5998
5999         DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev %.0f mode \
6000 0%o for file %s\n", (double)dev, (unsigned int)unixmode, fname ));
6001
6002         /* Ok - do the mknod. */
6003         if (SMB_VFS_MKNOD(conn, fname, unixmode, dev) != 0) {
6004                 return map_nt_error_from_unix(errno);
6005         }
6006
6007         /* If any of the other "set" calls fail we
6008          * don't want to end up with a half-constructed mknod.
6009          */
6010
6011         if (lp_inherit_perms(SNUM(conn))) {
6012                 char *parent;
6013                 if (!parent_dirname(talloc_tos(), fname, &parent, NULL)) {
6014                         return NT_STATUS_NO_MEMORY;
6015                 }
6016                 inherit_access_posix_acl(conn, parent, fname, unixmode);
6017                 TALLOC_FREE(parent);
6018         }
6019
6020         if (SMB_VFS_STAT(conn, fname, psbuf) != 0) {
6021                 status = map_nt_error_from_unix(errno);
6022                 SMB_VFS_UNLINK(conn,fname);
6023                 return status;
6024         }
6025         return NT_STATUS_OK;
6026 }
6027
6028 /****************************************************************************
6029  Deal with SMB_SET_FILE_UNIX_BASIC.
6030 ****************************************************************************/
6031
6032 static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
6033                                         struct smb_request *req,
6034                                         const char *pdata,
6035                                         int total_data,
6036                                         files_struct *fsp,
6037                                         const char *fname,
6038                                         SMB_STRUCT_STAT *psbuf)
6039 {
6040         struct smb_file_time ft;
6041         uint32 raw_unixmode;
6042         mode_t unixmode;
6043         SMB_OFF_T size = 0;
6044         uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
6045         gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
6046         NTSTATUS status = NT_STATUS_OK;
6047         bool delete_on_fail = False;
6048         enum perm_type ptype;
6049
6050         ZERO_STRUCT(ft);
6051
6052         if (total_data < 100) {
6053                 return NT_STATUS_INVALID_PARAMETER;
6054         }
6055
6056         if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
6057            IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
6058                 size=IVAL(pdata,0); /* first 8 Bytes are size */
6059 #ifdef LARGE_SMB_OFF_T
6060                 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
6061 #else /* LARGE_SMB_OFF_T */
6062                 if (IVAL(pdata,4) != 0) {
6063                         /* more than 32 bits? */
6064                         return NT_STATUS_INVALID_PARAMETER;
6065                 }
6066 #endif /* LARGE_SMB_OFF_T */
6067         }
6068
6069         ft.atime = interpret_long_date(pdata+24); /* access_time */
6070         ft.mtime = interpret_long_date(pdata+32); /* modification_time */
6071         set_owner = (uid_t)IVAL(pdata,40);
6072         set_grp = (gid_t)IVAL(pdata,48);
6073         raw_unixmode = IVAL(pdata,84);
6074
6075         if (VALID_STAT(*psbuf)) {
6076                 if (S_ISDIR(psbuf->st_mode)) {
6077                         ptype = PERM_EXISTING_DIR;
6078                 } else {
6079                         ptype = PERM_EXISTING_FILE;
6080                 }
6081         } else {
6082                 ptype = PERM_NEW_FILE;
6083         }
6084
6085         status = unix_perms_from_wire(conn, psbuf, raw_unixmode, ptype, &unixmode);
6086         if (!NT_STATUS_IS_OK(status)) {
6087                 return status;
6088         }
6089
6090         DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = %s \
6091 size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
6092                 fname, (double)size, (unsigned int)set_owner, (unsigned int)set_grp, (int)raw_unixmode));
6093
6094         if (!VALID_STAT(*psbuf)) {
6095                 /*
6096                  * The only valid use of this is to create character and block
6097                  * devices, and named pipes. This is deprecated (IMHO) and 
6098                  * a new info level should be used for mknod. JRA.
6099                  */
6100
6101                 status = smb_unix_mknod(conn,
6102                                         pdata,
6103                                         total_data,
6104                                         fname,
6105                                         psbuf);
6106                 if (!NT_STATUS_IS_OK(status)) {
6107                         return status;
6108                 }
6109
6110                 /* Ensure we don't try and change anything else. */
6111                 raw_unixmode = SMB_MODE_NO_CHANGE;
6112                 size = get_file_size_stat(psbuf);
6113                 ft.atime = get_atimespec(psbuf);
6114                 ft.mtime = get_mtimespec(psbuf);
6115                 /* 
6116                  * We continue here as we might want to change the 
6117                  * owner uid/gid.
6118                  */
6119                 delete_on_fail = True;
6120         }
6121
6122 #if 1
6123         /* Horrible backwards compatibility hack as an old server bug
6124          * allowed a CIFS client bug to remain unnoticed :-(. JRA.
6125          * */
6126
6127         if (!size) {
6128                 size = get_file_size_stat(psbuf);
6129         }
6130 #endif
6131
6132         /*
6133          * Deal with the UNIX specific mode set.
6134          */
6135
6136         if (raw_unixmode != SMB_MODE_NO_CHANGE) {
6137                 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC setting mode 0%o for file %s\n",
6138                         (unsigned int)unixmode, fname ));
6139                 if (SMB_VFS_CHMOD(conn, fname, unixmode) != 0) {
6140                         return map_nt_error_from_unix(errno);
6141                 }
6142         }
6143
6144         /*
6145          * Deal with the UNIX specific uid set.
6146          */
6147
6148         if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) && (psbuf->st_uid != set_owner)) {
6149                 int ret;
6150
6151                 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC changing owner %u for path %s\n",
6152                         (unsigned int)set_owner, fname ));
6153
6154                 if (S_ISLNK(psbuf->st_mode)) {
6155                         ret = SMB_VFS_LCHOWN(conn, fname, set_owner, (gid_t)-1);
6156                 } else {
6157                         ret = SMB_VFS_CHOWN(conn, fname, set_owner, (gid_t)-1);
6158                 }
6159
6160                 if (ret != 0) {
6161                         status = map_nt_error_from_unix(errno);
6162                         if (delete_on_fail) {
6163                                 SMB_VFS_UNLINK(conn,fname);
6164                         }
6165                         return status;
6166                 }
6167         }
6168
6169         /*
6170          * Deal with the UNIX specific gid set.
6171          */
6172
6173         if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) && (psbuf->st_gid != set_grp)) {
6174                 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC changing group %u for file %s\n",
6175                         (unsigned int)set_owner, fname ));
6176                 if (SMB_VFS_CHOWN(conn, fname, (uid_t)-1, set_grp) != 0) {
6177                         status = map_nt_error_from_unix(errno);
6178                         if (delete_on_fail) {
6179                                 SMB_VFS_UNLINK(conn,fname);
6180                         }
6181                         return status;
6182                 }
6183         }
6184
6185         /* Deal with any size changes. */
6186
6187         status = smb_set_file_size(conn, req,
6188                                 fsp,
6189                                 fname,
6190                                 psbuf,
6191                                 size);
6192         if (!NT_STATUS_IS_OK(status)) {
6193                 return status;
6194         }
6195
6196         /* Deal with any time changes. */
6197
6198         return smb_set_file_time(conn,
6199                                 fsp,
6200                                 fname,
6201                                 psbuf,
6202                                 &ft,
6203                                 true);
6204 }
6205
6206 /****************************************************************************
6207  Deal with SMB_SET_FILE_UNIX_INFO2.
6208 ****************************************************************************/
6209
6210 static NTSTATUS smb_set_file_unix_info2(connection_struct *conn,
6211                                         struct smb_request *req,
6212                                         const char *pdata,
6213                                         int total_data,
6214                                         files_struct *fsp,
6215                                         const char *fname,
6216                                         SMB_STRUCT_STAT *psbuf)
6217 {
6218         NTSTATUS status;
6219         uint32 smb_fflags;
6220         uint32 smb_fmask;
6221
6222         if (total_data < 116) {
6223                 return NT_STATUS_INVALID_PARAMETER;
6224         }
6225
6226         /* Start by setting all the fields that are common between UNIX_BASIC
6227          * and UNIX_INFO2.
6228          */
6229         status = smb_set_file_unix_basic(conn, req, pdata, total_data,
6230                                 fsp, fname, psbuf);
6231         if (!NT_STATUS_IS_OK(status)) {
6232                 return status;
6233         }
6234
6235         smb_fflags = IVAL(pdata, 108);
6236         smb_fmask = IVAL(pdata, 112);
6237
6238         /* NB: We should only attempt to alter the file flags if the client
6239          * sends a non-zero mask.
6240          */
6241         if (smb_fmask != 0) {
6242                 int stat_fflags = 0;
6243
6244                 if (!map_info2_flags_to_sbuf(psbuf, smb_fflags, smb_fmask,
6245                             &stat_fflags)) {
6246                         /* Client asked to alter a flag we don't understand. */
6247                         return NT_STATUS_INVALID_PARAMETER;
6248                 }
6249
6250                 if (fsp && fsp->fh->fd != -1) {
6251                         /* XXX: we should be  using SMB_VFS_FCHFLAGS here. */
6252                         return NT_STATUS_NOT_SUPPORTED;
6253                 } else {
6254                         if (SMB_VFS_CHFLAGS(conn, fname, stat_fflags) != 0) {
6255                                 return map_nt_error_from_unix(errno);
6256                         }
6257                 }
6258         }
6259
6260         /* XXX: need to add support for changing the create_time here. You
6261          * can do this for paths on Darwin with setattrlist(2). The right way
6262          * to hook this up is probably by extending the VFS utimes interface.
6263          */
6264
6265         return NT_STATUS_OK;
6266 }
6267
6268 /****************************************************************************
6269  Create a directory with POSIX semantics.
6270 ****************************************************************************/
6271
6272 static NTSTATUS smb_posix_mkdir(connection_struct *conn,
6273                                 struct smb_request *req,
6274                                 char **ppdata,
6275                                 int total_data,
6276                                 const char *fname,
6277                                 SMB_STRUCT_STAT *psbuf,
6278                                 int *pdata_return_size)
6279 {
6280         NTSTATUS status = NT_STATUS_OK;
6281         uint32 raw_unixmode = 0;
6282         uint32 mod_unixmode = 0;
6283         mode_t unixmode = (mode_t)0;
6284         files_struct *fsp = NULL;
6285         uint16 info_level_return = 0;
6286         int info;
6287         char *pdata = *ppdata;
6288
6289         if (total_data < 18) {
6290                 return NT_STATUS_INVALID_PARAMETER;
6291         }
6292
6293         raw_unixmode = IVAL(pdata,8);
6294         /* Next 4 bytes are not yet defined. */
6295
6296         status = unix_perms_from_wire(conn, psbuf, raw_unixmode, PERM_NEW_DIR, &unixmode);
6297         if (!NT_STATUS_IS_OK(status)) {
6298                 return status;
6299         }
6300
6301         mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
6302
6303         DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
6304                 fname, (unsigned int)unixmode ));
6305
6306         status = SMB_VFS_CREATE_FILE(
6307                 conn,                                   /* conn */
6308                 req,                                    /* req */
6309                 0,                                      /* root_dir_fid */
6310                 fname,                                  /* fname */
6311                 0,                                      /* create_file_flags */
6312                 FILE_READ_ATTRIBUTES,                   /* access_mask */
6313                 FILE_SHARE_NONE,                        /* share_access */
6314                 FILE_CREATE,                            /* create_disposition*/
6315                 FILE_DIRECTORY_FILE,                    /* create_options */
6316                 mod_unixmode,                           /* file_attributes */
6317                 0,                                      /* oplock_request */
6318                 0,                                      /* allocation_size */
6319                 NULL,                                   /* sd */
6320                 NULL,                                   /* ea_list */
6321                 &fsp,                                   /* result */
6322                 &info,                                  /* pinfo */
6323                 psbuf);                                 /* psbuf */
6324
6325         if (NT_STATUS_IS_OK(status)) {
6326                 close_file(req, fsp, NORMAL_CLOSE);
6327         }
6328
6329         info_level_return = SVAL(pdata,16);
6330  
6331         if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
6332                 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
6333         } else if (info_level_return ==  SMB_QUERY_FILE_UNIX_INFO2) {
6334                 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
6335         } else {
6336                 *pdata_return_size = 12;
6337         }
6338
6339         /* Realloc the data size */
6340         *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
6341         if (*ppdata == NULL) {
6342                 *pdata_return_size = 0;
6343                 return NT_STATUS_NO_MEMORY;
6344         }
6345         pdata = *ppdata;
6346
6347         SSVAL(pdata,0,NO_OPLOCK_RETURN);
6348         SSVAL(pdata,2,0); /* No fnum. */
6349         SIVAL(pdata,4,info); /* Was directory created. */
6350
6351         switch (info_level_return) {
6352                 case SMB_QUERY_FILE_UNIX_BASIC:
6353                         SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
6354                         SSVAL(pdata,10,0); /* Padding. */
6355                         store_file_unix_basic(conn, pdata + 12, fsp, psbuf);
6356                         break;
6357                 case SMB_QUERY_FILE_UNIX_INFO2:
6358                         SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
6359                         SSVAL(pdata,10,0); /* Padding. */
6360                         store_file_unix_basic_info2(conn, pdata + 12, fsp, psbuf);
6361                         break;
6362                 default:
6363                         SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
6364                         SSVAL(pdata,10,0); /* Padding. */
6365                         break;
6366         }
6367
6368         return status;
6369 }
6370
6371 /****************************************************************************
6372  Open/Create a file with POSIX semantics.
6373 ****************************************************************************/
6374
6375 static NTSTATUS smb_posix_open(connection_struct *conn,
6376                                struct smb_request *req,
6377                                 char **ppdata,
6378                                 int total_data,
6379                                 const char *fname,
6380                                 SMB_STRUCT_STAT *psbuf,
6381                                 int *pdata_return_size)
6382 {
6383         bool extended_oplock_granted = False;
6384         char *pdata = *ppdata;
6385         uint32 flags = 0;
6386         uint32 wire_open_mode = 0;
6387         uint32 raw_unixmode = 0;
6388         uint32 mod_unixmode = 0;
6389         uint32 create_disp = 0;
6390         uint32 access_mask = 0;
6391         uint32 create_options = 0;
6392         NTSTATUS status = NT_STATUS_OK;
6393         mode_t unixmode = (mode_t)0;
6394         files_struct *fsp = NULL;
6395         int oplock_request = 0;
6396         int info = 0;
6397         uint16 info_level_return = 0;
6398
6399         if (total_data < 18) {
6400                 return NT_STATUS_INVALID_PARAMETER;
6401         }
6402
6403         flags = IVAL(pdata,0);
6404         oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
6405         if (oplock_request) {
6406                 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
6407         }
6408
6409         wire_open_mode = IVAL(pdata,4);
6410
6411         if (wire_open_mode == (SMB_O_CREAT|SMB_O_DIRECTORY)) {
6412                 return smb_posix_mkdir(conn, req,
6413                                         ppdata,
6414                                         total_data,
6415                                         fname,
6416                                         psbuf,
6417                                         pdata_return_size);
6418         }
6419
6420         switch (wire_open_mode & SMB_ACCMODE) {
6421                 case SMB_O_RDONLY:
6422                         access_mask = FILE_READ_DATA;
6423                         break;
6424                 case SMB_O_WRONLY:
6425                         access_mask = FILE_WRITE_DATA;
6426                         break;
6427                 case SMB_O_RDWR:
6428                         access_mask = FILE_READ_DATA|FILE_WRITE_DATA;
6429                         break;
6430                 default:
6431                         DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
6432                                 (unsigned int)wire_open_mode ));
6433                         return NT_STATUS_INVALID_PARAMETER;
6434         }
6435
6436         wire_open_mode &= ~SMB_ACCMODE;
6437
6438         if((wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL)) == (SMB_O_CREAT | SMB_O_EXCL)) {
6439                 create_disp = FILE_CREATE;
6440         } else if((wire_open_mode & (SMB_O_CREAT | SMB_O_TRUNC)) == (SMB_O_CREAT | SMB_O_TRUNC)) {
6441                 create_disp = FILE_OVERWRITE_IF;
6442         } else if((wire_open_mode & SMB_O_CREAT) == SMB_O_CREAT) {
6443                 create_disp = FILE_OPEN_IF;
6444         } else if ((wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL | SMB_O_TRUNC)) == 0) {
6445                 create_disp = FILE_OPEN;
6446         } else {
6447                 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
6448                         (unsigned int)wire_open_mode ));
6449                 return NT_STATUS_INVALID_PARAMETER;
6450         }
6451
6452         raw_unixmode = IVAL(pdata,8);
6453         /* Next 4 bytes are not yet defined. */
6454
6455         status = unix_perms_from_wire(conn,
6456                                 psbuf,
6457                                 raw_unixmode,
6458                                 VALID_STAT(*psbuf) ? PERM_EXISTING_FILE : PERM_NEW_FILE,
6459                                 &unixmode);
6460
6461         if (!NT_STATUS_IS_OK(status)) {
6462                 return status;
6463         }
6464
6465         mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
6466
6467         if (wire_open_mode & SMB_O_SYNC) {
6468                 create_options |= FILE_WRITE_THROUGH;
6469         }
6470         if (wire_open_mode & SMB_O_APPEND) {
6471                 access_mask |= FILE_APPEND_DATA;
6472         }
6473         if (wire_open_mode & SMB_O_DIRECT) {
6474                 mod_unixmode |= FILE_FLAG_NO_BUFFERING;
6475         }
6476
6477         DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
6478                 fname,
6479                 (unsigned int)wire_open_mode,
6480                 (unsigned int)unixmode ));
6481
6482         status = SMB_VFS_CREATE_FILE(
6483                 conn,                                   /* conn */
6484                 req,                                    /* req */
6485                 0,                                      /* root_dir_fid */
6486                 fname,                                  /* fname */
6487                 0,                                      /* create_file_flags */
6488                 access_mask,                            /* access_mask */
6489                 (FILE_SHARE_READ | FILE_SHARE_WRITE |   /* share_access */
6490                     FILE_SHARE_DELETE),
6491                 create_disp,                            /* create_disposition*/
6492                 0,                                      /* create_options */
6493                 mod_unixmode,                           /* file_attributes */
6494                 oplock_request,                         /* oplock_request */
6495                 0,                                      /* allocation_size */
6496                 NULL,                                   /* sd */
6497                 NULL,                                   /* ea_list */
6498                 &fsp,                                   /* result */
6499                 &info,                                  /* pinfo */
6500                 psbuf);                                 /* psbuf */
6501
6502         if (!NT_STATUS_IS_OK(status)) {
6503                 return status;
6504         }
6505
6506         if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
6507                 extended_oplock_granted = True;
6508         }
6509
6510         if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
6511                 extended_oplock_granted = True;
6512         }
6513
6514         info_level_return = SVAL(pdata,16);
6515  
6516         /* Allocate the correct return size. */
6517
6518         if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
6519                 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
6520         } else if (info_level_return ==  SMB_QUERY_FILE_UNIX_INFO2) {
6521                 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
6522         } else {
6523                 *pdata_return_size = 12;
6524         }
6525
6526         /* Realloc the data size */
6527         *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
6528         if (*ppdata == NULL) {
6529                 close_file(req, fsp, ERROR_CLOSE);
6530                 *pdata_return_size = 0;
6531                 return NT_STATUS_NO_MEMORY;
6532         }
6533         pdata = *ppdata;
6534
6535         if (extended_oplock_granted) {
6536                 if (flags & REQUEST_BATCH_OPLOCK) {
6537                         SSVAL(pdata,0, BATCH_OPLOCK_RETURN);
6538                 } else {
6539                         SSVAL(pdata,0, EXCLUSIVE_OPLOCK_RETURN);
6540                 }
6541         } else if (fsp->oplock_type == LEVEL_II_OPLOCK) {
6542                 SSVAL(pdata,0, LEVEL_II_OPLOCK_RETURN);
6543         } else {
6544                 SSVAL(pdata,0,NO_OPLOCK_RETURN);
6545         }
6546
6547         SSVAL(pdata,2,fsp->fnum);
6548         SIVAL(pdata,4,info); /* Was file created etc. */
6549
6550         switch (info_level_return) {
6551                 case SMB_QUERY_FILE_UNIX_BASIC:
6552                         SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
6553                         SSVAL(pdata,10,0); /* padding. */
6554                         store_file_unix_basic(conn, pdata + 12, fsp, psbuf);
6555                         break;
6556                 case SMB_QUERY_FILE_UNIX_INFO2:
6557                         SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
6558                         SSVAL(pdata,10,0); /* padding. */
6559                         store_file_unix_basic_info2(conn, pdata + 12, fsp, psbuf);
6560                         break;
6561                 default:
6562                         SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
6563                         SSVAL(pdata,10,0); /* padding. */
6564                         break;
6565         }
6566         return NT_STATUS_OK;
6567 }
6568
6569 /****************************************************************************
6570  Delete a file with POSIX semantics.
6571 ****************************************************************************/
6572
6573 static NTSTATUS smb_posix_unlink(connection_struct *conn,
6574                                  struct smb_request *req,
6575                                 const char *pdata,
6576                                 int total_data,
6577                                 const char *fname,
6578                                 SMB_STRUCT_STAT *psbuf)
6579 {
6580         NTSTATUS status = NT_STATUS_OK;
6581         files_struct *fsp = NULL;
6582         uint16 flags = 0;
6583         char del = 1;
6584         int info = 0;
6585         int create_options = 0;
6586         int i;
6587         struct share_mode_lock *lck = NULL;
6588
6589         if (total_data < 2) {
6590                 return NT_STATUS_INVALID_PARAMETER;
6591         }
6592
6593         flags = SVAL(pdata,0);
6594
6595         if (!VALID_STAT(*psbuf)) {
6596                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6597         }
6598
6599         if ((flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) &&
6600                         !VALID_STAT_OF_DIR(*psbuf)) {
6601                 return NT_STATUS_NOT_A_DIRECTORY;
6602         }
6603
6604         DEBUG(10,("smb_posix_unlink: %s %s\n",
6605                 (flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) ? "directory" : "file",
6606                 fname));
6607
6608         if (VALID_STAT_OF_DIR(*psbuf)) {
6609                 create_options |= FILE_DIRECTORY_FILE;
6610         }
6611
6612         status = SMB_VFS_CREATE_FILE(
6613                 conn,                                   /* conn */
6614                 req,                                    /* req */
6615                 0,                                      /* root_dir_fid */
6616                 fname,                                  /* fname */
6617                 0,                                      /* create_file_flags */
6618                 DELETE_ACCESS,                          /* access_mask */
6619                 (FILE_SHARE_READ | FILE_SHARE_WRITE |   /* share_access */
6620                     FILE_SHARE_DELETE),
6621                 FILE_OPEN,                              /* create_disposition*/
6622                 create_options,                         /* create_options */
6623                 FILE_FLAG_POSIX_SEMANTICS|0777,         /* file_attributes */
6624                 0,                                      /* oplock_request */
6625                 0,                                      /* allocation_size */
6626                 NULL,                                   /* sd */
6627                 NULL,                                   /* ea_list */
6628                 &fsp,                                   /* result */
6629                 &info,                                  /* pinfo */
6630                 psbuf);                                 /* psbuf */
6631
6632         if (!NT_STATUS_IS_OK(status)) {
6633                 return status;
6634         }
6635
6636         /*
6637          * Don't lie to client. If we can't really delete due to
6638          * non-POSIX opens return SHARING_VIOLATION.
6639          */
6640
6641         lck = get_share_mode_lock(talloc_tos(), fsp->file_id, NULL, NULL,
6642                                   NULL);
6643         if (lck == NULL) {
6644                 DEBUG(0, ("smb_posix_unlink: Could not get share mode "
6645                         "lock for file %s\n", fsp->fsp_name));
6646                 close_file(req, fsp, NORMAL_CLOSE);
6647                 return NT_STATUS_INVALID_PARAMETER;
6648         }
6649
6650         /*
6651          * See if others still have the file open. If this is the case, then
6652          * don't delete. If all opens are POSIX delete we can set the delete
6653          * on close disposition.
6654          */
6655         for (i=0; i<lck->num_share_modes; i++) {
6656                 struct share_mode_entry *e = &lck->share_modes[i];
6657                 if (is_valid_share_mode_entry(e)) {
6658                         if (e->flags & SHARE_MODE_FLAG_POSIX_OPEN) {
6659                                 continue;
6660                         }
6661                         /* Fail with sharing violation. */
6662                         close_file(req, fsp, NORMAL_CLOSE);
6663                         TALLOC_FREE(lck);
6664                         return NT_STATUS_SHARING_VIOLATION;
6665                 }
6666         }
6667
6668         /*
6669          * Set the delete on close.
6670          */
6671         status = smb_set_file_disposition_info(conn,
6672                                                 &del,
6673                                                 1,
6674                                                 fsp,
6675                                                 fname,
6676                                                 psbuf);
6677
6678         if (!NT_STATUS_IS_OK(status)) {
6679                 close_file(req, fsp, NORMAL_CLOSE);
6680                 TALLOC_FREE(lck);
6681                 return status;
6682         }
6683         TALLOC_FREE(lck);
6684         return close_file(req, fsp, NORMAL_CLOSE);
6685 }
6686
6687 /****************************************************************************
6688  Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
6689 ****************************************************************************/
6690
6691 static void call_trans2setfilepathinfo(connection_struct *conn,
6692                                        struct smb_request *req,
6693                                        unsigned int tran_call,
6694                                        char **pparams, int total_params,
6695                                        char **ppdata, int total_data,
6696                                        unsigned int max_data_bytes)
6697 {
6698         char *params = *pparams;
6699         char *pdata = *ppdata;
6700         uint16 info_level;
6701         SMB_STRUCT_STAT sbuf;
6702         char *fname = NULL;
6703         files_struct *fsp = NULL;
6704         NTSTATUS status = NT_STATUS_OK;
6705         int data_return_size = 0;
6706         TALLOC_CTX *ctx = talloc_tos();
6707
6708         if (!params) {
6709                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6710                 return;
6711         }
6712
6713         ZERO_STRUCT(sbuf);
6714
6715         if (tran_call == TRANSACT2_SETFILEINFO) {
6716                 if (total_params < 4) {
6717                         reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6718                         return;
6719                 }
6720
6721                 fsp = file_fsp(req, SVAL(params,0));
6722                 /* Basic check for non-null fsp. */
6723                 if (!check_fsp_open(conn, req, fsp)) {
6724                         return;
6725                 }
6726                 info_level = SVAL(params,2);
6727
6728                 fname = talloc_strdup(talloc_tos(),fsp->fsp_name);
6729                 if (!fname) {
6730                         reply_nterror(req, NT_STATUS_NO_MEMORY);
6731                         return;
6732                 }
6733
6734                 if(fsp->is_directory || fsp->fh->fd == -1) {
6735                         /*
6736                          * This is actually a SETFILEINFO on a directory
6737                          * handle (returned from an NT SMB). NT5.0 seems
6738                          * to do this call. JRA.
6739                          */
6740                         if (INFO_LEVEL_IS_UNIX(info_level)) {
6741                                 /* Always do lstat for UNIX calls. */
6742                                 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
6743                                         DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
6744                                         reply_unixerror(req,ERRDOS,ERRbadpath);
6745                                         return;
6746                                 }
6747                         } else {
6748                                 if (SMB_VFS_STAT(conn,fname,&sbuf) != 0) {
6749                                         DEBUG(3,("call_trans2setfilepathinfo: fileinfo of %s failed (%s)\n",fname,strerror(errno)));
6750                                         reply_unixerror(req,ERRDOS,ERRbadpath);
6751                                         return;
6752                                 }
6753                         }
6754                 } else if (fsp->print_file) {
6755                         /*
6756                          * Doing a DELETE_ON_CLOSE should cancel a print job.
6757                          */
6758                         if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
6759                                 fsp->fh->private_options |= FILE_DELETE_ON_CLOSE;
6760
6761                                 DEBUG(3,("call_trans2setfilepathinfo: Cancelling print job (%s)\n", fsp->fsp_name ));
6762
6763                                 SSVAL(params,0,0);
6764                                 send_trans2_replies(conn, req, params, 2,
6765                                                     *ppdata, 0,
6766                                                     max_data_bytes);
6767                                 return;
6768                         } else {
6769                                 reply_unixerror(req, ERRDOS, ERRbadpath);
6770                                 return;
6771                         }
6772                 } else {
6773                         /*
6774                          * Original code - this is an open file.
6775                          */
6776                         if (!check_fsp(conn, req, fsp)) {
6777                                 return;
6778                         }
6779
6780                         if (SMB_VFS_FSTAT(fsp, &sbuf) != 0) {
6781                                 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",fsp->fnum, strerror(errno)));
6782                                 reply_unixerror(req, ERRDOS, ERRbadfid);
6783                                 return;
6784                         }
6785                 }
6786         } else {
6787                 /* set path info */
6788                 if (total_params < 7) {
6789                         reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6790                         return;
6791                 }
6792
6793                 info_level = SVAL(params,0);
6794                 srvstr_get_path(ctx, params, req->flags2, &fname, &params[6],
6795                                 total_params - 6, STR_TERMINATE,
6796                                 &status);
6797                 if (!NT_STATUS_IS_OK(status)) {
6798                         reply_nterror(req, status);
6799                         return;
6800                 }
6801
6802                 status = resolve_dfspath(ctx, conn,
6803                                          req->flags2 & FLAGS2_DFS_PATHNAMES,
6804                                          fname,
6805                                          &fname);
6806                 if (!NT_STATUS_IS_OK(status)) {
6807                         if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6808                                 reply_botherror(req,
6809                                                 NT_STATUS_PATH_NOT_COVERED,
6810                                                 ERRSRV, ERRbadpath);
6811                                 return;
6812                         }
6813                         reply_nterror(req, status);
6814                         return;
6815                 }
6816
6817                 status = unix_convert(ctx, conn, fname, False,
6818                                 &fname, NULL, &sbuf);
6819                 if (!NT_STATUS_IS_OK(status)) {
6820                         reply_nterror(req, status);
6821                         return;
6822                 }
6823
6824                 status = check_name(conn, fname);
6825                 if (!NT_STATUS_IS_OK(status)) {
6826                         reply_nterror(req, status);
6827                         return;
6828                 }
6829
6830                 if (INFO_LEVEL_IS_UNIX(info_level)) {
6831                         /*
6832                          * For CIFS UNIX extensions the target name may not exist.
6833                          */
6834
6835                         /* Always do lstat for UNIX calls. */
6836                         SMB_VFS_LSTAT(conn,fname,&sbuf);
6837
6838                 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,fname,&sbuf)) {
6839                         DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
6840                         reply_unixerror(req, ERRDOS, ERRbadpath);
6841                         return;
6842                 }
6843         }
6844
6845         if (!CAN_WRITE(conn)) {
6846                 reply_doserror(req, ERRSRV, ERRaccess);
6847                 return;
6848         }
6849
6850         if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
6851                 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6852                 return;
6853         }
6854
6855         DEBUG(3,("call_trans2setfilepathinfo(%d) %s (fnum %d) info_level=%d totdata=%d\n",
6856                 tran_call,fname, fsp ? fsp->fnum : -1, info_level,total_data));
6857
6858         /* Realloc the parameter size */
6859         *pparams = (char *)SMB_REALLOC(*pparams,2);
6860         if (*pparams == NULL) {
6861                 reply_nterror(req, NT_STATUS_NO_MEMORY);
6862                 return;
6863         }
6864         params = *pparams;
6865
6866         SSVAL(params,0,0);
6867
6868         switch (info_level) {
6869
6870                 case SMB_INFO_STANDARD:
6871                 {
6872                         status = smb_set_info_standard(conn,
6873                                         pdata,
6874                                         total_data,
6875                                         fsp,
6876                                         fname,
6877                                         &sbuf);
6878                         break;
6879                 }
6880
6881                 case SMB_INFO_SET_EA:
6882                 {
6883                         status = smb_info_set_ea(conn,
6884                                                 pdata,
6885                                                 total_data,
6886                                                 fsp,
6887                                                 fname);
6888                         break;
6889                 }
6890
6891                 case SMB_SET_FILE_BASIC_INFO:
6892                 case SMB_FILE_BASIC_INFORMATION:
6893                 {
6894                         status = smb_set_file_basic_info(conn,
6895                                                         pdata,
6896                                                         total_data,
6897                                                         fsp,
6898                                                         fname,
6899                                                         &sbuf);
6900                         break;
6901                 }
6902
6903                 case SMB_FILE_ALLOCATION_INFORMATION:
6904                 case SMB_SET_FILE_ALLOCATION_INFO:
6905                 {
6906                         status = smb_set_file_allocation_info(conn, req,
6907                                                                 pdata,
6908                                                                 total_data,
6909                                                                 fsp,
6910                                                                 fname,
6911                                                                 &sbuf);
6912                         break;
6913                 }
6914
6915                 case SMB_FILE_END_OF_FILE_INFORMATION:
6916                 case SMB_SET_FILE_END_OF_FILE_INFO:
6917                 {
6918                         status = smb_set_file_end_of_file_info(conn, req,
6919                                                                 pdata,
6920                                                                 total_data,
6921                                                                 fsp,
6922                                                                 fname,
6923                                                                 &sbuf);
6924                         break;
6925                 }
6926
6927                 case SMB_FILE_DISPOSITION_INFORMATION:
6928                 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
6929                 {
6930 #if 0
6931                         /* JRA - We used to just ignore this on a path ? 
6932                          * Shouldn't this be invalid level on a pathname
6933                          * based call ?
6934                          */
6935                         if (tran_call != TRANSACT2_SETFILEINFO) {
6936                                 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
6937                         }
6938 #endif
6939                         status = smb_set_file_disposition_info(conn,
6940                                                 pdata,
6941                                                 total_data,
6942                                                 fsp,
6943                                                 fname,
6944                                                 &sbuf);
6945                         break;
6946                 }
6947
6948                 case SMB_FILE_POSITION_INFORMATION:
6949                 {
6950                         status = smb_file_position_information(conn,
6951                                                 pdata,
6952                                                 total_data,
6953                                                 fsp);
6954                         break;
6955                 }
6956
6957                 /* From tridge Samba4 : 
6958                  * MODE_INFORMATION in setfileinfo (I have no
6959                  * idea what "mode information" on a file is - it takes a value of 0,
6960                  * 2, 4 or 6. What could it be?).
6961                  */
6962
6963                 case SMB_FILE_MODE_INFORMATION:
6964                 {
6965                         status = smb_file_mode_information(conn,
6966                                                 pdata,
6967                                                 total_data);
6968                         break;
6969                 }
6970
6971                 /*
6972                  * CIFS UNIX extensions.
6973                  */
6974
6975                 case SMB_SET_FILE_UNIX_BASIC:
6976                 {
6977                         status = smb_set_file_unix_basic(conn, req,
6978                                                         pdata,
6979                                                         total_data,
6980                                                         fsp,
6981                                                         fname,
6982                                                         &sbuf);
6983                         break;
6984                 }
6985
6986                 case SMB_SET_FILE_UNIX_INFO2:
6987                 {
6988                         status = smb_set_file_unix_info2(conn, req,
6989                                                         pdata,
6990                                                         total_data,
6991                                                         fsp,
6992                                                         fname,
6993                                                         &sbuf);
6994                         break;
6995                 }
6996
6997                 case SMB_SET_FILE_UNIX_LINK:
6998                 {
6999                         if (tran_call != TRANSACT2_SETPATHINFO) {
7000                                 /* We must have a pathname for this. */
7001                                 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
7002                                 return;
7003                         }
7004                         status = smb_set_file_unix_link(conn, req, pdata,
7005                                                         total_data, fname);
7006                         break;
7007                 }
7008
7009                 case SMB_SET_FILE_UNIX_HLINK:
7010                 {
7011                         if (tran_call != TRANSACT2_SETPATHINFO) {
7012                                 /* We must have a pathname for this. */
7013                                 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
7014                                 return;
7015                         }
7016                         status = smb_set_file_unix_hlink(conn, req,
7017                                                          pdata, total_data,
7018                                                          fname);
7019                         break;
7020                 }
7021
7022                 case SMB_FILE_RENAME_INFORMATION:
7023                 {
7024                         status = smb_file_rename_information(conn, req,
7025                                                              pdata, total_data,
7026                                                              fsp, fname);
7027                         break;
7028                 }
7029
7030 #if defined(HAVE_POSIX_ACLS)
7031                 case SMB_SET_POSIX_ACL:
7032                 {
7033                         status = smb_set_posix_acl(conn,
7034                                                 pdata,
7035                                                 total_data,
7036                                                 fsp,
7037                                                 fname,
7038                                                 &sbuf);
7039                         break;
7040                 }
7041 #endif
7042
7043                 case SMB_SET_POSIX_LOCK:
7044                 {
7045                         if (tran_call != TRANSACT2_SETFILEINFO) {
7046                                 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
7047                                 return;
7048                         }
7049                         status = smb_set_posix_lock(conn, req,
7050                                                     pdata, total_data, fsp);
7051                         break;
7052                 }
7053
7054                 case SMB_POSIX_PATH_OPEN:
7055                 {
7056                         if (tran_call != TRANSACT2_SETPATHINFO) {
7057                                 /* We must have a pathname for this. */
7058                                 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
7059                                 return;
7060                         }
7061
7062                         status = smb_posix_open(conn, req,
7063                                                 ppdata,
7064                                                 total_data,
7065                                                 fname,
7066                                                 &sbuf,
7067                                                 &data_return_size);
7068                         break;
7069                 }
7070
7071                 case SMB_POSIX_PATH_UNLINK:
7072                 {
7073                         if (tran_call != TRANSACT2_SETPATHINFO) {
7074                                 /* We must have a pathname for this. */
7075                                 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
7076                                 return;
7077                         }
7078
7079                         status = smb_posix_unlink(conn, req,
7080                                                 pdata,
7081                                                 total_data,
7082                                                 fname,
7083                                                 &sbuf);
7084                         break;
7085                 }
7086
7087                 default:
7088                         reply_nterror(req, NT_STATUS_INVALID_LEVEL);
7089                         return;
7090         }
7091
7092         
7093         if (!NT_STATUS_IS_OK(status)) {
7094                 if (open_was_deferred(req->mid)) {
7095                         /* We have re-scheduled this call. */
7096                         return;
7097                 }
7098                 if (blocking_lock_was_deferred(req->mid)) {
7099                         /* We have re-scheduled this call. */
7100                         return;
7101                 }
7102                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7103                         reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
7104                                         ERRSRV, ERRbadpath);
7105                         return;
7106                 }
7107                 if (info_level == SMB_POSIX_PATH_OPEN) {
7108                         reply_openerror(req, status);
7109                         return;
7110                 }
7111
7112                 reply_nterror(req, status);
7113                 return;
7114         }
7115
7116         SSVAL(params,0,0);
7117         send_trans2_replies(conn, req, params, 2, *ppdata, data_return_size,
7118                             max_data_bytes);
7119   
7120         return;
7121 }
7122
7123 /****************************************************************************
7124  Reply to a TRANS2_MKDIR (make directory with extended attributes).
7125 ****************************************************************************/
7126
7127 static void call_trans2mkdir(connection_struct *conn, struct smb_request *req,
7128                              char **pparams, int total_params,
7129                              char **ppdata, int total_data,
7130                              unsigned int max_data_bytes)
7131 {
7132         char *params = *pparams;
7133         char *pdata = *ppdata;
7134         char *directory = NULL;
7135         SMB_STRUCT_STAT sbuf;
7136         NTSTATUS status = NT_STATUS_OK;
7137         struct ea_list *ea_list = NULL;
7138         TALLOC_CTX *ctx = talloc_tos();
7139
7140         if (!CAN_WRITE(conn)) {
7141                 reply_doserror(req, ERRSRV, ERRaccess);
7142                 return;
7143         }
7144
7145         if (total_params < 5) {
7146                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7147                 return;
7148         }
7149
7150         srvstr_get_path(ctx, params, req->flags2, &directory, &params[4],
7151                         total_params - 4, STR_TERMINATE,
7152                         &status);
7153         if (!NT_STATUS_IS_OK(status)) {
7154                 reply_nterror(req, status);
7155                 return;
7156         }
7157
7158         DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
7159
7160         status = unix_convert(ctx, conn, directory, False, &directory, NULL, &sbuf);
7161         if (!NT_STATUS_IS_OK(status)) {
7162                 reply_nterror(req, status);
7163                 return;
7164         }
7165
7166         status = check_name(conn, directory);
7167         if (!NT_STATUS_IS_OK(status)) {
7168                 DEBUG(5,("call_trans2mkdir error (%s)\n", nt_errstr(status)));
7169                 reply_nterror(req, status);
7170                 return;
7171         }
7172
7173         /* Any data in this call is an EA list. */
7174         if (total_data && (total_data != 4) && !lp_ea_support(SNUM(conn))) {
7175                 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
7176                 return;
7177         }
7178
7179         /*
7180          * OS/2 workplace shell seems to send SET_EA requests of "null"
7181          * length (4 bytes containing IVAL 4).
7182          * They seem to have no effect. Bug #3212. JRA.
7183          */
7184
7185         if (total_data != 4) {
7186                 if (total_data < 10) {
7187                         reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7188                         return;
7189                 }
7190
7191                 if (IVAL(pdata,0) > total_data) {
7192                         DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
7193                                 IVAL(pdata,0), (unsigned int)total_data));
7194                         reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7195                         return;
7196                 }
7197
7198                 ea_list = read_ea_list(talloc_tos(), pdata + 4,
7199                                        total_data - 4);
7200                 if (!ea_list) {
7201                         reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7202                         return;
7203                 }
7204         }
7205         /* If total_data == 4 Windows doesn't care what values
7206          * are placed in that field, it just ignores them.
7207          * The System i QNTC IBM SMB client puts bad values here,
7208          * so ignore them. */
7209
7210         status = create_directory(conn, req, directory);
7211
7212         if (!NT_STATUS_IS_OK(status)) {
7213                 reply_nterror(req, status);
7214                 return;
7215         }
7216   
7217         /* Try and set any given EA. */
7218         if (ea_list) {
7219                 status = set_ea(conn, NULL, directory, ea_list);
7220                 if (!NT_STATUS_IS_OK(status)) {
7221                         reply_nterror(req, status);
7222                         return;
7223                 }
7224         }
7225
7226         /* Realloc the parameter and data sizes */
7227         *pparams = (char *)SMB_REALLOC(*pparams,2);
7228         if(*pparams == NULL) {
7229                 reply_nterror(req, NT_STATUS_NO_MEMORY);
7230                 return;
7231         }
7232         params = *pparams;
7233
7234         SSVAL(params,0,0);
7235
7236         send_trans2_replies(conn, req, params, 2, *ppdata, 0, max_data_bytes);
7237   
7238         return;
7239 }
7240
7241 /****************************************************************************
7242  Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
7243  We don't actually do this - we just send a null response.
7244 ****************************************************************************/
7245
7246 static void call_trans2findnotifyfirst(connection_struct *conn,
7247                                        struct smb_request *req,
7248                                        char **pparams, int total_params,
7249                                        char **ppdata, int total_data,
7250                                        unsigned int max_data_bytes)
7251 {
7252         char *params = *pparams;
7253         uint16 info_level;
7254
7255         if (total_params < 6) {
7256                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7257                 return;
7258         }
7259
7260         info_level = SVAL(params,4);
7261         DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
7262
7263         switch (info_level) {
7264                 case 1:
7265                 case 2:
7266                         break;
7267                 default:
7268                         reply_nterror(req, NT_STATUS_INVALID_LEVEL);
7269                         return;
7270         }
7271
7272         /* Realloc the parameter and data sizes */
7273         *pparams = (char *)SMB_REALLOC(*pparams,6);
7274         if (*pparams == NULL) {
7275                 reply_nterror(req, NT_STATUS_NO_MEMORY);
7276                 return;
7277         }
7278         params = *pparams;
7279
7280         SSVAL(params,0,fnf_handle);
7281         SSVAL(params,2,0); /* No changes */
7282         SSVAL(params,4,0); /* No EA errors */
7283
7284         fnf_handle++;
7285
7286         if(fnf_handle == 0)
7287                 fnf_handle = 257;
7288
7289         send_trans2_replies(conn, req, params, 6, *ppdata, 0, max_data_bytes);
7290   
7291         return;
7292 }
7293
7294 /****************************************************************************
7295  Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for 
7296  changes). Currently this does nothing.
7297 ****************************************************************************/
7298
7299 static void call_trans2findnotifynext(connection_struct *conn,
7300                                       struct smb_request *req,
7301                                       char **pparams, int total_params,
7302                                       char **ppdata, int total_data,
7303                                       unsigned int max_data_bytes)
7304 {
7305         char *params = *pparams;
7306
7307         DEBUG(3,("call_trans2findnotifynext\n"));
7308
7309         /* Realloc the parameter and data sizes */
7310         *pparams = (char *)SMB_REALLOC(*pparams,4);
7311         if (*pparams == NULL) {
7312                 reply_nterror(req, NT_STATUS_NO_MEMORY);
7313                 return;
7314         }
7315         params = *pparams;
7316
7317         SSVAL(params,0,0); /* No changes */
7318         SSVAL(params,2,0); /* No EA errors */
7319
7320         send_trans2_replies(conn, req, params, 4, *ppdata, 0, max_data_bytes);
7321   
7322         return;
7323 }
7324
7325 /****************************************************************************
7326  Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
7327 ****************************************************************************/
7328
7329 static void call_trans2getdfsreferral(connection_struct *conn,
7330                                       struct smb_request *req,
7331                                       char **pparams, int total_params,
7332                                       char **ppdata, int total_data,
7333                                       unsigned int max_data_bytes)
7334 {
7335         char *params = *pparams;
7336         char *pathname = NULL;
7337         int reply_size = 0;
7338         int max_referral_level;
7339         NTSTATUS status = NT_STATUS_OK;
7340         TALLOC_CTX *ctx = talloc_tos();
7341
7342         DEBUG(10,("call_trans2getdfsreferral\n"));
7343
7344         if (total_params < 3) {
7345                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7346                 return;
7347         }
7348
7349         max_referral_level = SVAL(params,0);
7350
7351         if(!lp_host_msdfs()) {
7352                 reply_doserror(req, ERRDOS, ERRbadfunc);
7353                 return;
7354         }
7355
7356         srvstr_pull_talloc(ctx, params, req->flags2, &pathname, &params[2],
7357                     total_params - 2, STR_TERMINATE);
7358         if (!pathname) {
7359                 reply_nterror(req, NT_STATUS_NOT_FOUND);
7360                 return;
7361         }
7362         if((reply_size = setup_dfs_referral(conn, pathname, max_referral_level,
7363                                             ppdata,&status)) < 0) {
7364                 reply_nterror(req, status);
7365                 return;
7366         }
7367
7368         SSVAL(req->inbuf, smb_flg2,
7369               SVAL(req->inbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
7370         send_trans2_replies(conn, req,0,0,*ppdata,reply_size, max_data_bytes);
7371
7372         return;
7373 }
7374
7375 #define LMCAT_SPL       0x53
7376 #define LMFUNC_GETJOBID 0x60
7377
7378 /****************************************************************************
7379  Reply to a TRANS2_IOCTL - used for OS/2 printing.
7380 ****************************************************************************/
7381
7382 static void call_trans2ioctl(connection_struct *conn,
7383                              struct smb_request *req,
7384                              char **pparams, int total_params,
7385                              char **ppdata, int total_data,
7386                              unsigned int max_data_bytes)
7387 {
7388         char *pdata = *ppdata;
7389         files_struct *fsp = file_fsp(req, SVAL(req->vwv+15, 0));
7390
7391         /* check for an invalid fid before proceeding */
7392
7393         if (!fsp) {
7394                 reply_doserror(req, ERRDOS, ERRbadfid);
7395                 return;
7396         }
7397
7398         if ((SVAL(req->vwv+16, 0) == LMCAT_SPL)
7399             && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
7400                 *ppdata = (char *)SMB_REALLOC(*ppdata, 32);
7401                 if (*ppdata == NULL) {
7402                         reply_nterror(req, NT_STATUS_NO_MEMORY);
7403                         return;
7404                 }
7405                 pdata = *ppdata;
7406
7407                 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
7408                         CAN ACCEPT THIS IN UNICODE. JRA. */
7409
7410                 SSVAL(pdata,0,fsp->rap_print_jobid);                     /* Job number */
7411                 srvstr_push(pdata, req->flags2, pdata + 2,
7412                             global_myname(), 15,
7413                             STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
7414                 srvstr_push(pdata, req->flags2, pdata+18,
7415                             lp_servicename(SNUM(conn)), 13,
7416                             STR_ASCII|STR_TERMINATE); /* Service name */
7417                 send_trans2_replies(conn, req, *pparams, 0, *ppdata, 32,
7418                                     max_data_bytes);
7419                 return;
7420         }
7421
7422         DEBUG(2,("Unknown TRANS2_IOCTL\n"));
7423         reply_doserror(req, ERRSRV, ERRerror);
7424 }
7425
7426 /****************************************************************************
7427  Reply to a SMBfindclose (stop trans2 directory search).
7428 ****************************************************************************/
7429
7430 void reply_findclose(struct smb_request *req)
7431 {
7432         int dptr_num;
7433
7434         START_PROFILE(SMBfindclose);
7435
7436         if (req->wct < 1) {
7437                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7438                 END_PROFILE(SMBfindclose);
7439                 return;
7440         }
7441
7442         dptr_num = SVALS(req->vwv+0, 0);
7443
7444         DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
7445
7446         dptr_close(&dptr_num);
7447
7448         reply_outbuf(req, 0, 0);
7449
7450         DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
7451
7452         END_PROFILE(SMBfindclose);
7453         return;
7454 }
7455
7456 /****************************************************************************
7457  Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
7458 ****************************************************************************/
7459
7460 void reply_findnclose(struct smb_request *req)
7461 {
7462         int dptr_num;
7463
7464         START_PROFILE(SMBfindnclose);
7465
7466         if (req->wct < 1) {
7467                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7468                 END_PROFILE(SMBfindnclose);
7469                 return;
7470         }
7471         
7472         dptr_num = SVAL(req->vwv+0, 0);
7473
7474         DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
7475
7476         /* We never give out valid handles for a 
7477            findnotifyfirst - so any dptr_num is ok here. 
7478            Just ignore it. */
7479
7480         reply_outbuf(req, 0, 0);
7481
7482         DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
7483
7484         END_PROFILE(SMBfindnclose);
7485         return;
7486 }
7487
7488 static void handle_trans2(connection_struct *conn, struct smb_request *req,
7489                           struct trans_state *state)
7490 {
7491         if (Protocol >= PROTOCOL_NT1) {
7492                 req->flags2 |= 0x40; /* IS_LONG_NAME */
7493                 SSVAL(req->inbuf,smb_flg2,req->flags2);
7494         }
7495
7496         if (conn->encrypt_level == Required && !req->encrypted) {
7497                 if (state->call != TRANSACT2_QFSINFO &&
7498                                 state->call != TRANSACT2_SETFSINFO) {
7499                         DEBUG(0,("handle_trans2: encryption required "
7500                                 "with call 0x%x\n",
7501                                 (unsigned int)state->call));
7502                         reply_nterror(req, NT_STATUS_ACCESS_DENIED);
7503                         return;
7504                 }
7505         }
7506
7507         SMB_PERFCOUNT_SET_SUBOP(&req->pcd, state->call);
7508
7509         /* Now we must call the relevant TRANS2 function */
7510         switch(state->call)  {
7511         case TRANSACT2_OPEN:
7512         {
7513                 START_PROFILE(Trans2_open);
7514                 call_trans2open(conn, req,
7515                                 &state->param, state->total_param,
7516                                 &state->data, state->total_data,
7517                                 state->max_data_return);
7518                 END_PROFILE(Trans2_open);
7519                 break;
7520         }
7521
7522         case TRANSACT2_FINDFIRST:
7523         {
7524                 START_PROFILE(Trans2_findfirst);
7525                 call_trans2findfirst(conn, req,
7526                                      &state->param, state->total_param,
7527                                      &state->data, state->total_data,
7528                                      state->max_data_return);
7529                 END_PROFILE(Trans2_findfirst);
7530                 break;
7531         }
7532
7533         case TRANSACT2_FINDNEXT:
7534         {
7535                 START_PROFILE(Trans2_findnext);
7536                 call_trans2findnext(conn, req,
7537                                     &state->param, state->total_param,
7538                                     &state->data, state->total_data,
7539                                     state->max_data_return);
7540                 END_PROFILE(Trans2_findnext);
7541                 break;
7542         }
7543
7544         case TRANSACT2_QFSINFO:
7545         {
7546                 START_PROFILE(Trans2_qfsinfo);
7547                 call_trans2qfsinfo(conn, req,
7548                                    &state->param, state->total_param,
7549                                    &state->data, state->total_data,
7550                                    state->max_data_return);
7551                 END_PROFILE(Trans2_qfsinfo);
7552             break;
7553         }
7554
7555         case TRANSACT2_SETFSINFO:
7556         {
7557                 START_PROFILE(Trans2_setfsinfo);
7558                 call_trans2setfsinfo(conn, req,
7559                                      &state->param, state->total_param,
7560                                      &state->data, state->total_data,
7561                                      state->max_data_return);
7562                 END_PROFILE(Trans2_setfsinfo);
7563                 break;
7564         }
7565
7566         case TRANSACT2_QPATHINFO:
7567         case TRANSACT2_QFILEINFO:
7568         {
7569                 START_PROFILE(Trans2_qpathinfo);
7570                 call_trans2qfilepathinfo(conn, req, state->call,
7571                                          &state->param, state->total_param,
7572                                          &state->data, state->total_data,
7573                                          state->max_data_return);
7574                 END_PROFILE(Trans2_qpathinfo);
7575                 break;
7576         }
7577
7578         case TRANSACT2_SETPATHINFO:
7579         case TRANSACT2_SETFILEINFO:
7580         {
7581                 START_PROFILE(Trans2_setpathinfo);
7582                 call_trans2setfilepathinfo(conn, req, state->call,
7583                                            &state->param, state->total_param,
7584                                            &state->data, state->total_data,
7585                                            state->max_data_return);
7586                 END_PROFILE(Trans2_setpathinfo);
7587                 break;
7588         }
7589
7590         case TRANSACT2_FINDNOTIFYFIRST:
7591         {
7592                 START_PROFILE(Trans2_findnotifyfirst);
7593                 call_trans2findnotifyfirst(conn, req,
7594                                            &state->param, state->total_param,
7595                                            &state->data, state->total_data,
7596                                            state->max_data_return);
7597                 END_PROFILE(Trans2_findnotifyfirst);
7598                 break;
7599         }
7600
7601         case TRANSACT2_FINDNOTIFYNEXT:
7602         {
7603                 START_PROFILE(Trans2_findnotifynext);
7604                 call_trans2findnotifynext(conn, req,
7605                                           &state->param, state->total_param,
7606                                           &state->data, state->total_data,
7607                                           state->max_data_return);
7608                 END_PROFILE(Trans2_findnotifynext);
7609                 break;
7610         }
7611
7612         case TRANSACT2_MKDIR:
7613         {
7614                 START_PROFILE(Trans2_mkdir);
7615                 call_trans2mkdir(conn, req,
7616                                  &state->param, state->total_param,
7617                                  &state->data, state->total_data,
7618                                  state->max_data_return);
7619                 END_PROFILE(Trans2_mkdir);
7620                 break;
7621         }
7622
7623         case TRANSACT2_GET_DFS_REFERRAL:
7624         {
7625                 START_PROFILE(Trans2_get_dfs_referral);
7626                 call_trans2getdfsreferral(conn, req,
7627                                           &state->param, state->total_param,
7628                                           &state->data, state->total_data,
7629                                           state->max_data_return);
7630                 END_PROFILE(Trans2_get_dfs_referral);
7631                 break;
7632         }
7633
7634         case TRANSACT2_IOCTL:
7635         {
7636                 START_PROFILE(Trans2_ioctl);
7637                 call_trans2ioctl(conn, req,
7638                                  &state->param, state->total_param,
7639                                  &state->data, state->total_data,
7640                                  state->max_data_return);
7641                 END_PROFILE(Trans2_ioctl);
7642                 break;
7643         }
7644
7645         default:
7646                 /* Error in request */
7647                 DEBUG(2,("Unknown request %d in trans2 call\n", state->call));
7648                 reply_doserror(req, ERRSRV,ERRerror);
7649         }
7650 }
7651
7652 /****************************************************************************
7653  Reply to a SMBtrans2.
7654  ****************************************************************************/
7655
7656 void reply_trans2(struct smb_request *req)
7657 {
7658         connection_struct *conn = req->conn;
7659         unsigned int dsoff;
7660         unsigned int dscnt;
7661         unsigned int psoff;
7662         unsigned int pscnt;
7663         unsigned int tran_call;
7664         struct trans_state *state;
7665         NTSTATUS result;
7666
7667         START_PROFILE(SMBtrans2);
7668
7669         if (req->wct < 14) {
7670                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7671                 END_PROFILE(SMBtrans2);
7672                 return;
7673         }
7674
7675         dsoff = SVAL(req->vwv+12, 0);
7676         dscnt = SVAL(req->vwv+11, 0);
7677         psoff = SVAL(req->vwv+10, 0);
7678         pscnt = SVAL(req->vwv+9, 0);
7679         tran_call = SVAL(req->vwv+14, 0);
7680
7681         result = allow_new_trans(conn->pending_trans, req->mid);
7682         if (!NT_STATUS_IS_OK(result)) {
7683                 DEBUG(2, ("Got invalid trans2 request: %s\n",
7684                           nt_errstr(result)));
7685                 reply_nterror(req, result);
7686                 END_PROFILE(SMBtrans2);
7687                 return;
7688         }
7689
7690         if (IS_IPC(conn)) {
7691                 switch (tran_call) {
7692                 /* List the allowed trans2 calls on IPC$ */
7693                 case TRANSACT2_OPEN:
7694                 case TRANSACT2_GET_DFS_REFERRAL:
7695                 case TRANSACT2_QFILEINFO:
7696                 case TRANSACT2_QFSINFO:
7697                 case TRANSACT2_SETFSINFO:
7698                         break;
7699                 default:
7700                         reply_doserror(req, ERRSRV, ERRaccess);
7701                         END_PROFILE(SMBtrans2);
7702                         return;
7703                 }
7704         }
7705
7706         if ((state = TALLOC_P(conn, struct trans_state)) == NULL) {
7707                 DEBUG(0, ("talloc failed\n"));
7708                 reply_nterror(req, NT_STATUS_NO_MEMORY);
7709                 END_PROFILE(SMBtrans2);
7710                 return;
7711         }
7712
7713         state->cmd = SMBtrans2;
7714
7715         state->mid = req->mid;
7716         state->vuid = req->vuid;
7717         state->setup_count = SVAL(req->vwv+13, 0);
7718         state->setup = NULL;
7719         state->total_param = SVAL(req->vwv+0, 0);
7720         state->param = NULL;
7721         state->total_data =  SVAL(req->vwv+1, 0);
7722         state->data = NULL;
7723         state->max_param_return = SVAL(req->vwv+2, 0);
7724         state->max_data_return  = SVAL(req->vwv+3, 0);
7725         state->max_setup_return = SVAL(req->vwv+4, 0);
7726         state->close_on_completion = BITSETW(req->vwv+5, 0);
7727         state->one_way = BITSETW(req->vwv+5, 1);
7728
7729         state->call = tran_call;
7730
7731         /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
7732            is so as a sanity check */
7733         if (state->setup_count != 1) {
7734                 /*
7735                  * Need to have rc=0 for ioctl to get job id for OS/2.
7736                  *  Network printing will fail if function is not successful.
7737                  *  Similar function in reply.c will be used if protocol
7738                  *  is LANMAN1.0 instead of LM1.2X002.
7739                  *  Until DosPrintSetJobInfo with PRJINFO3 is supported,
7740                  *  outbuf doesn't have to be set(only job id is used).
7741                  */
7742                 if ( (state->setup_count == 4)
7743                      && (tran_call == TRANSACT2_IOCTL)
7744                      && (SVAL(req->vwv+16, 0) == LMCAT_SPL)
7745                      && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
7746                         DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
7747                 } else {
7748                         DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state->setup_count));
7749                         DEBUG(2,("Transaction is %d\n",tran_call));
7750                         TALLOC_FREE(state);
7751                         reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7752                         END_PROFILE(SMBtrans2);
7753                         return;
7754                 }
7755         }
7756
7757         if ((dscnt > state->total_data) || (pscnt > state->total_param))
7758                 goto bad_param;
7759
7760         if (state->total_data) {
7761
7762                 if (trans_oob(state->total_data, 0, dscnt)
7763                     || trans_oob(smb_len(req->inbuf), dsoff, dscnt)) {
7764                         goto bad_param;
7765                 }
7766
7767                 /* Can't use talloc here, the core routines do realloc on the
7768                  * params and data. */
7769                 state->data = (char *)SMB_MALLOC(state->total_data);
7770                 if (state->data == NULL) {
7771                         DEBUG(0,("reply_trans2: data malloc fail for %u "
7772                                  "bytes !\n", (unsigned int)state->total_data));
7773                         TALLOC_FREE(state);
7774                         reply_nterror(req, NT_STATUS_NO_MEMORY);
7775                         END_PROFILE(SMBtrans2);
7776                         return;
7777                 }
7778
7779                 memcpy(state->data,smb_base(req->inbuf)+dsoff,dscnt);
7780         }
7781
7782         if (state->total_param) {
7783
7784                 if (trans_oob(state->total_param, 0, pscnt)
7785                     || trans_oob(smb_len(req->inbuf), psoff, pscnt)) {
7786                         goto bad_param;
7787                 }
7788
7789                 /* Can't use talloc here, the core routines do realloc on the
7790                  * params and data. */
7791                 state->param = (char *)SMB_MALLOC(state->total_param);
7792                 if (state->param == NULL) {
7793                         DEBUG(0,("reply_trans: param malloc fail for %u "
7794                                  "bytes !\n", (unsigned int)state->total_param));
7795                         SAFE_FREE(state->data);
7796                         TALLOC_FREE(state);
7797                         reply_nterror(req, NT_STATUS_NO_MEMORY);
7798                         END_PROFILE(SMBtrans2);
7799                         return;
7800                 } 
7801
7802                 memcpy(state->param,smb_base(req->inbuf)+psoff,pscnt);
7803         }
7804
7805         state->received_data  = dscnt;
7806         state->received_param = pscnt;
7807
7808         if ((state->received_param == state->total_param) &&
7809             (state->received_data == state->total_data)) {
7810
7811                 handle_trans2(conn, req, state);
7812
7813                 SAFE_FREE(state->data);
7814                 SAFE_FREE(state->param);
7815                 TALLOC_FREE(state);
7816                 END_PROFILE(SMBtrans2);
7817                 return;
7818         }
7819
7820         DLIST_ADD(conn->pending_trans, state);
7821
7822         /* We need to send an interim response then receive the rest
7823            of the parameter/data bytes */
7824         reply_outbuf(req, 0, 0);
7825         show_msg((char *)req->outbuf);
7826         END_PROFILE(SMBtrans2);
7827         return;
7828
7829   bad_param:
7830
7831         DEBUG(0,("reply_trans2: invalid trans parameters\n"));
7832         SAFE_FREE(state->data);
7833         SAFE_FREE(state->param);
7834         TALLOC_FREE(state);
7835         END_PROFILE(SMBtrans2);
7836         reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7837 }
7838
7839
7840 /****************************************************************************
7841  Reply to a SMBtranss2
7842  ****************************************************************************/
7843
7844 void reply_transs2(struct smb_request *req)
7845 {
7846         connection_struct *conn = req->conn;
7847         unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
7848         struct trans_state *state;
7849
7850         START_PROFILE(SMBtranss2);
7851
7852         show_msg((char *)req->inbuf);
7853
7854         if (req->wct < 8) {
7855                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7856                 END_PROFILE(SMBtranss2);
7857                 return;
7858         }
7859
7860         for (state = conn->pending_trans; state != NULL;
7861              state = state->next) {
7862                 if (state->mid == req->mid) {
7863                         break;
7864                 }
7865         }
7866
7867         if ((state == NULL) || (state->cmd != SMBtrans2)) {
7868                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7869                 END_PROFILE(SMBtranss2);
7870                 return;
7871         }
7872
7873         /* Revise state->total_param and state->total_data in case they have
7874            changed downwards */
7875
7876         if (SVAL(req->vwv+0, 0) < state->total_param)
7877                 state->total_param = SVAL(req->vwv+0, 0);
7878         if (SVAL(req->vwv+1, 0) < state->total_data)
7879                 state->total_data = SVAL(req->vwv+1, 0);
7880
7881         pcnt = SVAL(req->vwv+2, 0);
7882         poff = SVAL(req->vwv+3, 0);
7883         pdisp = SVAL(req->vwv+4, 0);
7884
7885         dcnt = SVAL(req->vwv+5, 0);
7886         doff = SVAL(req->vwv+6, 0);
7887         ddisp = SVAL(req->vwv+7, 0);
7888
7889         state->received_param += pcnt;
7890         state->received_data += dcnt;
7891                 
7892         if ((state->received_data > state->total_data) ||
7893             (state->received_param > state->total_param))
7894                 goto bad_param;
7895
7896         if (pcnt) {
7897                 if (trans_oob(state->total_param, pdisp, pcnt)
7898                     || trans_oob(smb_len(req->inbuf), poff, pcnt)) {
7899                         goto bad_param;
7900                 }
7901                 memcpy(state->param+pdisp,smb_base(req->inbuf)+poff,pcnt);
7902         }
7903
7904         if (dcnt) {
7905                 if (trans_oob(state->total_data, ddisp, dcnt)
7906                     || trans_oob(smb_len(req->inbuf), doff, dcnt)) {
7907                         goto bad_param;
7908                 }
7909                 memcpy(state->data+ddisp, smb_base(req->inbuf)+doff,dcnt);
7910         }
7911
7912         if ((state->received_param < state->total_param) ||
7913             (state->received_data < state->total_data)) {
7914                 END_PROFILE(SMBtranss2);
7915                 return;
7916         }
7917
7918         handle_trans2(conn, req, state);
7919
7920         DLIST_REMOVE(conn->pending_trans, state);
7921         SAFE_FREE(state->data);
7922         SAFE_FREE(state->param);
7923         TALLOC_FREE(state);
7924
7925         END_PROFILE(SMBtranss2);
7926         return;
7927
7928   bad_param:
7929
7930         DEBUG(0,("reply_transs2: invalid trans parameters\n"));
7931         DLIST_REMOVE(conn->pending_trans, state);
7932         SAFE_FREE(state->data);
7933         SAFE_FREE(state->param);
7934         TALLOC_FREE(state);
7935         reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7936         END_PROFILE(SMBtranss2);
7937         return;
7938 }