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