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