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