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