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