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