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