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