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