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