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