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