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