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