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