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