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