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