Add "store create time" parameter (docs to follow)
[samba.git] / source3 / smbd / trans2.c
1 /*
2    Unix SMB/CIFS implementation.
3    SMB transaction2 handling
4    Copyright (C) Jeremy Allison                 1994-2007
5    Copyright (C) Stefan (metze) Metzmacher      2003
6    Copyright (C) Volker Lendecke                2005-2007
7    Copyright (C) Steve French                   2005
8    Copyright (C) James Peach                    2006-2007
9
10    Extensively modified by Andrew Tridgell, 1995
11
12    This program is free software; you can redistribute it and/or modify
13    it under the terms of the GNU General Public License as published by
14    the Free Software Foundation; either version 3 of the License, or
15    (at your option) any later version.
16
17    This program is distributed in the hope that it will be useful,
18    but WITHOUT ANY WARRANTY; without even the implied warranty of
19    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20    GNU General Public License for more details.
21
22    You should have received a copy of the GNU General Public License
23    along with this program.  If not, see <http://www.gnu.org/licenses/>.
24 */
25
26 #include "includes.h"
27 #include "version.h"
28 #include "smbd/globals.h"
29 #include "../libcli/auth/libcli_auth.h"
30
31 extern enum protocol_types Protocol;
32
33 #define DIR_ENTRY_SAFETY_MARGIN 4096
34
35 static char *store_file_unix_basic(connection_struct *conn,
36                                 char *pdata,
37                                 files_struct *fsp,
38                                 const SMB_STRUCT_STAT *psbuf);
39
40 static char *store_file_unix_basic_info2(connection_struct *conn,
41                                 char *pdata,
42                                 files_struct *fsp,
43                                 const SMB_STRUCT_STAT *psbuf);
44
45 /********************************************************************
46  Roundup a value to the nearest allocation roundup size boundary.
47  Only do this for Windows clients.
48 ********************************************************************/
49
50 uint64_t smb_roundup(connection_struct *conn, uint64_t val)
51 {
52         uint64_t rval = lp_allocation_roundup_size(SNUM(conn));
53
54         /* Only roundup for Windows clients. */
55         enum remote_arch_types ra_type = get_remote_arch();
56         if (rval && (ra_type != RA_SAMBA) && (ra_type != RA_CIFSFS)) {
57                 val = SMB_ROUNDUP(val,rval);
58         }
59         return val;
60 }
61
62 /****************************************************************************
63  Utility functions for dealing with extended attributes.
64 ****************************************************************************/
65
66 /****************************************************************************
67  Refuse to allow clients to overwrite our private xattrs.
68 ****************************************************************************/
69
70 static bool samba_private_attr_name(const char *unix_ea_name)
71 {
72         static const char * const prohibited_ea_names[] = {
73                 SAMBA_POSIX_INHERITANCE_EA_NAME,
74                 SAMBA_XATTR_DOS_ATTRIB,
75                 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                                const 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 sbuf;
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         sbuf = smb_fname->st;
4021
4022         if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
4023                 return NT_STATUS_INVALID_LEVEL;
4024         }
4025
4026         DEBUG(5,("smbd_do_qfilepathinfo: %s (fnum = %d) level=%d max_data=%u\n",
4027                  smb_fname_str_dbg(smb_fname), fsp ? fsp->fnum : -1,
4028                  info_level, max_data_bytes));
4029
4030         if (ms_dfs_link) {
4031                 mode = dos_mode_msdfs(conn, smb_fname);
4032         } else {
4033                 mode = dos_mode(conn, smb_fname);
4034         }
4035         if (!mode)
4036                 mode = FILE_ATTRIBUTE_NORMAL;
4037
4038         nlink = sbuf.st_ex_nlink;
4039
4040         if (nlink && (mode&aDIR)) {
4041                 nlink = 1;
4042         }
4043
4044         if ((nlink > 0) && delete_pending) {
4045                 nlink -= 1;
4046         }
4047
4048         data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
4049         *ppdata = (char *)SMB_REALLOC(*ppdata, data_size); 
4050         if (*ppdata == NULL) {
4051                 return NT_STATUS_NO_MEMORY;
4052         }
4053         pdata = *ppdata;
4054         dstart = pdata;
4055         dend = dstart + data_size - 1;
4056
4057         if (!null_timespec(write_time_ts) && !INFO_LEVEL_IS_UNIX(info_level)) {
4058                 update_stat_ex_mtime(&sbuf, write_time_ts);
4059         }
4060
4061         create_time_ts = get_create_timespec(conn, fsp, smb_fname);
4062         mtime_ts = sbuf.st_ex_mtime;
4063         atime_ts = sbuf.st_ex_atime;
4064         ctime_ts = get_change_timespec(conn, fsp, smb_fname);
4065
4066         if (lp_dos_filetime_resolution(SNUM(conn))) {
4067                 dos_filetime_timespec(&create_time_ts);
4068                 dos_filetime_timespec(&mtime_ts);
4069                 dos_filetime_timespec(&atime_ts);
4070                 dos_filetime_timespec(&ctime_ts);
4071         }
4072
4073         create_time = convert_timespec_to_time_t(create_time_ts);
4074         mtime = convert_timespec_to_time_t(mtime_ts);
4075         atime = convert_timespec_to_time_t(atime_ts);
4076         c_time = convert_timespec_to_time_t(ctime_ts);
4077
4078         p = strrchr_m(smb_fname->base_name,'/');
4079         if (!p)
4080                 base_name = smb_fname->base_name;
4081         else
4082                 base_name = p+1;
4083
4084         /* NT expects the name to be in an exact form of the *full*
4085            filename. See the trans2 torture test */
4086         if (ISDOT(base_name)) {
4087                 dos_fname = talloc_strdup(mem_ctx, "\\");
4088                 if (!dos_fname) {
4089                         return NT_STATUS_NO_MEMORY;
4090                 }
4091         } else {
4092                 dos_fname = talloc_asprintf(mem_ctx,
4093                                 "\\%s",
4094                                 smb_fname->base_name);
4095                 if (!dos_fname) {
4096                         return NT_STATUS_NO_MEMORY;
4097                 }
4098                 if (is_ntfs_stream_smb_fname(smb_fname)) {
4099                         dos_fname = talloc_asprintf(dos_fname, "%s",
4100                                                     smb_fname->stream_name);
4101                         if (!dos_fname) {
4102                                 return NT_STATUS_NO_MEMORY;
4103                         }
4104                 }
4105
4106                 string_replace(dos_fname, '/', '\\');
4107         }
4108
4109         allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp, &sbuf);
4110
4111         if (!fsp) {
4112                 /* Do we have this path open ? */
4113                 files_struct *fsp1;
4114                 struct file_id fileid = vfs_file_id_from_sbuf(conn, &sbuf);
4115                 fsp1 = file_find_di_first(fileid);
4116                 if (fsp1 && fsp1->initial_allocation_size) {
4117                         allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp1, &sbuf);
4118                 }
4119         }
4120
4121         if (!(mode & aDIR)) {
4122                 file_size = get_file_size_stat(&sbuf);
4123         }
4124
4125         if (fsp) {
4126                 pos = fsp->fh->position_information;
4127         }
4128
4129         if (fsp) {
4130                 access_mask = fsp->access_mask;
4131         } else {
4132                 /* GENERIC_EXECUTE mapping from Windows */
4133                 access_mask = 0x12019F;
4134         }
4135
4136         /* This should be an index number - looks like
4137            dev/ino to me :-)
4138
4139            I think this causes us to fail the IFSKIT
4140            BasicFileInformationTest. -tpot */
4141         file_index =  ((sbuf.st_ex_ino) & UINT32_MAX); /* FileIndexLow */
4142         file_index |= ((uint64_t)((sbuf.st_ex_dev) & UINT32_MAX)) << 32; /* FileIndexHigh */
4143
4144         switch (info_level) {
4145                 case SMB_INFO_STANDARD:
4146                         DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_STANDARD\n"));
4147                         data_size = 22;
4148                         srv_put_dos_date2(pdata,l1_fdateCreation,create_time);
4149                         srv_put_dos_date2(pdata,l1_fdateLastAccess,atime);
4150                         srv_put_dos_date2(pdata,l1_fdateLastWrite,mtime); /* write time */
4151                         SIVAL(pdata,l1_cbFile,(uint32)file_size);
4152                         SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
4153                         SSVAL(pdata,l1_attrFile,mode);
4154                         break;
4155
4156                 case SMB_INFO_QUERY_EA_SIZE:
4157                 {
4158                         unsigned int ea_size =
4159                             estimate_ea_size(conn, fsp,
4160                                              smb_fname->base_name);
4161                         DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
4162                         data_size = 26;
4163                         srv_put_dos_date2(pdata,0,create_time);
4164                         srv_put_dos_date2(pdata,4,atime);
4165                         srv_put_dos_date2(pdata,8,mtime); /* write time */
4166                         SIVAL(pdata,12,(uint32)file_size);
4167                         SIVAL(pdata,16,(uint32)allocation_size);
4168                         SSVAL(pdata,20,mode);
4169                         SIVAL(pdata,22,ea_size);
4170                         break;
4171                 }
4172
4173                 case SMB_INFO_IS_NAME_VALID:
4174                         DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
4175                         if (fsp) {
4176                                 /* os/2 needs this ? really ?*/
4177                                 return NT_STATUS_DOS(ERRDOS, ERRbadfunc);
4178                         }
4179                         /* This is only reached for qpathinfo */
4180                         data_size = 0;
4181                         break;
4182
4183                 case SMB_INFO_QUERY_EAS_FROM_LIST:
4184                 {
4185                         size_t total_ea_len = 0;
4186                         struct ea_list *ea_file_list = NULL;
4187
4188                         DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
4189
4190                         ea_file_list =
4191                             get_ea_list_from_file(mem_ctx, conn, fsp,
4192                                                   smb_fname->base_name,
4193                                                   &total_ea_len);
4194                         ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
4195
4196                         if (!ea_list || (total_ea_len > data_size)) {
4197                                 data_size = 4;
4198                                 SIVAL(pdata,0,4);   /* EA List Length must be set to 4 if no EA's. */
4199                                 break;
4200                         }
4201
4202                         data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
4203                         break;
4204                 }
4205
4206                 case SMB_INFO_QUERY_ALL_EAS:
4207                 {
4208                         /* We have data_size bytes to put EA's into. */
4209                         size_t total_ea_len = 0;
4210
4211                         DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
4212
4213                         ea_list = get_ea_list_from_file(mem_ctx, conn, fsp,
4214                                                         smb_fname->base_name,
4215                                                         &total_ea_len);
4216                         if (!ea_list || (total_ea_len > data_size)) {
4217                                 data_size = 4;
4218                                 SIVAL(pdata,0,4);   /* EA List Length must be set to 4 if no EA's. */
4219                                 break;
4220                         }
4221
4222                         data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
4223                         break;
4224                 }
4225
4226                 case 0xFF0F:/*SMB2_INFO_QUERY_ALL_EAS*/
4227                 {
4228                         /* We have data_size bytes to put EA's into. */
4229                         size_t total_ea_len = 0;
4230                         struct ea_list *ea_file_list = NULL;
4231
4232                         DEBUG(10,("smbd_do_qfilepathinfo: SMB2_INFO_QUERY_ALL_EAS\n"));
4233
4234                         /*TODO: add filtering and index handling */
4235
4236                         ea_file_list =
4237                             get_ea_list_from_file(mem_ctx, conn, fsp,
4238                                                   smb_fname->base_name,
4239                                                   &total_ea_len);
4240                         if (!ea_file_list) {
4241                                 return NT_STATUS_NO_EAS_ON_FILE;
4242                         }
4243
4244                         status = fill_ea_chained_buffer(mem_ctx,
4245                                                         pdata,
4246                                                         data_size,
4247                                                         &data_size,
4248                                                         conn, ea_file_list);
4249                         if (!NT_STATUS_IS_OK(status)) {
4250                                 return status;
4251                         }
4252                         break;
4253                 }
4254
4255                 case SMB_FILE_BASIC_INFORMATION:
4256                 case SMB_QUERY_FILE_BASIC_INFO:
4257
4258                         if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
4259                                 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
4260                                 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
4261                         } else {
4262                                 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
4263                                 data_size = 40;
4264                                 SIVAL(pdata,36,0);
4265                         }
4266                         put_long_date_timespec(pdata,create_time_ts);
4267                         put_long_date_timespec(pdata+8,atime_ts);
4268                         put_long_date_timespec(pdata+16,mtime_ts); /* write time */
4269                         put_long_date_timespec(pdata+24,ctime_ts); /* change time */
4270                         SIVAL(pdata,32,mode);
4271
4272                         DEBUG(5,("SMB_QFBI - "));
4273                         DEBUG(5,("create: %s ", ctime(&create_time)));
4274                         DEBUG(5,("access: %s ", ctime(&atime)));
4275                         DEBUG(5,("write: %s ", ctime(&mtime)));
4276                         DEBUG(5,("change: %s ", ctime(&c_time)));
4277                         DEBUG(5,("mode: %x\n", mode));
4278                         break;
4279
4280                 case SMB_FILE_STANDARD_INFORMATION:
4281                 case SMB_QUERY_FILE_STANDARD_INFO:
4282
4283                         DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
4284                         data_size = 24;
4285                         SOFF_T(pdata,0,allocation_size);
4286                         SOFF_T(pdata,8,file_size);
4287                         SIVAL(pdata,16,nlink);
4288                         SCVAL(pdata,20,delete_pending?1:0);
4289                         SCVAL(pdata,21,(mode&aDIR)?1:0);
4290                         SSVAL(pdata,22,0); /* Padding. */
4291                         break;
4292
4293                 case SMB_FILE_EA_INFORMATION:
4294                 case SMB_QUERY_FILE_EA_INFO:
4295                 {
4296                         unsigned int ea_size =
4297                             estimate_ea_size(conn, fsp, smb_fname->base_name);
4298                         DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
4299                         data_size = 4;
4300                         SIVAL(pdata,0,ea_size);
4301                         break;
4302                 }
4303
4304                 /* Get the 8.3 name - used if NT SMB was negotiated. */
4305                 case SMB_QUERY_FILE_ALT_NAME_INFO:
4306                 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
4307                 {
4308                         int len;
4309                         char mangled_name[13];
4310                         DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
4311                         if (!name_to_8_3(base_name,mangled_name,
4312                                                 True,conn->params)) {
4313                                 return NT_STATUS_NO_MEMORY;
4314                         }
4315                         len = srvstr_push(dstart, flags2,
4316                                           pdata+4, mangled_name,
4317                                           PTR_DIFF(dend, pdata+4),
4318                                           STR_UNICODE);
4319                         data_size = 4 + len;
4320                         SIVAL(pdata,0,len);
4321                         break;
4322                 }
4323
4324                 case SMB_QUERY_FILE_NAME_INFO:
4325                 {
4326                         int len;
4327                         /*
4328                           this must be *exactly* right for ACLs on mapped drives to work
4329                          */
4330                         len = srvstr_push(dstart, flags2,
4331                                           pdata+4, dos_fname,
4332                                           PTR_DIFF(dend, pdata+4),
4333                                           STR_UNICODE);
4334                         DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
4335                         data_size = 4 + len;
4336                         SIVAL(pdata,0,len);
4337                         break;
4338                 }
4339
4340                 case SMB_FILE_ALLOCATION_INFORMATION:
4341                 case SMB_QUERY_FILE_ALLOCATION_INFO:
4342                         DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
4343                         data_size = 8;
4344                         SOFF_T(pdata,0,allocation_size);
4345                         break;
4346
4347                 case SMB_FILE_END_OF_FILE_INFORMATION:
4348                 case SMB_QUERY_FILE_END_OF_FILEINFO:
4349                         DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
4350                         data_size = 8;
4351                         SOFF_T(pdata,0,file_size);
4352                         break;
4353
4354                 case SMB_QUERY_FILE_ALL_INFO:
4355                 case SMB_FILE_ALL_INFORMATION:
4356                 {
4357                         int len;
4358                         unsigned int ea_size =
4359                             estimate_ea_size(conn, fsp, smb_fname->base_name);
4360                         DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
4361                         put_long_date_timespec(pdata,create_time_ts);
4362                         put_long_date_timespec(pdata+8,atime_ts);
4363                         put_long_date_timespec(pdata+16,mtime_ts); /* write time */
4364                         put_long_date_timespec(pdata+24,ctime_ts); /* change time */
4365                         SIVAL(pdata,32,mode);
4366                         SIVAL(pdata,36,0); /* padding. */
4367                         pdata += 40;
4368                         SOFF_T(pdata,0,allocation_size);
4369                         SOFF_T(pdata,8,file_size);
4370                         SIVAL(pdata,16,nlink);
4371                         SCVAL(pdata,20,delete_pending);
4372                         SCVAL(pdata,21,(mode&aDIR)?1:0);
4373                         SSVAL(pdata,22,0);
4374                         pdata += 24;
4375                         SIVAL(pdata,0,ea_size);
4376                         pdata += 4; /* EA info */
4377                         len = srvstr_push(dstart, flags2,
4378                                           pdata+4, dos_fname,
4379                                           PTR_DIFF(dend, pdata+4),
4380                                           STR_UNICODE);
4381                         SIVAL(pdata,0,len);
4382                         pdata += 4 + len;
4383                         data_size = PTR_DIFF(pdata,(*ppdata));
4384                         break;
4385                 }
4386
4387                 case 0xFF12:/*SMB2_FILE_ALL_INFORMATION*/
4388                 {
4389                         int len;
4390                         unsigned int ea_size =
4391                             estimate_ea_size(conn, fsp, smb_fname->base_name);
4392                         DEBUG(10,("smbd_do_qfilepathinfo: SMB2_FILE_ALL_INFORMATION\n"));
4393                         put_long_date_timespec(pdata+0x00,create_time_ts);
4394                         put_long_date_timespec(pdata+0x08,atime_ts);
4395                         put_long_date_timespec(pdata+0x10,mtime_ts); /* write time */
4396                         put_long_date_timespec(pdata+0x18,ctime_ts); /* change time */
4397                         SIVAL(pdata,    0x20, mode);
4398                         SIVAL(pdata,    0x24, 0); /* padding. */
4399                         SBVAL(pdata,    0x28, allocation_size);
4400                         SBVAL(pdata,    0x30, file_size);
4401                         SIVAL(pdata,    0x38, nlink);
4402                         SCVAL(pdata,    0x3C, delete_pending);
4403                         SCVAL(pdata,    0x3D, (mode&aDIR)?1:0);
4404                         SSVAL(pdata,    0x3E, 0); /* padding */
4405                         SBVAL(pdata,    0x40, file_index);
4406                         SIVAL(pdata,    0x48, ea_size);
4407                         SIVAL(pdata,    0x4C, access_mask);
4408                         SBVAL(pdata,    0x50, pos);
4409                         SIVAL(pdata,    0x58, mode); /*TODO: mode != mode fix this!!! */
4410                         SIVAL(pdata,    0x5C, 0); /* No alignment needed. */
4411
4412                         pdata += 0x60;
4413
4414                         len = srvstr_push(dstart, flags2,
4415                                           pdata+4, dos_fname,
4416                                           PTR_DIFF(dend, pdata+4),
4417                                           STR_UNICODE);
4418                         SIVAL(pdata,0,len);
4419                         pdata += 4 + len;
4420                         data_size = PTR_DIFF(pdata,(*ppdata));
4421                         break;
4422                 }
4423                 case SMB_FILE_INTERNAL_INFORMATION:
4424
4425                         DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
4426                         SBVAL(pdata, 0, file_index);
4427                         data_size = 8;
4428                         break;
4429
4430                 case SMB_FILE_ACCESS_INFORMATION:
4431                         DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
4432                         SIVAL(pdata, 0, access_mask);
4433                         data_size = 4;
4434                         break;
4435
4436                 case SMB_FILE_NAME_INFORMATION:
4437                         /* Pathname with leading '\'. */
4438                         {
4439                                 size_t byte_len;
4440                                 byte_len = dos_PutUniCode(pdata+4,dos_fname,(size_t)max_data_bytes,False);
4441                                 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
4442                                 SIVAL(pdata,0,byte_len);
4443                                 data_size = 4 + byte_len;
4444                                 break;
4445                         }
4446
4447                 case SMB_FILE_DISPOSITION_INFORMATION:
4448                         DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
4449                         data_size = 1;
4450                         SCVAL(pdata,0,delete_pending);
4451                         break;
4452
4453                 case SMB_FILE_POSITION_INFORMATION:
4454                         DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
4455                         data_size = 8;
4456                         SOFF_T(pdata,0,pos);
4457                         break;
4458
4459                 case SMB_FILE_MODE_INFORMATION:
4460                         DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
4461                         SIVAL(pdata,0,mode);
4462                         data_size = 4;
4463                         break;
4464
4465                 case SMB_FILE_ALIGNMENT_INFORMATION:
4466                         DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
4467                         SIVAL(pdata,0,0); /* No alignment needed. */
4468                         data_size = 4;
4469                         break;
4470
4471                 /*
4472                  * NT4 server just returns "invalid query" to this - if we try
4473                  * to answer it then NTws gets a BSOD! (tridge).  W2K seems to
4474                  * want this. JRA.
4475                  */
4476                 /* The first statement above is false - verified using Thursby
4477                  * client against NT4 -- gcolley.
4478                  */
4479                 case SMB_QUERY_FILE_STREAM_INFO:
4480                 case SMB_FILE_STREAM_INFORMATION: {
4481                         unsigned int num_streams;
4482                         struct stream_struct *streams;
4483
4484                         DEBUG(10,("smbd_do_qfilepathinfo: "
4485                                   "SMB_FILE_STREAM_INFORMATION\n"));
4486
4487                         if (is_ntfs_stream_smb_fname(smb_fname)) {
4488                                 return NT_STATUS_INVALID_PARAMETER;
4489                         }
4490
4491                         status = SMB_VFS_STREAMINFO(
4492                                 conn, fsp, smb_fname->base_name, talloc_tos(),
4493                                 &num_streams, &streams);
4494
4495                         if (!NT_STATUS_IS_OK(status)) {
4496                                 DEBUG(10, ("could not get stream info: %s\n",
4497                                            nt_errstr(status)));
4498                                 return status;
4499                         }
4500
4501                         status = marshall_stream_info(num_streams, streams,
4502                                                       pdata, max_data_bytes,
4503                                                       &data_size);
4504
4505                         if (!NT_STATUS_IS_OK(status)) {
4506                                 DEBUG(10, ("marshall_stream_info failed: %s\n",
4507                                            nt_errstr(status)));
4508                                 return status;
4509                         }
4510
4511                         TALLOC_FREE(streams);
4512
4513                         break;
4514                 }
4515                 case SMB_QUERY_COMPRESSION_INFO:
4516                 case SMB_FILE_COMPRESSION_INFORMATION:
4517                         DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
4518                         SOFF_T(pdata,0,file_size);
4519                         SIVAL(pdata,8,0); /* ??? */
4520                         SIVAL(pdata,12,0); /* ??? */
4521                         data_size = 16;
4522                         break;
4523
4524                 case SMB_FILE_NETWORK_OPEN_INFORMATION:
4525                         DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
4526                         put_long_date_timespec(pdata,create_time_ts);
4527                         put_long_date_timespec(pdata+8,atime_ts);
4528                         put_long_date_timespec(pdata+16,mtime_ts); /* write time */
4529                         put_long_date_timespec(pdata+24,ctime_ts); /* change time */
4530                         SOFF_T(pdata,32,allocation_size);
4531                         SOFF_T(pdata,40,file_size);
4532                         SIVAL(pdata,48,mode);
4533                         SIVAL(pdata,52,0); /* ??? */
4534                         data_size = 56;
4535                         break;
4536
4537                 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
4538                         DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
4539                         SIVAL(pdata,0,mode);
4540                         SIVAL(pdata,4,0);
4541                         data_size = 8;
4542                         break;
4543
4544                 /*
4545                  * CIFS UNIX Extensions.
4546                  */
4547
4548                 case SMB_QUERY_FILE_UNIX_BASIC:
4549
4550                         pdata = store_file_unix_basic(conn, pdata, fsp, &sbuf);
4551                         data_size = PTR_DIFF(pdata,(*ppdata));
4552
4553                         {
4554                                 int i;
4555                                 DEBUG(4,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_BASIC "));
4556
4557                                 for (i=0; i<100; i++)
4558                                         DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
4559                                 DEBUG(4,("\n"));
4560                         }
4561
4562                         break;
4563
4564                 case SMB_QUERY_FILE_UNIX_INFO2:
4565
4566                         pdata = store_file_unix_basic_info2(conn, pdata, fsp, &sbuf);
4567                         data_size = PTR_DIFF(pdata,(*ppdata));
4568
4569                         {
4570                                 int i;
4571                                 DEBUG(4,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
4572
4573                                 for (i=0; i<100; i++)
4574                                         DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
4575                                 DEBUG(4,("\n"));
4576                         }
4577
4578                         break;
4579
4580                 case SMB_QUERY_FILE_UNIX_LINK:
4581                         {
4582                                 int len;
4583                                 char *buffer = TALLOC_ARRAY(mem_ctx, char, PATH_MAX+1);
4584
4585                                 if (!buffer) {
4586                                         return NT_STATUS_NO_MEMORY;
4587                                 }
4588
4589                                 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
4590 #ifdef S_ISLNK
4591                                 if(!S_ISLNK(sbuf.st_ex_mode)) {
4592                                         return NT_STATUS_DOS(ERRSRV, ERRbadlink);
4593                                 }
4594 #else
4595                                 return NT_STATUS_DOS(ERRDOS, ERRbadlink);
4596 #endif
4597                                 len = SMB_VFS_READLINK(conn,
4598                                                        smb_fname->base_name,
4599                                                        buffer, PATH_MAX);
4600                                 if (len == -1) {
4601                                         return map_nt_error_from_unix(errno);
4602                                 }
4603                                 buffer[len] = 0;
4604                                 len = srvstr_push(dstart, flags2,
4605                                                   pdata, buffer,
4606                                                   PTR_DIFF(dend, pdata),
4607                                                   STR_TERMINATE);
4608                                 pdata += len;
4609                                 data_size = PTR_DIFF(pdata,(*ppdata));
4610
4611                                 break;
4612                         }
4613
4614 #if defined(HAVE_POSIX_ACLS)
4615                 case SMB_QUERY_POSIX_ACL:
4616                         {
4617                                 SMB_ACL_T file_acl = NULL;
4618                                 SMB_ACL_T def_acl = NULL;
4619                                 uint16 num_file_acls = 0;
4620                                 uint16 num_def_acls = 0;
4621
4622                                 if (fsp && !fsp->is_directory && (fsp->fh->fd != -1)) {
4623                                         file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp);
4624                                 } else {
4625                                         file_acl =
4626                                             SMB_VFS_SYS_ACL_GET_FILE(conn,
4627                                                 smb_fname->base_name,
4628                                                 SMB_ACL_TYPE_ACCESS);
4629                                 }
4630
4631                                 if (file_acl == NULL && no_acl_syscall_error(errno)) {
4632                                         DEBUG(5,("smbd_do_qfilepathinfo: ACLs "
4633                                                  "not implemented on "
4634                                                  "filesystem containing %s\n",
4635                                                  smb_fname->base_name));
4636                                         return NT_STATUS_NOT_IMPLEMENTED;
4637                                 }
4638
4639                                 if (S_ISDIR(sbuf.st_ex_mode)) {
4640                                         if (fsp && fsp->is_directory) {
4641                                                 def_acl =
4642                                                     SMB_VFS_SYS_ACL_GET_FILE(
4643                                                             conn,
4644                                                             fsp->fsp_name->base_name,
4645                                                             SMB_ACL_TYPE_DEFAULT);
4646                                         } else {
4647                                                 def_acl =
4648                                                     SMB_VFS_SYS_ACL_GET_FILE(
4649                                                             conn,
4650                                                             smb_fname->base_name,
4651                                                             SMB_ACL_TYPE_DEFAULT);
4652                                         }
4653                                         def_acl = free_empty_sys_acl(conn, def_acl);
4654                                 }
4655
4656                                 num_file_acls = count_acl_entries(conn, file_acl);
4657                                 num_def_acls = count_acl_entries(conn, def_acl);
4658
4659                                 if ( data_size < (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE) {
4660                                         DEBUG(5,("smbd_do_qfilepathinfo: data_size too small (%u) need %u\n",
4661                                                 data_size,
4662                                                 (unsigned int)((num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE +
4663                                                         SMB_POSIX_ACL_HEADER_SIZE) ));
4664                                         if (file_acl) {
4665                                                 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4666                                         }
4667                                         if (def_acl) {
4668                                                 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4669                                         }
4670                                         return NT_STATUS_BUFFER_TOO_SMALL;
4671                                 }
4672
4673                                 SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
4674                                 SSVAL(pdata,2,num_file_acls);
4675                                 SSVAL(pdata,4,num_def_acls);
4676                                 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE, &sbuf, file_acl)) {
4677                                         if (file_acl) {
4678                                                 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4679                                         }
4680                                         if (def_acl) {
4681                                                 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4682                                         }
4683                                         return NT_STATUS_INTERNAL_ERROR;
4684                                 }
4685                                 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE + (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE), &sbuf, def_acl)) {
4686                                         if (file_acl) {
4687                                                 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4688                                         }
4689                                         if (def_acl) {
4690                                                 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4691                                         }
4692                                         return NT_STATUS_INTERNAL_ERROR;
4693                                 }
4694
4695                                 if (file_acl) {
4696                                         SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4697                                 }
4698                                 if (def_acl) {
4699                                         SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4700                                 }
4701                                 data_size = (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE;
4702                                 break;
4703                         }
4704 #endif
4705
4706
4707                 case SMB_QUERY_POSIX_LOCK:
4708                 {
4709                         uint64_t count;
4710                         uint64_t offset;
4711                         uint32 lock_pid;
4712                         enum brl_type lock_type;
4713
4714                         /* We need an open file with a real fd for this. */
4715                         if (!fsp || fsp->is_directory || fsp->fh->fd == -1) {
4716                                 return NT_STATUS_INVALID_LEVEL;
4717                         }
4718
4719                         if (lock_data_count != POSIX_LOCK_DATA_SIZE) {
4720                                 return NT_STATUS_INVALID_PARAMETER;
4721                         }
4722
4723                         switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
4724                                 case POSIX_LOCK_TYPE_READ:
4725                                         lock_type = READ_LOCK;
4726                                         break;
4727                                 case POSIX_LOCK_TYPE_WRITE:
4728                                         lock_type = WRITE_LOCK;
4729                                         break;
4730                                 case POSIX_LOCK_TYPE_UNLOCK:
4731                                 default:
4732                                         /* There's no point in asking for an unlock... */
4733                                         return NT_STATUS_INVALID_PARAMETER;
4734                         }
4735
4736                         lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
4737 #if defined(HAVE_LONGLONG)
4738                         offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
4739                                         ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
4740                         count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
4741                                         ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
4742 #else /* HAVE_LONGLONG */
4743                         offset = (uint64_t)IVAL(pdata,POSIX_LOCK_START_OFFSET);
4744                         count = (uint64_t)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
4745 #endif /* HAVE_LONGLONG */
4746
4747                         status = query_lock(fsp,
4748                                         &lock_pid,
4749                                         &count,
4750                                         &offset,
4751                                         &lock_type,
4752                                         POSIX_LOCK);
4753
4754                         if (ERROR_WAS_LOCK_DENIED(status)) {
4755                                 /* Here we need to report who has it locked... */
4756                                 data_size = POSIX_LOCK_DATA_SIZE;
4757
4758                                 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, lock_type);
4759                                 SSVAL(pdata, POSIX_LOCK_FLAGS_OFFSET, 0);
4760                                 SIVAL(pdata, POSIX_LOCK_PID_OFFSET, lock_pid);
4761 #if defined(HAVE_LONGLONG)
4762                                 SIVAL(pdata, POSIX_LOCK_START_OFFSET, (uint32)(offset & 0xFFFFFFFF));
4763                                 SIVAL(pdata, POSIX_LOCK_START_OFFSET + 4, (uint32)((offset >> 32) & 0xFFFFFFFF));
4764                                 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, (uint32)(count & 0xFFFFFFFF));
4765                                 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET + 4, (uint32)((count >> 32) & 0xFFFFFFFF));
4766 #else /* HAVE_LONGLONG */
4767                                 SIVAL(pdata, POSIX_LOCK_START_OFFSET, offset);
4768                                 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, count);
4769 #endif /* HAVE_LONGLONG */
4770
4771                         } else if (NT_STATUS_IS_OK(status)) {
4772                                 /* For success we just return a copy of what we sent
4773                                    with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
4774                                 data_size = POSIX_LOCK_DATA_SIZE;
4775                                 memcpy(pdata, lock_data, POSIX_LOCK_DATA_SIZE);
4776                                 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, POSIX_LOCK_TYPE_UNLOCK);
4777                         } else {
4778                                 return status;
4779                         }
4780                         break;
4781                 }
4782
4783                 default:
4784                         return NT_STATUS_INVALID_LEVEL;
4785         }
4786
4787         *pdata_size = data_size;
4788         return NT_STATUS_OK;
4789 }
4790
4791 /****************************************************************************
4792  Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
4793  file name or file id).
4794 ****************************************************************************/
4795
4796 static void call_trans2qfilepathinfo(connection_struct *conn,
4797                                      struct smb_request *req,
4798                                      unsigned int tran_call,
4799                                      char **pparams, int total_params,
4800                                      char **ppdata, int total_data,
4801                                      unsigned int max_data_bytes)
4802 {
4803         char *params = *pparams;
4804         char *pdata = *ppdata;
4805         uint16 info_level;
4806         unsigned int data_size = 0;
4807         unsigned int param_size = 2;
4808         struct smb_filename *smb_fname = NULL;
4809         bool delete_pending = False;
4810         struct timespec write_time_ts;
4811         files_struct *fsp = NULL;
4812         struct file_id fileid;
4813         struct ea_list *ea_list = NULL;
4814         int lock_data_count = 0;
4815         char *lock_data = NULL;
4816         bool ms_dfs_link = false;
4817         NTSTATUS status = NT_STATUS_OK;
4818
4819         if (!params) {
4820                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4821                 return;
4822         }
4823
4824         ZERO_STRUCT(write_time_ts);
4825
4826         if (tran_call == TRANSACT2_QFILEINFO) {
4827                 if (total_params < 4) {
4828                         reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4829                         return;
4830                 }
4831
4832                 if (IS_IPC(conn)) {
4833                         call_trans2qpipeinfo(conn, req, tran_call,
4834                                              pparams, total_params,
4835                                              ppdata, total_data,
4836                                              max_data_bytes);
4837                         return;
4838                 }
4839
4840                 fsp = file_fsp(req, SVAL(params,0));
4841                 info_level = SVAL(params,2);
4842
4843                 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
4844
4845                 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
4846                         reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4847                         return;
4848                 }
4849
4850                 /* Initial check for valid fsp ptr. */
4851                 if (!check_fsp_open(conn, req, fsp)) {
4852                         return;
4853                 }
4854
4855                 status = copy_smb_filename(talloc_tos(), fsp->fsp_name,
4856                                            &smb_fname);
4857                 if (!NT_STATUS_IS_OK(status)) {
4858                         reply_nterror(req, status);
4859                         return;
4860                 }
4861
4862                 if(fsp->fake_file_handle) {
4863                         /*
4864                          * This is actually for the QUOTA_FAKE_FILE --metze
4865                          */
4866
4867                         /* We know this name is ok, it's already passed the checks. */
4868
4869                 } else if(fsp->is_directory || fsp->fh->fd == -1) {
4870                         /*
4871                          * This is actually a QFILEINFO on a directory
4872                          * handle (returned from an NT SMB). NT5.0 seems
4873                          * to do this call. JRA.
4874                          */
4875
4876                         if (INFO_LEVEL_IS_UNIX(info_level)) {
4877                                 /* Always do lstat for UNIX calls. */
4878                                 if (SMB_VFS_LSTAT(conn, smb_fname)) {
4879                                         DEBUG(3,("call_trans2qfilepathinfo: "
4880                                                  "SMB_VFS_LSTAT of %s failed "
4881                                                  "(%s)\n",
4882                                                  smb_fname_str_dbg(smb_fname),
4883                                                  strerror(errno)));
4884                                         reply_nterror(req,
4885                                                 map_nt_error_from_unix(errno));
4886                                         return;
4887                                 }
4888                         } else if (SMB_VFS_STAT(conn, smb_fname)) {
4889                                 DEBUG(3,("call_trans2qfilepathinfo: "
4890                                          "SMB_VFS_STAT of %s failed (%s)\n",
4891                                          smb_fname_str_dbg(smb_fname),
4892                                          strerror(errno)));
4893                                 reply_nterror(req,
4894                                         map_nt_error_from_unix(errno));
4895                                 return;
4896                         }
4897
4898                         fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
4899                         get_file_infos(fileid, &delete_pending, &write_time_ts);
4900                 } else {
4901                         /*
4902                          * Original code - this is an open file.
4903                          */
4904                         if (!check_fsp(conn, req, fsp)) {
4905                                 return;
4906                         }
4907
4908                         if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
4909                                 DEBUG(3, ("fstat of fnum %d failed (%s)\n",
4910                                           fsp->fnum, strerror(errno)));
4911                                 reply_nterror(req,
4912                                         map_nt_error_from_unix(errno));
4913                                 return;
4914                         }
4915                         fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
4916                         get_file_infos(fileid, &delete_pending, &write_time_ts);
4917                 }
4918
4919         } else {
4920                 char *fname = NULL;
4921
4922                 /* qpathinfo */
4923                 if (total_params < 7) {
4924                         reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4925                         return;
4926                 }
4927
4928                 info_level = SVAL(params,0);
4929
4930                 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
4931
4932                 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
4933                         reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4934                         return;
4935                 }
4936
4937                 srvstr_get_path(req, params, req->flags2, &fname, &params[6],
4938                                 total_params - 6,
4939                                 STR_TERMINATE, &status);
4940                 if (!NT_STATUS_IS_OK(status)) {
4941                         reply_nterror(req, status);
4942                         return;
4943                 }
4944
4945                 status = filename_convert(req,
4946                                         conn,
4947                                         req->flags2 & FLAGS2_DFS_PATHNAMES,
4948                                         fname,
4949                                         0,
4950                                         NULL,
4951                                         &smb_fname);
4952                 if (!NT_STATUS_IS_OK(status)) {
4953                         if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
4954                                 reply_botherror(req,
4955                                                 NT_STATUS_PATH_NOT_COVERED,
4956                                                 ERRSRV, ERRbadpath);
4957                                 return;
4958                         }
4959                         reply_nterror(req, status);
4960                         return;
4961                 }
4962
4963                 /* If this is a stream, check if there is a delete_pending. */
4964                 if ((conn->fs_capabilities & FILE_NAMED_STREAMS)
4965                     && is_ntfs_stream_smb_fname(smb_fname)) {
4966                         struct smb_filename *smb_fname_base = NULL;
4967
4968                         /* Create an smb_filename with stream_name == NULL. */
4969                         status =
4970                             create_synthetic_smb_fname(talloc_tos(),
4971                                                        smb_fname->base_name,
4972                                                        NULL, NULL,
4973                                                        &smb_fname_base);
4974                         if (!NT_STATUS_IS_OK(status)) {
4975                                 reply_nterror(req, status);
4976                                 return;
4977                         }
4978
4979                         if (INFO_LEVEL_IS_UNIX(info_level)) {
4980                                 /* Always do lstat for UNIX calls. */
4981                                 if (SMB_VFS_LSTAT(conn, smb_fname_base) != 0) {
4982                                         DEBUG(3,("call_trans2qfilepathinfo: "
4983                                                  "SMB_VFS_LSTAT of %s failed "
4984                                                  "(%s)\n",
4985                                                  smb_fname_str_dbg(smb_fname_base),
4986                                                  strerror(errno)));
4987                                         TALLOC_FREE(smb_fname_base);
4988                                         reply_nterror(req,
4989                                                 map_nt_error_from_unix(errno));
4990                                         return;
4991                                 }
4992                         } else {
4993                                 if (SMB_VFS_STAT(conn, smb_fname_base) != 0) {
4994                                         DEBUG(3,("call_trans2qfilepathinfo: "
4995                                                  "fileinfo of %s failed "
4996                                                  "(%s)\n",
4997                                                  smb_fname_str_dbg(smb_fname_base),
4998                                                  strerror(errno)));
4999                                         TALLOC_FREE(smb_fname_base);
5000                                         reply_nterror(req,
5001                                                 map_nt_error_from_unix(errno));
5002                                         return;
5003                                 }
5004                         }
5005
5006                         fileid = vfs_file_id_from_sbuf(conn,
5007                                                        &smb_fname_base->st);
5008                         TALLOC_FREE(smb_fname_base);
5009                         get_file_infos(fileid, &delete_pending, NULL);
5010                         if (delete_pending) {
5011                                 reply_nterror(req, NT_STATUS_DELETE_PENDING);
5012                                 return;
5013                         }
5014                 }
5015
5016                 if (INFO_LEVEL_IS_UNIX(info_level)) {
5017                         /* Always do lstat for UNIX calls. */
5018                         if (SMB_VFS_LSTAT(conn, smb_fname)) {
5019                                 DEBUG(3,("call_trans2qfilepathinfo: "
5020                                          "SMB_VFS_LSTAT of %s failed (%s)\n",
5021                                          smb_fname_str_dbg(smb_fname),
5022                                          strerror(errno)));
5023                                 reply_nterror(req,
5024                                         map_nt_error_from_unix(errno));
5025                                 return;
5026                         }
5027
5028                 } else if (!VALID_STAT(smb_fname->st) &&
5029                            SMB_VFS_STAT(conn, smb_fname) &&
5030                            (info_level != SMB_INFO_IS_NAME_VALID)) {
5031                         ms_dfs_link = check_msdfs_link(conn,
5032                                                        smb_fname->base_name,
5033                                                        &smb_fname->st);
5034
5035                         if (!ms_dfs_link) {
5036                                 DEBUG(3,("call_trans2qfilepathinfo: "
5037                                          "SMB_VFS_STAT of %s failed (%s)\n",
5038                                          smb_fname_str_dbg(smb_fname),
5039                                          strerror(errno)));
5040                                 reply_nterror(req,
5041                                         map_nt_error_from_unix(errno));
5042                                 return;
5043                         }
5044                 }
5045
5046                 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5047                 get_file_infos(fileid, &delete_pending, &write_time_ts);
5048                 if (delete_pending) {
5049                         reply_nterror(req, NT_STATUS_DELETE_PENDING);
5050                         return;
5051                 }
5052         }
5053
5054         DEBUG(3,("call_trans2qfilepathinfo %s (fnum = %d) level=%d call=%d "
5055                  "total_data=%d\n", smb_fname_str_dbg(smb_fname),
5056                  fsp ? fsp->fnum : -1, info_level,tran_call,total_data));
5057
5058         /* Pull out any data sent here before we realloc. */
5059         switch (info_level) {
5060                 case SMB_INFO_QUERY_EAS_FROM_LIST:
5061                 {
5062                         /* Pull any EA list from the data portion. */
5063                         uint32 ea_size;
5064
5065                         if (total_data < 4) {
5066                                 reply_nterror(
5067                                         req, NT_STATUS_INVALID_PARAMETER);
5068                                 return;
5069                         }
5070                         ea_size = IVAL(pdata,0);
5071
5072                         if (total_data > 0 && ea_size != total_data) {
5073                                 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
5074 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
5075                                 reply_nterror(
5076                                         req, NT_STATUS_INVALID_PARAMETER);
5077                                 return;
5078                         }
5079
5080                         if (!lp_ea_support(SNUM(conn))) {
5081                                 reply_doserror(req, ERRDOS,
5082                                                ERReasnotsupported);
5083                                 return;
5084                         }
5085
5086                         /* Pull out the list of names. */
5087                         ea_list = read_ea_name_list(req, pdata + 4, ea_size - 4);
5088                         if (!ea_list) {
5089                                 reply_nterror(
5090                                         req, NT_STATUS_INVALID_PARAMETER);
5091                                 return;
5092                         }
5093                         break;
5094                 }
5095
5096                 case SMB_QUERY_POSIX_LOCK:
5097                 {
5098                         if (fsp == NULL || fsp->fh->fd == -1) {
5099                                 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
5100                                 return;
5101                         }
5102
5103                         if (total_data != POSIX_LOCK_DATA_SIZE) {
5104                                 reply_nterror(
5105                                         req, NT_STATUS_INVALID_PARAMETER);
5106                                 return;
5107                         }
5108
5109                         /* Copy the lock range data. */
5110                         lock_data = (char *)TALLOC_MEMDUP(
5111                                 req, pdata, total_data);
5112                         if (!lock_data) {
5113                                 reply_nterror(req, NT_STATUS_NO_MEMORY);
5114                                 return;
5115                         }
5116                         lock_data_count = total_data;
5117                 }
5118                 default:
5119                         break;
5120         }
5121
5122         *pparams = (char *)SMB_REALLOC(*pparams,2);
5123         if (*pparams == NULL) {
5124                 reply_nterror(req, NT_STATUS_NO_MEMORY);
5125                 return;
5126         }
5127         params = *pparams;
5128         SSVAL(params,0,0);
5129
5130         /*
5131          * draft-leach-cifs-v1-spec-02.txt
5132          * 4.2.14 TRANS2_QUERY_PATH_INFORMATION: Get File Attributes given Path
5133          * says:
5134          *
5135          *  The requested information is placed in the Data portion of the
5136          *  transaction response. For the information levels greater than 0x100,
5137          *  the transaction response has 1 parameter word which should be
5138          *  ignored by the client.
5139          *
5140          * However Windows only follows this rule for the IS_NAME_VALID call.
5141          */
5142         switch (info_level) {
5143         case SMB_INFO_IS_NAME_VALID:
5144                 param_size = 0;
5145                 break;
5146         }
5147
5148         if ((info_level & 0xFF00) == 0xFF00) {
5149                 /*
5150                  * We use levels that start with 0xFF00
5151                  * internally to represent SMB2 specific levels
5152                  */
5153                 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5154                 return;
5155         }
5156
5157         status = smbd_do_qfilepathinfo(conn, req, info_level,
5158                                        fsp, smb_fname,
5159                                        delete_pending, write_time_ts,
5160                                        ms_dfs_link, ea_list,
5161                                        lock_data_count, lock_data,
5162                                        req->flags2, max_data_bytes,
5163                                        ppdata, &data_size);
5164         if (!NT_STATUS_IS_OK(status)) {
5165                 reply_nterror(req, status);
5166                 return;
5167         }
5168
5169         send_trans2_replies(conn, req, params, param_size, *ppdata, data_size,
5170                             max_data_bytes);
5171
5172         return;
5173 }
5174
5175 /****************************************************************************
5176  Set a hard link (called by UNIX extensions and by NT rename with HARD link
5177  code.
5178 ****************************************************************************/
5179
5180 NTSTATUS hardlink_internals(TALLOC_CTX *ctx,
5181                 connection_struct *conn,
5182                 const struct smb_filename *smb_fname_old,
5183                 const struct smb_filename *smb_fname_new)
5184 {
5185         NTSTATUS status = NT_STATUS_OK;
5186
5187         /* source must already exist. */
5188         if (!VALID_STAT(smb_fname_old->st)) {
5189                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5190         }
5191
5192         /* Disallow if newname already exists. */
5193         if (VALID_STAT(smb_fname_new->st)) {
5194                 return NT_STATUS_OBJECT_NAME_COLLISION;
5195         }
5196
5197         /* No links from a directory. */
5198         if (S_ISDIR(smb_fname_old->st.st_ex_mode)) {
5199                 return NT_STATUS_FILE_IS_A_DIRECTORY;
5200         }
5201
5202         /* Setting a hardlink to/from a stream isn't currently supported. */
5203         if (is_ntfs_stream_smb_fname(smb_fname_old) ||
5204             is_ntfs_stream_smb_fname(smb_fname_new)) {
5205                 return NT_STATUS_INVALID_PARAMETER;
5206         }
5207
5208         DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n",
5209                   smb_fname_old->base_name, smb_fname_new->base_name));
5210
5211         if (SMB_VFS_LINK(conn, smb_fname_old->base_name,
5212                          smb_fname_new->base_name) != 0) {
5213                 status = map_nt_error_from_unix(errno);
5214                 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
5215                          nt_errstr(status), smb_fname_old->base_name,
5216                          smb_fname_new->base_name));
5217         }
5218         return status;
5219 }
5220
5221 /****************************************************************************
5222  Deal with setting the time from any of the setfilepathinfo functions.
5223 ****************************************************************************/
5224
5225 NTSTATUS smb_set_file_time(connection_struct *conn,
5226                            files_struct *fsp,
5227                            const struct smb_filename *smb_fname,
5228                            struct smb_file_time *ft,
5229                            bool setting_write_time)
5230 {
5231         struct smb_filename *smb_fname_base = NULL;
5232         uint32 action =
5233                 FILE_NOTIFY_CHANGE_LAST_ACCESS
5234                 |FILE_NOTIFY_CHANGE_LAST_WRITE
5235                 |FILE_NOTIFY_CHANGE_CREATION;
5236         NTSTATUS status;
5237
5238         if (!VALID_STAT(smb_fname->st)) {
5239                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5240         }
5241
5242         /* get some defaults (no modifications) if any info is zero or -1. */
5243         if (null_timespec(ft->create_time)) {
5244                 action &= ~FILE_NOTIFY_CHANGE_CREATION;
5245         }
5246
5247         if (null_timespec(ft->atime)) {
5248                 action &= ~FILE_NOTIFY_CHANGE_LAST_ACCESS;
5249         }
5250
5251         if (null_timespec(ft->mtime)) {
5252                 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
5253         }
5254
5255         if (!setting_write_time) {
5256                 /* ft->mtime comes from change time, not write time. */
5257                 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
5258         }
5259
5260         DEBUG(5,("smb_set_filetime: actime: %s\n ",
5261                 time_to_asc(convert_timespec_to_time_t(ft->atime))));
5262         DEBUG(5,("smb_set_filetime: modtime: %s\n ",
5263                 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
5264         DEBUG(5,("smb_set_filetime: ctime: %s\n ",
5265                 time_to_asc(convert_timespec_to_time_t(ft->ctime))));
5266         DEBUG(5,("smb_set_file_time: createtime: %s\n ",
5267                 time_to_asc(convert_timespec_to_time_t(ft->create_time))));
5268
5269         if (setting_write_time) {
5270                 /*
5271                  * This was a Windows setfileinfo on an open file.
5272                  * NT does this a lot. We also need to 
5273                  * set the time here, as it can be read by 
5274                  * FindFirst/FindNext and with the patch for bug #2045
5275                  * in smbd/fileio.c it ensures that this timestamp is
5276                  * kept sticky even after a write. We save the request
5277                  * away and will set it on file close and after a write. JRA.
5278                  */
5279
5280                 DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n",
5281                           time_to_asc(convert_timespec_to_time_t(ft->mtime))));
5282
5283                 if (fsp != NULL) {
5284                         if (fsp->base_fsp) {
5285                                 set_sticky_write_time_fsp(fsp->base_fsp,
5286                                                           ft->mtime);
5287                         } else {
5288                                 set_sticky_write_time_fsp(fsp, ft->mtime);
5289                         }
5290                 } else {
5291                         set_sticky_write_time_path(
5292                                 vfs_file_id_from_sbuf(conn, &smb_fname->st),
5293                                 ft->mtime);
5294                 }
5295         }
5296
5297         DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
5298
5299         /* Always call ntimes on the base, even if a stream was passed in. */
5300         status = create_synthetic_smb_fname(talloc_tos(), smb_fname->base_name,
5301                                             NULL, &smb_fname->st,
5302                                             &smb_fname_base);
5303         if (!NT_STATUS_IS_OK(status)) {
5304                 return status;
5305         }
5306
5307         if(file_ntimes(conn, smb_fname_base, ft)!=0) {
5308                 TALLOC_FREE(smb_fname_base);
5309                 return map_nt_error_from_unix(errno);
5310         }
5311         TALLOC_FREE(smb_fname_base);
5312
5313         notify_fname(conn, NOTIFY_ACTION_MODIFIED, action,
5314                      smb_fname->base_name);
5315         return NT_STATUS_OK;
5316 }
5317
5318 /****************************************************************************
5319  Deal with setting the dosmode from any of the setfilepathinfo functions.
5320 ****************************************************************************/
5321
5322 static NTSTATUS smb_set_file_dosmode(connection_struct *conn,
5323                                      const struct smb_filename *smb_fname,
5324                                      uint32 dosmode)
5325 {
5326         struct smb_filename *smb_fname_base = NULL;
5327         NTSTATUS status;
5328
5329         if (!VALID_STAT(smb_fname->st)) {
5330                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5331         }
5332
5333         /* Always operate on the base_name, even if a stream was passed in. */
5334         status = create_synthetic_smb_fname(talloc_tos(), smb_fname->base_name,
5335                                             NULL, &smb_fname->st,
5336                                             &smb_fname_base);
5337         if (!NT_STATUS_IS_OK(status)) {
5338                 return status;
5339         }
5340
5341         if (dosmode) {
5342                 if (S_ISDIR(smb_fname_base->st.st_ex_mode)) {
5343                         dosmode |= aDIR;
5344                 } else {
5345                         dosmode &= ~aDIR;
5346                 }
5347         }
5348
5349         DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode));
5350
5351         /* check the mode isn't different, before changing it */
5352         if ((dosmode != 0) && (dosmode != dos_mode(conn, smb_fname_base))) {
5353                 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode "
5354                           "0x%x\n", smb_fname_str_dbg(smb_fname_base),
5355                           (unsigned int)dosmode));
5356
5357                 if(file_set_dosmode(conn, smb_fname_base, dosmode, NULL,
5358                                     false)) {
5359                         DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of "
5360                                  "%s failed (%s)\n",
5361                                  smb_fname_str_dbg(smb_fname_base),
5362                                  strerror(errno)));
5363                         status = map_nt_error_from_unix(errno);
5364                         goto out;
5365                 }
5366         }
5367         status = NT_STATUS_OK;
5368  out:
5369         TALLOC_FREE(smb_fname_base);
5370         return status;
5371 }
5372
5373 /****************************************************************************
5374  Deal with setting the size from any of the setfilepathinfo functions.
5375 ****************************************************************************/
5376
5377 static NTSTATUS smb_set_file_size(connection_struct *conn,
5378                                   struct smb_request *req,
5379                                   files_struct *fsp,
5380                                   const struct smb_filename *smb_fname,
5381                                   const SMB_STRUCT_STAT *psbuf,
5382                                   SMB_OFF_T size)
5383 {
5384         NTSTATUS status = NT_STATUS_OK;
5385         struct smb_filename *smb_fname_tmp = NULL;
5386         files_struct *new_fsp = NULL;
5387
5388         if (!VALID_STAT(*psbuf)) {
5389                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5390         }
5391
5392         DEBUG(6,("smb_set_file_size: size: %.0f ", (double)size));
5393
5394         if (size == get_file_size_stat(psbuf)) {
5395                 return NT_STATUS_OK;
5396         }
5397
5398         DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
5399                   smb_fname_str_dbg(smb_fname), (double)size));
5400
5401         if (fsp && fsp->fh->fd != -1) {
5402                 /* Handle based call. */
5403                 if (vfs_set_filelen(fsp, size) == -1) {
5404                         return map_nt_error_from_unix(errno);
5405                 }
5406                 trigger_write_time_update_immediate(fsp);
5407                 return NT_STATUS_OK;
5408         }
5409
5410         status = copy_smb_filename(talloc_tos(), smb_fname, &smb_fname_tmp);
5411         if (!NT_STATUS_IS_OK(status)) {
5412                 return status;
5413         }
5414
5415         smb_fname_tmp->st = *psbuf;
5416
5417         status = SMB_VFS_CREATE_FILE(
5418                 conn,                                   /* conn */
5419                 req,                                    /* req */
5420                 0,                                      /* root_dir_fid */
5421                 smb_fname_tmp,                          /* fname */
5422                 FILE_WRITE_ATTRIBUTES,                  /* access_mask */
5423                 (FILE_SHARE_READ | FILE_SHARE_WRITE |   /* share_access */
5424                     FILE_SHARE_DELETE),
5425                 FILE_OPEN,                              /* create_disposition*/
5426                 0,                                      /* create_options */
5427                 FILE_ATTRIBUTE_NORMAL,                  /* file_attributes */
5428                 FORCE_OPLOCK_BREAK_TO_NONE,             /* oplock_request */
5429                 0,                                      /* allocation_size */
5430                 NULL,                                   /* sd */
5431                 NULL,                                   /* ea_list */
5432                 &new_fsp,                               /* result */
5433                 NULL);                                  /* pinfo */
5434
5435         TALLOC_FREE(smb_fname_tmp);
5436
5437         if (!NT_STATUS_IS_OK(status)) {
5438                 /* NB. We check for open_was_deferred in the caller. */
5439                 return status;
5440         }
5441
5442         if (vfs_set_filelen(new_fsp, size) == -1) {
5443                 status = map_nt_error_from_unix(errno);
5444                 close_file(req, new_fsp,NORMAL_CLOSE);
5445                 return status;
5446         }
5447
5448         trigger_write_time_update_immediate(new_fsp);
5449         close_file(req, new_fsp,NORMAL_CLOSE);
5450         return NT_STATUS_OK;
5451 }
5452
5453 /****************************************************************************
5454  Deal with SMB_INFO_SET_EA.
5455 ****************************************************************************/
5456
5457 static NTSTATUS smb_info_set_ea(connection_struct *conn,
5458                                 const char *pdata,
5459                                 int total_data,
5460                                 files_struct *fsp,
5461                                 const struct smb_filename *smb_fname)
5462 {
5463         struct ea_list *ea_list = NULL;
5464         TALLOC_CTX *ctx = NULL;
5465         NTSTATUS status = NT_STATUS_OK;
5466
5467         if (total_data < 10) {
5468
5469                 /* OS/2 workplace shell seems to send SET_EA requests of "null"
5470                    length. They seem to have no effect. Bug #3212. JRA */
5471
5472                 if ((total_data == 4) && (IVAL(pdata,0) == 4)) {
5473                         /* We're done. We only get EA info in this call. */
5474                         return NT_STATUS_OK;
5475                 }
5476
5477                 return NT_STATUS_INVALID_PARAMETER;
5478         }
5479
5480         if (IVAL(pdata,0) > total_data) {
5481                 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
5482                         IVAL(pdata,0), (unsigned int)total_data));
5483                 return NT_STATUS_INVALID_PARAMETER;
5484         }
5485
5486         ctx = talloc_tos();
5487         ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
5488         if (!ea_list) {
5489                 return NT_STATUS_INVALID_PARAMETER;
5490         }
5491         status = set_ea(conn, fsp, smb_fname, ea_list);
5492
5493         return status;
5494 }
5495
5496 /****************************************************************************
5497  Deal with SMB_SET_FILE_DISPOSITION_INFO.
5498 ****************************************************************************/
5499
5500 static NTSTATUS smb_set_file_disposition_info(connection_struct *conn,
5501                                 const char *pdata,
5502                                 int total_data,
5503                                 files_struct *fsp,
5504                                 const struct smb_filename *smb_fname)
5505 {
5506         NTSTATUS status = NT_STATUS_OK;
5507         bool delete_on_close;
5508         uint32 dosmode = 0;
5509
5510         if (total_data < 1) {
5511                 return NT_STATUS_INVALID_PARAMETER;
5512         }
5513
5514         if (fsp == NULL) {
5515                 return NT_STATUS_INVALID_HANDLE;
5516         }
5517
5518         delete_on_close = (CVAL(pdata,0) ? True : False);
5519         dosmode = dos_mode(conn, smb_fname);
5520
5521         DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
5522                 "delete_on_close = %u\n",
5523                 smb_fname_str_dbg(smb_fname),
5524                 (unsigned int)dosmode,
5525                 (unsigned int)delete_on_close ));
5526
5527         status = can_set_delete_on_close(fsp, delete_on_close, dosmode);
5528  
5529         if (!NT_STATUS_IS_OK(status)) {
5530                 return status;
5531         }
5532
5533         /* The set is across all open files on this dev/inode pair. */
5534         if (!set_delete_on_close(fsp, delete_on_close,
5535                                  &conn->server_info->utok)) {
5536                 return NT_STATUS_ACCESS_DENIED;
5537         }
5538         return NT_STATUS_OK;
5539 }
5540
5541 /****************************************************************************
5542  Deal with SMB_FILE_POSITION_INFORMATION.
5543 ****************************************************************************/
5544
5545 static NTSTATUS smb_file_position_information(connection_struct *conn,
5546                                 const char *pdata,
5547                                 int total_data,
5548                                 files_struct *fsp)
5549 {
5550         uint64_t position_information;
5551
5552         if (total_data < 8) {
5553                 return NT_STATUS_INVALID_PARAMETER;
5554         }
5555
5556         if (fsp == NULL) {
5557                 /* Ignore on pathname based set. */
5558                 return NT_STATUS_OK;
5559         }
5560
5561         position_information = (uint64_t)IVAL(pdata,0);
5562 #ifdef LARGE_SMB_OFF_T
5563         position_information |= (((uint64_t)IVAL(pdata,4)) << 32);
5564 #else /* LARGE_SMB_OFF_T */
5565         if (IVAL(pdata,4) != 0) {
5566                 /* more than 32 bits? */
5567                 return NT_STATUS_INVALID_PARAMETER;
5568         }
5569 #endif /* LARGE_SMB_OFF_T */
5570
5571         DEBUG(10,("smb_file_position_information: Set file position "
5572                   "information for file %s to %.0f\n", fsp_str_dbg(fsp),
5573                   (double)position_information));
5574         fsp->fh->position_information = position_information;
5575         return NT_STATUS_OK;
5576 }
5577
5578 /****************************************************************************
5579  Deal with SMB_FILE_MODE_INFORMATION.
5580 ****************************************************************************/
5581
5582 static NTSTATUS smb_file_mode_information(connection_struct *conn,
5583                                 const char *pdata,
5584                                 int total_data)
5585 {
5586         uint32 mode;
5587
5588         if (total_data < 4) {
5589                 return NT_STATUS_INVALID_PARAMETER;
5590         }
5591         mode = IVAL(pdata,0);
5592         if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
5593                 return NT_STATUS_INVALID_PARAMETER;
5594         }
5595         return NT_STATUS_OK;
5596 }
5597
5598 /****************************************************************************
5599  Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
5600 ****************************************************************************/
5601
5602 static NTSTATUS smb_set_file_unix_link(connection_struct *conn,
5603                                        struct smb_request *req,
5604                                        const char *pdata,
5605                                        int total_data,
5606                                        const struct smb_filename *smb_fname)
5607 {
5608         char *link_target = NULL;
5609         const char *newname = smb_fname->base_name;
5610         NTSTATUS status = NT_STATUS_OK;
5611         TALLOC_CTX *ctx = talloc_tos();
5612
5613         /* Set a symbolic link. */
5614         /* Don't allow this if follow links is false. */
5615
5616         if (total_data == 0) {
5617                 return NT_STATUS_INVALID_PARAMETER;
5618         }
5619
5620         if (!lp_symlinks(SNUM(conn))) {
5621                 return NT_STATUS_ACCESS_DENIED;
5622         }
5623
5624         srvstr_pull_talloc(ctx, pdata, req->flags2, &link_target, pdata,
5625                     total_data, STR_TERMINATE);
5626
5627         if (!link_target) {
5628                 return NT_STATUS_INVALID_PARAMETER;
5629         }
5630
5631         /* !widelinks forces the target path to be within the share. */
5632         /* This means we can interpret the target as a pathname. */
5633         if (!lp_widelinks(SNUM(conn))) {
5634                 char *rel_name = NULL;
5635                 char *last_dirp = NULL;
5636
5637                 if (*link_target == '/') {
5638                         /* No absolute paths allowed. */
5639                         return NT_STATUS_ACCESS_DENIED;
5640                 }
5641                 rel_name = talloc_strdup(ctx,newname);
5642                 if (!rel_name) {
5643                         return NT_STATUS_NO_MEMORY;
5644                 }
5645                 last_dirp = strrchr_m(rel_name, '/');
5646                 if (last_dirp) {
5647                         last_dirp[1] = '\0';
5648                 } else {
5649                         rel_name = talloc_strdup(ctx,"./");
5650                         if (!rel_name) {
5651                                 return NT_STATUS_NO_MEMORY;
5652                         }
5653                 }
5654                 rel_name = talloc_asprintf_append(rel_name,
5655                                 "%s",
5656                                 link_target);
5657                 if (!rel_name) {
5658                         return NT_STATUS_NO_MEMORY;
5659                 }
5660
5661                 status = check_name(conn, rel_name);
5662                 if (!NT_STATUS_IS_OK(status)) {
5663                         return status;
5664                 }
5665         }
5666
5667         DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
5668                         newname, link_target ));
5669
5670         if (SMB_VFS_SYMLINK(conn,link_target,newname) != 0) {
5671                 return map_nt_error_from_unix(errno);
5672         }
5673
5674         return NT_STATUS_OK;
5675 }
5676
5677 /****************************************************************************
5678  Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
5679 ****************************************************************************/
5680
5681 static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn,
5682                                         struct smb_request *req,
5683                                         const char *pdata, int total_data,
5684                                         const struct smb_filename *smb_fname_new)
5685 {
5686         char *oldname = NULL;
5687         struct smb_filename *smb_fname_old = NULL;
5688         TALLOC_CTX *ctx = talloc_tos();
5689         NTSTATUS status = NT_STATUS_OK;
5690
5691         /* Set a hard link. */
5692         if (total_data == 0) {
5693                 return NT_STATUS_INVALID_PARAMETER;
5694         }
5695
5696         srvstr_get_path(ctx, pdata, req->flags2, &oldname, pdata,
5697                         total_data, STR_TERMINATE, &status);
5698         if (!NT_STATUS_IS_OK(status)) {
5699                 return status;
5700         }
5701
5702         DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
5703                 smb_fname_str_dbg(smb_fname_new), oldname));
5704
5705         status = filename_convert(ctx,
5706                                 conn,
5707                                 req->flags2 & FLAGS2_DFS_PATHNAMES,
5708                                 oldname,
5709                                 0,
5710                                 NULL,
5711                                 &smb_fname_old);
5712         if (!NT_STATUS_IS_OK(status)) {
5713                 return status;
5714         }
5715
5716         return hardlink_internals(ctx, conn, smb_fname_old, smb_fname_new);
5717 }
5718
5719 /****************************************************************************
5720  Deal with SMB_FILE_RENAME_INFORMATION.
5721 ****************************************************************************/
5722
5723 static NTSTATUS smb_file_rename_information(connection_struct *conn,
5724                                             struct smb_request *req,
5725                                             const char *pdata,
5726                                             int total_data,
5727                                             files_struct *fsp,
5728                                             struct smb_filename *smb_fname_src)
5729 {
5730         bool overwrite;
5731         uint32 root_fid;
5732         uint32 len;
5733         char *newname = NULL;
5734         struct smb_filename *smb_fname_dst = NULL;
5735         bool dest_has_wcard = False;
5736         NTSTATUS status = NT_STATUS_OK;
5737         char *p;
5738         TALLOC_CTX *ctx = talloc_tos();
5739
5740         if (total_data < 13) {
5741                 return NT_STATUS_INVALID_PARAMETER;
5742         }
5743
5744         overwrite = (CVAL(pdata,0) ? True : False);
5745         root_fid = IVAL(pdata,4);
5746         len = IVAL(pdata,8);
5747
5748         if (len > (total_data - 12) || (len == 0) || (root_fid != 0)) {
5749                 return NT_STATUS_INVALID_PARAMETER;
5750         }
5751
5752         srvstr_get_path_wcard(ctx, pdata, req->flags2, &newname, &pdata[12],
5753                               len, 0, &status,
5754                               &dest_has_wcard);
5755         if (!NT_STATUS_IS_OK(status)) {
5756                 return status;
5757         }
5758
5759         DEBUG(10,("smb_file_rename_information: got name |%s|\n",
5760                                 newname));
5761
5762         status = resolve_dfspath_wcard(ctx, conn,
5763                                        req->flags2 & FLAGS2_DFS_PATHNAMES,
5764                                        newname,
5765                                        &newname,
5766                                        &dest_has_wcard);
5767         if (!NT_STATUS_IS_OK(status)) {
5768                 return status;
5769         }
5770
5771         /* Check the new name has no '/' characters. */
5772         if (strchr_m(newname, '/')) {
5773                 return NT_STATUS_NOT_SUPPORTED;
5774         }
5775
5776         if (fsp && fsp->base_fsp) {
5777                 /* newname must be a stream name. */
5778                 if (newname[0] != ':') {
5779                         return NT_STATUS_NOT_SUPPORTED;
5780                 }
5781
5782                 /* Create an smb_fname to call rename_internals_fsp() with. */
5783                 status = create_synthetic_smb_fname(talloc_tos(),
5784                     fsp->base_fsp->fsp_name->base_name, newname, NULL,
5785                     &smb_fname_dst);
5786                 if (!NT_STATUS_IS_OK(status)) {
5787                         goto out;
5788                 }
5789
5790                 /*
5791                  * Set the original last component, since
5792                  * rename_internals_fsp() requires it.
5793                  */
5794                 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
5795                                                               newname);
5796                 if (smb_fname_dst->original_lcomp == NULL) {
5797                         status = NT_STATUS_NO_MEMORY;
5798                         goto out;
5799                 }
5800
5801         } else {
5802                 /*
5803                  * Build up an smb_fname_dst based on the filename passed in.
5804                  * We basically just strip off the last component, and put on
5805                  * the newname instead.
5806                  */
5807                 char *base_name = NULL;
5808
5809                 /* newname must *not* be a stream name. */
5810                 if (newname[0] == ':') {
5811                         return NT_STATUS_NOT_SUPPORTED;
5812                 }
5813
5814                 /*
5815                  * Strip off the last component (filename) of the path passed
5816                  * in.
5817                  */
5818                 base_name = talloc_strdup(ctx, smb_fname_src->base_name);
5819                 if (!base_name) {
5820                         return NT_STATUS_NO_MEMORY;
5821                 }
5822                 p = strrchr_m(base_name, '/');
5823                 if (p) {
5824                         p[1] = '\0';
5825                 } else {
5826                         base_name = talloc_strdup(ctx, "./");
5827                         if (!base_name) {
5828                                 return NT_STATUS_NO_MEMORY;
5829                         }
5830                 }
5831                 /* Append the new name. */
5832                 base_name = talloc_asprintf_append(base_name,
5833                                 "%s",
5834                                 newname);
5835                 if (!base_name) {
5836                         return NT_STATUS_NO_MEMORY;
5837                 }
5838
5839                 status = unix_convert(ctx, conn, base_name, &smb_fname_dst,
5840                                       (UCF_SAVE_LCOMP |
5841                                           (dest_has_wcard ?
5842                                               UCF_ALWAYS_ALLOW_WCARD_LCOMP :
5843                                               0)));
5844
5845                 /* If an error we expect this to be
5846                  * NT_STATUS_OBJECT_PATH_NOT_FOUND */
5847
5848                 if (!NT_STATUS_IS_OK(status)) {
5849                         if(!NT_STATUS_EQUAL(NT_STATUS_OBJECT_PATH_NOT_FOUND,
5850                                             status)) {
5851                                 goto out;
5852                         }
5853                         /* Create an smb_fname to call rename_internals_fsp() */
5854                         status = create_synthetic_smb_fname(ctx,
5855                                                             base_name, NULL,
5856                                                             NULL,
5857                                                             &smb_fname_dst);
5858                         if (!NT_STATUS_IS_OK(status)) {
5859                                 goto out;
5860                         }
5861                 }
5862         }
5863
5864         if (fsp) {
5865                 DEBUG(10,("smb_file_rename_information: "
5866                           "SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
5867                           fsp->fnum, fsp_str_dbg(fsp),
5868                           smb_fname_str_dbg(smb_fname_dst)));
5869                 status = rename_internals_fsp(conn, fsp, smb_fname_dst, 0,
5870                                               overwrite);
5871         } else {
5872                 DEBUG(10,("smb_file_rename_information: "
5873                           "SMB_FILE_RENAME_INFORMATION %s -> %s\n",
5874                           smb_fname_str_dbg(smb_fname_src),
5875                           smb_fname_str_dbg(smb_fname_dst)));
5876                 status = rename_internals(ctx, conn, req, smb_fname_src,
5877                                           smb_fname_dst, 0, overwrite, false,
5878                                           dest_has_wcard,
5879                                           FILE_WRITE_ATTRIBUTES);
5880         }
5881  out:
5882         TALLOC_FREE(smb_fname_dst);
5883         return status;
5884 }
5885
5886 /****************************************************************************
5887  Deal with SMB_SET_POSIX_ACL.
5888 ****************************************************************************/
5889
5890 #if defined(HAVE_POSIX_ACLS)
5891 static NTSTATUS smb_set_posix_acl(connection_struct *conn,
5892                                 const char *pdata,
5893                                 int total_data,
5894                                 files_struct *fsp,
5895                                 const struct smb_filename *smb_fname)
5896 {
5897         uint16 posix_acl_version;
5898         uint16 num_file_acls;
5899         uint16 num_def_acls;
5900         bool valid_file_acls = True;
5901         bool valid_def_acls = True;
5902
5903         if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
5904                 return NT_STATUS_INVALID_PARAMETER;
5905         }
5906         posix_acl_version = SVAL(pdata,0);
5907         num_file_acls = SVAL(pdata,2);
5908         num_def_acls = SVAL(pdata,4);
5909
5910         if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
5911                 valid_file_acls = False;
5912                 num_file_acls = 0;
5913         }
5914
5915         if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
5916                 valid_def_acls = False;
5917                 num_def_acls = 0;
5918         }
5919
5920         if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
5921                 return NT_STATUS_INVALID_PARAMETER;
5922         }
5923
5924         if (total_data < SMB_POSIX_ACL_HEADER_SIZE +
5925                         (num_file_acls+num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE) {
5926                 return NT_STATUS_INVALID_PARAMETER;
5927         }
5928
5929         DEBUG(10,("smb_set_posix_acl: file %s num_file_acls = %u, num_def_acls = %u\n",
5930                 smb_fname ? smb_fname_str_dbg(smb_fname) : fsp_str_dbg(fsp),
5931                 (unsigned int)num_file_acls,
5932                 (unsigned int)num_def_acls));
5933
5934         if (valid_file_acls && !set_unix_posix_acl(conn, fsp,
5935                 smb_fname->base_name, num_file_acls,
5936                 pdata + SMB_POSIX_ACL_HEADER_SIZE)) {
5937                 return map_nt_error_from_unix(errno);
5938         }
5939
5940         if (valid_def_acls && !set_unix_posix_default_acl(conn,
5941                 smb_fname->base_name, &smb_fname->st, num_def_acls,
5942                 pdata + SMB_POSIX_ACL_HEADER_SIZE +
5943                 (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE))) {
5944                 return map_nt_error_from_unix(errno);
5945         }
5946         return NT_STATUS_OK;
5947 }
5948 #endif
5949
5950 /****************************************************************************
5951  Deal with SMB_SET_POSIX_LOCK.
5952 ****************************************************************************/
5953
5954 static NTSTATUS smb_set_posix_lock(connection_struct *conn,
5955                                 struct smb_request *req,
5956                                 const char *pdata,
5957                                 int total_data,
5958                                 files_struct *fsp)
5959 {
5960         uint64_t count;
5961         uint64_t offset;
5962         uint32 lock_pid;
5963         bool blocking_lock = False;
5964         enum brl_type lock_type;
5965
5966         NTSTATUS status = NT_STATUS_OK;
5967
5968         if (fsp == NULL || fsp->fh->fd == -1) {
5969                 return NT_STATUS_INVALID_HANDLE;
5970         }
5971
5972         if (total_data != POSIX_LOCK_DATA_SIZE) {
5973                 return NT_STATUS_INVALID_PARAMETER;
5974         }
5975
5976         switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
5977                 case POSIX_LOCK_TYPE_READ:
5978                         lock_type = READ_LOCK;
5979                         break;
5980                 case POSIX_LOCK_TYPE_WRITE:
5981                         /* Return the right POSIX-mappable error code for files opened read-only. */
5982                         if (!fsp->can_write) {
5983                                 return NT_STATUS_INVALID_HANDLE;
5984                         }
5985                         lock_type = WRITE_LOCK;
5986                         break;
5987                 case POSIX_LOCK_TYPE_UNLOCK:
5988                         lock_type = UNLOCK_LOCK;
5989                         break;
5990                 default:
5991                         return NT_STATUS_INVALID_PARAMETER;
5992         }
5993
5994         if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_NOWAIT) {
5995                 blocking_lock = False;
5996         } else if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_WAIT) {
5997                 blocking_lock = True;
5998         } else {
5999                 return NT_STATUS_INVALID_PARAMETER;
6000         }
6001
6002         if (!lp_blocking_locks(SNUM(conn))) { 
6003                 blocking_lock = False;
6004         }
6005
6006         lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
6007 #if defined(HAVE_LONGLONG)
6008         offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
6009                         ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
6010         count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
6011                         ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
6012 #else /* HAVE_LONGLONG */
6013         offset = (uint64_t)IVAL(pdata,POSIX_LOCK_START_OFFSET);
6014         count = (uint64_t)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
6015 #endif /* HAVE_LONGLONG */
6016
6017         DEBUG(10,("smb_set_posix_lock: file %s, lock_type = %u,"
6018                         "lock_pid = %u, count = %.0f, offset = %.0f\n",
6019                 fsp_str_dbg(fsp),
6020                 (unsigned int)lock_type,
6021                 (unsigned int)lock_pid,
6022                 (double)count,
6023                 (double)offset ));
6024
6025         if (lock_type == UNLOCK_LOCK) {
6026                 status = do_unlock(smbd_messaging_context(),
6027                                 fsp,
6028                                 lock_pid,
6029                                 count,
6030                                 offset,
6031                                 POSIX_LOCK);
6032         } else {
6033                 uint32 block_smbpid;
6034
6035                 struct byte_range_lock *br_lck = do_lock(smbd_messaging_context(),
6036                                                         fsp,
6037                                                         lock_pid,
6038                                                         count,
6039                                                         offset,
6040                                                         lock_type,
6041                                                         POSIX_LOCK,
6042                                                         blocking_lock,
6043                                                         &status,
6044                                                         &block_smbpid,
6045                                                         NULL);
6046
6047                 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
6048                         /*
6049                          * A blocking lock was requested. Package up
6050                          * this smb into a queued request and push it
6051                          * onto the blocking lock queue.
6052                          */
6053                         if(push_blocking_lock_request(br_lck,
6054                                                 req,
6055                                                 fsp,
6056                                                 -1, /* infinite timeout. */
6057                                                 0,
6058                                                 lock_pid,
6059                                                 lock_type,
6060                                                 POSIX_LOCK,
6061                                                 offset,
6062                                                 count,
6063                                                 block_smbpid)) {
6064                                 TALLOC_FREE(br_lck);
6065                                 return status;
6066                         }
6067                 }
6068                 TALLOC_FREE(br_lck);
6069         }
6070
6071         return status;
6072 }
6073
6074 /****************************************************************************
6075  Deal with SMB_SET_FILE_BASIC_INFO.
6076 ****************************************************************************/
6077
6078 static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
6079                                         const char *pdata,
6080                                         int total_data,
6081                                         files_struct *fsp,
6082                                         const struct smb_filename *smb_fname)
6083 {
6084         /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
6085         struct smb_file_time ft;
6086         uint32 dosmode = 0;
6087         NTSTATUS status = NT_STATUS_OK;
6088
6089         ZERO_STRUCT(ft);
6090
6091         if (total_data < 36) {
6092                 return NT_STATUS_INVALID_PARAMETER;
6093         }
6094
6095         /* Set the attributes */
6096         dosmode = IVAL(pdata,32);
6097         status = smb_set_file_dosmode(conn, smb_fname, dosmode);
6098         if (!NT_STATUS_IS_OK(status)) {
6099                 return status;
6100         }
6101
6102         /* create time */
6103         ft.create_time = interpret_long_date(pdata);
6104
6105         /* access time */
6106         ft.atime = interpret_long_date(pdata+8);
6107
6108         /* write time. */
6109         ft.mtime = interpret_long_date(pdata+16);
6110
6111         /* change time. */
6112         ft.ctime = interpret_long_date(pdata+24);
6113
6114         DEBUG(10, ("smb_set_file_basic_info: file %s\n",
6115                    smb_fname_str_dbg(smb_fname)));
6116
6117         return smb_set_file_time(conn, fsp, smb_fname, &ft,
6118                                  true);
6119 }
6120
6121 /****************************************************************************
6122  Deal with SMB_INFO_STANDARD.
6123 ****************************************************************************/
6124
6125 static NTSTATUS smb_set_info_standard(connection_struct *conn,
6126                                         const char *pdata,
6127                                         int total_data,
6128                                         files_struct *fsp,
6129                                         const struct smb_filename *smb_fname)
6130 {
6131         struct smb_file_time ft;
6132
6133         ZERO_STRUCT(ft);
6134
6135         if (total_data < 12) {
6136                 return NT_STATUS_INVALID_PARAMETER;
6137         }
6138
6139         /* create time */
6140         ft.create_time = convert_time_t_to_timespec(srv_make_unix_date2(pdata));
6141         /* access time */
6142         ft.atime = convert_time_t_to_timespec(srv_make_unix_date2(pdata+4));
6143         /* write time */
6144         ft.mtime = convert_time_t_to_timespec(srv_make_unix_date2(pdata+8));
6145
6146         DEBUG(10,("smb_set_info_standard: file %s\n",
6147                 smb_fname_str_dbg(smb_fname)));
6148
6149         return smb_set_file_time(conn,
6150                                 fsp,
6151                                 smb_fname,
6152                                 &ft,
6153                                 true);
6154 }
6155
6156 /****************************************************************************
6157  Deal with SMB_SET_FILE_ALLOCATION_INFO.
6158 ****************************************************************************/
6159
6160 static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
6161                                              struct smb_request *req,
6162                                         const char *pdata,
6163                                         int total_data,
6164                                         files_struct *fsp,
6165                                         struct smb_filename *smb_fname)
6166 {
6167         uint64_t allocation_size = 0;
6168         NTSTATUS status = NT_STATUS_OK;
6169         files_struct *new_fsp = NULL;
6170
6171         if (!VALID_STAT(smb_fname->st)) {
6172                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6173         }
6174
6175         if (total_data < 8) {
6176                 return NT_STATUS_INVALID_PARAMETER;
6177         }
6178
6179         allocation_size = (uint64_t)IVAL(pdata,0);
6180 #ifdef LARGE_SMB_OFF_T
6181         allocation_size |= (((uint64_t)IVAL(pdata,4)) << 32);
6182 #else /* LARGE_SMB_OFF_T */
6183         if (IVAL(pdata,4) != 0) {
6184                 /* more than 32 bits? */
6185                 return NT_STATUS_INVALID_PARAMETER;
6186         }
6187 #endif /* LARGE_SMB_OFF_T */
6188
6189         DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for "
6190                   "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
6191                   (double)allocation_size));
6192
6193         if (allocation_size) {
6194                 allocation_size = smb_roundup(conn, allocation_size);
6195         }
6196
6197         DEBUG(10,("smb_set_file_allocation_info: file %s : setting new "
6198                   "allocation size to %.0f\n", smb_fname_str_dbg(smb_fname),
6199                   (double)allocation_size));
6200
6201         if (fsp && fsp->fh->fd != -1) {
6202                 /* Open file handle. */
6203                 /* Only change if needed. */
6204                 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
6205                         if (vfs_allocate_file_space(fsp, allocation_size) == -1) {
6206                                 return map_nt_error_from_unix(errno);
6207                         }
6208                 }
6209                 /* But always update the time. */
6210                 /*
6211                  * This is equivalent to a write. Ensure it's seen immediately
6212                  * if there are no pending writes.
6213                  */
6214                 trigger_write_time_update_immediate(fsp);
6215                 return NT_STATUS_OK;
6216         }
6217
6218         /* Pathname or stat or directory file. */
6219         status = SMB_VFS_CREATE_FILE(
6220                 conn,                                   /* conn */
6221                 req,                                    /* req */
6222                 0,                                      /* root_dir_fid */
6223                 smb_fname,                              /* fname */
6224                 FILE_WRITE_DATA,                        /* access_mask */
6225                 (FILE_SHARE_READ | FILE_SHARE_WRITE |   /* share_access */
6226                     FILE_SHARE_DELETE),
6227                 FILE_OPEN,                              /* create_disposition*/
6228                 0,                                      /* create_options */
6229                 FILE_ATTRIBUTE_NORMAL,                  /* file_attributes */
6230                 FORCE_OPLOCK_BREAK_TO_NONE,             /* oplock_request */
6231                 0,                                      /* allocation_size */
6232                 NULL,                                   /* sd */
6233                 NULL,                                   /* ea_list */
6234                 &new_fsp,                               /* result */
6235                 NULL);                                  /* pinfo */
6236
6237         if (!NT_STATUS_IS_OK(status)) {
6238                 /* NB. We check for open_was_deferred in the caller. */
6239                 return status;
6240         }
6241
6242         /* Only change if needed. */
6243         if (allocation_size != get_file_size_stat(&smb_fname->st)) {
6244                 if (vfs_allocate_file_space(new_fsp, allocation_size) == -1) {
6245                         status = map_nt_error_from_unix(errno);
6246                         close_file(req, new_fsp, NORMAL_CLOSE);
6247                         return status;
6248                 }
6249         }
6250
6251         /* Changing the allocation size should set the last mod time. */
6252         /*
6253          * This is equivalent to a write. Ensure it's seen immediately
6254          * if there are no pending writes.
6255          */
6256         trigger_write_time_update_immediate(new_fsp);
6257
6258         close_file(req, new_fsp, NORMAL_CLOSE);
6259         return NT_STATUS_OK;
6260 }
6261
6262 /****************************************************************************
6263  Deal with SMB_SET_FILE_END_OF_FILE_INFO.
6264 ****************************************************************************/
6265
6266 static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn,
6267                                               struct smb_request *req,
6268                                         const char *pdata,
6269                                         int total_data,
6270                                         files_struct *fsp,
6271                                         const struct smb_filename *smb_fname)
6272 {
6273         SMB_OFF_T size;
6274
6275         if (total_data < 8) {
6276                 return NT_STATUS_INVALID_PARAMETER;
6277         }
6278
6279         size = IVAL(pdata,0);
6280 #ifdef LARGE_SMB_OFF_T
6281         size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
6282 #else /* LARGE_SMB_OFF_T */
6283         if (IVAL(pdata,4) != 0) {
6284                 /* more than 32 bits? */
6285                 return NT_STATUS_INVALID_PARAMETER;
6286         }
6287 #endif /* LARGE_SMB_OFF_T */
6288         DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
6289                   "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
6290                   (double)size));
6291
6292         return smb_set_file_size(conn, req,
6293                                 fsp,
6294                                 smb_fname,
6295                                 &smb_fname->st,
6296                                 size);
6297 }
6298
6299 /****************************************************************************
6300  Allow a UNIX info mknod.
6301 ****************************************************************************/
6302
6303 static NTSTATUS smb_unix_mknod(connection_struct *conn,
6304                                         const char *pdata,
6305                                         int total_data,
6306                                         const struct smb_filename *smb_fname)
6307 {
6308         uint32 file_type = IVAL(pdata,56);
6309 #if defined(HAVE_MAKEDEV)
6310         uint32 dev_major = IVAL(pdata,60);
6311         uint32 dev_minor = IVAL(pdata,68);
6312 #endif
6313         SMB_DEV_T dev = (SMB_DEV_T)0;
6314         uint32 raw_unixmode = IVAL(pdata,84);
6315         NTSTATUS status;
6316         mode_t unixmode;
6317
6318         if (total_data < 100) {
6319                 return NT_STATUS_INVALID_PARAMETER;
6320         }
6321
6322         status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
6323                                       PERM_NEW_FILE, &unixmode);
6324         if (!NT_STATUS_IS_OK(status)) {
6325                 return status;
6326         }
6327
6328 #if defined(HAVE_MAKEDEV)
6329         dev = makedev(dev_major, dev_minor);
6330 #endif
6331
6332         switch (file_type) {
6333 #if defined(S_IFIFO)
6334                 case UNIX_TYPE_FIFO:
6335                         unixmode |= S_IFIFO;
6336                         break;
6337 #endif
6338 #if defined(S_IFSOCK)
6339                 case UNIX_TYPE_SOCKET:
6340                         unixmode |= S_IFSOCK;
6341                         break;
6342 #endif
6343 #if defined(S_IFCHR)
6344                 case UNIX_TYPE_CHARDEV:
6345                         unixmode |= S_IFCHR;
6346                         break;
6347 #endif
6348 #if defined(S_IFBLK)
6349                 case UNIX_TYPE_BLKDEV:
6350                         unixmode |= S_IFBLK;
6351                         break;
6352 #endif
6353                 default:
6354                         return NT_STATUS_INVALID_PARAMETER;
6355         }
6356
6357         DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev "
6358                   "%.0f mode 0%o for file %s\n", (double)dev,
6359                   (unsigned int)unixmode, smb_fname_str_dbg(smb_fname)));
6360
6361         /* Ok - do the mknod. */
6362         if (SMB_VFS_MKNOD(conn, smb_fname->base_name, unixmode, dev) != 0) {
6363                 return map_nt_error_from_unix(errno);
6364         }
6365
6366         /* If any of the other "set" calls fail we
6367          * don't want to end up with a half-constructed mknod.
6368          */
6369
6370         if (lp_inherit_perms(SNUM(conn))) {
6371                 char *parent;
6372                 if (!parent_dirname(talloc_tos(), smb_fname->base_name,
6373                                     &parent, NULL)) {
6374                         return NT_STATUS_NO_MEMORY;
6375                 }
6376                 inherit_access_posix_acl(conn, parent, smb_fname->base_name,
6377                                          unixmode);
6378                 TALLOC_FREE(parent);
6379         }
6380
6381         return NT_STATUS_OK;
6382 }
6383
6384 /****************************************************************************
6385  Deal with SMB_SET_FILE_UNIX_BASIC.
6386 ****************************************************************************/
6387
6388 static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
6389                                         struct smb_request *req,
6390                                         const char *pdata,
6391                                         int total_data,
6392                                         files_struct *fsp,
6393                                         const struct smb_filename *smb_fname)
6394 {
6395         struct smb_file_time ft;
6396         uint32 raw_unixmode;
6397         mode_t unixmode;
6398         SMB_OFF_T size = 0;
6399         uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
6400         gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
6401         NTSTATUS status = NT_STATUS_OK;
6402         bool delete_on_fail = False;
6403         enum perm_type ptype;
6404         files_struct *all_fsps = NULL;
6405         bool modify_mtime = true;
6406         struct file_id id;
6407         SMB_STRUCT_STAT sbuf;
6408
6409         ZERO_STRUCT(ft);
6410
6411         if (total_data < 100) {
6412                 return NT_STATUS_INVALID_PARAMETER;
6413         }
6414
6415         if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
6416            IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
6417                 size=IVAL(pdata,0); /* first 8 Bytes are size */
6418 #ifdef LARGE_SMB_OFF_T
6419                 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
6420 #else /* LARGE_SMB_OFF_T */
6421                 if (IVAL(pdata,4) != 0) {
6422                         /* more than 32 bits? */
6423                         return NT_STATUS_INVALID_PARAMETER;
6424                 }
6425 #endif /* LARGE_SMB_OFF_T */
6426         }
6427
6428         ft.atime = interpret_long_date(pdata+24); /* access_time */
6429         ft.mtime = interpret_long_date(pdata+32); /* modification_time */
6430         set_owner = (uid_t)IVAL(pdata,40);
6431         set_grp = (gid_t)IVAL(pdata,48);
6432         raw_unixmode = IVAL(pdata,84);
6433
6434         if (VALID_STAT(smb_fname->st)) {
6435                 if (S_ISDIR(smb_fname->st.st_ex_mode)) {
6436                         ptype = PERM_EXISTING_DIR;
6437                 } else {
6438                         ptype = PERM_EXISTING_FILE;
6439                 }
6440         } else {
6441                 ptype = PERM_NEW_FILE;
6442         }
6443
6444         status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
6445                                       ptype, &unixmode);
6446         if (!NT_STATUS_IS_OK(status)) {
6447                 return status;
6448         }
6449
6450         DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = "
6451                   "%s size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
6452                   smb_fname_str_dbg(smb_fname), (double)size,
6453                   (unsigned int)set_owner, (unsigned int)set_grp,
6454                   (int)raw_unixmode));
6455
6456         sbuf = smb_fname->st;
6457
6458         if (!VALID_STAT(sbuf)) {
6459                 struct smb_filename *smb_fname_tmp = NULL;
6460                 /*
6461                  * The only valid use of this is to create character and block
6462                  * devices, and named pipes. This is deprecated (IMHO) and 
6463                  * a new info level should be used for mknod. JRA.
6464                  */
6465
6466                 status = smb_unix_mknod(conn,
6467                                         pdata,
6468                                         total_data,
6469                                         smb_fname);
6470                 if (!NT_STATUS_IS_OK(status)) {
6471                         return status;
6472                 }
6473
6474                 status = copy_smb_filename(talloc_tos(), smb_fname,
6475                                            &smb_fname_tmp);
6476                 if (!NT_STATUS_IS_OK(status)) {
6477                         return status;
6478                 }
6479
6480                 if (SMB_VFS_STAT(conn, smb_fname_tmp) != 0) {
6481                         status = map_nt_error_from_unix(errno);
6482                         TALLOC_FREE(smb_fname_tmp);
6483                         SMB_VFS_UNLINK(conn, smb_fname);
6484                         return status;
6485                 }
6486
6487                 sbuf = smb_fname_tmp->st;
6488                 TALLOC_FREE(smb_fname_tmp);
6489
6490                 /* Ensure we don't try and change anything else. */
6491                 raw_unixmode = SMB_MODE_NO_CHANGE;
6492                 size = get_file_size_stat(&sbuf);
6493                 ft.atime = sbuf.st_ex_atime;
6494                 ft.mtime = sbuf.st_ex_mtime;
6495                 /* 
6496                  * We continue here as we might want to change the 
6497                  * owner uid/gid.
6498                  */
6499                 delete_on_fail = True;
6500         }
6501
6502 #if 1
6503         /* Horrible backwards compatibility hack as an old server bug
6504          * allowed a CIFS client bug to remain unnoticed :-(. JRA.
6505          * */
6506
6507         if (!size) {
6508                 size = get_file_size_stat(&sbuf);
6509         }
6510 #endif
6511
6512         /*
6513          * Deal with the UNIX specific mode set.
6514          */
6515
6516         if (raw_unixmode != SMB_MODE_NO_CHANGE) {
6517                 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
6518                           "setting mode 0%o for file %s\n",
6519                           (unsigned int)unixmode,
6520                           smb_fname_str_dbg(smb_fname)));
6521                 if (SMB_VFS_CHMOD(conn, smb_fname->base_name, unixmode) != 0) {
6522                         return map_nt_error_from_unix(errno);
6523                 }
6524         }
6525
6526         /*
6527          * Deal with the UNIX specific uid set.
6528          */
6529
6530         if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) &&
6531             (sbuf.st_ex_uid != set_owner)) {
6532                 int ret;
6533
6534                 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
6535                           "changing owner %u for path %s\n",
6536                           (unsigned int)set_owner,
6537                           smb_fname_str_dbg(smb_fname)));
6538
6539                 if (S_ISLNK(sbuf.st_ex_mode)) {
6540                         ret = SMB_VFS_LCHOWN(conn, smb_fname->base_name,
6541                                              set_owner, (gid_t)-1);
6542                 } else {
6543                         ret = SMB_VFS_CHOWN(conn, smb_fname->base_name,
6544                                             set_owner, (gid_t)-1);
6545                 }
6546
6547                 if (ret != 0) {
6548                         status = map_nt_error_from_unix(errno);
6549                         if (delete_on_fail) {
6550                                 SMB_VFS_UNLINK(conn, smb_fname);
6551                         }
6552                         return status;
6553                 }
6554         }
6555
6556         /*
6557          * Deal with the UNIX specific gid set.
6558          */
6559
6560         if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) &&
6561             (sbuf.st_ex_gid != set_grp)) {
6562                 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
6563                           "changing group %u for file %s\n",
6564                           (unsigned int)set_owner,
6565                           smb_fname_str_dbg(smb_fname)));
6566                 if (SMB_VFS_CHOWN(conn, smb_fname->base_name, (uid_t)-1,
6567                                   set_grp) != 0) {
6568                         status = map_nt_error_from_unix(errno);
6569                         if (delete_on_fail) {
6570                                 SMB_VFS_UNLINK(conn, smb_fname);
6571                         }
6572                         return status;
6573                 }
6574         }
6575
6576         /* Deal with any size changes. */
6577
6578         status = smb_set_file_size(conn, req,
6579                                    fsp,
6580                                    smb_fname,
6581                                    &sbuf,
6582                                    size);
6583         if (!NT_STATUS_IS_OK(status)) {
6584                 return status;
6585         }
6586
6587         /* Deal with any time changes. */
6588         if (null_timespec(ft.mtime) && null_timespec(ft.atime)) {
6589                 /* No change, don't cancel anything. */
6590                 return status;
6591         }
6592
6593         id = vfs_file_id_from_sbuf(conn, &sbuf);
6594         for(all_fsps = file_find_di_first(id); all_fsps;
6595                         all_fsps = file_find_di_next(all_fsps)) {
6596                 /*
6597                  * We're setting the time explicitly for UNIX.
6598                  * Cancel any pending changes over all handles.
6599                  */
6600                 all_fsps->update_write_time_on_close = false;
6601                 TALLOC_FREE(all_fsps->update_write_time_event);
6602         }
6603
6604         /*
6605          * Override the "setting_write_time"
6606          * parameter here as it almost does what
6607          * we need. Just remember if we modified
6608          * mtime and send the notify ourselves.
6609          */
6610         if (null_timespec(ft.mtime)) {
6611                 modify_mtime = false;
6612         }
6613
6614         status = smb_set_file_time(conn,
6615                                 fsp,
6616                                 smb_fname,
6617                                 &ft,
6618                                 false);
6619         if (modify_mtime) {
6620                 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
6621                         FILE_NOTIFY_CHANGE_LAST_WRITE, smb_fname->base_name);
6622         }
6623         return status;
6624 }
6625
6626 /****************************************************************************
6627  Deal with SMB_SET_FILE_UNIX_INFO2.
6628 ****************************************************************************/
6629
6630 static NTSTATUS smb_set_file_unix_info2(connection_struct *conn,
6631                                         struct smb_request *req,
6632                                         const char *pdata,
6633                                         int total_data,
6634                                         files_struct *fsp,
6635                                         const struct smb_filename *smb_fname)
6636 {
6637         NTSTATUS status;
6638         uint32 smb_fflags;
6639         uint32 smb_fmask;
6640
6641         if (total_data < 116) {
6642                 return NT_STATUS_INVALID_PARAMETER;
6643         }
6644
6645         /* Start by setting all the fields that are common between UNIX_BASIC
6646          * and UNIX_INFO2.
6647          */
6648         status = smb_set_file_unix_basic(conn, req, pdata, total_data,
6649                                          fsp, smb_fname);
6650         if (!NT_STATUS_IS_OK(status)) {
6651                 return status;
6652         }
6653
6654         smb_fflags = IVAL(pdata, 108);
6655         smb_fmask = IVAL(pdata, 112);
6656
6657         /* NB: We should only attempt to alter the file flags if the client
6658          * sends a non-zero mask.
6659          */
6660         if (smb_fmask != 0) {
6661                 int stat_fflags = 0;
6662
6663                 if (!map_info2_flags_to_sbuf(&smb_fname->st, smb_fflags,
6664                                              smb_fmask, &stat_fflags)) {
6665                         /* Client asked to alter a flag we don't understand. */
6666                         return NT_STATUS_INVALID_PARAMETER;
6667                 }
6668
6669                 if (fsp && fsp->fh->fd != -1) {
6670                         /* XXX: we should be  using SMB_VFS_FCHFLAGS here. */
6671                         return NT_STATUS_NOT_SUPPORTED;
6672                 } else {
6673                         if (SMB_VFS_CHFLAGS(conn, smb_fname->base_name,
6674                                             stat_fflags) != 0) {
6675                                 return map_nt_error_from_unix(errno);
6676                         }
6677                 }
6678         }
6679
6680         /* XXX: need to add support for changing the create_time here. You
6681          * can do this for paths on Darwin with setattrlist(2). The right way
6682          * to hook this up is probably by extending the VFS utimes interface.
6683          */
6684
6685         return NT_STATUS_OK;
6686 }
6687
6688 /****************************************************************************
6689  Create a directory with POSIX semantics.
6690 ****************************************************************************/
6691
6692 static NTSTATUS smb_posix_mkdir(connection_struct *conn,
6693                                 struct smb_request *req,
6694                                 char **ppdata,
6695                                 int total_data,
6696                                 struct smb_filename *smb_fname,
6697                                 int *pdata_return_size)
6698 {
6699         NTSTATUS status = NT_STATUS_OK;
6700         uint32 raw_unixmode = 0;
6701         uint32 mod_unixmode = 0;
6702         mode_t unixmode = (mode_t)0;
6703         files_struct *fsp = NULL;
6704         uint16 info_level_return = 0;
6705         int info;
6706         char *pdata = *ppdata;
6707
6708         if (total_data < 18) {
6709                 return NT_STATUS_INVALID_PARAMETER;
6710         }
6711
6712         raw_unixmode = IVAL(pdata,8);
6713         /* Next 4 bytes are not yet defined. */
6714
6715         status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
6716                                       PERM_NEW_DIR, &unixmode);
6717         if (!NT_STATUS_IS_OK(status)) {
6718                 return status;
6719         }
6720
6721         mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
6722
6723         DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
6724                   smb_fname_str_dbg(smb_fname), (unsigned int)unixmode));
6725
6726         status = SMB_VFS_CREATE_FILE(
6727                 conn,                                   /* conn */
6728                 req,                                    /* req */
6729                 0,                                      /* root_dir_fid */
6730                 smb_fname,                              /* fname */
6731                 FILE_READ_ATTRIBUTES,                   /* access_mask */
6732                 FILE_SHARE_NONE,                        /* share_access */
6733                 FILE_CREATE,                            /* create_disposition*/
6734                 FILE_DIRECTORY_FILE,                    /* create_options */
6735                 mod_unixmode,                           /* file_attributes */
6736                 0,                                      /* oplock_request */
6737                 0,                                      /* allocation_size */
6738                 NULL,                                   /* sd */
6739                 NULL,                                   /* ea_list */
6740                 &fsp,                                   /* result */
6741                 &info);                                 /* pinfo */
6742
6743         if (NT_STATUS_IS_OK(status)) {
6744                 close_file(req, fsp, NORMAL_CLOSE);
6745         }
6746
6747         info_level_return = SVAL(pdata,16);
6748  
6749         if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
6750                 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
6751         } else if (info_level_return ==  SMB_QUERY_FILE_UNIX_INFO2) {
6752                 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
6753         } else {
6754                 *pdata_return_size = 12;
6755         }
6756
6757         /* Realloc the data size */
6758         *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
6759         if (*ppdata == NULL) {
6760                 *pdata_return_size = 0;
6761                 return NT_STATUS_NO_MEMORY;
6762         }
6763         pdata = *ppdata;
6764
6765         SSVAL(pdata,0,NO_OPLOCK_RETURN);
6766         SSVAL(pdata,2,0); /* No fnum. */
6767         SIVAL(pdata,4,info); /* Was directory created. */
6768
6769         switch (info_level_return) {
6770                 case SMB_QUERY_FILE_UNIX_BASIC:
6771                         SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
6772                         SSVAL(pdata,10,0); /* Padding. */
6773                         store_file_unix_basic(conn, pdata + 12, fsp,
6774                                               &smb_fname->st);
6775                         break;
6776                 case SMB_QUERY_FILE_UNIX_INFO2:
6777                         SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
6778                         SSVAL(pdata,10,0); /* Padding. */
6779                         store_file_unix_basic_info2(conn, pdata + 12, fsp,
6780                                                     &smb_fname->st);
6781                         break;
6782                 default:
6783                         SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
6784                         SSVAL(pdata,10,0); /* Padding. */
6785                         break;
6786         }
6787
6788         return status;
6789 }
6790
6791 /****************************************************************************
6792  Open/Create a file with POSIX semantics.
6793 ****************************************************************************/
6794
6795 static NTSTATUS smb_posix_open(connection_struct *conn,
6796                                struct smb_request *req,
6797                                 char **ppdata,
6798                                 int total_data,
6799                                 struct smb_filename *smb_fname,
6800                                 int *pdata_return_size)
6801 {
6802         bool extended_oplock_granted = False;
6803         char *pdata = *ppdata;
6804         uint32 flags = 0;
6805         uint32 wire_open_mode = 0;
6806         uint32 raw_unixmode = 0;
6807         uint32 mod_unixmode = 0;
6808         uint32 create_disp = 0;
6809         uint32 access_mask = 0;
6810         uint32 create_options = 0;
6811         NTSTATUS status = NT_STATUS_OK;
6812         mode_t unixmode = (mode_t)0;
6813         files_struct *fsp = NULL;
6814         int oplock_request = 0;
6815         int info = 0;
6816         uint16 info_level_return = 0;
6817
6818         if (total_data < 18) {
6819                 return NT_STATUS_INVALID_PARAMETER;
6820         }
6821
6822         flags = IVAL(pdata,0);
6823         oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
6824         if (oplock_request) {
6825                 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
6826         }
6827
6828         wire_open_mode = IVAL(pdata,4);
6829
6830         if (wire_open_mode == (SMB_O_CREAT|SMB_O_DIRECTORY)) {
6831                 return smb_posix_mkdir(conn, req,
6832                                         ppdata,
6833                                         total_data,
6834                                         smb_fname,
6835                                         pdata_return_size);
6836         }
6837
6838         switch (wire_open_mode & SMB_ACCMODE) {
6839                 case SMB_O_RDONLY:
6840                         access_mask = FILE_READ_DATA;
6841                         break;
6842                 case SMB_O_WRONLY:
6843                         access_mask = FILE_WRITE_DATA;
6844                         break;
6845                 case SMB_O_RDWR:
6846                         access_mask = FILE_READ_DATA|FILE_WRITE_DATA;
6847                         break;
6848                 default:
6849                         DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
6850                                 (unsigned int)wire_open_mode ));
6851                         return NT_STATUS_INVALID_PARAMETER;
6852         }
6853
6854         wire_open_mode &= ~SMB_ACCMODE;
6855
6856         if((wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL)) == (SMB_O_CREAT | SMB_O_EXCL)) {
6857                 create_disp = FILE_CREATE;
6858         } else if((wire_open_mode & (SMB_O_CREAT | SMB_O_TRUNC)) == (SMB_O_CREAT | SMB_O_TRUNC)) {
6859                 create_disp = FILE_OVERWRITE_IF;
6860         } else if((wire_open_mode & SMB_O_CREAT) == SMB_O_CREAT) {
6861                 create_disp = FILE_OPEN_IF;
6862         } else if ((wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL | SMB_O_TRUNC)) == 0) {
6863                 create_disp = FILE_OPEN;
6864         } else {
6865                 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
6866                         (unsigned int)wire_open_mode ));
6867                 return NT_STATUS_INVALID_PARAMETER;
6868         }
6869
6870         raw_unixmode = IVAL(pdata,8);
6871         /* Next 4 bytes are not yet defined. */
6872
6873         status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
6874                                       (VALID_STAT(smb_fname->st) ?
6875                                           PERM_EXISTING_FILE : PERM_NEW_FILE),
6876                                       &unixmode);
6877
6878         if (!NT_STATUS_IS_OK(status)) {
6879                 return status;
6880         }
6881
6882         mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
6883
6884         if (wire_open_mode & SMB_O_SYNC) {
6885                 create_options |= FILE_WRITE_THROUGH;
6886         }
6887         if (wire_open_mode & SMB_O_APPEND) {
6888                 access_mask |= FILE_APPEND_DATA;
6889         }
6890         if (wire_open_mode & SMB_O_DIRECT) {
6891                 mod_unixmode |= FILE_FLAG_NO_BUFFERING;
6892         }
6893
6894         DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
6895                 smb_fname_str_dbg(smb_fname),
6896                 (unsigned int)wire_open_mode,
6897                 (unsigned int)unixmode ));
6898
6899         status = SMB_VFS_CREATE_FILE(
6900                 conn,                                   /* conn */
6901                 req,                                    /* req */
6902                 0,                                      /* root_dir_fid */
6903                 smb_fname,                              /* fname */
6904                 access_mask,                            /* access_mask */
6905                 (FILE_SHARE_READ | FILE_SHARE_WRITE |   /* share_access */
6906                     FILE_SHARE_DELETE),
6907                 create_disp,                            /* create_disposition*/
6908                 FILE_NON_DIRECTORY_FILE,                /* create_options */
6909                 mod_unixmode,                           /* file_attributes */
6910                 oplock_request,                         /* oplock_request */
6911                 0,                                      /* allocation_size */
6912                 NULL,                                   /* sd */
6913                 NULL,                                   /* ea_list */
6914                 &fsp,                                   /* result */
6915                 &info);                                 /* pinfo */
6916
6917         if (!NT_STATUS_IS_OK(status)) {
6918                 return status;
6919         }
6920
6921         if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
6922                 extended_oplock_granted = True;
6923         }
6924
6925         if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
6926                 extended_oplock_granted = True;
6927         }
6928
6929         info_level_return = SVAL(pdata,16);
6930  
6931         /* Allocate the correct return size. */
6932
6933         if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
6934                 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
6935         } else if (info_level_return ==  SMB_QUERY_FILE_UNIX_INFO2) {
6936                 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
6937         } else {
6938                 *pdata_return_size = 12;
6939         }
6940
6941         /* Realloc the data size */
6942         *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
6943         if (*ppdata == NULL) {
6944                 close_file(req, fsp, ERROR_CLOSE);
6945                 *pdata_return_size = 0;
6946                 return NT_STATUS_NO_MEMORY;
6947         }
6948         pdata = *ppdata;
6949
6950         if (extended_oplock_granted) {
6951                 if (flags & REQUEST_BATCH_OPLOCK) {
6952                         SSVAL(pdata,0, BATCH_OPLOCK_RETURN);
6953                 } else {
6954                         SSVAL(pdata,0, EXCLUSIVE_OPLOCK_RETURN);
6955                 }
6956         } else if (fsp->oplock_type == LEVEL_II_OPLOCK) {
6957                 SSVAL(pdata,0, LEVEL_II_OPLOCK_RETURN);
6958         } else {
6959                 SSVAL(pdata,0,NO_OPLOCK_RETURN);
6960         }
6961
6962         SSVAL(pdata,2,fsp->fnum);
6963         SIVAL(pdata,4,info); /* Was file created etc. */
6964
6965         switch (info_level_return) {
6966                 case SMB_QUERY_FILE_UNIX_BASIC:
6967                         SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
6968                         SSVAL(pdata,10,0); /* padding. */
6969                         store_file_unix_basic(conn, pdata + 12, fsp,
6970                                               &smb_fname->st);
6971                         break;
6972                 case SMB_QUERY_FILE_UNIX_INFO2:
6973                         SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
6974                         SSVAL(pdata,10,0); /* padding. */
6975                         store_file_unix_basic_info2(conn, pdata + 12, fsp,
6976                                                     &smb_fname->st);
6977                         break;
6978                 default:
6979                         SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
6980                         SSVAL(pdata,10,0); /* padding. */
6981                         break;
6982         }
6983         return NT_STATUS_OK;
6984 }
6985
6986 /****************************************************************************
6987  Delete a file with POSIX semantics.
6988 ****************************************************************************/
6989
6990 static NTSTATUS smb_posix_unlink(connection_struct *conn,
6991                                  struct smb_request *req,
6992                                 const char *pdata,
6993                                 int total_data,
6994                                 struct smb_filename *smb_fname)
6995 {
6996         NTSTATUS status = NT_STATUS_OK;
6997         files_struct *fsp = NULL;
6998         uint16 flags = 0;
6999         char del = 1;
7000         int info = 0;
7001         int create_options = 0;
7002         int i;
7003         struct share_mode_lock *lck = NULL;
7004
7005         if (total_data < 2) {
7006                 return NT_STATUS_INVALID_PARAMETER;
7007         }
7008
7009         flags = SVAL(pdata,0);
7010
7011         if (!VALID_STAT(smb_fname->st)) {
7012                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
7013         }
7014
7015         if ((flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) &&
7016                         !VALID_STAT_OF_DIR(smb_fname->st)) {
7017                 return NT_STATUS_NOT_A_DIRECTORY;
7018         }
7019
7020         DEBUG(10,("smb_posix_unlink: %s %s\n",
7021                 (flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) ? "directory" : "file",
7022                 smb_fname_str_dbg(smb_fname)));
7023
7024         if (VALID_STAT_OF_DIR(smb_fname->st)) {
7025                 create_options |= FILE_DIRECTORY_FILE;
7026         }
7027
7028         status = SMB_VFS_CREATE_FILE(
7029                 conn,                                   /* conn */
7030                 req,                                    /* req */
7031                 0,                                      /* root_dir_fid */
7032                 smb_fname,                              /* fname */
7033                 DELETE_ACCESS,                          /* access_mask */
7034                 (FILE_SHARE_READ | FILE_SHARE_WRITE |   /* share_access */
7035                     FILE_SHARE_DELETE),
7036                 FILE_OPEN,                              /* create_disposition*/
7037                 create_options,                         /* create_options */
7038                 FILE_FLAG_POSIX_SEMANTICS|0777,         /* file_attributes */
7039                 0,                                      /* oplock_request */
7040                 0,                                      /* allocation_size */
7041                 NULL,                                   /* sd */
7042                 NULL,                                   /* ea_list */
7043                 &fsp,                                   /* result */
7044                 &info);                                 /* pinfo */
7045
7046         if (!NT_STATUS_IS_OK(status)) {
7047                 return status;
7048         }
7049
7050         /*
7051          * Don't lie to client. If we can't really delete due to
7052          * non-POSIX opens return SHARING_VIOLATION.
7053          */
7054
7055         lck = get_share_mode_lock(talloc_tos(), fsp->file_id, NULL, NULL,
7056                                   NULL);
7057         if (lck == NULL) {
7058                 DEBUG(0, ("smb_posix_unlink: Could not get share mode "
7059                           "lock for file %s\n", fsp_str_dbg(fsp)));
7060                 close_file(req, fsp, NORMAL_CLOSE);
7061                 return NT_STATUS_INVALID_PARAMETER;
7062         }
7063
7064         /*
7065          * See if others still have the file open. If this is the case, then
7066          * don't delete. If all opens are POSIX delete we can set the delete
7067          * on close disposition.
7068          */
7069         for (i=0; i<lck->num_share_modes; i++) {
7070                 struct share_mode_entry *e = &lck->share_modes[i];
7071                 if (is_valid_share_mode_entry(e)) {
7072                         if (e->flags & SHARE_MODE_FLAG_POSIX_OPEN) {
7073                                 continue;
7074                         }
7075                         /* Fail with sharing violation. */
7076                         close_file(req, fsp, NORMAL_CLOSE);
7077                         TALLOC_FREE(lck);
7078                         return NT_STATUS_SHARING_VIOLATION;
7079                 }
7080         }
7081
7082         /*
7083          * Set the delete on close.
7084          */
7085         status = smb_set_file_disposition_info(conn,
7086                                                 &del,
7087                                                 1,
7088                                                 fsp,
7089                                                 smb_fname);
7090
7091         if (!NT_STATUS_IS_OK(status)) {
7092                 close_file(req, fsp, NORMAL_CLOSE);
7093                 TALLOC_FREE(lck);
7094                 return status;
7095         }
7096         TALLOC_FREE(lck);
7097         return close_file(req, fsp, NORMAL_CLOSE);
7098 }
7099
7100 NTSTATUS smbd_do_setfilepathinfo(connection_struct *conn,
7101                                 struct smb_request *req,
7102                                 TALLOC_CTX *mem_ctx,
7103                                 uint16_t info_level,
7104                                 files_struct *fsp,
7105                                 struct smb_filename *smb_fname,
7106                                 char **ppdata, int total_data,
7107                                 int *ret_data_size)
7108 {
7109         char *pdata = *ppdata;
7110         NTSTATUS status = NT_STATUS_OK;
7111         int data_return_size = 0;
7112
7113         *ret_data_size = 0;
7114
7115         if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
7116                 return NT_STATUS_INVALID_LEVEL;
7117         }
7118
7119         if (!CAN_WRITE(conn)) {
7120                 /* Allow POSIX opens. The open path will deny
7121                  * any non-readonly opens. */
7122                 if (info_level != SMB_POSIX_PATH_OPEN) {
7123                         return NT_STATUS_DOS(ERRSRV, ERRaccess);
7124                 }
7125         }
7126
7127         DEBUG(3,("smbd_do_setfilepathinfo: %s (fnum %d) info_level=%d "
7128                  "totdata=%d\n", smb_fname_str_dbg(smb_fname),
7129                  fsp ? fsp->fnum : -1, info_level, total_data));
7130
7131         switch (info_level) {
7132
7133                 case SMB_INFO_STANDARD:
7134                 {
7135                         status = smb_set_info_standard(conn,
7136                                         pdata,
7137                                         total_data,
7138                                         fsp,
7139                                         smb_fname);
7140                         break;
7141                 }
7142
7143                 case SMB_INFO_SET_EA:
7144                 {
7145                         status = smb_info_set_ea(conn,
7146                                                 pdata,
7147                                                 total_data,
7148                                                 fsp,
7149                                                 smb_fname);
7150                         break;
7151                 }
7152
7153                 case SMB_SET_FILE_BASIC_INFO:
7154                 case SMB_FILE_BASIC_INFORMATION:
7155                 {
7156                         status = smb_set_file_basic_info(conn,
7157                                                         pdata,
7158                                                         total_data,
7159                                                         fsp,
7160                                                         smb_fname);
7161                         break;
7162                 }
7163
7164                 case SMB_FILE_ALLOCATION_INFORMATION:
7165                 case SMB_SET_FILE_ALLOCATION_INFO:
7166                 {
7167                         status = smb_set_file_allocation_info(conn, req,
7168                                                                 pdata,
7169                                                                 total_data,
7170                                                                 fsp,
7171                                                                 smb_fname);
7172                         break;
7173                 }
7174
7175                 case SMB_FILE_END_OF_FILE_INFORMATION:
7176                 case SMB_SET_FILE_END_OF_FILE_INFO:
7177                 {
7178                         status = smb_set_file_end_of_file_info(conn, req,
7179                                                                 pdata,
7180                                                                 total_data,
7181                                                                 fsp,
7182                                                                 smb_fname);
7183                         break;
7184                 }
7185
7186                 case SMB_FILE_DISPOSITION_INFORMATION:
7187                 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
7188                 {
7189 #if 0
7190                         /* JRA - We used to just ignore this on a path ? 
7191                          * Shouldn't this be invalid level on a pathname
7192                          * based call ?
7193                          */
7194                         if (tran_call != TRANSACT2_SETFILEINFO) {
7195                                 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
7196                         }
7197 #endif
7198                         status = smb_set_file_disposition_info(conn,
7199                                                 pdata,
7200                                                 total_data,
7201                                                 fsp,
7202                                                 smb_fname);
7203                         break;
7204                 }
7205
7206                 case SMB_FILE_POSITION_INFORMATION:
7207                 {
7208                         status = smb_file_position_information(conn,
7209                                                 pdata,
7210                                                 total_data,
7211                                                 fsp);
7212                         break;
7213                 }
7214
7215                 /* From tridge Samba4 : 
7216                  * MODE_INFORMATION in setfileinfo (I have no
7217                  * idea what "mode information" on a file is - it takes a value of 0,
7218                  * 2, 4 or 6. What could it be?).
7219                  */
7220
7221                 case SMB_FILE_MODE_INFORMATION:
7222                 {
7223                         status = smb_file_mode_information(conn,
7224                                                 pdata,
7225                                                 total_data);
7226                         break;
7227                 }
7228
7229                 /*
7230                  * CIFS UNIX extensions.
7231                  */
7232
7233                 case SMB_SET_FILE_UNIX_BASIC:
7234                 {
7235                         status = smb_set_file_unix_basic(conn, req,
7236                                                         pdata,
7237                                                         total_data,
7238                                                         fsp,
7239                                                         smb_fname);
7240                         break;
7241                 }
7242
7243                 case SMB_SET_FILE_UNIX_INFO2:
7244                 {
7245                         status = smb_set_file_unix_info2(conn, req,
7246                                                         pdata,
7247                                                         total_data,
7248                                                         fsp,
7249                                                         smb_fname);
7250                         break;
7251                 }
7252
7253                 case SMB_SET_FILE_UNIX_LINK:
7254                 {
7255                         if (fsp) {
7256                                 /* We must have a pathname for this. */
7257                                 return NT_STATUS_INVALID_LEVEL;
7258                         }
7259                         status = smb_set_file_unix_link(conn, req, pdata,
7260                                                         total_data, smb_fname);
7261                         break;
7262                 }
7263
7264                 case SMB_SET_FILE_UNIX_HLINK:
7265                 {
7266                         if (fsp) {
7267                                 /* We must have a pathname for this. */
7268                                 return NT_STATUS_INVALID_LEVEL;
7269                         }
7270                         status = smb_set_file_unix_hlink(conn, req,
7271                                                          pdata, total_data,
7272                                                          smb_fname);
7273                         break;
7274                 }
7275
7276                 case SMB_FILE_RENAME_INFORMATION:
7277                 {
7278                         status = smb_file_rename_information(conn, req,
7279                                                              pdata, total_data,
7280                                                              fsp, smb_fname);
7281                         break;
7282                 }
7283
7284 #if defined(HAVE_POSIX_ACLS)
7285                 case SMB_SET_POSIX_ACL:
7286                 {
7287                         status = smb_set_posix_acl(conn,
7288                                                 pdata,
7289                                                 total_data,
7290                                                 fsp,
7291                                                 smb_fname);
7292                         break;
7293                 }
7294 #endif
7295
7296                 case SMB_SET_POSIX_LOCK:
7297                 {
7298                         if (!fsp) {
7299                                 return NT_STATUS_INVALID_LEVEL;
7300                         }
7301                         status = smb_set_posix_lock(conn, req,
7302                                                     pdata, total_data, fsp);
7303                         break;
7304                 }
7305
7306                 case SMB_POSIX_PATH_OPEN:
7307                 {
7308                         if (fsp) {
7309                                 /* We must have a pathname for this. */
7310                                 return NT_STATUS_INVALID_LEVEL;
7311                         }
7312
7313                         status = smb_posix_open(conn, req,
7314                                                 ppdata,
7315                                                 total_data,
7316                                                 smb_fname,
7317                                                 &data_return_size);
7318                         break;
7319                 }
7320
7321                 case SMB_POSIX_PATH_UNLINK:
7322                 {
7323                         if (fsp) {
7324                                 /* We must have a pathname for this. */
7325                                 return NT_STATUS_INVALID_LEVEL;
7326                         }
7327
7328                         status = smb_posix_unlink(conn, req,
7329                                                 pdata,
7330                                                 total_data,
7331                                                 smb_fname);
7332                         break;
7333                 }
7334
7335                 default:
7336                         return NT_STATUS_INVALID_LEVEL;
7337         }
7338
7339         if (!NT_STATUS_IS_OK(status)) {
7340                 return status;
7341         }
7342
7343         *ret_data_size = data_return_size;
7344         return NT_STATUS_OK;
7345 }
7346
7347 /****************************************************************************
7348  Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
7349 ****************************************************************************/
7350
7351 static void call_trans2setfilepathinfo(connection_struct *conn,
7352                                        struct smb_request *req,
7353                                        unsigned int tran_call,
7354                                        char **pparams, int total_params,
7355                                        char **ppdata, int total_data,
7356                                        unsigned int max_data_bytes)
7357 {
7358         char *params = *pparams;
7359         char *pdata = *ppdata;
7360         uint16 info_level;
7361         struct smb_filename *smb_fname = NULL;
7362         files_struct *fsp = NULL;
7363         NTSTATUS status = NT_STATUS_OK;
7364         int data_return_size = 0;
7365
7366         if (!params) {
7367                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7368                 return;
7369         }
7370
7371         if (tran_call == TRANSACT2_SETFILEINFO) {
7372                 if (total_params < 4) {
7373                         reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7374                         return;
7375                 }
7376
7377                 fsp = file_fsp(req, SVAL(params,0));
7378                 /* Basic check for non-null fsp. */
7379                 if (!check_fsp_open(conn, req, fsp)) {
7380                         return;
7381                 }
7382                 info_level = SVAL(params,2);
7383
7384                 status = copy_smb_filename(talloc_tos(), fsp->fsp_name,
7385                                            &smb_fname);
7386                 if (!NT_STATUS_IS_OK(status)) {
7387                         reply_nterror(req, status);
7388                         return;
7389                 }
7390
7391                 if(fsp->is_directory || fsp->fh->fd == -1) {
7392                         /*
7393                          * This is actually a SETFILEINFO on a directory
7394                          * handle (returned from an NT SMB). NT5.0 seems
7395                          * to do this call. JRA.
7396                          */
7397                         if (INFO_LEVEL_IS_UNIX(info_level)) {
7398                                 /* Always do lstat for UNIX calls. */
7399                                 if (SMB_VFS_LSTAT(conn, smb_fname)) {
7400                                         DEBUG(3,("call_trans2setfilepathinfo: "
7401                                                  "SMB_VFS_LSTAT of %s failed "
7402                                                  "(%s)\n",
7403                                                  smb_fname_str_dbg(smb_fname),
7404                                                  strerror(errno)));
7405                                         reply_nterror(req, map_nt_error_from_unix(errno));
7406                                         return;
7407                                 }
7408                         } else {
7409                                 if (SMB_VFS_STAT(conn, smb_fname) != 0) {
7410                                         DEBUG(3,("call_trans2setfilepathinfo: "
7411                                                  "fileinfo of %s failed (%s)\n",
7412                                                  smb_fname_str_dbg(smb_fname),
7413                                                  strerror(errno)));
7414                                         reply_nterror(req, map_nt_error_from_unix(errno));
7415                                         return;
7416                                 }
7417                         }
7418                 } else if (fsp->print_file) {
7419                         /*
7420                          * Doing a DELETE_ON_CLOSE should cancel a print job.
7421                          */
7422                         if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
7423                                 fsp->fh->private_options |= FILE_DELETE_ON_CLOSE;
7424
7425                                 DEBUG(3,("call_trans2setfilepathinfo: "
7426                                          "Cancelling print job (%s)\n",
7427                                          fsp_str_dbg(fsp)));
7428
7429                                 SSVAL(params,0,0);
7430                                 send_trans2_replies(conn, req, params, 2,
7431                                                     *ppdata, 0,
7432                                                     max_data_bytes);
7433                                 return;
7434                         } else {
7435                                 reply_doserror(req, ERRDOS, ERRbadpath);
7436                                 return;
7437                         }
7438                 } else {
7439                         /*
7440                          * Original code - this is an open file.
7441                          */
7442                         if (!check_fsp(conn, req, fsp)) {
7443                                 return;
7444                         }
7445
7446                         if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
7447                                 DEBUG(3,("call_trans2setfilepathinfo: fstat "
7448                                          "of fnum %d failed (%s)\n", fsp->fnum,
7449                                          strerror(errno)));
7450                                 reply_nterror(req, map_nt_error_from_unix(errno));
7451                                 return;
7452                         }
7453                 }
7454         } else {
7455                 char *fname = NULL;
7456
7457                 /* set path info */
7458                 if (total_params < 7) {
7459                         reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7460                         return;
7461                 }
7462
7463                 info_level = SVAL(params,0);
7464                 srvstr_get_path(req, params, req->flags2, &fname, &params[6],
7465                                 total_params - 6, STR_TERMINATE,
7466                                 &status);
7467                 if (!NT_STATUS_IS_OK(status)) {
7468                         reply_nterror(req, status);
7469                         return;
7470                 }
7471
7472                 status = filename_convert(req, conn,
7473                                          req->flags2 & FLAGS2_DFS_PATHNAMES,
7474                                          fname,
7475                                          0,
7476                                          NULL,
7477                                          &smb_fname);
7478                 if (!NT_STATUS_IS_OK(status)) {
7479                         if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7480                                 reply_botherror(req,
7481                                                 NT_STATUS_PATH_NOT_COVERED,
7482                                                 ERRSRV, ERRbadpath);
7483                                 return;
7484                         }
7485                         reply_nterror(req, status);
7486                         return;
7487                 }
7488
7489                 if (INFO_LEVEL_IS_UNIX(info_level)) {
7490                         /*
7491                          * For CIFS UNIX extensions the target name may not exist.
7492                          */
7493
7494                         /* Always do lstat for UNIX calls. */
7495                         SMB_VFS_LSTAT(conn, smb_fname);
7496
7497                 } else if (!VALID_STAT(smb_fname->st) &&
7498                            SMB_VFS_STAT(conn, smb_fname)) {
7499                         DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of "
7500                                  "%s failed (%s)\n",
7501                                  smb_fname_str_dbg(smb_fname),
7502                                  strerror(errno)));
7503                         reply_nterror(req, map_nt_error_from_unix(errno));
7504                         return;
7505                 }
7506         }
7507
7508         DEBUG(3,("call_trans2setfilepathinfo(%d) %s (fnum %d) info_level=%d "
7509                  "totdata=%d\n", tran_call, smb_fname_str_dbg(smb_fname),
7510                  fsp ? fsp->fnum : -1, info_level,total_data));
7511
7512         /* Realloc the parameter size */
7513         *pparams = (char *)SMB_REALLOC(*pparams,2);
7514         if (*pparams == NULL) {
7515                 reply_nterror(req, NT_STATUS_NO_MEMORY);
7516                 return;
7517         }
7518         params = *pparams;
7519
7520         SSVAL(params,0,0);
7521
7522         status = smbd_do_setfilepathinfo(conn, req, req,
7523                                          info_level,
7524                                          fsp,
7525                                          smb_fname,
7526                                          ppdata, total_data,
7527                                          &data_return_size);
7528         if (!NT_STATUS_IS_OK(status)) {
7529                 if (open_was_deferred(req->mid)) {
7530                         /* We have re-scheduled this call. */
7531                         return;
7532                 }
7533                 if (blocking_lock_was_deferred(req->mid)) {
7534                         /* We have re-scheduled this call. */
7535                         return;
7536                 }
7537                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7538                         reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
7539                                         ERRSRV, ERRbadpath);
7540                         return;
7541                 }
7542                 if (info_level == SMB_POSIX_PATH_OPEN) {
7543                         reply_openerror(req, status);
7544                         return;
7545                 }
7546
7547                 reply_nterror(req, status);
7548                 return;
7549         }
7550
7551         send_trans2_replies(conn, req, params, 2, *ppdata, data_return_size,
7552                             max_data_bytes);
7553
7554         return;
7555 }
7556
7557 /****************************************************************************
7558  Reply to a TRANS2_MKDIR (make directory with extended attributes).
7559 ****************************************************************************/
7560
7561 static void call_trans2mkdir(connection_struct *conn, struct smb_request *req,
7562                              char **pparams, int total_params,
7563                              char **ppdata, int total_data,
7564                              unsigned int max_data_bytes)
7565 {
7566         struct smb_filename *smb_dname = NULL;
7567         char *params = *pparams;
7568         char *pdata = *ppdata;
7569         char *directory = NULL;
7570         NTSTATUS status = NT_STATUS_OK;
7571         struct ea_list *ea_list = NULL;
7572         TALLOC_CTX *ctx = talloc_tos();
7573
7574         if (!CAN_WRITE(conn)) {
7575                 reply_doserror(req, ERRSRV, ERRaccess);
7576                 return;
7577         }
7578
7579         if (total_params < 5) {
7580                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7581                 return;
7582         }
7583
7584         srvstr_get_path(ctx, params, req->flags2, &directory, &params[4],
7585                         total_params - 4, STR_TERMINATE,
7586                         &status);
7587         if (!NT_STATUS_IS_OK(status)) {
7588                 reply_nterror(req, status);
7589                 return;
7590         }
7591
7592         DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
7593
7594         status = filename_convert(ctx,
7595                                 conn,
7596                                 req->flags2 & FLAGS2_DFS_PATHNAMES,
7597                                 directory,
7598                                 0,
7599                                 NULL,
7600                                 &smb_dname);
7601
7602         if (!NT_STATUS_IS_OK(status)) {
7603                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7604                         reply_botherror(req,
7605                                 NT_STATUS_PATH_NOT_COVERED,
7606                                 ERRSRV, ERRbadpath);
7607                         return;
7608                 }
7609                 reply_nterror(req, status);
7610                 return;
7611         }
7612
7613         /* Any data in this call is an EA list. */
7614         if (total_data && (total_data != 4) && !lp_ea_support(SNUM(conn))) {
7615                 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
7616                 goto out;
7617         }
7618
7619         /*
7620          * OS/2 workplace shell seems to send SET_EA requests of "null"
7621          * length (4 bytes containing IVAL 4).
7622          * They seem to have no effect. Bug #3212. JRA.
7623          */
7624
7625         if (total_data != 4) {
7626                 if (total_data < 10) {
7627                         reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7628                         goto out;
7629                 }
7630
7631                 if (IVAL(pdata,0) > total_data) {
7632                         DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
7633                                 IVAL(pdata,0), (unsigned int)total_data));
7634                         reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7635                         goto out;
7636                 }
7637
7638                 ea_list = read_ea_list(talloc_tos(), pdata + 4,
7639                                        total_data - 4);
7640                 if (!ea_list) {
7641                         reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7642                         goto out;
7643                 }
7644         }
7645         /* If total_data == 4 Windows doesn't care what values
7646          * are placed in that field, it just ignores them.
7647          * The System i QNTC IBM SMB client puts bad values here,
7648          * so ignore them. */
7649
7650         status = create_directory(conn, req, smb_dname);
7651
7652         if (!NT_STATUS_IS_OK(status)) {
7653                 reply_nterror(req, status);
7654                 goto out;
7655         }
7656
7657         /* Try and set any given EA. */
7658         if (ea_list) {
7659                 status = set_ea(conn, NULL, smb_dname, ea_list);
7660                 if (!NT_STATUS_IS_OK(status)) {
7661                         reply_nterror(req, status);
7662                         goto out;
7663                 }
7664         }
7665
7666         /* Realloc the parameter and data sizes */
7667         *pparams = (char *)SMB_REALLOC(*pparams,2);
7668         if(*pparams == NULL) {
7669                 reply_nterror(req, NT_STATUS_NO_MEMORY);
7670                 goto out;
7671         }
7672         params = *pparams;
7673
7674         SSVAL(params,0,0);
7675
7676         send_trans2_replies(conn, req, params, 2, *ppdata, 0, max_data_bytes);
7677
7678  out:
7679         TALLOC_FREE(smb_dname);
7680         return;
7681 }
7682
7683 /****************************************************************************
7684  Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
7685  We don't actually do this - we just send a null response.
7686 ****************************************************************************/
7687
7688 static void call_trans2findnotifyfirst(connection_struct *conn,
7689                                        struct smb_request *req,
7690                                        char **pparams, int total_params,
7691                                        char **ppdata, int total_data,
7692                                        unsigned int max_data_bytes)
7693 {
7694         char *params = *pparams;
7695         uint16 info_level;
7696
7697         if (total_params < 6) {
7698                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7699                 return;
7700         }
7701
7702         info_level = SVAL(params,4);
7703         DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
7704
7705         switch (info_level) {
7706                 case 1:
7707                 case 2:
7708                         break;
7709                 default:
7710                         reply_nterror(req, NT_STATUS_INVALID_LEVEL);
7711                         return;
7712         }
7713
7714         /* Realloc the parameter and data sizes */
7715         *pparams = (char *)SMB_REALLOC(*pparams,6);
7716         if (*pparams == NULL) {
7717                 reply_nterror(req, NT_STATUS_NO_MEMORY);
7718                 return;
7719         }
7720         params = *pparams;
7721
7722         SSVAL(params,0,fnf_handle);
7723         SSVAL(params,2,0); /* No changes */
7724         SSVAL(params,4,0); /* No EA errors */
7725
7726         fnf_handle++;
7727
7728         if(fnf_handle == 0)
7729                 fnf_handle = 257;
7730
7731         send_trans2_replies(conn, req, params, 6, *ppdata, 0, max_data_bytes);
7732
7733         return;
7734 }
7735
7736 /****************************************************************************
7737  Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for 
7738  changes). Currently this does nothing.
7739 ****************************************************************************/
7740
7741 static void call_trans2findnotifynext(connection_struct *conn,
7742                                       struct smb_request *req,
7743                                       char **pparams, int total_params,
7744                                       char **ppdata, int total_data,
7745                                       unsigned int max_data_bytes)
7746 {
7747         char *params = *pparams;
7748
7749         DEBUG(3,("call_trans2findnotifynext\n"));
7750
7751         /* Realloc the parameter and data sizes */
7752         *pparams = (char *)SMB_REALLOC(*pparams,4);
7753         if (*pparams == NULL) {
7754                 reply_nterror(req, NT_STATUS_NO_MEMORY);
7755                 return;
7756         }
7757         params = *pparams;
7758
7759         SSVAL(params,0,0); /* No changes */
7760         SSVAL(params,2,0); /* No EA errors */
7761
7762         send_trans2_replies(conn, req, params, 4, *ppdata, 0, max_data_bytes);
7763
7764         return;
7765 }
7766
7767 /****************************************************************************
7768  Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
7769 ****************************************************************************/
7770
7771 static void call_trans2getdfsreferral(connection_struct *conn,
7772                                       struct smb_request *req,
7773                                       char **pparams, int total_params,
7774                                       char **ppdata, int total_data,
7775                                       unsigned int max_data_bytes)
7776 {
7777         char *params = *pparams;
7778         char *pathname = NULL;
7779         int reply_size = 0;
7780         int max_referral_level;
7781         NTSTATUS status = NT_STATUS_OK;
7782         TALLOC_CTX *ctx = talloc_tos();
7783
7784         DEBUG(10,("call_trans2getdfsreferral\n"));
7785
7786         if (total_params < 3) {
7787                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7788                 return;
7789         }
7790
7791         max_referral_level = SVAL(params,0);
7792
7793         if(!lp_host_msdfs()) {
7794                 reply_doserror(req, ERRDOS, ERRbadfunc);
7795                 return;
7796         }
7797
7798         srvstr_pull_talloc(ctx, params, req->flags2, &pathname, &params[2],
7799                     total_params - 2, STR_TERMINATE);
7800         if (!pathname) {
7801                 reply_nterror(req, NT_STATUS_NOT_FOUND);
7802                 return;
7803         }
7804         if((reply_size = setup_dfs_referral(conn, pathname, max_referral_level,
7805                                             ppdata,&status)) < 0) {
7806                 reply_nterror(req, status);
7807                 return;
7808         }
7809
7810         SSVAL(req->inbuf, smb_flg2,
7811               SVAL(req->inbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
7812         send_trans2_replies(conn, req,0,0,*ppdata,reply_size, max_data_bytes);
7813
7814         return;
7815 }
7816
7817 #define LMCAT_SPL       0x53
7818 #define LMFUNC_GETJOBID 0x60
7819
7820 /****************************************************************************
7821  Reply to a TRANS2_IOCTL - used for OS/2 printing.
7822 ****************************************************************************/
7823
7824 static void call_trans2ioctl(connection_struct *conn,
7825                              struct smb_request *req,
7826                              char **pparams, int total_params,
7827                              char **ppdata, int total_data,
7828                              unsigned int max_data_bytes)
7829 {
7830         char *pdata = *ppdata;
7831         files_struct *fsp = file_fsp(req, SVAL(req->vwv+15, 0));
7832
7833         /* check for an invalid fid before proceeding */
7834
7835         if (!fsp) {
7836                 reply_doserror(req, ERRDOS, ERRbadfid);
7837                 return;
7838         }
7839
7840         if ((SVAL(req->vwv+16, 0) == LMCAT_SPL)
7841             && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
7842                 *ppdata = (char *)SMB_REALLOC(*ppdata, 32);
7843                 if (*ppdata == NULL) {
7844                         reply_nterror(req, NT_STATUS_NO_MEMORY);
7845                         return;
7846                 }
7847                 pdata = *ppdata;
7848
7849                 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
7850                         CAN ACCEPT THIS IN UNICODE. JRA. */
7851
7852                 SSVAL(pdata,0,fsp->rap_print_jobid);                     /* Job number */
7853                 srvstr_push(pdata, req->flags2, pdata + 2,
7854                             global_myname(), 15,
7855                             STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
7856                 srvstr_push(pdata, req->flags2, pdata+18,
7857                             lp_servicename(SNUM(conn)), 13,
7858                             STR_ASCII|STR_TERMINATE); /* Service name */
7859                 send_trans2_replies(conn, req, *pparams, 0, *ppdata, 32,
7860                                     max_data_bytes);
7861                 return;
7862         }
7863
7864         DEBUG(2,("Unknown TRANS2_IOCTL\n"));
7865         reply_doserror(req, ERRSRV, ERRerror);
7866 }
7867
7868 /****************************************************************************
7869  Reply to a SMBfindclose (stop trans2 directory search).
7870 ****************************************************************************/
7871
7872 void reply_findclose(struct smb_request *req)
7873 {
7874         int dptr_num;
7875         struct smbd_server_connection *sconn = smbd_server_conn;
7876
7877         START_PROFILE(SMBfindclose);
7878
7879         if (req->wct < 1) {
7880                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7881                 END_PROFILE(SMBfindclose);
7882                 return;
7883         }
7884
7885         dptr_num = SVALS(req->vwv+0, 0);
7886
7887         DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
7888
7889         dptr_close(sconn, &dptr_num);
7890
7891         reply_outbuf(req, 0, 0);
7892
7893         DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
7894
7895         END_PROFILE(SMBfindclose);
7896         return;
7897 }
7898
7899 /****************************************************************************
7900  Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
7901 ****************************************************************************/
7902
7903 void reply_findnclose(struct smb_request *req)
7904 {
7905         int dptr_num;
7906
7907         START_PROFILE(SMBfindnclose);
7908
7909         if (req->wct < 1) {
7910                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7911                 END_PROFILE(SMBfindnclose);
7912                 return;
7913         }
7914
7915         dptr_num = SVAL(req->vwv+0, 0);
7916
7917         DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
7918
7919         /* We never give out valid handles for a 
7920            findnotifyfirst - so any dptr_num is ok here. 
7921            Just ignore it. */
7922
7923         reply_outbuf(req, 0, 0);
7924
7925         DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
7926
7927         END_PROFILE(SMBfindnclose);
7928         return;
7929 }
7930
7931 static void handle_trans2(connection_struct *conn, struct smb_request *req,
7932                           struct trans_state *state)
7933 {
7934         if (Protocol >= PROTOCOL_NT1) {
7935                 req->flags2 |= 0x40; /* IS_LONG_NAME */
7936                 SSVAL(req->inbuf,smb_flg2,req->flags2);
7937         }
7938
7939         if (conn->encrypt_level == Required && !req->encrypted) {
7940                 if (state->call != TRANSACT2_QFSINFO &&
7941                                 state->call != TRANSACT2_SETFSINFO) {
7942                         DEBUG(0,("handle_trans2: encryption required "
7943                                 "with call 0x%x\n",
7944                                 (unsigned int)state->call));
7945                         reply_nterror(req, NT_STATUS_ACCESS_DENIED);
7946                         return;
7947                 }
7948         }
7949
7950         SMB_PERFCOUNT_SET_SUBOP(&req->pcd, state->call);
7951
7952         /* Now we must call the relevant TRANS2 function */
7953         switch(state->call)  {
7954         case TRANSACT2_OPEN:
7955         {
7956                 START_PROFILE(Trans2_open);
7957                 call_trans2open(conn, req,
7958                                 &state->param, state->total_param,
7959                                 &state->data, state->total_data,
7960                                 state->max_data_return);
7961                 END_PROFILE(Trans2_open);
7962                 break;
7963         }
7964
7965         case TRANSACT2_FINDFIRST:
7966         {
7967                 START_PROFILE(Trans2_findfirst);
7968                 call_trans2findfirst(conn, req,
7969                                      &state->param, state->total_param,
7970                                      &state->data, state->total_data,
7971                                      state->max_data_return);
7972                 END_PROFILE(Trans2_findfirst);
7973                 break;
7974         }
7975
7976         case TRANSACT2_FINDNEXT:
7977         {
7978                 START_PROFILE(Trans2_findnext);
7979                 call_trans2findnext(conn, req,
7980                                     &state->param, state->total_param,
7981                                     &state->data, state->total_data,
7982                                     state->max_data_return);
7983                 END_PROFILE(Trans2_findnext);
7984                 break;
7985         }
7986
7987         case TRANSACT2_QFSINFO:
7988         {
7989                 START_PROFILE(Trans2_qfsinfo);
7990                 call_trans2qfsinfo(conn, req,
7991                                    &state->param, state->total_param,
7992                                    &state->data, state->total_data,
7993                                    state->max_data_return);
7994                 END_PROFILE(Trans2_qfsinfo);
7995             break;
7996         }
7997
7998         case TRANSACT2_SETFSINFO:
7999         {
8000                 START_PROFILE(Trans2_setfsinfo);
8001                 call_trans2setfsinfo(conn, req,
8002                                      &state->param, state->total_param,
8003                                      &state->data, state->total_data,
8004                                      state->max_data_return);
8005                 END_PROFILE(Trans2_setfsinfo);
8006                 break;
8007         }
8008
8009         case TRANSACT2_QPATHINFO:
8010         case TRANSACT2_QFILEINFO:
8011         {
8012                 START_PROFILE(Trans2_qpathinfo);
8013                 call_trans2qfilepathinfo(conn, req, state->call,
8014                                          &state->param, state->total_param,
8015                                          &state->data, state->total_data,
8016                                          state->max_data_return);
8017                 END_PROFILE(Trans2_qpathinfo);
8018                 break;
8019         }
8020
8021         case TRANSACT2_SETPATHINFO:
8022         case TRANSACT2_SETFILEINFO:
8023         {
8024                 START_PROFILE(Trans2_setpathinfo);
8025                 call_trans2setfilepathinfo(conn, req, state->call,
8026                                            &state->param, state->total_param,
8027                                            &state->data, state->total_data,
8028                                            state->max_data_return);
8029                 END_PROFILE(Trans2_setpathinfo);
8030                 break;
8031         }
8032
8033         case TRANSACT2_FINDNOTIFYFIRST:
8034         {
8035                 START_PROFILE(Trans2_findnotifyfirst);
8036                 call_trans2findnotifyfirst(conn, req,
8037                                            &state->param, state->total_param,
8038                                            &state->data, state->total_data,
8039                                            state->max_data_return);
8040                 END_PROFILE(Trans2_findnotifyfirst);
8041                 break;
8042         }
8043
8044         case TRANSACT2_FINDNOTIFYNEXT:
8045         {
8046                 START_PROFILE(Trans2_findnotifynext);
8047                 call_trans2findnotifynext(conn, req,
8048                                           &state->param, state->total_param,
8049                                           &state->data, state->total_data,
8050                                           state->max_data_return);
8051                 END_PROFILE(Trans2_findnotifynext);
8052                 break;
8053         }
8054
8055         case TRANSACT2_MKDIR:
8056         {
8057                 START_PROFILE(Trans2_mkdir);
8058                 call_trans2mkdir(conn, req,
8059                                  &state->param, state->total_param,
8060                                  &state->data, state->total_data,
8061                                  state->max_data_return);
8062                 END_PROFILE(Trans2_mkdir);
8063                 break;
8064         }
8065
8066         case TRANSACT2_GET_DFS_REFERRAL:
8067         {
8068                 START_PROFILE(Trans2_get_dfs_referral);
8069                 call_trans2getdfsreferral(conn, req,
8070                                           &state->param, state->total_param,
8071                                           &state->data, state->total_data,
8072                                           state->max_data_return);
8073                 END_PROFILE(Trans2_get_dfs_referral);
8074                 break;
8075         }
8076
8077         case TRANSACT2_IOCTL:
8078         {
8079                 START_PROFILE(Trans2_ioctl);
8080                 call_trans2ioctl(conn, req,
8081                                  &state->param, state->total_param,
8082                                  &state->data, state->total_data,
8083                                  state->max_data_return);
8084                 END_PROFILE(Trans2_ioctl);
8085                 break;
8086         }
8087
8088         default:
8089                 /* Error in request */
8090                 DEBUG(2,("Unknown request %d in trans2 call\n", state->call));
8091                 reply_doserror(req, ERRSRV,ERRerror);
8092         }
8093 }
8094
8095 /****************************************************************************
8096  Reply to a SMBtrans2.
8097  ****************************************************************************/
8098
8099 void reply_trans2(struct smb_request *req)
8100 {
8101         connection_struct *conn = req->conn;
8102         unsigned int dsoff;
8103         unsigned int dscnt;
8104         unsigned int psoff;
8105         unsigned int pscnt;
8106         unsigned int tran_call;
8107         struct trans_state *state;
8108         NTSTATUS result;
8109
8110         START_PROFILE(SMBtrans2);
8111
8112         if (req->wct < 14) {
8113                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8114                 END_PROFILE(SMBtrans2);
8115                 return;
8116         }
8117
8118         dsoff = SVAL(req->vwv+12, 0);
8119         dscnt = SVAL(req->vwv+11, 0);
8120         psoff = SVAL(req->vwv+10, 0);
8121         pscnt = SVAL(req->vwv+9, 0);
8122         tran_call = SVAL(req->vwv+14, 0);
8123
8124         result = allow_new_trans(conn->pending_trans, req->mid);
8125         if (!NT_STATUS_IS_OK(result)) {
8126                 DEBUG(2, ("Got invalid trans2 request: %s\n",
8127                           nt_errstr(result)));
8128                 reply_nterror(req, result);
8129                 END_PROFILE(SMBtrans2);
8130                 return;
8131         }
8132
8133         if (IS_IPC(conn)) {
8134                 switch (tran_call) {
8135                 /* List the allowed trans2 calls on IPC$ */
8136                 case TRANSACT2_OPEN:
8137                 case TRANSACT2_GET_DFS_REFERRAL:
8138                 case TRANSACT2_QFILEINFO:
8139                 case TRANSACT2_QFSINFO:
8140                 case TRANSACT2_SETFSINFO:
8141                         break;
8142                 default:
8143                         reply_doserror(req, ERRSRV, ERRaccess);
8144                         END_PROFILE(SMBtrans2);
8145                         return;
8146                 }
8147         }
8148
8149         if ((state = TALLOC_P(conn, struct trans_state)) == NULL) {
8150                 DEBUG(0, ("talloc failed\n"));
8151                 reply_nterror(req, NT_STATUS_NO_MEMORY);
8152                 END_PROFILE(SMBtrans2);
8153                 return;
8154         }
8155
8156         state->cmd = SMBtrans2;
8157
8158         state->mid = req->mid;
8159         state->vuid = req->vuid;
8160         state->setup_count = SVAL(req->vwv+13, 0);
8161         state->setup = NULL;
8162         state->total_param = SVAL(req->vwv+0, 0);
8163         state->param = NULL;
8164         state->total_data =  SVAL(req->vwv+1, 0);
8165         state->data = NULL;
8166         state->max_param_return = SVAL(req->vwv+2, 0);
8167         state->max_data_return  = SVAL(req->vwv+3, 0);
8168         state->max_setup_return = SVAL(req->vwv+4, 0);
8169         state->close_on_completion = BITSETW(req->vwv+5, 0);
8170         state->one_way = BITSETW(req->vwv+5, 1);
8171
8172         state->call = tran_call;
8173
8174         /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
8175            is so as a sanity check */
8176         if (state->setup_count != 1) {
8177                 /*
8178                  * Need to have rc=0 for ioctl to get job id for OS/2.
8179                  *  Network printing will fail if function is not successful.
8180                  *  Similar function in reply.c will be used if protocol
8181                  *  is LANMAN1.0 instead of LM1.2X002.
8182                  *  Until DosPrintSetJobInfo with PRJINFO3 is supported,
8183                  *  outbuf doesn't have to be set(only job id is used).
8184                  */
8185                 if ( (state->setup_count == 4)
8186                      && (tran_call == TRANSACT2_IOCTL)
8187                      && (SVAL(req->vwv+16, 0) == LMCAT_SPL)
8188                      && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
8189                         DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
8190                 } else {
8191                         DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state->setup_count));
8192                         DEBUG(2,("Transaction is %d\n",tran_call));
8193                         TALLOC_FREE(state);
8194                         reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8195                         END_PROFILE(SMBtrans2);
8196                         return;
8197                 }
8198         }
8199
8200         if ((dscnt > state->total_data) || (pscnt > state->total_param))
8201                 goto bad_param;
8202
8203         if (state->total_data) {
8204
8205                 if (trans_oob(state->total_data, 0, dscnt)
8206                     || trans_oob(smb_len(req->inbuf), dsoff, dscnt)) {
8207                         goto bad_param;
8208                 }
8209
8210                 /* Can't use talloc here, the core routines do realloc on the
8211                  * params and data. */
8212                 state->data = (char *)SMB_MALLOC(state->total_data);
8213                 if (state->data == NULL) {
8214                         DEBUG(0,("reply_trans2: data malloc fail for %u "
8215                                  "bytes !\n", (unsigned int)state->total_data));
8216                         TALLOC_FREE(state);
8217                         reply_nterror(req, NT_STATUS_NO_MEMORY);
8218                         END_PROFILE(SMBtrans2);
8219                         return;
8220                 }
8221
8222                 memcpy(state->data,smb_base(req->inbuf)+dsoff,dscnt);
8223         }
8224
8225         if (state->total_param) {
8226
8227                 if (trans_oob(state->total_param, 0, pscnt)
8228                     || trans_oob(smb_len(req->inbuf), psoff, pscnt)) {
8229                         goto bad_param;
8230                 }
8231
8232                 /* Can't use talloc here, the core routines do realloc on the
8233                  * params and data. */
8234                 state->param = (char *)SMB_MALLOC(state->total_param);
8235                 if (state->param == NULL) {
8236                         DEBUG(0,("reply_trans: param malloc fail for %u "
8237                                  "bytes !\n", (unsigned int)state->total_param));
8238                         SAFE_FREE(state->data);
8239                         TALLOC_FREE(state);
8240                         reply_nterror(req, NT_STATUS_NO_MEMORY);
8241                         END_PROFILE(SMBtrans2);
8242                         return;
8243                 } 
8244
8245                 memcpy(state->param,smb_base(req->inbuf)+psoff,pscnt);
8246         }
8247
8248         state->received_data  = dscnt;
8249         state->received_param = pscnt;
8250
8251         if ((state->received_param == state->total_param) &&
8252             (state->received_data == state->total_data)) {
8253
8254                 handle_trans2(conn, req, state);
8255
8256                 SAFE_FREE(state->data);
8257                 SAFE_FREE(state->param);
8258                 TALLOC_FREE(state);
8259                 END_PROFILE(SMBtrans2);
8260                 return;
8261         }
8262
8263         DLIST_ADD(conn->pending_trans, state);
8264
8265         /* We need to send an interim response then receive the rest
8266            of the parameter/data bytes */
8267         reply_outbuf(req, 0, 0);
8268         show_msg((char *)req->outbuf);
8269         END_PROFILE(SMBtrans2);
8270         return;
8271
8272   bad_param:
8273
8274         DEBUG(0,("reply_trans2: invalid trans parameters\n"));
8275         SAFE_FREE(state->data);
8276         SAFE_FREE(state->param);
8277         TALLOC_FREE(state);
8278         END_PROFILE(SMBtrans2);
8279         reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8280 }
8281
8282
8283 /****************************************************************************
8284  Reply to a SMBtranss2
8285  ****************************************************************************/
8286
8287 void reply_transs2(struct smb_request *req)
8288 {
8289         connection_struct *conn = req->conn;
8290         unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
8291         struct trans_state *state;
8292
8293         START_PROFILE(SMBtranss2);
8294
8295         show_msg((char *)req->inbuf);
8296
8297         if (req->wct < 8) {
8298                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8299                 END_PROFILE(SMBtranss2);
8300                 return;
8301         }
8302
8303         for (state = conn->pending_trans; state != NULL;
8304              state = state->next) {
8305                 if (state->mid == req->mid) {
8306                         break;
8307                 }
8308         }
8309
8310         if ((state == NULL) || (state->cmd != SMBtrans2)) {
8311                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8312                 END_PROFILE(SMBtranss2);
8313                 return;
8314         }
8315
8316         /* Revise state->total_param and state->total_data in case they have
8317            changed downwards */
8318
8319         if (SVAL(req->vwv+0, 0) < state->total_param)
8320                 state->total_param = SVAL(req->vwv+0, 0);
8321         if (SVAL(req->vwv+1, 0) < state->total_data)
8322                 state->total_data = SVAL(req->vwv+1, 0);
8323
8324         pcnt = SVAL(req->vwv+2, 0);
8325         poff = SVAL(req->vwv+3, 0);
8326         pdisp = SVAL(req->vwv+4, 0);
8327
8328         dcnt = SVAL(req->vwv+5, 0);
8329         doff = SVAL(req->vwv+6, 0);
8330         ddisp = SVAL(req->vwv+7, 0);
8331
8332         state->received_param += pcnt;
8333         state->received_data += dcnt;
8334
8335         if ((state->received_data > state->total_data) ||
8336             (state->received_param > state->total_param))
8337                 goto bad_param;
8338
8339         if (pcnt) {
8340                 if (trans_oob(state->total_param, pdisp, pcnt)
8341                     || trans_oob(smb_len(req->inbuf), poff, pcnt)) {
8342                         goto bad_param;
8343                 }
8344                 memcpy(state->param+pdisp,smb_base(req->inbuf)+poff,pcnt);
8345         }
8346
8347         if (dcnt) {
8348                 if (trans_oob(state->total_data, ddisp, dcnt)
8349                     || trans_oob(smb_len(req->inbuf), doff, dcnt)) {
8350                         goto bad_param;
8351                 }
8352                 memcpy(state->data+ddisp, smb_base(req->inbuf)+doff,dcnt);
8353         }
8354
8355         if ((state->received_param < state->total_param) ||
8356             (state->received_data < state->total_data)) {
8357                 END_PROFILE(SMBtranss2);
8358                 return;
8359         }
8360
8361         handle_trans2(conn, req, state);
8362
8363         DLIST_REMOVE(conn->pending_trans, state);
8364         SAFE_FREE(state->data);
8365         SAFE_FREE(state->param);
8366         TALLOC_FREE(state);
8367
8368         END_PROFILE(SMBtranss2);
8369         return;
8370
8371   bad_param:
8372
8373         DEBUG(0,("reply_transs2: invalid trans parameters\n"));
8374         DLIST_REMOVE(conn->pending_trans, state);
8375         SAFE_FREE(state->data);
8376         SAFE_FREE(state->param);
8377         TALLOC_FREE(state);
8378         reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8379         END_PROFILE(SMBtranss2);
8380         return;
8381 }