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